commit e9899d2e6da1607206c5ac5969434dc8fff6160f Author: OpenCode AI Date: Sat Sep 12 02:42:02 2026 +0200 Initial DruksCode V2: fresh fork of web-to-app (f3b488e) with DruksCode identity - Package rename com.webtoapp -> br.com.drukstech.codeapp - Product rename WebToApp/web-to-app -> DruksCode/drukscode - Design system Wta* -> Dkc* - applicationId br.com.drukstech.codeapp (.play for gplay flavor) - rootProject.name DruksCode - Fresh git history (upstream kept as remote for sync) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..d95af07 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,449 @@ +# Contributing to DruksCode + +Thanks for taking the time to help. DruksCode moves fastest when contributions +stay **small and well-scoped** — pick one of the lanes below and ignore the +rest. + +> **English** · [简体中文](#贡献-webtoapp中文) + +This guide targets **DruksCode 2.6.0** (`versionCode 62`). + +--- + +## Lanes + +| You want to… | Go to | Effort | +| --- | --- | --- | +| Publish a JS/CSS module to the in-app **Module Market** | [`modules/README.md`](../modules/README.md) | hours | +| File a bug, request a feature, or ask a question | [GitHub Issues](https://github.com/shiaho777/web-to-app/issues) | minutes | +| Fix a bug or build a feature in the Android client | This guide ↓ | days | + +If you're not sure which lane fits, open an issue or a discussion first. There +is no need to write code before there's agreement on the shape of the change. + +--- + +## Module Market submissions + +The fastest way to ship something useful to every DruksCode user is to publish +a module. The canonical Module Market guide lives in +[`modules/README.md`](../modules/README.md). Use that file for the full +schema, field rules, reviewer checklist, and CI validation details. The short +version here is only meant to help you pick the right contribution lane: + +1. Fork the repo. +2. Add `modules//module.json` and `main.js` (plus `style.css` if + you need CSS). +3. Add an entry to `modules/registry.json`. +4. Open a PR. + +The market has **no backend**. Clients read `registry.json` and +`submissions.json`, and only merged modules show up in the catalog. Module +changes are validated in CI by `.github/scripts/ci/validate_modules.py`: + +```bash +python3 .github/scripts/ci/validate_modules.py +``` + +--- + +## Code contributions + +> The canonical working guide for AI coding agents and deep code +> contributors is [`AGENTS.md`](../AGENTS.md) — it documents how the editor, +> export pipeline, shell template, and runtime connect, the dual preview/export +> paths, config-field drift rules, packaging constraints, and common change +> recipes. Read it before any non-trivial change to the build, shell sync, +> export packaging, or config fields. + +### Before you write code + +- Search [issues](https://github.com/shiaho777/web-to-app/issues) for prior + discussion of the same idea. +- For non-trivial changes, open an issue first describing the problem and the + approach you have in mind. This is much cheaper than rewriting after review. +- **Avoid adding new dependencies.** The lists in `app/build.gradle.kts` and + `shell/build.gradle.kts` are intentionally restrained — the project signs and + packages APKs in-process, and the shell template pins `targetSdk = 28` on + purpose because generated apps rely on fork+exec native runtimes. New + dependencies need a strong justification, and host-only dependencies must + never leak into the shell template. + +### Local setup + +You'll need: + +- Android Studio Hedgehog or newer +- JDK 17 +- The Gradle wrapper pins Gradle 9.4.1 — no system Gradle install required + +```bash +git clone https://github.com/shiaho777/web-to-app.git +cd drukscode +./gradlew assembleDebug +``` + +The repo has three Gradle modules: **`app`** (the full builder and host), +**`shell`** (the runtime template embedded in generated APKs), and +**`clone-host`** (the host code used by app cloning). Shared runtime code is +authored **only** under `app/` and synchronized into `shell/` at build time +(`shell/build/generated/` — never edit `shell/src` by hand; it is +regenerated and partly git-ignored). + +Run the checks before submitting: + +```bash +./gradlew :app:compileStandardDebugKotlin -x syncCloneHostDex --no-configuration-cache +./gradlew :app:testStandardDebugUnitTest --no-configuration-cache -PskipShellTemplateSync=true +./gradlew :app:checkConfigFieldDrift --no-configuration-cache +``` + +If you touched shell-synced runtime code or export packaging, also rebuild the +template you touched: + +```bash +./gradlew :shell:assembleRelease :app:syncShellTemplateApk --no-configuration-cache +``` + +> Native code (`node_launcher`, `go_exec_loader`, the APK optimizer) builds +> via CMake per-ABI and needs the Android NDK + CMake installed through the +> SDK Manager. CI installs `cmake;3.22.1` and `ndk;28.2.13676358`. + +### Where things live + +| Area | Path | +| --- | --- | +| App types & central config (`AppType`, `WebApp`) | `app/src/main/java/br/com/drukstech/codeapp/data/model/` | +| On-device APK builder / signer | `app/src/main/java/br/com/drukstech/codeapp/core/apkbuilder/` | +| Server runtimes (Node / PHP / Python / Go / WordPress) | `app/src/main/java/br/com/drukstech/codeapp/core/{nodejs,php,python,golang,wordpress}/` | +| WebView engine, native bridge, fingerprint disguise | `app/src/main/java/br/com/drukstech/codeapp/core/{webview,engine,appearance}/` | +| Shell config + generated-APK entry points | `app/src/main/java/br/com/drukstech/codeapp/core/shell/` | +| Preview players (`ui/gallery/`, `ui/media/`) vs packaged players (`ui/shell/`) | `app/src/main/java/br/com/drukstech/codeapp/ui/` | +| Extension modules, Module Market, Agent | `app/src/main/java/br/com/drukstech/codeapp/core/{extension,market,agent}/` | +| Compose UI screens & design system | `app/src/main/java/br/com/drukstech/codeapp/ui/` | +| DI graph (source of truth) | `app/src/main/java/br/com/drukstech/codeapp/di/AppModule.kt` | + +### Preview ≠ export: the rule behind most rejections + +The host app (preview) and generated APKs (export) run **different code**: + +| | Preview (`:app`) | Exported APK | +| --- | --- | --- | +| UI | `ui/gallery/`, `ui/media/`, `WebViewManager` live | `ui/shell/*` synced copy | +| Config | Editor / in-memory models | JSON assets via `ShellModeManager` | + +A feature is done only when it works on **both** paths. Concretely, an editor +setting that must affect generated APKs has to flow through the full chain — +model → `ApkConfig` JSON → shell config → shell-synced runtime — and a +player-screen behavior has to be implemented in **both** the preview and the +shell composable. Three gates enforce this; run them, don't argue with them: + +- `checkConfigFieldDrift` — model/JSON/shell field names must match + (Gson silently drops mismatches). +- `WebViewConfigBooleanCoverageTest` — every new `WebViewConfig` Boolean must + be listed in `flipAllBooleans()` and survive the export round-trip. +- `ShellUiParityTest` — every model field read by host player UI must also be + read by shell player UI (or carry an explicit `allow` reason). Add your new + per-type player pair to it. + +### Coding conventions + +DruksCode leans on the Kotlin and Jetpack Compose patterns already in the +codebase. A few rules worth calling out: + +- **Comments explain *why*, not *what*.** Non-obvious decisions, cross-file + contracts, and issue references (`#781`) get a short comment; clear names + and small functions carry the rest. Don't narrate readable code. +- **Build new UI on the Dkc design system.** Everything renders through + `br.com.drukstech.codeapp.ui.design`. The older `Premium*` / `Enhanced*` / `Settings*` + components are retained as permanent alias layers over the Dkc internals — + don't add new ones, and you don't need to rip them out. A build-time audit + (`.github/scripts/audit_ui_design_system.py`, wired into `build.gradle.kts`) tracks + legacy UI debt against `.github/scripts/ui_design_allowlist.txt`. +- **Reuse the design tokens** in `ui/design/DkcTokens.kt` for spacing, radius, + alpha, and elevation. Don't hard-code numbers. Editor config cards share one + layout grammar (see `AGENTS.md` recipe 12) — copy the neighbouring cards, + don't invent your own, and verify on the emulator, not just by compiling. +- **Strings must cover all 10 supported languages.** UI copy lives in + `core/i18n/Strings.kt` (facade `object Strings` + in-file `StringsA`…`StringsE`, + split only for the JVM constant pool). Supported: Chinese, English, Arabic, + Portuguese, Spanish, French, German, Russian, Japanese, Korean. + Every new or changed user-visible `when (Strings.lang)` block **must** have + real translations for **all 10** branches with no `else ->` — do not leave + pt/es/fr/de/ru/ja/ko as English placeholders. Brand names and pure format + tokens may match English. If you truly cannot translate one language, use + English there and flag it in the PR. +- **Never load user-visible text from `R.string`.** Resource files only cover + zh/en/ar, so lookups silently fall back to Chinese for the other 7 locales. + `R.string` is reserved for non-localised resources. +- **No new top-level singletons** unless you discuss it first. The DI graph in + `di/AppModule.kt` is the source of truth. +- **The Native Bridge is capability-gated.** Any method exposed to web content + via `@JavascriptInterface` must be guarded by the per-capability allow-list + (`NativeBridgeCapabilities`). Never expose a native capability to arbitrary + pages without a gate. PRs that bypass this will be rejected. +- **Preview and packaged runtime are two paths.** See *Preview ≠ export* + above. Shared runtime sources are authored only under `app/` and synced into + `shell/` at build time — do not hand-edit anything under `shell/src`. +- **Avoid catching `Exception` to silence errors.** If recovery is impossible, + log via `AppLogger` and re-throw or return a failed `Result`. + +### Security + +Anything touching the WebView, file IO, APK signing, or the native bridge has +downstream impact on **every generated app**, so it gets extra scrutiny. +Specifically, PRs will be declined if they: + +- store or expose credentials/secrets to web content, +- widen the native surface exposed to arbitrary pages without a capability + gate, +- weaken APK signing, isolation, or the fingerprint-disguise defaults, +- bundle unrelated changes inside a large diff. + +### Commit messages + +We don't enforce Conventional Commits, but a clear subject line and a wrapped +body that explains *why* the change exists make reviews much faster. Example: + +``` +ModuleMarket: cache registry.json for an hour + +Repeatedly hitting raw.githubusercontent.com on every screen open is wasteful +and triggers GitHub's anonymous rate limit on slow connections. Cache the +parsed registry under cache/module_market/ and treat anything fresher than +an hour as authoritative; the refresh button always bypasses the cache. +``` + +### Pull requests + +- Branch from `main`. Keep PRs focused — one logical change per PR. +- **Write Issues and PRs in English** — titles, bodies, and review threads. +- Describe the user-visible effect in the PR body, not just the code change. +- The standard loop is Issue → branch → PR (`Fixes #N`) → green CI → merge. + Issues close on merge, never on PR open or red CI. +- If your PR touches the build system, native code, or APK packaging, attach + the output of the template rebuild above (or note the failure if it fails + on your machine). +- CI runs on every PR. A green CI is required before merge. +- Never commit secrets, keystores, `local.properties`, or IDE/cache junk. + +### Reviewer expectations + +Maintainer reviews look for: + +- **Correctness.** Does the change do what the PR description says? Was it + verified by execution (tests, build output), not just by reading? +- **Safety.** See *Security* above. +- **Scope discipline.** Drive-by refactors expand the review surface. Land + them in a separate PR. +- **Style fit.** See *Coding conventions* above. +- **Both paths.** Preview-only features and export-only wiring are the two + classic failure modes — see *Preview ≠ export* above. + +--- + +## Code of conduct + +Feedback is required to be precise. "This code is garbage" is acceptable only +when accompanied by which code, why, and what would be less so. The maintainer +(**shiaho**) has on file a standing waiver covering criticism of himself, his +judgment, and his life choices. Praise unaccompanied by a working patch is +logged and otherwise disregarded. + +--- + + +## 贡献 DruksCode(中文) + +非常感谢你愿意花时间。DruksCode 的迭代速度取决于"小而聚焦"的贡献——下面三条路 +里挑一条走,其他的先忽略。 + +本指南对应 **DruksCode 2.6.0**(`versionCode 62`)。 + +### 你想做什么? + +| 你想…… | 路径 | 投入 | +| --- | --- | --- | +| 给应用内的 **模块市场** 提交一个 JS/CSS 模块 | [`modules/README.md`](../modules/README.md) | 几小时 | +| 报 Bug、提 Feature、问问题 | [GitHub Issues](https://github.com/shiaho777/web-to-app/issues) | 几分钟 | +| 修 Bug 或在 Android 客户端里做新功能 | 见下方代码贡献小节 | 几天 | + +不确定走哪条,先开 issue 或 discussion——动手前对齐方向,比写完再返工便宜 +得多。 + +### 模块市场贡献 + +让你的工作触达每一个用户最快的方式就是提一个模块。Schema、审核 Checklist 和 +CI 校验细节的主文档是 [`modules/README.md`](../modules/README.md)。这里仅保 +留一个极简入口,方便你先判断自己是不是走这条贡献路线: + +1. Fork 本仓库 +2. 新建 `modules/<你的模块>/module.json` 和 `main.js`(需要 CSS 时再加 + `style.css`) +3. 在 `modules/registry.json` 里加一行索引 +4. 提 PR + +市场**没有后端**。客户端读取 `registry.json` 和 `submissions.json`,只有已合 +并的模块才会在市场出现。模块改动会经过 CI 的 +`.github/scripts/ci/validate_modules.py` 校验,提 PR 前建议先本地跑: + +```bash +python3 .github/scripts/ci/validate_modules.py +``` + +### 代码贡献 + +> 面向 AI 编码助手与深度代码贡献者的权威工作指南是 +> [`AGENTS.md`](../AGENTS.md) —— 它讲清了编辑器、导出流水线、shell 模板与运行时 +> 之间如何连接,以及双路径预览 / 导出、配置字段漂移规则、打包约束和常见改动 +> 配方。对构建、shell 同步、导出打包或配置字段的任何非平凡改动,动手前请先读。 + +**动手前** + +- 在 [issues](https://github.com/shiaho777/web-to-app/issues) 里先搜一下 + 类似讨论 +- 较大的改动请先开 issue 说明要解决的问题和方案 +- **谨慎引入新依赖**。`app/build.gradle.kts` 与 `shell/build.gradle.kts` 的依 + 赖列表刻意保持精简——本项目全程在设备内签名打包 APK,shell 模板也特意把 + `targetSdk` 锁在 28,因为生成应用依赖 `fork`、`exec` 原生运行时。新依赖需 + 要充分理由,且宿主专用依赖绝不能漏进 shell 模板。 + +**本地环境** + +- Android Studio Hedgehog 或更新版本 +- JDK 17 +- Gradle wrapper 已锁定 Gradle 9.4.1,无需系统安装 Gradle + +```bash +git clone https://github.com/shiaho777/web-to-app.git +cd drukscode +./gradlew assembleDebug +``` + +仓库有三个 Gradle 模块:**`app`**(完整构建器和宿主)、**`shell`**(嵌入生 +成 APK 的运行时模板)和 **`clone-host`**(应用克隆使用的宿主代码)。共享运 +行时代码以 `app/` 为唯一事实来源,构建时同步到 `shell/`(`shell/build/` 下, +不要手改 `shell/src`——它是再生成的产物,部分被 git 忽略)。 + +提交前请跑通: + +```bash +./gradlew :app:compileStandardDebugKotlin -x syncCloneHostDex --no-configuration-cache +./gradlew :app:testStandardDebugUnitTest --no-configuration-cache -PskipShellTemplateSync=true +./gradlew :app:checkConfigFieldDrift --no-configuration-cache +``` + +动到 shell 同步的运行时代码或导出打包,还要重建你碰过的模板: + +```bash +./gradlew :shell:assembleRelease :app:syncShellTemplateApk --no-configuration-cache +``` + +> 原生代码(`node_launcher`、`go_exec_loader`、APK 优化器)按 ABI 经 CMake +> 编译,需要通过 SDK Manager 安装 Android NDK + CMake。CI 安装的是 +> `cmake;3.22.1` 与 `ndk;28.2.13676358`。 + +**代码大致位置** + +| 区域 | 路径 | +| --- | --- | +| 应用类型与核心配置(`AppType`、`WebApp`) | `app/src/main/java/br/com/drukstech/codeapp/data/model/` | +| 设备端 APK 打包 / 签名 | `app/src/main/java/br/com/drukstech/codeapp/core/apkbuilder/` | +| 服务端运行时(Node / PHP / Python / Go / WordPress) | `app/src/main/java/br/com/drukstech/codeapp/core/{nodejs,php,python,golang,wordpress}/` | +| WebView 引擎、原生桥、指纹伪装 | `app/src/main/java/br/com/drukstech/codeapp/core/{webview,engine,appearance}/` | +| Shell 配置与生成 APK 入口 | `app/src/main/java/br/com/drukstech/codeapp/core/shell/` | +| 预览播放器(`ui/gallery/`、`ui/media/`)vs 打包播放器(`ui/shell/`) | `app/src/main/java/br/com/drukstech/codeapp/ui/` | +| 扩展模块、模块市场、Agent | `app/src/main/java/br/com/drukstech/codeapp/core/{extension,market,agent}/` | +| Compose UI 与设计系统 | `app/src/main/java/br/com/drukstech/codeapp/ui/` | +| DI 依赖图(单一事实来源) | `app/src/main/java/br/com/drukstech/codeapp/di/AppModule.kt` | + +**预览 ≠ 导出:大多数打回的原因** + +宿主应用(预览)和生成的 APK(导出)跑的是**两套代码**: + +| | 预览(`:app`) | 导出的 APK | +| --- | --- | --- | +| 界面 | `ui/gallery/`、`ui/media/`、实时 `WebViewManager` | `ui/shell/*` 的同步副本 | +| 配置 | 编辑器 / 内存模型 | 经 `ShellModeManager` 读取的 JSON 资源 | + +一个功能只有两边都通才算做完。编辑器开关要影响生成 APK,必须走完整条 +链——模型 → `ApkConfig` JSON → shell 配置 → shell 同步的运行时代码;而播放 +器界面的行为要在预览和壳两套 composable 里各实现一遍。三道门禁负责兜底, +跑过它们,别跟它们争: + +- `checkConfigFieldDrift`——模型 / JSON / shell 字段名必须一致(Gson 会静默 + 丢掉对不上的字段)。 +- `WebViewConfigBooleanCoverageTest`——`WebViewConfig` 每新增一个 Boolean 都 + 必须进 `flipAllBooleans()` 并走完导出往返。 +- `ShellUiParityTest`——宿主播放器读的每个模型字段,壳播放器也必须读(或写 + 明 `allow` 理由)。新增每类播放器时照样子扩展。 + +**代码风格** + +- **注释解释 *为什么*,不复述 *干了什么*。** 反直觉的决策、跨文件约定、 + issue 引用(`#781`)值得一句短注释;命名清晰的小函数不需要解说。不要给 + 易读的代码写旁白。 +- **新 UI 一律构建在 Dkc 设计系统之上**——所有界面通过 `br.com.drukstech.codeapp.ui.design` + 渲染。旧的 `Premium*` / `Enhanced*` / `Settings*` 组件作为 Dkc 内部实现的 + 永久别名层保留——不要再新增,也无需强行替换。构建期有一个审计脚本 + (`.github/scripts/audit_ui_design_system.py`,接进 `build.gradle.kts`)按 + `.github/scripts/ui_design_allowlist.txt` 跟踪历史 UI 债务。 +- 复用 `ui/design/DkcTokens.kt` 里的设计 token(间距、圆角、透明度、高度), + 别硬编码数字。编辑器配置卡片共用一套排版语法(见 `AGENTS.md` recipe 12)—— + 照抄相邻卡片,不要自创,跑模拟器验效果,不要只编译。 +- **字符串必须覆盖全部 10 种已支持语言**:文案在 `core/i18n/Strings.kt` + (facade `object Strings` + 同文件 `StringsA`…`StringsE`,拆分只为常量池)。 + 已支持:中 / 英 / 阿 / 葡 / 西 / 法 / 德 / 俄 / 日 / 韩。 + 新增或修改面向用户的 `when (Strings.lang)` **必须**为 10 个分支写真实翻译, + 且不许写 `else ->`;禁止把 pt/es/fr/de/ru/ja/ko 继续当英文占位。品牌名、 + 纯格式符可与英文相同。某语实在不会翻可暂填英文并在 PR 标明。 +- **面向用户的文案绝不用 `R.string`。** 资源文件只有 zh/en/ar 三套,其他 7 + 语会静默回落到中文。`R.string` 只保留给无需本地化的资源。 +- 引入新的全局单例前请先讨论;`di/AppModule.kt` 是单一事实来源 +- **原生桥是按能力门禁的**:任何通过 `@JavascriptInterface` 暴露给网页的方法, + 都必须经过逐能力白名单(`NativeBridgeCapabilities`)。绝不要在没有门禁的 + 情况下把原生能力暴露给任意页面。绕过门禁的 PR 会被拒 +- **预览和打包运行时是两条路径**:见上文《预览 ≠ 导出》。共享运行时代码只改 + `app/`,构建时同步进 `shell/`;不要手改 `shell/src` 下的任何东西 +- 不要 catch 然后吞掉异常;用 `AppLogger` 记录后重新抛出或返回失败的 `Result` + +**安全** + +动到 WebView、文件 IO、APK 签名或原生桥的改动会影响**每一个生成出来的 +应用**,因此审核更严。出现以下情况的 PR 会被拒: + +- 把凭据 / 密钥存储或暴露给网页内容 +- 在没有能力门禁的情况下扩大暴露给任意页面的原生面 +- 削弱 APK 签名、隔离或指纹伪装的默认强度 +- 在一个大 diff 里夹带不相关的改动 + +**Commit 消息** + +不强制 Conventional Commits,但请把"为什么"写进正文。示例见英文段。 + +**Pull Request** + +- 从 `main` 分出分支,每个 PR 只解决一件事 +- **Issue 与 PR 请用英文写**——标题、正文、评审讨论 +- PR 描述写"用户看得到的效果",不只是代码 diff +- 标准流程是 Issue → 分支 → PR(`Fixes #N`)→ CI 变绿 → 合并。 + Issue 只在合并时关闭,开 PR 时不关、CI 红时不关 +- 改动涉及构建系统、原生代码或 APK 打包时,附上上面模板重建命令的结果 +- CI 必须绿色才会合并 +- 不要提交密钥、keystore、`local.properties` 或 IDE / 缓存垃圾 + +**Review 标准** + +- **正确性**——是否真的做了 PR 描述里写的事;是否经过执行验证(测试、 + 构建产物),而不只是"读起来对" +- **安全**——见上面《安全》小节 +- **聚焦**——顺手做的重构请单独发 PR +- **风格**——参考上面那条 +- **两条路径**——只在预览生效的功能和只在导出接线的配置是两类经典翻车——见 + 上文《预览 ≠ 导出》 + +### 行为准则 + +反馈须精准。"这代码是坨屎"仅在同时说明"哪段代码、为何如此、怎样才不至于" +时方予受理。维护者(**shiaho**)已就针对其本人、其判断力及其人生选择的批评 +出具长期豁免一份并存档。未附可用补丁的赞美,予以记录,余不受理。 diff --git a/.github/assets/social-preview.png b/.github/assets/social-preview.png new file mode 100644 index 0000000..f355a9d Binary files /dev/null and b/.github/assets/social-preview.png differ diff --git a/.github/assets/sponsors/swiftproxy-banner-en.png b/.github/assets/sponsors/swiftproxy-banner-en.png new file mode 100644 index 0000000..9e18bd9 Binary files /dev/null and b/.github/assets/sponsors/swiftproxy-banner-en.png differ diff --git a/.github/assets/sponsors/swiftproxy-banner-zh.png b/.github/assets/sponsors/swiftproxy-banner-zh.png new file mode 100644 index 0000000..33581b7 Binary files /dev/null and b/.github/assets/sponsors/swiftproxy-banner-zh.png differ diff --git a/.github/assets/sponsors/swiftproxy-logo-full.png b/.github/assets/sponsors/swiftproxy-logo-full.png new file mode 100644 index 0000000..4f4c64c Binary files /dev/null and b/.github/assets/sponsors/swiftproxy-logo-full.png differ diff --git a/.github/docs/README_CN.md b/.github/docs/README_CN.md new file mode 100644 index 0000000..ace7248 --- /dev/null +++ b/.github/docs/README_CN.md @@ -0,0 +1,365 @@ +
+ +DruksCode 图标 + +# DruksCode + +### 在手机上把 Web 项目打包成可安装的 Android APK。 + +**一个运行在设备端的 APK 工作台,远不只是套个 WebView —— 它能在手机上 fork+exec 完整的服务端运行时,内置硬核反审查网络栈,能在设备内签名上架 Google Play 的 AAB,还能跑 MV3 浏览器扩展,全程不需要电脑或远程构建服务器。** + +[English](../../README.md) · **简体中文** + +[![Stars](https://img.shields.io/github/stars/shiaho777/drukscode?style=for-the-badge)](https://github.com/shiaho777/web-to-app/stargazers) +[![Forks](https://img.shields.io/github/forks/shiaho777/drukscode?style=for-the-badge)](https://github.com/shiaho777/web-to-app/network/members) +[![License](https://img.shields.io/badge/License-Unlicense-blue?style=for-the-badge)](../../LICENSE) +[![Android](https://img.shields.io/badge/Android-23%2B-3DDC84?style=for-the-badge&logo=android&logoColor=white)](#) + +
+ +

+ + Swiftproxy +
+ 由 Swiftproxy 赞助 —— 高质量纯净住宅IP提供商 +

+ +

+ 有什么不同 · + 能力速览 · + 能打包什么 · + 完整能力地图 · + 模块市场 · + 文档站点 · + 架构说明 · + 构建 +

+ +--- + +
+DruksCode:我的应用首页、应用列表与主工具箱(Agent、扩展模块、端口管理器)、单个应用的 APK 操作(编辑、创建快捷方式、构建/分享/导出 APK),以及关于页面——全部运行在 Android 手机上 +
+ +### 演示视频 + +
+观看:在设备上构建并打包一个应用的快速演示 + + + +
+ +--- + +## DruksCode 有什么不同 + +绝大多数「网站转 App」工具到「套一个 WebView」就结束了。DruksCode 更像一个放在手机里的 APK 工作台,而真正难的地方,正是它和那些工具的分界线: + +- **在设备上跑真实的服务端运行时。** Node.js、PHP、Python、Go、WordPress 以原生二进制的形式直接从 app 存储 fork+exec —— 像 Termux 那样,但被打进一个可安装的 APK。URL 套壳工具根本做不到。 +- **内置硬核、反审查的网络栈。** DNS-over-HTTPS、TLS 指纹伪装(Chrome / Firefox / Safari 的 JA3 模板,经本地 MITM 桥接)、双引擎 ECH(加密 SNI)、每应用代理、以及针对受限 SPA 的 CORS 绕过。 +- **整个构建自包含。** 二进制 AXML/ARSC 修补、权限裁剪、V1/V2/V3 签名、可直接上架 Google Play 的 AAB 导出,全部在 app 内通过 `apksig` 完成 —— 不排远程队列、不需要电脑。 +- **发布后仍可扩展。** 通过 JS/CSS 模块、Tampermonkey 风格油猴脚本,或 MV3 Chrome 扩展(可在应用内实时搜索 Chrome 网上应用店并安装)给应用补能力,不必重新发布宿主。 +- **宿主 UI 原生支持 10 种语言。** 中文、English、العربية(RTL)、Português、Español、Français、Deutsch、Русский、日本語、한국어 —— 设置里随时切换;新增界面文案按 10 语维护。 + +--- + +## 能力速览 + +一眼看清里面有什么。每项都对应下方完整能力地图。 + +| 方向 | 亮点 | +| --- | --- | +| **构建目标** | Web · HTML · 前端 · WordPress · Node.js · PHP · Python · Go · 图片 · 视频 · 图库 · 多网站 | +| **浏览器引擎** | 默认系统 WebView;可选 GeckoView(Firefox)运行时 | +| **网络与反审查** | DoH(7 个服务商)、TLS 指纹伪装 + MITM 桥、ECH、静态/PAC/SOCKS5 代理、CORS 绕过 | +| **隐私与加固** | 50+ 维浏览器指纹伪装、资源加密(AES-256-GCM)、反调试、激活码门控 | +| **本地运行时** | 原生 Node.js 18.20、PHP 8.4 + Composer 2.10、Python 3.14、官方 Go 1.26、WordPress 7.x over SQLite | +| **扩展能力** | 内置模块、`GM_*` 油猴脚本、MV3 Chrome 扩展、Chrome 网上应用店实时搜索 | +| **APK/AAB 产物** | 设备端 V1/V2/V3 签名、Google Play AAB 导出(自动改写 targetSdk)、密钥库管理 | +| **Agent** | 通过最多 57 个工具全面操控应用:生成、构建、导出、端口/引擎/运行时管理、应用克隆、广告拦截、配置模板等;429/5xx 自动重试 | +| **宿主语言** | **10 种界面语言** —— 中文 · English · العربية · Português · Español · Français · Deutsch · Русский · 日本語 · 한국어(阿语 RTL) | + +--- + +## 能打包什么 + +| 输入 | 输出 | 适合场景 | +| --- | --- | --- | +| 网站 URL | 基于 WebView 的 APK | 官网、工具、后台、文档、内部系统 | +| HTML / 静态前端 | 走 localhost 的 APK | React、Vue、Vite、静态构建、离线 Web 应用 | +| Node.js / PHP / Python / Go | 带设备端本地服务的 APK | 小型服务端应用、管理工具、演示、原型 | +| WordPress | 本地 PHP + SQLite 承载的 APK | 便携站点、主题/插件演示、本地内容包 | +| 图片 / 视频 / 图库 | 媒体型 APK | 相册、课程材料、作品集、离线浏览 | +| 多个网站 | 标签/卡片/信息流/抽屉布局 APK | 导航合集、门户、应用集合 | +| 已安装 APK | 重命名克隆或桌面快捷方式伪装 | 图标/名称/包名实验、APK 重打包研究 | + +--- + +## 完整能力地图 + +DruksCode 的开关非常多。下面按使用场景分组,并用可折叠区段保持页面顶部清爽可读。 + +
+🌐 浏览器引擎与网络 + +- **双引擎** —— 默认系统 WebView,可选 GeckoView(Firefox)运行时(首次使用时下载)。 +- **内核风味伪装** —— 对外表现为 Chrome、Edge、Samsung Internet、Firefox 或 Safari 风格,但真实引擎不变。 +- **桌面模式**、自定义 User-Agent,以及 document-start / end / idle 三种时机的 JS/CSS 注入。 +- **弹窗处理** —— 当前窗口、外部浏览器、弹窗窗口或直接拦截。 +- **代理** —— 静态 HTTP/HTTPS/SOCKS5、PAC、身份验证、绕过规则和本地 HTTP-to-SOCKS 桥。 +- **DNS-over-HTTPS** —— Cloudflare、Google、AdGuard、NextDNS、CleanBrowsing、Quad9、Mullvad,以及自定义 endpoint;支持 strict / automatic 模式。 +- **ECH(Encrypted Client Hello)** —— 在**两种引擎**上加密 TLS 握手中的 SNI:GeckoView 经 TRR + 自身 ECH 配置;系统 WebView 经本地 MITM 桥的 Chromium 上行链路(首次使用自动下载组件,导出的 APK 内置)。开关启用时自动联动 DoH;与 SOCKS 上游代理互斥。 +- **TLS 指纹伪装** —— 模拟 Chrome 131 / Firefox 133 / Safari 18 的 JA3 指纹(或自定义密码套件),经本地 TLS-MITM 桥接,让发出的 ClientHello 与真实浏览器一致。 +- **CORS 绕过** —— 默认开启,让受限静态 SPA 能调用原本被 CORS 拦截的外部 API;同源请求不会被误拦,仅需 CORS/内网桥接时可用轻量 `PrivateNetworkNativeBridgeAdapter`,不必挂完整 Native Bridge。 +- **回退链** —— 主目标不可达时自动回退到镜像 URL。 +- **PWA** 离线缓存策略、自定义错误页、每应用 hosts 覆写和支付协议处理。 +- **兼容开关** —— blob 下载拦截、滚动记忆、图片修复、剪贴板 / 方向 / 通知 polyfill、内网桥接和 Native Bridge 能力门控。 +- **下载位置** —— 系统 Downloads、应用私有目录,或用户用 SAF 自选文件夹,整条打包透传链已接通。 + +
+ +
+🛡️ 隐私、指纹防御与加固 + +- **跨 50+ 维的浏览器指纹伪装** —— User-Agent、WebGL、Canvas、AudioContext、ClientRects、时区、语言、内存、媒体设备、WebRTC、字体、电池、权限、性能、存储、通知、CSS media、iframe 传播和错误栈清理。 +- **hosts 规则广告拦截** + cosmetic MutationObserver 过滤,**内置 20 个社区过滤源**(EasyList、uBlock Origin、AdGuard、AdAway + 8 个语言列表),支持逐源启用/停用/删除,自定义导入的过滤源带名称、以卡片管理并可按应用勾选,以及打包进 APK 的自定义订阅规则。 +- **资源加密**(PBKDF2 + AES-256-GCM)覆盖打包进去的配置、HTML、媒体和 BGM;可设置自定义加密密码,比默认的包名/证书派生密钥更能抵御逆向提取。 +- **运行时加固**(开启加密后可用)—— 反调试、反 Frida、DEX 篡改检测;威胁响应可选只记录、静默退出或随机崩溃。 +- **WebView/内容隔离**覆盖存储、WebRTC、Canvas、Audio、WebGL、字体、请求头和 IP 暴露面。 +- **激活码门控** —— 本地验证,或接入你自己的 HTTPS 接口并用 EC P-256 验签。接口契约见 [remote activation 文档](remote-activation.md)。 + +
+ +
+📦 设备端服务器运行时(fork + exec) + +- **Node.js**(18.20.x)跑在独立 `:nodejs` OS 进程中,底层由原生 `node_launcher` 加载 `libnode.so`;支持自定义原生 `.node` 扩展。 +- **PHP 8.4** 取自 `pmmp/PHP-Binaries`,首次使用时下载,支持 Composer 2.10.x 和自定义原生扩展(`zend_extension`、`.so`)。 +- **Python 3.14** —— Flask、Django、FastAPI/uvicorn、Tornado、内置 HTTP server;pip 依赖解析到 `.pypackages`,支持自定义原生扩展;二进制名按版本生成,后续升级不必硬编码路径。 +- **Go 1.26** —— 官方 Linux arm64 工具链(`.tar.gz` 来自 `dl.google.com`,国内走 USTC 镜像),设备端 `go build` / `go mod` / `go run`、`vendor/` 离线构建、静态文件服务和原生 `go_exec_loader` 包装层;DNS 与 CA 信任走与 PHP 相同的本机 JVM 桥接。 +- **WordPress 7.x** 跑在本地 PHP 之上,用 `sqlite-database-integration` 接 SQLite,支持主题和插件导入。 +- **Linux Environment** 页面管理 Node、PHP、Python 的工具链和依赖。 +- **Port Manager** 通过广播 receiver 协调不同生成应用之间的运行时端口。 +- **本地 DNS 桥接代理**(运行在 Android JVM 的 HTTP CONNECT)在 musl/打包二进制无法访问系统 DNS 时,为运行时提供可用的 DNS 解析和出站 HTTP。 + +
+ +
+🧩 扩展与自动化 + +- **内置模块** —— 视频下载(YouTube / B 站 / 抖音 / 小红书提取器)、带 YouTube 净化(跳过广告、最高画质、后台播放、SponsorBlock)的视频增强、网页分析、页内查找、暗色模式、隐私工具、内容增强、元素拦截和 YouTube 启动器。 +- **油猴脚本** —— Greasemonkey/Tampermonkey 风格的 `.user.js`,配套 `GM_*` 桥接(存储、请求、样式、菜单命令)和按授权开放的 Promise 风格 `GM.*` API。 +- **MV3 Chrome 扩展运行时**,支持 manifest 内容脚本在 isolated 或 main world 注入,并提供覆盖 runtime、storage、tabs、scripting 和 declarative network request 解析的 `chrome.*` polyfill。 +- **应用内 Chrome 网上应用店搜索** —— 按关键词浏览并安装浏览器扩展(也可粘贴商店链接 / 扩展 ID),离线时回退到手动导入。 +- **分享码**(`DKC1:` gzip + Base64)和 ZXing 二维码传播。 +- **Agent** —— 工具调用型助手,内置最多 57 个工具覆盖应用全部功能:创建/编辑/构建/导出应用、管理端口与浏览器引擎、安装/清理运行时、广告拦截 hosts 规则、通用配置模板、使用统计、应用克隆、批量导入、Play 合规检查、模块开发。计划模式等待用户确认;对 429/5xx 自动退避重试。 + +
+ +
+📱 应用体验 + +- **启动屏** —— 图片或视频,支持跳过、视频裁剪区间和固定方向。 +- **背景音乐** —— 播放列表 + LRC 同步歌词、歌词动画、自定义字体/颜色/描边/阴影和在线音乐搜索。 +- **工具栏、状态栏(亮色/暗色)、导航栏、悬浮窗模式和长按菜单样式。** 浏览器工具栏是一个主开关(默认关闭),可逐项控制标题/URL/后退/前进/刷新按钮,并带原生 **页内查找** 底栏(工具栏查找按钮)和 **控制台** 面板,便于在设备上调试。状态栏颜色可跟随主题、自定义色、全透明,或 **PAGE_TOP**(采样页面顶部像素,让系统栏跟内容同色)。 +- **下载位置模式** —— 系统 Downloads、应用私有目录,或用户用 SAF 自选文件夹。 +- **公告模板**,可在启动、定时或无网络时触发。 +- **宿主应用语言** —— 整个打包器界面可在 10 种语言间切换(中文 / English / العربية / Português / Español / Français / Deutsch / Русский / 日本語 / 한국어);阿拉伯语完整 RTL。 +- **页内翻译覆盖层** —— 20 种目标语言,支持 Google、MyMemory、LibreTranslate、Lingva 引擎,并在引擎间自动故障转移(给*生成应用内容*做页内翻译,与宿主 UI 语言是两套能力)。 +- **打印桥接** —— 拦截 `window.print()` 和 blob/data-URL 的 PDF,交给 Android 打印框架 / 导出 PDF(onPageStarted 会再注入一次,避免晚导航丢 hook)。 +- **媒体会话桥接** —— 把网页媒体接入系统媒体通知和锁屏控制,支持蓝牙耳机和 Android Auto。 +- **通知** —— Web Notification polyfill、定时与持久化通知(含进度更新)、URL 轮询前台服务、深链、开机自启、定时启动和后台运行服务。 +- **每个 APK 的使用统计**、Vico 图表和 URL 健康监测。 + +
+ +
+🔧 APK / AAB 导出与签名 + +- **自定义包名**、`versionName`、`versionCode`、图标、名称、架构目标和导出格式。 +- **按生成 APK 的实际勾选注入权限**,并从模板 manifest 中裁剪未使用权限。 +- **一键 AAB 导出** —— 按需自动构建 APK,转换成可直接上架的签名 AAB(自动把 `targetSdk` 改写到 Play 要求的级别,目前为 36,并在本地生成 protobuf 元数据);支持中途取消。 +- **密钥库管理** —— 创建、导入、导出、删除和证书指纹查看;支持 PKCS12/PFX/JKS/BKS 导入,包括 Android Studio upload key 那种 store 密码和 key 密码不同的情况。 +- **签名方案** —— V1、V2、V3 独立控制,可对旧证书兼容性自动回退;自定义 V1 签名文件名,对应 `META-INF/.SF` / `.RSA`。 +- **性能选项** —— 图片压缩、WebP 转换、代码压缩、懒加载、DNS 预取、preload 提示。 +- **完整项目备份/恢复和应用数据备份/恢复。** + +
+ +
+🗂 文件管理与项目工具 + +- **文件管理** —— 一个界面统一查看、分享、安装、打开和清空构建产物(APK 构建、AAB 导出、应用克隆、构建日志)和用户文件目录,并提供只读的构建日志查看器。 +- **网站爬虫**用于生成离线包 —— HTML、CSS、JS、图片、字体、`url()`、`srcset`、`@import`、路径重写、同域限制、深度限制和体积限制;并行流式 worker 池,进度回调回到主线程。 +- **多网站应用** —— 标签、卡片、信息流、抽屉布局,每站点独立图标/主题色/提取选择器/刷新间隔和共享 JS/CSS。 +- **图库应用** —— 媒体分类、网格/列表/时间线视图、随机/单循、排序、缩略图条、浮层、视频自动下一个和播放记忆。 +- **应用修改器** —— 桌面快捷方式伪装,或真正的二进制克隆、manifest/资源修补和重签名。 + +
+ +
+🔬 专项工具与研究功能 + +- **设备伪装**属于技术演示能力,必须在用户知情同意下使用。 + +
+ +--- + +## Agent + +DruksCode 内置了一个 AI Agent(从 **⋮ → Agent** 打开),可以通过自然语言对话操控整个应用。你只需描述想做什么,Agent 就会通过工具调用循环在设备端执行,后端模型由你在 AI 设置中配置的任意受支持接口提供——Chat Completions、Anthropic Messages、OpenAI Responses 三种 API 格式,以及 Google Gemini 与 Ollama / LM Studio / VLLM 本地模型。 + +**工作原理:** + +1. 你发送消息(也可附带图片作为视觉上下文)。 +2. LLM 推理后发出 `tool_calls`。 +3. Agent 在设备端执行每个工具 —— 只读工具直接运行;写入工具会先弹出权限确认对话框。 +4. 结果回传给 LLM,LLM 继续执行直到任务完成或向你提出澄清问题。 + +**最多 57 个内置工具,按功能域分组(3 个图像工具仅在配置了图像模型时加载):** + +| 功能域 | 示例 | +| --- | --- | +| 文件 | 读取、写入、编辑、删除、列出、glob、grep 项目文件 | +| 应用 | 列出、查看、创建、更新应用配置 | +| 应用生命周期 | 构建 APK/AAB、导出、分享、创建快捷方式、复制、删除、移动分类 | +| 端口与引擎 | 扫描/终止端口,查看/切换/删除浏览器引擎(WebView、GeckoView) | +| 运行时 | Node.js、PHP、Python、Go、WordPress、Linux 环境的状态查看、安装和缓存清理 | +| 广告拦截 | 规则数量统计,导入/删除/启用/停用 hosts 订阅 | +| 统计与健康 | 使用统计、URL 健康检查 | +| 应用修改器 | 列出已安装应用、克隆/换壳、批量导入、导出模板 | +| 构建环境与合规 | 初始化 Linux 构建环境、安装组件、Google Play 合规检查 | +| 模块 | 列出、创建、更新扩展模块 | +| 交互 | 向用户提问(多选)、计划模式(提议→批准→执行)、待办跟踪 | + +--- + +## 模块市场 + +DruksCode 有一个由 GitHub 驱动的模块市场,用来分发社区贡献的 JS/CSS 扩展模块。目录本质上就是这个仓库里的文件,所以贡献流程就是普通 PR。 + +``` +modules/ +├── registry.json # App 读取的目录 +├── submissions.json # CI 生成的 PR / 贡献者元数据 +├── README.md # 贡献者指南 +└── <模块文件夹>/ # 每个模块 +``` + +App 会同时拉取 `registry.json` 和 `submissions.json`,只展示两边都存在的模块,保证应用内市场和已经合并的 PR 对齐。submissions 文件还会记录每个模块的全部贡献者,因此应用内会以叠加头像的形式展示所有参与过该模块的人,并按贡献模块数排出贡献者榜单。目录文件和模块图标会优先走全球镜像加速,raw.githubusercontent.com 和 jsDelivr 作为自动回退,因此商店在全球(含中国大陆)都能快速加载。 + +- 用户打开 **扩展模块** 页面,点击右上角商店图标即可安装。 +- 贡献者在 `modules/` 下添加文件夹,更新 `registry.json`,然后提交 PR。 +- 客户端默认缓存 1 小时,模块合并后不需要发新版 App。 + +这里保留的是模块市场的高层说明;真正的投稿规则、字段 schema、审核 Checklist 和 CI 校验细节统一写在 [`modules/README.md`](../../modules/README.md)。 + +社区市场只承载 JS/CSS 扩展模块。**浏览器扩展(MV3)**不再是社区目录 —— **浏览器扩展** Tab 直接实时搜索 Chrome 网上应用店:输入关键词、浏览结果、通过现有的 CRX 下载链路按需安装。如果实时搜索不可达,也可以粘贴商店链接或 32 位扩展 ID 直接安装。实时搜索需要能访问 Google 的网络。 + +## 文档站点 + +官方文档站点发布在 **[shiaho777.github.io/web-to-app](https://shiaho777.github.io/web-to-app/)**,中英双语: + +| 板块 | 地址 | 内容 | +| --- | --- | --- | +| 使用指南 | [/zh/guide/introduction](https://shiaho777.github.io/web-to-app/zh/guide/introduction) | 快速上手、主界面、应用类型、单应用操作与通用配置、FAQ | +| 开发者文档 | [/zh/developer/](https://shiaho777.github.io/web-to-app/zh/developer/) | 架构、导出管线、shell 同步、配置漂移、i18n、常见改动配方 | +| 扩展开发 | [/zh/extensions/](https://shiaho777.github.io/web-to-app/zh/extensions/) | JS/CSS 模块、油猴脚本、Chrome MV3、API 参考、发布流程 | +| English | [/](https://shiaho777.github.io/web-to-app/) | 上述全部页面的英文原版 | + +## 架构说明 + +- 仓库有**三个 Gradle 模块**:`app`(完整构建器和宿主)、`shell`(嵌入生成 APK 的运行时宿主)、`clone-host`(应用克隆的宿主代码 —— 编译提取 `classes.jar`,经 d8 转 DEX,作为 asset 供 `AppCloner` 使用)。 +- 运行时代码以 `app` 为唯一事实来源,再同步到 `shell`,所以共享 WebView/运行时行为只维护一份(`core/shell`、`core/webview`、`core/engine`、`core/extension`、`ui/shell` 等)。 +- APK 构建器在二进制 AXML/ARSC 层修补模板 APK,注入配置与资源,裁剪权限,并用 `apksig` 签名。另有独立的加密构建路径(`EncryptedApkBuilder`)提供资源加密、加壳和完整性校验。 +- 生成 APK(经 shell 模板)特意把 `targetSdk` 钉在 28 —— 这是让它们能从 app 存储 `fork`、`exec` 原生运行时(Node.js、PHP、Python、Go、WordPress)的关键,网址转 APK 类工具做不到这点。宿主应用自身以 35 为目标(杀毒引擎会把低 targetSdk 构建误判为旧木马);该级别的 SELinux W^X 会拦截宿主侧基于 exec 的运行时预览,它们会以明确提示优雅降级 —— Node.js 预览(JNI)和所有导出的应用均不受影响。导出 AAB 时会单独把 `targetSdk` 改写以满足 Google Play 上架要求;纯 WebView 应用类型(Web/HTML/Frontend/Gallery/Media/MultiWeb)还可在 APK 导出面板选择提高独立 APK 的 `targetSdk`(34/35/36),服务端运行时类型固定 28,因为 `targetSdk >= 29` 的 W^X 会破坏内置二进制的 fork+exec。 +- 服务端运行时和可选 GeckoView 原生库(`.so` + `omni.ja`)不会打进基础 APK,而是在首次使用时下载;GeckoView 的 API 类来自 gradle 依赖,而体积大的原生制品按需拉取。 +- 配置中心是 `WebApp`(`data/model/WebApp.kt`)及其各 `*Config` 类 —— 所有功能配置的单一事实来源,经一条完整的打包透传链带进生成的 APK。 + +## 技术栈 + +- Kotlin、Jetpack Compose、Material 3 +- Koin 依赖注入 +- Room 2.7.2 + KSP 数据持久化 +- OkHttp 4.12.0 + `okhttp-dnsoverhttps` +- `com.android.tools.build:apksig` 8.3.0 用于 APK 签名 +- BouncyCastle 1.78.1 用于加密与签名 +- `protobuf-javalite` 3.25.5 用于 AAB 元数据 +- Firebase Cloud Messaging(需自行配置 Firebase)用于推送通知 +- GeckoView 作为可选浏览器引擎(原生库在首次使用时下载) +- Coil 负责图片、视频、GIF 加载 +- Haze 用于毛玻璃 / 玻璃拟态 UI +- Gson 用于 JSON 序列化(shell 配置链路) +- AndroidX Security Crypto + DataStore 存储密钥 +- Vico Compose-M3 绘制图表 +- ZXing 用于二维码分享 +- Apache Commons Compress + xz 用于项目导入和网站爬虫 +- JNI 原生 C++ 目标:`node_launcher` 和 `go_exec_loader` +- Robolectric 单元测试 + +完整依赖见 [app/build.gradle.kts](../../app/build.gradle.kts)。 + +## 从源码构建 + +要求:Android Studio Hedgehog 或更新版本,JDK 17。Gradle wrapper 已锁定 Gradle 9.4.1。 + +```bash +git clone https://github.com/shiaho777/web-to-app.git +cd drukscode +./gradlew assembleDebug +``` + +Release 构建请通过 `local.properties` 和 `app/build.gradle.kts` 配置签名。 + +## 参与贡献 + +| 路径 | 内容 | 指南 | +| --- | --- | --- | +| `modules/` | 给应用内市场提交一个社区模块 | [modules/README.md](../../modules/README.md) | +| Issues | 报告 Bug 或申请功能 | [GitHub Issues](https://github.com/shiaho777/web-to-app/issues) | +| 代码 | 修 Bug 或在 Android 客户端做新功能 | [CONTRIBUTING.md](../CONTRIBUTING.md) | +| `AGENTS.md` | 面向 AI 编码助手与深度贡献者的权威指南(架构连线、shell 同步、导出流水线、配置漂移、打包约束) | [AGENTS.md](../../AGENTS.md) | + +## 联系方式 + +开发者:**shiaho**。 + +| 平台 | 链接 | +| --- | --- | +| GitHub | [github.com/shiaho777/web-to-app](https://github.com/shiaho777/web-to-app) | +| Telegram | [t.me/webtoapp777](https://t.me/webtoapp777) | +| X (Twitter) | [@shiaho777](https://x.com/shiaho777) | +| Bilibili | [b23.tv/8mGDo2N](https://b23.tv/8mGDo2N) | +| QQ 群 | 1041130206 | + +## 许可证 + +[The Unlicense](../../LICENSE)。 + +设备伪装等高级功能仅用于技术演示,必须在用户知情同意下使用。 + +## 鸣谢 + +[daoxe.com](https://daoxe.com) — 自用中转站。 + +

+ + Swiftproxy —— 全球高质量纯净住宅IP,动态流量不过期,支持HTTP(S)/SOCKS5,九折优惠码:PROXY90 + +

+ +

+ 由 Swiftproxy 赞助 —— Swiftproxy 提供 9000万+ 纯净住宅 IP,覆盖全球 220+ 个国家和地区,支持 HTTP(S)/SOCKS5、动态轮换、Sticky Session 及精准地域定位。适用于 Web App、自动化、网页抓取及全球网络访问等场景,提供稳定可靠的代理服务。支持免费测试,使用优惠码 PROXY90 可享 9 折优惠。 +

+ +--- + +
+ +**开源 · 为 Android 高阶用户打造 · Star 一下支持项目** + +
diff --git a/.github/docs/remote-activation.md b/.github/docs/remote-activation.md new file mode 100644 index 0000000..2a45f69 --- /dev/null +++ b/.github/docs/remote-activation.md @@ -0,0 +1,331 @@ +# Remote Activation — Server Contract + +DruksCode can verify activation codes against **your own HTTPS endpoint** +instead of (or in addition to) the codes baked into the APK. This lets you +revoke codes, issue them dynamically, and control usage centrally — without +rebuilding the app. + +> **Security note.** The host is open source and verification runs on the +> client, so a determined attacker can still patch the check out. Remote +> verification *raises the bar* and gives you revocation/rotation; it is not +> an anti-cracking guarantee. The response signature below stops a fake server +> or a man-in-the-middle from forging an `ok: true`, which is the part that +> matters most. + +## How it is configured in the app + +When building an app (or in App Modifier), enable **Online Verification** under +the activation-code section and fill in: + +| Field | Meaning | +| --- | --- | +| Verification endpoint | Your `https://…` URL. Plain `http://` is rejected. | +| Signature public key | An **EC P-256** public key in Base64 (SPKI / `BEGIN PUBLIC KEY`). The app verifies every response with it. | +| Offline policy | `ALLOW_CACHED` (default): allow the last successful result until it expires. `DENY`: block when offline. `ALLOW`: always allow when offline (insecure). | +| Deliver target URL | When on, the target URL is delivered by the server at activation time (not packaged in the APK). See [Dynamic URL delivery](#dynamic-url-delivery). | +| Encrypt target URL | When on (requires Deliver URL), the server must encrypt the URL with AES-256-GCM before signing. See [URL Encryption](#url-encryption-aes-256-gcm). | +| AES-256 key | 32-byte Base64 key shared with the server. Required when encryption is enabled. | + +## Request (app → your server) + +``` +POST +Content-Type: application/json; charset=utf-8 +Accept: application/json +``` + +```json +{ + "code": "ABC123", + "deviceId": "f3a9…", + "packageName": "com.example.app", + "nonce": "Base64-random-24-bytes", + "ts": 1733270400000, + "deviceBound": false +} +``` + +- `code` is normalised (uppercased, trimmed) before sending. +- `deviceId` is a per-device identifier (not a hardware ID; it is a salted hash). +- `nonce` is fresh per request — you **must** echo it back unchanged (replay + protection). +- `ts` is the client clock in epoch milliseconds. +- `deviceBound` is `true` when the app has the **Device binding (one-time codes)** + toggle enabled in the editor's remote-activation section (it is always `false` + for purely local verification — see below). For such codes your server should + enforce per-device binding: record the first `deviceId` that activates a given + `code`, and reject the same `code` from any different `deviceId` (return + `{ "ok": false }`). This is the only way to truly restrict a device-bound code + to one device — the app itself has no shared state between devices, so a purely + local device-bound code can only prevent re-activation on the same device + after a local reset or hardware change. + + The reference worker in `examples/remote-activation-worker` implements this as + seats: `maxDevices` (default `1`) devices may claim a code; a code with + `maxDevices: 1` behaves as a **one-time / single-device code**. The claimed + device id survives uninstall + reinstall on the same device (it derives from + `ANDROID_ID`, stable per signing key), so a seat is only released when you edit + the KV record. To free a seat manually, remove the `deviceId` entry from + `record.devices` (or delete `code:`). + +## Response (your server → app) + +```json +{ + "ok": true, + "expiresAt": 1735862400000, + "remainingUses": 5, + "message": "", + "nonce": "Base64-random-24-bytes", + "sig": "Base64-ECDSA-signature", + "url": "https://example.com/app" +} +``` + +| Field | Type | Notes | +| --- | --- | --- | +| `ok` | boolean | `true` grants activation. | +| `expiresAt` | number \| null | Epoch ms. If present and in the past, the app treats it as expired. Use `0`/omit for "never expires". | +| `remainingUses` | number \| null | Informational. Use `-1`/omit when not tracking. | +| `message` | string | Shown to the user on rejection. | +| `nonce` | string | Must equal the request nonce. | +| `sig` | string | Base64 ECDSA (`SHA256withECDSA`, DER-encoded) over the canonical payload below. | +| `url` | string \| null | Optional. The target URL to load. Only used (and signature-bound) when the app has **Deliver target URL from server** enabled — see [Dynamic URL delivery](#dynamic-url-delivery). When **Encrypt target URL** is also enabled, this field contains the AES-256-GCM ciphertext (see [URL Encryption](#url-encryption-aes-256-gcm)). Omit otherwise. | + +### Canonical payload that gets signed + +The app rebuilds this exact JSON string and verifies `sig` against it. **Key +order and formatting matter** — it is compact JSON with these four keys, in +this order: + +``` +{"ok":,"expiresAt":,"remainingUses":,"nonce":""} +``` + +- `expiresAt` falls back to `0` when you omit it. +- `remainingUses` falls back to `-1` when you omit it. +- No spaces, booleans unquoted, numbers unquoted. + +When **Deliver target URL from server** is enabled, a fifth key `url` is +appended (after `nonce`), and the signature must cover it too: + +``` +{"ok":,"expiresAt":,"remainingUses":,"nonce":"","url":""} +``` + +`url` falls back to `""` when you omit it. Apps that do not enable URL delivery +verify the legacy four-key payload, so existing servers keep working unchanged. + +Example of the precise bytes to sign: + +``` +{"ok":true,"expiresAt":1735862400000,"remainingUses":5,"nonce":"k7Q…"} +``` + +## Dynamic URL delivery + +When **Deliver target URL from server** is enabled in the app, the target URL +is not packaged into the APK. Instead the app loads the URL you return in the +`url` field after a successful activation (and caches it for offline launches +under `ALLOW_CACHED`). This lets you change the URL without repackaging, and +keeps the URL out of the APK so it cannot be extracted statically. + +- Return the URL in `url` and include it in the signed payload (fifth key). +- The URL is cached on the device after a successful online activation; offline + launches reuse the cached URL per the offline policy. +- The URL is delivered in the clear inside the signed response (over HTTPS). + This raises the bar against casual extraction but is not DRM-grade — a + determined attacker can still recover it from the response or memory. + +## URL Encryption (AES-256-GCM) + +When both **Deliver target URL from server** and **Encrypt target URL** are +enabled, the server must encrypt the URL with AES-256-GCM **before** signing. +The ciphertext goes into the `url` field and the signed payload. + +| Parameter | Value | +| --- | --- | +| Algorithm | AES-256-GCM (authenticated encryption) | +| Key | 32 bytes, shared between app config and server | +| IV | 12 random bytes per encryption | +| Wire format | `Base64(IV[12B] \|\| ciphertext \|\| GCM tag[16B])` | + +**Why encrypt the URL when the response is already over HTTPS and ECDSA-signed?** +Defense in depth. If an attacker compromises the TLS layer (corporate MITM +proxy with a user-installed CA, misconfigured certificate pinning bypass) or +dumps the response from memory, the URL stays unreadable without the AES key. +The signature still prevents tampering, and the encryption prevents reading. + +### Generating an AES-256 key + +```bash +# Generate a 32-byte random key and Base64-encode it +openssl rand -base64 32 +``` + +Paste the same Base64 string into both the app's **AES-256 key** field and +your server configuration. + +### Server-side encryption (Node.js) + +```js +const crypto = require("crypto"); + +function encryptUrl(plaintext, aesKeyBase64) { + const key = Buffer.from(aesKeyBase64, "base64"); // 32 bytes + const iv = crypto.randomBytes(12); + const cipher = crypto.createCipheriv("aes-256-gcm", key, iv); + let encrypted = cipher.update(plaintext, "utf8"); + encrypted = Buffer.concat([encrypted, cipher.final()]); + const tag = cipher.getAuthTag(); // 16 bytes + // Wire format: IV || ciphertext || tag + return Buffer.concat([iv, encrypted, tag]).toString("base64"); +} +``` + +### Signing flow with encryption + +1. Encrypt the URL → Base64 ciphertext blob. +2. Build the canonical payload with the ciphertext blob as the `url` value. +3. Sign the canonical payload with ECDSA. +4. Return the ciphertext blob in the response `url` field and the signature in `sig`. + +The client verifies the signature first (which covers the ciphertext), then +decrypts `url` with the shared AES key to recover the plaintext URL. An +attacker who tampers with the ciphertext breaks the signature; an attacker who +reads the response sees only encrypted bytes. + +## Generating a key pair + +```bash +# private key (keep on your server) +openssl ecparam -name prime256v1 -genkey -noout -out ec_private.pem +# public key (paste into the app's "Signature public key" field, header lines optional) +openssl ec -in ec_private.pem -pubout -out ec_public.pem +``` + +## Ready-to-deploy option (Cloudflare Worker) + +If you would rather not run a server at all, there is a complete reference +worker in +[`examples/remote-activation-worker/`](../../examples/remote-activation-worker/README.md): +codes held in Workers KV (revocable without rebuilding the APK), signed +responses, device binding, optional AES-256-GCM URL delivery, and a +`GET /` self-check that hands you the public key to paste into the app. It +deploys with `npx wrangler deploy` and ships a test that verifies responses the +way the client does. + +One caveat it documents, because it applies to any server you write: **the +request does not say whether the app expects a delivered URL**, so the server +cannot discover it. A code that carries a `url` must be paired with an app that +has "Deliver target URL" enabled, and a code without one with an app that has it +disabled — otherwise the two sides sign different payloads and every activation +fails. + +The Node example below is the same contract for your own infrastructure. + +## Reference server (Node.js, no framework) + +```js +const http = require("http"); +const crypto = require("crypto"); +const fs = require("fs"); + +const privateKey = crypto.createPrivateKey(fs.readFileSync("ec_private.pem")); + +// Your own source of truth. Revoke by removing/flipping entries here. +// `url` is optional: set it (and enable "Deliver target URL from server" in the +// app) to deliver the target URL dynamically instead of packaging it. +// When URL encryption is enabled, encrypt `url` with the shared AES key before +// returning it (see the `encryptUrl` helper below). +const CODES = { + "ABC123": { expiresAt: 1735862400000, remainingUses: 5, url: "https://example.com/app" }, +}; + +// ---- AES-256-GCM encryption (only needed when "Encrypt target URL" is on) ---- +const AES_KEY_BASE64 = process.env.AES_KEY_BASE64 || ""; // same as in the app config +const AES_KEY = AES_KEY_BASE64 ? Buffer.from(AES_KEY_BASE64, "base64") : null; + +function encryptUrl(plaintext) { + if (!AES_KEY || AES_KEY.length !== 32) return plaintext; // passthrough if not configured + const iv = crypto.randomBytes(12); + const cipher = crypto.createCipheriv("aes-256-gcm", AES_KEY, iv); + let encrypted = cipher.update(plaintext, "utf8"); + encrypted = Buffer.concat([encrypted, cipher.final()]); + const tag = cipher.getAuthTag(); + return Buffer.concat([iv, encrypted, tag]).toString("base64"); +} +// ------------------------------------------------------------------------- + +function signedPayload({ ok, expiresAt, remainingUses, nonce, url }) { + // Must match the app's canonical order exactly. + const payload = { + ok, + expiresAt: expiresAt ?? 0, + remainingUses: remainingUses ?? -1, + nonce, + }; + // Include url only when delivering it; it becomes the fifth signed key. + // When encryption is on, `url` is already the ciphertext blob here. + if (url !== undefined) { + payload.url = url ?? ""; + } + return JSON.stringify(payload); +} + +function sign(payloadString) { + return crypto + .sign("sha256", Buffer.from(payloadString, "utf8"), privateKey) + .toString("base64"); +} + +http + .createServer((req, res) => { + let body = ""; + req.on("data", (c) => (body += c)); + req.on("end", () => { + let parsed; + try { + parsed = JSON.parse(body); + } catch { + res.writeHead(400); + return res.end(); + } + + const code = String(parsed.code || "").trim().toUpperCase(); + const nonce = String(parsed.nonce || ""); + const entry = CODES[code]; + + const result = entry + ? { ok: true, expiresAt: entry.expiresAt, remainingUses: entry.remainingUses, message: "" } + : { ok: false, expiresAt: 0, remainingUses: -1, message: "Code not recognised" }; + + // Encrypt the URL if AES key is configured; the ciphertext goes into + // both the signed payload and the response. + const urlPlain = entry && entry.url ? entry.url : undefined; + const urlEnc = urlPlain ? encryptUrl(urlPlain) : undefined; + + const sig = sign(signedPayload({ ...result, nonce, url: urlEnc })); + + res.writeHead(200, { "Content-Type": "application/json" }); + res.end(JSON.stringify({ ...result, nonce, sig, url: urlEnc })); + }); + }) + .listen(8443); +``` + +Serve it over HTTPS (behind a reverse proxy with a TLS cert, or with +`https.createServer`). The app refuses non-HTTPS endpoints. + +## Offline behaviour + +After a successful online check, the app caches the result (bound to the code +and its `expiresAt`). With `ALLOW_CACHED`, a later offline launch is allowed +until that expiry, then it prompts again. With `DENY`, any offline launch is +blocked. With `ALLOW`, offline launches always pass — only use this if losing +the gate offline is acceptable. + +## Privacy + +When online verification is on, the app sends the activation code and a device +identifier to the endpoint you configure. Disclose this to your users. diff --git a/.github/scripts/audit_ui_design_system.py b/.github/scripts/audit_ui_design_system.py new file mode 100644 index 0000000..d8f1813 --- /dev/null +++ b/.github/scripts/audit_ui_design_system.py @@ -0,0 +1,278 @@ +#!/usr/bin/env python3 +"""Audit Compose UI files for design-system migration debt. + +This script is intentionally non-failing by default. It reports legacy patterns +so migrations can reduce the count over time without blocking unrelated work. +Use --enforce-baseline with .github/scripts/ui_design_allowlist.txt to block new debt +while allowing documented historical debt to remain during migration. +""" + +from __future__ import annotations + +import argparse +import re +from collections import Counter, defaultdict +from dataclasses import dataclass +from pathlib import Path + + +REPO_ROOT = Path(__file__).resolve().parents[2] +DEFAULT_TARGETS = ( + REPO_ROOT / "app/src/main/java/br/com/drukstech/codeapp/ui/screens", + REPO_ROOT / "app/src/main/java/br/com/drukstech/codeapp/ui/components", +) +DEFAULT_ALLOWLIST = REPO_ROOT / ".github/scripts/ui_design_allowlist.txt" + + +@dataclass(frozen=True) +class Rule: + key: str + label: str + pattern: re.Pattern[str] + + +RULES = ( + Rule( + key="hardcoded_color", + label="Direct Color(0x...)", + pattern=re.compile(r"\bColor\s*\(\s*0x[0-9A-Fa-f_]+"), + ), + Rule( + key="raw_corner_shape", + label="Raw RoundedCornerShape(dp)", + pattern=re.compile(r"\bRoundedCornerShape\s*\(\s*\d+(?:\.\d+)?\.dp"), + ), + Rule( + key="raw_card", + label="Raw Card/ElevatedCard/OutlinedCard", + pattern=re.compile(r"(? list[Path]: + if target.is_file(): + return [target] + return sorted(target.rglob("*.kt")) + + +def resolve_target(target_text: str) -> Path: + target = Path(target_text) + if not target.is_absolute(): + target = REPO_ROOT / target + return target + + +def display_targets(targets: list[Path]) -> str: + labels = [] + for target in targets: + labels.append( + str(target.relative_to(REPO_ROOT)) + if target.is_relative_to(REPO_ROOT) + else str(target) + ) + return ", ".join(labels) + + +def strip_line_comment(line: str) -> str: + return line.split("//", 1)[0] + + +def audit_file(path: Path) -> dict[str, list[int]]: + findings: dict[str, list[int]] = defaultdict(list) + try: + lines = path.read_text(encoding="utf-8").splitlines() + except UnicodeDecodeError: + lines = path.read_text(errors="ignore").splitlines() + + for line_no, line in enumerate(lines, start=1): + candidate = strip_line_comment(line) + for rule in RULES: + if rule.pattern.search(candidate): + findings[rule.key].append(line_no) + return findings + + +def relative_repo_path(path: Path) -> str: + if path.is_relative_to(REPO_ROOT): + return path.relative_to(REPO_ROOT).as_posix() + return path.as_posix() + + +def load_allowlist(path: Path) -> dict[str, Counter[str]]: + allowlist: dict[str, Counter[str]] = defaultdict(Counter) + if not path.exists(): + return allowlist + + for line_no, raw_line in enumerate(path.read_text(encoding="utf-8").splitlines(), start=1): + line = raw_line.strip() + if not line or line.startswith("#"): + continue + parts = line.split("|") + if len(parts) != 3: + raise ValueError(f"Invalid allowlist line {line_no}: {raw_line}") + rel_path, rule_key, count_text = parts + if rule_key not in {rule.key for rule in RULES}: + raise ValueError(f"Unknown rule '{rule_key}' on allowlist line {line_no}") + try: + count = int(count_text) + except ValueError as exc: + raise ValueError(f"Invalid count '{count_text}' on allowlist line {line_no}") from exc + if count < 0: + raise ValueError(f"Negative count on allowlist line {line_no}") + allowlist[rel_path][rule_key] = count + return allowlist + + +def write_allowlist(path: Path, current_counts: dict[str, Counter[str]]) -> None: + lines = [ + "# DruksCode UI design-system historical debt baseline.", + "# Format: relative/path.kt|rule_key|allowed_count", + "# Regenerate only after intentionally accepting a new migration checkpoint.", + ] + for rel_path in sorted(current_counts): + counts = current_counts[rel_path] + for rule in RULES: + count = counts[rule.key] + if count > 0: + lines.append(f"{rel_path}|{rule.key}|{count}") + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text("\n".join(lines) + "\n", encoding="utf-8") + + +def find_baseline_violations( + current_counts: dict[str, Counter[str]], + allowlist: dict[str, Counter[str]], +) -> list[tuple[str, str, int, int]]: + violations: list[tuple[str, str, int, int]] = [] + for rel_path in sorted(current_counts): + counts = current_counts[rel_path] + allowed = allowlist.get(rel_path, Counter()) + for rule in RULES: + current = counts[rule.key] + baseline = allowed[rule.key] + if current > baseline: + violations.append((rel_path, rule.key, current, baseline)) + return violations + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "targets", + nargs="*", + help="Files or directories to scan. Defaults to app ui/screens and ui/components.", + ) + parser.add_argument( + "--fail-on-findings", + action="store_true", + help="Exit with status 1 if any finding is detected.", + ) + parser.add_argument( + "--enforce-baseline", + action="store_true", + help="Exit with status 1 only when current findings exceed the allowlist baseline.", + ) + parser.add_argument( + "--allowlist", + default=str(DEFAULT_ALLOWLIST), + help="Baseline allowlist file for --enforce-baseline.", + ) + parser.add_argument( + "--write-allowlist", + help="Write the current finding counts as an allowlist baseline.", + ) + parser.add_argument( + "--top", + type=int, + default=20, + help="Number of highest-debt files to print.", + ) + args = parser.parse_args() + + targets = [resolve_target(target) for target in args.targets] if args.targets else list(DEFAULT_TARGETS) + + files = sorted( + {file_path.resolve() for target in targets for file_path in iter_kotlin_files(target)} + ) + totals: Counter[str] = Counter() + per_file: list[tuple[Path, Counter[str], dict[str, list[int]]]] = [] + current_counts: dict[str, Counter[str]] = {} + + for file_path in files: + findings = audit_file(file_path) + counts = Counter({key: len(lines) for key, lines in findings.items()}) + if counts: + totals.update(counts) + per_file.append((file_path, counts, findings)) + current_counts[relative_repo_path(file_path)] = counts + + print("DruksCode UI design-system audit") + print(f"Targets: {display_targets(targets)}") + print(f"Files scanned: {len(files)}") + print() + + if args.write_allowlist: + write_path = Path(args.write_allowlist) + if not write_path.is_absolute(): + write_path = REPO_ROOT / write_path + write_allowlist(write_path, current_counts) + print(f"Allowlist written: {relative_repo_path(write_path)}") + print() + + if not totals: + print("No findings.") + return 0 + + print("Totals:") + for rule in RULES: + print(f" {rule.label}: {totals[rule.key]}") + + print() + print(f"Top {args.top} files:") + per_file.sort(key=lambda item: sum(item[1].values()), reverse=True) + for file_path, counts, findings in per_file[: args.top]: + rel = file_path.relative_to(REPO_ROOT) + total = sum(counts.values()) + detail = ", ".join( + f"{rule.key}={counts[rule.key]}" + for rule in RULES + if counts[rule.key] + ) + first_lines = [] + for rule in RULES: + lines = findings.get(rule.key) + if lines: + first_lines.append(f"{rule.key}@{','.join(map(str, lines[:5]))}") + print(f" {rel}: {total} ({detail})") + print(f" first: {'; '.join(first_lines)}") + + if args.enforce_baseline: + allowlist_path = Path(args.allowlist) + if not allowlist_path.is_absolute(): + allowlist_path = REPO_ROOT / allowlist_path + allowlist = load_allowlist(allowlist_path) + violations = find_baseline_violations(current_counts, allowlist) + print() + if violations: + print("Baseline enforcement failed:") + for rel_path, rule_key, current, baseline in violations[:50]: + print(f" {rel_path}|{rule_key}: current={current}, allowed={baseline}") + return 1 + print("Baseline enforcement passed.") + + return 1 if args.fail_on_findings else 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/.github/scripts/ci/generate_submissions.py b/.github/scripts/ci/generate_submissions.py new file mode 100644 index 0000000..0022967 --- /dev/null +++ b/.github/scripts/ci/generate_submissions.py @@ -0,0 +1,664 @@ +#!/usr/bin/env python3 +""" +Generate `modules/submissions.json` for the DruksCode Module Market. + +Why: the in-app market only renders modules that have a corresponding +submission entry in this file. The repository contract is that an entry +is published only when the module has actually landed on `main`, either +by a merged PR (the normal path) or by a maintainer direct push (rare, +used for seeding the initial example modules). + +This script is what enforces the "merged PRs only" promise. It walks +every module folder under `modules/`, asks `git log` for the commit that +introduced or last touched it, then queries the GitHub REST API for the +PR associated with that commit. If the PR is found and merged, we record +PR number, merge timestamp, and the merger's GitHub identity. If no PR +is found, the commit is taken as a direct push and we record the +commit's author timestamp and resolved GitHub login — any human author +is recorded (modules only reach `main` through review or a maintainer +push; hiding non-maintainer authors made real contributor modules +disappear from the in-app market). Only bot identities +(github-actions[bot], web-flow, dependabot[bot]) are excluded, with the +repo owner as the fallback when a commit email maps to no GitHub +account. An orphan folder added without a commit ends up unrecorded, +and the in-app market hides it. + +Run locally (no network access — uses cache only): + + python3 .github/scripts/ci/generate_submissions.py --offline + +Run in CI: + + python3 .github/scripts/ci/generate_submissions.py \\ + --owner shiaho777 --repo drukscode \\ + --maintainers shiaho777 \\ + --token "$GITHUB_TOKEN" + +Exit codes: + 0 = file was generated successfully (may have committed nothing if + nothing changed) + 1 = a fatal error occurred +""" + +from __future__ import annotations + +import argparse +import json +import os +import re +import subprocess +import sys +import urllib.error +import urllib.parse +import urllib.request +from dataclasses import dataclass, field +from datetime import datetime, timezone +from pathlib import Path +from typing import Any + + +REPO_ROOT = Path(__file__).resolve().parents[3] +MODULES_DIR = REPO_ROOT / "modules" +SUBMISSIONS_PATH = MODULES_DIR / "submissions.json" +REGISTRY_PATH = MODULES_DIR / "registry.json" + + +# ───────────────────────── git helpers ───────────────────────────────── + +def _git(*args: str) -> str: + """Run a git command relative to the repo root and return stdout.""" + result = subprocess.run( + ["git", *args], + cwd=str(REPO_ROOT), + check=True, + capture_output=True, + text=True, + ) + return result.stdout + + +def _last_commit_for(path: Path) -> str | None: + """Return the SHA of the most recent commit that touched `path`.""" + try: + out = _git("log", "-n", "1", "--format=%H", "--", str(path.relative_to(REPO_ROOT))) + sha = out.strip() + return sha or None + except subprocess.CalledProcessError: + return None + + +def _commit_metadata(sha: str) -> dict[str, str]: + """ + Fetch author name, email, ISO timestamp, and subject for a commit. + Used as a fallback when the GitHub API can't tell us about a PR. + """ + out = _git("show", "-s", "--format=%an%n%ae%n%aI%n%s", sha) + parts = out.splitlines() + return { + "author_name": parts[0] if len(parts) > 0 else "", + "author_email": parts[1] if len(parts) > 1 else "", + "author_date": parts[2] if len(parts) > 2 else "", + "subject": parts[3] if len(parts) > 3 else "", + } + + + + +_PR_REF_RE = re.compile(r"(?:\(|\s)#(\d+)(?:\)|\b)") + + +def _pr_numbers_from_text(*texts: str) -> list[int]: + """Extract GitHub PR numbers mentioned in commit subjects / bodies.""" + found: list[int] = [] + seen: set[int] = set() + for text in texts: + if not text: + continue + for match in _PR_REF_RE.finditer(text): + num = int(match.group(1)) + if num not in seen: + seen.add(num) + found.append(num) + return found + + +def _all_commits_for(path: Path) -> list[str]: + """Return every commit SHA that touched `path`, newest first.""" + try: + out = _git("log", "--format=%H", "--", str(path.relative_to(REPO_ROOT))) + return [line.strip() for line in out.splitlines() if line.strip()] + except subprocess.CalledProcessError: + return [] + + +# ───────────────────────── GitHub API helpers ────────────────────────── + +@dataclass +class GitHubClient: + """Tiny GitHub REST client that uses urllib so we stay stdlib-only.""" + + owner: str + repo: str + token: str | None = None + timeout: int = 15 + + def _request(self, url: str) -> Any: + headers = { + "Accept": "application/vnd.github+json", + "User-Agent": "webtoapp-submissions-generator", + "X-GitHub-Api-Version": "2022-11-28", + } + if self.token: + headers["Authorization"] = f"Bearer {self.token}" + req = urllib.request.Request(url, headers=headers) + with urllib.request.urlopen(req, timeout=self.timeout) as resp: + return json.loads(resp.read().decode("utf-8")) + + def pulls_for_commit(self, sha: str) -> list[dict[str, Any]]: + """Return PRs associated with the given commit SHA.""" + url = ( + f"https://api.github.com/repos/{self.owner}/{self.repo}" + f"/commits/{sha}/pulls" + ) + try: + return self._request(url) or [] + except urllib.error.HTTPError as e: + # 404 just means no PR was associated with this commit, which + # is the normal case for a maintainer direct-push. Anything + # else is worth a note in the log. + if e.code == 404: + return [] + print(f"⚠️ GitHub API error for commit {sha[:7]}: {e}", file=sys.stderr) + return [] + except urllib.error.URLError as e: + print(f"⚠️ GitHub API URLError for commit {sha[:7]}: {e}", file=sys.stderr) + return [] + + def user(self, login: str) -> dict[str, Any] | None: + """Resolve a GitHub login to its display name / avatar URL.""" + url = f"https://api.github.com/users/{urllib.parse.quote(login)}" + try: + return self._request(url) + except urllib.error.HTTPError: + return None + except urllib.error.URLError: + return None + + def commit_author_login(self, sha: str) -> str: + """Resolve the GitHub login of a commit's author via the commit API.""" + url = f"https://api.github.com/repos/{self.owner}/{self.repo}/commits/{sha}" + try: + commit_info = self._request(url) + author = commit_info.get("author") or {} + return author.get("login") or "" + except (urllib.error.HTTPError, urllib.error.URLError): + return "" + + def get_pull(self, number: int) -> dict[str, Any] | None: + """Fetch a single pull request by number.""" + url = ( + f"https://api.github.com/repos/{self.owner}/{self.repo}" + f"/pulls/{int(number)}" + ) + try: + return self._request(url) + except urllib.error.HTTPError as e: + if e.code != 404: + print(f"⚠️ GitHub API error for PR #{number}: {e}", file=sys.stderr) + return None + except urllib.error.URLError as e: + print(f"⚠️ GitHub API URLError for PR #{number}: {e}", file=sys.stderr) + return None + + +# ───────────────────────── core logic ────────────────────────────────── + +@dataclass +class Contributor: + """A secondary contributor to a module (everyone except the original submitter).""" + + login: str = "" + name: str = "" + avatar: str = "" + profile: str = "" + + def to_json(self) -> dict[str, str]: + out: dict[str, str] = {} + if self.login: + out["login"] = self.login + if self.name: + out["name"] = self.name + if self.avatar: + out["avatarUrl"] = self.avatar + if self.profile: + out["profileUrl"] = self.profile + return out + + +@dataclass +class Submission: + """In-memory representation of a single `submissions.json` entry.""" + + pr_number: int | None = None + pr_url: str | None = None + submitted_at: str | None = None + direct: bool = False + submitter_login: str = "" + submitter_name: str = "" + submitter_avatar: str = "" + submitter_profile: str = "" + contributors: list[Contributor] = field(default_factory=list) + + def to_json(self) -> dict[str, Any]: + out: dict[str, Any] = {} + if self.pr_number is not None: + out["prNumber"] = self.pr_number + if self.pr_url: + out["prUrl"] = self.pr_url + if self.submitted_at: + out["submittedAt"] = self.submitted_at + if self.direct: + out["direct"] = True + submitter: dict[str, str] = {} + if self.submitter_login: + submitter["login"] = self.submitter_login + if self.submitter_name: + submitter["name"] = self.submitter_name + if self.submitter_avatar: + submitter["avatarUrl"] = self.submitter_avatar + if self.submitter_profile: + submitter["profileUrl"] = self.submitter_profile + if submitter: + out["submitter"] = submitter + if self.contributors: + out["contributors"] = [c.to_json() for c in self.contributors if c.login] + return out + + +def _read_existing_submissions() -> dict[str, Any]: + """Read the previous run's output so unchanged modules don't re-fetch.""" + if not SUBMISSIONS_PATH.is_file(): + return {} + try: + data = json.loads(SUBMISSIONS_PATH.read_text(encoding="utf-8")) + return data.get("submissions") or {} + except (json.JSONDecodeError, OSError): + return {} + + +def _read_registry() -> list[dict[str, Any]]: + """Read the registry to know which `id` ↔ `path` pairs to attribute.""" + if not REGISTRY_PATH.is_file(): + return [] + try: + data = json.loads(REGISTRY_PATH.read_text(encoding="utf-8")) + modules = data.get("modules") + if isinstance(modules, list): + return [m for m in modules if isinstance(m, dict)] + except (json.JSONDecodeError, OSError): + pass + return [] + + +def _resolve_for_path( + module_path: Path, + client: GitHubClient | None, + maintainers: set[str], + cache: dict[str, Any], +) -> Submission | None: + """Build a Submission for the module folder at `module_path`.""" + + sha = _last_commit_for(module_path) + if sha is None: + return None + + # We attribute to the *introducing* commit when possible — that's the + # one that landed the module on main. The simplest proxy in `git log` + # is the oldest commit that touched the folder. + introducing_sha: str | None = None + try: + out = _git( + "log", + "--diff-filter=A", + "--format=%H", + "--", + str(module_path.relative_to(REPO_ROOT) / "module.json"), + ) + intro_lines = [line.strip() for line in out.splitlines() if line.strip()] + if intro_lines: + introducing_sha = intro_lines[-1] + except subprocess.CalledProcessError: + pass + target_sha = introducing_sha or sha + + # In offline mode, fall back to git metadata only. + if client is None: + meta = _commit_metadata(target_sha) + # We still gate maintainer direct-pushes by the configured allowlist, + # so a stranger committing directly without a PR isn't silently + # promoted into the catalog. + login = "" # unknown without GitHub API + if not login and not maintainers: + return None + return Submission( + direct=True, + submitted_at=meta["author_date"], + submitter_login=meta["author_name"], + submitter_name=meta["author_name"], + ) + + meta = _commit_metadata(target_sha) + pulls = client.pulls_for_commit(target_sha) + + # Squash / rebase merges often leave commits/{sha}/pulls empty even though + # the subject carries "(#123)". Fall back to parsing PR refs from git + # metadata and fetching those PRs directly. + if not pulls: + for pr_number in _pr_numbers_from_text(meta.get("subject", "")): + pr_payload = client.get_pull(pr_number) + if pr_payload: + pulls.append(pr_payload) + + merged_pulls = [p for p in pulls if p.get("merged_at")] + merged_on_main = [ + p for p in merged_pulls + if (p.get("base") or {}).get("ref", "main") == "main" + ] + if merged_on_main: + merged_pulls = merged_on_main + + if merged_pulls: + # Prefer the earliest-merged PR — that is the one that introduced + # the module to main. Subsequent updates also produce PRs but they + # are version bumps, not the original submission. + pr = sorted(merged_pulls, key=lambda p: p.get("merged_at", ""))[0] + author = pr.get("user") or {} + login = author.get("login") or "" + avatar = author.get("avatar_url") or "" + profile = author.get("html_url") or ( + f"https://github.com/{login}" if login else "" + ) + + # The PR payload doesn't always carry the user's display name; fetch + # it lazily and cache so we don't repeat the call for the same login. + display_name = "" + if login: + cached = cache.setdefault("users", {}).get(login) + if cached is None: + resolved = client.user(login) + cached = { + "name": (resolved or {}).get("name") or login, + "avatar": (resolved or {}).get("avatar_url") or avatar, + } + cache["users"][login] = cached + display_name = cached.get("name") or login + avatar = cached.get("avatar") or avatar + + return Submission( + pr_number=pr.get("number"), + pr_url=pr.get("html_url"), + submitted_at=pr.get("merged_at"), + direct=False, + submitter_login=login, + submitter_name=display_name, + submitter_avatar=avatar, + submitter_profile=profile, + ) + + # No merged PR was found. This is a direct push to main. The main branch + # is branch-protected, so a direct push has already been authorised by a + # maintainer (or admin) — we trust that gate rather than re-checking the + # GitHub login, which is unreliable for commits whose author email isn't + # linked to a GitHub account (the API returns `author: null` and we'd + # silently hide legitimate maintainer pushes). + meta = _commit_metadata(target_sha) + # Try to resolve the GitHub login from the commit's email when possible. + # `git log` doesn't carry the GitHub login, so we look it up by querying + # the commit endpoint, which embeds the GH author when GitHub knows them. + login = "" + try: + url = f"https://api.github.com/repos/{client.owner}/{client.repo}/commits/{target_sha}" + commit_info = client._request(url) + author = commit_info.get("author") or {} + login = author.get("login") or "" + except (urllib.error.HTTPError, urllib.error.URLError): + pass + + if not login: + # Commit email isn't linked to a GitHub account, so the API can't + # tell us who authored it. The push already cleared branch + # protection, so attribute it to the repo owner as a fallback. + login = client.owner + + # Prefer PR attribution above. For true direct pushes we still record + # any resolved GitHub author — modules only land on main after review + # or maintainer push, so hiding non-maintainer authors made real + # contributor modules disappear from the in-app market. + if ( + maintainers + and login + and login.lower() not in {m.lower() for m in maintainers} + and login.lower() in {"github-actions[bot]", "web-flow", "dependabot[bot]"} + ): + return None + + avatar = "" + profile = "" + display_name = login or meta["author_name"] + if login: + cached = cache.setdefault("users", {}).get(login) + if cached is None: + resolved = client.user(login) + cached = { + "name": (resolved or {}).get("name") or login, + "avatar": (resolved or {}).get("avatar_url") or "", + "profile": (resolved or {}).get("html_url") or f"https://github.com/{login}", + } + cache["users"][login] = cached + display_name = cached.get("name") or login + avatar = cached.get("avatar") or "" + profile = cached.get("profile") or f"https://github.com/{login}" + + return Submission( + direct=True, + submitted_at=meta["author_date"], + submitter_login=login, + submitter_name=display_name, + submitter_avatar=avatar, + submitter_profile=profile, + ) + + +def _resolve_contributors( + module_path: Path, + submitter_login: str, + client: GitHubClient | None, + cache: dict[str, Any], +) -> list[Contributor]: + """ + Collect secondary contributors for a module folder. + + Walks every commit that touched the folder, resolves each distinct + author's GitHub login via the commit API, and returns everyone except + the original submitter (and bots/github-actions). Offline mode and + unresolvable logins yield an empty list — contributors are a + best-effort enrichment, never a hard requirement. + """ + if client is None: + return [] + + shas = _all_commits_for(module_path) + seen_logins: set[str] = set() + if submitter_login: + seen_logins.add(submitter_login.lower()) + seen_logins.add("github-actions[bot]") + seen_logins.add("web-flow") + + contributors: list[Contributor] = [] + users = cache.setdefault("users", {}) + for sha in shas: + login = client.commit_author_login(sha) + if not login or login.lower() in seen_logins: + continue + seen_logins.add(login.lower()) + + cached = users.get(login) + if cached is None: + resolved = client.user(login) + cached = { + "name": (resolved or {}).get("name") or login, + "avatar": (resolved or {}).get("avatar_url") or "", + "profile": (resolved or {}).get("html_url") or f"https://github.com/{login}", + } + users[login] = cached + + contributors.append(Contributor( + login=login, + name=cached.get("name") or login, + avatar=cached.get("avatar") or "", + profile=cached.get("profile") or f"https://github.com/{login}", + )) + + return contributors + + +# ───────────────────────── CLI entry ─────────────────────────────────── + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__.split("\n\n", 1)[0]) + parser.add_argument("--owner", default=os.environ.get("REPO_OWNER", "shiaho777")) + parser.add_argument("--repo", default=os.environ.get("REPO_NAME", "drukscode")) + parser.add_argument("--token", default=os.environ.get("GITHUB_TOKEN")) + parser.add_argument( + "--maintainers", + default=os.environ.get("MAINTAINERS", ""), + help=( + "Comma-separated GitHub logins allowed to seed modules via " + "direct push (no PR). Anything else without a merged PR is " + "deliberately hidden from the catalog." + ), + ) + parser.add_argument( + "--offline", + action="store_true", + help=( + "Skip the GitHub API entirely; useful for smoke-testing the " + "script locally. Falls back to git metadata only." + ), + ) + parser.add_argument( + "--check", + action="store_true", + help=( + "Generate to a temp file and exit with code 1 if the result " + "differs from the committed file. Used as a guard rail in CI " + "for PRs that touch modules/." + ), + ) + args = parser.parse_args() + + if not MODULES_DIR.is_dir(): + print(f"❌ {MODULES_DIR} does not exist", file=sys.stderr) + return 1 + + maintainers: set[str] = { + m.strip() for m in args.maintainers.split(",") if m.strip() + } + + client: GitHubClient | None + if args.offline: + client = None + else: + client = GitHubClient(owner=args.owner, repo=args.repo, token=args.token) + + registry = _read_registry() + # Map registry path → id so we attribute each folder to its catalog id. + path_to_id: dict[str, str] = {} + for entry in registry: + p = entry.get("path") + i = entry.get("id") + if isinstance(p, str) and isinstance(i, str): + path_to_id[p] = i + + # Walk every kebab-case folder; the validator already ensures the layout. + folders = sorted( + p for p in MODULES_DIR.iterdir() + if p.is_dir() and not p.name.startswith(".") + ) + + cache: dict[str, Any] = {} + submissions: dict[str, Any] = {} + skipped: list[str] = [] + for folder in folders: + module_id = path_to_id.get(folder.name) + if not module_id: + # Folder without a registry entry — the validator will already + # be screaming about this; we just skip it. + skipped.append(folder.name) + continue + submission = _resolve_for_path(folder, client, maintainers, cache) + if submission is None: + # Hidden by design: no merged PR and not a maintainer direct + # push. Surface this in the log so reviewers can tell what's + # going on. + skipped.append(folder.name) + continue + submission.contributors = _resolve_contributors( + folder, submission.submitter_login, client, cache + ) + submissions[module_id] = submission.to_json() + + output = { + "schema": 1, + "submissions": submissions, + } + + if not args.check: + existing_text = SUBMISSIONS_PATH.read_text(encoding="utf-8") if SUBMISSIONS_PATH.is_file() else "" + try: + existing_obj = json.loads(existing_text) if existing_text else {} + except json.JSONDecodeError: + existing_obj = {} + existing_subs = existing_obj.get("submissions") or {} + if existing_subs == submissions and "generatedAt" in existing_obj: + output["generatedAt"] = existing_obj["generatedAt"] + else: + output["generatedAt"] = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") + else: + output["generatedAt"] = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") + + ordered = { + "schema": output["schema"], + "generatedAt": output["generatedAt"], + "submissions": output["submissions"], + } + serialised = json.dumps(ordered, indent=2, ensure_ascii=False) + "\n" + + if args.check: + # Diff against the committed file. We tolerate a missing file by + # treating it as empty. `generatedAt` is excluded from the diff + # so check mode is deterministic. + existing_text = SUBMISSIONS_PATH.read_text(encoding="utf-8") if SUBMISSIONS_PATH.is_file() else "" + try: + existing_obj = json.loads(existing_text) if existing_text else {} + except json.JSONDecodeError: + existing_obj = {} + + existing_subs = existing_obj.get("submissions") or {} + if existing_subs == submissions: + print(f"✅ submissions.json is up to date ({len(submissions)} entries)") + if skipped: + print(f" ({len(skipped)} folder(s) hidden from catalog: {', '.join(skipped)})") + return 0 + print("❌ submissions.json is stale — re-run generate_submissions.py and commit the result.", file=sys.stderr) + return 1 + + SUBMISSIONS_PATH.write_text(serialised, encoding="utf-8") + print(f"✅ Wrote {SUBMISSIONS_PATH.relative_to(REPO_ROOT)} with {len(submissions)} entries") + if skipped: + print(f" ({len(skipped)} folder(s) hidden from catalog: {', '.join(skipped)})") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/.github/scripts/ci/validate_modules.py b/.github/scripts/ci/validate_modules.py new file mode 100755 index 0000000..f5d9011 --- /dev/null +++ b/.github/scripts/ci/validate_modules.py @@ -0,0 +1,671 @@ +#!/usr/bin/env python3 +""" +Validate the DruksCode Module Market catalog at `modules/`. + +This is the source of truth for what `modules/README.md` claims gets +checked at CI time. Every rule here corresponds to a real failure mode +that would either reject a module at install time or quietly waste space +on disk. + +The validator is intentionally written with only Python's standard +library — no pip install step, no extra container — so the CI job stays +fast and deterministic. + +Run locally: + + python3 .github/scripts/ci/validate_modules.py + +Exit codes: + 0 = catalog is valid + 1 = at least one error was found (CI fails) +""" + +from __future__ import annotations + +import json +import os +import re +import sys +from dataclasses import dataclass, field +from pathlib import Path +from typing import Any, Iterable + + +# ───────────────────────── enum values (must mirror the Kotlin source) ─ + +# `ModuleCategory` enum in `core/extension/ExtensionModule.kt`. +ALLOWED_CATEGORIES: set[str] = { + "CONTENT_FILTER", "CONTENT_ENHANCE", "STYLE_MODIFIER", "THEME", + "FUNCTION_ENHANCE", "AUTOMATION", "NAVIGATION", "DATA_EXTRACT", + "DATA_SAVE", "INTERACTION", "ACCESSIBILITY", "MEDIA", "VIDEO", + "IMAGE", "AUDIO", "SECURITY", "ANTI_TRACKING", "SOCIAL", "SHOPPING", + "READING", "TRANSLATE", "DEVELOPER", "OTHER", +} + +# `ModuleRunTime` enum. +ALLOWED_RUN_AT: set[str] = { + "DOCUMENT_START", "DOCUMENT_END", "DOCUMENT_IDLE", + "CONTEXT_MENU", "BEFORE_UNLOAD", +} + +# `ModulePermission` enum. +ALLOWED_PERMISSIONS: set[str] = { + "DOM_ACCESS", "DOM_OBSERVE", "CSS_INJECT", "STORAGE", "COOKIE", + "INDEXED_DB", "CACHE", "NETWORK", "WEBSOCKET", "FETCH_INTERCEPT", + "CLIPBOARD", "NOTIFICATION", "ALERT", "KEYBOARD", "MOUSE", "TOUCH", + "LOCATION", "CAMERA", "MICROPHONE", "DEVICE_INFO", "MEDIA", + "FULLSCREEN", "PICTURE_IN_PICTURE", "SCREEN_CAPTURE", "DOWNLOAD", + "FILE_ACCESS", "EVAL", "IFRAME", "WINDOW_OPEN", "HISTORY", + "NAVIGATION", +} + +# `ConfigItemType` enum. +ALLOWED_CONFIG_TYPES: set[str] = { + "TEXT", "TEXTAREA", "NUMBER", "BOOLEAN", "SELECT", "MULTI_SELECT", + "RADIO", "CHECKBOX", "COLOR", "URL", "EMAIL", "PASSWORD", "REGEX", + "CSS_SELECTOR", "JAVASCRIPT", "JSON", "RANGE", "DATE", "TIME", + "DATETIME", "FILE", "IMAGE", +} + +ALLOWED_SOURCE_TYPES: set[str] = {"CUSTOM", "CHROME_EXTENSION"} +STORE_ID_RE = re.compile(r"^[a-p]{32}$") + + +# ───────────────────────── regex helpers ─────────────────────────────── + +KEBAB_CASE_RE = re.compile(r"^[a-z0-9]+(?:-[a-z0-9]+)*$") +SEMVER_RE = re.compile(r"^\d+(?:\.\d+){0,3}(?:[-+][\w.-]+)?$") + +# Files we let people drop in besides the three the runtime actually +# downloads (module.json, main.js, style.css). +ALLOWED_EXTRA_FILES: set[str] = { + "README.md", # nice for module pages on GitHub + "CHANGELOG.md", + "LICENSE", + "LICENSE.md", + ".gitkeep", +} + +# Image files contributors may drop next to `main.js` for use as the +# module icon. The CI generator does not download these — they are served +# via the same GitHub raw / jsDelivr fallback the runtime already uses. +ALLOWED_ICON_FILES: set[str] = { + "icon.png", "icon.svg", "icon.webp", "icon.jpg", "icon.jpeg", +} + +# Maximum size for an inlined icon. Larger icons should be hosted off-repo +# and referenced via an absolute `iconUrl`. 256 KB is a forgiving limit: +# a 256x256 PNG with reasonable compression sits comfortably below it. +MAX_ICON_BYTES = 256 * 1024 + + +@dataclass +class Report: + """Accumulates diagnostics and pretty-prints them at the end.""" + + errors: list[str] = field(default_factory=list) + warnings: list[str] = field(default_factory=list) + + def error(self, where: str, message: str) -> None: + self.errors.append(f" ❌ {where}: {message}") + + def warning(self, where: str, message: str) -> None: + self.warnings.append(f" ⚠️ {where}: {message}") + + def ok(self) -> bool: + return not self.errors + + def render(self) -> str: + lines: list[str] = [] + if self.errors: + lines.append(f"\n{len(self.errors)} error(s):") + lines.extend(self.errors) + if self.warnings: + lines.append(f"\n{len(self.warnings)} warning(s):") + lines.extend(self.warnings) + if not lines: + lines.append("\nAll module checks passed.") + return "\n".join(lines) + + +# ───────────────────────── primitive checks ──────────────────────────── + +def _is_str(value: Any) -> bool: + return isinstance(value, str) + + +def _expect_str(report: Report, where: str, value: Any, field: str) -> str | None: + if value is None: + return None + if not _is_str(value): + report.error(where, f"`{field}` must be a string, got {type(value).__name__}") + return None + return value + + +def _expect_list_of_str(report: Report, where: str, value: Any, field: str) -> list[str]: + if value is None: + return [] + if not isinstance(value, list) or any(not _is_str(v) for v in value): + report.error(where, f"`{field}` must be a list of strings") + return [] + return value + + +def _validate_url_matches( + report: Report, where: str, url_matches: Any +) -> None: + if url_matches is None: + return + if not isinstance(url_matches, list): + report.error(where, "`urlMatches` must be a list") + return + for i, rule in enumerate(url_matches): + rule_loc = f"{where}::urlMatches[{i}]" + if not isinstance(rule, dict): + report.error(rule_loc, "must be an object with at least `pattern`") + continue + pattern = rule.get("pattern") + if not _is_str(pattern) or not pattern: + report.error(rule_loc, "`pattern` is required and must be a non-empty string") + for flag in ("isRegex", "exclude"): + if flag in rule and not isinstance(rule[flag], bool): + report.error(rule_loc, f"`{flag}` must be a boolean") + + +def _validate_author(report: Report, where: str, author: Any) -> None: + if author is None: + return + if not isinstance(author, dict): + report.error(where, "`author` must be an object") + return + name = author.get("name") + if not _is_str(name) or not name.strip(): + report.error(where, "`author.name` is required") + for opt_key in ("email", "url", "qq"): + if opt_key in author and author[opt_key] is not None and not _is_str(author[opt_key]): + report.error(where, f"`author.{opt_key}` must be a string") + + +# ───────────────────────── manifest checks ───────────────────────────── + +def _validate_module_json( + report: Report, folder: Path, manifest: dict[str, Any] +) -> None: + """Validate a per-module `module.json`.""" + + where = f"modules/{folder.name}/module.json" + + # Required fields. + if not _is_str(manifest.get("id")) or not manifest["id"].strip(): + report.error(where, "`id` is required and must be a non-empty string") + if not _is_str(manifest.get("name")) or not manifest["name"].strip(): + report.error(where, "`name` is required and must be a non-empty string") + + # Enums (with a friendly hint when wrong). + category = manifest.get("category", "OTHER") + if not _is_str(category) or category not in ALLOWED_CATEGORIES: + report.error( + where, + f"`category` must be one of {sorted(ALLOWED_CATEGORIES)}, got {category!r}", + ) + + run_at = manifest.get("runAt", "DOCUMENT_END") + if not _is_str(run_at) or run_at not in ALLOWED_RUN_AT: + report.error( + where, + f"`runAt` must be one of {sorted(ALLOWED_RUN_AT)}, got {run_at!r}", + ) + + # Version (object form). + version = manifest.get("version") + if version is None: + report.error(where, "`version` is required (object with `code`, `name`, `changelog`)") + elif not isinstance(version, dict): + report.error(where, "`version` must be an object — see modules/README.md schema") + else: + v_code = version.get("code") + if not isinstance(v_code, int) or v_code < 1: + report.error(where, "`version.code` must be a positive integer") + v_name = version.get("name") + if not _is_str(v_name) or not SEMVER_RE.match(v_name or ""): + report.error(where, f"`version.name` must be semver-shaped, got {v_name!r}") + if "changelog" in version and version["changelog"] is not None and not _is_str(version["changelog"]): + report.error(where, "`version.changelog` must be a string") + + # Permissions. + for perm in _expect_list_of_str(report, where, manifest.get("permissions"), "permissions"): + if perm not in ALLOWED_PERMISSIONS: + report.error(where, f"unknown permission {perm!r}") + + # urlMatches and author. + _validate_url_matches(report, where, manifest.get("urlMatches")) + _validate_author(report, where, manifest.get("author")) + + # configItems. + config_items = manifest.get("configItems", []) + if config_items is None: + config_items = [] + if not isinstance(config_items, list): + report.error(where, "`configItems` must be a list") + return + seen_keys: set[str] = set() + for i, item in enumerate(config_items): + item_loc = f"{where}::configItems[{i}]" + if not isinstance(item, dict): + report.error(item_loc, "must be an object") + continue + key = item.get("key") + if not _is_str(key) or not key.strip(): + report.error(item_loc, "`key` is required") + elif key in seen_keys: + report.error(item_loc, f"duplicate key {key!r}") + else: + seen_keys.add(key) + + if not _is_str(item.get("name")) or not item["name"].strip(): + report.error(item_loc, "`name` is required") + + type_ = item.get("type", "TEXT") + if not _is_str(type_) or type_ not in ALLOWED_CONFIG_TYPES: + report.error(item_loc, f"`type` must be one of {sorted(ALLOWED_CONFIG_TYPES)}") + + if "required" in item and not isinstance(item["required"], bool): + report.error(item_loc, "`required` must be a boolean") + + for str_field in ("description", "defaultValue", "placeholder", "validation"): + if str_field in item and item[str_field] is not None and not _is_str(item[str_field]): + report.error(item_loc, f"`{str_field}` must be a string") + + # SELECT / MULTI_SELECT / RADIO need `options`. + if type_ in {"SELECT", "MULTI_SELECT", "RADIO"}: + options = item.get("options") + if not isinstance(options, list) or not options: + report.error(item_loc, f"`options` is required for type {type_}") + elif not all(_is_str(o) for o in options): + report.error(item_loc, f"`options` for type {type_} must be a list of strings; the app parses ModuleConfigItem.options as List, so object forms like [{{\"value\",\"label\"}}] fail Gson deserialization") + + +# ───────────────────────── registry checks ───────────────────────────── + +def _validate_registry_entry( + report: Report, entry: dict[str, Any], index: int +) -> None: + where = f"registry.json::modules[{index}]" + + for required in ("id", "path", "name"): + if not _is_str(entry.get(required)) or not entry[required].strip(): + report.error(where, f"`{required}` is required and must be a non-empty string") + + path = entry.get("path", "") + if _is_str(path) and not KEBAB_CASE_RE.match(path): + report.error(where, f"`path` must be kebab-case, got {path!r}") + + version = entry.get("version") + if not _is_str(version) or not SEMVER_RE.match(version or ""): + report.error(where, f"`version` must be a semver string, got {version!r}") + + category = entry.get("category", "OTHER") + if not _is_str(category) or category not in ALLOWED_CATEGORIES: + report.error(where, f"`category` must be one of the allowed values, got {category!r}") + + run_at = entry.get("runAt", "DOCUMENT_END") + if not _is_str(run_at) or run_at not in ALLOWED_RUN_AT: + report.error(where, f"`runAt` must be one of the allowed values, got {run_at!r}") + + for perm in _expect_list_of_str(report, where, entry.get("permissions"), "permissions"): + if perm not in ALLOWED_PERMISSIONS: + report.error(where, f"unknown permission {perm!r}") + + _validate_url_matches(report, where, entry.get("urlMatches")) + _validate_author(report, where, entry.get("author")) + + if "minAppVersion" in entry and not isinstance(entry["minAppVersion"], int): + report.error(where, "`minAppVersion` must be an integer") + + if "hasCss" in entry and not isinstance(entry["hasCss"], bool): + report.error(where, "`hasCss` must be a boolean") + + icon_url = entry.get("iconUrl") + if icon_url is not None and not _is_str(icon_url): + report.error(where, "`iconUrl` must be a string when present") + + source_type = entry.get("sourceType", "CUSTOM") + if not _is_str(source_type) or source_type not in ALLOWED_SOURCE_TYPES: + report.error(where, f"`sourceType` must be one of {sorted(ALLOWED_SOURCE_TYPES)}, got {source_type!r}") + + if source_type == "CHROME_EXTENSION": + store_id = entry.get("storeId") + if not _is_str(store_id) or not STORE_ID_RE.match(store_id or ""): + report.error(where, "`storeId` is required for CHROME_EXTENSION and must be a 32-char Chrome Web Store ID") + + +def _validate_registry(report: Report, registry: dict[str, Any]) -> list[dict[str, Any]]: + where = "registry.json" + schema = registry.get("schema") + if schema != 1: + report.error(where, f"`schema` must be 1 (got {schema!r}); future versions need a parser update") + if "updatedAt" in registry and not _is_str(registry["updatedAt"]): + report.error(where, "`updatedAt` must be a string") + + modules = registry.get("modules") + if not isinstance(modules, list): + report.error(where, "`modules` must be a list") + return [] + + seen_ids: set[str] = set() + seen_paths: set[str] = set() + for i, entry in enumerate(modules): + if not isinstance(entry, dict): + report.error(f"{where}::modules[{i}]", "must be an object") + continue + _validate_registry_entry(report, entry, i) + + eid = entry.get("id") if _is_str(entry.get("id")) else None + if eid: + if eid in seen_ids: + report.error(f"{where}::modules[{i}]", f"duplicate id {eid!r}") + if not KEBAB_CASE_RE.match(eid): + report.error(f"{where}::modules[{i}]", f"id {eid!r} must be kebab-case") + seen_ids.add(eid) + + epath = entry.get("path") if _is_str(entry.get("path")) else None + if epath: + if epath in seen_paths: + report.error(f"{where}::modules[{i}]", f"duplicate path {epath!r}") + seen_paths.add(epath) + + return [m for m in modules if isinstance(m, dict)] + + +# ───────────────────────── cross-file consistency ───────────────────── + +def _validate_cross_consistency( + report: Report, + entry: dict[str, Any], + manifest: dict[str, Any], + folder: Path, +) -> None: + """`module.json` and `registry.json` must agree on the shared fields.""" + + where = f"modules/{folder.name}" + + # id + if entry.get("id") != manifest.get("id"): + report.error( + where, + f"`id` mismatch: registry says {entry.get('id')!r}, manifest says {manifest.get('id')!r}", + ) + + # name + if entry.get("name") != manifest.get("name"): + report.error( + where, + f"`name` mismatch: registry says {entry.get('name')!r}, manifest says {manifest.get('name')!r}", + ) + + # version: registry stores the string, manifest stores an object. + reg_version = entry.get("version") + man_version_obj = manifest.get("version") or {} + man_version = man_version_obj.get("name") if isinstance(man_version_obj, dict) else None + if reg_version != man_version: + report.error( + where, + f"`version` mismatch: registry={reg_version!r}, module.json::version.name={man_version!r}", + ) + + # runAt + if entry.get("runAt") and manifest.get("runAt") and entry["runAt"] != manifest["runAt"]: + report.error( + where, + f"`runAt` mismatch: registry={entry['runAt']!r}, manifest={manifest['runAt']!r}", + ) + + # permissions: registry should be a superset (the listing surface) of manifest. + reg_perms = set(entry.get("permissions") or []) + man_perms = set(manifest.get("permissions") or []) + missing_in_registry = man_perms - reg_perms + if missing_in_registry: + report.error( + where, + f"manifest declares permissions {sorted(missing_in_registry)} that registry.json does not list", + ) + + # hasCss must match style.css presence on disk. + has_css_flag = bool(entry.get("hasCss")) + style_present = (folder / "style.css").is_file() + if has_css_flag and not style_present: + report.error( + where, + "registry says `hasCss: true` but no `style.css` file is present", + ) + if style_present and not has_css_flag: + report.error( + where, + "`style.css` exists but registry has `hasCss: false` — it will not be downloaded", + ) + + +# ───────────────────────── per-folder structural checks ─────────────── + +def _validate_folder_layout(report: Report, folder: Path) -> None: + """Each module folder must look like the schema says it does.""" + + where = f"modules/{folder.name}" + + if not KEBAB_CASE_RE.match(folder.name): + report.error(where, f"folder name must be kebab-case, got {folder.name!r}") + + if not (folder / "module.json").is_file(): + report.error(where, "missing required `module.json`") + + if not (folder / "main.js").is_file(): + report.error(where, "missing required `main.js`") + + # Flag stray files. The runtime ignores them, so they only bloat the repo. + expected = {"module.json", "main.js", "style.css"} + for child in folder.iterdir(): + if child.name in expected or child.name in ALLOWED_EXTRA_FILES: + continue + if child.name in ALLOWED_ICON_FILES: + # Icons are size-checked separately further below. + continue + if child.is_dir(): + report.warning( + where, + f"unexpected sub-directory `{child.name}/` — the runtime won't read it", + ) + else: + report.warning( + where, + f"unexpected file `{child.name}` — the runtime won't download it", + ) + + +def _validate_icon_coherence( + report: Report, folder: Path, entry: dict[str, Any] | None +) -> None: + """ + Cross-check the contributor-supplied icon against the registry. + + The contract: + + - If `iconUrl` is missing/empty, the app falls back to the first letter + of the module name. No icon file is needed. + - If `iconUrl` looks like a relative path, the corresponding file must + actually exist next to `main.js` and stay within the size budget. + - If `iconUrl` is absolute (starts with `http://` or `https://`), we + defer to the contributor's hosting and do not check the file system. + - The file name must come from `ALLOWED_ICON_FILES` so we don't end up + shipping random binaries through the catalog. + """ + where = f"modules/{folder.name}" + icon_url = (entry or {}).get("iconUrl") + + icon_files_present = sorted( + f for f in ALLOWED_ICON_FILES if (folder / f).is_file() + ) + + # Warn about extra random icon files when the registry doesn't reference + # them — the runtime won't fetch a `logo.png` it has no way to know about. + if not icon_url and icon_files_present: + report.warning( + where, + f"icon file(s) {icon_files_present} present but registry has no " + "`iconUrl` — they won't be used by the runtime", + ) + + if not _is_str(icon_url) or not icon_url.strip(): + return + + icon_url = icon_url.strip() + if icon_url.startswith("http://") or icon_url.startswith("https://"): + if icon_url.startswith("http://"): + report.warning(where, "`iconUrl` uses http://; prefer https for catalog assets") + return + + # Relative path case. Reject path traversal and force the file to live + # inside the module folder with a known extension. + normalised = icon_url.lstrip("./") + if normalised.startswith("/") or ".." in normalised.split("/"): + report.error(where, f"`iconUrl` must be a path inside the module folder, got {icon_url!r}") + return + if normalised not in ALLOWED_ICON_FILES: + report.error( + where, + f"`iconUrl` must reference one of {sorted(ALLOWED_ICON_FILES)}, got {icon_url!r}", + ) + return + + icon_path = folder / normalised + if not icon_path.is_file(): + report.error(where, f"`iconUrl` points at {normalised!r} but no such file exists") + return + + size = icon_path.stat().st_size + if size > MAX_ICON_BYTES: + report.error( + where, + f"`{normalised}` is {size // 1024} KB, over the {MAX_ICON_BYTES // 1024} KB cap; " + "trim the icon or host it off-repo via an absolute URL", + ) + + +def _validate_main_js(report: Report, folder: Path) -> None: + """Cheap heuristics on `main.js`.""" + + main_js = folder / "main.js" + if not main_js.is_file(): + return + where = f"modules/{folder.name}/main.js" + + try: + content = main_js.read_text(encoding="utf-8") + except UnicodeDecodeError: + report.error(where, "must be UTF-8") + return + + if not content.strip(): + report.error(where, "is empty") + return + + if len(content) > 512 * 1024: + report.warning(where, f"is large ({len(content) // 1024} KB) — consider trimming") + + # No top-level `return` — the IIFE wrapper turns this into a syntax error. + for lineno, line in enumerate(content.splitlines(), start=1): + stripped = line.strip() + if stripped.startswith("return ") or stripped == "return;" or stripped == "return": + # Could still be inside a function literal at line 1; we can't + # parse JS exactly, but this is a strong smell. + indent = len(line) - len(line.lstrip()) + if indent == 0: + report.error( + where, + f"line {lineno}: top-level `return` — the IIFE wrapper would make this a syntax error", + ) + break + + # If `getConfig` is referenced but no configItems are declared in the + # manifest, the user will see "undefined" defaults silently. + manifest_path = folder / "module.json" + if manifest_path.is_file() and "getConfig(" in content: + try: + manifest = json.loads(manifest_path.read_text(encoding="utf-8")) + if not manifest.get("configItems"): + report.warning( + where, + "uses `getConfig(...)` but `module.json` declares no `configItems`", + ) + except (json.JSONDecodeError, OSError): + # The JSON-level checks elsewhere will report the actual cause. + pass + + +# ───────────────────────── entry point ───────────────────────────────── + +def _load_json(report: Report, path: Path, where: str) -> dict[str, Any] | None: + try: + return json.loads(path.read_text(encoding="utf-8")) + except FileNotFoundError: + report.error(where, f"file not found: {path}") + except json.JSONDecodeError as e: + report.error(where, f"invalid JSON: {e.msg} (line {e.lineno}, col {e.colno})") + except UnicodeDecodeError: + report.error(where, "file must be UTF-8") + return None + + +def main(repo_root: Path) -> int: + modules_dir = repo_root / "modules" + if not modules_dir.is_dir(): + print(f"❌ {modules_dir} does not exist", file=sys.stderr) + return 1 + + report = Report() + + # 1. Parse + validate the registry. + registry = _load_json(report, modules_dir / "registry.json", "registry.json") + registry_entries: list[dict[str, Any]] = [] + if isinstance(registry, dict): + registry_entries = _validate_registry(report, registry) + + # 2. Walk module folders. + folders = sorted( + p for p in modules_dir.iterdir() + if p.is_dir() and not p.name.startswith(".") + ) + + folder_paths = {p.name for p in folders} + registry_paths = {e["path"] for e in registry_entries if _is_str(e.get("path"))} + custom_paths = {e["path"] for e in registry_entries if _is_str(e.get("path")) and e.get("sourceType", "CUSTOM") != "CHROME_EXTENSION"} + + # Folders missing a registry entry. + for orphan in folder_paths - registry_paths: + report.error(f"modules/{orphan}", "module folder has no entry in registry.json") + # Registry entries pointing at non-existent folders (CHROME_EXTENSION entries don't need folders). + for ghost in custom_paths - folder_paths: + report.error("registry.json", f"entry refers to missing folder modules/{ghost}/") + + # 3. Per-folder validation + cross-file consistency. + entries_by_path = {e["path"]: e for e in registry_entries if _is_str(e.get("path")) and e.get("sourceType", "CUSTOM") != "CHROME_EXTENSION"} + for folder in folders: + _validate_folder_layout(report, folder) + _validate_main_js(report, folder) + _validate_icon_coherence(report, folder, entries_by_path.get(folder.name)) + + manifest_path = folder / "module.json" + manifest = _load_json(report, manifest_path, f"modules/{folder.name}/module.json") + if isinstance(manifest, dict): + _validate_module_json(report, folder, manifest) + entry = entries_by_path.get(folder.name) + if entry: + _validate_cross_consistency(report, entry, manifest, folder) + + print(report.render()) + return 0 if report.ok() else 1 + + +if __name__ == "__main__": + repo = Path(__file__).resolve().parents[3] + sys.exit(main(repo)) diff --git a/.github/scripts/ui_design_allowlist.txt b/.github/scripts/ui_design_allowlist.txt new file mode 100644 index 0000000..6335ffa --- /dev/null +++ b/.github/scripts/ui_design_allowlist.txt @@ -0,0 +1,122 @@ +# DruksCode UI design-system historical debt baseline. +# Format: relative/path.kt|rule_key|allowed_count +# Regenerate only after intentionally accepting a new migration checkpoint. +app/src/main/java/br/com/drukstech/codeapp/ui/components/ActivationCodeCard.kt|raw_corner_shape|12 +app/src/main/java/br/com/drukstech/codeapp/ui/components/ActivationCodeCard.kt|raw_surface|6 +app/src/main/java/br/com/drukstech/codeapp/ui/components/ActivationCodeCard.kt|raw_button|1 +app/src/main/java/br/com/drukstech/codeapp/ui/components/AutoRefreshCountdownOverlay.kt|raw_corner_shape|1 +app/src/main/java/br/com/drukstech/codeapp/ui/components/AutoRefreshCountdownOverlay.kt|raw_surface|1 +app/src/main/java/br/com/drukstech/codeapp/ui/components/AutoStartCard.kt|raw_corner_shape|6 +app/src/main/java/br/com/drukstech/codeapp/ui/components/AutoStartCard.kt|raw_card|1 +app/src/main/java/br/com/drukstech/codeapp/ui/components/AutoStartCard.kt|raw_surface|6 +app/src/main/java/br/com/drukstech/codeapp/ui/components/BgmCard.kt|raw_surface|2 +app/src/main/java/br/com/drukstech/codeapp/ui/components/BgmSelector.kt|raw_corner_shape|3 +app/src/main/java/br/com/drukstech/codeapp/ui/components/BgmSelector.kt|raw_surface|9 +app/src/main/java/br/com/drukstech/codeapp/ui/components/BrowserDisguiseConfigCard.kt|raw_corner_shape|10 +app/src/main/java/br/com/drukstech/codeapp/ui/components/BrowserDisguiseConfigCard.kt|raw_surface|5 +app/src/main/java/br/com/drukstech/codeapp/ui/components/CodeSnippetSelector.kt|raw_corner_shape|10 +app/src/main/java/br/com/drukstech/codeapp/ui/components/CodeSnippetSelector.kt|raw_surface|8 +app/src/main/java/br/com/drukstech/codeapp/ui/components/ColorPickerDialog.kt|raw_corner_shape|2 +app/src/main/java/br/com/drukstech/codeapp/ui/components/DnsConfigCard.kt|raw_corner_shape|2 +app/src/main/java/br/com/drukstech/codeapp/ui/components/DnsConfigCard.kt|raw_card|1 +app/src/main/java/br/com/drukstech/codeapp/ui/components/EncryptionConfigCard.kt|raw_corner_shape|1 +app/src/main/java/br/com/drukstech/codeapp/ui/components/EncryptionConfigCard.kt|raw_card|1 +app/src/main/java/br/com/drukstech/codeapp/ui/components/EnhancedActivationDialog.kt|raw_corner_shape|6 +app/src/main/java/br/com/drukstech/codeapp/ui/components/EnhancedActivationDialog.kt|raw_surface|3 +app/src/main/java/br/com/drukstech/codeapp/ui/components/IconGeneratorDialog.kt|raw_corner_shape|7 +app/src/main/java/br/com/drukstech/codeapp/ui/components/IconGeneratorDialog.kt|raw_surface|1 +app/src/main/java/br/com/drukstech/codeapp/ui/components/IconLibraryDialog.kt|raw_corner_shape|4 +app/src/main/java/br/com/drukstech/codeapp/ui/components/IconLibraryDialog.kt|raw_card|1 +app/src/main/java/br/com/drukstech/codeapp/ui/components/IconLibraryDialog.kt|raw_surface|2 +app/src/main/java/br/com/drukstech/codeapp/ui/components/IconPickerWithLibrary.kt|raw_surface|1 +app/src/main/java/br/com/drukstech/codeapp/ui/components/IsolationConfigCard.kt|raw_corner_shape|2 +app/src/main/java/br/com/drukstech/codeapp/ui/components/IsolationConfigCard.kt|raw_card|1 +app/src/main/java/br/com/drukstech/codeapp/ui/components/LanguageSelector.kt|raw_card|2 +app/src/main/java/br/com/drukstech/codeapp/ui/components/LiquidGlassEffect.kt|hardcoded_color|4 +app/src/main/java/br/com/drukstech/codeapp/ui/components/LongPressMenu.kt|hardcoded_color|6 +app/src/main/java/br/com/drukstech/codeapp/ui/components/LongPressMenu.kt|raw_corner_shape|10 +app/src/main/java/br/com/drukstech/codeapp/ui/components/LongPressMenu.kt|raw_surface|8 +app/src/main/java/br/com/drukstech/codeapp/ui/components/LrcEditorDialog.kt|raw_corner_shape|2 +app/src/main/java/br/com/drukstech/codeapp/ui/components/LrcEditorDialog.kt|raw_surface|5 +app/src/main/java/br/com/drukstech/codeapp/ui/components/ManualLrcAligner.kt|raw_corner_shape|3 +app/src/main/java/br/com/drukstech/codeapp/ui/components/ManualLrcAligner.kt|raw_card|2 +app/src/main/java/br/com/drukstech/codeapp/ui/components/ManualLrcAligner.kt|raw_surface|4 +app/src/main/java/br/com/drukstech/codeapp/ui/components/NotificationConfigCard.kt|raw_corner_shape|1 +app/src/main/java/br/com/drukstech/codeapp/ui/components/NotificationConfigCard.kt|raw_card|1 +app/src/main/java/br/com/drukstech/codeapp/ui/components/OnlineMusicSearchDialog.kt|raw_corner_shape|5 +app/src/main/java/br/com/drukstech/codeapp/ui/components/OnlineMusicSearchDialog.kt|raw_card|2 +app/src/main/java/br/com/drukstech/codeapp/ui/components/OnlineMusicSearchDialog.kt|raw_surface|3 +app/src/main/java/br/com/drukstech/codeapp/ui/components/PremiumComponents.kt|raw_button|1 +app/src/main/java/br/com/drukstech/codeapp/ui/components/QrCodeShareDialog.kt|raw_corner_shape|6 +app/src/main/java/br/com/drukstech/codeapp/ui/components/QrCodeShareDialog.kt|raw_card|1 +app/src/main/java/br/com/drukstech/codeapp/ui/components/RuntimeScreenComponents.kt|raw_corner_shape|5 +app/src/main/java/br/com/drukstech/codeapp/ui/components/RuntimeScreenComponents.kt|raw_card|2 +app/src/main/java/br/com/drukstech/codeapp/ui/components/RuntimeScreenComponents.kt|raw_surface|4 +app/src/main/java/br/com/drukstech/codeapp/ui/components/SampleProjectCard.kt|raw_corner_shape|3 +app/src/main/java/br/com/drukstech/codeapp/ui/components/Shimmer.kt|hardcoded_color|2 +app/src/main/java/br/com/drukstech/codeapp/ui/components/Shimmer.kt|raw_corner_shape|7 +app/src/main/java/br/com/drukstech/codeapp/ui/components/StatusBarImageCropper.kt|raw_corner_shape|3 +app/src/main/java/br/com/drukstech/codeapp/ui/components/StatusBarImageCropper.kt|raw_card|2 +app/src/main/java/br/com/drukstech/codeapp/ui/components/TypedSampleProjectCard.kt|raw_corner_shape|3 +app/src/main/java/br/com/drukstech/codeapp/ui/components/VideoTrimmer.kt|raw_surface|1 +app/src/main/java/br/com/drukstech/codeapp/ui/components/VirtualNavigationBar.kt|hardcoded_color|2 +app/src/main/java/br/com/drukstech/codeapp/ui/components/VirtualNavigationBar.kt|raw_surface|1 +app/src/main/java/br/com/drukstech/codeapp/ui/components/DkcCodeEditorDialog.kt|raw_surface|5 +app/src/main/java/br/com/drukstech/codeapp/ui/components/DkcErrorView.kt|raw_corner_shape|1 +app/src/main/java/br/com/drukstech/codeapp/ui/components/DkcErrorView.kt|raw_surface|1 +app/src/main/java/br/com/drukstech/codeapp/ui/components/announcement/AnnouncementTemplates.kt|hardcoded_color|28 +app/src/main/java/br/com/drukstech/codeapp/ui/components/announcement/AnnouncementTemplates.kt|raw_corner_shape|13 +app/src/main/java/br/com/drukstech/codeapp/ui/components/announcement/AnnouncementTemplates.kt|raw_card|3 +app/src/main/java/br/com/drukstech/codeapp/ui/components/announcement/AnnouncementTemplates.kt|raw_surface|1 +app/src/main/java/br/com/drukstech/codeapp/ui/components/announcement/AnnouncementTemplates.kt|raw_button|1 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/AboutScreen.kt|raw_corner_shape|1 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/AiSettingsScreen.kt|raw_corner_shape|2 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/AiSettingsScreen.kt|raw_surface|10 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/BatchImportDialog.kt|raw_surface|2 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateAppScreen.kt|raw_corner_shape|2 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateAppScreen.kt|raw_surface|1 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateAppScreen.kt|raw_button|1 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateAppSplashCard.kt|raw_surface|2 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateAppUserScripts.kt|raw_corner_shape|1 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateAppUserScripts.kt|raw_card|1 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateAppUserScripts.kt|raw_surface|1 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateAppWebViewCards.kt|raw_corner_shape|13 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateAppWebViewCards.kt|raw_surface|8 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateFrontendAppScreen.kt|raw_corner_shape|3 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateFrontendAppScreen.kt|raw_surface|2 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateGalleryAppScreen.kt|raw_corner_shape|7 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateGalleryAppScreen.kt|raw_surface|5 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateGoAppScreen.kt|raw_corner_shape|7 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateGoAppScreen.kt|raw_surface|8 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateHtmlAppScreen.kt|raw_corner_shape|6 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateHtmlAppScreen.kt|raw_surface|1 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateMediaAppScreen.kt|raw_corner_shape|16 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateMediaAppScreen.kt|raw_surface|7 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateMultiWebAppScreen.kt|raw_corner_shape|10 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateMultiWebAppScreen.kt|raw_card|2 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateMultiWebAppScreen.kt|raw_surface|3 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateMultiWebAppScreen.kt|raw_button|2 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateOfflinePackScreen.kt|raw_corner_shape|3 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreateOfflinePackScreen.kt|raw_surface|2 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreatePhpAppScreen.kt|raw_corner_shape|3 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreatePhpAppScreen.kt|raw_surface|4 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreatePythonAppScreen.kt|raw_corner_shape|8 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/CreatePythonAppScreen.kt|raw_surface|9 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/DeviceDisguiseCard.kt|raw_corner_shape|8 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/DeviceDisguiseCard.kt|raw_surface|6 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/HomeScreen.kt|raw_corner_shape|1 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/HomeScreen.kt|raw_surface|1 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/HostsAdBlockScreen.kt|raw_surface|1 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/InstallProjectDepsCard.kt|raw_corner_shape|2 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/LinuxEnvironmentScreen.kt|raw_corner_shape|11 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/PermissionConfigScreen.kt|raw_corner_shape|5 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/PermissionConfigScreen.kt|raw_surface|5 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/PlayStoreScreen.kt|hardcoded_color|7 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/PlayStoreScreen.kt|raw_corner_shape|3 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/PlayStoreScreen.kt|raw_surface|4 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/PortManagerScreen.kt|raw_corner_shape|6 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/PortManagerScreen.kt|raw_surface|3 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/RuntimeDepsScreen.kt|raw_surface|1 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/StatsScreen.kt|raw_corner_shape|4 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/StatsScreen.kt|raw_surface|4 +app/src/main/java/br/com/drukstech/codeapp/ui/screens/WordPressSettingsScreen.kt|raw_corner_shape|3 diff --git a/.github/workflows/android-ci.yml b/.github/workflows/android-ci.yml new file mode 100644 index 0000000..ab0499d --- /dev/null +++ b/.github/workflows/android-ci.yml @@ -0,0 +1,127 @@ +name: Android CI Build + +on: + pull_request: + workflow_dispatch: + push: + branches: + - "**" + +permissions: + contents: read + +concurrency: + # Group per ref AND event type: routine pushes to the same branch still cancel + # their superseded check runs, but a workflow_dispatch packaging run is never + # cancelled by a merge push landing on the same ref mid-build. + group: android-ci-${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} + cancel-in-progress: ${{ github.event_name == 'push' }} + +jobs: + check: + runs-on: ubuntu-latest + timeout-minutes: 45 + + steps: + - name: Download code + uses: actions/checkout@v6 + + - name: Prepare Java + uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: "17" + + - name: Prepare Android tools + uses: android-actions/setup-android@v3 + with: + packages: "" + + - name: Prepare Gradle + uses: gradle/actions/setup-gradle@v6 + with: + cache-provider: basic + + - name: Install needed tools + run: | + sdkmanager --install \ + "platform-tools" \ + "platforms;android-36" \ + "build-tools;36.0.0" \ + "cmake;3.22.1" \ + "ndk;28.2.13676358" + + - name: Run checks + run: | + ./gradlew --no-daemon --no-configuration-cache \ + -Dkotlin.compiler.execution.strategy=in-process \ + -PskipShellTemplateSync=true \ + -PallowDebugSignedRelease=true \ + :app:compileStandardDebugKotlin \ + :shell:compileDebugKotlin \ + :app:testStandardDebugUnitTest \ + :app:checkConfigFieldDrift + + package-apks: + if: github.event_name == 'workflow_dispatch' + runs-on: ubuntu-latest + timeout-minutes: 90 + + steps: + - name: Download code + uses: actions/checkout@v6 + + - name: Prepare Java + uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: "17" + + - name: Prepare Android tools + uses: android-actions/setup-android@v3 + with: + packages: "" + + - name: Prepare Gradle + uses: gradle/actions/setup-gradle@v6 + with: + cache-provider: basic + + - name: Install needed tools + run: | + sdkmanager --install \ + "platform-tools" \ + "platforms;android-36" \ + "build-tools;36.0.0" \ + "cmake;3.22.1" \ + "ndk;28.2.13676358" + + - name: Build APKs + run: | + ./gradlew --no-daemon --no-configuration-cache \ + -Dkotlin.compiler.execution.strategy=in-process \ + -PallowDebugSignedRelease=true \ + :app:assembleStandardDebug \ + :app:assembleStandardRelease \ + :app:assembleGplayDebug \ + :app:assembleGplayRelease \ + :shell:assembleDebug \ + :shell:assembleRelease + + - name: Upload standard APKs + uses: actions/upload-artifact@v4 + with: + name: standard-apks-DEBUG-SIGNED-do-not-distribute-${{ github.run_number }} + path: | + app/build/outputs/apk/standard/**/*.apk + shell/build/outputs/apk/**/*.apk + if-no-files-found: error + retention-days: 14 + + - name: Upload gplay APKs + uses: actions/upload-artifact@v4 + with: + name: gplay-apks-br.com.drukstech.codeapp.play-DEBUG-SIGNED-do-not-distribute-${{ github.run_number }} + path: app/build/outputs/apk/gplay/**/*.apk + if-no-files-found: error + retention-days: 14 diff --git a/.github/workflows/docs-deploy.yml b/.github/workflows/docs-deploy.yml new file mode 100644 index 0000000..5c2e634 --- /dev/null +++ b/.github/workflows/docs-deploy.yml @@ -0,0 +1,78 @@ +# Builds the VitePress documentation site under docs/ and deploys it to +# GitHub Pages. On pull requests the site is only built (to catch breakage); +# on push to main and on manual dispatch it is built and deployed. +name: Docs Deploy + +on: + pull_request: + paths: + - "docs/**" + - ".github/workflows/docs-deploy.yml" + push: + branches: + - main + paths: + - "docs/**" + - ".github/workflows/docs-deploy.yml" + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: pages-${{ github.ref }} + cancel-in-progress: false + +jobs: + build: + runs-on: ubuntu-latest + timeout-minutes: 15 + + steps: + - name: Download code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Prepare Node + uses: actions/setup-node@v4 + with: + node-version: "20" + cache: npm + cache-dependency-path: docs/package-lock.json + + - name: Install dependencies + working-directory: docs + run: npm ci + + - name: Build site + working-directory: docs + run: npm run build + + - name: Upload Pages artifact + if: github.event_name != 'pull_request' + uses: actions/upload-pages-artifact@v3 + with: + path: docs/.vitepress/dist + + deploy: + if: github.event_name != 'pull_request' + needs: build + runs-on: ubuntu-latest + timeout-minutes: 10 + # Only this job touches Pages: the build job runs on pull_requests (including + # same-repo branches) and executes third-party dependency postinstall code, so it + # must not hold Pages/OIDC write capabilities. + permissions: + contents: read + pages: write + id-token: write + + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.github/workflows/modules-check.yml b/.github/workflows/modules-check.yml new file mode 100644 index 0000000..04df6b1 --- /dev/null +++ b/.github/workflows/modules-check.yml @@ -0,0 +1,49 @@ +name: Module Market Check + +# Runs the module catalog validator at `.github/scripts/ci/validate_modules.py`. +# Triggered for any change touching the catalog or the validator itself, +# whether on a PR or a direct push to main. Other paths bypass this job +# so contributors who don't touch `modules/` aren't blocked by it. + +on: + pull_request: + paths: + - 'modules/**' + - '.github/scripts/ci/validate_modules.py' + - '.github/scripts/ci/generate_submissions.py' + - '.github/workflows/modules-check.yml' + push: + branches: + - main + paths: + - 'modules/**' + - '.github/scripts/ci/validate_modules.py' + - '.github/scripts/ci/generate_submissions.py' + - '.github/workflows/modules-check.yml' + # Manual run from the Actions tab — handy when adjusting the validator + # rules without a real catalog change to push. + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: modules-check-${{ github.ref }} + cancel-in-progress: true + +jobs: + validate-modules: + name: Validate modules/ + runs-on: ubuntu-latest + timeout-minutes: 5 + + steps: + - name: Download code + uses: actions/checkout@v6 + + - name: Use system Python 3 + # Ubuntu runners ship a recent Python 3 — no setup-python step needed. + run: python3 --version + + - name: Run module market validator + run: python3 .github/scripts/ci/validate_modules.py diff --git a/.github/workflows/modules-publish.yml b/.github/workflows/modules-publish.yml new file mode 100644 index 0000000..fca0da5 --- /dev/null +++ b/.github/workflows/modules-publish.yml @@ -0,0 +1,124 @@ +name: Module Market Publish + +# Regenerates `modules/submissions.json` after a PR is merged into main. +# +# This file is what tells the in-app market who submitted each module +# and when. Modules without a corresponding entry are deliberately +# hidden from the catalog — that's how the "only show merged PRs" +# guarantee is enforced. We regenerate from scratch on every relevant +# push so a missing entry can never silently outlive a revert. +# +# main is branch-protected (requires a PR + the "check" status), and the +# default GITHUB_TOKEN can't push to it directly. So instead of pushing, +# this workflow commits the regenerated file to a fixed working branch +# and opens (or updates) a PR, then queues an auto-merge so the catalog +# stays in sync without any manual step. + +on: + push: + branches: + - main + paths: + - 'modules/**' + - '.github/scripts/ci/generate_submissions.py' + - '.github/workflows/modules-publish.yml' + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +concurrency: + group: modules-publish + cancel-in-progress: false + +jobs: + publish: + name: Generate submissions.json + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - name: Check out repository + uses: actions/checkout@v6 + with: + # We need the full history so `git log --diff-filter=A` can find + # the introducing commit for each module folder. + fetch-depth: 0 + persist-credentials: true + + - name: Use system Python 3 + run: python3 --version + + - name: Generate submissions.json + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Legacy parameter: the generator records every human direct-push + # author (modules only reach main via review or maintainer push) + # and only excludes bot identities. + MAINTAINERS: shiaho777 + run: | + python3 .github/scripts/ci/generate_submissions.py \ + --owner "${GITHUB_REPOSITORY%%/*}" \ + --repo "${GITHUB_REPOSITORY##*/}" \ + --token "$GITHUB_TOKEN" + + - name: Open PR for regenerated submissions.json + env: + # Prefer a PAT (secret PAT_TOKEN) when available: a GITHUB_TOKEN- + # pushed branch can't trigger other workflows (GitHub anti-loop), so + # the required "check" never reports on the resulting PR and it can't + # merge. A PAT-pushed branch triggers android-ci normally. Fall back to + # GITHUB_TOKEN so the workflow still runs without a PAT configured. + GH_TOKEN: ${{ secrets.PAT_TOKEN || secrets.GITHUB_TOKEN }} + GIT_AUTH_USER: x-access-token + GIT_AUTH_PWD: ${{ secrets.PAT_TOKEN || secrets.GITHUB_TOKEN }} + HAS_PAT: ${{ secrets.PAT_TOKEN != '' }} + BRANCH: ci/regenerate-submissions + run: | + if git diff --quiet -- modules/submissions.json; then + echo "No changes to submissions.json" + exit 0 + fi + + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + + # The main branch is protected (requires a PR + the "check" status), + # and the default GITHUB_TOKEN can't push there directly. Push the + # regenerated file to a long-lived working branch and let a PR land it. + git checkout -B "$BRANCH" + git add modules/submissions.json + git commit -m "chore(modules): regenerate submissions.json" + + REPO="github.com/${GITHUB_REPOSITORY}" + if [ "$HAS_PAT" = "true" ]; then + git push --force-with-lease "https://${GIT_AUTH_USER}:${GIT_AUTH_PWD}@${REPO}" "$BRANCH" + else + git push --force-with-lease origin "$BRANCH" + fi + + # Reuse an existing open PR if one is already tracking this branch. + PR_NUMBER=$(gh pr list --head "$BRANCH" --base main --state open \ + --json number --jq '.[0].number // empty') + + TITLE="chore(modules): regenerate submissions.json" + BODY="Auto-generated by the \`Module Market Publish\` workflow on push to \`main\`. No manual changes — this only updates \`modules/submissions.json\` so the in-app market catalog stays in sync." + + if [ -z "$PR_NUMBER" ]; then + PR_NUMBER=$(gh pr create --head "$BRANCH" --base main \ + --title "$TITLE" --body "$BODY") + else + gh pr edit "$PR_NUMBER" --title "$TITLE" --body "$BODY" + fi + + # When using a PAT, the branch push already triggered android-ci, so + # wait for its "check" to report then enable auto-merge (GitHub merges + # automatically once all required checks pass). With GITHUB_TOKEN there + # is no check to wait on, so the PR is left for a manual merge. + if [ "$HAS_PAT" = "true" ]; then + gh pr merge "$PR_NUMBER" --squash --auto --delete-branch \ + || echo "::warning::Auto-merge setup failed; PR #$PR_NUMBER left open for manual merge." + else + echo "No PAT_TOKEN configured; PR #$PR_NUMBER left open for manual merge (GITHUB_TOKEN can't satisfy the required check)." + fi diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0ac90a8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,75 @@ +*.apk +*.aar +*.ap_ +*.aab +*.dex +*.class +*.so +*.tar.gz +bin/ +gen/ +out/ +release/ +.gradle/ +build/ +.vscode/ +.claude/ +.zcode/ +.workbuddy/ +.workbuddy-ai/ +local.properties +gradle/config.properties +gradle/gradle-daemon-jvm.properties +rule.md +CLAUDE.md +*.iml +.idea/ +.idea/workspace.xml +.idea/tasks.xml +.idea/gradle.xml +.idea/assetWizardSettings.xml +.idea/dictionaries +.idea/libraries +.idea/caches +.idea/modules.xml +.idea/misc.xml +.idea/vcs.xml +.navigation/ +captures/ +.externalNativeBuild/ +.cxx/ +*.jks +*.keystore +*.log +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db +*.kotlin_module +obj/ +app/src/main/jniLibs/arm64-v8a/libphp.so +/out/ +.idea/caches/ +.idea/libraries/ +.idea/shelf/ +.idea/workspace.xml +.idea/tasks.xml +.idea/.name +.idea/compiler.xml +.idea/copyright/profiles_settings.xml +.idea/encodings.xml +.idea/scopes/scope_settings.xml +.idea/vcs.xml +tmp_apk_inspect/ +bugreport-*.zip +test-haze.kt +restore +server/ +admin/ +node_modules/ +__pycache__/ +*.pyc +.kotlin/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..342754c --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,370 @@ +# AGENTS.md + +Instructions for coding agents working in this repository. + +## Code style + +- Do what you believe is right. Make the change complete and correct, not the smallest possible diff. If a fix calls for refactoring, renaming, or touching multiple files, do it. +- Match the patterns and conventions already in the surrounding code. +- Do not add copyright or license headers unless asked. + +## Project layout + +| Path | Role | +|------|------| +| `app/` | Full builder host: editor UI, export pipeline, runtimes, preview. | +| `shell/` | Runtime template. Built to `app/src/main/assets/template/webview_shell.apk` via `:shell:assembleRelease` + `:app:syncShellTemplateApk`. | +| `clone-host/` | Host-side APK clone / identity reshape support library. Its DEX asset generation (`syncCloneHostDex`) is deliberately disabled (`enabled = false`, AV false-positive mitigation, e0d2d4d6) — `AppCloner` runs fail-soft without the asset. | +| `modules/` | Module Market catalog (`registry.json` + per-module folders). | +| `docs/` | VitePress documentation site (guide / developer / extensions, EN + ZH), published to https://shiaho777.github.io/web-to-app/ by `.github/workflows/docs-deploy.yml`. Site URL paths map 1:1 to files under `docs/` (`/zh/...` → `docs/zh/...`). | +| `scripts/` | Build helpers and gates (`check_config_field_drift.py`). | + +Runtime Kotlin is authored under `app/` and synced into `shell` by `syncShellRuntimeSources`. Edit the `app/` source once; do not permanently fork copies under shell. + +User-facing product docs: `README.md`, `.github/docs/README_CN.md`, `.github/CONTRIBUTING.md`, `modules/README.md`. The published documentation site is https://shiaho777.github.io/web-to-app/ (source: `docs/`, deployed by `.github/workflows/docs-deploy.yml`). + +## How the main pieces connect + +```text +Editor (Compose screens in app/) + ↔ data models (WebApp, configs) + ↔ export factory (ApkConfig / ApkConfigJsonFactory) + ↔ ApkBuilder / ApkBuildCache → signed generated APK + +app/ sources + → syncShellRuntimeSources → shell DEX → webview_shell.apk (template) + +Generated APK runtime + DruksCodeApplication → ShellModeManager → load assets JSON config + → WebViewManager / runtime servers (Node/PHP/Python/Go/WordPress) +``` + +Mental model: + +- **Host preview** runs `:app` with all classes on the main classpath. +- **Generated APK** runs the shell template classes (full runtime synced from `app/`), reading config from assets JSON via `ShellModeManager`. +- A flag in the editor is useless at export unless it flows through **model → ApkConfig JSON → shell config → runtime code**. + +## i18n + +- Host UI strings live in `app/src/main/java/br/com/drukstech/codeapp/core/i18n/Strings.kt` (split across `Strings` / `StringsA` … `StringsE`). +- **All** user-visible strings must be inline `when (Strings.lang)` blocks covering all 10 languages: Chinese, English, Arabic, Portuguese, Spanish, French, German, Russian, Japanese, Korean. `when(lang)` blocks may never use `else ->` — `AppStringsResourceConsistencyTest` and `StringsKtTranslationParityTest` enforce this. +- **Never** load user-visible text via `context.getString(R.string.*)` / `stringResource(R.string.*)`. `res/values/strings.xml` holds only `translatable="false"` resources (e.g. `app_name`) and no locale `values-*/` directories exist, so a localized resource string could never cover the 10 languages and would silently fall back to the default `values/` (Chinese). Use `Strings.xxx` (or `Strings.funName(arg)` for parameterised strings — see `linuxEnvInstalledToast(name)` for the pattern). Tests gate this: `kotlin source never references R string for user-visible text`, plus `values strings xml only holds non-localised resources` and `no locale values dirs or grouped app strings files exist` which block resurrecting resource-based strings. +- `R.string` is reserved for `translatable="false"` non-localised resources only (e.g. `app_name`). +- Prefer adding properties on the existing split objects; match surrounding style. + +## Android and packaging constraints + +- Generated apps keep a low `targetSdk` (28) on the shell path because they rely on on-device fork+exec runtimes. Do not raise shell targetSdk casually. +- The host app targets SDK 35 (antivirus reputation); SELinux W^X therefore blocks host-side exec of downloaded runtimes. `RuntimeExecPolicy` (`core/linux`) gates those previews by probing the installed targetSdk — generated APKs (always 28) pass unconditionally. Node preview (JNI via native libs) is unaffected. +- Launch runtime / toolchain processes through `HostProcessLauncher` (`core/linux`): plain `ProcessBuilder` fork+exec where the platform allows it (generated APKs, targetSdk 28), the user-mode static exec loader (`StaticExecProcess`, memfd-based) on W^X hosts (targetSdk ≥ 29), or a degraded error when no static exec bridge is available. A raw `Runtime.exec` on a downloaded binary crashes the host app on W^X devices (#795). +- Avoid new third-party dependencies unless strongly justified (`app/build.gradle.kts` / `shell/build.gradle.kts`). Prefer platform APIs and existing modules. +- Notification push channels: Web Notification polyfill, polling, WebSocket, FCM (developer-owned Firebase config). Do not add OEM vendor push SDKs by default. +- Foreground services and notification helpers must use `SafeNotificationChannels` (or equivalent fail-soft create). Channel creation failures must not crash FGS startup. +- **One shell template:** `webview_shell.apk` from `:shell` release. Do not introduce a second template APK. +- Export incremental rebuild lives in `app/.../apkbuilder` (`ApkBuildCache` + `ApkBuilder`): + - Modes: `FULL` / `CONTENT_OVERLAY` / `REUSE_UNSIGNED`. + - Template / entry identities must be **content-stable** (no mtime-based keys). + - Encrypted builds always force a full rebuild. + - Do not feed signed or renamed APKs back into full `modifyApk` as templates. +- Port coordination: `PortManager` + `PortConflictMode` (`REASSIGN` / `AUTO_KILL` / `ALERT`) with real stop handlers. Local server runtimes must allocate through PortManager and clean up on stop. +- Local server / Linux env DNS: fork+exec runtimes (Node / PHP / Python / Go / WordPress / Linux env) should wire through `LocalDnsBridgeProxy` when they need host DNS/proxy bridging. +- Large runtime downloads use `NetworkModule.downloadClient` (extended timeouts), not the default short-lived client. +- HTML / FRONTEND packaged shells need file-scheme access via `ShellWebViewConfig` (`allowFileAccess` / local-file detection). Do not regress pure file-based HTML loads. +- Node.js export must embed `libnode_bridge.so`, `libnode.so` (16KB-aligned), and `libc++_shared.so` as native libs. Go export must embed `libgo_exec_loader.so`. +- Gradle custom tasks (`syncCloneHostDex`, etc.) must be configuration-cache safe: capture `File`/`Provider` values at configuration time, do not reference `Project`/`android.sdkDirectory` inside task closures. + +## Workflow + +- Do not commit secrets, `local.properties`, keystores, or IDE/cache junk. +- Do not create commits, push, open PRs, or file Issues unless the user asks to deliver / ship / push / open a PR (or equivalent). +- When changing export or shell packaging, rebuild the template you touched. +- When changing config fields, run `checkConfigFieldDrift` to catch model ↔ shell config name drift. + +### Delivery (Issue + PR + CI) + +Default target: [shiaho777/drukscode](https://github.com/shiaho777/web-to-app). Prefer a pull request over direct pushes to `main` when delivering code. Human-facing wording of the same loop lives in [CONTRIBUTING.md](.github/CONTRIBUTING.md); keep those docs in sync when this process changes. + +**Language (required):** GitHub **Issues and PRs must be written in English** — titles, bodies, labels text you author, and delivery comments on the Issue/PR. Local chat with the user may be Chinese or any language; do not copy that language into Issue/PR text. + +When the user asks to deliver a change, run the Issue → branch → PR → CI → merge loop end-to-end. Do not close the Issue until the PR is merged and CI is green. + +--- + +## Shell template and runtime sync + +### Dual runtime (preview vs export) + +| | Host `:app` | Generated APK | +|--|-------------|---------------| +| DEX | All `app/src` classes | Shell sync include−exclude (full runtime set) | +| Config | Editor / in-memory models | Assets JSON via `ShellModeManager` | +| Template | Not used | `app/src/main/assets/template/webview_shell.apk` | + +**Preview ≠ export** unless both paths stay valid: + +1. Host still has the real implementation. +2. Shell-synced code reads the config field from assets JSON at runtime. +3. The field name in `ApkConfig` JSON matches the `@SerializedName` in `ShellModeManager` (Gson silently drops mismatches). + +Most common failure: preview works; exported APK silently skips the feature because a config field name drifted between the export factory and the shell config class. + +### Where each concern is edited + +| Concern | Path | +|---------|------| +| What enters shell | `shell/build.gradle.kts` → `syncShellRuntimeSources` include/exclude | +| Shell template build | `:shell:assembleRelease` + `:app:syncShellTemplateApk` | +| Template output | `app/src/main/assets/template/webview_shell.apk` | +| Config → shell JSON | `app/.../apkbuilder/ApkConfigJsonFactory.kt` | +| Shell config types | `app/.../core/shell/ShellModeManager.kt` | +| Runtime WebView config | `app/.../ui/shell/ShellWebViewConfig.kt` | +| Config drift gate | `scripts/check_config_field_drift.py` → `:app:checkConfigFieldDrift` | +| Shell minify policy | `shell/proguard-rules.pro` | + +--- + +## Common change recipes + +These are the default approaches for everyday work. Follow the chain end-to-end; stopping at UI or host-only code is how preview and export diverge. + +### 1. Add or change a host UI string + +1. Add the property in the correct `Strings*` split with all 10 languages. +2. Reference it from Compose/UI the same way neighbors do. + +### 2. Add an editor setting that must affect the generated APK + +Trace and update **all** of: + +1. Model (`WebApp` / nested config) and editor UI binding +2. Export mapping (`ApkBuilder` / `ApkConfig` / `ApkConfigJsonFactory`) +3. Shell config types (`ShellModeManager` / shell config data classes) if runtime reads them +4. Runtime use site in shell-synced code +5. Unit tests for export wiring when flags change +6. **Coverage test update (REQUIRED).** When adding a new Boolean field to + `WebViewConfig`, you MUST add it to `flipAllBooleans()` in + `WebViewConfigBooleanCoverageTest.kt`. The test + `flipAllBooleans covers every declared Boolean field` uses reflection to + verify that every declared Boolean field is listed — if you forget, CI + fails with a message naming the missing field. For non-Boolean fields, add + a spot-check to `key non-Boolean WebViewConfig fields survive the export + round-trip`. This is the safety net that catches "preview works, export + broken" before it ships. +7. **Shell UI parity (REQUIRED for per-type player screens).** Gallery / media / + splash-style app types render through DIFFERENT composables in preview + (`ui/gallery/`, `ui/media/`) vs generated APKs (`ui/shell/`). A flag that flows + end-to-end still does nothing if the shell screen never reads it (gallery + thumbnail bar shipped config + assets correctly and still rendered nothing, + #781). `ShellUiParityTest.kt` enforces this: every model field read by host + runtime UI must also be read by shell runtime UI. If you add a field and read + it in a host player, the test fails naming the field until you port the + behavior to shell or add an explicit `allow` entry with a reason. When adding + a new per-type player pair, extend its `pairs` list the same way. + +Missing any step usually yields: editor shows the switch, export ignores it, or export embeds config the runtime never reads. + +### 3. Change shell runtime behavior used by every generated app + +1. Edit the source under `app/` (shared runtime). +2. Confirm the file is included by `syncShellRuntimeSources`. +3. Rebuild shell template if you need to validate packaging. +4. Keep changes surgical; shell has a low targetSdk and a thin dependency set. +5. If you touch FGS / notification channel creation, fail soft via `SafeNotificationChannels`. + +### 4. Add a host-only feature (editor, market, tooling) + +1. Keep implementation under host-only packages (`core/apkbuilder`, host screens, sample/market, `core/host`, …). +2. Do not pull host-only deps into `shell/build.gradle.kts`. + +### 5. Touch APK export or incremental rebuild + +1. Prefer `ApkBuildCache` / content hashes over timestamps. +2. Encrypted builds stay full rebuild. +3. Do not use signed outputs as templates. +4. If template bytes change, ensure cache keys invalidate correctly. + +### 6. Change notifications / engines / network hardening + +1. Prefer existing channel abstractions (polyfill / polling / WebSocket / FCM). +2. Do not add OEM push SDKs by default. +3. FGS channel create paths must tolerate OEM/channel failures. + +### 7. Module Market / `modules/` + +1. Follow `modules/README.md` catalog layout (`registry.json` + module folders). +2. Runtime consumption still goes through the extension/shell paths if it ships inside generated APKs. + +### 8. Fix "works in preview, broken after export" + +Checklist in order: + +1. Did shell config JSON actually contain the field at runtime? +2. Does the field name in `ApkConfig` JSON match the `@SerializedName` in shell config? Run `checkConfigFieldDrift`. +3. Is the runtime use site shell-synced (not host-only)? +4. For adblock: confirm `adBlockEnabled` mapping, host filter rebuild from cached subscriptions, and export rule compile without wiping host state. +5. Rebuild template after sync changes (stale template is a frequent miss). + +### 9. Local server runtime / download path + +1. Allocate ports through `PortManager` with the configured conflict policy; implement real stop handlers. +2. Wire fork+exec processes into `LocalDnsBridgeProxy` when they need host DNS/proxy env. +3. Use `NetworkModule.downloadClient` for large dependency / engine / runtime downloads. +4. Launch processes through `HostProcessLauncher` (`core/linux`) so W^X hosts (targetSdk ≥ 29) degrade to the user-mode static exec loader instead of crashing. + +### 10. Node.js / Go export + +1. Node.js: ensure `injectNodeJsNativeLibs` embeds `libnode_bridge.so` + `libnode.so` (16KB-aligned via `ElfAligner16k`) + `libc++_shared.so`. Node binary resolution prefers `nativeLibraryDir`, falls back to download cache. +2. Go: ensure `injectGoExecLoaderNativeLib` embeds `libgo_exec_loader.so`. +3. Go host-side builds never run the multi-process `go build` driver: `GoDirectBuilder` replays `compile`/`asm`/`link` as single-shot processes through `HostProcessLauncher` (user-mode static exec loader on W^X hosts), with a content-keyed persistent package archive cache (#796). +4. `NodeService` runs in a dedicated `:nodejs` OS process so V8 lifecycle is isolated from the host. + +### 11. Change a feature that has an Agent tool + +The in-app Agent exposes up to 57 tools — 52 base + 2 plan-mode + 3 imagery (imagery only load with an image-capable model; see `ToolRegistryFactory.build()`) — that wrap host service classes. When you change a feature, trace the tool chain: + +```text +LLM response (tool_calls) + → AgentEngine.executeToolCall() + → PermissionPrompter (write tools ask user; read-only run silently) + → Tool.execute(args, ctx) + → Service class (ApkBuilder, AppExporter, PortManager, EngineManager, AdBlocker, …) + → ToolResult → back to LLM +``` + +Checklist when touching a feature that an Agent tool wraps: + +1. **API signature drift.** If the service class constructor, method signature, or return type changes, update the tool's `execute()` in `app/.../agent/tool/builtin/`. A stale call compiles only if the old overload still exists; otherwise it's a build break. +2. **`parametersSchema` ↔ `execute()` alignment.** The JSON schema advertised to the LLM must match what `execute()` actually reads from `args`. Adding a parameter to the service call without exposing it in the schema means the LLM can never pass it. +3. **`description` accuracy.** The LLM decides *when* and *how* to call a tool solely from `description` + `parametersSchema`. If the feature's behavior changed, update the description text — a misleading description causes silent misuse. +4. **`isReadOnly()` correctness.** `true` → runs without user confirmation; `false` → triggers `PermissionPrompter` dialog. If a tool gains write side-effects, flip it to `false`. +5. **Registration.** New tools must be added to `ToolRegistryFactory.baseTools()` (grouped by domain comment). Forgotten registration = tool invisible to the LLM. +6. **Removed features.** If a feature is deleted, remove or disable its tool. A tool that calls a dead class crashes at runtime inside the agent loop. +7. **Host-only.** Agent tools live under `core/agent/` and are never shell-synced. Do not add them to `syncShellRuntimeSources`. + +Key paths: + +| Concern | Path | +|---------|------| +| Tool interface | `app/.../agent/tool/Tool.kt` | +| Tool registry | `app/.../agent/tool/ToolRegistryFactory.kt` | +| Tool context (services access) | `app/.../agent/tool/ToolContext.kt` | +| Built-in tools (by domain) | `app/.../agent/tool/builtin/*.kt` | +| Agent loop / execution | `app/.../agent/engine/AgentEngine.kt` | +| Permission prompt (Channel-based) | `app/.../agent/permission/PermissionPrompter.kt` | +| LLM provider (SSE streaming) | `app/.../agent/llm/OpenAiCompatProvider.kt` | + +### 12. Change editor config-card UI (Compose) + +The editor screens are built from `DkcSettingCard`s that share one visual grammar. The activation-card series (issue #567: PRs #568 → #571 → #573 → #574) took four attempts because each round invented layout instead of copying the neighbours, and each round was only compile-checked. A short prompt like "改一下 XX 卡的 UI" still means: follow these rules. + +**Copy, don't invent.** Before writing any card, open the reference implementation on the same screen and mirror it element by element: + +| You are writing… | Copy from (`CreateAppWebViewCards.kt`) | +|------------------|----------------------------------------| +| Toggle-headed feature card | `FullscreenModeCard` | +| Collapsible card with `DkcChoiceRow` header | `BrowserAdvancedConfigCard` | +| Radio group (single-choice) | PWA offline-strategy selector in `sectionOfflinePerformance` | +| Sub-toggles / fields inside an expanded zone | `staticAssetPack` block, proxy block | +| Nested conditional content | proxy MANUAL/PAC `AnimatedVisibility` swap | + +Inputs and dialogs follow the same grammar: text inputs are `PremiumTextField`, list-manager dialogs are `Dialog` + `DkcCard` + embedded `TopAppBar` (see `AdBlockSubscriptionSelectorDialog`), and `ActivationCodeCard`'s offline-policy rows are another canonical radio reference. + +Hard rules learned the hard way: + +1. **Two sanctioned card shapes.** Toggle header: `DkcSettingCard { DkcToggleRow(header); AnimatedVisibility(enabled, CardExpandTransition/CardCollapseTransition) { Column { DkcSectionDivider(); full-bleed rows separated by more dividers } } }`. Collapse header: `DkcSettingCard { Column { DkcChoiceRow(header); AnimatedVisibility(expanded) { Column(padding(horizontal = DkcSpacing.RowHorizontal, vertical = DkcSpacing.ContentGap), spacedBy(DkcSpacing.ContentGap)) { … } } } }`. +2. **Alignment grid.** `DkcToggleRow` / `DkcChoiceRow` are full-bleed rows carrying their own 16dp padding. Anything that is *not* a row — text fields, radios, group labels, buttons, notes — must sit inside a `Column(padding(horizontal = DkcSpacing.RowHorizontal, vertical = DkcSpacing.ContentGap))` zone. Sub-toggles inside a zone double-indent (16dp zone + 16dp row); that matches the reference, do not "fix" it. Group labels are `Text(style = labelMedium, color = primary)`, not `DkcSection`. +3. **Radio groups** are exactly: `Text(labelMedium, primary)` label, then `Row(fillMaxWidth().clip(MaterialTheme.shapes.small).clickable { … }.padding(vertical = 4.dp)) { RadioButton; Spacer(4.dp); Text(bodySmall) }`. Never wrap a radio group in `DkcSection`, never attach per-option prose. +4. **Card headers carry title + icon only.** No subtitle on the header row, no free-floating description text next to it. Subtitles belong on child rows that genuinely need one (e.g. 显示状态栏). +5. **Expansion state ≠ feature state.** Never bind a section's `isExpanded` / `AnimatedVisibility(visible=…)` to the feature's `enabled` flag — expanding a panel must never switch the feature on. Section collapse state is its own `remember { mutableStateOf }`. +6. **Conditional sub-blocks** (mode swaps, dependent fields) use `AnimatedVisibility` with `CardExpandTransition` / `CardCollapseTransition`, never bare `if` inside the card body. +7. **Compile ≠ verified.** After any card UI change, build + install on the emulator and check the rendered card: `uiautomator dump` element bounds, compare left edges / row heights of the changed card against its neighbours on the same screen (they must share the same content columns), plus a screenshot pass. Content a few dp off the grid is invisible in code review and obvious on screen. +8. **If a UI rework PR gets "this doesn't match the other cards" feedback**, the fix is realignment to these patterns, not further invention. + +--- + +## Easy-to-miss points + +- **Keyboard avoidance below API 30 requires the classic window path.** Android 10 and lower have no native IME-inset dispatch: an edge-to-edge window (`decorFitsSystemWindows = false`) is never resized for the keyboard and reports zero IME insets, so no `softInputMode` value helps there. `WindowHelper.applyImmersiveFullscreen` therefore keeps the decor fitting system windows on the RESIZE keyboard path below API 30 (system `SOFT_INPUT_ADJUST_RESIZE` works) and degrades TRANSPARENT/IMAGE status-bar styles to solid colors on that path. Do not re-enable edge-to-edge unconditionally for those devices (#613; #634 flipped only the softInputMode bits and fixed nothing — its Robolectric test passed because it never asserted the layout flags). +- **Shared sources are authored in `app/`.** Editing only a file under `shell/src` is usually wrong; it will be overwritten on sync or diverge from host. +- **Config field names drift.** Editor model, `ApkConfig`, JSON factory, and shell config must stay aligned; Gson silently drops unknown/missing fields. Run `checkConfigFieldDrift`. +- **Low targetSdk (28) and fork/exec runtimes** constrain "modernize the shell SDK" changes. +- **Incremental export cache** keys must be content-based; mtime and resigned APKs create false hits/misses. +- **HTML/FRONTEND file access.** Packaged local-file shells must have `allowFileAccess = true` (forced in `buildWebViewBlock` and `ShellWebViewConfig`); do not regress pure file-based HTML loads. +- **Node native libs.** Exported NODEJS_APP needs `libnode_bridge.so` + `libnode.so` + `libc++_shared.so`; missing any causes `loadNode` / `loadJniBridge` failure at runtime. +- **16KB page alignment.** `libnode.so` and other large ELF natives must be 16KB-aligned (`ElfAligner16k`) for Android 15+ devices; `node_bridge.cpp` / `node_launcher.c` enable 16KB app-compat before `dlopen`. +- **Node JNI output bridge.** `NodeJniOutputBridge` is a stable class referenced by native code; keep its `-keep` proguard rule so R8 does not rename `onOutput`. +- **Crashing FGS when notification channel creation fails.** Always use `SafeNotificationChannels` for channel creation. +- **Adblock is wired for preview + export.** Do not wipe host filter state during export; the host AdBlocker serves preview and the compiled rule set ships in the APK. +- **Runtime permissions are feature-driven.** `RuntimePermissionSync` derives the permission list from enabled features; do not revert to a static template. +- **Splash preview media path.** Preview reads splash media from the host filesystem (`splashMediaPath`); export packages it into assets. Do not hardcode `assets/splash_media.*` as the only source. +- **Host player UI ≠ shell player UI.** Preview players (`ui/gallery/`, `ui/media/`) and generated-APK players (`ui/shell/`) are separate composables sharing only the config. Port every visible behavior across (thumbnail bar, background, keep-screen-on, orientation) and let `ShellUiParityTest` verify the flags; config flowing end-to-end is necessary but not sufficient. +- **Port conflict policy.** Local server runtimes must allocate through `PortManager` and clean up on stop; do not bind ports directly. +- **Agent tool ↔ service drift.** When a service class API changes, the corresponding Agent tool in `core/agent/tool/builtin/` must be updated in the same PR. A stale tool either fails to compile or silently passes wrong arguments at runtime. Check `ToolRegistryFactory.baseTools()` for the full tool list. +- **Editor card UI grammar.** Config-screen cards share one layout grammar (recipe 12): rows are full-bleed, non-row content sits in 16dp-padded zones, expansion never toggles the feature, and card UI is verified on the emulator — not just compiled. + +--- + +## Forbidden / high-risk mistakes + +- Second shell template APK +- Excluding a shell-synced class but leaving imports/constructors in shell-synced sources +- Re-enabling shell R8 obfuscation / aggressive shrink without testing exported apps +- Putting host-only tools back into shell sync for convenience +- OEM push SDKs or unjustified heavy dependencies in shell +- Feeding signed/renamed APKs into template/modify paths +- Crashing FGS when notification channel creation fails +- Committing secrets, keystores, or local machine config +- Regressing HTML/FRONTEND file access in packaged shells +- Shipping a host player-screen feature without its shell counterpart (preview-only UI) +- Shipping NODEJS_APP without `libnode_bridge.so` / `libnode.so` / `libc++_shared.so` +- Skipping 16KB alignment for large ELF natives +- Inventing editor card layout/spacing/animations instead of copying the neighbouring cards' patterns, or shipping card UI verified only by compilation + +--- + +## Verify commands + +```bash +./gradlew :shell:assembleRelease :app:syncShellTemplateApk --no-configuration-cache +./gradlew :app:compileStandardDebugKotlin -x syncCloneHostDex --no-configuration-cache +./gradlew :app:checkConfigFieldDrift --no-configuration-cache +python3 scripts/check_config_field_drift.py +``` + +Use these when you change shell membership, export packaging, or config fields. For host-only UI/string work, targeted compile on `:app` is usually enough. + +CI note: the PR `check` job compiles only `:shell:compileDebugKotlin` (debug variant) and skips template sync (`-PskipShellTemplateSync=true`). The shell **release** variant (R8 / proguard) and the template pipeline are exercised only by the manual `workflow_dispatch` packaging job — after touching `shell/proguard-rules.pro` or shell packaging, run the first command locally before pushing. + +Related focused tests often worth running after nearby edits: `ApkBuildCacheTest`, `AdBlockerHostRuntimeTest`, `AdBlockExportWiringTest`, `PortManagerTest`, `BuildInputPreflightTest`, `GoBuildEnvironmentTest`, `RuntimePermissionSyncTest`. + +--- + +## Implementation snapshot + +Landed: + +- Single shell template (`webview_shell.apk`) from `:shell` release, full runtime synced from `app/` +- Incremental `ApkBuildCache` (`FULL` / `CONTENT_OVERLAY` / `REUSE_UNSIGNED`); encrypted builds always full +- Notification channels: polyfill, polling, WebSocket, FCM (BYO Firebase) via existing abstractions +- `SafeNotificationChannels` fail-soft path for FGS +- `PortManager` conflict policies + real stop handlers across Node/PHP/Python/Go/WordPress +- `LocalDnsBridgeProxy` wiring for local server runtimes (including Node.js) +- Runtime downloads via `NetworkModule.downloadClient` +- Adblock preview + export wiring restored +- HTML/FRONTEND file-access for packaged local shells +- Node.js export: `libnode_bridge.so` + 16KB-aligned `libnode.so` + `libc++_shared.so`; 16KB app-compat before dlopen; stable `NodeJniOutputBridge` JNI callback +- Go export: `libgo_exec_loader.so` embedded; in-app build ENOSPC handling + GOTMPDIR relocation +- Go host-side builds on W^X hosts: `GoDirectBuilder` replays `compile`/`asm`/`link` as single-shot processes through `HostProcessLauncher` (user-mode static exec loader), with a content-keyed persistent package archive cache (#796) +- Multi-web: gallery/media site sources embedded into the APK and resolved at runtime; nested site sources degrade to a URL instead of aborting the build (#798, #792) +- Gallery playback: shuffleOnLoop, rememberPosition, overview grid, thumbnail bar, pinch-to-zoom viewer, with host/shell parity enforced by `ShellUiParityTest` (#781, #786, #801) +- Untrusted bitmap decodes bounded (oversized-image crash fix) (#788) +- Backup/restore coverage aligned with the current storage layout; restarts only when local files change, with throttled progress callbacks (#790, #794) +- NativeBridge enabled by default for newly created apps (#805) +- Runtime permission sync (feature-driven) +- Splash preview media path fallback +- Config field drift detection (`checkConfigFieldDrift`) +- Module Market: Chrome Web Store live search + GreasyFork browse +- Code editor find-and-replace +- Security hardening sweep: TLS-fingerprint bridge validates upstream certs (system + custom CAs + hostname) and its local CA is signature-verified with no error-type fallback; JS bridges are caller/origin/scheme-gated (NativeBridge CORS bypass, GM bridge, MV3 `ChromeHostPermissions`); MITM proxy host-allowlisted and CA key wrapped at rest; zip extraction routed through `util/SafeZip`; concurrent exports serialized per package with per-package work dirs; multi-web server-runtime site sources degrade to URL; PHP/Python/WP embed failures fail the build; error pages and `TranslateBridge` callbacks JSON-escaped; keystore password sidecars excluded from backups +- Agent tool system: up to 57 tools — 52 base + 2 plan-mode + 3 imagery (image-capable models only) — covering app lifecycle, config templates, ports/engine, hosts/runtime, stats/modifier/import, build env/Play, modules, files, and imagery, with Channel-based permission prompting, per-section SSE parse resilience, and plan mode; runtime/build-env tools surface `localExecAllowed` so the LLM knows targetSdk>=29 hosts cannot exec app-storage binaries diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fdddb29 --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +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. + +For more information, please refer to diff --git a/README.md b/README.md new file mode 100644 index 0000000..ceab9dc --- /dev/null +++ b/README.md @@ -0,0 +1,365 @@ +
+ +DruksCode icon + +# DruksCode + +### Build Android APKs from web projects, directly on your phone. + +**An on-device APK workshop that goes far beyond URL wrapping — it can fork and exec full server runtimes, ship a hardened anti-censorship network stack, sign bundles for Google Play, and run MV3 browser extensions, all without a PC or a remote build server.** + +**English** · [简体中文](.github/docs/README_CN.md) + +

+ + Stars + + + Forks + + + Latest Version + +

+ +

+ + shiaho777%2Fdrukscode | Trendshift + +

+ +

+ + Swiftproxy +
+ Sponsored by Swiftproxy — Swiftproxy · Reliable Residential Proxies for Web Automation +

+ +

+ What's different · + What you can build · + Capability overview · + Feature map · + Module market · + Documentation · + Architecture · + Build +

+ +--- + +
+DruksCode: My Apps home, the app list with the main toolbox (Agent, Extension Modules, Port Manager), per-app APK actions (Edit, Create Shortcut, Build/Share/Export APK), and the About screen — all running on an Android phone +
+ +--- + +## What makes DruksCode different + +Most "website to app" tools stop at wrapping a URL in a WebView. DruksCode is closer to a pocket-sized APK workshop, and the hard parts are exactly where it diverges: + +- **It runs real server runtimes on-device.** Node.js, PHP, Python, Go, and WordPress are fork+exec'd as native binaries straight from app storage — like Termux, packaged into an installable APK. URL-wrapper tools cannot do this at all. +- **It ships a hardened, anti-censorship network stack.** DNS-over-HTTPS, TLS fingerprint spoofing (Chrome / Firefox / Safari JA3 templates) with a local MITM bridge, Encrypted Client Hello (ECH) on both engines to encrypt the SNI, per-app proxies, and CORS bypass for locked-down SPAs. +- **The whole build is self-contained.** Binary AXML/ARSC patching, permission pruning, V1/V2/V3 signing, and Google Play-ready AAB export all happen inside the app via `apksig` — no remote build queue, no PC. +- **It stays extensible after shipping.** Add JS/CSS modules, Tampermonkey-style userscripts, or MV3 Chrome extensions (live-searched and installed from the Chrome Web Store) without rebuilding the host. +- **The host UI speaks 10 languages out of the box.** Chinese, English, Arabic (RTL), Portuguese, Spanish, French, German, Russian, Japanese, and Korean — switch anytime in Settings; new in-app copy is maintained for all ten. + +--- + +## Capability overview + +A quick scan of what's in the box. Each links to the detailed feature map below. + +| Area | Highlights | +| --- | --- | +| **Build targets** | Web · HTML · Frontend · WordPress · Node.js · PHP · Python · Go · Image · Video · Gallery · Multi-Web | +| **Browser engines** | System WebView by default; optional GeckoView (Firefox) runtime | +| **Network & anti-censorship** | DoH (7 providers), TLS fingerprint spoofing + MITM bridge, ECH, static/PAC/SOCKS5 proxies, CORS bypass | +| **Privacy & hardening** | 50+ vector browser fingerprint disguise, resource encryption (AES-256-GCM), anti-debug, activation gating | +| **Local runtimes** | Native Node.js 18.20, PHP 8.4 + Composer 2.10, Python 3.14, official Go 1.26, WordPress 7.x over SQLite | +| **Extensions** | Built-in modules, userscripts with `GM_*`, MV3 Chrome extensions, live Chrome Web Store search | +| **APK/AAB output** | On-device V1/V2/V3 signing, Google Play AAB export with targetSdk rewrite, keystore management | +| **Agent** | Full-app automation via up to 57 tools: generate, build, export, manage ports/engines/runtimes, clone apps, ad-block rules, config templates, and more; auto-retry on 429/5xx | +| **Host languages** | **10 UI languages** — 中文 · English · العربية · Português · Español · Français · Deutsch · Русский · 日本語 · 한국어 (Arabic RTL) | + +--- + +## What you can build + +| Input | Output | Good for | +| --- | --- | --- | +| Website URL | WebView-based APK | Landing pages, tools, dashboards, docs, internal systems | +| HTML / static front-end | Localhost-backed APK | React, Vue, Vite, static builds, offline web apps | +| Node.js / PHP / Python / Go | APK with an on-device local server | Small server apps, admin tools, demos, prototypes | +| WordPress | APK running WordPress over local PHP + SQLite | Portable sites, theme/plugin demos, content packages | +| Images / video / galleries | Media-focused APK | Albums, course materials, portfolios, offline viewers | +| Multiple sites | Tab/card/feed/drawer multi-web APK | Link hubs, portals, app collections | +| Installed APK | Rebranded clone or shortcut disguise | Icon/name/package experiments, repackaging research | + +--- + +## Full feature map + +DruksCode has a large number of switches. The sections below group them by use case, kept collapsible so the top of the page stays scannable. + +
+🌐 Browser engine & networking + +- **Dual engine** — System WebView by default, or an optional GeckoView (Firefox) runtime downloaded on first use. +- **Kernel flavor disguise** — present as Chrome, Edge, Samsung Internet, Firefox, or Safari-style while keeping the real engine. +- **Desktop mode**, custom User-Agent, and JS/CSS injection at document-start / end / idle. +- **Popup handling** — same window, external browser, popup window, or block. +- **Proxies** — static HTTP/HTTPS/SOCKS5, PAC, authentication, bypass rules, and a local HTTP-to-SOCKS bridge. +- **DNS-over-HTTPS** — Cloudflare, Google, AdGuard, NextDNS, CleanBrowsing, Quad9, Mullvad, plus custom endpoints; strict or automatic modes. +- **Encrypted Client Hello (ECH)** — encrypt the SNI in the TLS handshake on **both engines**: GeckoView via TRR + its ECH prefs, the system WebView via the MITM bridge's Chromium upstream (auto-downloaded on first use, embedded in exported APKs). Auto-wires DoH when toggled; a SOCKS upstream proxy takes precedence. +- **TLS fingerprint spoofing** — impersonate Chrome 131 / Firefox 133 / Safari 18 JA3 profiles (or custom ciphers), served through a local TLS-MITM bridge so the outgoing ClientHello matches a real browser. +- **CORS bypass** — on by default for static SPAs that call external APIs blocked by CORS; same-origin traffic is left alone, and CORS-only apps can use a lightweight `PrivateNetworkNativeBridgeAdapter` without the full Native Bridge surface. +- **Failover** — automatic fallback to mirror URLs when the primary target is unreachable. +- **PWA** offline cache strategies, custom error pages, per-app host overrides, and payment-scheme handlers. +- **Compatibility toggles** — blob download interception, scroll memory, image repair, clipboard / orientation / notification polyfills, private-network bridging, and Native Bridge capability gates. +- **Download location** — system Downloads, app-private storage, or a user-picked SAF folder, wired through the full packaging passthrough chain. + +
+ +
+🛡️ Privacy, fingerprint defense & hardening + +- **Browser fingerprint disguise across 50+ vectors** — User-Agent, WebGL, Canvas, AudioContext, ClientRects, timezone, language, memory, media devices, WebRTC, fonts, battery, permissions, performance, storage, notifications, CSS media, iframe propagation, and error-stack cleanup. +- **Hosts-rule ad blocker** with cosmetic MutationObserver filtering, **20 built-in community filter lists** (EasyList, uBlock Origin, AdGuard, AdAway, plus 8 language-specific lists), per-source enable/disable/delete, named custom filter imports managed as cards and selectable per app, and custom subscription rules bundled into the APK. +- **Resource encryption** (PBKDF2 + AES-256-GCM) for packaged config, HTML, media, and BGM; optional custom encryption password stronger than package/certificate-derived keys. +- **Runtime hardening** when encryption is on — anti-debug, anti-Frida, DEX-tamper checks; threat response of log-only, silent exit, or randomized crash. +- **WebView/content isolation** for storage, WebRTC, Canvas, Audio, WebGL, fonts, headers, and IP surfaces. +- **Activation-code gating** — local verification, or your own HTTPS endpoint signed with EC P-256. See the [remote activation docs](.github/docs/remote-activation.md). + +
+ +
+📦 Local server runtimes (fork + exec on-device) + +- **Node.js** (18.20.x) runs in a dedicated `:nodejs` OS process via a native `node_launcher` wrapper loading `libnode.so`; supports custom native `.node` extensions. +- **PHP 8.4** from `pmmp/PHP-Binaries`, downloaded once on first use, with Composer 2.10.x and custom native extensions (`zend_extension`, `.so`). +- **Python 3.14** — Flask, Django, FastAPI via uvicorn, Tornado, the built-in HTTP server; pip dependencies resolved into `.pypackages`, custom native extensions supported; binary names are versioned so future bumps do not hard-code paths. +- **Go 1.26** — official Linux arm64 toolchain (`.tar.gz` from `dl.google.com`, USTC mirror for CN), on-device `go build` / `go mod` / `go run`, `vendor/` offline builds, static serving, and the native `go_exec_loader` wrapper; DNS and CA trust go through the same local JVM bridge used by PHP. +- **WordPress 7.x** over local PHP + SQLite (`sqlite-database-integration`), with theme and plugin import. +- **Linux Environment** screen manages toolchains and dependencies for Node, PHP, and Python. +- **Port Manager** coordinates runtime ports across generated apps via broadcast receivers. +- A **local DNS bridge proxy** (HTTP CONNECT in the Android JVM) gives runtimes working DNS resolution and outbound HTTP where the musl/packed binary can't reach the system resolver. + +
+ +
+🧩 Extensions & automation + +- **Built-in modules** — video download (YouTube / Bilibili / Douyin / Xiaohongshu extractors), video enhancer with YouTube cleanup (ad skip, max quality, background play, SponsorBlock), web analyzer, find-in-page, dark mode, privacy tools, content enhancer, element blocker, and YouTube launcher. +- **Userscripts** — Greasemonkey/Tampermonkey-style `.user.js` with a `GM_*` bridge (storage, requests, styles, menu commands) and promise-based `GM.*` APIs gated by script grants. +- **MV3 Chrome extension runtime** for manifest content scripts in isolated or main worlds, with `chrome.*` polyfills for runtime, storage, tabs, scripting, and declarative network-request parsing. +- **In-app Chrome Web Store search** — browse and install browser extensions by keyword (or paste a store URL / extension ID), with offline fallback to manual import. +- **Export codes** (`DKC1:` gzip + Base64) and QR sharing via ZXing. +- **Agent** — a tool-calling assistant with up to 57 built-in tools covering the entire app surface: create/edit/build/export apps, manage ports and browser engines, install/clear runtimes, ad-block hosts rules, common-config templates, usage stats, app cloning, batch import, Play policy checks, and module development. Plan mode waits for user approval; automatic retry/backoff on 429/5xx. + +
+ +
+📱 App experience + +- **Splash screens** — image or video, with skip behavior, trim ranges, and fixed orientation. +- **Background music** — playlists with synced LRC lyrics, lyric animations, custom font/color/stroke/shadow, and online music search. +- **Toolbar, status bar (light & dark), navigation, floating-window mode, and long-press menu styles.** The browser toolbar is a master toggle (off by default) with per-item buttons for title/URL/back/forward/refresh plus a native **find-in-page** bottom bar and a **console** panel for on-device debugging. Status bar color can follow theme, a custom color, full transparency, or **PAGE_TOP** (sample the page’s top pixels so the chrome matches the content). +- **Download location mode** — system Downloads, app-private directory, or a custom SAF folder picked by the user. +- **Announcement templates** for launch, interval, and no-network moments. +- **Host app language** — switch the entire builder UI among 10 languages (中文 / English / العربية / Português / Español / Français / Deutsch / Русский / 日本語 / 한국어); Arabic is full RTL. +- **Translation overlay** — 20 target languages via Google, MyMemory, LibreTranslate, or Lingva engines, with automatic failover across them (in-page translate for the *content* of generated apps, separate from host UI language). +- **Print bridge** — intercept `window.print()` and blob/data-URL PDFs to the Android print framework / PDF export (with an onPageStarted re-inject fallback so late navigations stay hooked). +- **Media Session bridge** — surface web media on the system media notification and lock-screen controls, with Bluetooth and Android Auto support. +- **Notifications** — Web Notification polyfill, scheduled and persistent notifications with progress, URL-polling foreground service, deep links, boot auto-start, scheduled launch, and background-run service. +- **Per-app usage stats** with Vico charts and URL health monitoring. + +
+ +
+🔧 APK / AAB export & signing + +- **Custom package name**, `versionName`, `versionCode`, icon, label, architecture target, and export format. +- **Build-time permission injection** with unused permissions pruned from the template manifest. +- **One-tap AAB export** — auto-builds the APK on demand, converts it to a Play-ready signed AAB with `targetSdk` rewritten to the Play-required level (currently 36) and protobuf metadata generated locally; cancellable mid-build. +- **Keystore management** — create, import, export, delete, and certificate-fingerprint viewing; PKCS12/PFX/JKS/BKS import including Android Studio upload-key cases where store and key passwords differ. +- **Signature schemes** — V1, V2, V3 independently controlled, with auto-fallback for legacy certificates; custom V1 signer filename for `META-INF/.SF` / `.RSA`. +- **Performance options** — image compression, WebP conversion, code minification, lazy loading, DNS prefetch, and preload hints. +- **Full project and app-data backup/restore.** + +
+ +
+🗂 File manager & project tooling + +- **File manager** — a single screen to view, share, install, open, and clear build outputs (APK builds, AAB exports, app clones, build logs) and a user-files directory, with a read-only build-log viewer. +- **Website scraper** for offline packs — HTML, CSS, JS, images, fonts, `url()`, `srcset`, `@import`, path rewriting, same-domain limits, depth limits, and size limits; parallel streaming worker pool with main-thread progress callbacks. +- **Multi-Web layouts** — tabs, cards, feeds, drawers, per-site icons/theme colors/extraction selectors/refresh intervals, and shared JS/CSS. +- **Gallery apps** — categorized media, grid/list/timeline views, shuffle/single-loop, sorting, thumbnail bar, overlays, auto-next, and playback memory. +- **App Modifier** — shortcut disguise or real binary clone with manifest/resource patching and re-signing. + +
+ +
+🔬 Specialized tools & research features + +- **Device disguise** is included for technical demonstration and must only be used with informed user consent. + +
+ +--- + +## Agent + +DruksCode ships a built-in AI agent (open from **⋮ → Agent**) that can operate the entire app through natural-language conversation. Instead of tapping through menus, you describe what you want and the Agent executes it via a tool-calling loop backed by any LLM you configure in [AI Settings](#tech-stack) — Chat Completions, Anthropic Messages, or OpenAI Responses endpoints, plus Google Gemini and Ollama / LM Studio / VLLM locals. + +**How it works:** + +1. You send a message (or attach an image for visual context). +2. The LLM reasons and emits `tool_calls`. +3. The Agent executes each tool on-device — read-only tools run immediately; write tools pop a permission dialog first. +4. Results flow back to the LLM, which continues until the task is done or it asks you a clarifying question. + +**Up to 57 built-in tools, grouped by domain (the 3 imagery tools load only with an image-capable model):** + +| Domain | Examples | +| --- | --- | +| Files | Read, Write, Edit, Delete, List, Glob, Grep project files | +| Apps | List, Get, Create, Update app configurations | +| App lifecycle | Build APK/AAB, Export, Share, Create shortcut, Duplicate, Delete, Move to category | +| Ports & engines | Scan/kill ports, check/select/delete browser engines (WebView, GeckoView) | +| Runtimes | Status, install, and cache-clear for Node.js, PHP, Python, Go, WordPress, Linux env | +| Ad-block | Rule counts, import/remove/enable/disable hosts subscriptions | +| Stats & health | Usage statistics, URL health checks | +| App modifier | List installed apps, clone/rebrand, batch import, export templates | +| Build env & compliance | Initialize Linux build env, install components, Google Play policy checks | +| Modules | List, create, update extension modules | +| Interaction | Ask user questions (multi-select), plan mode (propose → approve → execute), todo tracking | + +--- + +## Module market + +DruksCode has a GitHub-backed module market for community JS/CSS extension modules. The catalog is just files in this repository, so contributions use a normal pull-request flow. + +``` +modules/ +├── registry.json # app-facing catalog +├── submissions.json # CI-generated PR / contributor metadata +├── README.md # contributor guide +└── / # each module +``` + +The app fetches both `registry.json` and `submissions.json` and only shows modules present in both, keeping the in-app catalog aligned with actually-merged PRs. The submissions file also records every contributor per module, so the catalog shows stacked avatars and a contributors leaderboard. Catalog files and module icons route through a global mirror first, with `raw.githubusercontent.com` and jsDelivr as automatic fallbacks, so the store loads fast everywhere (including mainland China). + +- Users open **Extension Modules** and tap the storefront icon. +- Contributors add a folder under `modules/`, update `registry.json`, and open a PR. +- The default client cache is one hour, so merged modules propagate without an app update. + +The high-level architecture lives here; the canonical submission rules, field schemas, reviewer checklist, and CI validation details live in [`modules/README.md`](modules/README.md). + +The community market carries only JS/CSS extension modules. **Browser extensions (MV3)** are no longer a community catalog — instead the **Browser Extensions** tab searches the Chrome Web Store live: type a keyword, browse results, and install on demand through the existing CRX pipeline. Live search requires a network that can reach Google. + +## Documentation + +The official documentation site is published at **[shiaho777.github.io/web-to-app](https://shiaho777.github.io/web-to-app/)**, in English and 简体中文: + +| Section | URL | Covers | +| --- | --- | --- | +| Guide | [/guide/introduction](https://shiaho777.github.io/web-to-app/guide/introduction) | Getting started, main screen, app types, per-app actions and common config, FAQ | +| Developer | [/developer/](https://shiaho777.github.io/web-to-app/developer/) | Architecture, export pipeline, shell sync, config drift, i18n, change recipes | +| Extensions | [/extensions/](https://shiaho777.github.io/web-to-app/extensions/) | JS/CSS modules, userscripts, Chrome MV3, API reference, publishing | +| 简体中文 | [/zh/](https://shiaho777.github.io/web-to-app/zh/) | Full Chinese mirror of every page above | + +## Architecture + +- The repository has **three Gradle modules**: `app` (the full builder and host), `shell` (the runtime host embedded into generated APKs), and `clone-host` (host code for app cloning — compiled to a `classes.jar`, converted to DEX via d8, and bundled as an asset for `AppCloner`). +- Runtime code is authored in `app` and synchronized into `shell`, so shared WebView/runtime behavior has one source of truth (`core/shell`, `core/webview`, `core/engine`, `core/extension`, `ui/shell`, etc.). +- The APK builder patches template APKs at the binary AXML/ARSC level, injects config/resources, prunes permissions, and signs with `apksig`. A separate encrypted build path (`EncryptedApkBuilder`) offers resource encryption, shelling, and integrity checks. +- Generated APKs pin `targetSdk = 28` deliberately (via the shell template) — it is what lets them fork+exec native runtimes (Node.js, PHP, Python, Go, WordPress) from app storage, a capability URL-wrapper tools lack. The host app itself targets 35 (antivirus engines flag low-targetSdk builds as legacy malware); SELinux W^X at that level blocks host-side preview of the exec-based runtimes, which degrade with an explicit message — Node.js preview (JNI) and every exported app are unaffected. For Play Store distribution the AAB exporter separately rewrites `targetSdk` to the Play-required level (currently 36). WebView-only app types (Web/HTML/Frontend/Gallery/Media/MultiWeb) can also opt to raise the standalone APK's `targetSdk` (34/35/36) from the APK export section; server-runtime types are gated to 28 because `targetSdk >= 29` enforces W^X and breaks fork+exec of the bundled binaries. +- Server runtimes and the optional GeckoView native libraries (`.so` + `omni.ja`) are downloaded on first use rather than bundled into the base APK; the GeckoView API classes come from a gradle dependency, while the heavy native artifacts are fetched on demand. +- The configuration center is `WebApp` (`data/model/WebApp.kt`) and its `*Config` classes — the single source of truth for all feature settings, carried through a full packaging passthrough chain into the generated APK. + +## Tech stack + +- Kotlin, Jetpack Compose, Material 3 +- Koin for dependency injection +- Room 2.7.2 + KSP for persistence +- OkHttp 4.12.0 + `okhttp-dnsoverhttps` +- `com.android.tools.build:apksig` 8.3.0 for APK signing +- BouncyCastle 1.78.1 for crypto and signing +- `protobuf-javalite` 3.25.5 for AAB metadata +- Firebase Cloud Messaging (BYO Firebase config) for push notifications +- GeckoView as an optional browser engine (native libs downloaded on first use) +- Coil for image/video/GIF loading +- Haze for blur/glassmorphism UI +- Gson for JSON serialization (shell config pipeline) +- AndroidX Security Crypto + DataStore for stored secrets +- Vico Compose-M3 for charts +- ZXing for QR sharing +- Apache Commons Compress + xz for project import and website scraping +- Native C++ via JNI for `node_launcher` and `go_exec_loader` +- Robolectric for unit tests + +See [app/build.gradle.kts](app/build.gradle.kts) for the complete dependency list. + +## Build from source + +Requirements: Android Studio Hedgehog or newer, JDK 17. The Gradle wrapper pins Gradle 9.4.1. + +```bash +git clone https://github.com/shiaho777/web-to-app.git +cd drukscode +./gradlew assembleDebug +``` + +For release builds, configure signing through `local.properties` and `app/build.gradle.kts`. + +## Contributing + +| Lane | What you do | Guide | +| --- | --- | --- | +| `modules/` | Publish a community module to the in-app market | [modules/README.md](modules/README.md) | +| Issues | Report a bug or request a feature | [GitHub Issues](https://github.com/shiaho777/web-to-app/issues) | +| Code | Fix a bug or build a feature in the Android client | [CONTRIBUTING.md](.github/CONTRIBUTING.md) | +| `AGENTS.md` | Authoritative guide for AI coding agents and deep contributors (architecture, shell sync, export pipeline, config drift, packaging constraints) | [AGENTS.md](AGENTS.md) | + +## Contact + +Developed by **shiaho**. + +| Platform | Link | +| --- | --- | +| GitHub | [github.com/shiaho777/web-to-app](https://github.com/shiaho777/web-to-app) | +| Telegram | [t.me/webtoapp777](https://t.me/webtoapp777) | +| X (Twitter) | [@shiaho777](https://x.com/shiaho777) | +| Bilibili | [b23.tv/8mGDo2N](https://b23.tv/8mGDo2N) | +| QQ Group | 1041130206 | + +## License + +[The Unlicense](LICENSE). + +Advanced features such as device disguise are intended for technical demonstration and must only be used with informed user consent. + +## Acknowledgements + +[daoxe.com](https://daoxe.com) — AI API relay for personal use. + +

+ + Swiftproxy — Residential Proxies from $0.7/GB, ISP Proxies $6/IP, 10% off code: PROXY90 + +

+ +

+ Sponsored by Swiftproxy — Swiftproxy provides 90M+ clean residential IPs across 220+ locations, supporting HTTP(S) and SOCKS5 proxies, flexible targeting, rotating and sticky sessions, and non-expiring traffic. It helps DruksCode users with reliable global access, location-based testing, web automation, and data collection. Free testing is available, with 10% off using code PROXY90. +

+ +--- + +
+ +**Open source · Built for Android power users · Star to support the project** + +
diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 0000000..2796108 --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,701 @@ +import java.util.Properties +import java.util.zip.ZipFile +import org.gradle.api.DefaultTask +import org.gradle.api.GradleException +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputDirectory +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity +import org.gradle.api.tasks.TaskAction + +plugins { + id("com.android.application") + id("org.jetbrains.kotlin.android") + id("com.google.devtools.ksp") + id("org.jetbrains.kotlin.plugin.compose") + id("com.google.protobuf") +} + +ksp { + arg("room.schemaLocation", "$projectDir/schemas") +} + +val localProperties = Properties().apply { + val file = rootProject.file("local.properties") + if (file.exists()) { + file.inputStream().use { load(it) } + } +} + +val releaseSigningStoreFile = localProperties.getProperty("signing.storeFile") + ?.takeIf { it.isNotBlank() } + ?.let { rootProject.file(it) } +val hasReleaseSigningConfig = releaseSigningStoreFile?.isFile == true && + !localProperties.getProperty("signing.storePassword").isNullOrBlank() && + !localProperties.getProperty("signing.keyAlias").isNullOrBlank() && + !localProperties.getProperty("signing.keyPassword").isNullOrBlank() + +android { + + signingConfigs { + if (hasReleaseSigningConfig) { + create("release") { + storeFile = releaseSigningStoreFile + storePassword = localProperties.getProperty("signing.storePassword") + keyAlias = localProperties.getProperty("signing.keyAlias") + keyPassword = localProperties.getProperty("signing.keyPassword") + } + } + } + namespace = "br.com.drukstech.codeapp" + compileSdk = 36 + + defaultConfig { + applicationId = "br.com.drukstech.codeapp" + minSdk = 23 + + targetSdk = 35 + versionCode = 62 + versionName = "2.6.0" + buildConfigField("boolean", "SHELL_RUNTIME_ONLY", "false") + + vectorDrawables { + useSupportLibrary = true + } + + ndk { + abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64") + } + + externalNativeBuild { + cmake { + cppFlags += "-std=c++17" + arguments += "-DANDROID_STL=c++_shared" + } + } + } + + flavorDimensions += "distribution" + productFlavors { + create("standard") { + // Sideloaded variant (GitHub releases, keeps `br.com.drukstech.codeapp` for the existing + // update path). Identical to gplay in every way except the applicationId — + // both inherit targetSdk 35 from defaultConfig and run the same code paths + // (runtime capability gates key off the installed targetSdk, not the channel). + } + create("gplay") { + // Google Play variant. Only Play's applicationId requirement differs + // (`br.com.drukstech.codeapp` is registered on Google Play by another party); behavior, + // targetSdk and every build rule are shared with the standard flavor. + applicationId = "br.com.drukstech.codeapp.play" + } + } + + externalNativeBuild { + cmake { + path = file("src/main/cpp/CMakeLists.txt") + version = "3.22.1" + } + } + + buildTypes { + release { + isMinifyEnabled = true + isShrinkResources = true + signingConfig = if (hasReleaseSigningConfig) { + signingConfigs.getByName("release") + } else { + val allowDebugSigned = (project.findProperty("allowDebugSignedRelease") as? String) == "true" + if (allowDebugSigned) { + + signingConfigs.getByName("debug") + } else { + throw GradleException( + "Release build has no valid signing config. Configure signing.storeFile / " + + "signing.storePassword / signing.keyAlias / signing.keyPassword in local.properties " + + "before assembling a release APK for distribution. Refusing to silently sign with " + + "the debug key — a debug-signed release breaks upgrades for existing users " + + "('signatures do not match'). For a throwaway debug-signed build (e.g. CI smoke " + + "build, never distribute it), pass -PallowDebugSignedRelease=true." + ) + } + } + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + + splits { + abi { + isEnable = false + } + } + + bundle { + language { + enableSplit = false + } + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = "17" + } + + buildFeatures { + compose = true + buildConfig = true + } + + testOptions { + unitTests { + isIncludeAndroidResources = true + } + } + + lint { + + disable += "NullSafeMutableLiveData" + + disable += "ExpiredTargetSdkVersion" + disable += "ExpiringTargetSdkVersion" + disable += "OldTargetApi" + + abortOnError = false + } + + packaging { + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + // Gecko omni.ja is downloaded on demand, never bundle it in host. + excludes += "assets/omni.ja" + excludes += "**/omni.ja" + // BouncyCastle post-quantum experimental blobs (~1.2M), unused. + excludes += "**/org/bouncycastle/pqc/**" + // Django gettext sources (~5.9M raw): the Python runtime only reads + // compiled .mo files, .po never ships in a working install. + excludes += "**/*.po" + } + + jniLibs { + useLegacyPackaging = true + + excludes += "**/libxul.so" + excludes += "**/libmozglue.so" + excludes += "**/libgeckoffi.so" + excludes += "**/libmozavutil.so" + excludes += "**/libmozavcodec.so" + + excludes += "**/libgkcodecs.so" + excludes += "**/libminidump_analyzer.so" + excludes += "**/libnss3.so" + excludes += "**/libfreebl3.so" + excludes += "**/libsoftokn3.so" + excludes += "**/liblgpllibs.so" + excludes += "**/libplugin-container.so" + + excludes += "**/libcrypto_engine.so" + + // Cronet natives are downloaded on demand / injected per-export, never bundled. + excludes += "**/libcronet*.so" + } + } + androidResources { + // Keep "" semantics (include dot-dirs like .pypackages) while dropping + // Django gettext sources (*.po, runtime reads .mo only) and Gecko's + // omni.ja (downloaded on demand). packaging.resources.excludes does + // NOT cover assets, hence aapt-level filtering (verified by APK audit). + ignoreAssetsPattern = "*.po:*.ja" + + localeFilters += listOf("zh", "en", "ar") + } +} + +val shellTemplateOutput = project(":shell").layout.buildDirectory.file("outputs/apk/release/shell-release.apk") +val skipShellTemplateSync = providers.gradleProperty("skipShellTemplateSync").map(String::toBoolean).orElse(false) + +tasks.register("syncShellTemplateApk") { + description = "Builds the dedicated shell template APK and copies it into the app assets." + group = "build" + dependsOn(":shell:assembleRelease") + from(shellTemplateOutput) + into(file("src/main/assets/template")) + rename { "webview_shell.apk" } +} + +tasks.matching { it.name == "preBuild" }.configureEach { + if (!skipShellTemplateSync.get()) { + dependsOn("syncShellTemplateApk") + } +} + +val cloneHostAar = rootProject.layout.projectDirectory.file("clone-host/build/outputs/aar/clone-host-release.aar") +val androidSdkDir = android.sdkDirectory + +tasks.register("syncCloneHostDex") { + description = "Extracts classes.jar from clone-host AAR and converts it to a DEX asset for APK cloning." + group = "build" + dependsOn(":clone-host:assembleRelease") + + enabled = false + + val dexOutputDir = layout.projectDirectory.dir("src/main/assets/clone_host").asFile + val intermediateDir = layout.buildDirectory.dir("intermediates/clone-host-extract") + val sdkDir = androidSdkDir + + doFirst { + intermediateDir.get().asFile.mkdirs() + dexOutputDir.mkdirs() + } + + from(cloneHostAar) + into(intermediateDir) + rename { "clone-host.aar" } + + doLast { + val aarFile = intermediateDir.get().file("clone-host.aar").asFile + if (!aarFile.exists()) { + throw GradleException("clone-host AAR not found at ${aarFile.absolutePath}") + } + + val classesJar = intermediateDir.get().file("classes.jar").asFile + ZipFile(aarFile).use { zip -> + val entry = zip.getEntry("classes.jar") + ?: throw GradleException("classes.jar not found in clone-host AAR") + zip.getInputStream(entry).use { input -> + classesJar.outputStream().use { output -> input.copyTo(output) } + } + } + + val androidJar = sdkDir.resolve("platforms/android-36/android.jar") + if (!androidJar.exists()) { + throw GradleException("android.jar not found at ${androidJar.absolutePath}") + } + + val d8 = sdkDir.resolve("build-tools") + .listFiles()?.maxByOrNull { it.name } + ?.resolve("d8") + ?: throw GradleException("d8 not found in build-tools") + + dexOutputDir.mkdirs() + + val process = ProcessBuilder( + d8.absolutePath, + "--release", + "--min-api", "23", + "--lib", androidJar.absolutePath, + "--output", dexOutputDir.absolutePath, + classesJar.absolutePath + ).redirectErrorStream(true).start() + + val output = process.inputStream.bufferedReader().readText() + if (process.waitFor() != 0) { + throw GradleException("d8 failed to dex clone-host: $output") + } + } +} + +tasks.matching { it.name == "preBuild" }.configureEach { + dependsOn("syncCloneHostDex") +} + +tasks.register("testClasses") { + group = "verification" + description = "Compatibility alias for JVM-style test class compilation in the Android app module." + dependsOn("compileDebugUnitTestSources") +} + +tasks.register("unitTestClasses") { + group = "verification" + description = "Compatibility alias for Android unit test class compilation in the Android app module." + dependsOn("compileDebugUnitTestSources") +} + +abstract class SyncNativeExecutableJniLibsTask : DefaultTask() { + @get:Input + abstract val variantName: org.gradle.api.provider.Property + + @get:Input + abstract val buildTypeName: org.gradle.api.provider.Property + + @get:Input + abstract val executableName: org.gradle.api.provider.Property + + @get:Input + abstract val packagedLibraryName: org.gradle.api.provider.Property + + @get:InputDirectory + @get:PathSensitive(PathSensitivity.RELATIVE) + abstract val cxxRoot: DirectoryProperty + + @get:OutputDirectory + abstract val outputDir: DirectoryProperty + + @TaskAction + fun sync() { + val cxxRootDir = cxxRoot.asFile.get() + if (!cxxRootDir.exists()) { + throw GradleException("CXX output not found for ${variantName.get()}: ${cxxRootDir.absolutePath}") + } + + val executableTargets = cxxRootDir.walkTopDown() + .filter { file -> + file.isFile && + file.name == executableName.get() && + file.parentFile?.parentFile?.name == "obj" + } + .toList() + + if (executableTargets.isEmpty()) { + throw GradleException("${executableName.get()} artifacts not found for ${variantName.get()} under ${cxxRootDir.absolutePath}") + } + + val outputRoot = outputDir.get().asFile + outputRoot.deleteRecursively() + outputRoot.mkdirs() + + executableTargets.forEach { binary -> + val abi = binary.parentFile.name + val destFile = outputRoot.resolve("$abi/${packagedLibraryName.get()}") + destFile.parentFile.mkdirs() + binary.copyTo(destFile, overwrite = true) + destFile.setExecutable(true, false) + } + } +} + +/** + * Builds the patched musl dynamic linker (libmusl-linker.so) into generated + * jniLibs for arm64-v8a / x86_64. The linker carries the W^X exec bridge: + * app_data library fds that SELinux refuses to exec-map are copied into an + * executable memfd and mapped from there, restoring Python host previews on + * targetSdk>=29 builds. Source provenance: upstream musl tarball + + * scripts/patches/musl-1.2.5-dkc-exec-bridge.patch + + * scripts/musl-bridge/dkc_mulxc3.c (NDK compiler-rt drops x86_80 routines). + */ +abstract class BuildMuslBridgeTask : DefaultTask() { + @get:Input + abstract val muslVersion: org.gradle.api.provider.Property + + @get:InputFile + @get:PathSensitive(PathSensitivity.NONE) + abstract val patchFile: RegularFileProperty + + @get:InputFile + @get:PathSensitive(PathSensitivity.NONE) + abstract val x80ShimFile: RegularFileProperty + + @get:InputDirectory + @get:PathSensitive(PathSensitivity.NONE) + abstract val ndkToolchainDir: DirectoryProperty + + @get:Internal + abstract val workDir: DirectoryProperty + + @get:OutputDirectory + abstract val outputDir: DirectoryProperty + + private fun run(cmd: List, cwd: File? = null, env: Map = emptyMap()) { + val proc = ProcessBuilder(cmd).apply { + if (cwd != null) directory(cwd) + environment().putAll(env) + redirectErrorStream(true) + }.start() + val out = proc.inputStream.bufferedReader().readText() + val code = proc.waitFor() + if (code != 0) throw GradleException("command failed ($code): ${cmd.joinToString(" ")}\n$out") + } + + @TaskAction + fun build() { + val tc = ndkToolchainDir.get().asFile + if (!File(tc, "bin/clang").isFile) { + throw GradleException("NDK toolchain not found at $tc (set NDKVersion or install the NDK)") + } + val libccDir = File(tc, "lib/clang") + .listFiles { f -> f.isDirectory }?.map { File(it, "lib/linux") }.orEmpty() + fun libcc(name: String): String = + libccDir.firstOrNull { File(it, name).isFile }?.resolve(name)?.absolutePath + ?: throw GradleException("compiler-rt $name not found under $tc") + + val work = workDir.get().asFile.apply { mkdirs() } + val version = muslVersion.get() + val tarball = File(work, "musl-$version.tar.gz") + if (!tarball.isFile) { + run( + listOf( + "curl", "-fsSL", "--max-time", "180", "-o", tarball.absolutePath, + "https://musl.libc.org/releases/musl-$version.tar.gz" + ) + ) + } + val src = File(work, "musl-$version") + src.deleteRecursively() + run(listOf("tar", "xzf", tarball.absolutePath, "-C", work.absolutePath)) + run(listOf("patch", "-p1", "-d", src.absolutePath, "--input", patchFile.get().asFile.absolutePath)) + File(src, "src/math/x86_64").also { it.mkdirs() } + .resolve(x80ShimFile.get().asFile.name).run { + x80ShimFile.get().asFile.copyTo(this, overwrite = true) + } + + val clang = File(tc, "bin/clang").absolutePath + val strip = File(tc, "bin/llvm-strip").absolutePath + val jobs = Runtime.getRuntime().availableProcessors().toString() + val targets = listOf( + "arm64-v8a" to ("aarch64-linux-musl" to "libclang_rt.builtins-aarch64-android.a"), + "x86_64" to ("x86_64-linux-musl" to "libclang_rt.builtins-x86_64-android.a") + ) + val out = outputDir.get().asFile + out.deleteRecursively() + for ((abi, target) in targets) { + val (triple, rt) = target + val buildDir = File(work, "build-$abi").apply { deleteRecursively(); mkdirs() } + val libccPath = libcc(rt) + val configureEnv = mapOf( + "CC" to "$clang --target=$triple", + "CROSS_COMPILE" to "${File(tc, "bin/llvm-").absolutePath}", + "CFLAGS" to "-O2", + "LDFLAGS" to "-Wl,-z,max-page-size=16384" + ) + run(listOf("../musl-$version/configure", "--target=$triple"), cwd = buildDir, env = configureEnv) + run(listOf("make", "-j$jobs", "LIBCC=$libccPath"), cwd = buildDir, env = configureEnv) + val dest = File(out, "$abi/libmusl-linker.so") + dest.parentFile.mkdirs() + run(listOf(strip, File(buildDir, "lib/libc.so").absolutePath, "-o", dest.absolutePath)) + dest.setExecutable(true, false) + } + } +} + +val muslBridgeTask = tasks.register("buildMuslBridge") { + group = "build" + description = "Builds the patched musl dynamic linker (libmusl-linker.so) with the W^X exec bridge into generated jniLibs." + muslVersion.set("1.2.5") + patchFile.set(rootProject.file("scripts/patches/musl-1.2.5-dkc-exec-bridge.patch")) + x80ShimFile.set(rootProject.file("scripts/musl-bridge/dkc_mulxc3.c")) + val hostTag = if (System.getProperty("os.name").lowercase().contains("mac")) "darwin-x86_64" else "linux-x86_64" + ndkToolchainDir.set(File(android.ndkDirectory, "toolchains/llvm/prebuilt/$hostTag")) + workDir.set(layout.buildDirectory.dir("musl-bridge")) + outputDir.set(layout.buildDirectory.dir("generated/jniLibs/muslBridge")) +} + +androidComponents { + onVariants { variant -> + val capName = variant.name.replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() } + val variantBuildTypeName = variant.buildType ?: "release" + val cxxBuildType = if (variantBuildTypeName.equals("debug", ignoreCase = true)) "Debug" else "RelWithDebInfo" + val nativeBuildTaskName = "buildCMake$cxxBuildType" + + tasks.matching { it.name == "merge${capName}NativeLibs" }.configureEach { + dependsOn(muslBridgeTask) + } + variant.sources.jniLibs?.addGeneratedSourceDirectory( + muslBridgeTask, + BuildMuslBridgeTask::outputDir + ) + val syncNodeLauncherTask = tasks.register("syncNodeLauncherJniLibs$capName") { + group = "build" + description = "Copies ABI-specific node launcher executables into generated jniLibs for ${variant.name}." + variantName.set(variant.name) + buildTypeName.set(variantBuildTypeName) + executableName.set("node_launcher") + packagedLibraryName.set("libnode_launcher.so") + cxxRoot.set(layout.buildDirectory.dir("intermediates/cxx/$cxxBuildType")) + outputDir.set(layout.buildDirectory.dir("generated/jniLibs/nodeLauncher/${variant.name}")) + dependsOn(nativeBuildTaskName) + } + + val syncGoLoaderTask = tasks.register("syncGoExecLoaderJniLibs$capName") { + group = "build" + description = "Copies ABI-specific Go exec loader executables into generated jniLibs for ${variant.name}." + variantName.set(variant.name) + buildTypeName.set(variantBuildTypeName) + executableName.set("go_exec_loader") + packagedLibraryName.set("libgo_exec_loader.so") + cxxRoot.set(layout.buildDirectory.dir("intermediates/cxx/$cxxBuildType")) + outputDir.set(layout.buildDirectory.dir("generated/jniLibs/goExecLoader/${variant.name}")) + dependsOn(nativeBuildTaskName) + } + + tasks.matching { it.name == "merge${capName}NativeLibs" }.configureEach { + dependsOn(syncNodeLauncherTask) + dependsOn(syncGoLoaderTask) + } + + variant.sources.jniLibs?.addGeneratedSourceDirectory( + syncNodeLauncherTask, + SyncNativeExecutableJniLibsTask::outputDir + ) + variant.sources.jniLibs?.addGeneratedSourceDirectory( + syncGoLoaderTask, + SyncNativeExecutableJniLibsTask::outputDir + ) + } +} + +protobuf { + protoc { + artifact = "com.google.protobuf:protoc:3.25.5" + } + generateProtoTasks { + all().forEach { task -> + task.builtins { + + create("java") { + option("lite") + } + } + } + } +} + +dependencies { + + implementation("androidx.core:core-ktx:1.12.0") + implementation("androidx.appcompat:appcompat:1.6.1") + implementation("androidx.core:core-splashscreen:1.0.1") + implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0") + implementation("androidx.documentfile:documentfile:1.0.1") + + implementation("com.google.protobuf:protobuf-javalite:3.25.5") + + implementation("com.google.android.material:material:1.10.0") + implementation("androidx.activity:activity-compose:1.8.1") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2") + implementation("androidx.lifecycle:lifecycle-runtime-compose:2.6.2") + implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2") + + implementation(platform("androidx.compose:compose-bom:2026.06.01")) + implementation("androidx.compose.ui:ui") + implementation("androidx.compose.ui:ui-graphics") + implementation("androidx.compose.ui:ui-tooling-preview") + implementation("androidx.compose.material3:material3:1.5.0-alpha17") + + implementation("androidx.compose.material:material-icons-extended:1.7.8") + implementation("androidx.navigation:navigation-compose:2.7.5") + debugImplementation("androidx.compose.ui:ui-tooling") + + implementation("androidx.room:room-runtime:2.7.2") + implementation("androidx.room:room-ktx:2.7.2") + ksp("androidx.room:room-compiler:2.7.2") + + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") + + implementation("io.coil-kt:coil-compose:2.5.0") + implementation("io.coil-kt:coil-video:2.5.0") + + implementation("com.google.code.gson:gson:2.10.1") + + implementation("com.squareup.okhttp3:okhttp:4.12.0") + implementation("com.squareup.okhttp3:okhttp-dnsoverhttps:4.12.0") + + implementation(platform("com.google.firebase:firebase-bom:33.7.0")) + implementation("com.google.firebase:firebase-messaging") + + implementation("org.bouncycastle:bcpkix-jdk15to18:1.78.1") + implementation("org.bouncycastle:bcprov-jdk15to18:1.78.1") + + implementation("io.insert-koin:koin-android:3.5.3") + implementation("io.insert-koin:koin-androidx-compose:3.5.3") + + implementation("androidx.webkit:webkit:1.9.0") + + implementation("androidx.datastore:datastore-preferences:1.0.0") + + implementation("androidx.security:security-crypto:1.1.0-alpha06") + + implementation("org.apache.commons:commons-compress:1.26.0") + implementation("org.tukaani:xz:1.9") + + implementation("com.android.tools.build:apksig:8.3.0") + + implementation("org.mozilla.geckoview:geckoview-arm64-v8a:142.0.20250827004350") + + // Forced HTTP/3 (issue #721): Chromium's own network stack as the MITM bridge's + // upstream leg. Java classes ship in the APK; libcronet is NEVER bundled — the host + // downloads it on demand (filesDir/cronet_deps) and ApkBuilder injects it into + // exported APKs only when the app enables 强制 HTTP/3 (libnode/GeckoView precedent). + // Version must match CronetDependencyManager.CRONET_ARTIFACT_VERSION. + implementation("org.chromium.net:cronet-embedded:143.7445.0") + + implementation("com.google.zxing:core:3.5.2") + + // Native Google sign-in through the Jetpack Credential Manager (NativeBridge). + implementation("androidx.credentials:credentials:1.5.0") + implementation("androidx.credentials:credentials-play-services-auth:1.5.0") + implementation("com.google.android.libraries.identity.googleid:googleid:1.1.1") + implementation("androidx.browser:browser:1.8.0") + + implementation("androidx.media:media:1.7.0") + + testImplementation("junit:junit:4.13.2") + testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3") + testImplementation("com.google.truth:truth:1.1.5") + testImplementation("org.robolectric:robolectric:4.12.2") + testImplementation("androidx.test:core:1.5.0") + + androidTestImplementation("androidx.test.ext:junit:1.1.5") + androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") +} + +/** + * Resolves a Python 3 interpreter command for the current platform. Windows usually exposes + * Python as `python` (or the `py -3` launcher) rather than `python3`, so a hardcoded + * `python3` fails there. Each candidate is verified to actually be Python 3 before use. + * NOTE: intentionally duplicated in the root build.gradle.kts (this project has no buildSrc). + */ +fun resolvePython3Command(): List { + val isWindows = System.getProperty("os.name").lowercase().contains("windows") + val candidates: List> = if (isWindows) { + listOf(listOf("python3"), listOf("python"), listOf("py", "-3")) + } else { + listOf(listOf("python3"), listOf("python")) + } + for (candidate in candidates) { + try { + val probe = ProcessBuilder(candidate + "--version").redirectErrorStream(true).start() + val output = probe.inputStream.bufferedReader().readText() + if (probe.waitFor() == 0 && output.contains("Python 3")) { + return candidate + } + } catch (_: Exception) { + // Candidate unavailable; try the next one. + } + } + return listOf("python3") +} + +tasks.register("checkConfigFieldDrift") { + group = "verification" + description = "Detect field-name drift between ApkConfig payload keys and ShellConfig @SerializedName (static guard for preview/export config consistency)" + val script = rootProject.file("scripts/check_config_field_drift.py") + val payloadFile = file("src/main/java/br/com/drukstech/codeapp/core/apkbuilder/ApkConfigJsonFactory.kt") + val apkConfigFile = file("src/main/java/br/com/drukstech/codeapp/core/apkbuilder/ApkConfig.kt") + val shellConfigFile = file("src/main/java/br/com/drukstech/codeapp/core/shell/ShellModeManager.kt") + val allowlist = rootProject.file("scripts/config_field_drift_allowlist.json") + // Configuration-cache safe: capture values at configuration time; the doLast action + // must not reach through Project. + val rootDir = rootProject.projectDir + inputs.files(script, payloadFile, apkConfigFile, shellConfigFile, allowlist) + outputs.upToDateWhen { false } + doLast { + val pb = ProcessBuilder(resolvePython3Command() + script.absolutePath) + pb.directory(rootDir) + pb.redirectErrorStream(true) + val proc = pb.start() + val log = proc.inputStream.bufferedReader().readText() + val code = proc.waitFor() + logger.lifecycle(log.trim()) + if (code != 0) { + throw GradleException("checkConfigFieldDrift failed ($code)") + } + } +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..dda78a3 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,315 @@ +# DruksCode ProGuard Rules +# +# 策略:启用代码收缩(移除未使用代码)+ 资源压缩(移除未使用资源), +# 禁用混淆与激进优化。这是经过线上事故反复验证后的"稳定优先"配置, +# 减包体积仍能保留 30%+ 收益,但完全避免反射/泛型/ServiceLoader/JNI 类陷阱。 +# +# 收益与权衡: +# - shrink: 保留,移除未使用类/方法(约 25% 体积削减) +# - obfuscate: 关闭(开源项目无意义,反而引入 Gson/Koin/反射 bug) +# - optimize: 关闭部分激进优化(保留默认收缩,避免内联引发的 NPE) +# +# 出问题时排查方法: +# 1. ./gradlew :app:assembleRelease -PandroidProguardPrintUsage=true +# 会在 build/outputs/mapping/release/usage.txt 写出被 R8 删除的所有内容 +# 2. ./gradlew :app:assembleRelease -PandroidProguardPrintSeeds=true +# 会写出被显式 keep 的所有内容 +# 3. 把崩溃栈对照 build/outputs/mapping/release/mapping.txt 反推 + +-dontobfuscate + +# 关掉一组容易破坏反射 / Compose / 协程语义的优化模式 +# 这些是 R8 历史上反复出现 bug 的优化通道,关掉它们体积代价可忽略 +-optimizations !class/merging/*,!field/*,!method/marking/static,!method/inlining/*,!code/allocation/variable +-optimizationpasses 1 + +# ============================================================ +# 调试 / 崩溃堆栈可读 +# ============================================================ +-keepattributes SourceFile,LineNumberTable +-keepattributes Signature +-keepattributes Exceptions +-keepattributes *Annotation* +-keepattributes EnclosingMethod +-keepattributes InnerClasses +-keepattributes RuntimeVisibleAnnotations,RuntimeVisibleParameterAnnotations +-keepattributes RuntimeInvisibleAnnotations,RuntimeInvisibleParameterAnnotations +-keepattributes RuntimeVisibleTypeAnnotations,RuntimeInvisibleTypeAnnotations +-keepattributes AnnotationDefault +-keepattributes MethodParameters + +# 让崩溃栈打印 R8 重命名前的类名 / 行号 +-renamesourcefileattribute SourceFile + +# ============================================================ +# Android 组件 — Manifest 引用,必须保名 +# ============================================================ +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider +-keep public class * extends android.accessibilityservice.AccessibilityService +-keep public class * extends androidx.work.ListenableWorker +-keep public class * extends android.app.Application +-keep public class * extends androidx.fragment.app.Fragment +-keep public class * extends androidx.lifecycle.ViewModel +-keep public class * extends androidx.lifecycle.AndroidViewModel + +# ============================================================ +# 通用反射 — Parcelable / Serializable / enum / native +# ============================================================ +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} + +-keepclassmembers class * implements java.io.Serializable { + static final long serialVersionUID; + private static java.io.ObjectStreamField[] serialPersistentFields; + private void writeObject(java.io.ObjectOutputStream); + private void readObject(java.io.ObjectInputStream); + java.lang.Object writeReplace(); + java.lang.Object readResolve(); +} + +# JNI native 方法 +-keepclasseswithmembernames class * { + native ; +} + +# WebView @JavascriptInterface +-keepclassmembers class * { + @android.webkit.JavascriptInterface ; +} + +# View 的 XML inflate / setOnClick 反射回调 +-keepclassmembers class * extends android.view.View { + void set*(***); + *** get*(); +} +-keepclassmembers class * extends android.app.Activity { + public void *(android.view.View); +} + +# ============================================================ +# Kotlin +# ============================================================ +-keep class kotlin.Metadata { *; } +-keep class kotlin.reflect.** { *; } +-keepclassmembers class **$WhenMappings { ; } +-keepclassmembers class kotlin.Lazy { public ; } +-keep class kotlin.jvm.internal.DefaultConstructorMarker { *; } +-keepclassmembers class kotlin.coroutines.jvm.internal.** { *; } +-dontwarn kotlin.** +-dontwarn kotlinx.** + +# Kotlin Coroutines — ServiceLoader 加载 Dispatchers.Main +-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory +-keepnames class kotlinx.coroutines.android.AndroidDispatcherFactory +-keep class kotlinx.coroutines.android.AndroidDispatcherFactory { *; } +-keep class kotlinx.coroutines.android.AndroidExceptionPreHandler { *; } +-keep class kotlinx.coroutines.internal.MainDispatcherFactory { *; } +-keep class kotlinx.coroutines.CoroutineExceptionHandler { *; } +-keepclassmembers class kotlinx.coroutines.** { + volatile ; +} +# Coroutines 调试 / 异常 hooks +-keepnames class kotlinx.coroutines.flow.** { *; } + +# ============================================================ +# 项目自身代码 — 全部保留(开源 + 重反射) +# ============================================================ +-keep class br.com.drukstech.codeapp.** { *; } +-keepclassmembers class br.com.drukstech.codeapp.** { *; } +-keep enum br.com.drukstech.codeapp.** { *; } +-keep interface br.com.drukstech.codeapp.** { *; } + +# data class 的合成构造器(含默认参数)— Gson 反序列化必须 +-keepclassmembers class br.com.drukstech.codeapp.data.model.** { + (...); +} + +# ============================================================ +# Room — KSP 生成的 _Impl 类已经在 br.com.drukstech.codeapp.** 范围内 +# ============================================================ +-keep class * extends androidx.room.RoomDatabase { *; } +-keep @androidx.room.Entity class * +-keep @androidx.room.Dao class * +-keepclassmembers class * { + @androidx.room.* ; +} +-dontwarn androidx.room.paging.** + +# ============================================================ +# Gson — 序列化 / 反序列化通过反射 +# ============================================================ +-keep class sun.misc.Unsafe { *; } +-keep class com.google.gson.** { *; } +-keep class * implements com.google.gson.TypeAdapter +-keep class * implements com.google.gson.TypeAdapterFactory +-keep class * implements com.google.gson.JsonSerializer +-keep class * implements com.google.gson.JsonDeserializer +-keep class * implements com.google.gson.InstanceCreator +-keepclassmembers class * { + @com.google.gson.annotations.SerializedName ; + @com.google.gson.annotations.JsonAdapter ; + @com.google.gson.annotations.Expose ; +} + +# Gson TypeToken — R8 full mode 会把 `object : TypeToken>() {}` +# 匿名子类的 Signature 属性剥掉,运行时抛 IllegalStateException。 +# 参考: https://github.com/google/gson/blob/main/Troubleshooting.md#r8 +-keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken +-keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken + +# ============================================================ +# Koin DI — 大量反射 + ServiceLoader +# ============================================================ +-keep class org.koin.** { *; } +-keepclassmembers class * { + public (org.koin.core.scope.Scope); +} +-keepclassmembers class * extends org.koin.core.module.Module { *; } +-dontwarn org.koin.** + +# ============================================================ +# OkHttp / Okio — Platform 反射检测 OS 安全栈 +# ============================================================ +-keep class okhttp3.internal.platform.** { *; } +-keep class okhttp3.internal.publicsuffix.** { *; } +-dontwarn okhttp3.** +-dontwarn okio.** +-dontwarn org.conscrypt.** +-dontwarn org.bouncycastle.** +-dontwarn org.openjsse.** + +# ============================================================ +# Coil — ServiceLoader 加载 fetcher / decoder / mapper +# ============================================================ +-keep class coil.util.** { *; } +-keep class coil.fetch.** { *; } +-keep class coil.decode.** { *; } +-keep class coil.map.** { *; } +-dontwarn coil.** + +# ============================================================ +# apksig — 反射读取 @Asn1Class/@Asn1Field 注解序列化 PKCS#7 +# ============================================================ +-keep class com.android.apksig.** { *; } +-keepclassmembers class com.android.apksig.** { *; } +-keep @com.android.apksig.internal.asn1.Asn1Class class * +-keepclassmembers class * { + @com.android.apksig.internal.asn1.Asn1Field *; +} +-dontwarn com.android.apksig.** + +-keep class com.android.aapt.** { *; } +-keepclassmembers class com.android.aapt.** { *; } +-keep class com.android.bundle.** { *; } +-keepclassmembers class com.android.bundle.** { *; } + +# ============================================================ +# GeckoView — 大量 JNI / 注解反射 +# ============================================================ +-keep class org.mozilla.geckoview.** { *; } +-keep class org.mozilla.gecko.** { *; } +-keepclassmembers class * extends org.mozilla.geckoview.GeckoSession$* { *; } +-dontwarn org.mozilla.geckoview.** + +# ============================================================ +# ZXing — 反射查找编码格式 (仅 core,embedded 已移除) +# ============================================================ +-keep class com.google.zxing.** { *; } +-dontwarn com.google.zxing.** + +# BillingClient — AIDL stub +# ============================================================ +-keep class com.android.vending.billing.** { *; } +-keep class com.android.billingclient.** { *; } +-keep class com.google.android.gms.internal.** { *; } +-dontwarn com.android.billingclient.** + +# ============================================================ +# Credentials API + GoogleId — 反射解析 ID Token +# ============================================================ +-keep class androidx.credentials.** { *; } +-keep class com.google.android.libraries.identity.** { *; } +-keep class com.google.android.gms.auth.api.identity.** { *; } +-dontwarn androidx.credentials.** +-dontwarn com.google.android.libraries.identity.** + +# ============================================================ +# DataStore Preferences +# ============================================================ +-keep class androidx.datastore.** { *; } +-dontwarn androidx.datastore.** + +# ============================================================ +# Security crypto (alpha — 可能有反射) +# ============================================================ +-keep class androidx.security.crypto.** { *; } +-keep class com.google.crypto.tink.** { *; } +-dontwarn androidx.security.crypto.** +-dontwarn com.google.crypto.tink.** + +# ============================================================ +# Compress / xz — ServiceLoader 加载格式 +# ============================================================ +-keep class org.apache.commons.compress.compressors.FileNameUtil { *; } +-keep class org.apache.commons.compress.archivers.** { *; } +-keep class org.tukaani.xz.** { *; } +-dontwarn org.apache.commons.compress.** +-dontwarn org.tukaani.xz.** +-dontwarn org.brotli.dec.** +-dontwarn org.yaml.snakeyaml.** + +# ============================================================ +# Compose Runtime — 已有 consumer rules,仅压制 warn +# ============================================================ +-dontwarn androidx.compose.** + +# ============================================================ +# Material / AppCompat — 已有 consumer rules,仅兜底 +# ============================================================ +-dontwarn com.google.android.material.** + +# ============================================================ +# Custom Tabs (browser) +# ============================================================ +-keep class androidx.browser.** { *; } +-dontwarn androidx.browser.** + +# ============================================================ +# Haze (背景模糊) +# ============================================================ +-keep class dev.chrisbanes.haze.** { *; } +-dontwarn dev.chrisbanes.haze.** + +# Node.js JNI output bridge (R8 may rename onOutput otherwise) +-keep class br.com.drukstech.codeapp.core.nodejs.NodeBridge { *; } +-keep class br.com.drukstech.codeapp.core.nodejs.NodeJniOutputBridge { + (...); + public void onOutput(java.lang.String, boolean); +} + +# Firebase / FCM +-keep class com.google.firebase.** { *; } +-keep class com.google.android.gms.** { *; } +-dontwarn com.google.firebase.** +-dontwarn com.google.android.gms.** + +# ============================================================ +# Cronet (forced HTTP/3 upstream) +# ============================================================ +# Cronet's native code reaches its Java classes via JNI and ServiceLoader +# (org.chromium.net.impl.** / org.chromium.base.**); R8 must not rename or +# strip them. The AAR ships consumer rules, this is the belt-and-braces copy. +-keep class org.chromium.net.** { *; } +-keep class org.chromium.base.** { *; } +-keep class org.chromium.components.** { *; } +-dontwarn org.chromium.** +-keepdirectories META-INF/services/** diff --git a/app/schemas/br.com.drukstech.codeapp.data.database.AppDatabase/45.json b/app/schemas/br.com.drukstech.codeapp.data.database.AppDatabase/45.json new file mode 100644 index 0000000..34f8ee0 --- /dev/null +++ b/app/schemas/br.com.drukstech.codeapp.data.database.AppDatabase/45.json @@ -0,0 +1,563 @@ +{ + "formatVersion": 1, + "database": { + "version": 45, + "identityHash": "ea6b40911e9117204ec107ff693031d7", + "entities": [ + { + "tableName": "web_apps", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `url` TEXT NOT NULL, `iconPath` TEXT, `packageName` TEXT, `appType` TEXT NOT NULL, `mediaConfig` TEXT, `galleryConfig` TEXT, `htmlConfig` TEXT, `wordpressConfig` TEXT, `nodejsConfig` TEXT, `phpAppConfig` TEXT, `pythonAppConfig` TEXT, `goAppConfig` TEXT, `multiWebConfig` TEXT, `activationEnabled` INTEGER NOT NULL, `activationCodeList` TEXT NOT NULL, `activationRequireEveryTime` INTEGER NOT NULL, `activationRemoteConfig` TEXT, `isActivated` INTEGER NOT NULL, `adsEnabled` INTEGER NOT NULL, `adConfig` TEXT, `announcementEnabled` INTEGER NOT NULL, `announcement` TEXT, `adBlockEnabled` INTEGER NOT NULL, `adBlockRules` TEXT NOT NULL, `adBlockSubscriptions` TEXT NOT NULL, `webViewConfig` TEXT NOT NULL, `splashEnabled` INTEGER NOT NULL, `splashConfig` TEXT, `bgmEnabled` INTEGER NOT NULL, `bgmConfig` TEXT, `apkExportConfig` TEXT, `themeType` TEXT NOT NULL, `translateEnabled` INTEGER NOT NULL, `translateConfig` TEXT, `extensionEnabled` INTEGER NOT NULL, `extensionModuleIds` TEXT NOT NULL, `extensionFabIcon` TEXT, `autoStartConfig` TEXT, `browserDisguiseConfig` TEXT, `deviceDisguiseConfig` TEXT, `activationDialogConfig` TEXT, `categoryId` INTEGER, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "iconPath", + "columnName": "iconPath", + "affinity": "TEXT" + }, + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT" + }, + { + "fieldPath": "appType", + "columnName": "appType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "mediaConfig", + "columnName": "mediaConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "galleryConfig", + "columnName": "galleryConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "htmlConfig", + "columnName": "htmlConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "wordpressConfig", + "columnName": "wordpressConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "nodejsConfig", + "columnName": "nodejsConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "phpAppConfig", + "columnName": "phpAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "pythonAppConfig", + "columnName": "pythonAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "goAppConfig", + "columnName": "goAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "multiWebConfig", + "columnName": "multiWebConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "activationEnabled", + "columnName": "activationEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "activationCodeList", + "columnName": "activationCodeList", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "activationRequireEveryTime", + "columnName": "activationRequireEveryTime", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "activationRemoteConfig", + "columnName": "activationRemoteConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "isActivated", + "columnName": "isActivated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adsEnabled", + "columnName": "adsEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adConfig", + "columnName": "adConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "announcementEnabled", + "columnName": "announcementEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "announcement", + "columnName": "announcement", + "affinity": "TEXT" + }, + { + "fieldPath": "adBlockEnabled", + "columnName": "adBlockEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adBlockRules", + "columnName": "adBlockRules", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "adBlockSubscriptions", + "columnName": "adBlockSubscriptions", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "webViewConfig", + "columnName": "webViewConfig", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "splashEnabled", + "columnName": "splashEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "splashConfig", + "columnName": "splashConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "bgmEnabled", + "columnName": "bgmEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bgmConfig", + "columnName": "bgmConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "apkExportConfig", + "columnName": "apkExportConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "themeType", + "columnName": "themeType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "translateEnabled", + "columnName": "translateEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "translateConfig", + "columnName": "translateConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "extensionEnabled", + "columnName": "extensionEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "extensionModuleIds", + "columnName": "extensionModuleIds", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "extensionFabIcon", + "columnName": "extensionFabIcon", + "affinity": "TEXT" + }, + { + "fieldPath": "autoStartConfig", + "columnName": "autoStartConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "browserDisguiseConfig", + "columnName": "browserDisguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "deviceDisguiseConfig", + "columnName": "deviceDisguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "activationDialogConfig", + "columnName": "activationDialogConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "categoryId", + "columnName": "categoryId", + "affinity": "INTEGER" + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "updatedAt", + "columnName": "updatedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_web_apps_updatedAt", + "unique": false, + "columnNames": [ + "updatedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_updatedAt` ON `${TABLE_NAME}` (`updatedAt`)" + }, + { + "name": "index_web_apps_categoryId", + "unique": false, + "columnNames": [ + "categoryId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_categoryId` ON `${TABLE_NAME}` (`categoryId`)" + }, + { + "name": "index_web_apps_isActivated", + "unique": false, + "columnNames": [ + "isActivated" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_isActivated` ON `${TABLE_NAME}` (`isActivated`)" + }, + { + "name": "index_web_apps_appType_url", + "unique": false, + "columnNames": [ + "appType", + "url" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_appType_url` ON `${TABLE_NAME}` (`appType`, `url`)" + }, + { + "name": "index_web_apps_appType_iconPath_url", + "unique": false, + "columnNames": [ + "appType", + "iconPath", + "url" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_appType_iconPath_url` ON `${TABLE_NAME}` (`appType`, `iconPath`, `url`)" + } + ] + }, + { + "tableName": "app_categories", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `icon` TEXT NOT NULL, `color` TEXT NOT NULL, `sortOrder` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sortOrder", + "columnName": "sortOrder", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + } + }, + { + "tableName": "app_usage_stats", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `appId` INTEGER NOT NULL, `launchCount` INTEGER NOT NULL, `totalUsageMs` INTEGER NOT NULL, `lastUsedAt` INTEGER NOT NULL, `lastSessionDurationMs` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, FOREIGN KEY(`appId`) REFERENCES `web_apps`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "appId", + "columnName": "appId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "launchCount", + "columnName": "launchCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "totalUsageMs", + "columnName": "totalUsageMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastUsedAt", + "columnName": "lastUsedAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastSessionDurationMs", + "columnName": "lastSessionDurationMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_app_usage_stats_appId", + "unique": true, + "columnNames": [ + "appId" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_app_usage_stats_appId` ON `${TABLE_NAME}` (`appId`)" + }, + { + "name": "index_app_usage_stats_lastUsedAt", + "unique": false, + "columnNames": [ + "lastUsedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_usage_stats_lastUsedAt` ON `${TABLE_NAME}` (`lastUsedAt`)" + }, + { + "name": "index_app_usage_stats_launchCount", + "unique": false, + "columnNames": [ + "launchCount" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_usage_stats_launchCount` ON `${TABLE_NAME}` (`launchCount`)" + } + ], + "foreignKeys": [ + { + "table": "web_apps", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "appId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "app_health_records", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `appId` INTEGER NOT NULL, `url` TEXT NOT NULL, `status` TEXT NOT NULL, `responseTimeMs` INTEGER NOT NULL, `httpStatusCode` INTEGER NOT NULL, `errorMessage` TEXT, `checkedAt` INTEGER NOT NULL, FOREIGN KEY(`appId`) REFERENCES `web_apps`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "appId", + "columnName": "appId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "responseTimeMs", + "columnName": "responseTimeMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "httpStatusCode", + "columnName": "httpStatusCode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "errorMessage", + "columnName": "errorMessage", + "affinity": "TEXT" + }, + { + "fieldPath": "checkedAt", + "columnName": "checkedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_app_health_records_appId", + "unique": false, + "columnNames": [ + "appId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_health_records_appId` ON `${TABLE_NAME}` (`appId`)" + }, + { + "name": "index_app_health_records_checkedAt", + "unique": false, + "columnNames": [ + "checkedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_health_records_checkedAt` ON `${TABLE_NAME}` (`checkedAt`)" + } + ], + "foreignKeys": [ + { + "table": "web_apps", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "appId" + ], + "referencedColumns": [ + "id" + ] + } + ] + } + ], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'ea6b40911e9117204ec107ff693031d7')" + ] + } +} \ No newline at end of file diff --git a/app/schemas/com.webtoapp.data.database.AppDatabase/36.json b/app/schemas/com.webtoapp.data.database.AppDatabase/36.json new file mode 100644 index 0000000..7663bbb --- /dev/null +++ b/app/schemas/com.webtoapp.data.database.AppDatabase/36.json @@ -0,0 +1,573 @@ +{ + "formatVersion": 1, + "database": { + "version": 36, + "identityHash": "edf2cccde4bb442d6b044c0811e03272", + "entities": [ + { + "tableName": "web_apps", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `url` TEXT NOT NULL, `iconPath` TEXT, `packageName` TEXT, `appType` TEXT NOT NULL, `mediaConfig` TEXT, `galleryConfig` TEXT, `htmlConfig` TEXT, `wordpressConfig` TEXT, `nodejsConfig` TEXT, `phpAppConfig` TEXT, `pythonAppConfig` TEXT, `goAppConfig` TEXT, `multiWebConfig` TEXT, `activationEnabled` INTEGER NOT NULL, `activationCodes` TEXT NOT NULL, `activationCodeList` TEXT NOT NULL, `activationRequireEveryTime` INTEGER NOT NULL, `isActivated` INTEGER NOT NULL, `adsEnabled` INTEGER NOT NULL, `adConfig` TEXT, `announcementEnabled` INTEGER NOT NULL, `announcement` TEXT, `adBlockEnabled` INTEGER NOT NULL, `adBlockRules` TEXT NOT NULL, `webViewConfig` TEXT NOT NULL, `splashEnabled` INTEGER NOT NULL, `splashConfig` TEXT, `bgmEnabled` INTEGER NOT NULL, `bgmConfig` TEXT, `apkExportConfig` TEXT, `themeType` TEXT NOT NULL, `translateEnabled` INTEGER NOT NULL, `translateConfig` TEXT, `extensionEnabled` INTEGER NOT NULL, `extensionModuleIds` TEXT NOT NULL, `extensionFabIcon` TEXT, `autoStartConfig` TEXT, `forcedRunConfig` TEXT, `blackTechConfig` TEXT, `disguiseConfig` TEXT, `browserDisguiseConfig` TEXT, `deviceDisguiseConfig` TEXT, `activationDialogConfig` TEXT, `categoryId` INTEGER, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "iconPath", + "columnName": "iconPath", + "affinity": "TEXT" + }, + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT" + }, + { + "fieldPath": "appType", + "columnName": "appType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "mediaConfig", + "columnName": "mediaConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "galleryConfig", + "columnName": "galleryConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "htmlConfig", + "columnName": "htmlConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "wordpressConfig", + "columnName": "wordpressConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "nodejsConfig", + "columnName": "nodejsConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "phpAppConfig", + "columnName": "phpAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "pythonAppConfig", + "columnName": "pythonAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "goAppConfig", + "columnName": "goAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "multiWebConfig", + "columnName": "multiWebConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "activationEnabled", + "columnName": "activationEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "activationCodes", + "columnName": "activationCodes", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "activationCodeList", + "columnName": "activationCodeList", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "activationRequireEveryTime", + "columnName": "activationRequireEveryTime", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isActivated", + "columnName": "isActivated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adsEnabled", + "columnName": "adsEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adConfig", + "columnName": "adConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "announcementEnabled", + "columnName": "announcementEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "announcement", + "columnName": "announcement", + "affinity": "TEXT" + }, + { + "fieldPath": "adBlockEnabled", + "columnName": "adBlockEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adBlockRules", + "columnName": "adBlockRules", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "webViewConfig", + "columnName": "webViewConfig", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "splashEnabled", + "columnName": "splashEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "splashConfig", + "columnName": "splashConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "bgmEnabled", + "columnName": "bgmEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bgmConfig", + "columnName": "bgmConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "apkExportConfig", + "columnName": "apkExportConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "themeType", + "columnName": "themeType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "translateEnabled", + "columnName": "translateEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "translateConfig", + "columnName": "translateConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "extensionEnabled", + "columnName": "extensionEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "extensionModuleIds", + "columnName": "extensionModuleIds", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "extensionFabIcon", + "columnName": "extensionFabIcon", + "affinity": "TEXT" + }, + { + "fieldPath": "autoStartConfig", + "columnName": "autoStartConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "forcedRunConfig", + "columnName": "forcedRunConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "blackTechConfig", + "columnName": "blackTechConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "disguiseConfig", + "columnName": "disguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "browserDisguiseConfig", + "columnName": "browserDisguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "deviceDisguiseConfig", + "columnName": "deviceDisguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "activationDialogConfig", + "columnName": "activationDialogConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "categoryId", + "columnName": "categoryId", + "affinity": "INTEGER" + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "updatedAt", + "columnName": "updatedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_web_apps_updatedAt", + "unique": false, + "columnNames": [ + "updatedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_updatedAt` ON `${TABLE_NAME}` (`updatedAt`)" + }, + { + "name": "index_web_apps_categoryId", + "unique": false, + "columnNames": [ + "categoryId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_categoryId` ON `${TABLE_NAME}` (`categoryId`)" + }, + { + "name": "index_web_apps_isActivated", + "unique": false, + "columnNames": [ + "isActivated" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_isActivated` ON `${TABLE_NAME}` (`isActivated`)" + }, + { + "name": "index_web_apps_appType_url", + "unique": false, + "columnNames": [ + "appType", + "url" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_appType_url` ON `${TABLE_NAME}` (`appType`, `url`)" + }, + { + "name": "index_web_apps_appType_iconPath_url", + "unique": false, + "columnNames": [ + "appType", + "iconPath", + "url" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_appType_iconPath_url` ON `${TABLE_NAME}` (`appType`, `iconPath`, `url`)" + } + ] + }, + { + "tableName": "app_categories", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `icon` TEXT NOT NULL, `color` TEXT NOT NULL, `sortOrder` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sortOrder", + "columnName": "sortOrder", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + } + }, + { + "tableName": "app_usage_stats", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `appId` INTEGER NOT NULL, `launchCount` INTEGER NOT NULL, `totalUsageMs` INTEGER NOT NULL, `lastUsedAt` INTEGER NOT NULL, `lastSessionDurationMs` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, FOREIGN KEY(`appId`) REFERENCES `web_apps`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "appId", + "columnName": "appId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "launchCount", + "columnName": "launchCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "totalUsageMs", + "columnName": "totalUsageMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastUsedAt", + "columnName": "lastUsedAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastSessionDurationMs", + "columnName": "lastSessionDurationMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_app_usage_stats_appId", + "unique": true, + "columnNames": [ + "appId" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_app_usage_stats_appId` ON `${TABLE_NAME}` (`appId`)" + }, + { + "name": "index_app_usage_stats_lastUsedAt", + "unique": false, + "columnNames": [ + "lastUsedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_usage_stats_lastUsedAt` ON `${TABLE_NAME}` (`lastUsedAt`)" + }, + { + "name": "index_app_usage_stats_launchCount", + "unique": false, + "columnNames": [ + "launchCount" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_usage_stats_launchCount` ON `${TABLE_NAME}` (`launchCount`)" + } + ], + "foreignKeys": [ + { + "table": "web_apps", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "appId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "app_health_records", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `appId` INTEGER NOT NULL, `url` TEXT NOT NULL, `status` TEXT NOT NULL, `responseTimeMs` INTEGER NOT NULL, `httpStatusCode` INTEGER NOT NULL, `errorMessage` TEXT, `checkedAt` INTEGER NOT NULL, FOREIGN KEY(`appId`) REFERENCES `web_apps`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "appId", + "columnName": "appId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "responseTimeMs", + "columnName": "responseTimeMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "httpStatusCode", + "columnName": "httpStatusCode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "errorMessage", + "columnName": "errorMessage", + "affinity": "TEXT" + }, + { + "fieldPath": "checkedAt", + "columnName": "checkedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_app_health_records_appId", + "unique": false, + "columnNames": [ + "appId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_health_records_appId` ON `${TABLE_NAME}` (`appId`)" + }, + { + "name": "index_app_health_records_checkedAt", + "unique": false, + "columnNames": [ + "checkedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_health_records_checkedAt` ON `${TABLE_NAME}` (`checkedAt`)" + } + ], + "foreignKeys": [ + { + "table": "web_apps", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "appId" + ], + "referencedColumns": [ + "id" + ] + } + ] + } + ], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'edf2cccde4bb442d6b044c0811e03272')" + ] + } +} \ No newline at end of file diff --git a/app/schemas/com.webtoapp.data.database.AppDatabase/37.json b/app/schemas/com.webtoapp.data.database.AppDatabase/37.json new file mode 100644 index 0000000..0281d2e --- /dev/null +++ b/app/schemas/com.webtoapp.data.database.AppDatabase/37.json @@ -0,0 +1,567 @@ +{ + "formatVersion": 1, + "database": { + "version": 37, + "identityHash": "643c6f9480593253e00702649c9f1737", + "entities": [ + { + "tableName": "web_apps", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `url` TEXT NOT NULL, `iconPath` TEXT, `packageName` TEXT, `appType` TEXT NOT NULL, `mediaConfig` TEXT, `galleryConfig` TEXT, `htmlConfig` TEXT, `wordpressConfig` TEXT, `nodejsConfig` TEXT, `phpAppConfig` TEXT, `pythonAppConfig` TEXT, `goAppConfig` TEXT, `multiWebConfig` TEXT, `activationEnabled` INTEGER NOT NULL, `activationCodeList` TEXT NOT NULL, `activationRequireEveryTime` INTEGER NOT NULL, `isActivated` INTEGER NOT NULL, `adsEnabled` INTEGER NOT NULL, `adConfig` TEXT, `announcementEnabled` INTEGER NOT NULL, `announcement` TEXT, `adBlockEnabled` INTEGER NOT NULL, `adBlockRules` TEXT NOT NULL, `webViewConfig` TEXT NOT NULL, `splashEnabled` INTEGER NOT NULL, `splashConfig` TEXT, `bgmEnabled` INTEGER NOT NULL, `bgmConfig` TEXT, `apkExportConfig` TEXT, `themeType` TEXT NOT NULL, `translateEnabled` INTEGER NOT NULL, `translateConfig` TEXT, `extensionEnabled` INTEGER NOT NULL, `extensionModuleIds` TEXT NOT NULL, `extensionFabIcon` TEXT, `autoStartConfig` TEXT, `forcedRunConfig` TEXT, `blackTechConfig` TEXT, `disguiseConfig` TEXT, `browserDisguiseConfig` TEXT, `deviceDisguiseConfig` TEXT, `activationDialogConfig` TEXT, `categoryId` INTEGER, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "iconPath", + "columnName": "iconPath", + "affinity": "TEXT" + }, + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT" + }, + { + "fieldPath": "appType", + "columnName": "appType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "mediaConfig", + "columnName": "mediaConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "galleryConfig", + "columnName": "galleryConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "htmlConfig", + "columnName": "htmlConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "wordpressConfig", + "columnName": "wordpressConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "nodejsConfig", + "columnName": "nodejsConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "phpAppConfig", + "columnName": "phpAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "pythonAppConfig", + "columnName": "pythonAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "goAppConfig", + "columnName": "goAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "multiWebConfig", + "columnName": "multiWebConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "activationEnabled", + "columnName": "activationEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "activationCodeList", + "columnName": "activationCodeList", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "activationRequireEveryTime", + "columnName": "activationRequireEveryTime", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isActivated", + "columnName": "isActivated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adsEnabled", + "columnName": "adsEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adConfig", + "columnName": "adConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "announcementEnabled", + "columnName": "announcementEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "announcement", + "columnName": "announcement", + "affinity": "TEXT" + }, + { + "fieldPath": "adBlockEnabled", + "columnName": "adBlockEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adBlockRules", + "columnName": "adBlockRules", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "webViewConfig", + "columnName": "webViewConfig", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "splashEnabled", + "columnName": "splashEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "splashConfig", + "columnName": "splashConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "bgmEnabled", + "columnName": "bgmEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bgmConfig", + "columnName": "bgmConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "apkExportConfig", + "columnName": "apkExportConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "themeType", + "columnName": "themeType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "translateEnabled", + "columnName": "translateEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "translateConfig", + "columnName": "translateConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "extensionEnabled", + "columnName": "extensionEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "extensionModuleIds", + "columnName": "extensionModuleIds", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "extensionFabIcon", + "columnName": "extensionFabIcon", + "affinity": "TEXT" + }, + { + "fieldPath": "autoStartConfig", + "columnName": "autoStartConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "forcedRunConfig", + "columnName": "forcedRunConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "blackTechConfig", + "columnName": "blackTechConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "disguiseConfig", + "columnName": "disguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "browserDisguiseConfig", + "columnName": "browserDisguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "deviceDisguiseConfig", + "columnName": "deviceDisguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "activationDialogConfig", + "columnName": "activationDialogConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "categoryId", + "columnName": "categoryId", + "affinity": "INTEGER" + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "updatedAt", + "columnName": "updatedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_web_apps_updatedAt", + "unique": false, + "columnNames": [ + "updatedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_updatedAt` ON `${TABLE_NAME}` (`updatedAt`)" + }, + { + "name": "index_web_apps_categoryId", + "unique": false, + "columnNames": [ + "categoryId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_categoryId` ON `${TABLE_NAME}` (`categoryId`)" + }, + { + "name": "index_web_apps_isActivated", + "unique": false, + "columnNames": [ + "isActivated" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_isActivated` ON `${TABLE_NAME}` (`isActivated`)" + }, + { + "name": "index_web_apps_appType_url", + "unique": false, + "columnNames": [ + "appType", + "url" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_appType_url` ON `${TABLE_NAME}` (`appType`, `url`)" + }, + { + "name": "index_web_apps_appType_iconPath_url", + "unique": false, + "columnNames": [ + "appType", + "iconPath", + "url" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_appType_iconPath_url` ON `${TABLE_NAME}` (`appType`, `iconPath`, `url`)" + } + ] + }, + { + "tableName": "app_categories", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `icon` TEXT NOT NULL, `color` TEXT NOT NULL, `sortOrder` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sortOrder", + "columnName": "sortOrder", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + } + }, + { + "tableName": "app_usage_stats", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `appId` INTEGER NOT NULL, `launchCount` INTEGER NOT NULL, `totalUsageMs` INTEGER NOT NULL, `lastUsedAt` INTEGER NOT NULL, `lastSessionDurationMs` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, FOREIGN KEY(`appId`) REFERENCES `web_apps`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "appId", + "columnName": "appId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "launchCount", + "columnName": "launchCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "totalUsageMs", + "columnName": "totalUsageMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastUsedAt", + "columnName": "lastUsedAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastSessionDurationMs", + "columnName": "lastSessionDurationMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_app_usage_stats_appId", + "unique": true, + "columnNames": [ + "appId" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_app_usage_stats_appId` ON `${TABLE_NAME}` (`appId`)" + }, + { + "name": "index_app_usage_stats_lastUsedAt", + "unique": false, + "columnNames": [ + "lastUsedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_usage_stats_lastUsedAt` ON `${TABLE_NAME}` (`lastUsedAt`)" + }, + { + "name": "index_app_usage_stats_launchCount", + "unique": false, + "columnNames": [ + "launchCount" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_usage_stats_launchCount` ON `${TABLE_NAME}` (`launchCount`)" + } + ], + "foreignKeys": [ + { + "table": "web_apps", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "appId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "app_health_records", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `appId` INTEGER NOT NULL, `url` TEXT NOT NULL, `status` TEXT NOT NULL, `responseTimeMs` INTEGER NOT NULL, `httpStatusCode` INTEGER NOT NULL, `errorMessage` TEXT, `checkedAt` INTEGER NOT NULL, FOREIGN KEY(`appId`) REFERENCES `web_apps`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "appId", + "columnName": "appId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "responseTimeMs", + "columnName": "responseTimeMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "httpStatusCode", + "columnName": "httpStatusCode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "errorMessage", + "columnName": "errorMessage", + "affinity": "TEXT" + }, + { + "fieldPath": "checkedAt", + "columnName": "checkedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_app_health_records_appId", + "unique": false, + "columnNames": [ + "appId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_health_records_appId` ON `${TABLE_NAME}` (`appId`)" + }, + { + "name": "index_app_health_records_checkedAt", + "unique": false, + "columnNames": [ + "checkedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_health_records_checkedAt` ON `${TABLE_NAME}` (`checkedAt`)" + } + ], + "foreignKeys": [ + { + "table": "web_apps", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "appId" + ], + "referencedColumns": [ + "id" + ] + } + ] + } + ], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '643c6f9480593253e00702649c9f1737')" + ] + } +} \ No newline at end of file diff --git a/app/schemas/com.webtoapp.data.database.AppDatabase/38.json b/app/schemas/com.webtoapp.data.database.AppDatabase/38.json new file mode 100644 index 0000000..193393e --- /dev/null +++ b/app/schemas/com.webtoapp.data.database.AppDatabase/38.json @@ -0,0 +1,578 @@ +{ + "formatVersion": 1, + "database": { + "version": 38, + "identityHash": "983cf11423592851e73dc30dd6bb36e3", + "entities": [ + { + "tableName": "web_apps", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `url` TEXT NOT NULL, `iconPath` TEXT, `packageName` TEXT, `appType` TEXT NOT NULL, `mediaConfig` TEXT, `galleryConfig` TEXT, `htmlConfig` TEXT, `wordpressConfig` TEXT, `nodejsConfig` TEXT, `phpAppConfig` TEXT, `pythonAppConfig` TEXT, `goAppConfig` TEXT, `multiWebConfig` TEXT, `activationEnabled` INTEGER NOT NULL, `activationCodeList` TEXT NOT NULL, `activationRequireEveryTime` INTEGER NOT NULL, `activationRemoteConfig` TEXT, `isActivated` INTEGER NOT NULL, `adsEnabled` INTEGER NOT NULL, `adConfig` TEXT, `announcementEnabled` INTEGER NOT NULL, `announcement` TEXT, `adBlockEnabled` INTEGER NOT NULL, `adBlockRules` TEXT NOT NULL, `adBlockSubscriptions` TEXT NOT NULL, `webViewConfig` TEXT NOT NULL, `splashEnabled` INTEGER NOT NULL, `splashConfig` TEXT, `bgmEnabled` INTEGER NOT NULL, `bgmConfig` TEXT, `apkExportConfig` TEXT, `themeType` TEXT NOT NULL, `translateEnabled` INTEGER NOT NULL, `translateConfig` TEXT, `extensionEnabled` INTEGER NOT NULL, `extensionModuleIds` TEXT NOT NULL, `extensionFabIcon` TEXT, `autoStartConfig` TEXT, `forcedRunConfig` TEXT, `blackTechConfig` TEXT, `disguiseConfig` TEXT, `browserDisguiseConfig` TEXT, `deviceDisguiseConfig` TEXT, `activationDialogConfig` TEXT, `categoryId` INTEGER, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "iconPath", + "columnName": "iconPath", + "affinity": "TEXT" + }, + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT" + }, + { + "fieldPath": "appType", + "columnName": "appType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "mediaConfig", + "columnName": "mediaConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "galleryConfig", + "columnName": "galleryConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "htmlConfig", + "columnName": "htmlConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "wordpressConfig", + "columnName": "wordpressConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "nodejsConfig", + "columnName": "nodejsConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "phpAppConfig", + "columnName": "phpAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "pythonAppConfig", + "columnName": "pythonAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "goAppConfig", + "columnName": "goAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "multiWebConfig", + "columnName": "multiWebConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "activationEnabled", + "columnName": "activationEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "activationCodeList", + "columnName": "activationCodeList", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "activationRequireEveryTime", + "columnName": "activationRequireEveryTime", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "activationRemoteConfig", + "columnName": "activationRemoteConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "isActivated", + "columnName": "isActivated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adsEnabled", + "columnName": "adsEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adConfig", + "columnName": "adConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "announcementEnabled", + "columnName": "announcementEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "announcement", + "columnName": "announcement", + "affinity": "TEXT" + }, + { + "fieldPath": "adBlockEnabled", + "columnName": "adBlockEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adBlockRules", + "columnName": "adBlockRules", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "adBlockSubscriptions", + "columnName": "adBlockSubscriptions", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "webViewConfig", + "columnName": "webViewConfig", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "splashEnabled", + "columnName": "splashEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "splashConfig", + "columnName": "splashConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "bgmEnabled", + "columnName": "bgmEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bgmConfig", + "columnName": "bgmConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "apkExportConfig", + "columnName": "apkExportConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "themeType", + "columnName": "themeType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "translateEnabled", + "columnName": "translateEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "translateConfig", + "columnName": "translateConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "extensionEnabled", + "columnName": "extensionEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "extensionModuleIds", + "columnName": "extensionModuleIds", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "extensionFabIcon", + "columnName": "extensionFabIcon", + "affinity": "TEXT" + }, + { + "fieldPath": "autoStartConfig", + "columnName": "autoStartConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "forcedRunConfig", + "columnName": "forcedRunConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "blackTechConfig", + "columnName": "blackTechConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "disguiseConfig", + "columnName": "disguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "browserDisguiseConfig", + "columnName": "browserDisguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "deviceDisguiseConfig", + "columnName": "deviceDisguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "activationDialogConfig", + "columnName": "activationDialogConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "categoryId", + "columnName": "categoryId", + "affinity": "INTEGER" + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "updatedAt", + "columnName": "updatedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_web_apps_updatedAt", + "unique": false, + "columnNames": [ + "updatedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_updatedAt` ON `${TABLE_NAME}` (`updatedAt`)" + }, + { + "name": "index_web_apps_categoryId", + "unique": false, + "columnNames": [ + "categoryId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_categoryId` ON `${TABLE_NAME}` (`categoryId`)" + }, + { + "name": "index_web_apps_isActivated", + "unique": false, + "columnNames": [ + "isActivated" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_isActivated` ON `${TABLE_NAME}` (`isActivated`)" + }, + { + "name": "index_web_apps_appType_url", + "unique": false, + "columnNames": [ + "appType", + "url" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_appType_url` ON `${TABLE_NAME}` (`appType`, `url`)" + }, + { + "name": "index_web_apps_appType_iconPath_url", + "unique": false, + "columnNames": [ + "appType", + "iconPath", + "url" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_appType_iconPath_url` ON `${TABLE_NAME}` (`appType`, `iconPath`, `url`)" + } + ] + }, + { + "tableName": "app_categories", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `icon` TEXT NOT NULL, `color` TEXT NOT NULL, `sortOrder` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sortOrder", + "columnName": "sortOrder", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + } + }, + { + "tableName": "app_usage_stats", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `appId` INTEGER NOT NULL, `launchCount` INTEGER NOT NULL, `totalUsageMs` INTEGER NOT NULL, `lastUsedAt` INTEGER NOT NULL, `lastSessionDurationMs` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, FOREIGN KEY(`appId`) REFERENCES `web_apps`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "appId", + "columnName": "appId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "launchCount", + "columnName": "launchCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "totalUsageMs", + "columnName": "totalUsageMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastUsedAt", + "columnName": "lastUsedAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastSessionDurationMs", + "columnName": "lastSessionDurationMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_app_usage_stats_appId", + "unique": true, + "columnNames": [ + "appId" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_app_usage_stats_appId` ON `${TABLE_NAME}` (`appId`)" + }, + { + "name": "index_app_usage_stats_lastUsedAt", + "unique": false, + "columnNames": [ + "lastUsedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_usage_stats_lastUsedAt` ON `${TABLE_NAME}` (`lastUsedAt`)" + }, + { + "name": "index_app_usage_stats_launchCount", + "unique": false, + "columnNames": [ + "launchCount" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_usage_stats_launchCount` ON `${TABLE_NAME}` (`launchCount`)" + } + ], + "foreignKeys": [ + { + "table": "web_apps", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "appId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "app_health_records", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `appId` INTEGER NOT NULL, `url` TEXT NOT NULL, `status` TEXT NOT NULL, `responseTimeMs` INTEGER NOT NULL, `httpStatusCode` INTEGER NOT NULL, `errorMessage` TEXT, `checkedAt` INTEGER NOT NULL, FOREIGN KEY(`appId`) REFERENCES `web_apps`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "appId", + "columnName": "appId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "responseTimeMs", + "columnName": "responseTimeMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "httpStatusCode", + "columnName": "httpStatusCode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "errorMessage", + "columnName": "errorMessage", + "affinity": "TEXT" + }, + { + "fieldPath": "checkedAt", + "columnName": "checkedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_app_health_records_appId", + "unique": false, + "columnNames": [ + "appId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_health_records_appId` ON `${TABLE_NAME}` (`appId`)" + }, + { + "name": "index_app_health_records_checkedAt", + "unique": false, + "columnNames": [ + "checkedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_health_records_checkedAt` ON `${TABLE_NAME}` (`checkedAt`)" + } + ], + "foreignKeys": [ + { + "table": "web_apps", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "appId" + ], + "referencedColumns": [ + "id" + ] + } + ] + } + ], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '983cf11423592851e73dc30dd6bb36e3')" + ] + } +} \ No newline at end of file diff --git a/app/schemas/com.webtoapp.data.database.AppDatabase/39.json b/app/schemas/com.webtoapp.data.database.AppDatabase/39.json new file mode 100644 index 0000000..ed0d4d7 --- /dev/null +++ b/app/schemas/com.webtoapp.data.database.AppDatabase/39.json @@ -0,0 +1,578 @@ +{ + "formatVersion": 1, + "database": { + "version": 39, + "identityHash": "983cf11423592851e73dc30dd6bb36e3", + "entities": [ + { + "tableName": "web_apps", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `url` TEXT NOT NULL, `iconPath` TEXT, `packageName` TEXT, `appType` TEXT NOT NULL, `mediaConfig` TEXT, `galleryConfig` TEXT, `htmlConfig` TEXT, `wordpressConfig` TEXT, `nodejsConfig` TEXT, `phpAppConfig` TEXT, `pythonAppConfig` TEXT, `goAppConfig` TEXT, `multiWebConfig` TEXT, `activationEnabled` INTEGER NOT NULL, `activationCodeList` TEXT NOT NULL, `activationRequireEveryTime` INTEGER NOT NULL, `activationRemoteConfig` TEXT, `isActivated` INTEGER NOT NULL, `adsEnabled` INTEGER NOT NULL, `adConfig` TEXT, `announcementEnabled` INTEGER NOT NULL, `announcement` TEXT, `adBlockEnabled` INTEGER NOT NULL, `adBlockRules` TEXT NOT NULL, `adBlockSubscriptions` TEXT NOT NULL, `webViewConfig` TEXT NOT NULL, `splashEnabled` INTEGER NOT NULL, `splashConfig` TEXT, `bgmEnabled` INTEGER NOT NULL, `bgmConfig` TEXT, `apkExportConfig` TEXT, `themeType` TEXT NOT NULL, `translateEnabled` INTEGER NOT NULL, `translateConfig` TEXT, `extensionEnabled` INTEGER NOT NULL, `extensionModuleIds` TEXT NOT NULL, `extensionFabIcon` TEXT, `autoStartConfig` TEXT, `forcedRunConfig` TEXT, `blackTechConfig` TEXT, `disguiseConfig` TEXT, `browserDisguiseConfig` TEXT, `deviceDisguiseConfig` TEXT, `activationDialogConfig` TEXT, `categoryId` INTEGER, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "iconPath", + "columnName": "iconPath", + "affinity": "TEXT" + }, + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT" + }, + { + "fieldPath": "appType", + "columnName": "appType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "mediaConfig", + "columnName": "mediaConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "galleryConfig", + "columnName": "galleryConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "htmlConfig", + "columnName": "htmlConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "wordpressConfig", + "columnName": "wordpressConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "nodejsConfig", + "columnName": "nodejsConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "phpAppConfig", + "columnName": "phpAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "pythonAppConfig", + "columnName": "pythonAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "goAppConfig", + "columnName": "goAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "multiWebConfig", + "columnName": "multiWebConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "activationEnabled", + "columnName": "activationEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "activationCodeList", + "columnName": "activationCodeList", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "activationRequireEveryTime", + "columnName": "activationRequireEveryTime", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "activationRemoteConfig", + "columnName": "activationRemoteConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "isActivated", + "columnName": "isActivated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adsEnabled", + "columnName": "adsEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adConfig", + "columnName": "adConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "announcementEnabled", + "columnName": "announcementEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "announcement", + "columnName": "announcement", + "affinity": "TEXT" + }, + { + "fieldPath": "adBlockEnabled", + "columnName": "adBlockEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adBlockRules", + "columnName": "adBlockRules", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "adBlockSubscriptions", + "columnName": "adBlockSubscriptions", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "webViewConfig", + "columnName": "webViewConfig", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "splashEnabled", + "columnName": "splashEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "splashConfig", + "columnName": "splashConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "bgmEnabled", + "columnName": "bgmEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bgmConfig", + "columnName": "bgmConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "apkExportConfig", + "columnName": "apkExportConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "themeType", + "columnName": "themeType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "translateEnabled", + "columnName": "translateEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "translateConfig", + "columnName": "translateConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "extensionEnabled", + "columnName": "extensionEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "extensionModuleIds", + "columnName": "extensionModuleIds", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "extensionFabIcon", + "columnName": "extensionFabIcon", + "affinity": "TEXT" + }, + { + "fieldPath": "autoStartConfig", + "columnName": "autoStartConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "forcedRunConfig", + "columnName": "forcedRunConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "blackTechConfig", + "columnName": "blackTechConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "disguiseConfig", + "columnName": "disguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "browserDisguiseConfig", + "columnName": "browserDisguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "deviceDisguiseConfig", + "columnName": "deviceDisguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "activationDialogConfig", + "columnName": "activationDialogConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "categoryId", + "columnName": "categoryId", + "affinity": "INTEGER" + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "updatedAt", + "columnName": "updatedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_web_apps_updatedAt", + "unique": false, + "columnNames": [ + "updatedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_updatedAt` ON `${TABLE_NAME}` (`updatedAt`)" + }, + { + "name": "index_web_apps_categoryId", + "unique": false, + "columnNames": [ + "categoryId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_categoryId` ON `${TABLE_NAME}` (`categoryId`)" + }, + { + "name": "index_web_apps_isActivated", + "unique": false, + "columnNames": [ + "isActivated" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_isActivated` ON `${TABLE_NAME}` (`isActivated`)" + }, + { + "name": "index_web_apps_appType_url", + "unique": false, + "columnNames": [ + "appType", + "url" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_appType_url` ON `${TABLE_NAME}` (`appType`, `url`)" + }, + { + "name": "index_web_apps_appType_iconPath_url", + "unique": false, + "columnNames": [ + "appType", + "iconPath", + "url" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_appType_iconPath_url` ON `${TABLE_NAME}` (`appType`, `iconPath`, `url`)" + } + ] + }, + { + "tableName": "app_categories", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `icon` TEXT NOT NULL, `color` TEXT NOT NULL, `sortOrder` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sortOrder", + "columnName": "sortOrder", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + } + }, + { + "tableName": "app_usage_stats", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `appId` INTEGER NOT NULL, `launchCount` INTEGER NOT NULL, `totalUsageMs` INTEGER NOT NULL, `lastUsedAt` INTEGER NOT NULL, `lastSessionDurationMs` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, FOREIGN KEY(`appId`) REFERENCES `web_apps`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "appId", + "columnName": "appId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "launchCount", + "columnName": "launchCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "totalUsageMs", + "columnName": "totalUsageMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastUsedAt", + "columnName": "lastUsedAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastSessionDurationMs", + "columnName": "lastSessionDurationMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_app_usage_stats_appId", + "unique": true, + "columnNames": [ + "appId" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_app_usage_stats_appId` ON `${TABLE_NAME}` (`appId`)" + }, + { + "name": "index_app_usage_stats_lastUsedAt", + "unique": false, + "columnNames": [ + "lastUsedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_usage_stats_lastUsedAt` ON `${TABLE_NAME}` (`lastUsedAt`)" + }, + { + "name": "index_app_usage_stats_launchCount", + "unique": false, + "columnNames": [ + "launchCount" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_usage_stats_launchCount` ON `${TABLE_NAME}` (`launchCount`)" + } + ], + "foreignKeys": [ + { + "table": "web_apps", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "appId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "app_health_records", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `appId` INTEGER NOT NULL, `url` TEXT NOT NULL, `status` TEXT NOT NULL, `responseTimeMs` INTEGER NOT NULL, `httpStatusCode` INTEGER NOT NULL, `errorMessage` TEXT, `checkedAt` INTEGER NOT NULL, FOREIGN KEY(`appId`) REFERENCES `web_apps`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "appId", + "columnName": "appId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "responseTimeMs", + "columnName": "responseTimeMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "httpStatusCode", + "columnName": "httpStatusCode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "errorMessage", + "columnName": "errorMessage", + "affinity": "TEXT" + }, + { + "fieldPath": "checkedAt", + "columnName": "checkedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_app_health_records_appId", + "unique": false, + "columnNames": [ + "appId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_health_records_appId` ON `${TABLE_NAME}` (`appId`)" + }, + { + "name": "index_app_health_records_checkedAt", + "unique": false, + "columnNames": [ + "checkedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_health_records_checkedAt` ON `${TABLE_NAME}` (`checkedAt`)" + } + ], + "foreignKeys": [ + { + "table": "web_apps", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "appId" + ], + "referencedColumns": [ + "id" + ] + } + ] + } + ], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '983cf11423592851e73dc30dd6bb36e3')" + ] + } +} \ No newline at end of file diff --git a/app/schemas/com.webtoapp.data.database.AppDatabase/40.json b/app/schemas/com.webtoapp.data.database.AppDatabase/40.json new file mode 100644 index 0000000..bb4cd70 --- /dev/null +++ b/app/schemas/com.webtoapp.data.database.AppDatabase/40.json @@ -0,0 +1,578 @@ +{ + "formatVersion": 1, + "database": { + "version": 40, + "identityHash": "983cf11423592851e73dc30dd6bb36e3", + "entities": [ + { + "tableName": "web_apps", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `url` TEXT NOT NULL, `iconPath` TEXT, `packageName` TEXT, `appType` TEXT NOT NULL, `mediaConfig` TEXT, `galleryConfig` TEXT, `htmlConfig` TEXT, `wordpressConfig` TEXT, `nodejsConfig` TEXT, `phpAppConfig` TEXT, `pythonAppConfig` TEXT, `goAppConfig` TEXT, `multiWebConfig` TEXT, `activationEnabled` INTEGER NOT NULL, `activationCodeList` TEXT NOT NULL, `activationRequireEveryTime` INTEGER NOT NULL, `activationRemoteConfig` TEXT, `isActivated` INTEGER NOT NULL, `adsEnabled` INTEGER NOT NULL, `adConfig` TEXT, `announcementEnabled` INTEGER NOT NULL, `announcement` TEXT, `adBlockEnabled` INTEGER NOT NULL, `adBlockRules` TEXT NOT NULL, `adBlockSubscriptions` TEXT NOT NULL, `webViewConfig` TEXT NOT NULL, `splashEnabled` INTEGER NOT NULL, `splashConfig` TEXT, `bgmEnabled` INTEGER NOT NULL, `bgmConfig` TEXT, `apkExportConfig` TEXT, `themeType` TEXT NOT NULL, `translateEnabled` INTEGER NOT NULL, `translateConfig` TEXT, `extensionEnabled` INTEGER NOT NULL, `extensionModuleIds` TEXT NOT NULL, `extensionFabIcon` TEXT, `autoStartConfig` TEXT, `forcedRunConfig` TEXT, `blackTechConfig` TEXT, `disguiseConfig` TEXT, `browserDisguiseConfig` TEXT, `deviceDisguiseConfig` TEXT, `activationDialogConfig` TEXT, `categoryId` INTEGER, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "iconPath", + "columnName": "iconPath", + "affinity": "TEXT" + }, + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT" + }, + { + "fieldPath": "appType", + "columnName": "appType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "mediaConfig", + "columnName": "mediaConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "galleryConfig", + "columnName": "galleryConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "htmlConfig", + "columnName": "htmlConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "wordpressConfig", + "columnName": "wordpressConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "nodejsConfig", + "columnName": "nodejsConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "phpAppConfig", + "columnName": "phpAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "pythonAppConfig", + "columnName": "pythonAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "goAppConfig", + "columnName": "goAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "multiWebConfig", + "columnName": "multiWebConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "activationEnabled", + "columnName": "activationEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "activationCodeList", + "columnName": "activationCodeList", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "activationRequireEveryTime", + "columnName": "activationRequireEveryTime", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "activationRemoteConfig", + "columnName": "activationRemoteConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "isActivated", + "columnName": "isActivated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adsEnabled", + "columnName": "adsEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adConfig", + "columnName": "adConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "announcementEnabled", + "columnName": "announcementEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "announcement", + "columnName": "announcement", + "affinity": "TEXT" + }, + { + "fieldPath": "adBlockEnabled", + "columnName": "adBlockEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adBlockRules", + "columnName": "adBlockRules", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "adBlockSubscriptions", + "columnName": "adBlockSubscriptions", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "webViewConfig", + "columnName": "webViewConfig", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "splashEnabled", + "columnName": "splashEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "splashConfig", + "columnName": "splashConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "bgmEnabled", + "columnName": "bgmEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bgmConfig", + "columnName": "bgmConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "apkExportConfig", + "columnName": "apkExportConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "themeType", + "columnName": "themeType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "translateEnabled", + "columnName": "translateEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "translateConfig", + "columnName": "translateConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "extensionEnabled", + "columnName": "extensionEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "extensionModuleIds", + "columnName": "extensionModuleIds", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "extensionFabIcon", + "columnName": "extensionFabIcon", + "affinity": "TEXT" + }, + { + "fieldPath": "autoStartConfig", + "columnName": "autoStartConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "forcedRunConfig", + "columnName": "forcedRunConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "blackTechConfig", + "columnName": "blackTechConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "disguiseConfig", + "columnName": "disguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "browserDisguiseConfig", + "columnName": "browserDisguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "deviceDisguiseConfig", + "columnName": "deviceDisguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "activationDialogConfig", + "columnName": "activationDialogConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "categoryId", + "columnName": "categoryId", + "affinity": "INTEGER" + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "updatedAt", + "columnName": "updatedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_web_apps_updatedAt", + "unique": false, + "columnNames": [ + "updatedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_updatedAt` ON `${TABLE_NAME}` (`updatedAt`)" + }, + { + "name": "index_web_apps_categoryId", + "unique": false, + "columnNames": [ + "categoryId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_categoryId` ON `${TABLE_NAME}` (`categoryId`)" + }, + { + "name": "index_web_apps_isActivated", + "unique": false, + "columnNames": [ + "isActivated" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_isActivated` ON `${TABLE_NAME}` (`isActivated`)" + }, + { + "name": "index_web_apps_appType_url", + "unique": false, + "columnNames": [ + "appType", + "url" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_appType_url` ON `${TABLE_NAME}` (`appType`, `url`)" + }, + { + "name": "index_web_apps_appType_iconPath_url", + "unique": false, + "columnNames": [ + "appType", + "iconPath", + "url" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_appType_iconPath_url` ON `${TABLE_NAME}` (`appType`, `iconPath`, `url`)" + } + ] + }, + { + "tableName": "app_categories", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `icon` TEXT NOT NULL, `color` TEXT NOT NULL, `sortOrder` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sortOrder", + "columnName": "sortOrder", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + } + }, + { + "tableName": "app_usage_stats", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `appId` INTEGER NOT NULL, `launchCount` INTEGER NOT NULL, `totalUsageMs` INTEGER NOT NULL, `lastUsedAt` INTEGER NOT NULL, `lastSessionDurationMs` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, FOREIGN KEY(`appId`) REFERENCES `web_apps`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "appId", + "columnName": "appId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "launchCount", + "columnName": "launchCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "totalUsageMs", + "columnName": "totalUsageMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastUsedAt", + "columnName": "lastUsedAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastSessionDurationMs", + "columnName": "lastSessionDurationMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_app_usage_stats_appId", + "unique": true, + "columnNames": [ + "appId" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_app_usage_stats_appId` ON `${TABLE_NAME}` (`appId`)" + }, + { + "name": "index_app_usage_stats_lastUsedAt", + "unique": false, + "columnNames": [ + "lastUsedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_usage_stats_lastUsedAt` ON `${TABLE_NAME}` (`lastUsedAt`)" + }, + { + "name": "index_app_usage_stats_launchCount", + "unique": false, + "columnNames": [ + "launchCount" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_usage_stats_launchCount` ON `${TABLE_NAME}` (`launchCount`)" + } + ], + "foreignKeys": [ + { + "table": "web_apps", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "appId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "app_health_records", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `appId` INTEGER NOT NULL, `url` TEXT NOT NULL, `status` TEXT NOT NULL, `responseTimeMs` INTEGER NOT NULL, `httpStatusCode` INTEGER NOT NULL, `errorMessage` TEXT, `checkedAt` INTEGER NOT NULL, FOREIGN KEY(`appId`) REFERENCES `web_apps`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "appId", + "columnName": "appId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "responseTimeMs", + "columnName": "responseTimeMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "httpStatusCode", + "columnName": "httpStatusCode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "errorMessage", + "columnName": "errorMessage", + "affinity": "TEXT" + }, + { + "fieldPath": "checkedAt", + "columnName": "checkedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_app_health_records_appId", + "unique": false, + "columnNames": [ + "appId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_health_records_appId` ON `${TABLE_NAME}` (`appId`)" + }, + { + "name": "index_app_health_records_checkedAt", + "unique": false, + "columnNames": [ + "checkedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_health_records_checkedAt` ON `${TABLE_NAME}` (`checkedAt`)" + } + ], + "foreignKeys": [ + { + "table": "web_apps", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "appId" + ], + "referencedColumns": [ + "id" + ] + } + ] + } + ], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '983cf11423592851e73dc30dd6bb36e3')" + ] + } +} \ No newline at end of file diff --git a/app/schemas/com.webtoapp.data.database.AppDatabase/41.json b/app/schemas/com.webtoapp.data.database.AppDatabase/41.json new file mode 100644 index 0000000..e920a6c --- /dev/null +++ b/app/schemas/com.webtoapp.data.database.AppDatabase/41.json @@ -0,0 +1,573 @@ +{ + "formatVersion": 1, + "database": { + "version": 41, + "identityHash": "d5e920fa16e9de9b732ae1a50957f218", + "entities": [ + { + "tableName": "web_apps", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `url` TEXT NOT NULL, `iconPath` TEXT, `packageName` TEXT, `appType` TEXT NOT NULL, `mediaConfig` TEXT, `galleryConfig` TEXT, `htmlConfig` TEXT, `wordpressConfig` TEXT, `nodejsConfig` TEXT, `phpAppConfig` TEXT, `pythonAppConfig` TEXT, `goAppConfig` TEXT, `multiWebConfig` TEXT, `activationEnabled` INTEGER NOT NULL, `activationCodeList` TEXT NOT NULL, `activationRequireEveryTime` INTEGER NOT NULL, `activationRemoteConfig` TEXT, `isActivated` INTEGER NOT NULL, `adsEnabled` INTEGER NOT NULL, `adConfig` TEXT, `announcementEnabled` INTEGER NOT NULL, `announcement` TEXT, `adBlockEnabled` INTEGER NOT NULL, `adBlockRules` TEXT NOT NULL, `adBlockSubscriptions` TEXT NOT NULL, `webViewConfig` TEXT NOT NULL, `splashEnabled` INTEGER NOT NULL, `splashConfig` TEXT, `bgmEnabled` INTEGER NOT NULL, `bgmConfig` TEXT, `apkExportConfig` TEXT, `themeType` TEXT NOT NULL, `translateEnabled` INTEGER NOT NULL, `translateConfig` TEXT, `extensionEnabled` INTEGER NOT NULL, `extensionModuleIds` TEXT NOT NULL, `extensionFabIcon` TEXT, `autoStartConfig` TEXT, `forcedRunConfig` TEXT, `disguiseConfig` TEXT, `browserDisguiseConfig` TEXT, `deviceDisguiseConfig` TEXT, `activationDialogConfig` TEXT, `categoryId` INTEGER, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "iconPath", + "columnName": "iconPath", + "affinity": "TEXT" + }, + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT" + }, + { + "fieldPath": "appType", + "columnName": "appType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "mediaConfig", + "columnName": "mediaConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "galleryConfig", + "columnName": "galleryConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "htmlConfig", + "columnName": "htmlConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "wordpressConfig", + "columnName": "wordpressConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "nodejsConfig", + "columnName": "nodejsConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "phpAppConfig", + "columnName": "phpAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "pythonAppConfig", + "columnName": "pythonAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "goAppConfig", + "columnName": "goAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "multiWebConfig", + "columnName": "multiWebConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "activationEnabled", + "columnName": "activationEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "activationCodeList", + "columnName": "activationCodeList", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "activationRequireEveryTime", + "columnName": "activationRequireEveryTime", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "activationRemoteConfig", + "columnName": "activationRemoteConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "isActivated", + "columnName": "isActivated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adsEnabled", + "columnName": "adsEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adConfig", + "columnName": "adConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "announcementEnabled", + "columnName": "announcementEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "announcement", + "columnName": "announcement", + "affinity": "TEXT" + }, + { + "fieldPath": "adBlockEnabled", + "columnName": "adBlockEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adBlockRules", + "columnName": "adBlockRules", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "adBlockSubscriptions", + "columnName": "adBlockSubscriptions", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "webViewConfig", + "columnName": "webViewConfig", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "splashEnabled", + "columnName": "splashEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "splashConfig", + "columnName": "splashConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "bgmEnabled", + "columnName": "bgmEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bgmConfig", + "columnName": "bgmConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "apkExportConfig", + "columnName": "apkExportConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "themeType", + "columnName": "themeType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "translateEnabled", + "columnName": "translateEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "translateConfig", + "columnName": "translateConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "extensionEnabled", + "columnName": "extensionEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "extensionModuleIds", + "columnName": "extensionModuleIds", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "extensionFabIcon", + "columnName": "extensionFabIcon", + "affinity": "TEXT" + }, + { + "fieldPath": "autoStartConfig", + "columnName": "autoStartConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "forcedRunConfig", + "columnName": "forcedRunConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "disguiseConfig", + "columnName": "disguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "browserDisguiseConfig", + "columnName": "browserDisguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "deviceDisguiseConfig", + "columnName": "deviceDisguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "activationDialogConfig", + "columnName": "activationDialogConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "categoryId", + "columnName": "categoryId", + "affinity": "INTEGER" + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "updatedAt", + "columnName": "updatedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_web_apps_updatedAt", + "unique": false, + "columnNames": [ + "updatedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_updatedAt` ON `${TABLE_NAME}` (`updatedAt`)" + }, + { + "name": "index_web_apps_categoryId", + "unique": false, + "columnNames": [ + "categoryId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_categoryId` ON `${TABLE_NAME}` (`categoryId`)" + }, + { + "name": "index_web_apps_isActivated", + "unique": false, + "columnNames": [ + "isActivated" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_isActivated` ON `${TABLE_NAME}` (`isActivated`)" + }, + { + "name": "index_web_apps_appType_url", + "unique": false, + "columnNames": [ + "appType", + "url" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_appType_url` ON `${TABLE_NAME}` (`appType`, `url`)" + }, + { + "name": "index_web_apps_appType_iconPath_url", + "unique": false, + "columnNames": [ + "appType", + "iconPath", + "url" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_appType_iconPath_url` ON `${TABLE_NAME}` (`appType`, `iconPath`, `url`)" + } + ] + }, + { + "tableName": "app_categories", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `icon` TEXT NOT NULL, `color` TEXT NOT NULL, `sortOrder` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sortOrder", + "columnName": "sortOrder", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + } + }, + { + "tableName": "app_usage_stats", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `appId` INTEGER NOT NULL, `launchCount` INTEGER NOT NULL, `totalUsageMs` INTEGER NOT NULL, `lastUsedAt` INTEGER NOT NULL, `lastSessionDurationMs` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, FOREIGN KEY(`appId`) REFERENCES `web_apps`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "appId", + "columnName": "appId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "launchCount", + "columnName": "launchCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "totalUsageMs", + "columnName": "totalUsageMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastUsedAt", + "columnName": "lastUsedAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastSessionDurationMs", + "columnName": "lastSessionDurationMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_app_usage_stats_appId", + "unique": true, + "columnNames": [ + "appId" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_app_usage_stats_appId` ON `${TABLE_NAME}` (`appId`)" + }, + { + "name": "index_app_usage_stats_lastUsedAt", + "unique": false, + "columnNames": [ + "lastUsedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_usage_stats_lastUsedAt` ON `${TABLE_NAME}` (`lastUsedAt`)" + }, + { + "name": "index_app_usage_stats_launchCount", + "unique": false, + "columnNames": [ + "launchCount" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_usage_stats_launchCount` ON `${TABLE_NAME}` (`launchCount`)" + } + ], + "foreignKeys": [ + { + "table": "web_apps", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "appId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "app_health_records", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `appId` INTEGER NOT NULL, `url` TEXT NOT NULL, `status` TEXT NOT NULL, `responseTimeMs` INTEGER NOT NULL, `httpStatusCode` INTEGER NOT NULL, `errorMessage` TEXT, `checkedAt` INTEGER NOT NULL, FOREIGN KEY(`appId`) REFERENCES `web_apps`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "appId", + "columnName": "appId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "responseTimeMs", + "columnName": "responseTimeMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "httpStatusCode", + "columnName": "httpStatusCode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "errorMessage", + "columnName": "errorMessage", + "affinity": "TEXT" + }, + { + "fieldPath": "checkedAt", + "columnName": "checkedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_app_health_records_appId", + "unique": false, + "columnNames": [ + "appId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_health_records_appId` ON `${TABLE_NAME}` (`appId`)" + }, + { + "name": "index_app_health_records_checkedAt", + "unique": false, + "columnNames": [ + "checkedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_health_records_checkedAt` ON `${TABLE_NAME}` (`checkedAt`)" + } + ], + "foreignKeys": [ + { + "table": "web_apps", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "appId" + ], + "referencedColumns": [ + "id" + ] + } + ] + } + ], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd5e920fa16e9de9b732ae1a50957f218')" + ] + } +} \ No newline at end of file diff --git a/app/schemas/com.webtoapp.data.database.AppDatabase/42.json b/app/schemas/com.webtoapp.data.database.AppDatabase/42.json new file mode 100644 index 0000000..1895f27 --- /dev/null +++ b/app/schemas/com.webtoapp.data.database.AppDatabase/42.json @@ -0,0 +1,568 @@ +{ + "formatVersion": 1, + "database": { + "version": 42, + "identityHash": "c7e4c9285c607540b9f15d79ad87c359", + "entities": [ + { + "tableName": "web_apps", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `url` TEXT NOT NULL, `iconPath` TEXT, `packageName` TEXT, `appType` TEXT NOT NULL, `mediaConfig` TEXT, `galleryConfig` TEXT, `htmlConfig` TEXT, `wordpressConfig` TEXT, `nodejsConfig` TEXT, `phpAppConfig` TEXT, `pythonAppConfig` TEXT, `goAppConfig` TEXT, `multiWebConfig` TEXT, `activationEnabled` INTEGER NOT NULL, `activationCodeList` TEXT NOT NULL, `activationRequireEveryTime` INTEGER NOT NULL, `activationRemoteConfig` TEXT, `isActivated` INTEGER NOT NULL, `adsEnabled` INTEGER NOT NULL, `adConfig` TEXT, `announcementEnabled` INTEGER NOT NULL, `announcement` TEXT, `adBlockEnabled` INTEGER NOT NULL, `adBlockRules` TEXT NOT NULL, `adBlockSubscriptions` TEXT NOT NULL, `webViewConfig` TEXT NOT NULL, `splashEnabled` INTEGER NOT NULL, `splashConfig` TEXT, `bgmEnabled` INTEGER NOT NULL, `bgmConfig` TEXT, `apkExportConfig` TEXT, `themeType` TEXT NOT NULL, `translateEnabled` INTEGER NOT NULL, `translateConfig` TEXT, `extensionEnabled` INTEGER NOT NULL, `extensionModuleIds` TEXT NOT NULL, `extensionFabIcon` TEXT, `autoStartConfig` TEXT, `disguiseConfig` TEXT, `browserDisguiseConfig` TEXT, `deviceDisguiseConfig` TEXT, `activationDialogConfig` TEXT, `categoryId` INTEGER, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "iconPath", + "columnName": "iconPath", + "affinity": "TEXT" + }, + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT" + }, + { + "fieldPath": "appType", + "columnName": "appType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "mediaConfig", + "columnName": "mediaConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "galleryConfig", + "columnName": "galleryConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "htmlConfig", + "columnName": "htmlConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "wordpressConfig", + "columnName": "wordpressConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "nodejsConfig", + "columnName": "nodejsConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "phpAppConfig", + "columnName": "phpAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "pythonAppConfig", + "columnName": "pythonAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "goAppConfig", + "columnName": "goAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "multiWebConfig", + "columnName": "multiWebConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "activationEnabled", + "columnName": "activationEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "activationCodeList", + "columnName": "activationCodeList", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "activationRequireEveryTime", + "columnName": "activationRequireEveryTime", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "activationRemoteConfig", + "columnName": "activationRemoteConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "isActivated", + "columnName": "isActivated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adsEnabled", + "columnName": "adsEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adConfig", + "columnName": "adConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "announcementEnabled", + "columnName": "announcementEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "announcement", + "columnName": "announcement", + "affinity": "TEXT" + }, + { + "fieldPath": "adBlockEnabled", + "columnName": "adBlockEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adBlockRules", + "columnName": "adBlockRules", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "adBlockSubscriptions", + "columnName": "adBlockSubscriptions", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "webViewConfig", + "columnName": "webViewConfig", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "splashEnabled", + "columnName": "splashEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "splashConfig", + "columnName": "splashConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "bgmEnabled", + "columnName": "bgmEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bgmConfig", + "columnName": "bgmConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "apkExportConfig", + "columnName": "apkExportConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "themeType", + "columnName": "themeType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "translateEnabled", + "columnName": "translateEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "translateConfig", + "columnName": "translateConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "extensionEnabled", + "columnName": "extensionEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "extensionModuleIds", + "columnName": "extensionModuleIds", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "extensionFabIcon", + "columnName": "extensionFabIcon", + "affinity": "TEXT" + }, + { + "fieldPath": "autoStartConfig", + "columnName": "autoStartConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "disguiseConfig", + "columnName": "disguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "browserDisguiseConfig", + "columnName": "browserDisguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "deviceDisguiseConfig", + "columnName": "deviceDisguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "activationDialogConfig", + "columnName": "activationDialogConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "categoryId", + "columnName": "categoryId", + "affinity": "INTEGER" + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "updatedAt", + "columnName": "updatedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_web_apps_updatedAt", + "unique": false, + "columnNames": [ + "updatedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_updatedAt` ON `${TABLE_NAME}` (`updatedAt`)" + }, + { + "name": "index_web_apps_categoryId", + "unique": false, + "columnNames": [ + "categoryId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_categoryId` ON `${TABLE_NAME}` (`categoryId`)" + }, + { + "name": "index_web_apps_isActivated", + "unique": false, + "columnNames": [ + "isActivated" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_isActivated` ON `${TABLE_NAME}` (`isActivated`)" + }, + { + "name": "index_web_apps_appType_url", + "unique": false, + "columnNames": [ + "appType", + "url" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_appType_url` ON `${TABLE_NAME}` (`appType`, `url`)" + }, + { + "name": "index_web_apps_appType_iconPath_url", + "unique": false, + "columnNames": [ + "appType", + "iconPath", + "url" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_appType_iconPath_url` ON `${TABLE_NAME}` (`appType`, `iconPath`, `url`)" + } + ] + }, + { + "tableName": "app_categories", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `icon` TEXT NOT NULL, `color` TEXT NOT NULL, `sortOrder` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sortOrder", + "columnName": "sortOrder", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + } + }, + { + "tableName": "app_usage_stats", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `appId` INTEGER NOT NULL, `launchCount` INTEGER NOT NULL, `totalUsageMs` INTEGER NOT NULL, `lastUsedAt` INTEGER NOT NULL, `lastSessionDurationMs` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, FOREIGN KEY(`appId`) REFERENCES `web_apps`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "appId", + "columnName": "appId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "launchCount", + "columnName": "launchCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "totalUsageMs", + "columnName": "totalUsageMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastUsedAt", + "columnName": "lastUsedAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastSessionDurationMs", + "columnName": "lastSessionDurationMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_app_usage_stats_appId", + "unique": true, + "columnNames": [ + "appId" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_app_usage_stats_appId` ON `${TABLE_NAME}` (`appId`)" + }, + { + "name": "index_app_usage_stats_lastUsedAt", + "unique": false, + "columnNames": [ + "lastUsedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_usage_stats_lastUsedAt` ON `${TABLE_NAME}` (`lastUsedAt`)" + }, + { + "name": "index_app_usage_stats_launchCount", + "unique": false, + "columnNames": [ + "launchCount" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_usage_stats_launchCount` ON `${TABLE_NAME}` (`launchCount`)" + } + ], + "foreignKeys": [ + { + "table": "web_apps", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "appId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "app_health_records", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `appId` INTEGER NOT NULL, `url` TEXT NOT NULL, `status` TEXT NOT NULL, `responseTimeMs` INTEGER NOT NULL, `httpStatusCode` INTEGER NOT NULL, `errorMessage` TEXT, `checkedAt` INTEGER NOT NULL, FOREIGN KEY(`appId`) REFERENCES `web_apps`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "appId", + "columnName": "appId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "responseTimeMs", + "columnName": "responseTimeMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "httpStatusCode", + "columnName": "httpStatusCode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "errorMessage", + "columnName": "errorMessage", + "affinity": "TEXT" + }, + { + "fieldPath": "checkedAt", + "columnName": "checkedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_app_health_records_appId", + "unique": false, + "columnNames": [ + "appId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_health_records_appId` ON `${TABLE_NAME}` (`appId`)" + }, + { + "name": "index_app_health_records_checkedAt", + "unique": false, + "columnNames": [ + "checkedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_health_records_checkedAt` ON `${TABLE_NAME}` (`checkedAt`)" + } + ], + "foreignKeys": [ + { + "table": "web_apps", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "appId" + ], + "referencedColumns": [ + "id" + ] + } + ] + } + ], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'c7e4c9285c607540b9f15d79ad87c359')" + ] + } +} \ No newline at end of file diff --git a/app/schemas/com.webtoapp.data.database.AppDatabase/43.json b/app/schemas/com.webtoapp.data.database.AppDatabase/43.json new file mode 100644 index 0000000..fba13e9 --- /dev/null +++ b/app/schemas/com.webtoapp.data.database.AppDatabase/43.json @@ -0,0 +1,563 @@ +{ + "formatVersion": 1, + "database": { + "version": 43, + "identityHash": "ea6b40911e9117204ec107ff693031d7", + "entities": [ + { + "tableName": "web_apps", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `url` TEXT NOT NULL, `iconPath` TEXT, `packageName` TEXT, `appType` TEXT NOT NULL, `mediaConfig` TEXT, `galleryConfig` TEXT, `htmlConfig` TEXT, `wordpressConfig` TEXT, `nodejsConfig` TEXT, `phpAppConfig` TEXT, `pythonAppConfig` TEXT, `goAppConfig` TEXT, `multiWebConfig` TEXT, `activationEnabled` INTEGER NOT NULL, `activationCodeList` TEXT NOT NULL, `activationRequireEveryTime` INTEGER NOT NULL, `activationRemoteConfig` TEXT, `isActivated` INTEGER NOT NULL, `adsEnabled` INTEGER NOT NULL, `adConfig` TEXT, `announcementEnabled` INTEGER NOT NULL, `announcement` TEXT, `adBlockEnabled` INTEGER NOT NULL, `adBlockRules` TEXT NOT NULL, `adBlockSubscriptions` TEXT NOT NULL, `webViewConfig` TEXT NOT NULL, `splashEnabled` INTEGER NOT NULL, `splashConfig` TEXT, `bgmEnabled` INTEGER NOT NULL, `bgmConfig` TEXT, `apkExportConfig` TEXT, `themeType` TEXT NOT NULL, `translateEnabled` INTEGER NOT NULL, `translateConfig` TEXT, `extensionEnabled` INTEGER NOT NULL, `extensionModuleIds` TEXT NOT NULL, `extensionFabIcon` TEXT, `autoStartConfig` TEXT, `browserDisguiseConfig` TEXT, `deviceDisguiseConfig` TEXT, `activationDialogConfig` TEXT, `categoryId` INTEGER, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "iconPath", + "columnName": "iconPath", + "affinity": "TEXT" + }, + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT" + }, + { + "fieldPath": "appType", + "columnName": "appType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "mediaConfig", + "columnName": "mediaConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "galleryConfig", + "columnName": "galleryConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "htmlConfig", + "columnName": "htmlConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "wordpressConfig", + "columnName": "wordpressConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "nodejsConfig", + "columnName": "nodejsConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "phpAppConfig", + "columnName": "phpAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "pythonAppConfig", + "columnName": "pythonAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "goAppConfig", + "columnName": "goAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "multiWebConfig", + "columnName": "multiWebConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "activationEnabled", + "columnName": "activationEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "activationCodeList", + "columnName": "activationCodeList", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "activationRequireEveryTime", + "columnName": "activationRequireEveryTime", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "activationRemoteConfig", + "columnName": "activationRemoteConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "isActivated", + "columnName": "isActivated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adsEnabled", + "columnName": "adsEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adConfig", + "columnName": "adConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "announcementEnabled", + "columnName": "announcementEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "announcement", + "columnName": "announcement", + "affinity": "TEXT" + }, + { + "fieldPath": "adBlockEnabled", + "columnName": "adBlockEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adBlockRules", + "columnName": "adBlockRules", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "adBlockSubscriptions", + "columnName": "adBlockSubscriptions", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "webViewConfig", + "columnName": "webViewConfig", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "splashEnabled", + "columnName": "splashEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "splashConfig", + "columnName": "splashConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "bgmEnabled", + "columnName": "bgmEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bgmConfig", + "columnName": "bgmConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "apkExportConfig", + "columnName": "apkExportConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "themeType", + "columnName": "themeType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "translateEnabled", + "columnName": "translateEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "translateConfig", + "columnName": "translateConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "extensionEnabled", + "columnName": "extensionEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "extensionModuleIds", + "columnName": "extensionModuleIds", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "extensionFabIcon", + "columnName": "extensionFabIcon", + "affinity": "TEXT" + }, + { + "fieldPath": "autoStartConfig", + "columnName": "autoStartConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "browserDisguiseConfig", + "columnName": "browserDisguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "deviceDisguiseConfig", + "columnName": "deviceDisguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "activationDialogConfig", + "columnName": "activationDialogConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "categoryId", + "columnName": "categoryId", + "affinity": "INTEGER" + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "updatedAt", + "columnName": "updatedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_web_apps_updatedAt", + "unique": false, + "columnNames": [ + "updatedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_updatedAt` ON `${TABLE_NAME}` (`updatedAt`)" + }, + { + "name": "index_web_apps_categoryId", + "unique": false, + "columnNames": [ + "categoryId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_categoryId` ON `${TABLE_NAME}` (`categoryId`)" + }, + { + "name": "index_web_apps_isActivated", + "unique": false, + "columnNames": [ + "isActivated" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_isActivated` ON `${TABLE_NAME}` (`isActivated`)" + }, + { + "name": "index_web_apps_appType_url", + "unique": false, + "columnNames": [ + "appType", + "url" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_appType_url` ON `${TABLE_NAME}` (`appType`, `url`)" + }, + { + "name": "index_web_apps_appType_iconPath_url", + "unique": false, + "columnNames": [ + "appType", + "iconPath", + "url" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_appType_iconPath_url` ON `${TABLE_NAME}` (`appType`, `iconPath`, `url`)" + } + ] + }, + { + "tableName": "app_categories", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `icon` TEXT NOT NULL, `color` TEXT NOT NULL, `sortOrder` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sortOrder", + "columnName": "sortOrder", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + } + }, + { + "tableName": "app_usage_stats", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `appId` INTEGER NOT NULL, `launchCount` INTEGER NOT NULL, `totalUsageMs` INTEGER NOT NULL, `lastUsedAt` INTEGER NOT NULL, `lastSessionDurationMs` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, FOREIGN KEY(`appId`) REFERENCES `web_apps`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "appId", + "columnName": "appId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "launchCount", + "columnName": "launchCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "totalUsageMs", + "columnName": "totalUsageMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastUsedAt", + "columnName": "lastUsedAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastSessionDurationMs", + "columnName": "lastSessionDurationMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_app_usage_stats_appId", + "unique": true, + "columnNames": [ + "appId" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_app_usage_stats_appId` ON `${TABLE_NAME}` (`appId`)" + }, + { + "name": "index_app_usage_stats_lastUsedAt", + "unique": false, + "columnNames": [ + "lastUsedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_usage_stats_lastUsedAt` ON `${TABLE_NAME}` (`lastUsedAt`)" + }, + { + "name": "index_app_usage_stats_launchCount", + "unique": false, + "columnNames": [ + "launchCount" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_usage_stats_launchCount` ON `${TABLE_NAME}` (`launchCount`)" + } + ], + "foreignKeys": [ + { + "table": "web_apps", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "appId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "app_health_records", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `appId` INTEGER NOT NULL, `url` TEXT NOT NULL, `status` TEXT NOT NULL, `responseTimeMs` INTEGER NOT NULL, `httpStatusCode` INTEGER NOT NULL, `errorMessage` TEXT, `checkedAt` INTEGER NOT NULL, FOREIGN KEY(`appId`) REFERENCES `web_apps`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "appId", + "columnName": "appId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "responseTimeMs", + "columnName": "responseTimeMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "httpStatusCode", + "columnName": "httpStatusCode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "errorMessage", + "columnName": "errorMessage", + "affinity": "TEXT" + }, + { + "fieldPath": "checkedAt", + "columnName": "checkedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_app_health_records_appId", + "unique": false, + "columnNames": [ + "appId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_health_records_appId` ON `${TABLE_NAME}` (`appId`)" + }, + { + "name": "index_app_health_records_checkedAt", + "unique": false, + "columnNames": [ + "checkedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_health_records_checkedAt` ON `${TABLE_NAME}` (`checkedAt`)" + } + ], + "foreignKeys": [ + { + "table": "web_apps", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "appId" + ], + "referencedColumns": [ + "id" + ] + } + ] + } + ], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'ea6b40911e9117204ec107ff693031d7')" + ] + } +} \ No newline at end of file diff --git a/app/schemas/com.webtoapp.data.database.AppDatabase/44.json b/app/schemas/com.webtoapp.data.database.AppDatabase/44.json new file mode 100644 index 0000000..f01d07b --- /dev/null +++ b/app/schemas/com.webtoapp.data.database.AppDatabase/44.json @@ -0,0 +1,568 @@ +{ + "formatVersion": 1, + "database": { + "version": 44, + "identityHash": "0a034258a95fdd6ab5f7d94147e9de43", + "entities": [ + { + "tableName": "web_apps", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `url` TEXT NOT NULL, `iconPath` TEXT, `packageName` TEXT, `appType` TEXT NOT NULL, `mediaConfig` TEXT, `galleryConfig` TEXT, `htmlConfig` TEXT, `wordpressConfig` TEXT, `nodejsConfig` TEXT, `phpAppConfig` TEXT, `pythonAppConfig` TEXT, `goAppConfig` TEXT, `multiWebConfig` TEXT, `activationEnabled` INTEGER NOT NULL, `activationCodeList` TEXT NOT NULL, `activationRequireEveryTime` INTEGER NOT NULL, `activationRemoteConfig` TEXT, `isActivated` INTEGER NOT NULL, `appLockConfig` TEXT, `adsEnabled` INTEGER NOT NULL, `adConfig` TEXT, `announcementEnabled` INTEGER NOT NULL, `announcement` TEXT, `adBlockEnabled` INTEGER NOT NULL, `adBlockRules` TEXT NOT NULL, `adBlockSubscriptions` TEXT NOT NULL, `webViewConfig` TEXT NOT NULL, `splashEnabled` INTEGER NOT NULL, `splashConfig` TEXT, `bgmEnabled` INTEGER NOT NULL, `bgmConfig` TEXT, `apkExportConfig` TEXT, `themeType` TEXT NOT NULL, `translateEnabled` INTEGER NOT NULL, `translateConfig` TEXT, `extensionEnabled` INTEGER NOT NULL, `extensionModuleIds` TEXT NOT NULL, `extensionFabIcon` TEXT, `autoStartConfig` TEXT, `browserDisguiseConfig` TEXT, `deviceDisguiseConfig` TEXT, `activationDialogConfig` TEXT, `categoryId` INTEGER, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "iconPath", + "columnName": "iconPath", + "affinity": "TEXT" + }, + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT" + }, + { + "fieldPath": "appType", + "columnName": "appType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "mediaConfig", + "columnName": "mediaConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "galleryConfig", + "columnName": "galleryConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "htmlConfig", + "columnName": "htmlConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "wordpressConfig", + "columnName": "wordpressConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "nodejsConfig", + "columnName": "nodejsConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "phpAppConfig", + "columnName": "phpAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "pythonAppConfig", + "columnName": "pythonAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "goAppConfig", + "columnName": "goAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "multiWebConfig", + "columnName": "multiWebConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "activationEnabled", + "columnName": "activationEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "activationCodeList", + "columnName": "activationCodeList", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "activationRequireEveryTime", + "columnName": "activationRequireEveryTime", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "activationRemoteConfig", + "columnName": "activationRemoteConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "isActivated", + "columnName": "isActivated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "appLockConfig", + "columnName": "appLockConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "adsEnabled", + "columnName": "adsEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adConfig", + "columnName": "adConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "announcementEnabled", + "columnName": "announcementEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "announcement", + "columnName": "announcement", + "affinity": "TEXT" + }, + { + "fieldPath": "adBlockEnabled", + "columnName": "adBlockEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adBlockRules", + "columnName": "adBlockRules", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "adBlockSubscriptions", + "columnName": "adBlockSubscriptions", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "webViewConfig", + "columnName": "webViewConfig", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "splashEnabled", + "columnName": "splashEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "splashConfig", + "columnName": "splashConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "bgmEnabled", + "columnName": "bgmEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bgmConfig", + "columnName": "bgmConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "apkExportConfig", + "columnName": "apkExportConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "themeType", + "columnName": "themeType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "translateEnabled", + "columnName": "translateEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "translateConfig", + "columnName": "translateConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "extensionEnabled", + "columnName": "extensionEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "extensionModuleIds", + "columnName": "extensionModuleIds", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "extensionFabIcon", + "columnName": "extensionFabIcon", + "affinity": "TEXT" + }, + { + "fieldPath": "autoStartConfig", + "columnName": "autoStartConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "browserDisguiseConfig", + "columnName": "browserDisguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "deviceDisguiseConfig", + "columnName": "deviceDisguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "activationDialogConfig", + "columnName": "activationDialogConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "categoryId", + "columnName": "categoryId", + "affinity": "INTEGER" + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "updatedAt", + "columnName": "updatedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_web_apps_updatedAt", + "unique": false, + "columnNames": [ + "updatedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_updatedAt` ON `${TABLE_NAME}` (`updatedAt`)" + }, + { + "name": "index_web_apps_categoryId", + "unique": false, + "columnNames": [ + "categoryId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_categoryId` ON `${TABLE_NAME}` (`categoryId`)" + }, + { + "name": "index_web_apps_isActivated", + "unique": false, + "columnNames": [ + "isActivated" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_isActivated` ON `${TABLE_NAME}` (`isActivated`)" + }, + { + "name": "index_web_apps_appType_url", + "unique": false, + "columnNames": [ + "appType", + "url" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_appType_url` ON `${TABLE_NAME}` (`appType`, `url`)" + }, + { + "name": "index_web_apps_appType_iconPath_url", + "unique": false, + "columnNames": [ + "appType", + "iconPath", + "url" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_appType_iconPath_url` ON `${TABLE_NAME}` (`appType`, `iconPath`, `url`)" + } + ] + }, + { + "tableName": "app_categories", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `icon` TEXT NOT NULL, `color` TEXT NOT NULL, `sortOrder` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sortOrder", + "columnName": "sortOrder", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + } + }, + { + "tableName": "app_usage_stats", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `appId` INTEGER NOT NULL, `launchCount` INTEGER NOT NULL, `totalUsageMs` INTEGER NOT NULL, `lastUsedAt` INTEGER NOT NULL, `lastSessionDurationMs` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, FOREIGN KEY(`appId`) REFERENCES `web_apps`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "appId", + "columnName": "appId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "launchCount", + "columnName": "launchCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "totalUsageMs", + "columnName": "totalUsageMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastUsedAt", + "columnName": "lastUsedAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastSessionDurationMs", + "columnName": "lastSessionDurationMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_app_usage_stats_appId", + "unique": true, + "columnNames": [ + "appId" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_app_usage_stats_appId` ON `${TABLE_NAME}` (`appId`)" + }, + { + "name": "index_app_usage_stats_lastUsedAt", + "unique": false, + "columnNames": [ + "lastUsedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_usage_stats_lastUsedAt` ON `${TABLE_NAME}` (`lastUsedAt`)" + }, + { + "name": "index_app_usage_stats_launchCount", + "unique": false, + "columnNames": [ + "launchCount" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_usage_stats_launchCount` ON `${TABLE_NAME}` (`launchCount`)" + } + ], + "foreignKeys": [ + { + "table": "web_apps", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "appId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "app_health_records", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `appId` INTEGER NOT NULL, `url` TEXT NOT NULL, `status` TEXT NOT NULL, `responseTimeMs` INTEGER NOT NULL, `httpStatusCode` INTEGER NOT NULL, `errorMessage` TEXT, `checkedAt` INTEGER NOT NULL, FOREIGN KEY(`appId`) REFERENCES `web_apps`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "appId", + "columnName": "appId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "responseTimeMs", + "columnName": "responseTimeMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "httpStatusCode", + "columnName": "httpStatusCode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "errorMessage", + "columnName": "errorMessage", + "affinity": "TEXT" + }, + { + "fieldPath": "checkedAt", + "columnName": "checkedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_app_health_records_appId", + "unique": false, + "columnNames": [ + "appId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_health_records_appId` ON `${TABLE_NAME}` (`appId`)" + }, + { + "name": "index_app_health_records_checkedAt", + "unique": false, + "columnNames": [ + "checkedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_health_records_checkedAt` ON `${TABLE_NAME}` (`checkedAt`)" + } + ], + "foreignKeys": [ + { + "table": "web_apps", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "appId" + ], + "referencedColumns": [ + "id" + ] + } + ] + } + ], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '0a034258a95fdd6ab5f7d94147e9de43')" + ] + } +} \ No newline at end of file diff --git a/app/schemas/com.webtoapp.data.database.AppDatabase/45.json b/app/schemas/com.webtoapp.data.database.AppDatabase/45.json new file mode 100644 index 0000000..34f8ee0 --- /dev/null +++ b/app/schemas/com.webtoapp.data.database.AppDatabase/45.json @@ -0,0 +1,563 @@ +{ + "formatVersion": 1, + "database": { + "version": 45, + "identityHash": "ea6b40911e9117204ec107ff693031d7", + "entities": [ + { + "tableName": "web_apps", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `url` TEXT NOT NULL, `iconPath` TEXT, `packageName` TEXT, `appType` TEXT NOT NULL, `mediaConfig` TEXT, `galleryConfig` TEXT, `htmlConfig` TEXT, `wordpressConfig` TEXT, `nodejsConfig` TEXT, `phpAppConfig` TEXT, `pythonAppConfig` TEXT, `goAppConfig` TEXT, `multiWebConfig` TEXT, `activationEnabled` INTEGER NOT NULL, `activationCodeList` TEXT NOT NULL, `activationRequireEveryTime` INTEGER NOT NULL, `activationRemoteConfig` TEXT, `isActivated` INTEGER NOT NULL, `adsEnabled` INTEGER NOT NULL, `adConfig` TEXT, `announcementEnabled` INTEGER NOT NULL, `announcement` TEXT, `adBlockEnabled` INTEGER NOT NULL, `adBlockRules` TEXT NOT NULL, `adBlockSubscriptions` TEXT NOT NULL, `webViewConfig` TEXT NOT NULL, `splashEnabled` INTEGER NOT NULL, `splashConfig` TEXT, `bgmEnabled` INTEGER NOT NULL, `bgmConfig` TEXT, `apkExportConfig` TEXT, `themeType` TEXT NOT NULL, `translateEnabled` INTEGER NOT NULL, `translateConfig` TEXT, `extensionEnabled` INTEGER NOT NULL, `extensionModuleIds` TEXT NOT NULL, `extensionFabIcon` TEXT, `autoStartConfig` TEXT, `browserDisguiseConfig` TEXT, `deviceDisguiseConfig` TEXT, `activationDialogConfig` TEXT, `categoryId` INTEGER, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "iconPath", + "columnName": "iconPath", + "affinity": "TEXT" + }, + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT" + }, + { + "fieldPath": "appType", + "columnName": "appType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "mediaConfig", + "columnName": "mediaConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "galleryConfig", + "columnName": "galleryConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "htmlConfig", + "columnName": "htmlConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "wordpressConfig", + "columnName": "wordpressConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "nodejsConfig", + "columnName": "nodejsConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "phpAppConfig", + "columnName": "phpAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "pythonAppConfig", + "columnName": "pythonAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "goAppConfig", + "columnName": "goAppConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "multiWebConfig", + "columnName": "multiWebConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "activationEnabled", + "columnName": "activationEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "activationCodeList", + "columnName": "activationCodeList", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "activationRequireEveryTime", + "columnName": "activationRequireEveryTime", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "activationRemoteConfig", + "columnName": "activationRemoteConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "isActivated", + "columnName": "isActivated", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adsEnabled", + "columnName": "adsEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adConfig", + "columnName": "adConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "announcementEnabled", + "columnName": "announcementEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "announcement", + "columnName": "announcement", + "affinity": "TEXT" + }, + { + "fieldPath": "adBlockEnabled", + "columnName": "adBlockEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "adBlockRules", + "columnName": "adBlockRules", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "adBlockSubscriptions", + "columnName": "adBlockSubscriptions", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "webViewConfig", + "columnName": "webViewConfig", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "splashEnabled", + "columnName": "splashEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "splashConfig", + "columnName": "splashConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "bgmEnabled", + "columnName": "bgmEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bgmConfig", + "columnName": "bgmConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "apkExportConfig", + "columnName": "apkExportConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "themeType", + "columnName": "themeType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "translateEnabled", + "columnName": "translateEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "translateConfig", + "columnName": "translateConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "extensionEnabled", + "columnName": "extensionEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "extensionModuleIds", + "columnName": "extensionModuleIds", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "extensionFabIcon", + "columnName": "extensionFabIcon", + "affinity": "TEXT" + }, + { + "fieldPath": "autoStartConfig", + "columnName": "autoStartConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "browserDisguiseConfig", + "columnName": "browserDisguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "deviceDisguiseConfig", + "columnName": "deviceDisguiseConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "activationDialogConfig", + "columnName": "activationDialogConfig", + "affinity": "TEXT" + }, + { + "fieldPath": "categoryId", + "columnName": "categoryId", + "affinity": "INTEGER" + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "updatedAt", + "columnName": "updatedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_web_apps_updatedAt", + "unique": false, + "columnNames": [ + "updatedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_updatedAt` ON `${TABLE_NAME}` (`updatedAt`)" + }, + { + "name": "index_web_apps_categoryId", + "unique": false, + "columnNames": [ + "categoryId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_categoryId` ON `${TABLE_NAME}` (`categoryId`)" + }, + { + "name": "index_web_apps_isActivated", + "unique": false, + "columnNames": [ + "isActivated" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_isActivated` ON `${TABLE_NAME}` (`isActivated`)" + }, + { + "name": "index_web_apps_appType_url", + "unique": false, + "columnNames": [ + "appType", + "url" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_appType_url` ON `${TABLE_NAME}` (`appType`, `url`)" + }, + { + "name": "index_web_apps_appType_iconPath_url", + "unique": false, + "columnNames": [ + "appType", + "iconPath", + "url" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_web_apps_appType_iconPath_url` ON `${TABLE_NAME}` (`appType`, `iconPath`, `url`)" + } + ] + }, + { + "tableName": "app_categories", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `icon` TEXT NOT NULL, `color` TEXT NOT NULL, `sortOrder` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sortOrder", + "columnName": "sortOrder", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + } + }, + { + "tableName": "app_usage_stats", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `appId` INTEGER NOT NULL, `launchCount` INTEGER NOT NULL, `totalUsageMs` INTEGER NOT NULL, `lastUsedAt` INTEGER NOT NULL, `lastSessionDurationMs` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, FOREIGN KEY(`appId`) REFERENCES `web_apps`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "appId", + "columnName": "appId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "launchCount", + "columnName": "launchCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "totalUsageMs", + "columnName": "totalUsageMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastUsedAt", + "columnName": "lastUsedAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastSessionDurationMs", + "columnName": "lastSessionDurationMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_app_usage_stats_appId", + "unique": true, + "columnNames": [ + "appId" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_app_usage_stats_appId` ON `${TABLE_NAME}` (`appId`)" + }, + { + "name": "index_app_usage_stats_lastUsedAt", + "unique": false, + "columnNames": [ + "lastUsedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_usage_stats_lastUsedAt` ON `${TABLE_NAME}` (`lastUsedAt`)" + }, + { + "name": "index_app_usage_stats_launchCount", + "unique": false, + "columnNames": [ + "launchCount" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_usage_stats_launchCount` ON `${TABLE_NAME}` (`launchCount`)" + } + ], + "foreignKeys": [ + { + "table": "web_apps", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "appId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "app_health_records", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `appId` INTEGER NOT NULL, `url` TEXT NOT NULL, `status` TEXT NOT NULL, `responseTimeMs` INTEGER NOT NULL, `httpStatusCode` INTEGER NOT NULL, `errorMessage` TEXT, `checkedAt` INTEGER NOT NULL, FOREIGN KEY(`appId`) REFERENCES `web_apps`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "appId", + "columnName": "appId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "responseTimeMs", + "columnName": "responseTimeMs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "httpStatusCode", + "columnName": "httpStatusCode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "errorMessage", + "columnName": "errorMessage", + "affinity": "TEXT" + }, + { + "fieldPath": "checkedAt", + "columnName": "checkedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_app_health_records_appId", + "unique": false, + "columnNames": [ + "appId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_health_records_appId` ON `${TABLE_NAME}` (`appId`)" + }, + { + "name": "index_app_health_records_checkedAt", + "unique": false, + "columnNames": [ + "checkedAt" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_app_health_records_checkedAt` ON `${TABLE_NAME}` (`checkedAt`)" + } + ], + "foreignKeys": [ + { + "table": "web_apps", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "appId" + ], + "referencedColumns": [ + "id" + ] + } + ] + } + ], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'ea6b40911e9117204ec107ff693031d7')" + ] + } +} \ No newline at end of file diff --git a/app/src/debug/res/xml/network_security_config.xml b/app/src/debug/res/xml/network_security_config.xml new file mode 100644 index 0000000..6369259 --- /dev/null +++ b/app/src/debug/res/xml/network_security_config.xml @@ -0,0 +1,17 @@ + + + + + + + + + + localhost + 127.0.0.1 + + + + + + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..61d1323 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,522 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/assets/bgm/README.txt b/app/src/main/assets/bgm/README.txt new file mode 100644 index 0000000..8dfb7fd --- /dev/null +++ b/app/src/main/assets/bgm/README.txt @@ -0,0 +1,16 @@ +背景音乐预置目录 +================ + +将 MP3 音乐文件放入此目录即可作为预置背景音乐使用。 + +文件命名规则: +- 音乐文件:小乔.mp3 +- 封面图片:小乔.png(或 .jpg/.jpeg) + +同名的音乐和图片会自动配对,图片将作为音乐的封面图标显示。 +封面图片是可选的,仅用于在选择界面方便识别。 + +示例: +- 小乔.mp3 + 小乔.png +- 背景音乐1.mp3 + 背景音乐1.jpg +- bgm_01.mp3(无封面) diff --git a/app/src/main/assets/php_router_server.php b/app/src/main/assets/php_router_server.php new file mode 100644 index 0000000..13de246 --- /dev/null +++ b/app/src/main/assets/php_router_server.php @@ -0,0 +1,698 @@ + 0) { + http_response_code($response_code); + } elseif ($colonPos !== false) { + $headerName = strtolower(trim(substr($string, 0, $colonPos))); + if ($headerName === 'location') { + $currentCode = http_response_code(); + if ($currentCode < 300 || $currentCode >= 400) { + http_response_code(302); + } + } + } + } + + function headers_list(): array { + return $GLOBALS['__router_custom_headers']; + } + + function headers_sent(&$filename = null, &$line = null): bool { + return false; + } + + function header_remove(?string $name = null): void { + if ($name === null) { + $GLOBALS['__router_custom_headers'] = []; + } else { + $lower = strtolower($name); + $GLOBALS['__router_custom_headers'] = array_values(array_filter( + $GLOBALS['__router_custom_headers'], + function($h) use ($lower) { + $p = strpos($h, ':'); + return $p === false || strtolower(trim(substr($h, 0, $p))) !== $lower; + } + )); + } + } + + function setcookie( + string $name, string $value = '', int|array $expires_or_options = 0, + string $path = '', string $domain = '', bool $secure = false, bool $httponly = false + ): bool { + if (is_array($expires_or_options)) { + $o = $expires_or_options; + $cookie = rawurlencode($name) . '=' . rawurlencode($value); + if (!empty($o['expires']) && $o['expires'] > 0) { + $cookie .= '; Expires=' . gmdate('D, d M Y H:i:s T', (int)$o['expires']); + $cookie .= '; Max-Age=' . max(0, (int)$o['expires'] - time()); + } + if (!empty($o['path'])) $cookie .= '; Path=' . $o['path']; + if (!empty($o['domain'])) $cookie .= '; Domain=' . $o['domain']; + if (!empty($o['secure'])) $cookie .= '; Secure'; + if (!empty($o['httponly'])) $cookie .= '; HttpOnly'; + if (!empty($o['samesite'])) $cookie .= '; SameSite=' . $o['samesite']; + } else { + $cookie = rawurlencode($name) . '=' . rawurlencode($value); + if ($expires_or_options > 0) { + $cookie .= '; Expires=' . gmdate('D, d M Y H:i:s T', $expires_or_options); + $cookie .= '; Max-Age=' . max(0, $expires_or_options - time()); + } + if ($path !== '') $cookie .= '; Path=' . $path; + if ($domain !== '') $cookie .= '; Domain=' . $domain; + if ($secure) $cookie .= '; Secure'; + if ($httponly) $cookie .= '; HttpOnly'; + } + header('Set-Cookie: ' . $cookie, false); + return true; + } + + function setrawcookie( + string $name, string $value = '', int|array $expires_or_options = 0, + string $path = '', string $domain = '', bool $secure = false, bool $httponly = false + ): bool { + if (is_array($expires_or_options)) { + $o = $expires_or_options; + $cookie = $name . '=' . $value; + if (!empty($o['expires']) && $o['expires'] > 0) { + $cookie .= '; Expires=' . gmdate('D, d M Y H:i:s T', (int)$o['expires']); + $cookie .= '; Max-Age=' . max(0, (int)$o['expires'] - time()); + } + if (!empty($o['path'])) $cookie .= '; Path=' . $o['path']; + if (!empty($o['domain'])) $cookie .= '; Domain=' . $o['domain']; + if (!empty($o['secure'])) $cookie .= '; Secure'; + if (!empty($o['httponly'])) $cookie .= '; HttpOnly'; + if (!empty($o['samesite'])) $cookie .= '; SameSite=' . $o['samesite']; + } else { + $cookie = $name . '=' . $value; + if ($expires_or_options > 0) { + $cookie .= '; Expires=' . gmdate('D, d M Y H:i:s T', $expires_or_options); + $cookie .= '; Max-Age=' . max(0, $expires_or_options - time()); + } + if ($path !== '') $cookie .= '; Path=' . $path; + if ($domain !== '') $cookie .= '; Domain=' . $domain; + if ($secure) $cookie .= '; Secure'; + if ($httponly) $cookie .= '; HttpOnly'; + } + header('Set-Cookie: ' . $cookie, false); + return true; + } +} + +// ==================== Session Polyfill ==================== +// pmmp PHP 没有 session 扩展,提供基于文件的 session 实现 +// 对所有 PHP 项目自动生效(包括已有项目) + +$GLOBALS['__session_doc_root'] = $docRoot; + +if (!function_exists('session_start')) { + $GLOBALS['__session_file'] = null; + $GLOBALS['__session_id'] = ''; + $GLOBALS['__session_started'] = false; + $GLOBALS['__session_name'] = 'PHPSESSID'; + + function session_start(array $options = []): bool { + if ($GLOBALS['__session_started']) return true; + + $docRoot = $GLOBALS['__session_doc_root'] ?? '.'; + $sessionDir = $docRoot . '/.sessions'; + if (!is_dir($sessionDir)) @mkdir($sessionDir, 0777, true); + + // 从 cookie 获取 session ID,或生成新的 + $name = $GLOBALS['__session_name']; + $sid = $_COOKIE[$name] ?? ''; + if (empty($sid) || !preg_match('/^[a-zA-Z0-9,-]{22,256}$/', $sid)) { + $sid = bin2hex(random_bytes(16)); + header("Set-Cookie: $name=$sid; Path=/; HttpOnly; SameSite=Lax"); + } + + $GLOBALS['__session_id'] = $sid; + $GLOBALS['__session_file'] = $sessionDir . '/sess_' . $sid; + + $_SESSION = []; + if (file_exists($GLOBALS['__session_file'])) { + $data = @file_get_contents($GLOBALS['__session_file']); + if ($data !== false) { + $decoded = @json_decode($data, true); + if (is_array($decoded)) $_SESSION = $decoded; + } + } + + $GLOBALS['__session_started'] = true; + return true; + } + + function session_write_close(): bool { + if (!$GLOBALS['__session_started']) return true; + if ($GLOBALS['__session_file']) { + @file_put_contents( + $GLOBALS['__session_file'], + json_encode($_SESSION ?? [], JSON_UNESCAPED_UNICODE) + ); + } + $GLOBALS['__session_started'] = false; + return true; + } + + function session_commit(): bool { + return session_write_close(); + } + + function session_destroy(): bool { + $_SESSION = []; + if ($GLOBALS['__session_file'] && file_exists($GLOBALS['__session_file'])) { + @unlink($GLOBALS['__session_file']); + } + $GLOBALS['__session_started'] = false; + return true; + } + + function session_id(string $id = ''): string|false { + if ($id !== '') $GLOBALS['__session_id'] = $id; + return $GLOBALS['__session_id']; + } + + function session_name(string $name = ''): string|false { + $old = $GLOBALS['__session_name']; + if ($name !== '') $GLOBALS['__session_name'] = $name; + return $old; + } + + function session_status(): int { + // PHP_SESSION_ACTIVE = 2, PHP_SESSION_NONE = 1 + return $GLOBALS['__session_started'] ? 2 : 1; + } + + function session_regenerate_id(bool $delete_old = false): bool { + if (!$GLOBALS['__session_started']) return false; + $oldFile = $GLOBALS['__session_file']; + $sid = bin2hex(random_bytes(16)); + $GLOBALS['__session_id'] = $sid; + $name = $GLOBALS['__session_name']; + header("Set-Cookie: $name=$sid; Path=/; HttpOnly; SameSite=Lax"); + $docRoot = $GLOBALS['__session_doc_root'] ?? '.'; + $GLOBALS['__session_file'] = $docRoot . '/.sessions/sess_' . $sid; + if ($delete_old && $oldFile && file_exists($oldFile)) @unlink($oldFile); + return true; + } + + function session_unset(): bool { + $_SESSION = []; + return true; + } +} + +// ==================== 主循环 ==================== +while ($running) { + if (function_exists('pcntl_signal_dispatch')) { + pcntl_signal_dispatch(); + } + + $read = [$server]; $write = $except = null; + $changed = @stream_select($read, $write, $except, 1); + if ($changed === false || $changed === 0) continue; + + $client = @stream_socket_accept($server, 0); + if (!$client) continue; + + $request = readHttpRequest($client); + if (!$request) { + fwrite(STDERR, "[RouterServer] Empty request, closing\n"); + fclose($client); + continue; + } + + fwrite(STDERR, "[RouterServer] {$request['method']} {$request['path']}\n"); + + // 内置健康检查端点 — 不执行任何 PHP 文件 + if ($request['path'] === '/__health') { + sendRawResponse($client, 200, 'OK', ['Content-Type: text/plain'], 'OK'); + fclose($client); + continue; + } + + $filePath = resolveFilePath($request['path'], $docRoot, $entryFile); + $ext = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); + + // 静态文件 — 主进程直接响应 + if ($ext !== 'php' && file_exists($filePath) && !is_dir($filePath)) { + serveStaticFile($client, $filePath); + fclose($client); + continue; + } + + if (!file_exists($filePath)) { + sendRawResponse($client, 404, 'Not Found', [], 'Not Found'); + fclose($client); + continue; + } + + // PHP 文件 — fork 子进程隔离执行 + if ($hasPcntl) { + $pid = pcntl_fork(); + if ($pid === -1) { + executePHP($client, $filePath, $request, $docRoot, $port); + fclose($client); + } elseif ($pid === 0) { + fclose($server); + executePHP($client, $filePath, $request, $docRoot, $port); + fclose($client); + exit(0); + } else { + fclose($client); + } + } else { + executePHP($client, $filePath, $request, $docRoot, $port); + fclose($client); + } +} + +fclose($server); +fwrite(STDERR, "[RouterServer] Stopped\n"); +exit(0); + +// ==================== HTTP 请求解析 ==================== + +function readHttpRequest($client): ?array { + stream_set_timeout($client, 10); + + $requestLine = fgets($client, 8192); + if (!$requestLine) return null; + if (!preg_match('/^(\w+)\s+(\S+)\s+HTTP\/([\d.]+)/', trim($requestLine), $m)) { + return null; + } + + $method = strtoupper($m[1]); + $uri = $m[2]; + + $headers = []; + while (($line = fgets($client, 8192)) !== false) { + $line = rtrim($line, "\r\n"); + if ($line === '') break; + if (($pos = strpos($line, ':')) !== false) { + $headers[strtolower(trim(substr($line, 0, $pos)))] = trim(substr($line, $pos + 1)); + } + } + + $body = ''; + $contentLength = (int)($headers['content-length'] ?? 0); + if ($contentLength > 0) { + $remaining = $contentLength; + while ($remaining > 0) { + $chunk = fread($client, min($remaining, 65536)); + if ($chunk === false || $chunk === '') break; + $body .= $chunk; + $remaining -= strlen($chunk); + } + } + + $parts = parse_url($uri); + $path = urldecode($parts['path'] ?? '/'); + $queryString = $parts['query'] ?? ''; + + return compact('method', 'uri', 'path', 'queryString', 'headers', 'body'); +} + +// ==================== 路径解析 ==================== + +function resolveFilePath(string $path, string $docRoot, string $entryFile): string { + $path = '/' . ltrim(str_replace('\\', '/', $path), '/'); + if (strpos($path, '..') !== false) return ''; + + $filePath = $docRoot . $path; + $requestedExt = strtolower(pathinfo($path, PATHINFO_EXTENSION)); + + if (is_dir($filePath)) { + foreach (['index.php', 'index.html', 'index.htm'] as $idx) { + $c = $filePath . '/' . $idx; + if (file_exists($c)) return $c; + } + } + + if (file_exists($filePath) && !is_dir($filePath)) return $filePath; + + if ($requestedExt !== '' && in_array($requestedExt, [ + 'css','js','mjs','json','xml','txt','csv','png','jpg','jpeg','gif','svg','ico', + 'webp','avif','woff','woff2','ttf','otf','pdf','zip','mp4','webm','mp3','ogg','wav', + 'map','wasm' + ], true)) { + return $filePath; + } + + return $docRoot . '/' . $entryFile; +} + +// ==================== PHP 执行 ==================== + +function executePHP($client, string $filePath, array $request, string $docRoot, int $port): void { + $method = $request['method']; + $uri = $request['uri']; + $queryString = $request['queryString']; + $headers = $request['headers']; + $body = $request['body']; + $path = $request['path']; + + // 标记响应是否已发送,防止 shutdown function 重复发送 + $GLOBALS['__router_response_sent'] = false; + + // 将 body 写入临时文件并重定向 stdin (fd 0) + // 这样 php://input 可以正确读取请求体 + $tmpInput = null; + if (strlen($body) > 0) { + $tmpInput = tempnam(sys_get_temp_dir(), 'phpinput_'); + file_put_contents($tmpInput, $body); + fclose(STDIN); + $GLOBALS['STDIN'] = fopen($tmpInput, 'r'); // 获得 fd 0 + } + + // 构建 $_SERVER + $_SERVER = [ + 'REQUEST_METHOD' => $method, + 'REQUEST_URI' => $uri, + 'QUERY_STRING' => $queryString, + 'SCRIPT_FILENAME' => $filePath, + 'SCRIPT_NAME' => $path, + 'PHP_SELF' => $path, + 'DOCUMENT_ROOT' => $docRoot, + 'SERVER_NAME' => '*********', + 'SERVER_PORT' => (string)$port, + 'SERVER_PROTOCOL' => 'HTTP/1.1', + 'SERVER_SOFTWARE' => 'PHPRouterServer/1.0', + 'GATEWAY_INTERFACE' => 'CGI/1.1', + 'REDIRECT_STATUS' => '200', + 'REMOTE_ADDR' => '*********', + 'REMOTE_PORT' => '0', + 'HTTP_HOST' => $headers['host'] ?? "*********:$port", + 'CONTENT_TYPE' => $headers['content-type'] ?? '', + 'CONTENT_LENGTH' => (string)strlen($body), + 'REQUEST_TIME' => time(), + 'REQUEST_TIME_FLOAT'=> microtime(true), + ]; + foreach ($headers as $k => $v) { + $_SERVER['HTTP_' . strtoupper(str_replace('-', '_', $k))] = $v; + } + + // $_GET + $_GET = []; + parse_str($queryString, $_GET); + + // $_POST & $_FILES + $_POST = []; + $_FILES = []; + $ct = $headers['content-type'] ?? ''; + if (in_array($method, ['POST', 'PUT', 'PATCH']) && $body !== '') { + if (stripos($ct, 'application/x-www-form-urlencoded') !== false) { + parse_str($body, $_POST); + } elseif (stripos($ct, 'multipart/form-data') !== false) { + parseMultipart($ct, $body, $_POST, $_FILES); + } elseif (stripos($ct, 'application/json') !== false) { + // JSON body → $_POST fallback(当 php://input 在 CLI SAPI 下不可用时) + $decoded = json_decode($body, true); + if (is_array($decoded)) $_POST = $decoded; + } + } + + // $_COOKIE + $_COOKIE = []; + if (isset($headers['cookie'])) { + foreach (explode(';', $headers['cookie']) as $c) { + $c = trim($c); + if (($eq = strpos($c, '=')) !== false) { + $_COOKIE[trim(substr($c, 0, $eq))] = urldecode(trim(substr($c, $eq + 1))); + } + } + } + + $_REQUEST = array_merge($_GET, $_POST, $_COOKIE); + + // 注册 shutdown function — 安全网:当脚本调用 exit() 或发生致命错误时发送响应 + $responseClient = $client; + register_shutdown_function(function () use ($responseClient, $tmpInput, $uri) { + // 如果响应已发送(正常路径),仅清理 + if (!empty($GLOBALS['__router_response_sent'])) { + if ($tmpInput && file_exists($tmpInput)) @unlink($tmpInput); + return; + } + $GLOBALS['__router_response_sent'] = true; + + $output = ''; + while (ob_get_level() > 0) { + $output = ob_get_clean() . $output; + } + $code = http_response_code() ?: 200; + $headerList = headers_list(); + $lastError = error_get_last(); + if ($lastError && in_array($lastError['type'] ?? 0, [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR], true)) { + $code = 500; + $message = ($lastError['message'] ?? 'Unknown fatal error') + . ' in ' . ($lastError['file'] ?? 'unknown') + . ':' . ($lastError['line'] ?? 0); + fwrite(STDERR, "[RouterServer] Fatal error: $message\n"); + if ($output === '') { + $output = '

500 Internal Server Error

' . htmlspecialchars($message) . '
'; + } + } + // Surface the router's own diagnostic (fatal message / trace) to the WebView + // layer: local error pages read this header to show the cause instead of a + // bare "HTTP 500" that hides whether the failure is a fatal, a thrown + // exception, or PHP output. Keep it bounded — response bodies can be large. + if ($code >= 500 && $output !== '' && strlen($output) <= 65536) { + $headerList[] = 'X-Wta-Router-Error: ' . base64_encode($output); + } + if (function_exists('header_remove')) header_remove(); + + fwrite(STDERR, "[RouterServer] Shutdown response uri=$uri code=$code bytes=" . strlen($output) . " " . describeHeaders($headerList) . "\n"); + sendRawResponse($responseClient, $code, httpStatusText($code), $headerList, $output); + @fclose($responseClient); + + if ($tmpInput && file_exists($tmpInput)) @unlink($tmpInput); + }); + + ob_start(); + http_response_code(200); + if (function_exists('header_remove')) header_remove(); + + // 设置全局变量,让 PHP 脚本可以通过 $GLOBALS['__HTTP_RAW_BODY'] 获取原始请求体 + // 这是 php://input 在 CLI SAPI + fork 模式下的可靠替代方案 + $GLOBALS['__HTTP_RAW_BODY'] = $body; + + chdir($docRoot); + + try { + include $filePath; + } catch (\Throwable $e) { + while (ob_get_level() > 1) ob_end_clean(); + http_response_code(500); + fwrite(STDERR, "[RouterServer] PHP error: " . $e->getMessage() . "\n"); + echo "

500 Internal Server Error

"
+            . htmlspecialchars($e->getMessage()) . "\n"
+            . htmlspecialchars($e->getTraceAsString()) . "
"; + } + + // Thrown-exception path: response goes through the normal-path sender below, + // which also stamps X-Wta-Router-Error on 5xx (see the shutdown handler). + + // 自动保存 session 数据(模拟 PHP 原生 session 行为) + if (function_exists('session_write_close') && ($GLOBALS['__session_started'] ?? false)) { + session_write_close(); + } + + // 正常路径:显式发送响应(在 fclose 之前!) + if (!$GLOBALS['__router_response_sent']) { + $GLOBALS['__router_response_sent'] = true; + $output = ''; + while (ob_get_level() > 0) { + $output = ob_get_clean() . $output; + } + $code = http_response_code() ?: 200; + $headerList = headers_list(); + // Same 5xx diagnostic stamping as the shutdown handler (see there). + if ($code >= 500 && $output !== '' && strlen($output) <= 65536) { + $headerList[] = 'X-Wta-Router-Error: ' . base64_encode($output); + } + if (function_exists('header_remove')) header_remove(); + + fwrite(STDERR, "[RouterServer] Response uri=$uri code=$code bytes=" . strlen($output) . " " . describeHeaders($headerList) . "\n"); + sendRawResponse($client, $code, httpStatusText($code), $headerList, $output); + } +} + +// ==================== Multipart 解析 ==================== + +function parseMultipart(string $contentType, string $body, array &$post, array &$files): void { + if (!preg_match('/boundary=(.+?)(?:;|$)/i', $contentType, $m)) return; + $boundary = trim($m[1], '"'); + $parts = explode("--$boundary", $body); + array_shift($parts); + + foreach ($parts as $part) { + $part = ltrim($part, "\r\n"); + if (str_starts_with(trim($part), '--') || empty(trim($part))) continue; + + $headerEnd = strpos($part, "\r\n\r\n"); + if ($headerEnd === false) continue; + + $ph = substr($part, 0, $headerEnd); + $pb = rtrim(substr($part, $headerEnd + 4), "\r\n"); + + if (!preg_match('/name="([^"]+)"/', $ph, $nm)) continue; + $name = $nm[1]; + + if (preg_match('/filename="([^"]*)"/', $ph, $fn) && $fn[1] !== '') { + $tmp = tempnam(sys_get_temp_dir(), 'php_upload_'); + file_put_contents($tmp, $pb); + $pct = 'application/octet-stream'; + if (preg_match('/Content-Type:\s*(.+)/i', $ph, $ctm)) $pct = trim($ctm[1]); + $files[$name] = ['name'=>$fn[1],'type'=>$pct,'tmp_name'=>$tmp,'error'=>UPLOAD_ERR_OK,'size'=>strlen($pb)]; + } else { + $post[$name] = $pb; + } + } +} + +// ==================== 响应发送 ==================== + +function sendRawResponse($client, int $code, string $status, array $headers, string $body): void { + $resp = "HTTP/1.1 $code $status\r\n"; + $hasCT = false; $hasCL = false; + foreach ($headers as $h) { + $resp .= "$h\r\n"; + if (stripos($h, 'content-type:') === 0) $hasCT = true; + if (stripos($h, 'content-length:') === 0) $hasCL = true; + } + if (!$hasCT) $resp .= "Content-Type: text/html; charset=UTF-8\r\n"; + if (!$hasCL) $resp .= "Content-Length: " . strlen($body) . "\r\n"; + $resp .= "Connection: close\r\n\r\n" . $body; + @fwrite($client, $resp); +} + +function describeHeaders(array $headers): string { + $parts = []; + foreach ($headers as $h) { + if (stripos($h, 'location:') === 0 || stripos($h, 'content-type:') === 0) { + $parts[] = $h; + } elseif (stripos($h, 'set-cookie:') === 0) { + $parts[] = 'Set-Cookie: '; + } + } + return empty($parts) ? 'headers=[]' : 'headers=[' . implode('; ', $parts) . ']'; +} + +// ==================== 静态文件服务 ==================== + +function serveStaticFile($client, string $filePath): void { + $mime = getMimeType($filePath); + $size = filesize($filePath); + $resp = "HTTP/1.1 200 OK\r\nContent-Type: $mime\r\nContent-Length: $size\r\n" + . "Connection: close\r\nCache-Control: public, max-age=3600\r\n\r\n"; + fwrite($client, $resp); + $fp = fopen($filePath, 'rb'); + if ($fp) { + while (!feof($fp)) { @fwrite($client, fread($fp, 65536)); } + fclose($fp); + } +} + +function getMimeType(string $f): string { + static $t = [ + 'html'=>'text/html','htm'=>'text/html','css'=>'text/css', + 'js'=>'application/javascript','mjs'=>'application/javascript', + 'json'=>'application/json','xml'=>'application/xml', + 'txt'=>'text/plain','csv'=>'text/csv', + 'png'=>'image/png','jpg'=>'image/jpeg','jpeg'=>'image/jpeg', + 'gif'=>'image/gif','svg'=>'image/svg+xml','ico'=>'image/x-icon', + 'webp'=>'image/webp','avif'=>'image/avif', + 'woff'=>'font/woff','woff2'=>'font/woff2','ttf'=>'font/ttf','otf'=>'font/otf', + 'pdf'=>'application/pdf','zip'=>'application/zip', + 'mp4'=>'video/mp4','webm'=>'video/webm', + 'mp3'=>'audio/mpeg','ogg'=>'audio/ogg','wav'=>'audio/wav', + 'map'=>'application/json','wasm'=>'application/wasm', + ]; + return $t[strtolower(pathinfo($f, PATHINFO_EXTENSION))] ?? 'application/octet-stream'; +} + +function httpStatusText(int $c): string { + static $t = [ + 200=>'OK',201=>'Created',204=>'No Content', + 301=>'Moved Permanently',302=>'Found',304=>'Not Modified', + 307=>'Temporary Redirect',308=>'Permanent Redirect', + 400=>'Bad Request',401=>'Unauthorized',403=>'Forbidden', + 404=>'Not Found',405=>'Method Not Allowed',422=>'Unprocessable Entity', + 500=>'Internal Server Error',502=>'Bad Gateway',503=>'Service Unavailable', + ]; + return $t[$c] ?? 'Unknown'; +} diff --git a/app/src/main/assets/sample_projects/docs-hexo-ar/archives/index.html b/app/src/main/assets/sample_projects/docs-hexo-ar/archives/index.html new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-hexo-ar/archives/index.html @@ -0,0 +1 @@ +{} diff --git a/app/src/main/assets/sample_projects/docs-hexo-ar/index.html b/app/src/main/assets/sample_projects/docs-hexo-ar/index.html new file mode 100644 index 0000000..c0d1b25 --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-hexo-ar/index.html @@ -0,0 +1,328 @@ + + + + + + + وثائق Hexo + + + + +
+
+
📖
+

وثائق Hexo

+

إطار عمل مدونات سريع وبسيط مبني على Node.js

+
v7.0Node.jsMarkdown
+
+
+
+
🚀
+
البداية السريعة
+
أنشئ مدونتك في دقائق
+
+
+
🔧
+
الإعدادات
+
خصص كل التفاصيل
+
+
+
🎨
+
السمات
+
مئات السمات الجميلة
+
+
+
🔌
+
الإضافات
+
نظام إضافات غني
+
+
+
+
⚡ البداية السريعة
+
+
1
+
+
تثبيت Hexo
+
npm install -g hexo-cli
+
+
+
+
2
+
+
إنشاء المشروع
+
hexo init my-blog && cd my-blog
+
+
+
+
3
+
+
تشغيل الخادم
+
hexo server
+
+
+
+
+
📖 وثائق Hexo · مقدم من WebToApp
+
+
+ + + \ No newline at end of file diff --git a/app/src/main/assets/sample_projects/docs-hexo-ar/style.css b/app/src/main/assets/sample_projects/docs-hexo-ar/style.css new file mode 100644 index 0000000..04e12a5 --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-hexo-ar/style.css @@ -0,0 +1,14 @@ +*{margin:0;padding:0;box-sizing:border-box} +body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;display:flex;min-height:100vh;background:#fafafa} +.sidebar{width:240px;background:#fff;border-right:1px solid #eee;padding:20px} +.logo{font-size:20px;font-weight:700;margin-bottom:24px;padding:8px 0} +.sidebar a{display:block;padding:10px 16px;border-radius:8px;color:#333;text-decoration:none;margin-bottom:4px;font-size:14px} +.sidebar a.active{background:#e8f5e9;color:#2e7d32;font-weight:600} +.sidebar a:hover{background:#f5f5f5} +.content{flex:1;padding:40px 60px;max-width:800px} +h1{font-size:32px;color:#1a1a1a;margin-bottom:16px} +p{color:#666;line-height:1.8;margin-bottom:24px} +.features{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:32px} +.feature{background:#fff;border:1px solid #eee;border-radius:12px;padding:20px} +.feature h3{font-size:16px;margin-bottom:8px} +.feature p{font-size:14px;color:#888;margin:0} diff --git a/app/src/main/assets/sample_projects/docs-hexo-en/archives/index.html b/app/src/main/assets/sample_projects/docs-hexo-en/archives/index.html new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-hexo-en/archives/index.html @@ -0,0 +1 @@ +{} diff --git a/app/src/main/assets/sample_projects/docs-hexo-en/index.html b/app/src/main/assets/sample_projects/docs-hexo-en/index.html new file mode 100644 index 0000000..a6d2d7c --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-hexo-en/index.html @@ -0,0 +1,385 @@ + + + + + + + Hexo Docs + + + + +
+
+
📖
+

Hexo Docs

+

A fast, simple & powerful blog framework built on Node.js

+
v7.0Node.jsMarkdownOpen Source
+
+
+
+
🚀
+
Quick Start
+
Create your first blog in minutes
+
+
+
🔧
+
Configuration
+
Customize every detail
+
+
+
🎨
+
Themes
+
Hundreds of beautiful themes
+
+
+
🔌
+
Plugins
+
Rich plugin ecosystem
+
+
+
+
⚡ Getting Started
+
+
1
+
+
Install Hexo
+
npm install -g hexo-cli
+
+
+
+
2
+
+
Initialize
+
hexo init my-blog && cd my-blog
+
+
+
+
3
+
+
Start Server
+
hexo server
+
+
+
+ +
+
📖 Hexo Docs · Powered by WebToApp
+
+
+ + + \ No newline at end of file diff --git a/app/src/main/assets/sample_projects/docs-hexo-en/style.css b/app/src/main/assets/sample_projects/docs-hexo-en/style.css new file mode 100644 index 0000000..04e12a5 --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-hexo-en/style.css @@ -0,0 +1,14 @@ +*{margin:0;padding:0;box-sizing:border-box} +body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;display:flex;min-height:100vh;background:#fafafa} +.sidebar{width:240px;background:#fff;border-right:1px solid #eee;padding:20px} +.logo{font-size:20px;font-weight:700;margin-bottom:24px;padding:8px 0} +.sidebar a{display:block;padding:10px 16px;border-radius:8px;color:#333;text-decoration:none;margin-bottom:4px;font-size:14px} +.sidebar a.active{background:#e8f5e9;color:#2e7d32;font-weight:600} +.sidebar a:hover{background:#f5f5f5} +.content{flex:1;padding:40px 60px;max-width:800px} +h1{font-size:32px;color:#1a1a1a;margin-bottom:16px} +p{color:#666;line-height:1.8;margin-bottom:24px} +.features{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:32px} +.feature{background:#fff;border:1px solid #eee;border-radius:12px;padding:20px} +.feature h3{font-size:16px;margin-bottom:8px} +.feature p{font-size:14px;color:#888;margin:0} diff --git a/app/src/main/assets/sample_projects/docs-hexo/archives/index.html b/app/src/main/assets/sample_projects/docs-hexo/archives/index.html new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-hexo/archives/index.html @@ -0,0 +1 @@ +{} diff --git a/app/src/main/assets/sample_projects/docs-hexo/index.html b/app/src/main/assets/sample_projects/docs-hexo/index.html new file mode 100644 index 0000000..60e0b16 --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-hexo/index.html @@ -0,0 +1,87 @@ + + + + + +Hexo 文档 + + + +
+
+
📖
+

Hexo 文档

+

快速、简洁且高效的博客框架,基于 Node.js 构建

+
+ v7.0 + Node.js + Markdown + 开源 +
+
+
+
🚀
快速入门
几分钟内创建你的第一个博客
+
🔧
配置
自定义网站的每个细节
+
🎨
主题
数百个精美主题可选
+
🔌
插件
丰富的插件生态系统
+
+
+
⚡ 快速开始
+
1
安装 Hexo
npm install -g hexo-cli
+
2
初始化项目
hexo init my-blog && cd my-blog
+
3
启动服务
hexo server
+
+ +
📖 Hexo 文档 · 由 WebToApp 提供
+
+ + diff --git a/app/src/main/assets/sample_projects/docs-hexo/style.css b/app/src/main/assets/sample_projects/docs-hexo/style.css new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-hexo/style.css @@ -0,0 +1 @@ + diff --git a/app/src/main/assets/sample_projects/docs-mkdocs-ar/index.html b/app/src/main/assets/sample_projects/docs-mkdocs-ar/index.html new file mode 100644 index 0000000..4d68ad8 --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-mkdocs-ar/index.html @@ -0,0 +1,309 @@ + + + + + + + وثائق MkDocs + + + + +
+
+
📗
+

وثائق MkDocs

+

أنشئ وثائق المشروع بـ Markdown مع سمة Material

+
MaterialPythonMarkdown
+
+
+
+
🚀
+
بداية سريعة
+
إعداد الوثائق في 5 دقائق
+
+
+
🎨
+
سمة Material
+
تصميم عصري ووضع داكن
+
+
+
🔍
+
البحث
+
محرك بحث نصي مدمج
+
+
+
📱
+
متجاوب
+
دعم مثالي للهاتف
+
+
+
+
⚡ البداية السريعة
+
+
1
+
+
تثبيت MkDocs
+
pip install mkdocs-material
+
+
+
+
2
+
+
إنشاء مشروع
+
mkdocs new my-docs && cd my-docs
+
+
+
+
3
+
+
معاينة
+
mkdocs serve
+
+
+
+
+
📗 MkDocs Material · مقدم من WebToApp
+
+
+ + + \ No newline at end of file diff --git a/app/src/main/assets/sample_projects/docs-mkdocs-ar/mkdocs.yml b/app/src/main/assets/sample_projects/docs-mkdocs-ar/mkdocs.yml new file mode 100644 index 0000000..ea7a7b7 --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-mkdocs-ar/mkdocs.yml @@ -0,0 +1,2 @@ +site_name: MkDocs Demo +theme: material diff --git a/app/src/main/assets/sample_projects/docs-mkdocs-ar/style.css b/app/src/main/assets/sample_projects/docs-mkdocs-ar/style.css new file mode 100644 index 0000000..04e12a5 --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-mkdocs-ar/style.css @@ -0,0 +1,14 @@ +*{margin:0;padding:0;box-sizing:border-box} +body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;display:flex;min-height:100vh;background:#fafafa} +.sidebar{width:240px;background:#fff;border-right:1px solid #eee;padding:20px} +.logo{font-size:20px;font-weight:700;margin-bottom:24px;padding:8px 0} +.sidebar a{display:block;padding:10px 16px;border-radius:8px;color:#333;text-decoration:none;margin-bottom:4px;font-size:14px} +.sidebar a.active{background:#e8f5e9;color:#2e7d32;font-weight:600} +.sidebar a:hover{background:#f5f5f5} +.content{flex:1;padding:40px 60px;max-width:800px} +h1{font-size:32px;color:#1a1a1a;margin-bottom:16px} +p{color:#666;line-height:1.8;margin-bottom:24px} +.features{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:32px} +.feature{background:#fff;border:1px solid #eee;border-radius:12px;padding:20px} +.feature h3{font-size:16px;margin-bottom:8px} +.feature p{font-size:14px;color:#888;margin:0} diff --git a/app/src/main/assets/sample_projects/docs-mkdocs-en/index.html b/app/src/main/assets/sample_projects/docs-mkdocs-en/index.html new file mode 100644 index 0000000..3585c2a --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-mkdocs-en/index.html @@ -0,0 +1,325 @@ + + + + + + + MkDocs Docs + + + + +
+
+
📗
+

MkDocs

+

Build project documentation with Markdown, powered by Material theme

+
MaterialPythonMarkdown
+
+
+
+
🚀
+
Quick Start
+
Set up docs in 5 minutes
+
+
+
🎨
+
Material Theme
+
Modern design, dark mode
+
+
+
🔍
+
Search
+
Built-in full-text search
+
+
+
📱
+
Responsive
+
Perfect mobile support
+
+
+
+
⚡ Getting Started
+
+
1
+
+
Install MkDocs
+
pip install mkdocs-material
+
+
+
+
2
+
+
Create Project
+
mkdocs new my-docs && cd my-docs
+
+
+
+
3
+
+
Start Preview
+
mkdocs serve
+
+
+
+
+
📗 MkDocs Material · Powered by WebToApp
+
+
+ + + \ No newline at end of file diff --git a/app/src/main/assets/sample_projects/docs-mkdocs-en/mkdocs.yml b/app/src/main/assets/sample_projects/docs-mkdocs-en/mkdocs.yml new file mode 100644 index 0000000..ea7a7b7 --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-mkdocs-en/mkdocs.yml @@ -0,0 +1,2 @@ +site_name: MkDocs Demo +theme: material diff --git a/app/src/main/assets/sample_projects/docs-mkdocs-en/style.css b/app/src/main/assets/sample_projects/docs-mkdocs-en/style.css new file mode 100644 index 0000000..04e12a5 --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-mkdocs-en/style.css @@ -0,0 +1,14 @@ +*{margin:0;padding:0;box-sizing:border-box} +body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;display:flex;min-height:100vh;background:#fafafa} +.sidebar{width:240px;background:#fff;border-right:1px solid #eee;padding:20px} +.logo{font-size:20px;font-weight:700;margin-bottom:24px;padding:8px 0} +.sidebar a{display:block;padding:10px 16px;border-radius:8px;color:#333;text-decoration:none;margin-bottom:4px;font-size:14px} +.sidebar a.active{background:#e8f5e9;color:#2e7d32;font-weight:600} +.sidebar a:hover{background:#f5f5f5} +.content{flex:1;padding:40px 60px;max-width:800px} +h1{font-size:32px;color:#1a1a1a;margin-bottom:16px} +p{color:#666;line-height:1.8;margin-bottom:24px} +.features{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:32px} +.feature{background:#fff;border:1px solid #eee;border-radius:12px;padding:20px} +.feature h3{font-size:16px;margin-bottom:8px} +.feature p{font-size:14px;color:#888;margin:0} diff --git a/app/src/main/assets/sample_projects/docs-mkdocs/index.html b/app/src/main/assets/sample_projects/docs-mkdocs/index.html new file mode 100644 index 0000000..1068b72 --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-mkdocs/index.html @@ -0,0 +1,388 @@ + + + + + + + MkDocs 文档 + + + + +
+
+
📗
+

MkDocs 文档

+

使用 Markdown 构建项目文档,Material 主题打造极致体验

+
MaterialPythonMarkdown开源
+
+
+
+
🚀
+
快速入门
+
5 分钟搭建文档站
+
+
+
🎨
+
Material 主题
+
现代化设计,深色模式
+
+
+
🔍
+
搜索
+
内置全文搜索引擎
+
+
+
📱
+
响应式
+
完美适配移动设备
+
+
+
+
⚡ 快速开始
+
+
1
+
+
安装 MkDocs
+
pip install mkdocs-material
+
+
+
+
2
+
+
新建项目
+
mkdocs new my-docs && cd my-docs
+
+
+
+
3
+
+
启动预览
+
mkdocs serve
+
+
+
+ +
+
📗 MkDocs Material · 由 WebToApp 提供
+
+
+ + + \ No newline at end of file diff --git a/app/src/main/assets/sample_projects/docs-mkdocs/mkdocs.yml b/app/src/main/assets/sample_projects/docs-mkdocs/mkdocs.yml new file mode 100644 index 0000000..ea7a7b7 --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-mkdocs/mkdocs.yml @@ -0,0 +1,2 @@ +site_name: MkDocs Demo +theme: material diff --git a/app/src/main/assets/sample_projects/docs-mkdocs/style.css b/app/src/main/assets/sample_projects/docs-mkdocs/style.css new file mode 100644 index 0000000..04e12a5 --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-mkdocs/style.css @@ -0,0 +1,14 @@ +*{margin:0;padding:0;box-sizing:border-box} +body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;display:flex;min-height:100vh;background:#fafafa} +.sidebar{width:240px;background:#fff;border-right:1px solid #eee;padding:20px} +.logo{font-size:20px;font-weight:700;margin-bottom:24px;padding:8px 0} +.sidebar a{display:block;padding:10px 16px;border-radius:8px;color:#333;text-decoration:none;margin-bottom:4px;font-size:14px} +.sidebar a.active{background:#e8f5e9;color:#2e7d32;font-weight:600} +.sidebar a:hover{background:#f5f5f5} +.content{flex:1;padding:40px 60px;max-width:800px} +h1{font-size:32px;color:#1a1a1a;margin-bottom:16px} +p{color:#666;line-height:1.8;margin-bottom:24px} +.features{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:32px} +.feature{background:#fff;border:1px solid #eee;border-radius:12px;padding:20px} +.feature h3{font-size:16px;margin-bottom:8px} +.feature p{font-size:14px;color:#888;margin:0} diff --git a/app/src/main/assets/sample_projects/docs-vitepress-ar/.vitepress/config.json b/app/src/main/assets/sample_projects/docs-vitepress-ar/.vitepress/config.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-vitepress-ar/.vitepress/config.json @@ -0,0 +1 @@ +{} diff --git a/app/src/main/assets/sample_projects/docs-vitepress-ar/index.html b/app/src/main/assets/sample_projects/docs-vitepress-ar/index.html new file mode 100644 index 0000000..09bd6f4 --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-vitepress-ar/index.html @@ -0,0 +1,309 @@ + + + + + + + وثائق VitePress + + + + +
+
+
⚡
+

VitePress

+

مولد مواقع ثابتة مدعوم بـ Vite مصمم للتوثيق

+
v1.0Vue 3Vite
+
+
+
+
⚡
+
فائق السرعة
+
إعادة تحميل فورية
+
+
+
📝
+
Markdown
+
صيغة Markdown محسنة
+
+
+
🎨
+
السمات
+
سمة افتراضية جميلة
+
+
+
🔧
+
قابل للتخصيص
+
تكامل عميق مع Vue
+
+
+
+
🚀 البداية السريعة
+
+
1
+
+
إنشاء
+
npx vitepress init
+
+
+
+
2
+
+
تطوير
+
npx vitepress dev docs
+
+
+
+
3
+
+
بناء
+
npx vitepress build docs
+
+
+
+
+
⚡ VitePress · مقدم من WebToApp
+
+
+ + + \ No newline at end of file diff --git a/app/src/main/assets/sample_projects/docs-vitepress-ar/style.css b/app/src/main/assets/sample_projects/docs-vitepress-ar/style.css new file mode 100644 index 0000000..04e12a5 --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-vitepress-ar/style.css @@ -0,0 +1,14 @@ +*{margin:0;padding:0;box-sizing:border-box} +body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;display:flex;min-height:100vh;background:#fafafa} +.sidebar{width:240px;background:#fff;border-right:1px solid #eee;padding:20px} +.logo{font-size:20px;font-weight:700;margin-bottom:24px;padding:8px 0} +.sidebar a{display:block;padding:10px 16px;border-radius:8px;color:#333;text-decoration:none;margin-bottom:4px;font-size:14px} +.sidebar a.active{background:#e8f5e9;color:#2e7d32;font-weight:600} +.sidebar a:hover{background:#f5f5f5} +.content{flex:1;padding:40px 60px;max-width:800px} +h1{font-size:32px;color:#1a1a1a;margin-bottom:16px} +p{color:#666;line-height:1.8;margin-bottom:24px} +.features{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:32px} +.feature{background:#fff;border:1px solid #eee;border-radius:12px;padding:20px} +.feature h3{font-size:16px;margin-bottom:8px} +.feature p{font-size:14px;color:#888;margin:0} diff --git a/app/src/main/assets/sample_projects/docs-vitepress-en/.vitepress/config.json b/app/src/main/assets/sample_projects/docs-vitepress-en/.vitepress/config.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-vitepress-en/.vitepress/config.json @@ -0,0 +1 @@ +{} diff --git a/app/src/main/assets/sample_projects/docs-vitepress-en/index.html b/app/src/main/assets/sample_projects/docs-vitepress-en/index.html new file mode 100644 index 0000000..bd628f4 --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-vitepress-en/index.html @@ -0,0 +1,383 @@ + + + + + + + VitePress Docs + + + + +
+
+
⚡
+

VitePress

+

Vite-powered static site generator built for documentation

+
v1.0Vue 3ViteSSG
+
+
+
+
⚡
+
Lightning Fast
+
Instant hot reload
+
+
+
📝
+
Markdown
+
Enhanced Markdown syntax
+
+
+
🎨
+
Themes
+
Beautiful default theme
+
+
+
🔧
+
Customizable
+
Deep Vue integration
+
+
+
+
🚀 Getting Started
+
+
1
+
+
Initialize
+
npx vitepress init
+
+
+
+
2
+
+
Develop
+
npx vitepress dev docs
+
+
+
+
3
+
+
Build
+
npx vitepress build docs
+
+
+
+
+
✨ Features
+
+
⚡
+
+
Vite Powered
+
Instant server start + blazing fast HMR
+
+
+
+
🎯
+
+
Vue 3 Integration
+
Embed Vue components in Markdown
+
+
+
+
🔍
+
+
Built-in Search
+
Full-text search powered by minisearch
+
+
+
+
+
⚡ VitePress · Powered by WebToApp
+
+
+ + + \ No newline at end of file diff --git a/app/src/main/assets/sample_projects/docs-vitepress-en/style.css b/app/src/main/assets/sample_projects/docs-vitepress-en/style.css new file mode 100644 index 0000000..04e12a5 --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-vitepress-en/style.css @@ -0,0 +1,14 @@ +*{margin:0;padding:0;box-sizing:border-box} +body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;display:flex;min-height:100vh;background:#fafafa} +.sidebar{width:240px;background:#fff;border-right:1px solid #eee;padding:20px} +.logo{font-size:20px;font-weight:700;margin-bottom:24px;padding:8px 0} +.sidebar a{display:block;padding:10px 16px;border-radius:8px;color:#333;text-decoration:none;margin-bottom:4px;font-size:14px} +.sidebar a.active{background:#e8f5e9;color:#2e7d32;font-weight:600} +.sidebar a:hover{background:#f5f5f5} +.content{flex:1;padding:40px 60px;max-width:800px} +h1{font-size:32px;color:#1a1a1a;margin-bottom:16px} +p{color:#666;line-height:1.8;margin-bottom:24px} +.features{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:32px} +.feature{background:#fff;border:1px solid #eee;border-radius:12px;padding:20px} +.feature h3{font-size:16px;margin-bottom:8px} +.feature p{font-size:14px;color:#888;margin:0} diff --git a/app/src/main/assets/sample_projects/docs-vitepress/.vitepress/config.json b/app/src/main/assets/sample_projects/docs-vitepress/.vitepress/config.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-vitepress/.vitepress/config.json @@ -0,0 +1 @@ +{} diff --git a/app/src/main/assets/sample_projects/docs-vitepress/index.html b/app/src/main/assets/sample_projects/docs-vitepress/index.html new file mode 100644 index 0000000..0ac6c1a --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-vitepress/index.html @@ -0,0 +1,398 @@ + + + + + + + VitePress 文档 + + + + +
+
+
⚡
+

VitePress

+

由 Vite 驱动的静态站点生成器,为文档而生

+
v1.0Vue 3ViteSSG
+
+
+
+
⚡
+
极速启动
+
毫秒级热更新体验
+
+
+
📝
+
Markdown
+
增强版 Markdown 语法
+
+
+
🎨
+
主题
+
默认主题即开即用
+
+
+
🔧
+
自定义
+
Vue 组件深度集成
+
+
+
+
🚀 快速开始
+
+
1
+
+
安装 VitePress
+
npx vitepress init
+
+
+
+
2
+
+
启动开发
+
npx vitepress dev docs
+
+
+
+
3
+
+
构建发布
+
npx vitepress build docs
+
+
+
+
+
✨ 核心特性
+
+
⚡
+
+
Vite 驱动
+
即时服务器启动 + 闪电般的 HMR
+
+
+
+
🎯
+
+
Vue 3 集成
+
在 Markdown 中嵌入 Vue 组件
+
+
+
+
🔍
+
+
内置搜索
+
基于 minisearch 的全文搜索
+
+
+
+
📊
+
+
SEO 优化
+
自动生成 sitemap + meta 标签
+
+
+
+
+
⚡ VitePress · 由 WebToApp 提供
+
+
+ + + \ No newline at end of file diff --git a/app/src/main/assets/sample_projects/docs-vitepress/style.css b/app/src/main/assets/sample_projects/docs-vitepress/style.css new file mode 100644 index 0000000..04e12a5 --- /dev/null +++ b/app/src/main/assets/sample_projects/docs-vitepress/style.css @@ -0,0 +1,14 @@ +*{margin:0;padding:0;box-sizing:border-box} +body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;display:flex;min-height:100vh;background:#fafafa} +.sidebar{width:240px;background:#fff;border-right:1px solid #eee;padding:20px} +.logo{font-size:20px;font-weight:700;margin-bottom:24px;padding:8px 0} +.sidebar a{display:block;padding:10px 16px;border-radius:8px;color:#333;text-decoration:none;margin-bottom:4px;font-size:14px} +.sidebar a.active{background:#e8f5e9;color:#2e7d32;font-weight:600} +.sidebar a:hover{background:#f5f5f5} +.content{flex:1;padding:40px 60px;max-width:800px} +h1{font-size:32px;color:#1a1a1a;margin-bottom:16px} +p{color:#666;line-height:1.8;margin-bottom:24px} +.features{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:32px} +.feature{background:#fff;border:1px solid #eee;border-radius:12px;padding:20px} +.feature h3{font-size:16px;margin-bottom:8px} +.feature p{font-size:14px;color:#888;margin:0} diff --git a/app/src/main/assets/sample_projects/go-echo-ar/go.mod b/app/src/main/assets/sample_projects/go-echo-ar/go.mod new file mode 100644 index 0000000..fe1440d --- /dev/null +++ b/app/src/main/assets/sample_projects/go-echo-ar/go.mod @@ -0,0 +1,5 @@ +module github.com/demo/echo-server + +go 1.21 + +require github.com/labstack/echo/v4 v4.11.4 diff --git a/app/src/main/assets/sample_projects/go-echo-ar/main.go b/app/src/main/assets/sample_projects/go-echo-ar/main.go new file mode 100644 index 0000000..9ce34be --- /dev/null +++ b/app/src/main/assets/sample_projects/go-echo-ar/main.go @@ -0,0 +1,25 @@ +package main +// Echo Service Monitor (AR) +import ("fmt";"math/rand";"net/http";"os";"time";"github.com/labstack/echo/v4";"github.com/labstack/echo/v4/middleware") +var startTime = time.Now() +func main() { + e := echo.New(); e.HideBanner = true; e.Use(middleware.Logger()) + e.GET("/", func(c echo.Context) error { return c.HTML(http.StatusOK, dash()) }) + e.GET("/health", func(c echo.Context) error { return c.JSON(http.StatusOK, map[string]interface{}{"status":"healthy"}) }) + port := os.Getenv("PORT"); if port == "" { port = "1323" }; e.Logger.Fatal(e.Start(":"+port)) +} +func dash() string { + up := time.Since(startTime).Round(time.Second) + svcs := []struct{n,s,i,c string}{{"API Gateway","يعمل","🌐","#00d4aa"},{"قاعدة البيانات","يعمل","🗄️","#3b82f6"},{"التخزين المؤقت","يعمل","⚡","#f59e0b"},{"قائمة الرسائل","يعمل","📨","#8b5cf6"},{"خدمة المصادقة","يعمل","🔐","#ec4899"},{"التخزين","يعمل","💾","#06b6d4"}} + sh := ""; for _,s := range svcs { sh += fmt.Sprintf(`
%s
%s
● %s
`,s.c,s.i,s.n,s.c,s.s) } + bars := ""; days := []string{"إثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت","أحد"} + for i,d := range days { h:=30+rand.Intn(60); bars+=fmt.Sprintf(`
%s
`,h,0.3+float64(i)*0.08,d) } + return fmt.Sprintf(`Echo +
+

📡 Echo مراقب

لوحة مراقبة الخدمات

الكل يعمل
+
%s
وقت التشغيل
6
الخدمات
99.9%%
التوفر
+
حالة الخدمات
%s
+
حركة الزيارات
%s
+
Echo v4 · Go 1.22 · يعمل
+
`,up,sh,bars) +} diff --git a/app/src/main/assets/sample_projects/go-echo-en/go.mod b/app/src/main/assets/sample_projects/go-echo-en/go.mod new file mode 100644 index 0000000..fe1440d --- /dev/null +++ b/app/src/main/assets/sample_projects/go-echo-en/go.mod @@ -0,0 +1,5 @@ +module github.com/demo/echo-server + +go 1.21 + +require github.com/labstack/echo/v4 v4.11.4 diff --git a/app/src/main/assets/sample_projects/go-echo-en/main.go b/app/src/main/assets/sample_projects/go-echo-en/main.go new file mode 100644 index 0000000..349d814 --- /dev/null +++ b/app/src/main/assets/sample_projects/go-echo-en/main.go @@ -0,0 +1,24 @@ +package main +// Echo Service Monitor (EN) +import ("fmt";"math/rand";"net/http";"os";"time";"github.com/labstack/echo/v4";"github.com/labstack/echo/v4/middleware") +var startTime = time.Now() +func main() { + e := echo.New(); e.HideBanner = true; e.Use(middleware.Logger()) + e.GET("/", func(c echo.Context) error { return c.HTML(http.StatusOK, dash()) }) + e.GET("/health", func(c echo.Context) error { return c.JSON(http.StatusOK, map[string]interface{}{"status":"healthy","uptime":time.Since(startTime).String()}) }) + e.GET("/api/services", func(c echo.Context) error { return c.JSON(http.StatusOK, map[string]interface{}{"services":[]map[string]string{{"name":"API Gateway","status":"running"},{"name":"Database","status":"running"},{"name":"Cache","status":"running"}}}) }) + port := os.Getenv("PORT"); if port == "" { port = "1323" }; e.Logger.Fatal(e.Start(":"+port)) +} +func dash() string { + up := time.Since(startTime).Round(time.Second) + svcs := []struct{n,s,l,i,c string}{{"API Gateway","Running","2ms","🌐","#00d4aa"},{"Database","Running","5ms","🗄️","#3b82f6"},{"Redis Cache","Running","<1ms","⚡","#f59e0b"},{"Message Queue","Running","3ms","📨","#8b5cf6"},{"Auth Service","Running","4ms","🔐","#ec4899"},{"Storage","Running","8ms","💾","#06b6d4"}} + sh := ""; for _,s := range svcs { sh += fmt.Sprintf(`
%s
%s
● %s
%s
`,s.c,s.i,s.n,s.c,s.s,s.l) } + bars := ""; days := []string{"Mon","Tue","Wed","Thu","Fri","Sat","Sun"} + for i,d := range days { h:=30+rand.Intn(60); bars+=fmt.Sprintf(`
%s
`,h,0.3+float64(i)*0.08,d) } + return fmt.Sprintf(`Echo Monitor +

📡 Echo Monitor

Service Monitoring Panel

All OK
+
%s
Uptime
6
Services
99.9%%
Avail
+
Services🟢 All Online
%s
+
Traffic📊 Weekly
%s
+
Echo v4 · Go 1.22 · Running
`,up,sh,bars) +} diff --git a/app/src/main/assets/sample_projects/go-echo/go.mod b/app/src/main/assets/sample_projects/go-echo/go.mod new file mode 100644 index 0000000..fe1440d --- /dev/null +++ b/app/src/main/assets/sample_projects/go-echo/go.mod @@ -0,0 +1,5 @@ +module github.com/demo/echo-server + +go 1.21 + +require github.com/labstack/echo/v4 v4.11.4 diff --git a/app/src/main/assets/sample_projects/go-echo/main.go b/app/src/main/assets/sample_projects/go-echo/main.go new file mode 100644 index 0000000..27c6f77 --- /dev/null +++ b/app/src/main/assets/sample_projects/go-echo/main.go @@ -0,0 +1,117 @@ +package main + +// Echo 服务监控面板 — 精美的 Go Web 应用示例 +import ( + "fmt" + "math/rand" + "net/http" + "os" + "time" + + "github.com/labstack/echo/v4" + "github.com/labstack/echo/v4/middleware" +) + +type Status struct { + Service string `json:"service"` + Status string `json:"status"` + Uptime string `json:"uptime"` +} + +var startTime = time.Now() + +func main() { + e := echo.New() + e.HideBanner = true + e.Use(middleware.Logger()) + + e.GET("/", dashboardHandler) + e.GET("/health", func(c echo.Context) error { + return c.JSON(http.StatusOK, Status{"echo-dashboard", "healthy", time.Since(startTime).String()}) + }) + e.GET("/api/services", func(c echo.Context) error { + return c.JSON(http.StatusOK, map[string]interface{}{ + "services": []map[string]interface{}{ + {"name": "API Gateway", "status": "running", "latency": "2ms"}, + {"name": "Database", "status": "running", "latency": "5ms"}, + {"name": "Cache", "status": "running", "latency": "<1ms"}, + {"name": "Queue", "status": "running", "latency": "3ms"}, + }, + }) + }) + + port := os.Getenv("PORT") + if port == "" { + port = "1323" + } + e.Logger.Fatal(e.Start(":" + port)) +} + +func dashboardHandler(c echo.Context) error { + uptime := time.Since(startTime).Round(time.Second) + services := []struct{ name, status, latency, icon, color string }{ + {"API Gateway", "运行中", "2ms", "🌐", "#00d4aa"}, + {"Database", "运行中", "5ms", "🗄️", "#3b82f6"}, + {"Redis Cache", "运行中", "<1ms", "⚡", "#f59e0b"}, + {"Message Queue", "运行中", "3ms", "📨", "#8b5cf6"}, + {"Auth Service", "运行中", "4ms", "🔐", "#ec4899"}, + {"Storage", "运行中", "8ms", "💾", "#06b6d4"}, + } + svcHTML := "" + for _, s := range services { + svcHTML += fmt.Sprintf(`
%s
%s
● %s
%s
`, s.color, s.icon, s.name, s.color, s.status, s.latency) + } + bars := "" + days := []string{"周一", "周二", "周三", "周四", "周五", "周六", "周日"} + for i, d := range days { + h := 30 + rand.Intn(60) + bars += fmt.Sprintf(`
%s
`, h, 0.3+float64(i)*0.08, d) + } + + html := fmt.Sprintf(` +Echo Monitor + +
+

📡 Echo Monitor

服务监控面板

全部正常
+
+
%s
运行时间
+
6
服务数
+
99.9%%
可用性
+
+
服务状态🟢 全部在线
%s
+
流量趋势📊 本周
%s
+
Echo v4 · Go 1.22 · 运行中
+
`, uptime, svcHTML, bars) + + return c.HTML(http.StatusOK, html) +} diff --git a/app/src/main/assets/sample_projects/go-fiber-ar/go.mod b/app/src/main/assets/sample_projects/go-fiber-ar/go.mod new file mode 100644 index 0000000..dccb986 --- /dev/null +++ b/app/src/main/assets/sample_projects/go-fiber-ar/go.mod @@ -0,0 +1,5 @@ +module github.com/demo/fiber-app + +go 1.21 + +require github.com/gofiber/fiber/v2 v2.52.0 diff --git a/app/src/main/assets/sample_projects/go-fiber-ar/main.go b/app/src/main/assets/sample_projects/go-fiber-ar/main.go new file mode 100644 index 0000000..6eaccc1 --- /dev/null +++ b/app/src/main/assets/sample_projects/go-fiber-ar/main.go @@ -0,0 +1,26 @@ +package main +// Fiber Performance Dashboard (AR) +import ("fmt";"math/rand";"os";"runtime";"time";"github.com/gofiber/fiber/v2";"github.com/gofiber/fiber/v2/middleware/logger") +var startTime = time.Now() +func main() { + app := fiber.New(fiber.Config{AppName:"Fiber Dashboard",DisableStartupMessage:true}); app.Use(logger.New()) + app.Get("/", func(c *fiber.Ctx) error { c.Set("Content-Type","text/html; charset=utf-8"); return c.SendString(dash()) }) + app.Get("/api/users", func(c *fiber.Ctx) error { return c.JSON([]fiber.Map{{"id":1,"name":"أحمد"},{"id":2,"name":"فاطمة"},{"id":3,"name":"محمد"}}) }) + app.Get("/api/health", func(c *fiber.Ctx) error { var m runtime.MemStats; runtime.ReadMemStats(&m); return c.JSON(fiber.Map{"status":"healthy","memory_mb":m.Alloc/1024/1024}) }) + port := os.Getenv("PORT"); if port == "" { port = "3000" }; app.Listen(":"+port) +} +func dash() string { + up := time.Since(startTime).Round(time.Second); var m runtime.MemStats; runtime.ReadMemStats(&m); mb := m.Alloc/1024/1024; gr := runtime.NumGoroutine() + bars := ""; days := []string{"إثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت","أحد"} + for i,d := range days { h:=25+rand.Intn(65); bars+=fmt.Sprintf(`
%s
`,h,0.3+float64(i)*0.08,d) } + mets := []struct{l,v,i,c string}{{"زمن الاستجابة","<1ms","⚡","#f59e0b"},{"الذاكرة",fmt.Sprintf("%dMB",mb),"💾","#8b5cf6"},{"الخيوط",fmt.Sprintf("%d",gr),"🔄","#06b6d4"},{"QPS",fmt.Sprintf("%d",1000+rand.Intn(4000)),"📊","#ec4899"}} + mh := ""; for _,mt := range mets { mh += fmt.Sprintf(`
%s
%s
%s
`,mt.c,mt.i,mt.l,mt.c,mt.v) } + return fmt.Sprintf(`Fiber +
+

🔥 Fiber لوحة

إطار عمل Go فائق السرعة

يعمل
+
%s
التشغيل
%dMB
الذاكرة
%d
الخيوط
+
مقاييس الأداء
%s
+
الإنتاجية
%s
+
Fiber v2 · Go · يعمل
+
`,up,mb,gr,mh,bars) +} diff --git a/app/src/main/assets/sample_projects/go-fiber-en/go.mod b/app/src/main/assets/sample_projects/go-fiber-en/go.mod new file mode 100644 index 0000000..dccb986 --- /dev/null +++ b/app/src/main/assets/sample_projects/go-fiber-en/go.mod @@ -0,0 +1,5 @@ +module github.com/demo/fiber-app + +go 1.21 + +require github.com/gofiber/fiber/v2 v2.52.0 diff --git a/app/src/main/assets/sample_projects/go-fiber-en/main.go b/app/src/main/assets/sample_projects/go-fiber-en/main.go new file mode 100644 index 0000000..21d8d2b --- /dev/null +++ b/app/src/main/assets/sample_projects/go-fiber-en/main.go @@ -0,0 +1,26 @@ +package main +// Fiber Performance Dashboard (EN) +import ("fmt";"math/rand";"os";"runtime";"time";"github.com/gofiber/fiber/v2";"github.com/gofiber/fiber/v2/middleware/logger") +var startTime = time.Now() +func main() { + app := fiber.New(fiber.Config{AppName:"Fiber Dashboard",DisableStartupMessage:true}); app.Use(logger.New()) + app.Get("/", func(c *fiber.Ctx) error { c.Set("Content-Type","text/html; charset=utf-8"); return c.SendString(dash()) }) + app.Get("/api/users", func(c *fiber.Ctx) error { return c.JSON([]fiber.Map{{"id":1,"name":"Alice"},{"id":2,"name":"Bob"},{"id":3,"name":"Carol"}}) }) + app.Get("/api/health", func(c *fiber.Ctx) error { var m runtime.MemStats; runtime.ReadMemStats(&m); return c.JSON(fiber.Map{"status":"healthy","memory_mb":m.Alloc/1024/1024,"goroutines":runtime.NumGoroutine()}) }) + port := os.Getenv("PORT"); if port == "" { port = "3000" }; app.Listen(":"+port) +} +func dash() string { + up := time.Since(startTime).Round(time.Second); var m runtime.MemStats; runtime.ReadMemStats(&m); mb := m.Alloc/1024/1024; gr := runtime.NumGoroutine() + bars := ""; days := []string{"Mon","Tue","Wed","Thu","Fri","Sat","Sun"} + for i,d := range days { h:=25+rand.Intn(65); bars+=fmt.Sprintf(`
%s
`,h,0.3+float64(i)*0.08,d) } + mets := []struct{l,v,i,c string}{{"Response","<1ms","⚡","#f59e0b"},{"Memory",fmt.Sprintf("%dMB",mb),"💾","#8b5cf6"},{"Goroutines",fmt.Sprintf("%d",gr),"🔄","#06b6d4"},{"QPS",fmt.Sprintf("%d",1000+rand.Intn(4000)),"📊","#ec4899"}} + mh := ""; for _,mt := range mets { mh += fmt.Sprintf(`
%s
%s
%s
`,mt.c,mt.i,mt.l,mt.c,mt.v) } + return fmt.Sprintf(`Fiber +

🔥 Fiber Dashboard

Ultra-Fast Go Web Framework

Running
+
%s
Uptime
%dMB
Memory
%d
Goroutines
+
Performance⚡ Live
%s
+
Throughput📊 Weekly
%s
+
Live Test🧪
+
Fiber v2 · Go %s · Running
+`,up,mb,gr,mh,bars,runtime.Version()) +} diff --git a/app/src/main/assets/sample_projects/go-fiber/go.mod b/app/src/main/assets/sample_projects/go-fiber/go.mod new file mode 100644 index 0000000..dccb986 --- /dev/null +++ b/app/src/main/assets/sample_projects/go-fiber/go.mod @@ -0,0 +1,5 @@ +module github.com/demo/fiber-app + +go 1.21 + +require github.com/gofiber/fiber/v2 v2.52.0 diff --git a/app/src/main/assets/sample_projects/go-fiber/main.go b/app/src/main/assets/sample_projects/go-fiber/main.go new file mode 100644 index 0000000..bd90984 --- /dev/null +++ b/app/src/main/assets/sample_projects/go-fiber/main.go @@ -0,0 +1,126 @@ +package main + +// Fiber 性能分析面板 — 精美的 Go Web 应用示例 +import ( + "fmt" + "math/rand" + "os" + "runtime" + "time" + + "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v2/middleware/logger" +) + +var startTime = time.Now() + +func main() { + app := fiber.New(fiber.Config{AppName: "Fiber Dashboard v2.0", DisableStartupMessage: true}) + app.Use(logger.New()) + + app.Get("/", dashboardHandler) + app.Get("/api/users", func(c *fiber.Ctx) error { + return c.JSON([]fiber.Map{ + {"id": 1, "name": "Alice", "role": "Admin"}, + {"id": 2, "name": "Bob", "role": "User"}, + {"id": 3, "name": "Carol", "role": "Editor"}, + }) + }) + app.Get("/api/health", func(c *fiber.Ctx) error { + var m runtime.MemStats + runtime.ReadMemStats(&m) + return c.JSON(fiber.Map{ + "status": "healthy", + "framework": "Fiber", + "uptime": time.Since(startTime).String(), + "memory_mb": m.Alloc / 1024 / 1024, + "goroutines": runtime.NumGoroutine(), + }) + }) + + port := os.Getenv("PORT") + if port == "" { + port = "3000" + } + app.Listen(":" + port) +} + +func dashboardHandler(c *fiber.Ctx) error { + uptime := time.Since(startTime).Round(time.Second) + var m runtime.MemStats + runtime.ReadMemStats(&m) + memMB := m.Alloc / 1024 / 1024 + goroutines := runtime.NumGoroutine() + + bars := "" + days := []string{"周一", "周二", "周三", "周四", "周五", "周六", "周日"} + for i, d := range days { + h := 25 + rand.Intn(65) + bars += fmt.Sprintf(`
%s
`, h, 0.3+float64(i)*0.08, d) + } + + metrics := []struct{ label, value, icon, color string }{ + {"响应时间", "<1ms", "⚡", "#f59e0b"}, + {"内存使用", fmt.Sprintf("%dMB", memMB), "💾", "#8b5cf6"}, + {"协程数", fmt.Sprintf("%d", goroutines), "🔄", "#06b6d4"}, + {"QPS", fmt.Sprintf("%d", 1000+rand.Intn(4000)), "📊", "#ec4899"}, + } + metricHTML := "" + for _, met := range metrics { + metricHTML += fmt.Sprintf(`
%s
%s
%s
`, met.color, met.icon, met.label, met.color, met.value) + } + + html := fmt.Sprintf(` +Fiber Dashboard + +
+

🔥 Fiber Dashboard

超快 Go Web 框架

运行中
+
+
%s
运行时间
+
%dMB
内存
+
%d
协程
+
+
性能指标⚡ 实时
%s
+
吞吐趋势📊 本周
%s
+
在线测试🧪 交互
+
+
+
Fiber v2 · Go %s · 运行中
+
+ +`, uptime, memMB, goroutines, metricHTML, bars, runtime.Version()) + + c.Set("Content-Type", "text/html; charset=utf-8") + return c.SendString(html) +} diff --git a/app/src/main/assets/sample_projects/go-gin-ar/go.mod b/app/src/main/assets/sample_projects/go-gin-ar/go.mod new file mode 100644 index 0000000..adf53b1 --- /dev/null +++ b/app/src/main/assets/sample_projects/go-gin-ar/go.mod @@ -0,0 +1,5 @@ +module github.com/demo/gin-api + +go 1.21 + +require github.com/gin-gonic/gin v1.9.1 diff --git a/app/src/main/assets/sample_projects/go-gin-ar/main.go b/app/src/main/assets/sample_projects/go-gin-ar/main.go new file mode 100644 index 0000000..3ee7ef7 --- /dev/null +++ b/app/src/main/assets/sample_projects/go-gin-ar/main.go @@ -0,0 +1,25 @@ +package main +// Gin REST API Dashboard — Go Web (AR) +import ("fmt";"math/rand";"net/http";"os";"time";"github.com/gin-gonic/gin") +type Item struct { ID int `json:"id"`; Name string `json:"name"`; Price float64 `json:"price"` } +var items = []Item{{1,"MacBook Pro",1999},{2,"iPhone 15",999},{3,"AirPods Pro",249},{4,"iPad Air",599}} +var startTime = time.Now() +func main() { + gin.SetMode(gin.ReleaseMode); r := gin.Default() + r.GET("/", func(c *gin.Context) { c.Header("Content-Type","text/html; charset=utf-8"); c.String(http.StatusOK, dash()) }) + r.GET("/api/items", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"data":items}) }) + r.GET("/api/health", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"status":"healthy","uptime":time.Since(startTime).String()}) }) + port := os.Getenv("PORT"); if port == "" { port = "8080" }; r.Run(":"+port) +} +func dash() string { + up := time.Since(startTime).Round(time.Second); bars := "" + days := []string{"إثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت","أحد"} + for i,d := range days { h:=20+rand.Intn(70); bars+=fmt.Sprintf(`
%s
`,h,0.3+float64(i)*0.08,d) } + return fmt.Sprintf(`Gin +

🚀 Gin لوحة

إطار عمل Go عالي الأداء

يعمل
+
%s
وقت التشغيل
%d
المنتجات
4
المسارات
+
اتجاه الزيارات📊 أسبوعي
%s
+
اختبار مباشر🧪
+
Gin · Go 1.22 · يعمل
+`,up,len(items),bars) +} diff --git a/app/src/main/assets/sample_projects/go-gin-en/go.mod b/app/src/main/assets/sample_projects/go-gin-en/go.mod new file mode 100644 index 0000000..adf53b1 --- /dev/null +++ b/app/src/main/assets/sample_projects/go-gin-en/go.mod @@ -0,0 +1,5 @@ +module github.com/demo/gin-api + +go 1.21 + +require github.com/gin-gonic/gin v1.9.1 diff --git a/app/src/main/assets/sample_projects/go-gin-en/main.go b/app/src/main/assets/sample_projects/go-gin-en/main.go new file mode 100644 index 0000000..a72acd2 --- /dev/null +++ b/app/src/main/assets/sample_projects/go-gin-en/main.go @@ -0,0 +1,52 @@ +package main + +// Gin REST API Dashboard — Go Web App Demo (EN) +import ( + "fmt" + "math/rand" + "net/http" + "os" + "time" + "github.com/gin-gonic/gin" +) + +type Item struct { + ID int `json:"id"` + Name string `json:"name"` + Price float64 `json:"price"` +} + +var items = []Item{{1, "MacBook Pro", 1999.00}, {2, "iPhone 15", 999.00}, {3, "AirPods Pro", 249.00}, {4, "iPad Air", 599.00}} +var startTime = time.Now() + +func main() { + gin.SetMode(gin.ReleaseMode) + r := gin.Default() + r.GET("/", func(c *gin.Context) { c.Header("Content-Type", "text/html; charset=utf-8"); c.String(http.StatusOK, dashboard()) }) + api := r.Group("/api") + { + api.GET("/items", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"status": "ok", "data": items}) }) + api.GET("/health", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"status": "healthy", "uptime": time.Since(startTime).String()}) }) + } + port := os.Getenv("PORT"); if port == "" { port = "8080" } + r.Run(":" + port) +} + +func dashboard() string { + up := time.Since(startTime).Round(time.Second) + bars := "" + days := []string{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"} + for i, d := range days { + h := 20 + rand.Intn(70) + bars += fmt.Sprintf(`
%s
`, h, 0.3+float64(i)*0.08, d) + } + return fmt.Sprintf(`Gin Dashboard + +

🚀 Gin Dashboard

High-Performance Go Web Framework

Running
+
%s
Uptime
%d
Items
4
Routes
+
Traffic Trends📊 Weekly
%s
+
Live Testing🧪 Try It
+
Gin · Go 1.22 · Running
+ +`, up, len(items), bars) +} diff --git a/app/src/main/assets/sample_projects/go-gin/go.mod b/app/src/main/assets/sample_projects/go-gin/go.mod new file mode 100644 index 0000000..adf53b1 --- /dev/null +++ b/app/src/main/assets/sample_projects/go-gin/go.mod @@ -0,0 +1,5 @@ +module github.com/demo/gin-api + +go 1.21 + +require github.com/gin-gonic/gin v1.9.1 diff --git a/app/src/main/assets/sample_projects/go-gin/main.go b/app/src/main/assets/sample_projects/go-gin/main.go new file mode 100644 index 0000000..fae04a8 --- /dev/null +++ b/app/src/main/assets/sample_projects/go-gin/main.go @@ -0,0 +1,137 @@ +package main + +// Gin REST API 仪表盘 — 精美的 Go Web 应用示例 +import ( + "fmt" + "math/rand" + "net/http" + "os" + "time" + + "github.com/gin-gonic/gin" +) + +type Item struct { + ID int `json:"id"` + Name string `json:"name"` + Price float64 `json:"price"` +} + +var items = []Item{ + {1, "MacBook Pro", 1999.00}, + {2, "iPhone 15", 999.00}, + {3, "AirPods Pro", 249.00}, + {4, "iPad Air", 599.00}, +} + +var startTime = time.Now() + +func main() { + gin.SetMode(gin.ReleaseMode) + r := gin.Default() + + r.GET("/", func(c *gin.Context) { + c.Header("Content-Type", "text/html; charset=utf-8") + c.String(http.StatusOK, getDashboardHTML()) + }) + + api := r.Group("/api") + { + api.GET("/items", func(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{"status": "ok", "data": items, "count": len(items)}) + }) + api.GET("/items/:id", func(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{"status": "ok", "data": items[0]}) + }) + api.GET("/health", func(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{ + "status": "healthy", + "framework": "Gin", + "uptime": time.Since(startTime).String(), + "go": "1.22", + }) + }) + } + + port := os.Getenv("PORT") + if port == "" { + port = "8080" + } + r.Run(":" + port) +} + +func getDashboardHTML() string { + uptime := time.Since(startTime).Round(time.Second) + bars := "" + days := []string{"周一", "周二", "周三", "周四", "周五", "周六", "周日"} + for i, d := range days { + h := 20 + rand.Intn(70) + delay := fmt.Sprintf("%.2f", 0.3+float64(i)*0.08) + bars += fmt.Sprintf(`
%s
`, h, delay, d) + } + + routes := []struct{ method, path, desc, ms string }{ + {"GET", "/", "仪表盘首页", "<1ms"}, + {"GET", "/api/items", "获取商品列表", "~1ms"}, + {"GET", "/api/items/:id", "获取商品详情", "~1ms"}, + {"GET", "/api/health", "健康检查", "<1ms"}, + } + routeHTML := "" + for _, r := range routes { + color := "#00d4aa" + routeHTML += fmt.Sprintf(`
%s
%s
%s
%s
`, color, color, r.method, r.path, r.desc, r.ms) + } + + return fmt.Sprintf(` +Gin Dashboard + +
+

🚀 Gin Dashboard

高性能 Go Web 框架

运行中
+
+
%s
运行时间
+
%d
商品数
+
4
路由数
+
+
API 路由⚡ RESTful
%s
+
请求趋势📊 本周
%s
+
在线测试🧪 交互
+
+
+
Gin · Go 1.22 · 运行中
+
+ +`, uptime, len(items), routeHTML, bars) +} diff --git a/app/src/main/assets/sample_projects/leaflet-bench-finder-ar/dist/index.html b/app/src/main/assets/sample_projects/leaflet-bench-finder-ar/dist/index.html new file mode 100644 index 0000000..c01ea9f --- /dev/null +++ b/app/src/main/assets/sample_projects/leaflet-bench-finder-ar/dist/index.html @@ -0,0 +1,569 @@ + + + + + + + مستكشف المقاعد + + + + + + +
+ +
+ مستكشف المقاعد
+
+
جاري تحميل الخريطة...
+
+
+
+
+ +
+
مستكشف المقاعد
+
ابحث عن أقرب مقعد للراحة
+
+
+
+
+ جاري تحديد الموقع... +
+
+
📍
+ + + + + \ No newline at end of file diff --git a/app/src/main/assets/sample_projects/leaflet-bench-finder-en/dist/index.html b/app/src/main/assets/sample_projects/leaflet-bench-finder-en/dist/index.html new file mode 100644 index 0000000..e682a14 --- /dev/null +++ b/app/src/main/assets/sample_projects/leaflet-bench-finder-en/dist/index.html @@ -0,0 +1,639 @@ + + + + + + + Bench Explorer + + + + + + +
+ +
+ Bench Explorer
+
+
Loading map...
+
+ +
+ +
+
+ +
+
Bench Explorer
+
Find the nearest bench to rest
+
+
+
+
+ Getting location... +
+
+ +
📍
+ + + + + + + \ No newline at end of file diff --git a/app/src/main/assets/sample_projects/nodejs-express-ar/package.json b/app/src/main/assets/sample_projects/nodejs-express-ar/package.json new file mode 100644 index 0000000..b55f435 --- /dev/null +++ b/app/src/main/assets/sample_projects/nodejs-express-ar/package.json @@ -0,0 +1,7 @@ +{ + "name": "todo-app", + "version": "1.0.0", + "main": "server.js", + "scripts": { "start": "node server.js" }, + "dependencies": {} +} diff --git a/app/src/main/assets/sample_projects/nodejs-express-ar/server.js b/app/src/main/assets/sample_projects/nodejs-express-ar/server.js new file mode 100644 index 0000000..9b52278 --- /dev/null +++ b/app/src/main/assets/sample_projects/nodejs-express-ar/server.js @@ -0,0 +1,38 @@ + + + + +const http = require('http'); +const fs = require('fs'); +const path = require('path'); +const PORT = process.env.PORT || 3000; +const DATA_FILE = path.join(__dirname, 'todos.json'); +const loadTodos = () => { try { if (fs.existsSync(DATA_FILE)) return JSON.parse(fs.readFileSync(DATA_FILE, 'utf8')); } catch (e) { } return [{ id: 1, text: 'مرحباً بتطبيق المهام 👋', done: false, createdAt: Date.now() }, { id: 2, text: 'اضغط الدائرة لإكمال المهمة ✓', done: true, createdAt: Date.now() - 1000 }, { id: 3, text: 'اضغط × لحذف المهمة', done: false, createdAt: Date.now() - 2000 }]; }; +const saveTodos = t => fs.writeFileSync(DATA_FILE, JSON.stringify(t, null, 2)); +let todos = loadTodos(), nextId = Math.max(...todos.map(t => t.id), 0) + 1; +function parseBody(req) { return new Promise(r => { let b = ''; req.on('data', c => b += c); req.on('end', () => { try { r(JSON.parse(b)) } catch (e) { r({}) } }) }) } +function sendJson(res, data, s = 200) { res.writeHead(s, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify(data)) } +const server = http.createServer(async (req, res) => { + const url = new URL(req.url, `http://${req.headers.host}`); + if (m === 'GET' && p === '/') { res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); return res.end(getPage()) } + if (m === 'GET' && p === '/api/todos') return sendJson(res, { success: true, data: todos }); + if (m === 'POST' && p === '/api/todos') { const { text } = await parseBody(req); if (!text?.trim()) return sendJson(res, { success: false }, 400); const t = { id: nextId++, text: text.trim(), done: false, createdAt: Date.now() }; todos.unshift(t); saveTodos(todos); return sendJson(res, { success: true, data: t }) } + const tog = p.match(/^\/api\/todos\/(\d+)\/toggle$/); if (m === 'PATCH' && tog) { const t = todos.find(x => x.id === parseInt(tog[1])); if (!t) return sendJson(res, { success: false }, 404); t.done = !t.done; saveTodos(todos); return sendJson(res, { success: true, data: t }) } + if (m === 'DELETE' && p === '/api/todos/completed/all') { todos = todos.filter(t => !t.done); saveTodos(todos); return sendJson(res, { success: true }) } + const del = p.match(/^\/api\/todos\/(\d+)$/); if (m === 'DELETE' && del) { const i = todos.findIndex(t => t.id === parseInt(del[1])); if (i === -1) return sendJson(res, { success: false }, 404); todos.splice(i, 1); saveTodos(todos); return sendJson(res, { success: true }) } + sendJson(res, { error: 'Not Found' }, 404); +}); +server.listen(PORT, '0.0.0.0', () => console.log('Todo on http://0.0.0.0:' + PORT)); + +function getPage() { + return `مهام + +

📝 قائمة المهام

Express + Node.js

+
0
الكل
0
نشط
0
مكتمل
+
+
الكل
نشط
مكتمل
+
+
+
📝 Express · Node.js · WebToApp
+`; +} diff --git a/app/src/main/assets/sample_projects/nodejs-express-en/package.json b/app/src/main/assets/sample_projects/nodejs-express-en/package.json new file mode 100644 index 0000000..c4c4bed --- /dev/null +++ b/app/src/main/assets/sample_projects/nodejs-express-en/package.json @@ -0,0 +1,10 @@ +{ + "name": "todo-app", + "version": "1.0.0", + "description": "Todo App - Zero dependency task management with Material Design UI", + "main": "server.js", + "scripts": { + "start": "node server.js" + }, + "dependencies": {} +} diff --git a/app/src/main/assets/sample_projects/nodejs-express-en/server.js b/app/src/main/assets/sample_projects/nodejs-express-en/server.js new file mode 100644 index 0000000..f8e5013 --- /dev/null +++ b/app/src/main/assets/sample_projects/nodejs-express-en/server.js @@ -0,0 +1,51 @@ + + + + +const http = require('http'); +const fs = require('fs'); +const path = require('path'); +const PORT = process.env.PORT || 3000; +const DATA_FILE = path.join(__dirname, 'todos.json'); + +const loadTodos = () => { + try { if (fs.existsSync(DATA_FILE)) return JSON.parse(fs.readFileSync(DATA_FILE, 'utf8')); } catch (e) { } + return [ + { id: 1, text: 'Welcome to Todo App 👋', done: false, createdAt: Date.now() }, + { id: 2, text: 'Click circle to complete ✓', done: true, createdAt: Date.now() - 1000 }, + { id: 3, text: 'Click × to delete task', done: false, createdAt: Date.now() - 2000 }, + { id: 4, text: 'Data persists locally', done: false, createdAt: Date.now() - 3000 } + ]; +}; +const saveTodos = (t) => fs.writeFileSync(DATA_FILE, JSON.stringify(t, null, 2)); +let todos = loadTodos(); let nextId = Math.max(...todos.map(t => t.id), 0) + 1; + +function parseBody(req) { return new Promise(r => { let b = ''; req.on('data', c => b += c); req.on('end', () => { try { r(JSON.parse(b)) } catch (e) { r({}) } }); }); } +function sendJson(res, data, s = 200) { res.writeHead(s, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify(data)); } + +const server = http.createServer(async (req, res) => { + const url = new URL(req.url, `http://${req.headers.host}`); + const p = url.pathname, m = req.method; + if (m === 'GET' && p === '/') { res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); return res.end(getPage()); } + if (m === 'GET' && p === '/api/todos') return sendJson(res, { success: true, data: todos }); + if (m === 'POST' && p === '/api/todos') { const { text } = await parseBody(req); if (!text?.trim()) return sendJson(res, { success: false }, 400); const t = { id: nextId++, text: text.trim(), done: false, createdAt: Date.now() }; todos.unshift(t); saveTodos(todos); return sendJson(res, { success: true, data: t }); } + const tog = p.match(/^\/api\/todos\/(\d+)\/toggle$/); if (m === 'PATCH' && tog) { const t = todos.find(x => x.id === parseInt(tog[1])); if (!t) return sendJson(res, { success: false }, 404); t.done = !t.done; saveTodos(todos); return sendJson(res, { success: true, data: t }) } + if (m === 'DELETE' && p === '/api/todos/completed/all') { todos = todos.filter(t => !t.done); saveTodos(todos); return sendJson(res, { success: true }) } + const del = p.match(/^\/api\/todos\/(\d+)$/); if (m === 'DELETE' && del) { const i = todos.findIndex(t => t.id === parseInt(del[1])); if (i === -1) return sendJson(res, { success: false }, 404); todos.splice(i, 1); saveTodos(todos); return sendJson(res, { success: true }) } + sendJson(res, { error: 'Not Found' }, 404); +}); +server.listen(PORT, '0.0.0.0', () => console.log('Todo on http://0.0.0.0:' + PORT)); + +function getPage() { + return ` +Todo + +

📝 Todo App

Express + Node.js

+
0
Total
0
Active
0
Done
+
+
All
Active
Done
+
+
+
📝 Express · Node.js · WebToApp
+`; +} diff --git a/app/src/main/assets/sample_projects/nodejs-express/package.json b/app/src/main/assets/sample_projects/nodejs-express/package.json new file mode 100644 index 0000000..225a367 --- /dev/null +++ b/app/src/main/assets/sample_projects/nodejs-express/package.json @@ -0,0 +1,12 @@ +{ + "name": "todo-app", + "version": "1.0.0", + "description": "待办事项应用 - 零依赖 Todo App,使用 Node.js 内置 http 模块", + "main": "server.js", + "scripts": { + "start": "node server.js" + }, + "dependencies": {}, + "keywords": ["todo", "nodejs", "zero-dependency"], + "author": "WebToApp" +} diff --git a/app/src/main/assets/sample_projects/nodejs-express/server.js b/app/src/main/assets/sample_projects/nodejs-express/server.js new file mode 100644 index 0000000..f671393 --- /dev/null +++ b/app/src/main/assets/sample_projects/nodejs-express/server.js @@ -0,0 +1,148 @@ + + + + +const http = require('http'); +const fs = require('fs'); +const path = require('path'); + +const PORT = process.env.PORT || 3000; +const DATA_FILE = path.join(__dirname, 'todos.json'); + +const loadTodos = () => { + try { if (fs.existsSync(DATA_FILE)) return JSON.parse(fs.readFileSync(DATA_FILE, 'utf8')); } catch (e) { } + return [ + { id: 1, text: '欢迎使用待办事项 👋', done: false, createdAt: Date.now() }, + { id: 2, text: '点击圆圈完成任务 ✓', done: true, createdAt: Date.now() - 1000 }, + { id: 3, text: '点击 × 删除任务', done: false, createdAt: Date.now() - 2000 }, + { id: 4, text: '支持数据持久化', done: false, createdAt: Date.now() - 3000 } + ]; +}; +const saveTodos = (todos) => fs.writeFileSync(DATA_FILE, JSON.stringify(todos, null, 2)); +let todos = loadTodos(); +let nextId = Math.max(...todos.map(t => t.id), 0) + 1; + +function parseBody(req) { + return new Promise((resolve) => { + let body = ''; + req.on('data', chunk => body += chunk); + req.on('end', () => { try { resolve(JSON.parse(body)); } catch (e) { resolve({}); } }); + }); +} + +function sendJson(res, data, status = 200) { + res.writeHead(status, { 'Content-Type': 'application/json; charset=utf-8' }); + res.end(JSON.stringify(data)); +} + +const server = http.createServer(async (req, res) => { + const url = new URL(req.url, `http://${req.headers.host}`); + const p = url.pathname, m = req.method; + + if (m === 'GET' && p === '/') { + res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); + return res.end(getPage()); + } + if (m === 'GET' && p === '/api/todos') return sendJson(res, { success: true, data: todos }); + if (m === 'POST' && p === '/api/todos') { + const { text } = await parseBody(req); + if (!text?.trim()) return sendJson(res, { success: false }, 400); + const todo = { id: nextId++, text: text.trim(), done: false, createdAt: Date.now() }; + todos.unshift(todo); saveTodos(todos); + return sendJson(res, { success: true, data: todo }); + } + const tog = p.match(/^\/api\/todos\/(\d+)\/toggle$/); + if (m === 'PATCH' && tog) { + const todo = todos.find(t => t.id === parseInt(tog[1])); + if (!todo) return sendJson(res, { success: false }, 404); + todo.done = !todo.done; saveTodos(todos); + return sendJson(res, { success: true, data: todo }); + } + if (m === 'DELETE' && p === '/api/todos/completed/all') { + todos = todos.filter(t => !t.done); saveTodos(todos); + return sendJson(res, { success: true }); + } + const del = p.match(/^\/api\/todos\/(\d+)$/); + if (m === 'DELETE' && del) { + const i = todos.findIndex(t => t.id === parseInt(del[1])); + if (i === -1) return sendJson(res, { success: false }, 404); + todos.splice(i, 1); saveTodos(todos); + return sendJson(res, { success: true }); + } + sendJson(res, { error: 'Not Found' }, 404); +}); + +server.listen(PORT, '0.0.0.0', () => console.log(`✅ Todo on http://0.0.0.0:${PORT}`)); + +function getPage() { + return ` +待办事项 + +
+

📝 待办事项

Express + Node.js 驱动

+
0
全部
0
待办
0
完成
+
+
全部
待办
已完成
+
+
+
📝 Express · Node.js · WebToApp
+
+`; +} diff --git a/app/src/main/assets/sample_projects/nodejs-fastify-ar/package.json b/app/src/main/assets/sample_projects/nodejs-fastify-ar/package.json new file mode 100644 index 0000000..ac82bb7 --- /dev/null +++ b/app/src/main/assets/sample_projects/nodejs-fastify-ar/package.json @@ -0,0 +1,7 @@ +{ + "name": "system-dashboard", + "version": "1.0.0", + "main": "server.js", + "scripts": { "start": "node server.js" }, + "dependencies": {} +} diff --git a/app/src/main/assets/sample_projects/nodejs-fastify-ar/server.js b/app/src/main/assets/sample_projects/nodejs-fastify-ar/server.js new file mode 100644 index 0000000..d355549 --- /dev/null +++ b/app/src/main/assets/sample_projects/nodejs-fastify-ar/server.js @@ -0,0 +1,29 @@ + + + + +const http = require('http'); +const os = require('os'); +const PORT = process.env.PORT || 3000; +const stats = { requestCount: 0, startTime: Date.now() }; +function getStats() { stats.requestCount++; const cpus = os.cpus(); const cu = cpus.map(c => { const t = Object.values(c.times).reduce((a, b) => a + b, 0); return Math.round((1 - c.times.idle / t) * 100) }); const avg = Math.round(cu.reduce((a, b) => a + b, 0) / cu.length); const tm = os.totalmem(), fm = os.freemem(), um = tm - fm, mp = Math.round(um / tm * 100); const p = process.memoryUsage(); return { cpu: { cores: cpus.length, usage: avg, perCore: cu }, memory: { total: fB(tm), used: fB(um), free: fB(fm), percent: mp }, process: { heap: fB(p.heapUsed), rss: fB(p.rss), uptime: fT(process.uptime()) }, server: { requests: stats.requestCount, uptime: fT((Date.now() - stats.startTime) / 1000) }, system: { platform: os.platform(), arch: os.arch(), node: process.version } } } +function fB(b) { if (b < 1048576) return (b / 1024).toFixed(0) + ' KB'; if (b < 1073741824) return (b / 1048576).toFixed(1) + ' MB'; return (b / 1073741824).toFixed(2) + ' GB' } +function fT(s) { const m = Math.floor(s / 60), h = Math.floor(m / 60); if (h > 0) return h + 'س ' + m % 60 + 'د'; if (m > 0) return m + 'د ' + Math.floor(s % 60) + 'ث'; return Math.floor(s) + 'ث' } +const server = http.createServer((req, res) => { + const p = new URL(req.url, `http://${req.headers.host}`).pathname; + if (p === '/api/stats') { res.writeHead(200, { 'Content-Type': 'application/json' }); return res.end(JSON.stringify(getStats())) } + if (p === '/') { res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); return res.end(getPage()) } + res.writeHead(404); res.end('Not Found'); +}); +server.listen(PORT, '0.0.0.0', () => console.log('Monitor on ' + PORT)); + +function getPage() { + return `مراقبة النظام + +

⚡ مراقبة النظام

Fastify عالي الأداء

مباشر
+
💻 المعالج-
--%
🧠 الذاكرة-
--%
مستخدم
-
متاح
-
+
🚀 الخادم● يعمل
التشغيل
-
الطلبات
-
Heap
-
RSS
-
+
📊 النظاممعلومات
المنصة
-
الهندسة
-
Node.js
-
PID
${process.pid}
+
⚡ Fastify · Node.js · WebToApp
+`; +} diff --git a/app/src/main/assets/sample_projects/nodejs-fastify-en/package.json b/app/src/main/assets/sample_projects/nodejs-fastify-en/package.json new file mode 100644 index 0000000..0011324 --- /dev/null +++ b/app/src/main/assets/sample_projects/nodejs-fastify-en/package.json @@ -0,0 +1,10 @@ +{ + "name": "system-dashboard", + "version": "1.0.0", + "description": "System Monitor Dashboard - Zero dependency, uses Node.js built-in http module", + "main": "server.js", + "scripts": { + "start": "node server.js" + }, + "dependencies": {} +} diff --git a/app/src/main/assets/sample_projects/nodejs-fastify-en/server.js b/app/src/main/assets/sample_projects/nodejs-fastify-en/server.js new file mode 100644 index 0000000..0010d76 --- /dev/null +++ b/app/src/main/assets/sample_projects/nodejs-fastify-en/server.js @@ -0,0 +1,40 @@ + + + + +const http = require('http'); +const os = require('os'); +const PORT = process.env.PORT || 3000; +const stats = { requestCount: 0, startTime: Date.now() }; + +function getStats() { + stats.requestCount++; + const cpus = os.cpus(); + const cpuUsage = cpus.map(cpu => { const t = Object.values(cpu.times).reduce((a, b) => a + b, 0); return Math.round((1 - cpu.times.idle / t) * 100); }); + const avgCpu = Math.round(cpuUsage.reduce((a, b) => a + b, 0) / cpuUsage.length); + const totalMem = os.totalmem(), freeMem = os.freemem(), usedMem = totalMem - freeMem, memPct = Math.round(usedMem / totalMem * 100); + const proc = process.memoryUsage(); + return { cpu: { cores: cpus.length, usage: avgCpu, perCore: cpuUsage }, memory: { total: fmtB(totalMem), used: fmtB(usedMem), free: fmtB(freeMem), percent: memPct }, process: { heap: fmtB(proc.heapUsed), rss: fmtB(proc.rss), uptime: fmtT(process.uptime()) }, server: { requests: stats.requestCount, uptime: fmtT((Date.now() - stats.startTime) / 1000) }, system: { platform: os.platform(), arch: os.arch(), node: process.version } }; +} +function fmtB(b) { if (b < 1024 * 1024) return (b / 1024).toFixed(0) + ' KB'; if (b < 1024 * 1024 * 1024) return (b / 1024 / 1024).toFixed(1) + ' MB'; return (b / 1024 / 1024 / 1024).toFixed(2) + ' GB' } +function fmtT(s) { const m = Math.floor(s / 60), h = Math.floor(m / 60); if (h > 0) return h + 'h ' + m % 60 + 'm'; if (m > 0) return m + 'm ' + Math.floor(s % 60) + 's'; return Math.floor(s) + 's' } + +const server = http.createServer((req, res) => { + const p = new URL(req.url, `http://${req.headers.host}`).pathname; + if (p === '/api/stats') { res.writeHead(200, { 'Content-Type': 'application/json' }); return res.end(JSON.stringify(getStats())) } + if (p === '/') { res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); return res.end(getPage()) } + res.writeHead(404); res.end('Not Found'); +}); +server.listen(PORT, '0.0.0.0', () => console.log('Monitor on http://0.0.0.0:' + PORT)); + +function getPage() { + return ` +System Monitor + +

⚡ System Monitor

Fastify High-Performance

Live
+
💻 CPU-
--%
🧠 Memory-
--%
Used
-
Free
-
+
🚀 Server● Running
Uptime
-
Requests
-
Heap
-
RSS
-
+
📊 SystemInfo
Platform
-
Arch
-
Node.js
-
PID
${process.pid}
+
⚡ Fastify · Node.js · WebToApp
+`; +} diff --git a/app/src/main/assets/sample_projects/nodejs-fastify/package.json b/app/src/main/assets/sample_projects/nodejs-fastify/package.json new file mode 100644 index 0000000..0618ea7 --- /dev/null +++ b/app/src/main/assets/sample_projects/nodejs-fastify/package.json @@ -0,0 +1,12 @@ +{ + "name": "system-dashboard", + "version": "1.0.0", + "description": "实时系统监控仪表盘 - 零依赖,使用 Node.js 内置 http 模块", + "main": "server.js", + "scripts": { + "start": "node server.js" + }, + "dependencies": {}, + "keywords": ["dashboard", "monitor", "nodejs", "zero-dependency"], + "author": "WebToApp" +} diff --git a/app/src/main/assets/sample_projects/nodejs-fastify/server.js b/app/src/main/assets/sample_projects/nodejs-fastify/server.js new file mode 100644 index 0000000..d561148 --- /dev/null +++ b/app/src/main/assets/sample_projects/nodejs-fastify/server.js @@ -0,0 +1,113 @@ + + + + +const http = require('http'); +const os = require('os'); +const PORT = process.env.PORT || 3000; +const stats = { requestCount: 0, startTime: Date.now() }; + +function getStats() { + stats.requestCount++; + const cpus = os.cpus(); + const cpuUsage = cpus.map(cpu => { + const total = Object.values(cpu.times).reduce((a, b) => a + b, 0); + return Math.round((1 - cpu.times.idle / total) * 100); + }); + const avgCpu = Math.round(cpuUsage.reduce((a, b) => a + b, 0) / cpuUsage.length); + const totalMem = os.totalmem(), freeMem = os.freemem(), usedMem = totalMem - freeMem; + const memPct = Math.round((usedMem / totalMem) * 100); + const proc = process.memoryUsage(); + return { + cpu: { cores: cpus.length, usage: avgCpu, perCore: cpuUsage }, + memory: { total: fmtB(totalMem), used: fmtB(usedMem), free: fmtB(freeMem), percent: memPct }, + process: { heap: fmtB(proc.heapUsed), rss: fmtB(proc.rss), uptime: fmtT(process.uptime()) }, + server: { requests: stats.requestCount, uptime: fmtT((Date.now() - stats.startTime) / 1000) }, + system: { platform: os.platform(), arch: os.arch(), node: process.version } + }; +} + +function fmtB(b) { if (b < 1024 * 1024) return (b / 1024).toFixed(0) + ' KB'; if (b < 1024 * 1024 * 1024) return (b / 1024 / 1024).toFixed(1) + ' MB'; return (b / 1024 / 1024 / 1024).toFixed(2) + ' GB'; } +function fmtT(s) { const m = Math.floor(s / 60), h = Math.floor(m / 60); if (h > 0) return h + '时' + m % 60 + '分'; if (m > 0) return m + '分' + Math.floor(s % 60) + '秒'; return Math.floor(s) + '秒'; } + +const server = http.createServer((req, res) => { + const p = new URL(req.url, `http://${req.headers.host}`).pathname; + if (p === '/api/stats') { res.writeHead(200, { 'Content-Type': 'application/json' }); return res.end(JSON.stringify(getStats())); } + if (p === '/') { res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); return res.end(getPage()); } + res.writeHead(404); res.end('Not Found'); +}); +server.listen(PORT, '0.0.0.0', () => console.log(`⚡ Monitor on http://0.0.0.0:${PORT}`)); + +function getPage() { + return ` +系统监控 + +
+

⚡ 系统监控

Fastify 高性能服务

实时更新
+
+
💻 CPU-
--%
+
🧠 内存-
--%
已用
-
可用
-
+
+
🚀 服务器● 运行中
运行时间
-
请求数
-
堆内存
-
RSS
-
+
📊 系统信息
平台
-
架构
-
Node.js
-
PID
${process.pid}
+
⚡ Fastify · Node.js · WebToApp
+
+`; +} diff --git a/app/src/main/assets/sample_projects/nodejs-koa-ar/package.json b/app/src/main/assets/sample_projects/nodejs-koa-ar/package.json new file mode 100644 index 0000000..24a3d84 --- /dev/null +++ b/app/src/main/assets/sample_projects/nodejs-koa-ar/package.json @@ -0,0 +1,7 @@ +{ + "name": "notes-app", + "version": "1.0.0", + "main": "server.js", + "scripts": { "start": "node server.js" }, + "dependencies": {} +} diff --git a/app/src/main/assets/sample_projects/nodejs-koa-ar/server.js b/app/src/main/assets/sample_projects/nodejs-koa-ar/server.js new file mode 100644 index 0000000..97fd9bc --- /dev/null +++ b/app/src/main/assets/sample_projects/nodejs-koa-ar/server.js @@ -0,0 +1,34 @@ + + + + +const http = require('http'); const fs = require('fs'); const path = require('path'); +const PORT = process.env.PORT || 3000; const DATA_FILE = path.join(__dirname, 'notes.json'); +const loadNotes = () => { try { if (fs.existsSync(DATA_FILE)) return JSON.parse(fs.readFileSync(DATA_FILE, 'utf8')); } catch (e) { } return [{ id: 1, title: 'مرحباً بتطبيق الملاحظات', content: '# مرحباً\n\nهذا تطبيق ملاحظات يدعم **Markdown**.\n\n## الميزات\n- إنشاء وتعديل\n- معاينة Markdown\n- بحث\n- حفظ محلي', createdAt: Date.now(), updatedAt: Date.now() }, { id: 2, title: 'صياغة Markdown', content: '# Markdown\n\n## التأكيد\n- **غامق**: `**نص**`\n- *مائل*: `*نص*`\n\n## القوائم\n- استخدم - للنقاط\n1. أرقام للترتيب', createdAt: Date.now() - 3600000, updatedAt: Date.now() - 3600000 }]; }; +const saveNotes = n => fs.writeFileSync(DATA_FILE, JSON.stringify(n, null, 2)); +let notes = loadNotes(), nextId = Math.max(...notes.map(n => n.id), 0) + 1; +function parseBody(req) { return new Promise(r => { let b = ''; req.on('data', c => b += c); req.on('end', () => { try { r(JSON.parse(b)) } catch (e) { r({}) } }) }) } +function sendJson(res, data, s = 200) { res.writeHead(s, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify(data)) } +const server = http.createServer(async (req, res) => { + const url = new URL(req.url, `http://${req.headers.host}`); + if (m === 'GET' && p === '/') { res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); return res.end(getPage()) } + if (m === 'GET' && p === '/api/notes') { const q = url.searchParams.get('q'); let r = notes; if (q) { const ql = q.toLowerCase(); r = notes.filter(n => n.title.toLowerCase().includes(ql) || n.content.toLowerCase().includes(ql)) } return sendJson(res, { success: true, data: r.map(n => ({ ...n, preview: n.content.substring(0, 80) })) }) } + if (m === 'POST' && p === '/api/notes') { const { title, content } = await parseBody(req); const n = { id: nextId++, title: title || 'بدون عنوان', content: content || '', createdAt: Date.now(), updatedAt: Date.now() }; notes.unshift(n); saveNotes(notes); return sendJson(res, { success: true, data: n }) } + const nm = p.match(/^\/api\/notes\/(\d+)$/); + if (m === 'GET' && nm) { const n = notes.find(x => x.id === parseInt(nm[1])); return n ? sendJson(res, { success: true, data: n }) : sendJson(res, { success: false }, 404) } + if (m === 'PUT' && nm) { const n = notes.find(x => x.id === parseInt(nm[1])); if (!n) return sendJson(res, { success: false }, 404); const { title, content } = await parseBody(req); if (title !== undefined) n.title = title; if (content !== undefined) n.content = content; n.updatedAt = Date.now(); saveNotes(notes); return sendJson(res, { success: true, data: n }) } + if (m === 'DELETE' && nm) { const i = notes.findIndex(x => x.id === parseInt(nm[1])); if (i === -1) return sendJson(res, { success: false }, 404); notes.splice(i, 1); saveNotes(notes); return sendJson(res, { success: true }) } + sendJson(res, { error: 'Not Found' }, 404) +}); +server.listen(PORT, '0.0.0.0', () => console.log('Notes on ' + PORT)); + +function getPage() { + return `ملاحظات + +

📝 ملاحظات Markdown

Koa · Node.js

+ +
تحرير
معاينة
+
+
📝 Koa · Node.js · WebToApp
+`; +} diff --git a/app/src/main/assets/sample_projects/nodejs-koa-en/package.json b/app/src/main/assets/sample_projects/nodejs-koa-en/package.json new file mode 100644 index 0000000..964029a --- /dev/null +++ b/app/src/main/assets/sample_projects/nodejs-koa-en/package.json @@ -0,0 +1,10 @@ +{ + "name": "notes-app", + "version": "1.0.0", + "description": "Markdown Notes App - Zero dependency, uses Node.js built-in http module", + "main": "server.js", + "scripts": { + "start": "node server.js" + }, + "dependencies": {} +} diff --git a/app/src/main/assets/sample_projects/nodejs-koa-en/server.js b/app/src/main/assets/sample_projects/nodejs-koa-en/server.js new file mode 100644 index 0000000..ae14a1e --- /dev/null +++ b/app/src/main/assets/sample_projects/nodejs-koa-en/server.js @@ -0,0 +1,38 @@ + + + + +const http = require('http'); +const fs = require('fs'); +const path = require('path'); +const PORT = process.env.PORT || 3000; +const DATA_FILE = path.join(__dirname, 'notes.json'); +const loadNotes = () => { try { if (fs.existsSync(DATA_FILE)) return JSON.parse(fs.readFileSync(DATA_FILE, 'utf8')); } catch (e) { } return [{ id: 1, title: 'Welcome to Notes', content: '# Welcome\n\nThis is a **Markdown** notes app.\n\n## Features\n- Create & edit notes\n- Markdown preview\n- Search\n- Local persistence', createdAt: Date.now(), updatedAt: Date.now() }, { id: 2, title: 'Markdown Syntax', content: '# Markdown\n\n## Emphasis\n- **Bold**: `**text**`\n- *Italic*: `*text*`\n\n## Lists\n- Use - for bullets\n1. Use numbers for ordered\n\n## Code\n`inline code`', createdAt: Date.now() - 3600000, updatedAt: Date.now() - 3600000 }]; }; +const saveNotes = n => fs.writeFileSync(DATA_FILE, JSON.stringify(n, null, 2)); +let notes = loadNotes(), nextId = Math.max(...notes.map(n => n.id), 0) + 1; +function parseBody(req) { return new Promise(r => { let b = ''; req.on('data', c => b += c); req.on('end', () => { try { r(JSON.parse(b)) } catch (e) { r({}) } }) }) } +function sendJson(res, data, s = 200) { res.writeHead(s, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify(data)) } +const server = http.createServer(async (req, res) => { + const url = new URL(req.url, `http://${req.headers.host}`); + if (m === 'GET' && p === '/') { res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); return res.end(getPage()) } + if (m === 'GET' && p === '/api/notes') { const q = url.searchParams.get('q'); let r = notes; if (q) { const ql = q.toLowerCase(); r = notes.filter(n => n.title.toLowerCase().includes(ql) || n.content.toLowerCase().includes(ql)) } return sendJson(res, { success: true, data: r.map(n => ({ ...n, preview: n.content.substring(0, 80) })) }) } + if (m === 'POST' && p === '/api/notes') { const { title, content } = await parseBody(req); const n = { id: nextId++, title: title || 'Untitled', content: content || '', createdAt: Date.now(), updatedAt: Date.now() }; notes.unshift(n); saveNotes(notes); return sendJson(res, { success: true, data: n }) } + const nm = p.match(/^\/api\/notes\/(\d+)$/); + if (m === 'GET' && nm) { const n = notes.find(x => x.id === parseInt(nm[1])); return n ? sendJson(res, { success: true, data: n }) : sendJson(res, { success: false }, 404) } + if (m === 'PUT' && nm) { const n = notes.find(x => x.id === parseInt(nm[1])); if (!n) return sendJson(res, { success: false }, 404); const { title, content } = await parseBody(req); if (title !== undefined) n.title = title; if (content !== undefined) n.content = content; n.updatedAt = Date.now(); saveNotes(notes); return sendJson(res, { success: true, data: n }) } + if (m === 'DELETE' && nm) { const i = notes.findIndex(x => x.id === parseInt(nm[1])); if (i === -1) return sendJson(res, { success: false }, 404); notes.splice(i, 1); saveNotes(notes); return sendJson(res, { success: true }) } + sendJson(res, { error: 'Not Found' }, 404) +}); +server.listen(PORT, '0.0.0.0', () => console.log('Notes on ' + PORT)); + +function getPage() { + return ` +Notes + +

📝 Markdown Notes

Koa · Node.js

+ +
Edit
Preview
+
+
📝 Koa · Node.js · WebToApp
+`; +} diff --git a/app/src/main/assets/sample_projects/nodejs-koa/package.json b/app/src/main/assets/sample_projects/nodejs-koa/package.json new file mode 100644 index 0000000..0b65810 --- /dev/null +++ b/app/src/main/assets/sample_projects/nodejs-koa/package.json @@ -0,0 +1,12 @@ +{ + "name": "notes-app", + "version": "1.0.0", + "description": "Markdown 笔记应用 - 零依赖,使用 Node.js 内置 http 模块", + "main": "server.js", + "scripts": { + "start": "node server.js" + }, + "dependencies": {}, + "keywords": ["notes", "markdown", "nodejs", "zero-dependency"], + "author": "WebToApp" +} diff --git a/app/src/main/assets/sample_projects/nodejs-koa/server.js b/app/src/main/assets/sample_projects/nodejs-koa/server.js new file mode 100644 index 0000000..3b4e231 --- /dev/null +++ b/app/src/main/assets/sample_projects/nodejs-koa/server.js @@ -0,0 +1,134 @@ + + + + +const http = require('http'); +const fs = require('fs'); +const path = require('path'); +const PORT = process.env.PORT || 3000; +const DATA_FILE = path.join(__dirname, 'notes.json'); + +const loadNotes = () => { + try { if (fs.existsSync(DATA_FILE)) return JSON.parse(fs.readFileSync(DATA_FILE, 'utf8')); } catch (e) { } + return [ + { id: 1, title: '欢迎使用笔记应用', content: '# 欢迎\n\n这是一个支持 **Markdown** 的笔记应用。\n\n## 功能\n- 创建和编辑笔记\n- Markdown 预览\n- 搜索笔记\n- 本地持久化', createdAt: Date.now(), updatedAt: Date.now() }, + { id: 2, title: 'Markdown 语法', content: '# Markdown\n\n## 强调\n- **粗体**: `**文字**`\n- *斜体*: `*文字*`\n\n## 列表\n- 无序列表用 -\n1. 有序列表用数字\n\n## 代码\n`code`', createdAt: Date.now() - 3600000, updatedAt: Date.now() - 3600000 } + ]; +}; +const saveNotes = (notes) => fs.writeFileSync(DATA_FILE, JSON.stringify(notes, null, 2)); +let notes = loadNotes(); +let nextId = Math.max(...notes.map(n => n.id), 0) + 1; + +function parseBody(req) { return new Promise(r => { let b = ''; req.on('data', c => b += c); req.on('end', () => { try { r(JSON.parse(b)) } catch (e) { r({}) } }); }); } +function sendJson(res, data, s = 200) { res.writeHead(s, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify(data)); } + +const server = http.createServer(async (req, res) => { + const url = new URL(req.url, `http://${req.headers.host}`); + const p = url.pathname, m = req.method; + + if (m === 'GET' && p === '/') { res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); return res.end(getPage()); } + if (m === 'GET' && p === '/api/notes') { + const q = url.searchParams.get('q'); + let result = notes; + if (q) { const ql = q.toLowerCase(); result = notes.filter(n => n.title.toLowerCase().includes(ql) || n.content.toLowerCase().includes(ql)); } + return sendJson(res, { success: true, data: result.map(n => ({ ...n, preview: n.content.substring(0, 80) })) }); + } + if (m === 'POST' && p === '/api/notes') { + const { title, content } = await parseBody(req); + const note = { id: nextId++, title: title || '无标题', content: content || '', createdAt: Date.now(), updatedAt: Date.now() }; + notes.unshift(note); saveNotes(notes); + return sendJson(res, { success: true, data: note }); + } + const nm = p.match(/^\/api\/notes\/(\d+)$/); + if (m === 'GET' && nm) { const n = notes.find(x => x.id === parseInt(nm[1])); return n ? sendJson(res, { success: true, data: n }) : sendJson(res, { success: false }, 404); } + if (m === 'PUT' && nm) { + const n = notes.find(x => x.id === parseInt(nm[1])); + if (!n) return sendJson(res, { success: false }, 404); + const { title, content } = await parseBody(req); + if (title !== undefined) n.title = title; if (content !== undefined) n.content = content; n.updatedAt = Date.now(); + saveNotes(notes); return sendJson(res, { success: true, data: n }); + } + if (m === 'DELETE' && nm) { + const i = notes.findIndex(x => x.id === parseInt(nm[1])); + if (i === -1) return sendJson(res, { success: false }, 404); + notes.splice(i, 1); saveNotes(notes); return sendJson(res, { success: true }); + } + sendJson(res, { error: 'Not Found' }, 404); +}); +server.listen(PORT, '0.0.0.0', () => console.log('Notes on http://0.0.0.0:' + PORT)); + +function getPage() { + return ` +Markdown 笔记 + +
+

📝 Markdown 笔记

Koa · Node.js 驱动

+ +
+ +
编辑
预览
+ +
+
+
+
+
📝 Koa · Node.js · WebToApp
+
+`; +} diff --git a/app/src/main/assets/sample_projects/php-laravel-ar/composer.json b/app/src/main/assets/sample_projects/php-laravel-ar/composer.json new file mode 100644 index 0000000..b3063e8 --- /dev/null +++ b/app/src/main/assets/sample_projects/php-laravel-ar/composer.json @@ -0,0 +1,13 @@ +{ + "name": "demo/laravel-blog", + "description": "عرض مدونة Laravel", + "require": { + "php": "^8.1", + "laravel/framework": "^10.0", + "laravel/sanctum": "^3.3" + }, + "require-dev": { + "phpunit/phpunit": "^10.1" + }, + "autoload": { "psr-4": { "App\\": "app/" } } +} diff --git a/app/src/main/assets/sample_projects/php-laravel-ar/public/index.php b/app/src/main/assets/sample_projects/php-laravel-ar/public/index.php new file mode 100644 index 0000000..43ec5bb --- /dev/null +++ b/app/src/main/assets/sample_projects/php-laravel-ar/public/index.php @@ -0,0 +1,321 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $pdo->exec(' + CREATE TABLE IF NOT EXISTS posts ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + title TEXT NOT NULL, + excerpt TEXT, + content TEXT NOT NULL, + category TEXT DEFAULT "PHP", + created_at DATETIME DEFAULT CURRENT_TIMESTAMP + ) + '); + if ($pdo->query('SELECT COUNT(*) FROM posts')->fetchColumn() == 0) { + seedData($pdo); + } +} catch (Exception $e) { + $pdo = null; +} + +// ==================== 路由调度 ==================== +$routes = include $basePath . '/routes/web.php'; +$handler = null; +$params = []; + +foreach ($routes as [$rMethod, $rPath, $rHandler]) { + if ($method !== $rMethod) continue; + $pattern = preg_replace('/\{(\w+)\}/', '(?P<$1>[^/]+)', $rPath); + if (preg_match('#^' . $pattern . '$#', $uri, $m)) { + $handler = $rHandler; + $params = array_filter($m, 'is_string', ARRAY_FILTER_USE_KEY); + break; + } +} + +if (!$handler) $handler = 'notFound'; + +// ==================== 控制器 ==================== +$html = ''; +switch ($handler) { + case 'home': + $cat = $_GET['cat'] ?? ''; + $posts = getAllPosts($pdo, $cat); + $cats = getCategories($pdo); + $html = renderHome($posts, $cats, $cat); + break; + case 'show': + $post = getPost($pdo, (int)$params['id']); + $html = $post ? renderShow($post) : renderNotFound(); + break; + case 'create': + $html = renderCreate(); + break; + case 'store': + $title = trim($_POST['title'] ?? ''); + $excerpt = trim($_POST['excerpt'] ?? ''); + $content = trim($_POST['content'] ?? ''); + $category = trim($_POST['category'] ?? 'PHP'); + if ($title && $content && $pdo) { + $stmt = $pdo->prepare('INSERT INTO posts (title,excerpt,content,category) VALUES (?,?,?,?)'); + $stmt->execute([$title, $excerpt ?: mb_substr(strip_tags($content), 0, 120) . '...', $content, $category]); + } + header('Location: /'); + exit; + case 'delete': + if ($pdo) { + $pdo->prepare('DELETE FROM posts WHERE id=?')->execute([(int)$params['id']]); + } + header('Location: /'); + exit; + case 'apiPosts': + header('Content-Type: application/json; charset=utf-8'); + echo json_encode(['posts' => getAllPosts($pdo), 'total' => count(getAllPosts($pdo))], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + exit; + default: + http_response_code(404); + $html = renderNotFound(); +} + +echo renderLayout($html); +exit; + +// ==================== 数据层 ==================== +function seedData(PDO $pdo): void { + $posts = [ + ['PHP 8.4 新特性:属性钩子与不对称可见性', + 'PHP 8.4 引入了属性钩子和不对称可见性,让面向对象编程更加优雅。', + "PHP 8.4 是一次重要的语言更新。\n\n## 属性钩子 (Property Hooks)\n\n属性钩子允许你直接在属性声明中定义 getter 和 setter 逻辑:\n\n```php\nclass User {\n public string \$fullName {\n get => \$this->firstName . ' ' . \$this->lastName;\n set(string \$value) {\n [\$this->firstName, \$this->lastName] = explode(' ', \$value, 2);\n }\n }\n}\n```\n\n## 不对称可见性\n\n现在可以设置属性的读取和写入拥有不同的可见性:\n\n```php\nclass Config {\n public private(set) string \$apiKey;\n}\n```\n\n这些特性让 PHP 的封装性更上一层楼。", 'PHP'], + ['在 Android 设备上运行 PHP 服务器', + '探索如何在 Android 设备上本地运行完整的 PHP HTTP 服务器。', + "你正在看的这个博客,正是运行在你的 Android 设备上的 PHP 服务器!\n\n## 技术栈\n\n- **PHP " . phpversion() . "** (CLI SAPI)\n- **SQLite3** 内嵌式数据库\n- **自定义 HTTP 服务器** (stream_socket_server)\n- **pcntl_fork** 多进程并发\n\n## 工作原理\n\n1. PHP 二进制以 CLI 模式启动\n2. 自定义路由服务器监听 HTTP 端口\n3. 每个请求 fork 子进程处理\n4. 通过 include 执行 PHP 文件\n5. WebView 加载本地 HTTP 服务器地址\n\n这意味着所有处理都在设备本地完成,无需网络连接。", '技术'], + ['从零构建 PHP MVC 框架', + '理解 MVC 架构的核心原理,动手实现一个微型框架。', + "本博客本身就是一个微型 MVC 框架的实例!\n\n## 核心组件\n\n### 1. 路由器 (Router)\n将 URL 映射到处理器函数,支持参数提取:\n```\nGET /post/{id} -> show($id)\n```\n\n### 2. 控制器 (Controller)\n接收请求,调用模型获取数据,渲染视图。\n\n### 3. 模型 (Model)\n封装数据库操作,提供 CRUD 方法。\n\n### 4. 视图 (View)\n将数据渲染为 HTML,支持布局继承。\n\n## 目录结构\n```\npublic/index.php ← 前端控制器\nroutes/web.php ← 路由定义\nstorage/blog.sqlite ← 数据库\n```\n\n麻雀虽小五脏俱全,这就是 MVC 的精髓。", '架构'], + ['SQLite:移动开发的最佳数据库', + 'SQLite 无需服务器、零配置,完美适合移动和嵌入式场景。', + "SQLite 是全球部署最广泛的数据库引擎。\n\n## 为什么选择 SQLite\n\n- **零配置**: 无需安装数据库服务器\n- **单文件**: 整个数据库就是一个文件\n- **高性能**: 对于读多写少的场景极快\n- **跨平台**: 支持所有主流操作系统\n\n## 在 PHP 中使用\n\n```php\n\$pdo = new PDO('sqlite:blog.db');\n\$pdo->exec('CREATE TABLE posts (...)');\n\$stmt = \$pdo->prepare('SELECT * FROM posts WHERE id = ?');\n\$stmt->execute([1]);\n\$post = \$stmt->fetch(PDO::FETCH_ASSOC);\n```\n\n本博客的所有数据就存储在 SQLite 中!", '数据库'], + ['现代 PHP 开发最佳实践', + '从类型安全到架构设计,提升 PHP 代码质量的实用指南。', + "现代 PHP 已经不是你印象中的那个 PHP 了。\n\n## 1. 严格类型\n```php\ndeclare(strict_types=1);\nfunction add(int \$a, int \$b): int {\n return \$a + \$b;\n}\n```\n\n## 2. 枚举类型\n```php\nenum Status: string {\n case Active = 'active';\n case Inactive = 'inactive';\n}\n```\n\n## 3. 只读属性\n```php\nclass User {\n public function __construct(\n public readonly string \$name,\n public readonly string \$email,\n ) {}\n}\n```\n\n## 4. 箭头函数\n```php\n\$doubled = array_map(fn(\$n) => \$n * 2, [1, 2, 3]);\n```\n\n现代 PHP 简洁、高效、类型安全。", 'PHP'], + ]; + $stmt = $pdo->prepare('INSERT INTO posts (title, excerpt, content, category) VALUES (?, ?, ?, ?)'); + foreach ($posts as $p) $stmt->execute($p); +} + +function getAllPosts(?PDO $pdo, string $category = ''): array { + if (!$pdo) return []; + $sql = 'SELECT * FROM posts'; + if ($category) { + $stmt = $pdo->prepare($sql . ' WHERE category=? ORDER BY id DESC'); + $stmt->execute([$category]); + } else { + $stmt = $pdo->query($sql . ' ORDER BY id DESC'); + } + return $stmt->fetchAll(PDO::FETCH_ASSOC); +} + +function getPost(?PDO $pdo, int $id): ?array { + if (!$pdo) return null; + $stmt = $pdo->prepare('SELECT * FROM posts WHERE id=?'); + $stmt->execute([$id]); + return $stmt->fetch(PDO::FETCH_ASSOC) ?: null; +} + +function getCategories(?PDO $pdo): array { + if (!$pdo) return []; + return $pdo->query('SELECT DISTINCT category FROM posts ORDER BY category')->fetchAll(PDO::FETCH_COLUMN); +} + +// ==================== Markdown 简易渲染 ==================== +function renderMarkdown(string $text): string { + $text = htmlspecialchars($text); + $text = preg_replace('/```(\w*)\n(.*?)```/s', '
$2
', $text); + $text = preg_replace('/`([^`]+)`/', '$1', $text); + $text = preg_replace('/^## (.+)$/m', '

$1

', $text); + $text = preg_replace('/^### (.+)$/m', '

$1

', $text); + $text = preg_replace('/\*\*(.+?)\*\*/', '$1', $text); + $text = preg_replace('/^- (.+)$/m', '
  • $1
  • ', $text); + $text = preg_replace('/(
  • .*<\/li>)/s', '
      $1
    ', $text); + $text = preg_replace('/\n{2,}/', '

    ', $text); + return '

    ' . $text . '

    '; +} + +// ==================== 视图 ==================== +function renderHome(array $posts, array $cats, string $activeCat): string { + $postCards = ''; + foreach ($posts as $p) { + $date = date('YY-m-d', strtotime($p['created_at'])); + $postCards .= ' + '; + } + + $catLinks = 'الكل'; + foreach ($cats as $c) { + $catLinks .= '' . h($c) . ''; + } + + $count = count($posts); + return ' +
    +

    📝 مدونة Laravel

    +

    مدونة MVC مصغرة بلغة PHP — تعمل على جهاز Android

    +
    + 📚 ' . $count . ' مقالات + ⚡ PHP ' . phpversion() . ' + 🗄 SQLite ' . (class_exists("SQLite3") ? SQLite3::version()['versionString'] : 'N/A') . ' +
    +
    +
    +
    ' . $catLinks . '
    + ➕ مقال جديد +
    +
    ' . ($postCards ?: '

    لا توجد مقالات.اكتب الأول吧!

    ') . '
    '; +} + +function renderShow(array $post): string { + $date = date('YY-m-d H:i', strtotime($post['created_at'])); + $content = renderMarkdown($post['content']); + return ' +
    + ← الرجوع + ' . h($post['category']) . ' +
    +
    +

    ' . h($post['title']) . '

    + +
    ' . $content . '
    +
    +
    + ← العودة للقائمة + 🗑 حذف +
    '; +} + +function renderCreate(): string { + return ' +
    + ← الرجوع +
    +
    +

    ➕ مقال جديد

    +
    + + + + + + + + + +
    +
    '; +} + +function renderNotFound(): string { + return '

    404

    الصفحة غير موجودة

    الرجوع
    '; +} + +function h(string $s): string { return htmlspecialchars($s, ENT_QUOTES, 'UTF-8'); } + +// ==================== 布局 ==================== +function renderLayout(string $content): string { + return ' + + + + +مدونة Laravel + + + +
    ' . $content . '
    +
    Mini مدونة Laravel · PHP ' . phpversion() . ' · يعمل على Android
    + +'; +} diff --git a/app/src/main/assets/sample_projects/php-laravel-ar/routes/web.php b/app/src/main/assets/sample_projects/php-laravel-ar/routes/web.php new file mode 100644 index 0000000..a82ff0e --- /dev/null +++ b/app/src/main/assets/sample_projects/php-laravel-ar/routes/web.php @@ -0,0 +1,15 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $pdo->exec('CREATE TABLE IF NOT EXISTS posts ( + id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, + excerpt TEXT, content TEXT NOT NULL, category TEXT DEFAULT "PHP", + created_at DATETIME DEFAULT CURRENT_TIMESTAMP + )'); + if ($pdo->query('SELECT COUNT(*) FROM posts')->fetchColumn() == 0) seedData($pdo); +} catch (Exception $e) { $pdo = null; } + +$routes = include $basePath . '/routes/web.php'; +$handler = null; $params = []; +foreach ($routes as [$rMethod, $rPath, $rHandler]) { + if ($method !== $rMethod) continue; + $pattern = preg_replace('/\{(\w+)\}/', '(?P<$1>[^/]+)', $rPath); + if (preg_match('#^' . $pattern . '$#', $uri, $m)) { + $handler = $rHandler; + $params = array_filter($m, 'is_string', ARRAY_FILTER_USE_KEY); + break; + } +} +if (!$handler) $handler = 'notFound'; + +$html = ''; +switch ($handler) { + case 'home': + $cat = $_GET['cat'] ?? ''; + $html = renderHome(getAllPosts($pdo, $cat), getCategories($pdo), $cat); break; + case 'show': + $post = getPost($pdo, (int)$params['id']); + $html = $post ? renderShow($post) : renderNotFound(); break; + case 'create': $html = renderCreate(); break; + case 'store': + $title = trim($_POST['title'] ?? ''); $excerpt = trim($_POST['excerpt'] ?? ''); + $content = trim($_POST['content'] ?? ''); $category = trim($_POST['category'] ?? 'PHP'); + if ($title && $content && $pdo) { + $stmt = $pdo->prepare('INSERT INTO posts (title,excerpt,content,category) VALUES (?,?,?,?)'); + $stmt->execute([$title, $excerpt ?: mb_substr(strip_tags($content), 0, 120) . '...', $content, $category]); + } + header('Location: /'); exit; + case 'delete': + if ($pdo) $pdo->prepare('DELETE FROM posts WHERE id=?')->execute([(int)$params['id']]); + header('Location: /'); exit; + case 'apiPosts': + header('Content-Type: application/json; charset=utf-8'); + echo json_encode(['posts' => getAllPosts($pdo), 'total' => count(getAllPosts($pdo))], JSON_PRETTY_PRINT); exit; + default: http_response_code(404); $html = renderNotFound(); +} +echo renderLayout($html); exit; + +function seedData(PDO $pdo): void { + $posts = [ + ['PHP 8.4: Property Hooks & Asymmetric Visibility', + 'PHP 8.4 introduces property hooks and asymmetric visibility for more elegant OOP.', + "PHP 8.4 is a significant language update.\n\n## Property Hooks\n\nProperty hooks let you define getter and setter logic directly in property declarations:\n\n```php\nclass User {\n public string \$fullName {\n get => \$this->firstName . ' ' . \$this->lastName;\n set(string \$value) {\n [\$this->firstName, \$this->lastName] = explode(' ', \$value, 2);\n }\n }\n}\n```\n\n## Asymmetric Visibility\n\nYou can now set different visibility for reading and writing:\n\n```php\nclass Config {\n public private(set) string \$apiKey;\n}\n```\n\nThese features take PHP's encapsulation to the next level.", 'PHP'], + ['Running PHP on Android Devices', + 'Learn how to run a full PHP HTTP server locally on Android devices.', + "The blog you're reading is running on a PHP server on your Android device!\n\n## Tech Stack\n\n- **PHP " . phpversion() . "** (CLI SAPI)\n- **SQLite3** embedded database\n- **Custom HTTP Server** (stream_socket_server)\n- **pcntl_fork** for concurrency\n\n## How It Works\n\n1. PHP binary starts in CLI mode\n2. Custom router server listens on HTTP port\n3. Each request is handled in a forked child process\n4. PHP files are executed via include\n5. WebView loads the local HTTP server\n\nEverything runs locally on the device — no internet required.", 'Tech'], + ['Building a PHP MVC Framework from Scratch', + 'Understand the core principles of MVC architecture by building a micro framework.', + "This blog itself is an instance of a micro MVC framework!\n\n## Core Components\n\n### 1. Router\nMaps URLs to handler functions with parameter extraction:\n```\nGET /post/{id} -> show(\$id)\n```\n\n### 2. Controller\nReceives requests, calls models, renders views.\n\n### 3. Model\nEncapsulates database operations, provides CRUD methods.\n\n### 4. View\nRenders data as HTML with layout support.\n\n## Directory Structure\n```\npublic/index.php <- Front Controller\nroutes/web.php <- Route Definitions\nstorage/blog.sqlite <- Database\n```\n\nSmall but complete — the essence of MVC.", 'Architecture'], + ['SQLite: The Best Database for Mobile', + 'SQLite needs no server, zero config — perfect for mobile and embedded use cases.', + "SQLite is the most widely deployed database engine in the world.\n\n## Why SQLite\n\n- **Zero config**: No database server needed\n- **Single file**: The entire database is one file\n- **High performance**: Extremely fast for read-heavy workloads\n- **Cross-platform**: Works on all major operating systems\n\n## Using SQLite in PHP\n\n```php\n\$pdo = new PDO('sqlite:blog.db');\n\$pdo->exec('CREATE TABLE posts (...)');\n\$stmt = \$pdo->prepare('SELECT * FROM posts WHERE id = ?');\n\$stmt->execute([1]);\n\$post = \$stmt->fetch(PDO::FETCH_ASSOC);\n```\n\nAll data in this blog is stored in SQLite!", 'Database'], + ['Modern PHP Best Practices', + 'From type safety to architecture — a practical guide to better PHP code.', + "Modern PHP is not the PHP you remember.\n\n## 1. Strict Types\n```php\ndeclare(strict_types=1);\nfunction add(int \$a, int \$b): int {\n return \$a + \$b;\n}\n```\n\n## 2. Enums\n```php\nenum Status: string {\n case Active = 'active';\n case Inactive = 'inactive';\n}\n```\n\n## 3. Readonly Properties\n```php\nclass User {\n public function __construct(\n public readonly string \$name,\n public readonly string \$email,\n ) {}\n}\n```\n\n## 4. Arrow Functions\n```php\n\$doubled = array_map(fn(\$n) => \$n * 2, [1, 2, 3]);\n```\n\nModern PHP is clean, fast, and type-safe.", 'PHP'], + ]; + $stmt = $pdo->prepare('INSERT INTO posts (title, excerpt, content, category) VALUES (?, ?, ?, ?)'); + foreach ($posts as $p) $stmt->execute($p); +} + +function getAllPosts(?PDO $pdo, string $category = ''): array { + if (!$pdo) return []; + $sql = 'SELECT * FROM posts'; + if ($category) { $stmt = $pdo->prepare($sql . ' WHERE category=? ORDER BY id DESC'); $stmt->execute([$category]); } + else { $stmt = $pdo->query($sql . ' ORDER BY id DESC'); } + return $stmt->fetchAll(PDO::FETCH_ASSOC); +} +function getPost(?PDO $pdo, int $id): ?array { + if (!$pdo) return null; + $stmt = $pdo->prepare('SELECT * FROM posts WHERE id=?'); $stmt->execute([$id]); + return $stmt->fetch(PDO::FETCH_ASSOC) ?: null; +} +function getCategories(?PDO $pdo): array { + if (!$pdo) return []; + return $pdo->query('SELECT DISTINCT category FROM posts ORDER BY category')->fetchAll(PDO::FETCH_COLUMN); +} +function renderMarkdown(string $text): string { + $text = htmlspecialchars($text); + $text = preg_replace('/```(\w*)\n(.*?)```/s', '
    $2
    ', $text); + $text = preg_replace('/`([^`]+)`/', '$1', $text); + $text = preg_replace('/^## (.+)$/m', '

    $1

    ', $text); + $text = preg_replace('/^### (.+)$/m', '

    $1

    ', $text); + $text = preg_replace('/\*\*(.+?)\*\*/', '$1', $text); + $text = preg_replace('/^- (.+)$/m', '
  • $1
  • ', $text); + $text = preg_replace('/(
  • .*<\/li>)/s', '
      $1
    ', $text); + $text = preg_replace('/\n{2,}/', '

    ', $text); + return '

    ' . $text . '

    '; +} +function h(string $s): string { return htmlspecialchars($s, ENT_QUOTES, 'UTF-8'); } + +function renderHome(array $posts, array $cats, string $activeCat): string { + $postCards = ''; + foreach ($posts as $p) { + $date = date('M d, Y', strtotime($p['created_at'])); + $postCards .= ''; + } + $catLinks = 'All'; + foreach ($cats as $c) $catLinks .= '' . h($c) . ''; + $count = count($posts); + return '

    \xf0\x9f\x93\x9d Laravel Blog

    A micro MVC blog built with pure PHP — running on your Android device

    \xf0\x9f\x93\x9a ' . $count . ' articles\xe2\x9a\xa1 PHP ' . phpversion() . '\xf0\x9f\x97\x84 SQLite ' . (class_exists("SQLite3") ? SQLite3::version()['versionString'] : 'N/A') . '
    ' . $catLinks . '
    \xe2\x9e\x95 New Post
    ' . ($postCards ?: '

    No posts yet. Write the first one!

    ') . '
    '; +} +function renderShow(array $post): string { + $date = date('M d, Y \a\t H:i', strtotime($post['created_at'])); + return '
    ← Back' . h($post['category']) . '

    ' . h($post['title']) . '

    ' . renderMarkdown($post['content']) . '
    ← Back to list× Delete
    '; +} +function renderCreate(): string { + return '
    ← Back

    \xe2\x9e\x95 New Post

    '; +} +function renderNotFound(): string { + return '

    404

    Page not found

    Go Home
    '; +} +function renderLayout(string $content): string { + return 'Laravel Blog
    ' . $content . '
    Mini Laravel Blog · PHP ' . phpversion() . ' · Running on Android
    '; +} diff --git a/app/src/main/assets/sample_projects/php-laravel-en/routes/web.php b/app/src/main/assets/sample_projects/php-laravel-en/routes/web.php new file mode 100644 index 0000000..a82ff0e --- /dev/null +++ b/app/src/main/assets/sample_projects/php-laravel-en/routes/web.php @@ -0,0 +1,15 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $pdo->exec(' + CREATE TABLE IF NOT EXISTS posts ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + title TEXT NOT NULL, + excerpt TEXT, + content TEXT NOT NULL, + category TEXT DEFAULT "PHP", + created_at DATETIME DEFAULT CURRENT_TIMESTAMP + ) + '); + if ($pdo->query('SELECT COUNT(*) FROM posts')->fetchColumn() == 0) { + seedData($pdo); + } +} catch (Exception $e) { + $pdo = null; +} + +// ==================== 路由调度 ==================== +$routes = include $basePath . '/routes/web.php'; +$handler = null; +$params = []; + +foreach ($routes as [$rMethod, $rPath, $rHandler]) { + if ($method !== $rMethod) continue; + $pattern = preg_replace('/\{(\w+)\}/', '(?P<$1>[^/]+)', $rPath); + if (preg_match('#^' . $pattern . '$#', $uri, $m)) { + $handler = $rHandler; + $params = array_filter($m, 'is_string', ARRAY_FILTER_USE_KEY); + break; + } +} + +if (!$handler) $handler = 'notFound'; + +// ==================== 控制器 ==================== +$html = ''; +switch ($handler) { + case 'home': + $cat = $_GET['cat'] ?? ''; + $posts = getAllPosts($pdo, $cat); + $cats = getCategories($pdo); + $html = renderHome($posts, $cats, $cat); + break; + case 'show': + $post = getPost($pdo, (int)$params['id']); + $html = $post ? renderShow($post) : renderNotFound(); + break; + case 'create': + $html = renderCreate(); + break; + case 'store': + $title = trim($_POST['title'] ?? ''); + $excerpt = trim($_POST['excerpt'] ?? ''); + $content = trim($_POST['content'] ?? ''); + $category = trim($_POST['category'] ?? 'PHP'); + if ($title && $content && $pdo) { + $stmt = $pdo->prepare('INSERT INTO posts (title,excerpt,content,category) VALUES (?,?,?,?)'); + $stmt->execute([$title, $excerpt ?: mb_substr(strip_tags($content), 0, 120) . '...', $content, $category]); + } + header('Location: /'); + exit; + case 'delete': + if ($pdo) { + $pdo->prepare('DELETE FROM posts WHERE id=?')->execute([(int)$params['id']]); + } + header('Location: /'); + exit; + case 'apiPosts': + header('Content-Type: application/json; charset=utf-8'); + echo json_encode(['posts' => getAllPosts($pdo), 'total' => count(getAllPosts($pdo))], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + exit; + default: + http_response_code(404); + $html = renderNotFound(); +} + +echo renderLayout($html); +exit; + +// ==================== 数据层 ==================== +function seedData(PDO $pdo): void { + $posts = [ + ['PHP 8.4 新特性:属性钩子与不对称可见性', + 'PHP 8.4 引入了属性钩子和不对称可见性,让面向对象编程更加优雅。', + "PHP 8.4 是一次重要的语言更新。\n\n## 属性钩子 (Property Hooks)\n\n属性钩子允许你直接在属性声明中定义 getter 和 setter 逻辑:\n\n```php\nclass User {\n public string \$fullName {\n get => \$this->firstName . ' ' . \$this->lastName;\n set(string \$value) {\n [\$this->firstName, \$this->lastName] = explode(' ', \$value, 2);\n }\n }\n}\n```\n\n## 不对称可见性\n\n现在可以设置属性的读取和写入拥有不同的可见性:\n\n```php\nclass Config {\n public private(set) string \$apiKey;\n}\n```\n\n这些特性让 PHP 的封装性更上一层楼。", 'PHP'], + ['在 Android 设备上运行 PHP 服务器', + '探索如何在 Android 设备上本地运行完整的 PHP HTTP 服务器。', + "你正在看的这个博客,正是运行在你的 Android 设备上的 PHP 服务器!\n\n## 技术栈\n\n- **PHP " . phpversion() . "** (CLI SAPI)\n- **SQLite3** 内嵌式数据库\n- **自定义 HTTP 服务器** (stream_socket_server)\n- **pcntl_fork** 多进程并发\n\n## 工作原理\n\n1. PHP 二进制以 CLI 模式启动\n2. 自定义路由服务器监听 HTTP 端口\n3. 每个请求 fork 子进程处理\n4. 通过 include 执行 PHP 文件\n5. WebView 加载本地 HTTP 服务器地址\n\n这意味着所有处理都在设备本地完成,无需网络连接。", '技术'], + ['从零构建 PHP MVC 框架', + '理解 MVC 架构的核心原理,动手实现一个微型框架。', + "本博客本身就是一个微型 MVC 框架的实例!\n\n## 核心组件\n\n### 1. 路由器 (Router)\n将 URL 映射到处理器函数,支持参数提取:\n```\nGET /post/{id} -> show($id)\n```\n\n### 2. 控制器 (Controller)\n接收请求,调用模型获取数据,渲染视图。\n\n### 3. 模型 (Model)\n封装数据库操作,提供 CRUD 方法。\n\n### 4. 视图 (View)\n将数据渲染为 HTML,支持布局继承。\n\n## 目录结构\n```\npublic/index.php ← 前端控制器\nroutes/web.php ← 路由定义\nstorage/blog.sqlite ← 数据库\n```\n\n麻雀虽小五脏俱全,这就是 MVC 的精髓。", '架构'], + ['SQLite:移动开发的最佳数据库', + 'SQLite 无需服务器、零配置,完美适合移动和嵌入式场景。', + "SQLite 是全球部署最广泛的数据库引擎。\n\n## 为什么选择 SQLite\n\n- **零配置**: 无需安装数据库服务器\n- **单文件**: 整个数据库就是一个文件\n- **高性能**: 对于读多写少的场景极快\n- **跨平台**: 支持所有主流操作系统\n\n## 在 PHP 中使用\n\n```php\n\$pdo = new PDO('sqlite:blog.db');\n\$pdo->exec('CREATE TABLE posts (...)');\n\$stmt = \$pdo->prepare('SELECT * FROM posts WHERE id = ?');\n\$stmt->execute([1]);\n\$post = \$stmt->fetch(PDO::FETCH_ASSOC);\n```\n\n本博客的所有数据就存储在 SQLite 中!", '数据库'], + ['现代 PHP 开发最佳实践', + '从类型安全到架构设计,提升 PHP 代码质量的实用指南。', + "现代 PHP 已经不是你印象中的那个 PHP 了。\n\n## 1. 严格类型\n```php\ndeclare(strict_types=1);\nfunction add(int \$a, int \$b): int {\n return \$a + \$b;\n}\n```\n\n## 2. 枚举类型\n```php\nenum Status: string {\n case Active = 'active';\n case Inactive = 'inactive';\n}\n```\n\n## 3. 只读属性\n```php\nclass User {\n public function __construct(\n public readonly string \$name,\n public readonly string \$email,\n ) {}\n}\n```\n\n## 4. 箭头函数\n```php\n\$doubled = array_map(fn(\$n) => \$n * 2, [1, 2, 3]);\n```\n\n现代 PHP 简洁、高效、类型安全。", 'PHP'], + ]; + $stmt = $pdo->prepare('INSERT INTO posts (title, excerpt, content, category) VALUES (?, ?, ?, ?)'); + foreach ($posts as $p) $stmt->execute($p); +} + +function getAllPosts(?PDO $pdo, string $category = ''): array { + if (!$pdo) return []; + $sql = 'SELECT * FROM posts'; + if ($category) { + $stmt = $pdo->prepare($sql . ' WHERE category=? ORDER BY id DESC'); + $stmt->execute([$category]); + } else { + $stmt = $pdo->query($sql . ' ORDER BY id DESC'); + } + return $stmt->fetchAll(PDO::FETCH_ASSOC); +} + +function getPost(?PDO $pdo, int $id): ?array { + if (!$pdo) return null; + $stmt = $pdo->prepare('SELECT * FROM posts WHERE id=?'); + $stmt->execute([$id]); + return $stmt->fetch(PDO::FETCH_ASSOC) ?: null; +} + +function getCategories(?PDO $pdo): array { + if (!$pdo) return []; + return $pdo->query('SELECT DISTINCT category FROM posts ORDER BY category')->fetchAll(PDO::FETCH_COLUMN); +} + +// ==================== Markdown 简易渲染 ==================== +function renderMarkdown(string $text): string { + $text = htmlspecialchars($text); + $text = preg_replace('/```(\w*)\n(.*?)```/s', '
    $2
    ', $text); + $text = preg_replace('/`([^`]+)`/', '$1', $text); + $text = preg_replace('/^## (.+)$/m', '

    $1

    ', $text); + $text = preg_replace('/^### (.+)$/m', '

    $1

    ', $text); + $text = preg_replace('/\*\*(.+?)\*\*/', '$1', $text); + $text = preg_replace('/^- (.+)$/m', '
  • $1
  • ', $text); + $text = preg_replace('/(
  • .*<\/li>)/s', '
      $1
    ', $text); + $text = preg_replace('/\n{2,}/', '

    ', $text); + return '

    ' . $text . '

    '; +} + +// ==================== 视图 ==================== +function renderHome(array $posts, array $cats, string $activeCat): string { + $postCards = ''; + foreach ($posts as $p) { + $date = date('Y年m月d日', strtotime($p['created_at'])); + $postCards .= ' + '; + } + + $catLinks = '全部'; + foreach ($cats as $c) { + $catLinks .= '' . h($c) . ''; + } + + $count = count($posts); + return ' +
    +

    📝 Laravel 博客

    +

    用纯 PHP 构建的微型 MVC 博客 — 运行在你的 Android 设备上

    +
    + 📚 ' . $count . ' 篇文章 + ⚡ PHP ' . phpversion() . ' + 🗄 SQLite ' . (class_exists("SQLite3") ? SQLite3::version()['versionString'] : 'N/A') . ' +
    +
    +
    +
    ' . $catLinks . '
    + ➕ 写文章 +
    +
    ' . ($postCards ?: '

    还没有文章,写第一篇吧!

    ') . '
    '; +} + +function renderShow(array $post): string { + $date = date('Y年m月d日 H:i', strtotime($post['created_at'])); + $content = renderMarkdown($post['content']); + return ' +
    + ← 返回首页 + ' . h($post['category']) . ' +
    +
    +

    ' . h($post['title']) . '

    + +
    ' . $content . '
    +
    +
    + ← 返回列表 + 🗑 删除 +
    '; +} + +function renderCreate(): string { + return ' +
    + ← 返回首页 +
    +
    +

    ➕ 写新文章

    +
    + + + + + + + + + +
    +
    '; +} + +function renderNotFound(): string { + return '

    404

    页面未找到

    返回首页
    '; +} + +function h(string $s): string { return htmlspecialchars($s, ENT_QUOTES, 'UTF-8'); } + +// ==================== 布局 ==================== +function renderLayout(string $content): string { + return ' + + + + +Laravel 博客 + + + +
    ' . $content . '
    +
    Mini Laravel 博客 · PHP ' . phpversion() . ' · 运行在 Android 设备上
    + +'; +} diff --git a/app/src/main/assets/sample_projects/php-laravel/routes/web.php b/app/src/main/assets/sample_projects/php-laravel/routes/web.php new file mode 100644 index 0000000..a82ff0e --- /dev/null +++ b/app/src/main/assets/sample_projects/php-laravel/routes/web.php @@ -0,0 +1,15 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $pdo->exec('CREATE TABLE IF NOT EXISTS tasks ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + title TEXT NOT NULL, + done INTEGER DEFAULT 0, + priority TEXT DEFAULT "medium", + created_at DATETIME DEFAULT CURRENT_TIMESTAMP + )'); + if ($pdo->query('SELECT COUNT(*) FROM tasks')->fetchColumn() == 0) { + $seed = [ + ['تصميم واجهات REST API', 1, 'high'], + ['تنفيذ عمليات CRUD', 1, 'high'], + ['إضافة التحقق من المدخلات', 0, 'medium'], + ['كتابة وثائق API', 0, 'medium'], + ['تحسين الأداء', 0, 'low'], + ]; + $stmt = $pdo->prepare('INSERT INTO tasks (title,done,priority) VALUES (?,?,?)'); + foreach ($seed as $t) $stmt->execute($t); + } +} catch (Exception $e) { $pdo = null; } + +// ==================== API 路由 ==================== +function jsonResponse(int $code, $data): void { + http_response_code($code); + header('Content-Type: application/json; charset=utf-8'); + header('Access-Control-Allow-Origin: *'); + echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + exit; +} + +function getInput(): array { + $raw = $GLOBALS['__HTTP_RAW_BODY'] ?? file_get_contents('php://input'); + return json_decode($raw, true) ?: $_POST; +} + +// API 路由 +if (str_starts_with($uri, '/api/')) { + header('Access-Control-Allow-Methods: GET,POST,PUT,PATCH,DELETE,OPTIONS'); + header('Access-Control-Allow-Headers: Content-Type'); + if ($method === 'OPTIONS') { http_response_code(204); exit; } + + // GET /api/tasks + if ($method === 'GET' && $uri === '/api/tasks') { + $filter = $_GET['status'] ?? ''; + $sql = 'SELECT * FROM tasks'; + if ($filter === 'done') $sql .= ' WHERE done=1'; + elseif ($filter === 'pending') $sql .= ' WHERE done=0'; + $sql .= ' ORDER BY id DESC'; + $tasks = $pdo ? $pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC) : []; + foreach ($tasks as &$t) $t['done'] = (bool)$t['done']; + jsonResponse(200, ['tasks' => $tasks, 'total' => count($tasks)]); + } + + // POST /api/tasks + if ($method === 'POST' && $uri === '/api/tasks') { + $input = getInput(); + $title = trim($input['title'] ?? ''); + $priority = $input['priority'] ?? 'medium'; + if (!$title) jsonResponse(422, ['error' => 'العنوان مطلوب']); + if ($pdo) { + $stmt = $pdo->prepare('INSERT INTO tasks (title,priority) VALUES (?,?)'); + $stmt->execute([$title, $priority]); + $id = $pdo->lastInsertId(); + $task = $pdo->query("SELECT * FROM tasks WHERE id=$id")->fetch(PDO::FETCH_ASSOC); + $task['done'] = (bool)$task['done']; + jsonResponse(201, ['task' => $task]); + } + jsonResponse(500, ['error' => 'قاعدة البيانات غير متاحة']); + } + + // PATCH /api/tasks/{id}/toggle + if ($method === 'PATCH' && preg_match('#^/api/tasks/(\d+)/toggle$#', $uri, $m)) { + if ($pdo) { + $pdo->exec("UPDATE tasks SET done = NOT done WHERE id={$m[1]}"); + $task = $pdo->query("SELECT * FROM tasks WHERE id={$m[1]}")->fetch(PDO::FETCH_ASSOC); + if ($task) { $task['done'] = (bool)$task['done']; jsonResponse(200, ['task' => $task]); } + } + jsonResponse(404, ['error' => 'المهمة غير موجودة']); + } + + // DELETE /api/tasks/{id} + if ($method === 'DELETE' && preg_match('#^/api/tasks/(\d+)$#', $uri, $m)) { + if ($pdo) { + $pdo->exec("DELETE FROM tasks WHERE id={$m[1]}"); + jsonResponse(200, ['deleted' => true]); + } + jsonResponse(500, ['error' => 'قاعدة البيانات غير متاحة']); + } + + // GET /api/info + if ($method === 'GET' && $uri === '/api/info') { + jsonResponse(200, [ + 'server' => 'Mini Slim API', + 'php' => phpversion(), + 'sapi' => php_sapi_name(), + 'os' => PHP_OS, + 'extensions' => get_loaded_extensions(), + 'memory' => [ + 'usage' => memory_get_usage(true), + 'peak' => memory_get_peak_usage(true), + ], + ]); + } + + jsonResponse(404, ['error' => 'نقطة النهاية غير موجودة: ' . $method . ' ' . $uri]); +} + +// ==================== 仪表盘页面 ==================== +$taskCount = $pdo ? $pdo->query('SELECT COUNT(*) FROM tasks')->fetchColumn() : 0; +$doneCount = $pdo ? $pdo->query('SELECT COUNT(*) FROM tasks WHERE done=1')->fetchColumn() : 0; +?> + + + + + +لوحة Slim API + + + + + +
    +

    🚀 Slim REST API

    +

    خادم RESTful API مستقل — يعمل على جهاز Android

    +
    +
    إجمالي المهام
    +
    مكتملة
    +
    6
    نقاط API
    +
    PHP
    +
    +
    +
    +
    +

    📚 وثائق API

    +
    + GET + /api/tasks + جلب قائمة المهام +
    +
    + POST + /api/tasks + إنشاء مهمة جديدة +
    +
    + PATCH + /api/tasks/{id}/toggle + تبديل الحالة +
    +
    + DELETE + /api/tasks/{id} + حذف مهمة +
    +
    + GET + /api/info + معلومات الخادم +
    +
    +
    + + + +
    + +
    +
    +
    + +
    +

    ✅ إدارة المهام

    +
    + + + +
    +
    جار التحميل...
    +
    +
    +
    Mini Slim API · PHP · يعمل على Android
    + + + + diff --git a/app/src/main/assets/sample_projects/php-slim-en/composer.json b/app/src/main/assets/sample_projects/php-slim-en/composer.json new file mode 100644 index 0000000..a0fa82d --- /dev/null +++ b/app/src/main/assets/sample_projects/php-slim-en/composer.json @@ -0,0 +1,9 @@ +{ + "name": "demo/slim-api", + "description": "Slim REST API Demo", + "require": { + "php": "^8.0", + "slim/slim": "^4.12", + "slim/psr7": "^1.6" + } +} diff --git a/app/src/main/assets/sample_projects/php-slim-en/public/index.php b/app/src/main/assets/sample_projects/php-slim-en/public/index.php new file mode 100644 index 0000000..9285540 --- /dev/null +++ b/app/src/main/assets/sample_projects/php-slim-en/public/index.php @@ -0,0 +1,309 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $pdo->exec('CREATE TABLE IF NOT EXISTS tasks ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + title TEXT NOT NULL, + done INTEGER DEFAULT 0, + priority TEXT DEFAULT "medium", + created_at DATETIME DEFAULT CURRENT_TIMESTAMP + )'); + if ($pdo->query('SELECT COUNT(*) FROM tasks')->fetchColumn() == 0) { + $seed = [ + ['Design REST API endpoints', 1, 'high'], + ['Implement database CRUD', 1, 'high'], + ['Add input validation', 0, 'medium'], + ['Write API documentation', 0, 'medium'], + ['Performance optimization', 0, 'low'], + ]; + $stmt = $pdo->prepare('INSERT INTO tasks (title,done,priority) VALUES (?,?,?)'); + foreach ($seed as $t) $stmt->execute($t); + } +} catch (Exception $e) { $pdo = null; } + +// ==================== API 路由 ==================== +function jsonResponse(int $code, $data): void { + http_response_code($code); + header('Content-Type: application/json; charset=utf-8'); + header('Access-Control-Allow-Origin: *'); + echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + exit; +} + +function getInput(): array { + $raw = $GLOBALS['__HTTP_RAW_BODY'] ?? file_get_contents('php://input'); + return json_decode($raw, true) ?: $_POST; +} + +// API 路由 +if (str_starts_with($uri, '/api/')) { + header('Access-Control-Allow-Methods: GET,POST,PUT,PATCH,DELETE,OPTIONS'); + header('Access-Control-Allow-Headers: Content-Type'); + if ($method === 'OPTIONS') { http_response_code(204); exit; } + + // GET /api/tasks + if ($method === 'GET' && $uri === '/api/tasks') { + $filter = $_GET['status'] ?? ''; + $sql = 'SELECT * FROM tasks'; + if ($filter === 'done') $sql .= ' WHERE done=1'; + elseif ($filter === 'pending') $sql .= ' WHERE done=0'; + $sql .= ' ORDER BY id DESC'; + $tasks = $pdo ? $pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC) : []; + foreach ($tasks as &$t) $t['done'] = (bool)$t['done']; + jsonResponse(200, ['tasks' => $tasks, 'total' => count($tasks)]); + } + + // POST /api/tasks + if ($method === 'POST' && $uri === '/api/tasks') { + $input = getInput(); + $title = trim($input['title'] ?? ''); + $priority = $input['priority'] ?? 'medium'; + if (!$title) jsonResponse(422, ['error' => 'Title is required']); + if ($pdo) { + $stmt = $pdo->prepare('INSERT INTO tasks (title,priority) VALUES (?,?)'); + $stmt->execute([$title, $priority]); + $id = $pdo->lastInsertId(); + $task = $pdo->query("SELECT * FROM tasks WHERE id=$id")->fetch(PDO::FETCH_ASSOC); + $task['done'] = (bool)$task['done']; + jsonResponse(201, ['task' => $task]); + } + jsonResponse(500, ['error' => 'Database unavailable']); + } + + // PATCH /api/tasks/{id}/toggle + if ($method === 'PATCH' && preg_match('#^/api/tasks/(\d+)/toggle$#', $uri, $m)) { + if ($pdo) { + $pdo->exec("UPDATE tasks SET done = NOT done WHERE id={$m[1]}"); + $task = $pdo->query("SELECT * FROM tasks WHERE id={$m[1]}")->fetch(PDO::FETCH_ASSOC); + if ($task) { $task['done'] = (bool)$task['done']; jsonResponse(200, ['task' => $task]); } + } + jsonResponse(404, ['error' => 'Task not found']); + } + + // DELETE /api/tasks/{id} + if ($method === 'DELETE' && preg_match('#^/api/tasks/(\d+)$#', $uri, $m)) { + if ($pdo) { + $pdo->exec("DELETE FROM tasks WHERE id={$m[1]}"); + jsonResponse(200, ['deleted' => true]); + } + jsonResponse(500, ['error' => 'Database unavailable']); + } + + // GET /api/info + if ($method === 'GET' && $uri === '/api/info') { + jsonResponse(200, [ + 'server' => 'Mini Slim API', + 'php' => phpversion(), + 'sapi' => php_sapi_name(), + 'os' => PHP_OS, + 'extensions' => get_loaded_extensions(), + 'memory' => [ + 'usage' => memory_get_usage(true), + 'peak' => memory_get_peak_usage(true), + ], + ]); + } + + jsonResponse(404, ['error' => 'Endpoint not found: ' . $method . ' ' . $uri]); +} + +// ==================== 仪表盘页面 ==================== +$taskCount = $pdo ? $pdo->query('SELECT COUNT(*) FROM tasks')->fetchColumn() : 0; +$doneCount = $pdo ? $pdo->query('SELECT COUNT(*) FROM tasks WHERE done=1')->fetchColumn() : 0; +?> + + + + + +Slim API Dashboard + + + +
    +

    🚀 Slim REST API

    +

    Self-contained RESTful API server — running on your Android device

    +
    +
    Total Tasks
    +
    Completed
    +
    6
    API Endpoints
    +
    PHP
    +
    +
    +
    +
    +

    📚 API Docs

    +
    + GET + /api/tasks + Get task list +
    +
    + POST + /api/tasks + Create new task +
    +
    + PATCH + /api/tasks/{id}/toggle + Toggle status +
    +
    + DELETE + /api/tasks/{id} + Delete task +
    +
    + GET + /api/info + Server info +
    +
    +
    + + + +
    + +
    +
    +
    + +
    +

    ✅ Task Manager

    +
    + + + +
    +
    Loading...
    +
    +
    +
    Mini Slim API · PHP · Running on Android
    + + + + diff --git a/app/src/main/assets/sample_projects/php-slim/composer.json b/app/src/main/assets/sample_projects/php-slim/composer.json new file mode 100644 index 0000000..0557b6f --- /dev/null +++ b/app/src/main/assets/sample_projects/php-slim/composer.json @@ -0,0 +1,9 @@ +{ + "name": "demo/slim-api", + "description": "Slim REST API 示例", + "require": { + "php": "^8.0", + "slim/slim": "^4.12", + "slim/psr7": "^1.6" + } +} diff --git a/app/src/main/assets/sample_projects/php-slim/public/index.php b/app/src/main/assets/sample_projects/php-slim/public/index.php new file mode 100644 index 0000000..325cb62 --- /dev/null +++ b/app/src/main/assets/sample_projects/php-slim/public/index.php @@ -0,0 +1,311 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $pdo->exec('CREATE TABLE IF NOT EXISTS tasks ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + title TEXT NOT NULL, + done INTEGER DEFAULT 0, + priority TEXT DEFAULT "medium", + created_at DATETIME DEFAULT CURRENT_TIMESTAMP + )'); + if ($pdo->query('SELECT COUNT(*) FROM tasks')->fetchColumn() == 0) { + $seed = [ + ['设计 REST API 接口', 1, 'high'], + ['实现数据库 CRUD', 1, 'high'], + ['添加输入验证', 0, 'medium'], + ['编写 API 文档', 0, 'medium'], + ['性能优化与缓存', 0, 'low'], + ]; + $stmt = $pdo->prepare('INSERT INTO tasks (title,done,priority) VALUES (?,?,?)'); + foreach ($seed as $t) $stmt->execute($t); + } +} catch (Exception $e) { $pdo = null; } + +// ==================== API 路由 ==================== +function jsonResponse(int $code, $data): void { + http_response_code($code); + header('Content-Type: application/json; charset=utf-8'); + header('Access-Control-Allow-Origin: *'); + echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + exit; +} + +function getInput(): array { + // 优先使用路由服务器提供的原始请求体(CLI SAPI 下 php://input 可能不可用) + $raw = $GLOBALS['__HTTP_RAW_BODY'] ?? file_get_contents('php://input'); + return json_decode($raw, true) ?: $_POST; +} + +// API 路由 +if (str_starts_with($uri, '/api/')) { + header('Access-Control-Allow-Methods: GET,POST,PUT,PATCH,DELETE,OPTIONS'); + header('Access-Control-Allow-Headers: Content-Type'); + if ($method === 'OPTIONS') { http_response_code(204); exit; } + + // GET /api/tasks + if ($method === 'GET' && $uri === '/api/tasks') { + $filter = $_GET['status'] ?? ''; + $sql = 'SELECT * FROM tasks'; + if ($filter === 'done') $sql .= ' WHERE done=1'; + elseif ($filter === 'pending') $sql .= ' WHERE done=0'; + $sql .= ' ORDER BY id DESC'; + $tasks = $pdo ? $pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC) : []; + foreach ($tasks as &$t) $t['done'] = (bool)$t['done']; + jsonResponse(200, ['tasks' => $tasks, 'total' => count($tasks)]); + } + + // POST /api/tasks + if ($method === 'POST' && $uri === '/api/tasks') { + $input = getInput(); + $title = trim($input['title'] ?? ''); + $priority = $input['priority'] ?? 'medium'; + if (!$title) jsonResponse(422, ['error' => '标题不能为空']); + if ($pdo) { + $stmt = $pdo->prepare('INSERT INTO tasks (title,priority) VALUES (?,?)'); + $stmt->execute([$title, $priority]); + $id = $pdo->lastInsertId(); + $task = $pdo->query("SELECT * FROM tasks WHERE id=$id")->fetch(PDO::FETCH_ASSOC); + $task['done'] = (bool)$task['done']; + jsonResponse(201, ['task' => $task]); + } + jsonResponse(500, ['error' => '数据库不可用']); + } + + // PATCH /api/tasks/{id}/toggle + if ($method === 'PATCH' && preg_match('#^/api/tasks/(\d+)/toggle$#', $uri, $m)) { + if ($pdo) { + $pdo->exec("UPDATE tasks SET done = NOT done WHERE id={$m[1]}"); + $task = $pdo->query("SELECT * FROM tasks WHERE id={$m[1]}")->fetch(PDO::FETCH_ASSOC); + if ($task) { $task['done'] = (bool)$task['done']; jsonResponse(200, ['task' => $task]); } + } + jsonResponse(404, ['error' => '任务不存在']); + } + + // DELETE /api/tasks/{id} + if ($method === 'DELETE' && preg_match('#^/api/tasks/(\d+)$#', $uri, $m)) { + if ($pdo) { + $pdo->exec("DELETE FROM tasks WHERE id={$m[1]}"); + jsonResponse(200, ['deleted' => true]); + } + jsonResponse(500, ['error' => '数据库不可用']); + } + + // GET /api/info + if ($method === 'GET' && $uri === '/api/info') { + jsonResponse(200, [ + 'server' => 'Mini Slim API', + 'php' => phpversion(), + 'sapi' => php_sapi_name(), + 'os' => PHP_OS, + 'extensions' => get_loaded_extensions(), + 'memory' => [ + 'usage' => memory_get_usage(true), + 'peak' => memory_get_peak_usage(true), + ], + ]); + } + + jsonResponse(404, ['error' => '接口不存在: ' . $method . ' ' . $uri]); +} + +// ==================== 仪表盘页面 ==================== +$taskCount = $pdo ? $pdo->query('SELECT COUNT(*) FROM tasks')->fetchColumn() : 0; +$doneCount = $pdo ? $pdo->query('SELECT COUNT(*) FROM tasks WHERE done=1')->fetchColumn() : 0; +?> + + + + + +Slim API 仪表盘 + + + +
    +

    🚀 Slim REST API

    +

    自包含 RESTful API 服务器 — 运行在你的 Android 设备上

    +
    +
    任务总数
    +
    已完成
    +
    6
    API 接口
    +
    PHP
    +
    +
    +
    +
    +

    📚 API 文档

    +
    + GET + /api/tasks + 获取任务列表 +
    +
    + POST + /api/tasks + 创建新任务 +
    +
    + PATCH + /api/tasks/{id}/toggle + 切换完成状态 +
    +
    + DELETE + /api/tasks/{id} + 删除任务 +
    +
    + GET + /api/info + 服务器信息 +
    +
    +
    + + + +
    + +
    +
    +
    + +
    +

    ✅ 任务管理

    +
    + + + +
    +
    加载中...
    +
    +
    +
    Mini Slim API · PHP · 运行在 Android 设备上
    + + + + diff --git a/app/src/main/assets/sample_projects/php-vanilla-ar/index.php b/app/src/main/assets/sample_projects/php-vanilla-ar/index.php new file mode 100644 index 0000000..cd62a72 --- /dev/null +++ b/app/src/main/assets/sample_projects/php-vanilla-ar/index.php @@ -0,0 +1,202 @@ + phpversion(), + 'SAPI' => php_sapi_name(), + 'نظام التشغيل' => PHP_OS . ' (' . php_uname('m') . ')', + 'برنامج الخادم' => $_SERVER['SERVER_SOFTWARE'] ?? 'N/A', + 'إصدار Zend' => zend_version(), + 'وقت التنفيذ الأقصى' => ini_get('max_execution_time') . 's', + 'حد الذاكرة' => ini_get('memory_limit'), + 'الذاكرة المستخدمة' => round(memory_get_usage(true) / 1024 / 1024, 2) . ' MB', + 'ذروة الذاكرة' => round(memory_get_peak_usage(true) / 1024 / 1024, 2) . ' MB', + 'وقت الخادم' => date('Y-m-d H:i:s'), + 'المنطقة الزمنية' => date_default_timezone_get(), + 'معرف العملية' => getmypid(), +]; + +$extensions = get_loaded_extensions(); +sort($extensions); +$extCount = count($extensions); + +// كشف الميزات +$features = [ + 'PDO' => extension_loaded('pdo'), + 'SQLite3' => extension_loaded('pdo_sqlite') || extension_loaded('sqlite3'), + 'JSON' => extension_loaded('json'), + 'cURL' => extension_loaded('curl'), + 'OpenSSL' => extension_loaded('openssl'), + 'mbstring' => extension_loaded('mbstring'), + 'GD' => extension_loaded('gd'), + 'DOM/XML' => extension_loaded('dom'), + 'PCNTL' => extension_loaded('pcntl'), + 'Sockets' => extension_loaded('sockets'), + 'Zip' => extension_loaded('zip'), + 'BCMath' => extension_loaded('bcmath'), +]; + +// 性能基准 +$benchStart = hrtime(true); +$n = 0; for ($i = 0; $i < 1000000; $i++) $n += $i; +$intTime = round((hrtime(true) - $benchStart) / 1e6, 2); + +$benchStart = hrtime(true); +$s = ''; for ($i = 0; $i < 50000; $i++) $s .= 'a'; +$md5 = md5($s); +$strTime = round((hrtime(true) - $benchStart) / 1e6, 2); + +$benchStart = hrtime(true); +$arr = range(1, 10000); shuffle($arr); sort($arr); +$sortTime = round((hrtime(true) - $benchStart) / 1e6, 2); + +$sessionData = $_SESSION ?? []; +?> + + + + + +عرض قدرات PHP + + + +
    +

    🐘 عرض قدرات PHP

    +

    استكشف PHP على جهاز Android

    +
    +
    إصدار PHP
    +
    الإضافات
    +
    bit
    البنية
    +
    النظام
    +
    +
    +
    +
    +

    📊 معلومات النظام

    + $v): ?> +
    + +
    + +
    +

    ⚡ اختبار الأداء

    + $intTime, "عمليات نصية" => $strTime, "ترتيب مصفوفة" => $sortTime]; + foreach ($benchmarks as $name => $time): + $pct = min(($time / $maxTime) * 100, 100); + ?> +
    + +
    + ms +
    + +
    + +
    +

    ✅ كشف الميزات

    +
    + $ok): ?> +
    + +
    +
    + +
    +

    🔐 إدارة الجلسات

    +
    + + + +
    + + $v): ?> +
    + +
    + +

    لا توجد بيانات جلسة. جرب إضافة واحدة!

    + +
    + +
    +

    🧩 الإضافات ()

    +
    + + + +
    +
    +
    +
    عرض قدرات PHP · PHP · يعمل على Android
    + + diff --git a/app/src/main/assets/sample_projects/php-vanilla-en/index.php b/app/src/main/assets/sample_projects/php-vanilla-en/index.php new file mode 100644 index 0000000..e77bc55 --- /dev/null +++ b/app/src/main/assets/sample_projects/php-vanilla-en/index.php @@ -0,0 +1,203 @@ + phpversion(), + 'SAPI' => php_sapi_name(), + 'OS' => PHP_OS . ' (' . php_uname('m') . ')', + 'Server Software' => $_SERVER['SERVER_SOFTWARE'] ?? 'N/A', + 'Zend Version' => zend_version(), + 'Max Execution Time' => ini_get('max_execution_time') . 's', + 'Memory Limit' => ini_get('memory_limit'), + 'Memory Usage' => round(memory_get_usage(true) / 1024 / 1024, 2) . ' MB', + 'Peak Memory' => round(memory_get_peak_usage(true) / 1024 / 1024, 2) . ' MB', + 'Server Time' => date('Y-m-d H:i:s'), + 'Timezone' => date_default_timezone_get(), + 'Process ID' => getmypid(), +]; + +$extensions = get_loaded_extensions(); +sort($extensions); +$extCount = count($extensions); + +// Feature Detection +$features = [ + 'PDO' => extension_loaded('pdo'), + 'SQLite3' => extension_loaded('pdo_sqlite') || extension_loaded('sqlite3'), + 'JSON' => extension_loaded('json'), + 'cURL' => extension_loaded('curl'), + 'OpenSSL' => extension_loaded('openssl'), + 'mbstring' => extension_loaded('mbstring'), + 'GD' => extension_loaded('gd'), + 'DOM/XML' => extension_loaded('dom'), + 'PCNTL' => extension_loaded('pcntl'), + 'Sockets' => extension_loaded('sockets'), + 'Zip' => extension_loaded('zip'), + 'BCMath' => extension_loaded('bcmath'), +]; + +// 性能基准 +$benchStart = hrtime(true); +$n = 0; for ($i = 0; $i < 1000000; $i++) $n += $i; +$intTime = round((hrtime(true) - $benchStart) / 1e6, 2); + +$benchStart = hrtime(true); +$s = ''; for ($i = 0; $i < 50000; $i++) $s .= 'a'; +$md5 = md5($s); +$strTime = round((hrtime(true) - $benchStart) / 1e6, 2); + +$benchStart = hrtime(true); +$arr = range(1, 10000); shuffle($arr); sort($arr); +$sortTime = round((hrtime(true) - $benchStart) / 1e6, 2); + +$sessionData = $_SESSION ?? []; +?> + + + + + +PHP Showcase + + + +
    +

    🐘 PHP Showcase

    +

    Explore PHP capabilities on Android

    +
    +
    PHP Version
    +
    Extensions
    +
    bit
    Arch
    +
    OS
    +
    +
    +
    +
    +

    📊 System Info

    + $v): ?> +
    + +
    + +
    +

    ⚡ Benchmarks

    + $intTime, "String ops (50K)" => $strTime, "Array sort (10K)" => $sortTime]; + foreach ($benchmarks as $name => $time): + $pct = min(($time / $maxTime) * 100, 100); + ?> +
    + +
    + ms +
    + +
    + +
    +

    ✅ Feature Detection

    +
    + $ok): ?> +
    + +
    +
    + +
    +

    🔐 Session Manager

    +
    + + + +
    + + $v): ?> +
    + +
    + +

    No session data yet. Try adding one!

    + +
    + +
    +

    🧩 Extensions ()

    +
    + + + +
    +
    +
    +
    PHP Showcase · PHP · Running on Android
    + + diff --git a/app/src/main/assets/sample_projects/php-vanilla/index.php b/app/src/main/assets/sample_projects/php-vanilla/index.php new file mode 100644 index 0000000..51dc87e --- /dev/null +++ b/app/src/main/assets/sample_projects/php-vanilla/index.php @@ -0,0 +1,198 @@ + phpversion(), + 'SAPI' => php_sapi_name(), + '操作系统' => PHP_OS . ' (' . php_uname('m') . ')', + '服务器软件' => $_SERVER['SERVER_SOFTWARE'] ?? 'N/A', + 'Zend 版本' => zend_version(), + '最大执行时间' => ini_get('max_execution_time') . 's', + '内存限制' => ini_get('memory_limit'), + '当前内存' => round(memory_get_usage(true) / 1024 / 1024, 2) . ' MB', + '峰值内存' => round(memory_get_peak_usage(true) / 1024 / 1024, 2) . ' MB', + '服务器时间' => date('Y-m-d H:i:s'), + '时区' => date_default_timezone_get(), + '进程 ID' => getmypid(), +]; + +$extensions = get_loaded_extensions(); +sort($extensions); +$extCount = count($extensions); + +// 功能检测 +$features = [ + 'PDO' => extension_loaded('pdo'), + 'SQLite3' => extension_loaded('pdo_sqlite') || extension_loaded('sqlite3'), + 'JSON' => extension_loaded('json'), + 'cURL' => extension_loaded('curl'), + 'OpenSSL' => extension_loaded('openssl'), + 'mbstring' => extension_loaded('mbstring'), + 'GD' => extension_loaded('gd'), + 'DOM/XML' => extension_loaded('dom'), + 'PCNTL' => extension_loaded('pcntl'), + 'Sockets' => extension_loaded('sockets'), + 'Zip' => extension_loaded('zip'), + 'BCMath' => extension_loaded('bcmath'), +]; + +// 性能基准 +$benchStart = hrtime(true); +$n = 0; for ($i = 0; $i < 1000000; $i++) $n += $i; +$intTime = round((hrtime(true) - $benchStart) / 1e6, 2); + +$benchStart = hrtime(true); +$s = ''; for ($i = 0; $i < 50000; $i++) $s .= 'a'; +$md5 = md5($s); +$strTime = round((hrtime(true) - $benchStart) / 1e6, 2); + +$benchStart = hrtime(true); +$arr = range(1, 10000); shuffle($arr); sort($arr); +$sortTime = round((hrtime(true) - $benchStart) / 1e6, 2); + +$sessionData = $_SESSION ?? []; +?> + + + + + +PHP 能力展示 + + + +
    +

    🐘 PHP 能力展示

    +

    探索 PHP 在 Android 设备上的完整能力

    +
    +
    PHP 版本
    +
    已加载扩展
    +
    bit
    架构
    +
    操作系统
    +
    +
    +
    +
    +

    📊 系统信息

    + $v): ?> +
    + +
    + +
    +

    ⚡ 性能基准测试

    + $intTime, "字符串操作 (5万次)" => $strTime, "数组排序 (1万元素)" => $sortTime]; + foreach ($benchmarks as $name => $time): + $pct = min(($time / $maxTime) * 100, 100); + ?> +
    + +
    + ms +
    + +
    + +
    +

    ✅ 功能检测

    +
    + $ok): ?> +
    + +
    +
    + +
    +

    🔐 会话管理 (Session)

    +
    + + + +
    + + $v): ?> +
    + +
    + +

    暂无会话数据,试试添加一个!

    + +
    + +
    +

    🧩 已加载扩展 ()

    +
    + + + +
    +
    +
    +
    PHP 能力展示 · PHP · 运行在 Android 设备上
    + + diff --git a/app/src/main/assets/sample_projects/python-django-ar/manage.py b/app/src/main/assets/sample_projects/python-django-ar/manage.py new file mode 100644 index 0000000..2b37e9c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-ar/manage.py @@ -0,0 +1,9 @@ + + +import os, sys +def main(): + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') + from django.core.management import execute_from_command_line + execute_from_command_line(sys.argv) +if __name__ == '__main__': + main() diff --git a/app/src/main/assets/sample_projects/python-django-ar/mysite/__init__.py b/app/src/main/assets/sample_projects/python-django-ar/mysite/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-ar/mysite/settings.py b/app/src/main/assets/sample_projects/python-django-ar/mysite/settings.py new file mode 100644 index 0000000..5ababf7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-ar/mysite/settings.py @@ -0,0 +1,9 @@ +SECRET_KEY = 'demo-secret-key' +DEBUG = True +ALLOWED_HOSTS = ['*'] +INSTALLED_APPS = ['django.contrib.auth', 'django.contrib.contenttypes'] +MIDDLEWARE = [] +ROOT_URLCONF = 'mysite.urls' +WSGI_APPLICATION = 'mysite.wsgi.application' +DATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': 'db.sqlite3'}} +STATIC_URL = 'static/' diff --git a/app/src/main/assets/sample_projects/python-django-ar/mysite/urls.py b/app/src/main/assets/sample_projects/python-django-ar/mysite/urls.py new file mode 100644 index 0000000..9aca924 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-ar/mysite/urls.py @@ -0,0 +1,7 @@ +from django.urls import path +from mysite import views + +urlpatterns = [ + path('', views.dashboard), + path('api/stats', views.api_stats), +] diff --git a/app/src/main/assets/sample_projects/python-django-ar/mysite/views.py b/app/src/main/assets/sample_projects/python-django-ar/mysite/views.py new file mode 100644 index 0000000..ef3ec4b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-ar/mysite/views.py @@ -0,0 +1,113 @@ +""" +لوحة إدارة Django — لوحة إدارة جميلة +""" +import os +import random +from datetime import datetime +from django.http import HttpResponse, JsonResponse + +def dashboard(request): + stats = { + 'users': f'{random.randint(8000,15000):,}', + 'posts': f'{random.randint(2000,5000):,}', + 'comments': f'{random.randint(10000,30000):,}', + 'pageviews': f'{random.randint(80,200)}K', + } + models = [ + {'name': 'User', 'count': random.randint(800, 1500), 'icon': '👤', 'color': '#7c3aed'}, + {'name': 'Post', 'count': random.randint(200, 500), 'icon': '📝', 'color': '#3b82f6'}, + {'name': 'Comment', 'count': random.randint(1000, 3000), 'icon': '💬', 'color': '#10b981'}, + {'name': 'Category', 'count': random.randint(10, 30), 'icon': '📂', 'color': '#f59e0b'}, + {'name': 'Tag', 'count': random.randint(50, 150), 'icon': '🏷️', 'color': '#ec4899'}, + {'name': 'Media', 'count': random.randint(100, 400), 'icon': '🖼️', 'color': '#06b6d4'}, + ] + logs = [ + {'action': 'إنشاء مقال جديد', 'user': 'المدير', 'time': f'{random.randint(2,30)} دقيقة', 'icon': '📝', 'color': '#3b82f6'}, + {'action': 'تحديث الصلاحيات', 'user': 'النظام', 'time': f'{random.randint(1,5)} ساعة', 'icon': '🔐', 'color': '#7c3aed'}, + {'action': 'نشر 3 تعليقات', 'user': 'أحمد', 'time': f'{random.randint(1,3)} ساعة', 'icon': '💬', 'color': '#10b981'}, + {'action': 'رفع 5 صور', 'user': 'فاطمة', 'time': f'{random.randint(2,6)} ساعة', 'icon': '🖼️', 'color': '#06b6d4'}, + {'action': 'نسخ احتياطي', 'user': 'النظام', 'time': 'اليوم 08:00', 'icon': '💾', 'color': '#f59e0b'}, + ] + weekly = [random.randint(40, 100) for _ in range(7)] + max_w = max(weekly) or 1 + week_pct = [int(v / max_w * 85) + 15 for v in weekly] + days = ['إثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة', 'سبت', 'أحد'] + import django + html = f""" + + + + +Django Admin + + + +
    +

    🦄 Django Admin

    لوحة الإدارة

    يعمل
    +
    +
    المستخدمون👥
    {stats['users']}
    ↑ 12.3%
    +
    المقالات📝
    {stats['posts']}
    ↑ 8.7%
    +
    التعليقات💬
    {stats['comments']}
    ↑ 15.1%
    +
    المشاهدات👁️
    {stats['pageviews']}
    ↑ 22.4%
    +
    +
    +
    النشاط الأسبوعي📊 اتجاه
    +
    {''.join(f'
    {days[i]}
    ' for i in range(7))}
    +
    +
    +
    نماذج البيانات📦 {len(models)}
    + {''.join(f'
    {m["icon"]}
    {m["name"]}
    {m["count"]} سجل
    ' for m in models)} +
    +
    +
    سجل العمليات🔔 الأخير
    + {''.join(f'
    {l["icon"]}
    {l["action"]}
    {l["user"]}
    {l["time"]}
    ' for l in logs)} +
    +
    Django {django.get_version()} · Python
    +
    + +""" + return HttpResponse(html) + +def api_stats(request): + return JsonResponse({'status': 'ok', 'data': {'users': random.randint(8000,15000)}, 'framework': 'Django'}) diff --git a/app/src/main/assets/sample_projects/python-django-ar/mysite/wsgi.py b/app/src/main/assets/sample_projects/python-django-ar/mysite/wsgi.py new file mode 100644 index 0000000..b1fc26c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-ar/mysite/wsgi.py @@ -0,0 +1,4 @@ +import os +from django.core.wsgi import get_wsgi_application +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') +application = get_wsgi_application() diff --git a/app/src/main/assets/sample_projects/python-django-ar/requirements.txt b/app/src/main/assets/sample_projects/python-django-ar/requirements.txt new file mode 100644 index 0000000..9516b92 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-ar/requirements.txt @@ -0,0 +1,2 @@ +django==5.0 +gunicorn==21.2.0 diff --git a/app/src/main/assets/sample_projects/python-django-en/manage.py b/app/src/main/assets/sample_projects/python-django-en/manage.py new file mode 100644 index 0000000..2b37e9c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-en/manage.py @@ -0,0 +1,9 @@ + + +import os, sys +def main(): + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') + from django.core.management import execute_from_command_line + execute_from_command_line(sys.argv) +if __name__ == '__main__': + main() diff --git a/app/src/main/assets/sample_projects/python-django-en/mysite/__init__.py b/app/src/main/assets/sample_projects/python-django-en/mysite/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-en/mysite/settings.py b/app/src/main/assets/sample_projects/python-django-en/mysite/settings.py new file mode 100644 index 0000000..5ababf7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-en/mysite/settings.py @@ -0,0 +1,9 @@ +SECRET_KEY = 'demo-secret-key' +DEBUG = True +ALLOWED_HOSTS = ['*'] +INSTALLED_APPS = ['django.contrib.auth', 'django.contrib.contenttypes'] +MIDDLEWARE = [] +ROOT_URLCONF = 'mysite.urls' +WSGI_APPLICATION = 'mysite.wsgi.application' +DATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': 'db.sqlite3'}} +STATIC_URL = 'static/' diff --git a/app/src/main/assets/sample_projects/python-django-en/mysite/urls.py b/app/src/main/assets/sample_projects/python-django-en/mysite/urls.py new file mode 100644 index 0000000..9aca924 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-en/mysite/urls.py @@ -0,0 +1,7 @@ +from django.urls import path +from mysite import views + +urlpatterns = [ + path('', views.dashboard), + path('api/stats', views.api_stats), +] diff --git a/app/src/main/assets/sample_projects/python-django-en/mysite/views.py b/app/src/main/assets/sample_projects/python-django-en/mysite/views.py new file mode 100644 index 0000000..5117d69 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-en/mysite/views.py @@ -0,0 +1,115 @@ +""" +Django Admin Dashboard — Beautiful Admin Panel +Showcases Django's MTV architecture and template rendering +""" +import os +import random +from datetime import datetime +from django.http import HttpResponse, JsonResponse + +def dashboard(request): + stats = { + 'users': f'{random.randint(8000,15000):,}', + 'posts': f'{random.randint(2000,5000):,}', + 'comments': f'{random.randint(10000,30000):,}', + 'pageviews': f'{random.randint(80,200)}K', + } + models = [ + {'name': 'User', 'count': random.randint(800, 1500), 'icon': '👤', 'color': '#7c3aed'}, + {'name': 'Post', 'count': random.randint(200, 500), 'icon': '📝', 'color': '#3b82f6'}, + {'name': 'Comment', 'count': random.randint(1000, 3000), 'icon': '💬', 'color': '#10b981'}, + {'name': 'Category', 'count': random.randint(10, 30), 'icon': '📂', 'color': '#f59e0b'}, + {'name': 'Tag', 'count': random.randint(50, 150), 'icon': '🏷️', 'color': '#ec4899'}, + {'name': 'Media', 'count': random.randint(100, 400), 'icon': '🖼️', 'color': '#06b6d4'}, + ] + logs = [ + {'action': 'Created new post', 'user': 'Admin', 'time': f'{random.randint(2,30)} min ago', 'icon': '📝', 'color': '#3b82f6'}, + {'action': 'Updated user permissions', 'user': 'System', 'time': f'{random.randint(1,5)} hr ago', 'icon': '🔐', 'color': '#7c3aed'}, + {'action': 'Published 3 comments', 'user': 'Alex', 'time': f'{random.randint(1,3)} hr ago', 'icon': '💬', 'color': '#10b981'}, + {'action': 'Uploaded 5 images', 'user': 'Emily', 'time': f'{random.randint(2,6)} hr ago', 'icon': '🖼️', 'color': '#06b6d4'}, + {'action': 'Database backup', 'user': 'System', 'time': 'Today 08:00', 'icon': '💾', 'color': '#f59e0b'}, + ] + weekly = [random.randint(40, 100) for _ in range(7)] + max_w = max(weekly) or 1 + week_pct = [int(v / max_w * 85) + 15 for v in weekly] + days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] + import django + html = f""" + + + + +Django Admin + + + +
    +

    🦄 Django Admin

    Admin Dashboard

    Running
    +
    +
    Users👥
    {stats['users']}
    ↑ 12.3%
    +
    Posts📝
    {stats['posts']}
    ↑ 8.7%
    +
    Comments💬
    {stats['comments']}
    ↑ 15.1%
    +
    Views👁️
    {stats['pageviews']}
    ↑ 22.4%
    +
    +
    +
    Weekly Activity📊 Trend
    +
    {''.join(f'
    {days[i]}
    ' for i in range(7))}
    +
    +
    +
    Data Models📦 {len(models)}
    + {''.join(f'
    {m["icon"]}
    {m["name"]}
    {m["count"]} records
    ' for m in models)} +
    +
    +
    Activity Log🔔 Recent
    + {''.join(f'
    {l["icon"]}
    {l["action"]}
    {l["user"]}
    {l["time"]}
    ' for l in logs)} +
    +
    Django {django.get_version()} · Python · {datetime.now().strftime('%Y-%m-%d')}
    +
    + +""" + return HttpResponse(html) + +def api_stats(request): + return JsonResponse({'status': 'ok', 'data': {'users': random.randint(8000,15000), 'posts': random.randint(2000,5000)}, 'framework': 'Django'}) diff --git a/app/src/main/assets/sample_projects/python-django-en/mysite/wsgi.py b/app/src/main/assets/sample_projects/python-django-en/mysite/wsgi.py new file mode 100644 index 0000000..b1fc26c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-en/mysite/wsgi.py @@ -0,0 +1,4 @@ +import os +from django.core.wsgi import get_wsgi_application +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') +application = get_wsgi_application() diff --git a/app/src/main/assets/sample_projects/python-django-en/requirements.txt b/app/src/main/assets/sample_projects/python-django-en/requirements.txt new file mode 100644 index 0000000..9516b92 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-en/requirements.txt @@ -0,0 +1,2 @@ +django==5.0 +gunicorn==21.2.0 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/AUTHORS b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/AUTHORS new file mode 100644 index 0000000..b1f6c95 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/AUTHORS @@ -0,0 +1,1087 @@ +Django was originally created in late 2003 at World Online, the web division +of the Lawrence Journal-World newspaper in Lawrence, Kansas. + +Here is an inevitably incomplete list of MUCH-APPRECIATED CONTRIBUTORS -- +people who have submitted patches, reported bugs, added translations, helped +answer newbie questions, and generally made Django that much better: + + Aaron Cannon + Aaron Swartz + Aaron T. Myers + Abeer Upadhyay + Abhijeet Viswa + Abhinav Patil + Abhinav Yadav + Abhishek Gautam + Abhyudai + Adam Allred + Adam Bogdał + Adam Donaghy + Adam Johnson + Adam Malinowski + Adam Vandenberg + Ade Lee + Adiyat Mubarak + Adnan Umer + Arslan Noor + Adrian Holovaty + Adrian Torres + Adrien Lemaire + Afonso Fernández Nogueira + AgarFu + Ahmad Alhashemi + Ahmad Al-Ibrahim + Ahmed Eltawela + ajs + Akash Agrawal + Akash Kumar Sen + Akis Kesoglou + Aksel Ethem + Akshesh Doshi + alang@bright-green.com + Alasdair Nicol + Albert Defler + Albert Wang + Alcides Fonseca + Aldian Fazrihady + Aleksandra Sendecka + Aleksi Häkli + Alex Dutton + Alexander Myodov + Alexandr Tatarinov + Alex Aktsipetrov + Alex Becker + Alex Couper + Alex Dedul + Alex Gaynor + Alex Hill + Alex Ogier + Alex Robbins + Alexey Boriskin + Alexey Tsivunin + Ali Vakilzade + Aljaž Košir + Aljosa Mohorovic + Alokik Vijay + Amir Karimi + Amit Chakradeo + Amit Ramon + Amit Upadhyay + A. Murat Eren + Ana Belen Sarabia + Ana Krivokapic + Andi Albrecht + André Ericson + Andrei Kulakov + Andreas + Andreas Mock + Andreas Pelme + Andrés Torres Marroquín + Andrew Brehaut + Andrew Clark + Andrew Durdin + Andrew Godwin + Andrew Pinkham + Andrews Medina + Andrew Northall + Andriy Sokolovskiy + Andy Chosak + Andy Dustman + Andy Gayton + andy@jadedplanet.net + Anssi Kääriäinen + ant9000@netwise.it + Anthony Briggs + Anthony Wright + Anton Samarchyan + Antoni Aloy + Antonio Cavedoni + Antonis Christofides + Antti Haapala + Antti Kaihola + Anubhav Joshi + Anvesh Mishra + Aram Dulyan + arien + Armin Ronacher + Aron Podrigal + Arsalan Ghassemi + Artem Gnilov + Arthur + Arthur Jovart + Arthur Koziel + Arthur Moreira + Arthur Rio + Arvis Bickovskis + Arya Khaligh + Aryeh Leib Taurog + A S Alam + Asif Saif Uddin + atlithorn + Audrey Roy + av0000@mail.ru + Axel Haustant + Aymeric Augustin + Bahadır Kandemir + Baishampayan Ghose + Baptiste Mispelon + Barry Pederson + Bartolome Sanchez Salado + Barton Ip + Bartosz Grabski + Bashar Al-Abdulhadi + Bastian Kleineidam + Batiste Bieler + Batman + Batuhan Taskaya + Baurzhan Ismagulov + Ben Dean Kawamura + Ben Firshman + Ben Godfrey + Benjamin Wohlwend + Ben Khoo + Ben Lomax + Ben Slavin + Ben Sturmfels + Berker Peksag + Bernd Schlapsi + Bernhard Essl + berto + Bhuvnesh Sharma + Bill Fenner + Bjørn Stabell + Bo Marchman + Bogdan Mateescu + Bojan Mihelac + Bouke Haarsma + Božidar Benko + Brad Melin + Brandon Chinn + Brant Harris + Brendan Hayward + Brendan Quinn + Brenton Simpson + Brett Cannon + Brett Hoerner + Brian Beck + Brian Fabian Crain + Brian Harring + Brian Helba + Brian Ray + Brian Rosner + Bruce Kroeze + Bruno Alla + Bruno Renié + brut.alll@gmail.com + Bryan Chow + Bryan Veloso + bthomas + btoll@bestweb.net + C8E + Caio Ariede + Calvin Spealman + Cameron Curry + Cameron Knight (ckknight) + Can Burak Çilingir + Can Sarıgöl + Carl Meyer + Carles Pina i Estany + Carlos Eduardo de Paula + Carlos Matías de la Torre + Carlton Gibson + cedric@terramater.net + Chad Whitman + ChaosKCW + Charlie Leifer + charly.wilhelm@gmail.com + Chason Chaffin + Cheng Zhang + Chris Adams + Chris Beaven + Chris Bennett + Chris Cahoon + Chris Chamberlin + Chris Jerdonek + Chris Jones + Chris Lamb + Chris Streeter + Christian Barcenas + Christian Metts + Christian Oudard + Christian Tanzer + Christoffer Sjöbergsson + Christophe Pettus + Christopher Adams + Christopher Babiak + Christopher Lenz + Christoph Mędrela + Chris Wagner + Chris Wesseling + Chris Wilson + Ciaran McCormick + Claude Paroz + Clint Ecker + colin@owlfish.com + Colin Wood + Collin Anderson + Collin Grady + Colton Hicks + Craig Blaszczyk + crankycoder@gmail.com + Curtis Maloney (FunkyBob) + dackze+django@gmail.com + Dagur Páll Ammendrup + Dane Springmeyer + Dan Fairs + Daniel Alves Barbosa de Oliveira Vaz + Daniel Duan + Daniele Procida + Daniel Fairhead + Daniel Greenfeld + dAniel hAhler + Daniel Jilg + Daniel Lindsley + Daniel Poelzleithner + Daniel Pyrathon + Daniel Roseman + Daniel Tao + Daniel Wiesmann + Danilo Bargen + Dan Johnson + Dan Palmer + Dan Poirier + Dan Stephenson + Dan Watson + dave@thebarproject.com + David Ascher + David Avsajanishvili + David Blewett + David Brenneman + David Cramer + David Danier + David Eklund + David Foster + David Gouldin + david@kazserve.org + David Krauth + David Larlet + David Reynolds + David Sanders + David Schein + David Tulig + David Winterbottom + David Wobrock + Davide Ceretti + Deep L. Sukhwani + Deepak Thukral + Denis Kuzmichyov + Dennis Schwertel + Derek Willis + Deric Crago + deric@monowerks.com + Deryck Hodge + Dimitris Glezos + Dirk Datzert + Dirk Eschler + Dmitri Fedortchenko + Dmitry Jemerov + dne@mayonnaise.net + Dolan Antenucci + Donald Harvey + Donald Stufft + Don Spaulding + Doug Beck + Doug Napoleone + dready + Durval Carvalho de Souza + dusk@woofle.net + Dustyn Gibson + Ed Morley + Egidijus Macijauskas + eibaan@gmail.com + elky + Emmanuelle Delescolle + Emil Stenström + enlight + Enrico + Eric Boersma + Eric Brandwein + Eric Floehr + Eric Florenzano + Eric Holscher + Eric Moritz + Eric Palakovich Carr + Erik Karulf + Erik Romijn + eriks@win.tue.nl + Erwin Junge + Esdras Beleza + Espen Grindhaug + Étienne Beaulé + Eugene Lazutkin + Evan Grim + Fabian Büchler + Fabrice Aneche + Faishal Manzar + Farhaan Bukhsh + favo@exoweb.net + fdr + Federico Capoano + Felipe Lee + Filip Noetzel + Filip Wasilewski + Finn Gruwier Larsen + Fiza Ashraf + Flávio Juvenal da Silva Junior + flavio.curella@gmail.com + Florian Apolloner + Florian Demmer + Florian Moussous + fnaimi66 + Fran Hrženjak + Francesco Panico + Francisco Albarran Cristobal + Francisco Couzo + François Freitag + Frank Tegtmeyer + Frank Wierzbicki + Frank Wiles + František Malina + Fraser Nevett + Gabriel Grant + Gabriel Hurley + gandalf@owca.info + Garry Lawrence + Garry Polley + Garth Kidd + Gary Wilson + Gasper Koren + Gasper Zejn + Gav O'Connor + Gavin Wahl + Ge Hanbin + geber@datacollect.com + Geert Vanderkelen + George Karpenkov + George Song + George Vilches + Georg "Hugo" Bauer + Georgi Stanojevski + Gerardo Orozco + Gil Gonçalves + Girish Kumar + Girish Sontakke + Gisle Aas + Glenn Maynard + glin@seznam.cz + GomoX + Gonzalo Saavedra + Gopal Narayanan + Graham Carlyle + Grant Jenks + Greg Chapple + Greg Twohig + Gregor Allensworth + Gregor Müllegger + Grigory Fateyev + Grzegorz Ślusarek + Guilherme Mesquita Gondim + Guillaume Pannatier + Gustavo Picon + hambaloney + Hang Park + Hannes Ljungberg + Hannes Struß + Hao Dong + Harm Geerts + Hasan Ramezani + Hawkeye + Helen Sherwood-Taylor + Henrique Romano + Henry Dang + Hidde Bultsma + Himanshu Chauhan + hipertracker@gmail.com + Hiroki Kiyohara + Honza Král + Horst Gutmann + Hugo Osvaldo Barrera + HyukJin Jang + Hyun Mi Ae + Iacopo Spalletti + Ian A Wilson + Ian Clelland + Ian G. Kelly + Ian Holsman + Ian Lee + Ibon + Idan Gazit + Idan Melamed + Ifedapo Olarewaju + Igor Kolar + Illia Volochii + Ilya Bass + Ilya Semenov + Ingo Klöcker + I.S. van Oostveen + Iuri de Silvio + ivan.chelubeev@gmail.com + Ivan Sagalaev (Maniac) + Jaap Roes + Jack Moffitt + Jacob Burch + Jacob Green + Jacob Kaplan-Moss + Jacob Rief + Jacob Walls + Jakub Bagiński + Jakub Paczkowski + Jakub Wilk + Jakub Wiśniowski + james_027@yahoo.com + James Aylett + James Bennett + James Gillard + James Murty + James Tauber + James Timmins + James Turk + James Wheare + Jamie Matthews + Jannis Leidel + Janos Guljas + Jan Pazdziora + Jan Rademaker + Jarek Głowacki + Jarek Zgoda + Jarosław Wygoda + Jason Davies (Esaj) + Jason Huggins + Jason McBrayer + jason.sidabras@gmail.com + Jason Yan + Javier Mansilla + Jay Parlar + Jay Welborn + Jay Wineinger + J. Clifford Dyer + jcrasta@gmail.com + jdetaeye + Jeff Anderson + Jeff Balogh + Jeff Hui + Jeffrey Gelens + Jeff Triplett + Jeffrey Yancey + Jens Diemer + Jens Page + Jensen Cochran + Jeong-Min Lee + Jérémie Blaser + Jeremy Bowman + Jeremy Carbaugh + Jeremy Dunck + Jeremy Lainé + Jerin Peter George + Jesse Young + Jezeniel Zapanta + jhenry + Jim Dalton + Jimmy Song + Jiri Barton + Joachim Jablon + Joao Oliveira + Joao Pedro Silva + Joe Heck + Joe Jackson + Joel Bohman + Joel Heenan + Joel Watts + Joe Topjian + Johan C. Stöver + Johann Queuniet + john@calixto.net + John D'Agostino + John D'Ambrosio + John Huddleston + John Moses + John Paulett + John Shaffer + Jökull Sólberg Auðunsson + Jon Dufresne + Jon Janzen + Jonas Haag + Jonas Lundberg + Jonathan Davis + Jonatas C. D. + Jonathan Buchanan + Jonathan Daugherty (cygnus) + Jonathan Feignberg + Jonathan Slenders + Jonny Park + Jordan Bae + Jordan Dimov + Jordi J. Tablada + Jorge Bastida + Jorge Gajon + José Tomás Tocino García + Josef Rousek + Joseph Kocherhans + Josh Smeaton + Joshua Cannon + Joshua Ginsberg + Jozko Skrablin + J. Pablo Fernandez + jpellerin@gmail.com + Juan Catalano + Juan Manuel Caicedo + Juan Pedro Fisanotti + Julia Elman + Julia Matsieva + Julian Bez + Julie Rymer + Julien Phalip + Junyoung Choi + junzhang.jn@gmail.com + Jure Cuhalev + Justin Bronn + Justine Tunney + Justin Lilly + Justin Michalicek + Justin Myles Holmes + Jyrki Pulliainen + Kacper Wolkiewicz + Kadesarin Sanjek + Kapil Bansal + Karderio + Karen Tracey + Karol Sikora + Katherine “Kati” Michel + Kathryn Killebrew + Katie Miller + Keith Bussell + Kenneth Love + Kent Hauser + Keryn Knight + Kevin Grinberg + Kevin Kubasik + Kevin McConnell + Kieran Holland + kilian + Kim Joon Hwan 김준환 + Kim Soung Ryoul 김성렬 + Klaas van Schelven + knox + konrad@gwu.edu + Kowito Charoenratchatabhan + Krišjānis Vaiders + krzysiek.pawlik@silvermedia.pl + Krzysztof Jagiello + Krzysztof Jurewicz + Krzysztof Kulewski + kurtiss@meetro.com + Lakin Wecker + Lars Yencken + Lau Bech Lauritzen + Laurent Luce + Laurent Rahuel + lcordier@point45.com + Leah Culver + Leandra Finger + Lee Reilly + Lee Sanghyuck + Leo "hylje" Honkanen + Leo Shklovskii + Leo Soto + lerouxb@gmail.com + Lex Berezhny + Liang Feng + Lily Foote + limodou + Lincoln Smith + Liu Yijie <007gzs@gmail.com> + Loek van Gent + Loïc Bistuer + Lowe Thiderman + Luan Pablo + Lucas Connors + Luciano Ramalho + Lucidiot + Ludvig Ericson + Luis C. Berrocal + Łukasz Langa + Łukasz Rekucki + Luke Granger-Brown + Luke Plant + Maciej Fijalkowski + Maciej Wiśniowski + Mads Jensen + Makoto Tsuyuki + Malcolm Tredinnick + Manav Agarwal + Manuel Saelices + Manuzhai + Marc Aymerich Gubern + Marc Egli + Marcel Telka + Marcelo Galigniana + Marc Fargas + Marc Garcia + Marcin Wróbel + Marc Remolt + Marc Seguí Coll + Marc Tamlyn + Marc-Aurèle Brothier + Marian Andre + Marijn Vriens + Mario Gonzalez + Mariusz Felisiak + Mark Biggers + Mark Evans + Mark Gensler + mark@junklight.com + Mark Lavin + Mark Sandstrom + Markus Amalthea Magnuson + Markus Holtermann + Marten Kenbeek + Marti Raudsepp + martin.glueck@gmail.com + Martin Green + Martin Kosír + Martin Mahner + Martin Maney + Martin von Gagern + Mart Sõmermaa + Marty Alchin + Masashi Shibata + masonsimon+django@gmail.com + Massimiliano Ravelli + Massimo Scamarcia + Mathieu Agopian + Matías Bordese + Matt Boersma + Matt Brewer + Matt Croydon + Matt Deacalion Stevens + Matt Dennenbaum + Matthew Flanagan + Matthew Schinckel + Matthew Somerville + Matthew Tretter + Matthew Wilkes + Matthias Kestenholz + Matthias Pronk + Matt Hoskins + Matt McClanahan + Matt Riggott + Matt Robenolt + Mattia Larentis + Mattia Procopio + Mattias Loverot + mattycakes@gmail.com + Max Burstein + Max Derkachev + Max Smolens + Maxime Lorant + Maxime Toussaint + Maxime Turcotte + Maximilian Merz + Maximillian Dornseif + mccutchen@gmail.com + Meghana Bhange + Meir Kriheli + Michael S. Brown + Michael Hall + Michael Josephson + Michael Lissner + Michael Manfre + michael.mcewan@gmail.com + Michael Placentra II + Michael Radziej + Michael Sanders + Michael Schwarz + Michael Sinov + Michael Thornhill + Michal Chruszcz + michal@plovarna.cz + Michał Modzelewski + Mihai Damian + Mihai Preda + Mikaël Barbero + Mike Axiak + Mike Grouchy + Mike Malone + Mike Richardson + Mike Wiacek + Mikhail Korobov + Mikko Hellsing + Mikołaj Siedlarek + milkomeda + Milton Waddams + mitakummaa@gmail.com + mmarshall + Moayad Mardini + Morgan Aubert + Moritz Sichert + Morten Bagai + msaelices + msundstr + Mushtaq Ali + Mykola Zamkovoi + Nadège Michel + Nagy Károly + Nasimul Haque + Nasir Hussain + Natalia Bidart + Nate Bragg + Nathan Gaberel + Neal Norwitz + Nebojša Dorđević + Ned Batchelder + Nena Kojadin + Niall Dalton + Niall Kelly + Nick Efford + Nick Lane + Nick Pope + Nick Presta + Nick Sandford + Nick Sarbicki + Niclas Olofsson + Nicola Larosa + Nicolas Lara + Nicolas Noé + Nikita Marchant + Nikita Sobolev + Niran Babalola + Nis Jørgensen + Nowell Strite + Nuno Mariz + Octavio Peri + oggie rob + oggy + Oguzhan Akan + Oliver Beattie + Oliver Rutherfurd + Olivier Le Thanh Duong + Olivier Sels + Olivier Tabone + Orestis Markou + Orne Brocaar + Oscar Ramirez + Ossama M. Khayat + Owen Griffiths + Ömer Faruk Abacı + Pablo Martín + Panos Laganakos + Paolo Melchiorre + Pascal Hartig + Pascal Varet + Patrik Sletmo + Paul Bissex + Paul Collier + Paul Collins + Paul Donohue + Paul Lanier + Paul McLanahan + Paul McMillan + Paulo Poiati + Paulo Scardine + Paul Smith + Pavel Kulikov + pavithran s + Pavlo Kapyshin + permonik@mesias.brnonet.cz + Petar Marić + Pete Crosier + peter@mymart.com + Peter Sheats + Peter van Kampen + Peter Zsoldos + Pete Shinners + Petr Marhoun + Petter Strandmark + pgross@thoughtworks.com + phaedo + phil.h.smith@gmail.com + Philip Lindborg + Philippe Raoult + phil@produxion.net + Piotr Jakimiak + Piotr Lewandowski + plisk + polpak@yahoo.com + pradeep.gowda@gmail.com + Preston Holmes + Preston Timmons + Priyank Panchal + Priyansh Saxena + Przemysław Buczkowski + Przemysław Suliga + Qi Zhao + Rachel Tobin + Rachel Willmer + Radek Švarz + Rafael Giebisch + Raffaele Salmaso + Rahmat Faisal + Rajesh Dhawan + Ramez Ashraf + Ramil Yanbulatov + Ramin Farajpour Cami + Ramiro Morales + Ramon Saraiva + Ram Rachum + Randy Barlow + Raphaël Barrois + Raphael Michel + Raúl Cumplido + Rebecca Smith + Remco Wendt + Renaud Parent + Renbi Yu + Reza Mohammadi + rhettg@gmail.com + Ricardo Javier Cárdenes Medina + ricardojbarrios@gmail.com + Riccardo Di Virgilio + Riccardo Magliocchetti + Richard Davies + Richard House + Rick Wagner + Rigel Di Scala + Robert Coup + Robert Myers + Roberto Aguilar + Robert Rock Howard + Robert Wittams + Rob Golding-Day + Rob Hudson + Rob Nguyen + Robin Munn + Rodrigo Pinheiro Marques de Araújo + Rohith P R + Romain Garrigues + Ronnie van den Crommenacker + Ronny Haryanto + Ross Poulton + Roxane Bellot + Rozza + Rudolph Froger + Rudy Mutter + Rune Rønde Laursen + Russell Cloran + Russell Keith-Magee + Russ Webber + Ryan Hall + Ryan Heard + ryankanno + Ryan Kelly + Ryan Niemeyer + Ryan Petrello + Ryan Rubin + Ryno Mathee + Sachin Jat + Sage M. Abdullah + Sam Newman + Sander Dijkhuis + Sanket Saurav + Sanyam Khurana + Sarah Abderemane + Sarah Boyce + Sarthak Mehrish + schwank@gmail.com + Scot Hacker + Scott Barr + Scott Cranfill + Scott Fitsimones + Scott Pashley + scott@staplefish.com + Sean Brant + Sebastian Hillig + Sebastian Spiegel + Segyo Myung + Selwin Ong + Sengtha Chay + Senko Rašić + serbaut@gmail.com + Sergei Maertens + Sergey Fedoseev + Sergey Kolosov + Seth Hill + Shai Berger + Shannon -jj Behrens + Shawn Milochik + Shreya Bamne + Silvan Spross + Simeon Visser + Simon Blanchard + Simon Charette + Simon Greenhill + Simon Litchfield + Simon Meers + Simon Williams + Simon Willison + Sjoerd Job Postmus + Slawek Mikula + sloonz + smurf@smurf.noris.de + sopel + Sreehari K V + Sridhar Marella + Srinivas Reddy Thatiparthy + Stanislas Guerra + Stanislaus Madueke + Stanislav Karpov + starrynight + Stefan R. Filipek + Stefane Fermgier + Stefano Rivera + Stéphane Raimbault + Stephan Jaekel + Stephen Burrows + Steven L. Smith (fvox13) + Steven Noorbergen (Xaroth) + Stuart Langridge + Subhav Gautam + Sujay S Kumar + Sune Kirkeby + Sung-Jin Hong + SuperJared + Susan Tan + Sutrisno Efendi + Swaroop C H + Szilveszter Farkas + Taavi Teska + Tai Lee + Takashi Matsuo + Tareque Hossain + Taylor Mitchell + tell-k + Terry Huang + thebjorn + Thejaswi Puthraya + Thijs van Dien + Thom Wiggers + Thomas Chaumeny + Thomas Güttler + Thomas Kerpe + Thomas Sorrel + Thomas Steinacher + Thomas Stromberg + Thomas Tanner + tibimicu@gmx.net + Ties Jan Hefting + Tim Allen + Tim Givois + Tim Graham + Tim Heap + Tim McCurrach + Tim Saylor + Toan Vuong + Tobias Kunze + Tobias McNulty + tobias@neuyork.de + Todd O'Bryan + Tom Carrick + Tom Christie + Tom Forbes + Tom Insam + Tom Tobin + Tom Wojcik + Tomáš Ehrlich + Tomáš Kopeček + Tome Cvitan + Tomek Paczkowski + Tomer Chachamu + Tommy Beadle + Tore Lundqvist + torne-django@wolfpuppy.org.uk + Travis Cline + Travis Pinney + Travis Swicegood + Travis Terry + Trevor Caira + Trey Long + tstromberg@google.com + tt@gurgle.no + Tyler Tarabula + Tyson Clugg + Tyson Tate + Unai Zalakain + Valentina Mukhamedzhanova + valtron + Vasiliy Stavenko + Vasil Vangelovski + Vibhu Agarwal + Victor Andrée + viestards.lists@gmail.com + Viktor Danyliuk + Viktor Grabov + Ville Säävuori + Vinay Karanam + Vinay Sajip + Vincent Foley + Vinny Do + Vitaly Babiy + Vitaliy Yelnik + Vladimir Kuzma + Vlado + Vsevolod Solovyov + Vytis Banaitis + wam-djangobug@wamber.net + Wang Chun + Warren Smith + Waylan Limberg + Wiktor Kołodziej + Wiley Kestner + Wiliam Alves de Souza + Will Ayd + William Schwartz + Will Hardy + Will Zhao + Wilson Miner + Wim Glenn + wojtek + Wu Haotian + Xavier Francisco + Xia Kai + Yann Fouillat + Yann Malet + Yash Jhunjhunwala + Yasushi Masuda + ye7cakf02@sneakemail.com + ymasuda@ethercube.com + Yoong Kang Lim + Yury V. Zaytsev + Yusuke Miyazaki + Yves Weissig + yyyyyyyan + Zac Hatfield-Dodds + Zachary Voase + Zach Liu + Zach Thompson + Zain Memon + Zain Patel + Zak Johnson + Žan Anderle + Zbigniew Siciarz + zegor + Zeynel Özdemir + Zlatko Mašek + zriv + + +A big THANK YOU goes to: + + Rob Curley and Ralph Gage for letting us open-source Django. + + Frank Wiles for making excellent arguments for open-sourcing, and for + his sage sysadmin advice. + + Ian Bicking for convincing Adrian to ditch code generation. + + Mark Pilgrim for "Dive Into Python" (https://www.diveinto.org/python3/). + + Guido van Rossum for creating Python. diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/INSTALLER b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/LICENSE b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/LICENSE new file mode 100644 index 0000000..5f4f225 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) Django Software Foundation and individual contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of Django nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/LICENSE.python b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/LICENSE.python new file mode 100644 index 0000000..a25ce5c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/LICENSE.python @@ -0,0 +1,290 @@ +Django is licensed under the three-clause BSD license; see the file +LICENSE for details. + +Django includes code from the Python standard library, which is licensed under +the Python license, a permissive open source license. The copyright and license +is included below for compliance with Python's terms. + +---------------------------------------------------------------------- + +Copyright (c) 2001-present Python Software Foundation; All Rights Reserved + +A. HISTORY OF THE SOFTWARE +========================== + +Python was created in the early 1990s by Guido van Rossum at Stichting +Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands +as a successor of a language called ABC. Guido remains Python's +principal author, although it includes many contributions from others. + +In 1995, Guido continued his work on Python at the Corporation for +National Research Initiatives (CNRI, see http://www.cnri.reston.va.us) +in Reston, Virginia where he released several versions of the +software. + +In May 2000, Guido and the Python core development team moved to +BeOpen.com to form the BeOpen PythonLabs team. In October of the same +year, the PythonLabs team moved to Digital Creations, which became +Zope Corporation. In 2001, the Python Software Foundation (PSF, see +https://www.python.org/psf/) was formed, a non-profit organization +created specifically to own Python-related Intellectual Property. +Zope Corporation was a sponsoring member of the PSF. + +All Python releases are Open Source (see http://www.opensource.org for +the Open Source Definition). Historically, most, but not all, Python +releases have also been GPL-compatible; the table below summarizes +the various releases. + + Release Derived Year Owner GPL- + from compatible? (1) + + 0.9.0 thru 1.2 1991-1995 CWI yes + 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes + 1.6 1.5.2 2000 CNRI no + 2.0 1.6 2000 BeOpen.com no + 1.6.1 1.6 2001 CNRI yes (2) + 2.1 2.0+1.6.1 2001 PSF no + 2.0.1 2.0+1.6.1 2001 PSF yes + 2.1.1 2.1+2.0.1 2001 PSF yes + 2.1.2 2.1.1 2002 PSF yes + 2.1.3 2.1.2 2002 PSF yes + 2.2 and above 2.1.1 2001-now PSF yes + +Footnotes: + +(1) GPL-compatible doesn't mean that we're distributing Python under + the GPL. All Python licenses, unlike the GPL, let you distribute + a modified version without making your changes open source. The + GPL-compatible licenses make it possible to combine Python with + other software that is released under the GPL; the others don't. + +(2) According to Richard Stallman, 1.6.1 is not GPL-compatible, + because its license has a choice of law clause. According to + CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1 + is "not incompatible" with the GPL. + +Thanks to the many outside volunteers who have worked under Guido's +direction to make these releases possible. + + +B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON +=============================================================== + +Python software and documentation are licensed under the +Python Software Foundation License Version 2. + +Starting with Python 3.8.6, examples, recipes, and other code in +the documentation are dual licensed under the PSF License Version 2 +and the Zero-Clause BSD license. + +Some software incorporated into Python is under different licenses. +The licenses are listed with code falling under that license. + + +PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 +-------------------------------------------- + +1. This LICENSE AGREEMENT is between the Python Software Foundation +("PSF"), and the Individual or Organization ("Licensee") accessing and +otherwise using this software ("Python") in source or binary form and +its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, PSF hereby +grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, +analyze, test, perform and/or display publicly, prepare derivative works, +distribute, and otherwise use Python alone or in any derivative version, +provided, however, that PSF's License Agreement and PSF's notice of copyright, +i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022 Python Software Foundation; +All Rights Reserved" are retained in Python alone or in any derivative version +prepared by Licensee. + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python. + +4. PSF is making Python available to Licensee on an "AS IS" +basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. Nothing in this License Agreement shall be deemed to create any +relationship of agency, partnership, or joint venture between PSF and +Licensee. This License Agreement does not grant permission to use PSF +trademarks or trade name in a trademark sense to endorse or promote +products or services of Licensee, or any third party. + +8. By copying, installing or otherwise using Python, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. + + +BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 +------------------------------------------- + +BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 + +1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an +office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the +Individual or Organization ("Licensee") accessing and otherwise using +this software in source or binary form and its associated +documentation ("the Software"). + +2. Subject to the terms and conditions of this BeOpen Python License +Agreement, BeOpen hereby grants Licensee a non-exclusive, +royalty-free, world-wide license to reproduce, analyze, test, perform +and/or display publicly, prepare derivative works, distribute, and +otherwise use the Software alone or in any derivative version, +provided, however, that the BeOpen Python License is retained in the +Software, alone or in any derivative version prepared by Licensee. + +3. BeOpen is making the Software available to Licensee on an "AS IS" +basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE +SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS +AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY +DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +5. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +6. This License Agreement shall be governed by and interpreted in all +respects by the law of the State of California, excluding conflict of +law provisions. Nothing in this License Agreement shall be deemed to +create any relationship of agency, partnership, or joint venture +between BeOpen and Licensee. This License Agreement does not grant +permission to use BeOpen trademarks or trade names in a trademark +sense to endorse or promote products or services of Licensee, or any +third party. As an exception, the "BeOpen Python" logos available at +http://www.pythonlabs.com/logos.html may be used according to the +permissions granted on that web page. + +7. By copying, installing or otherwise using the software, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. + + +CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 +--------------------------------------- + +1. This LICENSE AGREEMENT is between the Corporation for National +Research Initiatives, having an office at 1895 Preston White Drive, +Reston, VA 20191 ("CNRI"), and the Individual or Organization +("Licensee") accessing and otherwise using Python 1.6.1 software in +source or binary form and its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, CNRI +hereby grants Licensee a nonexclusive, royalty-free, world-wide +license to reproduce, analyze, test, perform and/or display publicly, +prepare derivative works, distribute, and otherwise use Python 1.6.1 +alone or in any derivative version, provided, however, that CNRI's +License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) +1995-2001 Corporation for National Research Initiatives; All Rights +Reserved" are retained in Python 1.6.1 alone or in any derivative +version prepared by Licensee. Alternately, in lieu of CNRI's License +Agreement, Licensee may substitute the following text (omitting the +quotes): "Python 1.6.1 is made available subject to the terms and +conditions in CNRI's License Agreement. This Agreement together with +Python 1.6.1 may be located on the internet using the following +unique, persistent identifier (known as a handle): 1895.22/1013. This +Agreement may also be obtained from a proxy server on the internet +using the following URL: http://hdl.handle.net/1895.22/1013". + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python 1.6.1 or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python 1.6.1. + +4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" +basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. This License Agreement shall be governed by the federal +intellectual property law of the United States, including without +limitation the federal copyright law, and, to the extent such +U.S. federal law does not apply, by the law of the Commonwealth of +Virginia, excluding Virginia's conflict of law provisions. +Notwithstanding the foregoing, with regard to derivative works based +on Python 1.6.1 that incorporate non-separable material that was +previously distributed under the GNU General Public License (GPL), the +law of the Commonwealth of Virginia shall govern this License +Agreement only as to issues arising under or with respect to +Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this +License Agreement shall be deemed to create any relationship of +agency, partnership, or joint venture between CNRI and Licensee. This +License Agreement does not grant permission to use CNRI trademarks or +trade name in a trademark sense to endorse or promote products or +services of Licensee, or any third party. + +8. By clicking on the "ACCEPT" button where indicated, or by copying, +installing or otherwise using Python 1.6.1, Licensee agrees to be +bound by the terms and conditions of this License Agreement. + + ACCEPT + + +CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 +-------------------------------------------------- + +Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, +The Netherlands. All rights reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +ZERO-CLAUSE BSD LICENSE FOR CODE IN THE PYTHON DOCUMENTATION +---------------------------------------------------------------------- + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/METADATA b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/METADATA new file mode 100644 index 0000000..5a3f8d9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/METADATA @@ -0,0 +1,100 @@ +Metadata-Version: 2.1 +Name: Django +Version: 5.0 +Summary: A high-level Python web framework that encourages rapid development and clean, pragmatic design. +Home-page: https://www.djangoproject.com/ +Author: Django Software Foundation +Author-email: foundation@djangoproject.com +License: BSD-3-Clause +Project-URL: Documentation, https://docs.djangoproject.com/ +Project-URL: Release notes, https://docs.djangoproject.com/en/stable/releases/ +Project-URL: Funding, https://www.djangoproject.com/fundraising/ +Project-URL: Source, https://github.com/django/django +Project-URL: Tracker, https://code.djangoproject.com/ +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Framework :: Django +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Topic :: Internet :: WWW/HTTP +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI +Classifier: Topic :: Software Development :: Libraries :: Application Frameworks +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Requires-Python: >=3.10 +License-File: LICENSE +License-File: LICENSE.python +License-File: AUTHORS +Requires-Dist: asgiref >=3.7.0 +Requires-Dist: sqlparse >=0.3.1 +Requires-Dist: tzdata ; sys_platform == "win32" +Provides-Extra: argon2 +Requires-Dist: argon2-cffi >=19.1.0 ; extra == 'argon2' +Provides-Extra: bcrypt +Requires-Dist: bcrypt ; extra == 'bcrypt' + +====== +Django +====== + +Django is a high-level Python web framework that encourages rapid development +and clean, pragmatic design. Thanks for checking it out. + +All documentation is in the "``docs``" directory and online at +https://docs.djangoproject.com/en/stable/. If you're just getting started, +here's how we recommend you read the docs: + +* First, read ``docs/intro/install.txt`` for instructions on installing Django. + +* Next, work through the tutorials in order (``docs/intro/tutorial01.txt``, + ``docs/intro/tutorial02.txt``, etc.). + +* If you want to set up an actual deployment server, read + ``docs/howto/deployment/index.txt`` for instructions. + +* You'll probably want to read through the topical guides (in ``docs/topics``) + next; from there you can jump to the HOWTOs (in ``docs/howto``) for specific + problems, and check out the reference (``docs/ref``) for gory details. + +* See ``docs/README`` for instructions on building an HTML version of the docs. + +Docs are updated rigorously. If you find any problems in the docs, or think +they should be clarified in any way, please take 30 seconds to fill out a +ticket here: https://code.djangoproject.com/newticket + +To get more help: + +* Join the ``#django`` channel on ``irc.libera.chat``. Lots of helpful people + hang out there. `Webchat is available `_. + +* Join the django-users mailing list, or read the archives, at + https://groups.google.com/group/django-users. + +* Join the `Django Discord community `_. + +* Join the community on the `Django Forum `_. + +To contribute to Django: + +* Check out https://docs.djangoproject.com/en/dev/internals/contributing/ for + information about getting involved. + +To run Django's test suite: + +* Follow the instructions in the "Unit tests" section of + ``docs/internals/contributing/writing-code/unit-tests.txt``, published online at + https://docs.djangoproject.com/en/dev/internals/contributing/writing-code/unit-tests/#running-the-unit-tests + +Supporting the Development of Django +==================================== + +Django's development depends on your contributions. + +If you depend on Django, remember to support the Django Software Foundation: https://www.djangoproject.com/fundraising/ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/RECORD b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/RECORD new file mode 100644 index 0000000..0682a47 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/RECORD @@ -0,0 +1,3656 @@ +../../bin/django-admin,sha256=AcceQkxQAnNa7F93-Bspibv0FhLLFyvn77mFrTxRTX0,239 +Django-5.0.dist-info/AUTHORS,sha256=u4ktEfQXpxDA7MhQFmNbk27ISoqKdMb5CqxKsBbKZn4,42253 +Django-5.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +Django-5.0.dist-info/LICENSE,sha256=uEZBXRtRTpwd_xSiLeuQbXlLxUbKYSn5UKGM0JHipmk,1552 +Django-5.0.dist-info/LICENSE.python,sha256=pSxfIaEVix6-28uSiusYmITnfjxeOIw41mDVk-cf7x8,14383 +Django-5.0.dist-info/METADATA,sha256=upzWgi6Io674ROV_5Kyo0GeCIDoJLq43VywlsDJWIgY,4125 +Django-5.0.dist-info/RECORD,, +Django-5.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +Django-5.0.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92 +Django-5.0.dist-info/entry_points.txt,sha256=hi1U04jQDqr9xaV6Gklnqh-d69jiCZdS73E0l_671L4,82 +Django-5.0.dist-info/top_level.txt,sha256=V_goijg9tfO20ox_7os6CcnPvmBavbxu46LpJiNLwjA,7 +django/__init__.py,sha256=otC-IlUaEEtpAyiFTG3cmyXscgj6Xj1W8b707-o5erE,799 +django/__main__.py,sha256=9a5To1vQXqf2Jg_eh8nLvIc0GXmDjEXv4jE1QZEqBFk,211 +django/apps/__init__.py,sha256=8WZTI_JnNuP4tyfuimH3_pKQYbDAy2haq-xkQT1UXkc,90 +django/apps/config.py,sha256=1Zhxt4OrwRnOmsT_B_BurImz3oi8330TJG0rRRJ58bQ,11482 +django/apps/registry.py,sha256=rdexON5JuhKAMWAZv4k2DH0fRSKdPZoi6_tTjOUgFRA,17693 +django/conf/__init__.py,sha256=EQgR2WOeXLAoJSZR3baLFqInik_0WfOS2pas1q76PDM,13520 +django/conf/app_template/__init__.py-tpl,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/app_template/admin.py-tpl,sha256=suMo4x8I3JBxAFBVIdE-5qnqZ6JAZV0FESABHOSc-vg,63 +django/conf/app_template/apps.py-tpl,sha256=jrRjsh9lSkUvV4NnKdlAhLDtvydwBNjite0w2J9WPtI,171 +django/conf/app_template/migrations/__init__.py-tpl,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/app_template/models.py-tpl,sha256=Vjc0p2XbAPgE6HyTF6vll98A4eDhA5AvaQqsc4kQ9AQ,57 +django/conf/app_template/tests.py-tpl,sha256=mrbGGRNg5jwbTJtWWa7zSKdDyeB4vmgZCRc2nk6VY-g,60 +django/conf/app_template/views.py-tpl,sha256=xc1IQHrsij7j33TUbo-_oewy3vs03pw_etpBWaMYJl0,63 +django/conf/global_settings.py,sha256=6gBhUhQfG_lfN49xS0GLfiShehHZjBOIEg5ynkpDQH8,23154 +django/conf/locale/__init__.py,sha256=B9QaZacT1yFDOlsBHGvrRWE32ASKrtvi6PgUKjxBUhg,13864 +django/conf/locale/af/LC_MESSAGES/django.mo,sha256=tovK2PvTAeNaPSKwgok_EOQcinHawLaRbTkpfKCOaWc,24608 +django/conf/locale/af/LC_MESSAGES/django.po,sha256=XWu70t19zrRdOU1TNdlg3gJlZFMRpkHJDNisIoGPx0I,28689 +django/conf/locale/ar/LC_MESSAGES/django.mo,sha256=qBaEPhfJxd2mK1uPH7J06hPI3_leRPsWkVgcKtJSAvQ,35688 +django/conf/locale/ar/LC_MESSAGES/django.po,sha256=MQeB4q0H-uDLurniJP5b2SBOTETAUl9k9NHxtaw0nnU,38892 +django/conf/locale/ar/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/ar/formats.py,sha256=EI9DAiGt1avNY-a6luMnAqKISKGHXHiKE4QLRx7wGHU,696 +django/conf/locale/ar_DZ/LC_MESSAGES/django.mo,sha256=QosXYYYvQjGu13pLrC9LIVwUQXVwdJpIYn7RB9QCJY8,33960 +django/conf/locale/ar_DZ/LC_MESSAGES/django.po,sha256=2iT_sY4XedSSiHagu03OgpYXWNJVaKDwKUfxgEN4k3k,37626 +django/conf/locale/ar_DZ/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/ar_DZ/formats.py,sha256=T84q3oMKng-L7_xymPqYwpzs78LvvfHy2drfSRj8XjE,901 +django/conf/locale/ast/LC_MESSAGES/django.mo,sha256=XSStt50HP-49AJ8wFcnbn55SLncJCsS2lx_4UwK-h-8,15579 +django/conf/locale/ast/LC_MESSAGES/django.po,sha256=7qZUb5JjfrWLqtXPRjpNOMNycbcsEYpNO-oYmazLTk4,23675 +django/conf/locale/az/LC_MESSAGES/django.mo,sha256=DMupaHNLr95FRZeF1di-6DygIFSZ6YxYRIHrPv4Gv3E,26983 +django/conf/locale/az/LC_MESSAGES/django.po,sha256=ZF-Qz16zoirRayV4_C9AIzbQwt2thq1WeS0DpcD7SIY,29723 +django/conf/locale/az/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/az/formats.py,sha256=JQoS2AYHKJxiH6TJas1MoeYgTeUv5XcNtYUHF7ulDmw,1087 +django/conf/locale/be/LC_MESSAGES/django.mo,sha256=z09cfjPC1YHIdrbHJmwfJCme63opwjn469dHKSgJhs4,37503 +django/conf/locale/be/LC_MESSAGES/django.po,sha256=N3-jfRg85aFiHCQh9sKIbF6CjwteYsGeYZzIZ1QRsmc,40108 +django/conf/locale/bg/LC_MESSAGES/django.mo,sha256=7WnI0Knvqz95GxTs3LPWCx8M8IbZat8OXjSIjfcOSMs,34299 +django/conf/locale/bg/LC_MESSAGES/django.po,sha256=CYfKGLkoTKZxe0RReZZ5VLbU7ZzuDv1vcL8ZHn9dyBk,37043 +django/conf/locale/bg/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/bg/formats.py,sha256=LC7P_5yjdGgsxLQ_GDtC8H2bz9NTxUze_CAtzlm37TA,705 +django/conf/locale/bn/LC_MESSAGES/django.mo,sha256=sB0RIFrGS11Z8dx5829oOFw55vuO4vty3W4oVzIEe8Q,16660 +django/conf/locale/bn/LC_MESSAGES/django.po,sha256=rF9vML3LDOqXkmK6R_VF3tQaFEoZI7besJAPx5qHNM0,26877 +django/conf/locale/bn/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/bn/formats.py,sha256=jynhZ9XNNuxTXeF7f2FrJYYZuFwlLY58fGfQ6gVs7s8,964 +django/conf/locale/br/LC_MESSAGES/django.mo,sha256=Xow2-sd55CZJsvfF8axtxXNRe27EDwxKixCGelVQ4aU,14009 +django/conf/locale/br/LC_MESSAGES/django.po,sha256=ODCUDdEDAvsOVOAr49YiWT2YQaBZmc-38brdgYWc8Bs,24293 +django/conf/locale/bs/LC_MESSAGES/django.mo,sha256=Xa5QAbsHIdLkyG4nhLCD4UHdCngrw5Oh120abCNdWlA,10824 +django/conf/locale/bs/LC_MESSAGES/django.po,sha256=IB-2VvrQKUivAMLMpQo1LGRAxw3kj-7kB6ckPai0fug,22070 +django/conf/locale/bs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/bs/formats.py,sha256=760m-h4OHpij6p_BAD2dr3nsWaTb6oR1Y5culX9Gxqw,705 +django/conf/locale/ca/LC_MESSAGES/django.mo,sha256=v6lEJTUbXyEUBsctIdNFOg-Ck5MVFbuz-JgjqkUe32c,27707 +django/conf/locale/ca/LC_MESSAGES/django.po,sha256=16M-EtYLbfKnquh-IPRjWxTdHAqtisDc46Dzo5n-ZMc,30320 +django/conf/locale/ca/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/ca/formats.py,sha256=s7N6Ns3yIqr_KDhatnUvfjbPhUbrhvemB5HtCeodGZo,940 +django/conf/locale/ckb/LC_MESSAGES/django.mo,sha256=-7x01-x26Us9E5lRRaTgpFNkerqmYdxio5wSIKaMyMY,33473 +django/conf/locale/ckb/LC_MESSAGES/django.po,sha256=5a1UK1J87IlJtEaVpEaOnms0CQxtuFtOKIclGnGaGeI,35708 +django/conf/locale/ckb/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/ckb/formats.py,sha256=EbmQC-dyQl8EqVQOVGwy1Ra5-P1n-J3UF4K55p3VzOM,728 +django/conf/locale/cs/LC_MESSAGES/django.mo,sha256=z8TcGqBp91REABKRFu2Iv6Mfn7B9Xn0RrJpds3x5gA8,29060 +django/conf/locale/cs/LC_MESSAGES/django.po,sha256=pCdIvV7JEvQTgSBexXu7hHX-57IbJjDw3Q9Ub24Q3tw,32110 +django/conf/locale/cs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/cs/formats.py,sha256=3MA70CW0wfr0AIYvYqE0ACmX79tNOx-ZdlR6Aetp9e8,1539 +django/conf/locale/cy/LC_MESSAGES/django.mo,sha256=s7mf895rsoiqrPrXpyWg2k85rN8umYB2aTExWMTux7s,18319 +django/conf/locale/cy/LC_MESSAGES/django.po,sha256=S-1PVWWVgYmugHoYUlmTFAzKCpI81n9MIAhkETbpUoo,25758 +django/conf/locale/cy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/cy/formats.py,sha256=NY1pYPfpu7XjLMCCuJk5ggdpLcufV1h101ojyxfPUrY,1355 +django/conf/locale/da/LC_MESSAGES/django.mo,sha256=3GmZM_RT9mmIo9b1YH8kPQ6DmQoKmqk-2rlBf0TfsIw,27767 +django/conf/locale/da/LC_MESSAGES/django.po,sha256=gVXSrvvkVaZYCSLVKIwNgNpjWErBNZPUsvFD4D9JwVQ,30199 +django/conf/locale/da/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/da/formats.py,sha256=-y3033Fo7COyY0NbxeJVYGFybrnLbgXtRf1yBGlouys,876 +django/conf/locale/de/LC_MESSAGES/django.mo,sha256=-J6VqvJeSF8tk4rjb1aI5MSWwyV372EPzwI3O18vecE,29167 +django/conf/locale/de/LC_MESSAGES/django.po,sha256=RZMqmCY1nUVapY7ryTBN3vFNlEsuhw8mQC7b5M6IV9c,31680 +django/conf/locale/de/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/de/formats.py,sha256=fysX8z5TkbPUWAngoy_sMeFGWp2iaNU6ftkBz8cqplg,996 +django/conf/locale/de_CH/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/de_CH/formats.py,sha256=22UDF62ESuU0Jp_iNUqAj-Bhq4_-frpji0-ynBdHXYk,1377 +django/conf/locale/dsb/LC_MESSAGES/django.mo,sha256=7BR6XmSw2M21d2CY3RfmGo0KeUTLafSan93svc-uVEs,30694 +django/conf/locale/dsb/LC_MESSAGES/django.po,sha256=CuTAlu-Mq1Y9hZQc46U--wdxW3H88__UULc8HlINXh4,33213 +django/conf/locale/el/LC_MESSAGES/django.mo,sha256=P5lTOPFcl9x6_j69ZN3hM_mQbhW7Fbbx02RtTNJwfS0,33648 +django/conf/locale/el/LC_MESSAGES/django.po,sha256=rZCComPQcSSr8ZDLPgtz958uBeBZsmV_gEP-sW88kRA,37123 +django/conf/locale/el/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/el/formats.py,sha256=RON2aqQaQK3DYVF_wGlBQJDHrhANxypcUW_udYKI-ro,1241 +django/conf/locale/en/LC_MESSAGES/django.mo,sha256=mVpSj1AoAdDdW3zPZIg5ZDsDbkSUQUMACg_BbWHGFig,356 +django/conf/locale/en/LC_MESSAGES/django.po,sha256=NXe_TLhEdZv5gU0Fl93IdSjdNlpwSr2vHPBl6clWNBY,30270 +django/conf/locale/en/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/en/formats.py,sha256=VTQUhaZ_WFhS5rQj0PxbnoMySK0nzUSqrd6Gx-DtXxI,2438 +django/conf/locale/en_AU/LC_MESSAGES/django.mo,sha256=SntsKx21R2zdjj0D73BkOXGTDnoN5unsLMJ3y06nONM,25633 +django/conf/locale/en_AU/LC_MESSAGES/django.po,sha256=6Qh4Z6REzhUdG5KwNPNK9xgLlgq3VbAJuoSXyd_eHdE,28270 +django/conf/locale/en_AU/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/en_AU/formats.py,sha256=BoI5UviKGZ4TccqLmxpcdMf0Yk1YiEhY_iLQUddjvi0,1650 +django/conf/locale/en_GB/LC_MESSAGES/django.mo,sha256=jSIe44HYGfzQlPtUZ8tWK2vCYM9GqCKs-CxLURn4e1o,12108 +django/conf/locale/en_GB/LC_MESSAGES/django.po,sha256=PTXvOpkxgZFRoyiqftEAuMrFcYRLfLDd6w0K8crN8j4,22140 +django/conf/locale/en_GB/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/en_GB/formats.py,sha256=cJN8YNthkIOHCIMnwiTaSZ6RCwgSHkjWYMcfw8VFScE,1650 +django/conf/locale/en_IE/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/en_IE/formats.py,sha256=aKEIT96Y6tzbGHFu3qsFzFc4Qw_uzhNjB69GpmP6qX8,1484 +django/conf/locale/eo/LC_MESSAGES/django.mo,sha256=TPgHTDrh1amnOQjA7sY-lQvicdFewMutOfoptV3OKkU,27676 +django/conf/locale/eo/LC_MESSAGES/django.po,sha256=IPo-3crOWkp5dDQPDAFSzgCbf9OHjWB1zE3mklhTexk,30235 +django/conf/locale/eo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/eo/formats.py,sha256=zIEAk-SiLX0cvQVmRc3LpmV69jwRrejMMdC7vtVsSh0,1715 +django/conf/locale/es/LC_MESSAGES/django.mo,sha256=wtZbWxoHzfU2qRctZ3On6T5ivaTKIPe5Ss2BSfs5Vvo,29266 +django/conf/locale/es/LC_MESSAGES/django.po,sha256=moM8zcgQ75KDM_tmsvqChQesS-O39KyxdXTshRcVo30,33250 +django/conf/locale/es/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/es/formats.py,sha256=7SusO1dPErY68h5g4lpxvPbsJYdrbTcr_0EX7uDKYNo,978 +django/conf/locale/es_AR/LC_MESSAGES/django.mo,sha256=lP1VV3EXv4C7ogFFN1Iit8U8tm3Npui-Vv3SKyXa_n0,29643 +django/conf/locale/es_AR/LC_MESSAGES/django.po,sha256=n0FvSWY9XordnLSFr5JjLs7TqFYTnPtPriyzd0lknwQ,32057 +django/conf/locale/es_AR/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/es_AR/formats.py,sha256=4qgOJoR2K5ZE-pA2-aYRwFW7AbK-M9F9u3zVwgebr2w,935 +django/conf/locale/es_CO/LC_MESSAGES/django.mo,sha256=ehUwvqz9InObH3fGnOLuBwivRTVMJriZmJzXcJHsfjc,18079 +django/conf/locale/es_CO/LC_MESSAGES/django.po,sha256=XRgn56QENxEixlyix3v4ZSTSjo4vn8fze8smkrv_gc4,25107 +django/conf/locale/es_CO/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/es_CO/formats.py,sha256=0uAbBvOkdJZKjvhrrd0htScdO7sTgbofOkkC8A35_a8,691 +django/conf/locale/es_MX/LC_MESSAGES/django.mo,sha256=UkpQJeGOs_JQRmpRiU6kQmmYGL_tizL4JQOWb9i35M4,18501 +django/conf/locale/es_MX/LC_MESSAGES/django.po,sha256=M0O6o1f3V-EIY9meS3fXP_c7t144rXWZuERF5XeG5Uo,25870 +django/conf/locale/es_MX/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/es_MX/formats.py,sha256=fBvyAqBcAXARptSE3hxwzFYNx3lEE8QrhNrCWuuGNlA,768 +django/conf/locale/es_NI/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/es_NI/formats.py,sha256=UiOadPoMrNt0iTp8jZVq65xR_4LkOwp-fjvFb8MyNVg,711 +django/conf/locale/es_PR/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/es_PR/formats.py,sha256=VVTlwyekX80zCKlg1P4jhaAdKNpN5I64pW_xgrhpyVs,675 +django/conf/locale/es_VE/LC_MESSAGES/django.mo,sha256=h-h1D_Kr-LI_DyUJuIG4Zbu1HcLWTM1s5X515EYLXO8,18840 +django/conf/locale/es_VE/LC_MESSAGES/django.po,sha256=Xj38imu4Yw-Mugwge5CqAqWlcnRWnAKpVBPuL06Twjs,25494 +django/conf/locale/et/LC_MESSAGES/django.mo,sha256=AB-rTDqZm0O5NuykDiW9AJ-4QRHyFLz4uUEUr2Ms2Xk,27251 +django/conf/locale/et/LC_MESSAGES/django.po,sha256=TZTkv9dS-cz44smjX2x7pmGQ2QR2YA_OA-zH5NFaBh8,30013 +django/conf/locale/et/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/et/formats.py,sha256=DyFSZVuGSYGoImrRI2FodeM51OtvIcCkKzkI0KvYTQw,707 +django/conf/locale/eu/LC_MESSAGES/django.mo,sha256=OQAi-HVXLCx_xY8GcHYPYs5I_K1NVaPYhgqxjL_T5ds,21877 +django/conf/locale/eu/LC_MESSAGES/django.po,sha256=RKD5sVlCq-orCsMQfudiUz3Xi0Y46Z_wxMGvpY51OU0,27448 +django/conf/locale/eu/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/eu/formats.py,sha256=-PuRA6eHeXP8R3YV0aIEQRbk2LveaZk-_kjHlBT-Drg,749 +django/conf/locale/fa/LC_MESSAGES/django.mo,sha256=i9wWfM-zV76dkEoItqgfDniZ8qI66htM3cw48bBnvNg,31655 +django/conf/locale/fa/LC_MESSAGES/django.po,sha256=yry0L0s1KLG-NZ5T6rAAiQ1j7vhc3vXG24Knzn141eo,35114 +django/conf/locale/fa/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/fa/formats.py,sha256=v0dLaIh6-CWCAQHkmX0PaIlA499gTeRcJEi7lVJzw9o,722 +django/conf/locale/fi/LC_MESSAGES/django.mo,sha256=_Co3hzTYSaAMnKp8sNnxlX73AtEfjdUaqK46fiV7LdA,27865 +django/conf/locale/fi/LC_MESSAGES/django.po,sha256=_vBbAfxE0j-qD8PKwyxalip51sRZpA1NRpDnQwsyzXY,30420 +django/conf/locale/fi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/fi/formats.py,sha256=CO_wD5ZBHwAVgjxArXktLCD7M-PPhtHbayX_bBKqhlA,1213 +django/conf/locale/fr/LC_MESSAGES/django.mo,sha256=PNCl-y1WE66OVUxHor7W-UTEPRlrS9x_cRt5x0QHj9w,30266 +django/conf/locale/fr/LC_MESSAGES/django.po,sha256=4qHoDuTQFewu8c2heUxsGTQUfa7k5y1RCTFRNmvab8I,32877 +django/conf/locale/fr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/fr/formats.py,sha256=0uO3NMUAc2rRZOtr9SMJgFHTNNhr8t2xrGruVBRHTmw,938 +django/conf/locale/fr_BE/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/fr_BE/formats.py,sha256=DB7W-i5BYeRjMRGWMWmm5oK4FNOTy4H4LL_xx6Ztk00,1154 +django/conf/locale/fr_CA/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/fr_CA/formats.py,sha256=t8FZv84mgbfx3KEaOQt4If-CIAvaB6nguiSdPwQbv2Q,1168 +django/conf/locale/fr_CH/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/fr_CH/formats.py,sha256=DB7W-i5BYeRjMRGWMWmm5oK4FNOTy4H4LL_xx6Ztk00,1154 +django/conf/locale/fy/LC_MESSAGES/django.mo,sha256=9P7zoJtaYHfXly8d6zBoqkxLM98dO8uI6nmWtsGu-lM,2286 +django/conf/locale/fy/LC_MESSAGES/django.po,sha256=jveK-2MjopbqC9jWcrYbttIb4DUmFyW1_-0tYaD6R0I,19684 +django/conf/locale/fy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/fy/formats.py,sha256=mJXj1dHUnO883PYWPwuI07CNbjmnfBTQVRXZMg2hmOk,658 +django/conf/locale/ga/LC_MESSAGES/django.mo,sha256=abQpDgeTUIdZzldVuZLZiBOgf1s2YVSyrvEhxwl0GK8,14025 +django/conf/locale/ga/LC_MESSAGES/django.po,sha256=rppcWQVozZdsbl7Gud6KnJo6yDB8T0xH6hvIiLFi_zA,24343 +django/conf/locale/ga/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/ga/formats.py,sha256=Qh7R3UMfWzt7QIdMZqxY0o4OMpVsqlchHK7Z0QnDWds,682 +django/conf/locale/gd/LC_MESSAGES/django.mo,sha256=2VKzI7Nqd2NjABVQGdcduWHjj0h2b3UBGQub7xaTVPs,30752 +django/conf/locale/gd/LC_MESSAGES/django.po,sha256=3PfuhhmosuarfPjvM2TVf2kHhZaw5_G8oIM2VWTc3gI,33347 +django/conf/locale/gd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/gd/formats.py,sha256=7doL7JIoCqA_o-lpCwM3jDHMpptA3BbSgeLRqdZk8Lc,715 +django/conf/locale/gl/LC_MESSAGES/django.mo,sha256=AUPfPhyGP8m8ZPwAevblVkzV_fgNVU6Z6ty5ZAKnhpE,28425 +django/conf/locale/gl/LC_MESSAGES/django.po,sha256=o8lFb_m9s75xaYqVoSzYLRZ6181a8QRzlj9DoG6whyQ,30876 +django/conf/locale/gl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/gl/formats.py,sha256=ygSFv-YTS8htG_LW0awegkkOarPRTZNPbUck5sxkAwI,757 +django/conf/locale/he/LC_MESSAGES/django.mo,sha256=pAzuekmiofxdO7eLRThdsoghuHLWhzaeIrrNy0s6eCQ,32301 +django/conf/locale/he/LC_MESSAGES/django.po,sha256=JHeqYJDlX7s9sAkx1voy68XF_w21sopMLypB3I_ioqs,35086 +django/conf/locale/he/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/he/formats.py,sha256=M-tu-LmTZd_oYPNH6CZEsdxJN526RUOfnLHlQxRL0N0,712 +django/conf/locale/hi/LC_MESSAGES/django.mo,sha256=8pV5j5q8VbrxdVkcS0qwhVx6DmXRRXPKfRsm3nWhI2g,19712 +django/conf/locale/hi/LC_MESSAGES/django.po,sha256=DPV-I1aXgIiZB7zHdEgAHShZFyb9zlNmMXlyjH5ug0I,29221 +django/conf/locale/hi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/hi/formats.py,sha256=JArVM9dMluSP-cwpZydSVXHB5Vs9QKyR9c-bftI9hds,684 +django/conf/locale/hr/LC_MESSAGES/django.mo,sha256=HP4PCb-i1yYsl5eqCamg5s3qBxZpS_aXDDKZ4Hlbbcc,19457 +django/conf/locale/hr/LC_MESSAGES/django.po,sha256=qeVJgKiAv5dKR2msD2iokSOApZozB3Gp0xqzC09jnvs,26329 +django/conf/locale/hr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/hr/formats.py,sha256=F4mIdDoaOYJ_lPmsJ_6bQo4Zj8pOSVwuldm92zRy4Fo,1723 +django/conf/locale/hsb/LC_MESSAGES/django.mo,sha256=oMDdIf-qu97gcocpdx_g1MhBwzQ6XA7zaxL9RJMMsyo,30347 +django/conf/locale/hsb/LC_MESSAGES/django.po,sha256=cZ2Sp3cG6p_VNhYmFr20CIXoyBkh1r15zWhLO7Ow-rA,32838 +django/conf/locale/hu/LC_MESSAGES/django.mo,sha256=3ixfTAD0ckQHTmLU-rL_yTX13RKtyEOGZqQ0LHmoyK8,29185 +django/conf/locale/hu/LC_MESSAGES/django.po,sha256=yj8yjwlKQoGCHeYKYQfPTO0WTiAFgNKgAlGFuMQT4-o,31743 +django/conf/locale/hu/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/hu/formats.py,sha256=xAD7mNsC5wFA2_KGRbBMPKwj884pq0jCKmXhEenGAEk,1001 +django/conf/locale/hy/LC_MESSAGES/django.mo,sha256=KfmTnB-3ZUKDHeNgLiego2Af0WZoHTuNKss3zE-_XOE,22207 +django/conf/locale/hy/LC_MESSAGES/django.po,sha256=kNKlJ5NqZmeTnnxdqhmU3kXiqT9t8MgAFgxM2V09AIc,28833 +django/conf/locale/ia/LC_MESSAGES/django.mo,sha256=JcrpersrDAoJXrD3AnPYBCQyGJ-6kUzH_Q8StbqmMeE,21428 +django/conf/locale/ia/LC_MESSAGES/django.po,sha256=LG0juYDjf3KkscDxwjY3ac6H1u5BBwGHljW3QWvr1nc,26859 +django/conf/locale/id/LC_MESSAGES/django.mo,sha256=SrVuic3AoBbAku_LgEx1qRYxZieUASlppj-Po9iRyP0,27301 +django/conf/locale/id/LC_MESSAGES/django.po,sha256=H1dekz2XSLrQ6Md7lahXEDybqV3xfMVTPCdCA4xG8OM,29844 +django/conf/locale/id/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/id/formats.py,sha256=kYyOxWHN3Jyif3rFxLFyBUjTzFUwmuaLrkw5JvGbEz8,1644 +django/conf/locale/ig/LC_MESSAGES/django.mo,sha256=tAZG5GKhEbrUCJtLrUxzmrROe1RxOhep8w-RR7DaDYo,27188 +django/conf/locale/ig/LC_MESSAGES/django.po,sha256=DB_I4JXKMY4M7PdAeIsdqnLSFpq6ImkGPCuY82rNBpY,28931 +django/conf/locale/ig/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/ig/formats.py,sha256=P3IsxhF5rNFZ5nCWUSyJfFLb0V1QdX_Xn-tYdrcll5Q,1119 +django/conf/locale/io/LC_MESSAGES/django.mo,sha256=uI78C7Qkytf3g1A6kVWiri_CbS55jReO2XmRfLTeNs0,14317 +django/conf/locale/io/LC_MESSAGES/django.po,sha256=FyN4ZTfNPV5TagM8NEhRts8y_FhehIPPouh_MfslnWY,23124 +django/conf/locale/is/LC_MESSAGES/django.mo,sha256=1pFU-dTPg2zs87L0ZqFFGS9q-f-XrzTOlhKujlyNL2E,24273 +django/conf/locale/is/LC_MESSAGES/django.po,sha256=76cQ_9DLg1jR53hiKSc1tLUMeKn8qTdPwpHwutEK014,28607 +django/conf/locale/is/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/is/formats.py,sha256=scsNfP4vVacxWIoN03qc2Fa3R8Uh5Izr1MqBicrAl3A,688 +django/conf/locale/it/LC_MESSAGES/django.mo,sha256=39GKwsSkjlL1h4vVysTWMuo4hq2UGQEC-kqJcaVW54A,28587 +django/conf/locale/it/LC_MESSAGES/django.po,sha256=t973TArDuAfpRpPgSTyc-bU6CPti2xkST9O2tVb8vFc,31670 +django/conf/locale/it/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/it/formats.py,sha256=KzkSb3KXBwfM3gk2FezyR-W8_RYKpnlFeFuIi5zl-S0,1774 +django/conf/locale/ja/LC_MESSAGES/django.mo,sha256=-nCZMYXT-cAvJv1eHYYSDKNecn5pFu9SkY7xUeBuqpo,30944 +django/conf/locale/ja/LC_MESSAGES/django.po,sha256=1c1iiE4ZdlFG_4R3XTWmwa7kB9BOPx36vo-6rNfkq9o,33452 +django/conf/locale/ja/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/ja/formats.py,sha256=COUuaXo5zCSNzEwJ0smjbm9Qj28YNBcGxm8qFCJv4sE,729 +django/conf/locale/ka/LC_MESSAGES/django.mo,sha256=4e8at-KNaxYJKIJd8r6iPrYhEdnaJ1qtPw-QHPMh-Sc,24759 +django/conf/locale/ka/LC_MESSAGES/django.po,sha256=pIgaLU6hXgVQ2WJp1DTFoubI7zHOUkkKMddwV3PTdt8,32088 +django/conf/locale/ka/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/ka/formats.py,sha256=elTGOjS-mxuoSCAKOm8Wz2aLfh4pWvNyClUFcrYq9ng,1861 +django/conf/locale/kab/LC_MESSAGES/django.mo,sha256=x5Kyq2Uf3XNlQP06--4lT8Q1MacA096hZbyMJRrHYIc,7139 +django/conf/locale/kab/LC_MESSAGES/django.po,sha256=DsFL3IzidcAnPoAWIfIbGJ6Teop1yKPBRALeLYrdiFA,20221 +django/conf/locale/kk/LC_MESSAGES/django.mo,sha256=krjcDvA5bu591zcP76bWp2mD2FL1VUl7wutaZjgD668,13148 +django/conf/locale/kk/LC_MESSAGES/django.po,sha256=RgM4kzn46ZjkSDHMAsyOoUg7GdxGiZ-vaEOdf7k0c5A,23933 +django/conf/locale/km/LC_MESSAGES/django.mo,sha256=kEvhZlH7lkY1DUIHTHhFVQzOMAPd_-QMItXTYX0j1xY,7223 +django/conf/locale/km/LC_MESSAGES/django.po,sha256=QgRxEiJMopO14drcmeSG6XEXQpiAyfQN0Ot6eH4gca8,21999 +django/conf/locale/km/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/km/formats.py,sha256=0UMLrZz1aI2sdRPkJ0YzX99co2IV6tldP7pEvGEPdP0,750 +django/conf/locale/kn/LC_MESSAGES/django.mo,sha256=fQ7AD5tUiV_PZFBxUjNPQN79dWBJKqfoYwRdrOaQjU4,17515 +django/conf/locale/kn/LC_MESSAGES/django.po,sha256=fS4Z7L4NGVQ6ipZ7lMHAqAopTBP0KkOc-eBK0IYdbBE,28133 +django/conf/locale/kn/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/kn/formats.py,sha256=X5j9VHIW2XRdeTzDFEyS8tG05OBFzP2R7sEGUQa_INg,680 +django/conf/locale/ko/LC_MESSAGES/django.mo,sha256=OKH7o2na5tnnwQUHkQapc1a1POhLVve8h4-AXiXZF_E,28560 +django/conf/locale/ko/LC_MESSAGES/django.po,sha256=mM5G_0ZGLaJjbIDDFGnnO8gHWDpMrP1DiKtFVKt2f0c,31700 +django/conf/locale/ko/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/ko/formats.py,sha256=qn36EjiO4Bu12D_6qitjMDkBfy4M0LgFE-FhK8bPOto,2061 +django/conf/locale/ky/LC_MESSAGES/django.mo,sha256=IBVfwPwaZmaoljMRBGww_wWGMJqbF_IOHHnH2j-yJw8,31395 +django/conf/locale/ky/LC_MESSAGES/django.po,sha256=5ACTPMMbXuPJbU7Rfzs0yZHh3xy483pqo5DwSBQp4s4,33332 +django/conf/locale/ky/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/ky/formats.py,sha256=QCq7vxAD5fe9VhcjRhG6C3N28jNvdzKR-c-EvDSJ1Pg,1178 +django/conf/locale/lb/LC_MESSAGES/django.mo,sha256=tQSJLQUeD5iUt-eA2EsHuyYqsCSYFtbGdryATxisZsc,8008 +django/conf/locale/lb/LC_MESSAGES/django.po,sha256=GkKPLO3zfGTNync-xoYTf0vZ2GUSAotAjfPSP01SDMU,20622 +django/conf/locale/lt/LC_MESSAGES/django.mo,sha256=cdUzK5RYW-61Upf8Sd8ydAg9wXg21pJaIRWFSKPv17c,21421 +django/conf/locale/lt/LC_MESSAGES/django.po,sha256=Lvpe_xlbxSa5vWEossxBCKryDVT7Lwz0EnuL1kSO6OY,28455 +django/conf/locale/lt/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/lt/formats.py,sha256=C9ScR3gYswT1dQXFedUUnYe6DQPVGAS_nLxs0h2E3dE,1637 +django/conf/locale/lv/LC_MESSAGES/django.mo,sha256=Y7F2R52FeIfspPxGdZi1R-3lj5f7kWGgjdMPFPza8eU,29168 +django/conf/locale/lv/LC_MESSAGES/django.po,sha256=EMTq1DxibNdumhyexDNY1WgH1_8ikdU8L1tT-PUSWwU,31960 +django/conf/locale/lv/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/lv/formats.py,sha256=k8owdq0U7-x6yl8ll1W5VjRoKdp8a1G2enH04G5_nvU,1713 +django/conf/locale/mk/LC_MESSAGES/django.mo,sha256=uQKmcys0rOsRynEa812XDAaeiNTeBMkqhR4LZ_cfdAk,22737 +django/conf/locale/mk/LC_MESSAGES/django.po,sha256=4K11QRb493wD-FM6-ruCxks9_vl_jB59V1c1rx-TdKg,29863 +django/conf/locale/mk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/mk/formats.py,sha256=xwnJsXLXGogOqpP18u6GozjehpWAwwKmXbELolYV_k4,1451 +django/conf/locale/ml/LC_MESSAGES/django.mo,sha256=MGvV0e3LGUFdVIA-h__BuY8Ckom2dAhSFvAtZ8FiAXU,30808 +django/conf/locale/ml/LC_MESSAGES/django.po,sha256=iLllS6vlCpBNZfy9Xd_2Cuwi_1-Vz9fW4G1lUNOuZ6k,37271 +django/conf/locale/ml/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/ml/formats.py,sha256=ZR7tMdJF0U6K1H95cTqrFH4gop6ZuSQ7vD2h0yKq6mo,1597 +django/conf/locale/mn/LC_MESSAGES/django.mo,sha256=sd860BHXfgAjDzU3CiwO3JirA8S83nSr4Vy3QUpXHyU,24783 +django/conf/locale/mn/LC_MESSAGES/django.po,sha256=VBgXVee15TTorC7zwYFwmHM4qgpYy11yclv_u7UTNwA,30004 +django/conf/locale/mn/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/mn/formats.py,sha256=fsexJU9_UTig2PS_o11hcEmrbPBS8voI4ojuAVPOd_U,676 +django/conf/locale/mr/LC_MESSAGES/django.mo,sha256=aERpEBdJtkSwBj6zOtiKDaXuFzepi8_IwvPPHi8QtGU,1591 +django/conf/locale/mr/LC_MESSAGES/django.po,sha256=GFtk4tVQVi8b7N7KEhoNubVw_PV08pyRvcGOP270s1Q,19401 +django/conf/locale/ms/LC_MESSAGES/django.mo,sha256=U4_kzfbYF7u78DesFRSReOIeVbOnq8hi_pReFfHfyUQ,27066 +django/conf/locale/ms/LC_MESSAGES/django.po,sha256=49pG3cykGjVfC9N8WPyskz-m7r6KmQiq5i8MR6eOi54,28985 +django/conf/locale/ms/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/ms/formats.py,sha256=YtOBs6s4j4SOmfB3cpp2ekcxVFoVGgUN8mThoSueCt0,1522 +django/conf/locale/my/LC_MESSAGES/django.mo,sha256=SjYOewwnVim3-GrANk2RNanOjo6Hy2omw0qnpkMzTlM,2589 +django/conf/locale/my/LC_MESSAGES/django.po,sha256=b_QSKXc3lS2Xzb45yVYVg307uZNaAnA0eoXX2ZmNiT0,19684 +django/conf/locale/nb/LC_MESSAGES/django.mo,sha256=qX1Z1F3YXVavlrECVkHXek9tsvJEXbWNrogdjjY3jCg,27007 +django/conf/locale/nb/LC_MESSAGES/django.po,sha256=QQ_adZsyp2BfzcJS-LXnZL0EMmUZLbnHsBB1pRRfV-8,29500 +django/conf/locale/nb/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/nb/formats.py,sha256=y1QLE-SG00eHwje0lkAToHtz4t621Rz_HQRyBWCgK8c,1552 +django/conf/locale/ne/LC_MESSAGES/django.mo,sha256=BcK8z38SNWDXXWVWUmOyHEzwk2xHEeaW2t7JwrxehKM,27248 +django/conf/locale/ne/LC_MESSAGES/django.po,sha256=_Kj_i2zMb7JLU7EN7Z7JcUn89YgonJf6agSFCjXa49w,33369 +django/conf/locale/nl/LC_MESSAGES/django.mo,sha256=-MmCW-3_sYQ1KKq380IkXyv0uaDkfFADwQWaIw3D5xY,28156 +django/conf/locale/nl/LC_MESSAGES/django.po,sha256=UOHFRrRV1xWww02EBIrhohurTR5q3iMdPimK3kT72tk,30991 +django/conf/locale/nl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/nl/formats.py,sha256=cKaaOvRdeauORjvuZ1xyVcVsl36J3Zk4FSE-lnx2Xwg,3927 +django/conf/locale/nn/LC_MESSAGES/django.mo,sha256=Ccj8kjvjTefC8H6TuDCOdSrTmtkYXkmRR2V42HBMYo4,26850 +django/conf/locale/nn/LC_MESSAGES/django.po,sha256=oaVJTl0NgZ92XJv9DHdsXVaKAc81ky_R3CA6HljTH-8,29100 +django/conf/locale/nn/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/nn/formats.py,sha256=y1QLE-SG00eHwje0lkAToHtz4t621Rz_HQRyBWCgK8c,1552 +django/conf/locale/os/LC_MESSAGES/django.mo,sha256=LBpf_dyfBnvGOvthpn5-oJuFiSNHrgiVHBzJBR-FxOw,17994 +django/conf/locale/os/LC_MESSAGES/django.po,sha256=WYlAnNYwGFnH76Elnnth6YP2TWA-fEtvV5UinnNj7AA,26278 +django/conf/locale/pa/LC_MESSAGES/django.mo,sha256=H1hCnQzcq0EiSEaayT6t9H-WgONO5V4Cf7l25H2930M,11253 +django/conf/locale/pa/LC_MESSAGES/django.po,sha256=26ifUdCX9fOiXfWvgMkOXlsvS6h6nNskZcIBoASJec4,23013 +django/conf/locale/pl/LC_MESSAGES/django.mo,sha256=bvG7VGdyrz40jTf_dY8GjD06EpJ2m2c7SHyJpueV2IQ,30631 +django/conf/locale/pl/LC_MESSAGES/django.po,sha256=dyW30WjK0M-rT2f3M4cVxsPBqbvbQZkC5pfbiBeaGRk,34570 +django/conf/locale/pl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/pl/formats.py,sha256=KREhPtHuzKS_ZsAqXs5LqYPGhn6O-jLd4WZQ-39BA8I,1032 +django/conf/locale/pt/LC_MESSAGES/django.mo,sha256=nlj_L7Z2FkXs1w6wCGGseuZ_U-IecnlfYRtG5jPkGrs,20657 +django/conf/locale/pt/LC_MESSAGES/django.po,sha256=ETTedbjU2J4FLi2QDHNN8C7zlAsvLWNUlYzkEV1WB6s,26224 +django/conf/locale/pt/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/pt/formats.py,sha256=RQ9MuIwUPhiY2u-1hFU2abs9Wqv1qZE2AUAfYVK-NU8,1520 +django/conf/locale/pt_BR/LC_MESSAGES/django.mo,sha256=5ogcfMO25JDFumNUQev6biuWw7RsRufDB5aj6qb3QLQ,29165 +django/conf/locale/pt_BR/LC_MESSAGES/django.po,sha256=Z9obJIOeH12Fri8qULx0JbhJRZbII_fuL4kmdjZzamY,33116 +django/conf/locale/pt_BR/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/pt_BR/formats.py,sha256=J1IKV7cS2YMJ5_qlT9h1dDYUX9tLFvqA95l_GpZTLUY,1285 +django/conf/locale/ro/LC_MESSAGES/django.mo,sha256=9RSlC_3Ipn_Vm31ALaGHsrOA1IKmKJ5sN2m6iy5Hk60,21493 +django/conf/locale/ro/LC_MESSAGES/django.po,sha256=XoGlHKEnGlno_sbUTnbkg9nGkRfPIpxv7Wfm3hHGu9w,28099 +django/conf/locale/ro/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/ro/formats.py,sha256=e_dp0zyfFfoydrGyn6Kk3DnQIj7RTRuvRc6rQ6tSxzA,928 +django/conf/locale/ru/LC_MESSAGES/django.mo,sha256=l-qQJ8gO2uwtLnEOhdCmITMRfTmsvdMwyXjX2kS-Rr8,38774 +django/conf/locale/ru/LC_MESSAGES/django.po,sha256=OzPYJYCbEiOfUtjmAaCnHb2HSFtKCmriaPhIjvmplKc,42136 +django/conf/locale/ru/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/ru/formats.py,sha256=lTfYbecdSmHCxebog_2bd0N32iD3nEq_f5buh9il-nI,1098 +django/conf/locale/sk/LC_MESSAGES/django.mo,sha256=m4rFecNfLaaDjlq6yCKIH9ziuhLXKqALZX7BYTY90kQ,29942 +django/conf/locale/sk/LC_MESSAGES/django.po,sha256=lbXg5EJazVNhhDbFM4r4Qk_pWM_RDiAdLO9AntGVnfs,32766 +django/conf/locale/sk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/sk/formats.py,sha256=bWj0FNpYfOAgi9J-L4VuiN6C_jsgPsKNdLYd9gTnFs0,1051 +django/conf/locale/sl/LC_MESSAGES/django.mo,sha256=1mzO4ZC9IYwbKM7iavLJfb2bYaLaC1UVmm4T37Xil7g,23147 +django/conf/locale/sl/LC_MESSAGES/django.po,sha256=EDR734fFO7UM_F-4Q-psEHc-VF2po7fl6n5akKdWYyY,29440 +django/conf/locale/sl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/sl/formats.py,sha256=Nq4IfEUnlGebMZeRvB2l9aps-5G5b4y1kQ_3MiJTfe8,1642 +django/conf/locale/sq/LC_MESSAGES/django.mo,sha256=MzbTs0P_flhPIB0KTkVmYNmuvc0v0uckhLDFOc0DV8M,28644 +django/conf/locale/sq/LC_MESSAGES/django.po,sha256=kOIbwxIiVF8MXiFc3XPPEnCity2ccDn1xJ76JeUs_9k,31088 +django/conf/locale/sq/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/sq/formats.py,sha256=SA_jCSNwI8-p79skHoLxrPLZnkyq1PVadwT6gMt7n_M,688 +django/conf/locale/sr/LC_MESSAGES/django.mo,sha256=70EHujljfXFgLh_oTX0S9cLEIB7K4RgDuXQq_E-VDqo,35014 +django/conf/locale/sr/LC_MESSAGES/django.po,sha256=nCCxJ28Ua80V161FiwexK8DVJSKn4My2xjR0l4BYtDk,37530 +django/conf/locale/sr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/sr/formats.py,sha256=F3_gYopOXINcllaPFzTqZrZ2oZ1ye3xzR0NQtlqXYp0,1729 +django/conf/locale/sr_Latn/LC_MESSAGES/django.mo,sha256=XFg0D4jJjXqpYOGoMV1r9tmibEcebm9gczrjCNeWJfw,24760 +django/conf/locale/sr_Latn/LC_MESSAGES/django.po,sha256=Yd5SgZfBxFpEUkVL8WdtGrSmi1miLvSmXA-Uud0Ox70,30966 +django/conf/locale/sr_Latn/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/sr_Latn/formats.py,sha256=BDZm-ajQgCIxQ8mCcckEH32IoCN9233TvAOXkg4mc38,1728 +django/conf/locale/sv/LC_MESSAGES/django.mo,sha256=YzrwB3zyTvLdECT3Rwjdug6MkpBGVWouWxmOZpjZimQ,27605 +django/conf/locale/sv/LC_MESSAGES/django.po,sha256=yo1TejN4Qb8KFAg6IBtustBSfliDKcYE4VDfa0LtJkk,30413 +django/conf/locale/sv/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/sv/formats.py,sha256=9o8ZtaSq1UOa5y6Du3rQsLAAl5ZOEdVY1OVVMbj02RA,1311 +django/conf/locale/sw/LC_MESSAGES/django.mo,sha256=aUmIVLANgSCTK5Lq8QZPEKWjZWnsnBvm_-ZUcih3J6g,13534 +django/conf/locale/sw/LC_MESSAGES/django.po,sha256=GOE6greXZoLhpccsfPZjE6lR3G4vpK230EnIOdjsgPk,22698 +django/conf/locale/ta/LC_MESSAGES/django.mo,sha256=WeM8tElbcmL11P_D60y5oHKtDxUNWZM9UNgXe1CsRQ4,7094 +django/conf/locale/ta/LC_MESSAGES/django.po,sha256=kgHTFqysEMj1hqktLr-bnL1NRM715zTpiwhelqC232s,22329 +django/conf/locale/ta/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/ta/formats.py,sha256=vmjfiM54oJJxqcdgZJUNNQN7oMS-XLVBYJ4lWBb5ctY,682 +django/conf/locale/te/LC_MESSAGES/django.mo,sha256=Sk45kPC4capgRdW5ImOKYEVxiBjHXsosNyhVIDtHLBc,13259 +django/conf/locale/te/LC_MESSAGES/django.po,sha256=IQxpGTpsKUtBGN1P-KdGwvE7ojNCqKqPXEvYD3qT5A4,25378 +django/conf/locale/te/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/te/formats.py,sha256=-HOoZgmnME4--4CuXzcnhXqNma0Wh7Ninof3RCCGZkU,680 +django/conf/locale/tg/LC_MESSAGES/django.mo,sha256=ePzS2pD84CTkHBaiaMyXBxiizxfFBjHdsGH7hCt5p_4,28497 +django/conf/locale/tg/LC_MESSAGES/django.po,sha256=oSKu3YT3griCrDLPqptZmHcuviI99wvlfX6I6nLJnDk,33351 +django/conf/locale/tg/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/tg/formats.py,sha256=TG5TGfLNy4JSjl-QAWk46gIEb0ijdBpqPrDtwfJzshw,1160 +django/conf/locale/th/LC_MESSAGES/django.mo,sha256=SJeeJWbdF-Lae5BendxlyMKqx5zdDmh3GCQa8ER5FyY,18629 +django/conf/locale/th/LC_MESSAGES/django.po,sha256=K4ITjzHLq6DyTxgMAfu3CoGxrTd3aG2J6-ZxQj2KG1U,27507 +django/conf/locale/th/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/th/formats.py,sha256=SmCUD-zVgI1QE2HwqkFtAO87rJ-FoCjw1s-2-cfl1h0,1072 +django/conf/locale/tk/LC_MESSAGES/django.mo,sha256=XO-fnBwiAEVEyRP-UhWJjC28vHjCNyyuR8aN9T1gNmM,27726 +django/conf/locale/tk/LC_MESSAGES/django.po,sha256=8xy832KfxCgPVKkmEHG_8vv3kqsSzU70a-eCFcVEuk4,30193 +django/conf/locale/tk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/tk/formats.py,sha256=TG5TGfLNy4JSjl-QAWk46gIEb0ijdBpqPrDtwfJzshw,1160 +django/conf/locale/tr/LC_MESSAGES/django.mo,sha256=aHH9yGDn5u4CT9EYplgKKPYMh_0LCeIyxWyja-TeoLI,28804 +django/conf/locale/tr/LC_MESSAGES/django.po,sha256=F86yXAHOeHHCKG5z2l1k2YDvgQTQNUXWh5BfDqn73J8,31390 +django/conf/locale/tr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/tr/formats.py,sha256=yJg-7hmevD1gvj9iBRMCiYGgd5DxKZcL7T_C3K3ztME,1019 +django/conf/locale/tt/LC_MESSAGES/django.mo,sha256=r554DvdPjD_S8hBRjW8ehccEjEk8h7czQsp46FZZ_Do,14500 +django/conf/locale/tt/LC_MESSAGES/django.po,sha256=W8QgEAH7yXNmjWoF-UeqyVAu5jEMHZ5MXE60e5sawJc,24793 +django/conf/locale/udm/LC_MESSAGES/django.mo,sha256=cIf0i3TjY-yORRAcSev3mIsdGYT49jioTHZtTLYAEyc,12822 +django/conf/locale/udm/LC_MESSAGES/django.po,sha256=n9Az_8M8O5y16yE3iWmK20R9F9VoKBh3jR3iKwMgFlY,23113 +django/conf/locale/ug/LC_MESSAGES/django.mo,sha256=1rD3kSFFPQ_PYpjzvbg1oHbyqIrbxVSQe7x6bt0uA64,35453 +django/conf/locale/ug/LC_MESSAGES/django.po,sha256=E8npwLuDFsCoCsPRGKKc_XoJ5ogjRLwiX2ermZ4gvRM,37707 +django/conf/locale/ug/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/ug/formats.py,sha256=qoSAkaWqJ7FW2OTGaZs_CfiMN9PxAVxHecZfwNCzdUo,454 +django/conf/locale/uk/LC_MESSAGES/django.mo,sha256=9U34hcSaoTUqrMtp5wpdsu2L0S-l7Hn5RBDHQkhp38Y,30194 +django/conf/locale/uk/LC_MESSAGES/django.po,sha256=XZm1LpBkwoMFEXNJyAOitN223EuMzkT_2iN8yb8oWVs,36096 +django/conf/locale/uk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/uk/formats.py,sha256=ZmeYmL0eooFwQgmE054V36RQ469ZTfAv6k8SUJrDYQ8,1241 +django/conf/locale/ur/LC_MESSAGES/django.mo,sha256=M6R2DYFRBvcVRAsgVxVOLvH3e8v14b2mJs650UlUb2I,12291 +django/conf/locale/ur/LC_MESSAGES/django.po,sha256=Lr0DXaPqWtCFAxn10BQ0vlvZIMNRvCg_QJQxAC01eWk,23479 +django/conf/locale/uz/LC_MESSAGES/django.mo,sha256=c8eHLqubZqScsU8LjGK-j2uAGeWzHCSmCy-tYu9x_FA,27466 +django/conf/locale/uz/LC_MESSAGES/django.po,sha256=TxmmhZCC1zrAgo0xM0JQKywju0XBd1BujMKZ9HtOLKY,29376 +django/conf/locale/uz/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/uz/formats.py,sha256=cdmqOUBVnPSyi2k9AkOGl27s89PymFePG2gtnYzYbiw,1176 +django/conf/locale/vi/LC_MESSAGES/django.mo,sha256=TMsBzDnf9kZndozqVUnEKtKxfH2N1ajLdrm8hJ4HkYI,17396 +django/conf/locale/vi/LC_MESSAGES/django.po,sha256=tL2rvgunvaN_yqpPSBYAKImFDaFaeqbnpEw_egI11Lo,25342 +django/conf/locale/vi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/vi/formats.py,sha256=_xIugkqLnjN9dzIhefMpsJXaTPldr4blKSGS-c3swg0,762 +django/conf/locale/zh_Hans/LC_MESSAGES/django.mo,sha256=bKnjePnZ4hzBNpV7riyY897ztLPjez-7amTqMphbLiw,26598 +django/conf/locale/zh_Hans/LC_MESSAGES/django.po,sha256=6Ur0nzeMoNleIxU-llL7HOfC1KOcAZLKEvaW7x4udRw,29727 +django/conf/locale/zh_Hans/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/zh_Hans/formats.py,sha256=iMb9Taj6xQQA3l_NWCC7wUlQuh4YfNUgs2mHcQ6XUEo,1598 +django/conf/locale/zh_Hant/LC_MESSAGES/django.mo,sha256=1U3cID-BpV09p0sgYryzJCCApQYVlCtb4fJ5IPB8wtc,19560 +django/conf/locale/zh_Hant/LC_MESSAGES/django.po,sha256=buHXYy_UKFoGW8xz6PNrSwbMx-p8gwmPRgdWGBYwT2U,24939 +django/conf/locale/zh_Hant/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/locale/zh_Hant/formats.py,sha256=iMb9Taj6xQQA3l_NWCC7wUlQuh4YfNUgs2mHcQ6XUEo,1598 +django/conf/project_template/manage.py-tpl,sha256=JDuGG02670bELmn3XLUSxHFZ8VFhqZTT_oN9VbT5Acc,674 +django/conf/project_template/project_name/__init__.py-tpl,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/conf/project_template/project_name/asgi.py-tpl,sha256=q_6Jo5tLy6ba-S7pLs3YTK7byxSBmU0oYylYJlNvwHI,428 +django/conf/project_template/project_name/settings.py-tpl,sha256=JskIPIEWPSX2p7_rlsPr60JDjmFC0bVEeMChmq--0OY,3342 +django/conf/project_template/project_name/urls.py-tpl,sha256=5en0vlo3TdXdQquXZVNENrmX2DZJxje156HqcRbySKU,789 +django/conf/project_template/project_name/wsgi.py-tpl,sha256=OCfjjCsdEeXPkJgFIrMml_FURt7msovNUPnjzb401fs,428 +django/conf/urls/__init__.py,sha256=qmpaRi5Gn2uaY9h3g9RNu0z3LDEpEeNL9JlfSLed9s0,292 +django/conf/urls/i18n.py,sha256=M_lO6q_92QrrPoTY9oui95BQgJfPla9edRNuN5Vc4GM,1166 +django/conf/urls/static.py,sha256=gZOYaiIf3SxQ75N69GyVm9C0OmQv1r1IDrUJ0E7zMe0,908 +django/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/admin/__init__.py,sha256=i0TwjHWq6qfZJ0e9pVWAZXxVHZ-eOPewGjtdwHljbOM,1203 +django/contrib/admin/actions.py,sha256=AkTreqTS8asbCGCWgMDXxa_9Gbc-GtvqmatM517eIG8,3254 +django/contrib/admin/apps.py,sha256=BOiulA4tsb3wuAUtLGTGjrbywpSXX0dLo2pUCGV8URw,840 +django/contrib/admin/checks.py,sha256=yRvGePYB8G-54pk2ZgqCgMuDOhkU2T9CMVGfjkZIH08,50617 +django/contrib/admin/decorators.py,sha256=dki7GLFKOPT-mB5rxsYX12rox18BywroxmrzjG_VJXM,3481 +django/contrib/admin/exceptions.py,sha256=VJhzurallXV322hhZklmvp3OmDIZZQpbEOuE-CX7938,507 +django/contrib/admin/filters.py,sha256=Wee7nd7tuUdIb4Rmcrd1esBOEaV63L4sssSoLZKosi4,27662 +django/contrib/admin/forms.py,sha256=0UCJstmmBfp_c_0AqlALJQYy9bxXo9fqoQQICQONGEo,1023 +django/contrib/admin/helpers.py,sha256=MeFG4_YAq-WNmVt7S-6kRYb_1JNZkKKLn4nHtNWoibY,18108 +django/contrib/admin/locale/af/LC_MESSAGES/django.mo,sha256=Hd_hfh0WRkl_QsI_kwTEKsG_ricJ3O33QGEjntKuxTY,17249 +django/contrib/admin/locale/af/LC_MESSAGES/django.po,sha256=GpUZg6oe7byHq83p_fcQiSo0wslCj5oOmHugKZzSnw0,18757 +django/contrib/admin/locale/af/LC_MESSAGES/djangojs.mo,sha256=mvjNbeoFfpyc8aHeOi3-X7QGeY6o29IZPXMZT7BnOGU,5773 +django/contrib/admin/locale/af/LC_MESSAGES/djangojs.po,sha256=KdjKyHdgLPDj09K4IgTJ_KWU47ZlNSnuPklRZDT1bHo,6546 +django/contrib/admin/locale/am/LC_MESSAGES/django.mo,sha256=UOwMxYH1r5AEBpu-P9zxHazk3kwI4CtsPosGIYtl6Hs,8309 +django/contrib/admin/locale/am/LC_MESSAGES/django.po,sha256=NmsIZoBEQwyBIqbKjkwCJ2_iMHnMKB87atoT0iuNXrw,14651 +django/contrib/admin/locale/ar/LC_MESSAGES/django.mo,sha256=tzGQ8jSJc406IBBwtAErlXVqaA10glxB8krZtWp1Rq4,19890 +django/contrib/admin/locale/ar/LC_MESSAGES/django.po,sha256=RBJbiYNDy57K592OKghugZFYiHpTvxUoEQ_B26-5i8A,21339 +django/contrib/admin/locale/ar/LC_MESSAGES/djangojs.mo,sha256=xoI2xNKgspuuJe1UCUB9H6Kyp3AGhj5aeo_WEg5e23A,6545 +django/contrib/admin/locale/ar/LC_MESSAGES/djangojs.po,sha256=jwehFDFk3lMIEH43AEU_JyHOm84Seo-OLd5FmGBbaxo,7281 +django/contrib/admin/locale/ar_DZ/LC_MESSAGES/django.mo,sha256=ipELNNGQYb_nHTEQbUFED8IT26L9c2UXsELf4wk0q6k,19947 +django/contrib/admin/locale/ar_DZ/LC_MESSAGES/django.po,sha256=2mGF2NfofR8WgSJPShF5CrMjECXj0dGFcFaZ2lriulc,21378 +django/contrib/admin/locale/ar_DZ/LC_MESSAGES/djangojs.mo,sha256=L3N1U9OFXYZ8OfrvKHLbVvXa40biIDdmon0ZV8BOIvY,6423 +django/contrib/admin/locale/ar_DZ/LC_MESSAGES/djangojs.po,sha256=Atzp95E2dFtSHZHHna0pBCqU_2V7partODX675OBkQs,7206 +django/contrib/admin/locale/ast/LC_MESSAGES/django.mo,sha256=3uffu2zPbQ1rExUsG_ambggq854Vy8HbullkCYdazA4,2476 +django/contrib/admin/locale/ast/LC_MESSAGES/django.po,sha256=wCWFh9viYUhTGOX0mW3fpN2z0kdE6b7IaA-A5zzb3Yo,11676 +django/contrib/admin/locale/ast/LC_MESSAGES/djangojs.mo,sha256=kiG-lzQidkXER5s_6POO1G91mcAv9VAkAXI25jdYBLE,2137 +django/contrib/admin/locale/ast/LC_MESSAGES/djangojs.po,sha256=s4s6aHocTlzGcFi0p7cFGTi3K8AgoPvFCv7-Hji6At0,4085 +django/contrib/admin/locale/az/LC_MESSAGES/django.mo,sha256=wgOltdxxboFzjUqoaqdU_rmlVptlfIpGEWKNdKz3ORo,16008 +django/contrib/admin/locale/az/LC_MESSAGES/django.po,sha256=AK41oVjiPgrYRhnBNGgKUr7NFtxsW_ASfknO2Dj20Uw,18246 +django/contrib/admin/locale/az/LC_MESSAGES/djangojs.mo,sha256=sre90ULGTqwvLUyrrTJrj3kEPwlbP-VDg-fqT_02fsE,5225 +django/contrib/admin/locale/az/LC_MESSAGES/djangojs.po,sha256=-o9woCOf9ikbIptd9uTej6G-TtTQPKRSuK86N0Ta0yU,5968 +django/contrib/admin/locale/be/LC_MESSAGES/django.mo,sha256=rL6BEAt0t-mseSwX1bxG_cY3C94gu35kZiA855NN0zU,22852 +django/contrib/admin/locale/be/LC_MESSAGES/django.po,sha256=97q3u8Q9XVmY1R4IihvK3VUaWtQDVHcyKkCwWKJuxaE,24197 +django/contrib/admin/locale/be/LC_MESSAGES/djangojs.mo,sha256=e1xbTtl47sBU5ZCUEf4fHN6E7rRkz_HIYCObX0lWDug,7703 +django/contrib/admin/locale/be/LC_MESSAGES/djangojs.po,sha256=DBSHPnSZm7AVqxg1fINkRQ89QVp_cdi4VhQ7Ynd1NWs,8466 +django/contrib/admin/locale/bg/LC_MESSAGES/django.mo,sha256=Ip797rjerPWV_ZgfgxaHIDFqYafio5ugXSqjg9wVjgs,22105 +django/contrib/admin/locale/bg/LC_MESSAGES/django.po,sha256=_y3U41n9WQOVxp0tIWPkznLspDxwFA_Z0VRTDcLzUHc,23883 +django/contrib/admin/locale/bg/LC_MESSAGES/djangojs.mo,sha256=K5xrXMvGJoMoyo53w7DhwjcnM9ZH4g4QwvYSg_7bgg0,6590 +django/contrib/admin/locale/bg/LC_MESSAGES/djangojs.po,sha256=7KW02XJA9q_YBapVLQ4hGrIwXrKeG85JW0mZQQCpuRM,7836 +django/contrib/admin/locale/bn/LC_MESSAGES/django.mo,sha256=I3KUX53ePEC-8x_bwkR5spx3WbJRR8Xf67_2Xrr7Ccg,18585 +django/contrib/admin/locale/bn/LC_MESSAGES/django.po,sha256=UvKCBSa5MuxxZ7U5pRWXH6CEQ9WCJH2cQND0jjBmgpQ,22889 +django/contrib/admin/locale/bn/LC_MESSAGES/djangojs.mo,sha256=t_OiMyPMsR2IdH65qfD9qvQfpWbwFueNuY72XSed2Io,2313 +django/contrib/admin/locale/bn/LC_MESSAGES/djangojs.po,sha256=iFwEJi4k3ULklCq9eQNUhKVblivQPJIoC_6lbyEkotY,4576 +django/contrib/admin/locale/br/LC_MESSAGES/django.mo,sha256=yCuMwrrEB_H44UsnKwY0E87sLpect_AMo0GdBjMZRPs,6489 +django/contrib/admin/locale/br/LC_MESSAGES/django.po,sha256=WMU_sN0ENWgyEbKOm8uVQfTQh9sabvKihtSdMt4XQBM,13717 +django/contrib/admin/locale/br/LC_MESSAGES/djangojs.mo,sha256=n7Yx2k9sAVSNtdY-2Ao6VFsnsx4aiExZ3TF_DnnrKU0,1658 +django/contrib/admin/locale/br/LC_MESSAGES/djangojs.po,sha256=gjg-VapbI9n_827CqNYhbtIQ8W9UcMmMObCsxCzReUU,4108 +django/contrib/admin/locale/bs/LC_MESSAGES/django.mo,sha256=44D550fxiO59Pczu5HZ6gvWEClsfmMuaxQWbA4lCW2M,8845 +django/contrib/admin/locale/bs/LC_MESSAGES/django.po,sha256=FrieR1JB4ssdWwYitJVpZO-odzPBKrW4ZsGK9LA595I,14317 +django/contrib/admin/locale/bs/LC_MESSAGES/djangojs.mo,sha256=SupUK-RLDcqJkpLEsOVjgZOWBRKQMALZLRXGEnA623M,1183 +django/contrib/admin/locale/bs/LC_MESSAGES/djangojs.po,sha256=TOtcfw-Spn5Y8Yugv2OlPoaZ5DRwJjRIl-YKiyU092U,3831 +django/contrib/admin/locale/ca/LC_MESSAGES/django.mo,sha256=Wj8KdBSUuUtebE45FK3kvzl155GdTv4KgecoMxFi0_g,17535 +django/contrib/admin/locale/ca/LC_MESSAGES/django.po,sha256=5s5RIsOY5uL1oQQ5IrOhsOgAWWFZ25vTcYURO2dlR8g,19130 +django/contrib/admin/locale/ca/LC_MESSAGES/djangojs.mo,sha256=HjPaPtF5TZGtRu1P40X2YIuRAoKndwurWE4nlZlc7sE,6075 +django/contrib/admin/locale/ca/LC_MESSAGES/djangojs.po,sha256=G7jxAwjnpvvlGinLWDx_awUBu6XwVrdIFqdxBDMVfJQ,6906 +django/contrib/admin/locale/ckb/LC_MESSAGES/django.mo,sha256=uzWLPBPoqUkm8OXwU_cpT06zNJ_OqX1A0FXTwEAFGkQ,21719 +django/contrib/admin/locale/ckb/LC_MESSAGES/django.po,sha256=R7wDN5JhqjFqxyfGuywHbJefppiKjFQ8w6CIhCBuk24,23650 +django/contrib/admin/locale/ckb/LC_MESSAGES/djangojs.mo,sha256=BKJJBqLUBjw5TfnHRjua4q45YcPox-srsOHLWHvJp88,6604 +django/contrib/admin/locale/ckb/LC_MESSAGES/djangojs.po,sha256=JxZ2gNkbkV02p-InndqBbV4Z4lgo5WUvOv52gyMWGm0,7456 +django/contrib/admin/locale/cs/LC_MESSAGES/django.mo,sha256=SGPfh9-MhUiRmguk3CGa5GC-Q8LHIo5aHZa4zkpWgow,17736 +django/contrib/admin/locale/cs/LC_MESSAGES/django.po,sha256=4HVVC6Bb4MhileINcde8RmKbHKomhW4xpiyUx91cTdc,19306 +django/contrib/admin/locale/cs/LC_MESSAGES/djangojs.mo,sha256=OiM40p3ioK9FD4JWLb2jYP75kcurEcn9ih_HDL7Pyus,5851 +django/contrib/admin/locale/cs/LC_MESSAGES/djangojs.po,sha256=hh7P3DpEzkCb7M6d2iFwHKp1CzbrmMgeyAGP96BxprE,6629 +django/contrib/admin/locale/cy/LC_MESSAGES/django.mo,sha256=7ifUyqraN1n0hbyTVb_UjRIG1jdn1HcwehugHBiQvHs,12521 +django/contrib/admin/locale/cy/LC_MESSAGES/django.po,sha256=bS_gUoKklZwd3Vs0YlRTt24-k5ure5ObTu-b5nB5qCA,15918 +django/contrib/admin/locale/cy/LC_MESSAGES/djangojs.mo,sha256=fOCA1fXEmJw_QaXEISLkuBhaMnEmP1ssP9lhqdCCC3c,3801 +django/contrib/admin/locale/cy/LC_MESSAGES/djangojs.po,sha256=OVcS-3tlMJS_T58qnZbWLGczHwFyAjbuWr35YwuxAVM,5082 +django/contrib/admin/locale/da/LC_MESSAGES/django.mo,sha256=mq80-a5LINcNJ-r4EFyqAIhW5uK2qHssY-iNDfl-usU,17775 +django/contrib/admin/locale/da/LC_MESSAGES/django.po,sha256=qP_5OMHrsvB-6PpcYrI8wHyUs8O91pQrzXBLX1ixq7o,19217 +django/contrib/admin/locale/da/LC_MESSAGES/djangojs.mo,sha256=Y-_2QRAeQ3Mtl3stD2J4eHXdNyuzHcUcpIlvTEuDs6k,5984 +django/contrib/admin/locale/da/LC_MESSAGES/djangojs.po,sha256=tiONUqX3jJnHZ1BbMIOzuQH-SMp2ESlA0RuGJSumy_U,6866 +django/contrib/admin/locale/de/LC_MESSAGES/django.mo,sha256=v2tKhZL-KDMv4UDzNuUgXDEIIoE787wFfpKHk0PUTHU,18731 +django/contrib/admin/locale/de/LC_MESSAGES/django.po,sha256=lNY-xVF6alq55oF3Jn6wj2WWb2j9HO52OUVVxxqDHOQ,20259 +django/contrib/admin/locale/de/LC_MESSAGES/djangojs.mo,sha256=kdve4d181AhGDekHiaxt79iyVWvahp3k9SN3H6Xx_9w,6130 +django/contrib/admin/locale/de/LC_MESSAGES/djangojs.po,sha256=tb25boxPrggqnB7mB2M5iyZ6CEM87PBZNa_JzaOXFF4,6921 +django/contrib/admin/locale/dsb/LC_MESSAGES/django.mo,sha256=oimRC2FFZUE6ZhrBuC9AHS3GQ6zureqSVIZFdTdHO4E,18813 +django/contrib/admin/locale/dsb/LC_MESSAGES/django.po,sha256=ZSmE6VCjs0JkMfSTA7CBaerto6eLqxbmY1hpiY_wMkk,20102 +django/contrib/admin/locale/dsb/LC_MESSAGES/djangojs.mo,sha256=y9yhJ8ITu5uRDID0AX6dpqWLE5-0bqDuVmUBJ-JJ6H8,6609 +django/contrib/admin/locale/dsb/LC_MESSAGES/djangojs.po,sha256=ca5XVYaT4H4kK-LvvBL1fcpCxRbd1OrbSNk5DAZcfaM,7335 +django/contrib/admin/locale/el/LC_MESSAGES/django.mo,sha256=54kG_94nJigDgJpZM8Cy58G_AGLdS5csJFEjTTvJBfM,22968 +django/contrib/admin/locale/el/LC_MESSAGES/django.po,sha256=f2gUQtedb0sZCBxAoy3hP2rGXT9ysP5UTOlCBvu2NvI,24555 +django/contrib/admin/locale/el/LC_MESSAGES/djangojs.mo,sha256=cix1Bkj2hYO_ofRvtPDhJ9rBnTR6-cnKCFKpZrsxJ34,6509 +django/contrib/admin/locale/el/LC_MESSAGES/djangojs.po,sha256=R05tMMuQEjVQpioy_ayQgFBlLM4WdwXthkMguW6ga24,7339 +django/contrib/admin/locale/en/LC_MESSAGES/django.mo,sha256=U0OV81NfbuNL9ctF-gbGUG5al1StqN-daB-F-gFBFC8,356 +django/contrib/admin/locale/en/LC_MESSAGES/django.po,sha256=-OrBX0hiiWkgeAWPKRxcQtqXDapSafOKRGe730rBwdc,24730 +django/contrib/admin/locale/en/LC_MESSAGES/djangojs.mo,sha256=U0OV81NfbuNL9ctF-gbGUG5al1StqN-daB-F-gFBFC8,356 +django/contrib/admin/locale/en/LC_MESSAGES/djangojs.po,sha256=y9_Ayb3NzDVQCkYehVWYq-4hEHIJN1vfWHfejWO-AvQ,9112 +django/contrib/admin/locale/en_AU/LC_MESSAGES/django.mo,sha256=QEvxPxDqNUmq8NxN-8c_F6KMEcWWum3YzERlc3_S_DM,16191 +django/contrib/admin/locale/en_AU/LC_MESSAGES/django.po,sha256=BoVuGaPoGdQcF3zdgGRxrNKSq2XLHTvKfINCyU8t86Y,17548 +django/contrib/admin/locale/en_AU/LC_MESSAGES/djangojs.mo,sha256=s0qPS8TjODtPo4miSznQfS6M8CQK9URDeMKeQsp7DK4,5001 +django/contrib/admin/locale/en_AU/LC_MESSAGES/djangojs.po,sha256=YecPU6VmUDDNNIzZVl2Wgd6lNRp3msJaW8FhdHMtEyc,5553 +django/contrib/admin/locale/en_GB/LC_MESSAGES/django.mo,sha256=pFkTMRDDj76WA91wtGPjUB7Pq2PN7IJEC54Tewobrlc,11159 +django/contrib/admin/locale/en_GB/LC_MESSAGES/django.po,sha256=REUJMGLGRyDMkqh4kJdYXO9R0Y6CULFVumJ_P3a0nv0,15313 +django/contrib/admin/locale/en_GB/LC_MESSAGES/djangojs.mo,sha256=hW325c2HlYIIdvNE308c935_IaDu7_qeP-NlwPnklhQ,3147 +django/contrib/admin/locale/en_GB/LC_MESSAGES/djangojs.po,sha256=Ol5j1-BLbtSIDgbcC0o7tg_uHImcjJQmkA4-kSmZY9o,4581 +django/contrib/admin/locale/eo/LC_MESSAGES/django.mo,sha256=zAeGKzSNit2LNNX97WXaARyzxKIasOmTutcTPqpRKAE,14194 +django/contrib/admin/locale/eo/LC_MESSAGES/django.po,sha256=LHoYvbenD9A05EkHtOk8raW7aKyyiqN50d6OHMxnAZY,17258 +django/contrib/admin/locale/eo/LC_MESSAGES/djangojs.mo,sha256=hGXULxueBP24xSZ0StxfFCO0vwZZME7OEERxgnWBqcI,4595 +django/contrib/admin/locale/eo/LC_MESSAGES/djangojs.po,sha256=enHGjcvH_B0Z9K2Vk391qHAKT7QamqUcx8xPzYLQltA,5698 +django/contrib/admin/locale/es/LC_MESSAGES/django.mo,sha256=hZOu8rE7FttOvhQWO8PoRNT5SH05CSflfVW0NdwjBwQ,18887 +django/contrib/admin/locale/es/LC_MESSAGES/django.po,sha256=LG1DPWqAMOk3S25YFrlTCeEvZ4Dins946L0k0Y62N2I,20983 +django/contrib/admin/locale/es/LC_MESSAGES/djangojs.mo,sha256=GH3zJZEVfJc_REXoYwaCNzhL4EHJosWa7qDmeFRWbco,6347 +django/contrib/admin/locale/es/LC_MESSAGES/djangojs.po,sha256=aqR-EZ2XUWNclkSxVa1xKFdaZpw7sQMORSMMINDRjlQ,7290 +django/contrib/admin/locale/es_AR/LC_MESSAGES/django.mo,sha256=_YhWI2PXQ4y66adv6Ml2PMMr2_dy22BFB0BVZfiGxJ4,19032 +django/contrib/admin/locale/es_AR/LC_MESSAGES/django.po,sha256=KmDcmElOGL04i1RnZgjsF_7v2pPGVHiuwq29x8Kpc-U,20412 +django/contrib/admin/locale/es_AR/LC_MESSAGES/djangojs.mo,sha256=2VDkQJCHtYndAr3kz53BhLwxqbDzkQhoDwNedrGtMEw,6647 +django/contrib/admin/locale/es_AR/LC_MESSAGES/djangojs.po,sha256=MRHZAsXyTEiYtlqmybyuJgwfdHtjNOu4EgcWdzzVF4M,7351 +django/contrib/admin/locale/es_CO/LC_MESSAGES/django.mo,sha256=0k8kSiwIawYCa-Lao0uetNPLUzd4m_me3tCAVBvgcSw,15156 +django/contrib/admin/locale/es_CO/LC_MESSAGES/django.po,sha256=4T_syIsVY-nyvn5gEAtfN-ejPrJSUpNT2dmzufxaBsE,17782 +django/contrib/admin/locale/es_CO/LC_MESSAGES/djangojs.mo,sha256=PLS10KgX10kxyy7MUkiyLjqhMzRgkAFGPmzugx9AGfs,3895 +django/contrib/admin/locale/es_CO/LC_MESSAGES/djangojs.po,sha256=Y4bkC8vkJE6kqLbN8t56dR5670B06sB2fbtVzmQygK8,5176 +django/contrib/admin/locale/es_MX/LC_MESSAGES/django.mo,sha256=O8CbY83U4fTvvPPuONtlMx6jpA-qkrYxNTkLuMrWiRQ,11517 +django/contrib/admin/locale/es_MX/LC_MESSAGES/django.po,sha256=8MSKNxhHMp0ksr5AUUAbs_H6MtMjIqkaFwmaJlBxELs,16307 +django/contrib/admin/locale/es_MX/LC_MESSAGES/djangojs.mo,sha256=2w3CMJFBugP8xMOmXsDU82xUm8cWGRUGZQX5XjiTCpM,3380 +django/contrib/admin/locale/es_MX/LC_MESSAGES/djangojs.po,sha256=OP9cBsdCf3zZAXiKBMJPvY1AHwC_WE1k2vKlzVCtUec,4761 +django/contrib/admin/locale/es_VE/LC_MESSAGES/django.mo,sha256=himCORjsM-U3QMYoURSRbVv09i0P7-cfVh26aQgGnKg,16837 +django/contrib/admin/locale/es_VE/LC_MESSAGES/django.po,sha256=mlmaSYIHpa-Vp3f3NJfdt2RXB88CVZRoPEMfl-tccr0,18144 +django/contrib/admin/locale/es_VE/LC_MESSAGES/djangojs.mo,sha256=Zy-Hj_Mr2FiMiGGrZyssN7GZJrbxRj3_yKQFZKR36Ro,4635 +django/contrib/admin/locale/es_VE/LC_MESSAGES/djangojs.po,sha256=RI8CIdewjL3bAivniMOl7lA9tD7caP4zEo2WK71cX7c,5151 +django/contrib/admin/locale/et/LC_MESSAGES/django.mo,sha256=gI1NvY-KjRooKDisjdXZFzRqB-0Vu-mae3CnnDAyq20,17688 +django/contrib/admin/locale/et/LC_MESSAGES/django.po,sha256=1qDdgjOcjMoHNqvuaIgEH_qn2Y-3XspgVaDg3Mj1Bpw,19144 +django/contrib/admin/locale/et/LC_MESSAGES/djangojs.mo,sha256=VftLeDX1ngXgy3Rvztk21zNcPus9Vbr-Gp4MnChaRbM,5880 +django/contrib/admin/locale/et/LC_MESSAGES/djangojs.po,sha256=yi-8VC9eCScS98u4CIDirsfG_a5-BDnO0XrI9Gm4lK8,6718 +django/contrib/admin/locale/eu/LC_MESSAGES/django.mo,sha256=CBk_9H8S8LlK8hfGQsEB7IgSms-BsURzAFrX9Zrsw4c,15009 +django/contrib/admin/locale/eu/LC_MESSAGES/django.po,sha256=9vnPgJRPcdSa4P5rguB5zqWQC1xAt4POzDw-mSD8UHs,17489 +django/contrib/admin/locale/eu/LC_MESSAGES/djangojs.mo,sha256=vKtO_mbexiW-EO-L-G0PYruvc8N7GOF94HWQCkDnJNQ,4480 +django/contrib/admin/locale/eu/LC_MESSAGES/djangojs.po,sha256=BAWU-6kH8PLBxx_d9ZeeueB_lV5KFXjbRJXgKN43nQ4,5560 +django/contrib/admin/locale/fa/LC_MESSAGES/django.mo,sha256=Y01G4go-V_BZ1aR7u5Z9StnqL0BS5kvj2ZlSfffhToY,20889 +django/contrib/admin/locale/fa/LC_MESSAGES/django.po,sha256=1q914M9N6NfUgP72mIhTRMYukc1r-GpVV5Pt4qESTTM,23054 +django/contrib/admin/locale/fa/LC_MESSAGES/djangojs.mo,sha256=MAje4ub3vWYhiKrVR_LvxAIqkvOlFpVcXQEBz3ezlPs,6050 +django/contrib/admin/locale/fa/LC_MESSAGES/djangojs.po,sha256=1nzEmRuswDmyCCMShGH2CYdjMY7tUuedfN4kDCEnTCM,6859 +django/contrib/admin/locale/fi/LC_MESSAGES/django.mo,sha256=o2bZycvUaAigyMRW2EOSkqJy2Xq0BfvGB2eEWV-h9jg,17289 +django/contrib/admin/locale/fi/LC_MESSAGES/django.po,sha256=dBux4oefCngbb6PCukB-U6XrpY5tym9B0CMIsWk2LIs,18990 +django/contrib/admin/locale/fi/LC_MESSAGES/djangojs.mo,sha256=ZIJoZ4T-2iNfpdHiyqsKTqIC9lgGAPOCbQhk7Lh36N4,5822 +django/contrib/admin/locale/fi/LC_MESSAGES/djangojs.po,sha256=6suDw1Cj_AVqQocM67EN7ZZs6hWgvTa9TP80a7Y9xaM,6742 +django/contrib/admin/locale/fr/LC_MESSAGES/django.mo,sha256=1QY9Y9b-KAiBDCb0dXIuY_arRLWtMNU3pmXuJ0Te9GU,19735 +django/contrib/admin/locale/fr/LC_MESSAGES/django.po,sha256=8xUKptALeNs3H8kjC3mRbnxRdWWS-zNJvUdlRA5tYDk,21097 +django/contrib/admin/locale/fr/LC_MESSAGES/djangojs.mo,sha256=eSiwCTcZrv3jKlu_KVL9myvW6Yc6lSWx1CcA_T6qSng,6509 +django/contrib/admin/locale/fr/LC_MESSAGES/djangojs.po,sha256=lfTg4_vFyMbkCqTThaSn4f-D2S0sGNdW0PFWJgBz2ck,7226 +django/contrib/admin/locale/fy/LC_MESSAGES/django.mo,sha256=mWnHXGJUtiewo1F0bsuJCE_YBh7-Ak9gjTpwjOAv-HI,476 +django/contrib/admin/locale/fy/LC_MESSAGES/django.po,sha256=oSKEF_DInUC42Xzhw9HiTobJjE2fLNI1VE5_p6rqnCE,10499 +django/contrib/admin/locale/fy/LC_MESSAGES/djangojs.mo,sha256=YQQy7wpjBORD9Isd-p0lLzYrUgAqv770_56-vXa0EOc,476 +django/contrib/admin/locale/fy/LC_MESSAGES/djangojs.po,sha256=efBDCcu43j4SRxN8duO5Yfe7NlpcM88kUPzz-qOkC04,2864 +django/contrib/admin/locale/ga/LC_MESSAGES/django.mo,sha256=cIOjVge5KC37U6g-0MMaP5p8N0XJxzK6oJqWNUw9jfI,15075 +django/contrib/admin/locale/ga/LC_MESSAGES/django.po,sha256=Qx1D0cEGIIPnO10I_83IfU3faEYpp0lm-KHg48lJMxE,17687 +django/contrib/admin/locale/ga/LC_MESSAGES/djangojs.mo,sha256=G-9VfhiMcooTbAI1IMvbvUwj_h_ttNyxGS89nIgrpw4,5247 +django/contrib/admin/locale/ga/LC_MESSAGES/djangojs.po,sha256=DsDMYhm5PEpFBBGepf2iRD0qCkh2r45Y4tIHzFtjJAo,5920 +django/contrib/admin/locale/gd/LC_MESSAGES/django.mo,sha256=HEqiGvjMp0NnfIS0Z-c1i8SicEtMPIg8LvNMh-SXiPg,18871 +django/contrib/admin/locale/gd/LC_MESSAGES/django.po,sha256=cZWnJyEoyGFLbk_M4-eddTJLKJ0dqTIlIj4w6YwcjJg,20139 +django/contrib/admin/locale/gd/LC_MESSAGES/djangojs.mo,sha256=QA2_hxHGzt_y0U8sAGQaT27IvvyWrehLPKP2X1jAvEs,5904 +django/contrib/admin/locale/gd/LC_MESSAGES/djangojs.po,sha256=KyYGpFHq2E55dK005xzH0I2RD-C2kD6BlJi8bcMjtRA,6540 +django/contrib/admin/locale/gl/LC_MESSAGES/django.mo,sha256=AyUqVwwqjtw-ZNvqUoo7AYO60eC2sl0uy-A7r1EnN6Y,18208 +django/contrib/admin/locale/gl/LC_MESSAGES/django.po,sha256=Z646Tjw4KbPaRebWOvre9tgtXPlxZ2dbiFeNJPruMCk,19764 +django/contrib/admin/locale/gl/LC_MESSAGES/djangojs.mo,sha256=AePXV8VZToob6vNEsOqyuijJYv-QxRfBO7BrBUgLi_Q,6083 +django/contrib/admin/locale/gl/LC_MESSAGES/djangojs.po,sha256=eDMuV05SuQrACfcovaPb8Zsk8hP4g1GMx6507QNFAko,6868 +django/contrib/admin/locale/he/LC_MESSAGES/django.mo,sha256=DQnjAK201x7Zp_eoZiuq6GJZ7ML2WVeP5dXJNaeSEBs,19856 +django/contrib/admin/locale/he/LC_MESSAGES/django.po,sha256=-YnanZ_omTTjDkO8o-chGB6NSsKGLWmO7aWGnIUiJv8,21341 +django/contrib/admin/locale/he/LC_MESSAGES/djangojs.mo,sha256=E-ZlEnXIeJIkXWcthR9kgNJBzDp6gT7mKKDUpEVqM7k,6893 +django/contrib/admin/locale/he/LC_MESSAGES/djangojs.po,sha256=1tenNpIJmcT5wTRNETkSO7cDlDlL1Mqpnb-klRlHw-s,7809 +django/contrib/admin/locale/hi/LC_MESSAGES/django.mo,sha256=yWjTYyrVxXxwBWgPsC7IJ9IxL_85v378To4PCEEcwuI,13811 +django/contrib/admin/locale/hi/LC_MESSAGES/django.po,sha256=FpKFToDAMsgc1aG6-CVpi5wAxhMQjkZxz_89kCiKmS4,19426 +django/contrib/admin/locale/hi/LC_MESSAGES/djangojs.mo,sha256=yCUHDS17dQDKcAbqCg5q8ualaUgaa9qndORgM-tLCIw,4893 +django/contrib/admin/locale/hi/LC_MESSAGES/djangojs.po,sha256=U9rb5tPMICK50bRyTl40lvn-tvh6xL_6o7xIPkzfKi0,6378 +django/contrib/admin/locale/hr/LC_MESSAGES/django.mo,sha256=3TR3uFcd0pnkDi551WaB9IyKX1aOazH7USxqc0lA0KQ,14702 +django/contrib/admin/locale/hr/LC_MESSAGES/django.po,sha256=qcW7tvZoWZIR8l-nMRexGDD8VlrOD7l5Fah6-ecilMk,17378 +django/contrib/admin/locale/hr/LC_MESSAGES/djangojs.mo,sha256=KR34lviGYh1esCkPE9xcDE1pQ_q-RxK1R2LPjnG553w,3360 +django/contrib/admin/locale/hr/LC_MESSAGES/djangojs.po,sha256=w7AqbYcLtu88R3KIKKKXyRt2gwBBBnr-ulxONWbw01I,4870 +django/contrib/admin/locale/hsb/LC_MESSAGES/django.mo,sha256=PPTNUZAf0rsc54f01Xgntn3dIwGQuDpUj-48YbyVqic,18595 +django/contrib/admin/locale/hsb/LC_MESSAGES/django.po,sha256=AYuTF9tLEEtt1xbIVwjxP4ijfBYJ11VoxxLoUOtyvUM,19883 +django/contrib/admin/locale/hsb/LC_MESSAGES/djangojs.mo,sha256=4kIdcgSBZ5ldlS0LKZV8-gh45-AcRTMQc784VmoRmP8,6693 +django/contrib/admin/locale/hsb/LC_MESSAGES/djangojs.po,sha256=7Lx6Be_8i8g2GtqOfc1UKpKgwF2CFXfYG4PrjKV0t-0,7425 +django/contrib/admin/locale/hu/LC_MESSAGES/django.mo,sha256=fMea7oqZDrBAicpyubIq-JCPg_7QBws7N0PdyBwebOo,18629 +django/contrib/admin/locale/hu/LC_MESSAGES/django.po,sha256=eFRlDToCWD_BZVyRxW6L_xLIfItPmHQshxoOFC53iV0,20211 +django/contrib/admin/locale/hu/LC_MESSAGES/djangojs.mo,sha256=tXeG5F6_Yh6qHmNUNrlgzavH1Wc8NZb3fj4oEW9qE_M,6034 +django/contrib/admin/locale/hu/LC_MESSAGES/djangojs.po,sha256=pvn7ae43zgVp3mpjXPI7_JCqvQLaHZZF7hTasP2uZx0,6854 +django/contrib/admin/locale/hy/LC_MESSAGES/django.mo,sha256=Dcx9cOsYBfbgQgoAQoLhn_cG1d2sKGV6dag4DwnUTaY,18274 +django/contrib/admin/locale/hy/LC_MESSAGES/django.po,sha256=CnQlRZ_DUILMIqVEgUTT2sufAseEKJHHjWsYr_LAqi8,20771 +django/contrib/admin/locale/hy/LC_MESSAGES/djangojs.mo,sha256=ttfGmyEN0-3bM-WmfCge2lG8inubMPOzFXfZrfX9sfw,5636 +django/contrib/admin/locale/hy/LC_MESSAGES/djangojs.po,sha256=jf94wzUOMQaKSBR-77aijQXfdRAqiYSeAQopiT_8Obc,6046 +django/contrib/admin/locale/ia/LC_MESSAGES/django.mo,sha256=SRKlr8RqW8FQhzMsXdA9HNqttO3hc0xf4QdQJd4Dy8c,11278 +django/contrib/admin/locale/ia/LC_MESSAGES/django.po,sha256=pBQLQsMinRNh0UzIHBy3qEW0etUWMhFALu4-h-woFyE,15337 +django/contrib/admin/locale/ia/LC_MESSAGES/djangojs.mo,sha256=28MiqUf-0-p3PIaongqgPQp2F3D54MLAujPslVACAls,3177 +django/contrib/admin/locale/ia/LC_MESSAGES/djangojs.po,sha256=CauoEc8Fiowa8k6K-f9N8fQDle40qsgtXdNPDHBiudQ,4567 +django/contrib/admin/locale/id/LC_MESSAGES/django.mo,sha256=BbHXk2gBFjpTrcKNoZmuToaXp2MaHTWtZs4yNtJYRXs,16890 +django/contrib/admin/locale/id/LC_MESSAGES/django.po,sha256=hoh_j300x-sD-g8Ts7EDym-lHeCVoFTsd74dD6gGfms,18846 +django/contrib/admin/locale/id/LC_MESSAGES/djangojs.mo,sha256=aCPmIcwloBrlvfAf95HZfOgVs7XU9Bp064Sn08pQK1E,5275 +django/contrib/admin/locale/id/LC_MESSAGES/djangojs.po,sha256=x_D6AQiyGC-AJL889Q51JkmlqiVHfyAwGdA3Ck9_Z7Q,6589 +django/contrib/admin/locale/io/LC_MESSAGES/django.mo,sha256=URiYZQZpROBedC-AkpVo0q3Tz78VfkmwN1W7j6jYpMo,12624 +django/contrib/admin/locale/io/LC_MESSAGES/django.po,sha256=y0WXY7v_9ff-ZbFasj33loG-xWlFO8ttvCB6YPyF7FQ,15562 +django/contrib/admin/locale/io/LC_MESSAGES/djangojs.mo,sha256=nMu5JhIy8Fjie0g5bT8-h42YElCiS00b4h8ej_Ie-w0,464 +django/contrib/admin/locale/io/LC_MESSAGES/djangojs.po,sha256=WLh40q6yDs-8ZG1hpz6kfMQDXuUzOZa7cqtEPDywxG4,2852 +django/contrib/admin/locale/is/LC_MESSAGES/django.mo,sha256=csD3bmz3iQgLLdSqCKOmY_d893147TvDumrpRVoRTY0,16804 +django/contrib/admin/locale/is/LC_MESSAGES/django.po,sha256=tXgb3ARXP5tPa5iEYwwiHscDGfjS5JgIV2BsUX8OnjE,18222 +django/contrib/admin/locale/is/LC_MESSAGES/djangojs.mo,sha256=Z3ujWoenX5yYTAUmHUSCvHcuV65nQmYKPv6Jo9ygx_c,5174 +django/contrib/admin/locale/is/LC_MESSAGES/djangojs.po,sha256=YPf4XqfnpvrS9irAS8O4G0jgU5PCoQ9C-w3MoDipelk,5847 +django/contrib/admin/locale/it/LC_MESSAGES/django.mo,sha256=N_pVjbd3SkV4xtFMvwtlwRWo_ulGR83SzKcPD8wiFgY,18505 +django/contrib/admin/locale/it/LC_MESSAGES/django.po,sha256=hVYj4UvphkCqlFzH6NtyRAZgGewCKNjVnON0vHtxGKY,20338 +django/contrib/admin/locale/it/LC_MESSAGES/djangojs.mo,sha256=FWtyPVubufiaNKFxy4DQ0KbW93GUt-x1Mc8ZKhqokwg,5640 +django/contrib/admin/locale/it/LC_MESSAGES/djangojs.po,sha256=VRqeY7gYmcP5oWVMgpHL_Br8cAkFXphFQStFpIbWOrc,6578 +django/contrib/admin/locale/ja/LC_MESSAGES/django.mo,sha256=pEWwLYIk8nVcLmcu3Tct302q3Xvn4J57FHMqnVnULeQ,19662 +django/contrib/admin/locale/ja/LC_MESSAGES/django.po,sha256=ygZMeeG0Q7C9wUnH08hgUGdLbbCpkCcELIiXM2CqLhQ,21249 +django/contrib/admin/locale/ja/LC_MESSAGES/djangojs.mo,sha256=XBOtJbkByhQEMUxvnqSr1XhBCe-DsII4Ke5pISJZAb8,6233 +django/contrib/admin/locale/ja/LC_MESSAGES/djangojs.po,sha256=SrJeh3-t73Z2gY7nVP01cgZE6H11pryDms1pqrQKjnw,6968 +django/contrib/admin/locale/ka/LC_MESSAGES/django.mo,sha256=M3FBRrXFFa87DlUi0HDD_n7a_0IYElQAOafJoIH_i60,20101 +django/contrib/admin/locale/ka/LC_MESSAGES/django.po,sha256=abkt7pw4Kc-Y74ZCpAk_VpFWIkr7trseCtQdM6IUYpQ,23527 +django/contrib/admin/locale/ka/LC_MESSAGES/djangojs.mo,sha256=GlPU3qUavvU0FXPfvCl-8KboYhDOmMsKM-tv14NqOac,5516 +django/contrib/admin/locale/ka/LC_MESSAGES/djangojs.po,sha256=jDpB9c_edcLoFPHFIogOSPrFkssOjIdxtCA_lum8UCs,6762 +django/contrib/admin/locale/kab/LC_MESSAGES/django.mo,sha256=9QKEWgr8YQV17OJ14rMusgV8b79ZgOOsX4aIFMZrEto,3531 +django/contrib/admin/locale/kab/LC_MESSAGES/django.po,sha256=cSOG_HqsNE4tA5YYDd6txMFoUul8d5UKvk77ZhaqOK0,11711 +django/contrib/admin/locale/kab/LC_MESSAGES/djangojs.mo,sha256=nqwZHJdtjHUSFDJmC0nPNyvWcAdcoRcN3f-4XPIItvs,1844 +django/contrib/admin/locale/kab/LC_MESSAGES/djangojs.po,sha256=tF3RH22p2E236Cv6lpIWQxtuPFeWOvJ-Ery3vBUv6co,3713 +django/contrib/admin/locale/kk/LC_MESSAGES/django.mo,sha256=f2WU3e7dOz0XXHFFe0gnCm1MAPCJ9sva2OUnWYTHOJg,12845 +django/contrib/admin/locale/kk/LC_MESSAGES/django.po,sha256=D1vF3nqANT46f17Gc2D2iGCKyysHAyEmv9nBei6NRA4,17837 +django/contrib/admin/locale/kk/LC_MESSAGES/djangojs.mo,sha256=cBxp5pFJYUF2-zXxPVBIG06UNq6XAeZ72uRLwGeLbiE,2387 +django/contrib/admin/locale/kk/LC_MESSAGES/djangojs.po,sha256=Y30fcDpi31Fn7DU7JGqROAiZY76iumoiW9qGAgPCCbU,4459 +django/contrib/admin/locale/km/LC_MESSAGES/django.mo,sha256=eOe9EcFPzAWrTjbGUr-m6RAz2TryC-qHKbqRP337lPY,10403 +django/contrib/admin/locale/km/LC_MESSAGES/django.po,sha256=RSxy5vY2sgC43h-9sl6eomkFvxClvH_Ka4lFiwTvc2I,17103 +django/contrib/admin/locale/km/LC_MESSAGES/djangojs.mo,sha256=Ja8PIXmw6FMREHZhhBtGrr3nRKQF_rVjgLasGPnU95w,1334 +django/contrib/admin/locale/km/LC_MESSAGES/djangojs.po,sha256=LH4h4toEgpVBb9yjw7d9JQ8sdU0WIZD-M025JNlLXAU,3846 +django/contrib/admin/locale/kn/LC_MESSAGES/django.mo,sha256=955iPq05ru6tm_iPFVMebxwvZMtEa5_7GaFG1mPt6HU,9203 +django/contrib/admin/locale/kn/LC_MESSAGES/django.po,sha256=-4YAm0MyhS-wp4RQmo0TzWvqYqmzHFNpIBtdQlg_8Dw,16059 +django/contrib/admin/locale/kn/LC_MESSAGES/djangojs.mo,sha256=kJsCOGf62XOWTKcB9AF6Oc-GqHl2LFtz-qw0spjcU_w,1847 +django/contrib/admin/locale/kn/LC_MESSAGES/djangojs.po,sha256=zzl7QZ5DfdyNWrkIqYlpUcZiTdlZXx_ktahyXqM2-0Q,5022 +django/contrib/admin/locale/ko/LC_MESSAGES/django.mo,sha256=Q6ARBDqvyPrAuVuwP3C7GhCXl71kgP4KaTF7EUvVPCc,18524 +django/contrib/admin/locale/ko/LC_MESSAGES/django.po,sha256=rh6WGn5SaCpjGSZ6LImOnQlLnqVv_Kbjrj2-E5dE0tU,20364 +django/contrib/admin/locale/ko/LC_MESSAGES/djangojs.mo,sha256=wZ2hHD7BJgl855rxKburyumBSS7ECkL3kqNv2col5mo,5985 +django/contrib/admin/locale/ko/LC_MESSAGES/djangojs.po,sha256=qvndtDKv_TIoeYuEErRb62oSaCeS2iFYkjyZ4m8YKHI,6899 +django/contrib/admin/locale/ky/LC_MESSAGES/django.mo,sha256=eg-TnIzJO4h3q_FS2a1LnCs7qOf5dpNJwvRD99ZZ0GQ,20129 +django/contrib/admin/locale/ky/LC_MESSAGES/django.po,sha256=dWxU3yUAKHUGKdVJbRLkS6fJEefPBk2XM0i2INcRPms,21335 +django/contrib/admin/locale/ky/LC_MESSAGES/djangojs.mo,sha256=VuBYBwFwIHC27GFZiHY2_4AB0cME2R0Q3juczjOs3G0,5888 +django/contrib/admin/locale/ky/LC_MESSAGES/djangojs.po,sha256=uMk9CxL1wP45goq2093lYMza7LRuO4XbVo5RRWlsbaE,6432 +django/contrib/admin/locale/lb/LC_MESSAGES/django.mo,sha256=8GGM2sYG6GQTQwQFJ7lbg7w32SvqgSzNRZIUi9dIe6M,913 +django/contrib/admin/locale/lb/LC_MESSAGES/django.po,sha256=PZ3sL-HvghnlIdrdPovNJP6wDrdDMSYp_M1ok6dodrw,11078 +django/contrib/admin/locale/lb/LC_MESSAGES/djangojs.mo,sha256=xokesKl7h7k9dXFKIJwGETgwx1Ytq6mk2erBSxkgY-o,474 +django/contrib/admin/locale/lb/LC_MESSAGES/djangojs.po,sha256=fiMelo6K0_RITx8b9k26X1R86Ck2daQXm86FLJpzt20,2862 +django/contrib/admin/locale/lt/LC_MESSAGES/django.mo,sha256=SpaNUiaGtDlX5qngVj0dWdqNLSin8EOXXyBvRM9AnKg,17033 +django/contrib/admin/locale/lt/LC_MESSAGES/django.po,sha256=tHnRrSNG2ENVduP0sOffCIYQUn69O6zIev3Bb7PjKb0,18497 +django/contrib/admin/locale/lt/LC_MESSAGES/djangojs.mo,sha256=vZtnYQupzdTjVHnWrtjkC2QKNpsca5yrpb4SDuFx0_0,5183 +django/contrib/admin/locale/lt/LC_MESSAGES/djangojs.po,sha256=dMjFClA0mh5g0aNFTyHC8nbYxwmFD0-j-7gCKD8NFnw,5864 +django/contrib/admin/locale/lv/LC_MESSAGES/django.mo,sha256=qnmTqpnBJEZzdLt_6_1e4aSLHPbF10Xtmilsx2LpzTo,18245 +django/contrib/admin/locale/lv/LC_MESSAGES/django.po,sha256=jsY_Q1nP53Qiy5X4O9Bsi_GQaBdwGkPkK__SfxZH7zM,19825 +django/contrib/admin/locale/lv/LC_MESSAGES/djangojs.mo,sha256=TfQupQgc6UMUbj_6MoEEO87VmZTsh2McSDl_4Dsqgvo,6446 +django/contrib/admin/locale/lv/LC_MESSAGES/djangojs.po,sha256=cT0J4Bvh8UEdNq2HphcOwJBkgXwXNXl-xhwNt6GBcqg,7336 +django/contrib/admin/locale/mk/LC_MESSAGES/django.mo,sha256=xcKetKf7XcO-4vbWEIoI2c40gRE2twuiINaby6ypO7Q,17948 +django/contrib/admin/locale/mk/LC_MESSAGES/django.po,sha256=hx2peq-wztDHtiST_zZ58c7rjZ6jSvDDXhVOTmyUDzI,21063 +django/contrib/admin/locale/mk/LC_MESSAGES/djangojs.mo,sha256=8BkWjadml2f1lDeH-IULdxsogXSK8NpVuu293GvcQc8,4719 +django/contrib/admin/locale/mk/LC_MESSAGES/djangojs.po,sha256=u9mVSzbIgA1uRgV_L8ZOZLelyknoKFvXH0HbBurezf8,6312 +django/contrib/admin/locale/ml/LC_MESSAGES/django.mo,sha256=4Y1KAip3NNsoRc9Zz3k0YFLzes3DNRFvAXWSTBivXDk,20830 +django/contrib/admin/locale/ml/LC_MESSAGES/django.po,sha256=jL9i3kmOnoKYDq2RiF90WCc55KeA8EBN9dmPHjuUfmo,24532 +django/contrib/admin/locale/ml/LC_MESSAGES/djangojs.mo,sha256=COohY0mAHAOkv1eNzLkaGZy8mimXzcDK1EgRd3tTB_E,6200 +django/contrib/admin/locale/ml/LC_MESSAGES/djangojs.po,sha256=NvN0sF_w5tkc3bND4lBtCHsIDLkwqdEPo-8wi2MTQ14,7128 +django/contrib/admin/locale/mn/LC_MESSAGES/django.mo,sha256=Lu8mM_3lJuByz4xXE7shq4nuBwE71_yh4_HIuy7KK64,14812 +django/contrib/admin/locale/mn/LC_MESSAGES/django.po,sha256=yNbv9cOeXEHPiDOKPXIbq2-cBZvUXSXCfL4TPe74x0s,18851 +django/contrib/admin/locale/mn/LC_MESSAGES/djangojs.mo,sha256=H7fIPdWTK3_iuC0WRBJdfXN8zO77p7-IzTviEUVQJ2U,5228 +django/contrib/admin/locale/mn/LC_MESSAGES/djangojs.po,sha256=vJIqqVG34Zd7q8-MhTgZcXTtl6gukOSb6egt70AOyAc,5757 +django/contrib/admin/locale/mr/LC_MESSAGES/django.mo,sha256=UAxGnGliid2PTx6SMgIuHVfbCcqVvcwC4FQUWtDuSTc,468 +django/contrib/admin/locale/mr/LC_MESSAGES/django.po,sha256=TNARpu8Pfmu9fGOLUP0bRwqqDdyFmlh9rWjFspboTyc,10491 +django/contrib/admin/locale/mr/LC_MESSAGES/djangojs.mo,sha256=2Z5jaGJzpiJTCnhCk8ulCDeAdj-WwR99scdHFPRoHoA,468 +django/contrib/admin/locale/mr/LC_MESSAGES/djangojs.po,sha256=uGe9kH2mwrab97Ue77oggJBlrpzZNckKGRUMU1vaigs,2856 +django/contrib/admin/locale/ms/LC_MESSAGES/django.mo,sha256=Xj5v1F4_m1ZFUn42Rbep9eInxIV-NE-oA_NyfQkbp00,16840 +django/contrib/admin/locale/ms/LC_MESSAGES/django.po,sha256=ykFH-mPbv2plm2NIvKgaj3WVukJ3SquU8nQIAXuOrWA,17967 +django/contrib/admin/locale/ms/LC_MESSAGES/djangojs.mo,sha256=9VY_MrHK-dGOIkucLCyR9psy4o5p4nHd8kN_5N2E-gY,5018 +django/contrib/admin/locale/ms/LC_MESSAGES/djangojs.po,sha256=P4GvM17rlX1Vl-7EbCyfWVasAJBEv_RvgWEvfJqcErA,5479 +django/contrib/admin/locale/my/LC_MESSAGES/django.mo,sha256=xvlgM0vdYxZuA7kPQR7LhrLzgmyVCHAvqaqvFhKX9wY,3677 +django/contrib/admin/locale/my/LC_MESSAGES/django.po,sha256=zdUCYcyq2-vKudkYvFcjk95YUtbMDDSKQHCysmQ-Pvc,12522 +django/contrib/admin/locale/my/LC_MESSAGES/djangojs.mo,sha256=1fS9FfWi8b9NJKm3DBKETmuffsrTX-_OHo9fkCCXzpg,3268 +django/contrib/admin/locale/my/LC_MESSAGES/djangojs.po,sha256=-z1j108uoswi9YZfh3vSIswLXu1iUKgDXNdZNEA0yrA,5062 +django/contrib/admin/locale/nb/LC_MESSAGES/django.mo,sha256=viQKBFH6ospYn2sE-DokVJGGYhSqosTgbNMn5sBVnmM,16244 +django/contrib/admin/locale/nb/LC_MESSAGES/django.po,sha256=x0ANRpDhe1rxxAH0qjpPxRfccCvR73_4g5TNUdJqmrc,17682 +django/contrib/admin/locale/nb/LC_MESSAGES/djangojs.mo,sha256=KwrxBpvwveERK4uKTIgh-DCc9aDLumpHQYh5YroqxhQ,4939 +django/contrib/admin/locale/nb/LC_MESSAGES/djangojs.po,sha256=ygn6a5zkHkoIYMC8Hgup8Uw1tMbZcLGgwwDu3x33M-o,5555 +django/contrib/admin/locale/ne/LC_MESSAGES/django.mo,sha256=yrm85YXwXIli7eNaPyBTtV7y3TxQuH4mokKuHdAja2A,15772 +django/contrib/admin/locale/ne/LC_MESSAGES/django.po,sha256=F8vfWKvSNngkLPZUIwik_qDYu0UAnrWepbI9Z9Iz35g,20400 +django/contrib/admin/locale/ne/LC_MESSAGES/djangojs.mo,sha256=mJdtpLT9k4vDbN9fk2fOeiy4q720B3pLD3OjLbAjmUI,5362 +django/contrib/admin/locale/ne/LC_MESSAGES/djangojs.po,sha256=N91RciTV1m7e8-6Ihod5U2xR9K0vrLoFnyXjn2ta098,6458 +django/contrib/admin/locale/nl/LC_MESSAGES/django.mo,sha256=hepksXKWe_PTm0HSeknu5O-CV7v6-Az_BsnBRKWY-_I,18260 +django/contrib/admin/locale/nl/LC_MESSAGES/django.po,sha256=JFj_CcQC1nYd4Vm4hjwz7CL_VecAD69IG06AXD3pdrs,20038 +django/contrib/admin/locale/nl/LC_MESSAGES/djangojs.mo,sha256=iWjyDgay1LIiS6C-Zl33inFKxzM2LFQPIWyKEw2x6Is,6122 +django/contrib/admin/locale/nl/LC_MESSAGES/djangojs.po,sha256=xZjgzxEEWMG2ofgSfLNUU0abr9Y_cUpXIHsmjKBGyig,7217 +django/contrib/admin/locale/nn/LC_MESSAGES/django.mo,sha256=yAdb8Yew1ARlnAnvd5gHL7-SDzpkXedBwCSSPEzGCKk,16504 +django/contrib/admin/locale/nn/LC_MESSAGES/django.po,sha256=sFxr3UYzltQRqiotm_d5Qqtf8iLXI0LgCw_V6kYffJ0,17932 +django/contrib/admin/locale/nn/LC_MESSAGES/djangojs.mo,sha256=RsDri1DmCwrby8m7mLWkFdCe6HK7MD7GindOarVYPWc,4939 +django/contrib/admin/locale/nn/LC_MESSAGES/djangojs.po,sha256=koVTt2mmdku1j7SUDRbnug8EThxXuCIF2XPnGckMi7A,5543 +django/contrib/admin/locale/os/LC_MESSAGES/django.mo,sha256=c51PwfOeLU2YcVNEEPCK6kG4ZyNc79jUFLuNopmsRR8,14978 +django/contrib/admin/locale/os/LC_MESSAGES/django.po,sha256=yugDw7iziHto6s6ATNDK4yuG6FN6yJUvYKhrGxvKmcY,18188 +django/contrib/admin/locale/os/LC_MESSAGES/djangojs.mo,sha256=0gMkAyO4Zi85e9qRuMYmxm6JV98WvyRffOKbBVJ_fLQ,3806 +django/contrib/admin/locale/os/LC_MESSAGES/djangojs.po,sha256=skiTlhgUEN8uKk7ihl2z-Rxr1ZXqu5qV4wB4q9qXVq0,5208 +django/contrib/admin/locale/pa/LC_MESSAGES/django.mo,sha256=EEitcdoS-iQ9QWHPbJBK2ajdN56mBi0BzGnVl3KTmU4,8629 +django/contrib/admin/locale/pa/LC_MESSAGES/django.po,sha256=xscRlOkn9Jc8bDsSRM5bzQxEsCLMVsV-Wwin0rfkHDI,16089 +django/contrib/admin/locale/pa/LC_MESSAGES/djangojs.mo,sha256=Hub-6v7AfF-tWhw53abpyhnVHo76h_xBgGIhlGIcS70,1148 +django/contrib/admin/locale/pa/LC_MESSAGES/djangojs.po,sha256=7L8D4qqhq53XG83NJUZNoM8zCCScwMwzsrzzsyO4lHY,4357 +django/contrib/admin/locale/pl/LC_MESSAGES/django.mo,sha256=cZLqI_ihpYjcA2QJJc82P-2SgYlrK0W7Qps76oFJTJA,19117 +django/contrib/admin/locale/pl/LC_MESSAGES/django.po,sha256=ZjfaLZ1iRZNJUKRyz16sSNqbOi6vH4V2a9Wla6Pph9s,21090 +django/contrib/admin/locale/pl/LC_MESSAGES/djangojs.mo,sha256=J06UuQkB2V4E8XAeUfTHbbjGVeNWAu328oFIeieb588,6655 +django/contrib/admin/locale/pl/LC_MESSAGES/djangojs.po,sha256=E084nmFnaWDKZHwwSVIjBdNc-9tIfgGWCl58GqbVRP8,7808 +django/contrib/admin/locale/pt/LC_MESSAGES/django.mo,sha256=jZNC62eFhnXnFY9MmqXGoELL7aH8OaJZ2h3cAYWnOWU,18681 +django/contrib/admin/locale/pt/LC_MESSAGES/django.po,sha256=ZGTP8N_3zvTyHBPXnmIch3pA4vafqalk__-lqyhkJps,20270 +django/contrib/admin/locale/pt/LC_MESSAGES/djangojs.mo,sha256=RlsEslBxu8-1AJUz6olYHOVpqnV2kXrYXjxsMPHWGHs,5392 +django/contrib/admin/locale/pt/LC_MESSAGES/djangojs.po,sha256=D1sNOYDTY1DsaGC09V4nAaMea-FvW6UWOpnknP2F5uE,6716 +django/contrib/admin/locale/pt_BR/LC_MESSAGES/django.mo,sha256=UBAD_y4oqXWKuElSFpx2tya8ZbhxAxhts4aNBe-ErI0,18522 +django/contrib/admin/locale/pt_BR/LC_MESSAGES/django.po,sha256=UuB_DIBFoLpxzUQrkC2xco4HuOhcqBfX44GmScF34PM,21104 +django/contrib/admin/locale/pt_BR/LC_MESSAGES/djangojs.mo,sha256=OA_7ScHq4Q9IfEbAuF6exOBm1FC7kvpPFRQCh4ymzTI,6383 +django/contrib/admin/locale/pt_BR/LC_MESSAGES/djangojs.po,sha256=15uaFoplwLiUe1T1lJ3rroUSuFkfRO3-n4ilL5wkqKA,7496 +django/contrib/admin/locale/ro/LC_MESSAGES/django.mo,sha256=SEbnJ1aQ3m2nF7PtqzKvYYCdvgg_iG5hzrdO_Xxiv_k,15157 +django/contrib/admin/locale/ro/LC_MESSAGES/django.po,sha256=wPfGo9yi3j28cwikkogZ_erQKtUZ9WmzdZ2FuMVugFE,18253 +django/contrib/admin/locale/ro/LC_MESSAGES/djangojs.mo,sha256=voEqSN3JUgJM9vumLxE_QNPV7kA0XOoTktN7E7AYV6o,4639 +django/contrib/admin/locale/ro/LC_MESSAGES/djangojs.po,sha256=SO7FAqNnuvIDfZ_tsWRiwSv91mHx5NZHyR2VnmoYBWY,5429 +django/contrib/admin/locale/ru/LC_MESSAGES/django.mo,sha256=L9mScttwmJqxjUENCjHY0oKMWxyHWmwFRVyULzL36yg,23848 +django/contrib/admin/locale/ru/LC_MESSAGES/django.po,sha256=k_mhtXgOKBTMa2LJ4EhuExdQ36KgDJUmE3nRfky4yko,25634 +django/contrib/admin/locale/ru/LC_MESSAGES/djangojs.mo,sha256=TE4M5XbCJ3tX4pTzyTbLG_xjtCtqZzVg1ZXSxeSXgcU,8392 +django/contrib/admin/locale/ru/LC_MESSAGES/djangojs.po,sha256=owCCQnZqwfIOG3zZucZPwOh47TnDS59ItQwzYeEexvM,9546 +django/contrib/admin/locale/sk/LC_MESSAGES/django.mo,sha256=H_cS4U4rG97oRDxFyCx5VRPAHTbEGCDdIvmZPnSkFpI,18706 +django/contrib/admin/locale/sk/LC_MESSAGES/django.po,sha256=_innyhCl5gRfmmU_yRudZQYvhANGYbNwXt3x-85Ftdo,20366 +django/contrib/admin/locale/sk/LC_MESSAGES/djangojs.mo,sha256=sl2PRwXLtikrOiHJ_EEltZivpV5IwT5lmbyfpGCSrLo,6305 +django/contrib/admin/locale/sk/LC_MESSAGES/djangojs.po,sha256=-ZcKl0UxOObVuB_8My20fdjCrV51drP4w-yan3X-RKk,7275 +django/contrib/admin/locale/sl/LC_MESSAGES/django.mo,sha256=rBSsaXNtCo43Cri9Gq_Ueq2IUNMBmzOV6lgMm7xF_p0,15077 +django/contrib/admin/locale/sl/LC_MESSAGES/django.po,sha256=ywIn4PB3xg6Q27NARZ3JRmSvNhcRFKU8nF_gbgA93qg,18281 +django/contrib/admin/locale/sl/LC_MESSAGES/djangojs.mo,sha256=--wrlI4_qva1mlKR9ehUjaYGA5LLIY9otgvq7BYtUic,4637 +django/contrib/admin/locale/sl/LC_MESSAGES/djangojs.po,sha256=u-8YLLTAOmAQHA6qIGPueP6BOswjPctbFc8L8FrX51w,5956 +django/contrib/admin/locale/sq/LC_MESSAGES/django.mo,sha256=BvopdAM_n5_8NKTHCGwvYOdWSRtGR2UxAI5Z1B6A8eg,18567 +django/contrib/admin/locale/sq/LC_MESSAGES/django.po,sha256=BTWn1XFX5IlOY1UDoEAITd8YNfOK4kU_r3Logl6AdDQ,19903 +django/contrib/admin/locale/sq/LC_MESSAGES/djangojs.mo,sha256=JZd4AaMh0TPnT1bCSyDLWwRMMCVN9C8w3Ubd-UkLDWI,6122 +django/contrib/admin/locale/sq/LC_MESSAGES/djangojs.po,sha256=h0TU4rJnZ4KwpaL1mt8SiNvAQGuGVIFB1j4nh7vb7UI,6864 +django/contrib/admin/locale/sr/LC_MESSAGES/django.mo,sha256=gzt54HuzoQlvYNxrdVm_FjuBu-P8jMeKFK8FEuoG084,22776 +django/contrib/admin/locale/sr/LC_MESSAGES/django.po,sha256=tidHRus1NLzf3Xln_HUMn8q5rq5zNd3iqY5Syl53vQw,24151 +django/contrib/admin/locale/sr/LC_MESSAGES/djangojs.mo,sha256=1GW3zhwJYBiH5c0dmy4sXOsnt1r88LiHSZdlJ5IP1bI,7234 +django/contrib/admin/locale/sr/LC_MESSAGES/djangojs.po,sha256=AY4qY7h8JdA4WgOam0lSeVp0nUz2fdiLNHrFRNh2jLQ,8013 +django/contrib/admin/locale/sr_Latn/LC_MESSAGES/django.mo,sha256=8wcRn4O2WYMFJal760MvjtSPBNoDgHAEYtedg8CC7Ao,12383 +django/contrib/admin/locale/sr_Latn/LC_MESSAGES/django.po,sha256=N4fPEJTtUrQnc8q1MioPZ2a7E55YXrE-JvfAcWZubfA,16150 +django/contrib/admin/locale/sr_Latn/LC_MESSAGES/djangojs.mo,sha256=qyZM6sLb6BxwYxvrSOn3JRYtkU6LUxUvhB_JEf9V13M,5466 +django/contrib/admin/locale/sr_Latn/LC_MESSAGES/djangojs.po,sha256=2cJ1HPgHoj35lJZgIwWoYVESVjtW7xoZvQc7--AMI2U,6176 +django/contrib/admin/locale/sv/LC_MESSAGES/django.mo,sha256=DSX1yVs7X6KKjbQnKiHoWj955tWMKhT-jf5_YDdvyFE,17324 +django/contrib/admin/locale/sv/LC_MESSAGES/django.po,sha256=oqzCJzH71YWPBRbm3vHX1ATlToCC_JJXBuk4oHjP1Os,19352 +django/contrib/admin/locale/sv/LC_MESSAGES/djangojs.mo,sha256=j074t-0MbCkMAmo2_7VLGedSV1JMVpmqkn8Ar_odYIQ,5238 +django/contrib/admin/locale/sv/LC_MESSAGES/djangojs.po,sha256=LkmbaR8L6-VRaJkLCoAUdQlNKed5AJQRytwGrZRgCR0,6829 +django/contrib/admin/locale/sw/LC_MESSAGES/django.mo,sha256=Fvjpp8hZ8y6j4CvJYx_WKU7jZxm_nk_vt9ZFjj60Y-c,17415 +django/contrib/admin/locale/sw/LC_MESSAGES/django.po,sha256=flVzbBKoanskhi_Eh4xlQXRRcQ8W9lmMwyw13UIDHoA,18962 +django/contrib/admin/locale/sw/LC_MESSAGES/djangojs.mo,sha256=p0pi6-Zg-qsDVMDjNHO4aav3GfJ3tKKhy6MK7mPtC50,3647 +django/contrib/admin/locale/sw/LC_MESSAGES/djangojs.po,sha256=lZFP7Po4BM_QMTj-SXGlew1hqyJApZxu0lxMP-YduHI,4809 +django/contrib/admin/locale/ta/LC_MESSAGES/django.mo,sha256=ZdtNRZLRqquwMk7mE0XmTzEjTno9Zni3mV6j4DXL4nI,10179 +django/contrib/admin/locale/ta/LC_MESSAGES/django.po,sha256=D0TCLM4FFF7K9NqUGXNFE2KfoEzx5IHcJQ6-dYQi2Eg,16881 +django/contrib/admin/locale/ta/LC_MESSAGES/djangojs.mo,sha256=2-37FOw9Bge0ahIRxFajzxvMkAZL2zBiQFaELmqyhhY,1379 +django/contrib/admin/locale/ta/LC_MESSAGES/djangojs.po,sha256=Qs-D7N3ZVzpZVxXtMWKOzJfSmu_Mk9pge5W15f21ihI,3930 +django/contrib/admin/locale/te/LC_MESSAGES/django.mo,sha256=aIAG0Ey4154R2wa-vNe2x8X4fz2L958zRmTpCaXZzds,10590 +django/contrib/admin/locale/te/LC_MESSAGES/django.po,sha256=-zJYrDNmIs5fp37VsG4EAOVefgbBNl75c-Pp3RGBDAM,16941 +django/contrib/admin/locale/te/LC_MESSAGES/djangojs.mo,sha256=VozLzWQwrY-USvin5XyVPtUUKEmCr0dxaWC6J14BReo,1362 +django/contrib/admin/locale/te/LC_MESSAGES/djangojs.po,sha256=HI8IfXqJf4I6i-XZB8ELGyp5ZNr-oi5hW9h7n_8XSaQ,3919 +django/contrib/admin/locale/tg/LC_MESSAGES/django.mo,sha256=gJfgsEn9doTT0erBK77OBDi7_0O7Rb6PF9tRPacliXU,15463 +django/contrib/admin/locale/tg/LC_MESSAGES/django.po,sha256=Wkx7Hk2a9OzZymgrt9N91OL9K5HZXTbpPBXMhyE0pjI,19550 +django/contrib/admin/locale/tg/LC_MESSAGES/djangojs.mo,sha256=SEaBcnnKupXbTKCJchkSu_dYFBBvOTAOQSZNbCYUuHE,5154 +django/contrib/admin/locale/tg/LC_MESSAGES/djangojs.po,sha256=CfUjLtwMmz1h_MLE7c4UYv05ZTz_SOclyKKWmVEP9Jg,5978 +django/contrib/admin/locale/th/LC_MESSAGES/django.mo,sha256=EVlUISdKOvNkGMG4nbQFzSn5p7d8c9zOGpXwoHsHNlY,16394 +django/contrib/admin/locale/th/LC_MESSAGES/django.po,sha256=OqhGCZ87VX-WKdC2EQ8A8WeXdWXu9mj6k8mG9RLZMpM,20187 +django/contrib/admin/locale/th/LC_MESSAGES/djangojs.mo,sha256=ukj5tyDor9COi5BT9oRLucO2wVTI6jZWclOM-wNpXHM,6250 +django/contrib/admin/locale/th/LC_MESSAGES/djangojs.po,sha256=3L5VU3BNcmfiqzrAWK0tvRRVOtgR8Ceg9YIxL54RGBc,6771 +django/contrib/admin/locale/tk/LC_MESSAGES/django.mo,sha256=9EGO5sA_1Hz2fhEmkrLbPJXQtWdxQJUBQ3gSREvjEGM,2834 +django/contrib/admin/locale/tk/LC_MESSAGES/django.po,sha256=8dDS2pp8wNI_3J82ZORzOFlCS2_GvFsJ_PY8fPyExHg,12847 +django/contrib/admin/locale/tr/LC_MESSAGES/django.mo,sha256=deNilQqHGc4t3Nt8ea3zmKG3JioDChZdeoM6eptVpCU,18434 +django/contrib/admin/locale/tr/LC_MESSAGES/django.po,sha256=5XEXYRQAKvZwfHcNYp1GjAK-TItpPRrxVnG15xiQL1o,19976 +django/contrib/admin/locale/tr/LC_MESSAGES/djangojs.mo,sha256=ZD3OYJSFuhPLrYZbAHb3tPhIxWK_tW1F8DOt7UwDR6g,6044 +django/contrib/admin/locale/tr/LC_MESSAGES/djangojs.po,sha256=bmh2K3ZxUnvAy_OdQB-NOE2injry30mzKGlwCsigIjg,6789 +django/contrib/admin/locale/tt/LC_MESSAGES/django.mo,sha256=ObJ8zwVLhFsS6XZK_36AkNRCeznoJJwLTMh4_LLGPAA,12952 +django/contrib/admin/locale/tt/LC_MESSAGES/django.po,sha256=VDjg5nDrLqRGXpxCyQudEC_n-6kTCIYsOl3izt1Eblc,17329 +django/contrib/admin/locale/tt/LC_MESSAGES/djangojs.mo,sha256=Sz5qnMHWfLXjaCIHxQNrwac4c0w4oeAAQubn5R7KL84,2607 +django/contrib/admin/locale/tt/LC_MESSAGES/djangojs.po,sha256=_Uh3yH_RXVB3PP75RFztvSzVykVq0SQjy9QtTnyH3Qk,4541 +django/contrib/admin/locale/udm/LC_MESSAGES/django.mo,sha256=2Q_lfocM7OEjFKebqNR24ZBqUiIee7Lm1rmS5tPGdZA,622 +django/contrib/admin/locale/udm/LC_MESSAGES/django.po,sha256=L4TgEk2Fm2mtKqhZroE6k_gfz1VC-_dXe39CiJvaOPE,10496 +django/contrib/admin/locale/udm/LC_MESSAGES/djangojs.mo,sha256=CNmoKj9Uc0qEInnV5t0Nt4ZnKSZCRdIG5fyfSsqwky4,462 +django/contrib/admin/locale/udm/LC_MESSAGES/djangojs.po,sha256=ZLYr0yHdMYAl7Z7ipNSNjRFIMNYmzIjT7PsKNMT6XVk,2811 +django/contrib/admin/locale/ug/LC_MESSAGES/django.mo,sha256=U_CgE0Q_Db7s4lLO7oMXZOUISUzHx_4_ktBx9dPfJzs,22887 +django/contrib/admin/locale/ug/LC_MESSAGES/django.po,sha256=unvCb5iqBFR8XGY8N4ZqPWJ5ZegfOopOuGhu4WIT5I4,24251 +django/contrib/admin/locale/ug/LC_MESSAGES/djangojs.mo,sha256=xC3-Xz8R95NL6EkVKvUuPX4jCwnNA_0sq6PvWEKbZ5I,7306 +django/contrib/admin/locale/ug/LC_MESSAGES/djangojs.po,sha256=V3UuGjeYLnfV151Yn_X0QrAYwfqMe6WvoyWJ1QnKsjo,7927 +django/contrib/admin/locale/uk/LC_MESSAGES/django.mo,sha256=LwO4uX79ZynANx47kGLijkDJ-DAdYWlmW3nYOqbXuuo,22319 +django/contrib/admin/locale/uk/LC_MESSAGES/django.po,sha256=9vEMtbw4ck4Sipdu-Y8mYOufWOTWpu7PVrMDu71GT9g,24335 +django/contrib/admin/locale/uk/LC_MESSAGES/djangojs.mo,sha256=_YwTcBttv3DZNYkBq4Rsl6oq30o8nDvUHPI5Yx0GaA4,5787 +django/contrib/admin/locale/uk/LC_MESSAGES/djangojs.po,sha256=4lYvm_LDX5xha4Qj1dXE5tGs4BjGPUgjigvG2n6y1S4,6993 +django/contrib/admin/locale/ur/LC_MESSAGES/django.mo,sha256=HvyjnSeLhUf1JVDy759V_TI7ygZfLaMhLnoCBJxhH_s,13106 +django/contrib/admin/locale/ur/LC_MESSAGES/django.po,sha256=BFxxLbHs-UZWEmbvtWJNA7xeuvO9wDc32H2ysKZQvF4,17531 +django/contrib/admin/locale/ur/LC_MESSAGES/djangojs.mo,sha256=eYN9Q9KKTV2W0UuqRc-gg7y42yFAvJP8avMeZM-W7mw,2678 +django/contrib/admin/locale/ur/LC_MESSAGES/djangojs.po,sha256=Nj-6L6axLrqA0RHUQbidNAT33sXYfVdGcX4egVua-Pk,4646 +django/contrib/admin/locale/uz/LC_MESSAGES/django.mo,sha256=bWJujZSbu9Q4u2hcVJAkHDQCjx8Uo_Bj5gcU3CbkeLw,4610 +django/contrib/admin/locale/uz/LC_MESSAGES/django.po,sha256=3fxRPvC5_1md4LrntCTLUXVINdrHxgHOav04xabwYUg,13107 +django/contrib/admin/locale/uz/LC_MESSAGES/djangojs.mo,sha256=LpuFvNKqNRCCiV5VyRnJoZ8gY3Xieb05YV9KakNU7o8,3783 +django/contrib/admin/locale/uz/LC_MESSAGES/djangojs.po,sha256=joswozR3I1ijRapf50FZMzQQhI_aU2XiiSTLeSxkL64,5235 +django/contrib/admin/locale/vi/LC_MESSAGES/django.mo,sha256=coCDRhju7xVvdSaounXO5cMqCmLWICZPJth6JI3Si2c,18077 +django/contrib/admin/locale/vi/LC_MESSAGES/django.po,sha256=Q1etVmaAb1f79f4uVjbNjPkn-_3m2Spz1buNAV3y9lk,19543 +django/contrib/admin/locale/vi/LC_MESSAGES/djangojs.mo,sha256=45E-fCQkq-BRLzRzsGkw1-AvWlvjL1rdsRFqfsvAq98,5302 +django/contrib/admin/locale/vi/LC_MESSAGES/djangojs.po,sha256=k87QvFnt8psnwMXXrFO6TyH6xCyXIDd_rlnWDfl2FAA,5958 +django/contrib/admin/locale/zh_Hans/LC_MESSAGES/django.mo,sha256=Q5-R3I1ELrv66Tb-GgreNTX4B0q09bis1KVtVUqgpuE,16506 +django/contrib/admin/locale/zh_Hans/LC_MESSAGES/django.po,sha256=Yu0QXl2FRqvSxp3-QfC_Qh-IFbosb1QpI-I7tso7PDE,18872 +django/contrib/admin/locale/zh_Hans/LC_MESSAGES/djangojs.mo,sha256=u1aBhR4-p8zHRKLz89kzYNsC0iZG9NWU6KsOXuhTF_c,5052 +django/contrib/admin/locale/zh_Hans/LC_MESSAGES/djangojs.po,sha256=k8fiBGVBR0nqrRrhFsAt2CxYi67dOfnT9rcPjzJFBV8,6709 +django/contrib/admin/locale/zh_Hant/LC_MESSAGES/django.mo,sha256=kEKX-cQPRFCNkiqNs1BnyzEvJQF-EzA814ASnYPFMsw,15152 +django/contrib/admin/locale/zh_Hant/LC_MESSAGES/django.po,sha256=iH3w7Xt_MelkZefKi8F0yAWN6QGdQCJBz8VaFY4maUg,16531 +django/contrib/admin/locale/zh_Hant/LC_MESSAGES/djangojs.mo,sha256=yFwS8aTJUAG5lN4tYLCxx-FLfTsiOxXrCEhlIA-9vcs,4230 +django/contrib/admin/locale/zh_Hant/LC_MESSAGES/djangojs.po,sha256=C4Yk5yuYcmaovVs_CS8YFYY2iS4RGi0oNaUpTm7akeU,4724 +django/contrib/admin/migrations/0001_initial.py,sha256=9HFpidmBW2Ix8NcpF1SDXgCMloGER_5XmEu_iYWIMzU,2507 +django/contrib/admin/migrations/0002_logentry_remove_auto_add.py,sha256=LBJ-ZZoiNu3qDtV-zNOHhq6E42V5CoC5a3WMYX9QvkM,553 +django/contrib/admin/migrations/0003_logentry_add_action_flag_choices.py,sha256=AnAKgnGQcg5cQXSVo5UHG2uqKKNOdLyPkIJK-q_AGEE,538 +django/contrib/admin/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/admin/models.py,sha256=y-2sytJ1V-KnhKqUz8KfQho_wzxNbNhXQ38VG41Kb08,6501 +django/contrib/admin/options.py,sha256=_iI3A4HcYt14PGVl7wcMn-s9klieL9cgZxAoLU5EiIU,99864 +django/contrib/admin/sites.py,sha256=hzLzSOS7rhPwxXfXAUXVMEYKi_8fe_Lgx9Mu6Ig7mOs,22974 +django/contrib/admin/static/admin/css/autocomplete.css,sha256=6-fcQdqClpGf8EpH1NxgS8YL-diGXc8CFq3Sw2I9K8k,9114 +django/contrib/admin/static/admin/css/base.css,sha256=WjYLdJa86FCyonQHVeX10FBA25sxpYbjIcfhlMWPwH4,21544 +django/contrib/admin/static/admin/css/changelists.css,sha256=6-aXpCDh6dL_KvEyjcYbGotxhUqRFYklOkkKOYX6XZU,6811 +django/contrib/admin/static/admin/css/dark_mode.css,sha256=xVcEpQeNKsI4hMkIgTQFnG6lwsWEYNfADmL09EaMydg,2682 +django/contrib/admin/static/admin/css/dashboard.css,sha256=iCz7Kkr5Ld3Hyjx_O1r_XfZ2LcpxOpVjcDZS1wbqHWs,441 +django/contrib/admin/static/admin/css/forms.css,sha256=Ev9qjiQCtEp-XPnmqGo6f0ZCkr3NACOo26Y7xCuwqkc,9048 +django/contrib/admin/static/admin/css/login.css,sha256=BdAkR--cxd5HZXDNPInv2Qgs_c305sPbPCctkUkAmDU,958 +django/contrib/admin/static/admin/css/nav_sidebar.css,sha256=4wmBb5tVT5_fcnP_UtS16jal0QiqgOKq_yz162Hr_C4,2810 +django/contrib/admin/static/admin/css/responsive.css,sha256=xsrKMoXgefEsYB5AiIcPB5GNKyf5hE6403gN0_OPizs,17905 +django/contrib/admin/static/admin/css/responsive_rtl.css,sha256=lzUTK8NbPu7qIm6tCsiCcI3Hx0594ewFEfN7zk8-TJE,1864 +django/contrib/admin/static/admin/css/rtl.css,sha256=Miv8-nQ2UaQvsj9UX5zXAKbLeRq62KAldJ_43HdkMcM,4977 +django/contrib/admin/static/admin/css/vendor/select2/LICENSE-SELECT2.md,sha256=TuDLxRNwr941hlKg-XeXIFNyntV4tqQvXioDfRFPCzk,1124 +django/contrib/admin/static/admin/css/vendor/select2/select2.css,sha256=kalgQ55Pfy9YBkT-4yYYd5N8Iobe-iWeBuzP7LjVO0o,17358 +django/contrib/admin/static/admin/css/vendor/select2/select2.min.css,sha256=FdatTf20PQr_rWg-cAKfl6j4_IY3oohFAJ7gVC3M34E,14966 +django/contrib/admin/static/admin/css/widgets.css,sha256=yXtGYe0T4cxrDxlSWZT9w7jRsgGqvwXLjuTDCXDZqW8,11800 +django/contrib/admin/static/admin/img/LICENSE,sha256=0RT6_zSIwWwxmzI13EH5AjnT1j2YU3MwM9j3U19cAAQ,1081 +django/contrib/admin/static/admin/img/README.txt,sha256=XqN5MlT1SIi6sdnYnKJrOiJ6h9lTIejT7nLSY-Y74pk,319 +django/contrib/admin/static/admin/img/calendar-icons.svg,sha256=gbMu26nfxZphlqKFcVOXpcv5zhv5x_Qm_P4ba0Ze84I,1094 +django/contrib/admin/static/admin/img/gis/move_vertex_off.svg,sha256=ou-ppUNyy5QZCKFYlcrzGBwEEiTDX5mmJvM8rpwC5DM,1129 +django/contrib/admin/static/admin/img/gis/move_vertex_on.svg,sha256=DgmcezWDms_3VhgqgYUGn-RGFHyScBP0MeX8PwHy_nE,1129 +django/contrib/admin/static/admin/img/icon-addlink.svg,sha256=kBtPJJ3qeQPWeNftvprZiR51NYaZ2n_ZwJatY9-Zx1Q,331 +django/contrib/admin/static/admin/img/icon-alert.svg,sha256=aXtd9PA66tccls-TJfyECQrmdWrj8ROWKC0tJKa7twA,504 +django/contrib/admin/static/admin/img/icon-calendar.svg,sha256=_bcF7a_R94UpOfLf-R0plVobNUeeTto9UMiUIHBcSHY,1086 +django/contrib/admin/static/admin/img/icon-changelink.svg,sha256=clM2ew94bwVa2xQ6bvfKx8xLtk0i-u5AybNlyP8k-UM,380 +django/contrib/admin/static/admin/img/icon-clock.svg,sha256=k55Yv6R6-TyS8hlL3Kye0IMNihgORFjoJjHY21vtpEA,677 +django/contrib/admin/static/admin/img/icon-deletelink.svg,sha256=06XOHo5y59UfNBtO8jMBHQqmXt8UmohlSMloUuZ6d0A,392 +django/contrib/admin/static/admin/img/icon-hidelink.svg,sha256=4MGicntOFkPurB9LW_IC-0N88WXKvrQxVyBB9p5gMTA,784 +django/contrib/admin/static/admin/img/icon-no.svg,sha256=QqBaTrrp3KhYJxLYB5E-0cn_s4A_Y8PImYdWjfQSM-c,560 +django/contrib/admin/static/admin/img/icon-unknown-alt.svg,sha256=LyL9oJtR0U49kGHYKMxmmm1vAw3qsfXR7uzZH76sZ_g,655 +django/contrib/admin/static/admin/img/icon-unknown.svg,sha256=ePcXlyi7cob_IcJOpZ66uiymyFgMPHl8p9iEn_eE3fc,655 +django/contrib/admin/static/admin/img/icon-viewlink.svg,sha256=NL7fcy7mQOQ91sRzxoVRLfzWzXBRU59cFANOrGOwWM0,581 +django/contrib/admin/static/admin/img/icon-yes.svg,sha256=_H4JqLywJ-NxoPLqSqk9aGJcxEdZwtSFua1TuI9kIcM,436 +django/contrib/admin/static/admin/img/inline-delete.svg,sha256=Ni1z8eDYBOveVDqtoaGyEMWG5Mdnt9dniiuBWTlnr5Y,560 +django/contrib/admin/static/admin/img/search.svg,sha256=HgvLPNT7FfgYvmbt1Al1yhXgmzYHzMg8BuDLnU9qpMU,458 +django/contrib/admin/static/admin/img/selector-icons.svg,sha256=0RJyrulJ_UR9aYP7Wbvs5jYayBVhLoXR26zawNMZ0JQ,3291 +django/contrib/admin/static/admin/img/sorting-icons.svg,sha256=cCvcp4i3MAr-mo8LE_h8ZRu3LD7Ma9BtpK-p24O3lVA,1097 +django/contrib/admin/static/admin/img/tooltag-add.svg,sha256=fTZCouGMJC6Qq2xlqw_h9fFodVtLmDMrpmZacGVJYZQ,331 +django/contrib/admin/static/admin/img/tooltag-arrowright.svg,sha256=GIAqy_4Oor9cDMNC2fSaEGh-3gqScvqREaULnix3wHc,280 +django/contrib/admin/static/admin/js/SelectBox.js,sha256=b42sGVqaCDqlr0ibFiZus9FbrUweRcKD_y61HDAdQuc,4530 +django/contrib/admin/static/admin/js/SelectFilter2.js,sha256=QlF6lMKcWt0Br0P3xkY1jDlG5Ft7vlPuwzbV9kUv70M,15492 +django/contrib/admin/static/admin/js/actions.js,sha256=PLOvi9a24cOUtcVuIcrH7ScccIIW0sciAmLlqtAEegM,8067 +django/contrib/admin/static/admin/js/admin/DateTimeShortcuts.js,sha256=ryJhtM9SN0fMdfnhV_m2Hv2pc6a9B0Zpc37ocZ82_-0,19319 +django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js,sha256=3QhYkHpr7C3yaBhFh-Yv_94DB0Z1gXD27DsE8OVThRA,9042 +django/contrib/admin/static/admin/js/autocomplete.js,sha256=OAqSTiHZnTWZzJKEvOm-Z1tdAlLjPWX9jKpYkmH0Ozo,1060 +django/contrib/admin/static/admin/js/calendar.js,sha256=cj6qPrSqdWeq_OnWUUKWy4jVGCiy4YxsbXa5KhUw_r4,9141 +django/contrib/admin/static/admin/js/cancel.js,sha256=UEZdvvWu5s4ZH16lFfxa8UPgWXJ3i8VseK5Lcw2Kreg,884 +django/contrib/admin/static/admin/js/change_form.js,sha256=zOTeORCq1i9XXV_saSBBDOXbou5UtZvxYFpVPqxQ02Q,606 +django/contrib/admin/static/admin/js/collapse.js,sha256=UONBUueHwsm5SMlG0Ufp4mlqdgu7UGimU6psKzpxbuE,1803 +django/contrib/admin/static/admin/js/core.js,sha256=H4_YZp2B3Y9JxMZPpHKVutrUZJbAZd4H6Gc-ilSb4_E,6208 +django/contrib/admin/static/admin/js/filters.js,sha256=T-JlrqZEBSWbiFw_e5lxkMykkACWqWXd_wMy-b3TnaE,978 +django/contrib/admin/static/admin/js/inlines.js,sha256=yWB-KSw_aZmVZpIitKde7imygAa36LBdqoBfB7lTvJQ,15526 +django/contrib/admin/static/admin/js/jquery.init.js,sha256=uM_Kf7EOBMipcCmuQHbyubQkycleSWDCS8-c3WevFW0,347 +django/contrib/admin/static/admin/js/nav_sidebar.js,sha256=1xzV95R3GaqQ953sVmkLIuZJrzFNoDJMHBqwQePp6-Q,3063 +django/contrib/admin/static/admin/js/popup_response.js,sha256=H4ppG14jfrxB1XF5xZp5SS8PapYuYou5H7uwYjHd7eI,551 +django/contrib/admin/static/admin/js/prepopulate.js,sha256=UYkWrHNK1-OWp1a5IWZdg0udfo_dcR-jKSn5AlxxqgU,1531 +django/contrib/admin/static/admin/js/prepopulate_init.js,sha256=mJIPAgn8QHji_rSqO6WKNREbpkCILFrjRCCOQ1-9SoQ,586 +django/contrib/admin/static/admin/js/theme.js,sha256=zBii0JEYGHwG3PiyCjgLmJ3vSSUewb7SlPKzBoI7hQY,1943 +django/contrib/admin/static/admin/js/urlify.js,sha256=8oC4Bcxt8oJY4uy9O4NjPws5lXzDkdfwI2Xo3MxpBTo,7887 +django/contrib/admin/static/admin/js/vendor/jquery/LICENSE.txt,sha256=1Nuevm8p9RaOrEWtcT8FViOsXQ3NW6ktoj1lCuASAg0,1097 +django/contrib/admin/static/admin/js/vendor/jquery/jquery.js,sha256=eKhayi8LEQwp4NKxN-CfCh-3qOVUtJn3QNZ0TciWLP4,285314 +django/contrib/admin/static/admin/js/vendor/jquery/jquery.min.js,sha256=_JqT3SQfawRcv_BIHPThkBvs0OEvtFFmqPF_lYI_Cxo,87533 +django/contrib/admin/static/admin/js/vendor/select2/LICENSE.md,sha256=TuDLxRNwr941hlKg-XeXIFNyntV4tqQvXioDfRFPCzk,1124 +django/contrib/admin/static/admin/js/vendor/select2/i18n/af.js,sha256=IpI3uo19fo77jMtN5R3peoP0OriN-nQfPY2J4fufd8g,866 +django/contrib/admin/static/admin/js/vendor/select2/i18n/ar.js,sha256=zxQ3peSnbVIfrH1Ndjx4DrHDsmbpqu6mfeylVWFM5mY,905 +django/contrib/admin/static/admin/js/vendor/select2/i18n/az.js,sha256=N_KU7ftojf2HgvJRlpP8KqG6hKIbqigYN3K0YH_ctuQ,721 +django/contrib/admin/static/admin/js/vendor/select2/i18n/bg.js,sha256=5Z6IlHmuk_6IdZdAVvdigXnlj7IOaKXtcjuI0n0FmYQ,968 +django/contrib/admin/static/admin/js/vendor/select2/i18n/bn.js,sha256=wdQbgaxZ47TyGlwvso7GOjpmTXUKaWzvVUr_oCRemEE,1291 +django/contrib/admin/static/admin/js/vendor/select2/i18n/bs.js,sha256=g56kWSu9Rxyh_rarLSDa_8nrdqL51JqZai4QQx20jwQ,965 +django/contrib/admin/static/admin/js/vendor/select2/i18n/ca.js,sha256=DSyyAXJUI0wTp_TbFhLNGrgvgRsGWeV3IafxYUGBggM,900 +django/contrib/admin/static/admin/js/vendor/select2/i18n/cs.js,sha256=t_8OWVi6Yy29Kabqs_l1sM2SSrjUAgZTwbTX_m0MCL8,1292 +django/contrib/admin/static/admin/js/vendor/select2/i18n/da.js,sha256=tF2mvzFYSWYOU3Yktl3G93pCkf-V9gonCxk7hcA5J1o,828 +django/contrib/admin/static/admin/js/vendor/select2/i18n/de.js,sha256=5bspfcihMp8yXDwfcqvC_nV3QTbtBuQDmR3c7UPQtFw,866 +django/contrib/admin/static/admin/js/vendor/select2/i18n/dsb.js,sha256=KtP2xNoP75oWnobUrS7Ep_BOFPzcMNDt0wyPnkbIF_Q,1017 +django/contrib/admin/static/admin/js/vendor/select2/i18n/el.js,sha256=IdvD8eY_KpX9fdHvld3OMvQfYsnaoJjDeVkgbIemfn8,1182 +django/contrib/admin/static/admin/js/vendor/select2/i18n/en.js,sha256=C66AO-KOXNuXEWwhwfjYBFa3gGcIzsPFHQAZ9qSh3Go,844 +django/contrib/admin/static/admin/js/vendor/select2/i18n/es.js,sha256=IhZaIy8ufTduO2-vBrivswMCjlPk7vrk4P81pD6B0SM,922 +django/contrib/admin/static/admin/js/vendor/select2/i18n/et.js,sha256=LgLgdOkKjc63svxP1Ua7A0ze1L6Wrv0X6np-8iRD5zw,801 +django/contrib/admin/static/admin/js/vendor/select2/i18n/eu.js,sha256=rLmtP7bA_atkNIj81l_riTM7fi5CXxVrFBHFyddO-Hw,868 +django/contrib/admin/static/admin/js/vendor/select2/i18n/fa.js,sha256=fqZkE9e8tt2rZ7OrDGPiOsTNdj3S2r0CjbddVUBDeMA,1023 +django/contrib/admin/static/admin/js/vendor/select2/i18n/fi.js,sha256=KVGirhGGNee_iIpMGLX5EzH_UkNe-FOPC_0484G-QQ0,803 +django/contrib/admin/static/admin/js/vendor/select2/i18n/fr.js,sha256=aj0q2rdJN47BRBc9LqvsgxkuPOcWAbZsUFUlbguwdY0,924 +django/contrib/admin/static/admin/js/vendor/select2/i18n/gl.js,sha256=HSJafI85yKp4WzjFPT5_3eZ_-XQDYPzzf4BWmu6uXHk,924 +django/contrib/admin/static/admin/js/vendor/select2/i18n/he.js,sha256=DIPRKHw0NkDuUtLNGdTnYZcoCiN3ustHY-UMmw34V_s,984 +django/contrib/admin/static/admin/js/vendor/select2/i18n/hi.js,sha256=m6ZqiKZ_jzwzVFgC8vkYiwy4lH5fJEMV-LTPVO2Wu40,1175 +django/contrib/admin/static/admin/js/vendor/select2/i18n/hr.js,sha256=NclTlDTiNFX1y0W1Llj10-ZIoXUYd7vDXqyeUJ7v3B4,852 +django/contrib/admin/static/admin/js/vendor/select2/i18n/hsb.js,sha256=FTLszcrGaelTW66WV50u_rS6HV0SZxQ6Vhpi2tngC6M,1018 +django/contrib/admin/static/admin/js/vendor/select2/i18n/hu.js,sha256=3PdUk0SpHY-H-h62womw4AyyRMujlGc6_oxW-L1WyOs,831 +django/contrib/admin/static/admin/js/vendor/select2/i18n/hy.js,sha256=BLh0fntrwtwNwlQoiwLkdQOVyNXHdmRpL28p-W5FsDg,1028 +django/contrib/admin/static/admin/js/vendor/select2/i18n/id.js,sha256=fGJ--Aw70Ppzk3EgLjF1V_QvqD2q_ufXjnQIIyZqYgc,768 +django/contrib/admin/static/admin/js/vendor/select2/i18n/is.js,sha256=gn0ddIqTnJX4wk-tWC5gFORJs1dkgIH9MOwLljBuQK0,807 +django/contrib/admin/static/admin/js/vendor/select2/i18n/it.js,sha256=kGxtapwhRFj3u_IhY_7zWZhKgR5CrZmmasT5w-aoXRM,897 +django/contrib/admin/static/admin/js/vendor/select2/i18n/ja.js,sha256=tZ4sqdx_SEcJbiW5-coHDV8FVmElJRA3Z822EFHkjLM,862 +django/contrib/admin/static/admin/js/vendor/select2/i18n/ka.js,sha256=DH6VrnVdR8SX6kso2tzqnJqs32uCpBNyvP9Kxs3ssjI,1195 +django/contrib/admin/static/admin/js/vendor/select2/i18n/km.js,sha256=x9hyjennc1i0oeYrFUHQnYHakXpv7WD7MSF-c9AaTjg,1088 +django/contrib/admin/static/admin/js/vendor/select2/i18n/ko.js,sha256=ImmB9v7g2ZKEmPFUQeXrL723VEjbiEW3YelxeqHEgHc,855 +django/contrib/admin/static/admin/js/vendor/select2/i18n/lt.js,sha256=ZT-45ibVwdWnTyo-TqsqW2NjIp9zw4xs5So78KMb_s8,944 +django/contrib/admin/static/admin/js/vendor/select2/i18n/lv.js,sha256=hHpEK4eYSoJj_fvA2wl8QSuJluNxh-Tvp6UZm-ZYaeE,900 +django/contrib/admin/static/admin/js/vendor/select2/i18n/mk.js,sha256=PSpxrnBpL4SSs9Tb0qdWD7umUIyIoR2V1fpqRQvCXcA,1038 +django/contrib/admin/static/admin/js/vendor/select2/i18n/ms.js,sha256=NCz4RntkJZf8YDDC1TFBvK-nkn-D-cGNy7wohqqaQD4,811 +django/contrib/admin/static/admin/js/vendor/select2/i18n/nb.js,sha256=eduKCG76J3iIPrUekCDCq741rnG4xD7TU3E7Lib7sPE,778 +django/contrib/admin/static/admin/js/vendor/select2/i18n/ne.js,sha256=QQjDPQE6GDKXS5cxq2JRjk3MGDvjg3Izex71Zhonbj8,1357 +django/contrib/admin/static/admin/js/vendor/select2/i18n/nl.js,sha256=JctLfTpLQ5UFXtyAmgbCvSPUtW0fy1mE7oNYcMI90bI,904 +django/contrib/admin/static/admin/js/vendor/select2/i18n/pl.js,sha256=6gEuKYnJdf8cbPERsw-mtdcgdByUJuLf1QUH0aSajMo,947 +django/contrib/admin/static/admin/js/vendor/select2/i18n/ps.js,sha256=4J4sZtSavxr1vZdxmnub2J0H0qr1S8WnNsTehfdfq4M,1049 +django/contrib/admin/static/admin/js/vendor/select2/i18n/pt-BR.js,sha256=0DFe1Hu9fEDSXgpjPOQrA6Eq0rGb15NRbsGh1U4vEr0,876 +django/contrib/admin/static/admin/js/vendor/select2/i18n/pt.js,sha256=L5jqz8zc5BF8ukrhpI2vvGrNR34X7482dckX-IUuUpA,878 +django/contrib/admin/static/admin/js/vendor/select2/i18n/ro.js,sha256=Aadb6LV0u2L2mCOgyX2cYZ6xI5sDT9OI3V7HwuueivM,938 +django/contrib/admin/static/admin/js/vendor/select2/i18n/ru.js,sha256=bV6emVCE9lY0LzbVN87WKAAAFLUT3kKqEzn641pJ29o,1171 +django/contrib/admin/static/admin/js/vendor/select2/i18n/sk.js,sha256=MnbUcP6pInuBzTW_L_wmXY8gPLGCOcKyzQHthFkImZo,1306 +django/contrib/admin/static/admin/js/vendor/select2/i18n/sl.js,sha256=LPIKwp9gp_WcUc4UaVt_cySlNL5_lmfZlt0bgtwnkFk,925 +django/contrib/admin/static/admin/js/vendor/select2/i18n/sq.js,sha256=oIxJLYLtK0vG2g3s5jsGLn4lHuDgSodxYAWL0ByHRHo,903 +django/contrib/admin/static/admin/js/vendor/select2/i18n/sr-Cyrl.js,sha256=BoT2KdiceZGgxhESRz3W2J_7CFYqWyZyov2YktUo_2w,1109 +django/contrib/admin/static/admin/js/vendor/select2/i18n/sr.js,sha256=7EELYXwb0tISsuvL6eorxzTviMK-oedSvZvEZCMloGU,980 +django/contrib/admin/static/admin/js/vendor/select2/i18n/sv.js,sha256=c6nqUmitKs4_6AlYDviCe6HqLyOHqot2IrvJRGjj1JE,786 +django/contrib/admin/static/admin/js/vendor/select2/i18n/th.js,sha256=saDPLk-2dq5ftKCvW1wddkJOg-mXA-GUoPPVOlSZrIY,1074 +django/contrib/admin/static/admin/js/vendor/select2/i18n/tk.js,sha256=mUEGlb-9nQHvzcTYI-1kjsB7JsPRGpLxWbjrJ8URthU,771 +django/contrib/admin/static/admin/js/vendor/select2/i18n/tr.js,sha256=dDz8iSp07vbx9gciIqz56wmc2TLHj5v8o6es75vzmZU,775 +django/contrib/admin/static/admin/js/vendor/select2/i18n/uk.js,sha256=MixhFDvdRda-wj-TjrN018s7R7E34aQhRjz4baxrdKw,1156 +django/contrib/admin/static/admin/js/vendor/select2/i18n/vi.js,sha256=mwTeySsUAgqu_IA6hvFzMyhcSIM1zGhNYKq8G7X_tpM,796 +django/contrib/admin/static/admin/js/vendor/select2/i18n/zh-CN.js,sha256=olAdvPQ5qsN9IZuxAKgDVQM-blexUnWTDTXUtiorygI,768 +django/contrib/admin/static/admin/js/vendor/select2/i18n/zh-TW.js,sha256=DnDBG9ywBOfxVb2VXg71xBR_tECPAxw7QLhZOXiJ4fo,707 +django/contrib/admin/static/admin/js/vendor/select2/select2.full.js,sha256=ugZkER5OAEGzCwwb_4MvhBKE5Gvmc0S59MKn-dooZaI,173566 +django/contrib/admin/static/admin/js/vendor/select2/select2.full.min.js,sha256=XG_auAy4aieWldzMImofrFDiySK-pwJC7aoo9St7rS0,79212 +django/contrib/admin/static/admin/js/vendor/xregexp/LICENSE.txt,sha256=c68pSb_5KWyw-BbDvhmk2k6VrclMH5JHlui60_A_Lyk,1106 +django/contrib/admin/static/admin/js/vendor/xregexp/xregexp.js,sha256=FM2fFr4a9mVscQobpyNQG1Bu4_8exjunQglEoPSP5uo,325171 +django/contrib/admin/static/admin/js/vendor/xregexp/xregexp.min.js,sha256=-FQXGywOGwW-5DdFMWIq0QWpGX3rQFuQpIDe6N_9eVI,163184 +django/contrib/admin/templates/admin/404.html,sha256=zyawWu1I9IxDGBRsks6-DgtLUGDDYOKHfj9YQqPl0AA,282 +django/contrib/admin/templates/admin/500.html,sha256=rZNmFXr9POnc9TdZwD06qkY8h2W5K05vCyssrIzbZGE,551 +django/contrib/admin/templates/admin/actions.html,sha256=B2s3wWt4g_uhd7CZdmXp4ZGZlMfh6K9RAH4Bv6Ud9nQ,1235 +django/contrib/admin/templates/admin/app_index.html,sha256=7NPb0bdLKOdja7FoIERyRZRYK-ldX3PcxMoydguWfzc,493 +django/contrib/admin/templates/admin/app_list.html,sha256=ihZHIZLWNwtvmeDnsdXAVEo_mHNiM6X4CHA7y0I9YdA,1716 +django/contrib/admin/templates/admin/auth/user/add_form.html,sha256=5DL3UbNWW2rTvWrpMsxy5XcVNT6_uYv8DjDZZksiVKQ,320 +django/contrib/admin/templates/admin/auth/user/change_password.html,sha256=8qaHcl1yTsSOyUnBPsgF_LYwnezgcM9Ni1bEPcU5n_E,2515 +django/contrib/admin/templates/admin/base.html,sha256=VeboczX9MHrRcAuXXDZ1TfgesaXBOUIaAPF9Jiej9iM,6085 +django/contrib/admin/templates/admin/base_site.html,sha256=GCiXgXwC_ZZ1goTKnrbdNfWONojGxTatiD5hCsA8HTg,450 +django/contrib/admin/templates/admin/change_form.html,sha256=_FF9GbP-uuzKDdrgjKh_qvRNyv3BBf81c_ddH7AUGEI,3019 +django/contrib/admin/templates/admin/change_form_object_tools.html,sha256=C0l0BJF2HuSjIvtY-Yr-ByZ9dePFRrTc-MR-OVJD-AI,403 +django/contrib/admin/templates/admin/change_list.html,sha256=ldPEcMSOgYKoQ7cGKjaLjudf6l4YRVQxK2aMWgri7sU,3735 +django/contrib/admin/templates/admin/change_list_object_tools.html,sha256=-AX0bYTxDsdLtEpAEK3RFpY89tdvVChMAWPYBLqPn48,378 +django/contrib/admin/templates/admin/change_list_results.html,sha256=yOpb1o-L5Ys9GiRA_nCXoFhIzREDVXLBuYzZk1xrx1w,1502 +django/contrib/admin/templates/admin/color_theme_toggle.html,sha256=owh9iJVw55HfqHEEaKUpeCxEIB4db8qFALv4fsbG0fI,697 +django/contrib/admin/templates/admin/date_hierarchy.html,sha256=Hug06L1uQzPQ-NAeixTtKRtDu2lAWh96o6f8ElnyU0c,453 +django/contrib/admin/templates/admin/delete_confirmation.html,sha256=3eMxQPSITd7Mae22TALXtCvJR4YMwfzNG_iAtuyF0PI,2539 +django/contrib/admin/templates/admin/delete_selected_confirmation.html,sha256=5yyaNqfiK1evhJ7px7gmMqjFwYrrMaKNDvQJ3-Lu4mo,2241 +django/contrib/admin/templates/admin/edit_inline/stacked.html,sha256=o717YOSXLWSvR-Oug7jH5uyqwjZFr9Bkuy9cC0Kx8gs,2580 +django/contrib/admin/templates/admin/edit_inline/tabular.html,sha256=DRI0asniH-EAilQH5rXQ0k-FcEYX5CHpQduhuMLOREI,4086 +django/contrib/admin/templates/admin/filter.html,sha256=cvjazGEln3BL_0iyz8Kcsend5WhT9y-gXKRN2kHqejU,395 +django/contrib/admin/templates/admin/includes/fieldset.html,sha256=-cuBaE0YHvMnrjkah4ZYt54sfmKTiyn3q8tQnjrAeCc,2200 +django/contrib/admin/templates/admin/includes/object_delete_summary.html,sha256=OC7VhKQiczmi01Gt_3jyemelerSNrGyDiWghUK6xKEI,192 +django/contrib/admin/templates/admin/index.html,sha256=TQxZdAy2ZyeXBLA_KZMXus7e2TGezFAUTsYHJBMLPl8,2070 +django/contrib/admin/templates/admin/invalid_setup.html,sha256=F5FS3o7S3l4idPrX29OKlM_azYmCRKzFdYjV_jpTqhE,447 +django/contrib/admin/templates/admin/login.html,sha256=ShZFbs_ITw6YoOBI_L6B-zekHJqjlR14h8WHIo-g5Ro,1899 +django/contrib/admin/templates/admin/nav_sidebar.html,sha256=OfI8XJn3_Q_Wf2ymc1IH61eTGZNMFwkkGwXXTDqeuP8,486 +django/contrib/admin/templates/admin/object_history.html,sha256=5e6ki7C94YKBoFyCvDOfqt4YzCyhNmNMy8NM4aKqiHc,2136 +django/contrib/admin/templates/admin/pagination.html,sha256=OBvC2HWFaH3wIuk6gzKSyCli51NTaW8vnJFyBOpNo_8,549 +django/contrib/admin/templates/admin/popup_response.html,sha256=Lj8dfQrg1XWdA-52uNtWJ9hwBI98Wt2spSMkO4YBjEk,327 +django/contrib/admin/templates/admin/prepopulated_fields_js.html,sha256=PShGpqQWBBVwQ86r7b-SimwJS0mxNiz8AObaiDOSfvY,209 +django/contrib/admin/templates/admin/search_form.html,sha256=GImO4ldr2iVMDKPa2prQzrJyrZEQS1Zy6guNfF6VbQ8,1357 +django/contrib/admin/templates/admin/submit_line.html,sha256=yI7XWZCjvY5JtDAvbzx8hpXZi4vRYWx0mty7Zt5uWjY,1093 +django/contrib/admin/templates/admin/widgets/clearable_file_input.html,sha256=LycNnWa-tYVET6HfuUrWi2Vj8wHcu-mnLox3Gp08zms,615 +django/contrib/admin/templates/admin/widgets/date.html,sha256=uJME8ir5DrcrWze9ikzlspoaCudQqxyMMGr6azIMkMc,71 +django/contrib/admin/templates/admin/widgets/foreign_key_raw_id.html,sha256=s5BiNQDbL9GcEVzYMwPfoYRFdnMiSeoyLKvyAzMqGnw,339 +django/contrib/admin/templates/admin/widgets/many_to_many_raw_id.html,sha256=w18JMKnPKrw6QyqIXBcdPs3YJlTRtHK5HGxj0lVkMlY,54 +django/contrib/admin/templates/admin/widgets/radio.html,sha256=-ob26uqmvrEUMZPQq6kAqK4KBk2YZHTCWWCM6BnaL0w,57 +django/contrib/admin/templates/admin/widgets/related_widget_wrapper.html,sha256=VJpXuKj2WSpzkxCrb0H6-cHHrVGoWuRIUue4e19ngRc,2097 +django/contrib/admin/templates/admin/widgets/split_datetime.html,sha256=BQ9XNv3eqtvNqZZGW38VBM2Nan-5PBxokbo2Fm_wwCQ,238 +django/contrib/admin/templates/admin/widgets/time.html,sha256=oiXCD1IvDhALK3w0fCrVc7wBOFMJhvPNTG2_NNz9H7A,71 +django/contrib/admin/templates/admin/widgets/url.html,sha256=Tf7PwdoKAiimfmDTVbWzRVxxUeyfhF0OlsuiOZ1tHgI,218 +django/contrib/admin/templates/registration/logged_out.html,sha256=PuviqzJh7C6SZJl9yKZXDcxxqXNCTDVfRuEpqvwJiPE,425 +django/contrib/admin/templates/registration/password_change_done.html,sha256=Ukca5IPY_VhtO3wfu9jABgY7SsbB3iIGp2KCSJqihlQ,745 +django/contrib/admin/templates/registration/password_change_form.html,sha256=vOyAdwDe7ajx0iFQR-dbWK7Q3bo6NVejWEFIoNlRYbQ,2428 +django/contrib/admin/templates/registration/password_reset_complete.html,sha256=_fc5bDeYBaI5fCUJZ0ZFpmOE2CUqlbk3npGk63uc_Ks,417 +django/contrib/admin/templates/registration/password_reset_confirm.html,sha256=r8SneE3ofcZkm38eV1FPBfyNyKXKNqGci-hdqifV_3k,1498 +django/contrib/admin/templates/registration/password_reset_done.html,sha256=SQsksjWN8vPLpvtFYPBFMMqZtLeiB4nesPq2VxpB3Y8,588 +django/contrib/admin/templates/registration/password_reset_email.html,sha256=rqaoGa900-rsUasaGYP2W9nBd6KOGZTyc1PsGTFozHo,612 +django/contrib/admin/templates/registration/password_reset_form.html,sha256=_Grf7jbOWrdT5RR8ypvCNv0j_huX5O_EiNwAO_NF0jc,955 +django/contrib/admin/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/admin/templatetags/admin_list.py,sha256=3YK63XbbVWhipp2POdfSr5JWPf52XeJ2kCwnsfaytFQ,18724 +django/contrib/admin/templatetags/admin_modify.py,sha256=DGE-YaZB1-bUqvjOwmnWJTrIRiR1qYdY6NyPDj1Hj3U,4978 +django/contrib/admin/templatetags/admin_urls.py,sha256=fIWcZ4zhPURSQ0DliyMzmzALO5kshFyWG6YhIPvUx9A,2038 +django/contrib/admin/templatetags/base.py,sha256=SyI_Dwh5OvtdP0DaPNehpvjgZknlJmrucck5tF3eUHY,1474 +django/contrib/admin/templatetags/log.py,sha256=vL2TNhgFsCH-4JXDE-2I_BhB2xQQLwx4GkHKx7m8Rz4,2050 +django/contrib/admin/tests.py,sha256=jItB0bAMHtTkDmsPXmg8UZue09a5zGV_Ws2hYH_bL80,8524 +django/contrib/admin/utils.py,sha256=-VocsuPp2FerZpVwXUWFQ4cAPZMnJ-On-6zWe1Wt1q4,21174 +django/contrib/admin/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/admin/views/autocomplete.py,sha256=PjC8db25zhYgwLS_4pq6PApTD_YRn4muIH0A_VN7kCg,4385 +django/contrib/admin/views/decorators.py,sha256=4ndYdYoPLhWsdutME0Lxsmcf6UFP5Z2ou3_pMjgNbw8,639 +django/contrib/admin/views/main.py,sha256=JHdSjQnh3Zp1BlYXROQmRpfoMqsWbDGNKkW-DLjloq4,25613 +django/contrib/admin/widgets.py,sha256=fh3pNDcbdyiuXNOHsXYd_GB8Q7Mzl2_-P_T571cjJNQ,19480 +django/contrib/admindocs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/admindocs/apps.py,sha256=bklhU4oaTSmPdr0QzpVeuNT6iG77QM1AgiKKZDX05t4,216 +django/contrib/admindocs/locale/af/LC_MESSAGES/django.mo,sha256=zRYBDfH19gFwKEeNJkXRVhNwiCPcwPZkmsc6vWdOEcE,2514 +django/contrib/admindocs/locale/af/LC_MESSAGES/django.po,sha256=NnkXui_vXGO8cgqJjG5ZlIDjzQvhWGPAqAQStEAJ7EM,5419 +django/contrib/admindocs/locale/ar/LC_MESSAGES/django.mo,sha256=MwAJ0TMsgRN4wrwlhlw3gYCfZK5IKDzNPuvjfJS_Eug,7440 +django/contrib/admindocs/locale/ar/LC_MESSAGES/django.po,sha256=KSmZCjSEizBx5a6yN_u0FPqG5QoXsTV9gdJkqWC8xC8,8052 +django/contrib/admindocs/locale/ar_DZ/LC_MESSAGES/django.mo,sha256=lW-fKcGwnRtdpJLfVw9i1HiM25TctVK0oA0bGV7yAzU,7465 +django/contrib/admindocs/locale/ar_DZ/LC_MESSAGES/django.po,sha256=c8LOJTCkHd1objwj6Xqh0wF3LwkLJvWg9FIWSWWMI-I,7985 +django/contrib/admindocs/locale/ast/LC_MESSAGES/django.mo,sha256=d4u-2zZXnnueWm9CLSnt4TRWgZk2NMlrA6gaytJ2gdU,715 +django/contrib/admindocs/locale/ast/LC_MESSAGES/django.po,sha256=TUkc-Hm4h1kD0NKyndteW97jH6bWcJMFXUuw2Bd62qo,4578 +django/contrib/admindocs/locale/az/LC_MESSAGES/django.mo,sha256=oDigGRWoeAjZ4Z2LOrRToycqKjwwV3pjGl1LmedJpwQ,1835 +django/contrib/admindocs/locale/az/LC_MESSAGES/django.po,sha256=MUqRjD4VeiTQluNvnpCbGfwdd8Lw_V_lrxeW-k9ytVQ,5100 +django/contrib/admindocs/locale/be/LC_MESSAGES/django.mo,sha256=VZl0yvgbo0jwQpf-s472jagbUj83A3twnxddQGwGW5c,8163 +django/contrib/admindocs/locale/be/LC_MESSAGES/django.po,sha256=Z8ZtS_t5Tc7iy1p4TTrsKZqiMJl94f1jiTWuv1sep3A,8728 +django/contrib/admindocs/locale/bg/LC_MESSAGES/django.mo,sha256=bNNoMFB0_P1qut4txQqHiXGxJa8-sjIZA8bb_jPaaHk,8242 +django/contrib/admindocs/locale/bg/LC_MESSAGES/django.po,sha256=nJMwR6R19pXmf4u6jBwe8Xn9fObSaAzulNeqsm8bszo,8989 +django/contrib/admindocs/locale/bn/LC_MESSAGES/django.mo,sha256=NOKVcE8id9G1OctSly4C5lm64CgEF8dohX-Pdyt4kCM,3794 +django/contrib/admindocs/locale/bn/LC_MESSAGES/django.po,sha256=6M7LjIEjvDTjyraxz70On_TIsgqJPLW7omQ0Fz_zyfQ,6266 +django/contrib/admindocs/locale/br/LC_MESSAGES/django.mo,sha256=UsPTado4ZNJM_arSMXyuBGsKN-bCHXQZdFbh0GB3dtg,1571 +django/contrib/admindocs/locale/br/LC_MESSAGES/django.po,sha256=SHOxPSgozJbOkm8u5LQJ9VmL58ZSBmlxfOVw1fAGl2s,5139 +django/contrib/admindocs/locale/bs/LC_MESSAGES/django.mo,sha256=clvhu0z3IF5Nt0tZ85hOt4M37pnGEWeIYumE20vLpsI,1730 +django/contrib/admindocs/locale/bs/LC_MESSAGES/django.po,sha256=1-OrVWFqLpeXQFfh7JNjJtvWjVww7iB2s96dcSgLy90,5042 +django/contrib/admindocs/locale/ca/LC_MESSAGES/django.mo,sha256=nI2ctIbZVrsaMbJQGIHQCjwqJNTnH3DKxwI2dWR6G_w,6650 +django/contrib/admindocs/locale/ca/LC_MESSAGES/django.po,sha256=hPjkw0bkoUu-yKU8XYE3ji0NG4z5cE1LGonYPJXeze4,7396 +django/contrib/admindocs/locale/ckb/LC_MESSAGES/django.mo,sha256=QisqerDkDuKrctJ10CspniXNDqBnCI2Wo-CKZUZtsCY,8154 +django/contrib/admindocs/locale/ckb/LC_MESSAGES/django.po,sha256=0adJyGnFg3qoD11s9gZbJlY8O0Dd1mpKF8OLQAkHZHE,8727 +django/contrib/admindocs/locale/cs/LC_MESSAGES/django.mo,sha256=dJ-3fDenE42f6XZFc-yrfWL1pEAmSGt2j1eWAyy-5OQ,6619 +django/contrib/admindocs/locale/cs/LC_MESSAGES/django.po,sha256=uU4n9PsiI96O0UpJzL-inVzB1Kx7OB_SbLkjrFLuyVA,7227 +django/contrib/admindocs/locale/cy/LC_MESSAGES/django.mo,sha256=sYeCCq0CMrFWjT6rKtmFrpC09OEFpYLSI3vu9WtpVTY,5401 +django/contrib/admindocs/locale/cy/LC_MESSAGES/django.po,sha256=GhdikiXtx8Aea459uifQtBjHuTlyUeiKu0_rR_mDKyg,6512 +django/contrib/admindocs/locale/da/LC_MESSAGES/django.mo,sha256=vmsIZeMIVpLkSdJNS0G6alAmBBEtLDBLnOd-P3dSOAs,6446 +django/contrib/admindocs/locale/da/LC_MESSAGES/django.po,sha256=bSoTGPcE7MdRfAtBybZT9jsuww2VDH9t5CssaxSs_GU,7148 +django/contrib/admindocs/locale/de/LC_MESSAGES/django.mo,sha256=ReSz0aH1TKT6AtP13lWoONnwNM2OGo4jK9fXJlo75Hc,6567 +django/contrib/admindocs/locale/de/LC_MESSAGES/django.po,sha256=tVkDIPF_wYb_KaJ7PF9cZyBJoYu6RpznoM9JIk3RYN4,7180 +django/contrib/admindocs/locale/dsb/LC_MESSAGES/django.mo,sha256=K_QuInKk1HrrzQivwJcs_2lc1HreFj7_R7qQh3qMTPY,6807 +django/contrib/admindocs/locale/dsb/LC_MESSAGES/django.po,sha256=flF1D0gfTScuC_RddC9njLe6RrnqnksiRxwODVA9Vqw,7332 +django/contrib/admindocs/locale/el/LC_MESSAGES/django.mo,sha256=1x0sTZwWbGEURyRaSn4ONvTPXHwm7XemNlcun9Nm1QI,8581 +django/contrib/admindocs/locale/el/LC_MESSAGES/django.po,sha256=GebfJfW0QPzAQyBKz1Km9a3saCpAWT7d_Qe2nCBvGn4,9320 +django/contrib/admindocs/locale/en/LC_MESSAGES/django.mo,sha256=U0OV81NfbuNL9ctF-gbGUG5al1StqN-daB-F-gFBFC8,356 +django/contrib/admindocs/locale/en/LC_MESSAGES/django.po,sha256=pEypE71l-Ude2e3XVf0tkBpGx6BSYNqBagWnSYmEbxI,10688 +django/contrib/admindocs/locale/en_AU/LC_MESSAGES/django.mo,sha256=BQ54LF9Tx88m-pG_QVz_nm_vqvoy6pVJzL8urSO4l1Q,486 +django/contrib/admindocs/locale/en_AU/LC_MESSAGES/django.po,sha256=ho7s1uKEs9FGooyZBurvSjvFz1gDSX6R4G2ZKpF1c9Q,5070 +django/contrib/admindocs/locale/en_GB/LC_MESSAGES/django.mo,sha256=xKGbswq1kuWCbn4zCgUQUb58fEGlICIOr00oSdCgtU4,1821 +django/contrib/admindocs/locale/en_GB/LC_MESSAGES/django.po,sha256=No09XHkzYVFBgZqo7bPlJk6QD9heE0oaI3JmnrU_p24,4992 +django/contrib/admindocs/locale/eo/LC_MESSAGES/django.mo,sha256=114OOVg9hP0H0UU2aQngCm0wE7zEEAp7QFMupOuWCfQ,6071 +django/contrib/admindocs/locale/eo/LC_MESSAGES/django.po,sha256=h8P3lmvBaJ8J2xiytReJvI8iGK0gCe-LPK27kWxSNKI,6799 +django/contrib/admindocs/locale/es/LC_MESSAGES/django.mo,sha256=wVt9I5M6DGKZFhPhYuS2yKRGVzSROthx98TFiJvJA80,6682 +django/contrib/admindocs/locale/es/LC_MESSAGES/django.po,sha256=F72OFWbIZXvopNMzy7eIibNKc5EM0jsYgbN4PobD6tc,7602 +django/contrib/admindocs/locale/es_AR/LC_MESSAGES/django.mo,sha256=mZ7OKAmlj2_FOabKsEiWycxiKLSLCPFldponKNxINjs,6658 +django/contrib/admindocs/locale/es_AR/LC_MESSAGES/django.po,sha256=deaOq0YMCb1B1PHWYUbgUrQsyXFutn4wQ2BAXiyzugA,7257 +django/contrib/admindocs/locale/es_CO/LC_MESSAGES/django.mo,sha256=KFjQyWtSxH_kTdSJ-kNUDAFt3qVZI_3Tlpg2pdkvJfs,6476 +django/contrib/admindocs/locale/es_CO/LC_MESSAGES/django.po,sha256=dwrTVjYmueLiVPu2yiJ_fkFF8ZeRntABoVND5H2WIRI,7038 +django/contrib/admindocs/locale/es_MX/LC_MESSAGES/django.mo,sha256=3hZiFFVO8J9cC624LUt4lBweqmpgdksRtvt2TLq5Jqs,1853 +django/contrib/admindocs/locale/es_MX/LC_MESSAGES/django.po,sha256=gNmx1QTbmyMxP3ftGXGWJH_sVGThiSe_VNKkd7M9jOY,5043 +django/contrib/admindocs/locale/es_VE/LC_MESSAGES/django.mo,sha256=sMwJ7t5GqPF496w-PvBYUneZ9uSwmi5jP-sWulhc6BM,6663 +django/contrib/admindocs/locale/es_VE/LC_MESSAGES/django.po,sha256=ZOcE0f95Q6uD9SelK6bQlKtS2c3JX9QxNYCihPdlM5o,7201 +django/contrib/admindocs/locale/et/LC_MESSAGES/django.mo,sha256=JQHVKehV0sxNaBQRqbsN-Of22CMV70bQ9TUId3QDudY,6381 +django/contrib/admindocs/locale/et/LC_MESSAGES/django.po,sha256=qrS3cPEy16hEi1857jvqsmr9zHF9_AkkJUw4mKimg98,7096 +django/contrib/admindocs/locale/eu/LC_MESSAGES/django.mo,sha256=WHgK7vGaqjO4MwjBkWz2Y3ABPXCqfnwSGelazRhOiuo,6479 +django/contrib/admindocs/locale/eu/LC_MESSAGES/django.po,sha256=718XgJN7UQcHgE9ku0VyFp7Frs-cvmCTO1o-xS5kpqc,7099 +django/contrib/admindocs/locale/fa/LC_MESSAGES/django.mo,sha256=Qrkrb_CHPGymnXBoBq5oeTs4W54R6nLz5hLIWH63EHM,7499 +django/contrib/admindocs/locale/fa/LC_MESSAGES/django.po,sha256=L-rxiKqUmlQgrPTLQRaS50woZWB9JuEamJpgDpLvIXw,8251 +django/contrib/admindocs/locale/fi/LC_MESSAGES/django.mo,sha256=SzuPvgeiaBwABvkJbOoTHsbP7juAuyyMWAjENr50gYk,6397 +django/contrib/admindocs/locale/fi/LC_MESSAGES/django.po,sha256=jn4ZMVQ_Gh6I-YLSmBhlyTn5ICP5o3oj7u0VKpV2hnI,6972 +django/contrib/admindocs/locale/fr/LC_MESSAGES/django.mo,sha256=dD92eLXIDeI-a_BrxX1G49qRwLS4Vt56bTP9cha5MeE,6755 +django/contrib/admindocs/locale/fr/LC_MESSAGES/django.po,sha256=hiUeHTul4Z3JWmkClGZmD5Xn4a1Tj1A5OLRfKU5Zdmo,7329 +django/contrib/admindocs/locale/fy/LC_MESSAGES/django.mo,sha256=_xVO-FkPPoTla_R0CzktpRuafD9fuIP_G5N-Q08PxNg,476 +django/contrib/admindocs/locale/fy/LC_MESSAGES/django.po,sha256=b3CRH9bSUl_jjb9s51RlvFXp3bmsmuxTfN_MTmIIVNA,5060 +django/contrib/admindocs/locale/ga/LC_MESSAGES/django.mo,sha256=PkY5sLKd7gEIE2IkuuNJXP5RmjC-D4OODRv6KCCUDX8,1940 +django/contrib/admindocs/locale/ga/LC_MESSAGES/django.po,sha256=-l6VME96KR1KKNACVu7oHzlhCrnkC1PaJQyskOUqOvk,5211 +django/contrib/admindocs/locale/gd/LC_MESSAGES/django.mo,sha256=k5-Ov9BkwYHZ_IvIxQdHKVBdOUN7kWGft1l7w5Scd5o,6941 +django/contrib/admindocs/locale/gd/LC_MESSAGES/django.po,sha256=FyvfRNkSrEZo8x1didB6nFHYD54lZfKSoAGcwJ2wLso,7478 +django/contrib/admindocs/locale/gl/LC_MESSAGES/django.mo,sha256=15OYKk17Dlz74RReFrCHP3eHmaxP8VeRE2ylDOeUY8w,6564 +django/contrib/admindocs/locale/gl/LC_MESSAGES/django.po,sha256=mvQmxR4LwDLbCWyIU-xmJEw6oeSY3KFWC1nqnbnuDyc,7197 +django/contrib/admindocs/locale/he/LC_MESSAGES/django.mo,sha256=1_aXtUXx-NISzJmlfprUZ5LieD9BwCcCUQ-DQ_YF-jk,6998 +django/contrib/admindocs/locale/he/LC_MESSAGES/django.po,sha256=aONIl7C_5hgo0agjYleyZAkj4_VPkQVPT0R7wWPhJEs,7589 +django/contrib/admindocs/locale/hi/LC_MESSAGES/django.mo,sha256=sZhObIxqrmFu5Y-ZOQC0JGM3ly4IVFr02yqOOOHnDag,2297 +django/contrib/admindocs/locale/hi/LC_MESSAGES/django.po,sha256=X6UfEc6q0BeaxVP_C4priFt8irhh-YGOUUzNQyVnEYY,5506 +django/contrib/admindocs/locale/hr/LC_MESSAGES/django.mo,sha256=fMsayjODNoCdbpBAk9GHtIUaGJGFz4sD9qYrguj-BQA,2550 +django/contrib/admindocs/locale/hr/LC_MESSAGES/django.po,sha256=qi2IB-fBkGovlEz2JAQRUNE54MDdf5gjNJWXM-dIG1s,5403 +django/contrib/admindocs/locale/hsb/LC_MESSAGES/django.mo,sha256=4CbZ95VHJUg3UNt-FdzPtUtHJLralgnhadz-evigiFA,6770 +django/contrib/admindocs/locale/hsb/LC_MESSAGES/django.po,sha256=ty8zWmqY160ZpSbt1-_2iY2M4RIL7ksh5-ggQGc_TO8,7298 +django/contrib/admindocs/locale/hu/LC_MESSAGES/django.mo,sha256=ATEt9wE2VNQO_NMcwepgxpS7mYXdVD5OySFFPWpnBUA,6634 +django/contrib/admindocs/locale/hu/LC_MESSAGES/django.po,sha256=3XKQrlonyLXXpU8xeS1OLXcKmmE2hiBoMJN-QZ3k82g,7270 +django/contrib/admindocs/locale/ia/LC_MESSAGES/django.mo,sha256=KklX2loobVtA6PqHOZHwF1_A9YeVGlqORinHW09iupI,1860 +django/contrib/admindocs/locale/ia/LC_MESSAGES/django.po,sha256=Z7btOCeARREgdH4CIJlVob_f89r2M9j55IDtTLtgWJU,5028 +django/contrib/admindocs/locale/id/LC_MESSAGES/django.mo,sha256=2HZrdwFeJV4Xk2HIKsxp_rDyBrmxCuRb92HtFtW8MxE,6343 +django/contrib/admindocs/locale/id/LC_MESSAGES/django.po,sha256=O01yt7iDXvEwkebUxUlk-vCrLR26ebuqI51x64uqFl4,7041 +django/contrib/admindocs/locale/io/LC_MESSAGES/django.mo,sha256=5t9Vurrh6hGqKohwsZIoveGeYCsUvRBRMz9M7k9XYY8,464 +django/contrib/admindocs/locale/io/LC_MESSAGES/django.po,sha256=SVZZEmaS1WbXFRlLLGg5bzUe09pXR23TeJtHUbhyl0w,5048 +django/contrib/admindocs/locale/is/LC_MESSAGES/django.mo,sha256=pEr-_MJi4D-WpNyFaQe3tVKVLq_9V-a4eIF18B3Qyko,1828 +django/contrib/admindocs/locale/is/LC_MESSAGES/django.po,sha256=-mD5fFnL6xUqeW4MITzm8Lvx6KXq4C9DGsEM9kDluZ8,5045 +django/contrib/admindocs/locale/it/LC_MESSAGES/django.mo,sha256=AzCkkJ8x-V38XSOdOG2kMSUujcn0mD8TIvdAeNT6Qcw,6453 +django/contrib/admindocs/locale/it/LC_MESSAGES/django.po,sha256=SUsGtCKkCVoj5jaM6z_-JQR8kv8W4Wv_OE26hpOb96s,7171 +django/contrib/admindocs/locale/ja/LC_MESSAGES/django.mo,sha256=KoPwCbH9VlKoP_7zTEjOzPsHZ7jVWl2grQRckQmshw4,7358 +django/contrib/admindocs/locale/ja/LC_MESSAGES/django.po,sha256=6ZTqM2qfBS_j5aLH52yJPYW4e4X5MqiQFdqV1fmEQGg,8047 +django/contrib/admindocs/locale/ka/LC_MESSAGES/django.mo,sha256=w2cHLI1O3pVt43H-h71cnNcjNNvDC8y9uMYxZ_XDBtg,4446 +django/contrib/admindocs/locale/ka/LC_MESSAGES/django.po,sha256=omKVSzNA3evF5Mk_Ud6utHql-Do7s9xDzCVQGQA0pSg,6800 +django/contrib/admindocs/locale/kab/LC_MESSAGES/django.mo,sha256=XTuWnZOdXhCFXEW4Hp0zFtUtAF0wJHaFpQqoDUTWYGw,1289 +django/contrib/admindocs/locale/kab/LC_MESSAGES/django.po,sha256=lQWewMZncWUvGhpkgU_rtwWHcgAyvhIkrDfjFu1l-d8,4716 +django/contrib/admindocs/locale/kk/LC_MESSAGES/django.mo,sha256=mmhLzn9lo4ff_LmlIW3zZuhE77LoSUfpaMMMi3oyi38,1587 +django/contrib/admindocs/locale/kk/LC_MESSAGES/django.po,sha256=72sxLw-QDSFnsH8kuzeQcV5jx7Hf1xisBmxI8XqSCYw,5090 +django/contrib/admindocs/locale/km/LC_MESSAGES/django.mo,sha256=Fff1K0qzialXE_tLiGM_iO5kh8eAmQhPZ0h-eB9iNOU,1476 +django/contrib/admindocs/locale/km/LC_MESSAGES/django.po,sha256=E_CaaYc4GqOPgPh2t7iuo0Uf4HSQQFWAoxSOCG-uEGU,4998 +django/contrib/admindocs/locale/kn/LC_MESSAGES/django.mo,sha256=lisxE1zzW-Spdm7hIzXxDAfS7bM-RdrAG_mQVwz9WMU,1656 +django/contrib/admindocs/locale/kn/LC_MESSAGES/django.po,sha256=u6JnB-mYoYWvLl-2pzKNfeNlT1s6A2I3lRi947R_0yA,5184 +django/contrib/admindocs/locale/ko/LC_MESSAGES/django.mo,sha256=nVBVLfXUlGQCeF2foSQ2kksBmR3KbweXdbD6Kyq-PrU,6563 +django/contrib/admindocs/locale/ko/LC_MESSAGES/django.po,sha256=y2YjuXM3p0haXrGpxRtm6I84o75TQaMeT4xbHCg7zOM,7342 +django/contrib/admindocs/locale/ky/LC_MESSAGES/django.mo,sha256=HEJo4CLoIOWpK-MPcTqLhbNMA8Mt3totYN1YbJ_SNn4,7977 +django/contrib/admindocs/locale/ky/LC_MESSAGES/django.po,sha256=VaSXjz8Qlr2EI8f12gtziN7yA7IWsaVoEzL3G6dERXs,8553 +django/contrib/admindocs/locale/lb/LC_MESSAGES/django.mo,sha256=N0hKFuAdDIq5clRKZirGh4_YDLsxi1PSX3DVe_CZe4k,474 +django/contrib/admindocs/locale/lb/LC_MESSAGES/django.po,sha256=B46-wRHMKUMcbvMCdojOCxqIVL5qVEh4Czo20Qgz6oU,5058 +django/contrib/admindocs/locale/lt/LC_MESSAGES/django.mo,sha256=KOnpaVeomKJIHcVLrkeRVnaqQHzFdYM_wXZbbqxWs4g,6741 +django/contrib/admindocs/locale/lt/LC_MESSAGES/django.po,sha256=-uzCS8193VCZPyhO8VOi11HijtBG9CWVKStFBZSXfI4,7444 +django/contrib/admindocs/locale/lv/LC_MESSAGES/django.mo,sha256=5PAE_peuqlRcc45pm6RsSqnBpG-o8OZpfdt2aasYM2w,6449 +django/contrib/admindocs/locale/lv/LC_MESSAGES/django.po,sha256=_mFvAQT1ZVBuDhnWgKY3bVQUWA8DoEf-HFAEsMfkGuU,7085 +django/contrib/admindocs/locale/mk/LC_MESSAGES/django.mo,sha256=8H9IpRASM7O2-Ql1doVgM9c4ybZ2KcfnJr12PpprgP4,8290 +django/contrib/admindocs/locale/mk/LC_MESSAGES/django.po,sha256=Uew7tEljjgmslgfYJOP9JF9ELp6NbhkZG_v50CZgBg8,8929 +django/contrib/admindocs/locale/ml/LC_MESSAGES/django.mo,sha256=bm4tYwcaT8XyPcEW1PNZUqHJIds9CAq3qX_T1-iD4k4,6865 +django/contrib/admindocs/locale/ml/LC_MESSAGES/django.po,sha256=yNINX5M7JMTbYnFqQGetKGIXqOjGJtbN2DmIW9BKQ_c,8811 +django/contrib/admindocs/locale/mn/LC_MESSAGES/django.mo,sha256=KqdcvSpqmjRfA8M4nGB9Cnu9Auj4pTu9aH07XtCep3I,7607 +django/contrib/admindocs/locale/mn/LC_MESSAGES/django.po,sha256=PGhlnzDKyAIRzaPCbNujpxSpf_JaOG66LK_NMlnZy6I,8316 +django/contrib/admindocs/locale/mr/LC_MESSAGES/django.mo,sha256=LDGC7YRyVBU50W-iH0MuESunlRXrNfNjwjXRCBdfFVg,468 +django/contrib/admindocs/locale/mr/LC_MESSAGES/django.po,sha256=5cUgPltXyS2Z0kIKF5ER8f5DuBhwmAINJQyfHj652d0,5052 +django/contrib/admindocs/locale/ms/LC_MESSAGES/django.mo,sha256=vgoSQlIQeFWaVfJv3YK9_0FOywWwxLhWGICKBdxcqJY,6557 +django/contrib/admindocs/locale/ms/LC_MESSAGES/django.po,sha256=Qy_NjgqwEwLGk4oaHB4Np3dVbPeCK2URdI73S73IZLE,7044 +django/contrib/admindocs/locale/my/LC_MESSAGES/django.mo,sha256=AsdUmou0FjCiML3QOeXMdbHiaSt2GdGMcEKRJFonLOQ,1721 +django/contrib/admindocs/locale/my/LC_MESSAGES/django.po,sha256=c75V-PprKrWzgrHbfrZOpm00U_zZRzxAUr2U_j8MF4w,5189 +django/contrib/admindocs/locale/nb/LC_MESSAGES/django.mo,sha256=qlzN0-deW2xekojbHi2w6mYKeBe1Cf1nm8Z5FVrmYtA,6308 +django/contrib/admindocs/locale/nb/LC_MESSAGES/django.po,sha256=a60vtwHJXhjbRAtUIlO0w3XfQcQ0ljwmwFG3WbQ7PNo,6875 +django/contrib/admindocs/locale/ne/LC_MESSAGES/django.mo,sha256=fWPAUZOX9qrDIxGhVVouJCVDWEQLybZ129wGYymuS-c,2571 +django/contrib/admindocs/locale/ne/LC_MESSAGES/django.po,sha256=wb8pCm141YfGSHVW84FnAvsKt5KnKvzNyzGcPr-Wots,5802 +django/contrib/admindocs/locale/nl/LC_MESSAGES/django.mo,sha256=1-s_SdVm3kci2yLQhv1q6kt7zF5EdbaneGAr6PJ7dQU,6498 +django/contrib/admindocs/locale/nl/LC_MESSAGES/django.po,sha256=7s4RysNYRSisywqqZOrRR0il530jRlbEFP3kr4Hq2PA,7277 +django/contrib/admindocs/locale/nn/LC_MESSAGES/django.mo,sha256=tIOU1WrHkAfxD6JBpdakiMi6pVzzvIg0jun6gii-D08,6299 +django/contrib/admindocs/locale/nn/LC_MESSAGES/django.po,sha256=oekYY3xjjM2sPnHv_ZXxAti1ySPF-HxLrvLLk7Izibk,6824 +django/contrib/admindocs/locale/os/LC_MESSAGES/django.mo,sha256=zSQBgSj4jSu5Km0itNgDtbkb1SbxzRvQeZ5M9sXHI8k,2044 +django/contrib/admindocs/locale/os/LC_MESSAGES/django.po,sha256=hZlMmmqfbGmoiElGbJg7Fp791ZuOpRFrSu09xBXt6z4,5215 +django/contrib/admindocs/locale/pa/LC_MESSAGES/django.mo,sha256=yFeO0eZIksXeDhAl3CrnkL1CF7PHz1PII2kIxGA0opQ,1275 +django/contrib/admindocs/locale/pa/LC_MESSAGES/django.po,sha256=DA5LFFLOXHIJIqrrnj9k_rqL-wr63RYX_i-IJFhBuc0,4900 +django/contrib/admindocs/locale/pl/LC_MESSAGES/django.mo,sha256=DHxRNP6YK8qocDqSd2DZg7n-wPp2hJSbjNBLFti7U8o,6633 +django/contrib/admindocs/locale/pl/LC_MESSAGES/django.po,sha256=mRjleE2-9r9TfseHWeyjvRwzBZP_t2LMvihq8n_baU8,7575 +django/contrib/admindocs/locale/pt/LC_MESSAGES/django.mo,sha256=WcXhSlbGdJgVMvydkPYYee7iOQ9SYdrLkquzgIBhVWU,6566 +django/contrib/admindocs/locale/pt/LC_MESSAGES/django.po,sha256=J98Hxa-ApyzRevBwcAldK9bRYbkn5DFw3Z5P7SMEwx0,7191 +django/contrib/admindocs/locale/pt_BR/LC_MESSAGES/django.mo,sha256=L8t589rbg4vs4HArLpgburmMufZ6BTuwxxkv1QUetBA,6590 +django/contrib/admindocs/locale/pt_BR/LC_MESSAGES/django.po,sha256=EG4xELZ8emUIWB78cw8gFeiqTiN9UdAuEaXHyPyNtIE,7538 +django/contrib/admindocs/locale/ro/LC_MESSAGES/django.mo,sha256=9K8Sapn6sOg1wtt2mxn7u0cnqPjEHH70qjwM-XMPzNA,6755 +django/contrib/admindocs/locale/ro/LC_MESSAGES/django.po,sha256=b4AsPjWBYHQeThAtLP_TH4pJitwidtoPNkJ7dowUuRg,7476 +django/contrib/admindocs/locale/ru/LC_MESSAGES/django.mo,sha256=9pIPv2D0rq29vrBNWZENM_SOdNpaPidxmgT20hWtBis,8434 +django/contrib/admindocs/locale/ru/LC_MESSAGES/django.po,sha256=BTlxkS4C0DdfC9QJCegXwi5ejfG9pMsAdfy6UJzec3s,9175 +django/contrib/admindocs/locale/sk/LC_MESSAGES/django.mo,sha256=QR3Yvh6y6qJLr4umB0_HcVRIrqD-o1z3rnDv38hLkCQ,6670 +django/contrib/admindocs/locale/sk/LC_MESSAGES/django.po,sha256=QPTSNtN-7QBUX7G7d67zs5kPHS3tXoi7WCy_y1nhPfQ,7375 +django/contrib/admindocs/locale/sl/LC_MESSAGES/django.mo,sha256=FMg_s9ZpeRD42OsSF9bpe8pRQ7wP7-a9WWnaVliqXpU,6508 +django/contrib/admindocs/locale/sl/LC_MESSAGES/django.po,sha256=JWO_WZAwBpXw-4FoB7rkWXGhi9aEVq1tH2fOC69rcgg,7105 +django/contrib/admindocs/locale/sq/LC_MESSAGES/django.mo,sha256=XvNDzCc3-Hh5Pz7SHhG8zCT_3dtqGzBLkDqhim4jJpc,6551 +django/contrib/admindocs/locale/sq/LC_MESSAGES/django.po,sha256=0GZvLpxbuYln7GrTsFyzgjIleSw6Z9IRSPgAWWdx6Eo,7165 +django/contrib/admindocs/locale/sr/LC_MESSAGES/django.mo,sha256=wQbXQFTFYjeJvUQ4twmF_O2SYkYkigJ1LQj8xdC5Yu4,8154 +django/contrib/admindocs/locale/sr/LC_MESSAGES/django.po,sha256=KT72y37njw6vgAfXOoY41w_Myv5yrzFC1BQVAd_V79s,8778 +django/contrib/admindocs/locale/sr_Latn/LC_MESSAGES/django.mo,sha256=pCZYs6VIEkQE0VysTFwCc7L-OlsvexP7cICaXrCbLyc,3051 +django/contrib/admindocs/locale/sr_Latn/LC_MESSAGES/django.po,sha256=jtguErXG2NbHsakZ9ZXwsOlYEbw3WGTcUTzFha27N3U,5726 +django/contrib/admindocs/locale/sv/LC_MESSAGES/django.mo,sha256=5i9qxo9V7TghSIpKCOw5PpITYYHMP-0NhFivwc-w0yw,6394 +django/contrib/admindocs/locale/sv/LC_MESSAGES/django.po,sha256=WhABV5B-rhBly6ueJPOMsIBjSiw7i1yCZUQsXWE_jV4,7137 +django/contrib/admindocs/locale/sw/LC_MESSAGES/django.mo,sha256=pyJfGL7UdPrJAVlCB3YimXxTjTfEkoZQWX-CSpDkcWc,1808 +django/contrib/admindocs/locale/sw/LC_MESSAGES/django.po,sha256=SIywrLX1UGx4OiPxoxUYelmQ1YaY2LMa3dxynGQpHp8,4929 +django/contrib/admindocs/locale/ta/LC_MESSAGES/django.mo,sha256=8SjQ9eGGyaZGhkuDoZTdtYKuqcVyEtWrJuSabvNRUVM,1675 +django/contrib/admindocs/locale/ta/LC_MESSAGES/django.po,sha256=k593yzVqpSQOsdpuF-rdsSLwKQU8S_QFMRpZXww__1A,5194 +django/contrib/admindocs/locale/te/LC_MESSAGES/django.mo,sha256=eAzNpYRy_G1erCcKDAMnJC4809ITRHvJjO3vpyAC_mk,1684 +django/contrib/admindocs/locale/te/LC_MESSAGES/django.po,sha256=oDg_J8JxepFKIe5m6lDKVC4YWQ_gDLibgNyQ3508VOM,5204 +django/contrib/admindocs/locale/tg/LC_MESSAGES/django.mo,sha256=jSMmwS6F_ChDAZDyTZxRa3YuxkXWlO-M16osP2NLRc0,7731 +django/contrib/admindocs/locale/tg/LC_MESSAGES/django.po,sha256=mewOHgRsFydk0d5IY3jy3rOWa6uHdatlSIvFNZFONsc,8441 +django/contrib/admindocs/locale/th/LC_MESSAGES/django.mo,sha256=bHK49r45Q1nX4qv0a0jtDja9swKbDHHJVLa3gM13Cb4,2167 +django/contrib/admindocs/locale/th/LC_MESSAGES/django.po,sha256=_GMgPrD8Zs0lPKQOMlBmVu1I59yXSV42kfkrHzeiehY,5372 +django/contrib/admindocs/locale/tr/LC_MESSAGES/django.mo,sha256=L1iBsNGqqfdNkZZmvnnBB-HxogAgngwhanY1FYefveE,6661 +django/contrib/admindocs/locale/tr/LC_MESSAGES/django.po,sha256=D4vmznsY4icyKLXQUgAL4WZL5TOUZYVUSCJ4cvZuFg8,7311 +django/contrib/admindocs/locale/tt/LC_MESSAGES/django.mo,sha256=pQmAQOPbrBVzBqtoQ0dsFWFwC6LxA5mQZ9QPqL6pSFw,1869 +django/contrib/admindocs/locale/tt/LC_MESSAGES/django.po,sha256=NCLv7sSwvEficUOSoMJlHGqjgjYvrvm2V3j1Gkviw80,5181 +django/contrib/admindocs/locale/udm/LC_MESSAGES/django.mo,sha256=hwDLYgadsKrQEPi9HiuMWF6jiiYUSy4y-7PVNJMaNpY,618 +django/contrib/admindocs/locale/udm/LC_MESSAGES/django.po,sha256=29fpfn4p8KxxrBdg4QB0GW_l8genZVV0kYi50zO-qKs,5099 +django/contrib/admindocs/locale/ug/LC_MESSAGES/django.mo,sha256=OIyPz5i48Ab2CVmCe71agW8qMsYMTwTG2E7rJft7P5k,7867 +django/contrib/admindocs/locale/ug/LC_MESSAGES/django.po,sha256=GM6ypRwZ6d6VXM0XVvg9p_334pxhex1yd5-HS8Z1z9U,8380 +django/contrib/admindocs/locale/uk/LC_MESSAGES/django.mo,sha256=G-3yCDj2jK7ZTu80YXGJ_ZR1E7FejbLxTFe866G4Pr0,8468 +django/contrib/admindocs/locale/uk/LC_MESSAGES/django.po,sha256=bbWzP-gpbslzbTBc_AO7WBNmtr3CkLOwkSJHI0Z_dTA,9330 +django/contrib/admindocs/locale/ur/LC_MESSAGES/django.mo,sha256=VNg9o_7M0Z2LC0n3_-iwF3zYmncRJHaFqqpxuPmMq84,1836 +django/contrib/admindocs/locale/ur/LC_MESSAGES/django.po,sha256=QTg85c4Z13hMN_PnhjaLX3wx6TU4SH4hPTzNBfNVaMU,5148 +django/contrib/admindocs/locale/vi/LC_MESSAGES/django.mo,sha256=F6dyo00yeyUND_w1Ocm9SL_MUdXb60QQpmAQPto53IU,1306 +django/contrib/admindocs/locale/vi/LC_MESSAGES/django.po,sha256=JrVKjT848Y1cS4tpH-eRivFNwM-cUs886UEhY2FkTPw,4836 +django/contrib/admindocs/locale/zh_Hans/LC_MESSAGES/django.mo,sha256=ngPlxN85wGOMKoo3OK3wUQeikoaxPKqAIsgw2_0ovN4,6075 +django/contrib/admindocs/locale/zh_Hans/LC_MESSAGES/django.po,sha256=TNdJGJCAi0OijBN6w23SwKieZqNqkgNt2qdlPfY-r20,6823 +django/contrib/admindocs/locale/zh_Hant/LC_MESSAGES/django.mo,sha256=7c2QywaTzF_GX8T2PUknQ_PN5s0Cx37_cO-walIg8mk,4725 +django/contrib/admindocs/locale/zh_Hant/LC_MESSAGES/django.po,sha256=uX-3zu8RQdntg__qYBweKtcuBgLsXPUYApf4bQx9eSU,6153 +django/contrib/admindocs/middleware.py,sha256=owqLbigBtxKmhPQmz767KOAkN3nKRIJrwZAUuHRIAQM,1329 +django/contrib/admindocs/templates/admin_doc/bookmarklets.html,sha256=fSQP3eErm6R8yD7c8-KVilViI0vww6dqwkLwaAjgCaY,1282 +django/contrib/admindocs/templates/admin_doc/index.html,sha256=6bmIkahIH8CWMhGEytTHUZ7DtrDmcqhomJe48KbzvZY,1369 +django/contrib/admindocs/templates/admin_doc/missing_docutils.html,sha256=sx3z874_SIWPjKndIzfwYl8bQzEpTYMckA11RFFbqRI,788 +django/contrib/admindocs/templates/admin_doc/model_detail.html,sha256=kN8S3XRv_mLy8dLke-JFilT8zo_U0gAThlkFrM9qVqU,1866 +django/contrib/admindocs/templates/admin_doc/model_index.html,sha256=7fgybgDWYcWZaDPgf25DxFkdxtnrqnpLem7iVmPQmLk,1346 +django/contrib/admindocs/templates/admin_doc/template_detail.html,sha256=sApk1HNa-n41lMIxRZHGoft9S4PvYedDPTtvHWuSsSc,1035 +django/contrib/admindocs/templates/admin_doc/template_filter_index.html,sha256=U2HBVHXtgCqUp9hLuOMVqCxBbXyYMMgAORG8fziN7uc,1775 +django/contrib/admindocs/templates/admin_doc/template_tag_index.html,sha256=S4U-G05yi1YIlFEv-HG20bDiq4rhdiZCgebhVBzNzdY,1731 +django/contrib/admindocs/templates/admin_doc/view_detail.html,sha256=XmsemLe45BpHDKAroqH7dwlmI9npVu2DZGzELA7trgs,914 +django/contrib/admindocs/templates/admin_doc/view_index.html,sha256=ZLfmxMkVlPYETRFnjLmU3bagve4ZvY1Xzsya1Lntgkw,1734 +django/contrib/admindocs/urls.py,sha256=spPSD6wc_B9eABF4mEWIhPSZ3w6W4fM6ERGepo8NRtY,1309 +django/contrib/admindocs/utils.py,sha256=38lwFUI08_m5OK6d-EUzp90qxysM9Da7lAn-rwcSnwI,7554 +django/contrib/admindocs/views.py,sha256=mZMFgnVy-loEAI255NdgLVdJdMrwRbbXKwV40sbpsv4,18623 +django/contrib/auth/__init__.py,sha256=VeAspTskoTEXIlwPT-F3hZewopHyHJxaczuZDupxRX4,9465 +django/contrib/auth/admin.py,sha256=vTH4EmyETUNcAjCSaZ_NuViNDSYAKtCOO4tJHRlyJc0,9153 +django/contrib/auth/apps.py,sha256=JE5zuVw7Tx6NFULN_u8sOxs0OnHczMC9bM0N_m1xsmA,1224 +django/contrib/auth/backends.py,sha256=CimJyPjL4y1hth8WLKg87kJE7WqZYrNRKIZ8qfeaDIM,8535 +django/contrib/auth/base_user.py,sha256=8U8y3TsTY4h-p3uKagX5mVbIAR605iv-XZqmWMR8l5o,5512 +django/contrib/auth/checks.py,sha256=q05m4ylm3r3z8t7BPKeJLlpz5qfv6HOiPNcEl6sgAfw,8442 +django/contrib/auth/common-passwords.txt.gz,sha256=MrUGEpphkJZUW9O7s1yYu5g7PnYWd48T5BWySr3CO-c,82262 +django/contrib/auth/context_processors.py,sha256=8BbvdbTVPl8GVgB5-2LTzx6FrGsMzev-E7JMnUgr-rM,1911 +django/contrib/auth/decorators.py,sha256=0ghSVBcSxUgjfi4HWOK1_7AkSo6S4q6YsHM-d8mSbM0,2901 +django/contrib/auth/forms.py,sha256=V5qgl6lKIYr8SX3m1-7v3afQ0fHkHnUsLltgWPTWSU4,17620 +django/contrib/auth/handlers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/auth/handlers/modwsgi.py,sha256=bTXKVMezywsn1KA2MVyDWeHvTNa2KrwIxn2olH7o_5I,1248 +django/contrib/auth/hashers.py,sha256=O5vqTXgaSFMyXipu0mwNMjt-Al26eOdpNhVoAyb9pu4,27878 +django/contrib/auth/locale/af/LC_MESSAGES/django.mo,sha256=mVOEfY5dw97Eo1JuCOonKhU1p2Sfhi5QCPkvm_ExbOQ,7514 +django/contrib/auth/locale/af/LC_MESSAGES/django.po,sha256=twHhtsP_x0xV_NbCaTUqF4mBzODjmdjkrawlmn1qwbQ,7739 +django/contrib/auth/locale/ar/LC_MESSAGES/django.mo,sha256=7LhxFfL9y6RAfZ8PU-1lKI2V02LbHxXtB1UAf_vXpuc,10040 +django/contrib/auth/locale/ar/LC_MESSAGES/django.po,sha256=2QIaioY0RedAB0CFKVZLhGoCnhLzgUh84sAR7i6QUnQ,10520 +django/contrib/auth/locale/ar_DZ/LC_MESSAGES/django.mo,sha256=0UokSPc3WDs_0PozSalfBaq4JFYgF1Rt7b90CKvY5jE,10228 +django/contrib/auth/locale/ar_DZ/LC_MESSAGES/django.po,sha256=GDvm2m1U7NOY5l7FijKGR77DEZt6rYWoSPCxsY5BZ3Y,10574 +django/contrib/auth/locale/ast/LC_MESSAGES/django.mo,sha256=Pt3gYY3j8Eroo4lAEmf-LR6u9U56mpE3vqLhjR4Uq-o,2250 +django/contrib/auth/locale/ast/LC_MESSAGES/django.po,sha256=Kiq4s8d1HnYpo3DQGlgUl3bOkxmgGW8CvGp9AbryRk8,5440 +django/contrib/auth/locale/az/LC_MESSAGES/django.mo,sha256=kwobdDjncjpc7x7AQgAGSrAdrNlV3mJm1rxyAwweGKo,7576 +django/contrib/auth/locale/az/LC_MESSAGES/django.po,sha256=HQB__hodya8egKUqZElnuw47NYOHKpNnXYUpnl3P8LI,7932 +django/contrib/auth/locale/be/LC_MESSAGES/django.mo,sha256=ofb4WISgh93fPJemtBF0VyZ-pg0RHys1iMpO5eGYHQc,10123 +django/contrib/auth/locale/be/LC_MESSAGES/django.po,sha256=CY1dPSnUX4LIbI4sHE43nO-4yHYJLn5BlGPDhjxZX88,10450 +django/contrib/auth/locale/bg/LC_MESSAGES/django.mo,sha256=2hHb1wK_EGWfedP5xhPvDQ2VtLWL0vBQArEa5JVIRzc,9539 +django/contrib/auth/locale/bg/LC_MESSAGES/django.po,sha256=1GkraLFvGGCN8hnbr3I9ACyAA6nkLUSkCpBeBcXjU8Y,10072 +django/contrib/auth/locale/bn/LC_MESSAGES/django.mo,sha256=cJSawQn3rNh2I57zK9vRi0r1xc598Wr26AyHh6D50ZQ,5455 +django/contrib/auth/locale/bn/LC_MESSAGES/django.po,sha256=5Vqd4n9ab98IMev4GHLxpO7f4r9nnhC3Nfx27HQNd8s,7671 +django/contrib/auth/locale/br/LC_MESSAGES/django.mo,sha256=nxLj88BBhT3Hudev1S_BRC8P6Jv7eoR8b6CHGt5eoPo,1436 +django/contrib/auth/locale/br/LC_MESSAGES/django.po,sha256=rFo68wfXMyju633KCAhg0Jcb3GVm3rk4opFQqI89d6Y,5433 +django/contrib/auth/locale/bs/LC_MESSAGES/django.mo,sha256=jDjP1qIs02k6RixY9xy3V7Cr6zi-henR8nDnhqNG18s,3146 +django/contrib/auth/locale/bs/LC_MESSAGES/django.po,sha256=NOICHHU8eFtltH0OBlnasz9TF0uZGZd3hMibRmn158E,5975 +django/contrib/auth/locale/ca/LC_MESSAGES/django.mo,sha256=lqiOLv_LZDLeXbJZYsrWRHzcnwd1vd00tW5Jrh-HHkY,7643 +django/contrib/auth/locale/ca/LC_MESSAGES/django.po,sha256=v-3t7bDTh1835nZnjYh3_HyN4yw4a1HyHpC3-jX79Z0,8216 +django/contrib/auth/locale/ckb/LC_MESSAGES/django.mo,sha256=YiyQ7keGzWy_TSSjneCqj3TOqagupIgwsu038MyBh_k,9295 +django/contrib/auth/locale/ckb/LC_MESSAGES/django.po,sha256=ELvFy8shrwy_ZI5zfOT6z9bRRfPENhfM5lKfY9VeIBI,9656 +django/contrib/auth/locale/cs/LC_MESSAGES/django.mo,sha256=7TuyZNQ11j4iLxxr_xch3gBDQ0cSTh0VFUa0FMzH1Uo,7836 +django/contrib/auth/locale/cs/LC_MESSAGES/django.po,sha256=qoA5lHFEwLZZakgYONzA-TxBqpBNhBytGHxS40YCf0s,8292 +django/contrib/auth/locale/cy/LC_MESSAGES/django.mo,sha256=lSfCwEVteW4PDaiGKPDxnSnlDUcGMkPfsxIluExZar0,4338 +django/contrib/auth/locale/cy/LC_MESSAGES/django.po,sha256=-LPAKGXNzB77lVHfCRmFlH3SUaLgOXk_YxfC0BomcEs,6353 +django/contrib/auth/locale/da/LC_MESSAGES/django.mo,sha256=ZZgOToa8qKpjra9CS7SjjNiYjLTbEDmKIpzws0wpjaI,7560 +django/contrib/auth/locale/da/LC_MESSAGES/django.po,sha256=9MhLbrd25hBd5bG5w5xhUyXdENOzcdtA3mZJoXiM7g4,8045 +django/contrib/auth/locale/de/LC_MESSAGES/django.mo,sha256=nvwrbU-uvQonGW_UD5zVh7u70csi_5qCehsI-AlTRx4,7607 +django/contrib/auth/locale/de/LC_MESSAGES/django.po,sha256=MJGIuwfkwEs9oiktL4C2uB0XXG6gh2zCI_jr-DcH5Tk,8158 +django/contrib/auth/locale/dsb/LC_MESSAGES/django.mo,sha256=ENymm4sXNqH7K1z1zP7afU18b4NUcMezi7onBMArLRc,8249 +django/contrib/auth/locale/dsb/LC_MESSAGES/django.po,sha256=iOQZuKzPrsA-NE70SxzKsJWsy1CdvGLBL7y0oogOFso,8559 +django/contrib/auth/locale/el/LC_MESSAGES/django.mo,sha256=KaP9RLYThwYWLBx0W90HI0zJZ09iNhZ3tk8UVF63n74,10072 +django/contrib/auth/locale/el/LC_MESSAGES/django.po,sha256=O5JsNCUNr1YcNNqMugoM5epN6nC5pgq3E6nKXDh3OY0,10795 +django/contrib/auth/locale/en/LC_MESSAGES/django.mo,sha256=U0OV81NfbuNL9ctF-gbGUG5al1StqN-daB-F-gFBFC8,356 +django/contrib/auth/locale/en/LC_MESSAGES/django.po,sha256=ygtJurKRiMx7o1RW1RhoPQT09d7TXFNQaTfgr0CryVA,8256 +django/contrib/auth/locale/en_AU/LC_MESSAGES/django.mo,sha256=7cPKOZX0ZmWCYU2ZwgCp8LwXj7FAdP3lMoI2u4nzgeU,7183 +django/contrib/auth/locale/en_AU/LC_MESSAGES/django.po,sha256=92Q42wfwKhGxDkomv8JlGBHVUdFIc_wvm_LUNBc9Q1k,7467 +django/contrib/auth/locale/en_GB/LC_MESSAGES/django.mo,sha256=p57gDaYVvgEk1x80Hq4Pn2SZbsp9ly3XrJ5Ttlt2yOE,3179 +django/contrib/auth/locale/en_GB/LC_MESSAGES/django.po,sha256=-yDflw5-81VOlyqkmLJN17FRuwDrhYXItFUJwx2aqpE,5787 +django/contrib/auth/locale/eo/LC_MESSAGES/django.mo,sha256=OCEu7qwKb20Cq2UO-dmHjNPXRfDTsQHp9DbyVXCxNMw,7421 +django/contrib/auth/locale/eo/LC_MESSAGES/django.po,sha256=wrvLqKIJycioUFAI7GkCRtDNZ9_OigG_Bf79Dmgpa7c,7868 +django/contrib/auth/locale/es/LC_MESSAGES/django.mo,sha256=Q7WQnxjMh1GyuAO6HZGc7v4Remmt-L_v9w8jNdYbVXU,8073 +django/contrib/auth/locale/es/LC_MESSAGES/django.po,sha256=K_XwrlPa2L5SCuy3lREnaKMF7ZE6uo8DK4np0K0YZfg,8862 +django/contrib/auth/locale/es_AR/LC_MESSAGES/django.mo,sha256=bJqsTLq8LbNucR-xsZezUZt79NyRy6Zi-XZJczUTTas,8244 +django/contrib/auth/locale/es_AR/LC_MESSAGES/django.po,sha256=dpVb-WfOZmuDjQPZg7-Xd_ThwHV34KnzIOpJ0tDkWhU,8514 +django/contrib/auth/locale/es_CO/LC_MESSAGES/django.mo,sha256=K5VaKTyeV_WoKsLR1x8ZG4VQmk3azj6ZM8Phqjs81So,6529 +django/contrib/auth/locale/es_CO/LC_MESSAGES/django.po,sha256=qJywTaYi7TmeMB1sjwsiwG8GXtxAOaOX0voj7lLVZRw,7703 +django/contrib/auth/locale/es_MX/LC_MESSAGES/django.mo,sha256=dCav1yN5q3bU4PvXZd_NxHQ8cZ9KqQCiNoe4Xi8seoY,7822 +django/contrib/auth/locale/es_MX/LC_MESSAGES/django.po,sha256=_4un21ALfFsFaqpLrkE2_I18iEfJlcAnd_X8YChfdWo,8210 +django/contrib/auth/locale/es_VE/LC_MESSAGES/django.mo,sha256=GwpZytNHtK7Y9dqQKDiVi4SfA1AtPlk824_k7awqrdI,7415 +django/contrib/auth/locale/es_VE/LC_MESSAGES/django.po,sha256=G3mSCo_XGRUfOAKUeP_UNfWVzDPpbQrVYQt8Hv3VZVM,7824 +django/contrib/auth/locale/et/LC_MESSAGES/django.mo,sha256=1c45DZTFjyhVgwEC4QqSTYpJVQC_E9CswCjmylhQjGo,7194 +django/contrib/auth/locale/et/LC_MESSAGES/django.po,sha256=Z03L45SJSCZ5qFhCpdszRjWV8IN4Yw6jZu6rAXNovx4,7828 +django/contrib/auth/locale/eu/LC_MESSAGES/django.mo,sha256=aQfIMZ8FRzP-6OpZCpC2qrd4wbyWiapJOVIWlmyqde0,7181 +django/contrib/auth/locale/eu/LC_MESSAGES/django.po,sha256=AP53NIzFy-aCLnLds70LMg-XW7F_95VSD1ZWCedgkTI,7732 +django/contrib/auth/locale/fa/LC_MESSAGES/django.mo,sha256=yeA_5LAPu7OyQssunvUNlH07bPVCyGLpnvijNenrtHQ,8979 +django/contrib/auth/locale/fa/LC_MESSAGES/django.po,sha256=NChJSgpkXrwAiTrCJzvwlm9mh-LFSD1rR1ESdRQD43o,9513 +django/contrib/auth/locale/fi/LC_MESSAGES/django.mo,sha256=fH_rcYkl9L2dK1G3MjVETXAHunCPhsXQYMTbDcNe-00,7537 +django/contrib/auth/locale/fi/LC_MESSAGES/django.po,sha256=PVwyNBaToxjyHkxy4t4L-kULjJslTe94coSxWNseyn4,7892 +django/contrib/auth/locale/fr/LC_MESSAGES/django.mo,sha256=-OY_FLVUMHl7vTazzjtjvsveuggUtY839WkITcmLfQQ,8448 +django/contrib/auth/locale/fr/LC_MESSAGES/django.po,sha256=DkL1v2GwfRWEQ5sTcyAWK6_emBLz4LZaft70nUONsxM,8809 +django/contrib/auth/locale/fy/LC_MESSAGES/django.mo,sha256=95N-77SHF0AzQEer5LuBKu5n5oWf3pbH6_hQGvDrlP4,476 +django/contrib/auth/locale/fy/LC_MESSAGES/django.po,sha256=8XOzOFx-WerF7whzTie03hgO-dkbUFZneyrpZtat5JY,3704 +django/contrib/auth/locale/ga/LC_MESSAGES/django.mo,sha256=Nd02Ed9ACCY6JCCSwtiWl3DTODLFFu9Mq6JVlr5YbYk,3572 +django/contrib/auth/locale/ga/LC_MESSAGES/django.po,sha256=FQJMR5DosuKqo4vvF0NAQnjfqbH54MSzqL2-4BO4-uM,6127 +django/contrib/auth/locale/gd/LC_MESSAGES/django.mo,sha256=BLBYJV9Adx1BsXZaM0qZ54mNRAF5s4dxB1TBLtIyMHQ,8743 +django/contrib/auth/locale/gd/LC_MESSAGES/django.po,sha256=rqPK26mtE_U-TG2qyjc5xCR-feI3sGXZR5H6ohNzx4s,9099 +django/contrib/auth/locale/gl/LC_MESSAGES/django.mo,sha256=LEs4FmCgnInkfREWy4ytvs4txunfkDuwGK4x1iDdfq8,7806 +django/contrib/auth/locale/gl/LC_MESSAGES/django.po,sha256=CRlrXwKY_gYmJRxlnCmY51N7SoFpzQen0xTSEju2goM,8239 +django/contrib/auth/locale/he/LC_MESSAGES/django.mo,sha256=gnP77qGURtGKPgbqmI6JqmX6TExxuCbM6nxZHXwRC58,8716 +django/contrib/auth/locale/he/LC_MESSAGES/django.po,sha256=qlwNJbk638S8p90BiMJyLCHZuReShEJCZTnmbPiJNks,9162 +django/contrib/auth/locale/hi/LC_MESSAGES/django.mo,sha256=7CxV1H37hMbgKIhnAWx-aJmipLRosJe1qg8BH2CABfw,5364 +django/contrib/auth/locale/hi/LC_MESSAGES/django.po,sha256=DU5YM6r1kd5fo40yqFXzEaNh42ezFQFQ-0dmVqkaKQ0,7769 +django/contrib/auth/locale/hr/LC_MESSAGES/django.mo,sha256=GEap3QClwCkuwQZKJE7qOZl93RRxmyyvTTnOTYaAWUo,5894 +django/contrib/auth/locale/hr/LC_MESSAGES/django.po,sha256=ALftoYSaI1U90RNDEvnaFATbw1SL0m8fNXAyl6DkSvo,7355 +django/contrib/auth/locale/hsb/LC_MESSAGES/django.mo,sha256=bkFfrGhbVkopx8X9W5i2HJ6L-nCgebwT5w5WDbYvePY,8082 +django/contrib/auth/locale/hsb/LC_MESSAGES/django.po,sha256=Xb_73b2geSGdwolmiCnNoO8TfzbgAzbt6iXAlzH_5rI,8383 +django/contrib/auth/locale/hu/LC_MESSAGES/django.mo,sha256=GnQqvpIXhU3emYyLw6MMNbspnvIFzpJsz8Pd-I9jrjg,7714 +django/contrib/auth/locale/hu/LC_MESSAGES/django.po,sha256=zPswCaG-SLvyVa16iRgmPDF6vmd1yxXmTWHbjwhzy0Q,8111 +django/contrib/auth/locale/hy/LC_MESSAGES/django.mo,sha256=zoLe0EqIH8HQYC5XAWd8b8mA2DpbmDSEBsF-WIKX_OQ,8001 +django/contrib/auth/locale/hy/LC_MESSAGES/django.po,sha256=wIWLbz6f0n44ZcjEbZZsgoWTpzXRGND15hudr_DQ3l0,8787 +django/contrib/auth/locale/ia/LC_MESSAGES/django.mo,sha256=OTxh6u0QmsytMrp8IKWBwMnhrYCpyS6qVnF7YBCAWe0,7626 +django/contrib/auth/locale/ia/LC_MESSAGES/django.po,sha256=ue4RXEXweO1-9sZOKkLZsyZe8yxnPWB3JZyyh3qzmlA,7895 +django/contrib/auth/locale/id/LC_MESSAGES/django.mo,sha256=rEtc08pC6VidwzSMWJvZjERYpdTZd6np3-N3YK8uILk,7296 +django/contrib/auth/locale/id/LC_MESSAGES/django.po,sha256=X1pfbeKqnWg-Sw_hycWuXWDqKpdzrDHMt2SVuifAQjQ,7733 +django/contrib/auth/locale/io/LC_MESSAGES/django.mo,sha256=YwAS3aWljAGXWcBhGU_GLVuGJbHJnGY8kUCE89CPdks,464 +django/contrib/auth/locale/io/LC_MESSAGES/django.po,sha256=W36JXuA1HQ72LspixRxeuvxogVxtk7ZBbT0VWI38_oM,3692 +django/contrib/auth/locale/is/LC_MESSAGES/django.mo,sha256=0PBYGqQKJaAG9m2jmJUzcqRVPc16hCe2euECMCrNGgI,7509 +django/contrib/auth/locale/is/LC_MESSAGES/django.po,sha256=o6dQ8WMuPCw4brSzKUU3j8PYhkLBO7XQ3M7RlsIw-VY,7905 +django/contrib/auth/locale/it/LC_MESSAGES/django.mo,sha256=pcBcdOXLqT4shr7Yw5l-pxfYknJyDW6d-jGtkncl24E,7862 +django/contrib/auth/locale/it/LC_MESSAGES/django.po,sha256=f03_tMPiwLF1ZyWfnB_j2vhPR1AXkborGQS2Tbxufzk,8471 +django/contrib/auth/locale/ja/LC_MESSAGES/django.mo,sha256=yd8QAELWqvHDRaf0rZw8Omc0IhTiqe4a3gtsujennec,8174 +django/contrib/auth/locale/ja/LC_MESSAGES/django.po,sha256=EOasPPqLOtSKPeObb5DMDextIgtAdznPe4VQb61eyxE,8533 +django/contrib/auth/locale/ka/LC_MESSAGES/django.mo,sha256=4aJoE1O5jfm5MI7kBqymzb-xOKLDw2mJD5-VhezlMA8,10372 +django/contrib/auth/locale/ka/LC_MESSAGES/django.po,sha256=hvmbD3RS3lOFj2h7A3m23asktwM5zbCdRvs7YvesAkI,11163 +django/contrib/auth/locale/kab/LC_MESSAGES/django.mo,sha256=9qKeQ-gDByoOdSxDpSbLaM4uSP5sIi7qlTn8tJidVDs,2982 +django/contrib/auth/locale/kab/LC_MESSAGES/django.po,sha256=8cq5_rjRXPzTvn1jPo6H_Jcrv6IXkWr8n9fTPvghsS8,5670 +django/contrib/auth/locale/kk/LC_MESSAGES/django.mo,sha256=RJablrXpRba6YVB_8ACSt2q_BjmxrHQZzX6RxMJImlA,3542 +django/contrib/auth/locale/kk/LC_MESSAGES/django.po,sha256=OebwPN9iWBvjDu0P2gQyBbShvIFxFIqCw8DpKuti3xk,6360 +django/contrib/auth/locale/km/LC_MESSAGES/django.mo,sha256=FahcwnCgzEamtWcDEPOiJ4KpXCIHbnSowfSRdRQ2F9U,2609 +django/contrib/auth/locale/km/LC_MESSAGES/django.po,sha256=lvRHHIkClbt_8-9Yn0xY57dMxcS72z4sUkxLb4cohP0,5973 +django/contrib/auth/locale/kn/LC_MESSAGES/django.mo,sha256=u0YygqGJYljBZwI9rm0rRk_DdgaBEMA1etL-Lk-7Mls,4024 +django/contrib/auth/locale/kn/LC_MESSAGES/django.po,sha256=J67MIAas5egVq_FJBNsug3Y7rZ8KakhQt6isyF23HAA,6957 +django/contrib/auth/locale/ko/LC_MESSAGES/django.mo,sha256=8avsa0J96myXPxdFhChPiKpjvMhaQv3EHIjuo6f3jls,7651 +django/contrib/auth/locale/ko/LC_MESSAGES/django.po,sha256=gKhckUZzS1PekOV5Jingxke-3U2dPGRAidkgBbfootg,8422 +django/contrib/auth/locale/ky/LC_MESSAGES/django.mo,sha256=mnBXtpInYxaSNIURJTmx8uBg_PH-NuPN9r54pkQY3q4,8924 +django/contrib/auth/locale/ky/LC_MESSAGES/django.po,sha256=7FeO_Kb2er0S84KnFeXVHO3TgAmEJ0gTQEDHImoxiZ4,9170 +django/contrib/auth/locale/lb/LC_MESSAGES/django.mo,sha256=OFhpMA1ZXhrs5fwZPO5IjubvWDiju4wfwWiV94SFkiA,474 +django/contrib/auth/locale/lb/LC_MESSAGES/django.po,sha256=dOfY9HjTfMQ0nkRYumw_3ZaywbUrTgT-oTXAnrRyfxo,3702 +django/contrib/auth/locale/lt/LC_MESSAGES/django.mo,sha256=-nlZHl7w__TsFUmBb5pQV_XJtKGsi9kzP6CBZXkfM8M,8146 +django/contrib/auth/locale/lt/LC_MESSAGES/django.po,sha256=-rdhB6eroSSemsdZkG1Jl4CruNZc_7dj4m5IVoyRBUQ,8620 +django/contrib/auth/locale/lv/LC_MESSAGES/django.mo,sha256=3vBq92k5qYRbQGLgkLSxuTpnf1GdDdeGJ09_OqgU8gQ,7730 +django/contrib/auth/locale/lv/LC_MESSAGES/django.po,sha256=z1gylOSLagSoNfqwTp9AkOaOpdtRjm7duNixlNM8dlk,8236 +django/contrib/auth/locale/mk/LC_MESSAGES/django.mo,sha256=XS9dslnD_YBeD07P8WQkss1gT7GIV-qLiCx4i5_Vd_k,9235 +django/contrib/auth/locale/mk/LC_MESSAGES/django.po,sha256=QOLgcwHub9Uo318P2z6sp69MI8syIIWCcr4VOom9vfs,9799 +django/contrib/auth/locale/ml/LC_MESSAGES/django.mo,sha256=UEaqq7nnGvcZ8vqFicLiuqsuEUhEjd2FpWfyzy2HqdU,12611 +django/contrib/auth/locale/ml/LC_MESSAGES/django.po,sha256=xBROIwJb5h2LmyBLAafZ2tUlPVTAOcMgt-olq5XnPT8,13107 +django/contrib/auth/locale/mn/LC_MESSAGES/django.mo,sha256=hBYT0p3LcvIKKPtIn2NzPk_2di9L8jYrUt9j3TcVvaY,9403 +django/contrib/auth/locale/mn/LC_MESSAGES/django.po,sha256=R3wAEwnefEHZsma8J-XOn4XlLtuWYKDPLwJ99DUYmvE,9913 +django/contrib/auth/locale/mr/LC_MESSAGES/django.mo,sha256=zGuqUTqcWZZn8lZY56lf5tB0_lELn7Dd0Gj78wwO5T4,468 +django/contrib/auth/locale/mr/LC_MESSAGES/django.po,sha256=yLW9WuaBHqdp9PXoDEw7c05Vt0oOtlks5TS8oxYPAO8,3696 +django/contrib/auth/locale/ms/LC_MESSAGES/django.mo,sha256=eCAZrzQxsM_pAxr_XQo2fIOsCbj5LjGKpLNCzob2l-I,7654 +django/contrib/auth/locale/ms/LC_MESSAGES/django.po,sha256=FAtyzSGcD1mIhRIg8O_1SHLdisTPGYZK-QUjzgw-wCY,7847 +django/contrib/auth/locale/my/LC_MESSAGES/django.mo,sha256=gYzFJKi15RbphgG1IHbJF3yGz3P2D9vaPoHZpA7LoH8,1026 +django/contrib/auth/locale/my/LC_MESSAGES/django.po,sha256=lH5mrq-MyY8gvrNkH2_20rkjFnbviq23wIUqIjPIgFI,5130 +django/contrib/auth/locale/nb/LC_MESSAGES/django.mo,sha256=vLJ9F73atlexwVRzZJpQjcB9arodHIMCh-z8lP5Ah9w,7023 +django/contrib/auth/locale/nb/LC_MESSAGES/django.po,sha256=c3sTCdzWGZgs94z9dIIpfrFuujBuvWvQ-P0gb1tuqlA,7520 +django/contrib/auth/locale/ne/LC_MESSAGES/django.mo,sha256=pq8dEr1ugF5ldwkCDHOq5sXaXV31InbLHYyXU56U_Ao,7722 +django/contrib/auth/locale/ne/LC_MESSAGES/django.po,sha256=bV-uWvT1ViEejrbRbVTtwC2cZVD2yX-KaESxKBnxeRI,8902 +django/contrib/auth/locale/nl/LC_MESSAGES/django.mo,sha256=IupqA81jZtPewy_qhByAuLkfMSSmbF28fYlRHlWTe_o,7591 +django/contrib/auth/locale/nl/LC_MESSAGES/django.po,sha256=e8jDgsxDVXouMJJkUXIm3_Wx9m7HabITKb22GDTU6PI,8402 +django/contrib/auth/locale/nn/LC_MESSAGES/django.mo,sha256=83HdNOuNQVgJXBZMytPz1jx3wWDy8-e6t_JNEUu6W8w,7147 +django/contrib/auth/locale/nn/LC_MESSAGES/django.po,sha256=4ciwQsZFYSV6CjFqzxxcESAm16huv9XyXvU-nchD-Fs,7363 +django/contrib/auth/locale/os/LC_MESSAGES/django.mo,sha256=DVsYGz-31nofEjZla4YhM5L7qoBnQaYnZ4TBki03AI4,4434 +django/contrib/auth/locale/os/LC_MESSAGES/django.po,sha256=Akc1qelQWRA1DE6xseoK_zsY7SFI8SpiVflsSTUhQLw,6715 +django/contrib/auth/locale/pa/LC_MESSAGES/django.mo,sha256=PeOLukzQ_CZjWBa5FGVyBEysat4Gwv40xGMS29UKRww,3666 +django/contrib/auth/locale/pa/LC_MESSAGES/django.po,sha256=7ts9PUSuvfXGRLpfyVirJLDtsQcsVWFXDepVKUVlmtc,6476 +django/contrib/auth/locale/pl/LC_MESSAGES/django.mo,sha256=3t1UX7uu6kRAo90REXiJklBvvOzpS_q9J2Krw3lGDGY,8044 +django/contrib/auth/locale/pl/LC_MESSAGES/django.po,sha256=UNPOh_qohNom1u9Zyj80gGwTT0NerYjgJsT8Hyd7TCk,8908 +django/contrib/auth/locale/pt/LC_MESSAGES/django.mo,sha256=wRDb8DfDcvtj6MCrLJ9gxKKF2SlK_QHpqufHfoYaFa8,6953 +django/contrib/auth/locale/pt/LC_MESSAGES/django.po,sha256=suckZxgfaB1G1iXeUI59tc0AsDpdvkLugy52q1qvw9I,7893 +django/contrib/auth/locale/pt_BR/LC_MESSAGES/django.mo,sha256=A5o0xjCl1-Ufra8oiirwO2WbPEpq2tITUKYdqtDncd4,7821 +django/contrib/auth/locale/pt_BR/LC_MESSAGES/django.po,sha256=jUODMwx9mJsrLhFcbDkHHoZOOe7oUZP1lI_Uy6Fw7sw,8939 +django/contrib/auth/locale/ro/LC_MESSAGES/django.mo,sha256=GD04tb5R6nEeD6ZMAcZghVhXwr8en1omw0c6BxnyHas,7777 +django/contrib/auth/locale/ro/LC_MESSAGES/django.po,sha256=YfkFuPrMwAR50k6lfOYeBbMosEbvXGWwMBD8B7p_2ZA,8298 +django/contrib/auth/locale/ru/LC_MESSAGES/django.mo,sha256=CjniNGxB5nHfGtwfPAstnaSIqvScPU8RtVwQkZnB4ts,10539 +django/contrib/auth/locale/ru/LC_MESSAGES/django.po,sha256=VvNQXP94i1mZoLYzuL_93Mwq-wzYhTprdcfJXMquogg,11142 +django/contrib/auth/locale/sk/LC_MESSAGES/django.mo,sha256=FJvONd0jTxmUrKmRb6IPt1uHGMqvjQ7uUXDvQCd8XsI,7917 +django/contrib/auth/locale/sk/LC_MESSAGES/django.po,sha256=1GYkv3O1SqhUhotYgSEf_s817wtc4C7VTh62Y2Q3J8s,8385 +django/contrib/auth/locale/sl/LC_MESSAGES/django.mo,sha256=_Lx1YcW4tvCpsXXXmcCMhrttpLR4389330tnB1ycCok,7659 +django/contrib/auth/locale/sl/LC_MESSAGES/django.po,sha256=MPEv4Ac5MwcywffmPyLxAzSMLLX1cOdZevPlpIMju28,8136 +django/contrib/auth/locale/sq/LC_MESSAGES/django.mo,sha256=iKLIYoAHIdvVA7e31ql8JEJ0mPPEC3DV1WVvTDAyd6g,7940 +django/contrib/auth/locale/sq/LC_MESSAGES/django.po,sha256=U6XIO9QpdZ6a5J-sz7X_7Z_L25mlmXLRaLGRaDXBv08,8320 +django/contrib/auth/locale/sr/LC_MESSAGES/django.mo,sha256=_1KaR6V6RJFRIuomWC5WO7EJ6JDxEt2sEKqze2fzXsM,9850 +django/contrib/auth/locale/sr/LC_MESSAGES/django.po,sha256=TwJnxpwFP0OXcnJr7JJqyhGW3g8aFKm4CZAlN0gIE5w,10175 +django/contrib/auth/locale/sr_Latn/LC_MESSAGES/django.mo,sha256=UZz0vR6TeDfav6LRkQxmBKxT8-mg75-G4o0zuRx57Cs,4385 +django/contrib/auth/locale/sr_Latn/LC_MESSAGES/django.po,sha256=xKZSDnO3gW8M4jzUp1V6uSf_XDjfbUaMU01lF34JLyA,6447 +django/contrib/auth/locale/sv/LC_MESSAGES/django.mo,sha256=hdFeVy7UXyyHylfvuWrzcLE9eIDBTGWy91ReCvFgXAg,7484 +django/contrib/auth/locale/sv/LC_MESSAGES/django.po,sha256=Ia6YyrYr3hOKBojOfMVQBlY1LvcX0hi3LRvMmf9mOIw,8130 +django/contrib/auth/locale/sw/LC_MESSAGES/django.mo,sha256=I_lEsKuMGm07X1vM3-ReGDx2j09PGLkWcG0onC8q1uQ,5029 +django/contrib/auth/locale/sw/LC_MESSAGES/django.po,sha256=TiZS5mh0oN0e6dFEdh-FK81Vk-tdv35ngJ-EbM1yX80,6455 +django/contrib/auth/locale/ta/LC_MESSAGES/django.mo,sha256=T1t5CKEb8hIumvbOtai-z4LKj2et8sX-PgBMd0B3zuA,2679 +django/contrib/auth/locale/ta/LC_MESSAGES/django.po,sha256=X8UDNmk02X9q1leNV1qWWwPNakhvNd45mCKkQ8EpZQQ,6069 +django/contrib/auth/locale/te/LC_MESSAGES/django.mo,sha256=i9hG4thA0P-Hc-S2oX7GufWFDO4Y_LF4RcdQ22cbLyE,2955 +django/contrib/auth/locale/te/LC_MESSAGES/django.po,sha256=txND8Izv2oEjSlcsx3q6l5fEUqsS-zv-sjVVILB1Bmc,6267 +django/contrib/auth/locale/tg/LC_MESSAGES/django.mo,sha256=MwdyYwC4ILX4MFsqCy46NNfPKLbW1GzRhFxMV0uIbLI,7932 +django/contrib/auth/locale/tg/LC_MESSAGES/django.po,sha256=miOPNThjHZODwjXMbON8PTMQhaCGJ0Gy6FZr6Jcj4J8,8938 +django/contrib/auth/locale/th/LC_MESSAGES/django.mo,sha256=zRpZ2xM5JEQoHtfXm2_XYdhe2FtaqH-hULJadLJ1MHU,6013 +django/contrib/auth/locale/th/LC_MESSAGES/django.po,sha256=Yhh_AQS_aM_9f_yHNNSu_3THbrU-gOoMpfiDKhkaSHo,7914 +django/contrib/auth/locale/tk/LC_MESSAGES/django.mo,sha256=5Rl2GMYL11RMSyro83E2oHNaehHjjGJKAJmp0swjV-0,7467 +django/contrib/auth/locale/tk/LC_MESSAGES/django.po,sha256=HAcou6t1zkXVrzyau7gr4i_H0DYpT5HOh9AxV-tnKD0,7763 +django/contrib/auth/locale/tr/LC_MESSAGES/django.mo,sha256=mYG9uXXM3nGlu6LPpE5bI50ijVE2o30Ozlzj-nYGmcI,7594 +django/contrib/auth/locale/tr/LC_MESSAGES/django.po,sha256=lMpqDnx1JyK7yzFws5SSdqhGg4Cgdi1jgVRjxOteS9A,8183 +django/contrib/auth/locale/tt/LC_MESSAGES/django.mo,sha256=g4pTk8QLQFCOkU29RZvR1wOd1hkOZe_o5GV9Cg5u8N4,1371 +django/contrib/auth/locale/tt/LC_MESSAGES/django.po,sha256=owkJ7iPT-zJYkuKLykfWsw8j7O8hbgzVTOD0DVv956E,5222 +django/contrib/auth/locale/udm/LC_MESSAGES/django.mo,sha256=zey19UQmS79AJFxHGrOziExPDDpJ1AbUegbCRm0x0hM,462 +django/contrib/auth/locale/udm/LC_MESSAGES/django.po,sha256=gLVgaMGg0GA3Tey1_nWIjV1lnM7czLC0XR9NFBgL2Zk,3690 +django/contrib/auth/locale/ug/LC_MESSAGES/django.mo,sha256=ofwM5-xcJz6awJwKHfxKW4NnO5ozRjpPomGDbNA5NXs,9516 +django/contrib/auth/locale/ug/LC_MESSAGES/django.po,sha256=ad2o4iCsT5ONsjX6A1WRKlTFTcBuJESIO14Dcd9bxNE,9798 +django/contrib/auth/locale/uk/LC_MESSAGES/django.mo,sha256=hjA-VzGMy8ReYSjuELwK3WEliLLjGsi0iRadzoX8UyU,10146 +django/contrib/auth/locale/uk/LC_MESSAGES/django.po,sha256=8R2bP3QC6jhcz_XSpK-GK1OPTCCb7PN6bz-1ZRX37fs,10850 +django/contrib/auth/locale/ur/LC_MESSAGES/django.mo,sha256=rippTNHoh49W19c4HDUF8G5Yo3SknL3C87Afu8YXxzA,698 +django/contrib/auth/locale/ur/LC_MESSAGES/django.po,sha256=gwSd8noEwbcvDE1Q4ZsrftvoWMwhw1J15gvdtK6E9ns,4925 +django/contrib/auth/locale/uz/LC_MESSAGES/django.mo,sha256=bDkhpvduocjekq6eZiuEfWJqnIt5hQmxxoIMhLQWzqM,2549 +django/contrib/auth/locale/uz/LC_MESSAGES/django.po,sha256=tPp8tRZwSMQCQ9AyAeUDtnRfmOk54UQMwok3HH8VNSQ,5742 +django/contrib/auth/locale/vi/LC_MESSAGES/django.mo,sha256=eBMTwnpRWRj8SZVZ1tN592Re_8CPyJzuF4Vtg9IMmFw,7892 +django/contrib/auth/locale/vi/LC_MESSAGES/django.po,sha256=mOr5WgFpwztdW-pEZ4O80MGlltYQyL2cAMhz6-Esfo0,8246 +django/contrib/auth/locale/zh_Hans/LC_MESSAGES/django.mo,sha256=yvlxCFBjcx-glKmhtkQK6e14y8ypfsuD6es3N8_XLuA,6902 +django/contrib/auth/locale/zh_Hans/LC_MESSAGES/django.po,sha256=YhVLBn5UKSNNJ6nDv_GWFcFfF4jy3AA_VsYYqxfN2j0,7689 +django/contrib/auth/locale/zh_Hant/LC_MESSAGES/django.mo,sha256=yQ5Gllu4hXzuBpBNAgtJaBMVivJeXUUlpfDS4CT1wg4,6728 +django/contrib/auth/locale/zh_Hant/LC_MESSAGES/django.po,sha256=Rw18_ZEtobUhmj2oF544zdQ6Vrac0T9UI9RJO4plOdc,7145 +django/contrib/auth/management/__init__.py,sha256=SGcjDZGJsHYG70R_VG7EXyNzaa-mV2xobfP6Fy6KN7c,5490 +django/contrib/auth/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/auth/management/commands/changepassword.py,sha256=uMA0bm8Xy2JovP9M4WrVdZF4qxgRLMaebx3sET2BKSY,2633 +django/contrib/auth/management/commands/createsuperuser.py,sha256=Pmv-bPzlc0CbrAjv6C0rBgdAYUtSSmvLA7TkqiOnP2I,13402 +django/contrib/auth/middleware.py,sha256=Or8VP4RXqTEfRXa03gDPdDv4xZyEcVU_2d0qwwMFLkg,5679 +django/contrib/auth/migrations/0001_initial.py,sha256=hFz_MZYGMy9J7yDOFl0aF-UixCbF5W12FhM-nk6rpe8,7281 +django/contrib/auth/migrations/0002_alter_permission_name_max_length.py,sha256=_q-X4Oj30Ui-w9ubqyNJxeFYiBF8H_KCne_2PvnhbP8,346 +django/contrib/auth/migrations/0003_alter_user_email_max_length.py,sha256=nVZXtNuYctwmwtY0wvWRGj1pqx2FUq9MbWM7xAAd-r8,418 +django/contrib/auth/migrations/0004_alter_user_username_opts.py,sha256=lTjbNCyam-xMoSsxN_uAdyxOpK-4YehkeilisepYNEo,880 +django/contrib/auth/migrations/0005_alter_user_last_login_null.py,sha256=efYKNdwAD91Ce8BchSM65bnEraB4_waI_J94YEv36u4,410 +django/contrib/auth/migrations/0006_require_contenttypes_0002.py,sha256=AMsW40BfFLYtvv-hXGjJAwKR5N3VE9czZIukYNbF54E,369 +django/contrib/auth/migrations/0007_alter_validators_add_error_messages.py,sha256=EV24fcMnUw-14ZZLo9A_l0ZJL5BgBAaUe-OfVPbMBC8,802 +django/contrib/auth/migrations/0008_alter_user_username_max_length.py,sha256=AoV_ZffWSBR6XRJZayAKg-KRRTkdP5hs64SzuGWiw1E,814 +django/contrib/auth/migrations/0009_alter_user_last_name_max_length.py,sha256=GaiVAOfxCKc5famxczGB-SEF91hmOzaFtg9cLaOE124,415 +django/contrib/auth/migrations/0010_alter_group_name_max_length.py,sha256=CWPtZJisCzqEMLbKNMG0pLHV9VtD09uQLxWgP_dLFM0,378 +django/contrib/auth/migrations/0011_update_proxy_permissions.py,sha256=haXd5wjcS2ER4bxxznI-z7p7H4rt7P0TCQD_d4J2VDY,2860 +django/contrib/auth/migrations/0012_alter_user_first_name_max_length.py,sha256=bO-8n4CQN2P_hJKlN6IoNu9p8iJ-GdQCUJuAmdK67LA,411 +django/contrib/auth/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/auth/mixins.py,sha256=rHq9HsX4W8lKtfXsazxM3chhTFLqd3eKI-OVKpbeLjQ,4652 +django/contrib/auth/models.py,sha256=7DKhZJdEgTkm1j38W_BSfMQ3qh1y-AhqmElQ8kHKhAY,16500 +django/contrib/auth/password_validation.py,sha256=bcI_IpJGik69i5evI7ywa9bEPFRSkPTLJZ8Yf1y4mIE,9358 +django/contrib/auth/signals.py,sha256=BFks70O0Y8s6p1fr8SCD4-yk2kjucv7HwTcdRUzVDFM,118 +django/contrib/auth/templates/auth/widgets/read_only_password_hash.html,sha256=hP5lekZa5ww1wQbWNiEHkT_KGnXoCKFBm5yxIlJm3d8,196 +django/contrib/auth/templates/registration/password_reset_subject.txt,sha256=-TZcy_r0vArBgdPK7feeUY6mr9EkYwy7esQ62_onbBk,132 +django/contrib/auth/tokens.py,sha256=ljqQWO0dAkd45-bBJ6W85oZZU9pEjzNh3VbZfeANwxQ,4328 +django/contrib/auth/urls.py,sha256=Uh8DrSqpJXDA5a17Br9fMmIbEcgLkxdN9FvCRg-vxyg,1185 +django/contrib/auth/validators.py,sha256=VO7MyackTaTiK8OjEm7YyLtsjKrteVjdzPbNZki0irU,722 +django/contrib/auth/views.py,sha256=gRTqia66ArAged73GjoahjszD2uj3F3HgJybYRWecL8,13789 +django/contrib/contenttypes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/contenttypes/admin.py,sha256=a0KrlT8k2aPIKn54fNwCDTaAVdVr1fLY1BDz_FrE3ts,5200 +django/contrib/contenttypes/apps.py,sha256=1Q1mWjPvfYU7EaO50JvsWuDg_3uK8DoCwpvdIdT7iKY,846 +django/contrib/contenttypes/checks.py,sha256=KKB-4FOfPO60TM-uxqK8m9sIXzB3CRx7Imr-jaauM_U,1268 +django/contrib/contenttypes/fields.py,sha256=B73aIVVxffjt21zM2VzVIcBY24XOcQbu1AiJ_R5Xirc,31487 +django/contrib/contenttypes/forms.py,sha256=T6fZZkJjPrD6R3h5Wos2a9aDM3mZJLerHSh6NXHJp4I,3956 +django/contrib/contenttypes/locale/af/LC_MESSAGES/django.mo,sha256=93nlniPFfVcxfBCs_PsLtMKrJ2BqpcofPRNYYTTlels,1070 +django/contrib/contenttypes/locale/af/LC_MESSAGES/django.po,sha256=SY04sW55-xpO_qBjv8pHoN7eqB2C5q_9CxQguMz7Q94,1244 +django/contrib/contenttypes/locale/ar/LC_MESSAGES/django.mo,sha256=2t3y_6wxi0khsYi6s9ZyJwjRB8bnRT1PKvazWOKhJcQ,1271 +django/contrib/contenttypes/locale/ar/LC_MESSAGES/django.po,sha256=t6M3XYQLotNMFCjzB8aWFXnlRI8fU744YZvAoFdScQY,1634 +django/contrib/contenttypes/locale/ar_DZ/LC_MESSAGES/django.mo,sha256=upFxoSvOvdmqCvC5irRV_8yYpFidanHfRk6i3tPrFAc,1233 +django/contrib/contenttypes/locale/ar_DZ/LC_MESSAGES/django.po,sha256=jUg-4BVi0arx5v-osaUDAfM6cQgaBh7mE8Mr8aVTp5A,1447 +django/contrib/contenttypes/locale/ast/LC_MESSAGES/django.mo,sha256=y88CPGGbwTVRmZYIipCNIWkn4OuzuxEk2QCYsBhc7RY,643 +django/contrib/contenttypes/locale/ast/LC_MESSAGES/django.po,sha256=H-qMo5ikva84ycnlmBT4XXEWhzMIw-r7J_zuqxo3wu4,1088 +django/contrib/contenttypes/locale/az/LC_MESSAGES/django.mo,sha256=VTQ2qQ7aoZYUVl2yht2DbYzj2acs71Szqz7iZyySAqI,1065 +django/contrib/contenttypes/locale/az/LC_MESSAGES/django.po,sha256=9NcmP1jMQPfjPraoXui6iqJn3z3f3uG1RYN7K5-_-dU,1359 +django/contrib/contenttypes/locale/be/LC_MESSAGES/django.mo,sha256=Kp1TpXX1v0IgGp9HZxleXJ6y5ZvMZ6AqJrSIVcDs7xA,1353 +django/contrib/contenttypes/locale/be/LC_MESSAGES/django.po,sha256=Oy5QXZBmBM_OYLT5OeXJQzTBCHXBp8NVMYuKmr_TUm0,1615 +django/contrib/contenttypes/locale/bg/LC_MESSAGES/django.mo,sha256=IFghXuYj0yxP5j-LfRsNJXlyS2b2dUNJXD01uhUqxLg,1225 +django/contrib/contenttypes/locale/bg/LC_MESSAGES/django.po,sha256=y-OpKdDHxHDYATSmi8DAUXuhpIwgujKZUe48G8So8AU,1613 +django/contrib/contenttypes/locale/bn/LC_MESSAGES/django.mo,sha256=2Z1GL6c1ukKQCMcls7R0_n4eNdH3YOXZSR8nCct7SLI,1201 +django/contrib/contenttypes/locale/bn/LC_MESSAGES/django.po,sha256=PLjnppx0FxfGBQMuWVjo0N4sW2QYc2DAEMK6ziGWUc8,1491 +django/contrib/contenttypes/locale/br/LC_MESSAGES/django.mo,sha256=kAlOemlwBvCdktgYoV-4NpC7XFDaIue_XN7GJYzDu88,1419 +django/contrib/contenttypes/locale/br/LC_MESSAGES/django.po,sha256=BQmHVQqOc6xJWJLeAo49rl_Ogfv-lFtx18mj82jT_to,1613 +django/contrib/contenttypes/locale/bs/LC_MESSAGES/django.mo,sha256=klj9n7AKBkTf7pIa9m9b-itsy4UlbYPnHiuvSLcFZXY,700 +django/contrib/contenttypes/locale/bs/LC_MESSAGES/django.po,sha256=pmJaMBLWbYtYFFXYBvPEvwXkTPdjQDv2WkFI5jNGmTI,1151 +django/contrib/contenttypes/locale/ca/LC_MESSAGES/django.mo,sha256=uYq1BXdw1AXjnLusUQfN7ox1ld6siiy41C8yKVTry7Q,1095 +django/contrib/contenttypes/locale/ca/LC_MESSAGES/django.po,sha256=-dsOzvzVzEPVvA9lYsIP-782BbtJxGRo-OHtS3fIjmU,1403 +django/contrib/contenttypes/locale/ckb/LC_MESSAGES/django.mo,sha256=_dJ-2B3tupoUHRS7HjC-EIlghIYLWebwsy4IvEXI13w,1213 +django/contrib/contenttypes/locale/ckb/LC_MESSAGES/django.po,sha256=SrQwgQTltnR7OExi6sP5JsnEOg6qDzd8dSPXjX92B-M,1419 +django/contrib/contenttypes/locale/cs/LC_MESSAGES/django.mo,sha256=QexBQDuGdMFhVBtA9XWUs2geFBROcxyzdU_IBUGQ7x4,1108 +django/contrib/contenttypes/locale/cs/LC_MESSAGES/django.po,sha256=8pdPwZmpGOeSZjILGLZEAzqvmmV69ogpkh0c3tukT2g,1410 +django/contrib/contenttypes/locale/cy/LC_MESSAGES/django.mo,sha256=2QyCWeXFyymoFu0Jz1iVFgOIdLtt4N1rCZATZAwiH-8,1159 +django/contrib/contenttypes/locale/cy/LC_MESSAGES/django.po,sha256=ZWDxQTHJcw1UYav1C3MX08wCFrSeJNNI2mKjzRVd6H0,1385 +django/contrib/contenttypes/locale/da/LC_MESSAGES/django.mo,sha256=EyancRrTWxM6KTpLq65gIQB0sO_PLtVr1ESN2v1pSNU,1038 +django/contrib/contenttypes/locale/da/LC_MESSAGES/django.po,sha256=J09u3IjLgv4g77Kea_WQAhevHb8DskGU-nVxyucYf_0,1349 +django/contrib/contenttypes/locale/de/LC_MESSAGES/django.mo,sha256=MGUZ4Gw8rSFjBO2OfFX9ooGGpJYwAapgNkc-GdBMXa0,1055 +django/contrib/contenttypes/locale/de/LC_MESSAGES/django.po,sha256=T5ucSqa6VyfUcoN6nFWBtjUkrSrz7wxr8t0NGTBrWow,1308 +django/contrib/contenttypes/locale/dsb/LC_MESSAGES/django.mo,sha256=QpdSZObmfb-DQZb3Oh6I1bFRnaPorXMznNZMyVIM7Hc,1132 +django/contrib/contenttypes/locale/dsb/LC_MESSAGES/django.po,sha256=_tNajamEnnf9FEjI-XBRraKjJVilwvpv2TBf9PAzPxw,1355 +django/contrib/contenttypes/locale/el/LC_MESSAGES/django.mo,sha256=1ySEbSEzhH1lDjHQK9Kv59PMA3ZPdqY8EJe6xEQejIM,1286 +django/contrib/contenttypes/locale/el/LC_MESSAGES/django.po,sha256=8rlMKE5SCLTtm1myjLFBtbEIFyuRmSrL9HS2PA7gneQ,1643 +django/contrib/contenttypes/locale/en/LC_MESSAGES/django.mo,sha256=U0OV81NfbuNL9ctF-gbGUG5al1StqN-daB-F-gFBFC8,356 +django/contrib/contenttypes/locale/en/LC_MESSAGES/django.po,sha256=BRgOISCCJb4TU0dNxG4eeQJFe-aIe7U3GKLPip03d_Q,1110 +django/contrib/contenttypes/locale/en_AU/LC_MESSAGES/django.mo,sha256=dTndJxA-F1IE_nMUOtf1sRr7Kq2s_8yjgKk6mkWkVu4,486 +django/contrib/contenttypes/locale/en_AU/LC_MESSAGES/django.po,sha256=wmxyIJtz628AbsxgkB-MjdImcIJWhcW7NV3tWbDpedg,1001 +django/contrib/contenttypes/locale/en_GB/LC_MESSAGES/django.mo,sha256=_uM-jg43W7Pz8RQhMcR_o15wRkDaYD8aRcl2_NFGoNs,1053 +django/contrib/contenttypes/locale/en_GB/LC_MESSAGES/django.po,sha256=SyzwSvqAgKF8BEhXYh4598GYP583OK2GUXH1lc4iDMk,1298 +django/contrib/contenttypes/locale/eo/LC_MESSAGES/django.mo,sha256=4EgHUHPb4TuK2DKf0dWOf7rNzJNsyT8CG39SQixI0oM,1072 +django/contrib/contenttypes/locale/eo/LC_MESSAGES/django.po,sha256=gbxNuagxW01xLd3DY0Lc5UNNSlw1nEiBExzcElrB61E,1350 +django/contrib/contenttypes/locale/es/LC_MESSAGES/django.mo,sha256=KzgypFDwIlVzr_h9Dq2X8dXu3XnsbdSaHwJKJWZ6qc8,1096 +django/contrib/contenttypes/locale/es/LC_MESSAGES/django.po,sha256=Dpn9dTvdy87bVf3It8pZFOdEEKnO91bDeYyY1YujkIA,1456 +django/contrib/contenttypes/locale/es_AR/LC_MESSAGES/django.mo,sha256=WkHABVDmtKidPyo6zaYGVGrgXpe6tZ69EkxaIBu6mtg,1084 +django/contrib/contenttypes/locale/es_AR/LC_MESSAGES/django.po,sha256=yVSu_fJSKwS4zTlRud9iDochIaY0zOPILF59biVfkeY,1337 +django/contrib/contenttypes/locale/es_CO/LC_MESSAGES/django.mo,sha256=aACo1rOrgs_BYK3AWzXEljCdAc4bC3BXpyXrwE4lzAs,1158 +django/contrib/contenttypes/locale/es_CO/LC_MESSAGES/django.po,sha256=vemhoL-sESessGmIlHoRvtWICqF2aO05WvcGesUZBRM,1338 +django/contrib/contenttypes/locale/es_MX/LC_MESSAGES/django.mo,sha256=vD9rSUAZC_rgkwiOOsrrra07Gnx7yEpNHI96tr8xD3U,840 +django/contrib/contenttypes/locale/es_MX/LC_MESSAGES/django.po,sha256=tLgjAi9Z1kZloJFVQuUdAvyiJy1J-5QHfoWmxbqQZCc,1237 +django/contrib/contenttypes/locale/es_VE/LC_MESSAGES/django.mo,sha256=TVGDydYVg_jGfnYghk_cUFjCCtpGchuoTB4Vf0XJPYk,1152 +django/contrib/contenttypes/locale/es_VE/LC_MESSAGES/django.po,sha256=vJW37vuKYb_KpXBPmoNSqtNstFgCDlKmw-8iOoSCenU,1342 +django/contrib/contenttypes/locale/et/LC_MESSAGES/django.mo,sha256=TE84lZl6EP54-pgmv275jiTOW0vIsnsGU97qmtxMEVg,1028 +django/contrib/contenttypes/locale/et/LC_MESSAGES/django.po,sha256=KO9fhmRCx25VeHNDGXVNhoFx3VFH-6PSLVXZJ6ohOSA,1368 +django/contrib/contenttypes/locale/eu/LC_MESSAGES/django.mo,sha256=K0f1cXEhfg_djPzgCL9wC0iHGWF_JGIhWGFL0Y970g0,1077 +django/contrib/contenttypes/locale/eu/LC_MESSAGES/django.po,sha256=sSuVV0o8MeWN6BxlaeKcjKA3h4H29fCo1kKEtkczEp4,1344 +django/contrib/contenttypes/locale/fa/LC_MESSAGES/django.mo,sha256=hW3A3_9b-NlLS4u6qDnPS1dmNdn1UJCt-nihXvnXywI,1130 +django/contrib/contenttypes/locale/fa/LC_MESSAGES/django.po,sha256=TPiYsGGN-j-VD--Rentx1p-IcrNJYoYxrxDO_5xeZHI,1471 +django/contrib/contenttypes/locale/fi/LC_MESSAGES/django.mo,sha256=dWar3g1rJAkUG1xRLlmGkH63Fy_h2YqzhMVv0Z25aWc,1036 +django/contrib/contenttypes/locale/fi/LC_MESSAGES/django.po,sha256=yALWMFU8-gFD2G0NdWqIDIenrAMUY4VCW1oi8TJXFAc,1325 +django/contrib/contenttypes/locale/fr/LC_MESSAGES/django.mo,sha256=CTOu_JOAQeC72VX5z9cg8Bn3HtZsdgbtjA7XKcy681o,1078 +django/contrib/contenttypes/locale/fr/LC_MESSAGES/django.po,sha256=6LArEWoBpdaJa7UPcyv4HJKD3YoKUxrwGQGd16bi9DM,1379 +django/contrib/contenttypes/locale/fy/LC_MESSAGES/django.mo,sha256=YQQy7wpjBORD9Isd-p0lLzYrUgAqv770_56-vXa0EOc,476 +django/contrib/contenttypes/locale/fy/LC_MESSAGES/django.po,sha256=SB07aEGG7n4oX_5rqHB6OnjpK_K0KwFM7YxaWYNpB_4,991 +django/contrib/contenttypes/locale/ga/LC_MESSAGES/django.mo,sha256=GYQYfYWbgwL3nQJR5d7XGjc5KeYYXsB0yRQJz7zxd_k,1097 +django/contrib/contenttypes/locale/ga/LC_MESSAGES/django.po,sha256=byvw9sQ9VLVjS7Au81LcNpxOzwA29_4Al9nB1ZyV2b4,1408 +django/contrib/contenttypes/locale/gd/LC_MESSAGES/django.mo,sha256=dQz7j45qlY3M1rL2fCVdPnuHMUdUcJ0K6cKgRD7Js2w,1154 +django/contrib/contenttypes/locale/gd/LC_MESSAGES/django.po,sha256=_hwx9XqeX5QYRFtDpEYkChswn8WMdYTQlbzL1LjREbY,1368 +django/contrib/contenttypes/locale/gl/LC_MESSAGES/django.mo,sha256=OS8R8sck0Q__XBw3M9brT4jOHmXYUHH71zU2a0mY0vQ,1080 +django/contrib/contenttypes/locale/gl/LC_MESSAGES/django.po,sha256=i-kmfgIuDtreavYL3mCc_BSRi-GmTklAsqE4AhP3wgk,1417 +django/contrib/contenttypes/locale/he/LC_MESSAGES/django.mo,sha256=oaxWykyc3N63WpxyHPI5CyhCTBqhM5-2Sasp_DNm1xc,1219 +django/contrib/contenttypes/locale/he/LC_MESSAGES/django.po,sha256=wCm08UMCiCa6y1-5E-7bEz-8Kd0oMRMwgzoEJjMwFyw,1486 +django/contrib/contenttypes/locale/hi/LC_MESSAGES/django.mo,sha256=KAZuQMKOvIPj3a7GrNJE3yhT70O2abCEF2GOsbwTE5A,1321 +django/contrib/contenttypes/locale/hi/LC_MESSAGES/django.po,sha256=PcsNgu2YmT0biklhwOF_nSvoGTvWVKw2IsBxIwSVAtI,1577 +django/contrib/contenttypes/locale/hr/LC_MESSAGES/django.mo,sha256=DbOUA8ks3phsEwQvethkwZ9-ymrd36aQ6mP7OnGdpjU,1167 +django/contrib/contenttypes/locale/hr/LC_MESSAGES/django.po,sha256=722KxvayO6YXByAmO4gfsfzyVbT-HqqrLYQsr02KDc8,1445 +django/contrib/contenttypes/locale/hsb/LC_MESSAGES/django.mo,sha256=tPtv_lIzCPIUjGkAYalnNIUxVUQFE3MShhVXTnfVx3Q,1106 +django/contrib/contenttypes/locale/hsb/LC_MESSAGES/django.po,sha256=rbI3G8ARG7DF7uEe82SYCfotBnKTRJJ641bGhjdptTQ,1329 +django/contrib/contenttypes/locale/hu/LC_MESSAGES/django.mo,sha256=2nsylOwBIDOnkUjE2GYU-JRvgs_zxent7q3_PuscdXk,1102 +django/contrib/contenttypes/locale/hu/LC_MESSAGES/django.po,sha256=Dzcf94ZSvJtyNW9EUKpmyNJ1uZbXPvc7dIxCccZrDYc,1427 +django/contrib/contenttypes/locale/hy/LC_MESSAGES/django.mo,sha256=hKOErB5dzj44ThQ1_nZHak2-aXZlwMoxYcDWmPb3Xo8,1290 +django/contrib/contenttypes/locale/hy/LC_MESSAGES/django.po,sha256=UeGzaghsEt9Lt5DsEzRb9KCbuphWUQwLayt4AN194ao,1421 +django/contrib/contenttypes/locale/ia/LC_MESSAGES/django.mo,sha256=9B0XhxH0v3FvkEvS5MOHHqVbgV6KQITPrjzx1Sn76GA,1105 +django/contrib/contenttypes/locale/ia/LC_MESSAGES/django.po,sha256=NX8jpTaIhtVbVlwEsOl5aufZ80ljHZZwqtsVVozQb4M,1318 +django/contrib/contenttypes/locale/id/LC_MESSAGES/django.mo,sha256=4-6RBAvrtA1PY3LNxMrgwzBLZE0ZKwWaXa7SmtmAIyk,1031 +django/contrib/contenttypes/locale/id/LC_MESSAGES/django.po,sha256=xdxEOgfta1kaXyQAngmmbL8wDQzJU6boC9HdbmoM1iI,1424 +django/contrib/contenttypes/locale/io/LC_MESSAGES/django.mo,sha256=3SSRXx4tYiMUc00LZ9kGHuvTgaWpsICEf5G208CEqgg,1051 +django/contrib/contenttypes/locale/io/LC_MESSAGES/django.po,sha256=1ku9WPcenn47DOF05HL2eRqghZeRYfklo2huYUrkeJ0,1266 +django/contrib/contenttypes/locale/is/LC_MESSAGES/django.mo,sha256=ZYWbT4qeaco8h_J9SGF2Bs7Rdu3auZ969xZ0RQ_03go,1049 +django/contrib/contenttypes/locale/is/LC_MESSAGES/django.po,sha256=iNdghSbBVPZmfrHu52hRG8vHMgGUfOjLqie09fYcuso,1360 +django/contrib/contenttypes/locale/it/LC_MESSAGES/django.mo,sha256=GSP0BJc3bGLoNS0tnhiz_5dtSh5NXCrBiZbnwEhWbpk,1075 +django/contrib/contenttypes/locale/it/LC_MESSAGES/django.po,sha256=njEgvhDwWOc-CsGBDz1_mtEsXx2aTU6cP3jZzcLkkYk,1457 +django/contrib/contenttypes/locale/ja/LC_MESSAGES/django.mo,sha256=tVH6RvZ5tXz56lEM3aoJtFp5PKsSR-XXpi8ZNCHjiFw,1211 +django/contrib/contenttypes/locale/ja/LC_MESSAGES/django.po,sha256=5_-Uo7Ia3X9gAWm2f72ezQnNr_pQzf6Ax4AUutULuZU,1534 +django/contrib/contenttypes/locale/ka/LC_MESSAGES/django.mo,sha256=1_yGL68sK0QG_mhwFAVdksiDlB57_1W5QkL7NGGE5L0,1429 +django/contrib/contenttypes/locale/ka/LC_MESSAGES/django.po,sha256=6iUBbKjXsIgrq7Dj_xhxzoxItSSSKwQjIZsDayefGr8,1654 +django/contrib/contenttypes/locale/kk/LC_MESSAGES/django.mo,sha256=SNY0vydwLyR2ExofAHjmg1A2ykoLI7vU5Ryq-QFu5Gs,627 +django/contrib/contenttypes/locale/kk/LC_MESSAGES/django.po,sha256=PU-NAl6xUEeGV0jvJx9siVBTZIzHywL7oKc4DgUjNkc,1130 +django/contrib/contenttypes/locale/km/LC_MESSAGES/django.mo,sha256=BXifukxf48Lr0t0V3Y0GJUMhD1KiHN1wwbueoK0MW1A,678 +django/contrib/contenttypes/locale/km/LC_MESSAGES/django.po,sha256=fTPlBbnaNbLZxjzJutGvqe33t6dWsEKiHQYaw27m7KQ,1123 +django/contrib/contenttypes/locale/kn/LC_MESSAGES/django.mo,sha256=a4sDGaiyiWn-1jFozYI4vdAvuHXrs8gbZErP_SAUk9Y,714 +django/contrib/contenttypes/locale/kn/LC_MESSAGES/django.po,sha256=A6Vss8JruQcPUKQvY-zaubVZDTLEPwHsnd_rXcyzQUs,1168 +django/contrib/contenttypes/locale/ko/LC_MESSAGES/django.mo,sha256=myRfFxf2oKcbpmCboongTsL72RTM95nEmAC938M-ckE,1089 +django/contrib/contenttypes/locale/ko/LC_MESSAGES/django.po,sha256=uui_LhgGTrW0uo4p-oKr4JUzhjvkLbFCqRVLNMrptzY,1383 +django/contrib/contenttypes/locale/ky/LC_MESSAGES/django.mo,sha256=ULoIe36zGKPZZs113CenA6J9HviYcBOKagXrPGxyBUI,1182 +django/contrib/contenttypes/locale/ky/LC_MESSAGES/django.po,sha256=FnW5uO8OrTYqbvoRuZ6gnCD6CHnuLjN00s2Jo1HX1NE,1465 +django/contrib/contenttypes/locale/lb/LC_MESSAGES/django.mo,sha256=xokesKl7h7k9dXFKIJwGETgwx1Ytq6mk2erBSxkgY-o,474 +django/contrib/contenttypes/locale/lb/LC_MESSAGES/django.po,sha256=dwVKpCRYmXTD9h69v5ivkZe-yFtvdZNZ3VfuyIl4olY,989 +django/contrib/contenttypes/locale/lt/LC_MESSAGES/django.mo,sha256=HucsRl-eqfxw6ESTuXvl7IGjPGYSI9dxM5lMly_P1sc,1215 +django/contrib/contenttypes/locale/lt/LC_MESSAGES/django.po,sha256=odzYqHprxKFIrR8TzdxA4WeeMK0W0Nvn2gAVuzAsEqI,1488 +django/contrib/contenttypes/locale/lv/LC_MESSAGES/django.mo,sha256=nWfy7jv2VSsKYT6yhk_xqxjk1TlppJfsQcurC40CeTs,1065 +django/contrib/contenttypes/locale/lv/LC_MESSAGES/django.po,sha256=pHlbzgRpIJumDMp2rh1EKrxFBg_DRcvLLgkQ3mi_L0s,1356 +django/contrib/contenttypes/locale/mk/LC_MESSAGES/django.mo,sha256=KTFZWm0F4S6lmi1FX76YKOyJqIZN5cTsiTBI_D4ADHs,1258 +django/contrib/contenttypes/locale/mk/LC_MESSAGES/django.po,sha256=mQZosS90S-Bil6-EoGjs9BDWYlvOF6mtUDZ8h9NxEdE,1534 +django/contrib/contenttypes/locale/ml/LC_MESSAGES/django.mo,sha256=rtmLWfuxJED-1KuqkUT8F5CU1KGJP0Of718n2Gl_gI0,1378 +django/contrib/contenttypes/locale/ml/LC_MESSAGES/django.po,sha256=Z-kL9X9CD7rYfa4Uoykye2UgCNQlgyql0HTv1eUXAf4,1634 +django/contrib/contenttypes/locale/mn/LC_MESSAGES/django.mo,sha256=J6kKYjUOsQxptNXDcCaY4d3dHJio4HRibRk3qfwO6Xc,1225 +django/contrib/contenttypes/locale/mn/LC_MESSAGES/django.po,sha256=x8aRJH2WQvMBBWlQt3T3vpV4yHeZXLmRTT1U0at4ZIk,1525 +django/contrib/contenttypes/locale/mr/LC_MESSAGES/django.mo,sha256=2Z5jaGJzpiJTCnhCk8ulCDeAdj-WwR99scdHFPRoHoA,468 +django/contrib/contenttypes/locale/mr/LC_MESSAGES/django.po,sha256=FgZKD9E-By0NztUnBM4llpR59K0MJSIMZIrJYGKDqpc,983 +django/contrib/contenttypes/locale/ms/LC_MESSAGES/django.mo,sha256=EIwbOZ0QahW9AFFWRmRdKGKBtYYY_eTcfU4eqDVSVxw,1035 +django/contrib/contenttypes/locale/ms/LC_MESSAGES/django.po,sha256=t7nKsOMxycn_CsXw2nIfU-owJRge3FAixgbTsDhffvo,1225 +django/contrib/contenttypes/locale/my/LC_MESSAGES/django.mo,sha256=YYa2PFe9iJygqL-LZclfpgR6rBmIvx61JRpBkKS6Hrs,1554 +django/contrib/contenttypes/locale/my/LC_MESSAGES/django.po,sha256=6F3nXd9mBc-msMchkC8OwAHME1x1O90xrsZp7xmynpU,1732 +django/contrib/contenttypes/locale/nb/LC_MESSAGES/django.mo,sha256=EHU9Lm49U7WilR5u-Lq0Fg8ChR_OzOce4UyPlkZ6Zs4,1031 +django/contrib/contenttypes/locale/nb/LC_MESSAGES/django.po,sha256=lbktPYsJudrhe4vxnauzpzN9eNwyoVs0ZmZSdkwjkOk,1403 +django/contrib/contenttypes/locale/ne/LC_MESSAGES/django.mo,sha256=-zZAn5cex4PkScoZVqS74PUMThJJuovZSk3WUKZ8hnw,1344 +django/contrib/contenttypes/locale/ne/LC_MESSAGES/django.po,sha256=1ZCUkulQ9Gxb50yMKFKWaTJli2SinBeNj0KpXkKpsNE,1519 +django/contrib/contenttypes/locale/nl/LC_MESSAGES/django.mo,sha256=aXDHgg891TyTiMWNcbNaahfZQ2hqtl5yTkx5gNRocMU,1040 +django/contrib/contenttypes/locale/nl/LC_MESSAGES/django.po,sha256=zDJ_vyQxhP0mP06U-e4p6Uj6v1g863s8oaxc0JIAMjg,1396 +django/contrib/contenttypes/locale/nn/LC_MESSAGES/django.mo,sha256=a_X8e2lMieWwUtENJueBr8wMvkw6at0QSaWXd5AM6yQ,1040 +django/contrib/contenttypes/locale/nn/LC_MESSAGES/django.po,sha256=xFSirHUAKv78fWUpik6xv-6WQSEoUgN5jjPbTOy58C4,1317 +django/contrib/contenttypes/locale/os/LC_MESSAGES/django.mo,sha256=QV533Wu-UpjV3XiCe83jlz7XGuwgRviV0ggoeMaIOIY,1116 +django/contrib/contenttypes/locale/os/LC_MESSAGES/django.po,sha256=UZahnxo8z6oWJfEz4JNHGng0EAifXYtJupB6lx0JB60,1334 +django/contrib/contenttypes/locale/pa/LC_MESSAGES/django.mo,sha256=qacd7eywof8rvJpstNfEmbHgvDiQ9gmkcyG7gfato8s,697 +django/contrib/contenttypes/locale/pa/LC_MESSAGES/django.po,sha256=Kq2NTzdbgq8Q9jLLgV-ZJaSRj43D1dDHcRIgNnJXu-s,1145 +django/contrib/contenttypes/locale/pl/LC_MESSAGES/django.mo,sha256=J5sC36QwKLvrMB4adsojhuw2kYuEckHz6eoTrZwYcnI,1208 +django/contrib/contenttypes/locale/pl/LC_MESSAGES/django.po,sha256=gxP59PjlIHKSiYZcbgIY4PUZSoKYx4YKCpm4W4Gj22g,1577 +django/contrib/contenttypes/locale/pt/LC_MESSAGES/django.mo,sha256=MjyyKlA75YtEG9m6hm0GxKhU-cF3m1PA_j63BuIPPlE,1125 +django/contrib/contenttypes/locale/pt/LC_MESSAGES/django.po,sha256=X2Rec6LXIqPa9AVqF4J2mzYrwfls1BdUfN8XOe0zkdQ,1379 +django/contrib/contenttypes/locale/pt_BR/LC_MESSAGES/django.mo,sha256=qjl-3fBqNcAuoviGejjILC7Z8XmrRd7gHwOgwu1x1zw,1117 +django/contrib/contenttypes/locale/pt_BR/LC_MESSAGES/django.po,sha256=Xp0iBhseS8v13zjDcNQv4BDaroMtDJVs4-BzNc0UOpU,1494 +django/contrib/contenttypes/locale/ro/LC_MESSAGES/django.mo,sha256=sCthDD10v7GY2cui9Jj9HK8cofVEg2WERCm6aktOM-4,1142 +django/contrib/contenttypes/locale/ro/LC_MESSAGES/django.po,sha256=n-BPEfua0Gd6FN0rsP7qAlTGbQEZ14NnDMA8jI2844Y,1407 +django/contrib/contenttypes/locale/ru/LC_MESSAGES/django.mo,sha256=OSf206SFmVLULHmwVhTaRhWTQtyDKsxe03gIzuvAUnY,1345 +django/contrib/contenttypes/locale/ru/LC_MESSAGES/django.po,sha256=xHyJYD66r8We3iN5Hqo69syWkjhz4zM7X9BWPIiI6mU,1718 +django/contrib/contenttypes/locale/sk/LC_MESSAGES/django.mo,sha256=osKXPEE0x-oahNDjgr4aea3dzmLddTT_RLQ8TnbsIOg,1115 +django/contrib/contenttypes/locale/sk/LC_MESSAGES/django.po,sha256=nZBxZH3r93fbtth15iP-Q2tNLrZrYqc8V0B9c4XMRNI,1433 +django/contrib/contenttypes/locale/sl/LC_MESSAGES/django.mo,sha256=sMML-ubI_9YdKptzeri1du8FOdKcEzJbe4Tt0J4ePFI,1147 +django/contrib/contenttypes/locale/sl/LC_MESSAGES/django.po,sha256=0zxiyzRWWDNVpNNLlcwl-OLh5sLukma1vm-kYrGHYrE,1392 +django/contrib/contenttypes/locale/sq/LC_MESSAGES/django.mo,sha256=jYDQH3OpY4Vx9hp6ISFMI88uxBa2GDQK0BkLGm8Qulk,1066 +django/contrib/contenttypes/locale/sq/LC_MESSAGES/django.po,sha256=JIvguXVOFpQ3MRqRXHpxlg8_YhEzCsZBBMdpekYTxlk,1322 +django/contrib/contenttypes/locale/sr/LC_MESSAGES/django.mo,sha256=GUXj97VN15HdY7XMy5jmMLEu13juD3To5NsztcoyPGs,1204 +django/contrib/contenttypes/locale/sr/LC_MESSAGES/django.po,sha256=T1w_EeB6yT-PXr7mrwzqu270linf_KY3_ZCgl4wfLAQ,1535 +django/contrib/contenttypes/locale/sr_Latn/LC_MESSAGES/django.mo,sha256=m2plistrI8O-ztAs5HmDYXG8N_wChaDfXFev0GYWVys,1102 +django/contrib/contenttypes/locale/sr_Latn/LC_MESSAGES/django.po,sha256=lJrhLPDbJAcXgBPco-_lfUXqs31imj_vGwE5p1EXZjk,1390 +django/contrib/contenttypes/locale/sv/LC_MESSAGES/django.mo,sha256=J5ha8X6jnQ4yuafk-JCqPM5eIGNwKpDOpTwIVCrnGNE,1055 +django/contrib/contenttypes/locale/sv/LC_MESSAGES/django.po,sha256=HeKnQJaRNflAbKxTiC_2EFAg2Sx-e3nDXrReJyVoNTQ,1400 +django/contrib/contenttypes/locale/sw/LC_MESSAGES/django.mo,sha256=XLPle0JYPPkmm5xpJRmWztMTF1_3a2ZubWE4ur2sav8,563 +django/contrib/contenttypes/locale/sw/LC_MESSAGES/django.po,sha256=jRc8Eh6VuWgqc4kM-rxjbVE3yV9uip6mOJLdD6yxGLM,1009 +django/contrib/contenttypes/locale/ta/LC_MESSAGES/django.mo,sha256=L3eF4z9QSmIPqzEWrNk8-2uLteQUMsuxiD9VZyRuSfo,678 +django/contrib/contenttypes/locale/ta/LC_MESSAGES/django.po,sha256=iDb9lRU_-YPmO5tEQeXEZeGeFe-wVZy4k444sp_vTgw,1123 +django/contrib/contenttypes/locale/te/LC_MESSAGES/django.mo,sha256=S_UF_mZbYfScD6Z36aB-kwtTflTeX3Wt4k7z_pEcOV8,690 +django/contrib/contenttypes/locale/te/LC_MESSAGES/django.po,sha256=aAGMMoJPg_pF9_rCNZmda5A_TvDCvQfYEL64Xdoa4jo,1135 +django/contrib/contenttypes/locale/tg/LC_MESSAGES/django.mo,sha256=dkLic6fD2EMzrB7m7MQazaGLoJ_pBw55O4nYZc5UYEs,864 +django/contrib/contenttypes/locale/tg/LC_MESSAGES/django.po,sha256=1nv1cVJewfr44gbQh1Szzy3DT4Y9Dy7rUgAZ81otJQs,1232 +django/contrib/contenttypes/locale/th/LC_MESSAGES/django.mo,sha256=qilt-uZMvt0uw-zFz7-eCmkGEx3XYz7NNo9Xbq3s7uI,1186 +django/contrib/contenttypes/locale/th/LC_MESSAGES/django.po,sha256=42F34fNEn_3yQKBBJnCLttNeyktuLVpilhMyepOd6dg,1444 +django/contrib/contenttypes/locale/tk/LC_MESSAGES/django.mo,sha256=0fuA3E487-pceoGpX9vMCwSnCItN_pbLUIUzzcrAGOE,1068 +django/contrib/contenttypes/locale/tk/LC_MESSAGES/django.po,sha256=pS8wX9dzxys3q8Vvz3PyoVJYqplXhNuAqfq7Dsb07fw,1283 +django/contrib/contenttypes/locale/tr/LC_MESSAGES/django.mo,sha256=gKg2FCxs2fHpDB1U6gh9xrP7mOpYG65pB4CNmdPYiDg,1057 +django/contrib/contenttypes/locale/tr/LC_MESSAGES/django.po,sha256=gmI3RDhq39IlDuvNohT_FTPY5QG8JD0gFxG5CTsvVZs,1345 +django/contrib/contenttypes/locale/tt/LC_MESSAGES/django.mo,sha256=_LQ1N04FgosdDLUYXJOEqpCB2Mg92q95cBRgYPi1MyY,659 +django/contrib/contenttypes/locale/tt/LC_MESSAGES/django.po,sha256=L7wMMpxGnpQiKd_mjv2bJpE2iqCJ8XwiXK0IN4EHSbM,1110 +django/contrib/contenttypes/locale/udm/LC_MESSAGES/django.mo,sha256=CNmoKj9Uc0qEInnV5t0Nt4ZnKSZCRdIG5fyfSsqwky4,462 +django/contrib/contenttypes/locale/udm/LC_MESSAGES/django.po,sha256=YVyej0nAhhEf7knk4vCeRQhmSQeGZLhMPPXyIyWObnM,977 +django/contrib/contenttypes/locale/ug/LC_MESSAGES/django.mo,sha256=hddqwGR9yrDZye5FZSatvlBBGerLsxS0x1HRodFmwkk,1182 +django/contrib/contenttypes/locale/ug/LC_MESSAGES/django.po,sha256=DoAswgu8-Ukl5e5TLhMcMQRuWEalnmokpKZsKSN9RYk,1397 +django/contrib/contenttypes/locale/uk/LC_MESSAGES/django.mo,sha256=GgAuuLexfhYl1fRKPfZI5uMTkt2H42Ogil6MQHcejkU,1404 +django/contrib/contenttypes/locale/uk/LC_MESSAGES/django.po,sha256=1HzO_Wmxqk0Kd5gtACKZODiH8ZEpOf5Eh8Mkrg3IMf8,1779 +django/contrib/contenttypes/locale/ur/LC_MESSAGES/django.mo,sha256=OJs_EmDBps-9a_KjFJnrS8IqtJfd25LaSWeyG8u8UfI,671 +django/contrib/contenttypes/locale/ur/LC_MESSAGES/django.po,sha256=f0FnsaAM_qrBuCXzLnkBrW5uFfVc6pUh7S-qp4918Ng,1122 +django/contrib/contenttypes/locale/vi/LC_MESSAGES/django.mo,sha256=kGYgEI1gHkyU4y_73mBJN1hlKC2JujVXMg6iCdWncDg,1155 +django/contrib/contenttypes/locale/vi/LC_MESSAGES/django.po,sha256=RIDUgsElfRF8bvBdUKtshizuMnupdMGAM896s7qZKD4,1439 +django/contrib/contenttypes/locale/zh_Hans/LC_MESSAGES/django.mo,sha256=RviK0bqLZzPrZ46xUpc0f8IKkw3JLtsrt0gNA74Ypj0,1015 +django/contrib/contenttypes/locale/zh_Hans/LC_MESSAGES/django.po,sha256=vSKJDEQ_ANTj3-W8BFJd9u_QGdTMF12iS15rVgeujOs,1380 +django/contrib/contenttypes/locale/zh_Hant/LC_MESSAGES/django.mo,sha256=NMumOJ9dPX-7YjQH5Obm4Yj0-lnGXJmCMN5DGbsLQG4,1046 +django/contrib/contenttypes/locale/zh_Hant/LC_MESSAGES/django.po,sha256=7WIqYRpcs986MjUsegqIido5k6HG8d3FVvkrOQCRVCI,1338 +django/contrib/contenttypes/management/__init__.py,sha256=ZVHVJAYi_jCIXxWUZSkxq0IDECe6bvbFsWayrqbutfc,4937 +django/contrib/contenttypes/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/contenttypes/management/commands/remove_stale_contenttypes.py,sha256=09TVqCr74KyA-BhkIJvTHIeSd389XWmCDCDK9Wp5OxA,4592 +django/contrib/contenttypes/migrations/0001_initial.py,sha256=Ne2EiaFH4LQqFcIbXU8OiUDeb3P7Mm6dbeqRtNC5U8w,1434 +django/contrib/contenttypes/migrations/0002_remove_content_type_name.py,sha256=fTZJQHV1Dw7TwPaNDLFUjrpZzFk_UvaR9sw3oEMIN2Y,1199 +django/contrib/contenttypes/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/contenttypes/models.py,sha256=jALWOpJWnG_iAcjh0qMfPSOewgAls3b9KLWemaBGXpM,6939 +django/contrib/contenttypes/prefetch.py,sha256=LPfGep3aK_Ggl-WyZdDsUssNRulToOM7MuxOzwHtezQ,1363 +django/contrib/contenttypes/views.py,sha256=HBoIbNpgHTQN5pH8mul77UMEMZHbbkEH_Qdln-XFgd0,3549 +django/contrib/flatpages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/flatpages/admin.py,sha256=ynemOSDgvKoCfRFLXZrPwj27U0mPUXmxdrue7SOZeqQ,701 +django/contrib/flatpages/apps.py,sha256=_OlaDxWbMrUmFNCS4u-RnBsg67rCWs8Qzh_c58wvtXA,252 +django/contrib/flatpages/forms.py,sha256=r9yUG_-zAnI7Ubr836aiWgScYpKxHhJbNLhHRkZQOzY,2492 +django/contrib/flatpages/locale/af/LC_MESSAGES/django.mo,sha256=8NN8mhQOWgkFiG9Sk0y8cOifFm1uySJFTB95u2D2sq0,2279 +django/contrib/flatpages/locale/af/LC_MESSAGES/django.po,sha256=LJenaVmnKxgD5IRlklrI72wceqEFdwdIPBzZUZzi7Bk,2456 +django/contrib/flatpages/locale/ar/LC_MESSAGES/django.mo,sha256=dBHaqsaKH9QOIZ0h2lIDph8l9Bv2UAcD-Hr9TAxj8Ac,2636 +django/contrib/flatpages/locale/ar/LC_MESSAGES/django.po,sha256=-0ZdfA-sDU8fOucgT2Ow1iM3QnRMuQeslMOSwYhAH9M,2958 +django/contrib/flatpages/locale/ar_DZ/LC_MESSAGES/django.mo,sha256=jp6sS05alESJ4-SbEIf574UPVcbllAd_J-FW802lGyk,2637 +django/contrib/flatpages/locale/ar_DZ/LC_MESSAGES/django.po,sha256=yezpjWcROwloS08TEMo9oPXDKS1mfFE9NYI66FUuLaA,2799 +django/contrib/flatpages/locale/ast/LC_MESSAGES/django.mo,sha256=4SEsEE2hIZJwQUNs8jDgN6qVynnUYJUIE4w-usHKA6M,924 +django/contrib/flatpages/locale/ast/LC_MESSAGES/django.po,sha256=5UlyS59bVo1lccM6ZgdYSgHe9NLt_WeOdXX-swLKubU,1746 +django/contrib/flatpages/locale/az/LC_MESSAGES/django.mo,sha256=6ID6KejChxQzsUT4wevUAjd9u7Ly21mfJ22dgbitNN4,2373 +django/contrib/flatpages/locale/az/LC_MESSAGES/django.po,sha256=v7tkbuUUqkbUzXoOOWxS75TpvuMESqoZAEXDXisfbiA,2679 +django/contrib/flatpages/locale/be/LC_MESSAGES/django.mo,sha256=mOQlbfwwIZiwWCrFStwag2irCwsGYsXIn6wZDsPRvyA,2978 +django/contrib/flatpages/locale/be/LC_MESSAGES/django.po,sha256=wlIfhun5Jd6gxbkmmYPSIy_tzPVmSu4CjMwPzBNnvpo,3161 +django/contrib/flatpages/locale/bg/LC_MESSAGES/django.mo,sha256=9Un5mKtsAuNeYWFQKFkIyCpQquE6qVD3zIrFoq8sCDI,2802 +django/contrib/flatpages/locale/bg/LC_MESSAGES/django.po,sha256=Vr6d-9XjgK4_eXdWY3FEpdTlCEGgbCv93bLGyMTE9hs,3104 +django/contrib/flatpages/locale/bn/LC_MESSAGES/django.mo,sha256=2oK2Rm0UtAI7QFRwpUR5aE3-fOltE6kTilsTbah737Y,2988 +django/contrib/flatpages/locale/bn/LC_MESSAGES/django.po,sha256=QrbX69iqXOD6oByLcgPkD1QzAkfthpfTjezIFQ-6kVg,3172 +django/contrib/flatpages/locale/br/LC_MESSAGES/django.mo,sha256=SKbykdilX_NcpkVi_lHF8LouB2G49ZAzdF09xw49ERc,2433 +django/contrib/flatpages/locale/br/LC_MESSAGES/django.po,sha256=O_mwrHIiEwV4oB1gZ7Yua4nVKRgyIf3j5UtedZWAtwk,2783 +django/contrib/flatpages/locale/bs/LC_MESSAGES/django.mo,sha256=bd7ID7OsEhp57JRw_TXoTwsVQNkFYiR_sxSkgi4WvZU,1782 +django/contrib/flatpages/locale/bs/LC_MESSAGES/django.po,sha256=IyFvI5mL_qesEjf6NO1nNQbRHhCAZQm0UhIpmGjrSwQ,2233 +django/contrib/flatpages/locale/ca/LC_MESSAGES/django.mo,sha256=GcMVbg4i5zKCd2Su7oN30WVJN7Q9K7FsFifgTB8jDPI,2237 +django/contrib/flatpages/locale/ca/LC_MESSAGES/django.po,sha256=-aJHSbWPVyNha_uF6R35Q6yn4-Hse3jTInr9jtaxKOI,2631 +django/contrib/flatpages/locale/ckb/LC_MESSAGES/django.mo,sha256=ds26zJRsUHDNdhoUJ8nsLtBdKDhN29Kb51wNiB8Llgo,2716 +django/contrib/flatpages/locale/ckb/LC_MESSAGES/django.po,sha256=jqqMYjrplyX8jtyBLd1ObMEwoFmaETmNXrO3tg2S0BY,2918 +django/contrib/flatpages/locale/cs/LC_MESSAGES/django.mo,sha256=8nwep22P86bMCbW7sj4n0BMGl_XaJIJV0fjnVp-_dqY,2340 +django/contrib/flatpages/locale/cs/LC_MESSAGES/django.po,sha256=1agUeRthwpam1UvZY4vRnZtLLbiop75IEXb6ul_e3mg,2611 +django/contrib/flatpages/locale/cy/LC_MESSAGES/django.mo,sha256=zr_2vsDZsrby3U8AmvlJMU3q1U_4IrrTmz6oS29OWtQ,2163 +django/contrib/flatpages/locale/cy/LC_MESSAGES/django.po,sha256=E_NC_wtuhWKYKB3YvYGB9ccJgKI3AfIZlB2HpXSyOsk,2370 +django/contrib/flatpages/locale/da/LC_MESSAGES/django.mo,sha256=nALoI50EvFPa4f3HTuaHUHATF1zHMjo4v5zcHj4n6sA,2277 +django/contrib/flatpages/locale/da/LC_MESSAGES/django.po,sha256=j4dpnreB7LWdZO7Drj7E9zBwFx_Leuj7ZLyEPi-ccAQ,2583 +django/contrib/flatpages/locale/de/LC_MESSAGES/django.mo,sha256=I4CHFzjYM_Wd-vuIYOMf8E58ntOgkLmgOAg35Chdz3s,2373 +django/contrib/flatpages/locale/de/LC_MESSAGES/django.po,sha256=P6tPVPumP9JwBIv-XXi1QQYJyj1PY3OWoM4yOAmgTRE,2592 +django/contrib/flatpages/locale/dsb/LC_MESSAGES/django.mo,sha256=oTILSe5teHa9XTYWoamstpyPu02yb_xo8S0AtkP7WP8,2391 +django/contrib/flatpages/locale/dsb/LC_MESSAGES/django.po,sha256=1xD2aH5alerranvee6QLZqgxDVXxHThXCHR4kOJAV48,2576 +django/contrib/flatpages/locale/el/LC_MESSAGES/django.mo,sha256=LQ8qIGwzoKwewtLz_1NhnhEeR4dPx2rrQ_hAN4BF6Og,2864 +django/contrib/flatpages/locale/el/LC_MESSAGES/django.po,sha256=gbLO52fcZK7LoG5Rget2Aq5PTFoz467ackXpSsR81kY,3221 +django/contrib/flatpages/locale/en/LC_MESSAGES/django.mo,sha256=U0OV81NfbuNL9ctF-gbGUG5al1StqN-daB-F-gFBFC8,356 +django/contrib/flatpages/locale/en/LC_MESSAGES/django.po,sha256=0bNWKiu-1MkHFJ_UWrCLhp9ENr-pHzBz1lkhBkkrhJM,2169 +django/contrib/flatpages/locale/en_AU/LC_MESSAGES/django.mo,sha256=dTt7KtwiEyMEKYVzkPSqs6VS0CiUfK7ISz2c6rV2erA,2210 +django/contrib/flatpages/locale/en_AU/LC_MESSAGES/django.po,sha256=_V4RTf0JtmyU7DRQv7jIwtPJs05KA2THPid5nKQ0ego,2418 +django/contrib/flatpages/locale/en_GB/LC_MESSAGES/django.mo,sha256=7zyXYOsqFkUGxclW-VPPxrQTZKDuiYQ7MQJy4m8FClo,1989 +django/contrib/flatpages/locale/en_GB/LC_MESSAGES/django.po,sha256=oHrBd6lVnO7-SdnO-Taa7iIyiqp_q2mQZjkuuU3Qa_s,2232 +django/contrib/flatpages/locale/eo/LC_MESSAGES/django.mo,sha256=W8TkkQkV58oOvFdKCPAyoQNyCxSmfErwik1U8a_W5nE,2333 +django/contrib/flatpages/locale/eo/LC_MESSAGES/django.po,sha256=e54WOtIcIQLjB4bJGol51z6d6dwLBiiJN2k-nrTQlaI,2750 +django/contrib/flatpages/locale/es/LC_MESSAGES/django.mo,sha256=9Q7Qf1eSPvAfPTZSGWq7QMWrROY-CnpUkeRpiH8rpJw,2258 +django/contrib/flatpages/locale/es/LC_MESSAGES/django.po,sha256=3vGZ3uVCyWnIkDSUt6DMMOqyphv3EQteTPLx7e9J_sU,2663 +django/contrib/flatpages/locale/es_AR/LC_MESSAGES/django.mo,sha256=bUnFDa5vpxl27kn2ojTbNaCmwRkBCH-z9zKXAvXe3Z0,2275 +django/contrib/flatpages/locale/es_AR/LC_MESSAGES/django.po,sha256=vEg3wjL_7Ee-PK4FZTaGRCXFscthkoH9szJ7H01K8w8,2487 +django/contrib/flatpages/locale/es_CO/LC_MESSAGES/django.mo,sha256=jt8wzeYky5AEnoNuAv8W4nGgd45XsMbpEdRuLnptr3U,2140 +django/contrib/flatpages/locale/es_CO/LC_MESSAGES/django.po,sha256=xrbAayPoxT7yksXOGPb-0Nc-4g14UmWANaKTD4ItAFA,2366 +django/contrib/flatpages/locale/es_MX/LC_MESSAGES/django.mo,sha256=Y5IOKRzooJHIhJzD9q4PKOe39Z4Rrdz8dBKuvmGkqWU,2062 +django/contrib/flatpages/locale/es_MX/LC_MESSAGES/django.po,sha256=Y-EXhw-jISttA9FGMz7gY_kB-hQ3wEyKEaOc2gu2hKQ,2246 +django/contrib/flatpages/locale/es_VE/LC_MESSAGES/django.mo,sha256=EI6WskepXUmbwCPBNFKqLGNcWFVZIbvXayOHxOCLZKo,2187 +django/contrib/flatpages/locale/es_VE/LC_MESSAGES/django.po,sha256=ipG6a0A2d0Pyum8GcknA-aNExVLjSyuUqbgHM9VdRQo,2393 +django/contrib/flatpages/locale/et/LC_MESSAGES/django.mo,sha256=zriqETEWD-DDPiNzXgAzgEhjvPAaTo7KBosyvBebyc0,2233 +django/contrib/flatpages/locale/et/LC_MESSAGES/django.po,sha256=tMuITUlzy6LKJh3X3CxssFpTQogg8OaGHlKExzjwyOI,2525 +django/contrib/flatpages/locale/eu/LC_MESSAGES/django.mo,sha256=FoKazUkuPpDgsEEI6Gm-xnZYVHtxILiy6Yzvnu8y-L0,2244 +django/contrib/flatpages/locale/eu/LC_MESSAGES/django.po,sha256=POPFB5Jd8sE9Z_ivYSdnet14u-aaXneTUNDMuOrJy00,2478 +django/contrib/flatpages/locale/fa/LC_MESSAGES/django.mo,sha256=2rA7-OR8lQbl_ZhlAC4cmHEmQ9mwxnA8q5M-gx3NmVQ,2612 +django/contrib/flatpages/locale/fa/LC_MESSAGES/django.po,sha256=_-yKW2xIN9XSXEwZTdkhEpRHJoacN8f56D3AkCvlFs0,3006 +django/contrib/flatpages/locale/fi/LC_MESSAGES/django.mo,sha256=VsQdof8hE_AKQGS-Qp82o8PTN_7NxxEdxelGenIAE-8,2256 +django/contrib/flatpages/locale/fi/LC_MESSAGES/django.po,sha256=RL7eruNkgDjr1b3cF2yCqeM8eDKHwAqF6h8hYuxl6R4,2552 +django/contrib/flatpages/locale/fr/LC_MESSAGES/django.mo,sha256=ZqD4O3_Ny8p5i6_RVHlANCnPiowMd19Qi_LOPfTHav4,2430 +django/contrib/flatpages/locale/fr/LC_MESSAGES/django.po,sha256=liAoOgT2CfpANL_rYzyzsET1MhsM19o7wA2GBnoDvMA,2745 +django/contrib/flatpages/locale/fy/LC_MESSAGES/django.mo,sha256=DRsFoZKo36F34XaiQg_0KUOr3NS_MG3UHptzOI4uEAU,476 +django/contrib/flatpages/locale/fy/LC_MESSAGES/django.po,sha256=9JIrRVsPL1m0NPN6uHiaAYxJXHp5IghZmQhVSkGo5g8,1523 +django/contrib/flatpages/locale/ga/LC_MESSAGES/django.mo,sha256=KKvDhZULHQ4JQ_31ltLkk88H2BKUbBXDQFSvdKFqjn8,2191 +django/contrib/flatpages/locale/ga/LC_MESSAGES/django.po,sha256=Yat7oU2XPQFQ8vhNq1nJFAlX2rqfxz4mjpU5TcnaYO8,2400 +django/contrib/flatpages/locale/gd/LC_MESSAGES/django.mo,sha256=KbaTL8kF9AxDBLDQWlxcP5hZ4zWnbkvY0l2xRKZ9Dg0,2469 +django/contrib/flatpages/locale/gd/LC_MESSAGES/django.po,sha256=DVY_1R0AhIaI1qXIeRej3XSHMtlimeKNUwzFjc4OmwA,2664 +django/contrib/flatpages/locale/gl/LC_MESSAGES/django.mo,sha256=e8hfOxRyLtCsvdd1FVGuI_dnsptVhfW_O9KyuPT0ENk,2256 +django/contrib/flatpages/locale/gl/LC_MESSAGES/django.po,sha256=YqyR8qnKho8jK03igqPv9KlJw5yVIIDCAGc5z2QxckE,2583 +django/contrib/flatpages/locale/he/LC_MESSAGES/django.mo,sha256=PbypHBhT3W_rp37u8wvaCJdtYB4IP-UeE02VUvSHPf0,2517 +django/contrib/flatpages/locale/he/LC_MESSAGES/django.po,sha256=f7phCRqJPFL7CsuSE1xg9xlaBoOpdd-0zoTYotff29M,2827 +django/contrib/flatpages/locale/hi/LC_MESSAGES/django.mo,sha256=w29ukoF48C7iJ6nE045YoWi7Zcrgu_oXoxT-r6gcQy8,2770 +django/contrib/flatpages/locale/hi/LC_MESSAGES/django.po,sha256=nXq5y1FqMGVhpXpQVdV3uU5JcUtBc2BIrf-n__C2q30,3055 +django/contrib/flatpages/locale/hr/LC_MESSAGES/django.mo,sha256=Mt4gpBuUXvcBl8K714ls4PimHQqee82jFxY1BEAYQOE,2188 +django/contrib/flatpages/locale/hr/LC_MESSAGES/django.po,sha256=ZbUMJY6a-os-xDmcDCJNrN4-YqRe9b_zJ4V5gt2wlGI,2421 +django/contrib/flatpages/locale/hsb/LC_MESSAGES/django.mo,sha256=Pk44puT-3LxzNdGYxMALWpFdw6j6W0G-dWwAfv8sopI,2361 +django/contrib/flatpages/locale/hsb/LC_MESSAGES/django.po,sha256=mhnBXgZSK19E4JU8p2qzqyZqozSzltK-3iY5glr9WG8,2538 +django/contrib/flatpages/locale/hu/LC_MESSAGES/django.mo,sha256=rZxICk460iWBubNq53g9j2JfKIw2W7OqyPG5ylGE92s,2363 +django/contrib/flatpages/locale/hu/LC_MESSAGES/django.po,sha256=DDP7OLBkNbWXr-wiulmQgG461qAubJ8VrfCCXbyPk2g,2700 +django/contrib/flatpages/locale/hy/LC_MESSAGES/django.mo,sha256=qocNtyLcQpjmGqQ130VGjJo-ruaOCtfmZehS9If_hWk,2536 +django/contrib/flatpages/locale/hy/LC_MESSAGES/django.po,sha256=WD8ohMnsaUGQItyqQmS46d76tKgzhQ17X_tGevqULO0,2619 +django/contrib/flatpages/locale/ia/LC_MESSAGES/django.mo,sha256=bochtCPlc268n0WLF0bJtUUT-XveZLPOZPQUetnOWfU,500 +django/contrib/flatpages/locale/ia/LC_MESSAGES/django.po,sha256=gOJ850e8sFcjR2G79zGn3_0-9-KSy591i7ketBRFjyw,1543 +django/contrib/flatpages/locale/id/LC_MESSAGES/django.mo,sha256=2kRHbcmfo09pIEuBb8q5AOkgC0sISJrAG37Rb5F0vts,2222 +django/contrib/flatpages/locale/id/LC_MESSAGES/django.po,sha256=1avfX88CkKMh2AjzN7dxRwj9pgohIBgKE0aXB_shZfc,2496 +django/contrib/flatpages/locale/io/LC_MESSAGES/django.mo,sha256=N8R9dXw_cnBSbZtwRbX6Tzw5XMr_ZdRkn0UmsQFDTi4,464 +django/contrib/flatpages/locale/io/LC_MESSAGES/django.po,sha256=_pJveonUOmMu3T6WS-tV1OFh-8egW0o7vU3i5YqgChA,1511 +django/contrib/flatpages/locale/is/LC_MESSAGES/django.mo,sha256=lFtP1N5CN-x2aMtBNpB6j5HsZYZIZYRm6Y-22gNe1Ek,2229 +django/contrib/flatpages/locale/is/LC_MESSAGES/django.po,sha256=9e132zDa-n6IZxB8jO5H8I0Wr7ubYxrFEMBYj2W49vI,2490 +django/contrib/flatpages/locale/it/LC_MESSAGES/django.mo,sha256=oOEG327VGpi0K5P2UOQgQa39ln15t0lAz2Z36MIQQAc,2209 +django/contrib/flatpages/locale/it/LC_MESSAGES/django.po,sha256=ar8i-bTtAKhiXLULCsKMddpmYBjKyg2paYxBI6ImY1s,2526 +django/contrib/flatpages/locale/ja/LC_MESSAGES/django.mo,sha256=Qax3t7FFRonMrszVEeiyQNMtYyWQB3dmOeeIklEmhAg,2469 +django/contrib/flatpages/locale/ja/LC_MESSAGES/django.po,sha256=N6PBvnXLEWELKTx8nHm5KwydDuFFKq5pn6AIHsBSM5M,2848 +django/contrib/flatpages/locale/ka/LC_MESSAGES/django.mo,sha256=R4OSbZ-lGxMdeJYsaXVXpo6-KSZWeKPuErKmEsUvEQE,3022 +django/contrib/flatpages/locale/ka/LC_MESSAGES/django.po,sha256=TWKtkRamM6YD-4WMoqfZ7KY-ZPs5ny7G82Wst6vQRko,3306 +django/contrib/flatpages/locale/kk/LC_MESSAGES/django.mo,sha256=lMPryzUQr21Uy-NAGQhuIZjHz-4LfBHE_zxEc2_UPaw,2438 +django/contrib/flatpages/locale/kk/LC_MESSAGES/django.po,sha256=3y9PbPw-Q8wM7tCq6u3KeYUT6pfTqcQwlNlSxpAXMxQ,2763 +django/contrib/flatpages/locale/km/LC_MESSAGES/django.mo,sha256=FYRfhNSqBtavYb10sHZNfB-xwLwdZEfVEzX116nBs-k,1942 +django/contrib/flatpages/locale/km/LC_MESSAGES/django.po,sha256=d2AfbR78U0rJqbFmJQvwiBl_QvYIeSwsPKEnfYM4JZA,2471 +django/contrib/flatpages/locale/kn/LC_MESSAGES/django.mo,sha256=n5HCZEPYN_YIVCXrgA1qhxvfhZtDbhfiannJy5EkHkI,1902 +django/contrib/flatpages/locale/kn/LC_MESSAGES/django.po,sha256=-CHwu13UuE2-Qg6poG949I_dw3YiPI9ZhMh5h2vP4xw,2443 +django/contrib/flatpages/locale/ko/LC_MESSAGES/django.mo,sha256=M-IInVdIH24ORarb-KgY60tEorJZgrThDfJQOxW-S0c,2304 +django/contrib/flatpages/locale/ko/LC_MESSAGES/django.po,sha256=DjAtWVAN_fwOvZb-7CUSLtO8WN0Sr08z3jQLNqZ98wY,2746 +django/contrib/flatpages/locale/ky/LC_MESSAGES/django.mo,sha256=WmdWR6dRgmJ-nqSzFDUETypf373fj62igDVHC4ww7hQ,2667 +django/contrib/flatpages/locale/ky/LC_MESSAGES/django.po,sha256=0XDF6CjQTGkuaHADytG95lpFRVndlf_136q0lrQiU1U,2907 +django/contrib/flatpages/locale/lb/LC_MESSAGES/django.mo,sha256=Wkvlh5L_7CopayfNM5Z_xahmyVje1nYOBfQJyqucI_0,502 +django/contrib/flatpages/locale/lb/LC_MESSAGES/django.po,sha256=gGeTuniu3ZZ835t9HR-UtwCcd2s_Yr7ihIUm3jgQ7Y0,1545 +django/contrib/flatpages/locale/lt/LC_MESSAGES/django.mo,sha256=es6xV6X1twtqhIMkV-MByA7KZ5SoVsrx5Qh8BuzJS0Q,2506 +django/contrib/flatpages/locale/lt/LC_MESSAGES/django.po,sha256=T__44veTC_u4hpPvkLekDOWfntXYAMzCd5bffRtGxWA,2779 +django/contrib/flatpages/locale/lv/LC_MESSAGES/django.mo,sha256=RJbVUR8qS8iLL3dD5x1TOau4hcdscHUJBfxge3p3dsM,2359 +django/contrib/flatpages/locale/lv/LC_MESSAGES/django.po,sha256=M6GT6S-5-7__RtSbJ9oqkIlxfU3FIWMlGAQ03NEfcKo,2610 +django/contrib/flatpages/locale/mk/LC_MESSAGES/django.mo,sha256=55H8w6fB-B-RYlKKkGw3fg2m-djxUoEp_XpupK-ZL70,2699 +django/contrib/flatpages/locale/mk/LC_MESSAGES/django.po,sha256=OhHJ5OVWb0jvNaOB3wip9tSIZ1yaPPLkfQR--uUEyUI,2989 +django/contrib/flatpages/locale/ml/LC_MESSAGES/django.mo,sha256=VMMeOujp5fiLzrrbDeH24O2qKBPUkvI_YTSPH-LQjZc,3549 +django/contrib/flatpages/locale/ml/LC_MESSAGES/django.po,sha256=KR2CGnZ1sVuRzSGaPj5IlspoAkVuVEdf48XsAzt1se0,3851 +django/contrib/flatpages/locale/mn/LC_MESSAGES/django.mo,sha256=tqwROY6D-bJ4gbDQIowKXfuLIIdCWksGwecL2sj_wco,2776 +django/contrib/flatpages/locale/mn/LC_MESSAGES/django.po,sha256=jqiBpFLXlptDyU4F8ZWbP61S4APSPh0-nuTpNOejA6c,3003 +django/contrib/flatpages/locale/mr/LC_MESSAGES/django.mo,sha256=GvSfsp0Op7st6Ifd8zp8Cj4tTHoFMltQb4p64pebrqI,468 +django/contrib/flatpages/locale/mr/LC_MESSAGES/django.po,sha256=sayU0AfVaSFpBj0dT32Ri55LRafQFUHLi03K06kI7gc,1515 +django/contrib/flatpages/locale/ms/LC_MESSAGES/django.mo,sha256=5t_67bMQhux6v6SSWqHfzzCgc6hm3olxgHAsKOMGGZU,2184 +django/contrib/flatpages/locale/ms/LC_MESSAGES/django.po,sha256=-ZzZ8lfAglGkO_BRYz1lRlywxaF1zZ28-Xv74O2nT04,2336 +django/contrib/flatpages/locale/my/LC_MESSAGES/django.mo,sha256=OcbiA7tJPkyt_WNrqyvoFjHt7WL7tMGHV06AZSxzkho,507 +django/contrib/flatpages/locale/my/LC_MESSAGES/django.po,sha256=EPWE566Vn7tax0PYUKq93vtydvmt-A4ooIau9Cwcdfc,1550 +django/contrib/flatpages/locale/nb/LC_MESSAGES/django.mo,sha256=L_XICESZ0nywkk1dn6RqzdUbFTcR92ju-zHCT1g3iEg,2208 +django/contrib/flatpages/locale/nb/LC_MESSAGES/django.po,sha256=ZtcBVD0UqIcsU8iLu5a2wnHLqu5WRLLboVFye2IuQew,2576 +django/contrib/flatpages/locale/ne/LC_MESSAGES/django.mo,sha256=gDZKhcku1NVlSs5ZPPupc7RI8HOF7ex0R4Rs8tMmrYE,1500 +django/contrib/flatpages/locale/ne/LC_MESSAGES/django.po,sha256=GWlzsDaMsJkOvw2TidJOEf1Fvxx9WxGdGAtfZIHkHwk,2178 +django/contrib/flatpages/locale/nl/LC_MESSAGES/django.mo,sha256=_yV_-SYYjpbo-rOHp8NlRzVHFPOSrfS-ndHOEJ9JP3Y,2231 +django/contrib/flatpages/locale/nl/LC_MESSAGES/django.po,sha256=xUuxx2b4ZTCA-1RIdoMqykLgjLLkmpO4ur1Vh93IITU,2669 +django/contrib/flatpages/locale/nn/LC_MESSAGES/django.mo,sha256=sHkuZneEWo1TItSlarlnOUR7ERjc76bJfHUcuFgd9mQ,2256 +django/contrib/flatpages/locale/nn/LC_MESSAGES/django.po,sha256=MpI9qkWqj4rud__xetuqCP-eFHUgMYJpfBhDnWRKPK4,2487 +django/contrib/flatpages/locale/os/LC_MESSAGES/django.mo,sha256=cXGTA5M229UFsgc7hEiI9vI9SEBrNQ8d3A0XrtazO6w,2329 +django/contrib/flatpages/locale/os/LC_MESSAGES/django.po,sha256=m-qoTiKePeFviKGH1rJRjZRH-doJ2Fe4DcZ6W52rG8s,2546 +django/contrib/flatpages/locale/pa/LC_MESSAGES/django.mo,sha256=69_ZsZ4nWlQ0krS6Mx3oL6c4sP5W9mx-yAmOhZOnjPU,903 +django/contrib/flatpages/locale/pa/LC_MESSAGES/django.po,sha256=N6gkoRXP5MefEnjywzRiE3aeU6kHQ0TUG6IGdLV7uww,1780 +django/contrib/flatpages/locale/pl/LC_MESSAGES/django.mo,sha256=5M5-d-TOx2WHlD6BCw9BYIU6bYrSR0Wlem89ih5k3Pc,2448 +django/contrib/flatpages/locale/pl/LC_MESSAGES/django.po,sha256=oKeeo-vNfPaCYVUbufrJZGk0vsgzAE0kLQOTF5qHAK4,2793 +django/contrib/flatpages/locale/pt/LC_MESSAGES/django.mo,sha256=xD2pWdS3XMg7gAqBrUBmCEXFsOzEs0Npe8AJnlpueRY,2115 +django/contrib/flatpages/locale/pt/LC_MESSAGES/django.po,sha256=-K2jipPUWjXpfSPq3upnC_bvtaRAeOw0OLRFv03HWFY,2326 +django/contrib/flatpages/locale/pt_BR/LC_MESSAGES/django.mo,sha256=YGyagSFIc-ssFN8bnqVRce1_PsybvLmI8RVCygjow8E,2291 +django/contrib/flatpages/locale/pt_BR/LC_MESSAGES/django.po,sha256=pFA8RPNefZpuhbxBHLt9KrI2RiHxct5V-DnZA-XqBv0,2942 +django/contrib/flatpages/locale/ro/LC_MESSAGES/django.mo,sha256=oS3MXuRh2USyLOMrMH0WfMSFpgBcZWfrbCrovYgbONo,2337 +django/contrib/flatpages/locale/ro/LC_MESSAGES/django.po,sha256=UNKGNSZKS92pJDjxKDLqVUW87DKCWP4_Q51xS16IZl0,2632 +django/contrib/flatpages/locale/ru/LC_MESSAGES/django.mo,sha256=AACtHEQuytEohUZVgk-o33O7rJTFAluq22VJOw5JqII,2934 +django/contrib/flatpages/locale/ru/LC_MESSAGES/django.po,sha256=H6JOPAXNxji1oni9kfga_hNZevodStpEl0O6cDnZ148,3312 +django/contrib/flatpages/locale/sk/LC_MESSAGES/django.mo,sha256=P1192D_B2kDQ6nF_tGEW7WCoTodB3_9rMTaqEQSMO4E,2353 +django/contrib/flatpages/locale/sk/LC_MESSAGES/django.po,sha256=--_DaPB_aSZHn_uxzmCpITO7VPCpP4Nq2rdQGgN14r8,2638 +django/contrib/flatpages/locale/sl/LC_MESSAGES/django.mo,sha256=kOrhhBdM9nbQbCLN49bBn23hCrzpAPrfKvPs4QMHgvo,2301 +django/contrib/flatpages/locale/sl/LC_MESSAGES/django.po,sha256=oyTrOVH0v76Ttc93qfeyu3FHcWLh3tTiz2TefGkmoq4,2621 +django/contrib/flatpages/locale/sq/LC_MESSAGES/django.mo,sha256=Jv2sebdAM6CfiLzgi1b7rHo5hp-6_BFeeMQ4_BwYpjk,2328 +django/contrib/flatpages/locale/sq/LC_MESSAGES/django.po,sha256=Xm87FbWaQ1JGhhGx8uvtqwUltkTkwk5Oysagu8qIPUA,2548 +django/contrib/flatpages/locale/sr/LC_MESSAGES/django.mo,sha256=p--v7bpD8Pp6zeP3cdh8fnfC8g2nuhbzGJTdN9eoE58,2770 +django/contrib/flatpages/locale/sr/LC_MESSAGES/django.po,sha256=jxcyMN2Qh_osmo4Jf_6QUC2vW3KVKt1BupDWMMZyAXA,3071 +django/contrib/flatpages/locale/sr_Latn/LC_MESSAGES/django.mo,sha256=3N4mGacnZj0tI5tFniLqC2LQCPSopDEM1SGaw5N1bsw,2328 +django/contrib/flatpages/locale/sr_Latn/LC_MESSAGES/django.po,sha256=od7r3dPbZ7tRAJUW80Oe-nm_tHcmIiG6b2OZMsFg53s,2589 +django/contrib/flatpages/locale/sv/LC_MESSAGES/django.mo,sha256=1pFmNWiExWo5owNijZHZb8-Tbd0nYPqqvTmIitcFPbY,2252 +django/contrib/flatpages/locale/sv/LC_MESSAGES/django.po,sha256=l3anvdgLQJzYehCalwr1AAh8e-hRKrL_bSNwmkfgbbc,2613 +django/contrib/flatpages/locale/sw/LC_MESSAGES/django.mo,sha256=Lhf99AGmazKJHzWk2tkGrMInoYOq0mtdCd8SGblnVCQ,1537 +django/contrib/flatpages/locale/sw/LC_MESSAGES/django.po,sha256=cos3eahuznpTfTdl1Vj_07fCOSYE8C9CRYHCBLYZrVw,1991 +django/contrib/flatpages/locale/ta/LC_MESSAGES/django.mo,sha256=nNuoOX-FPAmTvM79o7colM4C7TtBroTFxYtETPPatcQ,1945 +django/contrib/flatpages/locale/ta/LC_MESSAGES/django.po,sha256=XE4SndPZPLf1yXGl5xQSb0uor4OE8CKJ0EIXBRDA3qU,2474 +django/contrib/flatpages/locale/te/LC_MESSAGES/django.mo,sha256=bMxhDMTQc_WseqoeqJMCSNy71o4U5tJZYgD2G0p-jD0,1238 +django/contrib/flatpages/locale/te/LC_MESSAGES/django.po,sha256=tmUWOrAZ98B9T6Cai8AgLCfb_rLeoPVGjDTgdsMOY1Y,2000 +django/contrib/flatpages/locale/tg/LC_MESSAGES/django.mo,sha256=gpzjf_LxwWX6yUrcUfNepK1LGez6yvnuYhmfULDPZ6E,2064 +django/contrib/flatpages/locale/tg/LC_MESSAGES/django.po,sha256=lZFLes8BWdJ-VbczHFDWCSKhKg0qmmk10hTjKcBNr5o,2572 +django/contrib/flatpages/locale/th/LC_MESSAGES/django.mo,sha256=mct17_099pUn0aGuHu8AlZG6UqdKDpYLojqGYDLRXRg,2698 +django/contrib/flatpages/locale/th/LC_MESSAGES/django.po,sha256=PEcRx5AtXrDZvlNGWFH-0arroD8nZbutdJBe8_I02ag,2941 +django/contrib/flatpages/locale/tk/LC_MESSAGES/django.mo,sha256=5iVSzjcnJLfdAnrI1yOKua_OfHmgUu6ydixKkvayrzQ,753 +django/contrib/flatpages/locale/tk/LC_MESSAGES/django.po,sha256=0VK0Ju55wTvmYXqS9hPKLJXyTtTz9Z8mv_qw66ck5gg,1824 +django/contrib/flatpages/locale/tr/LC_MESSAGES/django.mo,sha256=pPNGylfG8S0iBI4ONZbky3V2Q5AG-M1njp27tFrhhZc,2290 +django/contrib/flatpages/locale/tr/LC_MESSAGES/django.po,sha256=0ULZu3Plp8H9zdirHy3MSduJ_QRdpoaaivf3bL9MCwA,2588 +django/contrib/flatpages/locale/tt/LC_MESSAGES/django.mo,sha256=9RfCKyn0ZNYsqLvFNmY18xVMl7wnmDq5uXscrsFfupk,2007 +django/contrib/flatpages/locale/tt/LC_MESSAGES/django.po,sha256=SUwalSl8JWI9tuDswmnGT8SjuWR3DQGND9roNxJtH1o,2402 +django/contrib/flatpages/locale/udm/LC_MESSAGES/django.mo,sha256=7KhzWgskBlHmi-v61Ax9fjc3NBwHB17WppdNMuz-rEc,490 +django/contrib/flatpages/locale/udm/LC_MESSAGES/django.po,sha256=zidjP05Hx1OpXGqWEmF2cg9SFxASM4loOV85uW7zV5U,1533 +django/contrib/flatpages/locale/ug/LC_MESSAGES/django.mo,sha256=FL8P63c7BRO5hNABEzurk91v01ceRBhC1DJyjFJkiwg,2644 +django/contrib/flatpages/locale/ug/LC_MESSAGES/django.po,sha256=TxlRCGW-6fyxOO3YzAzKJa4utQp4NOOZ08YZxSit9E8,2774 +django/contrib/flatpages/locale/uk/LC_MESSAGES/django.mo,sha256=r2RZT8xQ1Gi9Yp0nnoNALqQ4zrEJ0JC7m26E5gSeq4g,3002 +django/contrib/flatpages/locale/uk/LC_MESSAGES/django.po,sha256=qcVizoTiKYc1c9KwSTwSALHgjjSGVY2oito_bBRLVTE,3405 +django/contrib/flatpages/locale/ur/LC_MESSAGES/django.mo,sha256=Li4gVdFoNOskGKAKiNuse6B2sz6ePGqGvZu7aGXMNy0,1976 +django/contrib/flatpages/locale/ur/LC_MESSAGES/django.po,sha256=hDasKiKrYov9YaNIHIpoooJo0Bzba___IuN2Hl6ofSc,2371 +django/contrib/flatpages/locale/vi/LC_MESSAGES/django.mo,sha256=FsFUi96oGTWGlZwM4qSMpuL1M2TAxsW51qO70TrybSM,1035 +django/contrib/flatpages/locale/vi/LC_MESSAGES/django.po,sha256=ITX3MWd7nlWPxTCoNPl22_OMLTt0rfvajGvTVwo0QC8,1900 +django/contrib/flatpages/locale/zh_Hans/LC_MESSAGES/django.mo,sha256=UTCQr9t2wSj6dYLK1ftpF8-pZ25dAMYLRE2wEUQva-o,2124 +django/contrib/flatpages/locale/zh_Hans/LC_MESSAGES/django.po,sha256=loi9RvOnrgFs4qp8FW4RGis7wgDzBBXuwha5pFfLRxY,2533 +django/contrib/flatpages/locale/zh_Hant/LC_MESSAGES/django.mo,sha256=Y5nDMQ3prLJ6OHuQEeEqjDLBC9_L-4XHDGJSLNoCgqg,2200 +django/contrib/flatpages/locale/zh_Hant/LC_MESSAGES/django.po,sha256=6dKCSJpw_8gnunfTY86_apXdH5Pqe0kKYSVaqRtOIh0,2475 +django/contrib/flatpages/middleware.py,sha256=aXeOeOkUmpdkGOyqZnkR-l1VrDQ161RWIWa3WPBhGac,784 +django/contrib/flatpages/migrations/0001_initial.py,sha256=4xhMsKaXOycsfo9O1QIuknS9wf7r0uVsshAJ7opeqsM,2408 +django/contrib/flatpages/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/flatpages/models.py,sha256=3ugRRsDwB5C3GHOWvtOzjJl-y0yqqjYZBSOMt24QYuw,1764 +django/contrib/flatpages/sitemaps.py,sha256=CEhZOsLwv3qIJ1hs4eHlE_0AAtYjicb_yRzsstY19eg,584 +django/contrib/flatpages/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/flatpages/templatetags/flatpages.py,sha256=QH-suzsoPIMSrgyHR9O8uOdmfIkBv_w3LM-hGfQvnU8,3552 +django/contrib/flatpages/urls.py,sha256=Rs37Ij192SOtSBjd4Lx9YtpINfEMg7XRY01dEOY8Rgg,179 +django/contrib/flatpages/views.py,sha256=H4LG7Janb6Dcn-zINLmp358hR60JigAKGzh4A4PMPaM,2724 +django/contrib/gis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/gis/admin/__init__.py,sha256=bCUsC6Hh7hztchqRKuaiTgk3nL0B4H053bVII-olB7k,486 +django/contrib/gis/admin/options.py,sha256=r60rycdAgcGSB21KQS_V0X78ulUjATYzws-JKLYd_lc,689 +django/contrib/gis/apps.py,sha256=dbAFKx9jj9_QdhdNfL5KCC47puH_ZTw098jsJFwDO9Y,417 +django/contrib/gis/db/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/gis/db/backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/gis/db/backends/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/gis/db/backends/base/adapter.py,sha256=qbLG-sLB6EZ_sA6-E_uIClyp5E5hz9UQ-CsR3BWx8W8,592 +django/contrib/gis/db/backends/base/features.py,sha256=fF-AKB6__RjkxVRadNkOP7Av4wMaRGkXKybYV6ES2Gk,3718 +django/contrib/gis/db/backends/base/models.py,sha256=WqpmVLqK21m9J6k_N-SGPXq1VZMuNHafyB9xqxUwR4k,4009 +django/contrib/gis/db/backends/base/operations.py,sha256=_g_B-_AN1OVmarA3O8FdU7hnAgBCX0d4gvqalNRJAYg,6859 +django/contrib/gis/db/backends/mysql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/gis/db/backends/mysql/base.py,sha256=z75wKhm-e9JfRLCvgDq-iv9OqOjBBAS238JTTrWfHRQ,498 +django/contrib/gis/db/backends/mysql/features.py,sha256=dVRo3CuV8Zp5822h9l48nApiXyn3lCuXQV3vsRZKeao,866 +django/contrib/gis/db/backends/mysql/introspection.py,sha256=ZihcSzwN0f8iqKOYKMHuQ_MY41ERSswjP46dvCF0v68,1602 +django/contrib/gis/db/backends/mysql/operations.py,sha256=zEHVKmhYhnjLP75_zC1gm-2bTSgMwK0QfqwI9J1wG_0,4258 +django/contrib/gis/db/backends/mysql/schema.py,sha256=XZb1ImKNFZNUEZMxdgLYXGs4Xirgw8kKoGHNVJv763E,3205 +django/contrib/gis/db/backends/oracle/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/gis/db/backends/oracle/adapter.py,sha256=AjD0eMuptu8BqkE2LshTizkf5iv9ArYVP9PoOTHfNao,2066 +django/contrib/gis/db/backends/oracle/base.py,sha256=_7qhvEdbnrJQEKL51sg8YYu8kRYmQNAlBgNb2OUbBkw,507 +django/contrib/gis/db/backends/oracle/features.py,sha256=3yCDutKz4iX01eOjLf0CLe_cemMaRjDmH8ZKNy_Sbyk,1021 +django/contrib/gis/db/backends/oracle/introspection.py,sha256=fW9FTIW_yAQQZwk0LzdoTtj6QQpFN6fgUQzv8dCmFEo,1939 +django/contrib/gis/db/backends/oracle/models.py,sha256=7mij7owmmwqAl-4rPJmEU_zW3hZZI0hix7HyFOwJkms,2084 +django/contrib/gis/db/backends/oracle/operations.py,sha256=N4InuTJfKjs8EOtnLUw2ctUz9gBLgwSR-1vvJ_a-uXM,8790 +django/contrib/gis/db/backends/oracle/schema.py,sha256=4bjssdtSl2_n3CWX67k4yLOCLzevU5CYg-yx8s4A39Y,4469 +django/contrib/gis/db/backends/postgis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/gis/db/backends/postgis/adapter.py,sha256=81hwPi7Z2b7BjKMTbA7MKEuCgSYc8MnGQfB2SL9BWqQ,1980 +django/contrib/gis/db/backends/postgis/base.py,sha256=37t0_fDD4IeFsQrMrKoQRW01e8KJeXCSkbv5sOpreR8,5793 +django/contrib/gis/db/backends/postgis/const.py,sha256=_ODq71ixhGpojzbO1DAWs5O4REFgzruIpQkNhPw9O-E,2007 +django/contrib/gis/db/backends/postgis/features.py,sha256=qOEJLQTIC1YdlDoJkpLCiVQU4GAy0d9_Dneui7w41bM,455 +django/contrib/gis/db/backends/postgis/introspection.py,sha256=ihrNd_qHQ64DRjoaPj9-1a0y3H8Ko4gWbK2N5fDA3_g,3164 +django/contrib/gis/db/backends/postgis/models.py,sha256=nFFshpCS4Az4js853MuZxdsp_SOOIlghjuu2XZEeB-Y,2002 +django/contrib/gis/db/backends/postgis/operations.py,sha256=sxeX_rmdRhLwBTjheRUdbpYaZ5JH0b4dhCEBSFwgUDc,16576 +django/contrib/gis/db/backends/postgis/pgraster.py,sha256=eCa2y-v3qGLeNbFI4ERFj2UmqgYAE19nuL3SgDFmm0o,4588 +django/contrib/gis/db/backends/postgis/schema.py,sha256=dU-o1GQh2lPdiNYmBgd7QTnKq3L3JYqZck5pKn-BA0o,3020 +django/contrib/gis/db/backends/spatialite/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/gis/db/backends/spatialite/adapter.py,sha256=qTiA5BBGUFND3D7xGK_85oo__HSexTH32XF4uin3ZV0,318 +django/contrib/gis/db/backends/spatialite/base.py,sha256=wU1fgp68CLyKELsMfO6zYM85ox4g_GloWESEK8EPrfM,3218 +django/contrib/gis/db/backends/spatialite/client.py,sha256=dNM7mqDyTzFlgQR1XhqZIftnR9VRH7AfcSvvy4vucEs,138 +django/contrib/gis/db/backends/spatialite/features.py,sha256=zkmJPExFtRqjRj608ZTlsSpxkYaPbV3A3SEfX3PcaFY,876 +django/contrib/gis/db/backends/spatialite/introspection.py,sha256=V_iwkz0zyF1U-AKq-UlxvyDImqQCsitcmvxk2cUw81A,3118 +django/contrib/gis/db/backends/spatialite/models.py,sha256=Of5O1At0W9wQ5PPLVpO0LWth2KDCOJt6Cfz5_OwaYR0,1930 +django/contrib/gis/db/backends/spatialite/operations.py,sha256=s549jK8yzs6UAKjLSvXAnRFdtOf3PQBdUNa150VIELE,8394 +django/contrib/gis/db/backends/spatialite/schema.py,sha256=URhFfLQM7FH39wmkViD8MZJ1qG3cixhNdWmjuM9ZB44,7340 +django/contrib/gis/db/backends/utils.py,sha256=rLwSv79tKJPxvDHACY8rhPDLFZC79mEIlIySTyl_qqc,785 +django/contrib/gis/db/models/__init__.py,sha256=TrCS27JdVa-Q7Hok-YaJxb4eLrPdyvRmasJGIu05fvA,865 +django/contrib/gis/db/models/aggregates.py,sha256=maFVXmuIF0KwJzgH5Hv3yGsgLA2eCloD4CLGI7mW38A,3207 +django/contrib/gis/db/models/fields.py,sha256=n40s9HYbqVpFKIW9b4X4IQ8INWUus7QZi5QdiWVPsTI,14312 +django/contrib/gis/db/models/functions.py,sha256=sp3upKA7LMejhvpAiFtrWD5Q1ZsFwyDInNqDYmb0nJY,18725 +django/contrib/gis/db/models/lookups.py,sha256=FOb501DBuopcbLy175O1BwD2ZoaVa2optogbXmvwv3o,11797 +django/contrib/gis/db/models/proxy.py,sha256=o2wXW3sFIWhjhkSrzrwFaCdatvZLF8Z5Zs3s1ugmriA,3173 +django/contrib/gis/db/models/sql/__init__.py,sha256=-rzcC3izMJi2bnvyQUCMzIOrigBnY6N_5EQIim4wCSY,134 +django/contrib/gis/db/models/sql/conversion.py,sha256=AZLJCMSw_svSLQPB5LTvA-YRFnMZSXYdHdvPSTFmK4Y,2432 +django/contrib/gis/feeds.py,sha256=0vNVVScIww13bOxvlQfXAOCItIOGWSXroKKl6QXGB58,5995 +django/contrib/gis/forms/__init__.py,sha256=Zyid_YlZzHUcMYkfGX1GewmPPDNc0ni7HyXKDTeIkjo,318 +django/contrib/gis/forms/fields.py,sha256=FrZaZWXFUdWK1QEu8wlda3u6EtqaVHjQRYrSKKu66PA,4608 +django/contrib/gis/forms/widgets.py,sha256=J29IUZ3HTfepfoiJvSeLoDfzyy6Gf6Hoo_Y-bTUMO3o,4549 +django/contrib/gis/gdal/LICENSE,sha256=VwoEWoNyts1qAOMOuv6OPo38Cn_j1O8sxfFtQZ62Ous,1526 +django/contrib/gis/gdal/__init__.py,sha256=m5cRj_qvD3jbLDjMk0ggDxW_hifeZ-CbtRtHZUIsRiQ,1827 +django/contrib/gis/gdal/base.py,sha256=yymyL0vZRMBfiFUzrehvaeaunIxMH5ucGjPRfKj-rAo,181 +django/contrib/gis/gdal/datasource.py,sha256=78S8Z5H61PCJS1_-CCJbiJAOP12X-IWo79PwCfyiVXI,4611 +django/contrib/gis/gdal/driver.py,sha256=eCzrqEVOwyTlcRItrUirmEdNaSrsAIvw9jP_Z669xds,3351 +django/contrib/gis/gdal/envelope.py,sha256=Aj3Qn33QWjDYrwX1je2AZOmokffzs-s4kD96HL1easQ,7323 +django/contrib/gis/gdal/error.py,sha256=Vt-Uis9z786UGE3tD7fjiH8_0P5HSTO81n4fad4l6kw,1578 +django/contrib/gis/gdal/feature.py,sha256=HPWoCZjwzsUnhc7QmKh-BBMRqJCjj07RcFI6vjbdnp4,4017 +django/contrib/gis/gdal/field.py,sha256=EKE-Ioj5L79vo93Oixz_JE4TIZbDTRy0YVGvZH-I1z4,6886 +django/contrib/gis/gdal/geometries.py,sha256=tYXqoHD0kY8LWN1SVcabj15kfeXy2WTQW9zKIeR8-iQ,24346 +django/contrib/gis/gdal/geomtype.py,sha256=VD_w5GymdaKJwgBW1cq2Xjtl3EVXCvJh26LIlKgW_PM,3071 +django/contrib/gis/gdal/layer.py,sha256=PygAgsRZzWekp6kq6NEAZ6vhQTSo1Nk4c1Yi_pOdK58,8825 +django/contrib/gis/gdal/libgdal.py,sha256=wsVA4TmXjaUrJDu9f8O6KYZ6PIL6P6aREfzEqmrFwJU,3578 +django/contrib/gis/gdal/prototypes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/gis/gdal/prototypes/ds.py,sha256=aWeItuRLGr9N3qcnB7vuooNbeGerkixnDRUjtaX7zk0,4525 +django/contrib/gis/gdal/prototypes/errcheck.py,sha256=wlRqrVnozMingrYIBH_9oMMzY9DMrX00BYzP_n54iu0,4173 +django/contrib/gis/gdal/prototypes/generation.py,sha256=c4m3x0QkDhDDaYxavGcvMLs3RNNb9EzfKTzHudWF1f8,4889 +django/contrib/gis/gdal/prototypes/geom.py,sha256=LjygKS-WbNMXj4Y8kaYGSn0OU5-UlQpjCmpmj3aPjhY,5046 +django/contrib/gis/gdal/prototypes/raster.py,sha256=HPLc2gAsGRhNwkjTgtZzHdjWG8LKbcSdwRl1A3qjQDk,5994 +django/contrib/gis/gdal/prototypes/srs.py,sha256=uJ7XgnrX7TuvpgJu8uwes7CWidC7-C6PSSqNeEpJur8,3731 +django/contrib/gis/gdal/raster/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/gis/gdal/raster/band.py,sha256=RPdut6BeQ9vW71rrPMwb2CnXrbCys8YAt1BA8Aholy0,8343 +django/contrib/gis/gdal/raster/base.py,sha256=2GGlL919lPr7YVGFtdIynLPIH-QKYhzrUpoXwVRlM1k,2882 +django/contrib/gis/gdal/raster/const.py,sha256=j52e6ODQLB7oJ-bXp-01suIuj2fDwZMALXz7CaT5ysw,3282 +django/contrib/gis/gdal/raster/source.py,sha256=NmsCjTWDbNFt7oEWfSQSN7ZlofyDZ2yJ3ClSAfDjiW0,18394 +django/contrib/gis/gdal/srs.py,sha256=jB6KRxTQkEOoPPN_myz-6X1GtcsxpacZRuWCoAeg7Ls,12800 +django/contrib/gis/geoip2/__init__.py,sha256=YY9IoFvLImeagLMqouHeY62qKfo0qXl3AFQh63-_Ego,824 +django/contrib/gis/geoip2/base.py,sha256=pth-ZPbB9ks3ikY_RVESzqUs_poKPulItSdJVDQXe28,8942 +django/contrib/gis/geoip2/resources.py,sha256=Lzz-Ok677UBmMZQdHsPv1-qPBeJ8bc4HKTk7_UzmY0I,819 +django/contrib/gis/geometry.py,sha256=0haUP7X6fB2lHBR2syb1oV8TgCqxPher29kn-mH4-78,661 +django/contrib/gis/geos/LICENSE,sha256=CL8kt1USOK4yUpUkVCWxyuua0PQvni0wPHs1NQJjIEU,1530 +django/contrib/gis/geos/__init__.py,sha256=LCGbpFFWXYm6SunsMzV9LoPLNRtDKEWaQ7P4VUtsk84,660 +django/contrib/gis/geos/base.py,sha256=NdlFg5l9akvDp87aqzh9dk0A3ZH2TI3cOq10mmmuHBk,181 +django/contrib/gis/geos/collections.py,sha256=p3-m7yjqxsKPhLZxvLoQUtNKElM3tQjbs860LTCSnYM,3940 +django/contrib/gis/geos/coordseq.py,sha256=ZnLEJDL1uFiYRoGCpvpAmUfK9utALzzv-Rwr7Mh9Oio,6840 +django/contrib/gis/geos/error.py,sha256=r3SNTnwDBI6HtuyL3mQ_iEEeKlOqqqdkHnhNoUkMohw,104 +django/contrib/gis/geos/factory.py,sha256=KQF6lqAh5KRlFSDgN-BSXWojmWFabbEUFgz2IGYX_vk,961 +django/contrib/gis/geos/geometry.py,sha256=CULDbXCSxYq0oPmyFLFG3JYWgs1XOmQN8KD_ZHIGMI0,26651 +django/contrib/gis/geos/io.py,sha256=P3bfg3AIWv99lrqmzFZyP-i6e5YiCuC32fql_IXPgUo,799 +django/contrib/gis/geos/libgeos.py,sha256=rEoKvo3cJ9yqIUyVCeQSIxxuHdVAmburE1cqFQFbtZM,4987 +django/contrib/gis/geos/linestring.py,sha256=BJAoWfHW08EX1UpNFVB09iSKXdTS6pZsTIBc6DcZcfc,6372 +django/contrib/gis/geos/mutable_list.py,sha256=nthCtQ0FsJrDGd29cSERwXb-tJkpK35Vc0T_ywCnXgc,10121 +django/contrib/gis/geos/point.py,sha256=bvatsdXTb1XYy1EaSZvp4Rnr2LwXZU12zILefLu6sRw,4781 +django/contrib/gis/geos/polygon.py,sha256=DZq6Ed9bJA3MqhpDQ9u926hHxcnxBjnbKSppHgbShxw,6710 +django/contrib/gis/geos/prepared.py,sha256=J5Dj6e3u3gEfVPNOM1E_rvcmcXR2-CdwtbAcoiDU5a0,1577 +django/contrib/gis/geos/prototypes/__init__.py,sha256=iAnsD0bg8u7Avo7Fmet4lkAo9lnsyyfZFa7k3IQ6T1w,1438 +django/contrib/gis/geos/prototypes/coordseq.py,sha256=fIcSIzmyCbazQSR-XdvCwtP2YZItQur1Y27vfAKXNfw,3122 +django/contrib/gis/geos/prototypes/errcheck.py,sha256=aW4kLew3tdXZ4NmJhOF2NFY837ACid6Vm-_a10ET5Q8,2788 +django/contrib/gis/geos/prototypes/geom.py,sha256=NlR-rUFCj_V3lppSmYSI2bapLim_VUJXABwElTldZM0,3398 +django/contrib/gis/geos/prototypes/io.py,sha256=j5379Sb-uLjW7SpxQiOeDvcJjrb1ZCa9bOa6IhD6sWI,11321 +django/contrib/gis/geos/prototypes/misc.py,sha256=3Ek1DTeDo4BBsS7LloseeSHPBz70Vu-4mF-dxSjyXLU,1168 +django/contrib/gis/geos/prototypes/predicates.py,sha256=7-K3nCSkYnnQNW47QaFvEokTPqmi4xcY-SZkIVWBtBQ,1661 +django/contrib/gis/geos/prototypes/prepared.py,sha256=4I9pS75Q5MZ1z8A1v0mKkmdCly33Kj_0sDcrqxOppzM,1175 +django/contrib/gis/geos/prototypes/threadsafe.py,sha256=n1yCYvQCtc7piFrhjeZCWH8Pf0-AiOGBH33VZusTgWI,2302 +django/contrib/gis/geos/prototypes/topology.py,sha256=7TNgvTU8L3cyoU0VMXbox3RA3qmUePDXejJiHMntXlU,2327 +django/contrib/gis/locale/af/LC_MESSAGES/django.mo,sha256=FWnPEpxhJG9xJ-uOTFryxIT6BFN3w-bsgqLn0IHF-Ew,518 +django/contrib/gis/locale/af/LC_MESSAGES/django.po,sha256=v5LXHABklHAVbfrPEx3xXGIHIZ4hz4MmfvZ6beC-XF4,1540 +django/contrib/gis/locale/ar/LC_MESSAGES/django.mo,sha256=5LCO903yJTtRVaaujBrmwMx8f8iLa3ihasgmj8te9eg,2301 +django/contrib/gis/locale/ar/LC_MESSAGES/django.po,sha256=pfUyK0VYgY0VC2_LvWZvG_EEIWa0OqIUfhiPT2Uov3Q,2569 +django/contrib/gis/locale/ar_DZ/LC_MESSAGES/django.mo,sha256=1e2lutVEjsa5vErMdjS6gaBbOLPTVIpDv15rax-wvKg,2403 +django/contrib/gis/locale/ar_DZ/LC_MESSAGES/django.po,sha256=dizXM36w-rUtI7Dv2mSoJDR5ouVR6Ar7zqjywX3xKr0,2555 +django/contrib/gis/locale/ast/LC_MESSAGES/django.mo,sha256=8o0Us4wR14bdv1M5oBeczYC4oW5uKnycWrj1-lMIqV4,850 +django/contrib/gis/locale/ast/LC_MESSAGES/django.po,sha256=0beyFcBkBOUNvPP45iqewTNv2ExvCPvDYwpafCJY5QM,1684 +django/contrib/gis/locale/az/LC_MESSAGES/django.mo,sha256=liiZOQ712WIdLolC8_uIHY6G4QPJ_sYhp5CfwxTXEv0,1976 +django/contrib/gis/locale/az/LC_MESSAGES/django.po,sha256=kUxBJdYhLZNnAO3IWKy4R3ijTZBiG-OFMg2wrZ7Jh28,2172 +django/contrib/gis/locale/be/LC_MESSAGES/django.mo,sha256=XcJGF9cH7M30Q8EwqovjAeiJFgB2PR4sXsbxdvVURjg,2389 +django/contrib/gis/locale/be/LC_MESSAGES/django.po,sha256=Cp_DXKCVHzYTA7v65TpjRhCJonkgI5Gy13Tfg1rkVp8,2596 +django/contrib/gis/locale/bg/LC_MESSAGES/django.mo,sha256=lLfpqEEEb1RYzy270gpDdEfv5k5jscyNgJv_Ok_BA_A,2323 +django/contrib/gis/locale/bg/LC_MESSAGES/django.po,sha256=hSxYwbKr-IqP5hJaPKQxoL1DkCIg60suHl1H8u8W7jQ,2586 +django/contrib/gis/locale/bn/LC_MESSAGES/django.mo,sha256=7oNsr_vHQfsanyP-o1FG8jZTSBK8jB3eK2fA9AqNOx4,1070 +django/contrib/gis/locale/bn/LC_MESSAGES/django.po,sha256=PTa9EFZdqfznUH7si3Rq3zp1kNkTOnn2HRTEYXQSOdM,1929 +django/contrib/gis/locale/br/LC_MESSAGES/django.mo,sha256=xN8hOvJi_gDlpdC5_lghXuX6yCBYDPfD_SQLjcvq8gU,1614 +django/contrib/gis/locale/br/LC_MESSAGES/django.po,sha256=LQw3Tp_ymJ_x7mJ6g4SOr6aP00bejkjuaxfFFRZnmaQ,2220 +django/contrib/gis/locale/bs/LC_MESSAGES/django.mo,sha256=9EdKtZkY0FX2NlX_q0tIxXD-Di0SNQJZk3jo7cend0A,1308 +django/contrib/gis/locale/bs/LC_MESSAGES/django.po,sha256=eu_qF8dbmlDiRKGNIz80XtIunrF8QIOcy8O28X02GvQ,1905 +django/contrib/gis/locale/ca/LC_MESSAGES/django.mo,sha256=6aq8xNlP95HRncIB6ThimqW14XFKp7OOjo0S0uT6d-Y,1948 +django/contrib/gis/locale/ca/LC_MESSAGES/django.po,sha256=0Tj64N9TVX-oDyq4srBCgqELmM8OjMgXC5Lci844Fvc,2298 +django/contrib/gis/locale/ckb/LC_MESSAGES/django.mo,sha256=tIH0KyO3XREfX8htOCAK6cJSZkS0BCE15AZngco_Vkw,2253 +django/contrib/gis/locale/ckb/LC_MESSAGES/django.po,sha256=krJj0SQiLAcc1uNA9Qazqy9Ty-7MhauoaIDHtjmPPfo,2442 +django/contrib/gis/locale/cs/LC_MESSAGES/django.mo,sha256=ia8l06-eW5VkQnNQU0aizio7pz_pSGA-KRk-liGRa2w,2026 +django/contrib/gis/locale/cs/LC_MESSAGES/django.po,sha256=8taX01JBHhr19_AKhfhbtlpt-TW1aOBwejN-o-HH5Xk,2274 +django/contrib/gis/locale/cy/LC_MESSAGES/django.mo,sha256=vUG_wzZaMumPwIlKwuN7GFcS9gnE5rpflxoA_MPM_po,1430 +django/contrib/gis/locale/cy/LC_MESSAGES/django.po,sha256=_QjXT6cySUXrjtHaJ3046z-5PoXkCqtOhvA7MCZsXxk,1900 +django/contrib/gis/locale/da/LC_MESSAGES/django.mo,sha256=eXid2KAU_8fd23jMFo41iJ3DntVNe0w939_UsBymGM4,1862 +django/contrib/gis/locale/da/LC_MESSAGES/django.po,sha256=9bSpjg9wv7nvWoaOfRhXKsuxVoMzOHU-fsnVNB8qbxM,2158 +django/contrib/gis/locale/de/LC_MESSAGES/django.mo,sha256=fECmj81LHOUcBcQ_PoQWlijVp3SjTG3GwsSRiUGMXOU,1930 +django/contrib/gis/locale/de/LC_MESSAGES/django.po,sha256=DB_2QZ0IHOxKJ51ZyJCNX24597W7DBc_DT1B-oId-bY,2129 +django/contrib/gis/locale/dsb/LC_MESSAGES/django.mo,sha256=YZOA1XJqoU3rI5REairrs9f36Cet75NmC8WXdApx0Mc,2016 +django/contrib/gis/locale/dsb/LC_MESSAGES/django.po,sha256=w36vo0t-HzjhslJLo5xesc1vVfl94sNP3XyyDcETDn0,2177 +django/contrib/gis/locale/el/LC_MESSAGES/django.mo,sha256=g3SeFfO8xTxsvs2jKG9CI99fTnVa-WuBMNG0FFGc0s8,2402 +django/contrib/gis/locale/el/LC_MESSAGES/django.po,sha256=7MATPbwGZGgWabd9BdmUCwxc2iAG2aeac9ltKsieuME,2853 +django/contrib/gis/locale/en/LC_MESSAGES/django.mo,sha256=U0OV81NfbuNL9ctF-gbGUG5al1StqN-daB-F-gFBFC8,356 +django/contrib/gis/locale/en/LC_MESSAGES/django.po,sha256=lXk5x3FBMnRKocOgqDiya7yKeXZqk9gkibxyADRQjOU,2074 +django/contrib/gis/locale/en_AU/LC_MESSAGES/django.mo,sha256=IPn5kRqOvv5S7jpbIUw8PEUkHlyjEL-4GuOANd1iAzI,486 +django/contrib/gis/locale/en_AU/LC_MESSAGES/django.po,sha256=x_58HmrHRia2LoYhmmN_NLb1J3f7oTDvwumgTo0LowI,1494 +django/contrib/gis/locale/en_GB/LC_MESSAGES/django.mo,sha256=WkORQDOsFuV2bI7hwVsJr_JTWnDQ8ZaK-VYugqnLv3w,1369 +django/contrib/gis/locale/en_GB/LC_MESSAGES/django.po,sha256=KWPMoX-X-gQhb47zoVsa79-16-SiCGpO0s4xkcGv9z0,1910 +django/contrib/gis/locale/eo/LC_MESSAGES/django.mo,sha256=FFSZ58VHOog4-tDy88OISaaLXMaHVuFsIr3uevM-LGc,1878 +django/contrib/gis/locale/eo/LC_MESSAGES/django.po,sha256=oyMvu7r3BKLV9VDYQI6IgjumYusSOgynlSdN3dDrcPo,2156 +django/contrib/gis/locale/es/LC_MESSAGES/django.mo,sha256=JTo6frVHdq3bDY7IwpP5K6Znbb0NXMyVBv-AOQ6gd9s,2005 +django/contrib/gis/locale/es/LC_MESSAGES/django.po,sha256=3xK9yehM6kTSbulhvTenKXmlBeUnfgqM3_a7waiNit4,2465 +django/contrib/gis/locale/es_AR/LC_MESSAGES/django.mo,sha256=Z_2xqsHzQNSQWphm6jV9efFFjzHmkmuk2KfLZXx5E1k,2006 +django/contrib/gis/locale/es_AR/LC_MESSAGES/django.po,sha256=_PHHHfzhzPI5xaZwDH6Rd35KEbj1l1-9IyPLEENaw6E,2161 +django/contrib/gis/locale/es_CO/LC_MESSAGES/django.mo,sha256=mMnOZTrmWutn2Lwv2Y7GuoZIhIbPsMCXJkdmeatXZaM,1817 +django/contrib/gis/locale/es_CO/LC_MESSAGES/django.po,sha256=JF0-_eNt-BPJ__GqNoEj7iKEOV8htZHyX5kZue-PZO4,2349 +django/contrib/gis/locale/es_MX/LC_MESSAGES/django.mo,sha256=bC-uMgJXdbKHQ-w7ez-6vh9E_2YSgCF_LkOQlvb60BU,1441 +django/contrib/gis/locale/es_MX/LC_MESSAGES/django.po,sha256=MYO9fGclp_VvLG5tXDjXY3J_1FXI4lDv23rGElXAyjA,1928 +django/contrib/gis/locale/es_VE/LC_MESSAGES/django.mo,sha256=5YVIO9AOtmjky90DAXVyU0YltfQ4NLEpVYRTTk7SZ5o,486 +django/contrib/gis/locale/es_VE/LC_MESSAGES/django.po,sha256=R8suLsdDnSUEKNlXzow3O6WIT5NcboZoCjir9GfSTSQ,1494 +django/contrib/gis/locale/et/LC_MESSAGES/django.mo,sha256=-Gn24H3qyIcf3ptRe7Iin8sHc6JtkkFsmJF4DI1Wwhs,1872 +django/contrib/gis/locale/et/LC_MESSAGES/django.po,sha256=c-8desC8uDUy9UrX3IicuGICF2xAWPudgAprvS3G7jY,2223 +django/contrib/gis/locale/eu/LC_MESSAGES/django.mo,sha256=c2YYr77DeKdHWhpq6T472Hc1wpzYQ1fgKXELx7GMW_U,1888 +django/contrib/gis/locale/eu/LC_MESSAGES/django.po,sha256=HVR7BSXjUy3pphfPKp2uapaKVnQeb3chQIxcG5bMxHY,2147 +django/contrib/gis/locale/fa/LC_MESSAGES/django.mo,sha256=oSM2n6s-E4eomcHHZT6gY0PrhUFDr7Wijs3Qkr62jX0,2155 +django/contrib/gis/locale/fa/LC_MESSAGES/django.po,sha256=uUaUbYmjFcZ3mp9-FmGVT3zv47n54sWtzaXHWFSpMik,2507 +django/contrib/gis/locale/fi/LC_MESSAGES/django.mo,sha256=A1QOLEk9dFKcxlE2puSLmdDdFWRwGbSKsDGbKemUsCM,1839 +django/contrib/gis/locale/fi/LC_MESSAGES/django.po,sha256=IbtvFNK1bXmck5zZQqXNCDSiuXcGonNl8UcN0BfopFQ,2064 +django/contrib/gis/locale/fr/LC_MESSAGES/django.mo,sha256=LXchLaOY_bGIf25s_rQgWHOvEMD-l8_HAT5WtC0irfs,2058 +django/contrib/gis/locale/fr/LC_MESSAGES/django.po,sha256=FVuGpVTPP2-f4CZKL0UZwLSxy2WiDczw9_q3KRTbclQ,2258 +django/contrib/gis/locale/fy/LC_MESSAGES/django.mo,sha256=2kCnWU_giddm3bAHMgDy0QqNwOb9qOiEyCEaYo1WdqQ,476 +django/contrib/gis/locale/fy/LC_MESSAGES/django.po,sha256=7ncWhxC5OLhXslQYv5unWurhyyu_vRsi4bGflZ6T2oQ,1484 +django/contrib/gis/locale/ga/LC_MESSAGES/django.mo,sha256=m6Owcr-5pln54TXcZFAkYEYDjYiAkT8bGFyw4nowNHA,1420 +django/contrib/gis/locale/ga/LC_MESSAGES/django.po,sha256=I0kyTnYBPSdYr8RontzhGPShJhylVAdRLBGWRQr2E7g,1968 +django/contrib/gis/locale/gd/LC_MESSAGES/django.mo,sha256=w9d6GRaJMzeRVMzOuapvpPayOQmrFQEwPf8g4TXSatg,2022 +django/contrib/gis/locale/gd/LC_MESSAGES/django.po,sha256=2jXpd-BBQ7JVj2l9tWhIkUXw4ZZPnGJrvHjs442GEx8,2197 +django/contrib/gis/locale/gl/LC_MESSAGES/django.mo,sha256=vjZQqAw3rDSY8Tgv-12EOhsqfFlaEOB7mVBOH6YlXNo,1956 +django/contrib/gis/locale/gl/LC_MESSAGES/django.po,sha256=zhqF1InI8QaKhDLqjfTRUbMPaT9X3D1eI1ocV5FHGf4,2231 +django/contrib/gis/locale/he/LC_MESSAGES/django.mo,sha256=qaxQ0A76SO7GM5WDK0_3pAJDFzkvAtjSV8r1P4ySCVY,2135 +django/contrib/gis/locale/he/LC_MESSAGES/django.po,sha256=f8w5v4W7w47vH6Tq4HfMOX9jB4ab0oEXnpuJcDlk7Ak,2336 +django/contrib/gis/locale/hi/LC_MESSAGES/django.mo,sha256=3nsy5mxKTPtx0EpqBNA_TJXmLmVZ4BPUZG72ZEe8OPM,1818 +django/contrib/gis/locale/hi/LC_MESSAGES/django.po,sha256=jTFG2gqqYAQct9-to0xL2kUFQu-ebR4j7RGfxn4sBAg,2372 +django/contrib/gis/locale/hr/LC_MESSAGES/django.mo,sha256=0XrRj2oriNZxNhEwTryo2zdMf-85-4X7fy7OJhB5ub4,1549 +django/contrib/gis/locale/hr/LC_MESSAGES/django.po,sha256=iijzoBoD_EJ1n-a5ys5CKnjzZzG299zPoCN-REFkeqE,2132 +django/contrib/gis/locale/hsb/LC_MESSAGES/django.mo,sha256=oXaJFKOmRL_hRqAbghejIgZiq67bAnrOV0eFpoqmyW0,1991 +django/contrib/gis/locale/hsb/LC_MESSAGES/django.po,sha256=uktC4ibheBFFZVh0LVtRVUT3RnefGXVOVQddK70hdgg,2155 +django/contrib/gis/locale/hu/LC_MESSAGES/django.mo,sha256=dXlt0Oq_W45B_Foneh2FgpExduFanuG7ia0wKsYCUqs,1891 +django/contrib/gis/locale/hu/LC_MESSAGES/django.po,sha256=Ws1oB2MpVa90a0JNK2LxsZytKBuMMNwLx0DW1sem4Es,2210 +django/contrib/gis/locale/hy/LC_MESSAGES/django.mo,sha256=pi9oAP8fLCg8ssz7ADZ_p9HntyDtdQ1Mep6KsR5Glfs,2020 +django/contrib/gis/locale/hy/LC_MESSAGES/django.po,sha256=FKRbr93M2S4dLWes80CTZ1AucKW8MF5cw98i0s8qZo4,2260 +django/contrib/gis/locale/ia/LC_MESSAGES/django.mo,sha256=gSHcbhwZ2H1amTQbWw908L0aTniLzK8T2RVGsiHuKIY,1812 +django/contrib/gis/locale/ia/LC_MESSAGES/django.po,sha256=IyKoOfc6ZNtvpL8s-r4lv41wlsCyq8CGNoNp7uHWUGE,2122 +django/contrib/gis/locale/id/LC_MESSAGES/django.mo,sha256=dzDiuO47A6XWR3G-OrY-A2c-7ccp1oGLlKPyUO2Wlpg,1862 +django/contrib/gis/locale/id/LC_MESSAGES/django.po,sha256=KZVcWZ_X8x3LO5Z4V-hzSEsvE-BEHIZq5eWJlW1SwZs,2278 +django/contrib/gis/locale/io/LC_MESSAGES/django.mo,sha256=_yUgF2fBUxVAZAPNw2ROyWly5-Bq0niGdNEzo2qbp8k,464 +django/contrib/gis/locale/io/LC_MESSAGES/django.po,sha256=fgGJ1xzliMK0MlVoV9CQn_BuuS3Kl71Kh5YEybGFS0Y,1472 +django/contrib/gis/locale/is/LC_MESSAGES/django.mo,sha256=UQb3H5F1nUxJSrADpLiYe12TgRhYKCFQE5Xy13MzEqU,1350 +django/contrib/gis/locale/is/LC_MESSAGES/django.po,sha256=8QWtgdEZR7OUVXur0mBCeEjbXTBjJmE-DOiKe55FvMo,1934 +django/contrib/gis/locale/it/LC_MESSAGES/django.mo,sha256=8VddOMr-JMs5D-J5mq-UgNnhf98uutpoJYJKTr8E224,1976 +django/contrib/gis/locale/it/LC_MESSAGES/django.po,sha256=Vp1G-GChjjTsODwABsg5LbmR6_Z-KpslwkNUipuOqk4,2365 +django/contrib/gis/locale/ja/LC_MESSAGES/django.mo,sha256=wOKVU0VP4RggkIqCzXVwVG9BfAz1MNI_zrZ1F3Bp_5s,2032 +django/contrib/gis/locale/ja/LC_MESSAGES/django.po,sha256=h-rtKSrjuRU7CkcAlK7ZdD-1hOekrPCZpvya-MQKs7Y,2286 +django/contrib/gis/locale/ka/LC_MESSAGES/django.mo,sha256=iqWQ9j8yanPjDhwi9cNSktYgfLVnofIsdICnAg2Y_to,1991 +django/contrib/gis/locale/ka/LC_MESSAGES/django.po,sha256=rkM7RG0zxDN8vqyAudmk5nocajhOYP6CTkdJKu21Pf4,2571 +django/contrib/gis/locale/kk/LC_MESSAGES/django.mo,sha256=NtgQONp0UncUNvrh0W2R7u7Ja8H33R-a-tsQShWq-QI,1349 +django/contrib/gis/locale/kk/LC_MESSAGES/django.po,sha256=78OMHuerBJZJZVo9GjGJ1h5fwdLuSc_X03ZhSRibtf4,1979 +django/contrib/gis/locale/km/LC_MESSAGES/django.mo,sha256=T0aZIZ_gHqHpQyejnBeX40jdcfhrCOjgKjNm2hLrpNE,459 +django/contrib/gis/locale/km/LC_MESSAGES/django.po,sha256=7ARjFcuPQJG0OGLJu9pVfSiAwc2Q-1tT6xcLeKeom1c,1467 +django/contrib/gis/locale/kn/LC_MESSAGES/django.mo,sha256=EkJRlJJSHZJvNZJuOLpO4IIUEoyi_fpKwNWe0OGFcy4,461 +django/contrib/gis/locale/kn/LC_MESSAGES/django.po,sha256=MnsSftGvmgJgGfgayQUVDMj755z8ItkM9vBehORfYbk,1475 +django/contrib/gis/locale/ko/LC_MESSAGES/django.mo,sha256=TyIytTrPe4GO6lRsK1CW0wIdhbrwDHxlO_29OX6MoH4,1888 +django/contrib/gis/locale/ko/LC_MESSAGES/django.po,sha256=V5OQ0oW3zU8MMdlOJXk-4RQo0UV3cCAhgSMOaQRgttM,2296 +django/contrib/gis/locale/ky/LC_MESSAGES/django.mo,sha256=nvMSOW77P-YCRkQgrQUpM94FexqLEt8Et0jri2nm_Ec,2157 +django/contrib/gis/locale/ky/LC_MESSAGES/django.po,sha256=0qqO8QWgJXPJpZ900MVsHdw6wMZBa0tE5GN3KSGa58E,2372 +django/contrib/gis/locale/lb/LC_MESSAGES/django.mo,sha256=XAyZQUi8jDr47VpSAHp_8nQb0KvSMJHo5THojsToFdk,474 +django/contrib/gis/locale/lb/LC_MESSAGES/django.po,sha256=5rfudPpH4snSq2iVm9E81EBwM0S2vbkY2WBGhpuga1Q,1482 +django/contrib/gis/locale/lt/LC_MESSAGES/django.mo,sha256=AD69M-SBrmQ5qaFKXX6FYOOXLfhuWlQdOYcMlV0UClo,2036 +django/contrib/gis/locale/lt/LC_MESSAGES/django.po,sha256=1yXUj9Hf4D2iyl97HoRuJLkfnR7Z-WmOoIJil98Cy-M,2366 +django/contrib/gis/locale/lv/LC_MESSAGES/django.mo,sha256=ZNt2B2qukArT3gRZE2SNsKna5pf9-UcsTUbQ3UbbQKA,1978 +django/contrib/gis/locale/lv/LC_MESSAGES/django.po,sha256=CM5WUeTmm4pp5Y4E1Cm3aCwGmTHNSyjSU3B44dRYdHA,2215 +django/contrib/gis/locale/mk/LC_MESSAGES/django.mo,sha256=fLSXxmJFE9kYsKMiwWAXS-9TweB_yuWzAjR-y0eysvI,2518 +django/contrib/gis/locale/mk/LC_MESSAGES/django.po,sha256=P2IKvpaMOj5UvJX_Lz-PE0-1D7Kt_fYM5Amm3d5g6t4,2918 +django/contrib/gis/locale/ml/LC_MESSAGES/django.mo,sha256=Kl9okrE3AzTPa5WQ-IGxYVNSRo2y_VEdgDcOyJ_Je78,2049 +django/contrib/gis/locale/ml/LC_MESSAGES/django.po,sha256=PWg8atPKfOsnVxg_uro8zYO9KCE1UVhfy_zmCWG0Bdk,2603 +django/contrib/gis/locale/mn/LC_MESSAGES/django.mo,sha256=1wijPq8UzkTFoQwKkLSO7kLnDrvnqaO6atRKzPVpF78,2346 +django/contrib/gis/locale/mn/LC_MESSAGES/django.po,sha256=kV8Nac4J4_BruT1Q2ndJbOliTnqpQqUt9zfkG6P3rpw,2765 +django/contrib/gis/locale/mr/LC_MESSAGES/django.mo,sha256=sO2E__g61S0p5I6aEwnoAsA3epxv7_Jn55TyF0PZCUA,468 +django/contrib/gis/locale/mr/LC_MESSAGES/django.po,sha256=McWaLXfWmYTDeeDbIOrV80gwnv07KCtNIt0OXW_v7vw,1476 +django/contrib/gis/locale/ms/LC_MESSAGES/django.mo,sha256=5_xS-XXVyw0cxvDzUIus5JImr0dkcswait04e7TrUtY,1828 +django/contrib/gis/locale/ms/LC_MESSAGES/django.po,sha256=I8rMkUEfsbjf-dWUuXyhYwCXhyX8AS3jjOKinAh7q2Q,1956 +django/contrib/gis/locale/my/LC_MESSAGES/django.mo,sha256=e6G8VbCCthUjV6tV6PRCy_ZzsXyZ-1OYjbYZIEShbXI,525 +django/contrib/gis/locale/my/LC_MESSAGES/django.po,sha256=R3v1S-904f8FWSVGHe822sWrOJI6cNJIk93-K7_E_1c,1580 +django/contrib/gis/locale/nb/LC_MESSAGES/django.mo,sha256=mx9uGqo5w_uRBWHswuEKoI-U-RX_Xvx_qck5ForI63Y,1808 +django/contrib/gis/locale/nb/LC_MESSAGES/django.po,sha256=LVjQsJxXdDBuKS5D7BEJ10C9OE8x3g0f9ewgjoG6fbY,2039 +django/contrib/gis/locale/ne/LC_MESSAGES/django.mo,sha256=nB-Ta8w57S6hIAhAdWZjDT0Dg6JYGbAt5FofIhJT7k8,982 +django/contrib/gis/locale/ne/LC_MESSAGES/django.po,sha256=eMH6uKZZZYn-P3kmHumiO4z9M4923s9tWGhHuJ0eWuI,1825 +django/contrib/gis/locale/nl/LC_MESSAGES/django.mo,sha256=ScPsjM7aMa8PwcbxliFgqfS7_WyOuTGmODGAZY85UM4,1897 +django/contrib/gis/locale/nl/LC_MESSAGES/django.po,sha256=zoUzuPhO4XGlrhmRluXNRMpjD7lEIjAW8TufBqAOO4o,2408 +django/contrib/gis/locale/nn/LC_MESSAGES/django.mo,sha256=P1RU0OICBDeHHtX6rCSB4xXgS4Qn97LqoxJ8phgiMDs,1830 +django/contrib/gis/locale/nn/LC_MESSAGES/django.po,sha256=-mkHmKp3b76uZlFOG3lFLp2nEFtBRV_4ThDPQmUWtX4,2027 +django/contrib/gis/locale/os/LC_MESSAGES/django.mo,sha256=02NpGC8WPjxmPqQkfv9Kj2JbtECdQCtgecf_Tjk1CZc,1594 +django/contrib/gis/locale/os/LC_MESSAGES/django.po,sha256=JBIsv5nJg3Wof7Xy7odCI_xKRBLN_Hlbb__kNqNW4Xw,2161 +django/contrib/gis/locale/pa/LC_MESSAGES/django.mo,sha256=JR1NxG5_h_dFE_7p6trBWWIx-QqWYIgfGomnjaCsWAA,1265 +django/contrib/gis/locale/pa/LC_MESSAGES/django.po,sha256=Ejd_8dq_M0E9XFijk0qj4oC-8_oe48GWWHXhvOrFlnY,1993 +django/contrib/gis/locale/pl/LC_MESSAGES/django.mo,sha256=KHar168QJ7Mj0419885rkyRXvWXkICAi0hUbb8KssY8,2045 +django/contrib/gis/locale/pl/LC_MESSAGES/django.po,sha256=cfeYjcF9R8VKujBMGLx_1z9zDY19DPCjUw5FpHuBIqs,2487 +django/contrib/gis/locale/pt/LC_MESSAGES/django.mo,sha256=sE5PPOHzfT8QQXuV5w0m2pnBTRhKYs_vFhk8p_A4Jg0,2036 +django/contrib/gis/locale/pt/LC_MESSAGES/django.po,sha256=TFt6Oj1NlCM3pgs2dIgFZR3S3y_g7oR7S-XRBlM4924,2443 +django/contrib/gis/locale/pt_BR/LC_MESSAGES/django.mo,sha256=5HGIao480s3B6kXtSmdy1AYjGUZqbYuZ9Eapho_jkTk,1976 +django/contrib/gis/locale/pt_BR/LC_MESSAGES/django.po,sha256=4-2WPZT15YZPyYbH7xnBRc7A8675875kVFjM9tr1o5U,2333 +django/contrib/gis/locale/ro/LC_MESSAGES/django.mo,sha256=jncf415WRI-GaemNGtbXITeYpx2zbokFNfQkONIOSO4,1770 +django/contrib/gis/locale/ro/LC_MESSAGES/django.po,sha256=5Xb2c11mwOdsd1D8SZC5u6nsuNjWEtdT1hslrQBfxP0,2181 +django/contrib/gis/locale/ru/LC_MESSAGES/django.mo,sha256=j9DEE5SVvEXWBj_PtR9_1IsaE-YCq4iOBcaiyHHqOEo,2481 +django/contrib/gis/locale/ru/LC_MESSAGES/django.po,sha256=fgj-PmNJ88IsjUUq7x9W6KSwXWdmnEq1PBlWsLFhzwE,2835 +django/contrib/gis/locale/sk/LC_MESSAGES/django.mo,sha256=FQy4gMIxrXNm42pvJ61q4ZfG0Ce98gv78b2I0vYN2CY,1980 +django/contrib/gis/locale/sk/LC_MESSAGES/django.po,sha256=z7uy3S2VXGZKMfgFLISYUPUb-zyEYXqlDgL_ODmb_4w,2315 +django/contrib/gis/locale/sl/LC_MESSAGES/django.mo,sha256=Ha88TShV2Bt_Jmvlkkc81CUkuV2iKfhGjzpD7KLMhv8,1972 +django/contrib/gis/locale/sl/LC_MESSAGES/django.po,sha256=B81yHSMjOYevk35kC4JEi4Ua3axjadkFW8aRuMnj6P0,2319 +django/contrib/gis/locale/sq/LC_MESSAGES/django.mo,sha256=hTehi3p1Qf7RCqK4vvcL-yoV7GVdbcokLN_5RGtmivE,1660 +django/contrib/gis/locale/sq/LC_MESSAGES/django.po,sha256=qnNVwZ69HLsTRC5GVYtVkIcZTCT_lNGjlDUibpCefr8,2037 +django/contrib/gis/locale/sr/LC_MESSAGES/django.mo,sha256=bM996RqI1wt4qHsUaGXoEO3fnaSZdjVD2TvUFDp5dVk,2365 +django/contrib/gis/locale/sr/LC_MESSAGES/django.po,sha256=hunakYgljjOiiYF98ZzFzIHTkIAGQM_IJLiLfmlR86Q,2628 +django/contrib/gis/locale/sr_Latn/LC_MESSAGES/django.mo,sha256=kniIObavM7XKqD5vcglrbcD8jqANKg7hN6AP4cIVAI0,1981 +django/contrib/gis/locale/sr_Latn/LC_MESSAGES/django.po,sha256=A2NsZJvk2Cckg8OS3yW_T11Tcv5-zgGEHcDRJpvE8Zg,2206 +django/contrib/gis/locale/sv/LC_MESSAGES/django.mo,sha256=CowUAoL4t4np5cBndBNM-a4Wu5oD899nVfifMOLz6xQ,1880 +django/contrib/gis/locale/sv/LC_MESSAGES/django.po,sha256=Xyzc8X3vwQ3wWfS4_5mpwFXPPAeCx4mODYFq3Kba04g,2252 +django/contrib/gis/locale/sw/LC_MESSAGES/django.mo,sha256=uBhpGHluGwYpODTE-xhdJD2e6PHleN07wLE-kjrXr_M,1426 +django/contrib/gis/locale/sw/LC_MESSAGES/django.po,sha256=nHXQQMYYXT1ec3lIBxQIDIAwLtXucX47M4Cozy08kko,1889 +django/contrib/gis/locale/ta/LC_MESSAGES/django.mo,sha256=Rboo36cGKwTebe_MiW4bOiMsRO2isB0EAyJJcoy_F6s,466 +django/contrib/gis/locale/ta/LC_MESSAGES/django.po,sha256=sLYW8_5BSVoSLWUr13BbKRe0hNJ_cBMEtmjCPBdTlAk,1474 +django/contrib/gis/locale/te/LC_MESSAGES/django.mo,sha256=xDkaSztnzQ33Oc-GxHoSuutSIwK9A5Bg3qXEdEvo4h4,824 +django/contrib/gis/locale/te/LC_MESSAGES/django.po,sha256=nYryhktJumcwtZDGZ43xBxWljvdd-cUeBrAYFZOryVg,1772 +django/contrib/gis/locale/tg/LC_MESSAGES/django.mo,sha256=6Jyeaq1ORsnE7Ceh_rrhbfslFskGe12Ar-dQl6NFyt0,611 +django/contrib/gis/locale/tg/LC_MESSAGES/django.po,sha256=9c1zPt7kz1OaRJPPLdqjQqO8MT99KtS9prUvoPa9qJk,1635 +django/contrib/gis/locale/th/LC_MESSAGES/django.mo,sha256=0kekAr7eXc_papwPAxEZ3TxHOBg6EPzdR3q4hmAxOjg,1835 +django/contrib/gis/locale/th/LC_MESSAGES/django.po,sha256=WJPdoZjLfvepGGMhfBB1EHCpxtxxfv80lRjPG9kGErM,2433 +django/contrib/gis/locale/tr/LC_MESSAGES/django.mo,sha256=5EKMteFT0WXGacwXnRt5Eak00kbtYmqskkuCg2rGvyc,1904 +django/contrib/gis/locale/tr/LC_MESSAGES/django.po,sha256=DSIty_3V3G_Pv498EU3H60-5jS0b1S5tPwR_fkwpq98,2180 +django/contrib/gis/locale/tt/LC_MESSAGES/django.mo,sha256=cGVPrWCe4WquVV77CacaJwgLSnJN0oEAepTzNMD-OWk,1470 +django/contrib/gis/locale/tt/LC_MESSAGES/django.po,sha256=98yeRs-JcMGTyizOpEuQenlnWJMYTR1-rG3HGhKCykk,2072 +django/contrib/gis/locale/udm/LC_MESSAGES/django.mo,sha256=I6bfLvRfMn79DO6bVIGfYSVeZY54N6c8BNO7OyyOOsw,462 +django/contrib/gis/locale/udm/LC_MESSAGES/django.po,sha256=B1PCuPYtNOrrhu4fKKJgkqxUrcEyifS2Y3kw-iTmSIk,1470 +django/contrib/gis/locale/ug/LC_MESSAGES/django.mo,sha256=cKr7ETLbYR1nMm2iJsQwZYKz8U5aP2CX5RdhbKW2gh4,2360 +django/contrib/gis/locale/ug/LC_MESSAGES/django.po,sha256=d1P7kH2ETJ9n34d9ALE0tHWw_1_fq7fuiLBNK2IlM10,2529 +django/contrib/gis/locale/uk/LC_MESSAGES/django.mo,sha256=jsJMgEt6VXoSjksQGngxaywARUsk5tiIKJfUw9kgEBw,2513 +django/contrib/gis/locale/uk/LC_MESSAGES/django.po,sha256=NNAUWdHmhsWtrPIgddjT03k4IeJUlUCYM7n78DisFQw,3015 +django/contrib/gis/locale/ur/LC_MESSAGES/django.mo,sha256=tB5tz7EscuE9IksBofNuyFjk89-h5X7sJhCKlIho5SY,1410 +django/contrib/gis/locale/ur/LC_MESSAGES/django.po,sha256=16m0t10Syv76UcI7y-EXfQHETePmrWX4QMVfyeuX1fQ,2007 +django/contrib/gis/locale/vi/LC_MESSAGES/django.mo,sha256=NT5T0FRCC2XINdtaCFCVUxb5VRv8ta62nE8wwSHGTrc,1384 +django/contrib/gis/locale/vi/LC_MESSAGES/django.po,sha256=y77GtqH5bv1wR78xN5JLHusmQzoENTH9kLf9Y3xz5xk,1957 +django/contrib/gis/locale/zh_Hans/LC_MESSAGES/django.mo,sha256=NvNiRwwuqrmOWqiiuYhoxTs3CXb9Zq0-R_2YVhY6n34,1760 +django/contrib/gis/locale/zh_Hans/LC_MESSAGES/django.po,sha256=jXKQKr3GOjL5LJ7Mv1O3zpn2hr_sA_31ote8Pzk9tOU,2232 +django/contrib/gis/locale/zh_Hant/LC_MESSAGES/django.mo,sha256=3P8QCJZnzJe4I-D5FKtnGYJWB70wFUDppXV7H5Pf404,1928 +django/contrib/gis/locale/zh_Hant/LC_MESSAGES/django.po,sha256=hxXDuPh9-Lpu-_Kt1zCPxcnNV-q8kVAq_WDC6OetHT8,2234 +django/contrib/gis/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/gis/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/gis/management/commands/inspectdb.py,sha256=8WhDOBICFAbLFu7kwAAS4I5pNs_p1BrCv8GJYI3S49k,760 +django/contrib/gis/management/commands/ogrinspect.py,sha256=XnWAbLxRxTSvbKSvjgePN7D1o_Ep4qWkvMwVrG1TpYY,6071 +django/contrib/gis/measure.py,sha256=SHaYvDHsvTFAf7F19EtY61dJeyHwI0BY4vUXXzbaPvc,12506 +django/contrib/gis/ptr.py,sha256=NeIBB-plwO61wGOOxGg7fFyVXI4a5vbAGUdaJ_Fmjqo,1312 +django/contrib/gis/serializers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/gis/serializers/geojson.py,sha256=lgwJ0xh-mjMVwJi_UpHH7MTKtjH_7txIQyLG-G2C4-A,3000 +django/contrib/gis/shortcuts.py,sha256=aa9zFjVU38qaEvRc0vAH_j2AgAERlI01rphYLHbc7Tg,1027 +django/contrib/gis/sitemaps/__init__.py,sha256=Tjj057omOVcoC5Fb8ITEYVhLm0HcVjrZ1Mbz_tKoD1A,138 +django/contrib/gis/sitemaps/kml.py,sha256=CUn_KKVrwGg2ZmmDcWosBc0QFuJp8hHpeNRCcloVk1U,2573 +django/contrib/gis/sitemaps/views.py,sha256=AFV1ay-oFftFC-IszzeKz3JAGzE0TOCH8pN1cwtg7yI,2353 +django/contrib/gis/static/gis/css/ol3.css,sha256=DmCfOuPC1wUs0kioWxIpSausvF6AYUlURbJLNGyvngA,773 +django/contrib/gis/static/gis/img/draw_line_off.svg,sha256=6XW83xsR5-Guh27UH3y5UFn9y9FB9T_Zc4kSPA-xSOI,918 +django/contrib/gis/static/gis/img/draw_line_on.svg,sha256=Hx-pXu4ped11esG6YjXP1GfZC5q84zrFQDPUo1C7FGA,892 +django/contrib/gis/static/gis/img/draw_point_off.svg,sha256=PICrywZPwuBkaQAKxR9nBJ0AlfTzPHtVn_up_rSiHH4,803 +django/contrib/gis/static/gis/img/draw_point_on.svg,sha256=raGk3oc8w87rJfLdtZ4nIXJyU3OChCcTd4oH-XAMmmM,803 +django/contrib/gis/static/gis/img/draw_polygon_off.svg,sha256=gnVmjeZE2jOvjfyx7mhazMDBXJ6KtSDrV9f0nSzkv3A,981 +django/contrib/gis/static/gis/img/draw_polygon_on.svg,sha256=ybJ9Ww7-bsojKQJtjErLd2cCOgrIzyqgIR9QNhH_ZfA,982 +django/contrib/gis/static/gis/js/OLMapWidget.js,sha256=wNkqWj8CdsMqxBYI57v0SKl-2Ay12ckFvq3eMk1bsg4,9356 +django/contrib/gis/templates/gis/kml/base.kml,sha256=VYnJaGgFVHRzDjiFjbcgI-jxlUos4B4Z1hx_JeI2ZXU,219 +django/contrib/gis/templates/gis/kml/placemarks.kml,sha256=TEC81sDL9RK2FVeH0aFJTwIzs6_YWcMeGnHkACJV1Uc,360 +django/contrib/gis/templates/gis/openlayers-osm.html,sha256=TeiUqCjt73W8Hgrp_6zAtk_ZMBxskNN6KHSmnJ1-GD4,378 +django/contrib/gis/templates/gis/openlayers.html,sha256=Ou-Cwe58NHmSyOuMeCNixrys_SCmd2RzMecNeAW67_I,1587 +django/contrib/gis/utils/__init__.py,sha256=2MFbWuhQauwW3NvtRFEEQzZMK5CEeVRW9HQpNFBDsG4,682 +django/contrib/gis/utils/layermapping.py,sha256=hSQ-sBvqD0Qy3_xhnOTYXa6puJDc7p20xn9LpHQGsew,28914 +django/contrib/gis/utils/ogrinfo.py,sha256=6m3KaRzLoZtQ0OSrpRkaFIQXi9YOXTkQcYeqYb0S0nw,1956 +django/contrib/gis/utils/ogrinspect.py,sha256=nxKd1cufjbP86uJcsaNb1c3n9IA-uy4ltQjLGgPjB1E,9169 +django/contrib/gis/utils/srs.py,sha256=UXsbxW0cQzdnPKO0d9E5K2HPdekdab5NaLZWNOUq-zk,2962 +django/contrib/gis/views.py,sha256=zdCV8QfUVfxEFGxESsUtCicsbSVtZNI_IXybdmsHKiM,714 +django/contrib/humanize/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/humanize/apps.py,sha256=LH3PTbB4V1gbBc8nmCw3BsSuA8La0fNOb4cSISvJAwI,194 +django/contrib/humanize/locale/af/LC_MESSAGES/django.mo,sha256=yFvTzvROTnoZF4ZPAs3z9ireOuOf5gTfECEUdGa4EkM,4224 +django/contrib/humanize/locale/af/LC_MESSAGES/django.po,sha256=m8GF4T4HY4aGsfadUdu04yc7cq9Sm-K5LM-OFjTrq5Y,7541 +django/contrib/humanize/locale/ar/LC_MESSAGES/django.mo,sha256=PokPfBR8w4AbRtNNabl5vO8r5E8_egHvFBjKp4CCvO4,7510 +django/contrib/humanize/locale/ar/LC_MESSAGES/django.po,sha256=QGW-kx-87DlPMGr5l_Eb6Ge-x4tkz2PuwHDe3EIkIQg,12326 +django/contrib/humanize/locale/ar_DZ/LC_MESSAGES/django.mo,sha256=NwCrL5FX_xdxYdqkW_S8tmU8ktDM8LqimmUvkt8me74,9155 +django/contrib/humanize/locale/ar_DZ/LC_MESSAGES/django.po,sha256=tt0AxhohGX79OQ_lX1S5soIo-iSCC07SdAhPpy0O7Q4,15234 +django/contrib/humanize/locale/ast/LC_MESSAGES/django.mo,sha256=WvBk8V6g1vgzGqZ_rR-4p7SMh43PFnDnRhIS9HSwdoQ,3468 +django/contrib/humanize/locale/ast/LC_MESSAGES/django.po,sha256=S9lcUf2y5wR8Ufa-Rlz-M73Z3bMo7zji_63cXwtDK2I,5762 +django/contrib/humanize/locale/az/LC_MESSAGES/django.mo,sha256=h7H_-Y-3YiP_98cdIz953QFmQJq86bHfN-U5pXjQLg8,4345 +django/contrib/humanize/locale/az/LC_MESSAGES/django.po,sha256=prn_LypmpP3By-EYF3_DMXtjrn4o60fpMi-SC9uD8fE,7770 +django/contrib/humanize/locale/be/LC_MESSAGES/django.mo,sha256=7KyJKhNqMqv32CPdJi01RPLBefOVCQW-Gx6-Vf9JVrs,6653 +django/contrib/humanize/locale/be/LC_MESSAGES/django.po,sha256=2mbReEHyXhmZysqhSmaT6A2XCHn8mYb2R_O16TMGCAo,10666 +django/contrib/humanize/locale/bg/LC_MESSAGES/django.mo,sha256=jCdDIbqWlhOs-4gML44wSRIXJQxypfak6ByRG_reMsk,4823 +django/contrib/humanize/locale/bg/LC_MESSAGES/django.po,sha256=v2ih4-pL1cdDXaa3uXm9FxRjRKyULLGyz78Q91eKEG8,8267 +django/contrib/humanize/locale/bn/LC_MESSAGES/django.mo,sha256=jbL4ucZxxtexI10jgldtgnDie3I23XR3u-PrMMMqP6U,4026 +django/contrib/humanize/locale/bn/LC_MESSAGES/django.po,sha256=0l4yyy7q3OIWyFk_PW0y883Vw2Pmu48UcnLM9OBxB68,6545 +django/contrib/humanize/locale/br/LC_MESSAGES/django.mo,sha256=V_tPVAyQzVdDwWPNlVGWmlVJjmVZfbh35alkwsFlCNU,5850 +django/contrib/humanize/locale/br/LC_MESSAGES/django.po,sha256=BcAqEV2JpF0hiCQDttIMblp9xbB7zoHsmj7fJFV632k,12245 +django/contrib/humanize/locale/bs/LC_MESSAGES/django.mo,sha256=1-RNRHPgZR_9UyiEn9Djp4mggP3fywKZho45E1nGMjM,1416 +django/contrib/humanize/locale/bs/LC_MESSAGES/django.po,sha256=M017Iu3hyXmINZkhCmn2he-FB8rQ7rXN0KRkWgrp7LI,5498 +django/contrib/humanize/locale/ca/LC_MESSAGES/django.mo,sha256=WDvXis2Y1ivSq6NdJgddO_WKbz8w5MpVpkT4sq-pWXI,4270 +django/contrib/humanize/locale/ca/LC_MESSAGES/django.po,sha256=AD3h2guGADdp1f9EcbP1vc1lmfDOL8-1qQfwvXa6I04,7731 +django/contrib/humanize/locale/ckb/LC_MESSAGES/django.mo,sha256=Mqv3kRZrOjWtTstmtOEqIJsi3vevf_hZUfYEetGxO7w,5021 +django/contrib/humanize/locale/ckb/LC_MESSAGES/django.po,sha256=q_7p7pEyV_NTw9eBvcztKlSFW7ykl0CIsNnA9g5oy20,8317 +django/contrib/humanize/locale/cs/LC_MESSAGES/django.mo,sha256=VFyZcn19aQUXhVyh2zo2g3PAuzOO38Kx9fMFOCCxzMc,5479 +django/contrib/humanize/locale/cs/LC_MESSAGES/django.po,sha256=mq3LagwA9hyWOGy76M9n_rD4p3wuVk6oQsneB9CF99w,9527 +django/contrib/humanize/locale/cy/LC_MESSAGES/django.mo,sha256=VjJiaUUhvX9tjOEe6x2Bdp7scvZirVcUsA4-iE2-ElQ,5241 +django/contrib/humanize/locale/cy/LC_MESSAGES/django.po,sha256=sylmceSq-NPvtr_FjklQXoBAfueKu7hrjEpMAsVbQC4,7813 +django/contrib/humanize/locale/da/LC_MESSAGES/django.mo,sha256=vfDHopmWFAomwqmmCX3wfmX870-zzVbgUFC6I77n9tE,4316 +django/contrib/humanize/locale/da/LC_MESSAGES/django.po,sha256=v7Al6UOkbYB1p7m8kOe-pPRIAoyWemoyg_Pm9bD5Ldc,7762 +django/contrib/humanize/locale/de/LC_MESSAGES/django.mo,sha256=aOUax9csInbXnjAJc3jq4dcW_9H-6ueVI-TtKz2b9q0,4364 +django/contrib/humanize/locale/de/LC_MESSAGES/django.po,sha256=gW3OfOfoVMvpVudwghKCYztkLrCIPbbcriZjBNnRyGo,7753 +django/contrib/humanize/locale/dsb/LC_MESSAGES/django.mo,sha256=OVKcuW9ZXosNvP_3A98WsIIk_Jl6U_kv3zOx4pvwh-g,5588 +django/contrib/humanize/locale/dsb/LC_MESSAGES/django.po,sha256=VimcsmobK3VXTbbTasg6osWDPOIZ555uimbUoUfNco4,9557 +django/contrib/humanize/locale/el/LC_MESSAGES/django.mo,sha256=o-yjhpzyGRbbdMzwUcG_dBP_FMEMZevm7Wz1p4Wd-pg,6740 +django/contrib/humanize/locale/el/LC_MESSAGES/django.po,sha256=UbD5QEw_-JNoNETaOyDfSReirkRsHnlHeSsZF5hOSkI,10658 +django/contrib/humanize/locale/en/LC_MESSAGES/django.mo,sha256=U0OV81NfbuNL9ctF-gbGUG5al1StqN-daB-F-gFBFC8,356 +django/contrib/humanize/locale/en/LC_MESSAGES/django.po,sha256=PKUuSyK8VzVdyyCpOXAffSBK7mFSiGuumzMmttS5yfM,9057 +django/contrib/humanize/locale/en_AU/LC_MESSAGES/django.mo,sha256=QFf4EgAsGprbFetnwogmj8vDV7SfGq1E3vhL9D8xTTM,918 +django/contrib/humanize/locale/en_AU/LC_MESSAGES/django.po,sha256=Bnfesr1_T9sa31qkKOMunwKKXbnFzZJhzV8rYC_pdSE,6532 +django/contrib/humanize/locale/en_GB/LC_MESSAGES/django.mo,sha256=mkx192XQM3tt1xYG8EOacMfa-BvgzYCbSsJQsWZGeAo,3461 +django/contrib/humanize/locale/en_GB/LC_MESSAGES/django.po,sha256=MArKzXxY1104jxaq3kvDZs2WzOGYxicfJxFKsLzFavw,5801 +django/contrib/humanize/locale/eo/LC_MESSAGES/django.mo,sha256=b47HphXBi0cax_reCZiD3xIedavRHcH2iRG8pcwqb54,5386 +django/contrib/humanize/locale/eo/LC_MESSAGES/django.po,sha256=oN1YqOZgxKY3L1a1liluhM6X5YA5bawg91mHF_Vfqx8,9095 +django/contrib/humanize/locale/es/LC_MESSAGES/django.mo,sha256=z5ZCmAG4jGYleEE6pESMXihlESRQPkTEo2vIedXdjjI,5005 +django/contrib/humanize/locale/es/LC_MESSAGES/django.po,sha256=WwykwsBM_Q_xtA2vllIbcFSO7eUB72r56AG4ITwM5VM,8959 +django/contrib/humanize/locale/es_AR/LC_MESSAGES/django.mo,sha256=-btiXH3B5M1qkAsW9D5I742Gt9GcJs5VC8ZhJ_DKkGY,4425 +django/contrib/humanize/locale/es_AR/LC_MESSAGES/django.po,sha256=UsiuRj-eq-Vl41wNZGw9XijCMEmcXhcGrMTPWgZn4LA,7858 +django/contrib/humanize/locale/es_CO/LC_MESSAGES/django.mo,sha256=2GhQNtNOjK5mTov5RvnuJFTYbdoGBkDGLxzvJ8Vsrfs,4203 +django/contrib/humanize/locale/es_CO/LC_MESSAGES/django.po,sha256=JBf2fHO8jWi6dFdgZhstKXwyot_qT3iJBixQZc3l330,6326 +django/contrib/humanize/locale/es_MX/LC_MESSAGES/django.mo,sha256=82DL2ztdq10X5RIceshK1nO99DW5628ZIjaN8Xzp9ok,3939 +django/contrib/humanize/locale/es_MX/LC_MESSAGES/django.po,sha256=-O7AQluA5Kce9-bd04GN4tfQKoCxb8Sa7EZR6TZBCdM,6032 +django/contrib/humanize/locale/es_VE/LC_MESSAGES/django.mo,sha256=cJECzKpD99RRIpVFKQW65x0Nvpzrm5Fuhfi-nxOWmkM,942 +django/contrib/humanize/locale/es_VE/LC_MESSAGES/django.po,sha256=tDdYtvRILgeDMgZqKHSebe7Z5ZgI1bZhDdvGVtj_anM,4832 +django/contrib/humanize/locale/et/LC_MESSAGES/django.mo,sha256=_vLDxD-e-pBY7vs6gNkhFZNGYu_dAeETVMKGsjjWOHg,4406 +django/contrib/humanize/locale/et/LC_MESSAGES/django.po,sha256=u0tSkVYckwXUv1tVfe1ODdZ8tJ2wUkS0Vv8pakJ8eBM,7915 +django/contrib/humanize/locale/eu/LC_MESSAGES/django.mo,sha256=k_3NJUSo2JS5OZeQmGuCx0PEa_Xy1DvKIknoSv5EhWo,4312 +django/contrib/humanize/locale/eu/LC_MESSAGES/django.po,sha256=YuD0UCpc-tE1l1MS4gLLgDXhWGoEH6b2JYkgCZyAPds,7733 +django/contrib/humanize/locale/fa/LC_MESSAGES/django.mo,sha256=N32l1DsPALoSGe9GtJ5baIo0XUDm8U09JhcHr0lXtw4,4656 +django/contrib/humanize/locale/fa/LC_MESSAGES/django.po,sha256=YsYRnmvABepSAOgEj6dRvdY_jYZqJb0_dbQ_6daiJAQ,8228 +django/contrib/humanize/locale/fi/LC_MESSAGES/django.mo,sha256=FJfyLFkz-oAz9e15e1aQUct7CJ2EJqSkZKh_ztDxtic,4425 +django/contrib/humanize/locale/fi/LC_MESSAGES/django.po,sha256=j5Z5t9zX1kePdM_Es1hu9AKOpOrijVWTsS2t19CIiaE,7807 +django/contrib/humanize/locale/fr/LC_MESSAGES/django.mo,sha256=pHHD7DV36bC86CKXWUpWUp3NtKuqWu9_YXU04sE6ib4,5125 +django/contrib/humanize/locale/fr/LC_MESSAGES/django.po,sha256=SyN1vUt8zDG-iSTDR4OH1B_CbvKMM2YaMJ2_s-FEyog,8812 +django/contrib/humanize/locale/fy/LC_MESSAGES/django.mo,sha256=YQQy7wpjBORD9Isd-p0lLzYrUgAqv770_56-vXa0EOc,476 +django/contrib/humanize/locale/fy/LC_MESSAGES/django.po,sha256=pPvcGgBWiZwQ5yh30OlYs-YZUd_XsFro71T9wErVv0M,4732 +django/contrib/humanize/locale/ga/LC_MESSAGES/django.mo,sha256=AOEiBNOak_KQkBeGyUpTNO12zyg3CiK66h4kMoS15_0,5112 +django/contrib/humanize/locale/ga/LC_MESSAGES/django.po,sha256=jTXihbd-ysAUs0TEKkOBmXJJj69V0cFNOHM6VbcPCWw,11639 +django/contrib/humanize/locale/gd/LC_MESSAGES/django.mo,sha256=wHsBVluXm4DW7iWxGHMHexqG9ovXEvgcaXvsmvkNHSE,5838 +django/contrib/humanize/locale/gd/LC_MESSAGES/django.po,sha256=CmmpKK7me-Ujitgx2IVkOcJyZOvie6XEBS7wCY4xZQ0,9802 +django/contrib/humanize/locale/gl/LC_MESSAGES/django.mo,sha256=LbJABG0-USW2C5CQro6WcPlPwT7I1BfuKGi_VFNhJIU,4345 +django/contrib/humanize/locale/gl/LC_MESSAGES/django.po,sha256=caidyTAFJ5iZ-tpEp0bflpUx0xlaH2jIYmPKxCVzlGE,7772 +django/contrib/humanize/locale/he/LC_MESSAGES/django.mo,sha256=phFZMDohKT86DUtiAlnZslPFwSmpcpxTgZaXb8pGohc,5875 +django/contrib/humanize/locale/he/LC_MESSAGES/django.po,sha256=xhEZYcK-fg_mHMyGCEZXEwbd6FvutaGvkDyHTET-sic,9970 +django/contrib/humanize/locale/hi/LC_MESSAGES/django.mo,sha256=qrzm-6vXIUsxA7nOxa-210-6iO-3BPBj67vKfhTOPrY,4131 +django/contrib/humanize/locale/hi/LC_MESSAGES/django.po,sha256=BrypbKaQGOyY_Gl1-aHXiBVlRqrbSjGfZ2OK8omj_9M,6527 +django/contrib/humanize/locale/hr/LC_MESSAGES/django.mo,sha256=29XTvFJHex31hbu2qsOfl5kOusz-zls9eqlxtvw_H0s,1274 +django/contrib/humanize/locale/hr/LC_MESSAGES/django.po,sha256=OuEH4fJE6Fk-s0BMqoxxdlUAtndvvKK7N8Iy-9BP3qA,5424 +django/contrib/humanize/locale/hsb/LC_MESSAGES/django.mo,sha256=a1DqdiuRfFSfSrD8IvzQmZdzE0dhkxDChFddrmt3fjA,5679 +django/contrib/humanize/locale/hsb/LC_MESSAGES/django.po,sha256=V5aRblcqKii4RXSQO87lyoQwwvxL59T3m4-KOBTx4bc,9648 +django/contrib/humanize/locale/hu/LC_MESSAGES/django.mo,sha256=7ZMxGa5FaUdjRtbawYzwwhWIroON8NNXknQ3frKUabw,4313 +django/contrib/humanize/locale/hu/LC_MESSAGES/django.po,sha256=5yWfXwvJQQuDoENkiytuKXFjsNW-lS2-EFThVnYWHbI,7672 +django/contrib/humanize/locale/hy/LC_MESSAGES/django.mo,sha256=C1yx1DrYTrZ7WkOzZ5hvunphWABvGX-DqXbChNQ5_yg,1488 +django/contrib/humanize/locale/hy/LC_MESSAGES/django.po,sha256=MGbuYylBt1C5hvSlktydD4oMLZ1Sjzj7DL_nl7uluTg,7823 +django/contrib/humanize/locale/ia/LC_MESSAGES/django.mo,sha256=d0m-FddFnKp08fQYQSC9Wr6M4THVU7ibt3zkIpx_Y_A,4167 +django/contrib/humanize/locale/ia/LC_MESSAGES/django.po,sha256=qX6fAZyn54hmtTU62oJcHF8p4QcYnoO2ZNczVjvjOeE,6067 +django/contrib/humanize/locale/id/LC_MESSAGES/django.mo,sha256=AdUmhfkQOV9Le4jXQyQSyd5f2GqwNt-oqnJV-WVELVw,3885 +django/contrib/humanize/locale/id/LC_MESSAGES/django.po,sha256=lMnTtM27j1EWg1i9d7NzAeueo7mRztGVfNOXtXdZVjw,7021 +django/contrib/humanize/locale/io/LC_MESSAGES/django.mo,sha256=nMu5JhIy8Fjie0g5bT8-h42YElCiS00b4h8ej_Ie-w0,464 +django/contrib/humanize/locale/io/LC_MESSAGES/django.po,sha256=RUs8JkpT0toKOLwdv1oCbcBP298EOk02dkdNSJiC-_A,4720 +django/contrib/humanize/locale/is/LC_MESSAGES/django.mo,sha256=D6ElUYj8rODRsZwlJlH0QyBSM44sVmuBCNoEkwPVxko,3805 +django/contrib/humanize/locale/is/LC_MESSAGES/django.po,sha256=1VddvtkhsK_5wmpYIqEFqFOo-NxIBnL9wwW74Tw9pbw,8863 +django/contrib/humanize/locale/it/LC_MESSAGES/django.mo,sha256=Zw8reudMUlPGC3eQ-CpsGYHX-FtNrAc5SxgTdmIrUC0,5374 +django/contrib/humanize/locale/it/LC_MESSAGES/django.po,sha256=wJzT-2ygufGLMIULd7afg1sZLQKnwQ55NZ2eAnwIY8M,9420 +django/contrib/humanize/locale/ja/LC_MESSAGES/django.mo,sha256=x8AvfUPBBJkGtE0jvAP4tLeZEByuyo2H4V_UuLoCEmw,3907 +django/contrib/humanize/locale/ja/LC_MESSAGES/django.po,sha256=G2yTPZq6DxgzPV5uJ6zvMK4o3aiuLWbl4vXPH7ylUhc,6919 +django/contrib/humanize/locale/ka/LC_MESSAGES/django.mo,sha256=UeUbonYTkv1d2ljC0Qj8ZHw-59zHu83fuMvnME9Fkmw,4878 +django/contrib/humanize/locale/ka/LC_MESSAGES/django.po,sha256=-eAMexwjm8nSB4ARJU3f811UZnuatHKIFf8FevpJEpo,9875 +django/contrib/humanize/locale/kk/LC_MESSAGES/django.mo,sha256=jujbUM0jOpt3Mw8zN4LSIIkxCJ0ihk_24vR0bXoux78,2113 +django/contrib/humanize/locale/kk/LC_MESSAGES/django.po,sha256=hjZg_NRE9xMA5uEa2mVSv1Hr4rv8inG9es1Yq7uy9Zc,8283 +django/contrib/humanize/locale/km/LC_MESSAGES/django.mo,sha256=mfXs9p8VokORs6JqIfaSSnQshZEhS90rRFhOIHjW7CI,459 +django/contrib/humanize/locale/km/LC_MESSAGES/django.po,sha256=JQBEHtcy-hrV_GVWIjvUJyOf3dZ5jUzzN8DUTAbHKUg,4351 +django/contrib/humanize/locale/kn/LC_MESSAGES/django.mo,sha256=Oq3DIPjgCqkn8VZMb6ael7T8fQ7LnWobPPAZKQSFHl4,461 +django/contrib/humanize/locale/kn/LC_MESSAGES/django.po,sha256=CAJ0etMlQF3voPYrxIRr5ChAwUYO7wI42n5kjpIEVjA,4359 +django/contrib/humanize/locale/ko/LC_MESSAGES/django.mo,sha256=mWmQEoe0MNVn3sNqsz6CBc826x3KIpOL53ziv6Ekf7c,3891 +django/contrib/humanize/locale/ko/LC_MESSAGES/django.po,sha256=UUxIUYM332DOZinJrqOUtQvHfCCHkodFhENDVWj3dpk,7003 +django/contrib/humanize/locale/ky/LC_MESSAGES/django.mo,sha256=jDu1bVgJMDpaZ0tw9-wdkorvZxDdRzcuzdeC_Ot7rUs,4177 +django/contrib/humanize/locale/ky/LC_MESSAGES/django.po,sha256=MEHbKMLIiFEG7BlxsNVF60viXSnlk5iqlFCH3hgamH0,7157 +django/contrib/humanize/locale/lb/LC_MESSAGES/django.mo,sha256=xokesKl7h7k9dXFKIJwGETgwx1Ytq6mk2erBSxkgY-o,474 +django/contrib/humanize/locale/lb/LC_MESSAGES/django.po,sha256=_y0QFS5Kzx6uhwOnzmoHtCrbufMrhaTLsHD0LfMqtcM,4730 +django/contrib/humanize/locale/lt/LC_MESSAGES/django.mo,sha256=O0C-tPhxWNW5J4tCMlB7c7shVjNO6dmTURtIpTVO9uc,7333 +django/contrib/humanize/locale/lt/LC_MESSAGES/django.po,sha256=M5LlRxC1KWh1-3fwS93UqTijFuyRENmQJXfpxySSKik,12086 +django/contrib/humanize/locale/lv/LC_MESSAGES/django.mo,sha256=3gEzmKBtYsFz9wvLw0ltiir91CDLxhK3IG2j55-uM7Y,5033 +django/contrib/humanize/locale/lv/LC_MESSAGES/django.po,sha256=yfeBxpH2J49xHDzZUZI3cK5ms4QbWq0gtTmhj8ejAjE,8836 +django/contrib/humanize/locale/mk/LC_MESSAGES/django.mo,sha256=htUgd6rcaeRPDf6UrEb18onz-Ayltw9LTvWRgEkXm08,4761 +django/contrib/humanize/locale/mk/LC_MESSAGES/django.po,sha256=Wl9Rt8j8WA_0jyxKCswIovSiCQD-ZWFYXbhFsCUKIWo,6665 +django/contrib/humanize/locale/ml/LC_MESSAGES/django.mo,sha256=5As-FXkEJIYetmV9dMtzLtsRPTOm1oUgyx-oeTH_guY,4655 +django/contrib/humanize/locale/ml/LC_MESSAGES/django.po,sha256=I9_Ln0C1nSj188_Zdq9Vy6lC8aLzg_YdNc5gy9hNGjE,10065 +django/contrib/humanize/locale/mn/LC_MESSAGES/django.mo,sha256=gi-b-GRPhg2s2O9wP2ENx4bVlgHBo0mSqoi58d_QpCw,6020 +django/contrib/humanize/locale/mn/LC_MESSAGES/django.po,sha256=0zV7fYPu6xs_DVOCUQ6li36JWOnpc-RQa0HXwo7FrWc,9797 +django/contrib/humanize/locale/mr/LC_MESSAGES/django.mo,sha256=2Z5jaGJzpiJTCnhCk8ulCDeAdj-WwR99scdHFPRoHoA,468 +django/contrib/humanize/locale/mr/LC_MESSAGES/django.po,sha256=M44sYiBJ7woVZZlDO8rPDQmS_Lz6pDTCajdheyxtdaI,4724 +django/contrib/humanize/locale/ms/LC_MESSAGES/django.mo,sha256=Bcictup-1bGKm0FIa3CeGNvrHg8VyxsqUHzWI7UMscs,3839 +django/contrib/humanize/locale/ms/LC_MESSAGES/django.po,sha256=UQEUC2iZxhtrWim96GaEK1VAKxAC0fTQIghg4Zx4R3Q,6774 +django/contrib/humanize/locale/my/LC_MESSAGES/django.mo,sha256=55CWHz34sy9k6TfOeVI9GYvE9GRa3pjSRE6DSPk9uQ8,3479 +django/contrib/humanize/locale/my/LC_MESSAGES/django.po,sha256=jCiDhSqARfqKcMLEHJd-Xe6zo3Uc9QpiCh3BbAAA5UE,5433 +django/contrib/humanize/locale/nb/LC_MESSAGES/django.mo,sha256=957mOf_wFBOTjpcevsRz5tQ6IQ4PJnZZfJUETUgF23s,4318 +django/contrib/humanize/locale/nb/LC_MESSAGES/django.po,sha256=G_4pAxT3QZhC-wmWKIhEkFf0IRBn6gKRQZvx0spqjuk,7619 +django/contrib/humanize/locale/ne/LC_MESSAGES/django.mo,sha256=YFT2D-yEkUdJBO2GfuUowau1OZQA5mS86CZvMzH38Rk,3590 +django/contrib/humanize/locale/ne/LC_MESSAGES/django.po,sha256=SN7yH65hthOHohnyEmQUjXusRTDRjxWJG_kuv5g2Enk,9038 +django/contrib/humanize/locale/nl/LC_MESSAGES/django.mo,sha256=RxwgVgdHvfFirimjPrpDhzqmI1Z9soDC--raoAzgBkw,4311 +django/contrib/humanize/locale/nl/LC_MESSAGES/django.po,sha256=M7dVQho17p71Ud6imsQLGMiBisLrVNEZNP4ufpkEJnM,7872 +django/contrib/humanize/locale/nn/LC_MESSAGES/django.mo,sha256=wyJDAGJWgvyBYZ_-UQnBQ84-Jelk5forKfk7hMFDGpQ,4336 +django/contrib/humanize/locale/nn/LC_MESSAGES/django.po,sha256=zuKg53XCX-C6Asc9M04BKZVVw1X6u5p5hvOXxc0AXnM,7651 +django/contrib/humanize/locale/os/LC_MESSAGES/django.mo,sha256=BwS3Mj7z_Fg5s7Qm-bGLVhzYLZ8nPgXoB0gXLnrMGWc,3902 +django/contrib/humanize/locale/os/LC_MESSAGES/django.po,sha256=CGrxyL5l-5HexruOc7QDyRbum7piADf-nY8zjDP9wVM,6212 +django/contrib/humanize/locale/pa/LC_MESSAGES/django.mo,sha256=TH1GkAhaVVLk2jrcqAmdxZprWyikAX6qMP0eIlr2tWM,1569 +django/contrib/humanize/locale/pa/LC_MESSAGES/django.po,sha256=_7oP0Hn-IU7IPLv_Qxg_wstLEdhgWNBBTCWYwSycMb0,5200 +django/contrib/humanize/locale/pl/LC_MESSAGES/django.mo,sha256=0QheMbF3Y0Q_sxZlN2wAYJRQyK3K_uq6ttVr7wCc33w,5596 +django/contrib/humanize/locale/pl/LC_MESSAGES/django.po,sha256=6wX50O68aIyKiP6CcyLMXZ3xuUnAzasFPIg_8deJQBY,9807 +django/contrib/humanize/locale/pt/LC_MESSAGES/django.mo,sha256=El9Sdr3kXS-yTol_sCg1dquxf0ThDdWyrWGjjim9Dj4,5408 +django/contrib/humanize/locale/pt/LC_MESSAGES/django.po,sha256=XudOc67ybF_fminrTR2XOCKEKwqB5FX14pl3clCNXGE,9281 +django/contrib/humanize/locale/pt_BR/LC_MESSAGES/django.mo,sha256=5iQ4VjZG60slrQqHejtlUoqastPUK-nwOLKsUMV4poM,5047 +django/contrib/humanize/locale/pt_BR/LC_MESSAGES/django.po,sha256=GZolivUh_cSWH53pjS3THvQMiOV3JwXgd5roJGqEfWA,8915 +django/contrib/humanize/locale/ro/LC_MESSAGES/django.mo,sha256=vP6o72bsgKPsbKGwH0PU8Xyz9BnQ_sPWT3EANLT2wRk,6188 +django/contrib/humanize/locale/ro/LC_MESSAGES/django.po,sha256=JZiW6Y9P5JdQe4vgCvcFg35kFa8bSX0lU_2zdeudQP0,10575 +django/contrib/humanize/locale/ru/LC_MESSAGES/django.mo,sha256=tVtMvbDmHtoXFav2cXzhHpHmT-4-593Vo7kE5sd-Agc,6733 +django/contrib/humanize/locale/ru/LC_MESSAGES/django.po,sha256=0OWESEN33yMIcRUaX_oSQUuDidhbzgKpdivwAS7kNgs,11068 +django/contrib/humanize/locale/sk/LC_MESSAGES/django.mo,sha256=6l7T4rvVb8dPl0-6vwrq5K1QqJ06IdFKxEl4EGzN8Ns,5541 +django/contrib/humanize/locale/sk/LC_MESSAGES/django.po,sha256=Edsza_V5MJD_HadigUZWZoFLjl8556KFW9tbuHVHL3g,9657 +django/contrib/humanize/locale/sl/LC_MESSAGES/django.mo,sha256=yonGwvQKyqpZ_NLTpynDdS6q4yg3eafL1K5MFmnGw7o,4967 +django/contrib/humanize/locale/sl/LC_MESSAGES/django.po,sha256=-nzc9Rk9f3U_Rpze_fdJrKR-_CglPJ0_GryNUDD80jI,9580 +django/contrib/humanize/locale/sq/LC_MESSAGES/django.mo,sha256=1XXRe0nurGUUxI7r7gbSIuluRuza7VOeNdkIVX3LIFU,5280 +django/contrib/humanize/locale/sq/LC_MESSAGES/django.po,sha256=BS-5o3aG8Im9dWTkx4E_IbbeTRFcjjohinz1823ZepI,9127 +django/contrib/humanize/locale/sr/LC_MESSAGES/django.mo,sha256=Zsv4ajqk9baWkNItJjkEsZP-OO-LuIg_5QopKgVesUw,5718 +django/contrib/humanize/locale/sr/LC_MESSAGES/django.po,sha256=AZddC4WvARQd3Qd-atFONB8KbzrNJCfiQcdP16m-EyM,9363 +django/contrib/humanize/locale/sr_Latn/LC_MESSAGES/django.mo,sha256=jg1u-tFg0HCuq0v66wQNJUmi3RgERXYovDJ1oKYuPeU,1065 +django/contrib/humanize/locale/sr_Latn/LC_MESSAGES/django.po,sha256=3G6QmXW9vBIZdYAl7proMq5MhitKUXBXXqmMxf1DUBU,7016 +django/contrib/humanize/locale/sv/LC_MESSAGES/django.mo,sha256=7OABdxvdZvKB9j1o99UiecoTXaVGn3XmXnU5xCNov8s,4333 +django/contrib/humanize/locale/sv/LC_MESSAGES/django.po,sha256=71tFrQzwtwzYfeC2BG0v8dZNkSEMbM-tAC5_z2AElLM,7876 +django/contrib/humanize/locale/sw/LC_MESSAGES/django.mo,sha256=cxjSUqegq1JX08xIAUgqq9ByP-HuqaXuxWM8Y2gHdB4,4146 +django/contrib/humanize/locale/sw/LC_MESSAGES/django.po,sha256=bPYrLJ2yY_lZ3y1K-RguNi-qrxq2r-GLlsz1gZcm2A8,6031 +django/contrib/humanize/locale/ta/LC_MESSAGES/django.mo,sha256=1X2vH0iZOwM0uYX9BccJUXqK-rOuhcu5isRzMpnjh2o,466 +django/contrib/humanize/locale/ta/LC_MESSAGES/django.po,sha256=8x1lMzq2KOJveX92ADSuqNmXGIEYf7fZ1JfIJPysS04,4722 +django/contrib/humanize/locale/te/LC_MESSAGES/django.mo,sha256=iKd4dW9tan8xPxgaSoenIGp1qQpvSHHXUw45Tj2ATKQ,1327 +django/contrib/humanize/locale/te/LC_MESSAGES/django.po,sha256=FQdjWKMsiv-qehYZ4AtN9iKRf8Rifzcm5TZzMkQVfQI,5103 +django/contrib/humanize/locale/tg/LC_MESSAGES/django.mo,sha256=1Fiqat0CZSyExRXRjRCBS0AFzwy0q1Iba-2RVnrXoZQ,1580 +django/contrib/humanize/locale/tg/LC_MESSAGES/django.po,sha256=j2iczgQDbqzpthKAAlMt1Jk7gprYLqZ1Ya0ASr2SgD0,7852 +django/contrib/humanize/locale/th/LC_MESSAGES/django.mo,sha256=jT7wGhYWP9HHwOvtr2rNPStiOgZW-rGMcO36w1U8Y4c,3709 +django/contrib/humanize/locale/th/LC_MESSAGES/django.po,sha256=ZO3_wU7z0VASS5E8RSLEtmTveMDjJ0O8QTynb2-jjt0,8318 +django/contrib/humanize/locale/tk/LC_MESSAGES/django.mo,sha256=cI2Ukp5kVTsUookoxyDD9gZKdxh4YezfRWYFBL7KuRU,4419 +django/contrib/humanize/locale/tk/LC_MESSAGES/django.po,sha256=6Qaxa03R4loH0FWQ6PCytT3Yz3LZt7UGTd01WVnHOIk,7675 +django/contrib/humanize/locale/tr/LC_MESSAGES/django.mo,sha256=D4ChMLE1Uz921NIF_Oe1vNkYAGfRpQuC8xANFwtlygE,4319 +django/contrib/humanize/locale/tr/LC_MESSAGES/django.po,sha256=4PjW65seHF9SsWnLv47JhgYPt0Gvzr-7_Ejech3d3ak,7754 +django/contrib/humanize/locale/tt/LC_MESSAGES/django.mo,sha256=z8VgtMhlfyDo7bERDfrDmcYV5aqOeBY7LDgqa5DRxDM,3243 +django/contrib/humanize/locale/tt/LC_MESSAGES/django.po,sha256=j_tRbg1hzLBFAmPQt0HoN-_WzWFtA07PloCkqhvNkcY,5201 +django/contrib/humanize/locale/udm/LC_MESSAGES/django.mo,sha256=CNmoKj9Uc0qEInnV5t0Nt4ZnKSZCRdIG5fyfSsqwky4,462 +django/contrib/humanize/locale/udm/LC_MESSAGES/django.po,sha256=AR55jQHmMrbA6RyHGOtqdvUtTFlxWnqvfMy8vZK25Bo,4354 +django/contrib/humanize/locale/ug/LC_MESSAGES/django.mo,sha256=_GtRGNtdwZ6lU2gZc5jN9nSDB15bLBMYdhiwHlKxOOc,4883 +django/contrib/humanize/locale/ug/LC_MESSAGES/django.po,sha256=x9DJRBObVq8C3orGfj737v2gCHcpqaWUXMEeCMkumco,8156 +django/contrib/humanize/locale/uk/LC_MESSAGES/django.mo,sha256=wQOJu-zKyuCazul-elFLZc-iKw2Zea7TGb90OVGZYkQ,6991 +django/contrib/humanize/locale/uk/LC_MESSAGES/django.po,sha256=hxEufGt-NOgSFc5T9OzxCibcfqkhWD7zxhQljoUQssQ,11249 +django/contrib/humanize/locale/ur/LC_MESSAGES/django.mo,sha256=MF9uX26-4FFIz-QpDUbUHUNLQ1APaMLQmISMIaPsOBE,1347 +django/contrib/humanize/locale/ur/LC_MESSAGES/django.po,sha256=D5UhcPEcQ16fsBEdkk_zmpjIF6f0gEv0P86z_pK_1eA,5015 +django/contrib/humanize/locale/uz/LC_MESSAGES/django.mo,sha256=HDah_1qqUz5m_ABBVIEML3WMR2xyomFckX82i6b3n4k,1915 +django/contrib/humanize/locale/uz/LC_MESSAGES/django.po,sha256=Ql3GZOhuoVgS0xHEzxjyYkOWQUyi_jiizfAXBp2Y4uw,7296 +django/contrib/humanize/locale/vi/LC_MESSAGES/django.mo,sha256=ZUK_Na0vnfdhjo0MgnBWnGFU34sxcMf_h0MeyuysKG8,3646 +django/contrib/humanize/locale/vi/LC_MESSAGES/django.po,sha256=DzRpXObt9yP5RK_slWruaIhnVI0-JXux2hn_uGsVZiE,5235 +django/contrib/humanize/locale/zh_Hans/LC_MESSAGES/django.mo,sha256=YgeAjXHMV1rXNNIrlDu_haxnKB0hxU5twJ86LMR10k8,3844 +django/contrib/humanize/locale/zh_Hans/LC_MESSAGES/django.po,sha256=JGfRVW_5UqwyI2mK_WRK8xDPzwBAO2q_mGsGzf89a88,7122 +django/contrib/humanize/locale/zh_Hant/LC_MESSAGES/django.mo,sha256=qYO9_rWuIMxnlL9Q8V9HfhUu7Ebv1HGOlvsnh7MvZkE,4520 +django/contrib/humanize/locale/zh_Hant/LC_MESSAGES/django.po,sha256=AijEfvIlJK9oVaLJ7lplmbvhGRKIbYcLh8WxoBYoQkA,7929 +django/contrib/humanize/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/humanize/templatetags/humanize.py,sha256=FuOhGLO0OS2KT0DgMgnOwllCwVSpwIvrOiCmku-W_fg,12085 +django/contrib/messages/__init__.py,sha256=_5b6kMxWt0TqW5ze5vZ-iqYEQfaQiAl28x2q9KRaMz4,171 +django/contrib/messages/api.py,sha256=3DbnVG5oOBdg499clMU8l2hxCXMXB6S03-HCKVuBXjA,3250 +django/contrib/messages/apps.py,sha256=W_nya0lzXYBew83hqP6I8gg6XnaRlh-gmN-pYpDGN84,611 +django/contrib/messages/constants.py,sha256=JD4TpaR4C5G0oxIh4BmrWiVmCACv7rnVgZSpJ8Rmzeg,312 +django/contrib/messages/context_processors.py,sha256=xMrgYeX6AcT_WwS9AYKNDDstbvAwE7_u1ssDVLN_bbg,354 +django/contrib/messages/middleware.py,sha256=2mxncCpJVUgLtjouUGSVl39mTF-QskQpWo2jCOOqV8A,986 +django/contrib/messages/storage/__init__.py,sha256=gXDHbQ9KgQdfhYOla9Qj59_SlE9WURQiKzIA0cFH0DQ,392 +django/contrib/messages/storage/base.py,sha256=T-bcy6HdwRbEKNIuO5fEJZ1EUj3rTHWXRg1oxqRahGc,6082 +django/contrib/messages/storage/cookie.py,sha256=6r-z_MyYImgEC5LPvjOdp64xwkiV_ib97Sg4N4eXjxY,8678 +django/contrib/messages/storage/fallback.py,sha256=K5CrVJfUDakMjIcqSRt1WZd_1Xco1Bc2AQM3O3ld9aA,2093 +django/contrib/messages/storage/session.py,sha256=kvdVosbBAvI3XBA0G4AFKf0vxLleyzlwbGEgl60DfMQ,1764 +django/contrib/messages/test.py,sha256=8PJVFT2ICdptbMZSBrZC0ZLC3AJzL7XUK2Vz4f4wXuk,332 +django/contrib/messages/utils.py,sha256=_oItQILchdwdXH08SIyZ-DBdYi7q_uobHQajWwmAeUw,256 +django/contrib/messages/views.py,sha256=I_7C4yr-YLkhTEWx3iuhixG7NrKuyuSDG_CVg-EYRD8,524 +django/contrib/postgres/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/postgres/aggregates/__init__.py,sha256=QCznqMKqPbpraxSi1Y8-B7_MYlL42F1kEWZ1HeLgTKs,65 +django/contrib/postgres/aggregates/general.py,sha256=gUXtYr1IzLx6d8HNGYfg7t2PLP2NkGy4SeNLpmer0uE,2904 +django/contrib/postgres/aggregates/mixins.py,sha256=k2fwYW89490mYW8H5113fMOTf-Y3vzrRH6VvJFHqA1Q,1181 +django/contrib/postgres/aggregates/statistics.py,sha256=xSWk5Z5ZVpM2LSaMgP97pxcijOnPHiPATe3X45poXCI,1511 +django/contrib/postgres/apps.py,sha256=sfjoL-2VJrFzrv0CC3S4WGWZblzR_4BwFDm9bEHs8B0,3692 +django/contrib/postgres/constraints.py,sha256=Z5DLQqZHnjsziiE7ShTpBBsTOIfVHeio6_BqsT4mbpM,9587 +django/contrib/postgres/expressions.py,sha256=fo5YASHJtIjexadqskuhYYk4WutofxzymYsivWWJS84,405 +django/contrib/postgres/fields/__init__.py,sha256=Xo8wuWPwVNOkKY-EwV9U1zusQ2DjMXXtL7_8R_xAi5s,148 +django/contrib/postgres/fields/array.py,sha256=4SUUGDZCUSw6oQWCNJtwFiEihmKxPzjWl5sladB-f3s,12302 +django/contrib/postgres/fields/citext.py,sha256=KMXa7CO8fyNYKa7zcU17hN8IEAw8qJxdHPVIr0jxhPg,2549 +django/contrib/postgres/fields/hstore.py,sha256=WWWEoBfMtAjd226vvjFtGqbHMHFCjSly-BEhm9UN1qQ,3276 +django/contrib/postgres/fields/jsonb.py,sha256=ncMGT6WY70lCbcmhwtu2bjRmfDMUIvCr76foUv7tqv0,406 +django/contrib/postgres/fields/ranges.py,sha256=IbjAQC7IdWuISqHdBXrraiOGPzUP_4pHHcnL8VuYZRs,11417 +django/contrib/postgres/fields/utils.py,sha256=TV-Aj9VpBb13I2iuziSDURttZtz355XakxXnFwvtGio,95 +django/contrib/postgres/forms/__init__.py,sha256=NjENn2-C6BcXH4T8YeC0K2AbDk8MVT8tparL3Q4OF6g,89 +django/contrib/postgres/forms/array.py,sha256=LRUU3fxXePptMh3lolxhX4sbMjNSvnzMvNgcJolKfZc,8401 +django/contrib/postgres/forms/hstore.py,sha256=XN5xOrI-jCeTsWFEjPXf6XMaLzJdXiqA6pTdGSjWdOw,1767 +django/contrib/postgres/forms/ranges.py,sha256=cKAeWvRISPLXIPhm2C57Lu9GoIlAd1xiRxzns69XehA,3652 +django/contrib/postgres/functions.py,sha256=7v6J01QQvX70KFyg9hDc322PgvT62xZqWlzp_vrl8bA,252 +django/contrib/postgres/indexes.py,sha256=jFMzMt6SwC7aCA-tXSrsBlBPCWQhxj3Xu5V04uwxTkw,8123 +django/contrib/postgres/jinja2/postgres/widgets/split_array.html,sha256=AzaPLlNLg91qkVQwwtAJxwOqDemrtt_btSkWLpboJDs,54 +django/contrib/postgres/locale/af/LC_MESSAGES/django.mo,sha256=kDeL_SZezO8DRNMRh2oXz94YtAK1ZzPiK5dftqAonKI,2841 +django/contrib/postgres/locale/af/LC_MESSAGES/django.po,sha256=ALKUHbZ8DE6IH80STMJhGOoyHB8HSSxI4PlX_SfxJWc,3209 +django/contrib/postgres/locale/ar/LC_MESSAGES/django.mo,sha256=UTBknYC-W7nclTrBCEiCpTglZxZQY80UqGki8I6j3EM,4294 +django/contrib/postgres/locale/ar/LC_MESSAGES/django.po,sha256=_PgF2T3ylO4vnixVoKRsgmpPDHO-Qhj3mShHtHeSna0,4821 +django/contrib/postgres/locale/ar_DZ/LC_MESSAGES/django.mo,sha256=fND1NtGTmEl7Rukt_VlqJeExdJjphBygmI-qJmE83P0,4352 +django/contrib/postgres/locale/ar_DZ/LC_MESSAGES/django.po,sha256=Z9y3h6lDnbwD4JOn7OACLjEZqNY8OpEwuzoUD8FSdwA,4868 +django/contrib/postgres/locale/az/LC_MESSAGES/django.mo,sha256=K-2weZNapdDjP5-ecOfQhhhWmVR53JneJ2n4amA_zTk,2855 +django/contrib/postgres/locale/az/LC_MESSAGES/django.po,sha256=Pn47g_NvMgSBjguFLT_AE1QzxOGXOYjA-g_heXAT_tU,3214 +django/contrib/postgres/locale/be/LC_MESSAGES/django.mo,sha256=tYaaEbBaVxIgxC9qUAuE3YpHJa-aUu9ufFuJLa8my-s,4143 +django/contrib/postgres/locale/be/LC_MESSAGES/django.po,sha256=CL9BslCvHOvwjTBbCEswW8ISH72gSAyW5Dc-zoXI670,4643 +django/contrib/postgres/locale/bg/LC_MESSAGES/django.mo,sha256=A_WOYkzm2QwAo8ZXCKg7jOOiM7bEwUT4cSsSlyC6sWQ,3529 +django/contrib/postgres/locale/bg/LC_MESSAGES/django.po,sha256=TEDRfX5DWADwlgYqScP1hGm2hq2_zUGzIBmKY8WLVLQ,3993 +django/contrib/postgres/locale/ca/LC_MESSAGES/django.mo,sha256=XR1UEZV9AXKFz7XrchjRkd-tEdjnlmccW_I7XANyMns,2904 +django/contrib/postgres/locale/ca/LC_MESSAGES/django.po,sha256=5wPLvkODU_501cHPZ7v0n89rmFrsuctt7T8dUBMfQ0Q,3430 +django/contrib/postgres/locale/ckb/LC_MESSAGES/django.mo,sha256=bue3b5xV84UvuzndoIQvLCNyRCkGKsNHBw1QQOF9MvU,2994 +django/contrib/postgres/locale/ckb/LC_MESSAGES/django.po,sha256=gaiFjvVSbX7_qwH4MIc5ma5oKqmjWBsvxzaEtI4hM0s,3526 +django/contrib/postgres/locale/cs/LC_MESSAGES/django.mo,sha256=_EmT9NnoX3xeRU-AI5sPlAszjzC0XwryWOmj8d07ox8,3388 +django/contrib/postgres/locale/cs/LC_MESSAGES/django.po,sha256=dkWVucs3-avEVtk_Xh5p-C8Tvw_oKDASdgab_-ByP-w,3884 +django/contrib/postgres/locale/da/LC_MESSAGES/django.mo,sha256=VaTePWY3W7YRW-CkTUx6timYDXEYOFRFCkg3F36_k_I,2886 +django/contrib/postgres/locale/da/LC_MESSAGES/django.po,sha256=5j5xI-yKORhnywIACpjvMQA6yHj4aHMYiiN4KVSmBMM,3344 +django/contrib/postgres/locale/de/LC_MESSAGES/django.mo,sha256=iTfG4OxvwSG32U_PQ0Tmtl38v83hSjFa2W0J8Sw0NUE,3078 +django/contrib/postgres/locale/de/LC_MESSAGES/django.po,sha256=GkF6wBg7JAvAB8YExwOx4hzpLr1r2K6HsvSLYfyojow,3611 +django/contrib/postgres/locale/dsb/LC_MESSAGES/django.mo,sha256=zZa1kLFCKar4P1xVNpJ0BTXm4I-xcNi_e8IY7n8Aa4w,3605 +django/contrib/postgres/locale/dsb/LC_MESSAGES/django.po,sha256=5vnAeH9tF9H9xL2nqfwc0MLlhI4hnNr45x2NXlw8owo,4061 +django/contrib/postgres/locale/el/LC_MESSAGES/django.mo,sha256=NmzROkTfSbioGv8exM3UdMDnRAxR65YMteGv9Nhury4,3583 +django/contrib/postgres/locale/el/LC_MESSAGES/django.po,sha256=4WuswUwrInAh-OPX9k7gDdLb-oMKp1vQFUGvfm0ej00,4144 +django/contrib/postgres/locale/en/LC_MESSAGES/django.mo,sha256=U0OV81NfbuNL9ctF-gbGUG5al1StqN-daB-F-gFBFC8,356 +django/contrib/postgres/locale/en/LC_MESSAGES/django.po,sha256=jrbHgf4TLTbEAaYV9-briB5JoE7sBWTn9r6aaRtpn54,2862 +django/contrib/postgres/locale/en_AU/LC_MESSAGES/django.mo,sha256=WA0RSssD8ljI16g6DynQZQLQhd_0XR8ilrnJnepsIFg,2839 +django/contrib/postgres/locale/en_AU/LC_MESSAGES/django.po,sha256=4JASYUpYlQlSPREPvMxFBqDpDhprlkI1GpAqTJrmb10,3215 +django/contrib/postgres/locale/eo/LC_MESSAGES/django.mo,sha256=1wqM_IVO8Dl9AefzvWYuoS4eNTrBg7LDH6XUMovKi9A,2742 +django/contrib/postgres/locale/eo/LC_MESSAGES/django.po,sha256=r2tpOblfLAAHMacDWU-OVXTQus_vvAPMjUzVfrV_T7U,3217 +django/contrib/postgres/locale/es/LC_MESSAGES/django.mo,sha256=O2Tdel44oxmQ13ZcwMwK3QPxUPChHdUzVKg2pLCPoqo,3163 +django/contrib/postgres/locale/es/LC_MESSAGES/django.po,sha256=YPjvjmvpS69FuNmPm-7Z1K1Eg_W01JwRHNrWkbKzVZ8,3794 +django/contrib/postgres/locale/es_AR/LC_MESSAGES/django.mo,sha256=zIN-1vsrChWXLDuGrzs61LbBuOwsyifWcvo9NrYCy2k,3140 +django/contrib/postgres/locale/es_AR/LC_MESSAGES/django.po,sha256=1seAy6OHEKG4fDV4NwKQyGfkjT29zjgwvXZ85u1VNtw,3506 +django/contrib/postgres/locale/es_CO/LC_MESSAGES/django.mo,sha256=Q2eOegYKQFY3fAKZCX7VvZAN6lT304W51aGl0lzkbLU,2484 +django/contrib/postgres/locale/es_CO/LC_MESSAGES/django.po,sha256=bbgOn34B7CSq1Kf2IrJh6oRJWPur_Smc4ebljIxAFGE,3233 +django/contrib/postgres/locale/es_MX/LC_MESSAGES/django.mo,sha256=l6WdS59mDfjsV9EMULjKP2DhXR7x3bYax1iokL-AXcU,689 +django/contrib/postgres/locale/es_MX/LC_MESSAGES/django.po,sha256=_-jzhIT71zV539_4SUbwvOXfDHkxRy1FDGdx23iB7B4,2283 +django/contrib/postgres/locale/et/LC_MESSAGES/django.mo,sha256=oPGqGUQhU9xE7j6hQZSVdC-be2WV-_BNrSAaN4csFR4,2886 +django/contrib/postgres/locale/et/LC_MESSAGES/django.po,sha256=xKkb-0CQCAn37xe0G2jfQmjg2kuYBmXB5yBpTA5lYNI,3404 +django/contrib/postgres/locale/eu/LC_MESSAGES/django.mo,sha256=UG7x642-n3U7mamXuNHD66a_mR0agX72xSwBD3PpyJU,2883 +django/contrib/postgres/locale/eu/LC_MESSAGES/django.po,sha256=dAx6nlRd4FF_8i7Xeylwvj4HkEDKi3swFenkdJkDawU,3321 +django/contrib/postgres/locale/fa/LC_MESSAGES/django.mo,sha256=uLh9fJtCSKg5eaj9uGP2muN_71aFxpZwOjRHtnZhPik,3308 +django/contrib/postgres/locale/fa/LC_MESSAGES/django.po,sha256=adN7bh9Q_R0Wzlf2fWaQnTtvxo0NslyoHH5t5V0eeMM,3845 +django/contrib/postgres/locale/fi/LC_MESSAGES/django.mo,sha256=gB2z3nI8Bz-km3DngYfJulwelHSlWgZeBXlj5yWyA08,2943 +django/contrib/postgres/locale/fi/LC_MESSAGES/django.po,sha256=LNVTHv4-FWT5KOre5qTwLEpKIQbaSIusFH2uUmbwYBg,3315 +django/contrib/postgres/locale/fr/LC_MESSAGES/django.mo,sha256=02ug8j0VpkPC2tRDkXrK2snj91M68Ju29PUiv4UhAsQ,3391 +django/contrib/postgres/locale/fr/LC_MESSAGES/django.po,sha256=5T_wkYoHJcpzemKqR-7apZ11Pas4dZhnAitHOgT8gRc,3759 +django/contrib/postgres/locale/gd/LC_MESSAGES/django.mo,sha256=okWU_Ke95EG2pm8rZ4PT5ScO-8f0Hqg65lYZgSid8tM,3541 +django/contrib/postgres/locale/gd/LC_MESSAGES/django.po,sha256=tjt5kfkUGryU3hFzPuAly2DBDLuLQTTD5p-XrxryFEI,4013 +django/contrib/postgres/locale/gl/LC_MESSAGES/django.mo,sha256=1Od7e0SG9tEeTefFLLWkU38tlk5PL5aRF1GTlKkfTAs,2912 +django/contrib/postgres/locale/gl/LC_MESSAGES/django.po,sha256=tE2-GX2OH06krOFxvzdJeYWC7a57QYNFx5OtMXFWTdQ,3316 +django/contrib/postgres/locale/he/LC_MESSAGES/django.mo,sha256=znkNJeCKSSA4DPdvN5LCj5tdcWvRJQKRLWMXqSIO4FI,3757 +django/contrib/postgres/locale/he/LC_MESSAGES/django.po,sha256=oVJ0bfd9gH3aF3lo6rCMbA_9_3nhLWKBqfVj-H220F0,4234 +django/contrib/postgres/locale/hr/LC_MESSAGES/django.mo,sha256=vdm5GxgpKuVdGoVl3VreD8IB1Mq5HGWuq-2YDeDrNnU,929 +django/contrib/postgres/locale/hr/LC_MESSAGES/django.po,sha256=8TxEnVH2yIQWbmbmDOpR7kksNFSaUGVhimRPQgSgDkM,2501 +django/contrib/postgres/locale/hsb/LC_MESSAGES/django.mo,sha256=SSZpG-PSeVCHrzB-wzW4wRHxIEt7hqobzvRLB-9tu8Y,3518 +django/contrib/postgres/locale/hsb/LC_MESSAGES/django.po,sha256=UQUlfpJsgd-0qa6hZhUkTAi6VF5ZYiygSMrLcsiEC4k,3971 +django/contrib/postgres/locale/hu/LC_MESSAGES/django.mo,sha256=o6JDAFIN7i21GE2N0q98SiqIdvGYPLLdDiMLC_UE5hM,2892 +django/contrib/postgres/locale/hu/LC_MESSAGES/django.po,sha256=yUcbOn1k08aqhkODsrQfLR3qk-UnEEbEYuP3JyQ3eCU,3432 +django/contrib/postgres/locale/hy/LC_MESSAGES/django.mo,sha256=2QFIJdmh47IGPqI-8rvuHR0HdH2LOAmaYqEeCwUpRuw,3234 +django/contrib/postgres/locale/hy/LC_MESSAGES/django.po,sha256=MLHMbdwdo1txzFOG-fVK4VUvAoDtrLA8CdpQThybSCQ,3825 +django/contrib/postgres/locale/ia/LC_MESSAGES/django.mo,sha256=gn8lf-gOP4vv-iiqnkcxvjzhJ8pTdetBhHyjl4TapXo,582 +django/contrib/postgres/locale/ia/LC_MESSAGES/django.po,sha256=FsqhPQf0j4g06rGuWSTn8A1kJ7E5U9rX16mtB8CAiIE,2251 +django/contrib/postgres/locale/id/LC_MESSAGES/django.mo,sha256=KKI5fjmuD7jqiGe7SgGkWmF6unHNe8JMVoOSDVemB8o,2733 +django/contrib/postgres/locale/id/LC_MESSAGES/django.po,sha256=Me13R5Oi89IZ0T3CtY0MZ34YK3T-HIZ7GbtFiXl2h50,3300 +django/contrib/postgres/locale/is/LC_MESSAGES/django.mo,sha256=rNL5Un5K_iRAZDtpHo4egcySaaBnNEirYDuWw0eI7gk,2931 +django/contrib/postgres/locale/is/LC_MESSAGES/django.po,sha256=UO53ciyI0jCVtBOXWkaip2AbPE2Hd2YhzK1RAlcxyQ8,3313 +django/contrib/postgres/locale/it/LC_MESSAGES/django.mo,sha256=dsn-Xuhg1WeRkJVGHHdoPz-KobYsS8A41BUdnM4wQQ8,3210 +django/contrib/postgres/locale/it/LC_MESSAGES/django.po,sha256=2RpaA-mmvXcYkYTu_y0u3p32aAhP9DyAy641ZJL79sk,3874 +django/contrib/postgres/locale/ja/LC_MESSAGES/django.mo,sha256=IC9mYW8gXWNGuXeh8gGxGFvrjfxiSpj57E63Ka47pkM,3046 +django/contrib/postgres/locale/ja/LC_MESSAGES/django.po,sha256=IPnDsh8rtq158a63zQJekJ0LJlR3uj6KAjx4omc7XN0,3437 +django/contrib/postgres/locale/ka/LC_MESSAGES/django.mo,sha256=A_VhLUZbocGNF5_5mMoYfB3l654MrPIW4dL1ywd3Tw8,713 +django/contrib/postgres/locale/ka/LC_MESSAGES/django.po,sha256=kRIwQ1Nrzdf5arHHxOPzQcB-XwPNK5lUFKU0L3QHfC8,2356 +django/contrib/postgres/locale/kk/LC_MESSAGES/django.mo,sha256=xMc-UwyP1_jBHcGIAGWmDAjvSL50jJaiZbcT5TmzDOg,665 +django/contrib/postgres/locale/kk/LC_MESSAGES/django.po,sha256=f6Z3VUFRJ3FgSReC0JItjA0RaYbblqDb31lbJ3RRExQ,2327 +django/contrib/postgres/locale/ko/LC_MESSAGES/django.mo,sha256=G9Cl4uFost_c2y-3dBEF5ODuOe2BLThiXcEMEMXQQE8,2905 +django/contrib/postgres/locale/ko/LC_MESSAGES/django.po,sha256=JXqG3VCGEhBzAxGzOBb9w6oflaX4duhxNVht69ytOQY,3481 +django/contrib/postgres/locale/ky/LC_MESSAGES/django.mo,sha256=F0Ws34MbE7zJa8FNxA-9rFm5sNLL22D24LyiBb927lE,3101 +django/contrib/postgres/locale/ky/LC_MESSAGES/django.po,sha256=yAzSeT2jBm7R2ZXiuYBQFSKQ_uWIUfNTAobE1UYnlPs,3504 +django/contrib/postgres/locale/lt/LC_MESSAGES/django.mo,sha256=kJ3ih8HrHt2M_hFW0H9BZg7zcj6sXy6H_fD1ReIzngM,3452 +django/contrib/postgres/locale/lt/LC_MESSAGES/django.po,sha256=PNADIV8hdpLoqwW4zpIhxtWnQN8cPkdcoXYngyjFeFw,3972 +django/contrib/postgres/locale/lv/LC_MESSAGES/django.mo,sha256=UwBbbIbC_MO6xhB66UzO80XFcmlyv8-mfFEK4kQd6fE,3153 +django/contrib/postgres/locale/lv/LC_MESSAGES/django.po,sha256=phDSZnB5JeCoCi0f_MYCjQiwhE00gcVl5urOFiAKmkU,3768 +django/contrib/postgres/locale/mk/LC_MESSAGES/django.mo,sha256=WE4nRJKWAZvXuyU2qT2_FGqGlKYsP1KSACCtT10gQQY,3048 +django/contrib/postgres/locale/mk/LC_MESSAGES/django.po,sha256=CQX91LP1Gbkazpt4hTownJtSqZGR1OJfoD-1MCo6C1Y,3783 +django/contrib/postgres/locale/ml/LC_MESSAGES/django.mo,sha256=N47idWIsmtghZ_D5325TRsDFeoUa0MIvMFtdx7ozAHc,1581 +django/contrib/postgres/locale/ml/LC_MESSAGES/django.po,sha256=lt_7fGZV7BCB2XqFWIQQtH4niU4oMBfGzQQuN5sD0fo,2947 +django/contrib/postgres/locale/mn/LC_MESSAGES/django.mo,sha256=VWeXaMvdqhW0GHs1Irb1ikTceH7jMKH_xMzKLH0vKZg,3310 +django/contrib/postgres/locale/mn/LC_MESSAGES/django.po,sha256=p3141FJiYrkV8rocgqdxnV05FReQYZmosv9LI46FlfE,3867 +django/contrib/postgres/locale/ms/LC_MESSAGES/django.mo,sha256=m3JZm1IIMZwmpvIs3oV0roYCeR_UlswHyCpZjjE6-A8,2712 +django/contrib/postgres/locale/ms/LC_MESSAGES/django.po,sha256=HCMBA1fxKLJct14ywap0PYVBi2bDp2F97Ms5_-G_Pwg,3025 +django/contrib/postgres/locale/nb/LC_MESSAGES/django.mo,sha256=3h8DqEFG39i6uHY0vpXuGFmoJnAxTtRFy1RazcYIXfg,2849 +django/contrib/postgres/locale/nb/LC_MESSAGES/django.po,sha256=gDUg-HDg3LiYMKzb2QaDrYopqaJmbvnw2Fo-qhUHFuI,3252 +django/contrib/postgres/locale/ne/LC_MESSAGES/django.mo,sha256=5XdBLGMkn20qeya3MgTCpsIDxLEa7PV-i2BmK993iRc,875 +django/contrib/postgres/locale/ne/LC_MESSAGES/django.po,sha256=1QLLfbrHneJmxM_5UTpNIYalP-qX7Bn7bmj4AfDLIzE,2421 +django/contrib/postgres/locale/nl/LC_MESSAGES/django.mo,sha256=XK0L91JYDbkgw45eJysai_3u28KqZ5UFPTYaCTMiDPA,2993 +django/contrib/postgres/locale/nl/LC_MESSAGES/django.po,sha256=qU17zpXRHSoBQIkcP-Cm1GFh0BcpUTJsdh277P8dYG0,3565 +django/contrib/postgres/locale/nn/LC_MESSAGES/django.mo,sha256=RdMFozwxYIckBY40mJhN-jjkghztKn0-ytCtqxFHBMY,2836 +django/contrib/postgres/locale/nn/LC_MESSAGES/django.po,sha256=vl8NkY342eonqbrj89eCR_8PsJpeQuaRjxems-OPIBk,3184 +django/contrib/postgres/locale/pl/LC_MESSAGES/django.mo,sha256=Wox9w-HN7Guf8N1nkgemuDVs0LQxxTmEqQDOxriKy60,3462 +django/contrib/postgres/locale/pl/LC_MESSAGES/django.po,sha256=pxm_IKMg8g5qfg19CKc5JEdK6IMnhyeSPHd7THUb1GY,4217 +django/contrib/postgres/locale/pt/LC_MESSAGES/django.mo,sha256=KZvJXjrIdtxbffckcrRV3nJ5GnID6PvqAb7vpOiWpHE,2745 +django/contrib/postgres/locale/pt/LC_MESSAGES/django.po,sha256=2gIDOjnFo6Iom-oTkQek4IX6FYPI9rNp9V-6sJ55aL8,3281 +django/contrib/postgres/locale/pt_BR/LC_MESSAGES/django.mo,sha256=PVEiflh0v3AqVOC0S85XO-V3xDU3d8UwS31lzGrLoi8,3143 +django/contrib/postgres/locale/pt_BR/LC_MESSAGES/django.po,sha256=onF2K6s-McAXDSRzQ50EpGrKAIv89vvRWjCjsLCVXvs,3896 +django/contrib/postgres/locale/ro/LC_MESSAGES/django.mo,sha256=w4tyByrZlba_Ju_F2OzD52ut5JSD6UGJfjt3A7CG_uc,3188 +django/contrib/postgres/locale/ro/LC_MESSAGES/django.po,sha256=hnotgrr-zeEmE4lgpqDDiJ051GoGbL_2GVs4O9dVLXI,3700 +django/contrib/postgres/locale/ru/LC_MESSAGES/django.mo,sha256=LKkZs-TvPFTSrXVVaaoZ-Ec0kL_E9_5vTaExVxlr_rk,4732 +django/contrib/postgres/locale/ru/LC_MESSAGES/django.po,sha256=mnmVUlwZqn9QwdMx4g0D9xYxxKw_4pMFslwT2c4AjuE,5488 +django/contrib/postgres/locale/sk/LC_MESSAGES/django.mo,sha256=dRnTFkvRMbq5QnVEtrQ9Of9MxKTFYPP8sE7kbvUEjug,3381 +django/contrib/postgres/locale/sk/LC_MESSAGES/django.po,sha256=OwKv_mc9cuwt_YGnoVQLF3t2RsIbFyG_k3NKoIMAMoY,3899 +django/contrib/postgres/locale/sl/LC_MESSAGES/django.mo,sha256=JM9YZagjHIIrCxOKkR4d4oKaEXKJU7bfVdM3_uzSTAE,2810 +django/contrib/postgres/locale/sl/LC_MESSAGES/django.po,sha256=1jI2zXSU4LWxfLEUL-FXpldCExZJLD53Jy7VnA258xs,3602 +django/contrib/postgres/locale/sq/LC_MESSAGES/django.mo,sha256=slZq_bGPIzF8AlmtsfIqo65B14YYfw_uYKNcw_Tun0g,2958 +django/contrib/postgres/locale/sq/LC_MESSAGES/django.po,sha256=TPmtauQdDYM5QIOhGj2EwjRBQ3qOiRmvPMpUavUqh9A,3394 +django/contrib/postgres/locale/sr/LC_MESSAGES/django.mo,sha256=OfsUq8rZdD2NP7NQjBoatSXATxc8d6QL-nxmlPp5QSc,3775 +django/contrib/postgres/locale/sr/LC_MESSAGES/django.po,sha256=vUvFaIp8renqgGs-VgrtPNu7IBkcB38mlTBJ0xxXTaI,4214 +django/contrib/postgres/locale/sr_Latn/LC_MESSAGES/django.mo,sha256=2nDFP43vk1Jih35jns8vSbOhhLq_w7t_2vJHg-crfxY,3112 +django/contrib/postgres/locale/sr_Latn/LC_MESSAGES/django.po,sha256=QN4NEy0zFaPNjTCBrT9TydedWG7w4QBPm-pO7cKvSjg,3510 +django/contrib/postgres/locale/sv/LC_MESSAGES/django.mo,sha256=AkUgWYRBGNJYg5QDPJR3qu4BA_XF9xaZA__3m_KF4hk,2918 +django/contrib/postgres/locale/sv/LC_MESSAGES/django.po,sha256=hhJBRobgyHkLeKxdDxNkEl9XKkDXkrlx6PjyWcERp7I,3487 +django/contrib/postgres/locale/tg/LC_MESSAGES/django.mo,sha256=3yW5NKKsa2f2qDGZ4NGlSn4DHatLOYEv5SEwB9voraA,2688 +django/contrib/postgres/locale/tg/LC_MESSAGES/django.po,sha256=Zuix5sJH5Fz9-joe_ivMRpNz2Fbzefsxz3OOoDV0o1c,3511 +django/contrib/postgres/locale/tk/LC_MESSAGES/django.mo,sha256=ytivs6cnECDuyVKToFQMRnH_RPr4PlVepg8xFHnr0W4,2789 +django/contrib/postgres/locale/tk/LC_MESSAGES/django.po,sha256=bfXIyKNOFRC3U34AEKCsYQn3XMBGtgqHsXpboHvRQq0,3268 +django/contrib/postgres/locale/tr/LC_MESSAGES/django.mo,sha256=hZ2pxkYNOGE4BX--QmDlzqXxT21gHaPGA6CmXDODzhI,2914 +django/contrib/postgres/locale/tr/LC_MESSAGES/django.po,sha256=fzQsDL_wSO62qUaXCutRgq0ifrQ9oOaaxVQRyfnvV7Y,3288 +django/contrib/postgres/locale/ug/LC_MESSAGES/django.mo,sha256=ClLFBgCNopAREx7jy9WRbEASJERWJO8WZHriZrPtDZU,3938 +django/contrib/postgres/locale/ug/LC_MESSAGES/django.po,sha256=Ldd11fS8-D6ZeannnC6pCmBk7fmtqR_RXaeaNZQtU6M,4323 +django/contrib/postgres/locale/uk/LC_MESSAGES/django.mo,sha256=Jg6nM7ah7hEv7eqpe11e0e_MvRaMAQW3mdHTj9hqyG8,4406 +django/contrib/postgres/locale/uk/LC_MESSAGES/django.po,sha256=6gBP1xKxK9hf8ISCR1wABxkKXEUTx2CUYHGr6RVPI94,5100 +django/contrib/postgres/locale/uz/LC_MESSAGES/django.mo,sha256=PcmhhVC1spz3EFrQ2qdhfPFcA1ELHtBhHGWk9Z868Ss,703 +django/contrib/postgres/locale/uz/LC_MESSAGES/django.po,sha256=lbQxX2cmueGCT8sl6hsNWcrf9H-XEUbioP4L7JHGqiU,2291 +django/contrib/postgres/locale/zh_Hans/LC_MESSAGES/django.mo,sha256=ln_p6MRs5JPvTAXFzegXYnCCKki-LEr_YiOw6sK8oPA,2560 +django/contrib/postgres/locale/zh_Hans/LC_MESSAGES/django.po,sha256=7YZE8B0c1HuKVjGzreY7iiyuFeyPgqzKIwzxe5YOKb4,3084 +django/contrib/postgres/locale/zh_Hant/LC_MESSAGES/django.mo,sha256=Twqt8SVetuVV6UQ8ne48RfXILh2I9_-5De7cIrd5Lvc,2586 +django/contrib/postgres/locale/zh_Hant/LC_MESSAGES/django.po,sha256=5qE-q9uXlHM59soKgNSqeCfP-DnFuYI4fXLAbQctJ8c,2962 +django/contrib/postgres/lookups.py,sha256=J50bsr8rLjp_zzdViSVDDcTLfDkY21fEUoyqCgeHauI,1991 +django/contrib/postgres/operations.py,sha256=NAxMCzBMjxMNvEBWdRibbSpJ_UhyheToJTVImRAGS6s,11755 +django/contrib/postgres/search.py,sha256=GAZAOSVpSL-eDjHCPGPrSBqw0Meic44bqdNgLAIsz0c,11676 +django/contrib/postgres/serializers.py,sha256=wCg0IzTNeuVOiC2cdy1wio6gChjqVvH6Ri4hkCkEeXU,435 +django/contrib/postgres/signals.py,sha256=cpkaedbyvajpN4NNAYLA6TfKI_4fe9AU40CeYhYmS8Q,2870 +django/contrib/postgres/templates/postgres/widgets/split_array.html,sha256=AzaPLlNLg91qkVQwwtAJxwOqDemrtt_btSkWLpboJDs,54 +django/contrib/postgres/utils.py,sha256=32nCnzdMZ7Ra4dDonbIdv1aCppV3tnQnoEX9AhCJe38,1187 +django/contrib/postgres/validators.py,sha256=GCJtwISehlhcqQhR5JEfrcwPUcCJqtpFV_fu4aRLb34,2801 +django/contrib/redirects/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/redirects/admin.py,sha256=1bPOgeZYRYCHdh7s2SpXnuL2WsfdQjD96U5Y3xhRY8g,314 +django/contrib/redirects/apps.py,sha256=1uS5EBp7WwDnY0WHeaRYo7VW9j-s20h4KDdImodjCNg,251 +django/contrib/redirects/locale/af/LC_MESSAGES/django.mo,sha256=p1jR8LLNrzuDM6gvYBzQAS5xg7X8O17301Fo5xEU2yI,1151 +django/contrib/redirects/locale/af/LC_MESSAGES/django.po,sha256=wkVhdkjL6kI-0uxzWPCrEMhf_iUSbbHV1D0dFPIw1eU,1385 +django/contrib/redirects/locale/ar/LC_MESSAGES/django.mo,sha256=FfPauXNUmQxq0R1-eQ2xw2WY1Oi33sLwVhyKX10_zFw,1336 +django/contrib/redirects/locale/ar/LC_MESSAGES/django.po,sha256=X0xX51asSDWedd56riJ4UrsCGEjH-lZdkcilIg4amgI,1595 +django/contrib/redirects/locale/ar_DZ/LC_MESSAGES/django.mo,sha256=hg1lkBEORP2vgLPRbuKcXiIFUcTvAO7KrjbPXlWhvqY,1379 +django/contrib/redirects/locale/ar_DZ/LC_MESSAGES/django.po,sha256=O4quBKA1jHATGGeDqCONDFfAqvDvOAATIBvueeMphyY,1581 +django/contrib/redirects/locale/ast/LC_MESSAGES/django.mo,sha256=a1ixBQQIdBZ7o-ADnF2r74CBtPLsuatG7txjc05_GXI,1071 +django/contrib/redirects/locale/ast/LC_MESSAGES/django.po,sha256=PguAqeIUeTMWsADOYLTxoC6AuKrCloi8HN18hbm3pZ0,1266 +django/contrib/redirects/locale/az/LC_MESSAGES/django.mo,sha256=KzpRUrONOi5Cdr9sSRz3p0X-gGhD1-3LNhen-XDhO3g,1092 +django/contrib/redirects/locale/az/LC_MESSAGES/django.po,sha256=RGjd2J_pRdSkin4UlKxg7kc3aA8PCQRjDPXkpGZHdn0,1347 +django/contrib/redirects/locale/be/LC_MESSAGES/django.mo,sha256=fVqy28ml508UJf5AA-QVsS5dzKI8Q_ugZZ34WjTpJ-s,1426 +django/contrib/redirects/locale/be/LC_MESSAGES/django.po,sha256=zHBVewcpt0KoavV96v3F4wybqtkGb1jUuPz7sbiWWDI,1662 +django/contrib/redirects/locale/bg/LC_MESSAGES/django.mo,sha256=o-ETSDGtAFZRo3SPd_IHe0mJ3R0RHA32KpgfOmUH11M,1279 +django/contrib/redirects/locale/bg/LC_MESSAGES/django.po,sha256=9qm8s6vj-0LStnyEJ8iYVi13_MfugVAAs2RHvIi7kW8,1587 +django/contrib/redirects/locale/bn/LC_MESSAGES/django.mo,sha256=SbQh_pgxNCogvUFud7xW9T6NTAvpaQb2jngXCtpjICM,1319 +django/contrib/redirects/locale/bn/LC_MESSAGES/django.po,sha256=LgUuiPryDLSXxo_4KMCdjM5XC3BiRfINuEk0s5PUQYQ,1511 +django/contrib/redirects/locale/br/LC_MESSAGES/django.mo,sha256=Yt8xo5B5LJ9HB8IChCkj5mljFQAAKlaW_gurtF8q8Yw,1429 +django/contrib/redirects/locale/br/LC_MESSAGES/django.po,sha256=L2qPx6mZEVUNay1yYEweKBLr_fXVURCnACfsezfP_pI,1623 +django/contrib/redirects/locale/bs/LC_MESSAGES/django.mo,sha256=0Yak4rXHjRRXLu3oYYzvS8qxvk2v4IFvUiDPA68a5YI,1115 +django/contrib/redirects/locale/bs/LC_MESSAGES/django.po,sha256=s9Nhx3H4074hlSqo1zgQRJbozakdJTwA1aTuMSqEJWw,1316 +django/contrib/redirects/locale/ca/LC_MESSAGES/django.mo,sha256=VHE6qHCEoA7rQk0fMUpoTfwqSfu63-CiOFvhvKp5DMQ,1136 +django/contrib/redirects/locale/ca/LC_MESSAGES/django.po,sha256=PSMb_7iZBuYhtdR8byh9zr9dr50Z_tQ518DUlqoEA_M,1484 +django/contrib/redirects/locale/ckb/LC_MESSAGES/django.mo,sha256=23RM9kso65HHxGHQ_DKxGDaUkmdX72DfYvqQfhr7JKw,1340 +django/contrib/redirects/locale/ckb/LC_MESSAGES/django.po,sha256=cGrAq3e6h3vbYrtyi0oFSfZmLlJ0-Y3uqrvFon48n80,1521 +django/contrib/redirects/locale/cs/LC_MESSAGES/django.mo,sha256=UwYsoEHsg7FJLVe0JxdOa1cTGypqJFienAbWe7Vldf0,1229 +django/contrib/redirects/locale/cs/LC_MESSAGES/django.po,sha256=hnWJLXX7IjwZK7_8L3p-dpj5XpDmEo7lQ7-F4upjn7U,1504 +django/contrib/redirects/locale/cy/LC_MESSAGES/django.mo,sha256=NSGoK12A7gbtuAuzQEVFPNSZMqqmhHyRvTEn9PUm9So,1132 +django/contrib/redirects/locale/cy/LC_MESSAGES/django.po,sha256=jDmC64z5exPnO9zwRkBmpa9v3DBlaeHRhqZYPoWqiIY,1360 +django/contrib/redirects/locale/da/LC_MESSAGES/django.mo,sha256=_UVfTMRG__5j7Ak8Q3HtXSy_DPGpZ1XvKj9MHdmR_xI,1132 +django/contrib/redirects/locale/da/LC_MESSAGES/django.po,sha256=RAWWbZXbJciNSdw4skUEoTnOb19iKXAe1KXJLWi0zPQ,1418 +django/contrib/redirects/locale/de/LC_MESSAGES/django.mo,sha256=uh-ldy-QkWS5-ARX6cLyzxzdhbTb_chyEbBPFCvCKuE,1155 +django/contrib/redirects/locale/de/LC_MESSAGES/django.po,sha256=hhGNnVCRV4HNxhCYfmVXTOIkabD7qsVQccwxKa5Tz9g,1424 +django/contrib/redirects/locale/dsb/LC_MESSAGES/django.mo,sha256=LXgczA38RzrN7zSWpxKy8_RY4gPg5tZLl30CJGjJ63s,1236 +django/contrib/redirects/locale/dsb/LC_MESSAGES/django.po,sha256=rI9dyDp7zuZ6CjvFyo2OkGUDK5XzdvdI0ma8IGVkjp4,1431 +django/contrib/redirects/locale/el/LC_MESSAGES/django.mo,sha256=sD3HT4e53Yd3HmQap_Mqlxkm0xF98A6PFW8Lil0PihI,1395 +django/contrib/redirects/locale/el/LC_MESSAGES/django.po,sha256=puhVCcshg5HaPHsVAOucneVgBYT6swhCCBpVGOZykgA,1716 +django/contrib/redirects/locale/en/LC_MESSAGES/django.mo,sha256=U0OV81NfbuNL9ctF-gbGUG5al1StqN-daB-F-gFBFC8,356 +django/contrib/redirects/locale/en/LC_MESSAGES/django.po,sha256=u4RcMkFmNvlG9Bv6kM0a0scWUMDUbTEDJGR90-G8C0E,1123 +django/contrib/redirects/locale/en_AU/LC_MESSAGES/django.mo,sha256=wxCpSLGl_zsE47kDwilDkpihazwHkA363PvtGOLWhdk,1127 +django/contrib/redirects/locale/en_AU/LC_MESSAGES/django.po,sha256=zujH1WuxoHw_32flptG0x2Ob_BlilLKXuMjQxVbZmgw,1307 +django/contrib/redirects/locale/en_GB/LC_MESSAGES/django.mo,sha256=VscL30uJnV-eiQZITpBCy0xk_FfKdnMh4O9Hk4HGxww,1053 +django/contrib/redirects/locale/en_GB/LC_MESSAGES/django.po,sha256=loe8xIVjZ7eyteQNLPoa-QceBZdgky22dR6deK5ubmA,1246 +django/contrib/redirects/locale/eo/LC_MESSAGES/django.mo,sha256=WZ3NHrS0qMoCJER5jWnGI12bvY5wH0yytM8F7BFTgYc,712 +django/contrib/redirects/locale/eo/LC_MESSAGES/django.po,sha256=T-Gw75sOjZgqpwjIfieIrLxbg1kekWzjrJYSMld2OEQ,1299 +django/contrib/redirects/locale/es/LC_MESSAGES/django.mo,sha256=xyeIQL_pHFyo7p7SkeuxzKdDsma2EXhvnPNDHUhaBv8,1159 +django/contrib/redirects/locale/es/LC_MESSAGES/django.po,sha256=Y3hPQrcbhLtR-pPYRJJXkJME5M8Enr20j9D63hhe9ZA,1490 +django/contrib/redirects/locale/es_AR/LC_MESSAGES/django.mo,sha256=JdKzpdyf9W2m_0_NguvXvyciOh6LAATfE6lqcsp45To,1144 +django/contrib/redirects/locale/es_AR/LC_MESSAGES/django.po,sha256=3zrKJXLh_mrjc4A6g9O6ePyFz8PNUMYTPjNFpvEhaDo,1364 +django/contrib/redirects/locale/es_CO/LC_MESSAGES/django.mo,sha256=wcAMOiqsgz2KEpRwirRH9FNoto6vmo_hxthrQJi0IHU,1147 +django/contrib/redirects/locale/es_CO/LC_MESSAGES/django.po,sha256=n8DM14vHekZRayH0B6Pm3L5XnSo4lto4ZAdu4OhcOmc,1291 +django/contrib/redirects/locale/es_MX/LC_MESSAGES/django.mo,sha256=38fbiReibMAmC75BCCbyo7pA2VA3QvmRqVEo_K6Ejow,1116 +django/contrib/redirects/locale/es_MX/LC_MESSAGES/django.po,sha256=t7R6PiQ1bCc7jhfMrjHlZxVQ6BRlWT2Vv4XXhxBD_Oo,1397 +django/contrib/redirects/locale/es_VE/LC_MESSAGES/django.mo,sha256=59fZBDut-htCj38ZUoqPjhXJPjZBz-xpU9__QFr3kLs,486 +django/contrib/redirects/locale/es_VE/LC_MESSAGES/django.po,sha256=f4XZW8OHjRJoztMJtSDCxd2_Mfy-XK44hLtigjGSsZY,958 +django/contrib/redirects/locale/et/LC_MESSAGES/django.mo,sha256=34-Z1s9msdnj6U7prMctEWCxAR8TNnP44MIoyUuFsls,1131 +django/contrib/redirects/locale/et/LC_MESSAGES/django.po,sha256=1VWcUbM9z_nNmiGnT9Mka3Y3ZLRVHuJdS_j_yNXvmQ0,1479 +django/contrib/redirects/locale/eu/LC_MESSAGES/django.mo,sha256=yHlAEz01pWse4ZworAj7JiATUam5Fp20EZd_3PRgSNw,1126 +django/contrib/redirects/locale/eu/LC_MESSAGES/django.po,sha256=zAvSdahjvq727hXeGjHJ_R5L5meCrOv98tbH3rwlBcE,1404 +django/contrib/redirects/locale/fa/LC_MESSAGES/django.mo,sha256=vZa1KKm2y8duEv9UbJMyiM8WO2EAXcevdR3Lj1ISgLU,1234 +django/contrib/redirects/locale/fa/LC_MESSAGES/django.po,sha256=1quB0Wx5VTIjX2QUCpENl1GA2hpSdsRpgK931jr20B0,1541 +django/contrib/redirects/locale/fi/LC_MESSAGES/django.mo,sha256=xJEd4M2IowXxKBlaGuOEgFKA9OuihcgPoK07Beat4cc,1164 +django/contrib/redirects/locale/fi/LC_MESSAGES/django.po,sha256=1I7AoXMPRDMY6TCjPkQh0Q9g68r9BwKOwki9DybcFWc,1429 +django/contrib/redirects/locale/fr/LC_MESSAGES/django.mo,sha256=YhVNoNaHdSOp2P2F7xfo2MHCd2KkHiehpVjLyJ4VLuw,1155 +django/contrib/redirects/locale/fr/LC_MESSAGES/django.po,sha256=-ljzEKiU05annJ8DHw4OOg8eDCAnWLV2V33R-tQn9dE,1391 +django/contrib/redirects/locale/fy/LC_MESSAGES/django.mo,sha256=YQQy7wpjBORD9Isd-p0lLzYrUgAqv770_56-vXa0EOc,476 +django/contrib/redirects/locale/fy/LC_MESSAGES/django.po,sha256=D7xverCbf3kTCcFM8h7EKWM5DcxZRqeOSKDB1irbKeE,948 +django/contrib/redirects/locale/ga/LC_MESSAGES/django.mo,sha256=blwOMshClFZKvOZXVvqENK_E_OkdS1ydbjQCDXcHXd4,1075 +django/contrib/redirects/locale/ga/LC_MESSAGES/django.po,sha256=76rdrG4GVbcKwgUQN4bB-B0t6hpivCA_ehf4uzGM_mY,1341 +django/contrib/redirects/locale/gd/LC_MESSAGES/django.mo,sha256=baZXdulbPZwe4_Q3OwfHFl4GJ4hCYtoZz-lE4wcdJvg,1250 +django/contrib/redirects/locale/gd/LC_MESSAGES/django.po,sha256=M4E2giFgzRowd3OsvhD389MyJmT5osKz1Vs1sEfmUpU,1428 +django/contrib/redirects/locale/gl/LC_MESSAGES/django.mo,sha256=au4ulT76A8cd_C_DmtEdiuQ14dIJaprVvFbS9_hYRNk,1131 +django/contrib/redirects/locale/gl/LC_MESSAGES/django.po,sha256=r2t9gHhIvPb8d9XR8fG0b_eW5xkkQswuj4ekJI9x90w,1393 +django/contrib/redirects/locale/he/LC_MESSAGES/django.mo,sha256=Yu8KTmY0mJEcxhkhTEVElPBaWwO9Zj4NqC8eopW0cRc,1278 +django/contrib/redirects/locale/he/LC_MESSAGES/django.po,sha256=UcCd_BqHOkTV1dP0hgJ4dNQzBZ4p8TujwSjF3FWAMjo,1513 +django/contrib/redirects/locale/hi/LC_MESSAGES/django.mo,sha256=onR8L7Kvkx6HgFLK7jT-wA_zjarBN8pyltG6BbKFIWU,1409 +django/contrib/redirects/locale/hi/LC_MESSAGES/django.po,sha256=fNv9_qwR9iS-pjWNXnrUFIqvc10lwg3bfj5lgdQOy1U,1649 +django/contrib/redirects/locale/hr/LC_MESSAGES/django.mo,sha256=7wHi6Uu0czZhI6v0ndJJ1wSkalTRfn7D5ovyw8tr4U4,1207 +django/contrib/redirects/locale/hr/LC_MESSAGES/django.po,sha256=HtxZwZ-ymmf-XID0z5s7nGYg-4gJL8i6FDGWt9i4Wns,1406 +django/contrib/redirects/locale/hsb/LC_MESSAGES/django.mo,sha256=6lfIW4LcMGvuLOY0U4w1V6Xwcd_TsUC3r-QzZOOLwys,1221 +django/contrib/redirects/locale/hsb/LC_MESSAGES/django.po,sha256=l5pATo8NHa8ypB8dCigRwqpLZvV8W0v2vPh60oAeGn0,1420 +django/contrib/redirects/locale/hu/LC_MESSAGES/django.mo,sha256=4oYBNGEmFMISzw3LExVf6CHsJD_o20mMy132pwzM-wk,1111 +django/contrib/redirects/locale/hu/LC_MESSAGES/django.po,sha256=UYJ_ZrAnOqA6S8nkkfN_FBLxCyPHJjOMd1OSIUVc8aY,1383 +django/contrib/redirects/locale/hy/LC_MESSAGES/django.mo,sha256=gT5x1TZXMNyBwfmQ-C_cOB60JGYdKIM7tVb3-J5d6nw,1261 +django/contrib/redirects/locale/hy/LC_MESSAGES/django.po,sha256=40QTpth2AVeoy9P36rMJC2C82YsBh_KYup19WL6zM6w,1359 +django/contrib/redirects/locale/ia/LC_MESSAGES/django.mo,sha256=PDB5ZQP6iH31xN6N2YmPZYjt6zzc88TRmh9_gAWH2U0,1152 +django/contrib/redirects/locale/ia/LC_MESSAGES/django.po,sha256=GXjbzY-cQz2QLx_iuqgijT7VUMcoNKL7prbP6yIbj8E,1297 +django/contrib/redirects/locale/id/LC_MESSAGES/django.mo,sha256=XEsvVWMR9As9csO_6iXNAcLZrErxz3HfDj5GTe06fJU,1105 +django/contrib/redirects/locale/id/LC_MESSAGES/django.po,sha256=t8FoC1xIB-XHDplyDJByQGFnHggxR0LSfUMGwWoAKWE,1410 +django/contrib/redirects/locale/io/LC_MESSAGES/django.mo,sha256=vz7TWRML-DFDFapbEXTByb9-pRQwoeJ0ApSdh6nOzXY,1019 +django/contrib/redirects/locale/io/LC_MESSAGES/django.po,sha256=obStuMYYSQ7x2utkGS3gekdPfnsNAwp3DcNwlwdg1sI,1228 +django/contrib/redirects/locale/is/LC_MESSAGES/django.mo,sha256=aMjlGilYfP7clGriAp1Za60uCD40rvLt9sKXuYX3ABg,1040 +django/contrib/redirects/locale/is/LC_MESSAGES/django.po,sha256=nw5fxVV20eQqsk4WKg6cIiKttG3zsITSVzH4p5xBV8s,1299 +django/contrib/redirects/locale/it/LC_MESSAGES/django.mo,sha256=bBj6dvhZSpxojLZ0GiMBamh1xiluxAYMt6RHubi9CxU,1092 +django/contrib/redirects/locale/it/LC_MESSAGES/django.po,sha256=NHSVus7ixtrB7JDIrYw22srZcse5i4Z9y8Ply_-Jcts,1390 +django/contrib/redirects/locale/ja/LC_MESSAGES/django.mo,sha256=XSJw3iLK0gYVjZ86MYuV4jfoiN_-WkH--oMK5uW9cs8,1193 +django/contrib/redirects/locale/ja/LC_MESSAGES/django.po,sha256=SlYrmC3arGgS7SL8cCnq7d37P-bQGcmpgUXAwVC2eRw,1510 +django/contrib/redirects/locale/ka/LC_MESSAGES/django.mo,sha256=0aOLKrhUX6YAIMNyt6KES9q2iFk2GupEr76WeGlJMkk,1511 +django/contrib/redirects/locale/ka/LC_MESSAGES/django.po,sha256=AQWIEdhxp55XnJwwHrUxxQaGbLJPmdo1YLeT86IJqnY,1725 +django/contrib/redirects/locale/kab/LC_MESSAGES/django.mo,sha256=Ogx9NXK1Nfw4ctZfp-slIL81ziDX3f4DZ01OkVNY5Tw,699 +django/contrib/redirects/locale/kab/LC_MESSAGES/django.po,sha256=gI6aUPkXH-XzKrStDsMCMNfQKDEc-D1ffqE-Z-ItQuI,1001 +django/contrib/redirects/locale/kk/LC_MESSAGES/django.mo,sha256=KVLc6PKL1MP_Px0LmpoW2lIvgLiSzlvoJ9062F-s3Zw,1261 +django/contrib/redirects/locale/kk/LC_MESSAGES/django.po,sha256=Xoy4mnOT51F_GS1oIO91EAuwt-ZfePKh-sutedo6D_g,1478 +django/contrib/redirects/locale/km/LC_MESSAGES/django.mo,sha256=tcW1s7jvTG0cagtdRNT0jSNkhX-B903LKl7bK31ZvJU,1248 +django/contrib/redirects/locale/km/LC_MESSAGES/django.po,sha256=KJ4h1umpfFLdsWZtsfXoeOl6cUPUD97U4ISWt80UZ2U,1437 +django/contrib/redirects/locale/kn/LC_MESSAGES/django.mo,sha256=24GHcQlEoCDri-98eLtqLbGjtJz9cTPAfYdAijsL5ck,788 +django/contrib/redirects/locale/kn/LC_MESSAGES/django.po,sha256=xkH24itr2fpuCQMGQ3xssOqaN_7KzM-GLy0u00ti27I,1245 +django/contrib/redirects/locale/ko/LC_MESSAGES/django.mo,sha256=viohri0QV3d46CN-YZP1k7w83Ac8r5lCkWU8fhbAEEc,1134 +django/contrib/redirects/locale/ko/LC_MESSAGES/django.po,sha256=8TsMfyl-BqGb-8fI12pazzlI7x3X1yruIYuvFroLti0,1521 +django/contrib/redirects/locale/ky/LC_MESSAGES/django.mo,sha256=4jX_g-hledmjWEx0RvY99G5QcBj_mQt_HZzpd000J44,1265 +django/contrib/redirects/locale/ky/LC_MESSAGES/django.po,sha256=yvx21nxsqqVzPyyxX9_rF-oeaY2WszXrG4ZDSZTW6-4,1522 +django/contrib/redirects/locale/lb/LC_MESSAGES/django.mo,sha256=xokesKl7h7k9dXFKIJwGETgwx1Ytq6mk2erBSxkgY-o,474 +django/contrib/redirects/locale/lb/LC_MESSAGES/django.po,sha256=Hv1CF9CC78YuVVNpklDtPJDU5-iIUeuXcljewmc9akg,946 +django/contrib/redirects/locale/lt/LC_MESSAGES/django.mo,sha256=reiFMXJnvE4XUosbKjyvUFzl4IKjlJoFK1gVJE9Tbnc,1191 +django/contrib/redirects/locale/lt/LC_MESSAGES/django.po,sha256=G56UIYuuVLgwzHCIj_suHNYPe1z76Y_cauWfGEs4nKI,1448 +django/contrib/redirects/locale/lv/LC_MESSAGES/django.mo,sha256=slGK6O2tYD5yciS8m_7h2WA4LOPf05nQ4oTRKB63etE,1175 +django/contrib/redirects/locale/lv/LC_MESSAGES/django.po,sha256=GUDn1IYQ5UMOQUBvGfuVOeVb-bpf5FHVigqTt_N0I0M,1442 +django/contrib/redirects/locale/mk/LC_MESSAGES/django.mo,sha256=3XGgf2K60LclScPKcgw07TId6x535AW5jtGVJ9lC01A,1353 +django/contrib/redirects/locale/mk/LC_MESSAGES/django.po,sha256=Smsdpid5VByoxvnfzju_XOlp6aTPl8qshFptot3cRYM,1596 +django/contrib/redirects/locale/ml/LC_MESSAGES/django.mo,sha256=IhSkvbgX9xfE4GypOQ7W7SDM-wOOqx1xgSTW7L1JofU,1573 +django/contrib/redirects/locale/ml/LC_MESSAGES/django.po,sha256=9KpXf88GRUB5I51Rj3q9qhvhjHFINuiJ9ig0SZdYE6k,1755 +django/contrib/redirects/locale/mn/LC_MESSAGES/django.mo,sha256=14fdHC_hZrRaA0EAFzBJy8BHj4jMMX6l2e6rLLBtJ8E,1274 +django/contrib/redirects/locale/mn/LC_MESSAGES/django.po,sha256=7_QzUWf5l0P-7gM35p9UW7bOj33NabQq_zSrekUeZsY,1502 +django/contrib/redirects/locale/mr/LC_MESSAGES/django.mo,sha256=2Z5jaGJzpiJTCnhCk8ulCDeAdj-WwR99scdHFPRoHoA,468 +django/contrib/redirects/locale/mr/LC_MESSAGES/django.po,sha256=0aGKTlriCJoP-Tirl-qCl7tjjpjURhgCjRGmurHVO3c,940 +django/contrib/redirects/locale/ms/LC_MESSAGES/django.mo,sha256=WUk6hvvHPWuylCGiDvy0MstWoQ1mdmwwfqlms1Nv4Ng,1094 +django/contrib/redirects/locale/ms/LC_MESSAGES/django.po,sha256=bsQDwxqtS5FgPCqTrfm9kw2hH_R2y44DnI5nluUgduc,1255 +django/contrib/redirects/locale/my/LC_MESSAGES/django.mo,sha256=H5-y9A3_1yIXJzC4sSuHqhURxhOlnYEL8Nvc0IF4zUE,549 +django/contrib/redirects/locale/my/LC_MESSAGES/django.po,sha256=MZGNt0jMQA6aHA6OmjvaC_ajvRWfUfDiKkV0j3_E480,1052 +django/contrib/redirects/locale/nb/LC_MESSAGES/django.mo,sha256=pxRtj5VFxTQBbi_mDS05iGoQs4BZ4y6LLJZ9pozJezY,1110 +django/contrib/redirects/locale/nb/LC_MESSAGES/django.po,sha256=ALYXciVa0d0sG70dqjtk17Yh_qwzKAzTXDlEZSU9kc0,1392 +django/contrib/redirects/locale/ne/LC_MESSAGES/django.mo,sha256=TxTnBGIi5k0PKAjADeCuOAJQV5dtzLrsFRXBXtfszWI,1420 +django/contrib/redirects/locale/ne/LC_MESSAGES/django.po,sha256=5b5R-6AlSIQrDyTtcmquoW5xrQRGZwlxZpBpZfVo5t4,1607 +django/contrib/redirects/locale/nl/LC_MESSAGES/django.mo,sha256=Xeh1YbEAu7Lhz07RXPTMDyv7AyWF9Bhe-9oHdWT74mo,1129 +django/contrib/redirects/locale/nl/LC_MESSAGES/django.po,sha256=QuNgrX7w2wO15KPEe3ogVhXbkt0v60EwKmKfD7-PedU,1476 +django/contrib/redirects/locale/nn/LC_MESSAGES/django.mo,sha256=8TQXBF2mzENl7lFpcrsKxkJ4nKySTOgXJM5_I2OD7q8,1143 +django/contrib/redirects/locale/nn/LC_MESSAGES/django.po,sha256=pfrKVQd1wLKKpq-b7CBpc-rZnEEgyZFDSjbipsEiwxM,1344 +django/contrib/redirects/locale/os/LC_MESSAGES/django.mo,sha256=joQ-ibV9_6ctGMNPLZQLCx5fUamRQngs6_LDd_s9sMQ,1150 +django/contrib/redirects/locale/os/LC_MESSAGES/django.po,sha256=ZwFWiuGS9comy7r2kMnKuqaPOvVehVdAAuFvXM5ldxM,1358 +django/contrib/redirects/locale/pa/LC_MESSAGES/django.mo,sha256=MY-OIDNXlZth-ZRoOJ52nlUPg_51_F5k0NBIpc7GZEw,748 +django/contrib/redirects/locale/pa/LC_MESSAGES/django.po,sha256=TPDTK2ZvDyvO1ob8Qfr64QDbHVWAREfEeBO5w9jf63E,1199 +django/contrib/redirects/locale/pl/LC_MESSAGES/django.mo,sha256=9Sc_8aDC8-PADnr4hYdat6iRUXj0QxsWR1RGWKIQP3M,1285 +django/contrib/redirects/locale/pl/LC_MESSAGES/django.po,sha256=RLuSAlWQPvxDGSNHL3j5ohMdf4IZL-g21-_QIuTdY4c,1605 +django/contrib/redirects/locale/pt/LC_MESSAGES/django.mo,sha256=WocPaVk3fQEz_MLmGVtFBGwsThD-gNU7GDocqEbeaBA,1129 +django/contrib/redirects/locale/pt/LC_MESSAGES/django.po,sha256=ptCzoE41c9uFAbgSjb6VHSFYPEUv_51YyBdoThXN3XA,1350 +django/contrib/redirects/locale/pt_BR/LC_MESSAGES/django.mo,sha256=LxFEZCH75ucCaB5fEmdsjEJi5aJa3barRLqcd6r-gj0,1171 +django/contrib/redirects/locale/pt_BR/LC_MESSAGES/django.po,sha256=PO5whkwiagEN_s8ViBDN41dW35wdjAuXZBB1j2m09lY,1615 +django/contrib/redirects/locale/ro/LC_MESSAGES/django.mo,sha256=D8FkmV6IxZOn5QAPBu9PwhStBpVQWudU62wKa7ADfJY,1158 +django/contrib/redirects/locale/ro/LC_MESSAGES/django.po,sha256=Z_-pDi2-A7_KXrEQtFlAJ_KLO0vXFKCbMphsNlqfNJk,1477 +django/contrib/redirects/locale/ru/LC_MESSAGES/django.mo,sha256=IvO0IXq1xuX0wpo2hV8po1AMifLS3ElGyQal0vmC_Jw,1457 +django/contrib/redirects/locale/ru/LC_MESSAGES/django.po,sha256=FHb4L3RMVV5ajxGj9y6ZymPtO_XjZrhHmvCZBPwwzmQ,1762 +django/contrib/redirects/locale/sk/LC_MESSAGES/django.mo,sha256=TTgi-SVyS9nbBCsI6NPbg-QA-GMc_-ciYewOUHDb1bM,1222 +django/contrib/redirects/locale/sk/LC_MESSAGES/django.po,sha256=yDuSGdVfHhsorxQNQ6S7ocyJfrI07pcLzyhkvXNCZXk,1506 +django/contrib/redirects/locale/sl/LC_MESSAGES/django.mo,sha256=GAZtOFSUxsOHdXs3AzT40D-3JFWIlNDZU_Z-cMvdaHo,1173 +django/contrib/redirects/locale/sl/LC_MESSAGES/django.po,sha256=gkZTyxNh8L2gNxyLVzm-M1HTiK8KDvughTa2MK9NzWo,1351 +django/contrib/redirects/locale/sq/LC_MESSAGES/django.mo,sha256=f2HyVjWFGnjNXV-EIk0YMFaMH6_ZwYLYgSDwU4fIJfM,1165 +django/contrib/redirects/locale/sq/LC_MESSAGES/django.po,sha256=gbd4JxoevGfDTRx3iYfDtlnh54EwyRKYXxs4XagHvRM,1453 +django/contrib/redirects/locale/sr/LC_MESSAGES/django.mo,sha256=OK90avxrpYxBcvPIZ_tDlSZP6PyRCzFg_7h0F_JlMy8,1367 +django/contrib/redirects/locale/sr/LC_MESSAGES/django.po,sha256=Ipi7j7q5N8aNGWmkz5XGlOPqpD46xCLKarfs-lNbKqM,1629 +django/contrib/redirects/locale/sr_Latn/LC_MESSAGES/django.mo,sha256=qYXT0j80c7a5jMsxeezncAL9Gff2Pb7eJz8iTX0TRX4,1210 +django/contrib/redirects/locale/sr_Latn/LC_MESSAGES/django.po,sha256=CL3ij3uGK8UOMggLXf0MctEydLbyi-9zvkXN5Teuu9c,1424 +django/contrib/redirects/locale/sv/LC_MESSAGES/django.mo,sha256=2j_IyOgbM_yED5lF10r7KGguEC2qX58dRIVogWj5PVY,1134 +django/contrib/redirects/locale/sv/LC_MESSAGES/django.po,sha256=lIFNLfEondtzlwlG3tDf3AH59uEotLtj-XdL87c-QUo,1404 +django/contrib/redirects/locale/sw/LC_MESSAGES/django.mo,sha256=qQjxB8Z6uKoNOa3wI6aDiAYLpWhx7z2yI7nEbXtMOXc,1165 +django/contrib/redirects/locale/sw/LC_MESSAGES/django.po,sha256=rAAmAwjvy69tVeB-QeccIS8CMA96XLeWdfRwDy3_QA0,1385 +django/contrib/redirects/locale/ta/LC_MESSAGES/django.mo,sha256=AE6Py2_CV2gQKjKQAa_UgkLT9i61x3i1hegQpRGuZZM,1502 +django/contrib/redirects/locale/ta/LC_MESSAGES/django.po,sha256=ojdq8p4HnwtK0n6By2I6_xuucOpJIobJEGRMGc_TrS8,1700 +django/contrib/redirects/locale/te/LC_MESSAGES/django.mo,sha256=Gtcs4cbgrD7-bSkPKiPbM5DcjONS2fSdHhvWdbs_E1M,467 +django/contrib/redirects/locale/te/LC_MESSAGES/django.po,sha256=RT-t3TjcOLyNQQWljVrIcPWErKssh_HQMyGujloy-EI,939 +django/contrib/redirects/locale/tg/LC_MESSAGES/django.mo,sha256=6e4Pk9vX1csvSz80spVLhNTd3N251JrXaCga9n60AP8,782 +django/contrib/redirects/locale/tg/LC_MESSAGES/django.po,sha256=2Cmle5usoNZBo8nTfAiqCRq3KqN1WKKdc-mogUOJm9I,1177 +django/contrib/redirects/locale/th/LC_MESSAGES/django.mo,sha256=1l6eO0k1KjcmuRJKUS4ZdtJGhAUmUDMAMIeNwEobQqY,1331 +django/contrib/redirects/locale/th/LC_MESSAGES/django.po,sha256=DVVqpGC6zL8Hy8e6P8ZkhKbvcMJmXV5euLxmfoTCtms,1513 +django/contrib/redirects/locale/tk/LC_MESSAGES/django.mo,sha256=NkxO6C7s1HHT1Jrmwad9zaD3pPyW_sPuZz3F2AGUD7M,1155 +django/contrib/redirects/locale/tk/LC_MESSAGES/django.po,sha256=0EQj1I1oNbAovKmF7o2rQ8_QsQiYqEFDab2KlCFw0s0,1373 +django/contrib/redirects/locale/tr/LC_MESSAGES/django.mo,sha256=-qySxKYwxfFO79cBytvzTBeFGdio1wJlM5DeBBfdxns,1133 +django/contrib/redirects/locale/tr/LC_MESSAGES/django.po,sha256=-03z3YMI6tlt12xwFI2lWchOxiIVbkdVRhghaCoMKlk,1408 +django/contrib/redirects/locale/tt/LC_MESSAGES/django.mo,sha256=Hf1JXcCGNwedxy1nVRM_pQ0yUebC-tvOXr7P0h86JyI,1178 +django/contrib/redirects/locale/tt/LC_MESSAGES/django.po,sha256=2WCyBQtqZk-8GXgtu-x94JYSNrryy2QoMnirhiBrgV0,1376 +django/contrib/redirects/locale/udm/LC_MESSAGES/django.mo,sha256=CNmoKj9Uc0qEInnV5t0Nt4ZnKSZCRdIG5fyfSsqwky4,462 +django/contrib/redirects/locale/udm/LC_MESSAGES/django.po,sha256=xsxlm4itpyLlLdPQRIHLuvTYRvruhM3Ezc9jtp3XSm4,934 +django/contrib/redirects/locale/ug/LC_MESSAGES/django.mo,sha256=qV4UXMJUeNM2vw0LWn-YR9TDn1sQVvnEUcXh7_AX3Jo,1409 +django/contrib/redirects/locale/ug/LC_MESSAGES/django.po,sha256=dilTTU3q5BCYiUIgpjncD3ijPaQgp1l73poSrsZiUUc,1633 +django/contrib/redirects/locale/uk/LC_MESSAGES/django.mo,sha256=QbN1ABfbr2YbZQXz2U4DI-6iTvWoKPrLAn5tGq57G5Y,1569 +django/contrib/redirects/locale/uk/LC_MESSAGES/django.po,sha256=pH9M4ilsJneoHw6E1E3T54QCHGS_i4tlhDc0nbAJP8I,1949 +django/contrib/redirects/locale/ur/LC_MESSAGES/django.mo,sha256=CQkt-yxyAaTd_Aj1ZZC8s5-4fI2TRyTEZ-SYJZgpRrQ,1138 +django/contrib/redirects/locale/ur/LC_MESSAGES/django.po,sha256=CkhmN49PvYTccvlSRu8qGpcbx2C-1aY7K3Lq1VC2fuM,1330 +django/contrib/redirects/locale/uz/LC_MESSAGES/django.mo,sha256=vD0Y920SSsRsLROKFaU6YM8CT5KjQxJcgMh5bZ4Pugo,743 +django/contrib/redirects/locale/uz/LC_MESSAGES/django.po,sha256=G2Rj-6g8Vse2Bp8L_hGIO84S--akagMXj8gSa7F2lK4,1195 +django/contrib/redirects/locale/vi/LC_MESSAGES/django.mo,sha256=BquXycJKh-7-D9p-rGUNnjqzs1d6S1YhEJjFW8_ARFA,1106 +django/contrib/redirects/locale/vi/LC_MESSAGES/django.po,sha256=xsCASrGZNbQk4d1mhsTZBcCpPJ0KO6Jr4Zz1wfnL67s,1301 +django/contrib/redirects/locale/zh_Hans/LC_MESSAGES/django.mo,sha256=iftb_HccNV383_odHbB6Tikn2h7EtP_9QK-Plq2xwTY,1100 +django/contrib/redirects/locale/zh_Hans/LC_MESSAGES/django.po,sha256=xZmfuCEYx7ou_qvtxBcBly5mBmkSBEhnx0xqJj3nvMw,1490 +django/contrib/redirects/locale/zh_Hant/LC_MESSAGES/django.mo,sha256=-H2o5p5v8j5RqKZ6vOsWToFWGOn8CaO3KSTiU42Zqjk,1071 +django/contrib/redirects/locale/zh_Hant/LC_MESSAGES/django.po,sha256=fQicS5nmJLgloKM83l6NcSJp36-Wjn2Dl9jf03e0pGo,1334 +django/contrib/redirects/middleware.py,sha256=ydqidqi5JTaoguEFQBRzLEkU3HeiohgVsFglHUE-HIU,1921 +django/contrib/redirects/migrations/0001_initial.py,sha256=0mXB5TgK_fwYbmbB_e7tKSjgOvpHWnZXg0IFcVtnmfU,2101 +django/contrib/redirects/migrations/0002_alter_redirect_new_path_help_text.py,sha256=RXPdSbYewnW1bjjXxNqUIL-qIeSxdBUehBp0BjfRl8o,635 +django/contrib/redirects/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/redirects/models.py,sha256=KJ6mj0BS243BNPKp26K7OSqcT9j49FPth5m0gNWWxFM,1083 +django/contrib/sessions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/sessions/apps.py,sha256=5WIMqa3ymqEvYMnFHe3uWZB8XSijUF_NSgaorRD50Lg,194 +django/contrib/sessions/backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/sessions/backends/base.py,sha256=xm9Rs0ZI8ERP6cZ-N4KdfVww3aWiXC8FcgcxQWNdrqw,11744 +django/contrib/sessions/backends/cache.py,sha256=Dz4lOirEI3ZSrvOWnAffQpyA53TuPm3MmV1u8jkT-hI,2741 +django/contrib/sessions/backends/cached_db.py,sha256=pxPlY9klOH0NCht8OZrHQew_UkMrQlKMtIKMLYIv2DI,2098 +django/contrib/sessions/backends/db.py,sha256=qEYZNmyWk1pBbuXGXbTsLtQ2Xt_HgoRALxTQm55ZLy0,3785 +django/contrib/sessions/backends/file.py,sha256=I4UHAdsrOaJBX_hg-u9hQ-xLMLf4qw4r27hc0LsTBxs,7760 +django/contrib/sessions/backends/signed_cookies.py,sha256=keRgy5CyvufiEo4A91znOKbX6UOzzH2hzaw51UzK_0Y,2676 +django/contrib/sessions/base_session.py,sha256=1woSGGF4IFWm2apOabxtdQHeVS6OmnivL_fwjUYGJwc,1490 +django/contrib/sessions/exceptions.py,sha256=KhkhXiFwfUflSP_t6wCLOEXz1YjBRTKVNbrLmGhOTLo,359 +django/contrib/sessions/locale/af/LC_MESSAGES/django.mo,sha256=0DS0pgVrMN-bUimDfesgHs8Lgr0loz2c6nJdz58RxyQ,717 +django/contrib/sessions/locale/af/LC_MESSAGES/django.po,sha256=ZJRLBshQCAiTTAUycdB3MZIadLeHR5LxbSlDvSWLnEo,838 +django/contrib/sessions/locale/ar/LC_MESSAGES/django.mo,sha256=yoepqaR68PTGLx--cAOzP94Sqyl5xIYpeQ0IFWgY380,846 +django/contrib/sessions/locale/ar/LC_MESSAGES/django.po,sha256=ZgwtBYIdtnqp_8nKHXF1NVJFzQU81-3yv9b7STrQHMc,995 +django/contrib/sessions/locale/ar_DZ/LC_MESSAGES/django.mo,sha256=_iSasR22CxvNWfei6aE_24woPhhhvNzQl5FUO_649dc,817 +django/contrib/sessions/locale/ar_DZ/LC_MESSAGES/django.po,sha256=vop5scstamgFSnO_FWXCEnI7R1N26t7jy_mZUAfETcY,978 +django/contrib/sessions/locale/ast/LC_MESSAGES/django.mo,sha256=hz2m-PkrHby2CKfIOARj6kCzisT-Vs0syfDSTx_iVVw,702 +django/contrib/sessions/locale/ast/LC_MESSAGES/django.po,sha256=M90j1Nx6oDJ16hguUkfKYlyb5OymUeZ5xzPixWxSC7I,846 +django/contrib/sessions/locale/az/LC_MESSAGES/django.mo,sha256=_4XcYdtRasbCjRoaWGoULsXX2cEa--KdRdqbnGoaRuM,731 +django/contrib/sessions/locale/az/LC_MESSAGES/django.po,sha256=qYd7vz6A-hHQNwewzI6wEsxRVLdoc2xLGm1RPW0Hxc4,891 +django/contrib/sessions/locale/be/LC_MESSAGES/django.mo,sha256=FHZ72QuOd-vAOjOXisLs4CaEk7uZuzjO_EfUSB6754M,854 +django/contrib/sessions/locale/be/LC_MESSAGES/django.po,sha256=tHsYVn3XNTcukB0SrHUWP1iV763rrQHCimOyJHRPiek,1023 +django/contrib/sessions/locale/bg/LC_MESSAGES/django.mo,sha256=fFZ8EgRlJ1Z-IP8gPtsUXAnqVHbqQRZpYv6PLWNlNVA,759 +django/contrib/sessions/locale/bg/LC_MESSAGES/django.po,sha256=tXcaDPNmFIv0RU-7sGscRkLCbKEgTBowzVj3AYymarY,997 +django/contrib/sessions/locale/bn/LC_MESSAGES/django.mo,sha256=0BdFN7ou9tmoVG00fCA-frb1Tri3iKz43W7SWal398s,762 +django/contrib/sessions/locale/bn/LC_MESSAGES/django.po,sha256=LycmTel6LXV2HGGN6qzlAfID-cVEQCNnW1Nv_hbWXJk,909 +django/contrib/sessions/locale/br/LC_MESSAGES/django.mo,sha256=6ubPQUyXX08KUssyVZBMMkTlD94mlA6wzsteAMiZ8C8,1027 +django/contrib/sessions/locale/br/LC_MESSAGES/django.po,sha256=LKxGGHOQejKpUp18rCU2FXW8D_H3WuP_P6dPlEluwcE,1201 +django/contrib/sessions/locale/bs/LC_MESSAGES/django.mo,sha256=M7TvlJMrSUAFhp7oUSpUKejnbTuIK-19yiGBBECl9Sc,759 +django/contrib/sessions/locale/bs/LC_MESSAGES/django.po,sha256=Ur0AeRjXUsLgDJhcGiw75hRk4Qe98DzPBOocD7GFDRQ,909 +django/contrib/sessions/locale/ca/LC_MESSAGES/django.mo,sha256=tbaZ48PaihGGD9-2oTKiMFY3kbXjU59nNciCRINOBNk,738 +django/contrib/sessions/locale/ca/LC_MESSAGES/django.po,sha256=tJuJdehKuD9aXOauWOkE5idQhsVsLbeg1Usmc6N_SP0,906 +django/contrib/sessions/locale/ckb/LC_MESSAGES/django.mo,sha256=qTCUlxmStU9w1nXRAc_gRodaN6ojJK_XAxDXoYC5vQI,741 +django/contrib/sessions/locale/ckb/LC_MESSAGES/django.po,sha256=F2bHLL66fWF5_VTM5QvNUFakY7gPRDr1qCjW6AkYxec,905 +django/contrib/sessions/locale/cs/LC_MESSAGES/django.mo,sha256=wEFP4NNaRQDbcbw96UC906jN4rOrlPJMn60VloXr944,759 +django/contrib/sessions/locale/cs/LC_MESSAGES/django.po,sha256=7XkKESwfOmbDRDbUYr1f62-fDOuyI-aCqLGaEiDrmX8,962 +django/contrib/sessions/locale/cy/LC_MESSAGES/django.mo,sha256=GeWVeV2PvgLQV8ecVUA2g3-VvdzMsedgIDUSpn8DByk,774 +django/contrib/sessions/locale/cy/LC_MESSAGES/django.po,sha256=zo18MXtkEdO1L0Q6ewFurx3lsEWTCdh0JpQJTmvw5bY,952 +django/contrib/sessions/locale/da/LC_MESSAGES/django.mo,sha256=7_YecCzfeYQp9zVYt2B7MtjhAAuVb0BcK2D5Qv_uAbg,681 +django/contrib/sessions/locale/da/LC_MESSAGES/django.po,sha256=qX_Oo7niVo57bazlIYFA6bnVmPBclUUTWvZFYNLaG04,880 +django/contrib/sessions/locale/de/LC_MESSAGES/django.mo,sha256=N3kTal0YK9z7Te3zYGLbJmoSB6oWaviWDLGdPlsPa9g,721 +django/contrib/sessions/locale/de/LC_MESSAGES/django.po,sha256=0qnfDeCUQN2buKn6R0MvwhQP05XWxSu-xgvfxvnJe3k,844 +django/contrib/sessions/locale/dsb/LC_MESSAGES/django.mo,sha256=RABl3WZmY6gLh4IqmTUhoBEXygDzjp_5lLF1MU9U5fA,810 +django/contrib/sessions/locale/dsb/LC_MESSAGES/django.po,sha256=cItKs5tASYHzDxfTg0A_dgBQounpzoGyOEFn18E_W_g,934 +django/contrib/sessions/locale/el/LC_MESSAGES/django.mo,sha256=QbTbmcfgc8_4r5hFrIghDhk2XQ4f8_emKmqupMG2ah0,809 +django/contrib/sessions/locale/el/LC_MESSAGES/django.po,sha256=HeaEbpVmFhhrZt2NsZteYaYoeo8FYKZF0IoNJwtzZkc,971 +django/contrib/sessions/locale/en/LC_MESSAGES/django.mo,sha256=U0OV81NfbuNL9ctF-gbGUG5al1StqN-daB-F-gFBFC8,356 +django/contrib/sessions/locale/en/LC_MESSAGES/django.po,sha256=afaM-IIUZtcRZduojUTS8tT0w7C4Ya9lXgReOvq_iF0,804 +django/contrib/sessions/locale/en_AU/LC_MESSAGES/django.mo,sha256=FgY1K6IVyQjMjXqVZxcsyWW_Tu5ckfrbmIfNYq5P-_E,693 +django/contrib/sessions/locale/en_AU/LC_MESSAGES/django.po,sha256=cMV15gJq8jNSUzkhn7uyOf2JYMFx7BNH1oFYa1vISnc,853 +django/contrib/sessions/locale/en_GB/LC_MESSAGES/django.mo,sha256=T5NQCTYkpERfP9yKbUvixT0VdBt1zGmGB8ITlkVc420,707 +django/contrib/sessions/locale/en_GB/LC_MESSAGES/django.po,sha256=1ks_VE1qpEfPcyKg0HybkTG0-DTttTHTfUPhQCR53sw,849 +django/contrib/sessions/locale/eo/LC_MESSAGES/django.mo,sha256=eBvYQbZS_WxVV3QCSZAOyHNIljC2ZXxVc4mktUuXVjI,727 +django/contrib/sessions/locale/eo/LC_MESSAGES/django.po,sha256=Ru9xicyTgHWVHh26hO2nQNFRQmwBnYKEagsS8TZRv3E,917 +django/contrib/sessions/locale/es/LC_MESSAGES/django.mo,sha256=jbHSvHjO2OCLlBD66LefocKOEbefWbPhj-l3NugiWuc,734 +django/contrib/sessions/locale/es/LC_MESSAGES/django.po,sha256=fY5WXeONEXHeuBlH0LkvzdZ2CSgbvLZ8BJc429aIbhI,909 +django/contrib/sessions/locale/es_AR/LC_MESSAGES/django.mo,sha256=_8icF2dMUWj4WW967rc5npgndXBAdJrIiz_VKf5D-Rw,694 +django/contrib/sessions/locale/es_AR/LC_MESSAGES/django.po,sha256=AnmvjeOA7EBTJ6wMOkCl8JRLVYRU8KS0egPijcKutns,879 +django/contrib/sessions/locale/es_CO/LC_MESSAGES/django.mo,sha256=UP7ia0gV9W-l0Qq5AS4ZPadJtml8iuzzlS5C9guMgh8,754 +django/contrib/sessions/locale/es_CO/LC_MESSAGES/django.po,sha256=_XeiiRWvDaGjofamsRHr5up_EQvcw0w-GLLeWK27Af8,878 +django/contrib/sessions/locale/es_MX/LC_MESSAGES/django.mo,sha256=MDM0K3xMvyf8ymvAurHYuacpxfG_YfJFyNnp1uuc6yY,756 +django/contrib/sessions/locale/es_MX/LC_MESSAGES/django.po,sha256=Y7VNa16F_yyK7_XJvF36rR2XNW8aBJK4UDweufyXpxE,892 +django/contrib/sessions/locale/es_VE/LC_MESSAGES/django.mo,sha256=59fZBDut-htCj38ZUoqPjhXJPjZBz-xpU9__QFr3kLs,486 +django/contrib/sessions/locale/es_VE/LC_MESSAGES/django.po,sha256=zWjgB0AmsmhX2tjk1PgldttqY56Czz8epOVCaYWXTLU,761 +django/contrib/sessions/locale/et/LC_MESSAGES/django.mo,sha256=aL1jZWourEC7jtjsuBZHD-Gw9lpL6L1SoqjTtzguxD0,737 +django/contrib/sessions/locale/et/LC_MESSAGES/django.po,sha256=VNBYohAOs59jYWkjVMY-v2zwVy5AKrtBbFRJZLwdCFg,899 +django/contrib/sessions/locale/eu/LC_MESSAGES/django.mo,sha256=M9piOB_t-ZnfN6pX-jeY0yWh2S_5cCuo1oGiy7X65A4,728 +django/contrib/sessions/locale/eu/LC_MESSAGES/django.po,sha256=bHdSoknoH0_dy26e93tWVdO4TT7rnCPXlSLPsYAhwyw,893 +django/contrib/sessions/locale/fa/LC_MESSAGES/django.mo,sha256=6DdJcqaYuBnhpFFHR42w-RqML0eQPFMAUEEDY0Redy8,755 +django/contrib/sessions/locale/fa/LC_MESSAGES/django.po,sha256=rklhNf0UFl2bM6mt7x9lWvfzPH4XWGbrW9Gc2w-9rzg,922 +django/contrib/sessions/locale/fi/LC_MESSAGES/django.mo,sha256=oAugvlTEvJmG8KsZw09WcfnifYY5oHnGo4lxcxqKeaY,721 +django/contrib/sessions/locale/fi/LC_MESSAGES/django.po,sha256=BVVrjbZZtLGAuZ9HK63p769CbjZFZMlS4BewSMfNMKU,889 +django/contrib/sessions/locale/fr/LC_MESSAGES/django.mo,sha256=aDGYdzx2eInF6IZ-UzPDEJkuYVPnvwVND3qVuSfJNWw,692 +django/contrib/sessions/locale/fr/LC_MESSAGES/django.po,sha256=hARxGdtBOzEZ_iVyzkNvcKlgyM8fOkdXTH3upj2XFYM,893 +django/contrib/sessions/locale/fy/LC_MESSAGES/django.mo,sha256=YQQy7wpjBORD9Isd-p0lLzYrUgAqv770_56-vXa0EOc,476 +django/contrib/sessions/locale/fy/LC_MESSAGES/django.po,sha256=U-VEY4WbmIkmrnPK4Mv-B-pbdtDzusBCVmE8iHyvzFU,751 +django/contrib/sessions/locale/ga/LC_MESSAGES/django.mo,sha256=zTrydRCRDiUQwF4tQ3cN1-5w36i6KptagsdA5_SaGy0,747 +django/contrib/sessions/locale/ga/LC_MESSAGES/django.po,sha256=Qpk1JaUWiHSEPdgBk-O_KfvGzwlZ4IAA6c6-nsJe400,958 +django/contrib/sessions/locale/gd/LC_MESSAGES/django.mo,sha256=Yi8blY_fUD5YTlnUD6YXZvv1qjm4QDriO6CJIUe1wIk,791 +django/contrib/sessions/locale/gd/LC_MESSAGES/django.po,sha256=fEa40AUqA5vh743Zqv0FO2WxSFXGYk4IzUR4BoaP-C4,890 +django/contrib/sessions/locale/gl/LC_MESSAGES/django.mo,sha256=lC8uu-mKxt48DLzRvaxz-mOqR0ZfvEuaBI1Hi_nuMpo,692 +django/contrib/sessions/locale/gl/LC_MESSAGES/django.po,sha256=L34leIfwmRJoqX0jfefbNHz0CmON5cSaRXeh7pmFqCY,943 +django/contrib/sessions/locale/he/LC_MESSAGES/django.mo,sha256=qhgjSWfGAOgl-i7iwzSrJttx88xcj1pB0iLkEK64mJU,809 +django/contrib/sessions/locale/he/LC_MESSAGES/django.po,sha256=KvQG6wOpokM-2JkhWnB2UUQacy5Ie1402K_pH2zUOu0,1066 +django/contrib/sessions/locale/hi/LC_MESSAGES/django.mo,sha256=naqxOjfAnNKy3qqnUG-4LGf9arLRJpjyWWmSj5tEfao,759 +django/contrib/sessions/locale/hi/LC_MESSAGES/django.po,sha256=WnTGvOz9YINMcUJg2BYCaHceZLKaTfsba_0AZtRNP38,951 +django/contrib/sessions/locale/hr/LC_MESSAGES/django.mo,sha256=axyJAmXmadpFxIhu8rroVD8NsGGadQemh9-_ZDo7L1U,819 +django/contrib/sessions/locale/hr/LC_MESSAGES/django.po,sha256=3G-qOYXBO-eMWWsa5LwTCW9M1oF0hlWgEz7hAK8hJqI,998 +django/contrib/sessions/locale/hsb/LC_MESSAGES/django.mo,sha256=_OXpOlCt4KU0i65Iw4LMjSsyn__E9wH20l9vDNBSEzw,805 +django/contrib/sessions/locale/hsb/LC_MESSAGES/django.po,sha256=yv3vX_UCDrdl07GQ79Mnytwgz2oTvySYOG9enzMpFJA,929 +django/contrib/sessions/locale/hu/LC_MESSAGES/django.mo,sha256=ik40LnsWkKYEUioJB9e11EX9XZ-qWMa-S7haxGhM-iI,727 +django/contrib/sessions/locale/hu/LC_MESSAGES/django.po,sha256=1-UWEEsFxRwmshP2x4pJbitWIGZ1YMeDDxnAX-XGNxc,884 +django/contrib/sessions/locale/hy/LC_MESSAGES/django.mo,sha256=x6VQWGdidRJFUJme-6jf1pcitktcQHQ7fhmw2UBej1Q,815 +django/contrib/sessions/locale/hy/LC_MESSAGES/django.po,sha256=eRMa3_A2Vx195mx2lvza1v-wcEcEeMrU63f0bgPPFjc,893 +django/contrib/sessions/locale/ia/LC_MESSAGES/django.mo,sha256=-o4aQPNJeqSDRSLqcKuYvJuKNBbFqDJDe3IzHgSgZeQ,744 +django/contrib/sessions/locale/ia/LC_MESSAGES/django.po,sha256=PULLDd3QOIU03kgradgQzT6IicoPhLPlUvFgRl-tGbA,869 +django/contrib/sessions/locale/id/LC_MESSAGES/django.mo,sha256=mOaIF0NGOO0-dt-nhHL-i3cfvt9-JKTbyUkFWPqDS9Y,705 +django/contrib/sessions/locale/id/LC_MESSAGES/django.po,sha256=EA6AJno3CaFOO-dEU9VQ_GEI-RAXS0v0uFqn1RJGjEs,914 +django/contrib/sessions/locale/io/LC_MESSAGES/django.mo,sha256=_rqAY6reegqmxmWc-pW8_kDaG9zflZuD-PGOVFsjRHo,683 +django/contrib/sessions/locale/io/LC_MESSAGES/django.po,sha256=tbKMxGuB6mh_m0ex9rO9KkTy6qyuRW2ERrQsGwmPiaw,840 +django/contrib/sessions/locale/is/LC_MESSAGES/django.mo,sha256=3QeMl-MCnBie9Sc_aQ1I7BrBhkbuArpoSJP95UEs4lg,706 +django/contrib/sessions/locale/is/LC_MESSAGES/django.po,sha256=LADIFJv8L5vgDJxiQUmKPSN64zzzrIKImh8wpLBEVWQ,853 +django/contrib/sessions/locale/it/LC_MESSAGES/django.mo,sha256=qTY3O-0FbbpZ5-BR5xOJWP0rlnIkBZf-oSawW_YJWlk,726 +django/contrib/sessions/locale/it/LC_MESSAGES/django.po,sha256=hEv0iTGLuUvEBk-lF-w7a9P3ifC0-eiodNtuSc7cXhg,869 +django/contrib/sessions/locale/ja/LC_MESSAGES/django.mo,sha256=hbv9FzWzXRIGRh_Kf_FLQB34xfmPU_9RQKn9u1kJqGU,757 +django/contrib/sessions/locale/ja/LC_MESSAGES/django.po,sha256=ppGx5ekOWGgDF3vzyrWsqnFUZ-sVZZhiOhvAzl_8v54,920 +django/contrib/sessions/locale/ka/LC_MESSAGES/django.mo,sha256=VZ-ysrDbea_-tMV-1xtlTeW62IAy2RWR94V3Y1iSh4U,803 +django/contrib/sessions/locale/ka/LC_MESSAGES/django.po,sha256=hqiWUiATlrc7qISF7ndlelIrFwc61kzhKje9l-DY6V4,955 +django/contrib/sessions/locale/kab/LC_MESSAGES/django.mo,sha256=W_yE0NDPJrVznA2Qb89VuprJNwyxSg59ovvjkQe6mAs,743 +django/contrib/sessions/locale/kab/LC_MESSAGES/django.po,sha256=FJeEuv4P3NT_PpWHEUsQVSWXu65nYkJ6Z2AlbSKb0ZA,821 +django/contrib/sessions/locale/kk/LC_MESSAGES/django.mo,sha256=FROGz_MuIhsIU5_-EYV38cHnRZrc3-OxxkBeK0ax9Rk,810 +django/contrib/sessions/locale/kk/LC_MESSAGES/django.po,sha256=P-oHO3Oi3V_RjWHjEAHdTrDfTwKP2xh3yJh7BlXL1VQ,1029 +django/contrib/sessions/locale/km/LC_MESSAGES/django.mo,sha256=VOuKsIG2DEeCA5JdheuMIeJlpmAhKrI6lD4KWYqIIPk,929 +django/contrib/sessions/locale/km/LC_MESSAGES/django.po,sha256=09i6Nd_rUK7UqFpJ70LMXTR6xS0NuGETRLe0CopMVBk,1073 +django/contrib/sessions/locale/kn/LC_MESSAGES/django.mo,sha256=TMZ71RqNR6zI20BeozyLa9cjYrWlvfIajGDfpnHd3pQ,810 +django/contrib/sessions/locale/kn/LC_MESSAGES/django.po,sha256=whdM8P74jkAAHvjgJN8Q77dYd9sIsf_135ID8KBu-a8,990 +django/contrib/sessions/locale/ko/LC_MESSAGES/django.mo,sha256=EUyVQYGtiFJg01mP30a0iOqBYHvpzHAcGTZM28Ubs5Q,700 +django/contrib/sessions/locale/ko/LC_MESSAGES/django.po,sha256=PjntvSzRz_Aekj9VFhGsP5yO6rAsxTMzwFj58JqToIU,855 +django/contrib/sessions/locale/ky/LC_MESSAGES/django.mo,sha256=ME7YUgKOYQz9FF_IdrqHImieEONDrkcn4T3HxTZKSV0,742 +django/contrib/sessions/locale/ky/LC_MESSAGES/django.po,sha256=JZHTs9wYmlWzilRMyp-jZWFSzGxWtPiQefPmLL9yhtM,915 +django/contrib/sessions/locale/lb/LC_MESSAGES/django.mo,sha256=xokesKl7h7k9dXFKIJwGETgwx1Ytq6mk2erBSxkgY-o,474 +django/contrib/sessions/locale/lb/LC_MESSAGES/django.po,sha256=3igeAnQjDg6D7ItBkQQhyBoFJOZlBxT7NoZiExwD-Fo,749 +django/contrib/sessions/locale/lt/LC_MESSAGES/django.mo,sha256=L9w8-qxlDlCqR_2P0PZegfhok_I61n0mJ1koJxzufy4,786 +django/contrib/sessions/locale/lt/LC_MESSAGES/django.po,sha256=dEefLGtg5flFr_v4vHS5HhK1kxx9WYWTw98cvEn132M,1023 +django/contrib/sessions/locale/lv/LC_MESSAGES/django.mo,sha256=exEzDUNwNS0GLsUkKPu_SfqBxU7T6VRA_T2schIQZ88,753 +django/contrib/sessions/locale/lv/LC_MESSAGES/django.po,sha256=fBgQEbsGg1ECVm1PFDrS2sfKs2eqmsqrSYzx9ELotNQ,909 +django/contrib/sessions/locale/mk/LC_MESSAGES/django.mo,sha256=4oTWp8-qzUQBiqG32hNieABgT3O17q2C4iEhcFtAxLA,816 +django/contrib/sessions/locale/mk/LC_MESSAGES/django.po,sha256=afApb5YRhPXUWR8yF_TTym73u0ov7lWiwRda1-uNiLY,988 +django/contrib/sessions/locale/ml/LC_MESSAGES/django.mo,sha256=tff5TsHILSV1kAAB3bzHQZDB9fgMglZJTofzCunGBzc,854 +django/contrib/sessions/locale/ml/LC_MESSAGES/django.po,sha256=eRkeupt42kUey_9vJmlH8USshnXPZ8M7aYHq88u-5iY,1016 +django/contrib/sessions/locale/mn/LC_MESSAGES/django.mo,sha256=CcCH2ggVYrD29Q11ZMthcscBno2ePkQDbZfoYquTRPM,784 +django/contrib/sessions/locale/mn/LC_MESSAGES/django.po,sha256=nvcjbJzXiDvWFXrM5CxgOQIq8XucsZEUVdYkY8LnCRE,992 +django/contrib/sessions/locale/mr/LC_MESSAGES/django.mo,sha256=2Z5jaGJzpiJTCnhCk8ulCDeAdj-WwR99scdHFPRoHoA,468 +django/contrib/sessions/locale/mr/LC_MESSAGES/django.po,sha256=FQRdZ-qIDuvTCrwbnWfxoxNi8rywLSebcNbxGvr-hb0,743 +django/contrib/sessions/locale/ms/LC_MESSAGES/django.mo,sha256=rFi4D_ZURYUPjs5AqJ66bW70yL7AekAKWnrZRBvGPiE,649 +django/contrib/sessions/locale/ms/LC_MESSAGES/django.po,sha256=nZuJ_D0JZUzmGensLa7tSgzbBo05qgQcuHmte2oU6WQ,786 +django/contrib/sessions/locale/my/LC_MESSAGES/django.mo,sha256=8zzzyfJYok969YuAwDUaa6YhxaSi3wcXy3HRNXDb_70,872 +django/contrib/sessions/locale/my/LC_MESSAGES/django.po,sha256=mfs0zRBI0tugyyEfXBZzZ_FMIohydq6EYPZGra678pw,997 +django/contrib/sessions/locale/nb/LC_MESSAGES/django.mo,sha256=hfJ1NCFgcAAtUvNEpaZ9b31PyidHxDGicifUWANIbM8,717 +django/contrib/sessions/locale/nb/LC_MESSAGES/django.po,sha256=yXr6oYuiu01oELdQKuztQFWz8x5C2zS5OzEfU9MHJsU,908 +django/contrib/sessions/locale/ne/LC_MESSAGES/django.mo,sha256=slFgMrqGVtLRHdGorLGPpB09SM92_WnbnRR0rlpNlPQ,802 +django/contrib/sessions/locale/ne/LC_MESSAGES/django.po,sha256=1vyoiGnnaB8f9SFz8PGfzpw6V_NoL78DQwjjnB6fS98,978 +django/contrib/sessions/locale/nl/LC_MESSAGES/django.mo,sha256=84BTlTyxa409moKbQMFyJisI65w22p09qjJHBAmQe-g,692 +django/contrib/sessions/locale/nl/LC_MESSAGES/django.po,sha256=smRr-QPGm6h6hdXxghggWES8b2NnL7yDQ07coUypa8g,909 +django/contrib/sessions/locale/nn/LC_MESSAGES/django.mo,sha256=cytH72J3yS1PURcgyrD8R2PV5d3SbPE73IAqOMBPPVg,667 +django/contrib/sessions/locale/nn/LC_MESSAGES/django.po,sha256=y9l60yy_W3qjxWzxgJg5VgEH9KAIHIQb5hv7mgnep9w,851 +django/contrib/sessions/locale/os/LC_MESSAGES/django.mo,sha256=xVux1Ag45Jo9HQBbkrRzcWrNjqP09nMQl16jIh0YVlo,732 +django/contrib/sessions/locale/os/LC_MESSAGES/django.po,sha256=1hG5Vsz2a2yW05_Z9cTNrBKtK9VRPZuQdx4KJ_0n98o,892 +django/contrib/sessions/locale/pa/LC_MESSAGES/django.mo,sha256=qEx4r_ONwXK1-qYD5uxxXEQPqK5I6rf38QZoUSm7UVA,771 +django/contrib/sessions/locale/pa/LC_MESSAGES/django.po,sha256=M7fmVGP8DtZGEuTV3iJhuWWqILVUTDZvUey_mrP4_fM,918 +django/contrib/sessions/locale/pl/LC_MESSAGES/django.mo,sha256=F9CQb7gQ1ltP6B82JNKu8IAsTdHK5TNke0rtDIgNz3c,828 +django/contrib/sessions/locale/pl/LC_MESSAGES/django.po,sha256=C_MJBB-vwTZbx-t4-mzun-RxHhdOVv04b6xrWdnTv8E,1084 +django/contrib/sessions/locale/pt/LC_MESSAGES/django.mo,sha256=dlJF7hF4GjLmQPdAJhtf-FCKX26XsOmZlChOcxxIqPk,738 +django/contrib/sessions/locale/pt/LC_MESSAGES/django.po,sha256=cOycrw3HCHjSYBadpalyrg5LdRTlqZCTyMh93GOQ8O0,896 +django/contrib/sessions/locale/pt_BR/LC_MESSAGES/django.mo,sha256=XHNF5D8oXIia3e3LYwxd46a2JOgDc_ykvc8yuo21fT0,757 +django/contrib/sessions/locale/pt_BR/LC_MESSAGES/django.po,sha256=K_zxKaUKngWPFpvHgXOcymJEsiONSw-OrVrroRXmUUk,924 +django/contrib/sessions/locale/ro/LC_MESSAGES/django.mo,sha256=WR9I9Gum_pq7Qg2Gzhf-zAv43OwR_uDtsbhtx4Ta5gE,776 +django/contrib/sessions/locale/ro/LC_MESSAGES/django.po,sha256=fEgVxL_0Llnjspu9EsXBf8AVL0DGdfF7NgV88G7WN1E,987 +django/contrib/sessions/locale/ru/LC_MESSAGES/django.mo,sha256=n-8vXR5spEbdfyeWOYWC_6kBbAppNoRrWYgqKFY6gJA,913 +django/contrib/sessions/locale/ru/LC_MESSAGES/django.po,sha256=sNqNGdoof6eXzFlh4YIp1O54MdDOAFDjD3GvAFsNP8k,1101 +django/contrib/sessions/locale/sk/LC_MESSAGES/django.mo,sha256=Yntm624Wt410RwuNPU1c-WwQoyrRrBs69VlKMlNUHeQ,766 +django/contrib/sessions/locale/sk/LC_MESSAGES/django.po,sha256=wt7BJk6RpFogJ2Wwa9Mh0mJi9YMpNYKTUSDuDuv1Ong,975 +django/contrib/sessions/locale/sl/LC_MESSAGES/django.mo,sha256=EE6mB8BiYRyAxK6qzurRWcaYVs96FO_4rERYQdtIt3k,770 +django/contrib/sessions/locale/sl/LC_MESSAGES/django.po,sha256=KTjBWyvaNCHbpV9K6vbnavwxxXqf2DlIqVPv7MVFcO8,928 +django/contrib/sessions/locale/sq/LC_MESSAGES/django.mo,sha256=eRaTy3WOC76EYLtMSD4xtJj2h8eE4W-TS4VvCVxI5bw,683 +django/contrib/sessions/locale/sq/LC_MESSAGES/django.po,sha256=9pzp7834LQKafe5fJzC4OKsAd6XfgtEQl6K6hVLaBQM,844 +django/contrib/sessions/locale/sr/LC_MESSAGES/django.mo,sha256=ZDBOYmWIoSyDeT0nYIIFeMtW5jwpr257CbdTZlkVeRQ,855 +django/contrib/sessions/locale/sr/LC_MESSAGES/django.po,sha256=OXQOYeac0ghuzLrwaErJGr1FczuORTu2yroFX5hvRnk,1027 +django/contrib/sessions/locale/sr_Latn/LC_MESSAGES/django.mo,sha256=f3x9f9hTOsJltghjzJMdd8ueDwzxJex6zTXsU-_Hf_Y,757 +django/contrib/sessions/locale/sr_Latn/LC_MESSAGES/django.po,sha256=HKjo7hjSAvgrIvlI0SkgF3zxz8TtKWyBT51UGNhDwek,946 +django/contrib/sessions/locale/sv/LC_MESSAGES/django.mo,sha256=SGbr0K_5iAMA22MfseAldMDgLSEBrI56pCtyV8tMAPc,707 +django/contrib/sessions/locale/sv/LC_MESSAGES/django.po,sha256=vraY3915wBYGeYu9Ro0-TlBeLWqGZP1fbckLv8y47Ys,853 +django/contrib/sessions/locale/sw/LC_MESSAGES/django.mo,sha256=Edhqp8yuBnrGtJqPO7jxobeXN4uU5wKSLrOsFO1F23k,743 +django/contrib/sessions/locale/sw/LC_MESSAGES/django.po,sha256=iY4rN4T-AA2FBQA7DiWWFvrclqKiDYQefqwwVw61-f8,858 +django/contrib/sessions/locale/ta/LC_MESSAGES/django.mo,sha256=qLIThhFQbJKc1_UVr7wVIm1rJfK2rO5m84BCB_oKq7s,801 +django/contrib/sessions/locale/ta/LC_MESSAGES/django.po,sha256=bYqtYf9XgP9IKKFJXh0u64JhRhDvPPUliI1J-NeRpKE,945 +django/contrib/sessions/locale/te/LC_MESSAGES/django.mo,sha256=kteZeivEckt4AmAeKgmgouMQo1qqSQrI8M42B16gMnQ,786 +django/contrib/sessions/locale/te/LC_MESSAGES/django.po,sha256=dQgiNS52RHrL6bV9CEO7Jk9lk3YUQrUBDCg_bP2OSZc,980 +django/contrib/sessions/locale/tg/LC_MESSAGES/django.mo,sha256=N6AiKfV47QTlO5Z_r4SQZXVLtouu-NVSwWkePgD17Tc,747 +django/contrib/sessions/locale/tg/LC_MESSAGES/django.po,sha256=wvvDNu060yqlTxy3swM0x3v6QpvCB9DkfNm0Q-kb9Xk,910 +django/contrib/sessions/locale/th/LC_MESSAGES/django.mo,sha256=D41vbkoYMdYPj3587p-c5yytLVi9pE5xvRZEYhZrxPs,814 +django/contrib/sessions/locale/th/LC_MESSAGES/django.po,sha256=43704TUv4ysKhL8T5MowZwlyv1JZrPyVGrpdIyb3r40,988 +django/contrib/sessions/locale/tk/LC_MESSAGES/django.mo,sha256=pT_hpKCwFT60GUXzD_4z8JOhmh1HRnkZj-QSouVEgUA,699 +django/contrib/sessions/locale/tk/LC_MESSAGES/django.po,sha256=trqXxfyIbh4V4szol0pXETmEWRxAAKywPZ9EzVMVE-I,865 +django/contrib/sessions/locale/tr/LC_MESSAGES/django.mo,sha256=STDnYOeO1d9nSCVf7pSkMq8R7z1aeqq-xAuIYjsofuE,685 +django/contrib/sessions/locale/tr/LC_MESSAGES/django.po,sha256=XYKo0_P5xitYehvjMzEw2MTp_Nza-cIXEECV3dA6BmY,863 +django/contrib/sessions/locale/tt/LC_MESSAGES/django.mo,sha256=Q-FGu_ljTsxXO_EWu7zCzGwoqFXkeoTzWSlvx85VLGc,806 +django/contrib/sessions/locale/tt/LC_MESSAGES/django.po,sha256=UC85dFs_1836noZTuZEzPqAjQMFfSvj7oGmEWOGcfCA,962 +django/contrib/sessions/locale/udm/LC_MESSAGES/django.mo,sha256=CNmoKj9Uc0qEInnV5t0Nt4ZnKSZCRdIG5fyfSsqwky4,462 +django/contrib/sessions/locale/udm/LC_MESSAGES/django.po,sha256=CPml2Fn9Ax_qO5brCFDLPBoTiNdvsvJb1btQ0COwUfY,737 +django/contrib/sessions/locale/ug/LC_MESSAGES/django.mo,sha256=HMwjTByc3HrhFvCt_iOioYZE7JEKLzNlb2DTu6TCgto,748 +django/contrib/sessions/locale/ug/LC_MESSAGES/django.po,sha256=QEdIUuvVMFbOPSCYs6k-61rBwmTUXFCcR1pKn53dXtQ,864 +django/contrib/sessions/locale/uk/LC_MESSAGES/django.mo,sha256=jzNrLuFghQMCHNRQ0ihnKMCicgear0yWiTOLnvdPszw,841 +django/contrib/sessions/locale/uk/LC_MESSAGES/django.po,sha256=4K2geuGjRpJCtNfGPMhYWZlGxUy5xzIoDKA2jL2iGos,1171 +django/contrib/sessions/locale/ur/LC_MESSAGES/django.mo,sha256=FkGIiHegr8HR8zjVyJ9TTW1T9WYtAL5Mg77nRKnKqWk,729 +django/contrib/sessions/locale/ur/LC_MESSAGES/django.po,sha256=qR4QEBTP6CH09XFCzsPSPg2Dv0LqzbRV_I67HO2OUwk,879 +django/contrib/sessions/locale/uz/LC_MESSAGES/django.mo,sha256=asPu0RhMB_Ui1li-OTVL4qIXnM9XpjsYyx5yJldDYBY,744 +django/contrib/sessions/locale/uz/LC_MESSAGES/django.po,sha256=KsHuLgGJt-KDH0h6ND7JLP2dDJAdLVHSlau4DkkfqA8,880 +django/contrib/sessions/locale/vi/LC_MESSAGES/django.mo,sha256=KriTpT-Hgr10DMnY5Bmbd4isxmSFLmav8vg2tuL2Bb8,679 +django/contrib/sessions/locale/vi/LC_MESSAGES/django.po,sha256=M7S46Q0Q961ykz_5FCAN8SXQ54w8tp4rZeZpy6bPtXs,909 +django/contrib/sessions/locale/zh_Hans/LC_MESSAGES/django.mo,sha256=zsbhIMocgB8Yn1XEBxbIIbBh8tLifvvYNlhe5U61ch8,722 +django/contrib/sessions/locale/zh_Hans/LC_MESSAGES/django.po,sha256=tPshgXjEv6pME4N082ztamJhd5whHB2_IV_egdP-LlQ,889 +django/contrib/sessions/locale/zh_Hant/LC_MESSAGES/django.mo,sha256=WZzfpFKZ41Pu8Q9SuhGu3hXwp4eiq8Dt8vdiQfxvF9M,733 +django/contrib/sessions/locale/zh_Hant/LC_MESSAGES/django.po,sha256=6IRDQu6-PAYh6SyEIcKdhuR172lX0buY8qqsU0QXlYU,898 +django/contrib/sessions/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/sessions/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/sessions/management/commands/clearsessions.py,sha256=pAiO5o7zgButVlYAV93bPnmiwzWP7V5N7-xPtxSkjJg,661 +django/contrib/sessions/middleware.py,sha256=ziZex9xiqxBYl9SC91i4QIDYuoenz4OoKaNO7sXu8kQ,3483 +django/contrib/sessions/migrations/0001_initial.py,sha256=KqQ44jk-5RNcTdqUv95l_UnoMA8cP5O-0lrjoJ8vabk,1148 +django/contrib/sessions/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/sessions/models.py,sha256=BguwuQSDzpeTNXhteYRAcspg1rop431tjFeZUVWZNYc,1250 +django/contrib/sessions/serializers.py,sha256=S9oDsUAjFv2MTlLQA6AoehggKyHXpu6-Qnrqybhgvkg,106 +django/contrib/sitemaps/__init__.py,sha256=hZuWQsKCQHfgPOx1GQPETMzTT9oqzcpp2wDMfGiLhp8,6923 +django/contrib/sitemaps/apps.py,sha256=xYE-mAs37nL8ZAnv052LhUKVUwGYKB3xyPy4t8pwOpw,249 +django/contrib/sitemaps/templates/sitemap.xml,sha256=L092SHTtwtmNJ_Lj_jLrzHhfI0-OKKIw5fpyOfr4qRs,683 +django/contrib/sitemaps/templates/sitemap_index.xml,sha256=SQf9avfFmnT8j-nLEc8lVQQcdhiy_qhnqjssIMti3oU,360 +django/contrib/sitemaps/views.py,sha256=WoBVQN0jHzjrhuB-_tMdbC8S1Hb9TAnVyL1Kk3CcGM4,4657 +django/contrib/sites/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/sites/admin.py,sha256=IWvGDQUTDPEUsd-uuxfHxJq4syGtddNKUdkP0nmVUMA,214 +django/contrib/sites/apps.py,sha256=uBLHUyQoSuo1Q7NwLTwlvsTuRU1MXwj4t6lRUnIBdwk,562 +django/contrib/sites/checks.py,sha256=AydGM1G1L9mvmTbNMTXRbZzPbHpIiknkRzLh5uFQLLI,366 +django/contrib/sites/locale/af/LC_MESSAGES/django.mo,sha256=A10bZFMs-wUetVfF5UrFwmuiKnN4ZnlrR4Rx8U4Ut1A,786 +django/contrib/sites/locale/af/LC_MESSAGES/django.po,sha256=O0-ZRvmXvV_34kONuqakuXV5OmYbQ569K1Puj3qQNac,907 +django/contrib/sites/locale/ar/LC_MESSAGES/django.mo,sha256=kLoytp2jvhWn6p1c8kNVua2sYAMnrpS4xnbluHD22Vs,947 +django/contrib/sites/locale/ar/LC_MESSAGES/django.po,sha256=HYA3pA29GktzXBP-soUEn9VP2vkZuhVIXVA8TNPCHCs,1135 +django/contrib/sites/locale/ar_DZ/LC_MESSAGES/django.mo,sha256=-ltwY57Th6LNqU3bgOPPP7qWtII5c6rj8Dv8eY7PZ84,918 +django/contrib/sites/locale/ar_DZ/LC_MESSAGES/django.po,sha256=KRTjZ2dFRWVPmE_hC5Hq8eDv3GQs3yQKCgV5ISFmEKk,1079 +django/contrib/sites/locale/ast/LC_MESSAGES/django.mo,sha256=eEvaeiGnZFBPGzKLlRz4M9AHemgJVAb-yNpbpxRqtd0,774 +django/contrib/sites/locale/ast/LC_MESSAGES/django.po,sha256=huBohKzLpdaJRFMFXXSDhDCUOqVqyWXfxb8_lLOkUd0,915 +django/contrib/sites/locale/az/LC_MESSAGES/django.mo,sha256=CjAGI4qGoXN95q4LpCLXLKvaNB33Ocf5SfXdurFBkas,773 +django/contrib/sites/locale/az/LC_MESSAGES/django.po,sha256=E84kNPFhgHmIfYT0uzCnTPGwPkAqKzqwFvJB7pETbVo,933 +django/contrib/sites/locale/be/LC_MESSAGES/django.mo,sha256=HGh78mI50ZldBtQ8jId26SI-lSHv4ZLcveRN2J8VzH8,983 +django/contrib/sites/locale/be/LC_MESSAGES/django.po,sha256=W5FhVJKcmd3WHl2Lpd5NJUsc7_sE_1Pipk3CVPoGPa4,1152 +django/contrib/sites/locale/bg/LC_MESSAGES/django.mo,sha256=a2R52umIQIhnzFaFYSRhQ6nBlywE8RGMj2FUOFmyb0A,904 +django/contrib/sites/locale/bg/LC_MESSAGES/django.po,sha256=awB8RMS-qByhNB6eH2f0Oyxb3SH8waLhrZ--rokGfaI,1118 +django/contrib/sites/locale/bn/LC_MESSAGES/django.mo,sha256=cI3a9_L-OC7gtdyRNaGX7A5w0Za0M4ERnYB7rSNkuRU,925 +django/contrib/sites/locale/bn/LC_MESSAGES/django.po,sha256=8ZxYF16bgtTZSZRZFok6IJxUV02vIztoVx2qXqwO8NM,1090 +django/contrib/sites/locale/br/LC_MESSAGES/django.mo,sha256=rI_dIznbwnadZbxOPtQxZ1pGYePNwcNNXt05iiPkchU,1107 +django/contrib/sites/locale/br/LC_MESSAGES/django.po,sha256=7Ein5Xw73DNGGtdd595Bx6ixfSD-dBXZNBUU44pSLuQ,1281 +django/contrib/sites/locale/bs/LC_MESSAGES/django.mo,sha256=bDeqQNme586LnQRQdvOWaLGZssjOoECef3vMq_OCXno,692 +django/contrib/sites/locale/bs/LC_MESSAGES/django.po,sha256=xRTWInDNiLxikjwsjgW_pYjhy24zOro90-909ns9fig,923 +django/contrib/sites/locale/ca/LC_MESSAGES/django.mo,sha256=lEUuQEpgDY3bVWzRONrPzYlojRoNduT16_oYDkkbdfk,791 +django/contrib/sites/locale/ca/LC_MESSAGES/django.po,sha256=aORAoVn69iG1ynmEfnkBzBO-UZOzzbkPVOU-ZvfMtZg,996 +django/contrib/sites/locale/ckb/LC_MESSAGES/django.mo,sha256=Chp4sX73l_RFw4aaf9x67vEO1_cM8eh5c0URKBgMU-Q,843 +django/contrib/sites/locale/ckb/LC_MESSAGES/django.po,sha256=2NPav4574kEwTS_nZTUoVbYxJFzsaC5MdQUCD9iqC6E,1007 +django/contrib/sites/locale/cs/LC_MESSAGES/django.mo,sha256=mnXnpU7sLDTJ3OrIUTnGarPYsupNIUPV4ex_BPWU8fk,827 +django/contrib/sites/locale/cs/LC_MESSAGES/django.po,sha256=ONzFlwzmt7p5jdp6111qQkkevckRrd7GNS0lkDPKu-4,1035 +django/contrib/sites/locale/cy/LC_MESSAGES/django.mo,sha256=70pOie0K__hkmM9oBUaQfVwHjK8Cl48E26kRQL2mtew,835 +django/contrib/sites/locale/cy/LC_MESSAGES/django.po,sha256=FAZrVc72x-4R1A-1qYOBwADoXngC_F6FO8nRjr5-Z6g,1013 +django/contrib/sites/locale/da/LC_MESSAGES/django.mo,sha256=FTOyV1DIH9sMldyjgPw98d2HCotoO4zJ_KY_C9DCB7Y,753 +django/contrib/sites/locale/da/LC_MESSAGES/django.po,sha256=Po1Z6u52CFCyz9hLfK009pMbZzZgHrBse0ViX8wCYm8,957 +django/contrib/sites/locale/de/LC_MESSAGES/django.mo,sha256=5Q6X0_bDQ1ZRpkTy7UpPNzrhmQsB9Q0P1agB7koRyzs,792 +django/contrib/sites/locale/de/LC_MESSAGES/django.po,sha256=aD0wBinqtDUPvBbwtHrLEhFdoVRx1nOh17cJFuWhN3U,980 +django/contrib/sites/locale/dsb/LC_MESSAGES/django.mo,sha256=pPpWYsYp81MTrqCsGF0QnGktZNIll70bdBwSkuVE8go,868 +django/contrib/sites/locale/dsb/LC_MESSAGES/django.po,sha256=IA3G8AKJls20gzfxnrfPzivMNpL8A0zBQBg7OyzrP6g,992 +django/contrib/sites/locale/el/LC_MESSAGES/django.mo,sha256=G9o1zLGysUePGzZRicQ2aIIrc2UXMLTQmdpbrUMfWBU,878 +django/contrib/sites/locale/el/LC_MESSAGES/django.po,sha256=RBi_D-_znYuV6LXfTlSOf1Mvuyl96fIyEoiZ-lgeyWs,1133 +django/contrib/sites/locale/en/LC_MESSAGES/django.mo,sha256=U0OV81NfbuNL9ctF-gbGUG5al1StqN-daB-F-gFBFC8,356 +django/contrib/sites/locale/en/LC_MESSAGES/django.po,sha256=tSjfrNZ_FqLHsXjm5NuTyo5-JpdlPLsPZjFqF2APhy8,817 +django/contrib/sites/locale/en_AU/LC_MESSAGES/django.mo,sha256=G--2j_CR99JjRgVIX2Y_5pDfO7IgIkvK4kYHZtGzpxU,753 +django/contrib/sites/locale/en_AU/LC_MESSAGES/django.po,sha256=Giw634r94MJT1Q3qgqM7gZakQCasRM9Dm7MDkb9JOc8,913 +django/contrib/sites/locale/en_GB/LC_MESSAGES/django.mo,sha256=FbSh7msJdrHsXr0EtDMuODFzSANG_HJ3iBlW8ePpqFs,639 +django/contrib/sites/locale/en_GB/LC_MESSAGES/django.po,sha256=Ib-DIuTWlrN3kg99kLCuqWJVtt1NWaFD4UbDFK6d4KY,862 +django/contrib/sites/locale/eo/LC_MESSAGES/django.mo,sha256=N4KkH12OHxic3pp1okeBhpfDx8XxxpULk3UC219vjWU,792 +django/contrib/sites/locale/eo/LC_MESSAGES/django.po,sha256=ymXSJaFJWGBO903ObqR-ows-p4T3KyUplc_p_3r1uk8,1043 +django/contrib/sites/locale/es/LC_MESSAGES/django.mo,sha256=qLN1uoCdslxdYWgdjgSBi7szllP-mQZtHbuZnNOthsQ,804 +django/contrib/sites/locale/es/LC_MESSAGES/django.po,sha256=QClia2zY39269VSQzkQsLwwukthN6u2JBsjbLNxA1VQ,1066 +django/contrib/sites/locale/es_AR/LC_MESSAGES/django.mo,sha256=_O4rVk7IM2BBlZvjDP2SvTOo8WWqthQi5exQzt027-s,776 +django/contrib/sites/locale/es_AR/LC_MESSAGES/django.po,sha256=RwyNylXbyxdSXn6qRDXd99-GaEPlmr6TicHTUW0boaQ,969 +django/contrib/sites/locale/es_CO/LC_MESSAGES/django.mo,sha256=a4Xje2M26wyIx6Wlg6puHo_OXjiDEy7b0FquT9gbThA,825 +django/contrib/sites/locale/es_CO/LC_MESSAGES/django.po,sha256=9bnRhVD099JzkheO80l65dufjuawsj9aSFgFu5A-lnM,949 +django/contrib/sites/locale/es_MX/LC_MESSAGES/django.mo,sha256=AtGta5jBL9XNBvfSpsCcnDtDhvcb89ALl4hNjSPxibM,809 +django/contrib/sites/locale/es_MX/LC_MESSAGES/django.po,sha256=TnkpQp-7swH-x9cytUJe-QJRd2n_pYMVo0ltDw9Pu8o,991 +django/contrib/sites/locale/es_VE/LC_MESSAGES/django.mo,sha256=59fZBDut-htCj38ZUoqPjhXJPjZBz-xpU9__QFr3kLs,486 +django/contrib/sites/locale/es_VE/LC_MESSAGES/django.po,sha256=8PWXy2L1l67wDIi98Q45j7OpVITr0Lt4zwitAnB-d_o,791 +django/contrib/sites/locale/et/LC_MESSAGES/django.mo,sha256=I2E-49UQsG-F26OeAfnKlfUdA3YCkUSV8ffA-GMSkE0,788 +django/contrib/sites/locale/et/LC_MESSAGES/django.po,sha256=mEfD6EyQ15PPivb5FTlkabt3Lo_XGtomI9XzHrrh34Y,992 +django/contrib/sites/locale/eu/LC_MESSAGES/django.mo,sha256=1HTAFI3DvTAflLJsN7NVtSd4XOTlfoeLGFyYCOX69Ec,807 +django/contrib/sites/locale/eu/LC_MESSAGES/django.po,sha256=NWxdE5-mF6Ak4nPRpCFEgAMIsVDe9YBEZl81v9kEuX8,1023 +django/contrib/sites/locale/fa/LC_MESSAGES/django.mo,sha256=odtsOpZ6noNqwDb18HDc2e6nz3NMsa-wrTN-9dk7d9w,872 +django/contrib/sites/locale/fa/LC_MESSAGES/django.po,sha256=-DirRvcTqcpIy90QAUiCSoNkCDRifqpWSzLriJ4cwQU,1094 +django/contrib/sites/locale/fi/LC_MESSAGES/django.mo,sha256=I5DUeLk1ChUC32q5uzriABCLLJpJKNbEK4BfqylPQzg,786 +django/contrib/sites/locale/fi/LC_MESSAGES/django.po,sha256=LH2sFIKM3YHPoz9zIu10z1DFv1svXphBdOhXNy4a17s,929 +django/contrib/sites/locale/fr/LC_MESSAGES/django.mo,sha256=W7Ne5HqgnRcl42njzbUaDSY059jdhwvr0tgZzecVWD8,756 +django/contrib/sites/locale/fr/LC_MESSAGES/django.po,sha256=u24rHDJ47AoBgcmBwI1tIescAgbjFxov6y906H_uhK0,999 +django/contrib/sites/locale/fy/LC_MESSAGES/django.mo,sha256=YQQy7wpjBORD9Isd-p0lLzYrUgAqv770_56-vXa0EOc,476 +django/contrib/sites/locale/fy/LC_MESSAGES/django.po,sha256=Yh6Lw0QI2Me0zCtlyXraFLjERKqklB6-IJLDTjH_jTs,781 +django/contrib/sites/locale/ga/LC_MESSAGES/django.mo,sha256=g5popLirHXWn6ZWJHESQaG5MmKWZL_JNI_5Vgn5FTqU,683 +django/contrib/sites/locale/ga/LC_MESSAGES/django.po,sha256=34hj3ELt7GQ7CaHL246uBDmvsVUaaN5kTrzt8j7eETM,962 +django/contrib/sites/locale/gd/LC_MESSAGES/django.mo,sha256=df4XIGGD6FIyMUXsb-SoSqNfBFAsRXf4qYtolh_C964,858 +django/contrib/sites/locale/gd/LC_MESSAGES/django.po,sha256=NPKp7A5-y-MR7r8r4WqtcVQJEHCIOP5mLTd0cIfUsug,957 +django/contrib/sites/locale/gl/LC_MESSAGES/django.mo,sha256=tiRYDFC1_V2n1jkEQqhjjQBdZzFkhxzNfHIzG2l3PX4,728 +django/contrib/sites/locale/gl/LC_MESSAGES/django.po,sha256=DNY_rv6w6VrAu3hMUwx3cgLLyH4PFfgaJ9dSKfLBrpI,979 +django/contrib/sites/locale/he/LC_MESSAGES/django.mo,sha256=L3bganfG4gHqp2WXGh4rfWmmbaIxHaGc7-ypAqjSL_E,820 +django/contrib/sites/locale/he/LC_MESSAGES/django.po,sha256=iO3OZwz2aiuAzugkKp5Hxonwdg3kKjBurxR685J2ZMk,1082 +django/contrib/sites/locale/hi/LC_MESSAGES/django.mo,sha256=J4oIS1vJnCvdCCUD4tlTUVyTe4Xn0gKcWedfhH4C0t0,665 +django/contrib/sites/locale/hi/LC_MESSAGES/django.po,sha256=INBrm37jL3okBHuzX8MSN1vMptj77a-4kwQkAyt8w_8,890 +django/contrib/sites/locale/hr/LC_MESSAGES/django.mo,sha256=KjDUhEaOuYSMexcURu2UgfkatN2rrUcAbCUbcpVSInk,876 +django/contrib/sites/locale/hr/LC_MESSAGES/django.po,sha256=-nFMFkVuDoKYDFV_zdNULOqQlnqtiCG57aakN5hqlmg,1055 +django/contrib/sites/locale/hsb/LC_MESSAGES/django.mo,sha256=RyHVb7u9aRn5BXmWzR1gApbZlOioPDJ59ufR1Oo3e8Y,863 +django/contrib/sites/locale/hsb/LC_MESSAGES/django.po,sha256=Aq54y5Gb14bIt28oDDrFltnSOk31Z2YalwaJMDMXfWc,987 +django/contrib/sites/locale/hu/LC_MESSAGES/django.mo,sha256=P--LN84U2BeZAvRVR-OiWl4R02cTTBi2o8XR2yHIwIU,796 +django/contrib/sites/locale/hu/LC_MESSAGES/django.po,sha256=b0VhyFdNaZZR5MH1vFsLL69FmICN8Dz-sTRk0PdK49E,953 +django/contrib/sites/locale/hy/LC_MESSAGES/django.mo,sha256=Hs9XwRHRkHicLWt_NvWvr7nMocmY-Kc8XphhVSAMQRc,906 +django/contrib/sites/locale/hy/LC_MESSAGES/django.po,sha256=MU4hXXGfjXKfYcjxDYzFfsEUIelz5ZzyQLkeSrUQKa0,1049 +django/contrib/sites/locale/ia/LC_MESSAGES/django.mo,sha256=gRMs-W5EiY26gqzwnDXEMbeb1vs0bYZ2DC2a9VCciew,809 +django/contrib/sites/locale/ia/LC_MESSAGES/django.po,sha256=HXZzn9ACIqfR2YoyvpK2FjZ7QuEq_RVZ1kSC4nxMgeg,934 +django/contrib/sites/locale/id/LC_MESSAGES/django.mo,sha256=__2E_2TmVUcbf1ygxtS1lHvkhv8L0mdTAtJpBsdH24Y,791 +django/contrib/sites/locale/id/LC_MESSAGES/django.po,sha256=e5teAHiMjLR8RDlg8q99qtW-K81ltcIiBIdb1MZw2sE,1000 +django/contrib/sites/locale/io/LC_MESSAGES/django.mo,sha256=W-NP0b-zR1oWUZnHZ6fPu5AC2Q6o7nUNoxssgeguUBo,760 +django/contrib/sites/locale/io/LC_MESSAGES/django.po,sha256=G4GUUz3rxoBjWTs-j5RFCvv52AEHiwrCBwom5hYeBSE,914 +django/contrib/sites/locale/is/LC_MESSAGES/django.mo,sha256=lkJgTzDjh5PNfIJpOS2DxKmwVUs9Sl5XwFHv4YdCB30,812 +django/contrib/sites/locale/is/LC_MESSAGES/django.po,sha256=1DVgAcHSZVyDd5xn483oqICIG4ooyZY8ko7A3aDogKM,976 +django/contrib/sites/locale/it/LC_MESSAGES/django.mo,sha256=6NQjjtDMudnAgnDCkemOXinzX0J-eAE5gSq1F8kjusY,795 +django/contrib/sites/locale/it/LC_MESSAGES/django.po,sha256=zxavlLMmp1t1rCDsgrw12kVgxiK5EyR_mOalSu8-ws8,984 +django/contrib/sites/locale/ja/LC_MESSAGES/django.mo,sha256=RNuCS6wv8uK5TmXkSH_7SjsbUFkf24spZfTsvfoTKro,814 +django/contrib/sites/locale/ja/LC_MESSAGES/django.po,sha256=e-cj92VOVc5ycIY6NwyFh5bO7Q9q5vp5CG4dOzd_eWQ,982 +django/contrib/sites/locale/ka/LC_MESSAGES/django.mo,sha256=m8GTqr9j0ijn0YJhvnsYwlk5oYcASKbHg_5hLqZ91TI,993 +django/contrib/sites/locale/ka/LC_MESSAGES/django.po,sha256=1upohcHrQH9T34b6lW09MTtFkk5WswdYOLs2vMAJIuE,1160 +django/contrib/sites/locale/kab/LC_MESSAGES/django.mo,sha256=Utdj5gH5YPeaYMjeMzF-vjqYvYTCipre2qCBkEJSc-Y,808 +django/contrib/sites/locale/kab/LC_MESSAGES/django.po,sha256=d78Z-YanYZkyP5tpasj8oAa5RimVEmce6dlq5vDSscA,886 +django/contrib/sites/locale/kk/LC_MESSAGES/django.mo,sha256=T2dTZ83vBRfQb2dRaKOrhvO00BHQu_2bu0O0k7RsvGA,895 +django/contrib/sites/locale/kk/LC_MESSAGES/django.po,sha256=HvdSFqsumyNurDJ6NKVLjtDdSIg0KZN2v29dM748GtU,1062 +django/contrib/sites/locale/km/LC_MESSAGES/django.mo,sha256=Q7pn5E4qN957j20-iCHgrfI-p8sm3Tc8O2DWeuH0By8,701 +django/contrib/sites/locale/km/LC_MESSAGES/django.po,sha256=TOs76vlCMYOZrdHgXPWZhQH1kTBQTpzsDJ8N4kbJQ7E,926 +django/contrib/sites/locale/kn/LC_MESSAGES/django.mo,sha256=_jl_4_39oe940UMyb15NljGOd45kkCeVNpJy6JvGWTE,673 +django/contrib/sites/locale/kn/LC_MESSAGES/django.po,sha256=cMPXF2DeiQuErhyFMe4i7swxMoqoz1sqtBEXf4Ghx1c,921 +django/contrib/sites/locale/ko/LC_MESSAGES/django.mo,sha256=wlfoWG-vmMSCipUJVVC0Y_W7QbGNNE-oEnVwl_6-AmY,807 +django/contrib/sites/locale/ko/LC_MESSAGES/django.po,sha256=TENAk9obGUxFwMnJQj_V9sZxEKJj4DyWMuGpx3Ft_pM,1049 +django/contrib/sites/locale/ky/LC_MESSAGES/django.mo,sha256=IYxp8jG5iyN81h7YJqOiSQdOH7DnwOiIvelKZfzP6ZA,811 +django/contrib/sites/locale/ky/LC_MESSAGES/django.po,sha256=rxPdgQoBtGQSi5diOy3MXyoM4ffpwdWCc4WE3pjIHEI,927 +django/contrib/sites/locale/lb/LC_MESSAGES/django.mo,sha256=xokesKl7h7k9dXFKIJwGETgwx1Ytq6mk2erBSxkgY-o,474 +django/contrib/sites/locale/lb/LC_MESSAGES/django.po,sha256=1yRdK9Zyh7kcWG7wUexuF9-zxEaKLS2gG3ggVOHbRJ8,779 +django/contrib/sites/locale/lt/LC_MESSAGES/django.mo,sha256=bK6PJtd7DaOgDukkzuqos5ktgdjSF_ffL9IJTQY839s,869 +django/contrib/sites/locale/lt/LC_MESSAGES/django.po,sha256=T-vdVqs9KCz9vMs9FfushgZN9z7LQOT-C86D85H2X8c,1195 +django/contrib/sites/locale/lv/LC_MESSAGES/django.mo,sha256=t9bQiVqpAmXrq8QijN4Lh0n6EGUGQjnuH7hDcu21z4c,823 +django/contrib/sites/locale/lv/LC_MESSAGES/django.po,sha256=vMaEtXGosD3AcTomiuctbOpjLes8TRBnumLe8DC4yq4,1023 +django/contrib/sites/locale/mk/LC_MESSAGES/django.mo,sha256=_YXasRJRWjYmmiEWCrAoqnrKuHHPBG_v_EYTUe16Nfo,885 +django/contrib/sites/locale/mk/LC_MESSAGES/django.po,sha256=AgdIjiSpN0P5o5rr5Ie4sFhnmS5d4doB1ffk91lmOvY,1062 +django/contrib/sites/locale/ml/LC_MESSAGES/django.mo,sha256=axNQVBY0nbR7hYa5bzNtdxB17AUOs2WXhu0Rg--FA3Q,1007 +django/contrib/sites/locale/ml/LC_MESSAGES/django.po,sha256=Sg7hHfK8OMs05ebtTv8gxS6_2kZv-OODwf7okP95Jtk,1169 +django/contrib/sites/locale/mn/LC_MESSAGES/django.mo,sha256=w2sqJRAe0wyz_IuCZ_Ocubs_VHL6wV1BcutWPz0dseQ,867 +django/contrib/sites/locale/mn/LC_MESSAGES/django.po,sha256=Zh_Eao0kLZsrQ8wkL1f-pRrsAtNJOspu45uStq5t8Mo,1127 +django/contrib/sites/locale/mr/LC_MESSAGES/django.mo,sha256=2Z5jaGJzpiJTCnhCk8ulCDeAdj-WwR99scdHFPRoHoA,468 +django/contrib/sites/locale/mr/LC_MESSAGES/django.po,sha256=pqnjF5oxvpMyjijy6JfI8qJbbbowZzE5tZF0DMYiCBs,773 +django/contrib/sites/locale/ms/LC_MESSAGES/django.mo,sha256=GToJlS8yDNEy-D3-p7p8ZlWEZYHlSzZAcVIH5nQEkkI,727 +django/contrib/sites/locale/ms/LC_MESSAGES/django.po,sha256=_4l4DCIqSWZtZZNyfzpBA0V-CbAaHe9Ckz06VLbTjFo,864 +django/contrib/sites/locale/my/LC_MESSAGES/django.mo,sha256=jN59e9wRheZYx1A4t_BKc7Hx11J5LJg2wQRd21aQv08,961 +django/contrib/sites/locale/my/LC_MESSAGES/django.po,sha256=EhqYIW5-rX33YjsDsBwfiFb3BK6fZKVc3CRYeJpZX1E,1086 +django/contrib/sites/locale/nb/LC_MESSAGES/django.mo,sha256=AaiHGcmcciy5IMBPVAShcc1OQOETJvBCv7GYHMcIQMA,793 +django/contrib/sites/locale/nb/LC_MESSAGES/django.po,sha256=936zoN1sPSiiq7GuH01umrw8W6BtymYEU3bCfOQyfWE,1000 +django/contrib/sites/locale/ne/LC_MESSAGES/django.mo,sha256=n96YovpBax3T5VZSmIfGmd7Zakn9FJShJs5rvUX7Kf0,863 +django/contrib/sites/locale/ne/LC_MESSAGES/django.po,sha256=B14rhDd8GAaIjxd1sYjxO2pZfS8gAwZ1C-kCdVkRXho,1078 +django/contrib/sites/locale/nl/LC_MESSAGES/django.mo,sha256=ghu-tNPNZuE4sVRDWDVmmmVNPYZLWYm_UPJRqh8wmec,735 +django/contrib/sites/locale/nl/LC_MESSAGES/django.po,sha256=1DCQNzMRhy4vW-KkmlPGy58UR27Np5ilmYhmjaq-8_k,1030 +django/contrib/sites/locale/nn/LC_MESSAGES/django.mo,sha256=eSW8kwbzm2HsE9s9IRCsAo9juimVQjcfdd8rtl3TQJM,731 +django/contrib/sites/locale/nn/LC_MESSAGES/django.po,sha256=OOyvE7iji9hwvz8Z_OxWoKw2e3ptk3dqeqlriXgilSc,915 +django/contrib/sites/locale/os/LC_MESSAGES/django.mo,sha256=Su06FkWMOPzBxoung3bEju_EnyAEAXROoe33imO65uQ,806 +django/contrib/sites/locale/os/LC_MESSAGES/django.po,sha256=4i4rX6aXDUKjq64T02iStqV2V2erUsSVnTivh2XtQeY,963 +django/contrib/sites/locale/pa/LC_MESSAGES/django.mo,sha256=tOHiisOtZrTyIFoo4Ipn_XFH9hhu-ubJLMdOML5ZUgk,684 +django/contrib/sites/locale/pa/LC_MESSAGES/django.po,sha256=ztGyuqvzxRfNjqDG0rMLCu_oQ8V3Dxdsx0WZoYUyNv8,912 +django/contrib/sites/locale/pl/LC_MESSAGES/django.mo,sha256=lo5K262sZmo-hXvcHoBsEDqX8oJEPSxJY5EfRIqHZh0,903 +django/contrib/sites/locale/pl/LC_MESSAGES/django.po,sha256=-kQ49UvXITMy1vjJoN_emuazV_EjNDQnZDERXWNoKvw,1181 +django/contrib/sites/locale/pt/LC_MESSAGES/django.mo,sha256=PrcFQ04lFJ7mIYThXbW6acmDigEFIoLAC0PYk5hfaJs,797 +django/contrib/sites/locale/pt/LC_MESSAGES/django.po,sha256=Aj8hYI9W5nk5uxKHj1oE-b9bxmmuoeXLKaJDPfI2x2o,993 +django/contrib/sites/locale/pt_BR/LC_MESSAGES/django.mo,sha256=BsFfarOR6Qk67fB-tTWgGhuOReJSgjwJBkIzZsv28vo,824 +django/contrib/sites/locale/pt_BR/LC_MESSAGES/django.po,sha256=jfvgelpWn2VQqYe2_CE39SLTsscCckvjuZo6dWII28c,1023 +django/contrib/sites/locale/ro/LC_MESSAGES/django.mo,sha256=oGsZw4_uYpaH6adMxnAuifJgHeZ_ytRZ4rFhiNfRQkQ,857 +django/contrib/sites/locale/ro/LC_MESSAGES/django.po,sha256=tWbWVbjFFELNzSXX4_5ltmzEeEJsY3pKwgEOjgV_W_8,1112 +django/contrib/sites/locale/ru/LC_MESSAGES/django.mo,sha256=bIZJWMpm2O5S6RC_2cfkrp5NXaTU2GWSsMr0wHVEmcw,1016 +django/contrib/sites/locale/ru/LC_MESSAGES/django.po,sha256=jHy5GR05ZSjLmAwaVNq3m0WdhO9GYxge3rDBziqesA8,1300 +django/contrib/sites/locale/sk/LC_MESSAGES/django.mo,sha256=-EYdm14ZjoR8bd7Rv2b5G7UJVSKmZa1ItLsdATR3-Cg,822 +django/contrib/sites/locale/sk/LC_MESSAGES/django.po,sha256=VSRlsq8uk-hP0JI94iWsGX8Al76vvGK4N1xIoFtoRQM,1070 +django/contrib/sites/locale/sl/LC_MESSAGES/django.mo,sha256=JmkpTKJGWgnBM3CqOUriGvrDnvg2YWabIU2kbYAOM4s,845 +django/contrib/sites/locale/sl/LC_MESSAGES/django.po,sha256=qWrWrSz5r3UOVraX08ILt3TTmfyTDGKbJKbTlN9YImU,1059 +django/contrib/sites/locale/sq/LC_MESSAGES/django.mo,sha256=DMLN1ZDJeDnslavjcKloXSXn6IvangVliVP3O6U8dAY,769 +django/contrib/sites/locale/sq/LC_MESSAGES/django.po,sha256=zg3ALcMNZErAS_xFxmtv6TmXZ0vxobX5AzCwOSRSwc8,930 +django/contrib/sites/locale/sr/LC_MESSAGES/django.mo,sha256=8kfi9IPdB2reF8C_eC2phaP6qonboHPwes_w3UgNtzw,935 +django/contrib/sites/locale/sr/LC_MESSAGES/django.po,sha256=A7xaen8H1W4uMBRAqCXT_0KQMoA2-45AUNDfGo9FydI,1107 +django/contrib/sites/locale/sr_Latn/LC_MESSAGES/django.mo,sha256=jMXiq18efq0wErJAQfJR1fCnkYcEb7OYXg8sv6kzP0s,815 +django/contrib/sites/locale/sr_Latn/LC_MESSAGES/django.po,sha256=9jkWYcZCTfQr2UZtyvhWDAmEHBrzunJUZcx7FlrFOis,1004 +django/contrib/sites/locale/sv/LC_MESSAGES/django.mo,sha256=1AttMJ2KbQQgJVH9e9KuCKC0UqDHvWSPcKkbPkSLphQ,768 +django/contrib/sites/locale/sv/LC_MESSAGES/django.po,sha256=N7wqrcFb5ZNX83q1ZCkpkP94Lb3ZIBUATDssNT8F51c,1028 +django/contrib/sites/locale/sw/LC_MESSAGES/django.mo,sha256=cWjjDdFXBGmpUm03UDtgdDrREa2r75oMsXiEPT_Bx3g,781 +django/contrib/sites/locale/sw/LC_MESSAGES/django.po,sha256=oOKNdztQQU0sd6XmLI-n3ONmTL7jx3Q0z1YD8673Wi8,901 +django/contrib/sites/locale/ta/LC_MESSAGES/django.mo,sha256=CLO41KsSKqBrgtrHi6fmXaBk-_Y2l4KBLDJctZuZyWY,714 +django/contrib/sites/locale/ta/LC_MESSAGES/django.po,sha256=YsTITHg7ikkNcsP29tDgkZrUdtO0s9PrV1XPu4mgqCw,939 +django/contrib/sites/locale/te/LC_MESSAGES/django.mo,sha256=GmIWuVyIOcoQoAmr2HxCwBDE9JUYEktzYig93H_4v50,687 +django/contrib/sites/locale/te/LC_MESSAGES/django.po,sha256=jbncxU9H3EjXxWPsEoCKJhKi392XXTGvWyuenqLDxps,912 +django/contrib/sites/locale/tg/LC_MESSAGES/django.mo,sha256=wiWRlf3AN5zlFMNyP_rSDZS7M5rHQJ2DTUHARtXjim8,863 +django/contrib/sites/locale/tg/LC_MESSAGES/django.po,sha256=VBGZfJIw40JZe15ghsk-n3qUVX0VH2nFQQhpBy_lk1Y,1026 +django/contrib/sites/locale/th/LC_MESSAGES/django.mo,sha256=dQOp4JoP3gvfsxqEQ73L6F8FgH1YtAA9hYY-Uz5sv6Y,898 +django/contrib/sites/locale/th/LC_MESSAGES/django.po,sha256=auZBoKKKCHZbbh0PaUr9YKiWB1TEYZoj4bE7efAonV8,1077 +django/contrib/sites/locale/tk/LC_MESSAGES/django.mo,sha256=YhzSiVb_NdG1s7G1-SGGd4R3uweZQgnTs3G8Lv9r5z0,755 +django/contrib/sites/locale/tk/LC_MESSAGES/django.po,sha256=sigmzH3Ni2vJwLJ7ba8EeB4wnDXsg8rQRFExZAGycF4,917 +django/contrib/sites/locale/tr/LC_MESSAGES/django.mo,sha256=ryf01jcvvBMGPKkdViieDuor-Lr2KRXZeFF1gPupCOA,758 +django/contrib/sites/locale/tr/LC_MESSAGES/django.po,sha256=L9tsnwxw1BEJD-Nm3m1RAS7ekgdmyC0ETs_mr7tQw1E,1043 +django/contrib/sites/locale/tt/LC_MESSAGES/django.mo,sha256=gmmjXeEQUlBpfDmouhxE-qpEtv-iWdQSobYL5MWprZc,706 +django/contrib/sites/locale/tt/LC_MESSAGES/django.po,sha256=yj49TjwcZ4YrGqnJrKh3neKydlTgwYduto9KsmxI_eI,930 +django/contrib/sites/locale/udm/LC_MESSAGES/django.mo,sha256=CNmoKj9Uc0qEInnV5t0Nt4ZnKSZCRdIG5fyfSsqwky4,462 +django/contrib/sites/locale/udm/LC_MESSAGES/django.po,sha256=vrLZ0XJF63CO3IucbQpd12lxuoM9S8tTUv6cpu3g81c,767 +django/contrib/sites/locale/ug/LC_MESSAGES/django.mo,sha256=EBWMPAJLaxkIPQ5hm_nMRxs7Y0SEEgu6zcDM4jBUAt8,868 +django/contrib/sites/locale/ug/LC_MESSAGES/django.po,sha256=9a0kmoIxg-KMu5faIjcRgWehr3Ild-stVZsBdDrzHV0,1030 +django/contrib/sites/locale/uk/LC_MESSAGES/django.mo,sha256=H4806mPqOoHJFm549F7drzsfkvAXWKmn1w_WVwQx9rk,960 +django/contrib/sites/locale/uk/LC_MESSAGES/django.po,sha256=CJZTOaurDXwpgBiwXx3W7juaF0EctEImPhJdDn8j1xU,1341 +django/contrib/sites/locale/ur/LC_MESSAGES/django.mo,sha256=s6QL8AB_Mp9haXS4n1r9b0YhEUECPxUyPrHTMI3agts,654 +django/contrib/sites/locale/ur/LC_MESSAGES/django.po,sha256=R9tv3qtett8CUGackoHrc5XADeygVKAE0Fz8YzK2PZ4,885 +django/contrib/sites/locale/uz/LC_MESSAGES/django.mo,sha256=OsuqnLEDl9gUAwsmM2s1KH7VD74ID-k7JXcjGhjFlEY,799 +django/contrib/sites/locale/uz/LC_MESSAGES/django.po,sha256=RoaOwLDjkqqIJTuxpuY7eMLo42n6FoYAYutCfMaDk4I,935 +django/contrib/sites/locale/vi/LC_MESSAGES/django.mo,sha256=YOaKcdrN1238Zdm81jUkc2cpxjInAbdnhsSqHP_jQsI,762 +django/contrib/sites/locale/vi/LC_MESSAGES/django.po,sha256=AHcqR2p0fdscLvzbJO_a-CzMzaeRL4LOw4HB9K3noVQ,989 +django/contrib/sites/locale/zh_Hans/LC_MESSAGES/django.mo,sha256=7D9_pDY5lBRpo1kfzIQL-PNvIg-ofCm7cBHE1-JWlMk,779 +django/contrib/sites/locale/zh_Hans/LC_MESSAGES/django.po,sha256=xI_N00xhV8dWDp4fg5Mmj9ivOBBdHP79T3-JYXPyc5M,946 +django/contrib/sites/locale/zh_Hant/LC_MESSAGES/django.mo,sha256=0F6Qmh1smIXlOUNDaDwDajyyGecc1azfwh8BhXrpETo,790 +django/contrib/sites/locale/zh_Hant/LC_MESSAGES/django.po,sha256=ixbXNBNKNfrpI_B0O_zktTfo63sRFMOk1B1uIh4DGGg,1046 +django/contrib/sites/management.py,sha256=AElGktvFhWXJtlJwOKpUlIeuv2thkNM8F6boliML84U,1646 +django/contrib/sites/managers.py,sha256=uqD_Cu3P4NCp7VVdGn0NvHfhsZB05MLmiPmgot-ygz4,1994 +django/contrib/sites/middleware.py,sha256=qYcVHsHOg0VxQNS4saoLHkdF503nJR-D7Z01vE0SvUM,309 +django/contrib/sites/migrations/0001_initial.py,sha256=8fY63Z5DwbKQ1HtvAajKDhBLEufigRTsoRazyEf5RU4,1361 +django/contrib/sites/migrations/0002_alter_domain_unique.py,sha256=llK7IKQKnFCK5viHLew2ZMdV9e1sHy0H1blszEu_NKs,549 +django/contrib/sites/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/sites/models.py,sha256=0DWVfDGMYqTZgs_LP6hlVxY3ztbwPzulE9Dos8z6M3Q,3695 +django/contrib/sites/requests.py,sha256=baABc6fmTejNmk8M3fcoQ1cuI2qpJzF8Y47A1xSt8gY,641 +django/contrib/sites/shortcuts.py,sha256=nekVQADJROFYwKCD7flmWDMQ9uLAaaKztHVKl5emuWc,573 +django/contrib/staticfiles/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/staticfiles/apps.py,sha256=8G9HetU3WBNDfXKfzYfyXjZ--X3loBkkQSB7xfleIl4,504 +django/contrib/staticfiles/checks.py,sha256=FPzYotgRzxqWYDnjIK78bgQAfBSFqeJB04RDVMxlhng,846 +django/contrib/staticfiles/finders.py,sha256=_mfSsh1rOFW_ZHzX__fug0yGAuBqdXI-v0cG1aTRMEE,10996 +django/contrib/staticfiles/handlers.py,sha256=DeDbXvIUeSs0icls4e1HQ3y-6-agjO_c2O5ufkSnuls,4035 +django/contrib/staticfiles/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/staticfiles/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/staticfiles/management/commands/collectstatic.py,sha256=Zd65dgKD8JlXmoDb3ig6tvZka4gMV_6egbLcoRLJ1SA,15137 +django/contrib/staticfiles/management/commands/findstatic.py,sha256=TMMGlbV-B1aq1b27nA6Otu6hV44pqAzeuEtTV2DPmp0,1638 +django/contrib/staticfiles/management/commands/runserver.py,sha256=U_7oCY8LJX5Jn1xlMv-qF4EQoUvlT0ldB5E_0sJmRtw,1373 +django/contrib/staticfiles/storage.py,sha256=PBe2ylqyN_AwIsHyRb8rK5Z3Ekb7LlqHqz9RY1_i0GQ,21012 +django/contrib/staticfiles/testing.py,sha256=4X-EtOfXnwkJAyFT8qe4H4sbVTKgM65klLUtY81KHiE,463 +django/contrib/staticfiles/urls.py,sha256=owDM_hdyPeRmxYxZisSMoplwnzWrptI_W8-3K2f7ITA,498 +django/contrib/staticfiles/utils.py,sha256=iPXHA0yMXu37PQwCrq9zjhSzjZf_zEBXJ-dHGsqZoX8,2279 +django/contrib/staticfiles/views.py,sha256=XacxXwbhLlcmxhspeDOYvNF0OhMtSMOHGouxqQf0jlU,1261 +django/contrib/syndication/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/contrib/syndication/apps.py,sha256=7IpHoihPWtOcA6S4O6VoG0XRlqEp3jsfrNf-D-eluic,203 +django/contrib/syndication/views.py,sha256=c8T8V49cyTMk6KLna8fbULOr3aMjkqye6C5lMAFofUU,9309 +django/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/core/asgi.py,sha256=N2L3GS6F6oL-yD9Tu2otspCi2UhbRQ90LEx3ExOP1m0,386 +django/core/cache/__init__.py,sha256=-ofAjaYaEq3HsbfOjMkRnQa8-WU8UYRHeqvEot4mPiY,1928 +django/core/cache/backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/core/cache/backends/base.py,sha256=n7j5e0LbCYY3y6mv96_qEqPW1g5a_Ogp6J98dqtScv0,14291 +django/core/cache/backends/db.py,sha256=HlTGDpZugousm1JUeT9HCdp1_leMdKihOJu8cWyIqfg,11372 +django/core/cache/backends/dummy.py,sha256=fQbFiL72DnVKP9UU4WDsZYaxYKx7FlMOJhtP8aky2ic,1043 +django/core/cache/backends/filebased.py,sha256=NCV0UEKnPt8Esfd4ItW7nV9w1LNavIAy_qB02tx1By0,5788 +django/core/cache/backends/locmem.py,sha256=cqdFgPxYrfEKDvKR2IYiFV7-MwhM0CIHPxLTBxJMDTQ,4035 +django/core/cache/backends/memcached.py,sha256=cB5QRCdr9uocB-tWA1FMBQtWQRqHSRpE7UcIMYI86gI,6776 +django/core/cache/backends/redis.py,sha256=TB1bw1JK7jmUMLlu-nzuuMhtUp0JXBxzFOX149RVeFc,7924 +django/core/cache/utils.py,sha256=3ZLYgUDD6iLiLMC6vjXKfUQigsoU23ffpJx8e71M4XA,397 +django/core/checks/__init__.py,sha256=gFG0gY0C0L-akCrk1F0Q_WmkptYDLXYdyzr3wNJVIi4,1195 +django/core/checks/async_checks.py,sha256=A9p_jebELrf4fiD6jJtBM6Gvm8cMb03sSuW9Ncx3-vU,403 +django/core/checks/caches.py,sha256=hbcIFD_grXUQR2lGAzzlCX6qMJfkXj02ZDJElgdT5Yg,2643 +django/core/checks/compatibility/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/core/checks/compatibility/django_4_0.py,sha256=2s7lm9LZ0NrhaYSrw1Y5mMkL5BC68SS-TyD-TKczbEI,657 +django/core/checks/database.py,sha256=sBj-8o4DmpG5QPy1KXgXtZ0FZ0T9xdlT4XBIc70wmEQ,341 +django/core/checks/files.py,sha256=W4yYHiWrqi0d_G6tDWTw79pr2dgJY41rOv7mRpbtp2Q,522 +django/core/checks/messages.py,sha256=vIJtvmeafgwFzwcXaoRBWkcL_t2gLTLjstWSw5xCtjQ,2241 +django/core/checks/model_checks.py,sha256=8aK5uit9yP_lDfdXBJPlz_r-46faP_gIOXLszXqLQqY,8830 +django/core/checks/registry.py,sha256=FaixxLUVKtF-wNVKYXVkOVTg06lLdwOty2mfdDcEfb4,3458 +django/core/checks/security/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/core/checks/security/base.py,sha256=I0Gm446twRIhbRopEmKsdsYW_NdI7_nK_ZV28msRPEo,9140 +django/core/checks/security/csrf.py,sha256=hmFJ4m9oxDGwhDAWedmtpnIYQcI8Mxcge1D6CCoOBbc,2055 +django/core/checks/security/sessions.py,sha256=Qyb93CJeQBM5LLhhrqor4KQJR2tSpFklS-p7WltXcHc,2554 +django/core/checks/templates.py,sha256=fGX25HveO6TJCeFTqhis0rQfVcD8gif4F_iGPeJdiKI,2257 +django/core/checks/translation.py,sha256=it7VjXf10-HBdCc3z55_lSxwok9qEncdojRBG74d4FA,1990 +django/core/checks/urls.py,sha256=NIRbMn2r9GzdgOxhIujAICdYWC2M7SAiC5QuamENfU4,3328 +django/core/exceptions.py,sha256=CCihQfXYhrWW9-r7zwESNdh7g0NsQCxK4vpsA69nZGw,6576 +django/core/files/__init__.py,sha256=Rhz5Jm9BM6gy_nf5yMtswN1VsTIILYUL7Z-5edjh_HI,60 +django/core/files/base.py,sha256=MKNxxgiuwHHwGifpydBgjfZpTzdF7VxCQnVV-w8bqhg,4845 +django/core/files/images.py,sha256=nn_GxARZobyRZr15MtCjbcgax8L4JhNQmfBK3-TvB78,2643 +django/core/files/locks.py,sha256=jDXgsIrT154uvOgid_vOzd4f-L1rVXr-GZq5z_84hmQ,3613 +django/core/files/move.py,sha256=XNamwgnbncyAdlo3rEoz4xfOwdYdOHjNgajgIke667A,3250 +django/core/files/storage/__init__.py,sha256=NyYVaA8GSQATXQ0zJya56tP_IqFQDe01QAYiSEKdF0s,1192 +django/core/files/storage/base.py,sha256=XCxIRrkt5Wh5V2d7aYVDCepwCEi1mF19zHj5RE9Lp8c,7424 +django/core/files/storage/filesystem.py,sha256=gpE8z9XPxgPxUl2VMafQzmHM8r6CkpURQLM95hsEIUM,7792 +django/core/files/storage/handler.py,sha256=vecHxIQmiFQmM_02qVI9xhWvGPz7DknAhbKnSuQuIxE,1999 +django/core/files/storage/memory.py,sha256=Mz27sDPbeRXGjh77id2LHt8sErp5WAmNj89NBNRDA3I,9745 +django/core/files/storage/mixins.py,sha256=j_Y3unzk9Ccmx-QQjj4AoC3MUhXIw5nFbDYF3Qn_Fh0,700 +django/core/files/temp.py,sha256=iUegEgQ3UyUrDN10SgvKIrHfBPSej1lk-LAgJqMZBcU,2503 +django/core/files/uploadedfile.py,sha256=6hBjxmx8P0fxmZQbtj4OTsXtUk9GdIA7IUcv_KwSI08,4189 +django/core/files/uploadhandler.py,sha256=riobj6SKikjiacrhObFsW9NFRfjG5qPklsaS1pzpFvE,7179 +django/core/files/utils.py,sha256=R5_DQUkXyJOXcttihtT6e-5ekZN7uFPk3eYgNuOL4X8,2658 +django/core/handlers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/core/handlers/asgi.py,sha256=cYy-j_tCFNd7rA3REyJV1VfuZlEHjd4hsYKd7pGfadI,13735 +django/core/handlers/base.py,sha256=j7ScIbMLKYa52HqwHYhIfMWWAG749natcsBsVQsvBjc,14813 +django/core/handlers/exception.py,sha256=Qa03HgQpLx7nqp5emF0bwdiemE0X7U9FfuLfoOHMf_4,5922 +django/core/handlers/wsgi.py,sha256=81DErgzHAaZcw2UivrKqwS69QpoRF8tm0ASEc4v3uQ4,7315 +django/core/mail/__init__.py,sha256=HJSPyTBz34PsIyv4jTFJvhswauZr51NpsB-gpYR73-A,4958 +django/core/mail/backends/__init__.py,sha256=VJ_9dBWKA48MXBZXVUaTy9NhgfRonapA6UAjVFEPKD8,37 +django/core/mail/backends/base.py,sha256=Cljbb7nil40Dfpob2R8iLmlO0Yv_wlOCBA9hF2Z6W54,1683 +django/core/mail/backends/console.py,sha256=Z9damLP7VPLswrNDX9kLjL3MdWf9yAM6ZCeUv-3tRgU,1426 +django/core/mail/backends/dummy.py,sha256=sI7tAa3MfG43UHARduttBvEAYYfiLasgF39jzaZPu9E,234 +django/core/mail/backends/filebased.py,sha256=AbEBL9tXr6WIhuSQvm3dHoCpuMoDTSIkx6qFb4GMUe4,2353 +django/core/mail/backends/locmem.py,sha256=AT8ilBy4m5OWaiyqm_k82HdkQIemn4gciIYILGZag2o,885 +django/core/mail/backends/smtp.py,sha256=arpxY7kF2oVCzVFQYznt8HHJfTLTXivTPO-_1dceN6E,5802 +django/core/mail/message.py,sha256=32eMiMoNue3S1Bol17w8vHKsnq5P2y8VVeLWmvRx9os,17809 +django/core/mail/utils.py,sha256=Wf-pdSdv0WLREYzI7EVWr59K6o7tfb3d2HSbAyE3SOE,506 +django/core/management/__init__.py,sha256=gkXgKuqIpyFauk2-kgOgU-IDxcw8TjAKM_MU-erraE0,17407 +django/core/management/base.py,sha256=hBNNQyTWWLDIeHPOSU1t0qU0GnMafGcyoCknN-S0UrU,24215 +django/core/management/color.py,sha256=KXdNATK5AvxVK8wtKH2GTWApnLGCZ_1NKewTsLWCBc0,3168 +django/core/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/core/management/commands/check.py,sha256=KPtpSfNkIPPKaBP4od_vh-kp_D439sG8T9MOU41p9DA,2652 +django/core/management/commands/compilemessages.py,sha256=zb5fkLrfXSg5LQgs5m-SUBDFt7OtYmdgEmqiENv1Vrc,6992 +django/core/management/commands/createcachetable.py,sha256=1gXJFZpvuCZPd1I_VlhFlCVOPmxk-LQxFB0Tf2H2eyA,4616 +django/core/management/commands/dbshell.py,sha256=u6JY5NkdlMk6WUE4YXtIiMCid7kqN_60m78TS9jW4cw,1741 +django/core/management/commands/diffsettings.py,sha256=NNL_J0P3HRzAZd9XcW7Eo_iE_lNliIpKtdcarDbBRpc,3554 +django/core/management/commands/dumpdata.py,sha256=9HW-j7njstiw53VOhFxegH1-ihmyNMB2eThUtSG7Zec,10960 +django/core/management/commands/flush.py,sha256=9KhMxzJFqA3cOCw-0VFZ2Utb2xZ-xCnn8ZGeiVGOm8E,3611 +django/core/management/commands/inspectdb.py,sha256=Pzi2hX66nWYl9Oj6Y6zi7V9mf2UoUTsYUswkfR-YEdg,17332 +django/core/management/commands/loaddata.py,sha256=I2DQt74OJD9X-u2ldbsi7q_c274Sw3GhJSp03Fpb_7s,15968 +django/core/management/commands/makemessages.py,sha256=2wWAiFl-S9SRY5qgBU1GCB68EjnnfVhp_zzv6Jo6q8s,29423 +django/core/management/commands/makemigrations.py,sha256=4iD62w3b2sc1Hj-elD2ZUfzBcle64MPepfpyg2NbBv0,22444 +django/core/management/commands/migrate.py,sha256=Gs52PfG-w8Krv6xprAYvt4fcJDM1EJviWcWh0amlXGI,21401 +django/core/management/commands/optimizemigration.py,sha256=GVWIhX94tOLHEx53w-VrUc48euVWpKCLMw-BbpiQgIg,5224 +django/core/management/commands/runserver.py,sha256=0iA-mwsuZ2dzGCZ0ahjQyppHt1oB5NthDi0Kc6FyCEo,6728 +django/core/management/commands/sendtestemail.py,sha256=sF5TUMbD_tlGBnUsn9t-oFVGNSyeiWRIrgyPbJE88cs,1518 +django/core/management/commands/shell.py,sha256=LKmj6KYv6zpJzQ2mWtR4-u2CDSQL-_Na6TsT4JLYsi4,4613 +django/core/management/commands/showmigrations.py,sha256=dHDyNji_c55LntHanNT7ZF2EOq6pN4nulP-e4WRPMwE,6807 +django/core/management/commands/sqlflush.py,sha256=wivzfu_vA5XeU7fu2x1k7nEBky_vjtJgU4ruPja1pRQ,991 +django/core/management/commands/sqlmigrate.py,sha256=fjC7M5-cFxPV6yiqpSwpBrvo4ygZQeqoGEAVywVhKQY,3308 +django/core/management/commands/sqlsequencereset.py,sha256=Bf6HoGe5WoyAivZv1qYpklFQF9CaG4X2s1sLxT6U0Xw,1061 +django/core/management/commands/squashmigrations.py,sha256=fkNbRS5D2Yu0TCY1gLQgIPNOe8YjxpRwVJOW-b5KB-s,10861 +django/core/management/commands/startapp.py,sha256=Dhllhaf1q3EKVnyBLhJ9QsWf6JmjAtYnVLruHsmMlcQ,503 +django/core/management/commands/startproject.py,sha256=Iv7KOco1GkzGqUEME_LCx5vGi4JfY8-lzdkazDqF7k8,789 +django/core/management/commands/test.py,sha256=R0DDsSQ3rYHvA6rL0tFh-Q66JibpP6naPhirF3PeKnY,2554 +django/core/management/commands/testserver.py,sha256=aiS0tCe6uXp9hjcE1LUfZ118xAcMa28ImHL4ynQSqO8,2238 +django/core/management/sql.py,sha256=fP6Bvq4NrQB_9Tb6XsYeCg57xs2Ck6uaCXq0ojFOSvA,1851 +django/core/management/templates.py,sha256=PlaxlTex6m1d42f_HT-B2nhittfw6RmjkIphVlQ558c,15415 +django/core/management/utils.py,sha256=VbXTgGLO7HYzg3Y93nt8VkHbPOBWWyojVHDMfdyzcyc,5434 +django/core/paginator.py,sha256=YFR2EE0W2cLhEuXSWI67c33DreVVSxlz9xRjqGs50zc,7905 +django/core/serializers/__init__.py,sha256=gaH58ip_2dyUFDlfOPenMkVJftQQOBvXqCcZBjAKwTA,8772 +django/core/serializers/base.py,sha256=Tjwr-Em6UCrECtLwDSx6Me4Th2XBAWTSQLYPdVk-OQI,12630 +django/core/serializers/json.py,sha256=dP-VqkWpam7kZxTTPqnB5nZY9CEgS48bi1JAm27jwUo,3464 +django/core/serializers/jsonl.py,sha256=671JRbWRgOH3-oeD3auK9QCziwtrcdbyCIRDy5s4Evw,1879 +django/core/serializers/python.py,sha256=Sokl0FEwRwgKV7hKDAOZL30-Si6DWs9_kANyt7mFjss,6866 +django/core/serializers/pyyaml.py,sha256=77zu6PCfJg_75m36lX9X5018ADcux5qsDGajKNh4pI8,2955 +django/core/serializers/xml_serializer.py,sha256=hMfgLGmn2AuUYd9Eg4_qldfG_xNC6BmWUGBzLnj0dnE,18328 +django/core/servers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/core/servers/basehttp.py,sha256=SGp7dTLRoKi7SFlOZoWFCT7ZTymA5e3xyBC6FrU4IlY,9936 +django/core/signals.py,sha256=5vh1e7IgPN78WXPo7-hEMPN9tQcqJSZHu0WCibNgd-E,151 +django/core/signing.py,sha256=l5Ic8e7nkzG6tDet63KF64zd2fx9471s2StvPWZKHq8,9576 +django/core/validators.py,sha256=yJVZZV_Bgt7fBYC4Nbcm1IsINMuERK7UQbdGRc8Jckw,21518 +django/core/wsgi.py,sha256=2sYMSe3IBrENeQT7rys-04CRmf8hW2Q2CjlkBUIyjHk,388 +django/db/__init__.py,sha256=8W-BApKlr4YNfaDdQ544Gyp3AYYbX2E0dyDmQTiVHr0,1483 +django/db/backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/db/backends/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/db/backends/base/base.py,sha256=WiQkps8m9GSe2kAQlPHViNbggKBUJE14IXycI7OUOTA,28388 +django/db/backends/base/client.py,sha256=90Ffs6zZYCli3tJjwsPH8TItZ8tz1Pp-zhQa-EpsNqc,937 +django/db/backends/base/creation.py,sha256=9EMiIEMjAi2egrOhCZP4ckl6Ss3GIhPEXhUVF5kf8FI,15668 +django/db/backends/base/features.py,sha256=L6Ry7tFtVnUaEgpnxXBm7EZRHAlMfRdFoNZ7fhaQ3TM,15877 +django/db/backends/base/introspection.py,sha256=CJG3MUmR-wJpNm-gNWuMRMNknWp3ZdZ9DRUbKxcnwuo,7900 +django/db/backends/base/operations.py,sha256=u5TkHxWfmxxmw0ihKVhMR01DhSDCCOwllAfqRjmYHLo,29523 +django/db/backends/base/schema.py,sha256=pscbRENPs_pmLpQULjZpF2h17niX1KoUR4CGfPP-jWc,79826 +django/db/backends/base/validation.py,sha256=2zpI11hyUJr0I0cA1xmvoFwQVdZ-7_1T2F11TpQ0Rkk,1067 +django/db/backends/ddl_references.py,sha256=eBDnxoh7_PY2H8AGuZ5FUoxsEscpnmMuYEMqzfPRFqk,8129 +django/db/backends/dummy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/db/backends/dummy/base.py,sha256=im1_ubNhbY6cP8yNntqDr6Hlg5d5c_5r5IUCPCDfv28,2181 +django/db/backends/dummy/features.py,sha256=Pg8_jND-aoJomTaBBXU3hJEjzpB-rLs6VwpoKkOYuQg,181 +django/db/backends/mysql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/db/backends/mysql/base.py,sha256=xPSAd10i2meJFS5OXeVsT-t0V8Ucx99GbgD0VKF3elg,17127 +django/db/backends/mysql/client.py,sha256=IpwdI-H5r-QUoM8ZvPXHykNxKb2wevcUx8HvxTn_otU,2988 +django/db/backends/mysql/compiler.py,sha256=SPhbsHi8x_r4ZG8U7-Tnqr6F0G4rsxOyJjITKPHz3zE,3333 +django/db/backends/mysql/creation.py,sha256=8BV8YHk3qEq555nH3NHukxpZZgxtvXFvkv7XvkRlhKA,3449 +django/db/backends/mysql/features.py,sha256=qf03u20fMmwhgFsWEclF6_wLABrdYtGabfVQ3WW1XZc,12001 +django/db/backends/mysql/introspection.py,sha256=AY06ZLynWypYTEGAsR-t4F9Uj7Fb0Hqi-QNW1YwRnEQ,14498 +django/db/backends/mysql/operations.py,sha256=Z5rDicNOyT-S4qIXo0-6LeqCBn3xvG8m1E-ZPoR1L0Q,18715 +django/db/backends/mysql/schema.py,sha256=wKPn1zkYHU_r39CkA-6oSWcCU9SRpzIHLtjJeSv3K5A,10788 +django/db/backends/mysql/validation.py,sha256=XERj0lPEihKThPvzoVJmNpWdPOun64cRF3gHv-zmCGk,3093 +django/db/backends/oracle/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/db/backends/oracle/base.py,sha256=VfzWUPD5gOuxuh1BoYBgwT3pTAsThOhygJnVnpM8u7E,22964 +django/db/backends/oracle/client.py,sha256=DfDURfno8Sek13M8r5S2t2T8VUutx2hBT9DZRfow9VQ,784 +django/db/backends/oracle/creation.py,sha256=KVUU5EqNWeaeRMRj0Q2Z3EQ-F-FRuj25JaXdSTA_Q7I,20834 +django/db/backends/oracle/features.py,sha256=5o1emZUrxP6u3SiGrmTm113PV1ojEHu3Ik9qPdes0_M,6914 +django/db/backends/oracle/functions.py,sha256=2OoBYyY1Lb4B5hYbkRHjd8YY_artr3QeGu2hlojC-vc,812 +django/db/backends/oracle/introspection.py,sha256=MjjO-PqpcfiUd9WkLqiC8XGgbC4gocvymqQ1bh-ceKk,15474 +django/db/backends/oracle/operations.py,sha256=AVCSdCAWzKX7fcGLJIbLPSSwjZQgsI_mPVIZbUnEa0Q,29546 +django/db/backends/oracle/oracledb_any.py,sha256=dZY337k3TH1JfZaXZR6HmDy6roolJrj50Sbv-27neFg,550 +django/db/backends/oracle/schema.py,sha256=eyY1zK21H72pF20dg4VBx_7ZpCz04or5sdLXqe_tB6g,10835 +django/db/backends/oracle/utils.py,sha256=VcfUESst2ML9n9ehsJNgt6xRPC-P8B5CCY8XBI-2KfI,2699 +django/db/backends/oracle/validation.py,sha256=cq-Bvy5C0_rmkgng0SSQ4s74FKg2yTM1N782Gfz86nY,860 +django/db/backends/postgresql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/db/backends/postgresql/base.py,sha256=UL9QWbJo3bzoftAGBCPkVVCDYwL3RTXOw0LvZdSLuYU,18196 +django/db/backends/postgresql/client.py,sha256=RLsYyqTlSlZyEB4SI0t0TsTItDcN3enyJoIoAKrqTE8,2052 +django/db/backends/postgresql/creation.py,sha256=1KGFQAIdULSPWQ8dmJEgbCDY2F6yYM3BMrbRRM7xyUM,3677 +django/db/backends/postgresql/features.py,sha256=xXHotGfovulCQRaGqc9o1ls5xkTb46NiOWCcsy8jBAk,5394 +django/db/backends/postgresql/introspection.py,sha256=0j4Y5ZAuSk8iaMbDBjUF9zHTcL3C5WibIiJygOvZMP8,11604 +django/db/backends/postgresql/operations.py,sha256=qdnVHKrQkS7Lr7dXNtVQ8zdqTVuHktQX43et0qyl27U,15600 +django/db/backends/postgresql/psycopg_any.py,sha256=0-DwOvdWp5Wuu0XlRu_LPLSr1q1EjtzgZS2ZOyiTwXg,3774 +django/db/backends/postgresql/schema.py,sha256=vu1oxMrQP256keiPmphP2Iumv7S--soxNc67DW5OWQU,14937 +django/db/backends/signals.py,sha256=Yl14KjYJijTt1ypIZirp90lS7UTJ8UogPFI_DwbcsSc,66 +django/db/backends/sqlite3/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/db/backends/sqlite3/_functions.py,sha256=2w-Lylrt965tyijbXtq-pvFxbDKdMaDC2dbxwXo1VmE,14340 +django/db/backends/sqlite3/base.py,sha256=-5ohfIr48tfd8S6P2lQ7l7qP8yPaFH1xJfmKLx1d8lQ,13841 +django/db/backends/sqlite3/client.py,sha256=Eb_-P1w0aTbZGVNYkv7KA1ku5Il1N2RQov2lc3v0nho,321 +django/db/backends/sqlite3/creation.py,sha256=ZOg_Tiw4EStCc2ab1q7wTTkI44qCDfA1j6ezH5teJS8,6841 +django/db/backends/sqlite3/features.py,sha256=yJr6jxYbJVFF3Z4m8Zk5yooY5qZunh3K-aWHagX_lOE,6483 +django/db/backends/sqlite3/introspection.py,sha256=tW6u4aGhbTUQ0AxK3xgJPU7weA9BGkBTXelFtWRh5ow,17551 +django/db/backends/sqlite3/operations.py,sha256=ZUsxB5qUpDaKUtVVbXBhUIAiNfxprQDd5cE_wR0SXoI,17249 +django/db/backends/sqlite3/schema.py,sha256=dBvgw-QJOUdWo905HQIBMiDXfj2CavPuQNgUzUmmFcM,20216 +django/db/backends/utils.py,sha256=6F6qGDwrcxeCedFd-ZpwdUfVaq_39WV-TORhV4C4n7Y,11055 +django/db/migrations/__init__.py,sha256=Oa4RvfEa6hITCqdcqwXYC66YknFKyluuy7vtNbSc-L4,97 +django/db/migrations/autodetector.py,sha256=4g5r_x0V2QQ0ym4SNVckUhdcXAu3iF5pEeLOivYABYI,79938 +django/db/migrations/exceptions.py,sha256=SotQF7ZKgJpd9KN-gKDL8wCJAKSEgbZToM_vtUAnqHw,1204 +django/db/migrations/executor.py,sha256=_XxTCSHiwAy6KqFsqS_V2fVojDdMdKnDchCdc1nU2Bo,18923 +django/db/migrations/graph.py,sha256=vt7Pc45LuiXR8aRCrXP5Umm6VDCCTs2LAr5NXh-rxcE,13055 +django/db/migrations/loader.py,sha256=KRHdjq7A0sHqOS0JHVNlR8MtQvbY9smjId7rngwrrOU,16863 +django/db/migrations/migration.py,sha256=itZASGGepJYCY2Uv5AmLrxOgjEH1tycGV0bv3EtRjQE,9767 +django/db/migrations/operations/__init__.py,sha256=qIOjQYpm3tOtj1jsJVSpzxDH_kYAWk8MOGj-R3WYvJc,964 +django/db/migrations/operations/base.py,sha256=-wdWlbVLtUGeOeWKyuQ67R3HCx_jd0ausstbJcBT4QQ,5082 +django/db/migrations/operations/fields.py,sha256=t84pFUPNt_4_wumHNpNLzQrIDDhXn73-gpnixCSw7qI,12706 +django/db/migrations/operations/models.py,sha256=detE3MoMrjpWzvfymXkz5twZPnoJR0VgmuTHjRLsWGs,43724 +django/db/migrations/operations/special.py,sha256=3Zbya6B1nEjvIwhQLoFR8kGBZUlc26kgBxX7XS3aeFQ,7831 +django/db/migrations/optimizer.py,sha256=c0JZ5FGltD_gmh20e5SR6A21q_De6rUKfkAJKwmX4Ks,3255 +django/db/migrations/questioner.py,sha256=HVtcEBRxQwL9JrQO5r1bVIZIZUFBfs9L-siuDQERZh0,13330 +django/db/migrations/recorder.py,sha256=HviA3DydJPqpE8gowv1lAnIdLMTSRpRXuLFn53r-Q1Y,3827 +django/db/migrations/serializer.py,sha256=WiapNZroFUXbcy-UBSMksHCFs3GC-BXOLm4olKihC9o,13796 +django/db/migrations/state.py,sha256=QM63FXvMy3qFUF4jFAxFBiBRJDeLg5ltURQnUv-GTNU,40654 +django/db/migrations/utils.py,sha256=pdrzumGDhgytc5KVWdZov7cQtBt3jRASLqbmBxSRSvg,4401 +django/db/migrations/writer.py,sha256=OWRUgtTrBLndIUeNxL3-6gI5ORPdIWG_Jy9Iluizs0M,11613 +django/db/models/__init__.py,sha256=CpEIiTgT4ta4nalp01yniXO-gRu9hTfEeFrl4fIWDGk,2857 +django/db/models/aggregates.py,sha256=KKYz7KzzLoqEScCBeDq7m2RmpdhNV2tSvi2PqmxxCIA,7642 +django/db/models/base.py,sha256=WQU09g4TlVXr8f0HgpnPIe9ITrqIclQ27NFfOtlmbDU,103704 +django/db/models/constants.py,sha256=yfhLjetzfpKFqd5pIIuILL3r2pmD-nhRL-4VzrZYQ4w,209 +django/db/models/constraints.py,sha256=ZdPqdRsiby6VFwWBJhHcmhha6ObZdFn2F0sAA1TfQ7Q,19121 +django/db/models/deletion.py,sha256=SkhsZIzb0orGhZOuxZqC_RiEEQRDVJ3nZ1RrN-iUWqM,21099 +django/db/models/enums.py,sha256=mgBBX7bFzuPYgkPR9hvy4FZOtbZE5gfbhHWsvrIhONQ,3527 +django/db/models/expressions.py,sha256=OuBJeqEAe9RdZMZeQcOhjvk-n7Rm6asR0G_VWfZH4Qs,66892 +django/db/models/fields/__init__.py,sha256=9wp9GbdXdz0F2pKeZCpJ9VdPtDpiUMQwLV_w84REfo0,97825 +django/db/models/fields/files.py,sha256=HyIQ8qbipwRp2Sekm-Xr4Off5aJ1MYQ8UnfFspwzMNE,18927 +django/db/models/fields/generated.py,sha256=BujXKUls7q4vSesyDScYjDsl-x4ymHtWSDZwiRzp2IY,7396 +django/db/models/fields/json.py,sha256=ydrGNRauN3xxjez6aBzot3Xl4w9dm60ot99037n0xIY,22508 +django/db/models/fields/mixins.py,sha256=AfnqL5l3yXQmYh9sW35MPFy9AvKjA7SarXijXfd68J8,1823 +django/db/models/fields/proxy.py,sha256=eFHyl4gRTqocjgd6nID9UlQuOIppBA57Vcr71UReTAs,515 +django/db/models/fields/related.py,sha256=L6ZVMq3hVcF1ZiSylbofO0-57v8bRbpixxXNVIe5Xv4,76623 +django/db/models/fields/related_descriptors.py,sha256=xKkYxPSsYs796LMo9CN4teq6R8yMjs-rtcRc0G5QmIc,64602 +django/db/models/fields/related_lookups.py,sha256=qTe81CM5MVVxmn28jfaoTDPYgh_m4gHW7g_MyJVtrmo,7813 +django/db/models/fields/reverse_related.py,sha256=6MDvF-RplTMcHteXbElEabsf0rgElAGyMwUVjxoWJnk,12837 +django/db/models/functions/__init__.py,sha256=aglCm_JtzDYk2KmxubDN_78CGG3JCfRWnfJ74Oj5YJ4,2658 +django/db/models/functions/comparison.py,sha256=_3_til98rfsc4YdeUQAszkRWBdwx4iGcuXd8BVc-yHs,8515 +django/db/models/functions/datetime.py,sha256=j2ZnlWCusQ23yI6o96G9AhHwNojzhEvPJ72l8MK8gN4,13502 +django/db/models/functions/math.py,sha256=9BH1yLLP5z_-kcfe5UuSH-4YkSEeBE1Ga88102lX83Y,6092 +django/db/models/functions/mixins.py,sha256=04MuLCiXw4DYDx0kRU3g_QZcOOCbttAkFEa4WtwGeao,2229 +django/db/models/functions/text.py,sha256=SG34jsbxvc9HDH1px_MDQMLabhkZvg86NLvENDS04tI,11157 +django/db/models/functions/window.py,sha256=g4fryay1tLQCpZRfmPQhrTiuib4RvPqtwFdodlLbi98,2841 +django/db/models/indexes.py,sha256=erBp-Vut5DAHbVrsSmWlWgeH2hNNuI77auGpubstQik,11895 +django/db/models/lookups.py,sha256=MUhIW_41p2nEoNkrPq3oCW_vbcdfJGEyoRXuH0QEmMQ,26998 +django/db/models/manager.py,sha256=n97p4q0ttwmI1XcF9dAl8Pfg5Zs8iudufhWebQ7Xau0,6866 +django/db/models/options.py,sha256=eYGBk7nFXVPqXzSqHYzy6pSK_WU1rSE8K-4eWk7HCH4,39012 +django/db/models/query.py,sha256=sVWs4U9dkr4Pm4hZmuEAj_aScymcq0N0BNUb_XTbM_I,105466 +django/db/models/query_utils.py,sha256=fYlGtEwbq2hyPmztJARGuvLP9IxwtnOLrGX9gmTnJLE,16653 +django/db/models/signals.py,sha256=mG6hxVWugr_m0ugTU2XAEMiqlu2FJ4CBuGa34dLJvEQ,1622 +django/db/models/sql/__init__.py,sha256=BGZ1GSn03dTOO8PYx6vF1-ImE3g1keZsQ74AHJoQwmQ,241 +django/db/models/sql/compiler.py,sha256=caaQH0xn8-5eMxz09USAh9lkNh2ei_rAQe1NEr0b4Vw,89233 +django/db/models/sql/constants.py,sha256=usb1LSh9WNGPsurWAGppDkV0wYJJg5GEegKibQdS718,533 +django/db/models/sql/datastructures.py,sha256=hCZH_Z80ZaaNOMJ60wAvAZ3NC10FoESqtAeN6ec2zY4,8270 +django/db/models/sql/query.py,sha256=X_GW655pwF9gbskNJTqSybRPOchmc4Igk365NAHyddI,116085 +django/db/models/sql/subqueries.py,sha256=0UgV3H-aG3178weqpp_hfQkwgUxm5t3LDlSKGAqmaU8,6029 +django/db/models/sql/where.py,sha256=Ih4LskF7lhzyrIVhCdxbQsceySfUoxaOIhhoHW2GGoY,12944 +django/db/models/utils.py,sha256=vzojL0uUQHuOm2KxTJ19DHGnQ1pBXbnWaTlzR0vVimI,2182 +django/db/transaction.py,sha256=U9O5DF_Eg8SG1dvcn_oFimU-ONaXKoHdDsXl0ZYtjFM,12504 +django/db/utils.py,sha256=RKtSSyVJmM5__SAs1pY0njX6hLVRy1WIBggYo1zP4RI,9279 +django/dispatch/__init__.py,sha256=qP203zNwjaolUFnXLNZHnuBn7HNzyw9_JkODECRKZbc,286 +django/dispatch/dispatcher.py,sha256=wxfVytgIV_1NYlCX5T1vA9ZbxRWXZy1EsYf50XvYAhk,17711 +django/dispatch/license.txt,sha256=VABMS2BpZOvBY68W0EYHwW5Cj4p4oCb-y1P3DAn0qU8,1743 +django/forms/__init__.py,sha256=S6ckOMmvUX-vVST6AC-M8BzsfVQwuEUAdHWabMN-OGI,368 +django/forms/boundfield.py,sha256=52nqDEIyGfoKLtxlFVDQrTe503tpCNS1ALm4r86tOps,12994 +django/forms/fields.py,sha256=kqiW2-OYIS_ARiX-xIIBbXdwFpWnXMzHECkPcEiWMi0,49244 +django/forms/forms.py,sha256=-YMYa7DSAdgk3dU6qJUJkSHpsyAckJkR-uGQ1L7Fxok,16115 +django/forms/formsets.py,sha256=MIEStWrUo7n62z92lvHyPGEltzZwDIEqevzsVF70Wco,21184 +django/forms/jinja2/django/forms/attrs.html,sha256=TD0lNK-ohDjb_bWg1Kosdn4kU01B_M0_C19dp9kYJqo,165 +django/forms/jinja2/django/forms/div.html,sha256=WaOqY1hQe1l6vnc3TdlBmQnQRsofIoNDvGAfg2-X1lU,514 +django/forms/jinja2/django/forms/errors/dict/default.html,sha256=1DLQf0Czjr5V4cghQOyJr3v34G2ClF0RAOc-H7GwXUE,49 +django/forms/jinja2/django/forms/errors/dict/text.txt,sha256=E7eqEWc6q2_kLyc9k926klRe2mPp4O2VqG-2_MliYaU,113 +django/forms/jinja2/django/forms/errors/dict/ul.html,sha256=65EYJOqDAn7-ca7FtjrcdbXygLE-RA_IJQTltO7qS1Q,137 +django/forms/jinja2/django/forms/errors/list/default.html,sha256=q41d4u6XcxDL06gRAVdU021kM_iFLIt5BuYa-HATOWE,49 +django/forms/jinja2/django/forms/errors/list/text.txt,sha256=VVbLrGMHcbs1hK9-2v2Y6SIoH9qRMtlKzM6qzLVAFyE,52 +django/forms/jinja2/django/forms/errors/list/ul.html,sha256=AwXfGxnos6llX44dhxMChz6Kk6VStAJiNzUpSLN8_y4,119 +django/forms/jinja2/django/forms/field.html,sha256=n7KoCKcYoERXwyxUsKk_uGfUBM-fyNar8GDstlDTi54,417 +django/forms/jinja2/django/forms/formsets/div.html,sha256=uq10XZdQ1WSt6kJFoKxtluvnCKE4L3oYcLkPraF4ovs,86 +django/forms/jinja2/django/forms/formsets/p.html,sha256=HzEX7XdSDt9owDkYJvBdFIETeU9RDbXc1e4R2YEt6ec,84 +django/forms/jinja2/django/forms/formsets/table.html,sha256=L9B4E8lR0roTr7dBoMiUlekuMbO-3y4_b4NHm6Oy_Vg,88 +django/forms/jinja2/django/forms/formsets/ul.html,sha256=ANvMWb6EeFAtLPDTr61IeI3-YHtAYZCT_zmm-_y-5Oc,85 +django/forms/jinja2/django/forms/label.html,sha256=trXo6yF4ezDv-y-8y1yJnP7sSByw0TTppgZLcrmfR6M,147 +django/forms/jinja2/django/forms/p.html,sha256=NsTxSuqV58iOT7_3EvWRkY1zVYCdhzLBrtde1V47QTA,740 +django/forms/jinja2/django/forms/table.html,sha256=RoJweFtjCPwkFhAAlPT7i_sSCDxo1xMs3NH0uFIla20,881 +django/forms/jinja2/django/forms/ul.html,sha256=svUpAmU5EhhGVHKs8qXixJN-3SzPft8CXoG3-4gegs8,779 +django/forms/jinja2/django/forms/widgets/attrs.html,sha256=_J2P-AOpHFhIwaqCNcrJFxEY4s-KPdy0Wcq0KlarIG0,172 +django/forms/jinja2/django/forms/widgets/checkbox.html,sha256=fXpbxMzAdbv_avfWC5464gD2jFng931Eq7vzbzy1-yA,48 +django/forms/jinja2/django/forms/widgets/checkbox_option.html,sha256=U2dFtAXvOn_eK4ok0oO6BwKE-3-jozJboGah_PQFLVM,55 +django/forms/jinja2/django/forms/widgets/checkbox_select.html,sha256=-ob26uqmvrEUMZPQq6kAqK4KBk2YZHTCWWCM6BnaL0w,57 +django/forms/jinja2/django/forms/widgets/clearable_file_input.html,sha256=h5_tWYnKRjGTYkzOq6AfDpkffj31DdEolpdtInilitM,511 +django/forms/jinja2/django/forms/widgets/date.html,sha256=fXpbxMzAdbv_avfWC5464gD2jFng931Eq7vzbzy1-yA,48 +django/forms/jinja2/django/forms/widgets/datetime.html,sha256=fXpbxMzAdbv_avfWC5464gD2jFng931Eq7vzbzy1-yA,48 +django/forms/jinja2/django/forms/widgets/email.html,sha256=fXpbxMzAdbv_avfWC5464gD2jFng931Eq7vzbzy1-yA,48 +django/forms/jinja2/django/forms/widgets/file.html,sha256=fXpbxMzAdbv_avfWC5464gD2jFng931Eq7vzbzy1-yA,48 +django/forms/jinja2/django/forms/widgets/hidden.html,sha256=fXpbxMzAdbv_avfWC5464gD2jFng931Eq7vzbzy1-yA,48 +django/forms/jinja2/django/forms/widgets/input.html,sha256=u12fZde-ugkEAAkPAtAfSxwGQmYBkXkssWohOUs-xoE,172 +django/forms/jinja2/django/forms/widgets/input_option.html,sha256=PyRNn9lmE9Da0-RK37zW4yJZUSiJWgIPCU9ou5oUC28,219 +django/forms/jinja2/django/forms/widgets/multiple_hidden.html,sha256=T54-n1ZeUlTd-svM3C4tLF42umKM0R5A7fdfsdthwkA,54 +django/forms/jinja2/django/forms/widgets/multiple_input.html,sha256=voM3dqu69R0Z202TmCgMFM6toJp7FgFPVvbWY9WKEAU,395 +django/forms/jinja2/django/forms/widgets/multiwidget.html,sha256=pr-MxRyucRxn_HvBGZvbc3JbFyrAolbroxvA4zmPz2Y,86 +django/forms/jinja2/django/forms/widgets/number.html,sha256=fXpbxMzAdbv_avfWC5464gD2jFng931Eq7vzbzy1-yA,48 +django/forms/jinja2/django/forms/widgets/password.html,sha256=fXpbxMzAdbv_avfWC5464gD2jFng931Eq7vzbzy1-yA,48 +django/forms/jinja2/django/forms/widgets/radio.html,sha256=-ob26uqmvrEUMZPQq6kAqK4KBk2YZHTCWWCM6BnaL0w,57 +django/forms/jinja2/django/forms/widgets/radio_option.html,sha256=U2dFtAXvOn_eK4ok0oO6BwKE-3-jozJboGah_PQFLVM,55 +django/forms/jinja2/django/forms/widgets/select.html,sha256=ESyDzbLTtM7-OG34EuSUnvxCtyP5IrQsZh0jGFrIdEA,365 +django/forms/jinja2/django/forms/widgets/select_date.html,sha256=AzaPLlNLg91qkVQwwtAJxwOqDemrtt_btSkWLpboJDs,54 +django/forms/jinja2/django/forms/widgets/select_option.html,sha256=tNa1D3G8iy2ZcWeKyI-mijjDjRmMaqSo-jnAR_VS3Qc,110 +django/forms/jinja2/django/forms/widgets/splitdatetime.html,sha256=AzaPLlNLg91qkVQwwtAJxwOqDemrtt_btSkWLpboJDs,54 +django/forms/jinja2/django/forms/widgets/splithiddendatetime.html,sha256=AzaPLlNLg91qkVQwwtAJxwOqDemrtt_btSkWLpboJDs,54 +django/forms/jinja2/django/forms/widgets/text.html,sha256=fXpbxMzAdbv_avfWC5464gD2jFng931Eq7vzbzy1-yA,48 +django/forms/jinja2/django/forms/widgets/textarea.html,sha256=Av1Y-hpXUU2AjrhnUivgZFKNBLdwCSZSeuSmCqmCkDA,145 +django/forms/jinja2/django/forms/widgets/time.html,sha256=fXpbxMzAdbv_avfWC5464gD2jFng931Eq7vzbzy1-yA,48 +django/forms/jinja2/django/forms/widgets/url.html,sha256=fXpbxMzAdbv_avfWC5464gD2jFng931Eq7vzbzy1-yA,48 +django/forms/models.py,sha256=0TpN3ABc5C4OMTipYf-Ui2cUj_Ort7DDYJl2tK8Mf20,60753 +django/forms/renderers.py,sha256=48Xahe1sV49TVX_A3aKwZqMbGgC7jd0LkZ1FX2vgU_k,3203 +django/forms/templates/django/forms/attrs.html,sha256=UFPgCXXCAkbumxZE1NM-aJVE4VCe2RjCrHLNseibv3I,165 +django/forms/templates/django/forms/div.html,sha256=PgJSGlEXXLmh58WLH49cxvUaWI8bxE0ioTf-MY89uF8,525 +django/forms/templates/django/forms/errors/dict/default.html,sha256=tFtwfHlkOY_XaKjoUPsWshiSWT5olxm3kDElND-GQtQ,48 +django/forms/templates/django/forms/errors/dict/text.txt,sha256=E7eqEWc6q2_kLyc9k926klRe2mPp4O2VqG-2_MliYaU,113 +django/forms/templates/django/forms/errors/dict/ul.html,sha256=65EYJOqDAn7-ca7FtjrcdbXygLE-RA_IJQTltO7qS1Q,137 +django/forms/templates/django/forms/errors/list/default.html,sha256=Kmx1nwrzQ49MaP80Gd17GC5TQH4B7doWa3I3azXvoHA,48 +django/forms/templates/django/forms/errors/list/text.txt,sha256=VVbLrGMHcbs1hK9-2v2Y6SIoH9qRMtlKzM6qzLVAFyE,52 +django/forms/templates/django/forms/errors/list/ul.html,sha256=5kt2ckbr3esK0yoPzco2EB0WzS8MvGzau_rAcomB508,118 +django/forms/templates/django/forms/field.html,sha256=qlnknH_1Q76IL6zRnC3ewp5ndGpDjnjrBwmSYZxYfQU,413 +django/forms/templates/django/forms/formsets/div.html,sha256=lmIRSTBuGczEd2lj-UfDS9zAlVv8ntpmRo-boDDRwEg,84 +django/forms/templates/django/forms/formsets/p.html,sha256=qkoHKem-gb3iqvTtROBcHNJqI-RoUwLHUvJC6EoHg-I,82 +django/forms/templates/django/forms/formsets/table.html,sha256=N0G9GETzJfV16wUesvdrNMDwc8Fhh6durrmkHUPeDZY,86 +django/forms/templates/django/forms/formsets/ul.html,sha256=bGQpjbpKwMahyiIP4-2p3zg3yJP-pN1A48yCqhHdw7o,83 +django/forms/templates/django/forms/label.html,sha256=0bJCdIj8G5e2Gaw3QUR0ZMdwVavC80YwxS5E0ShkzmE,122 +django/forms/templates/django/forms/p.html,sha256=NhXyxIJCngGT7xK2nA4_vpEWWiaIcIUKGVOmMcnjRy4,751 +django/forms/templates/django/forms/table.html,sha256=ELTypjKfqSluAJk6-no0m2_Rve3c6HJoWV3hQ_xfnto,892 +django/forms/templates/django/forms/ul.html,sha256=vPmRsKnLcofRZJq23XHxnBs8PLs6jD4_Pw1ULbtSxPg,790 +django/forms/templates/django/forms/widgets/attrs.html,sha256=9ylIPv5EZg-rx2qPLgobRkw6Zq_WJSM8kt106PpSYa0,172 +django/forms/templates/django/forms/widgets/checkbox.html,sha256=fXpbxMzAdbv_avfWC5464gD2jFng931Eq7vzbzy1-yA,48 +django/forms/templates/django/forms/widgets/checkbox_option.html,sha256=U2dFtAXvOn_eK4ok0oO6BwKE-3-jozJboGah_PQFLVM,55 +django/forms/templates/django/forms/widgets/checkbox_select.html,sha256=-ob26uqmvrEUMZPQq6kAqK4KBk2YZHTCWWCM6BnaL0w,57 +django/forms/templates/django/forms/widgets/clearable_file_input.html,sha256=h5_tWYnKRjGTYkzOq6AfDpkffj31DdEolpdtInilitM,511 +django/forms/templates/django/forms/widgets/date.html,sha256=fXpbxMzAdbv_avfWC5464gD2jFng931Eq7vzbzy1-yA,48 +django/forms/templates/django/forms/widgets/datetime.html,sha256=fXpbxMzAdbv_avfWC5464gD2jFng931Eq7vzbzy1-yA,48 +django/forms/templates/django/forms/widgets/email.html,sha256=fXpbxMzAdbv_avfWC5464gD2jFng931Eq7vzbzy1-yA,48 +django/forms/templates/django/forms/widgets/file.html,sha256=fXpbxMzAdbv_avfWC5464gD2jFng931Eq7vzbzy1-yA,48 +django/forms/templates/django/forms/widgets/hidden.html,sha256=fXpbxMzAdbv_avfWC5464gD2jFng931Eq7vzbzy1-yA,48 +django/forms/templates/django/forms/widgets/input.html,sha256=dwzzrLocGLZQIaGe-_X8k7z87jV6AFtn28LilnUnUH0,189 +django/forms/templates/django/forms/widgets/input_option.html,sha256=PyRNn9lmE9Da0-RK37zW4yJZUSiJWgIPCU9ou5oUC28,219 +django/forms/templates/django/forms/widgets/multiple_hidden.html,sha256=T54-n1ZeUlTd-svM3C4tLF42umKM0R5A7fdfsdthwkA,54 +django/forms/templates/django/forms/widgets/multiple_input.html,sha256=jxEWRqV32a73340eQ0uIn672Xz5jW9qm3V_srByLEd0,426 +django/forms/templates/django/forms/widgets/multiwidget.html,sha256=slk4AgCdXnVmFvavhjVcsza0quTOP2LG50D8wna0dw0,117 +django/forms/templates/django/forms/widgets/number.html,sha256=fXpbxMzAdbv_avfWC5464gD2jFng931Eq7vzbzy1-yA,48 +django/forms/templates/django/forms/widgets/password.html,sha256=fXpbxMzAdbv_avfWC5464gD2jFng931Eq7vzbzy1-yA,48 +django/forms/templates/django/forms/widgets/radio.html,sha256=-ob26uqmvrEUMZPQq6kAqK4KBk2YZHTCWWCM6BnaL0w,57 +django/forms/templates/django/forms/widgets/radio_option.html,sha256=U2dFtAXvOn_eK4ok0oO6BwKE-3-jozJboGah_PQFLVM,55 +django/forms/templates/django/forms/widgets/select.html,sha256=7U0RzjeESG87ENzQjPRUF71gvKvGjVVvXcpsW2-BTR4,384 +django/forms/templates/django/forms/widgets/select_date.html,sha256=AzaPLlNLg91qkVQwwtAJxwOqDemrtt_btSkWLpboJDs,54 +django/forms/templates/django/forms/widgets/select_option.html,sha256=N_psd0JYCqNhx2eh2oyvkF2KU2dv7M9mtMw_4BLYq8A,127 +django/forms/templates/django/forms/widgets/splitdatetime.html,sha256=AzaPLlNLg91qkVQwwtAJxwOqDemrtt_btSkWLpboJDs,54 +django/forms/templates/django/forms/widgets/splithiddendatetime.html,sha256=AzaPLlNLg91qkVQwwtAJxwOqDemrtt_btSkWLpboJDs,54 +django/forms/templates/django/forms/widgets/text.html,sha256=fXpbxMzAdbv_avfWC5464gD2jFng931Eq7vzbzy1-yA,48 +django/forms/templates/django/forms/widgets/textarea.html,sha256=Av1Y-hpXUU2AjrhnUivgZFKNBLdwCSZSeuSmCqmCkDA,145 +django/forms/templates/django/forms/widgets/time.html,sha256=fXpbxMzAdbv_avfWC5464gD2jFng931Eq7vzbzy1-yA,48 +django/forms/templates/django/forms/widgets/url.html,sha256=fXpbxMzAdbv_avfWC5464gD2jFng931Eq7vzbzy1-yA,48 +django/forms/utils.py,sha256=Aqd1Sz6wHl7SaueN7hzE1-XqhHvy9wOCWn_TSRlqLMY,7888 +django/forms/widgets.py,sha256=A6WI_WbVorjOOEutvF1xUAZJNRWYOskZgsWBUMxHgg4,39366 +django/http/__init__.py,sha256=uVUz0ov-emc29hbD78QKKka_R1L4mpDDPhkyfkx4jzQ,1200 +django/http/cookie.py,sha256=t7yGORGClUnCYVKQqyLBlEYsxQLLHn9crsMSWqK_Eic,679 +django/http/multipartparser.py,sha256=VZM9Pu2NnPjhhftgdwIwxE1kLlRc-cr1eun3JiXCZOM,27333 +django/http/request.py,sha256=dTHzYhWT37ySRjqPfqxbLBzE3Ws1Y0tSUryZx64EwXY,25710 +django/http/response.py,sha256=62Xj0NhLfYR_V_UHuLEddNKif-O55RHgZhan5D1TSxo,25348 +django/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/middleware/cache.py,sha256=WAfMAUktNAqHGkTwC8iB0HVcZwQTdXBCLWFng4ERGgM,7951 +django/middleware/clickjacking.py,sha256=rIm2VlbblLWrMTRYJ1JBIui5xshAM-2mpyJf989xOgY,1724 +django/middleware/common.py,sha256=lahRODOz_Gkk_a_toXGJe3iFZ9n0wk_dOqULkMivNyA,7648 +django/middleware/csrf.py,sha256=Gtn6AGkmiOFJCWCkpoNzxKOGcOFFBO5yNtfOiLkvXRw,19488 +django/middleware/gzip.py,sha256=jsJeYv0-A4iD6-1Pd3Hehl2ZtshpE4WeBTei-4PwciA,2945 +django/middleware/http.py,sha256=RqXN9Kp6GEh8j_ub7YXRi6W2_CKZTZEyAPpFUzeNPBs,1616 +django/middleware/locale.py,sha256=CV8aerSUWmO6cJQ6IrD5BzT3YlOxYNIqFraCqr8DoY4,3442 +django/middleware/security.py,sha256=yqawglqNcPrITIUvQhSpn3BD899It4fhyOyJCTImlXE,2599 +django/shortcuts.py,sha256=5I9UIbHkM8M6FGCJuih3gFj4ZLiRXl5PM3vd-ev9ppc,6292 +django/template/__init__.py,sha256=-hvAhcRO8ydLdjTJJFr6LYoBVCsJq561ebRqE9kYBJs,1845 +django/template/autoreload.py,sha256=hBanYQNDNEdgpty89I2mP_bxD-MyaeXWRmgX3K6a8Zg,2063 +django/template/backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/template/backends/base.py,sha256=9jHA5fnVWXoUCQyMnNg7csGhXPEXvoBh4I9tzFw8TX8,2751 +django/template/backends/django.py,sha256=j1l9froG5n3O_De8ByfmkaNFkeGnpGYZe_kHhr6C4wI,4408 +django/template/backends/dummy.py,sha256=M62stG_knf7AdVp42ZWWddkNv6g6ck_sc1nRR6Sc_xA,1751 +django/template/backends/jinja2.py,sha256=U9WBznoElT-REbITG7DnZgR7SA_Awf1gWS9vc0yrEfs,4036 +django/template/backends/utils.py,sha256=z5X_lxKa9qL4KFDVeai-FmsewU3KLgVHO8y-gHLiVts,424 +django/template/base.py,sha256=hSbIiz9K8dBtrzaeVOcVn4uxN5Q1PLMpSotEcV1xFSo,40202 +django/template/context.py,sha256=q8FYB8NyXnBGeioIefVQebM0Rp3vxuRLUDc4Qhn0rGA,9266 +django/template/context_processors.py,sha256=PMIuGUE1iljf5L8oXggIdvvFOhCLJpASdwd39BMdjBE,2480 +django/template/defaultfilters.py,sha256=NWTRpTYAAY2945PdE5gZ0Fe2mDLAB9iWOD6YVm_w9Pk,28386 +django/template/defaulttags.py,sha256=0BWUOckC90_67zJOAGD9bsuXneFDgB-jMK8kGrn1P_4,48516 +django/template/engine.py,sha256=c4ZINgREkvys2WDKNVkuZqZKG4t1Qu02tUTnLx0WA54,7733 +django/template/exceptions.py,sha256=rqG3_qZq31tUHbmtZD-MIu0StChqwaFejFFpR4u7th4,1342 +django/template/library.py,sha256=BBP9JU72wrRzIHSFHqzSfi3y9A1c70hAMuyS-Fm97B0,13331 +django/template/loader.py,sha256=PVFUUtC5WgiRVVTilhQ6NFZnvjly6sP9s7anFmMoKdo,2054 +django/template/loader_tags.py,sha256=yGu7UOutGgzM_60RmNQhFL5Ctuho6_IuIM1sIzENgrc,13119 +django/template/loaders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/template/loaders/app_directories.py,sha256=sQpVXKYpnKr9Rl1YStNca-bGIQHcOkSnmm1l2qRGFVE,312 +django/template/loaders/base.py,sha256=Y5V4g0ly9GuNe7BQxaJSMENJnvxzXJm7XhSTxzfFM0s,1636 +django/template/loaders/cached.py,sha256=bDwkWYPgbvprU_u9f9w9oNYpSW_j9b7so_mlKzp9-N4,3716 +django/template/loaders/filesystem.py,sha256=f4silD7WWhv3K9QySMgW7dlGGNwwYAcHCMSTFpwiiXY,1506 +django/template/loaders/locmem.py,sha256=t9p0GYF2VHf4XG6Gggp0KBmHkdIuSKuLdiVXMVb2iHs,672 +django/template/response.py,sha256=UAU-aM7mn6cbGOIJuurn4EE5ITdcAqSFgKD5RXFms4w,5584 +django/template/smartif.py,sha256=eTzcnzPBdbkoiP8j9q_sa_47SoLLMqYdLKC3z0TbjpA,6407 +django/template/utils.py,sha256=c9cJRfmBXs-41xa8KkZiLkeqUAbd-8elKc_7WdnI3G0,3626 +django/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/templatetags/cache.py,sha256=WaYvWUn5ZTERwjouvkm-c5L5LRLc-GpSWl19wFod_bk,3551 +django/templatetags/i18n.py,sha256=UrS-aE3XCEK_oX18kmH8gSgA10MGHMeMTLOAESDtufI,19961 +django/templatetags/l10n.py,sha256=GB5_u3ymAtzxUtAY8QLb_pcZrzie9ZxEca-1NuKIXBY,1563 +django/templatetags/static.py,sha256=W4Rqt3DN_YtXe6EoqO-GLy7WR7xd7z0JsoX-VT0vvjc,4730 +django/templatetags/tz.py,sha256=0uSwEcqywsn1FrdOtyIjSsSCCEqzW0CDVebP-tzIBiY,5357 +django/test/__init__.py,sha256=X12C98lKN5JW1-wms7B6OaMTo-Li90waQpjfJE1V3AE,834 +django/test/client.py,sha256=sHj1xE_R_OmqJB2q3bjHjs0wp_cT1LX1pxSZfooEqZk,51174 +django/test/html.py,sha256=qFBZbYCePx_gtbeBBjEYV-veCljE2fDcw0g7LgjzpJI,8868 +django/test/runner.py,sha256=Pw6HgBJufgUhMJcrjQeEsullQJcZmWI0vnaS9Uk1C8Q,42063 +django/test/selenium.py,sha256=KImhtAeve1uOIr3qBtGKEci70K7ifYJspItcwOSBJks,5234 +django/test/signals.py,sha256=SmayvfTL-iGFOnDIMdouEyY4CIUmBJDHk7U_o2-AlJ0,8099 +django/test/testcases.py,sha256=0yObh2N-KSHHMStmodPXSSwQcu56SSQY6NMVtFo3DIs,63509 +django/test/utils.py,sha256=Z3K5vlDRbFe3OVjPfmVb6GJM0TQ1iFspmuJP1snKQAc,31934 +django/urls/__init__.py,sha256=BHyBIOD3E4_3Ng27SpXnRmqO3IzUqvBLCE4TTfs4wNs,1079 +django/urls/base.py,sha256=MDgpJtKVu7wKbWhzuo9SJUOyvIi3ndef0b_htzawIPU,5691 +django/urls/conf.py,sha256=uP_G78p31DejLa638fnOysaYwxWJETK5FDpJ6T9klj4,3425 +django/urls/converters.py,sha256=s2JZVOdzZC16lgobsI93hygcdH5L0Kj4742WEkXsVcs,1193 +django/urls/exceptions.py,sha256=alLNjkORtAxneC00g4qnRpG5wouOHvJvGbymdpKtG_I,115 +django/urls/resolvers.py,sha256=jeSPS6otRmPwOT-Qtan3Mt0HNvM9fYquRtOc3_tMCuo,32532 +django/urls/utils.py,sha256=d1KSc6JVR-5Z8axg_yDgYKtkqObdbJwWNkhcB8x44Rs,2179 +django/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/utils/_os.py,sha256=Q0d96RWFaQr6YqG00GulGqQ9M2Oni5WIjf_y4JnEWn8,2323 +django/utils/archive.py,sha256=JExZfmiqSixQ_ujY7UM6sNShVpO5CsF-0hH2qyt44Eo,8086 +django/utils/asyncio.py,sha256=0glOg3eGmms-gUv04ZgDvZt19IZbdPBC64PnaKqeGDc,1138 +django/utils/autoreload.py,sha256=pvoogz4H-ZkENLc4nExLhQOU17GWxLls10sxk2bjumc,24441 +django/utils/cache.py,sha256=qitMvkupBbJ1pgjQFScUPmK8CwwGMGKGd3KbQsWTQVE,16582 +django/utils/choices.py,sha256=kSYtbZZit2Rdtl7PECG9f8Jrhkbn-DfBqZajUg8xPUg,4147 +django/utils/connection.py,sha256=2kqA6M_EObbZg6QKMXhX6p4YXG9RiPTUHwwN3mumhDY,2554 +django/utils/crypto.py,sha256=29fvZcWMlx7WwmIAwjf0NB1LaOpUbQQ1BzN-86AEHvk,2661 +django/utils/datastructures.py,sha256=mEt2-kg3zOQ24fW7ltxZDFaatZZyTSeJP9WAGWOg6UM,10267 +django/utils/dateformat.py,sha256=1C1axqfID4PjkSGr9QLmtei4XkEVfIesKdISUNWqUhw,10117 +django/utils/dateparse.py,sha256=oWTWbJax4NP1uY7tCGPSgnyAkoGxnXf1snEh-kfCkiQ,5356 +django/utils/dates.py,sha256=zHUHeOkxuo53rTvHG3dWMLRfVyfaMLBIt5xmA4E_Ids,2179 +django/utils/deconstruct.py,sha256=RaeX2YTce1I9XJsQ0_FqYTcudPM5xu_--M1tAZm7LOA,2078 +django/utils/decorators.py,sha256=p3NKImxC6MdbH2IVElMGu9OUdi3jRKt3d6_RXaeFm2M,8227 +django/utils/deprecation.py,sha256=8dlcL9XCPqWAVX1-7TeW8SoJmETAmmikjTiuh8ol_MY,5229 +django/utils/duration.py,sha256=HK5E36F1GGdPchCqHsmloYhrHX_ByyITvOHyuxtElSE,1230 +django/utils/encoding.py,sha256=X9yrBdWzF2UkEfb7f03AksJlNa8PlB2C0YVfGzwn3Ks,8872 +django/utils/feedgenerator.py,sha256=ORkZCUa8aazivb_qW8XhtKpRtM36BmMtyK6Eqp_uqqc,15635 +django/utils/formats.py,sha256=FmPUj3dfL2gCH2ijcWtcesYKbsi2-EbHGLGyHvGOJA0,10255 +django/utils/functional.py,sha256=URFZkoTNJmOlm_ay9872-_lEgV1ewunZS9GKSJRg-e8,14541 +django/utils/hashable.py,sha256=kFbHnVOA4g-rTFI_1oHeNGA0ZEzAlY0vOeGTAeqxz7E,740 +django/utils/html.py,sha256=CTKIO03q5Zakmo2v00W1bfT08iKBMCVllchkPXETOeM,14909 +django/utils/http.py,sha256=D4LhyD5fIJyQRr5_5-_hPmh4mmLR7rNMz_o5SUIsiCQ,12785 +django/utils/inspect.py,sha256=lhDEOtmSLEub5Jj__MIgW3AyWOEVkaA6doJKKwBhZ6A,2235 +django/utils/ipv6.py,sha256=laDOQe_r4W-oVKLOgQ4aAJxs37n8P3LkH-eeIchJqh4,1333 +django/utils/itercompat.py,sha256=lacIDjczhxbwG4ON_KfG1H6VNPOGOpbRhnVhbedo2CY,184 +django/utils/jslex.py,sha256=cha8xFT5cQ0OMhKMsdsIq1THDndmKUNYNNieQ8BNa9E,8048 +django/utils/log.py,sha256=qkGXBz4zCVkfOUy-3ciMNOAf53Z94LyAeYxlyD3ykE8,7952 +django/utils/lorem_ipsum.py,sha256=yUtBgKhshftIpPg04pc1IrLpOBydZIf7g0isFCIJZqk,5473 +django/utils/module_loading.py,sha256=-a7qOb5rpp-Lw_51vyIPSdb7R40B16Er1Zc1C_a6ibY,3820 +django/utils/numberformat.py,sha256=8LqSMmfxaN0PYSTTES6UT_ATerfDYQn7Ya4NI70gMaU,3781 +django/utils/regex_helper.py,sha256=gv0YfkofciCI4iptv_6GEwyLyVZg1_HFaNRwn3DuH4c,12771 +django/utils/safestring.py,sha256=-dKgvOyuADWC8mo0F5HH-OadkS87xF4OHzdB3_fpLUc,1876 +django/utils/termcolors.py,sha256=vvQbUH7GsFofGRSiKQwx4YvgE4yZMtAGRVz9QPDfisA,7386 +django/utils/text.py,sha256=pILfwGfn8A7HNxwo0_l6OvLcM_mEpO1CBTdc_kZKn4M,14690 +django/utils/timesince.py,sha256=j9B_wSnsdS3ZXn9pt9GImOJDpgO61YMr_jtnUpZDx0g,4914 +django/utils/timezone.py,sha256=Wg4eIhEHAsOMEKlzfSS_aYPf-h70DYqOqnmRDG1TbbE,7295 +django/utils/translation/__init__.py,sha256=MKFOm2b3sG8xLrR-wQFVt-RqFawI8lm8cDi14jX4OAc,8877 +django/utils/translation/reloader.py,sha256=oVM0xenn3fraUomMEFucvwlbr5UGYUijWnUn6FL55Zc,1114 +django/utils/translation/template.py,sha256=TOfPNT62RnUbUG64a_6d_VQ7tsDC1_F1TCopw_HwlcA,10549 +django/utils/translation/trans_null.py,sha256=niy_g1nztS2bPsINqK7_g0HcpI_w6hL-c8_hqpC7U7s,1287 +django/utils/translation/trans_real.py,sha256=AYamjmxjIyFJRB-LFJPhMTVmXyDfUsoZo9LsFhj8Bik,21758 +django/utils/tree.py,sha256=v8sNUsnsG2Loi9xBIIk0GmV5yN7VWOGTzbmk8BOEs6E,4394 +django/utils/version.py,sha256=M74iPaM0nPG2lboE6ftHS491jsK622bW56LuQY1eigA,3628 +django/utils/xmlutils.py,sha256=LsggeI4vhln3An_YXNBk2cCwKLQgMe-O_3L--j3o3GM,1172 +django/views/__init__.py,sha256=GIq6CKUBCbGpQVyK4xIoaAUDPrmRvbBPSX_KSHk0Bb4,63 +django/views/csrf.py,sha256=LxWJ02CxEG-e6FnKESo4o-799KoGvpotnXrds6cnwM0,3378 +django/views/debug.py,sha256=3yDwwZPSIv3D1FvSQ3r2bbZfNiPtfZt5rvf2S-JyN1w,25660 +django/views/decorators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +django/views/decorators/cache.py,sha256=4cWEWW88qPv57St9Wwmv0aK0vVxD-7aevFOQc8z4pQs,2821 +django/views/decorators/clickjacking.py,sha256=3w8djeDoQUK67uDfIzi9jdlds_ZdekwDMIV2IM8NBWk,2555 +django/views/decorators/common.py,sha256=Kcj1Q-aPTBLGMW_kkeUleRiYiEZCg7uoP_UexklyyQA,739 +django/views/decorators/csrf.py,sha256=q9lXnlNkbm7Hlg4FRx1pesf64sNpCIC52mCqY7xduZo,2324 +django/views/decorators/debug.py,sha256=1Ab84aEh6BTq_JSXhcUtu7E4VWkBFUTJrsjyHEDB_Bc,5121 +django/views/decorators/gzip.py,sha256=PtpSGd8BePa1utGqvKMFzpLtZJxpV2_Jej8llw5bCJY,253 +django/views/decorators/http.py,sha256=I2mBHevDyoFlV-12YGy8lyE90csKGpxbJHEYU4Y8T3M,6532 +django/views/decorators/vary.py,sha256=DGR1eA8mSaXM8kgMJta4XnzCznJIrW1_KDMrd4aqCTM,1201 +django/views/defaults.py,sha256=D5Pqjk0GZKXsRaA1NKouNeMEyWGoD_Tdp47U5LMKfKI,4683 +django/views/generic/__init__.py,sha256=VwQKUbBFJktiq5J2fo3qRNzRc0STfcMRPChlLPYAkkE,886 +django/views/generic/base.py,sha256=p5HbLA01-FQSqC3hSGIg7jQk23khBMn9ssg4d9GHui4,9275 +django/views/generic/dates.py,sha256=xwSEF6zsaSl1jUTePs6NPihnOJEWT-j8SST0RG4bco0,26332 +django/views/generic/detail.py,sha256=zrAuhJxrFvNqJLnlvK-NSiRiiONsKKOYFantD7UztwU,6663 +django/views/generic/edit.py,sha256=lQ9msLa7PVw3mp4Ivup5vPjb7Vo_9G_paX34R7xhD-8,9091 +django/views/generic/list.py,sha256=KWsT5UOK5jflxn5JFoJCnyJEQXa0fM4talHswzEjzXU,7941 +django/views/i18n.py,sha256=EVTwiUOVetsRqzxs3HSwiuC7Wa_e-CYBDq26m_Nexk8,9020 +django/views/static.py,sha256=ES-LAp4XYkCPPPaYRGvp7Yb7baOVmQSPuFJABoWG8FU,4054 +django/views/templates/csrf_403.html,sha256=Zz-WtFHcSbKftrCQklpMN0qgYwxgIn0WIDmz9IMiBHo,2855 +django/views/templates/default_urlconf.html,sha256=ljDRut90TjubDciay8zfvGNySWV8rs7wgAQduia7TsU,11082 +django/views/templates/directory_index.html,sha256=0CGI4FUy9n_Yo2e7U2vWeKCLsUgizBmoqHseNQxxe04,653 +django/views/templates/i18n_catalog.js,sha256=WTPJxawKwdORo12g9I_mUn4YSU6Xx-DCx6E06yKBKZQ,2785 +django/views/templates/technical_404.html,sha256=dJEOimEguJg6g4IhdRPG5HmdMy8D30U-lNI8wC8wwQs,2706 +django/views/templates/technical_500.html,sha256=x2Nr8PAHZfb3bVFhOxz3uSoqz_piWBVB_NCbNC87NAs,17662 +django/views/templates/technical_500.txt,sha256=b0ihE_FS7YtfAFOXU_yk0-CTgUmZ4ZkWVfkFHdEQXQI,3712 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/REQUESTED b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/WHEEL b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/WHEEL new file mode 100644 index 0000000..7e68873 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.41.2) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/entry_points.txt b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/entry_points.txt new file mode 100644 index 0000000..eaeb88e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[console_scripts] +django-admin = django.core.management:execute_from_command_line diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/top_level.txt b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/top_level.txt new file mode 100644 index 0000000..d3e4ba5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/Django-5.0.dist-info/top_level.txt @@ -0,0 +1 @@ +django diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref-3.11.1.dist-info/INSTALLER b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref-3.11.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref-3.11.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref-3.11.1.dist-info/METADATA b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref-3.11.1.dist-info/METADATA new file mode 100644 index 0000000..aa26d05 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref-3.11.1.dist-info/METADATA @@ -0,0 +1,247 @@ +Metadata-Version: 2.4 +Name: asgiref +Version: 3.11.1 +Summary: ASGI specs, helper code, and adapters +Home-page: https://github.com/django/asgiref/ +Author: Django Software Foundation +Author-email: foundation@djangoproject.com +License: BSD-3-Clause +Project-URL: Documentation, https://asgi.readthedocs.io/ +Project-URL: Further Documentation, https://docs.djangoproject.com/en/stable/topics/async/#async-adapter-functions +Project-URL: Changelog, https://github.com/django/asgiref/blob/master/CHANGELOG.txt +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 +Classifier: Topic :: Internet :: WWW/HTTP +Requires-Python: >=3.9 +License-File: LICENSE +Requires-Dist: typing_extensions>=4; python_version < "3.11" +Provides-Extra: tests +Requires-Dist: pytest; extra == "tests" +Requires-Dist: pytest-asyncio; extra == "tests" +Requires-Dist: mypy>=1.14.0; extra == "tests" +Dynamic: license-file + +asgiref +======= + +.. image:: https://github.com/django/asgiref/actions/workflows/tests.yml/badge.svg + :target: https://github.com/django/asgiref/actions/workflows/tests.yml + +.. image:: https://img.shields.io/pypi/v/asgiref.svg + :target: https://pypi.python.org/pypi/asgiref + +ASGI is a standard for Python asynchronous web apps and servers to communicate +with each other, and positioned as an asynchronous successor to WSGI. You can +read more at https://asgi.readthedocs.io/en/latest/ + +This package includes ASGI base libraries, such as: + +* Sync-to-async and async-to-sync function wrappers, ``asgiref.sync`` +* Server base classes, ``asgiref.server`` +* A WSGI-to-ASGI adapter, in ``asgiref.wsgi`` + + +Function wrappers +----------------- + +These allow you to wrap or decorate async or sync functions to call them from +the other style (so you can call async functions from a synchronous thread, +or vice-versa). + +In particular: + +* AsyncToSync lets a synchronous subthread stop and wait while the async + function is called on the main thread's event loop, and then control is + returned to the thread when the async function is finished. + +* SyncToAsync lets async code call a synchronous function, which is run in + a threadpool and control returned to the async coroutine when the synchronous + function completes. + +The idea is to make it easier to call synchronous APIs from async code and +asynchronous APIs from synchronous code so it's easier to transition code from +one style to the other. In the case of Channels, we wrap the (synchronous) +Django view system with SyncToAsync to allow it to run inside the (asynchronous) +ASGI server. + +Note that exactly what threads things run in is very specific, and aimed to +keep maximum compatibility with old synchronous code. See +"Synchronous code & Threads" below for a full explanation. By default, +``sync_to_async`` will run all synchronous code in the program in the same +thread for safety reasons; you can disable this for more performance with +``@sync_to_async(thread_sensitive=False)``, but make sure that your code does +not rely on anything bound to threads (like database connections) when you do. + + +Threadlocal replacement +----------------------- + +This is a drop-in replacement for ``threading.local`` that works with both +threads and asyncio Tasks. Even better, it will proxy values through from a +task-local context to a thread-local context when you use ``sync_to_async`` +to run things in a threadpool, and vice-versa for ``async_to_sync``. + +If you instead want true thread- and task-safety, you can set +``thread_critical`` on the Local object to ensure this instead. + + +Server base classes +------------------- + +Includes a ``StatelessServer`` class which provides all the hard work of +writing a stateless server (as in, does not handle direct incoming sockets +but instead consumes external streams or sockets to work out what is happening). + +An example of such a server would be a chatbot server that connects out to +a central chat server and provides a "connection scope" per user chatting to +it. There's only one actual connection, but the server has to separate things +into several scopes for easier writing of the code. + +You can see an example of this being used in `frequensgi `_. + + +WSGI-to-ASGI adapter +-------------------- + +Allows you to wrap a WSGI application so it appears as a valid ASGI application. + +Simply wrap it around your WSGI application like so:: + + asgi_application = WsgiToAsgi(wsgi_application) + +The WSGI application will be run in a synchronous threadpool, and the wrapped +ASGI application will be one that accepts ``http`` class messages. + +Please note that not all extended features of WSGI may be supported (such as +file handles for incoming POST bodies). + + +Dependencies +------------ + +``asgiref`` requires Python 3.9 or higher. + + +Contributing +------------ + +Please refer to the +`main Channels contributing docs `_. + + +Testing +''''''' + +To run tests, make sure you have installed the ``tests`` extra with the package:: + + cd asgiref/ + pip install -e .[tests] + pytest + + +Building the documentation +'''''''''''''''''''''''''' + +The documentation uses `Sphinx `_:: + + cd asgiref/docs/ + pip install sphinx + +To build the docs, you can use the default tools:: + + sphinx-build -b html . _build/html # or `make html`, if you've got make set up + cd _build/html + python -m http.server + +...or you can use ``sphinx-autobuild`` to run a server and rebuild/reload +your documentation changes automatically:: + + pip install sphinx-autobuild + sphinx-autobuild . _build/html + + +Releasing +''''''''' + +To release, first add details to CHANGELOG.txt and update the version number in ``asgiref/__init__.py``. + +Then, build and push the packages:: + + python -m build + twine upload dist/* + rm -r asgiref.egg-info dist + + +Implementation Details +---------------------- + +Synchronous code & threads +'''''''''''''''''''''''''' + +The ``asgiref.sync`` module provides two wrappers that let you go between +asynchronous and synchronous code at will, while taking care of the rough edges +for you. + +Unfortunately, the rough edges are numerous, and the code has to work especially +hard to keep things in the same thread as much as possible. Notably, the +restrictions we are working with are: + +* All synchronous code called through ``SyncToAsync`` and marked with + ``thread_sensitive`` should run in the same thread as each other (and if the + outer layer of the program is synchronous, the main thread) + +* If a thread already has a running async loop, ``AsyncToSync`` can't run things + on that loop if it's blocked on synchronous code that is above you in the + call stack. + +The first compromise you get to might be that ``thread_sensitive`` code should +just run in the same thread and not spawn in a sub-thread, fulfilling the first +restriction, but that immediately runs you into the second restriction. + +The only real solution is to essentially have a variant of ThreadPoolExecutor +that executes any ``thread_sensitive`` code on the outermost synchronous +thread - either the main thread, or a single spawned subthread. + +This means you now have two basic states: + +* If the outermost layer of your program is synchronous, then all async code + run through ``AsyncToSync`` will run in a per-call event loop in arbitrary + sub-threads, while all ``thread_sensitive`` code will run in the main thread. + +* If the outermost layer of your program is asynchronous, then all async code + runs on the main thread's event loop, and all ``thread_sensitive`` synchronous + code will run in a single shared sub-thread. + +Crucially, this means that in both cases there is a thread which is a shared +resource that all ``thread_sensitive`` code must run on, and there is a chance +that this thread is currently blocked on its own ``AsyncToSync`` call. Thus, +``AsyncToSync`` needs to act as an executor for thread code while it's blocking. + +The ``CurrentThreadExecutor`` class provides this functionality; rather than +simply waiting on a Future, you can call its ``run_until_future`` method and +it will run submitted code until that Future is done. This means that code +inside the call can then run code on your thread. + + +Maintenance and Security +------------------------ + +To report security issues, please contact security@djangoproject.com. For GPG +signatures and more security process information, see +https://docs.djangoproject.com/en/dev/internals/security/. + +To report bugs or request new features, please open a new GitHub issue. + +This repository is part of the Channels project. For the shepherd and maintenance team, please see the +`main Channels readme `_. diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref-3.11.1.dist-info/RECORD b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref-3.11.1.dist-info/RECORD new file mode 100644 index 0000000..ff28e4c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref-3.11.1.dist-info/RECORD @@ -0,0 +1,17 @@ +asgiref-3.11.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +asgiref-3.11.1.dist-info/METADATA,sha256=aLePcJP6N7HpneCbacTmO_4Gc4b0PRSo2fWPwsWLeYQ,9287 +asgiref-3.11.1.dist-info/RECORD,, +asgiref-3.11.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92 +asgiref-3.11.1.dist-info/licenses/LICENSE,sha256=uEZBXRtRTpwd_xSiLeuQbXlLxUbKYSn5UKGM0JHipmk,1552 +asgiref-3.11.1.dist-info/top_level.txt,sha256=bokQjCzwwERhdBiPdvYEZa4cHxT4NCeAffQNUqJ8ssg,8 +asgiref/__init__.py,sha256=UuKR3QjWk9sJtn2huDFsPdSgtx1CgiEl2B4BUtVRd58,23 +asgiref/compatibility.py,sha256=DhY1SOpOvOw0Y1lSEjCqg-znRUQKecG3LTaV48MZi68,1606 +asgiref/current_thread_executor.py,sha256=42CU1VODLTk-_PYise-cP1XgyAvI5Djc8f97owFzdrs,4157 +asgiref/local.py,sha256=ZZeWWIXptVU4GbNApMMWQ-skuglvodcQA5WpzJDMxh4,4912 +asgiref/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +asgiref/server.py,sha256=3A68169Nuh2sTY_2O5JzRd_opKObWvvrEFcrXssq3kA,6311 +asgiref/sync.py,sha256=KHjSkYRZKIJ1cmBvxcloGrcnhvAuEfXCWCZAoxN8grg,22929 +asgiref/testing.py,sha256=U5wcs_-ZYTO5SIGfl80EqRAGv_T8BHrAhvAKRuuztT4,4421 +asgiref/timeout.py,sha256=LtGL-xQpG8JHprdsEUCMErJ0kNWj4qwWZhEHJ3iKu4s,3627 +asgiref/typing.py,sha256=Zi72AZlOyF1C7N14LLZnpAdfUH4ljoBqFdQo_bBKMq0,6290 +asgiref/wsgi.py,sha256=OSxanm5Qf-VfrOkAx62mYW0mOnh8pwaTz1099HbJzM0,7941 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref-3.11.1.dist-info/WHEEL b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref-3.11.1.dist-info/WHEEL new file mode 100644 index 0000000..0885d05 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref-3.11.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: setuptools (80.10.2) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref-3.11.1.dist-info/licenses/LICENSE b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref-3.11.1.dist-info/licenses/LICENSE new file mode 100644 index 0000000..5f4f225 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref-3.11.1.dist-info/licenses/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) Django Software Foundation and individual contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of Django nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref-3.11.1.dist-info/top_level.txt b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref-3.11.1.dist-info/top_level.txt new file mode 100644 index 0000000..ddf99d3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref-3.11.1.dist-info/top_level.txt @@ -0,0 +1 @@ +asgiref diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/__init__.py new file mode 100644 index 0000000..595a2b3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/__init__.py @@ -0,0 +1 @@ +__version__ = "3.11.1" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/compatibility.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/compatibility.py new file mode 100644 index 0000000..3a2a63e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/compatibility.py @@ -0,0 +1,48 @@ +import inspect + +from .sync import iscoroutinefunction + + +def is_double_callable(application): + """ + Tests to see if an application is a legacy-style (double-callable) application. + """ + # Look for a hint on the object first + if getattr(application, "_asgi_single_callable", False): + return False + if getattr(application, "_asgi_double_callable", False): + return True + # Uninstanted classes are double-callable + if inspect.isclass(application): + return True + # Instanted classes depend on their __call__ + if hasattr(application, "__call__"): + # We only check to see if its __call__ is a coroutine function - + # if it's not, it still might be a coroutine function itself. + if iscoroutinefunction(application.__call__): + return False + # Non-classes we just check directly + return not iscoroutinefunction(application) + + +def double_to_single_callable(application): + """ + Transforms a double-callable ASGI application into a single-callable one. + """ + + async def new_application(scope, receive, send): + instance = application(scope) + return await instance(receive, send) + + return new_application + + +def guarantee_single_callable(application): + """ + Takes either a single- or double-callable application and always returns it + in single-callable style. Use this to add backwards compatibility for ASGI + 2.0 applications to your server/test harness/etc. + """ + if is_double_callable(application): + application = double_to_single_callable(application) + return application diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/current_thread_executor.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/current_thread_executor.py new file mode 100644 index 0000000..6293cbd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/current_thread_executor.py @@ -0,0 +1,123 @@ +import sys +import threading +from collections import deque +from concurrent.futures import Executor, Future +from typing import Any, Callable, TypeVar + +if sys.version_info >= (3, 10): + from typing import ParamSpec +else: + from typing_extensions import ParamSpec + +_T = TypeVar("_T") +_P = ParamSpec("_P") +_R = TypeVar("_R") + + +class _WorkItem: + """ + Represents an item needing to be run in the executor. + Copied from ThreadPoolExecutor (but it's private, so we're not going to rely on importing it) + """ + + def __init__( + self, + future: "Future[_R]", + fn: Callable[_P, _R], + *args: _P.args, + **kwargs: _P.kwargs, + ): + self.future = future + self.fn = fn + self.args = args + self.kwargs = kwargs + + def run(self) -> None: + __traceback_hide__ = True # noqa: F841 + if not self.future.set_running_or_notify_cancel(): + return + try: + result = self.fn(*self.args, **self.kwargs) + except BaseException as exc: + self.future.set_exception(exc) + # Break a reference cycle with the exception 'exc' + self = None # type: ignore[assignment] + else: + self.future.set_result(result) + + +class CurrentThreadExecutor(Executor): + """ + An Executor that actually runs code in the thread it is instantiated in. + Passed to other threads running async code, so they can run sync code in + the thread they came from. + """ + + def __init__(self, old_executor: "CurrentThreadExecutor | None") -> None: + self._work_thread = threading.current_thread() + self._work_ready = threading.Condition(threading.Lock()) + self._work_items = deque[_WorkItem]() # synchronized by _work_ready + self._broken = False # synchronized by _work_ready + self._old_executor = old_executor + + def run_until_future(self, future: "Future[Any]") -> None: + """ + Runs the code in the work queue until a result is available from the future. + Should be run from the thread the executor is initialised in. + """ + # Check we're in the right thread + if threading.current_thread() != self._work_thread: + raise RuntimeError( + "You cannot run CurrentThreadExecutor from a different thread" + ) + + def done(future: "Future[Any]") -> None: + with self._work_ready: + self._broken = True + self._work_ready.notify() + + future.add_done_callback(done) + # Keep getting and running work items until the future we're waiting for + # is done and the queue is empty. + while True: + with self._work_ready: + while not self._work_items and not self._broken: + self._work_ready.wait() + if not self._work_items: + break + # Get a work item and run it + work_item = self._work_items.popleft() + work_item.run() + del work_item + + def submit( + self, + fn: Callable[_P, _R], + /, + *args: _P.args, + **kwargs: _P.kwargs, + ) -> "Future[_R]": + # Check they're not submitting from the same thread + if threading.current_thread() == self._work_thread: + raise RuntimeError( + "You cannot submit onto CurrentThreadExecutor from its own thread" + ) + f: "Future[_R]" = Future() + work_item = _WorkItem(f, fn, *args, **kwargs) + + # Walk up the CurrentThreadExecutor stack to find the closest one still + # running + executor = self + while True: + with executor._work_ready: + if not executor._broken: + # Add to work queue + executor._work_items.append(work_item) + executor._work_ready.notify() + break + if executor._old_executor is None: + raise RuntimeError("CurrentThreadExecutor already quit or is broken") + executor = executor._old_executor + + # Return the future + return f diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/local.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/local.py new file mode 100644 index 0000000..845313a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/local.py @@ -0,0 +1,131 @@ +import asyncio +import contextlib +import contextvars +import threading +from typing import Any, Dict, Union + + +class _CVar: + """Storage utility for Local.""" + + def __init__(self) -> None: + self._data: "contextvars.ContextVar[Dict[str, Any]]" = contextvars.ContextVar( + "asgiref.local" + ) + + def __getattr__(self, key): + storage_object = self._data.get({}) + try: + return storage_object[key] + except KeyError: + raise AttributeError(f"{self!r} object has no attribute {key!r}") + + def __setattr__(self, key: str, value: Any) -> None: + if key == "_data": + return super().__setattr__(key, value) + + storage_object = self._data.get({}).copy() + storage_object[key] = value + self._data.set(storage_object) + + def __delattr__(self, key: str) -> None: + storage_object = self._data.get({}).copy() + if key in storage_object: + del storage_object[key] + self._data.set(storage_object) + else: + raise AttributeError(f"{self!r} object has no attribute {key!r}") + + +class Local: + """Local storage for async tasks. + + This is a namespace object (similar to `threading.local`) where data is + also local to the current async task (if there is one). + + In async threads, local means in the same sense as the `contextvars` + module - i.e. a value set in an async frame will be visible: + + - to other async code `await`-ed from this frame. + - to tasks spawned using `asyncio` utilities (`create_task`, `wait_for`, + `gather` and probably others). + - to code scheduled in a sync thread using `sync_to_async` + + In "sync" threads (a thread with no async event loop running), the + data is thread-local, but additionally shared with async code executed + via the `async_to_sync` utility, which schedules async code in a new thread + and copies context across to that thread. + + If `thread_critical` is True, then the local will only be visible per-thread, + behaving exactly like `threading.local` if the thread is sync, and as + `contextvars` if the thread is async. This allows genuinely thread-sensitive + code (such as DB handles) to be kept stricly to their initial thread and + disable the sharing across `sync_to_async` and `async_to_sync` wrapped calls. + + Unlike plain `contextvars` objects, this utility is threadsafe. + """ + + def __init__(self, thread_critical: bool = False) -> None: + self._thread_critical = thread_critical + self._thread_lock = threading.RLock() + + self._storage: "Union[threading.local, _CVar]" + + if thread_critical: + # Thread-local storage + self._storage = threading.local() + else: + # Contextvar storage + self._storage = _CVar() + + @contextlib.contextmanager + def _lock_storage(self): + # Thread safe access to storage + if self._thread_critical: + is_async = True + try: + # this is a test for are we in a async or sync + # thread - will raise RuntimeError if there is + # no current loop + asyncio.get_running_loop() + except RuntimeError: + is_async = False + if not is_async: + # We are in a sync thread, the storage is + # just the plain thread local (i.e, "global within + # this thread" - it doesn't matter where you are + # in a call stack you see the same storage) + yield self._storage + else: + # We are in an async thread - storage is still + # local to this thread, but additionally should + # behave like a context var (is only visible with + # the same async call stack) + + # Ensure context exists in the current thread + if not hasattr(self._storage, "cvar"): + self._storage.cvar = _CVar() + + # self._storage is a thread local, so the members + # can't be accessed in another thread (we don't + # need any locks) + yield self._storage.cvar + else: + # Lock for thread_critical=False as other threads + # can access the exact same storage object + with self._thread_lock: + yield self._storage + + def __getattr__(self, key): + with self._lock_storage() as storage: + return getattr(storage, key) + + def __setattr__(self, key, value): + if key in ("_local", "_storage", "_thread_critical", "_thread_lock"): + return super().__setattr__(key, value) + with self._lock_storage() as storage: + setattr(storage, key, value) + + def __delattr__(self, key): + with self._lock_storage() as storage: + delattr(storage, key) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/py.typed b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/server.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/server.py new file mode 100644 index 0000000..131ea43 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/server.py @@ -0,0 +1,173 @@ +import asyncio +import logging +import time +import traceback + +from .compatibility import guarantee_single_callable + +logger = logging.getLogger(__name__) + + +class StatelessServer: + """ + Base server class that handles basic concepts like application instance + creation/pooling, exception handling, and similar, for stateless protocols + (i.e. ones without actual incoming connections to the process) + + Your code should override the handle() method, doing whatever it needs to, + and calling get_or_create_application_instance with a unique `scope_id` + and `scope` for the scope it wants to get. + + If an application instance is found with the same `scope_id`, you are + given its input queue, otherwise one is made for you with the scope provided + and you are given that fresh new input queue. Either way, you should do + something like: + + input_queue = self.get_or_create_application_instance( + "user-123456", + {"type": "testprotocol", "user_id": "123456", "username": "andrew"}, + ) + input_queue.put_nowait(message) + + If you try and create an application instance and there are already + `max_application` instances, the oldest/least recently used one will be + reclaimed and shut down to make space. + + Application coroutines that error will be found periodically (every 100ms + by default) and have their exceptions printed to the console. Override + application_exception() if you want to do more when this happens. + + If you override run(), make sure you handle things like launching the + application checker. + """ + + application_checker_interval = 0.1 + + def __init__(self, application, max_applications=1000): + # Parameters + self.application = application + self.max_applications = max_applications + # Initialisation + self.application_instances = {} + + ### Mainloop and handling + + def run(self): + """ + Runs the asyncio event loop with our handler loop. + """ + event_loop = asyncio.get_event_loop() + try: + event_loop.run_until_complete(self.arun()) + except KeyboardInterrupt: + logger.info("Exiting due to Ctrl-C/interrupt") + + async def arun(self): + """ + Runs the asyncio event loop with our handler loop. + """ + + class Done(Exception): + pass + + async def handle(): + await self.handle() + raise Done + + try: + await asyncio.gather(self.application_checker(), handle()) + except Done: + pass + + async def handle(self): + raise NotImplementedError("You must implement handle()") + + async def application_send(self, scope, message): + """ + Receives outbound sends from applications and handles them. + """ + raise NotImplementedError("You must implement application_send()") + + ### Application instance management + + def get_or_create_application_instance(self, scope_id, scope): + """ + Creates an application instance and returns its queue. + """ + if scope_id in self.application_instances: + self.application_instances[scope_id]["last_used"] = time.time() + return self.application_instances[scope_id]["input_queue"] + # See if we need to delete an old one + while len(self.application_instances) > self.max_applications: + self.delete_oldest_application_instance() + # Make an instance of the application + input_queue = asyncio.Queue() + application_instance = guarantee_single_callable(self.application) + # Run it, and stash the future for later checking + future = asyncio.ensure_future( + application_instance( + scope=scope, + receive=input_queue.get, + send=lambda message: self.application_send(scope, message), + ), + ) + self.application_instances[scope_id] = { + "input_queue": input_queue, + "future": future, + "scope": scope, + "last_used": time.time(), + } + return input_queue + + def delete_oldest_application_instance(self): + """ + Finds and deletes the oldest application instance + """ + oldest_time = min( + details["last_used"] for details in self.application_instances.values() + ) + for scope_id, details in self.application_instances.items(): + if details["last_used"] == oldest_time: + self.delete_application_instance(scope_id) + # Return to make sure we only delete one in case two have + # the same oldest time + return + + def delete_application_instance(self, scope_id): + """ + Removes an application instance (makes sure its task is stopped, + then removes it from the current set) + """ + details = self.application_instances[scope_id] + del self.application_instances[scope_id] + if not details["future"].done(): + details["future"].cancel() + + async def application_checker(self): + """ + Goes through the set of current application instance Futures and cleans up + any that are done/prints exceptions for any that errored. + """ + while True: + await asyncio.sleep(self.application_checker_interval) + for scope_id, details in list(self.application_instances.items()): + if details["future"].done(): + exception = details["future"].exception() + if exception: + await self.application_exception(exception, details) + try: + del self.application_instances[scope_id] + except KeyError: + # Exception handling might have already got here before us. That's fine. + pass + + async def application_exception(self, exception, application_details): + """ + Called whenever an application coroutine has an exception. + """ + logging.error( + "Exception inside application: %s\n%s%s", + exception, + "".join(traceback.format_tb(exception.__traceback__)), + f" {exception}", + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/sync.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/sync.py new file mode 100644 index 0000000..e733c8e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/sync.py @@ -0,0 +1,657 @@ +import asyncio +import asyncio.coroutines +import contextvars +import functools +import inspect +import os +import sys +import threading +import warnings +import weakref +from concurrent.futures import Future, ThreadPoolExecutor +from typing import ( + TYPE_CHECKING, + Any, + Awaitable, + Callable, + Coroutine, + Dict, + Generic, + List, + Optional, + TypeVar, + Union, + overload, +) + +from .current_thread_executor import CurrentThreadExecutor +from .local import Local + +if sys.version_info >= (3, 10): + from typing import ParamSpec +else: + from typing_extensions import ParamSpec + +if TYPE_CHECKING: + # This is not available to import at runtime + from _typeshed import OptExcInfo + +_F = TypeVar("_F", bound=Callable[..., Any]) +_P = ParamSpec("_P") +_R = TypeVar("_R") + + +def _restore_context(context: contextvars.Context) -> None: + # Check for changes in contextvars, and set them to the current + # context for downstream consumers + for cvar in context: + cvalue = context.get(cvar) + try: + if cvar.get() != cvalue: + cvar.set(cvalue) + except LookupError: + cvar.set(cvalue) + + +# Python 3.12 deprecates asyncio.iscoroutinefunction() as an alias for +# inspect.iscoroutinefunction(), whilst also removing the _is_coroutine marker. +# The latter is replaced with the inspect.markcoroutinefunction decorator. +# Until 3.12 is the minimum supported Python version, provide a shim. + +if hasattr(inspect, "markcoroutinefunction"): + iscoroutinefunction = inspect.iscoroutinefunction + markcoroutinefunction: Callable[[_F], _F] = inspect.markcoroutinefunction +else: + iscoroutinefunction = asyncio.iscoroutinefunction # type: ignore[assignment] + + def markcoroutinefunction(func: _F) -> _F: + func._is_coroutine = asyncio.coroutines._is_coroutine # type: ignore + return func + + +class AsyncSingleThreadContext: + """Context manager to run async code inside the same thread. + + Normally, AsyncToSync functions run either inside a separate ThreadPoolExecutor or + the main event loop if it exists. This context manager ensures that all AsyncToSync + functions execute within the same thread. + + This context manager is re-entrant, so only the outer-most call to + AsyncSingleThreadContext will set the context. + + Usage: + + >>> import asyncio + >>> with AsyncSingleThreadContext(): + ... async_to_sync(asyncio.sleep(1))() + """ + + def __init__(self): + self.token = None + + def __enter__(self): + try: + AsyncToSync.async_single_thread_context.get() + except LookupError: + self.token = AsyncToSync.async_single_thread_context.set(self) + + return self + + def __exit__(self, exc, value, tb): + if not self.token: + return + + executor = AsyncToSync.context_to_thread_executor.pop(self, None) + if executor: + executor.shutdown() + + AsyncToSync.async_single_thread_context.reset(self.token) + + +class ThreadSensitiveContext: + """Async context manager to manage context for thread sensitive mode + + This context manager controls which thread pool executor is used when in + thread sensitive mode. By default, a single thread pool executor is shared + within a process. + + The ThreadSensitiveContext() context manager may be used to specify a + thread pool per context. + + This context manager is re-entrant, so only the outer-most call to + ThreadSensitiveContext will set the context. + + Usage: + + >>> import time + >>> async with ThreadSensitiveContext(): + ... await sync_to_async(time.sleep, 1)() + """ + + def __init__(self): + self.token = None + + async def __aenter__(self): + try: + SyncToAsync.thread_sensitive_context.get() + except LookupError: + self.token = SyncToAsync.thread_sensitive_context.set(self) + + return self + + async def __aexit__(self, exc, value, tb): + if not self.token: + return + + executor = SyncToAsync.context_to_thread_executor.pop(self, None) + if executor: + executor.shutdown() + SyncToAsync.thread_sensitive_context.reset(self.token) + + +class AsyncToSync(Generic[_P, _R]): + """ + Utility class which turns an awaitable that only works on the thread with + the event loop into a synchronous callable that works in a subthread. + + If the call stack contains an async loop, the code runs there. + Otherwise, the code runs in a new loop in a new thread. + + Either way, this thread then pauses and waits to run any thread_sensitive + code called from further down the call stack using SyncToAsync, before + finally exiting once the async task returns. + """ + + # Keeps a reference to the CurrentThreadExecutor in local context, so that + # any sync_to_async inside the wrapped code can find it. + executors: "Local" = Local() + + # When we can't find a CurrentThreadExecutor from the context, such as + # inside create_task, we'll look it up here from the running event loop. + loop_thread_executors: "Dict[asyncio.AbstractEventLoop, CurrentThreadExecutor]" = {} + + async_single_thread_context: "contextvars.ContextVar[AsyncSingleThreadContext]" = ( + contextvars.ContextVar("async_single_thread_context") + ) + + context_to_thread_executor: "weakref.WeakKeyDictionary[AsyncSingleThreadContext, ThreadPoolExecutor]" = ( + weakref.WeakKeyDictionary() + ) + + def __init__( + self, + awaitable: Union[ + Callable[_P, Coroutine[Any, Any, _R]], + Callable[_P, Awaitable[_R]], + ], + force_new_loop: bool = False, + ): + if not callable(awaitable) or ( + not iscoroutinefunction(awaitable) + and not iscoroutinefunction(getattr(awaitable, "__call__", awaitable)) + ): + # Python does not have very reliable detection of async functions + # (lots of false negatives) so this is just a warning. + warnings.warn( + "async_to_sync was passed a non-async-marked callable", stacklevel=2 + ) + self.awaitable = awaitable + try: + self.__self__ = self.awaitable.__self__ # type: ignore[union-attr] + except AttributeError: + pass + self.force_new_loop = force_new_loop + self.main_event_loop = None + try: + self.main_event_loop = asyncio.get_running_loop() + except RuntimeError: + # There's no event loop in this thread. + pass + + def __call__(self, *args: _P.args, **kwargs: _P.kwargs) -> _R: + __traceback_hide__ = True # noqa: F841 + + if not self.force_new_loop and not self.main_event_loop: + # There's no event loop in this thread. Look for the threadlocal if + # we're inside SyncToAsync + main_event_loop_pid = getattr( + SyncToAsync.threadlocal, "main_event_loop_pid", None + ) + # We make sure the parent loop is from the same process - if + # they've forked, this is not going to be valid any more (#194) + if main_event_loop_pid and main_event_loop_pid == os.getpid(): + self.main_event_loop = getattr( + SyncToAsync.threadlocal, "main_event_loop", None + ) + + # You can't call AsyncToSync from a thread with a running event loop + try: + asyncio.get_running_loop() + except RuntimeError: + pass + else: + raise RuntimeError( + "You cannot use AsyncToSync in the same thread as an async event loop - " + "just await the async function directly." + ) + + # Make a future for the return information + call_result: "Future[_R]" = Future() + + # Make a CurrentThreadExecutor we'll use to idle in this thread - we + # need one for every sync frame, even if there's one above us in the + # same thread. + old_executor = getattr(self.executors, "current", None) + current_executor = CurrentThreadExecutor(old_executor) + self.executors.current = current_executor + + # Wrapping context in list so it can be reassigned from within + # `main_wrap`. + context = [contextvars.copy_context()] + + # Get task context so that parent task knows which task to propagate + # an asyncio.CancelledError to. + task_context = getattr(SyncToAsync.threadlocal, "task_context", None) + + # Use call_soon_threadsafe to schedule a synchronous callback on the + # main event loop's thread if it's there, otherwise make a new loop + # in this thread. + try: + awaitable = self.main_wrap( + call_result, + sys.exc_info(), + task_context, + context, + # prepare an awaitable which can be passed as is to self.main_wrap, + # so that `args` and `kwargs` don't need to be + # destructured when passed to self.main_wrap + # (which is required by `ParamSpec`) + # as that may cause overlapping arguments + self.awaitable(*args, **kwargs), + ) + + async def new_loop_wrap() -> None: + loop = asyncio.get_running_loop() + self.loop_thread_executors[loop] = current_executor + try: + await awaitable + finally: + del self.loop_thread_executors[loop] + + if self.main_event_loop is not None: + try: + self.main_event_loop.call_soon_threadsafe( + self.main_event_loop.create_task, awaitable + ) + except RuntimeError: + running_in_main_event_loop = False + else: + running_in_main_event_loop = True + # Run the CurrentThreadExecutor until the future is done. + current_executor.run_until_future(call_result) + else: + running_in_main_event_loop = False + + if not running_in_main_event_loop: + loop_executor = None + + if self.async_single_thread_context.get(None): + single_thread_context = self.async_single_thread_context.get() + + if single_thread_context in self.context_to_thread_executor: + loop_executor = self.context_to_thread_executor[ + single_thread_context + ] + else: + loop_executor = ThreadPoolExecutor(max_workers=1) + self.context_to_thread_executor[ + single_thread_context + ] = loop_executor + else: + # Make our own event loop - in a new thread - and run inside that. + loop_executor = ThreadPoolExecutor(max_workers=1) + + loop_future = loop_executor.submit(asyncio.run, new_loop_wrap()) + # Run the CurrentThreadExecutor until the future is done. + current_executor.run_until_future(loop_future) + # Wait for future and/or allow for exception propagation + loop_future.result() + finally: + _restore_context(context[0]) + # Restore old current thread executor state + self.executors.current = old_executor + + # Wait for results from the future. + return call_result.result() + + def __get__(self, parent: Any, objtype: Any) -> Callable[_P, _R]: + """ + Include self for methods + """ + func = functools.partial(self.__call__, parent) + return functools.update_wrapper(func, self.awaitable) + + async def main_wrap( + self, + call_result: "Future[_R]", + exc_info: "OptExcInfo", + task_context: "Optional[List[asyncio.Task[Any]]]", + context: List[contextvars.Context], + awaitable: Union[Coroutine[Any, Any, _R], Awaitable[_R]], + ) -> None: + """ + Wraps the awaitable with something that puts the result into the + result/exception future. + """ + + __traceback_hide__ = True # noqa: F841 + + if context is not None: + _restore_context(context[0]) + + current_task = asyncio.current_task() + if current_task is not None and task_context is not None: + task_context.append(current_task) + + try: + # If we have an exception, run the function inside the except block + # after raising it so exc_info is correctly populated. + if exc_info[1]: + try: + raise exc_info[1] + except BaseException: + result = await awaitable + else: + result = await awaitable + except BaseException as e: + call_result.set_exception(e) + else: + call_result.set_result(result) + finally: + if current_task is not None and task_context is not None: + task_context.remove(current_task) + context[0] = contextvars.copy_context() + + +class SyncToAsync(Generic[_P, _R]): + """ + Utility class which turns a synchronous callable into an awaitable that + runs in a threadpool. It also sets a threadlocal inside the thread so + calls to AsyncToSync can escape it. + + If thread_sensitive is passed, the code will run in the same thread as any + outer code. This is needed for underlying Python code that is not + threadsafe (for example, code which handles SQLite database connections). + + If the outermost program is async (i.e. SyncToAsync is outermost), then + this will be a dedicated single sub-thread that all sync code runs in, + one after the other. If the outermost program is sync (i.e. AsyncToSync is + outermost), this will just be the main thread. This is achieved by idling + with a CurrentThreadExecutor while AsyncToSync is blocking its sync parent, + rather than just blocking. + + If executor is passed in, that will be used instead of the loop's default executor. + In order to pass in an executor, thread_sensitive must be set to False, otherwise + a TypeError will be raised. + """ + + # Storage for main event loop references + threadlocal = threading.local() + + # Single-thread executor for thread-sensitive code + single_thread_executor = ThreadPoolExecutor(max_workers=1) + + # Maintain a contextvar for the current execution context. Optionally used + # for thread sensitive mode. + thread_sensitive_context: "contextvars.ContextVar[ThreadSensitiveContext]" = ( + contextvars.ContextVar("thread_sensitive_context") + ) + + # Contextvar that is used to detect if the single thread executor + # would be awaited on while already being used in the same context + deadlock_context: "contextvars.ContextVar[bool]" = contextvars.ContextVar( + "deadlock_context" + ) + + # Maintaining a weak reference to the context ensures that thread pools are + # erased once the context goes out of scope. This terminates the thread pool. + context_to_thread_executor: "weakref.WeakKeyDictionary[ThreadSensitiveContext, ThreadPoolExecutor]" = ( + weakref.WeakKeyDictionary() + ) + + def __init__( + self, + func: Callable[_P, _R], + thread_sensitive: bool = True, + executor: Optional["ThreadPoolExecutor"] = None, + context: Optional[contextvars.Context] = None, + ) -> None: + if ( + not callable(func) + or iscoroutinefunction(func) + or iscoroutinefunction(getattr(func, "__call__", func)) + ): + raise TypeError("sync_to_async can only be applied to sync functions.") + + functools.update_wrapper(self, func) + self.func = func + self.context = context + + self._thread_sensitive = thread_sensitive + markcoroutinefunction(self) + if thread_sensitive and executor is not None: + raise TypeError("executor must not be set when thread_sensitive is True") + self._executor = executor + try: + self.__self__ = func.__self__ # type: ignore + except AttributeError: + pass + + async def __call__(self, *args: _P.args, **kwargs: _P.kwargs) -> _R: + __traceback_hide__ = True # noqa: F841 + loop = asyncio.get_running_loop() + + # Work out what thread to run the code in + if self._thread_sensitive: + current_thread_executor = getattr(AsyncToSync.executors, "current", None) + if current_thread_executor: + # If we have a parent sync thread above somewhere, use that + executor = current_thread_executor + elif self.thread_sensitive_context.get(None): + # If we have a way of retrieving the current context, attempt + # to use a per-context thread pool executor + thread_sensitive_context = self.thread_sensitive_context.get() + + if thread_sensitive_context in self.context_to_thread_executor: + # Re-use thread executor in current context + executor = self.context_to_thread_executor[thread_sensitive_context] + else: + # Create new thread executor in current context + executor = ThreadPoolExecutor(max_workers=1) + self.context_to_thread_executor[thread_sensitive_context] = executor + elif loop in AsyncToSync.loop_thread_executors: + # Re-use thread executor for running loop + executor = AsyncToSync.loop_thread_executors[loop] + elif self.deadlock_context.get(False): + raise RuntimeError( + "Single thread executor already being used, would deadlock" + ) + else: + # Otherwise, we run it in a fixed single thread + executor = self.single_thread_executor + self.deadlock_context.set(True) + else: + # Use the passed in executor, or the loop's default if it is None + executor = self._executor + + context = contextvars.copy_context() if self.context is None else self.context + child = functools.partial(self.func, *args, **kwargs) + func = context.run + task_context: List[asyncio.Task[Any]] = [] + + # Run the code in the right thread + exec_coro = loop.run_in_executor( + executor, + functools.partial( + self.thread_handler, + loop, + sys.exc_info(), + task_context, + func, + child, + ), + ) + ret: _R + try: + ret = await asyncio.shield(exec_coro) + except asyncio.CancelledError: + cancel_parent = True + try: + task = task_context[0] + task.cancel() + try: + await task + cancel_parent = False + except asyncio.CancelledError: + pass + except IndexError: + pass + if exec_coro.done(): + raise + if cancel_parent: + exec_coro.cancel() + ret = await exec_coro + finally: + if self.context is None: + _restore_context(context) + self.deadlock_context.set(False) + + return ret + + def __get__( + self, parent: Any, objtype: Any + ) -> Callable[_P, Coroutine[Any, Any, _R]]: + """ + Include self for methods + """ + func = functools.partial(self.__call__, parent) + return functools.update_wrapper(func, self.func) + + def thread_handler(self, loop, exc_info, task_context, func, *args, **kwargs): + """ + Wraps the sync application with exception handling. + """ + + __traceback_hide__ = True # noqa: F841 + + # Set the threadlocal for AsyncToSync + self.threadlocal.main_event_loop = loop + self.threadlocal.main_event_loop_pid = os.getpid() + self.threadlocal.task_context = task_context + + # Run the function + # If we have an exception, run the function inside the except block + # after raising it so exc_info is correctly populated. + if exc_info[1]: + try: + raise exc_info[1] + except BaseException: + return func(*args, **kwargs) + else: + return func(*args, **kwargs) + + +@overload +def async_to_sync( + *, + force_new_loop: bool = False, +) -> Callable[ + [Union[Callable[_P, Coroutine[Any, Any, _R]], Callable[_P, Awaitable[_R]]]], + Callable[_P, _R], +]: + ... + + +@overload +def async_to_sync( + awaitable: Union[ + Callable[_P, Coroutine[Any, Any, _R]], + Callable[_P, Awaitable[_R]], + ], + *, + force_new_loop: bool = False, +) -> Callable[_P, _R]: + ... + + +def async_to_sync( + awaitable: Optional[ + Union[ + Callable[_P, Coroutine[Any, Any, _R]], + Callable[_P, Awaitable[_R]], + ] + ] = None, + *, + force_new_loop: bool = False, +) -> Union[ + Callable[ + [Union[Callable[_P, Coroutine[Any, Any, _R]], Callable[_P, Awaitable[_R]]]], + Callable[_P, _R], + ], + Callable[_P, _R], +]: + if awaitable is None: + return lambda f: AsyncToSync( + f, + force_new_loop=force_new_loop, + ) + return AsyncToSync( + awaitable, + force_new_loop=force_new_loop, + ) + + +@overload +def sync_to_async( + *, + thread_sensitive: bool = True, + executor: Optional["ThreadPoolExecutor"] = None, + context: Optional[contextvars.Context] = None, +) -> Callable[[Callable[_P, _R]], Callable[_P, Coroutine[Any, Any, _R]]]: + ... + + +@overload +def sync_to_async( + func: Callable[_P, _R], + *, + thread_sensitive: bool = True, + executor: Optional["ThreadPoolExecutor"] = None, + context: Optional[contextvars.Context] = None, +) -> Callable[_P, Coroutine[Any, Any, _R]]: + ... + + +def sync_to_async( + func: Optional[Callable[_P, _R]] = None, + *, + thread_sensitive: bool = True, + executor: Optional["ThreadPoolExecutor"] = None, + context: Optional[contextvars.Context] = None, +) -> Union[ + Callable[[Callable[_P, _R]], Callable[_P, Coroutine[Any, Any, _R]]], + Callable[_P, Coroutine[Any, Any, _R]], +]: + if func is None: + return lambda f: SyncToAsync( + f, + thread_sensitive=thread_sensitive, + executor=executor, + context=context, + ) + return SyncToAsync( + func, + thread_sensitive=thread_sensitive, + executor=executor, + context=context, + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/testing.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/testing.py new file mode 100644 index 0000000..d6ccee5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/testing.py @@ -0,0 +1,137 @@ +import asyncio +import contextvars +import time + +from .compatibility import guarantee_single_callable +from .timeout import timeout as async_timeout + + +class ApplicationCommunicator: + """ + Runs an ASGI application in a test mode, allowing sending of + messages to it and retrieval of messages it sends. + """ + + def __init__(self, application, scope): + self._future = None + self.application = guarantee_single_callable(application) + self.scope = scope + self._input_queue = None + self._output_queue = None + + # For Python 3.9 we need to lazily bind the queues, on 3.10+ they bind the + # event loop lazily. + @property + def input_queue(self): + if self._input_queue is None: + self._input_queue = asyncio.Queue() + return self._input_queue + + @property + def output_queue(self): + if self._output_queue is None: + self._output_queue = asyncio.Queue() + return self._output_queue + + @property + def future(self): + if self._future is None: + # Clear context - this ensures that context vars set in the testing scope + # are not "leaked" into the application which would normally begin with + # an empty context. In Python >= 3.11 this could also be written as: + # asyncio.create_task(..., context=contextvars.Context()) + self._future = contextvars.Context().run( + asyncio.create_task, + self.application( + self.scope, self.input_queue.get, self.output_queue.put + ), + ) + return self._future + + async def wait(self, timeout=1): + """ + Waits for the application to stop itself and returns any exceptions. + """ + try: + async with async_timeout(timeout): + try: + await self.future + self.future.result() + except asyncio.CancelledError: + pass + finally: + if not self.future.done(): + self.future.cancel() + try: + await self.future + except asyncio.CancelledError: + pass + + def stop(self, exceptions=True): + future = self._future + if future is None: + return + + if not future.done(): + future.cancel() + elif exceptions: + # Give a chance to raise any exceptions + future.result() + + def __del__(self): + # Clean up on deletion + try: + self.stop(exceptions=False) + except RuntimeError: + # Event loop already stopped + pass + + async def send_input(self, message): + """ + Sends a single message to the application + """ + # Make sure there's not an exception to raise from the task + if self.future.done(): + self.future.result() + + # Give it the message + await self.input_queue.put(message) + + async def receive_output(self, timeout=1): + """ + Receives a single message from the application, with optional timeout. + """ + # Make sure there's not an exception to raise from the task + if self.future.done(): + self.future.result() + # Wait and receive the message + try: + async with async_timeout(timeout): + return await self.output_queue.get() + except asyncio.TimeoutError as e: + # See if we have another error to raise inside + if self.future.done(): + self.future.result() + else: + self.future.cancel() + try: + await self.future + except asyncio.CancelledError: + pass + raise e + + async def receive_nothing(self, timeout=0.1, interval=0.01): + """ + Checks that there is no message to receive in the given time. + """ + # Make sure there's not an exception to raise from the task + if self.future.done(): + self.future.result() + + # `interval` has precedence over `timeout` + start = time.monotonic() + while time.monotonic() - start < timeout: + if not self.output_queue.empty(): + return False + await asyncio.sleep(interval) + return self.output_queue.empty() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/timeout.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/timeout.py new file mode 100644 index 0000000..fd5381d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/timeout.py @@ -0,0 +1,118 @@ +# This code is originally sourced from the aio-libs project "async_timeout", +# under the Apache 2.0 license. You may see the original project at +# https://github.com/aio-libs/async-timeout + +# It is vendored here to reduce chain-dependencies on this library, and +# modified slightly to remove some features we don't use. + + +import asyncio +import warnings +from types import TracebackType +from typing import Any # noqa +from typing import Optional, Type + + +class timeout: + """timeout context manager. + + Useful in cases when you want to apply timeout logic around block + of code or in cases when asyncio.wait_for is not suitable. For example: + + >>> with timeout(0.001): + ... async with aiohttp.get('https://github.com') as r: + ... await r.text() + + + timeout - value in seconds or None to disable timeout logic + loop - asyncio compatible event loop + """ + + def __init__( + self, + timeout: Optional[float], + *, + loop: Optional[asyncio.AbstractEventLoop] = None, + ) -> None: + self._timeout = timeout + if loop is None: + loop = asyncio.get_running_loop() + else: + warnings.warn( + """The loop argument to timeout() is deprecated.""", DeprecationWarning + ) + self._loop = loop + self._task = None # type: Optional[asyncio.Task[Any]] + self._cancelled = False + self._cancel_handler = None # type: Optional[asyncio.Handle] + self._cancel_at = None # type: Optional[float] + + def __enter__(self) -> "timeout": + return self._do_enter() + + def __exit__( + self, + exc_type: Type[BaseException], + exc_val: BaseException, + exc_tb: TracebackType, + ) -> Optional[bool]: + self._do_exit(exc_type) + return None + + async def __aenter__(self) -> "timeout": + return self._do_enter() + + async def __aexit__( + self, + exc_type: Type[BaseException], + exc_val: BaseException, + exc_tb: TracebackType, + ) -> None: + self._do_exit(exc_type) + + @property + def expired(self) -> bool: + return self._cancelled + + @property + def remaining(self) -> Optional[float]: + if self._cancel_at is not None: + return max(self._cancel_at - self._loop.time(), 0.0) + else: + return None + + def _do_enter(self) -> "timeout": + # Support Tornado 5- without timeout + # Details: https://github.com/python/asyncio/issues/392 + if self._timeout is None: + return self + + self._task = asyncio.current_task(self._loop) + if self._task is None: + raise RuntimeError( + "Timeout context manager should be used " "inside a task" + ) + + if self._timeout <= 0: + self._loop.call_soon(self._cancel_task) + return self + + self._cancel_at = self._loop.time() + self._timeout + self._cancel_handler = self._loop.call_at(self._cancel_at, self._cancel_task) + return self + + def _do_exit(self, exc_type: Type[BaseException]) -> None: + if exc_type is asyncio.CancelledError and self._cancelled: + self._cancel_handler = None + self._task = None + raise asyncio.TimeoutError + if self._timeout is not None and self._cancel_handler is not None: + self._cancel_handler.cancel() + self._cancel_handler = None + self._task = None + return None + + def _cancel_task(self) -> None: + if self._task is not None: + self._task.cancel() + self._cancelled = True diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/typing.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/typing.py new file mode 100644 index 0000000..368aed5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/typing.py @@ -0,0 +1,279 @@ +import sys +from typing import ( + Any, + Awaitable, + Callable, + Dict, + Iterable, + Literal, + Optional, + Protocol, + Tuple, + Type, + TypedDict, + Union, +) + +if sys.version_info >= (3, 11): + from typing import NotRequired +else: + from typing_extensions import NotRequired + +__all__ = ( + "ASGIVersions", + "HTTPScope", + "WebSocketScope", + "LifespanScope", + "WWWScope", + "Scope", + "HTTPRequestEvent", + "HTTPResponseStartEvent", + "HTTPResponseBodyEvent", + "HTTPResponseTrailersEvent", + "HTTPResponsePathsendEvent", + "HTTPServerPushEvent", + "HTTPDisconnectEvent", + "WebSocketConnectEvent", + "WebSocketAcceptEvent", + "WebSocketReceiveEvent", + "WebSocketSendEvent", + "WebSocketResponseStartEvent", + "WebSocketResponseBodyEvent", + "WebSocketDisconnectEvent", + "WebSocketCloseEvent", + "LifespanStartupEvent", + "LifespanShutdownEvent", + "LifespanStartupCompleteEvent", + "LifespanStartupFailedEvent", + "LifespanShutdownCompleteEvent", + "LifespanShutdownFailedEvent", + "ASGIReceiveEvent", + "ASGISendEvent", + "ASGIReceiveCallable", + "ASGISendCallable", + "ASGI2Protocol", + "ASGI2Application", + "ASGI3Application", + "ASGIApplication", +) + + +class ASGIVersions(TypedDict): + spec_version: str + version: Union[Literal["2.0"], Literal["3.0"]] + + +class HTTPScope(TypedDict): + type: Literal["http"] + asgi: ASGIVersions + http_version: str + method: str + scheme: str + path: str + raw_path: bytes + query_string: bytes + root_path: str + headers: Iterable[Tuple[bytes, bytes]] + client: Optional[Tuple[str, int]] + server: Optional[Tuple[str, Optional[int]]] + state: NotRequired[Dict[str, Any]] + extensions: Optional[Dict[str, Dict[object, object]]] + + +class WebSocketScope(TypedDict): + type: Literal["websocket"] + asgi: ASGIVersions + http_version: str + scheme: str + path: str + raw_path: bytes + query_string: bytes + root_path: str + headers: Iterable[Tuple[bytes, bytes]] + client: Optional[Tuple[str, int]] + server: Optional[Tuple[str, Optional[int]]] + subprotocols: Iterable[str] + state: NotRequired[Dict[str, Any]] + extensions: Optional[Dict[str, Dict[object, object]]] + + +class LifespanScope(TypedDict): + type: Literal["lifespan"] + asgi: ASGIVersions + state: NotRequired[Dict[str, Any]] + + +WWWScope = Union[HTTPScope, WebSocketScope] +Scope = Union[HTTPScope, WebSocketScope, LifespanScope] + + +class HTTPRequestEvent(TypedDict): + type: Literal["http.request"] + body: bytes + more_body: bool + + +class HTTPResponseDebugEvent(TypedDict): + type: Literal["http.response.debug"] + info: Dict[str, object] + + +class HTTPResponseStartEvent(TypedDict): + type: Literal["http.response.start"] + status: int + headers: Iterable[Tuple[bytes, bytes]] + trailers: bool + + +class HTTPResponseBodyEvent(TypedDict): + type: Literal["http.response.body"] + body: bytes + more_body: bool + + +class HTTPResponseTrailersEvent(TypedDict): + type: Literal["http.response.trailers"] + headers: Iterable[Tuple[bytes, bytes]] + more_trailers: bool + + +class HTTPResponsePathsendEvent(TypedDict): + type: Literal["http.response.pathsend"] + path: str + + +class HTTPServerPushEvent(TypedDict): + type: Literal["http.response.push"] + path: str + headers: Iterable[Tuple[bytes, bytes]] + + +class HTTPDisconnectEvent(TypedDict): + type: Literal["http.disconnect"] + + +class WebSocketConnectEvent(TypedDict): + type: Literal["websocket.connect"] + + +class WebSocketAcceptEvent(TypedDict): + type: Literal["websocket.accept"] + subprotocol: Optional[str] + headers: Iterable[Tuple[bytes, bytes]] + + +class WebSocketReceiveEvent(TypedDict): + type: Literal["websocket.receive"] + bytes: Optional[bytes] + text: Optional[str] + + +class WebSocketSendEvent(TypedDict): + type: Literal["websocket.send"] + bytes: Optional[bytes] + text: Optional[str] + + +class WebSocketResponseStartEvent(TypedDict): + type: Literal["websocket.http.response.start"] + status: int + headers: Iterable[Tuple[bytes, bytes]] + + +class WebSocketResponseBodyEvent(TypedDict): + type: Literal["websocket.http.response.body"] + body: bytes + more_body: bool + + +class WebSocketDisconnectEvent(TypedDict): + type: Literal["websocket.disconnect"] + code: int + reason: Optional[str] + + +class WebSocketCloseEvent(TypedDict): + type: Literal["websocket.close"] + code: int + reason: Optional[str] + + +class LifespanStartupEvent(TypedDict): + type: Literal["lifespan.startup"] + + +class LifespanShutdownEvent(TypedDict): + type: Literal["lifespan.shutdown"] + + +class LifespanStartupCompleteEvent(TypedDict): + type: Literal["lifespan.startup.complete"] + + +class LifespanStartupFailedEvent(TypedDict): + type: Literal["lifespan.startup.failed"] + message: str + + +class LifespanShutdownCompleteEvent(TypedDict): + type: Literal["lifespan.shutdown.complete"] + + +class LifespanShutdownFailedEvent(TypedDict): + type: Literal["lifespan.shutdown.failed"] + message: str + + +ASGIReceiveEvent = Union[ + HTTPRequestEvent, + HTTPDisconnectEvent, + WebSocketConnectEvent, + WebSocketReceiveEvent, + WebSocketDisconnectEvent, + LifespanStartupEvent, + LifespanShutdownEvent, +] + + +ASGISendEvent = Union[ + HTTPResponseStartEvent, + HTTPResponseBodyEvent, + HTTPResponseTrailersEvent, + HTTPServerPushEvent, + HTTPDisconnectEvent, + WebSocketAcceptEvent, + WebSocketSendEvent, + WebSocketResponseStartEvent, + WebSocketResponseBodyEvent, + WebSocketCloseEvent, + LifespanStartupCompleteEvent, + LifespanStartupFailedEvent, + LifespanShutdownCompleteEvent, + LifespanShutdownFailedEvent, +] + + +ASGIReceiveCallable = Callable[[], Awaitable[ASGIReceiveEvent]] +ASGISendCallable = Callable[[ASGISendEvent], Awaitable[None]] + + +class ASGI2Protocol(Protocol): + def __init__(self, scope: Scope) -> None: + ... + + async def __call__( + self, receive: ASGIReceiveCallable, send: ASGISendCallable + ) -> None: + ... + + +ASGI2Application = Type[ASGI2Protocol] +ASGI3Application = Callable[ + [ + Scope, + ASGIReceiveCallable, + ASGISendCallable, + ], + Awaitable[None], +] +ASGIApplication = Union[ASGI2Application, ASGI3Application] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/wsgi.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/wsgi.py new file mode 100644 index 0000000..1bf398e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/asgiref/wsgi.py @@ -0,0 +1,197 @@ +import sys +from collections import defaultdict +from tempfile import SpooledTemporaryFile + +from asgiref.sync import AsyncToSync, sync_to_async + + +class WsgiToAsgi: + """ + Wraps a WSGI application to make it into an ASGI application. + """ + + def __init__(self, wsgi_application, duplicate_header_limit=100): + self.wsgi_application = wsgi_application + self.duplicate_header_limit = duplicate_header_limit + + async def __call__(self, scope, receive, send): + """ + ASGI application instantiation point. + We return a new WsgiToAsgiInstance here with the WSGI app + and the scope, ready to respond when it is __call__ed. + """ + await WsgiToAsgiInstance(self.wsgi_application, self.duplicate_header_limit)( + scope, receive, send + ) + + +class WsgiToAsgiInstance: + """ + Per-socket instance of a wrapped WSGI application + """ + + def __init__(self, wsgi_application, duplicate_header_limit=100): + self.wsgi_application = wsgi_application + self.duplicate_header_limit = duplicate_header_limit + self.response_started = False + self.response_content_length = None + + async def __call__(self, scope, receive, send): + if scope["type"] != "http": + raise ValueError("WSGI wrapper received a non-HTTP scope") + self.scope = scope + with SpooledTemporaryFile(max_size=65536) as body: + # Alright, wait for the http.request messages + while True: + message = await receive() + if message["type"] != "http.request": + raise ValueError("WSGI wrapper received a non-HTTP-request message") + body.write(message.get("body", b"")) + if not message.get("more_body"): + break + body.seek(0) + # Wrap send so it can be called from the subthread + self.sync_send = AsyncToSync(send) + # Call the WSGI app + await self.run_wsgi_app(body) + + def build_environ(self, scope, body): + """ + Builds a scope and request body into a WSGI environ object. + """ + script_name = scope.get("root_path", "").encode("utf8").decode("latin1") + path_info = scope["path"].encode("utf8").decode("latin1") + if path_info.startswith(script_name): + path_info = path_info[len(script_name) :] + environ = { + "REQUEST_METHOD": scope["method"], + "SCRIPT_NAME": script_name, + "PATH_INFO": path_info, + "QUERY_STRING": scope["query_string"].decode("ascii"), + "SERVER_PROTOCOL": "HTTP/%s" % scope["http_version"], + "wsgi.version": (1, 0), + "wsgi.url_scheme": scope.get("scheme", "http"), + "wsgi.input": body, + "wsgi.errors": sys.stderr, + "wsgi.multithread": True, + "wsgi.multiprocess": True, + "wsgi.run_once": False, + } + # Get server name and port - required in WSGI, not in ASGI + if "server" in scope: + environ["SERVER_NAME"] = scope["server"][0] + environ["SERVER_PORT"] = str(scope["server"][1]) + else: + environ["SERVER_NAME"] = "localhost" + environ["SERVER_PORT"] = "80" + + if scope.get("client") is not None: + environ["REMOTE_ADDR"] = scope["client"][0] + + # Go through headers and make them into environ entries + _headers = defaultdict(list) + for name, value in self.scope.get("headers", []): + name = name.decode("latin1") + if name == "content-length": + corrected_name = "CONTENT_LENGTH" + elif name == "content-type": + corrected_name = "CONTENT_TYPE" + else: + corrected_name = "HTTP_%s" % name.upper().replace("-", "_") + # HTTPbis say only ASCII chars are allowed in headers, but we latin1 just in case + value = value.decode("latin1") + if ( + self.duplicate_header_limit + and len(_headers[corrected_name]) >= self.duplicate_header_limit + ): + raise ValueError( + f"Too many duplicate headers: {corrected_name} exceeds limit of" + f"{self.duplicate_header_limit}" + ) + _headers[corrected_name].append(value) + for name, values in _headers.items(): + environ[name] = ",".join(values) + return environ + + def start_response(self, status, response_headers, exc_info=None): + """ + WSGI start_response callable. + """ + # Don't allow re-calling once response has begun + if self.response_started: + raise exc_info[1].with_traceback(exc_info[2]) + # Don't allow re-calling without exc_info + if hasattr(self, "response_start") and exc_info is None: + raise ValueError( + "You cannot call start_response a second time without exc_info" + ) + # Extract status code + status_code, _ = status.split(" ", 1) + status_code = int(status_code) + # Extract headers + headers = [ + (name.lower().encode("ascii"), value.encode("ascii")) + for name, value in response_headers + ] + # Extract content-length + self.response_content_length = None + for name, value in response_headers: + if name.lower() == "content-length": + self.response_content_length = int(value) + # Build and send response start message. + self.response_start = { + "type": "http.response.start", + "status": status_code, + "headers": headers, + } + + @sync_to_async + def run_wsgi_app(self, body): + """ + Called in a subthread to run the WSGI app. We encapsulate like + this so that the start_response callable is called in the same thread. + """ + # Translate the scope and incoming request body into a WSGI environ + try: + environ = self.build_environ(self.scope, body) + except ValueError: + # Return 400 Bad Request if header limit exceeded + self.sync_send( + { + "type": "http.response.start", + "status": 400, + "headers": [(b"content-type", b"text/plain")], + } + ) + self.sync_send( + { + "type": "http.response.body", + "body": b"Bad Request: Too many duplicate headers", + } + ) + return + # Run the WSGI app + bytes_sent = 0 + for output in self.wsgi_application(environ, self.start_response): + # If this is the first response, include the response headers + if not self.response_started: + self.response_started = True + self.sync_send(self.response_start) + # If the application supplies a Content-Length header + if self.response_content_length is not None: + # The server should not transmit more bytes to the client than the header allows + bytes_allowed = self.response_content_length - bytes_sent + if len(output) > bytes_allowed: + output = output[:bytes_allowed] + self.sync_send( + {"type": "http.response.body", "body": output, "more_body": True} + ) + bytes_sent += len(output) + # The server should stop iterating over the response when enough data has been sent + if bytes_sent == self.response_content_length: + break + # Close connection + if not self.response_started: + self.response_started = True + self.sync_send(self.response_start) + self.sync_send({"type": "http.response.body"}) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/__init__.py new file mode 100644 index 0000000..3b96a48 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/__init__.py @@ -0,0 +1,24 @@ +from django.utils.version import get_version + +VERSION = (5, 0, 0, "final", 0) + +__version__ = get_version(VERSION) + + +def setup(set_prefix=True): + """ + Configure the settings (this happens as a side effect of accessing the + first setting), configure logging and populate the app registry. + Set the thread-local urlresolvers script prefix if `set_prefix` is True. + """ + from django.apps import apps + from django.conf import settings + from django.urls import set_script_prefix + from django.utils.log import configure_logging + + configure_logging(settings.LOGGING_CONFIG, settings.LOGGING) + if set_prefix: + set_script_prefix( + "/" if settings.FORCE_SCRIPT_NAME is None else settings.FORCE_SCRIPT_NAME + ) + apps.populate(settings.INSTALLED_APPS) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/__main__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/__main__.py new file mode 100644 index 0000000..8b96e91 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/__main__.py @@ -0,0 +1,9 @@ +""" +Invokes django-admin when the django module is run as a script. + +Example: python -m django check +""" +from django.core import management + +if __name__ == "__main__": + management.execute_from_command_line() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/apps/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/apps/__init__.py new file mode 100644 index 0000000..96674be --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/apps/__init__.py @@ -0,0 +1,4 @@ +from .config import AppConfig +from .registry import apps + +__all__ = ["AppConfig", "apps"] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/apps/config.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/apps/config.py new file mode 100644 index 0000000..28e50e5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/apps/config.py @@ -0,0 +1,274 @@ +import inspect +import os +from importlib import import_module + +from django.core.exceptions import ImproperlyConfigured +from django.utils.functional import cached_property +from django.utils.module_loading import import_string, module_has_submodule + +APPS_MODULE_NAME = "apps" +MODELS_MODULE_NAME = "models" + + +class AppConfig: + """Class representing a Django application and its configuration.""" + + def __init__(self, app_name, app_module): + # Full Python path to the application e.g. 'django.contrib.admin'. + self.name = app_name + + # Root module for the application e.g. . + self.module = app_module + + # Reference to the Apps registry that holds this AppConfig. Set by the + # registry when it registers the AppConfig instance. + self.apps = None + + # The following attributes could be defined at the class level in a + # subclass, hence the test-and-set pattern. + + # Last component of the Python path to the application e.g. 'admin'. + # This value must be unique across a Django project. + if not hasattr(self, "label"): + self.label = app_name.rpartition(".")[2] + if not self.label.isidentifier(): + raise ImproperlyConfigured( + "The app label '%s' is not a valid Python identifier." % self.label + ) + + # Human-readable name for the application e.g. "Admin". + if not hasattr(self, "verbose_name"): + self.verbose_name = self.label.title() + + # Filesystem path to the application directory e.g. + # '/path/to/django/contrib/admin'. + if not hasattr(self, "path"): + self.path = self._path_from_module(app_module) + + # Module containing models e.g. . Set by import_models(). + # None if the application doesn't have a models module. + self.models_module = None + + # Mapping of lowercase model names to model classes. Initially set to + # None to prevent accidental access before import_models() runs. + self.models = None + + def __repr__(self): + return "<%s: %s>" % (self.__class__.__name__, self.label) + + @cached_property + def default_auto_field(self): + from django.conf import settings + + return settings.DEFAULT_AUTO_FIELD + + @property + def _is_default_auto_field_overridden(self): + return self.__class__.default_auto_field is not AppConfig.default_auto_field + + def _path_from_module(self, module): + """Attempt to determine app's filesystem path from its module.""" + # See #21874 for extended discussion of the behavior of this method in + # various cases. + # Convert to list because __path__ may not support indexing. + paths = list(getattr(module, "__path__", [])) + if len(paths) != 1: + filename = getattr(module, "__file__", None) + if filename is not None: + paths = [os.path.dirname(filename)] + else: + # For unknown reasons, sometimes the list returned by __path__ + # contains duplicates that must be removed (#25246). + paths = list(set(paths)) + if len(paths) > 1: + raise ImproperlyConfigured( + "The app module %r has multiple filesystem locations (%r); " + "you must configure this app with an AppConfig subclass " + "with a 'path' class attribute." % (module, paths) + ) + elif not paths: + raise ImproperlyConfigured( + "The app module %r has no filesystem location, " + "you must configure this app with an AppConfig subclass " + "with a 'path' class attribute." % module + ) + return paths[0] + + @classmethod + def create(cls, entry): + """ + Factory that creates an app config from an entry in INSTALLED_APPS. + """ + # create() eventually returns app_config_class(app_name, app_module). + app_config_class = None + app_name = None + app_module = None + + # If import_module succeeds, entry points to the app module. + try: + app_module = import_module(entry) + except Exception: + pass + else: + # If app_module has an apps submodule that defines a single + # AppConfig subclass, use it automatically. + # To prevent this, an AppConfig subclass can declare a class + # variable default = False. + # If the apps module defines more than one AppConfig subclass, + # the default one can declare default = True. + if module_has_submodule(app_module, APPS_MODULE_NAME): + mod_path = "%s.%s" % (entry, APPS_MODULE_NAME) + mod = import_module(mod_path) + # Check if there's exactly one AppConfig candidate, + # excluding those that explicitly define default = False. + app_configs = [ + (name, candidate) + for name, candidate in inspect.getmembers(mod, inspect.isclass) + if ( + issubclass(candidate, cls) + and candidate is not cls + and getattr(candidate, "default", True) + ) + ] + if len(app_configs) == 1: + app_config_class = app_configs[0][1] + else: + # Check if there's exactly one AppConfig subclass, + # among those that explicitly define default = True. + app_configs = [ + (name, candidate) + for name, candidate in app_configs + if getattr(candidate, "default", False) + ] + if len(app_configs) > 1: + candidates = [repr(name) for name, _ in app_configs] + raise RuntimeError( + "%r declares more than one default AppConfig: " + "%s." % (mod_path, ", ".join(candidates)) + ) + elif len(app_configs) == 1: + app_config_class = app_configs[0][1] + + # Use the default app config class if we didn't find anything. + if app_config_class is None: + app_config_class = cls + app_name = entry + + # If import_string succeeds, entry is an app config class. + if app_config_class is None: + try: + app_config_class = import_string(entry) + except Exception: + pass + # If both import_module and import_string failed, it means that entry + # doesn't have a valid value. + if app_module is None and app_config_class is None: + # If the last component of entry starts with an uppercase letter, + # then it was likely intended to be an app config class; if not, + # an app module. Provide a nice error message in both cases. + mod_path, _, cls_name = entry.rpartition(".") + if mod_path and cls_name[0].isupper(): + # We could simply re-trigger the string import exception, but + # we're going the extra mile and providing a better error + # message for typos in INSTALLED_APPS. + # This may raise ImportError, which is the best exception + # possible if the module at mod_path cannot be imported. + mod = import_module(mod_path) + candidates = [ + repr(name) + for name, candidate in inspect.getmembers(mod, inspect.isclass) + if issubclass(candidate, cls) and candidate is not cls + ] + msg = "Module '%s' does not contain a '%s' class." % ( + mod_path, + cls_name, + ) + if candidates: + msg += " Choices are: %s." % ", ".join(candidates) + raise ImportError(msg) + else: + # Re-trigger the module import exception. + import_module(entry) + + # Check for obvious errors. (This check prevents duck typing, but + # it could be removed if it became a problem in practice.) + if not issubclass(app_config_class, AppConfig): + raise ImproperlyConfigured("'%s' isn't a subclass of AppConfig." % entry) + + # Obtain app name here rather than in AppClass.__init__ to keep + # all error checking for entries in INSTALLED_APPS in one place. + if app_name is None: + try: + app_name = app_config_class.name + except AttributeError: + raise ImproperlyConfigured("'%s' must supply a name attribute." % entry) + + # Ensure app_name points to a valid module. + try: + app_module = import_module(app_name) + except ImportError: + raise ImproperlyConfigured( + "Cannot import '%s'. Check that '%s.%s.name' is correct." + % ( + app_name, + app_config_class.__module__, + app_config_class.__qualname__, + ) + ) + + # Entry is a path to an app config class. + return app_config_class(app_name, app_module) + + def get_model(self, model_name, require_ready=True): + """ + Return the model with the given case-insensitive model_name. + + Raise LookupError if no model exists with this name. + """ + if require_ready: + self.apps.check_models_ready() + else: + self.apps.check_apps_ready() + try: + return self.models[model_name.lower()] + except KeyError: + raise LookupError( + "App '%s' doesn't have a '%s' model." % (self.label, model_name) + ) + + def get_models(self, include_auto_created=False, include_swapped=False): + """ + Return an iterable of models. + + By default, the following models aren't included: + + - auto-created models for many-to-many relations without + an explicit intermediate table, + - models that have been swapped out. + + Set the corresponding keyword argument to True to include such models. + Keyword arguments aren't documented; they're a private API. + """ + self.apps.check_models_ready() + for model in self.models.values(): + if model._meta.auto_created and not include_auto_created: + continue + if model._meta.swapped and not include_swapped: + continue + yield model + + def import_models(self): + # Dictionary of models for this app, primarily maintained in the + # 'all_models' attribute of the Apps this AppConfig is attached to. + self.models = self.apps.all_models[self.label] + + if module_has_submodule(self.module, MODELS_MODULE_NAME): + models_module_name = "%s.%s" % (self.name, MODELS_MODULE_NAME) + self.models_module = import_module(models_module_name) + + def ready(self): + """ + Override this method in subclasses to run code when Django starts. + """ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/apps/registry.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/apps/registry.py new file mode 100644 index 0000000..92de607 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/apps/registry.py @@ -0,0 +1,437 @@ +import functools +import sys +import threading +import warnings +from collections import Counter, defaultdict +from functools import partial + +from django.core.exceptions import AppRegistryNotReady, ImproperlyConfigured + +from .config import AppConfig + + +class Apps: + """ + A registry that stores the configuration of installed applications. + + It also keeps track of models, e.g. to provide reverse relations. + """ + + def __init__(self, installed_apps=()): + # installed_apps is set to None when creating the main registry + # because it cannot be populated at that point. Other registries must + # provide a list of installed apps and are populated immediately. + if installed_apps is None and hasattr(sys.modules[__name__], "apps"): + raise RuntimeError("You must supply an installed_apps argument.") + + # Mapping of app labels => model names => model classes. Every time a + # model is imported, ModelBase.__new__ calls apps.register_model which + # creates an entry in all_models. All imported models are registered, + # regardless of whether they're defined in an installed application + # and whether the registry has been populated. Since it isn't possible + # to reimport a module safely (it could reexecute initialization code) + # all_models is never overridden or reset. + self.all_models = defaultdict(dict) + + # Mapping of labels to AppConfig instances for installed apps. + self.app_configs = {} + + # Stack of app_configs. Used to store the current state in + # set_available_apps and set_installed_apps. + self.stored_app_configs = [] + + # Whether the registry is populated. + self.apps_ready = self.models_ready = self.ready = False + # For the autoreloader. + self.ready_event = threading.Event() + + # Lock for thread-safe population. + self._lock = threading.RLock() + self.loading = False + + # Maps ("app_label", "modelname") tuples to lists of functions to be + # called when the corresponding model is ready. Used by this class's + # `lazy_model_operation()` and `do_pending_operations()` methods. + self._pending_operations = defaultdict(list) + + # Populate apps and models, unless it's the main registry. + if installed_apps is not None: + self.populate(installed_apps) + + def populate(self, installed_apps=None): + """ + Load application configurations and models. + + Import each application module and then each model module. + + It is thread-safe and idempotent, but not reentrant. + """ + if self.ready: + return + + # populate() might be called by two threads in parallel on servers + # that create threads before initializing the WSGI callable. + with self._lock: + if self.ready: + return + + # An RLock prevents other threads from entering this section. The + # compare and set operation below is atomic. + if self.loading: + # Prevent reentrant calls to avoid running AppConfig.ready() + # methods twice. + raise RuntimeError("populate() isn't reentrant") + self.loading = True + + # Phase 1: initialize app configs and import app modules. + for entry in installed_apps: + if isinstance(entry, AppConfig): + app_config = entry + else: + app_config = AppConfig.create(entry) + if app_config.label in self.app_configs: + raise ImproperlyConfigured( + "Application labels aren't unique, " + "duplicates: %s" % app_config.label + ) + + self.app_configs[app_config.label] = app_config + app_config.apps = self + + # Check for duplicate app names. + counts = Counter( + app_config.name for app_config in self.app_configs.values() + ) + duplicates = [name for name, count in counts.most_common() if count > 1] + if duplicates: + raise ImproperlyConfigured( + "Application names aren't unique, " + "duplicates: %s" % ", ".join(duplicates) + ) + + self.apps_ready = True + + # Phase 2: import models modules. + for app_config in self.app_configs.values(): + app_config.import_models() + + self.clear_cache() + + self.models_ready = True + + # Phase 3: run ready() methods of app configs. + for app_config in self.get_app_configs(): + app_config.ready() + + self.ready = True + self.ready_event.set() + + def check_apps_ready(self): + """Raise an exception if all apps haven't been imported yet.""" + if not self.apps_ready: + from django.conf import settings + + # If "not ready" is due to unconfigured settings, accessing + # INSTALLED_APPS raises a more helpful ImproperlyConfigured + # exception. + settings.INSTALLED_APPS + raise AppRegistryNotReady("Apps aren't loaded yet.") + + def check_models_ready(self): + """Raise an exception if all models haven't been imported yet.""" + if not self.models_ready: + raise AppRegistryNotReady("Models aren't loaded yet.") + + def get_app_configs(self): + """Import applications and return an iterable of app configs.""" + self.check_apps_ready() + return self.app_configs.values() + + def get_app_config(self, app_label): + """ + Import applications and returns an app config for the given label. + + Raise LookupError if no application exists with this label. + """ + self.check_apps_ready() + try: + return self.app_configs[app_label] + except KeyError: + message = "No installed app with label '%s'." % app_label + for app_config in self.get_app_configs(): + if app_config.name == app_label: + message += " Did you mean '%s'?" % app_config.label + break + raise LookupError(message) + + # This method is performance-critical at least for Django's test suite. + @functools.cache + def get_models(self, include_auto_created=False, include_swapped=False): + """ + Return a list of all installed models. + + By default, the following models aren't included: + + - auto-created models for many-to-many relations without + an explicit intermediate table, + - models that have been swapped out. + + Set the corresponding keyword argument to True to include such models. + """ + self.check_models_ready() + + result = [] + for app_config in self.app_configs.values(): + result.extend(app_config.get_models(include_auto_created, include_swapped)) + return result + + def get_model(self, app_label, model_name=None, require_ready=True): + """ + Return the model matching the given app_label and model_name. + + As a shortcut, app_label may be in the form .. + + model_name is case-insensitive. + + Raise LookupError if no application exists with this label, or no + model exists with this name in the application. Raise ValueError if + called with a single argument that doesn't contain exactly one dot. + """ + if require_ready: + self.check_models_ready() + else: + self.check_apps_ready() + + if model_name is None: + app_label, model_name = app_label.split(".") + + app_config = self.get_app_config(app_label) + + if not require_ready and app_config.models is None: + app_config.import_models() + + return app_config.get_model(model_name, require_ready=require_ready) + + def register_model(self, app_label, model): + # Since this method is called when models are imported, it cannot + # perform imports because of the risk of import loops. It mustn't + # call get_app_config(). + model_name = model._meta.model_name + app_models = self.all_models[app_label] + if model_name in app_models: + if ( + model.__name__ == app_models[model_name].__name__ + and model.__module__ == app_models[model_name].__module__ + ): + warnings.warn( + "Model '%s.%s' was already registered. Reloading models is not " + "advised as it can lead to inconsistencies, most notably with " + "related models." % (app_label, model_name), + RuntimeWarning, + stacklevel=2, + ) + else: + raise RuntimeError( + "Conflicting '%s' models in application '%s': %s and %s." + % (model_name, app_label, app_models[model_name], model) + ) + app_models[model_name] = model + self.do_pending_operations(model) + self.clear_cache() + + def is_installed(self, app_name): + """ + Check whether an application with this name exists in the registry. + + app_name is the full name of the app e.g. 'django.contrib.admin'. + """ + self.check_apps_ready() + return any(ac.name == app_name for ac in self.app_configs.values()) + + def get_containing_app_config(self, object_name): + """ + Look for an app config containing a given object. + + object_name is the dotted Python path to the object. + + Return the app config for the inner application in case of nesting. + Return None if the object isn't in any registered app config. + """ + self.check_apps_ready() + candidates = [] + for app_config in self.app_configs.values(): + if object_name.startswith(app_config.name): + subpath = object_name.removeprefix(app_config.name) + if subpath == "" or subpath[0] == ".": + candidates.append(app_config) + if candidates: + return sorted(candidates, key=lambda ac: -len(ac.name))[0] + + def get_registered_model(self, app_label, model_name): + """ + Similar to get_model(), but doesn't require that an app exists with + the given app_label. + + It's safe to call this method at import time, even while the registry + is being populated. + """ + model = self.all_models[app_label].get(model_name.lower()) + if model is None: + raise LookupError("Model '%s.%s' not registered." % (app_label, model_name)) + return model + + @functools.cache + def get_swappable_settings_name(self, to_string): + """ + For a given model string (e.g. "auth.User"), return the name of the + corresponding settings name if it refers to a swappable model. If the + referred model is not swappable, return None. + + This method is decorated with @functools.cache because it's performance + critical when it comes to migrations. Since the swappable settings don't + change after Django has loaded the settings, there is no reason to get + the respective settings attribute over and over again. + """ + to_string = to_string.lower() + for model in self.get_models(include_swapped=True): + swapped = model._meta.swapped + # Is this model swapped out for the model given by to_string? + if swapped and swapped.lower() == to_string: + return model._meta.swappable + # Is this model swappable and the one given by to_string? + if model._meta.swappable and model._meta.label_lower == to_string: + return model._meta.swappable + return None + + def set_available_apps(self, available): + """ + Restrict the set of installed apps used by get_app_config[s]. + + available must be an iterable of application names. + + set_available_apps() must be balanced with unset_available_apps(). + + Primarily used for performance optimization in TransactionTestCase. + + This method is safe in the sense that it doesn't trigger any imports. + """ + available = set(available) + installed = {app_config.name for app_config in self.get_app_configs()} + if not available.issubset(installed): + raise ValueError( + "Available apps isn't a subset of installed apps, extra apps: %s" + % ", ".join(available - installed) + ) + + self.stored_app_configs.append(self.app_configs) + self.app_configs = { + label: app_config + for label, app_config in self.app_configs.items() + if app_config.name in available + } + self.clear_cache() + + def unset_available_apps(self): + """Cancel a previous call to set_available_apps().""" + self.app_configs = self.stored_app_configs.pop() + self.clear_cache() + + def set_installed_apps(self, installed): + """ + Enable a different set of installed apps for get_app_config[s]. + + installed must be an iterable in the same format as INSTALLED_APPS. + + set_installed_apps() must be balanced with unset_installed_apps(), + even if it exits with an exception. + + Primarily used as a receiver of the setting_changed signal in tests. + + This method may trigger new imports, which may add new models to the + registry of all imported models. They will stay in the registry even + after unset_installed_apps(). Since it isn't possible to replay + imports safely (e.g. that could lead to registering listeners twice), + models are registered when they're imported and never removed. + """ + if not self.ready: + raise AppRegistryNotReady("App registry isn't ready yet.") + self.stored_app_configs.append(self.app_configs) + self.app_configs = {} + self.apps_ready = self.models_ready = self.loading = self.ready = False + self.clear_cache() + self.populate(installed) + + def unset_installed_apps(self): + """Cancel a previous call to set_installed_apps().""" + self.app_configs = self.stored_app_configs.pop() + self.apps_ready = self.models_ready = self.ready = True + self.clear_cache() + + def clear_cache(self): + """ + Clear all internal caches, for methods that alter the app registry. + + This is mostly used in tests. + """ + self.get_swappable_settings_name.cache_clear() + # Call expire cache on each model. This will purge + # the relation tree and the fields cache. + self.get_models.cache_clear() + if self.ready: + # Circumvent self.get_models() to prevent that the cache is refilled. + # This particularly prevents that an empty value is cached while cloning. + for app_config in self.app_configs.values(): + for model in app_config.get_models(include_auto_created=True): + model._meta._expire_cache() + + def lazy_model_operation(self, function, *model_keys): + """ + Take a function and a number of ("app_label", "modelname") tuples, and + when all the corresponding models have been imported and registered, + call the function with the model classes as its arguments. + + The function passed to this method must accept exactly n models as + arguments, where n=len(model_keys). + """ + # Base case: no arguments, just execute the function. + if not model_keys: + function() + # Recursive case: take the head of model_keys, wait for the + # corresponding model class to be imported and registered, then apply + # that argument to the supplied function. Pass the resulting partial + # to lazy_model_operation() along with the remaining model args and + # repeat until all models are loaded and all arguments are applied. + else: + next_model, *more_models = model_keys + + # This will be executed after the class corresponding to next_model + # has been imported and registered. The `func` attribute provides + # duck-type compatibility with partials. + def apply_next_model(model): + next_function = partial(apply_next_model.func, model) + self.lazy_model_operation(next_function, *more_models) + + apply_next_model.func = function + + # If the model has already been imported and registered, partially + # apply it to the function now. If not, add it to the list of + # pending operations for the model, where it will be executed with + # the model class as its sole argument once the model is ready. + try: + model_class = self.get_registered_model(*next_model) + except LookupError: + self._pending_operations[next_model].append(apply_next_model) + else: + apply_next_model(model_class) + + def do_pending_operations(self, model): + """ + Take a newly-prepared model and pass it to each function waiting for + it. This is called at the very end of Apps.register_model(). + """ + key = model._meta.app_label, model._meta.model_name + for function in self._pending_operations.pop(key, []): + function(model) + + +apps = Apps(installed_apps=None) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/__init__.py new file mode 100644 index 0000000..8d5fdd5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/__init__.py @@ -0,0 +1,364 @@ +""" +Settings and configuration for Django. + +Read values from the module specified by the DJANGO_SETTINGS_MODULE environment +variable, and then from django.conf.global_settings; see the global_settings.py +for a list of all possible variables. +""" + +import importlib +import os +import time +import traceback +import warnings +from pathlib import Path + +import django +from django.conf import global_settings +from django.core.exceptions import ImproperlyConfigured +from django.utils.deprecation import RemovedInDjango51Warning, RemovedInDjango60Warning +from django.utils.functional import LazyObject, empty + +ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE" +DEFAULT_STORAGE_ALIAS = "default" +STATICFILES_STORAGE_ALIAS = "staticfiles" + +DEFAULT_FILE_STORAGE_DEPRECATED_MSG = ( + "The DEFAULT_FILE_STORAGE setting is deprecated. Use STORAGES instead." +) + +STATICFILES_STORAGE_DEPRECATED_MSG = ( + "The STATICFILES_STORAGE setting is deprecated. Use STORAGES instead." +) + +# RemovedInDjango60Warning. +FORMS_URLFIELD_ASSUME_HTTPS_DEPRECATED_MSG = ( + "The FORMS_URLFIELD_ASSUME_HTTPS transitional setting is deprecated." +) + + +class SettingsReference(str): + """ + String subclass which references a current settings value. It's treated as + the value in memory but serializes to a settings.NAME attribute reference. + """ + + def __new__(self, value, setting_name): + return str.__new__(self, value) + + def __init__(self, value, setting_name): + self.setting_name = setting_name + + +class LazySettings(LazyObject): + """ + A lazy proxy for either global Django settings or a custom settings object. + The user can manually configure settings prior to using them. Otherwise, + Django uses the settings module pointed to by DJANGO_SETTINGS_MODULE. + """ + + def _setup(self, name=None): + """ + Load the settings module pointed to by the environment variable. This + is used the first time settings are needed, if the user hasn't + configured settings manually. + """ + settings_module = os.environ.get(ENVIRONMENT_VARIABLE) + if not settings_module: + desc = ("setting %s" % name) if name else "settings" + raise ImproperlyConfigured( + "Requested %s, but settings are not configured. " + "You must either define the environment variable %s " + "or call settings.configure() before accessing settings." + % (desc, ENVIRONMENT_VARIABLE) + ) + + self._wrapped = Settings(settings_module) + + def __repr__(self): + # Hardcode the class name as otherwise it yields 'Settings'. + if self._wrapped is empty: + return "" + return '' % { + "settings_module": self._wrapped.SETTINGS_MODULE, + } + + def __getattr__(self, name): + """Return the value of a setting and cache it in self.__dict__.""" + if (_wrapped := self._wrapped) is empty: + self._setup(name) + _wrapped = self._wrapped + val = getattr(_wrapped, name) + + # Special case some settings which require further modification. + # This is done here for performance reasons so the modified value is cached. + if name in {"MEDIA_URL", "STATIC_URL"} and val is not None: + val = self._add_script_prefix(val) + elif name == "SECRET_KEY" and not val: + raise ImproperlyConfigured("The SECRET_KEY setting must not be empty.") + + self.__dict__[name] = val + return val + + def __setattr__(self, name, value): + """ + Set the value of setting. Clear all cached values if _wrapped changes + (@override_settings does this) or clear single values when set. + """ + if name == "_wrapped": + self.__dict__.clear() + else: + self.__dict__.pop(name, None) + super().__setattr__(name, value) + + def __delattr__(self, name): + """Delete a setting and clear it from cache if needed.""" + super().__delattr__(name) + self.__dict__.pop(name, None) + + def configure(self, default_settings=global_settings, **options): + """ + Called to manually configure the settings. The 'default_settings' + parameter sets where to retrieve any unspecified values from (its + argument must support attribute access (__getattr__)). + """ + if self._wrapped is not empty: + raise RuntimeError("Settings already configured.") + holder = UserSettingsHolder(default_settings) + for name, value in options.items(): + if not name.isupper(): + raise TypeError("Setting %r must be uppercase." % name) + setattr(holder, name, value) + self._wrapped = holder + + @staticmethod + def _add_script_prefix(value): + """ + Add SCRIPT_NAME prefix to relative paths. + + Useful when the app is being served at a subpath and manually prefixing + subpath to STATIC_URL and MEDIA_URL in settings is inconvenient. + """ + # Don't apply prefix to absolute paths and URLs. + if value.startswith(("http://", "https://", "/")): + return value + from django.urls import get_script_prefix + + return "%s%s" % (get_script_prefix(), value) + + @property + def configured(self): + """Return True if the settings have already been configured.""" + return self._wrapped is not empty + + def _show_deprecation_warning(self, message, category): + stack = traceback.extract_stack() + # Show a warning if the setting is used outside of Django. + # Stack index: -1 this line, -2 the property, -3 the + # LazyObject __getattribute__(), -4 the caller. + filename, _, _, _ = stack[-4] + if not filename.startswith(os.path.dirname(django.__file__)): + warnings.warn(message, category, stacklevel=2) + + # RemovedInDjango51Warning. + @property + def DEFAULT_FILE_STORAGE(self): + self._show_deprecation_warning( + DEFAULT_FILE_STORAGE_DEPRECATED_MSG, RemovedInDjango51Warning + ) + return self.__getattr__("DEFAULT_FILE_STORAGE") + + # RemovedInDjango51Warning. + @property + def STATICFILES_STORAGE(self): + self._show_deprecation_warning( + STATICFILES_STORAGE_DEPRECATED_MSG, RemovedInDjango51Warning + ) + return self.__getattr__("STATICFILES_STORAGE") + + +class Settings: + def __init__(self, settings_module): + # update this dict from global settings (but only for ALL_CAPS settings) + for setting in dir(global_settings): + if setting.isupper(): + setattr(self, setting, getattr(global_settings, setting)) + + # store the settings module in case someone later cares + self.SETTINGS_MODULE = settings_module + + mod = importlib.import_module(self.SETTINGS_MODULE) + + tuple_settings = ( + "ALLOWED_HOSTS", + "INSTALLED_APPS", + "TEMPLATE_DIRS", + "LOCALE_PATHS", + "SECRET_KEY_FALLBACKS", + ) + self._explicit_settings = set() + for setting in dir(mod): + if setting.isupper(): + setting_value = getattr(mod, setting) + + if setting in tuple_settings and not isinstance( + setting_value, (list, tuple) + ): + raise ImproperlyConfigured( + "The %s setting must be a list or a tuple." % setting + ) + setattr(self, setting, setting_value) + self._explicit_settings.add(setting) + + if self.is_overridden("FORMS_URLFIELD_ASSUME_HTTPS"): + warnings.warn( + FORMS_URLFIELD_ASSUME_HTTPS_DEPRECATED_MSG, + RemovedInDjango60Warning, + ) + + if hasattr(time, "tzset") and self.TIME_ZONE: + # When we can, attempt to validate the timezone. If we can't find + # this file, no check happens and it's harmless. + zoneinfo_root = Path("/usr/share/zoneinfo") + zone_info_file = zoneinfo_root.joinpath(*self.TIME_ZONE.split("/")) + if zoneinfo_root.exists() and not zone_info_file.exists(): + raise ValueError("Incorrect timezone setting: %s" % self.TIME_ZONE) + # Move the time zone info into os.environ. See ticket #2315 for why + # we don't do this unconditionally (breaks Windows). + os.environ["TZ"] = self.TIME_ZONE + time.tzset() + + if self.is_overridden("DEFAULT_FILE_STORAGE"): + if self.is_overridden("STORAGES"): + raise ImproperlyConfigured( + "DEFAULT_FILE_STORAGE/STORAGES are mutually exclusive." + ) + self.STORAGES = { + **self.STORAGES, + DEFAULT_STORAGE_ALIAS: {"BACKEND": self.DEFAULT_FILE_STORAGE}, + } + warnings.warn(DEFAULT_FILE_STORAGE_DEPRECATED_MSG, RemovedInDjango51Warning) + + if self.is_overridden("STATICFILES_STORAGE"): + if self.is_overridden("STORAGES"): + raise ImproperlyConfigured( + "STATICFILES_STORAGE/STORAGES are mutually exclusive." + ) + self.STORAGES = { + **self.STORAGES, + STATICFILES_STORAGE_ALIAS: {"BACKEND": self.STATICFILES_STORAGE}, + } + warnings.warn(STATICFILES_STORAGE_DEPRECATED_MSG, RemovedInDjango51Warning) + # RemovedInDjango51Warning. + if self.is_overridden("STORAGES"): + setattr( + self, + "DEFAULT_FILE_STORAGE", + self.STORAGES.get(DEFAULT_STORAGE_ALIAS, {}).get("BACKEND"), + ) + setattr( + self, + "STATICFILES_STORAGE", + self.STORAGES.get(STATICFILES_STORAGE_ALIAS, {}).get("BACKEND"), + ) + + def is_overridden(self, setting): + return setting in self._explicit_settings + + def __repr__(self): + return '<%(cls)s "%(settings_module)s">' % { + "cls": self.__class__.__name__, + "settings_module": self.SETTINGS_MODULE, + } + + +class UserSettingsHolder: + """Holder for user configured settings.""" + + # SETTINGS_MODULE doesn't make much sense in the manually configured + # (standalone) case. + SETTINGS_MODULE = None + + def __init__(self, default_settings): + """ + Requests for configuration variables not in this class are satisfied + from the module specified in default_settings (if possible). + """ + self.__dict__["_deleted"] = set() + self.default_settings = default_settings + + def __getattr__(self, name): + if not name.isupper() or name in self._deleted: + raise AttributeError + return getattr(self.default_settings, name) + + def __setattr__(self, name, value): + self._deleted.discard(name) + if name == "DEFAULT_FILE_STORAGE": + self.STORAGES[DEFAULT_STORAGE_ALIAS] = { + "BACKEND": self.DEFAULT_FILE_STORAGE + } + warnings.warn(DEFAULT_FILE_STORAGE_DEPRECATED_MSG, RemovedInDjango51Warning) + if name == "STATICFILES_STORAGE": + self.STORAGES[STATICFILES_STORAGE_ALIAS] = { + "BACKEND": self.STATICFILES_STORAGE + } + warnings.warn(STATICFILES_STORAGE_DEPRECATED_MSG, RemovedInDjango51Warning) + if name == "FORMS_URLFIELD_ASSUME_HTTPS": + warnings.warn( + FORMS_URLFIELD_ASSUME_HTTPS_DEPRECATED_MSG, + RemovedInDjango60Warning, + ) + super().__setattr__(name, value) + # RemovedInDjango51Warning. + if name == "STORAGES": + if default_file_storage := self.STORAGES.get(DEFAULT_STORAGE_ALIAS): + super().__setattr__( + "DEFAULT_FILE_STORAGE", default_file_storage.get("BACKEND") + ) + else: + self.STORAGES.setdefault( + DEFAULT_STORAGE_ALIAS, + {"BACKEND": "django.core.files.storage.FileSystemStorage"}, + ) + if staticfiles_storage := self.STORAGES.get(STATICFILES_STORAGE_ALIAS): + super().__setattr__( + "STATICFILES_STORAGE", staticfiles_storage.get("BACKEND") + ) + else: + self.STORAGES.setdefault( + STATICFILES_STORAGE_ALIAS, + { + "BACKEND": ( + "django.contrib.staticfiles.storage.StaticFilesStorage" + ), + }, + ) + + def __delattr__(self, name): + self._deleted.add(name) + if hasattr(self, name): + super().__delattr__(name) + + def __dir__(self): + return sorted( + s + for s in [*self.__dict__, *dir(self.default_settings)] + if s not in self._deleted + ) + + def is_overridden(self, setting): + deleted = setting in self._deleted + set_locally = setting in self.__dict__ + set_on_default = getattr( + self.default_settings, "is_overridden", lambda s: False + )(setting) + return deleted or set_locally or set_on_default + + def __repr__(self): + return "<%(cls)s>" % { + "cls": self.__class__.__name__, + } + + +settings = LazySettings() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/app_template/__init__.py-tpl b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/app_template/__init__.py-tpl new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/app_template/admin.py-tpl b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/app_template/admin.py-tpl new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/app_template/admin.py-tpl @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/app_template/apps.py-tpl b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/app_template/apps.py-tpl new file mode 100644 index 0000000..b705352 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/app_template/apps.py-tpl @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class {{ camel_case_app_name }}Config(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = '{{ app_name }}' diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/app_template/migrations/__init__.py-tpl b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/app_template/migrations/__init__.py-tpl new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/app_template/models.py-tpl b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/app_template/models.py-tpl new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/app_template/models.py-tpl @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/app_template/tests.py-tpl b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/app_template/tests.py-tpl new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/app_template/tests.py-tpl @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/app_template/views.py-tpl b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/app_template/views.py-tpl new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/app_template/views.py-tpl @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/global_settings.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/global_settings.py new file mode 100644 index 0000000..18253b0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/global_settings.py @@ -0,0 +1,673 @@ +""" +Default Django settings. Override these with settings in the module pointed to +by the DJANGO_SETTINGS_MODULE environment variable. +""" + + +# This is defined here as a do-nothing function because we can't import +# django.utils.translation -- that module depends on the settings. +def gettext_noop(s): + return s + + +#################### +# CORE # +#################### + +DEBUG = False + +# Whether the framework should propagate raw exceptions rather than catching +# them. This is useful under some testing situations and should never be used +# on a live site. +DEBUG_PROPAGATE_EXCEPTIONS = False + +# People who get code error notifications. In the format +# [('Full Name', 'email@example.com'), ('Full Name', 'anotheremail@example.com')] +ADMINS = [] + +# List of IP addresses, as strings, that: +# * See debug comments, when DEBUG is true +# * Receive x-headers +INTERNAL_IPS = [] + +# Hosts/domain names that are valid for this site. +# "*" matches anything, ".example.com" matches example.com and all subdomains +ALLOWED_HOSTS = [] + +# Local time zone for this installation. All choices can be found here: +# https://en.wikipedia.org/wiki/List_of_tz_zones_by_name (although not all +# systems may support all possibilities). When USE_TZ is True, this is +# interpreted as the default user time zone. +TIME_ZONE = "America/Chicago" + +# If you set this to True, Django will use timezone-aware datetimes. +USE_TZ = True + +# Language code for this installation. All choices can be found here: +# http://www.i18nguy.com/unicode/language-identifiers.html +LANGUAGE_CODE = "en-us" + +# Languages we provide translations for, out of the box. +LANGUAGES = [ + ("af", gettext_noop("Afrikaans")), + ("ar", gettext_noop("Arabic")), + ("ar-dz", gettext_noop("Algerian Arabic")), + ("ast", gettext_noop("Asturian")), + ("az", gettext_noop("Azerbaijani")), + ("bg", gettext_noop("Bulgarian")), + ("be", gettext_noop("Belarusian")), + ("bn", gettext_noop("Bengali")), + ("br", gettext_noop("Breton")), + ("bs", gettext_noop("Bosnian")), + ("ca", gettext_noop("Catalan")), + ("ckb", gettext_noop("Central Kurdish (Sorani)")), + ("cs", gettext_noop("Czech")), + ("cy", gettext_noop("Welsh")), + ("da", gettext_noop("Danish")), + ("de", gettext_noop("German")), + ("dsb", gettext_noop("Lower Sorbian")), + ("el", gettext_noop("Greek")), + ("en", gettext_noop("English")), + ("en-au", gettext_noop("Australian English")), + ("en-gb", gettext_noop("British English")), + ("eo", gettext_noop("Esperanto")), + ("es", gettext_noop("Spanish")), + ("es-ar", gettext_noop("Argentinian Spanish")), + ("es-co", gettext_noop("Colombian Spanish")), + ("es-mx", gettext_noop("Mexican Spanish")), + ("es-ni", gettext_noop("Nicaraguan Spanish")), + ("es-ve", gettext_noop("Venezuelan Spanish")), + ("et", gettext_noop("Estonian")), + ("eu", gettext_noop("Basque")), + ("fa", gettext_noop("Persian")), + ("fi", gettext_noop("Finnish")), + ("fr", gettext_noop("French")), + ("fy", gettext_noop("Frisian")), + ("ga", gettext_noop("Irish")), + ("gd", gettext_noop("Scottish Gaelic")), + ("gl", gettext_noop("Galician")), + ("he", gettext_noop("Hebrew")), + ("hi", gettext_noop("Hindi")), + ("hr", gettext_noop("Croatian")), + ("hsb", gettext_noop("Upper Sorbian")), + ("hu", gettext_noop("Hungarian")), + ("hy", gettext_noop("Armenian")), + ("ia", gettext_noop("Interlingua")), + ("id", gettext_noop("Indonesian")), + ("ig", gettext_noop("Igbo")), + ("io", gettext_noop("Ido")), + ("is", gettext_noop("Icelandic")), + ("it", gettext_noop("Italian")), + ("ja", gettext_noop("Japanese")), + ("ka", gettext_noop("Georgian")), + ("kab", gettext_noop("Kabyle")), + ("kk", gettext_noop("Kazakh")), + ("km", gettext_noop("Khmer")), + ("kn", gettext_noop("Kannada")), + ("ko", gettext_noop("Korean")), + ("ky", gettext_noop("Kyrgyz")), + ("lb", gettext_noop("Luxembourgish")), + ("lt", gettext_noop("Lithuanian")), + ("lv", gettext_noop("Latvian")), + ("mk", gettext_noop("Macedonian")), + ("ml", gettext_noop("Malayalam")), + ("mn", gettext_noop("Mongolian")), + ("mr", gettext_noop("Marathi")), + ("ms", gettext_noop("Malay")), + ("my", gettext_noop("Burmese")), + ("nb", gettext_noop("Norwegian Bokmål")), + ("ne", gettext_noop("Nepali")), + ("nl", gettext_noop("Dutch")), + ("nn", gettext_noop("Norwegian Nynorsk")), + ("os", gettext_noop("Ossetic")), + ("pa", gettext_noop("Punjabi")), + ("pl", gettext_noop("Polish")), + ("pt", gettext_noop("Portuguese")), + ("pt-br", gettext_noop("Brazilian Portuguese")), + ("ro", gettext_noop("Romanian")), + ("ru", gettext_noop("Russian")), + ("sk", gettext_noop("Slovak")), + ("sl", gettext_noop("Slovenian")), + ("sq", gettext_noop("Albanian")), + ("sr", gettext_noop("Serbian")), + ("sr-latn", gettext_noop("Serbian Latin")), + ("sv", gettext_noop("Swedish")), + ("sw", gettext_noop("Swahili")), + ("ta", gettext_noop("Tamil")), + ("te", gettext_noop("Telugu")), + ("tg", gettext_noop("Tajik")), + ("th", gettext_noop("Thai")), + ("tk", gettext_noop("Turkmen")), + ("tr", gettext_noop("Turkish")), + ("tt", gettext_noop("Tatar")), + ("udm", gettext_noop("Udmurt")), + ("ug", gettext_noop("Uyghur")), + ("uk", gettext_noop("Ukrainian")), + ("ur", gettext_noop("Urdu")), + ("uz", gettext_noop("Uzbek")), + ("vi", gettext_noop("Vietnamese")), + ("zh-hans", gettext_noop("Simplified Chinese")), + ("zh-hant", gettext_noop("Traditional Chinese")), +] + +# Languages using BiDi (right-to-left) layout +LANGUAGES_BIDI = ["he", "ar", "ar-dz", "ckb", "fa", "ug", "ur"] + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = True +LOCALE_PATHS = [] + +# Settings for language cookie +LANGUAGE_COOKIE_NAME = "django_language" +LANGUAGE_COOKIE_AGE = None +LANGUAGE_COOKIE_DOMAIN = None +LANGUAGE_COOKIE_PATH = "/" +LANGUAGE_COOKIE_SECURE = False +LANGUAGE_COOKIE_HTTPONLY = False +LANGUAGE_COOKIE_SAMESITE = None + +# Not-necessarily-technical managers of the site. They get broken link +# notifications and other various emails. +MANAGERS = ADMINS + +# Default charset to use for all HttpResponse objects, if a MIME type isn't +# manually specified. It's used to construct the Content-Type header. +DEFAULT_CHARSET = "utf-8" + +# Email address that error messages come from. +SERVER_EMAIL = "root@localhost" + +# Database connection info. If left empty, will default to the dummy backend. +DATABASES = {} + +# Classes used to implement DB routing behavior. +DATABASE_ROUTERS = [] + +# The email backend to use. For possible shortcuts see django.core.mail. +# The default is to use the SMTP backend. +# Third-party backends can be specified by providing a Python path +# to a module that defines an EmailBackend class. +EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" + +# Host for sending email. +EMAIL_HOST = "localhost" + +# Port for sending email. +EMAIL_PORT = 25 + +# Whether to send SMTP 'Date' header in the local time zone or in UTC. +EMAIL_USE_LOCALTIME = False + +# Optional SMTP authentication information for EMAIL_HOST. +EMAIL_HOST_USER = "" +EMAIL_HOST_PASSWORD = "" +EMAIL_USE_TLS = False +EMAIL_USE_SSL = False +EMAIL_SSL_CERTFILE = None +EMAIL_SSL_KEYFILE = None +EMAIL_TIMEOUT = None + +# List of strings representing installed apps. +INSTALLED_APPS = [] + +TEMPLATES = [] + +# Default form rendering class. +FORM_RENDERER = "django.forms.renderers.DjangoTemplates" + +# RemovedInDjango60Warning: It's a transitional setting helpful in early +# adoption of "https" as the new default value of forms.URLField.assume_scheme. +# Set to True to assume "https" during the Django 5.x release cycle. +FORMS_URLFIELD_ASSUME_HTTPS = False + +# Default email address to use for various automated correspondence from +# the site managers. +DEFAULT_FROM_EMAIL = "webmaster@localhost" + +# Subject-line prefix for email messages send with django.core.mail.mail_admins +# or ...mail_managers. Make sure to include the trailing space. +EMAIL_SUBJECT_PREFIX = "[Django] " + +# Whether to append trailing slashes to URLs. +APPEND_SLASH = True + +# Whether to prepend the "www." subdomain to URLs that don't have it. +PREPEND_WWW = False + +# Override the server-derived value of SCRIPT_NAME +FORCE_SCRIPT_NAME = None + +# List of compiled regular expression objects representing User-Agent strings +# that are not allowed to visit any page, systemwide. Use this for bad +# robots/crawlers. Here are a few examples: +# import re +# DISALLOWED_USER_AGENTS = [ +# re.compile(r'^NaverBot.*'), +# re.compile(r'^EmailSiphon.*'), +# re.compile(r'^SiteSucker.*'), +# re.compile(r'^sohu-search'), +# ] +DISALLOWED_USER_AGENTS = [] + +ABSOLUTE_URL_OVERRIDES = {} + +# List of compiled regular expression objects representing URLs that need not +# be reported by BrokenLinkEmailsMiddleware. Here are a few examples: +# import re +# IGNORABLE_404_URLS = [ +# re.compile(r'^/apple-touch-icon.*\.png$'), +# re.compile(r'^/favicon.ico$'), +# re.compile(r'^/robots.txt$'), +# re.compile(r'^/phpmyadmin/'), +# re.compile(r'\.(cgi|php|pl)$'), +# ] +IGNORABLE_404_URLS = [] + +# A secret key for this particular Django installation. Used in secret-key +# hashing algorithms. Set this in your settings, or Django will complain +# loudly. +SECRET_KEY = "" + +# List of secret keys used to verify the validity of signatures. This allows +# secret key rotation. +SECRET_KEY_FALLBACKS = [] + +# Default file storage mechanism that holds media. +DEFAULT_FILE_STORAGE = "django.core.files.storage.FileSystemStorage" + +STORAGES = { + "default": { + "BACKEND": "django.core.files.storage.FileSystemStorage", + }, + "staticfiles": { + "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage", + }, +} + +# Absolute filesystem path to the directory that will hold user-uploaded files. +# Example: "/var/www/example.com/media/" +MEDIA_ROOT = "" + +# URL that handles the media served from MEDIA_ROOT. +# Examples: "http://example.com/media/", "http://media.example.com/" +MEDIA_URL = "" + +# Absolute path to the directory static files should be collected to. +# Example: "/var/www/example.com/static/" +STATIC_ROOT = None + +# URL that handles the static files served from STATIC_ROOT. +# Example: "http://example.com/static/", "http://static.example.com/" +STATIC_URL = None + +# List of upload handler classes to be applied in order. +FILE_UPLOAD_HANDLERS = [ + "django.core.files.uploadhandler.MemoryFileUploadHandler", + "django.core.files.uploadhandler.TemporaryFileUploadHandler", +] + +# Maximum size, in bytes, of a request before it will be streamed to the +# file system instead of into memory. +FILE_UPLOAD_MAX_MEMORY_SIZE = 2621440 # i.e. 2.5 MB + +# Maximum size in bytes of request data (excluding file uploads) that will be +# read before a SuspiciousOperation (RequestDataTooBig) is raised. +DATA_UPLOAD_MAX_MEMORY_SIZE = 2621440 # i.e. 2.5 MB + +# Maximum number of GET/POST parameters that will be read before a +# SuspiciousOperation (TooManyFieldsSent) is raised. +DATA_UPLOAD_MAX_NUMBER_FIELDS = 1000 + +# Maximum number of files encoded in a multipart upload that will be read +# before a SuspiciousOperation (TooManyFilesSent) is raised. +DATA_UPLOAD_MAX_NUMBER_FILES = 100 + +# Directory in which upload streamed files will be temporarily saved. A value of +# `None` will make Django use the operating system's default temporary directory +# (i.e. "/tmp" on *nix systems). +FILE_UPLOAD_TEMP_DIR = None + +# The numeric mode to set newly-uploaded files to. The value should be a mode +# you'd pass directly to os.chmod; see +# https://docs.python.org/library/os.html#files-and-directories. +FILE_UPLOAD_PERMISSIONS = 0o644 + +# The numeric mode to assign to newly-created directories, when uploading files. +# The value should be a mode as you'd pass to os.chmod; +# see https://docs.python.org/library/os.html#files-and-directories. +FILE_UPLOAD_DIRECTORY_PERMISSIONS = None + +# Python module path where user will place custom format definition. +# The directory where this setting is pointing should contain subdirectories +# named as the locales, containing a formats.py file +# (i.e. "myproject.locale" for myproject/locale/en/formats.py etc. use) +FORMAT_MODULE_PATH = None + +# Default formatting for date objects. See all available format strings here: +# https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "N j, Y" + +# Default formatting for datetime objects. See all available format strings here: +# https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATETIME_FORMAT = "N j, Y, P" + +# Default formatting for time objects. See all available format strings here: +# https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +TIME_FORMAT = "P" + +# Default formatting for date objects when only the year and month are relevant. +# See all available format strings here: +# https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +YEAR_MONTH_FORMAT = "F Y" + +# Default formatting for date objects when only the month and day are relevant. +# See all available format strings here: +# https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +MONTH_DAY_FORMAT = "F j" + +# Default short formatting for date objects. See all available format strings here: +# https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +SHORT_DATE_FORMAT = "m/d/Y" + +# Default short formatting for datetime objects. +# See all available format strings here: +# https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +SHORT_DATETIME_FORMAT = "m/d/Y P" + +# Default formats to be used when parsing dates from input boxes, in order +# See all available format string here: +# https://docs.python.org/library/datetime.html#strftime-behavior +# * Note that these format strings are different from the ones to display dates +DATE_INPUT_FORMATS = [ + "%Y-%m-%d", # '2006-10-25' + "%m/%d/%Y", # '10/25/2006' + "%m/%d/%y", # '10/25/06' + "%b %d %Y", # 'Oct 25 2006' + "%b %d, %Y", # 'Oct 25, 2006' + "%d %b %Y", # '25 Oct 2006' + "%d %b, %Y", # '25 Oct, 2006' + "%B %d %Y", # 'October 25 2006' + "%B %d, %Y", # 'October 25, 2006' + "%d %B %Y", # '25 October 2006' + "%d %B, %Y", # '25 October, 2006' +] + +# Default formats to be used when parsing times from input boxes, in order +# See all available format string here: +# https://docs.python.org/library/datetime.html#strftime-behavior +# * Note that these format strings are different from the ones to display dates +TIME_INPUT_FORMATS = [ + "%H:%M:%S", # '14:30:59' + "%H:%M:%S.%f", # '14:30:59.000200' + "%H:%M", # '14:30' +] + +# Default formats to be used when parsing dates and times from input boxes, +# in order +# See all available format string here: +# https://docs.python.org/library/datetime.html#strftime-behavior +# * Note that these format strings are different from the ones to display dates +DATETIME_INPUT_FORMATS = [ + "%Y-%m-%d %H:%M:%S", # '2006-10-25 14:30:59' + "%Y-%m-%d %H:%M:%S.%f", # '2006-10-25 14:30:59.000200' + "%Y-%m-%d %H:%M", # '2006-10-25 14:30' + "%m/%d/%Y %H:%M:%S", # '10/25/2006 14:30:59' + "%m/%d/%Y %H:%M:%S.%f", # '10/25/2006 14:30:59.000200' + "%m/%d/%Y %H:%M", # '10/25/2006 14:30' + "%m/%d/%y %H:%M:%S", # '10/25/06 14:30:59' + "%m/%d/%y %H:%M:%S.%f", # '10/25/06 14:30:59.000200' + "%m/%d/%y %H:%M", # '10/25/06 14:30' +] + +# First day of week, to be used on calendars +# 0 means Sunday, 1 means Monday... +FIRST_DAY_OF_WEEK = 0 + +# Decimal separator symbol +DECIMAL_SEPARATOR = "." + +# Boolean that sets whether to add thousand separator when formatting numbers +USE_THOUSAND_SEPARATOR = False + +# Number of digits that will be together, when splitting them by +# THOUSAND_SEPARATOR. 0 means no grouping, 3 means splitting by thousands... +NUMBER_GROUPING = 0 + +# Thousand separator symbol +THOUSAND_SEPARATOR = "," + +# The tablespaces to use for each model when not specified otherwise. +DEFAULT_TABLESPACE = "" +DEFAULT_INDEX_TABLESPACE = "" + +# Default primary key field type. +DEFAULT_AUTO_FIELD = "django.db.models.AutoField" + +# Default X-Frame-Options header value +X_FRAME_OPTIONS = "DENY" + +USE_X_FORWARDED_HOST = False +USE_X_FORWARDED_PORT = False + +# The Python dotted path to the WSGI application that Django's internal server +# (runserver) will use. If `None`, the return value of +# 'django.core.wsgi.get_wsgi_application' is used, thus preserving the same +# behavior as previous versions of Django. Otherwise this should point to an +# actual WSGI application object. +WSGI_APPLICATION = None + +# If your Django app is behind a proxy that sets a header to specify secure +# connections, AND that proxy ensures that user-submitted headers with the +# same name are ignored (so that people can't spoof it), set this value to +# a tuple of (header_name, header_value). For any requests that come in with +# that header/value, request.is_secure() will return True. +# WARNING! Only set this if you fully understand what you're doing. Otherwise, +# you may be opening yourself up to a security risk. +SECURE_PROXY_SSL_HEADER = None + +############## +# MIDDLEWARE # +############## + +# List of middleware to use. Order is important; in the request phase, these +# middleware will be applied in the order given, and in the response +# phase the middleware will be applied in reverse order. +MIDDLEWARE = [] + +############ +# SESSIONS # +############ + +# Cache to store session data if using the cache session backend. +SESSION_CACHE_ALIAS = "default" +# Cookie name. This can be whatever you want. +SESSION_COOKIE_NAME = "sessionid" +# Age of cookie, in seconds (default: 2 weeks). +SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2 +# A string like "example.com", or None for standard domain cookie. +SESSION_COOKIE_DOMAIN = None +# Whether the session cookie should be secure (https:// only). +SESSION_COOKIE_SECURE = False +# The path of the session cookie. +SESSION_COOKIE_PATH = "/" +# Whether to use the HttpOnly flag. +SESSION_COOKIE_HTTPONLY = True +# Whether to set the flag restricting cookie leaks on cross-site requests. +# This can be 'Lax', 'Strict', 'None', or False to disable the flag. +SESSION_COOKIE_SAMESITE = "Lax" +# Whether to save the session data on every request. +SESSION_SAVE_EVERY_REQUEST = False +# Whether a user's session cookie expires when the web browser is closed. +SESSION_EXPIRE_AT_BROWSER_CLOSE = False +# The module to store session data +SESSION_ENGINE = "django.contrib.sessions.backends.db" +# Directory to store session files if using the file session module. If None, +# the backend will use a sensible default. +SESSION_FILE_PATH = None +# class to serialize session data +SESSION_SERIALIZER = "django.contrib.sessions.serializers.JSONSerializer" + +######### +# CACHE # +######### + +# The cache backends to use. +CACHES = { + "default": { + "BACKEND": "django.core.cache.backends.locmem.LocMemCache", + } +} +CACHE_MIDDLEWARE_KEY_PREFIX = "" +CACHE_MIDDLEWARE_SECONDS = 600 +CACHE_MIDDLEWARE_ALIAS = "default" + +################## +# AUTHENTICATION # +################## + +AUTH_USER_MODEL = "auth.User" + +AUTHENTICATION_BACKENDS = ["django.contrib.auth.backends.ModelBackend"] + +LOGIN_URL = "/accounts/login/" + +LOGIN_REDIRECT_URL = "/accounts/profile/" + +LOGOUT_REDIRECT_URL = None + +# The number of seconds a password reset link is valid for (default: 3 days). +PASSWORD_RESET_TIMEOUT = 60 * 60 * 24 * 3 + +# the first hasher in this list is the preferred algorithm. any +# password using different algorithms will be converted automatically +# upon login +PASSWORD_HASHERS = [ + "django.contrib.auth.hashers.PBKDF2PasswordHasher", + "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher", + "django.contrib.auth.hashers.Argon2PasswordHasher", + "django.contrib.auth.hashers.BCryptSHA256PasswordHasher", + "django.contrib.auth.hashers.ScryptPasswordHasher", +] + +AUTH_PASSWORD_VALIDATORS = [] + +########### +# SIGNING # +########### + +SIGNING_BACKEND = "django.core.signing.TimestampSigner" + +######## +# CSRF # +######## + +# Dotted path to callable to be used as view when a request is +# rejected by the CSRF middleware. +CSRF_FAILURE_VIEW = "django.views.csrf.csrf_failure" + +# Settings for CSRF cookie. +CSRF_COOKIE_NAME = "csrftoken" +CSRF_COOKIE_AGE = 60 * 60 * 24 * 7 * 52 +CSRF_COOKIE_DOMAIN = None +CSRF_COOKIE_PATH = "/" +CSRF_COOKIE_SECURE = False +CSRF_COOKIE_HTTPONLY = False +CSRF_COOKIE_SAMESITE = "Lax" +CSRF_HEADER_NAME = "HTTP_X_CSRFTOKEN" +CSRF_TRUSTED_ORIGINS = [] +CSRF_USE_SESSIONS = False + +############ +# MESSAGES # +############ + +# Class to use as messages backend +MESSAGE_STORAGE = "django.contrib.messages.storage.fallback.FallbackStorage" + +# Default values of MESSAGE_LEVEL and MESSAGE_TAGS are defined within +# django.contrib.messages to avoid imports in this settings file. + +########### +# LOGGING # +########### + +# The callable to use to configure logging +LOGGING_CONFIG = "logging.config.dictConfig" + +# Custom logging configuration. +LOGGING = {} + +# Default exception reporter class used in case none has been +# specifically assigned to the HttpRequest instance. +DEFAULT_EXCEPTION_REPORTER = "django.views.debug.ExceptionReporter" + +# Default exception reporter filter class used in case none has been +# specifically assigned to the HttpRequest instance. +DEFAULT_EXCEPTION_REPORTER_FILTER = "django.views.debug.SafeExceptionReporterFilter" + +########### +# TESTING # +########### + +# The name of the class to use to run the test suite +TEST_RUNNER = "django.test.runner.DiscoverRunner" + +# Apps that don't need to be serialized at test database creation time +# (only apps with migrations are to start with) +TEST_NON_SERIALIZED_APPS = [] + +############ +# FIXTURES # +############ + +# The list of directories to search for fixtures +FIXTURE_DIRS = [] + +############### +# STATICFILES # +############### + +# A list of locations of additional static files +STATICFILES_DIRS = [] + +# The default file storage backend used during the build process +STATICFILES_STORAGE = "django.contrib.staticfiles.storage.StaticFilesStorage" + +# List of finder classes that know how to find static files in +# various locations. +STATICFILES_FINDERS = [ + "django.contrib.staticfiles.finders.FileSystemFinder", + "django.contrib.staticfiles.finders.AppDirectoriesFinder", + # 'django.contrib.staticfiles.finders.DefaultStorageFinder', +] + +############## +# MIGRATIONS # +############## + +# Migration module overrides for apps, by app label. +MIGRATION_MODULES = {} + +################# +# SYSTEM CHECKS # +################# + +# List of all issues generated by system checks that should be silenced. Light +# issues like warnings, infos or debugs will not generate a message. Silencing +# serious issues like errors and criticals does not result in hiding the +# message, but Django will not stop you from e.g. running server. +SILENCED_SYSTEM_CHECKS = [] + +####################### +# SECURITY MIDDLEWARE # +####################### +SECURE_CONTENT_TYPE_NOSNIFF = True +SECURE_CROSS_ORIGIN_OPENER_POLICY = "same-origin" +SECURE_HSTS_INCLUDE_SUBDOMAINS = False +SECURE_HSTS_PRELOAD = False +SECURE_HSTS_SECONDS = 0 +SECURE_REDIRECT_EXEMPT = [] +SECURE_REFERRER_POLICY = "same-origin" +SECURE_SSL_HOST = None +SECURE_SSL_REDIRECT = False diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/__init__.py new file mode 100644 index 0000000..1b21ffd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/__init__.py @@ -0,0 +1,629 @@ +""" +LANG_INFO is a dictionary structure to provide meta information about languages. + +About name_local: capitalize it as if your language name was appearing +inside a sentence in your language. +The 'fallback' key can be used to specify a special fallback logic which doesn't +follow the traditional 'fr-ca' -> 'fr' fallback logic. +""" + +LANG_INFO = { + "af": { + "bidi": False, + "code": "af", + "name": "Afrikaans", + "name_local": "Afrikaans", + }, + "ar": { + "bidi": True, + "code": "ar", + "name": "Arabic", + "name_local": "العربيّة", + }, + "ar-dz": { + "bidi": True, + "code": "ar-dz", + "name": "Algerian Arabic", + "name_local": "العربية الجزائرية", + }, + "ast": { + "bidi": False, + "code": "ast", + "name": "Asturian", + "name_local": "asturianu", + }, + "az": { + "bidi": True, + "code": "az", + "name": "Azerbaijani", + "name_local": "Azərbaycanca", + }, + "be": { + "bidi": False, + "code": "be", + "name": "Belarusian", + "name_local": "беларуская", + }, + "bg": { + "bidi": False, + "code": "bg", + "name": "Bulgarian", + "name_local": "български", + }, + "bn": { + "bidi": False, + "code": "bn", + "name": "Bengali", + "name_local": "বাংলা", + }, + "br": { + "bidi": False, + "code": "br", + "name": "Breton", + "name_local": "brezhoneg", + }, + "bs": { + "bidi": False, + "code": "bs", + "name": "Bosnian", + "name_local": "bosanski", + }, + "ca": { + "bidi": False, + "code": "ca", + "name": "Catalan", + "name_local": "català", + }, + "ckb": { + "bidi": True, + "code": "ckb", + "name": "Central Kurdish (Sorani)", + "name_local": "کوردی", + }, + "cs": { + "bidi": False, + "code": "cs", + "name": "Czech", + "name_local": "česky", + }, + "cy": { + "bidi": False, + "code": "cy", + "name": "Welsh", + "name_local": "Cymraeg", + }, + "da": { + "bidi": False, + "code": "da", + "name": "Danish", + "name_local": "dansk", + }, + "de": { + "bidi": False, + "code": "de", + "name": "German", + "name_local": "Deutsch", + }, + "dsb": { + "bidi": False, + "code": "dsb", + "name": "Lower Sorbian", + "name_local": "dolnoserbski", + }, + "el": { + "bidi": False, + "code": "el", + "name": "Greek", + "name_local": "Ελληνικά", + }, + "en": { + "bidi": False, + "code": "en", + "name": "English", + "name_local": "English", + }, + "en-au": { + "bidi": False, + "code": "en-au", + "name": "Australian English", + "name_local": "Australian English", + }, + "en-gb": { + "bidi": False, + "code": "en-gb", + "name": "British English", + "name_local": "British English", + }, + "eo": { + "bidi": False, + "code": "eo", + "name": "Esperanto", + "name_local": "Esperanto", + }, + "es": { + "bidi": False, + "code": "es", + "name": "Spanish", + "name_local": "español", + }, + "es-ar": { + "bidi": False, + "code": "es-ar", + "name": "Argentinian Spanish", + "name_local": "español de Argentina", + }, + "es-co": { + "bidi": False, + "code": "es-co", + "name": "Colombian Spanish", + "name_local": "español de Colombia", + }, + "es-mx": { + "bidi": False, + "code": "es-mx", + "name": "Mexican Spanish", + "name_local": "español de Mexico", + }, + "es-ni": { + "bidi": False, + "code": "es-ni", + "name": "Nicaraguan Spanish", + "name_local": "español de Nicaragua", + }, + "es-ve": { + "bidi": False, + "code": "es-ve", + "name": "Venezuelan Spanish", + "name_local": "español de Venezuela", + }, + "et": { + "bidi": False, + "code": "et", + "name": "Estonian", + "name_local": "eesti", + }, + "eu": { + "bidi": False, + "code": "eu", + "name": "Basque", + "name_local": "Basque", + }, + "fa": { + "bidi": True, + "code": "fa", + "name": "Persian", + "name_local": "فارسی", + }, + "fi": { + "bidi": False, + "code": "fi", + "name": "Finnish", + "name_local": "suomi", + }, + "fr": { + "bidi": False, + "code": "fr", + "name": "French", + "name_local": "français", + }, + "fy": { + "bidi": False, + "code": "fy", + "name": "Frisian", + "name_local": "frysk", + }, + "ga": { + "bidi": False, + "code": "ga", + "name": "Irish", + "name_local": "Gaeilge", + }, + "gd": { + "bidi": False, + "code": "gd", + "name": "Scottish Gaelic", + "name_local": "Gàidhlig", + }, + "gl": { + "bidi": False, + "code": "gl", + "name": "Galician", + "name_local": "galego", + }, + "he": { + "bidi": True, + "code": "he", + "name": "Hebrew", + "name_local": "עברית", + }, + "hi": { + "bidi": False, + "code": "hi", + "name": "Hindi", + "name_local": "हिंदी", + }, + "hr": { + "bidi": False, + "code": "hr", + "name": "Croatian", + "name_local": "Hrvatski", + }, + "hsb": { + "bidi": False, + "code": "hsb", + "name": "Upper Sorbian", + "name_local": "hornjoserbsce", + }, + "hu": { + "bidi": False, + "code": "hu", + "name": "Hungarian", + "name_local": "Magyar", + }, + "hy": { + "bidi": False, + "code": "hy", + "name": "Armenian", + "name_local": "հայերեն", + }, + "ia": { + "bidi": False, + "code": "ia", + "name": "Interlingua", + "name_local": "Interlingua", + }, + "io": { + "bidi": False, + "code": "io", + "name": "Ido", + "name_local": "ido", + }, + "id": { + "bidi": False, + "code": "id", + "name": "Indonesian", + "name_local": "Bahasa Indonesia", + }, + "ig": { + "bidi": False, + "code": "ig", + "name": "Igbo", + "name_local": "Asụsụ Ìgbò", + }, + "is": { + "bidi": False, + "code": "is", + "name": "Icelandic", + "name_local": "Íslenska", + }, + "it": { + "bidi": False, + "code": "it", + "name": "Italian", + "name_local": "italiano", + }, + "ja": { + "bidi": False, + "code": "ja", + "name": "Japanese", + "name_local": "日本語", + }, + "ka": { + "bidi": False, + "code": "ka", + "name": "Georgian", + "name_local": "ქართული", + }, + "kab": { + "bidi": False, + "code": "kab", + "name": "Kabyle", + "name_local": "taqbaylit", + }, + "kk": { + "bidi": False, + "code": "kk", + "name": "Kazakh", + "name_local": "Қазақ", + }, + "km": { + "bidi": False, + "code": "km", + "name": "Khmer", + "name_local": "Khmer", + }, + "kn": { + "bidi": False, + "code": "kn", + "name": "Kannada", + "name_local": "Kannada", + }, + "ko": { + "bidi": False, + "code": "ko", + "name": "Korean", + "name_local": "한국어", + }, + "ky": { + "bidi": False, + "code": "ky", + "name": "Kyrgyz", + "name_local": "Кыргызча", + }, + "lb": { + "bidi": False, + "code": "lb", + "name": "Luxembourgish", + "name_local": "Lëtzebuergesch", + }, + "lt": { + "bidi": False, + "code": "lt", + "name": "Lithuanian", + "name_local": "Lietuviškai", + }, + "lv": { + "bidi": False, + "code": "lv", + "name": "Latvian", + "name_local": "latviešu", + }, + "mk": { + "bidi": False, + "code": "mk", + "name": "Macedonian", + "name_local": "Македонски", + }, + "ml": { + "bidi": False, + "code": "ml", + "name": "Malayalam", + "name_local": "മലയാളം", + }, + "mn": { + "bidi": False, + "code": "mn", + "name": "Mongolian", + "name_local": "Mongolian", + }, + "mr": { + "bidi": False, + "code": "mr", + "name": "Marathi", + "name_local": "मराठी", + }, + "ms": { + "bidi": False, + "code": "ms", + "name": "Malay", + "name_local": "Bahasa Melayu", + }, + "my": { + "bidi": False, + "code": "my", + "name": "Burmese", + "name_local": "မြန်မာဘာသာ", + }, + "nb": { + "bidi": False, + "code": "nb", + "name": "Norwegian Bokmal", + "name_local": "norsk (bokmål)", + }, + "ne": { + "bidi": False, + "code": "ne", + "name": "Nepali", + "name_local": "नेपाली", + }, + "nl": { + "bidi": False, + "code": "nl", + "name": "Dutch", + "name_local": "Nederlands", + }, + "nn": { + "bidi": False, + "code": "nn", + "name": "Norwegian Nynorsk", + "name_local": "norsk (nynorsk)", + }, + "no": { + "bidi": False, + "code": "no", + "name": "Norwegian", + "name_local": "norsk", + }, + "os": { + "bidi": False, + "code": "os", + "name": "Ossetic", + "name_local": "Ирон", + }, + "pa": { + "bidi": False, + "code": "pa", + "name": "Punjabi", + "name_local": "Punjabi", + }, + "pl": { + "bidi": False, + "code": "pl", + "name": "Polish", + "name_local": "polski", + }, + "pt": { + "bidi": False, + "code": "pt", + "name": "Portuguese", + "name_local": "Português", + }, + "pt-br": { + "bidi": False, + "code": "pt-br", + "name": "Brazilian Portuguese", + "name_local": "Português Brasileiro", + }, + "ro": { + "bidi": False, + "code": "ro", + "name": "Romanian", + "name_local": "Română", + }, + "ru": { + "bidi": False, + "code": "ru", + "name": "Russian", + "name_local": "Русский", + }, + "sk": { + "bidi": False, + "code": "sk", + "name": "Slovak", + "name_local": "Slovensky", + }, + "sl": { + "bidi": False, + "code": "sl", + "name": "Slovenian", + "name_local": "Slovenščina", + }, + "sq": { + "bidi": False, + "code": "sq", + "name": "Albanian", + "name_local": "shqip", + }, + "sr": { + "bidi": False, + "code": "sr", + "name": "Serbian", + "name_local": "српски", + }, + "sr-latn": { + "bidi": False, + "code": "sr-latn", + "name": "Serbian Latin", + "name_local": "srpski (latinica)", + }, + "sv": { + "bidi": False, + "code": "sv", + "name": "Swedish", + "name_local": "svenska", + }, + "sw": { + "bidi": False, + "code": "sw", + "name": "Swahili", + "name_local": "Kiswahili", + }, + "ta": { + "bidi": False, + "code": "ta", + "name": "Tamil", + "name_local": "தமிழ்", + }, + "te": { + "bidi": False, + "code": "te", + "name": "Telugu", + "name_local": "తెలుగు", + }, + "tg": { + "bidi": False, + "code": "tg", + "name": "Tajik", + "name_local": "тоҷикӣ", + }, + "th": { + "bidi": False, + "code": "th", + "name": "Thai", + "name_local": "ภาษาไทย", + }, + "tk": { + "bidi": False, + "code": "tk", + "name": "Turkmen", + "name_local": "Türkmençe", + }, + "tr": { + "bidi": False, + "code": "tr", + "name": "Turkish", + "name_local": "Türkçe", + }, + "tt": { + "bidi": False, + "code": "tt", + "name": "Tatar", + "name_local": "Татарча", + }, + "udm": { + "bidi": False, + "code": "udm", + "name": "Udmurt", + "name_local": "Удмурт", + }, + "ug": { + "bidi": True, + "code": "ug", + "name": "Uyghur", + "name_local": "ئۇيغۇرچە", + }, + "uk": { + "bidi": False, + "code": "uk", + "name": "Ukrainian", + "name_local": "Українська", + }, + "ur": { + "bidi": True, + "code": "ur", + "name": "Urdu", + "name_local": "اردو", + }, + "uz": { + "bidi": False, + "code": "uz", + "name": "Uzbek", + "name_local": "oʻzbek tili", + }, + "vi": { + "bidi": False, + "code": "vi", + "name": "Vietnamese", + "name_local": "Tiếng Việt", + }, + "zh-cn": { + "fallback": ["zh-hans"], + }, + "zh-hans": { + "bidi": False, + "code": "zh-hans", + "name": "Simplified Chinese", + "name_local": "简体中文", + }, + "zh-hant": { + "bidi": False, + "code": "zh-hant", + "name": "Traditional Chinese", + "name_local": "繁體中文", + }, + "zh-hk": { + "fallback": ["zh-hant"], + }, + "zh-mo": { + "fallback": ["zh-hant"], + }, + "zh-my": { + "fallback": ["zh-hans"], + }, + "zh-sg": { + "fallback": ["zh-hans"], + }, + "zh-tw": { + "fallback": ["zh-hant"], + }, +} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/af/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/af/LC_MESSAGES/django.mo new file mode 100644 index 0000000..efb8b0f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/af/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/af/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/af/LC_MESSAGES/django.po new file mode 100644 index 0000000..405b9f6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/af/LC_MESSAGES/django.po @@ -0,0 +1,1318 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# F Wolff , 2019-2020,2022-2023 +# Stephen Cox , 2011-2012 +# unklphil , 2014,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: F Wolff , 2019-2020,2022-2023\n" +"Language-Team: Afrikaans (http://app.transifex.com/django/django/language/" +"af/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: af\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Afrikaans" + +msgid "Arabic" +msgstr "Arabies" + +msgid "Algerian Arabic" +msgstr "Algeriese Arabies" + +msgid "Asturian" +msgstr "Asturies" + +msgid "Azerbaijani" +msgstr "Aserbeidjans" + +msgid "Bulgarian" +msgstr "Bulgaars" + +msgid "Belarusian" +msgstr "Wit-Russies" + +msgid "Bengali" +msgstr "Bengali" + +msgid "Breton" +msgstr "Bretons" + +msgid "Bosnian" +msgstr "Bosnies" + +msgid "Catalan" +msgstr "Katalaans" + +msgid "Central Kurdish (Sorani)" +msgstr "" + +msgid "Czech" +msgstr "Tsjeggies" + +msgid "Welsh" +msgstr "Wallies" + +msgid "Danish" +msgstr "Deens" + +msgid "German" +msgstr "Duits" + +msgid "Lower Sorbian" +msgstr "Neder-Sorbies" + +msgid "Greek" +msgstr "Grieks" + +msgid "English" +msgstr "Engels" + +msgid "Australian English" +msgstr "Australiese Engels" + +msgid "British English" +msgstr "Britse Engels" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Spaans" + +msgid "Argentinian Spanish" +msgstr "Argentynse Spaans" + +msgid "Colombian Spanish" +msgstr "Kolombiaanse Spaans" + +msgid "Mexican Spanish" +msgstr "Meksikaanse Spaans" + +msgid "Nicaraguan Spanish" +msgstr "Nicaraguaanse Spaans" + +msgid "Venezuelan Spanish" +msgstr "Venezolaanse Spaans" + +msgid "Estonian" +msgstr "Estnies" + +msgid "Basque" +msgstr "Baskies" + +msgid "Persian" +msgstr "Persies" + +msgid "Finnish" +msgstr "Fins" + +msgid "French" +msgstr "Fraans" + +msgid "Frisian" +msgstr "Fries" + +msgid "Irish" +msgstr "Iers" + +msgid "Scottish Gaelic" +msgstr "Skots-Gaelies" + +msgid "Galician" +msgstr "Galicies" + +msgid "Hebrew" +msgstr "Hebreeus" + +msgid "Hindi" +msgstr "Hindoe" + +msgid "Croatian" +msgstr "Kroaties" + +msgid "Upper Sorbian" +msgstr "Opper-Sorbies" + +msgid "Hungarian" +msgstr "Hongaars" + +msgid "Armenian" +msgstr "Armeens" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonesies" + +msgid "Igbo" +msgstr "" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Yslands" + +msgid "Italian" +msgstr "Italiaans" + +msgid "Japanese" +msgstr "Japannees" + +msgid "Georgian" +msgstr "Georgian" + +msgid "Kabyle" +msgstr "Kabilies" + +msgid "Kazakh" +msgstr "Kazakh" + +msgid "Khmer" +msgstr "Khmer" + +msgid "Kannada" +msgstr "Kannada" + +msgid "Korean" +msgstr "Koreaans" + +msgid "Kyrgyz" +msgstr "" + +msgid "Luxembourgish" +msgstr "Luxemburgs" + +msgid "Lithuanian" +msgstr "Litaus" + +msgid "Latvian" +msgstr "Lets" + +msgid "Macedonian" +msgstr "Macedonies" + +msgid "Malayalam" +msgstr "Malabaars" + +msgid "Mongolian" +msgstr "Mongools" + +msgid "Marathi" +msgstr "Marathi" + +msgid "Malay" +msgstr "Maleisies" + +msgid "Burmese" +msgstr "Birmaans" + +msgid "Norwegian Bokmål" +msgstr "Noorweegse Bokmål" + +msgid "Nepali" +msgstr "Nepalees" + +msgid "Dutch" +msgstr "Nederlands" + +msgid "Norwegian Nynorsk" +msgstr "Noorweegse Nynorsk" + +msgid "Ossetic" +msgstr "Osseties" + +msgid "Punjabi" +msgstr "Punjabi" + +msgid "Polish" +msgstr "Pools" + +msgid "Portuguese" +msgstr "Portugees" + +msgid "Brazilian Portuguese" +msgstr "Brasiliaanse Portugees" + +msgid "Romanian" +msgstr "Roemeens" + +msgid "Russian" +msgstr "Russiese" + +msgid "Slovak" +msgstr "Slowaaks" + +msgid "Slovenian" +msgstr "Sloweens" + +msgid "Albanian" +msgstr "Albanees" + +msgid "Serbian" +msgstr "Serwies" + +msgid "Serbian Latin" +msgstr "Serwies Latyns" + +msgid "Swedish" +msgstr "Sweeds" + +msgid "Swahili" +msgstr "Swahili" + +msgid "Tamil" +msgstr "Tamil" + +msgid "Telugu" +msgstr "Teloegoe" + +msgid "Tajik" +msgstr "" + +msgid "Thai" +msgstr "Thai" + +msgid "Turkmen" +msgstr "" + +msgid "Turkish" +msgstr "Turks" + +msgid "Tatar" +msgstr "Tataars" + +msgid "Udmurt" +msgstr "Oedmoerts" + +msgid "Uyghur" +msgstr "" + +msgid "Ukrainian" +msgstr "Oekraïens" + +msgid "Urdu" +msgstr "Oerdoe" + +msgid "Uzbek" +msgstr "Oesbekies " + +msgid "Vietnamese" +msgstr "Viëtnamees" + +msgid "Simplified Chinese" +msgstr "Vereenvoudigde Sjinees" + +msgid "Traditional Chinese" +msgstr "Tradisionele Sjinees" + +msgid "Messages" +msgstr "Boodskappe" + +msgid "Site Maps" +msgstr "Werfkaarte" + +msgid "Static Files" +msgstr "Statiese lêers" + +msgid "Syndication" +msgstr "Sindikasie" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Daai bladsynommer is nie ’n heelgetal nie" + +msgid "That page number is less than 1" +msgstr "Daai bladsynommer is minder as 1" + +msgid "That page contains no results" +msgstr "Daai bladsy bevat geen resultate nie" + +msgid "Enter a valid value." +msgstr "Gee ’n geldige waarde." + +msgid "Enter a valid URL." +msgstr "Gee ’n geldige URL." + +msgid "Enter a valid integer." +msgstr "Gee ’n geldige heelgetal." + +msgid "Enter a valid email address." +msgstr "Gee ’n geldige e-posadres." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Gee ’n geldige “slak” in wat bestaan ​​uit letters, syfers, onderstreep of " +"koppelteken." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Gee ’n geldige “slak” in wat bestaan ​​uit Unicode-letters, syfers, " +"onderstreep of koppelteken." + +msgid "Enter a valid IPv4 address." +msgstr "Gee ’n geldige IPv4-adres." + +msgid "Enter a valid IPv6 address." +msgstr "Gee ’n geldige IPv6-adres." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Gee ’n geldige IPv4- of IPv6-adres." + +msgid "Enter only digits separated by commas." +msgstr "Gee slegs syfers wat deur kommas geskei is." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Maak seker dat hierdie waarde %(limit_value)s is (dit is %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Maak seker dat hierdie waarde kleiner of gelyk is aan %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Maak seker dat hierdie waarde groter of gelyk is aan %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" +"Maak seker dat hierdie waarde ’n veelvoud is van stapgrootte %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Maak seker hierdie waarde het ten minste %(limit_value)d karakter (dit het " +"%(show_value)d)." +msgstr[1] "" +"Maak seker hierdie waarde het ten minste %(limit_value)d karakters (dit het " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Maak seker hierdie waarde het op die meeste %(limit_value)d karakter (dit " +"het %(show_value)d)." +msgstr[1] "" +"Maak seker hierdie waarde het op die meeste %(limit_value)d karakters (dit " +"het %(show_value)d)." + +msgid "Enter a number." +msgstr "Gee ’n getal." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Maak seker dat daar nie meer as %(max)s syfer in totaal is nie." +msgstr[1] "Maak seker dat daar nie meer as %(max)s syfers in totaal is nie." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Maak seker dat daar nie meer as %(max)s desimale plek is nie." +msgstr[1] "Maak seker dat daar nie meer as %(max)s desimale plekke is nie." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Maak seker dat daar nie meer as %(max)s syfer voor die desimale punt is nie." +msgstr[1] "" +"Maak seker dat daar nie meer as %(max)s syfers voor die desimale punt is nie." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Lêeruitbreiding “%(extension)s” word nie toegelaat nie. Toegelate " +"uitbreidings is: %(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Nul-karakters word nie toegelaat nie." + +msgid "and" +msgstr "en" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s met hierdie %(field_labels)s bestaan alreeds." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Beperking “%(name)s” word verbreek." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Waarde %(value)r is nie ’n geldige keuse nie." + +msgid "This field cannot be null." +msgstr "Hierdie veld kan nie nil wees nie." + +msgid "This field cannot be blank." +msgstr "Hierdie veld kan nie leeg wees nie." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s met hierdie %(field_label)s bestaan ​​alreeds." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s moet uniek wees per %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Veld van tipe: %(field_type)s " + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "“%(value)s” waarde moet óf True óf False wees." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "Die waarde “%(value)s” moet True, False of None wees." + +msgid "Boolean (Either True or False)" +msgstr "Boole (True of False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "String (hoogstens %(max_length)s karakters)" + +msgid "String (unlimited)" +msgstr "String (onbeperk)" + +msgid "Comma-separated integers" +msgstr "Heelgetalle geskei met kommas" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"Die waarde “%(value)s” het ’n ongeldige datumformaat. Dit moet in die " +"formaat JJJJ-MM-DD wees." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"Die waarde “%(value)s” het die korrekte formaat (JJJJ-MM-DD), maar dit is ’n " +"ongeldige datum." + +msgid "Date (without time)" +msgstr "Datum (sonder die tyd)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"Die waarde “%(value)s” se formaat is ongeldig. Dit moet in die formaat JJJJ-" +"MM-DD HH:MM[:ss[.uuuuuu]][TZ] wees." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"Die waarde “%(value)s” het die korrekte formaat (JJJJ-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ]) maar dit is ’n ongeldige datum/tyd." + +msgid "Date (with time)" +msgstr "Datum (met die tyd)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "“%(value)s”-waarde moet ’n desimale getal wees." + +msgid "Decimal number" +msgstr "Desimale getal" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"Die waarde “%(value)s” het ’n ongeldige formaat. Dit moet in die formaat " +"[DD] [HH:[MM:]]ss[.uuuuuu] wees." + +msgid "Duration" +msgstr "Duur" + +msgid "Email address" +msgstr "E-posadres" + +msgid "File path" +msgstr "Lêerpad" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "Die waarde “%(value)s” moet ’n dryfpuntgetal wees." + +msgid "Floating point number" +msgstr "Dryfpuntgetal" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "Die waarde “%(value)s” moet ’n heelgetal wees." + +msgid "Integer" +msgstr "Heelgetal" + +msgid "Big (8 byte) integer" +msgstr "Groot (8 greep) heelgetal" + +msgid "Small integer" +msgstr "Klein heelgetal" + +msgid "IPv4 address" +msgstr "IPv4-adres" + +msgid "IP address" +msgstr "IP-adres" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "“%(value)s”-waarde moet een wees uit None, True of False." + +msgid "Boolean (Either True, False or None)" +msgstr "Boole (True, False, of None)" + +msgid "Positive big integer" +msgstr "Positiewe groot heelgetal" + +msgid "Positive integer" +msgstr "Positiewe heelgetal" + +msgid "Positive small integer" +msgstr "Klein positiewe heelgetal" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (tot en met %(max_length)s karakters)" + +msgid "Text" +msgstr "Teks" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"“%(value)s”-waarde het ’n ongeldige formaat. Dit moet geformateer word as HH:" +"MM[:ss[.uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"Die waarde “%(value)s” het die regte formaat (HH:MM[:ss[.uuuuuu]]) maar is " +"nie ’n geldige tyd nie." + +msgid "Time" +msgstr "Tyd" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Rou binêre data" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "“%(value)s” is nie ’n geldige UUID nie." + +msgid "Universally unique identifier" +msgstr "Universeel unieke identifiseerder" + +msgid "File" +msgstr "Lêer" + +msgid "Image" +msgstr "Prent" + +msgid "A JSON object" +msgstr "’n JSON-objek" + +msgid "Value must be valid JSON." +msgstr "Waarde moet geldige JSON wees." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(model)s-objek met %(field)s %(value)r bestaan nie." + +msgid "Foreign Key (type determined by related field)" +msgstr "Vreemde sleutel (tipe bepaal deur verwante veld)" + +msgid "One-to-one relationship" +msgstr "Een-tot-een-verhouding" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s-verwantskap" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s-verwantskappe" + +msgid "Many-to-many relationship" +msgstr "Baie-tot-baie-verwantskap" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Dié veld is verpligtend." + +msgid "Enter a whole number." +msgstr "Tik ’n heelgetal in." + +msgid "Enter a valid date." +msgstr "Tik ’n geldige datum in." + +msgid "Enter a valid time." +msgstr "Tik ’n geldige tyd in." + +msgid "Enter a valid date/time." +msgstr "Tik ’n geldige datum/tyd in." + +msgid "Enter a valid duration." +msgstr "Tik ’n geldige tydsduur in." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Die aantal dae moet tussen {min_days} en {max_days} wees." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" +"Geen lêer is ingedien nie. Maak seker die koderingtipe op die vorm is reg." + +msgid "No file was submitted." +msgstr "Geen lêer is ingedien nie." + +msgid "The submitted file is empty." +msgstr "Die ingediende lêer is leeg." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Maak seker hierdie lêernaam het hoogstens %(max)d karakter (dit het " +"%(length)d)." +msgstr[1] "" +"Maak seker hierdie lêernaam het hoogstens %(max)d karakters (dit het " +"%(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Dien die lêer in óf merk die Maak skoon-boksie, nie altwee nie." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Laai ’n geldige prent. Die lêer wat jy opgelaai het, is nie ’n prent nie of " +"dit is ’n korrupte prent." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Kies ’n geldige keuse. %(value)s is nie een van die beskikbare keuses nie." + +msgid "Enter a list of values." +msgstr "Tik ’n lys waardes in." + +msgid "Enter a complete value." +msgstr "Tik ’n volledige waarde in." + +msgid "Enter a valid UUID." +msgstr "Tik ’n geldig UUID in." + +msgid "Enter a valid JSON." +msgstr "Gee geldige JSON." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Versteekte veld %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Dien asseblief hoogstens %(num)d vorm in." +msgstr[1] "Dien asseblief hoogstens %(num)d vorms in." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Dien asseblief ten minste %(num)d vorm in." +msgstr[1] "Dien asseblief ten minste %(num)d vorms in." + +msgid "Order" +msgstr "Orde" + +msgid "Delete" +msgstr "Verwyder" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Korrigeer die dubbele data vir %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Korrigeer die dubbele data vir %(field)s, dit moet uniek wees." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Korrigeer die dubbele data vir %(field_name)s, dit moet uniek wees vir die " +"%(lookup)s in %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Korrigeer die dubbele waardes hieronder." + +msgid "The inline value did not match the parent instance." +msgstr "Die waarde inlyn pas nie by die ouerobjek nie." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Kies ’n geldige keuse. Daardie keuse is nie een van die beskikbare keuses " +"nie." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "“%(pk)s” is nie ’n geldige waarde nie." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Maak skoon" + +msgid "Currently" +msgstr "Tans" + +msgid "Change" +msgstr "Verander" + +msgid "Unknown" +msgstr "Onbekend" + +msgid "Yes" +msgstr "Ja" + +msgid "No" +msgstr "Nee" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "ja,nee,miskien" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d greep" +msgstr[1] "%(size)d grepe" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "nm." + +msgid "a.m." +msgstr "vm." + +msgid "PM" +msgstr "NM" + +msgid "AM" +msgstr "VM" + +msgid "midnight" +msgstr "middernag" + +msgid "noon" +msgstr "middag" + +msgid "Monday" +msgstr "Maandag" + +msgid "Tuesday" +msgstr "Dinsdag" + +msgid "Wednesday" +msgstr "Woensdag" + +msgid "Thursday" +msgstr "Donderdag" + +msgid "Friday" +msgstr "Vrydag" + +msgid "Saturday" +msgstr "Saterdag" + +msgid "Sunday" +msgstr "Sondag" + +msgid "Mon" +msgstr "Ma" + +msgid "Tue" +msgstr "Di" + +msgid "Wed" +msgstr "Wo" + +msgid "Thu" +msgstr "Do" + +msgid "Fri" +msgstr "Vr" + +msgid "Sat" +msgstr "Sa" + +msgid "Sun" +msgstr "So" + +msgid "January" +msgstr "Januarie" + +msgid "February" +msgstr "Februarie" + +msgid "March" +msgstr "Maart" + +msgid "April" +msgstr "April" + +msgid "May" +msgstr "Mei" + +msgid "June" +msgstr "Junie" + +msgid "July" +msgstr "Julie" + +msgid "August" +msgstr "Augustus" + +msgid "September" +msgstr "September" + +msgid "October" +msgstr "Oktober" + +msgid "November" +msgstr "November" + +msgid "December" +msgstr "Desember" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mrt" + +msgid "apr" +msgstr "apr" + +msgid "may" +msgstr "mei" + +msgid "jun" +msgstr "jun" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "aug" + +msgid "sep" +msgstr "sept" + +msgid "oct" +msgstr "okt" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "des" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Maart" + +msgctxt "abbrev. month" +msgid "April" +msgstr "April" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Mei" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Junie" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Julie" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Aug." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Sept." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Okt." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Des." + +msgctxt "alt. month" +msgid "January" +msgstr "Januarie" + +msgctxt "alt. month" +msgid "February" +msgstr "Februarie" + +msgctxt "alt. month" +msgid "March" +msgstr "Maart" + +msgctxt "alt. month" +msgid "April" +msgstr "April" + +msgctxt "alt. month" +msgid "May" +msgstr "Mei" + +msgctxt "alt. month" +msgid "June" +msgstr "Junie" + +msgctxt "alt. month" +msgid "July" +msgstr "Julie" + +msgctxt "alt. month" +msgid "August" +msgstr "Augustus" + +msgctxt "alt. month" +msgid "September" +msgstr "September" + +msgctxt "alt. month" +msgid "October" +msgstr "Oktober" + +msgctxt "alt. month" +msgid "November" +msgstr "November" + +msgctxt "alt. month" +msgid "December" +msgstr "Desember" + +msgid "This is not a valid IPv6 address." +msgstr "Hierdie is nie ’n geldige IPv6-adres nie." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "of" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d jaar" +msgstr[1] "%(num)d jaar" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d maand" +msgstr[1] "%(num)d maande" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d week" +msgstr[1] "%(num)d weke" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dag" +msgstr[1] "%(num)d dae" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d uur" +msgstr[1] "%(num)d uur" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuut" +msgstr[1] "%(num)d minute" + +msgid "Forbidden" +msgstr "Verbode" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF-verifikasie het misluk. Versoek is laat val." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"U sien hierdie boodskap omdat dié werf ’n CSRF-koekie benodig wanneer vorms " +"ingedien word. Dié koekie word vir sekuriteitsredes benodig om te te " +"verseker dat u blaaier nie deur derde partye gekaap word nie." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "Meer inligting is beskikbaar met DEBUG=True." + +msgid "No year specified" +msgstr "Geen jaar gespesifiseer nie" + +msgid "Date out of range" +msgstr "Datum buite omvang" + +msgid "No month specified" +msgstr "Geen maand gespesifiseer nie" + +msgid "No day specified" +msgstr "Geen dag gespesifiseer nie" + +msgid "No week specified" +msgstr "Geen week gespesifiseer nie" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Geen %(verbose_name_plural)s beskikbaar nie" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Toekomstige %(verbose_name_plural)s is nie beskikbaar nie, omdat " +"%(class_name)s.allow_future vals is." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Ongeldige datumstring “%(datestr)s” gegewe die formaat “%(format)s”" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Geen %(verbose_name)s gevind vir die soektog" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Ongeldige bladsy (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Gidsindekse word nie hier toegelaat nie." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "“%(path)s” bestaan nie." + +#, python-format +msgid "Index of %(directory)s" +msgstr "Indeks van %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Die installasie was suksesvol! Geluk!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Sien die vrystellingsnotas vir Django " +"%(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"U sien dié bladsy omdat DEBUG=True in die settings-lêer is en geen URL’e " +"opgestel is nie." + +msgid "Django Documentation" +msgstr "Django-dokumentasie" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "Kom aan die gang met Django" + +msgid "Django Community" +msgstr "Django-gemeenskap" + +msgid "Connect, get help, or contribute" +msgstr "Kontak, kry hulp om dra by" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ar/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ar/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f0a0412 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ar/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ar/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ar/LC_MESSAGES/django.po new file mode 100644 index 0000000..25a491b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ar/LC_MESSAGES/django.po @@ -0,0 +1,1389 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bashar Al-Abdulhadi, 2015-2016,2020-2021 +# Bashar Al-Abdulhadi, 2014 +# Eyad Toma , 2013-2014 +# Jannis Leidel , 2011 +# Mariusz Felisiak , 2021 +# Muaaz Alsaied, 2020 +# Omar Al-Ithawi , 2020 +# Ossama Khayat , 2011 +# Tony xD , 2020 +# صفا الفليج , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2021-11-24 16:27+0000\n" +"Last-Translator: Mariusz Felisiak \n" +"Language-Team: Arabic (http://www.transifex.com/django/django/language/ar/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +msgid "Afrikaans" +msgstr "الإفريقية" + +msgid "Arabic" +msgstr "العربيّة" + +msgid "Algerian Arabic" +msgstr "عربي جزائري" + +msgid "Asturian" +msgstr "الأسترية" + +msgid "Azerbaijani" +msgstr "الأذربيجانية" + +msgid "Bulgarian" +msgstr "البلغاريّة" + +msgid "Belarusian" +msgstr "البيلاروسية" + +msgid "Bengali" +msgstr "البنغاليّة" + +msgid "Breton" +msgstr "البريتونية" + +msgid "Bosnian" +msgstr "البوسنيّة" + +msgid "Catalan" +msgstr "الكتلانيّة" + +msgid "Czech" +msgstr "التشيكيّة" + +msgid "Welsh" +msgstr "الويلز" + +msgid "Danish" +msgstr "الدنماركيّة" + +msgid "German" +msgstr "الألمانيّة" + +msgid "Lower Sorbian" +msgstr "الصربية السفلى" + +msgid "Greek" +msgstr "اليونانيّة" + +msgid "English" +msgstr "الإنجليزيّة" + +msgid "Australian English" +msgstr "الإنجليزية الإسترالية" + +msgid "British English" +msgstr "الإنجليزيّة البريطانيّة" + +msgid "Esperanto" +msgstr "الاسبرانتو" + +msgid "Spanish" +msgstr "الإسبانيّة" + +msgid "Argentinian Spanish" +msgstr "الأسبانية الأرجنتينية" + +msgid "Colombian Spanish" +msgstr "الكولومبية الإسبانية" + +msgid "Mexican Spanish" +msgstr "الأسبانية المكسيكية" + +msgid "Nicaraguan Spanish" +msgstr "الإسبانية النيكاراغوية" + +msgid "Venezuelan Spanish" +msgstr "الإسبانية الفنزويلية" + +msgid "Estonian" +msgstr "الإستونيّة" + +msgid "Basque" +msgstr "الباسك" + +msgid "Persian" +msgstr "الفارسيّة" + +msgid "Finnish" +msgstr "الفنلنديّة" + +msgid "French" +msgstr "الفرنسيّة" + +msgid "Frisian" +msgstr "الفريزيّة" + +msgid "Irish" +msgstr "الإيرلنديّة" + +msgid "Scottish Gaelic" +msgstr "الغيلية الأسكتلندية" + +msgid "Galician" +msgstr "الجليقيّة" + +msgid "Hebrew" +msgstr "العبريّة" + +msgid "Hindi" +msgstr "الهندية" + +msgid "Croatian" +msgstr "الكرواتيّة" + +msgid "Upper Sorbian" +msgstr "الصربية العليا" + +msgid "Hungarian" +msgstr "الهنغاريّة" + +msgid "Armenian" +msgstr "الأرمنية" + +msgid "Interlingua" +msgstr "اللغة الوسيطة" + +msgid "Indonesian" +msgstr "الإندونيسيّة" + +msgid "Igbo" +msgstr "الإيبو" + +msgid "Ido" +msgstr "ايدو" + +msgid "Icelandic" +msgstr "الآيسلنديّة" + +msgid "Italian" +msgstr "الإيطاليّة" + +msgid "Japanese" +msgstr "اليابانيّة" + +msgid "Georgian" +msgstr "الجورجيّة" + +msgid "Kabyle" +msgstr "القبائل" + +msgid "Kazakh" +msgstr "الكازاخستانية" + +msgid "Khmer" +msgstr "الخمر" + +msgid "Kannada" +msgstr "الهنديّة (كنّادا)" + +msgid "Korean" +msgstr "الكوريّة" + +msgid "Kyrgyz" +msgstr "قيرغيز" + +msgid "Luxembourgish" +msgstr "اللوكسمبرجية" + +msgid "Lithuanian" +msgstr "اللتوانيّة" + +msgid "Latvian" +msgstr "اللاتفيّة" + +msgid "Macedonian" +msgstr "المقدونيّة" + +msgid "Malayalam" +msgstr "المايالام" + +msgid "Mongolian" +msgstr "المنغوليّة" + +msgid "Marathi" +msgstr "المهاراتية" + +msgid "Malay" +msgstr "" + +msgid "Burmese" +msgstr "البورمية" + +msgid "Norwegian Bokmål" +msgstr "النرويجية" + +msgid "Nepali" +msgstr "النيبالية" + +msgid "Dutch" +msgstr "الهولنديّة" + +msgid "Norwegian Nynorsk" +msgstr "النينورسك نرويجيّة" + +msgid "Ossetic" +msgstr "الأوسيتيكية" + +msgid "Punjabi" +msgstr "البنجابيّة" + +msgid "Polish" +msgstr "البولنديّة" + +msgid "Portuguese" +msgstr "البرتغاليّة" + +msgid "Brazilian Portuguese" +msgstr "البرتغاليّة البرازيليّة" + +msgid "Romanian" +msgstr "الرومانيّة" + +msgid "Russian" +msgstr "الروسيّة" + +msgid "Slovak" +msgstr "السلوفاكيّة" + +msgid "Slovenian" +msgstr "السلوفانيّة" + +msgid "Albanian" +msgstr "الألبانيّة" + +msgid "Serbian" +msgstr "الصربيّة" + +msgid "Serbian Latin" +msgstr "اللاتينيّة الصربيّة" + +msgid "Swedish" +msgstr "السويديّة" + +msgid "Swahili" +msgstr "السواحلية" + +msgid "Tamil" +msgstr "التاميل" + +msgid "Telugu" +msgstr "التيلوغو" + +msgid "Tajik" +msgstr "طاجيك" + +msgid "Thai" +msgstr "التايلنديّة" + +msgid "Turkmen" +msgstr "تركمان" + +msgid "Turkish" +msgstr "التركيّة" + +msgid "Tatar" +msgstr "التتاريية" + +msgid "Udmurt" +msgstr "الأدمرتية" + +msgid "Ukrainian" +msgstr "الأكرانيّة" + +msgid "Urdu" +msgstr "الأوردو" + +msgid "Uzbek" +msgstr "الأوزبكي" + +msgid "Vietnamese" +msgstr "الفيتناميّة" + +msgid "Simplified Chinese" +msgstr "الصينيّة المبسطة" + +msgid "Traditional Chinese" +msgstr "الصينيّة التقليدية" + +msgid "Messages" +msgstr "الرسائل" + +msgid "Site Maps" +msgstr "خرائط الموقع" + +msgid "Static Files" +msgstr "الملفات الثابتة" + +msgid "Syndication" +msgstr "توظيف النشر" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "..." + +msgid "That page number is not an integer" +msgstr "رقم الصفحة هذا ليس عدداً طبيعياً" + +msgid "That page number is less than 1" +msgstr "رقم الصفحة أقل من 1" + +msgid "That page contains no results" +msgstr "هذه الصفحة لا تحتوي على نتائج" + +msgid "Enter a valid value." +msgstr "أدخِل قيمة صحيحة." + +msgid "Enter a valid URL." +msgstr "أدخِل رابطًا صحيحًا." + +msgid "Enter a valid integer." +msgstr "أدخِل عدداً طبيعياً." + +msgid "Enter a valid email address." +msgstr "أدخِل عنوان بريد إلكتروني صحيح." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "أدخل اختصار 'slug' صحيح يتكوّن من أحرف، أرقام، شرطات سفلية وعاديّة." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"أدخل اختصار 'slug' صحيح يتكون من أحرف Unicode أو أرقام أو شرطات سفلية أو " +"واصلات." + +msgid "Enter a valid IPv4 address." +msgstr "أدخِل عنوان IPv4 صحيح." + +msgid "Enter a valid IPv6 address." +msgstr "أدخِل عنوان IPv6 صحيح." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "أدخِل عنوان IPv4 أو عنوان IPv6 صحيح." + +msgid "Enter only digits separated by commas." +msgstr "أدخِل فقط أرقامًا تفصلها الفواصل." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "تحقق من أن هذه القيمة هي %(limit_value)s (إنها %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "تحقق من أن تكون هذه القيمة أقل من %(limit_value)s أو مساوية لها." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "تحقق من أن تكون هذه القيمة أكثر من %(limit_value)s أو مساوية لها." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"تأكد أن هذه القيمة تحتوي على %(limit_value)d حرف أو رمز على الأقل (هي تحتوي " +"حالياً على %(show_value)d)." +msgstr[1] "" +"تأكد أن هذه القيمة تحتوي على حرف أو رمز %(limit_value)d على الأقل (هي تحتوي " +"حالياً على %(show_value)d)." +msgstr[2] "" +"تأكد أن هذه القيمة تحتوي على %(limit_value)d حرف و رمز على الأقل (هي تحتوي " +"حالياً على %(show_value)d)." +msgstr[3] "" +"تأكد أن هذه القيمة تحتوي على %(limit_value)d حرف أو رمز على الأقل (هي تحتوي " +"حالياً على %(show_value)d)." +msgstr[4] "" +"تأكد أن هذه القيمة تحتوي على %(limit_value)d حرف أو رمز على الأقل (هي تحتوي " +"حالياً على %(show_value)d)." +msgstr[5] "" +"تأكد أن هذه القيمة تحتوي على %(limit_value)d حرف أو رمز على الأقل (هي تحتوي " +"حالياً على %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"تأكد أن هذه القيمة تحتوي على %(limit_value)d حرف أو رمز على الأكثر (هي تحتوي " +"حالياً على %(show_value)d)." +msgstr[1] "" +"تأكد أن هذه القيمة تحتوي على حرف أو رمز %(limit_value)d على الأكثر (هي تحتوي " +"حالياً على %(show_value)d)." +msgstr[2] "" +"تأكد أن هذه القيمة تحتوي على %(limit_value)d حرف و رمز على الأكثر (هي تحتوي " +"حالياً على %(show_value)d)." +msgstr[3] "" +"تأكد أن هذه القيمة تحتوي على %(limit_value)d حرف أو رمز على الأكثر (هي تحتوي " +"حالياً على %(show_value)d)." +msgstr[4] "" +"تأكد أن هذه القيمة تحتوي على %(limit_value)d حرف أو رمز على الأكثر (هي تحتوي " +"حالياً على %(show_value)d)." +msgstr[5] "" +"تأكد أن هذه القيمة تحتوي على %(limit_value)d حرف أو رمز على الأكثر (هي تحتوي " +"حالياً على %(show_value)d)." + +msgid "Enter a number." +msgstr "أدخل رقماً." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "تحقق من أن تدخل %(max)s أرقام لا أكثر." +msgstr[1] "تحقق من أن تدخل رقم %(max)s لا أكثر." +msgstr[2] "تحقق من أن تدخل %(max)s رقمين لا أكثر." +msgstr[3] "تحقق من أن تدخل %(max)s أرقام لا أكثر." +msgstr[4] "تحقق من أن تدخل %(max)s أرقام لا أكثر." +msgstr[5] "تحقق من أن تدخل %(max)s أرقام لا أكثر." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "تحقق من أن تدخل %(max)s خانات عشرية لا أكثر." +msgstr[1] "تحقق من أن تدخل خانة %(max)s عشرية لا أكثر." +msgstr[2] "تحقق من أن تدخل %(max)s خانتين عشريتين لا أكثر." +msgstr[3] "تحقق من أن تدخل %(max)s خانات عشرية لا أكثر." +msgstr[4] "تحقق من أن تدخل %(max)s خانات عشرية لا أكثر." +msgstr[5] "تحقق من أن تدخل %(max)s خانات عشرية لا أكثر." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "تحقق من أن تدخل %(max)s أرقام قبل الفاصل العشري لا أكثر." +msgstr[1] "تحقق من أن تدخل رقم %(max)s قبل الفاصل العشري لا أكثر." +msgstr[2] "تحقق من أن تدخل %(max)s رقمين قبل الفاصل العشري لا أكثر." +msgstr[3] "تحقق من أن تدخل %(max)s أرقام قبل الفاصل العشري لا أكثر." +msgstr[4] "تحقق من أن تدخل %(max)s أرقام قبل الفاصل العشري لا أكثر." +msgstr[5] "تحقق من أن تدخل %(max)s أرقام قبل الفاصل العشري لا أكثر." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"امتداد الملف “%(extension)s” غير مسموح به. الامتدادات المسموح بها هي:" +"%(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "الأحرف الخالية غير مسموح بها." + +msgid "and" +msgstr "و" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s بهذا %(field_labels)s موجود سلفاً." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "القيمة %(value)r ليست خيارا صحيحاً." + +msgid "This field cannot be null." +msgstr "لا يمكن تعيين null كقيمة لهذا الحقل." + +msgid "This field cannot be blank." +msgstr "لا يمكن ترك هذا الحقل فارغاً." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "النموذج %(model_name)s والحقل %(field_label)s موجود مسبقاً." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s يجب أن يكون فريد لـ %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "حقل نوع: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "قيمة '%(value)s' يجب أن تكون True أو False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "قيمة “%(value)s” يجب أن تكون True , False أو None." + +msgid "Boolean (Either True or False)" +msgstr "ثنائي (إما True أو False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "سلسلة نص (%(max_length)s كحد أقصى)" + +msgid "Comma-separated integers" +msgstr "أرقام صحيحة مفصولة بفواصل" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"قيمة '%(value)s' ليست من بُنية تاريخ صحيحة. القيمة يجب ان تكون من البُنية YYYY-" +"MM-DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "قيمة '%(value)s' من بُنية صحيحة (YYYY-MM-DD) لكنها تحوي تاريخ غير صحيح." + +msgid "Date (without time)" +msgstr "التاريخ (دون الوقت)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"قيمة '%(value)s' ليست من بُنية صحيحة. القيمة يجب ان تكون من البُنية YYYY-MM-DD " +"HH:MM[:ss[.uuuuuu]][TZ] ." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"قيمة '%(value)s' من بُنية صحيحة (YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) لكنها " +"تحوي وقت و تاريخ غير صحيحين." + +msgid "Date (with time)" +msgstr "التاريخ (مع الوقت)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "قيمة '%(value)s' يجب ان تكون عدد عشري." + +msgid "Decimal number" +msgstr "رقم عشري" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"قيمة '%(value)s' ليست بنسق صحيح. القيمة يجب ان تكون من التنسيق ([DD] " +"[[HH:]MM:]ss[.uuuuuu])" + +msgid "Duration" +msgstr "المدّة" + +msgid "Email address" +msgstr "عنوان بريد إلكتروني" + +msgid "File path" +msgstr "مسار الملف" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "قيمة '%(value)s' يجب ان تكون عدد تعويم." + +msgid "Floating point number" +msgstr "رقم فاصلة عائمة" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "قيمة '%(value)s' يجب ان تكون عدد طبيعي." + +msgid "Integer" +msgstr "عدد صحيح" + +msgid "Big (8 byte) integer" +msgstr "عدد صحيح كبير (8 بايت)" + +msgid "Small integer" +msgstr "عدد صحيح صغير" + +msgid "IPv4 address" +msgstr "عنوان IPv4" + +msgid "IP address" +msgstr "عنوان IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "قيمة '%(value)s' يجب ان تكون None أو True أو False." + +msgid "Boolean (Either True, False or None)" +msgstr "ثنائي (إما True أو False أو None)" + +msgid "Positive big integer" +msgstr "عدد صحيح موجب كبير" + +msgid "Positive integer" +msgstr "عدد صحيح موجب" + +msgid "Positive small integer" +msgstr "عدد صحيح صغير موجب" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (حتى %(max_length)s)" + +msgid "Text" +msgstr "نص" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"قيمة '%(value)s' ليست بنسق صحيح. القيمة يجب ان تكون من التنسيق\n" +"HH:MM[:ss[.uuuuuu]]" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"قيمة '%(value)s' من بُنية صحيحة (HH:MM[:ss[.uuuuuu]]) لكنها تحوي وقت غير صحيح." + +msgid "Time" +msgstr "وقت" + +msgid "URL" +msgstr "رابط" + +msgid "Raw binary data" +msgstr "البيانات الثنائية الخام" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "القيمة \"%(value)s\" ليست UUID صالح." + +msgid "Universally unique identifier" +msgstr "معرّف فريد عالمياً" + +msgid "File" +msgstr "ملف" + +msgid "Image" +msgstr "صورة" + +msgid "A JSON object" +msgstr "كائن JSON" + +msgid "Value must be valid JSON." +msgstr "يجب أن تكون قيمة JSON صالحة." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "النموذج %(model)s ذو الحقل و القيمة %(field)s %(value)r غير موجود." + +msgid "Foreign Key (type determined by related field)" +msgstr "الحقل المرتبط (تم تحديد النوع وفقاً للحقل المرتبط)" + +msgid "One-to-one relationship" +msgstr "علاقة واحد إلى واحد" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s علاقة" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s علاقات" + +msgid "Many-to-many relationship" +msgstr "علاقة متعدد إلى متعدد" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "هذا الحقل مطلوب." + +msgid "Enter a whole number." +msgstr "أدخل رقما صحيحا." + +msgid "Enter a valid date." +msgstr "أدخل تاريخاً صحيحاً." + +msgid "Enter a valid time." +msgstr "أدخل وقتاً صحيحاً." + +msgid "Enter a valid date/time." +msgstr "أدخل تاريخاً/وقتاً صحيحاً." + +msgid "Enter a valid duration." +msgstr "أدخل مدّة صحيحة" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "يجب أن يكون عدد الأيام بين {min_days} و {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "لم يتم ارسال ملف، الرجاء التأكد من نوع ترميز الاستمارة." + +msgid "No file was submitted." +msgstr "لم يتم إرسال اي ملف." + +msgid "The submitted file is empty." +msgstr "الملف الذي قمت بإرساله فارغ." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"تأكد أن إسم هذا الملف يحتوي على %(max)d حرف على الأكثر (هو يحتوي الآن على " +"%(length)d حرف)." +msgstr[1] "" +"تأكد أن إسم هذا الملف يحتوي على حرف %(max)d على الأكثر (هو يحتوي الآن على " +"%(length)d حرف)." +msgstr[2] "" +"تأكد أن إسم هذا الملف يحتوي على %(max)d حرفين على الأكثر (هو يحتوي الآن على " +"%(length)d حرف)." +msgstr[3] "" +"تأكد أن إسم هذا الملف يحتوي على %(max)d حرف على الأكثر (هو يحتوي الآن على " +"%(length)d حرف)." +msgstr[4] "" +"تأكد أن إسم هذا الملف يحتوي على %(max)d حرف على الأكثر (هو يحتوي الآن على " +"%(length)d حرف)." +msgstr[5] "" +"تأكد أن إسم هذا الملف يحتوي على %(max)d حرف على الأكثر (هو يحتوي الآن على " +"%(length)d حرف)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "رجاءً أرسل ملف أو صح علامة صح عند مربع اختيار \"فارغ\"، وليس كلاهما." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"قم برفع صورة صحيحة، الملف الذي قمت برفعه إما أنه ليس ملفا لصورة أو أنه ملف " +"معطوب." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "انتق خياراً صحيحاً. %(value)s ليس أحد الخيارات المتاحة." + +msgid "Enter a list of values." +msgstr "أدخل قائمة من القيم." + +msgid "Enter a complete value." +msgstr "إدخال قيمة كاملة." + +msgid "Enter a valid UUID." +msgstr "أدخل قيمة UUID صحيحة." + +msgid "Enter a valid JSON." +msgstr "أدخل مدخل JSON صالح." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(الحقل الخفي %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"بيانات نموذج الإدارة مفقودة أو تم العبث بها. الحقول المفقودة: " +"%(field_names)s. قد تحتاج إلى تقديم تقرير خطأ إذا استمرت المشكلة." + +#, python-format +msgid "Please submit at most %d form." +msgid_plural "Please submit at most %d forms." +msgstr[0] "الرجاء إرسال %d إستمارة على الأكثر." +msgstr[1] "الرجاء إرسال %d إستمارة على الأكثر." +msgstr[2] "الرجاء إرسال %d إستمارة على الأكثر." +msgstr[3] "الرجاء إرسال %d إستمارة على الأكثر." +msgstr[4] "الرجاء إرسال %d إستمارة على الأكثر." +msgstr[5] "الرجاء إرسال %d إستمارة على الأكثر." + +#, python-format +msgid "Please submit at least %d form." +msgid_plural "Please submit at least %d forms." +msgstr[0] "الرجاء إرسال %d إستمارة على الأقل." +msgstr[1] "الرجاء إرسال %d إستمارة على الأقل." +msgstr[2] "الرجاء إرسال %d إستمارة على الأقل." +msgstr[3] "الرجاء إرسال %d إستمارة على الأقل." +msgstr[4] "الرجاء إرسال %d إستمارة على الأقل." +msgstr[5] "الرجاء إرسال %d إستمارة على الأقل." + +msgid "Order" +msgstr "الترتيب" + +msgid "Delete" +msgstr "احذف" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "رجاء صحّح بيانات %(field)s المتكررة." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "رجاء صحّح بيانات %(field)s المتكررة والتي يجب أن تكون مُميّزة." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"رجاء صحّح بيانات %(field_name)s المتكررة والتي يجب أن تكون مُميّزة لـ%(lookup)s " +"في %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "رجاءً صحّح القيم المُكرّرة أدناه." + +msgid "The inline value did not match the parent instance." +msgstr "لا تتطابق القيمة المضمنة مع المثيل الأصلي." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "انتق خياراً صحيحاً. اختيارك ليس أحد الخيارات المتاحة." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "\"%(pk)s\" ليست قيمة صالحة." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s لا يمكن تفسيرها في المنطقة الزمنية %(current_timezone)s; قد " +"تكون غامضة أو أنها غير موجودة." + +msgid "Clear" +msgstr "تفريغ" + +msgid "Currently" +msgstr "حالياً" + +msgid "Change" +msgstr "عدّل" + +msgid "Unknown" +msgstr "مجهول" + +msgid "Yes" +msgstr "نعم" + +msgid "No" +msgstr "لا" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "نعم,لا,ربما" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d بايت" +msgstr[1] "بايت واحد" +msgstr[2] "بايتان" +msgstr[3] "%(size)d بايتان" +msgstr[4] "%(size)d بايت" +msgstr[5] "%(size)d بايت" + +#, python-format +msgid "%s KB" +msgstr "%s ك.ب" + +#, python-format +msgid "%s MB" +msgstr "%s م.ب" + +#, python-format +msgid "%s GB" +msgstr "%s ج.ب" + +#, python-format +msgid "%s TB" +msgstr "%s ت.ب" + +#, python-format +msgid "%s PB" +msgstr "%s ب.ب" + +msgid "p.m." +msgstr "م" + +msgid "a.m." +msgstr "ص" + +msgid "PM" +msgstr "م" + +msgid "AM" +msgstr "ص" + +msgid "midnight" +msgstr "منتصف الليل" + +msgid "noon" +msgstr "ظهراً" + +msgid "Monday" +msgstr "الاثنين" + +msgid "Tuesday" +msgstr "الثلاثاء" + +msgid "Wednesday" +msgstr "الأربعاء" + +msgid "Thursday" +msgstr "الخميس" + +msgid "Friday" +msgstr "الجمعة" + +msgid "Saturday" +msgstr "السبت" + +msgid "Sunday" +msgstr "الأحد" + +msgid "Mon" +msgstr "إثنين" + +msgid "Tue" +msgstr "ثلاثاء" + +msgid "Wed" +msgstr "أربعاء" + +msgid "Thu" +msgstr "خميس" + +msgid "Fri" +msgstr "جمعة" + +msgid "Sat" +msgstr "سبت" + +msgid "Sun" +msgstr "أحد" + +msgid "January" +msgstr "يناير" + +msgid "February" +msgstr "فبراير" + +msgid "March" +msgstr "مارس" + +msgid "April" +msgstr "إبريل" + +msgid "May" +msgstr "مايو" + +msgid "June" +msgstr "يونيو" + +msgid "July" +msgstr "يوليو" + +msgid "August" +msgstr "أغسطس" + +msgid "September" +msgstr "سبتمبر" + +msgid "October" +msgstr "أكتوبر" + +msgid "November" +msgstr "نوفمبر" + +msgid "December" +msgstr "ديسمبر" + +msgid "jan" +msgstr "يناير" + +msgid "feb" +msgstr "فبراير" + +msgid "mar" +msgstr "مارس" + +msgid "apr" +msgstr "إبريل" + +msgid "may" +msgstr "مايو" + +msgid "jun" +msgstr "يونيو" + +msgid "jul" +msgstr "يوليو" + +msgid "aug" +msgstr "أغسطس" + +msgid "sep" +msgstr "سبتمبر" + +msgid "oct" +msgstr "أكتوبر" + +msgid "nov" +msgstr "نوفمبر" + +msgid "dec" +msgstr "ديسمبر" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "يناير" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "فبراير" + +msgctxt "abbrev. month" +msgid "March" +msgstr "مارس" + +msgctxt "abbrev. month" +msgid "April" +msgstr "إبريل" + +msgctxt "abbrev. month" +msgid "May" +msgstr "مايو" + +msgctxt "abbrev. month" +msgid "June" +msgstr "يونيو" + +msgctxt "abbrev. month" +msgid "July" +msgstr "يوليو" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "أغسطس" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "سبتمبر" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "أكتوبر" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "نوفمبر" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "ديسمبر" + +msgctxt "alt. month" +msgid "January" +msgstr "يناير" + +msgctxt "alt. month" +msgid "February" +msgstr "فبراير" + +msgctxt "alt. month" +msgid "March" +msgstr "مارس" + +msgctxt "alt. month" +msgid "April" +msgstr "أبريل" + +msgctxt "alt. month" +msgid "May" +msgstr "مايو" + +msgctxt "alt. month" +msgid "June" +msgstr "يونيو" + +msgctxt "alt. month" +msgid "July" +msgstr "يوليو" + +msgctxt "alt. month" +msgid "August" +msgstr "أغسطس" + +msgctxt "alt. month" +msgid "September" +msgstr "سبتمبر" + +msgctxt "alt. month" +msgid "October" +msgstr "أكتوبر" + +msgctxt "alt. month" +msgid "November" +msgstr "نوفمبر" + +msgctxt "alt. month" +msgid "December" +msgstr "ديسمبر" + +msgid "This is not a valid IPv6 address." +msgstr "هذا ليس عنوان IPv6 صحيح." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "أو" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "، " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d سنة" +msgstr[1] "%(num)d سنة" +msgstr[2] "%(num)d سنتين" +msgstr[3] "%(num)d سنوات" +msgstr[4] "%(num)d سنوات" +msgstr[5] "%(num)d سنوات" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d شهر" +msgstr[1] "%(num)d شهر" +msgstr[2] "%(num)d شهرين" +msgstr[3] "%(num)d أشهر" +msgstr[4] "%(num)d أشهر" +msgstr[5] "%(num)d أشهر" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d أسبوع" +msgstr[1] "%(num)d أسبوع" +msgstr[2] "%(num)d أسبوعين" +msgstr[3] "%(num)d أسابيع" +msgstr[4] "%(num)d أسابيع" +msgstr[5] "%(num)d أسابيع" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d يوم" +msgstr[1] "%(num)d يوم" +msgstr[2] "%(num)d يومين" +msgstr[3] "%(num)d أيام" +msgstr[4] "%(num)d يوم" +msgstr[5] "%(num)d أيام" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d ساعة" +msgstr[1] "%(num)d ساعة" +msgstr[2] "%(num)d ساعتين" +msgstr[3] "%(num)d ساعات" +msgstr[4] "%(num)d ساعة" +msgstr[5] "%(num)d ساعات" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d دقيقة" +msgstr[1] "%(num)d دقيقة" +msgstr[2] "%(num)d دقيقتين" +msgstr[3] "%(num)d دقائق" +msgstr[4] "%(num)d دقيقة" +msgstr[5] "%(num)d دقيقة" + +msgid "Forbidden" +msgstr "ممنوع" + +msgid "CSRF verification failed. Request aborted." +msgstr "تم الفشل للتحقق من CSRF. تم إنهاء الطلب." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"أنت ترى هذه الرسالة لأن موقع HTTPS هذا يتطلب إرسال “Referer header” بواسطة " +"متصفح الويب الخاص بك، ولكن لم يتم إرسال أي منها. هذا مطلوب لأسباب أمنية، " +"لضمان عدم اختطاف متصفحك من قبل أطراف ثالثة." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"إذا قمت بتكوين المستعرض لتعطيل رؤوس “Referer” ، فيرجى إعادة تمكينها ، على " +"الأقل لهذا الموقع ، أو لاتصالات HTTPS ، أو لطلبات “same-origin”." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"إذا كنت تستخدم العلامة أو " +"تضمين رأس “Referrer-Policy: no-referrer”، يرجى إزالتها. تتطلب حماية CSRF أن " +"يقوم رأس “Referer” بإجراء فحص صارم للمراجع. إذا كنت قلقًا بشأن الخصوصية ، " +"فاستخدم بدائل مثل للروابط إلى مواقع الجهات الخارجية." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"أنت ترى هذه الرسالة لأن هذا الموقع يتطلب كعكة CSRF عند تقديم النماذج. ملف " +"الكعكة هذا مطلوب لأسباب أمنية في تعريف الإرتباط، لضمان أنه لم يتم اختطاف " +"المتصفح من قبل أطراف أخرى." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"إذا قمت بضبط المتصفح لتعطيل الكوكيز الرجاء إعادة تغعيلها، على الأقل بالنسبة " +"لهذا الموقع، أو للطلبات من “same-origin”." + +msgid "More information is available with DEBUG=True." +msgstr "يتوفر مزيد من المعلومات عند ضبط الخيار DEBUG=True." + +msgid "No year specified" +msgstr "لم تحدد السنة" + +msgid "Date out of range" +msgstr "التاريخ خارج النطاق" + +msgid "No month specified" +msgstr "لم تحدد الشهر" + +msgid "No day specified" +msgstr "لم تحدد اليوم" + +msgid "No week specified" +msgstr "لم تحدد الأسبوع" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "لا يوجد %(verbose_name_plural)s" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"التاريخ بالمستقبل %(verbose_name_plural)s غير متوفر لأن قيمة %(class_name)s." +"allow_future هي False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "نسق تاريخ غير صحيح \"%(datestr)s\" محدد بالشكل ''%(format)s\"" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "لم يعثر على أي %(verbose_name)s مطابقة لهذا الإستعلام" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "الصفحة ليست \"الأخيرة\"، كما لا يمكن تحويل القيمة إلى رقم طبيعي." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "صفحة خاطئة (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" +"قائمة فارغة و\n" +"\"%(class_name)s.allow_empty\"\n" +"قيمته False." + +msgid "Directory indexes are not allowed here." +msgstr "لا يسمح لفهارس الدليل هنا." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "”%(path)s“ غير موجود" + +#, python-format +msgid "Index of %(directory)s" +msgstr "فهرس لـ %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "تمت عملية التنصيب بنجاح! تهانينا!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"استعراض ملاحظات الإصدار لجانغو %(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" +"تظهر لك هذه الصفحة لأن DEBUG=True في ملف settings خاصتك كما أنك لم تقم بإعداد الروابط URLs." + +msgid "Django Documentation" +msgstr "وثائق تعليمات جانغو" + +msgid "Topics, references, & how-to’s" +msgstr "المواضيع و المراجع و التعليمات" + +msgid "Tutorial: A Polling App" +msgstr "برنامج تعليمي: تطبيق تصويت" + +msgid "Get started with Django" +msgstr "إبدأ مع جانغو" + +msgid "Django Community" +msgstr "مجتمع جانغو" + +msgid "Connect, get help, or contribute" +msgstr "اتصل بنا أو احصل على مساعدة أو ساهم" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ar/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ar/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ar/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ar/formats.py new file mode 100644 index 0000000..8008ce6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ar/formats.py @@ -0,0 +1,21 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j F، Y" +TIME_FORMAT = "g:i A" +# DATETIME_FORMAT = +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "d‏/m‏/Y" +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +# NUMBER_GROUPING = diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ar_DZ/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ar_DZ/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3c0e324 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ar_DZ/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ar_DZ/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ar_DZ/LC_MESSAGES/django.po new file mode 100644 index 0000000..b32da34 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ar_DZ/LC_MESSAGES/django.po @@ -0,0 +1,1397 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jihad Bahmaid Al-Halki, 2022 +# Riterix , 2019-2020 +# Riterix , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-05-17 05:23-0500\n" +"PO-Revision-Date: 2022-07-25 06:49+0000\n" +"Last-Translator: Jihad Bahmaid Al-Halki\n" +"Language-Team: Arabic (Algeria) (http://www.transifex.com/django/django/" +"language/ar_DZ/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar_DZ\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +msgid "Afrikaans" +msgstr "الإفريقية" + +msgid "Arabic" +msgstr "العربية" + +msgid "Algerian Arabic" +msgstr "العربية الجزائرية" + +msgid "Asturian" +msgstr "الأسترية" + +msgid "Azerbaijani" +msgstr "الأذربيجانية" + +msgid "Bulgarian" +msgstr "البلغارية" + +msgid "Belarusian" +msgstr "البيلاروسية" + +msgid "Bengali" +msgstr "البنغالية" + +msgid "Breton" +msgstr "البريتونية" + +msgid "Bosnian" +msgstr "البوسنية" + +msgid "Catalan" +msgstr "الكتلانية" + +msgid "Czech" +msgstr "التشيكية" + +msgid "Welsh" +msgstr "الويلز" + +msgid "Danish" +msgstr "الدنماركية" + +msgid "German" +msgstr "الألمانية" + +msgid "Lower Sorbian" +msgstr "الصربية السفلى" + +msgid "Greek" +msgstr "اليونانية" + +msgid "English" +msgstr "الإنجليزية" + +msgid "Australian English" +msgstr "الإنجليزية الإسترالية" + +msgid "British English" +msgstr "الإنجليزية البريطانية" + +msgid "Esperanto" +msgstr "الاسبرانتو" + +msgid "Spanish" +msgstr "الإسبانية" + +msgid "Argentinian Spanish" +msgstr "الأسبانية الأرجنتينية" + +msgid "Colombian Spanish" +msgstr "الكولومبية الإسبانية" + +msgid "Mexican Spanish" +msgstr "الأسبانية المكسيكية" + +msgid "Nicaraguan Spanish" +msgstr "الإسبانية النيكاراغوية" + +msgid "Venezuelan Spanish" +msgstr "الإسبانية الفنزويلية" + +msgid "Estonian" +msgstr "الإستونية" + +msgid "Basque" +msgstr "الباسك" + +msgid "Persian" +msgstr "الفارسية" + +msgid "Finnish" +msgstr "الفنلندية" + +msgid "French" +msgstr "الفرنسية" + +msgid "Frisian" +msgstr "الفريزية" + +msgid "Irish" +msgstr "الإيرلندية" + +msgid "Scottish Gaelic" +msgstr "الغيلية الأسكتلندية" + +msgid "Galician" +msgstr "الجليقية" + +msgid "Hebrew" +msgstr "العبرية" + +msgid "Hindi" +msgstr "الهندية" + +msgid "Croatian" +msgstr "الكرواتية" + +msgid "Upper Sorbian" +msgstr "الصربية العليا" + +msgid "Hungarian" +msgstr "الهنغارية" + +msgid "Armenian" +msgstr "الأرمنية" + +msgid "Interlingua" +msgstr "اللغة الوسيطة" + +msgid "Indonesian" +msgstr "الإندونيسية" + +msgid "Igbo" +msgstr "إيبو" + +msgid "Ido" +msgstr "ايدو" + +msgid "Icelandic" +msgstr "الآيسلندية" + +msgid "Italian" +msgstr "الإيطالية" + +msgid "Japanese" +msgstr "اليابانية" + +msgid "Georgian" +msgstr "الجورجية" + +msgid "Kabyle" +msgstr "القبائلية" + +msgid "Kazakh" +msgstr "الكازاخستانية" + +msgid "Khmer" +msgstr "الخمر" + +msgid "Kannada" +msgstr "الهندية (كنّادا)" + +msgid "Korean" +msgstr "الكورية" + +msgid "Kyrgyz" +msgstr "القيرغيزية" + +msgid "Luxembourgish" +msgstr "اللوكسمبرجية" + +msgid "Lithuanian" +msgstr "اللتوانية" + +msgid "Latvian" +msgstr "اللاتفية" + +msgid "Macedonian" +msgstr "المقدونية" + +msgid "Malayalam" +msgstr "المايالام" + +msgid "Mongolian" +msgstr "المنغولية" + +msgid "Marathi" +msgstr "المهاراتية" + +msgid "Malay" +msgstr "ملاي" + +msgid "Burmese" +msgstr "البورمية" + +msgid "Norwegian Bokmål" +msgstr "النرويجية" + +msgid "Nepali" +msgstr "النيبالية" + +msgid "Dutch" +msgstr "الهولندية" + +msgid "Norwegian Nynorsk" +msgstr "النينورسك نرويجية" + +msgid "Ossetic" +msgstr "الأوسيتيكية" + +msgid "Punjabi" +msgstr "البنجابية" + +msgid "Polish" +msgstr "البولندية" + +msgid "Portuguese" +msgstr "البرتغالية" + +msgid "Brazilian Portuguese" +msgstr "البرتغالية البرازيلية" + +msgid "Romanian" +msgstr "الرومانية" + +msgid "Russian" +msgstr "الروسية" + +msgid "Slovak" +msgstr "السلوفاكية" + +msgid "Slovenian" +msgstr "السلوفانية" + +msgid "Albanian" +msgstr "الألبانية" + +msgid "Serbian" +msgstr "الصربية" + +msgid "Serbian Latin" +msgstr "اللاتينية الصربية" + +msgid "Swedish" +msgstr "السويدية" + +msgid "Swahili" +msgstr "السواحلية" + +msgid "Tamil" +msgstr "التاميل" + +msgid "Telugu" +msgstr "التيلوغو" + +msgid "Tajik" +msgstr "الطاجيكية" + +msgid "Thai" +msgstr "التايلندية" + +msgid "Turkmen" +msgstr "" + +msgid "Turkish" +msgstr "التركية" + +msgid "Tatar" +msgstr "التتاريية" + +msgid "Udmurt" +msgstr "الأدمرتية" + +msgid "Ukrainian" +msgstr "الأكرانية" + +msgid "Urdu" +msgstr "الأوردو" + +msgid "Uzbek" +msgstr "الأوزبكية" + +msgid "Vietnamese" +msgstr "الفيتنامية" + +msgid "Simplified Chinese" +msgstr "الصينية المبسطة" + +msgid "Traditional Chinese" +msgstr "الصينية التقليدية" + +msgid "Messages" +msgstr "الرسائل" + +msgid "Site Maps" +msgstr "خرائط الموقع" + +msgid "Static Files" +msgstr "الملفات الثابتة" + +msgid "Syndication" +msgstr "توظيف النشر" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "" + +msgid "That page number is not an integer" +msgstr "رقم الصفحة ليس عددًا صحيحًا" + +msgid "That page number is less than 1" +msgstr "رقم الصفحة أقل من 1" + +msgid "That page contains no results" +msgstr "هذه الصفحة لا تحتوي على نتائج" + +msgid "Enter a valid value." +msgstr "أدخل قيمة صحيحة." + +msgid "Enter a valid URL." +msgstr "أدخل رابطاً صحيحاً." + +msgid "Enter a valid integer." +msgstr "أدخل رقم صالح." + +msgid "Enter a valid email address." +msgstr "أدخل عنوان بريد إلكتروني صحيح." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"أدخل “slug” صالحة تتكون من أحرف أو أرقام أو الشرطة السفلية أو الواصلات." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"أدخل “slug” صالحة تتكون من أحرف Unicode أو الأرقام أو الشرطة السفلية أو " +"الواصلات." + +msgid "Enter a valid IPv4 address." +msgstr "أدخل عنوان IPv4 صحيح." + +msgid "Enter a valid IPv6 address." +msgstr "أدخل عنوان IPv6 صحيح." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "أدخل عنوان IPv4 أو عنوان IPv6 صحيح." + +msgid "Enter only digits separated by commas." +msgstr "أدخل أرقاما فقط مفصول بينها بفواصل." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "تحقق من أن هذه القيمة هي %(limit_value)s (إنها %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "تحقق من أن تكون هذه القيمة أقل من %(limit_value)s أو مساوية لها." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "تحقق من أن تكون هذه القيمة أكثر من %(limit_value)s أو مساوية لها." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"تأكد أن هذه القيمة تحتوي على %(limit_value)d حرف أو رمز على الأقل (هي تحتوي " +"حالياً على %(show_value)d)." +msgstr[1] "" +"تأكد أن هذه القيمة تحتوي على %(limit_value)d حرف أو رمز على الأقل (هي تحتوي " +"حالياً على %(show_value)d)." +msgstr[2] "" +"تأكد أن هذه القيمة تحتوي على %(limit_value)d حرف أو رمز على الأقل (هي تحتوي " +"حالياً على %(show_value)d)." +msgstr[3] "" +"تأكد أن هذه القيمة تحتوي على %(limit_value)d حرف أو رمز على الأقل (هي تحتوي " +"حالياً على %(show_value)d)." +msgstr[4] "" +"تأكد أن هذه القيمة تحتوي على %(limit_value)d حرف أو رمز على الأقل (هي تحتوي " +"حالياً على %(show_value)d)." +msgstr[5] "" +"تأكد أن هذه القيمة تحتوي على %(limit_value)d حرف أو رمز على الأقل (هي تحتوي " +"حالياً على %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"تأكد أن هذه القيمة تحتوي على %(limit_value)d حرف أو رمز على الأكثر (هي تحتوي " +"حالياً على %(show_value)d)." +msgstr[1] "" +"تأكد أن هذه القيمة تحتوي على %(limit_value)d حرف أو رمز على الأكثر (هي تحتوي " +"حالياً على %(show_value)d)." +msgstr[2] "" +"تأكد أن هذه القيمة تحتوي على %(limit_value)d حرف أو رمز على الأكثر (هي تحتوي " +"حالياً على %(show_value)d)." +msgstr[3] "" +"تأكد أن هذه القيمة تحتوي على %(limit_value)d حرف أو رمز على الأكثر (هي تحتوي " +"حالياً على %(show_value)d)." +msgstr[4] "" +"تأكد أن هذه القيمة تحتوي على %(limit_value)d حرف أو رمز على الأكثر (هي تحتوي " +"حالياً على %(show_value)d)." +msgstr[5] "" +"تأكد أن هذه القيمة تحتوي على %(limit_value)d حرف أو رمز على الأكثر (هي تحتوي " +"حالياً على %(show_value)d)." + +msgid "Enter a number." +msgstr "أدخل رقماً." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "تحقق من أن تدخل %(max)s أرقام لا أكثر." +msgstr[1] "تحقق من أن تدخل رقم %(max)s لا أكثر." +msgstr[2] "تحقق من أن تدخل %(max)s رقمين لا أكثر." +msgstr[3] "تحقق من أن تدخل %(max)s أرقام لا أكثر." +msgstr[4] "تحقق من أن تدخل %(max)s أرقام لا أكثر." +msgstr[5] "تحقق من أن تدخل %(max)s أرقام لا أكثر." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "تحقق من أن تدخل %(max)s خانات عشرية لا أكثر." +msgstr[1] "تحقق من أن تدخل %(max)s خانات عشرية لا أكثر." +msgstr[2] "تحقق من أن تدخل %(max)s خانات عشرية لا أكثر." +msgstr[3] "تحقق من أن تدخل %(max)s خانات عشرية لا أكثر." +msgstr[4] "تحقق من أن تدخل %(max)s خانات عشرية لا أكثر." +msgstr[5] "تحقق من أن تدخل %(max)s خانات عشرية لا أكثر." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "تحقق من أن تدخل %(max)s أرقام قبل الفاصل العشري لا أكثر." +msgstr[1] "تحقق من أن تدخل %(max)s أرقام قبل الفاصل العشري لا أكثر." +msgstr[2] "تحقق من أن تدخل %(max)s أرقام قبل الفاصل العشري لا أكثر." +msgstr[3] "تحقق من أن تدخل %(max)s أرقام قبل الفاصل العشري لا أكثر." +msgstr[4] "تحقق من أن تدخل %(max)s أرقام قبل الفاصل العشري لا أكثر." +msgstr[5] "تحقق من أن تدخل %(max)s أرقام قبل الفاصل العشري لا أكثر." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"امتداد الملف “%(extension)s” غير مسموح به. الامتدادات المسموح بها هي:" +"%(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "لا يُسمح بالأحرف الخالية." + +msgid "and" +msgstr "و" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s بهذا %(field_labels)s موجود سلفاً." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "القيمة %(value)r ليست خيارا صحيحاً." + +msgid "This field cannot be null." +msgstr "لا يمكن ترك هذا الحقل خالي." + +msgid "This field cannot be blank." +msgstr "لا يمكن ترك هذا الحقل فارغاً." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "النموذج %(model_name)s والحقل %(field_label)s موجود مسبقاً." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s يجب أن يكون فريد لـ %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "حقل نوع: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "يجب أن تكون القيمة “%(value)s” إما True أو False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "يجب أن تكون القيمة “%(value)s” إما True أو False أو None." + +msgid "Boolean (Either True or False)" +msgstr "ثنائي (إما True أو False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "سلسلة نص (%(max_length)s كحد أقصى)" + +msgid "Comma-separated integers" +msgstr "أرقام صحيحة مفصولة بفواصل" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"تحتوي القيمة “%(value)s” على تنسيق تاريخ غير صالح. يجب أن يكون بتنسيق YYYY-" +"MM-DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"تحتوي القيمة “%(value)s” على التنسيق الصحيح (YYYY-MM-DD) ولكنه تاريخ غير " +"صالح." + +msgid "Date (without time)" +msgstr "التاريخ (دون الوقت)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"تحتوي القيمة “%(value)s” على تنسيق غير صالح. يجب أن يكون بتنسيق YYYY-MM-DD " +"HH: MM [: ss [.uuuuuu]] [TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"تحتوي القيمة “%(value)s” على التنسيق الصحيح (YYYY-MM-DD HH: MM [: ss [." +"uuuuuu]] [TZ]) ولكنها تعد تاريخًا / وقتًا غير صالحين." + +msgid "Date (with time)" +msgstr "التاريخ (مع الوقت)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "يجب أن تكون القيمة “%(value)s” رقمًا عشريًا." + +msgid "Decimal number" +msgstr "رقم عشري" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"تحتوي القيمة “%(value)s” على تنسيق غير صالح. يجب أن يكون بتنسيق [DD] [[HH:] " +"MM:] ss [.uuuuuu]." + +msgid "Duration" +msgstr "المدّة" + +msgid "Email address" +msgstr "عنوان بريد إلكتروني" + +msgid "File path" +msgstr "مسار الملف" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "يجب أن تكون القيمة “%(value)s” قيمة عائمة." + +msgid "Floating point number" +msgstr "رقم فاصلة عائمة" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "يجب أن تكون القيمة “%(value)s” عددًا صحيحًا." + +msgid "Integer" +msgstr "عدد صحيح" + +msgid "Big (8 byte) integer" +msgstr "عدد صحيح كبير (8 بايت)" + +msgid "Small integer" +msgstr "عدد صحيح صغير" + +msgid "IPv4 address" +msgstr "عنوان IPv4" + +msgid "IP address" +msgstr "عنوان IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "يجب أن تكون القيمة “%(value)s” إما None أو True أو False." + +msgid "Boolean (Either True, False or None)" +msgstr "ثنائي (إما True أو False أو None)" + +msgid "Positive big integer" +msgstr "عدد صحيح كبير موجب" + +msgid "Positive integer" +msgstr "عدد صحيح موجب" + +msgid "Positive small integer" +msgstr "عدد صحيح صغير موجب" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (حتى %(max_length)s)" + +msgid "Text" +msgstr "نص" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"تحتوي القيمة “%(value)s” على تنسيق غير صالح. يجب أن يكون بتنسيق HH: MM [: ss " +"[.uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"تحتوي القيمة “%(value)s” على التنسيق الصحيح (HH: MM [: ss [.uuuuuu]]) ولكنه " +"وقت غير صالح." + +msgid "Time" +msgstr "وقت" + +msgid "URL" +msgstr "رابط" + +msgid "Raw binary data" +msgstr "البيانات الثنائية الخام" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "“%(value)s” ليس UUID صالحًا." + +msgid "Universally unique identifier" +msgstr "المعرف الفريد العالمي (UUID)" + +msgid "File" +msgstr "ملف" + +msgid "Image" +msgstr "صورة" + +msgid "A JSON object" +msgstr "كائن JSON" + +msgid "Value must be valid JSON." +msgstr "يجب أن تكون قيمة JSON صالحة." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "النموذج %(model)s ذو الحقل و القيمة %(field)s %(value)r غير موجود." + +msgid "Foreign Key (type determined by related field)" +msgstr "الحقل المرتبط (تم تحديد النوع وفقاً للحقل المرتبط)" + +msgid "One-to-one relationship" +msgstr "علاقة واحد إلى واحد" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s علاقة" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s علاقات" + +msgid "Many-to-many relationship" +msgstr "علاقة متعدد إلى متعدد" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "هذا الحقل مطلوب." + +msgid "Enter a whole number." +msgstr "أدخل رقما صحيحا." + +msgid "Enter a valid date." +msgstr "أدخل تاريخاً صحيحاً." + +msgid "Enter a valid time." +msgstr "أدخل وقتاً صحيحاً." + +msgid "Enter a valid date/time." +msgstr "أدخل تاريخاً/وقتاً صحيحاً." + +msgid "Enter a valid duration." +msgstr "أدخل مدّة صحيحة" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "يجب أن يتراوح عدد الأيام بين {min_days} و {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "لم يتم ارسال ملف، الرجاء التأكد من نوع ترميز الاستمارة." + +msgid "No file was submitted." +msgstr "لم يتم إرسال اي ملف." + +msgid "The submitted file is empty." +msgstr "الملف الذي قمت بإرساله فارغ." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"تأكد أن إسم هذا الملف يحتوي على %(max)d حرف على الأكثر (هو يحتوي الآن على " +"%(length)d حرف)." +msgstr[1] "" +"تأكد أن إسم هذا الملف يحتوي على %(max)d حرف على الأكثر (هو يحتوي الآن على " +"%(length)d حرف)." +msgstr[2] "" +"تأكد أن إسم هذا الملف يحتوي على %(max)d حرف على الأكثر (هو يحتوي الآن على " +"%(length)d حرف)." +msgstr[3] "" +"تأكد أن إسم هذا الملف يحتوي على %(max)d حرف على الأكثر (هو يحتوي الآن على " +"%(length)d حرف)." +msgstr[4] "" +"تأكد أن إسم هذا الملف يحتوي على %(max)d حرف على الأكثر (هو يحتوي الآن على " +"%(length)d حرف)." +msgstr[5] "" +"تأكد أن إسم هذا الملف يحتوي على %(max)d حرف على الأكثر (هو يحتوي الآن على " +"%(length)d حرف)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"رجاءً أرسل ملف أو صح علامة صح عند مربع اختيار \\\"فارغ\\\"، وليس كلاهما." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"قم برفع صورة صحيحة، الملف الذي قمت برفعه إما أنه ليس ملفا لصورة أو أنه ملف " +"معطوب." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "انتق خياراً صحيحاً. %(value)s ليس أحد الخيارات المتاحة." + +msgid "Enter a list of values." +msgstr "أدخل قائمة من القيم." + +msgid "Enter a complete value." +msgstr "إدخال قيمة كاملة." + +msgid "Enter a valid UUID." +msgstr "أدخل قيمة UUID صحيحة." + +msgid "Enter a valid JSON." +msgstr "ادخل كائن JSON صالح." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(الحقل الخفي %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"نموذج بيانات الإدارة مفقود أو تم العبث به. %(field_names)sمن الحقول مفقود. " +"قد تحتاج إلى رفع تقرير بالمشكلة إن استمرت الحالة." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +msgid "Order" +msgstr "الترتيب" + +msgid "Delete" +msgstr "احذف" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "رجاء صحّح بيانات %(field)s المتكررة." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "رجاء صحّح بيانات %(field)s المتكررة والتي يجب أن تكون مُميّزة." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"رجاء صحّح بيانات %(field_name)s المتكررة والتي يجب أن تكون مُميّزة لـ%(lookup)s " +"في %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "رجاءً صحّح القيم المُكرّرة أدناه." + +msgid "The inline value did not match the parent instance." +msgstr "القيمة المضمنة لا تتطابق مع المثيل الأصلي." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "انتق خياراً صحيحاً. اختيارك ليس أحد الخيارات المتاحة." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "“%(pk)s” ليست قيمة صالحة." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"لا يمكن تفسير٪ %(datetime)s في المنطقة الزمنية٪ %(current_timezone)s؛ قد " +"تكون غامضة أو غير موجودة." + +msgid "Clear" +msgstr "تفريغ" + +msgid "Currently" +msgstr "حالياً" + +msgid "Change" +msgstr "عدّل" + +msgid "Unknown" +msgstr "مجهول" + +msgid "Yes" +msgstr "نعم" + +msgid "No" +msgstr "لا" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "نعم,لا,ربما" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d بايت" +msgstr[1] "%(size)d بايت واحد " +msgstr[2] "%(size)d بايتان" +msgstr[3] "%(size)d بايت" +msgstr[4] "%(size)d بايت" +msgstr[5] "%(size)d بايت" + +#, python-format +msgid "%s KB" +msgstr "%s ك.ب" + +#, python-format +msgid "%s MB" +msgstr "%s م.ب" + +#, python-format +msgid "%s GB" +msgstr "%s ج.ب" + +#, python-format +msgid "%s TB" +msgstr "%s ت.ب" + +#, python-format +msgid "%s PB" +msgstr "%s ب.ب" + +msgid "p.m." +msgstr "م" + +msgid "a.m." +msgstr "ص" + +msgid "PM" +msgstr "م" + +msgid "AM" +msgstr "ص" + +msgid "midnight" +msgstr "منتصف الليل" + +msgid "noon" +msgstr "ظهراً" + +msgid "Monday" +msgstr "الاثنين" + +msgid "Tuesday" +msgstr "الثلاثاء" + +msgid "Wednesday" +msgstr "الأربعاء" + +msgid "Thursday" +msgstr "الخميس" + +msgid "Friday" +msgstr "الجمعة" + +msgid "Saturday" +msgstr "السبت" + +msgid "Sunday" +msgstr "الأحد" + +msgid "Mon" +msgstr "إثنين" + +msgid "Tue" +msgstr "ثلاثاء" + +msgid "Wed" +msgstr "أربعاء" + +msgid "Thu" +msgstr "خميس" + +msgid "Fri" +msgstr "جمعة" + +msgid "Sat" +msgstr "سبت" + +msgid "Sun" +msgstr "أحد" + +msgid "January" +msgstr "جانفي" + +msgid "February" +msgstr "فيفري" + +msgid "March" +msgstr "مارس" + +msgid "April" +msgstr "أفريل" + +msgid "May" +msgstr "ماي" + +msgid "June" +msgstr "جوان" + +msgid "July" +msgstr "جويليه" + +msgid "August" +msgstr "أوت" + +msgid "September" +msgstr "سبتمبر" + +msgid "October" +msgstr "أكتوبر" + +msgid "November" +msgstr "نوفمبر" + +msgid "December" +msgstr "ديسمبر" + +msgid "jan" +msgstr "جانفي" + +msgid "feb" +msgstr "فيفري" + +msgid "mar" +msgstr "مارس" + +msgid "apr" +msgstr "أفريل" + +msgid "may" +msgstr "ماي" + +msgid "jun" +msgstr "جوان" + +msgid "jul" +msgstr "جويليه" + +msgid "aug" +msgstr "أوت" + +msgid "sep" +msgstr "سبتمبر" + +msgid "oct" +msgstr "أكتوبر" + +msgid "nov" +msgstr "نوفمبر" + +msgid "dec" +msgstr "ديسمبر" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "جانفي" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "فيفري" + +msgctxt "abbrev. month" +msgid "March" +msgstr "مارس" + +msgctxt "abbrev. month" +msgid "April" +msgstr "أفريل" + +msgctxt "abbrev. month" +msgid "May" +msgstr "ماي" + +msgctxt "abbrev. month" +msgid "June" +msgstr "جوان" + +msgctxt "abbrev. month" +msgid "July" +msgstr "جويليه" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "أوت" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "سبتمبر" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "أكتوبر" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "نوفمبر" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "ديسمبر" + +msgctxt "alt. month" +msgid "January" +msgstr "جانفي" + +msgctxt "alt. month" +msgid "February" +msgstr "فيفري" + +msgctxt "alt. month" +msgid "March" +msgstr "مارس" + +msgctxt "alt. month" +msgid "April" +msgstr "أفريل" + +msgctxt "alt. month" +msgid "May" +msgstr "ماي" + +msgctxt "alt. month" +msgid "June" +msgstr "جوان" + +msgctxt "alt. month" +msgid "July" +msgstr "جويليه" + +msgctxt "alt. month" +msgid "August" +msgstr "أوت" + +msgctxt "alt. month" +msgid "September" +msgstr "سبتمبر" + +msgctxt "alt. month" +msgid "October" +msgstr "أكتوبر" + +msgctxt "alt. month" +msgid "November" +msgstr "نوفمبر" + +msgctxt "alt. month" +msgid "December" +msgstr "ديسمبر" + +msgid "This is not a valid IPv6 address." +msgstr "هذا ليس عنوان IPv6 صحيح." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "أو" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "، " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +msgid "Forbidden" +msgstr "ممنوع" + +msgid "CSRF verification failed. Request aborted." +msgstr "تم الفشل للتحقق من CSRF. تم إنهاء الطلب." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"أنت ترى هذه الرسالة لأن موقع HTTPS هذا يتطلب \"عنوان مرجعي\" ليتم إرساله " +"بواسطة متصفح الويب الخاص بك ، ولكن لم يتم إرسال أي شيء. هذا العنوان مطلوب " +"لأسباب أمنية ، لضمان عدم اختراق متصفحك من قبل أطراف أخرى." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"إذا قمت بتكوين المستعرض الخاص بك لتعطيل رؤوس “Referer” ، فالرجاء إعادة " +"تمكينها ، على الأقل لهذا الموقع ، أو لاتصالات HTTPS ، أو لطلبات “same-" +"origin”." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"إذا كنت تستخدم العلامة أو تتضمن رأس “Referrer-Policy: no-referrer” ، فيرجى إزالتها. تتطلب حماية " +"CSRF رأس “Referer” القيام بالتحقق من “strict referer”. إذا كنت مهتمًا " +"بالخصوصية ، فاستخدم بدائل مثل للروابط إلى مواقع " +"الجهات الخارجية." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"تشاهد هذه الرسالة لأن هذا الموقع يتطلب ملف تعريف ارتباط CSRF Cookie عند " +"إرسال النماذج. ملف تعريف ارتباط Cookie هذا مطلوب لأسباب أمنية ، لضمان عدم " +"اختطاف متصفحك من قبل أطراف ثالثة." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"إذا قمت بتكوين المستعرض الخاص بك لتعطيل ملفات تعريف الارتباط Cookies ، يرجى " +"إعادة تمكينها ، على الأقل لهذا الموقع ، أو لطلبات “same-origin”." + +msgid "More information is available with DEBUG=True." +msgstr "يتوفر مزيد من المعلومات عند ضبط الخيار DEBUG=True." + +msgid "No year specified" +msgstr "لم تحدد السنة" + +msgid "Date out of range" +msgstr "تاريخ خارج النطاق" + +msgid "No month specified" +msgstr "لم تحدد الشهر" + +msgid "No day specified" +msgstr "لم تحدد اليوم" + +msgid "No week specified" +msgstr "لم تحدد الأسبوع" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "لا يوجد %(verbose_name_plural)s" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"التاريخ بالمستقبل %(verbose_name_plural)s غير متوفر لأن قيمة %(class_name)s." +"allow_future هي False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "سلسلة تاريخ غير صالحة “%(datestr)s” شكل معين “%(format)s”" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "لم يعثر على أي %(verbose_name)s مطابقة لهذا الإستعلام" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "الصفحة ليست \"الأخيرة\" ، ولا يمكن تحويلها إلى عدد صحيح." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "صفحة خاطئة (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "القائمة فارغة و “%(class_name)s.allow_empty” هي False." + +msgid "Directory indexes are not allowed here." +msgstr "لا يسمح لفهارس الدليل هنا." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "“%(path)s” غير موجود" + +#, python-format +msgid "Index of %(directory)s" +msgstr "فهرس لـ %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "تمَّت عملية التثبيت بنجاح! تهانينا!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"عرض ملاحظات الإصدار ل جانغو " +"%(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" +"تشاهد هذه الصفحة لأن DEBUG = True موجود في ملف الإعدادات الخاص بك ولم تقم بتكوين أي " +"عناوين URL." + +msgid "Django Documentation" +msgstr "توثيق جانغو" + +msgid "Topics, references, & how-to’s" +msgstr "الموضوعات ، المراجع، & الكيفية" + +msgid "Tutorial: A Polling App" +msgstr "البرنامج التعليمي: تطبيق الاقتراع" + +msgid "Get started with Django" +msgstr "الخطوات الأولى مع جانغو" + +msgid "Django Community" +msgstr "مجتمع جانغو" + +msgid "Connect, get help, or contribute" +msgstr "الاتصال، الحصول على المساعدة أو المساهمة" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ar_DZ/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ar_DZ/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ar_DZ/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ar_DZ/formats.py new file mode 100644 index 0000000..cbd361d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ar_DZ/formats.py @@ -0,0 +1,29 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j F Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = "j F Y H:i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "j F Y" +SHORT_DATETIME_FORMAT = "j F Y H:i" +FIRST_DAY_OF_WEEK = 0 # Sunday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%Y/%m/%d", # '2006/10/25' +] +TIME_INPUT_FORMATS = [ + "%H:%M", # '14:30 + "%H:%M:%S", # '14:30:59' +] +DATETIME_INPUT_FORMATS = [ + "%Y/%m/%d %H:%M", # '2006/10/25 14:30' + "%Y/%m/%d %H:%M:%S", # '2006/10/25 14:30:59' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ast/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ast/LC_MESSAGES/django.mo new file mode 100644 index 0000000..31733b2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ast/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ast/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ast/LC_MESSAGES/django.po new file mode 100644 index 0000000..417f18d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ast/LC_MESSAGES/django.po @@ -0,0 +1,1237 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ḷḷumex03 , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Asturian (http://www.transifex.com/django/django/language/" +"ast/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ast\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Afrikáans" + +msgid "Arabic" +msgstr "Árabe" + +msgid "Asturian" +msgstr "" + +msgid "Azerbaijani" +msgstr "Azerbaixanu" + +msgid "Bulgarian" +msgstr "Búlgaru" + +msgid "Belarusian" +msgstr "Bielorrusu" + +msgid "Bengali" +msgstr "Bengalí" + +msgid "Breton" +msgstr "Bretón" + +msgid "Bosnian" +msgstr "Bosniu" + +msgid "Catalan" +msgstr "Catalán" + +msgid "Czech" +msgstr "Checu" + +msgid "Welsh" +msgstr "Galés" + +msgid "Danish" +msgstr "Danés" + +msgid "German" +msgstr "Alemán" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "Griegu" + +msgid "English" +msgstr "Inglés" + +msgid "Australian English" +msgstr "" + +msgid "British English" +msgstr "Inglés británicu" + +msgid "Esperanto" +msgstr "Esperantu" + +msgid "Spanish" +msgstr "Castellán" + +msgid "Argentinian Spanish" +msgstr "Español arxentín" + +msgid "Colombian Spanish" +msgstr "" + +msgid "Mexican Spanish" +msgstr "Español mexicanu" + +msgid "Nicaraguan Spanish" +msgstr "Español nicaraguanu" + +msgid "Venezuelan Spanish" +msgstr "Español venezolanu" + +msgid "Estonian" +msgstr "Estoniu" + +msgid "Basque" +msgstr "Vascu" + +msgid "Persian" +msgstr "Persa" + +msgid "Finnish" +msgstr "Finés" + +msgid "French" +msgstr "Francés" + +msgid "Frisian" +msgstr "Frisón" + +msgid "Irish" +msgstr "Irlandés" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "Gallegu" + +msgid "Hebrew" +msgstr "Hebréu" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Croata" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "Húngaru" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonesiu" + +msgid "Ido" +msgstr "" + +msgid "Icelandic" +msgstr "Islandés" + +msgid "Italian" +msgstr "Italianu" + +msgid "Japanese" +msgstr "Xaponés" + +msgid "Georgian" +msgstr "Xeorxanu" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "Kazakh" + +msgid "Khmer" +msgstr "Khmer" + +msgid "Kannada" +msgstr "Canarés" + +msgid "Korean" +msgstr "Coreanu" + +msgid "Luxembourgish" +msgstr "Luxemburgués" + +msgid "Lithuanian" +msgstr "Lituanu" + +msgid "Latvian" +msgstr "Letón" + +msgid "Macedonian" +msgstr "Macedoniu" + +msgid "Malayalam" +msgstr "Malayalam" + +msgid "Mongolian" +msgstr "Mongol" + +msgid "Marathi" +msgstr "" + +msgid "Burmese" +msgstr "Birmanu" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "Nepalí" + +msgid "Dutch" +msgstr "Holandés" + +msgid "Norwegian Nynorsk" +msgstr "Nynorsk noruegu" + +msgid "Ossetic" +msgstr "Osetiu" + +msgid "Punjabi" +msgstr "Punjabi" + +msgid "Polish" +msgstr "Polacu" + +msgid "Portuguese" +msgstr "Portugués" + +msgid "Brazilian Portuguese" +msgstr "Portugués brasileñu" + +msgid "Romanian" +msgstr "Rumanu" + +msgid "Russian" +msgstr "Rusu" + +msgid "Slovak" +msgstr "Eslovacu" + +msgid "Slovenian" +msgstr "Eslovenu" + +msgid "Albanian" +msgstr "Albanu" + +msgid "Serbian" +msgstr "Serbiu" + +msgid "Serbian Latin" +msgstr "Serbiu llatín" + +msgid "Swedish" +msgstr "Suecu" + +msgid "Swahili" +msgstr "Suaḥili" + +msgid "Tamil" +msgstr "Tamil" + +msgid "Telugu" +msgstr "Telugu" + +msgid "Thai" +msgstr "Tailandés" + +msgid "Turkish" +msgstr "Turcu" + +msgid "Tatar" +msgstr "Tatar" + +msgid "Udmurt" +msgstr "Udmurtu" + +msgid "Ukrainian" +msgstr "Ucranianu" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "Vietnamita" + +msgid "Simplified Chinese" +msgstr "Chinu simplificáu" + +msgid "Traditional Chinese" +msgstr "Chinu tradicional" + +msgid "Messages" +msgstr "" + +msgid "Site Maps" +msgstr "" + +msgid "Static Files" +msgstr "" + +msgid "Syndication" +msgstr "" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "Introduz un valor válidu." + +msgid "Enter a valid URL." +msgstr "Introduz una URL válida." + +msgid "Enter a valid integer." +msgstr "" + +msgid "Enter a valid email address." +msgstr "Introduz una direición de corréu válida." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Introduz una direición IPv4 válida." + +msgid "Enter a valid IPv6 address." +msgstr "Introduz una direición IPv6 válida." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Introduz una direición IPv4 o IPv6 válida." + +msgid "Enter only digits separated by commas." +msgstr "Introduz namái díxitos separtaos per comes." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Asegúrate qu'esti valor ye %(limit_value)s (ye %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Asegúrate qu'esti valor ye menor o igual a %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Asegúrate qu'esti valor ye mayor o igual a %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Asegúrate qu'esti valor tien polo menos %(limit_value)d caráuter (tien " +"%(show_value)d)." +msgstr[1] "" +"Asegúrate qu'esti valor tien polo menos %(limit_value)d caráuteres (tien " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Asegúrate qu'esti valor tien como muncho %(limit_value)d caráuter (tien " +"%(show_value)d)." +msgstr[1] "" +"Asegúrate qu'esti valor tien como muncho %(limit_value)d caráuteres (tien " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Introduz un númberu." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Asegúrate que nun hai más de %(max)s díxitu en total." +msgstr[1] "Asegúrate que nun hai más de %(max)s díxitos en total." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Asegúrate que nun hai más de %(max)s allugamientu decimal." +msgstr[1] "Asegúrate que nun hai más de %(max)s allugamientos decimales." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Asegúrate que nun hai más de %(max)s díxitu enantes del puntu decimal." +msgstr[1] "" +"Asegúrate que nun hai más de %(max)s díxitos enantes del puntu decimal." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "y" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "Esti campu nun pue ser nulu." + +msgid "This field cannot be blank." +msgstr "Esti campu nun pue tar baleru." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s con esti %(field_label)s yá esiste." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Campu de la triba: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "Boleanu (tamién True o False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Cadena (fasta %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "Enteros separtaos per coma" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "Data (ensin hora)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Data (con hora)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Númberu decimal" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "" + +msgid "Email address" +msgstr "Direición de corréu" + +msgid "File path" +msgstr "Camín del ficheru" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "Númberu de puntu flotante" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "Enteru" + +msgid "Big (8 byte) integer" +msgstr "Enteru big (8 byte)" + +msgid "IPv4 address" +msgstr "Direición IPv4" + +msgid "IP address" +msgstr "Direición IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "Boleanu (tamién True, False o None)" + +msgid "Positive integer" +msgstr "Enteru positivu" + +msgid "Positive small integer" +msgstr "Enteru pequeñu positivu" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (fasta %(max_length)s)" + +msgid "Small integer" +msgstr "Enteru pequeñu" + +msgid "Text" +msgstr "Testu" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Hora" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Datos binarios crudos" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "Ficheru" + +msgid "Image" +msgstr "Imaxe" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "Clave foriata (triba determinada pol campu rellacionáu)" + +msgid "One-to-one relationship" +msgstr "Rellación a ún" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "Rellación a munchos" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Requierse esti campu." + +msgid "Enter a whole number." +msgstr "Introduz un númberu completu" + +msgid "Enter a valid date." +msgstr "Introduz una data válida." + +msgid "Enter a valid time." +msgstr "Introduz una hora válida." + +msgid "Enter a valid date/time." +msgstr "Introduz una data/hora válida." + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Nun s'unvió'l ficheru. Comprueba la triba de cifráu nel formulariu." + +msgid "No file was submitted." +msgstr "No file was submitted." + +msgid "The submitted file is empty." +msgstr "El ficheru dunviáu ta baleru." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Asegúrate qu'esti nome de ficheru tien polo menos %(max)d caráuter (tien " +"%(length)d)." +msgstr[1] "" +"Asegúrate qu'esti nome de ficheru tien polo menos %(max)d caráuteres (tien " +"%(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Por favor, dunvia un ficheru o conseña la caxella , non dambos." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Xubi una imaxe válida. El ficheru que xubiesti o nun yera una imaxe, o taba " +"toriada." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Esbilla una escoyeta válida. %(value)s nun una ún de les escoyetes " +"disponibles." + +msgid "Enter a list of values." +msgstr "Introduz una llista valores." + +msgid "Enter a complete value." +msgstr "" + +msgid "Enter a valid UUID." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Campu anubríu %(name)s) %(error)s" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "Por favor, dunvia %d o menos formularios." +msgstr[1] "Por favor, dunvia %d o menos formularios." + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "Orde" + +msgid "Delete" +msgstr "Desanciar" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Por favor, igua'l datu duplicáu de %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Por favor, igua'l datu duplicáu pa %(field)s, el cual tien de ser únicu." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Por favor, igua'l datu duplicáu de %(field_name)s el cual tien de ser únicu " +"pal %(lookup)s en %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Por favor, igua los valores duplicaos embaxo" + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Esbilla una escoyeta válida. Esa escoyeta nun ye una de les escoyetes " +"disponibles." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Llimpiar" + +msgid "Currently" +msgstr "Anguaño" + +msgid "Change" +msgstr "Camudar" + +msgid "Unknown" +msgstr "Desconocíu" + +msgid "Yes" +msgstr "Sí" + +msgid "No" +msgstr "Non" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "sí,non,quiciabes" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d byte" +msgstr[1] "%(size)d bytes" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "Media nueche" + +msgid "noon" +msgstr "Meudía" + +msgid "Monday" +msgstr "Llunes" + +msgid "Tuesday" +msgstr "Martes" + +msgid "Wednesday" +msgstr "Miércoles" + +msgid "Thursday" +msgstr "Xueves" + +msgid "Friday" +msgstr "Vienres" + +msgid "Saturday" +msgstr "Sábadu" + +msgid "Sunday" +msgstr "Domingu" + +msgid "Mon" +msgstr "LLu" + +msgid "Tue" +msgstr "Mar" + +msgid "Wed" +msgstr "Mie" + +msgid "Thu" +msgstr "Xue" + +msgid "Fri" +msgstr "Vie" + +msgid "Sat" +msgstr "Sáb" + +msgid "Sun" +msgstr "Dom" + +msgid "January" +msgstr "Xineru" + +msgid "February" +msgstr "Febreru" + +msgid "March" +msgstr "Marzu" + +msgid "April" +msgstr "Abril" + +msgid "May" +msgstr "Mayu" + +msgid "June" +msgstr "Xunu" + +msgid "July" +msgstr "Xunetu" + +msgid "August" +msgstr "Agostu" + +msgid "September" +msgstr "Setiembre" + +msgid "October" +msgstr "Ochobre" + +msgid "November" +msgstr "Payares" + +msgid "December" +msgstr "Avientu" + +msgid "jan" +msgstr "xin" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "abr" + +msgid "may" +msgstr "may" + +msgid "jun" +msgstr "xun" + +msgid "jul" +msgstr "xnt" + +msgid "aug" +msgstr "ago" + +msgid "sep" +msgstr "set" + +msgid "oct" +msgstr "och" + +msgid "nov" +msgstr "pay" + +msgid "dec" +msgstr "avi" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Xin." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Mar." + +msgctxt "abbrev. month" +msgid "April" +msgstr "Abr." + +msgctxt "abbrev. month" +msgid "May" +msgstr "May." + +msgctxt "abbrev. month" +msgid "June" +msgstr "Xun." + +msgctxt "abbrev. month" +msgid "July" +msgstr "Xnt." + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Ago." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Set." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Och." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Pay." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Avi." + +msgctxt "alt. month" +msgid "January" +msgstr "Xineru" + +msgctxt "alt. month" +msgid "February" +msgstr "Febreru" + +msgctxt "alt. month" +msgid "March" +msgstr "Marzu" + +msgctxt "alt. month" +msgid "April" +msgstr "Abril" + +msgctxt "alt. month" +msgid "May" +msgstr "Mayu" + +msgctxt "alt. month" +msgid "June" +msgstr "Xunu" + +msgctxt "alt. month" +msgid "July" +msgstr "Xunetu" + +msgctxt "alt. month" +msgid "August" +msgstr "Agostu" + +msgctxt "alt. month" +msgid "September" +msgstr "Setiembre" + +msgctxt "alt. month" +msgid "October" +msgstr "Ochobre" + +msgctxt "alt. month" +msgid "November" +msgstr "Payares" + +msgctxt "alt. month" +msgid "December" +msgstr "Avientu" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "o" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d añu" +msgstr[1] "%d años" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d mes" +msgstr[1] "%d meses" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d selmana" +msgstr[1] "%d selmanes" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d día" +msgstr[1] "%d díes" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d hora" +msgstr[1] "%d hores" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d minutu" +msgstr[1] "%d minutos" + +msgid "0 minutes" +msgstr "0 minutos" + +msgid "Forbidden" +msgstr "" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "Nun s'especificó l'añu" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "Nun s'especificó'l mes" + +msgid "No day specified" +msgstr "Nun s'especificó'l día" + +msgid "No week specified" +msgstr "Nun s'especificó la selmana" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Ensin %(verbose_name_plural)s disponible" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Nun ta disponible'l %(verbose_name_plural)s futuru porque %(class_name)s." +"allow_future ye False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Nun s'alcontró %(verbose_name)s que concase cola gueta" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Páxina inválida (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Nun tán almitíos equí los indexaos de direutoriu." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Índiz de %(directory)s" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/az/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/az/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f24150d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/az/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/az/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/az/LC_MESSAGES/django.po new file mode 100644 index 0000000..2e25c04 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/az/LC_MESSAGES/django.po @@ -0,0 +1,1308 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Emin Mastizada , 2018,2020 +# Emin Mastizada , 2015-2016 +# Metin Amiroff , 2011 +# Nicat Məmmədov , 2022 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-05-17 05:23-0500\n" +"PO-Revision-Date: 2022-07-25 06:49+0000\n" +"Last-Translator: Nicat Məmmədov , 2022\n" +"Language-Team: Azerbaijani (http://www.transifex.com/django/django/language/" +"az/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: az\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Afrikaans" + +msgid "Arabic" +msgstr "Ərəbcə" + +msgid "Algerian Arabic" +msgstr "Əlcəzair Ərəbcəsi" + +msgid "Asturian" +msgstr "Asturiyaca" + +msgid "Azerbaijani" +msgstr "Azərbaycanca" + +msgid "Bulgarian" +msgstr "Bolqarca" + +msgid "Belarusian" +msgstr "Belarusca" + +msgid "Bengali" +msgstr "Benqalca" + +msgid "Breton" +msgstr "Bretonca" + +msgid "Bosnian" +msgstr "Bosniyaca" + +msgid "Catalan" +msgstr "Katalanca" + +msgid "Czech" +msgstr "Çexcə" + +msgid "Welsh" +msgstr "Uelscə" + +msgid "Danish" +msgstr "Danimarkaca" + +msgid "German" +msgstr "Almanca" + +msgid "Lower Sorbian" +msgstr "Aşağı Sorbca" + +msgid "Greek" +msgstr "Yunanca" + +msgid "English" +msgstr "İngiliscə" + +msgid "Australian English" +msgstr "Avstraliya İngiliscəsi" + +msgid "British English" +msgstr "Britaniya İngiliscəsi" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "İspanca" + +msgid "Argentinian Spanish" +msgstr "Argentina İspancası" + +msgid "Colombian Spanish" +msgstr "Kolumbia İspancası" + +msgid "Mexican Spanish" +msgstr "Meksika İspancası" + +msgid "Nicaraguan Spanish" +msgstr "Nikaraqua İspancası" + +msgid "Venezuelan Spanish" +msgstr "Venesuela İspancası" + +msgid "Estonian" +msgstr "Estonca" + +msgid "Basque" +msgstr "Baskca" + +msgid "Persian" +msgstr "Farsca" + +msgid "Finnish" +msgstr "Fincə" + +msgid "French" +msgstr "Fransızca" + +msgid "Frisian" +msgstr "Friscə" + +msgid "Irish" +msgstr "İrlandca" + +msgid "Scottish Gaelic" +msgstr "Şotland Keltcəsi" + +msgid "Galician" +msgstr "Qallik dili" + +msgid "Hebrew" +msgstr "İbranicə" + +msgid "Hindi" +msgstr "Hindcə" + +msgid "Croatian" +msgstr "Xorvatca" + +msgid "Upper Sorbian" +msgstr "Üst Sorbca" + +msgid "Hungarian" +msgstr "Macarca" + +msgid "Armenian" +msgstr "Ermənicə" + +msgid "Interlingua" +msgstr "İnterlinqua" + +msgid "Indonesian" +msgstr "İndonezcə" + +msgid "Igbo" +msgstr "İqbo dili" + +msgid "Ido" +msgstr "İdoca" + +msgid "Icelandic" +msgstr "İslandca" + +msgid "Italian" +msgstr "İtalyanca" + +msgid "Japanese" +msgstr "Yaponca" + +msgid "Georgian" +msgstr "Gürcücə" + +msgid "Kabyle" +msgstr "Kabile" + +msgid "Kazakh" +msgstr "Qazax" + +msgid "Khmer" +msgstr "Kxmercə" + +msgid "Kannada" +msgstr "Kannada dili" + +msgid "Korean" +msgstr "Koreyca" + +msgid "Kyrgyz" +msgstr "Qırğız" + +msgid "Luxembourgish" +msgstr "Lüksemburqca" + +msgid "Lithuanian" +msgstr "Litva dili" + +msgid "Latvian" +msgstr "Latviya dili" + +msgid "Macedonian" +msgstr "Makedonca" + +msgid "Malayalam" +msgstr "Malayamca" + +msgid "Mongolian" +msgstr "Monqolca" + +msgid "Marathi" +msgstr "Marathicə" + +msgid "Malay" +msgstr "Malay" + +msgid "Burmese" +msgstr "Burmescə" + +msgid "Norwegian Bokmål" +msgstr "Norveç Bukmolcası" + +msgid "Nepali" +msgstr "Nepal" + +msgid "Dutch" +msgstr "Flamandca" + +msgid "Norwegian Nynorsk" +msgstr "Nynorsk Norveçcəsi" + +msgid "Ossetic" +msgstr "Osetincə" + +msgid "Punjabi" +msgstr "Pancabicə" + +msgid "Polish" +msgstr "Polyakca" + +msgid "Portuguese" +msgstr "Portuqalca" + +msgid "Brazilian Portuguese" +msgstr "Braziliya Portuqalcası" + +msgid "Romanian" +msgstr "Rumınca" + +msgid "Russian" +msgstr "Rusca" + +msgid "Slovak" +msgstr "Slovakca" + +msgid "Slovenian" +msgstr "Slovencə" + +msgid "Albanian" +msgstr "Albanca" + +msgid "Serbian" +msgstr "Serbcə" + +msgid "Serbian Latin" +msgstr "Serbcə Latın" + +msgid "Swedish" +msgstr "İsveçcə" + +msgid "Swahili" +msgstr "Suahili" + +msgid "Tamil" +msgstr "Tamilcə" + +msgid "Telugu" +msgstr "Teluqu dili" + +msgid "Tajik" +msgstr "Tacik" + +msgid "Thai" +msgstr "Tayca" + +msgid "Turkmen" +msgstr "Türkmən" + +msgid "Turkish" +msgstr "Türkcə" + +msgid "Tatar" +msgstr "Tatar" + +msgid "Udmurt" +msgstr "Udmurtca" + +msgid "Ukrainian" +msgstr "Ukraynaca" + +msgid "Urdu" +msgstr "Urduca" + +msgid "Uzbek" +msgstr "Özbəkcə" + +msgid "Vietnamese" +msgstr "Vyetnamca" + +msgid "Simplified Chinese" +msgstr "Sadələşdirilmiş Çincə" + +msgid "Traditional Chinese" +msgstr "Ənənəvi Çincə" + +msgid "Messages" +msgstr "Mesajlar" + +msgid "Site Maps" +msgstr "Sayt Xəritələri" + +msgid "Static Files" +msgstr "Statik Fayllar" + +msgid "Syndication" +msgstr "Sindikasiya" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Səhifə nömrəsi rəqəm deyil" + +msgid "That page number is less than 1" +msgstr "Səhifə nömrəsi 1-dən balacadır" + +msgid "That page contains no results" +msgstr "Səhifədə nəticə yoxdur" + +msgid "Enter a valid value." +msgstr "Düzgün qiymət daxil edin." + +msgid "Enter a valid URL." +msgstr "Düzgün URL daxil edin." + +msgid "Enter a valid integer." +msgstr "Düzgün rəqəm daxil edin." + +msgid "Enter a valid email address." +msgstr "Düzgün e-poçt ünvanı daxil edin." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Hərflərdən, rəqəmlərdən, alt-xətlərdən və ya defislərdən ibarət düzgün " +"qısaltma (“slug”) daxil edin." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Unicode hərflərdən, rəqəmlərdən, alt-xətlərdən və ya defislərdən ibarət " +"düzgün qısaltma (“slug”) daxil edin." + +msgid "Enter a valid IPv4 address." +msgstr "Düzgün IPv4 ünvanı daxil edin." + +msgid "Enter a valid IPv6 address." +msgstr "Düzgün IPv6 ünvanını daxil edin." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Düzgün IPv4 və ya IPv6 ünvanını daxil edin." + +msgid "Enter only digits separated by commas." +msgstr "Vergüllə ayırmaqla yalnız rəqəmlər daxil edin." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Əmin edin ki, bu qiymət %(limit_value)s-dir (bu %(show_value)s-dir)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" +"Bu qiymətin %(limit_value)s-ya bərabər və ya ondan kiçik olduğunu yoxlayın." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" +"Bu qiymətin %(limit_value)s-ya bərabər və ya ondan böyük olduğunu yoxlayın." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Bu dəyərin ən az %(limit_value)d simvol olduğuna əmin olun (%(show_value)d " +"var)" +msgstr[1] "" +"Bu dəyərin ən az %(limit_value)d simvol olduğuna əmin olun (%(show_value)d " +"var)" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Bu dəyərin ən çox %(limit_value)d simvol olduğuna əmin olun (%(show_value)d " +"var)" +msgstr[1] "" +"Bu dəyərin ən çox %(limit_value)d simvol olduğuna əmin olun (%(show_value)d " +"var)" + +msgid "Enter a number." +msgstr "Ədəd daxil edin." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Toplamda %(max)s rəqəmdən çox olmadığına əmin olun." +msgstr[1] "Toplamda %(max)s rəqəmdən çox olmadığına əmin olun." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Onluq hissənin %(max)s rəqəmdən çox olmadığına əmin olun." +msgstr[1] "Onluq hissənin %(max)s rəqəmdən çox olmadığına əmin olun." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "Onluq hissədən əvvəl %(max)s rəqəmdən çox olmadığına əmin olun." +msgstr[1] "Onluq hissədən əvvəl %(max)s rəqəmdən çox olmadığına əmin olun." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"“%(extension)s” fayl uzantısına icazə verilmir. İcazə verilən fayl " +"uzantıları: %(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Null simvollara icazə verilmir." + +msgid "and" +msgstr "və" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(field_labels)s ilə %(model_name)s artıq mövcuddur." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "%(value)r dəyəri doğru seçim deyil." + +msgid "This field cannot be null." +msgstr "Bu sahə boş qala bilməz." + +msgid "This field cannot be blank." +msgstr "Bu sahə ağ qala bilməz." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s bu %(field_label)s sahə ilə artıq mövcuddur." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s dəyəri %(date_field_label)s %(lookup_type)s üçün unikal " +"olmalıdır." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Sahənin tipi: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "“%(value)s” dəyəri True və ya False olmalıdır." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "“%(value)s” dəyəri True, False və ya None olmalıdır." + +msgid "Boolean (Either True or False)" +msgstr "Bul (ya Doğru, ya Yalan)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Sətir (%(max_length)s simvola kimi)" + +msgid "Comma-separated integers" +msgstr "Vergüllə ayrılmış tam ədədlər" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"“%(value)s” dəyəri səhv tarix formatındadır. Formatı YYYY-MM-DD olmalıdır." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"“%(value)s” dəyəri düzgün formatdadır (YYYY-MM-DD) amma bu tarix xətalıdır." + +msgid "Date (without time)" +msgstr "Tarix (saatsız)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"“%(value)s” dəyərinin formatı səhvdir. Formatı YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ] olmalıdır." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"“%(value)s” dəyərinin formatı düzgündür (YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) " +"amma bu tarix xətalıdır." + +msgid "Date (with time)" +msgstr "Tarix (vaxt ilə)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "“%(value)s” dəyəri onluq kəsrli (decimal) rəqəm olmalıdır." + +msgid "Decimal number" +msgstr "Rasional ədəd" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"“%(value)s” dəyərinin formatı səhvdir. Formatı [DD] [HH:[MM:]]ss[.uuuuuu] " +"olmalıdır." + +msgid "Duration" +msgstr "Müddət" + +msgid "Email address" +msgstr "E-poçt" + +msgid "File path" +msgstr "Faylın ünvanı" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "“%(value)s” dəyəri float olmalıdır." + +msgid "Floating point number" +msgstr "Sürüşən vergüllü ədəd" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "“%(value)s” dəyəri tam rəqəm olmalıdır." + +msgid "Integer" +msgstr "Tam ədəd" + +msgid "Big (8 byte) integer" +msgstr "Böyük (8 bayt) tam ədəd" + +msgid "Small integer" +msgstr "Kiçik tam ədəd" + +msgid "IPv4 address" +msgstr "IPv4 ünvanı" + +msgid "IP address" +msgstr "IP ünvan" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "“%(value)s” dəyəri None, True və ya False olmalıdır." + +msgid "Boolean (Either True, False or None)" +msgstr "Bul (Ya Doğru, ya Yalan, ya da Heç nə)" + +msgid "Positive big integer" +msgstr "Müsbət böyük rəqəm" + +msgid "Positive integer" +msgstr "Müsbət tam ədəd" + +msgid "Positive small integer" +msgstr "Müsbət tam kiçik ədəd" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Əzmə (%(max_length)s simvola kimi)" + +msgid "Text" +msgstr "Mətn" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"“%(value)s” dəyərinin formatı səhvdir. Formatı HH:MM[:ss[.uuuuuu]] olmalıdır." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"“%(value)s” dəyəri düzgün formatdadır (HH:MM[:ss[.uuuuuu]]), amma vaxtı " +"xətalıdır." + +msgid "Time" +msgstr "Vaxt" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Düz ikili (binary) məlumat" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "“%(value)s” keçərli UUID deyil." + +msgid "Universally unique identifier" +msgstr "Universal təkrarolunmaz identifikator" + +msgid "File" +msgstr "Fayl" + +msgid "Image" +msgstr "Şəkil" + +msgid "A JSON object" +msgstr "JSON obyekti" + +msgid "Value must be valid JSON." +msgstr "Dəyər etibarlı JSON olmalıdır." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(field)s dəyəri %(value)r olan %(model)s mövcud deyil." + +msgid "Foreign Key (type determined by related field)" +msgstr "Xarici açar (bağlı olduğu sahəyə uyğun tipi alır)" + +msgid "One-to-one relationship" +msgstr "Birin-birə münasibət" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s əlaqəsi" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s əlaqələri" + +msgid "Many-to-many relationship" +msgstr "Çoxun-çoxa münasibət" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Bu sahə vacibdir." + +msgid "Enter a whole number." +msgstr "Tam ədəd daxil edin." + +msgid "Enter a valid date." +msgstr "Düzgün tarix daxil edin." + +msgid "Enter a valid time." +msgstr "Düzgün vaxt daxil edin." + +msgid "Enter a valid date/time." +msgstr "Düzgün tarix/vaxt daxil edin." + +msgid "Enter a valid duration." +msgstr "Keçərli müddət daxil edin." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Günlərin sayı {min_days} ilə {max_days} arasında olmalıdır." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Fayl göndərilməyib. Vərəqənin (\"form\") şifrələmə tipini yoxlayın." + +msgid "No file was submitted." +msgstr "Fayl göndərilməyib." + +msgid "The submitted file is empty." +msgstr "Göndərilən fayl boşdur." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Bu fayl adının ən çox %(max)d simvol olduğuna əmin olun (%(length)d var)." +msgstr[1] "" +"Bu fayl adının ən çox %(max)d simvol olduğuna əmin olun (%(length)d var)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Ya fayl göndərin, ya da xanaya quş qoymayın, hər ikisini də birdən etməyin." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Düzgün şəkil göndərin. Göndərdiyiniz fayl ya şəkil deyil, ya da şəkildə " +"problem var." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Düzgün seçim edin. %(value)s seçimlər arasında yoxdur." + +msgid "Enter a list of values." +msgstr "Qiymətlərin siyahısını daxil edin." + +msgid "Enter a complete value." +msgstr "Tam dəyər daxil edin." + +msgid "Enter a valid UUID." +msgstr "Keçərli UUID daxil et." + +msgid "Enter a valid JSON." +msgstr "Etibarlı bir JSON daxil edin." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Gizli %(name)s sahəsi) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Zəhmət olmasa ən çox %(num)d forma təsdiqləyin." +msgstr[1] "Zəhmət olmasa ən çox %(num)d forma təsdiqləyin." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Zəhmət olmasa ən az %(num)d forma təsdiqləyin." +msgstr[1] "Zəhmət olmasa ən az %(num)d forma təsdiqləyin." + +msgid "Order" +msgstr "Sırala" + +msgid "Delete" +msgstr "Sil" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "%(field)s sahəsinə görə təkrarlanan məlumatlara düzəliş edin." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"%(field)s sahəsinə görə təkrarlanan məlumatlara düzəliş edin, onların hamısı " +"fərqli olmalıdır." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"%(field_name)s sahəsinə görə təkrarlanan məlumatlara düzəliş edin, onlar " +"%(date_field)s %(lookup)s-a görə fərqli olmalıdır." + +msgid "Please correct the duplicate values below." +msgstr "Aşağıda təkrarlanan qiymətlərə düzəliş edin." + +msgid "The inline value did not match the parent instance." +msgstr "Sətiriçi dəyər ana nüsxəyə uyğun deyil." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Düzgün seçim edin. Bu seçim mümkün deyil." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "“%(pk)s” düzgün dəyər deyil." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s vaxtı %(current_timezone)s zaman qurşağında ifadə oluna bilmir; " +"ya duallıq, ya da mövcud olmaya bilər." + +msgid "Clear" +msgstr "Təmizlə" + +msgid "Currently" +msgstr "Hal-hazırda" + +msgid "Change" +msgstr "Dəyiş" + +msgid "Unknown" +msgstr "Məlum deyil" + +msgid "Yes" +msgstr "Hə" + +msgid "No" +msgstr "Yox" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "hə,yox,bəlkə" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d bayt" +msgstr[1] "%(size)d bayt" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s QB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "gecə yarısı" + +msgid "noon" +msgstr "günorta" + +msgid "Monday" +msgstr "Bazar ertəsi" + +msgid "Tuesday" +msgstr "Çərşənbə axşamı" + +msgid "Wednesday" +msgstr "Çərşənbə" + +msgid "Thursday" +msgstr "Cümə axşamı" + +msgid "Friday" +msgstr "Cümə" + +msgid "Saturday" +msgstr "Şənbə" + +msgid "Sunday" +msgstr "Bazar" + +msgid "Mon" +msgstr "B.e" + +msgid "Tue" +msgstr "Ç.a" + +msgid "Wed" +msgstr "Çrş" + +msgid "Thu" +msgstr "C.a" + +msgid "Fri" +msgstr "Cüm" + +msgid "Sat" +msgstr "Şnb" + +msgid "Sun" +msgstr "Bzr" + +msgid "January" +msgstr "Yanvar" + +msgid "February" +msgstr "Fevral" + +msgid "March" +msgstr "Mart" + +msgid "April" +msgstr "Aprel" + +msgid "May" +msgstr "May" + +msgid "June" +msgstr "İyun" + +msgid "July" +msgstr "İyul" + +msgid "August" +msgstr "Avqust" + +msgid "September" +msgstr "Sentyabr" + +msgid "October" +msgstr "Oktyabr" + +msgid "November" +msgstr "Noyabr" + +msgid "December" +msgstr "Dekabr" + +msgid "jan" +msgstr "ynv" + +msgid "feb" +msgstr "fvr" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "apr" + +msgid "may" +msgstr "may" + +msgid "jun" +msgstr "iyn" + +msgid "jul" +msgstr "iyl" + +msgid "aug" +msgstr "avq" + +msgid "sep" +msgstr "snt" + +msgid "oct" +msgstr "okt" + +msgid "nov" +msgstr "noy" + +msgid "dec" +msgstr "dek" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Yan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Fev." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Mart" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Aprel" + +msgctxt "abbrev. month" +msgid "May" +msgstr "May" + +msgctxt "abbrev. month" +msgid "June" +msgstr "İyun" + +msgctxt "abbrev. month" +msgid "July" +msgstr "İyul" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Avq." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Sent." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Okt." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Noy." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dek." + +msgctxt "alt. month" +msgid "January" +msgstr "Yanvar" + +msgctxt "alt. month" +msgid "February" +msgstr "Fevral" + +msgctxt "alt. month" +msgid "March" +msgstr "Mart" + +msgctxt "alt. month" +msgid "April" +msgstr "Aprel" + +msgctxt "alt. month" +msgid "May" +msgstr "May" + +msgctxt "alt. month" +msgid "June" +msgstr "İyun" + +msgctxt "alt. month" +msgid "July" +msgstr "İyul" + +msgctxt "alt. month" +msgid "August" +msgstr "Avqust" + +msgctxt "alt. month" +msgid "September" +msgstr "Sentyabr" + +msgctxt "alt. month" +msgid "October" +msgstr "Oktyabr" + +msgctxt "alt. month" +msgid "November" +msgstr "Noyabr" + +msgctxt "alt. month" +msgid "December" +msgstr "Dekabr" + +msgid "This is not a valid IPv6 address." +msgstr "Bu doğru IPv6 ünvanı deyil." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "və ya" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d il" +msgstr[1] "%(num)d il" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d ay" +msgstr[1] "%(num)d ay" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d həftə" +msgstr[1] "%(num)d həftə" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d gün" +msgstr[1] "%(num)d gün" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d saat" +msgstr[1] "%(num)d saat" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d dəqiqə" +msgstr[1] "%(num)d dəqiqə" + +msgid "Forbidden" +msgstr "Qadağan" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF təsdiqləmə alınmadı. Sorğu ləğv edildi." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Əgər səyyahınızın “Referer” başlığını göndərməsini söndürmüsünüzsə, lütfən " +"bu sayt üçün, HTTPS əlaqələr üçün və ya “same-origin” sorğular üçün aktiv " +"edin." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Əgər etiketini və ya " +"“Referrer-Policy: no-referrer” başlığını işlədirsinizsə, lütfən silin. CSRF " +"qoruma dəqiq yönləndirən yoxlaması üçün “Referer” başlığını tələb edir. Əgər " +"məxfilik üçün düşünürsünüzsə, üçüncü tərəf sayt keçidləri üçün kimi bir alternativ işlədin." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Bu sayt formaları göndərmək üçün CSRF çərəzini işlədir. Bu çərəz " +"səyyahınızın üçüncü biri tərəfindən hack-lənmədiyinə əmin olmaq üçün " +"istifadə edilir. " + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Əgər səyyahınızda çərəzlər söndürülübsə, lütfən bu sayt və ya “same-origin” " +"sorğular üçün aktiv edin." + +msgid "More information is available with DEBUG=True." +msgstr "Daha ətraflı məlumat DEBUG=True ilə mövcuddur." + +msgid "No year specified" +msgstr "İl göstərilməyib" + +msgid "Date out of range" +msgstr "Tarix aralığın xaricindədir" + +msgid "No month specified" +msgstr "Ay göstərilməyib" + +msgid "No day specified" +msgstr "Gün göstərilməyib" + +msgid "No week specified" +msgstr "Həftə göstərilməyib" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "%(verbose_name_plural)s seçmək mümkün deyil" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Gələcək %(verbose_name_plural)s seçmək mümkün deyil, çünki %(class_name)s." +"allow_future Yalan kimi qeyd olunub." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "“%(format)s” formatına görə “%(datestr)s” tarixi düzgün deyil" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Sorğuya uyğun %(verbose_name)s tapılmadı" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Səhifə həm “axırıncı” deyil, həm də tam ədədə çevrilə bilmir." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Qeyri-düzgün səhifə (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Siyahı boşdur və “%(class_name)s.allow_empty” dəyəri False-dur." + +msgid "Directory indexes are not allowed here." +msgstr "Ünvan indekslərinə icazə verilmir." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "“%(path)s” mövcud deyil" + +#, python-format +msgid "Index of %(directory)s" +msgstr "%(directory)s-nin indeksi" + +msgid "The install worked successfully! Congratulations!" +msgstr "Quruluş uğurla tamamlandı! Təbriklər!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Django %(version)s üçün buraxılış " +"qeydlərinə baxın" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" +"Tənzimləmə faylınızda DEBUG=True və heç bir URL qurmadığınız üçün bu səhifəni görürsünüz." + +msgid "Django Documentation" +msgstr "Django Sənədləri" + +msgid "Topics, references, & how-to’s" +msgstr "Mövzular, istinadlar və nümunələr" + +msgid "Tutorial: A Polling App" +msgstr "Məşğələ: Səsvermə Tətbiqi" + +msgid "Get started with Django" +msgstr "Django-ya başla" + +msgid "Django Community" +msgstr "Django İcması" + +msgid "Connect, get help, or contribute" +msgstr "Qoşul, kömək al və dəstək ol" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/az/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/az/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/az/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/az/formats.py new file mode 100644 index 0000000..253b6dd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/az/formats.py @@ -0,0 +1,30 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j E Y" +TIME_FORMAT = "G:i" +DATETIME_FORMAT = "j E Y, G:i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "d.m.Y" +SHORT_DATETIME_FORMAT = "d.m.Y H:i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d.%m.%Y", # '25.10.2006' + "%d.%m.%y", # '25.10.06' +] +DATETIME_INPUT_FORMATS = [ + "%d.%m.%Y %H:%M:%S", # '25.10.2006 14:30:59' + "%d.%m.%Y %H:%M:%S.%f", # '25.10.2006 14:30:59.000200' + "%d.%m.%Y %H:%M", # '25.10.2006 14:30' + "%d.%m.%y %H:%M:%S", # '25.10.06 14:30:59' + "%d.%m.%y %H:%M:%S.%f", # '25.10.06 14:30:59.000200' + "%d.%m.%y %H:%M", # '25.10.06 14:30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "\xa0" # non-breaking space +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/be/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/be/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c639c8b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/be/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/be/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/be/LC_MESSAGES/django.po new file mode 100644 index 0000000..c8dbffe --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/be/LC_MESSAGES/django.po @@ -0,0 +1,1383 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Viktar Palstsiuk , 2014-2015 +# znotdead , 2016-2017,2019-2021,2023 +# Bobsans , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: znotdead , 2016-2017,2019-2021,2023\n" +"Language-Team: Belarusian (http://app.transifex.com/django/django/language/" +"be/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: be\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || " +"(n%100>=11 && n%100<=14)? 2 : 3);\n" + +msgid "Afrikaans" +msgstr "Афрыкаанс" + +msgid "Arabic" +msgstr "Арабская" + +msgid "Algerian Arabic" +msgstr "Алжырская арабская" + +msgid "Asturian" +msgstr "Астурыйская" + +msgid "Azerbaijani" +msgstr "Азэрбайджанская" + +msgid "Bulgarian" +msgstr "Баўгарская" + +msgid "Belarusian" +msgstr "Беларуская" + +msgid "Bengali" +msgstr "Бэнґальская" + +msgid "Breton" +msgstr "Брэтонская" + +msgid "Bosnian" +msgstr "Басьнійская" + +msgid "Catalan" +msgstr "Каталёнская" + +msgid "Central Kurdish (Sorani)" +msgstr "Цэнтральнакурдская (сарані)" + +msgid "Czech" +msgstr "Чэская" + +msgid "Welsh" +msgstr "Валійская" + +msgid "Danish" +msgstr "Дацкая" + +msgid "German" +msgstr "Нямецкая" + +msgid "Lower Sorbian" +msgstr "Ніжнелужыцкая" + +msgid "Greek" +msgstr "Грэцкая" + +msgid "English" +msgstr "Анґельская" + +msgid "Australian English" +msgstr "Анґельская (Аўстралія)" + +msgid "British English" +msgstr "Анґельская (Брытанская)" + +msgid "Esperanto" +msgstr "Эспэранта" + +msgid "Spanish" +msgstr "Гішпанская" + +msgid "Argentinian Spanish" +msgstr "Гішпанская (Арґентына)" + +msgid "Colombian Spanish" +msgstr "Гішпанская (Калумбія)" + +msgid "Mexican Spanish" +msgstr "Гішпанская (Мэксыка)" + +msgid "Nicaraguan Spanish" +msgstr "Гішпанская (Нікараґуа)" + +msgid "Venezuelan Spanish" +msgstr "Іспанская (Вэнэсуэла)" + +msgid "Estonian" +msgstr "Эстонская" + +msgid "Basque" +msgstr "Басконская" + +msgid "Persian" +msgstr "Фарсі" + +msgid "Finnish" +msgstr "Фінская" + +msgid "French" +msgstr "Француская" + +msgid "Frisian" +msgstr "Фрызкая" + +msgid "Irish" +msgstr "Ірляндзкая" + +msgid "Scottish Gaelic" +msgstr "Гэльская шатляндзкая" + +msgid "Galician" +msgstr "Ґальская" + +msgid "Hebrew" +msgstr "Габрэйская" + +msgid "Hindi" +msgstr "Гінды" + +msgid "Croatian" +msgstr "Харвацкая" + +msgid "Upper Sorbian" +msgstr "Верхнелужыцкая" + +msgid "Hungarian" +msgstr "Вугорская" + +msgid "Armenian" +msgstr "Армянскі" + +msgid "Interlingua" +msgstr "Інтэрлінгва" + +msgid "Indonesian" +msgstr "Інданэзійская" + +msgid "Igbo" +msgstr "Ігба" + +msgid "Ido" +msgstr "Іда" + +msgid "Icelandic" +msgstr "Ісьляндзкая" + +msgid "Italian" +msgstr "Італьянская" + +msgid "Japanese" +msgstr "Японская" + +msgid "Georgian" +msgstr "Грузінская" + +msgid "Kabyle" +msgstr "Кабільскі" + +msgid "Kazakh" +msgstr "Казаская" + +msgid "Khmer" +msgstr "Кхмерская" + +msgid "Kannada" +msgstr "Каннада" + +msgid "Korean" +msgstr "Карэйская" + +msgid "Kyrgyz" +msgstr "Кіргізская" + +msgid "Luxembourgish" +msgstr "Люксэмбургская" + +msgid "Lithuanian" +msgstr "Літоўская" + +msgid "Latvian" +msgstr "Латыская" + +msgid "Macedonian" +msgstr "Македонская" + +msgid "Malayalam" +msgstr "Малаялам" + +msgid "Mongolian" +msgstr "Манґольская" + +msgid "Marathi" +msgstr "Маратхі" + +msgid "Malay" +msgstr "Малайская" + +msgid "Burmese" +msgstr "Бірманская" + +msgid "Norwegian Bokmål" +msgstr "Нарвэская букмал" + +msgid "Nepali" +msgstr "Нэпальская" + +msgid "Dutch" +msgstr "Галяндзкая" + +msgid "Norwegian Nynorsk" +msgstr "Нарвэская нюнорск" + +msgid "Ossetic" +msgstr "Асяцінская" + +msgid "Punjabi" +msgstr "Панджабі" + +msgid "Polish" +msgstr "Польская" + +msgid "Portuguese" +msgstr "Партуґальская" + +msgid "Brazilian Portuguese" +msgstr "Партуґальская (Бразылія)" + +msgid "Romanian" +msgstr "Румынская" + +msgid "Russian" +msgstr "Расейская" + +msgid "Slovak" +msgstr "Славацкая" + +msgid "Slovenian" +msgstr "Славенская" + +msgid "Albanian" +msgstr "Альбанская" + +msgid "Serbian" +msgstr "Сэрбская" + +msgid "Serbian Latin" +msgstr "Сэрбская (лацінка)" + +msgid "Swedish" +msgstr "Швэдзкая" + +msgid "Swahili" +msgstr "Суахілі" + +msgid "Tamil" +msgstr "Тамільская" + +msgid "Telugu" +msgstr "Тэлуґу" + +msgid "Tajik" +msgstr "Таджыкскі" + +msgid "Thai" +msgstr "Тайская" + +msgid "Turkmen" +msgstr "Туркменская" + +msgid "Turkish" +msgstr "Турэцкая" + +msgid "Tatar" +msgstr "Татарская" + +msgid "Udmurt" +msgstr "Удмурцкая" + +msgid "Uyghur" +msgstr "Уйгурскі" + +msgid "Ukrainian" +msgstr "Украінская" + +msgid "Urdu" +msgstr "Урду" + +msgid "Uzbek" +msgstr "Узбецкі" + +msgid "Vietnamese" +msgstr "Віетнамская" + +msgid "Simplified Chinese" +msgstr "Кітайская (спрошчаная)" + +msgid "Traditional Chinese" +msgstr "Кітайская (звычайная)" + +msgid "Messages" +msgstr "Паведамленні" + +msgid "Site Maps" +msgstr "Мапы сайту" + +msgid "Static Files" +msgstr "Cтатычныя файлы" + +msgid "Syndication" +msgstr "Сындыкацыя" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "..." + +msgid "That page number is not an integer" +msgstr "Лік гэтай старонкі не з'яўляецца цэлым лікам" + +msgid "That page number is less than 1" +msgstr "Лік старонкі менш чым 1" + +msgid "That page contains no results" +msgstr "Гэтая старонка не мае ніякіх вынікаў" + +msgid "Enter a valid value." +msgstr "Пазначце правільнае значэньне." + +msgid "Enter a valid URL." +msgstr "Пазначце чынную спасылку." + +msgid "Enter a valid integer." +msgstr "Увядзіце цэлы лік." + +msgid "Enter a valid email address." +msgstr "Увядзіце сапраўдны адрас электроннай пошты." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Значэнне павінна быць толькі з літараў, личбаў, знакаў падкрэслівання ці " +"злучкі." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Значэнне павінна быць толькі з літараў стандарту Unicode, личбаў, знакаў " +"падкрэслівання ці злучкі." + +msgid "Enter a valid IPv4 address." +msgstr "Пазначце чынны адрас IPv4." + +msgid "Enter a valid IPv6 address." +msgstr "Пазначце чынны адрас IPv6." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Пазначце чынны адрас IPv4 або IPv6." + +msgid "Enter only digits separated by commas." +msgstr "Набярыце лічбы, падзеленыя коскамі." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Упэўніцеся, што гэтае значэньне — %(limit_value)s (зараз яно — " +"%(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Значэньне мусіць быць меншым або роўным %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Значэньне мусіць быць большым або роўным %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "Пераканайцеся, што гэта значэнне кратнае памеру кроку %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"Пераканайцеся, што гэта значэнне кратнае памеру кроку %(limit_value)s, " +"пачынаючы з %(offset)s, напрыклад. %(offset)s, %(valid_value1)s, " +"%(valid_value2)s, і гэтак далей." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Упэўніцеся, што гэтае значэнне мае не менш %(limit_value)d сімвал (зараз " +"%(show_value)d)." +msgstr[1] "" +"Упэўніцеся, што гэтае значэнне мае не менш %(limit_value)d сімвала (зараз " +"%(show_value)d)." +msgstr[2] "" +"Упэўніцеся, што гэтае значэнне мае не менш %(limit_value)d сімвалаў (зараз " +"%(show_value)d)." +msgstr[3] "" +"Упэўніцеся, што гэтае значэнне мае не менш %(limit_value)d сімвалаў (зараз " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Упэўніцеся, што гэтае значэнне мае не болей %(limit_value)d сімвал (зараз " +"%(show_value)d)." +msgstr[1] "" +"Упэўніцеся, што гэтае значэнне мае не болей %(limit_value)d сімвала (зараз " +"%(show_value)d)." +msgstr[2] "" +"Упэўніцеся, што гэтае значэнне мае не болей %(limit_value)d сімвалаў (зараз " +"%(show_value)d)." +msgstr[3] "" +"Упэўніцеся, што гэтае значэнне мае не болей %(limit_value)d сімвалаў (зараз " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Набярыце лік." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Упэўніцеся, што набралі ня болей за %(max)s лічбу." +msgstr[1] "Упэўніцеся, што набралі ня болей за %(max)s лічбы." +msgstr[2] "Упэўніцеся, што набралі ня болей за %(max)s лічбаў." +msgstr[3] "Упэўніцеся, што набралі ня болей за %(max)s лічбаў." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Упэўніцеся, што набралі ня болей за %(max)s лічбу пасьля коскі." +msgstr[1] "Упэўніцеся, што набралі ня болей за %(max)s лічбы пасьля коскі." +msgstr[2] "Упэўніцеся, што набралі ня болей за %(max)s лічбаў пасьля коскі." +msgstr[3] "Упэўніцеся, што набралі ня болей за %(max)s лічбаў пасьля коскі." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "Упэўніцеся, што набралі ня болей за %(max)s лічбу да коскі." +msgstr[1] "Упэўніцеся, што набралі ня болей за %(max)s лічбы да коскі." +msgstr[2] "Упэўніцеся, што набралі ня болей за %(max)s лічбаў да коскі." +msgstr[3] "Упэўніцеся, што набралі ня болей за %(max)s лічбаў да коскі." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Пашырэнне файла “%(extension)s” не дапускаецца. Дапушчальныя пашырэння: " +"%(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Null сімвалы не дапускаюцца." + +msgid "and" +msgstr "і" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s з такім %(field_labels)s ужо існуе." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Абмежаванне \"%(name)s\" парушана." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Значэнне %(value)r не з'яўляецца правільным выбарам." + +msgid "This field cannot be null." +msgstr "Поле ня можа мець значэньне «null»." + +msgid "This field cannot be blank." +msgstr "Трэба запоўніць поле." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s з такім %(field_label)s ужо існуе." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s павінна быць унікальна для %(date_field_label)s " +"%(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Палі віду: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "Значэньне “%(value)s” павінна быць True альбо False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "Значэньне “%(value)s” павінна быць True, False альбо None." + +msgid "Boolean (Either True or False)" +msgstr "Ляґічнае («сапраўдна» або «не сапраўдна»)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Радок (ня болей за %(max_length)s)" + +msgid "String (unlimited)" +msgstr "Радок (неабмежаваны)" + +msgid "Comma-separated integers" +msgstr "Цэлыя лікі, падзеленыя коскаю" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"Значэнне “%(value)s” мае няправільны фармат. Яно павінна быць у фармаце ГГГГ-" +"ММ-ДД." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"Значэнне “%(value)s” мае правільны фармат(ГГГГ-ММ-ДД) але гэта несапраўдная " +"дата." + +msgid "Date (without time)" +msgstr "Дата (бяз часу)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"Значэнне “%(value)s” мае няправільны фармат. Яно павінна быць у фармаце ГГГГ-" +"ММ-ДД ГГ:ХХ[:сс[.мммммм]][ЧА], дзе ЧА — часавы абсяг." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"Значэнне “%(value)s” мае правільны фармат (ГГГГ-ММ-ДД ГГ:ХХ[:сс[.мммммм]]" +"[ЧА], дзе ЧА — часавы абсяг) але гэта несапраўдныя дата/час." + +msgid "Date (with time)" +msgstr "Дата (разам з часам)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "Значэньне “%(value)s” павінна быць дзесятковым лікам." + +msgid "Decimal number" +msgstr "Дзесятковы лік" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"Значэньне “%(value)s” мае няправільны фармат. Яно павінна быць у фармаце " +"[ДД] [ГГ:[ХХ:]]сс[.мммммм]." + +msgid "Duration" +msgstr "Працягласць" + +msgid "Email address" +msgstr "Адрас эл. пошты" + +msgid "File path" +msgstr "Шлях да файла" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "Значэньне “%(value)s” павінна быць дробным лікам." + +msgid "Floating point number" +msgstr "Лік зь пераноснай коскаю" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "Значэньне “%(value)s” павінна быць цэлым лікам." + +msgid "Integer" +msgstr "Цэлы лік" + +msgid "Big (8 byte) integer" +msgstr "Вялікі (8 байтаў) цэлы" + +msgid "Small integer" +msgstr "Малы цэлы лік" + +msgid "IPv4 address" +msgstr "Адрас IPv4" + +msgid "IP address" +msgstr "Адрас IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "Значэньне “%(value)s” павінна быць None, True альбо False." + +msgid "Boolean (Either True, False or None)" +msgstr "Ляґічнае («сапраўдна», «не сапраўдна» ці «нічога»)" + +msgid "Positive big integer" +msgstr "Дадатны вялікі цэлы лік" + +msgid "Positive integer" +msgstr "Дадатны цэлы лік" + +msgid "Positive small integer" +msgstr "Дадатны малы цэлы лік" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Бірка (ня болей за %(max_length)s)" + +msgid "Text" +msgstr "Тэкст" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"Значэньне “%(value)s” мае няправільны фармат. Яно павінна быць у фармаце ГГ:" +"ХХ[:сс[.мммммм]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"Значэнне “%(value)s” мае правільны фармат (ГГ:ХХ[:сс[.мммммм]]) але гэта " +"несапраўдны час." + +msgid "Time" +msgstr "Час" + +msgid "URL" +msgstr "Сеціўная спасылка" + +msgid "Raw binary data" +msgstr "Неапрацаваныя бінарныя зьвесткі" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "“%(value)s” не з'яўляецца дапушчальным UUID." + +msgid "Universally unique identifier" +msgstr "Універсальны непаўторны ідэнтыфікатар" + +msgid "File" +msgstr "Файл" + +msgid "Image" +msgstr "Выява" + +msgid "A JSON object" +msgstr "Аб'ект JSON" + +msgid "Value must be valid JSON." +msgstr "Значэньне павінна быць сапраўдным JSON." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "Экземпляр %(model)s з %(field)s %(value)r не iснуе." + +msgid "Foreign Key (type determined by related field)" +msgstr "Вонкавы ключ (від вызначаецца паводле зьвязанага поля)" + +msgid "One-to-one relationship" +msgstr "Сувязь «адзін да аднаго»" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "Сувязь %(from)s-%(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "Сувязi %(from)s-%(to)s" + +msgid "Many-to-many relationship" +msgstr "Сувязь «некалькі да некалькіх»" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Поле трэба запоўніць." + +msgid "Enter a whole number." +msgstr "Набярыце ўвесь лік." + +msgid "Enter a valid date." +msgstr "Пазначце чынную дату." + +msgid "Enter a valid time." +msgstr "Пазначце чынны час." + +msgid "Enter a valid date/time." +msgstr "Пазначце чынныя час і дату." + +msgid "Enter a valid duration." +msgstr "Увядзіце сапраўдны тэрмін." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Колькасць дзён павінна быць паміж {min_days} i {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Файл не даслалі. Зірніце кадоўку блянку." + +msgid "No file was submitted." +msgstr "Файл не даслалі." + +msgid "The submitted file is empty." +msgstr "Дасланы файл — парожні." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Упэўніцеся, што гэтае імя файлу мае не болей %(max)d сімвал (зараз " +"%(length)d)." +msgstr[1] "" +"Упэўніцеся, што гэтае імя файлу мае не болей %(max)d сімвала (зараз " +"%(length)d)." +msgstr[2] "" +"Упэўніцеся, што гэтае імя файлу мае не болей %(max)d сімвалаў (зараз " +"%(length)d)." +msgstr[3] "" +"Упэўніцеся, што гэтае імя файлу мае не болей %(max)d сімвалаў (зараз " +"%(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Трэба або даслаць файл, або абраць «Ачысьціць», але нельга рабіць гэта " +"адначасова." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Запампаваць чынны малюнак. Запампавалі або не выяву, або пашкоджаную выяву." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Абярыце дазволенае. %(value)s няма ў даступных значэньнях." + +msgid "Enter a list of values." +msgstr "Упішыце сьпіс значэньняў." + +msgid "Enter a complete value." +msgstr "Калі ласка, увядзіце поўнае значэньне." + +msgid "Enter a valid UUID." +msgstr "Увядзіце сапраўдны UUID." + +msgid "Enter a valid JSON." +msgstr "Пазначце сапраўдны JSON." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Схаванае поле %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"Дадзеныя формы ManagementForm адсутнічаюць ці былі падменены. Адсутнічаюць " +"палі: %(field_names)s. Магчыма, вам спатрэбіцца падаць справаздачу пра " +"памылку, калі праблема захоўваецца." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Калі ласка, адпраўце не болей чым %(num)d формаў." +msgstr[1] "Калі ласка, адпраўце не болей чым %(num)d формаў." +msgstr[2] "Калі ласка, адпраўце не болей чым %(num)d формаў." +msgstr[3] "Калі ласка, адпраўце не болей чым %(num)d формаў." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Калі ласка, адпраўце не менш чым %(num)d формаў." +msgstr[1] "Калі ласка, адпраўце не менш чым %(num)d формаў." +msgstr[2] "Калі ласка, адпраўце не менш чым %(num)d формаў." +msgstr[3] "Калі ласка, адпраўце не менш чым %(num)d формаў." + +msgid "Order" +msgstr "Парадак" + +msgid "Delete" +msgstr "Выдаліць" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "У полі «%(field)s» выпраўце зьвесткі, якія паўтараюцца." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Выпраўце зьвесткі ў полі «%(field)s»: нельга, каб яны паўтараліся." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Выпраўце зьвесткі ў полі «%(field_name)s»: нельга каб зьвесткі ў " +"«%(date_field)s» для «%(lookup)s» паўтараліся." + +msgid "Please correct the duplicate values below." +msgstr "Выпраўце зьвесткі, якія паўтараюцца (гл. ніжэй)." + +msgid "The inline value did not match the parent instance." +msgstr "Убудаванае значэнне не супадае з бацькоўскім значэннем." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Абярыце дазволенае. Абранага няма ў даступных значэньнях." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "“%(pk)s” не сапраўднае значэнне." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"У часавым абсягу %(current_timezone)s нельга зразумець дату %(datetime)s: " +"яна можа быць неадназначнаю або яе можа не існаваць." + +msgid "Clear" +msgstr "Ачысьціць" + +msgid "Currently" +msgstr "Зараз" + +msgid "Change" +msgstr "Зьмяніць" + +msgid "Unknown" +msgstr "Невядома" + +msgid "Yes" +msgstr "Так" + +msgid "No" +msgstr "Не" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "так,не,магчыма" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d байт" +msgstr[1] "%(size)d байты" +msgstr[2] "%(size)d байтаў" +msgstr[3] "%(size)d байтаў" + +#, python-format +msgid "%s KB" +msgstr "%s КБ" + +#, python-format +msgid "%s MB" +msgstr "%s МБ" + +#, python-format +msgid "%s GB" +msgstr "%s ҐБ" + +#, python-format +msgid "%s TB" +msgstr "%s ТБ" + +#, python-format +msgid "%s PB" +msgstr "%s ПБ" + +msgid "p.m." +msgstr "папаўдні" + +msgid "a.m." +msgstr "папоўначы" + +msgid "PM" +msgstr "папаўдні" + +msgid "AM" +msgstr "папоўначы" + +msgid "midnight" +msgstr "поўнач" + +msgid "noon" +msgstr "поўдзень" + +msgid "Monday" +msgstr "Панядзелак" + +msgid "Tuesday" +msgstr "Аўторак" + +msgid "Wednesday" +msgstr "Серада" + +msgid "Thursday" +msgstr "Чацьвер" + +msgid "Friday" +msgstr "Пятніца" + +msgid "Saturday" +msgstr "Субота" + +msgid "Sunday" +msgstr "Нядзеля" + +msgid "Mon" +msgstr "Пн" + +msgid "Tue" +msgstr "Аў" + +msgid "Wed" +msgstr "Ср" + +msgid "Thu" +msgstr "Чц" + +msgid "Fri" +msgstr "Пт" + +msgid "Sat" +msgstr "Сб" + +msgid "Sun" +msgstr "Нд" + +msgid "January" +msgstr "студзеня" + +msgid "February" +msgstr "лютага" + +msgid "March" +msgstr "сакавік" + +msgid "April" +msgstr "красавіка" + +msgid "May" +msgstr "траўня" + +msgid "June" +msgstr "чэрвеня" + +msgid "July" +msgstr "ліпеня" + +msgid "August" +msgstr "жніўня" + +msgid "September" +msgstr "верасьня" + +msgid "October" +msgstr "кастрычніка" + +msgid "November" +msgstr "лістапада" + +msgid "December" +msgstr "сьнежня" + +msgid "jan" +msgstr "сту" + +msgid "feb" +msgstr "лют" + +msgid "mar" +msgstr "сак" + +msgid "apr" +msgstr "кра" + +msgid "may" +msgstr "тра" + +msgid "jun" +msgstr "чэр" + +msgid "jul" +msgstr "ліп" + +msgid "aug" +msgstr "жні" + +msgid "sep" +msgstr "вер" + +msgid "oct" +msgstr "кас" + +msgid "nov" +msgstr "ліс" + +msgid "dec" +msgstr "сьн" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Сту." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Люты" + +msgctxt "abbrev. month" +msgid "March" +msgstr "сакавік" + +msgctxt "abbrev. month" +msgid "April" +msgstr "красавіка" + +msgctxt "abbrev. month" +msgid "May" +msgstr "траўня" + +msgctxt "abbrev. month" +msgid "June" +msgstr "чэрвеня" + +msgctxt "abbrev. month" +msgid "July" +msgstr "ліпеня" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Жні." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Вер." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Кас." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Ліс." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Сьн." + +msgctxt "alt. month" +msgid "January" +msgstr "студзеня" + +msgctxt "alt. month" +msgid "February" +msgstr "лютага" + +msgctxt "alt. month" +msgid "March" +msgstr "сакавік" + +msgctxt "alt. month" +msgid "April" +msgstr "красавіка" + +msgctxt "alt. month" +msgid "May" +msgstr "траўня" + +msgctxt "alt. month" +msgid "June" +msgstr "чэрвеня" + +msgctxt "alt. month" +msgid "July" +msgstr "ліпеня" + +msgctxt "alt. month" +msgid "August" +msgstr "жніўня" + +msgctxt "alt. month" +msgid "September" +msgstr "верасьня" + +msgctxt "alt. month" +msgid "October" +msgstr "кастрычніка" + +msgctxt "alt. month" +msgid "November" +msgstr "лістапада" + +msgctxt "alt. month" +msgid "December" +msgstr "сьнежня" + +msgid "This is not a valid IPv6 address." +msgstr "Гэта ня правільны адрас IPv6." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "або" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d год" +msgstr[1] "%(num)d гадоў" +msgstr[2] "%(num)d гадоў" +msgstr[3] "%(num)d гадоў" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d месяц" +msgstr[1] "%(num)d месяцаў" +msgstr[2] "%(num)d месяцаў" +msgstr[3] "%(num)d месяцаў" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d тыдзень" +msgstr[1] "%(num)d тыдняў" +msgstr[2] "%(num)d тыдняў" +msgstr[3] "%(num)d тыдняў" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d дзень" +msgstr[1] "%(num)d дзён" +msgstr[2] "%(num)d дзён" +msgstr[3] "%(num)d дзён" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d гадзіна" +msgstr[1] "%(num)d гадзін" +msgstr[2] "%(num)d гадзін" +msgstr[3] "%(num)d гадзін" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d хвіліна" +msgstr[1] "%(num)d хвілін" +msgstr[2] "%(num)d хвілін" +msgstr[3] "%(num)d хвілін" + +msgid "Forbidden" +msgstr "Забаронена" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF-праверка не атрымалася. Запыт спынены." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Вы бачыце гэта паведамленне, таму што гэты HTTPS-сайт патрабуе каб Referer " +"загаловак быў адасланы вашым аглядальнікам, але гэтага не адбылося. Гэты " +"загаловак неабходны для бяспекі, каб пераканацца, што ваш аглядальнік не " +"ўзаламаны трэцімі асобамі." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Калі вы сканфігуравалі ваш браўзэр так, каб ён не працаваў з “Referer” " +"загалоўкамі, калі ласка дазвольце іх хаця б для гэтага сайту, ці для HTTPS " +"злучэнняў, ці для 'same-origin' запытаў." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Калі вы выкарыстоўваеце тэг " +"ці дадалі загаловак “Referrer-Policy: no-referrer”, калі ласка выдаліце іх. " +"CSRF абароне неабходны “Referer” загаловак для строгай праверкі. Калі Вы " +"турбуецеся аб прыватнасці, выкарыстоўвайце альтэрнатывы, напрыклад , для спасылкі на сайты трэціх асоб." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Вы бачыце гэта паведамленне, таму што гэты сайт патрабуе CSRF кукі для " +"адсылкі формы. Гэтыя кукі неабходныя для бяспекі, каб пераканацца, што ваш " +"браўзэр не ўзламаны трэцімі асобамі." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Калі вы сканфігуравалі ваш браўзэр так, каб ён не працаваў з кукамі, калі " +"ласка дазвольце іх хаця б для гэтага сайту ці для “same-origin” запытаў." + +msgid "More information is available with DEBUG=True." +msgstr "Больш падрабязная інфармацыя даступная з DEBUG=True." + +msgid "No year specified" +msgstr "Не пазначылі год" + +msgid "Date out of range" +msgstr "Дата выходзіць за межы дыяпазону" + +msgid "No month specified" +msgstr "Не пазначылі месяц" + +msgid "No day specified" +msgstr "Не пазначылі дзень" + +msgid "No week specified" +msgstr "Не пазначылі тыдзень" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Няма доступу да %(verbose_name_plural)s" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Няма доступу да %(verbose_name_plural)s, якія будуць, бо «%(class_name)s." +"allow_future» мае значэньне «не сапраўдна»." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Радок даты “%(datestr)s” не адпавядае выгляду “%(format)s”" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Па запыце не знайшлі ніводнага %(verbose_name)s" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" +"Нумар бачыны ня мае значэньня “last” і яго нельга ператварыць у цэлы лік." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Няправільная старонка (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" +"Сьпіс парожні, але “%(class_name)s.allow_empty” мае значэньне «не " +"сапраўдна», што забараняе паказваць парожнія сьпісы." + +msgid "Directory indexes are not allowed here." +msgstr "Не дазваляецца глядзець сьпіс файлаў каталёґа." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "“%(path)s” не існуе" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Файлы каталёґа «%(directory)s»" + +msgid "The install worked successfully! Congratulations!" +msgstr "Усталяванне прайшло паспяхова! Віншаванні!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Паглядзець заўвагі да выпуску для Джангі " +"%(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Вы бачыце гэту старонку таму што DEBUG=True у вашым файле налад і вы не " +"сканфігурыравалі ніякіх URL." + +msgid "Django Documentation" +msgstr "Дакументацыя Джангі" + +msgid "Topics, references, & how-to’s" +msgstr "Тэмы, спасылкі, & як зрабіць" + +msgid "Tutorial: A Polling App" +msgstr "Падручнік: Дадатак для галасавання" + +msgid "Get started with Django" +msgstr "Пачніце з Джангаю" + +msgid "Django Community" +msgstr "Джанга супольнасць" + +msgid "Connect, get help, or contribute" +msgstr "Злучайцеся, атрымлівайце дапамогу, ці спрыяйце" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bg/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bg/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b7b8c86 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bg/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bg/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bg/LC_MESSAGES/django.po new file mode 100644 index 0000000..7446b54 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bg/LC_MESSAGES/django.po @@ -0,0 +1,1344 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# arneatec , 2022-2023 +# Boris Chervenkov , 2012 +# Claude Paroz , 2020 +# Jannis Leidel , 2011 +# Lyuboslav Petrov , 2014 +# Mariusz Felisiak , 2023 +# Todor Lubenov , 2013-2015 +# Venelin Stoykov , 2015-2017 +# vestimir , 2014 +# Alexander Atanasov , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Mariusz Felisiak , 2023\n" +"Language-Team: Bulgarian (http://app.transifex.com/django/django/language/" +"bg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "африкаански" + +msgid "Arabic" +msgstr "арабски език" + +msgid "Algerian Arabic" +msgstr "алжирски арабски" + +msgid "Asturian" +msgstr "Астурийски" + +msgid "Azerbaijani" +msgstr "Азербайджански език" + +msgid "Bulgarian" +msgstr "български език" + +msgid "Belarusian" +msgstr "Беларуски" + +msgid "Bengali" +msgstr "бенгалски език" + +msgid "Breton" +msgstr "Бретон" + +msgid "Bosnian" +msgstr "босненски език" + +msgid "Catalan" +msgstr "каталански" + +msgid "Central Kurdish (Sorani)" +msgstr "Кюрдски, централен (Сорани)" + +msgid "Czech" +msgstr "чешки" + +msgid "Welsh" +msgstr "уелски" + +msgid "Danish" +msgstr "датски" + +msgid "German" +msgstr "немски" + +msgid "Lower Sorbian" +msgstr "долносорбски" + +msgid "Greek" +msgstr "гръцки" + +msgid "English" +msgstr "английски" + +msgid "Australian English" +msgstr "австралийски английски" + +msgid "British English" +msgstr "британски английски" + +msgid "Esperanto" +msgstr "есперанто" + +msgid "Spanish" +msgstr "испански" + +msgid "Argentinian Spanish" +msgstr "кастилски" + +msgid "Colombian Spanish" +msgstr "колумбийски испански" + +msgid "Mexican Spanish" +msgstr "мексикански испански" + +msgid "Nicaraguan Spanish" +msgstr "никарагуански испански" + +msgid "Venezuelan Spanish" +msgstr "венецуелски испански" + +msgid "Estonian" +msgstr "естонски" + +msgid "Basque" +msgstr "баски" + +msgid "Persian" +msgstr "персийски" + +msgid "Finnish" +msgstr "финландски" + +msgid "French" +msgstr "френски" + +msgid "Frisian" +msgstr "фризийски" + +msgid "Irish" +msgstr "ирландски" + +msgid "Scottish Gaelic" +msgstr "шотландски галски" + +msgid "Galician" +msgstr "галицейски" + +msgid "Hebrew" +msgstr "иврит" + +msgid "Hindi" +msgstr "хинди" + +msgid "Croatian" +msgstr "хърватски" + +msgid "Upper Sorbian" +msgstr "горносорбски" + +msgid "Hungarian" +msgstr "унгарски" + +msgid "Armenian" +msgstr "арменски" + +msgid "Interlingua" +msgstr "интерлингва" + +msgid "Indonesian" +msgstr "индонезийски" + +msgid "Igbo" +msgstr "игбо" + +msgid "Ido" +msgstr "идо" + +msgid "Icelandic" +msgstr "исландски" + +msgid "Italian" +msgstr "италиански" + +msgid "Japanese" +msgstr "японски" + +msgid "Georgian" +msgstr "грузински" + +msgid "Kabyle" +msgstr "кабилски" + +msgid "Kazakh" +msgstr "казахски" + +msgid "Khmer" +msgstr "кхмерски" + +msgid "Kannada" +msgstr "каннада" + +msgid "Korean" +msgstr "корейски" + +msgid "Kyrgyz" +msgstr "киргизки" + +msgid "Luxembourgish" +msgstr "люксембургски" + +msgid "Lithuanian" +msgstr "литовски" + +msgid "Latvian" +msgstr "латвийски" + +msgid "Macedonian" +msgstr "македонски" + +msgid "Malayalam" +msgstr "малаялам" + +msgid "Mongolian" +msgstr "монголски" + +msgid "Marathi" +msgstr "марати" + +msgid "Malay" +msgstr "малайски" + +msgid "Burmese" +msgstr "бирмански" + +msgid "Norwegian Bokmål" +msgstr "норвежки букмол" + +msgid "Nepali" +msgstr "непалски" + +msgid "Dutch" +msgstr "нидерландски" + +msgid "Norwegian Nynorsk" +msgstr "съвременен норвежки" + +msgid "Ossetic" +msgstr "осетски" + +msgid "Punjabi" +msgstr "панджабски" + +msgid "Polish" +msgstr "полски" + +msgid "Portuguese" +msgstr "португалски" + +msgid "Brazilian Portuguese" +msgstr "бразилски португалски" + +msgid "Romanian" +msgstr "румънски" + +msgid "Russian" +msgstr "руски" + +msgid "Slovak" +msgstr "словашки" + +msgid "Slovenian" +msgstr "словенски" + +msgid "Albanian" +msgstr "албански" + +msgid "Serbian" +msgstr "сръбски" + +msgid "Serbian Latin" +msgstr "сръбски - латиница" + +msgid "Swedish" +msgstr "шведски" + +msgid "Swahili" +msgstr "суахили" + +msgid "Tamil" +msgstr "тамилски" + +msgid "Telugu" +msgstr "телугу" + +msgid "Tajik" +msgstr "таджикски" + +msgid "Thai" +msgstr "тайландски" + +msgid "Turkmen" +msgstr "туркменски" + +msgid "Turkish" +msgstr "турски" + +msgid "Tatar" +msgstr "татарски" + +msgid "Udmurt" +msgstr "удмурт" + +msgid "Uyghur" +msgstr "" + +msgid "Ukrainian" +msgstr "украински" + +msgid "Urdu" +msgstr "урду" + +msgid "Uzbek" +msgstr "узбекски" + +msgid "Vietnamese" +msgstr "виетнамски" + +msgid "Simplified Chinese" +msgstr "китайски" + +msgid "Traditional Chinese" +msgstr "традиционен китайски" + +msgid "Messages" +msgstr "Съобщения" + +msgid "Site Maps" +msgstr "Карти на сайта" + +msgid "Static Files" +msgstr "Статични файлове" + +msgid "Syndication" +msgstr "Синдикация" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "..." + +msgid "That page number is not an integer" +msgstr "Номерът на страницата не е цяло число" + +msgid "That page number is less than 1" +msgstr "Номерът на страницата е по-малък от 1" + +msgid "That page contains no results" +msgstr "В тази страница няма резултати" + +msgid "Enter a valid value." +msgstr "Въведете валидна стойност. " + +msgid "Enter a valid URL." +msgstr "Въведете валиден URL адрес." + +msgid "Enter a valid integer." +msgstr "Въведете валидно целочислено число." + +msgid "Enter a valid email address." +msgstr "Въведете валиден имейл адрес." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Въведете валиден 'слъг', състоящ се от букви, цифри, тирета или долни тирета." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Въведете валиден 'слъг', състоящ се от Уникод букви, цифри, тирета или долни " +"тирета." + +msgid "Enter a valid IPv4 address." +msgstr "Въведете валиден IPv4 адрес." + +msgid "Enter a valid IPv6 address." +msgstr "Въведете валиден IPv6 адрес." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Въведете валиден IPv4 или IPv6 адрес." + +msgid "Enter only digits separated by commas." +msgstr "Въведете само еднозначни числа, разделени със запетая. " + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Уверете се, че тази стойност е %(limit_value)s (тя е %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Уверете се, че тази стойност е по-малка или равна на %(limit_value)s ." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" +"Уверете се, че тази стойност е по-голяма или равна на %(limit_value)s ." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "Уверете се, че стойността е кратна на стъпката %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Уверете се, че тази стойност е най-малко %(limit_value)d знака (тя има " +"%(show_value)d )." +msgstr[1] "" +"Уверете се, че тази стойност е най-малко %(limit_value)d знака (тя има " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Уверете се, тази стойност има най-много %(limit_value)d знака (тя има " +"%(show_value)d)." +msgstr[1] "" +"Уверете се, че тази стойност има най-много %(limit_value)d знака (тя има " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Въведете число." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Уверете се, че има не повече от %(max)s цифри общо." +msgstr[1] "Уверете се, че има не повече от %(max)s цифри общо." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +"Уверете се, че има не повече от%(max)s знак след десетичната запетая." +msgstr[1] "" +"Уверете се, че има не повече от %(max)s знака след десетичната запетая." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Уверете се, че има не повече от %(max)s цифра преди десетичната запетая." +msgstr[1] "" +"Уверете се, че има не повече от %(max)s цифри преди десетичната запетая." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Не са разрешени файлове с раширение \"%(extension)s\". Позволените " +"разширения са: %(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Празни знаци не са разрешени." + +msgid "and" +msgstr "и" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s с този %(field_labels)s вече съществува." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Ограничението “%(name)s” е нарушено." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Стойността %(value)r не е валиден избор." + +msgid "This field cannot be null." +msgstr "Това поле не може да има празна стойност." + +msgid "This field cannot be blank." +msgstr "Това поле не може да е празно." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s с този %(field_label)s вече съществува." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s трябва да е уникално за %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Поле от тип: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "Стойността на \"%(value)s\" трябва да бъде или True, или False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "Стойност \"%(value)s\" трябва да бъде или True, или False или None." + +msgid "Boolean (Either True or False)" +msgstr "Булево (True или False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Символен низ (до %(max_length)s символа)" + +msgid "String (unlimited)" +msgstr "Стринг (неограничен)" + +msgid "Comma-separated integers" +msgstr "Цели числа, разделени с запетая" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"Стойността \"%(value)s\" е с невалиден формат за дата. Тя трябва да бъде в " +"ГГГГ-ММ-ДД формат." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"Стойността \"%(value)s\" е в правилния формат (ГГГГ-ММ-ДД), но самата дата е " +"невалидна." + +msgid "Date (without time)" +msgstr "Дата (без час)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"Стойността '%(value)s' е с невалиден формат. Трябва да бъде във формат ГГГГ-" +"ММ-ДД ЧЧ:ММ[:сс[.uuuuuu]][TZ]" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"Стойността '%(value)s' е с правилен формат ( ГГГГ-ММ-ДД ЧЧ:ММ[:сс[.μμμμμμ]]" +"[TZ]), но датата/часът са невалидни" + +msgid "Date (with time)" +msgstr "Дата (и час)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "Стойността \"%(value)s\" трябва да е десетично число." + +msgid "Decimal number" +msgstr "Десетична дроб" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"Стойността “%(value)s” е с невалиден формат. Трябва да бъде във формат [ДД] " +"[[ЧЧ:]ММ:]сс[.uuuuuu] format." + +msgid "Duration" +msgstr "Продължителност" + +msgid "Email address" +msgstr "Имейл адрес" + +msgid "File path" +msgstr "Път към файл" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "Стойността '%(value)s' трябва да е число с плаваща запетая." + +msgid "Floating point number" +msgstr "Число с плаваща запетая" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "Стойността \"%(value)s\" трябва да е цяло число." + +msgid "Integer" +msgstr "Цяло число" + +msgid "Big (8 byte) integer" +msgstr "Голямо (8 байта) цяло число" + +msgid "Small integer" +msgstr "2 байта цяло число" + +msgid "IPv4 address" +msgstr "IPv4 адрес" + +msgid "IP address" +msgstr "IP адрес" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "Стойността '%(value)s' трябва да бъде None, True или False." + +msgid "Boolean (Either True, False or None)" +msgstr "булев (възможните стойности са True, False или None)" + +msgid "Positive big integer" +msgstr "Положително голямо цяло число." + +msgid "Positive integer" +msgstr "Положително цяло число" + +msgid "Positive small integer" +msgstr "Положително 2 байта цяло число" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Слъг (до %(max_length)s )" + +msgid "Text" +msgstr "Текст" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"Стойността \"%(value)s\" е с невалиден формат. Тя трябва да бъде в ЧЧ:ММ [:" +"сс[.μμμμμμ]]" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"Стойността \"%(value)s\" е в правилния формат (ЧЧ:ММ [:сс[.μμμμμμ]]), но " +"часът е невалиден." + +msgid "Time" +msgstr "Време" + +msgid "URL" +msgstr "URL адрес" + +msgid "Raw binary data" +msgstr "сурови двоични данни" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "\"%(value)s\" не е валиден UUID." + +msgid "Universally unique identifier" +msgstr "Универсално уникален идентификатор" + +msgid "File" +msgstr "Файл" + +msgid "Image" +msgstr "Изображение" + +msgid "A JSON object" +msgstr "Обект във формат JSON" + +msgid "Value must be valid JSON." +msgstr "Стойността трябва да е валиден JSON." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "Инстанция на %(model)s с %(field)s %(value)r не съществува." + +msgid "Foreign Key (type determined by related field)" +msgstr "Външен ключ (тип, определен от свързаното поле)" + +msgid "One-to-one relationship" +msgstr "едно-към-едно релация " + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s релация" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s релации" + +msgid "Many-to-many relationship" +msgstr "Много-към-много релация" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Това поле е задължително." + +msgid "Enter a whole number." +msgstr "Въведете цяло число. " + +msgid "Enter a valid date." +msgstr "Въведете валидна дата." + +msgid "Enter a valid time." +msgstr "Въведете валиден час." + +msgid "Enter a valid date/time." +msgstr "Въведете валидна дата/час. " + +msgid "Enter a valid duration." +msgstr "Въведете валидна продължителност." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Броят на дните трябва да е между {min_days} и {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Няма изпратен файл. Проверете типа кодиране на формата. " + +msgid "No file was submitted." +msgstr "Няма изпратен файл." + +msgid "The submitted file is empty." +msgstr "Изпратеният файл е празен. " + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "Уверете се, това име е най-много %(max)d знака (то има %(length)d)." +msgstr[1] "" +"Уверете се, че това файлово име има най-много %(max)d знаци (има " +"%(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Моля, или пратете файл или маркирайте полето за изчистване, но не и двете." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Качете валидно изображение. Файлът, който сте качили или не е изображение, " +"или е повреден. " + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Направете валиден избор. %(value)s не е един от възможните избори." + +msgid "Enter a list of values." +msgstr "Въведете списък от стойности" + +msgid "Enter a complete value." +msgstr "Въведете пълна стойност." + +msgid "Enter a valid UUID." +msgstr "Въведете валиден UUID." + +msgid "Enter a valid JSON." +msgstr "Въведете валиден JSON." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Скрито поле %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"ManagementForm данните липсват или са променяни неправомерно. Липсващи " +"полета: %(field_names)s. Трябва да изпратите уведомление за бъг, ако този " +"проблем продължава." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Моля изпратете не повече от %(num)d формуляр." +msgstr[1] "Моля изпратете не повече от %(num)d формуляра." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Моля изпратете поне %(num)d формуляр." +msgstr[1] "Моля изпратете поне %(num)d формуляра." + +msgid "Order" +msgstr "Ред" + +msgid "Delete" +msgstr "Изтрий" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Моля, коригирайте дублираните данни за %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Моля, коригирайте дублираните данни за %(field)s, които трябва да са " +"уникални." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Моля, коригирайте дублиранитe данни за %(field_name)s , които трябва да са " +"уникални за %(lookup)s в %(date_field)s ." + +msgid "Please correct the duplicate values below." +msgstr "Моля, коригирайте повтарящите се стойности по-долу." + +msgid "The inline value did not match the parent instance." +msgstr "Стойността в реда не отговаря на родителската инстанция." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Направете валиден избор. Този не е един от възможните избори. " + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "“%(pk)s” не е валидна стойност." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s не може да се интерпретира в часова зона %(current_timezone)s; " +"вероятно стойността е нееднозначна или не съществува изобщо." + +msgid "Clear" +msgstr "Изчисти" + +msgid "Currently" +msgstr "Сега" + +msgid "Change" +msgstr "Промени" + +msgid "Unknown" +msgstr "Неизвестно" + +msgid "Yes" +msgstr "Да" + +msgid "No" +msgstr "Не" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "да,не,може би" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d, байт" +msgstr[1] "%(size)d байта" + +#, python-format +msgid "%s KB" +msgstr "%s KБ" + +#, python-format +msgid "%s MB" +msgstr "%s МБ" + +#, python-format +msgid "%s GB" +msgstr "%s ГБ" + +#, python-format +msgid "%s TB" +msgstr "%s ТБ" + +#, python-format +msgid "%s PB" +msgstr "%s ПБ" + +msgid "p.m." +msgstr "след обяд" + +msgid "a.m." +msgstr "преди обяд" + +msgid "PM" +msgstr "след обяд" + +msgid "AM" +msgstr "преди обяд" + +msgid "midnight" +msgstr "полунощ" + +msgid "noon" +msgstr "обяд" + +msgid "Monday" +msgstr "понеделник" + +msgid "Tuesday" +msgstr "вторник" + +msgid "Wednesday" +msgstr "сряда" + +msgid "Thursday" +msgstr "четвъртък" + +msgid "Friday" +msgstr "петък" + +msgid "Saturday" +msgstr "събота" + +msgid "Sunday" +msgstr "неделя" + +msgid "Mon" +msgstr "Пон" + +msgid "Tue" +msgstr "Вт" + +msgid "Wed" +msgstr "Ср" + +msgid "Thu" +msgstr "Чет" + +msgid "Fri" +msgstr "Пет" + +msgid "Sat" +msgstr "Съб" + +msgid "Sun" +msgstr "Нед" + +msgid "January" +msgstr "Януари" + +msgid "February" +msgstr "Февруари" + +msgid "March" +msgstr "Март" + +msgid "April" +msgstr "Април" + +msgid "May" +msgstr "Май" + +msgid "June" +msgstr "Юни" + +msgid "July" +msgstr "Юли" + +msgid "August" +msgstr "Август" + +msgid "September" +msgstr "Септември" + +msgid "October" +msgstr "Октомври" + +msgid "November" +msgstr "Ноември" + +msgid "December" +msgstr "Декември" + +msgid "jan" +msgstr "ян" + +msgid "feb" +msgstr "фев" + +msgid "mar" +msgstr "мар" + +msgid "apr" +msgstr "апр" + +msgid "may" +msgstr "май" + +msgid "jun" +msgstr "юни" + +msgid "jul" +msgstr "юли" + +msgid "aug" +msgstr "авг" + +msgid "sep" +msgstr "сеп" + +msgid "oct" +msgstr "окт" + +msgid "nov" +msgstr "ноем" + +msgid "dec" +msgstr "дек" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Ян." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Фев." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Март" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Апр." + +msgctxt "abbrev. month" +msgid "May" +msgstr "Май" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Юни" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Юли" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Авг." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Септ." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Окт." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Ноем." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Дек." + +msgctxt "alt. month" +msgid "January" +msgstr "Януари" + +msgctxt "alt. month" +msgid "February" +msgstr "Февруари" + +msgctxt "alt. month" +msgid "March" +msgstr "Март" + +msgctxt "alt. month" +msgid "April" +msgstr "Април" + +msgctxt "alt. month" +msgid "May" +msgstr "Май" + +msgctxt "alt. month" +msgid "June" +msgstr "Юни" + +msgctxt "alt. month" +msgid "July" +msgstr "Юли" + +msgctxt "alt. month" +msgid "August" +msgstr "Август" + +msgctxt "alt. month" +msgid "September" +msgstr "Септември" + +msgctxt "alt. month" +msgid "October" +msgstr "Октомври" + +msgctxt "alt. month" +msgid "November" +msgstr "Ноември" + +msgctxt "alt. month" +msgid "December" +msgstr "Декември" + +msgid "This is not a valid IPv6 address." +msgstr "Въведете валиден IPv6 адрес." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "или" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d година" +msgstr[1] "%(num)d години" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d месец" +msgstr[1] "%(num)d месеца" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d седмица" +msgstr[1] "%(num)d седмици" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d ден" +msgstr[1] "%(num)d дни" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d час" +msgstr[1] "%(num)d часа" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d минута" +msgstr[1] "%(num)d минути" + +msgid "Forbidden" +msgstr "Забранен" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF проверката се провали. Заявката прекратена." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Вие виждате това съобщение, защото този HTTPS сайт изисква да бъде изпратен " +"'Referer header' от вашият уеб браузър, но такъв не бе изпратен. Този " +"header е задължителен от съображения за сигурност, за да се гарантира, че " +"вашият браузър не е компрометиран от трети страни." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Ако сте настроили вашия браузър да деактивира 'Referer' headers, моля да ги " +"активирате отново, поне за този сайт, или за HTTPS връзки, или за 'same-" +"origin' заявки." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Ако използвате таг или " +"включвате “Referrer-Policy: no-referrer” header, моля премахнете ги. CSRF " +"защитата изисква “Referer” header, за да извърши стриктна проверка на " +"изпращача. Ако сте притеснени за поверителността, използвайте алтернативи " +"като за връзки към сайтове на трети страни." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Вие виждате това съобщение, защото този сайт изисква CSRF бисквитка, когато " +"се подават формуляри. Тази бисквитка е задължителна от съображения за " +"сигурност, за да се гарантира, че вашият браузър не е компрометиран от трети " +"страни." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Ако сте конфигурирали браузъра си да забрани бисквитките, моля да ги " +"активирате отново, поне за този сайт, или за \"same-origin\" заявки." + +msgid "More information is available with DEBUG=True." +msgstr "Повече информация е на разположение с DEBUG=True." + +msgid "No year specified" +msgstr "Не е посочена година" + +msgid "Date out of range" +msgstr "Датата е в невалиден диапазон" + +msgid "No month specified" +msgstr "Не е посочен месец" + +msgid "No day specified" +msgstr "Не е посочен ден" + +msgid "No week specified" +msgstr "Не е посочена седмица" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Няма достъпни %(verbose_name_plural)s" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Бъдещo %(verbose_name_plural)s е недостъпно, тъй като %(class_name)s." +"allow_future е False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" +"Невалидна текстова стойност на датата “%(datestr)s” при зададен формат " +"“%(format)s”" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Няма %(verbose_name)s, съвпадащи със заявката" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" +"Страницата не е \"последна\", нито може да се преобразува в цяло число." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Невалидна страница (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Празен списък и \"%(class_name)s.allow_empty\" e False." + +msgid "Directory indexes are not allowed here." +msgstr "Тук не е позволено индексиране на директория." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "\"%(path)s\" не съществува" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Индекс %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Инсталацията Ви заработи успешно! Поздравления!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Разгледайте release notes за Django %(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Вие виждате тази страница, защото DEBUG=True е във вашия файл с настройки и не сте " +"конфигурирали никакви URL-и." + +msgid "Django Documentation" +msgstr "Django документация" + +msgid "Topics, references, & how-to’s" +msgstr "Теми, наръчници, & друга документация" + +msgid "Tutorial: A Polling App" +msgstr "Урок: Приложение за анкета" + +msgid "Get started with Django" +msgstr "Започнете с Django" + +msgid "Django Community" +msgstr "Django общност" + +msgid "Connect, get help, or contribute" +msgstr "Свържете се, получете помощ или допринесете" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bg/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bg/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bg/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bg/formats.py new file mode 100644 index 0000000..ee90c5b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bg/formats.py @@ -0,0 +1,21 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "d F Y" +TIME_FORMAT = "H:i" +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "d.m.Y" +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = " " # Non-breaking space +# NUMBER_GROUPING = diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ef52f36 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bn/LC_MESSAGES/django.po new file mode 100644 index 0000000..b554f7a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bn/LC_MESSAGES/django.po @@ -0,0 +1,1218 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# M Nasimul Haque , 2013 +# Tahmid Rafi , 2012-2013 +# Tahmid Rafi , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Bengali (http://www.transifex.com/django/django/language/" +"bn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "আফ্রিকার অন্যতম সরকারি ভাষা" + +msgid "Arabic" +msgstr "আরবী" + +msgid "Asturian" +msgstr "" + +msgid "Azerbaijani" +msgstr "আজারবাইজানি" + +msgid "Bulgarian" +msgstr "বুলগেরিয়ান" + +msgid "Belarusian" +msgstr "বেলারুশীয়" + +msgid "Bengali" +msgstr "বাংলা" + +msgid "Breton" +msgstr "ব্রেটন" + +msgid "Bosnian" +msgstr "বসনিয়ান" + +msgid "Catalan" +msgstr "ক্যাটালান" + +msgid "Czech" +msgstr "চেক" + +msgid "Welsh" +msgstr "ওয়েল্স" + +msgid "Danish" +msgstr "ড্যানিশ" + +msgid "German" +msgstr "জার্মান" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "গ্রিক" + +msgid "English" +msgstr "ইংলিশ" + +msgid "Australian English" +msgstr "" + +msgid "British English" +msgstr "বৃটিশ ইংলিশ" + +msgid "Esperanto" +msgstr "আন্তর্জাতিক ভাষা" + +msgid "Spanish" +msgstr "স্প্যানিশ" + +msgid "Argentinian Spanish" +msgstr "আর্জেন্টিনিয়ান স্প্যানিশ" + +msgid "Colombian Spanish" +msgstr "" + +msgid "Mexican Spanish" +msgstr "মেক্সিকান স্প্যানিশ" + +msgid "Nicaraguan Spanish" +msgstr "নিকারাগুয়ান স্প্যানিশ" + +msgid "Venezuelan Spanish" +msgstr "ভেনেজুয়েলার স্প্যানিশ" + +msgid "Estonian" +msgstr "এস্তোনিয়ান" + +msgid "Basque" +msgstr "বাস্ক" + +msgid "Persian" +msgstr "ফারসি" + +msgid "Finnish" +msgstr "ফিনিশ" + +msgid "French" +msgstr "ফ্রেঞ্চ" + +msgid "Frisian" +msgstr "ফ্রিজ্ল্যানডের ভাষা" + +msgid "Irish" +msgstr "আইরিশ" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "গ্যালিসিয়ান" + +msgid "Hebrew" +msgstr "হিব্রু" + +msgid "Hindi" +msgstr "হিন্দী" + +msgid "Croatian" +msgstr "ক্রোয়েশিয়ান" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "হাঙ্গেরিয়ান" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "" + +msgid "Indonesian" +msgstr "ইন্দোনেশিয়ান" + +msgid "Ido" +msgstr "" + +msgid "Icelandic" +msgstr "আইসল্যান্ডিক" + +msgid "Italian" +msgstr "ইটালিয়ান" + +msgid "Japanese" +msgstr "জাপানিজ" + +msgid "Georgian" +msgstr "জর্জিয়ান" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "কাজাখ" + +msgid "Khmer" +msgstr "খমার" + +msgid "Kannada" +msgstr "কান্নাড়া" + +msgid "Korean" +msgstr "কোরিয়ান" + +msgid "Luxembourgish" +msgstr "লুক্সেমবার্গীয়" + +msgid "Lithuanian" +msgstr "লিথুয়ানিয়ান" + +msgid "Latvian" +msgstr "লাটভিয়ান" + +msgid "Macedonian" +msgstr "ম্যাসাডোনিয়ান" + +msgid "Malayalam" +msgstr "মালায়ালম" + +msgid "Mongolian" +msgstr "মঙ্গোলিয়ান" + +msgid "Marathi" +msgstr "" + +msgid "Burmese" +msgstr "বার্মিজ" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "নেপালি" + +msgid "Dutch" +msgstr "ডাচ" + +msgid "Norwegian Nynorsk" +msgstr "নরওয়েজীয়ান নিনর্স্ক" + +msgid "Ossetic" +msgstr "অসেটিক" + +msgid "Punjabi" +msgstr "পাঞ্জাবী" + +msgid "Polish" +msgstr "পোলিশ" + +msgid "Portuguese" +msgstr "পর্তুগীজ" + +msgid "Brazilian Portuguese" +msgstr "ব্রাজিলিয়ান পর্তুগীজ" + +msgid "Romanian" +msgstr "রোমানিয়ান" + +msgid "Russian" +msgstr "রাশান" + +msgid "Slovak" +msgstr "স্লোভাক" + +msgid "Slovenian" +msgstr "স্লোভেনিয়ান" + +msgid "Albanian" +msgstr "আলবেনীয়ান" + +msgid "Serbian" +msgstr "সার্বিয়ান" + +msgid "Serbian Latin" +msgstr "সার্বিয়ান ল্যাটিন" + +msgid "Swedish" +msgstr "সুইডিশ" + +msgid "Swahili" +msgstr "সোয়াহিলি" + +msgid "Tamil" +msgstr "তামিল" + +msgid "Telugu" +msgstr "তেলেগু" + +msgid "Thai" +msgstr "থাই" + +msgid "Turkish" +msgstr "তুর্কি" + +msgid "Tatar" +msgstr "তাতারদেশীয়" + +msgid "Udmurt" +msgstr "" + +msgid "Ukrainian" +msgstr "ইউক্রেনিয়ান" + +msgid "Urdu" +msgstr "উর্দু" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "ভিয়েতনামিজ" + +msgid "Simplified Chinese" +msgstr "সরলীকৃত চাইনীজ" + +msgid "Traditional Chinese" +msgstr "প্রচলিত চাইনীজ" + +msgid "Messages" +msgstr "" + +msgid "Site Maps" +msgstr "" + +msgid "Static Files" +msgstr "" + +msgid "Syndication" +msgstr "" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "একটি বৈধ মান দিন।" + +msgid "Enter a valid URL." +msgstr "বৈধ URL দিন" + +msgid "Enter a valid integer." +msgstr "" + +msgid "Enter a valid email address." +msgstr "একটি বৈধ ইমেইল ঠিকানা লিখুন." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "একটি বৈধ IPv4 ঠিকানা দিন।" + +msgid "Enter a valid IPv6 address." +msgstr "একটি বৈধ IPv6 ঠিকানা টাইপ করুন।" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "একটি বৈধ IPv4 অথবা IPv6 ঠিকানা টাইপ করুন।" + +msgid "Enter only digits separated by commas." +msgstr "শুধুমাত্র কমা দিয়ে সংখ্যা দিন।" + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "সংখ্যাটির মান %(limit_value)s হতে হবে (এটা এখন %(show_value)s আছে)।" + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "সংখ্যাটির মান %(limit_value)s এর চেয়ে ছোট বা সমান হতে হবে।" + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "সংখ্যাটির মান %(limit_value)s এর চেয়ে বড় বা সমান হতে হবে।" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Enter a number." +msgstr "একটি সংখ্যা প্রবেশ করান।" + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "এবং" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "এর মান null হতে পারবে না।" + +msgid "This field cannot be blank." +msgstr "এই ফিল্ডের মান ফাঁকা হতে পারে না" + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(field_label)s সহ %(model_name)s আরেকটি রয়েছে।" + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "ফিল্ডের ধরণ: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "বুলিয়ান (হয় True অথবা False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "স্ট্রিং (সর্বোচ্চ %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "কমা দিয়ে আলাদা করা ইন্টিজার" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "তারিখ (সময় বাদে)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "তারিখ (সময় সহ)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "দশমিক সংখ্যা" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "" + +msgid "Email address" +msgstr "ইমেইল ঠিকানা" + +msgid "File path" +msgstr "ফাইল পথ" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "ফ্লোটিং পয়েন্ট সংখ্যা" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "ইন্টিজার" + +msgid "Big (8 byte) integer" +msgstr "বিগ (৮ বাইট) ইন্টিজার" + +msgid "IPv4 address" +msgstr "IPv4 ঠিকানা" + +msgid "IP address" +msgstr "আইপি ঠিকানা" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "বুলিয়ান (হয় True, False অথবা None)" + +msgid "Positive integer" +msgstr "পজিটিভ ইন্টিজার" + +msgid "Positive small integer" +msgstr "পজিটিভ স্মল ইন্টিজার" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "স্লাগ (সর্বোচ্চ %(max_length)s)" + +msgid "Small integer" +msgstr "স্মল ইন্টিজার" + +msgid "Text" +msgstr "টেক্সট" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "সময়" + +msgid "URL" +msgstr "ইউআরএল (URL)" + +msgid "Raw binary data" +msgstr "র বাইনারি ডাটা" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "ফাইল" + +msgid "Image" +msgstr "ইমেজ" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "ফরেন কি (টাইপ রিলেটেড ফিল্ড দ্বারা নির্ণীত হবে)" + +msgid "One-to-one relationship" +msgstr "ওয়ান-টু-ওয়ান রিলেশানশিপ" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "ম্যানি-টু-ম্যানি রিলেশানশিপ" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr "" + +msgid "This field is required." +msgstr "এটি আবশ্যক।" + +msgid "Enter a whole number." +msgstr "একটি পূর্ণসংখ্যা দিন" + +msgid "Enter a valid date." +msgstr "বৈধ তারিখ দিন।" + +msgid "Enter a valid time." +msgstr "বৈধ সময় দিন।" + +msgid "Enter a valid date/time." +msgstr "বৈধ তারিখ/সময় দিন।" + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "কোন ফাইল দেয়া হয়নি। ফর্মের এনকোডিং ঠিক আছে কিনা দেখুন।" + +msgid "No file was submitted." +msgstr "কোন ফাইল দেয়া হয়নি।" + +msgid "The submitted file is empty." +msgstr "ফাইলটি খালি।" + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"একটি ফাইল সাবমিট করুন অথবা ক্লিয়ার চেকবক্সটি চেক করে দিন, যে কোন একটি করুন।" + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"সঠিক ছবি আপলোড করুন। যে ফাইলটি আপলোড করা হয়েছে তা হয় ছবি নয় অথবা নষ্ট হয়ে " +"যাওয়া ছবি।" + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "%(value)s বৈধ নয়। অনুগ্রহ করে আরেকটি সিলেক্ট করুন।" + +msgid "Enter a list of values." +msgstr "কয়েকটি মানের তালিকা দিন।" + +msgid "Enter a complete value." +msgstr "" + +msgid "Enter a valid UUID." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr "" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "ক্রম" + +msgid "Delete" +msgstr "মুছুন" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "" + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" + +msgid "Please correct the duplicate values below." +msgstr "" + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "এটি বৈধ নয়। অনুগ্রহ করে আরেকটি সিলেক্ট করুন।" + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "পরিষ্কার করুন" + +msgid "Currently" +msgstr "এই মুহুর্তে" + +msgid "Change" +msgstr "পরিবর্তন" + +msgid "Unknown" +msgstr "অজানা" + +msgid "Yes" +msgstr "হ্যাঁ" + +msgid "No" +msgstr "না" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "হ্যাঁ,না,হয়তো" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d বাইট" +msgstr[1] "%(size)d বাইট" + +#, python-format +msgid "%s KB" +msgstr "%s কিলোবাইট" + +#, python-format +msgid "%s MB" +msgstr "%s মেগাবাইট" + +#, python-format +msgid "%s GB" +msgstr "%s গিগাবাইট" + +#, python-format +msgid "%s TB" +msgstr "%s টেরাবাইট" + +#, python-format +msgid "%s PB" +msgstr "%s পেটাবাইট" + +msgid "p.m." +msgstr "অপরাহ্ন" + +msgid "a.m." +msgstr "পূর্বাহ্ন" + +msgid "PM" +msgstr "অপরাহ্ন" + +msgid "AM" +msgstr "পূর্বাহ্ন" + +msgid "midnight" +msgstr "মধ্যরাত" + +msgid "noon" +msgstr "দুপুর" + +msgid "Monday" +msgstr "সোমবার" + +msgid "Tuesday" +msgstr "মঙ্গলবার" + +msgid "Wednesday" +msgstr "বুধবার" + +msgid "Thursday" +msgstr "বৃহস্পতিবার" + +msgid "Friday" +msgstr "শুক্রবার" + +msgid "Saturday" +msgstr "শনিবার" + +msgid "Sunday" +msgstr "রবিবার" + +msgid "Mon" +msgstr "সোম" + +msgid "Tue" +msgstr "মঙ্গল" + +msgid "Wed" +msgstr "বুধ" + +msgid "Thu" +msgstr "বৃহঃ" + +msgid "Fri" +msgstr "শুক্র" + +msgid "Sat" +msgstr "শনি" + +msgid "Sun" +msgstr "রবি" + +msgid "January" +msgstr "জানুয়ারি" + +msgid "February" +msgstr "ফেব্রুয়ারি" + +msgid "March" +msgstr "মার্চ" + +msgid "April" +msgstr "এপ্রিল" + +msgid "May" +msgstr "মে" + +msgid "June" +msgstr "জুন" + +msgid "July" +msgstr "জুলাই" + +msgid "August" +msgstr "আগস্ট" + +msgid "September" +msgstr "সেপ্টেম্বর" + +msgid "October" +msgstr "অক্টোবর" + +msgid "November" +msgstr "নভেম্বর" + +msgid "December" +msgstr "ডিসেম্বর" + +msgid "jan" +msgstr "জান." + +msgid "feb" +msgstr "ফেব." + +msgid "mar" +msgstr "মার্চ" + +msgid "apr" +msgstr "এপ্রি." + +msgid "may" +msgstr "মে" + +msgid "jun" +msgstr "জুন" + +msgid "jul" +msgstr "জুল." + +msgid "aug" +msgstr "আগ." + +msgid "sep" +msgstr "সেপ্টে." + +msgid "oct" +msgstr "অক্টো." + +msgid "nov" +msgstr "নভে." + +msgid "dec" +msgstr "ডিসে." + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "জানু." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "ফেব্রু." + +msgctxt "abbrev. month" +msgid "March" +msgstr "মার্চ" + +msgctxt "abbrev. month" +msgid "April" +msgstr "এপ্রিল" + +msgctxt "abbrev. month" +msgid "May" +msgstr "মে" + +msgctxt "abbrev. month" +msgid "June" +msgstr "জুন" + +msgctxt "abbrev. month" +msgid "July" +msgstr "জুলাই" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "আগ." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "সেপ্ট." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "অক্টো." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "নভে." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "ডিসে." + +msgctxt "alt. month" +msgid "January" +msgstr "জানুয়ারি" + +msgctxt "alt. month" +msgid "February" +msgstr "ফেব্রুয়ারি" + +msgctxt "alt. month" +msgid "March" +msgstr "মার্চ" + +msgctxt "alt. month" +msgid "April" +msgstr "এপ্রিল" + +msgctxt "alt. month" +msgid "May" +msgstr "মে" + +msgctxt "alt. month" +msgid "June" +msgstr "জুন" + +msgctxt "alt. month" +msgid "July" +msgstr "জুলাই" + +msgctxt "alt. month" +msgid "August" +msgstr "আগস্ট" + +msgctxt "alt. month" +msgid "September" +msgstr "সেপ্টেম্বর" + +msgctxt "alt. month" +msgid "October" +msgstr "অক্টোবর" + +msgctxt "alt. month" +msgid "November" +msgstr "নভেম্বর" + +msgctxt "alt. month" +msgid "December" +msgstr "ডিসেম্বর" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "অথবা" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "," + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" + +msgid "0 minutes" +msgstr "0 মিনিট" + +msgid "Forbidden" +msgstr "" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "কোন বছর উল্লেখ করা হয়নি" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "কোন মাস উল্লেখ করা হয়নি" + +msgid "No day specified" +msgstr "কোন দিন উল্লেখ করা হয়নি" + +msgid "No week specified" +msgstr "কোন সপ্তাহ উল্লেখ করা হয়নি" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "কোন %(verbose_name_plural)s নেই" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "কুয়েরি ম্যাচ করে এমন কোন %(verbose_name)s পাওয়া যায় নি" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "ডিরেক্টরি ইনডেক্স অনুমোদিত নয়" + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "%(directory)s এর ইনডেক্স" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bn/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bn/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bn/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bn/formats.py new file mode 100644 index 0000000..9d1bb09 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bn/formats.py @@ -0,0 +1,32 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j F, Y" +TIME_FORMAT = "g:i A" +# DATETIME_FORMAT = +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "j M, Y" +# SHORT_DATETIME_FORMAT = +FIRST_DAY_OF_WEEK = 6 # Saturday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d/%m/%Y", # 25/10/2016 + "%d/%m/%y", # 25/10/16 + "%d-%m-%Y", # 25-10-2016 + "%d-%m-%y", # 25-10-16 +] +TIME_INPUT_FORMATS = [ + "%H:%M:%S", # 14:30:59 + "%H:%M", # 14:30 +] +DATETIME_INPUT_FORMATS = [ + "%d/%m/%Y %H:%M:%S", # 25/10/2006 14:30:59 + "%d/%m/%Y %H:%M", # 25/10/2006 14:30 +] +DECIMAL_SEPARATOR = "." +THOUSAND_SEPARATOR = "," +# NUMBER_GROUPING = diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/br/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/br/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d864abe Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/br/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/br/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/br/LC_MESSAGES/django.po new file mode 100644 index 0000000..3b1a759 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/br/LC_MESSAGES/django.po @@ -0,0 +1,1297 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Claude Paroz , 2020 +# Ewen , 2021 +# Fulup , 2012,2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2021-11-18 21:19+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Breton (http://www.transifex.com/django/django/language/br/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: br\n" +"Plural-Forms: nplurals=5; plural=((n%10 == 1) && (n%100 != 11) && (n%100 !" +"=71) && (n%100 !=91) ? 0 :(n%10 == 2) && (n%100 != 12) && (n%100 !=72) && (n" +"%100 !=92) ? 1 :(n%10 ==3 || n%10==4 || n%10==9) && (n%100 < 10 || n% 100 > " +"19) && (n%100 < 70 || n%100 > 79) && (n%100 < 90 || n%100 > 99) ? 2 :(n != 0 " +"&& n % 1000000 == 0) ? 3 : 4);\n" + +msgid "Afrikaans" +msgstr "Afrikaneg" + +msgid "Arabic" +msgstr "Arabeg" + +msgid "Algerian Arabic" +msgstr "" + +msgid "Asturian" +msgstr "Astureg" + +msgid "Azerbaijani" +msgstr "Azeri" + +msgid "Bulgarian" +msgstr "Bulgareg" + +msgid "Belarusian" +msgstr "Belaruseg" + +msgid "Bengali" +msgstr "Bengaleg" + +msgid "Breton" +msgstr "Brezhoneg" + +msgid "Bosnian" +msgstr "Bosneg" + +msgid "Catalan" +msgstr "Katalaneg" + +msgid "Czech" +msgstr "Tchekeg" + +msgid "Welsh" +msgstr "Kembraeg" + +msgid "Danish" +msgstr "Daneg" + +msgid "German" +msgstr "Alamaneg" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "Gresianeg" + +msgid "English" +msgstr "Saozneg" + +msgid "Australian English" +msgstr "Saozneg Aostralia" + +msgid "British English" +msgstr "Saozneg Breizh-Veur" + +msgid "Esperanto" +msgstr "Esperanteg" + +msgid "Spanish" +msgstr "Spagnoleg" + +msgid "Argentinian Spanish" +msgstr "Spagnoleg Arc'hantina" + +msgid "Colombian Spanish" +msgstr "Spagnoleg Kolombia" + +msgid "Mexican Spanish" +msgstr "Spagnoleg Mec'hiko" + +msgid "Nicaraguan Spanish" +msgstr "Spagnoleg Nicaragua" + +msgid "Venezuelan Spanish" +msgstr "Spagnoleg Venezuela" + +msgid "Estonian" +msgstr "Estoneg" + +msgid "Basque" +msgstr "Euskareg" + +msgid "Persian" +msgstr "Perseg" + +msgid "Finnish" +msgstr "Finneg" + +msgid "French" +msgstr "Galleg" + +msgid "Frisian" +msgstr "Frizeg" + +msgid "Irish" +msgstr "Iwerzhoneg" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "Galizeg" + +msgid "Hebrew" +msgstr "Hebraeg" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Kroateg" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "Hungareg" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonezeg" + +msgid "Igbo" +msgstr "" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Islandeg" + +msgid "Italian" +msgstr "Italianeg" + +msgid "Japanese" +msgstr "Japaneg" + +msgid "Georgian" +msgstr "Jorjianeg" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "kazak" + +msgid "Khmer" +msgstr "Khmer" + +msgid "Kannada" +msgstr "Kannata" + +msgid "Korean" +msgstr "Koreaneg" + +msgid "Kyrgyz" +msgstr "" + +msgid "Luxembourgish" +msgstr "Luksembourgeg" + +msgid "Lithuanian" +msgstr "Lituaneg" + +msgid "Latvian" +msgstr "Latveg" + +msgid "Macedonian" +msgstr "Makedoneg" + +msgid "Malayalam" +msgstr "Malayalam" + +msgid "Mongolian" +msgstr "Mongoleg" + +msgid "Marathi" +msgstr "Marathi" + +msgid "Malay" +msgstr "" + +msgid "Burmese" +msgstr "Burmeg" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "nepaleg" + +msgid "Dutch" +msgstr "Nederlandeg" + +msgid "Norwegian Nynorsk" +msgstr "Norvegeg Nynorsk" + +msgid "Ossetic" +msgstr "Oseteg" + +msgid "Punjabi" +msgstr "Punjabeg" + +msgid "Polish" +msgstr "Poloneg" + +msgid "Portuguese" +msgstr "Portugaleg" + +msgid "Brazilian Portuguese" +msgstr "Portugaleg Brazil" + +msgid "Romanian" +msgstr "Roumaneg" + +msgid "Russian" +msgstr "Rusianeg" + +msgid "Slovak" +msgstr "Slovakeg" + +msgid "Slovenian" +msgstr "Sloveneg" + +msgid "Albanian" +msgstr "Albaneg" + +msgid "Serbian" +msgstr "Serbeg" + +msgid "Serbian Latin" +msgstr "Serbeg e lizherennoù latin" + +msgid "Swedish" +msgstr "Svedeg" + +msgid "Swahili" +msgstr "swahileg" + +msgid "Tamil" +msgstr "Tamileg" + +msgid "Telugu" +msgstr "Telougou" + +msgid "Tajik" +msgstr "" + +msgid "Thai" +msgstr "Thai" + +msgid "Turkmen" +msgstr "" + +msgid "Turkish" +msgstr "Turkeg" + +msgid "Tatar" +msgstr "tatar" + +msgid "Udmurt" +msgstr "Oudmourteg" + +msgid "Ukrainian" +msgstr "Ukraineg" + +msgid "Urdu" +msgstr "Ourdou" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "Vietnameg" + +msgid "Simplified Chinese" +msgstr "Sinaeg eeunaet" + +msgid "Traditional Chinese" +msgstr "Sinaeg hengounel" + +msgid "Messages" +msgstr "Kemennadenn" + +msgid "Site Maps" +msgstr "Tresoù al lec'hienn" + +msgid "Static Files" +msgstr "Restroù statek" + +msgid "Syndication" +msgstr "Sindikadur" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "..." + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "An niver a bajenn mañ a zo bihanoc'h eget 1." + +msgid "That page contains no results" +msgstr "N'eus disoc'h er pajenn-mañ." + +msgid "Enter a valid value." +msgstr "Merkit un talvoud reizh" + +msgid "Enter a valid URL." +msgstr "Merkit un URL reizh" + +msgid "Enter a valid integer." +msgstr "Merkit un niver anterin reizh." + +msgid "Enter a valid email address." +msgstr "Merkit ur chomlec'h postel reizh" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Merkit ur chomlec'h IPv4 reizh." + +msgid "Enter a valid IPv6 address." +msgstr "Merkit ur chomlec'h IPv6 reizh." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Merkit ur chomlec'h IPv4 pe IPv6 reizh." + +msgid "Enter only digits separated by commas." +msgstr "Merkañ hepken sifroù dispartiet dre skejoù." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Bezit sur ez eo an talvoud-mañ %(limit_value)s (evit ar mare ez eo " +"%(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Gwiriit mat emañ an talvoud-mañ a-is pe par da %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Gwiriit mat emañ an talvoud-mañ a-us pe par da %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +msgid "Enter a number." +msgstr "Merkit un niver." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "ha" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "N'hall ket ar vaezienn chom goullo" + +msgid "This field cannot be blank." +msgstr "N'hall ket ar vaezienn chom goullo" + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "Bez' ez eus c'hoazh eus ur %(model_name)s gant ar %(field_label)s-mañ." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Seurt maezienn : %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "Boulean (gwir pe gaou)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "neudennad arouezennoù (betek %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "Niveroù anterin dispartiet dre ur skej" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "Deizad (hep eur)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Deizad (gant an eur)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Niver dekvedennel" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "" + +msgid "Email address" +msgstr "Chomlec'h postel" + +msgid "File path" +msgstr "Treug war-du ar restr" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "Niver gant skej nij" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "Anterin" + +msgid "Big (8 byte) integer" +msgstr "Anterin bras (8 okted)" + +msgid "Small integer" +msgstr "Niver anterin bihan" + +msgid "IPv4 address" +msgstr "Chomlec'h IPv4" + +msgid "IP address" +msgstr "Chomlec'h IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "Boulean (gwir pe gaou pe netra)" + +msgid "Positive big integer" +msgstr "" + +msgid "Positive integer" +msgstr "Niver anterin pozitivel" + +msgid "Positive small integer" +msgstr "Niver anterin bihan pozitivel" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (betek %(max_length)s arouez.)" + +msgid "Text" +msgstr "Testenn" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Eur" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "Restr" + +msgid "Image" +msgstr "Skeudenn" + +msgid "A JSON object" +msgstr "" + +msgid "Value must be valid JSON." +msgstr "" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "Alc'hwez estren (seurt termenet dre ar vaezienn liammet)" + +msgid "One-to-one relationship" +msgstr "Darempred unan-ouzh-unan" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "Darempred lies-ouzh-lies" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr "" + +msgid "This field is required." +msgstr "Rekis eo leuniañ ar vaezienn." + +msgid "Enter a whole number." +msgstr "Merkit un niver anterin." + +msgid "Enter a valid date." +msgstr "Merkit un deiziad reizh" + +msgid "Enter a valid time." +msgstr "Merkit un eur reizh" + +msgid "Enter a valid date/time." +msgstr "Merkit un eur/deiziad reizh" + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "N'eus ket kaset restr ebet. Gwiriit ar seurt enkodañ evit ar restr" + +msgid "No file was submitted." +msgstr "N'eus bet kaset restr ebet." + +msgid "The submitted file is empty." +msgstr "Goullo eo ar restr kaset." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Kasit ur restr pe askit al log riñsañ; an eil pe egile" + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Enpozhiit ur skeudenn reizh. Ar seurt bet enporzhiet ganeoc'h a oa foeltret " +"pe ne oa ket ur skeudenn" + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Dizuit un dibab reizh. %(value)s n'emañ ket e-touez an dibaboù posupl." + +msgid "Enter a list of values." +msgstr "Merkit ur roll talvoudoù" + +msgid "Enter a complete value." +msgstr "Merkañ un talvoud klok" + +msgid "Enter a valid UUID." +msgstr "" + +msgid "Enter a valid JSON." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr "" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" + +#, python-format +msgid "Please submit at most %d form." +msgid_plural "Please submit at most %d forms." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgid "Please submit at least %d form." +msgid_plural "Please submit at least %d forms." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +msgid "Order" +msgstr "Urzh" + +msgid "Delete" +msgstr "Diverkañ" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Reizhit ar roadennoù e doubl e %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Reizhit ar roadennoù e doubl e %(field)s, na zle bezañ enni nemet talvoudoù " +"dzho o-unan." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Reizhit ar roadennoù e doubl e %(field_name)s a rank bezañ ennañ talvodoù en " +"o-unan evit lodenn %(lookup)s %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Reizhañ ar roadennoù e doubl zo a-is" + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Diuzit un dibab reizh. N'emañ ket an dibab-mañ e-touez ar re bosupl." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Riñsañ" + +msgid "Currently" +msgstr "Evit ar mare" + +msgid "Change" +msgstr "Kemmañ" + +msgid "Unknown" +msgstr "Dianav" + +msgid "Yes" +msgstr "Ya" + +msgid "No" +msgstr "Ket" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "ya,ket,marteze" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d okted" +msgstr[1] "%(size)d okted" +msgstr[2] "%(size)d okted" +msgstr[3] "%(size)d okted" +msgstr[4] "%(size)d okted" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "g.m." + +msgid "a.m." +msgstr "mintin" + +msgid "PM" +msgstr "G.M." + +msgid "AM" +msgstr "Mintin" + +msgid "midnight" +msgstr "hanternoz" + +msgid "noon" +msgstr "kreisteiz" + +msgid "Monday" +msgstr "Lun" + +msgid "Tuesday" +msgstr "Meurzh" + +msgid "Wednesday" +msgstr "Merc'her" + +msgid "Thursday" +msgstr "Yaou" + +msgid "Friday" +msgstr "Gwener" + +msgid "Saturday" +msgstr "Sadorn" + +msgid "Sunday" +msgstr "Sul" + +msgid "Mon" +msgstr "Lun" + +msgid "Tue" +msgstr "Meu" + +msgid "Wed" +msgstr "Mer" + +msgid "Thu" +msgstr "Yao" + +msgid "Fri" +msgstr "Gwe" + +msgid "Sat" +msgstr "Sad" + +msgid "Sun" +msgstr "Sul" + +msgid "January" +msgstr "Genver" + +msgid "February" +msgstr "C'hwevrer" + +msgid "March" +msgstr "Meurzh" + +msgid "April" +msgstr "Ebrel" + +msgid "May" +msgstr "Mae" + +msgid "June" +msgstr "Mezheven" + +msgid "July" +msgstr "Gouere" + +msgid "August" +msgstr "Eost" + +msgid "September" +msgstr "Gwengolo" + +msgid "October" +msgstr "Here" + +msgid "November" +msgstr "Du" + +msgid "December" +msgstr "Kerzu" + +msgid "jan" +msgstr "Gen" + +msgid "feb" +msgstr "C'hwe" + +msgid "mar" +msgstr "Meu" + +msgid "apr" +msgstr "Ebr" + +msgid "may" +msgstr "Mae" + +msgid "jun" +msgstr "Mez" + +msgid "jul" +msgstr "Gou" + +msgid "aug" +msgstr "Eos" + +msgid "sep" +msgstr "Gwe" + +msgid "oct" +msgstr "Her" + +msgid "nov" +msgstr "Du" + +msgid "dec" +msgstr "Kzu" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Gen." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "C'hwe." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Meu." + +msgctxt "abbrev. month" +msgid "April" +msgstr "Ebr." + +msgctxt "abbrev. month" +msgid "May" +msgstr "Mae" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Mez." + +msgctxt "abbrev. month" +msgid "July" +msgstr "Gou." + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Eos." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Gwe." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Her." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Du" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Kzu" + +msgctxt "alt. month" +msgid "January" +msgstr "Genver" + +msgctxt "alt. month" +msgid "February" +msgstr "C'hwevrer" + +msgctxt "alt. month" +msgid "March" +msgstr "Meurzh" + +msgctxt "alt. month" +msgid "April" +msgstr "Ebrel" + +msgctxt "alt. month" +msgid "May" +msgstr "Mae" + +msgctxt "alt. month" +msgid "June" +msgstr "Mezheven" + +msgctxt "alt. month" +msgid "July" +msgstr "Gouere" + +msgctxt "alt. month" +msgid "August" +msgstr "Eost" + +msgctxt "alt. month" +msgid "September" +msgstr "Gwengolo" + +msgctxt "alt. month" +msgid "October" +msgstr "Here" + +msgctxt "alt. month" +msgid "November" +msgstr "Du" + +msgctxt "alt. month" +msgid "December" +msgstr "Kerzu" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "pe" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "," + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +msgid "Forbidden" +msgstr "Difennet" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "N'eus bet resisaet bloavezh ebet" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "N'eus bet resisaet miz ebet" + +msgid "No day specified" +msgstr "N'eus bet resisaet deiz ebet" + +msgid "No week specified" +msgstr "N'eus bet resisaet sizhun ebet" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "N'eus %(verbose_name_plural)s ebet da gaout." + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"En dazont ne vo ket a %(verbose_name_plural)s rak faos eo %(class_name)s." +"allow_future." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "" +"N'eus bet kavet traezenn %(verbose_name)s ebet o klotaén gant ar goulenn" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "N'haller ket diskwel endalc'had ar c'havlec'h-mañ." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Meneger %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bs/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bs/LC_MESSAGES/django.mo new file mode 100644 index 0000000..064cc5d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bs/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bs/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bs/LC_MESSAGES/django.po new file mode 100644 index 0000000..a985b84 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bs/LC_MESSAGES/django.po @@ -0,0 +1,1238 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Filip Dupanović , 2011 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Bosnian (http://www.transifex.com/django/django/language/" +"bs/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bs\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Afrikaans" +msgstr "" + +msgid "Arabic" +msgstr "arapski" + +msgid "Asturian" +msgstr "" + +msgid "Azerbaijani" +msgstr "Azerbejdžanski" + +msgid "Bulgarian" +msgstr "bugarski" + +msgid "Belarusian" +msgstr "" + +msgid "Bengali" +msgstr "bengalski" + +msgid "Breton" +msgstr "" + +msgid "Bosnian" +msgstr "bosanski" + +msgid "Catalan" +msgstr "katalonski" + +msgid "Czech" +msgstr "češki" + +msgid "Welsh" +msgstr "velški" + +msgid "Danish" +msgstr "danski" + +msgid "German" +msgstr "njemački" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "grčki" + +msgid "English" +msgstr "engleski" + +msgid "Australian English" +msgstr "" + +msgid "British English" +msgstr "Britanski engleski" + +msgid "Esperanto" +msgstr "" + +msgid "Spanish" +msgstr "španski" + +msgid "Argentinian Spanish" +msgstr "Argentinski španski" + +msgid "Colombian Spanish" +msgstr "" + +msgid "Mexican Spanish" +msgstr "Meksički španski" + +msgid "Nicaraguan Spanish" +msgstr "Nikuaraganski španski" + +msgid "Venezuelan Spanish" +msgstr "" + +msgid "Estonian" +msgstr "estonski" + +msgid "Basque" +msgstr "baskijski" + +msgid "Persian" +msgstr "persijski" + +msgid "Finnish" +msgstr "finski" + +msgid "French" +msgstr "francuski" + +msgid "Frisian" +msgstr "frišanski" + +msgid "Irish" +msgstr "irski" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "galski" + +msgid "Hebrew" +msgstr "hebrejski" + +msgid "Hindi" +msgstr "hindi" + +msgid "Croatian" +msgstr "hrvatski" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "mađarski" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "" + +msgid "Indonesian" +msgstr "Indonežanski" + +msgid "Ido" +msgstr "" + +msgid "Icelandic" +msgstr "islandski" + +msgid "Italian" +msgstr "italijanski" + +msgid "Japanese" +msgstr "japanski" + +msgid "Georgian" +msgstr "gruzijski" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "" + +msgid "Khmer" +msgstr "kambođanski" + +msgid "Kannada" +msgstr "kanada" + +msgid "Korean" +msgstr "korejski" + +msgid "Luxembourgish" +msgstr "" + +msgid "Lithuanian" +msgstr "litvanski" + +msgid "Latvian" +msgstr "latvijski" + +msgid "Macedonian" +msgstr "makedonski" + +msgid "Malayalam" +msgstr "Malajalamski" + +msgid "Mongolian" +msgstr "Mongolski" + +msgid "Marathi" +msgstr "" + +msgid "Burmese" +msgstr "" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "" + +msgid "Dutch" +msgstr "holandski" + +msgid "Norwegian Nynorsk" +msgstr "Norveški novi" + +msgid "Ossetic" +msgstr "" + +msgid "Punjabi" +msgstr "Pandžabi" + +msgid "Polish" +msgstr "poljski" + +msgid "Portuguese" +msgstr "portugalski" + +msgid "Brazilian Portuguese" +msgstr "brazilski portugalski" + +msgid "Romanian" +msgstr "rumunski" + +msgid "Russian" +msgstr "ruski" + +msgid "Slovak" +msgstr "slovački" + +msgid "Slovenian" +msgstr "slovenački" + +msgid "Albanian" +msgstr "albanski" + +msgid "Serbian" +msgstr "srpski" + +msgid "Serbian Latin" +msgstr "srpski latinski" + +msgid "Swedish" +msgstr "švedski" + +msgid "Swahili" +msgstr "" + +msgid "Tamil" +msgstr "tamilski" + +msgid "Telugu" +msgstr "telugu" + +msgid "Thai" +msgstr "tajlandski" + +msgid "Turkish" +msgstr "turski" + +msgid "Tatar" +msgstr "" + +msgid "Udmurt" +msgstr "" + +msgid "Ukrainian" +msgstr "ukrajinski" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "vijetnamežanski" + +msgid "Simplified Chinese" +msgstr "novokineski" + +msgid "Traditional Chinese" +msgstr "starokineski" + +msgid "Messages" +msgstr "" + +msgid "Site Maps" +msgstr "" + +msgid "Static Files" +msgstr "" + +msgid "Syndication" +msgstr "" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "Unesite ispravnu vrijednost." + +msgid "Enter a valid URL." +msgstr "Unesite ispravan URL." + +msgid "Enter a valid integer." +msgstr "" + +msgid "Enter a valid email address." +msgstr "" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Unesite ispravnu IPv4 adresu." + +msgid "Enter a valid IPv6 address." +msgstr "" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "" + +msgid "Enter only digits separated by commas." +msgstr "Unesite samo brojke razdvojene zapetama." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Pobrinite se da je ova vrijednost %(limit_value)s (trenutno je " +"%(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Ova vrijednost mora da bude manja ili jednaka %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Ova vrijednost mora biti veća ili jednaka %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +msgid "Enter a number." +msgstr "Unesite broj." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "i" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "Ovo polje ne može ostati prazno." + +msgid "This field cannot be blank." +msgstr "Ovo polje ne može biti prazno." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s sa ovom vrijednošću %(field_label)s već postoji." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Polje tipa: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "Bulova vrijednost (True ili False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "String (najviše %(max_length)s znakova)" + +msgid "Comma-separated integers" +msgstr "Cijeli brojevi razdvojeni zapetama" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "Datum (bez vremena)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Datum (sa vremenom)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Decimalni broj" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "" + +msgid "Email address" +msgstr "Email adresa" + +msgid "File path" +msgstr "Putanja fajla" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "Broj sa pokrenom zapetom" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "Cijeo broj" + +msgid "Big (8 byte) integer" +msgstr "Big (8 bajtni) integer" + +msgid "IPv4 address" +msgstr "" + +msgid "IP address" +msgstr "IP adresa" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "Bulova vrijednost (True, False ili None)" + +msgid "Positive integer" +msgstr "" + +msgid "Positive small integer" +msgstr "" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "" + +msgid "Small integer" +msgstr "" + +msgid "Text" +msgstr "Tekst" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Vrijeme" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "" + +msgid "Image" +msgstr "" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "Strani ključ (tip određen povezanim poljem)" + +msgid "One-to-one relationship" +msgstr "Jedan-na-jedan odnos" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "Više-na-više odsnos" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr "" + +msgid "This field is required." +msgstr "Ovo polje se mora popuniti." + +msgid "Enter a whole number." +msgstr "Unesite cijeo broj." + +msgid "Enter a valid date." +msgstr "Unesite ispravan datum." + +msgid "Enter a valid time." +msgstr "Unesite ispravno vrijeme" + +msgid "Enter a valid date/time." +msgstr "Unesite ispravan datum/vrijeme." + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Fajl nije prebačen. Provjerite tip enkodiranja formulara." + +msgid "No file was submitted." +msgstr "Fajl nije prebačen." + +msgid "The submitted file is empty." +msgstr "Prebačen fajl je prazan." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Prebacite ispravan fajl. Fajl koji je prebačen ili nije slika, ili je " +"oštećen." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"%(value)s nije među ponuđenim vrijednostima. Odaberite jednu od ponuđenih." + +msgid "Enter a list of values." +msgstr "Unesite listu vrijednosti." + +msgid "Enter a complete value." +msgstr "" + +msgid "Enter a valid UUID." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr "" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +msgid "Order" +msgstr "Redoslijed" + +msgid "Delete" +msgstr "Obriši" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Ispravite dupli sadržaj za polja: %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Ispravite dupli sadržaj za polja: %(field)s, koji mora da bude jedinstven." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Ispravite dupli sadržaj za polja: %(field_name)s, koji mora da bude " +"jedinstven za %(lookup)s u %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Ispravite duple vrijednosti dole." + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Odabrana vrijednost nije među ponuđenima. Odaberite jednu od ponuđenih." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Očisti" + +msgid "Currently" +msgstr "Trenutno" + +msgid "Change" +msgstr "Izmjeni" + +msgid "Unknown" +msgstr "Nepoznato" + +msgid "Yes" +msgstr "Da" + +msgid "No" +msgstr "Ne" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "da,ne,možda" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "po p." + +msgid "a.m." +msgstr "prije p." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "ponoć" + +msgid "noon" +msgstr "podne" + +msgid "Monday" +msgstr "ponedjeljak" + +msgid "Tuesday" +msgstr "utorak" + +msgid "Wednesday" +msgstr "srijeda" + +msgid "Thursday" +msgstr "četvrtak" + +msgid "Friday" +msgstr "petak" + +msgid "Saturday" +msgstr "subota" + +msgid "Sunday" +msgstr "nedjelja" + +msgid "Mon" +msgstr "pon." + +msgid "Tue" +msgstr "uto." + +msgid "Wed" +msgstr "sri." + +msgid "Thu" +msgstr "čet." + +msgid "Fri" +msgstr "pet." + +msgid "Sat" +msgstr "sub." + +msgid "Sun" +msgstr "ned." + +msgid "January" +msgstr "januar" + +msgid "February" +msgstr "februar" + +msgid "March" +msgstr "mart" + +msgid "April" +msgstr "april" + +msgid "May" +msgstr "maj" + +msgid "June" +msgstr "juni" + +msgid "July" +msgstr "juli" + +msgid "August" +msgstr "august" + +msgid "September" +msgstr "septembar" + +msgid "October" +msgstr "oktobar" + +msgid "November" +msgstr "novembar" + +msgid "December" +msgstr "decembar" + +msgid "jan" +msgstr "jan." + +msgid "feb" +msgstr "feb." + +msgid "mar" +msgstr "mar." + +msgid "apr" +msgstr "apr." + +msgid "may" +msgstr "maj." + +msgid "jun" +msgstr "jun." + +msgid "jul" +msgstr "jul." + +msgid "aug" +msgstr "aug." + +msgid "sep" +msgstr "sep." + +msgid "oct" +msgstr "okt." + +msgid "nov" +msgstr "nov." + +msgid "dec" +msgstr "dec." + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Mart" + +msgctxt "abbrev. month" +msgid "April" +msgstr "April" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Maj" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Juni" + +msgctxt "abbrev. month" +msgid "July" +msgstr "juli" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "august" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "septembar" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "oktobar" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "novembar" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "decembar" + +msgctxt "alt. month" +msgid "January" +msgstr "januar" + +msgctxt "alt. month" +msgid "February" +msgstr "februar" + +msgctxt "alt. month" +msgid "March" +msgstr "mart" + +msgctxt "alt. month" +msgid "April" +msgstr "april" + +msgctxt "alt. month" +msgid "May" +msgstr "maj" + +msgctxt "alt. month" +msgid "June" +msgstr "juni" + +msgctxt "alt. month" +msgid "July" +msgstr "juli" + +msgctxt "alt. month" +msgid "August" +msgstr "august" + +msgctxt "alt. month" +msgid "September" +msgstr "septembar" + +msgctxt "alt. month" +msgid "October" +msgstr "oktobar" + +msgctxt "alt. month" +msgid "November" +msgstr "Novembar" + +msgctxt "alt. month" +msgid "December" +msgstr "decembar" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "ili" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +msgid "0 minutes" +msgstr "" + +msgid "Forbidden" +msgstr "" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "Godina nije naznačena" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "Mjesec nije naznačen" + +msgid "No day specified" +msgstr "Dan nije naznačen" + +msgid "No week specified" +msgstr "Sedmica nije naznačena" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "" + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bs/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bs/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bs/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bs/formats.py new file mode 100644 index 0000000..a15e709 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/bs/formats.py @@ -0,0 +1,21 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j. N Y." +TIME_FORMAT = "G:i" +DATETIME_FORMAT = "j. N. Y. G:i T" +YEAR_MONTH_FORMAT = "F Y." +MONTH_DAY_FORMAT = "j. F" +SHORT_DATE_FORMAT = "Y M j" +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +# NUMBER_GROUPING = diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ca/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ca/LC_MESSAGES/django.mo new file mode 100644 index 0000000..208f4a4 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ca/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ca/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ca/LC_MESSAGES/django.po new file mode 100644 index 0000000..01e4dda --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ca/LC_MESSAGES/django.po @@ -0,0 +1,1340 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Antoni Aloy , 2012,2015-2017,2021-2022 +# Carles Barrobés , 2011-2012,2014,2020 +# duub qnnp, 2015 +# Emilio Carrion, 2022 +# Gil Obradors Via , 2019 +# Gil Obradors Via , 2019 +# Jannis Leidel , 2011 +# Manel Clos , 2020 +# Manuel Miranda , 2015 +# Mariusz Felisiak , 2021 +# Roger Pons , 2015 +# Santiago Lamora , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-05-17 05:23-0500\n" +"PO-Revision-Date: 2022-07-25 06:49+0000\n" +"Last-Translator: Emilio Carrion\n" +"Language-Team: Catalan (http://www.transifex.com/django/django/language/" +"ca/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ca\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Afrikans" + +msgid "Arabic" +msgstr "àrab" + +msgid "Algerian Arabic" +msgstr "àrab argelià" + +msgid "Asturian" +msgstr "Asturià" + +msgid "Azerbaijani" +msgstr "azerbaijanès" + +msgid "Bulgarian" +msgstr "búlgar" + +msgid "Belarusian" +msgstr "Bielorús" + +msgid "Bengali" +msgstr "bengalí" + +msgid "Breton" +msgstr "Bretó" + +msgid "Bosnian" +msgstr "bosnià" + +msgid "Catalan" +msgstr "català" + +msgid "Czech" +msgstr "txec" + +msgid "Welsh" +msgstr "gal·lès" + +msgid "Danish" +msgstr "danès" + +msgid "German" +msgstr "alemany" + +msgid "Lower Sorbian" +msgstr "baix serbi" + +msgid "Greek" +msgstr "grec" + +msgid "English" +msgstr "anglès" + +msgid "Australian English" +msgstr "Anglès d'Austràlia" + +msgid "British English" +msgstr "anglès britànic" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "castellà" + +msgid "Argentinian Spanish" +msgstr "castellà d'Argentina" + +msgid "Colombian Spanish" +msgstr "castellà de Colombia" + +msgid "Mexican Spanish" +msgstr "castellà de Mèxic" + +msgid "Nicaraguan Spanish" +msgstr "castellà de Nicaragua" + +msgid "Venezuelan Spanish" +msgstr "castellà de Veneçuela" + +msgid "Estonian" +msgstr "estonià" + +msgid "Basque" +msgstr "èuscar" + +msgid "Persian" +msgstr "persa" + +msgid "Finnish" +msgstr "finlandès" + +msgid "French" +msgstr "francès" + +msgid "Frisian" +msgstr "frisi" + +msgid "Irish" +msgstr "irlandès" + +msgid "Scottish Gaelic" +msgstr "Gaèlic escocès" + +msgid "Galician" +msgstr "gallec" + +msgid "Hebrew" +msgstr "hebreu" + +msgid "Hindi" +msgstr "hindi" + +msgid "Croatian" +msgstr "croat" + +msgid "Upper Sorbian" +msgstr "alt serbi" + +msgid "Hungarian" +msgstr "hongarès" + +msgid "Armenian" +msgstr "Armeni" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "indonesi" + +msgid "Igbo" +msgstr "lgbo" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "islandès" + +msgid "Italian" +msgstr "italià" + +msgid "Japanese" +msgstr "japonès" + +msgid "Georgian" +msgstr "georgià" + +msgid "Kabyle" +msgstr "Cabilenc" + +msgid "Kazakh" +msgstr "Kazakh" + +msgid "Khmer" +msgstr "khmer" + +msgid "Kannada" +msgstr "kannarès" + +msgid "Korean" +msgstr "coreà" + +msgid "Kyrgyz" +msgstr "Kyrgyz" + +msgid "Luxembourgish" +msgstr "Luxemburguès" + +msgid "Lithuanian" +msgstr "lituà" + +msgid "Latvian" +msgstr "letó" + +msgid "Macedonian" +msgstr "macedoni" + +msgid "Malayalam" +msgstr "malaiàlam " + +msgid "Mongolian" +msgstr "mongol" + +msgid "Marathi" +msgstr "Maratí" + +msgid "Malay" +msgstr "Malai" + +msgid "Burmese" +msgstr "Burmès" + +msgid "Norwegian Bokmål" +msgstr "Bokmål noruec" + +msgid "Nepali" +msgstr "nepalès" + +msgid "Dutch" +msgstr "holandès" + +msgid "Norwegian Nynorsk" +msgstr "noruec nynorsk" + +msgid "Ossetic" +msgstr "ossètic" + +msgid "Punjabi" +msgstr "panjabi" + +msgid "Polish" +msgstr "polonès" + +msgid "Portuguese" +msgstr "portuguès" + +msgid "Brazilian Portuguese" +msgstr "portuguès de brasil" + +msgid "Romanian" +msgstr "romanès" + +msgid "Russian" +msgstr "rus" + +msgid "Slovak" +msgstr "eslovac" + +msgid "Slovenian" +msgstr "eslovè" + +msgid "Albanian" +msgstr "albanès" + +msgid "Serbian" +msgstr "serbi" + +msgid "Serbian Latin" +msgstr "serbi llatí" + +msgid "Swedish" +msgstr "suec" + +msgid "Swahili" +msgstr "Swahili" + +msgid "Tamil" +msgstr "tàmil" + +msgid "Telugu" +msgstr "telugu" + +msgid "Tajik" +msgstr "Tajik" + +msgid "Thai" +msgstr "tailandès" + +msgid "Turkmen" +msgstr "Turkmen" + +msgid "Turkish" +msgstr "turc" + +msgid "Tatar" +msgstr "Tatar" + +msgid "Udmurt" +msgstr "Udmurt" + +msgid "Ukrainian" +msgstr "ucraïnès" + +msgid "Urdu" +msgstr "urdu" + +msgid "Uzbek" +msgstr "Uzbek" + +msgid "Vietnamese" +msgstr "vietnamita" + +msgid "Simplified Chinese" +msgstr "xinès simplificat" + +msgid "Traditional Chinese" +msgstr "xinès tradicional" + +msgid "Messages" +msgstr "Missatges" + +msgid "Site Maps" +msgstr "Mapes del lloc" + +msgid "Static Files" +msgstr "Arxius estàtics" + +msgid "Syndication" +msgstr "Sindicació" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "..." + +msgid "That page number is not an integer" +msgstr "Aquest número de plana no és un enter" + +msgid "That page number is less than 1" +msgstr "El nombre de plana és inferior a 1" + +msgid "That page contains no results" +msgstr "La plana no conté cap resultat" + +msgid "Enter a valid value." +msgstr "Introduïu un valor vàlid." + +msgid "Enter a valid URL." +msgstr "Introduïu una URL vàlida." + +msgid "Enter a valid integer." +msgstr "Introduïu un enter vàlid." + +msgid "Enter a valid email address." +msgstr "Introdueix una adreça de correu electrònic vàlida" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Introduïu un 'slug' vàlid, consistent en lletres, números, guions o guions " +"baixos." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Introduïu un 'slug' vàlid format per lletres Unicode, números, guions o " +"guions baixos." + +msgid "Enter a valid IPv4 address." +msgstr "Introduïu una adreça IPv4 vàlida." + +msgid "Enter a valid IPv6 address." +msgstr "Entreu una adreça IPv6 vàlida." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Entreu una adreça IPv4 o IPv6 vàlida." + +msgid "Enter only digits separated by commas." +msgstr "Introduïu només dígits separats per comes." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Assegureu-vos que aquest valor sigui %(limit_value)s (és %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" +"Assegureu-vos que aquest valor sigui menor o igual que %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" +"Assegureu-vos que aquest valor sigui més gran o igual que %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" +" \n" +"Asseguri's que aquest valor sigui un múltiple de %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Assegureu-vos que aquest valor té almenys %(limit_value)d caràcter (en té " +"%(show_value)d)." +msgstr[1] "" +"Assegureu-vos que el valor tingui almenys %(limit_value)d caràcters (en té " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Assegureu-vos que aquest valor té com a molt %(limit_value)d caràcter (en té " +"%(show_value)d)." +msgstr[1] "" +"Assegureu-vos que aquest valor tingui com a molt %(limit_value)d caràcters " +"(en té %(show_value)d)." + +msgid "Enter a number." +msgstr "Introduïu un número." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Assegureu-vos que no hi ha més de %(max)s dígit en total." +msgstr[1] "Assegureu-vos que no hi hagi més de %(max)s dígits en total." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Assegureu-vos que no hi ha més de %(max)s decimal." +msgstr[1] "Assegureu-vos que no hi hagi més de %(max)s decimals." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Assegureu-vos que no hi ha més de %(max)s dígit abans de la coma decimal." +msgstr[1] "" +"Assegureu-vos que no hi hagi més de %(max)s dígits abans de la coma decimal." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"L'extensió d'arxiu “%(extension)s” no està permesa. Les extensions permeses " +"són: %(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "No es permeten caràcters nuls." + +msgid "and" +msgstr "i" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "Ja existeix %(model_name)s amb aquest %(field_labels)s." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "La restricció %(name)s no es compleix." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "El valor %(value)r no és una opció vàlida." + +msgid "This field cannot be null." +msgstr "Aquest camp no pot ser nul." + +msgid "This field cannot be blank." +msgstr "Aquest camp no pot estar en blanc." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "Ja existeix %(model_name)s amb aquest %(field_label)s." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s ha de ser únic per a %(date_field_label)s i %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Camp del tipus: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "El valor '%(value)s' ha de ser \"True\" o \"False\"." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "El valor '%(value)s' ha de ser cert, fals o buid." + +msgid "Boolean (Either True or False)" +msgstr "Booleà (Cert o Fals)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Cadena (de fins a %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "Enters separats per comes" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"El valor '%(value)s' no té un format de data vàlid. Ha de tenir el format " +"YYYY-MM-DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"El valor '%(value)s' té el format correcte (YYYY-MM-DD) però no és una data " +"vàlida." + +msgid "Date (without time)" +msgstr "Data (sense hora)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"El valor '%(value)s' no té un format vàlid. Ha de tenir el format YYYY-MM-DD " +"HH:MM[:ss[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"El valor '%(value)s' té el format correcte (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) però no és una data/hora vàlida." + +msgid "Date (with time)" +msgstr "Data (amb hora)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "El valor '%(value)s' ha de ser un nombre decimal." + +msgid "Decimal number" +msgstr "Número decimal" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"'El valor %(value)s' té un format invàlid. Ha d'estar en el format [DD] [HH:" +"[MM:]]ss[.uuuuuu] ." + +msgid "Duration" +msgstr "Durada" + +msgid "Email address" +msgstr "Adreça de correu electrònic" + +msgid "File path" +msgstr "Ruta del fitxer" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "El valor '%(value)s' ha de ser un número decimal." + +msgid "Floating point number" +msgstr "Número de coma flotant" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "El valor '%(value)s' ha de ser un nombre enter." + +msgid "Integer" +msgstr "Enter" + +msgid "Big (8 byte) integer" +msgstr "Enter gran (8 bytes)" + +msgid "Small integer" +msgstr "Enter petit" + +msgid "IPv4 address" +msgstr "Adreça IPv4" + +msgid "IP address" +msgstr "Adreça IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "El valor '%(value)s' ha de ser None, True o False." + +msgid "Boolean (Either True, False or None)" +msgstr "Booleà (Cert, Fals o Cap ('None'))" + +msgid "Positive big integer" +msgstr "Enter gran positiu" + +msgid "Positive integer" +msgstr "Enter positiu" + +msgid "Positive small integer" +msgstr "Enter petit positiu" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (fins a %(max_length)s)" + +msgid "Text" +msgstr "Text" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"El valor '%(value)s' no té un format vàlid. Ha de tenir el format HH:MM[:ss[." +"uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"El valor '%(value)s' té el format correcte (HH:MM[:ss[.uuuuuu]]) però no és " +"una hora vàlida." + +msgid "Time" +msgstr "Hora" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Dades binàries" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "'%(value)s' no és un UUID vàlid." + +msgid "Universally unique identifier" +msgstr "Identificador únic universal" + +msgid "File" +msgstr "Arxiu" + +msgid "Image" +msgstr "Imatge" + +msgid "A JSON object" +msgstr "Un objecte JSON" + +msgid "Value must be valid JSON." +msgstr "El valor ha de ser JSON vàlid." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "La instància de %(model)s amb %(field)s %(value)r no existeix." + +msgid "Foreign Key (type determined by related field)" +msgstr "Clau forana (tipus determinat pel camp relacionat)" + +msgid "One-to-one relationship" +msgstr "Relació un-a-un" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "relació %(from)s-%(to)s " + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "relacions %(from)s-%(to)s " + +msgid "Many-to-many relationship" +msgstr "Relació molts-a-molts" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Aquest camp és obligatori." + +msgid "Enter a whole number." +msgstr "Introduïu un número enter." + +msgid "Enter a valid date." +msgstr "Introduïu una data vàlida." + +msgid "Enter a valid time." +msgstr "Introduïu una hora vàlida." + +msgid "Enter a valid date/time." +msgstr "Introduïu una data/hora vàlides." + +msgid "Enter a valid duration." +msgstr "Introduïu una durada vàlida." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "El número de dies ha de ser entre {min_days} i {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" +"No s'ha enviat cap fitxer. Comproveu el tipus de codificació del formulari." + +msgid "No file was submitted." +msgstr "No s'ha enviat cap fitxer." + +msgid "The submitted file is empty." +msgstr "El fitxer enviat està buit." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Aquest nom d'arxiu hauria de tenir com a molt %(max)d caràcter (en té " +"%(length)d)." +msgstr[1] "" +"Aquest nom d'arxiu hauria de tenir com a molt %(max)d caràcters (en té " +"%(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Si us plau, envieu un fitxer o marqueu la casella de selecció \"netejar\", " +"no ambdós." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Carregueu una imatge vàlida. El fitxer que heu carregat no era una imatge o " +"estava corrupte." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Esculliu una opció vàlida. %(value)s no és una de les opcions vàlides." + +msgid "Enter a list of values." +msgstr "Introduïu una llista de valors." + +msgid "Enter a complete value." +msgstr "Introduïu un valor complet." + +msgid "Enter a valid UUID." +msgstr "Intruduïu un UUID vàlid." + +msgid "Enter a valid JSON." +msgstr "Introduïu un JSON vàlid." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Camp ocult %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"Les dades de ManagementForm no hi són o han estat modificades. Camps que " +"falten: %(field_names)s. . Necessitaràs omplir una incidència si el problema " +"persisteix." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Enviau com a màxim %(num)d formulari, si us plau." +msgstr[1] "Enviau com a màxim %(num)d formularis, si us plau." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Enviau com a mínim %(num)d formulari, si us plau." +msgstr[1] "Enviau com a mínim %(num)d formularis, si us plau." + +msgid "Order" +msgstr "Ordre" + +msgid "Delete" +msgstr "Eliminar" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Si us plau, corregiu la dada duplicada per a %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Si us plau, corregiu la dada duplicada per a %(field)s, la qual ha de ser " +"única." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Si us plau, corregiu la dada duplicada per a %(field_name)s, la qual ha de " +"ser única per a %(lookup)s en %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Si us plau, corregiu els valors duplicats a sota." + +msgid "The inline value did not match the parent instance." +msgstr "El valor en línia no coincideix amb la instància mare ." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Esculliu una opció vàlida. La opció triada no és una de les opcions " +"disponibles." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "\"%(pk)s\" no és un valor vàlid" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"No s'ha pogut interpretar %(datetime)s a la zona horària " +"%(current_timezone)s; potser és ambigua o no existeix." + +msgid "Clear" +msgstr "Netejar" + +msgid "Currently" +msgstr "Actualment" + +msgid "Change" +msgstr "Modificar" + +msgid "Unknown" +msgstr "Desconegut" + +msgid "Yes" +msgstr "Sí" + +msgid "No" +msgstr "No" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "sí,no,potser" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d byte" +msgstr[1] "%(size)d bytes" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "mitjanit" + +msgid "noon" +msgstr "migdia" + +msgid "Monday" +msgstr "Dilluns" + +msgid "Tuesday" +msgstr "Dimarts" + +msgid "Wednesday" +msgstr "Dimecres" + +msgid "Thursday" +msgstr "Dijous" + +msgid "Friday" +msgstr "Divendres" + +msgid "Saturday" +msgstr "Dissabte" + +msgid "Sunday" +msgstr "Diumenge" + +msgid "Mon" +msgstr "dl." + +msgid "Tue" +msgstr "dt." + +msgid "Wed" +msgstr "dc." + +msgid "Thu" +msgstr "dj." + +msgid "Fri" +msgstr "dv." + +msgid "Sat" +msgstr "ds." + +msgid "Sun" +msgstr "dg." + +msgid "January" +msgstr "gener" + +msgid "February" +msgstr "febrer" + +msgid "March" +msgstr "març" + +msgid "April" +msgstr "abril" + +msgid "May" +msgstr "maig" + +msgid "June" +msgstr "juny" + +msgid "July" +msgstr "juliol" + +msgid "August" +msgstr "agost" + +msgid "September" +msgstr "setembre" + +msgid "October" +msgstr "octubre" + +msgid "November" +msgstr "novembre" + +msgid "December" +msgstr "desembre" + +msgid "jan" +msgstr "gen." + +msgid "feb" +msgstr "feb." + +msgid "mar" +msgstr "març" + +msgid "apr" +msgstr "abr." + +msgid "may" +msgstr "maig" + +msgid "jun" +msgstr "juny" + +msgid "jul" +msgstr "jul." + +msgid "aug" +msgstr "ago." + +msgid "sep" +msgstr "set." + +msgid "oct" +msgstr "oct." + +msgid "nov" +msgstr "nov." + +msgid "dec" +msgstr "des." + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Gen." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Març" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Abr." + +msgctxt "abbrev. month" +msgid "May" +msgstr "Maig" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Juny" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Jul." + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Ago." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Set." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Oct." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Des." + +msgctxt "alt. month" +msgid "January" +msgstr "gener" + +msgctxt "alt. month" +msgid "February" +msgstr "febrer" + +msgctxt "alt. month" +msgid "March" +msgstr "març" + +msgctxt "alt. month" +msgid "April" +msgstr "abril" + +msgctxt "alt. month" +msgid "May" +msgstr "maig" + +msgctxt "alt. month" +msgid "June" +msgstr "juny" + +msgctxt "alt. month" +msgid "July" +msgstr "juliol" + +msgctxt "alt. month" +msgid "August" +msgstr "agost" + +msgctxt "alt. month" +msgid "September" +msgstr "setembre" + +msgctxt "alt. month" +msgid "October" +msgstr "octubre" + +msgctxt "alt. month" +msgid "November" +msgstr "novembre" + +msgctxt "alt. month" +msgid "December" +msgstr "desembre" + +msgid "This is not a valid IPv6 address." +msgstr "Aquesta no és una adreça IPv6 vàlida." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "o" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d any" +msgstr[1] "%(num)d anys" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mes" +msgstr[1] "%(num)d mesos" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d setmana" +msgstr[1] "%(num)d setmanes" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dia" +msgstr[1] "%(num)d dies" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hora" +msgstr[1] "%(num)d hores" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minut" +msgstr[1] "%(num)d minuts" + +msgid "Forbidden" +msgstr "Prohibit" + +msgid "CSRF verification failed. Request aborted." +msgstr "La verificació de CSRF ha fallat. Petició abortada." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Esteu veient aquest missatge perquè aquest lloc HTTPS requereix que el " +"vostre navegador enviï una capçalera “Referer\", i no n'ha arribada cap. " +"Aquesta capçalera es requereix per motius de seguretat, per garantir que el " +"vostre navegador no està sent segrestat per tercers." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Si heu configurat el vostre navegador per deshabilitar capçaleres “Referer" +"\", sisplau torneu-les a habilitar, com a mínim per a aquest lloc, o per a " +"connexions HTTPs, o per a peticions amb el mateix orígen." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Si utilitzeu l'etiqueta o " +"incloeu la capçalera “Referer-Policy: no-referrer\" , si us plau elimineu-" +"la. La protecció CSRF requereix la capçalera “Referer\" per a fer una " +"comprovació estricta. Si esteu preocupats quant a la privacitat, utilitzeu " +"alternatives com per enllaços a aplicacions de " +"tercers." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Estàs veient aquest missatge perquè aquest lloc requereix una galeta CSRF " +"quan s'envien formularis. Aquesta galeta es requereix per motius de " +"seguretat, per garantir que el teu navegador no està sent infiltrat per " +"tercers." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Si has configurat el teu navegador per deshabilitar galetes, sisplau torna-" +"les a habilitar, com a mínim per a aquest lloc, o per a peticions amb el " +"mateix orígen." + +msgid "More information is available with DEBUG=True." +msgstr "Més informació disponible amb DEBUG=True." + +msgid "No year specified" +msgstr "No s'ha especificat any" + +msgid "Date out of range" +msgstr "Data fora de rang" + +msgid "No month specified" +msgstr "No s'ha especificat mes" + +msgid "No day specified" +msgstr "No s'ha especificat dia" + +msgid "No week specified" +msgstr "No s'ha especificat setmana" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Cap %(verbose_name_plural)s disponible" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Futurs %(verbose_name_plural)s no disponibles perquè %(class_name)s." +"allow_future és Fals." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Cadena invàlida de data '%(datestr)s' donat el format '%(format)s'" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "No s'ha trobat cap %(verbose_name)s que coincideixi amb la petició" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "La pàgina no és 'last', ni es pot convertir en un enter" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Pàgina invàlida (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Llista buida i '%(class_name)s.allow_empty' és Fals." + +msgid "Directory indexes are not allowed here." +msgstr "Aquí no es permeten índex de directori." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "\"%(path)s\" no existeix" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Índex de %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "La instal·lació ha estat un èxit! Enhorabona!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Visualitza notes de llançament per Django " +"%(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" +"Esteu veient aquesta pàgina perquè el paràmetre DEBUG=Trueconsta al fitxer de configuració i no teniu cap " +"URL configurada." + +msgid "Django Documentation" +msgstr "Documentació de Django" + +msgid "Topics, references, & how-to’s" +msgstr "Temes, referències, & Com es fa" + +msgid "Tutorial: A Polling App" +msgstr "Tutorial: Una aplicació enquesta" + +msgid "Get started with Django" +msgstr "Primers passos amb Django" + +msgid "Django Community" +msgstr "Comunitat Django" + +msgid "Connect, get help, or contribute" +msgstr "Connecta, obté ajuda, o col·labora" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ca/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ca/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ca/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ca/formats.py new file mode 100644 index 0000000..e616299 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ca/formats.py @@ -0,0 +1,30 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = r"j E \d\e Y" +TIME_FORMAT = "G:i" +DATETIME_FORMAT = r"j E \d\e Y \a \l\e\s G:i" +YEAR_MONTH_FORMAT = r"F \d\e\l Y" +MONTH_DAY_FORMAT = r"j E" +SHORT_DATE_FORMAT = "d/m/Y" +SHORT_DATETIME_FORMAT = "d/m/Y G:i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d/%m/%Y", # '31/12/2009' + "%d/%m/%y", # '31/12/09' +] +DATETIME_INPUT_FORMATS = [ + "%d/%m/%Y %H:%M:%S", + "%d/%m/%Y %H:%M:%S.%f", + "%d/%m/%Y %H:%M", + "%d/%m/%y %H:%M:%S", + "%d/%m/%y %H:%M:%S.%f", + "%d/%m/%y %H:%M", +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ckb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ckb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ca3d949 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ckb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ckb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ckb/LC_MESSAGES/django.po new file mode 100644 index 0000000..af7fef2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ckb/LC_MESSAGES/django.po @@ -0,0 +1,1313 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bawar Jalal, 2021 +# Bawar Jalal, 2020-2021 +# Bawar Jalal, 2020 +# kosar tofiq , 2020-2021 +# Swara , 2022-2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-25 06:49+0000\n" +"Last-Translator: Swara , 2022-2023\n" +"Language-Team: Central Kurdish (http://app.transifex.com/django/django/" +"language/ckb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ckb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "ئەفریقی" + +msgid "Arabic" +msgstr "عەرەبی" + +msgid "Algerian Arabic" +msgstr "عەرەبیی جەزائیری" + +msgid "Asturian" +msgstr "ئاستوری" + +msgid "Azerbaijani" +msgstr "ئازەربایجانی" + +msgid "Bulgarian" +msgstr "بولگاری" + +msgid "Belarusian" +msgstr "بیلاڕوسی" + +msgid "Bengali" +msgstr "بەنگالی" + +msgid "Breton" +msgstr "بریتۆنی" + +msgid "Bosnian" +msgstr "بۆسنێیی" + +msgid "Catalan" +msgstr "کاتالانی" + +msgid "Central Kurdish (Sorani)" +msgstr "" + +msgid "Czech" +msgstr "چیکی" + +msgid "Welsh" +msgstr "وێڵزی" + +msgid "Danish" +msgstr "دانیمارکی" + +msgid "German" +msgstr "ئەڵمانی" + +msgid "Lower Sorbian" +msgstr "سۆربیانی خواروو" + +msgid "Greek" +msgstr "یۆنانی" + +msgid "English" +msgstr "ئینگلیزی" + +msgid "Australian English" +msgstr "ئینگلیزی ئوستورالی" + +msgid "British English" +msgstr "ئینگلیزی بەریتانی" + +msgid "Esperanto" +msgstr "ئێسپەرانتەویی" + +msgid "Spanish" +msgstr "ئیسپانی" + +msgid "Argentinian Spanish" +msgstr "ئیسپانیی ئەرجەنتینی" + +msgid "Colombian Spanish" +msgstr "ئیسپانیی کۆڵۆمبی" + +msgid "Mexican Spanish" +msgstr "ئیسپانیی مەکسیکی" + +msgid "Nicaraguan Spanish" +msgstr "ئیسپانیی نیکاراگوایی" + +msgid "Venezuelan Spanish" +msgstr "ئیسپانیی فەنزوێلایی" + +msgid "Estonian" +msgstr "ئیستۆنی" + +msgid "Basque" +msgstr "باسکۆیی" + +msgid "Persian" +msgstr "فارسی" + +msgid "Finnish" +msgstr "فینلەندی" + +msgid "French" +msgstr "فەڕەنسی" + +msgid "Frisian" +msgstr "فریسی" + +msgid "Irish" +msgstr "ئیرلەندی" + +msgid "Scottish Gaelic" +msgstr "گالیکی سکۆتلەندی" + +msgid "Galician" +msgstr "گالیسیایی" + +msgid "Hebrew" +msgstr "ئیسرائیلی" + +msgid "Hindi" +msgstr "هیندی" + +msgid "Croatian" +msgstr "کڕواتی" + +msgid "Upper Sorbian" +msgstr "سڕبی سەروو" + +msgid "Hungarian" +msgstr "هەنگاری" + +msgid "Armenian" +msgstr "ئەرمەنی" + +msgid "Interlingua" +msgstr "ئینتەرلینگوایی" + +msgid "Indonesian" +msgstr "ئیندۆنیزی" + +msgid "Igbo" +msgstr "ئیگبۆیی" + +msgid "Ido" +msgstr "ئیدۆیی" + +msgid "Icelandic" +msgstr "ئایسلەندی" + +msgid "Italian" +msgstr "ئیتاڵی" + +msgid "Japanese" +msgstr "یابانی" + +msgid "Georgian" +msgstr "جۆرجی" + +msgid "Kabyle" +msgstr "کابایلی" + +msgid "Kazakh" +msgstr "کازاخی" + +msgid "Khmer" +msgstr "خەمیری" + +msgid "Kannada" +msgstr "کانێدایی" + +msgid "Korean" +msgstr "کۆری" + +msgid "Kyrgyz" +msgstr "کیرگزستانی" + +msgid "Luxembourgish" +msgstr "لۆکسەمبۆرگی" + +msgid "Lithuanian" +msgstr "لیتوانی" + +msgid "Latvian" +msgstr "لاتیڤی" + +msgid "Macedonian" +msgstr "مەسەدۆنی" + +msgid "Malayalam" +msgstr "مەلایالامی" + +msgid "Mongolian" +msgstr "مەنگۆلی" + +msgid "Marathi" +msgstr "ماراسی" + +msgid "Malay" +msgstr "مالایی" + +msgid "Burmese" +msgstr "بورمایی" + +msgid "Norwegian Bokmål" +msgstr "بۆکامۆلی نەرویجی" + +msgid "Nepali" +msgstr "نیپاڵی" + +msgid "Dutch" +msgstr "هۆڵەندی" + +msgid "Norwegian Nynorsk" +msgstr "نینۆرسکی نەرویجی" + +msgid "Ossetic" +msgstr "ئۆسیتی" + +msgid "Punjabi" +msgstr "پونجابی" + +msgid "Polish" +msgstr "پۆڵۆنی" + +msgid "Portuguese" +msgstr "پورتوگالی" + +msgid "Brazilian Portuguese" +msgstr "پورتوگالیی بەڕازیلی" + +msgid "Romanian" +msgstr "ڕۆمانیایی" + +msgid "Russian" +msgstr "ڕووسی" + +msgid "Slovak" +msgstr "سلۆڤاکی" + +msgid "Slovenian" +msgstr "سلۆڤینیایی" + +msgid "Albanian" +msgstr "ئەلبانی" + +msgid "Serbian" +msgstr "سڕبی" + +msgid "Serbian Latin" +msgstr "سڕبیی لاتین" + +msgid "Swedish" +msgstr "سویدی" + +msgid "Swahili" +msgstr "سواهیلی" + +msgid "Tamil" +msgstr "تامیلی" + +msgid "Telugu" +msgstr "تێلوگویی" + +msgid "Tajik" +msgstr "تاجیکی" + +msgid "Thai" +msgstr "تایلاندی" + +msgid "Turkmen" +msgstr "تورکمانی" + +msgid "Turkish" +msgstr "تورکی" + +msgid "Tatar" +msgstr "تاتاری" + +msgid "Udmurt" +msgstr "ئودمورتی" + +msgid "Ukrainian" +msgstr "ئۆکرانی" + +msgid "Urdu" +msgstr "ئوردویی" + +msgid "Uzbek" +msgstr "ئۆزبەکی" + +msgid "Vietnamese" +msgstr "ڤێتنامی" + +msgid "Simplified Chinese" +msgstr "چینی سادەکراو" + +msgid "Traditional Chinese" +msgstr "چینی کلاسیکی" + +msgid "Messages" +msgstr "پەیامەکان" + +msgid "Site Maps" +msgstr "نەخشەکانی پێگە" + +msgid "Static Files" +msgstr "فایلە نەگۆڕەکان" + +msgid "Syndication" +msgstr "هاوبەشکردن" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "..." + +msgid "That page number is not an integer" +msgstr "ئەو ژمارەی پەڕەیە ژمارەی تەواو نییە" + +msgid "That page number is less than 1" +msgstr "ئەو ژمارەی پەڕەیە لە 1 کەمترە" + +msgid "That page contains no results" +msgstr "ئەو پەڕەیە هیچ ئەنجامێکی تێدا نییە" + +msgid "Enter a valid value." +msgstr "نرخێکی دروست لەناودابنێ." + +msgid "Enter a valid URL." +msgstr "URL ی دروست لەناودابنێ." + +msgid "Enter a valid integer." +msgstr "ژمارەیەکی تەواو لەناودابنێ" + +msgid "Enter a valid email address." +msgstr "ناونیشانێکی ئیمەیڵی دروست لەناودابنێ" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "\"سلەگ\"ێکی دروست بنوسە کە پێکهاتووە لە پیت، ژمارە، ژێرهێڵ یان هێڵ." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"\"سلەگ\"ێکی دروست بنوسە کە پێکهاتووە لە پیتی یونیکۆد، ژمارە، هێڵی ژێرەوە، " +"یان هێما." + +msgid "Enter a valid IPv4 address." +msgstr "ناونیشانێکی IPv4 ی دروست لەناودابنێ." + +msgid "Enter a valid IPv6 address." +msgstr "ناونیشانێکی IPv64 ی دروست لەناودابنێ." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "ناونیشانێکی IPv4 یان IPv6 ی دروست لەناودابنێ." + +msgid "Enter only digits separated by commas." +msgstr "تەنها ژمارە لەناودابنێ بە فاریزە جیاکرابێتەوە." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "دڵنیاببە ئەم نرخە %(limit_value)sە (ئەوە %(show_value)sە). " + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "دڵنیاببە ئەم نرخە کەمترە یاخود یەکسانە بە %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "دڵنیاببە ئەم نرخە گەورەترە یاخود یەکسانە بە %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "دڵنیابە کە ئەم بەهایە چەندانێکە لە قەبارەی هەنگاوی%(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"دڵنیابە ئەم بەهایە لانیکەم %(limit_value)d نوسەی هەیە (%(show_value)d هەیە)." +msgstr[1] "" +"دڵنیابە ئەم بەهایە لانیکەم %(limit_value)d نوسەی هەیە (%(show_value)d هەیە)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"دڵنیابە ئەم بەهایە لانی زۆر %(limit_value)d نوسەی هەیە (%(show_value)d هەیە)." +msgstr[1] "" +"دڵنیابە ئەم بەهایە لانی زۆر %(limit_value)d نوسەی هەیە (%(show_value)d هەیە)." + +msgid "Enter a number." +msgstr "ژمارەیەک بنوسە." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "دڵنیابە لەوەی بەگشتی زیاتر لە %(max)s ژمارە نیە." +msgstr[1] "دڵنیابە لەوەی بەگشتی زیاتر لە %(max)s ژمارە نیە." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "دڵنیابە لەوەی بەگشتی زیاتر لە %(max)s ژمارەی دەیی نیە." +msgstr[1] "دڵنیابە لەوەی بەگشتی زیاتر لە %(max)s ژمارەی دەیی نیە." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "دڵنیابە لەوەی زیاتر نیە لە %(max)s ژمارە پێش خاڵی ژمارەی دەیی." +msgstr[1] "دڵنیابە لەوەی زیاتر نیە لە %(max)s ژمارە پێش خاڵی ژمارەی دەیی." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"پەڕگەپاشبەندی “%(extension)s” ڕێگەپێنەدراوە. پاشبنەدە ڕێگەپێدراوەکان: " +"%(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "نوسەی بەتاڵ ڕێگەپێنەدراوە." + +msgid "and" +msgstr "و" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s لەگەڵ %(field_labels)s پێشتر تۆمارکراوە." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "سنوردارکردنی “%(name)s” پێشێلکراوە." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "بەهای %(value)r هەڵبژاردەیەکی دروست نیە." + +msgid "This field cannot be null." +msgstr "ئەم خانەیە نابێت پووچ بێت." + +msgid "This field cannot be blank." +msgstr "ئەم خانەیە نابێت بەتاڵ بێت." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s لەگەڵ %(field_label)s پێشتر تۆمارکراوە." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s دەبێت بێهاوتا بێت بۆ %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "خانە لە جۆری: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "بەهای “%(value)s” دەبێت دروست یان چەوت بێت." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "بەهای “%(value)s” دەبێت یان دروست، یان چەوت یان هیچ بێت." + +msgid "Boolean (Either True or False)" +msgstr "بولی (یان دروست یان چەوت)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "ڕیزبەند (تا %(max_length)s)" + +msgid "String (unlimited)" +msgstr "" + +msgid "Comma-separated integers" +msgstr "ژمارە تەواوەکان بە کۆما جیاکراونەتەوە" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"بەهای “%(value)s” شێوازی بەروارێکی نادروستی هەیە. دەبێت بەشێوازی YYYY-MM-DD " +"بێت." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"بەهای “%(value)s” شێوازێکی تەواوی هەیە (YYYY-MM-DD) بەڵام بەروارێکی هەڵەیە." + +msgid "Date (without time)" +msgstr "بەروار (بەبێ کات)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"بەهای “%(value)s” شێوازێکی نادروستی هەیە. دەبێت بەشێوەی YYYY-MM-DD HH:MM[:" +"ss[.uuuuuu]][TZ] بێت." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"بەهای “%(value)s” شێوازێکی دروستی هەیە (YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) " +"بەروار/کاتێکی نادروستە." + +msgid "Date (with time)" +msgstr "بەروار (لەگەڵ کات)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "بەهای “%(value)s” دەبێت ژمارەیەکی دەیی بێت." + +msgid "Decimal number" +msgstr "ژمارەی دەیی" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"بەهای “%(value)s” شێوازێکی هەڵەی هەیە. دەبێت بەشێوەی [DD] [[HH:]MM:]ss[." +"uuuuuu] format بێت." + +msgid "Duration" +msgstr "ماوە" + +msgid "Email address" +msgstr "ناونیشانی ئیمەیڵ" + +msgid "File path" +msgstr "ڕێڕەوی پەڕگە" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "بەهای “%(value)s” دەبێت ژمارەی کەرتی بێت." + +msgid "Floating point number" +msgstr "خاڵی ژمارەی کەرتی" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "بەهای “%(value)s” دەبێت ژمارەی تەواو بێت." + +msgid "Integer" +msgstr "ژمارەی تەواو" + +msgid "Big (8 byte) integer" +msgstr "(8بایت) ژمارەی تەواوی گەورە" + +msgid "Small integer" +msgstr "ژمارەی تەواوی بچوک" + +msgid "IPv4 address" +msgstr "ناونیشانی IPv4" + +msgid "IP address" +msgstr "ناونیشانی ئای پی" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "بەهای “%(value)s” دەبێت یان هیچ، یان دروست یان چەوت بێت." + +msgid "Boolean (Either True, False or None)" +msgstr "بولی (یان دروست یان چەوت یان هیچ)" + +msgid "Positive big integer" +msgstr "ژمارەی تەواوی گەورەی ئەرێنی" + +msgid "Positive integer" +msgstr "ژمارەی تەواوی ئەرێنی" + +msgid "Positive small integer" +msgstr "ژمارەی تەواوی بچوکی ئەرێنی" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "سلەگ (تا %(max_length)s)" + +msgid "Text" +msgstr "نوسین" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"بەهای “%(value)s” شێوازێکی هەڵەی هەیە. دەبێت بەشێوەی HH:MM[:ss[.uuuuuu]] بێت." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"“%(value)s” بەهاکە شێوازێکی دروستی هەیە (HH:MM[:ss[.uuuuuu]]) بەڵام کاتێکی " +"نادروستە." + +msgid "Time" +msgstr "کات" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "داتای دووانەیی خاو" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "“%(value)s ” UUIDێکی دروستی نیە." + +msgid "Universally unique identifier" +msgstr "ناسێنەرێکی بێهاوتای گشتگیر" + +msgid "File" +msgstr "پەڕگە" + +msgid "Image" +msgstr "وێنە" + +msgid "A JSON object" +msgstr "ئۆبجێکتێکی JSON" + +msgid "Value must be valid JSON." +msgstr "بەها پێویستە JSONی دروست بێت." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(model)s هاوشێوەیە لەگەڵ %(field)s %(value)r نیە." + +msgid "Foreign Key (type determined by related field)" +msgstr "کلیلی دەرەکی(جۆر بەپێی خانەی پەیوەندیدار دیاری دەکرێت)" + +msgid "One-to-one relationship" +msgstr "پەیوەندیی یەک-بۆ-یەک" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s پەیوەندی" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s پەیوەندییەکان" + +msgid "Many-to-many relationship" +msgstr "پەیوەندیی گشت-بۆ-گشت" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":؟.!" + +msgid "This field is required." +msgstr "ئەم خانەیە داواکراوە." + +msgid "Enter a whole number." +msgstr "ژمارەیەکی تەواو بنوسە." + +msgid "Enter a valid date." +msgstr "بەرواری دروست بنوسە." + +msgid "Enter a valid time." +msgstr "تکایە کاتێکی ڕاست بنووسە." + +msgid "Enter a valid date/time." +msgstr "بەروار/کاتی دروست بنوسە." + +msgid "Enter a valid duration." +msgstr "بەهای دروستی ماوە بنوسە." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "ژمارەی ڕۆژەکان دەبێت لەنێوان {min_days} و {max_days} بێت." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "هیچ پەڕگەیەک نەنێردراوە. جۆری کۆدکردنی پەڕگەکە لەسەر فۆرمەکە بپشکنە." + +msgid "No file was submitted." +msgstr "هیچ پەڕگەیەک نەنێردراوە." + +msgid "The submitted file is empty." +msgstr "پەڕگەی نێردراو بەتاڵە." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "دڵنیابە کە ناوی پەڕگە زیاتر لە %(max)d نوسەی نیە (%(length)d هەیە)." +msgstr[1] "دڵنیابە کە ناوی پەڕگە زیاتر لە %(max)d نوسەی نیە (%(length)d هەیە)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"تکایە یان پەڕگەیەک بنێرە یان چوارچێوەی پشکنین هەڵبژێرە، نەک هەردووکیان." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"وێنەی دروست هەڵبژێرە. ئەو پەڕگەی بەرزتکردۆوە یان وێنە نیە یان وێنەیەکی خراپ " +"بووە." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"هەڵبژاردەیەکی دروست دیاری بکە. %(value)s یەکێک نیە لە هەڵبژاردە بەردەستەکان." + +msgid "Enter a list of values." +msgstr "لیستی بەهاکان بنوسە." + +msgid "Enter a complete value." +msgstr "تەواوی بەهایەک بنوسە." + +msgid "Enter a valid UUID." +msgstr "بەهای دروستی UUID بنوسە." + +msgid "Enter a valid JSON." +msgstr "JSONی دروست بنوسە." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(خانەی شاراوە %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"داتاکانی فۆڕمی بەڕێوەبردن نەماوە یان دەستکاری کراون. خانە وونبووەکان: " +"%(field_names)s. لەوانەیە پێویستت بە تۆمارکردنی ڕاپۆرتی هەڵە بێت ئەگەر " +"کێشەکە بەردەوام بوو." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "تکایە لانی زۆر %(num)d فۆرم بنێرە." +msgstr[1] "تکایە لانی زۆر %(num)d فۆرم بنێرە." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "تکایە لانی کەم %(num)d فۆرم بنێرە." +msgstr[1] "تکایە لانی کەم %(num)d فۆرم بنێرە." + +msgid "Order" +msgstr "ڕیز" + +msgid "Delete" +msgstr "سڕینەوە" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "تکایە داتا دووبارەکراوەکان چاکبکەرەوە بۆ %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"تکایە ئەو داتا دووبارەکراوەکانە چاکبکەرەوە بۆ %(field)s، کە دەبێت بێهاوتابن." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"تکایە ئەو داتا دووبارەکراوەکان چاکبکەرەوە بۆ %(field_name)s کە دەبێت بێهاوتا " +"بن بۆ %(lookup)s لە%(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "تکایە بەها دووبارەکانی خوارەوە ڕاست بکەرەوە." + +msgid "The inline value did not match the parent instance." +msgstr "بەهای ناوهێڵ هاوشێوەی نمونەی باوانەکەی نیە." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "هەڵبژاردەی دروست دیاری بکە. هەڵبژاردە لە هەڵبژاردە بەردەستەکان نیە." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "“%(pk)s” بەهایەکی دروست نیە." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s نەتوانرا لە ناوچەی کاتدا لێکبدرێتەوە %(current_timezone)s؛ " +"لەوانەیە ناڕوون بێت یان لەوانەیە بوونی نەبێت." + +msgid "Clear" +msgstr "پاککردنەوە" + +msgid "Currently" +msgstr "ئێستا" + +msgid "Change" +msgstr "گۆڕین" + +msgid "Unknown" +msgstr "نەزانراو" + +msgid "Yes" +msgstr "بەڵێ" + +msgid "No" +msgstr "نەخێر" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "بەڵێ،نەخێر،لەوانەیە" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)dبایت" +msgstr[1] "%(size)d بایت" + +#, python-format +msgid "%s KB" +msgstr "%s کب" + +#, python-format +msgid "%s MB" +msgstr "%s مب" + +#, python-format +msgid "%s GB" +msgstr "%s گب" + +#, python-format +msgid "%s TB" +msgstr "%s تب" + +#, python-format +msgid "%s PB" +msgstr "%s پب" + +msgid "p.m." +msgstr "پ.ن" + +msgid "a.m." +msgstr "پ.ن" + +msgid "PM" +msgstr "د.ن" + +msgid "AM" +msgstr "پ.ن" + +msgid "midnight" +msgstr "نیوەشەو" + +msgid "noon" +msgstr "نیوەڕۆ" + +msgid "Monday" +msgstr "دووشەممە" + +msgid "Tuesday" +msgstr "سێشەممە" + +msgid "Wednesday" +msgstr "چوارشەممە" + +msgid "Thursday" +msgstr "پێنجشەممە" + +msgid "Friday" +msgstr "هەینی" + +msgid "Saturday" +msgstr "شەممە" + +msgid "Sunday" +msgstr "یەکشەممە" + +msgid "Mon" +msgstr "دوو" + +msgid "Tue" +msgstr "سێ" + +msgid "Wed" +msgstr "چوار" + +msgid "Thu" +msgstr "پێنج" + +msgid "Fri" +msgstr "هەین" + +msgid "Sat" +msgstr "شەم" + +msgid "Sun" +msgstr "یەک" + +msgid "January" +msgstr "ڕێبەندان" + +msgid "February" +msgstr "ڕەشەمە" + +msgid "March" +msgstr "نەورۆز" + +msgid "April" +msgstr "گوڵان" + +msgid "May" +msgstr "جۆزەردان" + +msgid "June" +msgstr "پوشپەڕ" + +msgid "July" +msgstr "گەلاوێژ" + +msgid "August" +msgstr "خەرمانان" + +msgid "September" +msgstr "ڕەزبەر" + +msgid "October" +msgstr "گەڵاڕێزان" + +msgid "November" +msgstr "سەرماوەرز" + +msgid "December" +msgstr "بەفرانبار" + +msgid "jan" +msgstr "‎ڕێبەندان" + +msgid "feb" +msgstr "ڕەشەمە" + +msgid "mar" +msgstr "نەورۆز" + +msgid "apr" +msgstr "گوڵان" + +msgid "may" +msgstr "‎جۆزەردان" + +msgid "jun" +msgstr "پوشپەڕ" + +msgid "jul" +msgstr "‎گەلاوێژ" + +msgid "aug" +msgstr "خەرمانان" + +msgid "sep" +msgstr "‎ڕەزبەر" + +msgid "oct" +msgstr "‎گەڵاڕێزان" + +msgid "nov" +msgstr "‎سەرماوەرز" + +msgid "dec" +msgstr "‎بەفرانبار" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "‎ڕێبەندان" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "ڕەشەمە" + +msgctxt "abbrev. month" +msgid "March" +msgstr "نەورۆز" + +msgctxt "abbrev. month" +msgid "April" +msgstr "گوڵان" + +msgctxt "abbrev. month" +msgid "May" +msgstr "جۆزەردان" + +msgctxt "abbrev. month" +msgid "June" +msgstr "پوشپەڕ" + +msgctxt "abbrev. month" +msgid "July" +msgstr "گەلاوێژ" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "خەرمانان" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "ڕەزبەر" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "‎گەڵاڕێزان" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "‎سەرماوەرز" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "‎بەفرانبار" + +msgctxt "alt. month" +msgid "January" +msgstr "ڕێبەندان" + +msgctxt "alt. month" +msgid "February" +msgstr "ڕەشەمە" + +msgctxt "alt. month" +msgid "March" +msgstr "نەورۆز" + +msgctxt "alt. month" +msgid "April" +msgstr "گوڵان" + +msgctxt "alt. month" +msgid "May" +msgstr "جۆزەردان" + +msgctxt "alt. month" +msgid "June" +msgstr "پوشپەڕ" + +msgctxt "alt. month" +msgid "July" +msgstr "گەلاوێژ" + +msgctxt "alt. month" +msgid "August" +msgstr "خەرمانان" + +msgctxt "alt. month" +msgid "September" +msgstr "ڕەزبەر" + +msgctxt "alt. month" +msgid "October" +msgstr "گەڵاڕێزان" + +msgctxt "alt. month" +msgid "November" +msgstr "سەرماوەرز" + +msgctxt "alt. month" +msgid "December" +msgstr "بەفرانبار" + +msgid "This is not a valid IPv6 address." +msgstr "ئەمە ناونیشانی IPv6 دروست نیە." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s..." + +msgid "or" +msgstr "یان" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "، " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "‫%(num)d ساڵ" +msgstr[1] "‫%(num)d ساڵ" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "‫%(num)d مانگ" +msgstr[1] "‫%(num)d مانگ" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "‫%(num)d هەفتە" +msgstr[1] "‫%(num)d هەفتە" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "‫%(num)d ڕۆژ" +msgstr[1] "‫%(num)d ڕۆژ" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "‫%(num)d کاتژمێر" +msgstr[1] "‫%(num)d کاتژمێر" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "‫%(num)d خولەک" +msgstr[1] "‫%(num)d خولەک" + +msgid "Forbidden" +msgstr "ڕێپێنەدراو" + +msgid "CSRF verification failed. Request aborted." +msgstr "پشتڕاستکردنەوەی CSRF شکستی هێنا. داواکاری هەڵوەشاوەتەوە." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"تۆ ئەم پەیامە دەبینیت چونکە ئەم ماڵپەڕە HTTPS پێویستی بە \"سەردێڕی " +"ئاماژەدەر\" هەیە کە لەلایەن وێبگەڕەکەتەوە بنێردرێت، بەڵام هیچیان نەنێردراوە. " +"ئەم سەردێڕە بۆ هۆکاری ئاسایش پێویستە، بۆ دڵنیابوون لەوەی کە وێبگەڕەکەت " +"لەلایەن لایەنی سێیەمەوە دەستی بەسەردا ناگیرێت." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"ئەگەر ڕێکخستنی شەکرۆکەی ئەم وێبگەڕەت بۆ “Referer” ناچالاککردووە، تکایە " +"چالاکی بکەرەوە، لانیکەم بۆ ئەم ماڵپەڕە، یان بۆ پەیوەندییەکانی HTTPS، یاخود " +"بۆ داواکانی \"Same-origin\"." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"ئەگەر تۆ تاگی بەکاردەهێنێت " +"یان سەرپەڕەی “Referrer-Policy: no-referrer” لەخۆدەگرێت، تکایە بیانسڕەوە. " +"پاراستنی CSRFەکە پێویستی بە سەرپەڕەی “Referer”هەیە بۆ ئەنجامدانی پشکنینی " +"گەڕاندنەوەی توندوتۆڵ. ئەگەر خەمی تایبەتمەندیت هەیە، بەدیلەکانی وەکو بۆ بەستنەوەی ماڵپەڕەکانی لایەنی سێیەم." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"تۆ ئەم پەیامە دەبینیت چونکە ئەم ماڵپەڕە پێویستی بە شەکرۆکەی CSRF هەیە لە " +"کاتی ناردنی فۆڕمەکاندا. ئەم شەکرۆکەیە بۆ هۆکاری ئاسایش پێویستە، بۆ دڵنیابوون " +"لەوەی کە وێبگەڕەکەت لەلایەن لایەنی سێیەمەوە دەستی بەسەردا ناگیرێت." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"ئەگەر ڕێکخستنی شەکرۆکەی ئەم وێبگەڕەت ناچالاککردووە، تکایە چالاکی بکەرەوە، " +"لانیکەم بۆ ئەم ماڵپەڕە، یان بۆ داواکانی \"Same-origin\"" + +msgid "More information is available with DEBUG=True." +msgstr "زانیاریی زیاتر بەردەستە لەگەڵ DEBUG=True." + +msgid "No year specified" +msgstr "هیچ ساڵێک دیاری نەکراوە" + +msgid "Date out of range" +msgstr "بەروار لە دەرەوەی بواردایە" + +msgid "No month specified" +msgstr "هیچ مانگێک دیاری نەکراوە" + +msgid "No day specified" +msgstr "هیچ ڕۆژێک دیاری نەکراوە" + +msgid "No week specified" +msgstr "هیچ حەفتەیەک دیاری نەکراوە" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "هیچ %(verbose_name_plural)s بەردەست نییە" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"لەداهاتوودا %(verbose_name_plural)s بەردەست نیە چونکە %(class_name)s." +"allow_future چەوتە." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "ڕیزبەندی بەروار نادروستە “%(datestr)s” شێوازی “%(format)s” پێ بدە" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "هیچ %(verbose_name)s هاوتای داواکارییەکە نیە" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "لاپەڕە “کۆتا” نییە، هەروەها ناتوانرێت بگۆڕدرێت بۆ ژمارەی تەواو." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "لاپەڕەی نادروستە (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "لیستی بەتاڵ و “%(class_name)s.allow_empty” چەوتە." + +msgid "Directory indexes are not allowed here." +msgstr "لێرەدا نوانەی بوخچەکان ڕێگەپێدراو نیە." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "“%(path)s” بوونی نیە" + +#, python-format +msgid "Index of %(directory)s" +msgstr "نوانەی %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "دامەزراندن بەسەرکەوتوویی کاریکرد! پیرۆزە!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"سەیری تێبینیەکانی بڵاوکردنەوە بکە بۆ جانگۆی " +"%(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"ئەم لاپەڕەیە دەبینیت چونکە DEBUG=True لەناو پەڕگەی ڕێکخستنەکانتە و بۆ هیچ URLێک " +"ڕێکنەخراوە." + +msgid "Django Documentation" +msgstr "بەڵگەنامەکردنی جانگۆ" + +msgid "Topics, references, & how-to’s" +msgstr "بابەتەکان, سەرچاوەکان, & چۆنێتی" + +msgid "Tutorial: A Polling App" +msgstr "فێرکاریی: ئاپێکی ڕاپرسی" + +msgid "Get started with Django" +msgstr "دەستپێبکە لەگەڵ جانگۆ" + +msgid "Django Community" +msgstr "کۆمەڵگەی جانگۆ" + +msgid "Connect, get help, or contribute" +msgstr "پەیوەندی بکە، یارمەتی وەربگرە، یان بەشداری بکە" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ckb/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ckb/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ckb/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ckb/formats.py new file mode 100644 index 0000000..162c840 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ckb/formats.py @@ -0,0 +1,21 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j F Y" +TIME_FORMAT = "G:i" +DATETIME_FORMAT = "j F Y، کاتژمێر G:i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "Y/n/j" +SHORT_DATETIME_FORMAT = "Y/n/j،‏ G:i" +FIRST_DAY_OF_WEEK = 6 + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = "." +THOUSAND_SEPARATOR = "," +# NUMBER_GROUPING = diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/cs/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/cs/LC_MESSAGES/django.mo new file mode 100644 index 0000000..66e08fe Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/cs/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/cs/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/cs/LC_MESSAGES/django.po new file mode 100644 index 0000000..bf85e0c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/cs/LC_MESSAGES/django.po @@ -0,0 +1,1362 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Claude Paroz , 2020 +# Jannis Leidel , 2011 +# Jan Papež , 2012 +# trendspotter , 2022 +# Jirka Vejrazka , 2011 +# trendspotter , 2020 +# Tomáš Ehrlich , 2015 +# Vláďa Macek , 2012-2014 +# Vláďa Macek , 2015-2022 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-05-17 05:23-0500\n" +"PO-Revision-Date: 2022-07-25 06:49+0000\n" +"Last-Translator: trendspotter \n" +"Language-Team: Czech (http://www.transifex.com/django/django/language/cs/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cs\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n " +"<= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n" + +msgid "Afrikaans" +msgstr "afrikánsky" + +msgid "Arabic" +msgstr "arabsky" + +msgid "Algerian Arabic" +msgstr "alžírskou arabštinou" + +msgid "Asturian" +msgstr "asturštinou" + +msgid "Azerbaijani" +msgstr "ázerbájdžánsky" + +msgid "Bulgarian" +msgstr "bulharsky" + +msgid "Belarusian" +msgstr "bělorusky" + +msgid "Bengali" +msgstr "bengálsky" + +msgid "Breton" +msgstr "bretonsky" + +msgid "Bosnian" +msgstr "bosensky" + +msgid "Catalan" +msgstr "katalánsky" + +msgid "Czech" +msgstr "česky" + +msgid "Welsh" +msgstr "velšsky" + +msgid "Danish" +msgstr "dánsky" + +msgid "German" +msgstr "německy" + +msgid "Lower Sorbian" +msgstr "dolnolužickou srbštinou" + +msgid "Greek" +msgstr "řecky" + +msgid "English" +msgstr "anglicky" + +msgid "Australian English" +msgstr "australskou angličtinou" + +msgid "British English" +msgstr "britskou angličtinou" + +msgid "Esperanto" +msgstr "esperantsky" + +msgid "Spanish" +msgstr "španělsky" + +msgid "Argentinian Spanish" +msgstr "argentinskou španělštinou" + +msgid "Colombian Spanish" +msgstr "kolumbijskou španělštinou" + +msgid "Mexican Spanish" +msgstr "mexickou španělštinou" + +msgid "Nicaraguan Spanish" +msgstr "nikaragujskou španělštinou" + +msgid "Venezuelan Spanish" +msgstr "venezuelskou španělštinou" + +msgid "Estonian" +msgstr "estonsky" + +msgid "Basque" +msgstr "baskicky" + +msgid "Persian" +msgstr "persky" + +msgid "Finnish" +msgstr "finsky" + +msgid "French" +msgstr "francouzsky" + +msgid "Frisian" +msgstr "frísky" + +msgid "Irish" +msgstr "irsky" + +msgid "Scottish Gaelic" +msgstr "skotskou keltštinou" + +msgid "Galician" +msgstr "galicijsky" + +msgid "Hebrew" +msgstr "hebrejsky" + +msgid "Hindi" +msgstr "hindsky" + +msgid "Croatian" +msgstr "chorvatsky" + +msgid "Upper Sorbian" +msgstr "hornolužickou srbštinou" + +msgid "Hungarian" +msgstr "maďarsky" + +msgid "Armenian" +msgstr "arménštinou" + +msgid "Interlingua" +msgstr "interlingua" + +msgid "Indonesian" +msgstr "indonésky" + +msgid "Igbo" +msgstr "igboštinou" + +msgid "Ido" +msgstr "idem" + +msgid "Icelandic" +msgstr "islandsky" + +msgid "Italian" +msgstr "italsky" + +msgid "Japanese" +msgstr "japonsky" + +msgid "Georgian" +msgstr "gruzínštinou" + +msgid "Kabyle" +msgstr "kabylštinou" + +msgid "Kazakh" +msgstr "kazašsky" + +msgid "Khmer" +msgstr "khmersky" + +msgid "Kannada" +msgstr "kannadsky" + +msgid "Korean" +msgstr "korejsky" + +msgid "Kyrgyz" +msgstr "kyrgyzštinou" + +msgid "Luxembourgish" +msgstr "lucembursky" + +msgid "Lithuanian" +msgstr "litevsky" + +msgid "Latvian" +msgstr "lotyšsky" + +msgid "Macedonian" +msgstr "makedonsky" + +msgid "Malayalam" +msgstr "malajálamsky" + +msgid "Mongolian" +msgstr "mongolsky" + +msgid "Marathi" +msgstr "marathi" + +msgid "Malay" +msgstr "malajštinou" + +msgid "Burmese" +msgstr "barmštinou" + +msgid "Norwegian Bokmål" +msgstr "bokmål norštinou" + +msgid "Nepali" +msgstr "nepálsky" + +msgid "Dutch" +msgstr "nizozemsky" + +msgid "Norwegian Nynorsk" +msgstr "norsky (Nynorsk)" + +msgid "Ossetic" +msgstr "osetštinou" + +msgid "Punjabi" +msgstr "paňdžábsky" + +msgid "Polish" +msgstr "polsky" + +msgid "Portuguese" +msgstr "portugalsky" + +msgid "Brazilian Portuguese" +msgstr "brazilskou portugalštinou" + +msgid "Romanian" +msgstr "rumunsky" + +msgid "Russian" +msgstr "rusky" + +msgid "Slovak" +msgstr "slovensky" + +msgid "Slovenian" +msgstr "slovinsky" + +msgid "Albanian" +msgstr "albánsky" + +msgid "Serbian" +msgstr "srbsky" + +msgid "Serbian Latin" +msgstr "srbsky (latinkou)" + +msgid "Swedish" +msgstr "švédsky" + +msgid "Swahili" +msgstr "svahilsky" + +msgid "Tamil" +msgstr "tamilsky" + +msgid "Telugu" +msgstr "telužsky" + +msgid "Tajik" +msgstr "Tádžik" + +msgid "Thai" +msgstr "thajsky" + +msgid "Turkmen" +msgstr "turkmenštinou" + +msgid "Turkish" +msgstr "turecky" + +msgid "Tatar" +msgstr "tatarsky" + +msgid "Udmurt" +msgstr "udmurtsky" + +msgid "Ukrainian" +msgstr "ukrajinsky" + +msgid "Urdu" +msgstr "urdsky" + +msgid "Uzbek" +msgstr "uzbecky" + +msgid "Vietnamese" +msgstr "vietnamsky" + +msgid "Simplified Chinese" +msgstr "čínsky (zjednodušeně)" + +msgid "Traditional Chinese" +msgstr "čínsky (tradičně)" + +msgid "Messages" +msgstr "Zprávy" + +msgid "Site Maps" +msgstr "Mapy webu" + +msgid "Static Files" +msgstr "Statické soubory" + +msgid "Syndication" +msgstr "Syndikace" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Číslo stránky není celé číslo." + +msgid "That page number is less than 1" +msgstr "Číslo stránky je menší než 1" + +msgid "That page contains no results" +msgstr "Stránka je bez výsledků" + +msgid "Enter a valid value." +msgstr "Zadejte platnou hodnotu." + +msgid "Enter a valid URL." +msgstr "Zadejte platnou adresu URL." + +msgid "Enter a valid integer." +msgstr "Zadejte platné celé číslo." + +msgid "Enter a valid email address." +msgstr "Zadejte platnou e-mailovou adresu." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Vložte platný identifikátor složený pouze z písmen, čísel, podtržítek a " +"pomlček." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Zadejte platný identifikátor složený pouze z písmen, čísel, podtržítek a " +"pomlček typu Unicode." + +msgid "Enter a valid IPv4 address." +msgstr "Zadejte platnou adresu typu IPv4." + +msgid "Enter a valid IPv6 address." +msgstr "Zadejte platnou adresu typu IPv6." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Zadejte platnou adresu typu IPv4 nebo IPv6." + +msgid "Enter only digits separated by commas." +msgstr "Zadejte pouze číslice oddělené čárkami." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Hodnota musí být %(limit_value)s (nyní je %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Hodnota musí být menší nebo rovna %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Hodnota musí být větší nebo rovna %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" +"Ujistěte se, že tato hodnota je násobkem velikosti kroku %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Tato hodnota má mít nejméně %(limit_value)d znak (nyní má %(show_value)d)." +msgstr[1] "" +"Tato hodnota má mít nejméně %(limit_value)d znaky (nyní má %(show_value)d)." +msgstr[2] "" +"Tato hodnota má mít nejméně %(limit_value)d znaku (nyní má %(show_value)d)." +msgstr[3] "" +"Tato hodnota má mít nejméně %(limit_value)d znaků (nyní má %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Tato hodnota má mít nejvýše %(limit_value)d znak (nyní má %(show_value)d)." +msgstr[1] "" +"Tato hodnota má mít nejvýše %(limit_value)d znaky (nyní má %(show_value)d)." +msgstr[2] "" +"Tato hodnota má mít nejvýše %(limit_value)d znaků (nyní má %(show_value)d)." +msgstr[3] "" +"Tato hodnota má mít nejvýše %(limit_value)d znaků (nyní má %(show_value)d)." + +msgid "Enter a number." +msgstr "Zadejte číslo." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Ujistěte se, že pole neobsahuje celkem více než %(max)s číslici." +msgstr[1] "Ujistěte se, že pole neobsahuje celkem více než %(max)s číslice." +msgstr[2] "Ujistěte se, že pole neobsahuje celkem více než %(max)s číslic." +msgstr[3] "Ujistěte se, že pole neobsahuje celkem více než %(max)s číslic." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Ujistěte se, že pole neobsahuje více než %(max)s desetinné místo." +msgstr[1] "Ujistěte se, že pole neobsahuje více než %(max)s desetinná místa." +msgstr[2] "Ujistěte se, že pole neobsahuje více než %(max)s desetinných míst." +msgstr[3] "Ujistěte se, že pole neobsahuje více než %(max)s desetinných míst." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Ujistěte se, že hodnota neobsahuje více než %(max)s místo před desetinnou " +"čárkou (tečkou)." +msgstr[1] "" +"Ujistěte se, že hodnota neobsahuje více než %(max)s místa před desetinnou " +"čárkou (tečkou)." +msgstr[2] "" +"Ujistěte se, že hodnota neobsahuje více než %(max)s míst před desetinnou " +"čárkou (tečkou)." +msgstr[3] "" +"Ujistěte se, že hodnota neobsahuje více než %(max)s míst před desetinnou " +"čárkou (tečkou)." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Přípona souboru \"%(extension)s\" není povolena. Povolené jsou tyto: " +"%(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Nulové znaky nejsou povoleny." + +msgid "and" +msgstr "a" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" +"Položka %(model_name)s s touto kombinací hodnot v polích %(field_labels)s " +"již existuje." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Omezení \"%(name)s\" je porušeno." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Hodnota %(value)r není platná možnost." + +msgid "This field cannot be null." +msgstr "Pole nemůže být null." + +msgid "This field cannot be blank." +msgstr "Pole nemůže být prázdné." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "" +"Položka %(model_name)s s touto hodnotou v poli %(field_label)s již existuje." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"Pole %(field_label)s musí být unikátní testem %(lookup_type)s pro pole " +"%(date_field_label)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Pole typu: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "Hodnota \"%(value)s\" musí být buď True nebo False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "Hodnota \"%(value)s\" musí být buď True, False nebo None." + +msgid "Boolean (Either True or False)" +msgstr "Pravdivost (buď Ano (True), nebo Ne (False))" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Řetězec (max. %(max_length)s znaků)" + +msgid "Comma-separated integers" +msgstr "Celá čísla oddělená čárkou" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "Hodnota \"%(value)s\" není platné datum. Musí být ve tvaru RRRR-MM-DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"Ačkoli hodnota \"%(value)s\" je ve správném tvaru (RRRR-MM-DD), jde o " +"neplatné datum." + +msgid "Date (without time)" +msgstr "Datum (bez času)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"Hodnota \"%(value)s\" je v neplatném tvaru, který má být RRRR-MM-DD HH:MM[:" +"SS[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"Ačkoli hodnota \"%(value)s\" je ve správném tvaru (RRRR-MM-DD HH:MM[:SS[." +"uuuuuu]][TZ]), jde o neplatné datum a čas." + +msgid "Date (with time)" +msgstr "Datum (s časem)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "Hodnota \"%(value)s\" musí být desítkové číslo." + +msgid "Decimal number" +msgstr "Desetinné číslo" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"Hodnota \"%(value)s\" je v neplatném tvaru, který má být [DD] [HH:[MM:]]ss[." +"uuuuuu]." + +msgid "Duration" +msgstr "Doba trvání" + +msgid "Email address" +msgstr "E-mailová adresa" + +msgid "File path" +msgstr "Cesta k souboru" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "Hodnota \"%(value)s\" musí být reálné číslo." + +msgid "Floating point number" +msgstr "Číslo s pohyblivou řádovou čárkou" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "Hodnota \"%(value)s\" musí být celé číslo." + +msgid "Integer" +msgstr "Celé číslo" + +msgid "Big (8 byte) integer" +msgstr "Velké číslo (8 bajtů)" + +msgid "Small integer" +msgstr "Malé celé číslo" + +msgid "IPv4 address" +msgstr "Adresa IPv4" + +msgid "IP address" +msgstr "Adresa IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "Hodnota \"%(value)s\" musí být buď None, True nebo False." + +msgid "Boolean (Either True, False or None)" +msgstr "Pravdivost (buď Ano (True), Ne (False) nebo Nic (None))" + +msgid "Positive big integer" +msgstr "Velké kladné celé číslo" + +msgid "Positive integer" +msgstr "Kladné celé číslo" + +msgid "Positive small integer" +msgstr "Kladné malé celé číslo" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Identifikátor (nejvýše %(max_length)s znaků)" + +msgid "Text" +msgstr "Text" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"Hodnota \"%(value)s\" je v neplatném tvaru, který má být HH:MM[:ss[.uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"Ačkoli hodnota \"%(value)s\" je ve správném tvaru (HH:MM[:ss[.uuuuuu]]), jde " +"o neplatný čas." + +msgid "Time" +msgstr "Čas" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Přímá binární data" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "\"%(value)s\" není platná hodnota typu UUID." + +msgid "Universally unique identifier" +msgstr "Všeobecně jedinečný identifikátor" + +msgid "File" +msgstr "Soubor" + +msgid "Image" +msgstr "Obrázek" + +msgid "A JSON object" +msgstr "Objekt typu JSON" + +msgid "Value must be valid JSON." +msgstr "Hodnota musí být platná struktura typu JSON." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" +"Položka typu %(model)s s hodnotou %(field)s rovnou %(value)r neexistuje." + +msgid "Foreign Key (type determined by related field)" +msgstr "Cizí klíč (typ určen pomocí souvisejícího pole)" + +msgid "One-to-one relationship" +msgstr "Vazba jedna-jedna" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "Vazba z %(from)s do %(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "Vazby z %(from)s do %(to)s" + +msgid "Many-to-many relationship" +msgstr "Vazba mnoho-mnoho" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?!" + +msgid "This field is required." +msgstr "Toto pole je třeba vyplnit." + +msgid "Enter a whole number." +msgstr "Zadejte celé číslo." + +msgid "Enter a valid date." +msgstr "Zadejte platné datum." + +msgid "Enter a valid time." +msgstr "Zadejte platný čas." + +msgid "Enter a valid date/time." +msgstr "Zadejte platné datum a čas." + +msgid "Enter a valid duration." +msgstr "Zadejte platnou délku trvání." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Počet dní musí být mezi {min_days} a {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" +"Soubor nebyl odeslán. Zkontrolujte parametr \"encoding type\" formuláře." + +msgid "No file was submitted." +msgstr "Žádný soubor nebyl odeslán." + +msgid "The submitted file is empty." +msgstr "Odeslaný soubor je prázdný." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Tento název souboru má mít nejvýše %(max)d znak (nyní má %(length)d)." +msgstr[1] "" +"Tento název souboru má mít nejvýše %(max)d znaky (nyní má %(length)d)." +msgstr[2] "" +"Tento název souboru má mít nejvýše %(max)d znaku (nyní má %(length)d)." +msgstr[3] "" +"Tento název souboru má mít nejvýše %(max)d znaků (nyní má %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Musíte vybrat cestu k souboru nebo vymazat výběr, ne obojí." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Nahrajte platný obrázek. Odeslaný soubor buď nebyl obrázek nebo byl poškozen." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Vyberte platnou možnost, \"%(value)s\" není k dispozici." + +msgid "Enter a list of values." +msgstr "Zadejte seznam hodnot." + +msgid "Enter a complete value." +msgstr "Zadejte úplnou hodnotu." + +msgid "Enter a valid UUID." +msgstr "Zadejte platné UUID." + +msgid "Enter a valid JSON." +msgstr "Zadejte platnou strukturu typu JSON." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Skryté pole %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"Data objektu ManagementForm chybí nebo s nimi bylo nedovoleně manipulováno. " +"Chybějící pole: %(field_names)s. Pokud problém přetrvává, budete možná muset " +"problém ohlásit." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +msgid "Order" +msgstr "Pořadí" + +msgid "Delete" +msgstr "Odstranit" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Opravte duplicitní data v poli %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Opravte duplicitní data v poli %(field)s, které musí být unikátní." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Opravte duplicitní data v poli %(field_name)s, které musí být unikátní " +"testem %(lookup)s pole %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Odstraňte duplicitní hodnoty níže." + +msgid "The inline value did not match the parent instance." +msgstr "Hodnota typu inline neodpovídá rodičovské položce." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Vyberte platnou možnost. Tato není k dispozici." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "\"%(pk)s\" není platná hodnota." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"Hodnotu %(datetime)s nelze interpretovat v časové zóně %(current_timezone)s; " +"může být nejednoznačná nebo nemusí existovat." + +msgid "Clear" +msgstr "Zrušit" + +msgid "Currently" +msgstr "Aktuálně" + +msgid "Change" +msgstr "Změnit" + +msgid "Unknown" +msgstr "Neznámé" + +msgid "Yes" +msgstr "Ano" + +msgid "No" +msgstr "Ne" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "ano,ne,možná" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d bajt" +msgstr[1] "%(size)d bajty" +msgstr[2] "%(size)d bajtů" +msgstr[3] "%(size)d bajtů" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "odp." + +msgid "a.m." +msgstr "dop." + +msgid "PM" +msgstr "odp." + +msgid "AM" +msgstr "dop." + +msgid "midnight" +msgstr "půlnoc" + +msgid "noon" +msgstr "poledne" + +msgid "Monday" +msgstr "pondělí" + +msgid "Tuesday" +msgstr "úterý" + +msgid "Wednesday" +msgstr "středa" + +msgid "Thursday" +msgstr "čtvrtek" + +msgid "Friday" +msgstr "pátek" + +msgid "Saturday" +msgstr "sobota" + +msgid "Sunday" +msgstr "neděle" + +msgid "Mon" +msgstr "po" + +msgid "Tue" +msgstr "út" + +msgid "Wed" +msgstr "st" + +msgid "Thu" +msgstr "čt" + +msgid "Fri" +msgstr "pá" + +msgid "Sat" +msgstr "so" + +msgid "Sun" +msgstr "ne" + +msgid "January" +msgstr "leden" + +msgid "February" +msgstr "únor" + +msgid "March" +msgstr "březen" + +msgid "April" +msgstr "duben" + +msgid "May" +msgstr "květen" + +msgid "June" +msgstr "červen" + +msgid "July" +msgstr "červenec" + +msgid "August" +msgstr "srpen" + +msgid "September" +msgstr "září" + +msgid "October" +msgstr "říjen" + +msgid "November" +msgstr "listopad" + +msgid "December" +msgstr "prosinec" + +msgid "jan" +msgstr "led" + +msgid "feb" +msgstr "úno" + +msgid "mar" +msgstr "bře" + +msgid "apr" +msgstr "dub" + +msgid "may" +msgstr "kvě" + +msgid "jun" +msgstr "čen" + +msgid "jul" +msgstr "čec" + +msgid "aug" +msgstr "srp" + +msgid "sep" +msgstr "zář" + +msgid "oct" +msgstr "říj" + +msgid "nov" +msgstr "lis" + +msgid "dec" +msgstr "pro" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Led." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Úno." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Bře." + +msgctxt "abbrev. month" +msgid "April" +msgstr "Dub." + +msgctxt "abbrev. month" +msgid "May" +msgstr "Kvě." + +msgctxt "abbrev. month" +msgid "June" +msgstr "Čer." + +msgctxt "abbrev. month" +msgid "July" +msgstr "Čec." + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Srp." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Zář." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Říj." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Lis." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Pro." + +msgctxt "alt. month" +msgid "January" +msgstr "ledna" + +msgctxt "alt. month" +msgid "February" +msgstr "února" + +msgctxt "alt. month" +msgid "March" +msgstr "března" + +msgctxt "alt. month" +msgid "April" +msgstr "dubna" + +msgctxt "alt. month" +msgid "May" +msgstr "května" + +msgctxt "alt. month" +msgid "June" +msgstr "června" + +msgctxt "alt. month" +msgid "July" +msgstr "července" + +msgctxt "alt. month" +msgid "August" +msgstr "srpna" + +msgctxt "alt. month" +msgid "September" +msgstr "září" + +msgctxt "alt. month" +msgid "October" +msgstr "října" + +msgctxt "alt. month" +msgid "November" +msgstr "listopadu" + +msgctxt "alt. month" +msgid "December" +msgstr "prosince" + +msgid "This is not a valid IPv6 address." +msgstr "Toto není platná adresa typu IPv6." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "nebo" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d rok" +msgstr[1] "%(num)d roky" +msgstr[2] "%(num)d roku" +msgstr[3] "%(num)d let" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d měsíc" +msgstr[1] "%(num)d měsíce" +msgstr[2] "%(num)d měsíců" +msgstr[3] "%(num)d měsíců" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d týden" +msgstr[1] "%(num)d týdny" +msgstr[2] "%(num)d týdne" +msgstr[3] "%(num)d týdnů" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d den" +msgstr[1] "%(num)d dny" +msgstr[2] "%(num)d dní" +msgstr[3] "%(num)d dní" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hodina" +msgstr[1] "%(num)d hodiny" +msgstr[2] "%(num)d hodiny" +msgstr[3] "%(num)d hodin" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuta" +msgstr[1] "%(num)d minuty" +msgstr[2] "%(num)d minut" +msgstr[3] "%(num)d minut" + +msgid "Forbidden" +msgstr "Nepřístupné (Forbidden)" + +msgid "CSRF verification failed. Request aborted." +msgstr "Selhalo ověření typu CSRF. Požadavek byl zadržen." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Tuto zprávu vidíte, protože tento web na protokolu HTTPS vyžaduje, aby váš " +"prohlížeč zaslal v požadavku záhlaví \"Referer\", k čemuž nedošlo. Záhlaví " +"je požadováno z bezpečnostních důvodů pro kontrolu toho, že prohlížeče se " +"nezmocnila třetí strana." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Pokud má váš prohlížeč záhlaví \"Referer\" vypnuté, žádáme vás o jeho " +"zapnutí, alespoň pro tento web nebo pro spojení typu HTTPS nebo pro " +"požadavky typu \"stejný původ\" (same origin)." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Pokud používáte značku nebo " +"záhlaví \"Referrer-Policy: no-referrer\", odeberte je. Ochrana typu CSRF " +"vyžaduje, aby záhlaví zajišťovalo striktní hlídání refereru. Pokud je pro " +"vás soukromí důležité, použijte k odkazům na cizí weby alternativní možnosti " +"jako například ." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Tato zpráva se zobrazuje, protože tento web při odesílání formulářů požaduje " +"v souboru cookie údaj CSRF, a to z bezpečnostních důvodů, aby se zajistilo, " +"že se vašeho prohlížeče nezmocnil někdo další." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Pokud má váš prohlížeč soubory cookie vypnuté, žádáme vás o jejich zapnutí, " +"alespoň pro tento web nebo pro požadavky typu \"stejný původ\" (same origin)." + +msgid "More information is available with DEBUG=True." +msgstr "V případě zapnutí volby DEBUG=True bude k dispozici více informací." + +msgid "No year specified" +msgstr "Nebyl specifikován rok" + +msgid "Date out of range" +msgstr "Datum je mimo rozsah" + +msgid "No month specified" +msgstr "Nebyl specifikován měsíc" + +msgid "No day specified" +msgstr "Nebyl specifikován den" + +msgid "No week specified" +msgstr "Nebyl specifikován týden" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "%(verbose_name_plural)s nejsou k dispozici" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"%(verbose_name_plural)s s budoucím datem nejsou k dipozici protoze " +"%(class_name)s.allow_future je False" + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Datum \"%(datestr)s\" neodpovídá formátu \"%(format)s\"" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Nepodařilo se nalézt žádný objekt %(verbose_name)s" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" +"Požadavek na stránku nemohl být konvertován na celé číslo, ani není \"last\"." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Neplatná stránka (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "List je prázdný a \"%(class_name)s.allow_empty\" je nastaveno na False" + +msgid "Directory indexes are not allowed here." +msgstr "Indexy adresářů zde nejsou povoleny." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "Cesta \"%(path)s\" neexistuje" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Index adresáře %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Instalace proběhla úspěšně, gratulujeme!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Zobrazit poznámky k vydání frameworku Django " +"%(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" +"Tuto zprávu vidíte, protože máte v nastavení Djanga zapnutý vývojový režim " +"DEBUG=True a zatím nemáte " +"nastavena žádná URL." + +msgid "Django Documentation" +msgstr "Dokumentace frameworku Django" + +msgid "Topics, references, & how-to’s" +msgstr "Témata, odkazy & how-to" + +msgid "Tutorial: A Polling App" +msgstr "Tutoriál: Hlasovací aplikace" + +msgid "Get started with Django" +msgstr "Začínáme s frameworkem Django" + +msgid "Django Community" +msgstr "Komunita kolem frameworku Django" + +msgid "Connect, get help, or contribute" +msgstr "Propojte se, získejte pomoc, podílejte se" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/cs/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/cs/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/cs/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/cs/formats.py new file mode 100644 index 0000000..e4a7ab9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/cs/formats.py @@ -0,0 +1,43 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j. E Y" +TIME_FORMAT = "G:i" +DATETIME_FORMAT = "j. E Y G:i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j. F" +SHORT_DATE_FORMAT = "d.m.Y" +SHORT_DATETIME_FORMAT = "d.m.Y G:i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d.%m.%Y", # '05.01.2006' + "%d.%m.%y", # '05.01.06' + "%d. %m. %Y", # '5. 1. 2006' + "%d. %m. %y", # '5. 1. 06' + # "%d. %B %Y", # '25. October 2006' + # "%d. %b. %Y", # '25. Oct. 2006' +] +# Kept ISO formats as one is in first position +TIME_INPUT_FORMATS = [ + "%H:%M:%S", # '04:30:59' + "%H.%M", # '04.30' + "%H:%M", # '04:30' +] +DATETIME_INPUT_FORMATS = [ + "%d.%m.%Y %H:%M:%S", # '05.01.2006 04:30:59' + "%d.%m.%Y %H:%M:%S.%f", # '05.01.2006 04:30:59.000200' + "%d.%m.%Y %H.%M", # '05.01.2006 04.30' + "%d.%m.%Y %H:%M", # '05.01.2006 04:30' + "%d. %m. %Y %H:%M:%S", # '05. 01. 2006 04:30:59' + "%d. %m. %Y %H:%M:%S.%f", # '05. 01. 2006 04:30:59.000200' + "%d. %m. %Y %H.%M", # '05. 01. 2006 04.30' + "%d. %m. %Y %H:%M", # '05. 01. 2006 04:30' + "%Y-%m-%d %H.%M", # '2006-01-05 04.30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "\xa0" # non-breaking space +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/cy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/cy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ea5b45c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/cy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/cy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/cy/LC_MESSAGES/django.po new file mode 100644 index 0000000..16383ce --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/cy/LC_MESSAGES/django.po @@ -0,0 +1,1278 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Maredudd ap Gwyndaf , 2012,2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Welsh (http://www.transifex.com/django/django/language/cy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cy\n" +"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != " +"11) ? 2 : 3;\n" + +msgid "Afrikaans" +msgstr "Affricaneg" + +msgid "Arabic" +msgstr "Arabeg" + +msgid "Asturian" +msgstr "Astwrieg" + +msgid "Azerbaijani" +msgstr "Azerbaijanaidd" + +msgid "Bulgarian" +msgstr "Bwlgareg" + +msgid "Belarusian" +msgstr "Belarwseg" + +msgid "Bengali" +msgstr "Bengaleg" + +msgid "Breton" +msgstr "Llydaweg" + +msgid "Bosnian" +msgstr "Bosnieg" + +msgid "Catalan" +msgstr "Catalaneg" + +msgid "Czech" +msgstr "Tsieceg" + +msgid "Welsh" +msgstr "Cymraeg" + +msgid "Danish" +msgstr "Daneg" + +msgid "German" +msgstr "Almaeneg" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "Groegedd" + +msgid "English" +msgstr "Saesneg" + +msgid "Australian English" +msgstr "Saesneg Awstralia" + +msgid "British English" +msgstr "Saesneg Prydain" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Sbaeneg" + +msgid "Argentinian Spanish" +msgstr "Sbaeneg Ariannin" + +msgid "Colombian Spanish" +msgstr "" + +msgid "Mexican Spanish" +msgstr "Sbaeneg Mecsico" + +msgid "Nicaraguan Spanish" +msgstr "Sbaeneg Nicaragwa" + +msgid "Venezuelan Spanish" +msgstr "Sbaeneg Feneswela" + +msgid "Estonian" +msgstr "Estoneg" + +msgid "Basque" +msgstr "Basgeg" + +msgid "Persian" +msgstr "Persieg" + +msgid "Finnish" +msgstr "Ffinneg" + +msgid "French" +msgstr "Ffrangeg" + +msgid "Frisian" +msgstr "Ffrisieg" + +msgid "Irish" +msgstr "Gwyddeleg" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "Galisieg" + +msgid "Hebrew" +msgstr "Hebraeg" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Croasieg" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "Hwngareg" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indoneseg" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Islandeg" + +msgid "Italian" +msgstr "Eidaleg" + +msgid "Japanese" +msgstr "Siapanëeg" + +msgid "Georgian" +msgstr "Georgeg" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "Casacstanaidd" + +msgid "Khmer" +msgstr "Chmereg" + +msgid "Kannada" +msgstr "Canadeg" + +msgid "Korean" +msgstr "Corëeg" + +msgid "Luxembourgish" +msgstr "Lwcsembergeg" + +msgid "Lithuanian" +msgstr "Lithwaneg" + +msgid "Latvian" +msgstr "Latfieg" + +msgid "Macedonian" +msgstr "Macedoneg" + +msgid "Malayalam" +msgstr "Malaialam" + +msgid "Mongolian" +msgstr "Mongoleg" + +msgid "Marathi" +msgstr "Marathi" + +msgid "Burmese" +msgstr "Byrmaneg" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "Nepaleg" + +msgid "Dutch" +msgstr "Iseldireg" + +msgid "Norwegian Nynorsk" +msgstr "Ninorsk Norwyeg" + +msgid "Ossetic" +msgstr "Osetieg" + +msgid "Punjabi" +msgstr "Pwnjabi" + +msgid "Polish" +msgstr "Pwyleg" + +msgid "Portuguese" +msgstr "Portiwgaleg" + +msgid "Brazilian Portuguese" +msgstr "Portiwgaleg Brasil" + +msgid "Romanian" +msgstr "Romaneg" + +msgid "Russian" +msgstr "Rwsieg" + +msgid "Slovak" +msgstr "Slofaceg" + +msgid "Slovenian" +msgstr "Slofeneg" + +msgid "Albanian" +msgstr "Albaneg" + +msgid "Serbian" +msgstr "Serbeg" + +msgid "Serbian Latin" +msgstr "Lladin Serbiaidd" + +msgid "Swedish" +msgstr "Swedeg" + +msgid "Swahili" +msgstr "Swahili" + +msgid "Tamil" +msgstr "Tamil" + +msgid "Telugu" +msgstr "Telwgw" + +msgid "Thai" +msgstr "Tai" + +msgid "Turkish" +msgstr "Twrceg" + +msgid "Tatar" +msgstr "Tatareg" + +msgid "Udmurt" +msgstr "Wdmwrteg" + +msgid "Ukrainian" +msgstr "Wcreineg" + +msgid "Urdu" +msgstr "Wrdw" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "Fietnameg" + +msgid "Simplified Chinese" +msgstr "Tsieinëeg Syml" + +msgid "Traditional Chinese" +msgstr "Tseinëeg Traddodiadol" + +msgid "Messages" +msgstr "" + +msgid "Site Maps" +msgstr "Mapiau Safle" + +msgid "Static Files" +msgstr "Ffeiliau Statig" + +msgid "Syndication" +msgstr "Syndicetiad" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "Rhowch werth dilys." + +msgid "Enter a valid URL." +msgstr "Rhowch URL dilys." + +msgid "Enter a valid integer." +msgstr "Rhowch gyfanrif dilys." + +msgid "Enter a valid email address." +msgstr "Rhowch gyfeiriad ebost dilys." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Rhowch gyfeiriad IPv4 dilys." + +msgid "Enter a valid IPv6 address." +msgstr "Rhowch gyfeiriad IPv6 dilys." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Rhowch gyfeiriad IPv4 neu IPv6 dilys." + +msgid "Enter only digits separated by commas." +msgstr "Rhowch ddigidau wedi'i gwahanu gan gomas yn unig." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Sicrhewch taw y gwerth yw %(limit_value)s (%(show_value)s yw ar hyn o bryd)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Sicrhewch fod y gwerth hwn yn fwy neu'n llai na %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Sicrhewch fod y gwerth yn fwy na neu'n gyfartal â %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Sicrhewch fod gan y gwerth hwn oleiaf %(limit_value)d nod (mae ganddo " +"%(show_value)d)." +msgstr[1] "" +"Sicrhewch fod gan y gwerth hwn oleiaf %(limit_value)d nod (mae ganddo " +"%(show_value)d)." +msgstr[2] "" +"Sicrhewch fod gan y gwerth hwn oleiaf %(limit_value)d nod (mae ganddo " +"%(show_value)d)." +msgstr[3] "" +"Sicrhewch fod gan y gwerth hwn oleiaf %(limit_value)d nod (mae ganddo " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Sicrhewch fod gan y gwerth hwn ddim mwy na %(limit_value)d nod (mae ganddo " +"%(show_value)d)." +msgstr[1] "" +"Sicrhewch fod gan y gwerth hwn ddim mwy na %(limit_value)d nod (mae ganddo " +"%(show_value)d)." +msgstr[2] "" +"Sicrhewch fod gan y gwerth hwn ddim mwy na %(limit_value)d nod (mae ganddo " +"%(show_value)d)." +msgstr[3] "" +"Sicrhewch fod gan y gwerth hwn ddim mwy na %(limit_value)d nod (mae ganddo " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Rhowch rif." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Sicrhewch nad oes mwy nag %(max)s digid i gyd." +msgstr[1] "Sicrhewch nad oes mwy na %(max)s ddigid i gyd." +msgstr[2] "Sicrhewch nad oes mwy na %(max)s digid i gyd." +msgstr[3] "Sicrhewch nad oes mwy na %(max)s digid i gyd." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Sicrhewch nad oes mwy nag %(max)s lle degol." +msgstr[1] "Sicrhewch nad oes mwy na %(max)s le degol." +msgstr[2] "Sicrhewch nad oes mwy na %(max)s lle degol." +msgstr[3] "Sicrhewch nad oes mwy na %(max)s lle degol." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "Sicrhewch nad oes mwy nag %(max)s digid cyn y pwynt degol." +msgstr[1] "Sicrhewch nad oes mwy na %(max)s ddigid cyn y pwynt degol." +msgstr[2] "Sicrhewch nad oes mwy na %(max)s digid cyn y pwynt degol." +msgstr[3] "Sicrhewch nad oes mwy na %(max)s digid cyn y pwynt degol." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "a" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "Mae %(model_name)s gyda'r %(field_labels)s hyn yn bodoli'n barod." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Nid yw gwerth %(value)r yn ddewis dilys." + +msgid "This field cannot be null." +msgstr "Ni all y maes hwn fod yn 'null'." + +msgid "This field cannot be blank." +msgstr "Ni all y maes hwn fod yn wag." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "Mae %(model_name)s gyda'r %(field_label)s hwn yn bodoli'n barod." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Maes o fath: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "Boleaidd (Unai True neu False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "String (hyd at %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "Cyfanrifau wedi'u gwahanu gan gomas" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "Dyddiad (heb amser)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Dyddiad (gydag amser)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Rhif degol" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "" + +msgid "Email address" +msgstr "Cyfeiriad ebost" + +msgid "File path" +msgstr "Llwybr ffeil" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "Rhif pwynt symudol" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "cyfanrif" + +msgid "Big (8 byte) integer" +msgstr "Cyfanrif mawr (8 beit)" + +msgid "IPv4 address" +msgstr "Cyfeiriad IPv4" + +msgid "IP address" +msgstr "cyfeiriad IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "Boleaidd (Naill ai True, False neu None)" + +msgid "Positive integer" +msgstr "Cyfanrif positif" + +msgid "Positive small integer" +msgstr "Cyfanrif bach positif" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Malwen (hyd at %(max_length)s)" + +msgid "Small integer" +msgstr "Cyfanrif bach" + +msgid "Text" +msgstr "Testun" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Amser" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Data deuol crai" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "Ffeil" + +msgid "Image" +msgstr "Delwedd" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "Allwedd Estron (math yn ddibynol ar y maes cysylltiedig)" + +msgid "One-to-one relationship" +msgstr "Perthynas un-i-un" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "Perthynas llawer-i-lawer" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Mae angen y maes hwn." + +msgid "Enter a whole number." +msgstr "Rhowch cyfanrif." + +msgid "Enter a valid date." +msgstr "Rhif ddyddiad dilys." + +msgid "Enter a valid time." +msgstr "Rhowch amser dilys." + +msgid "Enter a valid date/time." +msgstr "Rhowch ddyddiad/amser dilys." + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Ni anfonwyd ffeil. Gwiriwch math yr amgodiad ar y ffurflen." + +msgid "No file was submitted." +msgstr "Ni anfonwyd ffeil." + +msgid "The submitted file is empty." +msgstr "Mae'r ffeil yn wag." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Sicrhewch fod gan enw'r ffeil ar y mwyaf %(max)d nod (mae ganddo %(length)d)." +msgstr[1] "" +"Sicrhewch fod gan enw'r ffeil ar y mwyaf %(max)d nod (mae ganddo %(length)d)." +msgstr[2] "" +"Sicrhewch fod gan enw'r ffeil ar y mwyaf %(max)d nod (mae ganddo %(length)d)." +msgstr[3] "" +"Sicrhewch fod gan enw'r ffeil ar y mwyaf %(max)d nod (mae ganddo %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Nail ai cyflwynwych ffeil neu dewisiwch y blwch gwiriad, ond nid y ddau." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Llwythwch ddelwedd dilys. Doedd y ddelwedd a lwythwyd ddim yn ddelwedd " +"dilys, neu roedd yn ddelwedd llygredig." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Dewiswch ddewisiad dilys. Nid yw %(value)s yn un o'r dewisiadau sydd ar gael." + +msgid "Enter a list of values." +msgstr "Rhowch restr o werthoedd." + +msgid "Enter a complete value." +msgstr "Rhowch werth cyflawn." + +msgid "Enter a valid UUID." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Maes cudd %(name)s) %(error)s" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "Mae data ManagementForm ar goll neu mae rhywun wedi ymyrryd ynddo" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "Cyflwynwch %d neu lai o ffurflenni." +msgstr[1] "Cyflwynwch %d neu lai o ffurflenni." +msgstr[2] "Cyflwynwch %d neu lai o ffurflenni." +msgstr[3] "Cyflwynwch %d neu lai o ffurflenni." + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "Cyflwynwch %d neu fwy o ffurflenni." +msgstr[1] "Cyflwynwch %d neu fwy o ffurflenni." +msgstr[2] "Cyflwynwch %d neu fwy o ffurflenni." +msgstr[3] "Cyflwynwch %d neu fwy o ffurflenni." + +msgid "Order" +msgstr "Trefn" + +msgid "Delete" +msgstr "Dileu" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Cywirwch y data dyblyg ar gyfer %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Cywirwch y data dyblyg ar gyfer %(field)s, sydd yn gorfod bod yn unigryw." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Cywirwch y data dyblyg ar gyfer %(field_name)s sydd yn gorfod bod yn unigryw " +"ar gyfer %(lookup)s yn %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Cywirwch y gwerthoedd dyblyg isod." + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Dewiswch ddewisiad dilys. Nid yw'r dewisiad yn un o'r dewisiadau sydd ar " +"gael." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Clirio" + +msgid "Currently" +msgstr "Ar hyn o bryd" + +msgid "Change" +msgstr "Newid" + +msgid "Unknown" +msgstr "Anhysbys" + +msgid "Yes" +msgstr "Ie" + +msgid "No" +msgstr "Na" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "ie,na,efallai" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d beit" +msgstr[1] "%(size)d beit" +msgstr[2] "%(size)d beit" +msgstr[3] "%(size)d beit" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "y.h." + +msgid "a.m." +msgstr "y.b." + +msgid "PM" +msgstr "YH" + +msgid "AM" +msgstr "YB" + +msgid "midnight" +msgstr "canol nos" + +msgid "noon" +msgstr "canol dydd" + +msgid "Monday" +msgstr "Dydd Llun" + +msgid "Tuesday" +msgstr "Dydd Mawrth" + +msgid "Wednesday" +msgstr "Dydd Mercher" + +msgid "Thursday" +msgstr "Dydd Iau" + +msgid "Friday" +msgstr "Dydd Gwener" + +msgid "Saturday" +msgstr "Dydd Sadwrn" + +msgid "Sunday" +msgstr "Dydd Sul" + +msgid "Mon" +msgstr "Llu" + +msgid "Tue" +msgstr "Maw" + +msgid "Wed" +msgstr "Mer" + +msgid "Thu" +msgstr "Iau" + +msgid "Fri" +msgstr "Gwe" + +msgid "Sat" +msgstr "Sad" + +msgid "Sun" +msgstr "Sul" + +msgid "January" +msgstr "Ionawr" + +msgid "February" +msgstr "Chwefror" + +msgid "March" +msgstr "Mawrth" + +msgid "April" +msgstr "Ebrill" + +msgid "May" +msgstr "Mai" + +msgid "June" +msgstr "Mehefin" + +msgid "July" +msgstr "Gorffenaf" + +msgid "August" +msgstr "Awst" + +msgid "September" +msgstr "Medi" + +msgid "October" +msgstr "Hydref" + +msgid "November" +msgstr "Tachwedd" + +msgid "December" +msgstr "Rhagfyr" + +msgid "jan" +msgstr "ion" + +msgid "feb" +msgstr "chw" + +msgid "mar" +msgstr "maw" + +msgid "apr" +msgstr "ebr" + +msgid "may" +msgstr "mai" + +msgid "jun" +msgstr "meh" + +msgid "jul" +msgstr "gor" + +msgid "aug" +msgstr "aws" + +msgid "sep" +msgstr "med" + +msgid "oct" +msgstr "hyd" + +msgid "nov" +msgstr "tach" + +msgid "dec" +msgstr "rhag" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Ion." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Chwe." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Mawrth" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Ebrill" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Mai" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Meh." + +msgctxt "abbrev. month" +msgid "July" +msgstr "Gorff." + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Awst" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Medi" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Hydr." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Tach." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Rhag." + +msgctxt "alt. month" +msgid "January" +msgstr "Ionawr" + +msgctxt "alt. month" +msgid "February" +msgstr "Chwefror" + +msgctxt "alt. month" +msgid "March" +msgstr "Mawrth" + +msgctxt "alt. month" +msgid "April" +msgstr "Ebrill" + +msgctxt "alt. month" +msgid "May" +msgstr "Mai" + +msgctxt "alt. month" +msgid "June" +msgstr "Mehefin" + +msgctxt "alt. month" +msgid "July" +msgstr "Gorffenaf" + +msgctxt "alt. month" +msgid "August" +msgstr "Awst" + +msgctxt "alt. month" +msgid "September" +msgstr "Medi" + +msgctxt "alt. month" +msgid "October" +msgstr "Hydref" + +msgctxt "alt. month" +msgid "November" +msgstr "Tachwedd" + +msgctxt "alt. month" +msgid "December" +msgstr "Rhagfyr" + +msgid "This is not a valid IPv6 address." +msgstr "Nid yw hwn yn gyfeiriad IPv6 dilys." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "neu" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "," + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d blwyddyn" +msgstr[1] "%d flynedd" +msgstr[2] "%d blwyddyn" +msgstr[3] "%d blwyddyn" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d mis" +msgstr[1] "%d fis" +msgstr[2] "%d mis" +msgstr[3] "%d mis" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d wythnos" +msgstr[1] "%d wythnos" +msgstr[2] "%d wythnos" +msgstr[3] "%d wythnos" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d diwrnod" +msgstr[1] "%d ddiwrnod" +msgstr[2] "%d diwrnod" +msgstr[3] "%d diwrnod" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d awr" +msgstr[1] "%d awr" +msgstr[2] "%d awr" +msgstr[3] "%d awr" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d munud" +msgstr[1] "%d funud" +msgstr[2] "%d munud" +msgstr[3] "%d munud" + +msgid "0 minutes" +msgstr "0 munud" + +msgid "Forbidden" +msgstr "Gwaharddedig" + +msgid "CSRF verification failed. Request aborted." +msgstr "Gwirio CSRF wedi methu. Ataliwyd y cais." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Dangosir y neges hwn oherwydd bod angen cwci CSRF ar y safle hwn pan yn " +"anfon ffurflenni. Mae angen y cwci ar gyfer diogelwch er mwyn sicrhau nad " +"oes trydydd parti yn herwgipio eich porwr." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "Mae mwy o wybodaeth ar gael gyda DEBUG=True" + +msgid "No year specified" +msgstr "Dim blwyddyn wedi’i bennu" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "Dim mis wedi’i bennu" + +msgid "No day specified" +msgstr "Dim diwrnod wedi’i bennu" + +msgid "No week specified" +msgstr "Dim wythnos wedi’i bennu" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Dim %(verbose_name_plural)s ar gael" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"%(verbose_name_plural)s i'r dyfodol ddim ar gael oherwydd mae %(class_name)s." +"allow_future yn 'False'. " + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Ni ganfuwyd %(verbose_name)s yn cydweddu â'r ymholiad" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Tudalen annilys (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Ni ganiateir mynegai cyfeiriaduron yma." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Mynegai %(directory)s" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/cy/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/cy/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/cy/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/cy/formats.py new file mode 100644 index 0000000..eaef6a6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/cy/formats.py @@ -0,0 +1,33 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j F Y" # '25 Hydref 2006' +TIME_FORMAT = "P" # '2:30 y.b.' +DATETIME_FORMAT = "j F Y, P" # '25 Hydref 2006, 2:30 y.b.' +YEAR_MONTH_FORMAT = "F Y" # 'Hydref 2006' +MONTH_DAY_FORMAT = "j F" # '25 Hydref' +SHORT_DATE_FORMAT = "d/m/Y" # '25/10/2006' +SHORT_DATETIME_FORMAT = "d/m/Y P" # '25/10/2006 2:30 y.b.' +FIRST_DAY_OF_WEEK = 1 # 'Dydd Llun' + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d/%m/%Y", # '25/10/2006' + "%d/%m/%y", # '25/10/06' +] +DATETIME_INPUT_FORMATS = [ + "%Y-%m-%d %H:%M:%S", # '2006-10-25 14:30:59' + "%Y-%m-%d %H:%M:%S.%f", # '2006-10-25 14:30:59.000200' + "%Y-%m-%d %H:%M", # '2006-10-25 14:30' + "%d/%m/%Y %H:%M:%S", # '25/10/2006 14:30:59' + "%d/%m/%Y %H:%M:%S.%f", # '25/10/2006 14:30:59.000200' + "%d/%m/%Y %H:%M", # '25/10/2006 14:30' + "%d/%m/%y %H:%M:%S", # '25/10/06 14:30:59' + "%d/%m/%y %H:%M:%S.%f", # '25/10/06 14:30:59.000200' + "%d/%m/%y %H:%M", # '25/10/06 14:30' +] +DECIMAL_SEPARATOR = "." +THOUSAND_SEPARATOR = "," +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/da/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/da/LC_MESSAGES/django.mo new file mode 100644 index 0000000..253c828 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/da/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/da/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/da/LC_MESSAGES/django.po new file mode 100644 index 0000000..7853017 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/da/LC_MESSAGES/django.po @@ -0,0 +1,1334 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Christian Joergensen , 2012 +# Danni Randeris , 2014 +# Erik Ramsgaard Wognsen , 2020-2023 +# Erik Ramsgaard Wognsen , 2013-2019 +# Finn Gruwier Larsen, 2011 +# Jannis Leidel , 2011 +# jonaskoelker , 2012 +# Mads Chr. Olesen , 2013 +# valberg , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Erik Ramsgaard Wognsen , 2020-2023\n" +"Language-Team: Danish (http://app.transifex.com/django/django/language/da/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: da\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "afrikaans" + +msgid "Arabic" +msgstr "arabisk" + +msgid "Algerian Arabic" +msgstr "algerisk arabisk" + +msgid "Asturian" +msgstr "Asturisk" + +msgid "Azerbaijani" +msgstr "azerbaidjansk" + +msgid "Bulgarian" +msgstr "bulgarsk" + +msgid "Belarusian" +msgstr "hviderussisk" + +msgid "Bengali" +msgstr "bengalsk" + +msgid "Breton" +msgstr "bretonsk" + +msgid "Bosnian" +msgstr "bosnisk" + +msgid "Catalan" +msgstr "catalansk" + +msgid "Central Kurdish (Sorani)" +msgstr "Centralkurdisk (Sorani)" + +msgid "Czech" +msgstr "tjekkisk" + +msgid "Welsh" +msgstr "walisisk" + +msgid "Danish" +msgstr "dansk" + +msgid "German" +msgstr "tysk" + +msgid "Lower Sorbian" +msgstr "nedresorbisk" + +msgid "Greek" +msgstr "græsk" + +msgid "English" +msgstr "engelsk" + +msgid "Australian English" +msgstr "australsk engelsk" + +msgid "British English" +msgstr "britisk engelsk" + +msgid "Esperanto" +msgstr "esperanto" + +msgid "Spanish" +msgstr "spansk" + +msgid "Argentinian Spanish" +msgstr "argentinsk spansk" + +msgid "Colombian Spanish" +msgstr "colombiansk spansk" + +msgid "Mexican Spanish" +msgstr "mexikansk spansk" + +msgid "Nicaraguan Spanish" +msgstr "nicaraguansk spansk" + +msgid "Venezuelan Spanish" +msgstr "venezuelansk spansk" + +msgid "Estonian" +msgstr "estisk" + +msgid "Basque" +msgstr "baskisk" + +msgid "Persian" +msgstr "persisk" + +msgid "Finnish" +msgstr "finsk" + +msgid "French" +msgstr "fransk" + +msgid "Frisian" +msgstr "frisisk" + +msgid "Irish" +msgstr "irsk" + +msgid "Scottish Gaelic" +msgstr "skotsk gælisk" + +msgid "Galician" +msgstr "galicisk" + +msgid "Hebrew" +msgstr "hebraisk" + +msgid "Hindi" +msgstr "hindi" + +msgid "Croatian" +msgstr "kroatisk" + +msgid "Upper Sorbian" +msgstr "øvresorbisk" + +msgid "Hungarian" +msgstr "ungarsk" + +msgid "Armenian" +msgstr "armensk" + +msgid "Interlingua" +msgstr "interlingua" + +msgid "Indonesian" +msgstr "indonesisk" + +msgid "Igbo" +msgstr "igbo" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "islandsk" + +msgid "Italian" +msgstr "italiensk" + +msgid "Japanese" +msgstr "japansk" + +msgid "Georgian" +msgstr "georgisk" + +msgid "Kabyle" +msgstr "kabylsk" + +msgid "Kazakh" +msgstr "kasakhisk" + +msgid "Khmer" +msgstr "khmer" + +msgid "Kannada" +msgstr "kannada" + +msgid "Korean" +msgstr "koreansk" + +msgid "Kyrgyz" +msgstr "kirgisisk" + +msgid "Luxembourgish" +msgstr "luxembourgisk" + +msgid "Lithuanian" +msgstr "litauisk" + +msgid "Latvian" +msgstr "lettisk" + +msgid "Macedonian" +msgstr "makedonsk" + +msgid "Malayalam" +msgstr "malayalam" + +msgid "Mongolian" +msgstr "mongolsk" + +msgid "Marathi" +msgstr "marathi" + +msgid "Malay" +msgstr "malajisk" + +msgid "Burmese" +msgstr "burmesisk" + +msgid "Norwegian Bokmål" +msgstr "norsk bokmål" + +msgid "Nepali" +msgstr "nepalesisk" + +msgid "Dutch" +msgstr "hollandsk" + +msgid "Norwegian Nynorsk" +msgstr "norsk nynorsk" + +msgid "Ossetic" +msgstr "ossetisk" + +msgid "Punjabi" +msgstr "punjabi" + +msgid "Polish" +msgstr "polsk" + +msgid "Portuguese" +msgstr "portugisisk" + +msgid "Brazilian Portuguese" +msgstr "brasiliansk portugisisk" + +msgid "Romanian" +msgstr "rumænsk" + +msgid "Russian" +msgstr "russisk" + +msgid "Slovak" +msgstr "slovakisk" + +msgid "Slovenian" +msgstr "slovensk" + +msgid "Albanian" +msgstr "albansk" + +msgid "Serbian" +msgstr "serbisk" + +msgid "Serbian Latin" +msgstr "serbisk (latin)" + +msgid "Swedish" +msgstr "svensk" + +msgid "Swahili" +msgstr "swahili" + +msgid "Tamil" +msgstr "tamil" + +msgid "Telugu" +msgstr "telugu" + +msgid "Tajik" +msgstr "tadsjikisk" + +msgid "Thai" +msgstr "thai" + +msgid "Turkmen" +msgstr "turkmensk" + +msgid "Turkish" +msgstr "tyrkisk" + +msgid "Tatar" +msgstr "tatarisk" + +msgid "Udmurt" +msgstr "udmurtisk" + +msgid "Uyghur" +msgstr "uygurisk" + +msgid "Ukrainian" +msgstr "ukrainsk" + +msgid "Urdu" +msgstr "urdu" + +msgid "Uzbek" +msgstr "usbekisk" + +msgid "Vietnamese" +msgstr "vietnamesisk" + +msgid "Simplified Chinese" +msgstr "forenklet kinesisk" + +msgid "Traditional Chinese" +msgstr "traditionelt kinesisk" + +msgid "Messages" +msgstr "Meddelelser" + +msgid "Site Maps" +msgstr "Site Maps" + +msgid "Static Files" +msgstr "Static Files" + +msgid "Syndication" +msgstr "Syndication" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Det sidetal er ikke et heltal" + +msgid "That page number is less than 1" +msgstr "Det sidetal er mindre end 1" + +msgid "That page contains no results" +msgstr "Den side indeholder ingen resultater" + +msgid "Enter a valid value." +msgstr "Indtast en gyldig værdi." + +msgid "Enter a valid URL." +msgstr "Indtast en gyldig URL." + +msgid "Enter a valid integer." +msgstr "Indtast et gyldigt heltal." + +msgid "Enter a valid email address." +msgstr "Indtast en gyldig e-mail-adresse." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Indtast en gyldig “slug” bestående af bogstaver, cifre, understreger eller " +"bindestreger." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Indtast en gyldig “slug” bestående af Unicode-bogstaver, cifre, understreger " +"eller bindestreger." + +msgid "Enter a valid IPv4 address." +msgstr "Indtast en gyldig IPv4-adresse." + +msgid "Enter a valid IPv6 address." +msgstr "Indtast en gyldig IPv6-adresse." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Indtast en gyldig IPv4- eller IPv6-adresse." + +msgid "Enter only digits separated by commas." +msgstr "Indtast kun cifre adskilt af kommaer." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Denne værdi skal være %(limit_value)s (den er %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Denne værdi skal være mindre end eller lig %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Denne værdi skal være større end eller lig %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "Denne værdi skal være et multiplum af trinstørrelse %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"Denne værdi skal være et multiplum af trinstørrelse %(limit_value)s, " +"startende fra %(offset)s, fx %(offset)s, %(valid_value1)s, %(valid_value2)s, " +"osv." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Denne værdi skal have mindst %(limit_value)d tegn (den har %(show_value)d)." +msgstr[1] "" +"Denne værdi skal have mindst %(limit_value)d tegn (den har %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Denne værdi må højst have %(limit_value)d tegn (den har %(show_value)d)." +msgstr[1] "" +"Denne værdi må højst have %(limit_value)d tegn (den har %(show_value)d)." + +msgid "Enter a number." +msgstr "Indtast et tal." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Der må maksimalt være %(max)s ciffer i alt." +msgstr[1] "Der må maksimalt være %(max)s cifre i alt." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Der må maksimalt være %(max)s decimal." +msgstr[1] "Der må maksimalt være %(max)s decimaler." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "Der må maksimalt være %(max)s ciffer før kommaet." +msgstr[1] "Der må maksimalt være %(max)s cifre før kommaet." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Filendelse “%(extension)s” er ikke tilladt. Tilladte filendelser er: " +"%(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Null-tegn er ikke tilladte." + +msgid "and" +msgstr "og" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s med dette %(field_labels)s eksisterer allerede." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Begrænsning “%(name)s” er overtrådt." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Værdien %(value)r er ikke et gyldigt valg." + +msgid "This field cannot be null." +msgstr "Dette felt kan ikke være null." + +msgid "This field cannot be blank." +msgstr "Dette felt kan ikke være tomt." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s med dette %(field_label)s eksisterer allerede." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s skal være unik for %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Felt af type: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "“%(value)s”-værdien skal være enten True eller False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "“%(value)s”-værdien skal være enten True, False eller None." + +msgid "Boolean (Either True or False)" +msgstr "Boolsk (enten True eller False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Streng (op til %(max_length)s)" + +msgid "String (unlimited)" +msgstr "Streng (ubegrænset)" + +msgid "Comma-separated integers" +msgstr "Kommaseparerede heltal" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"“%(value)s”-værdien har et ugyldigt datoformat. Den skal være i formatet " +"ÅÅÅÅ-MM-DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"“%(value)s”-værdien har det korrekte format (ÅÅÅÅ-MM-DD) men er en ugyldig " +"dato." + +msgid "Date (without time)" +msgstr "Dato (uden tid)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"“%(value)s”-værdien har et ugyldigt format. Den skal være i formatet ÅÅÅÅ-MM-" +"DD TT:MM[:ss[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"“%(value)s”-værdien har det korrekte format (ÅÅÅÅ-MM-DD TT:MM[:ss[.uuuuuu]]" +"[TZ]) men er en ugyldig dato/tid." + +msgid "Date (with time)" +msgstr "Dato (med tid)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "“%(value)s”-værdien skal være et decimaltal." + +msgid "Decimal number" +msgstr "Decimaltal" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"“%(value)s”-værdien har et ugyldigt format. Den skal være i formatet [DD] " +"[[TT:]MM:]ss[.uuuuuu]." + +msgid "Duration" +msgstr "Varighed" + +msgid "Email address" +msgstr "E-mail-adresse" + +msgid "File path" +msgstr "Sti" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "“%(value)s”-værdien skal være et kommatal." + +msgid "Floating point number" +msgstr "Flydende-komma-tal" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "“%(value)s”-værdien skal være et heltal." + +msgid "Integer" +msgstr "Heltal" + +msgid "Big (8 byte) integer" +msgstr "Stort heltal (8 byte)" + +msgid "Small integer" +msgstr "Lille heltal" + +msgid "IPv4 address" +msgstr "IPv4-adresse" + +msgid "IP address" +msgstr "IP-adresse" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "“%(value)s”-værdien skal være enten None, True eller False." + +msgid "Boolean (Either True, False or None)" +msgstr "Boolsk (True, False eller None)" + +msgid "Positive big integer" +msgstr "Positivt stort heltal" + +msgid "Positive integer" +msgstr "Positivt heltal" + +msgid "Positive small integer" +msgstr "Positivt lille heltal" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "\"Slug\" (op til %(max_length)s)" + +msgid "Text" +msgstr "Tekst" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"“%(value)s”-værdien har et ugyldigt format. Den skal være i formatet TT:MM[:" +"ss[.uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"“%(value)s”-værdien har det korrekte format (TT:MM[:ss[.uuuuuu]]) men er et " +"ugyldigt tidspunkt." + +msgid "Time" +msgstr "Tid" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Rå binære data" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "“%(value)s” er ikke et gyldigt UUID." + +msgid "Universally unique identifier" +msgstr "Universelt unik identifikator" + +msgid "File" +msgstr "Fil" + +msgid "Image" +msgstr "Billede" + +msgid "A JSON object" +msgstr "Et JSON-objekt" + +msgid "Value must be valid JSON." +msgstr "Værdien skal være gyldig JSON." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(model)s instans med %(field)s %(value)r findes ikke." + +msgid "Foreign Key (type determined by related field)" +msgstr "Fremmednøgle (type bestemt af relateret felt)" + +msgid "One-to-one relationship" +msgstr "En-til-en-relation" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s-relation" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s-relationer" + +msgid "Many-to-many relationship" +msgstr "Mange-til-mange-relation" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Dette felt er påkrævet." + +msgid "Enter a whole number." +msgstr "Indtast et heltal." + +msgid "Enter a valid date." +msgstr "Indtast en gyldig dato." + +msgid "Enter a valid time." +msgstr "Indtast en gyldig tid." + +msgid "Enter a valid date/time." +msgstr "Indtast gyldig dato/tid." + +msgid "Enter a valid duration." +msgstr "Indtast en gyldig varighed." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Antallet af dage skal være mellem {min_days} og {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Ingen fil blev indsendt. Kontroller kodningstypen i formularen." + +msgid "No file was submitted." +msgstr "Ingen fil blev indsendt." + +msgid "The submitted file is empty." +msgstr "Den indsendte fil er tom." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "Dette filnavn må højst have %(max)d tegn (det har %(length)d)." +msgstr[1] "Dette filnavn må højst have %(max)d tegn (det har %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Du skal enten indsende en fil eller afmarkere afkrydsningsfeltet, ikke begge " +"dele." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Indsend en billedfil. Filen, du indsendte, var enten ikke et billede eller " +"en defekt billedfil." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Marker en gyldig valgmulighed. %(value)s er ikke en af de tilgængelige " +"valgmuligheder." + +msgid "Enter a list of values." +msgstr "Indtast en liste af værdier." + +msgid "Enter a complete value." +msgstr "Indtast en komplet værdi." + +msgid "Enter a valid UUID." +msgstr "Indtast et gyldigt UUID." + +msgid "Enter a valid JSON." +msgstr "Indtast gyldig JSON." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Skjult felt %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"ManagementForm-data mangler eller er blevet pillet ved. Manglende felter: " +"%(field_names)s. Du kan få behov for at oprette en fejlrapport hvis " +"problemet varer ved." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Indsend venligst højst %(num)d formular." +msgstr[1] "Indsend venligst højst %(num)d formularer." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Indsend venligst mindst %(num)d formular." +msgstr[1] "Indsend venligst mindst %(num)d formularer." + +msgid "Order" +msgstr "Rækkefølge" + +msgid "Delete" +msgstr "Slet" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Ret venligst duplikerede data for %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Ret venligst de duplikerede data for %(field)s, som skal være unik." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Ret venligst de duplikerede data for %(field_name)s, som skal være unik for " +"%(lookup)s i %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Ret venligst de duplikerede data herunder." + +msgid "The inline value did not match the parent instance." +msgstr "Den indlejrede værdi passede ikke med forældreinstansen." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Marker en gyldig valgmulighed. Det valg, du har foretaget, er ikke blandt de " +"tilgængelige valgmuligheder." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "“%(pk)s” er ikke en gyldig værdi." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s kunne ikke fortolkes i tidszonen %(current_timezone)s; den kan " +"være tvetydig eller den eksisterer måske ikke." + +msgid "Clear" +msgstr "Afmarkér" + +msgid "Currently" +msgstr "Aktuelt" + +msgid "Change" +msgstr "Ret" + +msgid "Unknown" +msgstr "Ukendt" + +msgid "Yes" +msgstr "Ja" + +msgid "No" +msgstr "Nej" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "ja,nej,måske" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d byte" +msgstr[1] "%(size)d bytes" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "midnat" + +msgid "noon" +msgstr "middag" + +msgid "Monday" +msgstr "mandag" + +msgid "Tuesday" +msgstr "tirsdag" + +msgid "Wednesday" +msgstr "onsdag" + +msgid "Thursday" +msgstr "torsdag" + +msgid "Friday" +msgstr "fredag" + +msgid "Saturday" +msgstr "lørdag" + +msgid "Sunday" +msgstr "søndag" + +msgid "Mon" +msgstr "man" + +msgid "Tue" +msgstr "tir" + +msgid "Wed" +msgstr "ons" + +msgid "Thu" +msgstr "tor" + +msgid "Fri" +msgstr "fre" + +msgid "Sat" +msgstr "lør" + +msgid "Sun" +msgstr "søn" + +msgid "January" +msgstr "januar" + +msgid "February" +msgstr "februar" + +msgid "March" +msgstr "marts" + +msgid "April" +msgstr "april" + +msgid "May" +msgstr "maj" + +msgid "June" +msgstr "juni" + +msgid "July" +msgstr "juli" + +msgid "August" +msgstr "august" + +msgid "September" +msgstr "september" + +msgid "October" +msgstr "oktober" + +msgid "November" +msgstr "november" + +msgid "December" +msgstr "december" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "apr" + +msgid "may" +msgstr "maj" + +msgid "jun" +msgstr "jun" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "aug" + +msgid "sep" +msgstr "sept" + +msgid "oct" +msgstr "okt" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dec" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "marts" + +msgctxt "abbrev. month" +msgid "April" +msgstr "april" + +msgctxt "abbrev. month" +msgid "May" +msgstr "maj" + +msgctxt "abbrev. month" +msgid "June" +msgstr "juni" + +msgctxt "abbrev. month" +msgid "July" +msgstr "juli" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "aug." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "sept." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "okt." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "dec." + +msgctxt "alt. month" +msgid "January" +msgstr "januar" + +msgctxt "alt. month" +msgid "February" +msgstr "februar" + +msgctxt "alt. month" +msgid "March" +msgstr "marts" + +msgctxt "alt. month" +msgid "April" +msgstr "april" + +msgctxt "alt. month" +msgid "May" +msgstr "maj" + +msgctxt "alt. month" +msgid "June" +msgstr "juni" + +msgctxt "alt. month" +msgid "July" +msgstr "juli" + +msgctxt "alt. month" +msgid "August" +msgstr "august" + +msgctxt "alt. month" +msgid "September" +msgstr "september" + +msgctxt "alt. month" +msgid "October" +msgstr "oktober" + +msgctxt "alt. month" +msgid "November" +msgstr "november" + +msgctxt "alt. month" +msgid "December" +msgstr "december" + +msgid "This is not a valid IPv6 address." +msgstr "Dette er ikke en gyldig IPv6-adresse." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "eller" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d år" +msgstr[1] "%(num)d år" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d måned" +msgstr[1] "%(num)d måneder" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d uge" +msgstr[1] "%(num)d uger" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dag" +msgstr[1] "%(num)d dage" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d time" +msgstr[1] "%(num)d timer" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minut" +msgstr[1] "%(num)d minutter" + +msgid "Forbidden" +msgstr "Forbudt" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF-verifikationen mislykkedes. Forespørgslen blev afbrudt." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Du ser denne besked fordi denne HTTPS-webside kræver at din browser sender " +"en “Referer header”, som ikke blev sendt. Denne header er påkrævet af " +"sikkerhedsmæssige grunde for at sikre at din browser ikke bliver kapret af " +"tredjepart." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Hvis du har opsat din browser til ikke at sende “Referer” headere, beder vi " +"dig slå dem til igen, i hvert fald for denne webside, eller for HTTPS-" +"forbindelser, eller for “same-origin”-forespørgsler." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Hvis du bruger tagget eller " +"inkluderer headeren “Referrer-Policy: no-referrer”, så fjern dem venligst. " +"CSRF-beskyttelsen afhænger af at “Referer”-headeren udfører stringent " +"referer-kontrol. Hvis du er bekymret om privatliv, så brug alternativer så " +"som for links til tredjepartswebsider." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Du ser denne besked fordi denne webside kræver en CSRF-cookie, når du sender " +"formularer. Denne cookie er påkrævet af sikkerhedsmæssige grunde for at " +"sikre at din browser ikke bliver kapret af tredjepart." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Hvis du har slået cookies fra i din browser, beder vi dig slå dem til igen, " +"i hvert fald for denne webside, eller for “same-origin”-forespørgsler." + +msgid "More information is available with DEBUG=True." +msgstr "Mere information er tilgængeligt med DEBUG=True." + +msgid "No year specified" +msgstr "Intet år specificeret" + +msgid "Date out of range" +msgstr "Dato uden for rækkevidde" + +msgid "No month specified" +msgstr "Ingen måned specificeret" + +msgid "No day specified" +msgstr "Ingen dag specificeret" + +msgid "No week specified" +msgstr "Ingen uge specificeret" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Ingen %(verbose_name_plural)s til rådighed" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Fremtidige %(verbose_name_plural)s ikke tilgængelige, fordi %(class_name)s ." +"allow_future er falsk." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Ugyldig datostreng “%(datestr)s” givet format “%(format)s”" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Ingen %(verbose_name)s fundet matcher forespørgslen" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Side er ikke “sidste”, og kan heller ikke konverteres til en int." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Ugyldig side (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Tom liste og “%(class_name)s.allow_empty” er falsk." + +msgid "Directory indexes are not allowed here." +msgstr "Mappeindekser er ikke tilladte her" + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "“%(path)s” eksisterer ikke" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Indeks for %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Installationen virkede! Tillykke!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Vis udgivelsesnoter for Django %(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Du ser denne side fordi du har DEBUG=True i din settings-fil og ikke har opsat nogen " +"URL'er." + +msgid "Django Documentation" +msgstr "Django-dokumentation" + +msgid "Topics, references, & how-to’s" +msgstr "Emner, referencer & how-to’s" + +msgid "Tutorial: A Polling App" +msgstr "Gennemgang: En afstemnings-app" + +msgid "Get started with Django" +msgstr "Kom i gang med Django" + +msgid "Django Community" +msgstr "Django-fællesskabet" + +msgid "Connect, get help, or contribute" +msgstr "Forbind, få hjælp eller bidrag" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/da/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/da/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/da/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/da/formats.py new file mode 100644 index 0000000..5829208 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/da/formats.py @@ -0,0 +1,26 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j. F Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = "j. F Y H:i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j. F" +SHORT_DATE_FORMAT = "d.m.Y" +SHORT_DATETIME_FORMAT = "d.m.Y H:i" +FIRST_DAY_OF_WEEK = 1 + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d.%m.%Y", # '25.10.2006' +] +DATETIME_INPUT_FORMATS = [ + "%d.%m.%Y %H:%M:%S", # '25.10.2006 14:30:59' + "%d.%m.%Y %H:%M:%S.%f", # '25.10.2006 14:30:59.000200' + "%d.%m.%Y %H:%M", # '25.10.2006 14:30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/de/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/de/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e3ef1cb Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/de/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/de/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/de/LC_MESSAGES/django.po new file mode 100644 index 0000000..90037a2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/de/LC_MESSAGES/django.po @@ -0,0 +1,1356 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# André Hagenbruch, 2011-2012 +# Florian Apolloner , 2011 +# Daniel Roschka , 2016 +# Florian Apolloner , 2018,2020-2023 +# jnns, 2011,2013 +# Jannis Leidel , 2013-2018,2020 +# jnns, 2016 +# Markus Holtermann , 2023 +# Markus Holtermann , 2013,2015 +# Raphael Michel , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Markus Holtermann , 2023\n" +"Language-Team: German (http://app.transifex.com/django/django/language/de/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Afrikaans" + +msgid "Arabic" +msgstr "Arabisch" + +msgid "Algerian Arabic" +msgstr "Algerisches Arabisch" + +msgid "Asturian" +msgstr "Asturisch" + +msgid "Azerbaijani" +msgstr "Aserbaidschanisch" + +msgid "Bulgarian" +msgstr "Bulgarisch" + +msgid "Belarusian" +msgstr "Weißrussisch" + +msgid "Bengali" +msgstr "Bengali" + +msgid "Breton" +msgstr "Bretonisch" + +msgid "Bosnian" +msgstr "Bosnisch" + +msgid "Catalan" +msgstr "Katalanisch" + +msgid "Central Kurdish (Sorani)" +msgstr "Zentralkurdisch (Sorani)" + +msgid "Czech" +msgstr "Tschechisch" + +msgid "Welsh" +msgstr "Walisisch" + +msgid "Danish" +msgstr "Dänisch" + +msgid "German" +msgstr "Deutsch" + +msgid "Lower Sorbian" +msgstr "Niedersorbisch" + +msgid "Greek" +msgstr "Griechisch" + +msgid "English" +msgstr "Englisch" + +msgid "Australian English" +msgstr "Australisches Englisch" + +msgid "British English" +msgstr "Britisches Englisch" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Spanisch" + +msgid "Argentinian Spanish" +msgstr "Argentinisches Spanisch" + +msgid "Colombian Spanish" +msgstr "Kolumbianisches Spanisch" + +msgid "Mexican Spanish" +msgstr "Mexikanisches Spanisch" + +msgid "Nicaraguan Spanish" +msgstr "Nicaraguanisches Spanisch" + +msgid "Venezuelan Spanish" +msgstr "Venezolanisches Spanisch" + +msgid "Estonian" +msgstr "Estnisch" + +msgid "Basque" +msgstr "Baskisch" + +msgid "Persian" +msgstr "Persisch" + +msgid "Finnish" +msgstr "Finnisch" + +msgid "French" +msgstr "Französisch" + +msgid "Frisian" +msgstr "Friesisch" + +msgid "Irish" +msgstr "Irisch" + +msgid "Scottish Gaelic" +msgstr "Schottisch-Gälisch" + +msgid "Galician" +msgstr "Galicisch" + +msgid "Hebrew" +msgstr "Hebräisch" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Kroatisch" + +msgid "Upper Sorbian" +msgstr "Obersorbisch" + +msgid "Hungarian" +msgstr "Ungarisch" + +msgid "Armenian" +msgstr "Armenisch" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonesisch" + +msgid "Igbo" +msgstr "Igbo" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Isländisch" + +msgid "Italian" +msgstr "Italienisch" + +msgid "Japanese" +msgstr "Japanisch" + +msgid "Georgian" +msgstr "Georgisch" + +msgid "Kabyle" +msgstr "Kabylisch" + +msgid "Kazakh" +msgstr "Kasachisch" + +msgid "Khmer" +msgstr "Khmer" + +msgid "Kannada" +msgstr "Kannada" + +msgid "Korean" +msgstr "Koreanisch" + +msgid "Kyrgyz" +msgstr "Kirgisisch" + +msgid "Luxembourgish" +msgstr "Luxemburgisch" + +msgid "Lithuanian" +msgstr "Litauisch" + +msgid "Latvian" +msgstr "Lettisch" + +msgid "Macedonian" +msgstr "Mazedonisch" + +msgid "Malayalam" +msgstr "Malayalam" + +msgid "Mongolian" +msgstr "Mongolisch" + +msgid "Marathi" +msgstr "Marathi" + +msgid "Malay" +msgstr "Malaiisch" + +msgid "Burmese" +msgstr "Birmanisch" + +msgid "Norwegian Bokmål" +msgstr "Norwegisch (Bokmål)" + +msgid "Nepali" +msgstr "Nepali" + +msgid "Dutch" +msgstr "Niederländisch" + +msgid "Norwegian Nynorsk" +msgstr "Norwegisch (Nynorsk)" + +msgid "Ossetic" +msgstr "Ossetisch" + +msgid "Punjabi" +msgstr "Panjabi" + +msgid "Polish" +msgstr "Polnisch" + +msgid "Portuguese" +msgstr "Portugiesisch" + +msgid "Brazilian Portuguese" +msgstr "Brasilianisches Portugiesisch" + +msgid "Romanian" +msgstr "Rumänisch" + +msgid "Russian" +msgstr "Russisch" + +msgid "Slovak" +msgstr "Slowakisch" + +msgid "Slovenian" +msgstr "Slowenisch" + +msgid "Albanian" +msgstr "Albanisch" + +msgid "Serbian" +msgstr "Serbisch" + +msgid "Serbian Latin" +msgstr "Serbisch (Latein)" + +msgid "Swedish" +msgstr "Schwedisch" + +msgid "Swahili" +msgstr "Swahili" + +msgid "Tamil" +msgstr "Tamilisch" + +msgid "Telugu" +msgstr "Telugisch" + +msgid "Tajik" +msgstr "Tadschikisch" + +msgid "Thai" +msgstr "Thailändisch" + +msgid "Turkmen" +msgstr "Turkmenisch" + +msgid "Turkish" +msgstr "Türkisch" + +msgid "Tatar" +msgstr "Tatarisch" + +msgid "Udmurt" +msgstr "Udmurtisch" + +msgid "Uyghur" +msgstr "Uigurisch" + +msgid "Ukrainian" +msgstr "Ukrainisch" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "Usbekisch" + +msgid "Vietnamese" +msgstr "Vietnamesisch" + +msgid "Simplified Chinese" +msgstr "Vereinfachtes Chinesisch" + +msgid "Traditional Chinese" +msgstr "Traditionelles Chinesisch" + +msgid "Messages" +msgstr "Mitteilungen" + +msgid "Site Maps" +msgstr "Sitemaps" + +msgid "Static Files" +msgstr "Statische Dateien" + +msgid "Syndication" +msgstr "Syndication" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Diese Seitennummer ist keine Ganzzahl" + +msgid "That page number is less than 1" +msgstr "Diese Seitennummer ist kleiner als 1" + +msgid "That page contains no results" +msgstr "Diese Seite enthält keine Ergebnisse" + +msgid "Enter a valid value." +msgstr "Bitte einen gültigen Wert eingeben." + +msgid "Enter a valid URL." +msgstr "Bitte eine gültige Adresse eingeben." + +msgid "Enter a valid integer." +msgstr "Bitte eine gültige Ganzzahl eingeben." + +msgid "Enter a valid email address." +msgstr "Bitte gültige E-Mail-Adresse eingeben." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Bitte ein gültiges Kürzel, bestehend aus Buchstaben, Ziffern, Unterstrichen " +"und Bindestrichen, eingeben." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Bitte ein gültiges Kürzel eingeben, bestehend aus Buchstaben (Unicode), " +"Ziffern, Unter- und Bindestrichen." + +msgid "Enter a valid IPv4 address." +msgstr "Bitte eine gültige IPv4-Adresse eingeben." + +msgid "Enter a valid IPv6 address." +msgstr "Bitte eine gültige IPv6-Adresse eingeben." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Bitte eine gültige IPv4- oder IPv6-Adresse eingeben" + +msgid "Enter only digits separated by commas." +msgstr "Bitte nur durch Komma getrennte Ziffern eingeben." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Bitte sicherstellen, dass der Wert %(limit_value)s ist. (Er ist " +"%(show_value)s.)" + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Dieser Wert muss kleiner oder gleich %(limit_value)s sein." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Dieser Wert muss größer oder gleich %(limit_value)s sein." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "Dieser Wert muss ein Vielfaches von %(limit_value)s sein." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"Dieser Wert muss ein Vielfaches von %(limit_value)s sein und bei %(offset)s " +"beginnen, z.B. %(offset)s, %(valid_value1)s, %(valid_value2)s, und so weiter." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Bitte sicherstellen, dass der Wert aus mindestens %(limit_value)d Zeichen " +"besteht. (Er besteht aus %(show_value)d Zeichen.)" +msgstr[1] "" +"Bitte sicherstellen, dass der Wert aus mindestens %(limit_value)d Zeichen " +"besteht. (Er besteht aus %(show_value)d Zeichen.)" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Bitte sicherstellen, dass der Wert aus höchstens %(limit_value)d Zeichen " +"besteht. (Er besteht aus %(show_value)d Zeichen.)" +msgstr[1] "" +"Bitte sicherstellen, dass der Wert aus höchstens %(limit_value)d Zeichen " +"besteht. (Er besteht aus %(show_value)d Zeichen.)" + +msgid "Enter a number." +msgstr "Bitte eine Zahl eingeben." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" +"Bitte sicherstellen, dass der Wert höchstens %(max)s Ziffer enthält." +msgstr[1] "" +"Bitte sicherstellen, dass der Wert höchstens %(max)s Ziffern enthält." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +"Bitte sicherstellen, dass der Wert höchstens %(max)s Dezimalstelle enthält." +msgstr[1] "" +"Bitte sicherstellen, dass der Wert höchstens %(max)s Dezimalstellen enthält." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Bitte sicherstellen, dass der Wert höchstens %(max)s Ziffer vor dem Komma " +"enthält." +msgstr[1] "" +"Bitte sicherstellen, dass der Wert höchstens %(max)s Ziffern vor dem Komma " +"enthält." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Dateiendung „%(extension)s“ ist nicht erlaubt. Erlaubte Dateiendungen sind: " +"„%(allowed_extensions)s“." + +msgid "Null characters are not allowed." +msgstr "Nullzeichen sind nicht erlaubt." + +msgid "and" +msgstr "und" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s mit diesem %(field_labels)s existiert bereits." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Bedingung „%(name)s“ ist nicht erfüllt." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Wert %(value)r ist keine gültige Option." + +msgid "This field cannot be null." +msgstr "Dieses Feld darf nicht null sein." + +msgid "This field cannot be blank." +msgstr "Dieses Feld darf nicht leer sein." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s mit diesem %(field_label)s existiert bereits." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s muss für %(date_field_label)s %(lookup_type)s eindeutig sein." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Feldtyp: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "Wert „%(value)s“ muss entweder True oder False sein." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "Wert „%(value)s“ muss True, False oder None sein." + +msgid "Boolean (Either True or False)" +msgstr "Boolescher Wert (True oder False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Zeichenkette (bis zu %(max_length)s Zeichen)" + +msgid "String (unlimited)" +msgstr "Zeichenkette (unlimitiert)" + +msgid "Comma-separated integers" +msgstr "Kommaseparierte Liste von Ganzzahlen" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"Wert „%(value)s“ hat ein ungültiges Datumsformat. Es muss YYYY-MM-DD " +"entsprechen." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"Wert „%(value)s“ hat das korrekte Format (YYYY-MM-DD) aber ein ungültiges " +"Datum." + +msgid "Date (without time)" +msgstr "Datum (ohne Uhrzeit)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"Wert „%(value)s“ hat ein ungültiges Format. Es muss YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] entsprechen." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"Wert „%(value)s“ hat das korrekte Format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) aber eine ungültige Zeit-/Datumsangabe." + +msgid "Date (with time)" +msgstr "Datum (mit Uhrzeit)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "Wert „%(value)s“ muss eine Dezimalzahl sein." + +msgid "Decimal number" +msgstr "Dezimalzahl" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"Wert „%(value)s“ hat ein ungültiges Format. Es muss der Form [DD] [HH:" +"[MM:]]ss[.uuuuuu] entsprechen." + +msgid "Duration" +msgstr "Zeitspanne" + +msgid "Email address" +msgstr "E-Mail-Adresse" + +msgid "File path" +msgstr "Dateipfad" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "Wert „%(value)s“ muss eine Fließkommazahl sein." + +msgid "Floating point number" +msgstr "Gleitkommazahl" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "Wert „%(value)s“ muss eine Ganzzahl sein." + +msgid "Integer" +msgstr "Ganzzahl" + +msgid "Big (8 byte) integer" +msgstr "Große Ganzzahl (8 Byte)" + +msgid "Small integer" +msgstr "Kleine Ganzzahl" + +msgid "IPv4 address" +msgstr "IPv4-Adresse" + +msgid "IP address" +msgstr "IP-Adresse" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "Wert „%(value)s“ muss entweder None, True oder False sein." + +msgid "Boolean (Either True, False or None)" +msgstr "Boolescher Wert (True, False oder None)" + +msgid "Positive big integer" +msgstr "Positive große Ganzzahl" + +msgid "Positive integer" +msgstr "Positive Ganzzahl" + +msgid "Positive small integer" +msgstr "Positive kleine Ganzzahl" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Kürzel (bis zu %(max_length)s)" + +msgid "Text" +msgstr "Text" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"Wert „%(value)s“ hat ein ungültiges Format. Es muss HH:MM[:ss[.uuuuuu]] " +"entsprechen." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"Wert „%(value)s“ hat das korrekte Format (HH:MM[:ss[.uuuuuu]]), aber ist " +"eine ungültige Zeitangabe." + +msgid "Time" +msgstr "Zeit" + +msgid "URL" +msgstr "Adresse (URL)" + +msgid "Raw binary data" +msgstr "Binärdaten" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "Wert „%(value)s“ ist keine gültige UUID." + +msgid "Universally unique identifier" +msgstr "Universally Unique Identifier" + +msgid "File" +msgstr "Datei" + +msgid "Image" +msgstr "Bild" + +msgid "A JSON object" +msgstr "Ein JSON-Objekt" + +msgid "Value must be valid JSON." +msgstr "Wert muss gültiges JSON sein." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "Objekt vom Typ %(model)s mit %(field)s %(value)r existiert nicht." + +msgid "Foreign Key (type determined by related field)" +msgstr "Fremdschlüssel (Typ definiert durch verknüpftes Feld)" + +msgid "One-to-one relationship" +msgstr "1:1-Beziehung" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s-Beziehung" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s-Beziehungen" + +msgid "Many-to-many relationship" +msgstr "n:m-Beziehung" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Dieses Feld ist zwingend erforderlich." + +msgid "Enter a whole number." +msgstr "Bitte eine ganze Zahl eingeben." + +msgid "Enter a valid date." +msgstr "Bitte ein gültiges Datum eingeben." + +msgid "Enter a valid time." +msgstr "Bitte eine gültige Uhrzeit eingeben." + +msgid "Enter a valid date/time." +msgstr "Bitte ein gültiges Datum und Uhrzeit eingeben." + +msgid "Enter a valid duration." +msgstr "Bitte eine gültige Zeitspanne eingeben." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Die Anzahl der Tage muss zwischen {min_days} und {max_days} sein." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" +"Es wurde keine Datei übertragen. Überprüfen Sie das Encoding des Formulars." + +msgid "No file was submitted." +msgstr "Es wurde keine Datei übertragen." + +msgid "The submitted file is empty." +msgstr "Die übertragene Datei ist leer." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Bitte sicherstellen, dass der Dateiname aus höchstens %(max)d Zeichen " +"besteht. (Er besteht aus %(length)d Zeichen.)" +msgstr[1] "" +"Bitte sicherstellen, dass der Dateiname aus höchstens %(max)d Zeichen " +"besteht. (Er besteht aus %(length)d Zeichen.)" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Bitte wählen Sie entweder eine Datei aus oder wählen Sie „Löschen“, nicht " +"beides." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Bitte ein gültiges Bild hochladen. Die hochgeladene Datei ist kein Bild oder " +"ist defekt." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Bitte eine gültige Auswahl treffen. %(value)s ist keine gültige Auswahl." + +msgid "Enter a list of values." +msgstr "Bitte eine Liste mit Werten eingeben." + +msgid "Enter a complete value." +msgstr "Bitte einen vollständigen Wert eingeben." + +msgid "Enter a valid UUID." +msgstr "Bitte eine gültige UUID eingeben." + +msgid "Enter a valid JSON." +msgstr "Bitte ein gültiges JSON-Objekt eingeben." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Verstecktes Feld %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"Daten für das Management-Formular fehlen oder wurden manipuliert. Fehlende " +"Felder: %(field_names)s. Bitte erstellen Sie einen Bug-Report falls der " +"Fehler dauerhaft besteht." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Bitte höchstens %(num)d Forumlar abschicken." +msgstr[1] "Bitte höchstens %(num)d Formulare abschicken." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Bitte mindestends %(num)d Formular abschicken." +msgstr[1] "Bitte mindestens %(num)d Formulare abschicken." + +msgid "Order" +msgstr "Reihenfolge" + +msgid "Delete" +msgstr "Löschen" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Bitte die doppelten Daten für %(field)s korrigieren." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Bitte die doppelten Daten für %(field)s korrigieren, das eindeutig sein muss." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Bitte die doppelten Daten für %(field_name)s korrigieren, da es für " +"%(lookup)s in %(date_field)s eindeutig sein muss." + +msgid "Please correct the duplicate values below." +msgstr "Bitte die unten aufgeführten doppelten Werte korrigieren." + +msgid "The inline value did not match the parent instance." +msgstr "Der Inline-Wert passt nicht zur übergeordneten Instanz." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Bitte eine gültige Auswahl treffen. Dies ist keine gültige Auswahl." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "„%(pk)s“ ist kein gültiger Wert." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s konnte mit der Zeitzone %(current_timezone)s nicht eindeutig " +"interpretiert werden, da es doppeldeutig oder eventuell inkorrekt ist." + +msgid "Clear" +msgstr "Zurücksetzen" + +msgid "Currently" +msgstr "Derzeit" + +msgid "Change" +msgstr "Ändern" + +msgid "Unknown" +msgstr "Unbekannt" + +msgid "Yes" +msgstr "Ja" + +msgid "No" +msgstr "Nein" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "Ja,Nein,Vielleicht" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d Byte" +msgstr[1] "%(size)d Bytes" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "nachm." + +msgid "a.m." +msgstr "vorm." + +msgid "PM" +msgstr "nachm." + +msgid "AM" +msgstr "vorm." + +msgid "midnight" +msgstr "Mitternacht" + +msgid "noon" +msgstr "Mittag" + +msgid "Monday" +msgstr "Montag" + +msgid "Tuesday" +msgstr "Dienstag" + +msgid "Wednesday" +msgstr "Mittwoch" + +msgid "Thursday" +msgstr "Donnerstag" + +msgid "Friday" +msgstr "Freitag" + +msgid "Saturday" +msgstr "Samstag" + +msgid "Sunday" +msgstr "Sonntag" + +msgid "Mon" +msgstr "Mo" + +msgid "Tue" +msgstr "Di" + +msgid "Wed" +msgstr "Mi" + +msgid "Thu" +msgstr "Do" + +msgid "Fri" +msgstr "Fr" + +msgid "Sat" +msgstr "Sa" + +msgid "Sun" +msgstr "So" + +msgid "January" +msgstr "Januar" + +msgid "February" +msgstr "Februar" + +msgid "March" +msgstr "März" + +msgid "April" +msgstr "April" + +msgid "May" +msgstr "Mai" + +msgid "June" +msgstr "Juni" + +msgid "July" +msgstr "Juli" + +msgid "August" +msgstr "August" + +msgid "September" +msgstr "September" + +msgid "October" +msgstr "Oktober" + +msgid "November" +msgstr "November" + +msgid "December" +msgstr "Dezember" + +msgid "jan" +msgstr "Jan" + +msgid "feb" +msgstr "Feb" + +msgid "mar" +msgstr "Mär" + +msgid "apr" +msgstr "Apr" + +msgid "may" +msgstr "Mai" + +msgid "jun" +msgstr "Jun" + +msgid "jul" +msgstr "Jul" + +msgid "aug" +msgstr "Aug" + +msgid "sep" +msgstr "Sep" + +msgid "oct" +msgstr "Okt" + +msgid "nov" +msgstr "Nov" + +msgid "dec" +msgstr "Dez" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "März" + +msgctxt "abbrev. month" +msgid "April" +msgstr "April" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Mai" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Juni" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Juli" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Aug." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Sept." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Okt." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dez." + +msgctxt "alt. month" +msgid "January" +msgstr "Januar" + +msgctxt "alt. month" +msgid "February" +msgstr "Februar" + +msgctxt "alt. month" +msgid "March" +msgstr "März" + +msgctxt "alt. month" +msgid "April" +msgstr "April" + +msgctxt "alt. month" +msgid "May" +msgstr "Mai" + +msgctxt "alt. month" +msgid "June" +msgstr "Juni" + +msgctxt "alt. month" +msgid "July" +msgstr "Juli" + +msgctxt "alt. month" +msgid "August" +msgstr "August" + +msgctxt "alt. month" +msgid "September" +msgstr "September" + +msgctxt "alt. month" +msgid "October" +msgstr "Oktober" + +msgctxt "alt. month" +msgid "November" +msgstr "November" + +msgctxt "alt. month" +msgid "December" +msgstr "Dezember" + +msgid "This is not a valid IPv6 address." +msgstr "Dies ist keine gültige IPv6-Adresse." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "oder" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d Jahr" +msgstr[1] "%(num)d Jahre" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d Monat" +msgstr[1] "%(num)d Monate" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d Woche" +msgstr[1] "%(num)d Wochen" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d Tag" +msgstr[1] "%(num)d Tage" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d Stunde" +msgstr[1] "%(num)d Stunden" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d Minute" +msgstr[1] "%(num)d Minuten" + +msgid "Forbidden" +msgstr "Verboten" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF-Verifizierung fehlgeschlagen. Anfrage abgebrochen." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Sie sehen diese Fehlermeldung, da diese HTTPS-Seite einen „Referer“-Header " +"von Ihrem Webbrowser erwartet, aber keinen erhalten hat. Dieser Header ist " +"aus Sicherheitsgründen notwendig, um sicherzustellen, dass Ihr Webbrowser " +"nicht von Dritten missbraucht wird." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Falls Sie Ihren Webbrowser so konfiguriert haben, dass „Referer“-Header " +"nicht gesendet werden, müssen Sie diese Funktion mindestens für diese Seite, " +"für sichere HTTPS-Verbindungen oder für „Same-Origin“-Verbindungen " +"reaktivieren." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Wenn der Tag „“ oder der " +"„Referrer-Policy: no-referrer“-Header verwendet wird, entfernen Sie sie " +"bitte. Der „Referer“-Header wird zur korrekten CSRF-Verifizierung benötigt. " +"Falls es datenschutzrechtliche Gründe gibt, benutzen Sie bitte Alternativen " +"wie „“ für Links zu Drittseiten." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Sie sehen Diese Nachricht, da diese Seite einen CSRF-Cookie beim Verarbeiten " +"von Formulardaten benötigt. Dieses Cookie ist aus Sicherheitsgründen " +"notwendig, um sicherzustellen, dass Ihr Webbrowser nicht von Dritten " +"missbraucht wird." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Falls Sie Cookies in Ihren Webbrowser deaktiviert haben, müssen Sie sie " +"mindestens für diese Seite oder für „Same-Origin“-Verbindungen reaktivieren." + +msgid "More information is available with DEBUG=True." +msgstr "Mehr Information ist verfügbar mit DEBUG=True." + +msgid "No year specified" +msgstr "Kein Jahr angegeben" + +msgid "Date out of range" +msgstr "Datum außerhalb des zulässigen Bereichs" + +msgid "No month specified" +msgstr "Kein Monat angegeben" + +msgid "No day specified" +msgstr "Kein Tag angegeben" + +msgid "No week specified" +msgstr "Keine Woche angegeben" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Keine %(verbose_name_plural)s verfügbar" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"In der Zukunft liegende %(verbose_name_plural)s sind nicht verfügbar, da " +"%(class_name)s.allow_future auf False gesetzt ist." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Ungültiges Datum „%(datestr)s“ für das Format „%(format)s“" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Konnte keine %(verbose_name)s mit diesen Parametern finden." + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" +"Weder ist dies die letzte Seite („last“) noch konnte sie in einen " +"ganzzahligen Wert umgewandelt werden." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Ungültige Seite (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Leere Liste und „%(class_name)s.allow_empty“ ist False." + +msgid "Directory indexes are not allowed here." +msgstr "Dateilisten sind untersagt." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "„%(path)s“ ist nicht vorhanden" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Verzeichnis %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Die Installation war erfolgreich. Herzlichen Glückwunsch!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Versionshinweise für Django " +"%(version)s anzeigen" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Diese Seite ist sichtbar weil in der Settings-Datei DEBUG = True steht und die URLs noch nicht konfiguriert " +"sind." + +msgid "Django Documentation" +msgstr "Django-Dokumentation" + +msgid "Topics, references, & how-to’s" +msgstr "Themen, Referenz, & Kurzanleitungen" + +msgid "Tutorial: A Polling App" +msgstr "Tutorial: Eine Umfrage-App" + +msgid "Get started with Django" +msgstr "Los geht's mit Django" + +msgid "Django Community" +msgstr "Django-Community" + +msgid "Connect, get help, or contribute" +msgstr "Nimm Kontakt auf, erhalte Hilfe oder arbeite an Django mit" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/de/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/de/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/de/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/de/formats.py new file mode 100644 index 0000000..45953ce --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/de/formats.py @@ -0,0 +1,29 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j. F Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = "j. F Y H:i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j. F" +SHORT_DATE_FORMAT = "d.m.Y" +SHORT_DATETIME_FORMAT = "d.m.Y H:i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d.%m.%Y", # '25.10.2006' + "%d.%m.%y", # '25.10.06' + # "%d. %B %Y", # '25. October 2006' + # "%d. %b. %Y", # '25. Oct. 2006' +] +DATETIME_INPUT_FORMATS = [ + "%d.%m.%Y %H:%M:%S", # '25.10.2006 14:30:59' + "%d.%m.%Y %H:%M:%S.%f", # '25.10.2006 14:30:59.000200' + "%d.%m.%Y %H:%M", # '25.10.2006 14:30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/de_CH/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/de_CH/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/de_CH/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/de_CH/formats.py new file mode 100644 index 0000000..f42dd48 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/de_CH/formats.py @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j. F Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = "j. F Y H:i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j. F" +SHORT_DATE_FORMAT = "d.m.Y" +SHORT_DATETIME_FORMAT = "d.m.Y H:i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d.%m.%Y", # '25.10.2006' + "%d.%m.%y", # '25.10.06' + # "%d. %B %Y", # '25. October 2006' + # "%d. %b. %Y", # '25. Oct. 2006' +] +DATETIME_INPUT_FORMATS = [ + "%d.%m.%Y %H:%M:%S", # '25.10.2006 14:30:59' + "%d.%m.%Y %H:%M:%S.%f", # '25.10.2006 14:30:59.000200' + "%d.%m.%Y %H:%M", # '25.10.2006 14:30' +] + +# these are the separators for non-monetary numbers. For monetary numbers, +# the DECIMAL_SEPARATOR is a . (decimal point) and the THOUSAND_SEPARATOR is a +# ' (single quote). +# For details, please refer to the documentation and the following link: +# https://www.bk.admin.ch/bk/de/home/dokumentation/sprachen/hilfsmittel-textredaktion/schreibweisungen.html +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "\xa0" # non-breaking space +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/dsb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/dsb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..645e6c7 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/dsb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/dsb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/dsb/LC_MESSAGES/django.po new file mode 100644 index 0000000..e7c0fb6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/dsb/LC_MESSAGES/django.po @@ -0,0 +1,1385 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Michael Wolf , 2016-2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Michael Wolf , 2016-2023\n" +"Language-Team: Lower Sorbian (http://app.transifex.com/django/django/" +"language/dsb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: dsb\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || " +"n%100==4 ? 2 : 3);\n" + +msgid "Afrikaans" +msgstr "Afrikaanšćina" + +msgid "Arabic" +msgstr "Arabšćina" + +msgid "Algerian Arabic" +msgstr "Algeriska arabšćina" + +msgid "Asturian" +msgstr "Asturišćina" + +msgid "Azerbaijani" +msgstr "Azerbajdžanišćina" + +msgid "Bulgarian" +msgstr "Bulgaršćina" + +msgid "Belarusian" +msgstr "Běłorušćina" + +msgid "Bengali" +msgstr "Bengalšćina" + +msgid "Breton" +msgstr "Bretońšćina" + +msgid "Bosnian" +msgstr "Bosnišćina" + +msgid "Catalan" +msgstr "Katalańšćina" + +msgid "Central Kurdish (Sorani)" +msgstr "Centralna kurdišćina (Sorani)" + +msgid "Czech" +msgstr "Češćina" + +msgid "Welsh" +msgstr "Kymrišćina" + +msgid "Danish" +msgstr "Dańšćina" + +msgid "German" +msgstr "Nimšćina" + +msgid "Lower Sorbian" +msgstr "Dolnoserbšćina" + +msgid "Greek" +msgstr "Grichišćina" + +msgid "English" +msgstr "Engelšćina" + +msgid "Australian English" +msgstr "Awstralska engelšćina" + +msgid "British English" +msgstr "Britiska engelšćina" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Špańšćina" + +msgid "Argentinian Spanish" +msgstr "Argentinska špańšćina" + +msgid "Colombian Spanish" +msgstr "Kolumbiska špańšćina" + +msgid "Mexican Spanish" +msgstr "Mexikańska špańšćina" + +msgid "Nicaraguan Spanish" +msgstr "Nikaraguaska špańšćina" + +msgid "Venezuelan Spanish" +msgstr "Venezolaniska špańšćina" + +msgid "Estonian" +msgstr "Estnišćina" + +msgid "Basque" +msgstr "Baskišćina" + +msgid "Persian" +msgstr "Persišćina" + +msgid "Finnish" +msgstr "Finšćina" + +msgid "French" +msgstr "Francojšćina" + +msgid "Frisian" +msgstr "Frizišćina" + +msgid "Irish" +msgstr "Iršćina" + +msgid "Scottish Gaelic" +msgstr "Šotiska gelišćina" + +msgid "Galician" +msgstr "Galicišćina" + +msgid "Hebrew" +msgstr "Hebrejšćina" + +msgid "Hindi" +msgstr "Hindišćina" + +msgid "Croatian" +msgstr "Chorwatšćina" + +msgid "Upper Sorbian" +msgstr "Górnoserbšćina" + +msgid "Hungarian" +msgstr "Hungoršćina" + +msgid "Armenian" +msgstr "Armeńšćina" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonešćina" + +msgid "Igbo" +msgstr "Igbo" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Islandšćina" + +msgid "Italian" +msgstr "Italšćina" + +msgid "Japanese" +msgstr "Japańšćina" + +msgid "Georgian" +msgstr "Georgišćina" + +msgid "Kabyle" +msgstr "Kabylšćina" + +msgid "Kazakh" +msgstr "Kazachšćina" + +msgid "Khmer" +msgstr "Rěc Khmerow" + +msgid "Kannada" +msgstr "Kannadišćina" + +msgid "Korean" +msgstr "Korejańšćina" + +msgid "Kyrgyz" +msgstr "Kirgišćina" + +msgid "Luxembourgish" +msgstr "Luxemburgšćina" + +msgid "Lithuanian" +msgstr "Litawšćina" + +msgid "Latvian" +msgstr "Letišćina" + +msgid "Macedonian" +msgstr "Makedońšćina" + +msgid "Malayalam" +msgstr "Malajalam" + +msgid "Mongolian" +msgstr "Mongolšćina" + +msgid "Marathi" +msgstr "Marathi" + +msgid "Malay" +msgstr "Malayzišćina" + +msgid "Burmese" +msgstr "Myanmaršćina" + +msgid "Norwegian Bokmål" +msgstr "Norwegski Bokmål" + +msgid "Nepali" +msgstr "Nepalšćina" + +msgid "Dutch" +msgstr "¨Nižozemšćina" + +msgid "Norwegian Nynorsk" +msgstr "Norwegski Nynorsk" + +msgid "Ossetic" +msgstr "Osetšćina" + +msgid "Punjabi" +msgstr "Pundžabi" + +msgid "Polish" +msgstr "Pólšćina" + +msgid "Portuguese" +msgstr "Portugišćina" + +msgid "Brazilian Portuguese" +msgstr "Brazilska portugišćina" + +msgid "Romanian" +msgstr "Rumunšćina" + +msgid "Russian" +msgstr "Rušćina" + +msgid "Slovak" +msgstr "Słowakšćina" + +msgid "Slovenian" +msgstr "Słowjeńšćina" + +msgid "Albanian" +msgstr "Albanšćina" + +msgid "Serbian" +msgstr "Serbišćina" + +msgid "Serbian Latin" +msgstr "Serbišćina, łatyńska" + +msgid "Swedish" +msgstr "Šwedšćina" + +msgid "Swahili" +msgstr "Suahelšćina" + +msgid "Tamil" +msgstr "Tamilšćina" + +msgid "Telugu" +msgstr "Telugu" + +msgid "Tajik" +msgstr "Tadźikišćina" + +msgid "Thai" +msgstr "Thaišćina" + +msgid "Turkmen" +msgstr "Turkmeńšćina" + +msgid "Turkish" +msgstr "Turkojšćina" + +msgid "Tatar" +msgstr "Tataršćina" + +msgid "Udmurt" +msgstr "Udmurtšćina" + +msgid "Uyghur" +msgstr "Ujguršćina" + +msgid "Ukrainian" +msgstr "Ukrainšćina" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "Uzbekšćina" + +msgid "Vietnamese" +msgstr "Vietnamšćina" + +msgid "Simplified Chinese" +msgstr "Zjadnorjona chinšćina" + +msgid "Traditional Chinese" +msgstr "Tradicionelna chinšćina" + +msgid "Messages" +msgstr "Powěsći" + +msgid "Site Maps" +msgstr "Wopśimjeśowy pśeglěd sedła" + +msgid "Static Files" +msgstr "Statiske dataje" + +msgid "Syndication" +msgstr "Syndikacija" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Toś ten numer boka njejo ceła licba" + +msgid "That page number is less than 1" +msgstr "Numer boka jo mjeńšy ako 1" + +msgid "That page contains no results" +msgstr "Toś ten bok njewopśimujo wuslědki" + +msgid "Enter a valid value." +msgstr "Zapódajśo płaśiwu gódnotu." + +msgid "Enter a valid URL." +msgstr "Zapódajśo płaśiwy URL." + +msgid "Enter a valid integer." +msgstr "Zapódajśo płaśiwu cełu licbu." + +msgid "Enter a valid email address." +msgstr "Zapódajśo płaśiwu e-mailowu adresu." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Zapódajśo płaśiwe „adresowe mě“, kótarež jano wopśimujo pismiki, licby, " +"pódsmužki abo wězawki." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Zapódajśo płaśiwe „adresowe mě“, kótarež jano wopśimujo unicodowe pismiki, " +"licby, pódmužki abo wězawki." + +msgid "Enter a valid IPv4 address." +msgstr "Zapódajśo płaśiwu IPv4-adresu." + +msgid "Enter a valid IPv6 address." +msgstr "Zapódajśo płaśiwu IPv6-adresu." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Zapódajśo płaśiwu IPv4- abo IPv6-adresu." + +msgid "Enter only digits separated by commas." +msgstr "Zapódajśo jano cyfry źělone pśez komy." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Zawěsććo toś tu gódnotu jo %(limit_value)s (jo %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" +"Zawěsććo, až toś ta gódnota jo mjeńša ako abo to samske ako %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" +"Zawěsććo, až toś ta gódnota jo wětša ako abo to samske ako %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" +"Zawěsććo, až toś gódnota jo wjelesere kšacoweje wjelikosći %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"Zawěsććo, až toś ta gódnota jo wjele wót kšacoweje wjelikosći " +"%(limit_value)s, zachopinajucy z %(offset)s, na pś. %(offset)s, " +"%(valid_value1)s, %(valid_value2)s a tak dalej." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Zawěsććo, až toś ta gódnota ma nanejmjenjej %(limit_value)d znamuško (ma " +"%(show_value)d)." +msgstr[1] "" +"Zawěsććo, až toś ta gódnota ma nanejmjenjej %(limit_value)d znamušce (ma " +"%(show_value)d)." +msgstr[2] "" +"Zawěsććo, až toś ta gódnota ma nanejmjenjej %(limit_value)d znamuška (ma " +"%(show_value)d)." +msgstr[3] "" +"Zawěsććo, až toś ta gódnota ma nanejmjenjej %(limit_value)d znamuškow (ma " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Zawěććo, až toś ta gódnota ma maksimalnje %(limit_value)d znamuško (ma " +"%(show_value)d)." +msgstr[1] "" +"Zawěććo, až toś ta gódnota ma maksimalnje %(limit_value)d znamušce (ma " +"%(show_value)d)." +msgstr[2] "" +"Zawěććo, až toś ta gódnota ma maksimalnje %(limit_value)d znamuška (ma " +"%(show_value)d)." +msgstr[3] "" +"Zawěććo, až toś ta gódnota ma maksimalnje %(limit_value)d znamuškow (ma " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Zapódajśo licbu." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Zawěsććo, až njejo wěcej ako %(max)s cyfry dogromady." +msgstr[1] "Zawěsććo, až njejo wěcej ako %(max)s cyfrowu dogromady." +msgstr[2] "Zawěsććo, až njejo wěcej ako %(max)s cyfrow dogromady." +msgstr[3] "Zawěsććo, až njejo wěcej ako %(max)s cyfrow dogromady." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Zawěsććo, až njejo wěcej ako %(max)s decimalnego městna." +msgstr[1] "Zawěsććo, až njejo wěcej ako %(max)s decimalneju městnowu." +msgstr[2] "Zawěsććo, až njejo wěcej ako %(max)s decimalnych městnow." +msgstr[3] "Zawěsććo, až njejo wěcej ako %(max)s decimalnych městnow." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "Zawěsććo, až njejo wěcej ako %(max)s cyfry pśed decimalneju komu." +msgstr[1] "Zawěsććo, až njejo wěcej ako %(max)s cyfrowu pśed decimalneju komu." +msgstr[2] "Zawěsććo, až njejo wěcej ako %(max)s cyfrow pśed decimalneju komu." +msgstr[3] "Zawěsććo, až njejo wěcej ako %(max)s cyfrow pśed decimalneju komu." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Datajowy sufiks „%(extension)s“ njejo dowólony. Dowólone sufikse su: " +"%(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Znamuška nul njejsu dowólone." + +msgid "and" +msgstr "a" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s z toś tym %(field_labels)s južo eksistěrujo." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Wobranicowanje \"%(name)s\" jo pśestupjone." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Gódnota %(value)r njejo płaśiwa wóleńska móžnosć." + +msgid "This field cannot be null." +msgstr "Toś to pólo njamóžo nul byś." + +msgid "This field cannot be blank." +msgstr "Toś to pólo njamóžo prozne byś." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s z toś tym %(field_label)s južo eksistěrujo." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s musy za %(date_field_label)s %(lookup_type)s jadnorazowy byś." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Typ póla: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "Gódnota „%(value)s“ musy pak True pak False byś." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "Gódnota „%(value)s“ musy pak True, False pak None byś." + +msgid "Boolean (Either True or False)" +msgstr "Boolean (pak True pak False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Znamuškowy rjeśazk (až %(max_length)s)" + +msgid "String (unlimited)" +msgstr "Znamuškowy rjeśazk (njewobgranicowany)" + +msgid "Comma-separated integers" +msgstr "Pśez komu źělone cełe licby" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"Gódnota „%(value)s“ ma njepłaśiwy datumowy format. Musy we formaśe DD.MM." +"YYYY byś." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"Gódnota „%(value)s“ ma korektny format (DD.MM.YYYY), ale jo njepłaśiwy datum." + +msgid "Date (without time)" +msgstr "Datum (bźez casa)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"Gódnota „%(value)s“ ma njepłaśiwy format. Musy w formaśe DD.MM.YYYY HH:MM[:" +"ss[.uuuuuu]][TZ] byś." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"Gódnota „%(value)s“ ma korektny format (DD.MM.YYYY HH:MM[:ss[.uuuuuu]][TZ]), " +"ale jo njepłaśiwy datum/cas." + +msgid "Date (with time)" +msgstr "Datum (z casom)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "Gódnota „%(value)s“ musy decimalna licba byś." + +msgid "Decimal number" +msgstr "Decimalna licba" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"Gódnota „%(value)s“ ma njepłaśiwy format. Musy we formaśe [DD] " +"[[HH:]MM:]ss[.uuuuuu] byś." + +msgid "Duration" +msgstr "Traśe" + +msgid "Email address" +msgstr "E-mailowa adresa" + +msgid "File path" +msgstr "Datajowa sćažka" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "Gódnota „%(value)s“ musy typ float měś." + +msgid "Floating point number" +msgstr "Licba běžeceje komy" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "Gódnota „%(value)s“ musy ceła licba byś." + +msgid "Integer" +msgstr "Integer" + +msgid "Big (8 byte) integer" +msgstr "Big (8 bajtow) integer" + +msgid "Small integer" +msgstr "Mała ceła licba" + +msgid "IPv4 address" +msgstr "IPv4-adresa" + +msgid "IP address" +msgstr "IP-adresa" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "Gódnota „%(value)s“ musy pak None, True pak False byś." + +msgid "Boolean (Either True, False or None)" +msgstr "Boolean (pak True, False pak None)" + +msgid "Positive big integer" +msgstr "Pozitiwna wjelika ceła licba" + +msgid "Positive integer" +msgstr "Pozitiwna ceła licba" + +msgid "Positive small integer" +msgstr "Pozitiwna mała ceła licba" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Adresowe mě (až %(max_length)s)" + +msgid "Text" +msgstr "Tekst" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"Gódnota „%(value)s“ ma njepłaśiwy format. Musy w formaśe HH:MM[:ss[." +"uuuuuu]] byś." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"Gódnota „%(value)s“ ma korektny format (HH:MM[:ss[.uuuuuu]]), ale jo " +"njepłaśiwy cas." + +msgid "Time" +msgstr "Cas" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Gropne binarne daty" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "„%(value)s“ njejo płaśiwy UUID." + +msgid "Universally unique identifier" +msgstr "Uniwerselnje jadnorazowy identifikator" + +msgid "File" +msgstr "Dataja" + +msgid "Image" +msgstr "Woraz" + +msgid "A JSON object" +msgstr "JSON-objekt" + +msgid "Value must be valid JSON." +msgstr "Gódnota musy płaśiwy JSON byś." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "Instanca %(model)s z %(field)s %(value)r njeeksistěrujo." + +msgid "Foreign Key (type determined by related field)" +msgstr "Cuzy kluc (typ póstaja se pśez wótpowědne pólo)" + +msgid "One-to-one relationship" +msgstr "Póśěg jaden jaden" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "Póśěg %(from)s-%(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "Póśěgi %(from)s-%(to)s" + +msgid "Many-to-many relationship" +msgstr "Póśěg wjele wjele" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Toś to pólo jo trěbne." + +msgid "Enter a whole number." +msgstr "Zapódajśo cełu licbu." + +msgid "Enter a valid date." +msgstr "Zapódajśo płaśiwy datum." + +msgid "Enter a valid time." +msgstr "Zapódajśo płaśiwy cas." + +msgid "Enter a valid date/time." +msgstr "Zapódajśo płaśiwy datum/cas." + +msgid "Enter a valid duration." +msgstr "Zapódaśe płaśiwe traśe." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Licba dnjow musy mjazy {min_days} a {max_days} byś." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" +"Dataja njejo se wótpósłała. Pśeglědujśo koděrowański typ na formularje. " + +msgid "No file was submitted." +msgstr "Žedna dataja jo se wótpósłała." + +msgid "The submitted file is empty." +msgstr "Wótpósłana dataja jo prozna." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Zawěsććo, až toś to datajowe mě ma maksimalnje %(max)d znamuško (ma " +"%(length)d)." +msgstr[1] "" +"Zawěsććo, až toś to datajowe mě ma maksimalnje %(max)d znamušce (ma " +"%(length)d)." +msgstr[2] "" +"Zawěsććo, až toś to datajowe mě ma maksimalnje %(max)d znamuška (ma " +"%(length)d)." +msgstr[3] "" +"Zawěsććo, až toś to datajowe mě ma maksimalnje %(max)d znamuškow (ma " +"%(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Pšosym pak wótpósćelśo dataju pak stajśo kokulku do kontrolnego kašćika, " +"njecyńśo wobej." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Nagrajśo płaśiwy wobraz. Dataja, kótaruž sćo nagrał, pak njejo wobraz był " +"pak jo wobškóźony wobraz." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Wubjeŕśo płaśiwu wóleńsku móžnosć. %(value)s njejo jadna z k dispoziciji " +"stojecych wóleńskich móžnosćow." + +msgid "Enter a list of values." +msgstr "Zapódajśo lisćinu gódnotow." + +msgid "Enter a complete value." +msgstr "Zapódajśo dopołnu gódnotu." + +msgid "Enter a valid UUID." +msgstr "Zapódajśo płaśiwy UUID." + +msgid "Enter a valid JSON." +msgstr "Zapódajśo płaśiwy JSON." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Schowane pólo %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"Daty ManagementForm feluju abo su wobškóźone. Felujuce póla: " +"%(field_names)s. Móžośo zmólkowu rozpšawu pisaś, jolic problem dalej " +"eksistěrujo." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Pšosym wótposćelśo maksimalnje %(num)d formular." +msgstr[1] "Pšosym wótposćelśo maksimalnje %(num)d formulara." +msgstr[2] "Pšosym wótposćelśo maksimalnje %(num)d formulary." +msgstr[3] "Pšosym wótposćelśo maksimalnje %(num)d formularow." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Pšosym wótposćelśo minimalnje %(num)d formular." +msgstr[1] "Pšosym wótposćelśo minimalnje %(num)d formulara." +msgstr[2] "Pšosym wótposćelśo minimalnje %(num)d formulary." +msgstr[3] "Pšosym wótposćelśo minimalnje %(num)d formularow." + +msgid "Order" +msgstr "Rěd" + +msgid "Delete" +msgstr "Lašowaś" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Pšosym korigěrujśo dwójne daty za %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Pšosym korigěrujśo dwójne daty za %(field)s, kótarež muse jadnorazowe byś." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Pšosym korigěrujśo dwójne daty za %(field_name)s, kótarež muse za %(lookup)s " +"w %(date_field)s jadnorazowe byś." + +msgid "Please correct the duplicate values below." +msgstr "Pšosym korigěrujśo slědujuce dwójne gódnoty." + +msgid "The inline value did not match the parent instance." +msgstr "Gódnota inline nadrědowanej instance njewótpowědujo." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Wubjeŕśo płaśiwu wóleńsku móžnosć. Toś ta wóleńska móžnosć njejo žedna z " +"wóleńskich móžnosćow." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "„%(pk)s“ njejo płaśiwa gódnota." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s njedajo se w casowej conje %(current_timezone)s " +"interpretěrowaś; jo dwójozmysłowy abo snaź njeeksistěrujo." + +msgid "Clear" +msgstr "Lašowaś" + +msgid "Currently" +msgstr "Tuchylu" + +msgid "Change" +msgstr "Změniś" + +msgid "Unknown" +msgstr "Njeznaty" + +msgid "Yes" +msgstr "Jo" + +msgid "No" +msgstr "Ně" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "jo,ně,snaź" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d bajt" +msgstr[1] "%(size)d bajta" +msgstr[2] "%(size)d bajty" +msgstr[3] "%(size)d bajtow" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "wótpołdnja" + +msgid "a.m." +msgstr "dopołdnja" + +msgid "PM" +msgstr "wótpołdnja" + +msgid "AM" +msgstr "dopołdnja" + +msgid "midnight" +msgstr "połnoc" + +msgid "noon" +msgstr "połdnjo" + +msgid "Monday" +msgstr "Pónjeźele" + +msgid "Tuesday" +msgstr "Wałtora" + +msgid "Wednesday" +msgstr "Srjoda" + +msgid "Thursday" +msgstr "Stwórtk" + +msgid "Friday" +msgstr "Pětk" + +msgid "Saturday" +msgstr "Sobota" + +msgid "Sunday" +msgstr "Njeźela" + +msgid "Mon" +msgstr "Pón" + +msgid "Tue" +msgstr "Wał" + +msgid "Wed" +msgstr "Srj" + +msgid "Thu" +msgstr "Stw" + +msgid "Fri" +msgstr "Pět" + +msgid "Sat" +msgstr "Sob" + +msgid "Sun" +msgstr "Nje" + +msgid "January" +msgstr "Januar" + +msgid "February" +msgstr "Februar" + +msgid "March" +msgstr "Měrc" + +msgid "April" +msgstr "Apryl" + +msgid "May" +msgstr "Maj" + +msgid "June" +msgstr "Junij" + +msgid "July" +msgstr "Julij" + +msgid "August" +msgstr "Awgust" + +msgid "September" +msgstr "September" + +msgid "October" +msgstr "Oktober" + +msgid "November" +msgstr "Nowember" + +msgid "December" +msgstr "December" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "měr" + +msgid "apr" +msgstr "apr" + +msgid "may" +msgstr "maj" + +msgid "jun" +msgstr "jun" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "awg" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "okt" + +msgid "nov" +msgstr "now" + +msgid "dec" +msgstr "dec" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Měrc" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Apryl" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Maj" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Junij" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Julij" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Awg." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Sept." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Okt." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Now." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dec." + +msgctxt "alt. month" +msgid "January" +msgstr "Januar" + +msgctxt "alt. month" +msgid "February" +msgstr "Februar" + +msgctxt "alt. month" +msgid "March" +msgstr "Měrc" + +msgctxt "alt. month" +msgid "April" +msgstr "Apryl" + +msgctxt "alt. month" +msgid "May" +msgstr "Maj" + +msgctxt "alt. month" +msgid "June" +msgstr "Junij" + +msgctxt "alt. month" +msgid "July" +msgstr "Julij" + +msgctxt "alt. month" +msgid "August" +msgstr "Awgust" + +msgctxt "alt. month" +msgid "September" +msgstr "September" + +msgctxt "alt. month" +msgid "October" +msgstr "Oktober" + +msgctxt "alt. month" +msgid "November" +msgstr "Nowember" + +msgctxt "alt. month" +msgid "December" +msgstr "December" + +msgid "This is not a valid IPv6 address." +msgstr "To njejo płaśiwa IPv6-adresa." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "abo" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d lěto" +msgstr[1] "%(num)d lěśe" +msgstr[2] "%(num)d lěta" +msgstr[3] "%(num)d lět" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mjasec" +msgstr[1] "%(num)d mjaseca" +msgstr[2] "%(num)d mjasece" +msgstr[3] "%(num)dmjasecow" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d tyźeń" +msgstr[1] "%(num)d tyźenja" +msgstr[2] "%(num)d tyźenje" +msgstr[3] "%(num)d tyźenjow" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d źeń " +msgstr[1] "%(num)d dnja" +msgstr[2] "%(num)d dny" +msgstr[3] "%(num)d dnjow" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d góźina" +msgstr[1] "%(num)d góźinje" +msgstr[2] "%(num)d góźiny" +msgstr[3] "%(num)d góźin" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuta" +msgstr[1] "%(num)d minuśe" +msgstr[2] "%(num)d minuty" +msgstr[3] "%(num)d minutow" + +msgid "Forbidden" +msgstr "Zakazany" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF-pśeglědanje njejo se raźiło. Napšašowanje jo se pśetergnuło." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Wiźiśo toś tu powěźeńku, dokulaž toś to HTTPS-sedło trjeba \"Referer " +"header\", aby se pśez waš webwobglědowak słało, ale žedna njejo se pósłała. " +"Toś ta głowa jo trěbna z pśicynow wěstoty, aby so zawěsćiło, až waš " +"wobglědowak njekaprujo se wót tśeśich." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Jolic sćo swój wobglědowak tak konfigurěrował, aby se głowy 'Referer' " +"znjemóžnili, zmóžniśo je pšosym zasej, nanejmjenjej za toś to sedło, za " +"HTTPS-zwiski abo za napšašowanja 'same-origin'." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Jolic woznamjenje wužywaśo " +"abo głowu „Referrer-Policy: no-referrer“ zapśimujośo, wótwónoźćo je. CSRF-" +"šćit pomina se głowu „Referer“, aby striktnu kontrolu referera pśewjasć. " +"Jolic se wó swóju priwatnosć staraśo, wužywajśo alternatiwy ako za wótkazy k sedłam tśeśich." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Wiźiśo toś tu powěźeńku, dokulaž toś to HTTPS-sedło trjeba CSRF-cookie, aby " +"formulary wótpósłało. Toś ten cookie jo trěbna z pśicynow wěstoty, aby so " +"zawěsćiło, až waš wobglědowak njekaprujo se wót tśeśich." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Jolic sćo swój wobglědowak tak konfigurěrował, aby cookieje znjemóžnili, " +"zmóžniśo je pšosym zasej, nanejmjenjej za toś to sedło abo za napšašowanja " +"„same-origin“." + +msgid "More information is available with DEBUG=True." +msgstr "Dalšne informacije su k dispoziciji z DEBUG=True." + +msgid "No year specified" +msgstr "Žedno lěto pódane" + +msgid "Date out of range" +msgstr "Datum zwenka wobcerka" + +msgid "No month specified" +msgstr "Žeden mjasec pódany" + +msgid "No day specified" +msgstr "Žeden źeń pódany" + +msgid "No week specified" +msgstr "Žeden tyźeń pódany" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Žedne %(verbose_name_plural)s k dispoziciji" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Pśichodne %(verbose_name_plural)s njejo k dispoziciji, dokulaž " +"%(class_name)s.allow_future jo False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" +"Njepłaśiwy „%(format)s“ za datumowy znamuškowy rjeśazk „%(datestr)s“ pódany" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Žedno %(verbose_name)s namakane, kótarež wótpowědujo napšašowanjeju." + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Bok njejo „last“, ani njedajo se do „int“ konwertěrowaś." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Njepłaśiwy bok (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Prozna lisćina a „%(class_name)s.allow_empty“ jo False." + +msgid "Directory indexes are not allowed here." +msgstr "Zapisowe indekse njejsu how dowólone." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "„%(path)s“ njeeksistěrujo" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Indeks %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Instalacija jo była wuspěšna! Gratulacija!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Wersijowe informacije za Django " +"%(version)s pokazaś" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Wiźiśo toś ten bok, dokulaž DEBUG=True jo w swójej dataji nastajenjow a njejsćo " +"konfigurěrował URL." + +msgid "Django Documentation" +msgstr "Dokumentacija Django" + +msgid "Topics, references, & how-to’s" +msgstr "Temy, reference a rozpokazanja" + +msgid "Tutorial: A Polling App" +msgstr "Rozpokazanje: Napšašowańske nałoženje" + +msgid "Get started with Django" +msgstr "Prědne kšace z Django" + +msgid "Django Community" +msgstr "Zgromaźeństwo Django" + +msgid "Connect, get help, or contribute" +msgstr "Zwězajśo, wobsarajśo se pomoc abo źěłajśo sobu" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/el/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/el/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1b07550 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/el/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/el/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/el/LC_MESSAGES/django.po new file mode 100644 index 0000000..003a36c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/el/LC_MESSAGES/django.po @@ -0,0 +1,1332 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Apostolis Bessas , 2013 +# Dimitris Glezos , 2011,2013,2017 +# Fotis Athineos , 2021 +# Giannis Meletakis , 2015 +# Jannis Leidel , 2011 +# Nick Mavrakis , 2017-2020 +# Nikolas Demiridis , 2014 +# Nick Mavrakis , 2016 +# Pãnoș , 2014 +# Pãnoș , 2016 +# Serafeim Papastefanos , 2016 +# Stavros Korokithakis , 2014,2016 +# Yorgos Pagles , 2011-2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2021-11-18 21:19+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Greek (http://www.transifex.com/django/django/language/el/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: el\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Αφρικάνς" + +msgid "Arabic" +msgstr "Αραβικά" + +msgid "Algerian Arabic" +msgstr "Αραβικά Αλγερίας" + +msgid "Asturian" +msgstr "Αστούριας" + +msgid "Azerbaijani" +msgstr "Γλώσσα Αζερμπαϊτζάν" + +msgid "Bulgarian" +msgstr "Βουλγαρικά" + +msgid "Belarusian" +msgstr "Λευκορώσικα" + +msgid "Bengali" +msgstr "Μπενγκάλι" + +msgid "Breton" +msgstr "Βρετονικά" + +msgid "Bosnian" +msgstr "Βοσνιακά" + +msgid "Catalan" +msgstr "Καταλανικά" + +msgid "Czech" +msgstr "Τσέχικα" + +msgid "Welsh" +msgstr "Ουαλικά" + +msgid "Danish" +msgstr "Δανέζικα" + +msgid "German" +msgstr "Γερμανικά" + +msgid "Lower Sorbian" +msgstr "Κάτω Σορβικά" + +msgid "Greek" +msgstr "Ελληνικά" + +msgid "English" +msgstr "Αγγλικά" + +msgid "Australian English" +msgstr "Αγγλικά Αυστραλίας" + +msgid "British English" +msgstr "Αγγλικά Βρετανίας" + +msgid "Esperanto" +msgstr "Εσπεράντο" + +msgid "Spanish" +msgstr "Ισπανικά" + +msgid "Argentinian Spanish" +msgstr "Ισπανικά Αργεντινής" + +msgid "Colombian Spanish" +msgstr "Ισπανικά Κολομβίας" + +msgid "Mexican Spanish" +msgstr "Μεξικανική διάλεκτος Ισπανικών" + +msgid "Nicaraguan Spanish" +msgstr "Ισπανικά Νικαράγουας " + +msgid "Venezuelan Spanish" +msgstr "Ισπανικά Βενεζουέλας" + +msgid "Estonian" +msgstr "Εσθονικά" + +msgid "Basque" +msgstr "Βάσκικα" + +msgid "Persian" +msgstr "Περσικά" + +msgid "Finnish" +msgstr "Φινλανδικά" + +msgid "French" +msgstr "Γαλλικά" + +msgid "Frisian" +msgstr "Frisian" + +msgid "Irish" +msgstr "Ιρλανδικά" + +msgid "Scottish Gaelic" +msgstr "Σκωτσέζικα Γαελικά" + +msgid "Galician" +msgstr "Γαελικά" + +msgid "Hebrew" +msgstr "Εβραϊκά" + +msgid "Hindi" +msgstr "Ινδικά" + +msgid "Croatian" +msgstr "Κροατικά" + +msgid "Upper Sorbian" +msgstr "Άνω Σορβικά" + +msgid "Hungarian" +msgstr "Ουγγρικά" + +msgid "Armenian" +msgstr "Αρμενικά" + +msgid "Interlingua" +msgstr "Ιντερλίνγκουα" + +msgid "Indonesian" +msgstr "Ινδονησιακά" + +msgid "Igbo" +msgstr "Ίγκμπο" + +msgid "Ido" +msgstr "Ίντο" + +msgid "Icelandic" +msgstr "Ισλανδικά" + +msgid "Italian" +msgstr "Ιταλικά" + +msgid "Japanese" +msgstr "Γιαπωνέζικα" + +msgid "Georgian" +msgstr "Γεωργιανά" + +msgid "Kabyle" +msgstr "Kabyle" + +msgid "Kazakh" +msgstr "Καζακστά" + +msgid "Khmer" +msgstr "Χμερ" + +msgid "Kannada" +msgstr "Κανάντα" + +msgid "Korean" +msgstr "Κορεάτικα" + +msgid "Kyrgyz" +msgstr "Κιργιζικά" + +msgid "Luxembourgish" +msgstr "Λουξεμβουργιανά" + +msgid "Lithuanian" +msgstr "Λιθουανικά" + +msgid "Latvian" +msgstr "Λεττονικά" + +msgid "Macedonian" +msgstr "Μακεδονικά" + +msgid "Malayalam" +msgstr "Μαλαγιαλάμ" + +msgid "Mongolian" +msgstr "Μογγολικά" + +msgid "Marathi" +msgstr "Μαράθι" + +msgid "Malay" +msgstr "" + +msgid "Burmese" +msgstr "Βιρμανικά" + +msgid "Norwegian Bokmål" +msgstr "Νορβηγικά Μποκμάλ" + +msgid "Nepali" +msgstr "Νεπαλέζικα" + +msgid "Dutch" +msgstr "Ολλανδικά" + +msgid "Norwegian Nynorsk" +msgstr "Νορβηγική διάλεκτος Nynorsk - Νεονορβηγική" + +msgid "Ossetic" +msgstr "Οσσετικά" + +msgid "Punjabi" +msgstr "Πουντζάμπι" + +msgid "Polish" +msgstr "Πολωνικά" + +msgid "Portuguese" +msgstr "Πορτογαλικά" + +msgid "Brazilian Portuguese" +msgstr "Πορτογαλικά - διάλεκτος Βραζιλίας" + +msgid "Romanian" +msgstr "Ρουμανικά" + +msgid "Russian" +msgstr "Ρωσικά" + +msgid "Slovak" +msgstr "Σλοβακικά" + +msgid "Slovenian" +msgstr "Σλοβενικά" + +msgid "Albanian" +msgstr "Αλβανικά" + +msgid "Serbian" +msgstr "Σερβικά" + +msgid "Serbian Latin" +msgstr "Σέρβικα Λατινικά" + +msgid "Swedish" +msgstr "Σουηδικά" + +msgid "Swahili" +msgstr "Σουαχίλι" + +msgid "Tamil" +msgstr "Διάλεκτος Ταμίλ" + +msgid "Telugu" +msgstr "Τελούγκου" + +msgid "Tajik" +msgstr "Τατζικικά" + +msgid "Thai" +msgstr "Ταϊλάνδης" + +msgid "Turkmen" +msgstr "Τουρκμενικά" + +msgid "Turkish" +msgstr "Τουρκικά" + +msgid "Tatar" +msgstr "Ταταρικά" + +msgid "Udmurt" +msgstr "Ουντμουρτικά" + +msgid "Ukrainian" +msgstr "Ουκρανικά" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "Ουζμπεκικά" + +msgid "Vietnamese" +msgstr "Βιετναμέζικα" + +msgid "Simplified Chinese" +msgstr "Απλοποιημένα Κινέζικα" + +msgid "Traditional Chinese" +msgstr "Παραδοσιακά Κινέζικα" + +msgid "Messages" +msgstr "Μηνύματα" + +msgid "Site Maps" +msgstr "Χάρτες Ιστότοπου" + +msgid "Static Files" +msgstr "Στατικά Αρχεία" + +msgid "Syndication" +msgstr "Syndication" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "" + +msgid "That page number is not an integer" +msgstr "Ο αριθμός αυτής της σελίδας δεν είναι ακέραιος" + +msgid "That page number is less than 1" +msgstr "Ο αριθμός αυτής της σελίδας είναι μικρότερος του 1" + +msgid "That page contains no results" +msgstr "Η σελίδα αυτή δεν περιέχει αποτελέσματα" + +msgid "Enter a valid value." +msgstr "Εισάγετε μια έγκυρη τιμή." + +msgid "Enter a valid URL." +msgstr "Εισάγετε ένα έγκυρο URL." + +msgid "Enter a valid integer." +msgstr "Εισάγετε έναν έγκυρο ακέραιο." + +msgid "Enter a valid email address." +msgstr "Εισάγετε μια έγκυρη διεύθυνση ηλ. ταχυδρομείου." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Εισάγετε ένα 'slug' που να αποτελείται από γράμματα, αριθμούς, παύλες ή κάτω " +"παύλες." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Εισάγετε ένα 'slug' που να αποτελείται από Unicode γράμματα, παύλες ή κάτω " +"παύλες." + +msgid "Enter a valid IPv4 address." +msgstr "Εισάγετε μια έγκυρη IPv4 διεύθυνση." + +msgid "Enter a valid IPv6 address." +msgstr "Εισάγετε μία έγκυρη IPv6 διεύθυνση" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Εισάγετε μία έγκυρη IPv4 ή IPv6 διεύθυνση" + +msgid "Enter only digits separated by commas." +msgstr "Εισάγετε μόνο ψηφία χωρισμένα με κόμματα." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Βεβαιωθείτε ότι η τιμή είναι %(limit_value)s (η τιμή που καταχωρήσατε είναι " +"%(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Βεβαιωθείτε ότι η τιμή είναι μικρότερη ή ίση από %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Βεβαιωθείτε ότι η τιμή είναι μεγαλύτερη ή ίση από %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Βεβαιωθείται πως η τιμή αυτή έχει τουλάχιστον %(limit_value)d χαρακτήρες " +"(έχει %(show_value)d)." +msgstr[1] "" +"Βεβαιωθείτε πως η τιμή έχει τουλάχιστον %(limit_value)d χαρακτήρες (έχει " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Βεβαιωθείται πως η τιμή αυτή έχει τοπολύ %(limit_value)d χαρακτήρες (έχει " +"%(show_value)d)." +msgstr[1] "" +"Βεβαιωθείτε πως η τιμή έχει το πολύ %(limit_value)d χαρακτήρες (έχει " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Εισάγετε έναν αριθμό." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" +"Σιγουρευτείτε οτι τα σύνολο των ψηφίων δεν είναι παραπάνω από %(max)s" +msgstr[1] "" +"Σιγουρευτείτε οτι τα σύνολο των ψηφίων δεν είναι παραπάνω από %(max)s" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Σιγουρευτείτε ότι το δεκαδικό ψηφίο δεν είναι παραπάνω από %(max)s." +msgstr[1] "Σιγουρευτείτε ότι τα δεκαδικά ψηφία δεν είναι παραπάνω από %(max)s." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Βεβαιωθείτε ότι δεν υπάρχουν πάνω από %(max)s ψηφία πριν την υποδιαστολή." +msgstr[1] "" +"Βεβαιωθείτε ότι δεν υπάρχουν πάνω από %(max)s ψηφία πριν την υποδιαστολή." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Η επέκταση '%(extension)s' του αρχείου δεν επιτρέπεται. Οι επιτρεπόμενες " +"επεκτάσεις είναι: '%(allowed_extensions)s'." + +msgid "Null characters are not allowed." +msgstr "Δεν επιτρέπονται null (μηδενικοί) χαρακτήρες" + +msgid "and" +msgstr "και" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s με αυτή την %(field_labels)s υπάρχει ήδη." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Η τιμή %(value)r δεν είναι έγκυρη επιλογή." + +msgid "This field cannot be null." +msgstr "Το πεδίο αυτό δεν μπορεί να είναι μηδενικό (null)." + +msgid "This field cannot be blank." +msgstr "Το πεδίο αυτό δεν μπορεί να είναι κενό." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s με αυτό το %(field_label)s υπάρχει ήδη." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s πρέπει να είναι μοναδική για %(date_field_label)s " +"%(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Πεδίο τύπου: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "Η τιμή '%(value)s' πρέπει να είναι True ή False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "Η τιμή '%(value)s' πρέπει να είναι True, False, ή None." + +msgid "Boolean (Either True or False)" +msgstr "Boolean (Είτε Αληθές ή Ψευδές)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Συμβολοσειρά (μέχρι %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "Ακέραιοι χωρισμένοι με κόμματα" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"Η τιμή του '%(value)s' έχει μια λανθασμένη μορφή ημερομηνίας. Η ημερομηνία " +"θα πρέπει να είναι στην μορφή YYYY-MM-DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"Η τιμή '%(value)s' είναι στην σωστή μορφή (YYYY-MM-DD) αλλά είναι μια " +"λανθασμένη ημερομηνία." + +msgid "Date (without time)" +msgstr "Ημερομηνία (χωρίς την ώρα)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"Η τιμή του '%(value)s' έχει μια λανθασμένη μορφή. Η ημερομηνία/ώρα θα πρέπει " +"να είναι στην μορφή YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"Η τιμή '%(value)s' έχει τη σωστή μορφή (YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) " +"αλλά δεν αντιστοιχεί σε σωστή ημερομηνία και ώρα." + +msgid "Date (with time)" +msgstr "Ημερομηνία (με ώρα)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "Η τιμή '%(value)s' πρέπει να είναι δεκαδικός αριθμός." + +msgid "Decimal number" +msgstr "Δεκαδικός αριθμός" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"Η τιμή '%(value)s' έχει εσφαλμένη μορφή. Πρέπει να είναι της μορφής [DD] " +"[[HH:]MM:]ss[.uuuuuu]." + +msgid "Duration" +msgstr "Διάρκεια" + +msgid "Email address" +msgstr "Ηλεκτρονική διεύθυνση" + +msgid "File path" +msgstr "Τοποθεσία αρχείου" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "Η '%(value)s' τιμή πρέπει να είναι δεκαδικός." + +msgid "Floating point number" +msgstr "Αριθμός κινητής υποδιαστολής" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "Η τιμή '%(value)s' πρέπει να είναι ακέραιος." + +msgid "Integer" +msgstr "Ακέραιος" + +msgid "Big (8 byte) integer" +msgstr "Μεγάλος ακέραιος - big integer (8 bytes)" + +msgid "Small integer" +msgstr "Μικρός ακέραιος" + +msgid "IPv4 address" +msgstr "Διεύθυνση IPv4" + +msgid "IP address" +msgstr "IP διεύθυνση" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "Η τιμή '%(value)s' πρέπει να είναι None, True ή False." + +msgid "Boolean (Either True, False or None)" +msgstr "Boolean (Αληθές, Ψευδές, ή τίποτα)" + +msgid "Positive big integer" +msgstr "Μεγάλος θετικός ακέραιος" + +msgid "Positive integer" +msgstr "Θετικός ακέραιος" + +msgid "Positive small integer" +msgstr "Θετικός μικρός ακέραιος" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (μέχρι %(max_length)s)" + +msgid "Text" +msgstr "Κείμενο" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"Η τιμή '%(value)s' έχει εσφαλμένη μορφή. Πρέπει να είναι της μορφής HH:MM[:" +"ss[.uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"Η τιμή '%(value)s' έχει τη σωστή μορφή (HH:MM[:ss[.uuuuuu]]) αλλά δεν " +"αντιστοιχή σε σωστή ώρα." + +msgid "Time" +msgstr "Ώρα" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Δυαδικά δεδομένα" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "'%(value)s' δεν είναι ένα έγκυρο UUID." + +msgid "Universally unique identifier" +msgstr "Καθολικά μοναδικό αναγνωριστικό" + +msgid "File" +msgstr "Αρχείο" + +msgid "Image" +msgstr "Εικόνα" + +msgid "A JSON object" +msgstr "Ένα αντικείμενο JSON" + +msgid "Value must be valid JSON." +msgstr "Η τιμή πρέπει να είναι έγκυρο JSON." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" +"Το μοντέλο %(model)s με την τιμή %(value)r του πεδίου %(field)s δεν υπάρχει." + +msgid "Foreign Key (type determined by related field)" +msgstr "Foreign Key (ο τύπος καθορίζεται από το πεδίο του συσχετισμού)" + +msgid "One-to-one relationship" +msgstr "Σχέση ένα-προς-ένα" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "σχέση %(from)s-%(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "σχέσεις %(from)s-%(to)s" + +msgid "Many-to-many relationship" +msgstr "Σχέση πολλά-προς-πολλά" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Αυτό το πεδίο είναι απαραίτητο." + +msgid "Enter a whole number." +msgstr "Εισάγετε έναν ακέραιο αριθμό." + +msgid "Enter a valid date." +msgstr "Εισάγετε μια έγκυρη ημερομηνία." + +msgid "Enter a valid time." +msgstr "Εισάγετε μια έγκυρη ώρα." + +msgid "Enter a valid date/time." +msgstr "Εισάγετε μια έγκυρη ημερομηνία/ώρα." + +msgid "Enter a valid duration." +msgstr "Εισάγετε μια έγκυρη διάρκεια." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Ο αριθμός των ημερών πρέπει να είναι μεταξύ {min_days} και {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" +"Δεν έχει υποβληθεί κάποιο αρχείο. Ελέγξτε τον τύπο κωδικοποίησης στη φόρμα." + +msgid "No file was submitted." +msgstr "Δεν υποβλήθηκε κάποιο αρχείο." + +msgid "The submitted file is empty." +msgstr "Το αρχείο που υποβλήθηκε είναι κενό." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Βεβαιωθείται πως το όνομα του αρχείου έχει το πολύ %(max)d χαρακτήρα (το " +"παρόν έχει %(length)d)." +msgstr[1] "" +"Βεβαιωθείται πως το όνομα του αρχείου έχει το πολύ %(max)d χαρακτήρα (το " +"παρόν έχει %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Βεβαιωθείτε ότι είτε έχετε επιλέξει ένα αρχείο για αποστολή είτε έχετε " +"επιλέξει την εκκαθάριση του πεδίου. Δεν είναι δυνατή η επιλογή και των δύο " +"ταυτοχρόνως." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Βεβαιωθείτε ότι το αρχείο που έχετε επιλέξει για αποστολή είναι αρχείο " +"εικόνας. Το τρέχον είτε δεν ήταν εικόνα είτε έχει υποστεί φθορά." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Βεβαιωθείτε ότι έχετε επιλέξει μία έγκυρη επιλογή. Η τιμή %(value)s δεν " +"είναι διαθέσιμη προς επιλογή." + +msgid "Enter a list of values." +msgstr "Εισάγετε μια λίστα τιμών." + +msgid "Enter a complete value." +msgstr "Εισάγετε μια πλήρης τιμή" + +msgid "Enter a valid UUID." +msgstr "Εισάγετε μια έγκυρη UUID." + +msgid "Enter a valid JSON." +msgstr "Εισάγετε ένα έγκυρο JSON." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Κρυφό πεδίο %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" + +#, python-format +msgid "Please submit at most %d form." +msgid_plural "Please submit at most %d forms." +msgstr[0] "Παρακαλώ υποβάλλετε το πολύ %d φόρμα." +msgstr[1] "Παρακαλώ υποβάλλετε το πολύ %d φόρμες." + +#, python-format +msgid "Please submit at least %d form." +msgid_plural "Please submit at least %d forms." +msgstr[0] "Παρακαλώ υποβάλλετε τουλάχιστον %d φόρμα." +msgstr[1] "Παρακαλώ υποβάλλετε τουλάχιστον %d φόρμες." + +msgid "Order" +msgstr "Ταξινόμηση" + +msgid "Delete" +msgstr "Διαγραφή" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Στο %(field)s έχετε ξαναεισάγει τα ίδια δεδομένα." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Στο %(field)s έχετε ξαναεισάγει τα ίδια δεδομένα. Θα πρέπει να εμφανίζονται " +"μία φορά. " + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Στο %(field_name)s έχετε ξαναεισάγει τα ίδια δεδομένα. Θα πρέπει να " +"εμφανίζονται μία φορά για το %(lookup)s στο %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Έχετε ξαναεισάγει την ίδια τιμη. Βεβαιωθείτε ότι είναι μοναδική." + +msgid "The inline value did not match the parent instance." +msgstr "Η τιμή δεν είναι ίση με την αντίστοιχη τιμή του γονικού object." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Επιλέξτε μια έγκυρη επιλογή. Η επιλογή αυτή δεν είναι μία από τις διαθέσιμες " +"επιλογές." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "\"%(pk)s\" δεν είναι έγκυρη τιμή." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"Η ημερομηνία %(datetime)s δεν μπόρεσε να μετατραπεί στην ζώνη ώρας " +"%(current_timezone)s. Ίσως να είναι ασαφής ή να μην υπάρχει." + +msgid "Clear" +msgstr "Εκκαθάριση" + +msgid "Currently" +msgstr "Τώρα" + +msgid "Change" +msgstr "Επεξεργασία" + +msgid "Unknown" +msgstr "Άγνωστο" + +msgid "Yes" +msgstr "Ναι" + +msgid "No" +msgstr "Όχι" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "ναι,όχι,ίσως" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d bytes" +msgstr[1] "%(size)d bytes" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "μμ." + +msgid "a.m." +msgstr "πμ." + +msgid "PM" +msgstr "ΜΜ" + +msgid "AM" +msgstr "ΠΜ" + +msgid "midnight" +msgstr "μεσάνυχτα" + +msgid "noon" +msgstr "μεσημέρι" + +msgid "Monday" +msgstr "Δευτέρα" + +msgid "Tuesday" +msgstr "Τρίτη" + +msgid "Wednesday" +msgstr "Τετάρτη" + +msgid "Thursday" +msgstr "Πέμπτη" + +msgid "Friday" +msgstr "Παρασκευή" + +msgid "Saturday" +msgstr "Σάββατο" + +msgid "Sunday" +msgstr "Κυριακή" + +msgid "Mon" +msgstr "Δευ" + +msgid "Tue" +msgstr "Τρί" + +msgid "Wed" +msgstr "Τετ" + +msgid "Thu" +msgstr "Πέμ" + +msgid "Fri" +msgstr "Παρ" + +msgid "Sat" +msgstr "Σαβ" + +msgid "Sun" +msgstr "Κυρ" + +msgid "January" +msgstr "Ιανουάριος" + +msgid "February" +msgstr "Φεβρουάριος" + +msgid "March" +msgstr "Μάρτιος" + +msgid "April" +msgstr "Απρίλιος" + +msgid "May" +msgstr "Μάιος" + +msgid "June" +msgstr "Ιούνιος" + +msgid "July" +msgstr "Ιούλιος" + +msgid "August" +msgstr "Αύγουστος" + +msgid "September" +msgstr "Σεπτέμβριος" + +msgid "October" +msgstr "Οκτώβριος" + +msgid "November" +msgstr "Νοέμβριος" + +msgid "December" +msgstr "Δεκέμβριος" + +msgid "jan" +msgstr "Ιαν" + +msgid "feb" +msgstr "Φεβ" + +msgid "mar" +msgstr "Μάρ" + +msgid "apr" +msgstr "Απρ" + +msgid "may" +msgstr "Μάι" + +msgid "jun" +msgstr "Ιούν" + +msgid "jul" +msgstr "Ιούλ" + +msgid "aug" +msgstr "Αύγ" + +msgid "sep" +msgstr "Σεπ" + +msgid "oct" +msgstr "Οκτ" + +msgid "nov" +msgstr "Νοέ" + +msgid "dec" +msgstr "Δεκ" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Ιαν." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Φεβ." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Μάρτιος" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Απρίλ." + +msgctxt "abbrev. month" +msgid "May" +msgstr "Μάιος" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Ιούν." + +msgctxt "abbrev. month" +msgid "July" +msgstr "Ιούλ." + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Αύγ." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Σεπτ." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Οκτ." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Νοέμ." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Δεκ." + +msgctxt "alt. month" +msgid "January" +msgstr "Ιανουαρίου" + +msgctxt "alt. month" +msgid "February" +msgstr "Φεβρουαρίου" + +msgctxt "alt. month" +msgid "March" +msgstr "Μαρτίου" + +msgctxt "alt. month" +msgid "April" +msgstr "Απριλίου" + +msgctxt "alt. month" +msgid "May" +msgstr "Μαΐου" + +msgctxt "alt. month" +msgid "June" +msgstr "Ιουνίου" + +msgctxt "alt. month" +msgid "July" +msgstr "Ιουλίου" + +msgctxt "alt. month" +msgid "August" +msgstr "Αυγούστου" + +msgctxt "alt. month" +msgid "September" +msgstr "Σεπτεμβρίου" + +msgctxt "alt. month" +msgid "October" +msgstr "Οκτωβρίου" + +msgctxt "alt. month" +msgid "November" +msgstr "Νοεμβρίου" + +msgctxt "alt. month" +msgid "December" +msgstr "Δεκεμβρίου" + +msgid "This is not a valid IPv6 address." +msgstr "Αυτή δεν είναι έγκυρη διεύθυνση IPv6." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "ή" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "" +msgstr[1] "" + +msgid "Forbidden" +msgstr "Απαγορευμένο" + +msgid "CSRF verification failed. Request aborted." +msgstr "Η πιστοποίηση CSRF απέτυχε. Το αίτημα ματαιώθηκε." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Αν οι 'Referer' headers είναι απενεργοποιημένοι στον browser σας από εσάς, " +"παρακαλούμε να τους ξανά-ενεργοποιήσετε, τουλάχιστον για αυτό το site ή για " +"τις συνδέσεις HTTPS ή για τα 'same-origin' requests." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Αν χρησιμοποιείτε την ετικέτα ή συμπεριλαμβάνετε την κεφαλίδα (header) 'Referrer-Policy: no-referrer', " +"παρακαλούμε αφαιρέστε τα. Η προστασία CSRF απαιτεί την κεφαλίδα 'Referer' να " +"κάνει αυστηρό έλεγχο στον referer. Αν κύριο μέλημα σας είναι η ιδιωτικότητα, " +"σκεφτείτε να χρησιμοποιήσετε εναλλακτικές μεθόδους όπως για συνδέσμους από άλλες ιστοσελίδες." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Βλέπετε αυτό το μήνυμα επειδή αυτή η σελίδα απαιτεί ένα CSRF cookie, όταν " +"κατατίθενται φόρμες. Αυτό το cookie είναι απαραίτητο για λόγους ασφαλείας, " +"για να εξασφαλιστεί ότι ο browser δεν έχει γίνει hijacked από τρίτους." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Αν τα cookies είναι απενεργοποιημένα στον browser σας από εσάς, παρακαλούμε " +"να τα ξανά-ενεργοποιήσετε, τουλάχιστον για αυτό το site ή για τα 'same-" +"origin' requests." + +msgid "More information is available with DEBUG=True." +msgstr "Περισσότερες πληροφορίες είναι διαθέσιμες με DEBUG=True." + +msgid "No year specified" +msgstr "Δεν έχει οριστεί χρονιά" + +msgid "Date out of range" +msgstr "Ημερομηνία εκτός εύρους" + +msgid "No month specified" +msgstr "Δεν έχει οριστεί μήνας" + +msgid "No day specified" +msgstr "Δεν έχει οριστεί μέρα" + +msgid "No week specified" +msgstr "Δεν έχει οριστεί εβδομάδα" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Δεν υπάρχουν διαθέσιμα %(verbose_name_plural)s" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Μελλοντικά %(verbose_name_plural)s δεν είναι διαθέσιμα διότι δεν έχει τεθεί " +"το %(class_name)s.allow_future." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" +"Λανθασμένη μορφή ημερομηνίας '%(datestr)s' για την επιλεγμένη μορφή " +"'%(format)s'" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Δεν βρέθηκαν %(verbose_name)s που να ικανοποιούν την αναζήτηση." + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" +"Η σελίδα δεν έχει την τιμή 'last' υποδηλώνοντας την τελευταία σελίδα, ούτε " +"μπορεί να μετατραπεί σε ακέραιο." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Άκυρη σελίδα (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Άδεια λίστα και το \"%(class_name)s.allow_empty\" είναι False." + +msgid "Directory indexes are not allowed here." +msgstr "Τα ευρετήρια καταλόγων δεν επιτρέπονται εδώ." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "Το \"%(path)s\" δεν υπάρχει" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Ευρετήριο του %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Η εγκατάσταση δούλεψε με επιτυχία! Συγχαρητήρια!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Δείτε τις σημειώσεις κυκλοφορίας για το " +"Django %(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" +"Βλέπετε αυτό το μήνυμα επειδή έχετε DEBUG=True στο αρχείο settings και δεν έχετε ρυθμίσει κανένα URL στο " +"αρχείο urls.py. Στρωθείτε στην δουλειά!" + +msgid "Django Documentation" +msgstr "Εγχειρίδιο Django" + +msgid "Topics, references, & how-to’s" +msgstr "Θέματα, αναφορές & \"πως να...\"" + +msgid "Tutorial: A Polling App" +msgstr "Εγχειρίδιο: Ένα App Ψηφοφορίας" + +msgid "Get started with Django" +msgstr "Ξεκινήστε με το Django" + +msgid "Django Community" +msgstr "Κοινότητα Django" + +msgid "Connect, get help, or contribute" +msgstr "Συνδεθείτε, λάβετε βοήθεια, ή συνεισφέρετε" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/el/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/el/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/el/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/el/formats.py new file mode 100644 index 0000000..25c8ef7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/el/formats.py @@ -0,0 +1,34 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "d/m/Y" +TIME_FORMAT = "P" +DATETIME_FORMAT = "d/m/Y P" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "d/m/Y" +SHORT_DATETIME_FORMAT = "d/m/Y P" +FIRST_DAY_OF_WEEK = 0 # Sunday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d/%m/%Y", # '25/10/2006' + "%d/%m/%y", # '25/10/06' + "%Y-%m-%d", # '2006-10-25' +] +DATETIME_INPUT_FORMATS = [ + "%d/%m/%Y %H:%M:%S", # '25/10/2006 14:30:59' + "%d/%m/%Y %H:%M:%S.%f", # '25/10/2006 14:30:59.000200' + "%d/%m/%Y %H:%M", # '25/10/2006 14:30' + "%d/%m/%y %H:%M:%S", # '25/10/06 14:30:59' + "%d/%m/%y %H:%M:%S.%f", # '25/10/06 14:30:59.000200' + "%d/%m/%y %H:%M", # '25/10/06 14:30' + "%Y-%m-%d %H:%M:%S", # '2006-10-25 14:30:59' + "%Y-%m-%d %H:%M:%S.%f", # '2006-10-25 14:30:59.000200' + "%Y-%m-%d %H:%M", # '2006-10-25 14:30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0d4c976 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en/LC_MESSAGES/django.po new file mode 100644 index 0000000..cb9e747 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en/LC_MESSAGES/django.po @@ -0,0 +1,1604 @@ +# This file is distributed under the same license as the Django package. +# +msgid "" +msgstr "" +"Project-Id-Version: Django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2010-05-13 15:35+0200\n" +"Last-Translator: Django team\n" +"Language-Team: English \n" +"Language: en\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: conf/global_settings.py:52 +msgid "Afrikaans" +msgstr "" + +#: conf/global_settings.py:53 +msgid "Arabic" +msgstr "" + +#: conf/global_settings.py:54 +msgid "Algerian Arabic" +msgstr "" + +#: conf/global_settings.py:55 +msgid "Asturian" +msgstr "" + +#: conf/global_settings.py:56 +msgid "Azerbaijani" +msgstr "" + +#: conf/global_settings.py:57 +msgid "Bulgarian" +msgstr "" + +#: conf/global_settings.py:58 +msgid "Belarusian" +msgstr "" + +#: conf/global_settings.py:59 +msgid "Bengali" +msgstr "" + +#: conf/global_settings.py:60 +msgid "Breton" +msgstr "" + +#: conf/global_settings.py:61 +msgid "Bosnian" +msgstr "" + +#: conf/global_settings.py:62 +msgid "Catalan" +msgstr "" + +#: conf/global_settings.py:63 +msgid "Central Kurdish (Sorani)" +msgstr "" + +#: conf/global_settings.py:64 +msgid "Czech" +msgstr "" + +#: conf/global_settings.py:65 +msgid "Welsh" +msgstr "" + +#: conf/global_settings.py:66 +msgid "Danish" +msgstr "" + +#: conf/global_settings.py:67 +msgid "German" +msgstr "" + +#: conf/global_settings.py:68 +msgid "Lower Sorbian" +msgstr "" + +#: conf/global_settings.py:69 +msgid "Greek" +msgstr "" + +#: conf/global_settings.py:70 +msgid "English" +msgstr "" + +#: conf/global_settings.py:71 +msgid "Australian English" +msgstr "" + +#: conf/global_settings.py:72 +msgid "British English" +msgstr "" + +#: conf/global_settings.py:73 +msgid "Esperanto" +msgstr "" + +#: conf/global_settings.py:74 +msgid "Spanish" +msgstr "" + +#: conf/global_settings.py:75 +msgid "Argentinian Spanish" +msgstr "" + +#: conf/global_settings.py:76 +msgid "Colombian Spanish" +msgstr "" + +#: conf/global_settings.py:77 +msgid "Mexican Spanish" +msgstr "" + +#: conf/global_settings.py:78 +msgid "Nicaraguan Spanish" +msgstr "" + +#: conf/global_settings.py:79 +msgid "Venezuelan Spanish" +msgstr "" + +#: conf/global_settings.py:80 +msgid "Estonian" +msgstr "" + +#: conf/global_settings.py:81 +msgid "Basque" +msgstr "" + +#: conf/global_settings.py:82 +msgid "Persian" +msgstr "" + +#: conf/global_settings.py:83 +msgid "Finnish" +msgstr "" + +#: conf/global_settings.py:84 +msgid "French" +msgstr "" + +#: conf/global_settings.py:85 +msgid "Frisian" +msgstr "" + +#: conf/global_settings.py:86 +msgid "Irish" +msgstr "" + +#: conf/global_settings.py:87 +msgid "Scottish Gaelic" +msgstr "" + +#: conf/global_settings.py:88 +msgid "Galician" +msgstr "" + +#: conf/global_settings.py:89 +msgid "Hebrew" +msgstr "" + +#: conf/global_settings.py:90 +msgid "Hindi" +msgstr "" + +#: conf/global_settings.py:91 +msgid "Croatian" +msgstr "" + +#: conf/global_settings.py:92 +msgid "Upper Sorbian" +msgstr "" + +#: conf/global_settings.py:93 +msgid "Hungarian" +msgstr "" + +#: conf/global_settings.py:94 +msgid "Armenian" +msgstr "" + +#: conf/global_settings.py:95 +msgid "Interlingua" +msgstr "" + +#: conf/global_settings.py:96 +msgid "Indonesian" +msgstr "" + +#: conf/global_settings.py:97 +msgid "Igbo" +msgstr "" + +#: conf/global_settings.py:98 +msgid "Ido" +msgstr "" + +#: conf/global_settings.py:99 +msgid "Icelandic" +msgstr "" + +#: conf/global_settings.py:100 +msgid "Italian" +msgstr "" + +#: conf/global_settings.py:101 +msgid "Japanese" +msgstr "" + +#: conf/global_settings.py:102 +msgid "Georgian" +msgstr "" + +#: conf/global_settings.py:103 +msgid "Kabyle" +msgstr "" + +#: conf/global_settings.py:104 +msgid "Kazakh" +msgstr "" + +#: conf/global_settings.py:105 +msgid "Khmer" +msgstr "" + +#: conf/global_settings.py:106 +msgid "Kannada" +msgstr "" + +#: conf/global_settings.py:107 +msgid "Korean" +msgstr "" + +#: conf/global_settings.py:108 +msgid "Kyrgyz" +msgstr "" + +#: conf/global_settings.py:109 +msgid "Luxembourgish" +msgstr "" + +#: conf/global_settings.py:110 +msgid "Lithuanian" +msgstr "" + +#: conf/global_settings.py:111 +msgid "Latvian" +msgstr "" + +#: conf/global_settings.py:112 +msgid "Macedonian" +msgstr "" + +#: conf/global_settings.py:113 +msgid "Malayalam" +msgstr "" + +#: conf/global_settings.py:114 +msgid "Mongolian" +msgstr "" + +#: conf/global_settings.py:115 +msgid "Marathi" +msgstr "" + +#: conf/global_settings.py:116 +msgid "Malay" +msgstr "" + +#: conf/global_settings.py:117 +msgid "Burmese" +msgstr "" + +#: conf/global_settings.py:118 +msgid "Norwegian Bokmål" +msgstr "" + +#: conf/global_settings.py:119 +msgid "Nepali" +msgstr "" + +#: conf/global_settings.py:120 +msgid "Dutch" +msgstr "" + +#: conf/global_settings.py:121 +msgid "Norwegian Nynorsk" +msgstr "" + +#: conf/global_settings.py:122 +msgid "Ossetic" +msgstr "" + +#: conf/global_settings.py:123 +msgid "Punjabi" +msgstr "" + +#: conf/global_settings.py:124 +msgid "Polish" +msgstr "" + +#: conf/global_settings.py:125 +msgid "Portuguese" +msgstr "" + +#: conf/global_settings.py:126 +msgid "Brazilian Portuguese" +msgstr "" + +#: conf/global_settings.py:127 +msgid "Romanian" +msgstr "" + +#: conf/global_settings.py:128 +msgid "Russian" +msgstr "" + +#: conf/global_settings.py:129 +msgid "Slovak" +msgstr "" + +#: conf/global_settings.py:130 +msgid "Slovenian" +msgstr "" + +#: conf/global_settings.py:131 +msgid "Albanian" +msgstr "" + +#: conf/global_settings.py:132 +msgid "Serbian" +msgstr "" + +#: conf/global_settings.py:133 +msgid "Serbian Latin" +msgstr "" + +#: conf/global_settings.py:134 +msgid "Swedish" +msgstr "" + +#: conf/global_settings.py:135 +msgid "Swahili" +msgstr "" + +#: conf/global_settings.py:136 +msgid "Tamil" +msgstr "" + +#: conf/global_settings.py:137 +msgid "Telugu" +msgstr "" + +#: conf/global_settings.py:138 +msgid "Tajik" +msgstr "" + +#: conf/global_settings.py:139 +msgid "Thai" +msgstr "" + +#: conf/global_settings.py:140 +msgid "Turkmen" +msgstr "" + +#: conf/global_settings.py:141 +msgid "Turkish" +msgstr "" + +#: conf/global_settings.py:142 +msgid "Tatar" +msgstr "" + +#: conf/global_settings.py:143 +msgid "Udmurt" +msgstr "" + +#: conf/global_settings.py:144 +msgid "Uyghur" +msgstr "" + +#: conf/global_settings.py:145 +msgid "Ukrainian" +msgstr "" + +#: conf/global_settings.py:146 +msgid "Urdu" +msgstr "" + +#: conf/global_settings.py:147 +msgid "Uzbek" +msgstr "" + +#: conf/global_settings.py:148 +msgid "Vietnamese" +msgstr "" + +#: conf/global_settings.py:149 +msgid "Simplified Chinese" +msgstr "" + +#: conf/global_settings.py:150 +msgid "Traditional Chinese" +msgstr "" + +#: contrib/messages/apps.py:15 +msgid "Messages" +msgstr "" + +#: contrib/sitemaps/apps.py:8 +msgid "Site Maps" +msgstr "" + +#: contrib/staticfiles/apps.py:9 +msgid "Static Files" +msgstr "" + +#: contrib/syndication/apps.py:7 +msgid "Syndication" +msgstr "" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +#: core/paginator.py:30 +msgid "…" +msgstr "" + +#: core/paginator.py:32 +msgid "That page number is not an integer" +msgstr "" + +#: core/paginator.py:33 +msgid "That page number is less than 1" +msgstr "" + +#: core/paginator.py:34 +msgid "That page contains no results" +msgstr "" + +#: core/validators.py:22 +msgid "Enter a valid value." +msgstr "" + +#: core/validators.py:104 forms/fields.py:759 +msgid "Enter a valid URL." +msgstr "" + +#: core/validators.py:165 +msgid "Enter a valid integer." +msgstr "" + +#: core/validators.py:176 +msgid "Enter a valid email address." +msgstr "" + +#. Translators: "letters" means latin letters: a-z and A-Z. +#: core/validators.py:259 +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +#: core/validators.py:267 +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +#: core/validators.py:279 core/validators.py:306 +msgid "Enter a valid IPv4 address." +msgstr "" + +#: core/validators.py:286 core/validators.py:307 +msgid "Enter a valid IPv6 address." +msgstr "" + +#: core/validators.py:298 core/validators.py:305 +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "" + +#: core/validators.py:341 +msgid "Enter only digits separated by commas." +msgstr "" + +#: core/validators.py:347 +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" + +#: core/validators.py:382 +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" + +#: core/validators.py:391 +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" + +#: core/validators.py:400 +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" + +#: core/validators.py:407 +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" + +#: core/validators.py:439 +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +#: core/validators.py:457 +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +#: core/validators.py:480 forms/fields.py:354 forms/fields.py:393 +msgid "Enter a number." +msgstr "" + +#: core/validators.py:482 +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" +msgstr[1] "" + +#: core/validators.py:487 +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +msgstr[1] "" + +#: core/validators.py:492 +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +msgstr[1] "" + +#: core/validators.py:563 +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +#: core/validators.py:624 +msgid "Null characters are not allowed." +msgstr "" + +#: db/models/base.py:1465 forms/models.py:902 +msgid "and" +msgstr "" + +#: db/models/base.py:1467 +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#: db/models/constraints.py:20 +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "" + +#: db/models/fields/__init__.py:128 +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +#: db/models/fields/__init__.py:129 +msgid "This field cannot be null." +msgstr "" + +#: db/models/fields/__init__.py:130 +msgid "This field cannot be blank." +msgstr "" + +#: db/models/fields/__init__.py:131 +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "" + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#: db/models/fields/__init__.py:135 +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#: db/models/fields/__init__.py:174 +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "" + +#: db/models/fields/__init__.py:1157 +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#: db/models/fields/__init__.py:1158 +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +#: db/models/fields/__init__.py:1160 +msgid "Boolean (Either True or False)" +msgstr "" + +#: db/models/fields/__init__.py:1210 +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "" + +#: db/models/fields/__init__.py:1212 +msgid "String (unlimited)" +msgstr "" + +#: db/models/fields/__init__.py:1316 +msgid "Comma-separated integers" +msgstr "" + +#: db/models/fields/__init__.py:1417 +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#: db/models/fields/__init__.py:1421 db/models/fields/__init__.py:1556 +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +#: db/models/fields/__init__.py:1425 +msgid "Date (without time)" +msgstr "" + +#: db/models/fields/__init__.py:1552 +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#: db/models/fields/__init__.py:1560 +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +#: db/models/fields/__init__.py:1565 +msgid "Date (with time)" +msgstr "" + +#: db/models/fields/__init__.py:1689 +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +#: db/models/fields/__init__.py:1691 +msgid "Decimal number" +msgstr "" + +#: db/models/fields/__init__.py:1852 +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +#: db/models/fields/__init__.py:1856 +msgid "Duration" +msgstr "" + +#: db/models/fields/__init__.py:1908 +msgid "Email address" +msgstr "" + +#: db/models/fields/__init__.py:1933 +msgid "File path" +msgstr "" + +#: db/models/fields/__init__.py:2011 +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +#: db/models/fields/__init__.py:2013 +msgid "Floating point number" +msgstr "" + +#: db/models/fields/__init__.py:2053 +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +#: db/models/fields/__init__.py:2055 +msgid "Integer" +msgstr "" + +#: db/models/fields/__init__.py:2151 +msgid "Big (8 byte) integer" +msgstr "" + +#: db/models/fields/__init__.py:2168 +msgid "Small integer" +msgstr "" + +#: db/models/fields/__init__.py:2176 +msgid "IPv4 address" +msgstr "" + +#: db/models/fields/__init__.py:2207 +msgid "IP address" +msgstr "" + +#: db/models/fields/__init__.py:2300 db/models/fields/__init__.py:2301 +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +#: db/models/fields/__init__.py:2303 +msgid "Boolean (Either True, False or None)" +msgstr "" + +#: db/models/fields/__init__.py:2354 +msgid "Positive big integer" +msgstr "" + +#: db/models/fields/__init__.py:2369 +msgid "Positive integer" +msgstr "" + +#: db/models/fields/__init__.py:2384 +msgid "Positive small integer" +msgstr "" + +#: db/models/fields/__init__.py:2400 +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "" + +#: db/models/fields/__init__.py:2436 +msgid "Text" +msgstr "" + +#: db/models/fields/__init__.py:2511 +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#: db/models/fields/__init__.py:2515 +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +#: db/models/fields/__init__.py:2519 +msgid "Time" +msgstr "" + +#: db/models/fields/__init__.py:2627 +msgid "URL" +msgstr "" + +#: db/models/fields/__init__.py:2651 +msgid "Raw binary data" +msgstr "" + +#: db/models/fields/__init__.py:2716 +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +#: db/models/fields/__init__.py:2718 +msgid "Universally unique identifier" +msgstr "" + +#: db/models/fields/files.py:232 +msgid "File" +msgstr "" + +#: db/models/fields/files.py:393 +msgid "Image" +msgstr "" + +#: db/models/fields/json.py:26 +msgid "A JSON object" +msgstr "" + +#: db/models/fields/json.py:28 +msgid "Value must be valid JSON." +msgstr "" + +#: db/models/fields/related.py:939 +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +#: db/models/fields/related.py:941 +msgid "Foreign Key (type determined by related field)" +msgstr "" + +#: db/models/fields/related.py:1235 +msgid "One-to-one relationship" +msgstr "" + +#: db/models/fields/related.py:1292 +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#: db/models/fields/related.py:1294 +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +#: db/models/fields/related.py:1342 +msgid "Many-to-many relationship" +msgstr "" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the label +#: forms/boundfield.py:185 +msgid ":?.!" +msgstr "" + +#: forms/fields.py:94 +msgid "This field is required." +msgstr "" + +#: forms/fields.py:303 +msgid "Enter a whole number." +msgstr "" + +#: forms/fields.py:474 forms/fields.py:1246 +msgid "Enter a valid date." +msgstr "" + +#: forms/fields.py:497 forms/fields.py:1247 +msgid "Enter a valid time." +msgstr "" + +#: forms/fields.py:524 +msgid "Enter a valid date/time." +msgstr "" + +#: forms/fields.py:558 +msgid "Enter a valid duration." +msgstr "" + +#: forms/fields.py:559 +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +#: forms/fields.py:628 +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" + +#: forms/fields.py:629 +msgid "No file was submitted." +msgstr "" + +#: forms/fields.py:630 +msgid "The submitted file is empty." +msgstr "" + +#: forms/fields.py:632 +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +msgstr[1] "" + +#: forms/fields.py:637 +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" + +#: forms/fields.py:701 +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" + +#: forms/fields.py:868 forms/fields.py:954 forms/models.py:1581 +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" + +#: forms/fields.py:956 forms/fields.py:1075 forms/models.py:1579 +msgid "Enter a list of values." +msgstr "" + +#: forms/fields.py:1076 +msgid "Enter a complete value." +msgstr "" + +#: forms/fields.py:1315 +msgid "Enter a valid UUID." +msgstr "" + +#: forms/fields.py:1345 +msgid "Enter a valid JSON." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +#: forms/forms.py:94 +msgid ":" +msgstr "" + +#: forms/forms.py:231 +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "" + +#: forms/formsets.py:61 +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" + +#: forms/formsets.py:65 +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "" +msgstr[1] "" + +#: forms/formsets.py:70 +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "" +msgstr[1] "" + +#: forms/formsets.py:484 forms/formsets.py:491 +msgid "Order" +msgstr "" + +#: forms/formsets.py:499 +msgid "Delete" +msgstr "" + +#: forms/models.py:895 +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "" + +#: forms/models.py:900 +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" + +#: forms/models.py:907 +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" + +#: forms/models.py:916 +msgid "Please correct the duplicate values below." +msgstr "" + +#: forms/models.py:1353 +msgid "The inline value did not match the parent instance." +msgstr "" + +#: forms/models.py:1444 +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" + +#: forms/models.py:1583 +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#: forms/utils.py:227 +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +#: forms/widgets.py:457 +msgid "Clear" +msgstr "" + +#: forms/widgets.py:458 +msgid "Currently" +msgstr "" + +#: forms/widgets.py:459 +msgid "Change" +msgstr "" + +#: forms/widgets.py:796 +msgid "Unknown" +msgstr "" + +#: forms/widgets.py:797 +msgid "Yes" +msgstr "" + +#: forms/widgets.py:798 +msgid "No" +msgstr "" + +#. Translators: Please do not add spaces around commas. +#: template/defaultfilters.py:875 +msgid "yes,no,maybe" +msgstr "" + +#: template/defaultfilters.py:905 template/defaultfilters.py:922 +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "" +msgstr[1] "" + +#: template/defaultfilters.py:924 +#, python-format +msgid "%s KB" +msgstr "" + +#: template/defaultfilters.py:926 +#, python-format +msgid "%s MB" +msgstr "" + +#: template/defaultfilters.py:928 +#, python-format +msgid "%s GB" +msgstr "" + +#: template/defaultfilters.py:930 +#, python-format +msgid "%s TB" +msgstr "" + +#: template/defaultfilters.py:932 +#, python-format +msgid "%s PB" +msgstr "" + +#: utils/dateformat.py:73 +msgid "p.m." +msgstr "" + +#: utils/dateformat.py:74 +msgid "a.m." +msgstr "" + +#: utils/dateformat.py:79 +msgid "PM" +msgstr "" + +#: utils/dateformat.py:80 +msgid "AM" +msgstr "" + +#: utils/dateformat.py:152 +msgid "midnight" +msgstr "" + +#: utils/dateformat.py:154 +msgid "noon" +msgstr "" + +#: utils/dates.py:7 +msgid "Monday" +msgstr "" + +#: utils/dates.py:8 +msgid "Tuesday" +msgstr "" + +#: utils/dates.py:9 +msgid "Wednesday" +msgstr "" + +#: utils/dates.py:10 +msgid "Thursday" +msgstr "" + +#: utils/dates.py:11 +msgid "Friday" +msgstr "" + +#: utils/dates.py:12 +msgid "Saturday" +msgstr "" + +#: utils/dates.py:13 +msgid "Sunday" +msgstr "" + +#: utils/dates.py:16 +msgid "Mon" +msgstr "" + +#: utils/dates.py:17 +msgid "Tue" +msgstr "" + +#: utils/dates.py:18 +msgid "Wed" +msgstr "" + +#: utils/dates.py:19 +msgid "Thu" +msgstr "" + +#: utils/dates.py:20 +msgid "Fri" +msgstr "" + +#: utils/dates.py:21 +msgid "Sat" +msgstr "" + +#: utils/dates.py:22 +msgid "Sun" +msgstr "" + +#: utils/dates.py:25 +msgid "January" +msgstr "" + +#: utils/dates.py:26 +msgid "February" +msgstr "" + +#: utils/dates.py:27 +msgid "March" +msgstr "" + +#: utils/dates.py:28 +msgid "April" +msgstr "" + +#: utils/dates.py:29 +msgid "May" +msgstr "" + +#: utils/dates.py:30 +msgid "June" +msgstr "" + +#: utils/dates.py:31 +msgid "July" +msgstr "" + +#: utils/dates.py:32 +msgid "August" +msgstr "" + +#: utils/dates.py:33 +msgid "September" +msgstr "" + +#: utils/dates.py:34 +msgid "October" +msgstr "" + +#: utils/dates.py:35 +msgid "November" +msgstr "" + +#: utils/dates.py:36 +msgid "December" +msgstr "" + +#: utils/dates.py:39 +msgid "jan" +msgstr "" + +#: utils/dates.py:40 +msgid "feb" +msgstr "" + +#: utils/dates.py:41 +msgid "mar" +msgstr "" + +#: utils/dates.py:42 +msgid "apr" +msgstr "" + +#: utils/dates.py:43 +msgid "may" +msgstr "" + +#: utils/dates.py:44 +msgid "jun" +msgstr "" + +#: utils/dates.py:45 +msgid "jul" +msgstr "" + +#: utils/dates.py:46 +msgid "aug" +msgstr "" + +#: utils/dates.py:47 +msgid "sep" +msgstr "" + +#: utils/dates.py:48 +msgid "oct" +msgstr "" + +#: utils/dates.py:49 +msgid "nov" +msgstr "" + +#: utils/dates.py:50 +msgid "dec" +msgstr "" + +#: utils/dates.py:53 +msgctxt "abbrev. month" +msgid "Jan." +msgstr "" + +#: utils/dates.py:54 +msgctxt "abbrev. month" +msgid "Feb." +msgstr "" + +#: utils/dates.py:55 +msgctxt "abbrev. month" +msgid "March" +msgstr "" + +#: utils/dates.py:56 +msgctxt "abbrev. month" +msgid "April" +msgstr "" + +#: utils/dates.py:57 +msgctxt "abbrev. month" +msgid "May" +msgstr "" + +#: utils/dates.py:58 +msgctxt "abbrev. month" +msgid "June" +msgstr "" + +#: utils/dates.py:59 +msgctxt "abbrev. month" +msgid "July" +msgstr "" + +#: utils/dates.py:60 +msgctxt "abbrev. month" +msgid "Aug." +msgstr "" + +#: utils/dates.py:61 +msgctxt "abbrev. month" +msgid "Sept." +msgstr "" + +#: utils/dates.py:62 +msgctxt "abbrev. month" +msgid "Oct." +msgstr "" + +#: utils/dates.py:63 +msgctxt "abbrev. month" +msgid "Nov." +msgstr "" + +#: utils/dates.py:64 +msgctxt "abbrev. month" +msgid "Dec." +msgstr "" + +#: utils/dates.py:67 +msgctxt "alt. month" +msgid "January" +msgstr "" + +#: utils/dates.py:68 +msgctxt "alt. month" +msgid "February" +msgstr "" + +#: utils/dates.py:69 +msgctxt "alt. month" +msgid "March" +msgstr "" + +#: utils/dates.py:70 +msgctxt "alt. month" +msgid "April" +msgstr "" + +#: utils/dates.py:71 +msgctxt "alt. month" +msgid "May" +msgstr "" + +#: utils/dates.py:72 +msgctxt "alt. month" +msgid "June" +msgstr "" + +#: utils/dates.py:73 +msgctxt "alt. month" +msgid "July" +msgstr "" + +#: utils/dates.py:74 +msgctxt "alt. month" +msgid "August" +msgstr "" + +#: utils/dates.py:75 +msgctxt "alt. month" +msgid "September" +msgstr "" + +#: utils/dates.py:76 +msgctxt "alt. month" +msgid "October" +msgstr "" + +#: utils/dates.py:77 +msgctxt "alt. month" +msgid "November" +msgstr "" + +#: utils/dates.py:78 +msgctxt "alt. month" +msgid "December" +msgstr "" + +#: utils/ipv6.py:8 +msgid "This is not a valid IPv6 address." +msgstr "" + +#: utils/text.py:70 +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +#: utils/text.py:255 +msgid "or" +msgstr "" + +#. Translators: This string is used as a separator between list elements +#: utils/text.py:274 utils/timesince.py:135 +msgid ", " +msgstr "" + +#: utils/timesince.py:8 +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "" +msgstr[1] "" + +#: utils/timesince.py:9 +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "" +msgstr[1] "" + +#: utils/timesince.py:10 +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "" +msgstr[1] "" + +#: utils/timesince.py:11 +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "" +msgstr[1] "" + +#: utils/timesince.py:12 +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "" +msgstr[1] "" + +#: utils/timesince.py:13 +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "" +msgstr[1] "" + +#: views/csrf.py:29 +msgid "Forbidden" +msgstr "" + +#: views/csrf.py:30 +msgid "CSRF verification failed. Request aborted." +msgstr "" + +#: views/csrf.py:34 +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +#: views/csrf.py:40 +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +#: views/csrf.py:45 +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +#: views/csrf.py:54 +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +#: views/csrf.py:60 +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +#: views/csrf.py:66 +msgid "More information is available with DEBUG=True." +msgstr "" + +#: views/generic/dates.py:44 +msgid "No year specified" +msgstr "" + +#: views/generic/dates.py:64 views/generic/dates.py:115 +#: views/generic/dates.py:214 +msgid "Date out of range" +msgstr "" + +#: views/generic/dates.py:94 +msgid "No month specified" +msgstr "" + +#: views/generic/dates.py:147 +msgid "No day specified" +msgstr "" + +#: views/generic/dates.py:194 +msgid "No week specified" +msgstr "" + +#: views/generic/dates.py:349 views/generic/dates.py:380 +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "" + +#: views/generic/dates.py:652 +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" + +#: views/generic/dates.py:692 +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#: views/generic/detail.py:56 +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "" + +#: views/generic/list.py:70 +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#: views/generic/list.py:77 +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "" + +#: views/generic/list.py:169 +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +#: views/static.py:48 +msgid "Directory indexes are not allowed here." +msgstr "" + +#: views/static.py:50 +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#: views/static.py:67 views/templates/directory_index.html:8 +#: views/templates/directory_index.html:11 +#, python-format +msgid "Index of %(directory)s" +msgstr "" + +#: views/templates/default_urlconf.html:7 +#: views/templates/default_urlconf.html:220 +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#: views/templates/default_urlconf.html:206 +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +#: views/templates/default_urlconf.html:221 +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" + +#: views/templates/default_urlconf.html:229 +msgid "Django Documentation" +msgstr "" + +#: views/templates/default_urlconf.html:230 +msgid "Topics, references, & how-to’s" +msgstr "" + +#: views/templates/default_urlconf.html:238 +msgid "Tutorial: A Polling App" +msgstr "" + +#: views/templates/default_urlconf.html:239 +msgid "Get started with Django" +msgstr "" + +#: views/templates/default_urlconf.html:247 +msgid "Django Community" +msgstr "" + +#: views/templates/default_urlconf.html:248 +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en/formats.py new file mode 100644 index 0000000..f9d143b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en/formats.py @@ -0,0 +1,65 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date + +# Formatting for date objects. +DATE_FORMAT = "N j, Y" +# Formatting for time objects. +TIME_FORMAT = "P" +# Formatting for datetime objects. +DATETIME_FORMAT = "N j, Y, P" +# Formatting for date objects when only the year and month are relevant. +YEAR_MONTH_FORMAT = "F Y" +# Formatting for date objects when only the month and day are relevant. +MONTH_DAY_FORMAT = "F j" +# Short formatting for date objects. +SHORT_DATE_FORMAT = "m/d/Y" +# Short formatting for datetime objects. +SHORT_DATETIME_FORMAT = "m/d/Y P" +# First day of week, to be used on calendars. +# 0 means Sunday, 1 means Monday... +FIRST_DAY_OF_WEEK = 0 + +# Formats to be used when parsing dates from input boxes, in order. +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# Note that these format strings are different from the ones to display dates. +# Kept ISO formats as they are in first position +DATE_INPUT_FORMATS = [ + "%Y-%m-%d", # '2006-10-25' + "%m/%d/%Y", # '10/25/2006' + "%m/%d/%y", # '10/25/06' + "%b %d %Y", # 'Oct 25 2006' + "%b %d, %Y", # 'Oct 25, 2006' + "%d %b %Y", # '25 Oct 2006' + "%d %b, %Y", # '25 Oct, 2006' + "%B %d %Y", # 'October 25 2006' + "%B %d, %Y", # 'October 25, 2006' + "%d %B %Y", # '25 October 2006' + "%d %B, %Y", # '25 October, 2006' +] +DATETIME_INPUT_FORMATS = [ + "%Y-%m-%d %H:%M:%S", # '2006-10-25 14:30:59' + "%Y-%m-%d %H:%M:%S.%f", # '2006-10-25 14:30:59.000200' + "%Y-%m-%d %H:%M", # '2006-10-25 14:30' + "%m/%d/%Y %H:%M:%S", # '10/25/2006 14:30:59' + "%m/%d/%Y %H:%M:%S.%f", # '10/25/2006 14:30:59.000200' + "%m/%d/%Y %H:%M", # '10/25/2006 14:30' + "%m/%d/%y %H:%M:%S", # '10/25/06 14:30:59' + "%m/%d/%y %H:%M:%S.%f", # '10/25/06 14:30:59.000200' + "%m/%d/%y %H:%M", # '10/25/06 14:30' +] +TIME_INPUT_FORMATS = [ + "%H:%M:%S", # '14:30:59' + "%H:%M:%S.%f", # '14:30:59.000200' + "%H:%M", # '14:30' +] + +# Decimal separator symbol. +DECIMAL_SEPARATOR = "." +# Thousand separator symbol. +THOUSAND_SEPARATOR = "," +# Number of digits that will be together, when splitting them by +# THOUSAND_SEPARATOR. 0 means no grouping, 3 means splitting by thousands. +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_AU/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_AU/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d31b977 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_AU/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_AU/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_AU/LC_MESSAGES/django.po new file mode 100644 index 0000000..a0a3ed8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_AU/LC_MESSAGES/django.po @@ -0,0 +1,1299 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Tom Fifield , 2014 +# Tom Fifield , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2021-11-18 21:19+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: English (Australia) (http://www.transifex.com/django/django/" +"language/en_AU/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_AU\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Afrikaans" + +msgid "Arabic" +msgstr "Arabic" + +msgid "Algerian Arabic" +msgstr "Algerian Arabic" + +msgid "Asturian" +msgstr "Asturian" + +msgid "Azerbaijani" +msgstr "Azerbaijani" + +msgid "Bulgarian" +msgstr "Bulgarian" + +msgid "Belarusian" +msgstr "Belarusian" + +msgid "Bengali" +msgstr "Bengali" + +msgid "Breton" +msgstr "Breton" + +msgid "Bosnian" +msgstr "Bosnian" + +msgid "Catalan" +msgstr "Catalan" + +msgid "Czech" +msgstr "Czech" + +msgid "Welsh" +msgstr "Welsh" + +msgid "Danish" +msgstr "Danish" + +msgid "German" +msgstr "German" + +msgid "Lower Sorbian" +msgstr "Lower Sorbian" + +msgid "Greek" +msgstr "Greek" + +msgid "English" +msgstr "English" + +msgid "Australian English" +msgstr "Australian English" + +msgid "British English" +msgstr "British English" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Spanish" + +msgid "Argentinian Spanish" +msgstr "Argentinian Spanish" + +msgid "Colombian Spanish" +msgstr "Colombian Spanish" + +msgid "Mexican Spanish" +msgstr "Mexican Spanish" + +msgid "Nicaraguan Spanish" +msgstr "Nicaraguan Spanish" + +msgid "Venezuelan Spanish" +msgstr "Venezuelan Spanish" + +msgid "Estonian" +msgstr "Estonian" + +msgid "Basque" +msgstr "Basque" + +msgid "Persian" +msgstr "Persian" + +msgid "Finnish" +msgstr "Finnish" + +msgid "French" +msgstr "French" + +msgid "Frisian" +msgstr "Frisian" + +msgid "Irish" +msgstr "Irish" + +msgid "Scottish Gaelic" +msgstr "Scottish Gaelic" + +msgid "Galician" +msgstr "Galician" + +msgid "Hebrew" +msgstr "Hebrew" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Croatian" + +msgid "Upper Sorbian" +msgstr "Upper Sorbian" + +msgid "Hungarian" +msgstr "Hungarian" + +msgid "Armenian" +msgstr "Armenian" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonesian" + +msgid "Igbo" +msgstr "Igbo" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Icelandic" + +msgid "Italian" +msgstr "Italian" + +msgid "Japanese" +msgstr "Japanese" + +msgid "Georgian" +msgstr "Georgian" + +msgid "Kabyle" +msgstr "Kabyle" + +msgid "Kazakh" +msgstr "Kazakh" + +msgid "Khmer" +msgstr "Khmer" + +msgid "Kannada" +msgstr "Kannada" + +msgid "Korean" +msgstr "Korean" + +msgid "Kyrgyz" +msgstr "Kyrgyz" + +msgid "Luxembourgish" +msgstr "Luxembourgish" + +msgid "Lithuanian" +msgstr "Lithuanian" + +msgid "Latvian" +msgstr "Latvian" + +msgid "Macedonian" +msgstr "Macedonian" + +msgid "Malayalam" +msgstr "Malayalam" + +msgid "Mongolian" +msgstr "Mongolian" + +msgid "Marathi" +msgstr "Marathi" + +msgid "Malay" +msgstr "" + +msgid "Burmese" +msgstr "Burmese" + +msgid "Norwegian Bokmål" +msgstr "Norwegian Bokmål" + +msgid "Nepali" +msgstr "Nepali" + +msgid "Dutch" +msgstr "Dutch" + +msgid "Norwegian Nynorsk" +msgstr "Norwegian Nynorsk" + +msgid "Ossetic" +msgstr "Ossetic" + +msgid "Punjabi" +msgstr "Punjabi" + +msgid "Polish" +msgstr "Polish" + +msgid "Portuguese" +msgstr "Portuguese" + +msgid "Brazilian Portuguese" +msgstr "Brazilian Portuguese" + +msgid "Romanian" +msgstr "Romanian" + +msgid "Russian" +msgstr "Russian" + +msgid "Slovak" +msgstr "Slovak" + +msgid "Slovenian" +msgstr "Slovenian" + +msgid "Albanian" +msgstr "Albanian" + +msgid "Serbian" +msgstr "Serbian" + +msgid "Serbian Latin" +msgstr "Serbian Latin" + +msgid "Swedish" +msgstr "Swedish" + +msgid "Swahili" +msgstr "Swahili" + +msgid "Tamil" +msgstr "Tamil" + +msgid "Telugu" +msgstr "Telugu" + +msgid "Tajik" +msgstr "Tajik" + +msgid "Thai" +msgstr "Thai" + +msgid "Turkmen" +msgstr "Turkmen" + +msgid "Turkish" +msgstr "Turkish" + +msgid "Tatar" +msgstr "Tatar" + +msgid "Udmurt" +msgstr "Udmurt" + +msgid "Ukrainian" +msgstr "Ukrainian" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "Uzbek" + +msgid "Vietnamese" +msgstr "Vietnamese" + +msgid "Simplified Chinese" +msgstr "Simplified Chinese" + +msgid "Traditional Chinese" +msgstr "Traditional Chinese" + +msgid "Messages" +msgstr "Messages" + +msgid "Site Maps" +msgstr "Site Maps" + +msgid "Static Files" +msgstr "Static Files" + +msgid "Syndication" +msgstr "Syndication" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "That page number is not an integer" + +msgid "That page number is less than 1" +msgstr "That page number is less than 1" + +msgid "That page contains no results" +msgstr "That page contains no results" + +msgid "Enter a valid value." +msgstr "Enter a valid value." + +msgid "Enter a valid URL." +msgstr "Enter a valid URL." + +msgid "Enter a valid integer." +msgstr "Enter a valid integer." + +msgid "Enter a valid email address." +msgstr "Enter a valid email address." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." + +msgid "Enter a valid IPv4 address." +msgstr "Enter a valid IPv4 address." + +msgid "Enter a valid IPv6 address." +msgstr "Enter a valid IPv6 address." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Enter a valid IPv4 or IPv6 address." + +msgid "Enter only digits separated by commas." +msgstr "Enter only digits separated by commas." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Ensure this value is %(limit_value)s (it is %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Ensure this value is less than or equal to %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Ensure this value is greater than or equal to %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgstr[1] "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgstr[1] "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Enter a number." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Ensure that there are no more than %(max)s digit in total." +msgstr[1] "Ensure that there are no more than %(max)s digits in total." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Ensure that there are no more than %(max)s decimal place." +msgstr[1] "Ensure that there are no more than %(max)s decimal places." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgstr[1] "" +"Ensure that there are no more than %(max)s digits before the decimal point." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Null characters are not allowed." + +msgid "and" +msgstr "and" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s with this %(field_labels)s already exists." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Value %(value)r is not a valid choice." + +msgid "This field cannot be null." +msgstr "This field cannot be null." + +msgid "This field cannot be blank." +msgstr "This field cannot be blank." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s with this %(field_label)s already exists." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Field of type: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "“%(value)s” value must be either True or False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "“%(value)s” value must be either True, False, or None." + +msgid "Boolean (Either True or False)" +msgstr "Boolean (Either True or False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "String (up to %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "Comma-separated integers" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." + +msgid "Date (without time)" +msgstr "Date (without time)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." + +msgid "Date (with time)" +msgstr "Date (with time)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "“%(value)s” value must be a decimal number." + +msgid "Decimal number" +msgstr "Decimal number" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." + +msgid "Duration" +msgstr "Duration" + +msgid "Email address" +msgstr "Email address" + +msgid "File path" +msgstr "File path" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "“%(value)s” value must be a float." + +msgid "Floating point number" +msgstr "Floating point number" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "“%(value)s” value must be an integer." + +msgid "Integer" +msgstr "Integer" + +msgid "Big (8 byte) integer" +msgstr "Big (8 byte) integer" + +msgid "Small integer" +msgstr "Small integer" + +msgid "IPv4 address" +msgstr "IPv4 address" + +msgid "IP address" +msgstr "IP address" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "“%(value)s” value must be either None, True or False." + +msgid "Boolean (Either True, False or None)" +msgstr "Boolean (Either True, False or None)" + +msgid "Positive big integer" +msgstr "Positive big integer" + +msgid "Positive integer" +msgstr "Positive integer" + +msgid "Positive small integer" +msgstr "Positive small integer" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (up to %(max_length)s)" + +msgid "Text" +msgstr "Text" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." + +msgid "Time" +msgstr "Time" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Raw binary data" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "“%(value)s” is not a valid UUID." + +msgid "Universally unique identifier" +msgstr "Universally unique identifier" + +msgid "File" +msgstr "File" + +msgid "Image" +msgstr "Image" + +msgid "A JSON object" +msgstr "A JSON object" + +msgid "Value must be valid JSON." +msgstr "Value must be valid JSON." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(model)s instance with %(field)s %(value)r does not exist." + +msgid "Foreign Key (type determined by related field)" +msgstr "Foreign Key (type determined by related field)" + +msgid "One-to-one relationship" +msgstr "One-to-one relationship" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s relationship" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s relationships" + +msgid "Many-to-many relationship" +msgstr "Many-to-many relationship" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "This field is required." + +msgid "Enter a whole number." +msgstr "Enter a whole number." + +msgid "Enter a valid date." +msgstr "Enter a valid date." + +msgid "Enter a valid time." +msgstr "Enter a valid time." + +msgid "Enter a valid date/time." +msgstr "Enter a valid date/time." + +msgid "Enter a valid duration." +msgstr "Enter a valid duration." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "The number of days must be between {min_days} and {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "No file was submitted. Check the encoding type on the form." + +msgid "No file was submitted." +msgstr "No file was submitted." + +msgid "The submitted file is empty." +msgstr "The submitted file is empty." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Ensure this filename has at most %(max)d character (it has %(length)d)." +msgstr[1] "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Please either submit a file or check the clear checkbox, not both." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Select a valid choice. %(value)s is not one of the available choices." + +msgid "Enter a list of values." +msgstr "Enter a list of values." + +msgid "Enter a complete value." +msgstr "Enter a complete value." + +msgid "Enter a valid UUID." +msgstr "Enter a valid UUID." + +msgid "Enter a valid JSON." +msgstr "Enter a valid JSON." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Hidden field %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." + +#, python-format +msgid "Please submit at most %d form." +msgid_plural "Please submit at most %d forms." +msgstr[0] "Please submit at most %d form." +msgstr[1] "Please submit at most %d forms." + +#, python-format +msgid "Please submit at least %d form." +msgid_plural "Please submit at least %d forms." +msgstr[0] "Please submit at least %d form." +msgstr[1] "Please submit at least %d forms." + +msgid "Order" +msgstr "Order" + +msgid "Delete" +msgstr "Delete" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Please correct the duplicate data for %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Please correct the duplicate data for %(field)s, which must be unique." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Please correct the duplicate values below." + +msgid "The inline value did not match the parent instance." +msgstr "The inline value did not match the parent instance." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Select a valid choice. That choice is not one of the available choices." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "“%(pk)s” is not a valid value." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." + +msgid "Clear" +msgstr "Clear" + +msgid "Currently" +msgstr "Currently" + +msgid "Change" +msgstr "Change" + +msgid "Unknown" +msgstr "Unknown" + +msgid "Yes" +msgstr "Yes" + +msgid "No" +msgstr "No" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "yes,no,maybe" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d byte" +msgstr[1] "%(size)d bytes" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "midnight" + +msgid "noon" +msgstr "noon" + +msgid "Monday" +msgstr "Monday" + +msgid "Tuesday" +msgstr "Tuesday" + +msgid "Wednesday" +msgstr "Wednesday" + +msgid "Thursday" +msgstr "Thursday" + +msgid "Friday" +msgstr "Friday" + +msgid "Saturday" +msgstr "Saturday" + +msgid "Sunday" +msgstr "Sunday" + +msgid "Mon" +msgstr "Mon" + +msgid "Tue" +msgstr "Tue" + +msgid "Wed" +msgstr "Wed" + +msgid "Thu" +msgstr "Thu" + +msgid "Fri" +msgstr "Fri" + +msgid "Sat" +msgstr "Sat" + +msgid "Sun" +msgstr "Sun" + +msgid "January" +msgstr "January" + +msgid "February" +msgstr "February" + +msgid "March" +msgstr "March" + +msgid "April" +msgstr "April" + +msgid "May" +msgstr "May" + +msgid "June" +msgstr "June" + +msgid "July" +msgstr "July" + +msgid "August" +msgstr "August" + +msgid "September" +msgstr "September" + +msgid "October" +msgstr "October" + +msgid "November" +msgstr "November" + +msgid "December" +msgstr "December" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "apr" + +msgid "may" +msgstr "may" + +msgid "jun" +msgstr "jun" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "aug" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "oct" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dec" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "March" + +msgctxt "abbrev. month" +msgid "April" +msgstr "April" + +msgctxt "abbrev. month" +msgid "May" +msgstr "May" + +msgctxt "abbrev. month" +msgid "June" +msgstr "June" + +msgctxt "abbrev. month" +msgid "July" +msgstr "July" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Aug." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Sept." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Oct." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dec." + +msgctxt "alt. month" +msgid "January" +msgstr "January" + +msgctxt "alt. month" +msgid "February" +msgstr "February" + +msgctxt "alt. month" +msgid "March" +msgstr "March" + +msgctxt "alt. month" +msgid "April" +msgstr "April" + +msgctxt "alt. month" +msgid "May" +msgstr "May" + +msgctxt "alt. month" +msgid "June" +msgstr "June" + +msgctxt "alt. month" +msgid "July" +msgstr "July" + +msgctxt "alt. month" +msgid "August" +msgstr "August" + +msgctxt "alt. month" +msgid "September" +msgstr "September" + +msgctxt "alt. month" +msgid "October" +msgstr "October" + +msgctxt "alt. month" +msgid "November" +msgstr "November" + +msgctxt "alt. month" +msgid "December" +msgstr "December" + +msgid "This is not a valid IPv6 address." +msgstr "This is not a valid IPv6 address." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "or" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "" +msgstr[1] "" + +msgid "Forbidden" +msgstr "Forbidden" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF verification failed. Request aborted." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." + +msgid "More information is available with DEBUG=True." +msgstr "More information is available with DEBUG=True." + +msgid "No year specified" +msgstr "No year specified" + +msgid "Date out of range" +msgstr "Date out of range" + +msgid "No month specified" +msgstr "No month specified" + +msgid "No day specified" +msgstr "No day specified" + +msgid "No week specified" +msgstr "No week specified" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "No %(verbose_name_plural)s available" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Invalid date string “%(datestr)s” given format “%(format)s”" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "No %(verbose_name)s found matching the query" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Page is not “last”, nor can it be converted to an int." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Invalid page (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Empty list and “%(class_name)s.allow_empty” is False." + +msgid "Directory indexes are not allowed here." +msgstr "Directory indexes are not allowed here." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "“%(path)s” does not exist" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Index of %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "The install worked successfully! Congratulations!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"View release notes for Django %(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." + +msgid "Django Documentation" +msgstr "Django Documentation" + +msgid "Topics, references, & how-to’s" +msgstr "Topics, references, & how-to’s" + +msgid "Tutorial: A Polling App" +msgstr "Tutorial: A Polling App" + +msgid "Get started with Django" +msgstr "Get started with Django" + +msgid "Django Community" +msgstr "Django Community" + +msgid "Connect, get help, or contribute" +msgstr "Connect, get help, or contribute" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_AU/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_AU/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_AU/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_AU/formats.py new file mode 100644 index 0000000..caa6f72 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_AU/formats.py @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j M Y" # '25 Oct 2006' +TIME_FORMAT = "P" # '2:30 p.m.' +DATETIME_FORMAT = "j M Y, P" # '25 Oct 2006, 2:30 p.m.' +YEAR_MONTH_FORMAT = "F Y" # 'October 2006' +MONTH_DAY_FORMAT = "j F" # '25 October' +SHORT_DATE_FORMAT = "d/m/Y" # '25/10/2006' +SHORT_DATETIME_FORMAT = "d/m/Y P" # '25/10/2006 2:30 p.m.' +FIRST_DAY_OF_WEEK = 0 # Sunday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d/%m/%Y", # '25/10/2006' + "%d/%m/%y", # '25/10/06' + # "%b %d %Y", # 'Oct 25 2006' + # "%b %d, %Y", # 'Oct 25, 2006' + # "%d %b %Y", # '25 Oct 2006' + # "%d %b, %Y", # '25 Oct, 2006' + # "%B %d %Y", # 'October 25 2006' + # "%B %d, %Y", # 'October 25, 2006' + # "%d %B %Y", # '25 October 2006' + # "%d %B, %Y", # '25 October, 2006' +] +DATETIME_INPUT_FORMATS = [ + "%Y-%m-%d %H:%M:%S", # '2006-10-25 14:30:59' + "%Y-%m-%d %H:%M:%S.%f", # '2006-10-25 14:30:59.000200' + "%Y-%m-%d %H:%M", # '2006-10-25 14:30' + "%d/%m/%Y %H:%M:%S", # '25/10/2006 14:30:59' + "%d/%m/%Y %H:%M:%S.%f", # '25/10/2006 14:30:59.000200' + "%d/%m/%Y %H:%M", # '25/10/2006 14:30' + "%d/%m/%y %H:%M:%S", # '25/10/06 14:30:59' + "%d/%m/%y %H:%M:%S.%f", # '25/10/06 14:30:59.000200' + "%d/%m/%y %H:%M", # '25/10/06 14:30' +] +DECIMAL_SEPARATOR = "." +THOUSAND_SEPARATOR = "," +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_GB/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_GB/LC_MESSAGES/django.mo new file mode 100644 index 0000000..bc4b2cc Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_GB/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_GB/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_GB/LC_MESSAGES/django.po new file mode 100644 index 0000000..348adb0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_GB/LC_MESSAGES/django.po @@ -0,0 +1,1221 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# jon_atkinson , 2011-2012 +# Ross Poulton , 2011-2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: English (United Kingdom) (http://www.transifex.com/django/" +"django/language/en_GB/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_GB\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "" + +msgid "Arabic" +msgstr "Arabic" + +msgid "Asturian" +msgstr "" + +msgid "Azerbaijani" +msgstr "Azerbaijani" + +msgid "Bulgarian" +msgstr "Bulgarian" + +msgid "Belarusian" +msgstr "" + +msgid "Bengali" +msgstr "Bengali" + +msgid "Breton" +msgstr "" + +msgid "Bosnian" +msgstr "Bosnian" + +msgid "Catalan" +msgstr "Catalan" + +msgid "Czech" +msgstr "Czech" + +msgid "Welsh" +msgstr "Welsh" + +msgid "Danish" +msgstr "Danish" + +msgid "German" +msgstr "German" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "Greek" + +msgid "English" +msgstr "English" + +msgid "Australian English" +msgstr "" + +msgid "British English" +msgstr "British English" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Spanish" + +msgid "Argentinian Spanish" +msgstr "Argentinian Spanish" + +msgid "Colombian Spanish" +msgstr "" + +msgid "Mexican Spanish" +msgstr "Mexican Spanish" + +msgid "Nicaraguan Spanish" +msgstr "Nicaraguan Spanish" + +msgid "Venezuelan Spanish" +msgstr "" + +msgid "Estonian" +msgstr "Estonian" + +msgid "Basque" +msgstr "Basque" + +msgid "Persian" +msgstr "Persian" + +msgid "Finnish" +msgstr "Finnish" + +msgid "French" +msgstr "French" + +msgid "Frisian" +msgstr "Frisian" + +msgid "Irish" +msgstr "Irish" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "Galician" + +msgid "Hebrew" +msgstr "Hebrew" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Croatian" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "Hungarian" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "" + +msgid "Indonesian" +msgstr "Indonesian" + +msgid "Ido" +msgstr "" + +msgid "Icelandic" +msgstr "Icelandic" + +msgid "Italian" +msgstr "Italian" + +msgid "Japanese" +msgstr "Japanese" + +msgid "Georgian" +msgstr "Georgian" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "Kazakh" + +msgid "Khmer" +msgstr "Khmer" + +msgid "Kannada" +msgstr "Kannada" + +msgid "Korean" +msgstr "Korean" + +msgid "Luxembourgish" +msgstr "" + +msgid "Lithuanian" +msgstr "Lithuanian" + +msgid "Latvian" +msgstr "Latvian" + +msgid "Macedonian" +msgstr "Macedonian" + +msgid "Malayalam" +msgstr "Malayalam" + +msgid "Mongolian" +msgstr "Mongolian" + +msgid "Marathi" +msgstr "" + +msgid "Burmese" +msgstr "" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "Nepali" + +msgid "Dutch" +msgstr "Dutch" + +msgid "Norwegian Nynorsk" +msgstr "Norwegian Nynorsk" + +msgid "Ossetic" +msgstr "" + +msgid "Punjabi" +msgstr "Punjabi" + +msgid "Polish" +msgstr "Polish" + +msgid "Portuguese" +msgstr "Portuguese" + +msgid "Brazilian Portuguese" +msgstr "Brazilian Portuguese" + +msgid "Romanian" +msgstr "Romanian" + +msgid "Russian" +msgstr "Russian" + +msgid "Slovak" +msgstr "Slovak" + +msgid "Slovenian" +msgstr "Slovenian" + +msgid "Albanian" +msgstr "Albanian" + +msgid "Serbian" +msgstr "Serbian" + +msgid "Serbian Latin" +msgstr "Serbian Latin" + +msgid "Swedish" +msgstr "Swedish" + +msgid "Swahili" +msgstr "Swahili" + +msgid "Tamil" +msgstr "Tamil" + +msgid "Telugu" +msgstr "Telugu" + +msgid "Thai" +msgstr "Thai" + +msgid "Turkish" +msgstr "Turkish" + +msgid "Tatar" +msgstr "Tatar" + +msgid "Udmurt" +msgstr "" + +msgid "Ukrainian" +msgstr "Ukrainian" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "Vietnamese" + +msgid "Simplified Chinese" +msgstr "Simplified Chinese" + +msgid "Traditional Chinese" +msgstr "Traditional Chinese" + +msgid "Messages" +msgstr "" + +msgid "Site Maps" +msgstr "" + +msgid "Static Files" +msgstr "" + +msgid "Syndication" +msgstr "" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "Enter a valid value." + +msgid "Enter a valid URL." +msgstr "Enter a valid URL." + +msgid "Enter a valid integer." +msgstr "" + +msgid "Enter a valid email address." +msgstr "" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Enter a valid IPv4 address." + +msgid "Enter a valid IPv6 address." +msgstr "Enter a valid IPv6 address." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Enter a valid IPv4 or IPv6 address." + +msgid "Enter only digits separated by commas." +msgstr "Enter only digits separated by commas." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Ensure this value is %(limit_value)s (it is %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Ensure this value is less than or equal to %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Ensure this value is greater than or equal to %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Enter a number." +msgstr "Enter a number." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "and" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "This field cannot be null." + +msgid "This field cannot be blank." +msgstr "This field cannot be blank." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s with this %(field_label)s already exists." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Field of type: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "Boolean (Either True or False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "String (up to %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "Comma-separated integers" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "Date (without time)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Date (with time)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Decimal number" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "" + +msgid "Email address" +msgstr "Email address" + +msgid "File path" +msgstr "File path" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "Floating point number" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "Integer" + +msgid "Big (8 byte) integer" +msgstr "Big (8 byte) integer" + +msgid "IPv4 address" +msgstr "IPv4 address" + +msgid "IP address" +msgstr "IP address" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "Boolean (Either True, False or None)" + +msgid "Positive integer" +msgstr "Positive integer" + +msgid "Positive small integer" +msgstr "Positive small integer" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (up to %(max_length)s)" + +msgid "Small integer" +msgstr "Small integer" + +msgid "Text" +msgstr "Text" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Time" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "File" + +msgid "Image" +msgstr "Image" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "Foreign Key (type determined by related field)" + +msgid "One-to-one relationship" +msgstr "One-to-one relationship" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "Many-to-many relationship" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr "" + +msgid "This field is required." +msgstr "This field is required." + +msgid "Enter a whole number." +msgstr "Enter a whole number." + +msgid "Enter a valid date." +msgstr "Enter a valid date." + +msgid "Enter a valid time." +msgstr "Enter a valid time." + +msgid "Enter a valid date/time." +msgstr "Enter a valid date/time." + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "No file was submitted. Check the encoding type on the form." + +msgid "No file was submitted." +msgstr "No file was submitted." + +msgid "The submitted file is empty." +msgstr "The submitted file is empty." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Please either submit a file or check the clear checkbox, not both." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Select a valid choice. %(value)s is not one of the available choices." + +msgid "Enter a list of values." +msgstr "Enter a list of values." + +msgid "Enter a complete value." +msgstr "" + +msgid "Enter a valid UUID." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr "" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "Order" + +msgid "Delete" +msgstr "Delete" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Please correct the duplicate data for %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Please correct the duplicate data for %(field)s, which must be unique." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Please correct the duplicate values below." + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Select a valid choice. That choice is not one of the available choices." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Clear" + +msgid "Currently" +msgstr "Currently" + +msgid "Change" +msgstr "Change" + +msgid "Unknown" +msgstr "Unknown" + +msgid "Yes" +msgstr "Yes" + +msgid "No" +msgstr "No" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "yes,no,maybe" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d byte" +msgstr[1] "%(size)d bytes" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "midnight" + +msgid "noon" +msgstr "noon" + +msgid "Monday" +msgstr "Monday" + +msgid "Tuesday" +msgstr "Tuesday" + +msgid "Wednesday" +msgstr "Wednesday" + +msgid "Thursday" +msgstr "Thursday" + +msgid "Friday" +msgstr "Friday" + +msgid "Saturday" +msgstr "Saturday" + +msgid "Sunday" +msgstr "Sunday" + +msgid "Mon" +msgstr "Mon" + +msgid "Tue" +msgstr "Tue" + +msgid "Wed" +msgstr "Wed" + +msgid "Thu" +msgstr "Thu" + +msgid "Fri" +msgstr "Fri" + +msgid "Sat" +msgstr "Sat" + +msgid "Sun" +msgstr "Sun" + +msgid "January" +msgstr "January" + +msgid "February" +msgstr "February" + +msgid "March" +msgstr "March" + +msgid "April" +msgstr "April" + +msgid "May" +msgstr "May" + +msgid "June" +msgstr "June" + +msgid "July" +msgstr "July" + +msgid "August" +msgstr "August" + +msgid "September" +msgstr "September" + +msgid "October" +msgstr "October" + +msgid "November" +msgstr "November" + +msgid "December" +msgstr "December" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "apr" + +msgid "may" +msgstr "may" + +msgid "jun" +msgstr "jun" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "aug" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "oct" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dec" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "March" + +msgctxt "abbrev. month" +msgid "April" +msgstr "April" + +msgctxt "abbrev. month" +msgid "May" +msgstr "May" + +msgctxt "abbrev. month" +msgid "June" +msgstr "June" + +msgctxt "abbrev. month" +msgid "July" +msgstr "July" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Aug." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Sept." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Oct." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dec." + +msgctxt "alt. month" +msgid "January" +msgstr "January" + +msgctxt "alt. month" +msgid "February" +msgstr "February" + +msgctxt "alt. month" +msgid "March" +msgstr "March" + +msgctxt "alt. month" +msgid "April" +msgstr "April" + +msgctxt "alt. month" +msgid "May" +msgstr "May" + +msgctxt "alt. month" +msgid "June" +msgstr "June" + +msgctxt "alt. month" +msgid "July" +msgstr "July" + +msgctxt "alt. month" +msgid "August" +msgstr "August" + +msgctxt "alt. month" +msgid "September" +msgstr "September" + +msgctxt "alt. month" +msgid "October" +msgstr "October" + +msgctxt "alt. month" +msgid "November" +msgstr "November" + +msgctxt "alt. month" +msgid "December" +msgstr "December" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "or" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" + +msgid "0 minutes" +msgstr "" + +msgid "Forbidden" +msgstr "" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "No year specified" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "No month specified" + +msgid "No day specified" +msgstr "No day specified" + +msgid "No week specified" +msgstr "No week specified" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "No %(verbose_name_plural)s available" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "No %(verbose_name)s found matching the query" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Directory indexes are not allowed here." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Index of %(directory)s" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_GB/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_GB/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_GB/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_GB/formats.py new file mode 100644 index 0000000..bc90da5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_GB/formats.py @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j M Y" # '25 Oct 2006' +TIME_FORMAT = "P" # '2:30 p.m.' +DATETIME_FORMAT = "j M Y, P" # '25 Oct 2006, 2:30 p.m.' +YEAR_MONTH_FORMAT = "F Y" # 'October 2006' +MONTH_DAY_FORMAT = "j F" # '25 October' +SHORT_DATE_FORMAT = "d/m/Y" # '25/10/2006' +SHORT_DATETIME_FORMAT = "d/m/Y P" # '25/10/2006 2:30 p.m.' +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d/%m/%Y", # '25/10/2006' + "%d/%m/%y", # '25/10/06' + # "%b %d %Y", # 'Oct 25 2006' + # "%b %d, %Y", # 'Oct 25, 2006' + # "%d %b %Y", # '25 Oct 2006' + # "%d %b, %Y", # '25 Oct, 2006' + # "%B %d %Y", # 'October 25 2006' + # "%B %d, %Y", # 'October 25, 2006' + # "%d %B %Y", # '25 October 2006' + # "%d %B, %Y", # '25 October, 2006' +] +DATETIME_INPUT_FORMATS = [ + "%Y-%m-%d %H:%M:%S", # '2006-10-25 14:30:59' + "%Y-%m-%d %H:%M:%S.%f", # '2006-10-25 14:30:59.000200' + "%Y-%m-%d %H:%M", # '2006-10-25 14:30' + "%d/%m/%Y %H:%M:%S", # '25/10/2006 14:30:59' + "%d/%m/%Y %H:%M:%S.%f", # '25/10/2006 14:30:59.000200' + "%d/%m/%Y %H:%M", # '25/10/2006 14:30' + "%d/%m/%y %H:%M:%S", # '25/10/06 14:30:59' + "%d/%m/%y %H:%M:%S.%f", # '25/10/06 14:30:59.000200' + "%d/%m/%y %H:%M", # '25/10/06 14:30' +] +DECIMAL_SEPARATOR = "." +THOUSAND_SEPARATOR = "," +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_IE/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_IE/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_IE/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_IE/formats.py new file mode 100644 index 0000000..81b8324 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/en_IE/formats.py @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j M Y" # '25 Oct 2006' +TIME_FORMAT = "H:i" # '14:30' +DATETIME_FORMAT = "j M Y, H:i" # '25 Oct 2006, 14:30' +YEAR_MONTH_FORMAT = "F Y" # 'October 2006' +MONTH_DAY_FORMAT = "j F" # '25 October' +SHORT_DATE_FORMAT = "d/m/Y" # '25/10/2006' +SHORT_DATETIME_FORMAT = "d/m/Y H:i" # '25/10/2006 14:30' +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d/%m/%Y", # '25/10/2006' + "%d/%m/%y", # '25/10/06' + "%d %b %Y", # '25 Oct 2006' + "%d %b, %Y", # '25 Oct, 2006' + "%d %B %Y", # '25 October 2006' + "%d %B, %Y", # '25 October, 2006' +] +DATETIME_INPUT_FORMATS = [ + "%Y-%m-%d %H:%M:%S", # '2006-10-25 14:30:59' + "%Y-%m-%d %H:%M:%S.%f", # '2006-10-25 14:30:59.000200' + "%Y-%m-%d %H:%M", # '2006-10-25 14:30' + "%d/%m/%Y %H:%M:%S", # '25/10/2006 14:30:59' + "%d/%m/%Y %H:%M:%S.%f", # '25/10/2006 14:30:59.000200' + "%d/%m/%Y %H:%M", # '25/10/2006 14:30' + "%d/%m/%y %H:%M:%S", # '25/10/06 14:30:59' + "%d/%m/%y %H:%M:%S.%f", # '25/10/06 14:30:59.000200' + "%d/%m/%y %H:%M", # '25/10/06 14:30' +] +DECIMAL_SEPARATOR = "." +THOUSAND_SEPARATOR = "," +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/eo/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/eo/LC_MESSAGES/django.mo new file mode 100644 index 0000000..05260e5 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/eo/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/eo/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/eo/LC_MESSAGES/django.po new file mode 100644 index 0000000..66a2f38 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/eo/LC_MESSAGES/django.po @@ -0,0 +1,1331 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Batist D 🐍 , 2012-2013 +# Batist D 🐍 , 2013-2019 +# batisteo , 2011 +# Dinu Gherman , 2011 +# kristjan , 2011 +# Matthieu Desplantes , 2021 +# Meiyer , 2022 +# Nikolay Korotkiy , 2017-2018 +# Robin van der Vliet , 2019 +# Adamo Mesha , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-05-17 05:23-0500\n" +"PO-Revision-Date: 2022-05-25 06:49+0000\n" +"Last-Translator: Meiyer , 2022\n" +"Language-Team: Esperanto (http://www.transifex.com/django/django/language/" +"eo/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eo\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Afrikansa" + +msgid "Arabic" +msgstr "Araba" + +msgid "Algerian Arabic" +msgstr "Alĝeria araba" + +msgid "Asturian" +msgstr "Asturia" + +msgid "Azerbaijani" +msgstr "Azerbajĝana" + +msgid "Bulgarian" +msgstr "Bulgara" + +msgid "Belarusian" +msgstr "Belorusa" + +msgid "Bengali" +msgstr "Bengala" + +msgid "Breton" +msgstr "Bretona" + +msgid "Bosnian" +msgstr "Bosnia" + +msgid "Catalan" +msgstr "Kataluna" + +msgid "Czech" +msgstr "Ĉeĥa" + +msgid "Welsh" +msgstr "Kimra" + +msgid "Danish" +msgstr "Dana" + +msgid "German" +msgstr "Germana" + +msgid "Lower Sorbian" +msgstr "Malsuprasaroba" + +msgid "Greek" +msgstr "Greka" + +msgid "English" +msgstr "Angla" + +msgid "Australian English" +msgstr "Angla (Aŭstralia)" + +msgid "British English" +msgstr "Angla (Brita)" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Hispana" + +msgid "Argentinian Spanish" +msgstr "Hispana (Argentinio)" + +msgid "Colombian Spanish" +msgstr "Hispana (Kolombio)" + +msgid "Mexican Spanish" +msgstr "Hispana (Meksiko)" + +msgid "Nicaraguan Spanish" +msgstr "Hispana (Nikaragvo)" + +msgid "Venezuelan Spanish" +msgstr "Hispana (Venezuelo)" + +msgid "Estonian" +msgstr "Estona" + +msgid "Basque" +msgstr "Eŭska" + +msgid "Persian" +msgstr "Persa" + +msgid "Finnish" +msgstr "Finna" + +msgid "French" +msgstr "Franca" + +msgid "Frisian" +msgstr "Frisa" + +msgid "Irish" +msgstr "Irlanda" + +msgid "Scottish Gaelic" +msgstr "Skota gaela" + +msgid "Galician" +msgstr "Galega" + +msgid "Hebrew" +msgstr "Hebrea" + +msgid "Hindi" +msgstr "Hinda" + +msgid "Croatian" +msgstr "Kroata" + +msgid "Upper Sorbian" +msgstr "Suprasoraba" + +msgid "Hungarian" +msgstr "Hungara" + +msgid "Armenian" +msgstr "Armena" + +msgid "Interlingua" +msgstr "Interlingvaa" + +msgid "Indonesian" +msgstr "Indoneza" + +msgid "Igbo" +msgstr "Igba" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Islanda" + +msgid "Italian" +msgstr "Itala" + +msgid "Japanese" +msgstr "Japana" + +msgid "Georgian" +msgstr "Kartvela" + +msgid "Kabyle" +msgstr "Kabila" + +msgid "Kazakh" +msgstr "Kazaĥa" + +msgid "Khmer" +msgstr "Kmera" + +msgid "Kannada" +msgstr "Kanara" + +msgid "Korean" +msgstr "Korea" + +msgid "Kyrgyz" +msgstr "Kirgiza" + +msgid "Luxembourgish" +msgstr "Luksemburga" + +msgid "Lithuanian" +msgstr "Litova" + +msgid "Latvian" +msgstr "Latva" + +msgid "Macedonian" +msgstr "Makedona" + +msgid "Malayalam" +msgstr "Malajala" + +msgid "Mongolian" +msgstr "Mongola" + +msgid "Marathi" +msgstr "Marata" + +msgid "Malay" +msgstr "Malaja" + +msgid "Burmese" +msgstr "Birma" + +msgid "Norwegian Bokmål" +msgstr "Norvega (bokmål)" + +msgid "Nepali" +msgstr "Nepala" + +msgid "Dutch" +msgstr "Nederlanda" + +msgid "Norwegian Nynorsk" +msgstr "Norvega (nynorsk)" + +msgid "Ossetic" +msgstr "Oseta" + +msgid "Punjabi" +msgstr "Panĝaba" + +msgid "Polish" +msgstr "Pola" + +msgid "Portuguese" +msgstr "Portugala" + +msgid "Brazilian Portuguese" +msgstr "Portugala (Brazilo)" + +msgid "Romanian" +msgstr "Rumana" + +msgid "Russian" +msgstr "Rusa" + +msgid "Slovak" +msgstr "Slovaka" + +msgid "Slovenian" +msgstr "Slovena" + +msgid "Albanian" +msgstr "Albana" + +msgid "Serbian" +msgstr "Serba" + +msgid "Serbian Latin" +msgstr "Serba (latina)" + +msgid "Swedish" +msgstr "Sveda" + +msgid "Swahili" +msgstr "Svahila" + +msgid "Tamil" +msgstr "Tamila" + +msgid "Telugu" +msgstr "Telugua" + +msgid "Tajik" +msgstr "Taĝika" + +msgid "Thai" +msgstr "Taja" + +msgid "Turkmen" +msgstr "Turkmena" + +msgid "Turkish" +msgstr "Turka" + +msgid "Tatar" +msgstr "Tatara" + +msgid "Udmurt" +msgstr "Udmurta" + +msgid "Ukrainian" +msgstr "Ukraina" + +msgid "Urdu" +msgstr "Urdua" + +msgid "Uzbek" +msgstr "Uzbeka" + +msgid "Vietnamese" +msgstr "Vjetnama" + +msgid "Simplified Chinese" +msgstr "Ĉina (simpligite)" + +msgid "Traditional Chinese" +msgstr "Ĉina (tradicie)" + +msgid "Messages" +msgstr "Mesaĝoj" + +msgid "Site Maps" +msgstr "Retejaj mapoj" + +msgid "Static Files" +msgstr "Statikaj dosieroj" + +msgid "Syndication" +msgstr "Abonrilato" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Tia paĝnumero ne estas entjero" + +msgid "That page number is less than 1" +msgstr "La paĝnumero estas malpli ol 1" + +msgid "That page contains no results" +msgstr "Tiu paĝo ne enhavas rezultojn" + +msgid "Enter a valid value." +msgstr "Enigu ĝustan valoron." + +msgid "Enter a valid URL." +msgstr "Enigu ĝustan retadreson." + +msgid "Enter a valid integer." +msgstr "Enigu ĝustaforman entjeron." + +msgid "Enter a valid email address." +msgstr "Enigu ĝustaforman retpoŝtan adreson." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Enigu ĝustan “ĵetonvorton” konsistantan el latinaj literoj, ciferoj, " +"substrekoj, aŭ dividstrekoj." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Enigu ĝustan “ĵetonvorton” konsistantan el Unikodaj literoj, ciferoj, " +"substrekoj, aŭ dividstrekoj." + +msgid "Enter a valid IPv4 address." +msgstr "Enigu ĝustaforman IPv4-adreson." + +msgid "Enter a valid IPv6 address." +msgstr "Enigu ĝustaforman IPv6-adreson." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Enigu ĝustaforman IPv4- aŭ IPv6-adreson." + +msgid "Enter only digits separated by commas." +msgstr "Enigu nur ciferojn apartigitajn per komoj." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Certigu ke ĉi tiu valoro estas %(limit_value)s (ĝi estas %(show_value)s). " + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Certigu ke ĉi tiu valoro estas malpli ol aŭ egala al %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Certigu ke ĉi tiu valoro estas pli ol aŭ egala al %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "Certigu ke ĉi tiu valoro estas oblo de paŝo-grando %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Certigu, ke tiu valoro havas %(limit_value)d signon (ĝi havas " +"%(show_value)d)." +msgstr[1] "" +"Certigu ke ĉi tiu valoro enhavas almenaŭ %(limit_value)d signojn (ĝi havas " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Certigu, ke tio valuto maksimume havas %(limit_value)d karakterojn (ĝi havas " +"%(show_value)d)." +msgstr[1] "" +"Certigu ke ĉi tiu valoro maksimume enhavas %(limit_value)d signojn (ĝi havas " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Enigu nombron." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Certigu ke ne estas pli ol %(max)s cifero entute." +msgstr[1] "Certigu ke ne estas pli ol %(max)s ciferoj entute." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Certigu, ke ne estas pli ol %(max)s dekumaj lokoj." +msgstr[1] "Certigu, ke ne estas pli ol %(max)s dekumaj lokoj." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "Certigu ke ne estas pli ol %(max)s ciferoj antaŭ la dekuma punkto." +msgstr[1] "Certigu ke ne estas pli ol %(max)s ciferoj antaŭ la dekuma punkto." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Sufikso “%(extension)s” de dosiernomo ne estas permesita. Eblaj sufiksoj " +"estas: %(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Nulsignoj ne estas permesitaj." + +msgid "and" +msgstr "kaj" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s kun tiuj %(field_labels)s jam ekzistas." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Limigo “%(name)s” estas malobservita." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Valoro %(value)r ne estas ebla elekto." + +msgid "This field cannot be null." +msgstr "Tiu ĉi kampo ne povas esti senvalora (null)." + +msgid "This field cannot be blank." +msgstr "Tiu ĉi kampo ne povas esti malplena." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s kun tiu %(field_label)s jam ekzistas." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s devas esti unika por %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Kampo de tipo: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "La valoro “%(value)s” devas esti aŭ Vera (True) aŭ Malvera (False)." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" +"La valoro “%(value)s” devas esti Vera (True), Malvera (False), aŭ Nenia " +"(None)." + +msgid "Boolean (Either True or False)" +msgstr "Bulea (Vera aŭ Malvera)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Ĉeno (ĝis %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "Perkome disigitaj entjeroj" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"La valoro “%(value)s” havas malĝustan datformaton. Ĝi devas esti en la " +"formato JJJJ-MM-TT." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"La valoro “%(value)s” havas la ĝustan formaton (JJJJ-MM-TT), sed ĝi estas " +"neekzistanta dato." + +msgid "Date (without time)" +msgstr "Dato (sen horo)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"La valoro “%(value)s” havas malĝustan formaton. Ĝi devas esti en la formato " +"JJJJ-MM-TT HH:MM[:ss[.µµµµµµ]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"La valoro “%(value)s” havas la ĝustan formaton (JJJJ-MM-TT HH:MM[:ss[." +"µµµµµµ]][TZ]), sed ĝi estas neekzistanta dato/tempo." + +msgid "Date (with time)" +msgstr "Dato (kun horo)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "La valoro “%(value)s” devas esti dekuma frakcio." + +msgid "Decimal number" +msgstr "Dekuma nombro" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"La valoro “%(value)s” havas malĝustan formaton. Ĝi devas esti en la formato " +"[TT] [[HH:]MM:]ss[.µµµµµµ]." + +msgid "Duration" +msgstr "Daŭro" + +msgid "Email address" +msgstr "Retpoŝtadreso" + +msgid "File path" +msgstr "Dosierindiko" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "La valoro “%(value)s” devas esti glitpunkta nombro." + +msgid "Floating point number" +msgstr "Glitpunkta nombro" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "La valoro “%(value)s” devas esti entjero." + +msgid "Integer" +msgstr "Entjero" + +msgid "Big (8 byte) integer" +msgstr "Granda (8–bitoka) entjero" + +msgid "Small integer" +msgstr "Malgranda entjero" + +msgid "IPv4 address" +msgstr "IPv4-adreso" + +msgid "IP address" +msgstr "IP-adreso" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" +"La valoro “%(value)s” devas esti Nenia (None), Vera (True), aŭ Malvera " +"(False)." + +msgid "Boolean (Either True, False or None)" +msgstr "Buleo (Vera, Malvera, aŭ Nenia)" + +msgid "Positive big integer" +msgstr "Pozitiva granda entjero" + +msgid "Positive integer" +msgstr "Pozitiva entjero" + +msgid "Positive small integer" +msgstr "Pozitiva malgranda entjero" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Ĵetonvorto (ĝis %(max_length)s)" + +msgid "Text" +msgstr "Teksto" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"La valoro “%(value)s” havas malĝustan formaton. Ĝi devas esti en la formato " +"HH:MM[:ss[.µµµµµµ]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"La valoro “%(value)s” havas la (HH:MM[:ss[.µµµµµµ]]), sed tio estas " +"neekzistanta tempo." + +msgid "Time" +msgstr "Horo" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Kruda duuma datumo" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "“%(value)s” ne estas ĝustaforma UUID." + +msgid "Universally unique identifier" +msgstr "Universale unika identigilo" + +msgid "File" +msgstr "Dosiero" + +msgid "Image" +msgstr "Bildo" + +msgid "A JSON object" +msgstr "JSON-objekto" + +msgid "Value must be valid JSON." +msgstr "La valoro devas esti ĝustaforma JSON." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "Ekzemplero de %(model)s kun %(field)s egala al %(value)r ne ekzistas." + +msgid "Foreign Key (type determined by related field)" +msgstr "Fremda ŝlosilo (tipo determinita per rilata kampo)" + +msgid "One-to-one relationship" +msgstr "Unu-al-unu rilato" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s rilato" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s rilatoj" + +msgid "Many-to-many relationship" +msgstr "Mult-al-multa rilato" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Ĉi tiu kampo estas deviga." + +msgid "Enter a whole number." +msgstr "Enigu plenan nombron." + +msgid "Enter a valid date." +msgstr "Enigu ĝustan daton." + +msgid "Enter a valid time." +msgstr "Enigu ĝustan horon." + +msgid "Enter a valid date/time." +msgstr "Enigu ĝustan daton/tempon." + +msgid "Enter a valid duration." +msgstr "Enigu ĝustan daŭron." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "La nombro de tagoj devas esti inter {min_days} kaj {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" +"Neniu dosiero estis alŝutita. Kontrolu la kodoprezentan tipon en la " +"formularo." + +msgid "No file was submitted." +msgstr "Neniu dosiero estis alŝutita." + +msgid "The submitted file is empty." +msgstr "La alŝutita dosiero estas malplena." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Certigu, ke tio dosiernomo maksimume havas %(max)d karakteron (ĝi havas " +"%(length)d)." +msgstr[1] "" +"Certigu ke la dosiernomo maksimume havas %(max)d signojn (ĝi havas " +"%(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Bonvolu aŭ alŝuti dosieron, aŭ elekti la vakigan markobutonon, sed ne ambaŭ." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Alŝutu ĝustaforman bildon. La alŝutita dosiero ne estas bildo aŭ estas " +"difektita bildo." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Elektu ekzistantan opcion. %(value)s ne estas el la eblaj elektoj." + +msgid "Enter a list of values." +msgstr "Enigu liston de valoroj." + +msgid "Enter a complete value." +msgstr "Enigu kompletan valoron." + +msgid "Enter a valid UUID." +msgstr "Enigu ĝustaforman UUID." + +msgid "Enter a valid JSON." +msgstr "Enigu ĝustaforman JSON." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Kaŝita kampo %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"La datumoj de la mastruma ManagementForm mankas aŭ estis malice modifitaj. " +"Mankas la kampoj: %(field_names)s. Se la problemo plu okazas, vi poveble " +"devintus raporti cimon." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Bonvolu forsendi maksimume %(num)d formularon." +msgstr[1] "Bonvolu forsendi maksimume %(num)d formularojn." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Bonvolu forsendi almenaŭ %(num)d formularon." +msgstr[1] "Bonvolu forsendi almenaŭ %(num)d formularojn." + +msgid "Order" +msgstr "Ordo" + +msgid "Delete" +msgstr "Forigi" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Bonvolu ĝustigi la duoblan datumon por %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Bonvolu ĝustigi la duoblan datumon por %(field)s, kiu devas esti unika." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Bonvolu ĝustigi la duoblan datumon por %(field_name)s, kiu devas esti unika " +"por la %(lookup)s en %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Bonvolu ĝustigi la duoblan valoron sube." + +msgid "The inline value did not match the parent instance." +msgstr "La enteksta valoro ne egalas la patran ekzempleron." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Elektu ekzistantan opcion. Ĉi tiu opcio ne estas el la eblaj elektoj." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "“%(pk)s” estas neakceptebla valoro." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"Ne eblis interpreti %(datetime)s en la tempo-zono %(current_timezone)s. Ĝi " +"eble estas ambigua aŭ ne ekzistas en tiu tempo-zono." + +msgid "Clear" +msgstr "Vakigi" + +msgid "Currently" +msgstr "Nuntempe" + +msgid "Change" +msgstr "Ŝanĝi" + +msgid "Unknown" +msgstr "Nekonate" + +msgid "Yes" +msgstr "Jes" + +msgid "No" +msgstr "Ne" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "jes,ne,eble" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d bitoko" +msgstr[1] "%(size)d bitokoj" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "ptm" + +msgid "a.m." +msgstr "atm" + +msgid "PM" +msgstr "PTM" + +msgid "AM" +msgstr "ATM" + +msgid "midnight" +msgstr "noktomezo" + +msgid "noon" +msgstr "tagmezo" + +msgid "Monday" +msgstr "lundo" + +msgid "Tuesday" +msgstr "mardo" + +msgid "Wednesday" +msgstr "merkredo" + +msgid "Thursday" +msgstr "ĵaŭdo" + +msgid "Friday" +msgstr "vendredo" + +msgid "Saturday" +msgstr "sabato" + +msgid "Sunday" +msgstr "dimanĉo" + +msgid "Mon" +msgstr "lun" + +msgid "Tue" +msgstr "mar" + +msgid "Wed" +msgstr "mer" + +msgid "Thu" +msgstr "ĵaŭ" + +msgid "Fri" +msgstr "ven" + +msgid "Sat" +msgstr "sab" + +msgid "Sun" +msgstr "dim" + +msgid "January" +msgstr "januaro" + +msgid "February" +msgstr "februaro" + +msgid "March" +msgstr "marto" + +msgid "April" +msgstr "aprilo" + +msgid "May" +msgstr "majo" + +msgid "June" +msgstr "junio" + +msgid "July" +msgstr "julio" + +msgid "August" +msgstr "aŭgusto" + +msgid "September" +msgstr "septembro" + +msgid "October" +msgstr "oktobro" + +msgid "November" +msgstr "novembro" + +msgid "December" +msgstr "decembro" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "apr" + +msgid "may" +msgstr "maj" + +msgid "jun" +msgstr "jun" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "aŭg" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "okt" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dec" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "mar." + +msgctxt "abbrev. month" +msgid "April" +msgstr "apr." + +msgctxt "abbrev. month" +msgid "May" +msgstr "majo" + +msgctxt "abbrev. month" +msgid "June" +msgstr "jun." + +msgctxt "abbrev. month" +msgid "July" +msgstr "jul." + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "aŭg." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "sept." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "okt." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "dec." + +msgctxt "alt. month" +msgid "January" +msgstr "Januaro" + +msgctxt "alt. month" +msgid "February" +msgstr "Februaro" + +msgctxt "alt. month" +msgid "March" +msgstr "Marto" + +msgctxt "alt. month" +msgid "April" +msgstr "Aprilo" + +msgctxt "alt. month" +msgid "May" +msgstr "Majo" + +msgctxt "alt. month" +msgid "June" +msgstr "Junio" + +msgctxt "alt. month" +msgid "July" +msgstr "Julio" + +msgctxt "alt. month" +msgid "August" +msgstr "Aŭgusto" + +msgctxt "alt. month" +msgid "September" +msgstr "Septembro" + +msgctxt "alt. month" +msgid "October" +msgstr "Oktobro" + +msgctxt "alt. month" +msgid "November" +msgstr "Novembro" + +msgctxt "alt. month" +msgid "December" +msgstr "Decembro" + +msgid "This is not a valid IPv6 address." +msgstr "Tio ne estas ĝustaforma IPv6-adreso." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "aŭ" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d jaro" +msgstr[1] "%(num)d jaroj" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d monato" +msgstr[1] "%(num)d monatoj" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d semajno" +msgstr[1] "%(num)d semajnoj" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d tago" +msgstr[1] "%(num)d tagoj" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d horo" +msgstr[1] "%(num)d horoj" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuto" +msgstr[1] "%(num)d minutoj" + +msgid "Forbidden" +msgstr "Malpermesita" + +msgid "CSRF verification failed. Request aborted." +msgstr "Kontrolo de CSRF malsukcesis. Peto ĉesigita." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Vi vidas tiun ĉi mesaĝon ĉar ĉi-tiu HTTPS-retejo postulas ricevi la " +"kapinstrukcion “Referer” de via retumilo, sed neniu estis sendita. Tia " +"kapinstrukcio estas bezonata pro sekurecaj kialoj, por certigi ke via " +"retumilo ne agas laŭ nedezirataj instrukcioj de maliculoj." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Se la agordoj de via retumilo malebligas la kapinstrukciojn “Referer”, " +"bonvolu ebligi ilin por tiu ĉi retejo, aŭ por HTTPS-konektoj, aŭ por petoj " +"el sama fonto (“same-origin”)." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Se vi uzas la etikedon aŭ " +"sendas la kapinstrukcion “Referrer-Policy: no-referrer”, bonvolu forigi " +"ilin. La protekto kontraŭ CSRF postulas la ĉeeston de la kapinstrukcio " +"“Referer”, kaj strikte kontrolas la referencantan fonton. Se vi zorgas pri " +"privateco, uzu alternativojn kiajn por ligiloj al " +"eksteraj retejoj." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Vi vidas tiun ĉi mesaĝon ĉar ĉi-tiu retejo postulas ke CSRF-kuketo estu " +"sendita kune kun la formularoj. Tia kuketo estas bezonata pro sekurecaj " +"kialoj, por certigi ke via retumilo ne agas laŭ nedezirataj instrukcioj de " +"maliculoj." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Se la agordoj de via retumilo malebligas kuketojn, bonvolu ebligi ilin por " +"tiu ĉi retejo aŭ por petoj el sama fonto (“same-origin”)." + +msgid "More information is available with DEBUG=True." +msgstr "Pliaj informoj estas videblaj kun DEBUG=True." + +msgid "No year specified" +msgstr "Neniu jaro indikita" + +msgid "Date out of range" +msgstr "Dato ne en la intervalo" + +msgid "No month specified" +msgstr "Neniu monato indikita" + +msgid "No day specified" +msgstr "Neniu tago indikita" + +msgid "No week specified" +msgstr "Neniu semajno indikita" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Neniuj %(verbose_name_plural)s estas disponeblaj" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Estontaj %(verbose_name_plural)s ne disponeblas ĉar %(class_name)s." +"allow_future estas Malvera." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Erarforma dato-ĉeno “%(datestr)s” se uzi la formaton “%(format)s”" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Neniu %(verbose_name)s trovita kongrua kun la informpeto" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Paĝo ne estas “lasta”, nek eblas konverti ĝin en entjeron." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Malĝusta paĝo (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" +"La listo estas malplena dum “%(class_name)s.allow_empty” estas Malvera." + +msgid "Directory indexes are not allowed here." +msgstr "Dosierujaj indeksoj ne estas permesitaj ĉi tie." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "“%(path)s” ne ekzistas" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Indekso de %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "La instalado sukcesis! Gratulojn!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Vidu eldonajn notojn por Dĵango %(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Vi vidas ĉi tiun paĝon ĉar DEBUG = " +"True estas en via agorda dosiero kaj vi ne agordis ajnan URL." + +msgid "Django Documentation" +msgstr "Dĵanga dokumentaro" + +msgid "Topics, references, & how-to’s" +msgstr "Temoj, referencoj, kaj instruiloj" + +msgid "Tutorial: A Polling App" +msgstr "Instruilo: apo pri enketoj" + +msgid "Get started with Django" +msgstr "Komencu kun Dĵango" + +msgid "Django Community" +msgstr "Dĵanga komunumo" + +msgid "Connect, get help, or contribute" +msgstr "Konektiĝu, ricevu helpon aŭ kontribuu" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/eo/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/eo/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/eo/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/eo/formats.py new file mode 100644 index 0000000..d1346d1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/eo/formats.py @@ -0,0 +1,44 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = r"j\-\a \d\e F Y" # '26-a de julio 1887' +TIME_FORMAT = "H:i" # '18:59' +DATETIME_FORMAT = r"j\-\a \d\e F Y\, \j\e H:i" # '26-a de julio 1887, je 18:59' +YEAR_MONTH_FORMAT = r"F \d\e Y" # 'julio de 1887' +MONTH_DAY_FORMAT = r"j\-\a \d\e F" # '26-a de julio' +SHORT_DATE_FORMAT = "Y-m-d" # '1887-07-26' +SHORT_DATETIME_FORMAT = "Y-m-d H:i" # '1887-07-26 18:59' +FIRST_DAY_OF_WEEK = 1 # Monday (lundo) + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%Y-%m-%d", # '1887-07-26' + "%y-%m-%d", # '87-07-26' + "%Y %m %d", # '1887 07 26' + "%Y.%m.%d", # '1887.07.26' + "%d-a de %b %Y", # '26-a de jul 1887' + "%d %b %Y", # '26 jul 1887' + "%d-a de %B %Y", # '26-a de julio 1887' + "%d %B %Y", # '26 julio 1887' + "%d %m %Y", # '26 07 1887' + "%d/%m/%Y", # '26/07/1887' +] +TIME_INPUT_FORMATS = [ + "%H:%M:%S", # '18:59:00' + "%H:%M", # '18:59' +] +DATETIME_INPUT_FORMATS = [ + "%Y-%m-%d %H:%M:%S", # '1887-07-26 18:59:00' + "%Y-%m-%d %H:%M", # '1887-07-26 18:59' + "%Y.%m.%d %H:%M:%S", # '1887.07.26 18:59:00' + "%Y.%m.%d %H:%M", # '1887.07.26 18:59' + "%d/%m/%Y %H:%M:%S", # '26/07/1887 18:59:00' + "%d/%m/%Y %H:%M", # '26/07/1887 18:59' + "%y-%m-%d %H:%M:%S", # '87-07-26 18:59:00' + "%y-%m-%d %H:%M", # '87-07-26 18:59' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "\xa0" # non-breaking space +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d95011b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es/LC_MESSAGES/django.po new file mode 100644 index 0000000..1539ce8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es/LC_MESSAGES/django.po @@ -0,0 +1,1402 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# 8cb2d5a716c3c9a99b6d20472609a4d5_6d03802 , 2011 +# Abe Estrada, 2013 +# Abe Estrada, 2013 +# albertoalcolea , 2014 +# albertoalcolea , 2014 +# Amanda Copete, 2017 +# Amanda Copete, 2017 +# Antoni Aloy , 2011-2014,2017,2019 +# Claude Paroz , 2020 +# Diego Andres Sanabria Martin , 2012 +# Diego Schulz , 2012 +# e4db27214f7e7544f2022c647b585925_bb0e321, 2014,2020 +# e4db27214f7e7544f2022c647b585925_bb0e321, 2015-2016 +# e4db27214f7e7544f2022c647b585925_bb0e321, 2014 +# e4db27214f7e7544f2022c647b585925_bb0e321, 2020 +# Ernesto Rico Schmidt , 2017 +# Ernesto Rico Schmidt , 2017 +# 8cb2d5a716c3c9a99b6d20472609a4d5_6d03802 , 2011 +# Ignacio José Lizarán Rus , 2019 +# Igor Támara , 2015 +# Jannis Leidel , 2011 +# José Luis , 2016 +# José Luis , 2016 +# Josue Naaman Nistal Guerra , 2014 +# Leonardo J. Caballero G. , 2011,2013 +# Luigy, 2019 +# Luigy, 2019 +# Marc Garcia , 2011 +# Mariusz Felisiak , 2021 +# mpachas , 2022 +# monobotsoft , 2012 +# ntrrgc , 2013 +# ntrrgc , 2013 +# Pablo, 2015 +# Pablo, 2015 +# Sebastián Magrí, 2013 +# Sebastián Magrí, 2013 +# Uriel Medina , 2020-2021,2023 +# Veronicabh , 2015 +# Veronicabh , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Uriel Medina , 2020-2021,2023\n" +"Language-Team: Spanish (http://app.transifex.com/django/django/language/" +"es/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Africano" + +msgid "Arabic" +msgstr "Árabe" + +msgid "Algerian Arabic" +msgstr "Árabe argelino" + +msgid "Asturian" +msgstr "Asturiano" + +msgid "Azerbaijani" +msgstr "Azerbaiyán" + +msgid "Bulgarian" +msgstr "Búlgaro" + +msgid "Belarusian" +msgstr "Bielorruso" + +msgid "Bengali" +msgstr "Bengalí" + +msgid "Breton" +msgstr "Bretón" + +msgid "Bosnian" +msgstr "Bosnio" + +msgid "Catalan" +msgstr "Catalán" + +msgid "Central Kurdish (Sorani)" +msgstr "Kurdo central (Sorani)" + +msgid "Czech" +msgstr "Checo" + +msgid "Welsh" +msgstr "Galés" + +msgid "Danish" +msgstr "Danés" + +msgid "German" +msgstr "Alemán" + +msgid "Lower Sorbian" +msgstr "Bajo sorbio" + +msgid "Greek" +msgstr "Griego" + +msgid "English" +msgstr "Inglés" + +msgid "Australian English" +msgstr "Inglés australiano" + +msgid "British English" +msgstr "Inglés británico" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Español" + +msgid "Argentinian Spanish" +msgstr "Español de Argentina" + +msgid "Colombian Spanish" +msgstr "Español de Colombia" + +msgid "Mexican Spanish" +msgstr "Español de México" + +msgid "Nicaraguan Spanish" +msgstr "Español de Nicaragua" + +msgid "Venezuelan Spanish" +msgstr "Español de Venezuela" + +msgid "Estonian" +msgstr "Estonio" + +msgid "Basque" +msgstr "Vasco" + +msgid "Persian" +msgstr "Persa" + +msgid "Finnish" +msgstr "Finés" + +msgid "French" +msgstr "Francés" + +msgid "Frisian" +msgstr "Frisón" + +msgid "Irish" +msgstr "Irlandés" + +msgid "Scottish Gaelic" +msgstr "Gaélico Escocés" + +msgid "Galician" +msgstr "Gallego" + +msgid "Hebrew" +msgstr "Hebreo" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Croata" + +msgid "Upper Sorbian" +msgstr "Alto sorbio" + +msgid "Hungarian" +msgstr "Húngaro" + +msgid "Armenian" +msgstr "Armenio" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonesio" + +msgid "Igbo" +msgstr "Igbo" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Islandés" + +msgid "Italian" +msgstr "Italiano" + +msgid "Japanese" +msgstr "Japonés" + +msgid "Georgian" +msgstr "Georgiano" + +msgid "Kabyle" +msgstr "Cabilio" + +msgid "Kazakh" +msgstr "Kazajo" + +msgid "Khmer" +msgstr "Khmer" + +msgid "Kannada" +msgstr "Kannada" + +msgid "Korean" +msgstr "Coreano" + +msgid "Kyrgyz" +msgstr "Kirguís" + +msgid "Luxembourgish" +msgstr "Luxenburgués" + +msgid "Lithuanian" +msgstr "Lituano" + +msgid "Latvian" +msgstr "Letón" + +msgid "Macedonian" +msgstr "Macedonio" + +msgid "Malayalam" +msgstr "Malayalam" + +msgid "Mongolian" +msgstr "Mongol" + +msgid "Marathi" +msgstr "Maratí" + +msgid "Malay" +msgstr "Malayo" + +msgid "Burmese" +msgstr "Birmano" + +msgid "Norwegian Bokmål" +msgstr "Bokmål noruego" + +msgid "Nepali" +msgstr "Nepalí" + +msgid "Dutch" +msgstr "Holandés" + +msgid "Norwegian Nynorsk" +msgstr "Nynorsk" + +msgid "Ossetic" +msgstr "Osetio" + +msgid "Punjabi" +msgstr "Panyabí" + +msgid "Polish" +msgstr "Polaco" + +msgid "Portuguese" +msgstr "Portugués" + +msgid "Brazilian Portuguese" +msgstr "Portugués de Brasil" + +msgid "Romanian" +msgstr "Rumano" + +msgid "Russian" +msgstr "Ruso" + +msgid "Slovak" +msgstr "Eslovaco" + +msgid "Slovenian" +msgstr "Esloveno" + +msgid "Albanian" +msgstr "Albanés" + +msgid "Serbian" +msgstr "Serbio" + +msgid "Serbian Latin" +msgstr "Serbio latino" + +msgid "Swedish" +msgstr "Sueco" + +msgid "Swahili" +msgstr "Suajili" + +msgid "Tamil" +msgstr "Tamil" + +msgid "Telugu" +msgstr "Telugu" + +msgid "Tajik" +msgstr "Tayiko" + +msgid "Thai" +msgstr "Tailandés" + +msgid "Turkmen" +msgstr "Turcomanos" + +msgid "Turkish" +msgstr "Turco" + +msgid "Tatar" +msgstr "Tártaro" + +msgid "Udmurt" +msgstr "Udmurt" + +msgid "Uyghur" +msgstr "Uigur" + +msgid "Ukrainian" +msgstr "Ucraniano" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "Uzbeko" + +msgid "Vietnamese" +msgstr "Vietnamita" + +msgid "Simplified Chinese" +msgstr "Chino simplificado" + +msgid "Traditional Chinese" +msgstr "Chino tradicional" + +msgid "Messages" +msgstr "Mensajes" + +msgid "Site Maps" +msgstr "Mapas del sitio" + +msgid "Static Files" +msgstr "Archivos estáticos" + +msgid "Syndication" +msgstr "Sindicación" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "..." + +msgid "That page number is not an integer" +msgstr "Este número de página no es un entero" + +msgid "That page number is less than 1" +msgstr "Este número de página es menor que 1" + +msgid "That page contains no results" +msgstr "Esa página no contiene resultados" + +msgid "Enter a valid value." +msgstr "Introduzca un valor válido." + +msgid "Enter a valid URL." +msgstr "Introduzca una URL válida." + +msgid "Enter a valid integer." +msgstr "Introduzca un número entero válido." + +msgid "Enter a valid email address." +msgstr "Introduzca una dirección de correo electrónico válida." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Introduzca un 'slug' válido, consistente en letras, números, guiones bajos o " +"medios." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Introduzca un 'slug' válido, consistente en letras, números, guiones bajos o " +"medios de Unicode." + +msgid "Enter a valid IPv4 address." +msgstr "Introduzca una dirección IPv4 válida." + +msgid "Enter a valid IPv6 address." +msgstr "Introduzca una dirección IPv6 válida." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Introduzca una dirección IPv4 o IPv6 válida." + +msgid "Enter only digits separated by commas." +msgstr "Introduzca sólo dígitos separados por comas." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Asegúrese de que este valor es %(limit_value)s (actualmente es " +"%(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Asegúrese de que este valor es menor o igual a %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Asegúrese de que este valor es mayor o igual a %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "Asegúrese de que este valor es múltiplo de %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"Asegúrese de que este valor sea un múltiplo del tamaño del " +"paso%(limit_value)s, comenzando en%(offset)s, p.ej. %(offset)s, " +"%(valid_value1)s, %(valid_value2)s, etcétera." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Asegúrese de que este valor tenga al menos %(limit_value)d caracter (tiene " +"%(show_value)d)." +msgstr[1] "" +"Asegúrese de que este valor tenga al menos %(limit_value)d carácter(es) " +"(tiene%(show_value)d)." +msgstr[2] "" +"Asegúrese de que este valor tenga al menos %(limit_value)d carácter(es) " +"(tiene%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Asegúrese de que este valor tenga menos de %(limit_value)d caracter (tiene " +"%(show_value)d)." +msgstr[1] "" +"Asegúrese de que este valor tenga menos de %(limit_value)d caracteres (tiene " +"%(show_value)d)." +msgstr[2] "" +"Asegúrese de que este valor tenga menos de %(limit_value)d caracteres (tiene " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Introduzca un número." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Asegúrese de que no hay más de %(max)s dígito en total." +msgstr[1] "Asegúrese de que no haya más de %(max)s dígitos en total." +msgstr[2] "Asegúrese de que no haya más de %(max)s dígitos en total." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Asegúrese de que no haya más de %(max)s dígito decimal." +msgstr[1] "Asegúrese de que no haya más de %(max)s dígitos decimales." +msgstr[2] "Asegúrese de que no haya más de %(max)s dígitos decimales." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Asegúrese de que no haya más de %(max)s dígito antes del punto decimal" +msgstr[1] "" +"Asegúrese de que no haya más de %(max)s dígitos antes del punto decimal." +msgstr[2] "" +"Asegúrese de que no haya más de %(max)s dígitos antes del punto decimal." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"La extensión de archivo “%(extension)s” no esta permitida. Las extensiones " +"permitidas son: %(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Los caracteres nulos no están permitidos." + +msgid "and" +msgstr "y" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s con este %(field_labels)s ya existe." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "No se cumple la restricción \"%(name)s\"." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Valor %(value)r no es una opción válida." + +msgid "This field cannot be null." +msgstr "Este campo no puede ser nulo." + +msgid "This field cannot be blank." +msgstr "Este campo no puede estar vacío." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "Ya existe %(model_name)s con este %(field_label)s." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s debe ser único para %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Campo de tipo: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "“%(value)s”: el valor debe ser Verdadero o Falso." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "“%(value)s”: el valor debe ser Verdadero, Falso o Nulo." + +msgid "Boolean (Either True or False)" +msgstr "Booleano (Verdadero o Falso)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Cadena (máximo %(max_length)s)" + +msgid "String (unlimited)" +msgstr "Cadena (ilimitado)" + +msgid "Comma-separated integers" +msgstr "Enteros separados por coma" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"“%(value)s” : el valor tiene un formato de fecha inválido. Debería estar en " +"el formato YYYY-MM-DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"“%(value)s” : el valor tiene el formato correcto (YYYY-MM-DD) pero es una " +"fecha inválida." + +msgid "Date (without time)" +msgstr "Fecha (sin hora)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"“%(value)s”: el valor tiene un formato inválido. Debería estar en el formato " +"YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"“%(value)s”: el valor tiene el formato correcto (YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ]) pero es una fecha inválida." + +msgid "Date (with time)" +msgstr "Fecha (con hora)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "“%(value)s”: el valor debe ser un número decimal." + +msgid "Decimal number" +msgstr "Número decimal" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"“%(value)s”: el valor tiene un formato inválido. Debería estar en el formato " +"[DD] [[HH:]MM:]ss[.uuuuuu]" + +msgid "Duration" +msgstr "Duración" + +msgid "Email address" +msgstr "Correo electrónico" + +msgid "File path" +msgstr "Ruta de fichero" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "“%(value)s”: el valor debería ser un número de coma flotante." + +msgid "Floating point number" +msgstr "Número en coma flotante" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "“%(value)s”: el valor debería ser un numero entero" + +msgid "Integer" +msgstr "Entero" + +msgid "Big (8 byte) integer" +msgstr "Entero grande (8 bytes)" + +msgid "Small integer" +msgstr "Entero corto" + +msgid "IPv4 address" +msgstr "Dirección IPv4" + +msgid "IP address" +msgstr "Dirección IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "“%(value)s”: el valor debería ser None, Verdadero o Falso." + +msgid "Boolean (Either True, False or None)" +msgstr "Booleano (Verdadero, Falso o Nulo)" + +msgid "Positive big integer" +msgstr "Entero grande positivo" + +msgid "Positive integer" +msgstr "Entero positivo" + +msgid "Positive small integer" +msgstr "Entero positivo corto" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (hasta %(max_length)s)" + +msgid "Text" +msgstr "Texto" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"“%(value)s”: el valor tiene un formato inválido. Debería estar en el formato " +"HH:MM[:ss[.uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"“%(value)s” : el valor tiene el formato correcto (HH:MM[:ss[.uuuuuu]]) pero " +"es un tiempo inválido." + +msgid "Time" +msgstr "Hora" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Datos binarios en bruto" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "“%(value)s” no es un UUID válido." + +msgid "Universally unique identifier" +msgstr "Identificador universal único" + +msgid "File" +msgstr "Archivo" + +msgid "Image" +msgstr "Imagen" + +msgid "A JSON object" +msgstr "Un objeto JSON" + +msgid "Value must be valid JSON." +msgstr "El valor debe ser un objeto JSON válido." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "La instancia de %(model)s con %(field)s %(value)r no existe." + +msgid "Foreign Key (type determined by related field)" +msgstr "Clave foránea (tipo determinado por el campo relacionado)" + +msgid "One-to-one relationship" +msgstr "Relación uno-a-uno" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "relación %(from)s-%(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "relaciones %(from)s-%(to)s" + +msgid "Many-to-many relationship" +msgstr "Relación muchos-a-muchos" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Este campo es obligatorio." + +msgid "Enter a whole number." +msgstr "Introduzca un número entero." + +msgid "Enter a valid date." +msgstr "Introduzca una fecha válida." + +msgid "Enter a valid time." +msgstr "Introduzca una hora válida." + +msgid "Enter a valid date/time." +msgstr "Introduzca una fecha/hora válida." + +msgid "Enter a valid duration." +msgstr "Introduzca una duración válida." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "El número de días debe estar entre {min_days} y {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" +"No se ha enviado ningún fichero. Compruebe el tipo de codificación en el " +"formulario." + +msgid "No file was submitted." +msgstr "No se ha enviado ningún fichero" + +msgid "The submitted file is empty." +msgstr "El fichero enviado está vacío." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Asegúrese de que este nombre de archivo tenga como máximo %(max)d caracter " +"(tiene %(length)d)." +msgstr[1] "" +"Asegúrese de que este nombre de archivo tenga como máximo %(max)d " +"carácter(es) (tiene %(length)d)." +msgstr[2] "" +"Asegúrese de que este nombre de archivo tenga como máximo %(max)d " +"carácter(es) (tiene %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Por favor envíe un fichero o marque la casilla de limpiar, pero no ambos." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Envíe una imagen válida. El fichero que ha enviado no era una imagen o se " +"trataba de una imagen corrupta." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Escoja una opción válida. %(value)s no es una de las opciones disponibles." + +msgid "Enter a list of values." +msgstr "Introduzca una lista de valores." + +msgid "Enter a complete value." +msgstr "Introduzca un valor completo." + +msgid "Enter a valid UUID." +msgstr "Introduzca un UUID válido." + +msgid "Enter a valid JSON." +msgstr "Ingresa un JSON válido." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Campo oculto %(name)s) *%(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"Los datos de ManagementForm faltan o han sido alterados. Campos que faltan: " +"%(field_names)s. Es posible que deba presentar un informe de error si el " +"problema persiste." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Por favor, envíe %(num)d formulario como máximo." +msgstr[1] "Por favor, envíe %(num)d formularios como máximo." +msgstr[2] "Por favor, envíe %(num)d formularios como máximo." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Por favor, envíe %(num)d formulario como mínimo." +msgstr[1] "Por favor, envíe %(num)d formularios como mínimo." +msgstr[2] "Por favor, envíe %(num)d formularios como mínimo." + +msgid "Order" +msgstr "Orden" + +msgid "Delete" +msgstr "Eliminar" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Por favor, corrija el dato duplicado para %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Por favor corrija el dato duplicado para %(field)s, ya que debe ser único." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Por favor corrija los datos duplicados para %(field_name)s ya que debe ser " +"único para %(lookup)s en %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Por favor, corrija los valores duplicados abajo." + +msgid "The inline value did not match the parent instance." +msgstr "El valor en línea no coincide con la instancia padre." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Escoja una opción válida. Esa opción no está entre las disponibles." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "“%(pk)s” no es un valor válido." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s no pudo ser interpretado en la zona horaria " +"%(current_timezone)s; podría ser ambiguo o no existir." + +msgid "Clear" +msgstr "Limpiar" + +msgid "Currently" +msgstr "Actualmente" + +msgid "Change" +msgstr "Modificar" + +msgid "Unknown" +msgstr "Desconocido" + +msgid "Yes" +msgstr "Sí" + +msgid "No" +msgstr "No" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "sí,no,quizás" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d byte" +msgstr[1] "%(size)d bytes" +msgstr[2] "%(size)d bytes" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "medianoche" + +msgid "noon" +msgstr "mediodía" + +msgid "Monday" +msgstr "lunes" + +msgid "Tuesday" +msgstr "martes" + +msgid "Wednesday" +msgstr "miércoles" + +msgid "Thursday" +msgstr "jueves" + +msgid "Friday" +msgstr "viernes" + +msgid "Saturday" +msgstr "sábado" + +msgid "Sunday" +msgstr "domingo" + +msgid "Mon" +msgstr "lun" + +msgid "Tue" +msgstr "mar" + +msgid "Wed" +msgstr "mié" + +msgid "Thu" +msgstr "jue" + +msgid "Fri" +msgstr "vie" + +msgid "Sat" +msgstr "sáb" + +msgid "Sun" +msgstr "dom" + +msgid "January" +msgstr "enero" + +msgid "February" +msgstr "febrero" + +msgid "March" +msgstr "marzo" + +msgid "April" +msgstr "abril" + +msgid "May" +msgstr "mayo" + +msgid "June" +msgstr "junio" + +msgid "July" +msgstr "julio" + +msgid "August" +msgstr "agosto" + +msgid "September" +msgstr "septiembre" + +msgid "October" +msgstr "octubre" + +msgid "November" +msgstr "noviembre" + +msgid "December" +msgstr "diciembre" + +msgid "jan" +msgstr "ene" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "abr" + +msgid "may" +msgstr "may" + +msgid "jun" +msgstr "jun" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "ago" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "oct" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dic" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Ene." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "marzo" + +msgctxt "abbrev. month" +msgid "April" +msgstr "abril" + +msgctxt "abbrev. month" +msgid "May" +msgstr "mayo" + +msgctxt "abbrev. month" +msgid "June" +msgstr "junio" + +msgctxt "abbrev. month" +msgid "July" +msgstr "julio" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "ago." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "sept." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "oct." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "dic." + +msgctxt "alt. month" +msgid "January" +msgstr "enero" + +msgctxt "alt. month" +msgid "February" +msgstr "febrero" + +msgctxt "alt. month" +msgid "March" +msgstr "marzo" + +msgctxt "alt. month" +msgid "April" +msgstr "abril" + +msgctxt "alt. month" +msgid "May" +msgstr "mayo" + +msgctxt "alt. month" +msgid "June" +msgstr "junio" + +msgctxt "alt. month" +msgid "July" +msgstr "julio" + +msgctxt "alt. month" +msgid "August" +msgstr "agosto" + +msgctxt "alt. month" +msgid "September" +msgstr "septiembre" + +msgctxt "alt. month" +msgid "October" +msgstr "octubre" + +msgctxt "alt. month" +msgid "November" +msgstr "noviembre" + +msgctxt "alt. month" +msgid "December" +msgstr "diciembre" + +msgid "This is not a valid IPv6 address." +msgstr "No es una dirección IPv6 válida." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "o" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d años" +msgstr[1] "%(num)d años" +msgstr[2] "%(num)d años" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mes" +msgstr[1] "%(num)d meses" +msgstr[2] "%(num)d meses" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d semana" +msgstr[1] "%(num)d semanas" +msgstr[2] "%(num)d semanas" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d día" +msgstr[1] "%(num)d días" +msgstr[2] "%(num)d días" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hora" +msgstr[1] "%(num)d horas" +msgstr[2] "%(num)d horas" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minutos" +msgstr[1] "%(num)d minutes" +msgstr[2] "%(num)d minutos" + +msgid "Forbidden" +msgstr "Prohibido" + +msgid "CSRF verification failed. Request aborted." +msgstr "La verificación CSRF ha fallado. Solicitud abortada." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Estás viendo este mensaje porque este sitio HTTPS requiere que tu navegador " +"web envíe un \"encabezado de referencia\", pero no se envió ninguno. Este " +"encabezado es necesario por razones de seguridad, para garantizar que su " +"navegador no sea secuestrado por terceros." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Si ha configurado su navegador para deshabilitar los encabezados " +"\"Referer\", vuelva a habilitarlos, al menos para este sitio, o para " +"conexiones HTTPS, o para solicitudes del \"mismo origen\"." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Si esta utilizando la etiqueta o incluyendo el encabezado \"Referrer-Policy: no-referrer\", " +"elimínelos. La protección CSRF requiere que el encabezado \"Referer\" " +"realice una comprobación estricta del referente. Si le preocupa la " +"privacidad, utilice alternativas como para los " +"enlaces a sitios de terceros." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Estás viendo este mensaje porqué esta web requiere una cookie CSRF cuando se " +"envían formularios. Esta cookie se necesita por razones de seguridad, para " +"asegurar que tu navegador no ha sido comprometido por terceras partes." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Si ha configurado su navegador para deshabilitar las cookies, vuelva a " +"habilitarlas, al menos para este sitio o para solicitudes del \"mismo " +"origen\"." + +msgid "More information is available with DEBUG=True." +msgstr "Más información disponible si se establece DEBUG=True." + +msgid "No year specified" +msgstr "No se ha indicado el año" + +msgid "Date out of range" +msgstr "Fecha fuera de rango" + +msgid "No month specified" +msgstr "No se ha indicado el mes" + +msgid "No day specified" +msgstr "No se ha indicado el día" + +msgid "No week specified" +msgstr "No se ha indicado la semana" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "No %(verbose_name_plural)s disponibles" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Los futuros %(verbose_name_plural)s no están disponibles porque " +"%(class_name)s.allow_future es Falso." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Cadena de fecha no valida “%(datestr)s” dado el formato “%(format)s”" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "No se encontró ningún %(verbose_name)s coincidente con la consulta" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "La página no es la \"última\", ni se puede convertir a un entero." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Página inválida (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Lista vacía y “%(class_name)s.allow_empty” es Falso" + +msgid "Directory indexes are not allowed here." +msgstr "Los índices de directorio no están permitidos." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "“%(path)s” no existe" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Índice de %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "¡La instalación funcionó con éxito! ¡Felicitaciones!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Ve la notas de la versión de Django " +"%(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Estás viendo esta página porque DEBUG=True está en su archivo de configuración y no ha " +"configurado ninguna URL." + +msgid "Django Documentation" +msgstr "Documentación de Django" + +msgid "Topics, references, & how-to’s" +msgstr "Temas, referencias, & como hacer" + +msgid "Tutorial: A Polling App" +msgstr "Tutorial: Una aplicación de encuesta" + +msgid "Get started with Django" +msgstr "Comienza con Django" + +msgid "Django Community" +msgstr "Comunidad Django" + +msgid "Connect, get help, or contribute" +msgstr "Conéctate, obtén ayuda o contribuye" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es/formats.py new file mode 100644 index 0000000..f2716bb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es/formats.py @@ -0,0 +1,30 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = r"j \d\e F \d\e Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = r"j \d\e F \d\e Y \a \l\a\s H:i" +YEAR_MONTH_FORMAT = r"F \d\e Y" +MONTH_DAY_FORMAT = r"j \d\e F" +SHORT_DATE_FORMAT = "d/m/Y" +SHORT_DATETIME_FORMAT = "d/m/Y H:i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d/%m/%Y", # '31/12/2009' + "%d/%m/%y", # '31/12/09' +] +DATETIME_INPUT_FORMATS = [ + "%d/%m/%Y %H:%M:%S", + "%d/%m/%Y %H:%M:%S.%f", + "%d/%m/%Y %H:%M", + "%d/%m/%y %H:%M:%S", + "%d/%m/%y %H:%M:%S.%f", + "%d/%m/%y %H:%M", +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "\xa0" # non-breaking space +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_AR/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_AR/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5f62b71 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_AR/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_AR/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_AR/LC_MESSAGES/django.po new file mode 100644 index 0000000..ada4c31 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_AR/LC_MESSAGES/django.po @@ -0,0 +1,1370 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# lardissone , 2014 +# Natalia (Django Fellow), 2023 +# poli , 2014 +# Ramiro Morales, 2013-2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Natalia (Django Fellow), 2023\n" +"Language-Team: Spanish (Argentina) (http://app.transifex.com/django/django/" +"language/es_AR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_AR\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "afrikáans" + +msgid "Arabic" +msgstr "árabe" + +msgid "Algerian Arabic" +msgstr "Árabe de Argelia" + +msgid "Asturian" +msgstr "asturiano" + +msgid "Azerbaijani" +msgstr "azerbaiyán" + +msgid "Bulgarian" +msgstr "búlgaro" + +msgid "Belarusian" +msgstr "bielorruso" + +msgid "Bengali" +msgstr "bengalí" + +msgid "Breton" +msgstr "bretón" + +msgid "Bosnian" +msgstr "bosnio" + +msgid "Catalan" +msgstr "catalán" + +msgid "Central Kurdish (Sorani)" +msgstr "Kurdo central (Sorani)" + +msgid "Czech" +msgstr "checo" + +msgid "Welsh" +msgstr "galés" + +msgid "Danish" +msgstr "danés" + +msgid "German" +msgstr "alemán" + +msgid "Lower Sorbian" +msgstr "bajo sorabo" + +msgid "Greek" +msgstr "griego" + +msgid "English" +msgstr "inglés" + +msgid "Australian English" +msgstr "inglés australiano" + +msgid "British English" +msgstr "inglés británico" + +msgid "Esperanto" +msgstr "esperanto" + +msgid "Spanish" +msgstr "español" + +msgid "Argentinian Spanish" +msgstr "español (Argentina)" + +msgid "Colombian Spanish" +msgstr "español (Colombia)" + +msgid "Mexican Spanish" +msgstr "español (México)" + +msgid "Nicaraguan Spanish" +msgstr "español (Nicaragua)" + +msgid "Venezuelan Spanish" +msgstr "español (Venezuela)" + +msgid "Estonian" +msgstr "estonio" + +msgid "Basque" +msgstr "vasco" + +msgid "Persian" +msgstr "persa" + +msgid "Finnish" +msgstr "finlandés" + +msgid "French" +msgstr "francés" + +msgid "Frisian" +msgstr "frisón" + +msgid "Irish" +msgstr "irlandés" + +msgid "Scottish Gaelic" +msgstr "gaélico escocés" + +msgid "Galician" +msgstr "gallego" + +msgid "Hebrew" +msgstr "hebreo" + +msgid "Hindi" +msgstr "hindi" + +msgid "Croatian" +msgstr "croata" + +msgid "Upper Sorbian" +msgstr "alto sorabo" + +msgid "Hungarian" +msgstr "húngaro" + +msgid "Armenian" +msgstr "armenio" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "indonesio" + +msgid "Igbo" +msgstr "Igbo" + +msgid "Ido" +msgstr "ido" + +msgid "Icelandic" +msgstr "islandés" + +msgid "Italian" +msgstr "italiano" + +msgid "Japanese" +msgstr "japonés" + +msgid "Georgian" +msgstr "georgiano" + +msgid "Kabyle" +msgstr "cabilio" + +msgid "Kazakh" +msgstr "kazajo" + +msgid "Khmer" +msgstr "jémer" + +msgid "Kannada" +msgstr "canarés" + +msgid "Korean" +msgstr "coreano" + +msgid "Kyrgyz" +msgstr "kirguís" + +msgid "Luxembourgish" +msgstr "luxemburgués" + +msgid "Lithuanian" +msgstr "lituano" + +msgid "Latvian" +msgstr "letón" + +msgid "Macedonian" +msgstr "macedonio" + +msgid "Malayalam" +msgstr "malabar" + +msgid "Mongolian" +msgstr "mongol" + +msgid "Marathi" +msgstr "maratí" + +msgid "Malay" +msgstr "malayo" + +msgid "Burmese" +msgstr "burmés" + +msgid "Norwegian Bokmål" +msgstr "bokmål noruego" + +msgid "Nepali" +msgstr "nepalés" + +msgid "Dutch" +msgstr "holandés" + +msgid "Norwegian Nynorsk" +msgstr "nynorsk" + +msgid "Ossetic" +msgstr "osetio" + +msgid "Punjabi" +msgstr "panyabí" + +msgid "Polish" +msgstr "polaco" + +msgid "Portuguese" +msgstr "portugués" + +msgid "Brazilian Portuguese" +msgstr "portugués de Brasil" + +msgid "Romanian" +msgstr "rumano" + +msgid "Russian" +msgstr "ruso" + +msgid "Slovak" +msgstr "eslovaco" + +msgid "Slovenian" +msgstr "esloveno" + +msgid "Albanian" +msgstr "albanés" + +msgid "Serbian" +msgstr "serbio" + +msgid "Serbian Latin" +msgstr "latín de Serbia" + +msgid "Swedish" +msgstr "sueco" + +msgid "Swahili" +msgstr "suajili" + +msgid "Tamil" +msgstr "tamil" + +msgid "Telugu" +msgstr "telugu" + +msgid "Tajik" +msgstr "tayiko" + +msgid "Thai" +msgstr "tailandés" + +msgid "Turkmen" +msgstr "turcomano" + +msgid "Turkish" +msgstr "turco" + +msgid "Tatar" +msgstr "tártaro" + +msgid "Udmurt" +msgstr "udmurto" + +msgid "Uyghur" +msgstr "Uigur" + +msgid "Ukrainian" +msgstr "ucraniano" + +msgid "Urdu" +msgstr "urdu" + +msgid "Uzbek" +msgstr "uzbeko" + +msgid "Vietnamese" +msgstr "vietnamita" + +msgid "Simplified Chinese" +msgstr "chino simplificado" + +msgid "Traditional Chinese" +msgstr "chino tradicional" + +msgid "Messages" +msgstr "Mensajes" + +msgid "Site Maps" +msgstr "Mapas de sitio" + +msgid "Static Files" +msgstr "Archivos estáticos" + +msgid "Syndication" +msgstr "Sindicación" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "El número de página no es un entero" + +msgid "That page number is less than 1" +msgstr "El número de página es menor a 1" + +msgid "That page contains no results" +msgstr "Esa página no contiene resultados" + +msgid "Enter a valid value." +msgstr "Introduzca un valor válido." + +msgid "Enter a valid URL." +msgstr "Introduzca una URL válida." + +msgid "Enter a valid integer." +msgstr "Introduzca un valor numérico entero válido." + +msgid "Enter a valid email address." +msgstr "Introduzca una dirección de email válida." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "Introduzca un “slug” válido compuesto por letras, números o guiones." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Introduzca un “slug” compuesto por letras Unicode, números, guiones bajos o " +"guiones." + +msgid "Enter a valid IPv4 address." +msgstr "Introduzca una dirección IPv4 válida." + +msgid "Enter a valid IPv6 address." +msgstr "Introduzca una dirección IPv6 válida." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Introduzca una dirección IPv4 o IPv6 válida." + +msgid "Enter only digits separated by commas." +msgstr "Introduzca sólo dígitos separados por comas." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Asegúrese de que este valor sea %(limit_value)s (actualmente es " +"%(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Asegúrese de que este valor sea menor o igual a %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Asegúrese de que este valor sea mayor o igual a %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "Asegúrese de que este valor sea múltiplo de %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"Confirme que este valor sea un múltiplo del tamaño del paso %(limit_value)s, " +"empezando por %(offset)s, por ejemplo %(offset)s, %(valid_value1)s, " +"%(valid_value2)s, y así sucesivamente." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Asegúrese de que este valor tenga como mínimo %(limit_value)d caracter " +"(tiene %(show_value)d)." +msgstr[1] "" +"Asegúrese de que este valor tenga como mínimo %(limit_value)d caracteres " +"(tiene %(show_value)d)." +msgstr[2] "" +"Asegúrese de que este valor tenga como mínimo %(limit_value)d caracteres " +"(tiene %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Asegúrese de que este valor tenga como máximo %(limit_value)d caracter " +"(tiene %(show_value)d)." +msgstr[1] "" +"Asegúrese de que este valor tenga como máximo %(limit_value)d caracteres " +"(tiene %(show_value)d)." +msgstr[2] "" +"Asegúrese de que este valor tenga como máximo %(limit_value)d caracteres " +"(tiene %(show_value)d)." + +msgid "Enter a number." +msgstr "Introduzca un número." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Asegúrese de que no exista en total mas de %(max)s dígito." +msgstr[1] "Asegúrese de que no existan en total mas de %(max)s dígitos." +msgstr[2] "Asegúrese de que no existan en total mas de %(max)s dígitos." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Asegúrese de que no exista mas de %(max)s lugar decimal." +msgstr[1] "Asegúrese de que no existan mas de %(max)s lugares decimales." +msgstr[2] "Asegúrese de que no existan mas de %(max)s lugares decimales." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Asegúrese de que no exista mas de %(max)s dígito antes del punto decimal." +msgstr[1] "" +"Asegúrese de que no existan mas de %(max)s dígitos antes del punto decimal." +msgstr[2] "" +"Asegúrese de que no existan mas de %(max)s dígitos antes del punto decimal." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"La extensión de archivo “%(extension)s” no está permitida. Las extensiones " +"aceptadas son: “%(allowed_extensions)s”." + +msgid "Null characters are not allowed." +msgstr "No se admiten caracteres nulos." + +msgid "and" +msgstr "y" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "Ya existe un/a %(model_name)s con este/a %(field_labels)s." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "No se cumple la restricción “%(name)s”." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "El valor %(value)r no es una opción válida." + +msgid "This field cannot be null." +msgstr "Este campo no puede ser nulo." + +msgid "This field cannot be blank." +msgstr "Este campo no puede estar en blanco." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "Ya existe un/a %(model_name)s con este/a %(field_label)s." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s debe ser único/a para un %(lookup_type)s " +"%(date_field_label)s determinado." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Campo tipo: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "El valor de “%(value)s” debe ser Verdadero o Falso." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "El valor de “%(value)s” debe ser Verdadero, Falso o None." + +msgid "Boolean (Either True or False)" +msgstr "Booleano (Verdadero o Falso)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Cadena (máximo %(max_length)s)" + +msgid "String (unlimited)" +msgstr "Cadena (ilimitado)" + +msgid "Comma-separated integers" +msgstr "Enteros separados por comas" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"El valor de “%(value)s” tiene un formato de fecha inválido. Debe usar el " +"formato AAAA-MM-DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"El valor de “%(value)s” tiene un formato de fecha correcto (AAAA-MM-DD) pero " +"representa una fecha inválida." + +msgid "Date (without time)" +msgstr "Fecha (sin hora)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"El valor de “%(value)s” tiene un formato inválido. Debe usar el formato AAAA-" +"MM-DD HH:MM[:ss[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"El valor de “%(value)s” tiene un formato correcto (AAAA-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ]) pero representa una fecha/hora inválida." + +msgid "Date (with time)" +msgstr "Fecha (con hora)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "El valor de “%(value)s” debe ser un número decimal." + +msgid "Decimal number" +msgstr "Número decimal" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"El valor de “%(value)s” tiene un formato inválido. Debe usar el formato [DD] " +"[[HH:]MM:]ss[.uuuuuu]." + +msgid "Duration" +msgstr "Duración" + +msgid "Email address" +msgstr "Dirección de correo electrónico" + +msgid "File path" +msgstr "Ruta de archivo" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "El valor de “%(value)s” debe ser un número de coma flotante." + +msgid "Floating point number" +msgstr "Número de coma flotante" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "El valor de “%(value)s” debe ser un número entero." + +msgid "Integer" +msgstr "Entero" + +msgid "Big (8 byte) integer" +msgstr "Entero grande (8 bytes)" + +msgid "Small integer" +msgstr "Entero pequeño" + +msgid "IPv4 address" +msgstr "Dirección IPv4" + +msgid "IP address" +msgstr "Dirección IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "El valor de “%(value)s” debe ser None, Verdadero o Falso." + +msgid "Boolean (Either True, False or None)" +msgstr "Booleano (Verdadero, Falso o Nulo)" + +msgid "Positive big integer" +msgstr "Entero grande positivo" + +msgid "Positive integer" +msgstr "Entero positivo" + +msgid "Positive small integer" +msgstr "Entero pequeño positivo" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (de hasta %(max_length)s caracteres)" + +msgid "Text" +msgstr "Texto" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"El valor de “%(value)s” tiene un formato inválido. Debe usar el formato HH:" +"MM[:ss[.uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"El valor de “%(value)s” tiene un formato correcto (HH:MM[:ss[.uuuuuu]]) pero " +"representa una hora inválida." + +msgid "Time" +msgstr "Hora" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Datos binarios crudos" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "“%(value)s” no es un UUID válido." + +msgid "Universally unique identifier" +msgstr "Identificador universalmente único" + +msgid "File" +msgstr "Archivo" + +msgid "Image" +msgstr "Imagen" + +msgid "A JSON object" +msgstr "Un objeto JSON" + +msgid "Value must be valid JSON." +msgstr "El valor debe ser JSON válido." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "No existe una instancia de %(model)s con %(field)s %(value)r." + +msgid "Foreign Key (type determined by related field)" +msgstr "Clave foránea (el tipo está determinado por el campo relacionado)" + +msgid "One-to-one relationship" +msgstr "Relación uno-a-uno" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "relación %(from)s-%(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "relaciones %(from)s-%(to)s" + +msgid "Many-to-many relationship" +msgstr "Relación muchos-a-muchos" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Este campo es obligatorio." + +msgid "Enter a whole number." +msgstr "Introduzca un número entero." + +msgid "Enter a valid date." +msgstr "Introduzca una fecha válida." + +msgid "Enter a valid time." +msgstr "Introduzca un valor de hora válido." + +msgid "Enter a valid date/time." +msgstr "Introduzca un valor de fecha/hora válido." + +msgid "Enter a valid duration." +msgstr "Introduzca una duración válida." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "La cantidad de días debe tener valores entre {min_days} y {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" +"No se envió un archivo. Verifique el tipo de codificación en el formulario." + +msgid "No file was submitted." +msgstr "No se envió ningún archivo." + +msgid "The submitted file is empty." +msgstr "El archivo enviado está vacío." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Asegúrese de que este nombre de archivo tenga como máximo %(max)d caracter " +"(tiene %(length)d)." +msgstr[1] "" +"Asegúrese de que este nombre de archivo tenga como máximo %(max)d caracteres " +"(tiene %(length)d)." +msgstr[2] "" +"Asegúrese de que este nombre de archivo tenga como máximo %(max)d caracteres " +"(tiene %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Por favor envíe un archivo o active el checkbox, pero no ambas cosas." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Seleccione una imagen válida. El archivo que ha seleccionado no es una " +"imagen o es un archivo de imagen corrupto." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Seleccione una opción válida. %(value)s no es una de las opciones " +"disponibles." + +msgid "Enter a list of values." +msgstr "Introduzca una lista de valores." + +msgid "Enter a complete value." +msgstr "Introduzca un valor completo." + +msgid "Enter a valid UUID." +msgstr "Introduzca un UUID válido." + +msgid "Enter a valid JSON." +msgstr "Introduzca JSON válido." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Campo oculto %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"Los datos de ManagementForm faltan o han sido alterados. Campos faltantes: " +"%(field_names)s. Si el problema persiste es posible que deba reportarlo como " +"un error." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Por favor envíe un máximo de %(num)d formulario." +msgstr[1] "Por favor envíe un máximo de %(num)d formularios." +msgstr[2] "Por favor envíe un máximo de %(num)d formularios." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Por favor envíe %(num)d o mas formularios." +msgstr[1] "Por favor envíe %(num)d o mas formularios." +msgstr[2] "Por favor envíe %(num)d o mas formularios." + +msgid "Order" +msgstr "Ordenar" + +msgid "Delete" +msgstr "Eliminar" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Por favor, corrija la información duplicada en %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Por favor corrija la información duplicada en %(field)s, que debe ser única." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Por favor corrija la información duplicada en %(field_name)s que debe ser " +"única para el %(lookup)s en %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Por favor, corrija los valores duplicados detallados mas abajo." + +msgid "The inline value did not match the parent instance." +msgstr "El valor inline no coincide con el de la instancia padre." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Seleccione una opción válida. La opción seleccionada no es una de las " +"disponibles." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "“%(pk)s” no es un valor válido." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s no puede ser interpretado en la zona horaria " +"%(current_timezone)s; ya que podría ser ambiguo o podría no existir." + +msgid "Clear" +msgstr "Eliminar" + +msgid "Currently" +msgstr "Actualmente" + +msgid "Change" +msgstr "Modificar" + +msgid "Unknown" +msgstr "Desconocido" + +msgid "Yes" +msgstr "Sí" + +msgid "No" +msgstr "No" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "si,no,talvez" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d byte" +msgstr[1] "%(size)d bytes" +msgstr[2] "%(size)d bytes" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "medianoche" + +msgid "noon" +msgstr "mediodía" + +msgid "Monday" +msgstr "lunes" + +msgid "Tuesday" +msgstr "martes" + +msgid "Wednesday" +msgstr "miércoles" + +msgid "Thursday" +msgstr "jueves" + +msgid "Friday" +msgstr "viernes" + +msgid "Saturday" +msgstr "sábado" + +msgid "Sunday" +msgstr "Domingo" + +msgid "Mon" +msgstr "Lun" + +msgid "Tue" +msgstr "Mar" + +msgid "Wed" +msgstr "Mie" + +msgid "Thu" +msgstr "Jue" + +msgid "Fri" +msgstr "Vie" + +msgid "Sat" +msgstr "Sab" + +msgid "Sun" +msgstr "Dom" + +msgid "January" +msgstr "enero" + +msgid "February" +msgstr "febrero" + +msgid "March" +msgstr "marzo" + +msgid "April" +msgstr "abril" + +msgid "May" +msgstr "mayo" + +msgid "June" +msgstr "junio" + +msgid "July" +msgstr "julio" + +msgid "August" +msgstr "agosto" + +msgid "September" +msgstr "setiembre" + +msgid "October" +msgstr "octubre" + +msgid "November" +msgstr "noviembre" + +msgid "December" +msgstr "diciembre" + +msgid "jan" +msgstr "ene" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "abr" + +msgid "may" +msgstr "may" + +msgid "jun" +msgstr "jun" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "ago" + +msgid "sep" +msgstr "set" + +msgid "oct" +msgstr "oct" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dic" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Enero" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Marzo" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Abril" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Mayo" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Junio" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Julio" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Ago." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Set." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Oct." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dic." + +msgctxt "alt. month" +msgid "January" +msgstr "enero" + +msgctxt "alt. month" +msgid "February" +msgstr "febrero" + +msgctxt "alt. month" +msgid "March" +msgstr "marzo" + +msgctxt "alt. month" +msgid "April" +msgstr "abril" + +msgctxt "alt. month" +msgid "May" +msgstr "mayo" + +msgctxt "alt. month" +msgid "June" +msgstr "junio" + +msgctxt "alt. month" +msgid "July" +msgstr "julio" + +msgctxt "alt. month" +msgid "August" +msgstr "agosto" + +msgctxt "alt. month" +msgid "September" +msgstr "setiembre" + +msgctxt "alt. month" +msgid "October" +msgstr "octubre" + +msgctxt "alt. month" +msgid "November" +msgstr "noviembre" + +msgctxt "alt. month" +msgid "December" +msgstr "diciembre" + +msgid "This is not a valid IPv6 address." +msgstr "Esta no es una dirección IPv6 válida." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "o" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d año" +msgstr[1] "%(num)d años" +msgstr[2] "%(num)d años" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mes" +msgstr[1] "%(num)d meses" +msgstr[2] "%(num)d meses" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d semana" +msgstr[1] "%(num)d semanas" +msgstr[2] "%(num)d semanas" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d día" +msgstr[1] "%(num)d días" +msgstr[2] "%(num)d días" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hora" +msgstr[1] "%(num)d horas" +msgstr[2] "%(num)d horas" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuto" +msgstr[1] "%(num)d minutos" +msgstr[2] "%(num)d minutos" + +msgid "Forbidden" +msgstr "Prohibido" + +msgid "CSRF verification failed. Request aborted." +msgstr "Verificación CSRF fallida. Petición abortada." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Ud. está viendo este mensaje porque este sitio HTTPS tiene como " +"requerimiento que su navegador web envíe un encabezado “Referer” pero el " +"mismo no ha enviado uno. El hecho de que este encabezado sea obligatorio es " +"una medida de seguridad para comprobar que su navegador no está siendo " +"controlado por terceros." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Si ha configurado su browser para deshabilitar las cabeceras “Referer”, por " +"favor activelas al menos para este sitio, o para conexiones HTTPS o para " +"peticiones generadas desde el mismo origen." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Si está usando la etiqueta " +"o está incluyendo el encabezado “Referrer-Policy: no-referrer” por favor " +"quitelos. La protección CSRF necesita el encabezado “Referer” para realizar " +"una comprobación estricta de los referers. Si le preocupa la privacidad " +"tiene alternativas tales como usar en los enlaces a " +"sitios de terceros." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Ud. está viendo este mensaje porque este sitio tiene como requerimiento el " +"uso de una 'cookie' CSRF cuando se envíen formularios. El hecho de que esta " +"'cookie' sea obligatoria es una medida de seguridad para comprobar que su " +"browser no está siendo controlado por terceros." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Si ha configurado su browser para deshabilitar “cookies”, por favor " +"activelas al menos para este sitio o para peticiones generadas desde el " +"mismo origen." + +msgid "More information is available with DEBUG=True." +msgstr "Hay mas información disponible. Para ver la misma use DEBUG=True." + +msgid "No year specified" +msgstr "No se ha especificado el valor año" + +msgid "Date out of range" +msgstr "Fecha fuera de rango" + +msgid "No month specified" +msgstr "No se ha especificado el valor mes" + +msgid "No day specified" +msgstr "No se ha especificado el valor día" + +msgid "No week specified" +msgstr "No se ha especificado el valor semana" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "No hay %(verbose_name_plural)s disponibles" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"No hay %(verbose_name_plural)s futuros disponibles porque %(class_name)s." +"allow_future tiene el valor False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Cadena de fecha inválida “%(datestr)s”, formato “%(format)s”" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "No se han encontrado %(verbose_name)s que coincidan con la consulta " + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Página debe tener el valor “last” o un valor número entero." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Página inválida (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Lista vacía y “%(class_name)s.allow_empty” tiene el valor False." + +msgid "Directory indexes are not allowed here." +msgstr "" +"No está habilitada la generación de listados de directorios en esta " +"ubicación." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "“%(path)s” no existe" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Listado de %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "La instalación ha sido exitosa. ¡Felicitaciones!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Ver las release notes de Django %(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Está viendo esta página porque el archivo de configuración contiene DEBUG=True y no ha configurado " +"ninguna URL." + +msgid "Django Documentation" +msgstr "Documentación de Django" + +msgid "Topics, references, & how-to’s" +msgstr "Tópicos, referencia & how-to’s" + +msgid "Tutorial: A Polling App" +msgstr "Tutorial: Una app de encuesta" + +msgid "Get started with Django" +msgstr "Comience a aprender Django" + +msgid "Django Community" +msgstr "Comunidad Django" + +msgid "Connect, get help, or contribute" +msgstr "Conéctese, consiga ayuda o contribuya" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_AR/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_AR/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_AR/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_AR/formats.py new file mode 100644 index 0000000..601b458 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_AR/formats.py @@ -0,0 +1,30 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = r"j N Y" +TIME_FORMAT = r"H:i" +DATETIME_FORMAT = r"j N Y H:i" +YEAR_MONTH_FORMAT = r"F Y" +MONTH_DAY_FORMAT = r"j \d\e F" +SHORT_DATE_FORMAT = r"d/m/Y" +SHORT_DATETIME_FORMAT = r"d/m/Y H:i" +FIRST_DAY_OF_WEEK = 0 # 0: Sunday, 1: Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d/%m/%Y", # '31/12/2009' + "%d/%m/%y", # '31/12/09' +] +DATETIME_INPUT_FORMATS = [ + "%d/%m/%Y %H:%M:%S", + "%d/%m/%Y %H:%M:%S.%f", + "%d/%m/%Y %H:%M", + "%d/%m/%y %H:%M:%S", + "%d/%m/%y %H:%M:%S.%f", + "%d/%m/%y %H:%M", +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_CO/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_CO/LC_MESSAGES/django.mo new file mode 100644 index 0000000..678fdc7 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_CO/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_CO/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_CO/LC_MESSAGES/django.po new file mode 100644 index 0000000..9f839fe --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_CO/LC_MESSAGES/django.po @@ -0,0 +1,1258 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Carlos Muñoz , 2015 +# Claude Paroz , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-19 20:23+0200\n" +"PO-Revision-Date: 2020-07-14 21:42+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Spanish (Colombia) (http://www.transifex.com/django/django/" +"language/es_CO/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_CO\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Afrikáans" + +msgid "Arabic" +msgstr "Árabe" + +msgid "Algerian Arabic" +msgstr "" + +msgid "Asturian" +msgstr "Asturiano" + +msgid "Azerbaijani" +msgstr "Azerí" + +msgid "Bulgarian" +msgstr "Búlgaro" + +msgid "Belarusian" +msgstr "Bielorruso" + +msgid "Bengali" +msgstr "Bengalí" + +msgid "Breton" +msgstr "Bretón" + +msgid "Bosnian" +msgstr "Bosnio" + +msgid "Catalan" +msgstr "Catalán" + +msgid "Czech" +msgstr "Checo" + +msgid "Welsh" +msgstr "Galés" + +msgid "Danish" +msgstr "Danés" + +msgid "German" +msgstr "Alemán" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "Griego" + +msgid "English" +msgstr "Inglés" + +msgid "Australian English" +msgstr "Inglés Australiano" + +msgid "British English" +msgstr "Inglés Británico" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Español" + +msgid "Argentinian Spanish" +msgstr "Español de Argentina" + +msgid "Colombian Spanish" +msgstr "" + +msgid "Mexican Spanish" +msgstr "Español de México" + +msgid "Nicaraguan Spanish" +msgstr "Español de Nicaragua" + +msgid "Venezuelan Spanish" +msgstr "Español venezolano" + +msgid "Estonian" +msgstr "Estonio" + +msgid "Basque" +msgstr "Vasco" + +msgid "Persian" +msgstr "Persa" + +msgid "Finnish" +msgstr "Finés" + +msgid "French" +msgstr "Francés" + +msgid "Frisian" +msgstr "Frisón" + +msgid "Irish" +msgstr "Irlandés" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "Gallego" + +msgid "Hebrew" +msgstr "Hebreo" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Croata" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "Húngaro" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonesio" + +msgid "Igbo" +msgstr "" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Islandés" + +msgid "Italian" +msgstr "Italiano" + +msgid "Japanese" +msgstr "Japonés" + +msgid "Georgian" +msgstr "Georgiano" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "Kazajo" + +msgid "Khmer" +msgstr "Khmer" + +msgid "Kannada" +msgstr "Kannada" + +msgid "Korean" +msgstr "Koreano" + +msgid "Kyrgyz" +msgstr "" + +msgid "Luxembourgish" +msgstr "Luxenburgués" + +msgid "Lithuanian" +msgstr "Lituano" + +msgid "Latvian" +msgstr "Letón" + +msgid "Macedonian" +msgstr "Macedonio" + +msgid "Malayalam" +msgstr "Malayalam" + +msgid "Mongolian" +msgstr "Mongol" + +msgid "Marathi" +msgstr "Maratí" + +msgid "Burmese" +msgstr "Birmano" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "Nepalí" + +msgid "Dutch" +msgstr "Holandés" + +msgid "Norwegian Nynorsk" +msgstr "Nynorsk" + +msgid "Ossetic" +msgstr "Osetio" + +msgid "Punjabi" +msgstr "Panyabí" + +msgid "Polish" +msgstr "Polaco" + +msgid "Portuguese" +msgstr "Portugués" + +msgid "Brazilian Portuguese" +msgstr "Portugués brasileño" + +msgid "Romanian" +msgstr "Rumano" + +msgid "Russian" +msgstr "Ruso" + +msgid "Slovak" +msgstr "Eslovaco" + +msgid "Slovenian" +msgstr "Esloveno" + +msgid "Albanian" +msgstr "Albanés" + +msgid "Serbian" +msgstr "Serbio" + +msgid "Serbian Latin" +msgstr "Serbio latino" + +msgid "Swedish" +msgstr "Sueco" + +msgid "Swahili" +msgstr "Suajili" + +msgid "Tamil" +msgstr "Tamil" + +msgid "Telugu" +msgstr "Telugu" + +msgid "Tajik" +msgstr "" + +msgid "Thai" +msgstr "Tailandés" + +msgid "Turkmen" +msgstr "" + +msgid "Turkish" +msgstr "Turco" + +msgid "Tatar" +msgstr "Tártaro" + +msgid "Udmurt" +msgstr "Udmurt" + +msgid "Ukrainian" +msgstr "Ucraniano" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "Vietnamita" + +msgid "Simplified Chinese" +msgstr "Chino simplificado" + +msgid "Traditional Chinese" +msgstr "Chino tradicional" + +msgid "Messages" +msgstr "Mensajes" + +msgid "Site Maps" +msgstr "Mapas del sitio" + +msgid "Static Files" +msgstr "Archivos estáticos" + +msgid "Syndication" +msgstr "Sindicación" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "Ingrese un valor válido." + +msgid "Enter a valid URL." +msgstr "Ingrese una URL válida." + +msgid "Enter a valid integer." +msgstr "Ingrese un entero válido." + +msgid "Enter a valid email address." +msgstr "Ingrese una dirección de correo electrónico válida." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Ingrese una dirección IPv4 válida." + +msgid "Enter a valid IPv6 address." +msgstr "Ingrese una dirección IPv6 válida." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Ingrese una dirección IPv4 o IPv6 válida." + +msgid "Enter only digits separated by commas." +msgstr "Ingrese solo números separados por comas." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Asegúrese de que este valor es %(limit_value)s (es %(show_value)s )." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Asegúrese de que este valor sea menor o igual a %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Asegúrese de que este valor sea mayor o igual a %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Asegúrese de que este valor tenga como mínimo %(limit_value)d carácter " +"(tiene %(show_value)d)." +msgstr[1] "" +"Asegúrese de que este valor tenga como mínimo %(limit_value)d caracteres " +"(tiene %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Asegúrese de que este valor tenga como máximo %(limit_value)d carácter " +"(tiene %(show_value)d)." +msgstr[1] "" +"Asegúrese de que este valor tenga como máximo %(limit_value)d caracteres " +"(tiene %(show_value)d)." + +msgid "Enter a number." +msgstr "Ingrese un número." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Asegúrese de que no hayan mas de %(max)s dígito en total." +msgstr[1] "Asegúrese de que no hayan mas de %(max)s dígitos en total." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Asegúrese de que no hayan más de %(max)s decimal." +msgstr[1] "Asegúrese de que no hayan más de %(max)s decimales." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Asegúrese de que no hayan más de %(max)s dígito antes del punto decimal." +msgstr[1] "" +"Asegúrese de que no hayan más de %(max)s dígitos antes del punto decimal" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "y" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "Ya existe un/a %(model_name)s con este/a %(field_labels)s." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Valor %(value)r no es una opción válida." + +msgid "This field cannot be null." +msgstr "Este campo no puede ser nulo." + +msgid "This field cannot be blank." +msgstr "Este campo no puede estar en blanco." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "Ya existe un/a %(model_name)s con este/a %(field_label)s." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s debe ser único para %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Tipo de campo: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "Booleano (Verdadero o Falso)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Cadena (máximo %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "Enteros separados por comas" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "Fecha (sin hora)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Fecha (con hora)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Número decimal" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "Duración" + +msgid "Email address" +msgstr "Dirección de correo electrónico" + +msgid "File path" +msgstr "Ruta de archivo" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "Número de punto flotante" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "Entero" + +msgid "Big (8 byte) integer" +msgstr "Entero grande (8 bytes)" + +msgid "IPv4 address" +msgstr "Dirección IPv4" + +msgid "IP address" +msgstr "Dirección IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "Booleano (Verdadero, Falso o Nulo)" + +msgid "Positive big integer" +msgstr "" + +msgid "Positive integer" +msgstr "Entero positivo" + +msgid "Positive small integer" +msgstr "Entero positivo pequeño" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (hasta %(max_length)s)" + +msgid "Small integer" +msgstr "Entero pequeño" + +msgid "Text" +msgstr "Texto" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Hora" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Datos de binarios brutos" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "Archivo" + +msgid "Image" +msgstr "Imagen" + +msgid "A JSON object" +msgstr "" + +msgid "Value must be valid JSON." +msgstr "" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "La instancia del %(model)s con %(field)s %(value)r no existe." + +msgid "Foreign Key (type determined by related field)" +msgstr "Llave foránea (tipo determinado por el campo relacionado)" + +msgid "One-to-one relationship" +msgstr "Relación uno-a-uno" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "Relación muchos-a-muchos" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Este campo es obligatorio." + +msgid "Enter a whole number." +msgstr "Ingrese un número entero." + +msgid "Enter a valid date." +msgstr "Ingrese una fecha válida." + +msgid "Enter a valid time." +msgstr "Ingrese una hora válida." + +msgid "Enter a valid date/time." +msgstr "Ingrese una fecha/hora válida." + +msgid "Enter a valid duration." +msgstr "Ingrese una duración válida." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" +"No se ha enviado ningún fichero. Compruebe el tipo de codificación en el " +"formulario." + +msgid "No file was submitted." +msgstr "No se ha enviado ningún fichero." + +msgid "The submitted file is empty." +msgstr "El fichero enviado está vacío." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Asegúrese de que este nombre de archivo tenga como máximo %(max)d carácter " +"(tiene %(length)d)." +msgstr[1] "" +"Asegúrese de que este nombre de archivo tenga como máximo %(max)d caracteres " +"(tiene %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Por favor envíe un fichero o marque la casilla de limpiar, pero no ambos." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Envíe una imagen válida. El fichero que ha enviado no era una imagen o se " +"trataba de una imagen corrupta." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Escoja una opción válida. %(value)s no es una de las opciones disponibles." + +msgid "Enter a list of values." +msgstr "Ingrese una lista de valores." + +msgid "Enter a complete value." +msgstr "Ingrese un valor completo." + +msgid "Enter a valid UUID." +msgstr "Ingrese un UUID válido." + +msgid "Enter a valid JSON." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Campo oculto %(name)s) *%(error)s" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "Los datos de ManagementForm faltan o han sido manipulados" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "Por favor, envíe %d o menos formularios." +msgstr[1] "Por favor, envíe %d o menos formularios." + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "Por favor, envíe %d o mas formularios." +msgstr[1] "Por favor, envíe %d o mas formularios." + +msgid "Order" +msgstr "Orden" + +msgid "Delete" +msgstr "Eliminar" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Por favor, corrija el dato duplicado para %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Por favor corrija el dato duplicado para %(field)s, este debe ser único." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Por favor corrija los datos duplicados para %(field_name)s este debe ser " +"único para %(lookup)s en %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Por favor, corrija los valores duplicados abajo." + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Escoja una opción válida. Esa opción no está entre las disponibles." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Limpiar" + +msgid "Currently" +msgstr "Actualmente" + +msgid "Change" +msgstr "Cambiar" + +msgid "Unknown" +msgstr "Desconocido" + +msgid "Yes" +msgstr "Sí" + +msgid "No" +msgstr "No" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "sí,no,quizás" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d byte" +msgstr[1] "%(size)d bytes" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "medianoche" + +msgid "noon" +msgstr "mediodía" + +msgid "Monday" +msgstr "Lunes" + +msgid "Tuesday" +msgstr "Martes" + +msgid "Wednesday" +msgstr "Miércoles" + +msgid "Thursday" +msgstr "Jueves" + +msgid "Friday" +msgstr "Viernes" + +msgid "Saturday" +msgstr "Sábado" + +msgid "Sunday" +msgstr "Domingo" + +msgid "Mon" +msgstr "Lun" + +msgid "Tue" +msgstr "Mar" + +msgid "Wed" +msgstr "Mié" + +msgid "Thu" +msgstr "Jue" + +msgid "Fri" +msgstr "Vie" + +msgid "Sat" +msgstr "Sáb" + +msgid "Sun" +msgstr "Dom" + +msgid "January" +msgstr "Enero" + +msgid "February" +msgstr "Febrero" + +msgid "March" +msgstr "Marzo" + +msgid "April" +msgstr "Abril" + +msgid "May" +msgstr "Mayo" + +msgid "June" +msgstr "Junio" + +msgid "July" +msgstr "Julio" + +msgid "August" +msgstr "Agosto" + +msgid "September" +msgstr "Septiembre" + +msgid "October" +msgstr "Octubre" + +msgid "November" +msgstr "Noviembre" + +msgid "December" +msgstr "Diciembre" + +msgid "jan" +msgstr "ene" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "abr" + +msgid "may" +msgstr "may" + +msgid "jun" +msgstr "jun" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "ago" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "oct" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dic" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Ene." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Marzo" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Abril" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Mayo" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Junio" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Julio" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Ago." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Sep." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Oct." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dic." + +msgctxt "alt. month" +msgid "January" +msgstr "Enero" + +msgctxt "alt. month" +msgid "February" +msgstr "Febrero" + +msgctxt "alt. month" +msgid "March" +msgstr "Marzo" + +msgctxt "alt. month" +msgid "April" +msgstr "Abril" + +msgctxt "alt. month" +msgid "May" +msgstr "Mayo" + +msgctxt "alt. month" +msgid "June" +msgstr "Junio" + +msgctxt "alt. month" +msgid "July" +msgstr "Julio" + +msgctxt "alt. month" +msgid "August" +msgstr "Agosto" + +msgctxt "alt. month" +msgid "September" +msgstr "Septiembre" + +msgctxt "alt. month" +msgid "October" +msgstr "Octubre" + +msgctxt "alt. month" +msgid "November" +msgstr "Noviembre" + +msgctxt "alt. month" +msgid "December" +msgstr "Diciembre" + +msgid "This is not a valid IPv6 address." +msgstr "Esta no es una dirección IPv6 válida." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "o" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "," + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d año" +msgstr[1] "%d años" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d mes" +msgstr[1] "%d meses" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d semana" +msgstr[1] "%d semanas" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d día" +msgstr[1] "%d días" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d hora" +msgstr[1] "%d horas" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d minuto" +msgstr[1] "%d minutos" + +msgid "Forbidden" +msgstr "Prohibido" + +msgid "CSRF verification failed. Request aborted." +msgstr "Verificación CSRF fallida. Solicitud abortada." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Estás viendo este mensaje porqué esta web requiere una cookie CSRF cuando se " +"envían formularios. Esta cookie se necesita por razones de seguridad, para " +"asegurar que tu navegador no ha sido comprometido por terceras partes." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "Se puede ver más información si se establece DEBUG=True." + +msgid "No year specified" +msgstr "No se ha indicado el año" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "No se ha indicado el mes" + +msgid "No day specified" +msgstr "No se ha indicado el día" + +msgid "No week specified" +msgstr "No se ha indicado la semana" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "No %(verbose_name_plural)s disponibles" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Los futuros %(verbose_name_plural)s no están disponibles porque " +"%(class_name)s.allow_future es Falso." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "No se encontró ningún %(verbose_name)s coincidente con la consulta" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Página inválida (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Los índices de directorio no están permitidos." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Índice de %(directory)s" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_CO/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_CO/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_CO/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_CO/formats.py new file mode 100644 index 0000000..056d0ad --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_CO/formats.py @@ -0,0 +1,26 @@ +# This file is distributed under the same license as the Django package. +# +DATE_FORMAT = r"j \d\e F \d\e Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = r"j \d\e F \d\e Y \a \l\a\s H:i" +YEAR_MONTH_FORMAT = r"F \d\e Y" +MONTH_DAY_FORMAT = r"j \d\e F" +SHORT_DATE_FORMAT = "d/m/Y" +SHORT_DATETIME_FORMAT = "d/m/Y H:i" +FIRST_DAY_OF_WEEK = 1 +DATE_INPUT_FORMATS = [ + "%d/%m/%Y", # '25/10/2006' + "%d/%m/%y", # '25/10/06' + "%Y%m%d", # '20061025' +] +DATETIME_INPUT_FORMATS = [ + "%d/%m/%Y %H:%M:%S", + "%d/%m/%Y %H:%M:%S.%f", + "%d/%m/%Y %H:%M", + "%d/%m/%y %H:%M:%S", + "%d/%m/%y %H:%M:%S.%f", + "%d/%m/%y %H:%M", +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_MX/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_MX/LC_MESSAGES/django.mo new file mode 100644 index 0000000..42f2691 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_MX/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_MX/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_MX/LC_MESSAGES/django.po new file mode 100644 index 0000000..93b81a4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_MX/LC_MESSAGES/django.po @@ -0,0 +1,1279 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Abe Estrada, 2011-2013 +# Claude Paroz , 2020 +# Gustavo López Hernández, 2022 +# Jesús Bautista , 2019-2020 +# Sergio Benitez , 2021 +# zodman , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-05-17 05:23-0500\n" +"PO-Revision-Date: 2022-07-25 06:49+0000\n" +"Last-Translator: Gustavo López Hernández\n" +"Language-Team: Spanish (Mexico) (http://www.transifex.com/django/django/" +"language/es_MX/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_MX\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "afrikáans" + +msgid "Arabic" +msgstr "Árabe" + +msgid "Algerian Arabic" +msgstr "Árabe argelino" + +msgid "Asturian" +msgstr "Asturiano" + +msgid "Azerbaijani" +msgstr "Azerbaijani" + +msgid "Bulgarian" +msgstr "Búlgaro" + +msgid "Belarusian" +msgstr "bielorruso" + +msgid "Bengali" +msgstr "Bengalí" + +msgid "Breton" +msgstr "bretón" + +msgid "Bosnian" +msgstr "Bosnio" + +msgid "Catalan" +msgstr "Catalán" + +msgid "Czech" +msgstr "Checo" + +msgid "Welsh" +msgstr "Galés" + +msgid "Danish" +msgstr "Danés" + +msgid "German" +msgstr "Alemán" + +msgid "Lower Sorbian" +msgstr "Bajo sorbio" + +msgid "Greek" +msgstr "Griego" + +msgid "English" +msgstr "Inglés" + +msgid "Australian English" +msgstr "Inglés australiano" + +msgid "British English" +msgstr "Inglés británico" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Español" + +msgid "Argentinian Spanish" +msgstr "Español de Argentina" + +msgid "Colombian Spanish" +msgstr "Español Colombiano" + +msgid "Mexican Spanish" +msgstr "Español de México" + +msgid "Nicaraguan Spanish" +msgstr "Español de nicaragua" + +msgid "Venezuelan Spanish" +msgstr "español de Venezuela" + +msgid "Estonian" +msgstr "Estonio" + +msgid "Basque" +msgstr "Vasco" + +msgid "Persian" +msgstr "Persa" + +msgid "Finnish" +msgstr "Finés" + +msgid "French" +msgstr "Francés" + +msgid "Frisian" +msgstr "Frisón" + +msgid "Irish" +msgstr "Irlandés" + +msgid "Scottish Gaelic" +msgstr "Gaélico escocés" + +msgid "Galician" +msgstr "Gallego" + +msgid "Hebrew" +msgstr "Hebreo" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Croata" + +msgid "Upper Sorbian" +msgstr "Alto sorbio" + +msgid "Hungarian" +msgstr "Húngaro" + +msgid "Armenian" +msgstr "Armenio" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonesio" + +msgid "Igbo" +msgstr "Igbo" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Islandés" + +msgid "Italian" +msgstr "Italiano" + +msgid "Japanese" +msgstr "Japonés" + +msgid "Georgian" +msgstr "Georgiano" + +msgid "Kabyle" +msgstr "Cabilio" + +msgid "Kazakh" +msgstr "Kazajstán" + +msgid "Khmer" +msgstr "Khmer" + +msgid "Kannada" +msgstr "Kannada" + +msgid "Korean" +msgstr "Coreano" + +msgid "Kyrgyz" +msgstr "" + +msgid "Luxembourgish" +msgstr "luxemburgués" + +msgid "Lithuanian" +msgstr "Lituano" + +msgid "Latvian" +msgstr "Letón" + +msgid "Macedonian" +msgstr "Macedonio" + +msgid "Malayalam" +msgstr "Malayalam" + +msgid "Mongolian" +msgstr "Mongol" + +msgid "Marathi" +msgstr "" + +msgid "Malay" +msgstr "" + +msgid "Burmese" +msgstr "burmés" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "Nepal" + +msgid "Dutch" +msgstr "Holandés" + +msgid "Norwegian Nynorsk" +msgstr "Noruego Nynorsk" + +msgid "Ossetic" +msgstr "osetio" + +msgid "Punjabi" +msgstr "Punjabi" + +msgid "Polish" +msgstr "Polaco" + +msgid "Portuguese" +msgstr "Portugués" + +msgid "Brazilian Portuguese" +msgstr "Portugués de Brasil" + +msgid "Romanian" +msgstr "Rumano" + +msgid "Russian" +msgstr "Ruso" + +msgid "Slovak" +msgstr "Eslovaco" + +msgid "Slovenian" +msgstr "Esloveno" + +msgid "Albanian" +msgstr "Albanés" + +msgid "Serbian" +msgstr "Serbio" + +msgid "Serbian Latin" +msgstr "Latin Serbio" + +msgid "Swedish" +msgstr "Sueco" + +msgid "Swahili" +msgstr "Swahili" + +msgid "Tamil" +msgstr "Tamil" + +msgid "Telugu" +msgstr "Telugu" + +msgid "Tajik" +msgstr "" + +msgid "Thai" +msgstr "Tailandés" + +msgid "Turkmen" +msgstr "" + +msgid "Turkish" +msgstr "Turco" + +msgid "Tatar" +msgstr "Tatar" + +msgid "Udmurt" +msgstr "udmurto" + +msgid "Ukrainian" +msgstr "Ucraniano" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "Vietnamita" + +msgid "Simplified Chinese" +msgstr "Chino simplificado" + +msgid "Traditional Chinese" +msgstr "Chino tradicional" + +msgid "Messages" +msgstr "Mensajes" + +msgid "Site Maps" +msgstr "Mapas del sitio" + +msgid "Static Files" +msgstr "Archivos Estáticos" + +msgid "Syndication" +msgstr "Sindicación" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "" + +msgid "That page number is not an integer" +msgstr "Ese número de página no es un número entero" + +msgid "That page number is less than 1" +msgstr "Ese número de página es menor que 1" + +msgid "That page contains no results" +msgstr "Esa página no contiene resultados" + +msgid "Enter a valid value." +msgstr "Introduzca un valor válido." + +msgid "Enter a valid URL." +msgstr "Ingrese una URL válida." + +msgid "Enter a valid integer." +msgstr "Ingrese un entero válido." + +msgid "Enter a valid email address." +msgstr "Introduzca una dirección de correo electrónico válida." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Introduzca un \"slug\" válido que conste de letras, números, guiones bajos o " +"guiones." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Introduzca un \"slug\" válido que conste de letras Unicode, números, guiones " +"bajos o guiones." + +msgid "Enter a valid IPv4 address." +msgstr "Introduzca una dirección IPv4 válida." + +msgid "Enter a valid IPv6 address." +msgstr "Introduzca una dirección IPv6 válida." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Introduzca una dirección IPv4 o IPv6 válida." + +msgid "Enter only digits separated by commas." +msgstr "Introduzca sólo números separados por comas." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Asegúrese de que este valor es %(limit_value)s (es %(show_value)s )." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Asegúrese de que este valor sea menor o igual a %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Asegúrese de que este valor sea mayor o igual a %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Asegúrese de que este valor tenga como mínimo %(limit_value)d caracter " +"(tiene %(show_value)d)." +msgstr[1] "" +"Asegúrese de que este valor tenga como mínimo %(limit_value)d caracteres " +"(tiene %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Asegúrese de que este valor tenga como máximo %(limit_value)d caracteres " +"(tiene %(show_value)d)." +msgstr[1] "" +"Asegúrese de que este valor tenga como máximo %(limit_value)d caracteres " +"(tiene %(show_value)d)." + +msgid "Enter a number." +msgstr "Introduzca un número." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Asegúrese de que no hay más de %(max)s dígito en total." +msgstr[1] "Asegúrese de que no hay más de %(max)s dígitos en total." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "Caracteres nulos no están permitidos." + +msgid "and" +msgstr "y" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "El valor %(value)r no es una opción válida." + +msgid "This field cannot be null." +msgstr "Este campo no puede ser nulo." + +msgid "This field cannot be blank." +msgstr "Este campo no puede estar en blanco." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "Ya existe un/a %(model_name)s con este/a %(field_label)s." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Campo tipo: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "El valor \"%(value)s\" debe ser Verdadero o Falso. " + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "Boolean (Verdadero o Falso)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Cadena (máximo %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "Enteros separados por comas" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"“%(value)s” : el valor tiene un formato de fecha inválido. Debería estar en " +"el formato YYYY-MM-DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"“%(value)s” : el valor tiene el formato correcto (YYYY-MM-DD) pero es una " +"fecha inválida." + +msgid "Date (without time)" +msgstr "Fecha (sin hora)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"'%(value)s' tiene un formato de fecha no válido. Este valor debe estar en el " +"formato AAAA-MM-DD HH:MM[:ss[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Fecha (con hora)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Número decimal" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "Duración" + +msgid "Email address" +msgstr "Dirección de correo electrónico" + +msgid "File path" +msgstr "Ruta de archivo" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "El valor \"%(value)s\" debe ser flotante." + +msgid "Floating point number" +msgstr "Número de punto flotante" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "Entero" + +msgid "Big (8 byte) integer" +msgstr "Entero grande (8 bytes)" + +msgid "Small integer" +msgstr "Entero pequeño" + +msgid "IPv4 address" +msgstr "Dirección IPv4" + +msgid "IP address" +msgstr "Dirección IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "Booleano (Verdadero, Falso o Nulo)" + +msgid "Positive big integer" +msgstr "" + +msgid "Positive integer" +msgstr "Entero positivo" + +msgid "Positive small integer" +msgstr "Entero positivo pequeño" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (hasta %(max_length)s)" + +msgid "Text" +msgstr "Texto" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Hora" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Los datos en bruto" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "Archivo" + +msgid "Image" +msgstr "Imagen" + +msgid "A JSON object" +msgstr "Un objeto JSON" + +msgid "Value must be valid JSON." +msgstr "El valor debe ser JSON válido" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "La instancia de %(model)s con %(field)s %(value)r no existe." + +msgid "Foreign Key (type determined by related field)" +msgstr "Clave foránea (el tipo está determinado por el campo relacionado)" + +msgid "One-to-one relationship" +msgstr "Relación uno-a-uno" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "Relación %(from)s - %(to)s " + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "Relaciones %(from)s - %(to)s" + +msgid "Many-to-many relationship" +msgstr "Relación muchos-a-muchos" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Este campo es obligatorio." + +msgid "Enter a whole number." +msgstr "Introduzca un número entero." + +msgid "Enter a valid date." +msgstr "Introduzca una fecha válida." + +msgid "Enter a valid time." +msgstr "Introduzca una hora válida." + +msgid "Enter a valid date/time." +msgstr "Introduzca una fecha/hora válida." + +msgid "Enter a valid duration." +msgstr "Introduzca una duración válida." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "La cantidad de días debe tener valores entre {min_days} y {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" +"No se envió un archivo. Verifique el tipo de codificación en el formulario." + +msgid "No file was submitted." +msgstr "No se envió ningún archivo." + +msgid "The submitted file is empty." +msgstr "El archivo enviado está vacío." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Por favor envíe un archivo o marque la casilla, no ambos." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Seleccione una imagen válida. El archivo que ha seleccionado no es una " +"imagen o es un un archivo de imagen corrupto." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Seleccione una opción válida. %(value)s no es una de las opciones " +"disponibles." + +msgid "Enter a list of values." +msgstr "Introduzca una lista de valores." + +msgid "Enter a complete value." +msgstr "Ingrese un valor completo." + +msgid "Enter a valid UUID." +msgstr "Ingrese un UUID válido." + +msgid "Enter a valid JSON." +msgstr "Ingresa un JSON válido." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Campo oculto %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "Ordenar" + +msgid "Delete" +msgstr "Eliminar" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Por favor, corrija la información duplicada en %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Por favor corrija la información duplicada en %(field)s, que debe ser única." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Por favor corrija la información duplicada en %(field_name)s que debe ser " +"única para el %(lookup)s en %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Por favor, corrija los valores duplicados detallados mas abajo." + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Seleccione una opción válida. La opción seleccionada no es una de las " +"disponibles." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Borrar" + +msgid "Currently" +msgstr "Actualmente" + +msgid "Change" +msgstr "Modificar" + +msgid "Unknown" +msgstr "Desconocido" + +msgid "Yes" +msgstr "Sí" + +msgid "No" +msgstr "No" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "sí,no,tal vez" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d byte" +msgstr[1] "%(size)d bytes" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "medianoche" + +msgid "noon" +msgstr "mediodía" + +msgid "Monday" +msgstr "Lunes" + +msgid "Tuesday" +msgstr "Martes" + +msgid "Wednesday" +msgstr "Miércoles" + +msgid "Thursday" +msgstr "Jueves" + +msgid "Friday" +msgstr "Viernes" + +msgid "Saturday" +msgstr "Sábado" + +msgid "Sunday" +msgstr "Domingo" + +msgid "Mon" +msgstr "Lun" + +msgid "Tue" +msgstr "Mar" + +msgid "Wed" +msgstr "Mie" + +msgid "Thu" +msgstr "Jue" + +msgid "Fri" +msgstr "Vie" + +msgid "Sat" +msgstr "Sab" + +msgid "Sun" +msgstr "Dom" + +msgid "January" +msgstr "Enero" + +msgid "February" +msgstr "Febrero" + +msgid "March" +msgstr "Marzo" + +msgid "April" +msgstr "Abril" + +msgid "May" +msgstr "Mayo" + +msgid "June" +msgstr "Junio" + +msgid "July" +msgstr "Julio" + +msgid "August" +msgstr "Agosto" + +msgid "September" +msgstr "Septiembre" + +msgid "October" +msgstr "Octubre" + +msgid "November" +msgstr "Noviembre" + +msgid "December" +msgstr "Diciembre" + +msgid "jan" +msgstr "ene" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "abr" + +msgid "may" +msgstr "may" + +msgid "jun" +msgstr "jun" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "ago" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "oct" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dic" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Ene." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Marzo" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Abril" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Mayo" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Junio" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Julio" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Ago." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Sep." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Oct." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dic." + +msgctxt "alt. month" +msgid "January" +msgstr "Enero" + +msgctxt "alt. month" +msgid "February" +msgstr "Febrero" + +msgctxt "alt. month" +msgid "March" +msgstr "Marzo" + +msgctxt "alt. month" +msgid "April" +msgstr "Abril" + +msgctxt "alt. month" +msgid "May" +msgstr "Mayo" + +msgctxt "alt. month" +msgid "June" +msgstr "Junio" + +msgctxt "alt. month" +msgid "July" +msgstr "Julio" + +msgctxt "alt. month" +msgid "August" +msgstr "Agosto" + +msgctxt "alt. month" +msgid "September" +msgstr "Septiembre" + +msgctxt "alt. month" +msgid "October" +msgstr "Octubre" + +msgctxt "alt. month" +msgid "November" +msgstr "Noviembre" + +msgctxt "alt. month" +msgid "December" +msgstr "Diciembre" + +msgid "This is not a valid IPv6 address." +msgstr "Esta no es una dirección IPv6 válida." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "o" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "," + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hora" +msgstr[1] "%(num)d horas" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "" +msgstr[1] "" + +msgid "Forbidden" +msgstr "Prohibido" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "No se ha especificado el valor año" + +msgid "Date out of range" +msgstr "Fecha fuera de rango" + +msgid "No month specified" +msgstr "No se ha especificado el valor mes" + +msgid "No day specified" +msgstr "No se ha especificado el valor dia" + +msgid "No week specified" +msgstr "No se ha especificado el valor semana" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "No hay %(verbose_name_plural)s disponibles" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"No hay %(verbose_name_plural)s futuros disponibles porque %(class_name)s." +"allow_future tiene el valor False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "No se han encontrado %(verbose_name)s que coincidan con la consulta" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "La página no es \"last\", ni puede ser convertido a un int." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Página inválida (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Los índices del directorio no están permitidos." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Índice de %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "¡La instalación funcionó con éxito! ¡Felicidades!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "Documentación de Django" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "Comunidad de Django" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_MX/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_MX/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_MX/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_MX/formats.py new file mode 100644 index 0000000..d675d79 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_MX/formats.py @@ -0,0 +1,26 @@ +# This file is distributed under the same license as the Django package. +# +DATE_FORMAT = r"j \d\e F \d\e Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = r"j \d\e F \d\e Y \a \l\a\s H:i" +YEAR_MONTH_FORMAT = r"F \d\e Y" +MONTH_DAY_FORMAT = r"j \d\e F" +SHORT_DATE_FORMAT = "d/m/Y" +SHORT_DATETIME_FORMAT = "d/m/Y H:i" +FIRST_DAY_OF_WEEK = 1 # Monday: ISO 8601 +DATE_INPUT_FORMATS = [ + "%d/%m/%Y", # '25/10/2006' + "%d/%m/%y", # '25/10/06' + "%Y%m%d", # '20061025' +] +DATETIME_INPUT_FORMATS = [ + "%d/%m/%Y %H:%M:%S", + "%d/%m/%Y %H:%M:%S.%f", + "%d/%m/%Y %H:%M", + "%d/%m/%y %H:%M:%S", + "%d/%m/%y %H:%M:%S.%f", + "%d/%m/%y %H:%M", +] +DECIMAL_SEPARATOR = "." # ',' is also official (less common): NOM-008-SCFI-2002 +THOUSAND_SEPARATOR = "," +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_NI/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_NI/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_NI/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_NI/formats.py new file mode 100644 index 0000000..0c8112a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_NI/formats.py @@ -0,0 +1,26 @@ +# This file is distributed under the same license as the Django package. +# +DATE_FORMAT = r"j \d\e F \d\e Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = r"j \d\e F \d\e Y \a \l\a\s H:i" +YEAR_MONTH_FORMAT = r"F \d\e Y" +MONTH_DAY_FORMAT = r"j \d\e F" +SHORT_DATE_FORMAT = "d/m/Y" +SHORT_DATETIME_FORMAT = "d/m/Y H:i" +FIRST_DAY_OF_WEEK = 1 # Monday: ISO 8601 +DATE_INPUT_FORMATS = [ + "%d/%m/%Y", # '25/10/2006' + "%d/%m/%y", # '25/10/06' + "%Y%m%d", # '20061025' +] +DATETIME_INPUT_FORMATS = [ + "%d/%m/%Y %H:%M:%S", + "%d/%m/%Y %H:%M:%S.%f", + "%d/%m/%Y %H:%M", + "%d/%m/%y %H:%M:%S", + "%d/%m/%y %H:%M:%S.%f", + "%d/%m/%y %H:%M", +] +DECIMAL_SEPARATOR = "." +THOUSAND_SEPARATOR = "," +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_PR/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_PR/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_PR/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_PR/formats.py new file mode 100644 index 0000000..d50fe5d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_PR/formats.py @@ -0,0 +1,27 @@ +# This file is distributed under the same license as the Django package. +# +DATE_FORMAT = r"j \d\e F \d\e Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = r"j \d\e F \d\e Y \a \l\a\s H:i" +YEAR_MONTH_FORMAT = r"F \d\e Y" +MONTH_DAY_FORMAT = r"j \d\e F" +SHORT_DATE_FORMAT = "d/m/Y" +SHORT_DATETIME_FORMAT = "d/m/Y H:i" +FIRST_DAY_OF_WEEK = 0 # Sunday + +DATE_INPUT_FORMATS = [ + "%d/%m/%Y", # '31/12/2009' + "%d/%m/%y", # '31/12/09' +] +DATETIME_INPUT_FORMATS = [ + "%d/%m/%Y %H:%M:%S", + "%d/%m/%Y %H:%M:%S.%f", + "%d/%m/%Y %H:%M", + "%d/%m/%y %H:%M:%S", + "%d/%m/%y %H:%M:%S.%f", + "%d/%m/%y %H:%M", +] + +DECIMAL_SEPARATOR = "." +THOUSAND_SEPARATOR = "," +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_VE/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_VE/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f7efb3e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_VE/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_VE/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_VE/LC_MESSAGES/django.po new file mode 100644 index 0000000..bd0a904 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/es_VE/LC_MESSAGES/django.po @@ -0,0 +1,1260 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Claude Paroz , 2020 +# Eduardo , 2017 +# Leonardo J. Caballero G. , 2016 +# Sebastián Magrí, 2011 +# Yoel Acevedo, 2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-19 20:23+0200\n" +"PO-Revision-Date: 2020-07-14 21:42+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Spanish (Venezuela) (http://www.transifex.com/django/django/" +"language/es_VE/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_VE\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Afrikáans" + +msgid "Arabic" +msgstr "Árabe" + +msgid "Algerian Arabic" +msgstr "" + +msgid "Asturian" +msgstr "Asturiano" + +msgid "Azerbaijani" +msgstr "Azerí" + +msgid "Bulgarian" +msgstr "Búlgaro" + +msgid "Belarusian" +msgstr "Bielorruso" + +msgid "Bengali" +msgstr "Bengalí" + +msgid "Breton" +msgstr "Bretón" + +msgid "Bosnian" +msgstr "Bosnio" + +msgid "Catalan" +msgstr "Catalán" + +msgid "Czech" +msgstr "Checo" + +msgid "Welsh" +msgstr "Galés" + +msgid "Danish" +msgstr "Danés" + +msgid "German" +msgstr "Alemán" + +msgid "Lower Sorbian" +msgstr "Sorbio Inferior" + +msgid "Greek" +msgstr "Griego" + +msgid "English" +msgstr "Inglés" + +msgid "Australian English" +msgstr "Inglés Australiano" + +msgid "British English" +msgstr "Inglés Británico" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Español" + +msgid "Argentinian Spanish" +msgstr "Español de Argentina" + +msgid "Colombian Spanish" +msgstr "Español de Colombia" + +msgid "Mexican Spanish" +msgstr "Español de México" + +msgid "Nicaraguan Spanish" +msgstr "Español de Nicaragua" + +msgid "Venezuelan Spanish" +msgstr "Español de Venezuela" + +msgid "Estonian" +msgstr "Estonio" + +msgid "Basque" +msgstr "Vazco" + +msgid "Persian" +msgstr "Persa" + +msgid "Finnish" +msgstr "Finlandés" + +msgid "French" +msgstr "Francés" + +msgid "Frisian" +msgstr "Frisio" + +msgid "Irish" +msgstr "Irlandés" + +msgid "Scottish Gaelic" +msgstr "Gaélico Escocés" + +msgid "Galician" +msgstr "Galés" + +msgid "Hebrew" +msgstr "Hebreo" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Croata" + +msgid "Upper Sorbian" +msgstr "Sorbio Superior" + +msgid "Hungarian" +msgstr "Húngaro" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonesio" + +msgid "Igbo" +msgstr "" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Islandés" + +msgid "Italian" +msgstr "Italiano" + +msgid "Japanese" +msgstr "Japonés" + +msgid "Georgian" +msgstr "Georgiano" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "Kazajo" + +msgid "Khmer" +msgstr "Khmer" + +msgid "Kannada" +msgstr "Canarés" + +msgid "Korean" +msgstr "Coreano" + +msgid "Kyrgyz" +msgstr "" + +msgid "Luxembourgish" +msgstr "Luxenburgués" + +msgid "Lithuanian" +msgstr "Lituano" + +msgid "Latvian" +msgstr "Latvio" + +msgid "Macedonian" +msgstr "Macedonio" + +msgid "Malayalam" +msgstr "Malayala" + +msgid "Mongolian" +msgstr "Mongol" + +msgid "Marathi" +msgstr "Maratí" + +msgid "Burmese" +msgstr "Birmano" + +msgid "Norwegian Bokmål" +msgstr "Noruego" + +msgid "Nepali" +msgstr "Nepalí" + +msgid "Dutch" +msgstr "Holandés" + +msgid "Norwegian Nynorsk" +msgstr "Nynorsk" + +msgid "Ossetic" +msgstr "Osetio" + +msgid "Punjabi" +msgstr "Punjabi" + +msgid "Polish" +msgstr "Polaco" + +msgid "Portuguese" +msgstr "Portugués" + +msgid "Brazilian Portuguese" +msgstr "Portugués de Brasil" + +msgid "Romanian" +msgstr "Ruman" + +msgid "Russian" +msgstr "Ruso" + +msgid "Slovak" +msgstr "Eslovaco" + +msgid "Slovenian" +msgstr "Eslovenio" + +msgid "Albanian" +msgstr "Albano" + +msgid "Serbian" +msgstr "Serbi" + +msgid "Serbian Latin" +msgstr "Latín Serbio" + +msgid "Swedish" +msgstr "Sueco" + +msgid "Swahili" +msgstr "Suajili" + +msgid "Tamil" +msgstr "Tamil" + +msgid "Telugu" +msgstr "Telugu" + +msgid "Tajik" +msgstr "" + +msgid "Thai" +msgstr "Tailandés" + +msgid "Turkmen" +msgstr "" + +msgid "Turkish" +msgstr "Turco" + +msgid "Tatar" +msgstr "Tártaro" + +msgid "Udmurt" +msgstr "Udmurt" + +msgid "Ukrainian" +msgstr "Ucranio" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "Vietnamita" + +msgid "Simplified Chinese" +msgstr "Chino simplificado" + +msgid "Traditional Chinese" +msgstr "Chino tradicional" + +msgid "Messages" +msgstr "Mensajes" + +msgid "Site Maps" +msgstr "Mapas del sitio" + +msgid "Static Files" +msgstr "Archivos estáticos" + +msgid "Syndication" +msgstr "Sindicación" + +msgid "That page number is not an integer" +msgstr "Ese número de página no es un número entero" + +msgid "That page number is less than 1" +msgstr "Ese número de página es menor que 1" + +msgid "That page contains no results" +msgstr "Esa página no contiene resultados" + +msgid "Enter a valid value." +msgstr "Introduzca un valor válido." + +msgid "Enter a valid URL." +msgstr "Introduzca una URL válida." + +msgid "Enter a valid integer." +msgstr "Ingrese un valor válido." + +msgid "Enter a valid email address." +msgstr "Ingrese una dirección de correo electrónico válida." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Introduzca una dirección IPv4 válida." + +msgid "Enter a valid IPv6 address." +msgstr "Ingrese una dirección IPv6 válida." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Ingrese una dirección IPv4 o IPv6 válida." + +msgid "Enter only digits separated by commas." +msgstr "Introduzca solo dígitos separados por comas." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Asegúrese de que este valor %(limit_value)s (ahora es %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Asegúrese de que este valor es menor o igual que %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Asegúrese de que este valor es mayor o igual que %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Asegúrese de que este valor tenga como mínimo %(limit_value)d carácter " +"(tiene %(show_value)d)." +msgstr[1] "" +"Asegúrese de que este valor tenga como mínimo %(limit_value)d caracteres " +"(tiene %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Asegúrese de que este valor tenga como máximo %(limit_value)d carácter " +"(tiene %(show_value)d)." +msgstr[1] "" +"Asegúrese de que este valor tenga como máximo %(limit_value)d caracteres " +"(tiene %(show_value)d)." + +msgid "Enter a number." +msgstr "Introduzca un número." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Asegúrese de que no hayan más de %(max)s dígito en total." +msgstr[1] "Asegúrese de que no hayan más de %(max)s dígitos en total." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Asegúrese de que no hayan más de %(max)s decimal." +msgstr[1] "Asegúrese de que no hayan más de %(max)s decimales." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Asegúrese de que no hayan más de %(max)s dígito antes del punto decimal." +msgstr[1] "" +"Asegúrese de que no hayan más de %(max)s dígitos antes del punto decimal." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "y" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s con este %(field_labels)s ya existe." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Valor %(value)r no es una opción válida." + +msgid "This field cannot be null." +msgstr "Este campo no puede ser nulo." + +msgid "This field cannot be blank." +msgstr "Este campo no puede estar en blanco." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s con esta %(field_label)s ya existe." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s debe ser único para %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Tipo de campo: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "Booleano (Verdadero o Falso)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Cadena (máximo %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "Enteros separados por comas" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "Fecha (sin hora)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Fecha (con hora)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Número decimal" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "Duración" + +msgid "Email address" +msgstr "Dirección de correo electrónico" + +msgid "File path" +msgstr "Ruta de archivo" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "Número de punto flotante" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "Entero" + +msgid "Big (8 byte) integer" +msgstr "Entero grande (8 bytes)" + +msgid "IPv4 address" +msgstr "Dirección IPv4" + +msgid "IP address" +msgstr "Dirección IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "Booleano (Verdadero, Falso o Nulo)" + +msgid "Positive big integer" +msgstr "" + +msgid "Positive integer" +msgstr "Entero positivo" + +msgid "Positive small integer" +msgstr "Entero positivo pequeño" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (hasta %(max_length)s)" + +msgid "Small integer" +msgstr "Entero pequeño" + +msgid "Text" +msgstr "Texto" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Hora" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Datos de binarios brutos" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "Archivo" + +msgid "Image" +msgstr "Imagen" + +msgid "A JSON object" +msgstr "" + +msgid "Value must be valid JSON." +msgstr "" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "la instancia del %(model)s con %(field)s %(value)r no existe." + +msgid "Foreign Key (type determined by related field)" +msgstr "Clave foránea (tipo determinado por el campo relacionado)" + +msgid "One-to-one relationship" +msgstr "Relación uno a uno" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "Relación %(from)s - %(to)s " + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "Relaciones %(from)s - %(to)s" + +msgid "Many-to-many relationship" +msgstr "Relación muchos a muchos" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Este campo es obligatorio." + +msgid "Enter a whole number." +msgstr "Introduzca un número completo." + +msgid "Enter a valid date." +msgstr "Introduzca una fecha válida." + +msgid "Enter a valid time." +msgstr "Introduzca una hora válida." + +msgid "Enter a valid date/time." +msgstr "Introduzca una hora y fecha válida." + +msgid "Enter a valid duration." +msgstr "Ingrese una duración válida." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" +"No se envió archivo alguno. Revise el tipo de codificación del formulario." + +msgid "No file was submitted." +msgstr "No se envió ningún archivo." + +msgid "The submitted file is empty." +msgstr "El archivo enviado está vacío." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Asegúrese de que este nombre de archivo tenga como máximo %(max)d carácter " +"(tiene %(length)d)." +msgstr[1] "" +"Asegúrese de que este nombre de archivo tenga como máximo %(max)d caracteres " +"(tiene %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Por favor provea un archivo o active el selector de limpiar, no ambos." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Envíe una imagen válida. El fichero que ha enviado no era una imagen o se " +"trataba de una imagen corrupta." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Escoja una opción válida. %(value)s no es una de las opciones disponibles." + +msgid "Enter a list of values." +msgstr "Ingrese una lista de valores." + +msgid "Enter a complete value." +msgstr "Ingrese un valor completo." + +msgid "Enter a valid UUID." +msgstr "Ingrese un UUID válido." + +msgid "Enter a valid JSON." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Campo oculto %(name)s) %(error)s" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "Los datos de ManagementForm faltan o han sido manipulados" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "Por favor, envíe %d o un menor número de formularios." +msgstr[1] "Por favor, envíe %d o un menor número de formularios." + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "Por favor, envíe %d o más formularios." +msgstr[1] "Por favor, envíe %d o más formularios." + +msgid "Order" +msgstr "Orden" + +msgid "Delete" +msgstr "Eliminar" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Por favor, corrija el dato duplicado para %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Por favor, corrija el dato duplicado para %(field)s, este debe ser único." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Por favor, corrija los datos duplicados para %(field_name)s este debe ser " +"único para %(lookup)s en %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Por favor, corrija los valores duplicados abajo." + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Escoja una opción válida. Esa opción no está entre las opciones disponibles." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Limpiar" + +msgid "Currently" +msgstr "Actualmente" + +msgid "Change" +msgstr "Cambiar" + +msgid "Unknown" +msgstr "Desconocido" + +msgid "Yes" +msgstr "Sí" + +msgid "No" +msgstr "No" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "sí,no,quizás" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d byte" +msgstr[1] "%(size)d bytes" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "medianoche" + +msgid "noon" +msgstr "mediodía" + +msgid "Monday" +msgstr "Lunes" + +msgid "Tuesday" +msgstr "Martes" + +msgid "Wednesday" +msgstr "Miércoles" + +msgid "Thursday" +msgstr "Jueves" + +msgid "Friday" +msgstr "Viernes" + +msgid "Saturday" +msgstr "Sábado" + +msgid "Sunday" +msgstr "Domingo" + +msgid "Mon" +msgstr "Lun" + +msgid "Tue" +msgstr "Mar" + +msgid "Wed" +msgstr "Mié" + +msgid "Thu" +msgstr "Jue" + +msgid "Fri" +msgstr "Vie" + +msgid "Sat" +msgstr "Sáb" + +msgid "Sun" +msgstr "Dom" + +msgid "January" +msgstr "Enero" + +msgid "February" +msgstr "Febrero" + +msgid "March" +msgstr "Marzo" + +msgid "April" +msgstr "Abril" + +msgid "May" +msgstr "Mayo" + +msgid "June" +msgstr "Junio" + +msgid "July" +msgstr "Julio" + +msgid "August" +msgstr "Agosto" + +msgid "September" +msgstr "Septiembre" + +msgid "October" +msgstr "Octubre" + +msgid "November" +msgstr "Noviembre" + +msgid "December" +msgstr "Diciembre" + +msgid "jan" +msgstr "ene" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "abr" + +msgid "may" +msgstr "may" + +msgid "jun" +msgstr "jun" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "ago" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "oct" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dic" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Ene." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Marzo" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Abril" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Mayo" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Junio" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Julio" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Ago." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Sep." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Oct." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dic." + +msgctxt "alt. month" +msgid "January" +msgstr "Enero" + +msgctxt "alt. month" +msgid "February" +msgstr "Febrero" + +msgctxt "alt. month" +msgid "March" +msgstr "Marzo" + +msgctxt "alt. month" +msgid "April" +msgstr "Abril" + +msgctxt "alt. month" +msgid "May" +msgstr "Mayo" + +msgctxt "alt. month" +msgid "June" +msgstr "Junio" + +msgctxt "alt. month" +msgid "July" +msgstr "Julio" + +msgctxt "alt. month" +msgid "August" +msgstr "Agosto" + +msgctxt "alt. month" +msgid "September" +msgstr "Septiembre" + +msgctxt "alt. month" +msgid "October" +msgstr "Octubre" + +msgctxt "alt. month" +msgid "November" +msgstr "Noviembre" + +msgctxt "alt. month" +msgid "December" +msgstr "Diciembre" + +msgid "This is not a valid IPv6 address." +msgstr "Esta no es una dirección IPv6 válida." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "o" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d año" +msgstr[1] "%d años" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d mes" +msgstr[1] "%d meses" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d semana" +msgstr[1] "%d semanas" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d día" +msgstr[1] "%d días" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d hora" +msgstr[1] "%d horas" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d minuto" +msgstr[1] "%d minutos" + +msgid "Forbidden" +msgstr "Prohibido" + +msgid "CSRF verification failed. Request aborted." +msgstr "Verificación CSRF fallida. Solicitud abortada." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Estás viendo este mensaje porqué esta web requiere una cookie CSRF cuando se " +"envían formularios. Esta cookie se necesita por razones de seguridad, para " +"asegurar que tu navegador no ha sido comprometido por terceras partes." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "Se puede ver más información si se establece DEBUG=True." + +msgid "No year specified" +msgstr "No se ha indicado el año" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "No se ha indicado el mes" + +msgid "No day specified" +msgstr "No se ha indicado el día" + +msgid "No week specified" +msgstr "No se ha indicado la semana" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "No %(verbose_name_plural)s disponibles" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Los futuros %(verbose_name_plural)s no están disponibles porque " +"%(class_name)s.allow_future es Falso." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "No se encontró ningún %(verbose_name)s coincidente con la consulta" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Página inválida (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Los índices de directorio no están permitidos." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Índice de %(directory)s" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/et/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/et/LC_MESSAGES/django.mo new file mode 100644 index 0000000..186a258 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/et/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/et/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/et/LC_MESSAGES/django.po new file mode 100644 index 0000000..ed0121e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/et/LC_MESSAGES/django.po @@ -0,0 +1,1334 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# eallik , 2011 +# Erlend , 2020 +# Jannis Leidel , 2011 +# Janno Liivak , 2013-2015 +# madisvain , 2011 +# Martin , 2014-2015,2021-2023 +# Martin , 2016-2017,2019-2020 +# Marti Raudsepp , 2014,2016 +# Ragnar Rebase , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Martin , 2014-2015,2021-2023\n" +"Language-Team: Estonian (http://app.transifex.com/django/django/language/" +"et/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: et\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "afrikaani" + +msgid "Arabic" +msgstr "araabia" + +msgid "Algerian Arabic" +msgstr "Alžeeria Araabia" + +msgid "Asturian" +msgstr "astuuria" + +msgid "Azerbaijani" +msgstr "aserbaidžaani" + +msgid "Bulgarian" +msgstr "bulgaaria" + +msgid "Belarusian" +msgstr "valgevene" + +msgid "Bengali" +msgstr "bengali" + +msgid "Breton" +msgstr "bretooni" + +msgid "Bosnian" +msgstr "bosnia" + +msgid "Catalan" +msgstr "katalaani" + +msgid "Central Kurdish (Sorani)" +msgstr "Keskkurdi keel (sorani)" + +msgid "Czech" +msgstr "tšehhi" + +msgid "Welsh" +msgstr "uelsi" + +msgid "Danish" +msgstr "taani" + +msgid "German" +msgstr "saksa" + +msgid "Lower Sorbian" +msgstr "alamsorbi" + +msgid "Greek" +msgstr "kreeka" + +msgid "English" +msgstr "inglise" + +msgid "Australian English" +msgstr "austraalia inglise" + +msgid "British English" +msgstr "briti inglise" + +msgid "Esperanto" +msgstr "esperanto" + +msgid "Spanish" +msgstr "hispaania" + +msgid "Argentinian Spanish" +msgstr "argentiina hispaani" + +msgid "Colombian Spanish" +msgstr "kolumbia hispaania" + +msgid "Mexican Spanish" +msgstr "mehhiko hispaania" + +msgid "Nicaraguan Spanish" +msgstr "nikaraagua hispaania" + +msgid "Venezuelan Spanish" +msgstr "venetsueela hispaania" + +msgid "Estonian" +msgstr "eesti" + +msgid "Basque" +msgstr "baski" + +msgid "Persian" +msgstr "pärsia" + +msgid "Finnish" +msgstr "soome" + +msgid "French" +msgstr "prantsuse" + +msgid "Frisian" +msgstr "friisi" + +msgid "Irish" +msgstr "iiri" + +msgid "Scottish Gaelic" +msgstr "šoti gaeli" + +msgid "Galician" +msgstr "galiitsia" + +msgid "Hebrew" +msgstr "heebrea" + +msgid "Hindi" +msgstr "hindi" + +msgid "Croatian" +msgstr "horvaatia" + +msgid "Upper Sorbian" +msgstr "ülemsorbi" + +msgid "Hungarian" +msgstr "ungari" + +msgid "Armenian" +msgstr "armeenia" + +msgid "Interlingua" +msgstr "interlingua" + +msgid "Indonesian" +msgstr "indoneesi" + +msgid "Igbo" +msgstr "ibo" + +msgid "Ido" +msgstr "ido" + +msgid "Icelandic" +msgstr "islandi" + +msgid "Italian" +msgstr "itaalia" + +msgid "Japanese" +msgstr "jaapani" + +msgid "Georgian" +msgstr "gruusia" + +msgid "Kabyle" +msgstr "Kabiili" + +msgid "Kazakh" +msgstr "kasahhi" + +msgid "Khmer" +msgstr "khmeri" + +msgid "Kannada" +msgstr "kannada" + +msgid "Korean" +msgstr "korea" + +msgid "Kyrgyz" +msgstr "kirgiisi" + +msgid "Luxembourgish" +msgstr "letseburgi" + +msgid "Lithuanian" +msgstr "leedu" + +msgid "Latvian" +msgstr "läti" + +msgid "Macedonian" +msgstr "makedoonia" + +msgid "Malayalam" +msgstr "malaia" + +msgid "Mongolian" +msgstr "mongoolia" + +msgid "Marathi" +msgstr "marathi" + +msgid "Malay" +msgstr "malai" + +msgid "Burmese" +msgstr "birma" + +msgid "Norwegian Bokmål" +msgstr "norra bokmål" + +msgid "Nepali" +msgstr "nepali" + +msgid "Dutch" +msgstr "hollandi" + +msgid "Norwegian Nynorsk" +msgstr "norra (nynorsk)" + +msgid "Ossetic" +msgstr "osseetia" + +msgid "Punjabi" +msgstr "pandžab" + +msgid "Polish" +msgstr "poola" + +msgid "Portuguese" +msgstr "portugali" + +msgid "Brazilian Portuguese" +msgstr "brasiilia portugali" + +msgid "Romanian" +msgstr "rumeenia" + +msgid "Russian" +msgstr "vene" + +msgid "Slovak" +msgstr "slovaki" + +msgid "Slovenian" +msgstr "sloveeni" + +msgid "Albanian" +msgstr "albaania" + +msgid "Serbian" +msgstr "serbia" + +msgid "Serbian Latin" +msgstr "serbia (ladina)" + +msgid "Swedish" +msgstr "rootsi" + +msgid "Swahili" +msgstr "suahiili" + +msgid "Tamil" +msgstr "tamiili" + +msgid "Telugu" +msgstr "telugu" + +msgid "Tajik" +msgstr "tadžiki" + +msgid "Thai" +msgstr "tai" + +msgid "Turkmen" +msgstr "türkmeeni" + +msgid "Turkish" +msgstr "türgi" + +msgid "Tatar" +msgstr "tatari" + +msgid "Udmurt" +msgstr "udmurdi" + +msgid "Uyghur" +msgstr "Uiguuri" + +msgid "Ukrainian" +msgstr "ukrania" + +msgid "Urdu" +msgstr "urdu" + +msgid "Uzbek" +msgstr "Usbeki" + +msgid "Vietnamese" +msgstr "vietnami" + +msgid "Simplified Chinese" +msgstr "lihtsustatud hiina" + +msgid "Traditional Chinese" +msgstr "traditsiooniline hiina" + +msgid "Messages" +msgstr "Sõnumid" + +msgid "Site Maps" +msgstr "Saidikaardid" + +msgid "Static Files" +msgstr "Staatilised failid" + +msgid "Syndication" +msgstr "Sündikeerimine" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "See lehe number ei ole täisarv" + +msgid "That page number is less than 1" +msgstr "See lehe number on väiksem kui 1" + +msgid "That page contains no results" +msgstr "See leht ei sisalda tulemusi" + +msgid "Enter a valid value." +msgstr "Sisestage korrektne väärtus." + +msgid "Enter a valid URL." +msgstr "Sisestage korrektne URL." + +msgid "Enter a valid integer." +msgstr "Sisestage korrektne täisarv." + +msgid "Enter a valid email address." +msgstr "Sisestage korrektne e-posti aadress." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Sisestage korrektne “nälk”, mis koosneb tähtedest, numbritest, " +"alakriipsudest või sidekriipsudest." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Sisestage korrektne “nälk”, mis koosneb Unicode tähtedest, numbritest, ala- " +"või sidekriipsudest." + +msgid "Enter a valid IPv4 address." +msgstr "Sisestage korrektne IPv4 aadress." + +msgid "Enter a valid IPv6 address." +msgstr "Sisestage korrektne IPv6 aadress." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Sisestage korrektne IPv4 või IPv6 aadress." + +msgid "Enter only digits separated by commas." +msgstr "Sisestage ainult komaga eraldatud numbreid." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Veendu, et see väärtus on %(limit_value)s (hetkel on %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Veendu, et see väärtus on väiksem või võrdne kui %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Veendu, et see väärtus on suurem või võrdne kui %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "Veendu, et see väärtus on arvu %(limit_value)s kordne." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Väärtuses peab olema vähemalt %(limit_value)d tähemärk (praegu on " +"%(show_value)d)." +msgstr[1] "" +"Väärtuses peab olema vähemalt %(limit_value)d tähemärki (praegu on " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Väärtuses võib olla kõige rohkem %(limit_value)d tähemärk (praegu on " +"%(show_value)d)." +msgstr[1] "" +"Väärtuses võib olla kõige rohkem %(limit_value)d tähemärki (praegu on " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Sisestage arv." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Veenduge, et kogu numbrikohtade arv ei oleks suurem kui %(max)s." +msgstr[1] "Veenduge, et kogu numbrikohtade arv ei oleks suurem kui %(max)s." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Veenduge, et komakohtade arv ei oleks suurem kui %(max)s." +msgstr[1] "Veenduge, et komakohtade arv ei oleks suurem kui %(max)s." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Veenduge, et komast vasakul olevaid numbreid ei oleks rohkem kui %(max)s." +msgstr[1] "" +"Veenduge, et komast vasakul olevaid numbreid ei oleks rohkem kui %(max)s." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Faililaiend “%(extension)s” pole lubatud. Lubatud laiendid on: " +"%(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Tühjad tähemärgid ei ole lubatud." + +msgid "and" +msgstr "ja" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s väljaga %(field_labels)s on juba olemas." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Kitsendust “%(name)s” on rikutud." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Väärtus %(value)r ei ole kehtiv valik." + +msgid "This field cannot be null." +msgstr "See lahter ei tohi olla tühi." + +msgid "This field cannot be blank." +msgstr "See väli ei saa olla tühi." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "Sellise %(field_label)s-väljaga %(model_name)s on juba olemas." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s peab olema unikaalne %(date_field_label)s %(lookup_type)s " +"suhtes." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Lahter tüüpi: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "“%(value)s” väärtus peab olema Tõene või Väär." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "“%(value)s” väärtus peab olema Tõene, Väär või Tühi." + +msgid "Boolean (Either True or False)" +msgstr "Tõeväärtus (Kas tõene või väär)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "String (kuni %(max_length)s märki)" + +msgid "String (unlimited)" +msgstr "String (piiramatu)" + +msgid "Comma-separated integers" +msgstr "Komaga eraldatud täisarvud" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"“%(value)s” väärtusel on vale kuupäevaformaat. See peab olema kujul AAAA-KK-" +"PP." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"“%(value)s” väärtusel on õige formaat (AAAA-KK-PP), kuid kuupäev on vale." + +msgid "Date (without time)" +msgstr "Kuupäev (kellaajata)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"“%(value)s” väärtusel on vale formaat. Peab olema formaadis AAAA-KK-PP HH:" +"MM[:ss[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"“%(value)s” väärtusel on õige formaat (AAAA-KK-PP HH:MM[:ss[.uuuuuu]][TZ]), " +"kuid kuupäev/kellaaeg on vale." + +msgid "Date (with time)" +msgstr "Kuupäev (kellaajaga)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "“%(value)s” väärtus peab olema kümnendarv." + +msgid "Decimal number" +msgstr "Kümnendmurd" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"“%(value)s” väärtusel on vale formaat. Peab olema formaadis [DD] " +"[[HH:]MM:]ss[.uuuuuu]." + +msgid "Duration" +msgstr "Kestus" + +msgid "Email address" +msgstr "E-posti aadress" + +msgid "File path" +msgstr "Faili asukoht" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "“%(value)s” väärtus peab olema ujukomaarv." + +msgid "Floating point number" +msgstr "Ujukomaarv" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "“%(value)s” väärtus peab olema täisarv." + +msgid "Integer" +msgstr "Täisarv" + +msgid "Big (8 byte) integer" +msgstr "Suur (8 baiti) täisarv" + +msgid "Small integer" +msgstr "Väike täisarv" + +msgid "IPv4 address" +msgstr "IPv4 aadress" + +msgid "IP address" +msgstr "IP aadress" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "“%(value)s” väärtus peab olema kas Tühi, Tõene või Väär." + +msgid "Boolean (Either True, False or None)" +msgstr "Tõeväärtus (Kas tõene, väär või tühi)" + +msgid "Positive big integer" +msgstr "Positiivne suur täisarv" + +msgid "Positive integer" +msgstr "Positiivne täisarv" + +msgid "Positive small integer" +msgstr "Positiivne väikene täisarv" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Nälk (kuni %(max_length)s märki)" + +msgid "Text" +msgstr "Tekst" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"“%(value)s” väärtusel on vale formaat. Peab olema formaadis HH:MM[:ss[." +"uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"“%(value)s” väärtusel on õige formaat (HH:MM[:ss[.uuuuuu]]), kuid kellaaeg " +"on vale." + +msgid "Time" +msgstr "Aeg" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Töötlemata binaarandmed" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "“%(value)s” ei ole korrektne UUID." + +msgid "Universally unique identifier" +msgstr "Universaalne unikaalne identifikaator" + +msgid "File" +msgstr "Fail" + +msgid "Image" +msgstr "Pilt" + +msgid "A JSON object" +msgstr "JSON objekt" + +msgid "Value must be valid JSON." +msgstr "Väärtus peab olema korrektne JSON." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(model)s isendit %(field)s %(value)r ei leidu." + +msgid "Foreign Key (type determined by related field)" +msgstr "Välisvõti (tüübi määrab seotud väli) " + +msgid "One-to-one relationship" +msgstr "Üks-ühele seos" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s seos" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s seosed" + +msgid "Many-to-many relationship" +msgstr "Mitu-mitmele seos" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "See lahter on nõutav." + +msgid "Enter a whole number." +msgstr "Sisestage täisarv." + +msgid "Enter a valid date." +msgstr "Sisestage korrektne kuupäev." + +msgid "Enter a valid time." +msgstr "Sisestage korrektne kellaaeg." + +msgid "Enter a valid date/time." +msgstr "Sisestage korrektne kuupäev ja kellaaeg." + +msgid "Enter a valid duration." +msgstr "Sisestage korrektne kestus." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Päevade arv peab jääma vahemikku {min_days} kuni {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Ühtegi faili ei saadetud. Kontrollige vormi kodeeringutüüpi." + +msgid "No file was submitted." +msgstr "Ühtegi faili ei saadetud." + +msgid "The submitted file is empty." +msgstr "Saadetud fail on tühi." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Veenduge, et faili nimes poleks rohkem kui %(max)d märk (praegu on " +"%(length)d)." +msgstr[1] "" +"Veenduge, et faili nimes poleks rohkem kui %(max)d märki (praegu on " +"%(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Palun laadige fail või märgistage 'tühjenda' kast, mitte mõlemat." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Laadige korrektne pilt. Fail, mille laadisite, ei olnud kas pilt või oli " +"fail vigane." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Valige korrektne väärtus. %(value)s ei ole valitav." + +msgid "Enter a list of values." +msgstr "Sisestage väärtuste nimekiri." + +msgid "Enter a complete value." +msgstr "Sisestage täielik väärtus." + +msgid "Enter a valid UUID." +msgstr "Sisestage korrektne UUID." + +msgid "Enter a valid JSON." +msgstr "Sisestage korrektne JSON." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Peidetud väli %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Palun kinnitage kõige rohkem %(num)d vormi." +msgstr[1] "Palun kinnitage kõige rohkem %(num)d vormi." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Palun kinnitage vähemalt %(num)d vormi." +msgstr[1] "Palun kinnitage vähemalt %(num)d vormi." + +msgid "Order" +msgstr "Järjestus" + +msgid "Delete" +msgstr "Kustuta" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Palun parandage duplikaat-andmed lahtris %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Palun parandage duplikaat-andmed lahtris %(field)s, mis peab olema unikaalne." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Palun parandage allolevad duplikaat-väärtused" + +msgid "The inline value did not match the parent instance." +msgstr "Pesastatud väärtus ei sobi ülemobjektiga." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Valige korrektne väärtus. Valitud väärtus ei ole valitav." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "“%(pk)s” ei ole korrektne väärtus." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s ei saanud tõlgendada ajavööndis %(current_timezone)s; see on " +"kas mitmetähenduslik või seda ei eksisteeri." + +msgid "Clear" +msgstr "Tühjenda" + +msgid "Currently" +msgstr "Hetkel" + +msgid "Change" +msgstr "Muuda" + +msgid "Unknown" +msgstr "Tundmatu" + +msgid "Yes" +msgstr "Jah" + +msgid "No" +msgstr "Ei" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "jah,ei,võib-olla" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d bait" +msgstr[1] "%(size)d baiti" + +#, python-format +msgid "%s KB" +msgstr "%s kB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.l." + +msgid "a.m." +msgstr "e.l." + +msgid "PM" +msgstr "PL" + +msgid "AM" +msgstr "EL" + +msgid "midnight" +msgstr "südaöö" + +msgid "noon" +msgstr "keskpäev" + +msgid "Monday" +msgstr "esmaspäev" + +msgid "Tuesday" +msgstr "teisipäev" + +msgid "Wednesday" +msgstr "kolmapäev" + +msgid "Thursday" +msgstr "neljapäev" + +msgid "Friday" +msgstr "reede" + +msgid "Saturday" +msgstr "laupäev" + +msgid "Sunday" +msgstr "pühapäev" + +msgid "Mon" +msgstr "esmasp." + +msgid "Tue" +msgstr "teisip." + +msgid "Wed" +msgstr "kolmap." + +msgid "Thu" +msgstr "neljap." + +msgid "Fri" +msgstr "reede" + +msgid "Sat" +msgstr "laup." + +msgid "Sun" +msgstr "pühap." + +msgid "January" +msgstr "jaanuar" + +msgid "February" +msgstr "veebruar" + +msgid "March" +msgstr "märts" + +msgid "April" +msgstr "aprill" + +msgid "May" +msgstr "mai" + +msgid "June" +msgstr "juuni" + +msgid "July" +msgstr "juuli" + +msgid "August" +msgstr "august" + +msgid "September" +msgstr "september" + +msgid "October" +msgstr "oktoober" + +msgid "November" +msgstr "november" + +msgid "December" +msgstr "detsember" + +msgid "jan" +msgstr "jaan" + +msgid "feb" +msgstr "veeb" + +msgid "mar" +msgstr "märts" + +msgid "apr" +msgstr "apr" + +msgid "may" +msgstr "mai" + +msgid "jun" +msgstr "jun" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "aug" + +msgid "sep" +msgstr "sept" + +msgid "oct" +msgstr "okt" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dets" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "jaan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "veeb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "mär." + +msgctxt "abbrev. month" +msgid "April" +msgstr "apr." + +msgctxt "abbrev. month" +msgid "May" +msgstr "mai" + +msgctxt "abbrev. month" +msgid "June" +msgstr "juuni" + +msgctxt "abbrev. month" +msgid "July" +msgstr "juuli" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "aug." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "sept." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "okt." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "dets." + +msgctxt "alt. month" +msgid "January" +msgstr "jaanuar" + +msgctxt "alt. month" +msgid "February" +msgstr "veebruar" + +msgctxt "alt. month" +msgid "March" +msgstr "märts" + +msgctxt "alt. month" +msgid "April" +msgstr "aprill" + +msgctxt "alt. month" +msgid "May" +msgstr "mai" + +msgctxt "alt. month" +msgid "June" +msgstr "juuni" + +msgctxt "alt. month" +msgid "July" +msgstr "juuli" + +msgctxt "alt. month" +msgid "August" +msgstr "august" + +msgctxt "alt. month" +msgid "September" +msgstr "september" + +msgctxt "alt. month" +msgid "October" +msgstr "oktoober" + +msgctxt "alt. month" +msgid "November" +msgstr "november" + +msgctxt "alt. month" +msgid "December" +msgstr "detsember" + +msgid "This is not a valid IPv6 address." +msgstr "See ei ole korrektne IPv6 aadress." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "või" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d aasta" +msgstr[1] "%(num)d aastat" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d kuu" +msgstr[1] "%(num)d kuud" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d nädal" +msgstr[1] "%(num)d nädalat" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d päev" +msgstr[1] "%(num)d päeva" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d tund" +msgstr[1] "%(num)d tundi" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minut" +msgstr[1] "%(num)d minutit" + +msgid "Forbidden" +msgstr "Keelatud" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF verifitseerimine ebaõnnestus. Päring katkestati." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Näete seda sõnumit, kuna käesolev HTTPS leht nõuab “Viitaja päise” saatmist " +"teie brauserile, kuid seda ei saadetud. Seda päist on vaja " +"turvakaalutlustel, kindlustamaks et teie brauserit ei ole kolmandate " +"osapoolte poolt üle võetud." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Kui olete oma brauseri seadistustes välja lülitanud “Viitaja” päised siis " +"lülitage need taas sisse vähemalt antud lehe jaoks või HTTPS üheduste jaoks " +"või “sama-allika” päringute jaoks." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Kui kasutate silti või " +"saadate päist “Referrer-Policy: no-referrer”, siis palun eemaldage need. " +"CSRF kaitse vajab range viitaja kontrolliks päist “Referer”. Kui privaatsus " +"on probleemiks, kasutage alternatiive nagu " +"linkidele, mis viivad kolmandate poolte lehtedele." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Näete seda teadet, kuna see leht vajab CSRF küpsist vormide postitamiseks. " +"Seda küpsist on vaja turvakaalutlustel, kindlustamaks et teie brauserit ei " +"ole kolmandate osapoolte poolt üle võetud." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Kui olete oma brauseris küpsised keelanud, siis palun lubage need vähemalt " +"selle lehe jaoks või “sama-allika” päringute jaoks." + +msgid "More information is available with DEBUG=True." +msgstr "Saadaval on rohkem infot kasutades DEBUG=True" + +msgid "No year specified" +msgstr "Aasta on valimata" + +msgid "Date out of range" +msgstr "Kuupäev vahemikust väljas" + +msgid "No month specified" +msgstr "Kuu on valimata" + +msgid "No day specified" +msgstr "Päev on valimata" + +msgid "No week specified" +msgstr "Nädal on valimata" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Ei leitud %(verbose_name_plural)s" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Tulevane %(verbose_name_plural)s pole saadaval, sest %(class_name)s." +"allow_future on False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Vigane kuupäeva sõne “%(datestr)s” lähtudes formaadist “%(format)s”" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Päringule vastavat %(verbose_name)s ei leitud" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Lehekülg pole “viimane” ja ei saa teda konvertida täisarvuks." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Vigane leht (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Tühi list ja “%(class_name)s.allow_empty” on Väär." + +msgid "Directory indexes are not allowed here." +msgstr "Kausta sisuloendid ei ole siin lubatud." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "“%(path)s” ei eksisteeri" + +#, python-format +msgid "Index of %(directory)s" +msgstr "%(directory)s sisuloend" + +msgid "The install worked successfully! Congratulations!" +msgstr "Paigaldamine õnnestus! Palju õnne!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Vaata release notes Djangole %(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Näete seda lehte, kuna teil on määratud DEBUG=True Django seadete failis ja te ei ole ühtki " +"URLi seadistanud." + +msgid "Django Documentation" +msgstr "Django dokumentatsioon" + +msgid "Topics, references, & how-to’s" +msgstr "Teemad, viited, & õpetused" + +msgid "Tutorial: A Polling App" +msgstr "Õpetus: Küsitlusrakendus" + +msgid "Get started with Django" +msgstr "Alusta Djangoga" + +msgid "Django Community" +msgstr "Django Kogukond" + +msgid "Connect, get help, or contribute" +msgstr "Suhelge, küsige abi või panustage" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/et/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/et/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/et/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/et/formats.py new file mode 100644 index 0000000..3b2d9ba --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/et/formats.py @@ -0,0 +1,21 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j. F Y" +TIME_FORMAT = "G:i" +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +MONTH_DAY_FORMAT = "j. F" +SHORT_DATE_FORMAT = "d.m.Y" +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = " " # Non-breaking space +# NUMBER_GROUPING = diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/eu/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/eu/LC_MESSAGES/django.mo new file mode 100644 index 0000000..572ea61 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/eu/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/eu/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/eu/LC_MESSAGES/django.po new file mode 100644 index 0000000..563aa69 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/eu/LC_MESSAGES/django.po @@ -0,0 +1,1290 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Aitzol Naberan , 2013,2016 +# Ander Martinez , 2013-2014 +# Eneko Illarramendi , 2017-2019,2021-2022 +# Jannis Leidel , 2011 +# jazpillaga , 2011 +# julen, 2011-2012 +# julen, 2013,2015 +# Mikel Maldonado , 2021 +# totorika93 , 2012 +# 67feb0cba3962a6c9f09eb0e43697461_528661a , 2013 +# Urtzi Odriozola , 2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-05-17 05:23-0500\n" +"PO-Revision-Date: 2022-07-25 06:49+0000\n" +"Last-Translator: Eneko Illarramendi \n" +"Language-Team: Basque (http://www.transifex.com/django/django/language/eu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Afrikaans" + +msgid "Arabic" +msgstr "Arabiera" + +msgid "Algerian Arabic" +msgstr "Algeriar Arabiera" + +msgid "Asturian" +msgstr "Asturiera" + +msgid "Azerbaijani" +msgstr "Azerbaijanera" + +msgid "Bulgarian" +msgstr "Bulgariera" + +msgid "Belarusian" +msgstr "Bielorrusiera" + +msgid "Bengali" +msgstr "Bengalera" + +msgid "Breton" +msgstr "Bretoia" + +msgid "Bosnian" +msgstr "Bosniera" + +msgid "Catalan" +msgstr "Katalana" + +msgid "Czech" +msgstr "Txekiera" + +msgid "Welsh" +msgstr "Galesa" + +msgid "Danish" +msgstr "Daniera" + +msgid "German" +msgstr "Alemana" + +msgid "Lower Sorbian" +msgstr "Behe-sorbiera" + +msgid "Greek" +msgstr "Greziera" + +msgid "English" +msgstr "Ingelesa" + +msgid "Australian English" +msgstr "Australiar ingelesa" + +msgid "British English" +msgstr "Ingelesa" + +msgid "Esperanto" +msgstr "Esperantoa" + +msgid "Spanish" +msgstr "Gaztelania" + +msgid "Argentinian Spanish" +msgstr "Gaztelania (Argentina)" + +msgid "Colombian Spanish" +msgstr "Gaztelania (Kolonbia)" + +msgid "Mexican Spanish" +msgstr "Gaztelania (Mexiko)" + +msgid "Nicaraguan Spanish" +msgstr "Gaztelania (Nikaragua)" + +msgid "Venezuelan Spanish" +msgstr "Gaztelania (Venezuela)" + +msgid "Estonian" +msgstr "Estoniera" + +msgid "Basque" +msgstr "Euskara" + +msgid "Persian" +msgstr "Persiera" + +msgid "Finnish" +msgstr "Finlandiera" + +msgid "French" +msgstr "Frantsesa" + +msgid "Frisian" +msgstr "Frisiera" + +msgid "Irish" +msgstr "Irlandako gaelikoa" + +msgid "Scottish Gaelic" +msgstr "Eskoziako gaelikoa" + +msgid "Galician" +msgstr "Galiziera" + +msgid "Hebrew" +msgstr "Hebreera" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Kroaziera" + +msgid "Upper Sorbian" +msgstr "Goi-sorbiera" + +msgid "Hungarian" +msgstr "Hungariera" + +msgid "Armenian" +msgstr "Armeniera" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonesiera" + +msgid "Igbo" +msgstr "" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Islandiera" + +msgid "Italian" +msgstr "Italiera" + +msgid "Japanese" +msgstr "Japoniera" + +msgid "Georgian" +msgstr "Georgiera" + +msgid "Kabyle" +msgstr "Kabylera" + +msgid "Kazakh" +msgstr "Kazakhera" + +msgid "Khmer" +msgstr "Khmerera" + +msgid "Kannada" +msgstr "Kannada" + +msgid "Korean" +msgstr "Koreera" + +msgid "Kyrgyz" +msgstr "" + +msgid "Luxembourgish" +msgstr "Luxenburgera" + +msgid "Lithuanian" +msgstr "Lituaniera" + +msgid "Latvian" +msgstr "Letoniera" + +msgid "Macedonian" +msgstr "Mazedoniera" + +msgid "Malayalam" +msgstr "Malabarera" + +msgid "Mongolian" +msgstr "Mongoliera" + +msgid "Marathi" +msgstr "Marathera" + +msgid "Malay" +msgstr "" + +msgid "Burmese" +msgstr "Birmaniera" + +msgid "Norwegian Bokmål" +msgstr "Bokmåla (Norvegia)" + +msgid "Nepali" +msgstr "Nepalera" + +msgid "Dutch" +msgstr "Nederlandera" + +msgid "Norwegian Nynorsk" +msgstr "Nynorsk (Norvegia)" + +msgid "Ossetic" +msgstr "Osetiera" + +msgid "Punjabi" +msgstr "Punjabera" + +msgid "Polish" +msgstr "Poloniera" + +msgid "Portuguese" +msgstr "Portugesa" + +msgid "Brazilian Portuguese" +msgstr "Portugesa (Brazil)" + +msgid "Romanian" +msgstr "Errumaniera" + +msgid "Russian" +msgstr "Errusiera" + +msgid "Slovak" +msgstr "Eslovakiera" + +msgid "Slovenian" +msgstr "Esloveniera" + +msgid "Albanian" +msgstr "Albaniera" + +msgid "Serbian" +msgstr "Serbiera" + +msgid "Serbian Latin" +msgstr "Serbiera" + +msgid "Swedish" +msgstr "Suediera" + +msgid "Swahili" +msgstr "Swahilia" + +msgid "Tamil" +msgstr "Tamilera" + +msgid "Telugu" +msgstr "Telugua" + +msgid "Tajik" +msgstr "" + +msgid "Thai" +msgstr "Thailandiera" + +msgid "Turkmen" +msgstr "" + +msgid "Turkish" +msgstr "Turkiera" + +msgid "Tatar" +msgstr "Tatarera" + +msgid "Udmurt" +msgstr "Udmurtera" + +msgid "Ukrainian" +msgstr "Ukrainera" + +msgid "Urdu" +msgstr "Urdua" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "Vietnamera" + +msgid "Simplified Chinese" +msgstr "Txinera (sinpletua)" + +msgid "Traditional Chinese" +msgstr "Txinera (tradizionala)" + +msgid "Messages" +msgstr "Mezuak" + +msgid "Site Maps" +msgstr "Sitemap-ak" + +msgid "Static Files" +msgstr "Fitxategi estatikoak" + +msgid "Syndication" +msgstr "Sindikazioa" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "..." + +msgid "That page number is not an integer" +msgstr "Orrialde hori ez da zenbaki bat" + +msgid "That page number is less than 1" +msgstr "Orrialde zenbaki hori 1 baino txikiagoa da" + +msgid "That page contains no results" +msgstr "Orrialde horrek ez du emaitzarik" + +msgid "Enter a valid value." +msgstr "Idatzi baleko balio bat." + +msgid "Enter a valid URL." +msgstr "Idatzi baleko URL bat." + +msgid "Enter a valid integer." +msgstr "Idatzi baleko zenbaki bat." + +msgid "Enter a valid email address." +msgstr "Idatzi baleko helbide elektroniko bat." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Idatzi baleko IPv4 sare-helbide bat." + +msgid "Enter a valid IPv6 address." +msgstr "Idatzi baleko IPv6 sare-helbide bat." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Idatzi baleko IPv4 edo IPv6 sare-helbide bat." + +msgid "Enter only digits separated by commas." +msgstr "Idatzi komaz bereizitako digitoak soilik." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Ziurtatu balio hau gutxienez %(limit_value)s dela (orain %(show_value)s da)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Ziurtatu balio hau %(limit_value)s baino txikiagoa edo berdina dela." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Ziurtatu balio hau %(limit_value)s baino handiagoa edo berdina dela." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Ziurtatu balio honek gutxienez karaktere %(limit_value)d duela " +"(%(show_value)d ditu)." +msgstr[1] "" +"Ziurtatu balio honek gutxienez %(limit_value)d karaktere dituela " +"(%(show_value)d ditu)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Ziurtatu balio honek gehienez karaktere %(limit_value)d duela " +"(%(show_value)d ditu)." +msgstr[1] "" +"Ziurtatu balio honek gehienez %(limit_value)d karaktere dituela " +"(%(show_value)d ditu)." + +msgid "Enter a number." +msgstr "Idatzi zenbaki bat." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Ziurtatu digitu %(max)s baino gehiago ez dagoela guztira." +msgstr[1] "Ziurtatu %(max)s digitu baino gehiago ez dagoela guztira." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Ziurtatu ez dagoela digitu %(max)s baino gehiago komaren atzetik." +msgstr[1] "Ziurtatu ez dagoela %(max)s digitu baino gehiago komaren atzetik." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "Ziurtatu ez dagoela digitu %(max)s baino gehiago komaren aurretik." +msgstr[1] "Ziurtatu ez dagoela %(max)s digitu baino gehiago komaren aurretik." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "Null karaktereak ez daude baimenduta." + +msgid "and" +msgstr "eta" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(field_labels)s hauek dauzkan %(model_name)s dagoeneko existitzen da." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "%(value)r balioa ez da baleko aukera bat." + +msgid "This field cannot be null." +msgstr "Eremu hau ezin daiteke hutsa izan (null)." + +msgid "This field cannot be blank." +msgstr "Eremu honek ezin du hutsik egon." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(field_label)s hori daukan %(model_name)s dagoeneko existitzen da." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Eremuaren mota: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "\"%(value)s\" blioa True edo False izan behar da." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "\"%(value)s\" balioa, True, False edo None izan behar da." + +msgid "Boolean (Either True or False)" +msgstr "Boolearra (True edo False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "String-a (%(max_length)s gehienez)" + +msgid "Comma-separated integers" +msgstr "Komaz bereiztutako zenbaki osoak" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"\"%(value)s\" balioa data formatu okerra dauka. UUUU-HH-EE formatua izan " +"behar da." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"\"%(value)s\" balioa formatu egokia dauka (UUUU-HH-EE), baina data okerra." + +msgid "Date (without time)" +msgstr "Data (ordurik gabe)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Data (orduarekin)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "\"%(value)s\" balioa zenbaki hamartarra izan behar da." + +msgid "Decimal number" +msgstr "Zenbaki hamartarra" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"\"%(value)s\" balioa formatu okerra dauka. [EE][[OO:]MM:]ss[.uuuuuu] " +"formatua izan behar du." + +msgid "Duration" +msgstr "Iraupena" + +msgid "Email address" +msgstr "Helbide elektronikoa" + +msgid "File path" +msgstr "Fitxategiaren bidea" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "\"%(value)s\" float izan behar da." + +msgid "Floating point number" +msgstr "Koma higikorreko zenbakia (float)" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "\"%(value)s\" zenbaki osoa izan behar da." + +msgid "Integer" +msgstr "Zenbaki osoa" + +msgid "Big (8 byte) integer" +msgstr "Zenbaki osoa (handia 8 byte)" + +msgid "Small integer" +msgstr "Osoko txikia" + +msgid "IPv4 address" +msgstr "IPv4 sare-helbidea" + +msgid "IP address" +msgstr "IP helbidea" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "\"%(value)s\" None, True edo False izan behar da." + +msgid "Boolean (Either True, False or None)" +msgstr "Boolearra (True, False edo None)" + +msgid "Positive big integer" +msgstr "Zenbaki positivo osoa-handia" + +msgid "Positive integer" +msgstr "Osoko positiboa" + +msgid "Positive small integer" +msgstr "Osoko positibo txikia" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (gehienez %(max_length)s)" + +msgid "Text" +msgstr "Testua" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Ordua" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Datu bitar gordinak" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "\"Universally unique identifier\"" + +msgid "File" +msgstr "Fitxategia" + +msgid "Image" +msgstr "Irudia" + +msgid "A JSON object" +msgstr "JSON objektu bat" + +msgid "Value must be valid JSON." +msgstr "Balioa baliozko JSON bat izan behar da." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" +"%(field)s %(value)r edukidun %(model)s modeloko instantziarik ez da " +"exiistitzen." + +msgid "Foreign Key (type determined by related field)" +msgstr "1-N (mota erlazionatutako eremuaren arabera)" + +msgid "One-to-one relationship" +msgstr "Bat-bat erlazioa" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s erlazioa" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s erlazioak" + +msgid "Many-to-many relationship" +msgstr "M:N erlazioa" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Eremu hau beharrezkoa da." + +msgid "Enter a whole number." +msgstr "Idatzi zenbaki oso bat." + +msgid "Enter a valid date." +msgstr "Idatzi baleko data bat." + +msgid "Enter a valid time." +msgstr "Idatzi baleko ordu bat." + +msgid "Enter a valid date/time." +msgstr "Idatzi baleko data/ordu bat." + +msgid "Enter a valid duration." +msgstr "Idatzi baleko iraupen bat." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Egun kopuruak {min_days} eta {max_days} artean egon behar du." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Ez da fitxategirik bidali. Egiaztatu formularioaren kodeketa-mota." + +msgid "No file was submitted." +msgstr "Ez da fitxategirik bidali." + +msgid "The submitted file is empty." +msgstr "Bidalitako fitxategia hutsik dago." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Ziurtatu fitxategi izen honek gehienez karaktere %(max)d duela (%(length)d " +"ditu)." +msgstr[1] "" +"Ziurtatu fitxategi izen honek gehienez %(max)d karaktere dituela (%(length)d " +"ditu)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Mesedez, igo fitxategi bat edo egin klik garbitu botoian, ez biak." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Igo baleko irudi bat. Zuk igotako fitxategia ez da irudi bat edo akatsen bat " +"du." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Hautatu baleko aukera bat. %(value)s ez dago erabilgarri." + +msgid "Enter a list of values." +msgstr "Idatzi balio-zerrenda bat." + +msgid "Enter a complete value." +msgstr "Sartu balio osoa." + +msgid "Enter a valid UUID." +msgstr "Idatzi baleko UUID bat." + +msgid "Enter a valid JSON." +msgstr "Sartu baliozko JSON bat" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(%(name)s eremu ezkutua) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "Ordena" + +msgid "Delete" +msgstr "Ezabatu" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Zuzendu bikoiztketa %(field)s eremuan." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Zuzendu bikoizketa %(field)s eremuan. Bakarra izan behar da." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Zuzendu bakarra izan behar den%(field_name)s eremuarentzako bikoiztutako " +"data %(lookup)s egiteko %(date_field)s eremuan" + +msgid "Please correct the duplicate values below." +msgstr "Zuzendu hurrengo balio bikoiztuak." + +msgid "The inline value did not match the parent instance." +msgstr "Barneko balioa eta gurasoaren instantzia ez datoz bat." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Hautatu aukera zuzen bat. Hautatutakoa ez da zuzena." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Garbitu" + +msgid "Currently" +msgstr "Orain" + +msgid "Change" +msgstr "Aldatu" + +msgid "Unknown" +msgstr "Ezezaguna" + +msgid "Yes" +msgstr "Bai" + +msgid "No" +msgstr "Ez" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "bai,ez,agian" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "byte %(size)d " +msgstr[1] "%(size)d byte" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "gauerdia" + +msgid "noon" +msgstr "eguerdia" + +msgid "Monday" +msgstr "astelehena" + +msgid "Tuesday" +msgstr "asteartea" + +msgid "Wednesday" +msgstr "asteazkena" + +msgid "Thursday" +msgstr "osteguna" + +msgid "Friday" +msgstr "ostirala" + +msgid "Saturday" +msgstr "larunbata" + +msgid "Sunday" +msgstr "igandea" + +msgid "Mon" +msgstr "al" + +msgid "Tue" +msgstr "ar" + +msgid "Wed" +msgstr "az" + +msgid "Thu" +msgstr "og" + +msgid "Fri" +msgstr "ol" + +msgid "Sat" +msgstr "lr" + +msgid "Sun" +msgstr "ig" + +msgid "January" +msgstr "urtarrila" + +msgid "February" +msgstr "otsaila" + +msgid "March" +msgstr "martxoa" + +msgid "April" +msgstr "apirila" + +msgid "May" +msgstr "maiatza" + +msgid "June" +msgstr "ekaina" + +msgid "July" +msgstr "uztaila" + +msgid "August" +msgstr "abuztua" + +msgid "September" +msgstr "iraila" + +msgid "October" +msgstr "urria" + +msgid "November" +msgstr "azaroa" + +msgid "December" +msgstr "abendua" + +msgid "jan" +msgstr "urt" + +msgid "feb" +msgstr "ots" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "api" + +msgid "may" +msgstr "mai" + +msgid "jun" +msgstr "eka" + +msgid "jul" +msgstr "uzt" + +msgid "aug" +msgstr "abu" + +msgid "sep" +msgstr "ira" + +msgid "oct" +msgstr "urr" + +msgid "nov" +msgstr "aza" + +msgid "dec" +msgstr "abe" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "urt." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "ots." + +msgctxt "abbrev. month" +msgid "March" +msgstr "mar." + +msgctxt "abbrev. month" +msgid "April" +msgstr "api." + +msgctxt "abbrev. month" +msgid "May" +msgstr "mai." + +msgctxt "abbrev. month" +msgid "June" +msgstr "eka." + +msgctxt "abbrev. month" +msgid "July" +msgstr "uzt." + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "abu." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "ira." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "urr." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "aza." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "abe." + +msgctxt "alt. month" +msgid "January" +msgstr "urtarrila" + +msgctxt "alt. month" +msgid "February" +msgstr "otsaila" + +msgctxt "alt. month" +msgid "March" +msgstr "martxoa" + +msgctxt "alt. month" +msgid "April" +msgstr "apirila" + +msgctxt "alt. month" +msgid "May" +msgstr "maiatza" + +msgctxt "alt. month" +msgid "June" +msgstr "ekaina" + +msgctxt "alt. month" +msgid "July" +msgstr "uztaila" + +msgctxt "alt. month" +msgid "August" +msgstr "abuztua" + +msgctxt "alt. month" +msgid "September" +msgstr "iraila" + +msgctxt "alt. month" +msgid "October" +msgstr "urria" + +msgctxt "alt. month" +msgid "November" +msgstr "azaroa" + +msgctxt "alt. month" +msgid "December" +msgstr "abendua" + +msgid "This is not a valid IPv6 address." +msgstr "Hau ez da baleko IPv6 helbide bat." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "edo" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "urte %(num)d" +msgstr[1] "%(num)d urte" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "hilabete %(num)d" +msgstr[1] "%(num)d hilabete" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "aste %(num)d" +msgstr[1] "%(num)d aste" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "egun %(num)d" +msgstr[1] "%(num)d egun" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "ordu %(num)d" +msgstr[1] "%(num)d ordu" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "minutu %(num)d" +msgstr[1] "%(num)d minutu" + +msgid "Forbidden" +msgstr "Debekatuta" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF egiaztapenak huts egin du. Eskaera abortatu da." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Formularioa bidaltzean gune honek CSRF cookie bat behar duelako ikusten duzu " +"mezu hau. Cookie hau beharrezkoa da segurtasun arrazoiengatik, zure " +"nabigatzailea beste batek ordezkatzen ez duela ziurtatzeko." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "Informazio gehiago erabilgarri dago DEBUG=True ezarrita." + +msgid "No year specified" +msgstr "Ez da urterik zehaztu" + +msgid "Date out of range" +msgstr "Data baliozko tartetik kanpo" + +msgid "No month specified" +msgstr "Ez da hilabeterik zehaztu" + +msgid "No day specified" +msgstr "Ez da egunik zehaztu" + +msgid "No week specified" +msgstr "Ez da asterik zehaztu" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Ez dago %(verbose_name_plural)s" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Etorkizuneko %(verbose_name_plural)s ez dago aukeran %(class_name)s." +"allow_future False delako" + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Bilaketarekin bat datorren %(verbose_name)s-rik ez dago" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Orri baliogabea (%(page_number)s):%(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Direktorio zerrendak ez daude baimenduak." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "%(directory)s zerrenda" + +msgid "The install worked successfully! Congratulations!" +msgstr "Instalazioak arrakastaz funtzionatu du! Zorionak!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Ikusi Django %(version)s-ren argitaratze " +"oharrak" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" +"Zure settings fitxategian DEBUG=True jarrita eta URLrik konfiguratu gabe duzulako ari zara " +"ikusten orrialde hau." + +msgid "Django Documentation" +msgstr "Django dokumentazioa" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "Tutoriala: Galdetegi aplikazioa" + +msgid "Get started with Django" +msgstr "Hasi Djangorekin" + +msgid "Django Community" +msgstr "Django Komunitatea" + +msgid "Connect, get help, or contribute" +msgstr "Konektatu, lortu laguntza edo lagundu" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/eu/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/eu/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/eu/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/eu/formats.py new file mode 100644 index 0000000..61b16fb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/eu/formats.py @@ -0,0 +1,21 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = r"Y\k\o N j\a" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = r"Y\k\o N j\a, H:i" +YEAR_MONTH_FORMAT = r"Y\k\o F" +MONTH_DAY_FORMAT = r"F\r\e\n j\a" +SHORT_DATE_FORMAT = "Y-m-d" +SHORT_DATETIME_FORMAT = "Y-m-d H:i" +FIRST_DAY_OF_WEEK = 1 # Astelehena + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fa/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fa/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c131325 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fa/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fa/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fa/LC_MESSAGES/django.po new file mode 100644 index 0000000..440cf8e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fa/LC_MESSAGES/django.po @@ -0,0 +1,1343 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ahmad Hosseini , 2020 +# alirezamastery , 2021 +# ali salehi, 2023 +# Ali Vakilzade , 2015 +# Arash Fazeli , 2012 +# Eric Hamiter , 2019 +# Eshagh , 2022 +# Farshad Asadpour, 2021 +# Jannis Leidel , 2011 +# Mariusz Felisiak , 2021 +# Mazdak Badakhshan , 2014 +# Milad Hazrati , 2019 +# MJafar Mashhadi , 2018 +# Mohammad Hossein Mojtahedi , 2013,2019 +# Pouya Abbassi, 2016 +# Pouya Abbassi, 2016 +# rahim agh , 2020-2021 +# Reza Mohammadi , 2013-2016 +# Saeed , 2011 +# Sina Cheraghi , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: ali salehi, 2023\n" +"Language-Team: Persian (http://app.transifex.com/django/django/language/" +"fa/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fa\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Afrikaans" +msgstr "آفریکانس" + +msgid "Arabic" +msgstr "عربی" + +msgid "Algerian Arabic" +msgstr "عربی الجزایری" + +msgid "Asturian" +msgstr "آستوری" + +msgid "Azerbaijani" +msgstr "آذربایجانی" + +msgid "Bulgarian" +msgstr "بلغاری" + +msgid "Belarusian" +msgstr "بلاروس" + +msgid "Bengali" +msgstr "بنگالی" + +msgid "Breton" +msgstr "برتون" + +msgid "Bosnian" +msgstr "بوسنیایی" + +msgid "Catalan" +msgstr "کاتالونیایی" + +msgid "Central Kurdish (Sorani)" +msgstr "" + +msgid "Czech" +msgstr "چکی" + +msgid "Welsh" +msgstr "ویلزی" + +msgid "Danish" +msgstr "دانمارکی" + +msgid "German" +msgstr "آلمانی" + +msgid "Lower Sorbian" +msgstr "صربستانی پایین" + +msgid "Greek" +msgstr "یونانی" + +msgid "English" +msgstr "انگلیسی" + +msgid "Australian English" +msgstr "انگلیسی استرالیایی" + +msgid "British English" +msgstr "انگلیسی بریتیش" + +msgid "Esperanto" +msgstr "اسپرانتو" + +msgid "Spanish" +msgstr "اسپانیایی" + +msgid "Argentinian Spanish" +msgstr "اسپانیایی آرژانتینی" + +msgid "Colombian Spanish" +msgstr "اسپانیایی کلمبیایی" + +msgid "Mexican Spanish" +msgstr "اسپانیولی مکزیکی" + +msgid "Nicaraguan Spanish" +msgstr "نیکاراگوئه اسپانیایی" + +msgid "Venezuelan Spanish" +msgstr "ونزوئلا اسپانیایی" + +msgid "Estonian" +msgstr "استونی" + +msgid "Basque" +msgstr "باسکی" + +msgid "Persian" +msgstr "فارسی" + +msgid "Finnish" +msgstr "فنلاندی" + +msgid "French" +msgstr "فرانسوی" + +msgid "Frisian" +msgstr "فریزی" + +msgid "Irish" +msgstr "ایرلندی" + +msgid "Scottish Gaelic" +msgstr "گیلیک اسکاتلندی" + +msgid "Galician" +msgstr "گالیسیایی" + +msgid "Hebrew" +msgstr "عبری" + +msgid "Hindi" +msgstr "هندی" + +msgid "Croatian" +msgstr "کرواتی" + +msgid "Upper Sorbian" +msgstr "صربستانی بالا" + +msgid "Hungarian" +msgstr "مجاری" + +msgid "Armenian" +msgstr "ارمنی" + +msgid "Interlingua" +msgstr "اینترلینگوا" + +msgid "Indonesian" +msgstr "اندونزیایی" + +msgid "Igbo" +msgstr "ایگبو" + +msgid "Ido" +msgstr "ایدو" + +msgid "Icelandic" +msgstr "ایسلندی" + +msgid "Italian" +msgstr "ایتالیایی" + +msgid "Japanese" +msgstr "ژاپنی" + +msgid "Georgian" +msgstr "گرجی" + +msgid "Kabyle" +msgstr "قبایلی" + +msgid "Kazakh" +msgstr "قزاقستان" + +msgid "Khmer" +msgstr "خمری" + +msgid "Kannada" +msgstr "کناده‌ای" + +msgid "Korean" +msgstr "کره‌ای" + +msgid "Kyrgyz" +msgstr "قرقیزی" + +msgid "Luxembourgish" +msgstr "لوگزامبورگی" + +msgid "Lithuanian" +msgstr "لیتوانی" + +msgid "Latvian" +msgstr "لتونیایی" + +msgid "Macedonian" +msgstr "مقدونی" + +msgid "Malayalam" +msgstr "مالایایی" + +msgid "Mongolian" +msgstr "مغولی" + +msgid "Marathi" +msgstr "مِراتی" + +msgid "Malay" +msgstr "Malay" + +msgid "Burmese" +msgstr "برمه‌ای" + +msgid "Norwegian Bokmål" +msgstr "نروژی" + +msgid "Nepali" +msgstr "نپالی" + +msgid "Dutch" +msgstr "هلندی" + +msgid "Norwegian Nynorsk" +msgstr "نروژی Nynorsk" + +msgid "Ossetic" +msgstr "آسی" + +msgid "Punjabi" +msgstr "پنجابی" + +msgid "Polish" +msgstr "لهستانی" + +msgid "Portuguese" +msgstr "پرتغالی" + +msgid "Brazilian Portuguese" +msgstr "پرتغالیِ برزیل" + +msgid "Romanian" +msgstr "رومانی" + +msgid "Russian" +msgstr "روسی" + +msgid "Slovak" +msgstr "اسلواکی" + +msgid "Slovenian" +msgstr "اسلووِنی" + +msgid "Albanian" +msgstr "آلبانیایی" + +msgid "Serbian" +msgstr "صربی" + +msgid "Serbian Latin" +msgstr "صربی لاتین" + +msgid "Swedish" +msgstr "سوئدی" + +msgid "Swahili" +msgstr "سواحیلی" + +msgid "Tamil" +msgstr "تامیلی" + +msgid "Telugu" +msgstr "تلوگویی" + +msgid "Tajik" +msgstr "تاجیک" + +msgid "Thai" +msgstr "تایلندی" + +msgid "Turkmen" +msgstr "ترکمن" + +msgid "Turkish" +msgstr "ترکی" + +msgid "Tatar" +msgstr "تاتار" + +msgid "Udmurt" +msgstr "ادمورت" + +msgid "Uyghur" +msgstr "" + +msgid "Ukrainian" +msgstr "اکراینی" + +msgid "Urdu" +msgstr "اردو" + +msgid "Uzbek" +msgstr "ازبکی" + +msgid "Vietnamese" +msgstr "ویتنامی" + +msgid "Simplified Chinese" +msgstr "چینی ساده‌شده" + +msgid "Traditional Chinese" +msgstr "چینی سنتی" + +msgid "Messages" +msgstr "پیغام‌ها" + +msgid "Site Maps" +msgstr "نقشه‌های وب‌گاه" + +msgid "Static Files" +msgstr "پرونده‌های استاتیک" + +msgid "Syndication" +msgstr "پیوند" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "شمارهٔ صفحه یک عدد طبیعی نیست" + +msgid "That page number is less than 1" +msgstr "شمارهٔ صفحه کوچکتر از ۱ است" + +msgid "That page contains no results" +msgstr "این صفحه خالی از اطلاعات است" + +msgid "Enter a valid value." +msgstr "یک مقدار معتبر وارد کنید." + +msgid "Enter a valid URL." +msgstr "یک نشانی اینترنتی معتبر وارد کنید." + +msgid "Enter a valid integer." +msgstr "یک عدد معتبر وارد کنید." + +msgid "Enter a valid email address." +msgstr "یک ایمیل آدرس معتبر وارد کنید." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"یک \"اسلاگ\" معتبر متشکل از حروف، اعداد، خط زیر یا خط فاصله، وارد کنید. " + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"یک \"اسلاگ\" معتبر وارد کنید که شامل حروف یونیکد، اعداد، خط زیر یا خط فاصله " +"باشد." + +msgid "Enter a valid IPv4 address." +msgstr "یک نشانی IPv4 معتبر وارد کنید." + +msgid "Enter a valid IPv6 address." +msgstr "یک آدرس معتبر IPv6 وارد کنید." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "IPv4 یا IPv6 آدرس معتبر وارد کنید." + +msgid "Enter only digits separated by commas." +msgstr "فقط ارقام جدا شده با کاما وارد کنید." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "مطمئن شوید مقدار %(limit_value)s است. (اکنون %(show_value)s می باشد)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "مطمئن شوید این مقدار کوچکتر و یا مساوی %(limit_value)s است." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "مطمئن شوید این مقدار بزرگتر و یا مساوی %(limit_value)s است." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"طول این مقدار باید حداقل %(limit_value)d کاراکتر باشد (طولش %(show_value)d " +"است)." +msgstr[1] "" +"طول این مقدار باید حداقل %(limit_value)d کاراکتر باشد (طولش %(show_value)d " +"است)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"طول این مقدار باید حداکثر %(limit_value)d کاراکتر باشد (طولش %(show_value)d " +"است)." +msgstr[1] "" +"طول این مقدار باید حداکثر %(limit_value)d کاراکتر باشد (طولش %(show_value)d " +"است)." + +msgid "Enter a number." +msgstr "یک عدد وارد کنید." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "نباید در مجموع بیش از %(max)s رقم داشته باشد." +msgstr[1] "نباید در مجموع بیش از %(max)s رقم داشته باشد." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "نباید بیش از %(max)s رقم اعشار داشته باشد." +msgstr[1] "نباید بیش از %(max)s رقم اعشار داشته باشد." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "نباید بیش از %(max)s رقم قبل ممیز داشته باشد." +msgstr[1] "نباید بیش از %(max)s رقم قبل ممیز داشته باشد." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"استفاده از پرونده با پسوند '%(extension)s' مجاز نیست. پسوند‌های مجاز عبارتند " +"از: '%(allowed_extensions)s'" + +msgid "Null characters are not allowed." +msgstr "کاراکترهای تهی مجاز نیستند." + +msgid "and" +msgstr "و" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "‏%(model_name)s با این %(field_labels)s وجود دارد." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "مقدار %(value)r انتخاب معتبری نیست. " + +msgid "This field cannot be null." +msgstr "این فیلد نمی تواند پوچ باشد." + +msgid "This field cannot be blank." +msgstr "این فیلد نمی تواند خالی باشد." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s با این %(field_label)s از قبل موجود است." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"‏%(field_label)s باید برای %(lookup_type)s %(date_field_label)s یکتا باشد." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "فیلد با نوع: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "مقدار «%(value)s» باید True یا False باشد." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "مقدار «%(value)s» باید True یا False یا None باشد." + +msgid "Boolean (Either True or False)" +msgstr "بولی (درست یا غلط)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "رشته (تا %(max_length)s)" + +msgid "String (unlimited)" +msgstr "رشته (بی نهایت)" + +msgid "Comma-separated integers" +msgstr "اعداد صحیح جدا-شده با ویلگول" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"مقدار «%(value)s» در قالب نادرستی وارد شده است. تاریخ باید در قالب YYYY-MM-" +"DD باشد." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"مقدار تاریخ «%(value)s» با اینکه در قالب درستی (YYYY-MM-DD) است ولی تاریخ " +"ناممکنی را نشان می‌دهد." + +msgid "Date (without time)" +msgstr "تاریخ (بدون زمان)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"مقدار \"%(value)s\" یک قالب نامعتبر دارد. باید در قالب YYYY-MM-DD HH:MM[:" +"ss[.uuuuuu]][TZ] باشد." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"مقدار \"%(value)s\" یک قالب معتبر دارد (YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) " +"اما یک تاریخ/زمان نامعتبر است." + +msgid "Date (with time)" +msgstr "تاریخ (با زمان)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "مقدار '%(value)s' باید عدد دسیمال باشد." + +msgid "Decimal number" +msgstr "عدد دهدهی" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"مقدار «%(value)s» در قالب نادرستی وارد شده است. باید در قالب ‎[DD] [HH:" +"[MM:]]ss[.uuuuuu]‎ باشد." + +msgid "Duration" +msgstr "بازهٔ زمانی" + +msgid "Email address" +msgstr "نشانی پست الکترونیکی" + +msgid "File path" +msgstr "مسیر پرونده" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "مقدار «%(value)s» باید عدد اعشاری فلوت باشد." + +msgid "Floating point number" +msgstr "عدد اعشاری" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "مقدار «%(value)s» باید عدد حقیقی باشد." + +msgid "Integer" +msgstr "عدد صحیح" + +msgid "Big (8 byte) integer" +msgstr "بزرگ (8 بایت) عدد صحیح" + +msgid "Small integer" +msgstr "عدد صحیح کوچک" + +msgid "IPv4 address" +msgstr "IPv4 آدرس" + +msgid "IP address" +msgstr "نشانی IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "مقدار «%(value)s» باید True یا False یا None باشد." + +msgid "Boolean (Either True, False or None)" +msgstr "‌بولی (درست، نادرست یا پوچ)" + +msgid "Positive big integer" +msgstr "عدد صحیح مثبت" + +msgid "Positive integer" +msgstr "عدد صحیح مثبت" + +msgid "Positive small integer" +msgstr "مثبت عدد صحیح کوچک" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "تیتر (حداکثر %(max_length)s)" + +msgid "Text" +msgstr "متن" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"مقدار «%(value)s» در قالب نادرستی وارد شده است. باید در قالب HH:MM[:ss[." +"uuuuuu]]‎ باشد." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"مقدار «%(value)s» با اینکه در قالب درستی (HH:MM[:ss[.uuuuuu]]‎) است ولی زمان " +"ناممکنی را نشان می‌دهد." + +msgid "Time" +msgstr "زمان" + +msgid "URL" +msgstr "نشانی اینترنتی" + +msgid "Raw binary data" +msgstr "دادهٔ دودویی خام" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "\"%(value)s\" یک UUID معتبر نیست." + +msgid "Universally unique identifier" +msgstr "شناسه منحصر به فرد سراسری" + +msgid "File" +msgstr "پرونده" + +msgid "Image" +msgstr "تصویر" + +msgid "A JSON object" +msgstr "یک شیء JSON" + +msgid "Value must be valid JSON." +msgstr "مقدار، باید یک JSON معتبر باشد." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(model)s با %(field)s %(value)r وجود ندارد." + +msgid "Foreign Key (type determined by related field)" +msgstr "کلید خارجی ( نوع بر اساس فیلد رابط مشخص میشود )" + +msgid "One-to-one relationship" +msgstr "رابطه یک به یک " + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "رابطه %(from)s به %(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "روابط %(from)s به %(to)s" + +msgid "Many-to-many relationship" +msgstr "رابطه چند به چند" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":؟.!" + +msgid "This field is required." +msgstr "این فیلد لازم است." + +msgid "Enter a whole number." +msgstr "به طور کامل یک عدد وارد کنید." + +msgid "Enter a valid date." +msgstr "یک تاریخ معتبر وارد کنید." + +msgid "Enter a valid time." +msgstr "یک زمان معتبر وارد کنید." + +msgid "Enter a valid date/time." +msgstr "یک تاریخ/زمان معتبر وارد کنید." + +msgid "Enter a valid duration." +msgstr "یک بازهٔ زمانی معتبر وارد کنید." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "عدد روز باید بین {min_days} و {max_days} باشد." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "پرونده‌ای ارسال نشده است. نوع کدگذاری فرم را بررسی کنید." + +msgid "No file was submitted." +msgstr "پرونده‌ای ارسال نشده است." + +msgid "The submitted file is empty." +msgstr "پروندهٔ ارسال‌شده خالیست." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"طول عنوان پرونده باید حداقل %(max)d کاراکتر باشد (طولش %(length)d است)." +msgstr[1] "" +"طول عنوان پرونده باید حداقل %(max)d کاراکتر باشد (طولش %(length)d است)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "لطفا یا فایل ارسال کنید یا دکمه پاک کردن را علامت بزنید، نه هردو." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"یک تصویر معتبر بارگذاری کنید. پرونده‌ای که بارگذاری کردید یا تصویر نبوده و یا " +"تصویری مخدوش بوده است." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "یک گزینهٔ معتبر انتخاب کنید. %(value)s از گزینه‌های موجود نیست." + +msgid "Enter a list of values." +msgstr "فهرستی از مقادیر وارد کنید." + +msgid "Enter a complete value." +msgstr "یک مقدار کامل وارد کنید." + +msgid "Enter a valid UUID." +msgstr "یک UUID معتبر وارد کنید." + +msgid "Enter a valid JSON." +msgstr "یک JSON معتبر وارد کنید" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(فیلد پنهان %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"اطلاعات ManagementForm مفقود یا دستکاری شده است. ردیف های مفقود شده: " +"%(field_names)s. اگر این مشکل ادامه داشت، آن را گزارش کنید." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "ترتیب:" + +msgid "Delete" +msgstr "حذف" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "لطفا محتوی تکراری برای %(field)s را اصلاح کنید." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "لطفا محتوی تکراری برای %(field)s را که باید یکتا باشد اصلاح کنید." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"لطفا اطلاعات تکراری %(field_name)s را اصلاح کنید که باید در %(lookup)s " +"یکتا باشد %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "لطفا مقدار تکراری را اصلاح کنید." + +msgid "The inline value did not match the parent instance." +msgstr "مقدار درون خطی موجود با نمونه والد آن مطابقت ندارد." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "یک گزینهٔ معتبر انتخاب کنید. آن گزینه از گزینه‌های موجود نیست." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "\"%(pk)s\" یک مقدار معتبر نیست." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)sدر محدوده زمانی %(current_timezone)s، قابل تفسیر نیست؛ ممکن است " +"نامشخص باشد یا اصلاً وجود نداشته باشد." + +msgid "Clear" +msgstr "پاک کردن" + +msgid "Currently" +msgstr "در حال حاضر" + +msgid "Change" +msgstr "تغییر" + +msgid "Unknown" +msgstr "ناشناخته" + +msgid "Yes" +msgstr "بله" + +msgid "No" +msgstr "خیر" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "بله،خیر،شاید" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d بایت" +msgstr[1] "%(size)d بایت" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "ب.ظ." + +msgid "a.m." +msgstr "صبح" + +msgid "PM" +msgstr "بعد از ظهر" + +msgid "AM" +msgstr "صبح" + +msgid "midnight" +msgstr "نیمه شب" + +msgid "noon" +msgstr "ظهر" + +msgid "Monday" +msgstr "دوشنبه" + +msgid "Tuesday" +msgstr "سه شنبه" + +msgid "Wednesday" +msgstr "چهارشنبه" + +msgid "Thursday" +msgstr "پنجشنبه" + +msgid "Friday" +msgstr "جمعه" + +msgid "Saturday" +msgstr "شنبه" + +msgid "Sunday" +msgstr "یکشنبه" + +msgid "Mon" +msgstr "دوشنبه" + +msgid "Tue" +msgstr "سه‌شنبه" + +msgid "Wed" +msgstr "چهارشنبه" + +msgid "Thu" +msgstr "پنجشنبه" + +msgid "Fri" +msgstr "جمعه" + +msgid "Sat" +msgstr "شنبه" + +msgid "Sun" +msgstr "یکشنبه" + +msgid "January" +msgstr "ژانویه" + +msgid "February" +msgstr "فوریه" + +msgid "March" +msgstr "مارس" + +msgid "April" +msgstr "آوریل" + +msgid "May" +msgstr "مه" + +msgid "June" +msgstr "ژوئن" + +msgid "July" +msgstr "ژوئیه" + +msgid "August" +msgstr "اوت" + +msgid "September" +msgstr "سپتامبر" + +msgid "October" +msgstr "اکتبر" + +msgid "November" +msgstr "نوامبر" + +msgid "December" +msgstr "دسامبر" + +msgid "jan" +msgstr "ژانویه" + +msgid "feb" +msgstr "فوریه" + +msgid "mar" +msgstr "مارس" + +msgid "apr" +msgstr "آوریل" + +msgid "may" +msgstr "مه" + +msgid "jun" +msgstr "ژوئن" + +msgid "jul" +msgstr "ژوئیه" + +msgid "aug" +msgstr "اوت" + +msgid "sep" +msgstr "سپتامبر" + +msgid "oct" +msgstr "اکتبر" + +msgid "nov" +msgstr "نوامبر" + +msgid "dec" +msgstr "دسامبر" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "ژانویه" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "فوریه" + +msgctxt "abbrev. month" +msgid "March" +msgstr "مارس" + +msgctxt "abbrev. month" +msgid "April" +msgstr "آوریل" + +msgctxt "abbrev. month" +msgid "May" +msgstr "مه" + +msgctxt "abbrev. month" +msgid "June" +msgstr "ژوئن" + +msgctxt "abbrev. month" +msgid "July" +msgstr "جولای" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "اوت" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "سپتامبر" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "اکتبر" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "نوامبر" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "دسامبر" + +msgctxt "alt. month" +msgid "January" +msgstr "ژانویه" + +msgctxt "alt. month" +msgid "February" +msgstr "فوریه" + +msgctxt "alt. month" +msgid "March" +msgstr "مارس" + +msgctxt "alt. month" +msgid "April" +msgstr "آوریل" + +msgctxt "alt. month" +msgid "May" +msgstr "مه" + +msgctxt "alt. month" +msgid "June" +msgstr "ژوئن" + +msgctxt "alt. month" +msgid "July" +msgstr "جولای" + +msgctxt "alt. month" +msgid "August" +msgstr "اوت" + +msgctxt "alt. month" +msgid "September" +msgstr "سپتامبر" + +msgctxt "alt. month" +msgid "October" +msgstr "اکتبر" + +msgctxt "alt. month" +msgid "November" +msgstr "نوامبر" + +msgctxt "alt. month" +msgid "December" +msgstr "دسامبر" + +msgid "This is not a valid IPv6 address." +msgstr "این مقدار آدرس IPv6 معتبری نیست." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "یا" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "،" + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d سال" +msgstr[1] "%(num)d سال" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d ماه" +msgstr[1] "%(num)d ماه" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d هفته" +msgstr[1] "%(num)d هفته" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d روز" +msgstr[1] "%(num)d روز" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d ساعت" +msgstr[1] "%(num)d ساعت" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d دقیقه" +msgstr[1] "%(num)d دقیقه" + +msgid "Forbidden" +msgstr "ممنوع" + +msgid "CSRF verification failed. Request aborted." +msgstr "‏CSRF تأیید نشد. درخواست لغو شد." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"شما این پیغام را مشاهده میکنید برای اینکه این HTTPS site نیازمند یک " +"\"Referer header\" برای ارسال توسط مرورگر شما دارد،‌اما مقداری ارسال " +"نمیشود . این هدر الزامی میباشد برای امنیت ، در واقع برای اینکه مرورگر شما " +"مطمین شود hijack به عنوان نفر سوم (third parties) در میان نیست" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"اگر در مرورگر خود سر تیتر \"Referer\" را غیرفعال کرده‌اید، لطفاً آن را فعال " +"کنید، یا حداقل برای این وب‌گاه یا برای ارتباطات HTTPS و یا برای درخواست‌های " +"\"Same-origin\" فعال کنید." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"اگر شما از تگ استفاده " +"می‌کنید یا سر تیتر \"Referrer-Policy: no-referrer\" را اضافه کرده‌اید، لطفاً " +"آن را حذف کنید. محافظ CSRF به سرتیتر \"Referer\" نیاز دارد تا بتواند بررسی " +"سخت‌گیرانه ارجاع دهنده را انجام دهد. اگر ملاحظاتی در مورد حریم خصوصی دارید از " +"روش‎‌های جایگزین مانند برای ارجاع دادن به وب‌گاه‌های " +"شخص ثالث استفاده کنید." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"شما این پیام را میبینید چون این سایت نیازمند کوکی «جعل درخواست میان وبگاهی " +"(CSRF)» است. این کوکی برای امنیت شما ضروری است. با این کوکی می‌توانیم از " +"اینکه شخص ثالثی کنترل مرورگرتان را به دست نگرفته است اطمینان پیدا کنیم." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"اگر مرورگر خود را تنظیم کرده‌اید که کوکی غیرفعال باشد، لطفاً مجدداً آن را فعال " +"کنید؛ حداقل برای این وب‌گاه یا برای درخواست‌های \"same-origin\"." + +msgid "More information is available with DEBUG=True." +msgstr "اطلاعات بیشتر با DEBUG=True ارائه خواهد شد." + +msgid "No year specified" +msgstr "هیچ سالی مشخص نشده است" + +msgid "Date out of range" +msgstr "تاریخ غیرمجاز است" + +msgid "No month specified" +msgstr "هیچ ماهی مشخص نشده است" + +msgid "No day specified" +msgstr "هیچ روزی مشخص نشده است" + +msgid "No week specified" +msgstr "هیچ هفته‌ای مشخص نشده است" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "هیچ %(verbose_name_plural)s موجود نیست" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"آینده %(verbose_name_plural)s امکان پذیر نیست زیرا مقدار %(class_name)s." +"allow_future برابر False تنظیم شده است." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "نوشته تاریخ \"%(datestr)s\" در قالب \"%(format)s\" نامعتبر است" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "هیچ %(verbose_name)s ای مطابق جستجو پیدا نشد." + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "صفحه \"آخرین\" نیست یا شماره صفحه قابل ترجمه به یک عدد صحیح نیست." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "صفحه‌ی اشتباه (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "لیست خالی و \"%(class_name)s.allow_empty\" برابر False است." + +msgid "Directory indexes are not allowed here." +msgstr "شاخص دایرکتوری اینجا قابل قبول نیست." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "\"%(path)s\" وجود ندارد " + +#, python-format +msgid "Index of %(directory)s" +msgstr "فهرست %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "نصب درست کار کرد. تبریک می گویم!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"نمایش release notes برای نسخه %(version)s " +"جنگو" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"شما این صفحه را به این دلیل مشاهده می کنید که DEBUG=True در فایل تنظیمات شما وجود دارد و شما هیچ URL " +"تنظیم نکرده اید." + +msgid "Django Documentation" +msgstr "مستندات جنگو" + +msgid "Topics, references, & how-to’s" +msgstr "سرفصل‌ها، منابع و دستورالعمل‌ها" + +msgid "Tutorial: A Polling App" +msgstr "آموزش گام به گام: برنامکی برای رأی‌گیری" + +msgid "Get started with Django" +msgstr "شروع به کار با جنگو" + +msgid "Django Community" +msgstr "جامعهٔ جنگو" + +msgid "Connect, get help, or contribute" +msgstr "متصل شوید، کمک بگیرید یا مشارکت کنید" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fa/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fa/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fa/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fa/formats.py new file mode 100644 index 0000000..e7019bc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fa/formats.py @@ -0,0 +1,21 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j F Y" +TIME_FORMAT = "G:i" +DATETIME_FORMAT = "j F Y، ساعت G:i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "Y/n/j" +SHORT_DATETIME_FORMAT = "Y/n/j،‏ G:i" +FIRST_DAY_OF_WEEK = 6 + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = "." +THOUSAND_SEPARATOR = "," +# NUMBER_GROUPING = diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1a15cef Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fi/LC_MESSAGES/django.po new file mode 100644 index 0000000..afea426 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fi/LC_MESSAGES/django.po @@ -0,0 +1,1332 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Aarni Koskela, 2015,2017-2018,2020-2022 +# Antti Kaihola , 2011 +# Jannis Leidel , 2011 +# Jiri Grönroos , 2021,2023 +# Lasse Liehu , 2015 +# Mika Mäkelä , 2018 +# Klaus Dahlén, 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Jiri Grönroos , 2021,2023\n" +"Language-Team: Finnish (http://app.transifex.com/django/django/language/" +"fi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "afrikaans" + +msgid "Arabic" +msgstr "arabia" + +msgid "Algerian Arabic" +msgstr "Algerian arabia" + +msgid "Asturian" +msgstr "asturian kieli" + +msgid "Azerbaijani" +msgstr "azeri" + +msgid "Bulgarian" +msgstr "bulgaria" + +msgid "Belarusian" +msgstr "valkovenäjän kieli" + +msgid "Bengali" +msgstr "bengali" + +msgid "Breton" +msgstr "bretoni" + +msgid "Bosnian" +msgstr "bosnia" + +msgid "Catalan" +msgstr "katalaani" + +msgid "Central Kurdish (Sorani)" +msgstr "" + +msgid "Czech" +msgstr "tšekki" + +msgid "Welsh" +msgstr "wales" + +msgid "Danish" +msgstr "tanska" + +msgid "German" +msgstr "saksa" + +msgid "Lower Sorbian" +msgstr "Alasorbi" + +msgid "Greek" +msgstr "kreikka" + +msgid "English" +msgstr "englanti" + +msgid "Australian English" +msgstr "australianenglanti" + +msgid "British English" +msgstr "brittienglanti" + +msgid "Esperanto" +msgstr "esperanto" + +msgid "Spanish" +msgstr "espanja" + +msgid "Argentinian Spanish" +msgstr "Argentiinan espanja" + +msgid "Colombian Spanish" +msgstr "Kolumbian espanja" + +msgid "Mexican Spanish" +msgstr "Meksikon espanja" + +msgid "Nicaraguan Spanish" +msgstr "Nicaraguan espanja" + +msgid "Venezuelan Spanish" +msgstr "Venezuelan espanja" + +msgid "Estonian" +msgstr "viro" + +msgid "Basque" +msgstr "baski" + +msgid "Persian" +msgstr "persia" + +msgid "Finnish" +msgstr "suomi" + +msgid "French" +msgstr "ranska" + +msgid "Frisian" +msgstr "friisi" + +msgid "Irish" +msgstr "irlanti" + +msgid "Scottish Gaelic" +msgstr "skottilainen gaeli" + +msgid "Galician" +msgstr "galicia" + +msgid "Hebrew" +msgstr "heprea" + +msgid "Hindi" +msgstr "hindi" + +msgid "Croatian" +msgstr "kroatia" + +msgid "Upper Sorbian" +msgstr "Yläsorbi" + +msgid "Hungarian" +msgstr "unkari" + +msgid "Armenian" +msgstr "armenian kieli" + +msgid "Interlingua" +msgstr "interlingua" + +msgid "Indonesian" +msgstr "indonesia" + +msgid "Igbo" +msgstr "igbo" + +msgid "Ido" +msgstr "ido" + +msgid "Icelandic" +msgstr "islanti" + +msgid "Italian" +msgstr "italia" + +msgid "Japanese" +msgstr "japani" + +msgid "Georgian" +msgstr "georgia" + +msgid "Kabyle" +msgstr "Kabyle" + +msgid "Kazakh" +msgstr "kazakin kieli" + +msgid "Khmer" +msgstr "khmerin kieli" + +msgid "Kannada" +msgstr "kannada" + +msgid "Korean" +msgstr "korea" + +msgid "Kyrgyz" +msgstr "kirgiisi" + +msgid "Luxembourgish" +msgstr "luxemburgin kieli" + +msgid "Lithuanian" +msgstr "liettua" + +msgid "Latvian" +msgstr "latvia" + +msgid "Macedonian" +msgstr "makedonia" + +msgid "Malayalam" +msgstr "malajalam" + +msgid "Mongolian" +msgstr "mongolia" + +msgid "Marathi" +msgstr "marathi" + +msgid "Malay" +msgstr "malaiji" + +msgid "Burmese" +msgstr "burman kieli" + +msgid "Norwegian Bokmål" +msgstr "norja (bokmål)" + +msgid "Nepali" +msgstr "nepalin kieli" + +msgid "Dutch" +msgstr "hollanti" + +msgid "Norwegian Nynorsk" +msgstr "norja (uusnorja)" + +msgid "Ossetic" +msgstr "osseetin kieli" + +msgid "Punjabi" +msgstr "punjabin kieli" + +msgid "Polish" +msgstr "puola" + +msgid "Portuguese" +msgstr "portugali" + +msgid "Brazilian Portuguese" +msgstr "brasilian portugali" + +msgid "Romanian" +msgstr "romania" + +msgid "Russian" +msgstr "venäjä" + +msgid "Slovak" +msgstr "slovakia" + +msgid "Slovenian" +msgstr "slovenia" + +msgid "Albanian" +msgstr "albaani" + +msgid "Serbian" +msgstr "serbia" + +msgid "Serbian Latin" +msgstr "serbian latina" + +msgid "Swedish" +msgstr "ruotsi" + +msgid "Swahili" +msgstr "swahili" + +msgid "Tamil" +msgstr "tamili" + +msgid "Telugu" +msgstr "telugu" + +msgid "Tajik" +msgstr "tadžikki" + +msgid "Thai" +msgstr "thain kieli" + +msgid "Turkmen" +msgstr "turkmeeni" + +msgid "Turkish" +msgstr "turkki" + +msgid "Tatar" +msgstr "tataarin kieli" + +msgid "Udmurt" +msgstr "udmurtti" + +msgid "Uyghur" +msgstr "uiguuri" + +msgid "Ukrainian" +msgstr "ukraina" + +msgid "Urdu" +msgstr "urdu" + +msgid "Uzbek" +msgstr "uzbekki" + +msgid "Vietnamese" +msgstr "vietnam" + +msgid "Simplified Chinese" +msgstr "kiina (yksinkertaistettu)" + +msgid "Traditional Chinese" +msgstr "kiina (perinteinen)" + +msgid "Messages" +msgstr "Viestit" + +msgid "Site Maps" +msgstr "Sivukartat" + +msgid "Static Files" +msgstr "Staattiset tiedostot" + +msgid "Syndication" +msgstr "Syndikointi" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "..." + +msgid "That page number is not an integer" +msgstr "Annettu sivunumero ei ole kokonaisluku" + +msgid "That page number is less than 1" +msgstr "Annettu sivunumero on alle 1" + +msgid "That page contains no results" +msgstr "Annetulla sivulla ei ole tuloksia" + +msgid "Enter a valid value." +msgstr "Syötä oikea arvo." + +msgid "Enter a valid URL." +msgstr "Syötä oikea URL-osoite." + +msgid "Enter a valid integer." +msgstr "Syötä kelvollinen kokonaisluku." + +msgid "Enter a valid email address." +msgstr "Syötä kelvollinen sähköpostiosoite." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Anna lyhytnimi joka koostuu vain kirjaimista, numeroista sekä ala- ja " +"tavuviivoista." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Anna lyhytnimi joka koostuu vain Unicode-kirjaimista, numeroista sekä ala- " +"ja tavuviivoista." + +msgid "Enter a valid IPv4 address." +msgstr "Syötä kelvollinen IPv4-osoite." + +msgid "Enter a valid IPv6 address." +msgstr "Syötä kelvollinen IPv6-osoite." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Syötä kelvollinen IPv4- tai IPv6-osoite." + +msgid "Enter only digits separated by commas." +msgstr "Vain pilkulla erotetut numeromerkit kelpaavat tässä." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Tämän arvon on oltava %(limit_value)s (nyt %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Tämän arvon on oltava enintään %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Tämän luvun on oltava vähintään %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "Varmista, että arvo on askelkoon %(limit_value)smonikerta. " + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Varmista, että tämä arvo on vähintään %(limit_value)d merkin pituinen (tällä " +"hetkellä %(show_value)d)." +msgstr[1] "" +"Varmista, että tämä arvo on vähintään %(limit_value)d merkkiä pitkä (tällä " +"hetkellä %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Varmista, että tämä arvo on enintään %(limit_value)d merkin pituinen (tällä " +"hetkellä %(show_value)d)." +msgstr[1] "" +"Varmista, että tämä arvo on enintään %(limit_value)d merkkiä pitkä (tällä " +"hetkellä %(show_value)d)." + +msgid "Enter a number." +msgstr "Syötä luku." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Tässä luvussa voi olla yhteensä enintään %(max)s numero." +msgstr[1] "Tässä luvussa voi olla yhteensä enintään %(max)s numeroa." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Tässä luvussa saa olla enintään %(max)s desimaali." +msgstr[1] "Tässä luvussa saa olla enintään %(max)s desimaalia." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Tässä luvussa saa olla enintään %(max)s numero ennen desimaalipilkkua." +msgstr[1] "" +"Tässä luvussa saa olla enintään %(max)s numeroa ennen desimaalipilkkua." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Pääte \"%(extension)s\" ei ole sallittu. Sallittuja päätteitä ovat " +"\"%(allowed_extensions)s\"." + +msgid "Null characters are not allowed." +msgstr "Tyhjiä merkkejä (null) ei sallita." + +msgid "and" +msgstr "ja" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s jolla on nämä %(field_labels)s on jo olemassa." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Rajoitetta \"%(name)s\" loukataan." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Arvo %(value)r ei kelpaa." + +msgid "This field cannot be null." +msgstr "Tämän kentän arvo ei voi olla \"null\"." + +msgid "This field cannot be blank." +msgstr "Tämä kenttä ei voi olla tyhjä." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s jolla on tämä %(field_label)s, on jo olemassa." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"\"%(field_label)s\"-kentän on oltava uniikki suhteessa: %(date_field_label)s " +"%(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Kenttä tyyppiä: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "%(value)s-arvo pitää olla joko tosi tai epätosi." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "%(value)s-arvo pitää olla joko tosi, epätosi tai ei mitään." + +msgid "Boolean (Either True or False)" +msgstr "Totuusarvo: joko tosi (True) tai epätosi (False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Merkkijono (enintään %(max_length)s merkkiä)" + +msgid "String (unlimited)" +msgstr "Merkkijono (rajoittamaton)" + +msgid "Comma-separated integers" +msgstr "Pilkulla erotetut kokonaisluvut" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"%(value)s-arvo on väärässä päivämäärämuodossa. Sen tulee olla VVVV-KK-PP -" +"muodossa." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"%(value)s-arvo on oikeassa päivämäärämuodossa (VVVV-KK-PP), muttei ole " +"kelvollinen päivämäärä." + +msgid "Date (without time)" +msgstr "Päivämäärä (ilman kellonaikaa)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"%(value)s-arvon muoto ei kelpaa. Se tulee olla VVVV-KK-PP TT:MM[:ss[.uuuuuu]]" +"[TZ] -muodossa." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"%(value)s-arvon muoto on oikea (VVVV-KK-PP TT:MM[:ss[.uuuuuu]][TZ]), mutta " +"päivämäärä/aika ei ole kelvollinen." + +msgid "Date (with time)" +msgstr "Päivämäärä ja kellonaika" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "%(value)s-arvo tulee olla desimaaliluku." + +msgid "Decimal number" +msgstr "Desimaaliluku" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "%(value)s-arvo pitää olla muodossa [PP] TT:MM[:ss[.uuuuuu]]." + +msgid "Duration" +msgstr "Kesto" + +msgid "Email address" +msgstr "Sähköpostiosoite" + +msgid "File path" +msgstr "Tiedostopolku" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "%(value)s-arvo tulee olla liukuluku." + +msgid "Floating point number" +msgstr "Liukuluku" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "%(value)s-arvo tulee olla kokonaisluku." + +msgid "Integer" +msgstr "Kokonaisluku" + +msgid "Big (8 byte) integer" +msgstr "Suuri (8-tavuinen) kokonaisluku" + +msgid "Small integer" +msgstr "Pieni kokonaisluku" + +msgid "IPv4 address" +msgstr "IPv4-osoite" + +msgid "IP address" +msgstr "IP-osoite" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "%(value)s-arvo tulee olla joko ei mitään, tosi tai epätosi." + +msgid "Boolean (Either True, False or None)" +msgstr "Totuusarvo: joko tosi (True), epätosi (False) tai ei mikään (None)" + +msgid "Positive big integer" +msgstr "Suuri positiivinen kokonaisluku" + +msgid "Positive integer" +msgstr "Positiivinen kokonaisluku" + +msgid "Positive small integer" +msgstr "Pieni positiivinen kokonaisluku" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Lyhytnimi (enintään %(max_length)s merkkiä)" + +msgid "Text" +msgstr "Tekstiä" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "%(value)s-arvo pitää olla muodossa TT:MM[:ss[.uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"%(value)s-arvo on oikeassa muodossa (TT:MM[:ss[.uuuuuu]]), mutta kellonaika " +"ei kelpaa." + +msgid "Time" +msgstr "Kellonaika" + +msgid "URL" +msgstr "URL-osoite" + +msgid "Raw binary data" +msgstr "Raaka binaaridata" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "%(value)s ei ole kelvollinen UUID." + +msgid "Universally unique identifier" +msgstr "UUID-tunnus" + +msgid "File" +msgstr "Tiedosto" + +msgid "Image" +msgstr "Kuva" + +msgid "A JSON object" +msgstr "JSON-tietue" + +msgid "Value must be valid JSON." +msgstr "Arvon pitää olla kelvollista JSONia." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(model)s-tietuetta %(field)s-kentällä %(value)r ei ole olemassa." + +msgid "Foreign Key (type determined by related field)" +msgstr "Vierasavain (tyyppi määräytyy liittyvän kentän mukaan)" + +msgid "One-to-one relationship" +msgstr "Yksi-yhteen -relaatio" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s -suhde" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s -suhteet" + +msgid "Many-to-many relationship" +msgstr "Moni-moneen -relaatio" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Tämä kenttä vaaditaan." + +msgid "Enter a whole number." +msgstr "Syötä kokonaisluku." + +msgid "Enter a valid date." +msgstr "Syötä oikea päivämäärä." + +msgid "Enter a valid time." +msgstr "Syötä oikea kellonaika." + +msgid "Enter a valid date/time." +msgstr "Syötä oikea pvm/kellonaika." + +msgid "Enter a valid duration." +msgstr "Syötä oikea kesto." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Päivien määrä täytyy olla välillä {min_days} ja {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Tiedostoa ei lähetetty. Tarkista lomakkeen koodaus (encoding)." + +msgid "No file was submitted." +msgstr "Yhtään tiedostoa ei ole lähetetty." + +msgid "The submitted file is empty." +msgstr "Lähetetty tiedosto on tyhjä." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Varmista, että tämä tiedostonimi on enintään %(max)d merkin pituinen (tällä " +"hetkellä %(length)d)." +msgstr[1] "" +"Varmista, että tämä tiedostonimi on enintään %(max)d merkkiä pitkä (tällä " +"hetkellä %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Voit joko lähettää tai poistaa tiedoston, muttei kumpaakin samalla." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Kuva ei kelpaa. Lähettämäsi tiedosto ei ole kuva, tai tiedosto on vioittunut." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Valitse oikea vaihtoehto. %(value)s ei ole vaihtoehtojen joukossa." + +msgid "Enter a list of values." +msgstr "Syötä lista." + +msgid "Enter a complete value." +msgstr "Syötä kokonainen arvo." + +msgid "Enter a valid UUID." +msgstr "Syötä oikea UUID." + +msgid "Enter a valid JSON." +msgstr "Syötä oikea JSON-arvo." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Piilokenttä %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"ManagementForm-tiedot puuttuvat tai niitä on muutettu. Puuttuvat kentät ovat " +"%(field_names)s. Jos ongelma toistuu, voi olla että joudut raportoimaan " +"tämän bugina." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Lähetä enintään%(num)d lomake." +msgstr[1] "Lähetä enintään %(num)d lomaketta." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Lähetä vähintään %(num)d lomake." +msgstr[1] "Lähetä vähintään %(num)d lomaketta. " + +msgid "Order" +msgstr "Järjestys" + +msgid "Delete" +msgstr "Poista" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Korjaa kaksoisarvo kentälle %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Ole hyvä ja korjaa uniikin kentän %(field)s kaksoisarvo." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Korjaa alla olevat kaksoisarvot." + +msgid "The inline value did not match the parent instance." +msgstr "Liittyvä arvo ei vastannut vanhempaa instanssia." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Valitse oikea vaihtoehto. Valintasi ei löydy vaihtoehtojen joukosta." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "\"%(pk)s\" ei ole kelvollinen arvo." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s -arvoa ei pystytty lukemaan aikavyöhykkeellä " +"%(current_timezone)s; se saattaa olla moniarvoinen tai määrittämätön." + +msgid "Clear" +msgstr "Poista" + +msgid "Currently" +msgstr "Tällä hetkellä" + +msgid "Change" +msgstr "Muokkaa" + +msgid "Unknown" +msgstr "Tuntematon" + +msgid "Yes" +msgstr "Kyllä" + +msgid "No" +msgstr "Ei" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "kyllä,ei,ehkä" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d tavu" +msgstr[1] "%(size)d tavua" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "ip" + +msgid "a.m." +msgstr "ap" + +msgid "PM" +msgstr "IP" + +msgid "AM" +msgstr "AP" + +msgid "midnight" +msgstr "keskiyö" + +msgid "noon" +msgstr "keskipäivä" + +msgid "Monday" +msgstr "maanantai" + +msgid "Tuesday" +msgstr "tiistai" + +msgid "Wednesday" +msgstr "keskiviikko" + +msgid "Thursday" +msgstr "torstai" + +msgid "Friday" +msgstr "perjantai" + +msgid "Saturday" +msgstr "lauantai" + +msgid "Sunday" +msgstr "sunnuntai" + +msgid "Mon" +msgstr "ma" + +msgid "Tue" +msgstr "ti" + +msgid "Wed" +msgstr "ke" + +msgid "Thu" +msgstr "to" + +msgid "Fri" +msgstr "pe" + +msgid "Sat" +msgstr "la" + +msgid "Sun" +msgstr "su" + +msgid "January" +msgstr "tammikuu" + +msgid "February" +msgstr "helmikuu" + +msgid "March" +msgstr "maaliskuu" + +msgid "April" +msgstr "huhtikuu" + +msgid "May" +msgstr "toukokuu" + +msgid "June" +msgstr "kesäkuu" + +msgid "July" +msgstr "heinäkuu" + +msgid "August" +msgstr "elokuu" + +msgid "September" +msgstr "syyskuu" + +msgid "October" +msgstr "lokakuu" + +msgid "November" +msgstr "marraskuu" + +msgid "December" +msgstr "joulukuu" + +msgid "jan" +msgstr "tam" + +msgid "feb" +msgstr "hel" + +msgid "mar" +msgstr "maa" + +msgid "apr" +msgstr "huh" + +msgid "may" +msgstr "tou" + +msgid "jun" +msgstr "kes" + +msgid "jul" +msgstr "hei" + +msgid "aug" +msgstr "elo" + +msgid "sep" +msgstr "syy" + +msgid "oct" +msgstr "lok" + +msgid "nov" +msgstr "mar" + +msgid "dec" +msgstr "jou" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "tammi" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "helmi" + +msgctxt "abbrev. month" +msgid "March" +msgstr "maalis" + +msgctxt "abbrev. month" +msgid "April" +msgstr "huhti" + +msgctxt "abbrev. month" +msgid "May" +msgstr "touko" + +msgctxt "abbrev. month" +msgid "June" +msgstr "kesä" + +msgctxt "abbrev. month" +msgid "July" +msgstr "heinä" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "elo" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "syys" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "loka" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "marras" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "joulu" + +msgctxt "alt. month" +msgid "January" +msgstr "tammikuuta" + +msgctxt "alt. month" +msgid "February" +msgstr "helmikuuta" + +msgctxt "alt. month" +msgid "March" +msgstr "maaliskuuta" + +msgctxt "alt. month" +msgid "April" +msgstr "huhtikuuta" + +msgctxt "alt. month" +msgid "May" +msgstr "toukokuuta" + +msgctxt "alt. month" +msgid "June" +msgstr "kesäkuuta" + +msgctxt "alt. month" +msgid "July" +msgstr "heinäkuuta" + +msgctxt "alt. month" +msgid "August" +msgstr "elokuuta" + +msgctxt "alt. month" +msgid "September" +msgstr "syyskuuta" + +msgctxt "alt. month" +msgid "October" +msgstr "lokakuuta" + +msgctxt "alt. month" +msgid "November" +msgstr "marraskuuta" + +msgctxt "alt. month" +msgid "December" +msgstr "joulukuuta" + +msgid "This is not a valid IPv6 address." +msgstr "Tämä ei ole kelvollinen IPv6-osoite." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "tai" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d vuosi" +msgstr[1] "%(num)d vuotta" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d kuukausi" +msgstr[1] "%(num)d kuukautta " + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d viikko" +msgstr[1] "%(num)d viikkoa" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d päivä" +msgstr[1] "%(num)d päivää" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d tunti" +msgstr[1] "%(num)d tuntia" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuutti" +msgstr[1] "%(num)d minuuttia" + +msgid "Forbidden" +msgstr "Kielletty" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF-vahvistus epäonnistui. Pyyntö hylätty." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Näet tämän viestin, koska tämä HTTPS-sivusto vaatii selaintasi lähettämään " +"Referer-otsakkeen, mutta sitä ei vastaanotettu. Otsake vaaditaan " +"turvallisuussyistä, varmistamaan etteivät kolmannet osapuolet ole ottaneet " +"selaintasi haltuun." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Jos olet konfiguroinut selaimesi olemaan lähettämättä Referer-otsaketta, ole " +"hyvä ja kytke otsake takaisin päälle ainakin tälle sivulle, HTTPS-" +"yhteyksille tai saman lähteen (\"same-origin\") pyynnöille." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Jos käytät -tagia tai " +"\"Referrer-Policy: no-referrer\" -otsaketta, ole hyvä ja poista ne. CSRF-" +"suojaus vaatii Referer-otsakkeen tehdäkseen tarkan referer-tarkistuksen. Jos " +"vaadit yksityisyyttä, käytä vaihtoehtoja kuten linkittääksesi kolmannen osapuolen sivuille." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Näet tämän viestin, koska tämä sivusto vaatii CSRF-evästeen " +"vastaanottaessaan lomaketietoja. Eväste vaaditaan turvallisuussyistä, " +"varmistamaan etteivät kolmannet osapuolet ole ottaneet selaintasi haltuun." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Jos olet konfiguroinut selaimesi olemaan vastaanottamatta tai lähettämättä " +"evästeitä, ole hyvä ja kytke evästeet takaisin päälle ainakin tälle sivulle " +"tai saman lähteen (\"same-origin\") pyynnöille." + +msgid "More information is available with DEBUG=True." +msgstr "Lisätietoja `DEBUG=True`-konfiguraatioasetuksella." + +msgid "No year specified" +msgstr "Vuosi puuttuu" + +msgid "Date out of range" +msgstr "Päivämäärä ei alueella" + +msgid "No month specified" +msgstr "Kuukausi puuttuu" + +msgid "No day specified" +msgstr "Päivä puuttuu" + +msgid "No week specified" +msgstr "Viikko puuttuu" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "%(verbose_name_plural)s: yhtään kohdetta ei löydy" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"%(verbose_name_plural)s: tulevia kohteita ei löydy, koska %(class_name)s." +"allow_future:n arvo on False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Päivämäärä '%(datestr)s' ei ole muotoa '%(format)s'" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Hakua vastaavaa %(verbose_name)s -kohdetta ei löytynyt" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Sivunumero ei ole 'last' (viimeinen) eikä näytä luvulta." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Epäkelpo sivu (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Lista on tyhjä, ja '%(class_name)s.allow_empty':n arvo on False." + +msgid "Directory indexes are not allowed here." +msgstr "Hakemistolistauksia ei sallita täällä." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "\"%(path)s\" ei ole olemassa" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Hakemistolistaus: %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Asennus toimi! Onneksi olkoon!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Katso Djangon version %(version)s julkaisutiedot" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Näet tämän viestin, koska asetuksissasi on DEBUG = True etkä ole konfiguroinut yhtään URL-" +"osoitetta." + +msgid "Django Documentation" +msgstr "Django-dokumentaatio" + +msgid "Topics, references, & how-to’s" +msgstr "Aiheet, viittaukset & how-tot" + +msgid "Tutorial: A Polling App" +msgstr "Tutoriaali: kyselyapplikaatio" + +msgid "Get started with Django" +msgstr "Miten päästä alkuun Djangolla" + +msgid "Django Community" +msgstr "Django-yhteisö" + +msgid "Connect, get help, or contribute" +msgstr "Verkostoidu, saa apua tai jatkokehitä" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fi/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fi/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fi/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fi/formats.py new file mode 100644 index 0000000..d9fb6d2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fi/formats.py @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j. E Y" +TIME_FORMAT = "G.i" +DATETIME_FORMAT = r"j. E Y \k\e\l\l\o G.i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j. F" +SHORT_DATE_FORMAT = "j.n.Y" +SHORT_DATETIME_FORMAT = "j.n.Y G.i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d.%m.%Y", # '20.3.2014' + "%d.%m.%y", # '20.3.14' +] +DATETIME_INPUT_FORMATS = [ + "%d.%m.%Y %H.%M.%S", # '20.3.2014 14.30.59' + "%d.%m.%Y %H.%M.%S.%f", # '20.3.2014 14.30.59.000200' + "%d.%m.%Y %H.%M", # '20.3.2014 14.30' + "%d.%m.%y %H.%M.%S", # '20.3.14 14.30.59' + "%d.%m.%y %H.%M.%S.%f", # '20.3.14 14.30.59.000200' + "%d.%m.%y %H.%M", # '20.3.14 14.30' +] +TIME_INPUT_FORMATS = [ + "%H.%M.%S", # '14.30.59' + "%H.%M.%S.%f", # '14.30.59.000200' + "%H.%M", # '14.30' +] + +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "\xa0" # Non-breaking space +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..08b33f0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 0000000..6c5a6dd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,1387 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bruno Brouard , 2021 +# Simon Charette , 2012 +# Claude Paroz , 2013-2023 +# Claude Paroz , 2011 +# Jannis Leidel , 2011 +# Jean-Baptiste Mora, 2014 +# Larlet David , 2011 +# Marie-Cécile Gohier , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Claude Paroz , 2013-2023\n" +"Language-Team: French (http://app.transifex.com/django/django/language/fr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Afrikaans" +msgstr "Afrikaans" + +msgid "Arabic" +msgstr "Arabe" + +msgid "Algerian Arabic" +msgstr "Arabe algérien" + +msgid "Asturian" +msgstr "Asturien" + +msgid "Azerbaijani" +msgstr "Azéri" + +msgid "Bulgarian" +msgstr "Bulgare" + +msgid "Belarusian" +msgstr "Biélorusse" + +msgid "Bengali" +msgstr "Bengali" + +msgid "Breton" +msgstr "Breton" + +msgid "Bosnian" +msgstr "Bosniaque" + +msgid "Catalan" +msgstr "Catalan" + +msgid "Central Kurdish (Sorani)" +msgstr "Kurde central (sorani)" + +msgid "Czech" +msgstr "Tchèque" + +msgid "Welsh" +msgstr "Gallois" + +msgid "Danish" +msgstr "Danois" + +msgid "German" +msgstr "Allemand" + +msgid "Lower Sorbian" +msgstr "Bas-sorabe" + +msgid "Greek" +msgstr "Grec" + +msgid "English" +msgstr "Anglais" + +msgid "Australian English" +msgstr "Anglais australien" + +msgid "British English" +msgstr "Anglais britannique" + +msgid "Esperanto" +msgstr "Espéranto" + +msgid "Spanish" +msgstr "Espagnol" + +msgid "Argentinian Spanish" +msgstr "Espagnol argentin" + +msgid "Colombian Spanish" +msgstr "Espagnol colombien" + +msgid "Mexican Spanish" +msgstr "Espagnol mexicain" + +msgid "Nicaraguan Spanish" +msgstr "Espagnol nicaraguayen" + +msgid "Venezuelan Spanish" +msgstr "Espagnol vénézuélien" + +msgid "Estonian" +msgstr "Estonien" + +msgid "Basque" +msgstr "Basque" + +msgid "Persian" +msgstr "Perse" + +msgid "Finnish" +msgstr "Finlandais" + +msgid "French" +msgstr "Français" + +msgid "Frisian" +msgstr "Frison" + +msgid "Irish" +msgstr "Irlandais" + +msgid "Scottish Gaelic" +msgstr "Gaélique écossais" + +msgid "Galician" +msgstr "Galicien" + +msgid "Hebrew" +msgstr "Hébreu" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Croate" + +msgid "Upper Sorbian" +msgstr "Haut-sorabe" + +msgid "Hungarian" +msgstr "Hongrois" + +msgid "Armenian" +msgstr "Arménien" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonésien" + +msgid "Igbo" +msgstr "Igbo" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Islandais" + +msgid "Italian" +msgstr "Italien" + +msgid "Japanese" +msgstr "Japonais" + +msgid "Georgian" +msgstr "Géorgien" + +msgid "Kabyle" +msgstr "Kabyle" + +msgid "Kazakh" +msgstr "Kazakh" + +msgid "Khmer" +msgstr "Khmer" + +msgid "Kannada" +msgstr "Kannada" + +msgid "Korean" +msgstr "Coréen" + +msgid "Kyrgyz" +msgstr "Kirghiz" + +msgid "Luxembourgish" +msgstr "Luxembourgeois" + +msgid "Lithuanian" +msgstr "Lituanien" + +msgid "Latvian" +msgstr "Letton" + +msgid "Macedonian" +msgstr "Macédonien" + +msgid "Malayalam" +msgstr "Malayalam" + +msgid "Mongolian" +msgstr "Mongole" + +msgid "Marathi" +msgstr "Marathi" + +msgid "Malay" +msgstr "Malais" + +msgid "Burmese" +msgstr "Birman" + +msgid "Norwegian Bokmål" +msgstr "Norvégien bokmål" + +msgid "Nepali" +msgstr "Népalais" + +msgid "Dutch" +msgstr "Hollandais" + +msgid "Norwegian Nynorsk" +msgstr "Norvégien nynorsk" + +msgid "Ossetic" +msgstr "Ossète" + +msgid "Punjabi" +msgstr "Penjabi" + +msgid "Polish" +msgstr "Polonais" + +msgid "Portuguese" +msgstr "Portugais" + +msgid "Brazilian Portuguese" +msgstr "Portugais brésilien" + +msgid "Romanian" +msgstr "Roumain" + +msgid "Russian" +msgstr "Russe" + +msgid "Slovak" +msgstr "Slovaque" + +msgid "Slovenian" +msgstr "Slovène" + +msgid "Albanian" +msgstr "Albanais" + +msgid "Serbian" +msgstr "Serbe" + +msgid "Serbian Latin" +msgstr "Serbe latin" + +msgid "Swedish" +msgstr "Suédois" + +msgid "Swahili" +msgstr "Swahili" + +msgid "Tamil" +msgstr "Tamoul" + +msgid "Telugu" +msgstr "Télougou" + +msgid "Tajik" +msgstr "Tadjik" + +msgid "Thai" +msgstr "Thaï" + +msgid "Turkmen" +msgstr "Turkmène" + +msgid "Turkish" +msgstr "Turc" + +msgid "Tatar" +msgstr "Tatar" + +msgid "Udmurt" +msgstr "Oudmourte" + +msgid "Uyghur" +msgstr "Ouïghour" + +msgid "Ukrainian" +msgstr "Ukrainien" + +msgid "Urdu" +msgstr "Ourdou" + +msgid "Uzbek" +msgstr "Ouzbek" + +msgid "Vietnamese" +msgstr "Vietnamien" + +msgid "Simplified Chinese" +msgstr "Chinois simplifié" + +msgid "Traditional Chinese" +msgstr "Chinois traditionnel" + +msgid "Messages" +msgstr "Messages" + +msgid "Site Maps" +msgstr "Plans des sites" + +msgid "Static Files" +msgstr "Fichiers statiques" + +msgid "Syndication" +msgstr "Syndication" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Ce numéro de page n’est pas un nombre entier" + +msgid "That page number is less than 1" +msgstr "Ce numéro de page est plus petit que 1" + +msgid "That page contains no results" +msgstr "Cette page ne contient aucun résultat" + +msgid "Enter a valid value." +msgstr "Saisissez une valeur valide." + +msgid "Enter a valid URL." +msgstr "Saisissez une URL valide." + +msgid "Enter a valid integer." +msgstr "Saisissez un nombre entier valide." + +msgid "Enter a valid email address." +msgstr "Saisissez une adresse de courriel valide." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Ce champ ne doit contenir que des lettres, des nombres, des tirets bas (_) " +"et des traits d’union." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Ce champ ne doit contenir que des caractères Unicode, des nombres, des " +"tirets bas (_) et des traits d’union." + +msgid "Enter a valid IPv4 address." +msgstr "Saisissez une adresse IPv4 valide." + +msgid "Enter a valid IPv6 address." +msgstr "Saisissez une adresse IPv6 valide." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Saisissez une adresse IPv4 ou IPv6 valide." + +msgid "Enter only digits separated by commas." +msgstr "Saisissez uniquement des chiffres séparés par des virgules." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Assurez-vous que cette valeur est %(limit_value)s (actuellement " +"%(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" +"Assurez-vous que cette valeur est inférieure ou égale à %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" +"Assurez-vous que cette valeur est supérieure ou égale à %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" +"Assurez-vous que cette valeur est un multiple de la taille de pas " +"%(limit_value)s." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"Assurez-vous que cette valeur est un multiple de la taille de pas " +"%(limit_value)s, débutant à %(offset)s, par ex. %(offset)s, " +"%(valid_value1)s, %(valid_value2)s, etc." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Assurez-vous que cette valeur comporte au moins %(limit_value)d caractère " +"(actuellement %(show_value)d)." +msgstr[1] "" +"Assurez-vous que cette valeur comporte au moins %(limit_value)d caractères " +"(actuellement %(show_value)d)." +msgstr[2] "" +"Assurez-vous que cette valeur comporte au moins %(limit_value)d caractères " +"(actuellement %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Assurez-vous que cette valeur comporte au plus %(limit_value)d caractère " +"(actuellement %(show_value)d)." +msgstr[1] "" +"Assurez-vous que cette valeur comporte au plus %(limit_value)d caractères " +"(actuellement %(show_value)d)." +msgstr[2] "" +"Assurez-vous que cette valeur comporte au plus %(limit_value)d caractères " +"(actuellement %(show_value)d)." + +msgid "Enter a number." +msgstr "Saisissez un nombre." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Assurez-vous qu'il n'y a pas plus de %(max)s chiffre au total." +msgstr[1] "Assurez-vous qu’il n’y a pas plus de %(max)s chiffres au total." +msgstr[2] "Assurez-vous qu’il n’y a pas plus de %(max)s chiffres au total." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +"Assurez-vous qu'il n'y a pas plus de %(max)s chiffre après la virgule." +msgstr[1] "" +"Assurez-vous qu’il n’y a pas plus de %(max)s chiffres après la virgule." +msgstr[2] "" +"Assurez-vous qu’il n’y a pas plus de %(max)s chiffres après la virgule." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Assurez-vous qu'il n'y a pas plus de %(max)s chiffre avant la virgule." +msgstr[1] "" +"Assurez-vous qu’il n’y a pas plus de %(max)s chiffres avant la virgule." +msgstr[2] "" +"Assurez-vous qu’il n’y a pas plus de %(max)s chiffres avant la virgule." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"L'extension de fichier « %(extension)s » n’est pas autorisée. Les extensions " +"autorisées sont : %(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Le caractère nul n’est pas autorisé." + +msgid "and" +msgstr "et" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "Un objet %(model_name)s avec ces champs %(field_labels)s existe déjà." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "La contrainte « %(name)s » n’est pas respectée." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "La valeur « %(value)r » n’est pas un choix valide." + +msgid "This field cannot be null." +msgstr "Ce champ ne peut pas contenir la valeur nulle." + +msgid "This field cannot be blank." +msgstr "Ce champ ne peut pas être vide." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "Un objet %(model_name)s avec ce champ %(field_label)s existe déjà." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s doit être unique pour la partie %(lookup_type)s de " +"%(date_field_label)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Champ de type : %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "La valeur « %(value)s » doit être soit True (vrai), soit False (faux)." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" +"La valeur « %(value)s » doit être True (vrai), False (faux) ou None (vide)." + +msgid "Boolean (Either True or False)" +msgstr "Booléen (soit True (vrai) ou False (faux))" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Chaîne de caractères (jusqu'à %(max_length)s)" + +msgid "String (unlimited)" +msgstr "Chaîne de caractères (illimitée)" + +msgid "Comma-separated integers" +msgstr "Des entiers séparés par une virgule" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"Le format de date de la valeur « %(value)s » n’est pas valide. Le format " +"correct est AAAA-MM-JJ." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"Le format de date de la valeur « %(value)s » est correct (AAAA-MM-JJ), mais " +"la date n’est pas valide." + +msgid "Date (without time)" +msgstr "Date (sans l’heure)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"Le format de la valeur « %(value)s » n’est pas valide. Le format correct est " +"AAAA-MM-JJ HH:MM[:ss[.uuuuuu]][FH]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"Le format de date de la valeur « %(value)s » est correct (AAAA-MM-JJ HH:MM[:" +"ss[.uuuuuu]][FH]), mais la date ou l’heure n’est pas valide." + +msgid "Date (with time)" +msgstr "Date (avec l’heure)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "La valeur « %(value)s » doit être un nombre décimal." + +msgid "Decimal number" +msgstr "Nombre décimal" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"Le format de la valeur « %(value)s » n’est pas valide. Le format correct est " +"[JJ] [[HH:]MM:]ss[.uuuuuu]." + +msgid "Duration" +msgstr "Durée" + +msgid "Email address" +msgstr "Adresse électronique" + +msgid "File path" +msgstr "Chemin vers le fichier" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "La valeur « %(value)s » doit être un nombre à virgule flottante." + +msgid "Floating point number" +msgstr "Nombre à virgule flottante" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "La valeur « %(value)s » doit être un nombre entier." + +msgid "Integer" +msgstr "Entier" + +msgid "Big (8 byte) integer" +msgstr "Grand entier (8 octets)" + +msgid "Small integer" +msgstr "Petit nombre entier" + +msgid "IPv4 address" +msgstr "Adresse IPv4" + +msgid "IP address" +msgstr "Adresse IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" +"La valeur « %(value)s » doit être None (vide), True (vrai) ou False (faux)." + +msgid "Boolean (Either True, False or None)" +msgstr "Booléen (soit None (vide), True (vrai) ou False (faux))" + +msgid "Positive big integer" +msgstr "Grand nombre entier positif" + +msgid "Positive integer" +msgstr "Nombre entier positif" + +msgid "Positive small integer" +msgstr "Petit nombre entier positif" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (jusqu'à %(max_length)s car.)" + +msgid "Text" +msgstr "Texte" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"Le format de la valeur « %(value)s » n’est pas valide. Le format correct est " +"HH:MM[:ss[.uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"Le format de la valeur « %(value)s » est correct (HH:MM[:ss[.uuuuuu]]), mais " +"l’heure n’est pas valide." + +msgid "Time" +msgstr "Heure" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Données binaires brutes" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "La valeur « %(value)s » n’est pas un UUID valide." + +msgid "Universally unique identifier" +msgstr "Identifiant unique universel" + +msgid "File" +msgstr "Fichier" + +msgid "Image" +msgstr "Image" + +msgid "A JSON object" +msgstr "Un objet JSON" + +msgid "Value must be valid JSON." +msgstr "La valeur doit respecter la syntaxe JSON." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "L’instance %(model)s avec %(value)r dans %(field)s n’existe pas." + +msgid "Foreign Key (type determined by related field)" +msgstr "Clé étrangère (type défini par le champ lié)" + +msgid "One-to-one relationship" +msgstr "Relation un à un" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "Relation %(from)s-%(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "Relations %(from)s-%(to)s" + +msgid "Many-to-many relationship" +msgstr "Relation plusieurs à plusieurs" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Ce champ est obligatoire." + +msgid "Enter a whole number." +msgstr "Saisissez un nombre entier." + +msgid "Enter a valid date." +msgstr "Saisissez une date valide." + +msgid "Enter a valid time." +msgstr "Saisissez une heure valide." + +msgid "Enter a valid date/time." +msgstr "Saisissez une date et une heure valides." + +msgid "Enter a valid duration." +msgstr "Saisissez une durée valide." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Le nombre de jours doit être entre {min_days} et {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" +"Aucun fichier n’a été soumis. Vérifiez le type d’encodage du formulaire." + +msgid "No file was submitted." +msgstr "Aucun fichier n’a été soumis." + +msgid "The submitted file is empty." +msgstr "Le fichier soumis est vide." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Assurez-vous que ce nom de fichier comporte au plus %(max)d caractère " +"(actuellement %(length)d)." +msgstr[1] "" +"Assurez-vous que ce nom de fichier comporte au plus %(max)d caractères " +"(actuellement %(length)d)." +msgstr[2] "" +"Assurez-vous que ce nom de fichier comporte au plus %(max)d caractères " +"(actuellement %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Envoyez un fichier ou cochez la case d’effacement, mais pas les deux." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Téléversez une image valide. Le fichier que vous avez transféré n’est pas " +"une image ou bien est corrompu." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Sélectionnez un choix valide. %(value)s n’en fait pas partie." + +msgid "Enter a list of values." +msgstr "Saisissez une liste de valeurs." + +msgid "Enter a complete value." +msgstr "Saisissez une valeur complète." + +msgid "Enter a valid UUID." +msgstr "Saisissez un UUID valide." + +msgid "Enter a valid JSON." +msgstr "Saisissez du contenu JSON valide." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr " :" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(champ masqué %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"Des données du formulaire ManagementForm sont manquantes ou ont été " +"manipulées. Champs manquants : %(field_names)s. Vous pourriez créer un " +"rapport de bogue si le problème persiste." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Veuillez soumettre au plus %(num)d formulaire." +msgstr[1] "Veuillez soumettre au plus %(num)d formulaires." +msgstr[2] "Veuillez soumettre au plus %(num)d formulaires." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Veuillez soumettre au moins %(num)d formulaire." +msgstr[1] "Veuillez soumettre au moins %(num)d formulaires." +msgstr[2] "Veuillez soumettre au moins %(num)d formulaires." + +msgid "Order" +msgstr "Ordre" + +msgid "Delete" +msgstr "Supprimer" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Corrigez les données en double dans %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Corrigez les données en double dans %(field)s qui doit contenir des valeurs " +"uniques." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Corrigez les données en double dans %(field_name)s qui doit contenir des " +"valeurs uniques pour la partie %(lookup)s de %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Corrigez les valeurs en double ci-dessous." + +msgid "The inline value did not match the parent instance." +msgstr "La valeur en ligne ne correspond pas à l’instance parente." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Sélectionnez un choix valide. Ce choix ne fait pas partie de ceux " +"disponibles." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "« %(pk)s » n’est pas une valeur correcte." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"La valeur %(datetime)s n’a pas pu être interprétée dans le fuseau horaire " +"%(current_timezone)s ; elle est peut-être ambigüe ou elle n’existe pas." + +msgid "Clear" +msgstr "Effacer" + +msgid "Currently" +msgstr "Actuellement" + +msgid "Change" +msgstr "Modifier" + +msgid "Unknown" +msgstr "Inconnu" + +msgid "Yes" +msgstr "Oui" + +msgid "No" +msgstr "Non" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "oui,non,peut-être" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d octet" +msgstr[1] "%(size)d octets" +msgstr[2] "%(size)d octets" + +#, python-format +msgid "%s KB" +msgstr "%s Kio" + +#, python-format +msgid "%s MB" +msgstr "%s Mio" + +#, python-format +msgid "%s GB" +msgstr "%s Gio" + +#, python-format +msgid "%s TB" +msgstr "%s Tio" + +#, python-format +msgid "%s PB" +msgstr "%s Pio" + +msgid "p.m." +msgstr "après-midi" + +msgid "a.m." +msgstr "matin" + +msgid "PM" +msgstr "Après-midi" + +msgid "AM" +msgstr "Matin" + +msgid "midnight" +msgstr "minuit" + +msgid "noon" +msgstr "midi" + +msgid "Monday" +msgstr "lundi" + +msgid "Tuesday" +msgstr "mardi" + +msgid "Wednesday" +msgstr "mercredi" + +msgid "Thursday" +msgstr "jeudi" + +msgid "Friday" +msgstr "vendredi" + +msgid "Saturday" +msgstr "samedi" + +msgid "Sunday" +msgstr "dimanche" + +msgid "Mon" +msgstr "lun" + +msgid "Tue" +msgstr "mar" + +msgid "Wed" +msgstr "mer" + +msgid "Thu" +msgstr "jeu" + +msgid "Fri" +msgstr "ven" + +msgid "Sat" +msgstr "sam" + +msgid "Sun" +msgstr "dim" + +msgid "January" +msgstr "janvier" + +msgid "February" +msgstr "février" + +msgid "March" +msgstr "mars" + +msgid "April" +msgstr "avril" + +msgid "May" +msgstr "mai" + +msgid "June" +msgstr "juin" + +msgid "July" +msgstr "juillet" + +msgid "August" +msgstr "août" + +msgid "September" +msgstr "septembre" + +msgid "October" +msgstr "octobre" + +msgid "November" +msgstr "novembre" + +msgid "December" +msgstr "décembre" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "fév" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "avr" + +msgid "may" +msgstr "mai" + +msgid "jun" +msgstr "jui" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "aoû" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "oct" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "déc" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "fév." + +msgctxt "abbrev. month" +msgid "March" +msgstr "mars" + +msgctxt "abbrev. month" +msgid "April" +msgstr "avr." + +msgctxt "abbrev. month" +msgid "May" +msgstr "mai" + +msgctxt "abbrev. month" +msgid "June" +msgstr "juin" + +msgctxt "abbrev. month" +msgid "July" +msgstr "juil." + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "août" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "sept." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "oct." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "déc." + +msgctxt "alt. month" +msgid "January" +msgstr "Janvier" + +msgctxt "alt. month" +msgid "February" +msgstr "Février" + +msgctxt "alt. month" +msgid "March" +msgstr "Mars" + +msgctxt "alt. month" +msgid "April" +msgstr "Avril" + +msgctxt "alt. month" +msgid "May" +msgstr "Mai" + +msgctxt "alt. month" +msgid "June" +msgstr "Juin" + +msgctxt "alt. month" +msgid "July" +msgstr "Juillet" + +msgctxt "alt. month" +msgid "August" +msgstr "Août" + +msgctxt "alt. month" +msgid "September" +msgstr "Septembre" + +msgctxt "alt. month" +msgid "October" +msgstr "Octobre" + +msgctxt "alt. month" +msgid "November" +msgstr "Novembre" + +msgctxt "alt. month" +msgid "December" +msgstr "Décembre" + +msgid "This is not a valid IPv6 address." +msgstr "Ceci n’est pas une adresse IPv6 valide." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "ou" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d année" +msgstr[1] "%(num)d années" +msgstr[2] "%(num)d années" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mois" +msgstr[1] "%(num)d mois" +msgstr[2] "%(num)d mois" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d semaine" +msgstr[1] "%(num)d semaines" +msgstr[2] "%(num)d semaines" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d jour" +msgstr[1] "%(num)d jours" +msgstr[2] "%(num)d jours" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d heure" +msgstr[1] "%(num)d heures" +msgstr[2] "%(num)d heures" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minute" +msgstr[1] "%(num)d minutes" +msgstr[2] "%(num)d minutes" + +msgid "Forbidden" +msgstr "Interdit" + +msgid "CSRF verification failed. Request aborted." +msgstr "La vérification CSRF a échoué. La requête a été interrompue." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Vous voyez ce message parce que ce site HTTPS exige que le navigateur web " +"envoie un en-tête « Referer », ce qu’il n'a pas fait. Cet en-tête est exigé " +"pour des raisons de sécurité, afin de s’assurer que le navigateur n’ait pas " +"été piraté par un intervenant externe." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Si vous avez désactivé l’envoi des en-têtes « Referer » par votre " +"navigateur, veuillez les réactiver, au moins pour ce site ou pour les " +"connexions HTTPS, ou encore pour les requêtes de même origine (« same-" +"origin »)." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Si vous utilisez la balise " +"ou que vous incluez l’en-tête « Referrer-Policy: no-referrer », il est " +"préférable de les enlever. La protection CSRF exige que l’en-tête " +"``Referer`` effectue un contrôle de référant strict. Si vous vous souciez de " +"la confidentialité, utilisez des alternatives comme " +"pour les liens vers des sites tiers." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Vous voyez ce message parce que ce site exige la présence d’un cookie CSRF " +"lors de l’envoi de formulaires. Ce cookie est nécessaire pour des raisons de " +"sécurité, afin de s’assurer que le navigateur n’ait pas été piraté par un " +"intervenant externe." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Si vous avez désactivé l’envoi des cookies par votre navigateur, veuillez " +"les réactiver au moins pour ce site ou pour les requêtes de même origine (« " +"same-origin »)." + +msgid "More information is available with DEBUG=True." +msgstr "" +"Des informations plus détaillées sont affichées lorsque la variable DEBUG " +"vaut True." + +msgid "No year specified" +msgstr "Aucune année indiquée" + +msgid "Date out of range" +msgstr "Date hors limites" + +msgid "No month specified" +msgstr "Aucun mois indiqué" + +msgid "No day specified" +msgstr "Aucun jour indiqué" + +msgid "No week specified" +msgstr "Aucune semaine indiquée" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Pas de %(verbose_name_plural)s disponible" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Pas de %(verbose_name_plural)s disponible dans le futur car %(class_name)s." +"allow_future est faux (False)." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" +"Le format « %(format)s » appliqué à la chaîne date « %(datestr)s » n’est pas " +"valide" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Aucun objet %(verbose_name)s trouvé en réponse à la requête" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" +"La page n’est pas la « dernière », elle ne peut pas non plus être convertie " +"en nombre entier." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Page non valide (%(page_number)s) : %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Liste vide et « %(class_name)s.allow_empty » est faux (False)." + +msgid "Directory indexes are not allowed here." +msgstr "Il n’est pas autorisé d’afficher le contenu de ce répertoire." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "« %(path)s » n’existe pas" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Index de %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "L’installation s’est déroulée avec succès. Félicitations !" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Afficher les notes de publication de " +"Django %(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Vous voyez cette page parce que votre fichier de réglages contient DEBUG=True et que vous n’avez pas " +"encore configuré d’URL." + +msgid "Django Documentation" +msgstr "Documentation de Django" + +msgid "Topics, references, & how-to’s" +msgstr "Thématiques, références et guides pratiques" + +msgid "Tutorial: A Polling App" +msgstr "Tutoriel : une application de sondage" + +msgid "Get started with Django" +msgstr "Premiers pas avec Django" + +msgid "Django Community" +msgstr "Communauté Django" + +msgid "Connect, get help, or contribute" +msgstr "Se connecter, obtenir de l’aide ou contribuer" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr/formats.py new file mode 100644 index 0000000..338d8ad --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr/formats.py @@ -0,0 +1,27 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j F Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = "j F Y H:i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "d/m/Y" +SHORT_DATETIME_FORMAT = "d/m/Y H:i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d/%m/%Y", # '25/10/2006' + "%d/%m/%y", # '25/10/06' +] +DATETIME_INPUT_FORMATS = [ + "%d/%m/%Y %H:%M:%S", # '25/10/2006 14:30:59' + "%d/%m/%Y %H:%M:%S.%f", # '25/10/2006 14:30:59.000200' + "%d/%m/%Y %H:%M", # '25/10/2006 14:30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "\xa0" # non-breaking space +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr_BE/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr_BE/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr_BE/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr_BE/formats.py new file mode 100644 index 0000000..84f0657 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr_BE/formats.py @@ -0,0 +1,32 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j F Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = "j F Y H:i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "d.m.Y" +SHORT_DATETIME_FORMAT = "d.m.Y H:i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d.%m.%Y", # '25.10.2006' + "%d.%m.%y", # '25.10.06' + "%d/%m/%Y", # '25/10/2006' + "%d/%m/%y", # '25/10/06' +] +DATETIME_INPUT_FORMATS = [ + "%d.%m.%Y %H:%M:%S", # '25.10.2006 14:30:59' + "%d.%m.%Y %H:%M:%S.%f", # '25.10.2006 14:30:59.000200' + "%d.%m.%Y %H:%M", # '25.10.2006 14:30' + "%d/%m/%Y %H:%M:%S", # '25/10/2006 14:30:59' + "%d/%m/%Y %H:%M:%S.%f", # '25/10/2006 14:30:59.000200' + "%d/%m/%Y %H:%M", # '25/10/2006 14:30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "\xa0" # non-breaking space +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr_CA/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr_CA/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr_CA/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr_CA/formats.py new file mode 100644 index 0000000..b03e4ee --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr_CA/formats.py @@ -0,0 +1,30 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j F Y" # 31 janvier 2024 +TIME_FORMAT = "H\xa0h\xa0i" # 13 h 40 +DATETIME_FORMAT = "j F Y, H\xa0h\xa0i" # 31 janvier 2024, 13 h 40 +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "Y-m-d" +SHORT_DATETIME_FORMAT = "Y-m-d H\xa0h\xa0i" +FIRST_DAY_OF_WEEK = 1 # Lundi + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%Y-%m-%d", # '2006-05-15' + "%y-%m-%d", # '06-05-15' +] +DATETIME_INPUT_FORMATS = [ + "%Y-%m-%d %H:%M:%S", # '2006-05-15 14:30:57' + "%y-%m-%d %H:%M:%S", # '06-05-15 14:30:57' + "%Y-%m-%d %H:%M:%S.%f", # '2006-05-15 14:30:57.000200' + "%y-%m-%d %H:%M:%S.%f", # '06-05-15 14:30:57.000200' + "%Y-%m-%d %H:%M", # '2006-05-15 14:30' + "%y-%m-%d %H:%M", # '06-05-15 14:30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "\xa0" # non-breaking space +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr_CH/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr_CH/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr_CH/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr_CH/formats.py new file mode 100644 index 0000000..84f0657 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fr_CH/formats.py @@ -0,0 +1,32 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j F Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = "j F Y H:i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "d.m.Y" +SHORT_DATETIME_FORMAT = "d.m.Y H:i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d.%m.%Y", # '25.10.2006' + "%d.%m.%y", # '25.10.06' + "%d/%m/%Y", # '25/10/2006' + "%d/%m/%y", # '25/10/06' +] +DATETIME_INPUT_FORMATS = [ + "%d.%m.%Y %H:%M:%S", # '25.10.2006 14:30:59' + "%d.%m.%Y %H:%M:%S.%f", # '25.10.2006 14:30:59.000200' + "%d.%m.%Y %H:%M", # '25.10.2006 14:30' + "%d/%m/%Y %H:%M:%S", # '25/10/2006 14:30:59' + "%d/%m/%Y %H:%M:%S.%f", # '25/10/2006 14:30:59.000200' + "%d/%m/%Y %H:%M", # '25/10/2006 14:30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "\xa0" # non-breaking space +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2eff5df Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fy/LC_MESSAGES/django.po new file mode 100644 index 0000000..172f283 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fy/LC_MESSAGES/django.po @@ -0,0 +1,1218 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Western Frisian (http://www.transifex.com/django/django/" +"language/fy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fy\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "" + +msgid "Arabic" +msgstr "" + +msgid "Asturian" +msgstr "" + +msgid "Azerbaijani" +msgstr "" + +msgid "Bulgarian" +msgstr "" + +msgid "Belarusian" +msgstr "" + +msgid "Bengali" +msgstr "" + +msgid "Breton" +msgstr "" + +msgid "Bosnian" +msgstr "" + +msgid "Catalan" +msgstr "" + +msgid "Czech" +msgstr "" + +msgid "Welsh" +msgstr "" + +msgid "Danish" +msgstr "" + +msgid "German" +msgstr "" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "" + +msgid "English" +msgstr "" + +msgid "Australian English" +msgstr "" + +msgid "British English" +msgstr "" + +msgid "Esperanto" +msgstr "" + +msgid "Spanish" +msgstr "" + +msgid "Argentinian Spanish" +msgstr "" + +msgid "Colombian Spanish" +msgstr "" + +msgid "Mexican Spanish" +msgstr "" + +msgid "Nicaraguan Spanish" +msgstr "" + +msgid "Venezuelan Spanish" +msgstr "" + +msgid "Estonian" +msgstr "" + +msgid "Basque" +msgstr "" + +msgid "Persian" +msgstr "" + +msgid "Finnish" +msgstr "" + +msgid "French" +msgstr "" + +msgid "Frisian" +msgstr "" + +msgid "Irish" +msgstr "" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "" + +msgid "Hebrew" +msgstr "" + +msgid "Hindi" +msgstr "" + +msgid "Croatian" +msgstr "" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "" + +msgid "Indonesian" +msgstr "" + +msgid "Ido" +msgstr "" + +msgid "Icelandic" +msgstr "" + +msgid "Italian" +msgstr "" + +msgid "Japanese" +msgstr "" + +msgid "Georgian" +msgstr "" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "" + +msgid "Khmer" +msgstr "" + +msgid "Kannada" +msgstr "" + +msgid "Korean" +msgstr "" + +msgid "Luxembourgish" +msgstr "" + +msgid "Lithuanian" +msgstr "" + +msgid "Latvian" +msgstr "" + +msgid "Macedonian" +msgstr "" + +msgid "Malayalam" +msgstr "" + +msgid "Mongolian" +msgstr "" + +msgid "Marathi" +msgstr "" + +msgid "Burmese" +msgstr "" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "" + +msgid "Dutch" +msgstr "" + +msgid "Norwegian Nynorsk" +msgstr "" + +msgid "Ossetic" +msgstr "" + +msgid "Punjabi" +msgstr "" + +msgid "Polish" +msgstr "" + +msgid "Portuguese" +msgstr "" + +msgid "Brazilian Portuguese" +msgstr "" + +msgid "Romanian" +msgstr "" + +msgid "Russian" +msgstr "" + +msgid "Slovak" +msgstr "" + +msgid "Slovenian" +msgstr "" + +msgid "Albanian" +msgstr "" + +msgid "Serbian" +msgstr "" + +msgid "Serbian Latin" +msgstr "" + +msgid "Swedish" +msgstr "" + +msgid "Swahili" +msgstr "" + +msgid "Tamil" +msgstr "" + +msgid "Telugu" +msgstr "" + +msgid "Thai" +msgstr "" + +msgid "Turkish" +msgstr "" + +msgid "Tatar" +msgstr "" + +msgid "Udmurt" +msgstr "" + +msgid "Ukrainian" +msgstr "" + +msgid "Urdu" +msgstr "" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "" + +msgid "Simplified Chinese" +msgstr "" + +msgid "Traditional Chinese" +msgstr "" + +msgid "Messages" +msgstr "" + +msgid "Site Maps" +msgstr "" + +msgid "Static Files" +msgstr "" + +msgid "Syndication" +msgstr "" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "Jou in falide wearde." + +msgid "Enter a valid URL." +msgstr "Jou in falide URL." + +msgid "Enter a valid integer." +msgstr "" + +msgid "Enter a valid email address." +msgstr "" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Jou in falide IPv4-adres." + +msgid "Enter a valid IPv6 address." +msgstr "" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "" + +msgid "Enter only digits separated by commas." +msgstr "Jou allinnich sifers, skieden troch komma's." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Enter a number." +msgstr "Jou in nûmer." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "Dit fjild kin net leech wêze." + +msgid "This field cannot be blank." +msgstr "" + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s mei dit %(field_label)s bestiet al." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "" + +msgid "Comma-separated integers" +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "" + +msgid "Email address" +msgstr "" + +msgid "File path" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "" + +msgid "Big (8 byte) integer" +msgstr "" + +msgid "IPv4 address" +msgstr "" + +msgid "IP address" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "" + +msgid "Positive integer" +msgstr "" + +msgid "Positive small integer" +msgstr "" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "" + +msgid "Small integer" +msgstr "" + +msgid "Text" +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "" + +msgid "URL" +msgstr "" + +msgid "Raw binary data" +msgstr "" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "" + +msgid "Image" +msgstr "" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "" + +msgid "One-to-one relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr "" + +msgid "This field is required." +msgstr "Dit fjild is fereaske." + +msgid "Enter a whole number." +msgstr "Jou in folslein nûmer." + +msgid "Enter a valid date." +msgstr "Jou in falide datum." + +msgid "Enter a valid time." +msgstr "Jou in falide tiid." + +msgid "Enter a valid date/time." +msgstr "Jou in falide datum.tiid." + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" +"Der is gjin bestân yntsjinne. Kontrolearje it kodearringstype op it " +"formulier." + +msgid "No file was submitted." +msgstr "Der is gjin bestân yntsjinne." + +msgid "The submitted file is empty." +msgstr "It yntsjinne bestân is leech." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Laad in falide ôfbylding op. It bestân dy't jo opladen hawwe wie net in " +"ôfbylding of in skansearre ôfbylding." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Selektearje in falide kar. %(value)s is net ien fan de beskikbere karren." + +msgid "Enter a list of values." +msgstr "Jou in list mei weardes." + +msgid "Enter a complete value." +msgstr "" + +msgid "Enter a valid UUID." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr "" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "Oarder" + +msgid "Delete" +msgstr "" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "" + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" + +msgid "Please correct the duplicate values below." +msgstr "" + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Selektearje in falide kar. Dizze kar is net ien fan de beskikbere karren." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "" + +msgid "Currently" +msgstr "" + +msgid "Change" +msgstr "" + +msgid "Unknown" +msgstr "" + +msgid "Yes" +msgstr "" + +msgid "No" +msgstr "" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%s KB" +msgstr "" + +#, python-format +msgid "%s MB" +msgstr "" + +#, python-format +msgid "%s GB" +msgstr "" + +#, python-format +msgid "%s TB" +msgstr "" + +#, python-format +msgid "%s PB" +msgstr "" + +msgid "p.m." +msgstr "" + +msgid "a.m." +msgstr "" + +msgid "PM" +msgstr "" + +msgid "AM" +msgstr "" + +msgid "midnight" +msgstr "" + +msgid "noon" +msgstr "" + +msgid "Monday" +msgstr "" + +msgid "Tuesday" +msgstr "" + +msgid "Wednesday" +msgstr "" + +msgid "Thursday" +msgstr "" + +msgid "Friday" +msgstr "" + +msgid "Saturday" +msgstr "" + +msgid "Sunday" +msgstr "" + +msgid "Mon" +msgstr "" + +msgid "Tue" +msgstr "" + +msgid "Wed" +msgstr "" + +msgid "Thu" +msgstr "" + +msgid "Fri" +msgstr "" + +msgid "Sat" +msgstr "" + +msgid "Sun" +msgstr "" + +msgid "January" +msgstr "" + +msgid "February" +msgstr "" + +msgid "March" +msgstr "" + +msgid "April" +msgstr "" + +msgid "May" +msgstr "" + +msgid "June" +msgstr "" + +msgid "July" +msgstr "" + +msgid "August" +msgstr "" + +msgid "September" +msgstr "" + +msgid "October" +msgstr "" + +msgid "November" +msgstr "" + +msgid "December" +msgstr "" + +msgid "jan" +msgstr "" + +msgid "feb" +msgstr "" + +msgid "mar" +msgstr "" + +msgid "apr" +msgstr "" + +msgid "may" +msgstr "" + +msgid "jun" +msgstr "" + +msgid "jul" +msgstr "" + +msgid "aug" +msgstr "" + +msgid "sep" +msgstr "" + +msgid "oct" +msgstr "" + +msgid "nov" +msgstr "" + +msgid "dec" +msgstr "" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "" + +msgctxt "abbrev. month" +msgid "March" +msgstr "" + +msgctxt "abbrev. month" +msgid "April" +msgstr "" + +msgctxt "abbrev. month" +msgid "May" +msgstr "" + +msgctxt "abbrev. month" +msgid "June" +msgstr "" + +msgctxt "abbrev. month" +msgid "July" +msgstr "" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "" + +msgctxt "alt. month" +msgid "January" +msgstr "" + +msgctxt "alt. month" +msgid "February" +msgstr "" + +msgctxt "alt. month" +msgid "March" +msgstr "" + +msgctxt "alt. month" +msgid "April" +msgstr "" + +msgctxt "alt. month" +msgid "May" +msgstr "" + +msgctxt "alt. month" +msgid "June" +msgstr "" + +msgctxt "alt. month" +msgid "July" +msgstr "" + +msgctxt "alt. month" +msgid "August" +msgstr "" + +msgctxt "alt. month" +msgid "September" +msgstr "" + +msgctxt "alt. month" +msgid "October" +msgstr "" + +msgctxt "alt. month" +msgid "November" +msgstr "" + +msgctxt "alt. month" +msgid "December" +msgstr "" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "" + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" + +msgid "0 minutes" +msgstr "" + +msgid "Forbidden" +msgstr "" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "" + +msgid "No day specified" +msgstr "" + +msgid "No week specified" +msgstr "" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "" + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fy/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fy/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fy/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fy/formats.py new file mode 100644 index 0000000..3825be4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/fy/formats.py @@ -0,0 +1,21 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +# DATE_FORMAT = +# TIME_FORMAT = +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +# MONTH_DAY_FORMAT = +# SHORT_DATE_FORMAT = +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +# DECIMAL_SEPARATOR = +# THOUSAND_SEPARATOR = +# NUMBER_GROUPING = diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ga/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ga/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c2a8a88 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ga/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ga/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ga/LC_MESSAGES/django.po new file mode 100644 index 0000000..2b1b528 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ga/LC_MESSAGES/django.po @@ -0,0 +1,1293 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Claude Paroz , 2020 +# Jannis Leidel , 2011 +# John Moylan , 2013 +# John Stafford , 2013 +# Seán de Búrca , 2011 +# Luke Blaney , 2019 +# Michael Thornhill , 2011-2012,2015 +# Séamus Ó Cúile , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-19 20:23+0200\n" +"PO-Revision-Date: 2020-07-14 21:42+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Irish (http://www.transifex.com/django/django/language/ga/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ga\n" +"Plural-Forms: nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : " +"4);\n" + +msgid "Afrikaans" +msgstr "Afracáinis" + +msgid "Arabic" +msgstr "Araibis" + +msgid "Algerian Arabic" +msgstr "" + +msgid "Asturian" +msgstr "Astúiris" + +msgid "Azerbaijani" +msgstr "Asarbaiseáinis" + +msgid "Bulgarian" +msgstr "Bulgáiris" + +msgid "Belarusian" +msgstr "Bealarúisis" + +msgid "Bengali" +msgstr "Beangáilis" + +msgid "Breton" +msgstr "Briotánach" + +msgid "Bosnian" +msgstr "Boisnis" + +msgid "Catalan" +msgstr "Catalóinis" + +msgid "Czech" +msgstr "Seicis" + +msgid "Welsh" +msgstr "Breatnais" + +msgid "Danish" +msgstr "Danmhairgis " + +msgid "German" +msgstr "Gearmáinis" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "Gréigis" + +msgid "English" +msgstr "Béarla" + +msgid "Australian English" +msgstr "Béarla Astrálach" + +msgid "British English" +msgstr "Béarla na Breataine" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Spáinnis" + +msgid "Argentinian Spanish" +msgstr "Spáinnis na hAirgintíne" + +msgid "Colombian Spanish" +msgstr "" + +msgid "Mexican Spanish" +msgstr "Spáinnis Mheicsiceo " + +msgid "Nicaraguan Spanish" +msgstr "Spáinnis Nicearagua" + +msgid "Venezuelan Spanish" +msgstr "Spáinnis Veiniséalach" + +msgid "Estonian" +msgstr "Eastóinis" + +msgid "Basque" +msgstr "Bascais" + +msgid "Persian" +msgstr "Peirsis" + +msgid "Finnish" +msgstr "Fionlainnis" + +msgid "French" +msgstr "Fraincis" + +msgid "Frisian" +msgstr "Freaslainnis" + +msgid "Irish" +msgstr "Gaeilge" + +msgid "Scottish Gaelic" +msgstr "Gaeilge na hAlban" + +msgid "Galician" +msgstr "Gailísis" + +msgid "Hebrew" +msgstr "Eabhrais" + +msgid "Hindi" +msgstr "Hiondúis" + +msgid "Croatian" +msgstr "Cróitis" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "Ungáiris" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indinéisis" + +msgid "Igbo" +msgstr "" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Íoslainnis" + +msgid "Italian" +msgstr "Iodáilis" + +msgid "Japanese" +msgstr "Seapáinis" + +msgid "Georgian" +msgstr "Seoirsis" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "Casaicis" + +msgid "Khmer" +msgstr "Ciméiris" + +msgid "Kannada" +msgstr "Cannadais" + +msgid "Korean" +msgstr "Cóiréis" + +msgid "Kyrgyz" +msgstr "" + +msgid "Luxembourgish" +msgstr "Lucsamburgach" + +msgid "Lithuanian" +msgstr "Liotuáinis" + +msgid "Latvian" +msgstr "Laitvis" + +msgid "Macedonian" +msgstr "Macadóinis" + +msgid "Malayalam" +msgstr "Mailéalaimis" + +msgid "Mongolian" +msgstr "Mongóilis" + +msgid "Marathi" +msgstr "Maraitis" + +msgid "Burmese" +msgstr "Burmais" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "Neipeailis" + +msgid "Dutch" +msgstr "Ollainnis" + +msgid "Norwegian Nynorsk" +msgstr "Ioruais Nynorsk" + +msgid "Ossetic" +msgstr "Oiséitis" + +msgid "Punjabi" +msgstr "Puinseáibis" + +msgid "Polish" +msgstr "Polainnis" + +msgid "Portuguese" +msgstr "Portaingéilis" + +msgid "Brazilian Portuguese" +msgstr "Portaingéilis na Brasaíle" + +msgid "Romanian" +msgstr "Rómáinis" + +msgid "Russian" +msgstr "Rúisis" + +msgid "Slovak" +msgstr "Slóvaicis" + +msgid "Slovenian" +msgstr "Slóivéinis" + +msgid "Albanian" +msgstr "Albáinis" + +msgid "Serbian" +msgstr "Seirbis" + +msgid "Serbian Latin" +msgstr "Seirbis (Laidineach)" + +msgid "Swedish" +msgstr "Sualainnis" + +msgid "Swahili" +msgstr "" + +msgid "Tamil" +msgstr "Tamailis" + +msgid "Telugu" +msgstr "Teileagúis" + +msgid "Tajik" +msgstr "" + +msgid "Thai" +msgstr "Téalainnis" + +msgid "Turkmen" +msgstr "" + +msgid "Turkish" +msgstr "Tuircis" + +msgid "Tatar" +msgstr "" + +msgid "Udmurt" +msgstr "" + +msgid "Ukrainian" +msgstr "Úcráinis" + +msgid "Urdu" +msgstr "Urdais" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "Vítneamais" + +msgid "Simplified Chinese" +msgstr "Sínis Simplithe" + +msgid "Traditional Chinese" +msgstr "Sínis Traidisiúnta" + +msgid "Messages" +msgstr "Teachtaireachtaí" + +msgid "Site Maps" +msgstr "" + +msgid "Static Files" +msgstr "Comhaid Statach" + +msgid "Syndication" +msgstr "Sindeacáitiú" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "Iontráil luach bailí" + +msgid "Enter a valid URL." +msgstr "Iontráil URL bailí." + +msgid "Enter a valid integer." +msgstr "" + +msgid "Enter a valid email address." +msgstr "" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Iontráil seoladh IPv4 bailí." + +msgid "Enter a valid IPv6 address." +msgstr "Cuir seoladh bailí IPv6 isteach." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Cuir seoladh bailí IPv4 nó IPv6 isteach." + +msgid "Enter only digits separated by commas." +msgstr "Ná hiontráil ach digití atá deighilte le camóga." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Cinntigh go bhfuil an luach seo %(limit_value)s (tá sé %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" +"Cinntigh go bhfuil an luach seo níos lú ná nó cothrom le %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" +"Cinntigh go bhfuil an luach seo níos mó ná nó cothrom le %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +msgid "Enter a number." +msgstr "Iontráil uimhir." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "agus" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "Ní cheadaítear luach nialasach sa réimse seo." + +msgid "This field cannot be blank." +msgstr "Ní cheadaítear luach nialasach sa réimse seo." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "Tá %(model_name)s leis an %(field_label)s seo ann cheana." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Réimse de Cineál: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "Boole" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Teaghrán (suas go %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "Slánuimhireacha camóg-scartha" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "Dáta (gan am)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Dáta (le am)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Uimhir deachúlach" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "Fad" + +msgid "Email address" +msgstr "R-phost" + +msgid "File path" +msgstr "Conair comhaid" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "Snámhphointe" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "Slánuimhir" + +msgid "Big (8 byte) integer" +msgstr "Mór (8 byte) slánuimhi" + +msgid "IPv4 address" +msgstr "Seoladh IPv4" + +msgid "IP address" +msgstr "Seoladh IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "Boole (Fíor, Bréagach nó Dada)" + +msgid "Positive big integer" +msgstr "" + +msgid "Positive integer" +msgstr "Slánuimhir dearfach" + +msgid "Positive small integer" +msgstr "Slánuimhir beag dearfach" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (suas go %(max_length)s)" + +msgid "Small integer" +msgstr "Slánuimhir beag" + +msgid "Text" +msgstr "Téacs" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Am" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "Comhaid" + +msgid "Image" +msgstr "Íomhá" + +msgid "A JSON object" +msgstr "" + +msgid "Value must be valid JSON." +msgstr "" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "Eochair Eachtracha (cineál a chinnfear de réir réimse a bhaineann)" + +msgid "One-to-one relationship" +msgstr "Duine-le-duine caidreamh" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "Go leor le go leor caidreamh" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Tá an réimse seo riachtanach." + +msgid "Enter a whole number." +msgstr "Iontráil slánuimhir." + +msgid "Enter a valid date." +msgstr "Iontráil dáta bailí." + +msgid "Enter a valid time." +msgstr "Iontráil am bailí." + +msgid "Enter a valid date/time." +msgstr "Iontráil dáta/am bailí." + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Níor seoladh comhad. Deimhnigh cineál an ionchódaithe ar an bhfoirm." + +msgid "No file was submitted." +msgstr "Níor seoladh aon chomhad." + +msgid "The submitted file is empty." +msgstr "Tá an comhad a seoladh folamh." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Cuir ceachtar isteach comhad nó an ticbhosca soiléir, ní féidir an dá " +"sheiceáil." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Uasluchtaigh íomhá bhailí. Níorbh íomhá é an comhad a d'uasluchtaigh tú, nó " +"b'íomhá thruaillithe é." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Déan rogha bhailí. Ní ceann de na roghanna é %(value)s." + +msgid "Enter a list of values." +msgstr "Cuir liosta de luachanna isteach." + +msgid "Enter a complete value." +msgstr "" + +msgid "Enter a valid UUID." +msgstr "" + +msgid "Enter a valid JSON." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +msgid "Order" +msgstr "Ord" + +msgid "Delete" +msgstr "Scrios" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Le do thoil ceartaigh an sonra dúbail le %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Ceart le do thoil na sonraí a dhúbailt le haghaidh %(field)s, chaithfidh a " +"bheith uathúil." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Ceart le do thoil na sonraí a dhúbailt le haghaidh %(field_name)s ní mór a " +"bheith uaithúil le haghaidh an %(lookup)s i %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Le do thoil ceartaigh na luachanna dúbail thíos." + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Déan rogha bhailí. Ní ceann de na roghanna é do roghasa." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Glan" + +msgid "Currently" +msgstr "Faoi láthair" + +msgid "Change" +msgstr "Athraigh" + +msgid "Unknown" +msgstr "Anaithnid" + +msgid "Yes" +msgstr "Tá" + +msgid "No" +msgstr "Níl" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "tá,níl,b'fhéidir" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d bheart" +msgstr[1] "%(size)d bheart" +msgstr[2] "%(size)d bheart" +msgstr[3] "%(size)d mbeart" +msgstr[4] "%(size)d beart" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "i.n." + +msgid "a.m." +msgstr "r.n." + +msgid "PM" +msgstr "IN" + +msgid "AM" +msgstr "RN" + +msgid "midnight" +msgstr "meán oíche" + +msgid "noon" +msgstr "nóin" + +msgid "Monday" +msgstr "Dé Luain" + +msgid "Tuesday" +msgstr "Dé Máirt" + +msgid "Wednesday" +msgstr "Dé Céadaoin" + +msgid "Thursday" +msgstr "Déardaoin" + +msgid "Friday" +msgstr "Dé hAoine" + +msgid "Saturday" +msgstr "Dé Sathairn" + +msgid "Sunday" +msgstr "Dé Domhnaigh" + +msgid "Mon" +msgstr "L" + +msgid "Tue" +msgstr "M" + +msgid "Wed" +msgstr "C" + +msgid "Thu" +msgstr "D" + +msgid "Fri" +msgstr "A" + +msgid "Sat" +msgstr "S" + +msgid "Sun" +msgstr "D" + +msgid "January" +msgstr "Eanáir" + +msgid "February" +msgstr "Feabhra" + +msgid "March" +msgstr "Márta" + +msgid "April" +msgstr "Aibreán" + +msgid "May" +msgstr "Bealtaine" + +msgid "June" +msgstr "Meitheamh" + +msgid "July" +msgstr "Iúil" + +msgid "August" +msgstr "Lúnasa" + +msgid "September" +msgstr "Meán Fómhair" + +msgid "October" +msgstr "Deireadh Fómhair" + +msgid "November" +msgstr "Samhain" + +msgid "December" +msgstr "Nollaig" + +msgid "jan" +msgstr "ean" + +msgid "feb" +msgstr "feabh" + +msgid "mar" +msgstr "márta" + +msgid "apr" +msgstr "aib" + +msgid "may" +msgstr "beal" + +msgid "jun" +msgstr "meith" + +msgid "jul" +msgstr "iúil" + +msgid "aug" +msgstr "lún" + +msgid "sep" +msgstr "mfómh" + +msgid "oct" +msgstr "dfómh" + +msgid "nov" +msgstr "samh" + +msgid "dec" +msgstr "noll" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Ean." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feabh." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Márta" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Aib." + +msgctxt "abbrev. month" +msgid "May" +msgstr "Beal." + +msgctxt "abbrev. month" +msgid "June" +msgstr "Meith." + +msgctxt "abbrev. month" +msgid "July" +msgstr "Iúil" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Lún." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "MFómh." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "DFómh." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Samh." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Noll." + +msgctxt "alt. month" +msgid "January" +msgstr "Mí Eanáir" + +msgctxt "alt. month" +msgid "February" +msgstr "Mí Feabhra" + +msgctxt "alt. month" +msgid "March" +msgstr "Mí na Márta" + +msgctxt "alt. month" +msgid "April" +msgstr "Mí Aibreáin" + +msgctxt "alt. month" +msgid "May" +msgstr "Mí na Bealtaine" + +msgctxt "alt. month" +msgid "June" +msgstr "Mí an Mheithimh" + +msgctxt "alt. month" +msgid "July" +msgstr "Mí Iúil" + +msgctxt "alt. month" +msgid "August" +msgstr "Mí Lúnasa" + +msgctxt "alt. month" +msgid "September" +msgstr "Mí Mheán Fómhair" + +msgctxt "alt. month" +msgid "October" +msgstr "Mí Dheireadh Fómhair" + +msgctxt "alt. month" +msgid "November" +msgstr "Mí na Samhna" + +msgctxt "alt. month" +msgid "December" +msgstr "Mí na Nollag" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "nó" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d nóiméad" +msgstr[1] "%d nóiméad" +msgstr[2] "%d nóiméad" +msgstr[3] "%d nóiméad" +msgstr[4] "%d nóiméad" + +msgid "Forbidden" +msgstr "Toirmiscthe" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "Tá tuilleadh eolais ar fáil le DEBUG=True." + +msgid "No year specified" +msgstr "Bliain gan sonrú" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "Mí gan sonrú" + +msgid "No day specified" +msgstr "Lá gan sonrú" + +msgid "No week specified" +msgstr "Seachtain gan sonrú" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Gan %(verbose_name_plural)s ar fáil" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Níl %(verbose_name_plural)s sa todhchaí ar fáil mar tá %(class_name)s." +"allow_future Bréagach." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Níl bhfuarthas %(verbose_name)s le hadhaigh an iarratas" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Leathanach neamhbhailí (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Níl innéacsanna chomhadlann cheadaítear anseo." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Innéacs de %(directory)s" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "Tosaigh le Django" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ga/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ga/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ga/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ga/formats.py new file mode 100644 index 0000000..7cde1a5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ga/formats.py @@ -0,0 +1,21 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j F Y" +TIME_FORMAT = "H:i" +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "j M Y" +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = "." +THOUSAND_SEPARATOR = "," +# NUMBER_GROUPING = diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/gd/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/gd/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f177bbd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/gd/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/gd/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/gd/LC_MESSAGES/django.po new file mode 100644 index 0000000..ba28564 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/gd/LC_MESSAGES/django.po @@ -0,0 +1,1386 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Michael Bauer, 2014 +# GunChleoc, 2015-2017,2021 +# GunChleoc, 2015 +# GunChleoc, 2014-2015 +# Michael Bauer, 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2021-11-20 14:00+0000\n" +"Last-Translator: GunChleoc\n" +"Language-Team: Gaelic, Scottish (http://www.transifex.com/django/django/" +"language/gd/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: gd\n" +"Plural-Forms: nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : " +"(n > 2 && n < 20) ? 2 : 3;\n" + +msgid "Afrikaans" +msgstr "Afraganais" + +msgid "Arabic" +msgstr "Arabais" + +msgid "Algerian Arabic" +msgstr "Arabais Aildireach" + +msgid "Asturian" +msgstr "Astùrais" + +msgid "Azerbaijani" +msgstr "Asarbaideànais" + +msgid "Bulgarian" +msgstr "Bulgarais" + +msgid "Belarusian" +msgstr "Bealaruisis" + +msgid "Bengali" +msgstr "Beangailis" + +msgid "Breton" +msgstr "Breatnais" + +msgid "Bosnian" +msgstr "Bosnais" + +msgid "Catalan" +msgstr "Catalanais" + +msgid "Czech" +msgstr "Seacais" + +msgid "Welsh" +msgstr "Cuimris" + +msgid "Danish" +msgstr "Danmhairgis" + +msgid "German" +msgstr "Gearmailtis" + +msgid "Lower Sorbian" +msgstr "Sòrbais Ìochdarach" + +msgid "Greek" +msgstr "Greugais" + +msgid "English" +msgstr "Beurla" + +msgid "Australian English" +msgstr "Beurla Astràilia" + +msgid "British English" +msgstr "Beurla Bhreatainn" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Spàinntis" + +msgid "Argentinian Spanish" +msgstr "Spàinntis na h-Argantaine" + +msgid "Colombian Spanish" +msgstr "Spàinntis Choloimbia" + +msgid "Mexican Spanish" +msgstr "Spàinntis Mheagsagach" + +msgid "Nicaraguan Spanish" +msgstr "Spàinntis Niocaragua" + +msgid "Venezuelan Spanish" +msgstr "Spàinntis na Bheiniseala" + +msgid "Estonian" +msgstr "Eastoinis" + +msgid "Basque" +msgstr "Basgais" + +msgid "Persian" +msgstr "Farsaidh" + +msgid "Finnish" +msgstr "Fionnlannais" + +msgid "French" +msgstr "Fraingis" + +msgid "Frisian" +msgstr "Frìsis" + +msgid "Irish" +msgstr "Gaeilge" + +msgid "Scottish Gaelic" +msgstr "Gàidhlig" + +msgid "Galician" +msgstr "Gailìsis" + +msgid "Hebrew" +msgstr "Eabhra" + +msgid "Hindi" +msgstr "Hindis" + +msgid "Croatian" +msgstr "Cròthaisis" + +msgid "Upper Sorbian" +msgstr "Sòrbais Uachdarach" + +msgid "Hungarian" +msgstr "Ungairis" + +msgid "Armenian" +msgstr "Airmeinis" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Innd-Innsis" + +msgid "Igbo" +msgstr "Igbo" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Innis Tìlis" + +msgid "Italian" +msgstr "Eadailtis" + +msgid "Japanese" +msgstr "Seapanais" + +msgid "Georgian" +msgstr "Cairtbheilis" + +msgid "Kabyle" +msgstr "Kabyle" + +msgid "Kazakh" +msgstr "Casachais" + +msgid "Khmer" +msgstr "Cmèar" + +msgid "Kannada" +msgstr "Kannada" + +msgid "Korean" +msgstr "Coirèanais" + +msgid "Kyrgyz" +msgstr "Cìorgasais" + +msgid "Luxembourgish" +msgstr "Lugsamburgais" + +msgid "Lithuanian" +msgstr "Liotuainis" + +msgid "Latvian" +msgstr "Laitbheis" + +msgid "Macedonian" +msgstr "Masadonais" + +msgid "Malayalam" +msgstr "Malayalam" + +msgid "Mongolian" +msgstr "Mongolais" + +msgid "Marathi" +msgstr "Marathi" + +msgid "Malay" +msgstr "Malaidhis" + +msgid "Burmese" +msgstr "Burmais" + +msgid "Norwegian Bokmål" +msgstr "Nirribhis (Bokmål)" + +msgid "Nepali" +msgstr "Neapàlais" + +msgid "Dutch" +msgstr "Duitsis" + +msgid "Norwegian Nynorsk" +msgstr "Nirribhis (Nynorsk)" + +msgid "Ossetic" +msgstr "Ossetic" + +msgid "Punjabi" +msgstr "Panjabi" + +msgid "Polish" +msgstr "Pòlainnis" + +msgid "Portuguese" +msgstr "Portagailis" + +msgid "Brazilian Portuguese" +msgstr "Portagailis Bhraisileach" + +msgid "Romanian" +msgstr "Romàinis" + +msgid "Russian" +msgstr "Ruisis" + +msgid "Slovak" +msgstr "Slòbhacais" + +msgid "Slovenian" +msgstr "Slòbhainis" + +msgid "Albanian" +msgstr "Albàinis" + +msgid "Serbian" +msgstr "Sèirbis" + +msgid "Serbian Latin" +msgstr "Sèirbis (Laideann)" + +msgid "Swedish" +msgstr "Suainis" + +msgid "Swahili" +msgstr "Kiswahili" + +msgid "Tamil" +msgstr "Taimilis" + +msgid "Telugu" +msgstr "Telugu" + +msgid "Tajik" +msgstr "Taidigis" + +msgid "Thai" +msgstr "Tàidh" + +msgid "Turkmen" +msgstr "Turcmanais" + +msgid "Turkish" +msgstr "Turcais" + +msgid "Tatar" +msgstr "Tatarais" + +msgid "Udmurt" +msgstr "Udmurt" + +msgid "Ukrainian" +msgstr "Ucràinis" + +msgid "Urdu" +msgstr "Ùrdu" + +msgid "Uzbek" +msgstr "Usbagais" + +msgid "Vietnamese" +msgstr "Bhiet-Namais" + +msgid "Simplified Chinese" +msgstr "Sìnis Shimplichte" + +msgid "Traditional Chinese" +msgstr "Sìnis Thradaiseanta" + +msgid "Messages" +msgstr "Teachdaireachdan" + +msgid "Site Maps" +msgstr "Mapaichean-làraich" + +msgid "Static Files" +msgstr "Faidhlichean stadastaireachd" + +msgid "Syndication" +msgstr "Siondacaideadh" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Chan eil àireamh na duilleige seo 'na àireamh slàn" + +msgid "That page number is less than 1" +msgstr "Tha àireamh na duilleige seo nas lugha na 1" + +msgid "That page contains no results" +msgstr "Chan eil toradh aig an duilleag seo" + +msgid "Enter a valid value." +msgstr "Cuir a-steach luach dligheach." + +msgid "Enter a valid URL." +msgstr "Cuir a-steach URL dligheach." + +msgid "Enter a valid integer." +msgstr "Cuir a-steach àireamh slàin dhligheach." + +msgid "Enter a valid email address." +msgstr "Cuir a-steach seòladh puist-d dligheach." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Cuir a-steach “sluga” dligheach anns nach eil ach litrichean, àireamhan, fo-" +"loidhnichean is tàthanan." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Cuir a-steach “sluga” dligheach anns nach eil ach litrichean Unicode, " +"àireamhan, fo-loidhnichean is tàthanan." + +msgid "Enter a valid IPv4 address." +msgstr "Cuir a-steach seòladh IPv4 dligheach." + +msgid "Enter a valid IPv6 address." +msgstr "Cuir a-steach seòladh IPv6 dligheach." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Cuir a-steach seòladh IPv4 no IPv6 dligheach." + +msgid "Enter only digits separated by commas." +msgstr "Na cuir a-steach ach àireamhan ’gan sgaradh le cromagan." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Dèan cinnteach gu bheil an luach seo %(limit_value)s (’s e %(show_value)s a " +"th’ ann)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" +"Dèan cinnteach gu bheil an luach seo nas lugha na no co-ionnan ri " +"%(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" +"Dèan cinnteach gu bheil an luach seo nas motha na no co-ionnan ri " +"%(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Dèan cinnteach gu bheil %(limit_value)d charactar aig an luach seo air a’ " +"char as lugha (tha %(show_value)d aige an-dràsta)." +msgstr[1] "" +"Dèan cinnteach gu bheil %(limit_value)d charactar aig an luach seo air a’ " +"char as lugha (tha %(show_value)d aige an-dràsta)." +msgstr[2] "" +"Dèan cinnteach gu bheil %(limit_value)d caractaran aig an luach seo air a’ " +"char as lugha (tha %(show_value)d aige an-dràsta)." +msgstr[3] "" +"Dèan cinnteach gu bheil %(limit_value)d caractar aig an luach seo air a’ " +"char as lugha (tha %(show_value)d aige an-dràsta)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Dèan cinnteach gu bheil %(limit_value)d charactar aig an luach seo air a’ " +"char as motha (tha %(show_value)d aige an-dràsta)." +msgstr[1] "" +"Dèan cinnteach gu bheil %(limit_value)d charactar aig an luach seo air a’ " +"char as motha (tha %(show_value)d aige an-dràsta)." +msgstr[2] "" +"Dèan cinnteach gu bheil %(limit_value)d caractaran aig an luach seo air a’ " +"char as motha (tha %(show_value)d aige an-dràsta)." +msgstr[3] "" +"Dèan cinnteach gu bheil %(limit_value)d caractar aig an luach seo air a’ " +"char as motha (tha %(show_value)d aige an-dràsta)." + +msgid "Enter a number." +msgstr "Cuir a-steach àireamh." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" +"Dèan cinnteach nach eil barrachd air %(max)s àireamh ann gu h-iomlan." +msgstr[1] "" +"Dèan cinnteach nach eil barrachd air %(max)s àireamh ann gu h-iomlan." +msgstr[2] "" +"Dèan cinnteach nach eil barrachd air %(max)s àireamhan ann gu h-iomlan." +msgstr[3] "" +"Dèan cinnteach nach eil barrachd air %(max)s àireamh ann gu h-iomlan." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Dèan cinnteach nach eil barrachd air %(max)s ionad deicheach ann." +msgstr[1] "Dèan cinnteach nach eil barrachd air %(max)s ionad deicheach ann." +msgstr[2] "Dèan cinnteach nach eil barrachd air %(max)s ionadan deicheach ann." +msgstr[3] "Dèan cinnteach nach eil barrachd air %(max)s ionad deicheach ann." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Dèan cinnteach nach eil barrachd air %(max)s àireamh ann ron phuing " +"dheicheach." +msgstr[1] "" +"Dèan cinnteach nach eil barrachd air %(max)s àireamh ann ron phuing " +"dheicheach." +msgstr[2] "" +"Dèan cinnteach nach eil barrachd air %(max)s àireamhan ann ron phuing " +"dheicheach." +msgstr[3] "" +"Dèan cinnteach nach eil barrachd air %(max)s àireamh ann ron phuing " +"dheicheach." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Chan eil an leudachan faidhle “%(extension)s” ceadaichte. Seo na leudachain " +"a tha ceadaichte: %(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Chan eil caractaran null ceadaichte." + +msgid "and" +msgstr "agus" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "Tha %(model_name)s lis a’ %(field_labels)s seo ann mar-thà." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Chan eil an luach %(value)r ’na roghainn dhligheach." + +msgid "This field cannot be null." +msgstr "Chan fhaod an raon seo a bhith ’na neoni." + +msgid "This field cannot be blank." +msgstr "Chan fhaod an raon seo a bhith bàn." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "Tha %(model_name)s leis a’ %(field_label)s seo ann mar-thà." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"Chan fhaod %(field_label)s a bhith ann ach aon turas airson " +"%(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Raon dhen t-seòrsa: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "Feumaidh “%(value)s” a bhith True no False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "Feumaidh “%(value)s” a bhith True, False no None." + +msgid "Boolean (Either True or False)" +msgstr "Booleach (True no False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Sreang (suas ri %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "Àireamhan slàna sgaraichte le cromagan" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"Tha fòrmat cinn-là mì-dhligheach aig an luach “%(value)s”. Feumaidh e bhith " +"san fhòrmat BBBB-MM-LL." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"Tha fòrmat mar bu chòir (BBBB-MM-LL) aig an luach “%(value)s” ach tha an " +"ceann-là mì-dligheach." + +msgid "Date (without time)" +msgstr "Ceann-là (gun àm)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"Tha fòrmat mì-dhligheach aig an luach “%(value)s”. Feumaidh e bhith san " +"fhòrmat BBBB-MM-LL HH:MM[:dd[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"Tha fòrmat mar bu chòir (BBBB-MM-LL HH:MM[:dd[.uuuuuu]][TZ]) aig an luach " +"“%(value)s” ach tha an ceann-là/an t-àm mì-dligheach." + +msgid "Date (with time)" +msgstr "Ceann-là (le àm)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "Feumaidh “%(value)s” a bhith ’na àireamh dheicheach." + +msgid "Decimal number" +msgstr "Àireamh dheicheach" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"Tha fòrmat mì-dhligheach aig an luach “%(value)s”. Feumaidh e bhith san " +"fhòrmat [DD] [[HH:]MM:]ss[.uuuuuu]." + +msgid "Duration" +msgstr "Faid" + +msgid "Email address" +msgstr "Seòladh puist-d" + +msgid "File path" +msgstr "Slighe an fhaidhle" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "Feumaidh “%(value)s” a bhith ’na àireamh floda." + +msgid "Floating point number" +msgstr "Àireamh le puing floda" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "Feumaidh “%(value)s” a bhith ’na àireamh shlàn." + +msgid "Integer" +msgstr "Àireamh shlàn" + +msgid "Big (8 byte) integer" +msgstr "Mòr-àireamh shlàn (8 baidht)" + +msgid "Small integer" +msgstr "Beag-àireamh slàn" + +msgid "IPv4 address" +msgstr "Seòladh IPv4" + +msgid "IP address" +msgstr "Seòladh IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "Feumaidh “%(value)s” a bhith None, True no False." + +msgid "Boolean (Either True, False or None)" +msgstr "Booleach (True, False no None)" + +msgid "Positive big integer" +msgstr "Àireamh shlàn dhearbh" + +msgid "Positive integer" +msgstr "Àireamh shlàn dhearbh" + +msgid "Positive small integer" +msgstr "Beag-àireamh shlàn dhearbh" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Sluga (suas ri %(max_length)s)" + +msgid "Text" +msgstr "Teacsa" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"Tha fòrmat mì-dhligheach aig an luach “%(value)s”. Feumaidh e bhith san " +"fhòrmat HH:MM[:dd[.uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"Tha fòrmat mar bu chòir (HH:MM[:dd[.uuuuuu]]) aig an luach “%(value)s” ach " +"tha an t-àm mì-dligheach." + +msgid "Time" +msgstr "Àm" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Dàta bìnearaidh amh" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "Chan eil “%(value)s” ’na UUID dligheach." + +msgid "Universally unique identifier" +msgstr "Aithnichear àraidh gu h-uile-choitcheann" + +msgid "File" +msgstr "Faidhle" + +msgid "Image" +msgstr "Dealbh" + +msgid "A JSON object" +msgstr "Oibseact JSON" + +msgid "Value must be valid JSON." +msgstr "Feumaidh an luach a bhith ’na JSON dligheach." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "Chan eil ionstans dhe %(model)s le %(field)s %(value)r ann." + +msgid "Foreign Key (type determined by related field)" +msgstr "Iuchair chèin (thèid a sheòrsa a mhìneachadh leis an raon dàimheach)" + +msgid "One-to-one relationship" +msgstr "Dàimh aonan gu aonan" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "Dàimh %(from)s-%(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "Dàimhean %(from)s-%(to)s" + +msgid "Many-to-many relationship" +msgstr "Dàimh iomadh rud gu iomadh rud" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Tha an raon seo riatanach." + +msgid "Enter a whole number." +msgstr "Cuir a-steach àireamh shlàn." + +msgid "Enter a valid date." +msgstr "Cuir a-steach ceann-là dligheach." + +msgid "Enter a valid time." +msgstr "Cuir a-steach àm dligheach." + +msgid "Enter a valid date/time." +msgstr "Cuir a-steach ceann-là ’s àm dligheach." + +msgid "Enter a valid duration." +msgstr "Cuir a-steach faid dhligheach." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" +"Feumaidh an àireamh de làithean a bhith eadar {min_days} is {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" +"Cha deach faidhle a chur a-null. Dearbhaich seòrsa a’ chòdachaidh air an " +"fhoirm." + +msgid "No file was submitted." +msgstr "Cha deach faidhle a chur a-null." + +msgid "The submitted file is empty." +msgstr "Tha am faidhle a chaidh a chur a-null falamh." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Dèan cinnteach nach eil barrachd air %(max)d charactar ann an ainm an " +"fhaidhle (tha %(length)d aige)." +msgstr[1] "" +"Dèan cinnteach nach eil barrachd air %(max)d charactar ann an ainm an " +"fhaidhle (tha %(length)d aige)." +msgstr[2] "" +"Dèan cinnteach nach eil barrachd air %(max)d caractaran ann an ainm an " +"fhaidhle (tha %(length)d aige)." +msgstr[3] "" +"Dèan cinnteach nach eil barrachd air %(max)d caractar ann an ainm an " +"fhaidhle (tha %(length)d aige)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Cuir a-null faidhle no cuir cromag sa bhogsa fhalamh, na dèan an dà chuidh " +"dhiubh." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Luchdaich suas dealbh dligheach. Cha robh am faidhle a luchdaich thu suas " +"’na dhealbh no bha an dealbh coirbte." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Tagh rud dligheach. Chan eil %(value)s ’na roghainn dhut." + +msgid "Enter a list of values." +msgstr "Cuir a-steach liosta de luachan." + +msgid "Enter a complete value." +msgstr "Cuir a-steach luach slàn." + +msgid "Enter a valid UUID." +msgstr "Cuir a-steach UUID dligheach." + +msgid "Enter a valid JSON." +msgstr "Cuir a-steach JSON dligheach." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Raon falaichte %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"Tha dàta an fhoirm stiùiridh a dhìth no chaidh beantainn ris. Seo na " +"raointean a tha a dhìth: %(field_names)s. Ma mhaireas an duilgheadas, saoil " +"an cuir thu aithris air buga thugainn?" + +#, python-format +msgid "Please submit at most %d form." +msgid_plural "Please submit at most %d forms." +msgstr[0] "Na cuir a-null barrachd air %d fhoirm." +msgstr[1] "Na cuir a-null barrachd air %d fhoirm." +msgstr[2] "Na cuir a-null barrachd air %d foirmean." +msgstr[3] "Na cuir a-null barrachd air %d foirm." + +#, python-format +msgid "Please submit at least %d form." +msgid_plural "Please submit at least %d forms." +msgstr[0] "Cuir a-null %d fhoirm air a char as lugha." +msgstr[1] "Cuir a-null %d fhoirm air a char as lugha." +msgstr[2] "Cuir a-null %d foirmichean air a char as lugha." +msgstr[3] "Cuir a-null %d foirm air a char as lugha." + +msgid "Order" +msgstr "Òrdugh" + +msgid "Delete" +msgstr "Sguab às" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Ceartaich an dàta dùblaichte airson %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Ceartaich an dàta dùblaichte airson %(field)s, chan fhaod gach nì a bhith " +"ann ach aon turas." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Ceartaich an dàta dùblaichte airson %(field_name)s nach fhaod a bhith ann " +"ach aon turas airson %(lookup)s ann an %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Ceartaich na luachan dùblaichte gu h-ìosal." + +msgid "The inline value did not match the parent instance." +msgstr "" +"Chan eil an luach am broinn na loidhne a’ freagairt ris an ionstans-pàraint." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Tagh rud dligheach. Chan eil an rud seo ’na roghainn dhut." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "Chan e luach dligheach a tha ann an “%(pk)s”." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"Cha chiall dha %(datetime)s san roinn-tìde %(current_timezone)s; dh’fhaoidte " +"gu bheil e dà-sheaghach no nach eil e ann." + +msgid "Clear" +msgstr "Falamhaich" + +msgid "Currently" +msgstr "An-dràsta" + +msgid "Change" +msgstr "Atharraich" + +msgid "Unknown" +msgstr "Chan eil fhios" + +msgid "Yes" +msgstr "Tha" + +msgid "No" +msgstr "Chan eil" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "yes,no,maybe" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d baidht" +msgstr[1] "%(size)d baidht" +msgstr[2] "%(size)d baidht" +msgstr[3] "%(size)d baidht" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "f" + +msgid "a.m." +msgstr "m" + +msgid "PM" +msgstr "f" + +msgid "AM" +msgstr "m" + +msgid "midnight" +msgstr "meadhan-oidhche" + +msgid "noon" +msgstr "meadhan-latha" + +msgid "Monday" +msgstr "DiLuain" + +msgid "Tuesday" +msgstr "DiMàirt" + +msgid "Wednesday" +msgstr "DiCiadain" + +msgid "Thursday" +msgstr "DiarDaoin" + +msgid "Friday" +msgstr "DihAoine" + +msgid "Saturday" +msgstr "DiSathairne" + +msgid "Sunday" +msgstr "DiDòmhnaich" + +msgid "Mon" +msgstr "DiL" + +msgid "Tue" +msgstr "DiM" + +msgid "Wed" +msgstr "DiC" + +msgid "Thu" +msgstr "Dia" + +msgid "Fri" +msgstr "Dih" + +msgid "Sat" +msgstr "DiS" + +msgid "Sun" +msgstr "DiD" + +msgid "January" +msgstr "Am Faoilleach" + +msgid "February" +msgstr "An Gearran" + +msgid "March" +msgstr "Am Màrt" + +msgid "April" +msgstr "An Giblean" + +msgid "May" +msgstr "An Cèitean" + +msgid "June" +msgstr "An t-Ògmhios" + +msgid "July" +msgstr "An t-Iuchar" + +msgid "August" +msgstr "An Lùnastal" + +msgid "September" +msgstr "An t-Sultain" + +msgid "October" +msgstr "An Dàmhair" + +msgid "November" +msgstr "An t-Samhain" + +msgid "December" +msgstr "An Dùbhlachd" + +msgid "jan" +msgstr "faoi" + +msgid "feb" +msgstr "gearr" + +msgid "mar" +msgstr "màrt" + +msgid "apr" +msgstr "gibl" + +msgid "may" +msgstr "cèit" + +msgid "jun" +msgstr "ògmh" + +msgid "jul" +msgstr "iuch" + +msgid "aug" +msgstr "lùna" + +msgid "sep" +msgstr "sult" + +msgid "oct" +msgstr "dàmh" + +msgid "nov" +msgstr "samh" + +msgid "dec" +msgstr "dùbh" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Faoi" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Gearr" + +msgctxt "abbrev. month" +msgid "March" +msgstr "Màrt" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Gibl" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Cèit" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Ògmh" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Iuch" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Lùna" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Sult" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Dàmh" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Samh" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dùbh" + +msgctxt "alt. month" +msgid "January" +msgstr "Am Faoilleach" + +msgctxt "alt. month" +msgid "February" +msgstr "An Gearran" + +msgctxt "alt. month" +msgid "March" +msgstr "Am Màrt" + +msgctxt "alt. month" +msgid "April" +msgstr "An Giblean" + +msgctxt "alt. month" +msgid "May" +msgstr "An Cèitean" + +msgctxt "alt. month" +msgid "June" +msgstr "An t-Ògmhios" + +msgctxt "alt. month" +msgid "July" +msgstr "An t-Iuchar" + +msgctxt "alt. month" +msgid "August" +msgstr "An Lùnastal" + +msgctxt "alt. month" +msgid "September" +msgstr "An t-Sultain" + +msgctxt "alt. month" +msgid "October" +msgstr "An Dàmhair" + +msgctxt "alt. month" +msgid "November" +msgstr "An t-Samhain" + +msgctxt "alt. month" +msgid "December" +msgstr "An Dùbhlachd" + +msgid "This is not a valid IPv6 address." +msgstr "Chan eil seo ’na sheòladh IPv6 dligheach." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "no" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d bliadhna" +msgstr[1] "%(num)d bhliadhna" +msgstr[2] "%(num)d bliadhnaichean" +msgstr[3] "%(num)d bliadhna" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mhìos" +msgstr[1] "%(num)d mhìos" +msgstr[2] "%(num)d mìosan" +msgstr[3] "%(num)d mìos" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d seachdain" +msgstr[1] "%(num)d sheachdain" +msgstr[2] "%(num)d seachdainean" +msgstr[3] "%(num)d seachdain" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d latha" +msgstr[1] "%(num)d latha" +msgstr[2] "%(num)d làithean" +msgstr[3] "%(num)d latha" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d uair a thìde" +msgstr[1] "%(num)d uair a thìde" +msgstr[2] "%(num)d uairean a thìde" +msgstr[3] "%(num)d uair a thìde" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d mhionaid" +msgstr[1] "%(num)d mhionaid" +msgstr[2] "%(num)d mionaidean" +msgstr[3] "%(num)d mionaid" + +msgid "Forbidden" +msgstr "Toirmisgte" + +msgid "CSRF verification failed. Request aborted." +msgstr "Dh’fhàillig le dearbhadh CSRF. chaidh sgur dhen iarrtas." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Chì thu an teachdaireachd seo air sgàth ’s gu bheil an làrach-lìn HTTPS seo " +"ag iarraidh air a’ bhrabhsair-lìn agad gun cuir e bann-cinn “Referer” thuice " +"ach cha deach gin a chur a-null. Tha feum air a’ bhann-chinn seo a chum " +"tèarainteachd ach nach cleachd treas-phàrtaidh am brabhsair agad gu droch-" +"rùnach." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Ma rèitich thu am brabhsair agad ach an cuir e bannan-cinn “Referer” à " +"comas, cuir an comas iad a-rithist, co-dhiù airson na làraich seo no airson " +"ceanglaichean HTTPS no airson iarrtasan “same-origin”." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Ma tha thu a’ cleachdadh taga no a’ gabhail a-staigh bann-cinn “'Referrer-Policy: no-referrer” feuch " +"an doir thu air falbh iad. Iarraidh an dìon CSRF bann-cinn “Referer” gus na " +"referers a dhearbhadh gu teann. Ma tha thu iomagaineach a thaobh do " +"prìobhaideachd, cleachd roghainnean eile mar airson " +"ceangal gu làraichean-lìn threas-phàrtaidhean." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Chì thu an teachdaireachd seo air sgàth ’s gu bheil an làrach-lìn seo ag " +"iarraidh briosgaid CSRF nuair a chuireas tu foirm a-null. Tha feum air a’ " +"bhriosgaid seo a chum tèarainteachd ach nach cleachd treas-phàrtaidh am " +"brabhsair agad gu droch-rùnach." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Ma rèitich thu am brabhsair agad ach an cuir e briosgaidean à comas, cuir an " +"comas iad a-rithist, co-dhiù airson na làraich seo no airson iarrtasan “same-" +"origin”." + +msgid "More information is available with DEBUG=True." +msgstr "Gheibh thu barrachd fiosrachaidh le DEBUG=True." + +msgid "No year specified" +msgstr "Cha deach bliadhna a shònrachadh" + +msgid "Date out of range" +msgstr "Tha ceann-là taobh thar na rainse" + +msgid "No month specified" +msgstr "Cha deach mìos a shònrachadh" + +msgid "No day specified" +msgstr "Cha deach latha a shònrachadh" + +msgid "No week specified" +msgstr "Cha deach seachdain a shònrachadh" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Chan eil %(verbose_name_plural)s ri fhaighinn" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Chan eil %(verbose_name_plural)s san àm ri teachd ri fhaighinn air sgàth ’s " +"gun deach %(class_name)s.allow_future a shuidheachadh air False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" +"Sreang cinn-là “%(datestr)s” mì-dhligheach airson an fhòrmait “%(format)s”" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Cha deach %(verbose_name)s a lorg a fhreagras dhan cheist" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" +"Chan eil an duilleag ’na “last” is cha ghabh a h-iompachadh gu àireamh shlàn." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Duilleag mhì-dhligheach (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" +"Tha liosta fhalamh ann agus chaidh “%(class_name)s.allow_empty” a " +"shuidheachadh air False." + +msgid "Directory indexes are not allowed here." +msgstr "Chan eil clàran-amais pasgain falamh ceadaichte an-seo." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "Chan eil “%(path)s” ann" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Clàr-amais dhe %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Chaidh a stàladh! Meal do naidheachd!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Seall na nòtaichean sgaoilidh airson Django " +"%(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" +"Chì thu an duilleag seo on a tha DEBUG=True ann am faidhle nan roghainnean agad agus cha do rèitich " +"thu URL sam bith fhathast." + +msgid "Django Documentation" +msgstr "Docamaideadh Django" + +msgid "Topics, references, & how-to’s" +msgstr "Cuspairean, iomraidhean ⁊ treòraichean" + +msgid "Tutorial: A Polling App" +msgstr "Oideachadh: Aplacaid cunntais-bheachd" + +msgid "Get started with Django" +msgstr "Dèan toiseach-tòiseachaidh le Django" + +msgid "Django Community" +msgstr "Coimhearsnachd Django" + +msgid "Connect, get help, or contribute" +msgstr "Dèan ceangal, faigh taic no cuidich" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/gd/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/gd/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/gd/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/gd/formats.py new file mode 100644 index 0000000..5ef6774 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/gd/formats.py @@ -0,0 +1,21 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j F Y" +TIME_FORMAT = "h:ia" +DATETIME_FORMAT = "j F Y h:ia" +# YEAR_MONTH_FORMAT = +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "j M Y" +SHORT_DATETIME_FORMAT = "j M Y h:ia" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = "." +THOUSAND_SEPARATOR = "," +# NUMBER_GROUPING = diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/gl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/gl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d4d4dbb Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/gl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/gl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/gl/LC_MESSAGES/django.po new file mode 100644 index 0000000..58f7858 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/gl/LC_MESSAGES/django.po @@ -0,0 +1,1349 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# fasouto , 2011-2012 +# fonso , 2011,2013 +# fonso , 2013 +# fasouto , 2017 +# Jannis Leidel , 2011 +# Leandro Regueiro , 2013 +# 948a55bc37dd6d642f1875bb84258fff_07a28cc , 2012 +# X Bello , 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: X Bello , 2023\n" +"Language-Team: Galician (http://app.transifex.com/django/django/language/" +"gl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: gl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Africáner" + +msgid "Arabic" +msgstr "Árabe" + +msgid "Algerian Arabic" +msgstr "Árabe Arxelino" + +msgid "Asturian" +msgstr "Asturiano" + +msgid "Azerbaijani" +msgstr "Azerí" + +msgid "Bulgarian" +msgstr "Búlgaro" + +msgid "Belarusian" +msgstr "Bielorruso" + +msgid "Bengali" +msgstr "Bengalí" + +msgid "Breton" +msgstr "Bretón" + +msgid "Bosnian" +msgstr "Bosníaco" + +msgid "Catalan" +msgstr "Catalán" + +msgid "Central Kurdish (Sorani)" +msgstr "Kurdo Central (Sorani)" + +msgid "Czech" +msgstr "Checo" + +msgid "Welsh" +msgstr "Galés" + +msgid "Danish" +msgstr "Dinamarqués" + +msgid "German" +msgstr "Alemán" + +msgid "Lower Sorbian" +msgstr "Baixo Sorabo" + +msgid "Greek" +msgstr "Grego" + +msgid "English" +msgstr "Inglés" + +msgid "Australian English" +msgstr "Inglés australiano" + +msgid "British English" +msgstr "inglés británico" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Español" + +msgid "Argentinian Spanish" +msgstr "Español da Arxentina" + +msgid "Colombian Spanish" +msgstr "Español de Colombia" + +msgid "Mexican Spanish" +msgstr "Español de México" + +msgid "Nicaraguan Spanish" +msgstr "Español de Nicaragua" + +msgid "Venezuelan Spanish" +msgstr "Español de Venezuela" + +msgid "Estonian" +msgstr "Estoniano" + +msgid "Basque" +msgstr "Vasco" + +msgid "Persian" +msgstr "Persa" + +msgid "Finnish" +msgstr "Finés" + +msgid "French" +msgstr "Francés" + +msgid "Frisian" +msgstr "Frisón" + +msgid "Irish" +msgstr "Irlandés" + +msgid "Scottish Gaelic" +msgstr "Gaélico Escocés" + +msgid "Galician" +msgstr "Galego" + +msgid "Hebrew" +msgstr "Hebreo" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Croata" + +msgid "Upper Sorbian" +msgstr "Alto Sorabo" + +msgid "Hungarian" +msgstr "Húngaro" + +msgid "Armenian" +msgstr "Armenio" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonesio" + +msgid "Igbo" +msgstr "Ibo" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Islandés" + +msgid "Italian" +msgstr "Italiano" + +msgid "Japanese" +msgstr "Xaponés" + +msgid "Georgian" +msgstr "Xeorxiano" + +msgid "Kabyle" +msgstr "Cabilio" + +msgid "Kazakh" +msgstr "Casaco" + +msgid "Khmer" +msgstr "Camboxano" + +msgid "Kannada" +msgstr "Canará" + +msgid "Korean" +msgstr "Coreano" + +msgid "Kyrgyz" +msgstr "Kirguiz" + +msgid "Luxembourgish" +msgstr "Luxemburgués" + +msgid "Lithuanian" +msgstr "Lituano" + +msgid "Latvian" +msgstr "Letón" + +msgid "Macedonian" +msgstr "Macedonio" + +msgid "Malayalam" +msgstr "Mala" + +msgid "Mongolian" +msgstr "Mongol" + +msgid "Marathi" +msgstr "Marathi" + +msgid "Malay" +msgstr "Malaio" + +msgid "Burmese" +msgstr "Birmano" + +msgid "Norwegian Bokmål" +msgstr "Bokmål Noruegués" + +msgid "Nepali" +msgstr "Nepalés" + +msgid "Dutch" +msgstr "Holandés" + +msgid "Norwegian Nynorsk" +msgstr "Noruegués (nynorsk)" + +msgid "Ossetic" +msgstr "Osetio" + +msgid "Punjabi" +msgstr "Panxabiano" + +msgid "Polish" +msgstr "Polaco" + +msgid "Portuguese" +msgstr "Portugués" + +msgid "Brazilian Portuguese" +msgstr "Portugués do Brasil" + +msgid "Romanian" +msgstr "Romanés" + +msgid "Russian" +msgstr "Ruso" + +msgid "Slovak" +msgstr "Eslovaco" + +msgid "Slovenian" +msgstr "Esloveno" + +msgid "Albanian" +msgstr "Albanés" + +msgid "Serbian" +msgstr "Serbio" + +msgid "Serbian Latin" +msgstr "Serbio (alfabeto latino)" + +msgid "Swedish" +msgstr "Sueco" + +msgid "Swahili" +msgstr "Suahili" + +msgid "Tamil" +msgstr "Támil" + +msgid "Telugu" +msgstr "Telugu" + +msgid "Tajik" +msgstr "Taxico" + +msgid "Thai" +msgstr "Tai" + +msgid "Turkmen" +msgstr "Turcomá" + +msgid "Turkish" +msgstr "Turco" + +msgid "Tatar" +msgstr "Tártaro" + +msgid "Udmurt" +msgstr "Udmurt" + +msgid "Uyghur" +msgstr "Uigur" + +msgid "Ukrainian" +msgstr "Ucraíno" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "Uzbeco" + +msgid "Vietnamese" +msgstr "Vietnamita" + +msgid "Simplified Chinese" +msgstr "Chinés simplificado" + +msgid "Traditional Chinese" +msgstr "Chinés tradicional" + +msgid "Messages" +msgstr "Mensaxes" + +msgid "Site Maps" +msgstr "Mapas do sitio" + +msgid "Static Files" +msgstr "Arquivos Estáticos" + +msgid "Syndication" +msgstr "Sindicación" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Ese número de páxina non é un enteiro" + +msgid "That page number is less than 1" +msgstr "Ese número de páxina é menor que 1" + +msgid "That page contains no results" +msgstr "Esa páxina non contén resultados" + +msgid "Enter a valid value." +msgstr "Insira un valor válido." + +msgid "Enter a valid URL." +msgstr "Insira un URL válido." + +msgid "Enter a valid integer." +msgstr "Introduza un enteiro válido." + +msgid "Enter a valid email address." +msgstr "Insira un enderezo de correo electrónico válido." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Insira un “slug” valido composto por letras, números, guións baixos ou " +"medios." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Insira un “slug” valido composto por letras Unicode, números, guións baixos " +"ou medios." + +msgid "Enter a valid IPv4 address." +msgstr "Insira unha dirección IPv4 válida." + +msgid "Enter a valid IPv6 address." +msgstr "Insira unha dirección IPv6 válida" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Insira unha dirección IPv4 ou IPv6 válida" + +msgid "Enter only digits separated by commas." +msgstr "Insira só díxitos separados por comas." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Asegúrese de que este valor é %(limit_value)s (agora é %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Asegure que este valor é menor ou igual a %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Asegure que este valor é maior ou igual a %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" +"Asegúrese de que este valor é un múltiplo do tamaño do paso %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"Asegúrese de que este valor é un múltiplo do tamaño do paso %(limit_value)s, " +"comezando por %(offset)s, p. ex. %(offset)s, %(valid_value1)s, " +"%(valid_value2)s, e sucesivos." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Asegúrese de que este valor ten polo menos %(limit_value)d caracter (agora " +"ten %(show_value)d)." +msgstr[1] "" +"Asegúrese de que este valor ten polo menos %(limit_value)d caracteres (agora " +"ten %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Asegúrese de que este valor ten como moito %(limit_value)d caracter (agora " +"ten %(show_value)d)." +msgstr[1] "" +"Asegúrese de que este valor ten como moito %(limit_value)d caracteres (agora " +"ten %(show_value)d)." + +msgid "Enter a number." +msgstr "Insira un número." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Asegure que non hai mais de %(max)s díxito en total." +msgstr[1] "Asegure que non hai mais de %(max)s díxitos en total." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Asegúrese de que non hai máis de %(max)s lugar decimal." +msgstr[1] "Asegúrese de que non hai máis de %(max)s lugares decimais." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Asegúrese de que no hai máis de %(max)s díxito antes do punto decimal." +msgstr[1] "" +"Asegúrese de que non hai máis de %(max)s díxitos antes do punto decimal." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Non se permite a extensión “%(extension)s”. As extensións permitidas son: " +"%(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Non se permiten caracteres nulos." + +msgid "and" +msgstr "e" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "Xa existe un %(model_name)s con este %(field_labels)s." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Viólase a restricción “%(name)s”." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "O valor %(value)r non é unha opción válida." + +msgid "This field cannot be null." +msgstr "Este campo non pode ser nulo." + +msgid "This field cannot be blank." +msgstr "Este campo non pode estar baleiro." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "" +"Xa existe un modelo %(model_name)s coa etiqueta de campo %(field_label)s." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s ten que ser único para %(lookup_type)s en " +"%(date_field_label)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Campo de tipo: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "O valor “%(value)s” ten que ser ou True ou False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "O valor “%(value)s” ten que ser True, False ou None." + +msgid "Boolean (Either True or False)" +msgstr "Valor booleano (verdadeiro ou falso)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Cadea (máximo %(max_length)s)" + +msgid "String (unlimited)" +msgstr "Texto (sin límite)" + +msgid "Comma-separated integers" +msgstr "Números enteiros separados por comas" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"O valor “%(value)s” ten un formato inválido de data. Debe estar no formato " +"AAAA-MM-DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"O valor “%(value)s” ten o formato correcto (AAAA-MM-DD) pero non é unha data " +"válida." + +msgid "Date (without time)" +msgstr "Data (sen a hora)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"O valor “%(value)s” ten un formato non válido. Debe de ter o formato AAAA-MM-" +"DD HH:MM[:ss[.uuuuuu]][TZ]. " + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"O valor “%(value)s” ten o formato correcto (AAAA-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) pero non é unha data/hora válida." + +msgid "Date (with time)" +msgstr "Data (coa hora)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "“%(value)s” ten que ser un número en formato decimal." + +msgid "Decimal number" +msgstr "Número decimal" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"O valor “%(value)s” ten un formato non válido. Debe de ter o formato [DD] " +"[[HH:]MM:]ss[.uuuuuu]. " + +msgid "Duration" +msgstr "Duración" + +msgid "Email address" +msgstr "Enderezo electrónico" + +msgid "File path" +msgstr "Ruta de ficheiro" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "O valor “%(value)s” ten que ser un número en coma flotante." + +msgid "Floating point number" +msgstr "Número en coma flotante" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "O valor “%(value)s” ten que ser un número enteiro." + +msgid "Integer" +msgstr "Número enteiro" + +msgid "Big (8 byte) integer" +msgstr "Enteiro grande (8 bytes)" + +msgid "Small integer" +msgstr "Enteiro pequeno" + +msgid "IPv4 address" +msgstr "Enderezo IPv4" + +msgid "IP address" +msgstr "Enderezo IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "O valor “%(value)s” ten que ser None, True ou False." + +msgid "Boolean (Either True, False or None)" +msgstr "Booleano (verdadeiro, falso ou ningún)" + +msgid "Positive big integer" +msgstr "Número enteiro positivo grande" + +msgid "Positive integer" +msgstr "Numero enteiro positivo" + +msgid "Positive small integer" +msgstr "Enteiro pequeno positivo" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (ata %(max_length)s)" + +msgid "Text" +msgstr "Texto" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"O valor “%(value)s” ten un formato non válido. Ten que ter o formato HH:MM[:" +"ss[.uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"O valor “%(value)s” ten o formato correcto (HH:MM[:ss[.uuuuuu]]) pero non é " +"unha hora válida." + +msgid "Time" +msgstr "Hora" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Datos binarios en crú" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "“%(value)s” non é un UUID válido." + +msgid "Universally unique identifier" +msgstr "Identificador único universal" + +msgid "File" +msgstr "Ficheiro" + +msgid "Image" +msgstr "Imaxe" + +msgid "A JSON object" +msgstr "Un obxeto JSON" + +msgid "Value must be valid JSON." +msgstr "O valor ten que ser JSON válido." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "A instancia de %(model)s co %(field)s %(value)r non existe." + +msgid "Foreign Key (type determined by related field)" +msgstr "Clave Foránea (tipo determinado por un campo relacionado)" + +msgid "One-to-one relationship" +msgstr "Relación un a un" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "Relación %(from)s-%(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "Relacións %(from)s-%(to)s" + +msgid "Many-to-many relationship" +msgstr "Relación moitos a moitos" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Requírese este campo." + +msgid "Enter a whole number." +msgstr "Insira un número enteiro." + +msgid "Enter a valid date." +msgstr "Insira unha data válida." + +msgid "Enter a valid time." +msgstr "Insira unha hora válida." + +msgid "Enter a valid date/time." +msgstr "Insira unha data/hora válida." + +msgid "Enter a valid duration." +msgstr "Introduza unha duración válida." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "O número de días ten que estar entre {min_days} e {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" +"Non se enviou ficheiro ningún. Comprobe o tipo de codificación do formulario." + +msgid "No file was submitted." +msgstr "Non se enviou ficheiro ningún." + +msgid "The submitted file is empty." +msgstr "O ficheiro enviado está baleiro." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Asegúrese de que este nome de arquivo ten como moito %(max)d caracter (agora " +"ten %(length)d)." +msgstr[1] "" +"Asegúrese de que este nome de arquivo ten como moito %(max)d caracteres " +"(agora ten %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Ou ben envíe un ficheiro, ou ben marque a casilla de eliminar, pero non " +"ambas as dúas cousas." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Suba unha imaxe válida. O ficheiro subido non era unha imaxe ou esta estaba " +"corrupta." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Escolla unha opción válida. %(value)s non se atopa entre as opcións " +"dispoñibles." + +msgid "Enter a list of values." +msgstr "Insira unha lista de valores." + +msgid "Enter a complete value." +msgstr "Introduza un valor completo." + +msgid "Enter a valid UUID." +msgstr "Insira un UUID válido." + +msgid "Enter a valid JSON." +msgstr "Introduza un JSON válido." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Campo oculto %(name)s) %(error)s." + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"Faltan datos ou foron manipulados de ManagementForm. Campos afectados: " +"%(field_names)s. Debería abrir un informe de bug si o problema é persistente." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Por favor envíe como moito %(num)d formulario." +msgstr[1] "Por favor envíe como moito %(num)d formularios." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Por favor envíe polo menos %(num)d formulario." +msgstr[1] "Pro favor envíe polo menos %(num)d formularios." + +msgid "Order" +msgstr "Orde" + +msgid "Delete" +msgstr "Eliminar" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Corrixa os datos duplicados no campo %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Corrixa os datos duplicados no campo %(field)s, que debe ser único." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Corrixa os datos duplicados no campo %(field_name)s, que debe ser único para " +"a busca %(lookup)s no campo %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Corrixa os valores duplicados de abaixo." + +msgid "The inline value did not match the parent instance." +msgstr "O valor na liña non coincide ca instancia nai." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Escolla unha opción válida. Esta opción non se atopa entre as opcións " +"dispoñíbeis" + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "“%(pk)s” non é un valor válido." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s non se puido interpretar na zona hora horaria " +"%(current_timezone)s; pode ser ambiguo ou non existir." + +msgid "Clear" +msgstr "Limpar" + +msgid "Currently" +msgstr "Actualmente" + +msgid "Change" +msgstr "Modificar" + +msgid "Unknown" +msgstr "Descoñecido" + +msgid "Yes" +msgstr "Si" + +msgid "No" +msgstr "Non" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "si,non,quizais" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d byte" +msgstr[1] "%(size)d bytes" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "medianoite" + +msgid "noon" +msgstr "mediodía" + +msgid "Monday" +msgstr "Luns" + +msgid "Tuesday" +msgstr "Martes" + +msgid "Wednesday" +msgstr "Mércores" + +msgid "Thursday" +msgstr "Xoves" + +msgid "Friday" +msgstr "Venres" + +msgid "Saturday" +msgstr "Sábado" + +msgid "Sunday" +msgstr "Domingo" + +msgid "Mon" +msgstr "lun" + +msgid "Tue" +msgstr "mar" + +msgid "Wed" +msgstr "mér" + +msgid "Thu" +msgstr "xov" + +msgid "Fri" +msgstr "ven" + +msgid "Sat" +msgstr "sáb" + +msgid "Sun" +msgstr "dom" + +msgid "January" +msgstr "Xaneiro" + +msgid "February" +msgstr "Febreiro" + +msgid "March" +msgstr "Marzo" + +msgid "April" +msgstr "Abril" + +msgid "May" +msgstr "Maio" + +msgid "June" +msgstr "Xuño" + +msgid "July" +msgstr "Xullo" + +msgid "August" +msgstr "Agosto" + +msgid "September" +msgstr "Setembro" + +msgid "October" +msgstr "Outubro" + +msgid "November" +msgstr "Novembro" + +msgid "December" +msgstr "Decembro" + +msgid "jan" +msgstr "xan" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "abr" + +msgid "may" +msgstr "mai" + +msgid "jun" +msgstr "xuñ" + +msgid "jul" +msgstr "xul" + +msgid "aug" +msgstr "ago" + +msgid "sep" +msgstr "set" + +msgid "oct" +msgstr "out" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dec" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Xan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Marzo" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Abril" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Maio" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Xuño" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Xullo" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Ago." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Set." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Out." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dec." + +msgctxt "alt. month" +msgid "January" +msgstr "Xaneiro" + +msgctxt "alt. month" +msgid "February" +msgstr "Febreiro" + +msgctxt "alt. month" +msgid "March" +msgstr "Marzo" + +msgctxt "alt. month" +msgid "April" +msgstr "Abril" + +msgctxt "alt. month" +msgid "May" +msgstr "Maio" + +msgctxt "alt. month" +msgid "June" +msgstr "Xuño" + +msgctxt "alt. month" +msgid "July" +msgstr "Xullo" + +msgctxt "alt. month" +msgid "August" +msgstr "Agosto" + +msgctxt "alt. month" +msgid "September" +msgstr "Setembro" + +msgctxt "alt. month" +msgid "October" +msgstr "Outubro" + +msgctxt "alt. month" +msgid "November" +msgstr "Novembro" + +msgctxt "alt. month" +msgid "December" +msgstr "Decembro" + +msgid "This is not a valid IPv6 address." +msgstr "Isto non é un enderezo IPv6 válido." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "ou" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d ano" +msgstr[1] "%(num)d anos" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mes" +msgstr[1] "%(num)d meses" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d semana" +msgstr[1] "%(num)d semanas" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d día" +msgstr[1] "%(num)d días" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hora" +msgstr[1] "%(num)d horas" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuto" +msgstr[1] "%(num)d minutos" + +msgid "Forbidden" +msgstr "Denegado" + +msgid "CSRF verification failed. Request aborted." +msgstr "Fallóu a verificación CSRF. Abortouse a petición." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Está vendo esta mensaxe porque este sitio HTTPS require que o navegador " +"envíe un \"Referer header\", pero non envióu ningún. Este encabezamento é " +"necesario por razóns de seguridade, para asegurar que o navegador non está " +"sendo suplantado por terceiros." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Se ten o navegador configurado para deshabilitar os encabezamentos " +"\"Referer\", por favor habilíteos polo menos para este sitio, ou para " +"conexións HTTPS, ou para peticións de \"mesmo-orixe\"." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Si está usando a etiqueta " +"ou incluíndo o encabezado “Referrer-Policy: no-referrer”, por favor quíteos. " +"A protección CSRF require o encabezado “Referer” para facer a comprobación " +"estricta de referer. Si lle preocupa a privacidade, use alternativas como para enlazar con sitios de terceiros." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Está vendo esta mensaxe porque este sitio HTTPS require unha cookie CSRF ó " +"enviar formularios. Esta cookie é necesaria por razóns de seguridade, para " +"asegurar que o navegador non está sendo suplantado por terceiros." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Se ten o navegador configurado para deshabilitar as cookies, por favor " +"habilíteas, polo menos para este sitio, ou para peticións de “same-origin”." + +msgid "More information is available with DEBUG=True." +msgstr "Pode ver máis información se establece DEBUG=True." + +msgid "No year specified" +msgstr "Non se especificou ningún ano" + +msgid "Date out of range" +msgstr "Data fora de rango" + +msgid "No month specified" +msgstr "Non se especificou ningún mes" + +msgid "No day specified" +msgstr "Non se especificou ningún día" + +msgid "No week specified" +msgstr "Non se especificou ningunha semana" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Non hai %(verbose_name_plural)s dispoñibles" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Non hai dispoñibles %(verbose_name_plural)s futuros/as porque %(class_name)s." +"allow_futuro é False" + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "A data “%(datestr)s” non é válida para o formato “%(format)s”" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Non se atopou ningún/ha %(verbose_name)s que coincidise coa consulta" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "A páxina non é “last” nin se pode converter a int." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Páxina non válida (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "A lista está baleira pero “%(class_name)s.allow_empty” é False." + +msgid "Directory indexes are not allowed here." +msgstr "Os índices de directorio non están permitidos aquí." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "“%(path)s” non existe" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Índice de %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "A instalación foi un éxito! Noraboa!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Ver as notas de publicación para Django " +"%(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Está vendo esta páxina porque no arquivo de axustes ten DEBUG=True e non hai ningunha URL " +"configurada." + +msgid "Django Documentation" +msgstr "Documentación de Django" + +msgid "Topics, references, & how-to’s" +msgstr "Temas, referencias, & guías de uso" + +msgid "Tutorial: A Polling App" +msgstr "Tutorial: aplicación de enquisas" + +msgid "Get started with Django" +msgstr "Comenzar con Django" + +msgid "Django Community" +msgstr "Comunidade de Django" + +msgid "Connect, get help, or contribute" +msgstr "Conectar, conseguir axuda, ou contribuir" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/gl/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/gl/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/gl/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/gl/formats.py new file mode 100644 index 0000000..7372935 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/gl/formats.py @@ -0,0 +1,21 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = r"j \d\e F \d\e Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = r"j \d\e F \d\e Y \á\s H:i" +YEAR_MONTH_FORMAT = r"F \d\e Y" +MONTH_DAY_FORMAT = r"j \d\e F" +SHORT_DATE_FORMAT = "d-m-Y" +SHORT_DATETIME_FORMAT = "d-m-Y, H:i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +# NUMBER_GROUPING = diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/he/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/he/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e84ead5 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/he/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/he/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/he/LC_MESSAGES/django.po new file mode 100644 index 0000000..630a99b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/he/LC_MESSAGES/django.po @@ -0,0 +1,1351 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# 534b44a19bf18d20b71ecc4eb77c572f_db336e9 , 2011-2012 +# Jannis Leidel , 2011 +# Meir Kriheli , 2011-2015,2017,2019-2020,2023 +# Menachem G., 2021 +# Menachem G., 2021 +# אורי רודברג , 2021 +# Yaron Shahrabani , 2021 +# אורי רודברג , 2020,2022-2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Meir Kriheli , " +"2011-2015,2017,2019-2020,2023\n" +"Language-Team: Hebrew (http://app.transifex.com/django/django/language/he/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: he\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % " +"1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;\n" + +msgid "Afrikaans" +msgstr "אפריקאנס" + +msgid "Arabic" +msgstr "ערבית" + +msgid "Algerian Arabic" +msgstr "ערבית אלג'ירית" + +msgid "Asturian" +msgstr "אסטורית" + +msgid "Azerbaijani" +msgstr "אזרית" + +msgid "Bulgarian" +msgstr "בולגרית" + +msgid "Belarusian" +msgstr "בֶּלָרוּסִית" + +msgid "Bengali" +msgstr "בנגאלית" + +msgid "Breton" +msgstr "בְּרֶטוֹנִית" + +msgid "Bosnian" +msgstr "בוסנית" + +msgid "Catalan" +msgstr "קאטלונית" + +msgid "Central Kurdish (Sorani)" +msgstr "כורדית מרכזית (סוראני)" + +msgid "Czech" +msgstr "צ'כית" + +msgid "Welsh" +msgstr "וולשית" + +msgid "Danish" +msgstr "דנית" + +msgid "German" +msgstr "גרמנית" + +msgid "Lower Sorbian" +msgstr "סורבית תחתונה" + +msgid "Greek" +msgstr "יוונית" + +msgid "English" +msgstr "אנגלית" + +msgid "Australian English" +msgstr "אנגלית אוסטרלית" + +msgid "British English" +msgstr "אנגלית בריטית" + +msgid "Esperanto" +msgstr "אספרנטו" + +msgid "Spanish" +msgstr "ספרדית" + +msgid "Argentinian Spanish" +msgstr "ספרדית ארגנטינית" + +msgid "Colombian Spanish" +msgstr "ספרדית קולומביאנית" + +msgid "Mexican Spanish" +msgstr "ספרדית מקסיקנית" + +msgid "Nicaraguan Spanish" +msgstr "ספרדית ניקרגואה" + +msgid "Venezuelan Spanish" +msgstr "ספרדית ונצואלית" + +msgid "Estonian" +msgstr "אסטונית" + +msgid "Basque" +msgstr "בסקית" + +msgid "Persian" +msgstr "פרסית" + +msgid "Finnish" +msgstr "פינית" + +msgid "French" +msgstr "צרפתית" + +msgid "Frisian" +msgstr "פריזית" + +msgid "Irish" +msgstr "אירית" + +msgid "Scottish Gaelic" +msgstr "גאלית סקוטית" + +msgid "Galician" +msgstr "גאליציאנית" + +msgid "Hebrew" +msgstr "עברית" + +msgid "Hindi" +msgstr "הינדי" + +msgid "Croatian" +msgstr "קרואטית" + +msgid "Upper Sorbian" +msgstr "סורבית עילית" + +msgid "Hungarian" +msgstr "הונגרית" + +msgid "Armenian" +msgstr "ארמנית" + +msgid "Interlingua" +msgstr "אינטרלינגואה" + +msgid "Indonesian" +msgstr "אינדונזית" + +msgid "Igbo" +msgstr "איגבו" + +msgid "Ido" +msgstr "אידו" + +msgid "Icelandic" +msgstr "איסלנדית" + +msgid "Italian" +msgstr "איטלקית" + +msgid "Japanese" +msgstr "יפנית" + +msgid "Georgian" +msgstr "גיאורגית" + +msgid "Kabyle" +msgstr "קבילה" + +msgid "Kazakh" +msgstr "קזחית" + +msgid "Khmer" +msgstr "חמר" + +msgid "Kannada" +msgstr "קאנאדה" + +msgid "Korean" +msgstr "קוריאנית" + +msgid "Kyrgyz" +msgstr "קירגיזית" + +msgid "Luxembourgish" +msgstr "לוקסמבורגית" + +msgid "Lithuanian" +msgstr "ליטאית" + +msgid "Latvian" +msgstr "לטבית" + +msgid "Macedonian" +msgstr "מקדונית" + +msgid "Malayalam" +msgstr "מלאיאלאם" + +msgid "Mongolian" +msgstr "מונגולי" + +msgid "Marathi" +msgstr "מראטהי" + +msgid "Malay" +msgstr "מלאית" + +msgid "Burmese" +msgstr "בּוּרְמֶזִית" + +msgid "Norwegian Bokmål" +msgstr "נורבגית ספרותית" + +msgid "Nepali" +msgstr "נפאלית" + +msgid "Dutch" +msgstr "הולנדית" + +msgid "Norwegian Nynorsk" +msgstr "נורבגית חדשה" + +msgid "Ossetic" +msgstr "אוסטית" + +msgid "Punjabi" +msgstr "פנג'אבי" + +msgid "Polish" +msgstr "פולנית" + +msgid "Portuguese" +msgstr "פורטוגזית" + +msgid "Brazilian Portuguese" +msgstr "פורטוגזית ברזילאית" + +msgid "Romanian" +msgstr "רומנית" + +msgid "Russian" +msgstr "רוסית" + +msgid "Slovak" +msgstr "סלובקית" + +msgid "Slovenian" +msgstr "סלובנית" + +msgid "Albanian" +msgstr "אלבנית" + +msgid "Serbian" +msgstr "סרבית" + +msgid "Serbian Latin" +msgstr "סרבית לטינית" + +msgid "Swedish" +msgstr "שוודית" + +msgid "Swahili" +msgstr "סווהילי" + +msgid "Tamil" +msgstr "טמילית" + +msgid "Telugu" +msgstr "טלגו" + +msgid "Tajik" +msgstr "טג'יקית" + +msgid "Thai" +msgstr "תאילנדית" + +msgid "Turkmen" +msgstr "טורקמנית" + +msgid "Turkish" +msgstr "טורקית" + +msgid "Tatar" +msgstr "טטרית" + +msgid "Udmurt" +msgstr "אודמורטית" + +msgid "Uyghur" +msgstr "אויגורית" + +msgid "Ukrainian" +msgstr "אוקראינית" + +msgid "Urdu" +msgstr "אורדו" + +msgid "Uzbek" +msgstr "אוזבקית" + +msgid "Vietnamese" +msgstr "וייטנאמית" + +msgid "Simplified Chinese" +msgstr "סינית פשוטה" + +msgid "Traditional Chinese" +msgstr "סינית מסורתית" + +msgid "Messages" +msgstr "הודעות" + +msgid "Site Maps" +msgstr "מפות אתר" + +msgid "Static Files" +msgstr "קבצים סטטיים" + +msgid "Syndication" +msgstr "הפצת תכנים" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "..." + +msgid "That page number is not an integer" +msgstr "מספר העמוד אינו מספר שלם" + +msgid "That page number is less than 1" +msgstr "מספר העמוד קטן מ־1" + +msgid "That page contains no results" +msgstr "עמוד זה אינו מכיל תוצאות" + +msgid "Enter a valid value." +msgstr "יש להזין ערך חוקי." + +msgid "Enter a valid URL." +msgstr "יש להזין URL חוקי." + +msgid "Enter a valid integer." +msgstr "יש להזין מספר שלם חוקי." + +msgid "Enter a valid email address." +msgstr "נא להזין כתובת דוא\"ל חוקית" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"יש להזין 'slug' חוקי המכיל אותיות לטיניות, ספרות, קווים תחתונים או מקפים." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"יש להזין 'slug' חוקי המכיל אותיות יוניקוד, ספרות, קווים תחתונים או מקפים." + +msgid "Enter a valid IPv4 address." +msgstr "יש להזין כתובת IPv4 חוקית." + +msgid "Enter a valid IPv6 address." +msgstr "יש להזין כתובת IPv6 חוקית." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "יש להזין כתובת IPv4 או IPv6 חוקית." + +msgid "Enter only digits separated by commas." +msgstr "יש להזין רק ספרות מופרדות בפסיקים." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "יש לוודא שערך זה הינו %(limit_value)s (כרגע %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "יש לוודא שערך זה פחות מ או שווה ל־%(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "יש לוודא שערך זה גדול מ או שווה ל־%(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "יש לוודא שערך זה מהווה מכפלה של %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"יש לוודא שערך זה מהווה מכפלה של צעד בגודל %(limit_value)s, החל מ־%(offset)s, " +"לדוגמה: %(offset)s, %(valid_value1)s, %(valid_value2)s וכו'." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"נא לוודא שערך זה מכיל תו %(limit_value)d לכל הפחות (מכיל %(show_value)d)." +msgstr[1] "" +"נא לוודא שערך זה מכיל %(limit_value)d תווים לכל הפחות (מכיל %(show_value)d)." +msgstr[2] "" +"נא לוודא שערך זה מכיל %(limit_value)d תווים לכל הפחות (מכיל %(show_value)d)." +msgstr[3] "" +"נא לוודא שערך זה מכיל %(limit_value)d תווים לכל הפחות (מכיל %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"נא לוודא שערך זה מכיל תו %(limit_value)d לכל היותר (מכיל %(show_value)d)." +msgstr[1] "" +"נא לוודא שערך זה מכיל %(limit_value)d תווים לכל היותר (מכיל %(show_value)d)." +msgstr[2] "" +"נא לוודא שערך זה מכיל %(limit_value)d תווים לכל היותר (מכיל %(show_value)d)." +msgstr[3] "" +"נא לוודא שערך זה מכיל %(limit_value)d תווים לכל היותר (מכיל %(show_value)d)." + +msgid "Enter a number." +msgstr "נא להזין מספר." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "נא לוודא שאין יותר מספרה %(max)s בסה\"כ." +msgstr[1] "נא לוודא שאין יותר מ־%(max)s ספרות בסה\"כ." +msgstr[2] "נא לוודא שאין יותר מ־%(max)s ספרות בסה\"כ." +msgstr[3] "נא לוודא שאין יותר מ־%(max)s ספרות בסה\"כ." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "נא לוודא שאין יותר מספרה %(max)s אחרי הנקודה." +msgstr[1] "נא לוודא שאין יותר מ־%(max)s ספרות אחרי הנקודה." +msgstr[2] "נא לוודא שאין יותר מ־%(max)s ספרות אחרי הנקודה." +msgstr[3] "נא לוודא שאין יותר מ־%(max)s ספרות אחרי הנקודה." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "נא לוודא שאין יותר מספרה %(max)s לפני הנקודה העשרונית" +msgstr[1] "נא לוודא שאין יותר מ־%(max)s ספרות לפני הנקודה העשרונית" +msgstr[2] "נא לוודא שאין יותר מ־%(max)s ספרות לפני הנקודה העשרונית" +msgstr[3] "נא לוודא שאין יותר מ־%(max)s ספרות לפני הנקודה העשרונית" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"סיומת הקובץ \"%(extension)s\" אסורה. הסיומות המותרות הן: " +"%(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "תווי NULL אינם מותרים. " + +msgid "and" +msgstr "ו" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s·עם·%(field_labels)s·אלו קיימים כבר." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "המגבלה \"%(name)s\" הופרה." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "ערך %(value)r אינו אפשרות חוקית." + +msgid "This field cannot be null." +msgstr "שדה זה אינו יכול להיות ריק." + +msgid "This field cannot be blank." +msgstr "שדה זה אינו יכול להיות ריק." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s·עם·%(field_label)s·זה קיימת כבר." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s חייב להיות ייחודי עבור %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "שדה מסוג: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "הערך \"%(value)s\" חייב להיות True או False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "\"%(value)s\" חייב להיות אחד מ־True‏, False, או None." + +msgid "Boolean (Either True or False)" +msgstr "בוליאני (אמת או שקר)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "מחרוזת (עד %(max_length)s תווים)" + +msgid "String (unlimited)" +msgstr "מחרוזת (ללא הגבלה)." + +msgid "Comma-separated integers" +msgstr "מספרים שלמים מופרדים בפסיקים" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"הערך \"%(value)s\" מכיל פורמט תאריך לא חוקי. חייב להיות בפורמט YYYY-MM-DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "הערך \"%(value)s\" בפורמט הנכון (YYYY-MM-DD), אך אינו תאריך חוקי." + +msgid "Date (without time)" +msgstr "תאריך (ללא שעה)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"הערך \"%(value)s\" מכיל פורמט לא חוקי. הוא חייב להיות בפורמטYYYY-MM-DD HH:" +"MM[:ss[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"הערך \"%(value)s\" בפורמט הנכון (YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) אך אינו " +"מהווה תאריך/שעה חוקיים." + +msgid "Date (with time)" +msgstr "תאריך (כולל שעה)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "הערך \"%(value)s\" חייב להיות מספר עשרוני." + +msgid "Decimal number" +msgstr "מספר עשרוני" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"הערך \"%(value)s\" מכיל פורמט לא חוקי. הוא חייב להיות בפורמט [DD] " +"[[HH:]MM:]ss[.uuuuuu]." + +msgid "Duration" +msgstr "משך" + +msgid "Email address" +msgstr "כתובת דוא\"ל" + +msgid "File path" +msgstr "נתיב קובץ" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "“%(value)s” חייב להיות מספר נקודה צפה." + +msgid "Floating point number" +msgstr "מספר עשרוני" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "הערך '%(value)s' חייב להיות מספר שלם." + +msgid "Integer" +msgstr "מספר שלם" + +msgid "Big (8 byte) integer" +msgstr "מספר שלם גדול (8 בתים)" + +msgid "Small integer" +msgstr "מספר שלם קטן" + +msgid "IPv4 address" +msgstr "כתובת IPv4" + +msgid "IP address" +msgstr "כתובת IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "\"%(value)s\" חייב להיות אחד מ־None‏, True, או False." + +msgid "Boolean (Either True, False or None)" +msgstr "בוליאני (אמת, שקר או כלום)" + +msgid "Positive big integer" +msgstr "מספר שלם גדול וחיובי" + +msgid "Positive integer" +msgstr "מספר שלם חיובי" + +msgid "Positive small integer" +msgstr "מספר שלם חיובי קטן" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (עד %(max_length)s תווים)" + +msgid "Text" +msgstr "טקסט" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"הערך “%(value)s” מכיל פורמט לא חוקי. הוא חייב להיות בפורמט HH:MM[:ss[." +"uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"הערך “%(value)s” בפורמט הנכון (HH:MM[:ss[.uuuuuu]]) אך אינו מהווה שעה חוקית." + +msgid "Time" +msgstr "זמן" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "מידע בינארי גולמי" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "\"%(value)s\" אינו UUID חוקי." + +msgid "Universally unique identifier" +msgstr "מזהה ייחודי אוניברסלי" + +msgid "File" +msgstr "קובץ" + +msgid "Image" +msgstr "תמונה" + +msgid "A JSON object" +msgstr "אובייקט JSON" + +msgid "Value must be valid JSON." +msgstr "הערך חייב להיות JSON חוקי." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "פריט %(model)s עם %(field)s %(value)r אינו קיים." + +msgid "Foreign Key (type determined by related field)" +msgstr "Foreign Key (הסוג נקבע לפי השדה המקושר)" + +msgid "One-to-one relationship" +msgstr "יחס של אחד לאחד" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "קשר %(from)s-%(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "קשרי %(from)s-%(to)s" + +msgid "Many-to-many relationship" +msgstr "יחס של רבים לרבים" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "יש להזין תוכן בשדה זה." + +msgid "Enter a whole number." +msgstr "נא להזין מספר שלם." + +msgid "Enter a valid date." +msgstr "יש להזין תאריך חוקי." + +msgid "Enter a valid time." +msgstr "יש להזין שעה חוקית." + +msgid "Enter a valid date/time." +msgstr "יש להזין תאריך ושעה חוקיים." + +msgid "Enter a valid duration." +msgstr "יש להזין משך חוקי." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "מספר הימים חייב להיות בין {min_days} ל־{max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "לא נשלח שום קובץ. נא לבדוק את סוג הקידוד של הטופס." + +msgid "No file was submitted." +msgstr "לא נשלח שום קובץ" + +msgid "The submitted file is empty." +msgstr "הקובץ שנשלח ריק." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "נא לוודא ששם קובץ זה מכיל תו %(max)d לכל היותר (מכיל %(length)d)." +msgstr[1] "" +"נא לוודא ששם קובץ זה מכיל %(max)d תווים לכל היותר (מכיל %(length)d)." +msgstr[2] "" +"נא לוודא ששם קובץ זה מכיל %(max)d תווים לכל היותר (מכיל %(length)d)." +msgstr[3] "" +"נא לוודא ששם קובץ זה מכיל %(max)d תווים לכל היותר (מכיל %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "נא לשים קובץ או סימן את התיבה לניקוי, לא שניהם." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "נא להעלות תמונה חוקית. הקובץ שהעלת אינו תמונה או מכיל תמונה מקולקלת." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "יש לבחור אפשרות חוקית. %(value)s אינו בין האפשרויות הזמינות." + +msgid "Enter a list of values." +msgstr "יש להזין רשימת ערכים" + +msgid "Enter a complete value." +msgstr "יש להזין ערך שלם." + +msgid "Enter a valid UUID." +msgstr "יש להזין UUID חוקי." + +msgid "Enter a valid JSON." +msgstr "נא להזין JSON חוקי." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(שדה מוסתר %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"המידע של ManagementForm חסר או שובש. שדות חסרים: %(field_names)s. יתכן " +"שתצטרך להגיש דיווח באג אם הבעיה נמשכת." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "נא לשלוח טופס %(num)d לכל היותר." +msgstr[1] "נא לשלוח %(num)d טפסים לכל היותר." +msgstr[2] "נא לשלוח %(num)d טפסים לכל היותר." +msgstr[3] "נא לשלוח %(num)d טפסים לכל היותר." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "נא לשלוח טופס %(num)dאו יותר." +msgstr[1] "נא לשלוח %(num)d טפסים או יותר." +msgstr[2] "נא לשלוח %(num)d טפסים או יותר." +msgstr[3] "נא לשלוח %(num)d טפסים או יותר." + +msgid "Order" +msgstr "מיון" + +msgid "Delete" +msgstr "מחיקה" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "נא לתקן את הערכים הכפולים ל%(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "נא לתקן את הערכים הכפולים ל%(field)s, שערכים בו חייבים להיות ייחודיים." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"נא לתקן את הערכים הכפולים %(field_name)s, שחייבים להיות ייחודיים ל%(lookup)s " +"של %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "נא לתקן את הערכים הכפולים למטה." + +msgid "The inline value did not match the parent instance." +msgstr "הערך הפנימי אינו תואם לאב." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "יש לבחור אפשרות חוקית; אפשרות זו אינה אחת מהזמינות." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "\"%(pk)s\" אינו ערך חוקי." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"לא ניתן לפרש את %(datetime)s באזור הזמן %(current_timezone)s; הוא עשוי להיות " +"דו־משמעי או לא קיים." + +msgid "Clear" +msgstr "לסלק" + +msgid "Currently" +msgstr "עכשיו" + +msgid "Change" +msgstr "שינוי" + +msgid "Unknown" +msgstr "לא ידוע" + +msgid "Yes" +msgstr "כן" + +msgid "No" +msgstr "לא" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "כן,לא,אולי" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "בית %(size)d " +msgstr[1] "%(size)d בתים" +msgstr[2] "%(size)d בתים" +msgstr[3] "%(size)d בתים" + +#, python-format +msgid "%s KB" +msgstr "%s ק\"ב" + +#, python-format +msgid "%s MB" +msgstr "%s מ\"ב" + +#, python-format +msgid "%s GB" +msgstr "%s ג\"ב" + +#, python-format +msgid "%s TB" +msgstr "%s ט\"ב" + +#, python-format +msgid "%s PB" +msgstr "%s פ\"ב" + +msgid "p.m." +msgstr "אחר הצהריים" + +msgid "a.m." +msgstr "בבוקר" + +msgid "PM" +msgstr "אחר הצהריים" + +msgid "AM" +msgstr "בבוקר" + +msgid "midnight" +msgstr "חצות" + +msgid "noon" +msgstr "12 בצהריים" + +msgid "Monday" +msgstr "שני" + +msgid "Tuesday" +msgstr "שלישי" + +msgid "Wednesday" +msgstr "רביעי" + +msgid "Thursday" +msgstr "חמישי" + +msgid "Friday" +msgstr "שישי" + +msgid "Saturday" +msgstr "שבת" + +msgid "Sunday" +msgstr "ראשון" + +msgid "Mon" +msgstr "שני" + +msgid "Tue" +msgstr "שלישי" + +msgid "Wed" +msgstr "רביעי" + +msgid "Thu" +msgstr "חמישי" + +msgid "Fri" +msgstr "שישי" + +msgid "Sat" +msgstr "שבת" + +msgid "Sun" +msgstr "ראשון" + +msgid "January" +msgstr "ינואר" + +msgid "February" +msgstr "פברואר" + +msgid "March" +msgstr "מרץ" + +msgid "April" +msgstr "אפריל" + +msgid "May" +msgstr "מאי" + +msgid "June" +msgstr "יוני" + +msgid "July" +msgstr "יולי" + +msgid "August" +msgstr "אוגוסט" + +msgid "September" +msgstr "ספטמבר" + +msgid "October" +msgstr "אוקטובר" + +msgid "November" +msgstr "נובמבר" + +msgid "December" +msgstr "דצמבר" + +msgid "jan" +msgstr "ינו" + +msgid "feb" +msgstr "פבר" + +msgid "mar" +msgstr "מרץ" + +msgid "apr" +msgstr "אפר" + +msgid "may" +msgstr "מאי" + +msgid "jun" +msgstr "יונ" + +msgid "jul" +msgstr "יול" + +msgid "aug" +msgstr "אוג" + +msgid "sep" +msgstr "ספט" + +msgid "oct" +msgstr "אוק" + +msgid "nov" +msgstr "נוב" + +msgid "dec" +msgstr "דצמ" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "יאנ'" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "פבר'" + +msgctxt "abbrev. month" +msgid "March" +msgstr "מרץ" + +msgctxt "abbrev. month" +msgid "April" +msgstr "אפריל" + +msgctxt "abbrev. month" +msgid "May" +msgstr "מאי" + +msgctxt "abbrev. month" +msgid "June" +msgstr "יוני" + +msgctxt "abbrev. month" +msgid "July" +msgstr "יולי" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "אוג'" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "ספט'" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "אוק'" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "נוב'" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "דצמ'" + +msgctxt "alt. month" +msgid "January" +msgstr "ינואר" + +msgctxt "alt. month" +msgid "February" +msgstr "פברואר" + +msgctxt "alt. month" +msgid "March" +msgstr "מרץ" + +msgctxt "alt. month" +msgid "April" +msgstr "אפריל" + +msgctxt "alt. month" +msgid "May" +msgstr "מאי" + +msgctxt "alt. month" +msgid "June" +msgstr "יוני" + +msgctxt "alt. month" +msgid "July" +msgstr "יולי" + +msgctxt "alt. month" +msgid "August" +msgstr "אוגוסט" + +msgctxt "alt. month" +msgid "September" +msgstr "ספטמבר" + +msgctxt "alt. month" +msgid "October" +msgstr "אוקטובר" + +msgctxt "alt. month" +msgid "November" +msgstr "נובמבר" + +msgctxt "alt. month" +msgid "December" +msgstr "דצמבר" + +msgid "This is not a valid IPv6 address." +msgstr "זו אינה כתובת IPv6 חוקית." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s‮…" + +msgid "or" +msgstr "או" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "שנה" +msgstr[1] "שנתיים" +msgstr[2] "%(num)d שנים" +msgstr[3] "%(num)d שנים" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "חודש" +msgstr[1] "חודשיים" +msgstr[2] "%(num)d חודשים" +msgstr[3] "%(num)d חודשים" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "שבוע" +msgstr[1] "שבועיים" +msgstr[2] "%(num)d שבועות" +msgstr[3] "%(num)d שבועות" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "יום" +msgstr[1] "יומיים" +msgstr[2] "%(num)d ימים" +msgstr[3] "%(num)d ימים" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "שעה" +msgstr[1] "שעתיים" +msgstr[2] "%(num)d שעות" +msgstr[3] "%(num)d שעות" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "דקה" +msgstr[1] "%(num)d דקות" +msgstr[2] "%(num)d דקות" +msgstr[3] "%(num)d דקות" + +msgid "Forbidden" +msgstr "אסור" + +msgid "CSRF verification failed. Request aborted." +msgstr "אימות CSRF נכשל. הבקשה בוטלה." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"הודעה זו מופיעה מאחר ואתר ה־HTTPS הזה דורש מהדפדפן שלך לשלוח \"Referer " +"header\", אך הוא לא נשלח. זה נדרש מסיבות אבטחה, כדי להבטיח שהדפדפן שלך לא " +"נחטף ע\"י צד שלישי." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"אם ביטלת \"Referer\" headers בדפדפן שלך, נא לאפשר אותם מחדש, לפחות עבור אתר " +"זה, חיבורי HTTPS או בקשות \"same-origin\"." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"אם השתמשת בתגאו הוספת header " +"של “Referrer-Policy: no-referrer”, נא להסיר אותם. הגנת ה־CSRF דורשת " +"‎“Referer” header לבדיקת ה־referer. אם פרטיות מדאיגה אותך, ניתן להשתמש " +"בתחליפים כמו לקישור אל אתרי צד שלישי." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"הודעה זו מופיעה מאחר ואתר זה דורש עוגיית CSRF כאשר שולחים טפסים. עוגיה זו " +"נדרשת מסיבות אבטחה, כדי לוודא שהדפדפן שלך לא נחטף על ידי אחרים." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"אם ביטלת עוגיות בדפדפן שלך, נא לאפשר אותם מחדש לפחות עבור אתר זה או בקשות " +"“same-origin”." + +msgid "More information is available with DEBUG=True." +msgstr "מידע נוסף זמין עם " + +msgid "No year specified" +msgstr "לא צוינה שנה" + +msgid "Date out of range" +msgstr "תאריך מחוץ לטווח" + +msgid "No month specified" +msgstr "לא צוין חודש" + +msgid "No day specified" +msgstr "לא צוין יום" + +msgid "No week specified" +msgstr "לא צוין שבוע" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "לא נמצאו %(verbose_name_plural)s" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"לא נמצאו %(verbose_name_plural)s בזמן עתיד מאחר ש-%(class_name)s." +"allow_future מוגדר False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "מחרוזת תאריך %(datestr)s אינה חוקית בפורמט %(format)s." + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "לא נמצא/ה %(verbose_name)s התואם/ת לשאילתה" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "העמוד אינו \"last\" או לא ניתן להמרה למספר שם." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "עמוד לא חוקי (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "רשימה ריקה ו־“%(class_name)s.allow_empty” הוא False." + +msgid "Directory indexes are not allowed here." +msgstr "אינדקסים על תיקיה אסורים כאן." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "\"%(path)s\" אינו קיים" + +#, python-format +msgid "Index of %(directory)s" +msgstr "אינדקס של %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "ההתקנה עברה בהצלחה! מזל טוב!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"ראו הערות השחרור עבור Django %(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"עמוד זה מופיע בעקבות המצאות DEBUG=True בקובץ ההגדרות שלך ולא הגדרת שום URLs." + +msgid "Django Documentation" +msgstr "תיעוד Django" + +msgid "Topics, references, & how-to’s" +msgstr "נושאים, הפניות ומדריכים לביצוע" + +msgid "Tutorial: A Polling App" +msgstr "מדריך ללומד: יישום לסקרים." + +msgid "Get started with Django" +msgstr "התחילו לעבוד עם Django" + +msgid "Django Community" +msgstr "קהילת Django" + +msgid "Connect, get help, or contribute" +msgstr "יצירת קשר, קבלת עזרה או השתתפות" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/he/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/he/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/he/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/he/formats.py new file mode 100644 index 0000000..2cf9286 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/he/formats.py @@ -0,0 +1,21 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j בF Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = "j בF Y H:i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j בF" +SHORT_DATE_FORMAT = "d/m/Y" +SHORT_DATETIME_FORMAT = "d/m/Y H:i" +# FIRST_DAY_OF_WEEK = + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = "." +THOUSAND_SEPARATOR = "," +# NUMBER_GROUPING = diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2d535fb Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hi/LC_MESSAGES/django.po new file mode 100644 index 0000000..20da376 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hi/LC_MESSAGES/django.po @@ -0,0 +1,1254 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# alkuma , 2013 +# Bharat Toge, 2022 +# Chandan kumar , 2012 +# Claude Paroz , 2020 +# Jannis Leidel , 2011 +# Pratik , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-05-17 05:23-0500\n" +"PO-Revision-Date: 2022-07-25 06:49+0000\n" +"Last-Translator: Bharat Toge\n" +"Language-Team: Hindi (http://www.transifex.com/django/django/language/hi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "अफ़्रीकांस" + +msgid "Arabic" +msgstr "अरबी" + +msgid "Algerian Arabic" +msgstr "अल्जीरियाई अरब" + +msgid "Asturian" +msgstr "" + +msgid "Azerbaijani" +msgstr "आज़रबाइजानी" + +msgid "Bulgarian" +msgstr "बलगारियन" + +msgid "Belarusian" +msgstr "बेलारूसी" + +msgid "Bengali" +msgstr "बंगाली" + +msgid "Breton" +msgstr "ब्रेटन" + +msgid "Bosnian" +msgstr "बोस्नियन" + +msgid "Catalan" +msgstr "कटलान" + +msgid "Czech" +msgstr "च्चेक" + +msgid "Welsh" +msgstr "वेल्श" + +msgid "Danish" +msgstr "दानिश" + +msgid "German" +msgstr "जर्मन" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "ग्रीक" + +msgid "English" +msgstr "अंग्रेज़ी " + +msgid "Australian English" +msgstr "ऑस्ट्रेलियाई अंग्रेज़ी " + +msgid "British English" +msgstr "ब्रिटिश अंग्रेजी" + +msgid "Esperanto" +msgstr "एस्परेन्तो" + +msgid "Spanish" +msgstr "स्पानिश" + +msgid "Argentinian Spanish" +msgstr "अर्जेंटीना स्पैनिश " + +msgid "Colombian Spanish" +msgstr "कोलंबियाई स्पेनी" + +msgid "Mexican Spanish" +msgstr "मेक्सिकन स्पैनिश" + +msgid "Nicaraguan Spanish" +msgstr "निकारागुआ स्पैनिश" + +msgid "Venezuelan Spanish" +msgstr "वेनेज़ुएलाई स्पेनिश" + +msgid "Estonian" +msgstr "एस्टोनियन" + +msgid "Basque" +msgstr "बास्क" + +msgid "Persian" +msgstr "पारसी" + +msgid "Finnish" +msgstr "फ़िन्निश" + +msgid "French" +msgstr "फ्रेंच" + +msgid "Frisian" +msgstr "फ्रिसियन" + +msgid "Irish" +msgstr "आयरिश" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "गलिशियन" + +msgid "Hebrew" +msgstr "हि‍ब्रू" + +msgid "Hindi" +msgstr "हिंदी" + +msgid "Croatian" +msgstr "क्रोयेशियन" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "हंगेरियन" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "इंतर्लिंगुआ" + +msgid "Indonesian" +msgstr "इन्डोनेशियन " + +msgid "Igbo" +msgstr "" + +msgid "Ido" +msgstr "" + +msgid "Icelandic" +msgstr "आयिस्लान्डिक" + +msgid "Italian" +msgstr "इटैलियन" + +msgid "Japanese" +msgstr "जपानी" + +msgid "Georgian" +msgstr "ज्योर्जियन" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "कज़ाख" + +msgid "Khmer" +msgstr "ख्मेर" + +msgid "Kannada" +msgstr "कन्‍नड़" + +msgid "Korean" +msgstr "कोरियन" + +msgid "Kyrgyz" +msgstr "" + +msgid "Luxembourgish" +msgstr "लक्संबर्गी" + +msgid "Lithuanian" +msgstr "लिथुवेनियन" + +msgid "Latvian" +msgstr "लात्वियन" + +msgid "Macedonian" +msgstr "मेसिडोनियन" + +msgid "Malayalam" +msgstr "मलयालम" + +msgid "Mongolian" +msgstr "मंगोलियन" + +msgid "Marathi" +msgstr "मराठी" + +msgid "Malay" +msgstr "मलय भाषा" + +msgid "Burmese" +msgstr "बर्मीज़" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "नेपाली" + +msgid "Dutch" +msgstr "डच" + +msgid "Norwegian Nynorsk" +msgstr "नार्वेजियन नायनॉर्स्क" + +msgid "Ossetic" +msgstr "ओस्सेटिक" + +msgid "Punjabi" +msgstr "पंजाबी" + +msgid "Polish" +msgstr "पोलिश" + +msgid "Portuguese" +msgstr "पुर्तगाली" + +msgid "Brazilian Portuguese" +msgstr "ब्रजिलियन पुर्तगाली" + +msgid "Romanian" +msgstr "रोमानियन" + +msgid "Russian" +msgstr "रूसी" + +msgid "Slovak" +msgstr "स्लोवाक" + +msgid "Slovenian" +msgstr "स्लोवेनियन" + +msgid "Albanian" +msgstr "अल्बेनियन्" + +msgid "Serbian" +msgstr "सर्बियन" + +msgid "Serbian Latin" +msgstr "सर्बियाई लैटिन" + +msgid "Swedish" +msgstr "स्वीडिश" + +msgid "Swahili" +msgstr "स्वाहिली" + +msgid "Tamil" +msgstr "तमिल" + +msgid "Telugu" +msgstr "तेलुगु" + +msgid "Tajik" +msgstr "" + +msgid "Thai" +msgstr "थाई" + +msgid "Turkmen" +msgstr "" + +msgid "Turkish" +msgstr "तुर्किश" + +msgid "Tatar" +msgstr "तातार" + +msgid "Udmurt" +msgstr "उद्मर्त" + +msgid "Ukrainian" +msgstr "यूक्रानियन" + +msgid "Urdu" +msgstr "उर्दू" + +msgid "Uzbek" +msgstr "उज़्बेक" + +msgid "Vietnamese" +msgstr "वियतनामी" + +msgid "Simplified Chinese" +msgstr "सरल चीनी" + +msgid "Traditional Chinese" +msgstr "पारम्परिक चीनी" + +msgid "Messages" +msgstr "संदेश" + +msgid "Site Maps" +msgstr "साइट मैप" + +msgid "Static Files" +msgstr "स्थिर फ़ाइलें" + +msgid "Syndication" +msgstr "सिंडिकेशन" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "" + +msgid "That page number is not an integer" +msgstr "यह पृष्ठ संख्या पूर्णांक नहीं है" + +msgid "That page number is less than 1" +msgstr "यह पृष्ठ संख्या 1 से कम है " + +msgid "That page contains no results" +msgstr "उस पृष्ठ पर कोई परिणाम नहीं हैं" + +msgid "Enter a valid value." +msgstr "एक मान्य मूल्य दर्ज करें" + +msgid "Enter a valid URL." +msgstr "वैध यू.आर.एल भरें ।" + +msgid "Enter a valid integer." +msgstr "एक मान्य पूर्ण संख्या दर्ज करें" + +msgid "Enter a valid email address." +msgstr "वैध डाक पता प्रविष्ट करें।" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "वैध आइ.पि वी 4 पता भरें ।" + +msgid "Enter a valid IPv6 address." +msgstr "वैध IPv6 पता दर्ज करें." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "वैध IPv4 या IPv6 पता दर्ज करें." + +msgid "Enter only digits separated by commas." +msgstr "अल्पविराम अंक मात्र ही भरें ।" + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"सुनिश्चित करें कि यह मान %(limit_value)s (यह\n" +" %(show_value)s है) है ।" + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "सुनिश्चित करें कि यह मान %(limit_value)s से कम या बराबर है ।" + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "सुनिश्चित करें यह मान %(limit_value)s से बड़ा या बराबर है ।" + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Enter a number." +msgstr "एक संख्या दर्ज करें ।" + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "और" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "यह मूल्य खाली नहीं हो सकता ।" + +msgid "This field cannot be blank." +msgstr "इस फ़ील्ड रिक्त नहीं हो सकता है." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "इस %(field_label)s के साथ एक %(model_name)s पहले से ही उपस्थित है ।" + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "फील्ड के प्रकार: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "बूलियन (सही अथ‌वा गलत)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "स्ट्रिंग (अधिकतम लम्बाई %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "अल्पविराम सीमांकित संख्या" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "तिथि (बिना समय)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "तिथि (समय के साथ)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "दशमलव संख्या" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "अवधि" + +msgid "Email address" +msgstr "ईमेल पता" + +msgid "File path" +msgstr "संचिका पथ" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "चल बिन्दु संख्या" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "पूर्णांक" + +msgid "Big (8 byte) integer" +msgstr "बड़ा (8 बाइट) पूर्णांक " + +msgid "Small integer" +msgstr "छोटा पूर्णांक" + +msgid "IPv4 address" +msgstr "IPv4 पता" + +msgid "IP address" +msgstr "आइ.पि पता" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "बूलियन (सही, गलत या कुछ नहीं)" + +msgid "Positive big integer" +msgstr "" + +msgid "Positive integer" +msgstr "धनात्मक पूर्णांक" + +msgid "Positive small integer" +msgstr "धनात्मक छोटा पूर्णांक" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "स्लग (%(max_length)s तक)" + +msgid "Text" +msgstr "पाठ" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "समय" + +msgid "URL" +msgstr "यू.आर.एल" + +msgid "Raw binary data" +msgstr "" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "फाइल" + +msgid "Image" +msgstr "छवि" + +msgid "A JSON object" +msgstr "एक JSON डेटा object" + +msgid "Value must be valid JSON." +msgstr "दर्ज किया गया डेटा वैध JSON होना अनिवार्य है" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "विदेशी कुंजी (संबंधित क्षेत्र के द्वारा प्रकार निर्धारित)" + +msgid "One-to-one relationship" +msgstr "एक-एक संबंध" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "बहुत से कई संबंध" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr "" + +msgid "This field is required." +msgstr "यह क्षेत्र अपेक्षित हैं" + +msgid "Enter a whole number." +msgstr "एक पूर्ण संख्या दर्ज करें ।" + +msgid "Enter a valid date." +msgstr "वैध तिथि भरें ।" + +msgid "Enter a valid time." +msgstr "वैध समय भरें ।" + +msgid "Enter a valid date/time." +msgstr "वैध तिथि/समय भरें ।" + +msgid "Enter a valid duration." +msgstr "एक वैध अवधी दर्ज करें" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "दिनों की संख्या {min_days} और {max_days} के बीच होना अनिवार्य है " + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "कोई संचिका निवेदित नहीं हुई । कृपया कूटलेखन की जाँच करें ।" + +msgid "No file was submitted." +msgstr "कोई संचिका निवेदित नहीं हुई ।" + +msgid "The submitted file is empty." +msgstr "निवेदित संचिका खाली है ।" + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "कृपया या फ़ाइल प्रस्तुत करे या साफ जांचपेटी की जाँच करे,दोनों नहीं ." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "वैध चित्र निवेदन करें । आप के द्वारा निवेदित संचिका अमान्य अथवा दूषित है ।" + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "मान्य इच्छा चयन करें । %(value)s लभ्य इच्छाओं में उप्लब्ध नहीं हैं ।" + +msgid "Enter a list of values." +msgstr "मूल्य सूची दर्ज करें ।" + +msgid "Enter a complete value." +msgstr "" + +msgid "Enter a valid UUID." +msgstr "एक वैध UUID भरें " + +msgid "Enter a valid JSON." +msgstr "एक वैध JSON भरें " + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr "" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "छाटें" + +msgid "Delete" +msgstr "मिटाएँ" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "कृपया %(field)s के लिए डुप्लिकेट डेटा को सही करे." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "कृपया %(field)s के डुप्लिकेट डेटा जो अद्वितीय होना चाहिए को सही करें." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"कृपया %(field_name)s के लिए डुप्लिकेट डेटा को सही करे जो %(date_field)s में " +"%(lookup)s के लिए अद्वितीय होना चाहिए." + +msgid "Please correct the duplicate values below." +msgstr "कृपया डुप्लिकेट मानों को सही करें." + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "मान्य विकल्प चयन करें । यह विकल्प उपस्थित विकल्पों में नहीं है ।" + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "रिक्त करें" + +msgid "Currently" +msgstr "फिलहाल" + +msgid "Change" +msgstr "बदलें" + +msgid "Unknown" +msgstr "अनजान" + +msgid "Yes" +msgstr "हाँ" + +msgid "No" +msgstr "नहीं" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "हाँ,नहीं,शायद" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d बाइट" +msgstr[1] "%(size)d बाइट" + +#, python-format +msgid "%s KB" +msgstr "%s केबी " + +#, python-format +msgid "%s MB" +msgstr "%s मेबी " + +#, python-format +msgid "%s GB" +msgstr "%s जीबी " + +#, python-format +msgid "%s TB" +msgstr "%s टीबी" + +#, python-format +msgid "%s PB" +msgstr "%s पीबी" + +msgid "p.m." +msgstr "बजे" + +msgid "a.m." +msgstr "बजे" + +msgid "PM" +msgstr "बजे" + +msgid "AM" +msgstr "बजे" + +msgid "midnight" +msgstr "मध्यरात्री" + +msgid "noon" +msgstr "दोपहर" + +msgid "Monday" +msgstr "सोम‌वार" + +msgid "Tuesday" +msgstr "मंगलवार" + +msgid "Wednesday" +msgstr "बुधवार" + +msgid "Thursday" +msgstr "गुरूवार" + +msgid "Friday" +msgstr "शुक्रवार" + +msgid "Saturday" +msgstr "शनिवार" + +msgid "Sunday" +msgstr "रविवार" + +msgid "Mon" +msgstr "सोम" + +msgid "Tue" +msgstr "मंगल" + +msgid "Wed" +msgstr "बुध" + +msgid "Thu" +msgstr "गुरू" + +msgid "Fri" +msgstr "शुक्र" + +msgid "Sat" +msgstr "शनि" + +msgid "Sun" +msgstr "रवि" + +msgid "January" +msgstr "जनवरी" + +msgid "February" +msgstr "फ़रवरी" + +msgid "March" +msgstr "मार्च" + +msgid "April" +msgstr "अप्रैल" + +msgid "May" +msgstr "मई" + +msgid "June" +msgstr "जून" + +msgid "July" +msgstr "जुलाई" + +msgid "August" +msgstr "अगस्त" + +msgid "September" +msgstr "सितमबर" + +msgid "October" +msgstr "अक्टूबर" + +msgid "November" +msgstr "नवमबर" + +msgid "December" +msgstr "दिसमबर" + +msgid "jan" +msgstr "जन" + +msgid "feb" +msgstr "फ़र" + +msgid "mar" +msgstr "मा" + +msgid "apr" +msgstr "अप्र" + +msgid "may" +msgstr "मई" + +msgid "jun" +msgstr "जून" + +msgid "jul" +msgstr "जुल" + +msgid "aug" +msgstr "अग" + +msgid "sep" +msgstr "सित" + +msgid "oct" +msgstr "अक्ट" + +msgid "nov" +msgstr "नव" + +msgid "dec" +msgstr "दिस्" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "जनवरी." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "फ़रवरी." + +msgctxt "abbrev. month" +msgid "March" +msgstr "मार्च" + +msgctxt "abbrev. month" +msgid "April" +msgstr "अप्रैल" + +msgctxt "abbrev. month" +msgid "May" +msgstr "मई" + +msgctxt "abbrev. month" +msgid "June" +msgstr "जून" + +msgctxt "abbrev. month" +msgid "July" +msgstr "जुलाई" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "अग." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "सितम्बर." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "अक्टूबर" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "नवम्बर." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "दिसम्बर" + +msgctxt "alt. month" +msgid "January" +msgstr "जनवरी" + +msgctxt "alt. month" +msgid "February" +msgstr "फरवरी" + +msgctxt "alt. month" +msgid "March" +msgstr "मार्च" + +msgctxt "alt. month" +msgid "April" +msgstr "अप्रैल" + +msgctxt "alt. month" +msgid "May" +msgstr "मई" + +msgctxt "alt. month" +msgid "June" +msgstr "जून" + +msgctxt "alt. month" +msgid "July" +msgstr "जुलाई" + +msgctxt "alt. month" +msgid "August" +msgstr "अगस्त" + +msgctxt "alt. month" +msgid "September" +msgstr "सितंबर" + +msgctxt "alt. month" +msgid "October" +msgstr "अक्टूबर" + +msgctxt "alt. month" +msgid "November" +msgstr "नवंबर" + +msgctxt "alt. month" +msgid "December" +msgstr "दिसंबर" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "अथवा" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "" +msgstr[1] "" + +msgid "Forbidden" +msgstr "" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF सत्यापन असफल रहा. Request निरस्त की गई " + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "कोई साल निर्दिष्ट नहीं किया गया " + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "कोई महीने निर्दिष्ट नहीं किया गया " + +msgid "No day specified" +msgstr "कोई दिन निर्दिष्ट नहीं किया गया " + +msgid "No week specified" +msgstr "कोई सप्ताह निर्दिष्ट नहीं किया गया " + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "%(verbose_name_plural)s उपलब्ध नहीं है" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"भविष्य %(verbose_name_plural)s उपलब्ध नहीं है क्योंकि %(class_name)s.allow_future " +"गलत है." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr " इस प्रश्न %(verbose_name)s से मेल नहीं खाते है" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "अवैध पन्ना (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "निर्देशिका अनुक्रमित की अनुमति यहाँ नहीं है." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "%(directory)s का अनुक्रमणिका" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hi/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hi/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hi/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hi/formats.py new file mode 100644 index 0000000..ac078ec --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hi/formats.py @@ -0,0 +1,21 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j F Y" +TIME_FORMAT = "g:i A" +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "d-m-Y" +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = "." +THOUSAND_SEPARATOR = "," +# NUMBER_GROUPING = diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f7afa5d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hr/LC_MESSAGES/django.po new file mode 100644 index 0000000..574a7ab --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hr/LC_MESSAGES/django.po @@ -0,0 +1,1274 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# aljosa , 2011,2013 +# Berislav Lopac , 2013 +# Bojan Mihelač , 2012 +# Boni Đukić , 2017 +# Jannis Leidel , 2011 +# Mislav Cimperšak , 2015-2016 +# Nino , 2013 +# senko , 2012 +# Ylodi , 2011 +# zmasek , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Croatian (http://www.transifex.com/django/django/language/" +"hr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hr\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +msgid "Afrikaans" +msgstr "Afrikaans" + +msgid "Arabic" +msgstr "Arapski" + +msgid "Asturian" +msgstr "Asturijski" + +msgid "Azerbaijani" +msgstr "Azarbejdžanac" + +msgid "Bulgarian" +msgstr "Unesite ispravnu IPv4 adresu." + +msgid "Belarusian" +msgstr "Bjeloruski" + +msgid "Bengali" +msgstr "Bengalski" + +msgid "Breton" +msgstr "Bretonski" + +msgid "Bosnian" +msgstr "Bošnjački" + +msgid "Catalan" +msgstr "Katalanski" + +msgid "Czech" +msgstr "Češki" + +msgid "Welsh" +msgstr "Velški" + +msgid "Danish" +msgstr "Danski" + +msgid "German" +msgstr "Njemački" + +msgid "Lower Sorbian" +msgstr "Donjolužičkosrpski" + +msgid "Greek" +msgstr "Grčki" + +msgid "English" +msgstr "Engleski" + +msgid "Australian English" +msgstr "Australski engleski" + +msgid "British English" +msgstr "Britanski engleski" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Španjolski" + +msgid "Argentinian Spanish" +msgstr "Argentinski španjolski" + +msgid "Colombian Spanish" +msgstr "Kolumbijski španjolski" + +msgid "Mexican Spanish" +msgstr "Meksički španjolski" + +msgid "Nicaraguan Spanish" +msgstr "Nikaragvanski Španjolski" + +msgid "Venezuelan Spanish" +msgstr "Venezuelanski Španjolski" + +msgid "Estonian" +msgstr "Estonski" + +msgid "Basque" +msgstr "Baskijski" + +msgid "Persian" +msgstr "Perzijski" + +msgid "Finnish" +msgstr "Finski" + +msgid "French" +msgstr "Francuski" + +msgid "Frisian" +msgstr "Frizijski" + +msgid "Irish" +msgstr "Irski" + +msgid "Scottish Gaelic" +msgstr "Škotski gaelski" + +msgid "Galician" +msgstr "Galičanski" + +msgid "Hebrew" +msgstr "Hebrejski" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Hrvatski" + +msgid "Upper Sorbian" +msgstr "Gornjolužičkosrpski" + +msgid "Hungarian" +msgstr "Mađarski" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonezijski" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Islandski" + +msgid "Italian" +msgstr "Talijanski" + +msgid "Japanese" +msgstr "Japanski" + +msgid "Georgian" +msgstr "Gruzijski" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "Kazaški" + +msgid "Khmer" +msgstr "Kambođanski" + +msgid "Kannada" +msgstr "Kannada" + +msgid "Korean" +msgstr "Koreanski" + +msgid "Luxembourgish" +msgstr "Luksemburški" + +msgid "Lithuanian" +msgstr "Litvanski" + +msgid "Latvian" +msgstr "Latvijski" + +msgid "Macedonian" +msgstr "Makedonski" + +msgid "Malayalam" +msgstr "Malayalam" + +msgid "Mongolian" +msgstr "Mongolski" + +msgid "Marathi" +msgstr "Marathi" + +msgid "Burmese" +msgstr "Burmanski" + +msgid "Norwegian Bokmål" +msgstr "Bokmål" + +msgid "Nepali" +msgstr "Nepalski" + +msgid "Dutch" +msgstr "Nizozemski" + +msgid "Norwegian Nynorsk" +msgstr "Norveški Nynorsk" + +msgid "Ossetic" +msgstr "Osetski" + +msgid "Punjabi" +msgstr "Pendžabljanin" + +msgid "Polish" +msgstr "Poljski" + +msgid "Portuguese" +msgstr "Portugalski" + +msgid "Brazilian Portuguese" +msgstr "Brazilski portugalski" + +msgid "Romanian" +msgstr "Rumunjski" + +msgid "Russian" +msgstr "Ruski" + +msgid "Slovak" +msgstr "Slovački" + +msgid "Slovenian" +msgstr "Slovenski" + +msgid "Albanian" +msgstr "Albanski" + +msgid "Serbian" +msgstr "Srpski" + +msgid "Serbian Latin" +msgstr "Latinski srpski" + +msgid "Swedish" +msgstr "Švedski" + +msgid "Swahili" +msgstr "Swahili" + +msgid "Tamil" +msgstr "Tamilski" + +msgid "Telugu" +msgstr "Teluški" + +msgid "Thai" +msgstr "Thai (tajlandski)" + +msgid "Turkish" +msgstr "Turski" + +msgid "Tatar" +msgstr "Tatarski" + +msgid "Udmurt" +msgstr "Udmurtski" + +msgid "Ukrainian" +msgstr "Ukrajinski" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "Vijetnamski" + +msgid "Simplified Chinese" +msgstr "Pojednostavljeni kineski" + +msgid "Traditional Chinese" +msgstr "Tradicionalni kineski" + +msgid "Messages" +msgstr "Poruke" + +msgid "Site Maps" +msgstr "Mape stranica" + +msgid "Static Files" +msgstr "Statične datoteke" + +msgid "Syndication" +msgstr "" + +msgid "That page number is not an integer" +msgstr "Broj stranice nije cijeli broj" + +msgid "That page number is less than 1" +msgstr "Broj stranice je manji od 1" + +msgid "That page contains no results" +msgstr "Stranica ne sadrži rezultate" + +msgid "Enter a valid value." +msgstr "Unesite ispravnu vrijednost." + +msgid "Enter a valid URL." +msgstr "Unesite ispravan URL." + +msgid "Enter a valid integer." +msgstr "Unesite vrijednost u obliku cijelog broja." + +msgid "Enter a valid email address." +msgstr "Unesite ispravnu e-mail adresu." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Unesite ispravnu IPv4 adresu." + +msgid "Enter a valid IPv6 address." +msgstr "Unesite ispravnu IPv6 adresu." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Unesite ispravnu IPv4 ili IPv6 adresu." + +msgid "Enter only digits separated by commas." +msgstr "Unesite samo brojeve razdvojene zarezom." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Osigurajte da ova vrijednost ima %(limit_value)s (trenutno je " +"%(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Osigurajte da je ova vrijednost manja ili jednaka %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Osigurajte da je ova vrijednost veća ili jednaka %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Osigurajte da ova vrijednost ima najmanje %(limit_value)d znak (trenutno ima " +"%(show_value)d)." +msgstr[1] "" +"Osigurajte da ova vrijednost ima najmanje %(limit_value)d znakova (trenutno " +"ima %(show_value)d)." +msgstr[2] "" +"Osigurajte da ova vrijednost ima najmanje %(limit_value)d znakova (trenutno " +"ima %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Osigurajte da ova vrijednost ima najviše %(limit_value)d znak (trenutno ima " +"%(show_value)d)." +msgstr[1] "" +"Osigurajte da ova vrijednost ima najviše %(limit_value)d znakova (trenutno " +"ima %(show_value)d)." +msgstr[2] "" +"Osigurajte da ova vrijednost ima najviše %(limit_value)d znakova (trenutno " +"ima %(show_value)d)." + +msgid "Enter a number." +msgstr "Unesite broj." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Osigurajte da nema više od ukupno %(max)s numeričkog znaka." +msgstr[1] "Osigurajte da nema više od ukupno %(max)s numerička znaka." +msgstr[2] "Osigurajte da nema više od ukupno %(max)s numeričkih znakova." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Osigurajte da nema više od ukupno %(max)s decimalnog mjesta." +msgstr[1] "Osigurajte da nema više od ukupno %(max)s decimalna mjesta." +msgstr[2] "Osigurajte da nema više od ukupno %(max)s decimalnih mjesta." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Osigurajte da nema više od ukupno %(max)s numberičkog znaka prije decimalne " +"točke." +msgstr[1] "" +"Osigurajte da nema više od ukupno %(max)s numberička znaka prije decimalne " +"točke." +msgstr[2] "" +"Osigurajte da nema više od ukupno %(max)s numberičkih znakova prije " +"decimalne točke." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "i" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s sa navedenim %(field_labels)s već postoji." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Vrijednost %(value)r nije jedna od raspoloživih opcija." + +msgid "This field cannot be null." +msgstr "Ovo polje ne može biti null." + +msgid "This field cannot be blank." +msgstr "Ovo polje ne može biti prazno." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s sa navedenim %(field_label)s već postoji." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s mora biti jedinstven pojam za %(date_field_label)s " +"%(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Polje tipa: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "Boolean (True ili False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Slova (do %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "Cijeli brojevi odvojeni zarezom" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "Datum (bez vremena/sati)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Datum (sa vremenom/satima)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Decimalni broj" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "Trajanje" + +msgid "Email address" +msgstr "E-mail adresa" + +msgid "File path" +msgstr "Put do datoteke" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "Broj s pomičnim zarezom (floating point number)" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "Cijeli broj" + +msgid "Big (8 byte) integer" +msgstr "Big (8 byte) integer" + +msgid "IPv4 address" +msgstr "IPv4 adresa" + +msgid "IP address" +msgstr "IP adresa" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "Boolean (True, False ili None)" + +msgid "Positive integer" +msgstr "Pozitivan cijeli broj" + +msgid "Positive small integer" +msgstr "Pozitivan mali cijeli broj" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "'Slug' (do %(max_length)s)" + +msgid "Small integer" +msgstr "Mali broj" + +msgid "Text" +msgstr "Tekst" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Vrijeme" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Binarni podaci" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "Datoteka" + +msgid "Image" +msgstr "Slika" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(model)s instanca sa %(field)s %(value)r ne postoji." + +msgid "Foreign Key (type determined by related field)" +msgstr "Foreign Key (type determined by related field)" + +msgid "One-to-one relationship" +msgstr "One-to-one relationship" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s veza" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s veze" + +msgid "Many-to-many relationship" +msgstr "Many-to-many relationship" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Unos za ovo polje je obavezan." + +msgid "Enter a whole number." +msgstr "Unesite cijeli broj." + +msgid "Enter a valid date." +msgstr "Unesite ispravan datum." + +msgid "Enter a valid time." +msgstr "Unesite ispravno vrijeme." + +msgid "Enter a valid date/time." +msgstr "Unesite ispravan datum/vrijeme." + +msgid "Enter a valid duration." +msgstr "Unesite ispravno trajanje." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Datoteka nije poslana. Provjerite 'encoding type' forme." + +msgid "No file was submitted." +msgstr "Datoteka nije poslana." + +msgid "The submitted file is empty." +msgstr "Poslana datoteka je prazna." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Osigurajte da naziv datoteke ima najviše %(max)d znak (ima %(length)d)." +msgstr[1] "" +"Osigurajte da naziv datoteke ima najviše %(max)d znakova (ima %(length)d)." +msgstr[2] "" +"Osigurajte da naziv datoteke ima najviše %(max)d znakova (ima %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Molimo Vas da pošaljete ili datoteku ili označite izbor, a ne oboje." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Upload-ajte ispravnu sliku. Datoteka koju ste upload-ali ili nije slika ili " +"je oštečena." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Odaberite iz ponuđenog. %(value)s nije ponuđen kao opcija." + +msgid "Enter a list of values." +msgstr "Unesite listu vrijednosti." + +msgid "Enter a complete value." +msgstr "Unesite kompletnu vrijednost." + +msgid "Enter a valid UUID." +msgstr "Unesite ispravan UUID." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Skriveno polje %(name)s) %(error)s" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "ManagementForm podaci nedostaju ili su promijenjeni" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "Molimo unesite %d obrazac." +msgstr[1] "Molimo unesite %d ili manje obrazaca." +msgstr[2] "Molimo unesite %d ili manje obrazaca." + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "Molimo unesite %d ili više obrazaca." +msgstr[1] "Molimo unesite %d ili više obrazaca." +msgstr[2] "Molimo unesite %d ili više obrazaca." + +msgid "Order" +msgstr "Redoslijed:" + +msgid "Delete" +msgstr "Izbriši" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Ispravite duplicirane podatke za %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Molimo ispravite duplicirane podatke za %(field)s, koji moraju biti " +"jedinstveni." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Molimo ispravite duplicirane podatke za %(field_name)s koji moraju biti " +"jedinstveni za %(lookup)s u %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Molimo ispravite duplicirane vrijednosti ispod." + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Izaberite ispravnu opciju. Ta opcija nije jedna od dostupnih opcija." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Isprazni" + +msgid "Currently" +msgstr "Trenutno" + +msgid "Change" +msgstr "Promijeni" + +msgid "Unknown" +msgstr "Nepoznat pojam" + +msgid "Yes" +msgstr "Da" + +msgid "No" +msgstr "Ne" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "da,ne,možda" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d byte" +msgstr[1] "%(size)d byte-a" +msgstr[2] "%(size)d byte-a" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "popodne" + +msgid "a.m." +msgstr "ujutro" + +msgid "PM" +msgstr "popodne" + +msgid "AM" +msgstr "ujutro" + +msgid "midnight" +msgstr "ponoć" + +msgid "noon" +msgstr "podne" + +msgid "Monday" +msgstr "Ponedjeljak" + +msgid "Tuesday" +msgstr "Utorak" + +msgid "Wednesday" +msgstr "Srijeda" + +msgid "Thursday" +msgstr "Četvrtak" + +msgid "Friday" +msgstr "Petak" + +msgid "Saturday" +msgstr "Subota" + +msgid "Sunday" +msgstr "Nedjelja" + +msgid "Mon" +msgstr "Pon" + +msgid "Tue" +msgstr "Uto" + +msgid "Wed" +msgstr "Sri" + +msgid "Thu" +msgstr "Čet" + +msgid "Fri" +msgstr "Pet" + +msgid "Sat" +msgstr "Sub" + +msgid "Sun" +msgstr "Ned" + +msgid "January" +msgstr "Siječanj" + +msgid "February" +msgstr "Veljača" + +msgid "March" +msgstr "Ožujak" + +msgid "April" +msgstr "Travanj" + +msgid "May" +msgstr "Svibanj" + +msgid "June" +msgstr "Lipanj" + +msgid "July" +msgstr "Srpanj" + +msgid "August" +msgstr "Kolovoz" + +msgid "September" +msgstr "Rujan" + +msgid "October" +msgstr "Listopad" + +msgid "November" +msgstr "Studeni" + +msgid "December" +msgstr "Prosinac" + +msgid "jan" +msgstr "sij." + +msgid "feb" +msgstr "velj." + +msgid "mar" +msgstr "ožu." + +msgid "apr" +msgstr "tra." + +msgid "may" +msgstr "svi." + +msgid "jun" +msgstr "lip." + +msgid "jul" +msgstr "srp." + +msgid "aug" +msgstr "kol." + +msgid "sep" +msgstr "ruj." + +msgid "oct" +msgstr "lis." + +msgid "nov" +msgstr "stu." + +msgid "dec" +msgstr "pro." + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Sij." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Velj." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Ožu." + +msgctxt "abbrev. month" +msgid "April" +msgstr "Tra." + +msgctxt "abbrev. month" +msgid "May" +msgstr "Svi." + +msgctxt "abbrev. month" +msgid "June" +msgstr "Lip." + +msgctxt "abbrev. month" +msgid "July" +msgstr "Srp." + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Kol." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Ruj." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Lis." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Stu." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Pro." + +msgctxt "alt. month" +msgid "January" +msgstr "siječnja" + +msgctxt "alt. month" +msgid "February" +msgstr "veljače" + +msgctxt "alt. month" +msgid "March" +msgstr "ožujka" + +msgctxt "alt. month" +msgid "April" +msgstr "travnja" + +msgctxt "alt. month" +msgid "May" +msgstr "svibnja" + +msgctxt "alt. month" +msgid "June" +msgstr "lipnja" + +msgctxt "alt. month" +msgid "July" +msgstr "srpnja" + +msgctxt "alt. month" +msgid "August" +msgstr "kolovoza" + +msgctxt "alt. month" +msgid "September" +msgstr "rujna" + +msgctxt "alt. month" +msgid "October" +msgstr "listopada" + +msgctxt "alt. month" +msgid "November" +msgstr "studenoga" + +msgctxt "alt. month" +msgid "December" +msgstr "prosinca" + +msgid "This is not a valid IPv6 address." +msgstr "To nije ispravna IPv6 adresa." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "ili" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "," + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d godina" +msgstr[1] "%d godina" +msgstr[2] "%d godina" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d mjesec" +msgstr[1] "%d mjeseci" +msgstr[2] "%d mjeseci" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d tjedan" +msgstr[1] "%d tjedna" +msgstr[2] "%d tjedana" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d dana" +msgstr[1] "%d dana" +msgstr[2] "%d dana" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d sat" +msgstr[1] "%d sati" +msgstr[2] "%d sati" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d minutu" +msgstr[1] "%d minute" +msgstr[2] "%d minuta" + +msgid "0 minutes" +msgstr "0 minuta" + +msgid "Forbidden" +msgstr "Zabranjeno" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF verifikacija nije uspjela. Zahtjev je prekinut." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Ova poruka vam se prikazuje jer stranica na kojoj se nalazite zahtjeva CSRF " +"kolačić prilikom slanja forme. Navedeni kolačić je obavezan iz sigurnosnih " +"razloga, kako bi se osiguralo da vaš internetski preglednik ne bude otet od " +"strane trećih osoba." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "Dodatne informacije su dostupne sa postavkom DEBUG=True." + +msgid "No year specified" +msgstr "Nije navedena godina" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "Nije naveden mjesec" + +msgid "No day specified" +msgstr "Nije naveden dan" + +msgid "No week specified" +msgstr "Tjedan nije određen" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Nije dostupno: %(verbose_name_plural)s" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"%(verbose_name_plural)s nije dostupno jer je %(class_name)s.allow_future " +"False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "%(verbose_name)s - pretragom nisu pronađeni rezultati za upit" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Nevažeća stranica (%(page_number)s):%(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Sadržaji direktorija ovdje nisu dozvoljeni." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Sadržaj direktorija %(directory)s" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hr/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hr/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hr/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hr/formats.py new file mode 100644 index 0000000..a2dc457 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hr/formats.py @@ -0,0 +1,44 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j. E Y." +TIME_FORMAT = "H:i" +DATETIME_FORMAT = "j. E Y. H:i" +YEAR_MONTH_FORMAT = "F Y." +MONTH_DAY_FORMAT = "j. F" +SHORT_DATE_FORMAT = "j.m.Y." +SHORT_DATETIME_FORMAT = "j.m.Y. H:i" +FIRST_DAY_OF_WEEK = 1 + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# Kept ISO formats as they are in first position +DATE_INPUT_FORMATS = [ + "%Y-%m-%d", # '2006-10-25' + "%d.%m.%Y.", # '25.10.2006.' + "%d.%m.%y.", # '25.10.06.' + "%d. %m. %Y.", # '25. 10. 2006.' + "%d. %m. %y.", # '25. 10. 06.' +] +DATETIME_INPUT_FORMATS = [ + "%Y-%m-%d %H:%M:%S", # '2006-10-25 14:30:59' + "%Y-%m-%d %H:%M:%S.%f", # '2006-10-25 14:30:59.000200' + "%Y-%m-%d %H:%M", # '2006-10-25 14:30' + "%d.%m.%Y. %H:%M:%S", # '25.10.2006. 14:30:59' + "%d.%m.%Y. %H:%M:%S.%f", # '25.10.2006. 14:30:59.000200' + "%d.%m.%Y. %H:%M", # '25.10.2006. 14:30' + "%d.%m.%y. %H:%M:%S", # '25.10.06. 14:30:59' + "%d.%m.%y. %H:%M:%S.%f", # '25.10.06. 14:30:59.000200' + "%d.%m.%y. %H:%M", # '25.10.06. 14:30' + "%d. %m. %Y. %H:%M:%S", # '25. 10. 2006. 14:30:59' + "%d. %m. %Y. %H:%M:%S.%f", # '25. 10. 2006. 14:30:59.000200' + "%d. %m. %Y. %H:%M", # '25. 10. 2006. 14:30' + "%d. %m. %y. %H:%M:%S", # '25. 10. 06. 14:30:59' + "%d. %m. %y. %H:%M:%S.%f", # '25. 10. 06. 14:30:59.000200' + "%d. %m. %y. %H:%M", # '25. 10. 06. 14:30' +] + +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hsb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hsb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..600b787 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hsb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hsb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hsb/LC_MESSAGES/django.po new file mode 100644 index 0000000..a5fb97c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hsb/LC_MESSAGES/django.po @@ -0,0 +1,1377 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Michael Wolf , 2016-2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Michael Wolf , 2016-2023\n" +"Language-Team: Upper Sorbian (http://app.transifex.com/django/django/" +"language/hsb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hsb\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || " +"n%100==4 ? 2 : 3);\n" + +msgid "Afrikaans" +msgstr "Afrikaanšćina" + +msgid "Arabic" +msgstr "Arabšćina" + +msgid "Algerian Arabic" +msgstr "Algeriska arabšćina" + +msgid "Asturian" +msgstr "Asturišćina" + +msgid "Azerbaijani" +msgstr "Azerbajdźanšćina" + +msgid "Bulgarian" +msgstr "Bołharšćina" + +msgid "Belarusian" +msgstr "Běłorušćina" + +msgid "Bengali" +msgstr "Bengalšćina" + +msgid "Breton" +msgstr "Bretonšćina" + +msgid "Bosnian" +msgstr "Bosnišćina" + +msgid "Catalan" +msgstr "Katalanšćina" + +msgid "Central Kurdish (Sorani)" +msgstr "Centralna kurdišćina (Sorani)" + +msgid "Czech" +msgstr "Čěšćina" + +msgid "Welsh" +msgstr "Walizišćina" + +msgid "Danish" +msgstr "Danšćina" + +msgid "German" +msgstr "Němčina" + +msgid "Lower Sorbian" +msgstr "Delnjoserbšćina" + +msgid "Greek" +msgstr "Grjekšćina" + +msgid "English" +msgstr "Jendźelšćina" + +msgid "Australian English" +msgstr "Awstralska jendźelšćina" + +msgid "British English" +msgstr "Britiska jendźelšćina" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Španišćina" + +msgid "Argentinian Spanish" +msgstr "Argentinska španišćina" + +msgid "Colombian Spanish" +msgstr "Kolumbiska španišćina" + +msgid "Mexican Spanish" +msgstr "Mexiska španišćina" + +msgid "Nicaraguan Spanish" +msgstr "Nikaraguaska španišćina" + +msgid "Venezuelan Spanish" +msgstr "Venezuelska španišćina" + +msgid "Estonian" +msgstr "Estišćina" + +msgid "Basque" +msgstr "Baskišćina" + +msgid "Persian" +msgstr "Persišćina" + +msgid "Finnish" +msgstr "Finšćina" + +msgid "French" +msgstr "Francošćina" + +msgid "Frisian" +msgstr "Frizišćina" + +msgid "Irish" +msgstr "Irišćina" + +msgid "Scottish Gaelic" +msgstr "Šotiska gaelšćina" + +msgid "Galician" +msgstr "Galicišćina" + +msgid "Hebrew" +msgstr "Hebrejšćina" + +msgid "Hindi" +msgstr "Hindišćina" + +msgid "Croatian" +msgstr "Chorwatšćina" + +msgid "Upper Sorbian" +msgstr "Hornjoserbšćina" + +msgid "Hungarian" +msgstr "Madźaršćina" + +msgid "Armenian" +msgstr "Armenšćina" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonezišćina" + +msgid "Igbo" +msgstr "Igbo" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Islandšćina" + +msgid "Italian" +msgstr "Italšćina" + +msgid "Japanese" +msgstr "Japanšćina" + +msgid "Georgian" +msgstr "Georgišćina" + +msgid "Kabyle" +msgstr "Kabylšćina" + +msgid "Kazakh" +msgstr "Kazachšćina" + +msgid "Khmer" +msgstr "Khmeršćina" + +msgid "Kannada" +msgstr "Kannadšćina" + +msgid "Korean" +msgstr "Korejšćina" + +msgid "Kyrgyz" +msgstr "Kirgišćina" + +msgid "Luxembourgish" +msgstr "Luxemburgšćina" + +msgid "Lithuanian" +msgstr "Litawšćina" + +msgid "Latvian" +msgstr "Letišćina" + +msgid "Macedonian" +msgstr "Makedonšćina" + +msgid "Malayalam" +msgstr "Malajalam" + +msgid "Mongolian" +msgstr "Mongolšćina" + +msgid "Marathi" +msgstr "Marathišćina" + +msgid "Malay" +msgstr "Malajšćina" + +msgid "Burmese" +msgstr "Myanmaršćina" + +msgid "Norwegian Bokmål" +msgstr "Norwegski bokmål" + +msgid "Nepali" +msgstr "Nepalšćina" + +msgid "Dutch" +msgstr "Nižozemšćina" + +msgid "Norwegian Nynorsk" +msgstr "Norwegski nynorsk" + +msgid "Ossetic" +msgstr "Osetšćina" + +msgid "Punjabi" +msgstr "Pundźabišćina" + +msgid "Polish" +msgstr "Pólšćina" + +msgid "Portuguese" +msgstr "Portugalšćina" + +msgid "Brazilian Portuguese" +msgstr "Brazilska portugalšćina" + +msgid "Romanian" +msgstr "Rumunšćina" + +msgid "Russian" +msgstr "Rušćina" + +msgid "Slovak" +msgstr "Słowakšćina" + +msgid "Slovenian" +msgstr "Słowjenšćina" + +msgid "Albanian" +msgstr "Albanšćina" + +msgid "Serbian" +msgstr "Serbišćina" + +msgid "Serbian Latin" +msgstr "Serbšćina, łaćonska" + +msgid "Swedish" +msgstr "Šwedšćina" + +msgid "Swahili" +msgstr "Suahelšćina" + +msgid "Tamil" +msgstr "Tamilšćina" + +msgid "Telugu" +msgstr "Telugušćina" + +msgid "Tajik" +msgstr "Tadźikišćina" + +msgid "Thai" +msgstr "Thaišćina" + +msgid "Turkmen" +msgstr "Turkmenšćina" + +msgid "Turkish" +msgstr "Turkowšćina" + +msgid "Tatar" +msgstr "Tataršćina" + +msgid "Udmurt" +msgstr "Udmurtšćina" + +msgid "Uyghur" +msgstr "Ujguršćina" + +msgid "Ukrainian" +msgstr "Ukrainšćina" + +msgid "Urdu" +msgstr "Urdušćina" + +msgid "Uzbek" +msgstr "Uzbekšćina" + +msgid "Vietnamese" +msgstr "Vietnamšćina" + +msgid "Simplified Chinese" +msgstr "Zjednorjene chinšćina" + +msgid "Traditional Chinese" +msgstr "Tradicionalna chinšćina" + +msgid "Messages" +msgstr "Powěsće" + +msgid "Site Maps" +msgstr "Přehlady sydła" + +msgid "Static Files" +msgstr "Statiske dataje" + +msgid "Syndication" +msgstr "Syndikacija" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Tute čisko strony cyła ličba njeje." + +msgid "That page number is less than 1" +msgstr "Tute čisło strony je mjeńše hač 1." + +msgid "That page contains no results" +msgstr "Tuta strona wuslědki njewobsahuje" + +msgid "Enter a valid value." +msgstr "Zapodajće płaćiwu hódnotu." + +msgid "Enter a valid URL." +msgstr "Zapodajće płaćiwy URL." + +msgid "Enter a valid integer." +msgstr "Zapodajće płaćiwu cyłu ličbu." + +msgid "Enter a valid email address." +msgstr "Zapodajće płaćiwu e-mejlowu adresu." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Zapodajće płaćiwe adresowe mjeno, kotrež jenož pismiki, ličby, podsmužki abo " +"wjazawki wobsahuje." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Zapodajće płaćiwe „adresowe mjeno“, kotrež jenož pismiki, ličby, podsmužki " +"abo wjazawki wobsahuje." + +msgid "Enter a valid IPv4 address." +msgstr "Zapodajće płaćiwu IPv4-adresu." + +msgid "Enter a valid IPv6 address." +msgstr "Zapodajće płaćiwu IPv6-adresu." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Zapodajće płaćiwu IPv4- abo IPv6-adresu." + +msgid "Enter only digits separated by commas." +msgstr "Zapodajće jenož přez komy dźělene cyfry," + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Zawěsćće, zo tuta hódnota je %(limit_value)s (je %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Zawěsćće, zo hódnota je mjeńša hač abo runja %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Zawěsćće, zo tuta hódnota je wjetša hač abo runja %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" +"Zawěsćće, zo tuta hódnota je množina kročeloweje wulkosće %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"Zawěsćće, zo tuta hódnota je mnoho króć kročeloweje wulkosće " +"%(limit_value)s, započinajo z %(offset)s, na př. %(offset)s, " +"%(valid_value1)s, %(valid_value2)s a tak dale." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Zawěsćće, zo tuta hódnota ma znajmjeńša %(limit_value)d znamješko (ma " +"%(show_value)d)." +msgstr[1] "" +"Zawěsćće, zo tuta hódnota ma znajmjeńša %(limit_value)d znamješce (ma " +"%(show_value)d)." +msgstr[2] "" +"Zawěsćće, zo tuta hódnota ma znajmjeńša %(limit_value)d znamješka (ma " +"%(show_value)d)." +msgstr[3] "" +"Zawěsćće, zo tuta hódnota ma znajmjeńša %(limit_value)d znamješkow (ma " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Zawěsćće, zo tuta hódnota ma maksimalnje %(limit_value)d znamješko (ima " +"%(show_value)d)." +msgstr[1] "" +"Zawěsćće, zo tuta hódnota ma maksimalnje %(limit_value)d znamješce (ima " +"%(show_value)d)." +msgstr[2] "" +"Zawěsćće, zo tuta hódnota ma maksimalnje %(limit_value)d znamješka (ima " +"%(show_value)d)." +msgstr[3] "" +"Zawěsćće, zo tuta hódnota ma maksimalnje %(limit_value)d znamješkow (ima " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Zapodajće ličbu." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Zawěsćće, zo njeje wjace hač %(max)s cyfry dohromady." +msgstr[1] "Zawěsćće, zo njeje wjace hač %(max)s cyfrow dohromady." +msgstr[2] "Zawěsćće, zo njeje wjace hač %(max)s cyfrow dohromady." +msgstr[3] "Zawěsćće, zo njeje wjace hač %(max)s cyfrow dohromady." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Zawěsćće, zo njeje wjace hač %(max)s decimalneho městna." +msgstr[1] "Zawěsćće, zo njeje wjace hač %(max)s decimalneju městnow." +msgstr[2] "Zawěsćće, zo njeje wjace hač %(max)s decimalnych městnow." +msgstr[3] "Zawěsćće, zo njeje wjace hač %(max)s decimalnych městnow." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "Zawěsćće, zo njeje wjace hač %(max)s cyfry před decimalnej komu." +msgstr[1] "Zawěsćće, zo njeje wjace hač %(max)s cyfrow před decimalnej komu." +msgstr[2] "Zawěsćće, zo njeje wjace hač %(max)s cyfrow před decimalnej komu." +msgstr[3] "Zawěsćće, zo njeje wjace hač %(max)s cyfrow před decimalnej komu." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Datajowy sufiks ' %(extension)s' dowoleny njeje. Dowolene sufiksy su: " +"%(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Prózdne znamješka dowolene njejsu." + +msgid "and" +msgstr "a" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s z tutym %(field_labels)s hižo eksistuje." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Wobmjezowanje \"%(name)s\" je překročene." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Hódnota %(value)r płaćiwa wólba njeje." + +msgid "This field cannot be null." +msgstr "Tute polo njesmě nul być." + +msgid "This field cannot be blank." +msgstr "Tute polo njesmě prózdne być." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s z tutym %(field_label)s hižo eksistuje." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s dyrbi za %(date_field_label)s %(lookup_type)s jónkróćne być." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Polo typa: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "Hódnota „%(value)s“ dyrbi pak True pak False być." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "Hódnota „%(value)s“ dyrbi pak True, False pak None być." + +msgid "Boolean (Either True or False)" +msgstr "Boolean (pak True pak False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Znamješkowy rjećazk (hač %(max_length)s)" + +msgid "String (unlimited)" +msgstr "Znamješkowy rjećazk (njewobmjezowany)" + +msgid "Comma-separated integers" +msgstr "Cyłe ličby dźělene přez komu" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"Hódnota „%(value)s“ ma njepłaćiwy datumowy format. Dyrbi we formaće DD.MM." +"YYYY być." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"Hódnota „%(value)s“ ma korektny format (DD.MM.YYYY), ale je njepłaćiwy datum." + +msgid "Date (without time)" +msgstr "Datum (bjez časa)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"Hódnota „%(value)s“ ma njepłaćiwy format. Dyrbi we formaće DD.MM.YYYY HH:MM[:" +"ss[.uuuuuu]][TZ] być." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"Hódnota „%(value)s“ ma korektny format (DD.MM.YYYY HH:MM[:ss[.uuuuuu]][TZ]), " +"ale je njepłaćiwy datum/čas." + +msgid "Date (with time)" +msgstr "Datum (z časom)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "Hódnota „%(value)s“ dyrbi decimalna ličba być." + +msgid "Decimal number" +msgstr "Decimalna ličba" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"Hódnota „%(value)s“ ma njepłaćiwy format. Dyrbi w formaće [DD] [HH:[MM:]]ss[." +"uuuuuu] być." + +msgid "Duration" +msgstr "Traće" + +msgid "Email address" +msgstr "E-mejlowa adresa" + +msgid "File path" +msgstr "Datajowa šćežka" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "Hódnota „%(value)s“ dyrbi decimalna ličba być." + +msgid "Floating point number" +msgstr "Komowa ličba typa float" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "Hódnota „%(value)s“ dyrbi integer być." + +msgid "Integer" +msgstr "Integer" + +msgid "Big (8 byte) integer" +msgstr "Big (8 byte) integer" + +msgid "Small integer" +msgstr "Mała cyła ličba" + +msgid "IPv4 address" +msgstr "IPv4-adresa" + +msgid "IP address" +msgstr "IP-adresa" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "Hódnota „%(value)s“ dyrbi pak None, True pak False być." + +msgid "Boolean (Either True, False or None)" +msgstr "Boolean (pak True, False pak None)" + +msgid "Positive big integer" +msgstr "Pozitiwna wulka cyła ličba" + +msgid "Positive integer" +msgstr "Pozitiwna cyła ličba" + +msgid "Positive small integer" +msgstr "Pozitiwna mała cyła ličba" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Adresowe mjeno (hač %(max_length)s)" + +msgid "Text" +msgstr "Tekst" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"Hódnota „%(value)s“ ma njepłaćiwy format. Dyrbi we formaće HH:MM[:ss[." +"uuuuuu]] być." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"Hódnota „%(value)s“ ma korektny format (HH:MM[:ss[.uuuuuu]]), ale je " +"njepłaćiwy čas." + +msgid "Time" +msgstr "Čas" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Hrube binarne daty" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "„%(value)s“ płaćiwy UUID njeje." + +msgid "Universally unique identifier" +msgstr "Uniwerselnje jónkróćny identifikator" + +msgid "File" +msgstr "Dataja" + +msgid "Image" +msgstr "Wobraz" + +msgid "A JSON object" +msgstr "JSON-objekt" + +msgid "Value must be valid JSON." +msgstr "Hódnota dyrbi płaćiwy JSON być." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "Instanca %(model)s z %(field)s %(value)r njeeksistuje." + +msgid "Foreign Key (type determined by related field)" +msgstr "Cuzy kluč (typ so přez wotpowědne polo postaja)" + +msgid "One-to-one relationship" +msgstr "Poćah jedyn jedyn" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "Poćah %(from)s-%(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "Poćahi %(from)s-%(to)s" + +msgid "Many-to-many relationship" +msgstr "Poćah wjele wjele" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Tute polo je trěbne." + +msgid "Enter a whole number." +msgstr "Zapodajće cyłu ličbu." + +msgid "Enter a valid date." +msgstr "Zapodajće płaćiwy datum." + +msgid "Enter a valid time." +msgstr "Zapodajće płaćiwy čas." + +msgid "Enter a valid date/time." +msgstr "Zapodajće płaćiwy datum/čas." + +msgid "Enter a valid duration." +msgstr "Zapodajće płaćiwe traće." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Ličba dnjow dyrbi mjez {min_days} a {max_days} być." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Žana dataja je so pósłała. Přepruwujće kodowanski typ we formularje." + +msgid "No file was submitted." +msgstr "Žana dataja je so pósłała." + +msgid "The submitted file is empty." +msgstr "Pósłana dataja je prózdna." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Zawěsćće, zo tute datajowe mjeno ma maksimalnje %(max)d znamješko (ma " +"%(length)d)." +msgstr[1] "" +"Zawěsćće, zo tute datajowe mjeno ma maksimalnje %(max)d znamješce (ma " +"%(length)d)." +msgstr[2] "" +"Zawěsćće, zo tute datajowe mjeno ma maksimalnje %(max)d znamješka (ma " +"%(length)d)." +msgstr[3] "" +"Zawěsćće, zo tute datajowe mjeno ma maksimalnje %(max)d znamješkow (ma " +"%(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Prošu zapodajće dataju abo stajće hóčku do kontrolneho kašćika, nic wobě." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Nahrajće płaćiwy wobraz. Dataja, kotruž sće nahrał, pak njebě wobraz pak bě " +"wobškodźeny wobraz. " + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Wubjerće płaćiwu wolensku móžnosć. %(value)s žana k dispoziciji stejacych " +"wolenskich móžnosćow njeje. " + +msgid "Enter a list of values." +msgstr "Zapodajće lisćinu hódnotow." + +msgid "Enter a complete value." +msgstr "Zapodajće dospołnu hódnotu." + +msgid "Enter a valid UUID." +msgstr "Zapodajće płaćiwy UUID." + +msgid "Enter a valid JSON." +msgstr "Zapodajće płaćiwy JSON." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Schowane polo field %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"Daty ManagementForm faluja abo su skepsane. Falowace pola: %(field_names)s. " +"Móžeće zmylkowu rozprawu spisać, jeli problem dale eksistuje." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Prošu wotposćelće maksimalnje %(num)d formular." +msgstr[1] "Prošu wotposćelće maksimalnje %(num)d formularaj." +msgstr[2] "Prošu wotposćelće maksimalnje %(num)d formulary." +msgstr[3] "Prošu wotposćelće maksimalnje %(num)d formularow." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Prošu zapodajće znajmjeńša %(num)d formu." +msgstr[1] "Prošu zapodajće znajmjeńša %(num)d formje." +msgstr[2] "Prošu zapodajće znajmjeńša %(num)d formy." +msgstr[3] "Prošu zapodajće znajmjeńša %(num)d formow." + +msgid "Order" +msgstr "Porjad" + +msgid "Delete" +msgstr "Zhašeć" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Prošu porjedźće dwójne daty za %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Prošu porjedźće dwójne daty za %(field)s, kotrež dyrbja jónkróćne być." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Prošu porjedźće dwójne daty za %(field_name)s, kotrež dyrbja za %(lookup)s w " +"%(date_field)s jónkróćne być." + +msgid "Please correct the duplicate values below." +msgstr "Prošu porjedźće slědowace dwójne hódnoty." + +msgid "The inline value did not match the parent instance." +msgstr "Hódnota inline nadrjadowanej instancy njewotpowěduje." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Wubjerće płaćiwu wolensku móžnosć. Tuta wolenska móžnosć jedna z k " +"dispoziciji stejacych wolenskich móžnosćow njeje." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "\"%(pk)s\" płaćiwa hódnota njeje." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s njeda so w časowym pasmje %(current_timezone)s interpretować; " +"je snano dwuzmyslny abo njeeksistuje." + +msgid "Clear" +msgstr "Zhašeć" + +msgid "Currently" +msgstr "Tuchwilu" + +msgid "Change" +msgstr "Změnić" + +msgid "Unknown" +msgstr "Njeznaty" + +msgid "Yes" +msgstr "Haj" + +msgid "No" +msgstr "Ně" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "haj,ně,snano" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d bajt" +msgstr[1] "%(size)d bajtaj" +msgstr[2] "%(size)d bajty" +msgstr[3] "%(size)d bajtow" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "popołdnju" + +msgid "a.m." +msgstr "dopołdnja" + +msgid "PM" +msgstr "popołdnju" + +msgid "AM" +msgstr "dopołdnja" + +msgid "midnight" +msgstr "połnoc" + +msgid "noon" +msgstr "připołdnjo" + +msgid "Monday" +msgstr "Póndźela" + +msgid "Tuesday" +msgstr "Wutora" + +msgid "Wednesday" +msgstr "Srjeda" + +msgid "Thursday" +msgstr "Štwórtk" + +msgid "Friday" +msgstr "Pjatk" + +msgid "Saturday" +msgstr "Sobota" + +msgid "Sunday" +msgstr "Njedźela" + +msgid "Mon" +msgstr "Pón" + +msgid "Tue" +msgstr "Wut" + +msgid "Wed" +msgstr "Srj" + +msgid "Thu" +msgstr "Štw" + +msgid "Fri" +msgstr "Pja" + +msgid "Sat" +msgstr "Sob" + +msgid "Sun" +msgstr "Nje" + +msgid "January" +msgstr "Januar" + +msgid "February" +msgstr "Februar" + +msgid "March" +msgstr "Měrc" + +msgid "April" +msgstr "Apryl" + +msgid "May" +msgstr "Meja" + +msgid "June" +msgstr "Junij" + +msgid "July" +msgstr "Julij" + +msgid "August" +msgstr "Awgust" + +msgid "September" +msgstr "September" + +msgid "October" +msgstr "Oktober" + +msgid "November" +msgstr "Nowember" + +msgid "December" +msgstr "December" + +msgid "jan" +msgstr "jan." + +msgid "feb" +msgstr "feb." + +msgid "mar" +msgstr "měr." + +msgid "apr" +msgstr "apr." + +msgid "may" +msgstr "mej." + +msgid "jun" +msgstr "jun." + +msgid "jul" +msgstr "jul." + +msgid "aug" +msgstr "awg." + +msgid "sep" +msgstr "sep." + +msgid "oct" +msgstr "okt." + +msgid "nov" +msgstr "now." + +msgid "dec" +msgstr "dec." + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Měrc" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Apryl" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Meja" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Junij" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Julij" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Awg." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Sept." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Okt." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Now." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dec." + +msgctxt "alt. month" +msgid "January" +msgstr "Januar" + +msgctxt "alt. month" +msgid "February" +msgstr "Februar" + +msgctxt "alt. month" +msgid "March" +msgstr "Měrc" + +msgctxt "alt. month" +msgid "April" +msgstr "Apryl" + +msgctxt "alt. month" +msgid "May" +msgstr "Meja" + +msgctxt "alt. month" +msgid "June" +msgstr "Junij" + +msgctxt "alt. month" +msgid "July" +msgstr "Julij" + +msgctxt "alt. month" +msgid "August" +msgstr "Awgust" + +msgctxt "alt. month" +msgid "September" +msgstr "September" + +msgctxt "alt. month" +msgid "October" +msgstr "Oktober" + +msgctxt "alt. month" +msgid "November" +msgstr "Nowember" + +msgctxt "alt. month" +msgid "December" +msgstr "December" + +msgid "This is not a valid IPv6 address." +msgstr "To płaćiwa IPv6-adresa njeje." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "abo" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d lěto" +msgstr[1] "%(num)dlěće" +msgstr[2] "%(num)d lěta" +msgstr[3] "%(num)d lět" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d měsac" +msgstr[1] "%(num)d měsacaj" +msgstr[2] "%(num)d měsacy" +msgstr[3] "%(num)d měsacow" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d tydźeń" +msgstr[1] "%(num)d njedźeli" +msgstr[2] "%(num)d njedźele" +msgstr[3] "%(num)d njedźel" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dźeń" +msgstr[1] "%(num)d dnjej" +msgstr[2] "%(num)d dny" +msgstr[3] "%(num)d dnjow" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hodźina" +msgstr[1] "%(num)d hodźinje" +msgstr[2] "%(num)d hodźiny" +msgstr[3] "%(num)d hodźin" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d mjeńšina" +msgstr[1] "%(num)d mjeńšinje" +msgstr[2] "%(num)d mjeńšiny" +msgstr[3] "%(num)d mjeńšin" + +msgid "Forbidden" +msgstr "Zakazany" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF-přepruwowanje je so nimokuliło. Naprašowanje je so přetorhnyło." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Widźiće tutu zdźělenku, dokelž tute HTTPS-sydło \"Referer header\" trjeba, " +"kotryž so ma na waš webwobhladowak pósłać, ale žadyn njeje so pósłał. Tutón " +"header je z wěstotnych přičinow trěbny, zo by so zawěsćiło, zo waš " +"wobhladowak so wot třećich njekapruje." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Jei sće swój wobhladowak tak konfigurował, zo su hłowy „Referer“ " +"znjemóžnjene, zmóžńće je, znajmjeńša za tute sydło abo za HTTPS-zwiski abo " +"za naprašowanja „sameorigin“." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Jeli značku wužiwaće abo hłowu „Referrer-Policy: no-referrer“ zapřijimaće, " +"wotstrońće je prošu. CSRF-škit trjeba hłowu „Referer“ , zo by striktnu " +"kontrolu referer přewjedźe. Jeli so wo priwatnosć staraće, wužiwajće " +"alternatiwy kaž za wotkazy k sydłam třećich." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Widźiće tutu zdźělenku, dokelž tute sydło CSRF-plack trjeba, hdyž so " +"formulary wotesyłaja. Tutón plack je z přičinow wěstoty trěbny, zo by so waš " +"wobhladowak wot třećich njekapruje." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Jeli sće swój wobhladowak tak konfigurował, zo su placki znjemóžnjene, " +"zmóžńće je zaso, znajmjeńša za tute sydło abo za naprašowanja „same-origin“." + +msgid "More information is available with DEBUG=True." +msgstr "Z DEBUG=True su dalše informacije k dispoziciji." + +msgid "No year specified" +msgstr "Žane lěto podate" + +msgid "Date out of range" +msgstr "Datum zwonka wobłuka" + +msgid "No month specified" +msgstr "Žadyn měsac podaty" + +msgid "No day specified" +msgstr "Žadyn dźeń podaty" + +msgid "No week specified" +msgstr "Žadyn tydźeń podaty" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Žadyn %(verbose_name_plural)s k dispoziciji njeje" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Přichodowe %(verbose_name_plural)s k dispoziciji njejsu, dokelž hódnota " +"%(class_name)s.allow_future je False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" +"Njepłaćiwy „%(format)s“ za datumowy znamješkowy rjaćazk „%(datestr)s“ podaty" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Žane %(verbose_name)s namakane, kotrež naprašowanju wotpowěduje" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Strona „last“ njeje, ani njeda so do int konwertować." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Njepłaćiwa strona (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Prózdna lisćina a „%(class_name)s.allow_empty“ je False." + +msgid "Directory indexes are not allowed here." +msgstr "Zapisowe indeksy tu dowolone njejsu." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "„%(path)s“ njeeksistuje" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Indeks %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Instalacija bě wuspěšna! Zbožopřeće!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Čitajće wersijowe informacije za Django " +"%(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Widźiće tutu stronu, dokelž DEBUG=True je we wašej dataji nastajenjow a njejsće URL " +"skonfigurował." + +msgid "Django Documentation" +msgstr "Dokumentacija Django" + +msgid "Topics, references, & how-to’s" +msgstr "Temy, referency a nawody" + +msgid "Tutorial: A Polling App" +msgstr "Nawod: Naprašowanske nałoženje" + +msgid "Get started with Django" +msgstr "Prěnje kroki z Django" + +msgid "Django Community" +msgstr "Zhromadźenstwo Django" + +msgid "Connect, get help, or contribute" +msgstr "Zwjazać, pomoc wobstarać abo přinošować" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hu/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hu/LC_MESSAGES/django.mo new file mode 100644 index 0000000..621965a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hu/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hu/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hu/LC_MESSAGES/django.po new file mode 100644 index 0000000..54dd7ef --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hu/LC_MESSAGES/django.po @@ -0,0 +1,1357 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Akos Zsolt Hochrein , 2018 +# András Veres-Szentkirályi, 2016-2021,2023 +# Attila Nagy <>, 2012 +# Balázs R, 2023 +# Dóra Szendrei , 2017 +# Istvan Farkas , 2019 +# Jannis Leidel , 2011 +# János R, 2011-2012,2014 +# János R, 2022 +# Máté Őry , 2013 +# Szilveszter Farkas , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: András Veres-Szentkirályi, 2016-2021,2023\n" +"Language-Team: Hungarian (http://app.transifex.com/django/django/language/" +"hu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Afrikaans" + +msgid "Arabic" +msgstr "Arab" + +msgid "Algerian Arabic" +msgstr "algériai arab" + +msgid "Asturian" +msgstr "Asztúriai" + +msgid "Azerbaijani" +msgstr "azerbajdzsáni" + +msgid "Bulgarian" +msgstr "Bolgár" + +msgid "Belarusian" +msgstr "Belarusz" + +msgid "Bengali" +msgstr "Bengáli" + +msgid "Breton" +msgstr "Breton" + +msgid "Bosnian" +msgstr "Bosnyák" + +msgid "Catalan" +msgstr "Katalán" + +msgid "Central Kurdish (Sorani)" +msgstr "Közép-kurd (szoráni)" + +msgid "Czech" +msgstr "Cseh" + +msgid "Welsh" +msgstr "Walesi" + +msgid "Danish" +msgstr "Dán" + +msgid "German" +msgstr "Német" + +msgid "Lower Sorbian" +msgstr "Alsószorb" + +msgid "Greek" +msgstr "Görög" + +msgid "English" +msgstr "Angol" + +msgid "Australian English" +msgstr "Ausztráliai angol" + +msgid "British English" +msgstr "Brit angol" + +msgid "Esperanto" +msgstr "Eszperantó" + +msgid "Spanish" +msgstr "Spanyol" + +msgid "Argentinian Spanish" +msgstr "Argentin spanyol" + +msgid "Colombian Spanish" +msgstr "Kolumbiai spanyol" + +msgid "Mexican Spanish" +msgstr "Mexikói spanyol" + +msgid "Nicaraguan Spanish" +msgstr "Nicaraguai spanyol" + +msgid "Venezuelan Spanish" +msgstr "Venezuelai spanyol" + +msgid "Estonian" +msgstr "Észt" + +msgid "Basque" +msgstr "Baszk " + +msgid "Persian" +msgstr "Perzsa" + +msgid "Finnish" +msgstr "Finn" + +msgid "French" +msgstr "Francia" + +msgid "Frisian" +msgstr "Fríz" + +msgid "Irish" +msgstr "Ír" + +msgid "Scottish Gaelic" +msgstr "Skót gael" + +msgid "Galician" +msgstr "Gall" + +msgid "Hebrew" +msgstr "Héber" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Horvát" + +msgid "Upper Sorbian" +msgstr "Felsőszorb" + +msgid "Hungarian" +msgstr "Magyar" + +msgid "Armenian" +msgstr "Örmény" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonéz" + +msgid "Igbo" +msgstr "igbo" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Izlandi" + +msgid "Italian" +msgstr "Olasz" + +msgid "Japanese" +msgstr "Japán" + +msgid "Georgian" +msgstr "Grúz" + +msgid "Kabyle" +msgstr "Kabil" + +msgid "Kazakh" +msgstr "Kazak" + +msgid "Khmer" +msgstr "Khmer" + +msgid "Kannada" +msgstr "Kannada" + +msgid "Korean" +msgstr "Koreai" + +msgid "Kyrgyz" +msgstr "kirgiz" + +msgid "Luxembourgish" +msgstr "Luxemburgi" + +msgid "Lithuanian" +msgstr "Litván" + +msgid "Latvian" +msgstr "Lett" + +msgid "Macedonian" +msgstr "Macedón" + +msgid "Malayalam" +msgstr "Malajálam" + +msgid "Mongolian" +msgstr "Mongol" + +msgid "Marathi" +msgstr "Maráthi" + +msgid "Malay" +msgstr "Maláj" + +msgid "Burmese" +msgstr "Burmai" + +msgid "Norwegian Bokmål" +msgstr "Bokmål norvég" + +msgid "Nepali" +msgstr "Nepáli" + +msgid "Dutch" +msgstr "Holland" + +msgid "Norwegian Nynorsk" +msgstr "Nynorsk norvég" + +msgid "Ossetic" +msgstr "Oszét" + +msgid "Punjabi" +msgstr "Punjabi" + +msgid "Polish" +msgstr "Lengyel" + +msgid "Portuguese" +msgstr "Portugál" + +msgid "Brazilian Portuguese" +msgstr "Brazíliai portugál" + +msgid "Romanian" +msgstr "Román" + +msgid "Russian" +msgstr "Orosz" + +msgid "Slovak" +msgstr "Szlovák" + +msgid "Slovenian" +msgstr "Szlovén" + +msgid "Albanian" +msgstr "Albán" + +msgid "Serbian" +msgstr "Szerb" + +msgid "Serbian Latin" +msgstr "Latin betűs szerb" + +msgid "Swedish" +msgstr "Svéd" + +msgid "Swahili" +msgstr "Szuahéli" + +msgid "Tamil" +msgstr "Tamil" + +msgid "Telugu" +msgstr "Telugu" + +msgid "Tajik" +msgstr "tadzsik" + +msgid "Thai" +msgstr "Thai" + +msgid "Turkmen" +msgstr "türkmén" + +msgid "Turkish" +msgstr "Török" + +msgid "Tatar" +msgstr "Tatár" + +msgid "Udmurt" +msgstr "Udmurt" + +msgid "Uyghur" +msgstr "ujgur" + +msgid "Ukrainian" +msgstr "Ukrán" + +msgid "Urdu" +msgstr "urdu" + +msgid "Uzbek" +msgstr "Üzbég" + +msgid "Vietnamese" +msgstr "Vietnámi" + +msgid "Simplified Chinese" +msgstr "Egyszerű kínai" + +msgid "Traditional Chinese" +msgstr "Hagyományos kínai" + +msgid "Messages" +msgstr "Üzenetek" + +msgid "Site Maps" +msgstr "Oldaltérképek" + +msgid "Static Files" +msgstr "Statikus fájlok" + +msgid "Syndication" +msgstr "Szindikáció" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "..." + +msgid "That page number is not an integer" +msgstr "Az oldalszám nem egész szám." + +msgid "That page number is less than 1" +msgstr "Az oldalszám kisebb, mint 1" + +msgid "That page contains no results" +msgstr "Az oldal nem tartalmaz találatokat" + +msgid "Enter a valid value." +msgstr "Adjon meg egy érvényes értéket." + +msgid "Enter a valid URL." +msgstr "Adjon meg egy érvényes URL-t." + +msgid "Enter a valid integer." +msgstr "Adjon meg egy érvényes számot." + +msgid "Enter a valid email address." +msgstr "Írjon be egy érvényes e-mail címet." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Kérjük adjon meg egy érvényes \"domain-darabkát\", amely csak ékezet nélküli " +"betűkből, számokból, aláhúzásból és kötőjelből áll." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Kérjük adjon meg egy érvényes \"domain-darabkát\", amely csak betűkből, " +"számokból, aláhúzásból és kötőjelből áll." + +msgid "Enter a valid IPv4 address." +msgstr "Írjon be egy érvényes IPv4 címet." + +msgid "Enter a valid IPv6 address." +msgstr "Írjon be egy érvényes IPv6 címet." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Írjon be egy érvényes IPv4 vagy IPv6 címet." + +msgid "Enter only digits separated by commas." +msgstr "Csak számokat adjon meg, vesszővel elválasztva." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Bizonyosodjon meg arról, hogy az érték %(limit_value)s (jelenleg: " +"%(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Bizonyosodjon meg arról, hogy az érték %(limit_value)s, vagy kisebb." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Bizonyosodjon meg arról, hogy az érték %(limit_value)s, vagy nagyobb." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "Bizonyosodjon meg arról, hogy az érték %(limit_value)s többszöröse." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"Az érték %(limit_value)s többszörösével kell hogy eltérjen %(offset)s-hoz " +"képest, pl. %(offset)s, %(valid_value1)s, %(valid_value2)s, és így tovább. " + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Bizonyosodjon meg arról, hogy ez az érték legalább %(limit_value)d karaktert " +"tartalmaz (jelenlegi hossza: %(show_value)d)." +msgstr[1] "" +"Bizonyosodjon meg arról, hogy ez az érték legalább %(limit_value)d karaktert " +"tartalmaz (jelenlegi hossza: %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Bizonyosodjon meg arról, hogy ez az érték legfeljebb %(limit_value)d " +"karaktert tartalmaz (jelenlegi hossza: %(show_value)d)." +msgstr[1] "" +"Bizonyosodjon meg arról, hogy ez az érték legfeljebb %(limit_value)d " +"karaktert tartalmaz (jelenlegi hossza: %(show_value)d)." + +msgid "Enter a number." +msgstr "Adj meg egy számot." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Bizonyosodjon meg arról, hogy legfeljebb %(max)s számjegyből áll." +msgstr[1] "Bizonyosodjon meg arról, hogy legfeljebb %(max)s számjegyből áll." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +"Bizonyosodjon meg arról, hogy legfeljebb %(max)s tizedesjegyből áll." +msgstr[1] "" +"Bizonyosodjon meg arról, hogy legfeljebb %(max)s tizedesjegyből áll." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Bizonyosodjon meg arról, hogy legfeljebb %(max)s számjegy van a " +"tizedesvessző előtt." +msgstr[1] "" +"Bizonyosodjon meg arról, hogy legfeljebb %(max)s számjegy van a " +"tizedesvessző előtt." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"A(z) \"%(extension)s\" kiterjesztés nincs engedélyezve. Az engedélyezett " +"fájltípusok: %(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Null karakterek használata nem megengedett." + +msgid "and" +msgstr "és" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "Már létezik %(model_name)s ilyennel: %(field_labels)s." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "\"%(name)s\" kényszer megsértve." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "%(value)r érték érvénytelen." + +msgid "This field cannot be null." +msgstr "Ez a mező nem lehet nulla." + +msgid "This field cannot be blank." +msgstr "Ez a mező nem lehet üres." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "Már létezik %(model_name)s ilyennel: %(field_label)s." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s egyedi kell hogy legyen %(lookup_type)s alapján a(z) " +"%(date_field_label)s mezőn." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Mezőtípus: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "A(z) \"%(value)s\" értéke csak True vagy False lehet." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "A(z) \"%(value)s\" értéke csak True, False vagy üres lehet." + +msgid "Boolean (Either True or False)" +msgstr "Logikai (True vagy False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Karakterlánc (%(max_length)s hosszig)" + +msgid "String (unlimited)" +msgstr "Karakterlánc (korlátlan hosszúságú)" + +msgid "Comma-separated integers" +msgstr "Vesszővel elválasztott egészek" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"A(z) \"%(value)s\" érvénytelen dátumformátumot tartalmaz. A dátumnak ÉÉÉÉ-HH-" +"NN formában kell lennie." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"A(z) \"%(value)s\" értéke formára (ÉÉÉÉ-HH-NN) megfelel ugyan, de " +"érvénytelen dátumot tartalmaz." + +msgid "Date (without time)" +msgstr "Dátum (idő nélkül)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"A(z) \"%(value)s\" érvénytelen dátumformátumot tartalmaz. A dátumnak ÉÉÉÉ-HH-" +"NN ÓÓ:PP[:mm[.uuuuuu]][TZ] formában kell lennie." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"A(z) \"%(value)s\" értéke formára (ÉÉÉÉ-HH-NN ÓÓ:PP[:mm[:uuuuuu]][TZ]) " +"megfelel ugyan, de érvénytelen dátumot vagy időt tartalmaz." + +msgid "Date (with time)" +msgstr "Dátum (idővel)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "A(z) \"%(value)s\" értékének tizes számrendszerű számnak kell lennie." + +msgid "Decimal number" +msgstr "Tizes számrendszerű (decimális) szám" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"A(z) \"%(value)s\" érvénytelen idő formátumot tartalmaz. Az időnek ÓÓ:PP[:" +"mm[.uuuuuu]] formában kell lennie." + +msgid "Duration" +msgstr "Időtartam" + +msgid "Email address" +msgstr "E-mail cím" + +msgid "File path" +msgstr "Elérési út" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "A(z) \"%(value)s\" értékének lebegőpontos számnak kell lennie." + +msgid "Floating point number" +msgstr "Lebegőpontos szám" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "A(z) \"%(value)s\" értékének egész számnak kell lennie." + +msgid "Integer" +msgstr "Egész" + +msgid "Big (8 byte) integer" +msgstr "Nagy egész szám (8 bájtos)" + +msgid "Small integer" +msgstr "Kis egész" + +msgid "IPv4 address" +msgstr "IPv4 cím" + +msgid "IP address" +msgstr "IP cím" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "Az \"%(value)s\" értéke csak üres, True, vagy False lehet." + +msgid "Boolean (Either True, False or None)" +msgstr "Logikai (True, False vagy None)" + +msgid "Positive big integer" +msgstr "Pozitív nagy egész" + +msgid "Positive integer" +msgstr "Pozitív egész" + +msgid "Positive small integer" +msgstr "Pozitív kis egész" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "URL-barát cím (%(max_length)s hosszig)" + +msgid "Text" +msgstr "Szöveg" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"A(z) \"%(value)s\" érvénytelen idő formátumot tartalmaz. Az időnek ÓÓ:PP[:" +"mm[.uuuuuu]] formában kell lennie." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"A(z) \"%(value)s\" értéke formára (ÓÓ:PP[:mm[:uuuuuu]][TZ]) megfelel ugyan, " +"de érvénytelen időt tartalmaz." + +msgid "Time" +msgstr "Idő" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Nyers bináris adat" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "A(z) \"%(value)s\" értéke nem érvényes UUID érték." + +msgid "Universally unique identifier" +msgstr "Univerzálisan egyedi azonosító" + +msgid "File" +msgstr "Fájl" + +msgid "Image" +msgstr "Kép" + +msgid "A JSON object" +msgstr "Egy JSON objektum" + +msgid "Value must be valid JSON." +msgstr "Az érték érvényes JSON kell legyen." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(model)s példány %(value)r %(field)s értékkel nem létezik." + +msgid "Foreign Key (type determined by related field)" +msgstr "Idegen kulcs (típusa a kapcsolódó mezőtől függ)" + +msgid "One-to-one relationship" +msgstr "Egy-egy kapcsolat" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s kapcsolat" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s kapcsolatok" + +msgid "Many-to-many relationship" +msgstr "Több-több kapcsolat" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Ennek a mezőnek a megadása kötelező." + +msgid "Enter a whole number." +msgstr "Adjon meg egy egész számot." + +msgid "Enter a valid date." +msgstr "Adjon meg egy érvényes dátumot." + +msgid "Enter a valid time." +msgstr "Adjon meg egy érvényes időt." + +msgid "Enter a valid date/time." +msgstr "Adjon meg egy érvényes dátumot/időt." + +msgid "Enter a valid duration." +msgstr "Adjon meg egy érvényes időtartamot." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "A napok számának {min_days} és {max_days} közé kell esnie." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Nem küldött el fájlt. Ellenőrizze a kódolás típusát az űrlapon." + +msgid "No file was submitted." +msgstr "Semmilyen fájl sem került feltöltésre." + +msgid "The submitted file is empty." +msgstr "A küldött fájl üres." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Bizonyosodjon meg arról, hogy a fájlnév legfeljebb %(max)d karakterből áll " +"(jelenlegi hossza: %(length)d)." +msgstr[1] "" +"Bizonyosodjon meg arról, hogy a fájlnév legfeljebb %(max)d karakterből áll " +"(jelenlegi hossza: %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Küldjön egy új fájlt, vagy jelölje be a törlés négyzetet, de ne mindkettőt " +"egyszerre." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Töltsön fel egy érvényes képfájlt. A feltöltött fájl nem kép volt, vagy " +"megsérült." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Válasszon érvényes elemet. '%(value)s' nincs az elérhető lehetőségek között." + +msgid "Enter a list of values." +msgstr "Adja meg értékek egy listáját." + +msgid "Enter a complete value." +msgstr "Adjon meg egy teljes értéket." + +msgid "Enter a valid UUID." +msgstr "Adjon meg egy érvényes UUID-t." + +msgid "Enter a valid JSON." +msgstr "Adjon meg egy érvényes JSON-t." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Rejtett mező: %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"ManagementForm adatok hiányoznak vagy hamisításra kerültek. A hiányzó mezők: " +"%(field_names)s. Ha ez többször is előfordul, érdemes bejelenteni hibaként." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Legfeljebb %(num)d űrlapot küldjön be." +msgstr[1] "Legfeljebb %(num)d űrlapot küldjön be." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Legalább %(num)d űrlapot küldjön be." +msgstr[1] "Legalább %(num)d űrlapot küldjön be." + +msgid "Order" +msgstr "Sorrend" + +msgid "Delete" +msgstr "Törlés" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Javítsa a mezőhöz tartozó duplikált adatokat: %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Javítsa a mezőhöz tartozó duplikált adatokat: %(field)s (egyedinek kell " +"lenniük)." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Javítsa a mezőhöz tartozó duplikált adatokat: %(field_name)s (egyedinek kell " +"lenniük %(lookup)s alapján a dátum mezőn: %(date_field)s)." + +msgid "Please correct the duplicate values below." +msgstr "Javítsa az alábbi duplikált értékeket." + +msgid "The inline value did not match the parent instance." +msgstr "A beágyazott érték nem egyezik meg a szülő példányéval." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Válasszon érvényes elemet. Az Ön választása nincs az elérhető lehetőségek " +"között." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "Érvénytelen érték: \"%(pk)s\"" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"A(z) %(datetime)s nem értelmezhető a(z) %(current_timezone)s időzónában; " +"vagy bizonytalan, vagy nem létezik." + +msgid "Clear" +msgstr "Törlés" + +msgid "Currently" +msgstr "Jelenleg" + +msgid "Change" +msgstr "Módosítás" + +msgid "Unknown" +msgstr "Ismeretlen" + +msgid "Yes" +msgstr "Igen" + +msgid "No" +msgstr "Nem" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "igen,nem,talán" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d bájt" +msgstr[1] "%(size)d bájt" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "du" + +msgid "a.m." +msgstr "de" + +msgid "PM" +msgstr "DU" + +msgid "AM" +msgstr "DE" + +msgid "midnight" +msgstr "éjfél" + +msgid "noon" +msgstr "dél" + +msgid "Monday" +msgstr "hétfő" + +msgid "Tuesday" +msgstr "kedd" + +msgid "Wednesday" +msgstr "szerda" + +msgid "Thursday" +msgstr "csütörtök" + +msgid "Friday" +msgstr "péntek" + +msgid "Saturday" +msgstr "szombat" + +msgid "Sunday" +msgstr "vasárnap" + +msgid "Mon" +msgstr "hét" + +msgid "Tue" +msgstr "kedd" + +msgid "Wed" +msgstr "sze" + +msgid "Thu" +msgstr "csüt" + +msgid "Fri" +msgstr "pén" + +msgid "Sat" +msgstr "szo" + +msgid "Sun" +msgstr "vas" + +msgid "January" +msgstr "január" + +msgid "February" +msgstr "február" + +msgid "March" +msgstr "március" + +msgid "April" +msgstr "április" + +msgid "May" +msgstr "május" + +msgid "June" +msgstr "június" + +msgid "July" +msgstr "július" + +msgid "August" +msgstr "augusztus" + +msgid "September" +msgstr "szeptember" + +msgid "October" +msgstr "október" + +msgid "November" +msgstr "november" + +msgid "December" +msgstr "december" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "már" + +msgid "apr" +msgstr "ápr" + +msgid "may" +msgstr "máj" + +msgid "jun" +msgstr "jún" + +msgid "jul" +msgstr "júl" + +msgid "aug" +msgstr "aug" + +msgid "sep" +msgstr "sze" + +msgid "oct" +msgstr "okt" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dec" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "febr." + +msgctxt "abbrev. month" +msgid "March" +msgstr "márc." + +msgctxt "abbrev. month" +msgid "April" +msgstr "ápr." + +msgctxt "abbrev. month" +msgid "May" +msgstr "máj." + +msgctxt "abbrev. month" +msgid "June" +msgstr "jún." + +msgctxt "abbrev. month" +msgid "July" +msgstr "júl." + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "aug." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "szept." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "okt." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "dec." + +msgctxt "alt. month" +msgid "January" +msgstr "január" + +msgctxt "alt. month" +msgid "February" +msgstr "február" + +msgctxt "alt. month" +msgid "March" +msgstr "március" + +msgctxt "alt. month" +msgid "April" +msgstr "április" + +msgctxt "alt. month" +msgid "May" +msgstr "május" + +msgctxt "alt. month" +msgid "June" +msgstr "június" + +msgctxt "alt. month" +msgid "July" +msgstr "július" + +msgctxt "alt. month" +msgid "August" +msgstr "augusztus" + +msgctxt "alt. month" +msgid "September" +msgstr "szeptember" + +msgctxt "alt. month" +msgid "October" +msgstr "október" + +msgctxt "alt. month" +msgid "November" +msgstr "november" + +msgctxt "alt. month" +msgid "December" +msgstr "december" + +msgid "This is not a valid IPv6 address." +msgstr "Ez nem egy érvényes IPv6 cím." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "vagy" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d év" +msgstr[1] "%(num)d év" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d hónap" +msgstr[1] "%(num)d hónap" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d hét" +msgstr[1] "%(num)d hét" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d nap" +msgstr[1] "%(num)d nap" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d óra" +msgstr[1] "%(num)d óra" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d perc" +msgstr[1] "%(num)d perc" + +msgid "Forbidden" +msgstr "Hozzáférés megtagadva" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF ellenőrzés sikertelen. Kérés kiszolgálása megszakítva." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Ezt az üzenetet azért látja, mert ezen a HTTPS oldalon kötelező a \"Referer " +"header\", amelyet a böngészőnek kellene küldenie, de nem tette. Ez az adat " +"biztonsági okokból kötelező, ez biztosítja, hogy a böngészőt nem irányítja " +"át egy harmadik fél." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Ha a böngészője úgy van beállítva, hogy letilja a \"Referer\" adatokat, " +"kérjük engedélyezze őket ehhez az oldalhoz, vagy a HTTPS kapcsolatokhoz, " +"vagy a \"same-origin\" kérésekhez." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Ha a címkét használja, vagy " +"a “Referrer-Policy: no-referrer” fejlécet, kérjük távolítsa el ezeket. A " +"CSRF védelemnek szüksége van a \"Referer\" fejléc adatra a szigorú " +"ellenőrzéshez. Ha aggódik az adatainak biztonsága miatt, használjon " +"alternatívákat, mint például az , a külső oldalakra " +"mutató linkek esetén. " + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Azért látja ezt az üzenetet, mert ez a weboldal elvárja a CSRF cookie " +"elküldését űrlapoknál. Erre a cookie-ra biztonsági okból van szükség annak " +"kiszűrésére, hogy harmadik fél eltérítse az ön böngészőjét." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Ha kikapcsolta a cookie-kat a böngészőjében, kérjük engedélyezze őket újra, " +"legalább erre az oldalra, vagy a \"same-origin\" típusú kérésekre." + +msgid "More information is available with DEBUG=True." +msgstr "További információ DEBUG=True beállítással érhető el." + +msgid "No year specified" +msgstr "Nincs év megadva" + +msgid "Date out of range" +msgstr "A dátum a megengedett tartományon kívül esik." + +msgid "No month specified" +msgstr "Nincs hónap megadva" + +msgid "No day specified" +msgstr "Nincs nap megadva" + +msgid "No week specified" +msgstr "Nincs hét megadva" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Nincsenek elérhető %(verbose_name_plural)s" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Jövőbeli %(verbose_name_plural)s nem elérhetők, mert %(class_name)s." +"allow_future értéke False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" +"A megadott dátum \"%(datestr)s\" érvénytelen a következő formátumban: " +"\"%(format)s\"." + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Nincs a keresési feltételeknek megfelelő %(verbose_name)s" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Az oldalszám nem \"utolsó\", vagy nem lehet számmá alakítani." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Érvénytelen oldal (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Üres lista, de a \"%(class_name)s.allow_empty\" értéke hamis." + +msgid "Directory indexes are not allowed here." +msgstr "A könyvtárak listázása itt nincs engedélyezve." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "A(z) \"%(path)s\" útvonal nem létezik" + +#, python-format +msgid "Index of %(directory)s" +msgstr "A %(directory)s könyvtár tartalma" + +msgid "The install worked successfully! Congratulations!" +msgstr "A telepítés sikeresen végződött! Gratulálunk!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"A Django %(version)s kiadási megjegyzéseinek " +"megtekintése" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Azért látod ezt az oldalt, mert a DEBUG=True szerepel a settings fájlban, és még nem " +"került beállításra egy URL sem." + +msgid "Django Documentation" +msgstr "Django Dokumentáció" + +msgid "Topics, references, & how-to’s" +msgstr "Témák, hivatkozások, & leírások" + +msgid "Tutorial: A Polling App" +msgstr "Gyakorlat: egy szavazó app" + +msgid "Get started with Django" +msgstr "Első lépések a Djangóval" + +msgid "Django Community" +msgstr "Django Közösség" + +msgid "Connect, get help, or contribute" +msgstr "Lépj kapcsolatba, kérj segítséget, vagy járulj hozzá" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hu/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hu/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hu/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hu/formats.py new file mode 100644 index 0000000..c17f2c7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hu/formats.py @@ -0,0 +1,30 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "Y. F j." +TIME_FORMAT = "H:i" +DATETIME_FORMAT = "Y. F j. H:i" +YEAR_MONTH_FORMAT = "Y. F" +MONTH_DAY_FORMAT = "F j." +SHORT_DATE_FORMAT = "Y.m.d." +SHORT_DATETIME_FORMAT = "Y.m.d. H:i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%Y.%m.%d.", # '2006.10.25.' +] +TIME_INPUT_FORMATS = [ + "%H:%M:%S", # '14:30:59' + "%H:%M", # '14:30' +] +DATETIME_INPUT_FORMATS = [ + "%Y.%m.%d. %H:%M:%S", # '2006.10.25. 14:30:59' + "%Y.%m.%d. %H:%M:%S.%f", # '2006.10.25. 14:30:59.000200' + "%Y.%m.%d. %H:%M", # '2006.10.25. 14:30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = " " # Non-breaking space +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9dcc472 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hy/LC_MESSAGES/django.po new file mode 100644 index 0000000..e4860e2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/hy/LC_MESSAGES/django.po @@ -0,0 +1,1237 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Սմբատ Պետրոսյան , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Armenian (http://www.transifex.com/django/django/language/" +"hy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hy\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Աֆրիկաանս" + +msgid "Arabic" +msgstr "Արաբերեն" + +msgid "Asturian" +msgstr "Աստուրերեն" + +msgid "Azerbaijani" +msgstr "Ադրբեջաներեն" + +msgid "Bulgarian" +msgstr "Բուլղարերեն" + +msgid "Belarusian" +msgstr "Բելոռուսերեն" + +msgid "Bengali" +msgstr "Բենգալերեն" + +msgid "Breton" +msgstr "Բրետոներեն" + +msgid "Bosnian" +msgstr "Բոսնիերեն" + +msgid "Catalan" +msgstr "Կատալաներեն" + +msgid "Czech" +msgstr "Չեխերեն" + +msgid "Welsh" +msgstr "Վալլիերեն" + +msgid "Danish" +msgstr "Դանիերեն" + +msgid "German" +msgstr "Գերմաներեն" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "Հունարեն" + +msgid "English" +msgstr "Անգլերեն" + +msgid "Australian English" +msgstr "Ավստրալական Անգլերեն" + +msgid "British English" +msgstr "Բրիտանական Անգլերեն" + +msgid "Esperanto" +msgstr "Էսպերանտո" + +msgid "Spanish" +msgstr "Իսպաներեն" + +msgid "Argentinian Spanish" +msgstr "Արգենտինական իսպաներեն" + +msgid "Colombian Spanish" +msgstr "Կոլումբիական իսպաներեն" + +msgid "Mexican Spanish" +msgstr "Մեքսիկական իսպաներեն" + +msgid "Nicaraguan Spanish" +msgstr "Նիկարագուական իսպաներեն" + +msgid "Venezuelan Spanish" +msgstr "Վենեսուելլական իսպաներեն" + +msgid "Estonian" +msgstr "Էստոներեն" + +msgid "Basque" +msgstr "Բասկերեն" + +msgid "Persian" +msgstr "Պարսկերեն" + +msgid "Finnish" +msgstr "Ֆիներեն" + +msgid "French" +msgstr "Ֆրանսերեն" + +msgid "Frisian" +msgstr "Ֆրիզերեն" + +msgid "Irish" +msgstr "Իռլանդերեն" + +msgid "Scottish Gaelic" +msgstr "Գելական շոտլանդերեն" + +msgid "Galician" +msgstr "Գալիսերեն" + +msgid "Hebrew" +msgstr "Եբրայերեն" + +msgid "Hindi" +msgstr "Հինդի" + +msgid "Croatian" +msgstr "Խորվաթերեն" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "Հունգարերեն" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "Ինտերլինգուա" + +msgid "Indonesian" +msgstr "Ինդոնեզերեն" + +msgid "Ido" +msgstr "Իդո" + +msgid "Icelandic" +msgstr "Իսլանդերեն" + +msgid "Italian" +msgstr "Իտալերեն" + +msgid "Japanese" +msgstr "Ճապոներեն" + +msgid "Georgian" +msgstr "Վրացերեն" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "Ղազախերեն" + +msgid "Khmer" +msgstr "Քեմերերեն" + +msgid "Kannada" +msgstr "Կանադա" + +msgid "Korean" +msgstr "Կորեերեն" + +msgid "Luxembourgish" +msgstr "Լյուքսեմբուրգերեն" + +msgid "Lithuanian" +msgstr "Լիտվերեն" + +msgid "Latvian" +msgstr "Լատիշերեն" + +msgid "Macedonian" +msgstr "Մակեդոներեն" + +msgid "Malayalam" +msgstr "Մալայալամ" + +msgid "Mongolian" +msgstr "Մոնղոլերեն" + +msgid "Marathi" +msgstr "Մարատխի" + +msgid "Burmese" +msgstr "Բիրմաներեն" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "Նեպալերեն" + +msgid "Dutch" +msgstr "Հոլանդերեն" + +msgid "Norwegian Nynorsk" +msgstr "Նորվեգերեն (Նյունորսկ)" + +msgid "Ossetic" +msgstr "Օսերեն" + +msgid "Punjabi" +msgstr "Փանջաբի" + +msgid "Polish" +msgstr "Լեհերեն" + +msgid "Portuguese" +msgstr "Պորտուգալերեն" + +msgid "Brazilian Portuguese" +msgstr "Բրազիլական պորտուգալերեն" + +msgid "Romanian" +msgstr "Ռումիներեն" + +msgid "Russian" +msgstr "Ռուսերեն" + +msgid "Slovak" +msgstr "Սլովակերեն" + +msgid "Slovenian" +msgstr "Սլովեներեն" + +msgid "Albanian" +msgstr "Ալբաներեն" + +msgid "Serbian" +msgstr "Սերբերեն" + +msgid "Serbian Latin" +msgstr "Սերբերեն (լատինատառ)" + +msgid "Swedish" +msgstr "Շվեդերեն" + +msgid "Swahili" +msgstr "Սվահիլի" + +msgid "Tamil" +msgstr "Թամիլերեն" + +msgid "Telugu" +msgstr "Թելուգու" + +msgid "Thai" +msgstr "Թայերեն" + +msgid "Turkish" +msgstr "Թուրքերեն" + +msgid "Tatar" +msgstr "Թաթարերեն" + +msgid "Udmurt" +msgstr "Ումուրտերեն" + +msgid "Ukrainian" +msgstr "Ուկրաիներեն" + +msgid "Urdu" +msgstr "Ուրդու" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "Վիետնամերեն" + +msgid "Simplified Chinese" +msgstr "Հեշտացված չինարեն" + +msgid "Traditional Chinese" +msgstr "Ավանդական չինարեն" + +msgid "Messages" +msgstr "Հաղորդագրություններ" + +msgid "Site Maps" +msgstr "Կայքի քարտեզ" + +msgid "Static Files" +msgstr "Ստատիկ ֆայլեր\t" + +msgid "Syndication" +msgstr "Նորություններ" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "Մուտքագրեք ճիշտ արժեք" + +msgid "Enter a valid URL." +msgstr "Մուտքագրեք ճիշտ URL" + +msgid "Enter a valid integer." +msgstr "Մուտքագրեք ամբողջ թիվ" + +msgid "Enter a valid email address." +msgstr "Մուտքագրեք ճիշտ էլեկտրոնային փոստի հասցե" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Մուտքագրեք ճիշտ IPv4 հասցե" + +msgid "Enter a valid IPv6 address." +msgstr "Մուտքագրեք ճիշտ IPv6 հասցե" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Մուտքագրեք ճիշտ IPv4 կամ IPv6 հասցե" + +msgid "Enter only digits separated by commas." +msgstr "Մուտքագրեք միայն ստորակետով բաժանված թվեր" + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Համոզվեք, որ այս արժեքը %(limit_value)s (հիմա այն — %(show_value)s)" + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Համոզվեք, որ այս արժեքը փոքր է, կամ հավասար %(limit_value)s" + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Համոզվեք, որ այս արժեքը մեծ է, համ հավասար %(limit_value)s" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Համոզվեք, որ արժեքը պարունակում է ամենաքիչը %(limit_value)d նիշ (այն " +"պարունակում է %(show_value)d)." +msgstr[1] "" +"Համոզվեք, որ արժեքը պարունակում է ամենաքիչը %(limit_value)d նիշ (այն " +"պարունակում է %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Համոզվեք, որ արժեքը պարունակում է ամենաքիչը %(limit_value)d նիշ (այն " +"պարունակում է %(show_value)d)." +msgstr[1] "" +"Համոզվեք, որ արժեքը պարունակում է ամենաքիչը %(limit_value)d նիշ (այն " +"պարունակում է %(show_value)d)." + +msgid "Enter a number." +msgstr "Մուտքագրեք թիվ" + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Համոզվեք, որ թվերի քանակը մեծ չէ %(max)s -ից" +msgstr[1] "Համոզվեք, որ թվերի քանակը մեծ չէ %(max)s -ից" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Համոզվեք, որ ստորակետից հետո թվերի քանակը մեծ չէ %(max)s -ից" +msgstr[1] "Համոզվեք, որ ստորակետից հետո թվերի քանակը մեծ չէ %(max)s -ից" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "Համոզվեք, որ ստորակետից առաջ թվերի քանակը մեծ չէ %(max)s -ից" +msgstr[1] "Համոզվեք, որ ստորակետից առաջ թվերի քանակը մեծ չէ %(max)s -ից" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "և" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" +"%(field_labels)s դաշտերի այս արժեքով %(model_name)s արդեն գոյություն ունի" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "%(value)r արժեքը չի մտնում թույլատրված տարբերակների մեջ" + +msgid "This field cannot be null." +msgstr "Այս դաշտը չի կարող ունենալ NULL արժեք " + +msgid "This field cannot be blank." +msgstr "Այս դաշտը չի կարող լինել դատարկ" + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(field_label)s դաշտի այս արժեքով %(model_name)s արդեն գոյություն ունի" + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"«%(field_label)s» դաշտի արժեքը պետք է լինի միակը %(date_field_label)s " +"%(lookup_type)s համար" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "%(field_type)s տիպի դաշտ" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "Տրամաբանական (True կամ False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Տող (մինչև %(max_length)s երկարությամբ)" + +msgid "Comma-separated integers" +msgstr "Ստորակետով բաժանված ամբողջ թվեր" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "Ամսաթիվ (առանց ժամանակի)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Ամսաթիվ (և ժամանակ)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Տասնորդական թիվ" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "Տևողություն" + +msgid "Email address" +msgstr "Email հասցե" + +msgid "File path" +msgstr "Ֆայլի ճանապարհ" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "Floating point թիվ" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "Ամբողջ" + +msgid "Big (8 byte) integer" +msgstr "Մեծ (8 բայթ) ամբողջ թիվ" + +msgid "IPv4 address" +msgstr "IPv4 հասցե" + +msgid "IP address" +msgstr "IP հասցե" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "Տրամաբանական (Either True, False կամ None)" + +msgid "Positive integer" +msgstr "Դրական ամբողջ թիվ" + +msgid "Positive small integer" +msgstr "Դրայան փոքր ամբողջ թիվ" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (մինչև %(max_length)s նիշ)" + +msgid "Small integer" +msgstr "Փոքր ամբողջ թիվ" + +msgid "Text" +msgstr "Տեքստ" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Ժամանակ" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Երկուական տվյալներ" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "Ֆայլ" + +msgid "Image" +msgstr "Պատկեր" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" +" %(field)s դաշտի %(value)r արժեք ունեցող %(model)s օրինակ գոյություն չունի" + +msgid "Foreign Key (type determined by related field)" +msgstr "Արտաքին բանալի (տեսակը որոշվում է հարակից դաշտից)" + +msgid "One-to-one relationship" +msgstr "Մեկը մեկին կապ" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "Մի քանիսը մի քանիսին կապ" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Այս դաշտը պարտադիր է" + +msgid "Enter a whole number." +msgstr "Մուտքագրեք ամբողջ թիվ" + +msgid "Enter a valid date." +msgstr "Մուտքագրեք ճիշտ ամսաթիվ" + +msgid "Enter a valid time." +msgstr "Մուտքագրեք ճիշտ ժամանակ" + +msgid "Enter a valid date/time." +msgstr "Մուտքագրեք ճիշտ ամսաթիվ/ժամանակ" + +msgid "Enter a valid duration." +msgstr "Մուտքագրեք ճիշտ տևողություն" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Ոչ մի ֆայլ չի ուղարկվել։ Ստուգեք ձևաթղթի կոդավորում տեսակը" + +msgid "No file was submitted." +msgstr "Ոչ մի ֆայլ չի ուղարկվել" + +msgid "The submitted file is empty." +msgstr "Ուղարկված ֆայլը դատարկ է" + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Համոզվեք, որ ֆայլի անունը պարունակում է ամենաշատը %(max)d նիշ (այն " +"պարունակում է %(length)d)" +msgstr[1] "" +"Համոզվեք, որ ֆայլի անունը պարունակում է ամենաշատը %(max)d նիշ (այն " +"պարունակում է %(length)d)" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Ուղարկեք ֆայլ, կամ ակտիվացրեք մաքրելու նշման վանդակը, ոչ թե երկուսը միասին" + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "Ուղարկեք ճիշտ պատկեր․ Ուղարկված ֆայլը պատկեր չէ, կամ վնասված է" + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Ընտրեք ճիշտ տարբերակ։ %(value)s արժեքը չի մտնում ճիշտ արժեքների մեջ" + +msgid "Enter a list of values." +msgstr "Մուտքագրեք արժեքների ցուցակ" + +msgid "Enter a complete value." +msgstr "Մուտքագրեք ամբողջական արժեք" + +msgid "Enter a valid UUID." +msgstr "Մուտքագրեք ճիշտ UUID" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Թաքցված դաշտ %(name)s) %(error)s" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "Կառավարման ձևաթղթի տվյալները բացակայում են, կամ վնասված են" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "Ուղարկեք %d կամ քիչ ձևաթղթեր" +msgstr[1] "Ուղարկեք %d կամ քիչ ձևաթղթեր" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "Ուղարկեք %d կամ շատ ձևաթղթեր" +msgstr[1] "Ուղարկեք %d կամ շատ ձևաթղթեր" + +msgid "Order" +msgstr "Հերթականություն" + +msgid "Delete" +msgstr "Հեռացնել" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Ուղղեք %(field)s դաշտի կրկնվող տվյալները" + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Ուղղեք %(field)s դաշտի կրկնվող տվյալները, որոնք պետք է լինեն եզակի" + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Ուղղեք %(field_name)s դաշտի կրկնվող տվյալները, որոնք պետք է լինեն եզակի " +"%(date_field)s-ում %(lookup)s֊ի համար" + +msgid "Please correct the duplicate values below." +msgstr "Ուղղեք կրկնվող տվյալները" + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Ընտրեք ճիշտ տարբերակ։ Այս արժեքը չի մտնում ճիշտ արժեքների մեջ" + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Մաքրել" + +msgid "Currently" +msgstr "Տվյալ պահին" + +msgid "Change" +msgstr "Փոխել" + +msgid "Unknown" +msgstr "Անհայտ" + +msgid "Yes" +msgstr "Այո" + +msgid "No" +msgstr "Ոչ" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "այո,ոչ,միգուցե" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d բայթ" +msgstr[1] "%(size)d բայթ" + +#, python-format +msgid "%s KB" +msgstr "%s ԿԲ" + +#, python-format +msgid "%s MB" +msgstr "%s ՄԲ" + +#, python-format +msgid "%s GB" +msgstr "%s ԳԲ" + +#, python-format +msgid "%s TB" +msgstr "%s ՏԲ" + +#, python-format +msgid "%s PB" +msgstr "%s ՊԲ" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "կեսգիշեր" + +msgid "noon" +msgstr "կեսօր" + +msgid "Monday" +msgstr "Երկուշաբթի" + +msgid "Tuesday" +msgstr "Երեքշաբթի" + +msgid "Wednesday" +msgstr "Չորեքշաբթի" + +msgid "Thursday" +msgstr "Հինգշաբթի" + +msgid "Friday" +msgstr "Ուրբաթ" + +msgid "Saturday" +msgstr "Շաբաթ" + +msgid "Sunday" +msgstr "Կիրակի" + +msgid "Mon" +msgstr "Երկ" + +msgid "Tue" +msgstr "Երք" + +msgid "Wed" +msgstr "Չրք" + +msgid "Thu" +msgstr "Հնգ" + +msgid "Fri" +msgstr "Ուրբ" + +msgid "Sat" +msgstr "Շբթ" + +msgid "Sun" +msgstr "Կիր" + +msgid "January" +msgstr "Հունվար" + +msgid "February" +msgstr "Փետրվար" + +msgid "March" +msgstr "Մարտ" + +msgid "April" +msgstr "Ապրիլ" + +msgid "May" +msgstr "Մայիս" + +msgid "June" +msgstr "Հունիս" + +msgid "July" +msgstr "Հուլիս" + +msgid "August" +msgstr "Օգոստոս" + +msgid "September" +msgstr "Սեպտեմբեր" + +msgid "October" +msgstr "Հոկտեմբեր" + +msgid "November" +msgstr "Նոյեմբեր" + +msgid "December" +msgstr "Դեկտեմբեր" + +msgid "jan" +msgstr "հուն" + +msgid "feb" +msgstr "փետ" + +msgid "mar" +msgstr "մար" + +msgid "apr" +msgstr "ապր" + +msgid "may" +msgstr "մայ" + +msgid "jun" +msgstr "հուն" + +msgid "jul" +msgstr "հուլ" + +msgid "aug" +msgstr "օգտ" + +msgid "sep" +msgstr "սեպ" + +msgid "oct" +msgstr "հոկ" + +msgid "nov" +msgstr "նոյ" + +msgid "dec" +msgstr "դեկ" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Հուն․" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Փետ․" + +msgctxt "abbrev. month" +msgid "March" +msgstr "Մարտ" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Մարտ" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Մայիս" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Հունիս" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Հուլիս" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Օգոստ․" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Սեպտ․" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Հոկտ․" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Նոյ․" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Դեկ․" + +msgctxt "alt. month" +msgid "January" +msgstr "Հունվար" + +msgctxt "alt. month" +msgid "February" +msgstr "Փետրվար" + +msgctxt "alt. month" +msgid "March" +msgstr "Մարտ" + +msgctxt "alt. month" +msgid "April" +msgstr "Ապրիլ" + +msgctxt "alt. month" +msgid "May" +msgstr "Մայիս" + +msgctxt "alt. month" +msgid "June" +msgstr "Հունիս" + +msgctxt "alt. month" +msgid "July" +msgstr "Հուլիս" + +msgctxt "alt. month" +msgid "August" +msgstr "Օգոստոս" + +msgctxt "alt. month" +msgid "September" +msgstr "Սեպտեմբեր" + +msgctxt "alt. month" +msgid "October" +msgstr "Հոկտեմբեր" + +msgctxt "alt. month" +msgid "November" +msgstr "Նոյեմբեր" + +msgctxt "alt. month" +msgid "December" +msgstr "Դեկտեմբեր" + +msgid "This is not a valid IPv6 address." +msgstr "Սա ճիշտ IPv6 հասցե չէ" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "կամ" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d տարի" +msgstr[1] "%d տարի" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d ամիս" +msgstr[1] "%d ամիս" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d շաբաթ" +msgstr[1] "%d շաբաթ" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d օր" +msgstr[1] "%d օր" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d ժամ" +msgstr[1] "%d ժամ" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d րոպե" +msgstr[1] "%d րոպե" + +msgid "0 minutes" +msgstr "0 րոպե" + +msgid "Forbidden" +msgstr "Արգելված" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF ստուգման սխալ․ Հարցումն ընդհատված է" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Դուք տեսնում եք այս հաղորդագրությունը, քանի որ այս կայքը ձևաթերթերը " +"ուղարկելու համար պահանջում է CSRF cookie։ Այն անհրաժեշտ է անվտանգության " +"նկատառումներից ելնելով, համոզվելու համար, որ ձեր բրաուզերը չի գտնվում երրորդ " +"անձանց կառավարման տակ։" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "Ավելի մանրամասն տեղեկությունը հասանելի է DEBUG=True֊ի ժամանակ" + +msgid "No year specified" +msgstr "Տարին նշված չէ" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "Ամիսը նշված չէ" + +msgid "No day specified" +msgstr "Օրը նշված չէ" + +msgid "No week specified" +msgstr "Շաբաթը նշված չէ" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Ոչ մի %(verbose_name_plural)s հասանելի չէ" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Ապագա %(verbose_name_plural)s հասանելի չեն, քանի որ %(class_name)s." +"allow_future ունի False արժեք" + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Հարցմանը համապատասխանող ոչ մի %(verbose_name)s չի գտնվել" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Սխալ էջ (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Կատալոգների ինդեքսավորումը թույլատրված չէ այստեղ" + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "%(directory)s֊ի ինդեքսը" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ia/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ia/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e22136f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ia/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ia/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ia/LC_MESSAGES/django.po new file mode 100644 index 0000000..adb852f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ia/LC_MESSAGES/django.po @@ -0,0 +1,1289 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Martijn Dekker , 2012,2014,2016,2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2021-11-18 21:19+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Interlingua (http://www.transifex.com/django/django/language/" +"ia/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ia\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "afrikaans" + +msgid "Arabic" +msgstr "arabe" + +msgid "Algerian Arabic" +msgstr "Arabe algerian" + +msgid "Asturian" +msgstr "asturiano" + +msgid "Azerbaijani" +msgstr "azeri" + +msgid "Bulgarian" +msgstr "bulgaro" + +msgid "Belarusian" +msgstr "bielorusso" + +msgid "Bengali" +msgstr "bengali" + +msgid "Breton" +msgstr "breton" + +msgid "Bosnian" +msgstr "bosniaco" + +msgid "Catalan" +msgstr "catalano" + +msgid "Czech" +msgstr "tcheco" + +msgid "Welsh" +msgstr "gallese" + +msgid "Danish" +msgstr "danese" + +msgid "German" +msgstr "germano" + +msgid "Lower Sorbian" +msgstr "sorabo inferior" + +msgid "Greek" +msgstr "greco" + +msgid "English" +msgstr "anglese" + +msgid "Australian English" +msgstr "anglese australian" + +msgid "British English" +msgstr "anglese britannic" + +msgid "Esperanto" +msgstr "esperanto" + +msgid "Spanish" +msgstr "espaniol" + +msgid "Argentinian Spanish" +msgstr "espaniol argentin" + +msgid "Colombian Spanish" +msgstr "espaniol colombian" + +msgid "Mexican Spanish" +msgstr "espaniol mexican" + +msgid "Nicaraguan Spanish" +msgstr "espaniol nicaraguan" + +msgid "Venezuelan Spanish" +msgstr "espaniol venzuelan" + +msgid "Estonian" +msgstr "estoniano" + +msgid "Basque" +msgstr "basco" + +msgid "Persian" +msgstr "persiano" + +msgid "Finnish" +msgstr "finnese" + +msgid "French" +msgstr "francese" + +msgid "Frisian" +msgstr "frison" + +msgid "Irish" +msgstr "irlandese" + +msgid "Scottish Gaelic" +msgstr "gaelico scotese" + +msgid "Galician" +msgstr "galiciano" + +msgid "Hebrew" +msgstr "hebreo" + +msgid "Hindi" +msgstr "hindi" + +msgid "Croatian" +msgstr "croato" + +msgid "Upper Sorbian" +msgstr "sorabo superior" + +msgid "Hungarian" +msgstr "hungaro" + +msgid "Armenian" +msgstr "Armenio" + +msgid "Interlingua" +msgstr "interlingua" + +msgid "Indonesian" +msgstr "indonesiano" + +msgid "Igbo" +msgstr "Igbo" + +msgid "Ido" +msgstr "ido" + +msgid "Icelandic" +msgstr "islandese" + +msgid "Italian" +msgstr "italiano" + +msgid "Japanese" +msgstr "japonese" + +msgid "Georgian" +msgstr "georgiano" + +msgid "Kabyle" +msgstr "Kabyle" + +msgid "Kazakh" +msgstr "kazakh" + +msgid "Khmer" +msgstr "khmer" + +msgid "Kannada" +msgstr "kannada" + +msgid "Korean" +msgstr "coreano" + +msgid "Kyrgyz" +msgstr "Kyrgyz" + +msgid "Luxembourgish" +msgstr "luxemburgese" + +msgid "Lithuanian" +msgstr "lituano" + +msgid "Latvian" +msgstr "letton" + +msgid "Macedonian" +msgstr "macedone" + +msgid "Malayalam" +msgstr "malayalam" + +msgid "Mongolian" +msgstr "mongolico" + +msgid "Marathi" +msgstr "marathi" + +msgid "Malay" +msgstr "" + +msgid "Burmese" +msgstr "burmese" + +msgid "Norwegian Bokmål" +msgstr "norvegianio bokmål" + +msgid "Nepali" +msgstr "nepali" + +msgid "Dutch" +msgstr "hollandese" + +msgid "Norwegian Nynorsk" +msgstr "norvegiano, nynorsk" + +msgid "Ossetic" +msgstr "ossetico" + +msgid "Punjabi" +msgstr "punjabi" + +msgid "Polish" +msgstr "polonese" + +msgid "Portuguese" +msgstr "portugese" + +msgid "Brazilian Portuguese" +msgstr "portugese brasilian" + +msgid "Romanian" +msgstr "romaniano" + +msgid "Russian" +msgstr "russo" + +msgid "Slovak" +msgstr "slovaco" + +msgid "Slovenian" +msgstr "sloveno" + +msgid "Albanian" +msgstr "albanese" + +msgid "Serbian" +msgstr "serbo" + +msgid "Serbian Latin" +msgstr "serbo latin" + +msgid "Swedish" +msgstr "svedese" + +msgid "Swahili" +msgstr "swahili" + +msgid "Tamil" +msgstr "tamil" + +msgid "Telugu" +msgstr "telugu" + +msgid "Tajik" +msgstr "Tadzhik" + +msgid "Thai" +msgstr "thailandese" + +msgid "Turkmen" +msgstr "Turkmen" + +msgid "Turkish" +msgstr "turco" + +msgid "Tatar" +msgstr "tartaro" + +msgid "Udmurt" +msgstr "udmurto" + +msgid "Ukrainian" +msgstr "ukrainiano" + +msgid "Urdu" +msgstr "urdu" + +msgid "Uzbek" +msgstr "Uzbek" + +msgid "Vietnamese" +msgstr "vietnamese" + +msgid "Simplified Chinese" +msgstr "chinese simplificate" + +msgid "Traditional Chinese" +msgstr "chinese traditional" + +msgid "Messages" +msgstr "Messages" + +msgid "Site Maps" +msgstr "Mappas de sito" + +msgid "Static Files" +msgstr "Files static" + +msgid "Syndication" +msgstr "Syndication" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Le numero de pagina non es un numero integre" + +msgid "That page number is less than 1" +msgstr "Le numero de pagina es minus de 1" + +msgid "That page contains no results" +msgstr "Le pagina non contine resultatos" + +msgid "Enter a valid value." +msgstr "Specifica un valor valide." + +msgid "Enter a valid URL." +msgstr "Specifica un URL valide." + +msgid "Enter a valid integer." +msgstr "Specifica un numero integre valide." + +msgid "Enter a valid email address." +msgstr "Specifica un adresse de e-mail valide." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Scribe un denotation (\"slug\") valide, consistente de litteras, numeros, " +"tractos de sublineamento o tractos de union." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Scribe un denotation (\"slug\") valide, consistente de litteras Unicode, " +"numeros, tractos de sublineamento o tractos de union." + +msgid "Enter a valid IPv4 address." +msgstr "Specifica un adresse IPv4 valide." + +msgid "Enter a valid IPv6 address." +msgstr "Specifica un adresse IPv6 valide." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Specifica un adresse IPv4 o IPv6 valide." + +msgid "Enter only digits separated by commas." +msgstr "Scribe solmente digitos separate per commas." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Assecura te que iste valor es %(limit_value)s (illo es %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Assecura te que iste valor es inferior o equal a %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Assecura te que iste valor es superior o equal a %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Assecura te que iste valor ha al minus %(limit_value)d character (illo ha " +"%(show_value)d)." +msgstr[1] "" +"Assecura te que iste valor ha al minus %(limit_value)d characteres (illo ha " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Assecura te que iste valor ha al plus %(limit_value)d character (illo ha " +"%(show_value)d)." +msgstr[1] "" +"Assecura te que iste valor ha al plus %(limit_value)d characteres (illo ha " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Specifica un numero." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Assecura te que il non ha plus de %(max)s digito in total." +msgstr[1] "Assecura te que il non ha plus de %(max)s digitos in total." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +"Assecura te que il non ha plus de %(max)s cifra post le comma decimal." +msgstr[1] "" +"Assecura te que il non ha plus de %(max)s cifras post le comma decimal." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Assecura te que il non ha plus de %(max)s cifra ante le comma decimal." +msgstr[1] "" +"Assecura te que il non ha plus de %(max)s cifras ante le comma decimal." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Le extension de nomine de file “%(extension)s” non es permittite. Le " +"extensiones permittite es: %(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Characteres nulle non es permittite." + +msgid "and" +msgstr "e" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "Jam existe %(model_name)s con iste %(field_labels)s." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Le valor %(value)r non es un option valide." + +msgid "This field cannot be null." +msgstr "Iste campo non pote esser nulle." + +msgid "This field cannot be blank." +msgstr "Iste campo non pote esser vacue." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s con iste %(field_label)s jam existe." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s debe esser unic pro %(lookup_type)s de %(date_field_label)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Campo de typo: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "Le valor “%(value)s” debe esser o True/Ver o False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "Le valor “%(value)s” debe esser True/Ver, False o None/Necun." + +msgid "Boolean (Either True or False)" +msgstr "Booleano (ver o false)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Catena (longitude maxime: %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "Numeros integre separate per commas" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"Le valor “%(value)s” ha un formato de data invalide. Debe esser in formato " +"AAAA-MM-DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"Le valor “%(value)s” ha le formato correcte (AAAA-MM-DD) ma es un data " +"invalide." + +msgid "Date (without time)" +msgstr "Data (sin hora)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"Le valor “%(value)s” es in un formato invalide. Debe esser in formato AAAA-" +"MM-DD HH:MM[:ss[.uuuuuu]][FH]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"Le valor “%(value)s” es in le formato correcte (YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][FH]) ma es un data/hora invalide." + +msgid "Date (with time)" +msgstr "Data (con hora)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "Le valor “%(value)s” debe esser un numero decimal." + +msgid "Decimal number" +msgstr "Numero decimal" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"Le valor “%(value)s” es in un formato invalide. Debe esser in formato [DD] " +"[HH:[MM:]]ss[.uuuuuu]." + +msgid "Duration" +msgstr "Duration" + +msgid "Email address" +msgstr "Adresse de e-mail" + +msgid "File path" +msgstr "Cammino de file" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "Le valor “%(value)s” debe esser un numero a comma flottante." + +msgid "Floating point number" +msgstr "Numero a comma flottante" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "Le valor “%(value)s” debe esser un numero integre." + +msgid "Integer" +msgstr "Numero integre" + +msgid "Big (8 byte) integer" +msgstr "Numero integre grande (8 bytes)" + +msgid "Small integer" +msgstr "Parve numero integre" + +msgid "IPv4 address" +msgstr "Adresse IPv4" + +msgid "IP address" +msgstr "Adresse IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "Le valor “%(value)s” debe esser None/Nulle, True/Ver o False." + +msgid "Boolean (Either True, False or None)" +msgstr "Booleano (ver, false o nulle)" + +msgid "Positive big integer" +msgstr "Grande numero integre positive" + +msgid "Positive integer" +msgstr "Numero integre positive" + +msgid "Positive small integer" +msgstr "Parve numero integre positive" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Denotation (longitude maxime: %(max_length)s)" + +msgid "Text" +msgstr "Texto" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"Le valor “%(value)s” es in un formato invalide. Debe esser in formato HH:MM[:" +"ss[.uuuuuu]] ." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"Le valor “%(value)s” es in le formato correcte (HH:MM[:ss[.uuuuuu]]) ma es " +"un hora invalide." + +msgid "Time" +msgstr "Hora" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Datos binari crude" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "“%(value)s” non es un UUID valide." + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "File" + +msgid "Image" +msgstr "Imagine" + +msgid "A JSON object" +msgstr "" + +msgid "Value must be valid JSON." +msgstr "" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "Le instantia de %(model)s con %(field)s %(value)r non existe." + +msgid "Foreign Key (type determined by related field)" +msgstr "Clave estranier (typo determinate per le campo associate)" + +msgid "One-to-one relationship" +msgstr "Relation un a un" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "Relation %(from)s a %(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "Relationes %(from)s a %(to)s" + +msgid "Many-to-many relationship" +msgstr "Relation multes a multes" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr "" + +msgid "This field is required." +msgstr "Iste campo es obligatori." + +msgid "Enter a whole number." +msgstr "Specifica un numero integre." + +msgid "Enter a valid date." +msgstr "Specifica un data valide." + +msgid "Enter a valid time." +msgstr "Specifica un hora valide." + +msgid "Enter a valid date/time." +msgstr "Specifica un data e hora valide." + +msgid "Enter a valid duration." +msgstr "Specifica un duration valide." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" +"Nulle file esseva submittite. Verifica le typo de codification in le " +"formulario." + +msgid "No file was submitted." +msgstr "Nulle file esseva submittite." + +msgid "The submitted file is empty." +msgstr "Le file submittite es vacue." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Assecura te que iste valor ha al plus %(max)d character (illo ha %(length)d)." +msgstr[1] "" +"Assecura te que iste valor ha al plus %(max)d characteres (illo ha " +"%(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Per favor o submitte un file o marca le quadrato \"rader\", non ambes." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Per favor incarga un imagine valide. Le file que tu incargava o non esseva " +"un imagine o esseva un imagine corrumpite." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Selige un option valide. %(value)s non es inter le optiones disponibile." + +msgid "Enter a list of values." +msgstr "Scribe un lista de valores." + +msgid "Enter a complete value." +msgstr "Specifica un valor complete." + +msgid "Enter a valid UUID." +msgstr "Specifica un UUID valide." + +msgid "Enter a valid JSON." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr "" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Campo celate %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" + +#, python-format +msgid "Please submit at most %d form." +msgid_plural "Please submit at most %d forms." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Please submit at least %d form." +msgid_plural "Please submit at least %d forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "Ordine" + +msgid "Delete" +msgstr "Deler" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Per favor corrige le datos duplicate pro %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Per favor corrige le datos duplicate pro %(field)s, que debe esser unic." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Per favor corrige le datos duplicate pro %(field_name)s, que debe esser unic " +"pro le %(lookup)s in %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Per favor corrige le sequente valores duplicate." + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Per favor selige un option valide. Iste option non es inter le optiones " +"disponibile." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Rader" + +msgid "Currently" +msgstr "Actualmente" + +msgid "Change" +msgstr "Cambiar" + +msgid "Unknown" +msgstr "Incognite" + +msgid "Yes" +msgstr "Si" + +msgid "No" +msgstr "No" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "si,no,forsan" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d byte" +msgstr[1] "%(size)d bytes" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "pm." + +msgid "a.m." +msgstr "am." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "medienocte" + +msgid "noon" +msgstr "mediedie" + +msgid "Monday" +msgstr "lunedi" + +msgid "Tuesday" +msgstr "martedi" + +msgid "Wednesday" +msgstr "mercuridi" + +msgid "Thursday" +msgstr "jovedi" + +msgid "Friday" +msgstr "venerdi" + +msgid "Saturday" +msgstr "sabbato" + +msgid "Sunday" +msgstr "dominica" + +msgid "Mon" +msgstr "lun" + +msgid "Tue" +msgstr "mar" + +msgid "Wed" +msgstr "mer" + +msgid "Thu" +msgstr "jov" + +msgid "Fri" +msgstr "ven" + +msgid "Sat" +msgstr "sab" + +msgid "Sun" +msgstr "dom" + +msgid "January" +msgstr "januario" + +msgid "February" +msgstr "februario" + +msgid "March" +msgstr "martio" + +msgid "April" +msgstr "april" + +msgid "May" +msgstr "maio" + +msgid "June" +msgstr "junio" + +msgid "July" +msgstr "julio" + +msgid "August" +msgstr "augusto" + +msgid "September" +msgstr "septembre" + +msgid "October" +msgstr "octobre" + +msgid "November" +msgstr "novembre" + +msgid "December" +msgstr "decembre" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "apr" + +msgid "may" +msgstr "mai" + +msgid "jun" +msgstr "jun" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "aug" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "oct" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dec" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Mar." + +msgctxt "abbrev. month" +msgid "April" +msgstr "April" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Maio" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Junio" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Julio" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Aug." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Sept." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Oct." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dec." + +msgctxt "alt. month" +msgid "January" +msgstr "Januario" + +msgctxt "alt. month" +msgid "February" +msgstr "Februario" + +msgctxt "alt. month" +msgid "March" +msgstr "Martio" + +msgctxt "alt. month" +msgid "April" +msgstr "April" + +msgctxt "alt. month" +msgid "May" +msgstr "Maio" + +msgctxt "alt. month" +msgid "June" +msgstr "Junio" + +msgctxt "alt. month" +msgid "July" +msgstr "Julio" + +msgctxt "alt. month" +msgid "August" +msgstr "Augusto" + +msgctxt "alt. month" +msgid "September" +msgstr "Septembre" + +msgctxt "alt. month" +msgid "October" +msgstr "Octobre" + +msgctxt "alt. month" +msgid "November" +msgstr "Novembre" + +msgctxt "alt. month" +msgid "December" +msgstr "Decembre" + +msgid "This is not a valid IPv6 address." +msgstr "Isto non es un adresse IPv6 valide." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "o" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "" +msgstr[1] "" + +msgid "Forbidden" +msgstr "Prohibite" + +msgid "CSRF verification failed. Request aborted." +msgstr "Verification CSRF fallite. Requesta abortate." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Tu vide iste message perque iste sito require un cookie CSRF durante le " +"submission de formularios. Iste cookie es requirite pro motivos de " +"securitate, pro assecurar que tu navigator non es sequestrate per tertie " +"personas." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "Plus information es disponibile con DEBUG=True." + +msgid "No year specified" +msgstr "Nulle anno specificate" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "Nulle mense specificate" + +msgid "No day specified" +msgstr "Nulle die specificate" + +msgid "No week specified" +msgstr "Nulle septimana specificate" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Il non ha %(verbose_name_plural)s disponibile" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"In le futuro, %(verbose_name_plural)s non essera disponibile perque " +"%(class_name)s.allow_future es False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Nulle %(verbose_name)s trovate que corresponde al consulta" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Pagina invalide (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Le indices de directorio non es permittite hic." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Indice de %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/id/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/id/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4a2eb2b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/id/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/id/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/id/LC_MESSAGES/django.po new file mode 100644 index 0000000..f0027b7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/id/LC_MESSAGES/django.po @@ -0,0 +1,1327 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Adiyat Mubarak , 2017 +# Claude Paroz , 2018 +# Fery Setiawan , 2015-2019,2021-2023 +# Jannis Leidel , 2011 +# M Asep Indrayana , 2015 +# oon arfiandwi (OonID) , 2016,2020 +# rodin , 2011 +# rodin , 2013-2016 +# sag᠎e , 2018-2019 +# Sutrisno Efendi , 2015,2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Fery Setiawan , 2015-2019,2021-2023\n" +"Language-Team: Indonesian (http://app.transifex.com/django/django/language/" +"id/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: id\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Afrikaans" +msgstr "Afrikaans" + +msgid "Arabic" +msgstr "Arab" + +msgid "Algerian Arabic" +msgstr "Arab Aljazair" + +msgid "Asturian" +msgstr "Asturia" + +msgid "Azerbaijani" +msgstr "Azerbaijani" + +msgid "Bulgarian" +msgstr "Bulgaria" + +msgid "Belarusian" +msgstr "Belarusia" + +msgid "Bengali" +msgstr "Bengali" + +msgid "Breton" +msgstr "Breton" + +msgid "Bosnian" +msgstr "Bosnia" + +msgid "Catalan" +msgstr "Catalan" + +msgid "Central Kurdish (Sorani)" +msgstr "Kurdi Tengah (Sorani)" + +msgid "Czech" +msgstr "Ceska" + +msgid "Welsh" +msgstr "Wales" + +msgid "Danish" +msgstr "Denmark" + +msgid "German" +msgstr "Jerman" + +msgid "Lower Sorbian" +msgstr "Sorbian Bawah" + +msgid "Greek" +msgstr "Yunani" + +msgid "English" +msgstr "Inggris" + +msgid "Australian English" +msgstr "Inggris Australia" + +msgid "British English" +msgstr "Inggris Britania" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Spanyol" + +msgid "Argentinian Spanish" +msgstr "Spanyol Argentina" + +msgid "Colombian Spanish" +msgstr "Spanyol Kolombia" + +msgid "Mexican Spanish" +msgstr "Spanyol Meksiko" + +msgid "Nicaraguan Spanish" +msgstr "Spanyol Nikaragua" + +msgid "Venezuelan Spanish" +msgstr "Spanyol Venezuela" + +msgid "Estonian" +msgstr "Estonia" + +msgid "Basque" +msgstr "Basque" + +msgid "Persian" +msgstr "Persia" + +msgid "Finnish" +msgstr "Finlandia" + +msgid "French" +msgstr "Perancis" + +msgid "Frisian" +msgstr "Frisia" + +msgid "Irish" +msgstr "Irlandia" + +msgid "Scottish Gaelic" +msgstr "Skolandia Gaelik" + +msgid "Galician" +msgstr "Galicia" + +msgid "Hebrew" +msgstr "Ibrani" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Kroasia" + +msgid "Upper Sorbian" +msgstr "Sorbian Atas" + +msgid "Hungarian" +msgstr "Hungaria" + +msgid "Armenian" +msgstr "Armenia" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonesia" + +msgid "Igbo" +msgstr "Igbo" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Islandia" + +msgid "Italian" +msgstr "Italia" + +msgid "Japanese" +msgstr "Jepang" + +msgid "Georgian" +msgstr "Georgia" + +msgid "Kabyle" +msgstr "Kabyle" + +msgid "Kazakh" +msgstr "Kazakhstan" + +msgid "Khmer" +msgstr "Khmer" + +msgid "Kannada" +msgstr "Kannada" + +msgid "Korean" +msgstr "Korea" + +msgid "Kyrgyz" +msgstr "Kirgis" + +msgid "Luxembourgish" +msgstr "Luksemburg" + +msgid "Lithuanian" +msgstr "Lithuania" + +msgid "Latvian" +msgstr "Latvia" + +msgid "Macedonian" +msgstr "Makedonia" + +msgid "Malayalam" +msgstr "Malayalam" + +msgid "Mongolian" +msgstr "Mongolia" + +msgid "Marathi" +msgstr "Marathi" + +msgid "Malay" +msgstr "Malaysia" + +msgid "Burmese" +msgstr "Burma" + +msgid "Norwegian Bokmål" +msgstr "Norwegia Bokmål" + +msgid "Nepali" +msgstr "Nepal" + +msgid "Dutch" +msgstr "Belanda" + +msgid "Norwegian Nynorsk" +msgstr "Norwegia Nynorsk" + +msgid "Ossetic" +msgstr "Ossetic" + +msgid "Punjabi" +msgstr "Punjabi" + +msgid "Polish" +msgstr "Polandia" + +msgid "Portuguese" +msgstr "Portugis" + +msgid "Brazilian Portuguese" +msgstr "Portugis Brazil" + +msgid "Romanian" +msgstr "Romania" + +msgid "Russian" +msgstr "Rusia" + +msgid "Slovak" +msgstr "Slovakia" + +msgid "Slovenian" +msgstr "Slovenia" + +msgid "Albanian" +msgstr "Albania" + +msgid "Serbian" +msgstr "Serbia" + +msgid "Serbian Latin" +msgstr "Serbia Latin" + +msgid "Swedish" +msgstr "Swedia" + +msgid "Swahili" +msgstr "Swahili" + +msgid "Tamil" +msgstr "Tamil" + +msgid "Telugu" +msgstr "Telugu" + +msgid "Tajik" +msgstr "Tajik" + +msgid "Thai" +msgstr "Thailand" + +msgid "Turkmen" +msgstr "Turkmenistan" + +msgid "Turkish" +msgstr "Turki" + +msgid "Tatar" +msgstr "Tatar" + +msgid "Udmurt" +msgstr "Udmurt" + +msgid "Uyghur" +msgstr "" + +msgid "Ukrainian" +msgstr "Ukrainia" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "Uzbek" + +msgid "Vietnamese" +msgstr "Vietnam" + +msgid "Simplified Chinese" +msgstr "Tiongkok Sederhana" + +msgid "Traditional Chinese" +msgstr "Tiongkok Tradisionil" + +msgid "Messages" +msgstr "Pesan" + +msgid "Site Maps" +msgstr "Peta Situs" + +msgid "Static Files" +msgstr "Berkas Statis" + +msgid "Syndication" +msgstr "Sindikasi" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Nomor halaman itu bukan sebuah integer" + +msgid "That page number is less than 1" +msgstr "Nomor halaman itu kurang dari 1" + +msgid "That page contains no results" +msgstr "Tidak ada hasil untuk halaman tersebut" + +msgid "Enter a valid value." +msgstr "Masukkan nilai yang valid." + +msgid "Enter a valid URL." +msgstr "Masukkan URL yang valid." + +msgid "Enter a valid integer." +msgstr "Masukan sebuah bilangan bulat yang benar" + +msgid "Enter a valid email address." +msgstr "Masukkan alamat email yang valid." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Masukkan “slug” valid yang terdiri dari huruf, angka, garis bawah, atau " +"tanda hubung." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Masukkan sebuah “slug” valid yang terdiri dari huruf, angka, garis bawah, " +"atau penghubung Unicode." + +msgid "Enter a valid IPv4 address." +msgstr "Masukkan alamat IPv4 yang valid." + +msgid "Enter a valid IPv6 address." +msgstr "Masukkan alamat IPv6 yang valid" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Masukkan alamat IPv4 atau IPv6 yang valid" + +msgid "Enter only digits separated by commas." +msgstr "Hanya masukkan angka yang dipisahkan dengan koma." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Pastikan nilai ini %(limit_value)s (saat ini %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Pastikan nilai ini lebih kecil dari atau sama dengan %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Pastikan nilai ini lebih besar dari atau sama dengan %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" +"Pastikan nilai ini adalah kelipatan dari ukuran langkah %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Pastikan nilai ini mengandung paling sedikit %(limit_value)d karakter " +"(sekarang %(show_value)d karakter)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Pastikan nilai ini mengandung paling banyak %(limit_value)d karakter " +"(sekarang %(show_value)d karakter)." + +msgid "Enter a number." +msgstr "Masukkan sebuah bilangan." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Pastikan jumlah angka pada bilangan tidak melebihi %(max)s angka." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Pastikan bilangan tidak memiliki lebih dari %(max)s angka desimal." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Pastikan jumlah angka sebelum desimal pada bilangan tidak memiliki lebih " +"dari %(max)s angka." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Ekstensi berkas “%(extension)s” tidak diizinkan. Ekstensi diizinkan adalah: " +"%(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Karakter null tidak diizinkan." + +msgid "and" +msgstr "dan" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s dengan %(field_labels)s ini tidak ada." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Batasan “%(name)s” dilanggar." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Nilai %(value)r bukan pilihan yang valid." + +msgid "This field cannot be null." +msgstr "Field ini tidak boleh null." + +msgid "This field cannot be blank." +msgstr "Field ini tidak boleh kosong." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s dengan %(field_label)s telah ada." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s haruslah unik untuk %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Field dengan tipe: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "Nilai “%(value)s” harus berupa True atau False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "Nilai “%(value)s” harus berupa True, False, atau None." + +msgid "Boolean (Either True or False)" +msgstr "Nilai Boolean (Salah satu dari True atau False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "String (maksimum %(max_length)s)" + +msgid "String (unlimited)" +msgstr "String (tidak terbatas)" + +msgid "Comma-separated integers" +msgstr "Bilangan asli yang dipisahkan dengan koma" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"Nilai “%(value)s” mempunyai format tanggal yang tidak valid. Tanggal harus " +"dalam format YYYY-MM-DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"Nilai “%(value)s” memiliki format yang benar (YYYY-MM-DD), tetapi tanggalnya " +"tidak valid." + +msgid "Date (without time)" +msgstr "Tanggal (tanpa waktu)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"Nilai “%(value)s” memiliki format yang tidak valid. Tanggal dan waktu harus " +"dalam format YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"Nilai “%(value)s” memiliki format yang benar (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]), tetapi tanggal/waktunya tidak valid." + +msgid "Date (with time)" +msgstr "Tanggal (dengan waktu)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "Nilai “%(value)s” harus berupa bilangan desimal." + +msgid "Decimal number" +msgstr "Bilangan desimal" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"Nilai “%(value)s” mempunyai format yang tidak valid. Waktu harus dalam " +"format [DD] [[HH:]MM:]ss[.uuuuuu]." + +msgid "Duration" +msgstr "Durasi" + +msgid "Email address" +msgstr "Alamat email" + +msgid "File path" +msgstr "Lokasi berkas" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "Nilai “%(value)s” harus berupa bilangan real." + +msgid "Floating point number" +msgstr "Bilangan 'floating point'" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "Nilai “%(value)s” harus berupa integer." + +msgid "Integer" +msgstr "Bilangan Asli" + +msgid "Big (8 byte) integer" +msgstr "Bilangan asli raksasa (8 byte)" + +msgid "Small integer" +msgstr "Bilangan asli kecil" + +msgid "IPv4 address" +msgstr "Alamat IPv4" + +msgid "IP address" +msgstr "Alamat IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "Nilai “%(value)s” harus berupa None, True, atau False." + +msgid "Boolean (Either True, False or None)" +msgstr "Boolean (Salah satu dari True, False, atau None)" + +msgid "Positive big integer" +msgstr "Integer besar positif" + +msgid "Positive integer" +msgstr "Bilangan asli positif" + +msgid "Positive small integer" +msgstr "Bilangan asli kecil positif" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (hingga %(max_length)s karakter)" + +msgid "Text" +msgstr "Teks" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"Nilai “%(value)s” mempunyai format yang tidak valid. Waktu harus dalam " +"format HH:MM[:ss[.uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"Nilai “%(value)s” mempunyai format yang benar (HH:MM[:ss[.uuuuuu]]), tetapi " +"nilai waktunya tidak valid." + +msgid "Time" +msgstr "Waktu" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Data biner mentah" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "“%(value)s” bukan UUID yang valid." + +msgid "Universally unique identifier" +msgstr "Pengenal unik secara universal" + +msgid "File" +msgstr "Berkas" + +msgid "Image" +msgstr "Gambar" + +msgid "A JSON object" +msgstr "Objek JSON" + +msgid "Value must be valid JSON." +msgstr "Nilai harus JSON yang valid." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "Salinan %(model)s dengan %(field)s %(value)r tidak ada." + +msgid "Foreign Key (type determined by related field)" +msgstr "Kunci Asing (tipe tergantung dari bidang yang berkaitan)" + +msgid "One-to-one relationship" +msgstr "Hubungan satu-ke-satu" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "Hubungan %(from)s-%(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "Hubungan %(from)s-%(to)s" + +msgid "Many-to-many relationship" +msgstr "Hubungan banyak-ke-banyak" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Bidang ini tidak boleh kosong." + +msgid "Enter a whole number." +msgstr "Masukkan keseluruhan angka bilangan." + +msgid "Enter a valid date." +msgstr "Masukkan tanggal yang valid." + +msgid "Enter a valid time." +msgstr "Masukkan waktu yang valid." + +msgid "Enter a valid date/time." +msgstr "Masukkan tanggal/waktu yang valid." + +msgid "Enter a valid duration." +msgstr "Masukan durasi waktu yang benar." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Jumlah hari harus di antara {min_days} dan {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Tidak ada berkas yang dikirimkan. Periksa tipe pengaksaraan formulir." + +msgid "No file was submitted." +msgstr "Tidak ada berkas yang dikirimkan." + +msgid "The submitted file is empty." +msgstr "Berkas yang dikirimkan kosong." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Pastikan nama berkas ini mengandung paling banyak %(max)d karakter (sekarang " +"%(length)d karakter)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Pilih antara mengirimkan berkas atau menghapus tanda centang pada kotak " +"centang" + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Unggah gambar yang valid. Berkas yang Anda unggah bukan merupakan berkas " +"gambar atau gambarnya rusak." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Masukkan pilihan yang valid. %(value)s bukan salah satu dari pilihan yang " +"tersedia." + +msgid "Enter a list of values." +msgstr "Masukkan beberapa nilai." + +msgid "Enter a complete value." +msgstr "Masukkan nilai yang komplet." + +msgid "Enter a valid UUID." +msgstr "Masukan UUID yang benar." + +msgid "Enter a valid JSON." +msgstr "Masukkan JSON yang valid." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Bidang tersembunyi %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"Data ManagementForm telah hilang atau telah dirusak. Bidang yang hilang: " +"%(field_names)s. Anda mungkin butuh memberkaskan laporan kesalahan jika " +"masalah masih ada." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Harap ajukan paling banyak %(num)d formulir." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Harap ajukan setidaknya %(num)d formulir." + +msgid "Order" +msgstr "Urutan" + +msgid "Delete" +msgstr "Hapus" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Perbaiki data ganda untuk %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Perbaiki data ganda untuk %(field)s yang nilainya harus unik." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Perbaiki data ganda untuk %(field_name)s yang nilainya harus unik untuk " +"pencarian %(lookup)s pada %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Perbaiki nilai ganda di bawah ini." + +msgid "The inline value did not match the parent instance." +msgstr "Nilai sebaris tidak cocok dengan instance induk." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Masukkan pilihan yang valid. Pilihan tersebut bukan salah satu dari pilihan " +"yang tersedia." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "“%(pk)s” bukan nilai yang valid." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s tidak dapat diterjemahkan dalam zona waktu " +"%(current_timezone)s; mungkin nilainya ambigu atau tidak ada." + +msgid "Clear" +msgstr "Hapus" + +msgid "Currently" +msgstr "Saat ini" + +msgid "Change" +msgstr "Ubah" + +msgid "Unknown" +msgstr "Tidak diketahui" + +msgid "Yes" +msgstr "Ya" + +msgid "No" +msgstr "Tidak" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "ya,tidak,mungkin" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d bita" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m" + +msgid "a.m." +msgstr "a.m" + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "tengah malam" + +msgid "noon" +msgstr "siang" + +msgid "Monday" +msgstr "Senin" + +msgid "Tuesday" +msgstr "Selasa" + +msgid "Wednesday" +msgstr "Rabu" + +msgid "Thursday" +msgstr "Kamis" + +msgid "Friday" +msgstr "Jumat" + +msgid "Saturday" +msgstr "Sabtu" + +msgid "Sunday" +msgstr "Minggu" + +msgid "Mon" +msgstr "Sen" + +msgid "Tue" +msgstr "Sel" + +msgid "Wed" +msgstr "Rab" + +msgid "Thu" +msgstr "Kam" + +msgid "Fri" +msgstr "Jum" + +msgid "Sat" +msgstr "Sab" + +msgid "Sun" +msgstr "Min" + +msgid "January" +msgstr "Januari" + +msgid "February" +msgstr "Februari" + +msgid "March" +msgstr "Maret" + +msgid "April" +msgstr "April" + +msgid "May" +msgstr "Mei" + +msgid "June" +msgstr "Juni" + +msgid "July" +msgstr "Juli" + +msgid "August" +msgstr "Agustus" + +msgid "September" +msgstr "September" + +msgid "October" +msgstr "Oktober" + +msgid "November" +msgstr "November" + +msgid "December" +msgstr "Desember" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "apr" + +msgid "may" +msgstr "mei" + +msgid "jun" +msgstr "jun" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "agu" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "okt" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "des" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Maret" + +msgctxt "abbrev. month" +msgid "April" +msgstr "April" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Mei" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Juni" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Juli" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Agu" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Sep." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Okt." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Des." + +msgctxt "alt. month" +msgid "January" +msgstr "Januari" + +msgctxt "alt. month" +msgid "February" +msgstr "Februari" + +msgctxt "alt. month" +msgid "March" +msgstr "Maret" + +msgctxt "alt. month" +msgid "April" +msgstr "April" + +msgctxt "alt. month" +msgid "May" +msgstr "Mei" + +msgctxt "alt. month" +msgid "June" +msgstr "Juni" + +msgctxt "alt. month" +msgid "July" +msgstr "Juli" + +msgctxt "alt. month" +msgid "August" +msgstr "Agustus" + +msgctxt "alt. month" +msgid "September" +msgstr "September" + +msgctxt "alt. month" +msgid "October" +msgstr "Oktober" + +msgctxt "alt. month" +msgid "November" +msgstr "November" + +msgctxt "alt. month" +msgid "December" +msgstr "Desember" + +msgid "This is not a valid IPv6 address." +msgstr "Ini bukan alamat IPv6 yang valid." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "atau" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d tahun" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d bulan" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d minggu" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d hari" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d jam" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d menit" + +msgid "Forbidden" +msgstr "Terlarang" + +msgid "CSRF verification failed. Request aborted." +msgstr "Verifikasi CSRF gagal, Permintaan dibatalkan." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Anda melihat pesan ini karena jaringan HTTPS ini membutuhkan “Referer " +"header” untuk dikirim oleh peramban jaringan anda, tetapi tidak ada yg " +"dikirim. Kepala ini diwajibkan untuk alasan keamanan, untuk memastikan bahwa " +"peramban anda tidak sedang dibajak oleh pihak ketiga." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Jika Anda menonaktifkan header 'Referrer' pada konfigurasi peramban Anda, " +"mohon aktfikan kembali, setidaknya untuk situs ini, untuk koneksi HTTPS, " +"atau untuk request 'same-origin'." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Jika Anda menggunakan tag " +"atau menyertakan bagian kepala 'Referrer-Policy: no-referrer', harap hapus " +"hal tersebut. Perlindungan CSRF membutuhkan bagian kepala 'Referrer' untuk " +"melakukan pemeriksaan pengarahan ketat. Jika Anda khawatir mengenai privasi, " +"gunakan cara lain seperti untuk tautan ke situs " +"pihak ketiga." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Anda melihat pesan ini karena situs ini membutuhkan sebuah kuki CSRF ketika " +"mengirimkan formulir. Kuki ini dibutuhkan untuk alasan keamanan, untuk " +"memastikan bahwa peramban Anda tidak sedang dibajak oleh pihak ketiga." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Jika Anda telah mengatur peramban Anda untuk menonaktifkan kuki, maka " +"aktifkanlah kembali, setidaknya untuk website ini, atau untuk request 'same-" +"origin'." + +msgid "More information is available with DEBUG=True." +msgstr "Informasi lebih lanjut tersedia dengan DEBUG=True" + +msgid "No year specified" +msgstr "Tidak ada tahun dipilih" + +msgid "Date out of range" +msgstr "Tanggal di luar kisaran" + +msgid "No month specified" +msgstr "Tidak ada bulan dipilih" + +msgid "No day specified" +msgstr "Tidak ada hari dipilih" + +msgid "No week specified" +msgstr "Tidak ada minggu dipilih" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Tidak ada %(verbose_name_plural)s tersedia" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"%(verbose_name_plural)s di masa depan tidak tersedia karena %(class_name)s." +"allow_future bernilai False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Nilai tanggal tidak valid “%(datestr)s” untuk format “%(format)s”" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Tidak ada %(verbose_name)s yang cocok dengan kueri" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" +"Laman bukan yang “terakhir” dan juga tidak dapat dikonversikan ke sebuah " +"integer." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Laman tidak valid (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Daftar kosong dan '%(class_name)s.allow_empty' bernilai False." + +msgid "Directory indexes are not allowed here." +msgstr "Indeks direktori tidak diizinkan di sini." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "“%(path)s” tidak ada" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Daftar isi %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Selamat! Instalasi berjalan lancar!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Lihat catatan rilis untuk Django %(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Anda sedang melihat halaman ini karena DEBUG=True berada di berkas pengaturan Anda dan Anda " +"belum mengonfigurasi URL apa pun." + +msgid "Django Documentation" +msgstr "Dokumentasi Django" + +msgid "Topics, references, & how-to’s" +msgstr "Topik, referensi, & cara pemakaian" + +msgid "Tutorial: A Polling App" +msgstr "Tutorial: Sebuah Aplikasi Jajak Pendapat" + +msgid "Get started with Django" +msgstr "Memulai dengan Django" + +msgid "Django Community" +msgstr "Komunitas Django" + +msgid "Connect, get help, or contribute" +msgstr "Terhubung, minta bantuan, atau berkontribusi" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/id/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/id/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/id/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/id/formats.py new file mode 100644 index 0000000..91a2559 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/id/formats.py @@ -0,0 +1,49 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j N Y" +DATETIME_FORMAT = "j N Y, G.i" +TIME_FORMAT = "G.i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "d-m-Y" +SHORT_DATETIME_FORMAT = "d-m-Y G.i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d-%m-%Y", # '25-10-2009' + "%d/%m/%Y", # '25/10/2009' + "%d-%m-%y", # '25-10-09' + "%d/%m/%y", # '25/10/09' + "%d %b %Y", # '25 Oct 2006', + "%d %B %Y", # '25 October 2006' + "%m/%d/%y", # '10/25/06' + "%m/%d/%Y", # '10/25/2009' +] + +TIME_INPUT_FORMATS = [ + "%H.%M.%S", # '14.30.59' + "%H.%M", # '14.30' +] + +DATETIME_INPUT_FORMATS = [ + "%d-%m-%Y %H.%M.%S", # '25-10-2009 14.30.59' + "%d-%m-%Y %H.%M.%S.%f", # '25-10-2009 14.30.59.000200' + "%d-%m-%Y %H.%M", # '25-10-2009 14.30' + "%d-%m-%y %H.%M.%S", # '25-10-09' 14.30.59' + "%d-%m-%y %H.%M.%S.%f", # '25-10-09' 14.30.59.000200' + "%d-%m-%y %H.%M", # '25-10-09' 14.30' + "%m/%d/%y %H.%M.%S", # '10/25/06 14.30.59' + "%m/%d/%y %H.%M.%S.%f", # '10/25/06 14.30.59.000200' + "%m/%d/%y %H.%M", # '10/25/06 14.30' + "%m/%d/%Y %H.%M.%S", # '25/10/2009 14.30.59' + "%m/%d/%Y %H.%M.%S.%f", # '25/10/2009 14.30.59.000200' + "%m/%d/%Y %H.%M", # '25/10/2009 14.30' +] + +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ig/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ig/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8e689c8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ig/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ig/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ig/LC_MESSAGES/django.po new file mode 100644 index 0000000..19e47ed --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ig/LC_MESSAGES/django.po @@ -0,0 +1,1271 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Kelechi Precious Nwachukwu , 2020 +# Mariusz Felisiak , 2020 +# Okpala Olisa , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-19 20:23+0200\n" +"PO-Revision-Date: 2020-07-30 12:26+0000\n" +"Last-Translator: Mariusz Felisiak \n" +"Language-Team: Igbo (http://www.transifex.com/django/django/language/ig/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ig\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Afrikaans" +msgstr "Afrikaans" + +msgid "Arabic" +msgstr "Arabici" + +msgid "Algerian Arabic" +msgstr "Arabici ndị Algeria " + +msgid "Asturian" +msgstr "Asturian" + +msgid "Azerbaijani" +msgstr "Azerbaijani" + +msgid "Bulgarian" +msgstr "Bulgaria" + +msgid "Belarusian" +msgstr "Belarusia" + +msgid "Bengali" +msgstr "Bengali" + +msgid "Breton" +msgstr "Breton" + +msgid "Bosnian" +msgstr "Bosnian" + +msgid "Catalan" +msgstr "Catalan" + +msgid "Czech" +msgstr "Czech" + +msgid "Welsh" +msgstr "Welsh" + +msgid "Danish" +msgstr "Danishi" + +msgid "German" +msgstr "Germani" + +msgid "Lower Sorbian" +msgstr "Sorbian nke Ala" + +msgid "Greek" +msgstr "Greeki" + +msgid "English" +msgstr "Bekee" + +msgid "Australian English" +msgstr "Bekee ndị Australia" + +msgid "British English" +msgstr "Bekee ndị Britain" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Spanishi" + +msgid "Argentinian Spanish" +msgstr "Spanishi ndị Argentina" + +msgid "Colombian Spanish" +msgstr "Spanishi ndị Colombia " + +msgid "Mexican Spanish" +msgstr "Spanishi ndị Mexico " + +msgid "Nicaraguan Spanish" +msgstr "Spanishi ndị Nicaraguan" + +msgid "Venezuelan Spanish" +msgstr "Spanishi ndị Venezuela " + +msgid "Estonian" +msgstr "Estonian" + +msgid "Basque" +msgstr "Basque" + +msgid "Persian" +msgstr "Persian" + +msgid "Finnish" +msgstr "Finnishi" + +msgid "French" +msgstr "Fụrenchị" + +msgid "Frisian" +msgstr "Frisian" + +msgid "Irish" +msgstr "Irishi" + +msgid "Scottish Gaelic" +msgstr "Scottish Gaelici" + +msgid "Galician" +msgstr "Galiciani" + +msgid "Hebrew" +msgstr "Hibru" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Croatian" + +msgid "Upper Sorbian" +msgstr "Sorbian nke Elu" + +msgid "Hungarian" +msgstr "Hungarian" + +msgid "Armenian" +msgstr "Armeniani" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonesian" + +msgid "Igbo" +msgstr "ìgbò" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Icelandici" + +msgid "Italian" +msgstr "Italian" + +msgid "Japanese" +msgstr "Japanisi " + +msgid "Georgian" +msgstr "Georgian" + +msgid "Kabyle" +msgstr "Kabyle" + +msgid "Kazakh" +msgstr "Kazakh" + +msgid "Khmer" +msgstr "Khmer" + +msgid "Kannada" +msgstr "Kannada" + +msgid "Korean" +msgstr "Korean" + +msgid "Kyrgyz" +msgstr "Kyrgyz" + +msgid "Luxembourgish" +msgstr "Luxembourgish" + +msgid "Lithuanian" +msgstr "Lithuanian" + +msgid "Latvian" +msgstr "Latvian" + +msgid "Macedonian" +msgstr "Macedonian" + +msgid "Malayalam" +msgstr "Malayalam" + +msgid "Mongolian" +msgstr "Mongolian" + +msgid "Marathi" +msgstr "Marathi" + +msgid "Burmese" +msgstr "Burmese" + +msgid "Norwegian Bokmål" +msgstr "Bokmål ndị Norway" + +msgid "Nepali" +msgstr "Nepali" + +msgid "Dutch" +msgstr "Dutch" + +msgid "Norwegian Nynorsk" +msgstr "Nynorsk ndị Norway " + +msgid "Ossetic" +msgstr "Ossetici" + +msgid "Punjabi" +msgstr "Punjabi" + +msgid "Polish" +msgstr "Polishi" + +msgid "Portuguese" +msgstr "Portuguisi" + +msgid "Brazilian Portuguese" +msgstr "Portuguese ndị Brazil" + +msgid "Romanian" +msgstr "Romaniani" + +msgid "Russian" +msgstr "Russiani" + +msgid "Slovak" +msgstr "Slovaki" + +msgid "Slovenian" +msgstr "Sloveniani" + +msgid "Albanian" +msgstr "Albaniani" + +msgid "Serbian" +msgstr "Serbiani" + +msgid "Serbian Latin" +msgstr "Serbian Latini" + +msgid "Swedish" +msgstr "Swedishi" + +msgid "Swahili" +msgstr "Swahili" + +msgid "Tamil" +msgstr "Tamil" + +msgid "Telugu" +msgstr "Telugu" + +msgid "Tajik" +msgstr "Tajik" + +msgid "Thai" +msgstr "Thai" + +msgid "Turkmen" +msgstr "Turkmen" + +msgid "Turkish" +msgstr "Turkishi" + +msgid "Tatar" +msgstr "Tatar" + +msgid "Udmurt" +msgstr "Udmurt" + +msgid "Ukrainian" +msgstr "Ukrainiani" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "Uzbeki" + +msgid "Vietnamese" +msgstr "Vietnamesi" + +msgid "Simplified Chinese" +msgstr "Chinisi Ndị Mfe" + +msgid "Traditional Chinese" +msgstr "Odịnala Chinisi" + +msgid "Messages" +msgstr "Ozi" + +msgid "Site Maps" +msgstr "Maapụ Saịtị" + +msgid "Static Files" +msgstr "Faịlụ Nkwụsiri ike" + +msgid "Syndication" +msgstr "Nyefee Njikwa" + +msgid "That page number is not an integer" +msgstr "Nọmba peeji ahụ abụghị onu ogugu" + +msgid "That page number is less than 1" +msgstr "Nọmba peeji ahụ erughị 1" + +msgid "That page contains no results" +msgstr "Peeji ahụ enweghị nsonaazụ ọ bụla" + +msgid "Enter a valid value." +msgstr "Tinye uru zuru oke." + +msgid "Enter a valid URL." +msgstr "Tinye URL zuru oke." + +msgid "Enter a valid integer." +msgstr "Tinye nọmba zuru oke." + +msgid "Enter a valid email address." +msgstr "Tinye adreesị ozi ịntanetị n'zuru oke." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Tinye “slug” zuru oke nke mejupụtara mkpụrụedemede, ọnụọgụ, underscores ma ọ " +"bụ hyphens." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Tinye “slug” zuru oke nke mejupụtara Unicode mkpụrụedemede, ọnụọgụ, " +"underscores ma ọ bụ hyphens." + +msgid "Enter a valid IPv4 address." +msgstr "Tinye adreesị IPv4 zuru oke." + +msgid "Enter a valid IPv6 address." +msgstr "Tinye adreesị IPv6 zuru oke." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Tinye adreesị IPv4 ma obu IPv6 zuru oke." + +msgid "Enter only digits separated by commas." +msgstr "Tinye naanị ọnụọgụ kewapụrụ site na comma." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Gbaa mbọ hụ na %(limit_value)s (ọ bụ %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Gbaa mbọ hụ na orughị ma ọ bụ hara nhata %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Gbaa mbọ hụ na okarịa ma ọ bụ hara nhata%(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Gbaa mbọ hụ na a nwere opekata mpe %(limit_value)d odide (o nwere " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Gbaa mbọ hụ na a nwere kacha %(limit_value)d odide (o nwere%(show_value)d)." + +msgid "Enter a number." +msgstr "Tinye nọmba." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Gbaa mbọ hụ na ọ dighi karịrị %(max)s nọmba na mkpokọta." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Gbaa mbọ hụ na ọ dighi karịrị %(max)s na ebe ntụpọ." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "Gbaa mbọ hụ na ọ dighi karịrị %(max)s nọmba tupu akụkụ ebe ntụpọ." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Ndọtị Faịlị “%(extension)s”anaghị anabata. Ndọtị nke kwere n'nabata bu: " +"%(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Anabataghị ihe odide n'enweghị isi." + +msgid "and" +msgstr "na" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s ya na nke a %(field_labels)s dị adị." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Nọmba %(value)r abụghị ezigbo nhọrọ." + +msgid "This field cannot be null." +msgstr "Ebe a enweghị ike ịbụ ihe efu." + +msgid "This field cannot be blank." +msgstr "Ebe a enweghị ike ịbụ ohere efu." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s ya na nke a %(field_label)s dị adi." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s ga-abụ ihe pụrụ iche maka %(date_field_label)s " +"%(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Ebe a nke ụdị: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "“%(value)s” uru a ga-abụrịrị Eziokwu ma ọ bụ Ugha." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "“%(value)s”uru a ga-abụrịrị Eziokwu, Ugha, ma ọ bụ Onweghị." + +msgid "Boolean (Either True or False)" +msgstr "Boolean (Eziokwu ma o bụ Ugha)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "String (ruo %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "Rikom-kewapụrụ nomba" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"“%(value)s” uru a nwere usoro nke n'adịghị adị. Ọ ga-abụrịrị n'ụdị YYYY-MM-" +"DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"“%(value)s”uru a nwere usoro ziri ezi (YYYY-MM-DD) mana ọ bụ ụbọchị n'abaghị " +"uru." + +msgid "Date (without time)" +msgstr "Ubọchị (na-enweghị oge)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"“%(value)s” uru a nwere usoro nke n'adịghị adị. Ọ ga-abụrịrị n'ụdị YYYY-MM-" +"DD HH:MM[:ss[.uuuuuu]][TZ] usoro. " + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"“%(value)s”uru a nwere usoro ziri ezi (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ])mana ọ bụ ụbọchị n'abaghị uru." + +msgid "Date (with time)" +msgstr "Ubọchị (na oge)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "“%(value)s” uru a ga-abụrịrị nọmba ntụpọ." + +msgid "Decimal number" +msgstr "Nọmba ntụpọ." + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"“%(value)s”uru a nwere usoro nke n'adịghị adị. Ọ ga-abụrịrị n'ụdị [DD] " +"[[HH:]MM:]ss[.uuuuuu]usoro." + +msgid "Duration" +msgstr "Oge ole" + +msgid "Email address" +msgstr "Adreesị ozi ịntanetị" + +msgid "File path" +msgstr "Uzọ Faịlụ di" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "“%(value)s”uru a ga-abụrịrị float." + +msgid "Floating point number" +msgstr "Nọmba ebe floating no " + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "“%(value)s” uru a ga-abụrịrị onu ogugu" + +msgid "Integer" +msgstr "Onu ogugu" + +msgid "Big (8 byte) integer" +msgstr "Onu ogugu (8 byte) nnukwu" + +msgid "IPv4 address" +msgstr "Adreesị IPv4" + +msgid "IP address" +msgstr "Adreesị IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "“%(value)s”uru a ga-abụrịrị na Odighị, Eziokwu ma ọ bụ.Ugha." + +msgid "Boolean (Either True, False or None)" +msgstr "Boolean (Ihe a ga abụriri eziokwu, ụgha ma ọ bu na onweghi)" + +msgid "Positive big integer" +msgstr "Nnukwu nomba nke oma" + +msgid "Positive integer" +msgstr "Nọmba nke oma" + +msgid "Positive small integer" +msgstr "Obere nọmba nke oma" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (ruo %(max_length)s)" + +msgid "Small integer" +msgstr "Onu ogugu nke obere" + +msgid "Text" +msgstr "Ederede" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"“%(value)s” uru a nwere usoro nke n'adịghị adị. Ọ ga-abụrịrị n'ụdị HH:MM[:" +"ss[.uuuuuu]]usoro." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"“%(value)s” uru a nwere usoro ziri ezi (HH:MM[:ss[.uuuuuu]]) mana ọ bu oge " +"n'abaghị uru." + +msgid "Time" +msgstr "Oge" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Raw binary data" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "“%(value)s”abụghị UUID n’kwesịrị ekwesị." + +msgid "Universally unique identifier" +msgstr "Universally unique identifier" + +msgid "File" +msgstr "Faịlụ" + +msgid "Image" +msgstr "Foto" + +msgid "A JSON object" +msgstr "Ihe JSON" + +msgid "Value must be valid JSON." +msgstr "Uru a ga-abụrịrị JSON n’kwesịrị ekwesị." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(model)s dịka %(field)s %(value)r adịghị adị." + +msgid "Foreign Key (type determined by related field)" +msgstr "Foreign Key (ụdị kpebiri site na mpaghara metụtara)" + +msgid "One-to-one relationship" +msgstr "Mmekọrịta otu-na-otu" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s mmekọrịta" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s mmekọrịta" + +msgid "Many-to-many relationship" +msgstr "Mmekọrịta otutu-na-otutu" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Ebe a kwesiri ekwesi." + +msgid "Enter a whole number." +msgstr "Tinye nọmba onu ogugu." + +msgid "Enter a valid date." +msgstr "Tinye ụbọchị zuru oke." + +msgid "Enter a valid time." +msgstr "Tinye oge zuru oke." + +msgid "Enter a valid date/time." +msgstr "Tinye ụbọchị / oge zuru oke" + +msgid "Enter a valid duration." +msgstr "Tinye oge onuno zuru oke." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Onu ogugu ubochi a gha aburiri n’agbata {min_days} na {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Onweghi faịlụ a debanyere. Lee ụdị encoding a ntinye na ederede." + +msgid "No file was submitted." +msgstr "E nweghị faịlụ e watara" + +msgid "The submitted file is empty." +msgstr "O nweghị ihe dị n'ime faịlụ e wetara" + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Gbaa mbọ hụ na aha faịlụ a nwere kacha %(max)d odide (o nwere %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Biko nyefee faịlụ a ma ọ bụ tinye akara na igbe akara, ọ bụghị ha abụọ." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Bugote foto n’zuru oke. Faịlụ a ị bugoro abụghị foto ma ọ bụ foto rụrụ arụ." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Họrọ ezigbo nhọrọ. %(value)sabụghị otu nhọrọ n'ime nke dịnụ." + +msgid "Enter a list of values." +msgstr "Tinye ndepụta nke ụkpụrụ." + +msgid "Enter a complete value." +msgstr "Tinye uru zuru okè" + +msgid "Enter a valid UUID." +msgstr "Tinye UUID kwesịrị ekwesị" + +msgid "Enter a valid JSON." +msgstr "Tinye JSON kwesịrị ekwesị" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Ebe ezoro ezo%(name)s) %(error)s" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "Data ManagementForm na-efu efu ma ọ bụ a kpara ya aka" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "Biko nyefee %d ma ọ bụ fomụ di ole na ole." + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "Biko nyefee%d ma ọ bụ fomụ karịrị otu ahụ" + +msgid "Order" +msgstr "Usoro" + +msgid "Delete" +msgstr "Hichapụ" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Biko dozie data oji abuo a maka %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Biko dozie data oji abuo a maka %(field)s, nke gha diriri iche." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Biko dozie data oji abuo a maka %(field_name)s nke gha diriri iche maka " +"%(lookup)s n'ime %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Biko dozie uru oji abuo nke no n'okpuru." + +msgid "The inline value did not match the parent instance." +msgstr "Uru inline a adabaghị na parent instance." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Họrọ ezigbo nhọrọ. Nhọrọ a abụghị otu nhọrọ dịnụ." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "%(pk)sabụghi uru kwesịrị ekwesị" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s enweghị ike ịkọwa na mpaghara oge %(current_timezone)s; onwere " +"ike iju anya ma obu ọ gaghị adị." + +msgid "Clear" +msgstr "Kpochapu" + +msgid "Currently" +msgstr "Ugbu a" + +msgid "Change" +msgstr "Gbanwee" + +msgid "Unknown" +msgstr "Ihe N’amaghi" + +msgid "Yes" +msgstr "Ee" + +msgid "No" +msgstr "Mba" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "ee, mba, nwere ike" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d bytes" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "etiti Abalị" + +msgid "noon" +msgstr "Ehihie" + +msgid "Monday" +msgstr "Mọnde" + +msgid "Tuesday" +msgstr "Tiuzdee" + +msgid "Wednesday" +msgstr "Wenezdee" + +msgid "Thursday" +msgstr "Tọọzdee" + +msgid "Friday" +msgstr "Fraịdee" + +msgid "Saturday" +msgstr "Satọdee" + +msgid "Sunday" +msgstr "Mbọsi Uka" + +msgid "Mon" +msgstr "Mọnde" + +msgid "Tue" +msgstr "Tiu" + +msgid "Wed" +msgstr "Wen" + +msgid "Thu" +msgstr "Tọọ" + +msgid "Fri" +msgstr "Fraị" + +msgid "Sat" +msgstr "Sat" + +msgid "Sun" +msgstr "Ụka" + +msgid "January" +msgstr "Jenụwarị" + +msgid "February" +msgstr "Febrụwarị" + +msgid "March" +msgstr "Maachị" + +msgid "April" +msgstr "Eprel" + +msgid "May" +msgstr "Mee" + +msgid "June" +msgstr "Juun" + +msgid "July" +msgstr "Julaị" + +msgid "August" +msgstr "Ọgọọst" + +msgid "September" +msgstr "Septemba" + +msgid "October" +msgstr "Ọktoba" + +msgid "November" +msgstr "Novemba" + +msgid "December" +msgstr "Disemba" + +msgid "jan" +msgstr "jen" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "maa" + +msgid "apr" +msgstr "epr" + +msgid "may" +msgstr "mee" + +msgid "jun" +msgstr "juu" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "ọgọ" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "ọkt" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dis" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Jenụwarị" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Maachị" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Eprel" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Mee" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Juun" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Julaị" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Ọgọ." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Sep." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Ọkt." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dis." + +msgctxt "alt. month" +msgid "January" +msgstr "Jenụwarị" + +msgctxt "alt. month" +msgid "February" +msgstr "Febrụwarị" + +msgctxt "alt. month" +msgid "March" +msgstr "Maachị" + +msgctxt "alt. month" +msgid "April" +msgstr "Eprel" + +msgctxt "alt. month" +msgid "May" +msgstr "Mee" + +msgctxt "alt. month" +msgid "June" +msgstr "Juun" + +msgctxt "alt. month" +msgid "July" +msgstr "Julaị" + +msgctxt "alt. month" +msgid "August" +msgstr "Ọgọọst" + +msgctxt "alt. month" +msgid "September" +msgstr "Septemba" + +msgctxt "alt. month" +msgid "October" +msgstr "Ọktoba" + +msgctxt "alt. month" +msgid "November" +msgstr "Novemba" + +msgctxt "alt. month" +msgid "December" +msgstr "Disemba" + +msgid "This is not a valid IPv6 address." +msgstr "Nke a abaghị adresị IPv6 zuru oke." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "ma obu" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d afọ" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%dọnwa" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d izu" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d ụbọchị" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d awa" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d nkeji" + +msgid "Forbidden" +msgstr "Amachibidoro" + +msgid "CSRF verification failed. Request aborted." +msgstr "Nyocha CSRF emeghị nke ọma. Ajuju atọrọ.." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"I na-ahụ ozi a n'ihi na saịtị HTTPS a chọrọ “Onye isi okwu” ka ihe nchọgharị " +"weebụ gị zitere gị, mana onweghi nke zitere. Achọrọ isi ihe a maka ebumnuche " +"nchekwa, iji jide n’aka na ndị ọzọ anaghị egbochi ihe nchọgharị gị." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Ọ bụrụ na ihazila ihe nchọgharị gị iji gbanyụọ ndị na-eji “ndị nnọchianya”, " +"biko jisie iketiachi ya, ma ọ dịkarịa maka saịtị a, ma ọ bụ maka njikọ " +"HTTPS, ma ọ bụ maka a arịrịọ “otu ụdị”." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Ọ bụrụ na ị na-eji akara " +"mmado ma ọ bụ gụnyere isi nke \"Iwu-Onye na gba ama: neweghị onye na-gba ama" +"\", biko wepu ha. Nchedo CSRF chọrọ ka isi “onye na gba ama” wee mee nyocha " +"ike nlele nke gbara ama. Ọ bụrụ na ihe gbasara gị gbasara nzuzo, jiri ụzọ " +"ọzọ dị ka njikọ maka saịtị ndị ọzọ." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"I na-ahụ ozi a n'ihi na saịtị a chọrọ CSRF cookie mgbe ị na-edobe akwụkwọ. " +"Achọrọ cookie a maka ebumnuche nchekwa, iji hụ na ndị ọzọ anaghị egbochi ihe " +"nchọgharị gị." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Ọ bụrụ na ịhazila ihe nchọgharị gị iji gbanyụọ kuki, biko tiachi ya ka o na " +"ruo oru, opekata mpe maka saịtị a, ma ọ bụ maka “otu ụdị\"." + +msgid "More information is available with DEBUG=True." +msgstr "Ihe omuma ndi ozo di na DEBUG = Eziokwu." + +msgid "No year specified" +msgstr "Ọ dịghị afọ akọwapụtara" + +msgid "Date out of range" +msgstr "Ubọchị a puru na usoro" + +msgid "No month specified" +msgstr "Onweghị ọnwa akọwapụtara" + +msgid "No day specified" +msgstr "Onweghi ụbọchị akọwapụtara" + +msgid "No week specified" +msgstr "Onweghi izu akọwapụtara" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr " %(verbose_name_plural)sadịghị" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Ọdịnihu %(verbose_name_plural)s adịghị adị n'ihi %(class_name)s.allow_future " +"bu ugha." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "String ụbọchị nabaghị uru “%(datestr)s” Ntọala enyere “%(format)s”" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Mba %(verbose_name)s hụrụ ihe dabara na ajụjụ a" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Peeji a a-abụghị “nke ikpeazụ”, a pụghị ịgbanwe ya na int." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Peeji na-abaghị uru (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Tọgbọ chakoo ndepụta na “%(class_name)s.allow_empty” bụ Ugha." + +msgid "Directory indexes are not allowed here." +msgstr "Anaghị anabata directory indexes ebe a." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "“%(path)s” a dịghị" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Index of %(directory)s" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" +"Django: usoro Ntanetị maka ndị na-achọkarị izu okè ya na oge edetu imecha." + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Lee akwukwo e bipụtara maka Django" +"%(version)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Nwụnye ahụ dabara nke ọma! Ị mere nke ọma!" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" +"I na-ahụ peeji a n'ihi na DEBUG=True dị na faili setting gị mana ịhazibeghị URL ọ bụla." + +msgid "Django Documentation" +msgstr "Akwụkwọ Ederede Django" + +msgid "Topics, references, & how-to’s" +msgstr "Isiokwu, ntụaka, & otu esi-mee" + +msgid "Tutorial: A Polling App" +msgstr "Nkuzi: App Ntuli Aka" + +msgid "Get started with Django" +msgstr "Bido na Django" + +msgid "Django Community" +msgstr "Obodo Django" + +msgid "Connect, get help, or contribute" +msgstr "Jikọọ, nweta enyemaka, ma ọ bụ tinye aka." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ig/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ig/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ig/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ig/formats.py new file mode 100644 index 0000000..cb0b4de --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ig/formats.py @@ -0,0 +1,32 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j F Y" +TIME_FORMAT = "P" +DATETIME_FORMAT = "j F Y P" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "d.m.Y" +SHORT_DATETIME_FORMAT = "d.m.Y H:i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d.%m.%Y", # '25.10.2006' + "%d.%m.%y", # '25.10.06' +] +DATETIME_INPUT_FORMATS = [ + "%d.%m.%Y %H:%M:%S", # '25.10.2006 14:30:59' + "%d.%m.%Y %H:%M:%S.%f", # '25.10.2006 14:30:59.000200' + "%d.%m.%Y %H:%M", # '25.10.2006 14:30' + "%d.%m.%Y", # '25.10.2006' + "%d.%m.%y %H:%M:%S", # '25.10.06 14:30:59' + "%d.%m.%y %H:%M:%S.%f", # '25.10.06 14:30:59.000200' + "%d.%m.%y %H:%M", # '25.10.06 14:30' + "%d.%m.%y", # '25.10.06' +] +DECIMAL_SEPARATOR = "." +THOUSAND_SEPARATOR = "," +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/io/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/io/LC_MESSAGES/django.mo new file mode 100644 index 0000000..79b81f4 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/io/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/io/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/io/LC_MESSAGES/django.po new file mode 100644 index 0000000..d14d544 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/io/LC_MESSAGES/django.po @@ -0,0 +1,1231 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Viko Bartero , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Ido (http://www.transifex.com/django/django/language/io/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: io\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Afrikaans" + +msgid "Arabic" +msgstr "العربية" + +msgid "Asturian" +msgstr "" + +msgid "Azerbaijani" +msgstr "Azərbaycanca" + +msgid "Bulgarian" +msgstr "български" + +msgid "Belarusian" +msgstr "беларуская" + +msgid "Bengali" +msgstr "বাংলা" + +msgid "Breton" +msgstr "Brezhoneg" + +msgid "Bosnian" +msgstr "босански" + +msgid "Catalan" +msgstr "Català" + +msgid "Czech" +msgstr "čeština" + +msgid "Welsh" +msgstr "Cymraeg" + +msgid "Danish" +msgstr "dansk" + +msgid "German" +msgstr "Deutsch" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "Ελληνικά" + +msgid "English" +msgstr "English" + +msgid "Australian English" +msgstr "" + +msgid "British English" +msgstr "British English" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Español" + +msgid "Argentinian Spanish" +msgstr "Español de Argentina" + +msgid "Colombian Spanish" +msgstr "" + +msgid "Mexican Spanish" +msgstr "Español de México" + +msgid "Nicaraguan Spanish" +msgstr "Español de Nicaragua" + +msgid "Venezuelan Spanish" +msgstr "Español de Venezuela" + +msgid "Estonian" +msgstr "Eesti" + +msgid "Basque" +msgstr "Euskara" + +msgid "Persian" +msgstr "فارسی" + +msgid "Finnish" +msgstr "Suomi" + +msgid "French" +msgstr "Français" + +msgid "Frisian" +msgstr "Frysk" + +msgid "Irish" +msgstr "Gaeilge" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "Galego" + +msgid "Hebrew" +msgstr "עברית" + +msgid "Hindi" +msgstr "हिन्दी" + +msgid "Croatian" +msgstr "hrvatski" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "Magyar" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Bahasa Indonesia" + +msgid "Ido" +msgstr "" + +msgid "Icelandic" +msgstr "Íslenska" + +msgid "Italian" +msgstr "Italiano" + +msgid "Japanese" +msgstr "日本語" + +msgid "Georgian" +msgstr "ქართული" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "Қазақша" + +msgid "Khmer" +msgstr "Khmer" + +msgid "Kannada" +msgstr "Kannaḍa" + +msgid "Korean" +msgstr "한국어" + +msgid "Luxembourgish" +msgstr "Lëtzebuergesch" + +msgid "Lithuanian" +msgstr "Lietuvių" + +msgid "Latvian" +msgstr "Latviešu" + +msgid "Macedonian" +msgstr "Македонски" + +msgid "Malayalam" +msgstr "മലയാളം" + +msgid "Mongolian" +msgstr "Монгол" + +msgid "Marathi" +msgstr "" + +msgid "Burmese" +msgstr "Burmese" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "नेपाली" + +msgid "Dutch" +msgstr "Nederlands" + +msgid "Norwegian Nynorsk" +msgstr "Norsk nynorsk" + +msgid "Ossetic" +msgstr "Ossetic" + +msgid "Punjabi" +msgstr "ਪੰਜਾਬੀ" + +msgid "Polish" +msgstr "Polski" + +msgid "Portuguese" +msgstr "Português" + +msgid "Brazilian Portuguese" +msgstr "Português do Brasil" + +msgid "Romanian" +msgstr "Română" + +msgid "Russian" +msgstr "Русский" + +msgid "Slovak" +msgstr "Slovenčina" + +msgid "Slovenian" +msgstr "Slovenščina" + +msgid "Albanian" +msgstr "Shqip" + +msgid "Serbian" +msgstr "Српски / srpski" + +msgid "Serbian Latin" +msgstr "Serbian Latin" + +msgid "Swedish" +msgstr "Svenska" + +msgid "Swahili" +msgstr "Kiswahili" + +msgid "Tamil" +msgstr "தமிழ்" + +msgid "Telugu" +msgstr "Telugu" + +msgid "Thai" +msgstr "ไทย" + +msgid "Turkish" +msgstr "Türkçe" + +msgid "Tatar" +msgstr "Tatar" + +msgid "Udmurt" +msgstr "Удмурт" + +msgid "Ukrainian" +msgstr "Українська" + +msgid "Urdu" +msgstr "اُردُو" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "Tiếng Việt" + +msgid "Simplified Chinese" +msgstr "简体中文" + +msgid "Traditional Chinese" +msgstr "繁體中文" + +msgid "Messages" +msgstr "" + +msgid "Site Maps" +msgstr "" + +msgid "Static Files" +msgstr "" + +msgid "Syndication" +msgstr "" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "Skribez valida datumo." + +msgid "Enter a valid URL." +msgstr "Skribez valida URL." + +msgid "Enter a valid integer." +msgstr "" + +msgid "Enter a valid email address." +msgstr "Skribez valida e-posto adreso." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Skribez valida IPv4 adreso." + +msgid "Enter a valid IPv6 address." +msgstr "Skribez valida IPv6 adreso." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Skribez valida adreso IPv4 od IPv6." + +msgid "Enter only digits separated by commas." +msgstr "Skribez nur cifri separata per komi." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Verifikez ke ica datumo esas %(limit_value)s (olu esas %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Verifikez ke ica datumo esas minora kam od egala a %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Verifikez ke ica datumo esas majora kam od egala a %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Verifikez ke ica datumo havas %(limit_value)d litero adminime (olu havas " +"%(show_value)d)." +msgstr[1] "" +"Verifikez ke ica datumo havas %(limit_value)d literi adminime (olu havas " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Verifikez ke ica datumo havas %(limit_value)d litero admaxime (olu havas " +"%(show_value)d)." +msgstr[1] "" +"Verifikez ke ica datumo havas %(limit_value)d literi admaxime (olu havas " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Skribez numero." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "e" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "Ica feldo ne povas esar nula." + +msgid "This field cannot be blank." +msgstr "Ica feldo ne povas esar vakua." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "La %(model_name)s kun ica %(field_label)s ja existas." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Feldo de tipo: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "Booleano (True o False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "String (til %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "Integri separata per komi" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "Dato (sen horo)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Dato (kun horo)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Decimala numero" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "" + +msgid "Email address" +msgstr "E-postala adreso" + +msgid "File path" +msgstr "Arkivo voyo" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "Glitkomo numero" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "Integro" + +msgid "Big (8 byte) integer" +msgstr "Granda (8 byte) integro" + +msgid "IPv4 address" +msgstr "IPv4 adreso" + +msgid "IP address" +msgstr "IP adreso" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "Booleano (True, False o None)" + +msgid "Positive integer" +msgstr "Positiva integro" + +msgid "Positive small integer" +msgstr "Positiva mikra integro" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (til %(max_length)s)" + +msgid "Small integer" +msgstr "Mikra integro" + +msgid "Text" +msgstr "Texto" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Horo" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Kruda binara datumo" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "Arkivo" + +msgid "Image" +msgstr "Imajo" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "Exterklefo (la tipo esas determinata per la relatata feldo)" + +msgid "One-to-one relationship" +msgstr "Un-ad-un parenteso" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "Multi-a-multi parenteso" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr "" + +msgid "This field is required." +msgstr "Ica feldo esas obligata." + +msgid "Enter a whole number." +msgstr "Skribez kompleta numero" + +msgid "Enter a valid date." +msgstr "Skribez valida dato." + +msgid "Enter a valid time." +msgstr "Skribez valida horo." + +msgid "Enter a valid date/time." +msgstr "Skribez valida dato/horo." + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Nula arkivo sendesis. Verifikez la kodexigo tipo en la formulario." + +msgid "No file was submitted." +msgstr "Nula arkivo sendesis." + +msgid "The submitted file is empty." +msgstr "La sendita arkivo esas vakua." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Verifikez ke ica dosiero nomo havas %(max)d skribsigno admaxime (olu havas " +"%(length)d)." +msgstr[1] "" +"Verifikez ke ica arkivo nomo havas %(max)d skribsigni admaxime (olu havas " +"%(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Sendez arkivo o markizez la vakua markbuxo, ne la du." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Kargez valida imajo. La arkivo qua vu kargis ne esis imajo od esis defektiva." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Selektez valida selekto. %(value)s ne esas un de la disponebla selekti." + +msgid "Enter a list of values." +msgstr "Skribez listo de datumi." + +msgid "Enter a complete value." +msgstr "" + +msgid "Enter a valid UUID." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr "" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Okulta feldo %(name)s) %(error)s" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "Ordinar" + +msgid "Delete" +msgstr "Eliminar" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Koretigez duopligata datumi por %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Korektigez la duopligata datumi por %(field)s, qui mustas esar unika." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Korektigez la duopligata datumi por %(field_name)s qui mustas esar unika por " +"la %(lookup)s en %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Korektigez la duopligata datumi infre." + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Selektez valida selekto. Ita selekto ne esas un de la disponebla selekti." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Vakuigar" + +msgid "Currently" +msgstr "Aktuale" + +msgid "Change" +msgstr "Modifikar" + +msgid "Unknown" +msgstr "Nekonocata" + +msgid "Yes" +msgstr "Yes" + +msgid "No" +msgstr "No" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "yes,no,forsan" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d byte" +msgstr[1] "%(size)d bytes" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "noktomezo" + +msgid "noon" +msgstr "dimezo" + +msgid "Monday" +msgstr "Lundio" + +msgid "Tuesday" +msgstr "Mardio" + +msgid "Wednesday" +msgstr "Merkurdio" + +msgid "Thursday" +msgstr "Jovdio" + +msgid "Friday" +msgstr "Venerdio" + +msgid "Saturday" +msgstr "Saturdio" + +msgid "Sunday" +msgstr "Sundio" + +msgid "Mon" +msgstr "Lun" + +msgid "Tue" +msgstr "Mar" + +msgid "Wed" +msgstr "Mer" + +msgid "Thu" +msgstr "Jov" + +msgid "Fri" +msgstr "Ven" + +msgid "Sat" +msgstr "Sat" + +msgid "Sun" +msgstr "Sun" + +msgid "January" +msgstr "Januaro" + +msgid "February" +msgstr "Februaro" + +msgid "March" +msgstr "Marto" + +msgid "April" +msgstr "Aprilo" + +msgid "May" +msgstr "Mayo" + +msgid "June" +msgstr "Junio" + +msgid "July" +msgstr "Julio" + +msgid "August" +msgstr "Agosto" + +msgid "September" +msgstr "Septembro" + +msgid "October" +msgstr "Oktobro" + +msgid "November" +msgstr "Novembro" + +msgid "December" +msgstr "Decembro" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "apr" + +msgid "may" +msgstr "may" + +msgid "jun" +msgstr "jun" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "ago" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "okt" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dec" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Marto" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Aprilo" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Mayo" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Junio" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Julio" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Ago." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Sept." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Okt." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dec." + +msgctxt "alt. month" +msgid "January" +msgstr "Januaro" + +msgctxt "alt. month" +msgid "February" +msgstr "Februaro" + +msgctxt "alt. month" +msgid "March" +msgstr "Marto" + +msgctxt "alt. month" +msgid "April" +msgstr "Aprilo" + +msgctxt "alt. month" +msgid "May" +msgstr "Mayo" + +msgctxt "alt. month" +msgid "June" +msgstr "Junio" + +msgctxt "alt. month" +msgid "July" +msgstr "Julio" + +msgctxt "alt. month" +msgid "August" +msgstr "Agosto" + +msgctxt "alt. month" +msgid "September" +msgstr "Septembro" + +msgctxt "alt. month" +msgid "October" +msgstr "Oktobro" + +msgctxt "alt. month" +msgid "November" +msgstr "Novembro" + +msgctxt "alt. month" +msgid "December" +msgstr "Decembro" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "o" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d yaro" +msgstr[1] "%d yari" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d monato" +msgstr[1] "%d monati" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d semano" +msgstr[1] "%d semani" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d dio" +msgstr[1] "%d dii" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d horo" +msgstr[1] "%d hori" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d minuto" +msgstr[1] "%d minuti" + +msgid "0 minutes" +msgstr "0 minuti" + +msgid "Forbidden" +msgstr "" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "La yaro ne specizigesis" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "La monato ne specizigesis" + +msgid "No day specified" +msgstr "La dio ne specizigesis" + +msgid "No week specified" +msgstr "La semano ne specizigesis" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Ne esas %(verbose_name_plural)s disponebla" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"La futura %(verbose_name_plural)s ne esas disponebla pro ke %(class_name)s." +"allow_future esas False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Onu ne permisas direktorio indexi hike." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Indexi di %(directory)s" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/is/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/is/LC_MESSAGES/django.mo new file mode 100644 index 0000000..951078f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/is/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/is/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/is/LC_MESSAGES/django.po new file mode 100644 index 0000000..be73f3d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/is/LC_MESSAGES/django.po @@ -0,0 +1,1302 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# db999e1e0e51ac90b00482cb5db0f98b_32999f5 <3ec5202d5df408dd2f95d8c361fed970_5926>, 2011 +# Hafsteinn Einarsson , 2011-2012 +# Jannis Leidel , 2011 +# Matt R, 2018 +# saevarom , 2011 +# saevarom , 2013,2015 +# Thordur Sigurdsson , 2016-2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2021-11-18 21:19+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Icelandic (http://www.transifex.com/django/django/language/" +"is/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: is\n" +"Plural-Forms: nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);\n" + +msgid "Afrikaans" +msgstr "Afríkanska" + +msgid "Arabic" +msgstr "Arabíska" + +msgid "Algerian Arabic" +msgstr "" + +msgid "Asturian" +msgstr "Astúríska" + +msgid "Azerbaijani" +msgstr "Aserbaídsjíska" + +msgid "Bulgarian" +msgstr "Búlgarska" + +msgid "Belarusian" +msgstr "Hvítrússneska" + +msgid "Bengali" +msgstr "Bengalska" + +msgid "Breton" +msgstr "Bretónska" + +msgid "Bosnian" +msgstr "Bosníska" + +msgid "Catalan" +msgstr "Katalónska" + +msgid "Czech" +msgstr "Tékkneska" + +msgid "Welsh" +msgstr "Velska" + +msgid "Danish" +msgstr "Danska" + +msgid "German" +msgstr "Þýska" + +msgid "Lower Sorbian" +msgstr "Neðri sorbíska" + +msgid "Greek" +msgstr "Gríska" + +msgid "English" +msgstr "Enska" + +msgid "Australian English" +msgstr "Áströlsk enska" + +msgid "British English" +msgstr "Bresk enska" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Spænska" + +msgid "Argentinian Spanish" +msgstr "Argentínsk spænska" + +msgid "Colombian Spanish" +msgstr "Kólumbísk spænska" + +msgid "Mexican Spanish" +msgstr "Mexíkósk spænska" + +msgid "Nicaraguan Spanish" +msgstr "Níkaragva spænska" + +msgid "Venezuelan Spanish" +msgstr "Venesúelsk spænska" + +msgid "Estonian" +msgstr "Eistneska" + +msgid "Basque" +msgstr "Baskneska" + +msgid "Persian" +msgstr "Persneska" + +msgid "Finnish" +msgstr "Finnska" + +msgid "French" +msgstr "Franska" + +msgid "Frisian" +msgstr "Frísneska" + +msgid "Irish" +msgstr "Írska" + +msgid "Scottish Gaelic" +msgstr "Skosk gelíska" + +msgid "Galician" +msgstr "Galíska" + +msgid "Hebrew" +msgstr "Hebreska" + +msgid "Hindi" +msgstr "Hindí" + +msgid "Croatian" +msgstr "Króatíska" + +msgid "Upper Sorbian" +msgstr "Efri sorbíska" + +msgid "Hungarian" +msgstr "Ungverska" + +msgid "Armenian" +msgstr "Armenska" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indónesíska" + +msgid "Igbo" +msgstr "" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Íslenska" + +msgid "Italian" +msgstr "Ítalska" + +msgid "Japanese" +msgstr "Japanska" + +msgid "Georgian" +msgstr "Georgíska" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "Kasakska" + +msgid "Khmer" +msgstr "Kmeríska" + +msgid "Kannada" +msgstr "Kannadanska" + +msgid "Korean" +msgstr "Kóreska" + +msgid "Kyrgyz" +msgstr "" + +msgid "Luxembourgish" +msgstr "Lúxemborgíska" + +msgid "Lithuanian" +msgstr "Litháenska" + +msgid "Latvian" +msgstr "Lettneska" + +msgid "Macedonian" +msgstr "Makedónska" + +msgid "Malayalam" +msgstr "Malajalamska" + +msgid "Mongolian" +msgstr "Mongólska" + +msgid "Marathi" +msgstr "Maratí" + +msgid "Malay" +msgstr "" + +msgid "Burmese" +msgstr "Búrmíska" + +msgid "Norwegian Bokmål" +msgstr "Norskt bókmál" + +msgid "Nepali" +msgstr "Nepalska" + +msgid "Dutch" +msgstr "Hollenska" + +msgid "Norwegian Nynorsk" +msgstr "Nýnorska" + +msgid "Ossetic" +msgstr "Ossetíska" + +msgid "Punjabi" +msgstr "Púndjabíska" + +msgid "Polish" +msgstr "Pólska" + +msgid "Portuguese" +msgstr "Portúgalska" + +msgid "Brazilian Portuguese" +msgstr "Brasilísk portúgalska" + +msgid "Romanian" +msgstr "Rúmenska" + +msgid "Russian" +msgstr "Rússneska" + +msgid "Slovak" +msgstr "Slóvakíska" + +msgid "Slovenian" +msgstr "Slóvenska" + +msgid "Albanian" +msgstr "Albanska" + +msgid "Serbian" +msgstr "Serbneska" + +msgid "Serbian Latin" +msgstr "Serbnesk latína" + +msgid "Swedish" +msgstr "Sænska" + +msgid "Swahili" +msgstr "Svahílí" + +msgid "Tamil" +msgstr "Tamílska" + +msgid "Telugu" +msgstr "Telúgúska" + +msgid "Tajik" +msgstr "" + +msgid "Thai" +msgstr "Tælenska" + +msgid "Turkmen" +msgstr "" + +msgid "Turkish" +msgstr "Tyrkneska" + +msgid "Tatar" +msgstr "Tataríska" + +msgid "Udmurt" +msgstr "Údmúrt" + +msgid "Ukrainian" +msgstr "Úkraínska" + +msgid "Urdu" +msgstr "Úrdú" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "Víetnamska" + +msgid "Simplified Chinese" +msgstr "Einfölduð kínverska " + +msgid "Traditional Chinese" +msgstr "Hefðbundin kínverska" + +msgid "Messages" +msgstr "Skilaboð" + +msgid "Site Maps" +msgstr "" + +msgid "Static Files" +msgstr "" + +msgid "Syndication" +msgstr "" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Þetta síðunúmer er ekki heiltala" + +msgid "That page number is less than 1" +msgstr "Þetta síðunúmer er minna en 1" + +msgid "That page contains no results" +msgstr "Þessi síða hefur engar niðurstöður" + +msgid "Enter a valid value." +msgstr "Sláðu inn gilt gildi." + +msgid "Enter a valid URL." +msgstr "Sláðu inn gilt veffang (URL)." + +msgid "Enter a valid integer." +msgstr "Sláðu inn gilda heiltölu." + +msgid "Enter a valid email address." +msgstr "Sláðu inn gilt netfang." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Settu inn gildan vefslóðartitil sem samanstendur af latneskum bókstöfum, " +"númerin, undirstrikum og bandstrikum." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Settu inn gildan vefslóðartitil sem má innihalda unicode bókstafi, " +"tölustafi, undirstrik og bandstrik." + +msgid "Enter a valid IPv4 address." +msgstr "Sláðu inn gilda IPv4 tölu." + +msgid "Enter a valid IPv6 address." +msgstr "Sláðu inn gilt IPv6 vistfang." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Sláðu inn gilt IPv4 eða IPv6 vistfang." + +msgid "Enter only digits separated by commas." +msgstr "Skrifaðu einungis tölur aðskildar með kommum." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Gakktu úr skugga um að gildi sé %(limit_value)s (það er %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" +"Gakktu úr skugga um að gildið sé minna en eða jafnt og %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" +"Gakktu úr skugga um að gildið sé stærra en eða jafnt og %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Gildið má minnst vera %(limit_value)d stafur að lengd (það er %(show_value)d " +"nú)" +msgstr[1] "" +"Gildið má minnst vera %(limit_value)d stafir að lengd (það er %(show_value)d " +"nú)" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Gildið má mest vera %(limit_value)d stafur að lengd (það er %(show_value)d " +"nú)" +msgstr[1] "" +"Gildið má mest vera %(limit_value)d stafir að lengd (það er %(show_value)d " +"nú)" + +msgid "Enter a number." +msgstr "Sláðu inn tölu." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Gildið má ekki hafa fleiri en %(max)s tölu." +msgstr[1] "Gildið má ekki hafa fleiri en %(max)s tölur." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Gildið má ekki hafa meira en %(max)s tugatölustaf (decimal places)." +msgstr[1] "" +"Gildið má ekki hafa meira en %(max)s tugatölustafi (decimal places)." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "Gildið má ekki hafa fleiri en %(max)s tölu fyrir tugabrotskil." +msgstr[1] "Gildið má ekki hafa fleiri en %(max)s tölur fyrir tugabrotskil." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Skrár með endingunni „%(extension)s“ eru ekki leyfðar. Leyfilegar endingar " +"eru: „%(allowed_extensions)s“„." + +msgid "Null characters are not allowed." +msgstr "Núlltákn eru ekki leyfileg." + +msgid "and" +msgstr "og" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s með þessi %(field_labels)s er nú þegar til." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Gildið %(value)r er ógilt." + +msgid "This field cannot be null." +msgstr "Þessi reitur getur ekki haft tómgildi (null)." + +msgid "This field cannot be blank." +msgstr "Þessi reitur má ekki vera tómur." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s með þetta %(field_label)s er nú þegar til." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s verður að vera einkvæmt fyrir %(date_field_label)s " +"%(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Reitur af gerð: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "„%(value)s“ verður að vera annaðhvort satt eða ósatt." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "„%(value)s“ verður að vera eitt eftirtalinna: True, False eða None." + +msgid "Boolean (Either True or False)" +msgstr "Boole-gildi (True eða False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Strengur (mest %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "Heiltölur aðgreindar með kommum" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"„%(value)s“ er ógilt dagsetningarsnið. Það verður að vera á sniðinu YYYY-MM-" +"DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "„%(value)s“ hefur rétt snið (YYYY-MM-DD) en dagsetningin er ógild." + +msgid "Date (without time)" +msgstr "Dagsetning (án tíma)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"„%(value)s“ hefur ógilt snið. Það verður að vera á sniðinu: YYYY-MM-DD HH:" +"MM[:ss[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"„%(value)s“ hefur rétt snið (YYYY-MM-DD HH:MM [:ss[.uuuuuu]][TZ]) en það er " +"ógild dagsetning/tími." + +msgid "Date (with time)" +msgstr "Dagsetning (með tíma)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "„%(value)s“ verður að vera heiltala." + +msgid "Decimal number" +msgstr "Tugatala" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"„%(value)s“ er á ógildu sniði. Það verður að vera á sniðinu [DD] " +"[[HH:]MM:]ss[.uuuuuu]." + +msgid "Duration" +msgstr "Tímalengd" + +msgid "Email address" +msgstr "Netfang" + +msgid "File path" +msgstr "Skjalaslóð" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "„%(value)s“ verður að vera fleytitala." + +msgid "Floating point number" +msgstr "Fleytitala (floating point number)" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "Gildi „%(value)s“ verður að vera heiltala." + +msgid "Integer" +msgstr "Heiltala" + +msgid "Big (8 byte) integer" +msgstr "Stór (8 bæta) heiltala" + +msgid "Small integer" +msgstr "Lítil heiltala" + +msgid "IPv4 address" +msgstr "IPv4 vistfang" + +msgid "IP address" +msgstr "IP tala" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "„%(value)s“ verður að vera eitt eftirtalinna: None, True eða False." + +msgid "Boolean (Either True, False or None)" +msgstr "Boole-gildi (True, False eða None)" + +msgid "Positive big integer" +msgstr "Jákvæð stór heiltala" + +msgid "Positive integer" +msgstr "Jákvæð heiltala" + +msgid "Positive small integer" +msgstr "Jákvæð lítil heiltala" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slögg (allt að %(max_length)s)" + +msgid "Text" +msgstr "Texti" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"„%(value)s“ er á ógildu sniði. Það verður að vera á sniðinu HH:MM[:ss[." +"uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"„%(value)s“ er á réttu sniði (HH:MM[:ss[.uuuuuu]]), en það er ógild " +"dagsetning/tími." + +msgid "Time" +msgstr "Tími" + +msgid "URL" +msgstr "Veffang" + +msgid "Raw binary data" +msgstr "Hrá tvíundargögn (binary data)" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "„%(value)s“ er ekki gilt UUID." + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "Skrá" + +msgid "Image" +msgstr "Mynd" + +msgid "A JSON object" +msgstr "JSON hlutur" + +msgid "Value must be valid JSON." +msgstr "Gildi verður að vera gilt JSON." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(model)s hlutur með %(field)s %(value)r er ekki til." + +msgid "Foreign Key (type determined by related field)" +msgstr "Ytri lykill (Gerð ákveðin af skyldum reit)" + +msgid "One-to-one relationship" +msgstr "Einn-á-einn samband." + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s samband" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s sambönd" + +msgid "Many-to-many relationship" +msgstr "Margir-til-margra samband." + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Þennan reit þarf að fylla út." + +msgid "Enter a whole number." +msgstr "Sláðu inn heiltölu." + +msgid "Enter a valid date." +msgstr "Sláðu inn gilda dagsetningu." + +msgid "Enter a valid time." +msgstr "Sláðu inn gilda tímasetningu." + +msgid "Enter a valid date/time." +msgstr "Sláðu inn gilda dagsetningu ásamt tíma." + +msgid "Enter a valid duration." +msgstr "Sláðu inn gilt tímabil." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Fjöldi daga verður að vera á milli {min_days} og {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Engin skrá var send. Athugaðu kótunartegund á forminu (encoding type)." + +msgid "No file was submitted." +msgstr "Engin skrá var send." + +msgid "The submitted file is empty." +msgstr "Innsend skrá er tóm." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Skráarnafnið má mest vera %(max)d stafur að lengd (það er %(length)d nú)" +msgstr[1] "" +"Skráarnafnið má mest vera %(max)d stafir að lengd (það er %(length)d nú)" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Vinsamlegast sendu annað hvort inn skrá eða merktu í boxið, ekki bæði." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Halaðu upp gildri myndskrá. Skráin sem þú halaðir upp var annað hvort gölluð " +"eða ekki mynd." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Veldu gildan valmöguleika. %(value)s er ekki eitt af gildum valmöguleikum." + +msgid "Enter a list of values." +msgstr "Sláðu inn lista af gildum." + +msgid "Enter a complete value." +msgstr "Sláðu inn heilt gildi." + +msgid "Enter a valid UUID." +msgstr "Sláðu inn gilt UUID." + +msgid "Enter a valid JSON." +msgstr "Sláðu inn gilt JSON." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Falinn reitur %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" + +#, python-format +msgid "Please submit at most %d form." +msgid_plural "Please submit at most %d forms." +msgstr[0] "Vinsamlegast sendu ekki meira en %d form." +msgstr[1] "Vinsamlegast sendu ekki meira en %d form." + +#, python-format +msgid "Please submit at least %d form." +msgid_plural "Please submit at least %d forms." +msgstr[0] "Vinsamlegast sendu að minnsta kosta %d form." +msgstr[1] "Vinsamlegast sendu að minnsta kosta %d form." + +msgid "Order" +msgstr "Röð" + +msgid "Delete" +msgstr "Eyða" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Vinsamlegast leiðréttu tvítekin gögn í reit %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Vinsamlegast lagfærðu gögn í reit %(field)s, sem verða að vera einstök." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Vinsamlegast leiðréttu tvítekin gögn í reit %(field_name)s sem verða að vera " +"einstök fyrir %(lookup)s í %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Vinsamlegast lagfærðu tvítöldu gögnin fyrir neðan." + +msgid "The inline value did not match the parent instance." +msgstr "Innra gildið passar ekki við eiganda." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Veldu gildan valmöguleika. Valið virðist ekki vera eitt af gildum " +"valmöguleikum." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "„%(pk)s“ er ekki gilt gildi." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s er ekki hægt að túlka í tímabelti %(current_timezone)s, það " +"getur verið óljóst eða að það er ekki til." + +msgid "Clear" +msgstr "Hreinsa" + +msgid "Currently" +msgstr "Eins og er:" + +msgid "Change" +msgstr "Breyta" + +msgid "Unknown" +msgstr "Óþekkt" + +msgid "Yes" +msgstr "Já" + +msgid "No" +msgstr "Nei" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "já,nei,kannski" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d bæti" +msgstr[1] "%(size)d bæti" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "eftirmiðdegi" + +msgid "a.m." +msgstr "morgun" + +msgid "PM" +msgstr "Eftirmiðdegi" + +msgid "AM" +msgstr "Morgun" + +msgid "midnight" +msgstr "miðnætti" + +msgid "noon" +msgstr "hádegi" + +msgid "Monday" +msgstr "mánudagur" + +msgid "Tuesday" +msgstr "þriðjudagur" + +msgid "Wednesday" +msgstr "miðvikudagur" + +msgid "Thursday" +msgstr "fimmtudagur" + +msgid "Friday" +msgstr "föstudagur" + +msgid "Saturday" +msgstr "laugardagur" + +msgid "Sunday" +msgstr "sunnudagur" + +msgid "Mon" +msgstr "mán" + +msgid "Tue" +msgstr "þri" + +msgid "Wed" +msgstr "mið" + +msgid "Thu" +msgstr "fim" + +msgid "Fri" +msgstr "fös" + +msgid "Sat" +msgstr "lau" + +msgid "Sun" +msgstr "sun" + +msgid "January" +msgstr "janúar" + +msgid "February" +msgstr "febrúar" + +msgid "March" +msgstr "mars" + +msgid "April" +msgstr "apríl" + +msgid "May" +msgstr "maí" + +msgid "June" +msgstr "júní" + +msgid "July" +msgstr "júlí" + +msgid "August" +msgstr "ágúst" + +msgid "September" +msgstr "september" + +msgid "October" +msgstr "október" + +msgid "November" +msgstr "nóvember" + +msgid "December" +msgstr "desember" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "apr" + +msgid "may" +msgstr "maí" + +msgid "jun" +msgstr "jún" + +msgid "jul" +msgstr "júl" + +msgid "aug" +msgstr "ágú" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "okt" + +msgid "nov" +msgstr "nóv" + +msgid "dec" +msgstr "des" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "mars" + +msgctxt "abbrev. month" +msgid "April" +msgstr "apríl" + +msgctxt "abbrev. month" +msgid "May" +msgstr "maí" + +msgctxt "abbrev. month" +msgid "June" +msgstr "júní" + +msgctxt "abbrev. month" +msgid "July" +msgstr "júlí" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "ág." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "sept." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "okt." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "nóv." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "des." + +msgctxt "alt. month" +msgid "January" +msgstr "janúar" + +msgctxt "alt. month" +msgid "February" +msgstr "febrúar" + +msgctxt "alt. month" +msgid "March" +msgstr "mars" + +msgctxt "alt. month" +msgid "April" +msgstr "apríl" + +msgctxt "alt. month" +msgid "May" +msgstr "maí" + +msgctxt "alt. month" +msgid "June" +msgstr "júní" + +msgctxt "alt. month" +msgid "July" +msgstr "júlí" + +msgctxt "alt. month" +msgid "August" +msgstr "ágúst" + +msgctxt "alt. month" +msgid "September" +msgstr "september" + +msgctxt "alt. month" +msgid "October" +msgstr "október" + +msgctxt "alt. month" +msgid "November" +msgstr "nóvember" + +msgctxt "alt. month" +msgid "December" +msgstr "desember" + +msgid "This is not a valid IPv6 address." +msgstr "Þetta er ekki gilt IPv6 vistfang." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "eða" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "" +msgstr[1] "" + +msgid "Forbidden" +msgstr "" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF auðkenning tókst ekki." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Ef þú hefur stillt vafrann þinn til að gera „Referer“ hausa óvirka þarftu að " +"virkja þá aftur. Að minnsta kosti fyrir þetta vefsvæði, eða HTTPS tengingar " +"eða „same-origin“ fyrirspurnir." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Þú ert að fá þessi skilaboð því þetta vefsvæði þarfnast að CSRF kaka (e. " +"cookie) sé send þegar form eru send. Þessi kaka er nauðsynleg af " +"öryggisástæðum til að ganga úr skugga um að utanaðkomandi aðili sé ekki að " +"senda fyrirspurnir úr vafranum þínum." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Ef þú hefur stillt vafrann þinn til að gera kökur óvirkar þarftu að virkja " +"þær aftur. Að minnsta kosti fyrir þetta vefsvæði eða „same-origin“ " +"fyrirspurnir." + +msgid "More information is available with DEBUG=True." +msgstr "Meiri upplýsingar fást með DEBUG=True." + +msgid "No year specified" +msgstr "Ekkert ár tilgreint" + +msgid "Date out of range" +msgstr "Dagsetning utan tímabils" + +msgid "No month specified" +msgstr "Enginn mánuður tilgreindur" + +msgid "No day specified" +msgstr "Enginn dagur tilgreindur" + +msgid "No week specified" +msgstr "Engin vika tilgreind" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Ekkert %(verbose_name_plural)s í boði" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Framtíðar %(verbose_name_plural)s ekki í boði því %(class_name)s." +"allow_future er Ósatt." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Ógilt snið dagsetningar „%(datestr)s“ gefið sniðið „%(format)s“" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Ekkert %(verbose_name)s sem uppfyllir skilyrði" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Þetta er hvorki síðasta síða, né er hægt að breyta í heiltölu." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Ógild síða (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Tómur listi og „%(class_name)s.allow_empty“ er Ósatt." + +msgid "Directory indexes are not allowed here." +msgstr "Möppulistar eru ekki leyfðir hér." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "„%(path)s“ er ekki til" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Innihald %(directory)s " + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" +"Þú sérð þessa síðu vegna þess að þú hefur DEBUG=True í stillingunum þínum og hefur ekki sett upp " +"neinar vefslóðir." + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/is/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/is/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/is/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/is/formats.py new file mode 100644 index 0000000..d0f71cf --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/is/formats.py @@ -0,0 +1,21 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j. F Y" +TIME_FORMAT = "H:i" +# DATETIME_FORMAT = +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j. F" +SHORT_DATE_FORMAT = "j.n.Y" +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/it/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/it/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8b46b26 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/it/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/it/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/it/LC_MESSAGES/django.po new file mode 100644 index 0000000..ac26c5d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/it/LC_MESSAGES/django.po @@ -0,0 +1,1367 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# 0d21a39e384d88c2313b89b5042c04cb, 2017 +# Carlo Miron , 2011 +# Carlo Miron , 2014 +# Carlo Miron , 2018-2019 +# Davide Targa , 2021 +# Denis Darii , 2011 +# Emanuele Di Giacomo, 2021 +# Flavio Curella , 2013,2016 +# Jannis Leidel , 2011 +# Themis Savvidis , 2013 +# Luciano De Falco Alfano, 2016 +# Marco Bonetti, 2014 +# Mirco Grillo , 2018,2020 +# Nicola Larosa , 2013 +# palmux , 2014-2015,2017,2021 +# Paolo Melchiorre , 2022-2023 +# Mattia Procopio , 2015 +# Riccardo Magliocchetti , 2017 +# Stefano Brentegani , 2014-2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-25 06:49+0000\n" +"Last-Translator: Paolo Melchiorre , 2022-2023\n" +"Language-Team: Italian (http://www.transifex.com/django/django/language/" +"it/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: it\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Afrikaans" + +msgid "Arabic" +msgstr "Arabo" + +msgid "Algerian Arabic" +msgstr "Arabo Algerino" + +msgid "Asturian" +msgstr "Asturiano" + +msgid "Azerbaijani" +msgstr "Azero" + +msgid "Bulgarian" +msgstr "Bulgaro" + +msgid "Belarusian" +msgstr "Bielorusso" + +msgid "Bengali" +msgstr "Bengalese" + +msgid "Breton" +msgstr "Bretone" + +msgid "Bosnian" +msgstr "Bosniaco" + +msgid "Catalan" +msgstr "Catalano" + +msgid "Central Kurdish (Sorani)" +msgstr "Curdo centrale (Sorani)" + +msgid "Czech" +msgstr "Ceco" + +msgid "Welsh" +msgstr "Gallese" + +msgid "Danish" +msgstr "Danese" + +msgid "German" +msgstr "Tedesco" + +msgid "Lower Sorbian" +msgstr "Sorabo inferiore" + +msgid "Greek" +msgstr "Greco" + +msgid "English" +msgstr "Inglese" + +msgid "Australian English" +msgstr "Inglese Australiano" + +msgid "British English" +msgstr "Inglese britannico" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Spagnolo" + +msgid "Argentinian Spanish" +msgstr "Spagnolo Argentino" + +msgid "Colombian Spanish" +msgstr "Spagnolo Colombiano" + +msgid "Mexican Spanish" +msgstr "Spagnolo Messicano" + +msgid "Nicaraguan Spanish" +msgstr "Spagnolo Nicaraguense" + +msgid "Venezuelan Spanish" +msgstr "Spagnolo venezuelano" + +msgid "Estonian" +msgstr "Estone" + +msgid "Basque" +msgstr "Basco" + +msgid "Persian" +msgstr "Persiano" + +msgid "Finnish" +msgstr "Finlandese" + +msgid "French" +msgstr "Francese" + +msgid "Frisian" +msgstr "Frisone" + +msgid "Irish" +msgstr "Irlandese" + +msgid "Scottish Gaelic" +msgstr "Gaelico Scozzese" + +msgid "Galician" +msgstr "Galiziano" + +msgid "Hebrew" +msgstr "Ebraico" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Croato" + +msgid "Upper Sorbian" +msgstr "Sorabo superiore" + +msgid "Hungarian" +msgstr "Ungherese" + +msgid "Armenian" +msgstr "Armeno" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonesiano" + +msgid "Igbo" +msgstr "Igbo" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Islandese" + +msgid "Italian" +msgstr "Italiano" + +msgid "Japanese" +msgstr "Giapponese" + +msgid "Georgian" +msgstr "Georgiano" + +msgid "Kabyle" +msgstr "Cabilo" + +msgid "Kazakh" +msgstr "Kazako" + +msgid "Khmer" +msgstr "Khmer" + +msgid "Kannada" +msgstr "Kannada" + +msgid "Korean" +msgstr "Coreano" + +msgid "Kyrgyz" +msgstr "Kirghiso" + +msgid "Luxembourgish" +msgstr "Lussemburghese" + +msgid "Lithuanian" +msgstr "Lituano" + +msgid "Latvian" +msgstr "Lettone" + +msgid "Macedonian" +msgstr "Macedone" + +msgid "Malayalam" +msgstr "Malayalam" + +msgid "Mongolian" +msgstr "Mongolo" + +msgid "Marathi" +msgstr "Marathi" + +msgid "Malay" +msgstr "Malese" + +msgid "Burmese" +msgstr "Birmano" + +msgid "Norwegian Bokmål" +msgstr "Norvegese Bokmål" + +msgid "Nepali" +msgstr "Nepali" + +msgid "Dutch" +msgstr "Olandese" + +msgid "Norwegian Nynorsk" +msgstr "Norvegese Nynorsk" + +msgid "Ossetic" +msgstr "Ossetico" + +msgid "Punjabi" +msgstr "Punjabi" + +msgid "Polish" +msgstr "Polacco" + +msgid "Portuguese" +msgstr "Portoghese" + +msgid "Brazilian Portuguese" +msgstr "Brasiliano Portoghese" + +msgid "Romanian" +msgstr "Rumeno" + +msgid "Russian" +msgstr "Russo" + +msgid "Slovak" +msgstr "Slovacco" + +msgid "Slovenian" +msgstr "Sloveno" + +msgid "Albanian" +msgstr "Albanese" + +msgid "Serbian" +msgstr "Serbo" + +msgid "Serbian Latin" +msgstr "Serbo Latino" + +msgid "Swedish" +msgstr "Svedese" + +msgid "Swahili" +msgstr "Swahili" + +msgid "Tamil" +msgstr "Tamil" + +msgid "Telugu" +msgstr "Telugu" + +msgid "Tajik" +msgstr "Tajik" + +msgid "Thai" +msgstr "Tailandese" + +msgid "Turkmen" +msgstr "Turkmeno" + +msgid "Turkish" +msgstr "Turco" + +msgid "Tatar" +msgstr "Tatar" + +msgid "Udmurt" +msgstr "Udmurt" + +msgid "Ukrainian" +msgstr "Ucraino" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "Uzbeko" + +msgid "Vietnamese" +msgstr "Vietnamita" + +msgid "Simplified Chinese" +msgstr "Cinese semplificato" + +msgid "Traditional Chinese" +msgstr "Cinese tradizionale" + +msgid "Messages" +msgstr "Messaggi" + +msgid "Site Maps" +msgstr "Mappa del sito" + +msgid "Static Files" +msgstr "File statici" + +msgid "Syndication" +msgstr "Aggregazione" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "..." + +msgid "That page number is not an integer" +msgstr "Quel numero di pagina non è un integer" + +msgid "That page number is less than 1" +msgstr "Quel numero di pagina è minore di 1" + +msgid "That page contains no results" +msgstr "Quella pagina non presenta alcun risultato" + +msgid "Enter a valid value." +msgstr "Inserisci un valore valido." + +msgid "Enter a valid URL." +msgstr "Inserisci un URL valido." + +msgid "Enter a valid integer." +msgstr "Inserire un numero intero valido." + +msgid "Enter a valid email address." +msgstr "Inserisci un indirizzo email valido." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Inserisci uno \"slug\" valido contenente lettere, cifre, sottolineati o " +"trattini." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Inserisci uno 'slug' valido contenente lettere, cifre, sottolineati o " +"trattini." + +msgid "Enter a valid IPv4 address." +msgstr "Inserisci un indirizzo IPv4 valido." + +msgid "Enter a valid IPv6 address." +msgstr "Inserisci un indirizzo IPv6 valido." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Inserisci un indirizzo IPv4 o IPv6 valido." + +msgid "Enter only digits separated by commas." +msgstr "Inserisci solo cifre separate da virgole." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Assicurati che questo valore sia %(limit_value)s (ora è %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Assicurati che questo valore sia minore o uguale a %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Assicurati che questo valore sia maggiore o uguale a %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" +"Assicurarsi che questo valore sia un multiplo della dimensione di passo " +"%(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Assicurati che questo valore contenga almeno %(limit_value)d carattere (ne " +"ha %(show_value)d)." +msgstr[1] "" +"Assicurati che questo valore contenga almeno %(limit_value)d caratteri (ne " +"ha %(show_value)d)." +msgstr[2] "" +"Assicurati che questo valore contenga almeno %(limit_value)d caratteri (ne " +"ha %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Assicurati che questo valore non contenga più di %(limit_value)d carattere " +"(ne ha %(show_value)d)." +msgstr[1] "" +"Assicurati che questo valore non contenga più di %(limit_value)d caratteri " +"(ne ha %(show_value)d)." +msgstr[2] "" +"Assicurati che questo valore non contenga più di %(limit_value)d caratteri " +"(ne ha %(show_value)d)." + +msgid "Enter a number." +msgstr "Inserisci un numero." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Assicurati che non vi sia più di %(max)s cifra in totale." +msgstr[1] "Assicurati che non vi siano più di %(max)s cifre in totale." +msgstr[2] "Assicurati che non vi siano più di %(max)s cifre in totale." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Assicurati che non vi sia più di %(max)s cifra decimale." +msgstr[1] "Assicurati che non vi siano più di %(max)s cifre decimali." +msgstr[2] "Assicurati che non vi siano più di %(max)s cifre decimali." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "Assicurati che non vi sia più di %(max)s cifra prima della virgola." +msgstr[1] "" +"Assicurati che non vi siano più di %(max)s cifre prima della virgola." +msgstr[2] "" +"Assicurati che non vi siano più di %(max)s cifre prima della virgola." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Il file con estensione \"%(extension)s\" non e' permesso. Le estensioni " +"permesse sono: %(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "I caratteri null non sono ammessi." + +msgid "and" +msgstr "e" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s con questa %(field_labels)s esiste già." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Il vincolo “%(name)s” è stato violato." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Il valore %(value)r non è una scelta valida." + +msgid "This field cannot be null." +msgstr "Questo campo non può essere nullo." + +msgid "This field cannot be blank." +msgstr "Questo campo non può essere vuoto." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s con questo %(field_label)s esiste già." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s deve essere unico per %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Campo di tipo: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "Il valore \"%(value)s\" deve essere True oppure False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "Il valore di \"%(value)s\" deve essere True, False o None" + +msgid "Boolean (Either True or False)" +msgstr "Booleano (Vero o Falso)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Stringa (fino a %(max_length)s)" + +msgid "String (unlimited)" +msgstr "Stringa (illimitata)" + +msgid "Comma-separated integers" +msgstr "Interi separati da virgole" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"Il valore \"%(value)s\" ha un formato di data non valido. Deve essere nel " +"formato AAAA-MM-GG." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"Il valore di \"%(value)s\" ha il corretto formato (AAAA-MM-GG) ma non è una " +"data valida." + +msgid "Date (without time)" +msgstr "Data (senza ora)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"Il valore \"%(value)s\" ha un formato non valido. Deve essere nel formato " +"AAAA-MM-GG HH:MM[:ss[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"Il valore di \"%(value)s\" ha il formato corretto (AAAA-MM-GG HH:MM[:ss[." +"uuuuuu]][TZ]) ma non è una data/ora valida." + +msgid "Date (with time)" +msgstr "Data (con ora)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "Il valore \"%(value)s\" deve essere un numero decimale." + +msgid "Decimal number" +msgstr "Numero decimale" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"Il valore \"%(value)s\" ha un formato non valido. Deve essere nel formato " +"[GG] [[HH:]MM:]ss[.uuuuuu]." + +msgid "Duration" +msgstr "Durata" + +msgid "Email address" +msgstr "Indirizzo email" + +msgid "File path" +msgstr "Percorso file" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "Il valore di \"%(value)s\" deve essere un numero a virgola mobile." + +msgid "Floating point number" +msgstr "Numero in virgola mobile" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "Il valore \"%(value)s\" deve essere un intero." + +msgid "Integer" +msgstr "Intero" + +msgid "Big (8 byte) integer" +msgstr "Intero grande (8 byte)" + +msgid "Small integer" +msgstr "Piccolo intero" + +msgid "IPv4 address" +msgstr "Indirizzo IPv4" + +msgid "IP address" +msgstr "Indirizzo IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "Il valore \"%(value)s\" deve essere None, True oppure False." + +msgid "Boolean (Either True, False or None)" +msgstr "Booleano (True, False o None)" + +msgid "Positive big integer" +msgstr "Intero positivo" + +msgid "Positive integer" +msgstr "Intero positivo" + +msgid "Positive small integer" +msgstr "Piccolo intero positivo" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (fino a %(max_length)s)" + +msgid "Text" +msgstr "Testo" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"Il valore di \"%(value)s\" ha un formato non valido. Deve essere nel formato " +"HH:MM[:ss[.uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"Il valore di \"%(value)s\" ha il corretto formato (HH:MM[:ss[.uuuuuu]]) ma " +"non è un orario valido." + +msgid "Time" +msgstr "Ora" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Dati binari grezzi" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "\"%(value)s\" non è uno UUID valido." + +msgid "Universally unique identifier" +msgstr "Identificatore univoco universale" + +msgid "File" +msgstr "File" + +msgid "Image" +msgstr "Immagine" + +msgid "A JSON object" +msgstr "Un oggetto JSON" + +msgid "Value must be valid JSON." +msgstr "Il valore deve essere un JSON valido." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "L'istanza del modello %(model)s con %(field)s %(value)r non esiste." + +msgid "Foreign Key (type determined by related field)" +msgstr "Foreign Key (tipo determinato dal campo collegato)" + +msgid "One-to-one relationship" +msgstr "Relazione uno a uno" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "relazione %(from)s-%(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "relazioni %(from)s-%(to)s" + +msgid "Many-to-many relationship" +msgstr "Relazione molti a molti" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Questo campo è obbligatorio." + +msgid "Enter a whole number." +msgstr "Inserisci un numero intero." + +msgid "Enter a valid date." +msgstr "Inserisci una data valida." + +msgid "Enter a valid time." +msgstr "Inserisci un'ora valida." + +msgid "Enter a valid date/time." +msgstr "Inserisci una data/ora valida." + +msgid "Enter a valid duration." +msgstr "Inserisci una durata valida." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Il numero di giorni deve essere compreso tra {min_days} e {max_days}" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Non è stato inviato alcun file. Verifica il tipo di codifica sul form." + +msgid "No file was submitted." +msgstr "Nessun file è stato inviato." + +msgid "The submitted file is empty." +msgstr "Il file inviato è vuoto." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Assicurati che questo nome di file non contenga più di %(max)d carattere (ne " +"ha %(length)d)." +msgstr[1] "" +"Assicurati che questo nome di file non contenga più di %(max)d caratteri (ne " +"ha %(length)d)." +msgstr[2] "" +"Assicurati che questo nome di file non contenga più di %(max)d caratteri (ne " +"ha %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"È possibile inviare un file o selezionare la casella \"svuota\", ma non " +"entrambi." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Carica un'immagine valida. Il file caricato non è un'immagine o è " +"un'immagine danneggiata." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Scegli un'opzione valida. %(value)s non è tra quelle disponibili." + +msgid "Enter a list of values." +msgstr "Inserisci una lista di valori." + +msgid "Enter a complete value." +msgstr "Inserisci un valore completo." + +msgid "Enter a valid UUID." +msgstr "Inserire un UUID valido." + +msgid "Enter a valid JSON." +msgstr "Inserisci un JSON valido." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Campo nascosto %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"Mancano i dati ManagementForm o sono stati manomessi. Campi mancanti: " +"%(field_names)s. Potrebbe essere necessario inviare una segnalazione di " +"errore se il problema persiste." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Si prega di inviare al massimo %(num)d form." +msgstr[1] "Si prega di inviare al massimo %(num)d form." +msgstr[2] "Si prega di inviare al massimo %(num)d form." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Si prega di inviare almeno %(num)d form." +msgstr[1] "Si prega di inviare almeno %(num)d form." +msgstr[2] "Si prega di inviare almeno %(num)d form." + +msgid "Order" +msgstr "Ordine" + +msgid "Delete" +msgstr "Cancella" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Si prega di correggere i dati duplicati di %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Si prega di correggere i dati duplicati di %(field)s, che deve essere unico." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Si prega di correggere i dati duplicati di %(field_name)s che deve essere " +"unico/a per %(lookup)s in %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Si prega di correggere i dati duplicati qui sotto." + +msgid "The inline value did not match the parent instance." +msgstr "Il valore inline non corrisponde all'istanza padre." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Scegli un'opzione valida. La scelta effettuata non compare tra quelle " +"disponibili." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "\"%(pk)s\" non è un valore valido." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +" %(datetime)s non può essere interpretato nel fuso orario " +"%(current_timezone)s: potrebbe essere ambiguo o non esistere." + +msgid "Clear" +msgstr "Svuota" + +msgid "Currently" +msgstr "Attualmente" + +msgid "Change" +msgstr "Cambia" + +msgid "Unknown" +msgstr "Sconosciuto" + +msgid "Yes" +msgstr "Sì" + +msgid "No" +msgstr "No" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "sì,no,forse" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d byte" +msgstr[1] "%(size)d bytes" +msgstr[2] "%(size)d bytes" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "mezzanotte" + +msgid "noon" +msgstr "mezzogiorno" + +msgid "Monday" +msgstr "Lunedì" + +msgid "Tuesday" +msgstr "Martedì" + +msgid "Wednesday" +msgstr "Mercoledì" + +msgid "Thursday" +msgstr "Giovedì" + +msgid "Friday" +msgstr "Venerdì" + +msgid "Saturday" +msgstr "Sabato" + +msgid "Sunday" +msgstr "Domenica" + +msgid "Mon" +msgstr "Lun" + +msgid "Tue" +msgstr "Mar" + +msgid "Wed" +msgstr "Mer" + +msgid "Thu" +msgstr "Gio" + +msgid "Fri" +msgstr "Ven" + +msgid "Sat" +msgstr "Sab" + +msgid "Sun" +msgstr "Dom" + +msgid "January" +msgstr "Gennaio" + +msgid "February" +msgstr "Febbraio" + +msgid "March" +msgstr "Marzo" + +msgid "April" +msgstr "Aprile" + +msgid "May" +msgstr "Maggio" + +msgid "June" +msgstr "Giugno" + +msgid "July" +msgstr "Luglio" + +msgid "August" +msgstr "Agosto" + +msgid "September" +msgstr "Settembre" + +msgid "October" +msgstr "Ottobre" + +msgid "November" +msgstr "Novembre" + +msgid "December" +msgstr "Dicembre" + +msgid "jan" +msgstr "gen" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "apr" + +msgid "may" +msgstr "mag" + +msgid "jun" +msgstr "giu" + +msgid "jul" +msgstr "lug" + +msgid "aug" +msgstr "ago" + +msgid "sep" +msgstr "set" + +msgid "oct" +msgstr "ott" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dic" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Gen." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Marzo" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Aprile" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Maggio" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Giugno" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Luglio" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Ago." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Set." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Ott." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dic." + +msgctxt "alt. month" +msgid "January" +msgstr "Gennaio" + +msgctxt "alt. month" +msgid "February" +msgstr "Febbraio" + +msgctxt "alt. month" +msgid "March" +msgstr "Marzo" + +msgctxt "alt. month" +msgid "April" +msgstr "Aprile" + +msgctxt "alt. month" +msgid "May" +msgstr "Maggio" + +msgctxt "alt. month" +msgid "June" +msgstr "Giugno" + +msgctxt "alt. month" +msgid "July" +msgstr "Luglio" + +msgctxt "alt. month" +msgid "August" +msgstr "Agosto" + +msgctxt "alt. month" +msgid "September" +msgstr "Settembre" + +msgctxt "alt. month" +msgid "October" +msgstr "Ottobre" + +msgctxt "alt. month" +msgid "November" +msgstr "Novembre" + +msgctxt "alt. month" +msgid "December" +msgstr "Dicembre" + +msgid "This is not a valid IPv6 address." +msgstr "Questo non è un indirizzo IPv6 valido." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "o" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d anno" +msgstr[1] "%(num)d anni" +msgstr[2] "%(num)d anni" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mese" +msgstr[1] "%(num)d mesi" +msgstr[2] "%(num)d mesi" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d settimana" +msgstr[1] "%(num)d settimane" +msgstr[2] "%(num)d settimane" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d giorno" +msgstr[1] "%(num)d giorni" +msgstr[2] "%(num)d giorni" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d ora" +msgstr[1] "%(num)d ore" +msgstr[2] "%(num)d ore" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuto" +msgstr[1] "%(num)d minuti" +msgstr[2] "%(num)d minuti" + +msgid "Forbidden" +msgstr "Proibito" + +msgid "CSRF verification failed. Request aborted." +msgstr "Verifica CSRF fallita. Richiesta interrotta." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Vedi questo messaggio perchè questo sito HTTPS richiede l'invio da parte del " +"tuo browser del “Referer header”, che non è invece stato inviato. Questo " +"header è richiesto per motivi di sicurezza, per assicurare che il tuo " +"browser non sia stato sabotato da terzi." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Se hai configurato il tuo browser web per disattivare l'invio delle " +"intestazioni \"Referer\", riattiva questo invio, almeno per questo sito, o " +"per le connessioni HTTPS, o per le connessioni \"same-origin\"." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Se usi il tag o includi " +"header 'Referrer-Policy: no-referrer', per favore rimuovili. Per la " +"protezione CSRF è necessario eseguire un controllo rigoroso sull'header " +"'Referer'. Se ti preoccupano le ricadute sulla privacy, puoi ricorrere ad " +"alternative come per i link a siti di terze parti." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Stai vedendo questo messaggio perché questo sito richiede un cookie CSRF " +"quando invii dei form. Questo cookie è necessario per ragioni di sicurezza, " +"per assicurare che il tuo browser non sia stato dirottato da terze parti." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Se hai configurato il tuo browser web per disattivare l'invio dei cookies, " +"riattivalo almeno per questo sito, o per connessioni \"same-origin\"" + +msgid "More information is available with DEBUG=True." +msgstr "Maggiorni informazioni sono disponibili con DEBUG=True" + +msgid "No year specified" +msgstr "Anno non specificato" + +msgid "Date out of range" +msgstr "Data al di fuori dell'intervallo" + +msgid "No month specified" +msgstr "Mese non specificato" + +msgid "No day specified" +msgstr "Giorno non specificato" + +msgid "No week specified" +msgstr "Settimana non specificata" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Nessun %(verbose_name_plural)s disponibile" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"%(verbose_name_plural)s futuri/e non disponibili/e poichè %(class_name)s." +"allow_future è False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Data non valida \"%(datestr)s\" con il formato \"%(format)s\"" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Trovato nessun %(verbose_name)s corrispondente alla query" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "La pagina non è \"last\", né può essere convertita in un int." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Pagina non valida (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Lista vuota e \"%(class_name)s.allow_empty\" è False." + +msgid "Directory indexes are not allowed here." +msgstr "Indici di directory non sono consentiti qui." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "\"%(path)s\" non esiste" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Indice di %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Installazione completata con successo! Congratulazioni!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Leggi le note di rilascio per Django " +"%(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Stai vedendo questa pagina perché hai impostato DEBUG=True nel tuo file di configurazione e non hai " +"configurato nessun URL." + +msgid "Django Documentation" +msgstr "Documentazione di Django" + +msgid "Topics, references, & how-to’s" +msgstr "Temi, riferimenti, & guide" + +msgid "Tutorial: A Polling App" +msgstr "Tutorial: un'app per sondaggi" + +msgid "Get started with Django" +msgstr "Iniziare con Django" + +msgid "Django Community" +msgstr "La Community di Django" + +msgid "Connect, get help, or contribute" +msgstr "Connettiti, chiedi aiuto, o contribuisci." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/it/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/it/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/it/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/it/formats.py new file mode 100644 index 0000000..bb9e027 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/it/formats.py @@ -0,0 +1,43 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "d F Y" # 25 Ottobre 2006 +TIME_FORMAT = "H:i" # 14:30 +DATETIME_FORMAT = "l d F Y H:i" # Mercoledì 25 Ottobre 2006 14:30 +YEAR_MONTH_FORMAT = "F Y" # Ottobre 2006 +MONTH_DAY_FORMAT = "j F" # 25 Ottobre +SHORT_DATE_FORMAT = "d/m/Y" # 25/12/2009 +SHORT_DATETIME_FORMAT = "d/m/Y H:i" # 25/10/2009 14:30 +FIRST_DAY_OF_WEEK = 1 # Lunedì + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d/%m/%Y", # '25/10/2006' + "%Y/%m/%d", # '2006/10/25' + "%d-%m-%Y", # '25-10-2006' + "%Y-%m-%d", # '2006-10-25' + "%d-%m-%y", # '25-10-06' + "%d/%m/%y", # '25/10/06' +] +DATETIME_INPUT_FORMATS = [ + "%d/%m/%Y %H:%M:%S", # '25/10/2006 14:30:59' + "%d/%m/%Y %H:%M:%S.%f", # '25/10/2006 14:30:59.000200' + "%d/%m/%Y %H:%M", # '25/10/2006 14:30' + "%d/%m/%y %H:%M:%S", # '25/10/06 14:30:59' + "%d/%m/%y %H:%M:%S.%f", # '25/10/06 14:30:59.000200' + "%d/%m/%y %H:%M", # '25/10/06 14:30' + "%Y-%m-%d %H:%M:%S", # '2006-10-25 14:30:59' + "%Y-%m-%d %H:%M:%S.%f", # '2006-10-25 14:30:59.000200' + "%Y-%m-%d %H:%M", # '2006-10-25 14:30' + "%d-%m-%Y %H:%M:%S", # '25-10-2006 14:30:59' + "%d-%m-%Y %H:%M:%S.%f", # '25-10-2006 14:30:59.000200' + "%d-%m-%Y %H:%M", # '25-10-2006 14:30' + "%d-%m-%y %H:%M:%S", # '25-10-06 14:30:59' + "%d-%m-%y %H:%M:%S.%f", # '25-10-06 14:30:59.000200' + "%d-%m-%y %H:%M", # '25-10-06 14:30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ja/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ja/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d7f0f76 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ja/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ja/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ja/LC_MESSAGES/django.po new file mode 100644 index 0000000..591cdf3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ja/LC_MESSAGES/django.po @@ -0,0 +1,1323 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# xiu1 , 2016 +# tadasu , 2020 +# Goto Hayato , 2021 +# Goto Hayato , 2019 +# Hiroki Sawano, 2022 +# Jannis Leidel , 2011 +# Kamiyama Satoshi, 2021 +# Kentaro Matsuzaki , 2015 +# Masashi SHIBATA , 2017 +# Nikita K , 2019 +# Shinichi Katsumata , 2019 +# Shinya Okano , 2012-2019,2021,2023 +# Taichi Taniguchi, 2022 +# Takuro Onoue , 2020 +# Takuya N , 2020 +# Tetsuya Morimoto , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Shinya Okano , 2012-2019,2021,2023\n" +"Language-Team: Japanese (http://app.transifex.com/django/django/language/" +"ja/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ja\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Afrikaans" +msgstr "アフリカーンス語" + +msgid "Arabic" +msgstr "アラビア語" + +msgid "Algerian Arabic" +msgstr "アラビア語(アルジェリア)" + +msgid "Asturian" +msgstr "アストゥリアス語" + +msgid "Azerbaijani" +msgstr "アゼルバイジャン語" + +msgid "Bulgarian" +msgstr "ブルガリア語" + +msgid "Belarusian" +msgstr "ベラルーシ語" + +msgid "Bengali" +msgstr "ベンガル語" + +msgid "Breton" +msgstr "ブルトン語" + +msgid "Bosnian" +msgstr "ボスニア語" + +msgid "Catalan" +msgstr "カタロニア語" + +msgid "Central Kurdish (Sorani)" +msgstr "中央クルド語 (ソラニー語)" + +msgid "Czech" +msgstr "チェコ語" + +msgid "Welsh" +msgstr "ウェールズ語" + +msgid "Danish" +msgstr "デンマーク語" + +msgid "German" +msgstr "ドイツ語" + +msgid "Lower Sorbian" +msgstr "低地ソルブ語" + +msgid "Greek" +msgstr "ギリシャ語" + +msgid "English" +msgstr "英語(米国)" + +msgid "Australian English" +msgstr "英語(オーストラリア)" + +msgid "British English" +msgstr "英語(英国)" + +msgid "Esperanto" +msgstr "エスペラント語" + +msgid "Spanish" +msgstr "スペイン語" + +msgid "Argentinian Spanish" +msgstr "アルゼンチンスペイン語" + +msgid "Colombian Spanish" +msgstr "コロンビアスペイン語" + +msgid "Mexican Spanish" +msgstr "メキシコスペイン語" + +msgid "Nicaraguan Spanish" +msgstr "ニカラグアスペイン語" + +msgid "Venezuelan Spanish" +msgstr "ベネズエラスペイン語" + +msgid "Estonian" +msgstr "エストニア語" + +msgid "Basque" +msgstr "バスク語" + +msgid "Persian" +msgstr "ペルシア語" + +msgid "Finnish" +msgstr "フィンランド語" + +msgid "French" +msgstr "フランス語" + +msgid "Frisian" +msgstr "フリジア語" + +msgid "Irish" +msgstr "アイルランド語" + +msgid "Scottish Gaelic" +msgstr "ゲール語(スコットランド)" + +msgid "Galician" +msgstr "ガリシア語" + +msgid "Hebrew" +msgstr "ヘブライ語" + +msgid "Hindi" +msgstr "ヒンディー語" + +msgid "Croatian" +msgstr "クロアチア語" + +msgid "Upper Sorbian" +msgstr "高地ソルブ語" + +msgid "Hungarian" +msgstr "ハンガリー語" + +msgid "Armenian" +msgstr "アルメニア" + +msgid "Interlingua" +msgstr "インターリングア" + +msgid "Indonesian" +msgstr "インドネシア語" + +msgid "Igbo" +msgstr "イグボ語" + +msgid "Ido" +msgstr "イド語" + +msgid "Icelandic" +msgstr "アイスランド語" + +msgid "Italian" +msgstr "イタリア語" + +msgid "Japanese" +msgstr "日本語" + +msgid "Georgian" +msgstr "グルジア語" + +msgid "Kabyle" +msgstr "カビル語" + +msgid "Kazakh" +msgstr "カザフ語" + +msgid "Khmer" +msgstr "クメール語" + +msgid "Kannada" +msgstr "カンナダ語" + +msgid "Korean" +msgstr "韓国語" + +msgid "Kyrgyz" +msgstr "キルギス語" + +msgid "Luxembourgish" +msgstr "ルクセンブルグ語" + +msgid "Lithuanian" +msgstr "リトアニア語" + +msgid "Latvian" +msgstr "ラトビア語" + +msgid "Macedonian" +msgstr "マケドニア語" + +msgid "Malayalam" +msgstr "マラヤーラム語" + +msgid "Mongolian" +msgstr "モンゴル語" + +msgid "Marathi" +msgstr "マラーティー語" + +msgid "Malay" +msgstr "マレー語" + +msgid "Burmese" +msgstr "ビルマ語" + +msgid "Norwegian Bokmål" +msgstr "ノルウェーのブークモール" + +msgid "Nepali" +msgstr "ネパール語" + +msgid "Dutch" +msgstr "オランダ語" + +msgid "Norwegian Nynorsk" +msgstr "ノルウェーのニーノシュク" + +msgid "Ossetic" +msgstr "オセット語" + +msgid "Punjabi" +msgstr "パンジャブ語" + +msgid "Polish" +msgstr "ポーランド語" + +msgid "Portuguese" +msgstr "ポルトガル語" + +msgid "Brazilian Portuguese" +msgstr "ブラジルポルトガル語" + +msgid "Romanian" +msgstr "ルーマニア語" + +msgid "Russian" +msgstr "ロシア語" + +msgid "Slovak" +msgstr "スロバキア語" + +msgid "Slovenian" +msgstr "スロヴェニア語" + +msgid "Albanian" +msgstr "アルバニア語" + +msgid "Serbian" +msgstr "セルビア語" + +msgid "Serbian Latin" +msgstr "セルビア語ラテン文字" + +msgid "Swedish" +msgstr "スウェーデン語" + +msgid "Swahili" +msgstr "スワヒリ語" + +msgid "Tamil" +msgstr "タミル語" + +msgid "Telugu" +msgstr "テルグ語" + +msgid "Tajik" +msgstr "タジク語" + +msgid "Thai" +msgstr "タイ語" + +msgid "Turkmen" +msgstr "トルクメン語" + +msgid "Turkish" +msgstr "トルコ語" + +msgid "Tatar" +msgstr "タタール語" + +msgid "Udmurt" +msgstr "ウドムルト語" + +msgid "Uyghur" +msgstr "ウイグル語" + +msgid "Ukrainian" +msgstr "ウクライナ語" + +msgid "Urdu" +msgstr "ウルドゥー語" + +msgid "Uzbek" +msgstr "ウズベク語" + +msgid "Vietnamese" +msgstr "ベトナム語" + +msgid "Simplified Chinese" +msgstr "簡体字中国語" + +msgid "Traditional Chinese" +msgstr "繁体字中国語" + +msgid "Messages" +msgstr "メッセージ" + +msgid "Site Maps" +msgstr "サイトマップ" + +msgid "Static Files" +msgstr "静的ファイル" + +msgid "Syndication" +msgstr "シンジケーション" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "このページ番号は整数ではありません。" + +msgid "That page number is less than 1" +msgstr "ページ番号が 1 よりも小さいです。" + +msgid "That page contains no results" +msgstr "このページには結果が含まれていません。" + +msgid "Enter a valid value." +msgstr "値を正しく入力してください。" + +msgid "Enter a valid URL." +msgstr "URLを正しく入力してください。" + +msgid "Enter a valid integer." +msgstr "整数を正しく入力してください。" + +msgid "Enter a valid email address." +msgstr "有効なメールアドレスを入力してください。" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"“slug” には半角の英数字、アンダースコア、ハイフン以外は使用できません。" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"ユニコード文字、数字、アンダースコアまたはハイフンで構成された、有効なスラグ" +"を入力してください。" + +msgid "Enter a valid IPv4 address." +msgstr "有効なIPアドレス (IPv4) を入力してください。" + +msgid "Enter a valid IPv6 address." +msgstr "IPv6の正しいアドレスを入力してください。" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "IPv4またはIPv6の正しいアドレスを入力してください。" + +msgid "Enter only digits separated by commas." +msgstr "カンマ区切りの数字だけを入力してください。" + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"この値は %(limit_value)s でなければなりません(実際には %(show_value)s でし" +"た) 。" + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "この値は %(limit_value)s 以下でなければなりません。" + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "この値は %(limit_value)s 以上でなければなりません。" + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "この値は %(limit_value)s の倍数でなければなりません。" + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"この値は%(offset)s から始まる %(limit_value)s の倍数でなければなりません。" +"例. %(offset)s%(valid_value1)s%(valid_value2)s など。" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"この値が少なくとも %(limit_value)d 文字以上であることを確認してください " +"(%(show_value)d 文字になっています)。" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"この値は %(limit_value)d 文字以下でなければなりません( %(show_value)d 文字に" +"なっています)。" + +msgid "Enter a number." +msgstr "数値を入力してください。" + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "この値は合計 %(max)s 桁以内でなければなりません。" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "この値は小数点以下が合計 %(max)s 桁以内でなければなりません。" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "この値は小数点より前が合計 %(max)s 桁以内でなければなりません。" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"ファイル拡張子 “%(extension)s” は許可されていません。許可されている拡張子は " +"%(allowed_extensions)s です。" + +msgid "Null characters are not allowed." +msgstr "何か文字を入力してください。" + +msgid "and" +msgstr "と" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "この %(field_labels)s を持った %(model_name)s が既に存在します。" + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "制約 “%(name)s” に違反しています。" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "%(value)r は有効な選択肢ではありません。" + +msgid "This field cannot be null." +msgstr "このフィールドには NULL を指定できません。" + +msgid "This field cannot be blank." +msgstr "このフィールドは空ではいけません。" + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "この %(field_label)s を持った %(model_name)s が既に存在します。" + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(date_field_label)s %(lookup_type)s では %(field_label)s がユニークである必" +"要があります。" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "タイプが %(field_type)s のフィールド" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "“%(value)s” は True または False にしなければなりません。" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "“%(value)s” は True 、 False または None の値でなければなりません。" + +msgid "Boolean (Either True or False)" +msgstr "ブール値 (真: True または偽: False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "文字列 ( %(max_length)s 字まで )" + +msgid "String (unlimited)" +msgstr "文字列 (無制限)" + +msgid "Comma-separated integers" +msgstr "カンマ区切りの整数" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"“%(value)s” は無効な日付形式です。YYYY-MM-DD 形式にしなければなりません。" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "“%(value)s” は有効な日付形式(YYYY-MM-DD)ですが、不正な日付です。" + +msgid "Date (without time)" +msgstr "日付" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"“%(value)s” は無効な形式の値です。 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] 形式で" +"なければなりません。" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"“%(value)s” は正しい形式 (YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) の値ですが、無" +"効な日時です。" + +msgid "Date (with time)" +msgstr "日時" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "“%(value)s” は10進浮動小数値にしなければなりません。" + +msgid "Decimal number" +msgstr "10 進数 (小数可)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"“%(value)s” は無効な形式の値です。 [DD] [HH:[MM:]]ss[.uuuuuu] 形式でなければ" +"なりません。" + +msgid "Duration" +msgstr "時間差分" + +msgid "Email address" +msgstr "メールアドレス" + +msgid "File path" +msgstr "ファイルの場所" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "“%(value)s” は小数値にしなければなりません。" + +msgid "Floating point number" +msgstr "浮動小数点" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "“%(value)s” は整数値にしなければなりません。" + +msgid "Integer" +msgstr "整数" + +msgid "Big (8 byte) integer" +msgstr "大きな(8バイト)整数" + +msgid "Small integer" +msgstr "小さな整数" + +msgid "IPv4 address" +msgstr "IPv4アドレス" + +msgid "IP address" +msgstr "IP アドレス" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "“%(value)s” は None、True または False の値でなければなりません。" + +msgid "Boolean (Either True, False or None)" +msgstr "ブール値 (真: True 、偽: False または None)" + +msgid "Positive big integer" +msgstr "正の多倍長整数" + +msgid "Positive integer" +msgstr "正の整数" + +msgid "Positive small integer" +msgstr "小さな正の整数" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "スラグ(%(max_length)s文字以内)" + +msgid "Text" +msgstr "テキスト" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"“%(value)s” は無効な形式の値です。 HH:MM[:ss[.uuuuuu]] 形式でなければなりませ" +"ん。" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "“%(value)s” は正しい形式(HH:MM[:ss[.uuuuuu]])ですが、無効な時刻です。" + +msgid "Time" +msgstr "時刻" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "生のバイナリデータ" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "“%(value)s” は有効なUUIDではありません。" + +msgid "Universally unique identifier" +msgstr "汎用一意識別子" + +msgid "File" +msgstr "ファイル" + +msgid "Image" +msgstr "画像" + +msgid "A JSON object" +msgstr "JSONオブジェクト" + +msgid "Value must be valid JSON." +msgstr "JSONとして正しい値にしてください。" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(field)s が %(value)r である %(model)s のインスタンスは存在しません。" + +msgid "Foreign Key (type determined by related field)" +msgstr "外部キー(型は関連フィールドによって決まります)" + +msgid "One-to-one relationship" +msgstr "1対1の関連" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s の関連" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s の関連" + +msgid "Many-to-many relationship" +msgstr "多対多の関連" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "このフィールドは必須です。" + +msgid "Enter a whole number." +msgstr "整数を入力してください。" + +msgid "Enter a valid date." +msgstr "日付を正しく入力してください。" + +msgid "Enter a valid time." +msgstr "時間を正しく入力してください。" + +msgid "Enter a valid date/time." +msgstr "日時を正しく入力してください。" + +msgid "Enter a valid duration." +msgstr "時間差分を正しく入力してください。" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "日数は{min_days}から{max_days}の間でなければなりません。" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" +"ファイルが取得できませんでした。フォームのencoding typeを確認してください。" + +msgid "No file was submitted." +msgstr "ファイルが送信されていません。" + +msgid "The submitted file is empty." +msgstr "入力されたファイルは空です。" + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"このファイル名は %(max)d 文字以下でなければなりません( %(length)d 文字になっ" +"ています)。" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"ファイルを投稿するか、クリアチェックボックスをチェックするかどちらかを選択し" +"てください。両方とも行ってはいけません。" + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"画像をアップロードしてください。アップロードしたファイルは画像でないか、また" +"は壊れています。" + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "正しく選択してください。 %(value)s は候補にありません。" + +msgid "Enter a list of values." +msgstr "リストを入力してください。" + +msgid "Enter a complete value." +msgstr "すべての値を入力してください。" + +msgid "Enter a valid UUID." +msgstr "UUIDを正しく入力してください。" + +msgid "Enter a valid JSON." +msgstr "JSONを正しく入力してください。" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(隠しフィールド %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"ManagementForm のデータが不足しているか改竄されています。不足するフィールドの" +"数: %(field_names)s 。問題が続くようならバグレポートを出す必要があるかもしれ" +"ません。" + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "最大で %(num)d 個のフォームを送信してください。" + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "少なくとも %(num)d 個のフォームを送信してください。" + +msgid "Order" +msgstr "並び変え" + +msgid "Delete" +msgstr "削除" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "%(field)s の重複したデータを修正してください。" + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"%(field)s の重複したデータを修正してください。このフィールドはユニークである" +"必要があります。" + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"%(field_name)s の重複したデータを修正してください。%(date_field)s %(lookup)s " +"では %(field_name)s がユニークである必要があります。" + +msgid "Please correct the duplicate values below." +msgstr "下記の重複したデータを修正してください。" + +msgid "The inline value did not match the parent instance." +msgstr "インライン値が親のインスタンスに一致しません。" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "正しく選択してください。選択したものは候補にありません。" + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "“%(pk)s” は無効な値です。" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s は %(current_timezone)s のタイムゾーンでは解釈できませんでした。" +"それは曖昧であるか、存在しない可能性があります。" + +msgid "Clear" +msgstr "クリア" + +msgid "Currently" +msgstr "現在" + +msgid "Change" +msgstr "変更" + +msgid "Unknown" +msgstr "不明" + +msgid "Yes" +msgstr "はい" + +msgid "No" +msgstr "いいえ" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "はい,いいえ,たぶん" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d バイト" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "0時" + +msgid "noon" +msgstr "12時" + +msgid "Monday" +msgstr "月曜日" + +msgid "Tuesday" +msgstr "火曜日" + +msgid "Wednesday" +msgstr "水曜日" + +msgid "Thursday" +msgstr "木曜日" + +msgid "Friday" +msgstr "金曜日" + +msgid "Saturday" +msgstr "土曜日" + +msgid "Sunday" +msgstr "日曜日" + +msgid "Mon" +msgstr "月" + +msgid "Tue" +msgstr "火" + +msgid "Wed" +msgstr "水" + +msgid "Thu" +msgstr "木" + +msgid "Fri" +msgstr "金" + +msgid "Sat" +msgstr "土" + +msgid "Sun" +msgstr "日" + +msgid "January" +msgstr "1月" + +msgid "February" +msgstr "2月" + +msgid "March" +msgstr "3月" + +msgid "April" +msgstr "4月" + +msgid "May" +msgstr "5月" + +msgid "June" +msgstr "6月" + +msgid "July" +msgstr "7月" + +msgid "August" +msgstr "8月" + +msgid "September" +msgstr "9月" + +msgid "October" +msgstr "10月" + +msgid "November" +msgstr "11月" + +msgid "December" +msgstr "12月" + +msgid "jan" +msgstr "1月" + +msgid "feb" +msgstr "2月" + +msgid "mar" +msgstr "3月" + +msgid "apr" +msgstr "4月" + +msgid "may" +msgstr "5月" + +msgid "jun" +msgstr "6月" + +msgid "jul" +msgstr "7月" + +msgid "aug" +msgstr "8月" + +msgid "sep" +msgstr "9月" + +msgid "oct" +msgstr "10月" + +msgid "nov" +msgstr "11月" + +msgid "dec" +msgstr "12月" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "1月" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "2月" + +msgctxt "abbrev. month" +msgid "March" +msgstr "3月" + +msgctxt "abbrev. month" +msgid "April" +msgstr "4月" + +msgctxt "abbrev. month" +msgid "May" +msgstr "5月" + +msgctxt "abbrev. month" +msgid "June" +msgstr "6月" + +msgctxt "abbrev. month" +msgid "July" +msgstr "7月" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "8月" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "9月" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "10月" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "11月" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "12月" + +msgctxt "alt. month" +msgid "January" +msgstr "1月" + +msgctxt "alt. month" +msgid "February" +msgstr "2月" + +msgctxt "alt. month" +msgid "March" +msgstr "3月" + +msgctxt "alt. month" +msgid "April" +msgstr "4月" + +msgctxt "alt. month" +msgid "May" +msgstr "5月" + +msgctxt "alt. month" +msgid "June" +msgstr "6月" + +msgctxt "alt. month" +msgid "July" +msgstr "7月" + +msgctxt "alt. month" +msgid "August" +msgstr "8月" + +msgctxt "alt. month" +msgid "September" +msgstr "9月" + +msgctxt "alt. month" +msgid "October" +msgstr "10月" + +msgctxt "alt. month" +msgid "November" +msgstr "11月" + +msgctxt "alt. month" +msgid "December" +msgstr "12月" + +msgid "This is not a valid IPv6 address." +msgstr "これは有効なIPv6アドレスではありません。" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "または" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d年" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)dヶ月" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d週間" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d日" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d時間" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d分" + +msgid "Forbidden" +msgstr "アクセス禁止" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF検証に失敗したため、リクエストは中断されました。" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"このメッセージが表示されている理由は、このHTTPSのサイトはウェブブラウザからリ" +"ファラーヘッダが送信されることを必須としていますが、送信されなかったためで" +"す。このヘッダはセキュリティ上の理由(使用中のブラウザが第三者によってハイ" +"ジャックされていないことを確認するため)で必要です。" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"もしブラウザのリファラーヘッダを無効に設定しているならば、HTTPS接続やsame-" +"originリクエストのために、少なくともこのサイトでは再度有効にしてください。" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"もし タグを使用しているか " +"“Referrer-Policy: no-referrer” ヘッダを含んでいる場合は削除してください。" +"CSRF プロテクションは、厳密に “Referer” ヘッダが必要です。プライバシーが気に" +"なる場合は などの代替で第三者サイトと接続してくださ" +"い。" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"このメッセージが表示されている理由は、このサイトはフォーム送信時にCSRFクッ" +"キーを必須としているためです。このクッキーはセキュリティ上の理由(使用中のブラ" +"ウザが第三者によってハイジャックされていないことを確認するため)で必要です。" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"もしブラウザのクッキーを無効に設定しているならば、same-originリクエストのため" +"に少なくともこのサイトでは再度有効にしてください。" + +msgid "More information is available with DEBUG=True." +msgstr "詳細な情報は DEBUG=True を設定すると利用できます。" + +msgid "No year specified" +msgstr "年が未指定です" + +msgid "Date out of range" +msgstr "日付が有効範囲外です" + +msgid "No month specified" +msgstr "月が未指定です" + +msgid "No day specified" +msgstr "日が未指定です" + +msgid "No week specified" +msgstr "週が未指定です" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "%(verbose_name_plural)s は利用できません" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"%(class_name)s.allow_futureがFalseであるため、未来の%(verbose_name_plural)sは" +"利用できません。" + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "指定された形式 “%(format)s” では “%(datestr)s” は無効な日付文字列です" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "クエリーに一致する %(verbose_name)s は見つかりませんでした" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "ページが 「最後」ではないか、数値に変換できる値ではありません。" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "無効なページです (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "空の一覧かつ “%(class_name)s.allow_empty” が False です。" + +msgid "Directory indexes are not allowed here." +msgstr "ここではディレクトリインデックスが許可されていません。" + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "“%(path)s” が存在しません" + +#, python-format +msgid "Index of %(directory)s" +msgstr "%(directory)sのディレクトリインデックス" + +msgid "The install worked successfully! Congratulations!" +msgstr "インストールは成功しました!おめでとうございます!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Django%(version)sのリリースノートを見る。" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"このページは、設定ファイルでDEBUG=Trueが指定され、何もURLが設定されていない時に表示" +"されます。" + +msgid "Django Documentation" +msgstr "Django ドキュメント" + +msgid "Topics, references, & how-to’s" +msgstr "トピック、リファレンス、ハウツー" + +msgid "Tutorial: A Polling App" +msgstr "チュートリアル: 投票アプリケーション" + +msgid "Get started with Django" +msgstr "Djangoを始めよう" + +msgid "Django Community" +msgstr "Djangoのコミュニティ" + +msgid "Connect, get help, or contribute" +msgstr "つながり、助け合い、貢献しよう" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ja/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ja/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ja/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ja/formats.py new file mode 100644 index 0000000..c0554d9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ja/formats.py @@ -0,0 +1,21 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "Y年n月j日" +TIME_FORMAT = "G:i" +DATETIME_FORMAT = "Y年n月j日G:i" +YEAR_MONTH_FORMAT = "Y年n月" +MONTH_DAY_FORMAT = "n月j日" +SHORT_DATE_FORMAT = "Y/m/d" +SHORT_DATETIME_FORMAT = "Y/m/d G:i" +# FIRST_DAY_OF_WEEK = + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = "." +THOUSAND_SEPARATOR = "," +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ka/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ka/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7cdc3c5 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ka/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ka/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ka/LC_MESSAGES/django.po new file mode 100644 index 0000000..1f342b9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ka/LC_MESSAGES/django.po @@ -0,0 +1,1239 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# André Bouatchidzé , 2013-2015 +# David A. , 2019 +# David A. , 2011 +# Jannis Leidel , 2011 +# Tornike Beradze , 2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Georgian (http://www.transifex.com/django/django/language/" +"ka/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ka\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +msgid "Afrikaans" +msgstr "აფრიკაანსი" + +msgid "Arabic" +msgstr "არაბული" + +msgid "Asturian" +msgstr "ასტურიული" + +msgid "Azerbaijani" +msgstr "აზერბაიჯანული" + +msgid "Bulgarian" +msgstr "ბულგარული" + +msgid "Belarusian" +msgstr "ბელარუსული" + +msgid "Bengali" +msgstr "ბენგალიური" + +msgid "Breton" +msgstr "ბრეტონული" + +msgid "Bosnian" +msgstr "ბოსნიური" + +msgid "Catalan" +msgstr "კატალანური" + +msgid "Czech" +msgstr "ჩეხური" + +msgid "Welsh" +msgstr "უელსური" + +msgid "Danish" +msgstr "დანიური" + +msgid "German" +msgstr "გერმანული" + +msgid "Lower Sorbian" +msgstr "ქვემო სორბული" + +msgid "Greek" +msgstr "ბერძნული" + +msgid "English" +msgstr "ინგლისური" + +msgid "Australian English" +msgstr "ავსტრალიური ინგლისური" + +msgid "British English" +msgstr "ბრიტანეთის ინგლისური" + +msgid "Esperanto" +msgstr "ესპერანტო" + +msgid "Spanish" +msgstr "ესპანური" + +msgid "Argentinian Spanish" +msgstr "არგენტინის ესპანური" + +msgid "Colombian Spanish" +msgstr "კოლუმბიური ესპანური" + +msgid "Mexican Spanish" +msgstr "მექსიკური ესპანური" + +msgid "Nicaraguan Spanish" +msgstr "ნიკარაგუული ესპანური" + +msgid "Venezuelan Spanish" +msgstr "ვენესუელის ესპანური" + +msgid "Estonian" +msgstr "ესტონური" + +msgid "Basque" +msgstr "ბასკური" + +msgid "Persian" +msgstr "სპარსული" + +msgid "Finnish" +msgstr "ფინური" + +msgid "French" +msgstr "ფრანგული" + +msgid "Frisian" +msgstr "ფრისიული" + +msgid "Irish" +msgstr "ირლანდიური" + +msgid "Scottish Gaelic" +msgstr "შოტლანდიური-გელური" + +msgid "Galician" +msgstr "გალიციური" + +msgid "Hebrew" +msgstr "ებრაული" + +msgid "Hindi" +msgstr "ჰინდი" + +msgid "Croatian" +msgstr "ხორვატიული" + +msgid "Upper Sorbian" +msgstr "ზემო სორბიული" + +msgid "Hungarian" +msgstr "უნგრული" + +msgid "Armenian" +msgstr "სომხური" + +msgid "Interlingua" +msgstr "ინტერლინგუა" + +msgid "Indonesian" +msgstr "ინდონეზიური" + +msgid "Ido" +msgstr "იდო" + +msgid "Icelandic" +msgstr "ისლანდიური" + +msgid "Italian" +msgstr "იტალიური" + +msgid "Japanese" +msgstr "იაპონური" + +msgid "Georgian" +msgstr "ქართული" + +msgid "Kabyle" +msgstr "კაბილური" + +msgid "Kazakh" +msgstr "ყაზახური" + +msgid "Khmer" +msgstr "ხმერული" + +msgid "Kannada" +msgstr "კანნადა" + +msgid "Korean" +msgstr "კორეული" + +msgid "Luxembourgish" +msgstr "ლუქსემბურგული" + +msgid "Lithuanian" +msgstr "ლიტვური" + +msgid "Latvian" +msgstr "ლატვიური" + +msgid "Macedonian" +msgstr "მაკედონიური" + +msgid "Malayalam" +msgstr "მალაიზიური" + +msgid "Mongolian" +msgstr "მონღოლური" + +msgid "Marathi" +msgstr "მარათული" + +msgid "Burmese" +msgstr "ბირმული" + +msgid "Norwegian Bokmål" +msgstr "ნორვეგიული Bokmål" + +msgid "Nepali" +msgstr "ნეპალური" + +msgid "Dutch" +msgstr "ჰოლანდიური" + +msgid "Norwegian Nynorsk" +msgstr "ნორვეგიული-ნინორსკი" + +msgid "Ossetic" +msgstr "ოსური" + +msgid "Punjabi" +msgstr "პუნჯაბი" + +msgid "Polish" +msgstr "პოლონური" + +msgid "Portuguese" +msgstr "პორტუგალიური" + +msgid "Brazilian Portuguese" +msgstr "ბრაზილიური პორტუგალიური" + +msgid "Romanian" +msgstr "რუმინული" + +msgid "Russian" +msgstr "რუსული" + +msgid "Slovak" +msgstr "სლოვაკური" + +msgid "Slovenian" +msgstr "სლოვენიური" + +msgid "Albanian" +msgstr "ალბანური" + +msgid "Serbian" +msgstr "სერბული" + +msgid "Serbian Latin" +msgstr "სერბული (ლათინური)" + +msgid "Swedish" +msgstr "შვედური" + +msgid "Swahili" +msgstr "სუაჰილი" + +msgid "Tamil" +msgstr "თამილური" + +msgid "Telugu" +msgstr "ტელუგუ" + +msgid "Thai" +msgstr "ტაი" + +msgid "Turkish" +msgstr "თურქული" + +msgid "Tatar" +msgstr "თათრული" + +msgid "Udmurt" +msgstr "უდმურტული" + +msgid "Ukrainian" +msgstr "უკრაინული" + +msgid "Urdu" +msgstr "ურდუ" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "ვიეტნამური" + +msgid "Simplified Chinese" +msgstr "გამარტივებული ჩინური" + +msgid "Traditional Chinese" +msgstr "ტრადიციული ჩინური" + +msgid "Messages" +msgstr "შეტყობინებები" + +msgid "Site Maps" +msgstr "საიტის რუკები" + +msgid "Static Files" +msgstr "სტატიკური ფაილები" + +msgid "Syndication" +msgstr "სინდიკაცია" + +msgid "That page number is not an integer" +msgstr "გვერდის ნომერი არ არის მთელი რიცხვი" + +msgid "That page number is less than 1" +msgstr "გვერდის ნომერი ნაკლებია 1-ზე" + +msgid "That page contains no results" +msgstr "გვერდი არ შეიცავს მონაცემებს" + +msgid "Enter a valid value." +msgstr "შეიყვანეთ სწორი მნიშვნელობა." + +msgid "Enter a valid URL." +msgstr "შეიყვანეთ სწორი URL." + +msgid "Enter a valid integer." +msgstr "შეიყვანეთ სწორი მთელი რიცხვი." + +msgid "Enter a valid email address." +msgstr "შეიყვანეთ მართებული ელფოსტის მისამართი." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "შეიყვანეთ სწორი IPv4 მისამართი." + +msgid "Enter a valid IPv6 address." +msgstr "შეიყვანეთ მართებული IPv6 მისამართი." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "შეიყვანეთ მართებული IPv4 ან IPv6 მისამართი." + +msgid "Enter only digits separated by commas." +msgstr "შეიყვანეთ მხოლოდ მძიმეებით გამოყოფილი ციფრები." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "მნიშვნელობა უნდა იყოს %(limit_value)s (იგი არის %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "მნიშვნელობა უნდა იყოს %(limit_value)s-ზე ნაკლები ან ტოლი." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "მნიშვნელობა უნდა იყოს %(limit_value)s-ზე მეტი ან ტოლი." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"მნიშვნელობას უნდა ჰქონდეს სულ ცოტა %(limit_value)d სიმბოლო (მას აქვს " +"%(show_value)d)." +msgstr[1] "" +"მნიშვნელობას უნდა ჰქონდეს სულ ცოტა %(limit_value)d სიმბოლო (მას აქვს " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"მნიშვნელობას უნდა ჰქონდეს არაუმეტეს %(limit_value)d სიმბოლოსი (მას აქვს " +"%(show_value)d)." +msgstr[1] "" +"მნიშვნელობას უნდა ჰქონდეს არაუმეტეს %(limit_value)d სიმბოლოსი (მას აქვს " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "შეიყვანეთ რიცხვი." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "ციფრების სრული რაოდენობა %(max)s-ს არ უნდა აღემატებოდეს." +msgstr[1] "ციფრების სრული რაოდენობა %(max)s-ს არ უნდა აღემატებოდეს." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +"ათობითი გამყოფის შემდეგ ციფრების რაოდენობა %(max)s-ს არ უნდა აღემატებოდეს." +msgstr[1] "" +"ათობითი გამყოფის შემდეგ ციფრების რაოდენობა %(max)s-ს არ უნდა აღემატებოდეს." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"ათობითი გამყოფის შემდეგ ციფრების რაოდენობა %(max)s-ს არ უნდა აღემატებოდეს." +msgstr[1] "" +"ათობითი გამყოფის წინ ციფრების რაოდენობა %(max)s-ს არ უნდა აღემატებოდეს." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "Null მნიშვნელობები დაუშვებელია." + +msgid "and" +msgstr "და" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s ამ %(field_labels)s-ით უკვე არსებობს." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "მნიშვნელობა %(value)r არ არის დასაშვები." + +msgid "This field cannot be null." +msgstr "ეს ველი არ შეიძლება იყოს null." + +msgid "This field cannot be blank." +msgstr "ეს ველი არ შეიძლება იყოს ცარიელი." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s მოცემული %(field_label)s-ით უკვე არსებობს." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s უნდა იყოს უნიკალური %(date_field_label)s %(lookup_type)s-" +"სთვის." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "ველის ტიპი: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "ლოგიკური (True ან False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "სტრიქონი (%(max_length)s სიმბოლომდე)" + +msgid "Comma-separated integers" +msgstr "მძიმით გამოყოფილი მთელი რიცხვები" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "თარიღი (დროის გარეშე)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "თარიღი (დროსთან ერთად)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "ათობითი რიცხვი" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "ხანგრზლივობა" + +msgid "Email address" +msgstr "ელ. ფოსტის მისამართი" + +msgid "File path" +msgstr "გზა ფაილისაკენ" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "რიცხვი მცოცავი წერტილით" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "მთელი" + +msgid "Big (8 byte) integer" +msgstr "დიდი მთელი (8-ბაიტიანი)" + +msgid "IPv4 address" +msgstr "IPv4 მისამართი" + +msgid "IP address" +msgstr "IP-მისამართი" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "ლოგიკური (True, False ან None)" + +msgid "Positive integer" +msgstr "დადებითი მთელი რიცხვი" + +msgid "Positive small integer" +msgstr "დადებითი პატარა მთელი რიცხვი" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "სლაგი (%(max_length)s-მდე)" + +msgid "Small integer" +msgstr "პატარა მთელი რიცხვი" + +msgid "Text" +msgstr "ტექსტი" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "დრო" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "დაუმუშავებელი ორობითი მონაცემები" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "უნივერსალური უნიკალური იდენტიფიკატორი." + +msgid "File" +msgstr "ფაილი" + +msgid "Image" +msgstr "გამოსახულება" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "გარე გასაღები (ტიპი განისაზღვრება დაკავშირებული ველის ტიპით)" + +msgid "One-to-one relationship" +msgstr "კავშირი ერთი-ერთტან" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "კავშირი მრავალი-მრავალთან" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr "" + +msgid "This field is required." +msgstr "ეს ველი აუცილებელია." + +msgid "Enter a whole number." +msgstr "შეიყვანეთ მთელი რიცხვი" + +msgid "Enter a valid date." +msgstr "შეიყვანეთ სწორი თარიღი." + +msgid "Enter a valid time." +msgstr "შეიყვანეთ სწორი დრო." + +msgid "Enter a valid date/time." +msgstr "შეიყვანეთ სწორი თარიღი და დრო." + +msgid "Enter a valid duration." +msgstr "შეიყვანეთ სწორი დროის პერიოდი." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" +"ფაილი არ იყო გამოგზავნილი. შეამოწმეთ კოდირების ტიპი მოცემული ფორმისათვის." + +msgid "No file was submitted." +msgstr "ფაილი არ იყო გამოგზავნილი." + +msgid "The submitted file is empty." +msgstr "გამოგზავნილი ფაილი ცარიელია." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "ან გამოგზავნეთ ფაილი, ან მონიშნეთ \"წაშლის\" დროშა." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"ატვირთეთ დასაშვები გამოსახულება. თქვენს მიერ გამოგზავნილი ფაილი ან არ არის " +"გამოსახულება, ან დაზიანებულია." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "აირჩიეთ დასაშვები მნიშვნელობა. %(value)s დასაშვები არ არის." + +msgid "Enter a list of values." +msgstr "შეიყვანეთ მნიშვნელობების სია." + +msgid "Enter a complete value." +msgstr "შეიყვანეთ სრული მნიშვნელობა." + +msgid "Enter a valid UUID." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr "" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(დამალული ველი %(name)s) %(error)s" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "დალაგება" + +msgid "Delete" +msgstr "წავშალოთ" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "გთხოვთ, შეასწოროთ დუბლირებული მონაცემები %(field)s-თვის." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"გთხოვთ, შეასწოროთ დუბლირებული მნიშვნელობა %(field)s ველისთვის, რომელიც უნდა " +"იყოს უნიკალური." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"გთხოვთ, შეასწოროთ დუბლირებული მნიშვნელობა %(field_name)s ველისთვის, რომელიც " +"უნდა იყოს უნიკალური %(lookup)s-ზე, %(date_field)s-თვის." + +msgid "Please correct the duplicate values below." +msgstr "გთხოვთ, შეასწოროთ დუბლირებული მნიშვნელობები." + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "აირჩიეთ დასაშვები მნიშვნელობა. ეს არჩევანი დასაშვები არ არის." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "წაშლა" + +msgid "Currently" +msgstr "ამჟამად" + +msgid "Change" +msgstr "შეცვლა" + +msgid "Unknown" +msgstr "გაურკვეველი" + +msgid "Yes" +msgstr "კი" + +msgid "No" +msgstr "არა" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "კი,არა,შესაძლოა" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d ბაიტი" +msgstr[1] "%(size)d ბაიტი" + +#, python-format +msgid "%s KB" +msgstr "%s კბ" + +#, python-format +msgid "%s MB" +msgstr "%s მბ" + +#, python-format +msgid "%s GB" +msgstr "%s გბ" + +#, python-format +msgid "%s TB" +msgstr "%s ტბ" + +#, python-format +msgid "%s PB" +msgstr "%s პბ" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "შუაღამე" + +msgid "noon" +msgstr "შუადღე" + +msgid "Monday" +msgstr "ორშაბათი" + +msgid "Tuesday" +msgstr "სამშაბათი" + +msgid "Wednesday" +msgstr "ოთხშაბათი" + +msgid "Thursday" +msgstr "ხუთშაბათი" + +msgid "Friday" +msgstr "პარასკევი" + +msgid "Saturday" +msgstr "შაბათი" + +msgid "Sunday" +msgstr "კვირა" + +msgid "Mon" +msgstr "ორშ" + +msgid "Tue" +msgstr "სამ" + +msgid "Wed" +msgstr "ოთხ" + +msgid "Thu" +msgstr "ხუთ" + +msgid "Fri" +msgstr "პარ" + +msgid "Sat" +msgstr "შაბ" + +msgid "Sun" +msgstr "კვრ" + +msgid "January" +msgstr "იანვარი" + +msgid "February" +msgstr "თებერვალი" + +msgid "March" +msgstr "მარტი" + +msgid "April" +msgstr "აპრილი" + +msgid "May" +msgstr "მაისი" + +msgid "June" +msgstr "ივნისი" + +msgid "July" +msgstr "ივლისი" + +msgid "August" +msgstr "აგვისტო" + +msgid "September" +msgstr "სექტემბერი" + +msgid "October" +msgstr "ოქტომბერი" + +msgid "November" +msgstr "ნოემბერი" + +msgid "December" +msgstr "დეკემბერი" + +msgid "jan" +msgstr "იან" + +msgid "feb" +msgstr "თებ" + +msgid "mar" +msgstr "მარ" + +msgid "apr" +msgstr "აპრ" + +msgid "may" +msgstr "მაი" + +msgid "jun" +msgstr "ივნ" + +msgid "jul" +msgstr "ივლ" + +msgid "aug" +msgstr "აგვ" + +msgid "sep" +msgstr "სექ" + +msgid "oct" +msgstr "ოქტ" + +msgid "nov" +msgstr "ნოე" + +msgid "dec" +msgstr "დეკ" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "იან." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "თებ." + +msgctxt "abbrev. month" +msgid "March" +msgstr "მარ." + +msgctxt "abbrev. month" +msgid "April" +msgstr "აპრ." + +msgctxt "abbrev. month" +msgid "May" +msgstr "მაი" + +msgctxt "abbrev. month" +msgid "June" +msgstr "ივნ." + +msgctxt "abbrev. month" +msgid "July" +msgstr "ივლ." + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "აგვ." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "სექტ." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "ოქტ." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "ნოემ." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "დეკ." + +msgctxt "alt. month" +msgid "January" +msgstr "იანვარი" + +msgctxt "alt. month" +msgid "February" +msgstr "თებერვალი" + +msgctxt "alt. month" +msgid "March" +msgstr "მარტი" + +msgctxt "alt. month" +msgid "April" +msgstr "აპრილი" + +msgctxt "alt. month" +msgid "May" +msgstr "მაისი" + +msgctxt "alt. month" +msgid "June" +msgstr "ივნისი" + +msgctxt "alt. month" +msgid "July" +msgstr "ივლისი" + +msgctxt "alt. month" +msgid "August" +msgstr "აგვისტო" + +msgctxt "alt. month" +msgid "September" +msgstr "სექტემბერი" + +msgctxt "alt. month" +msgid "October" +msgstr "ოქტომბერი" + +msgctxt "alt. month" +msgid "November" +msgstr "ნოემბერი" + +msgctxt "alt. month" +msgid "December" +msgstr "დეკემბერი" + +msgid "This is not a valid IPv6 address." +msgstr "ეს არ არის სწორი IPv6 მისამართი." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "ან" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d წელი" +msgstr[1] "%d წელი" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d თვე" +msgstr[1] "%d თვე" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d კვირა" +msgstr[1] "%d კვირა" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d დღე" +msgstr[1] "%d დღე" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d საათი" +msgstr[1] "%d საათი" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d წუთი" +msgstr[1] "%d წუთი" + +msgid "0 minutes" +msgstr "0 წუთი" + +msgid "Forbidden" +msgstr "აკრძალული" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "მეტი ინფორმაცია მისაწვდომია DEBUG=True-ს მეშვეობით." + +msgid "No year specified" +msgstr "არ არის მითითებული წელი" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "არ არის მითითებული თვე" + +msgid "No day specified" +msgstr "არ არის მითითებული დღე" + +msgid "No week specified" +msgstr "არ არის მითითებული კვირა" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "%(verbose_name_plural)s არ არსებობს" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"მომავალი %(verbose_name_plural)s არ არსებობს იმიტომ, რომ %(class_name)s." +"allow_future არის False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "არ მოიძებნა არცერთი მოთხოვნის თანმხვედრი %(verbose_name)s" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "" + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "%(directory)s-ის იდექსი" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ka/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ka/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ka/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ka/formats.py new file mode 100644 index 0000000..661b71e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ka/formats.py @@ -0,0 +1,48 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "l, j F, Y" +TIME_FORMAT = "h:i a" +DATETIME_FORMAT = "j F, Y h:i a" +YEAR_MONTH_FORMAT = "F, Y" +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "j.M.Y" +SHORT_DATETIME_FORMAT = "j.M.Y H:i" +FIRST_DAY_OF_WEEK = 1 # (Monday) + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# Kept ISO formats as they are in first position +DATE_INPUT_FORMATS = [ + "%Y-%m-%d", # '2006-10-25' + "%m/%d/%Y", # '10/25/2006' + "%m/%d/%y", # '10/25/06' + "%d.%m.%Y", # '25.10.2006' + "%d.%m.%y", # '25.10.06' + # "%d %b %Y", # '25 Oct 2006' + # "%d %b, %Y", # '25 Oct, 2006' + # "%d %b. %Y", # '25 Oct. 2006' + # "%d %B %Y", # '25 October 2006' + # "%d %B, %Y", # '25 October, 2006' +] +DATETIME_INPUT_FORMATS = [ + "%Y-%m-%d %H:%M:%S", # '2006-10-25 14:30:59' + "%Y-%m-%d %H:%M:%S.%f", # '2006-10-25 14:30:59.000200' + "%Y-%m-%d %H:%M", # '2006-10-25 14:30' + "%d.%m.%Y %H:%M:%S", # '25.10.2006 14:30:59' + "%d.%m.%Y %H:%M:%S.%f", # '25.10.2006 14:30:59.000200' + "%d.%m.%Y %H:%M", # '25.10.2006 14:30' + "%d.%m.%y %H:%M:%S", # '25.10.06 14:30:59' + "%d.%m.%y %H:%M:%S.%f", # '25.10.06 14:30:59.000200' + "%d.%m.%y %H:%M", # '25.10.06 14:30' + "%m/%d/%Y %H:%M:%S", # '10/25/2006 14:30:59' + "%m/%d/%Y %H:%M:%S.%f", # '10/25/2006 14:30:59.000200' + "%m/%d/%Y %H:%M", # '10/25/2006 14:30' + "%m/%d/%y %H:%M:%S", # '10/25/06 14:30:59' + "%m/%d/%y %H:%M:%S.%f", # '10/25/06 14:30:59.000200' + "%m/%d/%y %H:%M", # '10/25/06 14:30' +] +DECIMAL_SEPARATOR = "." +THOUSAND_SEPARATOR = " " +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/kab/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/kab/LC_MESSAGES/django.mo new file mode 100644 index 0000000..151ed67 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/kab/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/kab/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/kab/LC_MESSAGES/django.po new file mode 100644 index 0000000..b0f6fa2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/kab/LC_MESSAGES/django.po @@ -0,0 +1,1211 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Kabyle (http://www.transifex.com/django/django/language/" +"kab/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kab\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Tafrikanst" + +msgid "Arabic" +msgstr "Taɛṛabt" + +msgid "Asturian" +msgstr "Tasturyant" + +msgid "Azerbaijani" +msgstr "Tazeṛbayǧant" + +msgid "Bulgarian" +msgstr "Tabulgarit" + +msgid "Belarusian" +msgstr "Tabilurusit" + +msgid "Bengali" +msgstr "Tabelgalit" + +msgid "Breton" +msgstr "Tabrutunt" + +msgid "Bosnian" +msgstr "Tabusnit" + +msgid "Catalan" +msgstr "Takaṭalant" + +msgid "Czech" +msgstr "Tačikit" + +msgid "Welsh" +msgstr "Takusit" + +msgid "Danish" +msgstr "Tadanit" + +msgid "German" +msgstr "Talmanit" + +msgid "Lower Sorbian" +msgstr "Tasiṛbit n wadda" + +msgid "Greek" +msgstr "Tagrigit" + +msgid "English" +msgstr "Taglizit" + +msgid "Australian English" +msgstr "Taglizit n Ustralya" + +msgid "British English" +msgstr "Taglizit (UK)" + +msgid "Esperanto" +msgstr "Taspirantit" + +msgid "Spanish" +msgstr "Taspanit" + +msgid "Argentinian Spanish" +msgstr "Taspanit n Arjuntin" + +msgid "Colombian Spanish" +msgstr "Taspanit n Kulumbya" + +msgid "Mexican Spanish" +msgstr "Taspanit n Miksik" + +msgid "Nicaraguan Spanish" +msgstr "Taspanit n Nikaragwa" + +msgid "Venezuelan Spanish" +msgstr "Taspanit n Vinizwila" + +msgid "Estonian" +msgstr "Tastunit" + +msgid "Basque" +msgstr "Tabaskit" + +msgid "Persian" +msgstr "Tafarsit" + +msgid "Finnish" +msgstr "Tafinit" + +msgid "French" +msgstr "Tafṛansist" + +msgid "Frisian" +msgstr "" + +msgid "Irish" +msgstr "" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "" + +msgid "Hebrew" +msgstr "" + +msgid "Hindi" +msgstr "Tahendit" + +msgid "Croatian" +msgstr "Takarwasit" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "Tahungarit" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "" + +msgid "Indonesian" +msgstr "Tandunizit" + +msgid "Ido" +msgstr "" + +msgid "Icelandic" +msgstr "Taslandit" + +msgid "Italian" +msgstr "Taṭelyanit" + +msgid "Japanese" +msgstr "" + +msgid "Georgian" +msgstr "Tajyuṛjit" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "Takazaxt" + +msgid "Khmer" +msgstr "" + +msgid "Kannada" +msgstr "Takannadat" + +msgid "Korean" +msgstr "Takurit" + +msgid "Luxembourgish" +msgstr "" + +msgid "Lithuanian" +msgstr "Talitwanit" + +msgid "Latvian" +msgstr "Talitunit" + +msgid "Macedonian" +msgstr "Tamasidunit" + +msgid "Malayalam" +msgstr "Tamayalamt" + +msgid "Mongolian" +msgstr "" + +msgid "Marathi" +msgstr "" + +msgid "Burmese" +msgstr "Tabirmanit" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "Tanipalit" + +msgid "Dutch" +msgstr "Tahulandit" + +msgid "Norwegian Nynorsk" +msgstr "" + +msgid "Ossetic" +msgstr "" + +msgid "Punjabi" +msgstr "Tabenjabit" + +msgid "Polish" +msgstr "Tapulandit" + +msgid "Portuguese" +msgstr "Tapurtugit" + +msgid "Brazilian Portuguese" +msgstr "" + +msgid "Romanian" +msgstr "Tarumanit" + +msgid "Russian" +msgstr "Tarusit" + +msgid "Slovak" +msgstr "Tasluvakt" + +msgid "Slovenian" +msgstr "" + +msgid "Albanian" +msgstr "Talbanit" + +msgid "Serbian" +msgstr "Tasiṛbit" + +msgid "Serbian Latin" +msgstr "" + +msgid "Swedish" +msgstr "Taswidit" + +msgid "Swahili" +msgstr "Taswahilit" + +msgid "Tamil" +msgstr "Taṭamult" + +msgid "Telugu" +msgstr "" + +msgid "Thai" +msgstr "" + +msgid "Turkish" +msgstr "Taṭurkit" + +msgid "Tatar" +msgstr "" + +msgid "Udmurt" +msgstr "" + +msgid "Ukrainian" +msgstr "" + +msgid "Urdu" +msgstr "" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "" + +msgid "Simplified Chinese" +msgstr "" + +msgid "Traditional Chinese" +msgstr "" + +msgid "Messages" +msgstr "Iznan" + +msgid "Site Maps" +msgstr "" + +msgid "Static Files" +msgstr "" + +msgid "Syndication" +msgstr "" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "Sekcem azal ameɣtu." + +msgid "Enter a valid URL." +msgstr "" + +msgid "Enter a valid integer." +msgstr "" + +msgid "Enter a valid email address." +msgstr "Sekcem tansa imayl tameɣtut." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Sekcem tansa IPv4 tameɣtut." + +msgid "Enter a valid IPv6 address." +msgstr "" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "" + +msgid "Enter only digits separated by commas." +msgstr "" + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Enter a number." +msgstr "Sekcem amḍan." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "akked" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "" + +msgid "This field cannot be blank." +msgstr "" + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "" + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "" + +msgid "Comma-separated integers" +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Azemz (s wakud)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "Tanzagt" + +msgid "Email address" +msgstr "Tansa email" + +msgid "File path" +msgstr "Abrid n ufaylu" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "Ummid" + +msgid "Big (8 byte) integer" +msgstr "" + +msgid "IPv4 address" +msgstr "" + +msgid "IP address" +msgstr "Tansa IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "" + +msgid "Positive integer" +msgstr "" + +msgid "Positive small integer" +msgstr "" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "" + +msgid "Small integer" +msgstr "" + +msgid "Text" +msgstr "Aḍris" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Akud" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "Afaylu" + +msgid "Image" +msgstr "Tugna" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "" + +msgid "One-to-one relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "" + +msgid "Enter a whole number." +msgstr "Sekcem amḍan ummid." + +msgid "Enter a valid date." +msgstr "" + +msgid "Enter a valid time." +msgstr "" + +msgid "Enter a valid date/time." +msgstr "" + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" + +msgid "No file was submitted." +msgstr "Afaylu ur yettwazen ara." + +msgid "The submitted file is empty." +msgstr "" + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" + +msgid "Enter a list of values." +msgstr "" + +msgid "Enter a complete value." +msgstr "Sekcem azal ummid." + +msgid "Enter a valid UUID." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "Amizwer" + +msgid "Delete" +msgstr "KKES" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "" + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" + +msgid "Please correct the duplicate values below." +msgstr "" + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Sfeḍ" + +msgid "Currently" +msgstr "Tura" + +msgid "Change" +msgstr "Beddel" + +msgid "Unknown" +msgstr "Arussin" + +msgid "Yes" +msgstr "Ih" + +msgid "No" +msgstr "Uhu" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%s KB" +msgstr "%s KAṬ" + +#, python-format +msgid "%s MB" +msgstr "%s MAṬ" + +#, python-format +msgid "%s GB" +msgstr "%s GAṬ" + +#, python-format +msgid "%s TB" +msgstr "%s TAṬ" + +#, python-format +msgid "%s PB" +msgstr "%s PAṬ" + +msgid "p.m." +msgstr "m.d." + +msgid "a.m." +msgstr "f.t." + +msgid "PM" +msgstr "MD" + +msgid "AM" +msgstr "FT" + +msgid "midnight" +msgstr "ttnaṣfa n yiḍ" + +msgid "noon" +msgstr "ttnaṣfa n uzal" + +msgid "Monday" +msgstr "Arim" + +msgid "Tuesday" +msgstr "Aram" + +msgid "Wednesday" +msgstr "Ahad" + +msgid "Thursday" +msgstr "Amhad" + +msgid "Friday" +msgstr "Sem" + +msgid "Saturday" +msgstr "Sed" + +msgid "Sunday" +msgstr "Acer" + +msgid "Mon" +msgstr "Ari" + +msgid "Tue" +msgstr "Ara" + +msgid "Wed" +msgstr "Aha" + +msgid "Thu" +msgstr "Amh" + +msgid "Fri" +msgstr "Sem" + +msgid "Sat" +msgstr "Sed" + +msgid "Sun" +msgstr "Ace" + +msgid "January" +msgstr "Yennayer" + +msgid "February" +msgstr "Fuṛaṛ" + +msgid "March" +msgstr "Meɣres" + +msgid "April" +msgstr "Yebrir" + +msgid "May" +msgstr "Mayyu" + +msgid "June" +msgstr "Yunyu" + +msgid "July" +msgstr "Yulyu" + +msgid "August" +msgstr "Ɣuct" + +msgid "September" +msgstr "Ctamber" + +msgid "October" +msgstr "Tuber" + +msgid "November" +msgstr "Wamber" + +msgid "December" +msgstr "Dujamber" + +msgid "jan" +msgstr "yen" + +msgid "feb" +msgstr "fuṛ" + +msgid "mar" +msgstr "meɣ" + +msgid "apr" +msgstr "yeb" + +msgid "may" +msgstr "may" + +msgid "jun" +msgstr "yun" + +msgid "jul" +msgstr "yul" + +msgid "aug" +msgstr "ɣuc" + +msgid "sep" +msgstr "cte" + +msgid "oct" +msgstr "tub" + +msgid "nov" +msgstr "wam" + +msgid "dec" +msgstr "duj" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Yen." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Fuṛ." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Meɣres" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Yebrir" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Mayyu" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Yunyu" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Yulyu" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Ɣuc." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Tub." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Wam." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Duj." + +msgctxt "alt. month" +msgid "January" +msgstr "Yennayer" + +msgctxt "alt. month" +msgid "February" +msgstr "Fuṛaṛ" + +msgctxt "alt. month" +msgid "March" +msgstr "Meɣres" + +msgctxt "alt. month" +msgid "April" +msgstr "Yebrir" + +msgctxt "alt. month" +msgid "May" +msgstr "Mayyu" + +msgctxt "alt. month" +msgid "June" +msgstr "Yunyu" + +msgctxt "alt. month" +msgid "July" +msgstr "Yulyu" + +msgctxt "alt. month" +msgid "August" +msgstr "Ɣuct" + +msgctxt "alt. month" +msgid "September" +msgstr "Ctamber" + +msgctxt "alt. month" +msgid "October" +msgstr "Tuber" + +msgctxt "alt. month" +msgid "November" +msgstr "Wamber" + +msgctxt "alt. month" +msgid "December" +msgstr "Dujamber" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "neɣ" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" + +msgid "0 minutes" +msgstr "0 n tisdatin" + +msgid "Forbidden" +msgstr "Yegdel" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "" + +msgid "No day specified" +msgstr "" + +msgid "No week specified" +msgstr "" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "" + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "Bdu s Django" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/kk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/kk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..38300b2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/kk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/kk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/kk/LC_MESSAGES/django.po new file mode 100644 index 0000000..2858be0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/kk/LC_MESSAGES/django.po @@ -0,0 +1,1223 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Baurzhan Muftakhidinov , 2015 +# Zharzhan Kulmyrza , 2011 +# Leo Trubach , 2017 +# Nurlan Rakhimzhanov , 2011 +# yun_man_ger , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Kazakh (http://www.transifex.com/django/django/language/kk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kk\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +msgid "Afrikaans" +msgstr "" + +msgid "Arabic" +msgstr "Араб" + +msgid "Asturian" +msgstr "" + +msgid "Azerbaijani" +msgstr "Әзірбайжан" + +msgid "Bulgarian" +msgstr "Болгар" + +msgid "Belarusian" +msgstr "" + +msgid "Bengali" +msgstr "Бенгал" + +msgid "Breton" +msgstr "" + +msgid "Bosnian" +msgstr "Босния" + +msgid "Catalan" +msgstr "Каталан" + +msgid "Czech" +msgstr "Чех" + +msgid "Welsh" +msgstr "Валлий" + +msgid "Danish" +msgstr "Дания" + +msgid "German" +msgstr "Неміс" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "Грек" + +msgid "English" +msgstr "Ағылшын" + +msgid "Australian English" +msgstr "" + +msgid "British English" +msgstr "Британдық ағылшын" + +msgid "Esperanto" +msgstr "" + +msgid "Spanish" +msgstr "Испан" + +msgid "Argentinian Spanish" +msgstr "Аргентиналық испан" + +msgid "Colombian Spanish" +msgstr "" + +msgid "Mexican Spanish" +msgstr "Мексикалық испан" + +msgid "Nicaraguan Spanish" +msgstr "Никарагуа испан" + +msgid "Venezuelan Spanish" +msgstr "" + +msgid "Estonian" +msgstr "Эстон" + +msgid "Basque" +msgstr "Баск" + +msgid "Persian" +msgstr "Парсы" + +msgid "Finnish" +msgstr "Фин" + +msgid "French" +msgstr "Француз" + +msgid "Frisian" +msgstr "Фриз" + +msgid "Irish" +msgstr "Ирландия" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "Галиц" + +msgid "Hebrew" +msgstr "Иврит" + +msgid "Hindi" +msgstr "Хинди" + +msgid "Croatian" +msgstr "Кроат" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "Венгрия" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "" + +msgid "Indonesian" +msgstr "Индонезия" + +msgid "Ido" +msgstr "" + +msgid "Icelandic" +msgstr "Исладия" + +msgid "Italian" +msgstr "Итальян" + +msgid "Japanese" +msgstr "Жапон" + +msgid "Georgian" +msgstr "Грузин" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "Қазақша" + +msgid "Khmer" +msgstr "Кхмер" + +msgid "Kannada" +msgstr "Канада" + +msgid "Korean" +msgstr "Корей" + +msgid "Luxembourgish" +msgstr "" + +msgid "Lithuanian" +msgstr "Литва" + +msgid "Latvian" +msgstr "Латвия" + +msgid "Macedonian" +msgstr "Македон" + +msgid "Malayalam" +msgstr "Малаялам" + +msgid "Mongolian" +msgstr "Монғол" + +msgid "Marathi" +msgstr "" + +msgid "Burmese" +msgstr "" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "" + +msgid "Dutch" +msgstr "Голланд" + +msgid "Norwegian Nynorsk" +msgstr "Норвегиялық нюнор" + +msgid "Ossetic" +msgstr "" + +msgid "Punjabi" +msgstr "Пенджаб" + +msgid "Polish" +msgstr "Поляк" + +msgid "Portuguese" +msgstr "Португал" + +msgid "Brazilian Portuguese" +msgstr "Бразилиялық португал" + +msgid "Romanian" +msgstr "Роман" + +msgid "Russian" +msgstr "Орыс" + +msgid "Slovak" +msgstr "Словак" + +msgid "Slovenian" +msgstr "Словениялық" + +msgid "Albanian" +msgstr "Албан" + +msgid "Serbian" +msgstr "Серб" + +msgid "Serbian Latin" +msgstr "Сербиялық латын" + +msgid "Swedish" +msgstr "Швед" + +msgid "Swahili" +msgstr "" + +msgid "Tamil" +msgstr "Тамиль" + +msgid "Telugu" +msgstr "Телугу" + +msgid "Thai" +msgstr "Тай" + +msgid "Turkish" +msgstr "Түрік" + +msgid "Tatar" +msgstr "" + +msgid "Udmurt" +msgstr "" + +msgid "Ukrainian" +msgstr "Украин" + +msgid "Urdu" +msgstr "Урду" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "Вьетнам" + +msgid "Simplified Chinese" +msgstr "Жеңілдетілген қытай" + +msgid "Traditional Chinese" +msgstr "Дәстүрлі қытай" + +msgid "Messages" +msgstr "" + +msgid "Site Maps" +msgstr "" + +msgid "Static Files" +msgstr "" + +msgid "Syndication" +msgstr "" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "Тура мәнін енгізіңіз." + +msgid "Enter a valid URL." +msgstr "Тура URL-ді енгізіңіз." + +msgid "Enter a valid integer." +msgstr "" + +msgid "Enter a valid email address." +msgstr "" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Тура IPv4 адресті енгізіңіз." + +msgid "Enter a valid IPv6 address." +msgstr "" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "" + +msgid "Enter only digits separated by commas." +msgstr "Тек үтірлермен бөлінген цифрлерді енгізіңіз." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Бұл мәннің %(limit_value)s екендігін тексеріңіз (қазір ол %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" +"Бұл мәннің мынадан %(limit_value)s кіші немесе тең екендігін тексеріңіз." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" +"Бұл мәннің мынадан %(limit_value)s үлкен немесе тең екендігін тексеріңіз." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Enter a number." +msgstr "Сан енгізіңіз." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "және" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "Бұл жолақ null болмау керек." + +msgid "This field cannot be blank." +msgstr "Бұл жолақ бос болмау керек." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s %(field_label)s жолақпен бұрыннан бар." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Жолақтын түрі: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "Boolean (True немесе False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Жол (%(max_length)s символға дейін)" + +msgid "Comma-separated integers" +msgstr "Үтірмен бөлінген бүтін сандар" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "Дата (уақытсыз)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Дата (уақытпен)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Ондық сан" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "" + +msgid "Email address" +msgstr "Email адрес" + +msgid "File path" +msgstr "Файл жолы" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "Реал сан" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "Бүтін сан" + +msgid "Big (8 byte) integer" +msgstr "Ұзын (8 байт) бүтін сан" + +msgid "IPv4 address" +msgstr "" + +msgid "IP address" +msgstr "IP мекенжайы" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "Булеан (True, False немесе None)" + +msgid "Positive integer" +msgstr "" + +msgid "Positive small integer" +msgstr "" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "" + +msgid "Small integer" +msgstr "" + +msgid "Text" +msgstr "Мәтін" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Уақыт" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "" + +msgid "Image" +msgstr "" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "Foreign Key (тип related field арқылы анықталады)" + +msgid "One-to-one relationship" +msgstr "One-to-one қатынас" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "Many-to-many қатынас" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr "" + +msgid "This field is required." +msgstr "Бұл өрісті толтыру міндетті." + +msgid "Enter a whole number." +msgstr "Толық санды енгізіңіз." + +msgid "Enter a valid date." +msgstr "Дұрыс күнді енгізіңіз." + +msgid "Enter a valid time." +msgstr "Дұрыс уақытты енгізіңіз." + +msgid "Enter a valid date/time." +msgstr "Дұрыс күнді/уақытты енгізіңіз." + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Ешқандай файл жіберілмеді. Форманың кодтау түрін тексеріңіз." + +msgid "No file was submitted." +msgstr "Ешқандай файл жіберілмеді." + +msgid "The submitted file is empty." +msgstr "Бос файл жіберілді." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Файлды жіберіңіз немесе тазалауды белгіленіз, екеуін бірге емес." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Дұрыс сүретті жүктеңіз. Сіз жүктеген файл - сүрет емес немесе бұзылған сүрет." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Дұрыс тандау жасаңыз. %(value)s дұрыс тандау емес." + +msgid "Enter a list of values." +msgstr "Мәндер тізімін енгізіңіз." + +msgid "Enter a complete value." +msgstr "" + +msgid "Enter a valid UUID." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr "" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "Сұрыптау" + +msgid "Delete" +msgstr "Жою" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "%(field)s жолақтағы қайталанған мәнді түзетіңіз." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "%(field)s жолақтағы мәнді түзетіңіз, ол бірегей болу керек." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"%(field_name)s жолақтағы мәнді түзетіңіз. Ол %(date_field)s жолақтың ішінде " +"%(lookup)s үшін бірегей болу керек." + +msgid "Please correct the duplicate values below." +msgstr "Қайталанатын мәндерді түзетіңіз." + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Дұрыс нұсқаны таңдаңыз. Бұл нұсқа дұрыс таңдаулардың арасында жоқ." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Тазалау" + +msgid "Currently" +msgstr "Ағымдағы" + +msgid "Change" +msgstr "Түзету" + +msgid "Unknown" +msgstr "Белгісіз" + +msgid "Yes" +msgstr "Иә" + +msgid "No" +msgstr "Жоқ" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "иә,жоқ,мүмкін" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d байт" +msgstr[1] "%(size)d байт" + +#, python-format +msgid "%s KB" +msgstr "%s КБ" + +#, python-format +msgid "%s MB" +msgstr "%s МБ" + +#, python-format +msgid "%s GB" +msgstr "%s ГБ" + +#, python-format +msgid "%s TB" +msgstr "%s ТБ" + +#, python-format +msgid "%s PB" +msgstr "%s ПБ" + +msgid "p.m." +msgstr "Т.Қ." + +msgid "a.m." +msgstr "Т.Ж." + +msgid "PM" +msgstr "ТҚ" + +msgid "AM" +msgstr "ТЖ" + +msgid "midnight" +msgstr "түнжарым" + +msgid "noon" +msgstr "түсқайта" + +msgid "Monday" +msgstr "Дүйсенбі" + +msgid "Tuesday" +msgstr "Сейсенбі" + +msgid "Wednesday" +msgstr "Сәрсенбі" + +msgid "Thursday" +msgstr "Бейсенбі" + +msgid "Friday" +msgstr "Жума" + +msgid "Saturday" +msgstr "Сенбі" + +msgid "Sunday" +msgstr "Жексенбі" + +msgid "Mon" +msgstr "Дб" + +msgid "Tue" +msgstr "Сб" + +msgid "Wed" +msgstr "Ср" + +msgid "Thu" +msgstr "Бс" + +msgid "Fri" +msgstr "Жм" + +msgid "Sat" +msgstr "Сн" + +msgid "Sun" +msgstr "Жк" + +msgid "January" +msgstr "Қаңтар" + +msgid "February" +msgstr "Ақпан" + +msgid "March" +msgstr "Наурыз" + +msgid "April" +msgstr "Сәуір" + +msgid "May" +msgstr "Мамыр" + +msgid "June" +msgstr "Маусым" + +msgid "July" +msgstr "Шілде" + +msgid "August" +msgstr "Тамыз" + +msgid "September" +msgstr "Қыркүйек" + +msgid "October" +msgstr "Қазан" + +msgid "November" +msgstr "Қараша" + +msgid "December" +msgstr "Желтоқсан" + +msgid "jan" +msgstr "қан" + +msgid "feb" +msgstr "ақп" + +msgid "mar" +msgstr "нау" + +msgid "apr" +msgstr "сәу" + +msgid "may" +msgstr "мам" + +msgid "jun" +msgstr "мау" + +msgid "jul" +msgstr "шіл" + +msgid "aug" +msgstr "там" + +msgid "sep" +msgstr "қыр" + +msgid "oct" +msgstr "қаз" + +msgid "nov" +msgstr "қар" + +msgid "dec" +msgstr "жел" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Қаң." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Ақп." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Наурыз" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Сәуір" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Мамыр" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Маусым" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Шілде" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Там." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Қыр." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Қаз." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Қар." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Жел." + +msgctxt "alt. month" +msgid "January" +msgstr "Қаңтар" + +msgctxt "alt. month" +msgid "February" +msgstr "Ақпан" + +msgctxt "alt. month" +msgid "March" +msgstr "Наурыз" + +msgctxt "alt. month" +msgid "April" +msgstr "Сәуір" + +msgctxt "alt. month" +msgid "May" +msgstr "Мамыр" + +msgctxt "alt. month" +msgid "June" +msgstr "Маусым" + +msgctxt "alt. month" +msgid "July" +msgstr "Шілде" + +msgctxt "alt. month" +msgid "August" +msgstr "Тамыз" + +msgctxt "alt. month" +msgid "September" +msgstr "Қыркүйек" + +msgctxt "alt. month" +msgid "October" +msgstr "Қазан" + +msgctxt "alt. month" +msgid "November" +msgstr "Қараша" + +msgctxt "alt. month" +msgid "December" +msgstr "Желтоқсан" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "немесе" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" + +msgid "0 minutes" +msgstr "" + +msgid "Forbidden" +msgstr "" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "Жыл таңдалмаған" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "Ай таңдалмаған" + +msgid "No day specified" +msgstr "Күн таңдалмаған" + +msgid "No week specified" +msgstr "Апта таңдалмаған" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "%(verbose_name_plural)s қол жеткізгісіз" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Болашақ %(verbose_name_plural)s қол жеткізгісіз, себебі %(class_name)s." +"allow_future False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "%(verbose_name)s табылған жоқ" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "" + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/km/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/km/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3de6c80 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/km/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/km/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/km/LC_MESSAGES/django.po new file mode 100644 index 0000000..c706129 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/km/LC_MESSAGES/django.po @@ -0,0 +1,1196 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Khmer (http://www.transifex.com/django/django/language/km/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: km\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Afrikaans" +msgstr "" + +msgid "Arabic" +msgstr "ភាសាអារ៉ាប់" + +msgid "Asturian" +msgstr "" + +msgid "Azerbaijani" +msgstr "" + +msgid "Bulgarian" +msgstr "" + +msgid "Belarusian" +msgstr "" + +msgid "Bengali" +msgstr "ភាសាបេឡារុស្ស" + +msgid "Breton" +msgstr "" + +msgid "Bosnian" +msgstr "" + +msgid "Catalan" +msgstr "" + +msgid "Czech" +msgstr "ភាសាឆេក" + +msgid "Welsh" +msgstr "ភាសាអ៊ុយក្រែន" + +msgid "Danish" +msgstr "ភាសាដាណឺម៉ាក" + +msgid "German" +msgstr "ភាសាអាល្លឺម៉ង់" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "ភាសាហ្កែលិគ" + +msgid "English" +msgstr "ភាសាអង់គ្លេស" + +msgid "Australian English" +msgstr "" + +msgid "British English" +msgstr "" + +msgid "Esperanto" +msgstr "" + +msgid "Spanish" +msgstr "ភាសាអេស្ប៉ាញ" + +msgid "Argentinian Spanish" +msgstr "" + +msgid "Colombian Spanish" +msgstr "" + +msgid "Mexican Spanish" +msgstr "" + +msgid "Nicaraguan Spanish" +msgstr "" + +msgid "Venezuelan Spanish" +msgstr "" + +msgid "Estonian" +msgstr "" + +msgid "Basque" +msgstr "" + +msgid "Persian" +msgstr "" + +msgid "Finnish" +msgstr "ភាសាហ្វាំងឡង់" + +msgid "French" +msgstr "ភាសាបារាំង" + +msgid "Frisian" +msgstr "" + +msgid "Irish" +msgstr "" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "ភាសាហ្កែលិគ" + +msgid "Hebrew" +msgstr "ភាសាហេប្រិ" + +msgid "Hindi" +msgstr "" + +msgid "Croatian" +msgstr "" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "ភាសាហុងគ្រី" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "" + +msgid "Indonesian" +msgstr "" + +msgid "Ido" +msgstr "" + +msgid "Icelandic" +msgstr "ភាសាអ៉ីស្លង់" + +msgid "Italian" +msgstr "ភាសាអ៊ីតាលី" + +msgid "Japanese" +msgstr "ភាសាជប៉ុន" + +msgid "Georgian" +msgstr "" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "" + +msgid "Khmer" +msgstr "" + +msgid "Kannada" +msgstr "" + +msgid "Korean" +msgstr "" + +msgid "Luxembourgish" +msgstr "" + +msgid "Lithuanian" +msgstr "" + +msgid "Latvian" +msgstr "" + +msgid "Macedonian" +msgstr "" + +msgid "Malayalam" +msgstr "" + +msgid "Mongolian" +msgstr "" + +msgid "Marathi" +msgstr "" + +msgid "Burmese" +msgstr "" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "" + +msgid "Dutch" +msgstr "ភាសាហ្វាំងឡង់" + +msgid "Norwegian Nynorsk" +msgstr "" + +msgid "Ossetic" +msgstr "" + +msgid "Punjabi" +msgstr "" + +msgid "Polish" +msgstr "" + +msgid "Portuguese" +msgstr "" + +msgid "Brazilian Portuguese" +msgstr "" + +msgid "Romanian" +msgstr "ភាសារូម៉ានី" + +msgid "Russian" +msgstr "ភាសាรัរូស្ស៉ី" + +msgid "Slovak" +msgstr "ភាសាស្លូវ៉ាគី" + +msgid "Slovenian" +msgstr "ភាសាស្លូវ៉ានី" + +msgid "Albanian" +msgstr "" + +msgid "Serbian" +msgstr "" + +msgid "Serbian Latin" +msgstr "" + +msgid "Swedish" +msgstr "ភាសាស៊ុយអែដ" + +msgid "Swahili" +msgstr "" + +msgid "Tamil" +msgstr "ភាសាតាមីល" + +msgid "Telugu" +msgstr "" + +msgid "Thai" +msgstr "" + +msgid "Turkish" +msgstr "ភាសាទួរគី" + +msgid "Tatar" +msgstr "" + +msgid "Udmurt" +msgstr "" + +msgid "Ukrainian" +msgstr "ភាសាអ៊ុយក្រែន" + +msgid "Urdu" +msgstr "" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "" + +msgid "Simplified Chinese" +msgstr "ភាសាចិនសាមញ្ញ" + +msgid "Traditional Chinese" +msgstr "ភាសាចិនបុរាណ" + +msgid "Messages" +msgstr "" + +msgid "Site Maps" +msgstr "" + +msgid "Static Files" +msgstr "" + +msgid "Syndication" +msgstr "" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "" + +msgid "Enter a valid URL." +msgstr "" + +msgid "Enter a valid integer." +msgstr "" + +msgid "Enter a valid email address." +msgstr "" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "" + +msgid "Enter a valid IPv6 address." +msgstr "" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "" + +msgid "Enter only digits separated by commas." +msgstr "បំពេញតែលេខហើយផ្តាច់ចេញពីគ្នាដោយសញ្ញាក្បៀស។" + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" + +msgid "Enter a number." +msgstr "" + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "និង" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "ចាំបាច់បំពេញទិន្នន័យកន្លែងនេះ។" + +msgid "This field cannot be blank." +msgstr "" + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "" + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "Boolean (អាច​ជា True រឺ False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "" + +msgid "Comma-separated integers" +msgstr "ចំនួនពិត(Integer) ដែលផ្តាច់ចេញពីគ្នាដោយ​ក្បៀស" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "កាល​បរិច្ឆេទ (Date) (មិនមានសរសេរម៉ោង)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "កាល​បរិច្ឆេទ (Date) (មានសរសេរម៉ោង)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "ចំនួនទសភាគ (Decimal)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "" + +msgid "Email address" +msgstr "" + +msgid "File path" +msgstr "ផ្លូវទៅកាន់ឯកសារ" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "ចំនួនពិត(Integer)" + +msgid "Big (8 byte) integer" +msgstr "" + +msgid "IPv4 address" +msgstr "" + +msgid "IP address" +msgstr "លេខ IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "Boolean (អាចជា True​ រឺ False រឺ None)" + +msgid "Positive integer" +msgstr "" + +msgid "Positive small integer" +msgstr "" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "" + +msgid "Small integer" +msgstr "" + +msgid "Text" +msgstr "អត្ថបទ" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "ពេលវេលា" + +msgid "URL" +msgstr "អាស័យដ្ឋានគេហទំព័រ(URL)" + +msgid "Raw binary data" +msgstr "" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "" + +msgid "Image" +msgstr "" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "" + +msgid "One-to-one relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr "" + +msgid "This field is required." +msgstr "ចាំបាច់បំពេញទិន្នន័យកន្លែងនេះ។" + +msgid "Enter a whole number." +msgstr "បំពេញចំនួនទាំងអស់។" + +msgid "Enter a valid date." +msgstr "" + +msgid "Enter a valid time." +msgstr "" + +msgid "Enter a valid date/time." +msgstr "" + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "មិនមានឯកសារត្រូវបានជ្រើសរើស។ សូមពិនិត្យប្រភេទឯកសារម្តងទៀត។" + +msgid "No file was submitted." +msgstr "" + +msgid "The submitted file is empty." +msgstr "ពុំមានឯកសារ។​" + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "រូបភាពដែលទាញយកមិនត្រឹមត្រូវ ប្រហែលជាមិនមែនជារូបភាព ឬក៏ជា រូបភាពខូច។" + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" + +msgid "Enter a list of values." +msgstr "" + +msgid "Enter a complete value." +msgstr "" + +msgid "Enter a valid UUID." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr "" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" + +msgid "Order" +msgstr "" + +msgid "Delete" +msgstr "លប់" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "" + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" + +msgid "Please correct the duplicate values below." +msgstr "" + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "" + +msgid "Currently" +msgstr "" + +msgid "Change" +msgstr "ផ្លាស់ប្តូរ" + +msgid "Unknown" +msgstr "មិន​ដឹង" + +msgid "Yes" +msgstr "យល់ព្រម" + +msgid "No" +msgstr "មិនយល់ព្រម" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "យល់ព្រម មិនយល់ព្រម​ ប្រហែល" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "" + +#, python-format +msgid "%s KB" +msgstr "" + +#, python-format +msgid "%s MB" +msgstr "" + +#, python-format +msgid "%s GB" +msgstr "" + +#, python-format +msgid "%s TB" +msgstr "" + +#, python-format +msgid "%s PB" +msgstr "" + +msgid "p.m." +msgstr "" + +msgid "a.m." +msgstr "" + +msgid "PM" +msgstr "" + +msgid "AM" +msgstr "" + +msgid "midnight" +msgstr "" + +msgid "noon" +msgstr "" + +msgid "Monday" +msgstr "ច័ន្ទ" + +msgid "Tuesday" +msgstr "អង្គារ" + +msgid "Wednesday" +msgstr "ពុធ" + +msgid "Thursday" +msgstr "ព្រហស្បតិ៍" + +msgid "Friday" +msgstr "សុក្រ" + +msgid "Saturday" +msgstr "សៅរ៍" + +msgid "Sunday" +msgstr "អាទិត្យ" + +msgid "Mon" +msgstr "" + +msgid "Tue" +msgstr "" + +msgid "Wed" +msgstr "" + +msgid "Thu" +msgstr "" + +msgid "Fri" +msgstr "" + +msgid "Sat" +msgstr "" + +msgid "Sun" +msgstr "" + +msgid "January" +msgstr "មករា" + +msgid "February" +msgstr "កុម្ភៈ" + +msgid "March" +msgstr "មិនា" + +msgid "April" +msgstr "មេសា" + +msgid "May" +msgstr "ឧសភា" + +msgid "June" +msgstr "មិថុនា" + +msgid "July" +msgstr "កក្កដា" + +msgid "August" +msgstr "សីហា" + +msgid "September" +msgstr "កញ្ញា" + +msgid "October" +msgstr "តុលា" + +msgid "November" +msgstr "វិច្ឆិកា" + +msgid "December" +msgstr "ធ្នូ" + +msgid "jan" +msgstr "មករា" + +msgid "feb" +msgstr "កុម្ភះ" + +msgid "mar" +msgstr "មិនា" + +msgid "apr" +msgstr "មេសា" + +msgid "may" +msgstr "ឧសភា" + +msgid "jun" +msgstr "មិថុនា" + +msgid "jul" +msgstr "កក្កដា" + +msgid "aug" +msgstr "សីហា" + +msgid "sep" +msgstr "កញ្ញា" + +msgid "oct" +msgstr "តុលា" + +msgid "nov" +msgstr "វិច្ឆិកា" + +msgid "dec" +msgstr "ធ្នូ" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "" + +msgctxt "abbrev. month" +msgid "March" +msgstr "មិនា" + +msgctxt "abbrev. month" +msgid "April" +msgstr "មេសា" + +msgctxt "abbrev. month" +msgid "May" +msgstr "ឧសភា" + +msgctxt "abbrev. month" +msgid "June" +msgstr "មិថុនា" + +msgctxt "abbrev. month" +msgid "July" +msgstr "កក្កដា" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "" + +msgctxt "alt. month" +msgid "January" +msgstr "មករា" + +msgctxt "alt. month" +msgid "February" +msgstr "កុម្ភៈ" + +msgctxt "alt. month" +msgid "March" +msgstr "មិនា" + +msgctxt "alt. month" +msgid "April" +msgstr "មេសា" + +msgctxt "alt. month" +msgid "May" +msgstr "ឧសភា" + +msgctxt "alt. month" +msgid "June" +msgstr "មិថុនា" + +msgctxt "alt. month" +msgid "July" +msgstr "កក្កដា" + +msgctxt "alt. month" +msgid "August" +msgstr "សីហា" + +msgctxt "alt. month" +msgid "September" +msgstr "កញ្ញា" + +msgctxt "alt. month" +msgid "October" +msgstr "តុលា" + +msgctxt "alt. month" +msgid "November" +msgstr "វិច្ឆិកា" + +msgctxt "alt. month" +msgid "December" +msgstr "ធ្នូ" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "" + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" + +msgid "0 minutes" +msgstr "" + +msgid "Forbidden" +msgstr "" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "" + +msgid "No day specified" +msgstr "" + +msgid "No week specified" +msgstr "" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "" + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/km/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/km/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/km/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/km/formats.py new file mode 100644 index 0000000..5923437 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/km/formats.py @@ -0,0 +1,21 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j ខែ F ឆ្នាំ Y" +TIME_FORMAT = "G:i" +DATETIME_FORMAT = "j ខែ F ឆ្នាំ Y, G:i" +# YEAR_MONTH_FORMAT = +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "j M Y" +SHORT_DATETIME_FORMAT = "j M Y, G:i" +# FIRST_DAY_OF_WEEK = + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +# NUMBER_GROUPING = diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/kn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/kn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c926f57 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/kn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/kn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/kn/LC_MESSAGES/django.po new file mode 100644 index 0000000..f2ba2aa --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/kn/LC_MESSAGES/django.po @@ -0,0 +1,1232 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# karthikbgl , 2011-2012 +# Ramakrishna Yekulla , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Kannada (http://www.transifex.com/django/django/language/" +"kn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kn\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Afrikaans" +msgstr "" + +msgid "Arabic" +msgstr "ಅರೇಬಿಕ್" + +msgid "Asturian" +msgstr "" + +msgid "Azerbaijani" +msgstr "ಆಜೆರ್ಬೈಜನಿ" + +msgid "Bulgarian" +msgstr "ಬಲ್ಗೇರಿಯನ್" + +msgid "Belarusian" +msgstr "" + +msgid "Bengali" +msgstr "ಬೆಂಗಾಲಿ" + +msgid "Breton" +msgstr "" + +msgid "Bosnian" +msgstr "ಬೋಸ್ನಿಯನ್" + +msgid "Catalan" +msgstr "ಕೆಟಲಾನ್" + +msgid "Czech" +msgstr "ಝೆಕ್" + +msgid "Welsh" +msgstr "ವೆಲ್ಷ್" + +msgid "Danish" +msgstr "ಡ್ಯಾನಿಷ್" + +msgid "German" +msgstr "ಜರ್ಮನ್" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "ಗ್ರೀಕ್" + +msgid "English" +msgstr "ಇಂಗ್ಲಿಷ್" + +msgid "Australian English" +msgstr "" + +msgid "British English" +msgstr "ಬ್ರಿಟೀಶ್ ಇಂಗ್ಲಿಷ್" + +msgid "Esperanto" +msgstr "" + +msgid "Spanish" +msgstr "ಸ್ಪ್ಯಾನಿಷ್" + +msgid "Argentinian Spanish" +msgstr "ಅರ್ಜೆಂಟಿನಿಯನ್ ಸ್ಪಾನಿಷ್" + +msgid "Colombian Spanish" +msgstr "" + +msgid "Mexican Spanish" +msgstr "ಮೆಕ್ಸಿಕನ್ ಸ್ಪಾನಿಷ್" + +msgid "Nicaraguan Spanish" +msgstr "nicarguan ಸ್ಪಾನಿಷ್" + +msgid "Venezuelan Spanish" +msgstr "" + +msgid "Estonian" +msgstr "ಎಷ್ಟೋನಿಯನ್" + +msgid "Basque" +msgstr "ಬಾಸ್ಕ್‍" + +msgid "Persian" +msgstr "ಪರ್ಶಿಯನ್" + +msgid "Finnish" +msgstr "ಫಿನ್ನಿಶ್" + +msgid "French" +msgstr "ಫ್ರೆಂಚ್" + +msgid "Frisian" +msgstr "ಫ್ರಿಸಿಯನ್" + +msgid "Irish" +msgstr "ಐರಿಶ್" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "ಗೆಲಿಶಿಯನ್" + +msgid "Hebrew" +msgstr "ಹೀಬ್ರೂ" + +msgid "Hindi" +msgstr "ಹಿಂದಿ" + +msgid "Croatian" +msgstr "ಕ್ರೊಯೇಶಿಯನ್" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "ಹಂಗೇರಿಯನ್" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "" + +msgid "Indonesian" +msgstr "ಇಂಡೋನಿಶಿಯನ್" + +msgid "Ido" +msgstr "" + +msgid "Icelandic" +msgstr "ಐಸ್‌ಲ್ಯಾಂಡಿಕ್" + +msgid "Italian" +msgstr "ಇಟಾಲಿಯನ್" + +msgid "Japanese" +msgstr "ಜಾಪನೀಸ್" + +msgid "Georgian" +msgstr "ಜಾರ್ಜೆಯನ್ " + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "" + +msgid "Khmer" +msgstr "ಖಮೇರ್" + +msgid "Kannada" +msgstr "ಕನ್ನಡ" + +msgid "Korean" +msgstr "ಕೊರಿಯನ್" + +msgid "Luxembourgish" +msgstr "" + +msgid "Lithuanian" +msgstr "ಲಿತುವಾನಿಯನ್ " + +msgid "Latvian" +msgstr "ಲಾಟ್ವಿಯನ್" + +msgid "Macedonian" +msgstr "ಮೆಸಡೊನಿಯನ್" + +msgid "Malayalam" +msgstr "ಮಲಯಾಳಂ" + +msgid "Mongolian" +msgstr "ಮಂಗೊಲಿಯನ್" + +msgid "Marathi" +msgstr "" + +msgid "Burmese" +msgstr "" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "" + +msgid "Dutch" +msgstr "ಡಚ್" + +msgid "Norwegian Nynorsk" +msgstr "ನಾರ್ವೇಜಿಯನ್ ನಿನೋರ್ಕ್" + +msgid "Ossetic" +msgstr "" + +msgid "Punjabi" +msgstr "ಪಂಜಾಬಿ" + +msgid "Polish" +msgstr "ಪೋಲಿಷ್" + +msgid "Portuguese" +msgstr "ಪೋರ್ಚುಗೀಸ್" + +msgid "Brazilian Portuguese" +msgstr "ಬ್ರಜೀಲಿಯನ್ ಪೋರ್ಚುಗೀಸ್" + +msgid "Romanian" +msgstr "ರೋಮೇನಿಯನ್" + +msgid "Russian" +msgstr "ರಶಿಯನ್" + +msgid "Slovak" +msgstr "ಸ್ಲೋವಾಕ್" + +msgid "Slovenian" +msgstr "ಸ್ಲೋವೇನಿಯನ್" + +msgid "Albanian" +msgstr "ಅಲ್ಬೆನಿಯನ್ " + +msgid "Serbian" +msgstr "ಸರ್ಬಿಯನ್" + +msgid "Serbian Latin" +msgstr "ಸರ್ಬಿಯನ್ ಲ್ಯಾಟಿನ್" + +msgid "Swedish" +msgstr "ಸ್ವೀಡಿಷ್" + +msgid "Swahili" +msgstr "" + +msgid "Tamil" +msgstr "ತಮಿಳು" + +msgid "Telugu" +msgstr "ತೆಲುಗು" + +msgid "Thai" +msgstr "ಥಾಯ್" + +msgid "Turkish" +msgstr "ಟರ್ಕಿಶ್" + +msgid "Tatar" +msgstr "" + +msgid "Udmurt" +msgstr "" + +msgid "Ukrainian" +msgstr "ಉಕ್ರೇನಿಯನ್" + +msgid "Urdu" +msgstr "ಉರ್ದು" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "ವಿಯೆತ್ನಾಮೀಸ್" + +msgid "Simplified Chinese" +msgstr "ಸರಳೀಕೃತ ಚೈನೀಸ್" + +msgid "Traditional Chinese" +msgstr "ಸಂಪ್ರದಾಯಿಕ ಚೈನೀಸ್ " + +msgid "Messages" +msgstr "" + +msgid "Site Maps" +msgstr "" + +msgid "Static Files" +msgstr "" + +msgid "Syndication" +msgstr "" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "ಸಿಂಧುವಾದ ಮೌಲ್ಯವನ್ನು ನಮೂದಿಸಿ." + +msgid "Enter a valid URL." +msgstr "ಸರಿಯಾದ ಒಂದು URL ಅನ್ನು ನಮೂದಿಸಿ." + +msgid "Enter a valid integer." +msgstr "" + +msgid "Enter a valid email address." +msgstr "" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "ಒಂದು ಸರಿಯಾದ IPv4 ವಿಳಾಸವನ್ನು ನಮೂದಿಸಿ." + +msgid "Enter a valid IPv6 address." +msgstr "ಮಾನ್ಯವಾದ IPv6 ವಿಳಾಸ ದಾಖಲಿಸಿ" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "ಮಾನ್ಯವಾದ IPv4 ಅಥವಾ IPv6 ವಿಳಾಸ ದಾಖಲಿಸಿ" + +msgid "Enter only digits separated by commas." +msgstr "ಅಲ್ಪವಿರಾಮ(,)ಗಳಿಂದ ಬೇರ್ಪಟ್ಟ ಅಂಕೆಗಳನ್ನು ಮಾತ್ರ ಬರೆಯಿರಿ." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"ಈ ಮೌಲ್ಯವು %(limit_value)s ಆಗಿದೆ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ (ಇದು %(show_value)s ಆಗಿದೆ)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" +"ಈ ಮೌಲ್ಯವು %(limit_value)s ಕ್ಕಿಂತ ಕಡಿಮೆಯ ಅಥವ ಸಮನಾದ ಮೌಲ್ಯವಾಗಿದೆ ಎಂದು ಖಾತ್ರಿ " +"ಮಾಡಿಕೊಳ್ಳಿ." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" +"ಈ ಮೌಲ್ಯವು %(limit_value)s ಕ್ಕಿಂತ ಹೆಚ್ಚಿನ ಅಥವ ಸಮನಾದ ಮೌಲ್ಯವಾಗಿದೆ ಎಂದು ಖಾತ್ರಿ " +"ಮಾಡಿಕೊಳ್ಳಿ." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Enter a number." +msgstr "ಒಂದು ಸಂಖ್ಯೆಯನ್ನು ನಮೂದಿಸಿ." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "ಮತ್ತು" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "ಈ ಅಂಶವನ್ನು ಖಾಲಿ ಬಿಡುವಂತಿಲ್ಲ." + +msgid "This field cannot be blank." +msgstr "ಈ ಸ್ಥಳವು ಖಾಲಿ ಇರುವಂತಿಲ್ಲ." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "" +"ಈ %(field_label)s ಅನ್ನು ಹೊಂದಿರುವ ಒಂದು %(model_name)s ಈಗಾಗಲೆ ಅಸ್ತಿತ್ವದಲ್ಲಿದೆ." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "ಕ್ಷೇತ್ರದ ಬಗೆ: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "ಬೂಲಿಯನ್ (ಹೌದು ಅಥವ ಅಲ್ಲ)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "ಪದಪುಂಜ (%(max_length)s ವರೆಗೆ)" + +msgid "Comma-separated integers" +msgstr "ಅಲ್ಪವಿರಾಮ(,) ದಿಂದ ಬೇರ್ಪಟ್ಟ ಪೂರ್ಣಸಂಖ್ಯೆಗಳು" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "ದಿನಾಂಕ (ಸಮಯವಿಲ್ಲದೆ)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "ದಿನಾಂಕ (ಸಮಯದೊಂದಿಗೆ)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "ದಶಮಾನ ಸಂಖ್ಯೆ" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "" + +msgid "Email address" +msgstr "" + +msgid "File path" +msgstr "ಕಡತದ ಸ್ಥಾನಪಥ" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "ತೇಲುವ-ಬಿಂದು ಸಂಖ್ಯೆ" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "ಪೂರ್ಣಾಂಕ" + +msgid "Big (8 byte) integer" +msgstr "ಬೃಹತ್ (೮ ಬೈಟ್) ಪೂರ್ಣ ಸಂಖ್ಯೆ" + +msgid "IPv4 address" +msgstr "IPv4 ವಿಳಾಸ" + +msgid "IP address" +msgstr "IP ವಿಳಾಸ" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "ಬೂಲಿಯನ್ (ನಿಜ, ಸುಳ್ಳು ಅಥವ ಯಾವುದೂ ಅಲ್ಲ ಇವುಗಳಲ್ಲಿ ಒಂದು)" + +msgid "Positive integer" +msgstr "" + +msgid "Positive small integer" +msgstr "" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "" + +msgid "Small integer" +msgstr "" + +msgid "Text" +msgstr "ಪಠ್ಯ" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "ಸಮಯ" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "" + +msgid "Image" +msgstr "" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "ಬಾಹ್ಯ ಕೀಲಿ (ಸಂಬಂಧಿತ ಸ್ಥಳದಿಂದ ಪ್ರಕಾರವನ್ನು ನಿರ್ಧರಿಸಲಾಗುತ್ತದೆ)" + +msgid "One-to-one relationship" +msgstr "ಒನ್-ಟು-ಒನ್ (ಪರಸ್ಪರ) ಸಂಬಂಧ" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "ಮೆನಿ-ಟು-ಮೆನಿ (ಸಾರ್ವಜನಿಕ) ಸಂಬಂಧ" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr "" + +msgid "This field is required." +msgstr "ಈ ಸ್ಥಳವು ಅಗತ್ಯವಿರುತ್ತದೆ." + +msgid "Enter a whole number." +msgstr "ಪೂರ್ಣಾಂಕವೊಂದನ್ನು ನಮೂದಿಸಿ." + +msgid "Enter a valid date." +msgstr "ಸರಿಯಾದ ದಿನಾಂಕವನ್ನು ನಮೂದಿಸಿ." + +msgid "Enter a valid time." +msgstr "ಸರಿಯಾದ ಸಮಯವನ್ನು ನಮೂದಿಸಿ." + +msgid "Enter a valid date/time." +msgstr "ಸರಿಯಾದ ದಿನಾಂಕ/ಸಮಯವನ್ನು ನಮೂದಿಸಿ." + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" +"ಯಾವದೇ ಕಡತವನ್ನೂ ಸಲ್ಲಿಸಲಾಗಿಲ್ಲ. ನಮೂನೆಯ ಮೇಲಿನ ಸಂಕೇತೀಕರಣ (ಎನ್ಕೋಡಿಂಗ್) ಬಗೆಯನ್ನು " +"ಪರೀಕ್ಷಿಸಿ." + +msgid "No file was submitted." +msgstr "ಯಾವದೇ ಕಡತವನ್ನೂ ಸಲ್ಲಿಸಲಾಗಿಲ್ಲ." + +msgid "The submitted file is empty." +msgstr "ಸಲ್ಲಿಸಲಾದ ಕಡತ ಖಾಲಿ ಇದೆ." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"ದಯವಿಟ್ಟು ಕಡತವನ್ನು ಸಲ್ಲಿಸಿ ಅಥವ ಅಳಿಸುವ ಗುರುತುಚೌಕವನ್ನು ಗುರುತು ಹಾಕಿ, ಎರಡನ್ನೂ ಒಟ್ಟಿಗೆ " +"ಮಾಡಬೇಡಿ." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"ಸರಿಯಾದ ಚಿತ್ರವನ್ನು ಸೇರಿಸಿ. ನೀವು ಸೇರಿಸಿದ ಕಡತವು ಚಿತ್ರವೇ ಅಲ್ಲ ಅಥವಾ ಅದು ಒಂದು ಹಾಳಾದ " +"ಚಿತ್ರವಾಗಿದೆ. " + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "ಸರಿಯಾದ ಒಂದು ಆಯ್ಕೆಯನ್ನು ಆರಿಸಿ. %(value)s ಎನ್ನುವುದು ಲಭ್ಯವಿರುವ ಆಯ್ಕೆಗಳಲ್ಲಿ ಇಲ್ಲ." + +msgid "Enter a list of values." +msgstr "ಮೌಲ್ಯಗಳ ಒಂದು ಪಟ್ಟಿಯನ್ನು ನಮೂದಿಸಿ." + +msgid "Enter a complete value." +msgstr "" + +msgid "Enter a valid UUID." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr "" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "ಕ್ರಮ" + +msgid "Delete" +msgstr "ಅಳಿಸಿಹಾಕಿ" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "%(field)s ಗಾಗಿ ಎರಡು ಬಾರಿ ನಮೂದಿಸಲಾದ ಮಾಹಿತಿಯನ್ನು ಸರಿಪಡಿಸಿ." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"%(field)s ಗಾಗಿ ಎರಡು ಬಾರಿ ನಮೂದಿಸಲಾದ ಮಾಹಿತಿಯನ್ನು ಸರಿಪಡಿಸಿ, ಇದರ ಮೌಲ್ಯವು " +"ವಿಶಿಷ್ಟವಾಗಿರಬೇಕು." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"%(field_name)s ಗಾಗಿ ಎರಡು ಬಾರಿ ನಮೂದಿಸಲಾದ ಮಾಹಿತಿಯನ್ನು ಸರಿಪಡಿಸಿ, %(date_field)s " +"ನಲ್ಲಿನ %(lookup)s ಗಾಗಿ ಇದರ ಮೌಲ್ಯವು ವಿಶಿಷ್ಟವಾಗಿರಬೇಕು." + +msgid "Please correct the duplicate values below." +msgstr "ದಯವಿಟ್ಟು ಈ ಕೆಳಗೆ ಎರಡು ಬಾರಿ ನಮೂದಿಸಲಾದ ಮೌಲ್ಯವನ್ನು ಸರಿಪಡಿಸಿ." + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "ಸರಿಯಾದ ಒಂದು ಆಯ್ಕೆಯನ್ನು ಆರಿಸಿ. ಆ ಆಯ್ಕೆಯು ಲಭ್ಯವಿರುವ ಆಯ್ಕೆಗಳಲ್ಲಿ ಇಲ್ಲ." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "ಮುಕ್ತಗೊಳಿಸು" + +msgid "Currently" +msgstr "ಪ್ರಸಕ್ತ" + +msgid "Change" +msgstr "ಬದಲಾವಣೆ" + +msgid "Unknown" +msgstr "ಗೊತ್ತಿರದ" + +msgid "Yes" +msgstr "ಹೌದು" + +msgid "No" +msgstr "ಇಲ್ಲ" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "ಹೌದು,ಇಲ್ಲ,ಇರಬಹುದು" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d ಬೈಟ್‌ಗಳು" +msgstr[1] "%(size)d ಬೈಟ್‌ಗಳು" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "ಅಪರಾಹ್ನ" + +msgid "a.m." +msgstr "ಪೂರ್ವಾಹ್ನ" + +msgid "PM" +msgstr "ಅಪರಾಹ್ನ" + +msgid "AM" +msgstr "ಪೂರ್ವಾಹ್ನ" + +msgid "midnight" +msgstr "ಮಧ್ಯರಾತ್ರಿ" + +msgid "noon" +msgstr "ಮಧ್ಯಾಹ್ನ" + +msgid "Monday" +msgstr "ಸೋಮವಾರ" + +msgid "Tuesday" +msgstr "ಮಂಗಳವಾರ" + +msgid "Wednesday" +msgstr "ಬುಧವಾರ" + +msgid "Thursday" +msgstr "ಗುರುವಾರ" + +msgid "Friday" +msgstr "ಶುಕ್ರವಾರ" + +msgid "Saturday" +msgstr "ಶನಿವಾರ" + +msgid "Sunday" +msgstr "ರವಿವಾರ" + +msgid "Mon" +msgstr "ಸೋಮ" + +msgid "Tue" +msgstr "ಮಂಗಳ" + +msgid "Wed" +msgstr "ಬುಧ" + +msgid "Thu" +msgstr "ಗುರು" + +msgid "Fri" +msgstr "ಶುಕ್ರ" + +msgid "Sat" +msgstr "ಶನಿ" + +msgid "Sun" +msgstr "ರವಿ" + +msgid "January" +msgstr "ಜನವರಿ" + +msgid "February" +msgstr "ಫೆಬ್ರುವರಿ" + +msgid "March" +msgstr "ಮಾರ್ಚ್" + +msgid "April" +msgstr "ಎಪ್ರಿಲ್" + +msgid "May" +msgstr "ಮೇ" + +msgid "June" +msgstr "ಜೂನ್" + +msgid "July" +msgstr "ಜುಲೈ" + +msgid "August" +msgstr "ಆಗಸ್ಟ್" + +msgid "September" +msgstr "ಸೆಪ್ಟೆಂಬರ್" + +msgid "October" +msgstr "ಅಕ್ಟೋಬರ್" + +msgid "November" +msgstr "ನವೆಂಬರ್" + +msgid "December" +msgstr "ಡಿಸೆಂಬರ್" + +msgid "jan" +msgstr "ಜನವರಿ" + +msgid "feb" +msgstr "ಫೆಬ್ರವರಿ" + +msgid "mar" +msgstr "ಮಾರ್ಚ್" + +msgid "apr" +msgstr "ಏಪ್ರಿಲ್" + +msgid "may" +msgstr "ಮೇ" + +msgid "jun" +msgstr "ಜೂನ್" + +msgid "jul" +msgstr "ಜುಲೈ" + +msgid "aug" +msgstr "ಆಗಸ್ಟ್‍" + +msgid "sep" +msgstr "ಸೆಪ್ಟೆಂಬರ್" + +msgid "oct" +msgstr "ಅಕ್ಟೋಬರ್" + +msgid "nov" +msgstr "ನವೆಂಬರ್" + +msgid "dec" +msgstr "ಡಿಸೆಂಬರ್" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "ಜನ." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "ಫೆಬ್ರ." + +msgctxt "abbrev. month" +msgid "March" +msgstr "ಮಾರ್ಚ್" + +msgctxt "abbrev. month" +msgid "April" +msgstr "ಏಪ್ರಿಲ್" + +msgctxt "abbrev. month" +msgid "May" +msgstr "ಮೇ" + +msgctxt "abbrev. month" +msgid "June" +msgstr "ಜೂನ್" + +msgctxt "abbrev. month" +msgid "July" +msgstr "ಜುಲೈ" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "ಆಗ." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "ಸೆಪ್ಟೆ." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "ಅಕ್ಟೋ." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "ನವೆಂ." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "ಡಿಸೆಂ." + +msgctxt "alt. month" +msgid "January" +msgstr "ಜನವರಿ" + +msgctxt "alt. month" +msgid "February" +msgstr "ಫೆಬ್ರವರಿ" + +msgctxt "alt. month" +msgid "March" +msgstr "ಮಾರ್ಚ್" + +msgctxt "alt. month" +msgid "April" +msgstr "ಏಪ್ರಿಲ್" + +msgctxt "alt. month" +msgid "May" +msgstr "ಮೇ" + +msgctxt "alt. month" +msgid "June" +msgstr "ಜೂನ್" + +msgctxt "alt. month" +msgid "July" +msgstr "ಜುಲೈ" + +msgctxt "alt. month" +msgid "August" +msgstr "ಆಗಸ್ಟ್‍" + +msgctxt "alt. month" +msgid "September" +msgstr "ಸಪ್ಟೆಂಬರ್" + +msgctxt "alt. month" +msgid "October" +msgstr "ಅಕ್ಟೋಬರ್" + +msgctxt "alt. month" +msgid "November" +msgstr "ನವೆಂಬರ್" + +msgctxt "alt. month" +msgid "December" +msgstr "ಡಿಸೆಂಬರ್" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "ಅಥವ" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" + +msgid "0 minutes" +msgstr "" + +msgid "Forbidden" +msgstr "" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "ಯಾವುದೆ ವರ್ಷವನ್ನು ಸೂಚಿಲಾಗಿಲ್ಲ" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "ಯಾವುದೆ ತಿಂಗಳನ್ನು ಸೂಚಿಸಲಾಗಿಲ್ಲ" + +msgid "No day specified" +msgstr "ಯಾವುದೆ ದಿನವನ್ನು ಸೂಚಿಸಲಾಗಿಲ್ಲ" + +msgid "No week specified" +msgstr "ಯಾವುದೆ ವಾರವನ್ನು ಸೂಚಿಸಲಾಗಿಲ್ಲ" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "ಯಾವುದೆ %(verbose_name_plural)s ಲಭ್ಯವಿಲ್ಲ" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"ಭವಿಷ್ಯದ %(verbose_name_plural)s ಲಭ್ಯವಿಲ್ಲ ಏಕೆಂದರೆ %(class_name)s.allow_future " +"ಎನ್ನುವುದು ಅಸತ್ಯವಾಗಿದೆ (ಫಾಲ್ಸ್‍) ಆಗಿದೆ." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "ಮನವಿಗೆ ತಾಳೆಯಾಗುವ ಯಾವುದೆ %(verbose_name)s ಕಂಡುಬಂದಿಲ್ಲ" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "" + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/kn/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/kn/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/kn/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/kn/formats.py new file mode 100644 index 0000000..d212fd5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/kn/formats.py @@ -0,0 +1,21 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j F Y" +TIME_FORMAT = "h:i A" +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "j M Y" +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +# DECIMAL_SEPARATOR = +# THOUSAND_SEPARATOR = +# NUMBER_GROUPING = diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ko/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ko/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0aaf757 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ko/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ko/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ko/LC_MESSAGES/django.po new file mode 100644 index 0000000..52832dc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ko/LC_MESSAGES/django.po @@ -0,0 +1,1322 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# BJ Jang , 2014 +# JunGu Kang , 2017 +# Jiyoon, Ha , 2016 +# DONGHO JEONG , 2020 +# Park Hyunwoo , 2017 +# Geonho Kim / Leo Kim , 2019 +# hoseung2 , 2017 +# Ian Y. Choi , 2015 +# Jaehong Kim , 2011 +# Jannis Leidel , 2011 +# Jay Oh , 2020 +# Le Tartuffe , 2014,2016 +# Jonghwa Seo , 2019 +# Jubeen Lee , 2020 +# JuneHyeon Bae , 2014 +# JunGu Kang , 2015 +# JunGu Kang , 2019 +# Kagami Sascha Rosylight , 2017 +# Mariusz Felisiak , 2021 +# Seho Noh , 2018 +# Seoeun(Sun☀️) Hong, 2023 +# Subin Choi , 2016 +# Taesik Yoon , 2015 +# 정훈 이, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Seoeun(Sun☀️) Hong, 2023\n" +"Language-Team: Korean (http://app.transifex.com/django/django/language/ko/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ko\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Afrikaans" +msgstr "아프리칸스어" + +msgid "Arabic" +msgstr "아랍어" + +msgid "Algerian Arabic" +msgstr "알제리 아랍어" + +msgid "Asturian" +msgstr "호주어" + +msgid "Azerbaijani" +msgstr "아제르바이잔어" + +msgid "Bulgarian" +msgstr "불가리어" + +msgid "Belarusian" +msgstr "벨라루스어" + +msgid "Bengali" +msgstr "방글라데시어" + +msgid "Breton" +msgstr "브르타뉴어" + +msgid "Bosnian" +msgstr "보스니아어" + +msgid "Catalan" +msgstr "카탈로니아어" + +msgid "Central Kurdish (Sorani)" +msgstr "중부 쿠르드어 (소라니어)" + +msgid "Czech" +msgstr "체코어" + +msgid "Welsh" +msgstr "웨일즈어" + +msgid "Danish" +msgstr "덴마크어" + +msgid "German" +msgstr "독일어" + +msgid "Lower Sorbian" +msgstr "저지 소르브어" + +msgid "Greek" +msgstr "그리스어" + +msgid "English" +msgstr "영어" + +msgid "Australian English" +msgstr "영어(호주)" + +msgid "British English" +msgstr "영어 (영국)" + +msgid "Esperanto" +msgstr "에스페란토어" + +msgid "Spanish" +msgstr "스페인어" + +msgid "Argentinian Spanish" +msgstr "아르헨티나 스페인어" + +msgid "Colombian Spanish" +msgstr "콜롬비아 스페인어" + +msgid "Mexican Spanish" +msgstr "멕시컨 스페인어" + +msgid "Nicaraguan Spanish" +msgstr "니카과라 스페인어" + +msgid "Venezuelan Spanish" +msgstr "베네수엘라 스페인어" + +msgid "Estonian" +msgstr "에스토니아어" + +msgid "Basque" +msgstr "바스크어" + +msgid "Persian" +msgstr "페르시아어" + +msgid "Finnish" +msgstr "핀란드어" + +msgid "French" +msgstr "프랑스어" + +msgid "Frisian" +msgstr "프리슬란트어" + +msgid "Irish" +msgstr "아일랜드어" + +msgid "Scottish Gaelic" +msgstr "스코틀랜드 게일어" + +msgid "Galician" +msgstr "갈리시아어" + +msgid "Hebrew" +msgstr "히브리어" + +msgid "Hindi" +msgstr "힌두어" + +msgid "Croatian" +msgstr "크로아티아어" + +msgid "Upper Sorbian" +msgstr "고지 소르브어" + +msgid "Hungarian" +msgstr "헝가리어" + +msgid "Armenian" +msgstr "아르메니아어" + +msgid "Interlingua" +msgstr "인테르링구아어" + +msgid "Indonesian" +msgstr "인도네시아어" + +msgid "Igbo" +msgstr "이그보어" + +msgid "Ido" +msgstr "이도어" + +msgid "Icelandic" +msgstr "아이슬란드어" + +msgid "Italian" +msgstr "이탈리아어" + +msgid "Japanese" +msgstr "일본어" + +msgid "Georgian" +msgstr "조지아어" + +msgid "Kabyle" +msgstr "커바일어" + +msgid "Kazakh" +msgstr "카자흐어" + +msgid "Khmer" +msgstr "크메르어" + +msgid "Kannada" +msgstr "칸나다어" + +msgid "Korean" +msgstr "한국어" + +msgid "Kyrgyz" +msgstr "키르키즈 공화국어" + +msgid "Luxembourgish" +msgstr "룩셈부르크" + +msgid "Lithuanian" +msgstr "리투아니아어" + +msgid "Latvian" +msgstr "라트비아어" + +msgid "Macedonian" +msgstr "마케도니아어" + +msgid "Malayalam" +msgstr "말라얄람어" + +msgid "Mongolian" +msgstr "몽고어" + +msgid "Marathi" +msgstr "마라티어" + +msgid "Malay" +msgstr "말레이시아어" + +msgid "Burmese" +msgstr "룩셈부르크어" + +msgid "Norwegian Bokmål" +msgstr "노르웨이어(보크몰)" + +msgid "Nepali" +msgstr "네팔어" + +msgid "Dutch" +msgstr "네덜란드어" + +msgid "Norwegian Nynorsk" +msgstr "노르웨이어 (뉘노르스크)" + +msgid "Ossetic" +msgstr "오세티아어" + +msgid "Punjabi" +msgstr "펀자브어" + +msgid "Polish" +msgstr "폴란드어" + +msgid "Portuguese" +msgstr "포르투갈어" + +msgid "Brazilian Portuguese" +msgstr "브라질 포르투갈어" + +msgid "Romanian" +msgstr "루마니아어" + +msgid "Russian" +msgstr "러시아어" + +msgid "Slovak" +msgstr "슬로바키아어" + +msgid "Slovenian" +msgstr "슬로베니아어" + +msgid "Albanian" +msgstr "알바니아어" + +msgid "Serbian" +msgstr "세르비아어" + +msgid "Serbian Latin" +msgstr "세르비아어" + +msgid "Swedish" +msgstr "스웨덴어" + +msgid "Swahili" +msgstr "스와힐리어" + +msgid "Tamil" +msgstr "타밀어" + +msgid "Telugu" +msgstr "텔루구어" + +msgid "Tajik" +msgstr "타지크어" + +msgid "Thai" +msgstr "태국어" + +msgid "Turkmen" +msgstr "튀르크멘어" + +msgid "Turkish" +msgstr "터키어" + +msgid "Tatar" +msgstr "타타르" + +msgid "Udmurt" +msgstr "이제프스크" + +msgid "Uyghur" +msgstr "" + +msgid "Ukrainian" +msgstr "우크라이나어" + +msgid "Urdu" +msgstr "우르드어" + +msgid "Uzbek" +msgstr "우즈베크어" + +msgid "Vietnamese" +msgstr "베트남어" + +msgid "Simplified Chinese" +msgstr "중국어 간체" + +msgid "Traditional Chinese" +msgstr "중국어 번체" + +msgid "Messages" +msgstr "메시지" + +msgid "Site Maps" +msgstr "사이트 맵" + +msgid "Static Files" +msgstr "정적 파일" + +msgid "Syndication" +msgstr "신디케이션" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "..." + +msgid "That page number is not an integer" +msgstr "페이지 번호가 정수가 아닙니다." + +msgid "That page number is less than 1" +msgstr "페이지 번호가 1보다 작습니다." + +msgid "That page contains no results" +msgstr "해당 페이지에 결과가 없습니다." + +msgid "Enter a valid value." +msgstr "올바른 값을 입력하세요." + +msgid "Enter a valid URL." +msgstr "올바른 URL을 입력하세요." + +msgid "Enter a valid integer." +msgstr "올바른 정수를 입력하세요." + +msgid "Enter a valid email address." +msgstr "올바른 이메일 주소를 입력하세요." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "문자, 숫자, '_', '-'만 가능합니다." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"유니코드 문자, 숫자, 언더스코어 또는 하이픈으로 구성된 올바른 내용을 입력하세" +"요." + +msgid "Enter a valid IPv4 address." +msgstr "올바른 IPv4 주소를 입력하세요." + +msgid "Enter a valid IPv6 address." +msgstr "올바른 IPv6 주소를 입력하세요." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "올바른 IPv4 혹은 IPv6 주소를 입력하세요." + +msgid "Enter only digits separated by commas." +msgstr "콤마로 구분된 숫자만 입력하세요." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"%(limit_value)s 안의 값을 입력해 주세요. (입력하신 값은 %(show_value)s입니" +"다.)" + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "%(limit_value)s 이하의 값을 입력해 주세요." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "%(limit_value)s 이상의 값을 입력해 주세요." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"이 값이 최소 %(limit_value)d 개의 글자인지 확인하세요(입력값 %(show_value)d " +"자)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"이 값이 최대 %(limit_value)d 개의 글자인지 확인하세요(입력값 %(show_value)d " +"자)." + +msgid "Enter a number." +msgstr "숫자를 입력하세요." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "전체 자릿수가 %(max)s 개를 넘지 않도록 해주세요." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "전체 유효자리 개수가 %(max)s 개를 넘지 않도록 해주세요." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "전체 유효자리 개수가 %(max)s 개를 넘지 않도록 해주세요." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"파일 확장자 '%(extension)s'는 허용되지 않습니다. 허용된 확장자: " +"'%(allowed_extensions)s'." + +msgid "Null characters are not allowed." +msgstr "null 문자는 사용할 수 없습니다. " + +msgid "and" +msgstr "또한" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s의 %(field_labels)s 은/는 이미 존재합니다." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "%(name)s을(를) 위반하였습니다." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "%(value)r 은/는 올바른 선택사항이 아닙니다." + +msgid "This field cannot be null." +msgstr "이 필드는 null 값을 사용할 수 없습니다. " + +msgid "This field cannot be blank." +msgstr "이 필드는 빈 칸으로 둘 수 없습니다." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s의 %(field_label)s은/는 이미 존재합니다." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s은/는 반드시 %(date_field_label)s %(lookup_type)s에 대해 유일" +"해야 합니다." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "%(field_type)s 형식 필드" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "'%(value)s' 값은 반드시 True 또는 False 중 하나여야만 합니다." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "'%(value)s'값은 반드시 True, False, None 중 하나여야만 합니다." + +msgid "Boolean (Either True or False)" +msgstr "boolean(True 또는 False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "문자열(%(max_length)s 글자까지)" + +msgid "String (unlimited)" +msgstr "" + +msgid "Comma-separated integers" +msgstr "정수(콤마로 구분)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "'%(value)s' 값은 날짜 형식이 아닙니다. YYYY-MM-DD 형식이어야 합니다." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"'%(value)s' 값은 올바른 형식(YYYY-MM-DD)이지만 유효하지 않은 날짜입니다." + +msgid "Date (without time)" +msgstr "날짜(시간 제외)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"'%(value)s' 값은 올바르지 않은 형식입니다. YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ] 형식이어야 합니다." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"'%(value)s' 값은 올바른 형식이지만 (YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) 유효" +"하지 않은 날짜/시간입니다." + +msgid "Date (with time)" +msgstr "날짜(시간 포함)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "'%(value)s' 값은 10진수를 입력하여야 합니다." + +msgid "Decimal number" +msgstr "10진수" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"'%(value)s' 값은 올바르지 않은 형식입니다. [DD] [HH:[MM:]]ss[.uuuuuu] 형식이" +"어야 합니다." + +msgid "Duration" +msgstr "지속시간" + +msgid "Email address" +msgstr "이메일 주소" + +msgid "File path" +msgstr "파일 경로" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "\"%(value)s\" 값은 실수를 입력하여야 합니다." + +msgid "Floating point number" +msgstr "부동소수점 숫자" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "\"%(value)s\" 값은 정수를 입력하여야 합니다." + +msgid "Integer" +msgstr "정수" + +msgid "Big (8 byte) integer" +msgstr "큰 정수 (8 byte)" + +msgid "Small integer" +msgstr "작은 정수" + +msgid "IPv4 address" +msgstr "IPv4 주소" + +msgid "IP address" +msgstr "IP 주소" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "\"%(value)s\" 값은 반드시 None, True 또는 False이어야 합니다." + +msgid "Boolean (Either True, False or None)" +msgstr "boolean (True, False 또는 None)" + +msgid "Positive big integer" +msgstr "큰 양의 정수" + +msgid "Positive integer" +msgstr "양의 정수" + +msgid "Positive small integer" +msgstr "작은 양의 정수" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "슬러그(%(max_length)s 까지)" + +msgid "Text" +msgstr "텍스트" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"\"%(value)s\" 값의 형식이 올바르지 않습니다. HH:MM[:ss[.uuuuuu]] 형식이어야 " +"합니다." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"\"%(value)s\" 값이 올바른 형식(HH:MM[:ss[.uuuuuu]])이나, 유효하지 않은 시간 " +"값입니다." + +msgid "Time" +msgstr "시각" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Raw binary data" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "\"%(value)s\"은 유효하지 않은 UUID입니다." + +msgid "Universally unique identifier" +msgstr "범용 고유 식별 수단(UUID)" + +msgid "File" +msgstr "파일" + +msgid "Image" +msgstr "이미지" + +msgid "A JSON object" +msgstr "JSON 객체" + +msgid "Value must be valid JSON." +msgstr "올바른 JSON 형식이여야 합니다." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(field)s %(value)r 를 가지는 %(model)s 인스턴스가 존재하지 않습니다." + +msgid "Foreign Key (type determined by related field)" +msgstr "외래 키 (연관 필드에 의해 형식 결정)" + +msgid "One-to-one relationship" +msgstr "일대일 관계" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s 관계" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s 관계들" + +msgid "Many-to-many relationship" +msgstr "다대다 관계" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "필수 항목입니다." + +msgid "Enter a whole number." +msgstr "정수를 입력하세요." + +msgid "Enter a valid date." +msgstr "올바른 날짜를 입력하세요." + +msgid "Enter a valid time." +msgstr "올바른 시각을 입력하세요." + +msgid "Enter a valid date/time." +msgstr "올바른 날짜/시각을 입력하세요." + +msgid "Enter a valid duration." +msgstr "올바른 기간을 입력하세요." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "날짜는 {min_days}와 {max_days} 사이여야 합니다." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "등록된 파일이 없습니다. 인코딩 형식을 확인하세요." + +msgid "No file was submitted." +msgstr "파일이 전송되지 않았습니다." + +msgid "The submitted file is empty." +msgstr "입력하신 파일은 빈 파일입니다." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "파일이름의 길이가 최대 %(max)d 자인지 확인하세요(%(length)d 자)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"파일 업로드 또는 삭제 체크박스를 선택하세요. 동시에 둘 다 할 수는 없습니다." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"올바른 이미지를 업로드하세요. 업로드하신 파일은 이미지 파일이 아니거나 파일" +"이 깨져 있습니다." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "올바르게 선택해 주세요. %(value)s 이/가 선택가능항목에 없습니다." + +msgid "Enter a list of values." +msgstr "리스트를 입력하세요." + +msgid "Enter a complete value." +msgstr "완전한 값을 입력하세요." + +msgid "Enter a valid UUID." +msgstr "올바른 UUID를 입력하세요." + +msgid "Enter a valid JSON." +msgstr "올바른 JSON을 입력하세요." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(%(name)s hidden 필드) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"ManagementForm 데이터가 없거나 변경되었습니다. 현재 없는 필드: " +"%(field_names)s. 이런 이슈가 지속된다면 버그 리포트를 제출해주시기 바랍니다." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "최대 %(num)d개의 양식을 제출하세요." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "최소 %(num)d개의 양식을 제출하세요." + +msgid "Order" +msgstr "순서:" + +msgid "Delete" +msgstr "삭제" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "%(field)s의 중복된 데이터를 고쳐주세요." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "%(field)s의 중복된 데이터를 고쳐주세요. 유일한 값이어야 합니다." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"%(field_name)s의 값은 %(date_field)s의 %(lookup)s에 대해 유일해야 합니다. 중" +"복된 데이터를 고쳐주세요." + +msgid "Please correct the duplicate values below." +msgstr "아래의 중복된 값들을 고쳐주세요." + +msgid "The inline value did not match the parent instance." +msgstr "Inline 값이 부모 인스턴스와 일치하지 않습니다." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "올바르게 선택해 주세요. 선택하신 것이 선택가능항목에 없습니다." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "\"%(pk)s\" 은/는 유효한 값이 아닙니다." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s 은/는 %(current_timezone)s 시간대에서 해석될 수 없습니다; 정보" +"가 모호하거나 존재하지 않을 수 있습니다." + +msgid "Clear" +msgstr "취소" + +msgid "Currently" +msgstr "현재" + +msgid "Change" +msgstr "변경" + +msgid "Unknown" +msgstr "알 수 없습니다." + +msgid "Yes" +msgstr "예" + +msgid "No" +msgstr "아니오" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "예,아니오,아마도" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d 바이트" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "오후" + +msgid "a.m." +msgstr "오전" + +msgid "PM" +msgstr "오후" + +msgid "AM" +msgstr "오전" + +msgid "midnight" +msgstr "자정" + +msgid "noon" +msgstr "정오" + +msgid "Monday" +msgstr "월요일" + +msgid "Tuesday" +msgstr "화요일" + +msgid "Wednesday" +msgstr "수요일" + +msgid "Thursday" +msgstr "목요일" + +msgid "Friday" +msgstr "금요일" + +msgid "Saturday" +msgstr "토요일" + +msgid "Sunday" +msgstr "일요일" + +msgid "Mon" +msgstr "월요일" + +msgid "Tue" +msgstr "화요일" + +msgid "Wed" +msgstr "수요일" + +msgid "Thu" +msgstr "목요일" + +msgid "Fri" +msgstr "금요일" + +msgid "Sat" +msgstr "토요일" + +msgid "Sun" +msgstr "일요일" + +msgid "January" +msgstr "1월" + +msgid "February" +msgstr "2월" + +msgid "March" +msgstr "3월" + +msgid "April" +msgstr "4월" + +msgid "May" +msgstr "5월" + +msgid "June" +msgstr "6월" + +msgid "July" +msgstr "7월" + +msgid "August" +msgstr "8월" + +msgid "September" +msgstr "9월" + +msgid "October" +msgstr "10월" + +msgid "November" +msgstr "11월" + +msgid "December" +msgstr "12월" + +msgid "jan" +msgstr "1월" + +msgid "feb" +msgstr "2월" + +msgid "mar" +msgstr "3월" + +msgid "apr" +msgstr "4월" + +msgid "may" +msgstr "5월" + +msgid "jun" +msgstr "6월" + +msgid "jul" +msgstr "7월" + +msgid "aug" +msgstr "8월" + +msgid "sep" +msgstr "9월" + +msgid "oct" +msgstr "10월" + +msgid "nov" +msgstr "11월" + +msgid "dec" +msgstr "12월" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "1월" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "2월" + +msgctxt "abbrev. month" +msgid "March" +msgstr "3월" + +msgctxt "abbrev. month" +msgid "April" +msgstr "4월" + +msgctxt "abbrev. month" +msgid "May" +msgstr "5월" + +msgctxt "abbrev. month" +msgid "June" +msgstr "6월" + +msgctxt "abbrev. month" +msgid "July" +msgstr "7월" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "8월" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "9월" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "10월" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "11월" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "12월" + +msgctxt "alt. month" +msgid "January" +msgstr "1월" + +msgctxt "alt. month" +msgid "February" +msgstr "2월" + +msgctxt "alt. month" +msgid "March" +msgstr "3월" + +msgctxt "alt. month" +msgid "April" +msgstr "4월" + +msgctxt "alt. month" +msgid "May" +msgstr "5월" + +msgctxt "alt. month" +msgid "June" +msgstr "6월" + +msgctxt "alt. month" +msgid "July" +msgstr "7월" + +msgctxt "alt. month" +msgid "August" +msgstr "8월" + +msgctxt "alt. month" +msgid "September" +msgstr "9월" + +msgctxt "alt. month" +msgid "October" +msgstr "10월" + +msgctxt "alt. month" +msgid "November" +msgstr "11월" + +msgctxt "alt. month" +msgid "December" +msgstr "12월" + +msgid "This is not a valid IPv6 address." +msgstr "올바른 IPv6 주소가 아닙니다." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "또는" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d년" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d개월" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d주" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d일" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d시간" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d분" + +msgid "Forbidden" +msgstr "Forbidden" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF 검증에 실패했습니다. 요청을 중단하였습니다." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"이 메세지가 보이는 이유는 이 HTTPS 사이트가 당신의 웹 브라우저로부터 \"참조 " +"헤더\"를 요구하지만, 아무것도 받기 못하였기 때문입니다. 이 헤더는 보안상의 이" +"유로 필요하며, 당신의 웹 브라우저가 제3자에 의해 해킹당하고 있지 않다는 것을 " +"보장하기 위함입니다." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"만약 브라우저 설정에서 '참조' 헤더를 비활성화 시켰을 경우, 적어도 이 사이트" +"나 HTTPS 연결, '동일-출처' 요청에 대해서는 이를 다시 활성화 시키십시오. " + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"태그나 'Referrer-Policy: no-" +"referrer' 헤더를 포함하고 있다면, 제거해주시기 바랍니다. CSRF 방지를 위한 리" +"퍼러 검사를 위해 'Referer' 헤더가 필요합니다. 개인 정보에 대해 우려가 있는 경" +"우, 서드 파티 사이트에 대한 링크에 와 같은 대안을 사" +"용할 수 있습니다." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"이 메세지가 보이는 이유는 사이트가 폼을 제출할 때 CSRF 쿠키를 필요로 하기 때" +"문입니다. 이 쿠키는 보안상의 이유로 필요하며, 제3자에 의해 당신의 브라우저가 " +"해킹당하고 있지 않다는 것을 보장합니다." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"만약 브라우저 설정에서 쿠키를 비활성화 시켰을 경우, 적어도 이 사이트나 '동일-" +"출처' 요청에 대해서는 활성화 시키십시오." + +msgid "More information is available with DEBUG=True." +msgstr "DEBUG=True 로 더 많은 정보를 확인할 수 있습니다." + +msgid "No year specified" +msgstr "년도가 없습니다." + +msgid "Date out of range" +msgstr "유효 범위 밖의 날짜" + +msgid "No month specified" +msgstr "월이 없습니다." + +msgid "No day specified" +msgstr "날짜가 없습니다." + +msgid "No week specified" +msgstr "주가 없습니다." + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr " %(verbose_name_plural)s를 사용할 수 없습니다." + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Future 모듈 %(verbose_name_plural)s을 사용할 수 없습니다. %(class_name)s." +"allow_future가 False 입니다." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "날짜 문자열 '%(datestr)s'이 표준 형식 '%(format)s'과 다릅니다." + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "쿼리 결과에 %(verbose_name)s가 없습니다." + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "'마지막' 페이지가 아니거나, 정수형으로 변환할 수 없습니다." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Invalid page (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "빈 리스트이고 '%(class_name)s.allow_empty'가 False입니다." + +msgid "Directory indexes are not allowed here." +msgstr "디렉토리 인덱스는 이곳에 사용할 수 없습니다." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "\"%(path)s\" 이/가 존재하지 않습니다." + +#, python-format +msgid "Index of %(directory)s" +msgstr "Index of %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "성공적으로 설치되었습니다! 축하합니다!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Django %(version)s릴리스 노트 보기" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"이 페이지는 어떤 URL도 지정되지 않았고, settings 파일에 DEBUG=True가 설정되어 있을 때 표시됩니" +"다." + +msgid "Django Documentation" +msgstr "Django 문서" + +msgid "Topics, references, & how-to’s" +msgstr "주제, 레퍼런스, & 입문참조하다" + +msgid "Tutorial: A Polling App" +msgstr "튜토리얼: 폴링 애플리케이션" + +msgid "Get started with Django" +msgstr "Django와 함께 시작하기" + +msgid "Django Community" +msgstr "Django 커뮤니티" + +msgid "Connect, get help, or contribute" +msgstr "연결하고, 도움을 받거나 기여하기" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ko/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ko/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ko/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ko/formats.py new file mode 100644 index 0000000..1f3487c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ko/formats.py @@ -0,0 +1,54 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "Y년 n월 j일" +TIME_FORMAT = "A g:i" +DATETIME_FORMAT = "Y년 n월 j일 g:i A" +YEAR_MONTH_FORMAT = "Y년 n월" +MONTH_DAY_FORMAT = "n월 j일" +SHORT_DATE_FORMAT = "Y-n-j." +SHORT_DATETIME_FORMAT = "Y-n-j H:i" +# FIRST_DAY_OF_WEEK = + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# Kept ISO formats as they are in first position +DATE_INPUT_FORMATS = [ + "%Y-%m-%d", # '2006-10-25' + "%m/%d/%Y", # '10/25/2006' + "%m/%d/%y", # '10/25/06' + # "%b %d %Y", # 'Oct 25 2006' + # "%b %d, %Y", # 'Oct 25, 2006' + # "%d %b %Y", # '25 Oct 2006' + # "%d %b, %Y", #'25 Oct, 2006' + # "%B %d %Y", # 'October 25 2006' + # "%B %d, %Y", #'October 25, 2006' + # "%d %B %Y", # '25 October 2006' + # "%d %B, %Y", # '25 October, 2006' + "%Y년 %m월 %d일", # '2006년 10월 25일', with localized suffix. +] +TIME_INPUT_FORMATS = [ + "%H:%M:%S", # '14:30:59' + "%H:%M:%S.%f", # '14:30:59.000200' + "%H:%M", # '14:30' + "%H시 %M분 %S초", # '14시 30분 59초' + "%H시 %M분", # '14시 30분' +] +DATETIME_INPUT_FORMATS = [ + "%Y-%m-%d %H:%M:%S", # '2006-10-25 14:30:59' + "%Y-%m-%d %H:%M:%S.%f", # '2006-10-25 14:30:59.000200' + "%Y-%m-%d %H:%M", # '2006-10-25 14:30' + "%m/%d/%Y %H:%M:%S", # '10/25/2006 14:30:59' + "%m/%d/%Y %H:%M:%S.%f", # '10/25/2006 14:30:59.000200' + "%m/%d/%Y %H:%M", # '10/25/2006 14:30' + "%m/%d/%y %H:%M:%S", # '10/25/06 14:30:59' + "%m/%d/%y %H:%M:%S.%f", # '10/25/06 14:30:59.000200' + "%m/%d/%y %H:%M", # '10/25/06 14:30' + "%Y년 %m월 %d일 %H시 %M분 %S초", # '2006년 10월 25일 14시 30분 59초' + "%Y년 %m월 %d일 %H시 %M분", # '2006년 10월 25일 14시 30분' +] + +DECIMAL_SEPARATOR = "." +THOUSAND_SEPARATOR = "," +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ky/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ky/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f99fc90 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ky/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ky/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ky/LC_MESSAGES/django.po new file mode 100644 index 0000000..391196f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ky/LC_MESSAGES/django.po @@ -0,0 +1,1279 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Mariusz Felisiak , 2021 +# Soyuzbek Orozbek uulu , 2020-2021 +# Soyuzbek Orozbek uulu , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2021-11-27 14:11+0000\n" +"Last-Translator: Soyuzbek Orozbek uulu \n" +"Language-Team: Kyrgyz (http://www.transifex.com/django/django/language/ky/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ky\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Afrikaans" +msgstr "Африканча" + +msgid "Arabic" +msgstr "Арабча" + +msgid "Algerian Arabic" +msgstr "Алжир арабчасы" + +msgid "Asturian" +msgstr "Австрийче" + +msgid "Azerbaijani" +msgstr "Азерче" + +msgid "Bulgarian" +msgstr "Болгарча" + +msgid "Belarusian" +msgstr "Белорусча" + +msgid "Bengali" +msgstr "Бенгалча" + +msgid "Breton" +msgstr "Бретончо" + +msgid "Bosnian" +msgstr "Босния" + +msgid "Catalan" +msgstr "Каталан" + +msgid "Czech" +msgstr "Чехче" + +msgid "Welsh" +msgstr "Валлий" + +msgid "Danish" +msgstr "Данчийче" + +msgid "German" +msgstr "Немисче" + +msgid "Lower Sorbian" +msgstr "Сорб" + +msgid "Greek" +msgstr "Грекче" + +msgid "English" +msgstr "Англисче" + +msgid "Australian English" +msgstr "Авс. Англисчеси" + +msgid "British English" +msgstr "Бр. Англ." + +msgid "Esperanto" +msgstr "Есперанто" + +msgid "Spanish" +msgstr "Испанча" + +msgid "Argentinian Spanish" +msgstr "Арг. исп" + +msgid "Colombian Spanish" +msgstr "Колумб Испанчасы" + +msgid "Mexican Spanish" +msgstr "Мекс. исп" + +msgid "Nicaraguan Spanish" +msgstr "Никарагуа испанчасы" + +msgid "Venezuelan Spanish" +msgstr "Венесуела Испанчасы" + +msgid "Estonian" +msgstr "Эстон" + +msgid "Basque" +msgstr "Баск" + +msgid "Persian" +msgstr "Персче" + +msgid "Finnish" +msgstr "Финче" + +msgid "French" +msgstr "Французча" + +msgid "Frisian" +msgstr "Фризче" + +msgid "Irish" +msgstr "Ирланча" + +msgid "Scottish Gaelic" +msgstr "Шотланча" + +msgid "Galician" +msgstr "Галицианча" + +msgid "Hebrew" +msgstr "Жөөтчө" + +msgid "Hindi" +msgstr "Хиндче" + +msgid "Croatian" +msgstr "Хорватча" + +msgid "Upper Sorbian" +msgstr "Жогорку Сорбчо" + +msgid "Hungarian" +msgstr "Венгрче" + +msgid "Armenian" +msgstr "Арменче" + +msgid "Interlingua" +msgstr "Эл аралык" + +msgid "Indonesian" +msgstr "Индонезче" + +msgid "Igbo" +msgstr "Игбо" + +msgid "Ido" +msgstr "идо" + +msgid "Icelandic" +msgstr "Исландча" + +msgid "Italian" +msgstr "Итальянча" + +msgid "Japanese" +msgstr "Жапончо" + +msgid "Georgian" +msgstr "Грузинче" + +msgid "Kabyle" +msgstr "Кабилче" + +msgid "Kazakh" +msgstr "Казакча" + +msgid "Khmer" +msgstr "Кхмер" + +msgid "Kannada" +msgstr "Канадча" + +msgid "Korean" +msgstr "Корейче" + +msgid "Kyrgyz" +msgstr "Кыргызча" + +msgid "Luxembourgish" +msgstr "Люкцембургча" + +msgid "Lithuanian" +msgstr "Литвача" + +msgid "Latvian" +msgstr "Латвияча" + +msgid "Macedonian" +msgstr "Македончо" + +msgid "Malayalam" +msgstr "Малаяламча" + +msgid "Mongolian" +msgstr "Монголчо" + +msgid "Marathi" +msgstr "Марати" + +msgid "Malay" +msgstr "Малай" + +msgid "Burmese" +msgstr "Бурмача" + +msgid "Norwegian Bokmål" +msgstr "Норвег Бокмолчо" + +msgid "Nepali" +msgstr "Непалча" + +msgid "Dutch" +msgstr "Голландча" + +msgid "Norwegian Nynorsk" +msgstr "Норвегиялык нюнор" + +msgid "Ossetic" +msgstr "Оссетче" + +msgid "Punjabi" +msgstr "Пенжабча" + +msgid "Polish" +msgstr "Полякча" + +msgid "Portuguese" +msgstr "Португалча" + +msgid "Brazilian Portuguese" +msgstr "Бразилиялык португалчасы" + +msgid "Romanian" +msgstr "Румынча" + +msgid "Russian" +msgstr "Орусча" + +msgid "Slovak" +msgstr "Словакча" + +msgid "Slovenian" +msgstr "Словенияча" + +msgid "Albanian" +msgstr "Албанча" + +msgid "Serbian" +msgstr "Сербче" + +msgid "Serbian Latin" +msgstr "Серб латынчасы" + +msgid "Swedish" +msgstr "Шведче" + +msgid "Swahili" +msgstr "Свахилче" + +msgid "Tamil" +msgstr "Тамиль" + +msgid "Telugu" +msgstr "Телугу" + +msgid "Tajik" +msgstr "Тажикче" + +msgid "Thai" +msgstr "Тайча" + +msgid "Turkmen" +msgstr "Түркмөнчө" + +msgid "Turkish" +msgstr "Түркчө" + +msgid "Tatar" +msgstr "Татарча" + +msgid "Udmurt" +msgstr "Удмурча" + +msgid "Ukrainian" +msgstr "Украинче" + +msgid "Urdu" +msgstr "Урду" + +msgid "Uzbek" +msgstr "Өзбекче" + +msgid "Vietnamese" +msgstr "Вьетнамча" + +msgid "Simplified Chinese" +msgstr "Жеңилдетилген кытайча" + +msgid "Traditional Chinese" +msgstr "салттык кытайча" + +msgid "Messages" +msgstr "Билдирүүлөр" + +msgid "Site Maps" +msgstr "сайт картасы" + +msgid "Static Files" +msgstr "Туруктуу файлдар" + +msgid "Syndication" +msgstr "Синдикат" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "..." + +msgid "That page number is not an integer" +msgstr "Бул барактын номуру сан эмес" + +msgid "That page number is less than 1" +msgstr "Бул барактын номуру 1 ден кичине" + +msgid "That page contains no results" +msgstr "Бул баракта жыйынтык жок" + +msgid "Enter a valid value." +msgstr "Туура маани киргиз" + +msgid "Enter a valid URL." +msgstr "Туура URL киргиз" + +msgid "Enter a valid integer." +msgstr "Туура натурал сан тер." + +msgid "Enter a valid email address." +msgstr "Туура эдарек тер." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"ариптер, цифралар, дефис же астыңкы сызык камтыган туура слаг киргизиңиз." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Юникод символдор, цифралар, астыңкы сызыктар же дефис камтыган туурга слаг " +"киргизиңиз." + +msgid "Enter a valid IPv4 address." +msgstr "Туура IPv4 тер." + +msgid "Enter a valid IPv6 address." +msgstr "Туура IPv6 тер." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Туура IPv4 же IPv6 тер." + +msgid "Enter only digits separated by commas." +msgstr "Жалаң үтүр менен бөлүнгөн сан тер." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Бул маани %(limit_value)s ашпоосун текшериңиз (азыр %(show_value)s)" + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "%(limit_value)s карата кичине же барабар маани болгонун текшериңиз" + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "%(limit_value)s карата чоң же барабар маани болгонун текшериңиз" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Бул маани жок дегенде %(limit_value)dсимвол камтыганын текшериңиз (азыркысы " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Бул маани эң көп %(limit_value)dсимвол камтыганын текшериңиз (азыркысы " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Сан киргизиңиз." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Жалпысынан %(max)sорундан ашпоосун текшериңиз." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Жалпысынан ондук сандын%(max)s ашпоосун текшериңиз." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "Жалпысынан үтүргө чейин%(max)s ашпоосун текшериңиз." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"%(extension)sфайл кеңейтүүсү кабыл алынбайт. Кабыл алынгандар: " +"%(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Боштук кабыл алынбайт" + +msgid "and" +msgstr "жана" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s бул %(field_labels)s менен мурдатан эле бар" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "%(value)r мааниси туура эмес тандоо." + +msgid "This field cannot be null." +msgstr "Бул аймак жок маани албашы керек" + +msgid "This field cannot be blank." +msgstr "Бул аймак бош калбашы керек" + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s бул %(field_label)s менен мурдатан эле бар" + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s %(date_field_label)s %(lookup_type)s үчүн уникал болуусу " +"керек." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "аймактын түрү: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "“%(value)s” мааниси же True же False болуусу керек." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "“%(value)s” мааниси же True же False же None болуусу керек." + +msgid "Boolean (Either True or False)" +msgstr "Булен (Туура же Ката)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Сап (%(max_length)s чейин)" + +msgid "Comma-separated integers" +msgstr "үтүр менен бөлүнгөн сан" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"“%(value)s” мааниси туура эмес форматта. Ал ЖЖЖЖ-АА-КК форматта болуусу " +"керек." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "%(value)sмааниси туура (ЖЖЖЖ-АА-КК) форматта бирок ал күн туура эмес." + +msgid "Date (without time)" +msgstr "Күн (убакытсыз)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"“%(value)s” мааниси туура эмес форматта. Ал ЖЖЖЖ-АА-КК СС:ММ[сс[.дддддд]]" +"[УЗ] форматта болуусу керек." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"“%(value)s” мааниси туура форматта (ЖЖЖЖ-АА-КК СС:ММ[сс[.дддддд]][УЗ] ) " +"бирок ал күн/убакыт туура эмес." + +msgid "Date (with time)" +msgstr "Күн(убакыттуу)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "“%(value)s” мааниси ондук сан болушу керек." + +msgid "Decimal number" +msgstr "ондук сан" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"“%(value)s” мааниси туура эмес форматта. Ал [КК][[CC:]MM:]cc[.дддддд] " +"форматта болуусу керек." + +msgid "Duration" +msgstr "Мөөнөт" + +msgid "Email address" +msgstr "электрондук дарек" + +msgid "File path" +msgstr "файл жайгашуусу" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "“%(value)s” мааниси калкыган чекиттүү болуусу керек." + +msgid "Floating point number" +msgstr "калкыган чекит саны" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "“%(value)s” мааниси натуралдык сан болуусу керек." + +msgid "Integer" +msgstr "Натурал сан" + +msgid "Big (8 byte) integer" +msgstr "Чоң ( 8 байт) натурал сан" + +msgid "Small integer" +msgstr "кичине натурал сан" + +msgid "IPv4 address" +msgstr "IPv4 дареги" + +msgid "IP address" +msgstr "IP дареги" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "“%(value)s” мааниси же None же True же False болуусу керек." + +msgid "Boolean (Either True, False or None)" +msgstr "Булен(Туура же Жалган же Куру)" + +msgid "Positive big integer" +msgstr "Оң чоң натуралдык сан." + +msgid "Positive integer" +msgstr "оң сан" + +msgid "Positive small integer" +msgstr "кичине оң сан" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "слаг ( %(max_length)s чейин)" + +msgid "Text" +msgstr "сап" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"“%(value)s” мааниси туура эмес форматта. Ал СС:ММ[:сс[.ддддддд]] форматта " +"болуусу керек." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"“%(value)s” мааниси туура форматта (СС:ММ[:cc[.дддддд]]) бирок ал убакыт " +"туура эмес." + +msgid "Time" +msgstr "Убакыт" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "жалаң экилик берилиш" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "“%(value)s” туура эмес UUID." + +msgid "Universally unique identifier" +msgstr "универсал уникал көрсөтүүчү" + +msgid "File" +msgstr "Файл" + +msgid "Image" +msgstr "Сүрөт" + +msgid "A JSON object" +msgstr "JSON обектиси" + +msgid "Value must be valid JSON." +msgstr "Маани туура JSON болушу керек." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(model)s нерсеси %(field)s аймагы %(value)r маани менен табылбады." + +msgid "Foreign Key (type determined by related field)" +msgstr "Бөтөн Ачкыч (байланышкан аймак менен аныкталат)" + +msgid "One-to-one relationship" +msgstr "Бирге-бир байланышы" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s байланышы" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s байланыштары" + +msgid "Many-to-many relationship" +msgstr "көпкө-көп байланышы" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Бул талаа керектүү." + +msgid "Enter a whole number." +msgstr "Толук сан киргиз." + +msgid "Enter a valid date." +msgstr "туура күн киргиз." + +msgid "Enter a valid time." +msgstr "Туура убакыт киргиз." + +msgid "Enter a valid date/time." +msgstr "Туура күн/убакыт киргиз." + +msgid "Enter a valid duration." +msgstr "Туура мөөнөт киргиз." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Күндөрдүн саны {min_days} жана {max_days} арасында болуусу керек." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Файл жиберилген жок. Формдун бекитүү түрүн текшер." + +msgid "No file was submitted." +msgstr "Файл жиберилген жок." + +msgid "The submitted file is empty." +msgstr "Жиберилген файл бош." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Бул файлдын аты эң көп %(max)dсимвол ала алат. (азыркысы %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Сураныч же файл жибериңиз же тандоону бош калтырыңыз. Экөөн тең эмес." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "Туура сүрөт жөнөтүңүз. Сиз жүктөгөн же сүрөт эмес же бузулган сүрөт." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Туура тандоону танда. %(value)s мүмкүн болгон тандоо эмес." + +msgid "Enter a list of values." +msgstr "Туура маанилер тизмесин киргиз." + +msgid "Enter a complete value." +msgstr "Толук маани киргиз." + +msgid "Enter a valid UUID." +msgstr "Туура UUID киргиз." + +msgid "Enter a valid JSON." +msgstr "Туура JSON киргиз." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(жашырылган аймак %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"ManagementForm берилиши жетишпей атат же жасалма болуп атат. Жетишпеген " +"талаалар: %(field_names)s. Эгер көйгөй чечилбей атса сиз баг билдирүү " +"жөнөтсөңүз болот." + +#, python-format +msgid "Please submit at most %d form." +msgid_plural "Please submit at most %d forms." +msgstr[0] "Сураныч, эң көп %d форм жөнөтүңүз." + +#, python-format +msgid "Please submit at least %d form." +msgid_plural "Please submit at least %d forms." +msgstr[0] "Сураныч, эң аз %dформ жөнөтүңүз." + +msgid "Order" +msgstr "Тартип" + +msgid "Delete" +msgstr "Өчүрүү" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "%(field)s үчүн кайталанган маанилерди оңдоңуз." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"%(field)s үчүн кайталанган маанилерди оңдоңуз алар уникал болуусу керек." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"%(field_name)s %(date_field)s да %(lookup)s үчүн уникал болусу керек. " +"Берилиштерди оңдоңуз." + +msgid "Please correct the duplicate values below." +msgstr "Төмөндө кайталанган маанилерди оңдоңуз." + +msgid "The inline value did not match the parent instance." +msgstr "Катардагы маани энелик нерсеге туура келбей жатат." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Туура тандоо кылыңыз. Ал тандоо мүмкүнчүлүктөн сырткары." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr " “%(pk)s”туура эмес маани." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)sкүнү %(current_timezone)sубактысы боюнча чечмелене албай атат. " +"Ал экианжы же жок болушу мүмкүн." + +msgid "Clear" +msgstr "Тазалоо" + +msgid "Currently" +msgstr "Азыркы" + +msgid "Change" +msgstr "өзгөртүү" + +msgid "Unknown" +msgstr "Белгисиз" + +msgid "Yes" +msgstr "Ооба" + +msgid "No" +msgstr "Жок" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "ооба, жок, балким" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)dбит" + +#, python-format +msgid "%s KB" +msgstr "%s КБ" + +#, python-format +msgid "%s MB" +msgstr "%s мегабайт" + +#, python-format +msgid "%s GB" +msgstr "%s гигабайт" + +#, python-format +msgid "%s TB" +msgstr "%s терабайт" + +#, python-format +msgid "%s PB" +msgstr "%s пикабайт" + +msgid "p.m." +msgstr "түштөн кийин" + +msgid "a.m." +msgstr "түшкө чейин" + +msgid "PM" +msgstr "Түштөн кийин" + +msgid "AM" +msgstr "Түшкө чейин" + +msgid "midnight" +msgstr "Түнүчү" + +msgid "noon" +msgstr "ай" + +msgid "Monday" +msgstr "Дүйшөмбү" + +msgid "Tuesday" +msgstr "Шейшемби" + +msgid "Wednesday" +msgstr "Шаршемби" + +msgid "Thursday" +msgstr "Бейшемби" + +msgid "Friday" +msgstr "Жума" + +msgid "Saturday" +msgstr "Ишемби" + +msgid "Sunday" +msgstr "Жекшемби" + +msgid "Mon" +msgstr "Дүйш" + +msgid "Tue" +msgstr "Шей" + +msgid "Wed" +msgstr "Шар" + +msgid "Thu" +msgstr "Бей" + +msgid "Fri" +msgstr "Жума" + +msgid "Sat" +msgstr "Ише" + +msgid "Sun" +msgstr "Жек" + +msgid "January" +msgstr "Январь" + +msgid "February" +msgstr "Февраль" + +msgid "March" +msgstr "Март" + +msgid "April" +msgstr "Апрель" + +msgid "May" +msgstr "Май" + +msgid "June" +msgstr "Июнь" + +msgid "July" +msgstr "Июль" + +msgid "August" +msgstr "Август" + +msgid "September" +msgstr "Сентябрь" + +msgid "October" +msgstr "Октябрь" + +msgid "November" +msgstr "Ноябрь" + +msgid "December" +msgstr "Декабрь" + +msgid "jan" +msgstr "янв" + +msgid "feb" +msgstr "фев" + +msgid "mar" +msgstr "мар" + +msgid "apr" +msgstr "апр" + +msgid "may" +msgstr "май" + +msgid "jun" +msgstr "июн" + +msgid "jul" +msgstr "июл" + +msgid "aug" +msgstr "авг" + +msgid "sep" +msgstr "сен" + +msgid "oct" +msgstr "окт" + +msgid "nov" +msgstr "ноя" + +msgid "dec" +msgstr "дек" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Янв." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Фев." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Март" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Апрель" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Май" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Июнь" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Июль" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Авг." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Сен." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Окт." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Ноя." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Дек." + +msgctxt "alt. month" +msgid "January" +msgstr "Январь" + +msgctxt "alt. month" +msgid "February" +msgstr "Февраль" + +msgctxt "alt. month" +msgid "March" +msgstr "Март" + +msgctxt "alt. month" +msgid "April" +msgstr "Апрель" + +msgctxt "alt. month" +msgid "May" +msgstr "Май" + +msgctxt "alt. month" +msgid "June" +msgstr "Июнь" + +msgctxt "alt. month" +msgid "July" +msgstr "Июль" + +msgctxt "alt. month" +msgid "August" +msgstr "Август" + +msgctxt "alt. month" +msgid "September" +msgstr "Сентябрь" + +msgctxt "alt. month" +msgid "October" +msgstr "Октябрь" + +msgctxt "alt. month" +msgid "November" +msgstr "Ноябрь" + +msgctxt "alt. month" +msgid "December" +msgstr "Декабрь" + +msgid "This is not a valid IPv6 address." +msgstr "Бул туура эмес IPv6 дареги" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "же" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "," + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d жыл" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d ай" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d апта" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d күн" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d саат" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d мүнөт" + +msgid "Forbidden" +msgstr "Тыйылган" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF текшерүү кыйрады. Суроо четке кагылды." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Браузер тараптан \"Referer header\" HTTPS сайтына жиберилбей калгандыгы үчүн " +"бул билдирүүнү көрүп турасыз. Бул хэдэр сиздин браузер үчүнчү жактан " +"чабуулга учурабаганын текшерүүгө коопсуздук үчүн керек." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Эгер сиз броузерден “Referer” хэдерин өчүрүп салсаңыз, аны күйгүзүп коюңуз. " +"Жок дегенде ушул сайт үчүн же жок дегенде HTTPS байланышуу үчүн. Же болбосо " +"“same-origin” суроолору үчүн." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Эгер сиз тегин же “Referrer-" +"Policy: no-referrer” хэдерин колдонуп жатсаңыз, аларды өчүрүп салыңыз. CSRF " +"коргоосу “Referer” хэдерин талап кылат. Эгер сиз коопсуздук жөнүндө " +"кабатырланып атсаңыз үчүнчү жактар үчүн шилтемесин " +"колдонуңуз." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Сиз бул билдирүүнү бул сайт форм жиберүүдө CSRF кукини талап кылгандыгы үчүн " +"көрүп жатасыз. Бул куки коопсуздуктан улам сиздин сайтыңыз үчүнчү жактан " +"чабуулга кабылбаганын текшерүү үчүн талап кылынат. " + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Эгер сиз броузерде кукиледи өчүрүп койсоңуз, аларды кайра күйгүзүп коюңуз. " +"Жок дегенде ушул сайтка же “same-origin” суроолоруна." + +msgid "More information is available with DEBUG=True." +msgstr "Сиз бул маалыматты DEBUG=True болгону үчүн көрүп жатасыз." + +msgid "No year specified" +msgstr "Жыл көрсөтүлгөн эмес" + +msgid "Date out of range" +msgstr "Күн чектен сырткары" + +msgid "No month specified" +msgstr "Ай көрсөтүлгөн эмес" + +msgid "No day specified" +msgstr "Апта күнү көрсөтүлгөн эмес" + +msgid "No week specified" +msgstr "Апта көрсөтүлгө эмес" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "%(verbose_name_plural)s жок" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"%(verbose_name_plural)s future си тейленбейт. Себеби %(class_name)s." +"allow_future си False маани алган." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Туура эмес күн сабы “%(datestr)s” берилген формат болсо “%(format)s”." + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "суроого эч бир %(verbose_name)s табылбады" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Барак акыркы эмес. Же натуралдык санга өткөрүлө албай атат." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Туура эмес (%(page_number)s) барак: %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Бош тизме жана “%(class_name)s.allow_empty” = False болуп калган." + +msgid "Directory indexes are not allowed here." +msgstr "Папка индекстери бул жерде иштей албайт." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "“%(path)s” жашабайт" + +#, python-format +msgid "Index of %(directory)s" +msgstr "%(directory)s индексттери" + +msgid "The install worked successfully! Congratulations!" +msgstr "Орнотуу ийгиликтүү аяктады! Куттуу болсун!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Жанго %(version)s үчүн чыгарылыш " +"эскертмелерин кара." + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" +"Сиз бул бетти сиздин тууралоо файлыңызда DEBUG=True жана эчбир урл тууралабагандыгыңыз үчүн көрүп " +"жататсыз." + +msgid "Django Documentation" +msgstr "Жанго Түшүндүрмөсү" + +msgid "Topics, references, & how-to’s" +msgstr "Темалар, Сурамжылар, & кантип.. тер" + +msgid "Tutorial: A Polling App" +msgstr "Колдонмо:" + +msgid "Get started with Django" +msgstr "Жангону башта" + +msgid "Django Community" +msgstr "Жанго жамааты" + +msgid "Connect, get help, or contribute" +msgstr "Туташ, жардам ал, же салым кош" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ky/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ky/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ky/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ky/formats.py new file mode 100644 index 0000000..25a0928 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ky/formats.py @@ -0,0 +1,32 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j E Y ж." +TIME_FORMAT = "G:i" +DATETIME_FORMAT = "j E Y ж. G:i" +YEAR_MONTH_FORMAT = "F Y ж." +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "d.m.Y" +SHORT_DATETIME_FORMAT = "d.m.Y H:i" +FIRST_DAY_OF_WEEK = 1 # Дүйшөмбү, Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d.%m.%Y", # '25.10.2006' + "%d.%m.%y", # '25.10.06' +] +DATETIME_INPUT_FORMATS = [ + "%d.%m.%Y %H:%M:%S", # '25.10.2006 14:30:59' + "%d.%m.%Y %H:%M:%S.%f", # '25.10.2006 14:30:59.000200' + "%d.%m.%Y %H:%M", # '25.10.2006 14:30' + "%d.%m.%Y", # '25.10.2006' + "%d.%m.%y %H:%M:%S", # '25.10.06 14:30:59' + "%d.%m.%y %H:%M:%S.%f", # '25.10.06 14:30:59.000200' + "%d.%m.%y %H:%M", # '25.10.06 14:30' + "%d.%m.%y", # '25.10.06' +] +DECIMAL_SEPARATOR = "." +THOUSAND_SEPARATOR = "\xa0" # non-breaking space +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2cf2c8b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lb/LC_MESSAGES/django.po new file mode 100644 index 0000000..b0d4755 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lb/LC_MESSAGES/django.po @@ -0,0 +1,1213 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# sim0n , 2011,2013 +# sim0n , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Luxembourgish (http://www.transifex.com/django/django/" +"language/lb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Afrikaans" + +msgid "Arabic" +msgstr "Arabesch" + +msgid "Asturian" +msgstr "" + +msgid "Azerbaijani" +msgstr "" + +msgid "Bulgarian" +msgstr "Bulgaresch" + +msgid "Belarusian" +msgstr "Wäissrussesch" + +msgid "Bengali" +msgstr "Bengalesch" + +msgid "Breton" +msgstr "" + +msgid "Bosnian" +msgstr "Bosnesch" + +msgid "Catalan" +msgstr "Katalanesch" + +msgid "Czech" +msgstr "Tschechesch" + +msgid "Welsh" +msgstr "Walisesch" + +msgid "Danish" +msgstr "Dänesch" + +msgid "German" +msgstr "Däitsch" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "Griichesch" + +msgid "English" +msgstr "Englesch" + +msgid "Australian English" +msgstr "" + +msgid "British English" +msgstr "Britesch Englesch" + +msgid "Esperanto" +msgstr "" + +msgid "Spanish" +msgstr "Spuenesch" + +msgid "Argentinian Spanish" +msgstr "Argentinesch Spuenesch" + +msgid "Colombian Spanish" +msgstr "" + +msgid "Mexican Spanish" +msgstr "Mexikanesch Spuenesch" + +msgid "Nicaraguan Spanish" +msgstr "" + +msgid "Venezuelan Spanish" +msgstr "" + +msgid "Estonian" +msgstr "Estonesch" + +msgid "Basque" +msgstr "Baskesch" + +msgid "Persian" +msgstr "Persesch" + +msgid "Finnish" +msgstr "Finnesch" + +msgid "French" +msgstr "Franséisch" + +msgid "Frisian" +msgstr "Frisesch" + +msgid "Irish" +msgstr "Iresch" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "Galesch" + +msgid "Hebrew" +msgstr "Hebräesch" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Kroatesch" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "Ungaresch" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "" + +msgid "Indonesian" +msgstr "Indonesesch" + +msgid "Ido" +msgstr "" + +msgid "Icelandic" +msgstr "Islännesch" + +msgid "Italian" +msgstr "Italienesch" + +msgid "Japanese" +msgstr "Japanesch" + +msgid "Georgian" +msgstr "Georgesch" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "" + +msgid "Khmer" +msgstr "Khmer" + +msgid "Kannada" +msgstr "Kanadesch" + +msgid "Korean" +msgstr "Koreanesch" + +msgid "Luxembourgish" +msgstr "Lëtzebuergesch" + +msgid "Lithuanian" +msgstr "Lithuanesesch" + +msgid "Latvian" +msgstr "Lättesch" + +msgid "Macedonian" +msgstr "Macedonesch" + +msgid "Malayalam" +msgstr "Malayalam" + +msgid "Mongolian" +msgstr "Mongolesch" + +msgid "Marathi" +msgstr "" + +msgid "Burmese" +msgstr "" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "" + +msgid "Dutch" +msgstr "Hollännesch" + +msgid "Norwegian Nynorsk" +msgstr "Norwegesch Nynorsk" + +msgid "Ossetic" +msgstr "" + +msgid "Punjabi" +msgstr "Punjabi" + +msgid "Polish" +msgstr "Polnesch" + +msgid "Portuguese" +msgstr "Portugisesch" + +msgid "Brazilian Portuguese" +msgstr "Brasilianesch Portugisesch" + +msgid "Romanian" +msgstr "Rumänesch" + +msgid "Russian" +msgstr "Russesch" + +msgid "Slovak" +msgstr "Slowakesch" + +msgid "Slovenian" +msgstr "Slowenesch" + +msgid "Albanian" +msgstr "Albanesch" + +msgid "Serbian" +msgstr "Serbesch" + +msgid "Serbian Latin" +msgstr "Serbesch Latäinesch" + +msgid "Swedish" +msgstr "Schwedesch" + +msgid "Swahili" +msgstr "" + +msgid "Tamil" +msgstr "Tamil" + +msgid "Telugu" +msgstr "Telugu" + +msgid "Thai" +msgstr "Thai" + +msgid "Turkish" +msgstr "Tierkesch" + +msgid "Tatar" +msgstr "" + +msgid "Udmurt" +msgstr "" + +msgid "Ukrainian" +msgstr "Ukrainesch" + +msgid "Urdu" +msgstr "" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "Vietnamesesch" + +msgid "Simplified Chinese" +msgstr "Einfach d'Chinesesch" + +msgid "Traditional Chinese" +msgstr "Traditionell d'Chinesesch" + +msgid "Messages" +msgstr "" + +msgid "Site Maps" +msgstr "" + +msgid "Static Files" +msgstr "" + +msgid "Syndication" +msgstr "" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "Gëff en validen Wärt an." + +msgid "Enter a valid URL." +msgstr "Gëff eng valid URL an." + +msgid "Enter a valid integer." +msgstr "" + +msgid "Enter a valid email address." +msgstr "Gëff eng valid e-mail Adress an." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Gëff eng valid IPv4 Adress an." + +msgid "Enter a valid IPv6 address." +msgstr "Gëff eng valid IPv6 Adress an." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Gëff eng valid IPv4 oder IPv6 Adress an." + +msgid "Enter only digits separated by commas." +msgstr "" + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Enter a number." +msgstr "" + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "an" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "" + +msgid "This field cannot be blank." +msgstr "" + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "" + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "" + +msgid "Comma-separated integers" +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "Datum (ouni Zäit)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Datum (mat Zäit)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Dezimalzuel" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "" + +msgid "Email address" +msgstr "E-mail Adress" + +msgid "File path" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "Kommazuel" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "Zuel" + +msgid "Big (8 byte) integer" +msgstr "Grouss (8 byte) Zuel" + +msgid "IPv4 address" +msgstr "IPv4 Adress" + +msgid "IP address" +msgstr "IP Adress" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "" + +msgid "Positive integer" +msgstr "Positiv Zuel" + +msgid "Positive small integer" +msgstr "Kleng positiv Zuel" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "" + +msgid "Small integer" +msgstr "Kleng Zuel" + +msgid "Text" +msgstr "Text" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Zäit" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Rei Binär Daten" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "Fichier" + +msgid "Image" +msgstr "Bild" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "" + +msgid "One-to-one relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "" + +msgid "Enter a whole number." +msgstr "" + +msgid "Enter a valid date." +msgstr "" + +msgid "Enter a valid time." +msgstr "" + +msgid "Enter a valid date/time." +msgstr "" + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" + +msgid "No file was submitted." +msgstr "Et ass keng Datei geschéckt ginn." + +msgid "The submitted file is empty." +msgstr "" + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" + +msgid "Enter a list of values." +msgstr "Gëff eng Lescht vun Wäerter an." + +msgid "Enter a complete value." +msgstr "" + +msgid "Enter a valid UUID." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "Sortéier" + +msgid "Delete" +msgstr "Läsch" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "" + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" + +msgid "Please correct the duplicate values below." +msgstr "" + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Maach eidel" + +msgid "Currently" +msgstr "Momentan" + +msgid "Change" +msgstr "Änner" + +msgid "Unknown" +msgstr "Onbekannt" + +msgid "Yes" +msgstr "Jo" + +msgid "No" +msgstr "Nee" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "jo,nee,vläit" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "" + +msgid "noon" +msgstr "" + +msgid "Monday" +msgstr "Méindeg" + +msgid "Tuesday" +msgstr "Dënschdeg" + +msgid "Wednesday" +msgstr "Mëttwoch" + +msgid "Thursday" +msgstr "Donneschdes" + +msgid "Friday" +msgstr "Freides" + +msgid "Saturday" +msgstr "Samschdes" + +msgid "Sunday" +msgstr "Sonndes" + +msgid "Mon" +msgstr "Mei" + +msgid "Tue" +msgstr "Dën" + +msgid "Wed" +msgstr "Mett" + +msgid "Thu" +msgstr "Don" + +msgid "Fri" +msgstr "Fre" + +msgid "Sat" +msgstr "Sam" + +msgid "Sun" +msgstr "Son" + +msgid "January" +msgstr "Januar" + +msgid "February" +msgstr "Februar" + +msgid "March" +msgstr "März" + +msgid "April" +msgstr "Abrell" + +msgid "May" +msgstr "" + +msgid "June" +msgstr "Juni" + +msgid "July" +msgstr "Juli" + +msgid "August" +msgstr "August" + +msgid "September" +msgstr "September" + +msgid "October" +msgstr "Oktober" + +msgid "November" +msgstr "November" + +msgid "December" +msgstr "Dezember" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mär" + +msgid "apr" +msgstr "abr" + +msgid "may" +msgstr "" + +msgid "jun" +msgstr "jun" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "aug" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "okt" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dec" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "März" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Abrell" + +msgctxt "abbrev. month" +msgid "May" +msgstr "" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Juni" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Juli" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Aug." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Sept." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Okt." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dec." + +msgctxt "alt. month" +msgid "January" +msgstr "Januar" + +msgctxt "alt. month" +msgid "February" +msgstr "Februar" + +msgctxt "alt. month" +msgid "March" +msgstr "März" + +msgctxt "alt. month" +msgid "April" +msgstr "Abrell" + +msgctxt "alt. month" +msgid "May" +msgstr "" + +msgctxt "alt. month" +msgid "June" +msgstr "Juni" + +msgctxt "alt. month" +msgid "July" +msgstr "Juli" + +msgctxt "alt. month" +msgid "August" +msgstr "August" + +msgctxt "alt. month" +msgid "September" +msgstr "September" + +msgctxt "alt. month" +msgid "October" +msgstr "Oktober" + +msgctxt "alt. month" +msgid "November" +msgstr "November" + +msgctxt "alt. month" +msgid "December" +msgstr "December" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "oder" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d Joer" +msgstr[1] "%d Joren" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d Mount" +msgstr[1] "%d Meint" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d Woch" +msgstr[1] "%d Wochen" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d Dag" +msgstr[1] "%d Deeg" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d Stonn" +msgstr[1] "%d Stonnen" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d Minutt" +msgstr[1] "%d Minutten" + +msgid "0 minutes" +msgstr "0 Minutten" + +msgid "Forbidden" +msgstr "" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "" + +msgid "No day specified" +msgstr "" + +msgid "No week specified" +msgstr "" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "" + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ee14fec Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lt/LC_MESSAGES/django.po new file mode 100644 index 0000000..0c055a2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lt/LC_MESSAGES/django.po @@ -0,0 +1,1324 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Kostas , 2011 +# lauris , 2011 +# Mariusz Felisiak , 2021 +# Matas Dailyda , 2015-2019 +# naktinis , 2012 +# Nikolajus Krauklis , 2013 +# Povilas Balzaravičius , 2011-2012 +# Simonas Kazlauskas , 2012-2014 +# Vytautas Astrauskas , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2021-11-24 16:28+0000\n" +"Last-Translator: Mariusz Felisiak \n" +"Language-Team: Lithuanian (http://www.transifex.com/django/django/language/" +"lt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lt\n" +"Plural-Forms: nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < " +"11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? " +"1 : n % 1 != 0 ? 2: 3);\n" + +msgid "Afrikaans" +msgstr "Afrikiečių" + +msgid "Arabic" +msgstr "Arabų" + +msgid "Algerian Arabic" +msgstr "" + +msgid "Asturian" +msgstr "Austrų" + +msgid "Azerbaijani" +msgstr "Azerbaidžaniečių" + +msgid "Bulgarian" +msgstr "Bulgarų" + +msgid "Belarusian" +msgstr "Gudų" + +msgid "Bengali" +msgstr "Bengalų" + +msgid "Breton" +msgstr "Bretonų" + +msgid "Bosnian" +msgstr "Bosnių" + +msgid "Catalan" +msgstr "Katalonų" + +msgid "Czech" +msgstr "Čekų" + +msgid "Welsh" +msgstr "Velso" + +msgid "Danish" +msgstr "Danų" + +msgid "German" +msgstr "Vokiečių" + +msgid "Lower Sorbian" +msgstr "Žemutinė Sorbų" + +msgid "Greek" +msgstr "Graikų" + +msgid "English" +msgstr "Anglų" + +msgid "Australian English" +msgstr "Australų Anlgų" + +msgid "British English" +msgstr "Britų Anglų" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Ispanų" + +msgid "Argentinian Spanish" +msgstr "Argentiniečių Ispanų" + +msgid "Colombian Spanish" +msgstr "Kolumbų Ispanų" + +msgid "Mexican Spanish" +msgstr "Meksikiečių Ispanų" + +msgid "Nicaraguan Spanish" +msgstr "Nikaragvos Ispanijos" + +msgid "Venezuelan Spanish" +msgstr "Venesuelos Ispanų" + +msgid "Estonian" +msgstr "Estų" + +msgid "Basque" +msgstr "Baskų" + +msgid "Persian" +msgstr "Persų" + +msgid "Finnish" +msgstr "Suomių" + +msgid "French" +msgstr "Prancūzų" + +msgid "Frisian" +msgstr "Fryzų" + +msgid "Irish" +msgstr "Airių" + +msgid "Scottish Gaelic" +msgstr "Škotų Gėlų" + +msgid "Galician" +msgstr "Galų" + +msgid "Hebrew" +msgstr "Hebrajų" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Kroatų" + +msgid "Upper Sorbian" +msgstr "Aukštutinė Sorbų" + +msgid "Hungarian" +msgstr "Vengrų" + +msgid "Armenian" +msgstr "Armėnų" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indoneziečių" + +msgid "Igbo" +msgstr "" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Islandų" + +msgid "Italian" +msgstr "Italų" + +msgid "Japanese" +msgstr "Japonų" + +msgid "Georgian" +msgstr "Gruzinų" + +msgid "Kabyle" +msgstr "Kabilų" + +msgid "Kazakh" +msgstr "Kazachų" + +msgid "Khmer" +msgstr "Khmerų" + +msgid "Kannada" +msgstr "Dravidų" + +msgid "Korean" +msgstr "Korėjiečių" + +msgid "Kyrgyz" +msgstr "" + +msgid "Luxembourgish" +msgstr "Liuksemburgų" + +msgid "Lithuanian" +msgstr "Lietuvių" + +msgid "Latvian" +msgstr "Latvių" + +msgid "Macedonian" +msgstr "Makedonų" + +msgid "Malayalam" +msgstr "Malajalių" + +msgid "Mongolian" +msgstr "Mongolų" + +msgid "Marathi" +msgstr "Marati" + +msgid "Malay" +msgstr "" + +msgid "Burmese" +msgstr "Mjanmų" + +msgid "Norwegian Bokmål" +msgstr "Norvegų Bokmal" + +msgid "Nepali" +msgstr "Nepalų" + +msgid "Dutch" +msgstr "Olandų" + +msgid "Norwegian Nynorsk" +msgstr "Norvegų Nynorsk" + +msgid "Ossetic" +msgstr "Osetinų" + +msgid "Punjabi" +msgstr "Pandžabi" + +msgid "Polish" +msgstr "Lenkų" + +msgid "Portuguese" +msgstr "Protugalų" + +msgid "Brazilian Portuguese" +msgstr "Brazilijos Portugalų" + +msgid "Romanian" +msgstr "Rumunų" + +msgid "Russian" +msgstr "Rusų" + +msgid "Slovak" +msgstr "Slovakų" + +msgid "Slovenian" +msgstr "Slovėnų" + +msgid "Albanian" +msgstr "Albanų" + +msgid "Serbian" +msgstr "Serbų" + +msgid "Serbian Latin" +msgstr "Serbų Lotynų" + +msgid "Swedish" +msgstr "Švedų" + +msgid "Swahili" +msgstr "Svahili" + +msgid "Tamil" +msgstr "Tamilų" + +msgid "Telugu" +msgstr "Telugų" + +msgid "Tajik" +msgstr "" + +msgid "Thai" +msgstr "Tailando" + +msgid "Turkmen" +msgstr "" + +msgid "Turkish" +msgstr "Turkų" + +msgid "Tatar" +msgstr "Totorių" + +msgid "Udmurt" +msgstr "Udmurtų" + +msgid "Ukrainian" +msgstr "Ukrainiečių" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "Vietnamiečių" + +msgid "Simplified Chinese" +msgstr "Supaprastinta kinų" + +msgid "Traditional Chinese" +msgstr "Tradicinė kinų" + +msgid "Messages" +msgstr "Žinutės" + +msgid "Site Maps" +msgstr "Tinklalapio struktūros" + +msgid "Static Files" +msgstr "Statiniai failai" + +msgid "Syndication" +msgstr "Sindikacija" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "" + +msgid "That page number is not an integer" +msgstr "To puslapio numeris nėra sveikasis skaičius." + +msgid "That page number is less than 1" +msgstr "To numerio puslapis yra mažesnis už 1" + +msgid "That page contains no results" +msgstr "Tas puslapis neturi jokių rezultatų" + +msgid "Enter a valid value." +msgstr "Įveskite tinkamą reikšmę." + +msgid "Enter a valid URL." +msgstr "Įveskite tinkamą URL adresą." + +msgid "Enter a valid integer." +msgstr "Įveskite tinkamą sveikąjį skaičių." + +msgid "Enter a valid email address." +msgstr "Įveskite teisingą el. pašto adresą." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Įveskite validų IPv4 adresą." + +msgid "Enter a valid IPv6 address." +msgstr "Įveskite validų IPv6 adresą." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Įveskite validų IPv4 arba IPv6 adresą." + +msgid "Enter only digits separated by commas." +msgstr "Įveskite skaitmenis atskirtus kableliais." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Įsitikinkite, kad reikšmę sudaro %(limit_value)s simbolių (dabar yra " +"%(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Įsitikinkite, kad reikšmė yra mažesnė arba lygi %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Įsitikinkite, kad reikšmė yra didesnė arba lygi %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Įsitikinkite, kad reikšmė sudaryta iš nemažiau kaip %(limit_value)d ženklo " +"(dabartinis ilgis %(show_value)d)." +msgstr[1] "" +"Įsitikinkite, kad reikšmė sudaryta iš nemažiau kaip %(limit_value)d ženklų " +"(dabartinis ilgis %(show_value)d)." +msgstr[2] "" +"Įsitikinkite, kad reikšmė sudaryta iš nemažiau kaip %(limit_value)d ženklų " +"(dabartinis ilgis %(show_value)d)." +msgstr[3] "" +"Įsitikinkite, kad reikšmė sudaryta iš nemažiau kaip %(limit_value)d ženklų " +"(dabartinis ilgis %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Įsitikinkite, kad reikšmė sudaryta iš nedaugiau kaip %(limit_value)d ženklo " +"(dabartinis ilgis %(show_value)d)." +msgstr[1] "" +"Įsitikinkite, kad reikšmė sudaryta iš nedaugiau kaip %(limit_value)d ženklų " +"(dabartinis ilgis %(show_value)d)." +msgstr[2] "" +"Įsitikinkite, kad reikšmė sudaryta iš nedaugiau kaip %(limit_value)d ženklų " +"(dabartinis ilgis %(show_value)d)." +msgstr[3] "" +"Įsitikinkite, kad reikšmė sudaryta iš nedaugiau kaip %(limit_value)d ženklų " +"(dabartinis ilgis %(show_value)d)." + +msgid "Enter a number." +msgstr "Įveskite skaičių." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Įsitikinkite, kad yra nedaugiau nei %(max)s skaitmuo." +msgstr[1] "Įsitikinkite, kad yra nedaugiau nei %(max)s skaitmenys." +msgstr[2] "Įsitikinkite, kad yra nedaugiau nei %(max)s skaitmenų." +msgstr[3] "Įsitikinkite, kad yra nedaugiau nei %(max)s skaitmenų." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Įsitikinkite, kad yra nedaugiau nei %(max)s skaitmuo po kablelio." +msgstr[1] "Įsitikinkite, kad yra nedaugiau nei %(max)s skaitmenys po kablelio." +msgstr[2] "Įsitikinkite, kad yra nedaugiau nei %(max)s skaitmenų po kablelio." +msgstr[3] "Įsitikinkite, kad yra nedaugiau nei %(max)s skaitmenų po kablelio." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "Įsitikinkite, kad yra nedaugiau nei %(max)s skaitmuo prieš kablelį." +msgstr[1] "" +"Įsitikinkite, kad yra nedaugiau nei %(max)s skaitmenys prieš kablelį." +msgstr[2] "" +"Įsitikinkite, kad yra nedaugiau nei %(max)s skaitmenų prieš kablelį." +msgstr[3] "" +"Įsitikinkite, kad yra nedaugiau nei %(max)s skaitmenų prieš kablelį." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "Nuliniai simboliai neleidžiami." + +msgid "and" +msgstr "ir" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s su šiais %(field_labels)s jau egzistuoja." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Reikšmės %(value)r rinktis negalima." + +msgid "This field cannot be null." +msgstr "Šis laukas negali būti null." + +msgid "This field cannot be blank." +msgstr "Lauką privaloma užpildyti." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s su šiuo %(field_label)s jau egzistuoja." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s privalo būti unikalus %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Lauko tipas: %(field_type)s " + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "Loginė reikšmė (Tiesa arba Netiesa)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Eilutė (ilgis iki %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "Kableliais atskirti sveikieji skaičiai" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "Data (be laiko)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Data (su laiku)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Dešimtainis skaičius" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "Trukmė" + +msgid "Email address" +msgstr "El. pašto adresas" + +msgid "File path" +msgstr "Kelias iki failo" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "Realus skaičius" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "Sveikas skaičius" + +msgid "Big (8 byte) integer" +msgstr "Didelis (8 baitų) sveikas skaičius" + +msgid "Small integer" +msgstr "Nedidelis sveikasis skaičius" + +msgid "IPv4 address" +msgstr "IPv4 adresas" + +msgid "IP address" +msgstr "IP adresas" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "Loginė reikšmė (Tiesa, Netiesa arba Nieko)" + +msgid "Positive big integer" +msgstr "" + +msgid "Positive integer" +msgstr "Teigiamas sveikasis skaičius" + +msgid "Positive small integer" +msgstr "Nedidelis teigiamas sveikasis skaičius" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Unikalus adresas (iki %(max_length)s ženklų)" + +msgid "Text" +msgstr "Tekstas" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Laikas" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Neapdorota informacija" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "Universaliai unikalus identifikatorius" + +msgid "File" +msgstr "Failas" + +msgid "Image" +msgstr "Paveiksliukas" + +msgid "A JSON object" +msgstr "" + +msgid "Value must be valid JSON." +msgstr "" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(model)s objektas su %(field)s %(value)r neegzistuoja." + +msgid "Foreign Key (type determined by related field)" +msgstr "Išorinis raktas (tipas nustatomas susijusiame lauke)" + +msgid "One-to-one relationship" +msgstr "Sąryšis vienas su vienu" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s sąryšis" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s sąryšiai" + +msgid "Many-to-many relationship" +msgstr "Sąryšis daug su daug" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Šis laukas yra privalomas." + +msgid "Enter a whole number." +msgstr "Įveskite pilną skaičių." + +msgid "Enter a valid date." +msgstr "Įveskite tinkamą datą." + +msgid "Enter a valid time." +msgstr "Įveskite tinkamą laiką." + +msgid "Enter a valid date/time." +msgstr "Įveskite tinkamą datą/laiką." + +msgid "Enter a valid duration." +msgstr "Įveskite tinkamą trukmę." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Dienų skaičius turi būti tarp {min_days} ir {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Nebuvo nurodytas failas. Patikrinkite formos koduotę." + +msgid "No file was submitted." +msgstr "Failas nebuvo nurodytas." + +msgid "The submitted file is empty." +msgstr "Nurodytas failas yra tuščias." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Įsitikinkite, kad failo pavadinimas sudarytas iš nedaugiau kaip %(max)d " +"ženklo (dabartinis ilgis %(length)d)." +msgstr[1] "" +"Įsitikinkite, kad failo pavadinimas sudarytas iš nedaugiau kaip %(max)d " +"ženklų (dabartinis ilgis %(length)d)." +msgstr[2] "" +"Įsitikinkite, kad failo pavadinimas sudarytas iš nedaugiau kaip %(max)d " +"ženklų (dabartinis ilgis %(length)d)." +msgstr[3] "" +"Įsitikinkite, kad failo pavadinimas sudarytas iš nedaugiau kaip %(max)d " +"ženklų (dabartinis ilgis %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Nurodykite failą arba pažymėkite išvalyti. Abu pasirinkimai negalimi." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Atsiųskite tinkamą paveiksliuką. Failas, kurį siuntėte nebuvo paveiksliukas, " +"arba buvo sugadintas." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Nurodykite tinkamą reikšmę. %(value)s nėra galimas pasirinkimas." + +msgid "Enter a list of values." +msgstr "Įveskite reikšmių sarašą." + +msgid "Enter a complete value." +msgstr "Įveskite pilną reikšmę." + +msgid "Enter a valid UUID." +msgstr "Įveskite tinkamą UUID." + +msgid "Enter a valid JSON." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Paslėptas laukelis %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" + +#, python-format +msgid "Please submit at most %d form." +msgid_plural "Please submit at most %d forms." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#, python-format +msgid "Please submit at least %d form." +msgid_plural "Please submit at least %d forms." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +msgid "Order" +msgstr "Nurodyti" + +msgid "Delete" +msgstr "Ištrinti" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Pataisykite pasikartojančius duomenis laukui %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Pataisykite pasikartojančius duomenis laukui %(field)s. Duomenys privalo " +"būti unikalūs." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Pataisykite pasikartojančius duomenis laukui %(field_name)s. Duomenys " +"privalo būti unikalūs %(lookup)s peržiūroms per %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Pataisykite žemiau esančias pasikartojančias reikšmes." + +msgid "The inline value did not match the parent instance." +msgstr "Reikšmė nesutapo su pirminiu objektu." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Pasirinkite tinkamą reikšmę. Parinkta reikšmė nėra galima." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Išvalyti" + +msgid "Currently" +msgstr "Šiuo metu" + +msgid "Change" +msgstr "Pakeisti" + +msgid "Unknown" +msgstr "Nežinomas" + +msgid "Yes" +msgstr "Taip" + +msgid "No" +msgstr "Ne" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "taip,ne,galbūt" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d baitas" +msgstr[1] "%(size)d baitai" +msgstr[2] "%(size)d baitai" +msgstr[3] "%(size)d baitai" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "vidurnaktis" + +msgid "noon" +msgstr "vidurdienis" + +msgid "Monday" +msgstr "Pirmadienis" + +msgid "Tuesday" +msgstr "Antradienis" + +msgid "Wednesday" +msgstr "Trečiadienis" + +msgid "Thursday" +msgstr "Ketvirtadienis" + +msgid "Friday" +msgstr "Penktadienis" + +msgid "Saturday" +msgstr "Šeštadienis" + +msgid "Sunday" +msgstr "Sekmadienis" + +msgid "Mon" +msgstr "Pr" + +msgid "Tue" +msgstr "A" + +msgid "Wed" +msgstr "T" + +msgid "Thu" +msgstr "K" + +msgid "Fri" +msgstr "P" + +msgid "Sat" +msgstr "Š" + +msgid "Sun" +msgstr "S" + +msgid "January" +msgstr "sausis" + +msgid "February" +msgstr "vasaris" + +msgid "March" +msgstr "kovas" + +msgid "April" +msgstr "balandis" + +msgid "May" +msgstr "gegužė" + +msgid "June" +msgstr "birželis" + +msgid "July" +msgstr "liepa" + +msgid "August" +msgstr "rugpjūtis" + +msgid "September" +msgstr "rugsėjis" + +msgid "October" +msgstr "spalis" + +msgid "November" +msgstr "lapkritis" + +msgid "December" +msgstr "gruodis" + +msgid "jan" +msgstr "sau" + +msgid "feb" +msgstr "vas" + +msgid "mar" +msgstr "kov" + +msgid "apr" +msgstr "bal" + +msgid "may" +msgstr "geg" + +msgid "jun" +msgstr "bir" + +msgid "jul" +msgstr "lie" + +msgid "aug" +msgstr "rugp" + +msgid "sep" +msgstr "rugs" + +msgid "oct" +msgstr "spa" + +msgid "nov" +msgstr "lap" + +msgid "dec" +msgstr "grd" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "saus." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "vas." + +msgctxt "abbrev. month" +msgid "March" +msgstr "kov." + +msgctxt "abbrev. month" +msgid "April" +msgstr "bal." + +msgctxt "abbrev. month" +msgid "May" +msgstr "geg." + +msgctxt "abbrev. month" +msgid "June" +msgstr "birž." + +msgctxt "abbrev. month" +msgid "July" +msgstr "liep." + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "rugpj." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "rugs." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "spal." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "lapkr." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "gruod." + +msgctxt "alt. month" +msgid "January" +msgstr "sausio" + +msgctxt "alt. month" +msgid "February" +msgstr "vasario" + +msgctxt "alt. month" +msgid "March" +msgstr "kovo" + +msgctxt "alt. month" +msgid "April" +msgstr "balandžio" + +msgctxt "alt. month" +msgid "May" +msgstr "gegužės" + +msgctxt "alt. month" +msgid "June" +msgstr "birželio" + +msgctxt "alt. month" +msgid "July" +msgstr "liepos" + +msgctxt "alt. month" +msgid "August" +msgstr "rugpjūčio" + +msgctxt "alt. month" +msgid "September" +msgstr "rugsėjo" + +msgctxt "alt. month" +msgid "October" +msgstr "spalio" + +msgctxt "alt. month" +msgid "November" +msgstr "lapkričio" + +msgctxt "alt. month" +msgid "December" +msgstr "gruodžio" + +msgid "This is not a valid IPv6 address." +msgstr "Tai nėra teisingas IPv6 adresas." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "arba" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "," + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +msgid "Forbidden" +msgstr "Uždrausta" + +msgid "CSRF verification failed. Request aborted." +msgstr "Nepavyko CSRF patvirtinimas. Užklausa nutraukta." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Jūs matote šią žinutę nes šis puslapis reikalauja CSRF slapuko, kai " +"pateikiama forma. Slapukas reikalaujamas saugumo sumetimais, kad užtikrinti " +"jog jūsų naršyklė nėra užgrobiama trečiųjų asmenų." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "Gauti daugiau informacijos galima su DEBUG=True nustatymu." + +msgid "No year specified" +msgstr "Nenurodyti metai" + +msgid "Date out of range" +msgstr "Data išeina iš ribų" + +msgid "No month specified" +msgstr "Nenurodytas mėnuo" + +msgid "No day specified" +msgstr "Nenurodyta diena" + +msgid "No week specified" +msgstr "Nenurodyta savaitė" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Nėra %(verbose_name_plural)s" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Ateities %(verbose_name_plural)s nėra prieinami, nes %(class_name)s." +"allow_future yra False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Atitinkantis užklausą %(verbose_name)s nerastas" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Neegzistuojantis puslapis (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Aplankų indeksai čia neleidžiami." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "%(directory)s indeksas" + +msgid "The install worked successfully! Congratulations!" +msgstr "Diegimas pavyko! Sveikiname!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Žiūrėti Django %(version)s išleidimo " +"pastabas" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" +"Jūs matote šią žinutę dėl to kad Django nustatymų faile įvesta DEBUG = True ir Jūs nenustatėte jokių URL'ų." + +msgid "Django Documentation" +msgstr "Django dokumentacija" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "Pamoka: Apklausos aplikacija" + +msgid "Get started with Django" +msgstr "Pradėti su Django" + +msgid "Django Community" +msgstr "Django Bendrija" + +msgid "Connect, get help, or contribute" +msgstr "Prisijunk, gauk pagalbą arba prisidėk" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lt/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lt/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lt/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lt/formats.py new file mode 100644 index 0000000..a351b3c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lt/formats.py @@ -0,0 +1,45 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = r"Y \m. E j \d." +TIME_FORMAT = "H:i" +DATETIME_FORMAT = r"Y \m. E j \d., H:i" +YEAR_MONTH_FORMAT = r"Y \m. F" +MONTH_DAY_FORMAT = r"E j \d." +SHORT_DATE_FORMAT = "Y-m-d" +SHORT_DATETIME_FORMAT = "Y-m-d H:i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%Y-%m-%d", # '2006-10-25' + "%d.%m.%Y", # '25.10.2006' + "%d.%m.%y", # '25.10.06' +] +TIME_INPUT_FORMATS = [ + "%H:%M:%S", # '14:30:59' + "%H:%M:%S.%f", # '14:30:59.000200' + "%H:%M", # '14:30' + "%H.%M.%S", # '14.30.59' + "%H.%M.%S.%f", # '14.30.59.000200' + "%H.%M", # '14.30' +] +DATETIME_INPUT_FORMATS = [ + "%Y-%m-%d %H:%M:%S", # '2006-10-25 14:30:59' + "%Y-%m-%d %H:%M:%S.%f", # '2006-10-25 14:30:59.000200' + "%Y-%m-%d %H:%M", # '2006-10-25 14:30' + "%d.%m.%Y %H:%M:%S", # '25.10.2006 14:30:59' + "%d.%m.%Y %H:%M:%S.%f", # '25.10.2006 14:30:59.000200' + "%d.%m.%Y %H:%M", # '25.10.2006 14:30' + "%d.%m.%y %H:%M:%S", # '25.10.06 14:30:59' + "%d.%m.%y %H:%M:%S.%f", # '25.10.06 14:30:59.000200' + "%d.%m.%y %H:%M", # '25.10.06 14:30' + "%d.%m.%y %H.%M.%S", # '25.10.06 14.30.59' + "%d.%m.%y %H.%M.%S.%f", # '25.10.06 14.30.59.000200' + "%d.%m.%y %H.%M", # '25.10.06 14.30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lv/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lv/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3e4fae8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lv/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lv/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lv/LC_MESSAGES/django.po new file mode 100644 index 0000000..91b6f74 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lv/LC_MESSAGES/django.po @@ -0,0 +1,1360 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# edgars , 2011 +# Edgars Voroboks , 2023 +# Edgars Voroboks , 2017,2022 +# Edgars Voroboks , 2017-2018 +# Jannis Leidel , 2011 +# krikulis , 2014 +# Māris Nartišs , 2016 +# Mariusz Felisiak , 2021 +# Mārtiņš Šulcs , 2018 +# Edgars Voroboks , 2018-2021 +# peterisb , 2016-2017 +# Pēteris Caune, 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Edgars Voroboks , 2023\n" +"Language-Team: Latvian (http://app.transifex.com/django/django/language/" +"lv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lv\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : " +"2);\n" + +msgid "Afrikaans" +msgstr "afrikāņu" + +msgid "Arabic" +msgstr "arābu" + +msgid "Algerian Arabic" +msgstr "Alžīrijas arābu" + +msgid "Asturian" +msgstr "asturiešu" + +msgid "Azerbaijani" +msgstr "azerbaidžāņu" + +msgid "Bulgarian" +msgstr "bulgāru" + +msgid "Belarusian" +msgstr "baltkrievu" + +msgid "Bengali" +msgstr "bengāļu" + +msgid "Breton" +msgstr "bretoņu" + +msgid "Bosnian" +msgstr "bosniešu" + +msgid "Catalan" +msgstr "katalāņu" + +msgid "Central Kurdish (Sorani)" +msgstr "centrālā kurdu (sorani)" + +msgid "Czech" +msgstr "čehu" + +msgid "Welsh" +msgstr "velsiešu" + +msgid "Danish" +msgstr "dāņu" + +msgid "German" +msgstr "vācu" + +msgid "Lower Sorbian" +msgstr "apakšsorbu" + +msgid "Greek" +msgstr "grieķu" + +msgid "English" +msgstr "angļu" + +msgid "Australian English" +msgstr "Austrālijas angļu" + +msgid "British English" +msgstr "Lielbritānijas angļu" + +msgid "Esperanto" +msgstr "esperanto" + +msgid "Spanish" +msgstr "spāņu" + +msgid "Argentinian Spanish" +msgstr "Argentīnas spāņu" + +msgid "Colombian Spanish" +msgstr "Kolumbijas spāņu" + +msgid "Mexican Spanish" +msgstr "Meksikas spāņu" + +msgid "Nicaraguan Spanish" +msgstr "Nikaragvas spāņu" + +msgid "Venezuelan Spanish" +msgstr "Venecuēlas spāņu" + +msgid "Estonian" +msgstr "igauņu" + +msgid "Basque" +msgstr "basku" + +msgid "Persian" +msgstr "persiešu" + +msgid "Finnish" +msgstr "somu" + +msgid "French" +msgstr "franču" + +msgid "Frisian" +msgstr "frīzu" + +msgid "Irish" +msgstr "īru" + +msgid "Scottish Gaelic" +msgstr "skotu gēlu" + +msgid "Galician" +msgstr "galīciešu" + +msgid "Hebrew" +msgstr "ebreju" + +msgid "Hindi" +msgstr "hindu" + +msgid "Croatian" +msgstr "horvātu" + +msgid "Upper Sorbian" +msgstr "augšsorbu" + +msgid "Hungarian" +msgstr "ungāru" + +msgid "Armenian" +msgstr "armēņu" + +msgid "Interlingua" +msgstr "modernā latīņu" + +msgid "Indonesian" +msgstr "indonēziešu" + +msgid "Igbo" +msgstr "igbo" + +msgid "Ido" +msgstr "ido" + +msgid "Icelandic" +msgstr "islandiešu" + +msgid "Italian" +msgstr "itāļu" + +msgid "Japanese" +msgstr "japāņu" + +msgid "Georgian" +msgstr "gruzīnu" + +msgid "Kabyle" +msgstr "kabiliešu" + +msgid "Kazakh" +msgstr "kazahu" + +msgid "Khmer" +msgstr "khmeru" + +msgid "Kannada" +msgstr "kannādiešu" + +msgid "Korean" +msgstr "korejiešu" + +msgid "Kyrgyz" +msgstr "kirgīzu" + +msgid "Luxembourgish" +msgstr "luksemburgiešu" + +msgid "Lithuanian" +msgstr "lietuviešu" + +msgid "Latvian" +msgstr "latviešu" + +msgid "Macedonian" +msgstr "maķedoniešu" + +msgid "Malayalam" +msgstr "malajalu" + +msgid "Mongolian" +msgstr "mongoļu" + +msgid "Marathi" +msgstr "maratiešu" + +msgid "Malay" +msgstr "malajiešu" + +msgid "Burmese" +msgstr "birmiešu" + +msgid "Norwegian Bokmål" +msgstr "norvēģu bokmål" + +msgid "Nepali" +msgstr "nepāliešu" + +msgid "Dutch" +msgstr "holandiešu" + +msgid "Norwegian Nynorsk" +msgstr "norvēģu nynorsk" + +msgid "Ossetic" +msgstr "osetiešu" + +msgid "Punjabi" +msgstr "pandžabu" + +msgid "Polish" +msgstr "poļu" + +msgid "Portuguese" +msgstr "portugāļu" + +msgid "Brazilian Portuguese" +msgstr "Brazīlijas portugāļu" + +msgid "Romanian" +msgstr "rumāņu" + +msgid "Russian" +msgstr "krievu" + +msgid "Slovak" +msgstr "slovāku" + +msgid "Slovenian" +msgstr "slovēņu" + +msgid "Albanian" +msgstr "albāņu" + +msgid "Serbian" +msgstr "serbu" + +msgid "Serbian Latin" +msgstr "serbu latīņu" + +msgid "Swedish" +msgstr "zviedru" + +msgid "Swahili" +msgstr "svahili" + +msgid "Tamil" +msgstr "tamilu" + +msgid "Telugu" +msgstr "telugu" + +msgid "Tajik" +msgstr "tadžiku" + +msgid "Thai" +msgstr "taizemiešu" + +msgid "Turkmen" +msgstr "turkmēņu" + +msgid "Turkish" +msgstr "turku" + +msgid "Tatar" +msgstr "tatāru" + +msgid "Udmurt" +msgstr "udmurtu" + +msgid "Uyghur" +msgstr "uiguru" + +msgid "Ukrainian" +msgstr "ukraiņu" + +msgid "Urdu" +msgstr "urdu" + +msgid "Uzbek" +msgstr "Uzbeku" + +msgid "Vietnamese" +msgstr "vjetnamiešu" + +msgid "Simplified Chinese" +msgstr "vienkāršā ķīniešu" + +msgid "Traditional Chinese" +msgstr "tradicionālā ķīniešu" + +msgid "Messages" +msgstr "Ziņojumi" + +msgid "Site Maps" +msgstr "Lapas kartes" + +msgid "Static Files" +msgstr "Statiski faili" + +msgid "Syndication" +msgstr "Sindikācija" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Lapas numurs nav cipars" + +msgid "That page number is less than 1" +msgstr "Lapas numurs ir mazāks par 1" + +msgid "That page contains no results" +msgstr "Lapa nesatur rezultātu" + +msgid "Enter a valid value." +msgstr "Ievadiet korektu vērtību." + +msgid "Enter a valid URL." +msgstr "Ievadiet korektu URL adresi." + +msgid "Enter a valid integer." +msgstr "Ievadiet veselu skaitli." + +msgid "Enter a valid email address." +msgstr "Ievadiet korektu e-pasta adresi" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Ievadiet korektu \"identifikatora\" vērtību, kas satur tikai burtus, " +"ciparus, apakšsvītras vai defises." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Ievadiet korektu \"identifikatora\" vērtību, kas satur tikai Unikoda burtus, " +"ciparus, apakšsvītras vai defises." + +msgid "Enter a valid IPv4 address." +msgstr "Ievadiet korektu IPv4 adresi." + +msgid "Enter a valid IPv6 address." +msgstr "Ievadiet korektu IPv6 adresi" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Ievadiet korektu IPv4 vai IPv6 adresi" + +msgid "Enter only digits separated by commas." +msgstr "Ievadiet tikai numurus, atdalītus ar komatiem." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Nodrošiniet, ka vērtība ir %(limit_value)s (tā satur %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Šai vērtībai jabūt mazākai vai vienādai ar %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Vērtībai jābūt lielākai vai vienādai ar %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "Vērtībai jābūt reizinājumam no %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"Pārliecinieties, ka šī vērtība ir soļa lieluma %(limit_value)s reizinājums, " +"sākot no %(offset)s, piem. %(offset)s, %(valid_value1)s, %(valid_value2)s, " +"un tā tālāk." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Vērtībai jābūt vismaz %(limit_value)d zīmēm (tai ir %(show_value)d)." +msgstr[1] "" +"Vērtībai jābūt vismaz %(limit_value)d zīmei (tai ir %(show_value)d)." +msgstr[2] "" +"Vērtībai jābūt vismaz %(limit_value)d zīmēm (tai ir %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Vērtībai jābūt ne vairāk kā %(limit_value)d zīmēm (tai ir %(show_value)d)." +msgstr[1] "" +"Vērtībai jābūt ne vairāk kā %(limit_value)d zīmei (tai ir %(show_value)d)." +msgstr[2] "" +"Vērtībai jābūt ne vairāk kā %(limit_value)d zīmēm (tai ir %(show_value)d)." + +msgid "Enter a number." +msgstr "Ievadiet skaitli." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Pārliecinieties, ka kopā nav vairāk par %(max)s ciparu." +msgstr[1] "Pārliecinieties, ka kopā nav vairāk par %(max)s cipariem." +msgstr[2] "Pārliecinieties, ka kopā nav vairāk par %(max)s cipariem." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +"Pārliecinieties, ka aiz decimālās zīmes nav vairāk par %(max)s ciparu." +msgstr[1] "" +"Pārliecinieties, ka aiz decimālās zīmes nav vairāk par %(max)s cipariem." +msgstr[2] "" +"Pārliecinieties, ka aiz decimālās zīmes nav vairāk par %(max)s cipariem." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Pārliecinieties, ka pirms decimālās zīmes nav vairāk par %(max)s ciparu." +msgstr[1] "" +"Pārliecinieties, ka pirms decimālās zīmes nav vairāk par %(max)s cipariem." +msgstr[2] "" +"Pārliecinieties, ka pirms decimālās zīmes nav vairāk par %(max)s cipariem." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Faila paplašinājums “%(extension)s” nav atļauts. Atļautie paplašinājumi ir: " +"%(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Nulles rakstzīmes nav atļautas." + +msgid "and" +msgstr "un" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s ar šādu lauka %(field_labels)s vērtību jau eksistē." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Ierobežojums “%(name)s” ir pārkāpts." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Vērtība %(value)r ir nederīga izvēle." + +msgid "This field cannot be null." +msgstr "Šis lauks nevar būt tukšs, null." + +msgid "This field cannot be blank." +msgstr "Šis lauks nevar būt tukšs" + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s ar šādu lauka %(field_label)s vērtību jau eksistē." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "%(field_label)s jābūt unikālam %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Lauks ar tipu: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "“%(value)s” vērtībai ir jābūt vai nu True, vai False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "“%(value)s” vērtībai ir jābūt True, False vai None." + +msgid "Boolean (Either True or False)" +msgstr "Boolean (vai nu True, vai False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Simbolu virkne (līdz pat %(max_length)s)" + +msgid "String (unlimited)" +msgstr "Simbolu virkne (neierobežota)" + +msgid "Comma-separated integers" +msgstr "Ar komatu atdalīti veselie skaitļi" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"“%(value)s” vērtība ir nepareizā formātā. Tai ir jābūt YYYY-MM-DD formātā." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"“%(value)s” vērtība ir pareizā formātā (YYYY-MM-DD), bet tas nav derīgs " +"datums." + +msgid "Date (without time)" +msgstr "Datums (bez laika)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"“%(value)s” vērtība ir nepareizā formātā. Tai ir jābūt YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] formātā." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"“%(value)s” vērtība ir pareizā formātā (YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]), " +"bet tas nav derīgs datums/laiks." + +msgid "Date (with time)" +msgstr "Datums (ar laiku)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "“%(value)s” vērtībai ir jābūt decimālam skaitlim." + +msgid "Decimal number" +msgstr "Decimāls skaitlis" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"“%(value)s” vērtība ir nepareizā formātā. Tai ir jābūt [DD] [[HH:]MM:]ss[." +"uuuuuu] formātā." + +msgid "Duration" +msgstr "Ilgums" + +msgid "Email address" +msgstr "E-pasta adrese" + +msgid "File path" +msgstr "Faila ceļš" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "“%(value)s” vērtībai ir jābūt daļskaitlim." + +msgid "Floating point number" +msgstr "Peldošā komata skaitlis" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "“%(value)s” vērtībai ir jābūt veselam skaitlim." + +msgid "Integer" +msgstr "Vesels skaitlis" + +msgid "Big (8 byte) integer" +msgstr "Liels (8 baitu) vesels skaitlis" + +msgid "Small integer" +msgstr "Mazs vesels skaitlis" + +msgid "IPv4 address" +msgstr "IPv4 adrese" + +msgid "IP address" +msgstr "IP adrese" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "“%(value)s” vērtībai ir jābūt None, True vai False." + +msgid "Boolean (Either True, False or None)" +msgstr "Boolean (vai nu True, False, vai None)" + +msgid "Positive big integer" +msgstr "Liels pozitīvs vesels skaitlis" + +msgid "Positive integer" +msgstr "Naturāls skaitlis" + +msgid "Positive small integer" +msgstr "Mazs pozitīvs vesels skaitlis" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Identifikators (līdz %(max_length)s)" + +msgid "Text" +msgstr "Teksts" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"“%(value)s” vērtība ir nepareizā formātā. Tai ir jābūt HH:MM[:ss[.uuuuuu]] " +"formātā." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"“%(value)s” vērtība ir pareizā formātā (HH:MM[:ss[.uuuuuu]]), bet tas nav " +"derīgs laiks." + +msgid "Time" +msgstr "Laiks" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Bināri dati" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "“%(value)s” nav derīgs UUID." + +msgid "Universally unique identifier" +msgstr "Universāli unikāls identifikators" + +msgid "File" +msgstr "Fails" + +msgid "Image" +msgstr "Attēls" + +msgid "A JSON object" +msgstr "JSON objekts" + +msgid "Value must be valid JSON." +msgstr "Vērtībai ir jābūt derīgam JSON." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(model)s instance ar %(field)s %(value)r neeksistē." + +msgid "Foreign Key (type determined by related field)" +msgstr "Ārējā atslēga (tipu nosaka lauks uz kuru attiecas)" + +msgid "One-to-one relationship" +msgstr "Attiecība viens pret vienu" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s attiecība" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s attiecības" + +msgid "Many-to-many relationship" +msgstr "Attiecība daudzi pret daudziem" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Šis lauks ir obligāts." + +msgid "Enter a whole number." +msgstr "Ievadiet veselu skaitli." + +msgid "Enter a valid date." +msgstr "Ievadiet korektu datumu." + +msgid "Enter a valid time." +msgstr "Ievadiet korektu laiku." + +msgid "Enter a valid date/time." +msgstr "Ievadiet korektu datumu/laiku." + +msgid "Enter a valid duration." +msgstr "Ievadiet korektu ilgumu." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Dienu skaitam jābūt no {min_days} līdz {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Nav nosūtīts fails. Pārbaudiet formas kodējuma tipu." + +msgid "No file was submitted." +msgstr "Netika nosūtīts fails." + +msgid "The submitted file is empty." +msgstr "Jūsu nosūtītais fails ir tukšs." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Faila nosaukuma garumam jābūt ne vairāk kā %(max)d zīmēm (tas ir %(length)d)." +msgstr[1] "" +"Faila nosaukuma garumam jābūt ne vairāk kā %(max)d zīmei (tas ir %(length)d)." +msgstr[2] "" +"Faila nosaukuma garumam jābūt ne vairāk kā %(max)d zīmēm (tas ir %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Vai nu iesniedziet failu, vai atzīmējiet tukšo izvēles rūtiņu, bet ne abus." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Augšupielādējiet korektu attēlu. Fails, ko augšupielādējāt, vai nu nav " +"attēls, vai arī ir bojāts." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Izvēlieties korektu izvēli. %(value)s nav pieejamo izvēļu sarakstā." + +msgid "Enter a list of values." +msgstr "Ievadiet sarakstu ar vērtībām." + +msgid "Enter a complete value." +msgstr "Ievadiet pilnu vērtību." + +msgid "Enter a valid UUID." +msgstr "Ievadiet derīgu UUID." + +msgid "Enter a valid JSON." +msgstr "Ievadiet korektu JSON." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Slēpts lauks %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"ManagementForm trūkst datu vai tie ir mainīti. Trūkstošie lauki: " +"%(field_names)s. Paziņojiet par kļūdu, ja problēma atkārtojas." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Lūdzu iesniedziet ne vairāk par %(num)d formām." +msgstr[1] "Lūdzu iesniedziet ne vairāk par %(num)d formu." +msgstr[2] "Lūdzu iesniedziet ne vairāk par %(num)d formām." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Lūdzu iesniedziet vismaz %(num)d formas." +msgstr[1] "Lūdzu iesniedziet vismaz %(num)d formu." +msgstr[2] "Lūdzu iesniedziet vismaz %(num)d formas." + +msgid "Order" +msgstr "Kārtība" + +msgid "Delete" +msgstr "Dzēst" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Lūdzu izlabojiet dublicētos datus priekš %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Lūdzu izlabojiet dublicētos datus laukam %(field)s, kam jābūt unikālam." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Lūdzu izlabojiet dublicētos datus laukam %(field_name)s, kam jābūt unikālam " +"priekš %(lookup)s iekš %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Lūdzu izlabojiet dublicētās vērtības zemāk." + +msgid "The inline value did not match the parent instance." +msgstr "Iekļautā vērtība nesakrita ar vecāka instanci." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Izvēlieties pareizu izvēli. Jūsu izvēle neietilpst pieejamo sarakstā." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "“%(pk)s” nav derīga vērtība." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s vērtība nevar tikt attēlota %(current_timezone)s laika zonā; tā " +"var būt neskaidra vai neeksistē." + +msgid "Clear" +msgstr "Notīrīt" + +msgid "Currently" +msgstr "Pašlaik" + +msgid "Change" +msgstr "Mainīt" + +msgid "Unknown" +msgstr "Nezināms" + +msgid "Yes" +msgstr "Jā" + +msgid "No" +msgstr "Nē" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "jā,nē,varbūt" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d baits" +msgstr[1] "%(size)d baiti" +msgstr[2] "%(size)d baitu" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "pusnakts" + +msgid "noon" +msgstr "dienasvidus" + +msgid "Monday" +msgstr "pirmdiena" + +msgid "Tuesday" +msgstr "otrdiena" + +msgid "Wednesday" +msgstr "trešdiena" + +msgid "Thursday" +msgstr "ceturtdiena" + +msgid "Friday" +msgstr "piektdiena" + +msgid "Saturday" +msgstr "sestdiena" + +msgid "Sunday" +msgstr "svētdiena" + +msgid "Mon" +msgstr "pr" + +msgid "Tue" +msgstr "ot" + +msgid "Wed" +msgstr "tr" + +msgid "Thu" +msgstr "ce" + +msgid "Fri" +msgstr "pk" + +msgid "Sat" +msgstr "se" + +msgid "Sun" +msgstr "sv" + +msgid "January" +msgstr "janvāris" + +msgid "February" +msgstr "februāris" + +msgid "March" +msgstr "marts" + +msgid "April" +msgstr "aprīlis" + +msgid "May" +msgstr "maijs" + +msgid "June" +msgstr "jūnijs" + +msgid "July" +msgstr "jūlijs" + +msgid "August" +msgstr "augusts" + +msgid "September" +msgstr "septembris" + +msgid "October" +msgstr "oktobris" + +msgid "November" +msgstr "novembris" + +msgid "December" +msgstr "decembris" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "apr" + +msgid "may" +msgstr "mai" + +msgid "jun" +msgstr "jūn" + +msgid "jul" +msgstr "jūl" + +msgid "aug" +msgstr "aug" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "okt" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dec" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "marts" + +msgctxt "abbrev. month" +msgid "April" +msgstr "aprīlis" + +msgctxt "abbrev. month" +msgid "May" +msgstr "maijs" + +msgctxt "abbrev. month" +msgid "June" +msgstr "jūnijs" + +msgctxt "abbrev. month" +msgid "July" +msgstr "jūlijs" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "aug." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "sept." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "okt." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "dec." + +msgctxt "alt. month" +msgid "January" +msgstr "janvāris" + +msgctxt "alt. month" +msgid "February" +msgstr "februāris" + +msgctxt "alt. month" +msgid "March" +msgstr "marts" + +msgctxt "alt. month" +msgid "April" +msgstr "aprīlis" + +msgctxt "alt. month" +msgid "May" +msgstr "maijs" + +msgctxt "alt. month" +msgid "June" +msgstr "jūnijs" + +msgctxt "alt. month" +msgid "July" +msgstr "jūlijs" + +msgctxt "alt. month" +msgid "August" +msgstr "augusts" + +msgctxt "alt. month" +msgid "September" +msgstr "septembris" + +msgctxt "alt. month" +msgid "October" +msgstr "oktobris" + +msgctxt "alt. month" +msgid "November" +msgstr "novembris" + +msgctxt "alt. month" +msgid "December" +msgstr "decembris" + +msgid "This is not a valid IPv6 address." +msgstr "Šī nav derīga IPv6 adrese." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "vai" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d gadi" +msgstr[1] "%(num)d gads" +msgstr[2] "%(num)d gadi" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mēneši" +msgstr[1] "%(num)d mēnesis" +msgstr[2] "%(num)d mēneši" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d nedēļas" +msgstr[1] "%(num)d nedēļa" +msgstr[2] "%(num)d nedēļas" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dienas" +msgstr[1] "%(num)d diena" +msgstr[2] "%(num)d dienas" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d stundas" +msgstr[1] "%(num)d stunda" +msgstr[2] "%(num)d stubdas" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minūtes" +msgstr[1] "%(num)d minūte" +msgstr[2] "%(num)d minūtes" + +msgid "Forbidden" +msgstr "Aizliegts" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF pārbaude neizdevās. Pieprasījums pārtrauks." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Jūs redzat šo paziņojumu, jo jūsu pārlūkprogrammai ir jānosūta “Referer " +"header” šai HTTPS vietnei, taču tā netika nosūtīta. Šī galvene ir " +"nepieciešama drošības apsvērumu dēļ, lai pārliecinātos, ka jūsu " +"pārlūkprogrammas komunikācijas datus nepārtver trešās puses." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Ja esat konfigurējis savu pārlūkprogrammu, lai atspējotu “Referer” headerus, " +"lūdzu, atkārtoti iespējojiet tos vismaz šai vietnei, HTTPS savienojumiem vai " +"“same-origin” pieprasījumiem." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Ja jūs izmantojat tagu vai " +"iekļaujat “Referrer-Policy: no-referrer” headeri, lūdzu noņemiet tos. CSRF " +"aizsardzībai ir nepieciešams, lai “Referer” headerī tiktu veikta strikta " +"pārvirzītāja pārbaude. Ja jūs domājat par privātumu, tad izmantojiet tādas " +"alternatīvas kā priekš saitēm uz trešo pušu vietnēm." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Jūs redzat šo ziņojumu, jo, iesniedzot veidlapas, šai vietnei ir " +"nepieciešams CSRF sīkfails. Šis sīkfails ir vajadzīgs drošības apsvērumu " +"dēļ, lai pārliecinātos, ka trešās personas nepārņems kontroli pār jūsu " +"pārlūkprogrammu." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Ja esat konfigurējis pārlūkprogrammu, lai atspējotu sīkdatnes, lūdzu, " +"atkārtoti iespējojiet tās vismaz šai vietnei vai “same-origin” " +"pieprasījumiem." + +msgid "More information is available with DEBUG=True." +msgstr "Vairāk informācijas ir pieejams ar DEBUG=True" + +msgid "No year specified" +msgstr "Nav norādīts gads" + +msgid "Date out of range" +msgstr "Datums ir ārpus diapazona" + +msgid "No month specified" +msgstr "Nav norādīts mēnesis" + +msgid "No day specified" +msgstr "Nav norādīta diena" + +msgid "No week specified" +msgstr "Nav norādīta nedēļa" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "%(verbose_name_plural)s nav pieejami" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Nākotne %(verbose_name_plural)s nav pieejama, jo %(class_name)s.allow_future " +"ir False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Nepareiza datuma rinda “%(datestr)s” norādītajā formātā “%(format)s”" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Neviens %(verbose_name)s netika atrasts" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Lapa nav “pēdējā”, kā arī tā nevar tikt konvertēta par ciparu." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Nepareiza lapa (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Tukšs saraksts un \"%(class_name)s.allow_empty\" ir False." + +msgid "Directory indexes are not allowed here." +msgstr "Direktoriju indeksi nav atļauti." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "\"%(path)s\" neeksistē" + +#, python-format +msgid "Index of %(directory)s" +msgstr "%(directory)s saturs" + +msgid "The install worked successfully! Congratulations!" +msgstr "Instalācija veiksmīga! Apsveicam!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Apskatīt laidiena piezīmes Django %(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Jūs redziet šo lapu, jo DEBUG=True ir iestatījumu failā un Jūs neesiet " +"konfigurējis nevienu saiti." + +msgid "Django Documentation" +msgstr "Django Dokumentācija" + +msgid "Topics, references, & how-to’s" +msgstr "Tēmas, atsauces, & how-to" + +msgid "Tutorial: A Polling App" +msgstr "Apmācība: Balsošanas aplikācija" + +msgid "Get started with Django" +msgstr "Sāciet ar Django" + +msgid "Django Community" +msgstr "Django Komūna" + +msgid "Connect, get help, or contribute" +msgstr "Sazinieties, saņemiet palīdzību vai sniedziet ieguldījumu" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lv/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lv/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lv/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lv/formats.py new file mode 100644 index 0000000..bb34444 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/lv/formats.py @@ -0,0 +1,46 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = r"Y. \g\a\d\a j. F" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = r"Y. \g\a\d\a j. F, H:i" +YEAR_MONTH_FORMAT = r"Y. \g. F" +MONTH_DAY_FORMAT = "j. F" +SHORT_DATE_FORMAT = r"j.m.Y" +SHORT_DATETIME_FORMAT = "j.m.Y H:i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# Kept ISO formats as they are in first position +DATE_INPUT_FORMATS = [ + "%Y-%m-%d", # '2006-10-25' + "%d.%m.%Y", # '25.10.2006' + "%d.%m.%y", # '25.10.06' +] +TIME_INPUT_FORMATS = [ + "%H:%M:%S", # '14:30:59' + "%H:%M:%S.%f", # '14:30:59.000200' + "%H:%M", # '14:30' + "%H.%M.%S", # '14.30.59' + "%H.%M.%S.%f", # '14.30.59.000200' + "%H.%M", # '14.30' +] +DATETIME_INPUT_FORMATS = [ + "%Y-%m-%d %H:%M:%S", # '2006-10-25 14:30:59' + "%Y-%m-%d %H:%M:%S.%f", # '2006-10-25 14:30:59.000200' + "%Y-%m-%d %H:%M", # '2006-10-25 14:30' + "%d.%m.%Y %H:%M:%S", # '25.10.2006 14:30:59' + "%d.%m.%Y %H:%M:%S.%f", # '25.10.2006 14:30:59.000200' + "%d.%m.%Y %H:%M", # '25.10.2006 14:30' + "%d.%m.%y %H:%M:%S", # '25.10.06 14:30:59' + "%d.%m.%y %H:%M:%S.%f", # '25.10.06 14:30:59.000200' + "%d.%m.%y %H:%M", # '25.10.06 14:30' + "%d.%m.%y %H.%M.%S", # '25.10.06 14.30.59' + "%d.%m.%y %H.%M.%S.%f", # '25.10.06 14.30.59.000200' + "%d.%m.%y %H.%M", # '25.10.06 14.30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = " " # Non-breaking space +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..798ca7e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mk/LC_MESSAGES/django.po new file mode 100644 index 0000000..ecd62ce --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mk/LC_MESSAGES/django.po @@ -0,0 +1,1273 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bojan Drangovski , 2021 +# Claude Paroz , 2020 +# dekomote , 2015 +# Jannis Leidel , 2011 +# Vasil Vangelovski , 2016-2017 +# Vasil Vangelovski , 2013-2015 +# Vasil Vangelovski , 2011-2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-05-12 22:47+0000\n" +"Last-Translator: Bojan Drangovski \n" +"Language-Team: Macedonian (http://www.transifex.com/django/django/language/" +"mk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mk\n" +"Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n" + +msgid "Afrikaans" +msgstr "Африканс" + +msgid "Arabic" +msgstr "Арапски" + +msgid "Algerian Arabic" +msgstr "" + +msgid "Asturian" +msgstr "Астуриски" + +msgid "Azerbaijani" +msgstr "Азербејџански" + +msgid "Bulgarian" +msgstr "Бугарски" + +msgid "Belarusian" +msgstr "Белоруски" + +msgid "Bengali" +msgstr "Бенгалски" + +msgid "Breton" +msgstr "Бретонски" + +msgid "Bosnian" +msgstr "Босански" + +msgid "Catalan" +msgstr "Каталански" + +msgid "Czech" +msgstr "Чешки" + +msgid "Welsh" +msgstr "Велшки" + +msgid "Danish" +msgstr "Дански" + +msgid "German" +msgstr "Германски" + +msgid "Lower Sorbian" +msgstr "Долно Лужичко-Српски" + +msgid "Greek" +msgstr "Грчки" + +msgid "English" +msgstr "Англиски" + +msgid "Australian English" +msgstr "Австралиски англиски" + +msgid "British English" +msgstr "Британски англиски" + +msgid "Esperanto" +msgstr "Есперанто" + +msgid "Spanish" +msgstr "Шпански" + +msgid "Argentinian Spanish" +msgstr "Аргентински шпански" + +msgid "Colombian Spanish" +msgstr "Колумбиски Шпански" + +msgid "Mexican Spanish" +msgstr "Мексикански шпански" + +msgid "Nicaraguan Spanish" +msgstr "Никарагва шпански" + +msgid "Venezuelan Spanish" +msgstr "Венецуела шпански" + +msgid "Estonian" +msgstr "Естонски" + +msgid "Basque" +msgstr "Баскиски" + +msgid "Persian" +msgstr "Персиски" + +msgid "Finnish" +msgstr "Фински" + +msgid "French" +msgstr "Француски" + +msgid "Frisian" +msgstr "Фризиски" + +msgid "Irish" +msgstr "Ирски" + +msgid "Scottish Gaelic" +msgstr "Шкотски Галски" + +msgid "Galician" +msgstr "Галски" + +msgid "Hebrew" +msgstr "Еврејски" + +msgid "Hindi" +msgstr "Хинди" + +msgid "Croatian" +msgstr "Хрватски" + +msgid "Upper Sorbian" +msgstr "Горно Лужичко-Српски" + +msgid "Hungarian" +msgstr "Унгарски" + +msgid "Armenian" +msgstr "Ерменски" + +msgid "Interlingua" +msgstr "Интерлингва" + +msgid "Indonesian" +msgstr "Индонезиски" + +msgid "Igbo" +msgstr "" + +msgid "Ido" +msgstr "Идо" + +msgid "Icelandic" +msgstr "Исландски" + +msgid "Italian" +msgstr "Италијански" + +msgid "Japanese" +msgstr "Јапонски" + +msgid "Georgian" +msgstr "Грузиски" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "Казахстански" + +msgid "Khmer" +msgstr "Кмер" + +msgid "Kannada" +msgstr "Канада" + +msgid "Korean" +msgstr "Корејски" + +msgid "Kyrgyz" +msgstr "" + +msgid "Luxembourgish" +msgstr "Луксембуршки" + +msgid "Lithuanian" +msgstr "Литвански" + +msgid "Latvian" +msgstr "Латвиски" + +msgid "Macedonian" +msgstr "Македонски" + +msgid "Malayalam" +msgstr "Малајалам" + +msgid "Mongolian" +msgstr "Монголски" + +msgid "Marathi" +msgstr "Марати" + +msgid "Burmese" +msgstr "Бурмански" + +msgid "Norwegian Bokmål" +msgstr "Норвешки Бокмел" + +msgid "Nepali" +msgstr "Непалски" + +msgid "Dutch" +msgstr "Холандски" + +msgid "Norwegian Nynorsk" +msgstr "Нинорск норвешки" + +msgid "Ossetic" +msgstr "Осетски" + +msgid "Punjabi" +msgstr "Пунџаби" + +msgid "Polish" +msgstr "Полски" + +msgid "Portuguese" +msgstr "Португалкски" + +msgid "Brazilian Portuguese" +msgstr "Бразилско португалски" + +msgid "Romanian" +msgstr "Романски" + +msgid "Russian" +msgstr "Руски" + +msgid "Slovak" +msgstr "Словачки" + +msgid "Slovenian" +msgstr "Словенечки" + +msgid "Albanian" +msgstr "Албански" + +msgid "Serbian" +msgstr "Српски" + +msgid "Serbian Latin" +msgstr "Српски Латиница" + +msgid "Swedish" +msgstr "Шведски" + +msgid "Swahili" +msgstr "Свахили" + +msgid "Tamil" +msgstr "Тамил" + +msgid "Telugu" +msgstr "Телугу" + +msgid "Tajik" +msgstr "" + +msgid "Thai" +msgstr "Тајландски" + +msgid "Turkmen" +msgstr "" + +msgid "Turkish" +msgstr "Турски" + +msgid "Tatar" +msgstr "Татарски" + +msgid "Udmurt" +msgstr "Удмурт" + +msgid "Ukrainian" +msgstr "Украински" + +msgid "Urdu" +msgstr "Урду" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "Виетнамски" + +msgid "Simplified Chinese" +msgstr "Поедноставен кинески" + +msgid "Traditional Chinese" +msgstr "Традиционален кинески" + +msgid "Messages" +msgstr "Пораки" + +msgid "Site Maps" +msgstr "Сајт мапи" + +msgid "Static Files" +msgstr "Статички датотеки" + +msgid "Syndication" +msgstr "Синдикација" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "" + +msgid "That page number is not an integer" +msgstr "Тој број на страна не е цел број" + +msgid "That page number is less than 1" +msgstr "Тој број на страна е помал од 1" + +msgid "That page contains no results" +msgstr "Таа страна не содржи резултати" + +msgid "Enter a valid value." +msgstr "Внесете правилна вредност." + +msgid "Enter a valid URL." +msgstr "Внесете правилна веб адреса." + +msgid "Enter a valid integer." +msgstr "Внесете валиден цел број." + +msgid "Enter a valid email address." +msgstr "Внесете валидна email адреса." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Внесeте правилна IPv4 адреса." + +msgid "Enter a valid IPv6 address." +msgstr "Внесете валидна IPv6 адреса." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Внесете валидна IPv4 или IPv6 адреса." + +msgid "Enter only digits separated by commas." +msgstr "Внесете само цифри одделени со запирки." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Осигурајте се дека оваа вредност е %(limit_value)s (моментално е " +"%(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" +"Осигурајте се дека оваа вредност е помала или еднаква со %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" +"Осигурајте се дека оваа вредност е поголема или еднаква со %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Осигурајте се дека оваа вредност има најмалку %(limit_value)d карактер (има " +"%(show_value)d)." +msgstr[1] "" +"Осигурајте се дека оваа вредност има најмалку %(limit_value)d карактери (има " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Осигурајте се дека оваа вредност има најмногу %(limit_value)d карактер (има " +"%(show_value)d)." +msgstr[1] "" +"Осигурајте се дека оваа вредност има најмногу %(limit_value)d карактери (има " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Внесете број." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Осигурајте се дека вкупно нема повеќе од %(max)s цифра." +msgstr[1] "Осигурајте се дека вкупно нема повеќе од %(max)s цифри." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Осигурајте се дека нема повеќе од %(max)s децимално место." +msgstr[1] "Осигурајте се дека нема повеќе од %(max)s децимални места." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Осигурајте се дека нема повеќе одs %(max)s цифра пред децималната запирка." +msgstr[1] "" +"Осигурајте се дека нема повеќе од %(max)s цифри пред децималната запирка." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "Null карактери не се дозволени." + +msgid "and" +msgstr "и" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s со ова %(field_labels)s веќе постојат." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Вредноста %(value)r не е валиден избор." + +msgid "This field cannot be null." +msgstr "Оваа вредност неможе да биде null." + +msgid "This field cannot be blank." +msgstr "Ова поле не може да биде празно" + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s со %(field_label)s веќе постои." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s мора да биде уникатно за %(date_field_label)s " +"%(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Поле од тип: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "Вредноста '%(value)s' мора да биде точно или неточно." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "Логичка (или точно или неточно)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Нишка од знаци (текст) (до %(max_length)s карактери)" + +msgid "Comma-separated integers" +msgstr "Целобројни вредности одделени со запирка" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "Датум (без време)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Датум (со време)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Децимален број" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "Траење" + +msgid "Email address" +msgstr "Адреса за е-пошта (email)" + +msgid "File path" +msgstr "Патека на датотека" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "Децимален број подвижна запирка" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "Цел број" + +msgid "Big (8 byte) integer" +msgstr "Голем (8 бајти) цел број" + +msgid "Small integer" +msgstr "Мал цел број" + +msgid "IPv4 address" +msgstr "IPv4 адреса" + +msgid "IP address" +msgstr "IP адреса" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "Логичка вредност (точно,неточно или ништо)" + +msgid "Positive big integer" +msgstr "" + +msgid "Positive integer" +msgstr "Позитивен цел број" + +msgid "Positive small integer" +msgstr "Позитивен мал цел број" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Скратено име (до %(max_length)s знаци)" + +msgid "Text" +msgstr "Текст" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Време" + +msgid "URL" +msgstr "URL (веб адреса)" + +msgid "Raw binary data" +msgstr "Сурови бинарни податоци" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "Датотека" + +msgid "Image" +msgstr "Слика" + +msgid "A JSON object" +msgstr "" + +msgid "Value must be valid JSON." +msgstr "" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(model)s инстанца со %(field)s %(value)r не постои." + +msgid "Foreign Key (type determined by related field)" +msgstr "Надворешен клуч (типот е одреден според поврзаното поле)" + +msgid "One-to-one relationship" +msgstr "Еден-према-еден релација" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s релација" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s релации" + +msgid "Many-to-many relationship" +msgstr "Повеќе-према-повеќе релација" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Ова поле е задолжително." + +msgid "Enter a whole number." +msgstr "Внесете цел број." + +msgid "Enter a valid date." +msgstr "Внесете правилен датум." + +msgid "Enter a valid time." +msgstr "Внесете правилно време." + +msgid "Enter a valid date/time." +msgstr "Внесете правилен датум со време." + +msgid "Enter a valid duration." +msgstr "Внесете валидно времетрање." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Не беше пратена датотека. Проверете го типот на енкодирање на формата." + +msgid "No file was submitted." +msgstr "Не беше пратена датотека." + +msgid "The submitted file is empty." +msgstr "Пратената датотека е празна." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Осигурајте се дека ова име на датотека има најмногу %(max)d карактер (има " +"%(length)d)." +msgstr[1] "" +"Осигурајте се дека ова име на датотека има најмногу %(max)d карактери (има " +"%(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Или прикачете датотека или штиклирајте го полето за чистење, не двете од " +"еднаш." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Качете валидна слика. Датотеката која ја качивте или не беше слика или беше " +"расипана датотеката." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Внесете валиден избор. %(value)s не е еден од можните избори." + +msgid "Enter a list of values." +msgstr "Внесете листа на вредности." + +msgid "Enter a complete value." +msgstr "Внесете целосна вредност." + +msgid "Enter a valid UUID." +msgstr "Внесете валиден UUID (единствен идентификатор)." + +msgid "Enter a valid JSON." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Скриено поле %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" + +#, python-format +msgid "Please submit at most %d form." +msgid_plural "Please submit at most %d forms." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Please submit at least %d form." +msgid_plural "Please submit at least %d forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "Редослед" + +msgid "Delete" +msgstr "Избриши" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Ве молам поправете ја дуплираната вредност за %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Ве молам поправете ја дуплираната вредност за %(field)s, која мора да биде " +"уникатна." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Ве молам поправете ја дуплираната вредност за %(field_name)s која мора да " +"биде уникатна за %(lookup)s во %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Ве молам поправете ги дуплираните вредности подолу." + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Изберете правилно. Тоа не е еден од можните избори." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Исчисти" + +msgid "Currently" +msgstr "Моментално" + +msgid "Change" +msgstr "Измени" + +msgid "Unknown" +msgstr "Непознато" + +msgid "Yes" +msgstr "Да" + +msgid "No" +msgstr "Не" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "да,не,можеби" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d бајт" +msgstr[1] "%(size)d бајти" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "попладне" + +msgid "a.m." +msgstr "наутро" + +msgid "PM" +msgstr "попладне" + +msgid "AM" +msgstr "наутро" + +msgid "midnight" +msgstr "полноќ" + +msgid "noon" +msgstr "пладне" + +msgid "Monday" +msgstr "Понеделник" + +msgid "Tuesday" +msgstr "Вторник" + +msgid "Wednesday" +msgstr "Среда" + +msgid "Thursday" +msgstr "Четврток" + +msgid "Friday" +msgstr "Петок" + +msgid "Saturday" +msgstr "Сабота" + +msgid "Sunday" +msgstr "Недела" + +msgid "Mon" +msgstr "Пон" + +msgid "Tue" +msgstr "Вто" + +msgid "Wed" +msgstr "Сре" + +msgid "Thu" +msgstr "Чет" + +msgid "Fri" +msgstr "Пет" + +msgid "Sat" +msgstr "Саб" + +msgid "Sun" +msgstr "Нед" + +msgid "January" +msgstr "Јануари" + +msgid "February" +msgstr "Февруари" + +msgid "March" +msgstr "Март" + +msgid "April" +msgstr "Април" + +msgid "May" +msgstr "Мај" + +msgid "June" +msgstr "Јуни" + +msgid "July" +msgstr "Јули" + +msgid "August" +msgstr "август" + +msgid "September" +msgstr "Септември" + +msgid "October" +msgstr "Октомври" + +msgid "November" +msgstr "Ноември" + +msgid "December" +msgstr "Декември" + +msgid "jan" +msgstr "јан" + +msgid "feb" +msgstr "фев" + +msgid "mar" +msgstr "мар" + +msgid "apr" +msgstr "апр" + +msgid "may" +msgstr "мај" + +msgid "jun" +msgstr "јун" + +msgid "jul" +msgstr "јул" + +msgid "aug" +msgstr "авг" + +msgid "sep" +msgstr "сеп" + +msgid "oct" +msgstr "окт" + +msgid "nov" +msgstr "ное" + +msgid "dec" +msgstr "дек" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Јан." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Фев." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Март" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Април" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Мај" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Јуни" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Јули" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Авг." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Септ." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Окт." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Ное." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Дек." + +msgctxt "alt. month" +msgid "January" +msgstr "Јануари" + +msgctxt "alt. month" +msgid "February" +msgstr "Февруари" + +msgctxt "alt. month" +msgid "March" +msgstr "Март" + +msgctxt "alt. month" +msgid "April" +msgstr "Април" + +msgctxt "alt. month" +msgid "May" +msgstr "Мај" + +msgctxt "alt. month" +msgid "June" +msgstr "Јуни" + +msgctxt "alt. month" +msgid "July" +msgstr "Јули" + +msgctxt "alt. month" +msgid "August" +msgstr "Август" + +msgctxt "alt. month" +msgid "September" +msgstr "Септември" + +msgctxt "alt. month" +msgid "October" +msgstr "Октомври" + +msgctxt "alt. month" +msgid "November" +msgstr "Ноември" + +msgctxt "alt. month" +msgid "December" +msgstr "Декември" + +msgid "This is not a valid IPv6 address." +msgstr "Ова не е валидна IPv6 адреса." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "или" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "," + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d година" +msgstr[1] "%d години" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d месец" +msgstr[1] "%d месеци" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d недела" +msgstr[1] "%d недели" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d ден" +msgstr[1] "%d дена" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d час" +msgstr[1] "%d часови" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d минута" +msgstr[1] "%d минути" + +msgid "Forbidden" +msgstr "Забрането" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF верификацијата не успеа. Барањето е прекинато." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Ја гледате оваа порака бидејќи овој сајт бара CSRF колаче (cookie) за да се " +"поднесуваат форми. Ова колаче е потребно од безбедносни причини, за да се " +"осигураме дека вашиот веб прелистувач не е грабнат и контролиран од трети " +"страни." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "Повеќе информации се достапни со DEBUG = True." + +msgid "No year specified" +msgstr "Не е дадена година" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "Не е даден месец" + +msgid "No day specified" +msgstr "Не е даден ден" + +msgid "No week specified" +msgstr "Не е дадена недела" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Нема достапни %(verbose_name_plural)s" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Идни %(verbose_name_plural)s не се достапни бидејќи %(class_name)s." +"allow_future е False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Нема %(verbose_name)s што се совпаѓа со пребарувањето" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Невалидна страна (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Индекси на директориуми не се дозволени тука." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Индекс на %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mk/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mk/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mk/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mk/formats.py new file mode 100644 index 0000000..fbb577f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mk/formats.py @@ -0,0 +1,40 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "d F Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = "j. F Y H:i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j. F" +SHORT_DATE_FORMAT = "j.m.Y" +SHORT_DATETIME_FORMAT = "j.m.Y H:i" +FIRST_DAY_OF_WEEK = 1 + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d.%m.%Y", # '25.10.2006' + "%d.%m.%y", # '25.10.06' + "%d. %m. %Y", # '25. 10. 2006' + "%d. %m. %y", # '25. 10. 06' +] + +DATETIME_INPUT_FORMATS = [ + "%d.%m.%Y %H:%M:%S", # '25.10.2006 14:30:59' + "%d.%m.%Y %H:%M:%S.%f", # '25.10.2006 14:30:59.000200' + "%d.%m.%Y %H:%M", # '25.10.2006 14:30' + "%d.%m.%y %H:%M:%S", # '25.10.06 14:30:59' + "%d.%m.%y %H:%M:%S.%f", # '25.10.06 14:30:59.000200' + "%d.%m.%y %H:%M", # '25.10.06 14:30' + "%d. %m. %Y %H:%M:%S", # '25. 10. 2006 14:30:59' + "%d. %m. %Y %H:%M:%S.%f", # '25. 10. 2006 14:30:59.000200' + "%d. %m. %Y %H:%M", # '25. 10. 2006 14:30' + "%d. %m. %y %H:%M:%S", # '25. 10. 06 14:30:59' + "%d. %m. %y %H:%M:%S.%f", # '25. 10. 06 14:30:59.000200' + "%d. %m. %y %H:%M", # '25. 10. 06 14:30' +] + +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ml/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ml/LC_MESSAGES/django.mo new file mode 100644 index 0000000..17d15c6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ml/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ml/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ml/LC_MESSAGES/django.po new file mode 100644 index 0000000..7e1945d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ml/LC_MESSAGES/django.po @@ -0,0 +1,1274 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# c1007a0b890405f1fbddfacebc4c6ef7, 2013 +# Claude Paroz , 2020 +# Hrishikesh , 2019-2020 +# Jannis Leidel , 2011 +# Jaseem KM , 2019 +# Jeffy , 2012 +# Jibin Mathew , 2019 +# Mariusz Felisiak , 2021 +# Rag sagar , 2016 +# Rajeesh Nair , 2011-2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2021-11-24 16:29+0000\n" +"Last-Translator: Mariusz Felisiak \n" +"Language-Team: Malayalam (http://www.transifex.com/django/django/language/" +"ml/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ml\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "ആഫ്രിക്കാന്‍സ്" + +msgid "Arabic" +msgstr "അറബിൿ" + +msgid "Algerian Arabic" +msgstr "അൾഗേരിയൻ അറബിൿ" + +msgid "Asturian" +msgstr "ആസ്ടൂറിയൻ" + +msgid "Azerbaijani" +msgstr "അസര്‍ബൈജാനി" + +msgid "Bulgarian" +msgstr "ബള്‍ഗേറിയന്‍" + +msgid "Belarusian" +msgstr "ബെലറൂഷ്യന്‍" + +msgid "Bengali" +msgstr "ബംഗാളി" + +msgid "Breton" +msgstr "ബ്രെട്ടണ്‍" + +msgid "Bosnian" +msgstr "ബോസ്നിയന്‍" + +msgid "Catalan" +msgstr "കാറ്റലന്‍" + +msgid "Czech" +msgstr "ചെൿ" + +msgid "Welsh" +msgstr "വെല്‍ഷ്" + +msgid "Danish" +msgstr "ഡാനിഷ്" + +msgid "German" +msgstr "ജര്‍മന്‍" + +msgid "Lower Sorbian" +msgstr "ലോവർ സോർബിയൻ " + +msgid "Greek" +msgstr "ഗ്രീക്ക്" + +msgid "English" +msgstr "ഇംഗ്ലീഷ്" + +msgid "Australian English" +msgstr "ആസ്ട്രേലിയൻ ഇംഗ്ലീഷ്" + +msgid "British English" +msgstr "ബ്രിട്ടീഷ് ഇംഗ്ലീഷ്" + +msgid "Esperanto" +msgstr "എസ്പെരാന്റോ" + +msgid "Spanish" +msgstr "സ്പാനിഷ്" + +msgid "Argentinian Spanish" +msgstr "അര്‍ജന്റീനിയന്‍ സ്പാനിഷ്" + +msgid "Colombian Spanish" +msgstr "കൊളംബിയൻ സ്പാനിഷ്" + +msgid "Mexican Spanish" +msgstr "മെക്സിക്കന്‍ സ്പാനിഷ്" + +msgid "Nicaraguan Spanish" +msgstr "നിക്കരാഗ്വന്‍ സ്പാനിഷ്" + +msgid "Venezuelan Spanish" +msgstr "വെനിസ്വലന്‍ സ്പാനിഷ്" + +msgid "Estonian" +msgstr "എസ്ടോണിയന്‍ സ്പാനിഷ്" + +msgid "Basque" +msgstr "ബാസ്ക്യു" + +msgid "Persian" +msgstr "പേര്‍ഷ്യന്‍" + +msgid "Finnish" +msgstr "ഫിന്നിഷ്" + +msgid "French" +msgstr "ഫ്രെഞ്ച്" + +msgid "Frisian" +msgstr "ഫ്രിസിയന്‍" + +msgid "Irish" +msgstr "ഐറിഷ്" + +msgid "Scottish Gaelic" +msgstr "സ്കോട്ടിഷ് ഗൈലിൿ" + +msgid "Galician" +msgstr "ഗലിഷ്യന്‍" + +msgid "Hebrew" +msgstr "ഹീബ്രു" + +msgid "Hindi" +msgstr "ഹിന്ദി" + +msgid "Croatian" +msgstr "ക്രൊയേഷ്യന്‍" + +msgid "Upper Sorbian" +msgstr "അപ്പർ സോർബിയൻ " + +msgid "Hungarian" +msgstr "ഹംഗേറിയന്‍" + +msgid "Armenian" +msgstr "അർമേനിയൻ" + +msgid "Interlingua" +msgstr "ഇന്റര്‍ലിംഗ്വാ" + +msgid "Indonesian" +msgstr "ഇന്തൊനേഷ്യന്‍" + +msgid "Igbo" +msgstr "" + +msgid "Ido" +msgstr "ഈടോ" + +msgid "Icelandic" +msgstr "ഐസ്ലാന്‍ഡിൿ" + +msgid "Italian" +msgstr "ഇറ്റാലിയന്‍" + +msgid "Japanese" +msgstr "ജാപ്പനീസ്" + +msgid "Georgian" +msgstr "ജോര്‍ജിയന്‍" + +msgid "Kabyle" +msgstr "കാബയെൽ " + +msgid "Kazakh" +msgstr "കസാഖ്" + +msgid "Khmer" +msgstr "ഖ്മേര്‍" + +msgid "Kannada" +msgstr "കന്നഡ" + +msgid "Korean" +msgstr "കൊറിയന്‍" + +msgid "Kyrgyz" +msgstr "" + +msgid "Luxembourgish" +msgstr "ലക്സംബര്‍ഗിഷ് " + +msgid "Lithuanian" +msgstr "ലിത്വാനിയന്‍" + +msgid "Latvian" +msgstr "ലാറ്റ്വിയന്‍" + +msgid "Macedonian" +msgstr "മാസിഡോണിയന്‍" + +msgid "Malayalam" +msgstr "മലയാളം" + +msgid "Mongolian" +msgstr "മംഗോളിയന്‍" + +msgid "Marathi" +msgstr "മറാത്തി" + +msgid "Malay" +msgstr "" + +msgid "Burmese" +msgstr "ബര്‍മീസ്" + +msgid "Norwegian Bokmål" +msgstr "നോർവേജിയൻ ബുക്ക്മൊൾ" + +msgid "Nepali" +msgstr "നേപ്പാളി" + +msgid "Dutch" +msgstr "ഡച്ച്" + +msgid "Norwegian Nynorsk" +msgstr "നോര്‍വീജിയന്‍ നിനോഷ്ക്" + +msgid "Ossetic" +msgstr "ഒസ്സെറ്റിക്" + +msgid "Punjabi" +msgstr "പഞ്ചാബി" + +msgid "Polish" +msgstr "പോളിഷ്" + +msgid "Portuguese" +msgstr "പോര്‍ചുഗീസ്" + +msgid "Brazilian Portuguese" +msgstr "ബ്രസീലിയന്‍ പോര്‍ച്ചുഗീസ്" + +msgid "Romanian" +msgstr "റൊമാനിയന്‍" + +msgid "Russian" +msgstr "റഷ്യന്‍" + +msgid "Slovak" +msgstr "സ്ലൊവാൿ" + +msgid "Slovenian" +msgstr "സ്ളൊവേനിയന്‍" + +msgid "Albanian" +msgstr "അല്‍ബേനിയന്‍" + +msgid "Serbian" +msgstr "സെര്‍ബിയന്‍" + +msgid "Serbian Latin" +msgstr "സെര്‍ബിയന്‍ ലാറ്റിന്‍" + +msgid "Swedish" +msgstr "സ്വീഡിഷ്" + +msgid "Swahili" +msgstr "സ്വാഹിലി" + +msgid "Tamil" +msgstr "തമിഴ്" + +msgid "Telugu" +msgstr "തെലുങ്ക്" + +msgid "Tajik" +msgstr "" + +msgid "Thai" +msgstr "തായ്" + +msgid "Turkmen" +msgstr "" + +msgid "Turkish" +msgstr "ടര്‍ക്കിഷ്" + +msgid "Tatar" +msgstr "തൊതാര്‍" + +msgid "Udmurt" +msgstr "ഉദ്മര്‍ത്" + +msgid "Ukrainian" +msgstr "യുക്രേനിയന്‍" + +msgid "Urdu" +msgstr "ഉര്‍ദു" + +msgid "Uzbek" +msgstr "ഉസ്ബെൿ" + +msgid "Vietnamese" +msgstr "വിയറ്റ്നാമീസ്" + +msgid "Simplified Chinese" +msgstr "സിമ്പ്ലിഫൈഡ് ചൈനീസ്" + +msgid "Traditional Chinese" +msgstr "പരമ്പരാഗത ചൈനീസ്" + +msgid "Messages" +msgstr "സന്ദേശങ്ങൾ" + +msgid "Site Maps" +msgstr "സൈറ്റ് മാപ്പുകൾ" + +msgid "Static Files" +msgstr " സ്റ്റാറ്റിൿ ഫയലുകൾ" + +msgid "Syndication" +msgstr "വിതരണം " + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "" + +msgid "That page number is not an integer" +msgstr "ആ പേജ് നമ്പർ ഒരു ഇന്റിജറല്ല" + +msgid "That page number is less than 1" +msgstr "ആ പേജ് നമ്പർ 1 നെ കാൾ ചെറുതാണ് " + +msgid "That page contains no results" +msgstr "ആ പേജിൽ റിസൾട്ടുകൾ ഒന്നും ഇല്ല " + +msgid "Enter a valid value." +msgstr "ശരിയായ വാല്യു നൽകുക." + +msgid "Enter a valid URL." +msgstr "ശരിയായ URL നല്‍കുക" + +msgid "Enter a valid integer." +msgstr "ശരിയായ ഇന്റിജർ നൽകുക." + +msgid "Enter a valid email address." +msgstr "ശരിയായ ഇമെയില്‍ വിലാസം നല്‍കുക." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"അക്ഷരങ്ങള്‍, അക്കങ്ങള്‍, അണ്ടര്‍സ്കോര്‍, ഹൈഫന്‍ എന്നിവ മാത്രം അടങ്ങിയ ശരിയായ ഒരു 'സ്ലഗ്ഗ്' നൽകുക. " + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"യൂണികോഡ് അക്ഷരങ്ങൾ, അക്കങ്ങൾ, ഹൈഫണുകൾ, അണ്ടർസ്കോറുക‌‌ൾ എന്നിവമാത്രം അടങ്ങിയ ശെരിയായ ‌ഒരു " +"“സ്ലഗ്” എഴുതുക ." + +msgid "Enter a valid IPv4 address." +msgstr "ശരിയായ IPv4 വിലാസം നൽകുക." + +msgid "Enter a valid IPv6 address." +msgstr "ശരിയായ ഒരു IPv6 വിലാസം നൽകുക." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "ശരിയായ ഒരു IPv4 വിലാസമോ IPv6 വിലാസമോ നൽകുക." + +msgid "Enter only digits separated by commas." +msgstr "കോമകൾ ഉപയോഗിച്ച് വേർതിരിച്ച രീതിയിലുള്ള അക്കങ്ങൾ മാത്രം നൽകുക." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "ഇത് %(limit_value)s ആവണം. (ഇപ്പോള്‍ %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "ഇത് %(limit_value)s-ഓ അതില്‍ കുറവോ ആവണം" + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "ഇത് %(limit_value)s-ഓ അതില്‍ കൂടുതലോ ആവണം" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"ഈ വാല്യൂയിൽ %(limit_value)d ക്യാരക്ടർ എങ്കിലും ഉണ്ടെന്നു ഉറപ്പു വരുത്തുക(ഇതിൽ " +"%(show_value)d ഉണ്ട് )" +msgstr[1] "" +"ഈ വാല്യൂയിൽ %(limit_value)dക്യാരക്ടേർസ് എങ്കിലും ഉണ്ടെന്നു ഉറപ്പു വരുത്തുക(ഇതിൽ " +"%(show_value)d ഉണ്ട് )" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"ഈ വാല്യൂയിൽ %(limit_value)d ക്യാരക്ടർ 1 ഇൽ കൂടുതൽ ഇല്ലെന്നു ഉറപ്പു വരുത്തുക(ഇതിൽ 2 " +"%(show_value)d ഉണ്ട് )" +msgstr[1] "" +"ഈ വാല്യൂയിൽ %(limit_value)d ക്യാരക്ടർസ് 1 ഇൽ കൂടുതൽ ഇല്ലെന്നു ഉറപ്പു വരുത്തുക(ഇതിൽ 2 " +"%(show_value)d ഉണ്ട് )" + +msgid "Enter a number." +msgstr "ഒരു സംഖ്യ നല്കുക." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "%(max)s ഡിജിറ്റിൽ കൂടുതൽ ഇല്ല എന്ന് ഉറപ്പു വരുത്തുക ." +msgstr[1] "%(max)sഡിജിറ്റ്സിൽ കൂടുതൽ ഇല്ല എന്ന് ഉറപ്പു വരുത്തുക. " + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "%(max)sകൂടുതൽ ഡെസിമൽ പോയന്റില്ല എന്ന് ഉറപ്പു വരുത്തുക. " +msgstr[1] "%(max)sകൂടുതൽ ഡെസിമൽ പോയിന്റുകളില്ല എന്ന് ഉറപ്പു വരുത്തുക. " + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "%(max)sഡിജിറ്റ് ഡെസിമൽ പോയിന്റിനു മുൻപ് ഇല്ല എന്ന് ഉറപ്പു വരുത്തുക." +msgstr[1] "%(max)sഡിജിറ്റ്സ് ഡെസിമൽ പോയിന്റിനു മുൻപ് ഇല്ല എന്ന് ഉറപ്പു വരുത്തുക. " + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"“%(extension)s” എന്ന ഫയൽ എക്സ്റ്റൻഷൻ അനുവദനീയമല്ല. അനുവദനീയമായ എക്സ്റ്റൻഷനുകൾ ഇവയാണ്: " +"%(allowed_extensions)s" + +msgid "Null characters are not allowed." +msgstr "Null ക്യാരക്ടറുകൾ അനുവദനീയമല്ല." + +msgid "and" +msgstr "പിന്നെ" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(field_labels)sഉള്ള %(model_name)sനിലവിലുണ്ട്." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "%(value)r എന്ന വാല്യൂ ശെരിയായ ചോയ്സ് അല്ല. " + +msgid "This field cannot be null." +msgstr "ഈ കളം (ഫീല്‍ഡ്) ഒഴിച്ചിടരുത്." + +msgid "This field cannot be blank." +msgstr "ഈ കളം (ഫീല്‍ഡ്) ഒഴിച്ചിടരുത്." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(field_label)s-ഓടു കൂടിയ %(model_name)s നിലവിലുണ്ട്." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(date_field_label)s %(lookup_type)s-നു %(field_label)s ആവര്‍ത്തിക്കാന്‍ പാടില്ല." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "%(field_type)s എന്ന തരത്തിലുള്ള കളം (ഫീല്‍ഡ്)" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "“%(value)s” മൂല്യം ഒന്നുകിൽ True, False എന്നിവയിലേതെങ്കിലുമേ ആവാൻ പാടുള്ളൂ." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" +"“%(value)s” മൂല്യം ഒന്നുകിൽ True, False അല്ലെങ്കിൽ None എന്നിവയിലേതെങ്കിലുമേ ആവാൻ " +"പാടുള്ളൂ." + +msgid "Boolean (Either True or False)" +msgstr "ശരിയോ തെറ്റോ (True അഥവാ False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "സ്ട്രിങ്ങ് (%(max_length)s വരെ നീളമുള്ളത്)" + +msgid "Comma-separated integers" +msgstr "കോമയിട്ട് വേര്‍തിരിച്ച സംഖ്യകള്‍" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "തീയതി (സമയം വേണ്ട)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "തീയതി (സമയത്തോടൊപ്പം)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "ദശാംശസംഖ്യ" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "കാലയളവ്" + +msgid "Email address" +msgstr "ഇ-മെയില്‍ വിലാസം" + +msgid "File path" +msgstr "ഫയല്‍ സ്ഥാനം" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "ദശാംശസംഖ്യ" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "പൂര്‍ണ്ണസംഖ്യ" + +msgid "Big (8 byte) integer" +msgstr "8 ബൈറ്റ് പൂര്‍ണസംഖ്യ." + +msgid "Small integer" +msgstr "ഹ്രസ്വ പൂര്‍ണസംഖ്യ" + +msgid "IPv4 address" +msgstr "IPv4 വിലാസം" + +msgid "IP address" +msgstr "IP വിലാസം" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "ശരിയോ തെറ്റോ എന്നു മാത്രം (True, False, None എന്നിവയില്‍ ഏതെങ്കിലും ഒന്ന്)" + +msgid "Positive big integer" +msgstr "" + +msgid "Positive integer" +msgstr "ധന പൂര്‍ണസംഖ്യ" + +msgid "Positive small integer" +msgstr "ധന ഹ്രസ്വ പൂര്‍ണസംഖ്യ" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "സ്ലഗ് (%(max_length)s വരെ)" + +msgid "Text" +msgstr "ടെക്സ്റ്റ്" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "സമയം" + +msgid "URL" +msgstr "URL(വെബ്-വിലാസം)" + +msgid "Raw binary data" +msgstr "റോ ബൈനറി ഡാറ്റ" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "എല്ലായിടത്തും യുണീക്കായ ഐഡന്റിഫൈയർ." + +msgid "File" +msgstr "ഫയല്‍" + +msgid "Image" +msgstr "ചിത്രം" + +msgid "A JSON object" +msgstr "" + +msgid "Value must be valid JSON." +msgstr "" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(field)s%(value)r ഉള്ള%(model)s ഇൻസ്റ്റൻസ് നിലവിൽ ഇല്ല." + +msgid "Foreign Key (type determined by related field)" +msgstr "ഫോറിന്‍ കീ (ടൈപ്പ് ബന്ധപ്പെട്ട ഫീല്‍ഡില്‍ നിന്നും നിര്‍ണ്ണയിക്കുന്നതാണ്)" + +msgid "One-to-one relationship" +msgstr "വണ്‍-ടു-വണ്‍ ബന്ധം" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s റിലേഷൻഷിപ്‌." + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)sറിലേഷൻഷിപ്‌സ്. " + +msgid "Many-to-many relationship" +msgstr "മെനി-ടു-മെനി ബന്ധം" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "ഈ കള്ളി(ഫീല്‍ഡ്) നിര്‍ബന്ധമാണ്." + +msgid "Enter a whole number." +msgstr "ഒരു പൂര്‍ണസംഖ്യ നല്കുക." + +msgid "Enter a valid date." +msgstr "ശരിയായ തീയതി നല്കുക." + +msgid "Enter a valid time." +msgstr "ശരിയായ സമയം നല്കുക." + +msgid "Enter a valid date/time." +msgstr "ശരിയായ തീയതിയും സമയവും നല്കുക." + +msgid "Enter a valid duration." +msgstr "സാധുതയുള്ള കാലയളവ് നല്കുക." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "ദിവസങ്ങളുടെ എണ്ണം {min_days}, {max_days} എന്നിവയുടെ ഇടയിലായിരിക്കണം." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "ഫയലൊന്നും ലഭിച്ചിട്ടില്ല. ഫോമിലെ എന്‍-കോഡിംഗ് പരിശോധിക്കുക." + +msgid "No file was submitted." +msgstr "ഫയലൊന്നും ലഭിച്ചിട്ടില്ല." + +msgid "The submitted file is empty." +msgstr "ലഭിച്ച ഫയല്‍ ശൂന്യമാണ്." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"ഈ ഫയൽ നെയ്മിൽ%(max)dക്യാരക്ടറിൽ കൂടുതലില്ല എന്ന് ഉറപ്പു വരുത്തുക (അതിൽ %(length)dഉണ്ട്) . " +msgstr[1] "" +"ഈ ഫയൽ നെയ്മിൽ%(max)dക്യാരക്ടേഴ്‌സിൽ കൂടുതലില്ല എന്ന് ഉറപ്പു വരുത്തുക (അതിൽ %(length)dഉണ്ട്)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"ഒന്നുകില്‍ ഫയല്‍ സമര്‍പ്പിക്കണം, അല്ലെങ്കില്‍ ക്ളിയര്‍ എന്ന ചെക്ബോക്സ് ടിക് ചെയ്യണം. ദയവായി രണ്ടും " +"കൂടി ചെയ്യരുത്." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"ശരിയായ ചിത്രം അപ് ലോഡ് ചെയ്യുക. നിങ്ങള്‍ നല്കിയ ഫയല്‍ ഒന്നുകില്‍ ഒരു ചിത്രമല്ല, അല്ലെങ്കില്‍ " +"വികലമാണ്." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "യോഗ്യമായത് തെരഞ്ഞെടുക്കുക. %(value)s ലഭ്യമായവയില്‍ ഉള്‍പ്പെടുന്നില്ല." + +msgid "Enter a list of values." +msgstr "മൂല്യങ്ങളുടെ പട്ടിക(ലിസ്റ്റ്) നല്കുക." + +msgid "Enter a complete value." +msgstr "പൂർണ്ണമായ വാല്യൂ നല്കുക." + +msgid "Enter a valid UUID." +msgstr "സാധുവായ യു യു ഐ ഡി നല്കുക." + +msgid "Enter a valid JSON." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(ഹിഡൻ ഫീൽഡ് %(name)s)%(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" + +#, python-format +msgid "Please submit at most %d form." +msgid_plural "Please submit at most %d forms." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Please submit at least %d form." +msgid_plural "Please submit at least %d forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "ക്രമം" + +msgid "Delete" +msgstr "ഡിലീറ്റ്" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "%(field)s-നായി നല്കുന്ന വിവരം ആവര്‍ത്തിച്ചത് ദയവായി തിരുത്തുക." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "%(field)s-നായി നല്കുന്ന വിവരം ആവര്‍ത്തിക്കാന്‍ പാടില്ല. ദയവായി തിരുത്തുക." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"%(date_field)s ലെ %(lookup)s നു വേണ്ടി %(field_name)s നു നല്കുന്ന വിവരം ആവര്‍ത്തിക്കാന്‍ " +"പാടില്ല. ദയവായി തിരുത്തുക." + +msgid "Please correct the duplicate values below." +msgstr "താഴെ കൊടുത്തവയില്‍ ആവര്‍ത്തനം ഒഴിവാക്കുക." + +msgid "The inline value did not match the parent instance." +msgstr "ഇൻലൈൻ വാല്യൂ, പാരെന്റ് ഇൻസ്റ്റൻസുമായി ചേരുന്നില്ല." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "യോഗ്യമായത് തെരഞ്ഞെടുക്കുക. നിങ്ങള്‍ നല്കിയത് ലഭ്യമായവയില്‍ ഉള്‍പ്പെടുന്നില്ല." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "കാലിയാക്കുക" + +msgid "Currently" +msgstr "നിലവിലുള്ളത്" + +msgid "Change" +msgstr "മാറ്റുക" + +msgid "Unknown" +msgstr "അജ്ഞാതം" + +msgid "Yes" +msgstr "അതെ" + +msgid "No" +msgstr "അല്ല" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "ഉണ്ട്,ഇല്ല,ഉണ്ടായേക്കാം" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d ബൈറ്റ്" +msgstr[1] "%(size)d ബൈറ്റുകള്‍" + +#, python-format +msgid "%s KB" +msgstr "%s കെ.ബി" + +#, python-format +msgid "%s MB" +msgstr "%s എം.ബി" + +#, python-format +msgid "%s GB" +msgstr "%s ജി.ബി" + +#, python-format +msgid "%s TB" +msgstr "%s ടി.ബി" + +#, python-format +msgid "%s PB" +msgstr "%s പി.ബി" + +msgid "p.m." +msgstr "പി. എം (ഉച്ചയ്ക്കു ശേഷം) " + +msgid "a.m." +msgstr "എ. എം (ഉച്ചയ്ക്കു മുമ്പ്)" + +msgid "PM" +msgstr "പി. എം (ഉച്ചയ്ക്കു ശേഷം) " + +msgid "AM" +msgstr "എ. എം (ഉച്ചയ്ക്കു മുമ്പ്)" + +msgid "midnight" +msgstr "അര്‍ധരാത്രി" + +msgid "noon" +msgstr "ഉച്ച" + +msgid "Monday" +msgstr "തിങ്കളാഴ്ച" + +msgid "Tuesday" +msgstr "ചൊവ്വാഴ്ച" + +msgid "Wednesday" +msgstr "ബുധനാഴ്ച" + +msgid "Thursday" +msgstr "വ്യാഴാഴ്ച" + +msgid "Friday" +msgstr "വെള്ളിയാഴ്ച" + +msgid "Saturday" +msgstr "ശനിയാഴ്ച" + +msgid "Sunday" +msgstr "ഞായറാഴ്ച" + +msgid "Mon" +msgstr "തിങ്കള്‍" + +msgid "Tue" +msgstr "ചൊവ്വ" + +msgid "Wed" +msgstr "ബുധന്‍" + +msgid "Thu" +msgstr "വ്യാഴം" + +msgid "Fri" +msgstr "വെള്ളി" + +msgid "Sat" +msgstr "ശനി" + +msgid "Sun" +msgstr "ഞായര്‍" + +msgid "January" +msgstr "ജനുവരി" + +msgid "February" +msgstr "ഫെബ്രുവരി" + +msgid "March" +msgstr "മാര്‍ച്ച്" + +msgid "April" +msgstr "ഏപ്രില്‍" + +msgid "May" +msgstr "മേയ്" + +msgid "June" +msgstr "ജൂണ്‍" + +msgid "July" +msgstr "ജൂലൈ" + +msgid "August" +msgstr "ആഗസ്ത്" + +msgid "September" +msgstr "സെപ്തംബര്‍" + +msgid "October" +msgstr "ഒക്ടോബര്‍" + +msgid "November" +msgstr "നവംബര്‍" + +msgid "December" +msgstr "ഡിസംബര്‍" + +msgid "jan" +msgstr "ജനു." + +msgid "feb" +msgstr "ഫെബ്രു." + +msgid "mar" +msgstr "മാര്‍ച്ച്" + +msgid "apr" +msgstr "ഏപ്രില്‍" + +msgid "may" +msgstr "മേയ്" + +msgid "jun" +msgstr "ജൂണ്‍" + +msgid "jul" +msgstr "ജൂലൈ" + +msgid "aug" +msgstr "ആഗസ്ത്" + +msgid "sep" +msgstr "സെപ്ടം." + +msgid "oct" +msgstr "ഒക്ടോ." + +msgid "nov" +msgstr "നവം." + +msgid "dec" +msgstr "ഡിസം." + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "ജനു." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "ഫെബ്രു." + +msgctxt "abbrev. month" +msgid "March" +msgstr "മാര്‍ച്ച്" + +msgctxt "abbrev. month" +msgid "April" +msgstr "ഏപ്രില്‍" + +msgctxt "abbrev. month" +msgid "May" +msgstr "മേയ്" + +msgctxt "abbrev. month" +msgid "June" +msgstr "ജൂണ്‍" + +msgctxt "abbrev. month" +msgid "July" +msgstr "ജൂലൈ" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "ആഗ." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "സെപ്തം." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "ഒക്ടോ." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "നവം." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "ഡിസം." + +msgctxt "alt. month" +msgid "January" +msgstr "ജനുവരി" + +msgctxt "alt. month" +msgid "February" +msgstr "ഫെബ്രുവരി" + +msgctxt "alt. month" +msgid "March" +msgstr "മാര്‍ച്ച്" + +msgctxt "alt. month" +msgid "April" +msgstr "ഏപ്രില്‍" + +msgctxt "alt. month" +msgid "May" +msgstr "മേയ്" + +msgctxt "alt. month" +msgid "June" +msgstr "ജൂണ്‍" + +msgctxt "alt. month" +msgid "July" +msgstr "ജൂലൈ" + +msgctxt "alt. month" +msgid "August" +msgstr "ആഗസ്ത്" + +msgctxt "alt. month" +msgid "September" +msgstr "സെപ്തംബര്‍" + +msgctxt "alt. month" +msgid "October" +msgstr "ഒക്ടോബര്‍" + +msgctxt "alt. month" +msgid "November" +msgstr "നവംബര്‍" + +msgctxt "alt. month" +msgid "December" +msgstr "ഡിസംബര്‍" + +msgid "This is not a valid IPv6 address." +msgstr "ഇതു സാധുവായ IPv6 വിലാസമല്ല." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "അഥവാ" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "" +msgstr[1] "" + +msgid "Forbidden" +msgstr "വിലക്കപ്പെട്ടത്" + +msgid "CSRF verification failed. Request aborted." +msgstr "സി എസ് ആർ എഫ് പരിശോധന പരാജയപ്പെട്ടു. റിക്വെസ്റ്റ് റദ്ദാക്കി." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"ഫോം സമർപ്പിക്കുമ്പോൾ ഒരു CSRF കുക്കി ഈ സൈറ്റിൽ ആവശ്യമാണ് എന്നതിനാലാണ് നിങ്ങൾ ഈ സന്ദേശം " +"കാണുന്നത്. മറ്റുള്ളവരാരെങ്കിലും നിങ്ങളുടെ ബ്രൗസറിനെ നിയന്ത്രിക്കുന്നില്ല എന്ന് ഉറപ്പുവരുത്താനായി ഈ " +"കുക്കി ആവശ്യമാണ്. " + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "Debug=True എന്നു കൊടുത്താൽ കൂടുതൽ കാര്യങ്ങൾ അറിയാൻ കഴിയും." + +msgid "No year specified" +msgstr "വര്‍ഷം പരാമര്‍ശിച്ചിട്ടില്ല" + +msgid "Date out of range" +msgstr "ഡാറ്റ പരിധിയുടെ പുറത്താണ്" + +msgid "No month specified" +msgstr "മാസം പരാമര്‍ശിച്ചിട്ടില്ല" + +msgid "No day specified" +msgstr "ദിവസം പരാമര്‍ശിച്ചിട്ടില്ല" + +msgid "No week specified" +msgstr "ആഴ്ച പരാമര്‍ശിച്ചിട്ടില്ല" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "%(verbose_name_plural)s ഒന്നും ലഭ്യമല്ല" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"%(class_name)s.allow_future ന് False എന്നു നല്കിയിട്ടുള്ളതിനാല്‍ Future " +"%(verbose_name_plural)s ഒന്നും ലഭ്യമല്ല." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "ചോദ്യത്തിനു ചേരുന്ന് %(verbose_name)s ഇല്ല" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "ഡയറക്ടറി സൂചികകള്‍ ഇവിടെ അനുവദനീയമല്ല." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "%(directory)s യുടെ സൂചിക" + +msgid "The install worked successfully! Congratulations!" +msgstr "ഇൻസ്ടാൾ ഭംഗിയായി നടന്നു! അഭിനന്ദനങ്ങൾ !" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "ജാംഗോ ഡോക്യുമെന്റേഷൻ" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "പരിശീലനം: ഒരു പോളിങ്ങ് ആപ്പ്" + +msgid "Get started with Django" +msgstr "ജാംഗോയുമായി പരിചയത്തിലാവുക" + +msgid "Django Community" +msgstr "ജാംഗോ കമ്യൂണിറ്റി" + +msgid "Connect, get help, or contribute" +msgstr "കൂട്ടുകൂടൂ, സഹായം തേടൂ, അല്ലെങ്കിൽ സഹകരിക്കൂ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ml/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ml/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ml/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ml/formats.py new file mode 100644 index 0000000..b1ca2ee --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ml/formats.py @@ -0,0 +1,43 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "N j, Y" +TIME_FORMAT = "P" +DATETIME_FORMAT = "N j, Y, P" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "F j" +SHORT_DATE_FORMAT = "m/d/Y" +SHORT_DATETIME_FORMAT = "m/d/Y P" +FIRST_DAY_OF_WEEK = 0 # Sunday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# Kept ISO formats as they are in first position +DATE_INPUT_FORMATS = [ + "%Y-%m-%d", # '2006-10-25' + "%m/%d/%Y", # '10/25/2006' + "%m/%d/%y", # '10/25/06' + # "%b %d %Y", # 'Oct 25 2006' + # "%b %d, %Y", # 'Oct 25, 2006' + # "%d %b %Y", # '25 Oct 2006' + # "%d %b, %Y", # '25 Oct, 2006' + # "%B %d %Y", # 'October 25 2006' + # "%B %d, %Y", # 'October 25, 2006' + # "%d %B %Y", # '25 October 2006' + # "%d %B, %Y", # '25 October, 2006' +] +DATETIME_INPUT_FORMATS = [ + "%Y-%m-%d %H:%M:%S", # '2006-10-25 14:30:59' + "%Y-%m-%d %H:%M:%S.%f", # '2006-10-25 14:30:59.000200' + "%Y-%m-%d %H:%M", # '2006-10-25 14:30' + "%m/%d/%Y %H:%M:%S", # '10/25/2006 14:30:59' + "%m/%d/%Y %H:%M:%S.%f", # '10/25/2006 14:30:59.000200' + "%m/%d/%Y %H:%M", # '10/25/2006 14:30' + "%m/%d/%y %H:%M:%S", # '10/25/06 14:30:59' + "%m/%d/%y %H:%M:%S.%f", # '10/25/06 14:30:59.000200' + "%m/%d/%y %H:%M", # '10/25/06 14:30' +] +DECIMAL_SEPARATOR = "." +THOUSAND_SEPARATOR = "," +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..06071c9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mn/LC_MESSAGES/django.po new file mode 100644 index 0000000..d846523 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mn/LC_MESSAGES/django.po @@ -0,0 +1,1256 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ankhbayar , 2013 +# Bayarkhuu Bataa, 2014,2017-2018 +# Baskhuu Lodoikhuu , 2011 +# Jannis Leidel , 2011 +# jargalan , 2011 +# Tsolmon , 2011 +# Zorig, 2013-2014,2016,2018 +# Zorig, 2019 +# Анхбаяр Анхаа , 2013-2016,2018-2019 +# Баясгалан Цэвлээ , 2011,2015,2017 +# Ганзориг БП , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 07:28+0000\n" +"Last-Translator: Анхбаяр Анхаа \n" +"Language-Team: Mongolian (http://www.transifex.com/django/django/language/" +"mn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Африк" + +msgid "Arabic" +msgstr "Араб" + +msgid "Asturian" +msgstr "Астури" + +msgid "Azerbaijani" +msgstr "Азербажан" + +msgid "Bulgarian" +msgstr "Болгар" + +msgid "Belarusian" +msgstr "Беларус" + +msgid "Bengali" +msgstr "Бенгал" + +msgid "Breton" +msgstr "Бэрэйтон " + +msgid "Bosnian" +msgstr "Босни" + +msgid "Catalan" +msgstr "Каталан" + +msgid "Czech" +msgstr "Чех" + +msgid "Welsh" +msgstr "Уэльс" + +msgid "Danish" +msgstr "Дани" + +msgid "German" +msgstr "Герман" + +msgid "Lower Sorbian" +msgstr "Доод Сорбин" + +msgid "Greek" +msgstr "Грек" + +msgid "English" +msgstr "Англи" + +msgid "Australian English" +msgstr "Австрали Англи" + +msgid "British English" +msgstr "Британи Англи" + +msgid "Esperanto" +msgstr "Эсперанто" + +msgid "Spanish" +msgstr "Испани" + +msgid "Argentinian Spanish" +msgstr "Аргентинийн Испани" + +msgid "Colombian Spanish" +msgstr "Колумбийн Испаниар" + +msgid "Mexican Spanish" +msgstr "Мексикийн Испани" + +msgid "Nicaraguan Spanish" +msgstr "Никрагуан Испани" + +msgid "Venezuelan Spanish" +msgstr "Венесуэлийн Спани" + +msgid "Estonian" +msgstr "Эстони" + +msgid "Basque" +msgstr "Баск" + +msgid "Persian" +msgstr "Перс" + +msgid "Finnish" +msgstr "Финлянд" + +msgid "French" +msgstr "Франц" + +msgid "Frisian" +msgstr "Фриз" + +msgid "Irish" +msgstr "Ирланд" + +msgid "Scottish Gaelic" +msgstr "Шотландийн Гаелик" + +msgid "Galician" +msgstr "Галици" + +msgid "Hebrew" +msgstr "Еврэй" + +msgid "Hindi" +msgstr "Хинди" + +msgid "Croatian" +msgstr "Хорват" + +msgid "Upper Sorbian" +msgstr "Дээд Сорбин" + +msgid "Hungarian" +msgstr "Унгар" + +msgid "Armenian" +msgstr "Армен" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Индонези" + +msgid "Ido" +msgstr "Идо" + +msgid "Icelandic" +msgstr "Исланд" + +msgid "Italian" +msgstr "Итали" + +msgid "Japanese" +msgstr "Япон" + +msgid "Georgian" +msgstr "Гүрж" + +msgid "Kabyle" +msgstr "Кабилэ" + +msgid "Kazakh" +msgstr "Казак" + +msgid "Khmer" +msgstr "Кхмер" + +msgid "Kannada" +msgstr "Канад" + +msgid "Korean" +msgstr "Солонгос" + +msgid "Luxembourgish" +msgstr "Лүксенбүргиш" + +msgid "Lithuanian" +msgstr "Литва" + +msgid "Latvian" +msgstr "Латви" + +msgid "Macedonian" +msgstr "Македон" + +msgid "Malayalam" +msgstr "Малайз" + +msgid "Mongolian" +msgstr "Монгол" + +msgid "Marathi" +msgstr "маратхи" + +msgid "Burmese" +msgstr "Бирм" + +msgid "Norwegian Bokmål" +msgstr "Норвеги Бокмал" + +msgid "Nepali" +msgstr "Непал" + +msgid "Dutch" +msgstr "Голланд" + +msgid "Norwegian Nynorsk" +msgstr "Норвегийн нюнорск" + +msgid "Ossetic" +msgstr "Оссетик" + +msgid "Punjabi" +msgstr "Панжаби" + +msgid "Polish" +msgstr "Польш" + +msgid "Portuguese" +msgstr "Португал" + +msgid "Brazilian Portuguese" +msgstr "Бразилийн Португали" + +msgid "Romanian" +msgstr "Румын" + +msgid "Russian" +msgstr "Орос" + +msgid "Slovak" +msgstr "Словак" + +msgid "Slovenian" +msgstr "Словен" + +msgid "Albanian" +msgstr "Альбани" + +msgid "Serbian" +msgstr "Серби" + +msgid "Serbian Latin" +msgstr "Серби латин" + +msgid "Swedish" +msgstr "Щвед" + +msgid "Swahili" +msgstr "Савахил" + +msgid "Tamil" +msgstr "Тамил" + +msgid "Telugu" +msgstr "Тэлүгү" + +msgid "Thai" +msgstr "Тайланд" + +msgid "Turkish" +msgstr "Турк" + +msgid "Tatar" +msgstr "Татар" + +msgid "Udmurt" +msgstr "Удмурт" + +msgid "Ukrainian" +msgstr "Украйн" + +msgid "Urdu" +msgstr "Урду" + +msgid "Uzbek" +msgstr "Узбек" + +msgid "Vietnamese" +msgstr "Вьетнам" + +msgid "Simplified Chinese" +msgstr "Хятад (хялбаршуулсан) " + +msgid "Traditional Chinese" +msgstr "Хятад (уламжлалт)" + +msgid "Messages" +msgstr "Мэдээллүүд" + +msgid "Site Maps" +msgstr "Сайтын бүтэц" + +msgid "Static Files" +msgstr "Статик файлууд" + +msgid "Syndication" +msgstr "Нэгтгэл" + +msgid "That page number is not an integer" +msgstr "Хуудасны дугаар бүхэл тоо / Integer / биш байна" + +msgid "That page number is less than 1" +msgstr "Хуудасны дугаар 1-ээс байга байна" + +msgid "That page contains no results" +msgstr "Хуудас үр дүн агуулаагүй байна" + +msgid "Enter a valid value." +msgstr "Зөв утга оруулна уу." + +msgid "Enter a valid URL." +msgstr "Зөв, хүчинтэй хаяг (URL) оруулна уу." + +msgid "Enter a valid integer." +msgstr "Бүхэл тоо оруулна уу" + +msgid "Enter a valid email address." +msgstr "Зөв имэйл хаяг оруулна уу" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Зөв IPv4 хаяг оруулна уу. " + +msgid "Enter a valid IPv6 address." +msgstr "Зөв IPv6 хаяг оруулна уу." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Зөв IPv4 эсвэл IPv6 хаяг оруулна уу." + +msgid "Enter only digits separated by commas." +msgstr "Зөвхөн таслалаар тусгаарлагдсан цифр оруулна уу." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Энэ утга хамгийн ихдээ %(limit_value)s байх ёстой. (одоо %(show_value)s " +"байна)" + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Энэ утга %(limit_value)s -с бага эсвэл тэнцүү байх ёстой." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Энэ утга %(limit_value)s -с их эсвэл тэнцүү байх нөхцлийг хангана уу." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Хамгийн ихдээ %(limit_value)d тэмдэгт байх нөхцлийг хангана уу. " +"(%(show_value)d-ийн дагуу)" +msgstr[1] "" +"Хамгийн ихдээ %(limit_value)d тэмдэгт байх нөхцлийг хангана уу. " +"(%(show_value)d-ийн дагуу)" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[1] "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Тоон утга оруулна уу." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "%(max)s -ээс ихгүй утга оруулна уу " +msgstr[1] "%(max)s -ээс ихгүй утга оруулна уу " + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Энд %(max)s -аас олонгүй бутархайн орон байх ёстой. " +msgstr[1] "Энд %(max)s -аас олонгүй бутархайн орон байх ёстой. " + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "Энд бутархайн таслалаас өмнө %(max)s-аас олонгүй цифр байх ёстой." +msgstr[1] "Энд бутархайн таслалаас өмнө %(max)s-аас олонгүй цифр байх ёстой." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "Хоосон тэмдэгт зөвшөөрөгдөхгүй." + +msgid "and" +msgstr "ба" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(field_labels)s талбар бүхий %(model_name)s аль хэдийн орсон байна." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "%(value)r буруу сонголт байна." + +msgid "This field cannot be null." +msgstr "Энэ хэсгийг хоосон орхиж болохгүй." + +msgid "This field cannot be blank." +msgstr "Энэ хэсэг хоосон байж болохгүй." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(field_label)s-тэй %(model_name)s-ийг аль хэдийнэ оруулсан байна." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s талбарт давхардахгүй байх хэрэгтэй %(date_field_label)s " +"%(lookup_type)s оруулна." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Талбарийн төрөл нь : %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "Boolean (Үнэн худлын аль нэг нь)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Бичвэр (%(max_length)s хүртэл)" + +msgid "Comma-separated integers" +msgstr "Таслалаар тусгаарлагдсан бүхэл тоо" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "Огноо (цаггүй)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Огноо (цагтай)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Аравтын бутархайт тоо" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "Үргэлжлэх хугацаа" + +msgid "Email address" +msgstr "Имэйл хаяг" + +msgid "File path" +msgstr "Файлын зам " + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "“%(value)s” бутархай тоон утга байх ёстой." + +msgid "Floating point number" +msgstr "Хөвөгч таслалтай тоо" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "Бүхэл тоо" + +msgid "Big (8 byte) integer" +msgstr "Том (8 байт) бүхэл тоо" + +msgid "IPv4 address" +msgstr "IPv4 хаяг" + +msgid "IP address" +msgstr "IP хаяг" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "Boolean (Үнэн, худал, эсвэл юу ч биш)" + +msgid "Positive integer" +msgstr "Бүхэл тоох утга" + +msgid "Positive small integer" +msgstr "Бага бүхэл тоон утга" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Слаг (ихдээ %(max_length)s )" + +msgid "Small integer" +msgstr "Бага тоон утна" + +msgid "Text" +msgstr "Текст" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Цаг" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Бинари өгөгдөл" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "UUID" + +msgid "File" +msgstr "Файл" + +msgid "Image" +msgstr "Зураг" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(field)s %(value)r утгатай %(model)s байхгүй байна." + +msgid "Foreign Key (type determined by related field)" +msgstr "Гадаад түлхүүр (тодорхой төрлийн холбоос талбар)" + +msgid "One-to-one relationship" +msgstr "Нэг-нэг холбоос" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s холбоос" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s холбоосууд" + +msgid "Many-to-many relationship" +msgstr "Олон-олон холбоос" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Энэ талбарыг бөглөх шаардлагатай." + +msgid "Enter a whole number." +msgstr "Бүхэл тоон утга оруулна уу." + +msgid "Enter a valid date." +msgstr "Зөв огноо оруулна уу." + +msgid "Enter a valid time." +msgstr "Зөв цаг оруулна уу." + +msgid "Enter a valid date/time." +msgstr "Огноо/цаг-ыг зөв оруулна уу." + +msgid "Enter a valid duration." +msgstr "Үргэлжилэх хугацааг зөв оруулна уу." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Өдөрийн утга {min_days} ээс {max_days} ийн хооронд байх ёстой." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Файл оруулаагүй байна. Маягтаас кодлох төрлийг чагтал. " + +msgid "No file was submitted." +msgstr "Файл оруулаагүй байна." + +msgid "The submitted file is empty." +msgstr "Оруулсан файл хоосон байна. " + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[1] "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Нэг бол сонголтын чягтыг авах эсвэл файл оруулна уу. Зэрэг хэрэгжих " +"боломжгүй." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Зөв зураг оруулна уу. Таны оруулсан файл нэг бол зургийн файл биш эсвэл " +"гэмтсэн зураг байна." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Зөв сонголт хийнэ үү. %(value)s гэсэн сонголт байхгүй байна." + +msgid "Enter a list of values." +msgstr "Өгөгдхүүний жагсаалтаа оруулна уу." + +msgid "Enter a complete value." +msgstr "Бүрэн утга оруулна уу." + +msgid "Enter a valid UUID." +msgstr "Зөв UUID оруулна уу." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Нууц талбар%(name)s) %(error)s" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "УдирдахФормын мэдээлэл олдсонгүй эсвэл өөрчлөгдсөн байна" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "%d ихгүй форм илгээн үү" +msgstr[1] "%d ихгүй форм илгээн үү" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "%d эсвэл их форм илгээнэ үү" +msgstr[1] "%d эсвэл их форм илгээнэ үү" + +msgid "Order" +msgstr "Эрэмбэлэх" + +msgid "Delete" +msgstr "Устгах" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "%(field)s хэсэг дэх давхардсан утгыг засварлана уу. " + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"%(field)s хэсэг дэх давхардсан утгыг засварлана уу. Түүний утгууд " +"давхардахгүй байх ёстой." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"%(field_name)s хэсэг дэх давхардсан утгыг засварлана уу. %(date_field)s-н " +"%(lookup)s хувьд давхардахгүй байх ёстой." + +msgid "Please correct the duplicate values below." +msgstr "Доорх давхардсан утгуудыг засна уу." + +msgid "The inline value did not match the parent instance." +msgstr "Inline утга эцэг обекттой таарахгүй байна." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Зөв сонголт хийнэ үү. Энэ утга сонголтонд алга." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Цэвэрлэх" + +msgid "Currently" +msgstr "Одоогийн" + +msgid "Change" +msgstr "Засах" + +msgid "Unknown" +msgstr "Тодорхойгүй" + +msgid "Yes" +msgstr "Тийм" + +msgid "No" +msgstr "Үгүй" + +msgid "Year" +msgstr "Жил" + +msgid "Month" +msgstr "Сар" + +msgid "Day" +msgstr "Өдөр" + +msgid "yes,no,maybe" +msgstr "тийм,үгүй,магадгүй" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d байт" +msgstr[1] "%(size)d байт" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "шөнө дунд" + +msgid "noon" +msgstr "үд дунд" + +msgid "Monday" +msgstr "Даваа гариг" + +msgid "Tuesday" +msgstr "Мягмар гариг" + +msgid "Wednesday" +msgstr "Лхагва гариг" + +msgid "Thursday" +msgstr "Пүрэв гариг" + +msgid "Friday" +msgstr "Баасан гариг" + +msgid "Saturday" +msgstr "Бямба гариг" + +msgid "Sunday" +msgstr "Ням гариг" + +msgid "Mon" +msgstr "Дав" + +msgid "Tue" +msgstr "Мяг" + +msgid "Wed" +msgstr "Лха" + +msgid "Thu" +msgstr "Пүр" + +msgid "Fri" +msgstr "Баа" + +msgid "Sat" +msgstr "Бям" + +msgid "Sun" +msgstr "Ням" + +msgid "January" +msgstr "1-р сар" + +msgid "February" +msgstr "2-р сар" + +msgid "March" +msgstr "3-р сар" + +msgid "April" +msgstr "4-р сар" + +msgid "May" +msgstr "5-р сар" + +msgid "June" +msgstr "6-р сар" + +msgid "July" +msgstr "7-р сар" + +msgid "August" +msgstr "8-р сар" + +msgid "September" +msgstr "9-р сар" + +msgid "October" +msgstr "10-р сар" + +msgid "November" +msgstr "11-р сар" + +msgid "December" +msgstr "12-р сар" + +msgid "jan" +msgstr "1-р сар" + +msgid "feb" +msgstr "2-р сар" + +msgid "mar" +msgstr "3-р сар" + +msgid "apr" +msgstr "4-р сар" + +msgid "may" +msgstr "5-р сар" + +msgid "jun" +msgstr "6-р сар" + +msgid "jul" +msgstr "7-р сар" + +msgid "aug" +msgstr "8-р сар " + +msgid "sep" +msgstr "9-р сар" + +msgid "oct" +msgstr "10-р сар" + +msgid "nov" +msgstr "11-р сар" + +msgid "dec" +msgstr "12-р сар" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "1-р сар." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "2-р сар." + +msgctxt "abbrev. month" +msgid "March" +msgstr "3-р сар." + +msgctxt "abbrev. month" +msgid "April" +msgstr "4-р сар." + +msgctxt "abbrev. month" +msgid "May" +msgstr "5-р сар." + +msgctxt "abbrev. month" +msgid "June" +msgstr "6-р сар." + +msgctxt "abbrev. month" +msgid "July" +msgstr "7-р сар." + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "8-р сар." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "9-р сар." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "10-р сар." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "11-р сар." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "12-р сар." + +msgctxt "alt. month" +msgid "January" +msgstr "Хулгана" + +msgctxt "alt. month" +msgid "February" +msgstr "Үхэр" + +msgctxt "alt. month" +msgid "March" +msgstr "Бар" + +msgctxt "alt. month" +msgid "April" +msgstr "Туулай" + +msgctxt "alt. month" +msgid "May" +msgstr "Луу" + +msgctxt "alt. month" +msgid "June" +msgstr "Могой" + +msgctxt "alt. month" +msgid "July" +msgstr "Морь" + +msgctxt "alt. month" +msgid "August" +msgstr "Хонь" + +msgctxt "alt. month" +msgid "September" +msgstr "Бич" + +msgctxt "alt. month" +msgid "October" +msgstr "Тахиа" + +msgctxt "alt. month" +msgid "November" +msgstr "Нохой" + +msgctxt "alt. month" +msgid "December" +msgstr "Гахай" + +msgid "This is not a valid IPv6 address." +msgstr "Энэ буруу IPv6 хаяг байна." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "буюу" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d жил" +msgstr[1] "%d жил" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d сар" +msgstr[1] "%d сар" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d долоо хоног" +msgstr[1] "%d долоо хоног" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d өдөр" +msgstr[1] "%d өдөр" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d цаг" +msgstr[1] "%d цаг" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d минут" +msgstr[1] "%d минут" + +msgid "0 minutes" +msgstr "0 минут" + +msgid "Forbidden" +msgstr "Хориотой" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF дээр уналаа. Хүсэлт таслагдсан." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Энэ хуудсанд форм илгээхийн тулд CSRF күүки шаардлагатай учир Та энэ " +"мэдэгдлийг харж байна. Энэ күүки нь гуравдагч этгээдээс хамгаалахын тулд " +"шаардлагатай." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "DEBUG=True үед дэлгэрэнгүй мэдээлэл харах боломжтой." + +msgid "No year specified" +msgstr "Он тодорхойлоогүй байна" + +msgid "Date out of range" +msgstr "Хугацааны хязгаар хэтэрсэн байна" + +msgid "No month specified" +msgstr "Сар тодорхойлоогүй байна" + +msgid "No day specified" +msgstr "Өдөр тодорхойлоогүй байна" + +msgid "No week specified" +msgstr "Долоо хоног тодорхойлоогүй байна" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "%(verbose_name_plural)s боломжгүй" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"%(class_name)s.allow_future нь худлаа учраас %(verbose_name_plural)s нь " +"боломжгүй." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Шүүлтүүрт таарах %(verbose_name)s олдсонгүй " + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Буруу хуудас (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Файлын жагсаалтыг энд зөвшөөрөөгүй." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "“%(path)s” хуудас байхгүй байна." + +#, python-format +msgid "Index of %(directory)s" +msgstr "%(directory)s ийн жагсаалт" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "Джанго: Чанартай бөгөөд хугацаанд нь хийхэд зориулсан Web framework." + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Джанго %(version)s хувирбарын тэмдэглэл харах " + +msgid "The install worked successfully! Congratulations!" +msgstr "Амжилттай суулгалаа! Баяр хүргэе!" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" +"Таний тохиргооны файл дээр DEBUG=TRUE гэж тохируулсан мөн URLs дээр тохиргоо хийгээгүй учраас " +"энэ хуудасыг харж байна." + +msgid "Django Documentation" +msgstr "Джанго баримтжуулалт" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "Хичээл: Санал асуулга App" + +msgid "Get started with Django" +msgstr "Джанготой ажиллаж эхлэх" + +msgid "Django Community" +msgstr "Django Бүлгэм" + +msgid "Connect, get help, or contribute" +msgstr "Холбогдох, тусламж авах эсвэл хувь нэмрээ оруулах" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mn/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mn/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mn/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mn/formats.py new file mode 100644 index 0000000..589c24c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mn/formats.py @@ -0,0 +1,21 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "d F Y" +TIME_FORMAT = "g:i A" +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +# MONTH_DAY_FORMAT = +SHORT_DATE_FORMAT = "j M Y" +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +# DECIMAL_SEPARATOR = +# THOUSAND_SEPARATOR = +# NUMBER_GROUPING = diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..46c9f34 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mr/LC_MESSAGES/django.po new file mode 100644 index 0000000..ab69085 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/mr/LC_MESSAGES/django.po @@ -0,0 +1,1212 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Suraj Kawade, 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Marathi (http://www.transifex.com/django/django/language/" +"mr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mr\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "अफ्रिकान्स" + +msgid "Arabic" +msgstr "अरेबिक" + +msgid "Asturian" +msgstr "" + +msgid "Azerbaijani" +msgstr "अझरबैजानी" + +msgid "Bulgarian" +msgstr "बल्गेरियन" + +msgid "Belarusian" +msgstr "बेलारूसी" + +msgid "Bengali" +msgstr "बंगाली" + +msgid "Breton" +msgstr "ब्रेटन" + +msgid "Bosnian" +msgstr "बोस्नियन" + +msgid "Catalan" +msgstr "कॅटलान" + +msgid "Czech" +msgstr "झेक" + +msgid "Welsh" +msgstr "वेल्श" + +msgid "Danish" +msgstr "डॅनिश" + +msgid "German" +msgstr "जर्मन" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "ग्रीक" + +msgid "English" +msgstr "इंग्रजी" + +msgid "Australian English" +msgstr "" + +msgid "British English" +msgstr "ब्रिटिश इंग्रजी" + +msgid "Esperanto" +msgstr "एस्पेरॅन्टो" + +msgid "Spanish" +msgstr "स्पॅनिश " + +msgid "Argentinian Spanish" +msgstr "अर्जेन्टिनाची स्पॅनिश" + +msgid "Colombian Spanish" +msgstr "" + +msgid "Mexican Spanish" +msgstr "मेक्सिकन स्पॅनिश" + +msgid "Nicaraguan Spanish" +msgstr "" + +msgid "Venezuelan Spanish" +msgstr "" + +msgid "Estonian" +msgstr "" + +msgid "Basque" +msgstr "" + +msgid "Persian" +msgstr "" + +msgid "Finnish" +msgstr "" + +msgid "French" +msgstr "" + +msgid "Frisian" +msgstr "" + +msgid "Irish" +msgstr "" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "" + +msgid "Hebrew" +msgstr "" + +msgid "Hindi" +msgstr "" + +msgid "Croatian" +msgstr "" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "" + +msgid "Indonesian" +msgstr "" + +msgid "Ido" +msgstr "" + +msgid "Icelandic" +msgstr "" + +msgid "Italian" +msgstr "" + +msgid "Japanese" +msgstr "" + +msgid "Georgian" +msgstr "" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "" + +msgid "Khmer" +msgstr "" + +msgid "Kannada" +msgstr "" + +msgid "Korean" +msgstr "" + +msgid "Luxembourgish" +msgstr "" + +msgid "Lithuanian" +msgstr "" + +msgid "Latvian" +msgstr "" + +msgid "Macedonian" +msgstr "" + +msgid "Malayalam" +msgstr "" + +msgid "Mongolian" +msgstr "" + +msgid "Marathi" +msgstr "" + +msgid "Burmese" +msgstr "" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "" + +msgid "Dutch" +msgstr "" + +msgid "Norwegian Nynorsk" +msgstr "" + +msgid "Ossetic" +msgstr "" + +msgid "Punjabi" +msgstr "" + +msgid "Polish" +msgstr "" + +msgid "Portuguese" +msgstr "" + +msgid "Brazilian Portuguese" +msgstr "" + +msgid "Romanian" +msgstr "" + +msgid "Russian" +msgstr "" + +msgid "Slovak" +msgstr "" + +msgid "Slovenian" +msgstr "" + +msgid "Albanian" +msgstr "" + +msgid "Serbian" +msgstr "" + +msgid "Serbian Latin" +msgstr "" + +msgid "Swedish" +msgstr "" + +msgid "Swahili" +msgstr "" + +msgid "Tamil" +msgstr "" + +msgid "Telugu" +msgstr "" + +msgid "Thai" +msgstr "" + +msgid "Turkish" +msgstr "" + +msgid "Tatar" +msgstr "" + +msgid "Udmurt" +msgstr "" + +msgid "Ukrainian" +msgstr "" + +msgid "Urdu" +msgstr "" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "" + +msgid "Simplified Chinese" +msgstr "" + +msgid "Traditional Chinese" +msgstr "" + +msgid "Messages" +msgstr "" + +msgid "Site Maps" +msgstr "" + +msgid "Static Files" +msgstr "" + +msgid "Syndication" +msgstr "" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "" + +msgid "Enter a valid URL." +msgstr "" + +msgid "Enter a valid integer." +msgstr "" + +msgid "Enter a valid email address." +msgstr "" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "" + +msgid "Enter a valid IPv6 address." +msgstr "" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "" + +msgid "Enter only digits separated by commas." +msgstr "" + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Enter a number." +msgstr "" + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "" + +msgid "This field cannot be blank." +msgstr "" + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "" + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "" + +msgid "Comma-separated integers" +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "" + +msgid "Email address" +msgstr "" + +msgid "File path" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "" + +msgid "Big (8 byte) integer" +msgstr "" + +msgid "IPv4 address" +msgstr "" + +msgid "IP address" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "" + +msgid "Positive integer" +msgstr "" + +msgid "Positive small integer" +msgstr "" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "" + +msgid "Small integer" +msgstr "" + +msgid "Text" +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "" + +msgid "URL" +msgstr "" + +msgid "Raw binary data" +msgstr "" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "" + +msgid "Image" +msgstr "" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "" + +msgid "One-to-one relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "" + +msgid "Enter a whole number." +msgstr "" + +msgid "Enter a valid date." +msgstr "" + +msgid "Enter a valid time." +msgstr "" + +msgid "Enter a valid date/time." +msgstr "" + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" + +msgid "No file was submitted." +msgstr "" + +msgid "The submitted file is empty." +msgstr "" + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" + +msgid "Enter a list of values." +msgstr "" + +msgid "Enter a complete value." +msgstr "" + +msgid "Enter a valid UUID." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "" + +msgid "Delete" +msgstr "" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "" + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" + +msgid "Please correct the duplicate values below." +msgstr "" + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "" + +msgid "Currently" +msgstr "" + +msgid "Change" +msgstr "" + +msgid "Unknown" +msgstr "" + +msgid "Yes" +msgstr "" + +msgid "No" +msgstr "" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%s KB" +msgstr "" + +#, python-format +msgid "%s MB" +msgstr "" + +#, python-format +msgid "%s GB" +msgstr "" + +#, python-format +msgid "%s TB" +msgstr "" + +#, python-format +msgid "%s PB" +msgstr "" + +msgid "p.m." +msgstr "" + +msgid "a.m." +msgstr "" + +msgid "PM" +msgstr "" + +msgid "AM" +msgstr "" + +msgid "midnight" +msgstr "" + +msgid "noon" +msgstr "" + +msgid "Monday" +msgstr "" + +msgid "Tuesday" +msgstr "" + +msgid "Wednesday" +msgstr "" + +msgid "Thursday" +msgstr "" + +msgid "Friday" +msgstr "" + +msgid "Saturday" +msgstr "" + +msgid "Sunday" +msgstr "" + +msgid "Mon" +msgstr "" + +msgid "Tue" +msgstr "" + +msgid "Wed" +msgstr "" + +msgid "Thu" +msgstr "" + +msgid "Fri" +msgstr "" + +msgid "Sat" +msgstr "" + +msgid "Sun" +msgstr "" + +msgid "January" +msgstr "" + +msgid "February" +msgstr "" + +msgid "March" +msgstr "" + +msgid "April" +msgstr "" + +msgid "May" +msgstr "" + +msgid "June" +msgstr "" + +msgid "July" +msgstr "" + +msgid "August" +msgstr "" + +msgid "September" +msgstr "" + +msgid "October" +msgstr "" + +msgid "November" +msgstr "" + +msgid "December" +msgstr "" + +msgid "jan" +msgstr "" + +msgid "feb" +msgstr "" + +msgid "mar" +msgstr "" + +msgid "apr" +msgstr "" + +msgid "may" +msgstr "" + +msgid "jun" +msgstr "" + +msgid "jul" +msgstr "" + +msgid "aug" +msgstr "" + +msgid "sep" +msgstr "" + +msgid "oct" +msgstr "" + +msgid "nov" +msgstr "" + +msgid "dec" +msgstr "" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "" + +msgctxt "abbrev. month" +msgid "March" +msgstr "" + +msgctxt "abbrev. month" +msgid "April" +msgstr "" + +msgctxt "abbrev. month" +msgid "May" +msgstr "" + +msgctxt "abbrev. month" +msgid "June" +msgstr "" + +msgctxt "abbrev. month" +msgid "July" +msgstr "" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "" + +msgctxt "alt. month" +msgid "January" +msgstr "" + +msgctxt "alt. month" +msgid "February" +msgstr "" + +msgctxt "alt. month" +msgid "March" +msgstr "" + +msgctxt "alt. month" +msgid "April" +msgstr "" + +msgctxt "alt. month" +msgid "May" +msgstr "" + +msgctxt "alt. month" +msgid "June" +msgstr "" + +msgctxt "alt. month" +msgid "July" +msgstr "" + +msgctxt "alt. month" +msgid "August" +msgstr "" + +msgctxt "alt. month" +msgid "September" +msgstr "" + +msgctxt "alt. month" +msgid "October" +msgstr "" + +msgctxt "alt. month" +msgid "November" +msgstr "" + +msgctxt "alt. month" +msgid "December" +msgstr "" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "" + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" + +msgid "0 minutes" +msgstr "" + +msgid "Forbidden" +msgstr "" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "" + +msgid "No day specified" +msgstr "" + +msgid "No week specified" +msgstr "" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "" + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ms/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ms/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9081340 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ms/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ms/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ms/LC_MESSAGES/django.po new file mode 100644 index 0000000..5884745 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ms/LC_MESSAGES/django.po @@ -0,0 +1,1286 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jafry Hisham, 2021 +# Mariusz Felisiak , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2021-12-06 07:43+0000\n" +"Last-Translator: Mariusz Felisiak \n" +"Language-Team: Malay (http://www.transifex.com/django/django/language/ms/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ms\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Afrikaans" +msgstr "Bahasa Afrikaans" + +msgid "Arabic" +msgstr "Bahasa Arab" + +msgid "Algerian Arabic" +msgstr "Bahasa Arab Algeria" + +msgid "Asturian" +msgstr "Bahasa Asturia" + +msgid "Azerbaijani" +msgstr "Bahasa Azerbaijan" + +msgid "Bulgarian" +msgstr "Bahasa Bulgaria" + +msgid "Belarusian" +msgstr "Bahasa Belarus" + +msgid "Bengali" +msgstr "Bahasa Benggali" + +msgid "Breton" +msgstr "Bahasa Breton" + +msgid "Bosnian" +msgstr "Bahasa Bosnia" + +msgid "Catalan" +msgstr "Bahasa Catalonia" + +msgid "Czech" +msgstr "Bahasa Czech" + +msgid "Welsh" +msgstr "Bahasa Wales" + +msgid "Danish" +msgstr "Bahasa Denmark" + +msgid "German" +msgstr "Bahasa Jerman" + +msgid "Lower Sorbian" +msgstr "Bahasa Sorbian Rendah" + +msgid "Greek" +msgstr "Bahasa Yunani" + +msgid "English" +msgstr "Bahasa Inggeris" + +msgid "Australian English" +msgstr "Bahasa Inggeris Australia" + +msgid "British English" +msgstr "Bahasa Inggeris British" + +msgid "Esperanto" +msgstr "Bahasa Esperanto" + +msgid "Spanish" +msgstr "Bahasa Sepanyol" + +msgid "Argentinian Spanish" +msgstr "Bahasa Sepanyol Argentina" + +msgid "Colombian Spanish" +msgstr "Bahasa Sepanyol Kolumbia" + +msgid "Mexican Spanish" +msgstr "Bahasa Sepanyol Mexico" + +msgid "Nicaraguan Spanish" +msgstr "Bahasa Sepanyol Nicaragua" + +msgid "Venezuelan Spanish" +msgstr "Bahasa Sepanyol Venezuela" + +msgid "Estonian" +msgstr "Bahasa Estonia" + +msgid "Basque" +msgstr "Bahasa Bask" + +msgid "Persian" +msgstr "Bahasa Farsi" + +msgid "Finnish" +msgstr "Bahassa Finland" + +msgid "French" +msgstr "Bahasa Perancis" + +msgid "Frisian" +msgstr "Bahasa Frisia" + +msgid "Irish" +msgstr "Bahasa Ireland" + +msgid "Scottish Gaelic" +msgstr "Bahasa Gael Scotland" + +msgid "Galician" +msgstr "Bahasa Galisia" + +msgid "Hebrew" +msgstr "Bahasa Ibrani" + +msgid "Hindi" +msgstr "Bahasa Hindi" + +msgid "Croatian" +msgstr "Bahasa Kroatia" + +msgid "Upper Sorbian" +msgstr "Bahasa Sorbia Atasan" + +msgid "Hungarian" +msgstr "Bahasa Hungary" + +msgid "Armenian" +msgstr "Bahasa Armenia" + +msgid "Interlingua" +msgstr "Bahasa Interlingua" + +msgid "Indonesian" +msgstr "Bahasa Indonesia" + +msgid "Igbo" +msgstr "Bahasa Igbo" + +msgid "Ido" +msgstr "Bahasa Ido" + +msgid "Icelandic" +msgstr "Bahasa Iceland" + +msgid "Italian" +msgstr "Bahasa Itali" + +msgid "Japanese" +msgstr "Bahasa Jepun" + +msgid "Georgian" +msgstr "Bahasa Georgia" + +msgid "Kabyle" +msgstr "Bahasa Kabylia" + +msgid "Kazakh" +msgstr "Bahasa Kazakhstan" + +msgid "Khmer" +msgstr "Bahasa Kambodia" + +msgid "Kannada" +msgstr "Bahasa Kannada" + +msgid "Korean" +msgstr "Bahasa Korea" + +msgid "Kyrgyz" +msgstr "Bahasa Kyrgyzstan" + +msgid "Luxembourgish" +msgstr "Bahasa Luxemborg" + +msgid "Lithuanian" +msgstr "Bahasa Lithuania" + +msgid "Latvian" +msgstr "Bahasa Latvia" + +msgid "Macedonian" +msgstr "Bahasa Masedonia" + +msgid "Malayalam" +msgstr "Malayalam" + +msgid "Mongolian" +msgstr "Bahasa Mongol" + +msgid "Marathi" +msgstr "Marathi" + +msgid "Malay" +msgstr "Bahasa Melayu" + +msgid "Burmese" +msgstr "Bahasa Burma" + +msgid "Norwegian Bokmål" +msgstr "Bahasa Bokmal Norway" + +msgid "Nepali" +msgstr "Bahasa Nepal" + +msgid "Dutch" +msgstr "Belanda" + +msgid "Norwegian Nynorsk" +msgstr "Bahasa Nynorsk Norway" + +msgid "Ossetic" +msgstr "Bahasa Ossetic" + +msgid "Punjabi" +msgstr "Bahasa Punjab" + +msgid "Polish" +msgstr "Bahasa Poland" + +msgid "Portuguese" +msgstr "Bahasa Portugal" + +msgid "Brazilian Portuguese" +msgstr "Bahasa Portugal Brazil" + +msgid "Romanian" +msgstr "Bahasa Romania" + +msgid "Russian" +msgstr "Bahasa Rusia" + +msgid "Slovak" +msgstr "Bahasa Slovakia" + +msgid "Slovenian" +msgstr "Bahasa Slovenia" + +msgid "Albanian" +msgstr "Bahasa Albania" + +msgid "Serbian" +msgstr "Bahasa Serbia" + +msgid "Serbian Latin" +msgstr "Bahasa Latin Serbia" + +msgid "Swedish" +msgstr "Bahasa Sweden" + +msgid "Swahili" +msgstr "Bahasa Swahili" + +msgid "Tamil" +msgstr "Bahasa Tamil" + +msgid "Telugu" +msgstr "Bahasa Telugu" + +msgid "Tajik" +msgstr "Bahasa Tajik" + +msgid "Thai" +msgstr "Bahasa Siam" + +msgid "Turkmen" +msgstr "Bahasa Turkmenistan" + +msgid "Turkish" +msgstr "Bahasa Turki" + +msgid "Tatar" +msgstr "Bahasa Tatar" + +msgid "Udmurt" +msgstr "Bahasa Udmurt" + +msgid "Ukrainian" +msgstr "Bahasa Ukraine" + +msgid "Urdu" +msgstr "Bahasa Urdu" + +msgid "Uzbek" +msgstr "Bahasa Uzbekistan" + +msgid "Vietnamese" +msgstr "Bahasa Vietnam" + +msgid "Simplified Chinese" +msgstr "Bahasa Cina (Dipermudahkan)" + +msgid "Traditional Chinese" +msgstr "Bahasa Cina Tradisional" + +msgid "Messages" +msgstr "Mesej" + +msgid "Site Maps" +msgstr "Peta Laman" + +msgid "Static Files" +msgstr "Fail Statik" + +msgid "Syndication" +msgstr "Sindikasi" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "..." + +msgid "That page number is not an integer" +msgstr "Nombor ruangan itu bukanlah integer" + +msgid "That page number is less than 1" +msgstr "Nombor ruangan itu kurang daripada 1" + +msgid "That page contains no results" +msgstr "Ruangan itu tiada keputusan" + +msgid "Enter a valid value." +msgstr "Masukkan nilai yang sah." + +msgid "Enter a valid URL." +msgstr "Masukkan URL yang sah." + +msgid "Enter a valid integer." +msgstr "Masukkan integer yang sah." + +msgid "Enter a valid email address." +msgstr "Masukkan alamat emel yang sah." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Masukkan \"slug\" yang sah yang mengandungi huruf, nombor, garisan atau " +"tanda sempang." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Masukkan \"slug\" yang sah yang mengandungi huruf Unicode, nombor, garisan, " +"atau tanda sempang." + +msgid "Enter a valid IPv4 address." +msgstr "Masukkan alamat IPv4 yang sah." + +msgid "Enter a valid IPv6 address." +msgstr "Masukkan alamat IPv6 yang sah." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Masukkan alamat IPv4 atau IPv6 yang sah." + +msgid "Enter only digits separated by commas." +msgstr "Hanya masukkan digit yang dipisahkan oleh koma." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Pastikan nilai ini adalah %(limit_value)s (ia adalah %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Pastikan nilai ini kurang daripada atau sama dengan %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Pastikan nilai ini lebih daripada atau sama dengan %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Pastikan nilai ini mempunyai sekurang-kurangnya %(limit_value)d karater (ia " +"mempunyai %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Pastikan nilai ini mempunyai sepalingnya %(limit_value)d karakter (ia " +"mempunyai %(show_value)d)." + +msgid "Enter a number." +msgstr "Masukkan nombor." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Pastikan jumlah tidak melebihi %(max)s digit." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Pastikan titik perpuluhan tidak melebihi %(max)s." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Pastikan jumlah digit tidak melebihi %(max)s sebelum titik perpuluhan." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Sambungan fail \"%(extension)s\" tidak dibenarkan. Sambungan yang dibenarkan " +"adalah: %(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Karakter Null tidak dibenarkan." + +msgid "and" +msgstr "dan" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s dengan %(field_labels)s ini sudah wujud." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Nilai %(value)r bukan pilihan yang sah." + +msgid "This field cannot be null." +msgstr "Medan ini tidak boleh null." + +msgid "This field cannot be blank." +msgstr "Medan ini tidak boleh dibiarkan kosong." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s dengan %(field_label)s ini sudah wujud." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "%(field_label)s mesti unik untuk %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Jenis medan: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "Nilai \"%(value)s\" mesti samada True atau False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "Nilai \"%(value)s\" mesti samada True, False, atau None." + +msgid "Boolean (Either True or False)" +msgstr "Boolean (Samada True atau False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "String (sehingga %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "Integer dipisahkan dengan koma" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"Nilai \"%(value)s\" mempunyai format tarikh yang tidak sah. Format harus " +"berbentuk YYYY-MM-DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"Nilai \"%(value)s\" mempunyai format yang betul (YYYY-MM-DD) tetapi ia " +"adalah tarikh yang tidak sah." + +msgid "Date (without time)" +msgstr "Tarikh (tanpa masa)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"Nilai \"%(value)s\" mempunyai format yang tidak sah. Format harus berbentuk " +"YYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"Nilai \"%(value)s\" mempunyai format yang betul (YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ]) tetapi ia adalah tarikh/masa yang tidak sah." + +msgid "Date (with time)" +msgstr "Tarikh (dengan masa)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "Nilai \"%(value)s\" mesti dalam bentuk nombor titik perpuluhan." + +msgid "Decimal number" +msgstr "Nombor titik perpuluhan" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"Nilai \"%(value)s\" mempunyai format yang tidak sah. Format harus berbentuk " +"[DD] [[HH:]MM:]ss[.uuuuuu]." + +msgid "Duration" +msgstr "Jangka-masa" + +msgid "Email address" +msgstr "Alama emel" + +msgid "File path" +msgstr "Laluan fail" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "Nilai \"%(value)s\" mesti dalam bentuk titik terapung." + +msgid "Floating point number" +msgstr "Nombor titik terapung" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "Nilai \"%(value)s\" mesti dalam bentuk integer." + +msgid "Integer" +msgstr "Integer" + +msgid "Big (8 byte) integer" +msgstr "Integer besar (8 bait)" + +msgid "Small integer" +msgstr "Integer kecil" + +msgid "IPv4 address" +msgstr "Alamat IPv4" + +msgid "IP address" +msgstr "Alamat IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "Nilai \"%(value)s\" mesti samada None, True, atau False." + +msgid "Boolean (Either True, False or None)" +msgstr "Boolean (samada True, False, None)" + +msgid "Positive big integer" +msgstr "Integer besar positif" + +msgid "Positive integer" +msgstr "Integer positif" + +msgid "Positive small integer" +msgstr "Integer kecil positif" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (sehingga %(max_length)s)" + +msgid "Text" +msgstr "Teks" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"Nilai \"%(value)s\" mempunyai format yang tidak sah. Format harus berbentuk " +"HH:MM[:ss[.uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"Nilai \"%(value)s\" mempunyai format yang betul (HH:MM[:ss[.uuuuuu]]) tetapi " +"ia mempunyai masa yang tidak sah." + +msgid "Time" +msgstr "Masa" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Data binari mentah" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "UUID \"%(value)s\" tidak sah." + +msgid "Universally unique identifier" +msgstr "Pengecam unik universal" + +msgid "File" +msgstr "Fail" + +msgid "Image" +msgstr "Imej" + +msgid "A JSON object" +msgstr "Objek JSON" + +msgid "Value must be valid JSON." +msgstr "Nilai harus dalam bentuk JSON yang sah." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(model)s dengan %(field)s %(value)r tidak wujud." + +msgid "Foreign Key (type determined by related field)" +msgstr "Kunci Asing (jenis ditentukan oleh medan yang berkaitan)" + +msgid "One-to-one relationship" +msgstr "Hubungan satu-ke-satu" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "Hubungan %(from)s-%(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "Hubungan %(from)s-%(to)s" + +msgid "Many-to-many relationship" +msgstr "Hubungan banyak-ke-banyak" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Medan ini diperlukan." + +msgid "Enter a whole number." +msgstr "Masukkan nombor bulat." + +msgid "Enter a valid date." +msgstr "Masukkan tarikh yang sah." + +msgid "Enter a valid time." +msgstr "Masukkan masa yang sah." + +msgid "Enter a valid date/time." +msgstr "Masukkan tarikh/masa yang sah." + +msgid "Enter a valid duration." +msgstr "Masukkan jangka-masa yang sah." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Jumlah hari mesti diantara {min_days} ke {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Tiada fail yang dihantar. Periksa jenis encoding pada borang." + +msgid "No file was submitted." +msgstr "Tiada fail yang dihantar." + +msgid "The submitted file is empty." +msgstr "Fail yang dihantar kosong." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Pastikan nama fial ini tidak melebihi %(max)d karakter (ia mempunyai " +"%(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Sila hantar fail atau tandakan pada kotak, bukan kedua-duanya sekali. " + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Muatnaik imej yang sah. Fail yang anda muatnaik samada bukan imej atau imej " +"yang rosak." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Pilih pilihan yang sah. %(value)s bukan pilihan yang tersedia." + +msgid "Enter a list of values." +msgstr "Masukkan senarai nilai." + +msgid "Enter a complete value." +msgstr "Masukkan nilai yang lengkap." + +msgid "Enter a valid UUID." +msgstr "Masukkan UUID yang sah." + +msgid "Enter a valid JSON." +msgstr "Masukkan JSON yang sah." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "%(error)s (Medan tersorok %(name)s)" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"Data ManagementForm tidak dijumpai atau telah diusik. Medan yang hilang: " +"%(field_names)s. Anda mungkin perlu menghantar laporan pepijat sekiranya " +"masalah masih berterusan." + +#, python-format +msgid "Please submit at most %d form." +msgid_plural "Please submit at most %d forms." +msgstr[0] "Sila hantar tidak lebih dari %d borang." + +#, python-format +msgid "Please submit at least %d form." +msgid_plural "Please submit at least %d forms." +msgstr[0] "Sila hantar sekurang-kurangnya %d borang." + +msgid "Order" +msgstr "Susunan" + +msgid "Delete" +msgstr "Padam" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Sila betulkan data duplikasi bagi %(field)s" + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Sila betulkan data duplikasi bagi %(field)s, yang mana mestilah unik." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Sila betulkan data duplikasi bagi %(field_name)s yang mana mestilah unik " +"untuk %(lookup)s didalam %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Sila betulkan nilai-nilai duplikasi dibawah." + +msgid "The inline value did not match the parent instance." +msgstr "Nilai didalam barisan tidak sepadan dengan parent instance." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Pilih pilihan yang sah. Pilihan itu tidak ada didalam senarai pilihan." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "\"%(pk)s\" bukan nilai yang sah." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s tidak dapat diterjemahkan ke dalam zon masa " +"%(current_timezone)s; ia mungkin samar-samar atau tidak wujud." + +msgid "Clear" +msgstr "Kosongkan" + +msgid "Currently" +msgstr "Kini" + +msgid "Change" +msgstr "Tukar" + +msgid "Unknown" +msgstr "Tidak diketahui" + +msgid "Yes" +msgstr "Ya" + +msgid "No" +msgstr "Tidak" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "ya,tidak,mungkin" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d bait" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "malam" + +msgid "a.m." +msgstr "pagi" + +msgid "PM" +msgstr "MALAM" + +msgid "AM" +msgstr "PAGI" + +msgid "midnight" +msgstr "tengah malam" + +msgid "noon" +msgstr "tengahari" + +msgid "Monday" +msgstr "Isnin" + +msgid "Tuesday" +msgstr "Selasa" + +msgid "Wednesday" +msgstr "Rabu" + +msgid "Thursday" +msgstr "Khamis" + +msgid "Friday" +msgstr "Jumaat" + +msgid "Saturday" +msgstr "Sabtu" + +msgid "Sunday" +msgstr "Ahad" + +msgid "Mon" +msgstr "Isn" + +msgid "Tue" +msgstr "Sel" + +msgid "Wed" +msgstr "Rab" + +msgid "Thu" +msgstr "Kha" + +msgid "Fri" +msgstr "Jum" + +msgid "Sat" +msgstr "Sab" + +msgid "Sun" +msgstr "Aha" + +msgid "January" +msgstr "Januari" + +msgid "February" +msgstr "Februari" + +msgid "March" +msgstr "Mac" + +msgid "April" +msgstr "April" + +msgid "May" +msgstr "Mei" + +msgid "June" +msgstr "Jun" + +msgid "July" +msgstr "Julai" + +msgid "August" +msgstr "Ogos" + +msgid "September" +msgstr "September" + +msgid "October" +msgstr "Oktober" + +msgid "November" +msgstr "November" + +msgid "December" +msgstr "Disember" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "apr" + +msgid "may" +msgstr "mei" + +msgid "jun" +msgstr "jun" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "ogo" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "okt" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dis" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb" + +msgctxt "abbrev. month" +msgid "March" +msgstr "Mac" + +msgctxt "abbrev. month" +msgid "April" +msgstr "April" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Mei" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Jun" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Julai" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Ogo." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Sept." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Okt." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dis." + +msgctxt "alt. month" +msgid "January" +msgstr "Januari" + +msgctxt "alt. month" +msgid "February" +msgstr "Februari" + +msgctxt "alt. month" +msgid "March" +msgstr "Mac" + +msgctxt "alt. month" +msgid "April" +msgstr "April" + +msgctxt "alt. month" +msgid "May" +msgstr "Mei" + +msgctxt "alt. month" +msgid "June" +msgstr "Jun" + +msgctxt "alt. month" +msgid "July" +msgstr "Julai" + +msgctxt "alt. month" +msgid "August" +msgstr "Ogos" + +msgctxt "alt. month" +msgid "September" +msgstr "September" + +msgctxt "alt. month" +msgid "October" +msgstr "Oktober" + +msgctxt "alt. month" +msgid "November" +msgstr "November" + +msgctxt "alt. month" +msgid "December" +msgstr "Disember" + +msgid "This is not a valid IPv6 address." +msgstr "Alamat IPv6 ini tidak sah." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s ..." + +msgid "or" +msgstr "atau" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "," + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d tahun" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d bulan" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d minggu " + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d hari" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d jam" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minit" + +msgid "Forbidden" +msgstr "Dilarang" + +msgid "CSRF verification failed. Request aborted." +msgstr "Verifikasi VSRF gagal. Permintaan dihentikan." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Anda melihat mesej ini kerana laman HTTPS ini memerlukan \"Referer header\" " +"dihantar ke pelayar sesawang anda, tetapi ia tidak dihantar. Header ini " +"diperlukan bagi tujuan keselamatan, agar dapat memastikan pelayar anda tidak " +"dirampas oleh pihak ketiga." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Sekiranya anda telah menetapkan pelayar anda untuk mematikan header \"Referer" +"\", sila hidupkannya semula, sekurang-kurangya bagi laman ini, atau bagi " +"sambungan HTTPS, atau bagi permintaan \"same-origin\"." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Sekiranya anda menggunakan tag atau memasukkan header \"Referer-Policy: no-referrer\", sila buangkan " +"ia. Perlindungan CSRF memerlukan header \"Referer\" untuk melakukan " +"penyemakan referer yang ketat. Sekiranya anda risau tentang privasi anda, " +"gunakan alternatif seperti bagi pautan laman pihak " +"ketiga." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Anda melihat mesej ini kerana laman ini memerlukan cookie CSRF apabila " +"menghantar borang. Cookie ini diperlukan bagi tujuan keselamatan, bagi " +"memastikan pelayar anda tidak dirampas oleh pihak ketiga." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Sekiranya anda telah menetapkan pelayar anda untuk tidak menerima cookie, " +"sila hidupkannya semula, sekurang-kurangnya bagi laman ini, atau bagi " +"permintaan \"same-origin\"." + +msgid "More information is available with DEBUG=True." +msgstr "Maklumat lanjut boleh didapati dengan menetapkan DEBUG=True." + +msgid "No year specified" +msgstr "Tiada tahun diberikan" + +msgid "Date out of range" +msgstr "Tarikh diluar julat" + +msgid "No month specified" +msgstr "Tiada bulan diberikan" + +msgid "No day specified" +msgstr "Tiada hari diberikan" + +msgid "No week specified" +msgstr "Tiada minggu diberikan" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "%(verbose_name_plural)s tiada" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"%(verbose_name_plural)s masa depan tiada kerana %(class_name)s.allow_future " +"adalah False. " + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" +"\"%(datestr)s\" tarikh yang diberikan tidak sah mengikut format \"%(format)s" +"\"" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Tiada %(verbose_name)s mengikut pertanyaan yang dimasukkan" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Ruangan ini bukan \"last\", dan tidak boleh ditukar kepada int." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Ruangan tidak sah (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Senarai kosong dan \"%(class_name)s.allow_empty\" adalah False." + +msgid "Directory indexes are not allowed here." +msgstr "Indeks Direktori tidak dibenarkan disini." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "\"%(path)s\" tidak wujud" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Indeks %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Pemasangan berjaya dilakukan! Tahniah!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Lihat nota pelepasan bagi Django %(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" +"Anda melihat ruangan ini kerana DEBUG=True terdapat didalam fail tetapan anda dan anda tidak " +"menetapkan sebarang URL." + +msgid "Django Documentation" +msgstr "Dokumentasi Django" + +msgid "Topics, references, & how-to’s" +msgstr "Topik, rujukan, & bagaimana-cara" + +msgid "Tutorial: A Polling App" +msgstr "Tutorial: App Soal-Selidik" + +msgid "Get started with Django" +msgstr "Mulakan dengan Django" + +msgid "Django Community" +msgstr "Komuniti Django" + +msgid "Connect, get help, or contribute" +msgstr "Sambung, minta bantuan, atau sumbang" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ms/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ms/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ms/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ms/formats.py new file mode 100644 index 0000000..d06719f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ms/formats.py @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j M Y" # '25 Oct 2006' +TIME_FORMAT = "P" # '2:30 p.m.' +DATETIME_FORMAT = "j M Y, P" # '25 Oct 2006, 2:30 p.m.' +YEAR_MONTH_FORMAT = "F Y" # 'October 2006' +MONTH_DAY_FORMAT = "j F" # '25 October' +SHORT_DATE_FORMAT = "d/m/Y" # '25/10/2006' +SHORT_DATETIME_FORMAT = "d/m/Y P" # '25/10/2006 2:30 p.m.' +FIRST_DAY_OF_WEEK = 0 # Sunday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%Y-%m-%d", # '2006-10-25' + "%d/%m/%Y", # '25/10/2006' + "%d/%m/%y", # '25/10/06' + "%d %b %Y", # '25 Oct 2006' + "%d %b, %Y", # '25 Oct, 2006' + "%d %B %Y", # '25 October 2006' + "%d %B, %Y", # '25 October, 2006' +] +DATETIME_INPUT_FORMATS = [ + "%Y-%m-%d %H:%M:%S", # '2006-10-25 14:30:59' + "%Y-%m-%d %H:%M:%S.%f", # '2006-10-25 14:30:59.000200' + "%Y-%m-%d %H:%M", # '2006-10-25 14:30' + "%d/%m/%Y %H:%M:%S", # '25/10/2006 14:30:59' + "%d/%m/%Y %H:%M:%S.%f", # '25/10/2006 14:30:59.000200' + "%d/%m/%Y %H:%M", # '25/10/2006 14:30' + "%d/%m/%y %H:%M:%S", # '25/10/06 14:30:59' + "%d/%m/%y %H:%M:%S.%f", # '25/10/06 14:30:59.000200' + "%d/%m/%y %H:%M", # '25/10/06 14:30' +] +DECIMAL_SEPARATOR = "." +THOUSAND_SEPARATOR = "," +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/my/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/my/LC_MESSAGES/django.mo new file mode 100644 index 0000000..06d9129 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/my/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/my/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/my/LC_MESSAGES/django.po new file mode 100644 index 0000000..a1c7e9a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/my/LC_MESSAGES/django.po @@ -0,0 +1,1197 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Yhal Htet Aung , 2013,2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Burmese (http://www.transifex.com/django/django/language/" +"my/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: my\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Afrikaans" +msgstr "အာဖရိကန်" + +msgid "Arabic" +msgstr "အာရပ်" + +msgid "Asturian" +msgstr "" + +msgid "Azerbaijani" +msgstr "" + +msgid "Bulgarian" +msgstr "ဘူဂေးရီယန်" + +msgid "Belarusian" +msgstr "" + +msgid "Bengali" +msgstr "ဘင်းဂလီ" + +msgid "Breton" +msgstr "" + +msgid "Bosnian" +msgstr "ဘော့်စ်နီယန်" + +msgid "Catalan" +msgstr "ကက်တလန်" + +msgid "Czech" +msgstr "ချက်" + +msgid "Welsh" +msgstr "ဝေးလ်" + +msgid "Danish" +msgstr "ဒိန်းမတ်" + +msgid "German" +msgstr "ဂျာမန်" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "ဂရိ" + +msgid "English" +msgstr "အင်္ဂလိပ်" + +msgid "Australian English" +msgstr "" + +msgid "British English" +msgstr "ဗြိတိသျှအင်္ဂလိပ်" + +msgid "Esperanto" +msgstr "" + +msgid "Spanish" +msgstr "စပိန်" + +msgid "Argentinian Spanish" +msgstr "" + +msgid "Colombian Spanish" +msgstr "" + +msgid "Mexican Spanish" +msgstr "" + +msgid "Nicaraguan Spanish" +msgstr "" + +msgid "Venezuelan Spanish" +msgstr "" + +msgid "Estonian" +msgstr "" + +msgid "Basque" +msgstr "" + +msgid "Persian" +msgstr "" + +msgid "Finnish" +msgstr "" + +msgid "French" +msgstr "" + +msgid "Frisian" +msgstr "" + +msgid "Irish" +msgstr "" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "" + +msgid "Hebrew" +msgstr "" + +msgid "Hindi" +msgstr "" + +msgid "Croatian" +msgstr "" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "" + +msgid "Indonesian" +msgstr "" + +msgid "Ido" +msgstr "" + +msgid "Icelandic" +msgstr "" + +msgid "Italian" +msgstr "" + +msgid "Japanese" +msgstr "" + +msgid "Georgian" +msgstr "" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "" + +msgid "Khmer" +msgstr "" + +msgid "Kannada" +msgstr "" + +msgid "Korean" +msgstr "" + +msgid "Luxembourgish" +msgstr "" + +msgid "Lithuanian" +msgstr "" + +msgid "Latvian" +msgstr "" + +msgid "Macedonian" +msgstr "" + +msgid "Malayalam" +msgstr "" + +msgid "Mongolian" +msgstr "" + +msgid "Marathi" +msgstr "" + +msgid "Burmese" +msgstr "" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "" + +msgid "Dutch" +msgstr "" + +msgid "Norwegian Nynorsk" +msgstr "" + +msgid "Ossetic" +msgstr "" + +msgid "Punjabi" +msgstr "" + +msgid "Polish" +msgstr "" + +msgid "Portuguese" +msgstr "" + +msgid "Brazilian Portuguese" +msgstr "" + +msgid "Romanian" +msgstr "" + +msgid "Russian" +msgstr "" + +msgid "Slovak" +msgstr "" + +msgid "Slovenian" +msgstr "" + +msgid "Albanian" +msgstr "" + +msgid "Serbian" +msgstr "" + +msgid "Serbian Latin" +msgstr "" + +msgid "Swedish" +msgstr "" + +msgid "Swahili" +msgstr "" + +msgid "Tamil" +msgstr "" + +msgid "Telugu" +msgstr "" + +msgid "Thai" +msgstr "" + +msgid "Turkish" +msgstr "" + +msgid "Tatar" +msgstr "" + +msgid "Udmurt" +msgstr "" + +msgid "Ukrainian" +msgstr "" + +msgid "Urdu" +msgstr "" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "" + +msgid "Simplified Chinese" +msgstr "" + +msgid "Traditional Chinese" +msgstr "" + +msgid "Messages" +msgstr "" + +msgid "Site Maps" +msgstr "" + +msgid "Static Files" +msgstr "" + +msgid "Syndication" +msgstr "" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "" + +msgid "Enter a valid URL." +msgstr "" + +msgid "Enter a valid integer." +msgstr "" + +msgid "Enter a valid email address." +msgstr "" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "" + +msgid "Enter a valid IPv6 address." +msgstr "" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "" + +msgid "Enter only digits separated by commas." +msgstr "" + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" + +msgid "Enter a number." +msgstr "" + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "နှင့်" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "" + +msgid "This field cannot be blank." +msgstr "" + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "" + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "" + +msgid "Comma-separated integers" +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "" + +msgid "Email address" +msgstr "အီးမေးလ်လိပ်စာ" + +msgid "File path" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "ကိန်းပြည့်" + +msgid "Big (8 byte) integer" +msgstr "" + +msgid "IPv4 address" +msgstr "အိုင်ပီဗီ၄လိပ်စာ" + +msgid "IP address" +msgstr "အိုင်ပီလိပ်စာ" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "" + +msgid "Positive integer" +msgstr "" + +msgid "Positive small integer" +msgstr "" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "" + +msgid "Small integer" +msgstr "" + +msgid "Text" +msgstr "စာသား" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "" + +msgid "URL" +msgstr "ယူအာအယ်" + +msgid "Raw binary data" +msgstr "" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "ဖိုင်" + +msgid "Image" +msgstr "ပံု" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "" + +msgid "One-to-one relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr "" + +msgid "This field is required." +msgstr "" + +msgid "Enter a whole number." +msgstr "" + +msgid "Enter a valid date." +msgstr "" + +msgid "Enter a valid time." +msgstr "" + +msgid "Enter a valid date/time." +msgstr "" + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" + +msgid "No file was submitted." +msgstr "" + +msgid "The submitted file is empty." +msgstr "" + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" + +msgid "Enter a list of values." +msgstr "" + +msgid "Enter a complete value." +msgstr "" + +msgid "Enter a valid UUID." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr "" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" + +msgid "Order" +msgstr "မှာကြား" + +msgid "Delete" +msgstr "ပယ်ဖျက်" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "" + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" + +msgid "Please correct the duplicate values below." +msgstr "" + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "" + +msgid "Currently" +msgstr "" + +msgid "Change" +msgstr "" + +msgid "Unknown" +msgstr "အမည်မသိ" + +msgid "Yes" +msgstr "ဟုတ်" + +msgid "No" +msgstr "မဟုတ်" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d ဘိုက်များ" + +#, python-format +msgid "%s KB" +msgstr "%s ကီလိုဘိုက်" + +#, python-format +msgid "%s MB" +msgstr "%s မက်ဂါဘိုက်" + +#, python-format +msgid "%s GB" +msgstr "%s ဂစ်ဂါဘိုက်" + +#, python-format +msgid "%s TB" +msgstr "%s တီရာဘိုက်" + +#, python-format +msgid "%s PB" +msgstr "%s ပီတာဘိုက်" + +msgid "p.m." +msgstr "ညနေ" + +msgid "a.m." +msgstr "မနက်" + +msgid "PM" +msgstr "ညနေ" + +msgid "AM" +msgstr "မနက်" + +msgid "midnight" +msgstr "သန်းခေါင်" + +msgid "noon" +msgstr "မွန်းတည့်" + +msgid "Monday" +msgstr "တနင်္လာနေ့" + +msgid "Tuesday" +msgstr "" + +msgid "Wednesday" +msgstr "" + +msgid "Thursday" +msgstr "" + +msgid "Friday" +msgstr "" + +msgid "Saturday" +msgstr "" + +msgid "Sunday" +msgstr "" + +msgid "Mon" +msgstr "" + +msgid "Tue" +msgstr "" + +msgid "Wed" +msgstr "" + +msgid "Thu" +msgstr "" + +msgid "Fri" +msgstr "" + +msgid "Sat" +msgstr "" + +msgid "Sun" +msgstr "" + +msgid "January" +msgstr "" + +msgid "February" +msgstr "" + +msgid "March" +msgstr "" + +msgid "April" +msgstr "" + +msgid "May" +msgstr "" + +msgid "June" +msgstr "" + +msgid "July" +msgstr "" + +msgid "August" +msgstr "" + +msgid "September" +msgstr "" + +msgid "October" +msgstr "" + +msgid "November" +msgstr "" + +msgid "December" +msgstr "" + +msgid "jan" +msgstr "" + +msgid "feb" +msgstr "" + +msgid "mar" +msgstr "" + +msgid "apr" +msgstr "" + +msgid "may" +msgstr "" + +msgid "jun" +msgstr "" + +msgid "jul" +msgstr "" + +msgid "aug" +msgstr "" + +msgid "sep" +msgstr "" + +msgid "oct" +msgstr "" + +msgid "nov" +msgstr "" + +msgid "dec" +msgstr "" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "" + +msgctxt "abbrev. month" +msgid "March" +msgstr "" + +msgctxt "abbrev. month" +msgid "April" +msgstr "" + +msgctxt "abbrev. month" +msgid "May" +msgstr "" + +msgctxt "abbrev. month" +msgid "June" +msgstr "" + +msgctxt "abbrev. month" +msgid "July" +msgstr "" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "" + +msgctxt "alt. month" +msgid "January" +msgstr "" + +msgctxt "alt. month" +msgid "February" +msgstr "" + +msgctxt "alt. month" +msgid "March" +msgstr "" + +msgctxt "alt. month" +msgid "April" +msgstr "" + +msgctxt "alt. month" +msgid "May" +msgstr "" + +msgctxt "alt. month" +msgid "June" +msgstr "" + +msgctxt "alt. month" +msgid "July" +msgstr "" + +msgctxt "alt. month" +msgid "August" +msgstr "" + +msgctxt "alt. month" +msgid "September" +msgstr "" + +msgctxt "alt. month" +msgid "October" +msgstr "" + +msgctxt "alt. month" +msgid "November" +msgstr "" + +msgctxt "alt. month" +msgid "December" +msgstr "" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "" + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" + +msgid "0 minutes" +msgstr "" + +msgid "Forbidden" +msgstr "" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "" + +msgid "No day specified" +msgstr "" + +msgid "No week specified" +msgstr "" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "" + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c4ebbae Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nb/LC_MESSAGES/django.po new file mode 100644 index 0000000..cb2932b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nb/LC_MESSAGES/django.po @@ -0,0 +1,1324 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Alexander Hansen , 2014 +# Eirik Krogstad , 2014 +# Jannis Leidel , 2011 +# jensadne , 2014-2015 +# Jon, 2015-2016 +# Jon, 2014 +# Jon, 2017-2022 +# Jon, 2013 +# Jon, 2011 +# Sigurd Gartmann , 2012 +# Tommy Strand , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-25 06:49+0000\n" +"Last-Translator: Jon, 2017-2022\n" +"Language-Team: Norwegian Bokmål (http://www.transifex.com/django/django/" +"language/nb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Afrikaans" + +msgid "Arabic" +msgstr "Arabisk" + +msgid "Algerian Arabic" +msgstr "Algerisk arabisk" + +msgid "Asturian" +msgstr "Asturiansk" + +msgid "Azerbaijani" +msgstr "Aserbajdsjansk" + +msgid "Bulgarian" +msgstr "Bulgarsk" + +msgid "Belarusian" +msgstr "Hviterussisk" + +msgid "Bengali" +msgstr "Bengalsk" + +msgid "Breton" +msgstr "Bretonsk" + +msgid "Bosnian" +msgstr "Bosnisk" + +msgid "Catalan" +msgstr "Katalansk" + +msgid "Central Kurdish (Sorani)" +msgstr "" + +msgid "Czech" +msgstr "Tsjekkisk" + +msgid "Welsh" +msgstr "Walisisk" + +msgid "Danish" +msgstr "Dansk" + +msgid "German" +msgstr "Tysk" + +msgid "Lower Sorbian" +msgstr "Lavsorbisk" + +msgid "Greek" +msgstr "Gresk" + +msgid "English" +msgstr "Engelsk" + +msgid "Australian English" +msgstr "Engelsk (australsk)" + +msgid "British English" +msgstr "Engelsk (britisk)" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Spansk" + +msgid "Argentinian Spanish" +msgstr "Argentinsk spansk" + +msgid "Colombian Spanish" +msgstr "Colombiansk spansk" + +msgid "Mexican Spanish" +msgstr "Meksikansk spansk" + +msgid "Nicaraguan Spanish" +msgstr "Nicaraguansk spansk" + +msgid "Venezuelan Spanish" +msgstr "Venezuelanske spansk" + +msgid "Estonian" +msgstr "Estisk" + +msgid "Basque" +msgstr "Baskisk" + +msgid "Persian" +msgstr "Persisk" + +msgid "Finnish" +msgstr "Finsk" + +msgid "French" +msgstr "Fransk" + +msgid "Frisian" +msgstr "Frisisk" + +msgid "Irish" +msgstr "Irsk" + +msgid "Scottish Gaelic" +msgstr "Skotsk-gælisk" + +msgid "Galician" +msgstr "Galisisk" + +msgid "Hebrew" +msgstr "Hebraisk" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Kroatisk" + +msgid "Upper Sorbian" +msgstr "Høysorbisk" + +msgid "Hungarian" +msgstr "Ungarsk" + +msgid "Armenian" +msgstr "Armensk" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonesisk" + +msgid "Igbo" +msgstr "Ibo" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Islandsk" + +msgid "Italian" +msgstr "Italiensk" + +msgid "Japanese" +msgstr "Japansk" + +msgid "Georgian" +msgstr "Georgisk" + +msgid "Kabyle" +msgstr "Kabylsk" + +msgid "Kazakh" +msgstr "Kasakhisk" + +msgid "Khmer" +msgstr "Khmer" + +msgid "Kannada" +msgstr "Kannada" + +msgid "Korean" +msgstr "Koreansk" + +msgid "Kyrgyz" +msgstr "Kirgisisk" + +msgid "Luxembourgish" +msgstr "Luxembourgsk" + +msgid "Lithuanian" +msgstr "Litauisk" + +msgid "Latvian" +msgstr "Latvisk" + +msgid "Macedonian" +msgstr "Makedonsk" + +msgid "Malayalam" +msgstr "Malayalam" + +msgid "Mongolian" +msgstr "Mongolsk" + +msgid "Marathi" +msgstr "Marathi" + +msgid "Malay" +msgstr "Malayisk" + +msgid "Burmese" +msgstr "Burmesisk" + +msgid "Norwegian Bokmål" +msgstr "Norsk (bokmål)" + +msgid "Nepali" +msgstr "Nepali" + +msgid "Dutch" +msgstr "Nederlandsk" + +msgid "Norwegian Nynorsk" +msgstr "Norsk (nynorsk)" + +msgid "Ossetic" +msgstr "Ossetisk" + +msgid "Punjabi" +msgstr "Panjabi" + +msgid "Polish" +msgstr "Polsk" + +msgid "Portuguese" +msgstr "Portugisisk" + +msgid "Brazilian Portuguese" +msgstr "Brasiliansk portugisisk" + +msgid "Romanian" +msgstr "Rumensk" + +msgid "Russian" +msgstr "Russisk" + +msgid "Slovak" +msgstr "Slovakisk" + +msgid "Slovenian" +msgstr "Slovensk" + +msgid "Albanian" +msgstr "Albansk" + +msgid "Serbian" +msgstr "Serbisk" + +msgid "Serbian Latin" +msgstr "Serbisk latin" + +msgid "Swedish" +msgstr "Svensk" + +msgid "Swahili" +msgstr "Swahili" + +msgid "Tamil" +msgstr "Tamil" + +msgid "Telugu" +msgstr "Telugu" + +msgid "Tajik" +msgstr "Tadsjikisk" + +msgid "Thai" +msgstr "Thai" + +msgid "Turkmen" +msgstr "Turkmensk" + +msgid "Turkish" +msgstr "Tyrkisk" + +msgid "Tatar" +msgstr "Tatarisk" + +msgid "Udmurt" +msgstr "Udmurtisk" + +msgid "Ukrainian" +msgstr "Ukrainsk" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "Usbekisk" + +msgid "Vietnamese" +msgstr "Vietnamesisk" + +msgid "Simplified Chinese" +msgstr "Forenklet kinesisk" + +msgid "Traditional Chinese" +msgstr "Tradisjonell kinesisk" + +msgid "Messages" +msgstr "Meldinger" + +msgid "Site Maps" +msgstr "Sidekart" + +msgid "Static Files" +msgstr "Statiske filer" + +msgid "Syndication" +msgstr "Syndikering" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Sidenummeret er ikke et heltall" + +msgid "That page number is less than 1" +msgstr "Sidenummeret er mindre enn 1" + +msgid "That page contains no results" +msgstr "Siden inneholder ingen resultater" + +msgid "Enter a valid value." +msgstr "Oppgi en gyldig verdi." + +msgid "Enter a valid URL." +msgstr "Oppgi en gyldig nettadresse." + +msgid "Enter a valid integer." +msgstr "Skriv inn et gyldig heltall." + +msgid "Enter a valid email address." +msgstr "Oppgi en gyldig e-postadresse" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Oppgi en gyldig \"slug\" bestående av bokstaver, nummer, understreker eller " +"bindestreker." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Oppgi en gyldig \"slug\" bestående av Unicode-bokstaver, nummer, " +"understreker eller bindestreker." + +msgid "Enter a valid IPv4 address." +msgstr "Oppgi en gyldig IPv4-adresse." + +msgid "Enter a valid IPv6 address." +msgstr "Oppgi en gyldig IPv6-adresse." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Oppgi en gyldig IPv4- eller IPv6-adresse." + +msgid "Enter only digits separated by commas." +msgstr "Oppgi kun tall adskilt med komma." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Verdien må være %(limit_value)s (den er %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Verdien må være mindre enn eller lik %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Verdien må være større enn eller lik %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "Verdien må være et multiplum av trinnstørrelse %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Sørg for denne verdien har minst %(limit_value)d tegn (den har " +"%(show_value)d)." +msgstr[1] "" +"Sørg for at denne verdien har minst %(limit_value)d tegn (den har " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Sørg for denne verdien har %(limit_value)d tegn (den har nå %(show_value)d)." +msgstr[1] "" +"Sørg for at denne verdien har %(limit_value)d eller færre tegn (den har nå " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Oppgi et tall." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Sørg for at det er kun %(max)s tall." +msgstr[1] "Sørg for at det er %(max)s eller færre tall totalt." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Sørg for at det er kun %(max)s desimal." +msgstr[1] "Sørg for at det er %(max)s eller færre desimaler." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "Sørg for at det kun %(max)s tall før desimalpunkt." +msgstr[1] "Sørg for at det er %(max)s eller færre tall før desimalpunkt." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Filendelsen \"%(extension)s\" er ikke tillatt. Tillatte filendelser er: " +"%(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Null-tegn er ikke tillatt." + +msgid "and" +msgstr "og" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s med denne %(field_labels)s finnes allerede." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Begrensning \"%(name)s\" er brutt." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Verdien %(value)r er ikke et gyldig valg." + +msgid "This field cannot be null." +msgstr "Feltet kan ikke være tomt." + +msgid "This field cannot be blank." +msgstr "Feltet kan ikke være blankt." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s med %(field_label)s finnes allerede." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "%(field_label)s må være unik for %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Felt av typen: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "\"%(value)s\"-verdien må være enten True eller False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "\"%(value)s\"-verdien må være enten True, False, eller None." + +msgid "Boolean (Either True or False)" +msgstr "Boolsk (True eller False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Tekst (opp til %(max_length)s tegn)" + +msgid "String (unlimited)" +msgstr "" + +msgid "Comma-separated integers" +msgstr "Heltall adskilt med komma" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"\"%(value)s\"-verdien har et ugyldig datoformat. Det må være på formen YYYY-" +"MM-DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"\"%(value)s\"-verdien er på den korrekte formen (YYYY-MM-DD), men det er en " +"ugyldig dato." + +msgid "Date (without time)" +msgstr "Dato (uten tid)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"\"%(value)s\"-verdien har et ugyldig datoformat. Det må være på formen YYYY-" +"MM-DD HH:MM[:ss[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"\"%(value)s\"-verdien er på den korrekte formen (YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ]), men er ugyldig dato/tid." + +msgid "Date (with time)" +msgstr "Dato (med tid)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "\"%(value)s\"-verdien må være et desimaltall." + +msgid "Decimal number" +msgstr "Desimaltall" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"\"%(value)s\"-verdien har et ugyldig format. Det må være på formen [DD] [HH:" +"[MM:]]ss[.uuuuuu]." + +msgid "Duration" +msgstr "Varighet" + +msgid "Email address" +msgstr "E-postadresse" + +msgid "File path" +msgstr "Filsti" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "Verdien \"%(value)s\" må være et flyttall." + +msgid "Floating point number" +msgstr "Flyttall" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "\"%(value)s\"-verdien må være et heltall." + +msgid "Integer" +msgstr "Heltall" + +msgid "Big (8 byte) integer" +msgstr "Stort (8 byte) heltall" + +msgid "Small integer" +msgstr "Lite heltall" + +msgid "IPv4 address" +msgstr "IPv4-adresse" + +msgid "IP address" +msgstr "IP-adresse" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "Verdien \"%(value)s\" må være enten None, True eller False." + +msgid "Boolean (Either True, False or None)" +msgstr "Boolsk (True, False eller None)" + +msgid "Positive big integer" +msgstr "Positivt stort heltall" + +msgid "Positive integer" +msgstr "Positivt heltall" + +msgid "Positive small integer" +msgstr "Positivt lite heltall" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (opp til %(max_length)s)" + +msgid "Text" +msgstr "Tekst" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"\"%(value)s\"-verdien har et ugyldig format. Det må være på formen HH:MM[:" +"ss[.uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"Verdien \"%(value)s\" har riktig format (HH:MM[:ss[.uuuuuu]]), men er ikke " +"et gyldig klokkeslett." + +msgid "Time" +msgstr "Tid" + +msgid "URL" +msgstr "Nettadresse" + +msgid "Raw binary data" +msgstr "Rå binærdata" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "\"%(value)s\" er ikke en gyldig UUID." + +msgid "Universally unique identifier" +msgstr "Universelt unik identifikator" + +msgid "File" +msgstr "Fil" + +msgid "Image" +msgstr "Bilde" + +msgid "A JSON object" +msgstr "Et JSON-objekt" + +msgid "Value must be valid JSON." +msgstr "Verdi må være gyldig JSON." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(model)s-instansen med %(field)s %(value)r finnes ikke." + +msgid "Foreign Key (type determined by related field)" +msgstr "Fremmednøkkel (type bestemmes av relatert felt)" + +msgid "One-to-one relationship" +msgstr "En-til-en-relasjon" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s-relasjon" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s-relasjoner" + +msgid "Many-to-many relationship" +msgstr "Mange-til-mange-relasjon" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Feltet er påkrevet." + +msgid "Enter a whole number." +msgstr "Oppgi et heltall." + +msgid "Enter a valid date." +msgstr "Oppgi en gyldig dato." + +msgid "Enter a valid time." +msgstr "Oppgi et gyldig tidspunkt." + +msgid "Enter a valid date/time." +msgstr "Oppgi gyldig dato og tidspunkt." + +msgid "Enter a valid duration." +msgstr "Oppgi en gyldig varighet." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Antall dager må være mellom {min_days} og {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Ingen fil ble sendt. Sjekk «encoding»-typen på skjemaet." + +msgid "No file was submitted." +msgstr "Ingen fil ble sendt." + +msgid "The submitted file is empty." +msgstr "Filen er tom." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "Sørg for at filnavnet har %(max)d tegn (det har nå %(length)d)." +msgstr[1] "" +"Sørg for at filnavnet har færre enn %(max)d tegn (det har nå %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Vennligst last opp en ny fil eller marker fjern-boksen, ikke begge." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Last opp et gyldig bilde. Filen du lastet opp var ødelagt eller ikke et " +"bilde." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Velg et gyldig valg. %(value)s er ikke et av de tilgjengelige valgene." + +msgid "Enter a list of values." +msgstr "Oppgi en liste med verdier." + +msgid "Enter a complete value." +msgstr "Skriv inn en fullstendig verdi." + +msgid "Enter a valid UUID." +msgstr "Oppgi en gyldig UUID." + +msgid "Enter a valid JSON." +msgstr "Oppgi gyldig JSON." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Skjult felt %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"ManagementForm-data mangler eller har blitt tuklet med. Felt som mangler: " +"%(field_names)s. Du må muligens rapportere en bug hvis problemet vedvarer." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Vennligst send inn maks %(num)d skjema." +msgstr[1] "Vennligst send inn maks %(num)d skjemaer." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Vennligst send inn minst %(num)d skjema." +msgstr[1] "Vennligst send inn minst %(num)d skjemaer." + +msgid "Order" +msgstr "Rekkefølge" + +msgid "Delete" +msgstr "Slett" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Vennligst korriger dupliserte data for %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Vennligst korriger dupliserte data for %(field)s, som må være unike." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Vennligst korriger dupliserte data for %(field_name)s, som må være unike for " +"%(lookup)s i %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Vennligst korriger de dupliserte verdiene nedenfor." + +msgid "The inline value did not match the parent instance." +msgstr "Inline-verdien var ikke i samsvar med foreldre-instansen." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Velg et gyldig valg. Valget er ikke av de tilgjengelige valgene." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "\"%(pk)s\" er ikke en gyldig verdi." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s kunne ikke tolkes i tidssonen %(current_timezone)s, det kan " +"være tvetydig eller ikke eksistere." + +msgid "Clear" +msgstr "Fjern" + +msgid "Currently" +msgstr "Nåværende" + +msgid "Change" +msgstr "Endre" + +msgid "Unknown" +msgstr "Ukjent" + +msgid "Yes" +msgstr "Ja" + +msgid "No" +msgstr "Nei" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "ja,nei,kanskje" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d byte" +msgstr[1] "%(size)d byte" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "midnatt" + +msgid "noon" +msgstr "12:00" + +msgid "Monday" +msgstr "mandag" + +msgid "Tuesday" +msgstr "tirsdag" + +msgid "Wednesday" +msgstr "onsdag" + +msgid "Thursday" +msgstr "torsdag" + +msgid "Friday" +msgstr "fredag" + +msgid "Saturday" +msgstr "lørdag" + +msgid "Sunday" +msgstr "søndag" + +msgid "Mon" +msgstr "man" + +msgid "Tue" +msgstr "tir" + +msgid "Wed" +msgstr "ons" + +msgid "Thu" +msgstr "tor" + +msgid "Fri" +msgstr "fre" + +msgid "Sat" +msgstr "lør" + +msgid "Sun" +msgstr "søn" + +msgid "January" +msgstr "januar" + +msgid "February" +msgstr "februar" + +msgid "March" +msgstr "mars" + +msgid "April" +msgstr "april" + +msgid "May" +msgstr "mai" + +msgid "June" +msgstr "juni" + +msgid "July" +msgstr "juli" + +msgid "August" +msgstr "august" + +msgid "September" +msgstr "september" + +msgid "October" +msgstr "oktober" + +msgid "November" +msgstr "november" + +msgid "December" +msgstr "desember" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "apr" + +msgid "may" +msgstr "mai" + +msgid "jun" +msgstr "jun" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "aug" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "okt" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "des" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "mar." + +msgctxt "abbrev. month" +msgid "April" +msgstr "apr." + +msgctxt "abbrev. month" +msgid "May" +msgstr "mai" + +msgctxt "abbrev. month" +msgid "June" +msgstr "jun." + +msgctxt "abbrev. month" +msgid "July" +msgstr "jul." + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "aug." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "sept." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "okt." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "des." + +msgctxt "alt. month" +msgid "January" +msgstr "Januar" + +msgctxt "alt. month" +msgid "February" +msgstr "Februar" + +msgctxt "alt. month" +msgid "March" +msgstr "Mars" + +msgctxt "alt. month" +msgid "April" +msgstr "April" + +msgctxt "alt. month" +msgid "May" +msgstr "Mai" + +msgctxt "alt. month" +msgid "June" +msgstr "Juni" + +msgctxt "alt. month" +msgid "July" +msgstr "Juli" + +msgctxt "alt. month" +msgid "August" +msgstr "August" + +msgctxt "alt. month" +msgid "September" +msgstr "September" + +msgctxt "alt. month" +msgid "October" +msgstr "Oktober" + +msgctxt "alt. month" +msgid "November" +msgstr "November" + +msgctxt "alt. month" +msgid "December" +msgstr "Desember" + +msgid "This is not a valid IPv6 address." +msgstr "Dette er ikke en gyldig IPv6-adresse." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "eller" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d år" +msgstr[1] "%(num)d år" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d måned" +msgstr[1] "%(num)d måneder" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d uke" +msgstr[1] "%(num)d uker" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dag" +msgstr[1] "%(num)d dager" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d time" +msgstr[1] "%(num)d timer" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minutt" +msgstr[1] "%(num)d minutter" + +msgid "Forbidden" +msgstr "Forbudt" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF-verifisering feilet. Forespørsel avbrutt." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Du ser denne meldingen fordi dette HTTPS-nettstedet krever en 'Referer'-" +"header til å bli sendt av nettleseren, men ingen ble sendt. Denne headeren " +"er nødvendig av sikkerhetsmessige årsaker, for å sikre at nettleseren din " +"ikke blir kapret av tredjeparter." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Hvis du har konfigurert nettleseren din til å deaktivere 'Referer'-headers, " +"kan du aktivere dem, i hvert fall for dette nettstedet, eller for HTTPS-" +"tilkoblinger, eller for 'same-origin'-forespørsler." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Hvis du bruker -taggen eller " +"inkluderer 'Referrer-Policy: no-referrer'-header, vennligst fjern dem. CSRF-" +"beskyttelsen krever 'Referer'-headeren for å utføre streng kontroll av " +"referanser. Hvis du er bekymret for personvern, bruk alternativer som for koblinger til tredjeparts nettsteder." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Du ser denne meldingen fordi denne nettsiden krever en CSRF-cookie når du " +"sender inn skjemaer. Denne informasjonskapselen er nødvendig av " +"sikkerhetsmessige årsaker, for å sikre at nettleseren din ikke blir kapret " +"av tredjeparter." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Hvis du har konfigurert nettleseren din til å deaktivere " +"informasjonskapsler, kan du aktivere dem, i hvert fall for dette nettstedet, " +"eller for 'same-origin'-forespørsler." + +msgid "More information is available with DEBUG=True." +msgstr "Mer informasjon er tilgjengelig med DEBUG=True." + +msgid "No year specified" +msgstr "År ikke spesifisert" + +msgid "Date out of range" +msgstr "Date utenfor rekkevidde" + +msgid "No month specified" +msgstr "Måned ikke spesifisert" + +msgid "No day specified" +msgstr "Dag ikke spesifisert" + +msgid "No week specified" +msgstr "Uke ikke spesifisert" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Ingen %(verbose_name_plural)s tilgjengelig" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Fremtidig %(verbose_name_plural)s ikke tilgjengelig fordi %(class_name)s." +"allow_future er False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Ugyldig datostreng \"%(datestr)s\" gitt formatet \"%(format)s\"" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Fant ingen %(verbose_name)s som passet spørringen" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Siden er ikke \"last\", og kan heller ikke konverteres til et heltall." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Ugyldig side (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Tom liste og \"%(class_name)s.allow_empty\" er False." + +msgid "Directory indexes are not allowed here." +msgstr "Mappeinnhold er ikke tillatt her." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "\"%(path)s\" finnes ikke" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Innhold i %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Installasjonen var vellykket! Gratulerer!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Se produktmerknader for Django " +"%(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Du ser denne siden fordi DEBUG=True er i din Django-innstillingsfil og du ikke " +"har konfigurert noen URL-er." + +msgid "Django Documentation" +msgstr "Django-dokumentasjon" + +msgid "Topics, references, & how-to’s" +msgstr "Temaer, referanser & how-tos" + +msgid "Tutorial: A Polling App" +msgstr "Tutorial: en polling-app" + +msgid "Get started with Django" +msgstr "Kom i gang med Django" + +msgid "Django Community" +msgstr "Django nettsamfunn" + +msgid "Connect, get help, or contribute" +msgstr "Koble, få hjelp eller bidra" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nb/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nb/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nb/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nb/formats.py new file mode 100644 index 0000000..0ddb8fe --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nb/formats.py @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j. F Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = "j. F Y H:i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j. F" +SHORT_DATE_FORMAT = "d.m.Y" +SHORT_DATETIME_FORMAT = "d.m.Y H:i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# Kept ISO formats as they are in first position +DATE_INPUT_FORMATS = [ + "%Y-%m-%d", # '2006-10-25' + "%d.%m.%Y", # '25.10.2006' + "%d.%m.%y", # '25.10.06' + # "%d. %b %Y", # '25. okt 2006' + # "%d %b %Y", # '25 okt 2006' + # "%d. %b. %Y", # '25. okt. 2006' + # "%d %b. %Y", # '25 okt. 2006' + # "%d. %B %Y", # '25. oktober 2006' + # "%d %B %Y", # '25 oktober 2006' +] +DATETIME_INPUT_FORMATS = [ + "%Y-%m-%d %H:%M:%S", # '2006-10-25 14:30:59' + "%Y-%m-%d %H:%M:%S.%f", # '2006-10-25 14:30:59.000200' + "%Y-%m-%d %H:%M", # '2006-10-25 14:30' + "%d.%m.%Y %H:%M:%S", # '25.10.2006 14:30:59' + "%d.%m.%Y %H:%M:%S.%f", # '25.10.2006 14:30:59.000200' + "%d.%m.%Y %H:%M", # '25.10.2006 14:30' + "%d.%m.%y %H:%M:%S", # '25.10.06 14:30:59' + "%d.%m.%y %H:%M:%S.%f", # '25.10.06 14:30:59.000200' + "%d.%m.%y %H:%M", # '25.10.06 14:30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "\xa0" # non-breaking space +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ne/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ne/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2a10814 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ne/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ne/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ne/LC_MESSAGES/django.po new file mode 100644 index 0000000..6882466 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ne/LC_MESSAGES/django.po @@ -0,0 +1,1253 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Claude Paroz , 2020 +# Jannis Leidel , 2014 +# Paras Nath Chaudhary , 2012 +# Sagar Chalise , 2011-2012,2015,2018 +# Sagar Chalise , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-19 20:23+0200\n" +"PO-Revision-Date: 2020-07-14 21:42+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Nepali (http://www.transifex.com/django/django/language/ne/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ne\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "अफ्रिकन" + +msgid "Arabic" +msgstr "अरबिक" + +msgid "Algerian Arabic" +msgstr "" + +msgid "Asturian" +msgstr "अस्टुरियन" + +msgid "Azerbaijani" +msgstr "अजरबैजानी" + +msgid "Bulgarian" +msgstr "बुल्गेरियाली" + +msgid "Belarusian" +msgstr "बेलारुसियन" + +msgid "Bengali" +msgstr "बंगाली" + +msgid "Breton" +msgstr "ब्रेटोन" + +msgid "Bosnian" +msgstr "बोस्नियाली" + +msgid "Catalan" +msgstr "क्याटालान" + +msgid "Czech" +msgstr "चेक" + +msgid "Welsh" +msgstr "वेल्स" + +msgid "Danish" +msgstr "डेनिस" + +msgid "German" +msgstr "जर्मन" + +msgid "Lower Sorbian" +msgstr "तल्लो सोर्बियन" + +msgid "Greek" +msgstr "ग्रिक" + +msgid "English" +msgstr "अंग्रेजी" + +msgid "Australian English" +msgstr "अस्ट्रेलियाली अंग्रेजी" + +msgid "British English" +msgstr "बेलायती अंग्रेजी" + +msgid "Esperanto" +msgstr "इस्परा्न्तो" + +msgid "Spanish" +msgstr "स्पेनिस" + +msgid "Argentinian Spanish" +msgstr "अर्जेन्टिनाली स्पेनिस" + +msgid "Colombian Spanish" +msgstr "कोलम्बियाली स्पेनिस" + +msgid "Mexican Spanish" +msgstr "मेक्सिकन स्पेनिस" + +msgid "Nicaraguan Spanish" +msgstr "निकारागुँवा स्पेनिस" + +msgid "Venezuelan Spanish" +msgstr "भेनेजुएला स्पेनिस" + +msgid "Estonian" +msgstr "इस्टोनियन" + +msgid "Basque" +msgstr "बास्क" + +msgid "Persian" +msgstr "फारसी" + +msgid "Finnish" +msgstr "फिन्निस" + +msgid "French" +msgstr "फ्रान्सेली" + +msgid "Frisian" +msgstr "फ्रिसियन" + +msgid "Irish" +msgstr "आयरिस" + +msgid "Scottish Gaelic" +msgstr "स्कटीस गैलिक" + +msgid "Galician" +msgstr "ग्यलिसियन" + +msgid "Hebrew" +msgstr "हिब्रु" + +msgid "Hindi" +msgstr "हिन्दि " + +msgid "Croatian" +msgstr "क्रोषियन" + +msgid "Upper Sorbian" +msgstr "माथिल्लो सोर्बियन " + +msgid "Hungarian" +msgstr "हन्गेरियन" + +msgid "Armenian" +msgstr "अर्मेनियन" + +msgid "Interlingua" +msgstr "ईन्टरलिन्गुवा" + +msgid "Indonesian" +msgstr "इन्डोनेसियाली" + +msgid "Igbo" +msgstr "" + +msgid "Ido" +msgstr "आइडु" + +msgid "Icelandic" +msgstr "आइसल्यान्डिक" + +msgid "Italian" +msgstr "ईटालियन" + +msgid "Japanese" +msgstr "जापनिज" + +msgid "Georgian" +msgstr "जर्जीयन" + +msgid "Kabyle" +msgstr "कबायल" + +msgid "Kazakh" +msgstr "कजाक" + +msgid "Khmer" +msgstr "ख्मेर" + +msgid "Kannada" +msgstr "कन्नड" + +msgid "Korean" +msgstr "कोरियाली" + +msgid "Kyrgyz" +msgstr "" + +msgid "Luxembourgish" +msgstr "लक्जेमबर्गेली" + +msgid "Lithuanian" +msgstr "लिथुवानियाली" + +msgid "Latvian" +msgstr "लाट्भियन" + +msgid "Macedonian" +msgstr "म्यासेडोनियन" + +msgid "Malayalam" +msgstr "मलायलम" + +msgid "Mongolian" +msgstr "मंगोलियन" + +msgid "Marathi" +msgstr "मराठी" + +msgid "Burmese" +msgstr "बर्मेली" + +msgid "Norwegian Bokmål" +msgstr "नर्वे बक्मल" + +msgid "Nepali" +msgstr "नेपाली" + +msgid "Dutch" +msgstr "डच" + +msgid "Norwegian Nynorsk" +msgstr "नर्वेली न्योर्स्क" + +msgid "Ossetic" +msgstr "ओसेटिक" + +msgid "Punjabi" +msgstr "पञ्जावी" + +msgid "Polish" +msgstr "पोलिस" + +msgid "Portuguese" +msgstr "पुर्तगाली" + +msgid "Brazilian Portuguese" +msgstr "ब्राजिली पुर्तगाली" + +msgid "Romanian" +msgstr "रोमानियाली" + +msgid "Russian" +msgstr "रुसी" + +msgid "Slovak" +msgstr "सलोभाक" + +msgid "Slovenian" +msgstr "स्लोभेनियाली" + +msgid "Albanian" +msgstr "अल्बानियाली" + +msgid "Serbian" +msgstr "सर्वियाली" + +msgid "Serbian Latin" +msgstr "सर्वियाली ल्याटिन" + +msgid "Swedish" +msgstr "स्विडिस" + +msgid "Swahili" +msgstr "स्वाहिली" + +msgid "Tamil" +msgstr "तामिल" + +msgid "Telugu" +msgstr "तेलुगु" + +msgid "Tajik" +msgstr "" + +msgid "Thai" +msgstr "थाई" + +msgid "Turkmen" +msgstr "" + +msgid "Turkish" +msgstr "टर्किस" + +msgid "Tatar" +msgstr "टाटर" + +msgid "Udmurt" +msgstr "उद्मुर्ट" + +msgid "Ukrainian" +msgstr "युक्रेनि" + +msgid "Urdu" +msgstr "उर्दु" + +msgid "Uzbek" +msgstr "उज्बेक" + +msgid "Vietnamese" +msgstr "भियतनामी" + +msgid "Simplified Chinese" +msgstr "सरल चिनि" + +msgid "Traditional Chinese" +msgstr "प्राचिन चिनि" + +msgid "Messages" +msgstr "सुचनाहरु" + +msgid "Site Maps" +msgstr "साइट म्याप्स" + +msgid "Static Files" +msgstr "स्टेेटिक फाइलहरु" + +msgid "Syndication" +msgstr "सिन्डिकेसन" + +msgid "That page number is not an integer" +msgstr "पृष्ठ नं अंक होइन ।" + +msgid "That page number is less than 1" +msgstr "पृष्ठ नं १ भन्दा कम भयो ।" + +msgid "That page contains no results" +msgstr "पृष्ठमा नतिजा छैन ।" + +msgid "Enter a valid value." +msgstr "उपयुक्त मान राख्नुहोस ।" + +msgid "Enter a valid URL." +msgstr "उपयुक्त URL राख्नुहोस ।" + +msgid "Enter a valid integer." +msgstr "उपयुक्त अंक राख्नुहोस ।" + +msgid "Enter a valid email address." +msgstr "सही ई-मेल ठेगाना राख्नु होस ।" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "उपयुक्त IPv4 ठेगाना राख्नुहोस" + +msgid "Enter a valid IPv6 address." +msgstr "उपयुक्त IPv6 ठेगाना राख्नुहोस ।" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "उपयुक्त IPv4 वा IPv6 ठेगाना राख्नुहोस ।" + +msgid "Enter only digits separated by commas." +msgstr "कम्मा सहितका वर्ण मात्र राख्नुहोस ।" + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "यो मान %(limit_value)s छ भन्ने निश्चित गर्नुहोस । (यो %(show_value)s हो ।)" + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "यो मान %(limit_value)s भन्दा कम अथवा बराबर छ भन्ने निश्चित गर्नुहोस ।" + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "यो मान %(limit_value)s भन्दा बढी अथवा बराबर छ भन्ने निशचित गर्नुहोस ।" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"यो मान कम्तिमा पनि %(limit_value)d अक्षर छ भन्ने निश्चित गर्नुहोस । (यसमा " +"%(show_value)d छ ।)" +msgstr[1] "" +"यो मान कम्तिमा पनि %(limit_value)d अक्षरहरु छ भन्ने निश्चित गर्नुहोस । (यसमा " +"%(show_value)d छ ।)" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"यो मान बढिमा पनि %(limit_value)d अक्षर छ भन्ने निश्चित गर्नुहोस । (यसमा " +"%(show_value)d छ ।)" +msgstr[1] "" +"यो मान बढिमा पनि %(limit_value)d अक्षरहरु छ भन्ने निश्चित गर्नुहोस । (यसमा " +"%(show_value)d छ ।)" + +msgid "Enter a number." +msgstr "संख्या राख्नुहोस ।" + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "जम्मा %(max)s भन्दा बढी अक्षर नभएको निश्चित पार्नु होस ।" +msgstr[1] "जम्मा %(max)s भन्दा बढी अक्षरहरु नभएको निश्चित पार्नु होस ।" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "दशमलव पछि %(max)s भन्दा बढी अक्षर नभएको निश्चित पार्नु होस ।" +msgstr[1] "दशमलव पछि %(max)s भन्दा बढी अक्षरहरु नभएको निश्चित पार्नु होस ।" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "दशमलव अघि %(max)s भन्दा बढी अक्षर नभएको निश्चित पार्नु होस ।" +msgstr[1] "दशमलव अघि %(max)s भन्दा बढी अक्षरहरु नभएको निश्चित पार्नु होस ।" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "शून्य मान अनुमति छैन।" + +msgid "and" +msgstr "र" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(field_labels)s भएको %(model_name)s बनि सकेको छ । " + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "%(value)r मान उपयुक्त छनोट होइन ।" + +msgid "This field cannot be null." +msgstr "यो फाँट शून्य हुन सक्दैन ।" + +msgid "This field cannot be blank." +msgstr "यो फाँट खाली हुन सक्दैन ।" + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(field_label)s भएको %(model_name)s पहिलै विद्धमान छ ।" + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(date_field_label)s %(lookup_type)s को लागि %(field_label)s अनुपम हुनु पर्दछ ।" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "फाँटको प्रकार: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "बुलियन (True अथवा False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "वर्ण (%(max_length)s सम्म)" + +msgid "Comma-separated integers" +msgstr "कम्माले छुट्याइएका अंकहरु ।" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "मिति (समय रहित)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "मिति (समय सहित)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "दश्मलव संख्या" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "अवधि" + +msgid "Email address" +msgstr "ई-मेल ठेगाना" + +msgid "File path" +msgstr "फाइलको मार्ग" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "दश्मलव हुने संख्या" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "अंक" + +msgid "Big (8 byte) integer" +msgstr "ठूलो (८ बाइटको) अंक" + +msgid "IPv4 address" +msgstr "आइ.पी.भी४ ठेगाना" + +msgid "IP address" +msgstr "IP ठेगाना" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "बुलियन (True, False अथवा None)" + +msgid "Positive big integer" +msgstr "" + +msgid "Positive integer" +msgstr "सकारात्मक पूर्णांक" + +msgid "Positive small integer" +msgstr "सानो जोड अङ्क" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "स्लग(%(max_length)s सम्म)" + +msgid "Small integer" +msgstr "सानो अङ्क" + +msgid "Text" +msgstr "पाठ" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "समय" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "र बाइनरी डाटा" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "फाइल" + +msgid "Image" +msgstr "चित्र" + +msgid "A JSON object" +msgstr "" + +msgid "Value must be valid JSON." +msgstr "" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "फोरेन कि (प्रकार नातागत फाँटले जनाउछ)" + +msgid "One-to-one relationship" +msgstr "एक-देखि-एक नाता" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s सम्बन्ध" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s सम्बन्धहरु" + +msgid "Many-to-many relationship" +msgstr "अनेक-देखि-अनेक नाता" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "यो फाँट अनिवार्य छ ।" + +msgid "Enter a whole number." +msgstr "संख्या राख्नुहोस ।" + +msgid "Enter a valid date." +msgstr "उपयुक्त मिति राख्नुहोस ।" + +msgid "Enter a valid time." +msgstr "उपयुक्त समय राख्नुहोस ।" + +msgid "Enter a valid date/time." +msgstr "उपयुक्त मिति/समय राख्नुहोस ।" + +msgid "Enter a valid duration." +msgstr "उपयुक्त अवधि राख्नुहोस ।" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "दिन गन्ती {min_days} र {max_days} बीचमा हुनु पर्छ । " + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "कुनै फाईल पेश गरिएको छैन । फारममा ईनकोडिङको प्रकार जाँच गर्नुहोस । " + +msgid "No file was submitted." +msgstr "कुनै फाईल पेश गरिएको छैन ।" + +msgid "The submitted file is empty." +msgstr "पेश गरिएको फाइल खाली छ ।" + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"यो फाइलको नाममा बाढीमा %(max)d अङ्क भएको निश्चित गर्नु होस । (यसमा %(length)d छ " +"।)" +msgstr[1] "" +"यो फाइलको नाममा बढी मा %(max)d अङ्कहरू भएको निश्चित गर्नु होस । (यसमा %(length)d " +"छ ।)" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "दुवै नछान्नुहोस, कि त फाइल पेश गर्नुहोस वा चेक बाकस मा छान्नुहोस ।" + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"उपयुक्त चित्र अपलोड गर्नुहोस । तपाइले अपलोड गर्नु भएको फाइल चित्र होइन वा बिग्रेको चित्र " +"हो ।" + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "उपयुक्त विकल्प छान्नुहोस । %(value)s प्रस्तावित विकल्प होइन ।" + +msgid "Enter a list of values." +msgstr "मानहरु राख्नुहोस" + +msgid "Enter a complete value." +msgstr "पुरा मान राख्नु होस ।" + +msgid "Enter a valid UUID." +msgstr "उपयुक्त UUID राख्नु होस ।" + +msgid "Enter a valid JSON." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(लुकेका %(name)s) %(error)s" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "म्यानेजमेन्ट फारम डाटा चलाइएको वा नभरेको पाइयो ।" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "कृपया %d अथवा सो भन्दा थोरै फारम बुझाउनु होस ।" +msgstr[1] "कृपया %d अथवा सो भन्दा थोरै फारमहरु बुझाउनु होस ।" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "कृपया %d अथवा सो भन्दा धेरै फारम बुझाउनु होस ।" +msgstr[1] "कृपया %d अथवा सो भन्दा धेरै फारमहरु बुझाउनु होस ।" + +msgid "Order" +msgstr "क्रम" + +msgid "Delete" +msgstr "मेट्नुहोस" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "कृपया %(field)s का लागि दोहोरिइका तथ्याङ्कहरु सच्याउनुहोस ।" + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "कृपया %(field)s का लागि दोहोरिइका तथ्याङ्कहरु नौलो तथ्याङ्क सहित सच्याउनुहोस ।" + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"कृपया %(field_name)s का लागि दोहोरिइका तथ्याङ्कहरु सच्याउनुहोस जसमा " +"%(date_field)sको %(lookup)s नौलो हुनुपर्दछ ।" + +msgid "Please correct the duplicate values below." +msgstr "कृपया तलका दोहोरिइका मानहरु सच्याउनुहोस ।" + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "उपयुक्त विकल्प छान्नुहोस । छानिएको विकल्प प्रस्तावित विकल्प होइन ।" + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "सबै खाली गर्नु होस ।" + +msgid "Currently" +msgstr "अहिले" + +msgid "Change" +msgstr "फेर्नुहोस" + +msgid "Unknown" +msgstr "अज्ञात" + +msgid "Yes" +msgstr "हुन्छ" + +msgid "No" +msgstr "होइन" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "हो,होइन,सायद" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d बाइट" +msgstr[1] "%(size)d बाइटहरु" + +#, python-format +msgid "%s KB" +msgstr "%s किलोबाइट" + +#, python-format +msgid "%s MB" +msgstr "%s मेगाबाइट" + +#, python-format +msgid "%s GB" +msgstr "%s गिगाबाइट" + +#, python-format +msgid "%s TB" +msgstr "%s टेराबाइट" + +#, python-format +msgid "%s PB" +msgstr "%s पिटाबाइट" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "मध्यरात" + +msgid "noon" +msgstr "मध्यान्ह" + +msgid "Monday" +msgstr "सोमवार" + +msgid "Tuesday" +msgstr "मंगलवार" + +msgid "Wednesday" +msgstr "बुधवार" + +msgid "Thursday" +msgstr "बिहीवार" + +msgid "Friday" +msgstr "शुक्रवार" + +msgid "Saturday" +msgstr "शनिवार" + +msgid "Sunday" +msgstr "आइतवार" + +msgid "Mon" +msgstr "सोम" + +msgid "Tue" +msgstr "मंगल" + +msgid "Wed" +msgstr "बुध" + +msgid "Thu" +msgstr "बिहि" + +msgid "Fri" +msgstr "शुक्र" + +msgid "Sat" +msgstr "शनि" + +msgid "Sun" +msgstr "आइत" + +msgid "January" +msgstr "जनवरी" + +msgid "February" +msgstr "फेब्रुअरी" + +msgid "March" +msgstr "मार्च" + +msgid "April" +msgstr "अप्रिल" + +msgid "May" +msgstr "मई" + +msgid "June" +msgstr "जुन" + +msgid "July" +msgstr "जुलै" + +msgid "August" +msgstr "अगस्त" + +msgid "September" +msgstr "सेप्टेम्बर" + +msgid "October" +msgstr "अक्टुवर" + +msgid "November" +msgstr "नभम्वर" + +msgid "December" +msgstr "डिसम्वर" + +msgid "jan" +msgstr "जनवरी" + +msgid "feb" +msgstr "फेब्रुअरी" + +msgid "mar" +msgstr "मार्च" + +msgid "apr" +msgstr "अप्रिल" + +msgid "may" +msgstr "मई" + +msgid "jun" +msgstr "जुन" + +msgid "jul" +msgstr "जुलै" + +msgid "aug" +msgstr "अग्सत" + +msgid "sep" +msgstr "सेप्तेम्बर" + +msgid "oct" +msgstr "अक्टुवर" + +msgid "nov" +msgstr "नभम्वर" + +msgid "dec" +msgstr "डिसम्वर" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "जनवरी" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "फेब्रुअरी" + +msgctxt "abbrev. month" +msgid "March" +msgstr "मार्च" + +msgctxt "abbrev. month" +msgid "April" +msgstr "अप्रिल" + +msgctxt "abbrev. month" +msgid "May" +msgstr "मई" + +msgctxt "abbrev. month" +msgid "June" +msgstr "जुन" + +msgctxt "abbrev. month" +msgid "July" +msgstr "जुलै" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "अगस्त" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "सेप्तेम्बर" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "अक्टुवर" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "नभम्वर" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "डिसम्वर" + +msgctxt "alt. month" +msgid "January" +msgstr "जनवरी" + +msgctxt "alt. month" +msgid "February" +msgstr "फेब्रुअरी" + +msgctxt "alt. month" +msgid "March" +msgstr "मार्च" + +msgctxt "alt. month" +msgid "April" +msgstr "अप्रिल" + +msgctxt "alt. month" +msgid "May" +msgstr "मई" + +msgctxt "alt. month" +msgid "June" +msgstr "जुन" + +msgctxt "alt. month" +msgid "July" +msgstr "जुलै" + +msgctxt "alt. month" +msgid "August" +msgstr "अगस्त" + +msgctxt "alt. month" +msgid "September" +msgstr "सेप्टेम्बर" + +msgctxt "alt. month" +msgid "October" +msgstr "अक्टुवर" + +msgctxt "alt. month" +msgid "November" +msgstr "नभम्वर" + +msgctxt "alt. month" +msgid "December" +msgstr "डिसम्वर" + +msgid "This is not a valid IPv6 address." +msgstr "यो उपयुक्त IPv6 ठेगाना होइन ।" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "अथवा" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "," + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d वर्ष" +msgstr[1] "%d वर्षहरु" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d महिना" +msgstr[1] "%d महिनाहरु" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d सप्ताह" +msgstr[1] "%d सप्ताहहरु" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d दिन" +msgstr[1] "%d दिनहरु" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d घण्टा" +msgstr[1] "%d घण्टाहरु" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d मिनट" +msgstr[1] "%d मिनटहरु" + +msgid "Forbidden" +msgstr "निषेधित" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF प्रमाणीकरण भएन । अनुरोध विफल ।" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "DEBUG=True ले ज्यादा सुचना प्रदान गर्दछ ।" + +msgid "No year specified" +msgstr "साल तोकिएको छैन ।" + +msgid "Date out of range" +msgstr "मिति मिलेन ।" + +msgid "No month specified" +msgstr "महिना तोकिएको छैन ।" + +msgid "No day specified" +msgstr "दिन तोकिएको छैन ।" + +msgid "No week specified" +msgstr "साता तोकिएको छैन ।" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "%(verbose_name_plural)s उपलब्ध छैन ।" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"%(class_name)s.allow_future 'False' हुनाले आगामी %(verbose_name_plural)s उपलब्ध " +"छैन ।" + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "%(verbose_name)s भेटिएन ।" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "रद्द पृष्ठ (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "डाइरेक्टरी इन्डेक्सहरु यहाँ अनुमति छैन ।" + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "%(directory)s को सूची" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "ज्याङ्गो : वेब साइट र एप्लिकेसन बनाउन सहयोगी औजार " + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"ज्याङ्गो %(version)s को परिवर्तन तथा विशेषता यहाँ हेर्नु होस" + +msgid "The install worked successfully! Congratulations!" +msgstr "बधाई छ । स्थापना भएको छ ।" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "ज्याङ्गो दस्तावेज ।" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "मतदान एप उदाहरण " + +msgid "Get started with Django" +msgstr "ज्याङ्गो सुरु गर्नु होस ।" + +msgid "Django Community" +msgstr "ज्याङ्गो समुदाय" + +msgid "Connect, get help, or contribute" +msgstr "सहयोग अथवा योगदान गरी जोडिनु होस" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..bd0c736 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nl/LC_MESSAGES/django.po new file mode 100644 index 0000000..9db19ac --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nl/LC_MESSAGES/django.po @@ -0,0 +1,1349 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bas Peschier , 2011,2013 +# Blue , 2011-2012 +# Bouke Haarsma , 2013 +# Claude Paroz , 2014 +# Erik Romijn , 2013 +# Evelijn Saaltink , 2016 +# Harro van der Klauw , 2011-2012 +# Ilja Maas , 2015 +# Jannis Leidel , 2011 +# 6a27f10aef159701c7a5ff07f0fb0a78_05545ed , 2011-2012,2014 +# Michiel Overtoom , 2014 +# Meteor0id, 2019-2020 +# 8de006b1b0894aab6aef71979dcd8bd6_5c6b207 , 2014-2015 +# Tino de Bruijn , 2013 +# Tonnes , 2017,2019-2020,2022-2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Tonnes , 2017,2019-2020,2022-2023\n" +"Language-Team: Dutch (http://app.transifex.com/django/django/language/nl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Afrikaans" + +msgid "Arabic" +msgstr "Arabisch" + +msgid "Algerian Arabic" +msgstr "Algerijns Arabisch" + +msgid "Asturian" +msgstr "Asturisch" + +msgid "Azerbaijani" +msgstr "Azerbeidzjaans" + +msgid "Bulgarian" +msgstr "Bulgaars" + +msgid "Belarusian" +msgstr "Wit-Russisch" + +msgid "Bengali" +msgstr "Bengaals" + +msgid "Breton" +msgstr "Bretons" + +msgid "Bosnian" +msgstr "Bosnisch" + +msgid "Catalan" +msgstr "Catalaans" + +msgid "Central Kurdish (Sorani)" +msgstr "Centraal-Koerdisch (Sorani)" + +msgid "Czech" +msgstr "Tsjechisch" + +msgid "Welsh" +msgstr "Welsh" + +msgid "Danish" +msgstr "Deens" + +msgid "German" +msgstr "Duits" + +msgid "Lower Sorbian" +msgstr "Nedersorbisch" + +msgid "Greek" +msgstr "Grieks" + +msgid "English" +msgstr "Engels" + +msgid "Australian English" +msgstr "Australisch-Engels" + +msgid "British English" +msgstr "Brits-Engels" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Spaans" + +msgid "Argentinian Spanish" +msgstr "Argentijns Spaans" + +msgid "Colombian Spanish" +msgstr "Colombiaans Spaans" + +msgid "Mexican Spanish" +msgstr "Mexicaans Spaans" + +msgid "Nicaraguan Spanish" +msgstr "Nicaraguaans Spaans" + +msgid "Venezuelan Spanish" +msgstr "Venezolaans Spaans" + +msgid "Estonian" +msgstr "Ests" + +msgid "Basque" +msgstr "Baskisch" + +msgid "Persian" +msgstr "Perzisch" + +msgid "Finnish" +msgstr "Fins" + +msgid "French" +msgstr "Frans" + +msgid "Frisian" +msgstr "Fries" + +msgid "Irish" +msgstr "Iers" + +msgid "Scottish Gaelic" +msgstr "Schots-Gaelisch" + +msgid "Galician" +msgstr "Galicisch" + +msgid "Hebrew" +msgstr "Hebreeuws" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Kroatisch" + +msgid "Upper Sorbian" +msgstr "Oppersorbisch" + +msgid "Hungarian" +msgstr "Hongaars" + +msgid "Armenian" +msgstr "Armeens" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonesisch" + +msgid "Igbo" +msgstr "Igbo" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "IJslands" + +msgid "Italian" +msgstr "Italiaans" + +msgid "Japanese" +msgstr "Japans" + +msgid "Georgian" +msgstr "Georgisch" + +msgid "Kabyle" +msgstr "Kabylisch" + +msgid "Kazakh" +msgstr "Kazachs" + +msgid "Khmer" +msgstr "Khmer" + +msgid "Kannada" +msgstr "Kannada" + +msgid "Korean" +msgstr "Koreaans" + +msgid "Kyrgyz" +msgstr "Kirgizisch" + +msgid "Luxembourgish" +msgstr "Luxemburgs" + +msgid "Lithuanian" +msgstr "Litouws" + +msgid "Latvian" +msgstr "Lets" + +msgid "Macedonian" +msgstr "Macedonisch" + +msgid "Malayalam" +msgstr "Malayalam" + +msgid "Mongolian" +msgstr "Mongools" + +msgid "Marathi" +msgstr "Marathi" + +msgid "Malay" +msgstr "Maleis" + +msgid "Burmese" +msgstr "Birmaans" + +msgid "Norwegian Bokmål" +msgstr "Noors Bokmål" + +msgid "Nepali" +msgstr "Nepalees" + +msgid "Dutch" +msgstr "Nederlands" + +msgid "Norwegian Nynorsk" +msgstr "Noors Nynorsk" + +msgid "Ossetic" +msgstr "Ossetisch" + +msgid "Punjabi" +msgstr "Punjabi" + +msgid "Polish" +msgstr "Pools" + +msgid "Portuguese" +msgstr "Portugees" + +msgid "Brazilian Portuguese" +msgstr "Braziliaans Portugees" + +msgid "Romanian" +msgstr "Roemeens" + +msgid "Russian" +msgstr "Russisch" + +msgid "Slovak" +msgstr "Slovaaks" + +msgid "Slovenian" +msgstr "Sloveens" + +msgid "Albanian" +msgstr "Albanisch" + +msgid "Serbian" +msgstr "Servisch" + +msgid "Serbian Latin" +msgstr "Servisch Latijn" + +msgid "Swedish" +msgstr "Zweeds" + +msgid "Swahili" +msgstr "Swahili" + +msgid "Tamil" +msgstr "Tamil" + +msgid "Telugu" +msgstr "Telegu" + +msgid "Tajik" +msgstr "Tadzjieks" + +msgid "Thai" +msgstr "Thai" + +msgid "Turkmen" +msgstr "Turkmeens" + +msgid "Turkish" +msgstr "Turks" + +msgid "Tatar" +msgstr "Tataars" + +msgid "Udmurt" +msgstr "Oedmoerts" + +msgid "Uyghur" +msgstr "Oeigoers" + +msgid "Ukrainian" +msgstr "Oekraïens" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "Oezbeeks" + +msgid "Vietnamese" +msgstr "Vietnamees" + +msgid "Simplified Chinese" +msgstr "Vereenvoudigd Chinees" + +msgid "Traditional Chinese" +msgstr "Traditioneel Chinees" + +msgid "Messages" +msgstr "Berichten" + +msgid "Site Maps" +msgstr "Sitemaps" + +msgid "Static Files" +msgstr "Statische bestanden" + +msgid "Syndication" +msgstr "Syndicatie" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Dat paginanummer is geen geheel getal" + +msgid "That page number is less than 1" +msgstr "Dat paginanummer is kleiner dan 1" + +msgid "That page contains no results" +msgstr "Die pagina bevat geen resultaten" + +msgid "Enter a valid value." +msgstr "Voer een geldige waarde in." + +msgid "Enter a valid URL." +msgstr "Voer een geldige URL in." + +msgid "Enter a valid integer." +msgstr "Voer een geldig geheel getal in." + +msgid "Enter a valid email address." +msgstr "Voer een geldig e-mailadres in." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Voer een geldige ‘slug’ in, bestaande uit letters, cijfers, liggende " +"streepjes en verbindingsstreepjes." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Voer een geldige ‘slug’ in, bestaande uit Unicode-letters, cijfers, liggende " +"streepjes en verbindingsstreepjes." + +msgid "Enter a valid IPv4 address." +msgstr "Voer een geldig IPv4-adres in." + +msgid "Enter a valid IPv6 address." +msgstr "Voer een geldig IPv6-adres in." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Voer een geldig IPv4- of IPv6-adres in." + +msgid "Enter only digits separated by commas." +msgstr "Voer alleen cijfers in, gescheiden door komma's." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Zorg ervoor dat deze waarde gelijk is aan %(limit_value)s (het is nu " +"%(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Zorg ervoor dat deze waarde hoogstens %(limit_value)s is." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Zorg ervoor dat deze waarde minstens %(limit_value)s is." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" +"Zorg ervoor dat deze waarde een veelvoud is van stapgrootte %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"Zorg dat deze waarde een veelvoud is van stapgrootte %(limit_value)s, " +"beginnend bij %(offset)s, bv. %(offset)s, %(valid_value1)s, " +"%(valid_value2)s, enzovoort." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Zorg dat deze waarde ten minste %(limit_value)d teken bevat (het zijn er nu " +"%(show_value)d)." +msgstr[1] "" +"Zorg dat deze waarde ten minste %(limit_value)d tekens bevat (het zijn er nu " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Zorg dat deze waarde niet meer dan %(limit_value)d teken bevat (het zijn er " +"nu %(show_value)d)." +msgstr[1] "" +"Zorg dat deze waarde niet meer dan %(limit_value)d tekens bevat (het zijn er " +"nu %(show_value)d)." + +msgid "Enter a number." +msgstr "Voer een getal in." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Zorg dat er niet meer dan %(max)s cijfer is." +msgstr[1] "Zorg dat er niet meer dan %(max)s cijfers zijn." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Zorg dat er niet meer dan %(max)s cijfer achter de komma staat." +msgstr[1] "Zorg dat er niet meer dan %(max)s cijfers achter de komma staan." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "Zorg dat er niet meer dan %(max)s cijfer voor de komma staat." +msgstr[1] "Zorg dat er niet meer dan %(max)s cijfers voor de komma staan." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Bestandsextensie ‘%(extension)s’ is niet toegestaan. Toegestane extensies " +"zijn: ‘%(allowed_extensions)s’." + +msgid "Null characters are not allowed." +msgstr "Null-tekens zijn niet toegestaan." + +msgid "and" +msgstr "en" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s met deze %(field_labels)s bestaat al." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Beperking ‘%(name)s’ is geschonden." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Waarde %(value)r is geen geldige keuze." + +msgid "This field cannot be null." +msgstr "Dit veld mag niet leeg zijn." + +msgid "This field cannot be blank." +msgstr "Dit veld kan niet leeg zijn" + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "Er bestaat al een %(model_name)s met eenzelfde %(field_label)s." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s moet uniek zijn voor %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Veld van type: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "Waarde van ‘%(value)s’ moet True of False zijn." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "Waarde van ‘%(value)s’ moet True, False of None zijn." + +msgid "Boolean (Either True or False)" +msgstr "Boolean (True of False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Tekenreeks (hooguit %(max_length)s)" + +msgid "String (unlimited)" +msgstr "Tekenreeks (onbeperkt)" + +msgid "Comma-separated integers" +msgstr "Komma-gescheiden gehele getallen" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"Waarde van ‘%(value)s’ heeft een ongeldige datumnotatie. De juiste notatie " +"is YYYY-MM-DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"Waarde van ‘%(value)s’ heeft de juiste notatie (YYYY-MM-DD), maar het is een " +"ongeldige datum." + +msgid "Date (without time)" +msgstr "Datum (zonder tijd)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"Waarde van ‘%(value)s’ heeft een ongeldige notatie. De juiste notatie is " +"YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"Waarde van ‘%(value)s’ heeft de juiste notatie (YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ]), maar het is een ongeldige datum/tijd." + +msgid "Date (with time)" +msgstr "Datum (met tijd)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "Waarde van ‘%(value)s’ moet een decimaal getal zijn." + +msgid "Decimal number" +msgstr "Decimaal getal" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"Waarde van ‘%(value)s’ heeft een ongeldige notatie. De juiste notatie is " +"[DD] [[HH:]MM:]ss[.uuuuuu]." + +msgid "Duration" +msgstr "Tijdsduur" + +msgid "Email address" +msgstr "E-mailadres" + +msgid "File path" +msgstr "Bestandspad" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "Waarde van ‘%(value)s’ moet een drijvende-kommagetal zijn." + +msgid "Floating point number" +msgstr "Drijvende-kommagetal" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "Waarde van ‘%(value)s’ moet een geheel getal zijn." + +msgid "Integer" +msgstr "Geheel getal" + +msgid "Big (8 byte) integer" +msgstr "Groot (8 byte) geheel getal" + +msgid "Small integer" +msgstr "Klein geheel getal" + +msgid "IPv4 address" +msgstr "IPv4-adres" + +msgid "IP address" +msgstr "IP-adres" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "Waarde van ‘%(value)s’ moet None, True of False zijn." + +msgid "Boolean (Either True, False or None)" +msgstr "Boolean (True, False of None)" + +msgid "Positive big integer" +msgstr "Positief groot geheel getal" + +msgid "Positive integer" +msgstr "Positief geheel getal" + +msgid "Positive small integer" +msgstr "Postitief klein geheel getal" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (max. lengte %(max_length)s)" + +msgid "Text" +msgstr "Tekst" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"Waarde van ‘%(value)s’ heeft een ongeldige notatie. De juiste notatie is HH:" +"MM[:ss[.uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"Waarde van ‘%(value)s’ heeft de juiste notatie (HH:MM[:ss[.uuuuuu]]), maar " +"het is een ongeldige tijd." + +msgid "Time" +msgstr "Tijd" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Onbewerkte binaire gegevens" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "‘%(value)s’ is geen geldige UUID." + +msgid "Universally unique identifier" +msgstr "Universally unique identifier" + +msgid "File" +msgstr "Bestand" + +msgid "Image" +msgstr "Afbeelding" + +msgid "A JSON object" +msgstr "Een JSON-object" + +msgid "Value must be valid JSON." +msgstr "Waarde moet geldige JSON zijn." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(model)s-instantie met %(field)s %(value)r bestaat niet." + +msgid "Foreign Key (type determined by related field)" +msgstr "Refererende sleutel (type wordt bepaald door gerelateerde veld)" + +msgid "One-to-one relationship" +msgstr "Een-op-een-relatie" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s-relatie" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s-relaties" + +msgid "Many-to-many relationship" +msgstr "Veel-op-veel-relatie" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Dit veld is verplicht." + +msgid "Enter a whole number." +msgstr "Voer een geheel getal in." + +msgid "Enter a valid date." +msgstr "Voer een geldige datum in." + +msgid "Enter a valid time." +msgstr "Voer een geldige tijd in." + +msgid "Enter a valid date/time." +msgstr "Voer een geldige datum/tijd in." + +msgid "Enter a valid duration." +msgstr "Voer een geldige tijdsduur in." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Het aantal dagen moet tussen {min_days} en {max_days} liggen." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" +"Er is geen bestand verstuurd. Controleer het coderingstype op het formulier." + +msgid "No file was submitted." +msgstr "Er is geen bestand verstuurd." + +msgid "The submitted file is empty." +msgstr "Het verstuurde bestand is leeg." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Zorg dat deze bestandsnaam niet meer dan %(max)d teken bevat (het zijn er nu " +"%(length)d)." +msgstr[1] "" +"Zorg dat deze bestandsnaam niet meer dan %(max)d tekens bevat (het zijn er " +"nu %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Upload een bestand of vink het vakje Wissen aan, niet allebei." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Upload een geldige afbeelding. Het geüploade bestand is geen of een " +"beschadigde afbeelding." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Selecteer een geldige keuze. %(value)s is geen beschikbare keuze." + +msgid "Enter a list of values." +msgstr "Voer een lijst met waarden in." + +msgid "Enter a complete value." +msgstr "Voer een volledige waarde in." + +msgid "Enter a valid UUID." +msgstr "Voer een geldige UUID in." + +msgid "Enter a valid JSON." +msgstr "Voer een geldige JSON in." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Verborgen veld %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"ManagementForm-gegevens ontbreken of er is mee geknoeid. Ontbrekende velden: " +"%(field_names)s. Mogelijk dient u een bug te melden als het probleem " +"aanhoudt." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Verstuur maximaal %(num)d formulier." +msgstr[1] "Verstuur maximaal %(num)d formulieren." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Verstuur minimaal %(num)d formulier." +msgstr[1] "Verstuur minimaal %(num)d formulieren." + +msgid "Order" +msgstr "Volgorde" + +msgid "Delete" +msgstr "Verwijderen" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Corrigeer de dubbele gegevens voor %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Corrigeer de dubbele gegevens voor %(field)s, dat uniek moet zijn." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Corrigeer de dubbele gegevens voor %(field_name)s, dat uniek moet zijn voor " +"de %(lookup)s in %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Corrigeer de dubbele waarden hieronder." + +msgid "The inline value did not match the parent instance." +msgstr "De inline waarde komt niet overeen met de bovenliggende instantie." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Selecteer een geldige keuze. Deze keuze is niet beschikbaar." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "‘%(pk)s’ is geen geldige waarde." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s kon niet worden geïnterpreteerd in tijdzone " +"%(current_timezone)s; mogelijk is deze dubbelzinnig of bestaat deze niet." + +msgid "Clear" +msgstr "Wissen" + +msgid "Currently" +msgstr "Huidige" + +msgid "Change" +msgstr "Wijzigen" + +msgid "Unknown" +msgstr "Onbekend" + +msgid "Yes" +msgstr "Ja" + +msgid "No" +msgstr "Nee" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "ja,nee,misschien" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d byte" +msgstr[1] "%(size)d bytes" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "middernacht" + +msgid "noon" +msgstr "middag" + +msgid "Monday" +msgstr "maandag" + +msgid "Tuesday" +msgstr "dinsdag" + +msgid "Wednesday" +msgstr "woensdag" + +msgid "Thursday" +msgstr "donderdag" + +msgid "Friday" +msgstr "vrijdag" + +msgid "Saturday" +msgstr "zaterdag" + +msgid "Sunday" +msgstr "zondag" + +msgid "Mon" +msgstr "ma" + +msgid "Tue" +msgstr "di" + +msgid "Wed" +msgstr "wo" + +msgid "Thu" +msgstr "do" + +msgid "Fri" +msgstr "vr" + +msgid "Sat" +msgstr "za" + +msgid "Sun" +msgstr "zo" + +msgid "January" +msgstr "januari" + +msgid "February" +msgstr "februari" + +msgid "March" +msgstr "maart" + +msgid "April" +msgstr "april" + +msgid "May" +msgstr "mei" + +msgid "June" +msgstr "juni" + +msgid "July" +msgstr "juli" + +msgid "August" +msgstr "augustus" + +msgid "September" +msgstr "september" + +msgid "October" +msgstr "oktober" + +msgid "November" +msgstr "november" + +msgid "December" +msgstr "december" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mrt" + +msgid "apr" +msgstr "apr" + +msgid "may" +msgstr "mei" + +msgid "jun" +msgstr "jun" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "aug" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "okt" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dec" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "jan" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "feb" + +msgctxt "abbrev. month" +msgid "March" +msgstr "mrt" + +msgctxt "abbrev. month" +msgid "April" +msgstr "apr" + +msgctxt "abbrev. month" +msgid "May" +msgstr "mei" + +msgctxt "abbrev. month" +msgid "June" +msgstr "jun" + +msgctxt "abbrev. month" +msgid "July" +msgstr "jul" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "aug" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "sep" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "okt" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "nov" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "dec" + +msgctxt "alt. month" +msgid "January" +msgstr "januari" + +msgctxt "alt. month" +msgid "February" +msgstr "februari" + +msgctxt "alt. month" +msgid "March" +msgstr "maart" + +msgctxt "alt. month" +msgid "April" +msgstr "april" + +msgctxt "alt. month" +msgid "May" +msgstr "mei" + +msgctxt "alt. month" +msgid "June" +msgstr "juni" + +msgctxt "alt. month" +msgid "July" +msgstr "juli" + +msgctxt "alt. month" +msgid "August" +msgstr "augustus" + +msgctxt "alt. month" +msgid "September" +msgstr "september" + +msgctxt "alt. month" +msgid "October" +msgstr "oktober" + +msgctxt "alt. month" +msgid "November" +msgstr "november" + +msgctxt "alt. month" +msgid "December" +msgstr "december" + +msgid "This is not a valid IPv6 address." +msgstr "Dit is geen geldig IPv6-adres." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "of" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d jaar" +msgstr[1] "%(num)d jaar" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d maand" +msgstr[1] "%(num)d maanden" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d week" +msgstr[1] "%(num)d weken" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dag" +msgstr[1] "%(num)d dagen" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d uur" +msgstr[1] "%(num)d uur" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuut" +msgstr[1] "%(num)d minuten" + +msgid "Forbidden" +msgstr "Verboden" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF-verificatie mislukt. Aanvraag afgebroken." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"U ziet deze melding, omdat deze HTTPS-website vereist dat uw webbrowser een " +"‘Referer header’ meestuurt, maar deze ontbreekt. Deze header is om " +"veiligheidsredenen vereist om er zeker van te zijn dat uw browser niet door " +"derden wordt gekaapt." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Als u ‘Referer’-headers in uw browser hebt uitgeschakeld, schakel deze dan " +"weer in, op zijn minst voor deze website, of voor HTTPS-verbindingen, of " +"voor ‘same-origin’-aanvragen." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Als u de tag gebruikt of de " +"header ‘Referrer-Policy: no-referrer’ opneemt, verwijder deze dan. De CSRF-" +"bescherming vereist de ‘Referer’-header voor strenge referer-controle. Als u " +"bezorgd bent om privacy, gebruik dan alternatieven zoals voor koppelingen naar websites van derden." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"U ziet deze melding, omdat deze website vereist dat een CSRF-cookie wordt " +"meegestuurd bij het verzenden van formulieren. Dit cookie is om " +"veiligheidsredenen vereist om er zeker van te zijn dat uw browser niet door " +"derden wordt gekaapt." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Als u cookies in uw webbrowser hebt uitgeschakeld, schakel deze dan weer in, " +"op zijn minst voor deze website, of voor ‘same-origin’-aanvragen." + +msgid "More information is available with DEBUG=True." +msgstr "Meer informatie is beschikbaar met DEBUG=True." + +msgid "No year specified" +msgstr "Geen jaar opgegeven" + +msgid "Date out of range" +msgstr "Datum buiten bereik" + +msgid "No month specified" +msgstr "Geen maand opgegeven" + +msgid "No day specified" +msgstr "Geen dag opgegeven" + +msgid "No week specified" +msgstr "Geen week opgegeven" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Geen %(verbose_name_plural)s beschikbaar" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Geen toekomstige %(verbose_name_plural)s beschikbaar, omdat %(class_name)s." +"allow_future de waarde False (Onwaar) heeft." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Ongeldige datumtekst ‘%(datestr)s’ op basis van notatie ‘%(format)s’" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Geen %(verbose_name)s gevonden die voldoet aan de query" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" +"Pagina is niet ‘last’ en kan ook niet naar een geheel getal worden " +"geconverteerd." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Ongeldige pagina (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Lege lijst en ‘%(class_name)s.allow_empty’ is False." + +msgid "Directory indexes are not allowed here." +msgstr "Directoryindexen zijn hier niet toegestaan." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "‘%(path)s’ bestaat niet" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Index van %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "De installatie is gelukt! Gefeliciteerd!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Uitgaveopmerkingen voor Django " +"%(version)s weergeven" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"U ziet deze pagina, omdat uw instellingenbestand DEBUG=True bevat en u geen URL's hebt geconfigureerd." + +msgid "Django Documentation" +msgstr "Django-documentatie" + +msgid "Topics, references, & how-to’s" +msgstr "Onderwerpen, referenties en instructies" + +msgid "Tutorial: A Polling App" +msgstr "Handleiding: een app voor peilingen" + +msgid "Get started with Django" +msgstr "Beginnen met Django" + +msgid "Django Community" +msgstr "Django-gemeenschap" + +msgid "Connect, get help, or contribute" +msgstr "Contact met anderen, hulp verkrijgen of bijdragen" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nl/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nl/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nl/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nl/formats.py new file mode 100644 index 0000000..e9f52b9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nl/formats.py @@ -0,0 +1,92 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j F Y" # '20 januari 2009' +TIME_FORMAT = "H:i" # '15:23' +DATETIME_FORMAT = "j F Y H:i" # '20 januari 2009 15:23' +YEAR_MONTH_FORMAT = "F Y" # 'januari 2009' +MONTH_DAY_FORMAT = "j F" # '20 januari' +SHORT_DATE_FORMAT = "j-n-Y" # '20-1-2009' +SHORT_DATETIME_FORMAT = "j-n-Y H:i" # '20-1-2009 15:23' +FIRST_DAY_OF_WEEK = 1 # Monday (in Dutch 'maandag') + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d-%m-%Y", # '20-01-2009' + "%d-%m-%y", # '20-01-09' + "%d/%m/%Y", # '20/01/2009' + "%d/%m/%y", # '20/01/09' + "%Y/%m/%d", # '2009/01/20' + # "%d %b %Y", # '20 jan 2009' + # "%d %b %y", # '20 jan 09' + # "%d %B %Y", # '20 januari 2009' + # "%d %B %y", # '20 januari 09' +] +# Kept ISO formats as one is in first position +TIME_INPUT_FORMATS = [ + "%H:%M:%S", # '15:23:35' + "%H:%M:%S.%f", # '15:23:35.000200' + "%H.%M:%S", # '15.23:35' + "%H.%M:%S.%f", # '15.23:35.000200' + "%H.%M", # '15.23' + "%H:%M", # '15:23' +] +DATETIME_INPUT_FORMATS = [ + # With time in %H:%M:%S : + "%d-%m-%Y %H:%M:%S", # '20-01-2009 15:23:35' + "%d-%m-%y %H:%M:%S", # '20-01-09 15:23:35' + "%Y-%m-%d %H:%M:%S", # '2009-01-20 15:23:35' + "%d/%m/%Y %H:%M:%S", # '20/01/2009 15:23:35' + "%d/%m/%y %H:%M:%S", # '20/01/09 15:23:35' + "%Y/%m/%d %H:%M:%S", # '2009/01/20 15:23:35' + # "%d %b %Y %H:%M:%S", # '20 jan 2009 15:23:35' + # "%d %b %y %H:%M:%S", # '20 jan 09 15:23:35' + # "%d %B %Y %H:%M:%S", # '20 januari 2009 15:23:35' + # "%d %B %y %H:%M:%S", # '20 januari 2009 15:23:35' + # With time in %H:%M:%S.%f : + "%d-%m-%Y %H:%M:%S.%f", # '20-01-2009 15:23:35.000200' + "%d-%m-%y %H:%M:%S.%f", # '20-01-09 15:23:35.000200' + "%Y-%m-%d %H:%M:%S.%f", # '2009-01-20 15:23:35.000200' + "%d/%m/%Y %H:%M:%S.%f", # '20/01/2009 15:23:35.000200' + "%d/%m/%y %H:%M:%S.%f", # '20/01/09 15:23:35.000200' + "%Y/%m/%d %H:%M:%S.%f", # '2009/01/20 15:23:35.000200' + # With time in %H.%M:%S : + "%d-%m-%Y %H.%M:%S", # '20-01-2009 15.23:35' + "%d-%m-%y %H.%M:%S", # '20-01-09 15.23:35' + "%d/%m/%Y %H.%M:%S", # '20/01/2009 15.23:35' + "%d/%m/%y %H.%M:%S", # '20/01/09 15.23:35' + # "%d %b %Y %H.%M:%S", # '20 jan 2009 15.23:35' + # "%d %b %y %H.%M:%S", # '20 jan 09 15.23:35' + # "%d %B %Y %H.%M:%S", # '20 januari 2009 15.23:35' + # "%d %B %y %H.%M:%S", # '20 januari 2009 15.23:35' + # With time in %H.%M:%S.%f : + "%d-%m-%Y %H.%M:%S.%f", # '20-01-2009 15.23:35.000200' + "%d-%m-%y %H.%M:%S.%f", # '20-01-09 15.23:35.000200' + "%d/%m/%Y %H.%M:%S.%f", # '20/01/2009 15.23:35.000200' + "%d/%m/%y %H.%M:%S.%f", # '20/01/09 15.23:35.000200' + # With time in %H:%M : + "%d-%m-%Y %H:%M", # '20-01-2009 15:23' + "%d-%m-%y %H:%M", # '20-01-09 15:23' + "%Y-%m-%d %H:%M", # '2009-01-20 15:23' + "%d/%m/%Y %H:%M", # '20/01/2009 15:23' + "%d/%m/%y %H:%M", # '20/01/09 15:23' + "%Y/%m/%d %H:%M", # '2009/01/20 15:23' + # "%d %b %Y %H:%M", # '20 jan 2009 15:23' + # "%d %b %y %H:%M", # '20 jan 09 15:23' + # "%d %B %Y %H:%M", # '20 januari 2009 15:23' + # "%d %B %y %H:%M", # '20 januari 2009 15:23' + # With time in %H.%M : + "%d-%m-%Y %H.%M", # '20-01-2009 15.23' + "%d-%m-%y %H.%M", # '20-01-09 15.23' + "%d/%m/%Y %H.%M", # '20/01/2009 15.23' + "%d/%m/%y %H.%M", # '20/01/09 15.23' + # "%d %b %Y %H.%M", # '20 jan 2009 15.23' + # "%d %b %y %H.%M", # '20 jan 09 15.23' + # "%d %B %Y %H.%M", # '20 januari 2009 15.23' + # "%d %B %y %H.%M", # '20 januari 2009 15.23' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7698eda Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nn/LC_MESSAGES/django.po new file mode 100644 index 0000000..04b872e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nn/LC_MESSAGES/django.po @@ -0,0 +1,1305 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# hgrimelid , 2011 +# Jannis Leidel , 2011 +# jensadne , 2013 +# Sigurd Gartmann , 2012 +# Sivert Olstad, 2021 +# velmont , 2012 +# Vibeke Uthaug, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2021-11-25 14:49+0000\n" +"Last-Translator: Sivert Olstad\n" +"Language-Team: Norwegian Nynorsk (http://www.transifex.com/django/django/" +"language/nn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Afrikaans" + +msgid "Arabic" +msgstr "Arabisk" + +msgid "Algerian Arabic" +msgstr "Arabisk (algersk)" + +msgid "Asturian" +msgstr "Asturiansk" + +msgid "Azerbaijani" +msgstr "Aserbajansk" + +msgid "Bulgarian" +msgstr "Bulgarsk" + +msgid "Belarusian" +msgstr "Kviterussisk" + +msgid "Bengali" +msgstr "Bengalsk" + +msgid "Breton" +msgstr "Bretonsk" + +msgid "Bosnian" +msgstr "Bosnisk" + +msgid "Catalan" +msgstr "Katalansk" + +msgid "Czech" +msgstr "Tsjekkisk" + +msgid "Welsh" +msgstr "Walisisk" + +msgid "Danish" +msgstr "Dansk" + +msgid "German" +msgstr "Tysk" + +msgid "Lower Sorbian" +msgstr "Lågsorbisk" + +msgid "Greek" +msgstr "Gresk" + +msgid "English" +msgstr "Engelsk" + +msgid "Australian English" +msgstr "Engelsk (australsk)" + +msgid "British English" +msgstr "Engelsk (britisk)" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Spansk" + +msgid "Argentinian Spanish" +msgstr "Spansk (argentinsk)" + +msgid "Colombian Spanish" +msgstr "Spansk (kolombiansk)" + +msgid "Mexican Spanish" +msgstr "Spansk (meksikansk)" + +msgid "Nicaraguan Spanish" +msgstr "Spansk (nicaraguansk)" + +msgid "Venezuelan Spanish" +msgstr "Spansk (venezuelansk)" + +msgid "Estonian" +msgstr "Estisk" + +msgid "Basque" +msgstr "Baskisk" + +msgid "Persian" +msgstr "Persisk" + +msgid "Finnish" +msgstr "Finsk" + +msgid "French" +msgstr "Fransk" + +msgid "Frisian" +msgstr "Frisisk" + +msgid "Irish" +msgstr "Irsk" + +msgid "Scottish Gaelic" +msgstr "Skotsk-gaelisk" + +msgid "Galician" +msgstr "Galisisk" + +msgid "Hebrew" +msgstr "Hebraisk" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Kroatisk" + +msgid "Upper Sorbian" +msgstr "Høgsorbisk" + +msgid "Hungarian" +msgstr "Ungarsk" + +msgid "Armenian" +msgstr "Armensk" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonesisk" + +msgid "Igbo" +msgstr "Igbo" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Islandsk" + +msgid "Italian" +msgstr "Italiensk" + +msgid "Japanese" +msgstr "Japansk" + +msgid "Georgian" +msgstr "Georgisk" + +msgid "Kabyle" +msgstr "Kabylsk" + +msgid "Kazakh" +msgstr "Kasakhisk" + +msgid "Khmer" +msgstr "Khmer" + +msgid "Kannada" +msgstr "Kannada" + +msgid "Korean" +msgstr "Koreansk" + +msgid "Kyrgyz" +msgstr "Kirgisisk" + +msgid "Luxembourgish" +msgstr "Luxembourgsk" + +msgid "Lithuanian" +msgstr "Litauisk" + +msgid "Latvian" +msgstr "Latvisk" + +msgid "Macedonian" +msgstr "Makedonsk" + +msgid "Malayalam" +msgstr "Malayalam" + +msgid "Mongolian" +msgstr "Mongolsk" + +msgid "Marathi" +msgstr "Marathi" + +msgid "Malay" +msgstr "Malayisk" + +msgid "Burmese" +msgstr "Burmesisk" + +msgid "Norwegian Bokmål" +msgstr "Norsk (bokmål)" + +msgid "Nepali" +msgstr "Nepali" + +msgid "Dutch" +msgstr "Nederlandsk" + +msgid "Norwegian Nynorsk" +msgstr "Norsk (nynorsk)" + +msgid "Ossetic" +msgstr "Ossetisk" + +msgid "Punjabi" +msgstr "Punjabi" + +msgid "Polish" +msgstr "Polsk" + +msgid "Portuguese" +msgstr "Portugisisk" + +msgid "Brazilian Portuguese" +msgstr "Brasiliansk portugisisk" + +msgid "Romanian" +msgstr "Rumensk" + +msgid "Russian" +msgstr "Russisk" + +msgid "Slovak" +msgstr "Slovakisk" + +msgid "Slovenian" +msgstr "Slovensk" + +msgid "Albanian" +msgstr "Albansk" + +msgid "Serbian" +msgstr "Serbisk" + +msgid "Serbian Latin" +msgstr "Serbisk latin" + +msgid "Swedish" +msgstr "Svensk" + +msgid "Swahili" +msgstr "Swahili" + +msgid "Tamil" +msgstr "Tamil" + +msgid "Telugu" +msgstr "Telugu" + +msgid "Tajik" +msgstr "Tadsjikisk" + +msgid "Thai" +msgstr "Thai" + +msgid "Turkmen" +msgstr "Turkmensk" + +msgid "Turkish" +msgstr "Tyrkisk" + +msgid "Tatar" +msgstr "Tatarisk" + +msgid "Udmurt" +msgstr "Udmurtisk" + +msgid "Ukrainian" +msgstr "Ukrainsk" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "Usbekisk" + +msgid "Vietnamese" +msgstr "Vietnamesisk" + +msgid "Simplified Chinese" +msgstr "Simplifisert kinesisk" + +msgid "Traditional Chinese" +msgstr "Tradisjonell kinesisk" + +msgid "Messages" +msgstr "Meldingar" + +msgid "Site Maps" +msgstr "Sidekart" + +msgid "Static Files" +msgstr "Statiske Filer" + +msgid "Syndication" +msgstr "Syndikering" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Sidenummeret er ikkje eit heiltal" + +msgid "That page number is less than 1" +msgstr "Sidenummeret er mindre enn 1" + +msgid "That page contains no results" +msgstr "Sida har ingen resultat" + +msgid "Enter a valid value." +msgstr "Oppgje ein gyldig verdi." + +msgid "Enter a valid URL." +msgstr "Oppgje ei gyldig nettadresse." + +msgid "Enter a valid integer." +msgstr "Oppgje eit gyldig heiltal." + +msgid "Enter a valid email address." +msgstr "Oppgje ei gyldig e-postadresse." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Oppgje ein gyldig \"slug\" som består av bokstavar, nummer, understrekar " +"eller bindestrekar." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Oppgje ein gyldig \"slug\" som består av Unicode bokstavar, nummer, " +"understrekar eller bindestrekar." + +msgid "Enter a valid IPv4 address." +msgstr "Oppgje ei gyldig IPv4-adresse." + +msgid "Enter a valid IPv6 address." +msgstr "Skriv inn ei gyldig IPv6-adresse." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Skriv inn ei gyldig IPv4- eller IPv6-adresse." + +msgid "Enter only digits separated by commas." +msgstr "Oppgje berre tall skild med komma." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Verdien må minimum ha %(limit_value)s teikn (den er %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Verdien må vere mindre enn eller lik %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Verdien må vere større enn eller lik %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "Verdien må ha minst %(limit_value)d teikn (den har %(show_value)d)." +msgstr[1] "Verdien må ha minst %(limit_value)d teikn (den har %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Verdien kan ikkje ha fleire enn %(limit_value)d teikn (den har " +"%(show_value)d)." +msgstr[1] "" +"Verdien kan ikkje ha fleire enn %(limit_value)d teikn (den har " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Oppgje eit tal." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Verdien kan ikkje ha meir enn %(max)s siffer totalt." +msgstr[1] "Verdien kan ikkje ha meir enn %(max)s siffer totalt." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Verdien kan ikkie ha meir enn %(max)s desimal." +msgstr[1] "Verdien kan ikkie ha meir enn %(max)s desimalar." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "Verdien kan ikkje ha meir enn %(max)s siffer framanfor komma." +msgstr[1] "Verdien kan ikkje ha meir enn %(max)s siffer framanfor komma." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Filtypen “%(extension)s” er ikkje tillate. Tillate filtypar er: " +"%(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Null-teikn er ikkje tillate." + +msgid "and" +msgstr "og" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s med %(field_labels)s fins allereie." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Verdi %(value)r er eit ugyldig val." + +msgid "This field cannot be null." +msgstr "Feltet kan ikkje vere tomt." + +msgid "This field cannot be blank." +msgstr "Feltet kan ikkje vere tomt." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s med %(field_label)s fins allereie." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "%(field_label)s må vere unik for %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Felt av typen: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "Verdien “%(value)s” må vere anten True eller False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "Verdien “%(value)s” må vere anten True, False, eller None." + +msgid "Boolean (Either True or False)" +msgstr "Boolsk (True eller False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Tekst (opp til %(max_length)s teikn)" + +msgid "Comma-separated integers" +msgstr "Heiltal skild med komma" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"Verdien “%(value)s” har eit ugyldig datoformat. Det må vere på formen YYYY-" +"MM-DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"Verdien “%(value)s” har rett format (YYYY-MM-DD) men er ein ugyldig dato." + +msgid "Date (without time)" +msgstr "Dato (utan tid)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"Verdien “%(value)s” har eit ugyldig format. Det må vere på formen YYYY-MM-DD " +"HH:MM[:ss[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"Verdien “%(value)s” har rett format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) men " +"er ein ugyldig dato eller klokkeslett." + +msgid "Date (with time)" +msgstr "Dato (med tid)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "Verdien “%(value)s” må vere eit desimaltal." + +msgid "Decimal number" +msgstr "Desimaltal" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"Verdien “%(value)s” har eit ugyldig format. Det må vere på formen [DD] " +"[[HH:]MM:]ss[.uuuuuu]." + +msgid "Duration" +msgstr "Varigskap" + +msgid "Email address" +msgstr "E-postadresse" + +msgid "File path" +msgstr "Filsti" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "Verdien “%(value)s” må vere eit flyttal." + +msgid "Floating point number" +msgstr "Flyttal" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "Verdien “%(value)s” må vere eit heiltal." + +msgid "Integer" +msgstr "Heiltal" + +msgid "Big (8 byte) integer" +msgstr "Stort (8 bitar) heiltal" + +msgid "Small integer" +msgstr "Lite heiltal" + +msgid "IPv4 address" +msgstr "IPv4-adresse" + +msgid "IP address" +msgstr "IP-adresse" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "Verdien “%(value)s” må vere anten None, True, eller False." + +msgid "Boolean (Either True, False or None)" +msgstr "Boolsk (True, False eller None)" + +msgid "Positive big integer" +msgstr "Positivt stort heiltal" + +msgid "Positive integer" +msgstr "Positivt heiltal" + +msgid "Positive small integer" +msgstr "Positivt lite heiltal" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (opp til %(max_length)s)" + +msgid "Text" +msgstr "Tekst" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"Verdien “%(value)s” har eit ugyldig format. Det må vere på formen HH:MM[:ss[." +"uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"Verdien “%(value)s” har rett format (HH:MM[:ss[.uuuuuu]]), men er eit " +"ugyldig klokkeslett." + +msgid "Time" +msgstr "Tid" + +msgid "URL" +msgstr "Nettadresse" + +msgid "Raw binary data" +msgstr "Rå binærdata" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "“%(value)s” er ikkje ein gyldig UUID." + +msgid "Universally unique identifier" +msgstr "Universelt unik identifikator." + +msgid "File" +msgstr "Fil" + +msgid "Image" +msgstr "Bilete" + +msgid "A JSON object" +msgstr "Eit JSON-objekt" + +msgid "Value must be valid JSON." +msgstr "Verdi må vere gyldig JSON." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(model)s-instans med %(field)s %(value)r eksisterer ikkje." + +msgid "Foreign Key (type determined by related field)" +msgstr "Fremmednøkkel (type bestemt av relatert felt)" + +msgid "One-to-one relationship" +msgstr "Ein-til-ein-forhold" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s-relasjon" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s-relasjonar" + +msgid "Many-to-many relationship" +msgstr "Mange-til-mange-forhold" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Feltet er påkravd." + +msgid "Enter a whole number." +msgstr "Oppgje eit heiltal." + +msgid "Enter a valid date." +msgstr "Oppgje ein gyldig dato." + +msgid "Enter a valid time." +msgstr "Oppgje eit gyldig tidspunkt." + +msgid "Enter a valid date/time." +msgstr "Oppgje gyldig dato og tidspunkt." + +msgid "Enter a valid duration." +msgstr "Oppgje ein gyldig varigskap." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Antal dagar må vere mellom {min_days} og {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Inga fil vart sendt. Sjekk \"encoding\"-typen på skjemaet." + +msgid "No file was submitted." +msgstr "Inga fil vart sendt." + +msgid "The submitted file is empty." +msgstr "Fila er tom." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Filnamnet kan ikkje ha fleire enn %(max)d teikn (det har %(length)d)." +msgstr[1] "" +"Filnamnet kan ikkje ha fleire enn %(max)d teikn (det har %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Last enten opp ei fil eller huk av i avkryssingsboksen." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Last opp eit gyldig bilete. Fila du lasta opp var ødelagt eller ikkje eit " +"bilete." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Velg eit gyldig valg. %(value)s er ikkje eit av dei tilgjengelege valga." + +msgid "Enter a list of values." +msgstr "Oppgje ei liste med verdiar." + +msgid "Enter a complete value." +msgstr "Oppgje ein fullstendig verdi." + +msgid "Enter a valid UUID." +msgstr "Oppgje ein gyldig UUID." + +msgid "Enter a valid JSON." +msgstr "Oppgje gyldig JSON." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Gøymt felt %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"ManagementForm data manglar eller har blitt tukla med. Felt som manglar: " +"%(field_names)s. Du burde kanskje sende ein feilrapport dersom problemet " +"fortset. " + +#, python-format +msgid "Please submit at most %d form." +msgid_plural "Please submit at most %d forms." +msgstr[0] "Ver vennleg å ikkje sende inn fleire enn %d skjema. " +msgstr[1] "Ver vennleg å ikkje sende inn fleire enn %d skjema. " + +#, python-format +msgid "Please submit at least %d form." +msgid_plural "Please submit at least %d forms." +msgstr[0] "Ver vennleg å sende inn minst %d skjema. " +msgstr[1] "Ver vennleg å sende inn minst %d skjema. " + +msgid "Order" +msgstr "Rekkefølge" + +msgid "Delete" +msgstr "Slett" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Korriger dupliserte data for %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Korriger dupliserte data for %(field)s, som må vere unike." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Korriger dupliserte data for %(field_name)s, som må vere unike for " +"%(lookup)s i %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Korriger dei dupliserte verdiane nedanfor." + +msgid "The inline value did not match the parent instance." +msgstr "Inline verdien stemmer ikkje overeins med forelder-instansen.  " + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Velg eit gyldig valg. Valget er ikkje eit av dei tilgjengelege valga." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "“%(pk)s” er ikkje ein gyldig verdi." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s kunne ikkje bli tolka i tidssona %(current_timezone)s; Verdien " +"er anten tvetydig eller ugyldig." + +msgid "Clear" +msgstr "Tøm" + +msgid "Currently" +msgstr "Noverande" + +msgid "Change" +msgstr "Endre" + +msgid "Unknown" +msgstr "Ukjend" + +msgid "Yes" +msgstr "Ja" + +msgid "No" +msgstr "Nei" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "ja,nei,kanskje" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d byte" +msgstr[1] "%(size)d bytes" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "midnatt" + +msgid "noon" +msgstr "12:00" + +msgid "Monday" +msgstr "måndag" + +msgid "Tuesday" +msgstr "tysdag" + +msgid "Wednesday" +msgstr "onsdag" + +msgid "Thursday" +msgstr "torsdag" + +msgid "Friday" +msgstr "fredag" + +msgid "Saturday" +msgstr "laurdag" + +msgid "Sunday" +msgstr "søndag" + +msgid "Mon" +msgstr "man" + +msgid "Tue" +msgstr "tys" + +msgid "Wed" +msgstr "ons" + +msgid "Thu" +msgstr "tor" + +msgid "Fri" +msgstr "fre" + +msgid "Sat" +msgstr "lau" + +msgid "Sun" +msgstr "søn" + +msgid "January" +msgstr "januar" + +msgid "February" +msgstr "februar" + +msgid "March" +msgstr "mars" + +msgid "April" +msgstr "april" + +msgid "May" +msgstr "mai" + +msgid "June" +msgstr "juni" + +msgid "July" +msgstr "juli" + +msgid "August" +msgstr "august" + +msgid "September" +msgstr "september" + +msgid "October" +msgstr "oktober" + +msgid "November" +msgstr "november" + +msgid "December" +msgstr "desember" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mars" + +msgid "apr" +msgstr "april" + +msgid "may" +msgstr "mai" + +msgid "jun" +msgstr "juni" + +msgid "jul" +msgstr "juli" + +msgid "aug" +msgstr "aug" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "okt" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "des" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "mars" + +msgctxt "abbrev. month" +msgid "April" +msgstr "april" + +msgctxt "abbrev. month" +msgid "May" +msgstr "mai" + +msgctxt "abbrev. month" +msgid "June" +msgstr "juni" + +msgctxt "abbrev. month" +msgid "July" +msgstr "juli" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "aug." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "sep." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "okt." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "des." + +msgctxt "alt. month" +msgid "January" +msgstr "Januar" + +msgctxt "alt. month" +msgid "February" +msgstr "Februar" + +msgctxt "alt. month" +msgid "March" +msgstr "Mars" + +msgctxt "alt. month" +msgid "April" +msgstr "April" + +msgctxt "alt. month" +msgid "May" +msgstr "Mai" + +msgctxt "alt. month" +msgid "June" +msgstr "Juni" + +msgctxt "alt. month" +msgid "July" +msgstr "Juli" + +msgctxt "alt. month" +msgid "August" +msgstr "August" + +msgctxt "alt. month" +msgid "September" +msgstr "September" + +msgctxt "alt. month" +msgid "October" +msgstr "Oktober" + +msgctxt "alt. month" +msgid "November" +msgstr "November" + +msgctxt "alt. month" +msgid "December" +msgstr "Desember" + +msgid "This is not a valid IPv6 address." +msgstr "Dette er ikkje ei gyldig IPv6-adresse." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "eller" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d år" +msgstr[1] "%(num)d år" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d månad" +msgstr[1] "%(num)d månader" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d veke" +msgstr[1] "%(num)d veker" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dag" +msgstr[1] "%(num)d dagar" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d time" +msgstr[1] "%(num)d timar" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minutt" +msgstr[1] "%(num)d minutt" + +msgid "Forbidden" +msgstr "Forbydd" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF-verifikasjon feila. Førespurnad avbrote." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Du ser denne meldinga på grunn av at det ikkje blei sendt nokon \"Referer\" " +"hovud frå din nettlesar, noko denne HTTPS-sida krev. Dette hovudet er eit " +"krav på grunn av sikkerheit, for å hindre at din nettlesar er kapra av " +"tredjepartar. " + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Dersom du har konfigurert nettlesaren din til å deaktiverere \"Referer\"-" +"hovud må du aktivere dei på nytt, i det minste for denne nettsida, eller for " +"HTTPS-tilkoplingar eller for førespurnadar av same opphav. " + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Dersom du brukar -taggen " +"eller inkludera \"Referrer-Policy: no-referrer\" hovud, ver vennleg å fjerne " +"dei. CSRF-vern krev \"Referer\" hovud for å gjennomføre strenge kontrollar " +"av referer. Dersom du har bekymringar for personvern bruk alternativ som for lenkjer til tredepartssider" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Du ser denne meldinga fordi denne nettsida krev ein CSRF informasjonskapsel " +"når du sender inn skjema. Denne informasjonskapselen er eit krav på grunn av " +"sikkerheit, for å forsikre at nettlesaren din ikkje er kapra av " +"tredjepartar. " + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Dersom du har konfigurert nettlesaren din til å deaktivere " +"informasjonskapslar, ver vennleg å aktiver dei på nytt, i det minste for " +"denne nettsida, eller for førespurnader av same opphav. " + +msgid "More information is available with DEBUG=True." +msgstr "Meir informasjon er tilgjengeleg med DEBUG=True." + +msgid "No year specified" +msgstr "Årstal ikkje spesifisert" + +msgid "Date out of range" +msgstr "Dato er utanfor rekkjevidde" + +msgid "No month specified" +msgstr "Månad ikkje spesifisert" + +msgid "No day specified" +msgstr "Dag ikkje spesifisert" + +msgid "No week specified" +msgstr "Veke ikkje spesifisert" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "%(verbose_name_plural)s tilgjengeleg" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Framtidig %(verbose_name_plural)s er ikkje tilgjengeleg fordi %(class_name)s." +"allow_future er sett til False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Ugyldig datostreng \"%(datestr)s\" grunna format \"%(format)s\"" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Fann ingen %(verbose_name)s som korresponderte med spørringa" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" +"Sida er ikkje \"last\" og den kan heller ikkje konverterast til eit heiltal. " + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Ugyldig side (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Tom liste og \"%(class_name)s.allow_empty\" er False." + +msgid "Directory indexes are not allowed here." +msgstr "Mappeindeksar er ikkje tillate her." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "\"%(path)s\" eksisterer ikkje" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Indeks for %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Installasjonen var vellykka! Gratulerer!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Sjå utgjevingsnotat for Django %(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" +"Du ser denne sida fordi DEBUG=True er i innstillingsfila di og du ikkje har konfigurert noka " +"nettadresser." + +msgid "Django Documentation" +msgstr "Django-dokumentasjon" + +msgid "Topics, references, & how-to’s" +msgstr "Tema, referansar, & how-tos" + +msgid "Tutorial: A Polling App" +msgstr "Opplæring: Ein avstemmingsapp" + +msgid "Get started with Django" +msgstr "Kom i gang med Django" + +msgid "Django Community" +msgstr "Django Nettsamfunn" + +msgid "Connect, get help, or contribute" +msgstr "Koble, få hjelp, eller bidra" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nn/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nn/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nn/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nn/formats.py new file mode 100644 index 0000000..0ddb8fe --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/nn/formats.py @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j. F Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = "j. F Y H:i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j. F" +SHORT_DATE_FORMAT = "d.m.Y" +SHORT_DATETIME_FORMAT = "d.m.Y H:i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# Kept ISO formats as they are in first position +DATE_INPUT_FORMATS = [ + "%Y-%m-%d", # '2006-10-25' + "%d.%m.%Y", # '25.10.2006' + "%d.%m.%y", # '25.10.06' + # "%d. %b %Y", # '25. okt 2006' + # "%d %b %Y", # '25 okt 2006' + # "%d. %b. %Y", # '25. okt. 2006' + # "%d %b. %Y", # '25 okt. 2006' + # "%d. %B %Y", # '25. oktober 2006' + # "%d %B %Y", # '25 oktober 2006' +] +DATETIME_INPUT_FORMATS = [ + "%Y-%m-%d %H:%M:%S", # '2006-10-25 14:30:59' + "%Y-%m-%d %H:%M:%S.%f", # '2006-10-25 14:30:59.000200' + "%Y-%m-%d %H:%M", # '2006-10-25 14:30' + "%d.%m.%Y %H:%M:%S", # '25.10.2006 14:30:59' + "%d.%m.%Y %H:%M:%S.%f", # '25.10.2006 14:30:59.000200' + "%d.%m.%Y %H:%M", # '25.10.2006 14:30' + "%d.%m.%y %H:%M:%S", # '25.10.06 14:30:59' + "%d.%m.%y %H:%M:%S.%f", # '25.10.06 14:30:59.000200' + "%d.%m.%y %H:%M", # '25.10.06 14:30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "\xa0" # non-breaking space +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/os/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/os/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b17907e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/os/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/os/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/os/LC_MESSAGES/django.po new file mode 100644 index 0000000..f3badb7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/os/LC_MESSAGES/django.po @@ -0,0 +1,1235 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Soslan Khubulov , 2013 +# Soslan Khubulov , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Ossetic (http://www.transifex.com/django/django/language/" +"os/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: os\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Африкаанс" + +msgid "Arabic" +msgstr "Араббаг" + +msgid "Asturian" +msgstr "" + +msgid "Azerbaijani" +msgstr "Тӕтӕйраг" + +msgid "Bulgarian" +msgstr "Болгайраг" + +msgid "Belarusian" +msgstr "Беларусаг" + +msgid "Bengali" +msgstr "Бенгалаг" + +msgid "Breton" +msgstr "Бретойнаг" + +msgid "Bosnian" +msgstr "Босниаг" + +msgid "Catalan" +msgstr "Каталайнаг" + +msgid "Czech" +msgstr "Чехаг" + +msgid "Welsh" +msgstr "Уельсаг" + +msgid "Danish" +msgstr "Даниаг" + +msgid "German" +msgstr "Немыцаг" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "Грекъаг" + +msgid "English" +msgstr "Англисаг" + +msgid "Australian English" +msgstr "" + +msgid "British English" +msgstr "Бритайнаг англисаг" + +msgid "Esperanto" +msgstr "Есперанто" + +msgid "Spanish" +msgstr "Испайнаг" + +msgid "Argentinian Spanish" +msgstr "Аргентинаг испайнаг" + +msgid "Colombian Spanish" +msgstr "" + +msgid "Mexican Spanish" +msgstr "Мексикайнаг Испайнаг" + +msgid "Nicaraguan Spanish" +msgstr "Никарагуайаг испайнаг" + +msgid "Venezuelan Spanish" +msgstr "Венесуелаг испайнаг" + +msgid "Estonian" +msgstr "Эстойнаг" + +msgid "Basque" +msgstr "Баскаг" + +msgid "Persian" +msgstr "Персайнаг" + +msgid "Finnish" +msgstr "Финнаг" + +msgid "French" +msgstr "Францаг" + +msgid "Frisian" +msgstr "Фризаг" + +msgid "Irish" +msgstr "Ирландиаг" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "Галициаг" + +msgid "Hebrew" +msgstr "Иврит" + +msgid "Hindi" +msgstr "Хинди" + +msgid "Croatian" +msgstr "Хорватаг" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "Венгриаг" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "Интерлингва" + +msgid "Indonesian" +msgstr "Индонезиаг" + +msgid "Ido" +msgstr "" + +msgid "Icelandic" +msgstr "Исландаг" + +msgid "Italian" +msgstr "Италиаг" + +msgid "Japanese" +msgstr "Япойнаг" + +msgid "Georgian" +msgstr "Гуырдзиаг" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "Казахаг" + +msgid "Khmer" +msgstr "Хмераг" + +msgid "Kannada" +msgstr "Каннадаг" + +msgid "Korean" +msgstr "Корейаг" + +msgid "Luxembourgish" +msgstr "Люксембургаг" + +msgid "Lithuanian" +msgstr "Литвайаг" + +msgid "Latvian" +msgstr "Латвийаг" + +msgid "Macedonian" +msgstr "Мӕчъидон" + +msgid "Malayalam" +msgstr "Малайаг" + +msgid "Mongolian" +msgstr "Монголиаг" + +msgid "Marathi" +msgstr "" + +msgid "Burmese" +msgstr "Бурмизаг" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "Непалаг" + +msgid "Dutch" +msgstr "Нидерландаг" + +msgid "Norwegian Nynorsk" +msgstr "Норвегийаг Нинорск" + +msgid "Ossetic" +msgstr "Ирон" + +msgid "Punjabi" +msgstr "Пенджабаг" + +msgid "Polish" +msgstr "Полаг" + +msgid "Portuguese" +msgstr "Португалаг" + +msgid "Brazilian Portuguese" +msgstr "Бразилаг португалаг" + +msgid "Romanian" +msgstr "Румынаг" + +msgid "Russian" +msgstr "Уырыссаг" + +msgid "Slovak" +msgstr "Словакиаг" + +msgid "Slovenian" +msgstr "Словенаг" + +msgid "Albanian" +msgstr "Албайнаг" + +msgid "Serbian" +msgstr "Сербаг" + +msgid "Serbian Latin" +msgstr "Латинаг Сербаг" + +msgid "Swedish" +msgstr "Шведаг" + +msgid "Swahili" +msgstr "Суахили" + +msgid "Tamil" +msgstr "Тамилаг" + +msgid "Telugu" +msgstr "Телугу" + +msgid "Thai" +msgstr "Тайаг" + +msgid "Turkish" +msgstr "Туркаг" + +msgid "Tatar" +msgstr "Тӕтӕйраг" + +msgid "Udmurt" +msgstr "Удмуртаг" + +msgid "Ukrainian" +msgstr "Украинаг" + +msgid "Urdu" +msgstr "Урду" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "Вьетнамаг" + +msgid "Simplified Chinese" +msgstr "Ӕнцонгонд Китайаг" + +msgid "Traditional Chinese" +msgstr "Традицион Китайаг" + +msgid "Messages" +msgstr "" + +msgid "Site Maps" +msgstr "" + +msgid "Static Files" +msgstr "" + +msgid "Syndication" +msgstr "" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "Раст бӕрц бафысс." + +msgid "Enter a valid URL." +msgstr "Раст URL бафысс." + +msgid "Enter a valid integer." +msgstr "" + +msgid "Enter a valid email address." +msgstr "Раст email адрис бафысс." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Раст IPv4 адрис бафысс." + +msgid "Enter a valid IPv6 address." +msgstr "Раст IPv6 адрис бафысс." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Раст IPv4 кӕнӕ IPv6 адрис бафысс." + +msgid "Enter only digits separated by commas." +msgstr "Бафысс ӕрмӕст нымӕцтӕ, къӕдзгуытӕй дихгонд." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Ацы бӕрц хъуамӕ уа %(limit_value)s (у %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Ацы бӕрц хъуамӕ уа %(limit_value)s, кӕнӕ цъусдӕр." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Ацы бӕрц хъуамӕ уа %(limit_value)s, кӕнӕ цъусдӕр." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Дӕ хъус бадар цӕмӕй ам %(limit_value)d дамгъӕ уӕддӕр уа (ис дзы " +"%(show_value)d)." +msgstr[1] "" +"Дӕ хъус бадар цӕмӕй ам %(limit_value)d дамгъӕйы уӕддӕр уа (ис дзы " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Дӕ хъус бадар цӕмӕй ам %(limit_value)d дамгъӕйӕ фылдӕр ма уа (ис дзы " +"%(show_value)d)." +msgstr[1] "" +"Дӕ хъус бадар цӕмӕй ам %(limit_value)d дамгъӕйӕ фылдӕр ма уа (ис дзы " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Бафысс нымӕц." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Дӕ хъус бадар цӕмӕй иууыл иумӕ %(max)s цифрӕйӕ фылдӕр уой." +msgstr[1] "Дӕ хъус бадар цӕмӕй иууыл иумӕ %(max)s цифрӕйӕ фылдӕр уой." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Дӕ хъус бадар цӕмӕй дӕсон бынӕттӕ %(max)s-ӕй фылдӕр ма уой." +msgstr[1] "Дӕ хъус бадар цӕмӕй дӕсон бынӕттӕ %(max)s-ӕй фылдӕр ма уой." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Дӕ хъус бадар цӕмӕй дӕсон стъӕлфы размӕ %(max)s цифрӕйӕ фылдӕр ма уа." +msgstr[1] "" +"Дӕ хъус бадар цӕмӕй дӕсон стъӕлфы размӕ %(max)s цифрӕйӕ фылдӕр ма уа." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "ӕмӕ" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "Ацы быдыр нул ма хъуамӕ уа." + +msgid "This field cannot be blank." +msgstr "Ацы быдыр афтид ма хъуамӕ уа." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s ацы %(field_label)s-имӕ нырид ис." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Быдыры хуыз: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "Булон (Бӕлвырд кӕнӕ Мӕнг)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Рӕнхъ (%(max_length)s-ы йонг)" + +msgid "Comma-separated integers" +msgstr "Къӕдзыгӕй хицӕнгонд ӕгас нымӕцтӕ" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "Бон (ӕнӕ рӕстӕг)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Бон (ӕд рӕстӕг)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Дӕсон нымӕц" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "" + +msgid "Email address" +msgstr "Электрон посты адрис" + +msgid "File path" +msgstr "Файлы фӕт" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "Уӕгъд стъӕлфимӕ нымӕц" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "Ӕгас нымӕц" + +msgid "Big (8 byte) integer" +msgstr "Стыр (8 байты) ӕгас нымӕц" + +msgid "IPv4 address" +msgstr "IPv4 адрис" + +msgid "IP address" +msgstr "IP адрис" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "Булон (Бӕлвырд, Мӕнг кӕнӕ Ницы)" + +msgid "Positive integer" +msgstr "Позитивон ӕгас нымӕц" + +msgid "Positive small integer" +msgstr "Позитивон гыццыл ӕгас нымӕц" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Слаг (ӕппӕты фылдӕр %(max_length)s)" + +msgid "Small integer" +msgstr "Гыццыл ӕгас нымӕц" + +msgid "Text" +msgstr "Текст" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Рӕстӕг" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Хом бинарон рардтӕ" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "Файл" + +msgid "Image" +msgstr "Ныв" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "Ӕттагон Амонӕн (хӕстӕг быдырӕй бӕрӕггонд хуыз)" + +msgid "One-to-one relationship" +msgstr "Иуӕн-иу бастдзинад" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "Бирӕйӕн-бирӕ бастдзинад" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr "" + +msgid "This field is required." +msgstr "Ацы быдыр ӕнӕмӕнг у." + +msgid "Enter a whole number." +msgstr "Бафысс ӕнӕхъӕн нымӕц." + +msgid "Enter a valid date." +msgstr "Раст бон бафысс." + +msgid "Enter a valid time." +msgstr "Раст рӕстӕг бафысс." + +msgid "Enter a valid date/time." +msgstr "Раст бон/рӕстӕг бафысс." + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Ницы файл уыд лӕвӕрд. Абӕрӕг кӕн формӕйы кодкӕнынады хуыз." + +msgid "No file was submitted." +msgstr "Ницы файл уыд лӕвӕрд." + +msgid "The submitted file is empty." +msgstr "Лӕвӕрд файл афтид у." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Дӕ хъус бадар цӕмӕй ацы файлы номы %(max)d дамгъӕйӕ фылдӕр ма уа(ис дзы " +"%(length)d)." +msgstr[1] "" +"Дӕ хъус бадар цӕмӕй ацы файлы номы %(max)d дамгъӕйӕ фылдӕр ма уа(ис дзы " +"%(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Дӕ хорзӕхӕй, кӕнӕ бадӕтт файл, кӕнӕ банысан кӕн сыгъдӕг чекбокс. Дыууӕ иумӕ " +"нӕ." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Раст ныв бавгӕн. Ды цы файл бавгӕдтай, уый кӕнӕ ныв нӕ уыд, кӕнӕ хӕлд ныв " +"уыд." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Раст фадат равзар. %(value)s фадӕтты ӕхсӕн нӕй." + +msgid "Enter a list of values." +msgstr "Бафысс мидисты номхыгъд." + +msgid "Enter a complete value." +msgstr "" + +msgid "Enter a valid UUID." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr "" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Ӕмбӕхст быдыр %(name)s) %(error)s" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "Рад" + +msgid "Delete" +msgstr "Схафын" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Дӕ хорзӕхӕй, %(field)s-ы дывӕр рардтӕ сраст кӕн." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Дӕ хорзӕхӕй, %(field)s-ы дывӕр рардтӕ сраст кӕн. Хъуамӕ уникалон уа." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Дӕ хорзӕхӕй, %(field_name)s-ы дывӕр рардтӕ сраст кӕн. Хъуамӕ %(date_field)s-" +"ы %(lookup)s-ӕн уникалон уа. " + +msgid "Please correct the duplicate values below." +msgstr "Дӕ хорзӕхӕй, бындӕр цы дывӕр рардтӕ ис, уыдон сраст кӕн." + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Раст фадат равзар. УКыцы фадат фадӕтты ӕхсӕн нӕй." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Сыгъдӕг" + +msgid "Currently" +msgstr "Ныр" + +msgid "Change" +msgstr "Фӕивын" + +msgid "Unknown" +msgstr "Ӕнӕбӕрӕг" + +msgid "Yes" +msgstr "О" + +msgid "No" +msgstr "Нӕ" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "о,нӕ,гӕнӕн ис" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d байт" +msgstr[1] "%(size)d байты" + +#, python-format +msgid "%s KB" +msgstr "%s КБ" + +#, python-format +msgid "%s MB" +msgstr "%s МБ" + +#, python-format +msgid "%s GB" +msgstr "%s ГБ" + +#, python-format +msgid "%s TB" +msgstr "%s ТБ" + +#, python-format +msgid "%s PB" +msgstr "%s ПБ" + +msgid "p.m." +msgstr "ӕ.ф." + +msgid "a.m." +msgstr "ӕ.р." + +msgid "PM" +msgstr "ӔФ" + +msgid "AM" +msgstr "ӔР" + +msgid "midnight" +msgstr "ӕмбисӕхсӕв" + +msgid "noon" +msgstr "ӕмбисбон" + +msgid "Monday" +msgstr "Къуырисӕр" + +msgid "Tuesday" +msgstr "Дыццӕг" + +msgid "Wednesday" +msgstr "Ӕртыццӕг" + +msgid "Thursday" +msgstr "Цыппӕрӕм" + +msgid "Friday" +msgstr "Майрӕмбон" + +msgid "Saturday" +msgstr "Сабат" + +msgid "Sunday" +msgstr "Хуыцаубон" + +msgid "Mon" +msgstr "Крс" + +msgid "Tue" +msgstr "Дцг" + +msgid "Wed" +msgstr "Ӕрт" + +msgid "Thu" +msgstr "Цпр" + +msgid "Fri" +msgstr "Мрб" + +msgid "Sat" +msgstr "Сбт" + +msgid "Sun" +msgstr "Хцб" + +msgid "January" +msgstr "Январь" + +msgid "February" +msgstr "Февраль" + +msgid "March" +msgstr "Мартъи" + +msgid "April" +msgstr "Апрель" + +msgid "May" +msgstr "Май" + +msgid "June" +msgstr "Июнь" + +msgid "July" +msgstr "Июль" + +msgid "August" +msgstr "Август" + +msgid "September" +msgstr "Сентябрь" + +msgid "October" +msgstr "Октябрь" + +msgid "November" +msgstr "Ноябрь" + +msgid "December" +msgstr "Декабрь" + +msgid "jan" +msgstr "янв" + +msgid "feb" +msgstr "фев" + +msgid "mar" +msgstr "мар" + +msgid "apr" +msgstr "апр" + +msgid "may" +msgstr "май" + +msgid "jun" +msgstr "июн" + +msgid "jul" +msgstr "июл" + +msgid "aug" +msgstr "авг" + +msgid "sep" +msgstr "сен" + +msgid "oct" +msgstr "окт" + +msgid "nov" +msgstr "ноя" + +msgid "dec" +msgstr "дек" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Янв." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Фев." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Мартъи" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Апрель" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Май" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Июнь" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Июль" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Авг." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Сен." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Окт." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Ноя." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Дек." + +msgctxt "alt. month" +msgid "January" +msgstr "Январь" + +msgctxt "alt. month" +msgid "February" +msgstr "Февраль" + +msgctxt "alt. month" +msgid "March" +msgstr "Мартъи" + +msgctxt "alt. month" +msgid "April" +msgstr "Апрель" + +msgctxt "alt. month" +msgid "May" +msgstr "Май" + +msgctxt "alt. month" +msgid "June" +msgstr "Июнь" + +msgctxt "alt. month" +msgid "July" +msgstr "Июль" + +msgctxt "alt. month" +msgid "August" +msgstr "Август" + +msgctxt "alt. month" +msgid "September" +msgstr "Сентябрь" + +msgctxt "alt. month" +msgid "October" +msgstr "Октябрь" + +msgctxt "alt. month" +msgid "November" +msgstr "Ноябрь" + +msgctxt "alt. month" +msgid "December" +msgstr "Декабрь" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "кӕнӕ" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d аз" +msgstr[1] "%d азы" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d мӕй" +msgstr[1] "%d мӕйы" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d къуыри" +msgstr[1] "%d къуырийы" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d бон" +msgstr[1] "%d боны" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d сахат" +msgstr[1] "%d сахаты" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d минут" +msgstr[1] "%d минуты" + +msgid "0 minutes" +msgstr "0 минуты" + +msgid "Forbidden" +msgstr "" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "Аз амынд нӕ уыд" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "Мӕй амынд нӕ уыд" + +msgid "No day specified" +msgstr "Бон амынд нӕ уыд" + +msgid "No week specified" +msgstr "Къуыри амынд нӕ уыд" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Ницы %(verbose_name_plural)s ис" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Фидӕн %(verbose_name_plural)s-мӕ бавналӕн нӕй, уымӕн ӕмӕ %(class_name)s." +"allow_future Мӕнг у." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Домӕнӕн ницы %(verbose_name)s ӕмбӕлы" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Мӕнг фарс (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Ам директориты индекстӕ нӕй гӕнӕн." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "%(directory)s-ы индекс" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pa/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pa/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a8fa88b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pa/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pa/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pa/LC_MESSAGES/django.po new file mode 100644 index 0000000..d71b5f7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pa/LC_MESSAGES/django.po @@ -0,0 +1,1213 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# A S Alam , 2011,2013,2015 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Panjabi (Punjabi) (http://www.transifex.com/django/django/" +"language/pa/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pa\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "ਅਫਰੀਕੀ" + +msgid "Arabic" +msgstr "ਅਰਬੀ" + +msgid "Asturian" +msgstr "" + +msgid "Azerbaijani" +msgstr "ਅਜ਼ਰਬਾਈਜਾਨੀ" + +msgid "Bulgarian" +msgstr "ਬੁਲਗਾਰੀਆਈ" + +msgid "Belarusian" +msgstr "ਬੇਲਾਰੂਸੀ" + +msgid "Bengali" +msgstr "ਬੰਗਾਲੀ" + +msgid "Breton" +msgstr "ਬਰੇਟੋਨ" + +msgid "Bosnian" +msgstr "ਬੋਸਨੀਆਈ" + +msgid "Catalan" +msgstr "ਕਾਟਾਲਾਨ" + +msgid "Czech" +msgstr "ਚੈੱਕ" + +msgid "Welsh" +msgstr "ਵੈਲਸ਼" + +msgid "Danish" +msgstr "ਡੈਨਿਸ਼" + +msgid "German" +msgstr "ਜਰਮਨ" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "ਗਰੀਕ" + +msgid "English" +msgstr "ਅੰਗਰੇਜ਼ੀ" + +msgid "Australian English" +msgstr "" + +msgid "British English" +msgstr "ਬਰਤਾਨੀਵੀਂ ਅੰਗਰੇਜ਼ੀ" + +msgid "Esperanto" +msgstr "" + +msgid "Spanish" +msgstr "ਸਪੇਨੀ" + +msgid "Argentinian Spanish" +msgstr "ਅਰਜਨਟੀਨੀ ਸਪੇਨੀ" + +msgid "Colombian Spanish" +msgstr "" + +msgid "Mexican Spanish" +msgstr "ਮੈਕਸੀਕਨ ਸਪੇਨੀ" + +msgid "Nicaraguan Spanish" +msgstr "" + +msgid "Venezuelan Spanish" +msgstr "" + +msgid "Estonian" +msgstr "ਈਸਟੋਨੀਆਈ" + +msgid "Basque" +msgstr "ਬਸਕਿਊ" + +msgid "Persian" +msgstr "ਪਰਸ਼ੀਆਈ" + +msgid "Finnish" +msgstr "ਫੈਨਿਸ਼" + +msgid "French" +msgstr "ਫਰੈਂਚ" + +msgid "Frisian" +msgstr "ਫ਼ਾਰਸੀ" + +msgid "Irish" +msgstr "ਆਈਰਸ਼" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "ਗਲੀਸੀਆਈ" + +msgid "Hebrew" +msgstr "ਹੈਬਰਿਊ" + +msgid "Hindi" +msgstr "ਹਿੰਦੀ" + +msgid "Croatian" +msgstr "ਕਰੋਆਟੀਆਈ" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "ਹੰਗਰੀਆਈ" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "" + +msgid "Indonesian" +msgstr "ਇੰਡੋਨੇਸ਼ੀਆਈ" + +msgid "Ido" +msgstr "" + +msgid "Icelandic" +msgstr "ਆਈਸਲੈਂਡਿਕ" + +msgid "Italian" +msgstr "ਇਤਾਲਵੀ" + +msgid "Japanese" +msgstr "ਜਾਪਾਨੀ" + +msgid "Georgian" +msgstr "ਜਾਰਜੀਆਈ" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "ਕਜ਼ਾਖ" + +msgid "Khmer" +msgstr "ਖਮੀਰ" + +msgid "Kannada" +msgstr "ਕੰਨੜ" + +msgid "Korean" +msgstr "ਕੋਰੀਆਈ" + +msgid "Luxembourgish" +msgstr "" + +msgid "Lithuanian" +msgstr "ਲੀਥੁਨੀਆਈ" + +msgid "Latvian" +msgstr "ਲਾਟਵੀਅਨ" + +msgid "Macedonian" +msgstr "ਮੈਕਡੋਨੀਆਈ" + +msgid "Malayalam" +msgstr "ਮਲਿਆਲਮ" + +msgid "Mongolian" +msgstr "ਮੰਗੋਲੀਆਈ" + +msgid "Marathi" +msgstr "ਮਰਾਠੀ" + +msgid "Burmese" +msgstr "" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "ਨੇਪਾਲੀ" + +msgid "Dutch" +msgstr "ਡੱਚ" + +msgid "Norwegian Nynorsk" +msgstr "ਨਾਰਵੇਗੀਅਨ ਨਯਨੋਰਸਕ" + +msgid "Ossetic" +msgstr "" + +msgid "Punjabi" +msgstr "ਪੰਜਾਬੀ" + +msgid "Polish" +msgstr "ਪੋਲੈਂਡੀ" + +msgid "Portuguese" +msgstr "ਪੁਰਤਗਾਲੀ" + +msgid "Brazilian Portuguese" +msgstr "ਬਰਾਜ਼ੀਲੀ ਪੁਰਤਗਾਲੀ" + +msgid "Romanian" +msgstr "ਰੋਮਾਨੀਆਈ" + +msgid "Russian" +msgstr "ਰੂਸੀ" + +msgid "Slovak" +msgstr "ਸਲੋਵਾਕ" + +msgid "Slovenian" +msgstr "ਸਲੋਵੀਨੀਆਈ" + +msgid "Albanian" +msgstr "ਅਲਬੀਨੀਆਈ" + +msgid "Serbian" +msgstr "ਸਰਬੀਆਈ" + +msgid "Serbian Latin" +msgstr "ਸਰਬੀਆਈ ਲੈਟਿਨ" + +msgid "Swedish" +msgstr "ਸਵੀਡਨੀ" + +msgid "Swahili" +msgstr "" + +msgid "Tamil" +msgstr "ਤਾਮਿਲ" + +msgid "Telugu" +msgstr "ਤੇਲਗੂ" + +msgid "Thai" +msgstr "ਥਾਈ" + +msgid "Turkish" +msgstr "ਤੁਰਕ" + +msgid "Tatar" +msgstr "ਤਤਾਰ" + +msgid "Udmurt" +msgstr "" + +msgid "Ukrainian" +msgstr "ਯੂਕਰੇਨੀ" + +msgid "Urdu" +msgstr "ਉਰਦੂ" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "ਵੀਅਤਨਾਮੀ" + +msgid "Simplified Chinese" +msgstr "ਸਧਾਰਨ ਚੀਨੀ" + +msgid "Traditional Chinese" +msgstr "ਮੂਲ ਚੀਨੀ" + +msgid "Messages" +msgstr "ਸੁਨੇਹੇ" + +msgid "Site Maps" +msgstr "ਸਾਈਟ ਖਾਕੇ" + +msgid "Static Files" +msgstr "ਸਥਿਰ ਫਾਈਲਾਂ" + +msgid "Syndication" +msgstr "" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "ਠੀਕ ਮੁੱਲ ਦਿਓ" + +msgid "Enter a valid URL." +msgstr "ਠੀਕ URL ਦਿਉ।" + +msgid "Enter a valid integer." +msgstr "" + +msgid "Enter a valid email address." +msgstr "ਢੁੱਕਵਾਂ ਈਮੇਲ ਸਿਰਨਾਵਾਂ ਦਿਉ ਜੀ।" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "" + +msgid "Enter a valid IPv6 address." +msgstr "" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "" + +msgid "Enter only digits separated by commas." +msgstr "" + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Enter a number." +msgstr "ਨੰਬਰ ਦਿਓ।" + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "ਅਤੇ" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "" + +msgid "This field cannot be blank." +msgstr "ਇਹ ਖੇਤਰ ਖਾਲੀ ਨਹੀਂ ਹੋ ਸਕਦਾ ਹੈ।" + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "" + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "ਖੇਤਰ ਦੀ ਕਿਸਮ: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "" + +msgid "Comma-separated integers" +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "ਮਿਤੀ (ਬਿਨਾਂ ਸਮਾਂ)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "ਮਿਤੀ (ਸਮੇਂ ਨਾਲ)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "ਦਸ਼ਮਲਵ ਅੰਕ" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "ਅੰਤਰਾਲ" + +msgid "Email address" +msgstr "ਈਮੇਲ ਐਡਰੈੱਸ" + +msgid "File path" +msgstr "ਫਾਇਲ ਪਾਥ" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "ਅੰਕ" + +msgid "Big (8 byte) integer" +msgstr "" + +msgid "IPv4 address" +msgstr "IPv4 ਸਿਰਨਾਵਾਂ" + +msgid "IP address" +msgstr "IP ਐਡਰੈੱਸ" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "" + +msgid "Positive integer" +msgstr "" + +msgid "Positive small integer" +msgstr "" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "" + +msgid "Small integer" +msgstr "" + +msgid "Text" +msgstr "ਟੈਕਸਟ" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "ਸਮਾਂ" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "ਫਾਇਲ" + +msgid "Image" +msgstr "ਚਿੱਤਰ" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "" + +msgid "One-to-one relationship" +msgstr "ਇੱਕ-ਤੋਂ-ਇੱਕ ਸਬੰਧ" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "ਕਈ-ਤੋਂ-ਕਈ ਸਬੰਧ" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr "" + +msgid "This field is required." +msgstr "ਇਹ ਖੇਤਰ ਲਾਜ਼ਮੀ ਹੈ।" + +msgid "Enter a whole number." +msgstr "ਪੂਰਨ ਨੰਬਰ ਦਿਉ।" + +msgid "Enter a valid date." +msgstr "ਠੀਕ ਮਿਤੀ ਦਿਓ।" + +msgid "Enter a valid time." +msgstr "ਠੀਕ ਸਮਾਂ ਦਿਓ।" + +msgid "Enter a valid date/time." +msgstr "ਠੀਕ ਮਿਤੀ/ਸਮਾਂ ਦਿਓ।" + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" + +msgid "No file was submitted." +msgstr "ਕੋਈ ਫਾਇਲ ਨਹੀਂ ਭੇਜੀ।" + +msgid "The submitted file is empty." +msgstr "ਦਿੱਤੀ ਫਾਇਲ ਖਾਲੀ ਹੈ।" + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" + +msgid "Enter a list of values." +msgstr "ਮੁੱਲ ਦੀ ਲਿਸਟ ਦਿਓ।" + +msgid "Enter a complete value." +msgstr "" + +msgid "Enter a valid UUID." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "ਲੜੀ" + +msgid "Delete" +msgstr "ਹਟਾਓ" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "" + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" + +msgid "Please correct the duplicate values below." +msgstr "" + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "ਸਾਫ਼ ਕਰੋ" + +msgid "Currently" +msgstr "ਮੌਜੂਦਾ" + +msgid "Change" +msgstr "ਬਦਲੋ" + +msgid "Unknown" +msgstr "ਅਣਜਾਣ" + +msgid "Yes" +msgstr "ਹਾਂ" + +msgid "No" +msgstr "ਨਹੀਂ" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "ਹਾਂ,ਨਹੀਂ,ਸ਼ਾਇਦ" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d ਬਾਈਟ" +msgstr[1] "%(size)d ਬਾਈਟ" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "ਸ਼ਾਮ" + +msgid "AM" +msgstr "ਸਵੇਰ" + +msgid "midnight" +msgstr "ਅੱਧੀ-ਰਾਤ" + +msgid "noon" +msgstr "ਨੂਨ" + +msgid "Monday" +msgstr "ਸੋਮਵਾਰ" + +msgid "Tuesday" +msgstr "ਮੰਗਲਵਾਰ" + +msgid "Wednesday" +msgstr "ਬੁੱਧਵਾਰ" + +msgid "Thursday" +msgstr "ਵੀਰਵਾਰ" + +msgid "Friday" +msgstr "ਸ਼ੁੱਕਰਵਾਰ" + +msgid "Saturday" +msgstr "ਸ਼ਨਿੱਚਰਵਾਰ" + +msgid "Sunday" +msgstr "ਐਤਵਾਰ" + +msgid "Mon" +msgstr "ਸੋਮ" + +msgid "Tue" +msgstr "ਮੰਗ" + +msgid "Wed" +msgstr "ਬੁੱਧ" + +msgid "Thu" +msgstr "ਵੀਰ" + +msgid "Fri" +msgstr "ਸ਼ੁੱਕ" + +msgid "Sat" +msgstr "ਸ਼ਨਿੱ" + +msgid "Sun" +msgstr "ਐਤ" + +msgid "January" +msgstr "ਜਨਵਰੀ" + +msgid "February" +msgstr "ਫਰਵਰੀ" + +msgid "March" +msgstr "ਮਾਰਚ" + +msgid "April" +msgstr "ਅਪਰੈਲ" + +msgid "May" +msgstr "ਮਈ" + +msgid "June" +msgstr "ਜੂਨ" + +msgid "July" +msgstr "ਜੁਲਾਈ" + +msgid "August" +msgstr "ਅਗਸਤ" + +msgid "September" +msgstr "ਸਤੰਬਰ" + +msgid "October" +msgstr "ਅਕਤੂਬਰ" + +msgid "November" +msgstr "ਨਵੰਬਰ" + +msgid "December" +msgstr "ਦਸੰਬਰ" + +msgid "jan" +msgstr "ਜਨ" + +msgid "feb" +msgstr "ਫਰ" + +msgid "mar" +msgstr "ਮਾਰ" + +msgid "apr" +msgstr "ਅਪ" + +msgid "may" +msgstr "ਮਈ" + +msgid "jun" +msgstr "ਜੂਨ" + +msgid "jul" +msgstr "ਜੁਲ" + +msgid "aug" +msgstr "ਅਗ" + +msgid "sep" +msgstr "ਸਤੰ" + +msgid "oct" +msgstr "ਅਕ" + +msgid "nov" +msgstr "ਨਵੰ" + +msgid "dec" +msgstr "ਦਸੰ" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "ਜਨ" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "ਫਰ" + +msgctxt "abbrev. month" +msgid "March" +msgstr "ਮਾਰ" + +msgctxt "abbrev. month" +msgid "April" +msgstr "ਅਪ" + +msgctxt "abbrev. month" +msgid "May" +msgstr "ਮਈ" + +msgctxt "abbrev. month" +msgid "June" +msgstr "ਜੂਨ" + +msgctxt "abbrev. month" +msgid "July" +msgstr "ਜੁਲ" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "ਅਗ" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "ਸਤੰ" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "ਅਕਤੂ" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "ਨਵੰ" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "ਦਸੰ" + +msgctxt "alt. month" +msgid "January" +msgstr "ਜਨਵਰੀ" + +msgctxt "alt. month" +msgid "February" +msgstr "ਫਰਵਰੀ" + +msgctxt "alt. month" +msgid "March" +msgstr "ਮਾਰਚ" + +msgctxt "alt. month" +msgid "April" +msgstr "ਅਪਰੈਲ" + +msgctxt "alt. month" +msgid "May" +msgstr "ਮਈ" + +msgctxt "alt. month" +msgid "June" +msgstr "ਜੂਨ" + +msgctxt "alt. month" +msgid "July" +msgstr "ਜੁਲਾਈ" + +msgctxt "alt. month" +msgid "August" +msgstr "ਅਗਸਤ" + +msgctxt "alt. month" +msgid "September" +msgstr "ਸਤੰਬਰ" + +msgctxt "alt. month" +msgid "October" +msgstr "ਅਕਤੂਬਰ" + +msgctxt "alt. month" +msgid "November" +msgstr "ਨਵੰਬਰ" + +msgctxt "alt. month" +msgid "December" +msgstr "ਦਸੰਬਰ" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "ਜਾਂ" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "," + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d ਸਾਲ" +msgstr[1] "%d ਸਾਲ" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d ਮਹੀਨਾ" +msgstr[1] "%d ਮਹੀਨੇ" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d ਹਫ਼ਤਾ" +msgstr[1] "%d ਹਫ਼ਤੇ" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d ਦਿਨ" +msgstr[1] "%d ਦਿਨ" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d ਘੰਟਾ" +msgstr[1] "%d ਘੰਟੇ" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d ਮਿੰਟ" +msgstr[1] "%d ਮਿੰਟ" + +msgid "0 minutes" +msgstr "0 ਮਿੰਟ" + +msgid "Forbidden" +msgstr "" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "ਕੋਈ ਸਾਲ ਨਹੀਂ ਦਿੱਤਾ" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "ਕੋਈ ਮਹੀਨਾ ਨਹੀਂ ਦਿੱਤਾ" + +msgid "No day specified" +msgstr "ਕੋਈ ਦਿਨ ਨਹੀਂ ਦਿੱਤਾ" + +msgid "No week specified" +msgstr "ਕੋਈ ਹਫ਼ਤਾ ਨਹੀਂ ਦਿੱਤਾ" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "" + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "%(directory)s ਦਾ ਇੰਡੈਕਸ" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3da1380 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pl/LC_MESSAGES/django.po new file mode 100644 index 0000000..99d69fa --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pl/LC_MESSAGES/django.po @@ -0,0 +1,1415 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# 8ffa075ab2f53c280beb2c066769d1ac_169beb5 <462ee687bbf3107fab5af73e8cc690d0_217822>, 2014 +# Adam Stachowicz , 2015 +# angularcircle, 2011,2013 +# angularcircle, 2011,2013 +# angularcircle, 2014 +# Dariusz Paluch , 2015 +# Darek, 2022 +# Jannis Leidel , 2011 +# Janusz Harkot , 2014-2015 +# Kacper Krupa , 2013 +# Karol , 2012 +# 0d5641585fd67fbdb97037c19ab83e4c_18c98b0 , 2011 +# 0d5641585fd67fbdb97037c19ab83e4c_18c98b0 , 2011 +# Łukasz Rekucki (lqc) , 2011 +# Maciej Olko , 2016-2021 +# Maciej Olko , 2023 +# Maciej Olko , 2015 +# Mariusz Felisiak , 2020-2021,2023 +# Michał Pasternak , 2013 +# c10516f0462e552b4c3672569f0745a7_cc5cca2 <841826256cd8f47d0e443806a8e56601_19204>, 2012 +# Piotr Meuś , 2014 +# c10516f0462e552b4c3672569f0745a7_cc5cca2 <841826256cd8f47d0e443806a8e56601_19204>, 2012 +# Quadric , 2014 +# Radek Czajka , 2013 +# Radek Czajka , 2013 +# Roman Barczyński, 2012 +# 8ffa075ab2f53c280beb2c066769d1ac_169beb5 <462ee687bbf3107fab5af73e8cc690d0_217822>, 2014 +# Tomasz Kajtoch , 2016-2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Mariusz Felisiak , " +"2020-2021,2023\n" +"Language-Team: Polish (http://app.transifex.com/django/django/language/pl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pl\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && " +"(n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && " +"n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" + +msgid "Afrikaans" +msgstr "afrykanerski" + +msgid "Arabic" +msgstr "arabski" + +msgid "Algerian Arabic" +msgstr "algierski arabski" + +msgid "Asturian" +msgstr "asturyjski" + +msgid "Azerbaijani" +msgstr "azerski" + +msgid "Bulgarian" +msgstr "bułgarski" + +msgid "Belarusian" +msgstr "białoruski" + +msgid "Bengali" +msgstr "bengalski" + +msgid "Breton" +msgstr "bretoński" + +msgid "Bosnian" +msgstr "bośniacki" + +msgid "Catalan" +msgstr "kataloński" + +msgid "Central Kurdish (Sorani)" +msgstr "sorani" + +msgid "Czech" +msgstr "czeski" + +msgid "Welsh" +msgstr "walijski" + +msgid "Danish" +msgstr "duński" + +msgid "German" +msgstr "niemiecki" + +msgid "Lower Sorbian" +msgstr "dolnołużycki" + +msgid "Greek" +msgstr "grecki" + +msgid "English" +msgstr "angielski" + +msgid "Australian English" +msgstr "australijski angielski" + +msgid "British English" +msgstr "brytyjski angielski" + +msgid "Esperanto" +msgstr "esperanto" + +msgid "Spanish" +msgstr "hiszpański" + +msgid "Argentinian Spanish" +msgstr "hiszpański argentyński" + +msgid "Colombian Spanish" +msgstr "hiszpański kolumbijski" + +msgid "Mexican Spanish" +msgstr "hiszpański meksykański" + +msgid "Nicaraguan Spanish" +msgstr "hiszpański nikaraguański" + +msgid "Venezuelan Spanish" +msgstr "hiszpański wenezuelski" + +msgid "Estonian" +msgstr "estoński" + +msgid "Basque" +msgstr "baskijski" + +msgid "Persian" +msgstr "perski" + +msgid "Finnish" +msgstr "fiński" + +msgid "French" +msgstr "francuski" + +msgid "Frisian" +msgstr "fryzyjski" + +msgid "Irish" +msgstr "irlandzki" + +msgid "Scottish Gaelic" +msgstr "Szkocki gaelicki" + +msgid "Galician" +msgstr "galicyjski" + +msgid "Hebrew" +msgstr "hebrajski" + +msgid "Hindi" +msgstr "hindi" + +msgid "Croatian" +msgstr "chorwacki" + +msgid "Upper Sorbian" +msgstr "górnołużycki" + +msgid "Hungarian" +msgstr "węgierski" + +msgid "Armenian" +msgstr "ormiański" + +msgid "Interlingua" +msgstr "interlingua" + +msgid "Indonesian" +msgstr "indonezyjski" + +msgid "Igbo" +msgstr "igbo" + +msgid "Ido" +msgstr "ido" + +msgid "Icelandic" +msgstr "islandzki" + +msgid "Italian" +msgstr "włoski" + +msgid "Japanese" +msgstr "japoński" + +msgid "Georgian" +msgstr "gruziński" + +msgid "Kabyle" +msgstr "kabylski" + +msgid "Kazakh" +msgstr "kazachski" + +msgid "Khmer" +msgstr "khmerski" + +msgid "Kannada" +msgstr "kannada" + +msgid "Korean" +msgstr "koreański" + +msgid "Kyrgyz" +msgstr "kirgiski" + +msgid "Luxembourgish" +msgstr "luksemburski" + +msgid "Lithuanian" +msgstr "litewski" + +msgid "Latvian" +msgstr "łotewski" + +msgid "Macedonian" +msgstr "macedoński" + +msgid "Malayalam" +msgstr "malajski" + +msgid "Mongolian" +msgstr "mongolski" + +msgid "Marathi" +msgstr "marathi" + +msgid "Malay" +msgstr "malajski" + +msgid "Burmese" +msgstr "birmański" + +msgid "Norwegian Bokmål" +msgstr "norweski (bokmål)" + +msgid "Nepali" +msgstr "nepalski" + +msgid "Dutch" +msgstr "holenderski" + +msgid "Norwegian Nynorsk" +msgstr "norweski (nynorsk)" + +msgid "Ossetic" +msgstr "osetyjski" + +msgid "Punjabi" +msgstr "pendżabski" + +msgid "Polish" +msgstr "polski" + +msgid "Portuguese" +msgstr "portugalski" + +msgid "Brazilian Portuguese" +msgstr "portugalski brazylijski" + +msgid "Romanian" +msgstr "rumuński" + +msgid "Russian" +msgstr "rosyjski" + +msgid "Slovak" +msgstr "słowacki" + +msgid "Slovenian" +msgstr "słoweński" + +msgid "Albanian" +msgstr "albański" + +msgid "Serbian" +msgstr "serbski" + +msgid "Serbian Latin" +msgstr "serbski (łaciński)" + +msgid "Swedish" +msgstr "szwedzki" + +msgid "Swahili" +msgstr "suahili" + +msgid "Tamil" +msgstr "tamilski" + +msgid "Telugu" +msgstr "telugu" + +msgid "Tajik" +msgstr "tadżycki" + +msgid "Thai" +msgstr "tajski" + +msgid "Turkmen" +msgstr "turkmeński" + +msgid "Turkish" +msgstr "turecki" + +msgid "Tatar" +msgstr "tatarski" + +msgid "Udmurt" +msgstr "udmurcki" + +msgid "Uyghur" +msgstr "ujgurski" + +msgid "Ukrainian" +msgstr "ukraiński" + +msgid "Urdu" +msgstr "urdu" + +msgid "Uzbek" +msgstr "uzbecki" + +msgid "Vietnamese" +msgstr "wietnamski" + +msgid "Simplified Chinese" +msgstr "chiński uproszczony" + +msgid "Traditional Chinese" +msgstr "chiński tradycyjny" + +msgid "Messages" +msgstr "Wiadomości" + +msgid "Site Maps" +msgstr "Mapy stron" + +msgid "Static Files" +msgstr "Pliki statyczne" + +msgid "Syndication" +msgstr "Syndykacja treści" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Ten numer strony nie jest liczbą całkowitą" + +msgid "That page number is less than 1" +msgstr "Ten numer strony jest mniejszy niż 1" + +msgid "That page contains no results" +msgstr "Ta strona nie zawiera wyników" + +msgid "Enter a valid value." +msgstr "Wpisz poprawną wartość." + +msgid "Enter a valid URL." +msgstr "Wpisz poprawny URL." + +msgid "Enter a valid integer." +msgstr "Wprowadź poprawną liczbę całkowitą." + +msgid "Enter a valid email address." +msgstr "Wprowadź poprawny adres email." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Wpisz poprawny „slug” zawierający litery, cyfry, podkreślenia i myślniki." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Wpisz poprawny „slug” zawierający litery Unicode, cyfry, podkreślenia i " +"myślniki." + +msgid "Enter a valid IPv4 address." +msgstr "Wprowadź poprawny adres IPv4." + +msgid "Enter a valid IPv6 address." +msgstr "Wprowadź poprawny adres IPv6." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Wprowadź poprawny adres IPv4 lub IPv6." + +msgid "Enter only digits separated by commas." +msgstr "Wpisz tylko cyfry oddzielone przecinkami." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Upewnij się, że ta wartość jest %(limit_value)s (jest %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Upewnij się, że ta wartość jest mniejsza lub równa %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Upewnij się, że ta wartość jest większa lub równa %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" +"Upewnij się, że ta wartość jest wielokrotnością wielkości " +"kroku%(limit_value)s." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"Upewnij się, że ta wartość jest wielokrotnością %(limit_value)s, zaczynają " +"od %(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s i tak " +"dalej." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Upewnij się, że ta wartość ma przynajmniej %(limit_value)d znak (obecnie ma " +"%(show_value)d)." +msgstr[1] "" +"Upewnij się, że ta wartość ma przynajmniej %(limit_value)d znaki (obecnie ma " +"%(show_value)d)." +msgstr[2] "" +"Upewnij się, że ta wartość ma przynajmniej %(limit_value)d znaków (obecnie " +"ma %(show_value)d)." +msgstr[3] "" +"Upewnij się, że ta wartość ma przynajmniej %(limit_value)d znaków (obecnie " +"ma %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Upewnij się, że ta wartość ma co najwyżej %(limit_value)d znak (obecnie ma " +"%(show_value)d)." +msgstr[1] "" +"Upewnij się, że ta wartość ma co najwyżej %(limit_value)d znaki (obecnie ma " +"%(show_value)d)." +msgstr[2] "" +"Upewnij się, że ta wartość ma co najwyżej %(limit_value)d znaków (obecnie ma " +"%(show_value)d)." +msgstr[3] "" +"Upewnij się, że ta wartość ma co najwyżej %(limit_value)d znaków (obecnie ma " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Wpisz liczbę." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Upewnij się, że łącznie nie ma więcej niż %(max)s cyfry." +msgstr[1] "Upewnij się, że łącznie nie ma więcej niż %(max)s cyfry." +msgstr[2] "Upewnij się, że łącznie nie ma więcej niż %(max)s cyfr." +msgstr[3] "Upewnij się, że łącznie nie ma więcej niż %(max)s cyfr." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +"Upewnij się, że liczba ma nie więcej niż %(max)s cyfrę po przecinku." +msgstr[1] "" +"Upewnij się, że liczba ma nie więcej niż %(max)s cyfry po przecinku." +msgstr[2] "Upewnij się, że liczba ma nie więcej niż %(max)s cyfr po przecinku." +msgstr[3] "Upewnij się, że liczba ma nie więcej niż %(max)s cyfr po przecinku." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Upewnij się, że liczba ma nie więcej niż %(max)s cyfrę przed przecinkiem." +msgstr[1] "" +"Upewnij się, że liczba ma nie więcej niż %(max)s cyfry przed przecinkiem." +msgstr[2] "" +"Upewnij się, że liczba ma nie więcej niż %(max)s cyfr przed przecinkiem." +msgstr[3] "" +"Upewnij się, że liczba ma nie więcej niż %(max)s cyfr przed przecinkiem." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Rozszerzenie pliku „%(extension)s” jest niedozwolone. Dozwolone rozszerzenia " +"to: %(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Znaki null są niedozwolone." + +msgid "and" +msgstr "i" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s z tymi %(field_labels)s już istnieje." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Ograniczenie \"%(name)s\" zostało naruszone." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Wartość %(value)r nie jest poprawnym wyborem." + +msgid "This field cannot be null." +msgstr "To pole nie może być puste." + +msgid "This field cannot be blank." +msgstr "To pole nie może być puste." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "Istnieje już %(model_name)s z tą wartością pola %(field_label)s." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"Wartość pola %(field_label)s musi być unikatowa dla %(date_field_label)s " +"%(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Pole typu: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "Wartością „%(value)s” musi być True albo False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "Wartością „%(value)s” musi być True, False lub None." + +msgid "Boolean (Either True or False)" +msgstr "Wartość logiczna (True lub False – prawda lub fałsz)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Ciąg znaków (do %(max_length)s znaków)" + +msgid "String (unlimited)" +msgstr "Ciąg znaków (bez limitu)" + +msgid "Comma-separated integers" +msgstr "Liczby całkowite rozdzielone przecinkami" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"Wartość „%(value)s” ma nieprawidłowy format daty. Musi być ona w formacie " +"YYYY-MM-DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"Wartość „%(value)s” ma prawidłowy format (YYYY-MM-DD), ale jest " +"nieprawidłową datą." + +msgid "Date (without time)" +msgstr "Data (bez godziny)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"Wartość „%(value)s” ma nieprawidłowy format. Musi być ona w formacie YYYY-MM-" +"DD HH:MM[:ss[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"Wartość „%(value)s” ma prawidłowy format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]), ale jest nieprawidłową datą/godziną." + +msgid "Date (with time)" +msgstr "Data (z godziną)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "Wartością „%(value)s” musi być liczba dziesiętna." + +msgid "Decimal number" +msgstr "Liczba dziesiętna" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"Wartość „%(value)s” ma błędny format. Poprawny format to [DD] [HH:[MM:]]ss[." +"uuuuuu]." + +msgid "Duration" +msgstr "Czas trwania" + +msgid "Email address" +msgstr "Adres e-mail" + +msgid "File path" +msgstr "Ścieżka do pliku" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "Wartością „%(value)s” musi być liczba zmiennoprzecinkowa." + +msgid "Floating point number" +msgstr "Liczba zmiennoprzecinkowa" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "Wartością „%(value)s” musi być liczba całkowita." + +msgid "Integer" +msgstr "Liczba całkowita" + +msgid "Big (8 byte) integer" +msgstr "Duża liczba całkowita (8 bajtów)" + +msgid "Small integer" +msgstr "Mała liczba całkowita" + +msgid "IPv4 address" +msgstr "adres IPv4" + +msgid "IP address" +msgstr "Adres IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "Wartością „%(value)s” musi być None, True lub False." + +msgid "Boolean (Either True, False or None)" +msgstr "Wartość logiczna (True, False, None – prawda, fałsz lub nic)" + +msgid "Positive big integer" +msgstr "Dodatnia duża liczba całkowita" + +msgid "Positive integer" +msgstr "Dodatnia liczba całkowita" + +msgid "Positive small integer" +msgstr "Dodatnia mała liczba całkowita" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (do %(max_length)s znaków)" + +msgid "Text" +msgstr "Tekst" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"Wartość „%(value)s” ma nieprawidłowy format. Musi być ona w formacie HH:MM[:" +"ss[.uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"Wartość „%(value)s” ma prawidłowy format (HH:MM[:ss[.uuuuuu]]), ale jest " +"nieprawidłową wartością czasu." + +msgid "Time" +msgstr "Czas" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Dane w postaci binarnej" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "Wartość „%(value)s” nie jest poprawnym UUID-em." + +msgid "Universally unique identifier" +msgstr "Uniwersalnie unikalny identyfikator" + +msgid "File" +msgstr "Plik" + +msgid "Image" +msgstr "Plik graficzny" + +msgid "A JSON object" +msgstr "Obiekt JSON" + +msgid "Value must be valid JSON." +msgstr "Wartość musi być poprawnym JSON-em." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(model)s z polem %(field)s o wartości %(value)r nie istnieje." + +msgid "Foreign Key (type determined by related field)" +msgstr "Klucz obcy (typ określony przez pole powiązane)" + +msgid "One-to-one relationship" +msgstr "Powiązanie jeden do jednego" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "powiązanie %(from)s do %(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "powiązania %(from)s do %(to)s" + +msgid "Many-to-many relationship" +msgstr "Powiązanie wiele-do-wielu" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "To pole jest wymagane." + +msgid "Enter a whole number." +msgstr "Wpisz liczbę całkowitą." + +msgid "Enter a valid date." +msgstr "Wpisz poprawną datę." + +msgid "Enter a valid time." +msgstr "Wpisz poprawną godzinę." + +msgid "Enter a valid date/time." +msgstr "Wpisz poprawną datę/godzinę." + +msgid "Enter a valid duration." +msgstr "Wpisz poprawny czas trwania." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Liczba dni musi wynosić między {min_days} a {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Nie wysłano żadnego pliku. Sprawdź typ kodowania formularza." + +msgid "No file was submitted." +msgstr "Żaden plik nie został przesłany." + +msgid "The submitted file is empty." +msgstr "Wysłany plik jest pusty." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Upewnij się, że nazwa pliku ma co najwyżej %(max)d znak (obecnie ma " +"%(length)d)." +msgstr[1] "" +"Upewnij się, że nazwa pliku ma co najwyżej %(max)d znaki (obecnie ma " +"%(length)d)." +msgstr[2] "" +"Upewnij się, że nazwa pliku ma co najwyżej %(max)d znaków (obecnie ma " +"%(length)d)." +msgstr[3] "" +"Upewnij się, że nazwa pliku ma co najwyżej %(max)d znaków (obecnie ma " +"%(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Prześlij plik lub zaznacz by usunąć, ale nie oba na raz." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Prześlij poprawny plik graficzny. Aktualnie przesłany plik nie jest " +"grafiką lub jest uszkodzony." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Wybierz poprawną wartość. %(value)s nie jest żadną z dostępnych opcji." + +msgid "Enter a list of values." +msgstr "Podaj listę wartości." + +msgid "Enter a complete value." +msgstr "Wprowadź kompletną wartość." + +msgid "Enter a valid UUID." +msgstr "Wpisz poprawny UUID." + +msgid "Enter a valid JSON." +msgstr "Wpisz poprawny JSON." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Ukryte pole %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"Brakuje danych ManagementForm lub zostały one naruszone. Brakujące pola: " +"%(field_names)s. Złóż zgłoszenie błędu, jeśli problem się powtarza." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Proszę wysłać co najwyżej %(num)dformularz." +msgstr[1] "Proszę wysłać co najwyżej %(num)d formularze." +msgstr[2] "Proszę wysłać co najwyżej %(num)dformularzy." +msgstr[3] "Proszę wysłać co najwyżej %(num)dformularzy." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Proszę wysłać co najmniej %(num)d formularz." +msgstr[1] "Proszę wysłać co najmniej %(num)dformularze." +msgstr[2] "Proszę wysłać co najmniej %(num)d formularzy." +msgstr[3] "Proszę wysłać co najmniej %(num)d formularzy." + +msgid "Order" +msgstr "Kolejność" + +msgid "Delete" +msgstr "Usuń" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Popraw zduplikowane dane w %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Popraw zduplikowane dane w %(field)s, które muszą być unikalne." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Popraw zduplikowane dane w %(field_name)s, które wymaga unikalności dla " +"%(lookup)s w polu %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Popraw poniższe zduplikowane wartości." + +msgid "The inline value did not match the parent instance." +msgstr "Wartość inline nie pasuje do obiektu rodzica." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Wybierz poprawną wartość. Podana nie jest jednym z dostępnych wyborów." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "„%(pk)s” nie jest poprawną wartością." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s nie mógł zostać zinterpretowany w strefie czasowej " +"%(current_timezone)s; może być niejednoznaczny lub może nie istnieć." + +msgid "Clear" +msgstr "Wyczyść" + +msgid "Currently" +msgstr "Teraz" + +msgid "Change" +msgstr "Zmień" + +msgid "Unknown" +msgstr "Nieznany" + +msgid "Yes" +msgstr "Tak" + +msgid "No" +msgstr "Nie" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "tak,nie,może" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d bajt" +msgstr[1] "%(size)d bajty" +msgstr[2] "%(size)d bajtów" +msgstr[3] "%(size)d bajtów" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "po południu" + +msgid "a.m." +msgstr "rano" + +msgid "PM" +msgstr "po południu" + +msgid "AM" +msgstr "rano" + +msgid "midnight" +msgstr "północ" + +msgid "noon" +msgstr "południe" + +msgid "Monday" +msgstr "Poniedziałek" + +msgid "Tuesday" +msgstr "Wtorek" + +msgid "Wednesday" +msgstr "Środa" + +msgid "Thursday" +msgstr "Czwartek" + +msgid "Friday" +msgstr "Piątek" + +msgid "Saturday" +msgstr "Sobota" + +msgid "Sunday" +msgstr "Niedziela" + +msgid "Mon" +msgstr "Pon" + +msgid "Tue" +msgstr "Wt" + +msgid "Wed" +msgstr "Śr" + +msgid "Thu" +msgstr "Czw" + +msgid "Fri" +msgstr "Pt" + +msgid "Sat" +msgstr "So" + +msgid "Sun" +msgstr "Nd" + +msgid "January" +msgstr "Styczeń" + +msgid "February" +msgstr "Luty" + +msgid "March" +msgstr "Marzec" + +msgid "April" +msgstr "Kwiecień" + +msgid "May" +msgstr "Maj" + +msgid "June" +msgstr "Czerwiec" + +msgid "July" +msgstr "Lipiec" + +msgid "August" +msgstr "Sierpień" + +msgid "September" +msgstr "Wrzesień" + +msgid "October" +msgstr "Październik" + +msgid "November" +msgstr "Listopad" + +msgid "December" +msgstr "Grudzień" + +msgid "jan" +msgstr "sty" + +msgid "feb" +msgstr "lut" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "kwi" + +msgid "may" +msgstr "maj" + +msgid "jun" +msgstr "cze" + +msgid "jul" +msgstr "lip" + +msgid "aug" +msgstr "sie" + +msgid "sep" +msgstr "wrz" + +msgid "oct" +msgstr "paź" + +msgid "nov" +msgstr "lis" + +msgid "dec" +msgstr "gru" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Sty." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Lut." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Mar." + +msgctxt "abbrev. month" +msgid "April" +msgstr "Kwi." + +msgctxt "abbrev. month" +msgid "May" +msgstr "Maj" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Cze." + +msgctxt "abbrev. month" +msgid "July" +msgstr "Lip." + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Sie." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Wrz." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Paź." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Lis." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Gru" + +msgctxt "alt. month" +msgid "January" +msgstr "stycznia" + +msgctxt "alt. month" +msgid "February" +msgstr "lutego" + +msgctxt "alt. month" +msgid "March" +msgstr "marca" + +msgctxt "alt. month" +msgid "April" +msgstr "kwietnia" + +msgctxt "alt. month" +msgid "May" +msgstr "maja" + +msgctxt "alt. month" +msgid "June" +msgstr "czerwca" + +msgctxt "alt. month" +msgid "July" +msgstr "lipca" + +msgctxt "alt. month" +msgid "August" +msgstr "sierpnia" + +msgctxt "alt. month" +msgid "September" +msgstr "września" + +msgctxt "alt. month" +msgid "October" +msgstr "października" + +msgctxt "alt. month" +msgid "November" +msgstr "listopada" + +msgctxt "alt. month" +msgid "December" +msgstr "grudnia" + +msgid "This is not a valid IPv6 address." +msgstr "To nie jest poprawny adres IPv6." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "lub" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d rok" +msgstr[1] "%(num)d lata" +msgstr[2] "%(num)d lat" +msgstr[3] "%(num)d roku" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d miesiąc" +msgstr[1] "%(num)d miesiące" +msgstr[2] "%(num)d miesięcy" +msgstr[3] "%(num)d miesiąca" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d tydzień" +msgstr[1] "%(num)d tygodnie" +msgstr[2] "%(num)d tygodni" +msgstr[3] "%(num)d tygodnia" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dzień" +msgstr[1] "%(num)d dni" +msgstr[2] "%(num)d dni" +msgstr[3] "%(num)d dnia" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d godzina" +msgstr[1] "%(num)d godziny" +msgstr[2] "%(num)d godzin" +msgstr[3] "%(num)d godziny" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuta" +msgstr[1] "%(num)d minuty" +msgstr[2] "%(num)d minut" +msgstr[3] "%(num)d minut" + +msgid "Forbidden" +msgstr "Dostęp zabroniony" + +msgid "CSRF verification failed. Request aborted." +msgstr "Weryfikacja CSRF nie powiodła się. Żądanie zostało przerwane." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Widzisz tę wiadomość, ponieważ ta witryna HTTPS wymaga, aby przeglądarka " +"wysłała „nagłówek Referer”, a żaden nie został wysłany. Nagłówek ten jest " +"wymagany ze względów bezpieczeństwa, aby upewnić się, że twoja przeglądarka " +"nie została przechwycona przez osoby trzecie." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Jeżeli nagłówki „Referer” w Twojej przeglądarce są wyłączone, to proszę " +"włącz je ponownie. Przynajmniej dla tej strony, połączeń HTTPS lub zapytań " +"typu „same-origin”." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Jeśli używasz taga lub " +"umieszczasz nagłówek „Referrer-Policy: no-referrer”, prosimy je usunąć. " +"Ochrona przed atakami CSRF wymaga nagłówka „Referer”, aby wykonać ścisłe " +"sprawdzenie referera HTTP. Jeśli zależy ci na prywatności, użyj alternatyw " +"takich jak dla linków do stron osób trzecich." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Widzisz tą wiadomość, ponieważ ta witryna wymaga ciasteczka CSRF do " +"przesyłania formularza. Ciasteczko to jest wymagane ze względów " +"bezpieczeństwa, aby upewnić się, że Twoja przeglądarka nie została " +"przechwycona przez osoby trzecie." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Jeżeli ciasteczka w Twojej przeglądarce są wyłączone, to proszę włącz je " +"ponownie. Przynajmniej dla tej strony lub żądań typu „same-origin”." + +msgid "More information is available with DEBUG=True." +msgstr "Więcej informacji jest dostępnych po ustawieniu DEBUG=True." + +msgid "No year specified" +msgstr "Nie określono roku" + +msgid "Date out of range" +msgstr "Data poza zakresem" + +msgid "No month specified" +msgstr "Nie określono miesiąca" + +msgid "No day specified" +msgstr "Nie określono dnia" + +msgid "No week specified" +msgstr "Nie określono tygodnia" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "%(verbose_name_plural)s nie są dostępne" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Wyświetlanie %(verbose_name_plural)s z datą przyszłą jest niedostępne, gdyż " +"atrybut '%(class_name)s.allow_future' ma wartość 'False'." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" +"Ciąg znaków „%(datestr)s” jest niezgodny z podanym formatem daty „%(format)s”" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Nie znaleziono %(verbose_name)s spełniających wybrane kryteria" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" +"Podanego numeru strony nie można przekształcić na liczbę całkowitą, nie " +"przyjął on również wartości „last” oznaczającej ostatnią stronę z dostępnego " +"zakresu." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Nieprawidłowy numer strony (%(page_number)s): %(message)s " + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" +"Lista nie zawiera żadnych elementów, a atrybut „%(class_name)s.allow_empty” " +"ma wartość False." + +msgid "Directory indexes are not allowed here." +msgstr "Wyświetlanie zawartości katalogu jest tu niedozwolone." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "„%(path)s” nie istnieje" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Zawartość %(directory)s " + +msgid "The install worked successfully! Congratulations!" +msgstr "Instalacja przebiegła pomyślnie! Gratulacje!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Zobacz informacje o wydaniu dla Django " +"%(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Widzisz tę stronę, ponieważ w swoim pliku ustawień masz DEBUG=True i nie skonfigurowałeś " +"żadnych URL-i." + +msgid "Django Documentation" +msgstr "Dokumentacja Django" + +msgid "Topics, references, & how-to’s" +msgstr "Przewodniki tematyczne, podręczniki i przewodniki „jak to zrobić”" + +msgid "Tutorial: A Polling App" +msgstr "Samouczek: Aplikacja ankietowa" + +msgid "Get started with Django" +msgstr "Pierwsze kroki z Django" + +msgid "Django Community" +msgstr "Społeczność Django" + +msgid "Connect, get help, or contribute" +msgstr "Nawiąż kontakt, uzyskaj pomoc lub wnieś swój wkład" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pl/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pl/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pl/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pl/formats.py new file mode 100644 index 0000000..2ad1bfe --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pl/formats.py @@ -0,0 +1,30 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j E Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = "j E Y H:i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j E" +SHORT_DATE_FORMAT = "d-m-Y" +SHORT_DATETIME_FORMAT = "d-m-Y H:i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d.%m.%Y", # '25.10.2006' + "%d.%m.%y", # '25.10.06' + "%y-%m-%d", # '06-10-25' + # "%d. %B %Y", # '25. października 2006' + # "%d. %b. %Y", # '25. paź. 2006' +] +DATETIME_INPUT_FORMATS = [ + "%d.%m.%Y %H:%M:%S", # '25.10.2006 14:30:59' + "%d.%m.%Y %H:%M:%S.%f", # '25.10.2006 14:30:59.000200' + "%d.%m.%Y %H:%M", # '25.10.2006 14:30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = " " +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2842e75 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pt/LC_MESSAGES/django.po new file mode 100644 index 0000000..311c21c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pt/LC_MESSAGES/django.po @@ -0,0 +1,1254 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Raúl Pedro Fernandes Santos, 2014 +# Bruno Miguel Custódio , 2012 +# Claudio Fernandes , 2015 +# Jannis Leidel , 2011 +# José Durães , 2014 +# jorgecarleitao , 2014-2015 +# Nuno Mariz , 2011-2013,2015-2018 +# Paulo Köch , 2011 +# Raúl Pedro Fernandes Santos, 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Portuguese (http://www.transifex.com/django/django/language/" +"pt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Africâner" + +msgid "Arabic" +msgstr "Árabe" + +msgid "Asturian" +msgstr "Asturiano" + +msgid "Azerbaijani" +msgstr "Azerbaijano" + +msgid "Bulgarian" +msgstr "Búlgaro" + +msgid "Belarusian" +msgstr "Bielorusso" + +msgid "Bengali" +msgstr "Bengalês" + +msgid "Breton" +msgstr "Bretão" + +msgid "Bosnian" +msgstr "Bósnio" + +msgid "Catalan" +msgstr "Catalão" + +msgid "Czech" +msgstr "Checo" + +msgid "Welsh" +msgstr "Galês" + +msgid "Danish" +msgstr "Dinamarquês" + +msgid "German" +msgstr "Alemão" + +msgid "Lower Sorbian" +msgstr "Sorbedo inferior" + +msgid "Greek" +msgstr "Grego" + +msgid "English" +msgstr "Inglês" + +msgid "Australian English" +msgstr "Inglês da Austrália" + +msgid "British English" +msgstr "Inglês Britânico" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Espanhol" + +msgid "Argentinian Spanish" +msgstr "Espanhol Argentino" + +msgid "Colombian Spanish" +msgstr "Espanhol Colombiano" + +msgid "Mexican Spanish" +msgstr "Espanhol mexicano" + +msgid "Nicaraguan Spanish" +msgstr "Nicarágua Espanhol" + +msgid "Venezuelan Spanish" +msgstr "Espanhol Venezuelano" + +msgid "Estonian" +msgstr "Estónio" + +msgid "Basque" +msgstr "Basco" + +msgid "Persian" +msgstr "Persa" + +msgid "Finnish" +msgstr "Filandês" + +msgid "French" +msgstr "Francês" + +msgid "Frisian" +msgstr "Frisão" + +msgid "Irish" +msgstr "Irlandês" + +msgid "Scottish Gaelic" +msgstr "Escocês Gaélico" + +msgid "Galician" +msgstr "Galaciano" + +msgid "Hebrew" +msgstr "Hebraico" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Croata" + +msgid "Upper Sorbian" +msgstr "Sorbedo superior" + +msgid "Hungarian" +msgstr "Húngaro" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "Interlíngua" + +msgid "Indonesian" +msgstr "Indonésio" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Islandês" + +msgid "Italian" +msgstr "Italiano" + +msgid "Japanese" +msgstr "Japonês" + +msgid "Georgian" +msgstr "Georgiano" + +msgid "Kabyle" +msgstr "Kabyle" + +msgid "Kazakh" +msgstr "Cazaque" + +msgid "Khmer" +msgstr "Khmer" + +msgid "Kannada" +msgstr "Canarês" + +msgid "Korean" +msgstr "Coreano" + +msgid "Luxembourgish" +msgstr "Luxemburguês" + +msgid "Lithuanian" +msgstr "Lituano" + +msgid "Latvian" +msgstr "Letão" + +msgid "Macedonian" +msgstr "Macedónio" + +msgid "Malayalam" +msgstr "Malaiala" + +msgid "Mongolian" +msgstr "Mongol" + +msgid "Marathi" +msgstr "Marathi" + +msgid "Burmese" +msgstr "Birmanês" + +msgid "Norwegian Bokmål" +msgstr "Norueguês Bokmål" + +msgid "Nepali" +msgstr "Nepali" + +msgid "Dutch" +msgstr "Holandês" + +msgid "Norwegian Nynorsk" +msgstr "Norueguês (Nynors)" + +msgid "Ossetic" +msgstr "Ossetic" + +msgid "Punjabi" +msgstr "Panjabi" + +msgid "Polish" +msgstr "Polaco" + +msgid "Portuguese" +msgstr "Português" + +msgid "Brazilian Portuguese" +msgstr "Português Brasileiro" + +msgid "Romanian" +msgstr "Romeno" + +msgid "Russian" +msgstr "Russo" + +msgid "Slovak" +msgstr "Eslovaco" + +msgid "Slovenian" +msgstr "Esloveno" + +msgid "Albanian" +msgstr "Albanês" + +msgid "Serbian" +msgstr "Sérvio" + +msgid "Serbian Latin" +msgstr "Sérvio Latim" + +msgid "Swedish" +msgstr "Sueco" + +msgid "Swahili" +msgstr "Suaíli" + +msgid "Tamil" +msgstr "Tamil" + +msgid "Telugu" +msgstr "Telugu" + +msgid "Thai" +msgstr "Thai" + +msgid "Turkish" +msgstr "Turco" + +msgid "Tatar" +msgstr "Tatar" + +msgid "Udmurt" +msgstr "Udmurte" + +msgid "Ukrainian" +msgstr "Ucraniano" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "Vietnamita" + +msgid "Simplified Chinese" +msgstr "Chinês Simplificado" + +msgid "Traditional Chinese" +msgstr "Chinês Tradicional" + +msgid "Messages" +msgstr "Mensagens" + +msgid "Site Maps" +msgstr "Mapas do Site" + +msgid "Static Files" +msgstr "Ficheiros Estáticos" + +msgid "Syndication" +msgstr "Syndication" + +msgid "That page number is not an integer" +msgstr "Esse número de página não é um número inteiro" + +msgid "That page number is less than 1" +msgstr "Esse número de página é inferior a 1" + +msgid "That page contains no results" +msgstr "Essa página não contém resultados" + +msgid "Enter a valid value." +msgstr "Introduza um valor válido." + +msgid "Enter a valid URL." +msgstr "Introduza um URL válido." + +msgid "Enter a valid integer." +msgstr "Introduza um número inteiro válido." + +msgid "Enter a valid email address." +msgstr "Introduza um endereço de e-mail válido." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Introduza um endereço IPv4 válido." + +msgid "Enter a valid IPv6 address." +msgstr "Insira um endereço IPv6 válido." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Digite um endereço válido IPv4 ou IPv6." + +msgid "Enter only digits separated by commas." +msgstr "Introduza apenas números separados por vírgulas." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Garanta que este valor seja %(limit_value)s (tem %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Garanta que este valor seja menor ou igual a %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Garanta que este valor seja maior ou igual a %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Garanta que este valor tenha pelo menos %(limit_value)d caractere (tem " +"%(show_value)d)." +msgstr[1] "" +"Garanta que este valor tenha pelo menos %(limit_value)d caracteres (tem " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Garanta que este valor tenha no máximo %(limit_value)d caractere (tem " +"%(show_value)d)." +msgstr[1] "" +"Garanta que este valor tenha no máximo %(limit_value)d caracteres (tem " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Introduza um número." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Garanta que não tem mais de %(max)s dígito no total." +msgstr[1] "Garanta que não tem mais de %(max)s dígitos no total." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Garanta que não tem mais %(max)s casa decimal." +msgstr[1] "Garanta que não tem mais %(max)s casas decimais." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "Garanta que não tem mais de %(max)s dígito antes do ponto decimal." +msgstr[1] "Garanta que não tem mais de %(max)s dígitos antes do ponto decimal." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "Não são permitidos caracteres nulos." + +msgid "and" +msgstr "e" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s com este %(field_labels)s já existe." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "O valor %(value)r não é uma escolha válida." + +msgid "This field cannot be null." +msgstr "Este campo não pode ser nulo." + +msgid "This field cannot be blank." +msgstr "Este campo não pode ser vazio." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s com este %(field_label)s já existe." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s tem de ser único para %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Campo do tipo: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "Boolean (Pode ser True ou False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "String (até %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "Inteiros separados por virgula" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "Data (sem hora)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Data (com hora)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Número décimal" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "Duração" + +msgid "Email address" +msgstr "Endereço de e-mail" + +msgid "File path" +msgstr "Caminho do ficheiro" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "Número em vírgula flutuante" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "Inteiro" + +msgid "Big (8 byte) integer" +msgstr "Inteiro grande (8 byte)" + +msgid "IPv4 address" +msgstr "Endereço IPv4" + +msgid "IP address" +msgstr "Endereço IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "Boolean (Pode ser True, False ou None)" + +msgid "Positive integer" +msgstr "Inteiro positivo" + +msgid "Positive small integer" +msgstr "Pequeno número inteiro positivo" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (até %(max_length)s)" + +msgid "Small integer" +msgstr "Inteiro pequeno" + +msgid "Text" +msgstr "Texto" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Hora" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Dados binários simples" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "Ficheiro" + +msgid "Image" +msgstr "Imagem" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "A instância de %(model)s com %(field)s %(value)r não existe." + +msgid "Foreign Key (type determined by related field)" +msgstr "Chave Estrangeira (tipo determinado pelo campo relacionado)" + +msgid "One-to-one relationship" +msgstr "Relação de um-para-um" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "Relação de %(from)s-%(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "Relações de %(from)s-%(to)s" + +msgid "Many-to-many relationship" +msgstr "Relação de muitos-para-muitos" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Este campo é obrigatório." + +msgid "Enter a whole number." +msgstr "Introduza um número inteiro." + +msgid "Enter a valid date." +msgstr "Introduza uma data válida." + +msgid "Enter a valid time." +msgstr "Introduza uma hora válida." + +msgid "Enter a valid date/time." +msgstr "Introduza uma data/hora válida." + +msgid "Enter a valid duration." +msgstr "Introduza uma duração válida." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "O número de dias deve ser entre {min_days} e {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" +"Nenhum ficheiro foi submetido. Verifique o tipo de codificação do formulário." + +msgid "No file was submitted." +msgstr "Nenhum ficheiro submetido." + +msgid "The submitted file is empty." +msgstr "O ficheiro submetido encontra-se vazio." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Garanta que o nome deste ficheiro tenha no máximo %(max)d caractere (tem " +"%(length)d)." +msgstr[1] "" +"Garanta que o nome deste ficheiro tenha no máximo %(max)d caracteres (tem " +"%(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Por favor, submeta um ficheiro ou remova a seleção da caixa, não ambos." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Introduza uma imagem válida. O ficheiro que introduziu ou não é uma imagem " +"ou está corrompido." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Selecione uma opção válida. %(value)s não se encontra nas opções disponíveis." + +msgid "Enter a list of values." +msgstr "Introduza uma lista de valores." + +msgid "Enter a complete value." +msgstr "Introduza um valor completo." + +msgid "Enter a valid UUID." +msgstr "Introduza um UUID válido." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Campo oculto %(name)s) %(error)s" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "Os dados do ManagementForm estão em falta ou foram adulterados" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "Por favor submeta %d ou menos formulários." +msgstr[1] "Por favor submeta %d ou menos formulários." + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "Por favor submeta %d ou mais formulários." +msgstr[1] "Por favor submeta %d ou mais formulários." + +msgid "Order" +msgstr "Ordem" + +msgid "Delete" +msgstr "Remover" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Por favor corrija os dados duplicados em %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Por favor corrija os dados duplicados em %(field)s, que deverá ser único." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Por favor corrija os dados duplicados em %(field_name)s que deverá ser único " +"para o %(lookup)s em %(date_field)s.\"" + +msgid "Please correct the duplicate values below." +msgstr "Por favor corrija os valores duplicados abaixo." + +msgid "The inline value did not match the parent instance." +msgstr "O valor em linha não corresponde à instância pai." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Selecione uma opção válida. Esse valor não se encontra opções disponíveis." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Limpar" + +msgid "Currently" +msgstr "Atualmente" + +msgid "Change" +msgstr "Modificar" + +msgid "Unknown" +msgstr "Desconhecido" + +msgid "Yes" +msgstr "Sim" + +msgid "No" +msgstr "Não" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "sim,não,talvez" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d byte" +msgstr[1] "%(size)d bytes" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "meia-noite" + +msgid "noon" +msgstr "meio-dia" + +msgid "Monday" +msgstr "Segunda-feira" + +msgid "Tuesday" +msgstr "Terça-feira" + +msgid "Wednesday" +msgstr "Quarta-feira" + +msgid "Thursday" +msgstr "Quinta-feira" + +msgid "Friday" +msgstr "Sexta-feira" + +msgid "Saturday" +msgstr "Sábado" + +msgid "Sunday" +msgstr "Domingo" + +msgid "Mon" +msgstr "Seg" + +msgid "Tue" +msgstr "Ter" + +msgid "Wed" +msgstr "Qua" + +msgid "Thu" +msgstr "Qui" + +msgid "Fri" +msgstr "Sex" + +msgid "Sat" +msgstr "Sáb" + +msgid "Sun" +msgstr "Dom" + +msgid "January" +msgstr "Janeiro" + +msgid "February" +msgstr "Fevereiro" + +msgid "March" +msgstr "Março" + +msgid "April" +msgstr "Abril" + +msgid "May" +msgstr "Maio" + +msgid "June" +msgstr "Junho" + +msgid "July" +msgstr "Julho" + +msgid "August" +msgstr "Agosto" + +msgid "September" +msgstr "Setembro" + +msgid "October" +msgstr "Outubro" + +msgid "November" +msgstr "Novembro" + +msgid "December" +msgstr "Dezembro" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "fev" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "abr" + +msgid "may" +msgstr "mai" + +msgid "jun" +msgstr "jun" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "ago" + +msgid "sep" +msgstr "set" + +msgid "oct" +msgstr "out" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dez" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Fev." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Março" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Abril" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Maio" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Jun." + +msgctxt "abbrev. month" +msgid "July" +msgstr "Jul." + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Ago." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Set." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Out." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dez." + +msgctxt "alt. month" +msgid "January" +msgstr "Janeiro" + +msgctxt "alt. month" +msgid "February" +msgstr "Fevereiro" + +msgctxt "alt. month" +msgid "March" +msgstr "Março" + +msgctxt "alt. month" +msgid "April" +msgstr "Abril" + +msgctxt "alt. month" +msgid "May" +msgstr "Maio" + +msgctxt "alt. month" +msgid "June" +msgstr "Junho" + +msgctxt "alt. month" +msgid "July" +msgstr "Julho" + +msgctxt "alt. month" +msgid "August" +msgstr "Agosto" + +msgctxt "alt. month" +msgid "September" +msgstr "Setembro" + +msgctxt "alt. month" +msgid "October" +msgstr "Outubro" + +msgctxt "alt. month" +msgid "November" +msgstr "Novembro" + +msgctxt "alt. month" +msgid "December" +msgstr "Dezembro" + +msgid "This is not a valid IPv6 address." +msgstr "Este não é um endereço IPv6 válido." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "ou" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d ano" +msgstr[1] "%d anos" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d mês" +msgstr[1] "%d meses" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d semana" +msgstr[1] "%d semanas" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d dia" +msgstr[1] "%d dias" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d hora" +msgstr[1] "%d horas" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d minuto" +msgstr[1] "%d minutos" + +msgid "0 minutes" +msgstr "0 minutos" + +msgid "Forbidden" +msgstr "Proibido" + +msgid "CSRF verification failed. Request aborted." +msgstr "A verificação de CSRF falhou. Pedido abortado." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Está a ver esta mensagem porque este site requer um cookie CSRF quando " +"submete formulários. Este cookie é requirido por razões de segurança, para " +"garantir que o seu browser não está a ser \"raptado\" por terceiros." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "Está disponível mais informação com DEBUG=True." + +msgid "No year specified" +msgstr "Nenhum ano especificado" + +msgid "Date out of range" +msgstr "Data fora do alcance" + +msgid "No month specified" +msgstr "Nenhum mês especificado" + +msgid "No day specified" +msgstr "Nenhum dia especificado" + +msgid "No week specified" +msgstr "Nenhuma semana especificado" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Nenhum %(verbose_name_plural)s disponível" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"%(verbose_name_plural)s futuros indisponíveis porque %(class_name)s." +"allow_future é False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Nenhum %(verbose_name)s de acordo com a procura." + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Página inválida (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Índices de diretório não são permitidas aqui." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Índice de %(directory)s" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "Django: the Web framework for perfectionists with deadlines." + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Visualizar notas de lançamento do Django " +"%(version)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "A instalação funcionou com sucesso! Parabéns!" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" +"Está a visualizar esta página porque tem DEBUG=True no seu ficheiro settings do Django e não " +"configurou nenhum URLs." + +msgid "Django Documentation" +msgstr "Documentação do Django" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "Tutorial: A Polling App" + +msgid "Get started with Django" +msgstr "Comece com o Django" + +msgid "Django Community" +msgstr "Comunidade Django" + +msgid "Connect, get help, or contribute" +msgstr "Conecte-se, obtenha ajuda ou contribua" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pt/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pt/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pt/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pt/formats.py new file mode 100644 index 0000000..bb4b3f5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pt/formats.py @@ -0,0 +1,39 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = r"j \d\e F \d\e Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = r"j \d\e F \d\e Y à\s H:i" +YEAR_MONTH_FORMAT = r"F \d\e Y" +MONTH_DAY_FORMAT = r"j \d\e F" +SHORT_DATE_FORMAT = "d/m/Y" +SHORT_DATETIME_FORMAT = "d/m/Y H:i" +FIRST_DAY_OF_WEEK = 0 # Sunday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# Kept ISO formats as they are in first position +DATE_INPUT_FORMATS = [ + "%Y-%m-%d", # '2006-10-25' + "%d/%m/%Y", # '25/10/2006' + "%d/%m/%y", # '25/10/06' + # "%d de %b de %Y", # '25 de Out de 2006' + # "%d de %b, %Y", # '25 Out, 2006' + # "%d de %B de %Y", # '25 de Outubro de 2006' + # "%d de %B, %Y", # '25 de Outubro, 2006' +] +DATETIME_INPUT_FORMATS = [ + "%Y-%m-%d %H:%M:%S", # '2006-10-25 14:30:59' + "%Y-%m-%d %H:%M:%S.%f", # '2006-10-25 14:30:59.000200' + "%Y-%m-%d %H:%M", # '2006-10-25 14:30' + "%d/%m/%Y %H:%M:%S", # '25/10/2006 14:30:59' + "%d/%m/%Y %H:%M:%S.%f", # '25/10/2006 14:30:59.000200' + "%d/%m/%Y %H:%M", # '25/10/2006 14:30' + "%d/%m/%y %H:%M:%S", # '25/10/06 14:30:59' + "%d/%m/%y %H:%M:%S.%f", # '25/10/06 14:30:59.000200' + "%d/%m/%y %H:%M", # '25/10/06 14:30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pt_BR/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pt_BR/LC_MESSAGES/django.mo new file mode 100644 index 0000000..66c5ac7 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pt_BR/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pt_BR/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pt_BR/LC_MESSAGES/django.po new file mode 100644 index 0000000..9e08d6b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pt_BR/LC_MESSAGES/django.po @@ -0,0 +1,1394 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Allisson Azevedo , 2014 +# Amanda Savluchinske , 2019 +# amcorreia , 2018 +# andrewsmedina , 2014-2015 +# Arthur Silva , 2017 +# bruno.devpod , 2014 +# Camilo B. Moreira , 2017 +# Carlos C. Leite , 2020 +# Carlos C. Leite , 2016,2019 +# Filipe Cifali , 2016 +# Claudio Rogerio Carvalho Filho , 2020 +# dudanogueira , 2012 +# dudanogueira , 2019 +# Elyézer Rezende , 2013 +# Fábio C. Barrionuevo da Luz , 2014-2015 +# Felipe Rodrigues , 2016 +# Filipe Cifali , 2019 +# Gladson , 2013 +# fa9e10542e458baef0599ae856e43651_13d2225, 2011-2014 +# Guilherme , 2022 +# Heron Fonsaca, 2022 +# Igor Cavalcante , 2017 +# Jannis Leidel , 2011 +# Jonas Rodrigues, 2023 +# Leonardo Gregianin, 2023 +# Lucas Infante , 2015 +# Luiz Boaretto , 2017 +# Marssal Jr. , 2022 +# Marcelo Moro Brondani , 2018 +# Mariusz Felisiak , 2021 +# Rafael Fontenelle , 2021-2022 +# Samuel Nogueira Bacelar , 2020 +# Sandro , 2011 +# Sergio Garcia , 2015 +# Tânia Andrea , 2017 +# Wiliam Souza , 2015 +# Francisco Petry Rauber , 2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Leonardo Gregianin, 2023\n" +"Language-Team: Portuguese (Brazil) (http://app.transifex.com/django/django/" +"language/pt_BR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt_BR\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Afrikaans" +msgstr "Africânder" + +msgid "Arabic" +msgstr "Árabe" + +msgid "Algerian Arabic" +msgstr "Árabe Argelino" + +msgid "Asturian" +msgstr "Asturiano" + +msgid "Azerbaijani" +msgstr "Azerbaijão" + +msgid "Bulgarian" +msgstr "Búlgaro" + +msgid "Belarusian" +msgstr "Bielorrussa" + +msgid "Bengali" +msgstr "Bengali" + +msgid "Breton" +msgstr "Bretão" + +msgid "Bosnian" +msgstr "Bósnio" + +msgid "Catalan" +msgstr "Catalão" + +msgid "Central Kurdish (Sorani)" +msgstr "Curdo Central (Sorâni)" + +msgid "Czech" +msgstr "Tcheco" + +msgid "Welsh" +msgstr "Galês" + +msgid "Danish" +msgstr "Dinamarquês" + +msgid "German" +msgstr "Alemão" + +msgid "Lower Sorbian" +msgstr "Sorábio Baixo" + +msgid "Greek" +msgstr "Grego" + +msgid "English" +msgstr "Inglês" + +msgid "Australian English" +msgstr "Inglês Australiano" + +msgid "British English" +msgstr "Inglês Britânico" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Espanhol" + +msgid "Argentinian Spanish" +msgstr "Espanhol Argentino" + +msgid "Colombian Spanish" +msgstr "Espanhol Colombiano" + +msgid "Mexican Spanish" +msgstr "Espanhol Mexicano" + +msgid "Nicaraguan Spanish" +msgstr "Espanhol Nicaraguense" + +msgid "Venezuelan Spanish" +msgstr "Espanhol Venuzuelano" + +msgid "Estonian" +msgstr "Estoniano" + +msgid "Basque" +msgstr "Basco" + +msgid "Persian" +msgstr "Persa" + +msgid "Finnish" +msgstr "Finlandês" + +msgid "French" +msgstr "Francês" + +msgid "Frisian" +msgstr "Frísia" + +msgid "Irish" +msgstr "Irlandês" + +msgid "Scottish Gaelic" +msgstr "Gaélico Escocês" + +msgid "Galician" +msgstr "Galiciano" + +msgid "Hebrew" +msgstr "Hebraico" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Croata" + +msgid "Upper Sorbian" +msgstr "Sorábio Alto" + +msgid "Hungarian" +msgstr "Húngaro" + +msgid "Armenian" +msgstr "Armênio" + +msgid "Interlingua" +msgstr "Interlíngua" + +msgid "Indonesian" +msgstr "Indonésio" + +msgid "Igbo" +msgstr "Igbo" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Islandês" + +msgid "Italian" +msgstr "Italiano" + +msgid "Japanese" +msgstr "Japonês" + +msgid "Georgian" +msgstr "Georgiano" + +msgid "Kabyle" +msgstr "Cabila" + +msgid "Kazakh" +msgstr "Cazaque" + +msgid "Khmer" +msgstr "Khmer" + +msgid "Kannada" +msgstr "Canarês" + +msgid "Korean" +msgstr "Coreano" + +msgid "Kyrgyz" +msgstr "Quirguiz" + +msgid "Luxembourgish" +msgstr "Luxemburguês" + +msgid "Lithuanian" +msgstr "Lituano" + +msgid "Latvian" +msgstr "Letão" + +msgid "Macedonian" +msgstr "Macedônio" + +msgid "Malayalam" +msgstr "Malaiala" + +msgid "Mongolian" +msgstr "Mongol" + +msgid "Marathi" +msgstr "Marathi" + +msgid "Malay" +msgstr "Malaia" + +msgid "Burmese" +msgstr "Birmanês" + +msgid "Norwegian Bokmål" +msgstr "Dano-norueguês" + +msgid "Nepali" +msgstr "Nepalês" + +msgid "Dutch" +msgstr "Neerlandês" + +msgid "Norwegian Nynorsk" +msgstr "Novo Norueguês" + +msgid "Ossetic" +msgstr "Osseto" + +msgid "Punjabi" +msgstr "Punjabi" + +msgid "Polish" +msgstr "Polonês" + +msgid "Portuguese" +msgstr "Português" + +msgid "Brazilian Portuguese" +msgstr "Português Brasileiro" + +msgid "Romanian" +msgstr "Romeno" + +msgid "Russian" +msgstr "Russo" + +msgid "Slovak" +msgstr "Eslovaco" + +msgid "Slovenian" +msgstr "Esloveno" + +msgid "Albanian" +msgstr "Albanesa" + +msgid "Serbian" +msgstr "Sérvio" + +msgid "Serbian Latin" +msgstr "Sérvio Latino" + +msgid "Swedish" +msgstr "Sueco" + +msgid "Swahili" +msgstr "Suaíli" + +msgid "Tamil" +msgstr "Tâmil" + +msgid "Telugu" +msgstr "Telugu" + +msgid "Tajik" +msgstr "Tadjique" + +msgid "Thai" +msgstr "Tailandês" + +msgid "Turkmen" +msgstr "Turcomano" + +msgid "Turkish" +msgstr "Turco" + +msgid "Tatar" +msgstr "Tatar" + +msgid "Udmurt" +msgstr "Udmurt" + +msgid "Uyghur" +msgstr "Uigur" + +msgid "Ukrainian" +msgstr "Ucraniano" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "Uzbeque" + +msgid "Vietnamese" +msgstr "Vietnamita" + +msgid "Simplified Chinese" +msgstr "Chinês Simplificado" + +msgid "Traditional Chinese" +msgstr "Chinês Tradicional" + +msgid "Messages" +msgstr "Mensagens" + +msgid "Site Maps" +msgstr "Site Maps" + +msgid "Static Files" +msgstr "Arquivos Estáticos" + +msgid "Syndication" +msgstr "Syndication" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Esse número de página não é um número inteiro" + +msgid "That page number is less than 1" +msgstr "Esse número de página é menor que 1" + +msgid "That page contains no results" +msgstr "Essa página não contém resultados" + +msgid "Enter a valid value." +msgstr "Informe um valor válido." + +msgid "Enter a valid URL." +msgstr "Informe uma URL válida." + +msgid "Enter a valid integer." +msgstr "Insira um número inteiro válido." + +msgid "Enter a valid email address." +msgstr "Informe um endereço de email válido." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Informe um “slug” válido tendo letras, números, \"underscores\" e hífens." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Informe um “slug” válido tendo letras em Unicode, números, \"underscores\" e " +"hífens." + +msgid "Enter a valid IPv4 address." +msgstr "Insira um endereço IPv4 válido." + +msgid "Enter a valid IPv6 address." +msgstr "Insira um endereço IPv6 válido." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Insira um endereço IPv4 ou IPv6 válido." + +msgid "Enter only digits separated by commas." +msgstr "Insira apenas dígitos separados por vírgulas." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Certifique-se de que o valor é %(limit_value)s (ele é %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Certifique-se que este valor seja menor ou igual a %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Certifique-se que este valor seja maior ou igual a %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" +"Certifique-se que este valor seja múltiplo do tamanho do passo " +"%(limit_value)s." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"Certifique-se que este valor seja múltiplo do tamanho do passo " +"%(limit_value)s, começando por %(offset)s, por exemplo %(offset)s, " +"%(valid_value1)s, %(valid_value2)s, e assim por diante." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Certifique-se de que o valor tenha no mínimo %(limit_value)d caractere (ele " +"possui %(show_value)d)." +msgstr[1] "" +"Certifique-se de que o valor tenha no mínimo %(limit_value)d caracteres (ele " +"possui %(show_value)d)." +msgstr[2] "" +"Certifique-se de que o valor tenha no mínimo %(limit_value)d caracteres (ele " +"possui %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Certifique-se de que o valor tenha no máximo %(limit_value)d caractere (ele " +"possui %(show_value)d)." +msgstr[1] "" +"Certifique-se de que o valor tenha no máximo %(limit_value)d caracteres (ele " +"possui %(show_value)d)." +msgstr[2] "" +"Certifique-se de que o valor tenha no máximo %(limit_value)d caracteres (ele " +"possui %(show_value)d)." + +msgid "Enter a number." +msgstr "Informe um número." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Certifique-se de que não tenha mais de %(max)s dígito no total." +msgstr[1] "Certifique-se de que não tenha mais de %(max)s dígitos no total." +msgstr[2] "Certifique-se de que não tenha mais de %(max)s dígitos no total." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Certifique-se de que não tenha mais de %(max)s casa decimal." +msgstr[1] "Certifique-se de que não tenha mais de %(max)s casas decimais." +msgstr[2] "Certifique-se de que não tenha mais de %(max)s casas decimais." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Certifique-se de que não tenha mais de %(max)s dígito antes do ponto decimal." +msgstr[1] "" +"Certifique-se de que não tenha mais de %(max)s dígitos antes do ponto " +"decimal." +msgstr[2] "" +"Certifique-se de que não tenha mais de %(max)s dígitos antes do ponto " +"decimal." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"A extensão de arquivo “%(extension)s” não é permitida. As extensões válidas " +"são: %(allowed_extensions)s ." + +msgid "Null characters are not allowed." +msgstr "Caracteres nulos não são permitidos." + +msgid "and" +msgstr "e" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s com este %(field_labels)s já existe." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Restrição \"%(name)s\" foi violada." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Valor %(value)r não é uma opção válida." + +msgid "This field cannot be null." +msgstr "Este campo não pode ser nulo." + +msgid "This field cannot be blank." +msgstr "Este campo não pode estar vazio." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s com este %(field_label)s já existe." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s deve ser único para %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Campo do tipo: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "o valor “%(value)s” deve ser True ou False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "o valor “%(value)s” deve ser True, False ou None." + +msgid "Boolean (Either True or False)" +msgstr "Booleano (Verdadeiro ou Falso)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "String (até %(max_length)s)" + +msgid "String (unlimited)" +msgstr "String (ilimitado)" + +msgid "Comma-separated integers" +msgstr "Inteiros separados por vírgula" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"O valor \"%(value)s\" tem um formato de data inválido. Deve ser no formato " +"YYYY-MM-DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"O valor “%(value)s” tem o formato correto (YYYY-MM-DD) mas uma data inválida." + +msgid "Date (without time)" +msgstr "Data (sem hora)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"O valor “%(value)s” tem um formato inválido. Deve estar no formato YYYY-MM-" +"DD HH:MM[:ss[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"O valor “%(value)s” está no formato correto. (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) mas é uma data/hora inválida" + +msgid "Date (with time)" +msgstr "Data (com hora)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "O valor “%(value)s” deve ser um número decimal." + +msgid "Decimal number" +msgstr "Número decimal" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"O valor “%(value)s” está em um formato inválido. Deve ser no formato [DD] " +"[[HH:]MM:]ss[.uuuuuu]." + +msgid "Duration" +msgstr "Duração" + +msgid "Email address" +msgstr "Endereço de e-mail" + +msgid "File path" +msgstr "Caminho do arquivo" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "O valor “%(value)s” deve ser um float." + +msgid "Floating point number" +msgstr "Número de ponto flutuante" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "O valor “%(value)s” deve ser inteiro." + +msgid "Integer" +msgstr "Inteiro" + +msgid "Big (8 byte) integer" +msgstr "Inteiro grande (8 byte)" + +msgid "Small integer" +msgstr "Inteiro curto" + +msgid "IPv4 address" +msgstr "Endereço IPv4" + +msgid "IP address" +msgstr "Endereço IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "O valor “%(value)s” deve ser None, True ou False." + +msgid "Boolean (Either True, False or None)" +msgstr "Booleano (Verdadeiro, Falso ou Nada)" + +msgid "Positive big integer" +msgstr "Inteiro grande positivo" + +msgid "Positive integer" +msgstr "Inteiro positivo" + +msgid "Positive small integer" +msgstr "Inteiro curto positivo" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (até %(max_length)s)" + +msgid "Text" +msgstr "Texto" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"O valor “%(value)s” tem um formato inválido. Deve estar no formato HH:MM[:" +"ss[.uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"O valor “%(value)s” está no formato correto (HH:MM[:ss[.uuuuuu]]) mas é uma " +"hora inválida." + +msgid "Time" +msgstr "Hora" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Dados binários bruto" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "O valor “%(value)s” não é um UUID válido" + +msgid "Universally unique identifier" +msgstr "Identificador único universal" + +msgid "File" +msgstr "Arquivo" + +msgid "Image" +msgstr "Imagem" + +msgid "A JSON object" +msgstr "Um objeto JSON" + +msgid "Value must be valid JSON." +msgstr "O valor deve ser um JSON válido." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "A instância de %(model)s com %(field)s %(value)r não existe." + +msgid "Foreign Key (type determined by related field)" +msgstr "Chave Estrangeira (tipo determinado pelo campo relacionado)" + +msgid "One-to-one relationship" +msgstr "Relacionamento um-para-um" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "Relacionamento %(from)s-%(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "Relacionamentos %(from)s-%(to)s" + +msgid "Many-to-many relationship" +msgstr "Relacionamento muitos-para-muitos" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Este campo é obrigatório." + +msgid "Enter a whole number." +msgstr "Informe um número inteiro." + +msgid "Enter a valid date." +msgstr "Informe uma data válida." + +msgid "Enter a valid time." +msgstr "Informe uma hora válida." + +msgid "Enter a valid date/time." +msgstr "Informe uma data/hora válida." + +msgid "Enter a valid duration." +msgstr "Insira uma duração válida." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "O número de dias deve ser entre {min_days} e {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Nenhum arquivo enviado. Verifique o tipo de codificação do formulário." + +msgid "No file was submitted." +msgstr "Nenhum arquivo foi enviado." + +msgid "The submitted file is empty." +msgstr "O arquivo enviado está vazio." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Certifique-se de que o arquivo tenha no máximo %(max)d caractere (ele possui " +"%(length)d)." +msgstr[1] "" +"Certifique-se de que o arquivo tenha no máximo %(max)d caracteres (ele " +"possui %(length)d)." +msgstr[2] "" +"Certifique-se de que o arquivo tenha no máximo %(max)d caracteres (ele " +"possui %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Por favor, envie um arquivo ou marque o checkbox, mas não ambos." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Envie uma imagem válida. O arquivo enviado não é uma imagem ou está " +"corrompido." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Faça uma escolha válida. %(value)s não é uma das escolhas disponíveis." + +msgid "Enter a list of values." +msgstr "Informe uma lista de valores." + +msgid "Enter a complete value." +msgstr "Insira um valor completo." + +msgid "Enter a valid UUID." +msgstr "Insira um UUID válido." + +msgid "Enter a valid JSON." +msgstr "Insira um JSON válido" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Campo oculto %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"Dados de ManagementForm estão faltando ou foram adulterados. Campos " +"ausentes: %(field_names)s. Você pode precisar enviar um relatório de bug se " +"o problema persistir." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Por favor, envie no máximo %(num)d formulário." +msgstr[1] "Por favor, envie no máximo %(num)d formulários." +msgstr[2] "Por favor, envie no máximo %(num)d formulários." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Por favor, envie ao menos %(num)d formulário." +msgstr[1] "Por favor, envie ao menos %(num)d formulários." +msgstr[2] "Por favor, envie ao menos %(num)d formulários." + +msgid "Order" +msgstr "Ordem" + +msgid "Delete" +msgstr "Remover" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Por favor, corrija o valor duplicado para %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Por favor, corrija o valor duplicado para %(field)s, o qual deve ser único." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Por favor, corrija o dado duplicado para %(field_name)s, o qual deve ser " +"único para %(lookup)s em %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Por favor, corrija os valores duplicados abaixo." + +msgid "The inline value did not match the parent instance." +msgstr "O valor na linha não correspondeu com a instância pai." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Faça uma escolha válida. Sua escolha não é uma das disponíveis." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "“%(pk)s” não é um valor válido." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s não pode ser interpretada dentro da fuso horário " +"%(current_timezone)s; está ambíguo ou não existe." + +msgid "Clear" +msgstr "Limpar" + +msgid "Currently" +msgstr "Atualmente" + +msgid "Change" +msgstr "Modificar" + +msgid "Unknown" +msgstr "Desconhecido" + +msgid "Yes" +msgstr "Sim" + +msgid "No" +msgstr "Não" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "sim,não,talvez" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d byte" +msgstr[1] "%(size)d bytes" +msgstr[2] "%(size)d bytes" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "meia-noite" + +msgid "noon" +msgstr "meio-dia" + +msgid "Monday" +msgstr "Segunda-feira" + +msgid "Tuesday" +msgstr "Terça-feira" + +msgid "Wednesday" +msgstr "Quarta-feira" + +msgid "Thursday" +msgstr "Quinta-feira" + +msgid "Friday" +msgstr "Sexta-feira" + +msgid "Saturday" +msgstr "Sábado" + +msgid "Sunday" +msgstr "Domingo" + +msgid "Mon" +msgstr "Seg" + +msgid "Tue" +msgstr "Ter" + +msgid "Wed" +msgstr "Qua" + +msgid "Thu" +msgstr "Qui" + +msgid "Fri" +msgstr "Sex" + +msgid "Sat" +msgstr "Sab" + +msgid "Sun" +msgstr "Dom" + +msgid "January" +msgstr "Janeiro" + +msgid "February" +msgstr "Fevereiro" + +msgid "March" +msgstr "Março" + +msgid "April" +msgstr "Abril" + +msgid "May" +msgstr "Maio" + +msgid "June" +msgstr "Junho" + +msgid "July" +msgstr "Julho" + +msgid "August" +msgstr "Agosto" + +msgid "September" +msgstr "Setembro" + +msgid "October" +msgstr "Outubro" + +msgid "November" +msgstr "Novembro" + +msgid "December" +msgstr "Dezembro" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "fev" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "abr" + +msgid "may" +msgstr "mai" + +msgid "jun" +msgstr "jun" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "ago" + +msgid "sep" +msgstr "set" + +msgid "oct" +msgstr "out" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dez" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Fev." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Março" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Abril" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Maio" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Junho" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Julho" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Ago." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Set." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Out." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dez." + +msgctxt "alt. month" +msgid "January" +msgstr "Janeiro" + +msgctxt "alt. month" +msgid "February" +msgstr "Fevereiro" + +msgctxt "alt. month" +msgid "March" +msgstr "Março" + +msgctxt "alt. month" +msgid "April" +msgstr "Abril" + +msgctxt "alt. month" +msgid "May" +msgstr "Maio" + +msgctxt "alt. month" +msgid "June" +msgstr "Junho" + +msgctxt "alt. month" +msgid "July" +msgstr "Julho" + +msgctxt "alt. month" +msgid "August" +msgstr "Agosto" + +msgctxt "alt. month" +msgid "September" +msgstr "Setembro" + +msgctxt "alt. month" +msgid "October" +msgstr "Outubro" + +msgctxt "alt. month" +msgid "November" +msgstr "Novembro" + +msgctxt "alt. month" +msgid "December" +msgstr "Dezembro" + +msgid "This is not a valid IPv6 address." +msgstr "Este não é um endereço IPv6 válido." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr " %(truncated_text)s…" + +msgid "or" +msgstr "ou" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d ano" +msgstr[1] "%(num)d anos" +msgstr[2] "%(num)d anos" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mês" +msgstr[1] "%(num)d meses" +msgstr[2] "%(num)d meses" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d semana" +msgstr[1] "%(num)d semanas" +msgstr[2] "%(num)d semanas" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dia" +msgstr[1] "%(num)d dias" +msgstr[2] "%(num)d dias" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hora" +msgstr[1] "%(num)d horas" +msgstr[2] "%(num)d horas" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuto" +msgstr[1] "%(num)d minutos" +msgstr[2] "%(num)d minutos" + +msgid "Forbidden" +msgstr "Proibido" + +msgid "CSRF verification failed. Request aborted." +msgstr "Verificação CSRF falhou. Pedido cancelado." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Você está vendo esta mensagem porque este site HTTPS requer que um " +"“cabeçalho Refer” seja enviado pelo seu navegador da web, mas nenhum foi " +"enviado. Este cabeçalho é necessário por motivos de segurança, para garantir " +"que seu navegador não seja invadido por terceiros." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Se você configurou seu browser para desabilitar os cabeçalhos “Referer”, por " +"favor reabilite-os, ao menos para este site, ou para conexões HTTPS, ou para " +"requisições “same-origin”." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Se estiver usando a tag ou " +"incluindo o cabeçalho “Referrer-Policy: no-referrer”, por favor remova-os. A " +"proteção CSRF requer o cabeçalho “Referer” para fazer a checagem de " +"referência. Se estiver preocupado com privacidade, use alternativas como para links de sites de terceiros." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Você está vendo esta mensagem, porque este site requer um cookie CSRF no " +"envio de formulários. Este cookie é necessário por razões de segurança, para " +"garantir que o seu browser não está sendo sequestrado por terceiros." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Se você configurou seu browser para desabilitar cookies, por favor reabilite-" +"os, ao menos para este site ou para requisições do tipo \"same-origin\"." + +msgid "More information is available with DEBUG=True." +msgstr "Mais informações estão disponíveis com DEBUG=True." + +msgid "No year specified" +msgstr "Ano não especificado" + +msgid "Date out of range" +msgstr "Data fora de alcance" + +msgid "No month specified" +msgstr "Mês não especificado" + +msgid "No day specified" +msgstr "Dia não especificado" + +msgid "No week specified" +msgstr "Semana não especificada" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Nenhum(a) %(verbose_name_plural)s disponível" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"%(verbose_name_plural)s futuros não disponíveis pois %(class_name)s." +"allow_future é False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" +"String de data com formato inválido “%(datestr)s” dado o formato “%(format)s”" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "%(verbose_name)s não encontrado de acordo com a consulta" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Página não é “last”, e também não pode ser convertida para um int." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Página inválida (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Lista vazia e o \"%(class_name)s.allow_empty\" está como False." + +msgid "Directory indexes are not allowed here." +msgstr "Índices de diretório não são permitidos aqui." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "\"%(path)s\" não existe" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Índice de %(directory)s " + +msgid "The install worked successfully! Congratulations!" +msgstr "A instalação foi com sucesso! Parabéns!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Ver as notas de lançamento do Django " +"%(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Você está vendo esta página pois possui DEBUG=True no seu arquivo de configurações e não " +"configurou nenhuma URL." + +msgid "Django Documentation" +msgstr "Documentação do Django" + +msgid "Topics, references, & how-to’s" +msgstr "Tópicos, referências, & how-to’s" + +msgid "Tutorial: A Polling App" +msgstr "Tutorial: Um aplicativo de votação" + +msgid "Get started with Django" +msgstr "Comece a usar Django" + +msgid "Django Community" +msgstr "Comunidade Django" + +msgid "Connect, get help, or contribute" +msgstr "Conecte-se, obtenha ajuda ou contribua" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pt_BR/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pt_BR/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pt_BR/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pt_BR/formats.py new file mode 100644 index 0000000..96a49b4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/pt_BR/formats.py @@ -0,0 +1,34 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = r"j \d\e F \d\e Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = r"j \d\e F \d\e Y à\s H:i" +YEAR_MONTH_FORMAT = r"F \d\e Y" +MONTH_DAY_FORMAT = r"j \d\e F" +SHORT_DATE_FORMAT = "d/m/Y" +SHORT_DATETIME_FORMAT = "d/m/Y H:i" +FIRST_DAY_OF_WEEK = 0 # Sunday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d/%m/%Y", # '25/10/2006' + "%d/%m/%y", # '25/10/06' + # "%d de %b de %Y", # '24 de Out de 2006' + # "%d de %b, %Y", # '25 Out, 2006' + # "%d de %B de %Y", # '25 de Outubro de 2006' + # "%d de %B, %Y", # '25 de Outubro, 2006' +] +DATETIME_INPUT_FORMATS = [ + "%d/%m/%Y %H:%M:%S", # '25/10/2006 14:30:59' + "%d/%m/%Y %H:%M:%S.%f", # '25/10/2006 14:30:59.000200' + "%d/%m/%Y %H:%M", # '25/10/2006 14:30' + "%d/%m/%y %H:%M:%S", # '25/10/06 14:30:59' + "%d/%m/%y %H:%M:%S.%f", # '25/10/06 14:30:59.000200' + "%d/%m/%y %H:%M", # '25/10/06 14:30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ro/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ro/LC_MESSAGES/django.mo new file mode 100644 index 0000000..37e80b0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ro/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ro/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ro/LC_MESSAGES/django.po new file mode 100644 index 0000000..3b83307 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ro/LC_MESSAGES/django.po @@ -0,0 +1,1323 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Abel Radac , 2017 +# Bogdan Mateescu, 2018-2019,2021 +# mihneasim , 2011 +# Daniel Ursache-Dogariu, 2011 +# Denis Darii , 2011,2014 +# Ionel Cristian Mărieș , 2012 +# Jannis Leidel , 2011 +# razvan ionescu , 2015 +# Razvan Stefanescu , 2016-2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-25 06:49+0000\n" +"Last-Translator: Bogdan Mateescu, 2018-2019,2021\n" +"Language-Team: Romanian (http://www.transifex.com/django/django/language/" +"ro/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ro\n" +"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?" +"2:1));\n" + +msgid "Afrikaans" +msgstr "Afrikaans" + +msgid "Arabic" +msgstr "Arabă" + +msgid "Algerian Arabic" +msgstr "" + +msgid "Asturian" +msgstr "Asturiană" + +msgid "Azerbaijani" +msgstr "Azeră" + +msgid "Bulgarian" +msgstr "Bulgară" + +msgid "Belarusian" +msgstr "Bielorusă" + +msgid "Bengali" +msgstr "Bengaleză" + +msgid "Breton" +msgstr "Bretonă" + +msgid "Bosnian" +msgstr "Bosniacă" + +msgid "Catalan" +msgstr "Catalană" + +msgid "Central Kurdish (Sorani)" +msgstr "" + +msgid "Czech" +msgstr "Cehă" + +msgid "Welsh" +msgstr "Galeză" + +msgid "Danish" +msgstr "Daneză" + +msgid "German" +msgstr "Germană" + +msgid "Lower Sorbian" +msgstr "Soraba Inferioară" + +msgid "Greek" +msgstr "Greacă" + +msgid "English" +msgstr "Engleză" + +msgid "Australian English" +msgstr "Engleză australiană" + +msgid "British English" +msgstr "Engleză britanică" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Spaniolă" + +msgid "Argentinian Spanish" +msgstr "Spaniolă Argentiniană" + +msgid "Colombian Spanish" +msgstr "Spaniolă Columbiană" + +msgid "Mexican Spanish" +msgstr "Spaniolă Mexicană" + +msgid "Nicaraguan Spanish" +msgstr "Spaniolă Nicaragua" + +msgid "Venezuelan Spanish" +msgstr "Spaniolă venezueleană" + +msgid "Estonian" +msgstr "Estonă" + +msgid "Basque" +msgstr "Bască" + +msgid "Persian" +msgstr "Persană" + +msgid "Finnish" +msgstr "Finlandeză" + +msgid "French" +msgstr "Franceză" + +msgid "Frisian" +msgstr "Frizian" + +msgid "Irish" +msgstr "Irlandeză" + +msgid "Scottish Gaelic" +msgstr "Galeză Scoțiană" + +msgid "Galician" +msgstr "Galiciană" + +msgid "Hebrew" +msgstr "Ebraică" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Croată" + +msgid "Upper Sorbian" +msgstr "Soraba Superioară" + +msgid "Hungarian" +msgstr "Ungară" + +msgid "Armenian" +msgstr "Armeană" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indoneză" + +msgid "Igbo" +msgstr "" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Islandeză" + +msgid "Italian" +msgstr "Italiană" + +msgid "Japanese" +msgstr "Japoneză" + +msgid "Georgian" +msgstr "Georgiană" + +msgid "Kabyle" +msgstr "Kabyle" + +msgid "Kazakh" +msgstr "Kazahă" + +msgid "Khmer" +msgstr "Khmeră" + +msgid "Kannada" +msgstr "Limba kannada" + +msgid "Korean" +msgstr "Koreană" + +msgid "Kyrgyz" +msgstr "" + +msgid "Luxembourgish" +msgstr "Luxemburgheză" + +msgid "Lithuanian" +msgstr "Lituaniană" + +msgid "Latvian" +msgstr "Letonă" + +msgid "Macedonian" +msgstr "Macedoneană" + +msgid "Malayalam" +msgstr "Malayalam" + +msgid "Mongolian" +msgstr "Mongolă" + +msgid "Marathi" +msgstr "Marathi" + +msgid "Malay" +msgstr "" + +msgid "Burmese" +msgstr "Burmeză" + +msgid "Norwegian Bokmål" +msgstr "Norvegiana modernă" + +msgid "Nepali" +msgstr "Nepaleză" + +msgid "Dutch" +msgstr "Olandeză" + +msgid "Norwegian Nynorsk" +msgstr "Norvegiană Nynorsk" + +msgid "Ossetic" +msgstr "Osețiană" + +msgid "Punjabi" +msgstr "Punjabi" + +msgid "Polish" +msgstr "Poloneză" + +msgid "Portuguese" +msgstr "Portugheză" + +msgid "Brazilian Portuguese" +msgstr "Portugheză braziliană" + +msgid "Romanian" +msgstr "Română" + +msgid "Russian" +msgstr "Rusă" + +msgid "Slovak" +msgstr "Slovacă" + +msgid "Slovenian" +msgstr "Slovenă" + +msgid "Albanian" +msgstr "Albaneză" + +msgid "Serbian" +msgstr "Sârbă" + +msgid "Serbian Latin" +msgstr "Sârbă latină" + +msgid "Swedish" +msgstr "Suedeză" + +msgid "Swahili" +msgstr "Swahili" + +msgid "Tamil" +msgstr "Limba tamila" + +msgid "Telugu" +msgstr "Limba telugu" + +msgid "Tajik" +msgstr "" + +msgid "Thai" +msgstr "Tailandeză" + +msgid "Turkmen" +msgstr "" + +msgid "Turkish" +msgstr "Turcă" + +msgid "Tatar" +msgstr "Tătară" + +msgid "Udmurt" +msgstr "Udmurtă" + +msgid "Ukrainian" +msgstr "Ucraineană" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "Uzbecă" + +msgid "Vietnamese" +msgstr "Vietnameză" + +msgid "Simplified Chinese" +msgstr "Chineză simplificată" + +msgid "Traditional Chinese" +msgstr "Chineză tradițională" + +msgid "Messages" +msgstr "Mesaje" + +msgid "Site Maps" +msgstr "Harta sit-ului" + +msgid "Static Files" +msgstr "Fișiere statice" + +msgid "Syndication" +msgstr "Sindicalizare" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "" + +msgid "That page number is not an integer" +msgstr "Numărul de pagină nu este întreg" + +msgid "That page number is less than 1" +msgstr "Numărul de pagină este mai mic decât 1" + +msgid "That page contains no results" +msgstr "Această pagină nu conține nici un rezultat" + +msgid "Enter a valid value." +msgstr "Introduceți o valoare validă." + +msgid "Enter a valid URL." +msgstr "Introduceți un URL valid." + +msgid "Enter a valid integer." +msgstr "Introduceți un întreg valid." + +msgid "Enter a valid email address." +msgstr "Introduceți o adresă de email validă." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Introduceți un “slug” valid care constă în litere, numere, underscore sau " +"cratime." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Introduceţi o adresă IPv4 validă." + +msgid "Enter a valid IPv6 address." +msgstr "Intoduceți o adresă IPv6 validă." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Introduceți o adresă IPv4 sau IPv6 validă." + +msgid "Enter only digits separated by commas." +msgstr "Introduceţi numai numere separate de virgule." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Asiguraţi-vă că această valoare este %(limit_value)s (este %(show_value)s )." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" +"Asiguraţi-vă că această valoare este mai mică sau egală cu %(limit_value)s ." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" +"Asiguraţi-vă că această valoare este mai mare sau egală cu %(limit_value)s ." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Asigurați-vă că această valoare are cel puțin %(limit_value)d caracter (are " +"%(show_value)d)." +msgstr[1] "" +"Asigurați-vă că această valoare are cel puțin %(limit_value)d caractere (are " +"%(show_value)d)." +msgstr[2] "" +"Asigurați-vă că această valoare are cel puțin %(limit_value)d de caractere " +"(are %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Asigurați-vă că această valoare are cel mult %(limit_value)d caracter (are " +"%(show_value)d)." +msgstr[1] "" +"Asigurați-vă că această valoare are cel mult %(limit_value)d caractere (are " +"%(show_value)d)." +msgstr[2] "" +"Asigurați-vă că această valoare are cel mult %(limit_value)d de caractere " +"(are %(show_value)d)." + +msgid "Enter a number." +msgstr "Introduceţi un număr." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Asigurați-vă că nu este mai mult de %(max)s cifră în total." +msgstr[1] "Asigurați-vă că nu sunt mai mult de %(max)s cifre în total." +msgstr[2] "Asigurați-vă că nu sunt mai mult de %(max)s de cifre în total." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Asigurați-vă că nu este mai mult de %(max)s zecimală în total." +msgstr[1] "Asigurați-vă că nu sunt mai mult de %(max)s zecimale în total." +msgstr[2] "Asigurați-vă că nu sunt mai mult de %(max)s de zecimale în total." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Asigurați-vă că nu este mai mult de %(max)s cifră înainte de punctul zecimal." +msgstr[1] "" +"Asigurați-vă că nu sunt mai mult de %(max)s cifre înainte de punctul zecimal." +msgstr[2] "" +"Asigurați-vă că nu sunt mai mult de %(max)s de cifre înainte de punctul " +"zecimal." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "Caracterele Null nu sunt permise." + +msgid "and" +msgstr "și" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s cu acest %(field_labels)s există deja." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Valoarea %(value)r nu este o opțiune validă." + +msgid "This field cannot be null." +msgstr "Acest câmp nu poate fi nul." + +msgid "This field cannot be blank." +msgstr "Acest câmp nu poate fi gol." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s cu %(field_label)s deja există." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s trebuie să fie unic(e) pentru %(date_field_label)s " +"%(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Câmp de tip: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "Boolean (adevărat sau fals)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Şir de caractere (cel mult %(max_length)s caractere)" + +msgid "String (unlimited)" +msgstr "" + +msgid "Comma-separated integers" +msgstr "Numere întregi separate de virgule" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "Dată (fară oră)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Dată (cu oră)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Număr zecimal" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "Durată" + +msgid "Email address" +msgstr "Adresă e-mail" + +msgid "File path" +msgstr "Calea fisierului" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "Număr cu virgulă" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "Întreg" + +msgid "Big (8 byte) integer" +msgstr "Întreg mare (8 octeți)" + +msgid "Small integer" +msgstr "Întreg mic" + +msgid "IPv4 address" +msgstr "Adresă IPv4" + +msgid "IP address" +msgstr "Adresă IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "Boolean (adevărat, fals sau niciuna)" + +msgid "Positive big integer" +msgstr "" + +msgid "Positive integer" +msgstr "Întreg pozitiv" + +msgid "Positive small integer" +msgstr "Întreg pozitiv mic" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (până la %(max_length)s)" + +msgid "Text" +msgstr "Text" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Timp" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Date binare brute" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "Identificator unic universal" + +msgid "File" +msgstr "Fișier" + +msgid "Image" +msgstr "Imagine" + +msgid "A JSON object" +msgstr "" + +msgid "Value must be valid JSON." +msgstr "" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "Instanța %(model)s cu %(field)s %(value)r inexistentă." + +msgid "Foreign Key (type determined by related field)" +msgstr "Foreign Key (tip determinat de câmpul aferent)" + +msgid "One-to-one relationship" +msgstr "Relaţie unul-la-unul" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "Relație %(from)s-%(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "Relații %(from)s-%(to)s" + +msgid "Many-to-many relationship" +msgstr "Relație multe-la-multe" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Acest câmp este obligatoriu." + +msgid "Enter a whole number." +msgstr "Introduceţi un număr întreg." + +msgid "Enter a valid date." +msgstr "Introduceți o dată validă." + +msgid "Enter a valid time." +msgstr "Introduceți o oră validă." + +msgid "Enter a valid date/time." +msgstr "Introduceți o dată/oră validă." + +msgid "Enter a valid duration." +msgstr "Introduceți o durată validă." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Numărul de zile trebuie să fie cuprins între {min_days} și {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Nici un fișier nu a fost trimis. Verificați tipul fișierului." + +msgid "No file was submitted." +msgstr "Nici un fișier nu a fost trimis." + +msgid "The submitted file is empty." +msgstr "Fișierul încărcat este gol." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Asigurați-vă că numele fișierului are cel mult %(max)d caracter (are " +"%(length)d)." +msgstr[1] "" +"Asigurați-vă că numele fișierului are cel mult %(max)d caractere (are " +"%(length)d)." +msgstr[2] "" +"Asigurați-vă că numele fișierului are cel mult %(max)d de caractere (are " +"%(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Fie indicați un fişier, fie bifaţi caseta de selectare, nu ambele." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Încărcaţi o imagine validă. Fişierul încărcat nu era o imagine sau era o " +"imagine coruptă." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Selectați o opțiune validă. %(value)s nu face parte din opțiunile " +"disponibile." + +msgid "Enter a list of values." +msgstr "Introduceți o listă de valori." + +msgid "Enter a complete value." +msgstr "Introduceți o valoare completă." + +msgid "Enter a valid UUID." +msgstr "Introduceți un UUID valid." + +msgid "Enter a valid JSON." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Câmp ascuns %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +msgid "Order" +msgstr "Ordine" + +msgid "Delete" +msgstr "Șterge" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Corectaţi datele duplicate pentru %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Corectaţi datele duplicate pentru %(field)s , ce trebuie să fie unic." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Corectaţi datele duplicate pentru %(field_name)s , care trebuie să fie unice " +"pentru %(lookup)s în %(date_field)s ." + +msgid "Please correct the duplicate values below." +msgstr "Corectaţi valorile duplicate de mai jos." + +msgid "The inline value did not match the parent instance." +msgstr "Valoarea în linie nu s-a potrivit cu instanța părinte." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Selectați o opțiune validă. Această opțiune nu face parte din opțiunile " +"disponibile." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Șterge" + +msgid "Currently" +msgstr "În prezent" + +msgid "Change" +msgstr "Schimbă" + +msgid "Unknown" +msgstr "Necunoscut" + +msgid "Yes" +msgstr "Da" + +msgid "No" +msgstr "Nu" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "da,nu,poate" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d octet" +msgstr[1] "%(size)d octeţi" +msgstr[2] "%(size)d de octeţi" + +#, python-format +msgid "%s KB" +msgstr "%s KO" + +#, python-format +msgid "%s MB" +msgstr "%s MO" + +#, python-format +msgid "%s GB" +msgstr "%s GO" + +#, python-format +msgid "%s TB" +msgstr "%s TO" + +#, python-format +msgid "%s PB" +msgstr "%s PO" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "miezul nopții" + +msgid "noon" +msgstr "amiază" + +msgid "Monday" +msgstr "Luni" + +msgid "Tuesday" +msgstr "Marți" + +msgid "Wednesday" +msgstr "Miercuri" + +msgid "Thursday" +msgstr "Joi" + +msgid "Friday" +msgstr "Vineri" + +msgid "Saturday" +msgstr "Sâmbătă" + +msgid "Sunday" +msgstr "Duminică" + +msgid "Mon" +msgstr "Lun" + +msgid "Tue" +msgstr "Mar" + +msgid "Wed" +msgstr "Mie" + +msgid "Thu" +msgstr "Joi" + +msgid "Fri" +msgstr "Vin" + +msgid "Sat" +msgstr "Sâm" + +msgid "Sun" +msgstr "Dum" + +msgid "January" +msgstr "Ianuarie" + +msgid "February" +msgstr "Februarie" + +msgid "March" +msgstr "Martie" + +msgid "April" +msgstr "Aprilie" + +msgid "May" +msgstr "Mai" + +msgid "June" +msgstr "Iunie" + +msgid "July" +msgstr "Iulie" + +msgid "August" +msgstr "August" + +msgid "September" +msgstr "Septembrie" + +msgid "October" +msgstr "Octombrie" + +msgid "November" +msgstr "Noiembrie" + +msgid "December" +msgstr "Decembrie" + +msgid "jan" +msgstr "ian" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "apr" + +msgid "may" +msgstr "mai" + +msgid "jun" +msgstr "iun" + +msgid "jul" +msgstr "iul" + +msgid "aug" +msgstr "aug" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "oct" + +msgid "nov" +msgstr "noi" + +msgid "dec" +msgstr "dec" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Ian." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Martie" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Aprilie" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Mai" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Iunie" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Iulie" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Aug." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Sept." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Oct." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Noie." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dec." + +msgctxt "alt. month" +msgid "January" +msgstr "Ianuarie" + +msgctxt "alt. month" +msgid "February" +msgstr "Februarie" + +msgctxt "alt. month" +msgid "March" +msgstr "Martie" + +msgctxt "alt. month" +msgid "April" +msgstr "Aprilie" + +msgctxt "alt. month" +msgid "May" +msgstr "Mai" + +msgctxt "alt. month" +msgid "June" +msgstr "Iunie" + +msgctxt "alt. month" +msgid "July" +msgstr "Iulie" + +msgctxt "alt. month" +msgid "August" +msgstr "August" + +msgctxt "alt. month" +msgid "September" +msgstr "Septembrie" + +msgctxt "alt. month" +msgid "October" +msgstr "Octombrie" + +msgctxt "alt. month" +msgid "November" +msgstr "Noiembrie" + +msgctxt "alt. month" +msgid "December" +msgstr "Decembrie" + +msgid "This is not a valid IPv6 address." +msgstr "Aceasta nu este o adresă IPv6 validă." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "sau" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d an" +msgstr[1] "%(num)d ani" +msgstr[2] "%(num)d de ani" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d lună" +msgstr[1] "%(num)d luni" +msgstr[2] "%(num)d de luni" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d săptămână" +msgstr[1] "%(num)d săptămâni" +msgstr[2] "%(num)d de săptămâni" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d zi" +msgstr[1] "%(num)d zile" +msgstr[2] "%(num)d de zile" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d oră" +msgstr[1] "%(num)d ore" +msgstr[2] "%(num)d de ore" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minut" +msgstr[1] "%(num)d minute" +msgstr[2] "%(num)d de minute" + +msgid "Forbidden" +msgstr "Interzis" + +msgid "CSRF verification failed. Request aborted." +msgstr "Verificarea CSRF nereușită. Cerere eșuată." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Vedeți acest mesaj deoarece această pagină web necesită un cookie CSRF la " +"trimiterea formularelor. Acest cookie este necesar din motive de securitate, " +"pentru a se asigura că browserul nu este deturnat de terți." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "Mai multe informații sunt disponibile pentru DEBUG=True." + +msgid "No year specified" +msgstr "Niciun an specificat" + +msgid "Date out of range" +msgstr "Dată în afara intervalului" + +msgid "No month specified" +msgstr "Nicio lună specificată" + +msgid "No day specified" +msgstr "Nicio zi specificată" + +msgid "No week specified" +msgstr "Nicio săptămîna specificată" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "%(verbose_name_plural)s nu e disponibil" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Viitorul %(verbose_name_plural)s nu e disponibil deoarece %(class_name)s ." +"allow_future este Fals." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Niciun rezultat pentru %(verbose_name)s care se potrivesc interogării" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Pagină invalidă (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Aici nu sunt permise indexuri la directoare" + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Index pentru %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Instalarea a funcționat cu succes! Felicitări!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Vezi notele de lansare pentru Django " +"%(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Vedeți această pagină deoarece DEBUG=True este în fișierul de setări și nu ați " +"configurat niciun URL." + +msgid "Django Documentation" +msgstr "Documentația Django" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "Tutorial: O aplicație de votare" + +msgid "Get started with Django" +msgstr "Începeți cu Django" + +msgid "Django Community" +msgstr "Comunitatea Django" + +msgid "Connect, get help, or contribute" +msgstr "Conectați-vă, obțineți ajutor sau contribuiți" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ro/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ro/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ro/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ro/formats.py new file mode 100644 index 0000000..5a0c173 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ro/formats.py @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j F Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = "j F Y, H:i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "d.m.Y" +SHORT_DATETIME_FORMAT = "d.m.Y, H:i" +FIRST_DAY_OF_WEEK = 1 + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d.%m.%Y", + "%d.%b.%Y", + "%d %B %Y", + "%A, %d %B %Y", +] +TIME_INPUT_FORMATS = [ + "%H:%M", + "%H:%M:%S", + "%H:%M:%S.%f", +] +DATETIME_INPUT_FORMATS = [ + "%d.%m.%Y, %H:%M", + "%d.%m.%Y, %H:%M:%S", + "%d.%B.%Y, %H:%M", + "%d.%B.%Y, %H:%M:%S", +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ru/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ru/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e404421 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ru/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ru/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ru/LC_MESSAGES/django.po new file mode 100644 index 0000000..a4d56f2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ru/LC_MESSAGES/django.po @@ -0,0 +1,1417 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Mingun , 2014 +# Anton Bazhanov , 2017 +# Denis Darii , 2011 +# Dimmus , 2011 +# eigrad , 2012 +# Eugene , 2013 +# Eugene Morozov , 2021 +# eXtractor , 2015 +# crazyzubr , 2020 +# Igor Melnyk, 2014 +# Ivan Khomutov , 2017 +# Jannis Leidel , 2011 +# lilo.panic, 2016 +# Mikhail Zholobov , 2013 +# Nikolay Korotkiy , 2018 +# Panasoft, 2021 +# Вася Аникин , 2017 +# SeryiMysh , 2020 +# Алексей Борискин , 2013-2017,2019-2020,2022-2023 +# Bobsans , 2016,2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Алексей Борискин , " +"2013-2017,2019-2020,2022-2023\n" +"Language-Team: Russian (http://app.transifex.com/django/django/language/" +"ru/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ru\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || " +"(n%100>=11 && n%100<=14)? 2 : 3);\n" + +msgid "Afrikaans" +msgstr "Бурский" + +msgid "Arabic" +msgstr "Арабский" + +msgid "Algerian Arabic" +msgstr "Алжирский арабский" + +msgid "Asturian" +msgstr "Астурийский" + +msgid "Azerbaijani" +msgstr "Азербайджанский" + +msgid "Bulgarian" +msgstr "Болгарский" + +msgid "Belarusian" +msgstr "Белоруский" + +msgid "Bengali" +msgstr "Бенгальский" + +msgid "Breton" +msgstr "Бретонский" + +msgid "Bosnian" +msgstr "Боснийский" + +msgid "Catalan" +msgstr "Каталанский" + +msgid "Central Kurdish (Sorani)" +msgstr "Центральнокурдский (Сорани)" + +msgid "Czech" +msgstr "Чешский" + +msgid "Welsh" +msgstr "Уэльский" + +msgid "Danish" +msgstr "Датский" + +msgid "German" +msgstr "Немецкий" + +msgid "Lower Sorbian" +msgstr "Нижнелужицкий" + +msgid "Greek" +msgstr "Греческий" + +msgid "English" +msgstr "Английский" + +msgid "Australian English" +msgstr "Австралийский английский" + +msgid "British English" +msgstr "Британский английский" + +msgid "Esperanto" +msgstr "Эсперанто" + +msgid "Spanish" +msgstr "Испанский" + +msgid "Argentinian Spanish" +msgstr "Аргентинский испанский" + +msgid "Colombian Spanish" +msgstr "Колумбийский испанский" + +msgid "Mexican Spanish" +msgstr "Мексиканский испанский" + +msgid "Nicaraguan Spanish" +msgstr "Никарагуанский испанский" + +msgid "Venezuelan Spanish" +msgstr "Венесуэльский Испанский" + +msgid "Estonian" +msgstr "Эстонский" + +msgid "Basque" +msgstr "Баскский" + +msgid "Persian" +msgstr "Персидский" + +msgid "Finnish" +msgstr "Финский" + +msgid "French" +msgstr "Французский" + +msgid "Frisian" +msgstr "Фризский" + +msgid "Irish" +msgstr "Ирландский" + +msgid "Scottish Gaelic" +msgstr "Шотландский гэльский" + +msgid "Galician" +msgstr "Галисийский" + +msgid "Hebrew" +msgstr "Иврит" + +msgid "Hindi" +msgstr "Хинди" + +msgid "Croatian" +msgstr "Хорватский" + +msgid "Upper Sorbian" +msgstr "Верхнелужицкий" + +msgid "Hungarian" +msgstr "Венгерский" + +msgid "Armenian" +msgstr "Армянский" + +msgid "Interlingua" +msgstr "Интерлингва" + +msgid "Indonesian" +msgstr "Индонезийский" + +msgid "Igbo" +msgstr "Игбо" + +msgid "Ido" +msgstr "Идо" + +msgid "Icelandic" +msgstr "Исландский" + +msgid "Italian" +msgstr "Итальянский" + +msgid "Japanese" +msgstr "Японский" + +msgid "Georgian" +msgstr "Грузинский" + +msgid "Kabyle" +msgstr "Кабильский" + +msgid "Kazakh" +msgstr "Казахский" + +msgid "Khmer" +msgstr "Кхмерский" + +msgid "Kannada" +msgstr "Каннада" + +msgid "Korean" +msgstr "Корейский" + +msgid "Kyrgyz" +msgstr "Киргизский" + +msgid "Luxembourgish" +msgstr "Люксембургский" + +msgid "Lithuanian" +msgstr "Литовский" + +msgid "Latvian" +msgstr "Латвийский" + +msgid "Macedonian" +msgstr "Македонский" + +msgid "Malayalam" +msgstr "Малаялам" + +msgid "Mongolian" +msgstr "Монгольский" + +msgid "Marathi" +msgstr "Маратхи" + +msgid "Malay" +msgstr "Малайский" + +msgid "Burmese" +msgstr "Бирманский" + +msgid "Norwegian Bokmål" +msgstr "Норвежский (Букмол)" + +msgid "Nepali" +msgstr "Непальский" + +msgid "Dutch" +msgstr "Голландский" + +msgid "Norwegian Nynorsk" +msgstr "Норвежский (Нюнорск)" + +msgid "Ossetic" +msgstr "Осетинский" + +msgid "Punjabi" +msgstr "Панджаби" + +msgid "Polish" +msgstr "Польский" + +msgid "Portuguese" +msgstr "Португальский" + +msgid "Brazilian Portuguese" +msgstr "Бразильский португальский" + +msgid "Romanian" +msgstr "Румынский" + +msgid "Russian" +msgstr "Русский" + +msgid "Slovak" +msgstr "Словацкий" + +msgid "Slovenian" +msgstr "Словенский" + +msgid "Albanian" +msgstr "Албанский" + +msgid "Serbian" +msgstr "Сербский" + +msgid "Serbian Latin" +msgstr "Сербский (латиница)" + +msgid "Swedish" +msgstr "Шведский" + +msgid "Swahili" +msgstr "Суахили" + +msgid "Tamil" +msgstr "Тамильский" + +msgid "Telugu" +msgstr "Телугу" + +msgid "Tajik" +msgstr "Таджикский" + +msgid "Thai" +msgstr "Тайский" + +msgid "Turkmen" +msgstr "Туркменский" + +msgid "Turkish" +msgstr "Турецкий" + +msgid "Tatar" +msgstr "Татарский" + +msgid "Udmurt" +msgstr "Удмуртский" + +msgid "Uyghur" +msgstr "Уйгурский" + +msgid "Ukrainian" +msgstr "Украинский" + +msgid "Urdu" +msgstr "Урду" + +msgid "Uzbek" +msgstr "Узбекский" + +msgid "Vietnamese" +msgstr "Вьетнамский" + +msgid "Simplified Chinese" +msgstr "Упрощенный китайский" + +msgid "Traditional Chinese" +msgstr "Традиционный китайский" + +msgid "Messages" +msgstr "Сообщения" + +msgid "Site Maps" +msgstr "Карта сайта" + +msgid "Static Files" +msgstr "Статические файлы" + +msgid "Syndication" +msgstr "Ленты новостей" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Номер страницы не является натуральным числом" + +msgid "That page number is less than 1" +msgstr "Номер страницы меньше 1" + +msgid "That page contains no results" +msgstr "Страница не содержит результатов" + +msgid "Enter a valid value." +msgstr "Введите правильное значение." + +msgid "Enter a valid URL." +msgstr "Введите правильный URL." + +msgid "Enter a valid integer." +msgstr "Введите правильное число." + +msgid "Enter a valid email address." +msgstr "Введите правильный адрес электронной почты." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Значение должно состоять только из латинских букв, цифр, знаков " +"подчеркивания или дефиса." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Значение должно состоять только из символов входящих в стандарт Юникод, " +"цифр, символов подчёркивания или дефисов." + +msgid "Enter a valid IPv4 address." +msgstr "Введите правильный IPv4 адрес." + +msgid "Enter a valid IPv6 address." +msgstr "Введите действительный IPv6 адрес." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Введите действительный IPv4 или IPv6 адрес." + +msgid "Enter only digits separated by commas." +msgstr "Введите цифры, разделенные запятыми." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Убедитесь, что это значение — %(limit_value)s (сейчас оно — %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Убедитесь, что это значение меньше либо равно %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Убедитесь, что это значение больше либо равно %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "Убедитесь, что это значение кратно числу %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"Убедитесь, что данное значение отстоит от %(offset)s на число, кратное шагу " +"%(limit_value)s, например: %(offset)s, %(valid_value1)s, %(valid_value2)s и " +"так далее." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Убедитесь, что это значение содержит не менее %(limit_value)d символ (сейчас " +"%(show_value)d)." +msgstr[1] "" +"Убедитесь, что это значение содержит не менее %(limit_value)d символов " +"(сейчас %(show_value)d)." +msgstr[2] "" +"Убедитесь, что это значение содержит не менее %(limit_value)d символов " +"(сейчас %(show_value)d)." +msgstr[3] "" +"Убедитесь, что это значение содержит не менее %(limit_value)d символов " +"(сейчас %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Убедитесь, что это значение содержит не более %(limit_value)d символ (сейчас " +"%(show_value)d)." +msgstr[1] "" +"Убедитесь, что это значение содержит не более %(limit_value)d символов " +"(сейчас %(show_value)d)." +msgstr[2] "" +"Убедитесь, что это значение содержит не более %(limit_value)d символов " +"(сейчас %(show_value)d)." +msgstr[3] "" +"Убедитесь, что это значение содержит не более %(limit_value)d символов " +"(сейчас %(show_value)d)." + +msgid "Enter a number." +msgstr "Введите число." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Убедитесь, что вы ввели не более %(max)s цифры." +msgstr[1] "Убедитесь, что вы ввели не более %(max)s цифр." +msgstr[2] "Убедитесь, что вы ввели не более %(max)s цифр." +msgstr[3] "Убедитесь, что вы ввели не более %(max)s цифр." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Убедитесь, что вы ввели не более %(max)s цифры после запятой." +msgstr[1] "Убедитесь, что вы ввели не более %(max)s цифр после запятой." +msgstr[2] "Убедитесь, что вы ввели не более %(max)s цифр после запятой." +msgstr[3] "Убедитесь, что вы ввели не более %(max)s цифр после запятой." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "Убедитесь, что вы ввели не более %(max)s цифры перед запятой." +msgstr[1] "Убедитесь, что вы ввели не более %(max)s цифр перед запятой." +msgstr[2] "Убедитесь, что вы ввели не более %(max)s цифр перед запятой." +msgstr[3] "Убедитесь, что вы ввели не более %(max)s цифр перед запятой." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Расширение файлов “%(extension)s” не поддерживается. Разрешенные расширения: " +"%(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Данные содержат запрещённый символ: ноль-байт" + +msgid "and" +msgstr "и" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" +"%(model_name)s с такими значениями полей %(field_labels)s уже существует." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Нарушено ограничение \"%(name)s\"." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Значения %(value)r нет среди допустимых вариантов." + +msgid "This field cannot be null." +msgstr "Это поле не может иметь значение NULL." + +msgid "This field cannot be blank." +msgstr "Это поле не может быть пустым." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s с таким %(field_label)s уже существует." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"Значение в поле «%(field_label)s» должно быть уникальным для фрагмента " +"«%(lookup_type)s» даты в поле %(date_field_label)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Поле типа %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "Значение “%(value)s” должно быть True или False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "Значение “%(value)s” должно быть True, False или None." + +msgid "Boolean (Either True or False)" +msgstr "Логическое (True или False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Строка (до %(max_length)s)" + +msgid "String (unlimited)" +msgstr "Строка (неограниченной длины)" + +msgid "Comma-separated integers" +msgstr "Целые, разделенные запятыми" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"Значение “%(value)s” имеет неверный формат даты. Оно должно быть в формате " +"YYYY-MM-DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"Значение “%(value)s” имеет корректный формат (YYYY-MM-DD), но это " +"недействительная дата." + +msgid "Date (without time)" +msgstr "Дата (без указания времени)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"Значение “%(value)s” имеет неверный формат. Оно должно быть в формате YYYY-" +"MM-DD HH:MM[:ss[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"Значение “%(value)s” имеет корректный формат (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]), но это недействительные дата/время." + +msgid "Date (with time)" +msgstr "Дата (с указанием времени)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "Значение “%(value)s” должно быть десятичным числом." + +msgid "Decimal number" +msgstr "Число с фиксированной запятой" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"Значение “%(value)s” имеет неверный формат. Оно должно быть в формате [DD] " +"[HH:[MM:]]ss[.uuuuuu]." + +msgid "Duration" +msgstr "Продолжительность" + +msgid "Email address" +msgstr "Адрес электронной почты" + +msgid "File path" +msgstr "Путь к файлу" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "Значение “%(value)s” должно быть числом с плавающей точкой." + +msgid "Floating point number" +msgstr "Число с плавающей запятой" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "Значение “%(value)s” должно быть целым числом." + +msgid "Integer" +msgstr "Целое" + +msgid "Big (8 byte) integer" +msgstr "Длинное целое (8 байт)" + +msgid "Small integer" +msgstr "Малое целое число" + +msgid "IPv4 address" +msgstr "IPv4 адрес" + +msgid "IP address" +msgstr "IP-адрес" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "Значение “%(value)s” должно быть None, True или False." + +msgid "Boolean (Either True, False or None)" +msgstr "Логическое (True, False или None)" + +msgid "Positive big integer" +msgstr "Положительное большое целое число" + +msgid "Positive integer" +msgstr "Положительное целое число" + +msgid "Positive small integer" +msgstr "Положительное малое целое число" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Слаг (до %(max_length)s)" + +msgid "Text" +msgstr "Текст" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"Значение “%(value)s” имеет неверный формат. Оно должно быть в формате HH:MM[:" +"ss[.uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"Значение “%(value)s” имеет корректный формат (HH:MM[:ss[.uuuuuu]]), но это " +"недействительное время." + +msgid "Time" +msgstr "Время" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Необработанные двоичные данные" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "Значение “%(value)s” не является верным UUID-ом." + +msgid "Universally unique identifier" +msgstr "Поле для UUID, универсального уникального идентификатора" + +msgid "File" +msgstr "Файл" + +msgid "Image" +msgstr "Изображение" + +msgid "A JSON object" +msgstr "JSON-объект" + +msgid "Value must be valid JSON." +msgstr "Значение должно быть корректным JSON-ом." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" +"Объект модели %(model)s со значением поля %(field)s, равным %(value)r, не " +"существует." + +msgid "Foreign Key (type determined by related field)" +msgstr "Внешний Ключ (тип определен по связанному полю)" + +msgid "One-to-one relationship" +msgstr "Связь \"один к одному\"" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "Связь %(from)s-%(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "Связи %(from)s-%(to)s" + +msgid "Many-to-many relationship" +msgstr "Связь \"многие ко многим\"" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Обязательное поле." + +msgid "Enter a whole number." +msgstr "Введите целое число." + +msgid "Enter a valid date." +msgstr "Введите правильную дату." + +msgid "Enter a valid time." +msgstr "Введите правильное время." + +msgid "Enter a valid date/time." +msgstr "Введите правильную дату и время." + +msgid "Enter a valid duration." +msgstr "Введите правильную продолжительность." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Количество дней должно быть в диапазоне от {min_days} до {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Ни одного файла не было отправлено. Проверьте тип кодировки формы." + +msgid "No file was submitted." +msgstr "Ни одного файла не было отправлено." + +msgid "The submitted file is empty." +msgstr "Отправленный файл пуст." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Убедитесь, что это имя файла содержит не более %(max)d символ (сейчас " +"%(length)d)." +msgstr[1] "" +"Убедитесь, что это имя файла содержит не более %(max)d символов (сейчас " +"%(length)d)." +msgstr[2] "" +"Убедитесь, что это имя файла содержит не более %(max)d символов (сейчас " +"%(length)d)." +msgstr[3] "" +"Убедитесь, что это имя файла содержит не более %(max)d символов (сейчас " +"%(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Пожалуйста, загрузите файл или поставьте флажок \"Очистить\", но не " +"совершайте оба действия одновременно." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Загрузите правильное изображение. Файл, который вы загрузили, поврежден или " +"не является изображением." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Выберите корректный вариант. %(value)s нет среди допустимых значений." + +msgid "Enter a list of values." +msgstr "Введите список значений." + +msgid "Enter a complete value." +msgstr "Введите весь список значений." + +msgid "Enter a valid UUID." +msgstr "Введите правильный UUID." + +msgid "Enter a valid JSON." +msgstr "Введите корректный JSON." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Скрытое поле %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"Данные ManagementForm отсутствуют или были подделаны. Отсутствующие поля: " +"%(field_names)s. Если проблема не исчезнет, вам может потребоваться " +"отправить отчет об ошибке." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Пожалуйста, отправьте не больше %(num)d формы." +msgstr[1] "Пожалуйста, отправьте не больше %(num)d форм." +msgstr[2] "Пожалуйста, отправьте не больше %(num)d форм." +msgstr[3] "Пожалуйста, отправьте не больше %(num)d форм." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Пожалуйста, отправьте %(num)d форму." +msgstr[1] "Пожалуйста, отправьте %(num)d формы." +msgstr[2] "Пожалуйста, отправьте %(num)d форм." +msgstr[3] "Пожалуйста, отправьте %(num)d форм." + +msgid "Order" +msgstr "Порядок" + +msgid "Delete" +msgstr "Удалить" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Пожалуйста, измените повторяющееся значение в поле \"%(field)s\"." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Пожалуйста, измените значение в поле %(field)s, оно должно быть уникальным." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Пожалуйста, измените значение в поле %(field_name)s, оно должно быть " +"уникальным для %(lookup)s в поле %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Пожалуйста, измените повторяющиеся значения ниже." + +msgid "The inline value did not match the parent instance." +msgstr "Значение во вложенной форме не совпадает со значением в базовой форме." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Выберите корректный вариант. Вашего варианта нет среди допустимых значений." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "“%(pk)s” является неверным значением." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s не может быть интерпретирована в часовом поясе " +"%(current_timezone)s; дата может быть неоднозначной или оказаться " +"несуществующей." + +msgid "Clear" +msgstr "Очистить" + +msgid "Currently" +msgstr "На данный момент" + +msgid "Change" +msgstr "Изменить" + +msgid "Unknown" +msgstr "Неизвестно" + +msgid "Yes" +msgstr "Да" + +msgid "No" +msgstr "Нет" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "да,нет,может быть" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d байт" +msgstr[1] "%(size)d байта" +msgstr[2] "%(size)d байт" +msgstr[3] "%(size)d байт" + +#, python-format +msgid "%s KB" +msgstr "%s КБ" + +#, python-format +msgid "%s MB" +msgstr "%s МБ" + +#, python-format +msgid "%s GB" +msgstr "%s ГБ" + +#, python-format +msgid "%s TB" +msgstr "%s ТБ" + +#, python-format +msgid "%s PB" +msgstr "%s ПБ" + +msgid "p.m." +msgstr "п.п." + +msgid "a.m." +msgstr "д.п." + +msgid "PM" +msgstr "ПП" + +msgid "AM" +msgstr "ДП" + +msgid "midnight" +msgstr "полночь" + +msgid "noon" +msgstr "полдень" + +msgid "Monday" +msgstr "Понедельник" + +msgid "Tuesday" +msgstr "Вторник" + +msgid "Wednesday" +msgstr "Среда" + +msgid "Thursday" +msgstr "Четверг" + +msgid "Friday" +msgstr "Пятница" + +msgid "Saturday" +msgstr "Суббота" + +msgid "Sunday" +msgstr "Воскресенье" + +msgid "Mon" +msgstr "Пн" + +msgid "Tue" +msgstr "Вт" + +msgid "Wed" +msgstr "Ср" + +msgid "Thu" +msgstr "Чт" + +msgid "Fri" +msgstr "Пт" + +msgid "Sat" +msgstr "Сб" + +msgid "Sun" +msgstr "Вс" + +msgid "January" +msgstr "Январь" + +msgid "February" +msgstr "Февраль" + +msgid "March" +msgstr "Март" + +msgid "April" +msgstr "Апрель" + +msgid "May" +msgstr "Май" + +msgid "June" +msgstr "Июнь" + +msgid "July" +msgstr "Июль" + +msgid "August" +msgstr "Август" + +msgid "September" +msgstr "Сентябрь" + +msgid "October" +msgstr "Октябрь" + +msgid "November" +msgstr "Ноябрь" + +msgid "December" +msgstr "Декабрь" + +msgid "jan" +msgstr "янв" + +msgid "feb" +msgstr "фев" + +msgid "mar" +msgstr "мар" + +msgid "apr" +msgstr "апр" + +msgid "may" +msgstr "май" + +msgid "jun" +msgstr "июн" + +msgid "jul" +msgstr "июл" + +msgid "aug" +msgstr "авг" + +msgid "sep" +msgstr "сен" + +msgid "oct" +msgstr "окт" + +msgid "nov" +msgstr "ноя" + +msgid "dec" +msgstr "дек" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Янв." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Фев." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Март" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Апрель" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Май" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Июнь" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Июль" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Авг." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Сен." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Окт." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Ноя." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Дек." + +msgctxt "alt. month" +msgid "January" +msgstr "января" + +msgctxt "alt. month" +msgid "February" +msgstr "февраля" + +msgctxt "alt. month" +msgid "March" +msgstr "марта" + +msgctxt "alt. month" +msgid "April" +msgstr "апреля" + +msgctxt "alt. month" +msgid "May" +msgstr "мая" + +msgctxt "alt. month" +msgid "June" +msgstr "июня" + +msgctxt "alt. month" +msgid "July" +msgstr "июля" + +msgctxt "alt. month" +msgid "August" +msgstr "августа" + +msgctxt "alt. month" +msgid "September" +msgstr "сентября" + +msgctxt "alt. month" +msgid "October" +msgstr "октября" + +msgctxt "alt. month" +msgid "November" +msgstr "ноября" + +msgctxt "alt. month" +msgid "December" +msgstr "декабря" + +msgid "This is not a valid IPv6 address." +msgstr "Значение не является корректным адресом IPv6." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "или" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d год" +msgstr[1] "%(num)d года" +msgstr[2] "%(num)d лет" +msgstr[3] "%(num)d лет" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d месяц" +msgstr[1] "%(num)d месяца" +msgstr[2] "%(num)d месяцев" +msgstr[3] "%(num)d месяцев" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d неделя" +msgstr[1] "%(num)d недели" +msgstr[2] "%(num)d недель" +msgstr[3] "%(num)d недель" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d день" +msgstr[1] "%(num)d дня" +msgstr[2] "%(num)d дней" +msgstr[3] "%(num)d дней" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d час" +msgstr[1] "%(num)d часа" +msgstr[2] "%(num)d часов" +msgstr[3] "%(num)d часов" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d минута" +msgstr[1] "%(num)d минуты" +msgstr[2] "%(num)d минут" +msgstr[3] "%(num)d минут" + +msgid "Forbidden" +msgstr "Ошибка доступа" + +msgid "CSRF verification failed. Request aborted." +msgstr "Ошибка проверки CSRF. Запрос отклонён." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Вы видите это сообщение потому что этот сайт работает по защищённому " +"протоколу HTTPS и требует, чтобы при запросе вашим браузером был передан " +"заголовок \"Referer\", но он не был передан. Этот заголовок необходим из " +"соображений безопасности: мы должны убедиться что запрос оправляете именно " +"вы." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Если вы настроили свой браузер таким образом, чтобы запретить ему передавать " +"заголовок “Referer”, пожалуйста, разрешите ему отсылать данный заголовок по " +"крайней мере для данного сайта, или для всех HTTPS-соединений, или для " +"запросов, домен и порт назначения совпадают с доменом и портом текущей " +"страницы." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Если Вы используете HTML-тэг или добавили HTTP-заголовок “Referrer-Policy: no-referrer”, " +"пожалуйста удалите их. CSRF защите необходим заголовок “Referer” для строгой " +"проверки адреса ссылающейся страницы. Если Вы беспокоитесь о приватности, " +"используйте альтернативы, например , для ссылок на " +"сайты третьих лиц." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Вы видите это сообщение, потому что данный сайт требует, чтобы при отправке " +"форм была отправлена и CSRF-cookie. Данный тип cookie необходим по " +"соображениям безопасности, чтобы убедиться, что ваш браузер не был взломан и " +"не выполняет от вашего лица действий, запрограммированных третьими лицами." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Если в вашем браузере отключены cookie, пожалуйста, включите эту функцию " +"вновь, по крайней мере для этого сайта, или для \"same-orign\" запросов." + +msgid "More information is available with DEBUG=True." +msgstr "" +"В отладочном режиме доступно больше информации. Включить отладочный режим " +"можно, установив значение переменной DEBUG=True." + +msgid "No year specified" +msgstr "Не указан год" + +msgid "Date out of range" +msgstr "Дата выходит за пределы диапазона" + +msgid "No month specified" +msgstr "Не указан месяц" + +msgid "No day specified" +msgstr "Не указан день" + +msgid "No week specified" +msgstr "Не указана неделя" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "%(verbose_name_plural)s не доступен" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Будущие %(verbose_name_plural)s недоступны, потому что %(class_name)s." +"allow_future выставлен в значение \"Ложь\"." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" +"Не удалось распознать строку с датой “%(datestr)s”, в заданном формате " +"“%(format)s”" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Не найден ни один %(verbose_name)s, соответствующий запросу" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" +"Номер страницы не содержит особое значение “last” и его не удалось " +"преобразовать к целому числу." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Неправильная страница (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" +"Список пуст, но “%(class_name)s.allow_empty” выставлено в значение \"Ложь\", " +"что запрещает показывать пустые списки." + +msgid "Directory indexes are not allowed here." +msgstr "Просмотр списка файлов директории здесь не разрешен." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "“%(path)s” не существует" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Список файлов директории %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Установка прошла успешно! Поздравляем!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Посмотреть примечания к выпуску для Django " +"%(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Вы видите данную страницу, потому что указали DEBUG=True в файле настроек и не настроили ни одного " +"обработчика URL-адресов." + +msgid "Django Documentation" +msgstr "Документация Django" + +msgid "Topics, references, & how-to’s" +msgstr "Разделы, справочник, & примеры" + +msgid "Tutorial: A Polling App" +msgstr "Руководство: Приложение для голосования" + +msgid "Get started with Django" +msgstr "Начало работы с Django" + +msgid "Django Community" +msgstr "Сообщество Django" + +msgid "Connect, get help, or contribute" +msgstr "Присоединяйтесь, получайте помощь или помогайте в разработке" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ru/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ru/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ru/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ru/formats.py new file mode 100644 index 0000000..212e526 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ru/formats.py @@ -0,0 +1,30 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j E Y г." +TIME_FORMAT = "G:i" +DATETIME_FORMAT = "j E Y г. G:i" +YEAR_MONTH_FORMAT = "F Y г." +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "d.m.Y" +SHORT_DATETIME_FORMAT = "d.m.Y H:i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d.%m.%Y", # '25.10.2006' + "%d.%m.%y", # '25.10.06' +] +DATETIME_INPUT_FORMATS = [ + "%d.%m.%Y %H:%M:%S", # '25.10.2006 14:30:59' + "%d.%m.%Y %H:%M:%S.%f", # '25.10.2006 14:30:59.000200' + "%d.%m.%Y %H:%M", # '25.10.2006 14:30' + "%d.%m.%y %H:%M:%S", # '25.10.06 14:30:59' + "%d.%m.%y %H:%M:%S.%f", # '25.10.06 14:30:59.000200' + "%d.%m.%y %H:%M", # '25.10.06 14:30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "\xa0" # non-breaking space +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e1f7271 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sk/LC_MESSAGES/django.po new file mode 100644 index 0000000..14da7f9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sk/LC_MESSAGES/django.po @@ -0,0 +1,1387 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Adam Zahradník, 2023 +# Jannis Leidel , 2011 +# 18f25ad6fa9930fc67cb11aca9d16a27, 2012-2013 +# Marian Andre , 2013,2015,2017-2018 +# 29cf7e517570e1bc05a1509565db92ae_2a01508, 2011 +# Martin Tóth , 2017,2023 +# Miroslav Bendik , 2023 +# Peter Kuma, 2021 +# Peter Stríž , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Martin Tóth , 2017,2023\n" +"Language-Team: Slovak (http://app.transifex.com/django/django/language/sk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n " +">= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);\n" + +msgid "Afrikaans" +msgstr "afrikánsky" + +msgid "Arabic" +msgstr "arabský" + +msgid "Algerian Arabic" +msgstr "alžírsky arabsky" + +msgid "Asturian" +msgstr "astúrsky" + +msgid "Azerbaijani" +msgstr "azerbajdžansky" + +msgid "Bulgarian" +msgstr "bulharsky" + +msgid "Belarusian" +msgstr "bielorusky" + +msgid "Bengali" +msgstr "bengálsky" + +msgid "Breton" +msgstr "bretónsky" + +msgid "Bosnian" +msgstr "bosniansky" + +msgid "Catalan" +msgstr "katalánsky" + +msgid "Central Kurdish (Sorani)" +msgstr "stredná kurdčina (Sorani)" + +msgid "Czech" +msgstr "česky" + +msgid "Welsh" +msgstr "walesky" + +msgid "Danish" +msgstr "dánsky" + +msgid "German" +msgstr "nemecky" + +msgid "Lower Sorbian" +msgstr "dolnolužická srbčina" + +msgid "Greek" +msgstr "grécky" + +msgid "English" +msgstr "anglicky" + +msgid "Australian English" +msgstr "austrálskou angličtinou" + +msgid "British English" +msgstr "britskou angličtinou" + +msgid "Esperanto" +msgstr "esperantsky" + +msgid "Spanish" +msgstr "španielsky" + +msgid "Argentinian Spanish" +msgstr "argentínska španielčina" + +msgid "Colombian Spanish" +msgstr "kolumbijská španielčina" + +msgid "Mexican Spanish" +msgstr "mexická španielčina" + +msgid "Nicaraguan Spanish" +msgstr "nikaragujská španielčina" + +msgid "Venezuelan Spanish" +msgstr "venezuelská španielčina" + +msgid "Estonian" +msgstr "estónsky" + +msgid "Basque" +msgstr "baskicky" + +msgid "Persian" +msgstr "perzsky" + +msgid "Finnish" +msgstr "fínsky" + +msgid "French" +msgstr "francúzsky" + +msgid "Frisian" +msgstr "frízsky" + +msgid "Irish" +msgstr "írsky" + +msgid "Scottish Gaelic" +msgstr "škótska gaelčina" + +msgid "Galician" +msgstr "galícijsky" + +msgid "Hebrew" +msgstr "hebrejsky" + +msgid "Hindi" +msgstr "hindsky" + +msgid "Croatian" +msgstr "chorvátsky" + +msgid "Upper Sorbian" +msgstr "hornolužická srbčina" + +msgid "Hungarian" +msgstr "maďarsky" + +msgid "Armenian" +msgstr "arménsky" + +msgid "Interlingua" +msgstr "interlinguánsky" + +msgid "Indonesian" +msgstr "indonézsky" + +msgid "Igbo" +msgstr "igbožsky" + +msgid "Ido" +msgstr "ido" + +msgid "Icelandic" +msgstr "islandsky" + +msgid "Italian" +msgstr "taliansky" + +msgid "Japanese" +msgstr "japonsky" + +msgid "Georgian" +msgstr "gruzínsky" + +msgid "Kabyle" +msgstr "kabylsky" + +msgid "Kazakh" +msgstr "kazašsky" + +msgid "Khmer" +msgstr "kmérsky" + +msgid "Kannada" +msgstr "kannadsky" + +msgid "Korean" +msgstr "kórejsky" + +msgid "Kyrgyz" +msgstr "kirgizsky" + +msgid "Luxembourgish" +msgstr "luxembursky" + +msgid "Lithuanian" +msgstr "litovsky" + +msgid "Latvian" +msgstr "lotyšsky" + +msgid "Macedonian" +msgstr "macedónsky" + +msgid "Malayalam" +msgstr "malajalámsky" + +msgid "Mongolian" +msgstr "mongolsky" + +msgid "Marathi" +msgstr "maráthsky" + +msgid "Malay" +msgstr "malajčina" + +msgid "Burmese" +msgstr "barmsky" + +msgid "Norwegian Bokmål" +msgstr "nórsky (Bokmål)" + +msgid "Nepali" +msgstr "nepálsky" + +msgid "Dutch" +msgstr "holandsky" + +msgid "Norwegian Nynorsk" +msgstr "nórsky (Nynorsk)" + +msgid "Ossetic" +msgstr "osetsky" + +msgid "Punjabi" +msgstr "pandžábsky" + +msgid "Polish" +msgstr "poľsky" + +msgid "Portuguese" +msgstr "portugalsky" + +msgid "Brazilian Portuguese" +msgstr "portugalsky (Brazília)" + +msgid "Romanian" +msgstr "rumunsky" + +msgid "Russian" +msgstr "rusky" + +msgid "Slovak" +msgstr "slovensky" + +msgid "Slovenian" +msgstr "slovinsky" + +msgid "Albanian" +msgstr "albánsky" + +msgid "Serbian" +msgstr "srbsky" + +msgid "Serbian Latin" +msgstr "srbsky (Latin)" + +msgid "Swedish" +msgstr "švédsky" + +msgid "Swahili" +msgstr "svahilsky" + +msgid "Tamil" +msgstr "tamilsky" + +msgid "Telugu" +msgstr "telugsky" + +msgid "Tajik" +msgstr "tadžiksky" + +msgid "Thai" +msgstr "thajsky" + +msgid "Turkmen" +msgstr "turkménsky" + +msgid "Turkish" +msgstr "turecky" + +msgid "Tatar" +msgstr "tatársky" + +msgid "Udmurt" +msgstr "udmurtsky" + +msgid "Uyghur" +msgstr "ujgursky" + +msgid "Ukrainian" +msgstr "ukrajinsky" + +msgid "Urdu" +msgstr "urdsky" + +msgid "Uzbek" +msgstr "uzbecky" + +msgid "Vietnamese" +msgstr "vietnamsky" + +msgid "Simplified Chinese" +msgstr "čínsky (zjednodušene)" + +msgid "Traditional Chinese" +msgstr "čínsky (tradične)" + +msgid "Messages" +msgstr "Správy" + +msgid "Site Maps" +msgstr "Mapy Sídla" + +msgid "Static Files" +msgstr "Statické Súbory" + +msgid "Syndication" +msgstr "Syndikácia" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Číslo stránky nie je celé číslo" + +msgid "That page number is less than 1" +msgstr "Číslo stránky je menšie ako 1" + +msgid "That page contains no results" +msgstr "Stránka neobsahuje žiadne výsledky" + +msgid "Enter a valid value." +msgstr "Zadajte platnú hodnotu." + +msgid "Enter a valid URL." +msgstr "Zadajte platnú URL adresu." + +msgid "Enter a valid integer." +msgstr "Zadajte platné celé číslo." + +msgid "Enter a valid email address." +msgstr "Zadajte platnú e-mailovú adresu." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Zadajte platnú skratku pozostávajúcu z písmen, čísel, podčiarkovníkov alebo " +"pomlčiek." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Zadajte platnú skratku pozostávajúcu z písmen Unicode, čísel, " +"podčiarkovníkov alebo pomlčiek." + +msgid "Enter a valid IPv4 address." +msgstr "Zadajte platnú IPv4 adresu." + +msgid "Enter a valid IPv6 address." +msgstr "Zadajte platnú IPv6 adresu." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Zadajte platnú IPv4 alebo IPv6 adresu." + +msgid "Enter only digits separated by commas." +msgstr "Zadajte len číslice oddelené čiarkami." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Uistite sa, že táto hodnota je %(limit_value)s (je to %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Uistite sa, že táto hodnota je menšia alebo rovná %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Uistite sa, že hodnota je väčšia alebo rovná %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "Uistite sa, že táto hodnota je násobkom %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"Uistite sa, že táto hodnota je násobkom %(limit_value)s, začínajúc od " +"%(offset)s, t.j. %(offset)s, %(valid_value1)s, %(valid_value2)s, atď." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Uistite sa, že zadaná hodnota má najmenej %(limit_value)d znak (má " +"%(show_value)d)." +msgstr[1] "" +"Uistite sa, že zadaná hodnota má najmenej %(limit_value)d znaky (má " +"%(show_value)d)." +msgstr[2] "" +"Uistite sa, že zadaná hodnota má najmenej %(limit_value)d znakov (má " +"%(show_value)d)." +msgstr[3] "" +"Uistite sa, že zadaná hodnota má najmenej %(limit_value)d znakov (má " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Uistite sa, že táto hodnota má najviac %(limit_value)d znak (má " +"%(show_value)d)." +msgstr[1] "" +"Uistite sa, že táto hodnota má najviac %(limit_value)d znaky (má " +"%(show_value)d)." +msgstr[2] "" +"Uistite sa, že táto hodnota má najviac %(limit_value)d znakov (má " +"%(show_value)d)." +msgstr[3] "" +"Uistite sa, že táto hodnota má najviac %(limit_value)d znakov (má " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Zadajte číslo." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Uistite sa, že nie je zadaných celkovo viac ako %(max)s číslica." +msgstr[1] "Uistite sa, že nie je zadaných celkovo viac ako %(max)s číslice." +msgstr[2] "Uistite sa, že nie je zadaných celkovo viac ako %(max)s číslic." +msgstr[3] "Uistite sa, že nie je zadaných celkovo viac ako %(max)s číslic." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Uistite sa, že nie je zadané viac ako %(max)s desatinné miesto." +msgstr[1] "Uistite sa, že nie sú zadané viac ako %(max)s desatinné miesta." +msgstr[2] "Uistite sa, že nie je zadaných viac ako %(max)s desatinných miest." +msgstr[3] "Uistite sa, že nie je zadaných viac ako %(max)s desatinných miest." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Uistite sa, že nie je zadaných viac ako %(max)s číslica pred desatinnou " +"čiarkou." +msgstr[1] "" +"Uistite sa, že nie sú zadané viac ako %(max)s číslice pred desatinnou " +"čiarkou." +msgstr[2] "" +"Uistite sa, že nie je zadaných viac ako %(max)s číslic pred desatinnou " +"čiarkou." +msgstr[3] "" +"Uistite sa, že nie je zadaných viac ako %(max)s číslic pred desatinnou " +"čiarkou." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Prípona súboru „%(extension)s“ nie je povolená. Povolené prípony sú: " +"%(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Znaky NULL nie sú povolené." + +msgid "and" +msgstr "a" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s s týmto %(field_labels)s už existuje." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Obmedzenie „%(name)s“ je porušené." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Hodnota %(value)r nie je platná možnosť." + +msgid "This field cannot be null." +msgstr "Toto pole nemôže byť prázdne." + +msgid "This field cannot be blank." +msgstr "Toto pole nemôže byť prázdne." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s s týmto %(field_label)s už existuje." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s musí byť jedinečné pre %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Pole typu: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "Hodnota „%(value)s“ musí byť True alebo False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "Hodnota „%(value)s“ musí byť True, False alebo None." + +msgid "Boolean (Either True or False)" +msgstr "Logická hodnota (buď True alebo False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Reťazec (až do %(max_length)s)" + +msgid "String (unlimited)" +msgstr "Reťazec (neobmedzený)" + +msgid "Comma-separated integers" +msgstr "Celé čísla oddelené čiarkou" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"Hodnota „%(value)s“ má neplatný tvar dátumu. Musí byť v tvare YYYY-MM-DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"Hodnota „%(value)s“ je v správnom tvare (YYYY-MM-DD), ale je to neplatný " +"dátum." + +msgid "Date (without time)" +msgstr "Dátum (bez času)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"Hodnota „%(value)s“ má neplatný tvar. Musí byť v tvare YYYY-MM-DD HH:MM[:" +"ss[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"Hodnota „%(value)s“ je v správnom tvare (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]), ale je to neplatný dátum/čas." + +msgid "Date (with time)" +msgstr "Dátum (a čas)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "Hodnota „%(value)s“ musí byť desatinné číslo." + +msgid "Decimal number" +msgstr "Desatinné číslo" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"Hodnota „%(value)s“ má neplatný tvar. Musí byť v tvare [DD] [[HH:]MM:]ss[." +"uuuuuu]." + +msgid "Duration" +msgstr "Doba trvania" + +msgid "Email address" +msgstr "E-mailová adresa" + +msgid "File path" +msgstr "Cesta k súboru" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "Hodnota „%(value)s“ musí byť desatinné číslo." + +msgid "Floating point number" +msgstr "Číslo s plávajúcou desatinnou čiarkou" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "Hodnota „%(value)s“ musí byť celé číslo." + +msgid "Integer" +msgstr "Celé číslo" + +msgid "Big (8 byte) integer" +msgstr "Veľké celé číslo (8 bajtov)" + +msgid "Small integer" +msgstr "Malé celé číslo" + +msgid "IPv4 address" +msgstr "IPv4 adresa" + +msgid "IP address" +msgstr "IP adresa" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "Hodnota „%(value)s“ musí byť buď None, True alebo False." + +msgid "Boolean (Either True, False or None)" +msgstr "Logická hodnota (buď True, False alebo None)" + +msgid "Positive big integer" +msgstr "Veľké kladné celé číslo" + +msgid "Positive integer" +msgstr "Kladné celé číslo" + +msgid "Positive small integer" +msgstr "Malé kladné celé číslo" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Identifikátor (najviac %(max_length)s)" + +msgid "Text" +msgstr "Text" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"Hodnota „%(value)s“ má neplatný tvar. Musí byť v tvare HH:MM[:ss[.uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"Hodnota „%(value)s“ je v správnom tvare (HH:MM[:ss[.uuuuuu]]), ale je to " +"neplatný čas." + +msgid "Time" +msgstr "Čas" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Binárne údaje" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "„%(value)s“ nie je platné UUID." + +msgid "Universally unique identifier" +msgstr "Všeobecne jedinečný identifikátor" + +msgid "File" +msgstr "Súbor" + +msgid "Image" +msgstr "Obrázok" + +msgid "A JSON object" +msgstr "Objekt typu JSON" + +msgid "Value must be valid JSON." +msgstr "Hodnota musí byť v platnom formáte JSON." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "Inštancia modelu %(model)s s %(field)s %(value)r neexistuje." + +msgid "Foreign Key (type determined by related field)" +msgstr "Cudzí kľúč (typ určuje pole v relácii)" + +msgid "One-to-one relationship" +msgstr "Typ relácie: jedna k jednej" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "vzťah: %(from)s-%(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "vzťahy: %(from)s-%(to)s" + +msgid "Many-to-many relationship" +msgstr "Typ relácie: M ku N" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Toto pole je povinné." + +msgid "Enter a whole number." +msgstr "Zadajte celé číslo." + +msgid "Enter a valid date." +msgstr "Zadajte platný dátum." + +msgid "Enter a valid time." +msgstr "Zadajte platný čas." + +msgid "Enter a valid date/time." +msgstr "Zadajte platný dátum/čas." + +msgid "Enter a valid duration." +msgstr "Zadajte platnú dobu trvania." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Počet dní musí byť medzi {min_days} a {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Súbor nebol odoslaný. Skontrolujte typ kódovania vo formulári." + +msgid "No file was submitted." +msgstr "Žiaden súbor nebol odoslaný." + +msgid "The submitted file is empty." +msgstr "Odoslaný súbor je prázdny." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Uistite sa, že názov súboru má najviac %(max)d znak (má %(length)d)." +msgstr[1] "" +"Uistite sa, že názov súboru má najviac %(max)d znaky (má %(length)d)." +msgstr[2] "" +"Uistite sa, že názov súboru má najviac %(max)d znakov (má %(length)d)." +msgstr[3] "" +"Uistite sa, že názov súboru má najviac %(max)d znakov (má %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Odošlite prosím súbor alebo zaškrtnite políčko pre vymazanie vstupného poľa, " +"nie oboje." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Nahrajte platný obrázok. Súbor, ktorý ste odoslali nebol obrázok alebo bol " +"poškodený." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Vyberte platnú voľbu. %(value)s nepatrí medzi dostupné možnosti." + +msgid "Enter a list of values." +msgstr "Zadajte zoznam hodnôt." + +msgid "Enter a complete value." +msgstr "Zadajte úplnú hodnotu." + +msgid "Enter a valid UUID." +msgstr "Zadajte platné UUID." + +msgid "Enter a valid JSON." +msgstr "Zadajte platný JSON." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Skryté pole %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"Dáta ManagementForm chýbajú alebo boli zmanipulované. Chýbajúce polia: " +"%(field_names)s. Možno budete musieť túto chybu nahlásiť, ak sa bude naďalej " +"vyskytovať." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Prosím, odošlite najviac %(num)d formulár." +msgstr[1] "Prosím, odošlite najviac %(num)d formuláre." +msgstr[2] "Prosím, odošlite najviac %(num)d formulárov." +msgstr[3] "Prosím, odošlite najviac %(num)d formulárov." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Prosím, odošlite aspoň %(num)d formulár." +msgstr[1] "Prosím, odošlite aspoň %(num)d formuláre." +msgstr[2] "Prosím, odošlite aspoň %(num)d formulárov." +msgstr[3] "Prosím, odošlite aspoň %(num)d formulárov." + +msgid "Order" +msgstr "Poradie" + +msgid "Delete" +msgstr "Odstrániť" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Prosím, opravte duplicitné údaje pre %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Údaje pre %(field)s musia byť jedinečné, prosím, opravte duplikáty." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Údaje pre %(field_name)s musia byť jedinečné pre %(lookup)s v " +"%(date_field)s, prosím, opravte duplikáty." + +msgid "Please correct the duplicate values below." +msgstr "Prosím, opravte nižšie uvedené duplicitné hodnoty. " + +msgid "The inline value did not match the parent instance." +msgstr "Vnorená hodnota sa nezhoduje s nadradenou inštanciou." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Vyberte platnú možnosť. Vybraná položka nepatrí medzi dostupné možnosti." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "„%(pk)s“ nie je platná hodnota." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"Hodnota %(datetime)s v časovej zóne %(current_timezone)s sa nedá " +"interpretovať; môže byť nejednoznačná alebo nemusí existovať." + +msgid "Clear" +msgstr "Vymazať" + +msgid "Currently" +msgstr "Súčasne" + +msgid "Change" +msgstr "Zmeniť" + +msgid "Unknown" +msgstr "Neznámy" + +msgid "Yes" +msgstr "Áno" + +msgid "No" +msgstr "Nie" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "áno,nie,možno" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d bajt" +msgstr[1] "%(size)d bajty" +msgstr[2] "%(size)d bajtov" +msgstr[3] "%(size)d bajtov" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "popoludní" + +msgid "a.m." +msgstr "predpoludním" + +msgid "PM" +msgstr "popoludní" + +msgid "AM" +msgstr "predpoludním" + +msgid "midnight" +msgstr "polnoc" + +msgid "noon" +msgstr "poludnie" + +msgid "Monday" +msgstr "pondelok" + +msgid "Tuesday" +msgstr "utorok" + +msgid "Wednesday" +msgstr "streda" + +msgid "Thursday" +msgstr "štvrtok" + +msgid "Friday" +msgstr "piatok" + +msgid "Saturday" +msgstr "sobota" + +msgid "Sunday" +msgstr "nedeľa" + +msgid "Mon" +msgstr "po" + +msgid "Tue" +msgstr "ut" + +msgid "Wed" +msgstr "st" + +msgid "Thu" +msgstr "št" + +msgid "Fri" +msgstr "pi" + +msgid "Sat" +msgstr "so" + +msgid "Sun" +msgstr "ne" + +msgid "January" +msgstr "január" + +msgid "February" +msgstr "február" + +msgid "March" +msgstr "marec" + +msgid "April" +msgstr "apríl" + +msgid "May" +msgstr "máj" + +msgid "June" +msgstr "jún" + +msgid "July" +msgstr "júl" + +msgid "August" +msgstr "august" + +msgid "September" +msgstr "september" + +msgid "October" +msgstr "október" + +msgid "November" +msgstr "november" + +msgid "December" +msgstr "december" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "apr" + +msgid "may" +msgstr "máj" + +msgid "jun" +msgstr "jún" + +msgid "jul" +msgstr "júl" + +msgid "aug" +msgstr "aug" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "okt" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dec" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "mar." + +msgctxt "abbrev. month" +msgid "April" +msgstr "apr." + +msgctxt "abbrev. month" +msgid "May" +msgstr "máj" + +msgctxt "abbrev. month" +msgid "June" +msgstr "jún" + +msgctxt "abbrev. month" +msgid "July" +msgstr "júl" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "aug." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "sep." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "okt." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "dec." + +msgctxt "alt. month" +msgid "January" +msgstr "január" + +msgctxt "alt. month" +msgid "February" +msgstr "február" + +msgctxt "alt. month" +msgid "March" +msgstr "marec" + +msgctxt "alt. month" +msgid "April" +msgstr "apríl" + +msgctxt "alt. month" +msgid "May" +msgstr "máj" + +msgctxt "alt. month" +msgid "June" +msgstr "jún" + +msgctxt "alt. month" +msgid "July" +msgstr "júl" + +msgctxt "alt. month" +msgid "August" +msgstr "august" + +msgctxt "alt. month" +msgid "September" +msgstr "september" + +msgctxt "alt. month" +msgid "October" +msgstr "október" + +msgctxt "alt. month" +msgid "November" +msgstr "november" + +msgctxt "alt. month" +msgid "December" +msgstr "december" + +msgid "This is not a valid IPv6 address." +msgstr "Toto nieje platná IPv6 adresa." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "alebo" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d rok" +msgstr[1] "%(num)d roky" +msgstr[2] "%(num)d rokov" +msgstr[3] "%(num)d rokov" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mesiac" +msgstr[1] "%(num)d mesiace" +msgstr[2] "%(num)d mesiacov" +msgstr[3] "%(num)d mesiacov" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d týždeň" +msgstr[1] "%(num)d týždne" +msgstr[2] "%(num)d týždňov" +msgstr[3] "%(num)d týždňov" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d deň" +msgstr[1] "%(num)d dni" +msgstr[2] "%(num)d dní" +msgstr[3] "%(num)d dní" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hodina" +msgstr[1] "%(num)d hodiny" +msgstr[2] "%(num)d hodín" +msgstr[3] "%(num)d hodiny" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minúta" +msgstr[1] "%(num)d minúty" +msgstr[2] "%(num)d minút" +msgstr[3] "%(num)d minúty" + +msgid "Forbidden" +msgstr "Zakázané (Forbidden)" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF verifikázia zlyhala. Požiadavka bola prerušená." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Túto správu vidíte, pretože táto stránka na protokole HTTPS vyžaduje, aby " +"váš prehliadač zaslal hlavičku „Referer„, k čomu nedošlo. Táto hlavička je " +"vyžadovaná z bezpečnostných dôvodov pre kontrolu toho, že sa prehliadača " +"nezmocnila tretia strana." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Ak ste vo vašom prehliadači vypli hlavičky „Referer“, tak ich prosím " +"zapnite, alebo aspoň pre túto stránku, alebo pre HTTPS pripojenia, alebo pre " +"požiadavky „same-origin“." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Ak používate tag , alebo " +"vkladáte hlavičku „Referrer-Policy: no-referrer“, prosím odstránte ich. " +"Ochrana CSRF vyžaduje hlavičku „Referer“ na striktnú kontrolu. Ak máte obavy " +"o súkromie, použite alternatívy ako pre linky na " +"iné stránky." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Túto správu vidíte, pretože táto lokalita vyžaduje CSRF cookie pri " +"odosielaní formulárov. Toto cookie je potrebné na zabezpečenie toho, že váš " +"prehliadač nie je zneužitý - „hijack“." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Ak ste vypli cookies vo vašom prehliadači, tak ich prosím zapnite, aspoň pre " +"túto stránku, alebo pre požiadavky „same-origin“." + +msgid "More information is available with DEBUG=True." +msgstr "Viac informácií bude dostupných s DEBUG=True." + +msgid "No year specified" +msgstr "Nešpecifikovaný rok" + +msgid "Date out of range" +msgstr "Dátum je mimo rozsahu" + +msgid "No month specified" +msgstr "Nešpecifikovaný mesiac" + +msgid "No day specified" +msgstr "Nešpecifikovaný deň" + +msgid "No week specified" +msgstr "Nešpecifikovaný týždeň" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "%(verbose_name_plural)s nie sú dostupné" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Budúce %(verbose_name_plural)s nie sú dostupné pretože %(class_name)s." +"allow_future má hodnotu False. " + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Neplatný dátumový reťazec „%(datestr)s“ pre formát „%(format)s“" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "" +"Nebol nájdený žiadny %(verbose_name)s zodpovedajúci databázovému dopytu" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" +"Stránka nemá hodnotu „last“ a taktiež nie je možné prekonvertovať hodnotu na " +"celé číslo." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Nesprávna stránka (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Zoznam je prázdny a hodnota „%(class_name)s.allow_empty“ je False." + +msgid "Directory indexes are not allowed here." +msgstr "Výpis adresárov tu nieje povolený." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "„%(path)s“ neexistuje" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Výpis %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Inštalácia prebehla úspešne! Gratulujeme!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Zobraziť poznámky k vydaniu pre Django " +"%(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Táto stránka sa zobrazuje pretože máte DEBUG=True v súbore s nastaveniami a nie sú " +"nakonfigurované žiadne URL." + +msgid "Django Documentation" +msgstr "Dokumentácia Django" + +msgid "Topics, references, & how-to’s" +msgstr "Témy, referencie a návody" + +msgid "Tutorial: A Polling App" +msgstr "Tutoriál: Aplikácia „Hlasovania“" + +msgid "Get started with Django" +msgstr "Začíname s Django" + +msgid "Django Community" +msgstr "Komunita Django" + +msgid "Connect, get help, or contribute" +msgstr "Spojte sa, získajte pomoc, alebo prispejte" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sk/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sk/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sk/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sk/formats.py new file mode 100644 index 0000000..31d4912 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sk/formats.py @@ -0,0 +1,30 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j. F Y" +TIME_FORMAT = "G:i" +DATETIME_FORMAT = "j. F Y G:i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j. F" +SHORT_DATE_FORMAT = "d.m.Y" +SHORT_DATETIME_FORMAT = "d.m.Y G:i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d.%m.%Y", # '25.10.2006' + "%d.%m.%y", # '25.10.06' + "%y-%m-%d", # '06-10-25' + # "%d. %B %Y", # '25. October 2006' + # "%d. %b. %Y", # '25. Oct. 2006' +] +DATETIME_INPUT_FORMATS = [ + "%d.%m.%Y %H:%M:%S", # '25.10.2006 14:30:59' + "%d.%m.%Y %H:%M:%S.%f", # '25.10.2006 14:30:59.000200' + "%d.%m.%Y %H:%M", # '25.10.2006 14:30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "\xa0" # non-breaking space +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..10e198e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sl/LC_MESSAGES/django.po new file mode 100644 index 0000000..4b5f932 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sl/LC_MESSAGES/django.po @@ -0,0 +1,1351 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Andrej Marsetič, 2022-2023 +# iElectric , 2011-2012 +# Jannis Leidel , 2011 +# Jure Cuhalev , 2012-2013 +# Marko Zabreznik , 2016 +# Primoz Verdnik , 2017 +# zejn , 2013,2016-2017 +# zejn , 2011-2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Andrej Marsetič, 2022-2023\n" +"Language-Team: Slovenian (http://app.transifex.com/django/django/language/" +"sl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sl\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || " +"n%100==4 ? 2 : 3);\n" + +msgid "Afrikaans" +msgstr "Afrikanščina" + +msgid "Arabic" +msgstr "Arabščina" + +msgid "Algerian Arabic" +msgstr "alžirska arabščina" + +msgid "Asturian" +msgstr "Asturijski jezik" + +msgid "Azerbaijani" +msgstr "Azerbajdžanščina" + +msgid "Bulgarian" +msgstr "Bolgarščina" + +msgid "Belarusian" +msgstr "Belorusko" + +msgid "Bengali" +msgstr "Bengalščina" + +msgid "Breton" +msgstr "Bretonščina" + +msgid "Bosnian" +msgstr "Bosanščina" + +msgid "Catalan" +msgstr "Katalonščina" + +msgid "Central Kurdish (Sorani)" +msgstr "" + +msgid "Czech" +msgstr "Češčina" + +msgid "Welsh" +msgstr "Valežanski jezik" + +msgid "Danish" +msgstr "Danščina" + +msgid "German" +msgstr "Nemščina" + +msgid "Lower Sorbian" +msgstr "Dolnjelužiška srbščina" + +msgid "Greek" +msgstr "Grščina" + +msgid "English" +msgstr "Angleščina" + +msgid "Australian English" +msgstr "Avstralska angleščina" + +msgid "British English" +msgstr "Britanska Angleščina" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Španščina" + +msgid "Argentinian Spanish" +msgstr "Argentinska španščina" + +msgid "Colombian Spanish" +msgstr "Kolumbijska španščina" + +msgid "Mexican Spanish" +msgstr "Mehiška španščina" + +msgid "Nicaraguan Spanish" +msgstr "Nikaragvijska španščina" + +msgid "Venezuelan Spanish" +msgstr "Španščina (Venezuela)" + +msgid "Estonian" +msgstr "Estonščina" + +msgid "Basque" +msgstr "Baskovščina" + +msgid "Persian" +msgstr "Perzijščina" + +msgid "Finnish" +msgstr "Finščina" + +msgid "French" +msgstr "Francoščina" + +msgid "Frisian" +msgstr "Frizijščina" + +msgid "Irish" +msgstr "Irščina" + +msgid "Scottish Gaelic" +msgstr "Škotska gelščina" + +msgid "Galician" +msgstr "Galičanski jezik" + +msgid "Hebrew" +msgstr "Hebrejski jezik" + +msgid "Hindi" +msgstr "Hindujščina" + +msgid "Croatian" +msgstr "Hrvaščina" + +msgid "Upper Sorbian" +msgstr "Gornjelužiška srbščina" + +msgid "Hungarian" +msgstr "Madžarščina" + +msgid "Armenian" +msgstr "armenščina" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonezijski" + +msgid "Igbo" +msgstr "" + +msgid "Ido" +msgstr "Jezik Ido" + +msgid "Icelandic" +msgstr "Islandski jezik" + +msgid "Italian" +msgstr "Italijanščina" + +msgid "Japanese" +msgstr "Japonščina" + +msgid "Georgian" +msgstr "Gruzijščina" + +msgid "Kabyle" +msgstr "Kabilski jezik" + +msgid "Kazakh" +msgstr "Kazaščina" + +msgid "Khmer" +msgstr "Kmerščina" + +msgid "Kannada" +msgstr "Kanareščina" + +msgid "Korean" +msgstr "Korejščina" + +msgid "Kyrgyz" +msgstr "" + +msgid "Luxembourgish" +msgstr "Luksemburščina" + +msgid "Lithuanian" +msgstr "Litvanščina" + +msgid "Latvian" +msgstr "Latvijščina" + +msgid "Macedonian" +msgstr "Makedonščina" + +msgid "Malayalam" +msgstr "Malajalščina" + +msgid "Mongolian" +msgstr "Mongolščina" + +msgid "Marathi" +msgstr "Jezik Marathi" + +msgid "Malay" +msgstr "" + +msgid "Burmese" +msgstr "Burmanski jezik" + +msgid "Norwegian Bokmål" +msgstr "Norveški jezik" + +msgid "Nepali" +msgstr "Nepalščina" + +msgid "Dutch" +msgstr "Nizozemščina" + +msgid "Norwegian Nynorsk" +msgstr "Norveščina Nynorsk" + +msgid "Ossetic" +msgstr "Osetski jezik" + +msgid "Punjabi" +msgstr "Pandžabščina" + +msgid "Polish" +msgstr "Poljščina" + +msgid "Portuguese" +msgstr "Portugalščina" + +msgid "Brazilian Portuguese" +msgstr "Brazilska portugalščina" + +msgid "Romanian" +msgstr "Romunščina" + +msgid "Russian" +msgstr "Ruščina" + +msgid "Slovak" +msgstr "Slovaščina" + +msgid "Slovenian" +msgstr "Slovenščina" + +msgid "Albanian" +msgstr "Albanščina" + +msgid "Serbian" +msgstr "Srbščina" + +msgid "Serbian Latin" +msgstr "Srbščina v latinici" + +msgid "Swedish" +msgstr "Švedščina" + +msgid "Swahili" +msgstr "Svahili" + +msgid "Tamil" +msgstr "Tamilščina" + +msgid "Telugu" +msgstr "Teluščina" + +msgid "Tajik" +msgstr "" + +msgid "Thai" +msgstr "Tajski jezik" + +msgid "Turkmen" +msgstr "" + +msgid "Turkish" +msgstr "Turščina" + +msgid "Tatar" +msgstr "Tatarščina" + +msgid "Udmurt" +msgstr "Udmurski jezik" + +msgid "Uyghur" +msgstr "" + +msgid "Ukrainian" +msgstr "Ukrajinščina" + +msgid "Urdu" +msgstr "Jezik Urdu" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "Vietnamščina" + +msgid "Simplified Chinese" +msgstr "Poenostavljena kitajščina" + +msgid "Traditional Chinese" +msgstr "Tradicionalna kitajščina" + +msgid "Messages" +msgstr "Sporočila" + +msgid "Site Maps" +msgstr "Zemljevid spletnega mesta" + +msgid "Static Files" +msgstr "Statične datoteke" + +msgid "Syndication" +msgstr "Sindiciranje" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Število te strani ni naravno število" + +msgid "That page number is less than 1" +msgstr "Število te strani je manj kot 1" + +msgid "That page contains no results" +msgstr "Ta stran nima zadetkov" + +msgid "Enter a valid value." +msgstr "Vnesite veljavno vrednost." + +msgid "Enter a valid URL." +msgstr "Vnesite veljaven URL naslov." + +msgid "Enter a valid integer." +msgstr "Vnesite veljavno celo število." + +msgid "Enter a valid email address." +msgstr "Vnesite veljaven e-poštni naslov." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Vnesite veljaven IPv4 naslov." + +msgid "Enter a valid IPv6 address." +msgstr "Vnesite veljaven IPv6 naslov." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Vnesite veljaven IPv4 ali IPv6 naslov." + +msgid "Enter only digits separated by commas." +msgstr "Vnesite samo števila, ločena z vejicami." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Poskrbite, da bo ta vrednost %(limit_value)s. Trenutno je %(show_value)s." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Poskrbite, da bo ta vrednost manj kot ali natanko %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Poskrbite, da bo ta vrednost večja ali enaka %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Preverite, da ima ta vrednost vsaj %(limit_value)d znak (trenutno ima " +"%(show_value)d)." +msgstr[1] "" +"Preverite, da ima ta vrednost vsaj %(limit_value)d znaka (trenutno ima " +"%(show_value)d)." +msgstr[2] "" +"Preverite, da ima ta vrednost vsaj %(limit_value)d znake (trenutno ima " +"%(show_value)d)." +msgstr[3] "" +"Preverite, da ima ta vrednost vsaj %(limit_value)d znakov (trenutno ima " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Preverite, da ima ta vrednost največ %(limit_value)d znak (trenutno ima " +"%(show_value)d)." +msgstr[1] "" +"Preverite, da ima ta vrednost največ %(limit_value)d znaka (trenutno ima " +"%(show_value)d)." +msgstr[2] "" +"Preverite, da ima ta vrednost največ %(limit_value)d znake (trenutno ima " +"%(show_value)d)." +msgstr[3] "" +"Preverite, da ima ta vrednost največ %(limit_value)d znakov (trenutno ima " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Vnesite število." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Poskrbite, da skupno ne bo več kot %(max)s števka." +msgstr[1] "Poskrbite, da skupno ne bosta več kot %(max)s števki." +msgstr[2] "Poskrbite, da skupno ne bojo več kot %(max)s števke." +msgstr[3] "Poskrbite, da skupno ne bo več kot %(max)s števk." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Poskrbite, da skupno ne bo več kot %(max)s decimalnih mesto." +msgstr[1] "Poskrbite, da skupno ne bosta več kot %(max)s decimalnih mesti." +msgstr[2] "Poskrbite, da skupno ne bo več kot %(max)s decimalnih mest." +msgstr[3] "Poskrbite, da skupno ne bo več kot %(max)s decimalnih mest." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Poskrbite, da skupno ne bo več kot %(max)s števka pred decimalno vejico." +msgstr[1] "" +"Poskrbite, da skupno ne bosta več kot %(max)s števki pred decimalno vejico." +msgstr[2] "" +"Poskrbite, da skupno ne bo več kot %(max)s števk pred decimalno vejico." +msgstr[3] "" +"Poskrbite, da skupno ne bo več kot %(max)s števk pred decimalno vejico." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "Znak null ni dovoljen." + +msgid "and" +msgstr "in" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s s tem %(field_labels)s že obstaja." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Vrednost %(value)r ni veljavna izbira." + +msgid "This field cannot be null." +msgstr "To polje ne more biti prazno." + +msgid "This field cannot be blank." +msgstr "To polje ne more biti prazno." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s s tem %(field_label)s že obstaja." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s mora biti enolična za %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Polje tipa: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "“%(value)s” vrednost mora biti Da ali Ne." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "Boolova vrednost (True ali False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Niz znakov (vse do %(max_length)s)" + +msgid "String (unlimited)" +msgstr "" + +msgid "Comma-separated integers" +msgstr "Z vejico ločena cela števila (integer)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"“%(value)s” vrednost ima neveljavno obliko datuma. Biti mora v obliki LLLL-" +"MM-DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"“%(value)s” vrednost ima pravilno obliko (LLLL-MM-DD), vendar je neveljaven " +"datum." + +msgid "Date (without time)" +msgstr "Datum (brez ure)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Datum (z uro)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Decimalno število" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "Trajanje" + +msgid "Email address" +msgstr "E-poštni naslov" + +msgid "File path" +msgstr "Pot do datoteke" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "“%(value)s” vrednost mora biti decimalno število." + +msgid "Floating point number" +msgstr "Število s plavajočo vejico" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "“%(value)s” vrednost mora biti celo število." + +msgid "Integer" +msgstr "Celo število (integer)" + +msgid "Big (8 byte) integer" +msgstr "Velika (8 bajtna) cela števila " + +msgid "Small integer" +msgstr "Celo število" + +msgid "IPv4 address" +msgstr "IPv4 naslov" + +msgid "IP address" +msgstr "IP naslov" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "“%(value)s” vrednost mora biti Nič, Da ali Ne." + +msgid "Boolean (Either True, False or None)" +msgstr "Boolova vrednost (True, False ali None)" + +msgid "Positive big integer" +msgstr "Pozitivno veliko celo število" + +msgid "Positive integer" +msgstr "Pozitivno celo število" + +msgid "Positive small integer" +msgstr "Pozitivno celo število (do 64 tisoč)" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Okrajšava naslova (do največ %(max_length)s znakov)" + +msgid "Text" +msgstr "Besedilo" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Čas" + +msgid "URL" +msgstr "URL (spletni naslov)" + +msgid "Raw binary data" +msgstr "Surovi binarni podatki" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "Datoteka" + +msgid "Image" +msgstr "Slika" + +msgid "A JSON object" +msgstr "JSON objekt" + +msgid "Value must be valid JSON." +msgstr "Vrednost mora biti veljaven JSON." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" +"Instanca %(model)s s poljem %(field)s, ki ustreza %(value)r, ne obstaja." + +msgid "Foreign Key (type determined by related field)" +msgstr "Tuji ključ (tip odvisen od povezanega polja)" + +msgid "One-to-one relationship" +msgstr "Relacija ena-na-ena" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "Relacija %(from)s-%(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "Relacija %(from)s-%(to)s" + +msgid "Many-to-many relationship" +msgstr "Relacija več-na-več" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "To polje je obvezno." + +msgid "Enter a whole number." +msgstr "Vnesite celo število." + +msgid "Enter a valid date." +msgstr "Vnesite veljaven datum." + +msgid "Enter a valid time." +msgstr "Vnesite veljaven čas." + +msgid "Enter a valid date/time." +msgstr "Vnesite veljaven datum/čas." + +msgid "Enter a valid duration." +msgstr "Vnesite veljavno obdobje trajanja." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Datoteka ni bila poslana. Preverite nabor znakov v formi." + +msgid "No file was submitted." +msgstr "Poslali niste nobene datoteke." + +msgid "The submitted file is empty." +msgstr "Poslana datoteka je prazna." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Poskrbite, da bo imelo to ime datoteke največ %(max)d znak (trenutno ima " +"%(length)d)." +msgstr[1] "" +"Poskrbite, da bo imelo to ime datoteke največ %(max)d znaka (trenutno ima " +"%(length)d)." +msgstr[2] "" +"Poskrbite, da bo imelo to ime datoteke največ %(max)d znake (trenutno ima " +"%(length)d)." +msgstr[3] "" +"Poskrbite, da bo imelo to ime datoteke največ %(max)d znakov (trenutno ima " +"%(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Prosim oddaj datoteko ali izberi počisti okvir, ampak ne oboje hkrati." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Naložite veljavno sliko. Naložena datoteka ni bila slika ali pa je bila le-" +"ta okvarjena." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Izberite veljavno možnost. %(value)s ni med ponujenimi izbirami." + +msgid "Enter a list of values." +msgstr "Vnesite seznam vrednosti." + +msgid "Enter a complete value." +msgstr "Vnesite popolno vrednost." + +msgid "Enter a valid UUID." +msgstr "Vnesite veljaven UUID." + +msgid "Enter a valid JSON." +msgstr "Vnesite veljaven JSON." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Skrito polje %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +msgid "Order" +msgstr "Razvrsti" + +msgid "Delete" +msgstr "Izbriši" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Prosimo, odpravite podvojene vrednosti za %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Prosimo popravite podvojene vrednosti za %(field)s, ki morajo biti unikatne." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Prosimo popravite podvojene vrednosti za polje %(field_name)s, ki mora biti " +"edinstveno za %(lookup)s po %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Prosimo odpravite podvojene vrednosti spodaj." + +msgid "The inline value did not match the parent instance." +msgstr "Vrednost se ne ujema s povezanim vnosom." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Izberite veljavno možnost. Te možnosti ni med ponujenimi izbirami." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Počisti" + +msgid "Currently" +msgstr "Trenutno" + +msgid "Change" +msgstr "Spremeni" + +msgid "Unknown" +msgstr "Neznano" + +msgid "Yes" +msgstr "Da" + +msgid "No" +msgstr "Ne" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "da,ne,morda" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d bajt" +msgstr[1] "%(size)d bajta" +msgstr[2] "%(size)d bajti" +msgstr[3] "%(size)d bajtov" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "polnoč" + +msgid "noon" +msgstr "poldne" + +msgid "Monday" +msgstr "ponedeljek" + +msgid "Tuesday" +msgstr "torek" + +msgid "Wednesday" +msgstr "sreda" + +msgid "Thursday" +msgstr "četrtek" + +msgid "Friday" +msgstr "petek" + +msgid "Saturday" +msgstr "sobota" + +msgid "Sunday" +msgstr "nedelja" + +msgid "Mon" +msgstr "pon" + +msgid "Tue" +msgstr "tor" + +msgid "Wed" +msgstr "sre" + +msgid "Thu" +msgstr "čet" + +msgid "Fri" +msgstr "pet" + +msgid "Sat" +msgstr "sob" + +msgid "Sun" +msgstr "ned" + +msgid "January" +msgstr "januar" + +msgid "February" +msgstr "februar" + +msgid "March" +msgstr "marec" + +msgid "April" +msgstr "april" + +msgid "May" +msgstr "maj" + +msgid "June" +msgstr "junij" + +msgid "July" +msgstr "julij" + +msgid "August" +msgstr "avgust" + +msgid "September" +msgstr "september" + +msgid "October" +msgstr "oktober" + +msgid "November" +msgstr "november" + +msgid "December" +msgstr "december" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "apr" + +msgid "may" +msgstr "maj" + +msgid "jun" +msgstr "jun" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "avg" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "okt" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dec" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Jan" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Marec" + +msgctxt "abbrev. month" +msgid "April" +msgstr "April" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Maj" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Junij" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Julij" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Avg." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Sept." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Okt." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dec." + +msgctxt "alt. month" +msgid "January" +msgstr "Januar" + +msgctxt "alt. month" +msgid "February" +msgstr "Februar" + +msgctxt "alt. month" +msgid "March" +msgstr "Marec" + +msgctxt "alt. month" +msgid "April" +msgstr "April" + +msgctxt "alt. month" +msgid "May" +msgstr "Maj" + +msgctxt "alt. month" +msgid "June" +msgstr "Junij" + +msgctxt "alt. month" +msgid "July" +msgstr "Julij" + +msgctxt "alt. month" +msgid "August" +msgstr "Avgust" + +msgctxt "alt. month" +msgid "September" +msgstr "September" + +msgctxt "alt. month" +msgid "October" +msgstr "Oktober" + +msgctxt "alt. month" +msgid "November" +msgstr "November" + +msgctxt "alt. month" +msgid "December" +msgstr "December" + +msgid "This is not a valid IPv6 address." +msgstr "To ni veljaven IPv6 naslov." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "ali" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d leto" +msgstr[1] "%(num)d leti" +msgstr[2] "%(num)d let" +msgstr[3] "%(num)d let" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mesec" +msgstr[1] "%(num)d meseca " +msgstr[2] "%(num)d mesecev" +msgstr[3] "%(num)d mesecev" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d teden" +msgstr[1] "%(num)d tedna" +msgstr[2] "%(num)d tednov" +msgstr[3] "%(num)d tednov" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dan" +msgstr[1] "%(num)d dneva" +msgstr[2] "%(num)d dni" +msgstr[3] "%(num)d dni" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d uro" +msgstr[1] "%(num)d uri" +msgstr[2] "%(num)d ure" +msgstr[3] "%(num)d ur" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuto" +msgstr[1] "%(num)d minuti" +msgstr[2] "%(num)d minute" +msgstr[3] "%(num)d minut" + +msgid "Forbidden" +msgstr "Prepovedano" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF preverjanje ni uspelo. Zahtevek preklican." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"To obvestilo vidite, ker ta spletna stran zahteva CSRF piškotek, ko " +"pošiljate obrazce. Piškotek je potreben zaradi varnosti, da se zagotovi, da " +"ste zahtevek res naredili vi." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Če ste brskalnik konfigurirali tako, da onemogoča piškotke, jih znova " +"omogočite za to spletno mesto ali za zahteve »istega izvora«." + +msgid "More information is available with DEBUG=True." +msgstr "Več informacij je na voljo, če nastavite DEBUG=True." + +msgid "No year specified" +msgstr "Leto ni vnešeno" + +msgid "Date out of range" +msgstr "Datum ni znotraj veljavnega obsega." + +msgid "No month specified" +msgstr "Mesec ni vnešen" + +msgid "No day specified" +msgstr "Dan ni vnešen" + +msgid "No week specified" +msgstr "Teden ni vnešen" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Na voljo ni noben %(verbose_name_plural)s" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Prihodnje %(verbose_name_plural)s niso na voljo, ker je vrednost " +"%(class_name)s.allow_future False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Noben %(verbose_name)s ne ustreza poizvedbi" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Stran ni »zadnja«, niti je ni mogoče pretvoriti v število." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Neveljavna stran (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Prikaz vsebine mape ni dovoljen." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "“%(path)s” ne obstaja" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Vsebina mape %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Namestitev se je uspešno izvedla! Čestitke!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Oglejte si obvestila ob izdaji za Django " +"%(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"To stran vidite, ker imate nastavljeno DEBUG=True v vaši settings.py datoteki in ker nimate " +"nastavljenih URL-jev." + +msgid "Django Documentation" +msgstr "Django Dokumentacija" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "Vodič: aplikacija anketa" + +msgid "Get started with Django" +msgstr "Začnite z Djangom" + +msgid "Django Community" +msgstr "Django Skupnost" + +msgid "Connect, get help, or contribute" +msgstr "Spoznajte nove ljudi, poiščite pomoč in prispevajte " diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sl/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sl/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sl/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sl/formats.py new file mode 100644 index 0000000..c3e96bb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sl/formats.py @@ -0,0 +1,44 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "d. F Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = "j. F Y. H:i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j. F" +SHORT_DATE_FORMAT = "j. M. Y" +SHORT_DATETIME_FORMAT = "j.n.Y. H:i" +FIRST_DAY_OF_WEEK = 0 + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d.%m.%Y", # '25.10.2006' + "%d.%m.%y", # '25.10.06' + "%d-%m-%Y", # '25-10-2006' + "%d. %m. %Y", # '25. 10. 2006' + "%d. %m. %y", # '25. 10. 06' +] + +DATETIME_INPUT_FORMATS = [ + "%d.%m.%Y %H:%M:%S", # '25.10.2006 14:30:59' + "%d.%m.%Y %H:%M:%S.%f", # '25.10.2006 14:30:59.000200' + "%d.%m.%Y %H:%M", # '25.10.2006 14:30' + "%d.%m.%y %H:%M:%S", # '25.10.06 14:30:59' + "%d.%m.%y %H:%M:%S.%f", # '25.10.06 14:30:59.000200' + "%d.%m.%y %H:%M", # '25.10.06 14:30' + "%d-%m-%Y %H:%M:%S", # '25-10-2006 14:30:59' + "%d-%m-%Y %H:%M:%S.%f", # '25-10-2006 14:30:59.000200' + "%d-%m-%Y %H:%M", # '25-10-2006 14:30' + "%d. %m. %Y %H:%M:%S", # '25. 10. 2006 14:30:59' + "%d. %m. %Y %H:%M:%S.%f", # '25. 10. 2006 14:30:59.000200' + "%d. %m. %Y %H:%M", # '25. 10. 2006 14:30' + "%d. %m. %y %H:%M:%S", # '25. 10. 06 14:30:59' + "%d. %m. %y %H:%M:%S.%f", # '25. 10. 06 14:30:59.000200' + "%d. %m. %y %H:%M", # '25. 10. 06 14:30' +] + +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sq/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sq/LC_MESSAGES/django.mo new file mode 100644 index 0000000..44c1348 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sq/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sq/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sq/LC_MESSAGES/django.po new file mode 100644 index 0000000..a58abd1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sq/LC_MESSAGES/django.po @@ -0,0 +1,1346 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Besnik Bleta , 2011-2014 +# Besnik Bleta , 2020-2023 +# Besnik Bleta , 2015-2019 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Besnik Bleta , 2020-2023\n" +"Language-Team: Albanian (http://app.transifex.com/django/django/language/" +"sq/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sq\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Afrikaans" + +msgid "Arabic" +msgstr "Arabe" + +msgid "Algerian Arabic" +msgstr "Arabishte Algjeriane" + +msgid "Asturian" +msgstr "Asturiase" + +msgid "Azerbaijani" +msgstr "Azerbaixhanase" + +msgid "Bulgarian" +msgstr "Bulgare" + +msgid "Belarusian" +msgstr "Bjelloruse" + +msgid "Bengali" +msgstr "Bengaleze" + +msgid "Breton" +msgstr "Bretone" + +msgid "Bosnian" +msgstr "Boshnjake" + +msgid "Catalan" +msgstr "Katalane" + +msgid "Central Kurdish (Sorani)" +msgstr "Kurdishte e Qendrës (Sorani)" + +msgid "Czech" +msgstr "Çeke" + +msgid "Welsh" +msgstr "Uellsiane" + +msgid "Danish" +msgstr "Daneze" + +msgid "German" +msgstr "Gjermane" + +msgid "Lower Sorbian" +msgstr "Sorbiane e Poshtme" + +msgid "Greek" +msgstr "Greke" + +msgid "English" +msgstr "Angleze" + +msgid "Australian English" +msgstr "Angleze Australiane" + +msgid "British English" +msgstr "Angleze Britanike" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Spanjolle" + +msgid "Argentinian Spanish" +msgstr "Spanjolle Argjentinase" + +msgid "Colombian Spanish" +msgstr "Spanjolle Kolumbiane" + +msgid "Mexican Spanish" +msgstr "Spanjolle Meksikane" + +msgid "Nicaraguan Spanish" +msgstr "Spanjolle Nikaraguane" + +msgid "Venezuelan Spanish" +msgstr "Spanjolle Venezuelane" + +msgid "Estonian" +msgstr "Estoneze" + +msgid "Basque" +msgstr "Baske" + +msgid "Persian" +msgstr "Persiane" + +msgid "Finnish" +msgstr "Finlandeze" + +msgid "French" +msgstr "Frënge" + +msgid "Frisian" +msgstr "Frisiane" + +msgid "Irish" +msgstr "Irlandeze" + +msgid "Scottish Gaelic" +msgstr "Skoceze Gaelike" + +msgid "Galician" +msgstr "Galike" + +msgid "Hebrew" +msgstr "Hebraishte" + +msgid "Hindi" +msgstr "Indiane" + +msgid "Croatian" +msgstr "Kroate" + +msgid "Upper Sorbian" +msgstr "Sorbiane e Sipërme" + +msgid "Hungarian" +msgstr "Hungareze" + +msgid "Armenian" +msgstr "Armenisht" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indoneziane" + +msgid "Igbo" +msgstr "Igbo" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Islandeze" + +msgid "Italian" +msgstr "Italiane" + +msgid "Japanese" +msgstr "Japoneze" + +msgid "Georgian" +msgstr "Gjeorgjiane" + +msgid "Kabyle" +msgstr "Kabilase" + +msgid "Kazakh" +msgstr "Kazake" + +msgid "Khmer" +msgstr "Khmere" + +msgid "Kannada" +msgstr "Kannada" + +msgid "Korean" +msgstr "Koreane" + +msgid "Kyrgyz" +msgstr "Kirgize" + +msgid "Luxembourgish" +msgstr "Luksemburgase" + +msgid "Lithuanian" +msgstr "Lituaneze" + +msgid "Latvian" +msgstr "Letoneze" + +msgid "Macedonian" +msgstr "Maqedone" + +msgid "Malayalam" +msgstr "Malajalame" + +msgid "Mongolian" +msgstr "Mongoliane" + +msgid "Marathi" +msgstr "Marati" + +msgid "Malay" +msgstr "" + +msgid "Burmese" +msgstr "Burmeze" + +msgid "Norwegian Bokmål" +msgstr "Norvegjeze Bokmal" + +msgid "Nepali" +msgstr "Nepaleze" + +msgid "Dutch" +msgstr "Holandeze" + +msgid "Norwegian Nynorsk" +msgstr "Norvegjeze Nynorsk" + +msgid "Ossetic" +msgstr "Osetishte" + +msgid "Punjabi" +msgstr "Panxhabe" + +msgid "Polish" +msgstr "Polake" + +msgid "Portuguese" +msgstr "Portugeze" + +msgid "Brazilian Portuguese" +msgstr "Portugeze Braziliane" + +msgid "Romanian" +msgstr "Rumune" + +msgid "Russian" +msgstr "Ruse" + +msgid "Slovak" +msgstr "Sllovake " + +msgid "Slovenian" +msgstr "Slovene" + +msgid "Albanian" +msgstr "Shqipe" + +msgid "Serbian" +msgstr "Serbe" + +msgid "Serbian Latin" +msgstr "Serbe Latine" + +msgid "Swedish" +msgstr "Suedeze" + +msgid "Swahili" +msgstr "Swahili" + +msgid "Tamil" +msgstr "Tamileze" + +msgid "Telugu" +msgstr "Telugu" + +msgid "Tajik" +msgstr "Taxhike" + +msgid "Thai" +msgstr "Tajlandeze" + +msgid "Turkmen" +msgstr "Turkmene" + +msgid "Turkish" +msgstr "Turke" + +msgid "Tatar" +msgstr "Tatare" + +msgid "Udmurt" +msgstr "Udmurt" + +msgid "Uyghur" +msgstr "Ujgure" + +msgid "Ukrainian" +msgstr "Ukrainase" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "Uzbeke" + +msgid "Vietnamese" +msgstr "Vietnameze" + +msgid "Simplified Chinese" +msgstr "Kineze e Thjeshtuar" + +msgid "Traditional Chinese" +msgstr "Kineze Tradicionale" + +msgid "Messages" +msgstr "Mesazhe" + +msgid "Site Maps" +msgstr "Harta Sajti" + +msgid "Static Files" +msgstr "Kartela Statike" + +msgid "Syndication" +msgstr "" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Ai numër faqeje s’është numër i plotë" + +msgid "That page number is less than 1" +msgstr "Ai numër faqeje është më i vogël se 1" + +msgid "That page contains no results" +msgstr "Ajo faqe s’përmban përfundime" + +msgid "Enter a valid value." +msgstr "Jepni një vlerë të vlefshme." + +msgid "Enter a valid URL." +msgstr "Jepni një URL të vlefshme." + +msgid "Enter a valid integer." +msgstr "Jepni një numër të plotë të vlefshëm." + +msgid "Enter a valid email address." +msgstr "Jepni një adresë email të vlefshme." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Jepni një “slug” të vlefshëm, të përbërë nga shkronja, numra, nëvija ose " +"vija në mes." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Jepni një “slug” të vlefshëm, të përbërë nga shkronja, numra, nënvija ose " +"vija ndarëse Unikod." + +msgid "Enter a valid IPv4 address." +msgstr "Jepni një adresë IPv4 të vlefshme." + +msgid "Enter a valid IPv6 address." +msgstr "Jepni një adresë IPv6 të vlefshme." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Jepni një adresë IPv4 ose IPv6 të vlefshme." + +msgid "Enter only digits separated by commas." +msgstr "Jepni vetëm shifra të ndara nga presje." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Siguroni që kjo vlerë të jetë %(limit_value)s (është %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Siguroni që kjo vlerë të jetë më e vogël ose baras me %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Siguroni që kjo vlerë është më e madhe ose baras me %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" +"Garantoni që vlera të jetë një shumëfish i madhësisë së hapit " +"%(limit_value)s." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"Garantoni që kjo vlerë të jetë një shumëfish i madhësisë %(limit_value)s, " +"duke filluar nga %(offset)s, p.sh., %(offset)s, %(valid_value1)s, " +"%(valid_value2)s, e me radhë." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Sigurohuni që kjo vlerë ka të paktën %(limit_value)d shenjë (ka " +"%(show_value)d)." +msgstr[1] "" +"Sigurohuni që kjo vlerë ka të paktën %(limit_value)d shenja (ka " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Sigurohuni që kjo vlerë ka të shumtën %(limit_value)d shenjë (ka " +"%(show_value)d)." +msgstr[1] "" +"Sigurohuni që kjo vlerë ka të shumtën %(limit_value)d shenja (ka " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Jepni një numër." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Sigurohuni që s’ka më tepër se %(max)s shifër gjithsej." +msgstr[1] "Sigurohuni që s’ka më tepër se %(max)s shifra gjithsej." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Sigurohuni që s’ka më shumë se %(max)s vend dhjetor." +msgstr[1] "Sigurohuni që s’ka më shumë se %(max)s vende dhjetore." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Sigurohuni që s’ka më tepër se %(max)s shifër para presjes dhjetore." +msgstr[1] "" +"Sigurohuni që s’ka më tepër se %(max)s shifra para presjes dhjetore." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Zgjatimi “%(extension)s” për kartela nuk lejohet. Zgjatime të lejuara janë: " +"%(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Nuk lejohen shenja null." + +msgid "and" +msgstr "dhe " + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "Ka tashmë %(model_name)s me këtë %(field_labels)s." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Është cenuar kufizimi “%(name)s”." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Vlera %(value)r s’është zgjedhje e vlefshme." + +msgid "This field cannot be null." +msgstr "Kjo fushë s’mund të përmbajë shenja null." + +msgid "This field cannot be blank." +msgstr "Kjo fushë s’mund të jetë e paplotësuar." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "Ka tashmë një %(model_name)s me këtë %(field_label)s." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s duhet të jetë unike për %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Fushë e llojit: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "Vlera “%(value)s” duhet të jetë ose True, ose False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "Vlera për “%(value)s” duhet të jetë ose True, ose False, ose None." + +msgid "Boolean (Either True or False)" +msgstr "Buleane (Ose True, ose False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Varg (deri në %(max_length)s)" + +msgid "String (unlimited)" +msgstr "Varg (i pakufizuar)" + +msgid "Comma-separated integers" +msgstr "Numra të plotë të ndarë me presje" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"Vlera “%(value)s” ka një format të pavlefshëm datash. Duhet të jetë në " +"formatin YYYY-MM-DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"Vlera “%(value)s” ka formatin e saktë (YYYY-MM-DD), por është datë e " +"pavlefshme." + +msgid "Date (without time)" +msgstr "Datë (pa kohë)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"Vlera “'%(value)s” ka një format të pavlefshëm. Duhet të jetë në formatin " +"YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"Vlera “%(value)s” ka format të saktë (YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]), " +"por është datë/kohë e pavlefshme." + +msgid "Date (with time)" +msgstr "Datë (me kohë)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "Vlera “%(value)s” duhet të jetë një numër dhjetor." + +msgid "Decimal number" +msgstr "Numër dhjetor" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"Vlera “%(value)s” ka format të pavlefshëm. Duhet të jetë në formatin [DD] " +"[HH:[MM:]]ss[.uuuuuu]." + +msgid "Duration" +msgstr "Kohëzgjatje" + +msgid "Email address" +msgstr "Adresë email" + +msgid "File path" +msgstr "Shteg kartele" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "Vlera “%(value)s” duhet të jetë numër i plotë." + +msgid "Integer" +msgstr "Numër i plotë" + +msgid "Big (8 byte) integer" +msgstr "Numër i plotë i madh (8 bajte)" + +msgid "Small integer" +msgstr "Numër i plotë i vogël" + +msgid "IPv4 address" +msgstr "Adresë IPv4" + +msgid "IP address" +msgstr "Adresë IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "Vlera “%(value)s” duhet të jetë ose None, ose True, ose False." + +msgid "Boolean (Either True, False or None)" +msgstr "Buleane (Ose True, ose False, ose None)" + +msgid "Positive big integer" +msgstr "Numër i plotë pozitiv i madh" + +msgid "Positive integer" +msgstr "Numër i plotë pozitiv" + +msgid "Positive small integer" +msgstr "Numër i plotë pozitiv i vogël" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Identifikues (deri në %(max_length)s)" + +msgid "Text" +msgstr "Tekst" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"Vlera “%(value)s” ka format të pavlefshëm. Duhet të jetë në formatin HH:MM[:" +"ss[.uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"Vlera “%(value)s” ka formatin e saktë (HH:MM[:ss[.uuuuuu]]) por është kohë e " +"pavlefshme." + +msgid "Time" +msgstr "Kohë" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Të dhëna dyore të papërpunuara" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "“%(value)s” s’është UUID i vlefshëm." + +msgid "Universally unique identifier" +msgstr "Identifikues universalisht unik" + +msgid "File" +msgstr "Kartelë" + +msgid "Image" +msgstr "Figurë" + +msgid "A JSON object" +msgstr "Objekt JSON" + +msgid "Value must be valid JSON." +msgstr "Vlera duhet të jetë JSON i vlefshëm." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "Instanca %(model)s me %(field)s %(value)r s’ekziston." + +msgid "Foreign Key (type determined by related field)" +msgstr "Kyç i Jashtëm (lloj i përcaktuar nga fusha përkatëse)" + +msgid "One-to-one relationship" +msgstr "Marrëdhënie një-për-një" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "Marrëdhënie %(from)s-%(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "Marrëdhënie %(from)s-%(to)s" + +msgid "Many-to-many relationship" +msgstr "Marrëdhënie shumë-për-shumë" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Kjo fushë është e domosdoshme." + +msgid "Enter a whole number." +msgstr "Jepni një numër të tërë." + +msgid "Enter a valid date." +msgstr "Jepni një datë të vlefshme." + +msgid "Enter a valid time." +msgstr "Jepni një kohë të vlefshme." + +msgid "Enter a valid date/time." +msgstr "Jepni një datë/kohë të vlefshme." + +msgid "Enter a valid duration." +msgstr "Jepni një kohëzgjatje të vlefshme." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Numri i ditëve duhet të jetë mes {min_days} dhe {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" +"S’u parashtrua ndonjë kartelë. Kontrolloni llojin e kodimit te formulari." + +msgid "No file was submitted." +msgstr "S’u parashtrua kartelë." + +msgid "The submitted file is empty." +msgstr "Kartela e parashtruar është e zbrazët." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Sigurohuni që ky emër kartele ka të shumtën %(max)d shenjë (it has " +"%(length)d)." +msgstr[1] "" +"Sigurohuni që ky emër kartele ka të shumtën %(max)d shenja (it has " +"%(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Ju lutemi, ose parashtroni një kartelë, ose i vini shenjë kutizës për " +"spastrim, jo që të dyja." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Ngarkoni një figurë të vlefshme. Kartela që ngarkuat ose nuk qe figurë, ose " +"qe figurë e dëmtuar." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Përzgjidhni një zgjedhje të vlefshme. %(value)s s’është një nga zgjedhjet e " +"mundshme." + +msgid "Enter a list of values." +msgstr "Jepni një listë vlerash." + +msgid "Enter a complete value." +msgstr "Jepni një vlerë të plotë." + +msgid "Enter a valid UUID." +msgstr "Jepni një UUID të vlefshëm." + +msgid "Enter a valid JSON." +msgstr "Jepni një JSON të vlefshëm." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Fushë e fshehur %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"Mungojnë të dhëna ManagementForm, ose në to janë futur hundët. Fusha që " +"mungojnë: %(field_names)s. Nëse problemi vazhdon, mund të duhet të " +"parashtroni një raport të mete." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Ju lutemi, parashtroni e shumta %(num)d formular." +msgstr[1] "Ju lutemi, parashtroni e shumta %(num)d formularë." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Ju lutemi, parashtroni të paktën %(num)d formular." +msgstr[1] "Ju lutemi, parashtroni të paktën %(num)d formularë." + +msgid "Order" +msgstr "Renditi" + +msgid "Delete" +msgstr "Fshije" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Ju lutemi, ndreqni të dhënat e përsëdytura për %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Ju lutemi, ndreqni të dhënat e përsëdytura për %(field)s, të cilat duhet të " +"jenë unike." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Ju lutemi, ndreqni të dhënat e përsëdytura për %(field_name)s të cilat duhet " +"të jenë unike për %(lookup)s te %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Ju lutemi, ndreqni më poshtë vlerat e përsëdytura." + +msgid "The inline value did not match the parent instance." +msgstr "Vlera e brendshme s’u përputh me instancën prind." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Përzgjidhni një zgjedhje të vlefshme. Ajo zgjedhje nuk është një nga " +"zgjedhjet e mundshme." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "“%(pk)s” s’është vlerë e vlefshme." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s s’u interpretua dot brenda zonës kohore %(current_timezone)s; " +"mund të jetë e dykuptimtë, ose mund të mos ekzistojë." + +msgid "Clear" +msgstr "Spastroje" + +msgid "Currently" +msgstr "Tani" + +msgid "Change" +msgstr "Ndryshoje" + +msgid "Unknown" +msgstr "E panjohur" + +msgid "Yes" +msgstr "Po" + +msgid "No" +msgstr "Jo" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "po,jo,ndoshta" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d bajt" +msgstr[1] "%(size)d bajte" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "mesnatë" + +msgid "noon" +msgstr "mesditë" + +msgid "Monday" +msgstr "E hënë" + +msgid "Tuesday" +msgstr "E martë" + +msgid "Wednesday" +msgstr "E mërkurë" + +msgid "Thursday" +msgstr "E enjte" + +msgid "Friday" +msgstr "E premte" + +msgid "Saturday" +msgstr "E shtunë" + +msgid "Sunday" +msgstr "E dielë" + +msgid "Mon" +msgstr "Hën" + +msgid "Tue" +msgstr "Mar" + +msgid "Wed" +msgstr "Mër" + +msgid "Thu" +msgstr "Enj" + +msgid "Fri" +msgstr "Pre" + +msgid "Sat" +msgstr "Sht" + +msgid "Sun" +msgstr "Die" + +msgid "January" +msgstr "Janar" + +msgid "February" +msgstr "Shkurt" + +msgid "March" +msgstr "Mars" + +msgid "April" +msgstr "Prill" + +msgid "May" +msgstr "Maj" + +msgid "June" +msgstr "Qershor" + +msgid "July" +msgstr "Korrik" + +msgid "August" +msgstr "Gusht" + +msgid "September" +msgstr "Shtator" + +msgid "October" +msgstr "Tetor" + +msgid "November" +msgstr "Nëntor" + +msgid "December" +msgstr "Dhjetor" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "shk" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "pri" + +msgid "may" +msgstr "maj" + +msgid "jun" +msgstr "qer" + +msgid "jul" +msgstr "kor" + +msgid "aug" +msgstr "gus" + +msgid "sep" +msgstr "sht" + +msgid "oct" +msgstr "tet" + +msgid "nov" +msgstr "nën" + +msgid "dec" +msgstr "dhj" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Shk." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Mars" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Prill" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Maj" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Qershor" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Korrik" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Gus." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Shta." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Tet." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Nën." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dhj." + +msgctxt "alt. month" +msgid "January" +msgstr "Janar" + +msgctxt "alt. month" +msgid "February" +msgstr "Shkurt" + +msgctxt "alt. month" +msgid "March" +msgstr "Mars" + +msgctxt "alt. month" +msgid "April" +msgstr "Prill" + +msgctxt "alt. month" +msgid "May" +msgstr "Maj" + +msgctxt "alt. month" +msgid "June" +msgstr "Qershor" + +msgctxt "alt. month" +msgid "July" +msgstr "Korrik" + +msgctxt "alt. month" +msgid "August" +msgstr "Gusht" + +msgctxt "alt. month" +msgid "September" +msgstr "Shtator" + +msgctxt "alt. month" +msgid "October" +msgstr "Tetor" + +msgctxt "alt. month" +msgid "November" +msgstr "Nëntor" + +msgctxt "alt. month" +msgid "December" +msgstr "Dhjetor" + +msgid "This is not a valid IPv6 address." +msgstr "Kjo s’është adresë IPv6 e vlefshme." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "ose" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d vit" +msgstr[1] "%(num)d vjet" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d muaj" +msgstr[1] "%(num)d muaj" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d javë" +msgstr[1] "%(num)d javë" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d ditë" +msgstr[1] "%(num)d ditë" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d orë" +msgstr[1] "%(num)d orë" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minutë" +msgstr[1] "%(num)d minuta" + +msgid "Forbidden" +msgstr "E ndaluar" + +msgid "CSRF verification failed. Request aborted." +msgstr "Verifikimi CSRF dështoi. Kërkesa u ndërpre." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Këtë mesazh po e shihni ngaqë ky sajt HTTPS e ka të domosdoshme dërgimin e " +"“Referer header” te shfletuesi juaj, por s’u dërgua ndonjë i tillë. Kjo krye " +"është e domosdoshme për arsye sigurie, për të bërë të mundur që shfletuesi " +"juaj të mos komprometohet nga palë të treta." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Nëse e keni formësuar shfletuesin tuaj të çaktivizojë kryet “Referer”, ju " +"lutemi, riaktivizojini, ose për lidhje HTTPS, ose për kërkesa “same-origin”." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Nëse përdorni etiketën " +"etiketën ose përfshini kryet “Referrer-Policy: no-referrer”, ju lutemi, " +"hiqini. Mbrojtja CSRF lyp që kryet “Referer” të kryejnë kontroll strikt " +"referuesi. Nëse shqetësoheni për privatësinë, për lidhje te sajte palësh të " +"treta përdorni alternativa si ." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Këtë mesazh po e shihni ngaqë ky sajt lyp një cookie CSRF, kur parashtrohen " +"formularë. Kjo cookie është e domosdoshme për arsye sigurie, për të bërë të " +"mundur që shfletuesi juaj të mos komprometohet nga palë të treta." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Nëse e keni formësuar shfletuesin tuaj të çaktivizojë cookie-t, ju lutemi, " +"riaktivizojini, të paktën për këtë sajt, ose për kërkesa “same-origin”." + +msgid "More information is available with DEBUG=True." +msgstr "Më tepër të dhëna mund të gjeni me DEBUG=True." + +msgid "No year specified" +msgstr "Nuk është caktuar vit" + +msgid "Date out of range" +msgstr "Datë jashtë intervali" + +msgid "No month specified" +msgstr "Nuk është caktuar muaj" + +msgid "No day specified" +msgstr "Nuk është caktuar ditë" + +msgid "No week specified" +msgstr "Nuk është caktuar javë" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Nuk ka %(verbose_name_plural)s të përcaktuar" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"%(verbose_name_plural)s i ardhshëm jo i passhëm, ngaqë %(class_name)s." +"allow_future është False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" +"U dha varg i pavlefshëm date “%(datestr)s” formati i dhënë “%(format)s”" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "S’u gjetën %(verbose_name)s me përputhje" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Faqja nuk është “last”, as mund të shndërrohet në një int." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Faqe e pavlefshme (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Listë e zbrazët dhe “%(class_name)s.allow_empty” është False." + +msgid "Directory indexes are not allowed here." +msgstr "Këtu s’lejohen tregues drejtorish." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "“%(path)s” s’ekziston" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Tregues i %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Instalimi funksionoi me sukses! Përgëzime!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Shihni shënimet për hedhjen në qarkullim të " +"Django %(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Po e shihni këtë faqe ngaqë te kartela juaj e rregullimeve gjendet DEBUG=True dhe s’keni formësuar " +"ndonjë URL." + +msgid "Django Documentation" +msgstr "Dokumentim i Django-s" + +msgid "Topics, references, & how-to’s" +msgstr "Tema, referenca, & how-to" + +msgid "Tutorial: A Polling App" +msgstr "Përkujdesore: Një Aplikacion Për Sondazhe" + +msgid "Get started with Django" +msgstr "Si t’ia filloni me Django-n" + +msgid "Django Community" +msgstr "Bashkësia Django" + +msgid "Connect, get help, or contribute" +msgstr "Lidhuni, merrni ndihmë, ose jepni ndihmesë" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sq/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sq/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sq/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sq/formats.py new file mode 100644 index 0000000..c7ed92e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sq/formats.py @@ -0,0 +1,21 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "d F Y" +TIME_FORMAT = "g.i.A" +# DATETIME_FORMAT = +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "Y-m-d" +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +# NUMBER_GROUPING = diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4b305d7 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sr/LC_MESSAGES/django.po new file mode 100644 index 0000000..7d8efcf --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sr/LC_MESSAGES/django.po @@ -0,0 +1,1357 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Branko Kokanovic , 2018-2019 +# Igor Jerosimić, 2019-2021,2023 +# Jannis Leidel , 2011 +# Janos Guljas , 2011-2012 +# Mariusz Felisiak , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Igor Jerosimić, 2019-2021,2023\n" +"Language-Team: Serbian (http://app.transifex.com/django/django/language/" +"sr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Afrikaans" +msgstr "африкански" + +msgid "Arabic" +msgstr "арапски" + +msgid "Algerian Arabic" +msgstr "Алжирски арапски" + +msgid "Asturian" +msgstr "астуријски" + +msgid "Azerbaijani" +msgstr "азербејџански" + +msgid "Bulgarian" +msgstr "бугарски" + +msgid "Belarusian" +msgstr "белоруски" + +msgid "Bengali" +msgstr "бенгалски" + +msgid "Breton" +msgstr "бретонски" + +msgid "Bosnian" +msgstr "босански" + +msgid "Catalan" +msgstr "каталонски" + +msgid "Central Kurdish (Sorani)" +msgstr "централнокурдски (сорани)" + +msgid "Czech" +msgstr "чешки" + +msgid "Welsh" +msgstr "велшки" + +msgid "Danish" +msgstr "дански" + +msgid "German" +msgstr "немачки" + +msgid "Lower Sorbian" +msgstr "доњолужичкосрпски" + +msgid "Greek" +msgstr "грчки" + +msgid "English" +msgstr "енглески" + +msgid "Australian English" +msgstr "аустралијски енглески" + +msgid "British English" +msgstr "британски енглески" + +msgid "Esperanto" +msgstr "есперанто" + +msgid "Spanish" +msgstr "шпански" + +msgid "Argentinian Spanish" +msgstr "аргентински шпански" + +msgid "Colombian Spanish" +msgstr "колумбијски шпански" + +msgid "Mexican Spanish" +msgstr "мексички шпански" + +msgid "Nicaraguan Spanish" +msgstr "никарагвански шпански" + +msgid "Venezuelan Spanish" +msgstr "венецуелански шпански" + +msgid "Estonian" +msgstr "естонски" + +msgid "Basque" +msgstr "баскијски" + +msgid "Persian" +msgstr "персијски" + +msgid "Finnish" +msgstr "фински" + +msgid "French" +msgstr "француски" + +msgid "Frisian" +msgstr "фризијски" + +msgid "Irish" +msgstr "ирски" + +msgid "Scottish Gaelic" +msgstr "шкотски гелски" + +msgid "Galician" +msgstr "галицијски" + +msgid "Hebrew" +msgstr "хебрејски" + +msgid "Hindi" +msgstr "хинду" + +msgid "Croatian" +msgstr "хрватски" + +msgid "Upper Sorbian" +msgstr "горњолужичкосрпски" + +msgid "Hungarian" +msgstr "мађарски" + +msgid "Armenian" +msgstr "јерменски" + +msgid "Interlingua" +msgstr "интерлингва" + +msgid "Indonesian" +msgstr "индонежански" + +msgid "Igbo" +msgstr "Игбо" + +msgid "Ido" +msgstr "идо" + +msgid "Icelandic" +msgstr "исландски" + +msgid "Italian" +msgstr "италијански" + +msgid "Japanese" +msgstr "јапански" + +msgid "Georgian" +msgstr "грузијски" + +msgid "Kabyle" +msgstr "кабилски" + +msgid "Kazakh" +msgstr "казашки" + +msgid "Khmer" +msgstr "кмерски" + +msgid "Kannada" +msgstr "канада" + +msgid "Korean" +msgstr "корејски" + +msgid "Kyrgyz" +msgstr "Киргиски" + +msgid "Luxembourgish" +msgstr "луксембуршки" + +msgid "Lithuanian" +msgstr "литвански" + +msgid "Latvian" +msgstr "латвијски" + +msgid "Macedonian" +msgstr "македонски" + +msgid "Malayalam" +msgstr "малајаламски" + +msgid "Mongolian" +msgstr "монголски" + +msgid "Marathi" +msgstr "маратхи" + +msgid "Malay" +msgstr "малајски" + +msgid "Burmese" +msgstr "бурмански" + +msgid "Norwegian Bokmål" +msgstr "норвешки књижевни" + +msgid "Nepali" +msgstr "непалски" + +msgid "Dutch" +msgstr "холандски" + +msgid "Norwegian Nynorsk" +msgstr "норвешки нови" + +msgid "Ossetic" +msgstr "осетински" + +msgid "Punjabi" +msgstr "панџаби" + +msgid "Polish" +msgstr "пољски" + +msgid "Portuguese" +msgstr "португалски" + +msgid "Brazilian Portuguese" +msgstr "бразилски португалски" + +msgid "Romanian" +msgstr "румунски" + +msgid "Russian" +msgstr "руски" + +msgid "Slovak" +msgstr "словачки" + +msgid "Slovenian" +msgstr "словеначки" + +msgid "Albanian" +msgstr "албански" + +msgid "Serbian" +msgstr "српски" + +msgid "Serbian Latin" +msgstr "српски (латиница)" + +msgid "Swedish" +msgstr "шведски" + +msgid "Swahili" +msgstr "свахили" + +msgid "Tamil" +msgstr "тамилски" + +msgid "Telugu" +msgstr "телугу" + +msgid "Tajik" +msgstr "Таџики" + +msgid "Thai" +msgstr "тајландски" + +msgid "Turkmen" +msgstr "Туркменски" + +msgid "Turkish" +msgstr "турски" + +msgid "Tatar" +msgstr "татарски" + +msgid "Udmurt" +msgstr "удмуртски" + +msgid "Uyghur" +msgstr "Ујгури" + +msgid "Ukrainian" +msgstr "украјински" + +msgid "Urdu" +msgstr "урду" + +msgid "Uzbek" +msgstr "Узбекистански" + +msgid "Vietnamese" +msgstr "вијетнамски" + +msgid "Simplified Chinese" +msgstr "поједностављени кинески" + +msgid "Traditional Chinese" +msgstr "традиционални кинески" + +msgid "Messages" +msgstr "Poruke" + +msgid "Site Maps" +msgstr "Мапе сајта" + +msgid "Static Files" +msgstr "Статички фајлови" + +msgid "Syndication" +msgstr "Удруживање садржаја" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Задати број стране није цео број" + +msgid "That page number is less than 1" +msgstr "Задати број стране је мањи од 1" + +msgid "That page contains no results" +msgstr "Тражена страна не садржи резултате" + +msgid "Enter a valid value." +msgstr "Унесите исправну вредност." + +msgid "Enter a valid URL." +msgstr "Унесите исправан URL." + +msgid "Enter a valid integer." +msgstr "Унесите исправан цео број." + +msgid "Enter a valid email address." +msgstr "Унесите исправну и-мејл адресу." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Унесите исрпаван „слаг“, који се састоји од слова, бројки, доњих црта или " +"циртица." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Унесите исправан \"слаг\", који се састоји од Уникод слова, бројки, доњих " +"црта или цртица." + +msgid "Enter a valid IPv4 address." +msgstr "Унесите исправну IPv4 адресу." + +msgid "Enter a valid IPv6 address." +msgstr "Унесите исправну IPv6 адресу." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Унесите исправну IPv4 или IPv6 адресу." + +msgid "Enter only digits separated by commas." +msgstr "Унесите само цифре раздвојене запетама." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Ово поље мора да буде %(limit_value)s (тренутно има %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Ова вредност мора да буде мања од %(limit_value)s. или тачно толико." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Ова вредност мора бити већа од %(limit_value)s или тачно толико." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "Ова вредност мора да умножак величине корака %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"Уверите се да је ова вредност вишекратник величине корака %(limit_value)s, " +"почевши од %(offset)s, нпр. %(offset)s, %(valid_value1)s, %(valid_value2)s, " +"и тако даље." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Ово поље мора да има најмање %(limit_value)d карактер (тренутно има " +"%(show_value)d)." +msgstr[1] "" +"Ово поље мора да има најмање %(limit_value)d карактера (тренутно има " +"%(show_value)d)." +msgstr[2] "" +"Ово поље мора да има најмање %(limit_value)d карактера (тренутно има " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Ово поље не сме да има више од %(limit_value)d карактера (тренутно има " +"%(show_value)d)." +msgstr[1] "" +"Ово поље не сме да има више од %(limit_value)d карактера (тренутно има " +"%(show_value)d)." +msgstr[2] "" +"Ово поље не сме да има више од %(limit_value)d карактера (тренутно има " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Унесите број." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Укупно не може бити више од %(max)s цифре." +msgstr[1] "Укупно не може бити више од %(max)s цифре." +msgstr[2] "Укупно не може бити више од %(max)s цифара." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Не може бити више од %(max)s децимале." +msgstr[1] "Не може бити више од %(max)s децимале." +msgstr[2] "Не може бити више од %(max)s децимала." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "Не може бити више од %(max)s цифре пре децималног зареза." +msgstr[1] "Не може бити више од %(max)s цифре пре децималног зареза." +msgstr[2] "Не може бити више од %(max)s цифара пре децималног зареза." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Екстензија датотеке \"%(extension)s\" није дозвољена. Дозвољене су следеће " +"екстензије: %(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "'Null' карактери нису дозвољени." + +msgid "and" +msgstr "и" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s са пољем %(field_labels)s већ постоји." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Ограничење „%(name)s“ је прекршено." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Вредност %(value)r није валидна." + +msgid "This field cannot be null." +msgstr "Ово поље не може бити 'null'." + +msgid "This field cannot be blank." +msgstr "Ово поље не може да остане празно." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s са пољем %(field_label)s већ постоји." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s мора бити јединствен(a) за %(date_field_label)s " +"%(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Поље типа: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "Вредност \"%(value)s\" мора бити True или False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "\"%(value)s\" вредност мора бити True, False или None." + +msgid "Boolean (Either True or False)" +msgstr "Булова вредност (True или False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Стринг са макс. дужином %(max_length)s" + +msgid "String (unlimited)" +msgstr "Стринг (неограниченo)" + +msgid "Comma-separated integers" +msgstr "Цели бројеви раздвојени запетама" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"Вредност \"%(value)s\" нема исправан формат датума. Мора бити у формату ГГГГ-" +"ММ-ДД." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"Вредност \"%(value)s\" има исправан формат (ГГГГ-ММ-ДД) али то није исправан " +"датум." + +msgid "Date (without time)" +msgstr "Датум (без времена)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"Вредност \"%(value)s\" нема исправан формат. Мора бити у формату ГГГГ-ММ-ДД " +"ЧЧ:ММ[:сс[.uuuuuu]][TZ] ." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"Вредност \"%(value)s\" има исправан формат (ГГГГ-ММ-ДД ЧЧ:ММ[:сс[.uuuuuu]]" +"[TZ]) али то није исправан датум/време." + +msgid "Date (with time)" +msgstr "Датум (са временом)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "Вредност \"%(value)s\" мора бити децимални број." + +msgid "Decimal number" +msgstr "Децимални број" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"Вредност \"%(value)s\" нема исправан формат. Мора бити у формату [ДД] [ЧЧ:" +"[ММ:]]сс[.uuuuuu]." + +msgid "Duration" +msgstr "Временски интервал" + +msgid "Email address" +msgstr "Имејл адреса" + +msgid "File path" +msgstr "Путања фајла" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "Вредност \"%(value)s\" мора бити број са покретним зарезом." + +msgid "Floating point number" +msgstr "Број са покретним зарезом" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "Вредност \"%(value)s\" мора бити цео број." + +msgid "Integer" +msgstr "Цео број" + +msgid "Big (8 byte) integer" +msgstr "Велики (8 бајтова) цео број" + +msgid "Small integer" +msgstr "Мали цео број" + +msgid "IPv4 address" +msgstr "IPv4 адреса" + +msgid "IP address" +msgstr "IP адреса" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "Вредност \"%(value)s\" мора бити None, True или False." + +msgid "Boolean (Either True, False or None)" +msgstr "Булова вредност (True, False или None)" + +msgid "Positive big integer" +msgstr "Велик позитиван цео број" + +msgid "Positive integer" +msgstr "Позитиван цео број" + +msgid "Positive small integer" +msgstr "Позитиван мали цео број" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Слаг са макс. дужином %(max_length)s" + +msgid "Text" +msgstr "Текст" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"Вредност \"%(value)s\" нема исправан формат. Мора бити у формату ЧЧ:ММ[:сс[." +"uuuuuu]] ." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"Вредност \"%(value)s\" има исправан формат (ЧЧ:ММ[:сс[.uuuuuu]]) али то није " +"исправно време." + +msgid "Time" +msgstr "Време" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Сирови бинарни подаци" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "\"%(value)s\" није исправан UUID." + +msgid "Universally unique identifier" +msgstr "Универзално јединствени идентификатор" + +msgid "File" +msgstr "Фајл" + +msgid "Image" +msgstr "Слика" + +msgid "A JSON object" +msgstr "JSON објекат" + +msgid "Value must be valid JSON." +msgstr "Вредност мора бити исправан JSON." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(model)s инстанца са вредношћу %(value)r у пољу %(field)s не постоји." + +msgid "Foreign Key (type determined by related field)" +msgstr "Спољни кључ (тип је одређен асоцираном колоном)" + +msgid "One-to-one relationship" +msgstr "Релација један на један" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "Релација %(from)s-%(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "Релације %(from)s-%(to)s" + +msgid "Many-to-many relationship" +msgstr "Релација више на више" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Ово поље се мора попунити." + +msgid "Enter a whole number." +msgstr "Унесите цео број." + +msgid "Enter a valid date." +msgstr "Унесите исправан датум." + +msgid "Enter a valid time." +msgstr "Унесите исправно време" + +msgid "Enter a valid date/time." +msgstr "Унесите исправан датум/време." + +msgid "Enter a valid duration." +msgstr "Унесите исправан временски интервал." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Број дана мора бити између {min_days} и {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Фајл није пребачен. Проверите тип енкодирања на форми." + +msgid "No file was submitted." +msgstr "Фајл није пребачен." + +msgid "The submitted file is empty." +msgstr "Пребачени фајл је празан." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Име фајла не може имати више од %(max)d карактера (тренутно има %(length)d)." +msgstr[1] "" +"Име фајла не може имати више од %(max)d карактера (тренутно има %(length)d)." +msgstr[2] "" +"Име фајла не може имати више од %(max)d карактера (тренутно има %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Може се само послати фајл или избрисати, не оба." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Пребаците исправан фајл. Фајл који је пребачен или није слика, или је " +"оштећен." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"%(value)s није међу понуђеним вредностима. Одаберите једну од понуђених." + +msgid "Enter a list of values." +msgstr "Унесите листу вредности." + +msgid "Enter a complete value." +msgstr "Унесите комплетну вредност." + +msgid "Enter a valid UUID." +msgstr "Унесите исправан UUID." + +msgid "Enter a valid JSON." +msgstr "Унесите исправан JSON." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Скривено поље %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"Подаци од ManagementForm недостају или су покварени. Поља која недостају: " +"%(field_names)s. Можда ће бити потребно да пријавите грешку ако се проблем " +"настави." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Молим проследите највише %(num)d форму." +msgstr[1] "Молим проследите највише %(num)d форме." +msgstr[2] "Молим проследите највише %(num)d форми." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Молим проследите најмање %(num)d форму." +msgstr[1] "Молим проследите најмање %(num)d форме." +msgstr[2] "Молим проследите најмање %(num)d форми." + +msgid "Order" +msgstr "Редослед" + +msgid "Delete" +msgstr "Обриши" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Исправите вредност за поље %(field)s - оно мора бити јединствено." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Исправите вредности за поља %(field)s - њихова комбинација мора бити " +"јединствена." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Иправите вредност за поље %(field_name)s, оно мора бити јединствено за " +"%(lookup)s у %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Исправите дуплиране вредности доле." + +msgid "The inline value did not match the parent instance." +msgstr "Директно унета вредност не одговара инстанци родитеља." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Одабрана вредност није међу понуђенима. Одаберите једну од понуђених." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "\"%(pk)s\" није исправна вредност." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"Време %(datetime)s се не може протумачити у временској зони " +"%(current_timezone)s; можда је двосмислено или не постоји." + +msgid "Clear" +msgstr "Очисти" + +msgid "Currently" +msgstr "Тренутно" + +msgid "Change" +msgstr "Измени" + +msgid "Unknown" +msgstr "Непознато" + +msgid "Yes" +msgstr "Да" + +msgid "No" +msgstr "Не" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "да,не,можда" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d бајт" +msgstr[1] "%(size)d бајта" +msgstr[2] "%(size)d бајтова" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "по п." + +msgid "a.m." +msgstr "пре п." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "поноћ" + +msgid "noon" +msgstr "подне" + +msgid "Monday" +msgstr "понедељак" + +msgid "Tuesday" +msgstr "уторак" + +msgid "Wednesday" +msgstr "среда" + +msgid "Thursday" +msgstr "четвртак" + +msgid "Friday" +msgstr "петак" + +msgid "Saturday" +msgstr "субота" + +msgid "Sunday" +msgstr "недеља" + +msgid "Mon" +msgstr "пон." + +msgid "Tue" +msgstr "уто." + +msgid "Wed" +msgstr "сре." + +msgid "Thu" +msgstr "чет." + +msgid "Fri" +msgstr "пет." + +msgid "Sat" +msgstr "суб." + +msgid "Sun" +msgstr "нед." + +msgid "January" +msgstr "јануар" + +msgid "February" +msgstr "фебруар" + +msgid "March" +msgstr "март" + +msgid "April" +msgstr "април" + +msgid "May" +msgstr "мај" + +msgid "June" +msgstr "јун" + +msgid "July" +msgstr "јул" + +msgid "August" +msgstr "август" + +msgid "September" +msgstr "септембар" + +msgid "October" +msgstr "октобар" + +msgid "November" +msgstr "новембар" + +msgid "December" +msgstr "децембар" + +msgid "jan" +msgstr "јан." + +msgid "feb" +msgstr "феб." + +msgid "mar" +msgstr "мар." + +msgid "apr" +msgstr "апр." + +msgid "may" +msgstr "мај." + +msgid "jun" +msgstr "јун." + +msgid "jul" +msgstr "јул." + +msgid "aug" +msgstr "ауг." + +msgid "sep" +msgstr "сеп." + +msgid "oct" +msgstr "окт." + +msgid "nov" +msgstr "нов." + +msgid "dec" +msgstr "дец." + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Јан." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Феб." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Март" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Април" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Мај" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Јун" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Јул" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Авг." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Септ." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Окт." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Нов." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Дец." + +msgctxt "alt. month" +msgid "January" +msgstr "Јануар" + +msgctxt "alt. month" +msgid "February" +msgstr "Фебруар" + +msgctxt "alt. month" +msgid "March" +msgstr "Март" + +msgctxt "alt. month" +msgid "April" +msgstr "Април" + +msgctxt "alt. month" +msgid "May" +msgstr "Мај" + +msgctxt "alt. month" +msgid "June" +msgstr "Јун" + +msgctxt "alt. month" +msgid "July" +msgstr "Јул" + +msgctxt "alt. month" +msgid "August" +msgstr "Август" + +msgctxt "alt. month" +msgid "September" +msgstr "Септембар" + +msgctxt "alt. month" +msgid "October" +msgstr "Октобар" + +msgctxt "alt. month" +msgid "November" +msgstr "Новембар" + +msgctxt "alt. month" +msgid "December" +msgstr "Децембар" + +msgid "This is not a valid IPv6 address." +msgstr "Ово није валидна IPv6 адреса." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "или" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d година" +msgstr[1] "%(num)d године" +msgstr[2] "%(num)d година" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d месец" +msgstr[1] "%(num)d месеца" +msgstr[2] "%(num)d месеци" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d недеља" +msgstr[1] "%(num)d недеље" +msgstr[2] "%(num)d недеља" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d дан" +msgstr[1] "%(num)d дана" +msgstr[2] "%(num)d дана" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d сат" +msgstr[1] "%(num)d сата" +msgstr[2] "%(num)d сати" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d минут" +msgstr[1] "%(num)d минута" +msgstr[2] "%(num)d минута" + +msgid "Forbidden" +msgstr "Забрањено" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF верификација није прошла. Захтев одбијен." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Ова порука је приказана јер овај HTTPS сајт захтева да \"Referer header\" " +"буде послат од стране вашег интернет прегледача, што тренутно није случај. " +"Поменуто заглавље је потребно из безбедоносних разлога, да би се осигурало " +"да ваш прегледач није под контролом трећих лица." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Ако сте подесили интернет прегледач да не шаље \"Referer\" заглавља, поново " +"их укључите, барем за овај сајт, или за HTTPS конекције, или за \"same-" +"origin\" захтеве." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Ако користите таг или " +"\"Referrer-Policy: no-referrer\" заглавље, молимо да их уклоните. CSRF " +"заштита захтева \"Referer\" заглавље да би се обавила стриктна \"referrer\" " +"провера. Уколико вас брине приватност, користите алтернативе као за линкове ка другим сајтовима." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Ова порука је приказана јер овај сајт захтева CSRF куки када се прослеђују " +"подаци из форми. Овај куки је потребан из сигурносних разлога, да би се " +"осигурало да ваш претраживач није под контролом трећих лица." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Ако је ваш интернет прегедач подешен да онемогући колачиће, молимо да их " +"укључите, барем за овај сајт, или за \"same-origin\" захтеве." + +msgid "More information is available with DEBUG=True." +msgstr "Више информација је доступно са DEBUG=True." + +msgid "No year specified" +msgstr "Година није назначена" + +msgid "Date out of range" +msgstr "Датум ван опсега" + +msgid "No month specified" +msgstr "Месец није назначен" + +msgid "No day specified" +msgstr "Дан није назначен" + +msgid "No week specified" +msgstr "Недеља није назначена" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Недоступни објекти %(verbose_name_plural)s" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Опција „future“ није доступна за „%(verbose_name_plural)s“ јер " +"%(class_name)s.allow_future има вредност False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Неисправан датум „%(datestr)s“ за формат „%(format)s“" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Ниједан објекат класе %(verbose_name)s није нађен датим упитом." + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Страница није последња, нити може бити конвертована у тип \"int\"." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Неисправна страна (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Празна листа и „%(class_name)s.allow_empty“ има вредност False." + +msgid "Directory indexes are not allowed here." +msgstr "Индекси директоријума нису дозвољени овде." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "„%(path)s“ не постоји" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Индекс директоријума %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Инсталација је прошла успешно. Честитке!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Погледајте напомене уз издање за Ђанго " +"%(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Ова страна је приказана јер је DEBUG=True у вашим подешавањима и нисте конфигурисали " +"ниједан URL." + +msgid "Django Documentation" +msgstr "Ђанго документација" + +msgid "Topics, references, & how-to’s" +msgstr "Теме, референце, & како-да" + +msgid "Tutorial: A Polling App" +msgstr "Упутство: апликација за гласање" + +msgid "Get started with Django" +msgstr "Почните са Ђангом" + +msgid "Django Community" +msgstr "Ђанго заједница" + +msgid "Connect, get help, or contribute" +msgstr "Повежите се, потражите помоћ или дајте допринос" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sr/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sr/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sr/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sr/formats.py new file mode 100644 index 0000000..423f86d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sr/formats.py @@ -0,0 +1,44 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j. F Y." +TIME_FORMAT = "H:i" +DATETIME_FORMAT = "j. F Y. H:i" +YEAR_MONTH_FORMAT = "F Y." +MONTH_DAY_FORMAT = "j. F" +SHORT_DATE_FORMAT = "j.m.Y." +SHORT_DATETIME_FORMAT = "j.m.Y. H:i" +FIRST_DAY_OF_WEEK = 1 + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d.%m.%Y.", # '25.10.2006.' + "%d.%m.%y.", # '25.10.06.' + "%d. %m. %Y.", # '25. 10. 2006.' + "%d. %m. %y.", # '25. 10. 06.' + # "%d. %b %y.", # '25. Oct 06.' + # "%d. %B %y.", # '25. October 06.' + # "%d. %b '%y.", # '25. Oct '06.' + # "%d. %B '%y.", # '25. October '06.' + # "%d. %b %Y.", # '25. Oct 2006.' + # "%d. %B %Y.", # '25. October 2006.' +] +DATETIME_INPUT_FORMATS = [ + "%d.%m.%Y. %H:%M:%S", # '25.10.2006. 14:30:59' + "%d.%m.%Y. %H:%M:%S.%f", # '25.10.2006. 14:30:59.000200' + "%d.%m.%Y. %H:%M", # '25.10.2006. 14:30' + "%d.%m.%y. %H:%M:%S", # '25.10.06. 14:30:59' + "%d.%m.%y. %H:%M:%S.%f", # '25.10.06. 14:30:59.000200' + "%d.%m.%y. %H:%M", # '25.10.06. 14:30' + "%d. %m. %Y. %H:%M:%S", # '25. 10. 2006. 14:30:59' + "%d. %m. %Y. %H:%M:%S.%f", # '25. 10. 2006. 14:30:59.000200' + "%d. %m. %Y. %H:%M", # '25. 10. 2006. 14:30' + "%d. %m. %y. %H:%M:%S", # '25. 10. 06. 14:30:59' + "%d. %m. %y. %H:%M:%S.%f", # '25. 10. 06. 14:30:59.000200' + "%d. %m. %y. %H:%M", # '25. 10. 06. 14:30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sr_Latn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sr_Latn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3e17b5a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sr_Latn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sr_Latn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sr_Latn/LC_MESSAGES/django.po new file mode 100644 index 0000000..ab4ac0f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sr_Latn/LC_MESSAGES/django.po @@ -0,0 +1,1353 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Aleksa Cukovic` , 2020 +# Danijela Popović, 2022 +# Igor Jerosimić, 2019-2021,2023 +# Jannis Leidel , 2011 +# Janos Guljas , 2011-2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Igor Jerosimić, 2019-2021,2023\n" +"Language-Team: Serbian (Latin) (http://app.transifex.com/django/django/" +"language/sr@latin/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr@latin\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Afrikaans" +msgstr "afrikanski" + +msgid "Arabic" +msgstr "arapski" + +msgid "Algerian Arabic" +msgstr "Alžirski arapski" + +msgid "Asturian" +msgstr "asturijski" + +msgid "Azerbaijani" +msgstr "azerbejdžanski" + +msgid "Bulgarian" +msgstr "bugarski" + +msgid "Belarusian" +msgstr "beloruski" + +msgid "Bengali" +msgstr "bengalski" + +msgid "Breton" +msgstr "bretonski" + +msgid "Bosnian" +msgstr "bosanski" + +msgid "Catalan" +msgstr "katalonski" + +msgid "Central Kurdish (Sorani)" +msgstr "centralnokurdski (sorani)" + +msgid "Czech" +msgstr "češki" + +msgid "Welsh" +msgstr "velški" + +msgid "Danish" +msgstr "danski" + +msgid "German" +msgstr "nemački" + +msgid "Lower Sorbian" +msgstr "donjolužičkosrpski" + +msgid "Greek" +msgstr "grčki" + +msgid "English" +msgstr "engleski" + +msgid "Australian English" +msgstr "australijski engleski" + +msgid "British English" +msgstr "britanski engleski" + +msgid "Esperanto" +msgstr "esperanto" + +msgid "Spanish" +msgstr "španski" + +msgid "Argentinian Spanish" +msgstr "argentinski španski" + +msgid "Colombian Spanish" +msgstr "kolumbijski španski" + +msgid "Mexican Spanish" +msgstr "meksički španski" + +msgid "Nicaraguan Spanish" +msgstr "nikaragvanski španski" + +msgid "Venezuelan Spanish" +msgstr "venecuelanski španski" + +msgid "Estonian" +msgstr "estonski" + +msgid "Basque" +msgstr "baskijski" + +msgid "Persian" +msgstr "persijski" + +msgid "Finnish" +msgstr "finski" + +msgid "French" +msgstr "francuski" + +msgid "Frisian" +msgstr "frizijski" + +msgid "Irish" +msgstr "irski" + +msgid "Scottish Gaelic" +msgstr "škotski galski" + +msgid "Galician" +msgstr "galski" + +msgid "Hebrew" +msgstr "hebrejski" + +msgid "Hindi" +msgstr "hindu" + +msgid "Croatian" +msgstr "hrvatski" + +msgid "Upper Sorbian" +msgstr "gornjolužičkosrpski" + +msgid "Hungarian" +msgstr "mađarski" + +msgid "Armenian" +msgstr "jermenski" + +msgid "Interlingua" +msgstr "interlingva" + +msgid "Indonesian" +msgstr "indonežanski" + +msgid "Igbo" +msgstr "Igbo" + +msgid "Ido" +msgstr "ido" + +msgid "Icelandic" +msgstr "islandski" + +msgid "Italian" +msgstr "italijanski" + +msgid "Japanese" +msgstr "japanski" + +msgid "Georgian" +msgstr "gruzijski" + +msgid "Kabyle" +msgstr "kabilski" + +msgid "Kazakh" +msgstr "kazaški" + +msgid "Khmer" +msgstr "kambodijski" + +msgid "Kannada" +msgstr "kanada" + +msgid "Korean" +msgstr "korejski" + +msgid "Kyrgyz" +msgstr "Kirgiski" + +msgid "Luxembourgish" +msgstr "luksemburški" + +msgid "Lithuanian" +msgstr "litvanski" + +msgid "Latvian" +msgstr "latvijski" + +msgid "Macedonian" +msgstr "makedonski" + +msgid "Malayalam" +msgstr "malajalamski" + +msgid "Mongolian" +msgstr "mongolski" + +msgid "Marathi" +msgstr "marathi" + +msgid "Malay" +msgstr "malajski" + +msgid "Burmese" +msgstr "burmanski" + +msgid "Norwegian Bokmål" +msgstr "norveški književni" + +msgid "Nepali" +msgstr "nepalski" + +msgid "Dutch" +msgstr "holandski" + +msgid "Norwegian Nynorsk" +msgstr "norveški novi" + +msgid "Ossetic" +msgstr "osetinski" + +msgid "Punjabi" +msgstr "Pandžabi" + +msgid "Polish" +msgstr "poljski" + +msgid "Portuguese" +msgstr "portugalski" + +msgid "Brazilian Portuguese" +msgstr "brazilski portugalski" + +msgid "Romanian" +msgstr "rumunski" + +msgid "Russian" +msgstr "ruski" + +msgid "Slovak" +msgstr "slovački" + +msgid "Slovenian" +msgstr "slovenački" + +msgid "Albanian" +msgstr "albanski" + +msgid "Serbian" +msgstr "srpski" + +msgid "Serbian Latin" +msgstr "srpski (latinica)" + +msgid "Swedish" +msgstr "švedski" + +msgid "Swahili" +msgstr "svahili" + +msgid "Tamil" +msgstr "tamilski" + +msgid "Telugu" +msgstr "telugu" + +msgid "Tajik" +msgstr "Tadžiki" + +msgid "Thai" +msgstr "tajlandski" + +msgid "Turkmen" +msgstr "Turkmenski" + +msgid "Turkish" +msgstr "turski" + +msgid "Tatar" +msgstr "tatarski" + +msgid "Udmurt" +msgstr "udmurtski" + +msgid "Uyghur" +msgstr "" + +msgid "Ukrainian" +msgstr "ukrajinski" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "Uzbekistanski" + +msgid "Vietnamese" +msgstr "vijetnamski" + +msgid "Simplified Chinese" +msgstr "novokineski" + +msgid "Traditional Chinese" +msgstr "starokineski" + +msgid "Messages" +msgstr "Poruke" + +msgid "Site Maps" +msgstr "Mape sajta" + +msgid "Static Files" +msgstr "Statičke datoteke" + +msgid "Syndication" +msgstr "Udruživanje sadržaja" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Zadati broj strane nije ceo broj" + +msgid "That page number is less than 1" +msgstr "Zadati broj strane je manji od 1" + +msgid "That page contains no results" +msgstr "Tražena strana ne sadrži rezultate" + +msgid "Enter a valid value." +msgstr "Unesite ispravnu vrednost." + +msgid "Enter a valid URL." +msgstr "Unesite ispravan URL." + +msgid "Enter a valid integer." +msgstr "Unesite ispravan ceo broj." + +msgid "Enter a valid email address." +msgstr "Unesite ispravnu e-mail adresu." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Unesite isrpavan „slag“, koji se sastoji od slova, brojki, donjih crta ili " +"cirtica." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Unesite ispravan \"slag\", koji se sastoji od Unikod slova, brojki, donjih " +"crta ili crtica." + +msgid "Enter a valid IPv4 address." +msgstr "Unesite ispravnu IPv4 adresu." + +msgid "Enter a valid IPv6 address." +msgstr "Unesite ispravnu IPv6 adresu." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Unesite ispravnu IPv4 ili IPv6 adresu." + +msgid "Enter only digits separated by commas." +msgstr "Unesite samo brojke razdvojene zapetama." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Ovo polje mora da bude %(limit_value)s (trenutno ima %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Ova vrednost mora da bude manja od %(limit_value)s. ili tačno toliko." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Ova vrednost mora biti veća od %(limit_value)s ili tačno toliko." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "Ova vrednost mora da umnožak veličine koraka %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Ovo polje mora da ima najmanje %(limit_value)d karakter (trenutno ima " +"%(show_value)d)." +msgstr[1] "" +"Ovo polje mora da ima najmanje %(limit_value)d karaktera (trenutno ima " +"%(show_value)d)." +msgstr[2] "" +"Ovo polje mora da ima %(limit_value)d najmanje karaktera (trenutno ima " +"%(show_value)d )." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Ovo polje ne sme da ima više od %(limit_value)d karaktera (trenutno ima " +"%(show_value)d)." +msgstr[1] "" +"Ovo polje ne sme da ima više od %(limit_value)d karaktera (trenutno ima " +"%(show_value)d)." +msgstr[2] "" +"Ovo polje ne sme da ima više od %(limit_value)d karaktera (trenutno ima " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Unesite broj." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Ukupno ne može biti više od %(max)s cifre." +msgstr[1] "Ukupno ne može biti više od %(max)s cifre." +msgstr[2] "Ukupno ne može biti više od %(max)s cifara." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Ne može biti više od %(max)s decimale." +msgstr[1] "Ne može biti više od %(max)s decimale." +msgstr[2] "Ne može biti više od %(max)s decimala." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "Ne može biti više od %(max)s cifre pre decimalnog zapisa." +msgstr[1] "Ne može biti više od %(max)s cifre pre decimalnog zapisa." +msgstr[2] "Ne može biti više od %(max)s cifara pre decimalnog zapisa." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Ekstenzija datoteke \"%(extension)s\" nije dozvoljena. Dozvoljene su sledeće " +"ekstenzije: %(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "'Null' karakteri nisu dozvoljeni." + +msgid "and" +msgstr "i" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s sa poljem %(field_labels)s već postoji." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Ograničenje „%(name)s“ je prekršeno." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Vrednost %(value)r nije validna." + +msgid "This field cannot be null." +msgstr "Ovo polje ne može da ostane prazno." + +msgid "This field cannot be blank." +msgstr "Ovo polje ne može da ostane prazno." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s sa ovom vrednošću %(field_label)s već postoji." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s mora biti jedinstven(a) za %(date_field_label)s " +"%(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Polje tipa: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "Vrednost \"%(value)s\" mora biti True ili False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "\"%(value)s\" vrednost mora biti True, False ili None." + +msgid "Boolean (Either True or False)" +msgstr "Bulova vrednost (True ili False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "String (najviše %(max_length)s znakova)" + +msgid "String (unlimited)" +msgstr "String (neograničeno)" + +msgid "Comma-separated integers" +msgstr "Celi brojevi razdvojeni zapetama" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"Vrednost \"%(value)s\" nema ispravan format datuma. Mora biti u formatu GGGG-" +"MM-DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"Vrednost “%(value)s” ima odgovarajući format (GGGG-MM-DD), ali nije validan " +"datum." + +msgid "Date (without time)" +msgstr "Datum (bez vremena)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"Vrednost “%(value)s” je u nevažećem formatu. Mora se uneti u formatu YYYY-MM-" +"DD HH:MM[:ss[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"Vrednost “%(value)s” je u odgovarajućem formatu (YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ]), ali nije validna vrednost za datum i vreme." + +msgid "Date (with time)" +msgstr "Datum (sa vremenom)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "Vrednost “%(value)s” mora biti decimalni broj." + +msgid "Decimal number" +msgstr "Decimalni broj" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"Vrednost “%(value)s” nije u odgovarajućem formatu. Mora biti u formatu [DD] " +"[[HH:]MM:]ss[.uuuuuu]." + +msgid "Duration" +msgstr "Vremenski interval" + +msgid "Email address" +msgstr "Imejl adresa" + +msgid "File path" +msgstr "Putanja fajla" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "Vrednost “%(value)s” value mora biti tipa float." + +msgid "Floating point number" +msgstr "Broj sa pokrenom zapetom" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "Vrednost “%(value)s” mora biti ceo broj." + +msgid "Integer" +msgstr "Ceo broj" + +msgid "Big (8 byte) integer" +msgstr "Veliki ceo broj" + +msgid "Small integer" +msgstr "Mali ceo broj" + +msgid "IPv4 address" +msgstr "IPv4 adresa" + +msgid "IP address" +msgstr "IP adresa" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "Vrednost “%(value)s” mora biti None, True ili False." + +msgid "Boolean (Either True, False or None)" +msgstr "Bulova vrednost (True, False ili None)" + +msgid "Positive big integer" +msgstr "Velik pozitivan celi broj" + +msgid "Positive integer" +msgstr "Pozitivan ceo broj" + +msgid "Positive small integer" +msgstr "Pozitivan mali ceo broj" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slag (ne duži od %(max_length)s)" + +msgid "Text" +msgstr "Tekst" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"Vrednost “%(value)s” nije u odgovarajućem formatu. Mora biti u formatu HH:" +"MM[:ss[.uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"Vrednost “%(value)s” je u odgovarajućem formatu (HH:MM[:ss[.uuuuuu]]), ali " +"nije validna vrednost za vreme." + +msgid "Time" +msgstr "Vreme" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Sirovi binarni podaci" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "Vrednost “%(value)s” nije validan UUID (jedinstveni ID)." + +msgid "Universally unique identifier" +msgstr "Univerzalno jedinstveni identifikator" + +msgid "File" +msgstr "Fajl" + +msgid "Image" +msgstr "Slika" + +msgid "A JSON object" +msgstr "JSON objekat" + +msgid "Value must be valid JSON." +msgstr "Vrednost mora biti ispravni JSON." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "Instanca modela %(model)s sa vrednošću %(field)s %(value)r ne postoji." + +msgid "Foreign Key (type determined by related field)" +msgstr "Strani ključ (tip određuje referentno polje)" + +msgid "One-to-one relationship" +msgstr "Relacija jedan na jedan" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "Relacija %(from)s-%(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "Relacije %(from)s-%(to)s" + +msgid "Many-to-many relationship" +msgstr "Relacija više na više" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Ovo polje se mora popuniti." + +msgid "Enter a whole number." +msgstr "Unesite ceo broj." + +msgid "Enter a valid date." +msgstr "Unesite ispravan datum." + +msgid "Enter a valid time." +msgstr "Unesite ispravno vreme" + +msgid "Enter a valid date/time." +msgstr "Unesite ispravan datum/vreme." + +msgid "Enter a valid duration." +msgstr "Unesite ispravno trajanje." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Broj dana mora biti između {min_days} i {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Fajl nije prebačen. Proverite tip enkodiranja formulara." + +msgid "No file was submitted." +msgstr "Fajl nije prebačen." + +msgid "The submitted file is empty." +msgstr "Prebačen fajl je prazan." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Ime fajla ne može imati više od %(max)d karaktera (trenutno ima %(length)d)." +msgstr[1] "" +"Ime fajla ne može imati više od %(max)d karaktera (trenutno ima %(length)d)." +msgstr[2] "" +"Ime fajla ne može imati više od %(max)d karaktera (trenutno ima %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Može se samo poslati fajl ili izbrisati, ne oba." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Prebacite ispravan fajl. Fajl koji je prebačen ili nije slika, ili je " +"oštećen." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"%(value)s nije među ponuđenim vrednostima. Odaberite jednu od ponuđenih." + +msgid "Enter a list of values." +msgstr "Unesite listu vrednosti." + +msgid "Enter a complete value." +msgstr "Unesite kompletnu vrednost." + +msgid "Enter a valid UUID." +msgstr "Unesite ispravan UUID." + +msgid "Enter a valid JSON." +msgstr "Unesite ispravan JSON." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Skriveno polje %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"Podaci od ManagementForm nedostaju ili su pokvareni. Polja koja nedostaju: " +"%(field_names)s. Možda će biti potrebno da prijavite grešku ako se problem " +"nastavi." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Molim prosledite najviše %(num)d formular." +msgstr[1] "Molim prosledite najviše %(num)d formulara." +msgstr[2] "Molim prosledite najviše %(num)d formulara." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] " Molim prosledite najmanje %(num)d formular." +msgstr[1] " Molim prosledite najmanje %(num)d formulara." +msgstr[2] " Molim prosledite najmanje %(num)d formulara." + +msgid "Order" +msgstr "Redosled" + +msgid "Delete" +msgstr "Obriši" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Ispravite dupliran sadržaj za polja: %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Ispravite dupliran sadržaj za polja: %(field)s, koji mora da bude jedinstven." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Ispravite dupliran sadržaj za polja: %(field_name)s, koji mora da bude " +"jedinstven za %(lookup)s u %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Ispravite duplirane vrednosti dole." + +msgid "The inline value did not match the parent instance." +msgstr "Direktno uneta vrednost ne odgovara instanci roditelja." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Odabrana vrednost nije među ponuđenima. Odaberite jednu od ponuđenih." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "\"%(pk)s\" nije ispravna vrednost." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"Vreme %(datetime)s se ne može protumačiti u vremenskoj zoni " +"%(current_timezone)s; možda je dvosmisleno ili ne postoji." + +msgid "Clear" +msgstr "Očisti" + +msgid "Currently" +msgstr "Trenutno" + +msgid "Change" +msgstr "Izmeni" + +msgid "Unknown" +msgstr "Nepoznato" + +msgid "Yes" +msgstr "Da" + +msgid "No" +msgstr "Ne" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "da,ne,možda" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d bajt" +msgstr[1] "%(size)d bajta" +msgstr[2] "%(size)d bajtova" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "po p." + +msgid "a.m." +msgstr "pre p." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "ponoć" + +msgid "noon" +msgstr "podne" + +msgid "Monday" +msgstr "ponedeljak" + +msgid "Tuesday" +msgstr "utorak" + +msgid "Wednesday" +msgstr "sreda" + +msgid "Thursday" +msgstr "četvrtak" + +msgid "Friday" +msgstr "petak" + +msgid "Saturday" +msgstr "subota" + +msgid "Sunday" +msgstr "nedelja" + +msgid "Mon" +msgstr "pon." + +msgid "Tue" +msgstr "uto." + +msgid "Wed" +msgstr "sre." + +msgid "Thu" +msgstr "čet." + +msgid "Fri" +msgstr "pet." + +msgid "Sat" +msgstr "sub." + +msgid "Sun" +msgstr "ned." + +msgid "January" +msgstr "januar" + +msgid "February" +msgstr "februar" + +msgid "March" +msgstr "mart" + +msgid "April" +msgstr "april" + +msgid "May" +msgstr "maj" + +msgid "June" +msgstr "jun" + +msgid "July" +msgstr "jul" + +msgid "August" +msgstr "avgust" + +msgid "September" +msgstr "septembar" + +msgid "October" +msgstr "oktobar" + +msgid "November" +msgstr "novembar" + +msgid "December" +msgstr "decembar" + +msgid "jan" +msgstr "jan." + +msgid "feb" +msgstr "feb." + +msgid "mar" +msgstr "mar." + +msgid "apr" +msgstr "apr." + +msgid "may" +msgstr "maj." + +msgid "jun" +msgstr "jun." + +msgid "jul" +msgstr "jul." + +msgid "aug" +msgstr "aug." + +msgid "sep" +msgstr "sep." + +msgid "oct" +msgstr "okt." + +msgid "nov" +msgstr "nov." + +msgid "dec" +msgstr "dec." + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Mart" + +msgctxt "abbrev. month" +msgid "April" +msgstr "April" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Maj" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Jun" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Jul" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Avg." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Sept." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Okt." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dec." + +msgctxt "alt. month" +msgid "January" +msgstr "Januar" + +msgctxt "alt. month" +msgid "February" +msgstr "Februar" + +msgctxt "alt. month" +msgid "March" +msgstr "Mart" + +msgctxt "alt. month" +msgid "April" +msgstr "April" + +msgctxt "alt. month" +msgid "May" +msgstr "Maj" + +msgctxt "alt. month" +msgid "June" +msgstr "Jun" + +msgctxt "alt. month" +msgid "July" +msgstr "Jul" + +msgctxt "alt. month" +msgid "August" +msgstr "Avgust" + +msgctxt "alt. month" +msgid "September" +msgstr "Septembar" + +msgctxt "alt. month" +msgid "October" +msgstr "Oktobar" + +msgctxt "alt. month" +msgid "November" +msgstr "Novembar" + +msgctxt "alt. month" +msgid "December" +msgstr "Decembar" + +msgid "This is not a valid IPv6 address." +msgstr "Ovo nije ispravna IPv6 adresa." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s..." + +msgid "or" +msgstr "ili" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "," + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d godina" +msgstr[1] "%(num)d godine" +msgstr[2] "%(num)d godina" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mesec" +msgstr[1] "%(num)d meseca" +msgstr[2] "%(num)d meseci" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d nedelja" +msgstr[1] "%(num)d nedelje" +msgstr[2] "%(num)d nedelja" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dan" +msgstr[1] "%(num)d dana" +msgstr[2] "%(num)d dana" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d sat" +msgstr[1] "%(num)d sata" +msgstr[2] "%(num)d sati" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minut" +msgstr[1] "%(num)d minuta" +msgstr[2] "%(num)d minuta" + +msgid "Forbidden" +msgstr "Zabranjeno" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF verifikacija nije prošla. Zahtev odbijen." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Ova poruka je prikazana jer ovaj HTTPS sajt zahteva da \"Referer header\" " +"bude poslat od strane vašeg internet pregledača, što trenutno nije slučaj. " +"Pomenuto zaglavlje je potrebno iz bezbedonosnih razloga, da bi se osiguralo " +"da vaš pregledač nije pod kontrolom trećih lica." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Ako ste podesili internet pregledač da ne šalje \"Referer\" zaglavlja, " +"ponovo ih uključite, barem za ovaj sajt, ili za HTTPS konekcije, ili za " +"\"same-origin\" zahteve." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Ako koristite tag ili " +"\"Referrer-Policy: no-referrer\" zaglavlje, molimo da ih uklonite. CSRF " +"zaštita zahteva \"Referer\" zaglavlje da bi se obavila striktna \"referrer\" " +"provera. Ukoliko vas brine privatnost, koristite alternative kao za linkove ka drugim sajtovima." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Ova poruka je prikazana jer ovaj sajt zahteva CSRF kuki kada se prosleđuju " +"podaci iz formi. Ovaj kuki je potreban iz sigurnosnih razloga, da bi se " +"osiguralo da vaš pretraživač nije pod kontrolom trećih lica." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Ako je vaš internet pregedač podešen da onemogući kolačiće, molimo da ih " +"uključite, barem za ovaj sajt, ili za \"same-origin\" zahteve." + +msgid "More information is available with DEBUG=True." +msgstr "Više informacija je dostupno sa DEBUG=True." + +msgid "No year specified" +msgstr "Godina nije naznačena" + +msgid "Date out of range" +msgstr "Datum van opsega" + +msgid "No month specified" +msgstr "Mesec nije naznačen" + +msgid "No day specified" +msgstr "Dan nije naznačen" + +msgid "No week specified" +msgstr "Nedelja nije naznačena" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Nedostupni objekti %(verbose_name_plural)s" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Opcija „future“ nije dostupna za „%(verbose_name_plural)s“ jer " +"%(class_name)s.allow_future ima vrednost False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Neispravan datum \"%(datestr)s\" za format \"%(format)s\"" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Nijedan objekat klase %(verbose_name)s nije nađen datim upitom." + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Stranica nije poslednja, niti može biti konvertovana u tip \"int\"." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Neispravna strana (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Prazna lista i „%(class_name)s.allow_empty“ ima vrednost False." + +msgid "Directory indexes are not allowed here." +msgstr "Indeksi direktorijuma nisu dozvoljeni ovde." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "„%(path)s“ ne postoji" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Indeks direktorijuma %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Instalacija je prošla uspešno. Čestitke!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Pogledajte napomene uz izdanje za Đango " +"%(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Ova strana je prikazana jer je DEBUG=True u vašim podešavanjima i niste konfigurisali " +"nijedan URL." + +msgid "Django Documentation" +msgstr "Đango dokumentacija" + +msgid "Topics, references, & how-to’s" +msgstr "Teme, reference, & kako-da" + +msgid "Tutorial: A Polling App" +msgstr "Uputstvo: aplikacija za glasanje" + +msgid "Get started with Django" +msgstr "Počnite sa Đangom" + +msgid "Django Community" +msgstr "Đango zajednica" + +msgid "Connect, get help, or contribute" +msgstr "Povežite se, potražite pomoć ili dajte doprinos" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sr_Latn/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sr_Latn/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sr_Latn/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sr_Latn/formats.py new file mode 100644 index 0000000..0078895 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sr_Latn/formats.py @@ -0,0 +1,44 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j. F Y." +TIME_FORMAT = "H:i" +DATETIME_FORMAT = "j. F Y. H:i" +YEAR_MONTH_FORMAT = "F Y." +MONTH_DAY_FORMAT = "j. F" +SHORT_DATE_FORMAT = "j.m.Y." +SHORT_DATETIME_FORMAT = "j.m.Y. H:i" +FIRST_DAY_OF_WEEK = 1 + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d.%m.%Y.", # '25.10.2006.' + "%d.%m.%y.", # '25.10.06.' + "%d. %m. %Y.", # '25. 10. 2006.' + "%d. %m. %y.", # '25. 10. 06.' + # "%d. %b %y.", # '25. Oct 06.' + # "%d. %B %y.", # '25. October 06.' + # "%d. %b '%y.", # '25. Oct '06.' + # "%d. %B '%y.", #'25. October '06.' + # "%d. %b %Y.", # '25. Oct 2006.' + # "%d. %B %Y.", # '25. October 2006.' +] +DATETIME_INPUT_FORMATS = [ + "%d.%m.%Y. %H:%M:%S", # '25.10.2006. 14:30:59' + "%d.%m.%Y. %H:%M:%S.%f", # '25.10.2006. 14:30:59.000200' + "%d.%m.%Y. %H:%M", # '25.10.2006. 14:30' + "%d.%m.%y. %H:%M:%S", # '25.10.06. 14:30:59' + "%d.%m.%y. %H:%M:%S.%f", # '25.10.06. 14:30:59.000200' + "%d.%m.%y. %H:%M", # '25.10.06. 14:30' + "%d. %m. %Y. %H:%M:%S", # '25. 10. 2006. 14:30:59' + "%d. %m. %Y. %H:%M:%S.%f", # '25. 10. 2006. 14:30:59.000200' + "%d. %m. %Y. %H:%M", # '25. 10. 2006. 14:30' + "%d. %m. %y. %H:%M:%S", # '25. 10. 06. 14:30:59' + "%d. %m. %y. %H:%M:%S.%f", # '25. 10. 06. 14:30:59.000200' + "%d. %m. %y. %H:%M", # '25. 10. 06. 14:30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sv/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sv/LC_MESSAGES/django.mo new file mode 100644 index 0000000..6685971 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sv/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sv/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sv/LC_MESSAGES/django.po new file mode 100644 index 0000000..897dde5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sv/LC_MESSAGES/django.po @@ -0,0 +1,1342 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Albin Larsson , 2022 +# Alex Nordlund , 2012 +# Anders Hovmöller , 2023 +# Anders Jonsson , 2022 +# Andreas Pelme , 2014,2021 +# Elias Johnstone , 2022 +# Gustaf Hansen , 2015 +# Jannis Leidel , 2011 +# Jonathan Lindén, 2015 +# Ken Lewerentz, 2022 +# Jonathan Lindén, 2014 +# Mattias Hansson , 2016 +# Mattias Benjaminsson , 2011 +# Petter Strandmark , 2019 +# Rasmus Précenth , 2014 +# Samuel Linde , 2011 +# Thomas Lundqvist, 2013,2016 +# Tomas Lööw , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-25 06:49+0000\n" +"Last-Translator: Anders Hovmöller , 2023\n" +"Language-Team: Swedish (http://www.transifex.com/django/django/language/" +"sv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sv\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Afrikaans" + +msgid "Arabic" +msgstr "Arabiska" + +msgid "Algerian Arabic" +msgstr "Algerisk arabiska" + +msgid "Asturian" +msgstr "Asturiska" + +msgid "Azerbaijani" +msgstr "Azerbajdzjanska" + +msgid "Bulgarian" +msgstr "Bulgariska" + +msgid "Belarusian" +msgstr "Vitryska" + +msgid "Bengali" +msgstr "Bengaliska" + +msgid "Breton" +msgstr "Bretonska" + +msgid "Bosnian" +msgstr "Bosniska" + +msgid "Catalan" +msgstr "Katalanska" + +msgid "Central Kurdish (Sorani)" +msgstr "Kurdiska (Sorani)" + +msgid "Czech" +msgstr "Tjeckiska" + +msgid "Welsh" +msgstr "Walesiska" + +msgid "Danish" +msgstr "Danska" + +msgid "German" +msgstr "Tyska" + +msgid "Lower Sorbian" +msgstr "Lågsorbiska" + +msgid "Greek" +msgstr "Grekiska" + +msgid "English" +msgstr "Engelska" + +msgid "Australian English" +msgstr "Australisk engelska" + +msgid "British English" +msgstr "Brittisk engelska" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Spanska" + +msgid "Argentinian Spanish" +msgstr "Argentinsk spanska" + +msgid "Colombian Spanish" +msgstr "Colombiansk spanska" + +msgid "Mexican Spanish" +msgstr "Mexikansk spanska" + +msgid "Nicaraguan Spanish" +msgstr "Nicaraguansk spanska" + +msgid "Venezuelan Spanish" +msgstr "Spanska (Venezuela)" + +msgid "Estonian" +msgstr "Estländska" + +msgid "Basque" +msgstr "Baskiska" + +msgid "Persian" +msgstr "Persiska" + +msgid "Finnish" +msgstr "Finska" + +msgid "French" +msgstr "Franska" + +msgid "Frisian" +msgstr "Frisiska" + +msgid "Irish" +msgstr "Irländska" + +msgid "Scottish Gaelic" +msgstr "Skotsk gäliska" + +msgid "Galician" +msgstr "Galisiska" + +msgid "Hebrew" +msgstr "Hebreiska" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Kroatiska" + +msgid "Upper Sorbian" +msgstr "Högsorbiska" + +msgid "Hungarian" +msgstr "Ungerska" + +msgid "Armenian" +msgstr "Armeniska" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonesiska" + +msgid "Igbo" +msgstr "Igbo" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Isländska" + +msgid "Italian" +msgstr "Italienska" + +msgid "Japanese" +msgstr "Japanska" + +msgid "Georgian" +msgstr "Georgiska" + +msgid "Kabyle" +msgstr "Kabyliska" + +msgid "Kazakh" +msgstr "Kazakiska" + +msgid "Khmer" +msgstr "Khmer" + +msgid "Kannada" +msgstr "Kannada" + +msgid "Korean" +msgstr "Koreanska" + +msgid "Kyrgyz" +msgstr "Kirgiziska" + +msgid "Luxembourgish" +msgstr "Luxemburgiska" + +msgid "Lithuanian" +msgstr "Lettiska" + +msgid "Latvian" +msgstr "Lettiska" + +msgid "Macedonian" +msgstr "Makedonska" + +msgid "Malayalam" +msgstr "Malayalam" + +msgid "Mongolian" +msgstr "Mongoliska" + +msgid "Marathi" +msgstr "Marathi" + +msgid "Malay" +msgstr "Malajiska" + +msgid "Burmese" +msgstr "Burmesiska" + +msgid "Norwegian Bokmål" +msgstr "Norskt Bokmål" + +msgid "Nepali" +msgstr "Nepali" + +msgid "Dutch" +msgstr "Holländska" + +msgid "Norwegian Nynorsk" +msgstr "Norska (nynorsk)" + +msgid "Ossetic" +msgstr "Ossetiska" + +msgid "Punjabi" +msgstr "Punjabi" + +msgid "Polish" +msgstr "Polska" + +msgid "Portuguese" +msgstr "Portugisiska" + +msgid "Brazilian Portuguese" +msgstr "Brasiliensk portugisiska" + +msgid "Romanian" +msgstr "Rumänska" + +msgid "Russian" +msgstr "Ryska" + +msgid "Slovak" +msgstr "Slovakiska" + +msgid "Slovenian" +msgstr "Slovenska" + +msgid "Albanian" +msgstr "Albanska" + +msgid "Serbian" +msgstr "Serbiska" + +msgid "Serbian Latin" +msgstr "Serbiska (latin)" + +msgid "Swedish" +msgstr "Svenska" + +msgid "Swahili" +msgstr "Swahili" + +msgid "Tamil" +msgstr "Tamilska" + +msgid "Telugu" +msgstr "Telugu" + +msgid "Tajik" +msgstr "Tadzjikiska" + +msgid "Thai" +msgstr "Thailändska" + +msgid "Turkmen" +msgstr "Turkmeniska" + +msgid "Turkish" +msgstr "Turkiska" + +msgid "Tatar" +msgstr "Tatariska" + +msgid "Udmurt" +msgstr "Udmurtiska" + +msgid "Ukrainian" +msgstr "Ukrainska" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "Uzbekiska" + +msgid "Vietnamese" +msgstr "Vietnamesiska" + +msgid "Simplified Chinese" +msgstr "Förenklad Kinesiska" + +msgid "Traditional Chinese" +msgstr "Traditionell Kinesiska" + +msgid "Messages" +msgstr "Meddelanden" + +msgid "Site Maps" +msgstr "Sidkartor" + +msgid "Static Files" +msgstr "Statiska filer" + +msgid "Syndication" +msgstr "Syndikering" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "..." + +msgid "That page number is not an integer" +msgstr "Sidnumret är inte ett heltal" + +msgid "That page number is less than 1" +msgstr "Sidnumret är mindre än 1" + +msgid "That page contains no results" +msgstr "Sidan innehåller inga resultat" + +msgid "Enter a valid value." +msgstr "Fyll i ett giltigt värde." + +msgid "Enter a valid URL." +msgstr "Fyll i en giltig URL." + +msgid "Enter a valid integer." +msgstr "Fyll i ett giltigt heltal." + +msgid "Enter a valid email address." +msgstr "Fyll i en giltig e-postadress." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Fyll i en giltig 'slug', beståendes av bokstäver, siffror, understreck eller " +"bindestreck i Unicode." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Fyll i en giltig 'slug', beståendes av bokstäver, siffror, understreck eller " +"bindestreck i Unicode." + +msgid "Enter a valid IPv4 address." +msgstr "Fyll i en giltig IPv4-adress." + +msgid "Enter a valid IPv6 address." +msgstr "Ange en giltig IPv6-adress." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Ange en giltig IPv4- eller IPv6-adress." + +msgid "Enter only digits separated by commas." +msgstr "Fyll enbart i siffror separerade med kommatecken." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Kontrollera att detta värde är %(limit_value)s (det är %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" +"Kontrollera att detta värde är mindre än eller lika med %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" +"Kontrollera att detta värde är större än eller lika med %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" +"Kontrollera att detta värde är multipel av stegstorlek %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Säkerställ att detta värde åtminstone har %(limit_value)d tecken (den har " +"%(show_value)d)." +msgstr[1] "" +"Säkerställ att detta värde åtminstone har %(limit_value)d tecken (den har " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Säkerställ att detta värde har som mest %(limit_value)d tecken (den har " +"%(show_value)d)." +msgstr[1] "" +"Säkerställ att detta värde har som mest %(limit_value)d tecken (den har " +"%(show_value)d)." + +msgid "Enter a number." +msgstr "Fyll i ett tal." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Säkerställ att det inte är mer än %(max)s siffra totalt." +msgstr[1] "Säkerställ att det inte är mer än %(max)s siffror totalt." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Säkerställ att det inte är mer än %(max)s decimal." +msgstr[1] "Säkerställ att det inte är mer än %(max)s decimaler." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Säkerställ att det inte är mer än %(max)s siffra före decimalavskiljaren." +msgstr[1] "" +"Säkerställ att det inte är mer än %(max)s siffror före decimalavskiljaren." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Filändelsen “%(extension)s” är inte giltig. Giltiga filändelser är: " +"%(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Null-tecken är inte tillåtna." + +msgid "and" +msgstr "och" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s med samma %(field_labels)s finns redan." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Begränsningen “%(name)s” överträds." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Värdet %(value)r är inget giltigt alternativ." + +msgid "This field cannot be null." +msgstr "Detta fält får inte vara null." + +msgid "This field cannot be blank." +msgstr "Detta fält får inte vara tomt." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s med detta %(field_label)s finns redan." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s måste vara unikt för %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Fält av typ: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "Värdet \"%(value)s\" måste vara antingen True eller False." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "Värdet ”%(value)s” måste vara antingen True, False eller None." + +msgid "Boolean (Either True or False)" +msgstr "Boolesk (antingen True eller False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Sträng (upp till %(max_length)s)" + +msgid "String (unlimited)" +msgstr "Sträng (obegränsad)" + +msgid "Comma-separated integers" +msgstr "Komma-separerade heltal" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"“%(value)s” har ett ogiltigt datumformat. Det måste vara i formatet YYYY-MM-" +"DD." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"Värdet “%(value)s” har det giltiga formatet (YYYY-MM-DD) men det är ett " +"ogiltigt datum." + +msgid "Date (without time)" +msgstr "Datum (utan tid)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"“%(value)s” har ett ogiltigt format. Det måste vara i formatet YYYY-MM-DD HH:" +"MM[:ss[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"“%(value)s” har det giltiga formatet (YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) " +"men ett ogiltigt datum/tid." + +msgid "Date (with time)" +msgstr "Datum (med tid)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "Värdet “%(value)s” måste vara ett decimaltal." + +msgid "Decimal number" +msgstr "Decimaltal" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"“%(value)s” har ett ogiltigt format. Det måste vara i formatet [DD] " +"[[HH:]MM:]ss[.uuuuuu]." + +msgid "Duration" +msgstr "Tidsspann" + +msgid "Email address" +msgstr "E-postadress" + +msgid "File path" +msgstr "Sökväg till fil" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "Värdet \"%(value)s\" måste vara ett flyttal." + +msgid "Floating point number" +msgstr "Flyttal" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "Värdet \"%(value)s\" måste vara ett heltal." + +msgid "Integer" +msgstr "Heltal" + +msgid "Big (8 byte) integer" +msgstr "Stort (8 byte) heltal" + +msgid "Small integer" +msgstr "Litet heltal" + +msgid "IPv4 address" +msgstr "IPv4-adress" + +msgid "IP address" +msgstr "IP-adress" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "Värdet ”%(value)s” måste vara antingen None, True eller False." + +msgid "Boolean (Either True, False or None)" +msgstr "Boolesk (antingen True, False eller None)" + +msgid "Positive big integer" +msgstr "Positivt stort heltal" + +msgid "Positive integer" +msgstr "Positivt heltal" + +msgid "Positive small integer" +msgstr "Positivt litet heltal" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (upp till %(max_length)s)" + +msgid "Text" +msgstr "Text" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"“%(value)s” har ett ogiltigt format. Det måste vara i formatet HH:MM[:ss[." +"uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"Värdet “%(value)s” har det giltiga formatet (HH:MM[:ss[.uuuuuu]]) men det är " +"en ogiltig tid." + +msgid "Time" +msgstr "Tid" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Rå binärdata" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "“%(value)s” är inget giltigt UUID." + +msgid "Universally unique identifier" +msgstr "Globalt unik identifierare" + +msgid "File" +msgstr "Fil" + +msgid "Image" +msgstr "Bild" + +msgid "A JSON object" +msgstr "Ett JSON-objekt" + +msgid "Value must be valid JSON." +msgstr "Värdet måste vara giltig JSON." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "Modell %(model)s med %(field)s %(value)r finns inte." + +msgid "Foreign Key (type determined by related field)" +msgstr "Främmande nyckel (typ bestäms av relaterat fält)" + +msgid "One-to-one relationship" +msgstr "Ett-till-ett-samband" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s relation" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s relationer" + +msgid "Many-to-many relationship" +msgstr "Många-till-många-samband" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Detta fält måste fyllas i." + +msgid "Enter a whole number." +msgstr "Fyll i ett heltal." + +msgid "Enter a valid date." +msgstr "Fyll i ett giltigt datum." + +msgid "Enter a valid time." +msgstr "Fyll i en giltig tid." + +msgid "Enter a valid date/time." +msgstr "Fyll i ett giltigt datum/tid." + +msgid "Enter a valid duration." +msgstr "Fyll i ett giltigt tidsspann." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Antalet dagar måste vara mellan {min_days} och {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Ingen fil skickades. Kontrollera kodningstypen i formuläret." + +msgid "No file was submitted." +msgstr "Ingen fil skickades." + +msgid "The submitted file is empty." +msgstr "Den skickade filen är tom." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Säkerställ att filnamnet har som mest %(max)d tecken (den har %(length)d)." +msgstr[1] "" +"Säkerställ att filnamnet har som mest %(max)d tecken (den har %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Var vänlig antingen skicka en fil eller markera kryssrutan för att rensa, " +"inte både och. " + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Ladda upp en giltig bild. Filen du laddade upp var antingen ingen bild eller " +"en korrupt bild." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Välj ett giltigt alternativ. %(value)s finns inte bland tillgängliga " +"alternativ." + +msgid "Enter a list of values." +msgstr "Fyll i en lista med värden." + +msgid "Enter a complete value." +msgstr "Fyll i ett fullständigt värde." + +msgid "Enter a valid UUID." +msgstr "Fyll i ett giltigt UUID." + +msgid "Enter a valid JSON." +msgstr "Fyll i ett giltigt JSON." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Gömt fält %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"ManagementForm-data saknas eller har manipulerats. Saknade fält: " +"%(field_names)s. Du kan behöva lämna in en felrapport om problemet kvarstår." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Vänligen skicka som mest %(num)d formulär." +msgstr[1] "Vänligen skicka som mest %(num)d formulär." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Vänligen skicka minst %(num)d formulär." +msgstr[1] "Vänligen skicka minst %(num)d formulär." + +msgid "Order" +msgstr "Sortering" + +msgid "Delete" +msgstr "Radera" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Var vänlig korrigera duplikatdata för %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Var vänlig korrigera duplikatdata för %(field)s, som måste vara unik." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Var vänlig korrigera duplikatdata för %(field_name)s som måste vara unik för " +"%(lookup)s i %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Vänligen korrigera duplikatvärdena nedan." + +msgid "The inline value did not match the parent instance." +msgstr "Värdet för InlineForeignKeyField motsvarade inte dess motpart." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Välj ett giltigt alternativ. Det valet finns inte bland tillgängliga " +"alternativ." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "“%(pk)s” är inte ett giltigt värde." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s kunde inte tolkas i tidszonen %(current_timezone)s; det kan " +"vara en ogiltig eller tvetydigt tidpunkt." + +msgid "Clear" +msgstr "Rensa" + +msgid "Currently" +msgstr "Nuvarande" + +msgid "Change" +msgstr "Ändra" + +msgid "Unknown" +msgstr "Okänt" + +msgid "Yes" +msgstr "Ja" + +msgid "No" +msgstr "Nej" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "ja,nej,kanske" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d byte" +msgstr[1] "%(size)d byte" + +#, python-format +msgid "%s KB" +msgstr "%s kB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "e.m." + +msgid "a.m." +msgstr "f.m." + +msgid "PM" +msgstr "FM" + +msgid "AM" +msgstr "EM" + +msgid "midnight" +msgstr "midnatt" + +msgid "noon" +msgstr "middag" + +msgid "Monday" +msgstr "måndag" + +msgid "Tuesday" +msgstr "tisdag" + +msgid "Wednesday" +msgstr "onsdag" + +msgid "Thursday" +msgstr "torsdag" + +msgid "Friday" +msgstr "fredag" + +msgid "Saturday" +msgstr "lördag" + +msgid "Sunday" +msgstr "söndag" + +msgid "Mon" +msgstr "mån" + +msgid "Tue" +msgstr "tis" + +msgid "Wed" +msgstr "ons" + +msgid "Thu" +msgstr "tors" + +msgid "Fri" +msgstr "fre" + +msgid "Sat" +msgstr "lör" + +msgid "Sun" +msgstr "sön" + +msgid "January" +msgstr "januari" + +msgid "February" +msgstr "februari" + +msgid "March" +msgstr "mars" + +msgid "April" +msgstr "april" + +msgid "May" +msgstr "maj" + +msgid "June" +msgstr "juni" + +msgid "July" +msgstr "juli" + +msgid "August" +msgstr "augusti" + +msgid "September" +msgstr "september" + +msgid "October" +msgstr "oktober" + +msgid "November" +msgstr "november" + +msgid "December" +msgstr "december" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "apr" + +msgid "may" +msgstr "maj" + +msgid "jun" +msgstr "jun" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "aug" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "okt" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dec" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "jan" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "feb" + +msgctxt "abbrev. month" +msgid "March" +msgstr "mars" + +msgctxt "abbrev. month" +msgid "April" +msgstr "april" + +msgctxt "abbrev. month" +msgid "May" +msgstr "maj" + +msgctxt "abbrev. month" +msgid "June" +msgstr "juni" + +msgctxt "abbrev. month" +msgid "July" +msgstr "juli" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "aug" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "sep" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "okt" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "nov" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "dec" + +msgctxt "alt. month" +msgid "January" +msgstr "januari" + +msgctxt "alt. month" +msgid "February" +msgstr "februari" + +msgctxt "alt. month" +msgid "March" +msgstr "mars" + +msgctxt "alt. month" +msgid "April" +msgstr "april" + +msgctxt "alt. month" +msgid "May" +msgstr "maj" + +msgctxt "alt. month" +msgid "June" +msgstr "juni" + +msgctxt "alt. month" +msgid "July" +msgstr "juli" + +msgctxt "alt. month" +msgid "August" +msgstr "augusti" + +msgctxt "alt. month" +msgid "September" +msgstr "september" + +msgctxt "alt. month" +msgid "October" +msgstr "oktober" + +msgctxt "alt. month" +msgid "November" +msgstr "november" + +msgctxt "alt. month" +msgid "December" +msgstr "december" + +msgid "This is not a valid IPv6 address." +msgstr "Detta är inte en giltig IPv6 adress." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "eller" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d år" +msgstr[1] "%(num)d år" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d månad" +msgstr[1] "%(num)d månader" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d vecka" +msgstr[1] "%(num)d veckor" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dag" +msgstr[1] "%(num)d dagar" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d timme" +msgstr[1] "%(num)d timmar" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minut" +msgstr[1] "%(num)d minuter" + +msgid "Forbidden" +msgstr "Otillåtet" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF-verifikation misslyckades. Förfrågan avbröts." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Du ser detta meddelande eftersom denna HTTPS-sida kräver att en “Referer " +"header” skickas från din webbläsare, men ingen skickades. Denna header krävs " +"av säkerhetsskäl, för att säkerställa att din webbläsare inte kapats." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Om 'Referer' headers är inaktiverade i din webbläsare, vänligen återaktivera " +"dem, åtminstone för denna sida, eller för HTTPS-anslutningar eller för 'same-" +"origin'-förfrågningar." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Om du använder -taggen eller " +"har med ”Referrer-Policy: no-referrer”, ta bort dem. CSRF-skyddet kräver " +"”Referer” för att kunna göra sin strikta kontroll. Om du oroar dig över din " +"integritet, använd alternativ såsom för länkar " +"till tredjepart." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Du ser detta meddelande eftersom denna sida kräver en CSRF-cookie när " +"formulär skickas. Denna cookie krävs av säkerhetsskäl, för att säkerställa " +"att din webbläsare inte kapats." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Om cookies är inaktiverade i din webbläsare, vänligen återaktivera dem, " +"åtminstone för denna sida eller för “same-origin”-förfrågningar." + +msgid "More information is available with DEBUG=True." +msgstr "Mer information är tillgänglig med DEBUG=True." + +msgid "No year specified" +msgstr "Inget år angivet" + +msgid "Date out of range" +msgstr "Datum är utanför intervallet" + +msgid "No month specified" +msgstr "Ingen månad angiven" + +msgid "No day specified" +msgstr "Ingen dag angiven" + +msgid "No week specified" +msgstr "Ingen vecka angiven" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Inga %(verbose_name_plural)s är tillgängliga" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Framtida %(verbose_name_plural)s är inte tillgängliga eftersom " +"%(class_name)s.allow_future är False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Ogiltig datumsträng “%(datestr)s” med givet format “%(format)s”" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Hittade inga %(verbose_name)s som matchar frågan" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Sidan är inte 'last', och kan inte heller omvandlas till en int." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Ogiltig sida (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Tom lista och '%(class_name)s.allow_empty' är False." + +msgid "Directory indexes are not allowed here." +msgstr "Kataloglistningar är inte tillåtna här." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "\"%(path)s\" finns inte" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Innehåll i %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Installationen lyckades! Grattis!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Visa release notes för Django %(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Du ser den här sidan eftersom DEBUG=True i din settings-fil och du har inte " +"konfigurerat några URL:er." + +msgid "Django Documentation" +msgstr "Djangodokumentation" + +msgid "Topics, references, & how-to’s" +msgstr "Ämnen, referenser och how-to’s" + +msgid "Tutorial: A Polling App" +msgstr "Tutorial: En undersöknings-app" + +msgid "Get started with Django" +msgstr "Kom igång med Django" + +msgid "Django Community" +msgstr "Djangos community" + +msgid "Connect, get help, or contribute" +msgstr "Kontakta, begär hjälp eller bidra" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sv/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sv/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sv/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sv/formats.py new file mode 100644 index 0000000..29e6317 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sv/formats.py @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j F Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = "j F Y H:i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "Y-m-d" +SHORT_DATETIME_FORMAT = "Y-m-d H:i" +FIRST_DAY_OF_WEEK = 1 + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# Kept ISO formats as they are in first position +DATE_INPUT_FORMATS = [ + "%Y-%m-%d", # '2006-10-25' + "%m/%d/%Y", # '10/25/2006' + "%m/%d/%y", # '10/25/06' +] +DATETIME_INPUT_FORMATS = [ + "%Y-%m-%d %H:%M:%S", # '2006-10-25 14:30:59' + "%Y-%m-%d %H:%M:%S.%f", # '2006-10-25 14:30:59.000200' + "%Y-%m-%d %H:%M", # '2006-10-25 14:30' + "%m/%d/%Y %H:%M:%S", # '10/25/2006 14:30:59' + "%m/%d/%Y %H:%M:%S.%f", # '10/25/2006 14:30:59.000200' + "%m/%d/%Y %H:%M", # '10/25/2006 14:30' + "%m/%d/%y %H:%M:%S", # '10/25/06 14:30:59' + "%m/%d/%y %H:%M:%S.%f", # '10/25/06 14:30:59.000200' + "%m/%d/%y %H:%M", # '10/25/06 14:30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "\xa0" # non-breaking space +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sw/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sw/LC_MESSAGES/django.mo new file mode 100644 index 0000000..449d588 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sw/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sw/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sw/LC_MESSAGES/django.po new file mode 100644 index 0000000..273893d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/sw/LC_MESSAGES/django.po @@ -0,0 +1,1221 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Machaku, 2015 +# Machaku, 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Swahili (http://www.transifex.com/django/django/language/" +"sw/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sw\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Kiafrikaani" + +msgid "Arabic" +msgstr "Kiarabu" + +msgid "Asturian" +msgstr "" + +msgid "Azerbaijani" +msgstr "Kiazerbaijani" + +msgid "Bulgarian" +msgstr "Kibulgaria" + +msgid "Belarusian" +msgstr "Kibelarusi" + +msgid "Bengali" +msgstr "Kibengali" + +msgid "Breton" +msgstr "Kibretoni" + +msgid "Bosnian" +msgstr "Kibosnia" + +msgid "Catalan" +msgstr "Kikatalani" + +msgid "Czech" +msgstr "Kicheki" + +msgid "Welsh" +msgstr "Kiweli" + +msgid "Danish" +msgstr "Kideni" + +msgid "German" +msgstr "Kijerumani" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "Kigiriki" + +msgid "English" +msgstr "Kiingereza" + +msgid "Australian English" +msgstr "Kiingereza cha Kiaustalia" + +msgid "British English" +msgstr "Kiingereza cha Uingereza" + +msgid "Esperanto" +msgstr "Kiesperanto" + +msgid "Spanish" +msgstr "Kihispania" + +msgid "Argentinian Spanish" +msgstr "Kihispania cha Argentina" + +msgid "Colombian Spanish" +msgstr "" + +msgid "Mexican Spanish" +msgstr "Kihispania cha Mexico" + +msgid "Nicaraguan Spanish" +msgstr "Kihispania cha Nikaragua" + +msgid "Venezuelan Spanish" +msgstr "Kihispania cha Kivenezuela" + +msgid "Estonian" +msgstr "Kiestonia" + +msgid "Basque" +msgstr "Kibaskyue" + +msgid "Persian" +msgstr "Kipershia" + +msgid "Finnish" +msgstr "Kifini" + +msgid "French" +msgstr "Kifaransa" + +msgid "Frisian" +msgstr "Kifrisi" + +msgid "Irish" +msgstr "Kiairishi" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "Kigalatia" + +msgid "Hebrew" +msgstr "Kiyahudi" + +msgid "Hindi" +msgstr "Kihindi" + +msgid "Croatian" +msgstr "Kikroeshia" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "Kihangaria" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "" + +msgid "Indonesian" +msgstr "Kiindonesia" + +msgid "Ido" +msgstr "" + +msgid "Icelandic" +msgstr "Kiaiselandi" + +msgid "Italian" +msgstr "Kiitaliano" + +msgid "Japanese" +msgstr "Kijapani" + +msgid "Georgian" +msgstr "Kijiojia" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "Kizakhi" + +msgid "Khmer" +msgstr "Kihema" + +msgid "Kannada" +msgstr "Kikanada" + +msgid "Korean" +msgstr "Kikorea" + +msgid "Luxembourgish" +msgstr "" + +msgid "Lithuanian" +msgstr "Kilithuania" + +msgid "Latvian" +msgstr "Kilatvia" + +msgid "Macedonian" +msgstr "Kimacedonia" + +msgid "Malayalam" +msgstr "Kimalayalam" + +msgid "Mongolian" +msgstr "Kimongolia" + +msgid "Marathi" +msgstr "" + +msgid "Burmese" +msgstr "" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "Kinepali" + +msgid "Dutch" +msgstr "Kidachi" + +msgid "Norwegian Nynorsk" +msgstr "Kinynorki cha Kinorwei" + +msgid "Ossetic" +msgstr "" + +msgid "Punjabi" +msgstr "Kipanjabi" + +msgid "Polish" +msgstr "Kipolishi" + +msgid "Portuguese" +msgstr "Kireno" + +msgid "Brazilian Portuguese" +msgstr "Kireno cha Kibrazili" + +msgid "Romanian" +msgstr "Kiromania" + +msgid "Russian" +msgstr "Kirusi" + +msgid "Slovak" +msgstr "Kislovakia" + +msgid "Slovenian" +msgstr "Kislovenia" + +msgid "Albanian" +msgstr "Kialbania" + +msgid "Serbian" +msgstr "Kiserbia" + +msgid "Serbian Latin" +msgstr "Kilatini cha Kiserbia" + +msgid "Swedish" +msgstr "Kiswidi" + +msgid "Swahili" +msgstr "Kiswahili" + +msgid "Tamil" +msgstr "Kitamili" + +msgid "Telugu" +msgstr "kitegulu" + +msgid "Thai" +msgstr "Kithai" + +msgid "Turkish" +msgstr "Kituruki" + +msgid "Tatar" +msgstr "Kitatari" + +msgid "Udmurt" +msgstr "" + +msgid "Ukrainian" +msgstr "Kiukreni" + +msgid "Urdu" +msgstr "Kiurdu" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "Kivietinamu" + +msgid "Simplified Chinese" +msgstr "Kichina Kilichorahisishwa" + +msgid "Traditional Chinese" +msgstr "Kichina Asilia" + +msgid "Messages" +msgstr "" + +msgid "Site Maps" +msgstr "" + +msgid "Static Files" +msgstr "" + +msgid "Syndication" +msgstr "" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "Ingiza thamani halali" + +msgid "Enter a valid URL." +msgstr "Ingiza URL halali." + +msgid "Enter a valid integer." +msgstr "Ingiza namba halali" + +msgid "Enter a valid email address." +msgstr "Ingiza anuani halali ya barua pepe" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Ingiza anuani halali ya IPV4" + +msgid "Enter a valid IPv6 address." +msgstr "Ingiza anuani halali ya IPV6" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Ingiza anuani halali za IPV4 au IPV6" + +msgid "Enter only digits separated by commas." +msgstr "Ingiza tarakimu zilizotenganishwa kwa koma tu." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Hakikisha thamani hii ni %(limit_value)s (ni %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Hakikisha thamani hii ni ndogo kuliko au sawa na %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Hakikisha thamani hii ni kubwa kuliko au sawa na %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Enter a number." +msgstr "Ingiza namba" + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "na" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "Uga huu hauwezi kuwa hauna kitu." + +msgid "This field cannot be blank." +msgstr "Uga huu hauwezi kuwa mtupu" + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "Tayari kuna %(field_label)s kwa %(model_name)s nyingine." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Uga wa aina %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "Buleani (Aidha Kweli au Si kweli)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Tungo (hadi %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "Inteja zilizotengwa kwa koma" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "Tarehe (bila ya muda)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Tarehe (pamoja na muda)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Namba ya desimali" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "" + +msgid "Email address" +msgstr "Anuani ya baruapepe" + +msgid "File path" +msgstr "Njia ya faili" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "Namba ya `floating point`" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "Inteja" + +msgid "Big (8 byte) integer" +msgstr "Inteja kubwa (baiti 8)" + +msgid "IPv4 address" +msgstr "anuani ya IPV4" + +msgid "IP address" +msgstr "anuani ya IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "Buleani (Aidha kweli, Si kweli au Hukuna)" + +msgid "Positive integer" +msgstr "Inteja chanya" + +msgid "Positive small integer" +msgstr "Inteja chanya ndogo" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slagi (hadi %(max_length)s)" + +msgid "Small integer" +msgstr "Inteja ndogo" + +msgid "Text" +msgstr "Maandishi" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Muda" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "Faili" + +msgid "Image" +msgstr "Picha" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "'Foreign Key' (aina inapatikana kwa uga unaohusiana)" + +msgid "One-to-one relationship" +msgstr "Uhusiano wa moja-kwa-moja" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "Uhusiano wa vingi-kwa-vingi" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Sehemu hii inahitajika" + +msgid "Enter a whole number." +msgstr "Ingiza namba kamili" + +msgid "Enter a valid date." +msgstr "Ingiza tarehe halali" + +msgid "Enter a valid time." +msgstr "Ingiza muda halali" + +msgid "Enter a valid date/time." +msgstr "Ingiza tarehe/muda halali" + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Hakuna faili lililokusanywa. Angalia aina ya msimbo kwenye fomu." + +msgid "No file was submitted." +msgstr "Hakuna faili lililokusanywa." + +msgid "The submitted file is empty." +msgstr "Faili lililokusanywa ni tupu." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Tafadhali aidha kusanya faili au tiki kisanduku kilicho wazi, si yote." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Pakia picha halali. Faili ulilopakia lilikua aidha si picha au ni picha " +"iliyopotoshwa." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Chagua chaguo halali. %(value)s si moja kati ya machaguo yaliyopo." + +msgid "Enter a list of values." +msgstr "Ingiza orodha ya thamani" + +msgid "Enter a complete value." +msgstr "" + +msgid "Enter a valid UUID." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "Panga" + +msgid "Delete" +msgstr "Futa" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Tafadhali rekebisha data zilizojirudia kwa %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Tafadhali rekebisha data zilizojirudia kwa %(field)s, zinazotakiwa kuwa za " +"kipekee." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Tafadhali sahihisha data zilizojirudia kwa %(field_name)s ,uga huu ni lazima " +"kuwa wa pekee kwa %(lookup)s katika %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Tafadhali sahihisha thamani zilizojirudia hapo chini." + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Chagua chaguo halali. Chaguo hilo si moja kati ya chaguzi halali" + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Safisha" + +msgid "Currently" +msgstr "Kwa sasa" + +msgid "Change" +msgstr "Badili" + +msgid "Unknown" +msgstr "Haijulikani" + +msgid "Yes" +msgstr "Ndiyo" + +msgid "No" +msgstr "Hapana" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "ndiyo,hapana,labda" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "baiti %(size)d" +msgstr[1] "baiti %(size)d" + +#, python-format +msgid "%s KB" +msgstr "KB %s" + +#, python-format +msgid "%s MB" +msgstr "MB %s" + +#, python-format +msgid "%s GB" +msgstr "GB %s" + +#, python-format +msgid "%s TB" +msgstr "TB %s" + +#, python-format +msgid "%s PB" +msgstr "PB %s" + +msgid "p.m." +msgstr "p.m" + +msgid "a.m." +msgstr "a.m" + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "usiku wa manane" + +msgid "noon" +msgstr "mchana" + +msgid "Monday" +msgstr "Jumatatu" + +msgid "Tuesday" +msgstr "Jumanne" + +msgid "Wednesday" +msgstr "Jumatano" + +msgid "Thursday" +msgstr "Alhamisi" + +msgid "Friday" +msgstr "Ijumaa" + +msgid "Saturday" +msgstr "Jumamosi" + +msgid "Sunday" +msgstr "Jumapili" + +msgid "Mon" +msgstr "Jtatu" + +msgid "Tue" +msgstr "Jnne" + +msgid "Wed" +msgstr "jtano" + +msgid "Thu" +msgstr "Alh" + +msgid "Fri" +msgstr "Ijmaa" + +msgid "Sat" +msgstr "Jmosi" + +msgid "Sun" +msgstr "Jpili" + +msgid "January" +msgstr "Januari" + +msgid "February" +msgstr "Februari" + +msgid "March" +msgstr "Machi" + +msgid "April" +msgstr "Aprili" + +msgid "May" +msgstr "Mei" + +msgid "June" +msgstr "Juni" + +msgid "July" +msgstr "Julai" + +msgid "August" +msgstr "Agosti" + +msgid "September" +msgstr "Septemba" + +msgid "October" +msgstr "Oktoba" + +msgid "November" +msgstr "Novemba" + +msgid "December" +msgstr "Disemba" + +msgid "jan" +msgstr "jan" + +msgid "feb" +msgstr "feb" + +msgid "mar" +msgstr "machi" + +msgid "apr" +msgstr "apr" + +msgid "may" +msgstr "mei" + +msgid "jun" +msgstr "Juni" + +msgid "jul" +msgstr "jul" + +msgid "aug" +msgstr "ago" + +msgid "sep" +msgstr "sep" + +msgid "oct" +msgstr "okt" + +msgid "nov" +msgstr "nov" + +msgid "dec" +msgstr "dis" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Jan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Feb." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Machi" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Aprili" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Mei" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Juni" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Julai" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Ago." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Sep." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Okt." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Nov." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dis." + +msgctxt "alt. month" +msgid "January" +msgstr "Januari" + +msgctxt "alt. month" +msgid "February" +msgstr "Februari" + +msgctxt "alt. month" +msgid "March" +msgstr "Machi" + +msgctxt "alt. month" +msgid "April" +msgstr "Aprili" + +msgctxt "alt. month" +msgid "May" +msgstr "Mei" + +msgctxt "alt. month" +msgid "June" +msgstr "Juni" + +msgctxt "alt. month" +msgid "July" +msgstr "Julai" + +msgctxt "alt. month" +msgid "August" +msgstr "Agosti" + +msgctxt "alt. month" +msgid "September" +msgstr "Septemba" + +msgctxt "alt. month" +msgid "October" +msgstr "Oktoba" + +msgctxt "alt. month" +msgid "November" +msgstr "Novemba" + +msgctxt "alt. month" +msgid "December" +msgstr "Disemba" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "au" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "mwaka %d" +msgstr[1] "miaka %d" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "mwezi %d" +msgstr[1] "miezi %d" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "wiki %d" +msgstr[1] "wiki %d" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "siku %d" +msgstr[1] "siku %d" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "saa %d" +msgstr[1] "saa %d" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "dakika %d" +msgstr[1] "dakika %d" + +msgid "0 minutes" +msgstr "dakika 0" + +msgid "Forbidden" +msgstr "Marufuku" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "Maelezo zaidi yanapatikana ikiwa DEBUG=True" + +msgid "No year specified" +msgstr "Hakuna mwaka maalum uliotajwa" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "Hakuna mwezi maalum uliotajwa" + +msgid "No day specified" +msgstr "Hakuna siku maalum iliyitajwa" + +msgid "No week specified" +msgstr "Hakuna wiki maalum iliyotajwa" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Hakujapatikana %(verbose_name_plural)s" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"%(verbose_name_plural)s kutoka wakati ujao haiwezekani kwani `" +"%(class_name)s.allow_future` ni `False`." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "hakuna %(verbose_name)s kulingana na ulizo" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Ukurasa batili (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Sahirisi za saraka haziruhusiwi hapa." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Sahirisi ya %(directory)s" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ta/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ta/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1c684f8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ta/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ta/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ta/LC_MESSAGES/django.po new file mode 100644 index 0000000..ad7bf71 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ta/LC_MESSAGES/django.po @@ -0,0 +1,1230 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Claude Paroz , 2020 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-19 20:23+0200\n" +"PO-Revision-Date: 2020-07-14 21:42+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Tamil (http://www.transifex.com/django/django/language/ta/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ta\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "" + +msgid "Arabic" +msgstr "அரபிக்" + +msgid "Algerian Arabic" +msgstr "" + +msgid "Asturian" +msgstr "" + +msgid "Azerbaijani" +msgstr "" + +msgid "Bulgarian" +msgstr "" + +msgid "Belarusian" +msgstr "" + +msgid "Bengali" +msgstr "பெங்காலி" + +msgid "Breton" +msgstr "" + +msgid "Bosnian" +msgstr "" + +msgid "Catalan" +msgstr "" + +msgid "Czech" +msgstr "செக்" + +msgid "Welsh" +msgstr "வெல்ஸ்" + +msgid "Danish" +msgstr "டேனிஷ்" + +msgid "German" +msgstr "ஜெர்மன்" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "கிரேக்கம்" + +msgid "English" +msgstr "ஆங்கிலம்" + +msgid "Australian English" +msgstr "" + +msgid "British English" +msgstr "" + +msgid "Esperanto" +msgstr "" + +msgid "Spanish" +msgstr "ஸ்பானிஷ்" + +msgid "Argentinian Spanish" +msgstr "" + +msgid "Colombian Spanish" +msgstr "" + +msgid "Mexican Spanish" +msgstr "" + +msgid "Nicaraguan Spanish" +msgstr "" + +msgid "Venezuelan Spanish" +msgstr "" + +msgid "Estonian" +msgstr "" + +msgid "Basque" +msgstr "" + +msgid "Persian" +msgstr "" + +msgid "Finnish" +msgstr "பீனீஷ்" + +msgid "French" +msgstr "ப்ரென்சு" + +msgid "Frisian" +msgstr "" + +msgid "Irish" +msgstr "" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "கலீஷீயன்" + +msgid "Hebrew" +msgstr "ஹீப்ரு" + +msgid "Hindi" +msgstr "" + +msgid "Croatian" +msgstr "" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "ஹங்கேரியன்" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "" + +msgid "Indonesian" +msgstr "" + +msgid "Igbo" +msgstr "" + +msgid "Ido" +msgstr "" + +msgid "Icelandic" +msgstr "ஐஸ்லான்டிக்" + +msgid "Italian" +msgstr "இத்தாலியன்" + +msgid "Japanese" +msgstr "ஜப்பானிய" + +msgid "Georgian" +msgstr "" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "" + +msgid "Khmer" +msgstr "" + +msgid "Kannada" +msgstr "" + +msgid "Korean" +msgstr "" + +msgid "Kyrgyz" +msgstr "" + +msgid "Luxembourgish" +msgstr "" + +msgid "Lithuanian" +msgstr "" + +msgid "Latvian" +msgstr "" + +msgid "Macedonian" +msgstr "" + +msgid "Malayalam" +msgstr "" + +msgid "Mongolian" +msgstr "" + +msgid "Marathi" +msgstr "" + +msgid "Burmese" +msgstr "" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "" + +msgid "Dutch" +msgstr "டச்சு" + +msgid "Norwegian Nynorsk" +msgstr "" + +msgid "Ossetic" +msgstr "" + +msgid "Punjabi" +msgstr "" + +msgid "Polish" +msgstr "" + +msgid "Portuguese" +msgstr "" + +msgid "Brazilian Portuguese" +msgstr "" + +msgid "Romanian" +msgstr "ரோமானியன்" + +msgid "Russian" +msgstr "ரஷ்யன்" + +msgid "Slovak" +msgstr "சுலோவாக்" + +msgid "Slovenian" +msgstr "ஸ்லோவேனியன்" + +msgid "Albanian" +msgstr "" + +msgid "Serbian" +msgstr "செர்பியன்" + +msgid "Serbian Latin" +msgstr "" + +msgid "Swedish" +msgstr "சுவிடிஷ்" + +msgid "Swahili" +msgstr "" + +msgid "Tamil" +msgstr "தமிழ்" + +msgid "Telugu" +msgstr "" + +msgid "Tajik" +msgstr "" + +msgid "Thai" +msgstr "" + +msgid "Turkmen" +msgstr "" + +msgid "Turkish" +msgstr "துருக்கிஷ்" + +msgid "Tatar" +msgstr "" + +msgid "Udmurt" +msgstr "" + +msgid "Ukrainian" +msgstr "உக்ரேனியன்" + +msgid "Urdu" +msgstr "" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "" + +msgid "Simplified Chinese" +msgstr "எளிய சீன மொழி" + +msgid "Traditional Chinese" +msgstr "மரபு சீன மொழி" + +msgid "Messages" +msgstr "" + +msgid "Site Maps" +msgstr "" + +msgid "Static Files" +msgstr "" + +msgid "Syndication" +msgstr "" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "" + +msgid "Enter a valid URL." +msgstr "" + +msgid "Enter a valid integer." +msgstr "" + +msgid "Enter a valid email address." +msgstr "" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "" + +msgid "Enter a valid IPv6 address." +msgstr "" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "" + +msgid "Enter only digits separated by commas." +msgstr "இங்கு எண்களை மட்டுமே எழுதவும் காமவாள் தனிமைபடுத்தவும் " + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Enter a number." +msgstr "" + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "மற்றும்" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "இந்த புலம் காலியாக இருக்கக் கூடாது" + +msgid "This field cannot be blank." +msgstr "" + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "" + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "பூலியன் (சரி அல்லது தவறு)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "" + +msgid "Comma-separated integers" +msgstr "கமாவாள் பிரிக்கப்பட்ட முழு எண்" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "தேதி (நேரமில்லாமல்)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "தேதி (நேரமுடன்)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "தசம எண்கள்" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "" + +msgid "Email address" +msgstr "" + +msgid "File path" +msgstr "கோப்புப் பாதை" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "முழு எண்" + +msgid "Big (8 byte) integer" +msgstr "" + +msgid "IPv4 address" +msgstr "" + +msgid "IP address" +msgstr "IP விலாசம்" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "இலக்கு முறை (சரி, தவறு அல்லது ஒன்றும் இல்லை)" + +msgid "Positive big integer" +msgstr "" + +msgid "Positive integer" +msgstr "" + +msgid "Positive small integer" +msgstr "" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "" + +msgid "Small integer" +msgstr "" + +msgid "Text" +msgstr "உரை" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "நேரம்" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "" + +msgid "Image" +msgstr "" + +msgid "A JSON object" +msgstr "" + +msgid "Value must be valid JSON." +msgstr "" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "" + +msgid "One-to-one relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr "" + +msgid "This field is required." +msgstr "இந்த புலத்தில் மதிப்பு தேவை" + +msgid "Enter a whole number." +msgstr "முழு எண் மட்டுமே எழுதவும்" + +msgid "Enter a valid date." +msgstr "" + +msgid "Enter a valid time." +msgstr "" + +msgid "Enter a valid date/time." +msgstr "" + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "அந்த பக்கத்தின் encoding வகையைப் பரிசோதிக்க.கோப்பு சமர்பிக்கப் பட்டவில்லை " + +msgid "No file was submitted." +msgstr "" + +msgid "The submitted file is empty." +msgstr "சமர்பிக்கப் பட்ட கோப்புக் காலியாக உள்ளது" + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"முறையான படம் மட்டுமே பதிவேற்றம் செய்யவும். நீங்கள் பதிவேற்றம் செய்த கோப்பு படம் அள்ளாத " +"அல்லது கெட்டுப்போன கோப்பாகும்" + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" + +msgid "Enter a list of values." +msgstr "" + +msgid "Enter a complete value." +msgstr "" + +msgid "Enter a valid UUID." +msgstr "" + +msgid "Enter a valid JSON." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr "" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "" + +msgid "Delete" +msgstr "நீக்குக" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "" + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" + +msgid "Please correct the duplicate values below." +msgstr "" + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "" + +msgid "Currently" +msgstr "" + +msgid "Change" +msgstr "மாற்றுக" + +msgid "Unknown" +msgstr "தெரியாத" + +msgid "Yes" +msgstr "ஆம்" + +msgid "No" +msgstr "இல்லை" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "ஆம்,இல்லை,இருக்கலாம்" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%s KB" +msgstr "" + +#, python-format +msgid "%s MB" +msgstr "" + +#, python-format +msgid "%s GB" +msgstr "" + +#, python-format +msgid "%s TB" +msgstr "" + +#, python-format +msgid "%s PB" +msgstr "" + +msgid "p.m." +msgstr "" + +msgid "a.m." +msgstr "" + +msgid "PM" +msgstr "" + +msgid "AM" +msgstr "" + +msgid "midnight" +msgstr "" + +msgid "noon" +msgstr "" + +msgid "Monday" +msgstr "திங்கள்" + +msgid "Tuesday" +msgstr "செவ்வாய்" + +msgid "Wednesday" +msgstr "புதன்" + +msgid "Thursday" +msgstr "வியாழன்" + +msgid "Friday" +msgstr "வெள்ளி" + +msgid "Saturday" +msgstr "சனி" + +msgid "Sunday" +msgstr "ஞாயிறு" + +msgid "Mon" +msgstr "" + +msgid "Tue" +msgstr "" + +msgid "Wed" +msgstr "" + +msgid "Thu" +msgstr "" + +msgid "Fri" +msgstr "" + +msgid "Sat" +msgstr "" + +msgid "Sun" +msgstr "" + +msgid "January" +msgstr "ஜனவரி" + +msgid "February" +msgstr "பிப்ரவரி" + +msgid "March" +msgstr "மார்ச்" + +msgid "April" +msgstr "ஏப்ரல்" + +msgid "May" +msgstr "மே" + +msgid "June" +msgstr "ஜூன்" + +msgid "July" +msgstr "ஜூலை" + +msgid "August" +msgstr "ஆகஸ்டு" + +msgid "September" +msgstr "செப்டம்பர்" + +msgid "October" +msgstr "அக்டோபர்" + +msgid "November" +msgstr "நவம்பர்" + +msgid "December" +msgstr "டிசம்பர்" + +msgid "jan" +msgstr "ஜன" + +msgid "feb" +msgstr "பிப்" + +msgid "mar" +msgstr "மார்" + +msgid "apr" +msgstr "ஏப்" + +msgid "may" +msgstr "மே" + +msgid "jun" +msgstr "ஜூன்" + +msgid "jul" +msgstr "ஜூலை" + +msgid "aug" +msgstr "ஆக" + +msgid "sep" +msgstr "செப்" + +msgid "oct" +msgstr "அக்" + +msgid "nov" +msgstr "நவ" + +msgid "dec" +msgstr "டிச" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "" + +msgctxt "abbrev. month" +msgid "March" +msgstr "மார்ச்" + +msgctxt "abbrev. month" +msgid "April" +msgstr "ஏப்ரல்" + +msgctxt "abbrev. month" +msgid "May" +msgstr "மே" + +msgctxt "abbrev. month" +msgid "June" +msgstr "ஜூன்" + +msgctxt "abbrev. month" +msgid "July" +msgstr "ஜூலை" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "" + +msgctxt "alt. month" +msgid "January" +msgstr "ஜனவரி" + +msgctxt "alt. month" +msgid "February" +msgstr "பிப்ரவரி" + +msgctxt "alt. month" +msgid "March" +msgstr "மார்ச்" + +msgctxt "alt. month" +msgid "April" +msgstr "ஏப்ரல்" + +msgctxt "alt. month" +msgid "May" +msgstr "மே" + +msgctxt "alt. month" +msgid "June" +msgstr "ஜூன்" + +msgctxt "alt. month" +msgid "July" +msgstr "ஜூலை" + +msgctxt "alt. month" +msgid "August" +msgstr "ஆகஸ்டு" + +msgctxt "alt. month" +msgid "September" +msgstr "செப்டம்பர்" + +msgctxt "alt. month" +msgid "October" +msgstr "அக்டோபர்" + +msgctxt "alt. month" +msgid "November" +msgstr "நவம்பர்" + +msgctxt "alt. month" +msgid "December" +msgstr "டிசம்பர்" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "" + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" + +msgid "Forbidden" +msgstr "" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "" + +msgid "No day specified" +msgstr "" + +msgid "No week specified" +msgstr "" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "" + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ta/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ta/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ta/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ta/formats.py new file mode 100644 index 0000000..d023608 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ta/formats.py @@ -0,0 +1,21 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j F, Y" +TIME_FORMAT = "g:i A" +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "j M, Y" +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +# DECIMAL_SEPARATOR = +# THOUSAND_SEPARATOR = +# NUMBER_GROUPING = diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/te/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/te/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1366ff2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/te/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/te/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/te/LC_MESSAGES/django.po new file mode 100644 index 0000000..168ffa4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/te/LC_MESSAGES/django.po @@ -0,0 +1,1233 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# bhaskar teja yerneni , 2011 +# Claude Paroz , 2020 +# Jannis Leidel , 2011 +# ప్రవీణ్ ఇళ్ళ , 2013 +# వీవెన్ , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-19 20:23+0200\n" +"PO-Revision-Date: 2020-07-14 21:42+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Telugu (http://www.transifex.com/django/django/language/te/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: te\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "ఆఫ్రికాన్స్" + +msgid "Arabic" +msgstr "ఆరబిక్" + +msgid "Algerian Arabic" +msgstr "" + +msgid "Asturian" +msgstr "" + +msgid "Azerbaijani" +msgstr "అజేర్బైజని " + +msgid "Bulgarian" +msgstr "బల్గేరియన్" + +msgid "Belarusian" +msgstr "బెలారషియన్" + +msgid "Bengali" +msgstr "బెంగాలీ" + +msgid "Breton" +msgstr "బ్రిటన్" + +msgid "Bosnian" +msgstr "బోస్నియన్" + +msgid "Catalan" +msgstr "కాటలాన్" + +msgid "Czech" +msgstr "ఛెక్" + +msgid "Welsh" +msgstr "వెల్ష్" + +msgid "Danish" +msgstr "డానిష్" + +msgid "German" +msgstr "జెర్మన్" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "గ్రీక్" + +msgid "English" +msgstr "ఆంగ్లం" + +msgid "Australian English" +msgstr "" + +msgid "British English" +msgstr "బ్రిటీష్ ఆంగ్లం" + +msgid "Esperanto" +msgstr "ఎస్పరాంటో" + +msgid "Spanish" +msgstr "స్పానిష్" + +msgid "Argentinian Spanish" +msgstr "అర్జెంటీనా స్పానిష్" + +msgid "Colombian Spanish" +msgstr "" + +msgid "Mexican Spanish" +msgstr "మెక్షికన్ స్పానిష్ " + +msgid "Nicaraguan Spanish" +msgstr "" + +msgid "Venezuelan Spanish" +msgstr "వెనుజులా స్పానిష్" + +msgid "Estonian" +msgstr "ఎస్టొనియన్" + +msgid "Basque" +msgstr "బాస్క్" + +msgid "Persian" +msgstr "పారసీ" + +msgid "Finnish" +msgstr "ఫీన్నిష్" + +msgid "French" +msgstr "ఫ్రెంచ్" + +msgid "Frisian" +msgstr "ఫ్రిసియన్" + +msgid "Irish" +msgstr "ఐరిష్" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "గలిసియన్" + +msgid "Hebrew" +msgstr "హీబ్రూ" + +msgid "Hindi" +msgstr "హిందీ" + +msgid "Croatian" +msgstr "క్రొయేషియన్" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "హంగేరియన్" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "ఇంటర్లింగ్వా" + +msgid "Indonesian" +msgstr "ఇండోనేషియన్" + +msgid "Igbo" +msgstr "" + +msgid "Ido" +msgstr "" + +msgid "Icelandic" +msgstr "ఐస్లాండిక్" + +msgid "Italian" +msgstr "ఇటాలియవ్" + +msgid "Japanese" +msgstr "జపనీ" + +msgid "Georgian" +msgstr "జార్జియన్" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "కజఖ్" + +msgid "Khmer" +msgstr "ఖ్మెర్" + +msgid "Kannada" +msgstr "కన్నడ" + +msgid "Korean" +msgstr "కొరియన్" + +msgid "Kyrgyz" +msgstr "" + +msgid "Luxembourgish" +msgstr "లగ్జెంబర్గిష్" + +msgid "Lithuanian" +msgstr "లిథుయేనియన్" + +msgid "Latvian" +msgstr "లాత్వియన్" + +msgid "Macedonian" +msgstr "మెసిడోనియన్" + +msgid "Malayalam" +msgstr "మలయాళం" + +msgid "Mongolian" +msgstr "మంగోలియన్" + +msgid "Marathi" +msgstr "" + +msgid "Burmese" +msgstr "బర్మీస్" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "నేపాలీ" + +msgid "Dutch" +msgstr "డచ్" + +msgid "Norwegian Nynorsk" +msgstr "నోర్వేగియన్ న్య్నోర్స్క్ " + +msgid "Ossetic" +msgstr "" + +msgid "Punjabi" +msgstr "పంజాబీ" + +msgid "Polish" +msgstr "పొలిష్" + +msgid "Portuguese" +msgstr "పోర్చుగీస్" + +msgid "Brazilian Portuguese" +msgstr "బ్రజీలియన్ పోర్చుగీస్" + +msgid "Romanian" +msgstr "రొమానియన్" + +msgid "Russian" +msgstr "రష్యన్" + +msgid "Slovak" +msgstr "స్లొవాక్" + +msgid "Slovenian" +msgstr "స్లొవానియన్" + +msgid "Albanian" +msgstr "అల్బేనియన్" + +msgid "Serbian" +msgstr "సెర్బియన్" + +msgid "Serbian Latin" +msgstr "సెర్బియన్ లాటిన్" + +msgid "Swedish" +msgstr "స్వీడిష్" + +msgid "Swahili" +msgstr "స్వాహిలి" + +msgid "Tamil" +msgstr "తమిళం" + +msgid "Telugu" +msgstr "తెలుగు" + +msgid "Tajik" +msgstr "" + +msgid "Thai" +msgstr "థాయి" + +msgid "Turkmen" +msgstr "" + +msgid "Turkish" +msgstr "టర్కిష్" + +msgid "Tatar" +msgstr "టటర్" + +msgid "Udmurt" +msgstr "" + +msgid "Ukrainian" +msgstr "ఉక్రేనియన్" + +msgid "Urdu" +msgstr "ఉర్దూ" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "వియెత్నామీ" + +msgid "Simplified Chinese" +msgstr "సరళ చైనీ" + +msgid "Traditional Chinese" +msgstr "సాంప్రదాయ చైనీ" + +msgid "Messages" +msgstr "" + +msgid "Site Maps" +msgstr "" + +msgid "Static Files" +msgstr "" + +msgid "Syndication" +msgstr "" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "సరైన విలువని ఇవ్వండి." + +msgid "Enter a valid URL." +msgstr "సరైన URL ఇవ్వండి." + +msgid "Enter a valid integer." +msgstr "" + +msgid "Enter a valid email address." +msgstr "దయచేసి సరైన ఈమెయిల్ చిరునామాను ప్రవేశపెట్టండి." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "దయచేసి సరైన IPv4 అడ్రస్ ఇవ్వండి" + +msgid "Enter a valid IPv6 address." +msgstr "" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "" + +msgid "Enter only digits separated by commas." +msgstr "కామాల తో అంకెలు విడడీసి ఇవ్వండి " + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"దయచేసి దీని విలువ %(limit_value)s గ ఉండేట్లు చూసుకొనుము. ( మీరు సమర్పించిన విలువ " +"%(show_value)s )" + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "దయచేసి దీని విలువ %(limit_value)s కు సమానముగా లేక తక్కువగా ఉండేట్లు చూసుకొనుము." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "దయచేసి దీని విలువ %(limit_value)s కు సమానముగా లేక ఎక్కువగా ఉండేట్లు చూసుకొనుము." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Enter a number." +msgstr "దయచేసి పూర్ణ సంఖ్య ఇవ్వండి" + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "మరియు" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "ఈ ఫీల్డ్ కాళీగా ఉందకూడడు " + +msgid "This field cannot be blank." +msgstr "ఈ ఖాళీని తప్పనిసరిగా పూరించాలి" + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "" + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "బూలియన్ (అవునా లేక కాదా)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "పదబంధం (గరిష్ఠం %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "కామా తో విడడీసిన సంఖ్య" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "తేదీ (సమయం లేకుండా)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "తేది (సమయం తో)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "దశగణసంఖ్య" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "" + +msgid "Email address" +msgstr "ఈమెయిలు చిరునామా" + +msgid "File path" +msgstr "ఫైల్ పాత్" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "పూర్ణసంఖ్య" + +msgid "Big (8 byte) integer" +msgstr "" + +msgid "IPv4 address" +msgstr "" + +msgid "IP address" +msgstr "ఐపీ చిరునామా" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "" + +msgid "Positive big integer" +msgstr "" + +msgid "Positive integer" +msgstr "" + +msgid "Positive small integer" +msgstr "" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "" + +msgid "Small integer" +msgstr "" + +msgid "Text" +msgstr "పాఠ్యం" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "సమయం" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "దస్త్రం" + +msgid "Image" +msgstr "బొమ్మ" + +msgid "A JSON object" +msgstr "" + +msgid "Value must be valid JSON." +msgstr "" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "" + +msgid "One-to-one relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr "" + +msgid "This field is required." +msgstr "ఈ ఫీల్డ్ అవసరము" + +msgid "Enter a whole number." +msgstr "పూర్ణ సంఖ్య ఇవ్వండి" + +msgid "Enter a valid date." +msgstr "దయచేసి సరైన తేది ఇవ్వండి." + +msgid "Enter a valid time." +msgstr "దయచేసి సరైన సమయం ఇవ్వండి." + +msgid "Enter a valid date/time." +msgstr "దయచేసి సరైన తెది/సమయం ఇవ్వండి." + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "" + +msgid "No file was submitted." +msgstr "ఫైలు సమర్పించబడలేదు." + +msgid "The submitted file is empty." +msgstr "మీరు సమర్పించిన ఫైల్ కాళీగా ఉంది " + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" + +msgid "Enter a list of values." +msgstr "సరైన విలువల జాబితాను ఇవ్వండి." + +msgid "Enter a complete value." +msgstr "" + +msgid "Enter a valid UUID." +msgstr "" + +msgid "Enter a valid JSON." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr "" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "అంతరము" + +msgid "Delete" +msgstr "తొలగించు" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "దయచేసి %(field)s యొక్క నకలు విలువను సరిదిద్దుకోండి." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "దయచేసి %(field)s యొక్క నకలు విలువను సరిదిద్దుకోండి. దీని విలువ అద్వితీయమయినది " + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" + +msgid "Please correct the duplicate values below." +msgstr "దయచేసి క్రింద ఉన్న నకలు విలువను సరిదిద్దుకోండి." + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "" + +msgid "Currently" +msgstr "ప్రస్తుతము " + +msgid "Change" +msgstr "మార్చు" + +msgid "Unknown" +msgstr "తెలియనది" + +msgid "Yes" +msgstr "అవును" + +msgid "No" +msgstr "కాదు" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "అవును,కాదు,ఏమొ" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d బైటు" +msgstr[1] "%(size)d బైట్లు" + +#, python-format +msgid "%s KB" +msgstr "%s కిబై" + +#, python-format +msgid "%s MB" +msgstr "%s మెబై" + +#, python-format +msgid "%s GB" +msgstr "%s గిబై" + +#, python-format +msgid "%s TB" +msgstr "" + +#, python-format +msgid "%s PB" +msgstr "" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "అర్ధరాత్రి" + +msgid "noon" +msgstr "మధ్యాహ్నం" + +msgid "Monday" +msgstr "సోమవారం" + +msgid "Tuesday" +msgstr "మంగళవారం" + +msgid "Wednesday" +msgstr "బుధవారం" + +msgid "Thursday" +msgstr "గురువారం" + +msgid "Friday" +msgstr "శుక్రవారం" + +msgid "Saturday" +msgstr "శనివారం" + +msgid "Sunday" +msgstr "ఆదివారం" + +msgid "Mon" +msgstr "సోమ" + +msgid "Tue" +msgstr "మంగళ" + +msgid "Wed" +msgstr "బుధ" + +msgid "Thu" +msgstr "గురు" + +msgid "Fri" +msgstr "శుక్ర" + +msgid "Sat" +msgstr "శని" + +msgid "Sun" +msgstr "ఆది" + +msgid "January" +msgstr "జనవరి" + +msgid "February" +msgstr "ఫిబ్రవరి" + +msgid "March" +msgstr "మార్చి" + +msgid "April" +msgstr "ఎప్రిల్" + +msgid "May" +msgstr "మే" + +msgid "June" +msgstr "జూన్" + +msgid "July" +msgstr "జులై" + +msgid "August" +msgstr "ఆగష్టు" + +msgid "September" +msgstr "సెప్టెంబర్" + +msgid "October" +msgstr "అక్టోబర్" + +msgid "November" +msgstr "నవంబర్" + +msgid "December" +msgstr "డిసెంబర్" + +msgid "jan" +msgstr "జన" + +msgid "feb" +msgstr "ఫిబ్ర" + +msgid "mar" +msgstr "మార్చి" + +msgid "apr" +msgstr "ఎప్రి" + +msgid "may" +msgstr "మే" + +msgid "jun" +msgstr "జూన్" + +msgid "jul" +msgstr "జూలై" + +msgid "aug" +msgstr "ఆగ" + +msgid "sep" +msgstr "సెప్టెం" + +msgid "oct" +msgstr "అక్టో" + +msgid "nov" +msgstr "నవం" + +msgid "dec" +msgstr "డిసెం" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "జన." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "ఫిబ్ర." + +msgctxt "abbrev. month" +msgid "March" +msgstr "మార్చి" + +msgctxt "abbrev. month" +msgid "April" +msgstr "ఏప్రి." + +msgctxt "abbrev. month" +msgid "May" +msgstr "మే" + +msgctxt "abbrev. month" +msgid "June" +msgstr "జూన్" + +msgctxt "abbrev. month" +msgid "July" +msgstr "జూలై" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "ఆగ." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "సెప్టెం." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "అక్టో." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "నవం." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "డిసెం." + +msgctxt "alt. month" +msgid "January" +msgstr "జనవరి" + +msgctxt "alt. month" +msgid "February" +msgstr "ఫిబ్రవరి" + +msgctxt "alt. month" +msgid "March" +msgstr "మార్చి" + +msgctxt "alt. month" +msgid "April" +msgstr "ఏప్రిల్" + +msgctxt "alt. month" +msgid "May" +msgstr "మే" + +msgctxt "alt. month" +msgid "June" +msgstr "జూన్" + +msgctxt "alt. month" +msgid "July" +msgstr "జూలై" + +msgctxt "alt. month" +msgid "August" +msgstr "ఆగస్ట్" + +msgctxt "alt. month" +msgid "September" +msgstr "సెప్టెంబర్" + +msgctxt "alt. month" +msgid "October" +msgstr "అక్టోబర్" + +msgctxt "alt. month" +msgid "November" +msgstr "నవంబర్" + +msgctxt "alt. month" +msgid "December" +msgstr "డిసెంబర్" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "లేదా" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" + +msgid "Forbidden" +msgstr "" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "" + +msgid "No day specified" +msgstr "" + +msgid "No week specified" +msgstr "" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "" + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/te/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/te/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/te/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/te/formats.py new file mode 100644 index 0000000..bb7f2d1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/te/formats.py @@ -0,0 +1,21 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j F Y" +TIME_FORMAT = "g:i A" +# DATETIME_FORMAT = +# YEAR_MONTH_FORMAT = +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "j M Y" +# SHORT_DATETIME_FORMAT = +# FIRST_DAY_OF_WEEK = + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +# DECIMAL_SEPARATOR = +# THOUSAND_SEPARATOR = +# NUMBER_GROUPING = diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tg/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tg/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e93dc87 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tg/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tg/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tg/LC_MESSAGES/django.po new file mode 100644 index 0000000..05a4ca9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tg/LC_MESSAGES/django.po @@ -0,0 +1,1299 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Mariusz Felisiak , 2020 +# Surush Sufiew , 2020 +# Siroj Sufiew , 2020 +# Surush Sufiew , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-19 20:23+0200\n" +"PO-Revision-Date: 2020-07-30 18:50+0000\n" +"Last-Translator: Mariusz Felisiak \n" +"Language-Team: Tajik (http://www.transifex.com/django/django/language/tg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Ҳолландӣ" + +msgid "Arabic" +msgstr "Арабӣ" + +msgid "Algerian Arabic" +msgstr "Арабӣ" + +msgid "Asturian" +msgstr "Астурӣ" + +msgid "Azerbaijani" +msgstr "Озарбойҷонӣ" + +msgid "Bulgarian" +msgstr "Булғорӣ" + +msgid "Belarusian" +msgstr "Белорусӣ" + +msgid "Bengali" +msgstr "Бенгалӣ" + +msgid "Breton" +msgstr "Бретонӣ" + +msgid "Bosnian" +msgstr "Боснӣ" + +msgid "Catalan" +msgstr "Каталанӣ" + +msgid "Czech" +msgstr "Чехӣ" + +msgid "Welsh" +msgstr "Уэлсӣ" + +msgid "Danish" +msgstr "Даниягӣ" + +msgid "German" +msgstr "Олмонӣ" + +msgid "Lower Sorbian" +msgstr "Сербиягӣ" + +msgid "Greek" +msgstr "Юнонӣ" + +msgid "English" +msgstr "Англисӣ" + +msgid "Australian English" +msgstr "Англисии австралиёӣ" + +msgid "British English" +msgstr "Ангилисии бритониёӣ" + +msgid "Esperanto" +msgstr "Эсперантоӣ" + +msgid "Spanish" +msgstr "Испанӣ" + +msgid "Argentinian Spanish" +msgstr "Испании аргентиноӣ" + +msgid "Colombian Spanish" +msgstr "Испании колумбигӣ" + +msgid "Mexican Spanish" +msgstr "Испании мексикоӣ" + +msgid "Nicaraguan Spanish" +msgstr "Никарагуанский испанский" + +msgid "Venezuelan Spanish" +msgstr "Испании венесуэлӣ" + +msgid "Estonian" +msgstr "Эстонӣ" + +msgid "Basque" +msgstr "Баскувӣ" + +msgid "Persian" +msgstr "Форсӣ" + +msgid "Finnish" +msgstr "Финикӣ" + +msgid "French" +msgstr "Фаронсавӣ" + +msgid "Frisian" +msgstr "Фризӣ" + +msgid "Irish" +msgstr "Ирландӣ" + +msgid "Scottish Gaelic" +msgstr "Шотландӣ" + +msgid "Galician" +msgstr "" + +msgid "Hebrew" +msgstr "Ивритӣ" + +msgid "Hindi" +msgstr "Ҳиндӣ" + +msgid "Croatian" +msgstr "Хорватӣ" + +msgid "Upper Sorbian" +msgstr "Себриягӣ" + +msgid "Hungarian" +msgstr "" + +msgid "Armenian" +msgstr "Арманӣ" + +msgid "Interlingua" +msgstr "" + +msgid "Indonesian" +msgstr "Индонезӣ" + +msgid "Igbo" +msgstr "" + +msgid "Ido" +msgstr "" + +msgid "Icelandic" +msgstr "Исландӣ" + +msgid "Italian" +msgstr "Итолиёвӣ" + +msgid "Japanese" +msgstr "Японӣ" + +msgid "Georgian" +msgstr "Грузӣ" + +msgid "Kabyle" +msgstr "Кабилӣ" + +msgid "Kazakh" +msgstr "Қазоқӣ" + +msgid "Khmer" +msgstr "" + +msgid "Kannada" +msgstr "" + +msgid "Korean" +msgstr "Кореӣ" + +msgid "Kyrgyz" +msgstr "" + +msgid "Luxembourgish" +msgstr "Люксембургӣ" + +msgid "Lithuanian" +msgstr "Литвигӣ" + +msgid "Latvian" +msgstr "Латвигӣ" + +msgid "Macedonian" +msgstr "Македонӣ" + +msgid "Malayalam" +msgstr "" + +msgid "Mongolian" +msgstr "Монголӣ" + +msgid "Marathi" +msgstr "" + +msgid "Burmese" +msgstr "" + +msgid "Norwegian Bokmål" +msgstr "Норвежский (Букмол)" + +msgid "Nepali" +msgstr "Непалӣ" + +msgid "Dutch" +msgstr "Голландӣ" + +msgid "Norwegian Nynorsk" +msgstr "Норвегӣ" + +msgid "Ossetic" +msgstr "Осетинӣ" + +msgid "Punjabi" +msgstr "Панҷобӣ" + +msgid "Polish" +msgstr "Полякӣ" + +msgid "Portuguese" +msgstr "Португалӣ" + +msgid "Brazilian Portuguese" +msgstr "Португалии бразилиёгӣ" + +msgid "Romanian" +msgstr "Руминӣ" + +msgid "Russian" +msgstr "Руссӣ" + +msgid "Slovak" +msgstr "Словакӣ" + +msgid "Slovenian" +msgstr "Словенӣ" + +msgid "Albanian" +msgstr "Албанӣ" + +msgid "Serbian" +msgstr "Сербӣ" + +msgid "Serbian Latin" +msgstr "Сербӣ" + +msgid "Swedish" +msgstr "Шведӣ" + +msgid "Swahili" +msgstr "Суахили" + +msgid "Tamil" +msgstr "Тамилӣ" + +msgid "Telugu" +msgstr "Телугу" + +msgid "Tajik" +msgstr "" + +msgid "Thai" +msgstr "Тайский" + +msgid "Turkmen" +msgstr "" + +msgid "Turkish" +msgstr "Туркӣ" + +msgid "Tatar" +msgstr "Тоторӣ" + +msgid "Udmurt" +msgstr "Удмуртӣ" + +msgid "Ukrainian" +msgstr "Украинӣ" + +msgid "Urdu" +msgstr "Урдуӣ" + +msgid "Uzbek" +msgstr "Узбекӣ" + +msgid "Vietnamese" +msgstr "Вэтнамӣ" + +msgid "Simplified Chinese" +msgstr "Хитоӣ" + +msgid "Traditional Chinese" +msgstr "Хитоӣ" + +msgid "Messages" +msgstr "Маълумот" + +msgid "Site Maps" +msgstr "Харитаи сайт" + +msgid "Static Files" +msgstr "Файлҳои статикӣ" + +msgid "Syndication" +msgstr "Тасмаи хабарҳо" + +msgid "That page number is not an integer" +msgstr "Рақами саҳифа бояд адади натуралӣ бошад" + +msgid "That page number is less than 1" +msgstr "Рақами саҳифа камтар аз 1" + +msgid "That page contains no results" +msgstr "Саҳифа холӣ аст" + +msgid "Enter a valid value." +msgstr "Қимматро дуруст ворид созед." + +msgid "Enter a valid URL." +msgstr "Суроға(URL)-ро дуруст ворид созед." + +msgid "Enter a valid integer." +msgstr "Ададро дуруст ворид созед." + +msgid "Enter a valid email address." +msgstr "Суроғаи почтаи электрониро дуруст ворид созед." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Қимати “slug”-ро дуруст ворид созед, бояд аз ҳарфҳо (“a-z ва A-Z”), рақамҳо, " +"зердефисҳо(_) ва дефисҳо иборат бошад." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Қимати “slug”-ро дуруст ворид созед, бояд аз Unicode-ҳарфҳо (“a-z ва A-Z”), " +"рақамҳо, зердефисҳо(_) ва дефисҳо иборат бошад." + +msgid "Enter a valid IPv4 address." +msgstr "Шакли дурусти IPv4-суроғаро ворид созед." + +msgid "Enter a valid IPv6 address." +msgstr "Шакли ҳақиқии IPv4-суроғаро ворид кунед." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Шакли ҳақиқии IPv4 ё IPv6 -суроғаро ворид кунед." + +msgid "Enter only digits separated by commas." +msgstr "Рақамҳои бо вергул шудокардашударо ворид созед." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Боварӣ ҳосил кунед, ки қиммати — %(limit_value)s (ҳоло шакли — " +"%(show_value)s -ро дорад)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" +"Боварӣ ҳосил кунед, ки ин қиммат хурд ё баробар аст ба %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" +"Боварӣ ҳосил кунед, ки ин қиммат калон ё баробар аст ба %(limit_value)s." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Enter a number." +msgstr "Ададро ворид созед." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "Маълумот символӣ мамнӯъро дар бар мегирад: 0-байт" + +msgid "and" +msgstr "ва" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" +"%(model_name)s бо ин гуна майдонӣ қиматдор %(field_labels)s алакай вуҷуд " +"дорад." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Қимати %(value)r дар байни вариантҳои омадашуда вуҷуд надорад." + +msgid "This field cannot be null." +msgstr "Ин майдон наметавонад қимати NULL дошта бошад." + +msgid "This field cannot be blank." +msgstr "Ин майдон наметавонад холӣ бошад." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s бо ин гуна %(field_label)s алакай вуҷуд дорад." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"Қимат дар майдони «%(field_label)s» бояд барои фрагменти«%(lookup_type)s» " +"ягона бошад, санаҳо барои майдон %(date_field_label)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Майдони намуди %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "Қимати “%(value)s” бояд True ё False бошад." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "Қимати “%(value)s” бояд True, False ё None бошад." + +msgid "Boolean (Either True or False)" +msgstr "Мантиқан (True ё False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Сатр (то %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "Яклухт, бо вергул ҷудокардашуда" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "“%(value)s” шакли нодуруст дорад. Шакли дуруст: сол.моҳ.рӯз, аст" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "“%(value)s” шакли дуруст (сол.моҳ.рӯз) дорад, аммо сана нодуруст аст" + +msgid "Date (without time)" +msgstr "Сана (бе ишораи вақт)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"“%(value)s” шакли нодуруст дорад. Шакли дуруст: сол.моҳ.рӯз соат.дақ[:сония[." +"uuuuuu]][TZ] аст" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"“%(value)s” шакли дуруст дорад (сол.моҳ.рӯз соат.дақ[:сония[.uuuuuu]][TZ]), " +"аммо 'сана/вақт'' нодуруст аст" + +msgid "Date (with time)" +msgstr "Сана (бо ишораи вақт)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "“%(value)s” бояд адади даҳӣ бошад" + +msgid "Decimal number" +msgstr "Адади 'даҳӣ' ." + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"“%(value)s” шакли нодуруст дорад. Шакли дуруст [рӯз] [[соат:]дақ:]сония[." +"uuuuuu]" + +msgid "Duration" +msgstr "Давомнокӣ" + +msgid "Email address" +msgstr "Суроғаи почтаи электронӣ" + +msgid "File path" +msgstr "Суроғаи файл" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "Қимати “%(value)s” бояд бутун бошад" + +msgid "Floating point number" +msgstr "Адади бутун." + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "Қимати “%(value)s” бояд яклухт бошад" + +msgid "Integer" +msgstr "Яклухт" + +msgid "Big (8 byte) integer" +msgstr "Адади калони яклухт (8 байт)" + +msgid "IPv4 address" +msgstr "IPv4 - суроға" + +msgid "IP address" +msgstr "IP-суроға" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "Қимати “%(value)s” бояд 'None', 'True' ё 'False' бошад" + +msgid "Boolean (Either True, False or None)" +msgstr "Мантиқӣ (True, False ё None)" + +msgid "Positive big integer" +msgstr "" + +msgid "Positive integer" +msgstr "Адади яклухти мусбат" + +msgid "Positive small integer" +msgstr "дади яклухти мусбати хурд" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Слаг (то %(max_length)s)" + +msgid "Small integer" +msgstr "Адади яклухти хурд" + +msgid "Text" +msgstr "Матн" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"“%(value)s” шакли нодуруст дорад. Шакли дуруст соат:дақ[:сония[.uuuuuu]" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"“%(value)s” шакли дуруст дорад (соат:моҳ[:сония[.uuuuuu, аммо 'вақт' " +"нодуруст қайд шудааст " + +msgid "Time" +msgstr "Вақт" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Маълумоти бинари(дуи)-и коркарднашуда" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "Қимати “%(value)s” барои UUID номувофиқ аст." + +msgid "Universally unique identifier" +msgstr "Майдони UUID, идентификатори универсалии ягона" + +msgid "File" +msgstr "Файл" + +msgid "Image" +msgstr "Тасвир" + +msgid "A JSON object" +msgstr "" + +msgid "Value must be valid JSON." +msgstr "" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" +"Объекти модели %(model)s бо майдони %(field)s, -и дорои қимати %(value)r, " +"вуҷқд надорад." + +msgid "Foreign Key (type determined by related field)" +msgstr "" +"Калиди беруна(Foreign Key) (Шакл муайян шудаст аз рӯи майдони алоқамандшуда.)" + +msgid "One-to-one relationship" +msgstr "Алоқаи \"як ба як\"" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "Алоқаи %(from)s-%(to)s" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "Алоқаи %(from)s-%(to)s" + +msgid "Many-to-many relationship" +msgstr "Алоқаи \\'бисёр ба бисёр\\'" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Майдони ҳатмӣ." + +msgid "Enter a whole number." +msgstr "Адади яклухтро ворид кунед." + +msgid "Enter a valid date." +msgstr "Санаи дурстро ворид кунед." + +msgid "Enter a valid time." +msgstr "Вақтро дуруст ворид кунед.." + +msgid "Enter a valid date/time." +msgstr "Сана ва вақтро дуруст ворид кунед." + +msgid "Enter a valid duration." +msgstr "авомнокии дурустро ворид кунед." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" +"Миқдори рӯзҳо бояд доираи аз {min_days} то {max_days} -ро дарбар гирад." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Файл равон карда нашуд. Шакли кодировкаи формаро тафтиш кунед." + +msgid "No file was submitted." +msgstr "Ягон файл равон карда нашуд" + +msgid "The submitted file is empty." +msgstr "Файли равонкардашуда холӣ аст." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Хоҳиш мекунем файлро бор кунед ё байрақчаи ишоратӣ гузоред \"Тоза кардан\", " +"вале ҳарду амалро дар якҷоягӣ иҷро накунед." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Тасвири дурустро бор кунед. Файли боркардаи шумо нуқсон дорад ва ё 'тасвира' " +"нест" + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Варианти дурустро интихоб кунед. %(value)s дар байни варианҳои дастрас вуҷуд " +"надорад." + +msgid "Enter a list of values." +msgstr "Рӯйхати қиматҳоро ворид кунед." + +msgid "Enter a complete value." +msgstr "Рӯйхати ҳамаи қиматҳоро ворид кунед." + +msgid "Enter a valid UUID." +msgstr "Шакли дурусти UUID -ро ворид кунед." + +msgid "Enter a valid JSON." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Майдони махфии %(name)s) %(error)s" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "Маълумоти идоракунандаи форма вуҷуд надорад ё ин ки осеб дидааст." + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "Тартиб" + +msgid "Delete" +msgstr "Нест кардан" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "" +"Илтимос қимати такроршудаистодаи майдони \"%(field)s\" ро тағйир диҳед." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Илтимос, қимати майдони %(field)s ро тағйир диҳед, вай бояд 'ягона' бошад." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Илтимос, қимати майдони %(field_name)s ро тағйир диҳед, вай бояд барои " +"%(lookup)s дар майдони %(date_field)s ягона бошад (Ягона будан маънои " +"такрорнашавандагиро дорад)." + +msgid "Please correct the duplicate values below." +msgstr "Хоҳиш мекунам, қимати такроршудаистодаи зеринро иваз кунед." + +msgid "The inline value did not match the parent instance." +msgstr "" +"Қимати дар форма воридкардашуда бо қимати формаи база мутобиқат намекунад." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Варианти дурустро интихоб кунед. Варианти шумо дар қатори қиматҳои " +"овардашуда вуҷуд надорад." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Тоза кардан" + +msgid "Currently" +msgstr "Дар айни замон" + +msgid "Change" +msgstr "Тағйир додан" + +msgid "Unknown" +msgstr "Номаълум" + +msgid "Yes" +msgstr "Ҳа" + +msgid "No" +msgstr "Не" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "ҳа,не,шояд" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%s KB" +msgstr "%s КБ" + +#, python-format +msgid "%s MB" +msgstr "%s МБ" + +#, python-format +msgid "%s GB" +msgstr "%s ГБ" + +#, python-format +msgid "%s TB" +msgstr "%s ТБ" + +#, python-format +msgid "%s PB" +msgstr "%s ПБ" + +msgid "p.m." +msgstr "н.ш." + +msgid "a.m." +msgstr "н.р." + +msgid "PM" +msgstr "НШ" + +msgid "AM" +msgstr "НР" + +msgid "midnight" +msgstr "нимашабӣ" + +msgid "noon" +msgstr "нисфирузӣ" + +msgid "Monday" +msgstr "Душанбе" + +msgid "Tuesday" +msgstr "Сешанбе" + +msgid "Wednesday" +msgstr "Чоршанбе" + +msgid "Thursday" +msgstr "Панҷшанбе" + +msgid "Friday" +msgstr "Ҷумъа" + +msgid "Saturday" +msgstr "Шанбе" + +msgid "Sunday" +msgstr "Якшанбе" + +msgid "Mon" +msgstr "Дш" + +msgid "Tue" +msgstr "Яш" + +msgid "Wed" +msgstr "Чш" + +msgid "Thu" +msgstr "Пш" + +msgid "Fri" +msgstr "Ҷ" + +msgid "Sat" +msgstr "Ш" + +msgid "Sun" +msgstr "Яш" + +msgid "January" +msgstr "Январ" + +msgid "February" +msgstr "Феврал" + +msgid "March" +msgstr "Март" + +msgid "April" +msgstr "Апрел" + +msgid "May" +msgstr "Май" + +msgid "June" +msgstr "Июн" + +msgid "July" +msgstr "Июл" + +msgid "August" +msgstr "Август" + +msgid "September" +msgstr "Сентябр" + +msgid "October" +msgstr "Октябр" + +msgid "November" +msgstr "Ноябр" + +msgid "December" +msgstr "Декабр" + +msgid "jan" +msgstr "янв" + +msgid "feb" +msgstr "фев" + +msgid "mar" +msgstr "мар" + +msgid "apr" +msgstr "апр" + +msgid "may" +msgstr "май" + +msgid "jun" +msgstr "июн" + +msgid "jul" +msgstr "июл" + +msgid "aug" +msgstr "авг" + +msgid "sep" +msgstr "сен" + +msgid "oct" +msgstr "окт" + +msgid "nov" +msgstr "ноя" + +msgid "dec" +msgstr "дек" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Янв." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Фев." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Март" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Апрел" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Май" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Июн" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Июл" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Авг." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Сен." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Окт." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Ноя." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Дек." + +msgctxt "alt. month" +msgid "January" +msgstr "январ" + +msgctxt "alt. month" +msgid "February" +msgstr "феврал" + +msgctxt "alt. month" +msgid "March" +msgstr "март" + +msgctxt "alt. month" +msgid "April" +msgstr "апрел" + +msgctxt "alt. month" +msgid "May" +msgstr "май" + +msgctxt "alt. month" +msgid "June" +msgstr "июн" + +msgctxt "alt. month" +msgid "July" +msgstr "июл" + +msgctxt "alt. month" +msgid "August" +msgstr "август" + +msgctxt "alt. month" +msgid "September" +msgstr "сентябр" + +msgctxt "alt. month" +msgid "October" +msgstr "октябр" + +msgctxt "alt. month" +msgid "November" +msgstr "ноябр" + +msgctxt "alt. month" +msgid "December" +msgstr "декабр" + +msgid "This is not a valid IPv6 address." +msgstr "Қиммат суроғаи дурусти IPv6 нест." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "ё" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" + +msgid "Forbidden" +msgstr "Мушкилӣ дар воридшавӣ" + +msgid "CSRF verification failed. Request aborted." +msgstr "Мушкили дар тафтиши CSRF. Дархост рад шуд." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Шумо ин хабарро барои он мебинед, ки ин HTTPS -сомона, тавассути браузери " +"шумо дархости равон кардани 'Referer' 'header' -ро дорад. Вале ягон дархост " +"равон нашудааст.Иҷрои ин амал аз ҷиҳати бехатарӣ барои мутмаин шудани он, ки " +"браузери шумо аз тарафи шахси сеюм 'шикаста'' (взлом)нашудааст, ҳатмӣ " +"мебошад." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Агар шумо браузери худро ба таври 'Referer'-сархатҳояшон дастнорас ба танзим " +"даровада бошед,хоҳиш мекунем, ки ҳадди ақал барои сомонаи мазкур ё барои " +"пайсшавии таввассути HTTPS ё ин ки бароидархостҳои манбаашон якхела, амали " +"азнавбатанзимдарориро иҷро намоед." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Шумо ин хабарро барои он мебинед, ки сомонаи мазкур талаб менамояд, то амали " +"равонкунииформа ва CSRF cookie дар якҷоягӣ сурат гирад. Ин намуди 'cookie' " +"аз ҷиҳати бехатарӣбарои мутмаин шудани он, ки браузери шумо аз тарафи шахси " +"сеюм 'шикаста'' (взлом)нашудааст, ҳатмӣ мебошад." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Агар шумо браузери худро ба таври дастнораси ба cookies' ба танзим даровада " +"бошед,хоҳиш мекунем, ки ҳадди ақал барои сомонаи мазкур ё барои пайсшавии " +"таввассути HTTPS ё ин ки бароидархостҳои манбаашон якхела, амали " +"азнавбатанзимдарориро иҷро намоед." + +msgid "More information is available with DEBUG=True." +msgstr "" +"Маълумоти бештар дар режими 'танзимдарорӣ'(отладчика), бо фаъолсозии " +"DEBUG=True." + +msgid "No year specified" +msgstr "Сол ишора нашудааст" + +msgid "Date out of range" +msgstr "сана аз доираи муайян берун аст" + +msgid "No month specified" +msgstr "Моҳ ишора нашудааст" + +msgid "No day specified" +msgstr "Рӯз ишора нашудааст" + +msgid "No week specified" +msgstr "Ҳафта ишора нашудааст" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "%(verbose_name_plural)s дастнорас аст" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"%(verbose_name_plural)s навбатӣ дастнорасанд барои он ки %(class_name)s." +"allow_future бо қимати \" False\" гузошта шудааст." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Санаи нодурусти “%(datestr)s” шакли “%(format)s” гирифтааст" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Ягон %(verbose_name)s, мувофиқ бо дархости шумо ёфт нашуд" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Саҳифа 'охирин' нест ва ё ки бо адади яклухт(int) ишора нашудааст" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Саҳифаи нодуруст (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Азназаргузаронии рӯёхати файлҳо дар директорияи зерин номумкин аст." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "“%(path)s” вуҷуд надорад" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Рӯёхати файлҳои директорияи %(directory)s" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" +"Django: веб-фреймворк барои перфектсионистҳо бо дедлайнҳо. Бисёр фреймворки " +"табъи дилва хастанакунанда ҳангоми кор." + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Инҷо андешаҳо оиди баромади Django " +"%(version)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Ҷобаҷогузорӣ муваффақона анҷом ёфт! Табрик!" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" +"Шумо ин хабарро барои он мебинед, ки дар ишора намудед: DEBUG=True ва дар файли " +"ҷобаҷогузорӣ(settings)ягонто танзимгари URL-суроғаҳоро ишора нанамудед." + +msgid "Django Documentation" +msgstr "Ҳуҷҷатгузории Django" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "Роҳбарият: Барнома барои овоздиҳӣ" + +msgid "Get started with Django" +msgstr "оғози кор бо Django" + +msgid "Django Community" +msgstr "Иттиҳоди Django" + +msgid "Connect, get help, or contribute" +msgstr "Бо мо ҳамкорӣ намуда имкониятҳои навро пайдо намоед." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tg/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tg/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tg/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tg/formats.py new file mode 100644 index 0000000..0ab7d49 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tg/formats.py @@ -0,0 +1,32 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j E Y г." +TIME_FORMAT = "G:i" +DATETIME_FORMAT = "j E Y г. G:i" +YEAR_MONTH_FORMAT = "F Y г." +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "d.m.Y" +SHORT_DATETIME_FORMAT = "d.m.Y H:i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d.%m.%Y", # '25.10.2006' + "%d.%m.%y", # '25.10.06' +] +DATETIME_INPUT_FORMATS = [ + "%d.%m.%Y %H:%M:%S", # '25.10.2006 14:30:59' + "%d.%m.%Y %H:%M:%S.%f", # '25.10.2006 14:30:59.000200' + "%d.%m.%Y %H:%M", # '25.10.2006 14:30' + "%d.%m.%Y", # '25.10.2006' + "%d.%m.%y %H:%M:%S", # '25.10.06 14:30:59' + "%d.%m.%y %H:%M:%S.%f", # '25.10.06 14:30:59.000200' + "%d.%m.%y %H:%M", # '25.10.06 14:30' + "%d.%m.%y", # '25.10.06' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "\xa0" # non-breaking space +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/th/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/th/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3969ebd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/th/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/th/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/th/LC_MESSAGES/django.po new file mode 100644 index 0000000..8ab31f2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/th/LC_MESSAGES/django.po @@ -0,0 +1,1208 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Abhabongse Janthong, 2015 +# Jannis Leidel , 2011 +# Kowit Charoenratchatabhan , 2014,2018-2019 +# Naowal Siripatana , 2017 +# sipp11 , 2014 +# Suteepat Damrongyingsupab , 2011-2012 +# Suteepat Damrongyingsupab , 2013 +# Vichai Vongvorakul , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Thai (http://www.transifex.com/django/django/language/th/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: th\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Afrikaans" +msgstr "อาฟฟริกัน" + +msgid "Arabic" +msgstr "อารบิก" + +msgid "Asturian" +msgstr "อัสตูเรียน" + +msgid "Azerbaijani" +msgstr "อาเซอร์ไบจาน" + +msgid "Bulgarian" +msgstr "บัลแกเรีย" + +msgid "Belarusian" +msgstr "เบลารุส" + +msgid "Bengali" +msgstr "เบ็งกาลี" + +msgid "Breton" +msgstr "เบรตัน" + +msgid "Bosnian" +msgstr "บอสเนีย" + +msgid "Catalan" +msgstr "คาตะลาน" + +msgid "Czech" +msgstr "เช็ก" + +msgid "Welsh" +msgstr "เวลส์" + +msgid "Danish" +msgstr "เดนมาร์ก" + +msgid "German" +msgstr "เยอรมัน" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "กรีก" + +msgid "English" +msgstr "อังกฤษ" + +msgid "Australian English" +msgstr "อังกฤษ - ออสเตรเลีย" + +msgid "British English" +msgstr "อังกฤษ - สหราชอาณาจักร" + +msgid "Esperanto" +msgstr "เอสเปรันโต" + +msgid "Spanish" +msgstr "สเปน" + +msgid "Argentinian Spanish" +msgstr "สเปน - อาร์เจนติน่า" + +msgid "Colombian Spanish" +msgstr "สเปน - โคลัมเบีย" + +msgid "Mexican Spanish" +msgstr "สเปน - เม็กซิกัน" + +msgid "Nicaraguan Spanish" +msgstr "นิการากัวสเปน" + +msgid "Venezuelan Spanish" +msgstr "เวเนซุเอลาสเปน" + +msgid "Estonian" +msgstr "เอสโตเนีย" + +msgid "Basque" +msgstr "แบ็ซค์" + +msgid "Persian" +msgstr "เปอร์เชีย" + +msgid "Finnish" +msgstr "ฟินแลนด์" + +msgid "French" +msgstr "ฝรั่งเศส" + +msgid "Frisian" +msgstr "ฟริเซียน" + +msgid "Irish" +msgstr "ไอริช" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "กาลิเซีย" + +msgid "Hebrew" +msgstr "ฮีบรู" + +msgid "Hindi" +msgstr "ฮินดี" + +msgid "Croatian" +msgstr "โครเอเชีย" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "ฮังการี" + +msgid "Armenian" +msgstr "อาร์เมเนียน" + +msgid "Interlingua" +msgstr "ภาษากลาง" + +msgid "Indonesian" +msgstr "อินโดนิเซีย" + +msgid "Ido" +msgstr "" + +msgid "Icelandic" +msgstr "ไอซ์แลนด์" + +msgid "Italian" +msgstr "อิตาลี" + +msgid "Japanese" +msgstr "ญี่ปุ่น" + +msgid "Georgian" +msgstr "จอร์เจีย" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "คาซัค" + +msgid "Khmer" +msgstr "เขมร" + +msgid "Kannada" +msgstr "กัณณาท" + +msgid "Korean" +msgstr "เกาหลี" + +msgid "Luxembourgish" +msgstr "ลักแซมเบิร์ก" + +msgid "Lithuanian" +msgstr "ลิทัวเนีย" + +msgid "Latvian" +msgstr "ลัตเวีย" + +msgid "Macedonian" +msgstr "มาซิโดเนีย" + +msgid "Malayalam" +msgstr "มลายู" + +msgid "Mongolian" +msgstr "มองโกเลีย" + +msgid "Marathi" +msgstr "" + +msgid "Burmese" +msgstr "พม่า" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "เนปาล" + +msgid "Dutch" +msgstr "ดัตช์" + +msgid "Norwegian Nynorsk" +msgstr "นอร์เวย์ - Nynorsk" + +msgid "Ossetic" +msgstr "" + +msgid "Punjabi" +msgstr "ปัญจาบี" + +msgid "Polish" +msgstr "โปแลนด์" + +msgid "Portuguese" +msgstr "โปรตุเกส" + +msgid "Brazilian Portuguese" +msgstr "โปรตุเกส (บราซิล)" + +msgid "Romanian" +msgstr "โรมาเนีย" + +msgid "Russian" +msgstr "รัสเซีย" + +msgid "Slovak" +msgstr "สโลวัก" + +msgid "Slovenian" +msgstr "สโลวีเนีย" + +msgid "Albanian" +msgstr "อัลแบเนีย" + +msgid "Serbian" +msgstr "เซอร์เบีย" + +msgid "Serbian Latin" +msgstr "เซอร์เบียละติน" + +msgid "Swedish" +msgstr "สวีเดน" + +msgid "Swahili" +msgstr "สวาฮีลี" + +msgid "Tamil" +msgstr "ทมิฬ" + +msgid "Telugu" +msgstr "เตลุคู" + +msgid "Thai" +msgstr "ไทย" + +msgid "Turkish" +msgstr "ตุรกี" + +msgid "Tatar" +msgstr "ตาตาร์" + +msgid "Udmurt" +msgstr "อัดเมิร์ท" + +msgid "Ukrainian" +msgstr "ยูเครน" + +msgid "Urdu" +msgstr "เออร์ดู" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "เวียดนาม" + +msgid "Simplified Chinese" +msgstr "จีนตัวย่อ" + +msgid "Traditional Chinese" +msgstr "จีนตัวเต็ม" + +msgid "Messages" +msgstr "ข้อความ" + +msgid "Site Maps" +msgstr "" + +msgid "Static Files" +msgstr "" + +msgid "Syndication" +msgstr "" + +msgid "That page number is not an integer" +msgstr "หมายเลขหน้าดังกล่าวไม่ใช่จำนวนเต็ม" + +msgid "That page number is less than 1" +msgstr "หมายเลขหน้าดังกล่าวมีค่าน้อยกว่า 1" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "กรุณาใส่ค่าที่ถูกต้อง" + +msgid "Enter a valid URL." +msgstr "ใส่ URL ที่ถูกต้อง" + +msgid "Enter a valid integer." +msgstr "" + +msgid "Enter a valid email address." +msgstr "ป้อนที่อยู่อีเมลที่ถูกต้อง" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "กรุณาใส่หมายเลขไอพีที่ถูกต้อง" + +msgid "Enter a valid IPv6 address." +msgstr "กรอก IPv6 address ให้ถูกต้อง" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "กรอก IPv4 หรือ IPv6 address ให้ถูกต้อง" + +msgid "Enter only digits separated by commas." +msgstr "ใส่ตัวเลขที่คั่นด้วยจุลภาคเท่านั้น" + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "ค่านี้ต้องเป็น %(limit_value)s (ปัจจุบันคือ %(show_value)s)" + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "ค่านี้ต้องน้อยกว่าหรือเท่ากับ %(limit_value)s" + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "ค่านี้ต้องมากกว่าหรือเท่ากับ %(limit_value)s" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" + +msgid "Enter a number." +msgstr "กรอกหมายเลข" + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "และ" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "ฟิลด์นี้ไม่สารถปล่อยว่างได้" + +msgid "This field cannot be blank." +msgstr "ฟิลด์นี้เว้นว่างไม่ได้" + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s และ %(field_label)s มีอยู่แล้ว" + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "ฟิลด์ข้อมูล: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "ตรรกะแบบบูลหมายถึง ค่า\"จริง\" (True) หรือ \"ไม่จริง \" (False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "สตริง(ได้ถึง %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "จำนวนเต็มแบบมีจุลภาค" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "วันที่ (ไม่มีเวลา)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "วันที่ (พร้อมด้วยเวลา)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "เลขฐานสิบหรือเลขทศนิยม" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "ช่วงเวลา" + +msgid "Email address" +msgstr "อีเมล" + +msgid "File path" +msgstr "ตำแหน่งไฟล์" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "เลขทศนิยม" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "จำนวนเต็ม" + +msgid "Big (8 byte) integer" +msgstr "จำนวนเต็ม (8 byte)" + +msgid "IPv4 address" +msgstr "IPv4 address" + +msgid "IP address" +msgstr "หมายเลขไอพี" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "" +"ตรรกะแบบบูลหมายถึง ค่า\"จริง\" (True) หรือ \"ไม่จริง \" (False) หรือ \"ไม่มี\" (None)" + +msgid "Positive integer" +msgstr "จํานวนเต็มบวก" + +msgid "Positive small integer" +msgstr "จํานวนเต็มบวกขนาดเล็ก" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (ถึง %(max_length)s )" + +msgid "Small integer" +msgstr "จำนวนเต็มขนาดเล็ก" + +msgid "Text" +msgstr "ข้อความ" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "เวลา" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "ไฟล์" + +msgid "Image" +msgstr "รูปภาพ" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "Foreign Key (ชนิดของข้อมูลจะถูกกำหนดจากฟิลด์ที่เกี่ยวข้อง)" + +msgid "One-to-one relationship" +msgstr "ความสัมพันธ์แบบหนึ่งต่อหนึ่ง" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "ความสัมพันธ์แบบ many-to-many" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "ฟิลด์นี้จำเป็น" + +msgid "Enter a whole number." +msgstr "กรอกหมายเลข" + +msgid "Enter a valid date." +msgstr "กรุณาใส่วัน" + +msgid "Enter a valid time." +msgstr "กรุณาใส่เวลา" + +msgid "Enter a valid date/time." +msgstr "กรุณาใส่วันเวลา" + +msgid "Enter a valid duration." +msgstr "ใส่ระยะเวลาที่ถูกต้อง" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "ไม่มีไฟล์ใดถูกส่ง. ตรวจสอบ encoding type ในฟอร์ม." + +msgid "No file was submitted." +msgstr "ไม่มีไฟล์ใดถูกส่ง" + +msgid "The submitted file is empty." +msgstr "ไฟล์ที่ส่งว่างเปล่า" + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "โปรดเลือกไฟล์หรือติ๊ก clear checkbox อย่างใดอย่างหนึ่ง" + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "อัพโหลดรูปที่ถูกต้อง. ไฟล์ที่อัพโหลดไปไม่ใช่รูป หรือรูปเสียหาย." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "เลือกตัวเลือกที่ถูกต้อง. %(value)s ไม่ใช่ตัวเลือกที่ใช้ได้." + +msgid "Enter a list of values." +msgstr "ใส่รายการ" + +msgid "Enter a complete value." +msgstr "" + +msgid "Enter a valid UUID." +msgstr "ใส่ UUID ที่ถูกต้อง" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" + +msgid "Order" +msgstr "เรียงลำดับ" + +msgid "Delete" +msgstr "ลบ" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "โปรดแก้ไขข้อมูลที่ซ้ำซ้อนใน %(field)s" + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "โปรดแก้ไขข้อมูลที่ซ้ำซ้อนใน %(field)s ซึ่งจะต้องไม่ซ้ำกัน" + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"โปรดแก้ไขข้อมูลซ้ำซ้อนใน %(field_name)s ซึ่งจะต้องไม่ซ้ำกันสำหรับ %(lookup)s ใน " +"%(date_field)s" + +msgid "Please correct the duplicate values below." +msgstr "โปรดแก้ไขค่าที่ซ้ำซ้อนด้านล่าง" + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "เลือกตัวเลือกที่ถูกต้อง. ตัวเลือกนั้นไม่สามารถเลือกได้." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "ล้าง" + +msgid "Currently" +msgstr "ปัจจุบัน" + +msgid "Change" +msgstr "เปลี่ยนแปลง" + +msgid "Unknown" +msgstr "ไม่รู้" + +msgid "Yes" +msgstr "ใช่" + +msgid "No" +msgstr "ไม่ใช่" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "ใช่,ไม่ใช่,อาจจะ" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d ไบต์" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "เที่ยงคืน" + +msgid "noon" +msgstr "เที่ยงวัน" + +msgid "Monday" +msgstr "จันทร์" + +msgid "Tuesday" +msgstr "อังคาร" + +msgid "Wednesday" +msgstr "พุธ" + +msgid "Thursday" +msgstr "พฤหัสบดี" + +msgid "Friday" +msgstr "ศุกร์" + +msgid "Saturday" +msgstr "เสาร์" + +msgid "Sunday" +msgstr "อาทิตย์" + +msgid "Mon" +msgstr "จ." + +msgid "Tue" +msgstr "อ." + +msgid "Wed" +msgstr "พ." + +msgid "Thu" +msgstr "พฤ." + +msgid "Fri" +msgstr "ศ." + +msgid "Sat" +msgstr "ส." + +msgid "Sun" +msgstr "อา." + +msgid "January" +msgstr "มกราคม" + +msgid "February" +msgstr "กุมภาพันธ์" + +msgid "March" +msgstr "มีนาคม" + +msgid "April" +msgstr "เมษายน" + +msgid "May" +msgstr "พฤษภาคม" + +msgid "June" +msgstr "มิถุนายน" + +msgid "July" +msgstr "กรกฎาคม" + +msgid "August" +msgstr "สิงหาคม" + +msgid "September" +msgstr "กันยายน" + +msgid "October" +msgstr "ตุลาคม" + +msgid "November" +msgstr "พฤศจิกายน" + +msgid "December" +msgstr "ธันวาคม" + +msgid "jan" +msgstr "ม.ค." + +msgid "feb" +msgstr "ก.พ." + +msgid "mar" +msgstr "มี.ค." + +msgid "apr" +msgstr "เม.ย." + +msgid "may" +msgstr "พ.ค." + +msgid "jun" +msgstr "มิ.ย." + +msgid "jul" +msgstr "ก.ค." + +msgid "aug" +msgstr "ส.ค." + +msgid "sep" +msgstr "ก.ย." + +msgid "oct" +msgstr "ต.ค." + +msgid "nov" +msgstr "พ.ย." + +msgid "dec" +msgstr "ธ.ค." + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "ม.ค." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "ก.พ." + +msgctxt "abbrev. month" +msgid "March" +msgstr "มี.ค." + +msgctxt "abbrev. month" +msgid "April" +msgstr "เม.ย." + +msgctxt "abbrev. month" +msgid "May" +msgstr "พ.ค." + +msgctxt "abbrev. month" +msgid "June" +msgstr "มิ.ย." + +msgctxt "abbrev. month" +msgid "July" +msgstr "ก.ค." + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "ส.ค." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "ก.ย." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "ต.ค." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "พ.ย." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "ธ.ค." + +msgctxt "alt. month" +msgid "January" +msgstr "มกราคม" + +msgctxt "alt. month" +msgid "February" +msgstr "กุมภาพันธ์" + +msgctxt "alt. month" +msgid "March" +msgstr "มีนาคม" + +msgctxt "alt. month" +msgid "April" +msgstr "เมษายน" + +msgctxt "alt. month" +msgid "May" +msgstr "พฤษภาคม" + +msgctxt "alt. month" +msgid "June" +msgstr "มิถุนายน" + +msgctxt "alt. month" +msgid "July" +msgstr "กรกฎาคม" + +msgctxt "alt. month" +msgid "August" +msgstr "สิงหาคม" + +msgctxt "alt. month" +msgid "September" +msgstr "กันยายน" + +msgctxt "alt. month" +msgid "October" +msgstr "ตุลาคม" + +msgctxt "alt. month" +msgid "November" +msgstr "พฤศจิกายน" + +msgctxt "alt. month" +msgid "December" +msgstr "ธันวาคม" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "หรือ" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d ปี" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d เดือน" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d สัปดาห์" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d วัน" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d ชั่วโมง" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d นาที" + +msgid "0 minutes" +msgstr "0 นาที" + +msgid "Forbidden" +msgstr "หวงห้าม" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "ไม่ระบุปี" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "ไม่ระบุเดือน" + +msgid "No day specified" +msgstr "ไม่ระบุวัน" + +msgid "No week specified" +msgstr "ไม่ระบุสัปดาห์" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "ไม่มี %(verbose_name_plural)s ที่ใช้ได้" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"%(verbose_name_plural)s ในอนาคตไม่สามารถใช้ได้ เนื่องจาก %(class_name)s." +"allow_future มีค่าเป็น False" + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "ไม่พบ %(verbose_name)s จาก query" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "หน้าไม่ถูกต้อง (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "ไม่ได้รับอนุญาตให้ใช้ Directory indexes ที่นี่" + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "ดัชนีของ %(directory)s" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "เริ่มต้นกับ Django" + +msgid "Django Community" +msgstr "ชุมชน Django" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/th/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/th/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/th/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/th/formats.py new file mode 100644 index 0000000..190e6d1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/th/formats.py @@ -0,0 +1,33 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j F Y" +TIME_FORMAT = "G:i" +DATETIME_FORMAT = "j F Y, G:i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "j M Y" +SHORT_DATETIME_FORMAT = "j M Y, G:i" +FIRST_DAY_OF_WEEK = 0 # Sunday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d/%m/%Y", # 25/10/2006 + "%d %b %Y", # 25 ต.ค. 2006 + "%d %B %Y", # 25 ตุลาคม 2006 +] +TIME_INPUT_FORMATS = [ + "%H:%M:%S", # 14:30:59 + "%H:%M:%S.%f", # 14:30:59.000200 + "%H:%M", # 14:30 +] +DATETIME_INPUT_FORMATS = [ + "%d/%m/%Y %H:%M:%S", # 25/10/2006 14:30:59 + "%d/%m/%Y %H:%M:%S.%f", # 25/10/2006 14:30:59.000200 + "%d/%m/%Y %H:%M", # 25/10/2006 14:30 +] +DECIMAL_SEPARATOR = "." +THOUSAND_SEPARATOR = "," +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..cb4590d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tk/LC_MESSAGES/django.po new file mode 100644 index 0000000..0d0f398 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tk/LC_MESSAGES/django.po @@ -0,0 +1,1330 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Mariusz Felisiak , 2020-2021 +# Resul , 2020 +# Resul , 2022-2023 +# Welbeck Garli , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Resul , 2022-2023\n" +"Language-Team: Turkmen (http://app.transifex.com/django/django/language/" +"tk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tk\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "Afrikaans" + +msgid "Arabic" +msgstr "Arapça" + +msgid "Algerian Arabic" +msgstr "Alžir Arapçasy" + +msgid "Asturian" +msgstr "Asturian" + +msgid "Azerbaijani" +msgstr "Azeri Türkçesi" + +msgid "Bulgarian" +msgstr "Bolgar" + +msgid "Belarusian" +msgstr "Belarusça" + +msgid "Bengali" +msgstr "Bengali" + +msgid "Breton" +msgstr "Breton" + +msgid "Bosnian" +msgstr "Bosniýaça" + +msgid "Catalan" +msgstr "Katalan" + +msgid "Central Kurdish (Sorani)" +msgstr "Merkezi Kürtçe (Soraniçe)" + +msgid "Czech" +msgstr "Çehçe" + +msgid "Welsh" +msgstr "Uelsçe" + +msgid "Danish" +msgstr "Daniýaça" + +msgid "German" +msgstr "Nemesçe" + +msgid "Lower Sorbian" +msgstr "Aşaky Sorbian" + +msgid "Greek" +msgstr "Grekçe" + +msgid "English" +msgstr "Iňlisçe" + +msgid "Australian English" +msgstr "Awstraliýa Iňlisçesi" + +msgid "British English" +msgstr "Britan Iňlisçesi" + +msgid "Esperanto" +msgstr "Esperanto" + +msgid "Spanish" +msgstr "Ispança" + +msgid "Argentinian Spanish" +msgstr "Argentina Ispançasy" + +msgid "Colombian Spanish" +msgstr "Kolumbiýa Ispançasy" + +msgid "Mexican Spanish" +msgstr "Meksika Ispançasy" + +msgid "Nicaraguan Spanish" +msgstr "Nikaragua Ispançasy" + +msgid "Venezuelan Spanish" +msgstr "Wenezuela Ispançasy" + +msgid "Estonian" +msgstr "Estonça" + +msgid "Basque" +msgstr "Baskça" + +msgid "Persian" +msgstr "Parsça" + +msgid "Finnish" +msgstr "Finçe" + +msgid "French" +msgstr "Fransuzça" + +msgid "Frisian" +msgstr "Frisça" + +msgid "Irish" +msgstr "Irlandça" + +msgid "Scottish Gaelic" +msgstr "Şotlandiýa Gaelçasy" + +msgid "Galician" +msgstr "Galisiýaça" + +msgid "Hebrew" +msgstr "Ýewreýçe" + +msgid "Hindi" +msgstr "Hindi" + +msgid "Croatian" +msgstr "Horwatça" + +msgid "Upper Sorbian" +msgstr "Ýokarky Sorbian" + +msgid "Hungarian" +msgstr "Wengerçe" + +msgid "Armenian" +msgstr "Ermeniçe" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Indonezça" + +msgid "Igbo" +msgstr "Igbo" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Islandça" + +msgid "Italian" +msgstr "Italýança" + +msgid "Japanese" +msgstr "Ýaponça" + +msgid "Georgian" +msgstr "Gruzinçe" + +msgid "Kabyle" +msgstr "Kabyle" + +msgid "Kazakh" +msgstr "Gazakça" + +msgid "Khmer" +msgstr "Hmerçe" + +msgid "Kannada" +msgstr "Kannada" + +msgid "Korean" +msgstr "Koreýçe" + +msgid "Kyrgyz" +msgstr "Gyrgyzça" + +msgid "Luxembourgish" +msgstr "Lýuksemburgça" + +msgid "Lithuanian" +msgstr "Litwança" + +msgid "Latvian" +msgstr "Latwiýaça" + +msgid "Macedonian" +msgstr "Makedonça" + +msgid "Malayalam" +msgstr "Malaýalam" + +msgid "Mongolian" +msgstr "Mongolça" + +msgid "Marathi" +msgstr "Marasi" + +msgid "Malay" +msgstr "Malaý" + +msgid "Burmese" +msgstr "Birma" + +msgid "Norwegian Bokmål" +msgstr "Norwegiýa Bokmaly" + +msgid "Nepali" +msgstr "Nepali" + +msgid "Dutch" +msgstr "Gollandça" + +msgid "Norwegian Nynorsk" +msgstr "Norwegiýa Nynorskçasy" + +msgid "Ossetic" +msgstr "Osetikçe" + +msgid "Punjabi" +msgstr "Penjebiçe" + +msgid "Polish" +msgstr "Polýakça" + +msgid "Portuguese" +msgstr "Portugalça" + +msgid "Brazilian Portuguese" +msgstr "Braziliýa Portugalçasy" + +msgid "Romanian" +msgstr "Rumynça" + +msgid "Russian" +msgstr "Rusça" + +msgid "Slovak" +msgstr "Slowakça" + +msgid "Slovenian" +msgstr "Slowençe" + +msgid "Albanian" +msgstr "Albança" + +msgid "Serbian" +msgstr "Serbçe" + +msgid "Serbian Latin" +msgstr "Serb Latynçasy" + +msgid "Swedish" +msgstr "Şwedçe" + +msgid "Swahili" +msgstr "Swahili" + +msgid "Tamil" +msgstr "Tamil" + +msgid "Telugu" +msgstr "Telugu" + +msgid "Tajik" +msgstr "Täjik" + +msgid "Thai" +msgstr "Taýça" + +msgid "Turkmen" +msgstr "Türkmençe" + +msgid "Turkish" +msgstr "Türkçe" + +msgid "Tatar" +msgstr "Tatarça" + +msgid "Udmurt" +msgstr "Udmurt" + +msgid "Uyghur" +msgstr "" + +msgid "Ukrainian" +msgstr "Ukrainçe" + +msgid "Urdu" +msgstr "Urduça" + +msgid "Uzbek" +msgstr "Özbekçe" + +msgid "Vietnamese" +msgstr "Wýetnamça" + +msgid "Simplified Chinese" +msgstr "Ýönekeýleşdirilen Hytaýça" + +msgid "Traditional Chinese" +msgstr "Adaty Hytaýça" + +msgid "Messages" +msgstr "Habarlar" + +msgid "Site Maps" +msgstr "Saýt Kartalary" + +msgid "Static Files" +msgstr "Statik Faýllar" + +msgid "Syndication" +msgstr "Syndikasiýa" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "..." + +msgid "That page number is not an integer" +msgstr "Ol sahypanyň sany bitewi san däl" + +msgid "That page number is less than 1" +msgstr "Ol sahypanyň belgisi 1-den az" + +msgid "That page contains no results" +msgstr "Ol sahypada hiç hili netije ýok" + +msgid "Enter a valid value." +msgstr "Dogry baha giriziň." + +msgid "Enter a valid URL." +msgstr "Dogry URL giriziň." + +msgid "Enter a valid integer." +msgstr "Dogry bitewi san giriziň." + +msgid "Enter a valid email address." +msgstr "Dogry e-poçta salgysyny giriziň." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Harplardan, sanlardan, aşaky çyzyklardan ýa-da defislerden ybarat dogry " +"“slug” giriziň." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Unikod harplaryndan, sanlardan, aşaky çyzyklardan ýa-da defislerden ybarat " +"dogry “slug” giriziň." + +msgid "Enter a valid IPv4 address." +msgstr "Dogry IPv4 salgysyny giriziň." + +msgid "Enter a valid IPv6 address." +msgstr "Dogry IPv6 salgysyny giriziň." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Dogry IPv4 ýa-da IPv6 adresi giriziň." + +msgid "Enter only digits separated by commas." +msgstr "Diňe otur bilen aýrylan sanlary giriziň." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"%(limit_value)s bahasynyň dogry bolmagyny üpjün ediň (şuwagt %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" +"Maglumatyň %(limit_value)s bahasyndan az ýa-da deň bolmagyny üpjün ediň." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" +"Maglumatyň %(limit_value)s bahasyndan köp ýa-da deň bolmagyny üpjün ediň." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "Bu baha %(limit_value)s-nyň essesi bolmaly." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Bu maglumatda iň az %(limit_value)d harp bardygyna göz ýetiriň (munda " +"%(show_value)d bar)." +msgstr[1] "" +"Bu maglumatda azyndan %(limit_value)d nyşanyň bolmagyny üpjün ediň (şuwagt " +"%(show_value)d sany bar)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Bu maglumatda köpünden %(limit_value)d harp bardygyna göz ýetiriň (bunda " +"%(show_value)d bar)" +msgstr[1] "" +"Bu maglumatda iň köp %(limit_value)d nyşanyň bolmagyny üpjün ediň (şuwagt " +"%(show_value)d sany bar)" + +msgid "Enter a number." +msgstr "San giriziň" + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Bu ýerde jemi %(max)s'dan köp san ýokduguna göz ýetiriň." +msgstr[1] "Bu ýerde jemi %(max)s sanydan köp sifriň bolmazlygyny üpjün ediň." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Bu ýerde %(max)s'dan köp nokatly san ýokdugyna göz ýetiriň" +msgstr[1] "Bu ýerde %(max)s sanydan köp nokatly san ýoklugyny üpjün ediň." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "Nokatdan öň %(max)s'dan köp san ýokdugyna göz ýetiriň" +msgstr[1] "Nokatdan öň %(max)s sanydan köp sifriň ýoklugyny üpjün ediň." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"\"%(extension)s\" faýl görnüşine rugsat edilmeýär. Rugsat berilýän faýl " +"görnüşleri şulardan ybarat: %(allowed_extensions)s" + +msgid "Null characters are not allowed." +msgstr "Null nyşanlara rugsat berilmeýär." + +msgid "and" +msgstr "we" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(field_labels)s bilen baglanyşykly %(model_name)s eýýäm bar." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "Çäklendirme “%(name)s” bozuldy." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "%(value)r dogry saýlaw däl." + +msgid "This field cannot be null." +msgstr "Bu meýdan null bilmez." + +msgid "This field cannot be blank." +msgstr "Bu meýdan boş bolup bilmez." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(field_label)s bilen baglanyşykly %(model_name)s eýýäm bar." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(lookup_type)s %(date_field_label)s üçin %(field_label)s özboluşly " +"bolmalydyr." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Meýdan görnüşi: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "\"%(value)s\" hökman True ýa-da False bolmalydyr." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "\"%(value)s\" hökman True, False ýa-da None bolmalydyr." + +msgid "Boolean (Either True or False)" +msgstr "Boolean (True ýa-da False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Setir (iň köp %(max_length)s)" + +msgid "String (unlimited)" +msgstr "String (limitsiz)" + +msgid "Comma-separated integers" +msgstr "Otur bilen bölünen bitewi sanlar" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"\"%(value)s\" bahasynyň nädogry sene formaty bar. ÝÝÝÝ-AA-GG görnüşinde " +"bolmaly." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"\"%(value)s\" dogry yazylyş usuluna (ÝÝÝÝ-AA-GG) eýe, ýöne, sene nädogry." + +msgid "Date (without time)" +msgstr "Sene (wagtsyz)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"\"%(value)s\" ýalňyş görnüşde ýazylan. Bu baha hökmany suratda ÝÝÝÝ-AA-GG SS:" +"MM[:ss[.uuuuuu]][TZ] görnüşde bolmalydyr." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"\"%(value)s\" dogry sene görnüşine eýe (ÝÝÝÝ-AA-GG SS:MM[:ss[.uuuuuu]][TZ]). " +"Ýöne bu nädogry sene/wagt." + +msgid "Date (with time)" +msgstr "Sene (wagty bilen)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "\"%(value)s\" hökman nokatly san bolmalydyr." + +msgid "Decimal number" +msgstr "Onluk san" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"\"%(value)s\" ýalňyş sene görnüşine eýe. Bu hökman [GG] [[SS:]AA:]ss[." +"uuuuuu] görnüşinde bolmalydyr." + +msgid "Duration" +msgstr "Dowamlylyk" + +msgid "Email address" +msgstr "Email adres" + +msgid "File path" +msgstr "Faýl ýoly" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "\"%(value)s float san bolmaly." + +msgid "Floating point number" +msgstr "Float san" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "\"%(value)s\" bitewi san bolmaly." + +msgid "Integer" +msgstr "Bitewi san" + +msgid "Big (8 byte) integer" +msgstr "Uly (8 baýt) bitewi san" + +msgid "Small integer" +msgstr "Kiçi bitewi san" + +msgid "IPv4 address" +msgstr "IPv4 salgy" + +msgid "IP address" +msgstr "IP salgy" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "\"%(value)s\" None, True ýa-da False bolmaly." + +msgid "Boolean (Either True, False or None)" +msgstr "Boolean (True, False ýa-da None)" + +msgid "Positive big integer" +msgstr "Pozitiw uly bitewi san" + +msgid "Positive integer" +msgstr "Pozitiw bitewi san" + +msgid "Positive small integer" +msgstr "Pozitiw kiçi bitewi san" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (iň köp %(max_length)s)" + +msgid "Text" +msgstr "Tekst" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"\"%(value)s\" bahasy nädogry formata eýe. SS:MM[:ss[.uuuuuu]] formatda " +"bolmaly." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"\"%(value)s\" bahasy dogry formata eýe (SS:MM[:ss[.uuuuuu]]) ýöne bu nädogry " +"wagt." + +msgid "Time" +msgstr "Wagt" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Çig ikilik maglumat" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "\"%(value)s\" dogry UUID däl." + +msgid "Universally unique identifier" +msgstr "Ähliumumy özboluşly kesgitleýji" + +msgid "File" +msgstr "Faýl" + +msgid "Image" +msgstr "Surat" + +msgid "A JSON object" +msgstr "JSON obýekti" + +msgid "Value must be valid JSON." +msgstr "Bahasy JSON bolmaly." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(field)s%(value)r bolan %(model)s ýok." + +msgid "Foreign Key (type determined by related field)" +msgstr "Daşary açary (baglanyşykly meýdança bilen kesgitlenýär)" + +msgid "One-to-one relationship" +msgstr "Bire-bir gatnaşyk" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s gatnaşyk" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s gatnaşyklar" + +msgid "Many-to-many relationship" +msgstr "Köp-köp gatnaşyk" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Bu meýdança hökman gerekli." + +msgid "Enter a whole number." +msgstr "Bitin san giriziň." + +msgid "Enter a valid date." +msgstr "Dogry senäni giriziň." + +msgid "Enter a valid time." +msgstr "Dogry wagt giriziň." + +msgid "Enter a valid date/time." +msgstr "Dogry senäni/wagty giriziň." + +msgid "Enter a valid duration." +msgstr "Dogry dowamlylygy giriziň." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Günleriň sany {min_days} bilen {max_days} arasynda bolmaly." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Hiç hili faýl tabşyrylmady. Formadaky enkodiň görnüşini barlaň." + +msgid "No file was submitted." +msgstr "Hiç hili faýl tabşyrylmady." + +msgid "The submitted file is empty." +msgstr "Tabşyrylan faýl boş." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Bu faýl adynyň iň köp %(max)d nyşanynyň bolmagyny üpjin ediň (şuwagt " +"%(length)d sany bar)." +msgstr[1] "" +"Bu faýl adynyň iň köp %(max)d nyşanynyň bolmagyny üpjin ediň (şuwagt " +"%(length)d sany bar)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Bir faýl iberiň ýa-da arassala gutyjygyny belläň, ikisini bile däl." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Dogry surat ýükläň. Ýüklän faýlyňyz ýa surat däldi ýa-da zaýalanan suratdy." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Dogry saýlawy saýlaň. %(value)s elýeterli saýlawlaryň biri däl." + +msgid "Enter a list of values." +msgstr "Bahalaryň sanawyny giriziň." + +msgid "Enter a complete value." +msgstr "Doly bahany giriziň." + +msgid "Enter a valid UUID." +msgstr "Dogry UUID giriziň." + +msgid "Enter a valid JSON." +msgstr "Dogry JSON giriziň." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Gizlin meýdan %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"ManagementForm maglumatlary ýok ýa-da bozulan. Tapylmadyk meýdança: " +"%(field_names)s. Mesele dowam etse, \"bug report\" açmaly bolmagyňyz mümkin." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Haýyş, iň köp %(num)d form tabşyryň." +msgstr[1] "Haýyş, iň köp %(num)d form tabşyryň." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Haýyş, azyndan %(num)d form tabşyryň." +msgstr[1] "Haýyş, azyndan %(num)d form tabşyryň." + +msgid "Order" +msgstr "Tertip" + +msgid "Delete" +msgstr "Poz" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "%(field)s üçin dublikat maglumatlary düzediň." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Özboluşly bolmaly %(field)s üçin dublikat maglumatlary düzediň." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"%(date_field)s meýdanynda %(lookup)süçin özboluşly bolmaly %(field_name)s " +"üçin dublikat maglumatlary düzediň." + +msgid "Please correct the duplicate values below." +msgstr "Aşakdaky dublikat bahalary düzediň." + +msgid "The inline value did not match the parent instance." +msgstr "Giriş bahasy esasy mysal bilen gabat gelmedi." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Dogry saýlawy saýlaň. Bu saýlaw, elýeterli saýlawlaryň biri däl." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "\"%(pk)s\" dogry baha däl." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s wagty %(current_timezone)s wagt zolagy bilen düşündirip " +"bolmady; garyşyk bolup biler ýa-da ýok bolmagy mümkin." + +msgid "Clear" +msgstr "Arassala" + +msgid "Currently" +msgstr "Häzirki wagtda" + +msgid "Change" +msgstr "Üýtget" + +msgid "Unknown" +msgstr "Näbelli" + +msgid "Yes" +msgstr "Hawa" + +msgid "No" +msgstr "Ýok" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "hawa,ýok,belki" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d baýt" +msgstr[1] "%(size)d baýt" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m" + +msgid "a.m." +msgstr "a.m" + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "ýary gije" + +msgid "noon" +msgstr "günortan" + +msgid "Monday" +msgstr "Duşenbe" + +msgid "Tuesday" +msgstr "Sişenbe" + +msgid "Wednesday" +msgstr "Çarşenbe" + +msgid "Thursday" +msgstr "Penşenbe" + +msgid "Friday" +msgstr "Anna" + +msgid "Saturday" +msgstr "Şenbe" + +msgid "Sunday" +msgstr "Ýekşenbe" + +msgid "Mon" +msgstr "Duş" + +msgid "Tue" +msgstr "Siş" + +msgid "Wed" +msgstr "Çarş" + +msgid "Thu" +msgstr "Pen" + +msgid "Fri" +msgstr "Anna" + +msgid "Sat" +msgstr "Şen" + +msgid "Sun" +msgstr "Ýek" + +msgid "January" +msgstr "Ýanwar" + +msgid "February" +msgstr "Fewral" + +msgid "March" +msgstr "Mart" + +msgid "April" +msgstr "Aprel" + +msgid "May" +msgstr "Maý" + +msgid "June" +msgstr "Iýun" + +msgid "July" +msgstr "Iýul" + +msgid "August" +msgstr "Awgust" + +msgid "September" +msgstr "Sentýabr" + +msgid "October" +msgstr "Oktýabr" + +msgid "November" +msgstr "Noýabr" + +msgid "December" +msgstr "Dekabr" + +msgid "jan" +msgstr "ýan" + +msgid "feb" +msgstr "few" + +msgid "mar" +msgstr "mart" + +msgid "apr" +msgstr "apr" + +msgid "may" +msgstr "maý" + +msgid "jun" +msgstr "iýun" + +msgid "jul" +msgstr "iýul" + +msgid "aug" +msgstr "awg" + +msgid "sep" +msgstr "sent" + +msgid "oct" +msgstr "okt" + +msgid "nov" +msgstr "noý" + +msgid "dec" +msgstr "dek" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Ýan." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Few." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Mart" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Aprel" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Maý" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Iýun" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Iýul" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Awg." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Sent." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Okt." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Noý." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dek." + +msgctxt "alt. month" +msgid "January" +msgstr "Ýanwar" + +msgctxt "alt. month" +msgid "February" +msgstr "Fewral" + +msgctxt "alt. month" +msgid "March" +msgstr "Mart" + +msgctxt "alt. month" +msgid "April" +msgstr "Aprel" + +msgctxt "alt. month" +msgid "May" +msgstr "Maý" + +msgctxt "alt. month" +msgid "June" +msgstr "Iýun" + +msgctxt "alt. month" +msgid "July" +msgstr "Iýul" + +msgctxt "alt. month" +msgid "August" +msgstr "Awgust" + +msgctxt "alt. month" +msgid "September" +msgstr "Sentýabr" + +msgctxt "alt. month" +msgid "October" +msgstr "Oktýabr" + +msgctxt "alt. month" +msgid "November" +msgstr "Noýabr" + +msgctxt "alt. month" +msgid "December" +msgstr "Dekabr" + +msgid "This is not a valid IPv6 address." +msgstr "Bu dogry IPv6 salgy däl." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "ýa" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "\"" + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d ýyl" +msgstr[1] "%(num)d ýyl" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d aý" +msgstr[1] "%(num)d aý" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d hepde" +msgstr[1] "%(num)d hepde" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d gün" +msgstr[1] "%(num)d gün" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d sagat" +msgstr[1] "%(num)d sagat" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minut" +msgstr[1] "%(num)d minut" + +msgid "Forbidden" +msgstr "Gadagan " + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF dogrylamak şowsuz. Talap ýatyryldy." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Bu haty görýärsiňiz, sebäbi bu HTTPS sahypasy web brauzeriňiz tarapyndan " +"iberilmeli \"Referer header\" talap edýär, ýöne hiç biri iberilmedi. Bu " +"sözbaşy, brauzeriňiziň üçünji şahyslar tarapyndan ogurlanmazlygy üçin " +"howpsuzlyk sebäpli talap edilýär." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Brauzeriňizde \"Referer\" sözbaşylaryny öçüren bolsaňyz, iň bolmanda bu " +"sahypa ýa-da HTTPS birikmeleri ýa-da \"meňzeş\" talaplar üçin täzeden açyň." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Egerde siz diýen bellik " +"ýada \"Referrer-Policy: no-referrer\" header ulanýan bolsaňyz, olary " +"aýyrmagyňyzy haýyş edýäris. CSRF goragy üçin \"Referer\" header-i dogry " +"salgylanma üçin gereklidir. Eger siz gizlinlik üçin alada etseňiz, üçinji " +"şahs sahypalara baglanyşyklar üçin ýaly " +"alternatiwalary ulanyp bilersiňiz." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Bu sahypa formalary tabşyranda CSRF kukisini talap edýäligi sebäpli bu " +"habary görýärsiňiz. Bu kuki, brauzeriňiziň üçünji taraplar tarapyndan " +"ogurlanmazlygy üçin howpsuzlyk sebäpli talap edilýär." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Brauzeriňizde kukileri öçüren bolsaňyz, iň bolmanda şu sahypa ýa-da " +"\"meňzeş\" talaplar üçin olary täzeden açyň." + +msgid "More information is available with DEBUG=True." +msgstr "Has giňişleýin maglumat DEBUG=True bilen elýeterlidir." + +msgid "No year specified" +msgstr "Ýyl görkezilmedi" + +msgid "Date out of range" +msgstr "Sene çägiň daşynda" + +msgid "No month specified" +msgstr "Aý görkezilmedi" + +msgid "No day specified" +msgstr "Gün görkezilmedi" + +msgid "No week specified" +msgstr "Hepde görkezilmedi" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Elýeterli %(verbose_name_plural)s ýok" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Gelejek %(verbose_name_plural)s elýeterli däl sebäbi %(class_name)s." +"allow_future bahasy False" + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Nädogry sene setiri \"%(datestr)s\" berlen format \"%(format)s\"" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Talap bilen gabat gelýän %(verbose_name)s tapylmady" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Sahypa “iň soňky” däl, ony int-ede öwrüp bolmaz." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Nädogry sahypa (%(page_number)s ): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Boş list we \"%(class_name)s.allow_empty\" bahasy False" + +msgid "Directory indexes are not allowed here." +msgstr "Bu ýerde katalog indekslerine rugsat berilmeýär." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "\"%(path)s\" beýle ýol ýok" + +#, python-format +msgid "Index of %(directory)s" +msgstr "%(directory)s indeksi" + +msgid "The install worked successfully! Congratulations!" +msgstr "Üstünlikli guruldy! Gutlaýarys!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Django %(version)s üçin goýberiş " +"belliklerini görüň" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Bu sahypany görýärsiňiz, sebäbi sazlamalar faýlyňyzda DEBUG=True we hiç hili URL düzmediňiz." + +msgid "Django Documentation" +msgstr "Django resminamalary" + +msgid "Topics, references, & how-to’s" +msgstr "Mowzuklar, salgylanmalar, & how-to-lar" + +msgid "Tutorial: A Polling App" +msgstr "Gollanma: Ses beriş programmasy" + +msgid "Get started with Django" +msgstr "Django bilen başlaň" + +msgid "Django Community" +msgstr "Django jemgyýeti" + +msgid "Connect, get help, or contribute" +msgstr "Birikiň, kömek alyň ýa-da goşant goşuň" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tk/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tk/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tk/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tk/formats.py new file mode 100644 index 0000000..0ab7d49 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tk/formats.py @@ -0,0 +1,32 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j E Y г." +TIME_FORMAT = "G:i" +DATETIME_FORMAT = "j E Y г. G:i" +YEAR_MONTH_FORMAT = "F Y г." +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "d.m.Y" +SHORT_DATETIME_FORMAT = "d.m.Y H:i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d.%m.%Y", # '25.10.2006' + "%d.%m.%y", # '25.10.06' +] +DATETIME_INPUT_FORMATS = [ + "%d.%m.%Y %H:%M:%S", # '25.10.2006 14:30:59' + "%d.%m.%Y %H:%M:%S.%f", # '25.10.2006 14:30:59.000200' + "%d.%m.%Y %H:%M", # '25.10.2006 14:30' + "%d.%m.%Y", # '25.10.2006' + "%d.%m.%y %H:%M:%S", # '25.10.06 14:30:59' + "%d.%m.%y %H:%M:%S.%f", # '25.10.06 14:30:59.000200' + "%d.%m.%y %H:%M", # '25.10.06 14:30' + "%d.%m.%y", # '25.10.06' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "\xa0" # non-breaking space +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..dd8be7f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tr/LC_MESSAGES/django.po new file mode 100644 index 0000000..e9cee04 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tr/LC_MESSAGES/django.po @@ -0,0 +1,1352 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ahmet Emre Aladağ , 2013 +# BouRock, 2015-2023 +# BouRock, 2014-2015 +# Caner Başaran , 2013 +# Cihad GÜNDOĞDU , 2012 +# Cihad GÜNDOĞDU , 2013-2014 +# Gökmen Görgen , 2013 +# Jannis Leidel , 2011 +# Mesut Can Gürle , 2013 +# Murat Çorlu , 2012 +# Murat Sahin , 2011-2012 +# Türker Sezer , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: BouRock, 2015-2023\n" +"Language-Team: Turkish (http://app.transifex.com/django/django/language/" +"tr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Afrikaans" +msgstr "Afrikanca" + +msgid "Arabic" +msgstr "Arapça" + +msgid "Algerian Arabic" +msgstr "Cezayir Arapçası" + +msgid "Asturian" +msgstr "Asturyaca" + +msgid "Azerbaijani" +msgstr "Azerice" + +msgid "Bulgarian" +msgstr "Bulgarca" + +msgid "Belarusian" +msgstr "Beyaz Rusça" + +msgid "Bengali" +msgstr "Bengalce" + +msgid "Breton" +msgstr "Bretonca" + +msgid "Bosnian" +msgstr "Boşnakça" + +msgid "Catalan" +msgstr "Katalanca" + +msgid "Central Kurdish (Sorani)" +msgstr "Orta Kürtçe (Sorani)" + +msgid "Czech" +msgstr "Çekçe" + +msgid "Welsh" +msgstr "Galce" + +msgid "Danish" +msgstr "Danca" + +msgid "German" +msgstr "Almanca" + +msgid "Lower Sorbian" +msgstr "Aşağı Sorb dili" + +msgid "Greek" +msgstr "Yunanca" + +msgid "English" +msgstr "İngilizce" + +msgid "Australian English" +msgstr "Avusturya İngilizcesi" + +msgid "British English" +msgstr "İngiliz İngilizcesi" + +msgid "Esperanto" +msgstr "Esperanto dili" + +msgid "Spanish" +msgstr "İspanyolca" + +msgid "Argentinian Spanish" +msgstr "Arjantin İspanyolcası" + +msgid "Colombian Spanish" +msgstr "Kolomiya İspanyolcası" + +msgid "Mexican Spanish" +msgstr "Meksika İspanyolcası" + +msgid "Nicaraguan Spanish" +msgstr "Nikaragua İspanyolcası" + +msgid "Venezuelan Spanish" +msgstr "Venezüella İspanyolcası" + +msgid "Estonian" +msgstr "Estonca" + +msgid "Basque" +msgstr "Baskça" + +msgid "Persian" +msgstr "Farsça" + +msgid "Finnish" +msgstr "Fince" + +msgid "French" +msgstr "Fransızca" + +msgid "Frisian" +msgstr "Frizce" + +msgid "Irish" +msgstr "İrlandaca" + +msgid "Scottish Gaelic" +msgstr "İskoçça Galcesi" + +msgid "Galician" +msgstr "Galiçyaca" + +msgid "Hebrew" +msgstr "İbranice" + +msgid "Hindi" +msgstr "Hintçe" + +msgid "Croatian" +msgstr "Hırvatça" + +msgid "Upper Sorbian" +msgstr "Yukarı Sorb dili" + +msgid "Hungarian" +msgstr "Macarca" + +msgid "Armenian" +msgstr "Ermenice" + +msgid "Interlingua" +msgstr "Interlingua" + +msgid "Indonesian" +msgstr "Endonezce" + +msgid "Igbo" +msgstr "Igbo dili" + +msgid "Ido" +msgstr "Ido dili" + +msgid "Icelandic" +msgstr "İzlandaca" + +msgid "Italian" +msgstr "İtalyanca" + +msgid "Japanese" +msgstr "Japonca" + +msgid "Georgian" +msgstr "Gürcüce" + +msgid "Kabyle" +msgstr "Kabiliye dili" + +msgid "Kazakh" +msgstr "Kazakça" + +msgid "Khmer" +msgstr "Kmerce" + +msgid "Kannada" +msgstr "Kannada dili" + +msgid "Korean" +msgstr "Korece" + +msgid "Kyrgyz" +msgstr "Kırgızca" + +msgid "Luxembourgish" +msgstr "Lüksemburgca" + +msgid "Lithuanian" +msgstr "Litovca" + +msgid "Latvian" +msgstr "Letonca" + +msgid "Macedonian" +msgstr "Makedonca" + +msgid "Malayalam" +msgstr "Malayamca" + +msgid "Mongolian" +msgstr "Moğolca" + +msgid "Marathi" +msgstr "Marathi dili" + +msgid "Malay" +msgstr "Malayca" + +msgid "Burmese" +msgstr "Birmanca" + +msgid "Norwegian Bokmål" +msgstr "Norveççe Bokmal" + +msgid "Nepali" +msgstr "Nepalce" + +msgid "Dutch" +msgstr "Flemenkçe" + +msgid "Norwegian Nynorsk" +msgstr "Norveççe Nynorsk" + +msgid "Ossetic" +msgstr "Osetçe" + +msgid "Punjabi" +msgstr "Pencapça" + +msgid "Polish" +msgstr "Lehçe" + +msgid "Portuguese" +msgstr "Portekizce" + +msgid "Brazilian Portuguese" +msgstr "Brezilya Portekizcesi" + +msgid "Romanian" +msgstr "Romence" + +msgid "Russian" +msgstr "Rusça" + +msgid "Slovak" +msgstr "Slovakça" + +msgid "Slovenian" +msgstr "Slovence" + +msgid "Albanian" +msgstr "Arnavutça" + +msgid "Serbian" +msgstr "Sırpça" + +msgid "Serbian Latin" +msgstr "Sırpça Latin" + +msgid "Swedish" +msgstr "İsveççe" + +msgid "Swahili" +msgstr "Savahilice" + +msgid "Tamil" +msgstr "Tamilce" + +msgid "Telugu" +msgstr "Telugu dili" + +msgid "Tajik" +msgstr "Tacikçe" + +msgid "Thai" +msgstr "Tayca" + +msgid "Turkmen" +msgstr "Türkmence" + +msgid "Turkish" +msgstr "Türkçe" + +msgid "Tatar" +msgstr "Tatarca" + +msgid "Udmurt" +msgstr "Udmurtça" + +msgid "Uyghur" +msgstr "Uygur" + +msgid "Ukrainian" +msgstr "Ukraynaca" + +msgid "Urdu" +msgstr "Urduca" + +msgid "Uzbek" +msgstr "‎Özbekçe" + +msgid "Vietnamese" +msgstr "Vietnamca" + +msgid "Simplified Chinese" +msgstr "Basitleştirilmiş Çince" + +msgid "Traditional Chinese" +msgstr "Geleneksel Çince" + +msgid "Messages" +msgstr "İletiler" + +msgid "Site Maps" +msgstr "Site Haritaları" + +msgid "Static Files" +msgstr "Sabit Dosyalar" + +msgid "Syndication" +msgstr "Dağıtım" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Bu sayfa numarası bir tamsayı değil" + +msgid "That page number is less than 1" +msgstr "Bu sayfa numarası 1’den az" + +msgid "That page contains no results" +msgstr "Bu sayfa hiç sonuç içermiyor" + +msgid "Enter a valid value." +msgstr "Geçerli bir değer girin." + +msgid "Enter a valid URL." +msgstr "Geçerli bir URL girin." + +msgid "Enter a valid integer." +msgstr "Geçerli bir tamsayı girin." + +msgid "Enter a valid email address." +msgstr "Geçerli bir e-posta adresi girin." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Harflerden, sayılardan, altçizgilerden veya tirelerden oluşan geçerli bir " +"“kısaltma” girin." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Evrensel kod harflerden, sayılardan, altçizgilerden veya tirelerden oluşan " +"geçerli bir “kısaltma” girin." + +msgid "Enter a valid IPv4 address." +msgstr "Geçerli bir IPv4 adresi girin." + +msgid "Enter a valid IPv6 address." +msgstr "Geçerli bir IPv6 adresi girin." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Geçerli bir IPv4 veya IPv6 adresi girin." + +msgid "Enter only digits separated by commas." +msgstr "Sadece virgülle ayrılmış rakamlar girin." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Bu değerin %(limit_value)s olduğuna emin olun (şu an %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Bu değerin %(limit_value)s değerinden az veya eşit olduğuna emin olun." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" +"Bu değerin %(limit_value)s değerinden büyük veya eşit olduğuna emin olun." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" +"Bu değerin %(limit_value)s adım boyutunun katları olduğundan emin olun." + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"Bu değerin %(offset)s değerinden başlayarak %(limit_value)s adım boyutunun " +"katı olduğundan emin olun, örn. %(offset)s, %(valid_value1)s, " +"%(valid_value2)s, vb." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Bu değerin en az %(limit_value)d karaktere sahip olduğuna emin olun (şu an " +"%(show_value)d)." +msgstr[1] "" +"Bu değerin en az %(limit_value)d karaktere sahip olduğuna emin olun (şu an " +"%(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Bu değerin en fazla %(limit_value)d karaktere sahip olduğuna emin olun (şu " +"an %(show_value)d)." +msgstr[1] "" +"Bu değerin en fazla %(limit_value)d karaktere sahip olduğuna emin olun (şu " +"an %(show_value)d)." + +msgid "Enter a number." +msgstr "Bir sayı girin." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Toplamda %(max)s rakamdan daha fazla olmadığından emin olun." +msgstr[1] "Toplamda %(max)s rakamdan daha fazla olmadığından emin olun." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "%(max)s ondalık basamaktan daha fazla olmadığından emin olun." +msgstr[1] "%(max)s ondalık basamaktan daha fazla olmadığından emin olun." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Ondalık noktasından önce %(max)s rakamdan daha fazla olmadığından emin olun." +msgstr[1] "" +"Ondalık noktasından önce %(max)s rakamdan daha fazla olmadığından emin olun." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"“%(extension)s” dosya uzantısına izin verilmiyor. İzin verilen uzantılar: " +"%(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Boş karakterlere izin verilmiyor." + +msgid "and" +msgstr "ve" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "Bu %(field_labels)s alanına sahip %(model_name)s zaten mevcut." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "\"%(name)s\" kısıtlaması ihlal edildi." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "%(value)r değeri geçerli bir seçim değil." + +msgid "This field cannot be null." +msgstr "Bu alan boş olamaz." + +msgid "This field cannot be blank." +msgstr "Bu alan boş olamaz." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "Bu %(field_label)s alanına sahip %(model_name)s zaten mevcut." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s, %(date_field_label)s %(lookup_type)s için benzersiz olmak " +"zorundadır." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Alan türü: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "“%(value)s” değeri ya True ya da False olmak zorundadır." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "“%(value)s” değeri ya True, False ya da None olmak zorundadır." + +msgid "Boolean (Either True or False)" +msgstr "Boolean (Ya True ya da False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Dizgi (%(max_length)s karaktere kadar)" + +msgid "String (unlimited)" +msgstr "Dizgi (sınırsız)" + +msgid "Comma-separated integers" +msgstr "Virgülle ayrılmış tamsayılar" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"“%(value)s” değeri geçersiz bir tarih biçimine sahip. Bu YYYY-MM-DD " +"biçiminde olmak zorundadır." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"“%(value)s” değeri doğru bir biçime (YYYY-MM-DD) sahip ancak bu geçersiz bir " +"tarih." + +msgid "Date (without time)" +msgstr "Tarih (saat olmadan)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"“%(value)s” değeri geçersiz bir biçime sahip. YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ] biçiminde olmak zorundadır." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"“%(value)s” değeri doğru bir biçime (YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) " +"sahip ancak bu geçersiz bir tarih/saat." + +msgid "Date (with time)" +msgstr "Tarih (saat olan)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "“%(value)s” değeri bir ondalık sayı olmak zorundadır." + +msgid "Decimal number" +msgstr "Ondalık sayı" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"“%(value)s” değer geçersiz bir biçime sahip. [DD] [HH:[MM:]]ss[.uuuuuu] " +"biçiminde olmak zorundadır." + +msgid "Duration" +msgstr "Süre" + +msgid "Email address" +msgstr "E-posta adresi" + +msgid "File path" +msgstr "Dosya yolu" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "“%(value)s” değeri kayan noktalı bir sayı olmak zorundadır." + +msgid "Floating point number" +msgstr "Kayan noktalı sayı" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "“%(value)s” değeri bir tamsayı olmak zorundadır." + +msgid "Integer" +msgstr "Tamsayı" + +msgid "Big (8 byte) integer" +msgstr "Büyük (8 bayt) tamsayı" + +msgid "Small integer" +msgstr "Küçük tamsayı" + +msgid "IPv4 address" +msgstr "IPv4 adresi" + +msgid "IP address" +msgstr "IP adresi" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "“%(value)s” değeri ya None, True ya da False olmak zorundadır." + +msgid "Boolean (Either True, False or None)" +msgstr "Booleanl (Ya True, False, ya da None)" + +msgid "Positive big integer" +msgstr "Pozitif büyük tamsayı" + +msgid "Positive integer" +msgstr "Pozitif tamsayı" + +msgid "Positive small integer" +msgstr "Pozitif küçük tamsayı" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Kısaltma (%(max_length)s karaktere kadar)" + +msgid "Text" +msgstr "Metin" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"“%(value)s” değeri geçersiz bir biçime sahip. HH:MM[:ss[.uuuuuu]] biçiminde " +"olmak zorundadır." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"“%(value)s” değeri doğru biçime (HH:MM[:ss[.uuuuuu]]) sahip ancak bu " +"geçersiz bir saat." + +msgid "Time" +msgstr "Saat" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Ham ikili veri" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "“%(value)s” geçerli bir UUID değil." + +msgid "Universally unique identifier" +msgstr "Evrensel benzersiz tanımlayıcı" + +msgid "File" +msgstr "Dosya" + +msgid "Image" +msgstr "Resim" + +msgid "A JSON object" +msgstr "JSON nesnesi" + +msgid "Value must be valid JSON." +msgstr "Değer geçerli JSON olmak zorundadır." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(field)s %(value)r olan %(model)s benzeri mevcut değil." + +msgid "Foreign Key (type determined by related field)" +msgstr "Dış Anahtar (türü ilgili alana göre belirlenir)" + +msgid "One-to-one relationship" +msgstr "Bire-bir ilişki" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s ilişkisi" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s ilişkileri" + +msgid "Many-to-many relationship" +msgstr "Çoka-çok ilişki" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Bu alan zorunludur." + +msgid "Enter a whole number." +msgstr "Tam bir sayı girin." + +msgid "Enter a valid date." +msgstr "Geçerli bir tarih girin." + +msgid "Enter a valid time." +msgstr "Geçerli bir saat girin." + +msgid "Enter a valid date/time." +msgstr "Geçerli bir tarih/saat girin." + +msgid "Enter a valid duration." +msgstr "Geçerli bir süre girin." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Gün sayıları {min_days} ve {max_days} arasında olmak zorundadır." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Hiç dosya gönderilmedi. Formdaki kodlama türünü kontrol edin." + +msgid "No file was submitted." +msgstr "Hiç dosya gönderilmedi." + +msgid "The submitted file is empty." +msgstr "Gönderilen dosya boş." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Bu dosya adının en fazla %(max)d karaktere sahip olduğundan emin olun (şu an " +"%(length)d)." +msgstr[1] "" +"Bu dosya adının en fazla %(max)d karaktere sahip olduğundan emin olun (şu an " +"%(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Lütfen ya bir dosya gönderin ya da temizle işaretleme kutusunu işaretleyin, " +"ikisini aynı anda işaretlemeyin." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Geçerli bir resim gönderin. Gönderdiğiniz dosya ya bir resim değildi ya da " +"bozulmuş bir resimdi." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Geçerli bir seçenek seçin. %(value)s mevcut seçeneklerden biri değil." + +msgid "Enter a list of values." +msgstr "Değerlerin bir listesini girin." + +msgid "Enter a complete value." +msgstr "Tam bir değer girin." + +msgid "Enter a valid UUID." +msgstr "Geçerli bir UUID girin." + +msgid "Enter a valid JSON." +msgstr "Geçerli bir JSON girin." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Gizli alan %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"ManagementForm verileri eksik veya değiştirilmiş. Eksik alanlar: " +"%(field_names)s. Sorun devam ederse bir hata raporu dosyalamanız gerekebilir." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "Lütfen en fazla %(num)d form gönderin." +msgstr[1] "Lütfen en fazla %(num)d form gönderin." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "Lütfen en az %(num)d form gönderin." +msgstr[1] "Lütfen en az %(num)d form gönderin." + +msgid "Order" +msgstr "Sıralama" + +msgid "Delete" +msgstr "Sil" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Lütfen %(field)s için kopya veriyi düzeltin." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Lütfen %(field)s için benzersiz olmak zorunda olan, kopya veriyi düzeltin." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Lütfen %(date_field)s içindeki %(lookup)s için benzersiz olmak zorunda olan " +"%(field_name)s için kopya veriyi düzeltin." + +msgid "Please correct the duplicate values below." +msgstr "Lütfen aşağıdaki kopya değerleri düzeltin." + +msgid "The inline value did not match the parent instance." +msgstr "Satıriçi değer ana örnek ile eşleşmedi." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Geçerli bir seçenek seçin. Bu seçenek, mevcut seçeneklerden biri değil." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "“%(pk)s” geçerli bir değer değil." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s, %(current_timezone)s saat dilimi olarak yorumlanamadı; bu " +"belirsiz olabilir ya da mevcut olmayabilir." + +msgid "Clear" +msgstr "Temizle" + +msgid "Currently" +msgstr "Şu anki" + +msgid "Change" +msgstr "Değiştir" + +msgid "Unknown" +msgstr "Bilinmiyor" + +msgid "Yes" +msgstr "Evet" + +msgid "No" +msgstr "Hayır" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "evet,hayır,olabilir" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d bayt" +msgstr[1] "%(size)d bayt" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "ö.s." + +msgid "a.m." +msgstr "ö.ö." + +msgid "PM" +msgstr "ÖS" + +msgid "AM" +msgstr "ÖÖ" + +msgid "midnight" +msgstr "gece yarısı" + +msgid "noon" +msgstr "öğlen" + +msgid "Monday" +msgstr "Pazartesi" + +msgid "Tuesday" +msgstr "Salı" + +msgid "Wednesday" +msgstr "Çarşamba" + +msgid "Thursday" +msgstr "Perşembe" + +msgid "Friday" +msgstr "Cuma" + +msgid "Saturday" +msgstr "Cumartesi" + +msgid "Sunday" +msgstr "Pazar" + +msgid "Mon" +msgstr "Pzt" + +msgid "Tue" +msgstr "Sal" + +msgid "Wed" +msgstr "Çrş" + +msgid "Thu" +msgstr "Prş" + +msgid "Fri" +msgstr "Cum" + +msgid "Sat" +msgstr "Cmt" + +msgid "Sun" +msgstr "Paz" + +msgid "January" +msgstr "Ocak" + +msgid "February" +msgstr "Şubat" + +msgid "March" +msgstr "Mart" + +msgid "April" +msgstr "Nisan" + +msgid "May" +msgstr "Mayıs" + +msgid "June" +msgstr "Haziran" + +msgid "July" +msgstr "Temmuz" + +msgid "August" +msgstr "Ağustos" + +msgid "September" +msgstr "Eylül" + +msgid "October" +msgstr "Ekim" + +msgid "November" +msgstr "Kasım" + +msgid "December" +msgstr "Aralık" + +msgid "jan" +msgstr "oca" + +msgid "feb" +msgstr "şub" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "nis" + +msgid "may" +msgstr "may" + +msgid "jun" +msgstr "haz" + +msgid "jul" +msgstr "tem" + +msgid "aug" +msgstr "ağu" + +msgid "sep" +msgstr "eyl" + +msgid "oct" +msgstr "eki" + +msgid "nov" +msgstr "kas" + +msgid "dec" +msgstr "ara" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Oca." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Şub." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Mart" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Nisan" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Mayıs" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Haz." + +msgctxt "abbrev. month" +msgid "July" +msgstr "Tem." + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Ağu." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Eyl." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Eki." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Kas." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Ara." + +msgctxt "alt. month" +msgid "January" +msgstr "Ocak" + +msgctxt "alt. month" +msgid "February" +msgstr "Şubat" + +msgctxt "alt. month" +msgid "March" +msgstr "Mart" + +msgctxt "alt. month" +msgid "April" +msgstr "Nisan" + +msgctxt "alt. month" +msgid "May" +msgstr "Mayıs" + +msgctxt "alt. month" +msgid "June" +msgstr "Haziran" + +msgctxt "alt. month" +msgid "July" +msgstr "Temmuz" + +msgctxt "alt. month" +msgid "August" +msgstr "Ağustos" + +msgctxt "alt. month" +msgid "September" +msgstr "Eylül" + +msgctxt "alt. month" +msgid "October" +msgstr "Ekim" + +msgctxt "alt. month" +msgid "November" +msgstr "Kasım" + +msgctxt "alt. month" +msgid "December" +msgstr "Aralık" + +msgid "This is not a valid IPv6 address." +msgstr "Bu, geçerli bir IPv6 adresi değil." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "ya da" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d yıl" +msgstr[1] "%(num)d yıl" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d ay" +msgstr[1] "%(num)d ay" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d hafta" +msgstr[1] "%(num)d hafta" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d gün" +msgstr[1] "%(num)d gün" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d saat" +msgstr[1] "%(num)d saat" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d dakika" +msgstr[1] "%(num)d dakika" + +msgid "Forbidden" +msgstr "Yasak" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF doğrulaması başarısız oldu. İstek iptal edildi." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Bu iletiyi görüyorsunuz çünkü bu HTTPS sitesi, web tarayıcınız tarafından " +"gönderilen “Referer üstbilgisi”ni gerektirir, ancak hiçbir şey gönderilmedi. " +"Bu üstbilgi güvenlik nedenleri için gerekir, tarayıcınızın üçüncü taraf " +"uygulamalar tarafından ele geçirilmediğinden emin olun." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Eğer tarayıcınızı “Referer” üstbilgilerini etkisizleştirmek için " +"yapılandırdıysanız, lütfen bunları, en azından bu site ya da HTTPS " +"bağlantıları veya “aynı-kaynakta” olan istekler için yeniden etkinleştirin." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Eğer etiketi " +"kullanıyorsanız ya da “Referrer-Policy: no-referrer” üstbilgisini dahil " +"ediyorsanız, lütfen bunları kaldırın. CSRF koruması, katı göndereni denetimi " +"yapmak için “Referer” üstbilgisi gerektirir. Gizlilik konusunda endişeniz " +"varsa, üçüncü taraf sitelere bağlantılar için gibi " +"alternatifler kullanın." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Bu iletiyi görüyorsunuz çünkü bu site, formları gönderdiğinizde bir CSRF " +"tanımlama bilgisini gerektirir. Bu tanımlama bilgisi güvenlik nedenleri için " +"gerekir, tarayıcınızın üçüncü taraf uygulamalar tarafından ele " +"geçirilmediğinden emin olun." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Eğer tarayıcınızı tanımlama bilgilerini etkisizleştirmek için " +"yapılandırdıysanız, lütfen bunları, en azından bu site ya da “aynı-kaynakta” " +"olan istekler için yeniden etkinleştirin." + +msgid "More information is available with DEBUG=True." +msgstr "Daha fazla bilgi DEBUG=True ayarı ile mevcut olur." + +msgid "No year specified" +msgstr "Yıl bilgisi belirtilmedi" + +msgid "Date out of range" +msgstr "Tarih aralık dışında" + +msgid "No month specified" +msgstr "Ay bilgisi belirtilmedi" + +msgid "No day specified" +msgstr "Gün bilgisi belirtilmedi" + +msgid "No week specified" +msgstr "Hafta bilgisi belirtilmedi" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Mevcut %(verbose_name_plural)s yok" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Gelecek %(verbose_name_plural)s mevcut değil, çünkü %(class_name)s." +"allow_future değeri False olarak tanımlı." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "Geçersiz tarih dizgisi “%(datestr)s” verilen biçim “%(format)s”" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Sorguyla eşleşen hiç %(verbose_name)s bulunamadı" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Sayfa “sonuncu” değil, ya da bir tamsayıya dönüştürülemez." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Geçersiz sayfa (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Liste boş ve “%(class_name)s.allow_empty” değeri False." + +msgid "Directory indexes are not allowed here." +msgstr "Dizin indekslerine burada izin verilmiyor." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "“%(path)s” mevcut değil" + +#, python-format +msgid "Index of %(directory)s" +msgstr "%(directory)s indeksi" + +msgid "The install worked successfully! Congratulations!" +msgstr "Yükleme başarılı olarak çalıştı! Tebrikler!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Django %(version)s sürümü için yayım notlarını göster" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Bu sayfayı görüyorsunuz çünkü DEBUG=True parametresi ayarlar dosyanızın içindedir ve " +"herhangi bir URL yapılandırmadınız." + +msgid "Django Documentation" +msgstr "Django Belgeleri" + +msgid "Topics, references, & how-to’s" +msgstr "Konular, kaynaklar ve nasıl yapılırlar" + +msgid "Tutorial: A Polling App" +msgstr "Eğitim: Anket Uygulaması" + +msgid "Get started with Django" +msgstr "Django ile başlayın" + +msgid "Django Community" +msgstr "Django Topluluğu" + +msgid "Connect, get help, or contribute" +msgstr "Bağlanın, yardım alın, ya da katkıda bulunun" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tr/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tr/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tr/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tr/formats.py new file mode 100644 index 0000000..806f442 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tr/formats.py @@ -0,0 +1,30 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "d F Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = "d F Y H:i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "d F" +SHORT_DATE_FORMAT = "d M Y" +SHORT_DATETIME_FORMAT = "d M Y H:i" +FIRST_DAY_OF_WEEK = 1 # Pazartesi + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d/%m/%Y", # '25/10/2006' + "%d/%m/%y", # '25/10/06' + "%y-%m-%d", # '06-10-25' + # "%d %B %Y", # '25 Ekim 2006' + # "%d %b. %Y", # '25 Eki. 2006' +] +DATETIME_INPUT_FORMATS = [ + "%d/%m/%Y %H:%M:%S", # '25/10/2006 14:30:59' + "%d/%m/%Y %H:%M:%S.%f", # '25/10/2006 14:30:59.000200' + "%d/%m/%Y %H:%M", # '25/10/2006 14:30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..843b012 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tt/LC_MESSAGES/django.po new file mode 100644 index 0000000..84d06ef --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/tt/LC_MESSAGES/django.po @@ -0,0 +1,1211 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Azat Khasanshin , 2011 +# v_ildar , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Tatar (http://www.transifex.com/django/django/language/tt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tt\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Afrikaans" +msgstr "" + +msgid "Arabic" +msgstr "Гарәп теле" + +msgid "Asturian" +msgstr "" + +msgid "Azerbaijani" +msgstr "Азәрбайҗан" + +msgid "Bulgarian" +msgstr "Болгар теле" + +msgid "Belarusian" +msgstr "" + +msgid "Bengali" +msgstr "Бенгалия теле" + +msgid "Breton" +msgstr "" + +msgid "Bosnian" +msgstr "Босния теле" + +msgid "Catalan" +msgstr "Каталан теле" + +msgid "Czech" +msgstr "Чех теле" + +msgid "Welsh" +msgstr "Уэльс теле" + +msgid "Danish" +msgstr "Дания теле" + +msgid "German" +msgstr "Алман теле" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "Грек теле" + +msgid "English" +msgstr "Инглиз теле" + +msgid "Australian English" +msgstr "" + +msgid "British English" +msgstr "Британ инглиз теле" + +msgid "Esperanto" +msgstr "Эсперанто теле" + +msgid "Spanish" +msgstr "Испан теле" + +msgid "Argentinian Spanish" +msgstr "Аргентина испан теле" + +msgid "Colombian Spanish" +msgstr "" + +msgid "Mexican Spanish" +msgstr "Мексикалы испан" + +msgid "Nicaraguan Spanish" +msgstr "Никарагуалы испан" + +msgid "Venezuelan Spanish" +msgstr "" + +msgid "Estonian" +msgstr "Эстон теле" + +msgid "Basque" +msgstr "Баск теле" + +msgid "Persian" +msgstr "Фарсы теле" + +msgid "Finnish" +msgstr "Финн теле" + +msgid "French" +msgstr "Француз теле" + +msgid "Frisian" +msgstr "Фриз теле" + +msgid "Irish" +msgstr "Ирланд теле" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "Галлий теле" + +msgid "Hebrew" +msgstr "Яһүд теле" + +msgid "Hindi" +msgstr "Хинд теле" + +msgid "Croatian" +msgstr "Хорват теле" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "Венгр теле" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "" + +msgid "Indonesian" +msgstr "Индонезия теле" + +msgid "Ido" +msgstr "" + +msgid "Icelandic" +msgstr "Исланд теле" + +msgid "Italian" +msgstr "Итальян теле" + +msgid "Japanese" +msgstr "Япон теле" + +msgid "Georgian" +msgstr "Грузин теле" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "Казах теле" + +msgid "Khmer" +msgstr "Кхмер теле" + +msgid "Kannada" +msgstr "Каннада теле" + +msgid "Korean" +msgstr "Корея теле" + +msgid "Luxembourgish" +msgstr "Люксембург теле" + +msgid "Lithuanian" +msgstr "Литвалылар теле" + +msgid "Latvian" +msgstr "Латвия теле" + +msgid "Macedonian" +msgstr "Македон теле" + +msgid "Malayalam" +msgstr "Малаялам теле" + +msgid "Mongolian" +msgstr "Монгол теле" + +msgid "Marathi" +msgstr "" + +msgid "Burmese" +msgstr "" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "" + +msgid "Dutch" +msgstr "Голланд теле" + +msgid "Norwegian Nynorsk" +msgstr "Норвегиялеләр (Нюнорск) теле" + +msgid "Ossetic" +msgstr "" + +msgid "Punjabi" +msgstr "Паджаби теле" + +msgid "Polish" +msgstr "Поляк теле" + +msgid "Portuguese" +msgstr "Португал теле" + +msgid "Brazilian Portuguese" +msgstr "Бразилия португал теле" + +msgid "Romanian" +msgstr "Румын теле" + +msgid "Russian" +msgstr "Рус теле" + +msgid "Slovak" +msgstr "Словак теле" + +msgid "Slovenian" +msgstr "Словен теле" + +msgid "Albanian" +msgstr "Албан теле" + +msgid "Serbian" +msgstr "Серб теле" + +msgid "Serbian Latin" +msgstr "Серб теле (латин алфавиты)" + +msgid "Swedish" +msgstr "Швед теле" + +msgid "Swahili" +msgstr "" + +msgid "Tamil" +msgstr "Тамиль теле" + +msgid "Telugu" +msgstr "Телугу теле" + +msgid "Thai" +msgstr "Тай теле" + +msgid "Turkish" +msgstr "Төрек теле" + +msgid "Tatar" +msgstr "Татар теле" + +msgid "Udmurt" +msgstr "" + +msgid "Ukrainian" +msgstr "Украин теле" + +msgid "Urdu" +msgstr "Урду" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "Вьетнам теле" + +msgid "Simplified Chinese" +msgstr "Гадиләштерелгән кытай теле" + +msgid "Traditional Chinese" +msgstr "Традицион кытай теле" + +msgid "Messages" +msgstr "" + +msgid "Site Maps" +msgstr "" + +msgid "Static Files" +msgstr "" + +msgid "Syndication" +msgstr "" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "Дөрес кыйммәтне кертегез." + +msgid "Enter a valid URL." +msgstr "Рөхсәт ителгән URLны кертегез." + +msgid "Enter a valid integer." +msgstr "" + +msgid "Enter a valid email address." +msgstr "Дөрес эл. почта адресны кертегез." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Рөхсәт ителгән IPv4 адресын кертегез." + +msgid "Enter a valid IPv6 address." +msgstr "" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "" + +msgid "Enter only digits separated by commas." +msgstr "Өтерләр белән бүленгән сан билгеләрен кертегез" + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Бу кыйммәтнең %(limit_value)s булуын тикшерегез (хәзер ул - %(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" +"Бу кыйммәтнең %(limit_value)s карата кечерәк яки тигез булуын тикшерегез." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" +"Бу кыйммәтнең %(limit_value)s карата зуррак яки тигез булуын тикшерегез." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" + +msgid "Enter a number." +msgstr "Сан кертегез." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "һәм" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "Бу кырның кыйммәте NULL булырга тиеш түгел." + +msgid "This field cannot be blank." +msgstr "Бу кыр буш булырга тиеш түгел." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "Мондый %(field_label)s белән булган %(model_name)s инде бар." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "%(field_type)s типтагы кыр" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "Логик (True яисә False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Юл (күп дигәндә %(max_length)s)" + +msgid "Comma-separated integers" +msgstr "Өтерләр белән бүленгән бөтен саннар" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "Дата (вакыт күрсәтмәсе булмаган)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Дата (вакыт күрсәтмәсе белән)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Унарлы вакланма" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "" + +msgid "Email address" +msgstr "Эл. почта" + +msgid "File path" +msgstr "Файл юлы" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "Күчерелүчән өтер белән булган сан" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "Бөтен сан" + +msgid "Big (8 byte) integer" +msgstr "Зур бөтен (8 байт)" + +msgid "IPv4 address" +msgstr "" + +msgid "IP address" +msgstr "IP-адрес" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "Логик (True, False я None)" + +msgid "Positive integer" +msgstr "" + +msgid "Positive small integer" +msgstr "" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "" + +msgid "Small integer" +msgstr "" + +msgid "Text" +msgstr "Текст" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Вакыт" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "" + +msgid "Image" +msgstr "" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "Тыш ачкыч (тип бәйле кыр буенча билгеләнгән)" + +msgid "One-to-one relationship" +msgstr "\"Бергә бер\" элемтәсе" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "\"Күпкә куп\" элемтәсе" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr "" + +msgid "This field is required." +msgstr "Мәҗбүри кыр." + +msgid "Enter a whole number." +msgstr "Бөтен сан кертегез." + +msgid "Enter a valid date." +msgstr "Рөхсәт ителгән датаны кертегез." + +msgid "Enter a valid time." +msgstr "Рөхсәт ителгән вакытны кертегез." + +msgid "Enter a valid date/time." +msgstr "Рөхсәт ителгән дата һәм вакытны кертегез." + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Һишбер файл җибәрелмәгән. Форма кодлавын тикшерегез." + +msgid "No file was submitted." +msgstr "Һишбер файл җибәрелмәгән." + +msgid "The submitted file is empty." +msgstr "Җибәрелгән файл буш." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Зинһар, җибәрегез файлны яисә бушайту байракчасын билгеләгез, икесен бергә " +"түгел." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Рөхсәт ителгән рәсемне йөкләгез. Сез йөкләгән файл рәсем түгел яисә бозылган." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Дөрес тәкъдимне сайлагыз. Рөхсәт ителгән кыйммәтләр арасында %(value)s юк. " + +msgid "Enter a list of values." +msgstr "Кыйммәтләр исемлеген кертегез." + +msgid "Enter a complete value." +msgstr "" + +msgid "Enter a valid UUID." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr "" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" + +msgid "Order" +msgstr "Тәртип" + +msgid "Delete" +msgstr "Бетерергә" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Зинһар, %(field)s кырындагы кабатлана торган кыйммәтне төзәтегез." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Зинһар, %(field)s кырындагы кыйммәтне төзәтегез, ул уникаль булырга тиеш." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Зинһар, %(field_name)s кырындагы кыйммәтне төзәтегез, ул %(date_field)s " +"кырындагы %(lookup)s өчен уникаль булырга тиеш." + +msgid "Please correct the duplicate values below." +msgstr "Зинһар, астагы кабатлана торган кыйммәтләрне төзәтегез." + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Дөрес тәкъдимне сайлагыз. Рөхсәт ителгән кыйммәтләр арасында сезнең вариант " +"юк." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Бушайтырга" + +msgid "Currently" +msgstr "Хәзерге вакытта" + +msgid "Change" +msgstr "Үзгәртергә" + +msgid "Unknown" +msgstr "Билгесез" + +msgid "Yes" +msgstr "Әйе" + +msgid "No" +msgstr "Юк" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "әйе,юк,бәлки" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d байт" + +#, python-format +msgid "%s KB" +msgstr "%s КБ" + +#, python-format +msgid "%s MB" +msgstr "%s МБ" + +#, python-format +msgid "%s GB" +msgstr "%s ГБ" + +#, python-format +msgid "%s TB" +msgstr "%s ТБ" + +#, python-format +msgid "%s PB" +msgstr "%s ПБ" + +msgid "p.m." +msgstr "т.с." + +msgid "a.m." +msgstr "т.к." + +msgid "PM" +msgstr "ТС" + +msgid "AM" +msgstr "ТК" + +msgid "midnight" +msgstr "төн уртасы" + +msgid "noon" +msgstr "көн уртасы" + +msgid "Monday" +msgstr "Дүшәмбе" + +msgid "Tuesday" +msgstr "Сишәмбе" + +msgid "Wednesday" +msgstr "Чәршәмбе" + +msgid "Thursday" +msgstr "Пәнҗешәмбе" + +msgid "Friday" +msgstr "Җомга" + +msgid "Saturday" +msgstr "Шимбә" + +msgid "Sunday" +msgstr "Якшәмбе" + +msgid "Mon" +msgstr "Дүш" + +msgid "Tue" +msgstr "Сиш" + +msgid "Wed" +msgstr "Чәр" + +msgid "Thu" +msgstr "Пнҗ" + +msgid "Fri" +msgstr "Җом" + +msgid "Sat" +msgstr "Шим" + +msgid "Sun" +msgstr "Якш" + +msgid "January" +msgstr "Гыйнвар" + +msgid "February" +msgstr "Февраль" + +msgid "March" +msgstr "Март" + +msgid "April" +msgstr "Апрель" + +msgid "May" +msgstr "Май" + +msgid "June" +msgstr "Июнь" + +msgid "July" +msgstr "Июль" + +msgid "August" +msgstr "Август" + +msgid "September" +msgstr "Сентябрь" + +msgid "October" +msgstr "Октябрь" + +msgid "November" +msgstr "Ноябрь" + +msgid "December" +msgstr "Декабрь" + +msgid "jan" +msgstr "гый" + +msgid "feb" +msgstr "фев" + +msgid "mar" +msgstr "мар" + +msgid "apr" +msgstr "апр" + +msgid "may" +msgstr "май" + +msgid "jun" +msgstr "июн" + +msgid "jul" +msgstr "июл" + +msgid "aug" +msgstr "авг" + +msgid "sep" +msgstr "сен" + +msgid "oct" +msgstr "окт" + +msgid "nov" +msgstr "ноя" + +msgid "dec" +msgstr "дек" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Гый." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Фев." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Март" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Апрель" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Май" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Июнь" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Июль" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Авг." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Сен." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Окт." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Ноя." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Дек." + +msgctxt "alt. month" +msgid "January" +msgstr "гыйнвар" + +msgctxt "alt. month" +msgid "February" +msgstr "февраль" + +msgctxt "alt. month" +msgid "March" +msgstr "март" + +msgctxt "alt. month" +msgid "April" +msgstr "апрель" + +msgctxt "alt. month" +msgid "May" +msgstr "май" + +msgctxt "alt. month" +msgid "June" +msgstr "июнь" + +msgctxt "alt. month" +msgid "July" +msgstr "июль" + +msgctxt "alt. month" +msgid "August" +msgstr "август" + +msgctxt "alt. month" +msgid "September" +msgstr "сентябрь" + +msgctxt "alt. month" +msgid "October" +msgstr "октябрь" + +msgctxt "alt. month" +msgid "November" +msgstr "ноябрь" + +msgctxt "alt. month" +msgid "December" +msgstr "декабрь" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "я" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "," + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" + +msgid "0 minutes" +msgstr "" + +msgid "Forbidden" +msgstr "" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "Ел билгеләнмәгән" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "Ай билгеләнмәгән" + +msgid "No day specified" +msgstr "Көн билгеләнмәгән" + +msgid "No week specified" +msgstr "Атна билгеләнмәгән" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Файдалана алырлык %(verbose_name_plural)s юк" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"%(class_name)s.allow_future False булуы сәбәпле, киләсе " +"%(verbose_name_plural)s файдалана алырлык түгел" + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Таләпкә туры килгән %(verbose_name)s табылмаган" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "" + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/udm/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/udm/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0c7ab6d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/udm/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/udm/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/udm/LC_MESSAGES/django.po new file mode 100644 index 0000000..68c2bc7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/udm/LC_MESSAGES/django.po @@ -0,0 +1,1197 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Udmurt (http://www.transifex.com/django/django/language/" +"udm/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: udm\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Afrikaans" +msgstr "Африкаанс" + +msgid "Arabic" +msgstr "Араб" + +msgid "Asturian" +msgstr "" + +msgid "Azerbaijani" +msgstr "Азербайджан" + +msgid "Bulgarian" +msgstr "Болгар" + +msgid "Belarusian" +msgstr "Беларус" + +msgid "Bengali" +msgstr "Бенгал" + +msgid "Breton" +msgstr "Бретон" + +msgid "Bosnian" +msgstr "Босниец" + +msgid "Catalan" +msgstr "Каталан" + +msgid "Czech" +msgstr "Чех" + +msgid "Welsh" +msgstr "Уэльс" + +msgid "Danish" +msgstr "Датчан" + +msgid "German" +msgstr "Немец" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "Грек" + +msgid "English" +msgstr "Англи" + +msgid "Australian English" +msgstr "" + +msgid "British English" +msgstr "Британиысь англи" + +msgid "Esperanto" +msgstr "Эсперанто" + +msgid "Spanish" +msgstr "Испан" + +msgid "Argentinian Spanish" +msgstr "Аргентинаысь испан" + +msgid "Colombian Spanish" +msgstr "" + +msgid "Mexican Spanish" +msgstr "Мексикаысь испан" + +msgid "Nicaraguan Spanish" +msgstr "Никарагуаысь испан" + +msgid "Venezuelan Spanish" +msgstr "Венесуэлаысь испан" + +msgid "Estonian" +msgstr "Эстон" + +msgid "Basque" +msgstr "Баск" + +msgid "Persian" +msgstr "Перс" + +msgid "Finnish" +msgstr "Финн" + +msgid "French" +msgstr "Француз" + +msgid "Frisian" +msgstr "Фриз" + +msgid "Irish" +msgstr "Ирланд" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "Галисий" + +msgid "Hebrew" +msgstr "Иврит" + +msgid "Hindi" +msgstr "Хинди" + +msgid "Croatian" +msgstr "Хорват" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "Венгер" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "Интерлингва" + +msgid "Indonesian" +msgstr "Индонези" + +msgid "Ido" +msgstr "" + +msgid "Icelandic" +msgstr "Исланд" + +msgid "Italian" +msgstr "Итальян" + +msgid "Japanese" +msgstr "Япон" + +msgid "Georgian" +msgstr "Грузин" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "Казах" + +msgid "Khmer" +msgstr "Кхмер" + +msgid "Kannada" +msgstr "Каннада" + +msgid "Korean" +msgstr "Корей" + +msgid "Luxembourgish" +msgstr "Люксембург" + +msgid "Lithuanian" +msgstr "Литва" + +msgid "Latvian" +msgstr "Латвий" + +msgid "Macedonian" +msgstr "Македон" + +msgid "Malayalam" +msgstr "Малаялам" + +msgid "Mongolian" +msgstr "Монгол" + +msgid "Marathi" +msgstr "" + +msgid "Burmese" +msgstr "" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "Непал" + +msgid "Dutch" +msgstr "Голланд" + +msgid "Norwegian Nynorsk" +msgstr "Норвег (нюнорск)" + +msgid "Ossetic" +msgstr "" + +msgid "Punjabi" +msgstr "Панджаби" + +msgid "Polish" +msgstr "Поляк" + +msgid "Portuguese" +msgstr "Португал" + +msgid "Brazilian Portuguese" +msgstr "Бразилиысь португал" + +msgid "Romanian" +msgstr "Румын" + +msgid "Russian" +msgstr "Ӟуч" + +msgid "Slovak" +msgstr "Словак" + +msgid "Slovenian" +msgstr "Словен" + +msgid "Albanian" +msgstr "Албан" + +msgid "Serbian" +msgstr "Серб" + +msgid "Serbian Latin" +msgstr "Серб (латиницаен)" + +msgid "Swedish" +msgstr "Швед" + +msgid "Swahili" +msgstr "Суахили" + +msgid "Tamil" +msgstr "Тамиль" + +msgid "Telugu" +msgstr "Телугу" + +msgid "Thai" +msgstr "Тай" + +msgid "Turkish" +msgstr "Турок" + +msgid "Tatar" +msgstr "Бигер" + +msgid "Udmurt" +msgstr "Удмурт" + +msgid "Ukrainian" +msgstr "Украин" + +msgid "Urdu" +msgstr "Урду" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "Вьетнам" + +msgid "Simplified Chinese" +msgstr "Китай (капчиятэм)" + +msgid "Traditional Chinese" +msgstr "Китай (традици)" + +msgid "Messages" +msgstr "" + +msgid "Site Maps" +msgstr "" + +msgid "Static Files" +msgstr "" + +msgid "Syndication" +msgstr "" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "Тазэ шонер гожтэ." + +msgid "Enter a valid URL." +msgstr "Шонер URL гожтэ." + +msgid "Enter a valid integer." +msgstr "" + +msgid "Enter a valid email address." +msgstr "Электорн почта адресэз шонер гожтэ" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Шонер IPv4-адрес гожтэ." + +msgid "Enter a valid IPv6 address." +msgstr "Шонер IPv6-адрес гожтэ." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Шонер IPv4 яке IPv6 адрес гожтэ." + +msgid "Enter only digits separated by commas." +msgstr "Запятойёсын висъям лыдпусъёсты гожтэ" + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Эскере, та %(limit_value)s шуыса. Али татын %(show_value)s." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Талы %(limit_value)s-лэсь бадӟымгес луыны уг яра." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Талы %(limit_value)s-лэсь ӧжытгес луыны уг яра." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" + +msgid "Enter a number." +msgstr "Лыд гожтэ." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "но" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "Та NULL луыны уг яра." + +msgid "This field cannot be blank." +msgstr "Та буш луыны уг яра." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "Таӵе %(field_label)s-ен %(model_name)s вань ини." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "%(field_type)s типъем бусы" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "True яке False" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Чур (%(max_length)s пусозь кузьда)" + +msgid "Comma-separated integers" +msgstr "Запятоен висъям быдэс лыдъёс" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "Дата (час-минут пусйытэк)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Дата но час-минут" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Десятичной лыд." + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "" + +msgid "Email address" +msgstr "Электрон почта адрес" + +msgid "File path" +msgstr "Файллэн нимыз" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "Вещественной лыд" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "целой" + +msgid "Big (8 byte) integer" +msgstr "Бадӟым (8 байтъем) целой лыд" + +msgid "IPv4 address" +msgstr "IPv4 адрес" + +msgid "IP address" +msgstr "IP адрес" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "True, False яке None" + +msgid "Positive integer" +msgstr "Целой, нольлэсь бадӟым лыд" + +msgid "Positive small integer" +msgstr "Нольлэсь бадӟым пичи целой лыд" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Компьютерной ним (%(max_length)s пусозь кузьда)" + +msgid "Small integer" +msgstr "Пичи целой лыд" + +msgid "Text" +msgstr "Текст" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Час-минут" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "Файл" + +msgid "Image" +msgstr "Суред" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "Мукет моделен герӟет (тип герӟано бусыя валамын)." + +msgid "One-to-one relationship" +msgstr "Одӥг-одӥг герӟет" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "Трос-трос герӟет" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr "" + +msgid "This field is required." +msgstr "Та клуэ." + +msgid "Enter a whole number." +msgstr "Целой лыд гожтэ." + +msgid "Enter a valid date." +msgstr "Шонер дата гожтэ." + +msgid "Enter a valid time." +msgstr "Шонер час-минут гожтэ." + +msgid "Enter a valid date/time." +msgstr "Шонер дата но час-минут гожтэ." + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Одӥг файл но лэзьымтэ. Формалэсь код." + +msgid "No file was submitted." +msgstr "Файл лэземын ӧвӧл." + +msgid "The submitted file is empty." +msgstr "Лэзем файл буш." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Файл лэзе яке файл ӵушоно шуыса пусъе, огдыръя соиз но, таиз но уг яра." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "Суред лэзе. Тӥляд файлды лэзьымтэ яке со суред ӧвӧл." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Шонер вариант быръе. %(value)s вариантъёс пӧлын ӧвӧл." + +msgid "Enter a list of values." +msgstr "Список лэзе." + +msgid "Enter a complete value." +msgstr "" + +msgid "Enter a valid UUID." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr "" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" + +msgid "Order" +msgstr "Рад" + +msgid "Delete" +msgstr "Ӵушоно" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "" + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" + +msgid "Please correct the duplicate values below." +msgstr "" + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Буш кароно" + +msgid "Currently" +msgstr "Али" + +msgid "Change" +msgstr "Тупатъяно" + +msgid "Unknown" +msgstr "Тодымтэ" + +msgid "Yes" +msgstr "Бен" + +msgid "No" +msgstr "Ӧвӧл" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "бен,ӧвӧл,уг тодӥськы" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d байт" + +#, python-format +msgid "%s KB" +msgstr "%s КБ" + +#, python-format +msgid "%s MB" +msgstr "%s МБ" + +#, python-format +msgid "%s GB" +msgstr "%s МБ" + +#, python-format +msgid "%s TB" +msgstr "%s ТБ" + +#, python-format +msgid "%s PB" +msgstr "%s ПБ" + +msgid "p.m." +msgstr "лымшор бере" + +msgid "a.m." +msgstr "лымшор азе" + +msgid "PM" +msgstr "лымшор бере" + +msgid "AM" +msgstr "лымшор азе" + +msgid "midnight" +msgstr "уйшор" + +msgid "noon" +msgstr "лымшор" + +msgid "Monday" +msgstr "Вордӥськон" + +msgid "Tuesday" +msgstr "Пуксён" + +msgid "Wednesday" +msgstr "Вирнунал" + +msgid "Thursday" +msgstr "Покчиарня" + +msgid "Friday" +msgstr "Удмуртарня" + +msgid "Saturday" +msgstr "Кӧснунал" + +msgid "Sunday" +msgstr "Арнянунал" + +msgid "Mon" +msgstr "врд" + +msgid "Tue" +msgstr "пкс" + +msgid "Wed" +msgstr "врн" + +msgid "Thu" +msgstr "пкч" + +msgid "Fri" +msgstr "удм" + +msgid "Sat" +msgstr "ксн" + +msgid "Sun" +msgstr "арн" + +msgid "January" +msgstr "толшор" + +msgid "February" +msgstr "тулыспал" + +msgid "March" +msgstr "южтолэзь" + +msgid "April" +msgstr "оштолэзь" + +msgid "May" +msgstr "куартолэзь" + +msgid "June" +msgstr "инвожо" + +msgid "July" +msgstr "пӧсьтолэзь" + +msgid "August" +msgstr "гудырикошкон" + +msgid "September" +msgstr "куарусён" + +msgid "October" +msgstr "коньывуон" + +msgid "November" +msgstr "шуркынмон" + +msgid "December" +msgstr "толсур" + +msgid "jan" +msgstr "тшт" + +msgid "feb" +msgstr "тпт" + +msgid "mar" +msgstr "южт" + +msgid "apr" +msgstr "ошт" + +msgid "may" +msgstr "крт" + +msgid "jun" +msgstr "ивт" + +msgid "jul" +msgstr "пст" + +msgid "aug" +msgstr "гкт" + +msgid "sep" +msgstr "кут" + +msgid "oct" +msgstr "квт" + +msgid "nov" +msgstr "шкт" + +msgid "dec" +msgstr "тст" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "тшт" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "тпт" + +msgctxt "abbrev. month" +msgid "March" +msgstr "южт" + +msgctxt "abbrev. month" +msgid "April" +msgstr "ошт" + +msgctxt "abbrev. month" +msgid "May" +msgstr "крт" + +msgctxt "abbrev. month" +msgid "June" +msgstr "ивт" + +msgctxt "abbrev. month" +msgid "July" +msgstr "пст" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "гкт" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "кут" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "квт" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "шкт" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "тст" + +msgctxt "alt. month" +msgid "January" +msgstr "толшоре" + +msgctxt "alt. month" +msgid "February" +msgstr "тулыспалэ" + +msgctxt "alt. month" +msgid "March" +msgstr "южтолэзе" + +msgctxt "alt. month" +msgid "April" +msgstr "оштолэзе" + +msgctxt "alt. month" +msgid "May" +msgstr "куартолэзе" + +msgctxt "alt. month" +msgid "June" +msgstr "инвожое" + +msgctxt "alt. month" +msgid "July" +msgstr "пӧсьтолэзе" + +msgctxt "alt. month" +msgid "August" +msgstr "гудырикошконэ" + +msgctxt "alt. month" +msgid "September" +msgstr "куарусёнэ" + +msgctxt "alt. month" +msgid "October" +msgstr "коньывуонэ" + +msgctxt "alt. month" +msgid "November" +msgstr "шуркынмонэ" + +msgctxt "alt. month" +msgid "December" +msgstr "толсуре" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "яке" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "," + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" + +msgid "0 minutes" +msgstr "" + +msgid "Forbidden" +msgstr "" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "" + +msgid "No day specified" +msgstr "" + +msgid "No week specified" +msgstr "" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Папкаослэсь пуштроссэс татын учкыны уг яра." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "%(directory)s папкалэн пушторсэз" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ug/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ug/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4b9aed3 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ug/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ug/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ug/LC_MESSAGES/django.po new file mode 100644 index 0000000..ccaf4da --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ug/LC_MESSAGES/django.po @@ -0,0 +1,1346 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# abdl erkin <84247764@qq.com>, 2018 +# Abduqadir Abliz , 2023 +# Abduqadir Abliz , 2023 +# Azat, 2023 +# Murat Orhun , 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 06:49+0000\n" +"Last-Translator: Abduqadir Abliz , 2023\n" +"Language-Team: Uyghur (http://app.transifex.com/django/django/language/ug/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ug\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "ئافرىكانسچە" + +msgid "Arabic" +msgstr "ئەرەبچە" + +msgid "Algerian Arabic" +msgstr "ئالجىرىيە ئەرەپچىسى" + +msgid "Asturian" +msgstr "ئاستۇرىچە" + +msgid "Azerbaijani" +msgstr "ئەزەربەيجانچە" + +msgid "Bulgarian" +msgstr "بۇلغارچە" + +msgid "Belarusian" +msgstr "بېلورۇسىچە" + +msgid "Bengali" +msgstr "بېنگالچە" + +msgid "Breton" +msgstr "بىرېتونچە" + +msgid "Bosnian" +msgstr "بوسنىيەچە" + +msgid "Catalan" +msgstr "كاتالانچە" + +msgid "Central Kurdish (Sorani)" +msgstr "مەركىزى كۇردچە ( سورانى) " + +msgid "Czech" +msgstr "چېخچە" + +msgid "Welsh" +msgstr "ۋېلشچە" + +msgid "Danish" +msgstr "دانىشچە" + +msgid "German" +msgstr "گىرمانچە" + +msgid "Lower Sorbian" +msgstr "تۆۋەن سوربچە" + +msgid "Greek" +msgstr "گىرېكچە" + +msgid "English" +msgstr "ئىنگلىزچە" + +msgid "Australian English" +msgstr "" +"ئاۋىستىرالىيە ئىنگلزچىسى\n" +" " + +msgid "British English" +msgstr "ئەنگىلىيە ئىنگىلىزچىسى" + +msgid "Esperanto" +msgstr "دۇنيا تىلى" + +msgid "Spanish" +msgstr "ئىسپانچە" + +msgid "Argentinian Spanish" +msgstr "ئارگېنتىنا ئىسپانچىسى" + +msgid "Colombian Spanish" +msgstr "كولۇمبىيە ئىسپانچىسى" + +msgid "Mexican Spanish" +msgstr "مېكسىكا ئىسپانچىسى" + +msgid "Nicaraguan Spanish" +msgstr "نىكاراگۇئا ئىسپاچىسى" + +msgid "Venezuelan Spanish" +msgstr "ۋېنېزۇئېلا ئىسپانچىسى" + +msgid "Estonian" +msgstr "ئېستونىيەچە" + +msgid "Basque" +msgstr "بەسىكچە" + +msgid "Persian" +msgstr "پارىسچە" + +msgid "Finnish" +msgstr "ڧىنلانىدچە" + +msgid "French" +msgstr "ڧىرانسۇزچە" + +msgid "Frisian" +msgstr "فىرىزىيەچە" + +msgid "Irish" +msgstr "ئىرېلاندىيەچە" + +msgid "Scottish Gaelic" +msgstr "شوتلاندىيەچە" + +msgid "Galician" +msgstr "گالىچىيەچە" + +msgid "Hebrew" +msgstr "ئىبرانىچە" + +msgid "Hindi" +msgstr "ھىندىچە" + +msgid "Croatian" +msgstr "كىرودىيەچە" + +msgid "Upper Sorbian" +msgstr "يۇقىرى سوربچە" + +msgid "Hungarian" +msgstr "ماجارچە" + +msgid "Armenian" +msgstr "ئارمىنىيەچە" + +msgid "Interlingua" +msgstr "خەلقئارالىق تىل" + +msgid "Indonesian" +msgstr "ھىندىنوزىيەچە" + +msgid "Igbo" +msgstr "ئىبوچە" + +msgid "Ido" +msgstr "ئىيدوچە" + +msgid "Icelandic" +msgstr "ئىسلاندىيەچە" + +msgid "Italian" +msgstr "ئىتالىيەچە" + +msgid "Japanese" +msgstr "ياپونچە" + +msgid "Georgian" +msgstr "گرۇزىيەچە" + +msgid "Kabyle" +msgstr "كەبىيلچە" + +msgid "Kazakh" +msgstr "قازاقچە" + +msgid "Khmer" +msgstr "كامىيرچە" + +msgid "Kannada" +msgstr "كانناداچە" + +msgid "Korean" +msgstr "كورىيەچە" + +msgid "Kyrgyz" +msgstr "قىرغىزچە" + +msgid "Luxembourgish" +msgstr "لىيۇكسېمبۇرگچە" + +msgid "Lithuanian" +msgstr "لىتۋاچە" + +msgid "Latvian" +msgstr "لاتۋىيەچە" + +msgid "Macedonian" +msgstr "ماكېدونىيەچە" + +msgid "Malayalam" +msgstr "مالىيالامچە" + +msgid "Mongolian" +msgstr "مۇڭغۇلچە" + +msgid "Marathi" +msgstr "ماراتىچە" + +msgid "Malay" +msgstr "مالايچە" + +msgid "Burmese" +msgstr "بېرمىچە" + +msgid "Norwegian Bokmål" +msgstr "نورۋېگىيە بوكمىلچىسى" + +msgid "Nepali" +msgstr "نېپالچە" + +msgid "Dutch" +msgstr "گوللاندىيەچە" + +msgid "Norwegian Nynorsk" +msgstr "نورۋېگىيە نىنورسكچىسى" + +msgid "Ossetic" +msgstr "ئوسېتچە" + +msgid "Punjabi" +msgstr "پۇنجابىچە" + +msgid "Polish" +msgstr "پولشاچە" + +msgid "Portuguese" +msgstr "پورتۇگالچە" + +msgid "Brazilian Portuguese" +msgstr "بىرازىلىيە پورتۇگالچىسى" + +msgid "Romanian" +msgstr "رومەينىيەچە" + +msgid "Russian" +msgstr "رۇسچە" + +msgid "Slovak" +msgstr "سلوۋاكىيەچە" + +msgid "Slovenian" +msgstr "سىلوۋېنىيەچە" + +msgid "Albanian" +msgstr "ئالبانىيەچە" + +msgid "Serbian" +msgstr "سېربىيەچە" + +msgid "Serbian Latin" +msgstr "سېربىيە لاتىنچىسى" + +msgid "Swedish" +msgstr "شىۋىتسىيەچە" + +msgid "Swahili" +msgstr "سۋاھىلچە" + +msgid "Tamil" +msgstr "تامىلچە" + +msgid "Telugu" +msgstr "تېلۇگۇ" + +msgid "Tajik" +msgstr "تاجىكچە" + +msgid "Thai" +msgstr "تايلاندچە" + +msgid "Turkmen" +msgstr "تۈركمەنچە" + +msgid "Turkish" +msgstr "تۈركچە" + +msgid "Tatar" +msgstr "تاتارچە" + +msgid "Udmurt" +msgstr "ئۇدمۇرتچە" + +msgid "Uyghur" +msgstr "ئۇيغۇرچە" + +msgid "Ukrainian" +msgstr "ئۇكرائىنچە" + +msgid "Urdu" +msgstr "ئوردۇچە" + +msgid "Uzbek" +msgstr "ئۆزبەكچە" + +msgid "Vietnamese" +msgstr "ۋېيتنامچە" + +msgid "Simplified Chinese" +msgstr "خەنزۇچە" + +msgid "Traditional Chinese" +msgstr "ئەنئەنىۋى خەنزۇچىسى" + +msgid "Messages" +msgstr "قىسقا ئۇچۇر" + +msgid "Site Maps" +msgstr "بېكەت خەرىتىسى" + +msgid "Static Files" +msgstr "سىتاتىك ھۆججەت" + +msgid "Syndication" +msgstr "تەشكىللىنىش" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "بەت نومۇرى پۈتۈن سان ئەمەس" + +msgid "That page number is less than 1" +msgstr "بەت نومۇرى 1 دىن كىچىك" + +msgid "That page contains no results" +msgstr "ئۇ بەتتە ھېچقانداق نەتىجە يوق" + +msgid "Enter a valid value." +msgstr "بىر ئىناۋەتلىك قىممەتنى تولدۇرۇڭ" + +msgid "Enter a valid URL." +msgstr "ئىناۋەتلىك URL نى تولدۇرۇڭ" + +msgid "Enter a valid integer." +msgstr "ئىناۋەتلىك پۈتۈن سان تولدۇرۇڭ" + +msgid "Enter a valid email address." +msgstr "ئىناۋەتلىك ئېلخەت ئادرېسىنى كىرگۈزۈڭ." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"ھەرپ ، سان ، ئاستى سىزىق ياكى سىزىقچىلاردىن تەركىب تاپقان ئۈنۈملۈك «سىلاگ» " +"نى كىرگۈزۈڭ." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"يۇنىكودلۇق ھەرپ، سان، ئاستى سىزىق ياكى سىزىقچىلاردىن تەركىب تاپقان ئۈنۈملۈك " +"«slug» نى كىرگۈزۈڭ." + +msgid "Enter a valid IPv4 address." +msgstr "ئىناۋەتلىك IPv4 ئادرېسىنى كىرگۈزۈڭ." + +msgid "Enter a valid IPv6 address." +msgstr "ئىناۋەتلىك IPv6 ئادرېسىنى كىرگۈزۈڭ." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "ئىناۋەتلىك IPv4 ياكى IPv6 ئادرېسىنى كىرگۈزۈڭ." + +msgid "Enter only digits separated by commas." +msgstr "پەش ئارقىلىق ئايرىلغان رەقەملەرنىلا كىرگۈزۈڭ." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"بۇ قىممەتنىڭ %(limit_value)s بولىشىغا كاپالەتلىك قىلىڭ ( ھازىر " +"%(show_value)s)" + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" +"بۇ قىممەتنىڭ %(limit_value)s دىن تۆۋەن ياكى تەڭ بولۇشىغا كاپالەتلىك قىلىڭ" + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" +"بۇ قىممەتنىڭ %(limit_value)s دىن چوڭ ياكى تەڭ بولۇشىغا كاپالەتلىك قىلىڭ" + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "بۇ قىممەتنىڭ %(limit_value)s نىڭ كۆپەيتمىسى بولىشىغا كاپالەتلىك قىلىڭ" + +#, python-format +msgid "" +"Ensure this value is a multiple of step size %(limit_value)s, starting from " +"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on." +msgstr "" +"بۇ قىممەت كۆپ قەدەم باسقۇچلۇق بولسۇن %(limit_value)s، %(offset)s دىن " +"باشلىنىپ، مەسىلەن %(offset)s، %(valid_value1)s، %(valid_value2)s ۋە باشقىلار." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"بۇ قىممەتنىڭ كەم دېگەندە %(limit_value)d ھەرپ بولۇشىغا كاپالەتلىك قىلىڭ " +"(ھازىر %(show_value)d بار)." +msgstr[1] "" +"بۇ قىممەتنىڭ كەم دېگەندە %(limit_value)d ھەرپ بولۇشىغا كاپالەتلىك قىلىڭ " +"(ھازىر %(show_value)d بار)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"بۇ قىممەتنىڭ ئەڭ كۆپ بولغاندا %(limit_value)d ھەرپ بولۇشىغا كاپالەتلىك قىلىڭ " +"(ھازىر %(show_value)d بار)." +msgstr[1] "" +"بۇ قىممەتنىڭ ئەڭ كۆپ بولغاندا %(limit_value)d ھەرپ بولۇشىغا كاپالەتلىك قىلىڭ " +"(ئۇنىڭدا %(show_value)d بار). " + +msgid "Enter a number." +msgstr "سان كىرگۈزۈڭ." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "جەمى 4%(max)s خانىدىن ئېشىپ كەتمەسلىكىگە كاپالەتلىك قىلىڭ." +msgstr[1] "جەمى %(max)s خانىدىن ئېشىپ كەتمەسلىكىگە كاپالەتلىك قىلىڭ." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "%(max)s ئونلۇق ئورۇندىن ئېشىپ كەتمەسلىكىگە كاپالەتلىك قىلىڭ." +msgstr[1] "%(max)s ئونلۇق ئورۇندىن ئېشىپ كەتمەسلىكىگە كاپالەتلىك قىلىڭ." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"ئونلۇق نۇقتىدىن ئىلگىرى %(max)s خانىدىن ئېشىپ كەتمەسلىكىگە كاپالەتلىك قىلىڭ." +msgstr[1] "" +"ئونلۇق نۇقتىدىن ئىلگىرى %(max)s خانىدىن ئېشىپ كەتمەسلىكىگە كاپالەتلىك قىلىڭ." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"ھۆججەت كېڭەيتىشكە «%(extension)s» رۇخسەت قىلىنمايدۇ. رۇخسەت قىلىنغان " +"كېڭەيتىلمە: %(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "بوش ھەرپلەرگە رۇخسەت قىلىنمايدۇ." + +msgid "and" +msgstr "ۋە" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s بىلەن بۇ %(field_labels)s مەۋجۇت." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "«%(name)s» چەكلىمىسى بۇزۇلدى." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "قىممەت %(value)r ئىناۋەتسىز." + +msgid "This field cannot be null." +msgstr "بۇ ئورۇننى بوش قويۇشقا بولمايدۇ" + +msgid "This field cannot be blank." +msgstr "بۇ ئورۇننى بوش قويۇشقا بولمايدۇ" + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "بۇ %(field_label)s بىلەن %(model_name)s مەۋجۇت." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s چوقۇم %(date_field_label)s %(lookup_type)s ئۈچۈن بىردىنبىر " +"بولۇشى كېرەك." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "تىپ تۈرى: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "«%(value)s» قىممىتى چوقۇم True ياكى False بولۇشى كېرەك." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "«%(value)s» قىممىتى چوقۇم True ، False ياكى None بولۇشى كېرەك." + +msgid "Boolean (Either True or False)" +msgstr "Boolean (True ياكى False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "(%(max_length)s گە قەدەر ئۇزۇنلۇقتىكى) ھەرپ-بەلگە" + +msgid "String (unlimited)" +msgstr "ھەرپ-بەلگە ( ئۇزۇنلۇققا چەكلىمە يوق)" + +msgid "Comma-separated integers" +msgstr "پەش بىلەن ئايرىلغان پۈتۈن سان" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"«%(value)s» قىممىتى ئىناۋەتسىز ۋاقىت فورماتىدا. ئۇ چوقۇم YYYY-MM-DD شەكلىدە " +"بولۇشى كېرەك." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"«%(value)s» قىممىتىنىڭ توغرا فورماتى (YYYY-MM-DD) بار ، ئەمما ئۇ ۋاقىت " +"ئىناۋەتسىز." + +msgid "Date (without time)" +msgstr "چېسلا (سائەت مىنۇت يوق)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"«%(value)s» قىممىتى ئىناۋەتسىز. ئۇ چوقۇم YYYY-MM-DD HH: MM [: ss [.uuuuuu]] " +"[TZ] شەكلىدە بولۇشى كېرەك." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"«%(value)s» قىممىتىنىڭ توغرا فورماتى بار (YYYY-MM-DD HH: MM [: ss [.uuuuuu]] " +"[TZ]) ئەمما ئۇ ئىناۋەتسىز كۈن / ۋاقىت." + +msgid "Date (with time)" +msgstr "چېسلا (ۋاقىت بىلەن)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "«%(value)s» قىممىتى چوقۇم پۈتۈن سان بولۇشى كېرەك." + +msgid "Decimal number" +msgstr "ئونلۇق سان" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"«%(value)s» قىممىتى ئىناۋەتسىز. ئۇ چوقۇم [DD] [[HH:] MM:] ss [.uuuuuu] " +"شەكلىدە بولۇشى كېرەك." + +msgid "Duration" +msgstr "داۋاملىشىش ۋاقتى" + +msgid "Email address" +msgstr "ئېلخەت ئادرېسى" + +msgid "File path" +msgstr "ھۆججەت يولى" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "«%(value)s» قىممىتى چوقۇم لەيلىمە چېكىتلىك مىقتار بولۇشى كېرەك." + +msgid "Floating point number" +msgstr "كەسرىلىك سان نومۇر" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "«%(value)s» قىممىتى چوقۇم پۈتۈن سان بولۇشى كېرەك." + +msgid "Integer" +msgstr "پۈتۈن سان" + +msgid "Big (8 byte) integer" +msgstr "چوڭ (8 بايىت) پۈتۈن سان" + +msgid "Small integer" +msgstr "كىچىك پۈتۈن سان" + +msgid "IPv4 address" +msgstr "IPv4 ئادرېسى" + +msgid "IP address" +msgstr "IP ئادرېسى" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "«%(value)s» قىممىتى چوقۇم True ، False ياكى None بولۇشى كېرەك." + +msgid "Boolean (Either True, False or None)" +msgstr "Boolean (True ياكى False)" + +msgid "Positive big integer" +msgstr "مۇسبەت چوڭ پۈتۈن سان" + +msgid "Positive integer" +msgstr "مۇسبەت پۈتۈن سان" + +msgid "Positive small integer" +msgstr "مۇسبەت كىچىك پۈتۈن سان" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (كۆپ بولغاندا %(max_length)s)" + +msgid "Text" +msgstr "تېكىست" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"«%(value)s» قىممىتى ئىناۋەتسىز. ئۇ چوقۇم HH: MM [: ss [.uuuuuu]] شەكلىدە " +"بولۇشى كېرەك." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"«%(value)s» قىممىتىنىڭ توغرا فورماتى بار (HH: MM [: ss [.uuuuuu]]) ئەمما ئۇ " +"ئىناۋەتسىز ۋاقىت." + +msgid "Time" +msgstr "ۋاقىت" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "خام ئىككىلىك سان" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "«%(value)s» ئىناۋەتلىك UUID ئەمەس." + +msgid "Universally unique identifier" +msgstr "ئۇنىۋېرسال بىردىنبىر كىملىك" + +msgid "File" +msgstr "ھۆججەت" + +msgid "Image" +msgstr "رەسىم" + +msgid "A JSON object" +msgstr "JSON ئوبيېكتى" + +msgid "Value must be valid JSON." +msgstr "چوقۇم ئىناۋەتلىك JSON بولۇشى كېرەك." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "مىسال %(value)r %(field)s قىممىتى بولغان %(model)s مەۋجۇت ئەمەس." + +msgid "Foreign Key (type determined by related field)" +msgstr "سىرتقى ئاچقۇچ (تىپى مۇناسىۋەتلىك مەيدان تەرىپىدىن بېكىتىلگەن)" + +msgid "One-to-one relationship" +msgstr "بىرمۇبىر مۇناسىۋەت" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s مۇناسىۋەت" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s مۇناسىۋەتلەر" + +msgid "Many-to-many relationship" +msgstr "كۆپكە كۆب مۇناسىۋىتى" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "بۇ رايون تەلەپ قىلىنىدۇ." + +msgid "Enter a whole number." +msgstr "پۈتۈن ساننى كىرگۈزۈڭ." + +msgid "Enter a valid date." +msgstr "ئىناۋەتلىك چېسلانى كىرگۈزۈڭ." + +msgid "Enter a valid time." +msgstr "ئىناۋەتلىك ۋاقىت كىرگۈزۈڭ." + +msgid "Enter a valid date/time." +msgstr "ئىناۋەتلىك چېسلا / ۋاقىت كىرگۈزۈڭ." + +msgid "Enter a valid duration." +msgstr "ئىناۋەتلىك مۇددىتىنى كىرگۈزۈڭ." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "كۈن سانى چوقۇم {min_days} بىلەن {max_days} ئارىسىدا بولۇشى كېرەك." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "ھېچقانداق ھۆججەت يوللانمىدى. جەدۋەلدىكى كودلاش تۈرىنى تەكشۈرۈڭ." + +msgid "No file was submitted." +msgstr "ھېچقانداق ھۆججەت يوللانمىدى." + +msgid "The submitted file is empty." +msgstr "يوللانغان ھۆججەت قۇرۇق." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"بۇ ھۆججەت نامىنىڭ ئەڭ كۆپ بولغاندا %(max)d ھەرپ بولۇشىغا كاپالەتلىك قىلىڭ " +"(ئۇنىڭدا %(length)d بار)." +msgstr[1] "" +"بۇ ھۆججەت نامىنىڭ ئەڭ كۆپ بولغاندا %(max)d ھەرپ بولۇشىغا كاپالەتلىك قىلىڭ " +"(ئۇنىڭدا %(length)d بار)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "ھۆججەت يوللاڭ ياكى تەكشۈرۈش رامكىسىنى تەكشۈرۈڭ ، ھەر ئىككىسىنى ئەمەس." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"ئىناۋەتلىك رەسىم يۈكلەڭ. سىز يۈكلىگەن ھۆججەت يا رەسىم ئەمەس ۋەياكى بۇزۇلغان." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "ئۈنۈملۈك تاللاشنى تاللاڭ. %(value)s تاللاشلارنىڭ بىرى ئەمەس." + +msgid "Enter a list of values." +msgstr "قىممەت تىزىملىكىنى كىرگۈزۈڭ." + +msgid "Enter a complete value." +msgstr "تولۇق قىممەت كىرگۈزۈڭ." + +msgid "Enter a valid UUID." +msgstr "ئىناۋەتلىك UUID نى كىرگۈزۈڭ." + +msgid "Enter a valid JSON." +msgstr "ئىناۋەتلىك JSON نى كىرگۈزۈڭ." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(يوشۇرۇن مەيدان %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"ManagementForm سانلىق مەلۇماتلىرى يوقاپ كەتتى ياكى ئۆزگەرتىلدى. يوقاپ كەتكەن " +"ساھە: %(field_names)s. ئەگەر مەسىلە ساقلىنىپ قالسا ، خاتالىق دوكلاتىنى " +"تاپشۇرۇشىڭىز كېرەك." + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "ئەڭ كۆپ بولغاندا %(num)d جەدۋەلنى يوللاڭ." +msgstr[1] "ئەڭ كۆپ بولغاندا %(num)d جەدۋەلنى يوللاڭ." + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "كەم دېگەندە %(num)d جەدۋەلنى يوللاڭ." +msgstr[1] "كەم دېگەندە %(num)d جەدۋەلنى يوللاڭ." + +msgid "Order" +msgstr "زاكاز" + +msgid "Delete" +msgstr "ئۆچۈرۈش" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "%(field)s نىڭ قايتىلانغان سانلىق مەلۇماتلىرىنى تۈزىتىڭ." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"%(field)s نىڭ كۆپەيتىلگەن سانلىق مەلۇماتلىرىنى تۈزىتىڭ ، بۇ چوقۇم ئۆزگىچە " +"بولۇشى كېرەك." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"%(field_name)s دىكى قايتىلانغان سانلىق مەلۇماتنى تۈزىتىڭ ، بۇ چوقۇم " +"%(date_field)s دىكى %(lookup)s غا خاس بولۇشى كېرەك." + +msgid "Please correct the duplicate values below." +msgstr "تۆۋەندىكى قايتىلانغان قىممەتنى تۈزىتىڭ." + +msgid "The inline value did not match the parent instance." +msgstr "ئىچكى قىممەت ئاتا مىسالغا ماس كەلمىدى." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"ئۈنۈملۈك تاللاشنى تاللاڭ. بۇ تاللاش ئىشلەتكىلى بولىدىغان تاللاشلارنىڭ بىرى " +"ئەمەس." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "«%(pk)s» ئىناۋەتلىك قىممەت ئەمەس." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s نى %(current_timezone)s ۋاقىت رايونىدا ئىزاھلاشقا بولمايدۇ ئۇ " +"مۈجمەل بولۇشى مۇمكىن ياكى ئۇ مەۋجۇت بولماسلىقى مۇمكىن." + +msgid "Clear" +msgstr "تازىلاش" + +msgid "Currently" +msgstr "نۆۋەتتە" + +msgid "Change" +msgstr "ئۆزگەرتىش" + +msgid "Unknown" +msgstr "نامەلۇم" + +msgid "Yes" +msgstr "ھەئە" + +msgid "No" +msgstr "ياق" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "ھەئە، ياق، بەلكىىم" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d بايىت" +msgstr[1] "%(size)d بايىت" + +#, python-format +msgid "%s KB" +msgstr "%s كىلوبايت" + +#, python-format +msgid "%s MB" +msgstr "%sمېگا بايىت" + +#, python-format +msgid "%s GB" +msgstr "%sگىگا بايىت" + +#, python-format +msgid "%s TB" +msgstr "%s تېرا بايت" + +#, python-format +msgid "%s PB" +msgstr "%s پېتا بايىت" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "يېرىم كېچىدە" + +msgid "noon" +msgstr "چۈشتە" + +msgid "Monday" +msgstr "دۈشەنبە" + +msgid "Tuesday" +msgstr "سەيشەنبە" + +msgid "Wednesday" +msgstr "چارشەمبە" + +msgid "Thursday" +msgstr "پەيشەمبە" + +msgid "Friday" +msgstr "جۈمە" + +msgid "Saturday" +msgstr "شەنبە" + +msgid "Sunday" +msgstr "يەكشەنبە" + +msgid "Mon" +msgstr "دۈش" + +msgid "Tue" +msgstr "سەي" + +msgid "Wed" +msgstr "چار" + +msgid "Thu" +msgstr "پەي" + +msgid "Fri" +msgstr "جۈ" + +msgid "Sat" +msgstr "شەن" + +msgid "Sun" +msgstr "يەك" + +msgid "January" +msgstr "يانۋار" + +msgid "February" +msgstr "فېۋرال" + +msgid "March" +msgstr "مارت" + +msgid "April" +msgstr "ئاپرىل" + +msgid "May" +msgstr "ماي" + +msgid "June" +msgstr "ئىيۇن" + +msgid "July" +msgstr "ئىيۇل" + +msgid "August" +msgstr "ئاۋغۇست" + +msgid "September" +msgstr "سىنتەبىر" + +msgid "October" +msgstr "ئۆكتەبىر" + +msgid "November" +msgstr "نويابىر" + +msgid "December" +msgstr "دىكابىر" + +msgid "jan" +msgstr "يان" + +msgid "feb" +msgstr "فېۋ" + +msgid "mar" +msgstr "مار" + +msgid "apr" +msgstr "ئاپ" + +msgid "may" +msgstr "ماي" + +msgid "jun" +msgstr "ئ‍ىيۇن" + +msgid "jul" +msgstr "ئىيۇل" + +msgid "aug" +msgstr "ئاۋ" + +msgid "sep" +msgstr "سېن" + +msgid "oct" +msgstr "ئۆك" + +msgid "nov" +msgstr "نوي" + +msgid "dec" +msgstr "دىك" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "يانۋار" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "فېۋرال" + +msgctxt "abbrev. month" +msgid "March" +msgstr "مارت" + +msgctxt "abbrev. month" +msgid "April" +msgstr "ئاپرىل" + +msgctxt "abbrev. month" +msgid "May" +msgstr "ماي" + +msgctxt "abbrev. month" +msgid "June" +msgstr "ئىيۇن" + +msgctxt "abbrev. month" +msgid "July" +msgstr "ئىيۇل" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "ئاۋغۇست" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "سېنتەبىر" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "ئۆكتەبىر" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "نويابىر" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "دىكابىر" + +msgctxt "alt. month" +msgid "January" +msgstr "يانۋار" + +msgctxt "alt. month" +msgid "February" +msgstr "فېۋرال" + +msgctxt "alt. month" +msgid "March" +msgstr "مارت" + +msgctxt "alt. month" +msgid "April" +msgstr "ئاپرىل" + +msgctxt "alt. month" +msgid "May" +msgstr "ماي" + +msgctxt "alt. month" +msgid "June" +msgstr "ئىيۇن" + +msgctxt "alt. month" +msgid "July" +msgstr "ئىيۇل" + +msgctxt "alt. month" +msgid "August" +msgstr "ئاۋغۇست" + +msgctxt "alt. month" +msgid "September" +msgstr "سىنتەبىر" + +msgctxt "alt. month" +msgid "October" +msgstr "ئۆكتەبىر" + +msgctxt "alt. month" +msgid "November" +msgstr "نويابىر" + +msgctxt "alt. month" +msgid "December" +msgstr "دىكابىر" + +msgid "This is not a valid IPv6 address." +msgstr "بۇ ئىناۋەتلىك IPv6 ئادرېس ئەمەس." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "ياكى" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "،" + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d يىل" +msgstr[1] "%(num)d يىل" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d ئاي" +msgstr[1] "%(num)d ئاي" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d ھەپتە" +msgstr[1] "%(num)d ھەپتە" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d كۈن" +msgstr[1] "%(num)d كۈن" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d سائەت" +msgstr[1] "%(num)d سائەت" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d مىنۇت" +msgstr[1] "%(num)d مىنۇت" + +msgid "Forbidden" +msgstr "چەكلەنگەن" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF دەلىللەش مەغلۇپ بولدى. تەلەپ ئەمەلدىن قالدۇرۇلدى." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"چۈنكى بۇ HTTPS تور بېكىتى توركۆرگۈڭىز تەرىپىدىن پايدىلانما ئۇچۇرلىرىنى " +"ئەۋەتىشنى تەلەب قىلىدۇ، ئەمما ھېچقايسىسى ئەۋەتىلمىدى، شۇ سەۋەبتىن سىز بۇ " +"ئۇچۇرنى كۆرىۋاتىسىز.\n" +"بۇ ئۇچۇرلار سىزنىڭ بىخەتەرلىكڭىز ۋە تور كۆرگۈڭىزنىڭ ئۈچۈنجى شەخىس تەرىپىدىن " +"تۇتقۇن قىلىنىشىنىڭ ئالدىنى ئېلىش ئۈچۈندۇر. " + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"ئەگەر سىز توركۆرگۈچىڭىزنى “Referer” بېكەت سېكىرتكۈچىنى چەكلەپ تەڭشىسىڭىز، بۇ " +"تور بېكەت، ياكى HTTPS ئۇلىنىشى، ياكى “ئوخشاش-مەنبە” ئىلتىماسلىرى ئۈچۈن ئۇنى " +"قايتا ئىچىپ قويۇڭ." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"ئەگەر سىز تەگىنى ياكى " +"“Referrer-Policy: no-referrer” بېكەت سېكىرتكۈچىنى ئىشلىتىۋاتىسىز، ئۇلارنى " +"ئۆچۈرۈڭ. CSRF قوغداش تەلەپ قىلىدۇ “Referer” بېكەت سېكىرتكۈچى قاتتىق " +"سېكىرتىشنى ئېلىپ بېرىشى كېرەك. ئەگەر سىز شەخسىيەتىڭىزگە قاراشقا ئۆزىڭىزنى " +"ئۆزىڭىز قارغىلى بولسىڭىز، ئۈچىنچى تەرەپ تور بېكەتلىرىگە ئۇلىنىشلاردا قاتارلىق ئالتۇرناتىۋىلارنى ئىشلىتىڭ." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +" بۇ تور بېكەت جەدۋەل يوللىغاندا CSRF ساقلانمىسىنى تەلەپ قىلىدۇ. بۇ " +"ساقلانمىلار بىخەتەرلىكنى كۆزدە تۇتۇپ ، تور كۆرگۈچىڭىزنىڭ ئۈچىنچى تەرەپ " +"تەرىپىدىن ئوغرىلانماسلىقىغا كاپالەتلىك قىلىدۇ." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"ئەگەر توركۆرگۈڭىزنى ساقلانمىلارنى چەكلەش ئۈچۈن تەڭشىگەن بولسىڭىز ، ھېچ " +"بولمىغاندا بۇ تور بېكەت ياكى «ئوخشاش مەنبە» تەلەپلىرى ئۈچۈن ئۇلارنى قايتا " +"قوزغىتىڭ." + +msgid "More information is available with DEBUG=True." +msgstr "DEBUG = True بىلەن تېخىمۇ كۆپ ئۇچۇرلارغا ئېرىشكىلى بولىدۇ." + +msgid "No year specified" +msgstr "يىل بەلگىلەنمىدى" + +msgid "Date out of range" +msgstr "ۋاقىت چەكلىمىسىدىن ئېشىب كەتتى" + +msgid "No month specified" +msgstr "ئاي بەلگىلەنمىدى" + +msgid "No day specified" +msgstr "كۈن بەلگىلەنمىدى" + +msgid "No week specified" +msgstr "ھەپتە بەلگىلەنمىدى" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "%(verbose_name_plural)s يوق" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"كەلگۈسى %(verbose_name_plural)s ئىشلەتكىلى بولمايدۇ ، چۈنكى %(class_name)s." +"allow_future بولسا False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "ئىناۋەتسىز چېسلا تىزمىسى «%(datestr)s» بېرىلگەن فورمات «%(format)s»" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "بۇ سوئالغا ماس كېلىدىغان %(verbose_name)s تېپىلمىدى" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "بەت «ئاخىرقى» ئەمەس ،ياكى ئۇنى int غا ئايلاندۇرغىلى بولمىدى." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "ئىناۋەتسىز بەت (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "بوش تىزىملىك %(class_name)s ۋە «.allow_empty» بولسا False." + +msgid "Directory indexes are not allowed here." +msgstr "ھۆججەت مۇندەرىجىسى بۇ يەردە رۇخسەت قىلىنمايدۇ." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "%(path)s مەۋجۇت ئەمەس" + +#, python-format +msgid "Index of %(directory)s" +msgstr "%(directory)s نىڭ كۆرسەتكۈچىسى" + +msgid "The install worked successfully! Congratulations!" +msgstr "قاچىلاش مۇۋەپپەقىيەتلىك بولدى! مۇبارەك بولسۇن!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +" Django %(version)s ئۈچۈن ئېلان قىلىش " +"خاتىرىسى نى كۆرۈڭ" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"سىز بۇ بەتنى كۆرۈۋاتىسىز ، چۈنكى DEBUG = " +"True سىزنىڭ تەڭشەك ھۆججىتىڭىزدە ،شۇنداقلا ھېچقانداق URL تەڭشەلىمىگەن." + +msgid "Django Documentation" +msgstr " Django قوللانمىسى" + +msgid "Topics, references, & how-to’s" +msgstr "تېما ، پايدىلانما ، & amp; قانداق قىلىش " + +msgid "Tutorial: A Polling App" +msgstr "دەرسلىك: بىر بېلەت تاشلاش دىتالى" + +msgid "Get started with Django" +msgstr "Django بىلەن تونۇشۇش" + +msgid "Django Community" +msgstr "Django جەمىيىتى" + +msgid "Connect, get help, or contribute" +msgstr "قوشۇلۇش ، ياردەمگە ئېرىشىش ياكى تۆھپە قوشۇش" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ug/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ug/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ug/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ug/formats.py new file mode 100644 index 0000000..92f0134 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ug/formats.py @@ -0,0 +1,14 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "j F Y" +TIME_FORMAT = "G:i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "Y/m/d" +SHORT_DATETIME_FORMAT = "Y/m/d G:i" +FIRST_DAY_OF_WEEK = 1 +DECIMAL_SEPARATOR = "." +THOUSAND_SEPARATOR = "," +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/uk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/uk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7c96efb Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/uk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/uk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/uk/LC_MESSAGES/django.po new file mode 100644 index 0000000..8f50fc4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/uk/LC_MESSAGES/django.po @@ -0,0 +1,1365 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Oleksandr Chernihov , 2014 +# Boryslav Larin , 2011,2022 +# Denis Podlesniy , 2016 +# Igor Melnyk, 2014-2015,2017 +# Illia Volochii , 2019,2021-2023 +# Jannis Leidel , 2011 +# Kirill Gagarski , 2014 +# Max V. Stotsky , 2014 +# Mikhail Kolesnik , 2015 +# Mykola Zamkovoi , 2014 +# Alex Bolotov , 2013-2014 +# Roman Kozlovskyi , 2012 +# Sergiy Kuzmenko , 2011 +# tarasyyyk , 2018 +# tarasyyyk , 2019 +# Zoriana Zaiats, 2016-2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-25 06:49+0000\n" +"Last-Translator: Illia Volochii , 2019,2021-2023\n" +"Language-Team: Ukrainian (http://www.transifex.com/django/django/language/" +"uk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: uk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != " +"11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % " +"100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || " +"(n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n" + +msgid "Afrikaans" +msgstr "Африканська" + +msgid "Arabic" +msgstr "Арабська" + +msgid "Algerian Arabic" +msgstr "Алжирська арабська" + +msgid "Asturian" +msgstr "Астурійська" + +msgid "Azerbaijani" +msgstr "Азербайджанська" + +msgid "Bulgarian" +msgstr "Болгарська" + +msgid "Belarusian" +msgstr "Білоруська" + +msgid "Bengali" +msgstr "Бенгальська" + +msgid "Breton" +msgstr "Бретонська" + +msgid "Bosnian" +msgstr "Боснійська" + +msgid "Catalan" +msgstr "Каталонська" + +msgid "Central Kurdish (Sorani)" +msgstr "Центральнокурдська (сорані)" + +msgid "Czech" +msgstr "Чеська" + +msgid "Welsh" +msgstr "Валлійська" + +msgid "Danish" +msgstr "Датська" + +msgid "German" +msgstr "Німецька" + +msgid "Lower Sorbian" +msgstr "Нижньолужицька" + +msgid "Greek" +msgstr "Грецька" + +msgid "English" +msgstr "Англійська" + +msgid "Australian English" +msgstr "Австралійська англійська" + +msgid "British English" +msgstr "Англійська (Великобританія)" + +msgid "Esperanto" +msgstr "Есперанто" + +msgid "Spanish" +msgstr "Іспанська" + +msgid "Argentinian Spanish" +msgstr "Іспанська (Аргентина)" + +msgid "Colombian Spanish" +msgstr "Колумбійська іспанська" + +msgid "Mexican Spanish" +msgstr "Мексиканська іспанська" + +msgid "Nicaraguan Spanish" +msgstr "Нікарагуанська іспанська" + +msgid "Venezuelan Spanish" +msgstr "Венесуельська іспанська" + +msgid "Estonian" +msgstr "Естонська" + +msgid "Basque" +msgstr "Баскська" + +msgid "Persian" +msgstr "Перська" + +msgid "Finnish" +msgstr "Фінська" + +msgid "French" +msgstr "Французька" + +msgid "Frisian" +msgstr "Фризька" + +msgid "Irish" +msgstr "Ірландська" + +msgid "Scottish Gaelic" +msgstr "Шотландська ґельська" + +msgid "Galician" +msgstr "Галіційська" + +msgid "Hebrew" +msgstr "Іврит" + +msgid "Hindi" +msgstr "Хінді" + +msgid "Croatian" +msgstr "Хорватська" + +msgid "Upper Sorbian" +msgstr "Верхньолужицька" + +msgid "Hungarian" +msgstr "Угорська" + +msgid "Armenian" +msgstr "Вірменська" + +msgid "Interlingua" +msgstr "Інтерлінгва" + +msgid "Indonesian" +msgstr "Індонезійська" + +msgid "Igbo" +msgstr "Ігбо" + +msgid "Ido" +msgstr "Ідо" + +msgid "Icelandic" +msgstr "Ісландська" + +msgid "Italian" +msgstr "Італійська" + +msgid "Japanese" +msgstr "Японська" + +msgid "Georgian" +msgstr "Грузинська" + +msgid "Kabyle" +msgstr "Кабіли" + +msgid "Kazakh" +msgstr "Казахська" + +msgid "Khmer" +msgstr "Кхмерська" + +msgid "Kannada" +msgstr "Каннадська" + +msgid "Korean" +msgstr "Корейська" + +msgid "Kyrgyz" +msgstr "Киргизька" + +msgid "Luxembourgish" +msgstr "Люксембурзька" + +msgid "Lithuanian" +msgstr "Литовська" + +msgid "Latvian" +msgstr "Латвійська" + +msgid "Macedonian" +msgstr "Македонська" + +msgid "Malayalam" +msgstr "Малаялам" + +msgid "Mongolian" +msgstr "Монгольська" + +msgid "Marathi" +msgstr "Маратхі" + +msgid "Malay" +msgstr "Малайська" + +msgid "Burmese" +msgstr "Бірманська" + +msgid "Norwegian Bokmål" +msgstr "Норвезька (Букмол)" + +msgid "Nepali" +msgstr "Непальська" + +msgid "Dutch" +msgstr "Голландська" + +msgid "Norwegian Nynorsk" +msgstr "Норвезька (Нюнорськ)" + +msgid "Ossetic" +msgstr "Осетинська" + +msgid "Punjabi" +msgstr "Панджабі" + +msgid "Polish" +msgstr "Польська" + +msgid "Portuguese" +msgstr "Португальська" + +msgid "Brazilian Portuguese" +msgstr "Бразильська португальська" + +msgid "Romanian" +msgstr "Румунська" + +msgid "Russian" +msgstr "Російська" + +msgid "Slovak" +msgstr "Словацька" + +msgid "Slovenian" +msgstr "Словенська" + +msgid "Albanian" +msgstr "Албанська" + +msgid "Serbian" +msgstr "Сербська" + +msgid "Serbian Latin" +msgstr "Сербська (латинська)" + +msgid "Swedish" +msgstr "Шведська" + +msgid "Swahili" +msgstr "Суахілі" + +msgid "Tamil" +msgstr "Тамільська" + +msgid "Telugu" +msgstr "Телугу" + +msgid "Tajik" +msgstr "Таджицька" + +msgid "Thai" +msgstr "Тайська" + +msgid "Turkmen" +msgstr "Туркменська" + +msgid "Turkish" +msgstr "Турецька" + +msgid "Tatar" +msgstr "Татарська" + +msgid "Udmurt" +msgstr "Удмуртська" + +msgid "Ukrainian" +msgstr "Українська" + +msgid "Urdu" +msgstr "Урду" + +msgid "Uzbek" +msgstr "Узбецька" + +msgid "Vietnamese" +msgstr "В'єтнамська" + +msgid "Simplified Chinese" +msgstr "Китайська спрощена" + +msgid "Traditional Chinese" +msgstr "Китайська традиційна" + +msgid "Messages" +msgstr "Повідомлення" + +msgid "Site Maps" +msgstr "Мапи сайту" + +msgid "Static Files" +msgstr "Статичні файли" + +msgid "Syndication" +msgstr "Об'єднання" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "Номер сторінки не є цілим числом" + +msgid "That page number is less than 1" +msgstr "Номер сторінки менше 1" + +msgid "That page contains no results" +msgstr "Сторінка не містить результатів" + +msgid "Enter a valid value." +msgstr "Введіть коректне значення." + +msgid "Enter a valid URL." +msgstr "Введіть коректний URL." + +msgid "Enter a valid integer." +msgstr "Введіть коректне ціле число." + +msgid "Enter a valid email address." +msgstr "Введіть коректну email адресу." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Введіть коректне значення 'slug' (короткого заголовку), що може містити " +"тільки літери, числа, символи підкреслювання або дефіси." + +msgid "Enter a valid IPv4 address." +msgstr "Введіть коректну IPv4 адресу." + +msgid "Enter a valid IPv6 address." +msgstr "Введіть дійсну IPv6 адресу." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Введіть дійсну IPv4 чи IPv6 адресу." + +msgid "Enter only digits separated by commas." +msgstr "Введіть тільки цифри, що розділені комами." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Переконайтеся, що це значення дорівнює %(limit_value)s (зараз " +"%(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Переконайтеся, що це значення менше чи дорівнює %(limit_value)s." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Переконайтеся, що це значення більше чи дорівнює %(limit_value)s." + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Переконайтеся, що це значення містить не менш ніж %(limit_value)d символ " +"(зараз %(show_value)d)." +msgstr[1] "" +"Переконайтеся, що це значення містить не менш ніж %(limit_value)d символів " +"(зараз %(show_value)d)." +msgstr[2] "" +"Переконайтеся, що це значення містить не менш ніж %(limit_value)d символів " +"(зараз %(show_value)d)." +msgstr[3] "" +"Переконайтеся, що це значення містить не менш ніж %(limit_value)d символів " +"(зараз %(show_value)d)." + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Переконайтеся, що це значення містить не більше ніж %(limit_value)d символ " +"(зараз %(show_value)d)." +msgstr[1] "" +"Переконайтеся, що це значення містить не більше ніж %(limit_value)d символи " +"(зараз %(show_value)d)." +msgstr[2] "" +"Переконайтеся, що це значення містить не більше ніж %(limit_value)d символів " +"(зараз %(show_value)d)." +msgstr[3] "" +"Переконайтеся, що це значення містить не більше ніж %(limit_value)d символів " +"(зараз %(show_value)d)." + +msgid "Enter a number." +msgstr "Введіть число." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Переконайтеся, що загалом тут не більше ніж %(max)s цифра." +msgstr[1] "Переконайтеся, що загалом тут не більше ніж %(max)s цифер." +msgstr[2] "Переконайтеся, що загалом тут не більше ніж %(max)s цифер." +msgstr[3] "Переконайтеся, що загалом тут не більше ніж %(max)s цифер." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +"Переконайтеся, що тут не більше ніж %(max)s цифра після десяткової коми." +msgstr[1] "" +"Переконайтеся, що тут не більше ніж %(max)s цифри після десяткової коми." +msgstr[2] "" +"Переконайтеся, що тут не більше ніж %(max)s цифер після десяткової коми." +msgstr[3] "" +"Переконайтеся, що тут не більше ніж %(max)s цифер після десяткової коми." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Переконайтеся, що тут не більше ніж %(max)s цифра до десяткової коми." +msgstr[1] "" +"Переконайтеся, що тут не більше ніж %(max)s цифри до десяткової коми." +msgstr[2] "" +"Переконайтеся, що тут не більше ніж %(max)s цифер до десяткової коми." +msgstr[3] "" +"Переконайтеся, що тут не більше ніж %(max)s цифер до десяткової коми." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"Розширення файлу '%(extension)s' не дозволено. Дозволені розширення: ' " +"%(allowed_extensions)s'." + +msgid "Null characters are not allowed." +msgstr "Символи Null не дозволені." + +msgid "and" +msgstr "та" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s з таким %(field_labels)s вже існує." + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Значення %(value)r не є дозволеним вибором." + +msgid "This field cannot be null." +msgstr "Це поле не може бути пустим." + +msgid "This field cannot be blank." +msgstr "Це поле не може бути порожнім." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s з таким %(field_label)s вже існує." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s повинне бути унікальним для %(date_field_label)s " +"%(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Тип поля: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "Значення \"%(value)s\" повинне бути True, False, або None." + +msgid "Boolean (Either True or False)" +msgstr "Булеве значення (True або False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Рядок (до %(max_length)s)" + +msgid "String (unlimited)" +msgstr "Рядок (необмежений)" + +msgid "Comma-separated integers" +msgstr "Цілі, розділені комою" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "Дата (без часу)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"Значення \"%(value)s\" має невірний формат. Воно повинне бути у форматі YYYY-" +"MM-DD HH:MM[:ss[.uuuuuu]][TZ]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Дата (з часом)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Десяткове число" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "Тривалість" + +msgid "Email address" +msgstr "E-mail адреса" + +msgid "File path" +msgstr "Шлях до файла" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "Число з плаваючою комою" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "Ціле число" + +msgid "Big (8 byte) integer" +msgstr "Велике (8 байтів) ціле число" + +msgid "Small integer" +msgstr "Мале ціле число" + +msgid "IPv4 address" +msgstr "IPv4 адреса" + +msgid "IP address" +msgstr "IP адреса" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "Булеве значення (включаючи True, False або None)" + +msgid "Positive big integer" +msgstr "Додатнє велике ціле число" + +msgid "Positive integer" +msgstr "Додатнє ціле число" + +msgid "Positive small integer" +msgstr "Додатнє мале ціле число" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (до %(max_length)s)" + +msgid "Text" +msgstr "Текст" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"Значення \"%(value)s\" має невірний формат. Воно повинне бути у форматі HH:" +"MM[:ss[.uuuuuu]]." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Час" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "Необроблені двійкові дані" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "“%(value)s” не є валідним UUID." + +msgid "Universally unique identifier" +msgstr "Універсальний унікальний ідентифікатор" + +msgid "File" +msgstr "Файл" + +msgid "Image" +msgstr "Зображення" + +msgid "A JSON object" +msgstr "JSON-об'єкт" + +msgid "Value must be valid JSON." +msgstr "Значення має бути коректним JSON." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "Екземпляр %(model)s з %(field)s %(value)r не існує." + +msgid "Foreign Key (type determined by related field)" +msgstr "Зовнішній ключ (тип визначається відповідно поля)" + +msgid "One-to-one relationship" +msgstr "Один-до-одного" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s звязок" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s звязки" + +msgid "Many-to-many relationship" +msgstr "Багато-до-багатьох" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Це поле обов'язкове." + +msgid "Enter a whole number." +msgstr "Введіть ціле число." + +msgid "Enter a valid date." +msgstr "Введіть коректну дату." + +msgid "Enter a valid time." +msgstr "Введіть коректний час." + +msgid "Enter a valid date/time." +msgstr "Введіть коректну дату/час." + +msgid "Enter a valid duration." +msgstr "Введіть коректну тривалість." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Кількість днів повинна бути від {min_days} до {max_days}." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Файл не надіслано. Перевірте тип кодування форми." + +msgid "No file was submitted." +msgstr "Файл не було надіслано." + +msgid "The submitted file is empty." +msgstr "Переданий файл порожній." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Переконайтеся, що це ім'я файлу містить не більше ніж з %(max)d символ " +"(зараз %(length)d)." +msgstr[1] "" +"Переконайтеся, що це ім'я файлу містить не більше ніж з %(max)d символи " +"(зараз %(length)d)." +msgstr[2] "" +"Переконайтеся, що це ім'я файлу містить не більше ніж з %(max)d символів " +"(зараз %(length)d)." +msgstr[3] "" +"Переконайтеся, що це ім'я файлу містить не більше ніж з %(max)d символів " +"(зараз %(length)d)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Будь ласка, або завантажте файл, або відмітьте прапорець очищення, а не " +"обидва варіанти одразу" + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Завантажте правильний малюнок. Файл, який ви завантажили, не є малюнком, або " +"є зіпсованим малюнком." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "Зробить коректний вибір, %(value)s немає серед варіантів вибору." + +msgid "Enter a list of values." +msgstr "Введіть список значень." + +msgid "Enter a complete value." +msgstr "Введіть значення повністю." + +msgid "Enter a valid UUID." +msgstr "Введіть коректне значення UUID," + +msgid "Enter a valid JSON." +msgstr "Введіть коректний JSON." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Приховане поле %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +msgid "Order" +msgstr "Послідовність" + +msgid "Delete" +msgstr "Видалити" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Будь ласка, виправте повторювані дані для поля %(field)s." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Будь ласка, виправте повторювані дані для поля %(field)s, яке має бути " +"унікальним." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Будь ласка, виправте повторювані дані для поля %(field_name)s, яке має бути " +"унікальним для вибірки %(lookup)s на %(date_field)s." + +msgid "Please correct the duplicate values below." +msgstr "Будь ласка, виправте повторювані значення нижче." + +msgid "The inline value did not match the parent instance." +msgstr "Зв'язане значення не відповідає батьківському екземпляру." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "Зробить коректний вибір. Такого варіанту нема серед доступних." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Очистити" + +msgid "Currently" +msgstr "Наразі" + +msgid "Change" +msgstr "Змінити" + +msgid "Unknown" +msgstr "Невідомо" + +msgid "Yes" +msgstr "Так" + +msgid "No" +msgstr "Ні" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "так,ні,можливо" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d байт" +msgstr[1] "%(size)d байти" +msgstr[2] "%(size)d байтів" +msgstr[3] "%(size)d байтів" + +#, python-format +msgid "%s KB" +msgstr "%s Кб" + +#, python-format +msgid "%s MB" +msgstr "%s Мб" + +#, python-format +msgid "%s GB" +msgstr "%s Гб" + +#, python-format +msgid "%s TB" +msgstr "%s Тб" + +#, python-format +msgid "%s PB" +msgstr "%s Пб" + +msgid "p.m." +msgstr "після полудня" + +msgid "a.m." +msgstr "до полудня" + +msgid "PM" +msgstr "після полудня" + +msgid "AM" +msgstr "до полудня" + +msgid "midnight" +msgstr "північ" + +msgid "noon" +msgstr "полудень" + +msgid "Monday" +msgstr "Понеділок" + +msgid "Tuesday" +msgstr "Вівторок" + +msgid "Wednesday" +msgstr "Середа" + +msgid "Thursday" +msgstr "Четвер" + +msgid "Friday" +msgstr "П'ятниця" + +msgid "Saturday" +msgstr "Субота" + +msgid "Sunday" +msgstr "Неділя" + +msgid "Mon" +msgstr "Пн" + +msgid "Tue" +msgstr "Вт" + +msgid "Wed" +msgstr "Ср" + +msgid "Thu" +msgstr "Чт" + +msgid "Fri" +msgstr "Пт" + +msgid "Sat" +msgstr "Сб" + +msgid "Sun" +msgstr "Нд" + +msgid "January" +msgstr "Січень" + +msgid "February" +msgstr "Лютий" + +msgid "March" +msgstr "Березень" + +msgid "April" +msgstr "Квітень" + +msgid "May" +msgstr "Травень" + +msgid "June" +msgstr "Червень" + +msgid "July" +msgstr "Липень" + +msgid "August" +msgstr "Серпень" + +msgid "September" +msgstr "Вересень" + +msgid "October" +msgstr "Жовтень" + +msgid "November" +msgstr "Листопад" + +msgid "December" +msgstr "Грудень" + +msgid "jan" +msgstr "січ" + +msgid "feb" +msgstr "лют" + +msgid "mar" +msgstr "бер" + +msgid "apr" +msgstr "кві" + +msgid "may" +msgstr "тра" + +msgid "jun" +msgstr "чер" + +msgid "jul" +msgstr "лип" + +msgid "aug" +msgstr "сер" + +msgid "sep" +msgstr "вер" + +msgid "oct" +msgstr "жов" + +msgid "nov" +msgstr "лис" + +msgid "dec" +msgstr "гру" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Січ." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Лют." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Березень" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Квітень" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Травень" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Червень" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Липень" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Сер." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Вер." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Жов." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Лис." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Гру." + +msgctxt "alt. month" +msgid "January" +msgstr "січня" + +msgctxt "alt. month" +msgid "February" +msgstr "лютого" + +msgctxt "alt. month" +msgid "March" +msgstr "березня" + +msgctxt "alt. month" +msgid "April" +msgstr "квітня" + +msgctxt "alt. month" +msgid "May" +msgstr "травня" + +msgctxt "alt. month" +msgid "June" +msgstr "червня" + +msgctxt "alt. month" +msgid "July" +msgstr "липня" + +msgctxt "alt. month" +msgid "August" +msgstr "серпня" + +msgctxt "alt. month" +msgid "September" +msgstr "вересня" + +msgctxt "alt. month" +msgid "October" +msgstr "жовтня" + +msgctxt "alt. month" +msgid "November" +msgstr "листопада" + +msgctxt "alt. month" +msgid "December" +msgstr "грудня" + +msgid "This is not a valid IPv6 address." +msgstr "Це не є правильною адресою IPv6." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "або" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d рік" +msgstr[1] "%(num)d роки" +msgstr[2] "%(num)d років" +msgstr[3] "%(num)d років" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d місяць" +msgstr[1] "%(num)d місяці" +msgstr[2] "%(num)d місяців" +msgstr[3] "%(num)d місяців" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d тиждень" +msgstr[1] "%(num)d тижні" +msgstr[2] "%(num)d тижнів" +msgstr[3] "%(num)d тижнів" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d день" +msgstr[1] "%(num)d дні" +msgstr[2] "%(num)d днів" +msgstr[3] "%(num)d днів" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d година" +msgstr[1] "%(num)d години" +msgstr[2] "%(num)d годин" +msgstr[3] "%(num)d годин" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d хвилина" +msgstr[1] "%(num)d хвилини" +msgstr[2] "%(num)d хвилин" +msgstr[3] "%(num)d хвилин" + +msgid "Forbidden" +msgstr "Заборонено" + +msgid "CSRF verification failed. Request aborted." +msgstr "Помилка перевірки CSRF. Запит відхилений." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Якщо ви налаштували свій браузер таким чином, щоб заборонити йому передавати " +"заголовок «Referer», будь ласка, дозвольте йому відсилати даний заголовок " +"принаймні для даного сайту, або для всіх HTTPS-з'єднань, або для подібних " +"запитів." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Ви бачите це повідомлення, тому що даний сайт вимагає, щоб при відправці " +"форм була відправлена ​​і CSRF-cookie. Даний тип cookie необхідний з міркувань " +"безпеки, щоб переконатися, що ваш браузер не був взламаний третьою стороною." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "Більше інформації можна отримати з DEBUG=True." + +msgid "No year specified" +msgstr "Рік не вказано" + +msgid "Date out of range" +msgstr "Дата поза діапазоном" + +msgid "No month specified" +msgstr "Місяць не вказано" + +msgid "No day specified" +msgstr "День не вказано" + +msgid "No week specified" +msgstr "Тиждень не вказано" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "%(verbose_name_plural)s недоступні" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Майбутні %(verbose_name_plural)s недоступні, тому що %(class_name)s." +"allow_future має нульове значення." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Жодні %(verbose_name)s не були знайдені по запиту" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Невірна сторінка (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Перегляд вмісту каталогу не дозволено." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "\"%(path)s\" не існує" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Вміст директорії %(directory)s" + +msgid "The install worked successfully! Congratulations!" +msgstr "Вітаємо, команда install завершилась успішно!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Нотатки релізу for Django %(version)s" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"Ви бачите цю сторінку тому що змінна DEBUG встановлена на True у вашому файлі " +"конфігурації і ви не налаштували жодного URL." + +msgid "Django Documentation" +msgstr "Документація Django" + +msgid "Topics, references, & how-to’s" +msgstr "Статті, довідки та інструкції" + +msgid "Tutorial: A Polling App" +msgstr "Посібник: програма голосування" + +msgid "Get started with Django" +msgstr "Початок роботи з Django" + +msgid "Django Community" +msgstr "Спільнота Django" + +msgid "Connect, get help, or contribute" +msgstr "Отримати допомогу, чи допомогти" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/uk/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/uk/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/uk/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/uk/formats.py new file mode 100644 index 0000000..0f28831 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/uk/formats.py @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "d E Y р." +TIME_FORMAT = "H:i" +DATETIME_FORMAT = "d E Y р. H:i" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "d F" +SHORT_DATE_FORMAT = "d.m.Y" +SHORT_DATETIME_FORMAT = "d.m.Y H:i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d.%m.%Y", # '25.10.2006' + "%d %B %Y", # '25 October 2006' +] +TIME_INPUT_FORMATS = [ + "%H:%M:%S", # '14:30:59' + "%H:%M:%S.%f", # '14:30:59.000200' + "%H:%M", # '14:30' +] +DATETIME_INPUT_FORMATS = [ + "%d.%m.%Y %H:%M:%S", # '25.10.2006 14:30:59' + "%d.%m.%Y %H:%M:%S.%f", # '25.10.2006 14:30:59.000200' + "%d.%m.%Y %H:%M", # '25.10.2006 14:30' + "%d %B %Y %H:%M:%S", # '25 October 2006 14:30:59' + "%d %B %Y %H:%M:%S.%f", # '25 October 2006 14:30:59.000200' + "%d %B %Y %H:%M", # '25 October 2006 14:30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "\xa0" # non-breaking space +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ur/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ur/LC_MESSAGES/django.mo new file mode 100644 index 0000000..706c2ce Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ur/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ur/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ur/LC_MESSAGES/django.po new file mode 100644 index 0000000..6067c00 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/ur/LC_MESSAGES/django.po @@ -0,0 +1,1222 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Mansoorulhaq Mansoor , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Urdu (http://www.transifex.com/django/django/language/ur/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ur\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Afrikaans" +msgstr "" + +msgid "Arabic" +msgstr "عربی" + +msgid "Asturian" +msgstr "" + +msgid "Azerbaijani" +msgstr "" + +msgid "Bulgarian" +msgstr "بلغاری" + +msgid "Belarusian" +msgstr "" + +msgid "Bengali" +msgstr "بنگالی" + +msgid "Breton" +msgstr "" + +msgid "Bosnian" +msgstr "بوسنیائی" + +msgid "Catalan" +msgstr "کیٹالانی" + +msgid "Czech" +msgstr "زیچ" + +msgid "Welsh" +msgstr "ویلش" + +msgid "Danish" +msgstr "ڈینش" + +msgid "German" +msgstr "جرمن" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "گریک" + +msgid "English" +msgstr "انگلش" + +msgid "Australian English" +msgstr "" + +msgid "British English" +msgstr "برطانوی انگلش" + +msgid "Esperanto" +msgstr "" + +msgid "Spanish" +msgstr "ھسپانوی" + +msgid "Argentinian Spanish" +msgstr "ارجنٹائنی سپینش" + +msgid "Colombian Spanish" +msgstr "" + +msgid "Mexican Spanish" +msgstr "" + +msgid "Nicaraguan Spanish" +msgstr "" + +msgid "Venezuelan Spanish" +msgstr "" + +msgid "Estonian" +msgstr "اسٹانین" + +msgid "Basque" +msgstr "باسک" + +msgid "Persian" +msgstr "فارسی" + +msgid "Finnish" +msgstr "فنش" + +msgid "French" +msgstr "فرانسیسی" + +msgid "Frisian" +msgstr "فریسی" + +msgid "Irish" +msgstr "آئرش" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "گیلیشین" + +msgid "Hebrew" +msgstr "عبرانی" + +msgid "Hindi" +msgstr "ھندی" + +msgid "Croatian" +msgstr "کروشن" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "ھونگارین" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "" + +msgid "Indonesian" +msgstr "انڈونیشین" + +msgid "Ido" +msgstr "" + +msgid "Icelandic" +msgstr "آئس لینڈک" + +msgid "Italian" +msgstr "اطالوی" + +msgid "Japanese" +msgstr "جاپانی" + +msgid "Georgian" +msgstr "جارجیائی" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "" + +msgid "Khmer" +msgstr "خمر" + +msgid "Kannada" +msgstr "کناڈا" + +msgid "Korean" +msgstr "کوریائی" + +msgid "Luxembourgish" +msgstr "" + +msgid "Lithuanian" +msgstr "لیتھونیائی" + +msgid "Latvian" +msgstr "لتوینی" + +msgid "Macedonian" +msgstr "میسیڈونین" + +msgid "Malayalam" +msgstr "ملایالم" + +msgid "Mongolian" +msgstr "منگولین" + +msgid "Marathi" +msgstr "" + +msgid "Burmese" +msgstr "" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "" + +msgid "Dutch" +msgstr "ڈچ" + +msgid "Norwegian Nynorsk" +msgstr "نارویائی نینورسک" + +msgid "Ossetic" +msgstr "" + +msgid "Punjabi" +msgstr "پنجابی" + +msgid "Polish" +msgstr "پولش" + +msgid "Portuguese" +msgstr "پورتگیز" + +msgid "Brazilian Portuguese" +msgstr "برازیلی پورتگیز" + +msgid "Romanian" +msgstr "رومانی" + +msgid "Russian" +msgstr "روسی" + +msgid "Slovak" +msgstr "سلووک" + +msgid "Slovenian" +msgstr "سلووینین" + +msgid "Albanian" +msgstr "البانوی" + +msgid "Serbian" +msgstr "سربین" + +msgid "Serbian Latin" +msgstr "سربین لاطینی" + +msgid "Swedish" +msgstr "سویڈش" + +msgid "Swahili" +msgstr "" + +msgid "Tamil" +msgstr "تاملی" + +msgid "Telugu" +msgstr "تیلگو" + +msgid "Thai" +msgstr "تھائی" + +msgid "Turkish" +msgstr "ترکش" + +msgid "Tatar" +msgstr "" + +msgid "Udmurt" +msgstr "" + +msgid "Ukrainian" +msgstr "یوکرائنی" + +msgid "Urdu" +msgstr "" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "ویتنامی" + +msgid "Simplified Chinese" +msgstr "سادی چینی" + +msgid "Traditional Chinese" +msgstr "روایتی چینی" + +msgid "Messages" +msgstr "" + +msgid "Site Maps" +msgstr "" + +msgid "Static Files" +msgstr "" + +msgid "Syndication" +msgstr "" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "درست قیمت (ویلیو) درج کریں۔" + +msgid "Enter a valid URL." +msgstr "درست یو آر ایل (URL) درج کریں۔" + +msgid "Enter a valid integer." +msgstr "" + +msgid "Enter a valid email address." +msgstr "" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "IPv4 کا درست پتہ درج کریں۔" + +msgid "Enter a valid IPv6 address." +msgstr "" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "" + +msgid "Enter only digits separated by commas." +msgstr "صرف اعداد درج کریں جو کوموں سے الگ کئے ھوئے ھوں۔" + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"اس بات کا یقین کر لیں کہ یہ قیمت (ویلیو) %(limit_value)s ھے۔ (یہ " +"%(show_value)s ھے)%(show_value)s" + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" +"اس بات کا یقین کر لیں کہ یہ قیمت (ویلیو) %(limit_value)s سے کم یا اس کے " +"برابر ھے۔" + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" +"اس بات کا یقین کر لیں کہ یہ قیمت (ویلیو) %(limit_value)s سے زیادہ یا اس کے " +"برابر ھے۔" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Enter a number." +msgstr "نمبر درج کریں۔" + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "اور" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "" + +msgid "This field cannot be null." +msgstr "یہ خانہ نامعلوم (null( نھیں رہ سکتا۔" + +msgid "This field cannot be blank." +msgstr "یہ خانہ خالی نھیں چھوڑا جا سکتا۔" + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s اس %(field_label)s کے ساتھ پہلے ہی موجود ھے۔" + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "%(field_type)s قسم کا خانہ" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "بولین (True یا False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "سلسلۂ حروف (String) (%(max_length)s تک)" + +msgid "Comma-separated integers" +msgstr " کومے سے الگ کئے ھوئے صحیح اعداد" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "تاریخ (وقت کے بغیر)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "تاریخ (بمع وقت)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "اعشاری نمبر" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "" + +msgid "Email address" +msgstr "" + +msgid "File path" +msgstr "فائل کا راستہ(path(" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "نقطہ اعشاریہ والا نمبر" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "صحیح عدد" + +msgid "Big (8 byte) integer" +msgstr "بڑا (8 بائٹ) صحیح عدد" + +msgid "IPv4 address" +msgstr "" + +msgid "IP address" +msgstr "IP ایڈریس" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "بولین (True، False یا None(" + +msgid "Positive integer" +msgstr "" + +msgid "Positive small integer" +msgstr "" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "" + +msgid "Small integer" +msgstr "" + +msgid "Text" +msgstr "متن" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "وقت" + +msgid "URL" +msgstr "یو آر ایل" + +msgid "Raw binary data" +msgstr "" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "" + +msgid "Image" +msgstr "" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "بیرونی کلید (FK( (قسم متعلقہ خانے سے متعین ھو گی)" + +msgid "One-to-one relationship" +msgstr "ون-ٹو-ون ریلیشن شپ" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "مینی-ٹو-مینی ریلیشن شپ" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr "" + +msgid "This field is required." +msgstr "یہ خانہ درکار ھے۔" + +msgid "Enter a whole number." +msgstr "مکمل نمبر درج کریں۔" + +msgid "Enter a valid date." +msgstr "درست تاریخ درج کریں۔" + +msgid "Enter a valid time." +msgstr "درست وقت درج کریں۔" + +msgid "Enter a valid date/time." +msgstr "درست تاریخ/وقت درج کریں۔" + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "کوئی فائل پیش نہیں کی گئی۔ فارم پر اینکوڈنگ کی قسم چیک کریں۔" + +msgid "No file was submitted." +msgstr "کوئی فائل پیش نہیں کی گئی تھی۔" + +msgid "The submitted file is empty." +msgstr "پیش کی گئی فائل خالی ھے۔" + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +msgstr[1] "" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "براہ مھربانی فائل پیش کریں یا Clear checkbox منتخب کریں۔ نہ کہ دونوں۔" + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"درست تصویر اپ لوڈ کریں۔ جو فائل آپ نے اپ لوڈ کی تھی وہ تصویر نہیں تھی یا " +"خراب تصویر تھی۔" + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "درست انتخاب منتخب کریں۔ %(value)s دستیاب انتخابات میں سے کوئی نہیں۔" + +msgid "Enter a list of values." +msgstr "قیمتوں (ویلیوز) کی لسٹ درج کریں۔" + +msgid "Enter a complete value." +msgstr "" + +msgid "Enter a valid UUID." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr "" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" +msgstr[1] "" + +msgid "Order" +msgstr "ترتیب" + +msgid "Delete" +msgstr "مٹائیں" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "براہ کرم %(field)s کے لئے دوہرا مواد درست کریں۔" + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"براہ کرم %(field)s کے لئے دوہرا مواد درست کریں جوکہ منفرد ھونا ضروری ھے۔" + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"براہ کرم %(field_name)s میں دوہرا مواد درست کریں جو کہ %(date_field)s میں " +"%(lookup)s کے لئے منفرد ھونا ضروری ھے۔" + +msgid "Please correct the duplicate values below." +msgstr "براہ کرم نیچے دوہری قیمتیں (ویلیوز) درست کریں۔" + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "درست انتخاب منتخب کریں۔ یہ انتخاب دستیاب انتخابات میں سے کوئی نہیں ھے۔" + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "صاف کریں" + +msgid "Currently" +msgstr "فی الحال" + +msgid "Change" +msgstr "تبدیل کریں" + +msgid "Unknown" +msgstr "نامعلوم" + +msgid "Yes" +msgstr "ھاں" + +msgid "No" +msgstr "نھیں" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "ھاں،نہیں،ھوسکتاہے" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d بائٹ" +msgstr[1] "%(size)d بائٹس" + +#, python-format +msgid "%s KB" +msgstr "%s ک ۔ ب" + +#, python-format +msgid "%s MB" +msgstr "%s م ۔ ب" + +#, python-format +msgid "%s GB" +msgstr "%s ج ۔ ب" + +#, python-format +msgid "%s TB" +msgstr "%s ٹ ۔ ب" + +#, python-format +msgid "%s PB" +msgstr "%s پ ۔ پ" + +msgid "p.m." +msgstr "شام" + +msgid "a.m." +msgstr "صبح" + +msgid "PM" +msgstr "شام" + +msgid "AM" +msgstr "صبح" + +msgid "midnight" +msgstr "نصف رات" + +msgid "noon" +msgstr "دوپہر" + +msgid "Monday" +msgstr "سوموار" + +msgid "Tuesday" +msgstr "منگل" + +msgid "Wednesday" +msgstr "بدھ" + +msgid "Thursday" +msgstr "جمعرات" + +msgid "Friday" +msgstr "جمعہ" + +msgid "Saturday" +msgstr "ھفتہ" + +msgid "Sunday" +msgstr "اتوار" + +msgid "Mon" +msgstr "سوموار" + +msgid "Tue" +msgstr "منگل" + +msgid "Wed" +msgstr "بدھ" + +msgid "Thu" +msgstr "جمعرات" + +msgid "Fri" +msgstr "جمعہ" + +msgid "Sat" +msgstr "ھفتہ" + +msgid "Sun" +msgstr "اتوار" + +msgid "January" +msgstr "جنوری" + +msgid "February" +msgstr "فروری" + +msgid "March" +msgstr "مارچ" + +msgid "April" +msgstr "اپریل" + +msgid "May" +msgstr "مئی" + +msgid "June" +msgstr "جون" + +msgid "July" +msgstr "جولائی" + +msgid "August" +msgstr "اگست" + +msgid "September" +msgstr "ستمبر" + +msgid "October" +msgstr "اکتوبر" + +msgid "November" +msgstr "نومبر" + +msgid "December" +msgstr "دسمبر" + +msgid "jan" +msgstr "جنوری" + +msgid "feb" +msgstr "فروری" + +msgid "mar" +msgstr "مارچ" + +msgid "apr" +msgstr "اپریل" + +msgid "may" +msgstr "مئی" + +msgid "jun" +msgstr "جون" + +msgid "jul" +msgstr "جولائی" + +msgid "aug" +msgstr "اگست" + +msgid "sep" +msgstr "ستمبر" + +msgid "oct" +msgstr "اکتوبر" + +msgid "nov" +msgstr "نومبر" + +msgid "dec" +msgstr "دسمبر" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "جنوری" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "فروری" + +msgctxt "abbrev. month" +msgid "March" +msgstr "مارچ" + +msgctxt "abbrev. month" +msgid "April" +msgstr "اپریل" + +msgctxt "abbrev. month" +msgid "May" +msgstr "مئی" + +msgctxt "abbrev. month" +msgid "June" +msgstr "جون" + +msgctxt "abbrev. month" +msgid "July" +msgstr "جولائی" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "اگست" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "ستمبر" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "اکتوبر" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "نومبر" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "دسمبر" + +msgctxt "alt. month" +msgid "January" +msgstr "جنوری" + +msgctxt "alt. month" +msgid "February" +msgstr "فروری" + +msgctxt "alt. month" +msgid "March" +msgstr "مارچ" + +msgctxt "alt. month" +msgid "April" +msgstr "اپریل" + +msgctxt "alt. month" +msgid "May" +msgstr "مئی" + +msgctxt "alt. month" +msgid "June" +msgstr "جون" + +msgctxt "alt. month" +msgid "July" +msgstr "جولائی" + +msgctxt "alt. month" +msgid "August" +msgstr "اگست" + +msgctxt "alt. month" +msgid "September" +msgstr "ستمبر" + +msgctxt "alt. month" +msgid "October" +msgstr "اکتوبر" + +msgctxt "alt. month" +msgid "November" +msgstr "نومبر" + +msgctxt "alt. month" +msgid "December" +msgstr "دسمبر" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "یا" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "،" + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" + +msgid "0 minutes" +msgstr "" + +msgid "Forbidden" +msgstr "" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "" + +msgid "No day specified" +msgstr "" + +msgid "No week specified" +msgstr "" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "" + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/uz/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/uz/LC_MESSAGES/django.mo new file mode 100644 index 0000000..57f89e8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/uz/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/uz/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/uz/LC_MESSAGES/django.po new file mode 100644 index 0000000..4e9b6cf --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/uz/LC_MESSAGES/django.po @@ -0,0 +1,1295 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Abdulaminkhon Khaydarov , 2020 +# Bedilbek Khamidov , 2019 +# Claude Paroz , 2020 +# Sukhrobbek Ismatov , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-19 20:23+0200\n" +"PO-Revision-Date: 2020-07-25 17:08+0000\n" +"Last-Translator: Abdulaminkhon Khaydarov \n" +"Language-Team: Uzbek (http://www.transifex.com/django/django/language/uz/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: uz\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Afrikaans" +msgstr "Afrika tili" + +msgid "Arabic" +msgstr "Arab tili" + +msgid "Algerian Arabic" +msgstr "Jazoir arab tili" + +msgid "Asturian" +msgstr "Asturiya tili" + +msgid "Azerbaijani" +msgstr "Ozarbayjon tili" + +msgid "Bulgarian" +msgstr "Bolgar tili" + +msgid "Belarusian" +msgstr "Belorus tili" + +msgid "Bengali" +msgstr "Bengal tili" + +msgid "Breton" +msgstr "Breton tili" + +msgid "Bosnian" +msgstr "Bosniya tili" + +msgid "Catalan" +msgstr "Katalon tili" + +msgid "Czech" +msgstr "Chex tili" + +msgid "Welsh" +msgstr "Uels tili" + +msgid "Danish" +msgstr "Daniya tili" + +msgid "German" +msgstr "Nemis tili" + +msgid "Lower Sorbian" +msgstr "Quyi sorbiya tili" + +msgid "Greek" +msgstr "Yunon tili" + +msgid "English" +msgstr "Ingliz tili" + +msgid "Australian English" +msgstr "Avstraliya ingliz tili" + +msgid "British English" +msgstr "Britan Ingliz tili" + +msgid "Esperanto" +msgstr "Esperanto tili" + +msgid "Spanish" +msgstr "Ispan tili" + +msgid "Argentinian Spanish" +msgstr "Argentina Ispan tili" + +msgid "Colombian Spanish" +msgstr "Kolumbiya Ispan tili" + +msgid "Mexican Spanish" +msgstr "Meksika Ispan tili " + +msgid "Nicaraguan Spanish" +msgstr "Nikaragua Ispan tili" + +msgid "Venezuelan Spanish" +msgstr "Venesuela Ispan tili" + +msgid "Estonian" +msgstr "Estoniya tili" + +msgid "Basque" +msgstr "Bask tili" + +msgid "Persian" +msgstr "Fors tili" + +msgid "Finnish" +msgstr "Fin tili" + +msgid "French" +msgstr "Fransuz tili" + +msgid "Frisian" +msgstr "Friziya tili" + +msgid "Irish" +msgstr "Irland tili" + +msgid "Scottish Gaelic" +msgstr "Shotland Gal tili" + +msgid "Galician" +msgstr "Galisiya tili" + +msgid "Hebrew" +msgstr "Ibroniy tili" + +msgid "Hindi" +msgstr "Hind tili" + +msgid "Croatian" +msgstr "Xorvat tili" + +msgid "Upper Sorbian" +msgstr "Yuqori Sorbiya tili" + +msgid "Hungarian" +msgstr "Vengriya tili" + +msgid "Armenian" +msgstr "Arman tili" + +msgid "Interlingua" +msgstr "Interlingua tili" + +msgid "Indonesian" +msgstr "Indoneziya tili" + +msgid "Igbo" +msgstr "Igbo tili" + +msgid "Ido" +msgstr "Ido tili" + +msgid "Icelandic" +msgstr "Island tili" + +msgid "Italian" +msgstr "Italyan tili" + +msgid "Japanese" +msgstr "Yapon tili" + +msgid "Georgian" +msgstr "Gruzin tili" + +msgid "Kabyle" +msgstr "Kabil tili" + +msgid "Kazakh" +msgstr "Qozoq tili" + +msgid "Khmer" +msgstr "Xmer tili" + +msgid "Kannada" +msgstr "Kannada tili" + +msgid "Korean" +msgstr "Koreys tili" + +msgid "Kyrgyz" +msgstr "Qirg'iz tili" + +msgid "Luxembourgish" +msgstr "Lyuksemburg tili" + +msgid "Lithuanian" +msgstr "Litva tili" + +msgid "Latvian" +msgstr "Latviya tili" + +msgid "Macedonian" +msgstr "Makedoniya tili" + +msgid "Malayalam" +msgstr "Malayalam tili" + +msgid "Mongolian" +msgstr "Mo'g'ul tili" + +msgid "Marathi" +msgstr "Marati tili" + +msgid "Burmese" +msgstr "Birma tili" + +msgid "Norwegian Bokmål" +msgstr "Norvegiya Bokmal tili" + +msgid "Nepali" +msgstr "Nepal tili" + +msgid "Dutch" +msgstr "Golland tili" + +msgid "Norwegian Nynorsk" +msgstr "Norvegiya Ninorsk tili" + +msgid "Ossetic" +msgstr "Osetik tili" + +msgid "Punjabi" +msgstr "Panjob tili" + +msgid "Polish" +msgstr "Polyak tili" + +msgid "Portuguese" +msgstr "Portugal tili" + +msgid "Brazilian Portuguese" +msgstr "Braziliya Portugal tili" + +msgid "Romanian" +msgstr "Rumin tili" + +msgid "Russian" +msgstr "Rus tili" + +msgid "Slovak" +msgstr "Slovak tili" + +msgid "Slovenian" +msgstr "Slovan tili" + +msgid "Albanian" +msgstr "Alban tili" + +msgid "Serbian" +msgstr "Serb tili" + +msgid "Serbian Latin" +msgstr "Serbiya Lotin tili" + +msgid "Swedish" +msgstr "Shved tili" + +msgid "Swahili" +msgstr "Suaxili tili" + +msgid "Tamil" +msgstr "Tamil tili" + +msgid "Telugu" +msgstr "Telugu tili" + +msgid "Tajik" +msgstr "Tojik tili" + +msgid "Thai" +msgstr "Tay tili" + +msgid "Turkmen" +msgstr "Turkman tili" + +msgid "Turkish" +msgstr "Turk tili" + +msgid "Tatar" +msgstr "Tatar tili" + +msgid "Udmurt" +msgstr "Udmurt tili" + +msgid "Ukrainian" +msgstr "Ukrain tili" + +msgid "Urdu" +msgstr "Urdu tili" + +msgid "Uzbek" +msgstr "O'zbek tili" + +msgid "Vietnamese" +msgstr "Vetnam tili" + +msgid "Simplified Chinese" +msgstr "Soddalashtirilgan xitoy tili" + +msgid "Traditional Chinese" +msgstr "An'anaviy xitoy tili" + +msgid "Messages" +msgstr "Xabarlar" + +msgid "Site Maps" +msgstr "Sayt xaritalari" + +msgid "Static Files" +msgstr "Statik fayllar" + +msgid "Syndication" +msgstr "Sindikatsiya" + +msgid "That page number is not an integer" +msgstr "Bu sahifa raqami butun son emas" + +msgid "That page number is less than 1" +msgstr "Bu sahifa raqami 1 dan kichik" + +msgid "That page contains no results" +msgstr "Ushbu sahifada hech qanday natija yo'q" + +msgid "Enter a valid value." +msgstr "To'g'ri qiymatni kiriting." + +msgid "Enter a valid URL." +msgstr "To'g'ri URL manzilini kiriting." + +msgid "Enter a valid integer." +msgstr "To'g'ri butun sonni kiriting." + +msgid "Enter a valid email address." +msgstr "To'g'ri elektron pochta manzilini kiriting." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" +"Harflar, raqamlar, pastki chiziqlar yoki chiziqlardan iborat to'g'ri \"slug" +"\" ni kiriting." + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" +"Unicode harflari, raqamlari, pastki chiziqlari yoki chiziqlardan iborat " +"to'g'ri \"slug\" ni kiriting." + +msgid "Enter a valid IPv4 address." +msgstr "To'g'ri IPv4 manzilini kiriting." + +msgid "Enter a valid IPv6 address." +msgstr "To'g'ri IPv6 manzilini kiriting." + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "To'g'ri IPv4 yoki IPv6 manzilini kiriting." + +msgid "Enter only digits separated by commas." +msgstr "Faqat vergul bilan ajratilgan raqamlarni kiriting." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "" +"Ushbu qiymat %(limit_value)s ekanligiga ishonch hosil qiling (Hozir u " +"%(show_value)s)." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "" +"Ushbu qiymat %(limit_value)s dan kichik yoki unga teng ekanligini tekshiring." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "" +"Ushbu qiymat %(limit_value)s dan katta yoki unga teng ekanligini tekshiring." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Ushbu qiymat kamida %(limit_value)dga ega ekanligiga ishonch hosil qiling " +"(unda bor %(show_value)d)" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Ushbu qiymat eng ko'pi bilan %(limit_value)d ta belgidan iboratligiga " +"ishonch hosil qiling (hozir, %(show_value)d tadan iborat)." + +msgid "Enter a number." +msgstr "Raqamni kiriting." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "" +"Umumiy raqamlar soni %(max)s tadan ko'p bo'lmasligiga ishonch hosil qiling." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "" +"O'nlik kasr xonalari %(max)s tadan ko'p bo'lmasligiga ishonch hosil qiling." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"O'nli kasr nuqtasidan oldin %(max)s tadan ko'p raqam bo'lmasligiga ishonch " +"hosil qiling." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"\"%(extension)s\" fayl kengaytmasiga ruxsat berilmagan Ruxsat berilgan " +"kengaytmalar: %(allowed_extensions)s." + +msgid "Null characters are not allowed." +msgstr "Bo'shliq belgilaridan foydalanish mumkin emas." + +msgid "and" +msgstr "va" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(field_labels)s bilan %(model_name)s allaqachon mavjud." + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "%(value)r qiymati to'g'ri tanlov emas." + +msgid "This field cannot be null." +msgstr "Bu maydon bo‘shliq belgisidan iborat bo'lishi mumkin emas." + +msgid "This field cannot be blank." +msgstr "Bu maydon bo‘sh bo‘lishi mumkin emas." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "\"%(field_label)s\" %(model_name)s allaqachon mavjud." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s %(date_field_label)s %(lookup_type)s uchun noyob bo'lishi " +"kerak." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Maydon turi: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "\"%(value)s\" qiymati rost yoki yolg'on bo'lishi kerak." + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" +"\"%(value)s\" qiymati Rost, Yolg'on yoki Bo'shliq belgisidan iborat bo'lishi " +"kerak." + +msgid "Boolean (Either True or False)" +msgstr "Mantiqiy (Rost yoki Yolg'on)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Birikma uzunligi (%(max_length)s gacha)" + +msgid "Comma-separated integers" +msgstr "Vergul bilan ajratilgan butun sonlar" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" +"\"%(value)s\" qiymati yaroqsiz sana formatiga ega. U YYYY-MM-DD formatida " +"bo'lishi kerak." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" +"\"%(value)s\" qiymati to'g'ri formatga (YYYY-MM-DD) ega, ammo bu noto'g'ri " +"sana." + +msgid "Date (without time)" +msgstr "Sana (vaqtsiz)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"\"%(value)s\" qiymati noto'g'ri formatga ega. U YYYY-MM-DD HH: MM [: ss [." +"uuuuuu]] [TZ] formatida bo'lishi kerak." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"\"%(value)s\" qiymati to'g'ri formatga ega (YYYY-MM-DD HH: MM [: ss [." +"uuuuuu]] [TZ]), lekin u noto'g'ri sana / vaqt." + +msgid "Date (with time)" +msgstr "Sana (vaqt bilan)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "\"%(value)s\" qiymati o'nlik kasr sonlardan iborat bo'lishi kerak." + +msgid "Decimal number" +msgstr "O'nli kasr son" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"\"%(value)s\" qiymati noto'g'ri formatga ega. U [DD] [[HH:] MM:] ss [." +"uuuuuu] formatida bo'lishi kerak." + +msgid "Duration" +msgstr "Davomiyligi" + +msgid "Email address" +msgstr "Elektron pochta manzili" + +msgid "File path" +msgstr "Fayl manzili" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "\"%(value)s\" qiymati haqiqiy son bo'lishi kerak." + +msgid "Floating point number" +msgstr "Haqiqiy son" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "\"%(value)s\" qiymati butun son bo'lishi kerak." + +msgid "Integer" +msgstr "Butun son" + +msgid "Big (8 byte) integer" +msgstr "Katta (8 bayt) butun son" + +msgid "IPv4 address" +msgstr "IPv4 manzili" + +msgid "IP address" +msgstr "IP manzili" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "\"%(value)s\" qiymati Yo‘q, To‘g‘ri yoki Noto'g'ri bo'lishi kerak." + +msgid "Boolean (Either True, False or None)" +msgstr "Boolean (To'g'ri, Yolg'on yoki Hech biri)" + +msgid "Positive big integer" +msgstr "Musbat katta butun son" + +msgid "Positive integer" +msgstr "Ijobiy butun son" + +msgid "Positive small integer" +msgstr "Musbat kichik butun son" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug uzunligi (%(max_length)s gacha)" + +msgid "Small integer" +msgstr "Kichik butun son" + +msgid "Text" +msgstr "Matn" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" +"\"%(value)s\" qiymati noto'g'ri formatga ega. U HH: MM [: ss [.uuuuuu]] " +"formatida bo'lishi kerak." + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" +"\"%(value)s\" qiymati to'g'ri formatga ega (HH: MM [: ss [.uuuuuu]]), lekin " +"bu noto'g'ri vaqt." + +msgid "Time" +msgstr "Vaqt" + +msgid "URL" +msgstr "URL manzili" + +msgid "Raw binary data" +msgstr "Tartibsiz Ikkilik ma'lumotlar" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "\"%(value)s\" to'g'ri UUID emas." + +msgid "Universally unique identifier" +msgstr "Umum noyob aniqlovchi" + +msgid "File" +msgstr "Fayl" + +msgid "Image" +msgstr "Rasm" + +msgid "A JSON object" +msgstr "JSON ob'ekti" + +msgid "Value must be valid JSON." +msgstr "Qiymat yaroqli JSON bo'lishi kerak." + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(field)s %(value)r lari bilan %(model)s namunasi uchun mavjud emas." + +msgid "Foreign Key (type determined by related field)" +msgstr "Tashqi kalit (turi aloqador maydon tomonidan belgilanadi)" + +msgid "One-to-one relationship" +msgstr "Birga-bir yago munosabat" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s -%(to)s gacha bo'lgan munosabat" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s -%(to)s gacha bo'lgan munosabatlar" + +msgid "Many-to-many relationship" +msgstr "Ko'pchilikka-ko'pchilik munosabatlar" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Ushbu maydon to'ldirilishi shart." + +msgid "Enter a whole number." +msgstr "Butun raqamni kiriting." + +msgid "Enter a valid date." +msgstr "Sanani to‘g‘ri kiriting." + +msgid "Enter a valid time." +msgstr "Vaqtni to‘g‘ri kiriting." + +msgid "Enter a valid date/time." +msgstr "Sana/vaqtni to‘g‘ri kiriting." + +msgid "Enter a valid duration." +msgstr "Muddatni to'g'ri kiriting." + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "Kunlar soni {min_days} va {max_days} orasida bo'lishi kerak." + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Hech qanday fayl yuborilmadi. Formadagi kodlash turini tekshiring." + +msgid "No file was submitted." +msgstr "Hech qanday fayl yuborilmadi." + +msgid "The submitted file is empty." +msgstr "Yuborilgan etilgan fayl bo'sh." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "" +"Fayl nomi maksimum %(max)d belgilardan ko'p emasligiga ishonch hosil qiling " +"(hozir %(length)d belgi ishlatilgan)." + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "" +"Iltimos, faylni yuboring yoki katachani belgilang, lekin ikkalasinimas." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"To'g'ri rasmni yuklang. Siz yuklagan fayl yoki rasm emas yoki buzilgan rasm " +"edi." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "To'g'ri tanlovni tanlang. %(value)s mavjud tanlovlardan biri emas." + +msgid "Enter a list of values." +msgstr "Qiymatlar ro'yxatini kiriting." + +msgid "Enter a complete value." +msgstr "To'liq qiymatni kiriting." + +msgid "Enter a valid UUID." +msgstr "To'g'ri UUID kiriting." + +msgid "Enter a valid JSON." +msgstr "Yaroqli JSONni kiriting." + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Yashirilgan maydon %(name)s) %(error)s" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "ManagementForm ma'lumotlari yo'q yoki o'zgartirilgan" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "Iltimos, %d ta yoki kamroq forma topshiring." + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "Iltimos, %d ta yoki ko'proq forma topshiring." + +msgid "Order" +msgstr "Buyurtma" + +msgid "Delete" +msgstr "Yo'q qilish" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Iltimos, %(field)s uchun takroriy ma'lumotni tuzating." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "" +"Iltimos, noyob bo'lishi kerak bo'lgan %(field)s uchun takroriy ma'lumotlarni " +"to'g'rilang." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Iltimos, %(field_name)s uchun takroriy ma'lumotlarni %(date_field)s ga noyob " +"bo'la oladigan %(lookup)s ichidagi ma'lumotlarni moslab to'g'rilang." + +msgid "Please correct the duplicate values below." +msgstr "Iltimos, quyidagi takroriy qiymatlarni to'g'irlang." + +msgid "The inline value did not match the parent instance." +msgstr "Kiritilgan ichki qiymat ajdod misoliga mos kelmaydi." + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "To'g'ri tanlovni tanlang. Bu tanlov mavjud tanlovlardan biri emas." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "\"%(pk)s\" to'g'ri qiymat emas." + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s vaqtni %(current_timezone)s mintaqa talqinida ifodalab " +"bo'lmadi; u noaniq yoki mavjud bo'lmasligi mumkin." + +msgid "Clear" +msgstr "Aniq" + +msgid "Currently" +msgstr "Hozirda" + +msgid "Change" +msgstr "O'zgartirish" + +msgid "Unknown" +msgstr "Noma'lum" + +msgid "Yes" +msgstr "Ha" + +msgid "No" +msgstr "Yo'q" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "ha,yo'q,ehtimol" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)dbayt" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "kechqurun" + +msgid "a.m." +msgstr "ertalab" + +msgid "PM" +msgstr "Kechqurun" + +msgid "AM" +msgstr "Ertalab" + +msgid "midnight" +msgstr "yarim tunda" + +msgid "noon" +msgstr "peshin" + +msgid "Monday" +msgstr "Dushanba" + +msgid "Tuesday" +msgstr "Seshanba" + +msgid "Wednesday" +msgstr "Chorshanba" + +msgid "Thursday" +msgstr "Payshanba" + +msgid "Friday" +msgstr "Juma" + +msgid "Saturday" +msgstr "Shanba" + +msgid "Sunday" +msgstr "Yakshanba" + +msgid "Mon" +msgstr "Dush" + +msgid "Tue" +msgstr "Sesh" + +msgid "Wed" +msgstr "Chor" + +msgid "Thu" +msgstr "Pay" + +msgid "Fri" +msgstr "Jum" + +msgid "Sat" +msgstr "Shan" + +msgid "Sun" +msgstr "Yak" + +msgid "January" +msgstr "Yanvar" + +msgid "February" +msgstr "Fevral" + +msgid "March" +msgstr "Mart" + +msgid "April" +msgstr "Aprel" + +msgid "May" +msgstr "May" + +msgid "June" +msgstr "Iyun" + +msgid "July" +msgstr "Iyul" + +msgid "August" +msgstr "Avgust" + +msgid "September" +msgstr "Sentabr" + +msgid "October" +msgstr "Oktabr" + +msgid "November" +msgstr "Noyabr" + +msgid "December" +msgstr "Dekabr" + +msgid "jan" +msgstr "yan" + +msgid "feb" +msgstr "fev" + +msgid "mar" +msgstr "mar" + +msgid "apr" +msgstr "apr" + +msgid "may" +msgstr "may" + +msgid "jun" +msgstr "iyn" + +msgid "jul" +msgstr "iyl" + +msgid "aug" +msgstr "avg" + +msgid "sep" +msgstr "sen" + +msgid "oct" +msgstr "okt" + +msgid "nov" +msgstr "noy" + +msgid "dec" +msgstr "dek" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Yan," + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Fev." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Mart" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Aprel" + +msgctxt "abbrev. month" +msgid "May" +msgstr "May" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Iyun" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Iyul" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Avg." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Sen." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Okt." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Noy." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Dek." + +msgctxt "alt. month" +msgid "January" +msgstr "Yanvar" + +msgctxt "alt. month" +msgid "February" +msgstr "Fevral" + +msgctxt "alt. month" +msgid "March" +msgstr "Mart" + +msgctxt "alt. month" +msgid "April" +msgstr "Aprel" + +msgctxt "alt. month" +msgid "May" +msgstr "May" + +msgctxt "alt. month" +msgid "June" +msgstr "Iyun" + +msgctxt "alt. month" +msgid "July" +msgstr "Iyul" + +msgctxt "alt. month" +msgid "August" +msgstr "Avgust" + +msgctxt "alt. month" +msgid "September" +msgstr "Sentabr" + +msgctxt "alt. month" +msgid "October" +msgstr "Oktabr" + +msgctxt "alt. month" +msgid "November" +msgstr "Noyabr" + +msgctxt "alt. month" +msgid "December" +msgstr "Dekabr" + +msgid "This is not a valid IPv6 address." +msgstr "Bu to'g'ri IPv6 manzili emas." + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s…" + +msgid "or" +msgstr "yoki" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "," + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%dyil" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%doy" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%dhafta" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%dkun" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%dsoat" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%dminut" + +msgid "Forbidden" +msgstr "Taqiqlangan" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF tekshiruvi amalga oshmadi. So‘rov bekor qilindi." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"Siz ushbu xabarni ko'rmoqdasiz, chunki bu HTTPS saytida veb-brauzeringiz " +"tomonidan \"Referer header\" yuborilishi talab qilinadi, ammo hech biri " +"yuborilmadi. Ushbu sarlavha xavfsizlik nuqtai nazaridan, brauzeringizni " +"uchinchi shaxslar tomonidan o'g'irlanmasligini ta'minlash uchun talab " +"qilinadi." + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"Agar siz \"Referer\" sarlavhalarini o'chirib qo'yish uchun brauzeringizni " +"sozlagan bo'lsangiz, iltimos, hech bo'lmasa ushbu sayt uchun, HTTPS " +"ulanishlari, yoki \"same-origin\" so'rovlari uchun ularni qayta yoqib " +"qo'ying." + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"Agar siz yorlig'idan yoki " +"\"Referrer-Policy: no-referer\" sarlavhasidan foydalanayotgan bo'lsangiz, " +"iltimos ularni olib tashlang. CSRF himoyasi \"Referer\" sarlavhasini " +"havolalarni qat'iy tekshirishni talab qiladi. Agar maxfiyligingiz haqida " +"xavotirda bo'lsangiz, uchinchi tomon saytlari kabi " +"havola alternativalaridan foydalaning." + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"Siz ushbu xabarni ko'rmoqdasiz, chunki ushbu sayt formalarni yuborishda CSRF " +"cookie ma'lumotlarini talab qiladi. Ushbu cookie ma'lumotlari xavfsizlik " +"nuqtai nazaridan, brauzeringizni uchinchi shaxslar tomonidan " +"o'g'irlanmasligini ta'minlash uchun xizmat qilinadi." + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"Agar siz cookie ma'lumotlarni o'chirib qo'yish uchun brauzeringizni " +"konfiguratsiya qilgan bo'lsangiz, iltimos, ushbu sayt yoki \"same-origin\" " +"so'rovlari uchun ularni qayta yoqib qo'ying." + +msgid "More information is available with DEBUG=True." +msgstr "Qo'shimcha ma'lumotlarni DEBUG = True ifodasi bilan ko'rish mumkin." + +msgid "No year specified" +msgstr "Yil ko‘rsatilmagan" + +msgid "Date out of range" +msgstr "Sana chegaradan tashqarida" + +msgid "No month specified" +msgstr "Oy ko'rsatilmagan" + +msgid "No day specified" +msgstr "Hech qanday kun ko‘rsatilmagan" + +msgid "No week specified" +msgstr "Hech qanday hafta belgilanmagan" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Hech qanday %(verbose_name_plural)s lar mavjud emas" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"Kelajak %(verbose_name_plural)s lari mavjud emas, chunki %(class_name)s." +"allow_future yolg'ondur." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" +"\"%(datestr)s\" sana birikmasi noto'g'ri berilgan. \"%(format)s\" formati " +"tavsiya etilgan" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "So'rovga mos keladigan %(verbose_name)s topilmadi" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "Sahifa \"oxirgi\" emas va uni butun songa aylantirish mumkin emas." + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Noto'g'ri sahifa (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "Bo'sh ro'yxat va \"%(class_name)s.allow_empty\" yolg'on." + +msgid "Directory indexes are not allowed here." +msgstr "Bu yerda katalog indekslaridan foydalanib bo'lmaydi." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "\"%(path)s\" mavjud emas" + +#, python-format +msgid "Index of %(directory)s" +msgstr "%(directory)s indeksi" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "Django: muddati chegaralangan perfektsionistlar uchun veb freymvork." + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"Django %(version)s uchun chiqarilgan " +"nashrlarni ko'rish" + +msgid "The install worked successfully! Congratulations!" +msgstr "O'rnatish muvaffaqiyatli amalga oshdi! Tabriklaymiz!" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" +"Siz ushbu sahifani ko'rmoqdasiz, chunki DEBUG = True ifodasi sizning sozlamalar faylingizda ko'rsatilgan va " +"siz biron bir URL manzilini to'gri sozlamagansiz." + +msgid "Django Documentation" +msgstr "Django Hujjatlari" + +msgid "Topics, references, & how-to’s" +msgstr "Mavzular, havolalar va qanday qilish yo'llari" + +msgid "Tutorial: A Polling App" +msgstr "Qo'llanma: So'rovnoma" + +msgid "Get started with Django" +msgstr "Django bilan boshlang" + +msgid "Django Community" +msgstr "Django hamjamiyati" + +msgid "Connect, get help, or contribute" +msgstr "Bog'laning, yordam oling yoki hissa qo'shing" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/uz/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/uz/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/uz/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/uz/formats.py new file mode 100644 index 0000000..2c7ee73 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/uz/formats.py @@ -0,0 +1,30 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = r"j-E, Y-\y\i\l" +TIME_FORMAT = "G:i" +DATETIME_FORMAT = r"j-E, Y-\y\i\l G:i" +YEAR_MONTH_FORMAT = r"F Y-\y\i\l" +MONTH_DAY_FORMAT = "j-E" +SHORT_DATE_FORMAT = "d.m.Y" +SHORT_DATETIME_FORMAT = "d.m.Y H:i" +FIRST_DAY_OF_WEEK = 1 # Monday + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%d.%m.%Y", # '25.10.2006' + "%d-%B, %Y-yil", # '25-Oktabr, 2006-yil' +] +DATETIME_INPUT_FORMATS = [ + "%d.%m.%Y %H:%M:%S", # '25.10.2006 14:30:59' + "%d.%m.%Y %H:%M:%S.%f", # '25.10.2006 14:30:59.000200' + "%d.%m.%Y %H:%M", # '25.10.2006 14:30' + "%d-%B, %Y-yil %H:%M:%S", # '25-Oktabr, 2006-yil 14:30:59' + "%d-%B, %Y-yil %H:%M:%S.%f", # '25-Oktabr, 2006-yil 14:30:59.000200' + "%d-%B, %Y-yil %H:%M", # '25-Oktabr, 2006-yil 14:30' +] +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "\xa0" # non-breaking space +NUMBER_GROUPING = 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/vi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/vi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..43a2a61 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/vi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/vi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/vi/LC_MESSAGES/django.po new file mode 100644 index 0000000..a0e6eb4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/vi/LC_MESSAGES/django.po @@ -0,0 +1,1234 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Claude Paroz , 2020 +# Jannis Leidel , 2011 +# Anh Phan , 2013 +# Thanh Le Viet , 2013 +# Tran , 2011 +# Tran Van , 2011,2013 +# Vuong Nguyen , 2011 +# xgenvn , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-19 20:23+0200\n" +"PO-Revision-Date: 2020-07-14 21:42+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Vietnamese (http://www.transifex.com/django/django/language/" +"vi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: vi\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Afrikaans" +msgstr "Afrikaans" + +msgid "Arabic" +msgstr "Tiếng Ả Rập" + +msgid "Algerian Arabic" +msgstr "" + +msgid "Asturian" +msgstr "Asturian" + +msgid "Azerbaijani" +msgstr "Tiếng Azerbaijan" + +msgid "Bulgarian" +msgstr "Tiếng Bun-ga-ri" + +msgid "Belarusian" +msgstr "Tiếng Bê-la-rút" + +msgid "Bengali" +msgstr "Tiếng Bengal" + +msgid "Breton" +msgstr "Tiếng Breton" + +msgid "Bosnian" +msgstr "Tiếng Bosnia" + +msgid "Catalan" +msgstr "Tiếng Catala" + +msgid "Czech" +msgstr "Tiếng Séc" + +msgid "Welsh" +msgstr "Xứ Wales" + +msgid "Danish" +msgstr "Tiếng Đan Mạch" + +msgid "German" +msgstr "Tiếng Đức" + +msgid "Lower Sorbian" +msgstr "" + +msgid "Greek" +msgstr "Tiếng Hy Lạp" + +msgid "English" +msgstr "Tiếng Anh" + +msgid "Australian English" +msgstr "Tiếng Anh ở Úc" + +msgid "British English" +msgstr "British English" + +msgid "Esperanto" +msgstr "Quốc Tế Ngữ" + +msgid "Spanish" +msgstr "Tiếng Tây Ban Nha" + +msgid "Argentinian Spanish" +msgstr "Argentinian Spanish" + +msgid "Colombian Spanish" +msgstr "" + +msgid "Mexican Spanish" +msgstr "Mexican Spanish" + +msgid "Nicaraguan Spanish" +msgstr "Tiếng Tây Ban Nha-Nicaragua" + +msgid "Venezuelan Spanish" +msgstr "Tiếng Vê-nê-du-ê-la" + +msgid "Estonian" +msgstr "Tiếng Estonia" + +msgid "Basque" +msgstr "Tiếng Baxcơ" + +msgid "Persian" +msgstr "Tiếng Ba Tư" + +msgid "Finnish" +msgstr "Tiếng Phần Lan" + +msgid "French" +msgstr "Tiếng Pháp" + +msgid "Frisian" +msgstr "Tiếng Frisco" + +msgid "Irish" +msgstr "Tiếng Ai-len" + +msgid "Scottish Gaelic" +msgstr "" + +msgid "Galician" +msgstr "Tiếng Pháp cổ" + +msgid "Hebrew" +msgstr "Tiếng Do Thái cổ" + +msgid "Hindi" +msgstr "Tiếng Hindi" + +msgid "Croatian" +msgstr "Tiếng Croatia" + +msgid "Upper Sorbian" +msgstr "" + +msgid "Hungarian" +msgstr "Tiếng Hung-ga-ri" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "Tiếng Khoa học Quốc tế" + +msgid "Indonesian" +msgstr "Tiếng In-đô-nê-xi-a" + +msgid "Igbo" +msgstr "" + +msgid "Ido" +msgstr "Ido" + +msgid "Icelandic" +msgstr "Tiếng Aixơlen" + +msgid "Italian" +msgstr "Tiếng Ý" + +msgid "Japanese" +msgstr "Tiếng Nhật Bản" + +msgid "Georgian" +msgstr "Georgian" + +msgid "Kabyle" +msgstr "" + +msgid "Kazakh" +msgstr "Tiếng Kazakh" + +msgid "Khmer" +msgstr "Tiếng Khơ-me" + +msgid "Kannada" +msgstr "Tiếng Kannada" + +msgid "Korean" +msgstr "Tiếng Hàn Quốc" + +msgid "Kyrgyz" +msgstr "" + +msgid "Luxembourgish" +msgstr "Tiếng Luxembourg" + +msgid "Lithuanian" +msgstr "Tiếng Lat-vi" + +msgid "Latvian" +msgstr "Ngôn ngữ vùng Bantic" + +msgid "Macedonian" +msgstr "Tiếng Maxêđôni" + +msgid "Malayalam" +msgstr "Tiếng Malayalam" + +msgid "Mongolian" +msgstr "Tiếng Mông Cổ" + +msgid "Marathi" +msgstr "Marathi" + +msgid "Burmese" +msgstr "My-an-ma" + +msgid "Norwegian Bokmål" +msgstr "" + +msgid "Nepali" +msgstr "Nê-pan" + +msgid "Dutch" +msgstr "Tiếng Hà Lan" + +msgid "Norwegian Nynorsk" +msgstr "Tiếng Na Uy Nynorsk" + +msgid "Ossetic" +msgstr "Ô-sét-ti-a" + +msgid "Punjabi" +msgstr "Punjabi" + +msgid "Polish" +msgstr "Tiếng Ba lan" + +msgid "Portuguese" +msgstr "Tiếng Bồ Đào Nha" + +msgid "Brazilian Portuguese" +msgstr "Brazilian Portuguese" + +msgid "Romanian" +msgstr "Tiếng Ru-ma-ni" + +msgid "Russian" +msgstr "Tiếng Nga" + +msgid "Slovak" +msgstr "Ngôn ngữ Slô-vac" + +msgid "Slovenian" +msgstr "Tiếng Slôven" + +msgid "Albanian" +msgstr "Tiếng Albania" + +msgid "Serbian" +msgstr "Tiếng Xéc-bi" + +msgid "Serbian Latin" +msgstr "Serbian Latin" + +msgid "Swedish" +msgstr "Tiếng Thụy Điển" + +msgid "Swahili" +msgstr "Xì-qua-hi-đi thuộc ngôn ngữ Bantu" + +msgid "Tamil" +msgstr "Tiếng Ta-min" + +msgid "Telugu" +msgstr "Telugu" + +msgid "Tajik" +msgstr "" + +msgid "Thai" +msgstr "Tiếng Thái" + +msgid "Turkmen" +msgstr "" + +msgid "Turkish" +msgstr "Tiếng Thổ Nhĩ Kỳ" + +msgid "Tatar" +msgstr "Tác-ta" + +msgid "Udmurt" +msgstr "Udmurt" + +msgid "Ukrainian" +msgstr "Tiếng Ukraina" + +msgid "Urdu" +msgstr "Urdu" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "Tiếng Việt Nam" + +msgid "Simplified Chinese" +msgstr "Tiếng Tàu giản thể" + +msgid "Traditional Chinese" +msgstr "Tiếng Tàu truyền thống" + +msgid "Messages" +msgstr "" + +msgid "Site Maps" +msgstr "Bản đồ trang web" + +msgid "Static Files" +msgstr "Tập tin tĩnh" + +msgid "Syndication" +msgstr "Syndication" + +msgid "That page number is not an integer" +msgstr "" + +msgid "That page number is less than 1" +msgstr "" + +msgid "That page contains no results" +msgstr "" + +msgid "Enter a valid value." +msgstr "Nhập một giá trị hợp lệ." + +msgid "Enter a valid URL." +msgstr "Nhập một URL hợp lệ." + +msgid "Enter a valid integer." +msgstr "Nhập một số nguyên hợp lệ." + +msgid "Enter a valid email address." +msgstr "Nhập địa chỉ email." + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "Nhập một địa chỉ IPv4 hợp lệ." + +msgid "Enter a valid IPv6 address." +msgstr "Nhập địa chỉ IPv6 hợp lệ" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "Nhập địa chỉ IPv4 hoặc IPv6 hợp lệ" + +msgid "Enter only digits separated by commas." +msgstr "Chỉ nhập chữ số, cách nhau bằng dấu phẩy." + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "Đảm bảo giá trị này là %(limit_value)s (nó là %(show_value)s )." + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "Đảm bảo giá trị này là nhỏ hơn hoặc bằng với %(limit_value)s ." + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "Đảm bảo giá trị này lớn hơn hoặc bằng với %(limit_value)s ." + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Giá trị này phải có ít nhất %(limit_value)d kí tự (hiện có %(show_value)d)" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"Giá trị này chỉ có tối đa %(limit_value)d kí tự (hiện có %(show_value)d)" + +msgid "Enter a number." +msgstr "Nhập một số." + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "Đảm bảo rằng tối đa không có nhiều hơn %(max)s số." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "Hãy chắc chắn rằng không có nhiều hơn %(max)s chữ số thập phân." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "" +"Hãy chắc chắn rằng không có nhiều hơn %(max)s chữ số trước dấu phẩy thập " +"phân." + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "" + +msgid "and" +msgstr "và" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "%(model_name)s với thông tin %(field_labels)s đã tồn tại" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "Giá trị %(value)r không phải là lựa chọn hợp lệ." + +msgid "This field cannot be null." +msgstr "Trường này không thể để trống." + +msgid "This field cannot be blank." +msgstr "Trường này không được để trắng." + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "%(model_name)s có %(field_label)s đã tồn tại." + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "%(field_label)s phải là duy nhất %(date_field_label)s %(lookup_type)s." + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "Trường thuộc dạng: %(field_type)s " + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "Boolean (hoặc là Đúng hoặc là Sai)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "Chuỗi (dài đến %(max_length)s ký tự )" + +msgid "Comma-separated integers" +msgstr "Các số nguyên được phân cách bằng dấu phẩy" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "Ngày (không có giờ)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "Ngày (có giờ)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "Số thập phân" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "" + +msgid "Email address" +msgstr "Địa chỉ email" + +msgid "File path" +msgstr "Đường dẫn tắt tới file" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "Giá trị dấu chấm động" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "Số nguyên" + +msgid "Big (8 byte) integer" +msgstr "Big (8 byte) integer" + +msgid "IPv4 address" +msgstr "Địa chỉ IPv4" + +msgid "IP address" +msgstr "Địa chỉ IP" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "Luận lý (Có thể Đúng, Sai hoặc Không cái nào đúng)" + +msgid "Positive big integer" +msgstr "" + +msgid "Positive integer" +msgstr "Số nguyên dương" + +msgid "Positive small integer" +msgstr "Số nguyên dương nhỏ" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug(lên đến %(max_length)s)" + +msgid "Small integer" +msgstr "Số nguyên nhỏ" + +msgid "Text" +msgstr "Đoạn văn" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "Giờ" + +msgid "URL" +msgstr "Đường dẫn URL" + +msgid "Raw binary data" +msgstr "Dữ liệu nhị phân " + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "File" + +msgid "Image" +msgstr "Image" + +msgid "A JSON object" +msgstr "" + +msgid "Value must be valid JSON." +msgstr "" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "" + +msgid "Foreign Key (type determined by related field)" +msgstr "Khóa ngoại (kiểu được xác định bởi trường liên hệ)" + +msgid "One-to-one relationship" +msgstr "Mối quan hệ một-một" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "" + +msgid "Many-to-many relationship" +msgstr "Mối quan hệ nhiều-nhiều" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "Trường này là bắt buộc." + +msgid "Enter a whole number." +msgstr "Nhập một số tổng thể." + +msgid "Enter a valid date." +msgstr "Nhập một ngày hợp lệ." + +msgid "Enter a valid time." +msgstr "Nhập một thời gian hợp lệ." + +msgid "Enter a valid date/time." +msgstr "Nhập một ngày/thời gian hợp lệ." + +msgid "Enter a valid duration." +msgstr "" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "Không có tập tin nào được gửi. Hãy kiểm tra kiểu mã hóa của biểu mẫu." + +msgid "No file was submitted." +msgstr "Không có tập tin nào được gửi." + +msgid "The submitted file is empty." +msgstr "Tập tin được gửi là rỗng." + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "Tên tệp tin có tối đa %(max)d kí tự (Hiện có %(length)d)" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "Vui lòng gửi một tập tin hoặc để ô chọn trắng, không chọn cả hai." + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "" +"Hãy tải lên một hình ảnh hợp lệ. Tập tin mà bạn đã tải không phải là hình " +"ảnh hoặc đã bị hư hỏng." + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "" +"Hãy chọn một lựa chọn hợp lệ. %(value)s không phải là một trong các lựa chọn " +"khả thi." + +msgid "Enter a list of values." +msgstr "Nhập một danh sách giá trị." + +msgid "Enter a complete value." +msgstr "" + +msgid "Enter a valid UUID." +msgstr "" + +msgid "Enter a valid JSON." +msgstr "" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(Trường ẩn %(name)s) %(error)s" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "Vui lòng đệ trình %d hoặc ít các mẫu đơn hơn." + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "" + +msgid "Order" +msgstr "Thứ tự" + +msgid "Delete" +msgstr "Xóa" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "Hãy sửa các dữ liệu trùng lặp cho %(field)s ." + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "Hãy sửa các dữ liệu trùng lặp cho %(field)s, mà phải là duy nhất." + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"Hãy sửa các dữ liệu trùng lặp cho %(field_name)s mà phải là duy nhất cho " +"%(lookup)s tại %(date_field)s ." + +msgid "Please correct the duplicate values below." +msgstr "Hãy sửa các giá trị trùng lặp dưới đây." + +msgid "The inline value did not match the parent instance." +msgstr "" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "" +"Hãy chọn một lựa chọn hợp lệ. Lựa chọn đó không phải là một trong các lựa " +"chọn khả thi." + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "Xóa" + +msgid "Currently" +msgstr "Hiện nay" + +msgid "Change" +msgstr "Thay đổi" + +msgid "Unknown" +msgstr "Chưa xác định" + +msgid "Yes" +msgstr "Có" + +msgid "No" +msgstr "Không" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "Có,Không,Có thể" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d byte" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "chiều" + +msgid "AM" +msgstr "sáng" + +msgid "midnight" +msgstr "Nửa đêm" + +msgid "noon" +msgstr "Buổi trưa" + +msgid "Monday" +msgstr "Thứ 2" + +msgid "Tuesday" +msgstr "Thứ 3" + +msgid "Wednesday" +msgstr "Thứ 4" + +msgid "Thursday" +msgstr "Thứ 5" + +msgid "Friday" +msgstr "Thứ 6" + +msgid "Saturday" +msgstr "Thứ 7" + +msgid "Sunday" +msgstr "Chủ nhật" + +msgid "Mon" +msgstr "Thứ 2" + +msgid "Tue" +msgstr "Thứ 3" + +msgid "Wed" +msgstr "Thứ 4" + +msgid "Thu" +msgstr "Thứ 5" + +msgid "Fri" +msgstr "Thứ 6" + +msgid "Sat" +msgstr "Thứ 7" + +msgid "Sun" +msgstr "Chủ nhật" + +msgid "January" +msgstr "Tháng 1" + +msgid "February" +msgstr "Tháng 2" + +msgid "March" +msgstr "Tháng 3" + +msgid "April" +msgstr "Tháng 4" + +msgid "May" +msgstr "Tháng 5" + +msgid "June" +msgstr "Tháng 6" + +msgid "July" +msgstr "Tháng 7" + +msgid "August" +msgstr "Tháng 8" + +msgid "September" +msgstr "Tháng 9" + +msgid "October" +msgstr "Tháng 10" + +msgid "November" +msgstr "Tháng 11" + +msgid "December" +msgstr "Tháng 12" + +msgid "jan" +msgstr "Tháng 1" + +msgid "feb" +msgstr "Tháng 2" + +msgid "mar" +msgstr "Tháng 3" + +msgid "apr" +msgstr "Tháng 4" + +msgid "may" +msgstr "Tháng 5" + +msgid "jun" +msgstr "Tháng 6" + +msgid "jul" +msgstr "Tháng 7" + +msgid "aug" +msgstr "Tháng 8" + +msgid "sep" +msgstr "Tháng 9" + +msgid "oct" +msgstr "Tháng 10" + +msgid "nov" +msgstr "Tháng 11" + +msgid "dec" +msgstr "Tháng 12" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "Tháng 1." + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "Tháng 2." + +msgctxt "abbrev. month" +msgid "March" +msgstr "Tháng ba" + +msgctxt "abbrev. month" +msgid "April" +msgstr "Tháng tư" + +msgctxt "abbrev. month" +msgid "May" +msgstr "Tháng năm" + +msgctxt "abbrev. month" +msgid "June" +msgstr "Tháng sáu" + +msgctxt "abbrev. month" +msgid "July" +msgstr "Tháng bảy" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "Tháng 8." + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "Tháng 9." + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "Tháng 10." + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "Tháng 11." + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "Tháng 12." + +msgctxt "alt. month" +msgid "January" +msgstr "Tháng một" + +msgctxt "alt. month" +msgid "February" +msgstr "Tháng hai" + +msgctxt "alt. month" +msgid "March" +msgstr "Tháng ba" + +msgctxt "alt. month" +msgid "April" +msgstr "Tháng tư" + +msgctxt "alt. month" +msgid "May" +msgstr "Tháng năm" + +msgctxt "alt. month" +msgid "June" +msgstr "Tháng sáu" + +msgctxt "alt. month" +msgid "July" +msgstr "Tháng bảy" + +msgctxt "alt. month" +msgid "August" +msgstr "Tháng tám" + +msgctxt "alt. month" +msgid "September" +msgstr "Tháng Chín" + +msgctxt "alt. month" +msgid "October" +msgstr "Tháng Mười" + +msgctxt "alt. month" +msgid "November" +msgstr "Tháng mười một" + +msgctxt "alt. month" +msgid "December" +msgstr "Tháng mười hai" + +msgid "This is not a valid IPv6 address." +msgstr "" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "hoặc" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d năm" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d tháng" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d tuần" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d ngày" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d giờ" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d phút" + +msgid "Forbidden" +msgstr "" + +msgid "CSRF verification failed. Request aborted." +msgstr "" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "" + +msgid "No year specified" +msgstr "Không có năm xác định" + +msgid "Date out of range" +msgstr "" + +msgid "No month specified" +msgstr "Không có tháng xác định" + +msgid "No day specified" +msgstr "Không có ngày xác định" + +msgid "No week specified" +msgstr "Không có tuần xác định" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "Không có %(verbose_name_plural)s phù hợp" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"%(verbose_name_plural)s trong tương lai không có sẵn vì %(class_name)s." +"allow_future là False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "Không có %(verbose_name)s tìm thấy phù hợp với truy vấn" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "Trang không hợp lệ (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "Tại đây không cho phép đánh số chỉ mục dành cho thư mục." + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "Index của %(directory)s" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" + +msgid "The install worked successfully! Congratulations!" +msgstr "" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" + +msgid "Django Documentation" +msgstr "" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "" + +msgid "Get started with Django" +msgstr "" + +msgid "Django Community" +msgstr "" + +msgid "Connect, get help, or contribute" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/vi/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/vi/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/vi/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/vi/formats.py new file mode 100644 index 0000000..7b76020 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/vi/formats.py @@ -0,0 +1,21 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = r"\N\gà\y d \t\há\n\g n \nă\m Y" +TIME_FORMAT = "H:i" +DATETIME_FORMAT = r"H:i \N\gà\y d \t\há\n\g n \nă\m Y" +YEAR_MONTH_FORMAT = "F Y" +MONTH_DAY_FORMAT = "j F" +SHORT_DATE_FORMAT = "d-m-Y" +SHORT_DATETIME_FORMAT = "H:i d-m-Y" +# FIRST_DAY_OF_WEEK = + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +# DATE_INPUT_FORMATS = +# TIME_INPUT_FORMATS = +# DATETIME_INPUT_FORMATS = +DECIMAL_SEPARATOR = "," +THOUSAND_SEPARATOR = "." +# NUMBER_GROUPING = diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/zh_Hans/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/zh_Hans/LC_MESSAGES/django.mo new file mode 100644 index 0000000..39927e8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/zh_Hans/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/zh_Hans/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/zh_Hans/LC_MESSAGES/django.po new file mode 100644 index 0000000..c0c6d60 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/zh_Hans/LC_MESSAGES/django.po @@ -0,0 +1,1305 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# HuanCheng Bai白宦成(Bestony) , 2017-2018 +# lanbla , 2021 +# Daniel Duan , 2013 +# Fan Xu , 2022 +# Ford Guo , 2022 +# Huanqun Yang, 2022 +# jamin M , 2019 +# Jannis Leidel , 2011 +# Kevin Sze , 2012 +# Lele Long , 2011,2015,2017 +# Le Yang , 2018 +# li beite , 2020 +# Liping Wang , 2016-2017 +# matthew Yip , 2020 +# mozillazg , 2016 +# Ronald White , 2014 +# Lemon Li , 2013 +# Ray Wang , 2017 +# slene , 2011 +# Sun Liwen , 2014 +# Suntravel Chris , 2019 +# Veoco , 2021 +# Liping Wang , 2016 +# Wentao Han , 2018 +# wolf ice , 2020 +# Xiang Yu , 2014 +# Jeff Yin , 2013 +# Zhengyang Wang , 2017 +# ced773123cfad7b4e8b79ca80f736af9, 2011-2012 +# Ziya Tang , 2018 +# 付峥 , 2018 +# Fangjiaqi77 <370358679@qq.com>, 2020 +# Kevin Sze , 2012 +# 高乐喆 , 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-25 06:49+0000\n" +"Last-Translator: 高乐喆 , 2023\n" +"Language-Team: Chinese (China) (http://www.transifex.com/django/django/" +"language/zh_CN/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_CN\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Afrikaans" +msgstr "南非荷兰语" + +msgid "Arabic" +msgstr "阿拉伯语" + +msgid "Algerian Arabic" +msgstr "阿尔及利亚的阿拉伯语" + +msgid "Asturian" +msgstr "阿斯图里亚斯" + +msgid "Azerbaijani" +msgstr "阿塞拜疆语" + +msgid "Bulgarian" +msgstr "保加利亚语" + +msgid "Belarusian" +msgstr "白俄罗斯语" + +msgid "Bengali" +msgstr "孟加拉语" + +msgid "Breton" +msgstr "布雷顿" + +msgid "Bosnian" +msgstr "波斯尼亚语" + +msgid "Catalan" +msgstr "加泰罗尼亚语" + +msgid "Central Kurdish (Sorani)" +msgstr "中部库尔德语(Sorani)" + +msgid "Czech" +msgstr "捷克语" + +msgid "Welsh" +msgstr "威尔士语" + +msgid "Danish" +msgstr "丹麦语" + +msgid "German" +msgstr "德语" + +msgid "Lower Sorbian" +msgstr "下索布" + +msgid "Greek" +msgstr "希腊语" + +msgid "English" +msgstr "英语" + +msgid "Australian English" +msgstr "澳大利亚英语" + +msgid "British English" +msgstr "英国英语" + +msgid "Esperanto" +msgstr "世界语" + +msgid "Spanish" +msgstr "西班牙语" + +msgid "Argentinian Spanish" +msgstr "阿根廷西班牙语" + +msgid "Colombian Spanish" +msgstr "哥伦比亚西班牙语" + +msgid "Mexican Spanish" +msgstr "墨西哥西班牙语" + +msgid "Nicaraguan Spanish" +msgstr "尼加拉瓜西班牙语" + +msgid "Venezuelan Spanish" +msgstr "委内瑞拉西班牙语" + +msgid "Estonian" +msgstr "爱沙尼亚语" + +msgid "Basque" +msgstr "巴斯克语" + +msgid "Persian" +msgstr "波斯语" + +msgid "Finnish" +msgstr "芬兰语" + +msgid "French" +msgstr "法语" + +msgid "Frisian" +msgstr "夫里斯兰语" + +msgid "Irish" +msgstr "爱尔兰语" + +msgid "Scottish Gaelic" +msgstr "苏格兰盖尔语" + +msgid "Galician" +msgstr "加利西亚语" + +msgid "Hebrew" +msgstr "希伯来语" + +msgid "Hindi" +msgstr "北印度语" + +msgid "Croatian" +msgstr "克罗地亚语" + +msgid "Upper Sorbian" +msgstr "上索布" + +msgid "Hungarian" +msgstr "匈牙利语" + +msgid "Armenian" +msgstr "亚美尼亚语" + +msgid "Interlingua" +msgstr "国际语" + +msgid "Indonesian" +msgstr "印尼语" + +msgid "Igbo" +msgstr "伊博" + +msgid "Ido" +msgstr "简化伊多语" + +msgid "Icelandic" +msgstr "冰岛语" + +msgid "Italian" +msgstr "意大利语" + +msgid "Japanese" +msgstr "日语" + +msgid "Georgian" +msgstr "格鲁吉亚语" + +msgid "Kabyle" +msgstr "卡拜尔语" + +msgid "Kazakh" +msgstr "哈萨克语" + +msgid "Khmer" +msgstr "高棉语" + +msgid "Kannada" +msgstr "埃纳德语" + +msgid "Korean" +msgstr "韩语" + +msgid "Kyrgyz" +msgstr "吉尔吉斯坦语" + +msgid "Luxembourgish" +msgstr "卢森堡语" + +msgid "Lithuanian" +msgstr "立陶宛语" + +msgid "Latvian" +msgstr "拉脱维亚语" + +msgid "Macedonian" +msgstr "马其顿语" + +msgid "Malayalam" +msgstr "马来亚拉姆语" + +msgid "Mongolian" +msgstr "蒙古语" + +msgid "Marathi" +msgstr "马拉地语" + +msgid "Malay" +msgstr "马来语" + +msgid "Burmese" +msgstr "缅甸语" + +msgid "Norwegian Bokmål" +msgstr "挪威博克马尔" + +msgid "Nepali" +msgstr "尼泊尔语" + +msgid "Dutch" +msgstr "荷兰语" + +msgid "Norwegian Nynorsk" +msgstr "新挪威语" + +msgid "Ossetic" +msgstr "奥塞梯语" + +msgid "Punjabi" +msgstr "旁遮普语 " + +msgid "Polish" +msgstr "波兰语" + +msgid "Portuguese" +msgstr "葡萄牙语" + +msgid "Brazilian Portuguese" +msgstr "巴西葡萄牙语" + +msgid "Romanian" +msgstr "罗马尼亚语" + +msgid "Russian" +msgstr "俄语" + +msgid "Slovak" +msgstr "斯洛伐克语" + +msgid "Slovenian" +msgstr "斯洛文尼亚语" + +msgid "Albanian" +msgstr "阿尔巴尼亚语" + +msgid "Serbian" +msgstr "塞尔维亚语" + +msgid "Serbian Latin" +msgstr "塞尔维亚拉丁语" + +msgid "Swedish" +msgstr "瑞典语" + +msgid "Swahili" +msgstr "斯瓦西里语" + +msgid "Tamil" +msgstr "泰米尔语" + +msgid "Telugu" +msgstr "泰卢固语" + +msgid "Tajik" +msgstr "塔吉克语" + +msgid "Thai" +msgstr "泰语" + +msgid "Turkmen" +msgstr "土库曼人" + +msgid "Turkish" +msgstr "土耳其语" + +msgid "Tatar" +msgstr "鞑靼语" + +msgid "Udmurt" +msgstr "乌德穆尔特语" + +msgid "Ukrainian" +msgstr "乌克兰语" + +msgid "Urdu" +msgstr "乌尔都语" + +msgid "Uzbek" +msgstr "乌兹别克语" + +msgid "Vietnamese" +msgstr "越南语" + +msgid "Simplified Chinese" +msgstr "简体中文" + +msgid "Traditional Chinese" +msgstr "繁体中文" + +msgid "Messages" +msgstr "消息" + +msgid "Site Maps" +msgstr "站点地图" + +msgid "Static Files" +msgstr "静态文件" + +msgid "Syndication" +msgstr "联合" + +#. Translators: String used to replace omitted page numbers in elided page +#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. +msgid "…" +msgstr "…" + +msgid "That page number is not an integer" +msgstr "页码不是整数" + +msgid "That page number is less than 1" +msgstr "页码小于 1" + +msgid "That page contains no results" +msgstr "本页结果为空" + +msgid "Enter a valid value." +msgstr "输入一个有效的值。" + +msgid "Enter a valid URL." +msgstr "输入一个有效的 URL。" + +msgid "Enter a valid integer." +msgstr "输入一个有效的整数。" + +msgid "Enter a valid email address." +msgstr "输入一个有效的 Email 地址。" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "输入由字母,数字,下划线或连字符号组成的有效“字段”。" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "输入由Unicode字母,数字,下划线或连字符号组成的有效“字段”。" + +msgid "Enter a valid IPv4 address." +msgstr "输入一个有效的 IPv4 地址。" + +msgid "Enter a valid IPv6 address." +msgstr "输入一个有效的 IPv6 地址。" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "输入一个有效的 IPv4 或 IPv6 地址." + +msgid "Enter only digits separated by commas." +msgstr "只能输入用逗号分隔的数字。" + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "确保该值为 %(limit_value)s (现在为 %(show_value)s)。" + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "确保该值小于或等于%(limit_value)s。" + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "确保该值大于或等于%(limit_value)s。" + +#, python-format +msgid "Ensure this value is a multiple of step size %(limit_value)s." +msgstr "确保该值是步长的倍数%(limit_value)s" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"确保该变量至少包含 %(limit_value)d 字符(目前字符数 %(show_value)d)。" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"确保该变量包含不超过 %(limit_value)d 字符 (目前字符数 %(show_value)d)。" + +msgid "Enter a number." +msgstr "输入一个数字。" + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "确认总共不超过 %(max)s 个数字." + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "确认小数不超过 %(max)s 位." + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "确认小数点前不超过 %(max)s 位。" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" +"文件扩展“%(extension)s”是不被允许。允许的扩展为:%(allowed_extensions)s。" + +msgid "Null characters are not allowed." +msgstr "不允许是用空字符串。" + +msgid "and" +msgstr "和" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "包含 %(field_labels)s 的 %(model_name)s 已经存在。" + +#, python-format +msgid "Constraint “%(name)s” is violated." +msgstr "约束 “%(name)s” 是无效的" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "值 %(value)r 不是有效选项。" + +msgid "This field cannot be null." +msgstr "这个值不能为 null。" + +msgid "This field cannot be blank." +msgstr "此字段不能为空。" + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "具有 %(field_label)s 的 %(model_name)s 已存在。" + +#. Translators: The 'lookup_type' is one of 'date', 'year' or +#. 'month'. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "" +"%(field_label)s 必须在 %(date_field_label)s 字段查找类型为 %(lookup_type)s 中" +"唯一。" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "字段类型:%(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "“%(value)s”的值应该为True或False" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "“%(value)s”的值应该为True,False或None" + +msgid "Boolean (Either True or False)" +msgstr "布尔值( True或False )" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "字符串(最长 %(max_length)s 位)" + +msgid "String (unlimited)" +msgstr "字符串(无限)" + +msgid "Comma-separated integers" +msgstr "逗号分隔的整数" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "“%(value)s”的值有一个错误的日期格式。它的格式应该是YYYY-MM-DD" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "“%(value)s”的值有正确的格式(YYYY-MM-DD)但它是一个错误的日期" + +msgid "Date (without time)" +msgstr "日期(不带时分)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" +"“%(value)s”的值有一个错误的日期格式。它的格式应该是YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] " + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" +"“%(value)s”的值有正确的格式 (YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) 但它是一个错" +"误的日期/时间" + +msgid "Date (with time)" +msgstr "日期(带时分)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "“%(value)s”的值应该是一个十进制数字。" + +msgid "Decimal number" +msgstr "小数" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" +"“%(value)s”的值有一个错误的格式。它的格式应该是[DD] [[HH:]MM:]ss[.uuuuuu] " + +msgid "Duration" +msgstr "时长" + +msgid "Email address" +msgstr "Email 地址" + +msgid "File path" +msgstr "文件路径" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "“%(value)s”的值应该是一个浮点数" + +msgid "Floating point number" +msgstr "浮点数" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "“%(value)s”的值应该是一个整型" + +msgid "Integer" +msgstr "整数" + +msgid "Big (8 byte) integer" +msgstr "大整数(8字节)" + +msgid "Small integer" +msgstr "小整数" + +msgid "IPv4 address" +msgstr "IPv4 地址" + +msgid "IP address" +msgstr "IP 地址" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "“%(value)s”的值应该是None、True或False" + +msgid "Boolean (Either True, False or None)" +msgstr "布尔值(True、False或None)" + +msgid "Positive big integer" +msgstr "正大整数" + +msgid "Positive integer" +msgstr "正整数" + +msgid "Positive small integer" +msgstr "正小整数" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "Slug (多达 %(max_length)s)" + +msgid "Text" +msgstr "文本" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "“%(value)s”的值有一个错误的格式。它的格式应该是HH:MM[:ss[.uuuuuu]]" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "“%(value)s”的值有正确的格式(HH:MM[:ss[.uuuuuu]]),但它是一个错误的时间" + +msgid "Time" +msgstr "时间" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "原始二进制数据" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "“%(value)s”不是一个有效的UUID" + +msgid "Universally unique identifier" +msgstr "通用唯一识别码" + +msgid "File" +msgstr "文件" + +msgid "Image" +msgstr "图像" + +msgid "A JSON object" +msgstr "一个JSON对象" + +msgid "Value must be valid JSON." +msgstr "值必须是有效的JSON。" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "包含%(field)s %(value)r的%(model)s实例不存在。" + +msgid "Foreign Key (type determined by related field)" +msgstr "外键(由相关字段确定)" + +msgid "One-to-one relationship" +msgstr "一对一关系" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s关系" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s关系" + +msgid "Many-to-many relationship" +msgstr "多对多关系" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "这个字段是必填项。" + +msgid "Enter a whole number." +msgstr "输入整数。" + +msgid "Enter a valid date." +msgstr "输入一个有效的日期。" + +msgid "Enter a valid time." +msgstr "输入一个有效的时间。" + +msgid "Enter a valid date/time." +msgstr "输入一个有效的日期/时间。" + +msgid "Enter a valid duration." +msgstr "请输入有效的时长。" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "天数应该在 {min_days} 和 {max_days} 之间。" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "未提交文件。请检查表单的编码类型。" + +msgid "No file was submitted." +msgstr "没有提交文件。" + +msgid "The submitted file is empty." +msgstr "所提交的是空文件。" + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "确保该文件名长度不超过 %(max)d 字符(目前字符数 %(length)d)。" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "请提交文件或勾选清除复选框,两者其一即可。" + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "请上传一张有效的图片。您所上传的文件不是图片或者是已损坏的图片。" + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "选择一个有效的选项。 %(value)s 不在可用的选项中。" + +msgid "Enter a list of values." +msgstr "输入一系列值。" + +msgid "Enter a complete value." +msgstr "请输入完整的值。" + +msgid "Enter a valid UUID." +msgstr "请输入有效UUID。" + +msgid "Enter a valid JSON." +msgstr "输入一个有效的JSON。" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(隐藏字段 %(name)s) %(error)s" + +#, python-format +msgid "" +"ManagementForm data is missing or has been tampered with. Missing fields: " +"%(field_names)s. You may need to file a bug report if the issue persists." +msgstr "" +"ManagementForm 数据缺失或被篡改。缺少的字段: %(field_names)s。如果问题持续存" +"在,你可能需要提交错误报告。" + +#, python-format +msgid "Please submit at most %(num)d form." +msgid_plural "Please submit at most %(num)d forms." +msgstr[0] "请最多提交 %(num)d 个表单。" + +#, python-format +msgid "Please submit at least %(num)d form." +msgid_plural "Please submit at least %(num)d forms." +msgstr[0] "请至少提交 %(num)d 个表单。" + +msgid "Order" +msgstr "排序" + +msgid "Delete" +msgstr "删除" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "请修改%(field)s的重复数据" + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "请修改%(field)s的重复数据.这个字段必须唯一" + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"请修正%(field_name)s的重复数据。%(date_field)s %(lookup)s 在 %(field_name)s " +"必须保证唯一." + +msgid "Please correct the duplicate values below." +msgstr "请修正重复的数据." + +msgid "The inline value did not match the parent instance." +msgstr "内联值与父实例不匹配。" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "选择一个有效的选项: 该选择不在可用的选项中。" + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "“%(pk)s”不是一个有效的值" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" +"%(datetime)s无法在时区%(current_timezone)s被解析;它可能是模糊的,也可能是不" +"存在的。" + +msgid "Clear" +msgstr "清除" + +msgid "Currently" +msgstr "目前" + +msgid "Change" +msgstr "修改" + +msgid "Unknown" +msgstr "未知" + +msgid "Yes" +msgstr "是" + +msgid "No" +msgstr "否" + +#. Translators: Please do not add spaces around commas. +msgid "yes,no,maybe" +msgstr "是、否、也许" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d 字节" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "午夜" + +msgid "noon" +msgstr "中午" + +msgid "Monday" +msgstr "星期一" + +msgid "Tuesday" +msgstr "星期二" + +msgid "Wednesday" +msgstr "星期三" + +msgid "Thursday" +msgstr "星期四" + +msgid "Friday" +msgstr "星期五" + +msgid "Saturday" +msgstr "星期六" + +msgid "Sunday" +msgstr "星期日" + +msgid "Mon" +msgstr "星期一" + +msgid "Tue" +msgstr "星期二" + +msgid "Wed" +msgstr "星期三" + +msgid "Thu" +msgstr "星期四" + +msgid "Fri" +msgstr "星期五" + +msgid "Sat" +msgstr "星期六" + +msgid "Sun" +msgstr "星期日" + +msgid "January" +msgstr "一月" + +msgid "February" +msgstr "二月" + +msgid "March" +msgstr "三月" + +msgid "April" +msgstr "四月" + +msgid "May" +msgstr "五月" + +msgid "June" +msgstr "六月" + +msgid "July" +msgstr "七月" + +msgid "August" +msgstr "八月" + +msgid "September" +msgstr "九月" + +msgid "October" +msgstr "十月" + +msgid "November" +msgstr "十一月" + +msgid "December" +msgstr "十二月" + +msgid "jan" +msgstr "一月" + +msgid "feb" +msgstr "二月" + +msgid "mar" +msgstr "三月" + +msgid "apr" +msgstr "四月" + +msgid "may" +msgstr "五月" + +msgid "jun" +msgstr "六月" + +msgid "jul" +msgstr "七月" + +msgid "aug" +msgstr "八月" + +msgid "sep" +msgstr "九月" + +msgid "oct" +msgstr "十月" + +msgid "nov" +msgstr "十一月" + +msgid "dec" +msgstr "十二月" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "一月" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "二月" + +msgctxt "abbrev. month" +msgid "March" +msgstr "三月" + +msgctxt "abbrev. month" +msgid "April" +msgstr "四月" + +msgctxt "abbrev. month" +msgid "May" +msgstr "五月" + +msgctxt "abbrev. month" +msgid "June" +msgstr "六月" + +msgctxt "abbrev. month" +msgid "July" +msgstr "七月" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "八月" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "九月" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "十月" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "十一月" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "十二月" + +msgctxt "alt. month" +msgid "January" +msgstr "一月" + +msgctxt "alt. month" +msgid "February" +msgstr "二月" + +msgctxt "alt. month" +msgid "March" +msgstr "三月" + +msgctxt "alt. month" +msgid "April" +msgstr "四月" + +msgctxt "alt. month" +msgid "May" +msgstr "五月" + +msgctxt "alt. month" +msgid "June" +msgstr "六月" + +msgctxt "alt. month" +msgid "July" +msgstr "七月" + +msgctxt "alt. month" +msgid "August" +msgstr "八月" + +msgctxt "alt. month" +msgid "September" +msgstr "九月" + +msgctxt "alt. month" +msgid "October" +msgstr "十月" + +msgctxt "alt. month" +msgid "November" +msgstr "十一月" + +msgctxt "alt. month" +msgid "December" +msgstr "十二月" + +msgid "This is not a valid IPv6 address." +msgstr "该值不是合法的IPv6地址。" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "%(truncated_text)s..." + +msgid "or" +msgstr "或" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr "," + +#, python-format +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d 年" + +#, python-format +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d 月" + +#, python-format +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d 周" + +#, python-format +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d 日" + +#, python-format +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d 小时" + +#, python-format +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d 分钟" + +msgid "Forbidden" +msgstr "禁止访问" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF验证失败. 请求被中断." + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" +"您看到此消息是由于HTTPS站点需要您的浏览器发送 'Referer header',但是该信息并" +"未被发送。出于安全原因,此HTTP头是必需的,以确保您的浏览器不会被第三方劫持。" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" +"如果您已将浏览器配置为禁用“ Referer”头,请重新启用它们,至少针对此站点,或" +"HTTPS连接或“同源”请求。" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" +"如果您使用的是标签或包" +"含“Referrer-Policy: no-referrer”的HTTP头,请将其删除。CSRF保护要求“Referer”头" +"执行严格的Referer检查。如果你担心隐私问题,可以使用类似这样的替代方法链接到第三方网站。" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"您看到此消息是由于该站点在提交表单时需要一个CSRF cookie。此项是出于安全考虑," +"以确保您的浏览器没有被第三方劫持。" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" +"如果您已将浏览器配置为禁用cookie,请重新启用它们,至少针对此站点或“同源”请" +"求。" + +msgid "More information is available with DEBUG=True." +msgstr "更多可用信息请设置选项DEBUG=True。" + +msgid "No year specified" +msgstr "没有指定年" + +msgid "Date out of range" +msgstr "日期超出范围。" + +msgid "No month specified" +msgstr "没有指定月" + +msgid "No day specified" +msgstr "没有指定天" + +msgid "No week specified" +msgstr "没有指定周" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "%(verbose_name_plural)s 可用" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"因为 %(class_name)s.allow_future 设置为 False,所以特性 " +"%(verbose_name_plural)s 不可用。" + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "日期字符串“%(datestr)s”与格式“%(format)s”不匹配" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "没有找到符合查询的 %(verbose_name)s" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "页面不是最后一页,也不能被转为整数型" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "非法页面 (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "列表是空的并且“%(class_name)s.allow_empty”是False" + +msgid "Directory indexes are not allowed here." +msgstr "这里不允许目录索引" + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "”%(path)s\"不存在" + +#, python-format +msgid "Index of %(directory)s" +msgstr "%(directory)s的索引" + +msgid "The install worked successfully! Congratulations!" +msgstr "" +"安装成功!\n" +"祝贺!" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"查看 Django %(version)s 的 release notes " + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not " +"configured any URLs." +msgstr "" +"您现在看见这个页面,因为您设置了 DEBUG=True 并且您还没有配置任何URLs。" + +msgid "Django Documentation" +msgstr "Django 文档" + +msgid "Topics, references, & how-to’s" +msgstr "主题,参考资料和操作方法" + +msgid "Tutorial: A Polling App" +msgstr "教程:投票应用" + +msgid "Get started with Django" +msgstr "开始使用 Django" + +msgid "Django Community" +msgstr "Django 社区" + +msgid "Connect, get help, or contribute" +msgstr "联系,获取帮助,贡献代码" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/zh_Hans/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/zh_Hans/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/zh_Hans/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/zh_Hans/formats.py new file mode 100644 index 0000000..79936f8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/zh_Hans/formats.py @@ -0,0 +1,42 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "Y年n月j日" # 2016年9月5日 +TIME_FORMAT = "H:i" # 20:45 +DATETIME_FORMAT = "Y年n月j日 H:i" # 2016年9月5日 20:45 +YEAR_MONTH_FORMAT = "Y年n月" # 2016年9月 +MONTH_DAY_FORMAT = "m月j日" # 9月5日 +SHORT_DATE_FORMAT = "Y年n月j日" # 2016年9月5日 +SHORT_DATETIME_FORMAT = "Y年n月j日 H:i" # 2016年9月5日 20:45 +FIRST_DAY_OF_WEEK = 1 # 星期一 (Monday) + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%Y/%m/%d", # '2016/09/05' + "%Y-%m-%d", # '2016-09-05' + "%Y年%n月%j日", # '2016年9月5日' +] + +TIME_INPUT_FORMATS = [ + "%H:%M", # '20:45' + "%H:%M:%S", # '20:45:29' + "%H:%M:%S.%f", # '20:45:29.000200' +] + +DATETIME_INPUT_FORMATS = [ + "%Y/%m/%d %H:%M", # '2016/09/05 20:45' + "%Y-%m-%d %H:%M", # '2016-09-05 20:45' + "%Y年%n月%j日 %H:%M", # '2016年9月5日 14:45' + "%Y/%m/%d %H:%M:%S", # '2016/09/05 20:45:29' + "%Y-%m-%d %H:%M:%S", # '2016-09-05 20:45:29' + "%Y年%n月%j日 %H:%M:%S", # '2016年9月5日 20:45:29' + "%Y/%m/%d %H:%M:%S.%f", # '2016/09/05 20:45:29.000200' + "%Y-%m-%d %H:%M:%S.%f", # '2016-09-05 20:45:29.000200' + "%Y年%n月%j日 %H:%n:%S.%f", # '2016年9月5日 20:45:29.000200' +] + +DECIMAL_SEPARATOR = "." +THOUSAND_SEPARATOR = "" +NUMBER_GROUPING = 4 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/zh_Hant/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/zh_Hant/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b6726c5 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/zh_Hant/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/zh_Hant/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/zh_Hant/LC_MESSAGES/django.po new file mode 100644 index 0000000..61d827a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/zh_Hant/LC_MESSAGES/django.po @@ -0,0 +1,1218 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Chen Chun-Chia , 2015 +# Eric Ho , 2013 +# ilay , 2012 +# Jannis Leidel , 2011 +# mail6543210 , 2013 +# ming hsien tzang , 2011 +# tcc , 2011 +# Tzu-ping Chung , 2016-2017 +# Yeh-Yung , 2013 +# Yeh-Yung , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-27 22:40+0200\n" +"PO-Revision-Date: 2019-11-05 00:38+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Chinese (Taiwan) (http://www.transifex.com/django/django/" +"language/zh_TW/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_TW\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Afrikaans" +msgstr "南非語" + +msgid "Arabic" +msgstr "阿拉伯語" + +msgid "Asturian" +msgstr "阿斯圖里亞斯語" + +msgid "Azerbaijani" +msgstr "亞塞拜然語" + +msgid "Bulgarian" +msgstr "保加利亞語" + +msgid "Belarusian" +msgstr "白俄羅斯語" + +msgid "Bengali" +msgstr "孟加拉語" + +msgid "Breton" +msgstr "布列塔尼語" + +msgid "Bosnian" +msgstr "波士尼亞語" + +msgid "Catalan" +msgstr "加泰隆語" + +msgid "Czech" +msgstr "捷克語" + +msgid "Welsh" +msgstr "威爾斯語" + +msgid "Danish" +msgstr "丹麥語" + +msgid "German" +msgstr "德語" + +msgid "Lower Sorbian" +msgstr "下索布語" + +msgid "Greek" +msgstr "希臘語" + +msgid "English" +msgstr "英語" + +msgid "Australian English" +msgstr "澳大利亞英語" + +msgid "British English" +msgstr "英國英語" + +msgid "Esperanto" +msgstr "世界語" + +msgid "Spanish" +msgstr "西班牙語" + +msgid "Argentinian Spanish" +msgstr "阿根廷西班牙語" + +msgid "Colombian Spanish" +msgstr "哥倫比亞西班牙語" + +msgid "Mexican Spanish" +msgstr "墨西哥西班牙語" + +msgid "Nicaraguan Spanish" +msgstr "尼加拉瓜西班牙語" + +msgid "Venezuelan Spanish" +msgstr "委內瑞拉西班牙語" + +msgid "Estonian" +msgstr "愛沙尼亞語" + +msgid "Basque" +msgstr "巴斯克語" + +msgid "Persian" +msgstr "波斯語" + +msgid "Finnish" +msgstr "芬蘭語" + +msgid "French" +msgstr "法語" + +msgid "Frisian" +msgstr "菲士蘭語" + +msgid "Irish" +msgstr "愛爾蘭語" + +msgid "Scottish Gaelic" +msgstr "蘇格蘭蓋爾語" + +msgid "Galician" +msgstr "加利西亞語" + +msgid "Hebrew" +msgstr "希伯來語" + +msgid "Hindi" +msgstr "印地語" + +msgid "Croatian" +msgstr "克羅埃西亞語" + +msgid "Upper Sorbian" +msgstr "上索布語" + +msgid "Hungarian" +msgstr "匈牙利語" + +msgid "Armenian" +msgstr "" + +msgid "Interlingua" +msgstr "國際語" + +msgid "Indonesian" +msgstr "印尼語" + +msgid "Ido" +msgstr "伊多語" + +msgid "Icelandic" +msgstr "冰島語" + +msgid "Italian" +msgstr "義大利語" + +msgid "Japanese" +msgstr "日語" + +msgid "Georgian" +msgstr "喬治亞語" + +msgid "Kabyle" +msgstr "卡拜爾語" + +msgid "Kazakh" +msgstr "哈薩克語" + +msgid "Khmer" +msgstr "高棉語" + +msgid "Kannada" +msgstr "康納達語" + +msgid "Korean" +msgstr "韓語" + +msgid "Luxembourgish" +msgstr "盧森堡語" + +msgid "Lithuanian" +msgstr "立陶宛語" + +msgid "Latvian" +msgstr "拉脫維亞語" + +msgid "Macedonian" +msgstr "馬其頓語" + +msgid "Malayalam" +msgstr "馬拉雅拉姆語" + +msgid "Mongolian" +msgstr "蒙古語" + +msgid "Marathi" +msgstr "馬拉提語" + +msgid "Burmese" +msgstr "緬甸語" + +msgid "Norwegian Bokmål" +msgstr "書面挪威語" + +msgid "Nepali" +msgstr "尼泊爾語" + +msgid "Dutch" +msgstr "荷蘭語" + +msgid "Norwegian Nynorsk" +msgstr "新挪威語" + +msgid "Ossetic" +msgstr "奧塞梯語" + +msgid "Punjabi" +msgstr "旁遮普語" + +msgid "Polish" +msgstr "波蘭語" + +msgid "Portuguese" +msgstr "葡萄牙語" + +msgid "Brazilian Portuguese" +msgstr "巴西葡萄牙語" + +msgid "Romanian" +msgstr "羅馬尼亞語" + +msgid "Russian" +msgstr "俄語" + +msgid "Slovak" +msgstr "斯洛伐克語" + +msgid "Slovenian" +msgstr "斯洛維尼亞語" + +msgid "Albanian" +msgstr "阿爾巴尼亞語" + +msgid "Serbian" +msgstr "塞爾維亞語" + +msgid "Serbian Latin" +msgstr "塞爾維亞拉丁語" + +msgid "Swedish" +msgstr "瑞典語" + +msgid "Swahili" +msgstr "斯瓦希里語" + +msgid "Tamil" +msgstr "坦米爾語" + +msgid "Telugu" +msgstr "泰盧固語" + +msgid "Thai" +msgstr "泰語" + +msgid "Turkish" +msgstr "土耳其語" + +msgid "Tatar" +msgstr "韃靼語" + +msgid "Udmurt" +msgstr "烏德穆爾特語" + +msgid "Ukrainian" +msgstr "烏克蘭語" + +msgid "Urdu" +msgstr "烏爾都語" + +msgid "Uzbek" +msgstr "" + +msgid "Vietnamese" +msgstr "越南語" + +msgid "Simplified Chinese" +msgstr "簡體中文" + +msgid "Traditional Chinese" +msgstr "繁體中文" + +msgid "Messages" +msgstr "訊息" + +msgid "Site Maps" +msgstr "網站地圖" + +msgid "Static Files" +msgstr "靜態文件" + +msgid "Syndication" +msgstr "聯播" + +msgid "That page number is not an integer" +msgstr "該頁碼並非整數" + +msgid "That page number is less than 1" +msgstr "該頁碼小於 1" + +msgid "That page contains no results" +msgstr "該頁未包含任何內容" + +msgid "Enter a valid value." +msgstr "請輸入有效的值。" + +msgid "Enter a valid URL." +msgstr "請輸入有效的 URL。" + +msgid "Enter a valid integer." +msgstr "請輸入有效的整數。" + +msgid "Enter a valid email address." +msgstr "請輸入有效的電子郵件地址。" + +#. Translators: "letters" means latin letters: a-z and A-Z. +msgid "" +"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." +msgstr "" + +msgid "" +"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " +"hyphens." +msgstr "" + +msgid "Enter a valid IPv4 address." +msgstr "請輸入有效的 IPv4 位址。" + +msgid "Enter a valid IPv6 address." +msgstr "請輸入有效的 IPv6 位址。" + +msgid "Enter a valid IPv4 or IPv6 address." +msgstr "請輸入有效的 IPv4 或 IPv6 位址。" + +msgid "Enter only digits separated by commas." +msgstr "請輸入以逗號分隔的數字。" + +#, python-format +msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)." +msgstr "請確認這個值是否為 %(limit_value)s (目前是 %(show_value)s)。" + +#, python-format +msgid "Ensure this value is less than or equal to %(limit_value)s." +msgstr "請確認此數值是否小於或等於 %(limit_value)s。" + +#, python-format +msgid "Ensure this value is greater than or equal to %(limit_value)s." +msgstr "請確認此數值是否大於或等於 %(limit_value)s。" + +#, python-format +msgid "" +"Ensure this value has at least %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at least %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"請確認這個值至少包含 %(limit_value)d 個字 (目前為 %(show_value)d 個字)。" + +#, python-format +msgid "" +"Ensure this value has at most %(limit_value)d character (it has " +"%(show_value)d)." +msgid_plural "" +"Ensure this value has at most %(limit_value)d characters (it has " +"%(show_value)d)." +msgstr[0] "" +"請確認這個值至多包含 %(limit_value)d 個字 (目前為 %(show_value)d 個字)。" + +msgid "Enter a number." +msgstr "輸入一個數字" + +#, python-format +msgid "Ensure that there are no more than %(max)s digit in total." +msgid_plural "Ensure that there are no more than %(max)s digits in total." +msgstr[0] "請確認數字全長不超過 %(max)s 位。" + +#, python-format +msgid "Ensure that there are no more than %(max)s decimal place." +msgid_plural "Ensure that there are no more than %(max)s decimal places." +msgstr[0] "請確認十進位數字不多於 %(max)s 位。" + +#, python-format +msgid "" +"Ensure that there are no more than %(max)s digit before the decimal point." +msgid_plural "" +"Ensure that there are no more than %(max)s digits before the decimal point." +msgstr[0] "請確認小數點前不多於 %(max)s 位。" + +#, python-format +msgid "" +"File extension “%(extension)s” is not allowed. Allowed extensions are: " +"%(allowed_extensions)s." +msgstr "" + +msgid "Null characters are not allowed." +msgstr "不允許空(null)字元。" + +msgid "and" +msgstr "和" + +#, python-format +msgid "%(model_name)s with this %(field_labels)s already exists." +msgstr "這個 %(field_labels)s 在 %(model_name)s 已經存在。" + +#, python-format +msgid "Value %(value)r is not a valid choice." +msgstr "數值 %(value)r 不是有效的選擇。" + +msgid "This field cannot be null." +msgstr "這個值不能是 null。" + +msgid "This field cannot be blank." +msgstr "這個欄位不能留白。" + +#, python-format +msgid "%(model_name)s with this %(field_label)s already exists." +msgstr "這個 %(field_label)s 在 %(model_name)s 已經存在。" + +#. Translators: The 'lookup_type' is one of 'date', 'year' or 'month'. +#. Eg: "Title must be unique for pub_date year" +#, python-format +msgid "" +"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s." +msgstr "%(field_label)s 在 %(date_field_label)s %(lookup_type)s 上必須唯一。" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "欄位型態: %(field_type)s" + +#, python-format +msgid "“%(value)s” value must be either True or False." +msgstr "" + +#, python-format +msgid "“%(value)s” value must be either True, False, or None." +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "布林值 (True 或 False)" + +#, python-format +msgid "String (up to %(max_length)s)" +msgstr "字串 (至多 %(max_length)s 個字)" + +msgid "Comma-separated integers" +msgstr "逗號分隔的整數" + +#, python-format +msgid "" +"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid " +"date." +msgstr "" + +msgid "Date (without time)" +msgstr "日期 (不包括時間)" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[." +"uuuuuu]][TZ] format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]" +"[TZ]) but it is an invalid date/time." +msgstr "" + +msgid "Date (with time)" +msgstr "日期 (包括時間)" + +#, python-format +msgid "“%(value)s” value must be a decimal number." +msgstr "" + +msgid "Decimal number" +msgstr "十進位數" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[." +"uuuuuu] format." +msgstr "" + +msgid "Duration" +msgstr "時間長" + +msgid "Email address" +msgstr "電子郵件地址" + +msgid "File path" +msgstr "檔案路徑" + +#, python-format +msgid "“%(value)s” value must be a float." +msgstr "" + +msgid "Floating point number" +msgstr "浮點數" + +#, python-format +msgid "“%(value)s” value must be an integer." +msgstr "" + +msgid "Integer" +msgstr "整數" + +msgid "Big (8 byte) integer" +msgstr "大整數 (8 位元組)" + +msgid "IPv4 address" +msgstr "IPv4 地址" + +msgid "IP address" +msgstr "IP 位址" + +#, python-format +msgid "“%(value)s” value must be either None, True or False." +msgstr "" + +msgid "Boolean (Either True, False or None)" +msgstr "布林值 (True, False 或 None)" + +msgid "Positive integer" +msgstr "正整數" + +msgid "Positive small integer" +msgstr "正小整數" + +#, python-format +msgid "Slug (up to %(max_length)s)" +msgstr "可讀網址 (長度最多 %(max_length)s)" + +msgid "Small integer" +msgstr "小整數" + +msgid "Text" +msgstr "文字" + +#, python-format +msgid "" +"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] " +"format." +msgstr "" + +#, python-format +msgid "" +"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an " +"invalid time." +msgstr "" + +msgid "Time" +msgstr "時間" + +msgid "URL" +msgstr "URL" + +msgid "Raw binary data" +msgstr "原始二進制數據" + +#, python-format +msgid "“%(value)s” is not a valid UUID." +msgstr "" + +msgid "Universally unique identifier" +msgstr "" + +msgid "File" +msgstr "檔案" + +msgid "Image" +msgstr "影像" + +#, python-format +msgid "%(model)s instance with %(field)s %(value)r does not exist." +msgstr "%(field)s 為 %(value)r 的 %(model)s 物件不存在。" + +msgid "Foreign Key (type determined by related field)" +msgstr "外鍵 (型態由關連欄位決定)" + +msgid "One-to-one relationship" +msgstr "一對一關連" + +#, python-format +msgid "%(from)s-%(to)s relationship" +msgstr "%(from)s-%(to)s 關連" + +#, python-format +msgid "%(from)s-%(to)s relationships" +msgstr "%(from)s-%(to)s 關連" + +msgid "Many-to-many relationship" +msgstr "多對多關連" + +#. Translators: If found as last label character, these punctuation +#. characters will prevent the default label_suffix to be appended to the +#. label +msgid ":?.!" +msgstr ":?.!" + +msgid "This field is required." +msgstr "這個欄位是必須的。" + +msgid "Enter a whole number." +msgstr "輸入整數" + +msgid "Enter a valid date." +msgstr "輸入有效的日期" + +msgid "Enter a valid time." +msgstr "輸入有效的時間" + +msgid "Enter a valid date/time." +msgstr "輸入有效的日期/時間" + +msgid "Enter a valid duration." +msgstr "輸入有效的時間長。" + +#, python-brace-format +msgid "The number of days must be between {min_days} and {max_days}." +msgstr "" + +msgid "No file was submitted. Check the encoding type on the form." +msgstr "沒有檔案被送出。請檢查表單的編碼類型。" + +msgid "No file was submitted." +msgstr "沒有檔案送出" + +msgid "The submitted file is empty." +msgstr "送出的檔案是空的。" + +#, python-format +msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." +msgid_plural "" +"Ensure this filename has at most %(max)d characters (it has %(length)d)." +msgstr[0] "請確認這個檔名至多包含 %(max)d 個字 (目前為 %(length)d)。" + +msgid "Please either submit a file or check the clear checkbox, not both." +msgstr "請提交一個檔案或確認清除核可項, 不能兩者都做。" + +msgid "" +"Upload a valid image. The file you uploaded was either not an image or a " +"corrupted image." +msgstr "上傳一個有效的圖檔。你上傳的檔案為非圖片,不然就是損壞的圖檔。" + +#, python-format +msgid "Select a valid choice. %(value)s is not one of the available choices." +msgstr "請選擇有效的項目, %(value)s 不是一個可用的選擇。" + +msgid "Enter a list of values." +msgstr "請輸入一個列表的值。" + +msgid "Enter a complete value." +msgstr "請輸入完整的值。" + +msgid "Enter a valid UUID." +msgstr "請輸入有效的 UUID。" + +#. Translators: This is the default suffix added to form field labels +msgid ":" +msgstr ":" + +#, python-format +msgid "(Hidden field %(name)s) %(error)s" +msgstr "(隱藏欄位 %(name)s) %(error)s" + +msgid "ManagementForm data is missing or has been tampered with" +msgstr "ManagementForm 資料缺失或遭竄改" + +#, python-format +msgid "Please submit %d or fewer forms." +msgid_plural "Please submit %d or fewer forms." +msgstr[0] "請送出不多於 %d 個表單。" + +#, python-format +msgid "Please submit %d or more forms." +msgid_plural "Please submit %d or more forms." +msgstr[0] "請送出多於 %d 個表單。" + +msgid "Order" +msgstr "排序" + +msgid "Delete" +msgstr "刪除" + +#, python-format +msgid "Please correct the duplicate data for %(field)s." +msgstr "請修正 %(field)s 的重覆資料" + +#, python-format +msgid "Please correct the duplicate data for %(field)s, which must be unique." +msgstr "請修正 %(field)s 的重覆資料, 必須為唯一值" + +#, python-format +msgid "" +"Please correct the duplicate data for %(field_name)s which must be unique " +"for the %(lookup)s in %(date_field)s." +msgstr "" +"請修正 %(field_name)s 重複資料, %(date_field)s 的 %(lookup)s 必須是唯一值。" + +msgid "Please correct the duplicate values below." +msgstr "請修正下方重覆的數值" + +msgid "The inline value did not match the parent instance." +msgstr "內含的外鍵無法連接到對應的上層實體。" + +msgid "Select a valid choice. That choice is not one of the available choices." +msgstr "選擇有效的選項: 此選擇不在可用的選項中。" + +#, python-format +msgid "“%(pk)s” is not a valid value." +msgstr "" + +#, python-format +msgid "" +"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it " +"may be ambiguous or it may not exist." +msgstr "" + +msgid "Clear" +msgstr "清除" + +msgid "Currently" +msgstr "目前" + +msgid "Change" +msgstr "變更" + +msgid "Unknown" +msgstr "未知" + +msgid "Yes" +msgstr "是" + +msgid "No" +msgstr "否" + +msgid "Year" +msgstr "" + +msgid "Month" +msgstr "" + +msgid "Day" +msgstr "" + +msgid "yes,no,maybe" +msgstr "是、否、也許" + +#, python-format +msgid "%(size)d byte" +msgid_plural "%(size)d bytes" +msgstr[0] "%(size)d 位元組" + +#, python-format +msgid "%s KB" +msgstr "%s KB" + +#, python-format +msgid "%s MB" +msgstr "%s MB" + +#, python-format +msgid "%s GB" +msgstr "%s GB" + +#, python-format +msgid "%s TB" +msgstr "%s TB" + +#, python-format +msgid "%s PB" +msgstr "%s PB" + +msgid "p.m." +msgstr "p.m." + +msgid "a.m." +msgstr "a.m." + +msgid "PM" +msgstr "PM" + +msgid "AM" +msgstr "AM" + +msgid "midnight" +msgstr "午夜" + +msgid "noon" +msgstr "中午" + +msgid "Monday" +msgstr "星期一" + +msgid "Tuesday" +msgstr "星期二" + +msgid "Wednesday" +msgstr "星期三" + +msgid "Thursday" +msgstr "星期四" + +msgid "Friday" +msgstr "星期五" + +msgid "Saturday" +msgstr "星期六" + +msgid "Sunday" +msgstr "星期日" + +msgid "Mon" +msgstr "星期一" + +msgid "Tue" +msgstr "星期二" + +msgid "Wed" +msgstr "星期三" + +msgid "Thu" +msgstr "星期四" + +msgid "Fri" +msgstr "星期五" + +msgid "Sat" +msgstr "星期六" + +msgid "Sun" +msgstr "星期日" + +msgid "January" +msgstr "一月" + +msgid "February" +msgstr "二月" + +msgid "March" +msgstr "三月" + +msgid "April" +msgstr "四月" + +msgid "May" +msgstr "五月" + +msgid "June" +msgstr "六月" + +msgid "July" +msgstr "七月" + +msgid "August" +msgstr "八月" + +msgid "September" +msgstr "九月" + +msgid "October" +msgstr "十月" + +msgid "November" +msgstr "十一月" + +msgid "December" +msgstr "十二月" + +msgid "jan" +msgstr "一月" + +msgid "feb" +msgstr "二月" + +msgid "mar" +msgstr "三月" + +msgid "apr" +msgstr "四月" + +msgid "may" +msgstr "五月" + +msgid "jun" +msgstr "六月" + +msgid "jul" +msgstr "七月" + +msgid "aug" +msgstr "八月" + +msgid "sep" +msgstr "九月" + +msgid "oct" +msgstr "十月" + +msgid "nov" +msgstr "十一月" + +msgid "dec" +msgstr "十二月" + +msgctxt "abbrev. month" +msgid "Jan." +msgstr "一月" + +msgctxt "abbrev. month" +msgid "Feb." +msgstr "二月" + +msgctxt "abbrev. month" +msgid "March" +msgstr "三月" + +msgctxt "abbrev. month" +msgid "April" +msgstr "四月" + +msgctxt "abbrev. month" +msgid "May" +msgstr "五月" + +msgctxt "abbrev. month" +msgid "June" +msgstr "六月" + +msgctxt "abbrev. month" +msgid "July" +msgstr "七月" + +msgctxt "abbrev. month" +msgid "Aug." +msgstr "八月" + +msgctxt "abbrev. month" +msgid "Sept." +msgstr "九月" + +msgctxt "abbrev. month" +msgid "Oct." +msgstr "十月" + +msgctxt "abbrev. month" +msgid "Nov." +msgstr "十一月" + +msgctxt "abbrev. month" +msgid "Dec." +msgstr "十二月" + +msgctxt "alt. month" +msgid "January" +msgstr "一月" + +msgctxt "alt. month" +msgid "February" +msgstr "二月" + +msgctxt "alt. month" +msgid "March" +msgstr "三月" + +msgctxt "alt. month" +msgid "April" +msgstr "四月" + +msgctxt "alt. month" +msgid "May" +msgstr "五月" + +msgctxt "alt. month" +msgid "June" +msgstr "六月" + +msgctxt "alt. month" +msgid "July" +msgstr "七月" + +msgctxt "alt. month" +msgid "August" +msgstr "八月" + +msgctxt "alt. month" +msgid "September" +msgstr "九月" + +msgctxt "alt. month" +msgid "October" +msgstr "十月" + +msgctxt "alt. month" +msgid "November" +msgstr "十一月" + +msgctxt "alt. month" +msgid "December" +msgstr "十二月" + +msgid "This is not a valid IPv6 address." +msgstr "這是無效的 IPv6 位址。" + +#, python-format +msgctxt "String to return when truncating text" +msgid "%(truncated_text)s…" +msgstr "" + +msgid "or" +msgstr "或" + +#. Translators: This string is used as a separator between list elements +msgid ", " +msgstr ", " + +#, python-format +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d 年" + +#, python-format +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d 月" + +#, python-format +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d 週" + +#, python-format +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d 日" + +#, python-format +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d 時" + +#, python-format +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d 分" + +msgid "0 minutes" +msgstr "0 分" + +msgid "Forbidden" +msgstr "禁止" + +msgid "CSRF verification failed. Request aborted." +msgstr "CSRF 驗證失敗。已中止請求。" + +msgid "" +"You are seeing this message because this HTTPS site requires a “Referer " +"header” to be sent by your Web browser, but none was sent. This header is " +"required for security reasons, to ensure that your browser is not being " +"hijacked by third parties." +msgstr "" + +msgid "" +"If you have configured your browser to disable “Referer” headers, please re-" +"enable them, at least for this site, or for HTTPS connections, or for “same-" +"origin” requests." +msgstr "" + +msgid "" +"If you are using the tag or " +"including the “Referrer-Policy: no-referrer” header, please remove them. The " +"CSRF protection requires the “Referer” header to do strict referer checking. " +"If you’re concerned about privacy, use alternatives like for links to third-party sites." +msgstr "" + +msgid "" +"You are seeing this message because this site requires a CSRF cookie when " +"submitting forms. This cookie is required for security reasons, to ensure " +"that your browser is not being hijacked by third parties." +msgstr "" +"你看到這個訊息,是因為這個網站要求在送出表單包含一個 CSRF cookie。這個 " +"cookie 是用於安全用途,保護你的瀏覽器不被第三方挾持。" + +msgid "" +"If you have configured your browser to disable cookies, please re-enable " +"them, at least for this site, or for “same-origin” requests." +msgstr "" + +msgid "More information is available with DEBUG=True." +msgstr "設定 DEBUG=True 以獲得更多資訊。" + +msgid "No year specified" +msgstr "不指定年份" + +msgid "Date out of range" +msgstr "日期超過範圍" + +msgid "No month specified" +msgstr "不指定月份" + +msgid "No day specified" +msgstr "不指定日期" + +msgid "No week specified" +msgstr "不指定週數" + +#, python-format +msgid "No %(verbose_name_plural)s available" +msgstr "%(verbose_name_plural)s 無法使用" + +#, python-format +msgid "" +"Future %(verbose_name_plural)s not available because %(class_name)s." +"allow_future is False." +msgstr "" +"未來的 %(verbose_name_plural)s 不可用,因 %(class_name)s.allow_future 為 " +"False." + +#, python-format +msgid "Invalid date string “%(datestr)s” given format “%(format)s”" +msgstr "" + +#, python-format +msgid "No %(verbose_name)s found matching the query" +msgstr "無 %(verbose_name)s 符合本次搜尋" + +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#, python-format +msgid "Invalid page (%(page_number)s): %(message)s" +msgstr "無效的頁面 (%(page_number)s): %(message)s" + +#, python-format +msgid "Empty list and “%(class_name)s.allow_empty” is False." +msgstr "" + +msgid "Directory indexes are not allowed here." +msgstr "這裡不允許目錄索引。" + +#, python-format +msgid "“%(path)s” does not exist" +msgstr "" + +#, python-format +msgid "Index of %(directory)s" +msgstr "%(directory)s 的索引" + +msgid "Django: the Web framework for perfectionists with deadlines." +msgstr "Django:為有時間壓力的完美主義者設計的網站框架。" + +#, python-format +msgid "" +"View release notes for Django %(version)s" +msgstr "" +"查看 Django %(version)s 的發行筆記" + +msgid "The install worked successfully! Congratulations!" +msgstr "安裝成功!恭喜!" + +#, python-format +msgid "" +"You are seeing this page because DEBUG=True is in your settings file and you have not configured any " +"URLs." +msgstr "" +"你看到這個訊息,是因為你在 Django 設定檔中包含 DEBUG = True,且尚未配置任何網址。開始工作吧!" + +msgid "Django Documentation" +msgstr "Django 文件" + +msgid "Topics, references, & how-to’s" +msgstr "" + +msgid "Tutorial: A Polling App" +msgstr "教學:投票應用" + +msgid "Get started with Django" +msgstr "初學 Django" + +msgid "Django Community" +msgstr "Django 社群" + +msgid "Connect, get help, or contribute" +msgstr "聯繫、求助、貢獻" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/zh_Hant/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/zh_Hant/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/zh_Hant/formats.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/zh_Hant/formats.py new file mode 100644 index 0000000..79936f8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/locale/zh_Hant/formats.py @@ -0,0 +1,42 @@ +# This file is distributed under the same license as the Django package. +# +# The *_FORMAT strings use the Django date format syntax, +# see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date +DATE_FORMAT = "Y年n月j日" # 2016年9月5日 +TIME_FORMAT = "H:i" # 20:45 +DATETIME_FORMAT = "Y年n月j日 H:i" # 2016年9月5日 20:45 +YEAR_MONTH_FORMAT = "Y年n月" # 2016年9月 +MONTH_DAY_FORMAT = "m月j日" # 9月5日 +SHORT_DATE_FORMAT = "Y年n月j日" # 2016年9月5日 +SHORT_DATETIME_FORMAT = "Y年n月j日 H:i" # 2016年9月5日 20:45 +FIRST_DAY_OF_WEEK = 1 # 星期一 (Monday) + +# The *_INPUT_FORMATS strings use the Python strftime format syntax, +# see https://docs.python.org/library/datetime.html#strftime-strptime-behavior +DATE_INPUT_FORMATS = [ + "%Y/%m/%d", # '2016/09/05' + "%Y-%m-%d", # '2016-09-05' + "%Y年%n月%j日", # '2016年9月5日' +] + +TIME_INPUT_FORMATS = [ + "%H:%M", # '20:45' + "%H:%M:%S", # '20:45:29' + "%H:%M:%S.%f", # '20:45:29.000200' +] + +DATETIME_INPUT_FORMATS = [ + "%Y/%m/%d %H:%M", # '2016/09/05 20:45' + "%Y-%m-%d %H:%M", # '2016-09-05 20:45' + "%Y年%n月%j日 %H:%M", # '2016年9月5日 14:45' + "%Y/%m/%d %H:%M:%S", # '2016/09/05 20:45:29' + "%Y-%m-%d %H:%M:%S", # '2016-09-05 20:45:29' + "%Y年%n月%j日 %H:%M:%S", # '2016年9月5日 20:45:29' + "%Y/%m/%d %H:%M:%S.%f", # '2016/09/05 20:45:29.000200' + "%Y-%m-%d %H:%M:%S.%f", # '2016-09-05 20:45:29.000200' + "%Y年%n月%j日 %H:%n:%S.%f", # '2016年9月5日 20:45:29.000200' +] + +DECIMAL_SEPARATOR = "." +THOUSAND_SEPARATOR = "" +NUMBER_GROUPING = 4 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/project_template/manage.py-tpl b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/project_template/manage.py-tpl new file mode 100755 index 0000000..a628884 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/project_template/manage.py-tpl @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', '{{ project_name }}.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/project_template/project_name/__init__.py-tpl b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/project_template/project_name/__init__.py-tpl new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/project_template/project_name/asgi.py-tpl b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/project_template/project_name/asgi.py-tpl new file mode 100644 index 0000000..a827238 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/project_template/project_name/asgi.py-tpl @@ -0,0 +1,16 @@ +""" +ASGI config for {{ project_name }} project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/{{ docs_version }}/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', '{{ project_name }}.settings') + +application = get_asgi_application() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/project_template/project_name/settings.py-tpl b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/project_template/project_name/settings.py-tpl new file mode 100644 index 0000000..3b6caab --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/project_template/project_name/settings.py-tpl @@ -0,0 +1,123 @@ +""" +Django settings for {{ project_name }} project. + +Generated by 'django-admin startproject' using Django {{ django_version }}. + +For more information on this file, see +https://docs.djangoproject.com/en/{{ docs_version }}/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/{{ docs_version }}/ref/settings/ +""" + +from pathlib import Path + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/{{ docs_version }}/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = '{{ secret_key }}' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = '{{ project_name }}.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = '{{ project_name }}.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/{{ docs_version }}/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} + + +# Password validation +# https://docs.djangoproject.com/en/{{ docs_version }}/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/{{ docs_version }}/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/{{ docs_version }}/howto/static-files/ + +STATIC_URL = 'static/' + +# Default primary key field type +# https://docs.djangoproject.com/en/{{ docs_version }}/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/project_template/project_name/urls.py-tpl b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/project_template/project_name/urls.py-tpl new file mode 100644 index 0000000..622f79e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/project_template/project_name/urls.py-tpl @@ -0,0 +1,22 @@ +""" +URL configuration for {{ project_name }} project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/{{ docs_version }}/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/project_template/project_name/wsgi.py-tpl b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/project_template/project_name/wsgi.py-tpl new file mode 100644 index 0000000..1ee28d0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/project_template/project_name/wsgi.py-tpl @@ -0,0 +1,16 @@ +""" +WSGI config for {{ project_name }} project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/{{ docs_version }}/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', '{{ project_name }}.settings') + +application = get_wsgi_application() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/urls/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/urls/__init__.py new file mode 100644 index 0000000..302f68d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/urls/__init__.py @@ -0,0 +1,9 @@ +from django.urls import include +from django.views import defaults + +__all__ = ["handler400", "handler403", "handler404", "handler500", "include"] + +handler400 = defaults.bad_request +handler403 = defaults.permission_denied +handler404 = defaults.page_not_found +handler500 = defaults.server_error diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/urls/i18n.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/urls/i18n.py new file mode 100644 index 0000000..6b3fe70 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/urls/i18n.py @@ -0,0 +1,39 @@ +import functools + +from django.conf import settings +from django.urls import LocalePrefixPattern, URLResolver, get_resolver, path +from django.views.i18n import set_language + + +def i18n_patterns(*urls, prefix_default_language=True): + """ + Add the language code prefix to every URL pattern within this function. + This may only be used in the root URLconf, not in an included URLconf. + """ + if not settings.USE_I18N: + return list(urls) + return [ + URLResolver( + LocalePrefixPattern(prefix_default_language=prefix_default_language), + list(urls), + ) + ] + + +@functools.cache +def is_language_prefix_patterns_used(urlconf): + """ + Return a tuple of two booleans: ( + `True` if i18n_patterns() (LocalePrefixPattern) is used in the URLconf, + `True` if the default language should be prefixed + ) + """ + for url_pattern in get_resolver(urlconf).url_patterns: + if isinstance(url_pattern.pattern, LocalePrefixPattern): + return True, url_pattern.pattern.prefix_default_language + return False, False + + +urlpatterns = [ + path("setlang/", set_language, name="set_language"), +] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/urls/static.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/urls/static.py new file mode 100644 index 0000000..8e7816e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/conf/urls/static.py @@ -0,0 +1,30 @@ +import re +from urllib.parse import urlsplit + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.urls import re_path +from django.views.static import serve + + +def static(prefix, view=serve, **kwargs): + """ + Return a URL pattern for serving files in debug mode. + + from django.conf import settings + from django.conf.urls.static import static + + urlpatterns = [ + # ... the rest of your URLconf goes here ... + ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + """ + if not prefix: + raise ImproperlyConfigured("Empty static prefix not permitted") + elif not settings.DEBUG or urlsplit(prefix).netloc: + # No-op if not in debug mode or a non-local prefix. + return [] + return [ + re_path( + r"^%s(?P.*)$" % re.escape(prefix.lstrip("/")), view, kwargs=kwargs + ), + ] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/apps.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/apps.py new file mode 100644 index 0000000..e79dc89 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/apps.py @@ -0,0 +1,7 @@ +from django.apps import AppConfig +from django.utils.translation import gettext_lazy as _ + + +class AdminDocsConfig(AppConfig): + name = "django.contrib.admindocs" + verbose_name = _("Administrative Documentation") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/af/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/af/LC_MESSAGES/django.mo new file mode 100644 index 0000000..43410e7 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/af/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/af/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/af/LC_MESSAGES/django.po new file mode 100644 index 0000000..6074aa0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/af/LC_MESSAGES/django.po @@ -0,0 +1,268 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Charl du Plessis , 2021 +# F Wolff , 2019,2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2023-12-04 20:19+0000\n" +"Last-Translator: F Wolff , 2019,2023\n" +"Language-Team: Afrikaans (http://app.transifex.com/django/django/language/" +"af/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: af\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Administratiewe dokumentasie" + +msgid "Home" +msgstr "Tuisblad" + +msgid "Documentation" +msgstr "Dokumentasie" + +msgid "Bookmarklets" +msgstr "" + +msgid "Documentation bookmarklets" +msgstr "" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "Dokumentasie vir dié bladsy" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Neem jou van enige bladsy na die dokumentasie vir die vertooning wat daardie " +"bladsy genereer." + +msgid "Tags" +msgstr "Etikette" + +msgid "List of all the template tags and their functions." +msgstr "Lys van alle templaat tags en hulle funksies." + +msgid "Filters" +msgstr "Filters" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Elke bladsy op die publieke werf word gegenereer deur 'n vertoning. Die " +"vertoning definiëer watter templaat word gebruik om die bladsy te genereer " +"en watter objekte is beskikbaar aan daardie templaat." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "Installeer asseblief docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Die admin dokumentasie stelsel benodig Python se docutils biblioteek." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Vra asseblief jou administrateurs om docutils te " +"installeer." + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "Velde" + +msgid "Field" +msgstr "Veld" + +msgid "Type" +msgstr "Tipe" + +msgid "Description" +msgstr "Beskrywing" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "Terug na Model dokumentasie" + +msgid "Model documentation" +msgstr "Model dokumentasie" + +msgid "Model groups" +msgstr "Model groepe" + +msgid "Templates" +msgstr "Template" + +#, python-format +msgid "Template: %(name)s" +msgstr "Templaat: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Templaat: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "" + +msgid "(does not exist)" +msgstr "(bestaan nie)" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "" + +msgid "filter:" +msgstr "" + +msgid "view:" +msgstr "" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "" + +msgid "model:" +msgstr "" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "" + +#, python-format +msgid "all %s" +msgstr "alle %s" + +#, python-format +msgid "number of %s" +msgstr "" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ar/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ar/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7a45097 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ar/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ar/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ar/LC_MESSAGES/django.po new file mode 100644 index 0000000..05d5370 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ar/LC_MESSAGES/django.po @@ -0,0 +1,278 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bashar Al-Abdulhadi, 2015-2016,2021 +# Bashar Al-Abdulhadi, 2014 +# Jannis Leidel , 2011 +# Muaaz Alsaied, 2020 +# Ossama Khayat , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-10-15 21:25+0000\n" +"Last-Translator: Bashar Al-Abdulhadi\n" +"Language-Team: Arabic (http://www.transifex.com/django/django/language/ar/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +msgid "Administrative Documentation" +msgstr "الوثائق الإدارية" + +msgid "Home" +msgstr "الرئيسية" + +msgid "Documentation" +msgstr "الوثائق" + +msgid "Bookmarklets" +msgstr "أوامر المفضلة" + +msgid "Documentation bookmarklets" +msgstr "أوامر مفضلة الوثائق" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"لتثبيت أوامر المفضلة، اسحب الرابط إلى المواقع المفضلة في شريط الأدوات الخاص " +"بك، أو إضغط بزر الماوس الأيمن على الرابط وأضفه إلى قائمة المواقع المفضلة " +"الخاصة بك. الآن يمكنك اختيار أوامر المفضلة من أي صفحة في الموقع." + +msgid "Documentation for this page" +msgstr "الوثائق لهذه الصفحة" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "ينتقل بك من أي صفحة إلى وثائق العرض الذي أنشأ هذه الصفحة." + +msgid "Tags" +msgstr "الوسوم" + +msgid "List of all the template tags and their functions." +msgstr "قائمة بجميع وسوم القوالب ووظائفهم." + +msgid "Filters" +msgstr "الفلاتر" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"المرشحات هي الإجراءات التي يمكن تطبيقها على المتغيرات في قالب لتغيير الناتج." + +msgid "Models" +msgstr "النماذج" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"الموديلات هي وصف لجميع الكائنات في النظام والحقول المرتبطة بها. كل موديول " +"يحتوي على قائمة الحقول التي يمكن الوصول إليها كمتغيرات قالب" + +msgid "Views" +msgstr "إستعراض" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"يتم إنشاء كل صفحة على الموقع علني من خلال عرض. يعرّف العرض الذي يستخدم كقالب " +"لتوليد الصفحة والتي هي الكائنات المتاحة لذلك القالب." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "أدوات المتصفح لكي تتمكن من الوصول بسرعة وظائف المشرف." + +msgid "Please install docutils" +msgstr "الرجاء تثبيت docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"نظام توثيقات المشرف يتطلب مكتبة بايثون docutils." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "الرجاء الطلب من مشرف النظام لتنصيب docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "المودل: %(name)s" + +msgid "Fields" +msgstr "الحقول" + +msgid "Field" +msgstr "حقل" + +msgid "Type" +msgstr "نوع" + +msgid "Description" +msgstr "وصف" + +msgid "Methods with arguments" +msgstr "طُرق بمُعطيات" + +msgid "Method" +msgstr "الطريقة" + +msgid "Arguments" +msgstr "مُعطيات" + +msgid "Back to Model documentation" +msgstr "العودة إلى وثائق الموديول" + +msgid "Model documentation" +msgstr "وثائق الموديول" + +msgid "Model groups" +msgstr "مجموعات الموديول" + +msgid "Templates" +msgstr "القوالب" + +#, python-format +msgid "Template: %(name)s" +msgstr "قالب: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "قالب: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "البحث عن مسار القالب %(name)s:" + +msgid "(does not exist)" +msgstr "(غير موجود)" + +msgid "Back to Documentation" +msgstr "العودة إلى الوثائق" + +msgid "Template filters" +msgstr "مرشحات القالب" + +msgid "Template filter documentation" +msgstr "وثائق مرشح القالب" + +msgid "Built-in filters" +msgstr "المرشحات المدمجة" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"لإستخدام هذه المرشحات, الرجاء وضع %(code)s في القالب الخاص بك " +"قبل إستخدام المرشّح." + +msgid "Template tags" +msgstr "وسوم القالب" + +msgid "Template tag documentation" +msgstr "وثائق وسم القالب" + +msgid "Built-in tags" +msgstr "المسوم المدمجة" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"لإستخدام هذه الوسوم, الرجاء وضع %(code)s في القالب الخاص بك قبل " +"إستخدام الوسم." + +#, python-format +msgid "View: %(name)s" +msgstr "عرض: %(name)s" + +msgid "Context:" +msgstr "السياق:" + +msgid "Templates:" +msgstr "القوالب:" + +msgid "Back to View documentation" +msgstr "العودة إلى وثائق الفيو" + +msgid "View documentation" +msgstr "وثائق الفيو" + +msgid "Jump to namespace" +msgstr "القفز إلى مساحة الاسم" + +msgid "Empty namespace" +msgstr "مساحة إسم فارغة" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "العروض عبر مساحة الإسم %(name)s" + +msgid "Views by empty namespace" +msgstr "العروض عبر مساحة الإسم الفارغة" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +" عرض الخاصية: %(full_name)s. الإسم: %(url_name)s.\n" + +msgid "tag:" +msgstr "وسم:" + +msgid "filter:" +msgstr "مرشّح" + +msgid "view:" +msgstr "عرض:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "البرنامج %(app_label)r غير موجود" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "النموذج %(model_name)r غير موجود في التطبيق %(app_label)r" + +msgid "model:" +msgstr "نموذج:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "العنصر `%(app_label)s.%(data_type)s` المرتبط" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "عناصر `%(app_label)s.%(object_name)s` مرتبطة" + +#, python-format +msgid "all %s" +msgstr "كل %s" + +#, python-format +msgid "number of %s" +msgstr "عدد %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "يبدو أن %s ليس عنصر urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ar_DZ/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ar_DZ/LC_MESSAGES/django.mo new file mode 100644 index 0000000..541933d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ar_DZ/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ar_DZ/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ar_DZ/LC_MESSAGES/django.po new file mode 100644 index 0000000..9a32599 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ar_DZ/LC_MESSAGES/django.po @@ -0,0 +1,277 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jihad Bahmaid Al-Halki, 2022 +# Riterix , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2022-07-24 20:19+0000\n" +"Last-Translator: Jihad Bahmaid Al-Halki\n" +"Language-Team: Arabic (Algeria) (http://www.transifex.com/django/django/" +"language/ar_DZ/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar_DZ\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +msgid "Administrative Documentation" +msgstr "الوثائق الإدارية" + +msgid "Home" +msgstr "الرئيسية" + +msgid "Documentation" +msgstr "الوثائق" + +msgid "Bookmarklets" +msgstr "أوامر المفضلة" + +msgid "Documentation bookmarklets" +msgstr "أوامر مفضلة للوثائق" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"لتثبيت أوامر المفضلة، اسحب الرابط إلى المواقع المفضلة في شريط الأدوات الخاص " +"بك، أو إضغط بزر الماوس الأيمن على الرابط وأضفه إلى قائمة المواقع المفضلة " +"الخاصة بك. الآن يمكنك اختيار أوامر المفضلة من أي صفحة في الموقع." + +msgid "Documentation for this page" +msgstr "الوثائق لهذه الصفحة" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "ينتقل بك من أي صفحة إلى وثائق العرض الذي أنشأ هذه الصفحة." + +msgid "Tags" +msgstr "الوسوم" + +msgid "List of all the template tags and their functions." +msgstr "قائمة بجميع وسوم القوالب ووظائفهم." + +msgid "Filters" +msgstr "الفلاتر" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"المرشحات هي الإجراءات التي يمكن تطبيقها على المتغيرات في قالب لتغيير الناتج." + +msgid "Models" +msgstr "النماذج" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"الموديلات هي وصف لجميع الكائنات في النظام والحقول المرتبطة بها. كل موديول " +"يحتوي على قائمة الحقول التي يمكن الوصول إليها كمتغيرات قالب" + +msgid "Views" +msgstr "إستعراض" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"يتم إنشاء كل صفحة على الموقع علني من خلال عرض. يعرّف العرض الذي يستخدم كقالب " +"لتوليد الصفحة والتي هي الكائنات المتاحة لذلك القالب." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "أدوات المتصفح لكي تتمكن من الوصول بسرعة وظائف المشرف." + +msgid "Please install docutils" +msgstr "الرجاء تثبيت docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"نظام إدارة التوثيق يحتاج إلى وثيقةمن مكتبة بايثون " + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"الرجاء الطلب من مشرف النظام لتنصيب docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "المودل: %(name)s" + +msgid "Fields" +msgstr "الحقول" + +msgid "Field" +msgstr "حقل" + +msgid "Type" +msgstr "نوع" + +msgid "Description" +msgstr "وصف" + +msgid "Methods with arguments" +msgstr "طرق بمعطيات" + +msgid "Method" +msgstr "الطريقة" + +msgid "Arguments" +msgstr "معطيات" + +msgid "Back to Model documentation" +msgstr "العودة إلى وثائق الموديول" + +msgid "Model documentation" +msgstr "وثائق الموديول" + +msgid "Model groups" +msgstr "مجموعات الموديول" + +msgid "Templates" +msgstr "القوالب" + +#, python-format +msgid "Template: %(name)s" +msgstr "قالب: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "قالب: \\\"%(name)s\\\"" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "البحث عن مسار القالب \\\"%(name)s\\\":" + +msgid "(does not exist)" +msgstr "(غير موجود)" + +msgid "Back to Documentation" +msgstr "العودة إلى الوثائق" + +msgid "Template filters" +msgstr "مرشحات القالب" + +msgid "Template filter documentation" +msgstr "وثائق مرشح القالب" + +msgid "Built-in filters" +msgstr "المرشحات المدمجة" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"لإستخدام هذه المرشحات, الرجاء وضع %(code)s في القالب الخاص بك " +"قبل إستخدام المرشّح." + +msgid "Template tags" +msgstr "وسوم القالب" + +msgid "Template tag documentation" +msgstr "وثائق وسم القالب" + +msgid "Built-in tags" +msgstr "المسوم المدمجة" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"لإستخدام هذه الوسوم, الرجاء وضع %(code)s في القالب الخاص بك قبل " +"إستخدام الوسم." + +#, python-format +msgid "View: %(name)s" +msgstr "عرض: %(name)s" + +msgid "Context:" +msgstr "السياق:" + +msgid "Templates:" +msgstr "القوالب:" + +msgid "Back to View documentation" +msgstr "العودة لـ : عرض الوثائق" + +msgid "View documentation" +msgstr "عرض الوثائق" + +msgid "Jump to namespace" +msgstr "القفز إلى مساحة الاسم" + +msgid "Empty namespace" +msgstr "مساحة إسم فارغة" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "العروض عبر مساحة الإسم %(name)s" + +msgid "Views by empty namespace" +msgstr "العروض عبر مساحة الإسم الفارغة" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +" عرض الخاصية: %(full_name)s. الإسم: %(url_name)s." +"\\n\n" + +msgid "tag:" +msgstr "وسم:" + +msgid "filter:" +msgstr "مرشّح" + +msgid "view:" +msgstr "عرض:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "البرنامج %(app_label)r غير موجود" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "النموذج %(model_name)r غير موجود في التطبيق %(app_label)r" + +msgid "model:" +msgstr "نموذج:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "العنصر `%(app_label)s.%(data_type)s` المرتبط" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "عناصر `%(app_label)s.%(object_name)s` مرتبطة" + +#, python-format +msgid "all %s" +msgstr "كل %s" + +#, python-format +msgid "number of %s" +msgstr "عدد %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "يبدو أن %s ليس عنصر urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ast/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ast/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7e87432 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ast/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ast/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ast/LC_MESSAGES/django.po new file mode 100644 index 0000000..acf919c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ast/LC_MESSAGES/django.po @@ -0,0 +1,258 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ḷḷumex03 , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-20 02:41+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Asturian (http://www.transifex.com/django/django/language/" +"ast/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ast\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "" + +msgid "Documentation" +msgstr "" + +msgid "Bookmarklets" +msgstr "" + +msgid "Documentation bookmarklets" +msgstr "" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" + +msgid "Tags" +msgstr "" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "Campu" + +msgid "Type" +msgstr "Triba" + +msgid "Description" +msgstr "Descripción" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "marca:" + +msgid "filter:" +msgstr "filtru:" + +msgid "view:" +msgstr "vista:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "" + +msgid "model:" +msgstr "modelu:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "" + +#, python-format +msgid "all %s" +msgstr "" + +#, python-format +msgid "number of %s" +msgstr "" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/az/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/az/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3e0d63b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/az/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/az/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/az/LC_MESSAGES/django.po new file mode 100644 index 0000000..76156dc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/az/LC_MESSAGES/django.po @@ -0,0 +1,259 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ali Ismayilov , 2011 +# Nicat Məmmədov , 2022 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2022-07-24 20:19+0000\n" +"Last-Translator: Nicat Məmmədov \n" +"Language-Team: Azerbaijani (http://www.transifex.com/django/django/language/" +"az/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: az\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Administrativ Dokumentasiya" + +msgid "Home" +msgstr "Ev" + +msgid "Documentation" +msgstr "Sənədləşmə" + +msgid "Bookmarklets" +msgstr "Əlfəcinciklər (Bookmarklets)" + +msgid "Documentation bookmarklets" +msgstr "Sənədləşmə əlfəcincikləri (bookmarklets)" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "Bu səhifənin sənədləşməsi" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "Hər hansı səhifəni əmələ gətirən funksiyanın sənədləşməsini göstərir." + +msgid "Tags" +msgstr "" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "Filterlər" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "" + +msgid "(does not exist)" +msgstr "(mövcud deyil)" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "teq:" + +msgid "filter:" +msgstr "süzgəc:" + +msgid "view:" +msgstr "baxış:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "%(model_name)r modelini %(app_label)r tətbiqetməsində tapa bilmədik" + +msgid "model:" +msgstr "model:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "bağlı \"%(app_label)s.%(data_type)s\" obyekti" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "bağlı \"%(app_label)s.%(object_name)s\" obyektləri" + +#, python-format +msgid "all %s" +msgstr "bütün %s" + +#, python-format +msgid "number of %s" +msgstr "%s-in sayı" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s urlpattern obyekti deyil" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/be/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/be/LC_MESSAGES/django.mo new file mode 100644 index 0000000..96f61d3 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/be/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/be/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/be/LC_MESSAGES/django.po new file mode 100644 index 0000000..0da3c32 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/be/LC_MESSAGES/django.po @@ -0,0 +1,284 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Viktar Palstsiuk , 2014-2015 +# znotdead , 2016,2019,2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-01-15 17:29+0000\n" +"Last-Translator: znotdead \n" +"Language-Team: Belarusian (http://www.transifex.com/django/django/language/" +"be/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: be\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n" +"%100>=11 && n%100<=14)? 2 : 3);\n" + +msgid "Administrative Documentation" +msgstr "Адміністратыўная дакументацыя" + +msgid "Home" +msgstr "Пачатак" + +msgid "Documentation" +msgstr "Дакумэнтацыя" + +msgid "Bookmarklets" +msgstr "Закладкі" + +msgid "Documentation bookmarklets" +msgstr "Закладкі дакумэнтацыі" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Каб паставіць закладку, перацягніце спасылку на паліцу закладак або " +"пстрыкніце па спасылцы праваю кнопкаю і дадайце яе да закладак. Цяпер можна " +"абраць закладку з якой пажадаеце бачыны." + +msgid "Documentation for this page" +msgstr "Дакумэнтацыя па бачыне" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "Накіроўвае з хоць-якое бачыны да прагляду, які стварае гэтую бачыну." + +msgid "Tags" +msgstr "Цэтлікі" + +msgid "List of all the template tags and their functions." +msgstr "Спіс усіх тэгаў шаблонаў і іх функцый." + +msgid "Filters" +msgstr "Сіты" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Фільтры гэта дзеянні, якія могуць быць выкананы над пераменнымі ў шаблоне " +"каб змяніць вынік." + +msgid "Models" +msgstr "Мадэлі" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Мадэлі - гэта апісанне ўсіх аб'ектаў у сістэме і іх асацыіраваныя палі. " +"Кожная мадэль мае спіс палёў, якія могуць быць даступны як пераменная шаблону" + +msgid "Views" +msgstr "Прагляды" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Кожная бачына сайту генерыруеца праглядам. Прагляд вызначае які шаблон " +"выкарыстоўваць для генерацыі бачыны і якія аб'екты даступны для гэтага " +"шаблону." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Інструмент для вашага браўзэра для хуткага доступу да кіраўнічай " +"функцыянальнасці. " + +msgid "Please install docutils" +msgstr "Калі ласка, усталюйце Docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Дакументацыя кіраўнічай сістэмы патрабуе бібліятэку Python docutils." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Калі ласка, спытайцу вашых адміністратараў усталяваць docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Мадэль: %(name)s" + +msgid "Fields" +msgstr "Палі" + +msgid "Field" +msgstr "Поле" + +msgid "Type" +msgstr "Тып" + +msgid "Description" +msgstr "Апісаньне" + +msgid "Methods with arguments" +msgstr "Метад з аргументамі" + +msgid "Method" +msgstr "Метад" + +msgid "Arguments" +msgstr "Аргументы" + +msgid "Back to Model documentation" +msgstr "Вярнуцца да дакументацыі мадэлі" + +msgid "Model documentation" +msgstr "Дакументацыя мадэлі" + +msgid "Model groups" +msgstr "Групы мадэлі" + +msgid "Templates" +msgstr "Шаблёны" + +#, python-format +msgid "Template: %(name)s" +msgstr "Шаблон: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Шаблон: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Шлях пошуку для шаблону %(name)s:" + +msgid "(does not exist)" +msgstr "(не існуе)" + +msgid "Back to Documentation" +msgstr "Вярнуцца да дакументацыі" + +msgid "Template filters" +msgstr "Фільтры шаблону" + +msgid "Template filter documentation" +msgstr "Дакументацыя фільтраў шаблону" + +msgid "Built-in filters" +msgstr "Убудаваныя фільтры" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Каб карыстаць гэтыя фільтры, трэба памясціць %(code)s у ваш " +"шаблон перад тым як карыстаць гэты фільтр." + +msgid "Template tags" +msgstr "Тэгі шаблону" + +msgid "Template tag documentation" +msgstr "Дакументацыя тэгаў шаблону" + +msgid "Built-in tags" +msgstr "Убудаваныя тэгі" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Каб карыстаць гэтыя тэгі, трэба памясціць %(code)s у ваш " +"шаблон перад тым як карыстаць гэты тэг." + +#, python-format +msgid "View: %(name)s" +msgstr "Прагляд: %(name)s" + +msgid "Context:" +msgstr "Кантэкст:" + +msgid "Templates:" +msgstr "Шаблоны:" + +msgid "Back to View documentation" +msgstr "Вярнуцца да дакументацыі прагляду" + +msgid "View documentation" +msgstr "Паглядзець дакументацыю" + +msgid "Jump to namespace" +msgstr "Перайсці да прасторы імёнаў" + +msgid "Empty namespace" +msgstr "Ачысціць прастору імёнаў" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Прагляды ў просторы імёнаў %(name)s" + +msgid "Views by empty namespace" +msgstr "Прагляды ў пустым просторы імёнаў" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"Функцыя прагляду: %(full_name)s. Імя: %(url_name)s.\n" + +msgid "tag:" +msgstr "цэтлік:" + +msgid "filter:" +msgstr "сіта:" + +msgid "view:" +msgstr "прагляд:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Праграму %(app_label)r не знайшлі" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Мадэль %(model_name)r у праґраме «%(app_label)r» не знайшлі" + +msgid "model:" +msgstr "мадэль:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "залежны аб’ект «%(app_label)s.%(data_type)s»" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "залежныя аб’екты «%(app_label)s.%(object_name)s»" + +#, python-format +msgid "all %s" +msgstr "усе %s" + +#, python-format +msgid "number of %s" +msgstr "колькасьць %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s не падобны да аб’екта «шаблён спасылкі» — «urlpattern»" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/bg/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/bg/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8f522e1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/bg/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/bg/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/bg/LC_MESSAGES/django.po new file mode 100644 index 0000000..cb702a1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/bg/LC_MESSAGES/django.po @@ -0,0 +1,290 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# arneatec , 2022 +# Boris Chervenkov , 2012 +# Jannis Leidel , 2011 +# Lyuboslav Petrov , 2014 +# Todor Lubenov , 2011,2015 +# Venelin Stoykov , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2022-05-25 07:05+0000\n" +"Last-Translator: arneatec , 2022\n" +"Language-Team: Bulgarian (http://www.transifex.com/django/django/language/" +"bg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Административна документация" + +msgid "Home" +msgstr "Начало" + +msgid "Documentation" +msgstr "Документация" + +msgid "Bookmarklets" +msgstr "Bookmarklets" + +msgid "Documentation bookmarklets" +msgstr "Bookmarklet-и за документация" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"За да инсталирате bookmarklet-и, задърпайте линка в лентата с отметки " +"(bookmarks toolbar), или щракнете с десния бутон и добавете линка в " +"отметките. Сега можете да изберете bookmarklet-а от която и да е страница на " +"сайта." + +msgid "Documentation for this page" +msgstr "Документация за тази страница" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Препраща Ви от която и да е страница към документацията за изгледа, който я " +"е генерирал." + +msgid "Tags" +msgstr "Тагове" + +msgid "List of all the template tags and their functions." +msgstr "Списък на всички шаблонни тагове и техните функции." + +msgid "Filters" +msgstr "Филтри" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Филтрите са действия, които могат да се използват върху променливи в даден " +"шаблон, за да променят изхода." + +msgid "Models" +msgstr "Модели" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Моделите са описания на всички обекти в системата и свързаните с тях полета. " +"Всеки модел си има списък на полетата, които могат да бъдат достъпени както " +"шаблонни променливи" + +msgid "Views" +msgstr "Изгледи" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Всяка страница на публичния сайт се генерира от изглед. Изгледът определя " +"кой шаблон се използва за генериране на страницата и кои обекти са на " +"разположение за този шаблон." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Инструменти за вашия браузър за бърз достъп до администраторската " +"функционалност." + +msgid "Please install docutils" +msgstr "Моля инсталирайте docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Системата за администраторска документация изисква библиотеката за Python docutils." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Моля, помолете вашите администратори да инсталират docutils ." + +#, python-format +msgid "Model: %(name)s" +msgstr "Модел: %(name)s" + +msgid "Fields" +msgstr "Полета" + +msgid "Field" +msgstr "Поле" + +msgid "Type" +msgstr "Тип" + +msgid "Description" +msgstr "Описание" + +msgid "Methods with arguments" +msgstr "Методи с аргументи" + +msgid "Method" +msgstr "Метод" + +msgid "Arguments" +msgstr "Аргументи" + +msgid "Back to Model documentation" +msgstr " Върни се в документацията за модели" + +msgid "Model documentation" +msgstr "Документация за модели" + +msgid "Model groups" +msgstr "Групи на модела" + +msgid "Templates" +msgstr "Шаблони" + +#, python-format +msgid "Template: %(name)s" +msgstr "Шаблон: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Шаблон: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Път за търсене на шаблон %(name)s:" + +msgid "(does not exist)" +msgstr "(не съществува)" + +msgid "Back to Documentation" +msgstr "Назад към Документацията" + +msgid "Template filters" +msgstr "Шаблонни филтри" + +msgid "Template filter documentation" +msgstr "Документация за шаблонни филтри" + +msgid "Built-in filters" +msgstr "Вградени филтри" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"За да използвате тези филтри, сложете %(code)s във вашия " +"шаблон, преди да използвате филтъра." + +msgid "Template tags" +msgstr "Шаблонни тагове" + +msgid "Template tag documentation" +msgstr "Документация за Шаблонни тагове" + +msgid "Built-in tags" +msgstr "Вградени тагове" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"За да използвате тези тагове, сложете %(code)s във вашия " +"шаблон, преди да използвате тага." + +#, python-format +msgid "View: %(name)s" +msgstr "Изглед: %(name)s" + +msgid "Context:" +msgstr "Контекст:" + +msgid "Templates:" +msgstr "Шаблони:" + +msgid "Back to View documentation" +msgstr "Обратно към документацията за Изглед" + +msgid "View documentation" +msgstr "Документация за Изглед" + +msgid "Jump to namespace" +msgstr "Прескочи към именни пространства" + +msgid "Empty namespace" +msgstr "Празни именни пространства" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Изгледи по именни пространства %(name)s" + +msgid "Views by empty namespace" +msgstr "Изгледи по празни именни пространства" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +" Изглед функция: %(full_name)s. Име: %(url_name)s.\n" + +msgid "tag:" +msgstr "таг:" + +msgid "filter:" +msgstr "филтър:" + +msgid "view:" +msgstr "изглед:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Приложението %(app_label)r не е намерено" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Моделът %(model_name)r не е намерен в приложение %(app_label)r" + +msgid "model:" +msgstr "модел:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "свързания '%(app_label)s.%(data_type)s' обект" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "свързаните '%(app_label)s.%(object_name)s' обекти" + +#, python-format +msgid "all %s" +msgstr "всички %s" + +#, python-format +msgid "number of %s" +msgstr "брой %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s не прилича на обект от тип urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/bn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/bn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9ac735f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/bn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/bn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/bn/LC_MESSAGES/django.po new file mode 100644 index 0000000..625ef05 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/bn/LC_MESSAGES/django.po @@ -0,0 +1,261 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Anubhab Baksi, 2013 +# Jannis Leidel , 2011 +# Tahmid Rafi , 2012 +# Tahmid Rafi , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Bengali (http://www.transifex.com/django/django/language/" +"bn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "নীড়পাতা" + +msgid "Documentation" +msgstr "সহায়িকা" + +msgid "Bookmarklets" +msgstr "বুকমার্কলেট" + +msgid "Documentation bookmarklets" +msgstr "সহায়িকা বুকমার্কলেট" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "এই পাতার সহায়িকা" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "যেকোন পাতা থেকে ভিউ সহায়িকাতে নিয়ে যান।" + +msgid "Tags" +msgstr "ট্যাগগুলো" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "ফিল্টারগুলো" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "মডেলগুলো" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "ভিউগুলো" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "দয়া করে docutils ইনস্টল করুন" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "মডেল: %(name)s" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "ফিল্ড" + +msgid "Type" +msgstr "টাইপ" + +msgid "Description" +msgstr "বিবরন" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "মডেল ডকুমেন্টেশন" + +msgid "Model groups" +msgstr "মডেল গ্রুপ" + +msgid "Templates" +msgstr "টেমপ্লেটগুলো" + +#, python-format +msgid "Template: %(name)s" +msgstr "টেমপ্লেট: %(name)s" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "টেমপ্লেট: \"%(name)s\"" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "ডকুমেন্টেশনে ফেরত যান" + +msgid "Template filters" +msgstr "টেমপ্লেট ফিল্টার" + +msgid "Template filter documentation" +msgstr "টেমপ্লেট ফিল্টার ডকুমেন্টেশন" + +msgid "Built-in filters" +msgstr "বিল্ট-ইন ফিল্টার" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "টেমপ্লেট ট্যাগ" + +msgid "Template tag documentation" +msgstr "টেমপ্লেট ট্যাগ ডকুমেন্টেশন" + +msgid "Built-in tags" +msgstr "বিল্ট-ইন ট্যাগ" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "ভিউ: %(name)s" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "টেমপ্লেটসমূহ:" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "ভিউ ডকুমেন্টেশন" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "ফাঁকা নেমস্পেস" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "ট্যাগঃ" + +msgid "filter:" +msgstr "ফিল্টারঃ" + +msgid "view:" +msgstr "ভিউঃ" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "%(app_label)r এ্যপে %(model_name)r মডেলটি পাওয়া যায়নি" + +msgid "model:" +msgstr "মডেলঃ" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "`%(app_label)s.%(data_type)s` সম্পর্কিত অবজেক্ট" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "`%(app_label)s.%(object_name)s` সম্পর্কিত অবজেক্ট সমূহ" + +#, python-format +msgid "all %s" +msgstr "সকল %s" + +#, python-format +msgid "number of %s" +msgstr "%s সংখ্যা" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s ইউআরএল -এর মত নয়" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/br/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/br/LC_MESSAGES/django.mo new file mode 100644 index 0000000..56cfb09 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/br/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/br/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/br/LC_MESSAGES/django.po new file mode 100644 index 0000000..f3e1246 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/br/LC_MESSAGES/django.po @@ -0,0 +1,263 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Fulup , 2012 +# Irriep Nala Novram , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2019-03-12 14:33+0000\n" +"Last-Translator: Irriep Nala Novram \n" +"Language-Team: Breton (http://www.transifex.com/django/django/language/br/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: br\n" +"Plural-Forms: nplurals=5; plural=((n%10 == 1) && (n%100 != 11) && (n%100 !" +"=71) && (n%100 !=91) ? 0 :(n%10 == 2) && (n%100 != 12) && (n%100 !=72) && (n" +"%100 !=92) ? 1 :(n%10 ==3 || n%10==4 || n%10==9) && (n%100 < 10 || n% 100 > " +"19) && (n%100 < 70 || n%100 > 79) && (n%100 < 90 || n%100 > 99) ? 2 :(n != 0 " +"&& n % 1000000 == 0) ? 3 : 4);\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "Degemer" + +msgid "Documentation" +msgstr "Teuliadoù" + +msgid "Bookmarklets" +msgstr "Sinedoù" + +msgid "Documentation bookmarklets" +msgstr "" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" + +msgid "Tags" +msgstr "Tikedennoù" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "Siloù" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "baliz:" + +msgid "filter:" +msgstr "sil:" + +msgid "view:" +msgstr "gwel:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "" +"Neket bet kavet ar patrom %(model_name)r e-barzh an arload %(app_label)r" + +msgid "model:" +msgstr "patrom:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "an objed e liamm \"%(app_label)s.%(data_type)s\"" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "an objedoù e liamm \"%(app_label)s.%(object_name)s\"" + +#, python-format +msgid "all %s" +msgstr "an holl %s" + +#, python-format +msgid "number of %s" +msgstr "niver a %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/bs/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/bs/LC_MESSAGES/django.mo new file mode 100644 index 0000000..77617c0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/bs/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/bs/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/bs/LC_MESSAGES/django.po new file mode 100644 index 0000000..c24803f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/bs/LC_MESSAGES/django.po @@ -0,0 +1,261 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Bosnian (http://www.transifex.com/django/django/language/" +"bs/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bs\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "Početna" + +msgid "Documentation" +msgstr "Dokumentacija" + +msgid "Bookmarklets" +msgstr "Bookmarkleti" + +msgid "Documentation bookmarklets" +msgstr "Bookmarkleti dokumentacije" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "Dokumentacija za ovu stranicu" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Vodi od bilo koje stranice do dokumentacije za pogled koji generiše tu " +"stranicu." + +msgid "Tags" +msgstr "" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "tag:" + +msgid "filter:" +msgstr "filter:" + +msgid "view:" +msgstr "pogled:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Model %(model_name)r nije pronađen u aplikaciji %(app_label)r" + +msgid "model:" +msgstr "model:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "povezani objekti klase `%(app_label)s.%(data_type)s`" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "klase `%(app_label)s.%(object_name)s`" + +#, python-format +msgid "all %s" +msgstr "svi povezani objekti %s" + +#, python-format +msgid "number of %s" +msgstr "broj povezanih objekata %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s ne izgleda kao urlpattern objekat" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ca/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ca/LC_MESSAGES/django.mo new file mode 100644 index 0000000..37daf44 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ca/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ca/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ca/LC_MESSAGES/django.po new file mode 100644 index 0000000..8a0984b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ca/LC_MESSAGES/django.po @@ -0,0 +1,288 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# abraham.martin , 2014 +# Antoni Aloy , 2014,2017,2021 +# Carles Barrobés , 2012 +# Gil Obradors Via , 2019 +# Jannis Leidel , 2011 +# Roger Pons , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-10-27 08:46+0000\n" +"Last-Translator: Antoni Aloy \n" +"Language-Team: Catalan (http://www.transifex.com/django/django/language/" +"ca/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ca\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Documentació Administrativa" + +msgid "Home" +msgstr "Inici" + +msgid "Documentation" +msgstr "Documentació" + +msgid "Bookmarklets" +msgstr "'Bookmarklets'" + +msgid "Documentation bookmarklets" +msgstr "'Bookmarklets' de documentació" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Per instal·lar miniaplicacions enllaçades, arrossegueu l'enllaç a la vostra " +"barra de marcados, o feu clic dret a l'enllaç i afegiu-lo als vostres " +"marcadors. Ara podeu seleccionar la miniaplicació des de qualsevol pàgina " +"del lloc." + +msgid "Documentation for this page" +msgstr "Documentació d'aquesta pàgina" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Us porta des de qualsevol pàgina a la documentació de la vista que la genera." + +msgid "Tags" +msgstr "Etiquetes" + +msgid "List of all the template tags and their functions." +msgstr "Llista d'etiquetes de plantilles i les seves funcions." + +msgid "Filters" +msgstr "Filtres" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Els filtres són accions que poden ser aplicades a variables a una plantilla " +"per alterar la seva sortida." + +msgid "Models" +msgstr "Models" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Els models són descripcions de tots els objectes del sistema i els seus " +"camps associats. Cada model té una llista de camps que són accessibles com " +"variables de la plantilla." + +msgid "Views" +msgstr "Vistes" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Cada plana del lloc públic és generat per una vista (view). La vista " +"defineix quina plantilla es fa servir per generar la plana i quins objectes " +"estan disponibles a aquella plantilla." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Eines pel seu navegador per accedir ràpidament a la funcionalitat de l'admin." + +msgid "Please install docutils" +msgstr "Si us plau instal·leu docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"El sistema d'administració de documentació requereix de la biblioteca de " +"Python docutils." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Si us plau, demani als seus administradors la instal·lació de docutils ." + +#, python-format +msgid "Model: %(name)s" +msgstr "Model: %(name)s" + +msgid "Fields" +msgstr "Camps" + +msgid "Field" +msgstr "Camp" + +msgid "Type" +msgstr "Tipus" + +msgid "Description" +msgstr "Descripció" + +msgid "Methods with arguments" +msgstr "Mètodes amb arguments" + +msgid "Method" +msgstr "Mètode" + +msgid "Arguments" +msgstr "Arguments" + +msgid "Back to Model documentation" +msgstr "Tornar a la documentació del Model" + +msgid "Model documentation" +msgstr "Documentació del model" + +msgid "Model groups" +msgstr "Grups de model" + +msgid "Templates" +msgstr "Plantilles" + +#, python-format +msgid "Template: %(name)s" +msgstr "Plantilla: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Plantilla: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Camí de cerca per la plantilla \"%(name)s\":" + +msgid "(does not exist)" +msgstr "(no existeix)" + +msgid "Back to Documentation" +msgstr "Tornar a la documentació" + +msgid "Template filters" +msgstr "Filtres de plantilla" + +msgid "Template filter documentation" +msgstr "Documentació dels filtres de plantilla" + +msgid "Built-in filters" +msgstr "Filtres integrats" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Per utilitzar aquests filtres, introdueixi %(code)s a la seva " +"plantilla abans d'utilitzar el filtre." + +msgid "Template tags" +msgstr "Etiquetes de plantilles" + +msgid "Template tag documentation" +msgstr "Documentació de les etiquetes de plantilla" + +msgid "Built-in tags" +msgstr "Etiquetes integrades" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Per utilitzar aquestes etiquetes, introdueix %(code)s a la teva " +"plantilla abans d'utilitzar l'etiqueta" + +#, python-format +msgid "View: %(name)s" +msgstr "Vista: %(name)s" + +msgid "Context:" +msgstr "Contexte:" + +msgid "Templates:" +msgstr "Plantilles:" + +msgid "Back to View documentation" +msgstr "Tornar a la documentació de les Vistes" + +msgid "View documentation" +msgstr "Veure documentació" + +msgid "Jump to namespace" +msgstr "Anar a l'espai de noms" + +msgid "Empty namespace" +msgstr "Espai de noms buit" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Vistes de l'espai de noms %(name)s" + +msgid "Views by empty namespace" +msgstr "Vistes per l'espai de noms buit" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"Funció de la vista: %(full_name)s . Nom: %(url_name)s .\n" + +msgid "tag:" +msgstr "etiqueta:" + +msgid "filter:" +msgstr "filtre:" + +msgid "view:" +msgstr "vista:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Aplicació %(app_label)r no trobada" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "El model %(model_name)r no s'ha trobat a l'aplicació %(app_label)r" + +msgid "model:" +msgstr "model:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "l'objecte relacionat `%(app_label)s.%(data_type)s`" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "objectes relacionats `%(app_label)s.%(object_name)s`" + +#, python-format +msgid "all %s" +msgstr "tots %s" + +#, python-format +msgid "number of %s" +msgstr "nombre de %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s no sembla ser un objecte 'urlpattern'" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ckb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ckb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..72802d8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ckb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ckb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ckb/LC_MESSAGES/django.po new file mode 100644 index 0000000..3d8bd73 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ckb/LC_MESSAGES/django.po @@ -0,0 +1,286 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bakhtawar Barzan, 2021 +# kosar tofiq , 2020 +# Swara , 2022 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2023-04-24 20:19+0000\n" +"Last-Translator: Swara , 2022\n" +"Language-Team: Central Kurdish (http://www.transifex.com/django/django/" +"language/ckb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ckb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "بەڵگەنامەکردنی کارگێڕی" + +msgid "Home" +msgstr "ماڵەوە" + +msgid "Documentation" +msgstr "بەڵگەنامەکردن" + +msgid "Bookmarklets" +msgstr "ئاماژەکان" + +msgid "Documentation bookmarklets" +msgstr "بەڵگەنامەکردنی ئاماژەکان" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"بۆ دامەزراندنی ئاماژەکان، بەستەرەکە ڕابکێشە بۆ سەر جێدۆزەکانت، یان کرتەی " +"ڕاست لەسەر بەستەرەکە بکە و زیادی بکە بۆ ئاماژەکانت. ئێستا دەتوانیت لە هەر " +"لاپەڕەیەک لە ماڵپەڕەکەدا ئاماژە هەڵبژێریت." + +msgid "Documentation for this page" +msgstr "بەڵگەنامەکردن بۆ ئەم لاپەڕە" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"لە هەر لاپەڕەیەکەوە دەچێتەسەر بەڵگەنامەکان بۆ ئەو دیمەنەی کە ئەو لاپەڕەیە " +"دروست دەکات." + +msgid "Tags" +msgstr "تاگەکان" + +msgid "List of all the template tags and their functions." +msgstr "لیستی هەموو تاگەکانی ڕووکار و ئەرکەکانیان." + +msgid "Filters" +msgstr "پاڵاوتنەکان" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"پاڵاوتنەکان ئەو کردارانەن کە دەتوانرێت بۆ گۆڕاوەکان لە ڕووکارێکدا " +"بەکاربهێنرێن بۆ گۆڕینی دەرچوێنراوەکە." + +msgid "Models" +msgstr "مۆدیلەکان" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"مۆدێلەکان بریتین لە باسکردنی هەموو شتەکانی ناو سیستەمەکە و بوارە " +"پەیوەندیدارەکانیان. هەر مۆدێلێک لیستی خانەی هەیە کە دەتوانرێت وەک گۆڕاوەکانی " +"ڕووکار دەستی پێ بگات" + +msgid "Views" +msgstr "دیمەنەکان" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"هەر لاپەڕەیەک لە پێگەی گشتیدا بە دیمەنێک دروست دەکرێت. دیمەنەکە ئەوە پێناسە " +"دەکات کە کام ڕووکار بۆ دروستکردنی لاپەڕەکە بەکاردەهێنرێت و کام ئۆبجێکت " +"بەردەستە بۆ ئەو ڕووکارە." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"ئامرازەکان بۆ وێبگەڕەکەت بۆ ئەوەی بە خێرایی دەستت بگات بە کاراییەکانی " +"بەڕێوەبەر." + +msgid "Please install docutils" +msgstr "تکایە docutils دابمەزرێنە" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"سیستەمی بەڵگەنامەکردنی بەڕێوەبەر پێویستی بە کتێبخانەی docutils پایسۆن هەیە." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"تکایە پرسیار لە بەڕێوەبەرایەتی بکە بۆ دامەزراندنی docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "مۆدێل: %(name)s" + +msgid "Fields" +msgstr "خانەکان" + +msgid "Field" +msgstr "خانە" + +msgid "Type" +msgstr "جۆر" + +msgid "Description" +msgstr "باسکردن" + +msgid "Methods with arguments" +msgstr "شێوازەکان و ئارگومێنتەکان" + +msgid "Method" +msgstr "شێواز" + +msgid "Arguments" +msgstr "ئارگومێنتەکان" + +msgid "Back to Model documentation" +msgstr "گەڕانەوە بۆ بەڵگەنامەکردنی مۆدێل" + +msgid "Model documentation" +msgstr "بەڵگەنامەی مۆدێل" + +msgid "Model groups" +msgstr "گرووپەکانی مۆدێل" + +msgid "Templates" +msgstr "ڕووکارەکان" + +#, python-format +msgid "Template: %(name)s" +msgstr "ڕووکار: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "ڕووکاری: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "گەڕانی ڕێڕەو بۆ ڕووکاری %(name)s:" + +msgid "(does not exist)" +msgstr "(بوونی نیە)" + +msgid "Back to Documentation" +msgstr "گەڕانەوە بۆ بەڵگەنامەکردن" + +msgid "Template filters" +msgstr "پاڵاوتنەکانی ڕووکار" + +msgid "Template filter documentation" +msgstr "بەڵگەنامەکردنی پاڵاوتنی ڕووکار" + +msgid "Built-in filters" +msgstr "پاڵاوتنەکانی Built-in" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"بۆ بەکارهێنانی ئەم پاڵاوتنانە%(code)s لەناو ڕووکارەکەت دابنێ " +"پێش ئەوەی پاڵاوتن بەکاربهێنیت." + +msgid "Template tags" +msgstr "تاگەکانی ڕووکار" + +msgid "Template tag documentation" +msgstr "بەڵگەنامەکردنی تاگی ڕووکار" + +msgid "Built-in tags" +msgstr "تاگەکانی Built-in" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"بۆ بەکارهێنانی ئەم تاگانە, %(code)s لەناو ڕووکارەکەت دابنێ پێش " +"ئەوەی تاگ بەکاربهێنیت." + +#, python-format +msgid "View: %(name)s" +msgstr "دیمەن: %(name)s" + +msgid "Context:" +msgstr "دەق:" + +msgid "Templates:" +msgstr "ڕووکارەکان:" + +msgid "Back to View documentation" +msgstr "گەڕانەوە بۆ بەڵگەنامەکردنی دیمەن" + +msgid "View documentation" +msgstr "بەڵگەنامەکردنی دیمەن" + +msgid "Jump to namespace" +msgstr "بازدان بۆ بۆشاییناو" + +msgid "Empty namespace" +msgstr "بۆشاییناوی بەتاڵ" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "دیمەنەکان لەلایەن بۆشاییناو %(name)s" + +msgid "Views by empty namespace" +msgstr "دیمەنەکان لایەن بۆشاییناوی بەتاڵەوە" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +" کرداری دیمەن: %(full_name)s. ناو: %(url_name)s.\n" + +msgid "tag:" +msgstr "تاگ:" + +msgid "filter:" +msgstr "پاڵاوتن:" + +msgid "view:" +msgstr "دیمەن:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "بەرنامەی %(app_label)r نەدۆزرایەوە" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "مۆدێلی %(model_name)r ناوتوانرێت لە ئاپی %(app_label)r بدۆزرێتەوە" + +msgid "model:" +msgstr "مۆدێل:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "پەیوەستکراو `%(app_label)s. ئۆبجێکتی%(data_type)s`" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "پەیوەستکراوە `%(app_label)s. ئۆبجێکتی%(object_name)s`" + +#, python-format +msgid "all %s" +msgstr "هەموو %s" + +#, python-format +msgid "number of %s" +msgstr "ژمارە لە %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s بەگوێرەی شێوازی urlی ئۆبجێکتێک نیە" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/cs/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/cs/LC_MESSAGES/django.mo new file mode 100644 index 0000000..49b5b86 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/cs/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/cs/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/cs/LC_MESSAGES/django.po new file mode 100644 index 0000000..e68dbfb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/cs/LC_MESSAGES/django.po @@ -0,0 +1,284 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Vláďa Macek , 2012-2014 +# Vláďa Macek , 2015-2016,2019,2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-03-18 23:13+0000\n" +"Last-Translator: Vláďa Macek \n" +"Language-Team: Czech (http://www.transifex.com/django/django/language/cs/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cs\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n " +"<= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n" + +msgid "Administrative Documentation" +msgstr "Dokumentace správy" + +msgid "Home" +msgstr "Domů" + +msgid "Documentation" +msgstr "Dokumentace" + +msgid "Bookmarklets" +msgstr "Bookmarklety" + +msgid "Documentation bookmarklets" +msgstr "Dokumentační bookmarklety" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Pro nainstalování bookmarkletů, přetáhněte odkaz na vaše záložky " +"(„Oblíbené“), nebo klepněte pravým tlačítkem na odkaz a přidejte ho k vašim " +"záložkám. Nyní můžete zvolit bookmarklet z libovolné stránky jakéhokoli webu." + +msgid "Documentation for this page" +msgstr "Dokumentace k této stránce" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Z libovolné stránky otevře dokumentaci pohledu (view), který generoval tuto " +"stránku." + +msgid "Tags" +msgstr "Tagy" + +msgid "List of all the template tags and their functions." +msgstr "Seznam všech šablonových tagů a jejich funkce." + +msgid "Filters" +msgstr "Filtry" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Filtry jsou akce, které mohou být aplikovány na proměnné v šabloně za účelem " +"úpravy hodnoty." + +msgid "Models" +msgstr "Modely" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Modely jsou popisy všech objektů v systému a jejich přidružených polí. Každý " +"model má seznam polí, které mohou být čteny jako proměnné v šablonách." + +msgid "Views" +msgstr "Views" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Každá stránka na veřejném webu je generována pomocí pohledu. Pohled " +"definuje, která šablona bude použita ke generování stránky a které objekty " +"budou v šabloně k dispozici." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Nástroje pro prohlížeč k rychlému přístupu k funkcím administračního " +"rozhraní." + +msgid "Please install docutils" +msgstr "Nainstalujte balík docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Dokumentační systém administračního rozhraní vyžaduje pythonskou knihovnu docutils." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Požádejte správce o instalaci balíku docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Model: %(name)s" + +msgid "Fields" +msgstr "Pole" + +msgid "Field" +msgstr "Pole" + +msgid "Type" +msgstr "Typ" + +msgid "Description" +msgstr "Popis" + +msgid "Methods with arguments" +msgstr "Metody s argumenty" + +msgid "Method" +msgstr "Metoda" + +msgid "Arguments" +msgstr "Argumenty" + +msgid "Back to Model documentation" +msgstr "Zpět na popis modelů" + +msgid "Model documentation" +msgstr "Dokumentace modelů" + +msgid "Model groups" +msgstr "Skupiny modelů" + +msgid "Templates" +msgstr "Šablony" + +#, python-format +msgid "Template: %(name)s" +msgstr "Šablona: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Šablona: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Vyhledávací cesta pro šablonu %(name)s:" + +msgid "(does not exist)" +msgstr "(neexistuje)" + +msgid "Back to Documentation" +msgstr "Zpět na dokumentaci" + +msgid "Template filters" +msgstr "Šablonové filtry" + +msgid "Template filter documentation" +msgstr "Dokumentace šablonových filtrů" + +msgid "Built-in filters" +msgstr "Vestavěné filtry" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Chcete-li tyto filtry používat, vložte do šablony před místo použití kód " +"%(code)s." + +msgid "Template tags" +msgstr "Šablonové tagy" + +msgid "Template tag documentation" +msgstr "Dokumentace šablonových tagů" + +msgid "Built-in tags" +msgstr "Vestavěné tagy" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Chcete-li tyto tagy používat, vložte do šablony před místo použití kód " +"%(code)s." + +#, python-format +msgid "View: %(name)s" +msgstr "Pohled: %(name)s" + +msgid "Context:" +msgstr "Kontext:" + +msgid "Templates:" +msgstr "Šablony:" + +msgid "Back to View documentation" +msgstr "Zpět na popis pohledů" + +msgid "View documentation" +msgstr "Dokumentace pohledů" + +msgid "Jump to namespace" +msgstr "Přejít na jmenný prostor" + +msgid "Empty namespace" +msgstr "Prázdný jmenný prostor" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Pohledy dle jmenného prostoru %(name)s" + +msgid "Views by empty namespace" +msgstr "Pohledy dle prázdného jmenného prostoru" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"Funkce pohledu: %(full_name)s. Název: %(url_name)s.\n" + +msgid "tag:" +msgstr "tag:" + +msgid "filter:" +msgstr "filtr:" + +msgid "view:" +msgstr "pohled (view):" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Aplikace %(app_label)r nebyla nalezena" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Model %(model_name)r v aplikaci %(app_label)r nenalezen" + +msgid "model:" +msgstr "model:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "související položka `%(app_label)s.%(data_type)s`" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "související položky `%(app_label)s.%(object_name)s`" + +#, python-format +msgid "all %s" +msgstr "Vše: %s" + +#, python-format +msgid "number of %s" +msgstr "Počet: %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "Objekt %s patrně není typu urlpattern." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/cy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/cy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..64f4ab6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/cy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/cy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/cy/LC_MESSAGES/django.po new file mode 100644 index 0000000..653b2d8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/cy/LC_MESSAGES/django.po @@ -0,0 +1,279 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Maredudd ap Gwyndaf , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Welsh (http://www.transifex.com/django/django/language/cy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cy\n" +"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != " +"11) ? 2 : 3;\n" + +msgid "Administrative Documentation" +msgstr "Dogfennaeth Gweinyddol" + +msgid "Home" +msgstr "Hafan" + +msgid "Documentation" +msgstr "Dogfennaeth" + +msgid "Bookmarklets" +msgstr "Nodau tudalen" + +msgid "Documentation bookmarklets" +msgstr "Nodau tudalen dogfennaeth" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "Dogfennaeth y dudalen hon" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Cymerir chi o unrhyw dudalen i'r dogfennaeth am yr olwg sy'n creu'r dudalen " +"hwnnw." + +msgid "Tags" +msgstr "Tagiau" + +msgid "List of all the template tags and their functions." +msgstr "Rhestr o holl dagiau'r templad a'u swyddogaeth." + +msgid "Filters" +msgstr "Hidlau" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Gweithredoedd yw hidlau sy'n gallu cael eu gosod ar newidynnau mewn templad " +"i newid yr allbwm." + +msgid "Models" +msgstr "Modelau" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Mae modelau yn disgrifio pob gwrthrych yn y system a'u meysydd " +"cysylltiedig. Mae gan bob model restr o feysydd y gellir eu defnyddio fel " +"newidynnau templad" + +msgid "Views" +msgstr "Golygon" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Mae pob tudalen ar y wefan gyhoeddus yn cael eu creu gan olwg. Mae'r golwg " +"yn diffunio pa templad i'w ddefnyddio i gynhyrchu'r dudalen a pa wrthrychau " +"sydd ar gael i'r templad." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Offer ar gyfer eich porwr i gael mynediad cyflym i swyddogaethau gweinyddwr." + +msgid "Please install docutils" +msgstr "Gosodwch docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" +"Mae'r system dogfennaeth gweinyddol angen llyfrgell docutils Python." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "Gofynnwch i'r gweinyddwr i osod docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Model: %(name)s" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "Maes" + +msgid "Type" +msgstr "Math" + +msgid "Description" +msgstr "Disgrifiad" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "Dogfennaeth model" + +msgid "Model groups" +msgstr "Grwpiau model" + +msgid "Templates" +msgstr "Templadau" + +#, python-format +msgid "Template: %(name)s" +msgstr "Templad: %(name)s" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "Templad: \"%(name)s\"" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "Chwilio'r llwybr am dempled \"%(name)s\":" + +msgid "(does not exist)" +msgstr "(nid yw'n bodoli)" + +msgid "Back to Documentation" +msgstr "Nôl i Dogfennaeth" + +msgid "Template filters" +msgstr "Hidlau templadau" + +msgid "Template filter documentation" +msgstr "Dogfennaeth hidlau templadau" + +msgid "Built-in filters" +msgstr "Hidlau mewnol" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"I ddefnyddio'r hildau, rhowch %(code)s yn eich templad cyn " +"defnyddio'r hidl." + +msgid "Template tags" +msgstr "Tagiau templadau" + +msgid "Template tag documentation" +msgstr "Dogfennaeth tag templad" + +msgid "Built-in tags" +msgstr "Tagiau mewnol" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"I ddefnyddio'r tagiau rhowch %(code)s yn eich templad cyn " +"defnyddio'r tag." + +#, python-format +msgid "View: %(name)s" +msgstr "Golwg: %(name)s" + +msgid "Context:" +msgstr "Cyd-destun:" + +msgid "Templates:" +msgstr "Templadau:" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "Dogfennaeth golygon" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"Gweld ffwythiant: %(full_name)s. Enw: %(url_name)s.\n" + +msgid "tag:" +msgstr "tag:" + +msgid "filter:" +msgstr "hidl:" + +msgid "view:" +msgstr "golwg:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Ni ddarganfuwyd ap %(app_label)r" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Ni darganfyddwyd model %(model_name)r yn ap %(app_label)r" + +msgid "model:" +msgstr "model:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "y gwrthrych `%(app_label)s.%(data_type)s` cysylltiedig" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "gwrthrychau `%(app_label)s.%(object_name)s` cysylltiedig" + +#, python-format +msgid "all %s" +msgstr "pob %s" + +#, python-format +msgid "number of %s" +msgstr "nifer o %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "nid yw %s yn ymweld i fod yn wrthrych urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/da/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/da/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d085482 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/da/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/da/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/da/LC_MESSAGES/django.po new file mode 100644 index 0000000..4544478 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/da/LC_MESSAGES/django.po @@ -0,0 +1,285 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Christian Joergensen , 2012 +# Erik Ramsgaard Wognsen , 2021 +# Erik Ramsgaard Wognsen , 2013,2015-2016,2019 +# Jannis Leidel , 2011 +# valberg , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-01-15 18:23+0000\n" +"Last-Translator: Erik Ramsgaard Wognsen \n" +"Language-Team: Danish (http://www.transifex.com/django/django/language/da/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: da\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Administrationsdokumentation" + +msgid "Home" +msgstr "Hjem" + +msgid "Documentation" +msgstr "Dokumentation" + +msgid "Bookmarklets" +msgstr "Bookmarklets" + +msgid "Documentation bookmarklets" +msgstr "Dokumentations-bookmarklets" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"For at installere bookmarklets, skal du trække linket til din bogmærkelinje " +"eller højreklikke linket og tilføje det til dine bogmærker. Derefter kan du " +"vælge bookmarkletten fra enhver side på websitet." + +msgid "Documentation for this page" +msgstr "Dokumentation for denne side" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Bringer dig fra en hvilken som helst side til dokumentationen for det view, " +"der genererer den pågældende side." + +msgid "Tags" +msgstr "Mærker" + +msgid "List of all the template tags and their functions." +msgstr "Liste af alle template tags og deres funktioner." + +msgid "Filters" +msgstr "Filtre" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Filtre er handlinger, der kan anvendes på variabler i en skabelon for at " +"ændre outputtet." + +msgid "Models" +msgstr "Modeller" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Modeller er beskrivelser af alle objekter i systemet, og deres tilhørende " +"felter. Hver model har en liste af felter som kan tilgås som en skabelon " +"variabel." + +msgid "Views" +msgstr "Views" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Hver side på den offentlige side bliver genereret af et view. Viewet " +"definerer hvilken skabelon der bruges til at generere siden og hvilke " +"objekter er tilgængelige fra skabelonen." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "Værktøjer for din browser til hurtig adgang til admin funktionalitet." + +msgid "Please install docutils" +msgstr "Installer venligst docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Admin dokumentationssystemet kræver Pythons docutils bibliotek." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Venligst spørg dine administratorer om at installere docutils ." + +#, python-format +msgid "Model: %(name)s" +msgstr "Model: %(name)s" + +msgid "Fields" +msgstr "Felter" + +msgid "Field" +msgstr "Felt" + +msgid "Type" +msgstr "Type" + +msgid "Description" +msgstr "Beskrivelse" + +msgid "Methods with arguments" +msgstr "Metode med argumenter" + +msgid "Method" +msgstr "Metode" + +msgid "Arguments" +msgstr "Argumenter" + +msgid "Back to Model documentation" +msgstr "Tilbage til modeldokumentationen" + +msgid "Model documentation" +msgstr "Modeldokumentation" + +msgid "Model groups" +msgstr "Modelgrupper" + +msgid "Templates" +msgstr "Skabeloner" + +#, python-format +msgid "Template: %(name)s" +msgstr "Skabelon: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Skabelon: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Søgesti for skabelon %(name)s:" + +msgid "(does not exist)" +msgstr "(eksisterer ikke)" + +msgid "Back to Documentation" +msgstr "Tilbage til dokumentationen" + +msgid "Template filters" +msgstr "Skabelonfiltre" + +msgid "Template filter documentation" +msgstr "Skabelonfilterdokumentation" + +msgid "Built-in filters" +msgstr "Indbyggede filtre" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"For at bruge disse filtre, indsæt %(code)s i din skabelon, før " +"du bruger filteret." + +msgid "Template tags" +msgstr "Skabelon-tags" + +msgid "Template tag documentation" +msgstr "Skabelon-tag-dokumentation" + +msgid "Built-in tags" +msgstr "Indbyggede tags" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"For at bruge disse tags, indsæt %(code)s i din skabelon, før du " +"bruger tagget." + +#, python-format +msgid "View: %(name)s" +msgstr "View: %(name)s" + +msgid "Context:" +msgstr "Kontekst:" + +msgid "Templates:" +msgstr "Skabeloner:" + +msgid "Back to View documentation" +msgstr "Tilbage til View-dokumentationen" + +msgid "View documentation" +msgstr "View dokumentation" + +msgid "Jump to namespace" +msgstr "Hop til namespace" + +msgid "Empty namespace" +msgstr "Tomt namespace" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Views efter namespace %(name)s" + +msgid "Views by empty namespace" +msgstr "Views efter tomt namespace" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +" View funktion: %(full_name)s. Navn: %(url_name)s.\n" + +msgid "tag:" +msgstr "tag:" + +msgid "filter:" +msgstr "filter:" + +msgid "view:" +msgstr "view:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Applikation %(app_label)r blev ikke fundet" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Modellen %(model_name)r ikke fundet i applikationen %(app_label)r" + +msgid "model:" +msgstr "model:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "det relaterede `%(app_label)s.%(data_type)s`-objekt" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "relaterede `%(app_label)s.%(object_name)s`-objekter" + +#, python-format +msgid "all %s" +msgstr "alle %s" + +#, python-format +msgid "number of %s" +msgstr "antal %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s ser ikke ud til at være et urlpattern-objekt" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/de/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/de/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ae993f7 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/de/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/de/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/de/LC_MESSAGES/django.po new file mode 100644 index 0000000..0cb229f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/de/LC_MESSAGES/django.po @@ -0,0 +1,287 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Florian Apolloner , 2021 +# Jannis Vajen, 2013 +# Jannis Leidel , 2013-2016,2020 +# Jannis Vajen, 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-11-28 17:15+0000\n" +"Last-Translator: Raphael Michel \n" +"Language-Team: German (http://www.transifex.com/django/django/language/de/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Administrative Dokumentation" + +msgid "Home" +msgstr "Start" + +msgid "Documentation" +msgstr "Dokumentation" + +msgid "Bookmarklets" +msgstr "Bookmarklets" + +msgid "Documentation bookmarklets" +msgstr "Dokumentations-Bookmarklets" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Um die Bookmarklets zu installieren, muss dieser Link in die Browser-" +"Werkzeugleiste gezogen werden oder mittels rechter Maustaste in den " +"Bookmarks gespeichert werden. Danach können die Bookmarklets von jeder Seite " +"aufgerufen werden." + +msgid "Documentation for this page" +msgstr "Dokumentation für diese Seite" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Springt von jeder Seite zu der Dokumentation für den View, der diese Seite " +"erzeugt." + +msgid "Tags" +msgstr "Tags" + +msgid "List of all the template tags and their functions." +msgstr "Alle Template-Tags und deren Funktionen auflisten." + +msgid "Filters" +msgstr "Filter" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Filter sind Aktionen, die in Templates auf Variablen angewendet werden " +"können, um deren Ausgabe zu verändern." + +msgid "Models" +msgstr "Modelle" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Modelle sind Beschreibungen aller Objekte und ihrer Felder, die sich im " +"System befinden. Jedes Model hat eine Reihe von Feldern, auf in Form von " +"Templatevariablen zugegriffen werden kann." + +msgid "Views" +msgstr "Views" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Jede öffentliche Seite wird durch einen View generiert. Dieser View " +"definiert, welches Template genutzt wird, um die Seite zu generieren und " +"welche Objekte in dem jeweiligen Template zur Verfügung stehen." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Hilfsfunktionen für den Browser, um schnell auf den Administrationsbereich " +"zugreifen zu können." + +msgid "Please install docutils" +msgstr "Bitte docutils installieren." + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Das Admin-Dokumentationssystem erfordert die Python-Bibliothek docutils." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Bitte durch den/die Administrator/in docutils " +"installieren lassen." + +#, python-format +msgid "Model: %(name)s" +msgstr "Model: %(name)s" + +msgid "Fields" +msgstr "Felder" + +msgid "Field" +msgstr "Feld" + +msgid "Type" +msgstr "Klasse" + +msgid "Description" +msgstr "Beschreibung" + +msgid "Methods with arguments" +msgstr "Methode mit Argumenten" + +msgid "Method" +msgstr "Methode" + +msgid "Arguments" +msgstr "Argumente" + +msgid "Back to Model documentation" +msgstr "Zurück zur Model-Dokumentation" + +msgid "Model documentation" +msgstr "Model-Dokumentation" + +msgid "Model groups" +msgstr "Model-Gruppen" + +msgid "Templates" +msgstr "Templates" + +#, python-format +msgid "Template: %(name)s" +msgstr "Template: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Template: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Suchpfade für Template %(name)s:" + +msgid "(does not exist)" +msgstr "(existiert nicht)" + +msgid "Back to Documentation" +msgstr "Zurück zur Dokumentation" + +msgid "Template filters" +msgstr "Template-Filter" + +msgid "Template filter documentation" +msgstr "Template-Filter-Dokumentation" + +msgid "Built-in filters" +msgstr "Mitgelieferte Filter" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Um diese Filter zu nutzen, muss sich %(code)s vor Aufruf des " +"Filters im Template befinden." + +msgid "Template tags" +msgstr "Template-Tags" + +msgid "Template tag documentation" +msgstr "Template-Tag-Dokumentation" + +msgid "Built-in tags" +msgstr "Mitgelieferte Tags" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Um diese Tags zu nutzen, muss sich %(code)s vor Aufruf des Tags " +"im Template befinden." + +#, python-format +msgid "View: %(name)s" +msgstr "View: %(name)s" + +msgid "Context:" +msgstr "Kontext:" + +msgid "Templates:" +msgstr "Templates:" + +msgid "Back to View documentation" +msgstr "Zurück zur View-Dokumentation" + +msgid "View documentation" +msgstr "View Dokumentation" + +msgid "Jump to namespace" +msgstr "Zu Namespace springen" + +msgid "Empty namespace" +msgstr "Leerer Namespace" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Views in Namespace %(name)s" + +msgid "Views by empty namespace" +msgstr "Views ohne Namespace" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +" View-Funktion: %(full_name)s. Name: %(url_name)s.\n" + +msgid "tag:" +msgstr "Tag:" + +msgid "filter:" +msgstr "Filter:" + +msgid "view:" +msgstr "View:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Anwendung %(app_label)r nicht gefunden" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Modell %(model_name)r wurde nicht in Anwendung %(app_label)r gefunden" + +msgid "model:" +msgstr "Modell:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "Das verknüpfte `%(app_label)s.%(data_type)s` Objekt" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "verknüpfte `%(app_label)s.%(object_name)s` Objekte" + +#, python-format +msgid "all %s" +msgstr "Alle %s" + +#, python-format +msgid "number of %s" +msgstr "Anzahl von %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s ist scheinbar kein urlpattern-Objekt" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/dsb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/dsb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d07d187 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/dsb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/dsb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/dsb/LC_MESSAGES/django.po new file mode 100644 index 0000000..f4caac7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/dsb/LC_MESSAGES/django.po @@ -0,0 +1,285 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Michael Wolf , 2016,2020-2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-02-01 22:06+0000\n" +"Last-Translator: Michael Wolf \n" +"Language-Team: Lower Sorbian (http://www.transifex.com/django/django/" +"language/dsb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: dsb\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" + +msgid "Administrative Documentation" +msgstr "Administratiwna dokumentacija" + +msgid "Home" +msgstr "Startowy bok" + +msgid "Documentation" +msgstr "Dokumentacija" + +msgid "Bookmarklets" +msgstr "Skriptowe cytańske znamjenja" + +msgid "Documentation bookmarklets" +msgstr "Skriptowe cytańske znamjenja dokumentacije" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Aby skriptowe cytańske znamjenja instalěrował, śěgniśo wótkaz do swójeje " +"rědki cytańskich znamjenjow abo klikniśo z pšaweju tastu myški a pśidajśo " +"jen swójim cytańskim znamjenjam. Něnto móžośo skriptowe cytańske znamje z " +"drugego boka na sedle wubraś." + +msgid "Documentation for this page" +msgstr "Dokumentacija za toś ten bok" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Zmóžnja wam, z někakego boka do dokumentacije naglěda skócyś, kótaryž twóri " +"ten bok." + +msgid "Tags" +msgstr "Wobznamjenja" + +msgid "List of all the template tags and their functions." +msgstr "Lisćina wšych pśedłogowych wobznamjenjow a jich funkcijow." + +msgid "Filters" +msgstr "Filtry" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Filtry su akcije, kótarež daju se na wariable w pśedłoze nałožyś, aby wudaśe " +"změnili." + +msgid "Models" +msgstr "Modele" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Modele su wopisanja wšych objektow w systemje a jich pśisłušnych pólow. " +"Kuždy model ma lisćinu pólow, na kótarež maju pśistup ako pśedłogowe " +"wariable." + +msgid "Views" +msgstr "Naglědy" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Kuždy bok na zjawnem sedle twóri se pśez naglěd. Naglěd definěrujo, kótara " +"pśedłoga se wužywa, aby se bok napórał a kótare objekty su tej pśedłoze k " +"dispoziciji." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Rědy za waš wobglědowak za malsny pśistup na adminstratorowu funkcionalnosć." + +msgid "Please install docutils" +msgstr "Pšosym instalěrujśo docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Administratorowy dokumentaciski system pomina se Pythonowu biblioteku docutils." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Pšosym pšosćo swóje administratory, docutils " +"instalěrowaś." + +#, python-format +msgid "Model: %(name)s" +msgstr "Model: %(name)s" + +msgid "Fields" +msgstr "Póla" + +msgid "Field" +msgstr "Pólo" + +msgid "Type" +msgstr "Typ" + +msgid "Description" +msgstr "Wopisanje" + +msgid "Methods with arguments" +msgstr "Metody z argumentami" + +msgid "Method" +msgstr "Metoda" + +msgid "Arguments" +msgstr "Argumenty" + +msgid "Back to Model documentation" +msgstr "Slědk k modelowej dokumentaciji" + +msgid "Model documentation" +msgstr "Modelowa dokumentacija" + +msgid "Model groups" +msgstr "Modelowe kupki" + +msgid "Templates" +msgstr "Pśedłogi" + +#, python-format +msgid "Template: %(name)s" +msgstr "Pśedłoga: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Pśedłoga: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Pytańska sćažka za pśedłogu %(name)s:" + +msgid "(does not exist)" +msgstr "(njeeksistěrujo)" + +msgid "Back to Documentation" +msgstr "Slědk k dokumentaciji" + +msgid "Template filters" +msgstr "Pśedłogowe filtry" + +msgid "Template filter documentation" +msgstr "Dokumentacija za pśedłogowe filtry" + +msgid "Built-in filters" +msgstr "Zatwarjone filtry" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Aby toś te filtry wužywał, zasajźćo %(code)s do wójeje " +"pśedłogi, nježli až wužywaśo filter." + +msgid "Template tags" +msgstr "Pśedłogowe wobznamjenja" + +msgid "Template tag documentation" +msgstr "Dokumentacija za pśedłogowe wobznamjenja" + +msgid "Built-in tags" +msgstr "Zatworjone wobznamjenja" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Aby toś te wobznamjenja wužywał, zasajźćo %(code)s do wójeje " +"pśedłogi, nježli až wužywaśo wobznamjenje." + +#, python-format +msgid "View: %(name)s" +msgstr "Naglěd: %(name)s" + +msgid "Context:" +msgstr "Kontekst:" + +msgid "Templates:" +msgstr "Pśedłogi" + +msgid "Back to View documentation" +msgstr "Slědk k naglědowej dokumentaciji" + +msgid "View documentation" +msgstr "Naglědowa dokumentacija" + +msgid "Jump to namespace" +msgstr "K mjenjowemu rumoju skócyś" + +msgid "Empty namespace" +msgstr "Prozny mjenjowy rum" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Naglědy pó mjenjowem rumje %(name)s" + +msgid "Views by empty namespace" +msgstr "Naglědy pó proznem mjenjowem rumje" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +" Naglědowa funkcija: %(full_name)s. Mě: %(url_name)s.\n" + +msgid "tag:" +msgstr "wobznamjenje:" + +msgid "filter:" +msgstr "filter:" + +msgid "view:" +msgstr "naglěd:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Nałoženje %(app_label)r njenamakane" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Model %(model_name)r njejo se w nałoženju %(app_label)r namakał" + +msgid "model:" +msgstr "model:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "pśisłušny objekt %(app_label)s.%(data_type)s“" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "pśisłušne objekty „%(app_label)s.%(object_name)s" + +#, python-format +msgid "all %s" +msgstr "wšykne %s" + +#, python-format +msgid "number of %s" +msgstr "ůicba %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "zda se, až %s njejo objekt urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/el/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/el/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9739b41 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/el/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/el/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/el/LC_MESSAGES/django.po new file mode 100644 index 0000000..bc4aebb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/el/LC_MESSAGES/django.po @@ -0,0 +1,290 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Dimitris Glezos , 2011 +# Fotis Athineos , 2021 +# Jannis Leidel , 2011 +# Nick Mavrakis , 2016 +# Pãnoș , 2014 +# Yorgos Pagles , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-08-04 06:47+0000\n" +"Last-Translator: Fotis Athineos \n" +"Language-Team: Greek (http://www.transifex.com/django/django/language/el/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: el\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Διαχειριστική Τεκμηρίωση" + +msgid "Home" +msgstr "Αρχική" + +msgid "Documentation" +msgstr "Τεκμηρίωση" + +msgid "Bookmarklets" +msgstr "Σελιδοδείκτες" + +msgid "Documentation bookmarklets" +msgstr "Σελιδοδείκτες τεκμηρίωσης" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Για την εγκατάσταση bookmarklets, σύρετε το link στην γραμμή εργαλείων των " +"bookmarks του browser σας ή δεξί-κλικ πάνω στο link και προσθέστε το στα " +"bookmarks. Τώρα μπορείτε να επιλέξετε το bookmarklet μέσα από κάθε σελίδα " +"του site." + +msgid "Documentation for this page" +msgstr "Τεκμηρίωση για αυτήν τη σελίδα" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Μεταπήδηση από οποιαδήποτε σελίδα στην τεκμηρίωση για το view που " +"δημιούργησε τη σελίδα αυτή." + +msgid "Tags" +msgstr "Ετικέτες" + +msgid "List of all the template tags and their functions." +msgstr "Λίστα όλωςν τον ετικετών περιγραμμάτων και των λειτουργιών τους." + +msgid "Filters" +msgstr " Φίλτρα" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Τα φίλτρα είναι ενέργειες που μπορούν να εφαρμοστούν σε μεταβλητές μέσα σε " +"ένα περίγραμμα για να αλλάξουν το αποτέλεσμα." + +msgid "Models" +msgstr "Μοντέλα" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Τα μοντέλα είναι περιγραφές όλωςν τον αντικειμένων στο σύστημα και των " +"συνδεδεμένων πεδίων. Κάθε μοντέλο έχει μια λίστα πεδιών που είναι προσβάσιμα " +"ως μεταβλητές περιγραμμάτων" + +msgid "Views" +msgstr "Οπτικές" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Κάθε σελίδα στη δημόσια ιστοσελίδα παράγεται από μια οπτική. Η οπτική ορίζει " +"ποιό περίγραμμα θα χρησιμοποιηθεί για να παραχθεί η σελίδα και ποιά " +"αντικείμενα είναι διαθέσιμα σε αυτό το περίγραμμα." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Εργαλεία για το πρόγραμμα περιήγησης για γρήγορη πρόσβαση σε διαχειριστική " +"λειτουργικότητα. " + +msgid "Please install docutils" +msgstr "Παρακαλώ εγκαταστείστε τα docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Το σύστημα διαχειριστικής τεκμηρίωσης απαιτεί την βιβλιοθήκη της Python docutils." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Παρακαλώ ζητήστε απο τον διαχειριστή σας να εγκαταστήσει τα docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Μοντέλο: %(name)s" + +msgid "Fields" +msgstr "Πεδία" + +msgid "Field" +msgstr "Πεδίο" + +msgid "Type" +msgstr "Τύπος" + +msgid "Description" +msgstr "Περιγραφή" + +msgid "Methods with arguments" +msgstr "Μέθοδοι με ορίσματα" + +msgid "Method" +msgstr "Μέθοδος" + +msgid "Arguments" +msgstr "Ορίσματα" + +msgid "Back to Model documentation" +msgstr "Πίσω στην τεκμηρίωση των Μοντέλων" + +msgid "Model documentation" +msgstr "Τεκμηρίωση Μοντέλων" + +msgid "Model groups" +msgstr "Ομάδες μοντέλου" + +msgid "Templates" +msgstr "Περιγράμματα" + +#, python-format +msgid "Template: %(name)s" +msgstr "Περίγραμμα: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Περίγραμμα: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Αναζήτηση μονοπατιού για περίγραμμα %(name)s:" + +msgid "(does not exist)" +msgstr "(δεν υπάρχει)" + +msgid "Back to Documentation" +msgstr "Επιστροφή στην Τεκμηρίωση" + +msgid "Template filters" +msgstr "Φίλτρα περιγραμμάτων" + +msgid "Template filter documentation" +msgstr "Τεκμηρίωση φίλτρων περιγραμμάτων" + +msgid "Built-in filters" +msgstr "Ενσωματωμένα φίλτρα" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Για να χρησιμοποιήσετε αυτά τα φίλτρα, βάλτε %(code)s στο " +"περίγραμμα σας, προτού χρησιμοποιήσετε το φίλτρο." + +msgid "Template tags" +msgstr "Ετικέτες περιγραμμάτων" + +msgid "Template tag documentation" +msgstr "Τεκμηρίωση ετικετών περιγραμμάτων" + +msgid "Built-in tags" +msgstr "Ενσωματωμένες ετικέτες" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Για να χρησιμοποιήσετε αυτές τις ετικέτες, βάλτε %(code)s στο " +"περίγραμμα σας, προτού χρησιμοποιήσετε την ετικέτα." + +#, python-format +msgid "View: %(name)s" +msgstr "Οπτική: %(name)s" + +msgid "Context:" +msgstr "Πλαίσιο:" + +msgid "Templates:" +msgstr "Περιγράμματα:" + +msgid "Back to View documentation" +msgstr "Πίσω στην τεκμηρίωση του View" + +msgid "View documentation" +msgstr "Προβολή Τεκμηρίωσης" + +msgid "Jump to namespace" +msgstr "Μεταφερθείτε στο namespace" + +msgid "Empty namespace" +msgstr "Άδειο namespace" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Οπτικές ανά namespace %(name)s" + +msgid "Views by empty namespace" +msgstr "Οπτικές ανά κενό namespace" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"Συνάρτηση οπτικής: %(full_name)s. Όνομα: %(url_name)s.\n" + +msgid "tag:" +msgstr "ετικέτα:" + +msgid "filter:" +msgstr "φίλτρο:" + +msgid "view:" +msgstr "προβολή:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Η εφαρμογή %(app_label)r δεν βρέθηκε" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "" +"Το μοντέλο %(model_name)r δεν μπορεί να βρεθεί στην εφαρμογή %(app_label)r" + +msgid "model:" +msgstr "μοντέλο:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "το συσχετισμένο `%(app_label)s.%(data_type)s` αντικείμενο" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "συσχετισμένα `%(app_label)s.%(object_name)s` αντικείμενα" + +#, python-format +msgid "all %s" +msgstr "όλα %s" + +#, python-format +msgid "number of %s" +msgstr "πλήθος number of %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "Το %s δε φαίνεται να είναι ένα αντικείμενο urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/en/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/en/LC_MESSAGES/django.mo new file mode 100644 index 0000000..08a7b68 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/en/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/en/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/en/LC_MESSAGES/django.po new file mode 100644 index 0000000..34eb488 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/en/LC_MESSAGES/django.po @@ -0,0 +1,359 @@ +# This file is distributed under the same license as the Django package. +# +msgid "" +msgstr "" +"Project-Id-Version: Django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2010-05-13 15:35+0200\n" +"Last-Translator: Django team\n" +"Language-Team: English \n" +"Language: en\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: contrib/admindocs/apps.py:7 +msgid "Administrative Documentation" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/bookmarklets.html:6 +#: contrib/admindocs/templates/admin_doc/index.html:6 +#: contrib/admindocs/templates/admin_doc/missing_docutils.html:6 +#: contrib/admindocs/templates/admin_doc/model_detail.html:14 +#: contrib/admindocs/templates/admin_doc/model_index.html:8 +#: contrib/admindocs/templates/admin_doc/template_detail.html:6 +#: contrib/admindocs/templates/admin_doc/template_filter_index.html:7 +#: contrib/admindocs/templates/admin_doc/template_tag_index.html:7 +#: contrib/admindocs/templates/admin_doc/view_detail.html:6 +#: contrib/admindocs/templates/admin_doc/view_index.html:7 +msgid "Home" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/bookmarklets.html:7 +#: contrib/admindocs/templates/admin_doc/index.html:7 +#: contrib/admindocs/templates/admin_doc/index.html:10 +#: contrib/admindocs/templates/admin_doc/index.html:14 +#: contrib/admindocs/templates/admin_doc/missing_docutils.html:7 +#: contrib/admindocs/templates/admin_doc/missing_docutils.html:14 +#: contrib/admindocs/templates/admin_doc/model_detail.html:15 +#: contrib/admindocs/templates/admin_doc/model_index.html:9 +#: contrib/admindocs/templates/admin_doc/template_detail.html:7 +#: contrib/admindocs/templates/admin_doc/template_filter_index.html:8 +#: contrib/admindocs/templates/admin_doc/template_tag_index.html:8 +#: contrib/admindocs/templates/admin_doc/view_detail.html:7 +#: contrib/admindocs/templates/admin_doc/view_index.html:8 +msgid "Documentation" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/bookmarklets.html:8 +#: contrib/admindocs/templates/admin_doc/index.html:29 +msgid "Bookmarklets" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/bookmarklets.html:11 +msgid "Documentation bookmarklets" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/bookmarklets.html:15 +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +#: contrib/admindocs/templates/admin_doc/bookmarklets.html:22 +msgid "Documentation for this page" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/bookmarklets.html:23 +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" + +#: contrib/admindocs/templates/admin_doc/index.html:17 +#: contrib/admindocs/templates/admin_doc/template_tag_index.html:9 +msgid "Tags" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/index.html:18 +msgid "List of all the template tags and their functions." +msgstr "" + +#: contrib/admindocs/templates/admin_doc/index.html:20 +#: contrib/admindocs/templates/admin_doc/template_filter_index.html:9 +msgid "Filters" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/index.html:21 +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +#: contrib/admindocs/templates/admin_doc/index.html:23 +#: contrib/admindocs/templates/admin_doc/model_detail.html:16 +#: contrib/admindocs/templates/admin_doc/model_index.html:10 +#: contrib/admindocs/templates/admin_doc/model_index.html:14 +msgid "Models" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/index.html:24 +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/index.html:26 +#: contrib/admindocs/templates/admin_doc/view_detail.html:8 +#: contrib/admindocs/templates/admin_doc/view_index.html:9 +#: contrib/admindocs/templates/admin_doc/view_index.html:12 +msgid "Views" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/index.html:27 +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +#: contrib/admindocs/templates/admin_doc/index.html:30 +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +#: contrib/admindocs/templates/admin_doc/missing_docutils.html:10 +msgid "Please install docutils" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/missing_docutils.html:17 +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" + +#: contrib/admindocs/templates/admin_doc/missing_docutils.html:19 +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#: contrib/admindocs/templates/admin_doc/model_detail.html:21 +#, python-format +msgid "Model: %(name)s" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/model_detail.html:30 +msgid "Fields" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/model_detail.html:35 +msgid "Field" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/model_detail.html:36 +msgid "Type" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/model_detail.html:37 +#: contrib/admindocs/templates/admin_doc/model_detail.html:60 +msgid "Description" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/model_detail.html:53 +msgid "Methods with arguments" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/model_detail.html:58 +msgid "Method" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/model_detail.html:59 +msgid "Arguments" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/model_detail.html:76 +msgid "Back to Model documentation" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/model_index.html:18 +msgid "Model documentation" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/model_index.html:43 +msgid "Model groups" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/template_detail.html:8 +msgid "Templates" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/template_detail.html:13 +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/template_detail.html:16 +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#: contrib/admindocs/templates/admin_doc/template_detail.html:19 +#, python-format +msgid "Search path for template %(name)s:" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/template_detail.html:22 +msgid "(does not exist)" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/template_detail.html:26 +msgid "Back to Documentation" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/template_filter_index.html:12 +msgid "Template filters" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/template_filter_index.html:16 +msgid "Template filter documentation" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/template_filter_index.html:22 +#: contrib/admindocs/templates/admin_doc/template_filter_index.html:43 +msgid "Built-in filters" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/template_filter_index.html:23 +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +#: contrib/admindocs/templates/admin_doc/template_tag_index.html:12 +msgid "Template tags" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/template_tag_index.html:16 +msgid "Template tag documentation" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/template_tag_index.html:22 +#: contrib/admindocs/templates/admin_doc/template_tag_index.html:43 +msgid "Built-in tags" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/template_tag_index.html:23 +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#: contrib/admindocs/templates/admin_doc/view_detail.html:12 +#, python-format +msgid "View: %(name)s" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/view_detail.html:23 +msgid "Context:" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/view_detail.html:28 +msgid "Templates:" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/view_detail.html:32 +msgid "Back to View documentation" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/view_index.html:16 +msgid "View documentation" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/view_index.html:22 +msgid "Jump to namespace" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/view_index.html:27 +msgid "Empty namespace" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/view_index.html:40 +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/view_index.html:42 +msgid "Views by empty namespace" +msgstr "" + +#: contrib/admindocs/templates/admin_doc/view_index.html:49 +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +#: contrib/admindocs/views.py:72 contrib/admindocs/views.py:73 +#: contrib/admindocs/views.py:75 +msgid "tag:" +msgstr "" + +#: contrib/admindocs/views.py:103 contrib/admindocs/views.py:104 +#: contrib/admindocs/views.py:106 +msgid "filter:" +msgstr "" + +#: contrib/admindocs/views.py:162 contrib/admindocs/views.py:163 +#: contrib/admindocs/views.py:165 +msgid "view:" +msgstr "" + +#: contrib/admindocs/views.py:192 +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#: contrib/admindocs/views.py:196 +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "" + +#: contrib/admindocs/views.py:201 contrib/admindocs/views.py:202 +#: contrib/admindocs/views.py:217 contrib/admindocs/views.py:240 +#: contrib/admindocs/views.py:245 contrib/admindocs/views.py:260 +#: contrib/admindocs/views.py:301 contrib/admindocs/views.py:306 +msgid "model:" +msgstr "" + +#: contrib/admindocs/views.py:213 +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "" + +#: contrib/admindocs/views.py:233 contrib/admindocs/views.py:293 +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "" + +#: contrib/admindocs/views.py:240 contrib/admindocs/views.py:301 +#, python-format +msgid "all %s" +msgstr "" + +#: contrib/admindocs/views.py:245 contrib/admindocs/views.py:306 +#, python-format +msgid "number of %s" +msgstr "" + +#: contrib/admindocs/views.py:398 +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/en_AU/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/en_AU/LC_MESSAGES/django.mo new file mode 100644 index 0000000..68f8cb0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/en_AU/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/en_AU/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/en_AU/LC_MESSAGES/django.po new file mode 100644 index 0000000..4a97bca --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/en_AU/LC_MESSAGES/django.po @@ -0,0 +1,275 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2015-01-18 08:34+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: English (Australia) (http://www.transifex.com/projects/p/" +"django/language/en_AU/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_AU\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "" + +msgid "Documentation" +msgstr "" + +msgid "Bookmarklets" +msgstr "" + +msgid "Documentation bookmarklets" +msgstr "" + +msgid "" +"\n" +"

    To install bookmarklets, drag the link to your bookmarks\n" +"toolbar, or right-click the link and add it to your bookmarks. Now you can\n" +"select the bookmarklet from any page in the site. Note that some of these\n" +"bookmarklets require you to be viewing the site from a computer designated\n" +"as \"internal\" (talk to your system administrator if you aren't sure if\n" +"your computer is \"internal\").

    \n" +msgstr "" + +msgid "Documentation for this page" +msgstr "" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" + +msgid "Show object ID" +msgstr "" + +msgid "" +"Shows the content-type and unique ID for pages that represent a single " +"object." +msgstr "" + +msgid "Edit this object (current window)" +msgstr "" + +msgid "Jumps to the admin page for pages that represent a single object." +msgstr "" + +msgid "Edit this object (new window)" +msgstr "" + +msgid "As above, but opens the admin page in a new window." +msgstr "" + +msgid "Tags" +msgstr "" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Back to Model Documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to Views Documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "" + +msgid "tag:" +msgstr "" + +msgid "filter:" +msgstr "" + +msgid "view:" +msgstr "" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "" + +msgid "model:" +msgstr "" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "" + +#, python-format +msgid "all %s" +msgstr "" + +#, python-format +msgid "number of %s" +msgstr "" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/en_GB/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/en_GB/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c3a8bf5 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/en_GB/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/en_GB/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/en_GB/LC_MESSAGES/django.po new file mode 100644 index 0000000..e513e88 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/en_GB/LC_MESSAGES/django.po @@ -0,0 +1,260 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# jon_atkinson , 2011-2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: English (United Kingdom) (http://www.transifex.com/django/" +"django/language/en_GB/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_GB\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "Home" + +msgid "Documentation" +msgstr "Documentation" + +msgid "Bookmarklets" +msgstr "Bookmarklets" + +msgid "Documentation bookmarklets" +msgstr "Documentation bookmarklets" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "Documentation for this page" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Jumps you from any page to the documentation for the view that generates " +"that page." + +msgid "Tags" +msgstr "Tags" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "Filters" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "Models" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "Views" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "Templates" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "tag:" + +msgid "filter:" +msgstr "filter:" + +msgid "view:" +msgstr "view:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Model %(model_name)r not found in app %(app_label)r" + +msgid "model:" +msgstr "model:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "the related `%(app_label)s.%(data_type)s` object" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "related `%(app_label)s.%(object_name)s` objects" + +#, python-format +msgid "all %s" +msgstr "all %s" + +#, python-format +msgid "number of %s" +msgstr "number of %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s does not appear to be a urlpattern object" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/eo/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/eo/LC_MESSAGES/django.mo new file mode 100644 index 0000000..26e4989 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/eo/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/eo/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/eo/LC_MESSAGES/django.po new file mode 100644 index 0000000..e4892d9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/eo/LC_MESSAGES/django.po @@ -0,0 +1,279 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Batist D 🐍 , 2013-2016 +# Matthieu Desplantes , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-04-13 08:19+0000\n" +"Last-Translator: Matthieu Desplantes \n" +"Language-Team: Esperanto (http://www.transifex.com/django/django/language/" +"eo/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eo\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Administra dokumentaro" + +msgid "Home" +msgstr "Ĉefpaĝo" + +msgid "Documentation" +msgstr "Dokumentaro" + +msgid "Bookmarklets" +msgstr "Legosignetoj" + +msgid "Documentation bookmarklets" +msgstr "Dokumentaraj legosignetoj" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Por instali legosignetoj, trenu la ligilon ĝis via legosignan ilobreton, aŭ " +"dekstre klaku la ligilon kaj aldoni ĝin al viaj markiloj. Nun vi povas " +"elekti la legosignetoj de ajna paĝo en la retejo." + +msgid "Documentation for this page" +msgstr "Dokumentaro por tiu paĝo" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Sendas vin el ajna paĝo, al la dokumentado de la vido kiu generis tiun paĝon." + +msgid "Tags" +msgstr "Etikedoj" + +msgid "List of all the template tags and their functions." +msgstr "Listigi ĉiujn ŝablonmarkojn kaj iliajn funkciojn." + +msgid "Filters" +msgstr "Filtriloj" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Filtriloj estas agoj kiuj povas esti aplikitaj al variabloj en ŝablono por " +"ŝanĝi la eligon." + +msgid "Models" +msgstr "Modeloj" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Modeloj estas priskriboj de ĉiuj objektoj en la sistemo kaj iliaj rilataj " +"kampoj. Ĉiu modelo havas liston de kampoj kiu povas esti alirita kiel " +"ŝablona variabloj" + +msgid "Views" +msgstr "Vidoj" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Ĉiu paĝo sur la publika retejo estas produktita per vido. La vido difinas " +"kiun ŝablonon estas uzita por produkti la paĝon kaj kiuj objektoj estas " +"haveblaj en tiu ŝablono." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "Iloj por via retumilo por rapide aliri la administran funkciaron." + +msgid "Please install docutils" +msgstr "Bonvolu instali docutils-n" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Bonvolu demandi al viaj administrantoj instali docutils-n." + +#, python-format +msgid "Model: %(name)s" +msgstr "Modelo: %(name)s" + +msgid "Fields" +msgstr "Kampoj" + +msgid "Field" +msgstr "Kampo" + +msgid "Type" +msgstr "Tipo" + +msgid "Description" +msgstr "Priskribo" + +msgid "Methods with arguments" +msgstr "Metodoj kun argumentoj" + +msgid "Method" +msgstr "Metodo" + +msgid "Arguments" +msgstr "Argumentoj" + +msgid "Back to Model documentation" +msgstr "Reen al la modelo dokumentaro" + +msgid "Model documentation" +msgstr "Modelo dokumentaro" + +msgid "Model groups" +msgstr "Modelaj grupoj" + +msgid "Templates" +msgstr "Ŝablonoj" + +#, python-format +msgid "Template: %(name)s" +msgstr "Ŝablono: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Ŝablono: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "" + +msgid "(does not exist)" +msgstr "(ne ekzistas)" + +msgid "Back to Documentation" +msgstr "Reen al dokumentaro" + +msgid "Template filters" +msgstr "Ŝablonaj filtriloj" + +msgid "Template filter documentation" +msgstr "Ŝablona filtrila dokumentaro" + +msgid "Built-in filters" +msgstr "Integritaj filtriloj" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Por uzi tiujn filtrilojn, metu %(code)s en via ŝablono antaŭ " +"uzi la filtrilo." + +msgid "Template tags" +msgstr "Ŝablonaj etikedoj" + +msgid "Template tag documentation" +msgstr "Ŝablona etikeda dokumentado" + +msgid "Built-in tags" +msgstr "Integritaj etikedoj" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Por uzi tiujn etikedojn, metu %(code)s en via ŝablono antaŭ uzi " +"la etikedon." + +#, python-format +msgid "View: %(name)s" +msgstr "Vido: %(name)s" + +msgid "Context:" +msgstr "Kunteksto:" + +msgid "Templates:" +msgstr "Ŝablonoj:" + +msgid "Back to View documentation" +msgstr "Reen al vidaj dokumentaro" + +msgid "View documentation" +msgstr "Vida dokumentaro" + +msgid "Jump to namespace" +msgstr "Iri al nomspaco" + +msgid "Empty namespace" +msgstr "Malplena nomspaco" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Vidoj per nomspaco %(name)s" + +msgid "Views by empty namespace" +msgstr "Vidoj per malplenaj nomspacoj" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"Vida funkcio: %(full_name)s. Nomo: %(url_name)s.\n" + +msgid "tag:" +msgstr "etikedo:" + +msgid "filter:" +msgstr "filtro:" + +msgid "view:" +msgstr "vido:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Aplikaĵo %(app_label)r ne trovita" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Modelo %(model_name)r netrovita en aplikaĵo %(app_label)r" + +msgid "model:" +msgstr "modelo:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "la rilatita `%(app_label)s.%(data_type)s` objekto" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "rilatitaj `%(app_label)s.%(object_name)s` objektoj" + +#, python-format +msgid "all %s" +msgstr "ĉiuj %s" + +#, python-format +msgid "number of %s" +msgstr "nombro da %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s ne ŝajnas esti URLmotiva objekto" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es/LC_MESSAGES/django.mo new file mode 100644 index 0000000..bf264a8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es/LC_MESSAGES/django.po new file mode 100644 index 0000000..2747c1a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es/LC_MESSAGES/django.po @@ -0,0 +1,293 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Antoni Aloy , 2012-2013 +# Claude Paroz , 2014 +# Eduardo , 2017 +# e4db27214f7e7544f2022c647b585925_bb0e321, 2015 +# Herty Nava , 2013 +# Jannis Leidel , 2011 +# José Luis , 2016 +# Josue Naaman Nistal Guerra , 2014 +# Uriel Medina , 2020-2021 +# Veronicabh , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-02-11 05:39+0000\n" +"Last-Translator: Uriel Medina \n" +"Language-Team: Spanish (http://www.transifex.com/django/django/language/" +"es/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Documentación Administrativa" + +msgid "Home" +msgstr "Inicio" + +msgid "Documentation" +msgstr "Documentación" + +msgid "Bookmarklets" +msgstr "Bookmarklets" + +msgid "Documentation bookmarklets" +msgstr "Bookmarklets de documentación" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Para instalar bookmarklets, arrastre el enlace a su barra de favoritos, o " +"pulse con el botón derecho el enlace y añádalo a sus favoritos. Ahora puede " +"seleccionar el bookmarklet desde cualquier página del sitio. " + +msgid "Documentation for this page" +msgstr "Documentación para esta página" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Lo lleva desde cualquier página a la documentación de la vista que la genera." + +msgid "Tags" +msgstr "Etiquetas" + +msgid "List of all the template tags and their functions." +msgstr "Lista de todas la etiquetas de plantillas y sus funciones." + +msgid "Filters" +msgstr "Filtros" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Los filtros son acciones que se pueden aplicar a variables en una plantilla " +"para alterar el resultado." + +msgid "Models" +msgstr "Modelos" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Los modelos son descripciones de todos los objetos en el sistema y sus " +"campos asociados. Cada modelo tienen una lista de campos a los que se puede " +"acceder como variables de plantilla" + +msgid "Views" +msgstr "Vistas" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Cada página en el sitio público se genera a través de una vista. La vista " +"define que plantilla se usa para generar la página y que objetos están " +"disponibles para esa plantilla." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Herramientas para el navegador para acceder a funciones de administración " +"rápidamente." + +msgid "Please install docutils" +msgstr "Por favor, instale docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"El sistema de documentación del administrador requiere la librería de Python " +"docutils." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Por favor, pida al administrador que instale docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Modelo: %(name)s" + +msgid "Fields" +msgstr "Campos" + +msgid "Field" +msgstr "Campo" + +msgid "Type" +msgstr "Tipo" + +msgid "Description" +msgstr "Descripción" + +msgid "Methods with arguments" +msgstr "Métodos con argumentos" + +msgid "Method" +msgstr "Método" + +msgid "Arguments" +msgstr "Argumentos" + +msgid "Back to Model documentation" +msgstr "Volver a la documentación de modelos" + +msgid "Model documentation" +msgstr "Documentación de modelos" + +msgid "Model groups" +msgstr "Grupo de modelos" + +msgid "Templates" +msgstr "Plantillas" + +#, python-format +msgid "Template: %(name)s" +msgstr "Plantilla: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Plantilla: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Buscar ruta de la plantilla %(name)s:" + +msgid "(does not exist)" +msgstr "(no existe)" + +msgid "Back to Documentation" +msgstr "Volver a la documentación" + +msgid "Template filters" +msgstr "Filtros de plantilla" + +msgid "Template filter documentation" +msgstr "Documentación de los filtros de plantilla" + +msgid "Built-in filters" +msgstr "Filtros integrados" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Para utilizar estos filtros, incluya %(code)s en su plantilla " +"antes de usar el filtro." + +msgid "Template tags" +msgstr "Etiquetas de plantilla" + +msgid "Template tag documentation" +msgstr "Documentación de las etiquetas de plantilla" + +msgid "Built-in tags" +msgstr "Etiquetas integradas" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Para utilizar estas etiquetas, incluya %(code)s en su plantilla " +"antes de utilizar la etiqueta." + +#, python-format +msgid "View: %(name)s" +msgstr "Vista: %(name)s" + +msgid "Context:" +msgstr "Contexto:" + +msgid "Templates:" +msgstr "Plantillas:" + +msgid "Back to View documentation" +msgstr "Volver a la documentación de vistas" + +msgid "View documentation" +msgstr "Documentación de vistas" + +msgid "Jump to namespace" +msgstr "Ir al espacio de nombres" + +msgid "Empty namespace" +msgstr "Espacio de nombres vacío" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Visualizaciones por espacio de nombres %(name)s" + +msgid "Views by empty namespace" +msgstr "Visualizaciones por espacio de nombres vacío" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"Visualizar función: %(full_name)s. Nombre: %(url_name)s.\n" + +msgid "tag:" +msgstr "etiqueta:" + +msgid "filter:" +msgstr "filtro:" + +msgid "view:" +msgstr "vista:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Aplicación %(app_label)r no encontrada" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "" +"El modelo %(model_name)r no se ha encontrado en la aplicación %(app_label)r" + +msgid "model:" +msgstr "modelo:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "el objeto relacionado `%(app_label)s.%(data_type)s`" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "los objetos relacionados `%(app_label)s.%(object_name)s`" + +#, python-format +msgid "all %s" +msgstr "todo %s" + +#, python-format +msgid "number of %s" +msgstr "número de %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s no parece ser un objeto urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es_AR/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es_AR/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1bae524 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es_AR/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es_AR/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es_AR/LC_MESSAGES/django.po new file mode 100644 index 0000000..07e8021 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es_AR/LC_MESSAGES/django.po @@ -0,0 +1,286 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Federico Bond , 2013 +# Jannis Leidel , 2011 +# Ramiro Morales, 2012-2016,2019,2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-03-21 12:57+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Spanish (Argentina) (http://www.transifex.com/django/django/" +"language/es_AR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_AR\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Documentación administrativa" + +msgid "Home" +msgstr "Inicio" + +msgid "Documentation" +msgstr "Documentación" + +msgid "Bookmarklets" +msgstr "Bookmarklets" + +msgid "Documentation bookmarklets" +msgstr "Bookmarklets de documentación" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Para instalar bookmarklets, arrastre el enlace a su barra\n" +"de favoritos, o pulse con el botón derecho el enlace y añádalo a sus " +"favoritos.\n" +"Ahora puede seleccionar el bookmarklet desde cualquier página en el sitio." + +msgid "Documentation for this page" +msgstr "Documentación de esta página" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Le lleva desde cualquier página a la documentación de la vista que la genera." + +msgid "Tags" +msgstr "Etiquetas" + +msgid "List of all the template tags and their functions." +msgstr "Lista de todas las etiquetas de plantilla y sus funciones." + +msgid "Filters" +msgstr "Filtros" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Los filtros son acciones que pueden ser aplicadas a variables en una " +"plantilla para alterar el resultado final." + +msgid "Models" +msgstr "Modelos" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Los modelos son descripciones de todos los objetos en el sistema y sus " +"campos asociados. Cada modelo contiene una lista de campos accesibles como " +"variables de plantilla" + +msgid "Views" +msgstr "Vistas" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Cada página en el sitio público es generada por una vista. La vista define " +"qué plantilla es utilizada para generar la página y qué objetos están " +"disponibles para esta plantilla." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Herramientas para su navegador para acceder rápidamente a la funcionalidad " +"de administración." + +msgid "Please install docutils" +msgstr "Por favor instale docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"El sistema de documentación de admin requiere la biblioteca Python docutils." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Por favor solicite a sus administradores de sistemas que instalen docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Modelo: %(name)s" + +msgid "Fields" +msgstr "Campos" + +msgid "Field" +msgstr "Campo" + +msgid "Type" +msgstr "Tipo" + +msgid "Description" +msgstr "Descripción" + +msgid "Methods with arguments" +msgstr "Métodos con argumentos" + +msgid "Method" +msgstr "Método" + +msgid "Arguments" +msgstr "Argumentos" + +msgid "Back to Model documentation" +msgstr "Volver a documentación de modelos" + +msgid "Model documentation" +msgstr "Documentación de modelos" + +msgid "Model groups" +msgstr "Grupos de modelos" + +msgid "Templates" +msgstr "Plantillas" + +#, python-format +msgid "Template: %(name)s" +msgstr "Plantilla: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Plantilla: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Ruta de búsqueda para la plantilla %(name)s:" + +msgid "(does not exist)" +msgstr "(no existe)" + +msgid "Back to Documentation" +msgstr "Volver a la documentación" + +msgid "Template filters" +msgstr "Filtros de plantilla" + +msgid "Template filter documentation" +msgstr "Documentación de filtros de plantilla" + +msgid "Built-in filters" +msgstr "Filtros Django 'de fábrica'" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Para usar estos filtros, escriba %(code)s en su plantilla antes " +"de usar el filtro." + +msgid "Template tags" +msgstr "Etiquetas de plantilla" + +msgid "Template tag documentation" +msgstr "Documentación de etiquetas de plantilla" + +msgid "Built-in tags" +msgstr "Etiquetas Django 'de fábrica'" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Para usar estas etiquetas, escriba %(code)s en su plantilla " +"antes de usar la etiqueta." + +#, python-format +msgid "View: %(name)s" +msgstr "Vista: %(name)s" + +msgid "Context:" +msgstr "Contexto:" + +msgid "Templates:" +msgstr "Plantillas:" + +msgid "Back to View documentation" +msgstr "Volver a documentación de vistas" + +msgid "View documentation" +msgstr "Documentación de vistas" + +msgid "Jump to namespace" +msgstr "Ir a espacio de nombres" + +msgid "Empty namespace" +msgstr "Espacio de nombres vacío" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Vistas por espacio de nombres %(name)s" + +msgid "Views by empty namespace" +msgstr "Vistas por espacio de nombres vacío" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"Función vista: %(full_name)s. Nombre: %(url_name)s.\n" + +msgid "tag:" +msgstr "etiqueta:" + +msgid "filter:" +msgstr "filtro:" + +msgid "view:" +msgstr "vista:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Aplicación %(app_label)r no encontrada" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Modelo %(model_name)r no encontrado en aplicación %(app_label)r" + +msgid "model:" +msgstr "modelo:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "el objeto `%(app_label)s.%(data_type)s` relacionado" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "objetos `%(app_label)s.%(object_name)s` relacionados" + +#, python-format +msgid "all %s" +msgstr "todos los %s" + +#, python-format +msgid "number of %s" +msgstr "número de %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s no parece ser un objeto urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es_CO/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es_CO/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b4ce79b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es_CO/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es_CO/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es_CO/LC_MESSAGES/django.po new file mode 100644 index 0000000..abe7ac2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es_CO/LC_MESSAGES/django.po @@ -0,0 +1,281 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Carlos Muñoz , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 19:11+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Spanish (Colombia) (http://www.transifex.com/django/django/" +"language/es_CO/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_CO\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Documentación Administrativa" + +msgid "Home" +msgstr "Inicio" + +msgid "Documentation" +msgstr "Documentación" + +msgid "Bookmarklets" +msgstr "Bookmarklets" + +msgid "Documentation bookmarklets" +msgstr "Documentación de Bookmarklets" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Para instalar bookmarklets, arrastre el enlace a tu barra de marcadores, o " +"haga clic derecho en el enlace y agregarlo a tus marcadores. Ahora puede " +"seleccionar el bookmarklet desde cualquier página en el sitio." + +msgid "Documentation for this page" +msgstr "Documentación para esta página" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "Ir desde cualquier página a la documentación de vista que la genera." + +msgid "Tags" +msgstr "Etiquetas" + +msgid "List of all the template tags and their functions." +msgstr "Lista de todas las etiquetas de plantillas y sus funciones." + +msgid "Filters" +msgstr "Filtros" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Los filtros son acciones que pueden ser aplicadas a variables en la " +"plantilla para cambiar el resultado." + +msgid "Models" +msgstr "Modelos" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Los modelos son descripción de los objetos del sistema y sus campos " +"asociados. Cada modelo tiene una lista de campos a la que se puede acceder " +"como variables de plantilla" + +msgid "Views" +msgstr "Vistas" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Cada página del sitio es generada por una vista. En la vista se define que " +"plantilla se utilizara para generar la página y que objetos están " +"disponibles para esa plantilla." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Herramientas para su navegador para acceder rápidamente a la funcionalidad " +"de administrador" + +msgid "Please install docutils" +msgstr "Por favor instale docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" +"El sistema de documentación de la administración require la biblioteca docutils de Python." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Por favor pregunte a su administrador como instalar docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Modelo: %(name)s" + +msgid "Fields" +msgstr "Campos" + +msgid "Field" +msgstr "Campo" + +msgid "Type" +msgstr "Tipo" + +msgid "Description" +msgstr "Descripción" + +msgid "Methods with arguments" +msgstr "Métodos con argumentos" + +msgid "Method" +msgstr "Método" + +msgid "Arguments" +msgstr "Argumentos" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "Documentación del Modelo" + +msgid "Model groups" +msgstr "Grupo de modelos" + +msgid "Templates" +msgstr "Plantillas" + +#, python-format +msgid "Template: %(name)s" +msgstr "Plantilla: %(name)s" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "Plantilla: \"%(name)s\"" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "Burscar ruta para la plantilla \"%(name)s\":" + +msgid "(does not exist)" +msgstr "(no existe)" + +msgid "Back to Documentation" +msgstr "Volver a la documentación" + +msgid "Template filters" +msgstr "Filtros de plantilla" + +msgid "Template filter documentation" +msgstr "Documentación de los filtros de plantilla" + +msgid "Built-in filters" +msgstr "Filtros incorporados" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Para utilizar estos filtros, incluya %(code)s en su plantilla " +"antes de usar el filtro." + +msgid "Template tags" +msgstr "Etiquetas de plantilla" + +msgid "Template tag documentation" +msgstr "Documentación de las etiquetas de plantilla" + +msgid "Built-in tags" +msgstr "Etiquetas incorporadas" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Para utilizar estas etiquetas, incluya %(code)s en su plantilla " +"antes de utilizar la etiqueta." + +#, python-format +msgid "View: %(name)s" +msgstr "Vista: %(name)s" + +msgid "Context:" +msgstr "Contexto:" + +msgid "Templates:" +msgstr "Plantillas:" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "Documentación de la vista" + +msgid "Jump to namespace" +msgstr "Ir al namespace" + +msgid "Empty namespace" +msgstr "Namespace vacío" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Vistas por namespace %(name)s" + +msgid "Views by empty namespace" +msgstr "Vistas por namespace vacío" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"Ver función: %(full_name)s. Nombre: %(url_name)s.\n" + +msgid "tag:" +msgstr "etiqueta:" + +msgid "filter:" +msgstr "filtro:" + +msgid "view:" +msgstr "vista:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Aplicación %(app_label)r no encontrada" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Modelo %(model_name)r no encontrado en la aplicación %(app_label)r" + +msgid "model:" +msgstr "modelo:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "el objeto relacionado'%(app_label)s.%(data_type)s'" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "objectos relacionados '%(app_label)s.%(object_name)s'" + +#, python-format +msgid "all %s" +msgstr "todo %s" + +#, python-format +msgid "number of %s" +msgstr "numero de %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s no parece ser un objecto urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es_MX/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es_MX/LC_MESSAGES/django.mo new file mode 100644 index 0000000..164f061 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es_MX/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es_MX/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es_MX/LC_MESSAGES/django.po new file mode 100644 index 0000000..3242cb0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es_MX/LC_MESSAGES/django.po @@ -0,0 +1,260 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Abraham Estrada, 2011-2012 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Spanish (Mexico) (http://www.transifex.com/django/django/" +"language/es_MX/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_MX\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "Inicio" + +msgid "Documentation" +msgstr "Documentación" + +msgid "Bookmarklets" +msgstr "Bookmarklets" + +msgid "Documentation bookmarklets" +msgstr "Bookmarklets de documentación" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "Documentación de esta página" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Le lleva desde cualquier página a la documentación de la vista que la genera." + +msgid "Tags" +msgstr "Etiquetas" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "Filtros" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "Modelos" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "Vistas" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "Plantillas" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "etiqueta:" + +msgid "filter:" +msgstr "filtro:" + +msgid "view:" +msgstr "ver:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Modelo %(model_name)r no encontrado en aplicación %(app_label)r" + +msgid "model:" +msgstr "modelo:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "el objeto `%(app_label)s.%(data_type)s` relacionado" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "objetos `%(app_label)s.%(object_name)s` relacionados" + +#, python-format +msgid "all %s" +msgstr "todos los %s" + +#, python-format +msgid "number of %s" +msgstr "número de %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s no parece ser un objeto urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es_VE/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es_VE/LC_MESSAGES/django.mo new file mode 100644 index 0000000..434fc87 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es_VE/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es_VE/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es_VE/LC_MESSAGES/django.po new file mode 100644 index 0000000..bfbca39 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/es_VE/LC_MESSAGES/django.po @@ -0,0 +1,286 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Hotellook, 2014 +# Leonardo J. Caballero G. , 2016 +# Yoel Acevedo, 2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 19:11+0000\n" +"Last-Translator: Yoel Acevedo\n" +"Language-Team: Spanish (Venezuela) (http://www.transifex.com/django/django/" +"language/es_VE/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_VE\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Documentación Administrativa" + +msgid "Home" +msgstr "Inicio" + +msgid "Documentation" +msgstr "Documentación" + +msgid "Bookmarklets" +msgstr "Bookmarklets" + +msgid "Documentation bookmarklets" +msgstr "Documentación de Bookmarklets" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Para instalar bookmarklets, arrastre el enlace a tu barra de marcadores, o " +"haga clic derecho en el enlace y agregarlo a tus marcadores. Ahora puede " +"seleccionar el bookmarklet desde cualquier página en el sitio." + +msgid "Documentation for this page" +msgstr "Documentación para esta página" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Ir desde cualquier página a la documentación de vista que la genera esa " +"página." + +msgid "Tags" +msgstr "Etiquetas" + +msgid "List of all the template tags and their functions." +msgstr "Lista de todas las etiquetas de plantillas y sus funciones." + +msgid "Filters" +msgstr "Filtros" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Los filtros son acciones que pueden ser aplicadas a variables en la " +"plantilla para cambiar el resultado." + +msgid "Models" +msgstr "Modelos" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Los modelos son descripción de los objetos del sistema y sus campos " +"asociados. Cada modelo tiene una lista de campos a la que se puede acceder " +"como variables de plantilla" + +msgid "Views" +msgstr "Vistas" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Cada página del sitio es generada por una vista. En la vista se define que " +"plantilla se utilizara para generar la página y que objetos están " +"disponibles para esa plantilla." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Herramientas para su navegador para acceder rápidamente a la funcionalidad " +"de administrador." + +msgid "Please install docutils" +msgstr "Por favor, instale la biblioteca docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" +"El sistema de documentación de la administración requiere la biblioteca docutils de Python." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Por favor, pregunte a su administrador como instalar la biblioteca docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Modelo: %(name)s" + +msgid "Fields" +msgstr "Campos" + +msgid "Field" +msgstr "Campo" + +msgid "Type" +msgstr "Tipo" + +msgid "Description" +msgstr "Descripción" + +msgid "Methods with arguments" +msgstr "Métodos con argumentos" + +msgid "Method" +msgstr "Método" + +msgid "Arguments" +msgstr "Argumentos" + +msgid "Back to Model documentation" +msgstr "Volver a la documentación de Modelos" + +msgid "Model documentation" +msgstr "Documentación del Modelo" + +msgid "Model groups" +msgstr "Grupo de modelos" + +msgid "Templates" +msgstr "Plantillas" + +#, python-format +msgid "Template: %(name)s" +msgstr "Plantilla: %(name)s" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "Plantilla: \"%(name)s\"" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "Buscar ruta para la plantilla \"%(name)s\":" + +msgid "(does not exist)" +msgstr "(no existe)" + +msgid "Back to Documentation" +msgstr "Volver a la documentación" + +msgid "Template filters" +msgstr "Filtros de plantilla" + +msgid "Template filter documentation" +msgstr "Documentación de los filtros de plantilla" + +msgid "Built-in filters" +msgstr "Filtros incorporados" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Para utilizar estos filtros, incluya %(code)s en su plantilla " +"antes de usar el filtro." + +msgid "Template tags" +msgstr "Etiquetas de plantilla" + +msgid "Template tag documentation" +msgstr "Documentación de las etiquetas de plantilla" + +msgid "Built-in tags" +msgstr "Etiquetas incorporadas" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Para utilizar estas etiquetas, incluya %(code)s en su plantilla " +"antes de utilizar la etiqueta." + +#, python-format +msgid "View: %(name)s" +msgstr "Vista: %(name)s" + +msgid "Context:" +msgstr "Contexto:" + +msgid "Templates:" +msgstr "Plantillas:" + +msgid "Back to View documentation" +msgstr "Volver a la documentación de Vistas" + +msgid "View documentation" +msgstr "Documentación de la vista" + +msgid "Jump to namespace" +msgstr "Ir al namespace" + +msgid "Empty namespace" +msgstr "Namespace vacío" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Vistas por namespace %(name)s" + +msgid "Views by empty namespace" +msgstr "Vistas por namespace vacío" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +" Ver función: %(full_name)s. Nombre: %(url_name)s.\n" + +msgid "tag:" +msgstr "etiqueta:" + +msgid "filter:" +msgstr "filtro:" + +msgid "view:" +msgstr "vista:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Aplicación %(app_label)r no encontrada" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Modelo %(model_name)r no encontrado en la aplicación %(app_label)r" + +msgid "model:" +msgstr "modelo:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "el objeto relacionado '%(app_label)s.%(data_type)s'" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "objetos relacionados '%(app_label)s.%(object_name)s'" + +#, python-format +msgid "all %s" +msgstr "todo %s" + +#, python-format +msgid "number of %s" +msgstr "numero de %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s no parece ser un objeto urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/et/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/et/LC_MESSAGES/django.mo new file mode 100644 index 0000000..81898a8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/et/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/et/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/et/LC_MESSAGES/django.po new file mode 100644 index 0000000..ade7542 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/et/LC_MESSAGES/django.po @@ -0,0 +1,286 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Janno Liivak , 2013,2015 +# Martin , 2021 +# Martin , 2016 +# Marti Raudsepp , 2014 +# Ragnar Rebase , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-11-22 11:26+0000\n" +"Last-Translator: Martin \n" +"Language-Team: Estonian (http://www.transifex.com/django/django/language/" +"et/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: et\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Administreerimise Dokumentatsioon" + +msgid "Home" +msgstr "Kodu" + +msgid "Documentation" +msgstr "Dokumentatsioon" + +msgid "Bookmarklets" +msgstr "Järjehoidjandid" + +msgid "Documentation bookmarklets" +msgstr "Dokumentatsiooni järjehoidjandid" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Järjehoidjandite paigaldamiseks lohista viit järjehoidjateribale või tee " +"parem-klikk viidal ning lisa see järjehoidjatesse. Seejärel võite " +"järjehoidjandi aktiveerida suvaliselt saidi lehelt." + +msgid "Documentation for this page" +msgstr "Selle lehekülje dokumentatsioon" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Suunab teid suvalisel lehel asudes selle vaate dokumentatsioonile, mis antud " +"lehe genereerib." + +msgid "Tags" +msgstr "Lipikud" + +msgid "List of all the template tags and their functions." +msgstr "Nimekiri kõikidest malli märgistustest ja nende funktsioonidest." + +msgid "Filters" +msgstr "Filtrid" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Filtrid on tegevused, mida saab mallides külge panna muutujatele muutmaks " +"viimaste väljundit." + +msgid "Models" +msgstr "Mudelid" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Mudelid on süsteemi kõikide objektide ja nende väljade omavaheliste seoste " +"kirjeldused. Igal mudelil on hulk väljasid, mida saab mallide muutujatena " +"kasutada" + +msgid "Views" +msgstr "Vaated" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Avaliku saidi iga leht on genereeritud vaate poolt. Vaade defineerib lehe " +"genereerimiseks kasutatava malli ning objektid mida mall kasutada saab." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Töövahendid sinu brauserile pääsemaks kiiresti ligi administraatori " +"funktsioonidele. " + +msgid "Please install docutils" +msgstr "Palun paigaldage docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Administreerimise dokumentatsioon vajab Python'i docutils teeki." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "Palu administraatoril paigaldada docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Mudel: %(name)s" + +msgid "Fields" +msgstr "Väljad" + +msgid "Field" +msgstr "Väli" + +msgid "Type" +msgstr "Tüüp" + +msgid "Description" +msgstr "Kirjeldus" + +msgid "Methods with arguments" +msgstr "Meetodid parameetritega" + +msgid "Method" +msgstr "Meetod" + +msgid "Arguments" +msgstr "Parameetrid" + +msgid "Back to Model documentation" +msgstr "Tagasi Mudeli dokumentatsiooni" + +msgid "Model documentation" +msgstr "Mudeli dokumentatsioon" + +msgid "Model groups" +msgstr "Mudeligrupid" + +msgid "Templates" +msgstr "Mallid" + +#, python-format +msgid "Template: %(name)s" +msgstr "Mall: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Mall: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Otsinguteekond mallile %(name)s:" + +msgid "(does not exist)" +msgstr "(pole olemas)" + +msgid "Back to Documentation" +msgstr "Tagasi Dokumentatsiooni" + +msgid "Template filters" +msgstr "Mallifiltrid" + +msgid "Template filter documentation" +msgstr "Mallifiltrite dokumentatsioon" + +msgid "Built-in filters" +msgstr "Sisseehitatud filtrid" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Et kasutada neid filtreid, pane malli sisse %(code)s enne kui " +"kasutad filtrit." + +msgid "Template tags" +msgstr "Malli märgendid" + +msgid "Template tag documentation" +msgstr "Malli märgendite dokumentatsioon" + +msgid "Built-in tags" +msgstr "Sisseehitatud märgendid" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Et kasutada neid märgendeid pane malli %(code)s enne kui " +"kasutad märgendit." + +#, python-format +msgid "View: %(name)s" +msgstr "Vaade: %(name)s" + +msgid "Context:" +msgstr "Kontekst:" + +msgid "Templates:" +msgstr "Mallid:" + +msgid "Back to View documentation" +msgstr "Tagasi Vaate dokumentatsiooni" + +msgid "View documentation" +msgstr "Vaata dokumentatsiooni" + +msgid "Jump to namespace" +msgstr "Mine nimeruumile" + +msgid "Empty namespace" +msgstr "Tühi nimeruum" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Vaated nimeruumi kaupa %(name)s" + +msgid "Views by empty namespace" +msgstr "Vaated tühja nimeruumi kaupa" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"Vaate funktsioon: %(full_name)s. Nimi: %(url_name)s.\n" + +msgid "tag:" +msgstr "lipik:" + +msgid "filter:" +msgstr "filtreeri:" + +msgid "view:" +msgstr "vaade:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Rakendust %(app_label)r ei leitud" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Mudelit %(model_name)r ei leitud rakendusest %(app_label)r" + +msgid "model:" +msgstr "mudel:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "seotud `%(app_label)s.%(data_type)s` objekt" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "seotud `%(app_label)s.%(object_name)s` objektid" + +#, python-format +msgid "all %s" +msgstr "kõik %s" + +#, python-format +msgid "number of %s" +msgstr "%s arv" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s ei tundu olevat urlpattern objekt" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/eu/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/eu/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d72319b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/eu/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/eu/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/eu/LC_MESSAGES/django.po new file mode 100644 index 0000000..055d056 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/eu/LC_MESSAGES/django.po @@ -0,0 +1,283 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Aitzol Naberan , 2011-2013 +# Eneko Illarramendi , 2017 +# Jannis Leidel , 2011 +# Urtzi Odriozola , 2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-25 09:47+0000\n" +"Last-Translator: Urtzi Odriozola \n" +"Language-Team: Basque (http://www.transifex.com/django/django/language/eu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Kudeaketa dokumentazioa" + +msgid "Home" +msgstr "Hasiera" + +msgid "Documentation" +msgstr "Dokumentazioa" + +msgid "Bookmarklets" +msgstr "Markadoreak" + +msgid "Documentation bookmarklets" +msgstr "Dokumentazio markadoreak" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Markadoreak instalatzeko eraman linka zure erreminta panelera (toolbar), edo " +"eskuineko botoiarekin klik egin eta gehitu erreminta panelera. Orain edozein " +"markadore aukera dezakezu webguneko edozein orrialdetatik." + +msgid "Documentation for this page" +msgstr "Web orri honen dokumentazioa" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Edozein orritik, orria sortzen duen bistaren dokumentaziora eramango zaitu." + +msgid "Tags" +msgstr "Etiketak" + +msgid "List of all the template tags and their functions." +msgstr "Template tag guztien eta beraien funtzioen zerrnda." + +msgid "Filters" +msgstr "Iragazkiak" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Txantiloi barneko aldagaien irteera aldatzeko aplikatzen diren ekintzak dira " +"Filter-ak." + +msgid "Models" +msgstr "Ereduak" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Sisteman definitutako objektu eta beraien eremuen zehaztapenak dira " +"modeloak. Modelo bakoitzak eremu zerrenda bat dauka eta eremu hauetako " +"bakoitza txantiloietako aldagai gisa atzitu daiteke." + +msgid "Views" +msgstr "Bistak" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Webgune publikoan agertzen den orri bakoitza bista batek sortzen du. Bistak " +"zehazten duzein txantiloi erabiliko den eta honek eskuragarri izango dituen " +"objektuak." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "Adminera azkar sartzeko arakatzailearentzako tresnak" + +msgid "Please install docutils" +msgstr "Instalatu docutils mesedez" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" +"Admin dokumentazio sostemak Pythonen docutils " +"liburutegia behar du." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Eskatu zure administratzaileari docutils " +"instalatzeko." + +#, python-format +msgid "Model: %(name)s" +msgstr "Modeloa: %(name)s" + +msgid "Fields" +msgstr "Eremuak" + +msgid "Field" +msgstr "Eremua" + +msgid "Type" +msgstr "Mota" + +msgid "Description" +msgstr "Deskribapena" + +msgid "Methods with arguments" +msgstr "Argumentudun metodoak" + +msgid "Method" +msgstr "Metodoa" + +msgid "Arguments" +msgstr "Argumentuak" + +msgid "Back to Model documentation" +msgstr "Bueltatu Modeloaren Dokumentaziora" + +msgid "Model documentation" +msgstr "Modeloaren dokumentazioa" + +msgid "Model groups" +msgstr "Modelo taldeak" + +msgid "Templates" +msgstr "Txantiloiak" + +#, python-format +msgid "Template: %(name)s" +msgstr "Txantiloia: %(name)s" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "Txantiloia: \"%(name)s\"" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "\"%(name)s\" txantiloiaren bilaketa bidea:" + +msgid "(does not exist)" +msgstr "(ez da existitzen)" + +msgid "Back to Documentation" +msgstr "Bueltatu Dokumentaziora" + +msgid "Template filters" +msgstr "Txantiloi iragazkiak" + +msgid "Template filter documentation" +msgstr "Txantiloi iragazkien dokumentazioa" + +msgid "Built-in filters" +msgstr "Iragazki integratuak" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Iragazki hauek erabiltzeko jarri %(code)s iragazkia erabili " +"aurretik zure txantiloian" + +msgid "Template tags" +msgstr "Template tags" + +msgid "Template tag documentation" +msgstr "Template tag documentazioa" + +msgid "Built-in tags" +msgstr "Etiketa integratuak" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Tag hauek erabiltzeko, jarri %(code)s txantiloian taga erabili " +"aurretik." + +#, python-format +msgid "View: %(name)s" +msgstr "View: %(name)s" + +msgid "Context:" +msgstr "Kontextua:" + +msgid "Templates:" +msgstr "Txantiloia:" + +msgid "Back to View documentation" +msgstr "Bueltatu Bisten Dokumentaziora" + +msgid "View documentation" +msgstr "Bisten dokumentazioa" + +msgid "Jump to namespace" +msgstr "Joan izen-espaziora" + +msgid "Empty namespace" +msgstr "Izen-espazio hutsa" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Bistak %(name)s izen-espazio arabera" + +msgid "Views by empty namespace" +msgstr "Bistak izen-espazio hutsen arabera" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +" Bista funtzioa: %(full_name)s. Izena: %(url_name)s.\n" + +msgid "tag:" +msgstr "etiketa:" + +msgid "filter:" +msgstr "filtroa:" + +msgid "view:" +msgstr "bista:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "%(app_label)r aplikazioa ez da aurkitu" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "%(model_name)r modeloa ez da aurkitu %(app_label)r aplikazioan" + +msgid "model:" +msgstr "modeloa:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "erlazionatutako `%(app_label)s.%(data_type)s` objektua" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "erlazionatutako `%(app_label)s.%(object_name)s` objektuak" + +#, python-format +msgid "all %s" +msgstr "%s dena" + +#, python-format +msgid "number of %s" +msgstr "%s zenbakia" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s ez dirudi url heredu objetua" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/fa/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/fa/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5ef8683 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/fa/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/fa/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/fa/LC_MESSAGES/django.po new file mode 100644 index 0000000..5e2266d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/fa/LC_MESSAGES/django.po @@ -0,0 +1,285 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ali Nikneshan , 2011-2012,2020 +# Ali Vakilzade , 2015 +# Eric Hamiter , 2013 +# Jannis Leidel , 2011 +# Pouya Abbassi, 2016 +# rahim agh , 2021 +# Reza Mohammadi , 2013-2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-04-03 06:13+0000\n" +"Last-Translator: rahim agh \n" +"Language-Team: Persian (http://www.transifex.com/django/django/language/" +"fa/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fa\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Administrative Documentation" +msgstr "مستندات مدیریت" + +msgid "Home" +msgstr "خانه" + +msgid "Documentation" +msgstr "مستندات" + +msgid "Bookmarklets" +msgstr "Bookmarklet ها" + +msgid "Documentation bookmarklets" +msgstr "مستندات bookmarklet ها" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"برای نصب بوکمارکلت‌ها، لینک را به نوار‌ابزار بوکمارک خود بکشید، یا راست‌کلیک " +"کنید و به بوکمارکهای خود اضافه کنید. حالا شما میتوانید از هر صفحه ای در سایت " +"بوکمارکلت انتخاب کنید." + +msgid "Documentation for this page" +msgstr "مستندات این صفحه" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"شما را از هر صفحه‌ای که باشید به مستندات نمایی که صفحه را ایجاد کرده می‌برد" + +msgid "Tags" +msgstr "برچسب‌ها" + +msgid "List of all the template tags and their functions." +msgstr "لیست همه برچسب‌های قالب‌ها و توابعشان" + +msgid "Filters" +msgstr "فیلترها" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"فیلترها عملیاتی هستند که میتوان روی متغیرها و قالب‌ها اعمال شود تا خروجی را " +"تغییر دهند." + +msgid "Models" +msgstr "مدل‌ها" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"مدلها توضحاتی هستند از اشیایی در سیستم و فیلدهای مرتبط. هر مدل یک لیست از " +"فیلد یک لیست از فیلدها را دارد که میتواند از طریق متغیرهای قالب در دسترس " +"قرار بگیرد." + +msgid "Views" +msgstr "نمایش ها" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"هر صفحه در وبسایت عمومی با یک نمایش ساخته میشود. نمایش تعیین میکند کدام قالب " +"برای ساخت صفحه استفاده شود و کدام شیء برای قالب در دسترس باشد." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "ابزار مرورگر خود را به سرعت قابلیت اداری دسترسی داشته باشید." + +msgid "Please install docutils" +msgstr "لطفاً docutils نصب کنید" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"سیستم مستندات مدیر نیازمند کتابخانه‌ی docutils " +"پایتون است." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"لطفا از مدیر خود درخواست کنید تا کتابخانه‌ی docutils " +"را نصب کند." + +#, python-format +msgid "Model: %(name)s" +msgstr "مدل: %(name)s" + +msgid "Fields" +msgstr "فیلدها" + +msgid "Field" +msgstr "فیلد" + +msgid "Type" +msgstr "نوع" + +msgid "Description" +msgstr "توضیحات" + +msgid "Methods with arguments" +msgstr "متدهایی با آرگومانها" + +msgid "Method" +msgstr "متد" + +msgid "Arguments" +msgstr "آرکومانها" + +msgid "Back to Model documentation" +msgstr "برگشت به مستندات مدل" + +msgid "Model documentation" +msgstr "مستندات مدل" + +msgid "Model groups" +msgstr "گروه‌های مدل" + +msgid "Templates" +msgstr "قالب‌ها" + +#, python-format +msgid "Template: %(name)s" +msgstr "قالب: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "قالب: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "مسیر جستجو برای قالب \"%(name)s\":" + +msgid "(does not exist)" +msgstr "(وجود ندارد)" + +msgid "Back to Documentation" +msgstr "برگشت به مستندات" + +msgid "Template filters" +msgstr "فیلترهای قالب" + +msgid "Template filter documentation" +msgstr "مستندات فیلتر قالب" + +msgid "Built-in filters" +msgstr "فیلترهای از اول موجود" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"برای استفاده از این فیلترها، کد %(code)s را قبل از استفاده از " +"فیلتر، در قالب قرار دهید." + +msgid "Template tags" +msgstr "برچسب‌های قالب" + +msgid "Template tag documentation" +msgstr "مستندات برچسب قالب" + +msgid "Built-in tags" +msgstr "برچسب‌های از اول موجود" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"برای استفاده از این تگ‌ها، کد %(code)s را قبل از استفاده از تگ، " +"در قالب قرار دهید." + +#, python-format +msgid "View: %(name)s" +msgstr "نمایش: %(name)s" + +msgid "Context:" +msgstr "زمینه:" + +msgid "Templates:" +msgstr "قالب‌ها:" + +msgid "Back to View documentation" +msgstr "برگشت به مستندات نمایش" + +msgid "View documentation" +msgstr "مشاهده مستندات" + +msgid "Jump to namespace" +msgstr "پرش به فضای نام" + +msgid "Empty namespace" +msgstr "فضای نام خالی" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "نمایشها بر اساس فضای نام %(name)s" + +msgid "Views by empty namespace" +msgstr "نمایشها بر اساس فضای نام خالی" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"نمایش تابع: %(full_name)s. نام: %(url_name)s.\n" + +msgid "tag:" +msgstr "برچسب:" + +msgid "filter:" +msgstr "فیلتر" + +msgid "view:" +msgstr "نمایش:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "برنامه‌ی %(app_label)r پیدا نشد" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "مدل %(model_name)r در برنامهٔ %(app_label)r یافت نشد" + +msgid "model:" +msgstr "مدل:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "شیء «%(app_label)s.%(data_type)s» مرتبط" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "اشیاء «%(app_label)s.%(object_name)s» مرتبط" + +#, python-format +msgid "all %s" +msgstr "همهٔ %s" + +#, python-format +msgid "number of %s" +msgstr "تعداد %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "به نظر نمی رسد %s یک شیء از نوع urlpattern باشد" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/fi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/fi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8886f15 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/fi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/fi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/fi/LC_MESSAGES/django.po new file mode 100644 index 0000000..bec75c9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/fi/LC_MESSAGES/django.po @@ -0,0 +1,278 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Aarni Koskela, 2015,2017,2020-2021 +# Elias Luttinen , 2015 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-04-14 12:19+0000\n" +"Last-Translator: Aarni Koskela\n" +"Language-Team: Finnish (http://www.transifex.com/django/django/language/" +"fi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Hallinnan ohjeet" + +msgid "Home" +msgstr "Etusivu" + +msgid "Documentation" +msgstr "Ohjeita" + +msgid "Bookmarklets" +msgstr "Kirjanmerkkiset" + +msgid "Documentation bookmarklets" +msgstr "Ohjeiden kirjanmerkkiset" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Asenna kirjanmerkkinen raahaamalla linkki kirjanmerkkien työkalupalkkiin tai " +"napsauttamalla linkkiä oikeanpuoleisella hiiren painikkeella ja valitsemalla " +"kirjanmerkkeihin lisäämisen. Sen jälkeen voit valita kirjanmerkkisen miltä " +"tahansa sivuston sivulta." + +msgid "Documentation for this page" +msgstr "Tämän sivun ohjeita" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "Näyttää ohjeet, jotka koskevat ko. sivun luonutta näkymää." + +msgid "Tags" +msgstr "Tagit" + +msgid "List of all the template tags and their functions." +msgstr "Lista kaikista mallinetunnisteista ja niiden toiminnasta." + +msgid "Filters" +msgstr "Suodattimet" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Suotimet ovat toimintoja, jotka käsittelevät mallineessa käytettävän " +"muuttujan ulostuloa." + +msgid "Models" +msgstr "Mallit" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Mallit kuvaavat järjestelmän kaikkia objekteja ja niihin liittyviä kenttiä. " +"Kenttiä pystyy käyttämään mallineista mallinemuuttujina." + +msgid "Views" +msgstr "Näkymät" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Jokainen sivuston sivu on näkymän luoma. Näkymä määrittelee mitä mallinetta " +"sivun luontiin käytetään ja mitä objekteja mallineella on käytössä." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "Selaintyökaluja, joilla pääset nopeasti hallinnointitoimintoihin." + +msgid "Please install docutils" +msgstr "Ole hyvä ja asenna docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Hallinnan dokumentaatio vaatii Pythonin docutils-" +"kirjaston." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "Pyydä ylläpitäjiä asentamaan docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Malli: %(name)s" + +msgid "Fields" +msgstr "Kentät" + +msgid "Field" +msgstr "Kenttä" + +msgid "Type" +msgstr "Tyyppi" + +msgid "Description" +msgstr "Selite" + +msgid "Methods with arguments" +msgstr "Metodit argumentteineen" + +msgid "Method" +msgstr "Metodi" + +msgid "Arguments" +msgstr "Argumentit" + +msgid "Back to Model documentation" +msgstr "Takaisin mallidokumentaatioon" + +msgid "Model documentation" +msgstr "Mallidokumentaatio" + +msgid "Model groups" +msgstr "Malliryhmät" + +msgid "Templates" +msgstr "Mallineet" + +#, python-format +msgid "Template: %(name)s" +msgstr "Malline: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Malline: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Mallineen %(name)s hakupolku" + +msgid "(does not exist)" +msgstr "(ei ole olemassa)" + +msgid "Back to Documentation" +msgstr "Takaisin dokumentaatioon" + +msgid "Template filters" +msgstr "Mallinesuotimet" + +msgid "Template filter documentation" +msgstr "Mallinesuodindokumentaatio" + +msgid "Built-in filters" +msgstr "Sisäänrakennetut suotimet" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Käyttääksesi näitä suotimia, sisällytä %(code)s mallineesi " +"alkuun." + +msgid "Template tags" +msgstr "Mallinetunnisteet" + +msgid "Template tag documentation" +msgstr "Mallinetunnistedokumentaatio" + +msgid "Built-in tags" +msgstr "Sisäänrakennetut tunnisteet" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Käyttääksesi näitä tunnisteita, sisällytä %(code)s mallineesi " +"alkuun." + +#, python-format +msgid "View: %(name)s" +msgstr "Näkymä: %(name)s" + +msgid "Context:" +msgstr "Konteksti:" + +msgid "Templates:" +msgstr "Mallineet:" + +msgid "Back to View documentation" +msgstr "Takaisin näkymädokumentaatioon" + +msgid "View documentation" +msgstr "Näkymädokumentaatio" + +msgid "Jump to namespace" +msgstr "Siirry nimiavaruuteen" + +msgid "Empty namespace" +msgstr "Tyhjä nimiavaruus" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Näkymät nimiavaruuden %(name)s mukaan" + +msgid "Views by empty namespace" +msgstr "Näkymät tyhjän nimiavaruuden mukaan" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"Näkymäfunktio: %(full_name)s. Nimi: %(url_name)s.\n" + +msgid "tag:" +msgstr "tagi:" + +msgid "filter:" +msgstr "suodatin:" + +msgid "view:" +msgstr "näkymä:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Sovellusta %(app_label)r ei löydy" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Sovelluksesta %(app_label)r ei löydy mallia %(model_name)r" + +msgid "model:" +msgstr "malli:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "tähän liittyvä `%(app_label)s.%(data_type)s`-kohde" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "tähän liittyvät `%(app_label)s.%(object_name)s`-kohteet" + +#, python-format +msgid "all %s" +msgstr "kaikki %s" + +#, python-format +msgid "number of %s" +msgstr "%s-kohteiden lukumäärä" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s ei näytä olevan urlpattern-olio" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/fr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/fr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8a47fb9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/fr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/fr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 0000000..81e0571 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,285 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Claude Paroz , 2013-2016,2018-2019,2021 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-01-15 14:25+0000\n" +"Last-Translator: Claude Paroz \n" +"Language-Team: French (http://www.transifex.com/django/django/language/fr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Administrative Documentation" +msgstr "Documentation technique" + +msgid "Home" +msgstr "Accueil" + +msgid "Documentation" +msgstr "Documentation" + +msgid "Bookmarklets" +msgstr "Signets" + +msgid "Documentation bookmarklets" +msgstr "Documentation des signets" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Pour installer des signets, faites glisser le lien vers votre barre de " +"marques-pages, ou effectuez un clic droit sur le lien et ajoutez-le. " +"Maintenant, vous pouvez le sélectionner depuis n'importe quelle page du site." + +msgid "Documentation for this page" +msgstr "Documentation pour cette page" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Vous envoie de n'importe quelle page vers la documentation de la vue qui a " +"généré cette page." + +msgid "Tags" +msgstr "Balises" + +msgid "List of all the template tags and their functions." +msgstr "Liste de toutes les balises de gabarit et leur fonction." + +msgid "Filters" +msgstr "Filtres" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Les filtres sont des actions qui peuvent être appliquées à des variables " +"dans un gabarit pour modifier leur valeur affichée." + +msgid "Models" +msgstr "Modèles" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Les modèles sont des descriptions de tous les objets du système avec leurs " +"champs associés. Chaque modèle possède une liste de champs auxquels on peut " +"accéder comme pour les variables de gabarit" + +msgid "Views" +msgstr "Vues" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Chaque page du site public est générée par une vue. La vue détermine le " +"gabarit utilisé pour générer la page ainsi que les objets qui sont " +"disponibles dans le gabarit." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Outils permettant au navigateur d'accéder rapidement aux fonctionnalités de " +"l'interface d'administration." + +msgid "Please install docutils" +msgstr "Veuillez installer docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Le système de documentation de l'interface d'administration nécessite la " +"bibliothèque Python docutils." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Demandez à votre administrateur système d'installer docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Modèle : %(name)s" + +msgid "Fields" +msgstr "Champs" + +msgid "Field" +msgstr "Champ" + +msgid "Type" +msgstr "Type" + +msgid "Description" +msgstr "Description" + +msgid "Methods with arguments" +msgstr "Méthodes avec paramètres" + +msgid "Method" +msgstr "Méthode" + +msgid "Arguments" +msgstr "Paramètres" + +msgid "Back to Model documentation" +msgstr "Retour à la documentation des modèles" + +msgid "Model documentation" +msgstr "Documentation des modèles" + +msgid "Model groups" +msgstr "Groupes de modèles" + +msgid "Templates" +msgstr "Gabarits" + +#, python-format +msgid "Template: %(name)s" +msgstr "Gabarit : %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Gabarit : %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Chemin de recherche du gabarit %(name)s :" + +msgid "(does not exist)" +msgstr "(n'existe pas)" + +msgid "Back to Documentation" +msgstr "Retour à la documentation" + +msgid "Template filters" +msgstr "Filtres de gabarit" + +msgid "Template filter documentation" +msgstr "Documentation des filtres de gabarit" + +msgid "Built-in filters" +msgstr "Filtres intégrés" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Pour utiliser ces filtres, placez %(code)s dans votre gabarit " +"avant d'utiliser un des filtres." + +msgid "Template tags" +msgstr "Balises de gabarit" + +msgid "Template tag documentation" +msgstr "Documentation des balises de gabarit" + +msgid "Built-in tags" +msgstr "Balises intégrées" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Pour utiliser ces balises, placez %(code)s dans le gabarit " +"avant d'utiliser une des balises." + +#, python-format +msgid "View: %(name)s" +msgstr "Vue : %(name)s" + +msgid "Context:" +msgstr "Contexte :" + +msgid "Templates:" +msgstr "Gabarits :" + +msgid "Back to View documentation" +msgstr "Retour à la documentation des vues" + +msgid "View documentation" +msgstr "Documentation des vues" + +msgid "Jump to namespace" +msgstr "Aller à l'espace de noms" + +msgid "Empty namespace" +msgstr "Espace de noms vide" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Vues par espace de noms %(name)s" + +msgid "Views by empty namespace" +msgstr "Vues par espace de noms vide" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"Fonction de vue : %(full_name)s. Nom : %(url_name)s.\n" + +msgid "tag:" +msgstr "mot-clé :" + +msgid "filter:" +msgstr "filtre :" + +msgid "view:" +msgstr "vue :" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "L'application %(app_label)r n'a pas été trouvée" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "" +"Le modèle %(model_name)r n'a pas été trouvé dans l'application %(app_label)r" + +msgid "model:" +msgstr "modèle :" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "l'objet « %(app_label)s.%(data_type)s » en relation" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "les objets « %(app_label)s.%(object_name)s » en relation" + +#, python-format +msgid "all %s" +msgstr "tous les %s" + +#, python-format +msgid "number of %s" +msgstr "nombre de %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s ne semble pas être un objet urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/fy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/fy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2b14503 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/fy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/fy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/fy/LC_MESSAGES/django.po new file mode 100644 index 0000000..f962a4d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/fy/LC_MESSAGES/django.po @@ -0,0 +1,275 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2015-01-18 08:34+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Western Frisian (http://www.transifex.com/projects/p/django/" +"language/fy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fy\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "" + +msgid "Documentation" +msgstr "" + +msgid "Bookmarklets" +msgstr "" + +msgid "Documentation bookmarklets" +msgstr "" + +msgid "" +"\n" +"

    To install bookmarklets, drag the link to your bookmarks\n" +"toolbar, or right-click the link and add it to your bookmarks. Now you can\n" +"select the bookmarklet from any page in the site. Note that some of these\n" +"bookmarklets require you to be viewing the site from a computer designated\n" +"as \"internal\" (talk to your system administrator if you aren't sure if\n" +"your computer is \"internal\").

    \n" +msgstr "" + +msgid "Documentation for this page" +msgstr "" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" + +msgid "Show object ID" +msgstr "" + +msgid "" +"Shows the content-type and unique ID for pages that represent a single " +"object." +msgstr "" + +msgid "Edit this object (current window)" +msgstr "" + +msgid "Jumps to the admin page for pages that represent a single object." +msgstr "" + +msgid "Edit this object (new window)" +msgstr "" + +msgid "As above, but opens the admin page in a new window." +msgstr "" + +msgid "Tags" +msgstr "" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Back to Model Documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to Views Documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "" + +msgid "tag:" +msgstr "" + +msgid "filter:" +msgstr "" + +msgid "view:" +msgstr "" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "" + +msgid "model:" +msgstr "" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "" + +#, python-format +msgid "all %s" +msgstr "" + +#, python-format +msgid "number of %s" +msgstr "" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ga/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ga/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ebd4321 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ga/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ga/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ga/LC_MESSAGES/django.po new file mode 100644 index 0000000..d786e70 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ga/LC_MESSAGES/django.po @@ -0,0 +1,262 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Luke Blaney , 2019 +# Michael Thornhill , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2019-06-22 21:37+0000\n" +"Last-Translator: Luke Blaney \n" +"Language-Team: Irish (http://www.transifex.com/django/django/language/ga/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ga\n" +"Plural-Forms: nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : " +"4);\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "Baile" + +msgid "Documentation" +msgstr "Doiciméadúchán" + +msgid "Bookmarklets" +msgstr "Leabharmharcín" + +msgid "Documentation bookmarklets" +msgstr "Leabharmharcín doiciméadúchán" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "Doiciméadúchán le hadhaigh an leathanach seo" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Tógann se tusa ón aon leathanach go dtí an doiciméadúchán le hadhaigh an " +"radharc a rinne an leathanach." + +msgid "Tags" +msgstr "Clibeanna" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "Scagairí" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "Samhla" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "Radharcanna" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "Cineál" + +msgid "Description" +msgstr "" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "Teimpléid" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "clib:" + +msgid "filter:" +msgstr "scag:" + +msgid "view:" +msgstr "radharc:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Ní bhfuarthas samhail %(model_name)r i bhfeidhmclár %(app_label)r" + +msgid "model:" +msgstr "samhail:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "An oibiacht gaolmhara `%(app_label)s.%(data_type)s`" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "Oibiachtí gaolmhara `%(app_label)s.%(object_name)s`" + +#, python-format +msgid "all %s" +msgstr "gach %s" + +#, python-format +msgid "number of %s" +msgstr "líon %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "Feiceann sé nach bhfuil %s oibiacht urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/gd/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/gd/LC_MESSAGES/django.mo new file mode 100644 index 0000000..19f0f72 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/gd/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/gd/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/gd/LC_MESSAGES/django.po new file mode 100644 index 0000000..bb8b1b4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/gd/LC_MESSAGES/django.po @@ -0,0 +1,289 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# GunChleoc, 2015-2016 +# GunChleoc, 2015 +# GunChleoc, 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-07-15 10:42+0000\n" +"Last-Translator: GunChleoc\n" +"Language-Team: Gaelic, Scottish (http://www.transifex.com/django/django/" +"language/gd/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: gd\n" +"Plural-Forms: nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : " +"(n > 2 && n < 20) ? 2 : 3;\n" + +msgid "Administrative Documentation" +msgstr "Docamaideadh na rianachd" + +msgid "Home" +msgstr "Dhachaigh" + +msgid "Documentation" +msgstr "Docamaideadh" + +msgid "Bookmarklets" +msgstr "Bookmarklets" + +msgid "Documentation bookmarklets" +msgstr "Bookmarklets an docamaididh" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Gus bookmarklet a stàladh, slaodaich an ceangal gu bàr-inneal nan comharran-" +"lìn agad no dèan briogadh deas air a’ cheangal is cuir e ris na comharran-" +"lìn agad. ’S urrainn dhut am bookmarklet a thaghadh o duilleag sam bith san " +"làrach an uairsin." + +msgid "Documentation for this page" +msgstr "Docamaideadh airson na duilleige seo" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Gearraidh tu leum o duilleag sam bith dhan docamaideadh airson an t-" +"seallaidh a ghineas an duilleag sin." + +msgid "Tags" +msgstr "Tagaichean" + +msgid "List of all the template tags and their functions." +msgstr "" +"Liosta dhe thagaichean nan ùrlaran uile ’s dhe na foincseanan a th’ aca." + +msgid "Filters" +msgstr "Criathragan" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"’S e gnìomhan a tha sna criathragan as urrainn dhut cur an sàs air " +"caochladairean ann an teamplaid gus an t-às-chur atharrachadh." + +msgid "Models" +msgstr "Modailean" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"’S e tuairisgeulan air a h-uile oibseact san t-siostam ’s air na raointean " +"co-cheangailte riutha-san a tha sna modailean. Tha liosta dhe raointean aig " +"gach modail as urrainn dhut inntrigeadh mar chaochladairean teamplaide" + +msgid "Views" +msgstr "Seallaidhean" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Thèid gach duilleag air an làrach phoblach a ghintinn le sealladh. Mìnichidh " +"an sealladh dè an teamplaid a thèid a chleachdadh gus an duilleag a ghintinn " +"agus dè na h-oibseactan as urrainn dhan teamplaid ud a chleachdadh." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Innealan airson a’ bhrabhsair agad gus gnìomhan nan rianairean inntrigeadh " +"gu luath." + +msgid "Please install docutils" +msgstr "Stàlaich docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Tha siostam docamaideadh na rianachd feumach air an leabharlann docutils aig Python." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Iarr air na rianairean agad gun stàlaich iad docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Modail: %(name)s" + +msgid "Fields" +msgstr "Raointean" + +msgid "Field" +msgstr "Raoin" + +msgid "Type" +msgstr "Seòrsa" + +msgid "Description" +msgstr "Tuairisgeul" + +msgid "Methods with arguments" +msgstr "Modhan le argamaidean" + +msgid "Method" +msgstr "Modh" + +msgid "Arguments" +msgstr "Argamaidean" + +msgid "Back to Model documentation" +msgstr "Till gu docamaideadh modail" + +msgid "Model documentation" +msgstr "Docamaideadh modail" + +msgid "Model groups" +msgstr "Buidhnean modail" + +msgid "Templates" +msgstr "Teamplaidean" + +#, python-format +msgid "Template: %(name)s" +msgstr "Teamplaid: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Teamplaid: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Lorg slighe airson teamplaid %(name)s:" + +msgid "(does not exist)" +msgstr "(chan eil e ann)" + +msgid "Back to Documentation" +msgstr "Till gun docamaideadh" + +msgid "Template filters" +msgstr "Criathragan teamplaid" + +msgid "Template filter documentation" +msgstr "Docamaideadh air criathragan teamplaid" + +msgid "Built-in filters" +msgstr "Criathragan ’na bhroinn" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Gus na criathragan seo a chleachdadh, cuir %(code)s san " +"teamplaid agad mus cleachd thu a’ chriathrag." + +msgid "Template tags" +msgstr "Tagaichean teamplaid" + +msgid "Template tag documentation" +msgstr "Docamaideadh air tagaichean teamplaid" + +msgid "Built-in tags" +msgstr "Tagaichean ’na bhroinn" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Gus na tagaichean seo a chleachdadh, cuir %(code)s san " +"teamplaid agad mus cleachd thu an taga." + +#, python-format +msgid "View: %(name)s" +msgstr "Sealladh: %(name)s" + +msgid "Context:" +msgstr "Co-theacsa:" + +msgid "Templates:" +msgstr "Teamplaidean:" + +msgid "Back to View documentation" +msgstr "Till gu docamaideadh nan seallaidhean" + +msgid "View documentation" +msgstr "Docamaideadh nan seallaidhean" + +msgid "Jump to namespace" +msgstr "Gearr leum dhan ainm-spàs" + +msgid "Empty namespace" +msgstr "Ainm-spàs falamh" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Seallaidhean a-rèir ainm-spàs %(name)s" + +msgid "Views by empty namespace" +msgstr "Seallaidhean a-rèir an ainm-spàis fhalaimh" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +" Foincsean seallaidh: %(full_name)s. Ainm: " +"%(url_name)s.\n" + +msgid "tag:" +msgstr "taga:" + +msgid "filter:" +msgstr "criathrag:" + +msgid "view:" +msgstr "sealladh:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Cha deach aplacaid %(app_label)r a lorg" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Cha deach modail %(model_name)r a lorg ann an aplacaid %(app_label)r" + +msgid "model:" +msgstr "modail:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "an t-oibseact `%(app_label)s.%(data_type)s` dàimheach" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "na h-oibseactan `%(app_label)s.%(object_name)s` dàimheach" + +#, python-format +msgid "all %s" +msgstr "a h-uile %s" + +#, python-format +msgid "number of %s" +msgstr "àireamh dhe %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "Chan eil coltas oibseact urlpattern air %s" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/gl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/gl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0216d60 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/gl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/gl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/gl/LC_MESSAGES/django.po new file mode 100644 index 0000000..d679091 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/gl/LC_MESSAGES/django.po @@ -0,0 +1,285 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# fonso , 2011,2013 +# Jannis Leidel , 2011 +# Leandro Regueiro , 2013 +# X Bello , 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2023-04-24 20:19+0000\n" +"Last-Translator: X Bello , 2023\n" +"Language-Team: Galician (http://www.transifex.com/django/django/language/" +"gl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: gl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Documentación administrativa" + +msgid "Home" +msgstr "Inicio" + +msgid "Documentation" +msgstr "Documentación" + +msgid "Bookmarklets" +msgstr "Bookmarklets" + +msgid "Documentation bookmarklets" +msgstr "Bookmarklets de documentación" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Para instalar os bookmarklets, arrastre o enlace á súa barra de marcadores, " +"ou pinche co botón dereito no enlace e engádao ós marcadores. Agora poderá " +"seleccionar o bookmarklet desde calquera páxina do sitio." + +msgid "Documentation for this page" +msgstr "Documentación para esta páxina" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "Salta á documentación para a vista que xera a páxina." + +msgid "Tags" +msgstr "Etiquetas" + +msgid "List of all the template tags and their functions." +msgstr "Listado de todas as etiquetas de plantilla e as súas funcións." + +msgid "Filters" +msgstr "Filtros" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Os filtros son accións que poden aplicarse a variables nunha plantilla para " +"modificar a salida." + +msgid "Models" +msgstr "Modelos" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Os modelos son descripcións de tódos os obxetos no sistema e os seus campos " +"asociados. Cada modelo ten unha lista de campos ós que pode accederse como " +"variables de plantilla." + +msgid "Views" +msgstr "Vistas" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Cada páxina no sitio público é xerada por unha vista. A vista define qué " +"plantilla se usa para xerar a páxina, e qué obxetos están dispoñibles nesa " +"plantilla." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Ferramentas para o navegador para acceder rápidamente á funcionalidade de " +"administración." + +msgid "Please install docutils" +msgstr "Por favor instale docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"O sistema de documentación de admin require da librería de Python docutils." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Por favor pídalle ós administradores que instalen docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Modelo: %(name)s" + +msgid "Fields" +msgstr "Campos" + +msgid "Field" +msgstr "Campo" + +msgid "Type" +msgstr "Tipo" + +msgid "Description" +msgstr "Descrición" + +msgid "Methods with arguments" +msgstr "Métodos con argumentos" + +msgid "Method" +msgstr "Método" + +msgid "Arguments" +msgstr "Argumentos" + +msgid "Back to Model documentation" +msgstr "Volver á documentación do Modelo" + +msgid "Model documentation" +msgstr "Documentación do modelo" + +msgid "Model groups" +msgstr "Modelos dos grupos" + +msgid "Templates" +msgstr "Patróns" + +#, python-format +msgid "Template: %(name)s" +msgstr "Plantilla: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Plantilla: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Rutas de busca para a plantilla %(name)s:" + +msgid "(does not exist)" +msgstr "(non existe)" + +msgid "Back to Documentation" +msgstr "Volver á documentación" + +msgid "Template filters" +msgstr "Filtros de plantilla" + +msgid "Template filter documentation" +msgstr "Documentación dos filtros de plantilla" + +msgid "Built-in filters" +msgstr "Filtros incluidos" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Para usar estes filtros, poña %(code)s na plantilla antes de " +"usar o filtro." + +msgid "Template tags" +msgstr "Etiquetas de plantilla" + +msgid "Template tag documentation" +msgstr "Documentación das etiquetas de plantilla" + +msgid "Built-in tags" +msgstr "Etiquetas incluidas" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Para usar estas etiquetas, poña %(code)s na plantilla antes de " +"usar a etiqueta." + +#, python-format +msgid "View: %(name)s" +msgstr "Vista: %(name)s" + +msgid "Context:" +msgstr "Contexto:" + +msgid "Templates:" +msgstr "Plantillas:" + +msgid "Back to View documentation" +msgstr "Volver á documentación da Vista" + +msgid "View documentation" +msgstr "Ver documentación" + +msgid "Jump to namespace" +msgstr "Saltar ó espacio de nomes" + +msgid "Empty namespace" +msgstr "Baleirar espacio de nomes" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Vistas por espacio de nomes %(name)s" + +msgid "Views by empty namespace" +msgstr "Vustas por espacio de nomes baleiro" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"Función de vista: %(full_name)s. Nome %(url_name)s.\n" + +msgid "tag:" +msgstr "etiqueta:" + +msgid "filter:" +msgstr "filtro:" + +msgid "view:" +msgstr "vista:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Non se atopa a aplicación %(app_label)r" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "O modelo %(model_name)r non se atopou na aplicación %(app_label)r" + +msgid "model:" +msgstr "modelo:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "o obxecto relacionado `%(app_label)s.%(data_type)s`" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "obxectos relacionados `%(app_label)s.%(object_name)s`" + +#, python-format +msgid "all %s" +msgstr "todos os %s" + +#, python-format +msgid "number of %s" +msgstr "número de %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s non semella ser un obxecto urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/he/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/he/LC_MESSAGES/django.mo new file mode 100644 index 0000000..24b9b3d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/he/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/he/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/he/LC_MESSAGES/django.po new file mode 100644 index 0000000..82a480b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/he/LC_MESSAGES/django.po @@ -0,0 +1,276 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Meir Kriheli , 2012-2015,2017,2020,2023 +# Yaron Shahrabani , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2023-12-04 20:19+0000\n" +"Last-Translator: Meir Kriheli , " +"2012-2015,2017,2020,2023\n" +"Language-Team: Hebrew (http://app.transifex.com/django/django/language/he/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: he\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % " +"1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;\n" + +msgid "Administrative Documentation" +msgstr "תיעוד ניהולי" + +msgid "Home" +msgstr "דף הבית" + +msgid "Documentation" +msgstr "תיעוד" + +msgid "Bookmarklets" +msgstr "ייסומניות" + +msgid "Documentation bookmarklets" +msgstr "ייסומוניות תיעוד" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"כדי להתקין ייסומניות, יש לגרור את הקישור לסרגל הסימניות שלך, או קליק ימני " +"והוספה לסימניות. כעת ניתן לבחור את הייסומניה מכל עמוד באתר." + +msgid "Documentation for this page" +msgstr "תיעוד לדף זה" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "מקפיץ אותך מכל עמוד לתיעוד התצוגה שייצרה אותו." + +msgid "Tags" +msgstr "תגים" + +msgid "List of all the template tags and their functions." +msgstr "רשימת כל ה-template tags והפונקציות שלהן." + +msgid "Filters" +msgstr "מסננים" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "פילטרים ופעולות אשר ניתן ליישם על משתנים בתבנית לשינוי הפלט." + +msgid "Models" +msgstr "מודלים" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"מודלים הם תיאור כל האובייקטים במערכת והשדות הקשורים אליהם. לכל מודל יש רשימת " +"שדות אשר ניתן לגשת אליהם בתור משתני תבנית" + +msgid "Views" +msgstr "Views" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"כל עמוד באתר הציבורי מיוצר ע\"י view. ה־view מגדיר את התבנית המשמשת ליצירת " +"העמוד ואת האובייקטים הזמינים לתבנית" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "כלים המאפשרים לדפדפן שלך גישה מהירה ליכולות הניהול." + +msgid "Please install docutils" +msgstr "נא להתקין את docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"מערכת התיעוד במנשק הניהול דורשת את ספריית הפייתון docutils." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "נא לבקש ממנהל המערכת להתקין את docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "מודל: %(name)s" + +msgid "Fields" +msgstr "שדות" + +msgid "Field" +msgstr "שדה" + +msgid "Type" +msgstr "סוג" + +msgid "Description" +msgstr "תיאור" + +msgid "Methods with arguments" +msgstr "מתודות עם פרמטרים" + +msgid "Method" +msgstr "מתודות" + +msgid "Arguments" +msgstr "פרמטרים" + +msgid "Back to Model documentation" +msgstr "חזרה לתיעוד מודל" + +msgid "Model documentation" +msgstr "תיעוד מודלים" + +msgid "Model groups" +msgstr "קבוצות מודלים" + +msgid "Templates" +msgstr "תבניות" + +#, python-format +msgid "Template: %(name)s" +msgstr "תבנית: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "תבנית: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "נתיב חיפוש לתבנית %(name)s:" + +msgid "(does not exist)" +msgstr "(לא קיים)" + +msgid "Back to Documentation" +msgstr "חזרה לתיעוד" + +msgid "Template filters" +msgstr "פילטרים לתבניות" + +msgid "Template filter documentation" +msgstr "תיעוד פילטר לתבנית" + +msgid "Built-in filters" +msgstr "פילטרים מובנים" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"כדי להשתמש בפילטרים האלו יש להוסיף %(code)s בתבנית שלך לפני " +"השימוש בפילטר." + +msgid "Template tags" +msgstr "תגים לתבניות" + +msgid "Template tag documentation" +msgstr "תיעוד תגים לתבניות" + +msgid "Built-in tags" +msgstr "תגים מובנים" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"כדי להשתמש בתגים האלו יש להוסיף %(code)s בתבנית שלך לפני השימוש " +"בתג." + +#, python-format +msgid "View: %(name)s" +msgstr "View: %(name)s" + +msgid "Context:" +msgstr "קונטקסט:" + +msgid "Templates:" +msgstr "תבניות:" + +msgid "Back to View documentation" +msgstr "חזרה לתיעוד ה-View" + +msgid "View documentation" +msgstr "תיעוד View" + +msgid "Jump to namespace" +msgstr "מעבר למרחב שמות" + +msgid "Empty namespace" +msgstr "מרחב שמות ריק" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Views לפי מרחב שמות %(name)s" + +msgid "Views by empty namespace" +msgstr "Views לפני מרחב שמות ריק" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +" פונקציית View: %(full_name)s. שם: %(url_name)s.\n" + +msgid "tag:" +msgstr "תג:" + +msgid "filter:" +msgstr "סינון:" + +msgid "view:" +msgstr "ה־view:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "יישום %(app_label)r לא נמצא" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "מודל %(model_name)r לא נמצא ביישום %(app_label)r" + +msgid "model:" +msgstr "מודל:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "עצמי `%(app_label)s.%(data_type)s` קשורים" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "עצמי `%(app_label)s.%(object_name)s` קשורים" + +#, python-format +msgid "all %s" +msgstr "כל %s" + +#, python-format +msgid "number of %s" +msgstr "מספר %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "לא נראה כי %s הוא עצם urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/hi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/hi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0233cc8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/hi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/hi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/hi/LC_MESSAGES/django.po new file mode 100644 index 0000000..876b764 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/hi/LC_MESSAGES/django.po @@ -0,0 +1,258 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Chandan kumar , 2012 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Hindi (http://www.transifex.com/django/django/language/hi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "गृह" + +msgid "Documentation" +msgstr "दस्तावेज़ीकरण" + +msgid "Bookmarklets" +msgstr "बुकमार्कलेट्स" + +msgid "Documentation bookmarklets" +msgstr "प्रलेखन बुकमार्कलेट्स" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "इस पृष्ठ की प्रलेखन" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "दृश्य जो उस पृष्ठ को उत्पन्न करता है के प्रलेखन के लिए किसी भी पृष्ठ पर जा सकते है." + +msgid "Tags" +msgstr "टैग्स" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "फ़िल्टर्स" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "मॉडल" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "दृश्य" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "प्रारूप" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "टैग:" + +msgid "filter:" +msgstr "छन्नी:" + +msgid "view:" +msgstr "दृष्टि:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "%(model_name)r मॉडल %(app_label)r अनुप्रयोग में लापता है" + +msgid "model:" +msgstr "मॉडल :" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "`%(app_label)s.%(data_type)s` संबंधित वस्तु" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "`%(app_label)s.%(object_name)s` संबंधित वस्तु" + +#, python-format +msgid "all %s" +msgstr "सभी %s" + +#, python-format +msgid "number of %s" +msgstr "%s संख्या" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s सही यू.आऱ.एल प्रतिरूप वस्तु नहीं है" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/hr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/hr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e789b5a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/hr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/hr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/hr/LC_MESSAGES/django.po new file mode 100644 index 0000000..0b70aa7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/hr/LC_MESSAGES/django.po @@ -0,0 +1,264 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# aljosa , 2012 +# Filip Cuk , 2016 +# Jannis Leidel , 2011 +# Mislav Cimperšak , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Croatian (http://www.transifex.com/django/django/language/" +"hr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hr\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +msgid "Administrative Documentation" +msgstr "Administrativna dokumentacija" + +msgid "Home" +msgstr "Početna" + +msgid "Documentation" +msgstr "Dokumentacija" + +msgid "Bookmarklets" +msgstr "Bookmarklets" + +msgid "Documentation bookmarklets" +msgstr "Dokumentacija bookmarklets-a" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "Dokumentacija za ovu stranicu" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Preusmjeri te sa bilo koje stranice na dokumentaciju za taj prikaz (view) " +"koji generira stranicu." + +msgid "Tags" +msgstr "Tagovi" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "Filteri" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "Modeli" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "Views" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "Molimo instalirajte docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "Polja" + +msgid "Field" +msgstr "Polje" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "Opis" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "Predlošci" + +#, python-format +msgid "Template: %(name)s" +msgstr "Predložak: %(name)s" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "Predložak: \"%(name)s\"" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "(ne postoji)" + +msgid "Back to Documentation" +msgstr "Povratak na dokumentaciju" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "Predlošci:" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "tag:" + +msgid "filter:" +msgstr "filter:" + +msgid "view:" +msgstr "prikaz:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Aplikacija %(app_label)r nije pronađena" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Model %(model_name)r nije pronađen u aplikaciji %(app_label)r" + +msgid "model:" +msgstr "model:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "povezani `%(app_label)s.%(data_type)s` objekt" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "povezani `%(app_label)s.%(object_name)s` objekti" + +#, python-format +msgid "all %s" +msgstr "svi %s" + +#, python-format +msgid "number of %s" +msgstr "broj %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "izgleda da %s nije urlpattern objekt" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/hsb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/hsb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..734adc0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/hsb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/hsb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/hsb/LC_MESSAGES/django.po new file mode 100644 index 0000000..d210e38 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/hsb/LC_MESSAGES/django.po @@ -0,0 +1,286 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Michael Wolf , 2016,2019,2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-02-01 21:47+0000\n" +"Last-Translator: Michael Wolf \n" +"Language-Team: Upper Sorbian (http://www.transifex.com/django/django/" +"language/hsb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hsb\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" + +msgid "Administrative Documentation" +msgstr "Administratiwna dokumentacija" + +msgid "Home" +msgstr "Startowa strona" + +msgid "Documentation" +msgstr "Dokumentacija" + +msgid "Bookmarklets" +msgstr "Skriptowe zapołožki" + +msgid "Documentation bookmarklets" +msgstr "Skriptowe zapołožki dokumentacije" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Zo byšće skriptowe zapołožki instalował, ćehńće wotkaz do swojeje lajsty " +"zapołožkow abo klikńće z prawej tastu myški na wotkaz a přidajće jón k " +"swojim zapołožkam. Móžeće skriptowu zapołožku nětko z kóždeje strony na " +"sydle wubrać." + +msgid "Documentation for this page" +msgstr "Dokumentacija za tutu stronu" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Zmóžnja wam, wot někajkeje strony do dokumentacije napohlada skočić, kotryž " +"je tu stronu wutworił." + +msgid "Tags" +msgstr "Znački" + +msgid "List of all the template tags and their functions." +msgstr "Lisćina wšěch předłohowych značkow a jich funkcijow." + +msgid "Filters" +msgstr "Filtry" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Filtry su akcije, kotrež dadźa so na wariable w předłoze nałožić, zo bychu " +"wudaće změnili." + +msgid "Models" +msgstr "Modele" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Modele su wopisanja wšěch objektow w systemje a jich přisłušnych polow. " +"Kóždy model ma lisćinu polow, na kotrež maja přistup jako předłohowe " +"wariable." + +msgid "Views" +msgstr "Napohlady" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Kóžda strona na zjawnym sydle so přez napohlad twori. Napohlad definuje, " +"kotra předłoha so wužiwa, zo by stronu wutworiła a kotre objekty su tej " +"přełoze k dispoziciji." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Nastroje za waš wobhladowak za spěšny přistup na administratorowu " +"funkcionalnosć." + +msgid "Please install docutils" +msgstr "Prošu instalujće docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Administratorowy dokumentaciski system sej Pythonowu biblioteku docutils wužaduje." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Prošu prošće swojich administratorow, docutils " +"instalować." + +#, python-format +msgid "Model: %(name)s" +msgstr "Model: %(name)s" + +msgid "Fields" +msgstr "Pola" + +msgid "Field" +msgstr "Polo" + +msgid "Type" +msgstr "Typ" + +msgid "Description" +msgstr "Wopisanje" + +msgid "Methods with arguments" +msgstr "Metody z argumentami" + +msgid "Method" +msgstr "Metoda" + +msgid "Arguments" +msgstr "Argumenty" + +msgid "Back to Model documentation" +msgstr "Wróćo k modelowej dokumentaciji" + +msgid "Model documentation" +msgstr "Modelowa dokumentacija" + +msgid "Model groups" +msgstr "Modelowe skupiny" + +msgid "Templates" +msgstr "Předłohi" + +#, python-format +msgid "Template: %(name)s" +msgstr "Předłoha: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Předłoha: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Pytanska šćežka za předłohu %(name)s:" + +msgid "(does not exist)" +msgstr "(njeeksistuje)" + +msgid "Back to Documentation" +msgstr "Wróćo k dokumentaciji" + +msgid "Template filters" +msgstr "Předłohowe filtry" + +msgid "Template filter documentation" +msgstr "Dokumentacija předłohowych filtrow" + +msgid "Built-in filters" +msgstr "Zatwarjene filtry" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Zo byšće tute filtry wužiwał, zasadźće %(code)s do swojeje " +"předłohi, prjedy hač filter wužiwaće." + +msgid "Template tags" +msgstr "Předłohowe znački" + +msgid "Template tag documentation" +msgstr "Dokumentacija předłohowych značkow" + +msgid "Built-in tags" +msgstr "Zatwarjene znački" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Zo byšće tute znački wužiwał, zasadźće %(code)s do swojeje " +"předłohi, prjedy hač značku wužiwaće." + +#, python-format +msgid "View: %(name)s" +msgstr "Napohlad: %(name)s" + +msgid "Context:" +msgstr "Kontekst:" + +msgid "Templates:" +msgstr "Předłohi:" + +msgid "Back to View documentation" +msgstr "Wróćo k napohladowej dokumentaciji" + +msgid "View documentation" +msgstr "Napohladowa dokumentacija" + +msgid "Jump to namespace" +msgstr "K mjenowemu rumej skočić" + +msgid "Empty namespace" +msgstr "Prózdny mjenowy rum" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Napohlady po mjenowym rumje %(name)s" + +msgid "Views by empty namespace" +msgstr "Napohlady po prózdnym mjenowym rumje" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +" Napohladowa funkcija: %(full_name)s. Mjeno: " +"%(url_name)s.\n" + +msgid "tag:" +msgstr "značka:" + +msgid "filter:" +msgstr "filter:" + +msgid "view:" +msgstr "napohlad:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Nałoženje %(app_label)r njenamakane" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Model %(model_name)r njeje so w nałoženju %(app_label)r namakał" + +msgid "model:" +msgstr "model:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "přisłušny objekt %(app_label)s.%(data_type)s“" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "přisłušne objekty %(app_label)s.%(object_name)s“" + +#, python-format +msgid "all %s" +msgstr "wšě %s" + +#, python-format +msgid "number of %s" +msgstr "ličba %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "zda so, zo %s objekt urlpattern njeje" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/hu/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/hu/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d8a25af Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/hu/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/hu/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/hu/LC_MESSAGES/django.po new file mode 100644 index 0000000..dd8727d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/hu/LC_MESSAGES/django.po @@ -0,0 +1,288 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# András Veres-Szentkirályi, 2016 +# Attila Nagy <>, 2012 +# Istvan Farkas , 2019 +# Jannis Leidel , 2011 +# János R, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-04-02 13:45+0000\n" +"Last-Translator: János R\n" +"Language-Team: Hungarian (http://www.transifex.com/django/django/language/" +"hu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Adminisztrációs dokumentáció" + +msgid "Home" +msgstr "Kezdőlap" + +msgid "Documentation" +msgstr "Dokumentáció" + +msgid "Bookmarklets" +msgstr "Könyvjelzők" + +msgid "Documentation bookmarklets" +msgstr "Dokumentum könyvjelzők" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"A könyvjelzők felvételéhez húzza a könyvjelzők linkjét az eszköztárra, vagy " +"kattintson rájuk jobb egérgombbal és úgy adja hozzá. Ezután már ki tudja " +"választani a könyvjelzőt a honlap bármely oldaláról." + +msgid "Documentation for this page" +msgstr "Az oldal dokumentációja" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Bármely oldalról annak a nézetnek a dokumentációjára ugrik, amely a kérdéses " +"oldalt generálta." + +msgid "Tags" +msgstr "Címkék" + +msgid "List of all the template tags and their functions." +msgstr "" +"Az összes sablon címke (template tags) és a hozzá tartozó függvények listája" + +msgid "Filters" +msgstr "Szűrők" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"A szűrők olyan műveletek, amelyeket változókon végrehajtva a sablon kimenete " +"módosul." + +msgid "Models" +msgstr "Modellek" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"A modellek a rendszerben található objektumok és a hozzá tartozó mezők " +"leírásai. Minden modell rendelkezik mezőkkel, amelyek a sablonokban " +"változóként érhetők el." + +msgid "Views" +msgstr "Nézetek" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"A honlapon minden oldalt egy nézet generál. A nézet definiálja, melyik " +"sablonból készül az oldal, és milyen objektumok állnak az adott nézet " +"rendelkezésére." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "Segédeszközök a böngészőjébe az admin funkciók gyors eléréséhez." + +msgid "Please install docutils" +msgstr "Kérem telepítse a docutils-t" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Az adminisztrációs dokumentáció működéséhez szükség van a Python docutils könyvtárára." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Kérje meg a rendszergazdát, hogy telepítse a docutils-t." + +#, python-format +msgid "Model: %(name)s" +msgstr "%(name)s modell" + +msgid "Fields" +msgstr "Mezők" + +msgid "Field" +msgstr "Mező" + +msgid "Type" +msgstr "Típus" + +msgid "Description" +msgstr "Leírás" + +msgid "Methods with arguments" +msgstr "Metódusok és paramétereik" + +msgid "Method" +msgstr "Metódus" + +msgid "Arguments" +msgstr "Paraméterek" + +msgid "Back to Model documentation" +msgstr "Vissza a modell dokumentációhoz" + +msgid "Model documentation" +msgstr "Modell dokumentáció" + +msgid "Model groups" +msgstr "Modell csoportok" + +msgid "Templates" +msgstr "Sablonok" + +#, python-format +msgid "Template: %(name)s" +msgstr "%(name)s sablon" + +#, python-format +msgid "Template: %(name)s" +msgstr "Sablon: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "%(name)ssablon keresési útvonala:" + +msgid "(does not exist)" +msgstr "(nem létezik)" + +msgid "Back to Documentation" +msgstr "Vissza a dokumentációhoz" + +msgid "Template filters" +msgstr "Sablon szűrők" + +msgid "Template filter documentation" +msgstr "Sablon szűrő dokumentáci" + +msgid "Built-in filters" +msgstr "Beépített szűrők" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Ezen szűrők használatához a %(code)s kódrészletnek kell " +"szerepelnie használat előtt a sablonban." + +msgid "Template tags" +msgstr "Sablon címkék" + +msgid "Template tag documentation" +msgstr "Sablon címke dokumentáció" + +msgid "Built-in tags" +msgstr "Beépített címkék" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Ezen címkék használatához a %(code)s kódrészletnek kell " +"szerepelnie használat előtt a sablonban." + +#, python-format +msgid "View: %(name)s" +msgstr "%(name)s nézet" + +msgid "Context:" +msgstr "Környezet:" + +msgid "Templates:" +msgstr "Sablonok:" + +msgid "Back to View documentation" +msgstr "Vissza a nézetek dokumentációhoz" + +msgid "View documentation" +msgstr "Nézet dokumentáció" + +msgid "Jump to namespace" +msgstr "Ugrás a névtérhez" + +msgid "Empty namespace" +msgstr "Üres névtér" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "%(name)s névtérhez tartozó nézetek" + +msgid "Views by empty namespace" +msgstr "Névtér nélküli nézetek" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +" Nézet függvény: %(full_name)s. Név: %(url_name)s.\n" + +msgid "tag:" +msgstr "címke:" + +msgid "filter:" +msgstr "szűrő:" + +msgid "view:" +msgstr "nézet:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "%(app_label)r alkalmazás nem található" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "" +"%(model_name)r modell nem található a következő alkalmazásban: %(app_label)r" + +msgid "model:" +msgstr "modell:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "a kapcsolódó '%(app_label)s.%(data_type)s' objektum" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "kapcsolódó '%(app_label)s.%(object_name)s' objektumok" + +#, python-format +msgid "all %s" +msgstr "minden %s" + +#, python-format +msgid "number of %s" +msgstr "%s mennyisége" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s nem tűnik egy urlpattern objektumnak." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ia/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ia/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5563512 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ia/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ia/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ia/LC_MESSAGES/django.po new file mode 100644 index 0000000..f20e8b6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ia/LC_MESSAGES/django.po @@ -0,0 +1,260 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Martijn Dekker , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Interlingua (http://www.transifex.com/django/django/language/" +"ia/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ia\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "Initio" + +msgid "Documentation" +msgstr "Documentation" + +msgid "Bookmarklets" +msgstr "Bookmarklets" + +msgid "Documentation bookmarklets" +msgstr "Documentation bookmarklets" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "Documentation pro iste pagina" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Transporta vos ab omne pagina al documentation pro le visualisation que " +"genera ille pagina." + +msgid "Tags" +msgstr "Etiquettas" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "Filtros" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "Modellos" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "Visualisationes" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "Patronos" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "etiquetta:" + +msgid "filter:" +msgstr "filtro:" + +msgid "view:" +msgstr "visualisation:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Modello %(model_name)r non trovate in application %(app_label)r" + +msgid "model:" +msgstr "modello:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "le objecto `%(app_label)s.%(data_type)s` connexe" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "objectos `%(app_label)s.%(object_name)s` connexe" + +#, python-format +msgid "all %s" +msgstr "tote le %s" + +#, python-format +msgid "number of %s" +msgstr "numero de %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s non pare esser un objecto urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/id/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/id/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d6d934d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/id/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/id/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/id/LC_MESSAGES/django.po new file mode 100644 index 0000000..92b70c3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/id/LC_MESSAGES/django.po @@ -0,0 +1,287 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Fery Setiawan , 2015-2016,2021 +# Jannis Leidel , 2011 +# rodin , 2011-2012 +# rodin , 2013-2014,2016 +# sag᠎e , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-09-14 00:30+0000\n" +"Last-Translator: Fery Setiawan \n" +"Language-Team: Indonesian (http://www.transifex.com/django/django/language/" +"id/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: id\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Administrative Documentation" +msgstr "Dokumentasi Administrasi" + +msgid "Home" +msgstr "Beranda" + +msgid "Documentation" +msgstr "Dokumentasi" + +msgid "Bookmarklets" +msgstr "Bookmarklet" + +msgid "Documentation bookmarklets" +msgstr "Bookmarklet dokumentasi" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Untuk memasang bookmarklet, tarik tautan ke bilah markah, atau klik kanan " +"tautan dan tambahkan ke markah Anda. Sekarang Anda dapat memilih bookmarklet " +"dari semua halaman di situs." + +msgid "Documentation for this page" +msgstr "Dokumentasi untuk laman ini" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Buka dari laman apa saja ke laman dokumentasi untuk view yang menghasilkan " +"laman tersebut." + +msgid "Tags" +msgstr "Tag" + +msgid "List of all the template tags and their functions." +msgstr "Daftar seluruh tag templat dan fungsinya." + +msgid "Filters" +msgstr "Filter" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Filter merupakan tindakan yang dapat diterapkan pada variabel dalam sebuah " +"templat untuk mengubah keluaran." + +msgid "Models" +msgstr "Model" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Model merupakan deskripsi semua objek dalam sistem dan bidang yang terkait. " +"Setiap model memiliki beberapa bidang yang dapat diakses sebagai variabel " +"templat" + +msgid "Views" +msgstr "View" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Setiap laman pada situs publik dihasilkan oleh sebuah 'view'. 'View' " +"mendefinisikan templat mana yang digunakan untuk menghasilkan laman dan " +"objek mana yang tersedia untuk templat tersebut." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Alat untuk peramban Anda untuk mempercepat akses fungsionalitas admin. " + +msgid "Please install docutils" +msgstr "Instal docutils." + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Sistem dokumentasi admin membutuhkan pustaka docutils Python." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Ajukan permintaan kepada administrator Anda untuk menginstal docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Model: %(name)s" + +msgid "Fields" +msgstr "Bidang" + +msgid "Field" +msgstr "Bidang" + +msgid "Type" +msgstr "Tipe" + +msgid "Description" +msgstr "Deskripsi" + +msgid "Methods with arguments" +msgstr "Metode dengan argumen" + +msgid "Method" +msgstr "Metode" + +msgid "Arguments" +msgstr "Argumen" + +msgid "Back to Model documentation" +msgstr "Kembali ke Dokumentasi Model" + +msgid "Model documentation" +msgstr "Dokumentasi model" + +msgid "Model groups" +msgstr "Grup model" + +msgid "Templates" +msgstr "Templat" + +#, python-format +msgid "Template: %(name)s" +msgstr "Templat: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Templat: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Lokasi pencarian templat %(name)s:" + +msgid "(does not exist)" +msgstr "(tidak ada)" + +msgid "Back to Documentation" +msgstr "Kembali ke Dokumentasi" + +msgid "Template filters" +msgstr "Filter templat" + +msgid "Template filter documentation" +msgstr "Dokumentasi filter templat" + +msgid "Built-in filters" +msgstr "Filter bawaan" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Untuk menggunakan filter ini, sertakan %(code)s pada templat " +"Anda sebelum menggunakan filternya." + +msgid "Template tags" +msgstr "Tag templat" + +msgid "Template tag documentation" +msgstr "Dokumentasi tag templat" + +msgid "Built-in tags" +msgstr "Tag bawaan" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Untuk menggunakan tag ini, sertakan %(code)s pada templat Anda " +"sebelum menggunakan tagnya." + +#, python-format +msgid "View: %(name)s" +msgstr "View: %(name)s" + +msgid "Context:" +msgstr "Konteks:" + +msgid "Templates:" +msgstr "Templat:" + +msgid "Back to View documentation" +msgstr "Kembali ke dokumentasi Tampilan" + +msgid "View documentation" +msgstr "Dokumentasi view" + +msgid "Jump to namespace" +msgstr "Loncat ke namespace" + +msgid "Empty namespace" +msgstr "Namespace kosong" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "View berdasarkan namespace %(name)s" + +msgid "Views by empty namespace" +msgstr "View berdasarkan namespace kosong" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +" Fungsi view: %(full_name)s. Nama: %(url_name)s.\n" + +msgid "tag:" +msgstr "tag:" + +msgid "filter:" +msgstr "filter:" + +msgid "view:" +msgstr "view:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Aplikasi %(app_label)r tidak ditemukan" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Model %(model_name)r tidak ditemukan di aplikasi %(app_label)r" + +msgid "model:" +msgstr "model:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "objek `%(app_label)s.%(data_type)s` yang terkait" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "obyek `%(app_label)s.%(object_name)s` yang terkait" + +#, python-format +msgid "all %s" +msgstr "semua %s" + +#, python-format +msgid "number of %s" +msgstr "jumlah %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s bukan berupa objek urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/io/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/io/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4e88926 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/io/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/io/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/io/LC_MESSAGES/django.po new file mode 100644 index 0000000..ae4bec1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/io/LC_MESSAGES/django.po @@ -0,0 +1,275 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2015-01-18 08:34+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Ido (http://www.transifex.com/projects/p/django/language/" +"io/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: io\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "" + +msgid "Documentation" +msgstr "" + +msgid "Bookmarklets" +msgstr "" + +msgid "Documentation bookmarklets" +msgstr "" + +msgid "" +"\n" +"

    To install bookmarklets, drag the link to your bookmarks\n" +"toolbar, or right-click the link and add it to your bookmarks. Now you can\n" +"select the bookmarklet from any page in the site. Note that some of these\n" +"bookmarklets require you to be viewing the site from a computer designated\n" +"as \"internal\" (talk to your system administrator if you aren't sure if\n" +"your computer is \"internal\").

    \n" +msgstr "" + +msgid "Documentation for this page" +msgstr "" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" + +msgid "Show object ID" +msgstr "" + +msgid "" +"Shows the content-type and unique ID for pages that represent a single " +"object." +msgstr "" + +msgid "Edit this object (current window)" +msgstr "" + +msgid "Jumps to the admin page for pages that represent a single object." +msgstr "" + +msgid "Edit this object (new window)" +msgstr "" + +msgid "As above, but opens the admin page in a new window." +msgstr "" + +msgid "Tags" +msgstr "" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Back to Model Documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to Views Documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "" + +msgid "tag:" +msgstr "" + +msgid "filter:" +msgstr "" + +msgid "view:" +msgstr "" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "" + +msgid "model:" +msgstr "" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "" + +#, python-format +msgid "all %s" +msgstr "" + +#, python-format +msgid "number of %s" +msgstr "" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/is/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/is/LC_MESSAGES/django.mo new file mode 100644 index 0000000..fcc3bcd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/is/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/is/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/is/LC_MESSAGES/django.po new file mode 100644 index 0000000..a70aa6e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/is/LC_MESSAGES/django.po @@ -0,0 +1,261 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Hafsteinn Einarsson , 2012,2014 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Icelandic (http://www.transifex.com/django/django/language/" +"is/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: is\n" +"Plural-Forms: nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "Heim" + +msgid "Documentation" +msgstr "Skjölun" + +msgid "Bookmarklets" +msgstr "Bókamerklar" + +msgid "Documentation bookmarklets" +msgstr "Skjölunarbókamerklar" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "Skjölun þessarar síðu" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Sendir þig af hvaða síðu sem er á skjölun þess framsetningarlags sem myndar " +"hana." + +msgid "Tags" +msgstr "Tögg" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "Síur" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "Módel" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "Ásýndir" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "Sniðmát" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "merki:" + +msgid "filter:" +msgstr "sía:" + +msgid "view:" +msgstr "skoða:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Líkanið %(model_name)r finnst ekki í forritinu %(app_label)r" + +msgid "model:" +msgstr "líkan:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "tengdi `%(app_label)s.%(data_type)s` hluturinn" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "tengdir `%(app_label)s.%(object_name)s` hlutir" + +#, python-format +msgid "all %s" +msgstr "allt %s" + +#, python-format +msgid "number of %s" +msgstr "fjöldi af %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s virðist ekki vera urlpattern hlutur" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/it/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/it/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4bf8985 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/it/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/it/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/it/LC_MESSAGES/django.po new file mode 100644 index 0000000..e2c43bd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/it/LC_MESSAGES/django.po @@ -0,0 +1,289 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Flavio Curella , 2013 +# Jannis Leidel , 2011 +# Luciano De Falco Alfano, 2016 +# Marco Bonetti, 2014 +# palmux , 2015-2016,2019,2021 +# Stefano Brentegani , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-01-15 16:05+0000\n" +"Last-Translator: palmux \n" +"Language-Team: Italian (http://www.transifex.com/django/django/language/" +"it/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: it\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Documentazione Amministrativa" + +msgid "Home" +msgstr "Pagina iniziale" + +msgid "Documentation" +msgstr "Documentazione" + +msgid "Bookmarklets" +msgstr "Bookmarklet" + +msgid "Documentation bookmarklets" +msgstr "Bookmarklet alla documentazione" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Per installare i bookmarklets, trascina il link sulla barra dei segnalibri o " +"clicca col tasto desto sul link ed aggiungilo ai tuoi segnalibri. Ora potrai " +"selezione un bookmarklet da ogni pagina del sito." + +msgid "Documentation for this page" +msgstr "Documentazione per questa pagina" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Porta da qualsiasi pagina alla documentazione della view che genera quella " +"pagina." + +msgid "Tags" +msgstr "Tag" + +msgid "List of all the template tags and their functions." +msgstr "Lista di tutti i template tags e delle loro funzioni." + +msgid "Filters" +msgstr "Filtri" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"I Filtri sono azioni che possono essere applicate alle variabili all'interno " +"di un Template per alterarne l'output." + +msgid "Models" +msgstr "Modelli" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"I Modelli sono descrizioni di tutti gli oggetti nel sistema e dei campi ad " +"essi associati. Ogni modello ha una lista di campi accessibili come " +"variabili nel template." + +msgid "Views" +msgstr "View" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Ogni pagina sul sito pubblico è generata da una View. La View definisce " +"quale Template è usato per generare la pagina e quali oggetti sono " +"disponibili in quel Template." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Strumenti per il tuo browser per accedere velocemente a funzionalità " +"dell'admin." + +msgid "Please install docutils" +msgstr "Installa docutils, per favore" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Il sistema di documentazione dell'admin richiede la libreria Python docutils." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Chiedi ai tuoi amministratori di installare docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Model: %(name)s" + +msgid "Fields" +msgstr "Campi" + +msgid "Field" +msgstr "Campo" + +msgid "Type" +msgstr "Tipo" + +msgid "Description" +msgstr "Descrizione" + +msgid "Methods with arguments" +msgstr "Metodi con argomenti" + +msgid "Method" +msgstr "Metodo" + +msgid "Arguments" +msgstr "Argomenti" + +msgid "Back to Model documentation" +msgstr "Torna alla documentzione del Model" + +msgid "Model documentation" +msgstr "Documentazione Modello" + +msgid "Model groups" +msgstr "Gruppi del Model" + +msgid "Templates" +msgstr "Template" + +#, python-format +msgid "Template: %(name)s" +msgstr "Template: \"%(name)s\"" + +#, python-format +msgid "Template: %(name)s" +msgstr "Template: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Percorso di ricerca per il template %(name)s:" + +msgid "(does not exist)" +msgstr "(non esiste)" + +msgid "Back to Documentation" +msgstr "Torna alla Documentazione" + +msgid "Template filters" +msgstr "Filtri Template" + +msgid "Template filter documentation" +msgstr "Documentazione del filtro template" + +msgid "Built-in filters" +msgstr "Filtri inclusi" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Per usare questi filtri, inserisci %(code)s nel tuo template " +"prima di usare il filtro." + +msgid "Template tags" +msgstr "Tag Template" + +msgid "Template tag documentation" +msgstr "Documentazione del Tag Template" + +msgid "Built-in tags" +msgstr "Tag inclusi" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Per usare questi tag, inserisci %(code)s nel tuo template prima " +"di usare il tag." + +#, python-format +msgid "View: %(name)s" +msgstr "View: %(name)s" + +msgid "Context:" +msgstr "Contesto:" + +msgid "Templates:" +msgstr "Template:" + +msgid "Back to View documentation" +msgstr "Torna alla documentazione della View" + +msgid "View documentation" +msgstr "Documentazione View" + +msgid "Jump to namespace" +msgstr "Vai al namespace" + +msgid "Empty namespace" +msgstr "Namespace vuoto" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Views per il namespace %(name)s" + +msgid "Views by empty namespace" +msgstr "Views per il namespace vuoto" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"Funzione di View: %(full_name)s. Nome: %(url_name)s.\n" + +msgid "tag:" +msgstr "tag:" + +msgid "filter:" +msgstr "filtro:" + +msgid "view:" +msgstr "view:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "App %(app_label)r non trovata" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Modello %(model_name)r non trovato nell'app %(app_label)r" + +msgid "model:" +msgstr "modello:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "l'oggetto `%(app_label)s.%(data_type)s` collegato" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "oggetti `%(app_label)s.%(object_name)s` collegati" + +#, python-format +msgid "all %s" +msgstr "tutti %s" + +#, python-format +msgid "number of %s" +msgstr "numero di %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s non sembra essere un oggetto urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ja/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ja/LC_MESSAGES/django.mo new file mode 100644 index 0000000..edac83e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ja/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ja/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ja/LC_MESSAGES/django.po new file mode 100644 index 0000000..54d9c99 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ja/LC_MESSAGES/django.po @@ -0,0 +1,284 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Fandekasp , 2012 +# Jannis Leidel , 2011 +# Shinya Okano , 2013-2016 +# Takuya N , 2020 +# Tsuboi Yuto , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-05-09 04:02+0000\n" +"Last-Translator: Tsuboi Yuto \n" +"Language-Team: Japanese (http://www.transifex.com/django/django/language/" +"ja/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ja\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Administrative Documentation" +msgstr "管理用ドキュメント" + +msgid "Home" +msgstr "ホーム" + +msgid "Documentation" +msgstr "ドキュメント" + +msgid "Bookmarklets" +msgstr "ブックマークレット" + +msgid "Documentation bookmarklets" +msgstr "ドキュメントへのブックマークレット" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"ブックマークレットをインストールするには、リンクをブックマークツールバーにド" +"ラッグするか、 リンクを右クリックしてブックマークに追加してください。これでサ" +"イトのどのページからでもブックマークレットを選択可能になります。" + +msgid "Documentation for this page" +msgstr "このページのドキュメント" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "各ページから、ページを生成したビューのドキュメントにジャンプします。" + +msgid "Tags" +msgstr "タグ" + +msgid "List of all the template tags and their functions." +msgstr "すべてのテンプレートタグとその機能の一覧です。" + +msgid "Filters" +msgstr "フィルター" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"フィルタは、テンプレート内の変数に適用して出力を変更するためのアクションで" +"す。" + +msgid "Models" +msgstr "モデル" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"モデルは、すべてのシステム内のオブジェクトとそれに関連するフィールドの説明で" +"す。各モデルは、テンプレート変数としてアクセスできるフィールドのリストを持っ" +"ています。" + +msgid "Views" +msgstr "ビュー" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"公開サイトの各ページは、ビューによって生成されます。ビューは、ページの生成に" +"使用されるテンプレートとそのテンプレートで利用できるオブジェクトが定義されて" +"います。" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "ブラウザから管理機能にすぐにアクセスするためのツールです。" + +msgid "Please install docutils" +msgstr "docutilsをインストールして下さい" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"管理用ドキュメントシステムにはPythonのdocutilsライブ" +"ラリが必要です。" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"管理者に docutils のインストールについて問い合せて下" +"さい。" + +#, python-format +msgid "Model: %(name)s" +msgstr "モデル: %(name)s" + +msgid "Fields" +msgstr "フィールド" + +msgid "Field" +msgstr "フィールド" + +msgid "Type" +msgstr "型" + +msgid "Description" +msgstr "説明" + +msgid "Methods with arguments" +msgstr "メソッドと引数" + +msgid "Method" +msgstr "メソッド" + +msgid "Arguments" +msgstr "引数" + +msgid "Back to Model documentation" +msgstr "モデルドキュメントに戻る" + +msgid "Model documentation" +msgstr "モデルドキュメント" + +msgid "Model groups" +msgstr "モデルグループ" + +msgid "Templates" +msgstr "テンプレート" + +#, python-format +msgid "Template: %(name)s" +msgstr "テンプレート: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "テンプレート: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "テンプレートの検索パス %(name)s:" + +msgid "(does not exist)" +msgstr "(存在しません)" + +msgid "Back to Documentation" +msgstr "ドキュメントに戻る" + +msgid "Template filters" +msgstr "テンプレートフィルタ" + +msgid "Template filter documentation" +msgstr "テンプレートフィルタドキュメント" + +msgid "Built-in filters" +msgstr "組み込みフィルタ" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"これらのフィルタを使用するには、テンプレート内でのフィルタの使用箇所より前に " +"%(code)s を記述してください。" + +msgid "Template tags" +msgstr "テンプレートタグ" + +msgid "Template tag documentation" +msgstr "テンプレートタグドキュメント" + +msgid "Built-in tags" +msgstr "組み込みタグ" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"これらのタグを使用するためには、タグの使用箇所より前に %(code)s " +"をテンプレート内に記述します。" + +#, python-format +msgid "View: %(name)s" +msgstr "ビュー: %(name)s" + +msgid "Context:" +msgstr "コンテキスト:" + +msgid "Templates:" +msgstr "テンプレート:" + +msgid "Back to View documentation" +msgstr "ビュードキュメントに戻る" + +msgid "View documentation" +msgstr "ビュードキュメント" + +msgid "Jump to namespace" +msgstr "ネームスペースへ移動" + +msgid "Empty namespace" +msgstr "空のネームスペース" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "ネームスペース %(name)s のビュー" + +msgid "Views by empty namespace" +msgstr "空のネームスペースのよるビュー" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"ビュー関数: %(full_name)s. 名前: %(url_name)s.\n" + +msgid "tag:" +msgstr "タグ" + +msgid "filter:" +msgstr "フィルター" + +msgid "view:" +msgstr "ビュー" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "アプリケーション %(app_label)r が見つかりません" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "" +"モデル %(model_name)r が %(app_label)r アプリケーションに見つかりません" + +msgid "model:" +msgstr "モデル :" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "`%(app_label)s.%(data_type)s` (関連オブジェクト)" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "`%(app_label)s.%(object_name)s` (関連オブジェクト)" + +#, python-format +msgid "all %s" +msgstr "全ての %s" + +#, python-format +msgid "number of %s" +msgstr "%s の数" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s はurlpatternオブジェクトでは無いようです" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ka/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ka/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9b8e30e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ka/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ka/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ka/LC_MESSAGES/django.po new file mode 100644 index 0000000..7d2e0f3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ka/LC_MESSAGES/django.po @@ -0,0 +1,263 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# André Bouatchidzé , 2013,2015 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Georgian (http://www.transifex.com/django/django/language/" +"ka/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ka\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +msgid "Administrative Documentation" +msgstr "ადმინისტრირების დოკუმენტაცია" + +msgid "Home" +msgstr "საწყისი გვერდი" + +msgid "Documentation" +msgstr "დოკუმენტაცია" + +msgid "Bookmarklets" +msgstr "სანიშნები" + +msgid "Documentation bookmarklets" +msgstr "დოკუმენტაციის სანიშნები" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "ამ გვერდის დოკუმენტაცია" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"გადასვლა ნებისმიერი გვერდიდან იმ წარმოდგენის დოკუმენტაციაზე, რომელიც ამ " +"გვერდს აგენერირებს." + +msgid "Tags" +msgstr "ტეგები" + +msgid "List of all the template tags and their functions." +msgstr "ყველა შაბლონის ტეგის სია და მათი ფუნქციები." + +msgid "Filters" +msgstr "ფილტრები" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"ფილტრები მოქმედებებია, რომელებიც შეიძლება გამოიყენებოდეს ცვლადებზე შაბლონში " +"გამონატანის შესაცვლელად." + +msgid "Models" +msgstr "მოდელები" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "წარმოდგენები" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "გთხოვთ, დააყენოთ docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "მოდელი: %(name)s" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "ველი" + +msgid "Type" +msgstr "ტიპი" + +msgid "Description" +msgstr "აღწერა" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "მოდელის დოკუმენტაცია" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "შაბლონები" + +#, python-format +msgid "Template: %(name)s" +msgstr "შაბლონი: %(name)s" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "შაბლონი: \"%(name)s\"" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "(არ არსებობს)" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "შაბლონის ფილტრები" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "შაბლონის ტეგები" + +msgid "Template tag documentation" +msgstr "შაბლონის ტეგების დოკუმენტაცია" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "ხედი: %(name)s" + +msgid "Context:" +msgstr "კონტექსტი" + +msgid "Templates:" +msgstr "შაბლონები:" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "ხედების დოკუმენტაცია" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "ტეგი:" + +msgid "filter:" +msgstr "ფილტრი:" + +msgid "view:" +msgstr "წარმოდგენა:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "მოდელი %(model_name)r ვერ მოიძებნა აპლიკაციაში %(app_label)r" + +msgid "model:" +msgstr "მოდელი:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "`%(app_label)s.%(data_type)s` დაკავშირებული ობიექტი" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "`%(app_label)s.%(object_name)s` დაკავშირებული ობიექტები" + +#, python-format +msgid "all %s" +msgstr "ყველა %s" + +#, python-format +msgid "number of %s" +msgstr "%s - რაოდენობა" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s არ არის urlpattern-ის შესაბამისი ობიექტი" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/kab/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/kab/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2b4eb43 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/kab/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/kab/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/kab/LC_MESSAGES/django.po new file mode 100644 index 0000000..f404ac2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/kab/LC_MESSAGES/django.po @@ -0,0 +1,258 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Muḥend Belqasem , 2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-10-06 12:00+0000\n" +"Last-Translator: Muḥend Belqasem \n" +"Language-Team: Kabyle (http://www.transifex.com/django/django/language/" +"kab/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kab\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "Agejdan" + +msgid "Documentation" +msgstr "Tasemlit" + +msgid "Bookmarklets" +msgstr "" + +msgid "Documentation bookmarklets" +msgstr "" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" + +msgid "Tags" +msgstr "Tiṛekkizin" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "Imzizdigen" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "Timeẓriyin" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "Urtan" + +msgid "Field" +msgstr "Urti" + +msgid "Type" +msgstr "Tawsit" + +msgid "Description" +msgstr "Aglam" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "Tarrayt" + +msgid "Arguments" +msgstr "Tiɣira" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "Tineɣrufin" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "(ula- it)" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "Asatal:" + +msgid "Templates:" +msgstr "Tineɣrufin:" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "Sken tasemlit" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "tabzimt:" + +msgid "filter:" +msgstr "imzizdig:" + +msgid "view:" +msgstr "wali:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "" + +msgid "model:" +msgstr "Taneɣruft" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "" + +#, python-format +msgid "all %s" +msgstr "akk %s" + +#, python-format +msgid "number of %s" +msgstr "" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/kk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/kk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..050a289 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/kk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/kk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/kk/LC_MESSAGES/django.po new file mode 100644 index 0000000..1b33c36 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/kk/LC_MESSAGES/django.po @@ -0,0 +1,258 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Nurlan Rakhimzhanov , 2011 +# yun_man_ger , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Kazakh (http://www.transifex.com/django/django/language/kk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kk\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "Негізгі" + +msgid "Documentation" +msgstr "Документация" + +msgid "Bookmarklets" +msgstr "Букмарклеттер" + +msgid "Documentation bookmarklets" +msgstr "Құжаттама букмарклеттері" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "Бұл бетке арналған документация" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" + +msgid "Tags" +msgstr "" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "тег:" + +msgid "filter:" +msgstr "сүзгіш:" + +msgid "view:" +msgstr "көрініс:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "%(app_label)r app ішінен %(model_name)r үлгісі табылмады" + +msgid "model:" +msgstr "модель:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "байланысты `%(app_label)s.%(data_type)s` объект" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "байланысты `%(app_label)s.%(object_name)s` объекттер" + +#, python-format +msgid "all %s" +msgstr "барлық %s" + +#, python-format +msgid "number of %s" +msgstr "%s саны" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s urlpattern объектке ұқсамайды" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/km/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/km/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8440d72 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/km/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/km/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/km/LC_MESSAGES/django.po new file mode 100644 index 0000000..f606425 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/km/LC_MESSAGES/django.po @@ -0,0 +1,259 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Khmer (http://www.transifex.com/django/django/language/km/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: km\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "គេហទំព័រ" + +msgid "Documentation" +msgstr "ឯកសារ" + +msgid "Bookmarklets" +msgstr "កំរងចំណាំ" + +msgid "Documentation bookmarklets" +msgstr "កំរងចំណាំអំពីឯកសារ" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "ឯកសារសំរាប់ទំព័រនេះ" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Jumps you from any page to the documentation for the view that generates " +"that page." + +msgid "Tags" +msgstr "" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "ប្រភេទ:" + +msgid "filter:" +msgstr "ពាក្យស្វែងរក" + +msgid "view:" +msgstr "មើល" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "" + +msgid "model:" +msgstr "model:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "" + +#, python-format +msgid "all %s" +msgstr "ទាំងអស់ %s" + +#, python-format +msgid "number of %s" +msgstr "ចំនួន​នៃ​%s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s ហាក់បីដូចជា URL ដែល​ត្រឹមត្រូវទេ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/kn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/kn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1c112d5 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/kn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/kn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/kn/LC_MESSAGES/django.po new file mode 100644 index 0000000..7d67436 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/kn/LC_MESSAGES/django.po @@ -0,0 +1,259 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Kannada (http://www.transifex.com/django/django/language/" +"kn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kn\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "ಪ್ರಾರಂಭಸ್ಥಳ(ಮನೆ)" + +msgid "Documentation" +msgstr "ವಿವರಮಾಹಿತಿ" + +msgid "Bookmarklets" +msgstr "ಚಿಕ್ಕ ಪುಟಗುರುತುಗಳು" + +msgid "Documentation bookmarklets" +msgstr "ಮಾಹಿತಿಯ ಚಿಕ್ಕ ಪುಟಗುರುತುಗಳು" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "ಈ ಪುಟದ ಬಗೆಗಿನ ಮಾಹಿತಿ" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"ನಿಮ್ಮನ್ನು ಯಾವುದೇ ಪುಟದಿಂದ ಆ ಪುಟವನ್ನು ಸೃಷ್ಟಿಸುವ ನೋಟದ ಮಾಹಿತಿಪುಟಕ್ಕೆ ಕೊಂಡೊಯ್ಯುವದು" + +msgid "Tags" +msgstr "" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "ಟ್ಯಾಗ್:" + +msgid "filter:" +msgstr "ಸೋಸಕ:" + +msgid "view:" +msgstr "ನೋಟ:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "" + +msgid "model:" +msgstr "ಮಾಡೆಲ್:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "" + +#, python-format +msgid "all %s" +msgstr "ಎಲ್ಲಾ %s" + +#, python-format +msgid "number of %s" +msgstr "%s ಗಳ ಸಂಖ್ಯೆ" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s URL ಸ್ವರೂಪದ್ದಾಗಿ ತೋರುವದಿಲ್ಲ." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ko/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ko/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3185670 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ko/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ko/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ko/LC_MESSAGES/django.po new file mode 100644 index 0000000..7466f0f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ko/LC_MESSAGES/django.po @@ -0,0 +1,280 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jiyoon, Ha , 2016 +# 코딩 영, 2021 +# Geonho Kim / Leo Kim , 2019 +# Ian Y. Choi , 2015 +# Jannis Leidel , 2011 +# Le Tartuffe , 2014,2016 +# Kagami Sascha Rosylight , 2017 +# 이지현 , 2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-11-10 02:10+0000\n" +"Last-Translator: 코딩 영\n" +"Language-Team: Korean (http://www.transifex.com/django/django/language/ko/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ko\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Administrative Documentation" +msgstr "관리 문서" + +msgid "Home" +msgstr "홈" + +msgid "Documentation" +msgstr "문서" + +msgid "Bookmarklets" +msgstr "북마크릿" + +msgid "Documentation bookmarklets" +msgstr "문서 북마크릿" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"북마크릿을 설치하시려면 링크를 북마크 툴바로 드래그 하거나, 오른쪽 클릭으로 " +"해당 링크를 북마크에 추가하세요. 이제 사이트 내의 모든 페이지에서 북마크릿 선" +"택이 가능합니다." + +msgid "Documentation for this page" +msgstr "이 페이지의 문서" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "각 페이지로에서 해당 페이지를 생성한 뷰의 문서로 갑니다." + +msgid "Tags" +msgstr "태그" + +msgid "List of all the template tags and their functions." +msgstr "모든 템플릿 태그와 함수의 목록" + +msgid "Filters" +msgstr "필터" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "필터는 템플릿의 변수에 적용되어 출력을 바꿀 수 있는 동작입니다." + +msgid "Models" +msgstr "모델" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"모델은 모든 시스템에서 개체와 연관된 필드에 대한 설명입니다. 각 모델은 템플" +"릿 변수로 접근 할 수 있는 필드의 목록을 가지고 있습니다." + +msgid "Views" +msgstr "뷰" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"일반 사이트의 각 페이지는 뷰에 의해 생성됩니다. 뷰는 페이지를 생성하는데 사용" +"되는 템플릿과 그 템플릿을 사용할 수 있게해주는 개체를 정의합니다." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "브라우저 도구는 신속하게 관리자 기능에 접근 할 수 있습니다." + +msgid "Please install docutils" +msgstr "docutils를 설치해주세요." + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"관리자 문서 시스템은 파이썬의 docutils 라이브러리" +"를 필요로 합니다." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "관리자에게 docutils 설치를 요청해주세요." + +#, python-format +msgid "Model: %(name)s" +msgstr "Model: %(name)s" + +msgid "Fields" +msgstr "필드" + +msgid "Field" +msgstr "필드" + +msgid "Type" +msgstr "타입" + +msgid "Description" +msgstr "설명" + +msgid "Methods with arguments" +msgstr "아규먼트를 포함한 메소드" + +msgid "Method" +msgstr "메소드" + +msgid "Arguments" +msgstr "아규먼트" + +msgid "Back to Model documentation" +msgstr "모델문서로 돌아가기" + +msgid "Model documentation" +msgstr "모델 문서" + +msgid "Model groups" +msgstr "모델 그룹" + +msgid "Templates" +msgstr "템플릿" + +#, python-format +msgid "Template: %(name)s" +msgstr "템플릿 : %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "템플릿: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "템플릿%(name)s에 대한 검색 경로:" + +msgid "(does not exist)" +msgstr "(존재하지 않습니다)" + +msgid "Back to Documentation" +msgstr "문서로 " + +msgid "Template filters" +msgstr "템플릿 필터" + +msgid "Template filter documentation" +msgstr "템플릿 필터 문서" + +msgid "Built-in filters" +msgstr "내장 필터" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"이 필터를 사용하기 위해서는 필터를 사용하기 전에 템플릿에 <코드>%(code)s 를 입력하세요." + +msgid "Template tags" +msgstr "템플릿 태그" + +msgid "Template tag documentation" +msgstr "템플릿 태그 문서" + +msgid "Built-in tags" +msgstr "내장 태그" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"이 태그를 사용하기 위해서는 태그를 사용하기 전에 템플릿에 %(code)s 를 입력하세요." + +#, python-format +msgid "View: %(name)s" +msgstr "뷰: %(name)s" + +msgid "Context:" +msgstr "컨텍스트 :" + +msgid "Templates:" +msgstr "템플릿 :" + +msgid "Back to View documentation" +msgstr "뷰 문서로 돌아가기" + +msgid "View documentation" +msgstr "뷰 문서" + +msgid "Jump to namespace" +msgstr "네임스페이스로" + +msgid "Empty namespace" +msgstr "빈 네임스페이스" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "%(name)s 네임스페이스 뷰" + +msgid "Views by empty namespace" +msgstr "빈 네임스페이스 뷰" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"뷰 함수: %(full_name)s. Name: %(url_name)s.\n" + +msgid "tag:" +msgstr "태그:" + +msgid "filter:" +msgstr "필터:" + +msgid "view:" +msgstr "뷰:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "애플리케이션 %(app_label)r 을 찾을 수 없습니다." + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "" +"모델 %(model_name)r 을 애플리케이션 %(app_label)r 에서 찾을 수 없습니다." + +msgid "model:" +msgstr "모델:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "`%(app_label)s.%(data_type)s` 관련된 개체" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "`%(app_label)s.%(object_name)s` 관련된 개체들" + +#, python-format +msgid "all %s" +msgstr "모든 %s" + +#, python-format +msgid "number of %s" +msgstr "%s 의 수" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s 은/는 url 패턴의 개체가 아닙니다." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ky/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ky/LC_MESSAGES/django.mo new file mode 100644 index 0000000..de83cd3 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ky/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ky/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ky/LC_MESSAGES/django.po new file mode 100644 index 0000000..ae974b6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ky/LC_MESSAGES/django.po @@ -0,0 +1,281 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Soyuzbek Orozbek uulu , 2020-2021 +# Soyuzbek Orozbek uulu , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-04-02 11:59+0000\n" +"Last-Translator: Soyuzbek Orozbek uulu \n" +"Language-Team: Kyrgyz (http://www.transifex.com/django/django/language/ky/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ky\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Administrative Documentation" +msgstr "Башкармалык түшүндүрмөсү" + +msgid "Home" +msgstr "Башкы" + +msgid "Documentation" +msgstr "Түшүндүрмө" + +msgid "Bookmarklets" +msgstr "Букмарклеттер" + +msgid "Documentation bookmarklets" +msgstr "букмарклет түшүндүрмөсү" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Букмарклетти орнотуу үчүн шилтемени кыстырмалар панелине сүйрөңүз же " +"шилтемени оң чыкылдатып андан соң кыстырмаларыңызга кошуп алыңыз. Азыр " +"букмарклетти сайттын бүт бетинен тандап алсаңыз болот." + +msgid "Documentation for this page" +msgstr "Бул барактын түшүндүрмөсү" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Бул баракты жараткан көрүнүш үчүн сиз каалаган барактагы түшүндүрмөдөн " +"секирип өтүңүз." + +msgid "Tags" +msgstr "Тегдер" + +msgid "List of all the template tags and their functions." +msgstr "Бүт калып тегдердин жана алардын кызматынын тизмеси" + +msgid "Filters" +msgstr "Чыпкалар" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Чыпкалар чыгуучу агымды өзгөртүү үчүн калыптагы өзгөрмөгө жасалуучу аракет " +"болуп саналат." + +msgid "Models" +msgstr "Моделдер" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Моделдер системдеги бүт обекттер жана алардын талаалардын ачыкталышы. Ар бир " +"модел өзүнө талааларды камтыйт. Алар өз учурунда калыптуу өзгөрмөлөр катары " +"жетүүнү камсыз кылат." + +msgid "Views" +msgstr "Көрүнүштөр" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Ачык саттагы ар бир барак көрүнүш аркылуу чыгарылган. Көрүнүш баракты " +"чыгаруу үчүн кайсы калып колдонууларын жана кайсы обекттер жеткиликтүү " +"экендигин аныктайт." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "Браузер үчүн башкаруу кызматына тез жетүү үчүн куралдар." + +msgid "Please install docutils" +msgstr "түшүндүрмө утилитасын орнотуңуз." + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Башкармалыктын түшүндүрмө системи Питондун docutils " +"китепканасын талап кылат. " + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Башкаруучудан түшүндүрмө утилитасынорнотууну " +"сураңыз." + +#, python-format +msgid "Model: %(name)s" +msgstr "Модел: %(name)s" + +msgid "Fields" +msgstr "Талаалар" + +msgid "Field" +msgstr "Талаа" + +msgid "Type" +msgstr "Тип" + +msgid "Description" +msgstr "Ачыктоо" + +msgid "Methods with arguments" +msgstr "аргументүү ыкма" + +msgid "Method" +msgstr "Ыкма" + +msgid "Arguments" +msgstr "Аргумент" + +msgid "Back to Model documentation" +msgstr "Модел түшүндүрмөсүнө кайт" + +msgid "Model documentation" +msgstr "Модел түшүндүрмөсү" + +msgid "Model groups" +msgstr "Модел тайпасы" + +msgid "Templates" +msgstr "Калыптар" + +#, python-format +msgid "Template: %(name)s" +msgstr "Калып: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Калып: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "%(name)sкалыбы үчүн жолду издөө:" + +msgid "(does not exist)" +msgstr "(табылган жок)" + +msgid "Back to Documentation" +msgstr "Түшүндүрмөгө кайт" + +msgid "Template filters" +msgstr "Калып чыпкалары" + +msgid "Template filter documentation" +msgstr "Калып чыпкалары түшүндүрмөсү" + +msgid "Built-in filters" +msgstr "Бар чыпкалар" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Бул чыпкаларды колдонуудан мурда калыбыңызга %(code)sкоюңуз." + +msgid "Template tags" +msgstr "Калып тегдер" + +msgid "Template tag documentation" +msgstr "Калып тегдер түшүндүрмөсү" + +msgid "Built-in tags" +msgstr "Мурдатан бар тегдер" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Тегдерди колдонуш үчүн: тегди колдонуудан мурда калыбыңызга%(code)sкоюңуз." + +#, python-format +msgid "View: %(name)s" +msgstr "Көрүнүш: %(name)s" + +msgid "Context:" +msgstr "Мазмун:" + +msgid "Templates:" +msgstr "Калыптар:" + +msgid "Back to View documentation" +msgstr "Көрүнүш түшүндүрмөсүнө кайт" + +msgid "View documentation" +msgstr "Көрүнүш түшүндүрмөсү" + +msgid "Jump to namespace" +msgstr "ысым мейкиндигине өтүү" + +msgid "Empty namespace" +msgstr "бош ысым мейкиндиги" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "%(name)sысым мейкиндиги боюнча көрүү" + +msgid "Views by empty namespace" +msgstr "бош ысым мейкиндиги боюнча көрүү" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"Көрүнүш функциасы: %(full_name)s.Аты:%(url_name)s.\n" + +msgid "tag:" +msgstr "тег:" + +msgid "filter:" +msgstr "чыпка:" + +msgid "view:" +msgstr "көрүнүш:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "%(app_label)r колдонмосу табылган жок" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "%(app_label)r колдонмосунда %(model_name)r модели табылбады" + +msgid "model:" +msgstr "модел:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "байланышкан `%(app_label)s.%(data_type)s` обектиси" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "байланышкан `%(app_label)s.%(object_name)s` обекттери" + +#, python-format +msgid "all %s" +msgstr "Бүт %s" + +#, python-format +msgid "number of %s" +msgstr "%s саны" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s урлкалып обектисине тиешеси жок" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/lb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/lb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b5507d4 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/lb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/lb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/lb/LC_MESSAGES/django.po new file mode 100644 index 0000000..26d571b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/lb/LC_MESSAGES/django.po @@ -0,0 +1,275 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2015-01-18 08:34+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Luxembourgish (http://www.transifex.com/projects/p/django/" +"language/lb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "" + +msgid "Documentation" +msgstr "" + +msgid "Bookmarklets" +msgstr "" + +msgid "Documentation bookmarklets" +msgstr "" + +msgid "" +"\n" +"

    To install bookmarklets, drag the link to your bookmarks\n" +"toolbar, or right-click the link and add it to your bookmarks. Now you can\n" +"select the bookmarklet from any page in the site. Note that some of these\n" +"bookmarklets require you to be viewing the site from a computer designated\n" +"as \"internal\" (talk to your system administrator if you aren't sure if\n" +"your computer is \"internal\").

    \n" +msgstr "" + +msgid "Documentation for this page" +msgstr "" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" + +msgid "Show object ID" +msgstr "" + +msgid "" +"Shows the content-type and unique ID for pages that represent a single " +"object." +msgstr "" + +msgid "Edit this object (current window)" +msgstr "" + +msgid "Jumps to the admin page for pages that represent a single object." +msgstr "" + +msgid "Edit this object (new window)" +msgstr "" + +msgid "As above, but opens the admin page in a new window." +msgstr "" + +msgid "Tags" +msgstr "" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Back to Model Documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to Views Documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "" + +msgid "tag:" +msgstr "" + +msgid "filter:" +msgstr "" + +msgid "view:" +msgstr "" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "" + +msgid "model:" +msgstr "" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "" + +#, python-format +msgid "all %s" +msgstr "" + +#, python-format +msgid "number of %s" +msgstr "" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/lt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/lt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e4e2172 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/lt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/lt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/lt/LC_MESSAGES/django.po new file mode 100644 index 0000000..1d392c8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/lt/LC_MESSAGES/django.po @@ -0,0 +1,290 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Kostas , 2014 +# lauris , 2011 +# Matas Dailyda , 2015-2016 +# Povilas Balzaravičius , 2014 +# Simonas Kazlauskas , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Lithuanian (http://www.transifex.com/django/django/language/" +"lt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lt\n" +"Plural-Forms: nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < " +"11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? " +"1 : n % 1 != 0 ? 2: 3);\n" + +msgid "Administrative Documentation" +msgstr "Administravimo dokumentacija" + +msgid "Home" +msgstr "Pradinis" + +msgid "Documentation" +msgstr "Dokumentacija" + +msgid "Bookmarklets" +msgstr "Greitosios žymės" + +msgid "Documentation bookmarklets" +msgstr "Doumentacijos greitosios žymės" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Greitųjų žymių įdiegimui, nutempkite nuorodą į greitųjų žymių juostą, arba " +"spauskite dešinį pelės klavišą ir pridėkite prie greitųjų žymių. Dabar " +"galite pasirinkti greitąją žymę iš bet kurio tinklalapio puslapio." + +msgid "Documentation for this page" +msgstr "Šio puslapio dokumentacija" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Pereina iš bet kurio puslapio į jo view funkcijos dokumentaciją, kuri " +"sukūria tą puslapį" + +msgid "Tags" +msgstr "Žymenos" + +msgid "List of all the template tags and their functions." +msgstr "Sąrašas visų šablono žymenų ir jų funkcijų." + +msgid "Filters" +msgstr "Filtrai" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Filtrai yra veiksmai, kurie gali būti pritaikyti šablono kintamiesiems, kad " +"pakeisti jų išvestį." + +msgid "Models" +msgstr "Modeliai" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Modeliai yra visų sistemos objektų ir su jais susijusių laukų apibūdinimai. " +"Kiekvienas modelis turi sąrašą laukų, kuriuos galima pasiekti kaip šablono " +"kintamuosius." + +msgid "Views" +msgstr "Rodiniai" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Kiekvienas puslapis viešame tinklalapyje sugeneruojamas pagal rodmenis. " +"Rodmuo apibūdina kuris šablonas yra naudojamas generuojant puslapį ir kurie " +"objektai yra suteikiami tam šablonui." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Įrankiai Jūsų naršyklėi, kad greitai pasiektumėte administravimo " +"funkcionalumą." + +msgid "Please install docutils" +msgstr "Įdiekite docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" +"Administravimo dokumentacijos sistema reikalauja Python'o bibliotekos docutils." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Prašykite kad administratorius įdiegtų docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Modelis: %(name)s" + +msgid "Fields" +msgstr "Laukai" + +msgid "Field" +msgstr "Laukas" + +msgid "Type" +msgstr "Tipas" + +msgid "Description" +msgstr "Aprašymas" + +msgid "Methods with arguments" +msgstr "Metodai su argumentais" + +msgid "Method" +msgstr "Metodas" + +msgid "Arguments" +msgstr "Argumentai" + +msgid "Back to Model documentation" +msgstr "Grįžti į modelio dokumentaciją" + +msgid "Model documentation" +msgstr "Modelio dokumentacija" + +msgid "Model groups" +msgstr "Modelio grupės" + +msgid "Templates" +msgstr "Šablonai" + +#, python-format +msgid "Template: %(name)s" +msgstr "Šablonas: %(name)s" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "Šablonas: \"%(name)s\"" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "Ieškoti kelio šablonui \"%(name)s\":" + +msgid "(does not exist)" +msgstr "(neegzistuoja)" + +msgid "Back to Documentation" +msgstr "Grįžti į dokumentacija" + +msgid "Template filters" +msgstr "Šablono filtrai" + +msgid "Template filter documentation" +msgstr "Šablono filtro dokumentacija" + +msgid "Built-in filters" +msgstr "Standartiniai filtrai" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Kad panaudoti šiuos filtrus, prieš naudojant filtrą šablone įveskite " +"%(code)s." + +msgid "Template tags" +msgstr "Šablono žymenos" + +msgid "Template tag documentation" +msgstr "Šablono žymenos dokumentacija" + +msgid "Built-in tags" +msgstr "Standartinės žymenos" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Kad panaudoti šias žymenas, prieš naudojant žymeną šablone įveskite " +"%(code)s." + +#, python-format +msgid "View: %(name)s" +msgstr "Rodinys: %(name)s" + +msgid "Context:" +msgstr "Konstekstas:" + +msgid "Templates:" +msgstr "Šablonai:" + +msgid "Back to View documentation" +msgstr "Grįžti į rodinio dokumentaciją" + +msgid "View documentation" +msgstr "Žiūrėti dokumentaciją" + +msgid "Jump to namespace" +msgstr "Eiti į vardų plotmę" + +msgid "Empty namespace" +msgstr "Tuščia vardų plotmė" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Rodiniai pagal vardų plotmes %(name)s" + +msgid "Views by empty namespace" +msgstr "Rodiniai pagal tuščias vardų plotmes." + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"Rodinio funkcija: %(full_name)s. Pavadinimas: " +"%(url_name)s.\n" + +msgid "tag:" +msgstr "žymė:" + +msgid "filter:" +msgstr "filtras:" + +msgid "view:" +msgstr "vaizdas:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "%(app_label)r aplikacija nerasta" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Modelis %(model_name)r programoje %(app_label)r nerastas" + +msgid "model:" +msgstr "modelis:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "susijęs `%(app_label)s.%(data_type)s` objektas" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "susiję`%(app_label)s.%(object_name)s` objektai" + +#, python-format +msgid "all %s" +msgstr "visi %s" + +#, python-format +msgid "number of %s" +msgstr "%s skaičius" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s neatrodo kaip urlpattern objektas" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/lv/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/lv/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d2ef159 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/lv/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/lv/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/lv/LC_MESSAGES/django.po new file mode 100644 index 0000000..b153b4d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/lv/LC_MESSAGES/django.po @@ -0,0 +1,284 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# NullIsNot0 , 2017 +# Jannis Leidel , 2011 +# Māris Nartišs , 2016 +# NullIsNot0 , 2019,2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-01-25 22:44+0000\n" +"Last-Translator: NullIsNot0 \n" +"Language-Team: Latvian (http://www.transifex.com/django/django/language/" +"lv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lv\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : " +"2);\n" + +msgid "Administrative Documentation" +msgstr "Administrācijas dokumentācija" + +msgid "Home" +msgstr "Sākums" + +msgid "Documentation" +msgstr "Dokumentācija" + +msgid "Bookmarklets" +msgstr "Grāmatzīmes" + +msgid "Documentation bookmarklets" +msgstr "Dokumentācijas grāmatzīmes" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Lai instalētu bukmarkletu, velciet saiti uz grāmatzīmju rīkjoslu, vai ar " +"peles labo pogu noklikšķiniet uz saites un pievienojiet to savām " +"grāmatzīmēm. Tagad jūs varat izvēlēties bukmarkletu no jebkuras vietnes " +"lapas." + +msgid "Documentation for this page" +msgstr "Dokumentācija šai lapai" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Pārvieto no jebkuras lapas uz tā skata dokumentāciju, kas ģenerē šo lapu." + +msgid "Tags" +msgstr "Tagi" + +msgid "List of all the template tags and their functions." +msgstr "Visu šablonu tagu un to funkciju saraksts." + +msgid "Filters" +msgstr "Filtri" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Filtri ir darbības, kuras var tikt pielietotas šablona mainīgajiem, lai " +"mainītu izvades rezultātu." + +msgid "Models" +msgstr "Modeļi" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Modeļi ir visu sistēmas objektu un to saistīto lauku apraksti. Katram " +"modelim ir saraksts ar laukiem, kuriem var piekļūt kā šablonu mainīgajiem" + +msgid "Views" +msgstr "Skati" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Katru lapu publiskajā vietnē ģenerē skats. Skats nosaka, kuru šablonu " +"izmanto lapas ģenerēšanai un kādi objekti ir pieejami šim šablonam." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Rīki Jūsu pārlūkprogrammai, lai ātri piekļūtu administratora " +"funkcionalitātei." + +msgid "Please install docutils" +msgstr "Lūdzu instalējiet 'docutils'" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Administratora dokumentācijas sistēmai ir nepieciešama Python docutils bibliotēka." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "Palūdziet administratoram instalēt docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Modelis: %(name)s" + +msgid "Fields" +msgstr "Lauki" + +msgid "Field" +msgstr "Lauks" + +msgid "Type" +msgstr "Tips" + +msgid "Description" +msgstr "Apraksts" + +msgid "Methods with arguments" +msgstr "Metodes ar parametriem" + +msgid "Method" +msgstr "Metode" + +msgid "Arguments" +msgstr "Parametrs" + +msgid "Back to Model documentation" +msgstr "Atpakaļ uz Modeļu dokumentāciju" + +msgid "Model documentation" +msgstr "Modeļu dokumentācija" + +msgid "Model groups" +msgstr "Modeļu grupas" + +msgid "Templates" +msgstr "Šabloni" + +#, python-format +msgid "Template: %(name)s" +msgstr "Šablons: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Šablons: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Šablona %(name)s ceļš:" + +msgid "(does not exist)" +msgstr "(neeksistē)" + +msgid "Back to Documentation" +msgstr "Atpakaļ pie Dokumentācijas" + +msgid "Template filters" +msgstr "Šablona filtri" + +msgid "Template filter documentation" +msgstr "Šablona filtru dokumentācija" + +msgid "Built-in filters" +msgstr "Iebūvētie filtri" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Lai izmantotu šos filtrus, ievietojiet %(code)s šablonā pirms " +"filtra izmantošanas." + +msgid "Template tags" +msgstr "Šablonu tagi" + +msgid "Template tag documentation" +msgstr "Šablonu tagu dokumentācija" + +msgid "Built-in tags" +msgstr "Iebūvētie tagi" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Lai izmantotu šos tagus, ievietojiet %(code)s šablonā pirms " +"taga izmantošanas." + +#, python-format +msgid "View: %(name)s" +msgstr "View: %(name)s" + +msgid "Context:" +msgstr "Konteksts:" + +msgid "Templates:" +msgstr "Šabloni:" + +msgid "Back to View documentation" +msgstr "Atpakaļ pie Skatu dokumentācijas" + +msgid "View documentation" +msgstr "Skatu dokumentācija" + +msgid "Jump to namespace" +msgstr "Pāriet uz vārdtelpu" + +msgid "Empty namespace" +msgstr "Tukša vārdtelpa" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Skati pēc vārdtelpas %(name)s" + +msgid "Views by empty namespace" +msgstr "Skati pēc tukšas vārdtelpas" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +" Skata funkcija: %(full_name)s. Nosaukums: " +"%(url_name)s.\n" + +msgid "tag:" +msgstr "tags:" + +msgid "filter:" +msgstr "filtrs:" + +msgid "view:" +msgstr "skats:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Lietotne %(app_label)r netika atrasta" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Modelis %(model_name)r lietotnē %(app_label)r nav atrasts" + +msgid "model:" +msgstr "modelis:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "saistītais `%(app_label)s.%(data_type)s` objekts" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "saistītie `%(app_label)s.%(object_name)s` objekti" + +#, python-format +msgid "all %s" +msgstr "visi %s" + +#, python-format +msgid "number of %s" +msgstr "%s skaits" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s nav urlpattern objekts" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/mk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/mk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e2b663e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/mk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/mk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/mk/LC_MESSAGES/django.po new file mode 100644 index 0000000..128e463 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/mk/LC_MESSAGES/django.po @@ -0,0 +1,286 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Vasil Vangelovski , 2016-2017 +# Vasil Vangelovski , 2013-2014 +# Vasil Vangelovski , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Vasil Vangelovski \n" +"Language-Team: Macedonian (http://www.transifex.com/django/django/language/" +"mk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mk\n" +"Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n" + +msgid "Administrative Documentation" +msgstr "Административна документација" + +msgid "Home" +msgstr "Дома" + +msgid "Documentation" +msgstr "Документација" + +msgid "Bookmarklets" +msgstr "Обележувачи" + +msgid "Documentation bookmarklets" +msgstr "Обележувачи на документација" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"За да инсталирате букмарклети повлечете го линкот во траката со bookmarks, " +"или кликенете со десното копче и додадете го во bookmarks. Така ќе можете да " +"го одберете букмарклетот од било која страна на сајтот." + +msgid "Documentation for this page" +msgstr "Документација за оваа страница" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Ве носи од било која страница од документацијата до погледот кој ја генерира " +"таа страница." + +msgid "Tags" +msgstr "Тагови" + +msgid "List of all the template tags and their functions." +msgstr "Листа на сите шаблонски тагови и нивните функции." + +msgid "Filters" +msgstr "Филтри" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Филтри се акции кои може да се применат на променливи во шаблон за менување " +"на излезниот резултат." + +msgid "Models" +msgstr "Модели" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Модели се описи на сите објекти во системот и нивните полиња. Секој модел " +"има листа на полиња до кои може да се пристапи со променливи во шаблони." + +msgid "Views" +msgstr "Погледи (вјуа)" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Секоја страна на јавниот сајт се генерира од поглед. Подгледот дефинира кој " +"шаблон се користи за да се генерира страната и кој објекти се достапни за " +"тој шаблон." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Алатки за вашиот веб прегледувач за брз пристап до администраторските " +"функционалности." + +msgid "Please install docutils" +msgstr "Ве молиме инсталирајте docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" +"На админ документацискиот систем му е потребна docutils Python библиотеката." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Ве молиме побарајте од вашите администратори да инсталираат docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Модел %(name)s" + +msgid "Fields" +msgstr "Полиња" + +msgid "Field" +msgstr "Поле" + +msgid "Type" +msgstr "Тип" + +msgid "Description" +msgstr "Опис" + +msgid "Methods with arguments" +msgstr "Методи со аргументи" + +msgid "Method" +msgstr "Метод" + +msgid "Arguments" +msgstr "Аргументи" + +msgid "Back to Model documentation" +msgstr "Назад до документација за модели." + +msgid "Model documentation" +msgstr "Документација за модели" + +msgid "Model groups" +msgstr "Групи на модели" + +msgid "Templates" +msgstr "Шаблони (темплејти)" + +#, python-format +msgid "Template: %(name)s" +msgstr "Шаблон: %(name)s" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "Шаблон: \"%(name)s\"" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "Пребарај ја патеката за шаблонот \"%(name)s\":" + +msgid "(does not exist)" +msgstr "(не постои)" + +msgid "Back to Documentation" +msgstr "Назад во документација" + +msgid "Template filters" +msgstr "Шаблонски филтри" + +msgid "Template filter documentation" +msgstr "Документација за шаблонски филтер" + +msgid "Built-in filters" +msgstr "Вградени филтри" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"За да ги користите овие филтри, внесете %(code)s во вашиот " +"шаблон пред да го користите филтерот." + +msgid "Template tags" +msgstr "Шаблонски тагови" + +msgid "Template tag documentation" +msgstr "Документација за шаблонски таг" + +msgid "Built-in tags" +msgstr "Вградени тагови" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"За да ги користите овие тагови, внесете %(code)s во вашиот " +"шаблон пред да го користите тагот." + +#, python-format +msgid "View: %(name)s" +msgstr "Поглед: %(name)s" + +msgid "Context:" +msgstr "Контекст:" + +msgid "Templates:" +msgstr "Шаблони:" + +msgid "Back to View documentation" +msgstr "Назад до документација за погледи" + +msgid "View documentation" +msgstr "Документација за поглед" + +msgid "Jump to namespace" +msgstr "Скокни до именски простор" + +msgid "Empty namespace" +msgstr "Празен именски простор" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Погледи по именски простор %(name)s" + +msgid "Views by empty namespace" +msgstr "Погледи по празен именски простор" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +" Погледска функција (вју функција): %(full_name)s. Име: " +"%(url_name)s.\n" + +msgid "tag:" +msgstr "таг:" + +msgid "filter:" +msgstr "филтер:" + +msgid "view:" +msgstr "поглед:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Апликацијата %(app_label)r не е пронајдена" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Моделот %(model_name)r не е најден во апликацијата %(app_label)r" + +msgid "model:" +msgstr "модел:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "поврзаниот `%(app_label)s.%(data_type)s` објект" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "поврзани `%(app_label)s.%(object_name)s` објекти" + +#, python-format +msgid "all %s" +msgstr "сите %s" + +#, python-format +msgid "number of %s" +msgstr "број на %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s не изгледа дека е url објект" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ml/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ml/LC_MESSAGES/django.mo new file mode 100644 index 0000000..89d79cc Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ml/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ml/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ml/LC_MESSAGES/django.po new file mode 100644 index 0000000..a73c318 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ml/LC_MESSAGES/django.po @@ -0,0 +1,268 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Emil Joseph , 2019 +# Jannis Leidel , 2011 +# MUHAMMED RAMEEZ , 2019 +# Rag sagar , 2016 +# Rajeesh Nair , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2019-03-10 07:17+0000\n" +"Last-Translator: Emil Joseph \n" +"Language-Team: Malayalam (http://www.transifex.com/django/django/language/" +"ml/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ml\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "കാര്യനിർവ്വാഹകർക്കായുള്ള ഡോക്യൂമെന്റേഷൻ " + +msgid "Home" +msgstr "ഹോം " + +msgid "Documentation" +msgstr "സഹായക്കുറിപ്പുകള്‍" + +msgid "Bookmarklets" +msgstr "ബുക്ക് മാര്‍ക്കുകള്‍" + +msgid "Documentation bookmarklets" +msgstr "സഹായക്കുറിപ്പുകളുടെ ബുക്ക്മാര്‍ക്കുകള്‍" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"ബുക്ക്മാർക്കുകൾ ഇൻസ്റ്റാൾ ചെയ്യാൻ, നിങ്ങളുടെ ബുക്ക്മാർക്കുകൾ ടൂൾബാറിലേക്ക് ലിങ്ക് ഇഴയ്ക്കുക, " +"അല്ലെങ്കിൽ ലിങ്കിൽ വലത് ക്ലിക്കുചെയ്ത് നിങ്ങളുടെ ബുക്ക്മാർക്കുകളിൽ ചേർക്കുക. ഇപ്പോൾ നിങ്ങൾക്ക് " +"സൈറ്റിലെ ഏത് പേജിൽ നിന്നും ബുക്മാർക്കറ്റ് തിരഞ്ഞെടുക്കാം." + +msgid "Documentation for this page" +msgstr "ഈ പേജിന്റെ സഹായക്കുറിപ്പുകള്‍" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "ഏതു പേജില്‍ നിന്നും അതിന്റെ ഉദ്ഭവമായ വ്യൂവിന്റെ സഹായക്കുറിപ്പിലേക്കു ചാടാന്‍" + +msgid "Tags" +msgstr "ടാഗുകള്‍" + +msgid "List of all the template tags and their functions." +msgstr "എല്ലാ ടെംപ്ലേറ്റുകളും അവയുടെ ഫംഗ്ഷനുകളുടെ പട്ടിക" + +msgid "Filters" +msgstr "ഫില്‍ട്ടറുകള്‍" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"ഫിൽറ്ററുകൾ എന്നാൽ ഔട്പുട്ടിനു മാറ്റം വരുത്തുവാൻ ടെംപ്ലേറ്റുകൾക്കു ഉള്ളില്ലേ വാരിയബിലിസിന് " +"(variables) നൽകുന്ന ആക്ഷൻസ്സാണ് " + +msgid "Models" +msgstr "മോഡലുകള്‍" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "വ്യൂകള്‍" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"അഡ്മിൻ ഫങ്ക്ഷണാലിറ്റിയിലേക്കു പെട്ടെന്നു പ്രവേശിക്കുവാൻ നിങ്ങളുടെ ബ്രൗസെറിനുള്ള ടൂളുകൾ ." + +msgid "Please install docutils" +msgstr "ദയവായി ഡോക്യൂട്ടിൽസ്‌ ഇൻസ്റ്റാൾ ചെയ്യുക." + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "ഫീൽഡുകൾ " + +msgid "Field" +msgstr "ഫീൽഡ്." + +msgid "Type" +msgstr "ടൈപ്പ് " + +msgid "Description" +msgstr "വിവരണം" + +msgid "Methods with arguments" +msgstr "മെതോടുകൾ ഉള്ള ആർഗുമെന്റ്സ് " + +msgid "Method" +msgstr "രീതി" + +msgid "Arguments" +msgstr "വാദങ്ങൾ" + +msgid "Back to Model documentation" +msgstr "മോഡൽ ഡോക്യൂമെന്റന്റഷനിലേക്ക് തിരികെ പോവുക ." + +msgid "Model documentation" +msgstr "മോഡൽ ഡോക്യൂമെന്റേഷൻ." + +msgid "Model groups" +msgstr "മോഡൽ ഗ്രൂപ്സ്" + +msgid "Templates" +msgstr "ടെമ്പ്‌ലേറ്റുകള്‍" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "(എക്സിസ്റ് ചെയ്യുന്നില്ല )" + +msgid "Back to Documentation" +msgstr "ഡോക്യൂമെന്റഷനിലേക്കു തിരികെ പോവുക ." + +msgid "Template filters" +msgstr "ടെമ്പ്ലേറ്റ് ഫിൽറ്ററുകൾ " + +msgid "Template filter documentation" +msgstr "ടെമ്പ്ലേറ്റ് ഫിൽറ്റർ ഡോക്യൂമെന്റേഷൻ " + +msgid "Built-in filters" +msgstr "ബിൽട്ടിൻ ഫിൽറ്ററുകൾ " + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "ടെമ്പ്ലേറ്റ് റ്റാഗുകൾ " + +msgid "Template tag documentation" +msgstr "ടെമ്പ്ലേറ്റ് ടാഗിന്റെ ഡോക്യൂമെന്റേഷൻ " + +msgid "Built-in tags" +msgstr "ബിൽട്ടിൻ റ്റാഗുകൾ " + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "കോണ്ടെക്സ്റ് :" + +msgid "Templates:" +msgstr "ടെമ്പ്‌ലേറ്റുകള്‍" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "ഡോക്യൂമെന്റെഷൻ കാണുക " + +msgid "Jump to namespace" +msgstr "നെയിംസ്പേസിലേക്ക് ചാടുക ." + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "ടാഗ്:" + +msgid "filter:" +msgstr "അരിപ്പ:" + +msgid "view:" +msgstr "വ്യൂ" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "%(app_label)r എന്ന Appല്‍ %(model_name)r എന്ന മാത്രുക കണ്ടില്ല." + +msgid "model:" +msgstr "മാത്രുക:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "ബന്ധപ്പെട്ട `%(app_label)s.%(data_type)s` വസ്തു" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "ബന്ധപ്പെട്ട `%(app_label)s.%(object_name)s` വസ്തുക്കള്‍" + +#, python-format +msgid "all %s" +msgstr "%s എല്ലാം" + +#, python-format +msgid "number of %s" +msgstr "%sന്റെ എണ്ണം" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s വിലാസ മാത്രുക (urlpattern object) ആണെന്ന് തോന്നുന്നില്ല." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/mn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/mn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7d0ec6a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/mn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/mn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/mn/LC_MESSAGES/django.po new file mode 100644 index 0000000..e4e4b0c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/mn/LC_MESSAGES/django.po @@ -0,0 +1,284 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bayarkhuu Bataa, 2014 +# Claude Paroz , 2014 +# Jannis Leidel , 2011 +# Zorig , 2013-2014,2016-2017 +# Анхбаяр Анхаа , 2014-2015 +# Баясгалан Цэвлээ , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Zorig \n" +"Language-Team: Mongolian (http://www.transifex.com/django/django/language/" +"mn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Удирдлагын баримт" + +msgid "Home" +msgstr "Админ эхлэл" + +msgid "Documentation" +msgstr "Баримтжуулалт" + +msgid "Bookmarklets" +msgstr "Bookmarklet-ууд" + +msgid "Documentation bookmarklets" +msgstr "Мookmarklet-уудын баримтжуулалт" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Bookmarklet тэмдэглэл суулгахын тулд холбоосыг өөрийн bookmark талбар руу " +"чирэх эсвэл хулганы баруун даралт дарж bookmark -т нэмэх сонголтыг сонгоно. " +"Ингэснээр аль ч хуудаснаас bookmarklet-ээ сонгох боломжтой болно." + +msgid "Documentation for this page" +msgstr "Энэ хуудасны баримтжуулалт" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Таныг ямар ч хамаагүй хуудаснаас тухайн хуудсыг гаргаж байгаа " +"баримтжуулалтанд аваачна." + +msgid "Tags" +msgstr "Таг-ууд" + +msgid "List of all the template tags and their functions." +msgstr "Бүх загваруудын шошго мөн тэдний функц" + +msgid "Filters" +msgstr "Шүүлтүүрүүд" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "Шүүлтүүр нь тэмплэйтийн илэрцэд хувисагчаар оролцох үйлдэл" + +msgid "Models" +msgstr "Моделууд" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Model-ууд бол системтэй холбоотой талбарууд бүхий объектуудын тайлбар, Model " +"бүр тэмплэйт хувьсагч болох боломтой талбаруудтай " + +msgid "Views" +msgstr "View-үүд" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Нийтэд ил хуудас бүр view-ээс бүтнэ. View нь ямар объектийг, тухайн template-" +"д ашиглахыг тодорхойлно." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Админы ажиллагаанд хурдан нэвтрэхын тулд таны вэб хөтөчид зориулагдсан " +"хэрэгсэл." + +msgid "Please install docutils" +msgstr "docutils ийг суулгана уу" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" +"Админ хэсгийн баримтжуулалтын ажиллуулхад Python ийн docutils санг суулгах шаардлагатай." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Админуудаас docutils санг суулгасан эсхийг асууна " +"уу." + +#, python-format +msgid "Model: %(name)s" +msgstr "Модель: %(name)s" + +msgid "Fields" +msgstr "Талбарууд" + +msgid "Field" +msgstr "Талбар" + +msgid "Type" +msgstr "Төрөл" + +msgid "Description" +msgstr "Товчхон" + +msgid "Methods with arguments" +msgstr "Аргументтэй функцүүд" + +msgid "Method" +msgstr "Функц" + +msgid "Arguments" +msgstr "Аргументүүд" + +msgid "Back to Model documentation" +msgstr "Моделийн баримтруу буцах" + +msgid "Model documentation" +msgstr "Моделийн баримт" + +msgid "Model groups" +msgstr "Модел бүлэгүүд" + +msgid "Templates" +msgstr "Загварууд" + +#, python-format +msgid "Template: %(name)s" +msgstr "Загвар: %(name)s" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "Загвар: \"%(name)s\"" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "\"%(name)s\" тэмплэйтын зам хайх" + +msgid "(does not exist)" +msgstr "(Оршдоггүй)" + +msgid "Back to Documentation" +msgstr "Баримтруу буцах" + +msgid "Template filters" +msgstr "Загвар шүүлт" + +msgid "Template filter documentation" +msgstr "Загвар шүүлтийн баримт" + +msgid "Built-in filters" +msgstr "Өгөгдмөл шүүлтүүрүүд" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Энэ шошгыг ашиглахын тулд үүнийг %(code)s шошгоны өмнө загвар " +"дотроо бич" + +msgid "Template tags" +msgstr "Загвар шошго" + +msgid "Template tag documentation" +msgstr "Template tag баримтжуулалт" + +msgid "Built-in tags" +msgstr "Өгөгдмөл шошгууд" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Энэ шошгыг ашиглахын тулд үүнийг %(code)s шошгоны өмнө загвар " +"дотроо бич" + +#, python-format +msgid "View: %(name)s" +msgstr "Харагдац: %(name)s" + +msgid "Context:" +msgstr "Уул үг: " + +msgid "Templates:" +msgstr "Загварууд:" + +msgid "Back to View documentation" +msgstr "Харагдац баримтруу буцах" + +msgid "View documentation" +msgstr "Харагдац баримт" + +msgid "Jump to namespace" +msgstr "Хоосон зай үүсгэх" + +msgid "Empty namespace" +msgstr "Хоосон нэрний зай" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "%(name)s нэрсээр харах" + +msgid "Views by empty namespace" +msgstr "Хоосон зайгаар харах" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"Функц харах: %(full_name)s. Нэр: %(url_name)s.\n" + +msgid "tag:" +msgstr "шошго:" + +msgid "filter:" +msgstr "шүүлтүүр:" + +msgid "view:" +msgstr "харах:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "%(app_label)r аппликэйшн олдсонгүй" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr " %(app_label)r програмд %(model_name)r модел олдсонгүй" + +msgid "model:" +msgstr "модел:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "холбогдох `%(app_label)s.%(data_type)s`объект" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "холбогдох `%(app_label)s.%(object_name)s` объектууд" + +#, python-format +msgid "all %s" +msgstr "бүх %s" + +#, python-format +msgid "number of %s" +msgstr "%s-ийн тоо" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s нь url хэлбэрийн объект биш байна" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/mr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/mr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a3218b0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/mr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/mr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/mr/LC_MESSAGES/django.po new file mode 100644 index 0000000..6e87657 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/mr/LC_MESSAGES/django.po @@ -0,0 +1,275 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2015-01-18 08:34+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Marathi (http://www.transifex.com/projects/p/django/language/" +"mr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mr\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "" + +msgid "Documentation" +msgstr "" + +msgid "Bookmarklets" +msgstr "" + +msgid "Documentation bookmarklets" +msgstr "" + +msgid "" +"\n" +"

    To install bookmarklets, drag the link to your bookmarks\n" +"toolbar, or right-click the link and add it to your bookmarks. Now you can\n" +"select the bookmarklet from any page in the site. Note that some of these\n" +"bookmarklets require you to be viewing the site from a computer designated\n" +"as \"internal\" (talk to your system administrator if you aren't sure if\n" +"your computer is \"internal\").

    \n" +msgstr "" + +msgid "Documentation for this page" +msgstr "" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" + +msgid "Show object ID" +msgstr "" + +msgid "" +"Shows the content-type and unique ID for pages that represent a single " +"object." +msgstr "" + +msgid "Edit this object (current window)" +msgstr "" + +msgid "Jumps to the admin page for pages that represent a single object." +msgstr "" + +msgid "Edit this object (new window)" +msgstr "" + +msgid "As above, but opens the admin page in a new window." +msgstr "" + +msgid "Tags" +msgstr "" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Back to Model Documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to Views Documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "" + +msgid "tag:" +msgstr "" + +msgid "filter:" +msgstr "" + +msgid "view:" +msgstr "" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "" + +msgid "model:" +msgstr "" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "" + +#, python-format +msgid "all %s" +msgstr "" + +#, python-format +msgid "number of %s" +msgstr "" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ms/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ms/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0db0e9c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ms/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ms/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ms/LC_MESSAGES/django.po new file mode 100644 index 0000000..13fd43e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ms/LC_MESSAGES/django.po @@ -0,0 +1,283 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jafry Hisham, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-11-16 14:09+0000\n" +"Last-Translator: Jafry Hisham\n" +"Language-Team: Malay (http://www.transifex.com/django/django/language/ms/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ms\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Administrative Documentation" +msgstr "Dokumentasi Pentadbiran" + +msgid "Home" +msgstr "Utama" + +msgid "Documentation" +msgstr "Dokumentasi" + +msgid "Bookmarklets" +msgstr "Penanda" + +msgid "Documentation bookmarklets" +msgstr "Dokumentasi penanda" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Untuk memasang penanda, heret pautan ke palang-alat penanda-buku, atau klik-" +"kanan pada pautan dan tambahkan ke penanda-buku anda. Kini anda boleh " +"memilih penanda itu daripada mana-mana ruangan di laman." + +msgid "Documentation for this page" +msgstr "Dokumentasi untuk ruangan ini" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Membawa anda daripada mana-mana ruangan kepada dokumentasi bagi pemandangan " +"yang menjana ruang itu." + +msgid "Tags" +msgstr "Tag-tag" + +msgid "List of all the template tags and their functions." +msgstr "Senarai kesemua tag templat dan fungsiannya." + +msgid "Filters" +msgstr "Tapisan" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Tapisan adalah tindakan yang boleh digunakan pada pembolehubah didalam " +"templat untuk mengubah outputnya." + +msgid "Models" +msgstr "Model-model" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Model-model adalah penerangan bagi semua objek-objek didalam sistem dan " +"medan-medan yang berkaitan. Setiap model mempunyai senarai medan-medan yang " +"boleh diakses sebagai tempat pembolehubah." + +msgid "Views" +msgstr "Pemandangan" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Setiap ruangan pada laman awan dihasilkan daripada pemandangan. Pemandangan " +"menakrifkan templat mana yang diguna-pakai untuk menghasilkan ruangan itu " +"dan objek mana yang boleh digunakan bersama templat itu." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Alat-alat untuk pelayar anda untuk mengakses fungsian pentadbiran secara " +"pantas." + +msgid "Please install docutils" +msgstr "Sila pasang docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Sistem dokumentasi pentadbiran memerlukan perpustakaan docutils Python." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Sila mohon pada pentadbir-pentadbir anda untuk memasang docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Model: %(name)s" + +msgid "Fields" +msgstr "Medan-medan" + +msgid "Field" +msgstr "Medan" + +msgid "Type" +msgstr "Jenis" + +msgid "Description" +msgstr "Penerangan" + +msgid "Methods with arguments" +msgstr "Kaedah dengan argumen" + +msgid "Method" +msgstr "Kaedah" + +msgid "Arguments" +msgstr "Argumen" + +msgid "Back to Model documentation" +msgstr "Patah balik ke dokumentasi Model" + +msgid "Model documentation" +msgstr "Dokumentasi Model" + +msgid "Model groups" +msgstr "Kumpulan-kumpulan Model" + +msgid "Templates" +msgstr "Templat-templat" + +#, python-format +msgid "Template: %(name)s" +msgstr "Templat: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Templat: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Cari laluan untuk templat %(name)s:" + +msgid "(does not exist)" +msgstr "(tidak wujud)" + +msgid "Back to Documentation" +msgstr "Patah balik ke Dokumentasi" + +msgid "Template filters" +msgstr "Penapisan templat" + +msgid "Template filter documentation" +msgstr "Dokumentasi penapisan templat" + +msgid "Built-in filters" +msgstr "Penapisan terbina-dalam" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Untuk menggunakan tapisan-tapisan ini, letakkan %(code)s " +"didalam templat anda sebelum menggunakan tapisan itu." + +msgid "Template tags" +msgstr "Tag-tag templat" + +msgid "Template tag documentation" +msgstr "Dokumentasi tag templat" + +msgid "Built-in tags" +msgstr "Tag-tag terbina-dalam" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Untuk menggunakan tag-tag ini, letakkan %(code)s didalam " +"templat anda sebelum menggunakan tag itu." + +#, python-format +msgid "View: %(name)s" +msgstr "Pemandagan: %(name)s" + +msgid "Context:" +msgstr "Konteks:" + +msgid "Templates:" +msgstr "Templat-templat:" + +msgid "Back to View documentation" +msgstr "Patah balik ke Dokumentasi Pemandangan" + +msgid "View documentation" +msgstr "Dokumentasi Pemandangan" + +msgid "Jump to namespace" +msgstr "Lompat ke ruangnama" + +msgid "Empty namespace" +msgstr "Ruangnama koson" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Pemandangan berdasakran ruangnama %(name)s" + +msgid "Views by empty namespace" +msgstr "Pemandangan berdasarkan ruangnama kosong" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"Fungsi Pemandangan: %(full_name)s. Name: %(url_name)s.\n" + +msgid "tag:" +msgstr "tag:" + +msgid "filter:" +msgstr "tapis:" + +msgid "view:" +msgstr "lihat:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "App %(app_label)r tidak dijumpai" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Model %(model_name)r tidak dijumpai didalam app %(app_label)r" + +msgid "model:" +msgstr "model:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "objek `%(app_label)s.%(data_type)s` berkaitan" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "objek-objek `%(app_label)s.%(object_name)s` berkaitan" + +#, python-format +msgid "all %s" +msgstr "semua %s" + +#, python-format +msgid "number of %s" +msgstr "bilangan %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s nampaknya bukan objek urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/my/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/my/LC_MESSAGES/django.mo new file mode 100644 index 0000000..fa8a6a5 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/my/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/my/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/my/LC_MESSAGES/django.po new file mode 100644 index 0000000..450fa41 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/my/LC_MESSAGES/django.po @@ -0,0 +1,258 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Yhal Htet Aung , 2013,2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Burmese (http://www.transifex.com/django/django/language/" +"my/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: my\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "ပင်မ" + +msgid "Documentation" +msgstr "အချက်အလက်" + +msgid "Bookmarklets" +msgstr "" + +msgid "Documentation bookmarklets" +msgstr "" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" + +msgid "Tags" +msgstr "အမည်များ" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "စီစစ်မှုများ" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "မော်ဒယ်များ" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "ကြည့်ရှုခြင်းများ" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "ပံုစံပြားများ" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "အမည်:" + +msgid "filter:" +msgstr "စီစစ်မှု:" + +msgid "view:" +msgstr "ကြည့်ရှု:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "%(app_label)r အပ်ပရိုဂရမ်တွင် %(model_name)r မော်ဒယ်ရှာမတွေ့" + +msgid "model:" +msgstr "မော်ဒယ်:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "ဆက်နွယ်သော `%(app_label)s.%(data_type)s` အရာဝတ္ထု" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "ဆက်နွယ်သော `%(app_label)s.%(object_name)s` အရာဝတ္ထုများ" + +#, python-format +msgid "all %s" +msgstr "%s အားလံုး" + +#, python-format +msgid "number of %s" +msgstr "%s အရေအတွက်" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/nb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/nb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e6595dc Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/nb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/nb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/nb/LC_MESSAGES/django.po new file mode 100644 index 0000000..b7959c6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/nb/LC_MESSAGES/django.po @@ -0,0 +1,284 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Jon, 2015-2016 +# Jon, 2014 +# Jon, 2020-2021 +# Jon, 2013 +# Jon, 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-03-18 14:16+0000\n" +"Last-Translator: Jon\n" +"Language-Team: Norwegian Bokmål (http://www.transifex.com/django/django/" +"language/nb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Administrasjons-dokumentasjon" + +msgid "Home" +msgstr "Hjem" + +msgid "Documentation" +msgstr "Dokumentasjon" + +msgid "Bookmarklets" +msgstr "Bokmerker" + +msgid "Documentation bookmarklets" +msgstr "Dokumentasjonsbokmerker" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"For å installere bokmerker, dra linken til verktøylinjen for bokmerker, " +"eller høyreklikk og legg til i bokmerker. Nå kan du du velge bokmerket fra " +"hvilken som helst side på nettstedet." + +msgid "Documentation for this page" +msgstr "Dokumentasjon for denne siden" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Hopp fra hvilken som helst side til dokumentasjonen for visningsfunksjonen " +"som genererte den siden." + +msgid "Tags" +msgstr "Tags" + +msgid "List of all the template tags and their functions." +msgstr "Liste over alle mal-taggene og deres funksjoner." + +msgid "Filters" +msgstr "Filter" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Filtre er handlinger som kan brukes på variabler i en mal for å endre output." + +msgid "Models" +msgstr "Modeller" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Modeller er beskrivelser av alle objektene i systemet og tilhørende felter. " +"Hver modell har en liste over felt som kan brukes som mal-variabler" + +msgid "Views" +msgstr "Views" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Hver side på det offentlige nettstedet er generert av et view. View'et " +"definerer hvilken malen som blir brukt til å generere siden og hvilke " +"objekter som er tilgjengelige for den malen." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Verktøy for nettleseren din for å få rask tilgang til admin-funksjonalitet." + +msgid "Please install docutils" +msgstr "Vennligst installer docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Admin-verktøyets dokumentasjonssystem behøver Pythons docutils-bibliotek ." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Spør dine administratorer om å installere docutils ." + +#, python-format +msgid "Model: %(name)s" +msgstr "Modell: %(name)s" + +msgid "Fields" +msgstr "Felter" + +msgid "Field" +msgstr "Felt" + +msgid "Type" +msgstr "Type" + +msgid "Description" +msgstr "Beskrivelse" + +msgid "Methods with arguments" +msgstr "Metoder med argumenter" + +msgid "Method" +msgstr "Metode" + +msgid "Arguments" +msgstr "Argumenter" + +msgid "Back to Model documentation" +msgstr "Tilbake til modell-dokumentasjon" + +msgid "Model documentation" +msgstr "Modelldokumentasjon" + +msgid "Model groups" +msgstr "Modellgrupper" + +msgid "Templates" +msgstr "Maler" + +#, python-format +msgid "Template: %(name)s" +msgstr "Mal: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Mal: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Søkebane for mal %(name)s:" + +msgid "(does not exist)" +msgstr "(finnes ikke)" + +msgid "Back to Documentation" +msgstr "Tilbake til dokumentasjonen" + +msgid "Template filters" +msgstr "Mal-filtre" + +msgid "Template filter documentation" +msgstr "Mal-filter dokumentasjon" + +msgid "Built-in filters" +msgstr "Innebygde filtre" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"For å bruke disse filtrene, sett inn %(code)s i malen før du " +"bruker filteret." + +msgid "Template tags" +msgstr "Mal-tagger" + +msgid "Template tag documentation" +msgstr "Mal-tag-dokumentasjon" + +msgid "Built-in tags" +msgstr "Innebygde tagger" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"For å bruke disse taggene, sett inn %(code)s i malen før du " +"bruker taggen." + +#, python-format +msgid "View: %(name)s" +msgstr "View: %(name)s" + +msgid "Context:" +msgstr "Kontekst:" + +msgid "Templates:" +msgstr "Maler:" + +msgid "Back to View documentation" +msgstr "Tilbake til view-dokumentasjonen" + +msgid "View documentation" +msgstr "View-dokumentasjon" + +msgid "Jump to namespace" +msgstr "Gå til navnerom" + +msgid "Empty namespace" +msgstr "Tomt navnerom" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Views etter navnerom %(name)s" + +msgid "Views by empty namespace" +msgstr "Views etter tomt navnerom" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"View-funksjon: %(full_name)s. Navn: %(url_name)s.\n" + +msgid "tag:" +msgstr "tag:" + +msgid "filter:" +msgstr "filter:" + +msgid "view:" +msgstr "view:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Applikasjon %(app_label)r ikke funnet" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Fant ikke modellen %(model_name)r i applikasjonen %(app_label)r" + +msgid "model:" +msgstr "modell:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "det relaterte `%(app_label)s.%(data_type)s`-objektet" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "relaterte `%(app_label)s.%(object_name)s`-objekter" + +#, python-format +msgid "all %s" +msgstr "alle %s" + +#, python-format +msgid "number of %s" +msgstr "antall %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s ser ikke ut til å være et urlpattern-objekt" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ne/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ne/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a72f32d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ne/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ne/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ne/LC_MESSAGES/django.po new file mode 100644 index 0000000..2d6a26d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ne/LC_MESSAGES/django.po @@ -0,0 +1,261 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Paras Nath Chaudhary , 2012 +# Sandesh Rana , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-09-20 19:57+0000\n" +"Last-Translator: Sandesh Rana \n" +"Language-Team: Nepali (http://www.transifex.com/django/django/language/ne/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ne\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "प्रशासनिक दस्तावेज" + +msgid "Home" +msgstr "गृह " + +msgid "Documentation" +msgstr "प्रलेखन" + +msgid "Bookmarklets" +msgstr "बुकमार्कलेटहरू" + +msgid "Documentation bookmarklets" +msgstr "कागजातका बुकमार्कलेटहरू" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"बुकमार्कलेटहरू स्थापना गर्न, लिंकलाई तपाईंको बुकमार्क टूलबारमा ड्र्याग गर्नुहोस्, वा लिंकमा " +"दायाँ क्लिक गर्नुहोस् र तपाईंको बुकमार्कमा थप्नुहोस्। अब तपाईं साइटमा कुनै पृष्ठबाट बुकमार्क " +"चयन गर्न सक्नुहुन्छ।" + +msgid "Documentation for this page" +msgstr "यो पृस्ठको लागी प्रलेखन" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" + +msgid "Tags" +msgstr "ट्यागहरु " + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "नमुनाहरु " + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "धृस्यहरु " + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "वर्णन" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "ट्याग:" + +msgid "filter:" +msgstr "" + +msgid "view:" +msgstr "धृस्य :" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "%(model_name)r नमुना %(app_label)r appमा भेटिएन" + +msgid "model:" +msgstr "नमुना :" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "`%(app_label)s.%(data_type)s` संबंधित बस्तु " + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "`%(app_label)s.%(object_name)s` संबंधित बस्तु " + +#, python-format +msgid "all %s" +msgstr "सबै %s" + +#, python-format +msgid "number of %s" +msgstr "%sको संख्या" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/nl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/nl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..89f9123 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/nl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/nl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/nl/LC_MESSAGES/django.po new file mode 100644 index 0000000..84983aa --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/nl/LC_MESSAGES/django.po @@ -0,0 +1,286 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bouke Haarsma , 2013 +# Evelijn Saaltink , 2016 +# Ilja Maas , 2015 +# Jannis Leidel , 2011 +# 6a27f10aef159701c7a5ff07f0fb0a78_05545ed , 2012,2014 +# Tonnes , 2019,2022 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2023-04-24 20:19+0000\n" +"Last-Translator: Tonnes , 2019,2022\n" +"Language-Team: Dutch (http://www.transifex.com/django/django/language/nl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Beheerdocumentatie" + +msgid "Home" +msgstr "Voorpagina" + +msgid "Documentation" +msgstr "Documentatie" + +msgid "Bookmarklets" +msgstr "Bookmarklets" + +msgid "Documentation bookmarklets" +msgstr "Documentatiebookmarklets" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Om bookmarklets te installeren, sleept u de koppeling naar uw " +"bladwijzerwerkbalk, of klikt u met de rechtermuisknop op de koppeling en " +"voegt u deze toe aan uw bladwijzers. De bookmarklet kan nu vanuit elke " +"pagina op de website worden geselecteerd." + +msgid "Documentation for this page" +msgstr "Documentatie voor deze pagina" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Springt vanuit elke pagina naar de documentatie voor de weergave die die " +"pagina genereert." + +msgid "Tags" +msgstr "Tags" + +msgid "List of all the template tags and their functions." +msgstr "Overzicht van alle sjabloontags en hun functies." + +msgid "Filters" +msgstr "Filters" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Filters zijn acties die op variabelen in een sjabloon kunnen worden " +"toegepast om de uitvoer aan te passen." + +msgid "Models" +msgstr "Modellen" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Modellen zijn beschrijvingen van alle objecten in het systeem en hun " +"gekoppelde velden. Elk model heeft een lijst van velden die als " +"sjabloonvariabelen kunnen worden gekoppeld." + +msgid "Views" +msgstr "Weergaven" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Elke pagina op de publieke website wordt gegenereerd door een weergave. De " +"weergave bepaalt welke sjabloon wordt gebruikt om de pagina te genereren en " +"welke objecten in die sjabloon beschikbaar zijn." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "Snelkoppelingen in je browser om makkelijk beheerpagina's te openen." + +msgid "Please install docutils" +msgstr "Docutils is niet geïnstalleerd" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Het beheerdocumentatiesysteem vereist de docutils-" +"bibliotheek van Python." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Vraag de beheerder om docutils te installeren." + +#, python-format +msgid "Model: %(name)s" +msgstr "Model: %(name)s" + +msgid "Fields" +msgstr "Velden" + +msgid "Field" +msgstr "Veld" + +msgid "Type" +msgstr "Type" + +msgid "Description" +msgstr "Beschrijving" + +msgid "Methods with arguments" +msgstr "Methode met argumenten" + +msgid "Method" +msgstr "Methode" + +msgid "Arguments" +msgstr "Argumenten" + +msgid "Back to Model documentation" +msgstr "Terug naar Modeldocumentatie" + +msgid "Model documentation" +msgstr "Modeldocumentatie" + +msgid "Model groups" +msgstr "Modules" + +msgid "Templates" +msgstr "Sjablonen" + +#, python-format +msgid "Template: %(name)s" +msgstr "Sjabloon: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Sjabloon: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Zoekpad voor sjabloon %(name)s:" + +msgid "(does not exist)" +msgstr "(bestaat niet)" + +msgid "Back to Documentation" +msgstr "Terug naar Documentatie" + +msgid "Template filters" +msgstr "Sjabloonfilters" + +msgid "Template filter documentation" +msgstr "Sjabloontagdocumentatie " + +msgid "Built-in filters" +msgstr "Standaardfilters" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Om deze filters te gebruiken, plaatst u %(code)s in uw sjabloon " +"voordat u het filter gebruikt." + +msgid "Template tags" +msgstr "Sjabloontags" + +msgid "Template tag documentation" +msgstr "Sjabloontagdocumentatie" + +msgid "Built-in tags" +msgstr "Standaardtags" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Om deze tags te gebruiken, plaatst u %(code)s in uw sjabloon " +"voordat u de tag gebruikt." + +#, python-format +msgid "View: %(name)s" +msgstr "Weergave: %(name)s" + +msgid "Context:" +msgstr "Contextvariabelen:" + +msgid "Templates:" +msgstr "Sjablonen:" + +msgid "Back to View documentation" +msgstr "Terug naar Weergavedocumentatie" + +msgid "View documentation" +msgstr "Weergavedocumentatie" + +msgid "Jump to namespace" +msgstr "Naar namespace springen" + +msgid "Empty namespace" +msgstr "Lege namespace" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Weergaven per namespace %(name)s" + +msgid "Views by empty namespace" +msgstr "Weergaven per lege namespace" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +" Weergavefunctie: %(full_name)s. Naam: %(url_name)s.\n" + +msgid "tag:" +msgstr "tag:" + +msgid "filter:" +msgstr "filter:" + +msgid "view:" +msgstr "weergave:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "App %(app_label)r niet gevonden" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Model %(model_name)r niet gevonden in module %(app_label)r" + +msgid "model:" +msgstr "model:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "het gerelateerde `%(app_label)s.%(data_type)s` object" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "gerelateerde `%(app_label)s.%(object_name)s` objecten" + +#, python-format +msgid "all %s" +msgstr "alle %s" + +#, python-format +msgid "number of %s" +msgstr "aantal %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s lijkt geen urlpattern-object te zijn" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/nn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/nn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..72add0c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/nn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/nn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/nn/LC_MESSAGES/django.po new file mode 100644 index 0000000..673f796 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/nn/LC_MESSAGES/django.po @@ -0,0 +1,282 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Sivert Olstad, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-11-16 23:22+0000\n" +"Last-Translator: Sivert Olstad\n" +"Language-Team: Norwegian Nynorsk (http://www.transifex.com/django/django/" +"language/nn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Administrasjons-dokumentasjon" + +msgid "Home" +msgstr "Heim" + +msgid "Documentation" +msgstr "Dokumentasjon" + +msgid "Bookmarklets" +msgstr "Bokmerke" + +msgid "Documentation bookmarklets" +msgstr "Dokumentasjonsbokmerke" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"For å installere bokmerke, dra lenkja til verktøylinja for bokmerke, eller " +"høgreklikk og legg til i dine bokmerke. No kan du velje bokmerket frå kva " +"for helst side på nettstaden." + +msgid "Documentation for this page" +msgstr "Dokumentasjon for denne sida" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Hopp frå kva som helst side til dokumentasjonen for visingsfunksjonen som " +"genererte sida." + +msgid "Tags" +msgstr "Taggar" + +msgid "List of all the template tags and their functions." +msgstr "Liste over alle mal-taggar og funksjonane deira." + +msgid "Filters" +msgstr "Filter" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Filter er handlingar som kan bli brukt på variablar i ein mal for å endre " +"utdata." + +msgid "Models" +msgstr "Modellar" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Modellar er beskrivingar av alle objekta i eit system og tilhøyrande felt. " +"Kvar modell har ein liste over felt som kan bli brukt som mal-variablar." + +msgid "Views" +msgstr "Views" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Kvar side på den offentlege nettstaden er generert av ein view. Viewen " +"definerer kva for ein mal som blir brukt til å generere sida og kva for " +"nokre objekt som er tilgjengelege for den malen." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Verktøy for nettlesaren din for å få rask tilgang til admin-funksjonalitet" + +msgid "Please install docutils" +msgstr "Installer docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Admin-verktøyet sitt dokumentasjonssystem behøver Python sitt docutils-bibliotek." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Spør administratorane dine om å installere docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Modell: %(name)s" + +msgid "Fields" +msgstr "Felt" + +msgid "Field" +msgstr "Felt" + +msgid "Type" +msgstr "Type" + +msgid "Description" +msgstr "Beskriving" + +msgid "Methods with arguments" +msgstr "Metodar med argument" + +msgid "Method" +msgstr "Metode" + +msgid "Arguments" +msgstr "Argument" + +msgid "Back to Model documentation" +msgstr "Attende til Modelldokumentasjon" + +msgid "Model documentation" +msgstr "Modelldokumentasjon" + +msgid "Model groups" +msgstr "Modellgrupper" + +msgid "Templates" +msgstr "Malar" + +#, python-format +msgid "Template: %(name)s" +msgstr "Mal: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Mal: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Søkjebane for mal %(name)s:" + +msgid "(does not exist)" +msgstr "(finnast ikkje)" + +msgid "Back to Documentation" +msgstr "Attende til Dokumentasjon" + +msgid "Template filters" +msgstr "Malfilter" + +msgid "Template filter documentation" +msgstr "Malfilterdokumentasjon" + +msgid "Built-in filters" +msgstr "Innbygde filter" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"For å bruke desse filtera, set inn %(code)s i malen før du " +"brukar filteret." + +msgid "Template tags" +msgstr "Maltaggar" + +msgid "Template tag documentation" +msgstr "Maltagdokumentasjon" + +msgid "Built-in tags" +msgstr "Innebygde taggar" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"For å bruke desse taggane, set inn %(code)s i malen før du " +"brukar taggen." + +#, python-format +msgid "View: %(name)s" +msgstr "View: %(name)s" + +msgid "Context:" +msgstr "Kontekst:" + +msgid "Templates:" +msgstr "Malar:" + +msgid "Back to View documentation" +msgstr "Attende til Viewdokumentasjon" + +msgid "View documentation" +msgstr "Viewdokumentasjon" + +msgid "Jump to namespace" +msgstr "Gå til namnerom" + +msgid "Empty namespace" +msgstr "Tomt namnerom" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Views etter namnerom %(name)s" + +msgid "Views by empty namespace" +msgstr "Views etter tomt namnerom" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +" Viewfunksjon: %(full_name)s. Namn: %(url_name)s.\n" + +msgid "tag:" +msgstr "tag:" + +msgid "filter:" +msgstr "filter:" + +msgid "view:" +msgstr "view:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Applikasjon %(app_label)r ikkje funne" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "" +"Kunne ikkje finne modellen %(model_name)r i applikasjonen %(app_label)r" + +msgid "model:" +msgstr "modell:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "det relaterte `%(app_label)s.%(data_type)s`-objektet" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "relaterte `%(app_label)s.%(object_name)s`-objekt" + +#, python-format +msgid "all %s" +msgstr "alle %s" + +#, python-format +msgid "number of %s" +msgstr "tal på %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s ser ikkje ut til å vere eit urlpattern-objekt" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/os/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/os/LC_MESSAGES/django.mo new file mode 100644 index 0000000..dc8f9df Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/os/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/os/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/os/LC_MESSAGES/django.po new file mode 100644 index 0000000..d7c9eae --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/os/LC_MESSAGES/django.po @@ -0,0 +1,258 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Soslan Khubulov , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Ossetic (http://www.transifex.com/django/django/language/" +"os/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: os\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "Хӕдзар" + +msgid "Documentation" +msgstr "Документаци" + +msgid "Bookmarklets" +msgstr "Букмарклеттӕ" + +msgid "Documentation bookmarklets" +msgstr "Документацийы букмарклеттӕ" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "Ацы фарсы документаци" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "Цыфӕнды фарсӕй дӕ уыцы фарс цы хуыз фӕлдисы, уый документацимӕ ӕрвиты." + +msgid "Tags" +msgstr "Тӕгтӕ" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "Фӕрсудзӕнтӕ" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "Моделтӕ" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "Хуызтӕ" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "Хуызӕгтӕ" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "тӕг:" + +msgid "filter:" +msgstr "фӕрсудзӕн:" + +msgid "view:" +msgstr "хуыз:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Модел %(model_name)r ӕфтуан %(app_label)r-ы мидӕг нӕ разынд" + +msgid "model:" +msgstr "модел" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "хӕстӕг `%(app_label)s.%(data_type)s` объект" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "хӕстӕг `%(app_label)s.%(object_name)s` объекттӕ" + +#, python-format +msgid "all %s" +msgstr "%s иууылдӕр" + +#, python-format +msgid "number of %s" +msgstr "%s нымӕц" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s url-ы хуызӕгы объект нӕу" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/pa/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/pa/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8be0a2c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/pa/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/pa/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/pa/LC_MESSAGES/django.po new file mode 100644 index 0000000..775238c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/pa/LC_MESSAGES/django.po @@ -0,0 +1,258 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Panjabi (Punjabi) (http://www.transifex.com/django/django/" +"language/pa/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pa\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "ਘਰ" + +msgid "Documentation" +msgstr "ਡੌਕੂਮੈਂਟੇਸ਼ਨ" + +msgid "Bookmarklets" +msgstr "ਬੁੱਕਮਾਰਕਲਿਟ" + +msgid "Documentation bookmarklets" +msgstr "ਡੌਕੂਮੈਟੇਸ਼ਨ ਬੁੱਕਮਾਰਕਲਿਟ" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "ਇਹ ਸਫ਼ੇ ਲਈ ਡੌਕੂਮੈਂਟੇਸ਼ਨ" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" + +msgid "Tags" +msgstr "" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "ਟੈਗ:" + +msgid "filter:" +msgstr "ਫਿਲਟਰ:" + +msgid "view:" +msgstr "ਵੇਖੋ:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "" + +msgid "model:" +msgstr "ਮਾਡਲ:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "ਸਬੰਧਿਤ `%(app_label)s.%(object_name)s` ਆਬਜੈਕਟ" + +#, python-format +msgid "all %s" +msgstr "ਸਭ %s" + +#, python-format +msgid "number of %s" +msgstr "%s ਦੀ ਗਿਣਤੀ" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/pl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/pl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..6908181 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/pl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/pl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/pl/LC_MESSAGES/django.po new file mode 100644 index 0000000..9a76f27 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/pl/LC_MESSAGES/django.po @@ -0,0 +1,294 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Adam Stachowicz , 2015 +# angularcircle, 2012 +# Jannis Leidel , 2011 +# Janusz Harkot , 2015 +# m_aciek , 2016,2019 +# m_aciek , 2014 +# Mariusz Felisiak , 2021 +# c10516f0462e552b4c3672569f0745a7_cc5cca2 <841826256cd8f47d0e443806a8e56601_19204>, 2014 +# Mattia Procopio , 2014 +# Tomasz Kajtoch , 2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-04-01 09:45+0000\n" +"Last-Translator: Mariusz Felisiak \n" +"Language-Team: Polish (http://www.transifex.com/django/django/language/pl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pl\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n" +"%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n" +"%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" + +msgid "Administrative Documentation" +msgstr "Dokumentacja administracyjna" + +msgid "Home" +msgstr "Strona główna" + +msgid "Documentation" +msgstr "Dokumentacja" + +msgid "Bookmarklets" +msgstr "Zakładki" + +msgid "Documentation bookmarklets" +msgstr "Zakładki Dokumentacji" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Aby zainstalować skryptozakładkę, przeciągnij jej link do paska zakładek lub " +"kliknij prawym przyciskiem na link i wybierz opcję zapisania do zakładek. Od " +"tego momentu możesz użyć tak zapisanej zakładki na dowolnej podstronie tego " +"serwisu." + +msgid "Documentation for this page" +msgstr "Dokumentacja dla tej strony" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Przekierowuje z dowolnej strony do dokumentacji dla widoku, który ją " +"generuje." + +msgid "Tags" +msgstr "Tagi" + +msgid "List of all the template tags and their functions." +msgstr "Lista wszystkich templatetagów i ich funkcji." + +msgid "Filters" +msgstr "Filtry" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Filtry to akcje, które mogą być stosowane w odniesieniu do zmiennych w " +"szablonie, aby zmienić wyjście." + +msgid "Models" +msgstr "Modele" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Modele to opisy wszystkich obiektów w systemie i związanych z nimi pól. " +"Każdy model ma listę pól, które mogą być dostępne jako zmienne szablonu" + +msgid "Views" +msgstr "Widoki" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Każda strona dostępna publicznie jest generowana przez widok. Widok określa, " +"który szablon jest używany do wygenerowania strony i które obiekty są " +"dostępne dla tego szablonu." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Narzędzia do twojej przeglądarki, aby uzyskać szybki dostęp do " +"funkcjonalności admina." + +msgid "Please install docutils" +msgstr "Zainstaluj docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"System dokumentacji admina wymaga Pythonowej biblioteki docutils." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Poproś swoich administratorów, aby zainstalowali docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Model: %(name)s" + +msgid "Fields" +msgstr "Pola" + +msgid "Field" +msgstr "Pole" + +msgid "Type" +msgstr "Typ" + +msgid "Description" +msgstr "Opis" + +msgid "Methods with arguments" +msgstr "Metody z argumentami" + +msgid "Method" +msgstr "Metoda" + +msgid "Arguments" +msgstr "Argumenty" + +msgid "Back to Model documentation" +msgstr "Powrót do dokumentacji modelu" + +msgid "Model documentation" +msgstr "Dokumentacja modelu" + +msgid "Model groups" +msgstr "Grupy modelu" + +msgid "Templates" +msgstr "Szablony" + +#, python-format +msgid "Template: %(name)s" +msgstr "Szablon: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Szablon: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Ścieżki wyszukiwania dla szablonu %(name)s:" + +msgid "(does not exist)" +msgstr "(nie istnieje)" + +msgid "Back to Documentation" +msgstr "Powrót do dokumentacji" + +msgid "Template filters" +msgstr "Filtry szablonu" + +msgid "Template filter documentation" +msgstr "Dokumentacja filtrów szablonu" + +msgid "Built-in filters" +msgstr "Wbudowane filtry" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Aby użyć tych filtrów, umieść %(code)s w swoim szablonie przed " +"użyciem filtra." + +msgid "Template tags" +msgstr "Tagi szablonu" + +msgid "Template tag documentation" +msgstr "Dokumentacja tagów szablonu" + +msgid "Built-in tags" +msgstr "Wbudowane tagi" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Aby użyć tych tagów, umieść %(code)s w swoim szablonie przed " +"użyciem taga." + +#, python-format +msgid "View: %(name)s" +msgstr "Widok: %(name)s" + +msgid "Context:" +msgstr "Kontekst:" + +msgid "Templates:" +msgstr "Szablony:" + +msgid "Back to View documentation" +msgstr "Powrót do dokumentacji widoku" + +msgid "View documentation" +msgstr "Zobacz dokumentację" + +msgid "Jump to namespace" +msgstr "Przejdź do przestrzeni nazw" + +msgid "Empty namespace" +msgstr "Pusta przestrzeń nazw" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Widoki według przestrzeni nazw %(name)s" + +msgid "Views by empty namespace" +msgstr "Widoki po pustej przestrzeni nazw" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"Funkcja widoku: %(full_name)s. Nazwa: %(url_name)s.\n" + +msgid "tag:" +msgstr "tag:" + +msgid "filter:" +msgstr "filtr:" + +msgid "view:" +msgstr "widok:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Nie znaleziono aplikacji %(app_label)r" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Model %(model_name)r nie został znaleziony w aplikacji %(app_label)r" + +msgid "model:" +msgstr "model:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "powiązany obiekt `%(app_label)s.%(data_type)s`" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "powiązane obiekty `%(app_label)s.%(object_name)s`" + +#, python-format +msgid "all %s" +msgstr "wszystkie %s" + +#, python-format +msgid "number of %s" +msgstr "liczba %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s nie jest obiektem urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/pt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/pt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..da299eb Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/pt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/pt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/pt/LC_MESSAGES/django.po new file mode 100644 index 0000000..7c0ce19 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/pt/LC_MESSAGES/django.po @@ -0,0 +1,286 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bruno Miguel Custódio , 2012 +# Jannis Leidel , 2011 +# Nuno Mariz , 2011-2013,2015,2017 +# Raúl Pedro Fernandes Santos, 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Portuguese (http://www.transifex.com/django/django/language/" +"pt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Documentação Administrativa" + +msgid "Home" +msgstr "Início" + +msgid "Documentation" +msgstr "Documentação" + +msgid "Bookmarklets" +msgstr "Bookmarklets" + +msgid "Documentation bookmarklets" +msgstr "Documentação dos bookmarklets" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Para instalar bookmarklets, arraste o link da barra dos bookmarks, ou " +"pressione do lado direito no link e adicione aos bookmarks.\n" +"Agora poderá selecionar o bookmarklet de qualquer página do site." + +msgid "Documentation for this page" +msgstr "Documentação desta página" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Vai de qualquer página para a documentação da view que gera essa página." + +msgid "Tags" +msgstr "Tags" + +msgid "List of all the template tags and their functions." +msgstr "Lista de todas as template tags e suas funções." + +msgid "Filters" +msgstr "Filtros" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Os filtros são as acções que podem ser aplicadas às variáveis ​​de uma " +"template para alterar o output." + +msgid "Models" +msgstr "Models" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Models são descrições de todos os objetos no sistema e seus campos " +"associados. Cada model tem uma lista de campos que podem ser acedidos como " +"variáveis ​​de template" + +msgid "Views" +msgstr "Views" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Cada página no site público é gerada por uma view. A view define qual " +"template será usado para gerar a página e quais objetos estarão disponíveis " +"para esse template." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Ferramentas para o seu navegador para aceder rapidamente a funcionalidade de " +"administração." + +msgid "Please install docutils" +msgstr "Por favor, instale o docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" +"A documentação do sistema de admin requer a biblioteca docutils do Python." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Por favor, peça aos seu administradores para instalar o docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Model: %(name)s" + +msgid "Fields" +msgstr "Campos" + +msgid "Field" +msgstr "Campo" + +msgid "Type" +msgstr "Tipo" + +msgid "Description" +msgstr "Descrição" + +msgid "Methods with arguments" +msgstr "Métodos com argumentos" + +msgid "Method" +msgstr "Métodos" + +msgid "Arguments" +msgstr "Argumentos" + +msgid "Back to Model documentation" +msgstr "Voltar para a documentação dos Models" + +msgid "Model documentation" +msgstr "Documentação dos Models" + +msgid "Model groups" +msgstr "Grupos de Models" + +msgid "Templates" +msgstr "Templates" + +#, python-format +msgid "Template: %(name)s" +msgstr "Template: %(name)s" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "Template: \"%(name)s\"" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "Caminho de pesquisa para o template \"%(name)s\":" + +msgid "(does not exist)" +msgstr "(Não existe)" + +msgid "Back to Documentation" +msgstr "Voltar para a Documentação" + +msgid "Template filters" +msgstr "Filtros de template" + +msgid "Template filter documentation" +msgstr "Documentação de filtros de template" + +msgid "Built-in filters" +msgstr "Filtros built-in" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Para utilizar estes filtros, coloque %(code)s na sua template " +"antes de utilizar o filtro." + +msgid "Template tags" +msgstr "Tags de template" + +msgid "Template tag documentation" +msgstr "Documentação de tags de template" + +msgid "Built-in tags" +msgstr "Tags built-in" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Para utilizar estas tags, coloque %(code)s na sua template " +"antes de usar a tag." + +#, python-format +msgid "View: %(name)s" +msgstr "View: %(name)s" + +msgid "Context:" +msgstr "Contexto:" + +msgid "Templates:" +msgstr "Templates:" + +msgid "Back to View documentation" +msgstr "Voltar para a documentação das Views" + +msgid "View documentation" +msgstr "Ver documentação" + +msgid "Jump to namespace" +msgstr "Saltar para namespace" + +msgid "Empty namespace" +msgstr "Namespace vazio" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Views por namespace %(name)s" + +msgid "Views by empty namespace" +msgstr "Views por namespace vazio" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +" Função de view: %(full_name)s. Nome: %(url_name)s.\n" + +msgid "tag:" +msgstr "tag:" + +msgid "filter:" +msgstr "filtro:" + +msgid "view:" +msgstr "view:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "A aplicação %(app_label)r não foi encontrada" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "O Model %(model_name)r não foi encontrado na aplicação %(app_label)r" + +msgid "model:" +msgstr "model:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "o objeto `%(app_label)s.%(data_type)s` relacionado" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "os objetos `%(app_label)s.%(object_name)s` relacionados" + +#, python-format +msgid "all %s" +msgstr "todos %s" + +#, python-format +msgid "number of %s" +msgstr "número de %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s não parece ser um objeto urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/pt_BR/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/pt_BR/LC_MESSAGES/django.mo new file mode 100644 index 0000000..28ee8c6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/pt_BR/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/pt_BR/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/pt_BR/LC_MESSAGES/django.po new file mode 100644 index 0000000..a215108 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/pt_BR/LC_MESSAGES/django.po @@ -0,0 +1,292 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Allisson Azevedo , 2014 +# andrewsmedina , 2016 +# Carlos C. Leite , 2016 +# Filipe Cifali Stangler , 2016 +# Eduardo Cereto Carvalho, 2016 +# Elyézer Rezende , 2013 +# semente, 2012 +# Jannis Leidel , 2011 +# Lucas Infante , 2015 +# Rafael Fontenelle , 2021 +# Vinícius Muniz de Melo , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-01-17 05:53+0000\n" +"Last-Translator: Rafael Fontenelle \n" +"Language-Team: Portuguese (Brazil) (http://www.transifex.com/django/django/" +"language/pt_BR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt_BR\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Administrative Documentation" +msgstr "Documentação Administrativa" + +msgid "Home" +msgstr "Início" + +msgid "Documentation" +msgstr "Documentação" + +msgid "Bookmarklets" +msgstr "Itens de bookmark" + +msgid "Documentation bookmarklets" +msgstr "Documentação de itens de bookmark" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Para instalar bookmarklets, arraste o link para a sua barra de favoritos, ou " +"clique com o botão direito no link e o adicione aos seus favoritos. Agora " +"você pode selecionar o bookmarklet a partir de qualquer página do site." + +msgid "Documentation for this page" +msgstr "Documentação para esta página" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Leva você de qualquer página para a documentação da view que gera tal página." + +msgid "Tags" +msgstr "Tags" + +msgid "List of all the template tags and their functions." +msgstr "Lista de todas as tags de template e suas funções." + +msgid "Filters" +msgstr "Filtros" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Os filtros são ações que podem ser aplicadas às variáveis ​​em um template " +"para alterar a saída." + +msgid "Models" +msgstr "Models" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Modelos são descrições de todos os objetos no sistema e seus campos " +"associados. Cada modelo tem uma lista de campos que podem ser acessados ​​como " +"variáveis ​​no template" + +msgid "Views" +msgstr "Views" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Cada página no site público é gerada por uma view. A view define qual " +"template será usado para gerar a página e quais objetos estarão disponíveis " +"para este template." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Ferramentas para o seu navegador para acessar rapidamente a funcionalidade " +"de administração." + +msgid "Please install docutils" +msgstr "Por favor, instale o docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"O sistema de documentação de administração exige a biblioteca docutils do Python." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Por favor, peça para os seus administradores para instalar o docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Model: %(name)s" + +msgid "Fields" +msgstr "Campos" + +msgid "Field" +msgstr "Campo" + +msgid "Type" +msgstr "Tipo" + +msgid "Description" +msgstr "Descrição" + +msgid "Methods with arguments" +msgstr "Métodos com argumentos" + +msgid "Method" +msgstr "Método" + +msgid "Arguments" +msgstr "Argumentos" + +msgid "Back to Model documentation" +msgstr "Voltar para Documentação do Model" + +msgid "Model documentation" +msgstr "Documentação do model" + +msgid "Model groups" +msgstr "Grupos de models" + +msgid "Templates" +msgstr "Templates" + +#, python-format +msgid "Template: %(name)s" +msgstr "Template: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Template: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Caminho de busca para o template %(name)s:" + +msgid "(does not exist)" +msgstr "(não existe)" + +msgid "Back to Documentation" +msgstr "Voltar para Documentação" + +msgid "Template filters" +msgstr "Filtros do template" + +msgid "Template filter documentation" +msgstr "Documentação do filtro do template" + +msgid "Built-in filters" +msgstr "Filtros built-in" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Para usar esses filtros, coloque %(code)s no seu template antes " +"de usar o filtro." + +msgid "Template tags" +msgstr "Tags de template" + +msgid "Template tag documentation" +msgstr "Documentação da tag de template" + +msgid "Built-in tags" +msgstr "Tags built-in" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Para usar estas tags, coloque o código %(code)s no seu template " +"antes de usar a tag." + +#, python-format +msgid "View: %(name)s" +msgstr "View: %(name)s" + +msgid "Context:" +msgstr "Contexto:" + +msgid "Templates:" +msgstr "Templates:" + +msgid "Back to View documentation" +msgstr "Voltar para a Documentação das Views" + +msgid "View documentation" +msgstr "Ver documentação" + +msgid "Jump to namespace" +msgstr "Ir para namespace" + +msgid "Empty namespace" +msgstr "Namespace vazio" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Views por namespace %(name)s" + +msgid "Views by empty namespace" +msgstr "Views por namespace vazio" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"View função: %(full_name)s. Nome: %(url_name)s.\n" + +msgid "tag:" +msgstr "tag:" + +msgid "filter:" +msgstr "filtro:" + +msgid "view:" +msgstr "view:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "App %(app_label)r não encontrado" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Model %(model_name)r não encontrado na aplicação %(app_label)r" + +msgid "model:" +msgstr "model:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "o objeto `%(app_label)s.%(data_type)s` relacionado" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "objetos `%(app_label)s.%(object_name)s` relacionados" + +#, python-format +msgid "all %s" +msgstr "todos %s" + +#, python-format +msgid "number of %s" +msgstr "número de %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s não aparenta ser um objeto urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ro/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ro/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b7f58b6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ro/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ro/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ro/LC_MESSAGES/django.po new file mode 100644 index 0000000..8fd150e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ro/LC_MESSAGES/django.po @@ -0,0 +1,288 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bogdan Mateescu, 2018-2019 +# Daniel Ursache-Dogariu, 2011 +# Denis Darii , 2014 +# Eugenol Man , 2020 +# Jannis Leidel , 2011 +# Razvan Stefanescu , 2015-2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-07-15 11:18+0000\n" +"Last-Translator: Eugenol Man \n" +"Language-Team: Romanian (http://www.transifex.com/django/django/language/" +"ro/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ro\n" +"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?" +"2:1));\n" + +msgid "Administrative Documentation" +msgstr "Documentație Administrativă" + +msgid "Home" +msgstr "Acasă" + +msgid "Documentation" +msgstr "Documentație" + +msgid "Bookmarklets" +msgstr "Semne de carte" + +msgid "Documentation bookmarklets" +msgstr "Semne de carte pentru documentație" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Pentru a instala semne de carte, trageți link-ul în bara de semne de carte, " +"sau clic dreapta pe link și adăugați la semnele de carte. Acum puteți " +"selecta semnul de carte din orice pagină." + +msgid "Documentation for this page" +msgstr "Documentație pentru pagina aceasta" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Vă trimite de la orice pagină către documentația pentru codul de afișare " +"care generează acea pagină." + +msgid "Tags" +msgstr "Taguri" + +msgid "List of all the template tags and their functions." +msgstr "Lista tuturor tagurilor din șabloane și funcțiile lor." + +msgid "Filters" +msgstr "Filtre" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Filtrele sunt acțiuni care pot fi aplicate variabilelor într-un șablon " +"pentru a altera rezultatul." + +msgid "Models" +msgstr "Modele" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Modelele sunt descrieri ale tuturor obiectelor în sistem și a câmpurilor " +"asociate ale acestora. Fiecare model are o listă de câmpuri care pot fi " +"accesate ca variabile în șabloane." + +msgid "Views" +msgstr "Coduri de afișare" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Fiecare pagină din pagina web este generată de un cod de afișare. Codul de " +"afișare definește ce șablon este utlizat la generarea paginii și ce obiecte " +"sunt disponibile acelui șablon." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Instrumente pentru browser pentru accesarea rapidă a funcționalității de " +"administrare." + +msgid "Please install docutils" +msgstr "Instalați vă rugăm docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" +"Sistemul de documentație administrativă are nevoie de librăria Python docutils." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "Rugați administratorii să instaleze docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Model: %(name)s" + +msgid "Fields" +msgstr "Câmpuri" + +msgid "Field" +msgstr "Câmp" + +msgid "Type" +msgstr "Tip" + +msgid "Description" +msgstr "Descriere" + +msgid "Methods with arguments" +msgstr "Metode cu argumente" + +msgid "Method" +msgstr "Metodă" + +msgid "Arguments" +msgstr "Argumente" + +msgid "Back to Model documentation" +msgstr "Înapoi la Documentația Modelelor" + +msgid "Model documentation" +msgstr "Documentația modelelor" + +msgid "Model groups" +msgstr "Grupuri de modele" + +msgid "Templates" +msgstr "Șabloane" + +#, python-format +msgid "Template: %(name)s" +msgstr "Șablonul: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Template: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Calea de căutare pentru template %(name)s:" + +msgid "(does not exist)" +msgstr "(inexistent)" + +msgid "Back to Documentation" +msgstr "Înapoi la Documentație" + +msgid "Template filters" +msgstr "Filtre pentru șabloane" + +msgid "Template filter documentation" +msgstr "Documentația filtrelor pentru șabloane" + +msgid "Built-in filters" +msgstr "Filtre implicite" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Pentru a utiliza aceste filtre, puneți %(code)s în șablon " +"înainte de utilizarea acestui filtru." + +msgid "Template tags" +msgstr "Taguri pentru șabloane" + +msgid "Template tag documentation" +msgstr "Documentația tagurilor pentru șabloane" + +msgid "Built-in tags" +msgstr "Taguri implicite" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Pentru a utiliza aceste taguri, puneți %(code)s în șablon " +"înainte de a utiliza tagul." + +#, python-format +msgid "View: %(name)s" +msgstr "Cod de afișare: %(name)s" + +msgid "Context:" +msgstr "Context:" + +msgid "Templates:" +msgstr "Șablonuri:" + +msgid "Back to View documentation" +msgstr "Înapoi la Documentația Codurilor de afișare" + +msgid "View documentation" +msgstr "Vezi documentația" + +msgid "Jump to namespace" +msgstr "Mergeți la spațiul de nume" + +msgid "Empty namespace" +msgstr "Spațiu de nume gol" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Coduri de afișare după spațiul de nume %(name)s" + +msgid "Views by empty namespace" +msgstr "Coduri de afișare după spațiu de nume gol" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"Funcția din codul de afișare: %(full_name)s. Nume: " +"%(url_name)s.\n" + +msgid "tag:" +msgstr "tag:" + +msgid "filter:" +msgstr "filtru:" + +msgid "view:" +msgstr "cod de afișare:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Aplicația %(app_label)r nu a fost găsită" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Modelul %(model_name)r nu a fost găsit în aplicația %(app_label)r" + +msgid "model:" +msgstr "model:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "obiectul înrudit `%(app_label)s.%(data_type)s`" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "obiectele înrudite `%(app_label)s.%(object_name)s`" + +#, python-format +msgid "all %s" +msgstr "toate %s" + +#, python-format +msgid "number of %s" +msgstr "numărul de %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s nu pare a fi un obiect urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ru/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ru/LC_MESSAGES/django.mo new file mode 100644 index 0000000..21931a6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ru/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ru/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ru/LC_MESSAGES/django.po new file mode 100644 index 0000000..0f7e30f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ru/LC_MESSAGES/django.po @@ -0,0 +1,292 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Eugene , 2012 +# Jannis Leidel , 2011 +# Panasoft, 2021 +# SeryiMysh , 2020 +# Алексей Борискин , 2012-2015 +# Андрей Щуров , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-03-16 22:51+0000\n" +"Last-Translator: Panasoft\n" +"Language-Team: Russian (http://www.transifex.com/django/django/language/" +"ru/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ru\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n" +"%100>=11 && n%100<=14)? 2 : 3);\n" + +msgid "Administrative Documentation" +msgstr "Документация для администраторов" + +msgid "Home" +msgstr "Начало" + +msgid "Documentation" +msgstr "Документация" + +msgid "Bookmarklets" +msgstr "Закладки" + +msgid "Documentation bookmarklets" +msgstr "Закладки документации" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Чтобы установить букмарклет, перетащите ссылку на панель закладок браузера " +"или откройте кликом по правой кнопке мышки контекстное меню и добавьте " +"ссылку в закладки. Теперь у вас есть доступ к букмарклету с любой страницы " +"сайта." + +msgid "Documentation for this page" +msgstr "Документация для данной страницы" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Перенаправляет вас с любой страницы к документации для view, который " +"генерирует эту страницу." + +msgid "Tags" +msgstr "Теги" + +msgid "List of all the template tags and their functions." +msgstr "Список всех template tag-ов и их функций." + +msgid "Filters" +msgstr "Фильтры" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Фильтры - это действия, которые могут быть выполнены над переменными в " +"шаблоне, чтобы изменить их отображение." + +msgid "Models" +msgstr "Модели" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Модели - это описания всех объектов, существующих в системе и связанные с " +"ними поля. Каждая модель имеет список полей, которые могут быть использованы " +"в качестве переменных в шаблонах" + +msgid "Views" +msgstr "View" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Каждая страница сайта создаётся с помощью view. View определяет, какой " +"шаблон использовать, чтобы создать страницу и какие объекты будут доступны в " +"этом шаблоне." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Инструменты для вашего браузера для быстрого доступа к функциональности " +"административного раздела сайта (букмарклеты)." + +msgid "Please install docutils" +msgstr "Пожалуйста, установите docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Для системы административной документации требуется библиотека Python docutils." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Пожалуйста, попросите ваших администраторов установить docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Модель: %(name)s" + +msgid "Fields" +msgstr "Поля" + +msgid "Field" +msgstr "Поле" + +msgid "Type" +msgstr "Тип" + +msgid "Description" +msgstr "Описание" + +msgid "Methods with arguments" +msgstr "Методы с аргументами" + +msgid "Method" +msgstr "Метод" + +msgid "Arguments" +msgstr "Аргументы" + +msgid "Back to Model documentation" +msgstr "Назад к документации моделей" + +msgid "Model documentation" +msgstr "Документация моделей" + +msgid "Model groups" +msgstr "Группы моделей" + +msgid "Templates" +msgstr "Шаблоны" + +#, python-format +msgid "Template: %(name)s" +msgstr "Шаблон: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Шаблон: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Путь к местонахождению шаблона %(name)s:" + +msgid "(does not exist)" +msgstr "(не существует)" + +msgid "Back to Documentation" +msgstr "Назад к документации" + +msgid "Template filters" +msgstr "Фильтры в шаблонах" + +msgid "Template filter documentation" +msgstr "Документация о фильтрах в шаблонах" + +msgid "Built-in filters" +msgstr "Встроенные фильтры" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Чтобы использовать эти фильтры, поместите %(code)s в ваш шаблон " +"выше строки с использованием фильтра." + +msgid "Template tags" +msgstr "Теги шаблонов" + +msgid "Template tag documentation" +msgstr "Документация по тегам шаблонов" + +msgid "Built-in tags" +msgstr "Встроенные теги" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Чтобы использовать эти теги, поместите %(code)s в ваш шаблон " +"выше строки с использованием тега." + +#, python-format +msgid "View: %(name)s" +msgstr "View: %(name)s" + +msgid "Context:" +msgstr "Контекст:" + +msgid "Templates:" +msgstr "Шаблоны:" + +msgid "Back to View documentation" +msgstr "Назад к документации о представлений" + +msgid "View documentation" +msgstr "Документация о view" + +msgid "Jump to namespace" +msgstr "Перейти к пространству имён" + +msgid "Empty namespace" +msgstr "Глобальное пространство имён" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "View в пространстве имён %(name)s" + +msgid "Views by empty namespace" +msgstr "View в глобальном пространстве имён" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"View-функция: %(full_name)s. Имя url-шаблона: " +"%(url_name)s.\n" + +msgid "tag:" +msgstr "тег:" + +msgid "filter:" +msgstr "фильтр:" + +msgid "view:" +msgstr "view:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Приложение «%(app_label)r» не найдено" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Модель %(model_name)r не найдена в приложении %(app_label)r" + +msgid "model:" +msgstr "модель:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "зависимый `%(app_label)s.%(data_type)s` объект" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "связанные объекты `%(app_label)s.%(object_name)s`" + +#, python-format +msgid "all %s" +msgstr "все %s" + +#, python-format +msgid "number of %s" +msgstr "количество %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s не похож на объект urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3cc3702 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sk/LC_MESSAGES/django.po new file mode 100644 index 0000000..18448d1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sk/LC_MESSAGES/django.po @@ -0,0 +1,286 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# 18f25ad6fa9930fc67cb11aca9d16a27, 2012-2013 +# Marian Andre , 2012-2013,2015,2017 +# Martin Tóth , 2017,2023 +# Peter Kuma, 2021 +# supowski , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2023-12-04 20:19+0000\n" +"Last-Translator: Martin Tóth , 2017,2023\n" +"Language-Team: Slovak (http://app.transifex.com/django/django/language/sk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n " +">= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);\n" + +msgid "Administrative Documentation" +msgstr "Správcovská dokumentácia" + +msgid "Home" +msgstr "Domov" + +msgid "Documentation" +msgstr "Dokumentácia" + +msgid "Bookmarklets" +msgstr "Záložky" + +msgid "Documentation bookmarklets" +msgstr "Záložky dokumentácie" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Na nainštalovanie bookmarkletov, pretiahnite odkaz váš panel so záložkami, " +"alebo kliknite pravým tlačidlom na odkaz a pridajte ho do vašich záložiek. " +"Teraz si môžete vybrať bookmarklet z ľubovoľnej stránky na sídle." + +msgid "Documentation for this page" +msgstr "Dokumentácia pre túto stránku" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Nasmeruje vás z ľubovoľnej stránky do dokumentácie, kde je popísané, ako sa " +"táto stránka generuje." + +msgid "Tags" +msgstr "Značky" + +msgid "List of all the template tags and their functions." +msgstr "Zoznam všetkých šablónových značiek a ich funkcií." + +msgid "Filters" +msgstr "Filtre" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Filtre su akcie, ktoré môžu byť aplikované na premenné v šablóne, aby " +"zmenili ich výstup." + +msgid "Models" +msgstr "Modely" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Modely sú popisom všetkých objektov v systéme a ich pridružených polí. Každý " +"model má zoznam polí, ktoré sú dostupné ako premenné v šablónach." + +msgid "Views" +msgstr "Zobrazenia" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Každá stránka na verejnom sídle je generovaná pomocou pohľadu. Pohľad " +"definuje, ktorá šablóna sa použije na generovanie stránky, a ktoré objekty " +"budú v šablóne k dispozícii." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Nástroje pre váš prohliadač k rýchlemu prístupu k funkciám správy stránok." + +msgid "Please install docutils" +msgstr "Prosím, nainštalujte docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Dokumentačný systém správy stránok vyžaduje Python knižnicu docutils." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Požiadajte administrátorov o inštaláciu docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Model: %(name)s" + +msgid "Fields" +msgstr "Polia" + +msgid "Field" +msgstr "Pole" + +msgid "Type" +msgstr "Typ" + +msgid "Description" +msgstr "Popis" + +msgid "Methods with arguments" +msgstr "Metódy s argumentami" + +msgid "Method" +msgstr "Metódy" + +msgid "Arguments" +msgstr "Argumenty" + +msgid "Back to Model documentation" +msgstr "Späť na dokumentáciu modelov" + +msgid "Model documentation" +msgstr "Dokumentácia modelu" + +msgid "Model groups" +msgstr "Skupiny modelov" + +msgid "Templates" +msgstr "Šablóny" + +#, python-format +msgid "Template: %(name)s" +msgstr "Šablóna: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Šablóna: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Vyhľadávacia cesta pre šablónu %(name)s:" + +msgid "(does not exist)" +msgstr "(neexistuje)" + +msgid "Back to Documentation" +msgstr "Späť na Dokumentáciu" + +msgid "Template filters" +msgstr "Filtre šablóny" + +msgid "Template filter documentation" +msgstr "Dokumentácia filtrov šablón" + +msgid "Built-in filters" +msgstr "Vstavané filtre" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Na použitie týchto filtrov, vložte %(code)s do vašej šablóny " +"pred použitím filtra." + +msgid "Template tags" +msgstr "Šablónové značky" + +msgid "Template tag documentation" +msgstr "Dokumentácia šablónových značiek" + +msgid "Built-in tags" +msgstr "Vstavané značky" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Na použitie týchto značiek, vložte %(code)s do vašej šablóny " +"pred použitím značky." + +#, python-format +msgid "View: %(name)s" +msgstr "Pohľad: %(name)s" + +msgid "Context:" +msgstr "Kontext:" + +msgid "Templates:" +msgstr "Šablóny:" + +msgid "Back to View documentation" +msgstr "Späť na dokumentáciu pohľadov" + +msgid "View documentation" +msgstr "Dokumentácia pohľadov" + +msgid "Jump to namespace" +msgstr "Prejsť na menný priestor" + +msgid "Empty namespace" +msgstr "Prázdny menný priestor" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Pohľady podľa menného priestoru %(name)s" + +msgid "Views by empty namespace" +msgstr "Pohľady podľa prázdneho menného priestoru" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"Funkcia pohľadu: %(full_name)s. Názov: %(url_name)s.\n" + +msgid "tag:" +msgstr "značka:" + +msgid "filter:" +msgstr "filter:" + +msgid "view:" +msgstr "pohľad:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Applikácia %(app_label)r nenájdená" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Model %(model_name)r sa v aplikácii %(app_label)r nenachádza" + +msgid "model:" +msgstr "model:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "súvisiaci objekt `%(app_label)s.%(data_type)s`" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "súvisiace objekty `%(app_label)s.%(object_name)s`" + +#, python-format +msgid "all %s" +msgstr "všetky %s" + +#, python-format +msgid "number of %s" +msgstr "počet %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s nevyzerá ako urlpattern objekt" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..cc2764f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sl/LC_MESSAGES/django.po new file mode 100644 index 0000000..1cb6abc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sl/LC_MESSAGES/django.po @@ -0,0 +1,285 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Primož Verdnik , 2017 +# zejn , 2013,2016 +# zejn , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Primož Verdnik \n" +"Language-Team: Slovenian (http://www.transifex.com/django/django/language/" +"sl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sl\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" + +msgid "Administrative Documentation" +msgstr "Dokumentacija o administraciji" + +msgid "Home" +msgstr "Domov" + +msgid "Documentation" +msgstr "Dokumentacija" + +msgid "Bookmarklets" +msgstr "Apleti zaznamkov" + +msgid "Documentation bookmarklets" +msgstr "Dokumentacijski apleti zaznamkov" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Aplete zaznamkov je mogoče namestiti z vleko povezave v orodno vrstico z " +"zaznamki, ali pa z desnim klikom na povezavo. Zaznamek je mogoče izbrati s " +"katerekoli strani tega spletnega mesta." + +msgid "Documentation for this page" +msgstr "Dokumentacija te strani" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "Skok na stran z dokumentacijo za pogled, ki gustvarja trenutno stran." + +msgid "Tags" +msgstr "Oznake" + +msgid "List of all the template tags and their functions." +msgstr "Izpiši vse značke za predloge in njihov opis." + +msgid "Filters" +msgstr "Filtri" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Filtri so opravila, ki jih lahko uporabite na spremenljivkah v predlogah, da " +"spremenite izpis." + +msgid "Models" +msgstr "Modeli" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Modeli so opisi vseh objektov v sistemu in njihovih pripadajočih polj. Vsak " +"model ima seznam polj, do katerih lahko dostopate v predlogi" + +msgid "Views" +msgstr "Pogledi" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Vsaka stran na javni strani je zgenerirana iz pogleda. Pogled definira " +"katera predloga je uporabljena za generiranje strani in kateri objekti so " +"dostopni ti predlogi." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Orodja za vaš brskalnik, da lahko hitro dostopate do administracijskih " +"funkcij." + +msgid "Please install docutils" +msgstr "Prosimo namestite paket docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" +"Dokumentcijski sistem administracijskega vmesnika zahteva knjižnico docutils za Python." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Prosimo povprašajte administratorja, da namesti docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Model: %(name)s" + +msgid "Fields" +msgstr "Polja" + +msgid "Field" +msgstr "Polje" + +msgid "Type" +msgstr "Tip" + +msgid "Description" +msgstr "Opis" + +msgid "Methods with arguments" +msgstr "Metode z argumenti" + +msgid "Method" +msgstr "Metoda" + +msgid "Arguments" +msgstr "Argumenti" + +msgid "Back to Model documentation" +msgstr "Nazaj na dokumentacijo modelov" + +msgid "Model documentation" +msgstr "Dokumentacija modelov" + +msgid "Model groups" +msgstr "Skupine modelov" + +msgid "Templates" +msgstr "Predloge" + +#, python-format +msgid "Template: %(name)s" +msgstr "Predloga: %(name)s" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "Predloga: \"%(name)s\"" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "Poti iskanja za predlogo \"%(name)s\":" + +msgid "(does not exist)" +msgstr "(ne obstaja)" + +msgid "Back to Documentation" +msgstr "Nazaj na dokumentacijo" + +msgid "Template filters" +msgstr "Filtri v predlogah" + +msgid "Template filter documentation" +msgstr "Dokumentacija filtrov v predlogah" + +msgid "Built-in filters" +msgstr "Vgrajeni filtri" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Če želite uporabiti te filtre, dodajte %(code)s v vašo predlogo " +"preden uporabite filter." + +msgid "Template tags" +msgstr "Značke v predlogah" + +msgid "Template tag documentation" +msgstr "Dokumentacija značk v predlogah" + +msgid "Built-in tags" +msgstr "Vgrajene značke" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Če želite uporabiti te značke, dodajte %(code)s v vašo predlogo " +"preden uporabite značko." + +#, python-format +msgid "View: %(name)s" +msgstr "Pogled: %(name)s" + +msgid "Context:" +msgstr "Kontekst:" + +msgid "Templates:" +msgstr "Predloge:" + +msgid "Back to View documentation" +msgstr "Nazaj na dokumentacijo pogledov" + +msgid "View documentation" +msgstr "Dokumentacija pogledov" + +msgid "Jump to namespace" +msgstr "Skoči na imenski prostor" + +msgid "Empty namespace" +msgstr "Prazen imenski prostor" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Pogledi v imenskem prostoru %(name)s" + +msgid "Views by empty namespace" +msgstr "Pogledi brez imenskega prostora" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +" Funkcija pogleda: %(full_name)s. Ime: %(url_name)s.\n" + +msgid "tag:" +msgstr "oznaka:" + +msgid "filter:" +msgstr "filter:" + +msgid "view:" +msgstr "pogled:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Applikacije %(app_label)r ni bilo mogoče najti" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Modela %(model_name)r ni v programu %(app_label)r" + +msgid "model:" +msgstr "model:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "povezani predmet `%(app_label)s.%(data_type)s`" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "povezani predmeti `%(app_label)s.%(object_name)s`" + +#, python-format +msgid "all %s" +msgstr "vse %s" + +#, python-format +msgid "number of %s" +msgstr "število %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "Predmet %s ni videti veljaven predmet urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sq/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sq/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1ff898e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sq/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sq/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sq/LC_MESSAGES/django.po new file mode 100644 index 0000000..54a5233 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sq/LC_MESSAGES/django.po @@ -0,0 +1,283 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Besnik Bleta , 2011,2015 +# Besnik Bleta , 2021 +# Besnik Bleta , 2015,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-01-15 13:31+0000\n" +"Last-Translator: Besnik Bleta \n" +"Language-Team: Albanian (http://www.transifex.com/django/django/language/" +"sq/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sq\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Dokumentim Administrimi" + +msgid "Home" +msgstr "Hyrje" + +msgid "Documentation" +msgstr "Dokumentim" + +msgid "Bookmarklets" +msgstr "Bookmarklet-e" + +msgid "Documentation bookmarklets" +msgstr "Bookmarklet-e Dokumentimi" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Që të instaloni bookmarklet-e, tërhiqeni lidhjen te paneli juaj i " +"faqerojtësve, ose djathtasklikoni lidhjen dhe shtojeni te faqerojtësit tuaj. " +"Tani mund ta përzgjidhni bookmarklet-in prej cilësdo faqe te sajti." + +msgid "Documentation for this page" +msgstr "Dokumentim për këtë faqe" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "Nga cilado faqe, ju kalon te dokumenti për skenën që prodhon atë faqe." + +msgid "Tags" +msgstr "Etiketa" + +msgid "List of all the template tags and their functions." +msgstr "listë e krejt etiketave të gjedheve dhe funksionet e tyre." + +msgid "Filters" +msgstr "Filtra" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Filtrat janë veprime që mund të zbatohen mbi ndryshoret në një gjedhe për të " +"ndryshuar përfundimet e saj." + +msgid "Models" +msgstr "Modele" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Modelet janë përshkrime të krejt objekteve në sistem dhe fushave " +"përshoqëruar me to. Çdo model ka një listë fushash të cilat mund të përdoren " +"si ndryshore gjedheje" + +msgid "Views" +msgstr "Skena" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Çdo faqe në sajtin publik prodhohet nga ajo që quhet skenë. Skena përcakton " +"cila gjedhe përdoret për të prodhuar faqen dhe cilët objekte mund të kihen " +"për atë gjedhe." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Mjete që shfletuesi juaj të përdorë me shpejtësi funksione administrimi." + +msgid "Please install docutils" +msgstr "Ju lutemi, instaloni docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Sistemi i dokumentimit për përgjegjësin lyp librarinë Python docutils." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Ju lutemi, kërkojuni përgjegjësve të sistemit të instalojnë docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Model: %(name)s" + +msgid "Fields" +msgstr "Fusha" + +msgid "Field" +msgstr "Fushë" + +msgid "Type" +msgstr "Lloj" + +msgid "Description" +msgstr "Përshkrim" + +msgid "Methods with arguments" +msgstr "Metoda me argumente" + +msgid "Method" +msgstr "Metodë" + +msgid "Arguments" +msgstr "Argumente" + +msgid "Back to Model documentation" +msgstr "Mbrapsht te dokumentim Modeli" + +msgid "Model documentation" +msgstr "Dokumentim modeli" + +msgid "Model groups" +msgstr "Grupe modeli" + +msgid "Templates" +msgstr "Gjedhe" + +#, python-format +msgid "Template: %(name)s" +msgstr "Gjedhe: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Gjedhe: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Shteg kërkimi për gjedhen %(name)s:" + +msgid "(does not exist)" +msgstr "(nuk ekziston)" + +msgid "Back to Documentation" +msgstr "Mbrapsht te Dokumentimi" + +msgid "Template filters" +msgstr "Filtra gjedhesh" + +msgid "Template filter documentation" +msgstr "Dokumentim filtrash gjedheje" + +msgid "Built-in filters" +msgstr "Filtra të brendshëm" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Për të përdorur këta filtra, vendosni te gjedhja juaj %(code)s " +"përpara se të përdorni filtrin." + +msgid "Template tags" +msgstr "Etiketa gjedhesh" + +msgid "Template tag documentation" +msgstr "Dokumentim etiketash gjedheje" + +msgid "Built-in tags" +msgstr "Etiketa të brendshme" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Për të përdorur këto etiketa, vendosni te gjedhja juaj %(code)s " +"përpara se të përdorni etiketën." + +#, python-format +msgid "View: %(name)s" +msgstr "Skenë: %(name)s" + +msgid "Context:" +msgstr "Kontekst:" + +msgid "Templates:" +msgstr "Gjedhe:" + +msgid "Back to View documentation" +msgstr "Mbrapsht te dokumentim Parjeje" + +msgid "View documentation" +msgstr "Dokumentim skenash" + +msgid "Jump to namespace" +msgstr "Kalo te emërhapësira" + +msgid "Empty namespace" +msgstr "Emërhapësirë e zbrazët" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Skena me emërhapësirë %(name)s" + +msgid "Views by empty namespace" +msgstr "Skena me emërhapësirë të zbrazët" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +" Funksion skene: %(full_name)s. Emër: %(url_name)s.\n" + +msgid "tag:" +msgstr "etiketë:" + +msgid "filter:" +msgstr "filtër:" + +msgid "view:" +msgstr "skenë:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "S’u gjet dot aplikacioni %(app_label)r" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "S’u gjet modeli %(model_name)r në aplikacionin %(app_label)r" + +msgid "model:" +msgstr "model:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "objekti i afërt `%(app_label)s.%(data_type)s`" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "objektet e afërta `%(app_label)s.%(object_name)s`" + +#, python-format +msgid "all %s" +msgstr "krejt %s" + +#, python-format +msgid "number of %s" +msgstr "numër i %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s s’duket se është objekt urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3fe888e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sr/LC_MESSAGES/django.po new file mode 100644 index 0000000..6bc596e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sr/LC_MESSAGES/django.po @@ -0,0 +1,285 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Branko Kokanovic , 2018 +# Igor Jerosimić, 2019,2023 +# Jannis Leidel , 2011 +# Janos Guljas , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2023-12-04 20:19+0000\n" +"Last-Translator: Igor Jerosimić, 2019,2023\n" +"Language-Team: Serbian (http://app.transifex.com/django/django/language/" +"sr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Administrative Documentation" +msgstr "Административна документација" + +msgid "Home" +msgstr "Почетна" + +msgid "Documentation" +msgstr "Документација" + +msgid "Bookmarklets" +msgstr "Букмарклети" + +msgid "Documentation bookmarklets" +msgstr "Букмарклети документације" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Да бисте инсталирали обележиваче, превуците везу на траку са алаткама за " +"обележиваче или кликните десним тастером миша на везу и додајте је у " +"обележиваче. Сада можете да изаберете боокмарклет са било које странице на " +"сајту." + +msgid "Documentation for this page" +msgstr "Документација за ову страницу" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Води од било које странице до документације погледа који је генерисао ту " +"страницу." + +msgid "Tags" +msgstr "Тагови" + +msgid "List of all the template tags and their functions." +msgstr "Листа свих ознака шаблона и њихових функција." + +msgid "Filters" +msgstr "Филтери" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Филтери су радње које се могу применити на променљиве у шаблону да би се " +"променио излаз." + +msgid "Models" +msgstr "Модели" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Модели су описи свих објеката у систему и њихових повезаних поља. Сваки " +"модел има листу поља којима се може приступити као променљиве шаблона" + +msgid "Views" +msgstr "Погледи" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Сваку страницу на јавном сајту генерише поглед. Поглед дефинише који шаблон " +"се користи за генерисање странице и који објекти су доступни том шаблону." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "Алатке за ваш претраживач за брзи приступ функцијама администратора." + +msgid "Please install docutils" +msgstr "Молимо инсталирајте docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Систем административне документације захтева Пајтон docutils библиотеку." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Замолите своје администраторе да инсталирају docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Модел: %(name)s" + +msgid "Fields" +msgstr "Поља" + +msgid "Field" +msgstr "Поље" + +msgid "Type" +msgstr "Тип" + +msgid "Description" +msgstr "Опис" + +msgid "Methods with arguments" +msgstr "Метода са аргументима" + +msgid "Method" +msgstr "Метод" + +msgid "Arguments" +msgstr "Аргументи" + +msgid "Back to Model documentation" +msgstr "Назад на документацију о Моделима" + +msgid "Model documentation" +msgstr "Документација о Моделима" + +msgid "Model groups" +msgstr "Групе модела" + +msgid "Templates" +msgstr "Шаблони" + +#, python-format +msgid "Template: %(name)s" +msgstr "Шаблон: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Шаблон: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Путања за тражење шаблона %(name)s:" + +msgid "(does not exist)" +msgstr "(не постоји)" + +msgid "Back to Documentation" +msgstr "Назада на документацију" + +msgid "Template filters" +msgstr "Филтери шаблона" + +msgid "Template filter documentation" +msgstr "Документација филтера шаблона" + +msgid "Built-in filters" +msgstr "Уграђени филтери" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Да бисте користили ове филтере, ставите %(code)s у свој шаблон " +"пре употребе филтера." + +msgid "Template tags" +msgstr "Ознаке шаблона" + +msgid "Template tag documentation" +msgstr "Документација ознаке шаблона" + +msgid "Built-in tags" +msgstr "Уграђене ознаке" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Да бисте користили ове ознаке, ставите %(code)s у свој шаблон " +"пре употребе ознаке." + +#, python-format +msgid "View: %(name)s" +msgstr "Поглед: %(name)s" + +msgid "Context:" +msgstr "Контекст:" + +msgid "Templates:" +msgstr "Шаблони:" + +msgid "Back to View documentation" +msgstr "Назад на документацију о погледима" + +msgid "View documentation" +msgstr "Документација о погледима" + +msgid "Jump to namespace" +msgstr "Скочи на именски простор" + +msgid "Empty namespace" +msgstr "Празан именски простор" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Погледи по именском простору %(name)s" + +msgid "Views by empty namespace" +msgstr "Погледи по празном именском простору" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +" Функција погледа: %(full_name)s. Име: %(url_name)s.\n" + +msgid "tag:" +msgstr "таг:" + +msgid "filter:" +msgstr "филтер:" + +msgid "view:" +msgstr "поглед:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Апликација %(app_label)r није пронађена" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Модел %(model_name)r није пронађен у апликацији %(app_label)r" + +msgid "model:" +msgstr "модел:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "повезани објекти класе `%(app_label)s.%(data_type)s`" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "класе `%(app_label)s.%(object_name)s`" + +#, python-format +msgid "all %s" +msgstr "сви повезани објекти %s" + +#, python-format +msgid "number of %s" +msgstr "број повезаних објеката %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s не изгледа као „urlpattern“ објекат" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sr_Latn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sr_Latn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..cfa870b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sr_Latn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sr_Latn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sr_Latn/LC_MESSAGES/django.po new file mode 100644 index 0000000..d8cb1cb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sr_Latn/LC_MESSAGES/django.po @@ -0,0 +1,271 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Igor Jerosimić, 2023 +# Jannis Leidel , 2011 +# Janos Guljas , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2023-12-04 20:19+0000\n" +"Last-Translator: Igor Jerosimić, 2023\n" +"Language-Team: Serbian (Latin) (http://app.transifex.com/django/django/" +"language/sr@latin/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr@latin\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Administrative Documentation" +msgstr "Administrativna dokumentacija" + +msgid "Home" +msgstr "Početna" + +msgid "Documentation" +msgstr "Dokumentacija" + +msgid "Bookmarklets" +msgstr "Bukmarkleti" + +msgid "Documentation bookmarklets" +msgstr "Bukmarkleti dokumentacije" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Da biste instalirali obeleživače, prevucite vezu na traku sa alatkama za " +"obeleživače ili kliknite desnim tasterom miša na vezu i dodajte je u " +"obeleživače. Sada možete da izaberete bookmarklet sa bilo koje stranice na " +"sajtu." + +msgid "Documentation for this page" +msgstr "Dokumentacija za ovu stranicu" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Vodi od bilo koje stranice do dokumentaicje pogleda koji je generisao tu " +"stranicu." + +msgid "Tags" +msgstr "Tagovi" + +msgid "List of all the template tags and their functions." +msgstr "Lista svih oznaka šablona i njihovih funkcija." + +msgid "Filters" +msgstr "Filteri" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Filteri su radnje koje se mogu primeniti na promenljive u šablonu da bi se " +"promenio izlaz." + +msgid "Models" +msgstr "Modeli" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Modeli su opisi svih objekata u sistemu i njihovih povezanih polja. Svaki " +"model ima listu polja kojima se može pristupiti kao promenljive šablona" + +msgid "Views" +msgstr "Vjuevi" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "Šabloni" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "tag:" + +msgid "filter:" +msgstr "filter:" + +msgid "view:" +msgstr "vju:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Model %(model_name)r nije pronađen u aplikaciji %(app_label)r" + +msgid "model:" +msgstr "model:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "povezani objekti klase `%(app_label)s.%(data_type)s`" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "klase `%(app_label)s.%(object_name)s`" + +#, python-format +msgid "all %s" +msgstr "svi povezani objekti %s" + +#, python-format +msgid "number of %s" +msgstr "broj povezanih objekata %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s ne izgleda kao „urlpattern“ objekat" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sv/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sv/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d20b69b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sv/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sv/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sv/LC_MESSAGES/django.po new file mode 100644 index 0000000..fe36350 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sv/LC_MESSAGES/django.po @@ -0,0 +1,288 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Albin Larsson , 2022 +# Andreas Pelme , 2012,2014 +# Jannis Leidel , 2011 +# Jonathan Lindén, 2014 +# Petter Strandmark , 2019 +# Thomas Lundqvist, 2013 +# Tomas Lööw , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2022-07-24 20:19+0000\n" +"Last-Translator: Albin Larsson \n" +"Language-Team: Swedish (http://www.transifex.com/django/django/language/" +"sv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sv\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Dokumentation för admin" + +msgid "Home" +msgstr "Hem" + +msgid "Documentation" +msgstr "Dokumentation" + +msgid "Bookmarklets" +msgstr "Smarta bokmärken" + +msgid "Documentation bookmarklets" +msgstr "Smarta bokmärken för dokumentation" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"För att installera bookmarklets, dra länken till din verkygsrad för " +"bokmärken, eller högerklicka på länken och lägg till den till dina " +"bokmärken. Nu kan du välja din bookmarklet från vilken sida som helst." + +msgid "Documentation for this page" +msgstr "Dokumentation för denna sida" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Förflyttar dig från valfri sida till dokumentationen för vyn som genererar " +"den sidan." + +msgid "Tags" +msgstr "Taggar" + +msgid "List of all the template tags and their functions." +msgstr "En lista på alla malltaggar och deras funktioner." + +msgid "Filters" +msgstr "Filter" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Filter är åtgärder som kan appliceras på variabler i en mall för att ändra " +"utmatningen." + +msgid "Models" +msgstr "Modeller" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Modeller är beskrivningar av alla objekt i systemet och deras tillhörande " +"fält. Varje modell har en lista av fält som kan kommas åt som variabler i " +"mallen." + +msgid "Views" +msgstr "Vyer" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Varje sida på den publika sidan är genererad av en vy. Vyn definierar vilka " +"mallar som används för att generera sidan samt vilka objekt som är " +"tillgängliga i den mallen." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Verktyg till din webbläsare för snabb tillgång till " +"administrationsfunktioner." + +msgid "Please install docutils" +msgstr "Vänligen installera docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Administrationsdokumentationen kräver Pythons docutils bibliotek." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Vänligen be din administratör installera docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Modell: %(name)s" + +msgid "Fields" +msgstr "Fält" + +msgid "Field" +msgstr "Fält" + +msgid "Type" +msgstr "Typ" + +msgid "Description" +msgstr "Beskrivning" + +msgid "Methods with arguments" +msgstr "Metod med argument" + +msgid "Method" +msgstr "Metod" + +msgid "Arguments" +msgstr "Argument" + +msgid "Back to Model documentation" +msgstr "Tillbaka till modell-dokumentation" + +msgid "Model documentation" +msgstr "Modelldokumentation" + +msgid "Model groups" +msgstr "Modellgrupper" + +msgid "Templates" +msgstr "Mallar" + +#, python-format +msgid "Template: %(name)s" +msgstr "Mall: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Mall:%(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Sökvägen för mall %(name)s:" + +msgid "(does not exist)" +msgstr "(finns inte)" + +msgid "Back to Documentation" +msgstr "Tillbaka till dokumentation" + +msgid "Template filters" +msgstr "Mallfilter" + +msgid "Template filter documentation" +msgstr "Mallfilterdokumentation" + +msgid "Built-in filters" +msgstr "Inbyggda filter" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"För att använda dessa filter, lägg till %(code)s innan du " +"använder filtret i din mall." + +msgid "Template tags" +msgstr "Malltaggar" + +msgid "Template tag documentation" +msgstr "Malltaggdokumentation" + +msgid "Built-in tags" +msgstr "Inbyggda taggar" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"För att använda dessa taggar, lägg till %(code)s innan du " +"använder taggen i din mall." + +#, python-format +msgid "View: %(name)s" +msgstr "Vy: %(name)s" + +msgid "Context:" +msgstr "Kontext:" + +msgid "Templates:" +msgstr "Mallar:" + +msgid "Back to View documentation" +msgstr "Tillbaka till vy-dokumentation" + +msgid "View documentation" +msgstr "Titta på dokumentationen" + +msgid "Jump to namespace" +msgstr "Hoppa till namespace" + +msgid "Empty namespace" +msgstr "Tom namespace" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Vyer för namespace %(name)s" + +msgid "Views by empty namespace" +msgstr "Vyer för tom namespace" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"Vyfunktion: %(full_name)s. Namn: %(url_name)s.\n" + +msgid "tag:" +msgstr "tagg:" + +msgid "filter:" +msgstr "filter:" + +msgid "view:" +msgstr "vy:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Applikation %(app_label)r hittades inte" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Modell %(model_name)r hittades inte i applikation %(app_label)r" + +msgid "model:" +msgstr "modell:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "det relaterade `%(app_label)s.%(data_type)s`-objektet" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "relaterade `%(app_label)s.%(object_name)s`-objekt" + +#, python-format +msgid "all %s" +msgstr "alla %s" + +#, python-format +msgid "number of %s" +msgstr "antal %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s verkar inte vara ett urlpattern-objekt" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sw/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sw/LC_MESSAGES/django.mo new file mode 100644 index 0000000..349f77b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sw/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sw/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sw/LC_MESSAGES/django.po new file mode 100644 index 0000000..3a9e2fd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/sw/LC_MESSAGES/django.po @@ -0,0 +1,259 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Swahili (http://www.transifex.com/django/django/language/" +"sw/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sw\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "Sebule" + +msgid "Documentation" +msgstr "Waraka" + +msgid "Bookmarklets" +msgstr "Vialamisho" + +msgid "Documentation bookmarklets" +msgstr "Vialamisho vya waraka" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "Nyaraka kwa ajili ya ukurasa huu" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Inakurusha kutoka ukurasa wowote hadi kwenye waraka wa mounekano unaozalisha " +"ukurasa huo." + +msgid "Tags" +msgstr "Tagi" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "Chujio" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "Modeli" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "Mionekano" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "Templeti" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "tagi" + +msgid "filter:" +msgstr "chujio" + +msgid "view:" +msgstr "muonekano" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Modeli %(model_name)r haijapatikana katika programu %(app_label)r" + +msgid "model:" +msgstr "modeli" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "`%(app_label)s.%(data_type)s` kinachohusiana" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "`%(app_label)s.%(object_name)s` vinavyohusiana" + +#, python-format +msgid "all %s" +msgstr "kila %s" + +#, python-format +msgid "number of %s" +msgstr "idadi ya %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s haionekani kuwa ni kitu cha urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ta/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ta/LC_MESSAGES/django.mo new file mode 100644 index 0000000..acf0768 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ta/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ta/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ta/LC_MESSAGES/django.po new file mode 100644 index 0000000..c0ca3d9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ta/LC_MESSAGES/django.po @@ -0,0 +1,258 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Tamil (http://www.transifex.com/django/django/language/ta/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ta\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "வீடு" + +msgid "Documentation" +msgstr "ஆவனமாக்கம்" + +msgid "Bookmarklets" +msgstr "புத்தகக்குறிகள்" + +msgid "Documentation bookmarklets" +msgstr "ஆவணமாக்கக் குறியீடுகள்" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "இந்த பக்கத்திற்கான ஆவணம்" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"எந்த ஒரு பக்கத்திலிருந்தும் ஆவணப்பக்கத்தை பார்வையிடுதல், அந்த பக்கத்தை உருவாக்குகிறது." + +msgid "Tags" +msgstr "" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "ஒட்டு:" + +msgid "filter:" +msgstr "வடிகட்டி:" + +msgid "view:" +msgstr "நோற்றமிடு:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "" + +msgid "model:" +msgstr "மாதிரி:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "" + +#, python-format +msgid "all %s" +msgstr "அனைத்து %s " + +#, python-format +msgid "number of %s" +msgstr "எண்ணிக்கை %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s -ல் urlpattern தோன்றுவதில்லை" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/te/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/te/LC_MESSAGES/django.mo new file mode 100644 index 0000000..eb86525 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/te/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/te/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/te/LC_MESSAGES/django.po new file mode 100644 index 0000000..b03f0b3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/te/LC_MESSAGES/django.po @@ -0,0 +1,258 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# bhaskar teja yerneni , 2011 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Telugu (http://www.transifex.com/django/django/language/te/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: te\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "నివాసము" + +msgid "Documentation" +msgstr "పత్రికీకరణ" + +msgid "Bookmarklets" +msgstr "నిర్దుష్ట గుర్తులు " + +msgid "Documentation bookmarklets" +msgstr "పత్రికీకరణ యొక్క నిర్దుష్ట గుర్తులు " + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "ఈ పొరటుకు పత్రికీకరణ" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" + +msgid "Tags" +msgstr "" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "టాగ్:" + +msgid "filter:" +msgstr "వడపోత:" + +msgid "view:" +msgstr "దర్శనం:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "" + +msgid "model:" +msgstr "మొడల్:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "సంబంధించిన `%(app_label)s.%(data_type)s` అంశము" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "సంబంధించిన `%(app_label)s.%(object_name)s` వస్తువులు" + +#, python-format +msgid "all %s" +msgstr "ఆన్నీ %s" + +#, python-format +msgid "number of %s" +msgstr "%s సంఖ్య" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s యు ఆర్ యల్ నిర్మాణక్రమ అంశము లా లేదు " diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/tg/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/tg/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f906516 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/tg/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/tg/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/tg/LC_MESSAGES/django.po new file mode 100644 index 0000000..58fdd30 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/tg/LC_MESSAGES/django.po @@ -0,0 +1,281 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Surush Sufiew , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-05-15 00:08+0000\n" +"Last-Translator: Surush Sufiew \n" +"Language-Team: Tajik (http://www.transifex.com/django/django/language/tg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "Хуччатгузории рохбарият" + +msgid "Home" +msgstr "Асосӣ" + +msgid "Documentation" +msgstr "Хуҷҷатгузорӣ" + +msgid "Bookmarklets" +msgstr "Гузориш" + +msgid "Documentation bookmarklets" +msgstr "Хуҷҷатгузорӣ" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Барои ба панели гузоришот ворид сохтани сурогаи сомонаи мазкур ба равзанаи " +"гузоришот ,бо пахши тугмаи чапи муш сурогаро дохил кунед.Акнун шумо аз " +"тамоми саҳифаҳои сомона ба ин суроға дастрасӣ пайдо кардед." + +msgid "Documentation for this page" +msgstr "Хуҷҷатгузорӣ барои саҳифаи мазкур" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Аз тамоми саҳифаҳо бв ҳуҷҷатгузории view, ки ин саҳифаро табдил медиҳад, " +"раҳнамоӣ месозад" + +msgid "Tags" +msgstr "Тегҳо" + +msgid "List of all the template tags and their functions." +msgstr "Руйхати хама template -ҳо ва функқияи онхо" + +msgid "Filters" +msgstr "Поло-ҳо (Filters)" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Полоҳо(Filters) - ин амалиётест ,ки барои тағйирдиҳии инъикоси шаблонҳо иҷро " +"мешавад" + +msgid "Models" +msgstr "Моделҳо" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Моделҳо - ин рӯйхати ҳамаи объектҳо ва майдонҳои ба онҳо алоқандӣ дар " +"система мавҷудбуда аст.Ҳар як модел руйхати майдонҳои худро дорад, ки дар " +"шаблонҳо ба сифати тағйирёбанда истифода бурда мешаванд." + +msgid "Views" +msgstr "View" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Ҳар як саҳифаи сомона тавассути view сохта мешавад. View муайян месозад, ки " +"кадом шаблон барои сохтанисаҳифа истифода мешавад ва кадом кадом объектҳо " +"дар он дастрасанд." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Асбобҳо барои браузери шумо, барои дастрасии зуд ба қисми маъмурияти " +"сомона(Гузоришот)" + +msgid "Please install docutils" +msgstr "Хоҳиш менамоем, docutil-ро танзим(install) кунед" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" +"Барои фаъолияти маъмурияти системаи ҳуҷҷатгузорӣ, бояд пакетҳои docutils -b Pythonтанзим карда шуда бошанд." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Хоҳишмандем аз маъмурият дархости танзими docutils -" +"ро кунед." + +#, python-format +msgid "Model: %(name)s" +msgstr "Модел: %(name)s" + +msgid "Fields" +msgstr "Майдонҳо" + +msgid "Field" +msgstr "Майдон" + +msgid "Type" +msgstr "Намуд" + +msgid "Description" +msgstr "Тавсиф" + +msgid "Methods with arguments" +msgstr "Усулҳо бо санадҳо" + +msgid "Method" +msgstr "Усул" + +msgid "Arguments" +msgstr "Санадҳо" + +msgid "Back to Model documentation" +msgstr "Ба қафо, ба қисми ҳуҷҷатгузории моделҳо" + +msgid "Model documentation" +msgstr "Ҳуҷҷатгузории моделҳо" + +msgid "Model groups" +msgstr "Гурӯҳы моделҳо" + +msgid "Templates" +msgstr "Нусхаҳо" + +#, python-format +msgid "Template: %(name)s" +msgstr "Нусхаи: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "" + +msgid "(does not exist)" +msgstr "(вуҷуд надорад)" + +msgid "Back to Documentation" +msgstr "Ба қафо, ба қисми ҳуҷҷатгузорӣ" + +msgid "Template filters" +msgstr "Полоҳо(Filters)-и нусхаҳо" + +msgid "Template filter documentation" +msgstr "Нусхаи ҳуҷҷатгузории полоҳо" + +msgid "Built-in filters" +msgstr "Бо полоҳо(filters) сохташуда." + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Барои истифодаи ин поло(filter), %(code)s - ро дар нусхаи худ " +"бо истифода аз полоҳо (Filters) ҷой диҳед." + +msgid "Template tags" +msgstr "Теги шаблонов" + +msgid "Template tag documentation" +msgstr "Ҳуҷатгузории нусхаи тегҳо" + +msgid "Built-in tags" +msgstr "Тегҳои сохташуда" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "View: %(name)s" + +msgid "Context:" +msgstr "Контекст:" + +msgid "Templates:" +msgstr "Нусхаҳо:" + +msgid "Back to View documentation" +msgstr "Ба қафо ба қисми намоиш(View)" + +msgid "View documentation" +msgstr "Ҳуҷҷатгузории view" + +msgid "Jump to namespace" +msgstr "Гузариш ба майдони номҳо" + +msgid "Empty namespace" +msgstr "Майдони номҳои фарох" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "View дар майдони номҳо %(name)s" + +msgid "Views by empty namespace" +msgstr "View дар майдони номҳои фарох" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"View-функсия: %(full_name)s. Номи url-нусхаҳо: " +"%(url_name)s.\n" + +msgid "tag:" +msgstr "тег:" + +msgid "filter:" +msgstr "Поло(filter):" + +msgid "view:" +msgstr "view:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Барномаи «%(app_label)r» ёфт нашуд" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Модели %(model_name)r дар барномаи %(app_label)r ёфт нашуд" + +msgid "model:" +msgstr "модел:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "Объектҳои вобаста `%(app_label)s.%(data_type)s` " + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "Объектҳои алоқаманд `%(app_label)s.%(object_name)s`" + +#, python-format +msgid "all %s" +msgstr "ҳамаи %s" + +#, python-format +msgid "number of %s" +msgstr "миқдори %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s ба объекти urlpattern монанд нест." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/th/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/th/LC_MESSAGES/django.mo new file mode 100644 index 0000000..23adcdd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/th/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/th/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/th/LC_MESSAGES/django.po new file mode 100644 index 0000000..f165ce2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/th/LC_MESSAGES/django.po @@ -0,0 +1,258 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Vichai Vongvorakul , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Thai (http://www.transifex.com/django/django/language/th/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: th\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "หน้าหลัก" + +msgid "Documentation" +msgstr "เอกสารประกอบ" + +msgid "Bookmarklets" +msgstr "Bookmarklets" + +msgid "Documentation bookmarklets" +msgstr "Documentation bookmarklets" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "เอกสารสำหรับหน้านี้" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "ย้ายจากทุกหน้าไปที่วิวที่สร้างหน้านั้นขึ้นมา" + +msgid "Tags" +msgstr "Tags:" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "Filters" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "Models" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "View" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "Templates" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "ป้ายกำกับ:" + +msgid "filter:" +msgstr "ตัวกรอง:" + +msgid "view:" +msgstr "ดู:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "ไม่พบโมเดล %(model_name)r ในแอป %(app_label)r" + +msgid "model:" +msgstr "โมเดล:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "ความสัมพันธ์`%(app_label)s.%(data_type)s` อ็อบเจ็กต์" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "ความสัมพันธ์`%(app_label)s.%(object_name)s` อ็อบเจ็กต์" + +#, python-format +msgid "all %s" +msgstr "ทั้งหมด %s " + +#, python-format +msgid "number of %s" +msgstr "จำนวนของ %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s ดูเหมือนจะไม่ใช่ urlpattern อ็อบเจ็กต์" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/tr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/tr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f8752e1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/tr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/tr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/tr/LC_MESSAGES/django.po new file mode 100644 index 0000000..dcb2f9b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/tr/LC_MESSAGES/django.po @@ -0,0 +1,287 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ahmet Emre Aladağ , 2013 +# BouRock, 2015-2016,2019,2021 +# BouRock, 2014 +# Jannis Leidel , 2011 +# Murat Çorlu , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-01-16 19:32+0000\n" +"Last-Translator: BouRock\n" +"Language-Team: Turkish (http://www.transifex.com/django/django/language/" +"tr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Administrative Documentation" +msgstr "Yönetimsel Belgeler" + +msgid "Home" +msgstr "Giriş" + +msgid "Documentation" +msgstr "Belgeler" + +msgid "Bookmarklets" +msgstr "Kod içeren yer işaretşeri" + +msgid "Documentation bookmarklets" +msgstr "Belge kod içeren yer işaretleri" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Kod içeren yer işaretlerini yüklemek için bağlantıyı yer imleri araç " +"çubuğuna sürükleyin ya da bağlantıya sağ tıklayın ve yer imlerinize ekleyin. " +"Artık sitedeki herhangi bir sayfadan kod içeren yer işaretini seçebilirsiniz." + +msgid "Documentation for this page" +msgstr "Bu sayfa için belgeler" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Sizi, bu sayfayı oluşturan görünüm için herhangi bir sayfadan belgelere " +"atlatır." + +msgid "Tags" +msgstr "Etiketler" + +msgid "List of all the template tags and their functions." +msgstr "Tüm şablon etiketlerinin ve işlevlerinin listesi." + +msgid "Filters" +msgstr "Süzgeçler" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Süzgeçler, çıktıyı değiştirmek için bir şablondaki değişkenlere " +"uygulanabilen eylemlerdir." + +msgid "Models" +msgstr "Modeller" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Modeller, sistemdeki nesnelerin ve ilişkilendirilmiş alanlarının tümünün " +"tanımlarıdır. Her model, şablon değişkenleri olarak erişilebilen alanların " +"bir listesine sahiptir." + +msgid "Views" +msgstr "Görünümler" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Ortak sitedeki her sayfa, bir görünüm tarafından oluşturulur. Görünüm, " +"sayfayı oluşturmak için hangi şablonun kullanılacağını ve bu şablon için " +"hangi nesnelerin kullanılabilir olacağını tanımlar." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Tarayıcınızın yönetici işlevselliğine hızlıca erişebilmesi için araçlar" + +msgid "Please install docutils" +msgstr "Lütfen docutils’i yükleyin" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Yönetici belge sistemi, Python’un docutils " +"kütüphanesini gerektirir." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Lütfen yöneticilerinizden docutils yüklemesini " +"isteyin." + +#, python-format +msgid "Model: %(name)s" +msgstr "Model: %(name)s" + +msgid "Fields" +msgstr "Alanlar" + +msgid "Field" +msgstr "Alan" + +msgid "Type" +msgstr "Tür" + +msgid "Description" +msgstr "Açıklama" + +msgid "Methods with arguments" +msgstr "Bağımsız değişkenleri olan yöntemler" + +msgid "Method" +msgstr "Yöntem" + +msgid "Arguments" +msgstr "Bağımsız değişkenler" + +msgid "Back to Model documentation" +msgstr "Model belgelerine geri dön" + +msgid "Model documentation" +msgstr "Model belgeleri" + +msgid "Model groups" +msgstr "Model grupları" + +msgid "Templates" +msgstr "Şablonlar" + +#, python-format +msgid "Template: %(name)s" +msgstr "Şablon: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Şablon: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "%(name)s şablonu için arama yolu:" + +msgid "(does not exist)" +msgstr "(mevcut değil)" + +msgid "Back to Documentation" +msgstr "Belgelere Geri Dön" + +msgid "Template filters" +msgstr "Şablon süzgeçleri" + +msgid "Template filter documentation" +msgstr "Şablon süzgeci belgeleri" + +msgid "Built-in filters" +msgstr "Yerleşik süzgeçler" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Bu süzgeçleri kullanmak için, süzgeci kullanmadan önce şablonunuzun içine " +"%(code)s yerleştirin." + +msgid "Template tags" +msgstr "Şablon etiketleri" + +msgid "Template tag documentation" +msgstr "Şablon etiketi belgeleri" + +msgid "Built-in tags" +msgstr "Yerleşik etiketler" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Bu etiketleri kullanmak için, etiketi kullanmadan önce şablonunuzun içine " +"%(code)s yerleştirin." + +#, python-format +msgid "View: %(name)s" +msgstr "Görünüm: %(name)s" + +msgid "Context:" +msgstr "Bağlam:" + +msgid "Templates:" +msgstr "Şablonlar:" + +msgid "Back to View documentation" +msgstr "Görünüm belgelerine geri dön" + +msgid "View documentation" +msgstr "Belgeleri görüntüle" + +msgid "Jump to namespace" +msgstr "İsim alanına atla" + +msgid "Empty namespace" +msgstr "Boş isim alanı" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "%(name)s isim alanına göre görünümler" + +msgid "Views by empty namespace" +msgstr "Boş isim alanına göre görünümler" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +" Görünüm işlevi: %(full_name)s. Adı: %(url_name)s.\n" + +msgid "tag:" +msgstr "etiket:" + +msgid "filter:" +msgstr "süzgeç:" + +msgid "view:" +msgstr "görünüm:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "%(app_label)r uygulaması bulunamadı" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "%(app_label)r uygulamasında %(model_name)r modeli bulunamadı" + +msgid "model:" +msgstr "model:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "İlgili `%(app_label)s.%(data_type)s` nesnesi" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "ilgili `%(app_label)s.%(object_name)s` nesneleri" + +#, python-format +msgid "all %s" +msgstr "tüm %s" + +#, python-format +msgid "number of %s" +msgstr "%s sayısı" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s, bir urlpattern nesnesi olarak görünmüyor" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/tt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/tt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..83b6d94 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/tt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/tt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/tt/LC_MESSAGES/django.po new file mode 100644 index 0000000..0e38bdb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/tt/LC_MESSAGES/django.po @@ -0,0 +1,259 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Azat Khasanshin , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Tatar (http://www.transifex.com/django/django/language/tt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tt\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "Өй" + +msgid "Documentation" +msgstr "Документация" + +msgid "Bookmarklets" +msgstr "Кыстыргычлар" + +msgid "Documentation bookmarklets" +msgstr "Документация кыстыргычлары" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "Бу сәхифә өчен документация" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Теләсә нинди сәхифәдән сезне ул сәхифәне төзи торган view документациясенә " +"җибәрә." + +msgid "Tags" +msgstr "" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "билге:" + +msgid "filter:" +msgstr "фильтр:" + +msgid "view:" +msgstr "күрсәтелеш:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "%(model_name)r моделе %(app_label)r кушымтасында табылмаган" + +msgid "model:" +msgstr "модель:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "бәйләнгән '%(app_label)s.%(data_type)s' объект" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "бәйләнгән '%(app_label)s.%(object_name)s' объектлар" + +#, python-format +msgid "all %s" +msgstr "бөтен %s" + +#, python-format +msgid "number of %s" +msgstr "%s саны" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s urlpattern объектына ошамаган" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/udm/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/udm/LC_MESSAGES/django.mo new file mode 100644 index 0000000..509c1e9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/udm/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/udm/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/udm/LC_MESSAGES/django.po new file mode 100644 index 0000000..5a54ef3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/udm/LC_MESSAGES/django.po @@ -0,0 +1,275 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2015-01-18 08:34+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Udmurt (http://www.transifex.com/projects/p/django/language/" +"udm/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: udm\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "" + +msgid "Documentation" +msgstr "" + +msgid "Bookmarklets" +msgstr "" + +msgid "Documentation bookmarklets" +msgstr "" + +msgid "" +"\n" +"

    To install bookmarklets, drag the link to your bookmarks\n" +"toolbar, or right-click the link and add it to your bookmarks. Now you can\n" +"select the bookmarklet from any page in the site. Note that some of these\n" +"bookmarklets require you to be viewing the site from a computer designated\n" +"as \"internal\" (talk to your system administrator if you aren't sure if\n" +"your computer is \"internal\").

    \n" +msgstr "" + +msgid "Documentation for this page" +msgstr "" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" + +msgid "Show object ID" +msgstr "" + +msgid "" +"Shows the content-type and unique ID for pages that represent a single " +"object." +msgstr "" + +msgid "Edit this object (current window)" +msgstr "" + +msgid "Jumps to the admin page for pages that represent a single object." +msgstr "" + +msgid "Edit this object (new window)" +msgstr "" + +msgid "As above, but opens the admin page in a new window." +msgstr "" + +msgid "Tags" +msgstr "" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Back to Model Documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to Views Documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "Boolean (Either True or False)" +msgstr "True яке False" + +#, python-format +msgid "Field of type: %(field_type)s" +msgstr "%(field_type)s типъем бусы" + +msgid "tag:" +msgstr "" + +msgid "filter:" +msgstr "" + +msgid "view:" +msgstr "" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "" + +msgid "model:" +msgstr "" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "" + +#, python-format +msgid "all %s" +msgstr "" + +#, python-format +msgid "number of %s" +msgstr "" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ug/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ug/LC_MESSAGES/django.mo new file mode 100644 index 0000000..88ae816 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ug/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ug/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ug/LC_MESSAGES/django.po new file mode 100644 index 0000000..b19161e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ug/LC_MESSAGES/django.po @@ -0,0 +1,280 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Abduqadir Abliz , 2023 +# Azat, 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2023-12-04 20:19+0000\n" +"Last-Translator: Azat, 2023\n" +"Language-Team: Uyghur (http://app.transifex.com/django/django/language/ug/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ug\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "باشقۇرۇش قوللانمىسى" + +msgid "Home" +msgstr "باش بەت" + +msgid "Documentation" +msgstr "قوللانمىلار" + +msgid "Bookmarklets" +msgstr "خەتكۈچلەر" + +msgid "Documentation bookmarklets" +msgstr "قوللانما خەتكۈچلىرى" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"خەتكۈچنى ئورنىتىش ئۈچۈن، ئۇلانمىنى خەتكۈچ ئىشارىتىڭىزگە سۆرۈڭ ياكى ئۇلانمىنى " +"ئوڭ تېكشۈرۈپ خەتكۈچكە قوشۇڭ. ھازىر سىز تور بېكەتتىكى ھەرقايسى بەتتىن " +"خەتكۈچنى تاللىيالايسىز." + +msgid "Documentation for this page" +msgstr "بۇ بەتنىڭ قوللانما ھۆججىتى" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "ھەرقايسى بەتتىن سىزنى ئۇ بەتنىڭ قوللانما كۆرۈنۈش ھۆججىتىغا ئاتلىدۇ." + +msgid "Tags" +msgstr "خەتكۈچلەر" + +msgid "List of all the template tags and their functions." +msgstr "بارلىق قېلىپ خەتكۈچلىرى ۋە ئۇلارنىڭ ئىقتىدارلىرى تىزىملىكى." + +msgid "Filters" +msgstr "سۈزگۈچ" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"سۈزگۈچ نەتىجىنى ئۆزگەرتىش ئۈچۈن قېلىپدىكى ئۆزگەرگۈچى مىقدارلارغا " +"قوللىنىلىدىغان ھەرىكەتلەر." + +msgid "Models" +msgstr "ئەندىزەلەر" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"مودېللار سىستېمىدىكى بارلىق جىسىملارنىڭ ۋە ئۇلارنىڭ مۇناسىۋەتلىك ساھەلىرىنىڭ " +"تەسۋىرى. ھەر بىر مودېلنىڭ قېلىپ ئۆزگەرگۈچى مىقدار سۈپىتىدە زىيارەت قىلغىلى " +"بولىدىغان ساھە تىزىملىكى بار" + +msgid "Views" +msgstr "كۆرۈنۈشلەر" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"ئاممىۋى تور بېكەتتىكى ھەر بىر بەت كۆرۈنۈش ئارقىلىق ھاسىل بولىدۇ. كۆرۈنۈشتە " +"قايسى قېلىپنىڭ بەت ھاسىل قىلىشتا ئىشلىتىلىدىغانلىقى ۋە قايسى قېلىپلارنىڭ شۇ " +"قېلىپقا ئىشلىتىلىدىغانلىقىنى بەلگىلەيدۇ." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "تور كۆرگۈچىڭىزنىڭ باشقۇرۇش ئىقتىدارىنى تېز زىيارەت قىلىدىغان قوراللار." + +msgid "Please install docutils" +msgstr "docutils نى قاچىلاڭ" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"باشقۇرغۇچى ھۆججەت سىستېمىسى Python نىڭdocutils1 " +"كۈتۈپخانىسىنى تەلەپ قىلىدۇ." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"باشقۇرغۇچىلىرىڭىزدىن docutils نى قاچىلاشنى تەلەپ " +"قىلىڭ." + +#, python-format +msgid "Model: %(name)s" +msgstr "مودېل: %(name)s" + +msgid "Fields" +msgstr "سۆز بۆلىكى" + +msgid "Field" +msgstr "سۆز بۆلىكى" + +msgid "Type" +msgstr "تىپى" + +msgid "Description" +msgstr "چۈشەندۈرۈش" + +msgid "Methods with arguments" +msgstr "ئارگۇمېنىتى بار مېتودلار" + +msgid "Method" +msgstr "چارە" + +msgid "Arguments" +msgstr "ئۆزگەرگۈچىلەر" + +msgid "Back to Model documentation" +msgstr "مودېل ھۆججىتىگە قايتىڭ" + +msgid "Model documentation" +msgstr "مودېل ھۆججىتى" + +msgid "Model groups" +msgstr "ئەندىزە گۇرۇپپىلىرى" + +msgid "Templates" +msgstr "قېلىپلار" + +#, python-format +msgid "Template: %(name)s" +msgstr "قېلىپ: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "قېلىپ: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "قېلىپنىڭ ئىزدەش يولى: %(name)s" + +msgid "(does not exist)" +msgstr "(مەۋجۇت ئەمەس)" + +msgid "Back to Documentation" +msgstr "ھۆججەتكە قايتىش" + +msgid "Template filters" +msgstr "قېلىپ سۈزگۈچلىرى" + +msgid "Template filter documentation" +msgstr "قېلىپ سۈزگۈچ ھۆججىتى" + +msgid "Built-in filters" +msgstr "ئىچكى سۈزگۈچ" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"بۇ سۈزگۈچلەرنى ئىشلىتىش ئۈچۈن سۈزگۈچنى ئىشلىتىشتىن بۇرۇن قېلىپقا " +"%(code)s قويۇڭ." + +msgid "Template tags" +msgstr "قېلىپ خەتكۈچلىرى" + +msgid "Template tag documentation" +msgstr "قېلىپ بەلگىلەر ھۆججىتى" + +msgid "Built-in tags" +msgstr "ئىچكى بەلگىلەر" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"بۇ بەلگىلەرنى ئىشلىتىش ئۈچۈن ، خەتكۈچنى ئىشلىتىشتىن بۇرۇن قېلىپقا " +"%(code)s قويۇڭ." + +#, python-format +msgid "View: %(name)s" +msgstr "كۆرۈنۈش: %(name)s" + +msgid "Context:" +msgstr "تىل مۇھىتى:" + +msgid "Templates:" +msgstr "قېلىپلار:" + +msgid "Back to View documentation" +msgstr "ھۆججەتلەرنى كۆرۈش" + +msgid "View documentation" +msgstr "ھۆججەتلەرنى كۆرۈش" + +msgid "Jump to namespace" +msgstr "ئىسىم بوشلۇقىغا ئاتلاڭ" + +msgid "Empty namespace" +msgstr "ئىسىم بوشلۇقى بوش" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "ئىسىم بوشلۇقىدىكى كۆرۈنۈش %(name)s" + +msgid "Views by empty namespace" +msgstr "قۇرۇق ئىسىم بوشلۇقىدىكى كۆرۈنۈشلەر" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" + +msgid "tag:" +msgstr "بەلگە:" + +msgid "filter:" +msgstr "سۈزگۈچ:" + +msgid "view:" +msgstr "كۆرۈنۈش:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "ئەپ %(app_label)r تېپىلمىدى" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Model %(model_name)r not found in app %(app_label)r" + +msgid "model:" +msgstr "ئەندىزە:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "the related `%(app_label)s.%(data_type)s` object" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "related `%(app_label)s.%(object_name)s` objects" + +#, python-format +msgid "all %s" +msgstr "ھەممە %s" + +#, python-format +msgid "number of %s" +msgstr "%sنىڭ سانى" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s urlpattern ئوبىيكتى ئەمەستەك كۆرۈنىدۇ." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/uk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/uk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..76e5f11 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/uk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/uk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/uk/LC_MESSAGES/django.po new file mode 100644 index 0000000..dc91383 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/uk/LC_MESSAGES/django.po @@ -0,0 +1,294 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Oleksandr Chernihov , 2014 +# Andriy Sokolovskiy , 2015 +# Denis Podlesniy , 2016 +# Illia Volochii , 2021 +# Jannis Leidel , 2011 +# Kirill Gagarski , 2016 +# Max V. Stotsky , 2014 +# Sergey Lysach , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-01-20 00:21+0000\n" +"Last-Translator: Illia Volochii \n" +"Language-Team: Ukrainian (http://www.transifex.com/django/django/language/" +"uk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: uk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != " +"11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % " +"100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || " +"(n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n" + +msgid "Administrative Documentation" +msgstr "Адміністративна документація" + +msgid "Home" +msgstr "Домівка" + +msgid "Documentation" +msgstr "Документація" + +msgid "Bookmarklets" +msgstr "Інтерактивні закладки" + +msgid "Documentation bookmarklets" +msgstr "Інтерактивні закладки документації" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"Щоб встановити bookmarklets, перетягніть посилання на вашу bookmarklets або " +"клацніть правою кнопкою миші по посиланню і додайте його в bookmarklets. " +"Тепер ви можете вибрати bookmarklets з будь-якої сторінки сайту." + +msgid "Documentation for this page" +msgstr "Документація для цієї сторінки" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"Перекидає вас з будь-якої сторінки в документацію для відображення, що " +"сгенерувало цю сторінку." + +msgid "Tags" +msgstr "Теги" + +msgid "List of all the template tags and their functions." +msgstr "Список усіх тегів шаблонів та їх функцій." + +msgid "Filters" +msgstr "Фільтри" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" +"Фільтри - це дії, які можуть бути виконані над змінними в шаблоні, щоб " +"змінити їх відображення." + +msgid "Models" +msgstr "Моделі" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"Моделі - це описання всіх об'єктів системи та пов'язаних з ними полів.\n" +"Кожна модель має список полів що можуть бути доступні у вигляді змінних в " +"шаблонах." + +msgid "Views" +msgstr "Відображення" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"Кожна сторінка для відкритого сайту створена за допомогою відображення." +"Відображення визначає, який шаблон використовується для генерації сторінки " +"та об'єкти, які доступні для цього шаблону." + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" +"Інструменти для вашого браузеру для швидкого доступу до адміністративних " +"функцій." + +msgid "Please install docutils" +msgstr "Будь ласка, встановіть docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "" +"Система адміністративної документації вимагає Python-бібліотеку docutils." + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" +"Будь ласка, попросить вашого адміністратора встановити docutils." + +#, python-format +msgid "Model: %(name)s" +msgstr "Модель: %(name)s" + +msgid "Fields" +msgstr "Поля" + +msgid "Field" +msgstr "Поле" + +msgid "Type" +msgstr "Тип" + +msgid "Description" +msgstr "Опис" + +msgid "Methods with arguments" +msgstr "Методи з аргументами" + +msgid "Method" +msgstr "Метод" + +msgid "Arguments" +msgstr "Аргументи" + +msgid "Back to Model documentation" +msgstr "Назад до Документація моделі" + +msgid "Model documentation" +msgstr "Документація моделі" + +msgid "Model groups" +msgstr "Групи моделей" + +msgid "Templates" +msgstr "Шаблони" + +#, python-format +msgid "Template: %(name)s" +msgstr "Шаблон: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "Шаблон: %(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "Шлях для пошуку шаблону %(name)s:" + +msgid "(does not exist)" +msgstr "(не існує)" + +msgid "Back to Documentation" +msgstr "Назад до Документації" + +msgid "Template filters" +msgstr "Фільтри у шаблонах" + +msgid "Template filter documentation" +msgstr "Документація фільтрів у шаблонах" + +msgid "Built-in filters" +msgstr "Вбудовані фільтри" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"Щоб використовувати ці фільтри, помістіть %(code)s в ваш шаблон " +"перед використанням фільтру." + +msgid "Template tags" +msgstr "Теги шаблонів" + +msgid "Template tag documentation" +msgstr "Документація по тегам шаблонів" + +msgid "Built-in tags" +msgstr "Вбудовані теги" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"Щоб використовувати ці теги, помістіть %(code)s в ваш шаблон " +"перед використанням тегу." + +#, python-format +msgid "View: %(name)s" +msgstr "Відображення: %(name)s" + +msgid "Context:" +msgstr "Контекст:" + +msgid "Templates:" +msgstr "Шаблони:" + +msgid "Back to View documentation" +msgstr "Назад до Переглянути документацію" + +msgid "View documentation" +msgstr "Переглянути документацію" + +msgid "Jump to namespace" +msgstr "Перейти до іменованої зони" + +msgid "Empty namespace" +msgstr "Порожня іменована зона" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "Відображення у просторі імен %(name)s" + +msgid "Views by empty namespace" +msgstr "Відображення у глобальному просторі імен " + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"Функція відображення: %(full_name)s. Им'я: %(url_name)s.\n" + +msgid "tag:" +msgstr "тег:" + +msgid "filter:" +msgstr "відфільтрувати:" + +msgid "view:" +msgstr "переглянути:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "Застосунок %(app_label)r не знайдено" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Модель %(model_name)r не знайдено в прикладній системі %(app_label)r" + +msgid "model:" +msgstr "модель:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "пов'язаний `%(app_label)s.%(data_type)s` об'єкт" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "пов'язані з `%(app_label)s.%(object_name)s` об'єкти" + +#, python-format +msgid "all %s" +msgstr "всі %s" + +#, python-format +msgid "number of %s" +msgstr "кількість з %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s не є об'єктом urlpattern" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ur/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ur/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d945bd1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ur/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ur/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ur/LC_MESSAGES/django.po new file mode 100644 index 0000000..c15800a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/ur/LC_MESSAGES/django.po @@ -0,0 +1,259 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Mansoorulhaq Mansoor , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Urdu (http://www.transifex.com/django/django/language/ur/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ur\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "صفحۂ اول" + +msgid "Documentation" +msgstr "طریق استعمال" + +msgid "Bookmarklets" +msgstr "بک مارک لیٹس" + +msgid "Documentation bookmarklets" +msgstr "طریق استعمال کے بک مارک لیٹس" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "اس صفحے کا طریق استعمال" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" +"آپ کو لے جاتا ہے کسی بھی صفحے سے طریق استعمال کی طرف اس ویو کے لئے جو اس " +"صفحے کو بناتا ہے۔" + +msgid "Tags" +msgstr "" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "ٹیگ :" + +msgid "filter:" +msgstr "فلٹر:" + +msgid "view:" +msgstr "ویو:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "ماڈل %(model_name)r ایپ %(app_label)r میں نہیں ملا" + +msgid "model:" +msgstr "model:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "متعلقہ `%(app_label)s.%(data_type)s`اوبجیکٹ" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "متعلقہ `%(app_label)s.%(object_name)s` اوبجیکٹس" + +#, python-format +msgid "all %s" +msgstr "تمام %s" + +#, python-format +msgid "number of %s" +msgstr "%sکی تعداد " + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s بطور urlpattern ظاہر نہیں ہو رہا۔" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/vi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/vi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..52b2159 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/vi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/vi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/vi/LC_MESSAGES/django.po new file mode 100644 index 0000000..6219618 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/vi/LC_MESSAGES/django.po @@ -0,0 +1,259 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Thanh Le Viet , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Vietnamese (http://www.transifex.com/django/django/language/" +"vi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: vi\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Administrative Documentation" +msgstr "" + +msgid "Home" +msgstr "Trang chủ" + +msgid "Documentation" +msgstr "Tài liệu" + +msgid "Bookmarklets" +msgstr "" + +msgid "Documentation bookmarklets" +msgstr "" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" + +msgid "Documentation for this page" +msgstr "Tài liệu cho trang này" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "" + +msgid "Tags" +msgstr "Thẻ" + +msgid "List of all the template tags and their functions." +msgstr "" + +msgid "Filters" +msgstr "Bộ lọc" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "Models" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "Xem" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "" + +msgid "Please install docutils" +msgstr "" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "" + +#, python-format +msgid "Model: %(name)s" +msgstr "" + +msgid "Fields" +msgstr "" + +msgid "Field" +msgstr "" + +msgid "Type" +msgstr "" + +msgid "Description" +msgstr "" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "" + +msgid "Arguments" +msgstr "" + +msgid "Back to Model documentation" +msgstr "" + +msgid "Model documentation" +msgstr "" + +msgid "Model groups" +msgstr "" + +msgid "Templates" +msgstr "Templates" + +#, python-format +msgid "Template: %(name)s" +msgstr "" + +#, python-format +msgid "Template: \"%(name)s\"" +msgstr "" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template \"%(name)s\":" +msgstr "" + +msgid "(does not exist)" +msgstr "" + +msgid "Back to Documentation" +msgstr "" + +msgid "Template filters" +msgstr "" + +msgid "Template filter documentation" +msgstr "" + +msgid "Built-in filters" +msgstr "" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "" + +msgid "Template tag documentation" +msgstr "" + +msgid "Built-in tags" +msgstr "" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "" + +msgid "Back to View documentation" +msgstr "" + +msgid "View documentation" +msgstr "" + +msgid "Jump to namespace" +msgstr "" + +msgid "Empty namespace" +msgstr "" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "" + +msgid "Views by empty namespace" +msgstr "" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" + +msgid "tag:" +msgstr "Nhãn:" + +msgid "filter:" +msgstr "Lọc:" + +msgid "view:" +msgstr "Xem:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "Mẫu %(model_name)r không tìm thấy trong ứng dụng %(app_label)r" + +msgid "model:" +msgstr "mẫu:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "liên quan tới đối tượng `%(app_label)s.%(object_name)s`" + +#, python-format +msgid "all %s" +msgstr "Tất cả %s" + +#, python-format +msgid "number of %s" +msgstr "số của %s" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/zh_Hans/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/zh_Hans/LC_MESSAGES/django.mo new file mode 100644 index 0000000..497df3e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/zh_Hans/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/zh_Hans/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/zh_Hans/LC_MESSAGES/django.po new file mode 100644 index 0000000..5241457 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/zh_Hans/LC_MESSAGES/django.po @@ -0,0 +1,276 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Lele Long , 2015 +# Liping Wang , 2016 +# mozillazg , 2016 +# Ronald White , 2014 +# Veoco , 2021 +# wolf ice , 2020 +# Kevin Sze , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-02-07 04:24+0000\n" +"Last-Translator: Veoco \n" +"Language-Team: Chinese (China) (http://www.transifex.com/django/django/" +"language/zh_CN/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_CN\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Administrative Documentation" +msgstr "管理文档" + +msgid "Home" +msgstr "首页" + +msgid "Documentation" +msgstr "文档" + +msgid "Bookmarklets" +msgstr "书签" + +msgid "Documentation bookmarklets" +msgstr "文档书签" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"为了安装书签,将链接拖到你的书签工具条,或者鼠标右击链接然后把它添加到你的书" +"签中。现在你可以从这个站点的任何页面选择书签。" + +msgid "Documentation for this page" +msgstr "关于本页面的文档" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "从任何页面跳转到生成该页面的 view 文档。" + +msgid "Tags" +msgstr "标签" + +msgid "List of all the template tags and their functions." +msgstr "列出所有模板标签及其功能。" + +msgid "Filters" +msgstr "过滤器" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "过滤器可以应用到模板中的变量上来动态的改变输出。" + +msgid "Models" +msgstr "模型" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" +"模型是系统中的所有的对象字段及其关联性的描述。每个模型都有其可以被模板变量访" +"问的字段列表" + +msgid "Views" +msgstr "视图" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" +"由视图生成在公共站点的每个页面。视图定义了哪些模板用于生成页面和哪些对象可用" +"于该模板。" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "工具为您的浏览器提供了快速访问和管理的功能。" + +msgid "Please install docutils" +msgstr "请安装 docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python’s docutils library." +msgstr "该管理文档系统需要 Python 的 docutils 库。" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "请询问你的管理员并安装 docutils 。" + +#, python-format +msgid "Model: %(name)s" +msgstr "模型: %(name)s" + +msgid "Fields" +msgstr "字段" + +msgid "Field" +msgstr "字段" + +msgid "Type" +msgstr "类型" + +msgid "Description" +msgstr "描述" + +msgid "Methods with arguments" +msgstr "方法和参数" + +msgid "Method" +msgstr "方法" + +msgid "Arguments" +msgstr "参数" + +msgid "Back to Model documentation" +msgstr "返回到模型文档" + +msgid "Model documentation" +msgstr "模型文档" + +msgid "Model groups" +msgstr "模型组" + +msgid "Templates" +msgstr "模板" + +#, python-format +msgid "Template: %(name)s" +msgstr "模板: %(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "模板:%(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "模板%(name)s的查找路径:" + +msgid "(does not exist)" +msgstr "(不存在)" + +msgid "Back to Documentation" +msgstr "回到文档" + +msgid "Template filters" +msgstr "模板过滤器" + +msgid "Template filter documentation" +msgstr "模板过滤器文档" + +msgid "Built-in filters" +msgstr "内置过滤器" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" +"要使用这些过滤器, 在你使用过滤器之前需要在模板中放置 %(code)s 。" + +msgid "Template tags" +msgstr "模板标签" + +msgid "Template tag documentation" +msgstr "模板标签文档" + +msgid "Built-in tags" +msgstr "内置标签" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" +"要使用这些标签, 在你使用标签之前需要在模板中放置 %(code)s 。" + +#, python-format +msgid "View: %(name)s" +msgstr "视图: %(name)s" + +msgid "Context:" +msgstr "内容:" + +msgid "Templates:" +msgstr "模板:" + +msgid "Back to View documentation" +msgstr "回到视图文档" + +msgid "View documentation" +msgstr "视图文档" + +msgid "Jump to namespace" +msgstr "跳转到命名空间" + +msgid "Empty namespace" +msgstr "空命名空间" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "按命名空间 %(name)s 排序视图" + +msgid "Views by empty namespace" +msgstr "按空命名空间排序视图" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"查看函数:%(full_name)s. 名字:%(url_name)s.\n" +"\n" + +msgid "tag:" +msgstr "标签:" + +msgid "filter:" +msgstr "过滤器:" + +msgid "view:" +msgstr "视图:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "应用 %(app_label)r 没有找到" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "在应用 %(app_label)r 里找不到模型 %(model_name)r" + +msgid "model:" +msgstr "模型:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "相关的 `%(app_label)s.%(data_type)s` 对象" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "相关的 `%(app_label)s.%(object_name)s` 对象" + +#, python-format +msgid "all %s" +msgstr "所有 %s" + +#, python-format +msgid "number of %s" +msgstr "%s 的数量" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s 似乎不是一个 urlpattern 对象" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/zh_Hant/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/zh_Hant/LC_MESSAGES/django.mo new file mode 100644 index 0000000..922dd0e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/zh_Hant/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/zh_Hant/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/zh_Hant/LC_MESSAGES/django.po new file mode 100644 index 0000000..b4060d4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/locale/zh_Hant/LC_MESSAGES/django.po @@ -0,0 +1,267 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Chen Chun-Chia , 2015 +# Jannis Leidel , 2011 +# mail6543210 , 2013 +# 619e61dbdb61c57213f62815aaf60e01, 2011 +# Tzu-ping Chung , 2016,2019 +# Yeh-Yung , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-09-18 09:05+0000\n" +"Last-Translator: Tzu-ping Chung \n" +"Language-Team: Chinese (Taiwan) (http://www.transifex.com/django/django/" +"language/zh_TW/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_TW\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Administrative Documentation" +msgstr "管理文件" + +msgid "Home" +msgstr "首頁" + +msgid "Documentation" +msgstr "文件" + +msgid "Bookmarklets" +msgstr "書籤" + +msgid "Documentation bookmarklets" +msgstr "文件 bookmarklets" + +msgid "" +"To install bookmarklets, drag the link to your bookmarks toolbar, or right-" +"click the link and add it to your bookmarks. Now you can select the " +"bookmarklet from any page in the site." +msgstr "" +"要安裝 bookmarklet,把連結拖進你的書籤工具列,或右擊該連結後新增到你的書籤" +"裡。現在你可以從網站的任何頁面來選擇 bookmarklet。" + +msgid "Documentation for this page" +msgstr "本頁面的文件" + +msgid "" +"Jumps you from any page to the documentation for the view that generates " +"that page." +msgstr "讓你跳到用來產生該頁面之檢視的任何一頁文件。" + +msgid "Tags" +msgstr "標籤" + +msgid "List of all the template tags and their functions." +msgstr "列出所有模板標籤與其函數" + +msgid "Filters" +msgstr "過濾器" + +msgid "" +"Filters are actions which can be applied to variables in a template to alter " +"the output." +msgstr "" + +msgid "Models" +msgstr "模型" + +msgid "" +"Models are descriptions of all the objects in the system and their " +"associated fields. Each model has a list of fields which can be accessed as " +"template variables" +msgstr "" + +msgid "Views" +msgstr "視圖" + +msgid "" +"Each page on the public site is generated by a view. The view defines which " +"template is used to generate the page and which objects are available to " +"that template." +msgstr "" + +msgid "Tools for your browser to quickly access admin functionality." +msgstr "方便使用管理功能的瀏覽器工具。" + +msgid "Please install docutils" +msgstr "請安裝 docutils" + +#, python-format +msgid "" +"The admin documentation system requires Python's docutils library." +msgstr "管理文件系統需要 Python 的 docutils 函式庫。" + +#, python-format +msgid "" +"Please ask your administrators to install docutils." +msgstr "請要求您的管理員安裝 docutils。" + +#, python-format +msgid "Model: %(name)s" +msgstr "模型:%(name)s" + +msgid "Fields" +msgstr "欄位" + +msgid "Field" +msgstr "欄位" + +msgid "Type" +msgstr "類別" + +msgid "Description" +msgstr "描述" + +msgid "Methods with arguments" +msgstr "" + +msgid "Method" +msgstr "方法" + +msgid "Arguments" +msgstr "參數" + +msgid "Back to Model documentation" +msgstr "回到模型文件" + +msgid "Model documentation" +msgstr "模型文件" + +msgid "Model groups" +msgstr "模型群組" + +msgid "Templates" +msgstr "模版" + +#, python-format +msgid "Template: %(name)s" +msgstr "模版:%(name)s" + +#, python-format +msgid "Template: %(name)s" +msgstr "模板:%(name)s" + +#. Translators: Search is not a verb here, it qualifies path (a search path) +#, python-format +msgid "Search path for template %(name)s:" +msgstr "搜尋模板 %(name)s 的路徑:" + +msgid "(does not exist)" +msgstr "(不存在)" + +msgid "Back to Documentation" +msgstr "回到文件" + +msgid "Template filters" +msgstr "模板過濾器" + +msgid "Template filter documentation" +msgstr "模板過濾器文件" + +msgid "Built-in filters" +msgstr "內建過濾器" + +#, python-format +msgid "" +"To use these filters, put %(code)s in your template before " +"using the filter." +msgstr "" + +msgid "Template tags" +msgstr "模版標籤" + +msgid "Template tag documentation" +msgstr "模板標籤文件" + +msgid "Built-in tags" +msgstr "內建標籤" + +#, python-format +msgid "" +"To use these tags, put %(code)s in your template before using " +"the tag." +msgstr "" + +#, python-format +msgid "View: %(name)s" +msgstr "視圖:%(name)s" + +msgid "Context:" +msgstr "" + +msgid "Templates:" +msgstr "模版:" + +msgid "Back to View documentation" +msgstr "回到視圖文件" + +msgid "View documentation" +msgstr "視圖文件" + +msgid "Jump to namespace" +msgstr "跳至名稱空間" + +msgid "Empty namespace" +msgstr "空的名稱空間" + +#, python-format +msgid "Views by namespace %(name)s" +msgstr "名稱空間 %(name)s 之視圖" + +msgid "Views by empty namespace" +msgstr "空名稱空間之視圖" + +#, python-format +msgid "" +"\n" +" View function: %(full_name)s. Name: %(url_name)s.\n" +msgstr "" +"\n" +"視圖函式:%(full_name)s,名稱:%(url_name)s\n" + +msgid "tag:" +msgstr "標籤:" + +msgid "filter:" +msgstr "過濾器:" + +msgid "view:" +msgstr "視圖:" + +#, python-format +msgid "App %(app_label)r not found" +msgstr "找不到 App %(app_label)r" + +#, python-format +msgid "Model %(model_name)r not found in app %(app_label)r" +msgstr "未在%(app_label)r 找到模組 %(model_name)r " + +msgid "model:" +msgstr "模型:" + +#, python-format +msgid "the related `%(app_label)s.%(data_type)s` object" +msgstr "有關 `%(app_label)s.%(data_type)s` 的物件" + +#, python-format +msgid "related `%(app_label)s.%(object_name)s` objects" +msgstr "有關 `%(app_label)s.%(object_name)s` 的物件" + +#, python-format +msgid "all %s" +msgstr "所有 %s" + +#, python-format +msgid "number of %s" +msgstr "%s 的数量" + +#, python-format +msgid "%s does not appear to be a urlpattern object" +msgstr "%s 似乎不是一個 urlpattern 物件" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/middleware.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/middleware.py new file mode 100644 index 0000000..5c9f08d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/middleware.py @@ -0,0 +1,33 @@ +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.http import HttpResponse +from django.utils.deprecation import MiddlewareMixin + +from .utils import get_view_name + + +class XViewMiddleware(MiddlewareMixin): + """ + Add an X-View header to internal HEAD requests. + """ + + def process_view(self, request, view_func, view_args, view_kwargs): + """ + If the request method is HEAD and either the IP is internal or the + user is a logged-in staff member, return a response with an x-view + header indicating the view function. This is used to lookup the view + function for an arbitrary page. + """ + if not hasattr(request, "user"): + raise ImproperlyConfigured( + "The XView middleware requires authentication middleware to " + "be installed. Edit your MIDDLEWARE setting to insert " + "'django.contrib.auth.middleware.AuthenticationMiddleware'." + ) + if request.method == "HEAD" and ( + request.META.get("REMOTE_ADDR") in settings.INTERNAL_IPS + or (request.user.is_active and request.user.is_staff) + ): + response = HttpResponse() + response.headers["X-View"] = get_view_name(view_func) + return response diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/bookmarklets.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/bookmarklets.html new file mode 100644 index 0000000..04b329e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/bookmarklets.html @@ -0,0 +1,26 @@ +{% extends "admin/base_site.html" %} +{% load i18n %} + +{% block breadcrumbs %} + +{% endblock %} +{% block title %}{% translate "Documentation bookmarklets" %}{% endblock %} + +{% block content %} + +

    {% blocktranslate trimmed %} +To install bookmarklets, drag the link to your bookmarks toolbar, or right-click +the link and add it to your bookmarks. Now you can select the bookmarklet +from any page in the site. +{% endblocktranslate %}

    + +
    +

    {% translate "Documentation for this page" %}

    +

    {% translate "Jumps you from any page to the documentation for the view that generates that page." %}

    +
    + +{% endblock %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/index.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/index.html new file mode 100644 index 0000000..1b95a21 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/index.html @@ -0,0 +1,34 @@ +{% extends "admin/base_site.html" %} +{% load i18n %} + +{% block breadcrumbs %} + +{% endblock %} +{% block title %}{% translate 'Documentation' %}{% endblock %} + +{% block content %} + +

    {% translate 'Documentation' %}

    + +
    +

    {% translate 'Tags' %}

    +

    {% translate 'List of all the template tags and their functions.' %}

    + +

    {% translate 'Filters' %}

    +

    {% translate 'Filters are actions which can be applied to variables in a template to alter the output.' %}

    + +

    {% translate 'Models' %}

    +

    {% translate 'Models are descriptions of all the objects in the system and their associated fields. Each model has a list of fields which can be accessed as template variables' %}.

    + +

    {% translate 'Views' %}

    +

    {% translate 'Each page on the public site is generated by a view. The view defines which template is used to generate the page and which objects are available to that template.' %}

    + +

    {% translate 'Bookmarklets' %}

    +

    {% translate 'Tools for your browser to quickly access admin functionality.' %}

    +
    + +{% endblock %} + diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/missing_docutils.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/missing_docutils.html new file mode 100644 index 0000000..56c063b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/missing_docutils.html @@ -0,0 +1,22 @@ +{% extends "admin/base_site.html" %} +{% load i18n %} + +{% block breadcrumbs %} + +{% endblock %} +{% block title %}{% translate 'Please install docutils' %}{% endblock %} + +{% block content %} + +

    {% translate 'Documentation' %}

    + +
    +

    {% blocktranslate with "https://docutils.sourceforge.io/" as link %}The admin documentation system requires Python’s docutils library.{% endblocktranslate %}

    + +

    {% blocktranslate with "https://pypi.org/project/docutils/" as link %}Please ask your administrators to install docutils.{% endblocktranslate %}

    +
    + +{% endblock %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/model_detail.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/model_detail.html new file mode 100644 index 0000000..ebeeafc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/model_detail.html @@ -0,0 +1,78 @@ +{% extends "admin/base_site.html" %} +{% load i18n %} + +{% block extrahead %} +{{ block.super }} + +{% endblock %} + +{% block breadcrumbs %} + +{% endblock %} + +{% block title %}{% blocktranslate %}Model: {{ name }}{% endblocktranslate %}{% endblock %} + +{% block content %} +
    +

    {{ name }}

    +

    {{ summary }}

    + +{{ description }} + +

    {% translate 'Fields' %}

    +
    + + + + + + + + + +{% for field in fields|dictsort:"name" %} + + + + + +{% endfor %} + +
    {% translate 'Field' %}{% translate 'Type' %}{% translate 'Description' %}
    {{ field.name }}{{ field.data_type }}{{ field.verbose }}{% if field.help_text %} - {{ field.help_text|safe }}{% endif %}
    +
    + +{% if methods %} +

    {% translate 'Methods with arguments' %}

    +
    + + + + + + + + + +{% for method in methods|dictsort:"name" %} + + + + + +{% endfor %} + +
    {% translate 'Method' %}{% translate 'Arguments' %}{% translate 'Description' %}
    {{ method.name }}{{ method.arguments }}{{ method.verbose }}
    +
    +{% endif %} + +

    ‹ {% translate 'Back to Model documentation' %}

    +
    +{% endblock %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/model_index.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/model_index.html new file mode 100644 index 0000000..2342be4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/model_index.html @@ -0,0 +1,52 @@ +{% extends "admin/base_site.html" %} +{% load i18n %} + +{% block coltype %}colSM{% endblock %} + +{% block breadcrumbs %} + +{% endblock %} + +{% block title %}{% translate 'Models' %}{% endblock %} + +{% block content %} + +

    {% translate 'Model documentation' %}

    + +{% regroup models by app_config as grouped_models %} + +
    +{% for group in grouped_models %} +
    +

    {{ group.grouper.verbose_name }} ({{ group.grouper.name }})

    + + +{% for model in group.list %} + + + +{% endfor %} +
    {{ model.object_name }}
    +
    +{% endfor %} + +
    +{% endblock %} + +{% block sidebar %} + +{% endblock %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/template_detail.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/template_detail.html new file mode 100644 index 0000000..3dadaa6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/template_detail.html @@ -0,0 +1,27 @@ +{% extends "admin/base_site.html" %} +{% load i18n %} + +{% block breadcrumbs %} + +{% endblock %} + +{% block title %}{% blocktranslate %}Template: {{ name }}{% endblocktranslate %}{% endblock %} + +{% block content %} +

    {% blocktranslate %}Template: {{ name }}{% endblocktranslate %}

    + +{# Translators: Search is not a verb here, it qualifies path (a search path) #} +

    {% blocktranslate %}Search path for template {{ name }}:{% endblocktranslate %}

    +
      +{% for template in templates|dictsort:"order" %} +
    1. {{ template.file }}{% if not template.exists %} {% translate '(does not exist)' %}{% endif %}
    2. +{% endfor %} +
    + +

    ‹ {% translate 'Back to Documentation' %}

    +{% endblock %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/template_filter_index.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/template_filter_index.html new file mode 100644 index 0000000..c66b7ed --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/template_filter_index.html @@ -0,0 +1,54 @@ +{% extends "admin/base_site.html" %} +{% load i18n %} + +{% block coltype %}colSM{% endblock %} +{% block breadcrumbs %} + +{% endblock %} +{% block title %}{% translate 'Template filters' %}{% endblock %} + +{% block content %} + +

    {% translate 'Template filter documentation' %}

    + +
    +{% regroup filters|dictsort:"library" by library as filter_libraries %} +{% for library in filter_libraries %} +
    +

    {% firstof library.grouper _("Built-in filters") %}

    + {% if library.grouper %}

    {% blocktranslate with code="{"|add:"% load "|add:library.grouper|add:" %"|add:"}" %}To use these filters, put {{ code }} in your template before using the filter.{% endblocktranslate %}


    {% endif %} + {% for filter in library.list|dictsort:"name" %} +

    {{ filter.name }}

    + {{ filter.title }} + {{ filter.body }} + {% if not forloop.last %}
    {% endif %} + {% endfor %} +
    +{% endfor %} +
    + +{% endblock %} + +{% block sidebar %} + + + +{% endblock %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/template_tag_index.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/template_tag_index.html new file mode 100644 index 0000000..17b930e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/template_tag_index.html @@ -0,0 +1,54 @@ +{% extends "admin/base_site.html" %} +{% load i18n %} + +{% block coltype %}colSM{% endblock %} +{% block breadcrumbs %} + +{% endblock %} +{% block title %}{% translate 'Template tags' %}{% endblock %} + +{% block content %} + +

    {% translate 'Template tag documentation' %}

    + +
    +{% regroup tags|dictsort:"library" by library as tag_libraries %} +{% for library in tag_libraries %} +
    +

    {% firstof library.grouper _("Built-in tags") %}

    + {% if library.grouper %}

    {% blocktranslate with code="{"|add:"% load "|add:library.grouper|add:" %"|add:"}" %}To use these tags, put {{ code }} in your template before using the tag.{% endblocktranslate %}


    {% endif %} + {% for tag in library.list|dictsort:"name" %} +

    {{ tag.name }}

    +

    {{ tag.title|striptags }}

    + {{ tag.body }} + {% if not forloop.last %}
    {% endif %} + {% endfor %} +
    +{% endfor %} +
    + +{% endblock %} + +{% block sidebar %} + + + +{% endblock %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/view_detail.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/view_detail.html new file mode 100644 index 0000000..d1aa3ab --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/view_detail.html @@ -0,0 +1,33 @@ +{% extends "admin/base_site.html" %} +{% load i18n %} + +{% block breadcrumbs %} + +{% endblock %} +{% block title %}{% blocktranslate %}View: {{ name }}{% endblocktranslate %}{% endblock %} + +{% block content %} + +

    {{ name }}

    + +

    {{ summary|striptags }}

    + +{{ body }} + +{% if meta.Context %} +

    {% translate 'Context:' %}

    +

    {{ meta.Context }}

    +{% endif %} + +{% if meta.Templates %} +

    {% translate 'Templates:' %}

    +

    {{ meta.Templates }}

    +{% endif %} + +

    ‹ {% translate 'Back to View documentation' %}

    +{% endblock %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/view_index.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/view_index.html new file mode 100644 index 0000000..873303f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/templates/admin_doc/view_index.html @@ -0,0 +1,59 @@ +{% extends "admin/base_site.html" %} +{% load i18n %} + +{% block coltype %}colSM{% endblock %} +{% block breadcrumbs %} + +{% endblock %} +{% block title %}{% translate 'Views' %}{% endblock %} + +{% block content %} + +

    {% translate 'View documentation' %}

    + +{% regroup views|dictsort:'namespace' by namespace as views_by_ns %} + + + +
    + +{% for ns_views in views_by_ns %} +
    +

    +{% if ns_views.grouper %} + {% blocktranslate with ns_views.grouper as name %}Views by namespace {{ name }}{% endblocktranslate %} +{% else %} + {% blocktranslate %}Views by empty namespace{% endblocktranslate %} +{% endif %} +

    + +{% for view in ns_views.list|dictsort:"url" %} +{% ifchanged %} +

    {{ view.url }}

    +

    {% blocktranslate with view.full_name as full_name and view.url_name as url_name %} + View function: {{ full_name }}. Name: {{ url_name }}. +{% endblocktranslate %}

    +

    {{ view.title }}

    +
    +{% endifchanged %} +{% endfor %} +
    +{% endfor %} +
    +{% endblock %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/urls.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/urls.py new file mode 100644 index 0000000..5de2dba --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/urls.py @@ -0,0 +1,50 @@ +from django.contrib.admindocs import views +from django.urls import path, re_path + +urlpatterns = [ + path( + "", + views.BaseAdminDocsView.as_view(template_name="admin_doc/index.html"), + name="django-admindocs-docroot", + ), + path( + "bookmarklets/", + views.BookmarkletsView.as_view(), + name="django-admindocs-bookmarklets", + ), + path( + "tags/", + views.TemplateTagIndexView.as_view(), + name="django-admindocs-tags", + ), + path( + "filters/", + views.TemplateFilterIndexView.as_view(), + name="django-admindocs-filters", + ), + path( + "views/", + views.ViewIndexView.as_view(), + name="django-admindocs-views-index", + ), + path( + "views//", + views.ViewDetailView.as_view(), + name="django-admindocs-views-detail", + ), + path( + "models/", + views.ModelIndexView.as_view(), + name="django-admindocs-models-index", + ), + re_path( + r"^models/(?P[^.]+)\.(?P[^/]+)/$", + views.ModelDetailView.as_view(), + name="django-admindocs-models-detail", + ), + path( + "templates//", + views.TemplateDetailView.as_view(), + name="django-admindocs-templates", + ), +] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/utils.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/utils.py new file mode 100644 index 0000000..3708a32 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/utils.py @@ -0,0 +1,244 @@ +"Misc. utility functions/classes for admin documentation generator." + +import re +from email.errors import HeaderParseError +from email.parser import HeaderParser +from inspect import cleandoc + +from django.urls import reverse +from django.utils.regex_helper import _lazy_re_compile +from django.utils.safestring import mark_safe + +try: + import docutils.core + import docutils.nodes + import docutils.parsers.rst.roles +except ImportError: + docutils_is_available = False +else: + docutils_is_available = True + + +def get_view_name(view_func): + if hasattr(view_func, "view_class"): + klass = view_func.view_class + return f"{klass.__module__}.{klass.__qualname__}" + mod_name = view_func.__module__ + view_name = getattr(view_func, "__qualname__", view_func.__class__.__name__) + return mod_name + "." + view_name + + +def parse_docstring(docstring): + """ + Parse out the parts of a docstring. Return (title, body, metadata). + """ + if not docstring: + return "", "", {} + docstring = cleandoc(docstring) + parts = re.split(r"\n{2,}", docstring) + title = parts[0] + if len(parts) == 1: + body = "" + metadata = {} + else: + parser = HeaderParser() + try: + metadata = parser.parsestr(parts[-1]) + except HeaderParseError: + metadata = {} + body = "\n\n".join(parts[1:]) + else: + metadata = dict(metadata.items()) + if metadata: + body = "\n\n".join(parts[1:-1]) + else: + body = "\n\n".join(parts[1:]) + return title, body, metadata + + +def parse_rst(text, default_reference_context, thing_being_parsed=None): + """ + Convert the string from reST to an XHTML fragment. + """ + overrides = { + "doctitle_xform": True, + "initial_header_level": 3, + "default_reference_context": default_reference_context, + "link_base": reverse("django-admindocs-docroot").rstrip("/"), + "raw_enabled": False, + "file_insertion_enabled": False, + } + thing_being_parsed = thing_being_parsed and "<%s>" % thing_being_parsed + # Wrap ``text`` in some reST that sets the default role to ``cmsreference``, + # then restores it. + source = """ +.. default-role:: cmsreference + +%s + +.. default-role:: +""" + parts = docutils.core.publish_parts( + source % text, + source_path=thing_being_parsed, + destination_path=None, + writer_name="html", + settings_overrides=overrides, + ) + return mark_safe(parts["fragment"]) + + +# +# reST roles +# +ROLES = { + "model": "%s/models/%s/", + "view": "%s/views/%s/", + "template": "%s/templates/%s/", + "filter": "%s/filters/#%s", + "tag": "%s/tags/#%s", +} + + +def create_reference_role(rolename, urlbase): + # Views and template names are case-sensitive. + is_case_sensitive = rolename in ["template", "view"] + + def _role(name, rawtext, text, lineno, inliner, options=None, content=None): + if options is None: + options = {} + node = docutils.nodes.reference( + rawtext, + text, + refuri=( + urlbase + % ( + inliner.document.settings.link_base, + text if is_case_sensitive else text.lower(), + ) + ), + **options, + ) + return [node], [] + + docutils.parsers.rst.roles.register_canonical_role(rolename, _role) + + +def default_reference_role( + name, rawtext, text, lineno, inliner, options=None, content=None +): + if options is None: + options = {} + context = inliner.document.settings.default_reference_context + node = docutils.nodes.reference( + rawtext, + text, + refuri=( + ROLES[context] + % ( + inliner.document.settings.link_base, + text.lower(), + ) + ), + **options, + ) + return [node], [] + + +if docutils_is_available: + docutils.parsers.rst.roles.register_canonical_role( + "cmsreference", default_reference_role + ) + + for name, urlbase in ROLES.items(): + create_reference_role(name, urlbase) + +# Match the beginning of a named, unnamed, or non-capturing groups. +named_group_matcher = _lazy_re_compile(r"\(\?P(<\w+>)") +unnamed_group_matcher = _lazy_re_compile(r"\(") +non_capturing_group_matcher = _lazy_re_compile(r"\(\?\:") + + +def replace_metacharacters(pattern): + """Remove unescaped metacharacters from the pattern.""" + return re.sub( + r"((?:^|(?(x|y))/b' or '^b/((x|y)\w+)$'. + unmatched_open_brackets, prev_char = 1, None + for idx, val in enumerate(pattern[end:]): + # Check for unescaped `(` and `)`. They mark the start and end of a + # nested group. + if val == "(" and prev_char != "\\": + unmatched_open_brackets += 1 + elif val == ")" and prev_char != "\\": + unmatched_open_brackets -= 1 + prev_char = val + # If brackets are balanced, the end of the string for the current named + # capture group pattern has been reached. + if unmatched_open_brackets == 0: + return start, end + idx + 1 + + +def _find_groups(pattern, group_matcher): + prev_end = None + for match in group_matcher.finditer(pattern): + if indices := _get_group_start_end(match.start(0), match.end(0), pattern): + start, end = indices + if prev_end and start > prev_end or not prev_end: + yield start, end, match + prev_end = end + + +def replace_named_groups(pattern): + r""" + Find named groups in `pattern` and replace them with the group name. E.g., + 1. ^(?P\w+)/b/(\w+)$ ==> ^/b/(\w+)$ + 2. ^(?P\w+)/b/(?P\w+)/$ ==> ^/b//$ + 3. ^(?P\w+)/b/(\w+) ==> ^/b/(\w+) + 4. ^(?P\w+)/b/(?P\w+) ==> ^/b/ + """ + group_pattern_and_name = [ + (pattern[start:end], match[1]) + for start, end, match in _find_groups(pattern, named_group_matcher) + ] + for group_pattern, group_name in group_pattern_and_name: + pattern = pattern.replace(group_pattern, group_name) + return pattern + + +def replace_unnamed_groups(pattern): + r""" + Find unnamed groups in `pattern` and replace them with ''. E.g., + 1. ^(?P\w+)/b/(\w+)$ ==> ^(?P\w+)/b/$ + 2. ^(?P\w+)/b/((x|y)\w+)$ ==> ^(?P\w+)/b/$ + 3. ^(?P\w+)/b/(\w+) ==> ^(?P\w+)/b/ + 4. ^(?P\w+)/b/((x|y)\w+) ==> ^(?P\w+)/b/ + """ + final_pattern, prev_end = "", None + for start, end, _ in _find_groups(pattern, unnamed_group_matcher): + if prev_end: + final_pattern += pattern[prev_end:start] + final_pattern += pattern[:start] + "" + prev_end = end + return final_pattern + pattern[prev_end:] + + +def remove_non_capturing_groups(pattern): + r""" + Find non-capturing groups in the given `pattern` and remove them, e.g. + 1. (?P\w+)/b/(?:\w+)c(?:\w+) => (?P\\w+)/b/c + 2. ^(?:\w+(?:\w+))a => ^a + 3. ^a(?:\w+)/b(?:\w+) => ^a/b + """ + group_start_end_indices = _find_groups(pattern, non_capturing_group_matcher) + final_pattern, prev_end = "", None + for start, end, _ in group_start_end_indices: + final_pattern += pattern[prev_end:start] + prev_end = end + return final_pattern + pattern[prev_end:] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/views.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/views.py new file mode 100644 index 0000000..4f970e8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/admindocs/views.py @@ -0,0 +1,498 @@ +import inspect +from importlib import import_module +from inspect import cleandoc +from pathlib import Path + +from django.apps import apps +from django.contrib import admin +from django.contrib.admin.views.decorators import staff_member_required +from django.contrib.admindocs import utils +from django.contrib.admindocs.utils import ( + remove_non_capturing_groups, + replace_metacharacters, + replace_named_groups, + replace_unnamed_groups, +) +from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist +from django.db import models +from django.http import Http404 +from django.template.engine import Engine +from django.urls import get_mod_func, get_resolver, get_urlconf +from django.utils._os import safe_join +from django.utils.decorators import method_decorator +from django.utils.functional import cached_property +from django.utils.inspect import ( + func_accepts_kwargs, + func_accepts_var_args, + get_func_full_args, + method_has_no_args, +) +from django.utils.translation import gettext as _ +from django.views.generic import TemplateView + +from .utils import get_view_name + +# Exclude methods starting with these strings from documentation +MODEL_METHODS_EXCLUDE = ("_", "add_", "delete", "save", "set_") + + +class BaseAdminDocsView(TemplateView): + """ + Base view for admindocs views. + """ + + @method_decorator(staff_member_required) + def dispatch(self, request, *args, **kwargs): + if not utils.docutils_is_available: + # Display an error message for people without docutils + self.template_name = "admin_doc/missing_docutils.html" + return self.render_to_response(admin.site.each_context(request)) + return super().dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + return super().get_context_data( + **{ + **kwargs, + **admin.site.each_context(self.request), + } + ) + + +class BookmarkletsView(BaseAdminDocsView): + template_name = "admin_doc/bookmarklets.html" + + +class TemplateTagIndexView(BaseAdminDocsView): + template_name = "admin_doc/template_tag_index.html" + + def get_context_data(self, **kwargs): + tags = [] + try: + engine = Engine.get_default() + except ImproperlyConfigured: + # Non-trivial TEMPLATES settings aren't supported (#24125). + pass + else: + app_libs = sorted(engine.template_libraries.items()) + builtin_libs = [("", lib) for lib in engine.template_builtins] + for module_name, library in builtin_libs + app_libs: + for tag_name, tag_func in library.tags.items(): + title, body, metadata = utils.parse_docstring(tag_func.__doc__) + title = title and utils.parse_rst( + title, "tag", _("tag:") + tag_name + ) + body = body and utils.parse_rst(body, "tag", _("tag:") + tag_name) + for key in metadata: + metadata[key] = utils.parse_rst( + metadata[key], "tag", _("tag:") + tag_name + ) + tag_library = module_name.split(".")[-1] + tags.append( + { + "name": tag_name, + "title": title, + "body": body, + "meta": metadata, + "library": tag_library, + } + ) + return super().get_context_data(**{**kwargs, "tags": tags}) + + +class TemplateFilterIndexView(BaseAdminDocsView): + template_name = "admin_doc/template_filter_index.html" + + def get_context_data(self, **kwargs): + filters = [] + try: + engine = Engine.get_default() + except ImproperlyConfigured: + # Non-trivial TEMPLATES settings aren't supported (#24125). + pass + else: + app_libs = sorted(engine.template_libraries.items()) + builtin_libs = [("", lib) for lib in engine.template_builtins] + for module_name, library in builtin_libs + app_libs: + for filter_name, filter_func in library.filters.items(): + title, body, metadata = utils.parse_docstring(filter_func.__doc__) + title = title and utils.parse_rst( + title, "filter", _("filter:") + filter_name + ) + body = body and utils.parse_rst( + body, "filter", _("filter:") + filter_name + ) + for key in metadata: + metadata[key] = utils.parse_rst( + metadata[key], "filter", _("filter:") + filter_name + ) + tag_library = module_name.split(".")[-1] + filters.append( + { + "name": filter_name, + "title": title, + "body": body, + "meta": metadata, + "library": tag_library, + } + ) + return super().get_context_data(**{**kwargs, "filters": filters}) + + +class ViewIndexView(BaseAdminDocsView): + template_name = "admin_doc/view_index.html" + + def get_context_data(self, **kwargs): + views = [] + url_resolver = get_resolver(get_urlconf()) + try: + view_functions = extract_views_from_urlpatterns(url_resolver.url_patterns) + except ImproperlyConfigured: + view_functions = [] + for func, regex, namespace, name in view_functions: + views.append( + { + "full_name": get_view_name(func), + "url": simplify_regex(regex), + "url_name": ":".join((namespace or []) + (name and [name] or [])), + "namespace": ":".join(namespace or []), + "name": name, + } + ) + return super().get_context_data(**{**kwargs, "views": views}) + + +class ViewDetailView(BaseAdminDocsView): + template_name = "admin_doc/view_detail.html" + + @staticmethod + def _get_view_func(view): + urlconf = get_urlconf() + if get_resolver(urlconf)._is_callback(view): + mod, func = get_mod_func(view) + try: + # Separate the module and function, e.g. + # 'mymodule.views.myview' -> 'mymodule.views', 'myview'). + return getattr(import_module(mod), func) + except ImportError: + # Import may fail because view contains a class name, e.g. + # 'mymodule.views.ViewContainer.my_view', so mod takes the form + # 'mymodule.views.ViewContainer'. Parse it again to separate + # the module and class. + mod, klass = get_mod_func(mod) + return getattr(getattr(import_module(mod), klass), func) + + def get_context_data(self, **kwargs): + view = self.kwargs["view"] + view_func = self._get_view_func(view) + if view_func is None: + raise Http404 + title, body, metadata = utils.parse_docstring(view_func.__doc__) + title = title and utils.parse_rst(title, "view", _("view:") + view) + body = body and utils.parse_rst(body, "view", _("view:") + view) + for key in metadata: + metadata[key] = utils.parse_rst(metadata[key], "model", _("view:") + view) + return super().get_context_data( + **{ + **kwargs, + "name": view, + "summary": title, + "body": body, + "meta": metadata, + } + ) + + +class ModelIndexView(BaseAdminDocsView): + template_name = "admin_doc/model_index.html" + + def get_context_data(self, **kwargs): + m_list = [m._meta for m in apps.get_models()] + return super().get_context_data(**{**kwargs, "models": m_list}) + + +class ModelDetailView(BaseAdminDocsView): + template_name = "admin_doc/model_detail.html" + + def get_context_data(self, **kwargs): + model_name = self.kwargs["model_name"] + # Get the model class. + try: + app_config = apps.get_app_config(self.kwargs["app_label"]) + except LookupError: + raise Http404(_("App %(app_label)r not found") % self.kwargs) + try: + model = app_config.get_model(model_name) + except LookupError: + raise Http404( + _("Model %(model_name)r not found in app %(app_label)r") % self.kwargs + ) + + opts = model._meta + + title, body, metadata = utils.parse_docstring(model.__doc__) + title = title and utils.parse_rst(title, "model", _("model:") + model_name) + body = body and utils.parse_rst(body, "model", _("model:") + model_name) + + # Gather fields/field descriptions. + fields = [] + for field in opts.fields: + # ForeignKey is a special case since the field will actually be a + # descriptor that returns the other object + if isinstance(field, models.ForeignKey): + data_type = field.remote_field.model.__name__ + app_label = field.remote_field.model._meta.app_label + verbose = utils.parse_rst( + ( + _("the related `%(app_label)s.%(data_type)s` object") + % { + "app_label": app_label, + "data_type": data_type, + } + ), + "model", + _("model:") + data_type, + ) + else: + data_type = get_readable_field_data_type(field) + verbose = field.verbose_name + fields.append( + { + "name": field.name, + "data_type": data_type, + "verbose": verbose or "", + "help_text": field.help_text, + } + ) + + # Gather many-to-many fields. + for field in opts.many_to_many: + data_type = field.remote_field.model.__name__ + app_label = field.remote_field.model._meta.app_label + verbose = _("related `%(app_label)s.%(object_name)s` objects") % { + "app_label": app_label, + "object_name": data_type, + } + fields.append( + { + "name": "%s.all" % field.name, + "data_type": "List", + "verbose": utils.parse_rst( + _("all %s") % verbose, "model", _("model:") + opts.model_name + ), + } + ) + fields.append( + { + "name": "%s.count" % field.name, + "data_type": "Integer", + "verbose": utils.parse_rst( + _("number of %s") % verbose, + "model", + _("model:") + opts.model_name, + ), + } + ) + + methods = [] + # Gather model methods. + for func_name, func in model.__dict__.items(): + if inspect.isfunction(func) or isinstance( + func, (cached_property, property) + ): + try: + for exclude in MODEL_METHODS_EXCLUDE: + if func_name.startswith(exclude): + raise StopIteration + except StopIteration: + continue + verbose = func.__doc__ + verbose = verbose and ( + utils.parse_rst( + cleandoc(verbose), "model", _("model:") + opts.model_name + ) + ) + # Show properties, cached_properties, and methods without + # arguments as fields. Otherwise, show as a 'method with + # arguments'. + if isinstance(func, (cached_property, property)): + fields.append( + { + "name": func_name, + "data_type": get_return_data_type(func_name), + "verbose": verbose or "", + } + ) + elif ( + method_has_no_args(func) + and not func_accepts_kwargs(func) + and not func_accepts_var_args(func) + ): + fields.append( + { + "name": func_name, + "data_type": get_return_data_type(func_name), + "verbose": verbose or "", + } + ) + else: + arguments = get_func_full_args(func) + # Join arguments with ', ' and in case of default value, + # join it with '='. Use repr() so that strings will be + # correctly displayed. + print_arguments = ", ".join( + [ + "=".join([arg_el[0], *map(repr, arg_el[1:])]) + for arg_el in arguments + ] + ) + methods.append( + { + "name": func_name, + "arguments": print_arguments, + "verbose": verbose or "", + } + ) + + # Gather related objects + for rel in opts.related_objects: + verbose = _("related `%(app_label)s.%(object_name)s` objects") % { + "app_label": rel.related_model._meta.app_label, + "object_name": rel.related_model._meta.object_name, + } + accessor = rel.get_accessor_name() + fields.append( + { + "name": "%s.all" % accessor, + "data_type": "List", + "verbose": utils.parse_rst( + _("all %s") % verbose, "model", _("model:") + opts.model_name + ), + } + ) + fields.append( + { + "name": "%s.count" % accessor, + "data_type": "Integer", + "verbose": utils.parse_rst( + _("number of %s") % verbose, + "model", + _("model:") + opts.model_name, + ), + } + ) + return super().get_context_data( + **{ + **kwargs, + "name": opts.label, + "summary": title, + "description": body, + "fields": fields, + "methods": methods, + } + ) + + +class TemplateDetailView(BaseAdminDocsView): + template_name = "admin_doc/template_detail.html" + + def get_context_data(self, **kwargs): + template = self.kwargs["template"] + templates = [] + try: + default_engine = Engine.get_default() + except ImproperlyConfigured: + # Non-trivial TEMPLATES settings aren't supported (#24125). + pass + else: + # This doesn't account for template loaders (#24128). + for index, directory in enumerate(default_engine.dirs): + template_file = Path(safe_join(directory, template)) + if template_file.exists(): + template_contents = template_file.read_text() + else: + template_contents = "" + templates.append( + { + "file": template_file, + "exists": template_file.exists(), + "contents": template_contents, + "order": index, + } + ) + return super().get_context_data( + **{ + **kwargs, + "name": template, + "templates": templates, + } + ) + + +#################### +# Helper functions # +#################### + + +def get_return_data_type(func_name): + """Return a somewhat-helpful data type given a function name""" + if func_name.startswith("get_"): + if func_name.endswith("_list"): + return "List" + elif func_name.endswith("_count"): + return "Integer" + return "" + + +def get_readable_field_data_type(field): + """ + Return the description for a given field type, if it exists. Fields' + descriptions can contain format strings, which will be interpolated with + the values of field.__dict__ before being output. + """ + return field.description % field.__dict__ + + +def extract_views_from_urlpatterns(urlpatterns, base="", namespace=None): + """ + Return a list of views from a list of urlpatterns. + + Each object in the returned list is a 4-tuple: + (view_func, regex, namespace, name) + """ + views = [] + for p in urlpatterns: + if hasattr(p, "url_patterns"): + try: + patterns = p.url_patterns + except ImportError: + continue + views.extend( + extract_views_from_urlpatterns( + patterns, + base + str(p.pattern), + (namespace or []) + (p.namespace and [p.namespace] or []), + ) + ) + elif hasattr(p, "callback"): + try: + views.append((p.callback, base + str(p.pattern), namespace, p.name)) + except ViewDoesNotExist: + continue + else: + raise TypeError(_("%s does not appear to be a urlpattern object") % p) + return views + + +def simplify_regex(pattern): + r""" + Clean up urlpattern regexes into something more readable by humans. For + example, turn "^(?P\w+)/athletes/(?P\w+)/$" + into "//athletes//". + """ + pattern = remove_non_capturing_groups(pattern) + pattern = replace_named_groups(pattern) + pattern = replace_unnamed_groups(pattern) + pattern = replace_metacharacters(pattern) + if not pattern.startswith("/"): + pattern = "/" + pattern + return pattern diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/__init__.py new file mode 100644 index 0000000..91257dd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/__init__.py @@ -0,0 +1,272 @@ +import inspect +import re + +from asgiref.sync import sync_to_async + +from django.apps import apps as django_apps +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured, PermissionDenied +from django.middleware.csrf import rotate_token +from django.utils.crypto import constant_time_compare +from django.utils.module_loading import import_string +from django.views.decorators.debug import sensitive_variables + +from .signals import user_logged_in, user_logged_out, user_login_failed + +SESSION_KEY = "_auth_user_id" +BACKEND_SESSION_KEY = "_auth_user_backend" +HASH_SESSION_KEY = "_auth_user_hash" +REDIRECT_FIELD_NAME = "next" + + +def load_backend(path): + return import_string(path)() + + +def _get_backends(return_tuples=False): + backends = [] + for backend_path in settings.AUTHENTICATION_BACKENDS: + backend = load_backend(backend_path) + backends.append((backend, backend_path) if return_tuples else backend) + if not backends: + raise ImproperlyConfigured( + "No authentication backends have been defined. Does " + "AUTHENTICATION_BACKENDS contain anything?" + ) + return backends + + +def get_backends(): + return _get_backends(return_tuples=False) + + +@sensitive_variables("credentials") +def _clean_credentials(credentials): + """ + Clean a dictionary of credentials of potentially sensitive info before + sending to less secure functions. + + Not comprehensive - intended for user_login_failed signal + """ + SENSITIVE_CREDENTIALS = re.compile("api|token|key|secret|password|signature", re.I) + CLEANSED_SUBSTITUTE = "********************" + for key in credentials: + if SENSITIVE_CREDENTIALS.search(key): + credentials[key] = CLEANSED_SUBSTITUTE + return credentials + + +def _get_user_session_key(request): + # This value in the session is always serialized to a string, so we need + # to convert it back to Python whenever we access it. + return get_user_model()._meta.pk.to_python(request.session[SESSION_KEY]) + + +@sensitive_variables("credentials") +def authenticate(request=None, **credentials): + """ + If the given credentials are valid, return a User object. + """ + for backend, backend_path in _get_backends(return_tuples=True): + backend_signature = inspect.signature(backend.authenticate) + try: + backend_signature.bind(request, **credentials) + except TypeError: + # This backend doesn't accept these credentials as arguments. Try + # the next one. + continue + try: + user = backend.authenticate(request, **credentials) + except PermissionDenied: + # This backend says to stop in our tracks - this user should not be + # allowed in at all. + break + if user is None: + continue + # Annotate the user object with the path of the backend. + user.backend = backend_path + return user + + # The credentials supplied are invalid to all backends, fire signal + user_login_failed.send( + sender=__name__, credentials=_clean_credentials(credentials), request=request + ) + + +@sensitive_variables("credentials") +async def aauthenticate(request=None, **credentials): + """See authenticate().""" + return await sync_to_async(authenticate)(request, **credentials) + + +def login(request, user, backend=None): + """ + Persist a user id and a backend in the request. This way a user doesn't + have to reauthenticate on every request. Note that data set during + the anonymous session is retained when the user logs in. + """ + session_auth_hash = "" + if user is None: + user = request.user + if hasattr(user, "get_session_auth_hash"): + session_auth_hash = user.get_session_auth_hash() + + if SESSION_KEY in request.session: + if _get_user_session_key(request) != user.pk or ( + session_auth_hash + and not constant_time_compare( + request.session.get(HASH_SESSION_KEY, ""), session_auth_hash + ) + ): + # To avoid reusing another user's session, create a new, empty + # session if the existing session corresponds to a different + # authenticated user. + request.session.flush() + else: + request.session.cycle_key() + + try: + backend = backend or user.backend + except AttributeError: + backends = _get_backends(return_tuples=True) + if len(backends) == 1: + _, backend = backends[0] + else: + raise ValueError( + "You have multiple authentication backends configured and " + "therefore must provide the `backend` argument or set the " + "`backend` attribute on the user." + ) + else: + if not isinstance(backend, str): + raise TypeError( + "backend must be a dotted import path string (got %r)." % backend + ) + + request.session[SESSION_KEY] = user._meta.pk.value_to_string(user) + request.session[BACKEND_SESSION_KEY] = backend + request.session[HASH_SESSION_KEY] = session_auth_hash + if hasattr(request, "user"): + request.user = user + rotate_token(request) + user_logged_in.send(sender=user.__class__, request=request, user=user) + + +async def alogin(request, user, backend=None): + """See login().""" + return await sync_to_async(login)(request, user, backend) + + +def logout(request): + """ + Remove the authenticated user's ID from the request and flush their session + data. + """ + # Dispatch the signal before the user is logged out so the receivers have a + # chance to find out *who* logged out. + user = getattr(request, "user", None) + if not getattr(user, "is_authenticated", True): + user = None + user_logged_out.send(sender=user.__class__, request=request, user=user) + request.session.flush() + if hasattr(request, "user"): + from django.contrib.auth.models import AnonymousUser + + request.user = AnonymousUser() + + +async def alogout(request): + """See logout().""" + return await sync_to_async(logout)(request) + + +def get_user_model(): + """ + Return the User model that is active in this project. + """ + try: + return django_apps.get_model(settings.AUTH_USER_MODEL, require_ready=False) + except ValueError: + raise ImproperlyConfigured( + "AUTH_USER_MODEL must be of the form 'app_label.model_name'" + ) + except LookupError: + raise ImproperlyConfigured( + "AUTH_USER_MODEL refers to model '%s' that has not been installed" + % settings.AUTH_USER_MODEL + ) + + +def get_user(request): + """ + Return the user model instance associated with the given request session. + If no user is retrieved, return an instance of `AnonymousUser`. + """ + from .models import AnonymousUser + + user = None + try: + user_id = _get_user_session_key(request) + backend_path = request.session[BACKEND_SESSION_KEY] + except KeyError: + pass + else: + if backend_path in settings.AUTHENTICATION_BACKENDS: + backend = load_backend(backend_path) + user = backend.get_user(user_id) + # Verify the session + if hasattr(user, "get_session_auth_hash"): + session_hash = request.session.get(HASH_SESSION_KEY) + if not session_hash: + session_hash_verified = False + else: + session_auth_hash = user.get_session_auth_hash() + session_hash_verified = constant_time_compare( + session_hash, session_auth_hash + ) + if not session_hash_verified: + # If the current secret does not verify the session, try + # with the fallback secrets and stop when a matching one is + # found. + if session_hash and any( + constant_time_compare(session_hash, fallback_auth_hash) + for fallback_auth_hash in user.get_session_auth_fallback_hash() + ): + request.session.cycle_key() + request.session[HASH_SESSION_KEY] = session_auth_hash + else: + request.session.flush() + user = None + + return user or AnonymousUser() + + +async def aget_user(request): + """See get_user().""" + return await sync_to_async(get_user)(request) + + +def get_permission_codename(action, opts): + """ + Return the codename of the permission for the specified action. + """ + return "%s_%s" % (action, opts.model_name) + + +def update_session_auth_hash(request, user): + """ + Updating a user's password logs out all sessions for the user. + + Take the current request and the updated user object from which the new + session hash will be derived and update the session hash appropriately to + prevent a password change from logging out the session from which the + password was changed. + """ + request.session.cycle_key() + if hasattr(user, "get_session_auth_hash") and request.user == user: + request.session[HASH_SESSION_KEY] = user.get_session_auth_hash() + + +async def aupdate_session_auth_hash(request, user): + """See update_session_auth_hash().""" + return await sync_to_async(update_session_auth_hash)(request, user) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/admin.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/admin.py new file mode 100644 index 0000000..f9532ab --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/admin.py @@ -0,0 +1,232 @@ +from django.conf import settings +from django.contrib import admin, messages +from django.contrib.admin.options import IS_POPUP_VAR +from django.contrib.admin.utils import unquote +from django.contrib.auth import update_session_auth_hash +from django.contrib.auth.forms import ( + AdminPasswordChangeForm, + UserChangeForm, + UserCreationForm, +) +from django.contrib.auth.models import Group, User +from django.core.exceptions import PermissionDenied +from django.db import router, transaction +from django.http import Http404, HttpResponseRedirect +from django.template.response import TemplateResponse +from django.urls import path, reverse +from django.utils.decorators import method_decorator +from django.utils.html import escape +from django.utils.translation import gettext +from django.utils.translation import gettext_lazy as _ +from django.views.decorators.csrf import csrf_protect +from django.views.decorators.debug import sensitive_post_parameters + +csrf_protect_m = method_decorator(csrf_protect) +sensitive_post_parameters_m = method_decorator(sensitive_post_parameters()) + + +@admin.register(Group) +class GroupAdmin(admin.ModelAdmin): + search_fields = ("name",) + ordering = ("name",) + filter_horizontal = ("permissions",) + + def formfield_for_manytomany(self, db_field, request=None, **kwargs): + if db_field.name == "permissions": + qs = kwargs.get("queryset", db_field.remote_field.model.objects) + # Avoid a major performance hit resolving permission names which + # triggers a content_type load: + kwargs["queryset"] = qs.select_related("content_type") + return super().formfield_for_manytomany(db_field, request=request, **kwargs) + + +@admin.register(User) +class UserAdmin(admin.ModelAdmin): + add_form_template = "admin/auth/user/add_form.html" + change_user_password_template = None + fieldsets = ( + (None, {"fields": ("username", "password")}), + (_("Personal info"), {"fields": ("first_name", "last_name", "email")}), + ( + _("Permissions"), + { + "fields": ( + "is_active", + "is_staff", + "is_superuser", + "groups", + "user_permissions", + ), + }, + ), + (_("Important dates"), {"fields": ("last_login", "date_joined")}), + ) + add_fieldsets = ( + ( + None, + { + "classes": ("wide",), + "fields": ("username", "password1", "password2"), + }, + ), + ) + form = UserChangeForm + add_form = UserCreationForm + change_password_form = AdminPasswordChangeForm + list_display = ("username", "email", "first_name", "last_name", "is_staff") + list_filter = ("is_staff", "is_superuser", "is_active", "groups") + search_fields = ("username", "first_name", "last_name", "email") + ordering = ("username",) + filter_horizontal = ( + "groups", + "user_permissions", + ) + + def get_fieldsets(self, request, obj=None): + if not obj: + return self.add_fieldsets + return super().get_fieldsets(request, obj) + + def get_form(self, request, obj=None, **kwargs): + """ + Use special form during user creation + """ + defaults = {} + if obj is None: + defaults["form"] = self.add_form + defaults.update(kwargs) + return super().get_form(request, obj, **defaults) + + def get_urls(self): + return [ + path( + "/password/", + self.admin_site.admin_view(self.user_change_password), + name="auth_user_password_change", + ), + ] + super().get_urls() + + # RemovedInDjango60Warning: when the deprecation ends, replace with: + # def lookup_allowed(self, lookup, value, request): + def lookup_allowed(self, lookup, value, request=None): + # Don't allow lookups involving passwords. + return not lookup.startswith("password") and super().lookup_allowed( + lookup, value, request + ) + + @sensitive_post_parameters_m + @csrf_protect_m + def add_view(self, request, form_url="", extra_context=None): + with transaction.atomic(using=router.db_for_write(self.model)): + return self._add_view(request, form_url, extra_context) + + def _add_view(self, request, form_url="", extra_context=None): + # It's an error for a user to have add permission but NOT change + # permission for users. If we allowed such users to add users, they + # could create superusers, which would mean they would essentially have + # the permission to change users. To avoid the problem entirely, we + # disallow users from adding users if they don't have change + # permission. + if not self.has_change_permission(request): + if self.has_add_permission(request) and settings.DEBUG: + # Raise Http404 in debug mode so that the user gets a helpful + # error message. + raise Http404( + 'Your user does not have the "Change user" permission. In ' + "order to add users, Django requires that your user " + 'account have both the "Add user" and "Change user" ' + "permissions set." + ) + raise PermissionDenied + if extra_context is None: + extra_context = {} + username_field = self.opts.get_field(self.model.USERNAME_FIELD) + defaults = { + "auto_populated_fields": (), + "username_help_text": username_field.help_text, + } + extra_context.update(defaults) + return super().add_view(request, form_url, extra_context) + + @sensitive_post_parameters_m + def user_change_password(self, request, id, form_url=""): + user = self.get_object(request, unquote(id)) + if not self.has_change_permission(request, user): + raise PermissionDenied + if user is None: + raise Http404( + _("%(name)s object with primary key %(key)r does not exist.") + % { + "name": self.opts.verbose_name, + "key": escape(id), + } + ) + if request.method == "POST": + form = self.change_password_form(user, request.POST) + if form.is_valid(): + form.save() + change_message = self.construct_change_message(request, form, None) + self.log_change(request, user, change_message) + msg = gettext("Password changed successfully.") + messages.success(request, msg) + update_session_auth_hash(request, form.user) + return HttpResponseRedirect( + reverse( + "%s:%s_%s_change" + % ( + self.admin_site.name, + user._meta.app_label, + user._meta.model_name, + ), + args=(user.pk,), + ) + ) + else: + form = self.change_password_form(user) + + fieldsets = [(None, {"fields": list(form.base_fields)})] + admin_form = admin.helpers.AdminForm(form, fieldsets, {}) + + context = { + "title": _("Change password: %s") % escape(user.get_username()), + "adminForm": admin_form, + "form_url": form_url, + "form": form, + "is_popup": (IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET), + "is_popup_var": IS_POPUP_VAR, + "add": True, + "change": False, + "has_delete_permission": False, + "has_change_permission": True, + "has_absolute_url": False, + "opts": self.opts, + "original": user, + "save_as": False, + "show_save": True, + **self.admin_site.each_context(request), + } + + request.current_app = self.admin_site.name + + return TemplateResponse( + request, + self.change_user_password_template + or "admin/auth/user/change_password.html", + context, + ) + + def response_add(self, request, obj, post_url_continue=None): + """ + Determine the HttpResponse for the add_view stage. It mostly defers to + its superclass implementation but is customized because the User model + has a slightly different workflow. + """ + # We should allow further modification of the user just added i.e. the + # 'Save' button should behave like the 'Save and continue editing' + # button except in two scenarios: + # * The user has pressed the 'Save and add another' button + # * We are adding a user in a popup + if "_addanother" not in request.POST and IS_POPUP_VAR not in request.POST: + request.POST = request.POST.copy() + request.POST["_continue"] = 1 + return super().response_add(request, obj, post_url_continue) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/apps.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/apps.py new file mode 100644 index 0000000..4882a27 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/apps.py @@ -0,0 +1,30 @@ +from django.apps import AppConfig +from django.core import checks +from django.db.models.query_utils import DeferredAttribute +from django.db.models.signals import post_migrate +from django.utils.translation import gettext_lazy as _ + +from . import get_user_model +from .checks import check_models_permissions, check_user_model +from .management import create_permissions +from .signals import user_logged_in + + +class AuthConfig(AppConfig): + default_auto_field = "django.db.models.AutoField" + name = "django.contrib.auth" + verbose_name = _("Authentication and Authorization") + + def ready(self): + post_migrate.connect( + create_permissions, + dispatch_uid="django.contrib.auth.management.create_permissions", + ) + last_login_field = getattr(get_user_model(), "last_login", None) + # Register the handler only if UserModel.last_login is a field. + if isinstance(last_login_field, DeferredAttribute): + from .models import update_last_login + + user_logged_in.connect(update_last_login, dispatch_uid="update_last_login") + checks.register(check_user_model, checks.Tags.models) + checks.register(check_models_permissions, checks.Tags.models) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/backends.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/backends.py new file mode 100644 index 0000000..dd3c2e5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/backends.py @@ -0,0 +1,233 @@ +from django.contrib.auth import get_user_model +from django.contrib.auth.models import Permission +from django.db.models import Exists, OuterRef, Q + +UserModel = get_user_model() + + +class BaseBackend: + def authenticate(self, request, **kwargs): + return None + + def get_user(self, user_id): + return None + + def get_user_permissions(self, user_obj, obj=None): + return set() + + def get_group_permissions(self, user_obj, obj=None): + return set() + + def get_all_permissions(self, user_obj, obj=None): + return { + *self.get_user_permissions(user_obj, obj=obj), + *self.get_group_permissions(user_obj, obj=obj), + } + + def has_perm(self, user_obj, perm, obj=None): + return perm in self.get_all_permissions(user_obj, obj=obj) + + +class ModelBackend(BaseBackend): + """ + Authenticates against settings.AUTH_USER_MODEL. + """ + + def authenticate(self, request, username=None, password=None, **kwargs): + if username is None: + username = kwargs.get(UserModel.USERNAME_FIELD) + if username is None or password is None: + return + try: + user = UserModel._default_manager.get_by_natural_key(username) + except UserModel.DoesNotExist: + # Run the default password hasher once to reduce the timing + # difference between an existing and a nonexistent user (#20760). + UserModel().set_password(password) + else: + if user.check_password(password) and self.user_can_authenticate(user): + return user + + def user_can_authenticate(self, user): + """ + Reject users with is_active=False. Custom user models that don't have + that attribute are allowed. + """ + return getattr(user, "is_active", True) + + def _get_user_permissions(self, user_obj): + return user_obj.user_permissions.all() + + def _get_group_permissions(self, user_obj): + user_groups_field = get_user_model()._meta.get_field("groups") + user_groups_query = "group__%s" % user_groups_field.related_query_name() + return Permission.objects.filter(**{user_groups_query: user_obj}) + + def _get_permissions(self, user_obj, obj, from_name): + """ + Return the permissions of `user_obj` from `from_name`. `from_name` can + be either "group" or "user" to return permissions from + `_get_group_permissions` or `_get_user_permissions` respectively. + """ + if not user_obj.is_active or user_obj.is_anonymous or obj is not None: + return set() + + perm_cache_name = "_%s_perm_cache" % from_name + if not hasattr(user_obj, perm_cache_name): + if user_obj.is_superuser: + perms = Permission.objects.all() + else: + perms = getattr(self, "_get_%s_permissions" % from_name)(user_obj) + perms = perms.values_list("content_type__app_label", "codename").order_by() + setattr( + user_obj, perm_cache_name, {"%s.%s" % (ct, name) for ct, name in perms} + ) + return getattr(user_obj, perm_cache_name) + + def get_user_permissions(self, user_obj, obj=None): + """ + Return a set of permission strings the user `user_obj` has from their + `user_permissions`. + """ + return self._get_permissions(user_obj, obj, "user") + + def get_group_permissions(self, user_obj, obj=None): + """ + Return a set of permission strings the user `user_obj` has from the + groups they belong. + """ + return self._get_permissions(user_obj, obj, "group") + + def get_all_permissions(self, user_obj, obj=None): + if not user_obj.is_active or user_obj.is_anonymous or obj is not None: + return set() + if not hasattr(user_obj, "_perm_cache"): + user_obj._perm_cache = super().get_all_permissions(user_obj) + return user_obj._perm_cache + + def has_perm(self, user_obj, perm, obj=None): + return user_obj.is_active and super().has_perm(user_obj, perm, obj=obj) + + def has_module_perms(self, user_obj, app_label): + """ + Return True if user_obj has any permissions in the given app_label. + """ + return user_obj.is_active and any( + perm[: perm.index(".")] == app_label + for perm in self.get_all_permissions(user_obj) + ) + + def with_perm(self, perm, is_active=True, include_superusers=True, obj=None): + """ + Return users that have permission "perm". By default, filter out + inactive users and include superusers. + """ + if isinstance(perm, str): + try: + app_label, codename = perm.split(".") + except ValueError: + raise ValueError( + "Permission name should be in the form " + "app_label.permission_codename." + ) + elif not isinstance(perm, Permission): + raise TypeError( + "The `perm` argument must be a string or a permission instance." + ) + + if obj is not None: + return UserModel._default_manager.none() + + permission_q = Q(group__user=OuterRef("pk")) | Q(user=OuterRef("pk")) + if isinstance(perm, Permission): + permission_q &= Q(pk=perm.pk) + else: + permission_q &= Q(codename=codename, content_type__app_label=app_label) + + user_q = Exists(Permission.objects.filter(permission_q)) + if include_superusers: + user_q |= Q(is_superuser=True) + if is_active is not None: + user_q &= Q(is_active=is_active) + + return UserModel._default_manager.filter(user_q) + + def get_user(self, user_id): + try: + user = UserModel._default_manager.get(pk=user_id) + except UserModel.DoesNotExist: + return None + return user if self.user_can_authenticate(user) else None + + +class AllowAllUsersModelBackend(ModelBackend): + def user_can_authenticate(self, user): + return True + + +class RemoteUserBackend(ModelBackend): + """ + This backend is to be used in conjunction with the ``RemoteUserMiddleware`` + found in the middleware module of this package, and is used when the server + is handling authentication outside of Django. + + By default, the ``authenticate`` method creates ``User`` objects for + usernames that don't already exist in the database. Subclasses can disable + this behavior by setting the ``create_unknown_user`` attribute to + ``False``. + """ + + # Create a User object if not already in the database? + create_unknown_user = True + + def authenticate(self, request, remote_user): + """ + The username passed as ``remote_user`` is considered trusted. Return + the ``User`` object with the given username. Create a new ``User`` + object if ``create_unknown_user`` is ``True``. + + Return None if ``create_unknown_user`` is ``False`` and a ``User`` + object with the given username is not found in the database. + """ + if not remote_user: + return + created = False + user = None + username = self.clean_username(remote_user) + + # Note that this could be accomplished in one try-except clause, but + # instead we use get_or_create when creating unknown users since it has + # built-in safeguards for multiple threads. + if self.create_unknown_user: + user, created = UserModel._default_manager.get_or_create( + **{UserModel.USERNAME_FIELD: username} + ) + else: + try: + user = UserModel._default_manager.get_by_natural_key(username) + except UserModel.DoesNotExist: + pass + user = self.configure_user(request, user, created=created) + return user if self.user_can_authenticate(user) else None + + def clean_username(self, username): + """ + Perform any cleaning on the "username" prior to using it to get or + create the user object. Return the cleaned username. + + By default, return the username unchanged. + """ + return username + + def configure_user(self, request, user, created=True): + """ + Configure a user and return the updated user. + + By default, return the user unmodified. + """ + return user + + +class AllowAllUsersRemoteUserBackend(RemoteUserBackend): + def user_can_authenticate(self, user): + return True diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/base_user.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/base_user.py new file mode 100644 index 0000000..da0eac7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/base_user.py @@ -0,0 +1,179 @@ +""" +This module allows importing AbstractBaseUser even when django.contrib.auth is +not in INSTALLED_APPS. +""" +import unicodedata +import warnings + +from django.conf import settings +from django.contrib.auth import password_validation +from django.contrib.auth.hashers import ( + acheck_password, + check_password, + is_password_usable, + make_password, +) +from django.db import models +from django.utils.crypto import get_random_string, salted_hmac +from django.utils.deprecation import RemovedInDjango51Warning +from django.utils.translation import gettext_lazy as _ + + +class BaseUserManager(models.Manager): + @classmethod + def normalize_email(cls, email): + """ + Normalize the email address by lowercasing the domain part of it. + """ + email = email or "" + try: + email_name, domain_part = email.strip().rsplit("@", 1) + except ValueError: + pass + else: + email = email_name + "@" + domain_part.lower() + return email + + def make_random_password( + self, + length=10, + allowed_chars="abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789", + ): + """ + Generate a random password with the given length and given + allowed_chars. The default value of allowed_chars does not have "I" or + "O" or letters and digits that look similar -- just to avoid confusion. + """ + warnings.warn( + "BaseUserManager.make_random_password() is deprecated.", + category=RemovedInDjango51Warning, + stacklevel=2, + ) + return get_random_string(length, allowed_chars) + + def get_by_natural_key(self, username): + return self.get(**{self.model.USERNAME_FIELD: username}) + + +class AbstractBaseUser(models.Model): + password = models.CharField(_("password"), max_length=128) + last_login = models.DateTimeField(_("last login"), blank=True, null=True) + + is_active = True + + REQUIRED_FIELDS = [] + + # Stores the raw password if set_password() is called so that it can + # be passed to password_changed() after the model is saved. + _password = None + + class Meta: + abstract = True + + def __str__(self): + return self.get_username() + + def save(self, *args, **kwargs): + super().save(*args, **kwargs) + if self._password is not None: + password_validation.password_changed(self._password, self) + self._password = None + + def get_username(self): + """Return the username for this User.""" + return getattr(self, self.USERNAME_FIELD) + + def clean(self): + setattr(self, self.USERNAME_FIELD, self.normalize_username(self.get_username())) + + def natural_key(self): + return (self.get_username(),) + + @property + def is_anonymous(self): + """ + Always return False. This is a way of comparing User objects to + anonymous users. + """ + return False + + @property + def is_authenticated(self): + """ + Always return True. This is a way to tell if the user has been + authenticated in templates. + """ + return True + + def set_password(self, raw_password): + self.password = make_password(raw_password) + self._password = raw_password + + def check_password(self, raw_password): + """ + Return a boolean of whether the raw_password was correct. Handles + hashing formats behind the scenes. + """ + + def setter(raw_password): + self.set_password(raw_password) + # Password hash upgrades shouldn't be considered password changes. + self._password = None + self.save(update_fields=["password"]) + + return check_password(raw_password, self.password, setter) + + async def acheck_password(self, raw_password): + """See check_password().""" + + async def setter(raw_password): + self.set_password(raw_password) + # Password hash upgrades shouldn't be considered password changes. + self._password = None + await self.asave(update_fields=["password"]) + + return await acheck_password(raw_password, self.password, setter) + + def set_unusable_password(self): + # Set a value that will never be a valid hash + self.password = make_password(None) + + def has_usable_password(self): + """ + Return False if set_unusable_password() has been called for this user. + """ + return is_password_usable(self.password) + + def get_session_auth_hash(self): + """ + Return an HMAC of the password field. + """ + return self._get_session_auth_hash() + + def get_session_auth_fallback_hash(self): + for fallback_secret in settings.SECRET_KEY_FALLBACKS: + yield self._get_session_auth_hash(secret=fallback_secret) + + def _get_session_auth_hash(self, secret=None): + key_salt = "django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash" + return salted_hmac( + key_salt, + self.password, + secret=secret, + algorithm="sha256", + ).hexdigest() + + @classmethod + def get_email_field_name(cls): + try: + return cls.EMAIL_FIELD + except AttributeError: + return "email" + + @classmethod + def normalize_username(cls, username): + return ( + unicodedata.normalize("NFKC", username) + if isinstance(username, str) + else username + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/checks.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/checks.py new file mode 100644 index 0000000..ee80825 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/checks.py @@ -0,0 +1,220 @@ +from itertools import chain +from types import MethodType + +from django.apps import apps +from django.conf import settings +from django.core import checks + +from .management import _get_builtin_permissions + + +def check_user_model(app_configs=None, **kwargs): + if app_configs is None: + cls = apps.get_model(settings.AUTH_USER_MODEL) + else: + app_label, model_name = settings.AUTH_USER_MODEL.split(".") + for app_config in app_configs: + if app_config.label == app_label: + cls = app_config.get_model(model_name) + break + else: + # Checks might be run against a set of app configs that don't + # include the specified user model. In this case we simply don't + # perform the checks defined below. + return [] + + errors = [] + + # Check that REQUIRED_FIELDS is a list + if not isinstance(cls.REQUIRED_FIELDS, (list, tuple)): + errors.append( + checks.Error( + "'REQUIRED_FIELDS' must be a list or tuple.", + obj=cls, + id="auth.E001", + ) + ) + + # Check that the USERNAME FIELD isn't included in REQUIRED_FIELDS. + if cls.USERNAME_FIELD in cls.REQUIRED_FIELDS: + errors.append( + checks.Error( + "The field named as the 'USERNAME_FIELD' " + "for a custom user model must not be included in 'REQUIRED_FIELDS'.", + hint=( + "The 'USERNAME_FIELD' is currently set to '%s', you " + "should remove '%s' from the 'REQUIRED_FIELDS'." + % (cls.USERNAME_FIELD, cls.USERNAME_FIELD) + ), + obj=cls, + id="auth.E002", + ) + ) + + # Check that the username field is unique + if not cls._meta.get_field(cls.USERNAME_FIELD).unique and not any( + constraint.fields == (cls.USERNAME_FIELD,) + for constraint in cls._meta.total_unique_constraints + ): + if settings.AUTHENTICATION_BACKENDS == [ + "django.contrib.auth.backends.ModelBackend" + ]: + errors.append( + checks.Error( + "'%s.%s' must be unique because it is named as the " + "'USERNAME_FIELD'." % (cls._meta.object_name, cls.USERNAME_FIELD), + obj=cls, + id="auth.E003", + ) + ) + else: + errors.append( + checks.Warning( + "'%s.%s' is named as the 'USERNAME_FIELD', but it is not unique." + % (cls._meta.object_name, cls.USERNAME_FIELD), + hint=( + "Ensure that your authentication backend(s) can handle " + "non-unique usernames." + ), + obj=cls, + id="auth.W004", + ) + ) + + if isinstance(cls().is_anonymous, MethodType): + errors.append( + checks.Critical( + "%s.is_anonymous must be an attribute or property rather than " + "a method. Ignoring this is a security issue as anonymous " + "users will be treated as authenticated!" % cls, + obj=cls, + id="auth.C009", + ) + ) + if isinstance(cls().is_authenticated, MethodType): + errors.append( + checks.Critical( + "%s.is_authenticated must be an attribute or property rather " + "than a method. Ignoring this is a security issue as anonymous " + "users will be treated as authenticated!" % cls, + obj=cls, + id="auth.C010", + ) + ) + return errors + + +def check_models_permissions(app_configs=None, **kwargs): + if app_configs is None: + models = apps.get_models() + else: + models = chain.from_iterable( + app_config.get_models() for app_config in app_configs + ) + + Permission = apps.get_model("auth", "Permission") + permission_name_max_length = Permission._meta.get_field("name").max_length + permission_codename_max_length = Permission._meta.get_field("codename").max_length + errors = [] + + for model in models: + opts = model._meta + builtin_permissions = dict(_get_builtin_permissions(opts)) + # Check builtin permission name length. + max_builtin_permission_name_length = ( + max(len(name) for name in builtin_permissions.values()) + if builtin_permissions + else 0 + ) + if max_builtin_permission_name_length > permission_name_max_length: + verbose_name_max_length = permission_name_max_length - ( + max_builtin_permission_name_length - len(opts.verbose_name_raw) + ) + errors.append( + checks.Error( + "The verbose_name of model '%s' must be at most %d " + "characters for its builtin permission names to be at " + "most %d characters." + % (opts.label, verbose_name_max_length, permission_name_max_length), + obj=model, + id="auth.E007", + ) + ) + # Check builtin permission codename length. + max_builtin_permission_codename_length = ( + max(len(codename) for codename in builtin_permissions.keys()) + if builtin_permissions + else 0 + ) + if max_builtin_permission_codename_length > permission_codename_max_length: + model_name_max_length = permission_codename_max_length - ( + max_builtin_permission_codename_length - len(opts.model_name) + ) + errors.append( + checks.Error( + "The name of model '%s' must be at most %d characters " + "for its builtin permission codenames to be at most %d " + "characters." + % ( + opts.label, + model_name_max_length, + permission_codename_max_length, + ), + obj=model, + id="auth.E011", + ) + ) + codenames = set() + for codename, name in opts.permissions: + # Check custom permission name length. + if len(name) > permission_name_max_length: + errors.append( + checks.Error( + "The permission named '%s' of model '%s' is longer " + "than %d characters." + % ( + name, + opts.label, + permission_name_max_length, + ), + obj=model, + id="auth.E008", + ) + ) + # Check custom permission codename length. + if len(codename) > permission_codename_max_length: + errors.append( + checks.Error( + "The permission codenamed '%s' of model '%s' is " + "longer than %d characters." + % ( + codename, + opts.label, + permission_codename_max_length, + ), + obj=model, + id="auth.E012", + ) + ) + # Check custom permissions codename clashing. + if codename in builtin_permissions: + errors.append( + checks.Error( + "The permission codenamed '%s' clashes with a builtin " + "permission for model '%s'." % (codename, opts.label), + obj=model, + id="auth.E005", + ) + ) + elif codename in codenames: + errors.append( + checks.Error( + "The permission codenamed '%s' is duplicated for " + "model '%s'." % (codename, opts.label), + obj=model, + id="auth.E006", + ) + ) + codenames.add(codename) + + return errors diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/common-passwords.txt.gz b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/common-passwords.txt.gz new file mode 100644 index 0000000..bc94fde Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/common-passwords.txt.gz differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/context_processors.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/context_processors.py new file mode 100644 index 0000000..0a88199 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/context_processors.py @@ -0,0 +1,67 @@ +# PermWrapper and PermLookupDict proxy the permissions system into objects that +# the template system can understand. + + +class PermLookupDict: + def __init__(self, user, app_label): + self.user, self.app_label = user, app_label + + def __repr__(self): + return str(self.user.get_all_permissions()) + + def __getitem__(self, perm_name): + return self.user.has_perm("%s.%s" % (self.app_label, perm_name)) + + def __iter__(self): + # To fix 'item in perms.someapp' and __getitem__ interaction we need to + # define __iter__. See #18979 for details. + raise TypeError("PermLookupDict is not iterable.") + + def __bool__(self): + return self.user.has_module_perms(self.app_label) + + +class PermWrapper: + def __init__(self, user): + self.user = user + + def __repr__(self): + return f"{self.__class__.__qualname__}({self.user!r})" + + def __getitem__(self, app_label): + return PermLookupDict(self.user, app_label) + + def __iter__(self): + # I am large, I contain multitudes. + raise TypeError("PermWrapper is not iterable.") + + def __contains__(self, perm_name): + """ + Lookup by "someapp" or "someapp.someperm" in perms. + """ + if "." not in perm_name: + # The name refers to module. + return bool(self[perm_name]) + app_label, perm_name = perm_name.split(".", 1) + return self[app_label][perm_name] + + +def auth(request): + """ + Return context variables required by apps that use Django's authentication + system. + + If there is no 'user' attribute in the request, use AnonymousUser (from + django.contrib.auth). + """ + if hasattr(request, "user"): + user = request.user + else: + from django.contrib.auth.models import AnonymousUser + + user = AnonymousUser() + + return { + "user": user, + "perms": PermWrapper(user), + } diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/decorators.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/decorators.py new file mode 100644 index 0000000..cfcc4a2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/decorators.py @@ -0,0 +1,82 @@ +from functools import wraps +from urllib.parse import urlparse + +from django.conf import settings +from django.contrib.auth import REDIRECT_FIELD_NAME +from django.core.exceptions import PermissionDenied +from django.shortcuts import resolve_url + + +def user_passes_test( + test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME +): + """ + Decorator for views that checks that the user passes the given test, + redirecting to the log-in page if necessary. The test should be a callable + that takes the user object and returns True if the user passes. + """ + + def decorator(view_func): + @wraps(view_func) + def _wrapper_view(request, *args, **kwargs): + if test_func(request.user): + return view_func(request, *args, **kwargs) + path = request.build_absolute_uri() + resolved_login_url = resolve_url(login_url or settings.LOGIN_URL) + # If the login url is the same scheme and net location then just + # use the path as the "next" url. + login_scheme, login_netloc = urlparse(resolved_login_url)[:2] + current_scheme, current_netloc = urlparse(path)[:2] + if (not login_scheme or login_scheme == current_scheme) and ( + not login_netloc or login_netloc == current_netloc + ): + path = request.get_full_path() + from django.contrib.auth.views import redirect_to_login + + return redirect_to_login(path, resolved_login_url, redirect_field_name) + + return _wrapper_view + + return decorator + + +def login_required( + function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None +): + """ + Decorator for views that checks that the user is logged in, redirecting + to the log-in page if necessary. + """ + actual_decorator = user_passes_test( + lambda u: u.is_authenticated, + login_url=login_url, + redirect_field_name=redirect_field_name, + ) + if function: + return actual_decorator(function) + return actual_decorator + + +def permission_required(perm, login_url=None, raise_exception=False): + """ + Decorator for views that checks whether a user has a particular permission + enabled, redirecting to the log-in page if necessary. + If the raise_exception parameter is given the PermissionDenied exception + is raised. + """ + + def check_perms(user): + if isinstance(perm, str): + perms = (perm,) + else: + perms = perm + # First check if the user has the permission (even anon users) + if user.has_perms(perms): + return True + # In case the 403 handler should be called raise the exception + if raise_exception: + raise PermissionDenied + # As the last resort, show the login form + return False + + return user_passes_test(check_perms, login_url=login_url) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/forms.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/forms.py new file mode 100644 index 0000000..061dc81 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/forms.py @@ -0,0 +1,518 @@ +import unicodedata + +from django import forms +from django.contrib.auth import authenticate, get_user_model, password_validation +from django.contrib.auth.hashers import UNUSABLE_PASSWORD_PREFIX, identify_hasher +from django.contrib.auth.models import User +from django.contrib.auth.tokens import default_token_generator +from django.contrib.sites.shortcuts import get_current_site +from django.core.exceptions import ValidationError +from django.core.mail import EmailMultiAlternatives +from django.template import loader +from django.utils.encoding import force_bytes +from django.utils.http import urlsafe_base64_encode +from django.utils.text import capfirst +from django.utils.translation import gettext +from django.utils.translation import gettext_lazy as _ + +UserModel = get_user_model() + + +def _unicode_ci_compare(s1, s2): + """ + Perform case-insensitive comparison of two identifiers, using the + recommended algorithm from Unicode Technical Report 36, section + 2.11.2(B)(2). + """ + return ( + unicodedata.normalize("NFKC", s1).casefold() + == unicodedata.normalize("NFKC", s2).casefold() + ) + + +class ReadOnlyPasswordHashWidget(forms.Widget): + template_name = "auth/widgets/read_only_password_hash.html" + read_only = True + + def get_context(self, name, value, attrs): + context = super().get_context(name, value, attrs) + summary = [] + if not value or value.startswith(UNUSABLE_PASSWORD_PREFIX): + summary.append({"label": gettext("No password set.")}) + else: + try: + hasher = identify_hasher(value) + except ValueError: + summary.append( + { + "label": gettext( + "Invalid password format or unknown hashing algorithm." + ) + } + ) + else: + for key, value_ in hasher.safe_summary(value).items(): + summary.append({"label": gettext(key), "value": value_}) + context["summary"] = summary + return context + + def id_for_label(self, id_): + return None + + +class ReadOnlyPasswordHashField(forms.Field): + widget = ReadOnlyPasswordHashWidget + + def __init__(self, *args, **kwargs): + kwargs.setdefault("required", False) + kwargs.setdefault("disabled", True) + super().__init__(*args, **kwargs) + + +class UsernameField(forms.CharField): + def to_python(self, value): + value = super().to_python(value) + if self.max_length is not None and len(value) > self.max_length: + # Normalization can increase the string length (e.g. + # "ff" -> "ff", "½" -> "1⁄2") but cannot reduce it, so there is no + # point in normalizing invalid data. Moreover, Unicode + # normalization is very slow on Windows and can be a DoS attack + # vector. + return value + return unicodedata.normalize("NFKC", value) + + def widget_attrs(self, widget): + return { + **super().widget_attrs(widget), + "autocapitalize": "none", + "autocomplete": "username", + } + + +class BaseUserCreationForm(forms.ModelForm): + """ + A form that creates a user, with no privileges, from the given username and + password. + """ + + error_messages = { + "password_mismatch": _("The two password fields didn’t match."), + } + password1 = forms.CharField( + label=_("Password"), + strip=False, + widget=forms.PasswordInput(attrs={"autocomplete": "new-password"}), + help_text=password_validation.password_validators_help_text_html(), + ) + password2 = forms.CharField( + label=_("Password confirmation"), + widget=forms.PasswordInput(attrs={"autocomplete": "new-password"}), + strip=False, + help_text=_("Enter the same password as before, for verification."), + ) + + class Meta: + model = User + fields = ("username",) + field_classes = {"username": UsernameField} + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + if self._meta.model.USERNAME_FIELD in self.fields: + self.fields[self._meta.model.USERNAME_FIELD].widget.attrs[ + "autofocus" + ] = True + + def clean_password2(self): + password1 = self.cleaned_data.get("password1") + password2 = self.cleaned_data.get("password2") + if password1 and password2 and password1 != password2: + raise ValidationError( + self.error_messages["password_mismatch"], + code="password_mismatch", + ) + return password2 + + def _post_clean(self): + super()._post_clean() + # Validate the password after self.instance is updated with form data + # by super(). + password = self.cleaned_data.get("password2") + if password: + try: + password_validation.validate_password(password, self.instance) + except ValidationError as error: + self.add_error("password2", error) + + def save(self, commit=True): + user = super().save(commit=False) + user.set_password(self.cleaned_data["password1"]) + if commit: + user.save() + if hasattr(self, "save_m2m"): + self.save_m2m() + return user + + +class UserCreationForm(BaseUserCreationForm): + def clean_username(self): + """Reject usernames that differ only in case.""" + username = self.cleaned_data.get("username") + if ( + username + and self._meta.model.objects.filter(username__iexact=username).exists() + ): + self._update_errors( + ValidationError( + { + "username": self.instance.unique_error_message( + self._meta.model, ["username"] + ) + } + ) + ) + else: + return username + + +class UserChangeForm(forms.ModelForm): + password = ReadOnlyPasswordHashField( + label=_("Password"), + help_text=_( + "Raw passwords are not stored, so there is no way to see this " + "user’s password, but you can change the password using " + 'this form.' + ), + ) + + class Meta: + model = User + fields = "__all__" + field_classes = {"username": UsernameField} + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + password = self.fields.get("password") + if password: + password.help_text = password.help_text.format( + f"../../{self.instance.pk}/password/" + ) + user_permissions = self.fields.get("user_permissions") + if user_permissions: + user_permissions.queryset = user_permissions.queryset.select_related( + "content_type" + ) + + +class AuthenticationForm(forms.Form): + """ + Base class for authenticating users. Extend this to get a form that accepts + username/password logins. + """ + + username = UsernameField(widget=forms.TextInput(attrs={"autofocus": True})) + password = forms.CharField( + label=_("Password"), + strip=False, + widget=forms.PasswordInput(attrs={"autocomplete": "current-password"}), + ) + + error_messages = { + "invalid_login": _( + "Please enter a correct %(username)s and password. Note that both " + "fields may be case-sensitive." + ), + "inactive": _("This account is inactive."), + } + + def __init__(self, request=None, *args, **kwargs): + """ + The 'request' parameter is set for custom auth use by subclasses. + The form data comes in via the standard 'data' kwarg. + """ + self.request = request + self.user_cache = None + super().__init__(*args, **kwargs) + + # Set the max length and label for the "username" field. + self.username_field = UserModel._meta.get_field(UserModel.USERNAME_FIELD) + username_max_length = self.username_field.max_length or 254 + self.fields["username"].max_length = username_max_length + self.fields["username"].widget.attrs["maxlength"] = username_max_length + if self.fields["username"].label is None: + self.fields["username"].label = capfirst(self.username_field.verbose_name) + + def clean(self): + username = self.cleaned_data.get("username") + password = self.cleaned_data.get("password") + + if username is not None and password: + self.user_cache = authenticate( + self.request, username=username, password=password + ) + if self.user_cache is None: + raise self.get_invalid_login_error() + else: + self.confirm_login_allowed(self.user_cache) + + return self.cleaned_data + + def confirm_login_allowed(self, user): + """ + Controls whether the given User may log in. This is a policy setting, + independent of end-user authentication. This default behavior is to + allow login by active users, and reject login by inactive users. + + If the given user cannot log in, this method should raise a + ``ValidationError``. + + If the given user may log in, this method should return None. + """ + if not user.is_active: + raise ValidationError( + self.error_messages["inactive"], + code="inactive", + ) + + def get_user(self): + return self.user_cache + + def get_invalid_login_error(self): + return ValidationError( + self.error_messages["invalid_login"], + code="invalid_login", + params={"username": self.username_field.verbose_name}, + ) + + +class PasswordResetForm(forms.Form): + email = forms.EmailField( + label=_("Email"), + max_length=254, + widget=forms.EmailInput(attrs={"autocomplete": "email"}), + ) + + def send_mail( + self, + subject_template_name, + email_template_name, + context, + from_email, + to_email, + html_email_template_name=None, + ): + """ + Send a django.core.mail.EmailMultiAlternatives to `to_email`. + """ + subject = loader.render_to_string(subject_template_name, context) + # Email subject *must not* contain newlines + subject = "".join(subject.splitlines()) + body = loader.render_to_string(email_template_name, context) + + email_message = EmailMultiAlternatives(subject, body, from_email, [to_email]) + if html_email_template_name is not None: + html_email = loader.render_to_string(html_email_template_name, context) + email_message.attach_alternative(html_email, "text/html") + + email_message.send() + + def get_users(self, email): + """Given an email, return matching user(s) who should receive a reset. + + This allows subclasses to more easily customize the default policies + that prevent inactive users and users with unusable passwords from + resetting their password. + """ + email_field_name = UserModel.get_email_field_name() + active_users = UserModel._default_manager.filter( + **{ + "%s__iexact" % email_field_name: email, + "is_active": True, + } + ) + return ( + u + for u in active_users + if u.has_usable_password() + and _unicode_ci_compare(email, getattr(u, email_field_name)) + ) + + def save( + self, + domain_override=None, + subject_template_name="registration/password_reset_subject.txt", + email_template_name="registration/password_reset_email.html", + use_https=False, + token_generator=default_token_generator, + from_email=None, + request=None, + html_email_template_name=None, + extra_email_context=None, + ): + """ + Generate a one-use only link for resetting password and send it to the + user. + """ + email = self.cleaned_data["email"] + if not domain_override: + current_site = get_current_site(request) + site_name = current_site.name + domain = current_site.domain + else: + site_name = domain = domain_override + email_field_name = UserModel.get_email_field_name() + for user in self.get_users(email): + user_email = getattr(user, email_field_name) + context = { + "email": user_email, + "domain": domain, + "site_name": site_name, + "uid": urlsafe_base64_encode(force_bytes(user.pk)), + "user": user, + "token": token_generator.make_token(user), + "protocol": "https" if use_https else "http", + **(extra_email_context or {}), + } + self.send_mail( + subject_template_name, + email_template_name, + context, + from_email, + user_email, + html_email_template_name=html_email_template_name, + ) + + +class SetPasswordForm(forms.Form): + """ + A form that lets a user set their password without entering the old + password + """ + + error_messages = { + "password_mismatch": _("The two password fields didn’t match."), + } + new_password1 = forms.CharField( + label=_("New password"), + widget=forms.PasswordInput(attrs={"autocomplete": "new-password"}), + strip=False, + help_text=password_validation.password_validators_help_text_html(), + ) + new_password2 = forms.CharField( + label=_("New password confirmation"), + strip=False, + widget=forms.PasswordInput(attrs={"autocomplete": "new-password"}), + ) + + def __init__(self, user, *args, **kwargs): + self.user = user + super().__init__(*args, **kwargs) + + def clean_new_password2(self): + password1 = self.cleaned_data.get("new_password1") + password2 = self.cleaned_data.get("new_password2") + if password1 and password2 and password1 != password2: + raise ValidationError( + self.error_messages["password_mismatch"], + code="password_mismatch", + ) + password_validation.validate_password(password2, self.user) + return password2 + + def save(self, commit=True): + password = self.cleaned_data["new_password1"] + self.user.set_password(password) + if commit: + self.user.save() + return self.user + + +class PasswordChangeForm(SetPasswordForm): + """ + A form that lets a user change their password by entering their old + password. + """ + + error_messages = { + **SetPasswordForm.error_messages, + "password_incorrect": _( + "Your old password was entered incorrectly. Please enter it again." + ), + } + old_password = forms.CharField( + label=_("Old password"), + strip=False, + widget=forms.PasswordInput( + attrs={"autocomplete": "current-password", "autofocus": True} + ), + ) + + field_order = ["old_password", "new_password1", "new_password2"] + + def clean_old_password(self): + """ + Validate that the old_password field is correct. + """ + old_password = self.cleaned_data["old_password"] + if not self.user.check_password(old_password): + raise ValidationError( + self.error_messages["password_incorrect"], + code="password_incorrect", + ) + return old_password + + +class AdminPasswordChangeForm(forms.Form): + """ + A form used to change the password of a user in the admin interface. + """ + + error_messages = { + "password_mismatch": _("The two password fields didn’t match."), + } + required_css_class = "required" + password1 = forms.CharField( + label=_("Password"), + widget=forms.PasswordInput( + attrs={"autocomplete": "new-password", "autofocus": True} + ), + strip=False, + help_text=password_validation.password_validators_help_text_html(), + ) + password2 = forms.CharField( + label=_("Password (again)"), + widget=forms.PasswordInput(attrs={"autocomplete": "new-password"}), + strip=False, + help_text=_("Enter the same password as before, for verification."), + ) + + def __init__(self, user, *args, **kwargs): + self.user = user + super().__init__(*args, **kwargs) + + def clean_password2(self): + password1 = self.cleaned_data.get("password1") + password2 = self.cleaned_data.get("password2") + if password1 and password2 and password1 != password2: + raise ValidationError( + self.error_messages["password_mismatch"], + code="password_mismatch", + ) + password_validation.validate_password(password2, self.user) + return password2 + + def save(self, commit=True): + """Save the new password.""" + password = self.cleaned_data["password1"] + self.user.set_password(password) + if commit: + self.user.save() + return self.user + + @property + def changed_data(self): + data = super().changed_data + for name in self.fields: + if name not in data: + return [] + return ["password"] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/handlers/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/handlers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/handlers/modwsgi.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/handlers/modwsgi.py new file mode 100644 index 0000000..591ec72 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/handlers/modwsgi.py @@ -0,0 +1,43 @@ +from django import db +from django.contrib import auth + +UserModel = auth.get_user_model() + + +def check_password(environ, username, password): + """ + Authenticate against Django's auth database. + + mod_wsgi docs specify None, True, False as return value depending + on whether the user exists and authenticates. + """ + # db connection state is managed similarly to the wsgi handler + # as mod_wsgi may call these functions outside of a request/response cycle + db.reset_queries() + try: + try: + user = UserModel._default_manager.get_by_natural_key(username) + except UserModel.DoesNotExist: + return None + if not user.is_active: + return None + return user.check_password(password) + finally: + db.close_old_connections() + + +def groups_for_user(environ, username): + """ + Authorize a user based on groups + """ + db.reset_queries() + try: + try: + user = UserModel._default_manager.get_by_natural_key(username) + except UserModel.DoesNotExist: + return [] + if not user.is_active: + return [] + return [group.name.encode() for group in user.groups.all()] + finally: + db.close_old_connections() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/hashers.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/hashers.py new file mode 100644 index 0000000..b63904c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/hashers.py @@ -0,0 +1,842 @@ +import base64 +import binascii +import functools +import hashlib +import importlib +import math +import warnings + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.core.signals import setting_changed +from django.dispatch import receiver +from django.utils.crypto import ( + RANDOM_STRING_CHARS, + constant_time_compare, + get_random_string, + pbkdf2, +) +from django.utils.deprecation import RemovedInDjango51Warning +from django.utils.module_loading import import_string +from django.utils.translation import gettext_noop as _ + +UNUSABLE_PASSWORD_PREFIX = "!" # This will never be a valid encoded hash +UNUSABLE_PASSWORD_SUFFIX_LENGTH = ( + 40 # number of random chars to add after UNUSABLE_PASSWORD_PREFIX +) + + +def is_password_usable(encoded): + """ + Return True if this password wasn't generated by + User.set_unusable_password(), i.e. make_password(None). + """ + return encoded is None or not encoded.startswith(UNUSABLE_PASSWORD_PREFIX) + + +def verify_password(password, encoded, preferred="default"): + """ + Return two booleans. The first is whether the raw password matches the + three part encoded digest, and the second whether to regenerate the + password. + """ + if password is None or not is_password_usable(encoded): + return False, False + + preferred = get_hasher(preferred) + try: + hasher = identify_hasher(encoded) + except ValueError: + # encoded is gibberish or uses a hasher that's no longer installed. + return False, False + + hasher_changed = hasher.algorithm != preferred.algorithm + must_update = hasher_changed or preferred.must_update(encoded) + is_correct = hasher.verify(password, encoded) + + # If the hasher didn't change (we don't protect against enumeration if it + # does) and the password should get updated, try to close the timing gap + # between the work factor of the current encoded password and the default + # work factor. + if not is_correct and not hasher_changed and must_update: + hasher.harden_runtime(password, encoded) + + return is_correct, must_update + + +def check_password(password, encoded, setter=None, preferred="default"): + """ + Return a boolean of whether the raw password matches the three part encoded + digest. + + If setter is specified, it'll be called when you need to regenerate the + password. + """ + is_correct, must_update = verify_password(password, encoded, preferred=preferred) + if setter and is_correct and must_update: + setter(password) + return is_correct + + +async def acheck_password(password, encoded, setter=None, preferred="default"): + """See check_password().""" + is_correct, must_update = verify_password(password, encoded, preferred=preferred) + if setter and is_correct and must_update: + await setter(password) + return is_correct + + +def make_password(password, salt=None, hasher="default"): + """ + Turn a plain-text password into a hash for database storage + + Same as encode() but generate a new random salt. If password is None then + return a concatenation of UNUSABLE_PASSWORD_PREFIX and a random string, + which disallows logins. Additional random string reduces chances of gaining + access to staff or superuser accounts. See ticket #20079 for more info. + """ + if password is None: + return UNUSABLE_PASSWORD_PREFIX + get_random_string( + UNUSABLE_PASSWORD_SUFFIX_LENGTH + ) + if not isinstance(password, (bytes, str)): + raise TypeError( + "Password must be a string or bytes, got %s." % type(password).__qualname__ + ) + hasher = get_hasher(hasher) + salt = salt or hasher.salt() + return hasher.encode(password, salt) + + +@functools.lru_cache +def get_hashers(): + hashers = [] + for hasher_path in settings.PASSWORD_HASHERS: + hasher_cls = import_string(hasher_path) + hasher = hasher_cls() + if not getattr(hasher, "algorithm"): + raise ImproperlyConfigured( + "hasher doesn't specify an algorithm name: %s" % hasher_path + ) + hashers.append(hasher) + return hashers + + +@functools.lru_cache +def get_hashers_by_algorithm(): + return {hasher.algorithm: hasher for hasher in get_hashers()} + + +@receiver(setting_changed) +def reset_hashers(*, setting, **kwargs): + if setting == "PASSWORD_HASHERS": + get_hashers.cache_clear() + get_hashers_by_algorithm.cache_clear() + + +def get_hasher(algorithm="default"): + """ + Return an instance of a loaded password hasher. + + If algorithm is 'default', return the default hasher. Lazily import hashers + specified in the project's settings file if needed. + """ + if hasattr(algorithm, "algorithm"): + return algorithm + + elif algorithm == "default": + return get_hashers()[0] + + else: + hashers = get_hashers_by_algorithm() + try: + return hashers[algorithm] + except KeyError: + raise ValueError( + "Unknown password hashing algorithm '%s'. " + "Did you specify it in the PASSWORD_HASHERS " + "setting?" % algorithm + ) + + +def identify_hasher(encoded): + """ + Return an instance of a loaded password hasher. + + Identify hasher algorithm by examining encoded hash, and call + get_hasher() to return hasher. Raise ValueError if + algorithm cannot be identified, or if hasher is not loaded. + """ + # Ancient versions of Django created plain MD5 passwords and accepted + # MD5 passwords with an empty salt. + if (len(encoded) == 32 and "$" not in encoded) or ( + len(encoded) == 37 and encoded.startswith("md5$$") + ): + algorithm = "unsalted_md5" + # Ancient versions of Django accepted SHA1 passwords with an empty salt. + elif len(encoded) == 46 and encoded.startswith("sha1$$"): + algorithm = "unsalted_sha1" + else: + algorithm = encoded.split("$", 1)[0] + return get_hasher(algorithm) + + +def mask_hash(hash, show=6, char="*"): + """ + Return the given hash, with only the first ``show`` number shown. The + rest are masked with ``char`` for security reasons. + """ + masked = hash[:show] + masked += char * len(hash[show:]) + return masked + + +def must_update_salt(salt, expected_entropy): + # Each character in the salt provides log_2(len(alphabet)) bits of entropy. + return len(salt) * math.log2(len(RANDOM_STRING_CHARS)) < expected_entropy + + +class BasePasswordHasher: + """ + Abstract base class for password hashers + + When creating your own hasher, you need to override algorithm, + verify(), encode() and safe_summary(). + + PasswordHasher objects are immutable. + """ + + algorithm = None + library = None + salt_entropy = 128 + + def _load_library(self): + if self.library is not None: + if isinstance(self.library, (tuple, list)): + name, mod_path = self.library + else: + mod_path = self.library + try: + module = importlib.import_module(mod_path) + except ImportError as e: + raise ValueError( + "Couldn't load %r algorithm library: %s" + % (self.__class__.__name__, e) + ) + return module + raise ValueError( + "Hasher %r doesn't specify a library attribute" % self.__class__.__name__ + ) + + def salt(self): + """ + Generate a cryptographically secure nonce salt in ASCII with an entropy + of at least `salt_entropy` bits. + """ + # Each character in the salt provides + # log_2(len(alphabet)) bits of entropy. + char_count = math.ceil(self.salt_entropy / math.log2(len(RANDOM_STRING_CHARS))) + return get_random_string(char_count, allowed_chars=RANDOM_STRING_CHARS) + + def verify(self, password, encoded): + """Check if the given password is correct.""" + raise NotImplementedError( + "subclasses of BasePasswordHasher must provide a verify() method" + ) + + def _check_encode_args(self, password, salt): + if password is None: + raise TypeError("password must be provided.") + if not salt or "$" in salt: + raise ValueError("salt must be provided and cannot contain $.") + + def encode(self, password, salt): + """ + Create an encoded database value. + + The result is normally formatted as "algorithm$salt$hash" and + must be fewer than 128 characters. + """ + raise NotImplementedError( + "subclasses of BasePasswordHasher must provide an encode() method" + ) + + def decode(self, encoded): + """ + Return a decoded database value. + + The result is a dictionary and should contain `algorithm`, `hash`, and + `salt`. Extra keys can be algorithm specific like `iterations` or + `work_factor`. + """ + raise NotImplementedError( + "subclasses of BasePasswordHasher must provide a decode() method." + ) + + def safe_summary(self, encoded): + """ + Return a summary of safe values. + + The result is a dictionary and will be used where the password field + must be displayed to construct a safe representation of the password. + """ + raise NotImplementedError( + "subclasses of BasePasswordHasher must provide a safe_summary() method" + ) + + def must_update(self, encoded): + return False + + def harden_runtime(self, password, encoded): + """ + Bridge the runtime gap between the work factor supplied in `encoded` + and the work factor suggested by this hasher. + + Taking PBKDF2 as an example, if `encoded` contains 20000 iterations and + `self.iterations` is 30000, this method should run password through + another 10000 iterations of PBKDF2. Similar approaches should exist + for any hasher that has a work factor. If not, this method should be + defined as a no-op to silence the warning. + """ + warnings.warn( + "subclasses of BasePasswordHasher should provide a harden_runtime() method" + ) + + +class PBKDF2PasswordHasher(BasePasswordHasher): + """ + Secure password hashing using the PBKDF2 algorithm (recommended) + + Configured to use PBKDF2 + HMAC + SHA256. + The result is a 64 byte binary string. Iterations may be changed + safely but you must rename the algorithm if you change SHA256. + """ + + algorithm = "pbkdf2_sha256" + iterations = 720000 + digest = hashlib.sha256 + + def encode(self, password, salt, iterations=None): + self._check_encode_args(password, salt) + iterations = iterations or self.iterations + hash = pbkdf2(password, salt, iterations, digest=self.digest) + hash = base64.b64encode(hash).decode("ascii").strip() + return "%s$%d$%s$%s" % (self.algorithm, iterations, salt, hash) + + def decode(self, encoded): + algorithm, iterations, salt, hash = encoded.split("$", 3) + assert algorithm == self.algorithm + return { + "algorithm": algorithm, + "hash": hash, + "iterations": int(iterations), + "salt": salt, + } + + def verify(self, password, encoded): + decoded = self.decode(encoded) + encoded_2 = self.encode(password, decoded["salt"], decoded["iterations"]) + return constant_time_compare(encoded, encoded_2) + + def safe_summary(self, encoded): + decoded = self.decode(encoded) + return { + _("algorithm"): decoded["algorithm"], + _("iterations"): decoded["iterations"], + _("salt"): mask_hash(decoded["salt"]), + _("hash"): mask_hash(decoded["hash"]), + } + + def must_update(self, encoded): + decoded = self.decode(encoded) + update_salt = must_update_salt(decoded["salt"], self.salt_entropy) + return (decoded["iterations"] != self.iterations) or update_salt + + def harden_runtime(self, password, encoded): + decoded = self.decode(encoded) + extra_iterations = self.iterations - decoded["iterations"] + if extra_iterations > 0: + self.encode(password, decoded["salt"], extra_iterations) + + +class PBKDF2SHA1PasswordHasher(PBKDF2PasswordHasher): + """ + Alternate PBKDF2 hasher which uses SHA1, the default PRF + recommended by PKCS #5. This is compatible with other + implementations of PBKDF2, such as openssl's + PKCS5_PBKDF2_HMAC_SHA1(). + """ + + algorithm = "pbkdf2_sha1" + digest = hashlib.sha1 + + +class Argon2PasswordHasher(BasePasswordHasher): + """ + Secure password hashing using the argon2 algorithm. + + This is the winner of the Password Hashing Competition 2013-2015 + (https://password-hashing.net). It requires the argon2-cffi library which + depends on native C code and might cause portability issues. + """ + + algorithm = "argon2" + library = "argon2" + + time_cost = 2 + memory_cost = 102400 + parallelism = 8 + + def encode(self, password, salt): + argon2 = self._load_library() + params = self.params() + data = argon2.low_level.hash_secret( + password.encode(), + salt.encode(), + time_cost=params.time_cost, + memory_cost=params.memory_cost, + parallelism=params.parallelism, + hash_len=params.hash_len, + type=params.type, + ) + return self.algorithm + data.decode("ascii") + + def decode(self, encoded): + argon2 = self._load_library() + algorithm, rest = encoded.split("$", 1) + assert algorithm == self.algorithm + params = argon2.extract_parameters("$" + rest) + variety, *_, b64salt, hash = rest.split("$") + # Add padding. + b64salt += "=" * (-len(b64salt) % 4) + salt = base64.b64decode(b64salt).decode("latin1") + return { + "algorithm": algorithm, + "hash": hash, + "memory_cost": params.memory_cost, + "parallelism": params.parallelism, + "salt": salt, + "time_cost": params.time_cost, + "variety": variety, + "version": params.version, + "params": params, + } + + def verify(self, password, encoded): + argon2 = self._load_library() + algorithm, rest = encoded.split("$", 1) + assert algorithm == self.algorithm + try: + return argon2.PasswordHasher().verify("$" + rest, password) + except argon2.exceptions.VerificationError: + return False + + def safe_summary(self, encoded): + decoded = self.decode(encoded) + return { + _("algorithm"): decoded["algorithm"], + _("variety"): decoded["variety"], + _("version"): decoded["version"], + _("memory cost"): decoded["memory_cost"], + _("time cost"): decoded["time_cost"], + _("parallelism"): decoded["parallelism"], + _("salt"): mask_hash(decoded["salt"]), + _("hash"): mask_hash(decoded["hash"]), + } + + def must_update(self, encoded): + decoded = self.decode(encoded) + current_params = decoded["params"] + new_params = self.params() + # Set salt_len to the salt_len of the current parameters because salt + # is explicitly passed to argon2. + new_params.salt_len = current_params.salt_len + update_salt = must_update_salt(decoded["salt"], self.salt_entropy) + return (current_params != new_params) or update_salt + + def harden_runtime(self, password, encoded): + # The runtime for Argon2 is too complicated to implement a sensible + # hardening algorithm. + pass + + def params(self): + argon2 = self._load_library() + # salt_len is a noop, because we provide our own salt. + return argon2.Parameters( + type=argon2.low_level.Type.ID, + version=argon2.low_level.ARGON2_VERSION, + salt_len=argon2.DEFAULT_RANDOM_SALT_LENGTH, + hash_len=argon2.DEFAULT_HASH_LENGTH, + time_cost=self.time_cost, + memory_cost=self.memory_cost, + parallelism=self.parallelism, + ) + + +class BCryptSHA256PasswordHasher(BasePasswordHasher): + """ + Secure password hashing using the bcrypt algorithm (recommended) + + This is considered by many to be the most secure algorithm but you + must first install the bcrypt library. Please be warned that + this library depends on native C code and might cause portability + issues. + """ + + algorithm = "bcrypt_sha256" + digest = hashlib.sha256 + library = ("bcrypt", "bcrypt") + rounds = 12 + + def salt(self): + bcrypt = self._load_library() + return bcrypt.gensalt(self.rounds) + + def encode(self, password, salt): + bcrypt = self._load_library() + password = password.encode() + # Hash the password prior to using bcrypt to prevent password + # truncation as described in #20138. + if self.digest is not None: + # Use binascii.hexlify() because a hex encoded bytestring is str. + password = binascii.hexlify(self.digest(password).digest()) + + data = bcrypt.hashpw(password, salt) + return "%s$%s" % (self.algorithm, data.decode("ascii")) + + def decode(self, encoded): + algorithm, empty, algostr, work_factor, data = encoded.split("$", 4) + assert algorithm == self.algorithm + return { + "algorithm": algorithm, + "algostr": algostr, + "checksum": data[22:], + "salt": data[:22], + "work_factor": int(work_factor), + } + + def verify(self, password, encoded): + algorithm, data = encoded.split("$", 1) + assert algorithm == self.algorithm + encoded_2 = self.encode(password, data.encode("ascii")) + return constant_time_compare(encoded, encoded_2) + + def safe_summary(self, encoded): + decoded = self.decode(encoded) + return { + _("algorithm"): decoded["algorithm"], + _("work factor"): decoded["work_factor"], + _("salt"): mask_hash(decoded["salt"]), + _("checksum"): mask_hash(decoded["checksum"]), + } + + def must_update(self, encoded): + decoded = self.decode(encoded) + return decoded["work_factor"] != self.rounds + + def harden_runtime(self, password, encoded): + _, data = encoded.split("$", 1) + salt = data[:29] # Length of the salt in bcrypt. + rounds = data.split("$")[2] + # work factor is logarithmic, adding one doubles the load. + diff = 2 ** (self.rounds - int(rounds)) - 1 + while diff > 0: + self.encode(password, salt.encode("ascii")) + diff -= 1 + + +class BCryptPasswordHasher(BCryptSHA256PasswordHasher): + """ + Secure password hashing using the bcrypt algorithm + + This is considered by many to be the most secure algorithm but you + must first install the bcrypt library. Please be warned that + this library depends on native C code and might cause portability + issues. + + This hasher does not first hash the password which means it is subject to + bcrypt's 72 bytes password truncation. Most use cases should prefer the + BCryptSHA256PasswordHasher. + """ + + algorithm = "bcrypt" + digest = None + + +class ScryptPasswordHasher(BasePasswordHasher): + """ + Secure password hashing using the Scrypt algorithm. + """ + + algorithm = "scrypt" + block_size = 8 + maxmem = 0 + parallelism = 1 + work_factor = 2**14 + + def encode(self, password, salt, n=None, r=None, p=None): + self._check_encode_args(password, salt) + n = n or self.work_factor + r = r or self.block_size + p = p or self.parallelism + hash_ = hashlib.scrypt( + password.encode(), + salt=salt.encode(), + n=n, + r=r, + p=p, + maxmem=self.maxmem, + dklen=64, + ) + hash_ = base64.b64encode(hash_).decode("ascii").strip() + return "%s$%d$%s$%d$%d$%s" % (self.algorithm, n, salt, r, p, hash_) + + def decode(self, encoded): + algorithm, work_factor, salt, block_size, parallelism, hash_ = encoded.split( + "$", 6 + ) + assert algorithm == self.algorithm + return { + "algorithm": algorithm, + "work_factor": int(work_factor), + "salt": salt, + "block_size": int(block_size), + "parallelism": int(parallelism), + "hash": hash_, + } + + def verify(self, password, encoded): + decoded = self.decode(encoded) + encoded_2 = self.encode( + password, + decoded["salt"], + decoded["work_factor"], + decoded["block_size"], + decoded["parallelism"], + ) + return constant_time_compare(encoded, encoded_2) + + def safe_summary(self, encoded): + decoded = self.decode(encoded) + return { + _("algorithm"): decoded["algorithm"], + _("work factor"): decoded["work_factor"], + _("block size"): decoded["block_size"], + _("parallelism"): decoded["parallelism"], + _("salt"): mask_hash(decoded["salt"]), + _("hash"): mask_hash(decoded["hash"]), + } + + def must_update(self, encoded): + decoded = self.decode(encoded) + return ( + decoded["work_factor"] != self.work_factor + or decoded["block_size"] != self.block_size + or decoded["parallelism"] != self.parallelism + ) + + def harden_runtime(self, password, encoded): + # The runtime for Scrypt is too complicated to implement a sensible + # hardening algorithm. + pass + + +# RemovedInDjango51Warning. +class SHA1PasswordHasher(BasePasswordHasher): + """ + The SHA1 password hashing algorithm (not recommended) + """ + + algorithm = "sha1" + + def __init__(self, *args, **kwargs): + warnings.warn( + "django.contrib.auth.hashers.SHA1PasswordHasher is deprecated.", + RemovedInDjango51Warning, + stacklevel=2, + ) + super().__init__(*args, **kwargs) + + def encode(self, password, salt): + self._check_encode_args(password, salt) + hash = hashlib.sha1((salt + password).encode()).hexdigest() + return "%s$%s$%s" % (self.algorithm, salt, hash) + + def decode(self, encoded): + algorithm, salt, hash = encoded.split("$", 2) + assert algorithm == self.algorithm + return { + "algorithm": algorithm, + "hash": hash, + "salt": salt, + } + + def verify(self, password, encoded): + decoded = self.decode(encoded) + encoded_2 = self.encode(password, decoded["salt"]) + return constant_time_compare(encoded, encoded_2) + + def safe_summary(self, encoded): + decoded = self.decode(encoded) + return { + _("algorithm"): decoded["algorithm"], + _("salt"): mask_hash(decoded["salt"], show=2), + _("hash"): mask_hash(decoded["hash"]), + } + + def must_update(self, encoded): + decoded = self.decode(encoded) + return must_update_salt(decoded["salt"], self.salt_entropy) + + def harden_runtime(self, password, encoded): + pass + + +class MD5PasswordHasher(BasePasswordHasher): + """ + The Salted MD5 password hashing algorithm (not recommended) + """ + + algorithm = "md5" + + def encode(self, password, salt): + self._check_encode_args(password, salt) + hash = hashlib.md5((salt + password).encode()).hexdigest() + return "%s$%s$%s" % (self.algorithm, salt, hash) + + def decode(self, encoded): + algorithm, salt, hash = encoded.split("$", 2) + assert algorithm == self.algorithm + return { + "algorithm": algorithm, + "hash": hash, + "salt": salt, + } + + def verify(self, password, encoded): + decoded = self.decode(encoded) + encoded_2 = self.encode(password, decoded["salt"]) + return constant_time_compare(encoded, encoded_2) + + def safe_summary(self, encoded): + decoded = self.decode(encoded) + return { + _("algorithm"): decoded["algorithm"], + _("salt"): mask_hash(decoded["salt"], show=2), + _("hash"): mask_hash(decoded["hash"]), + } + + def must_update(self, encoded): + decoded = self.decode(encoded) + return must_update_salt(decoded["salt"], self.salt_entropy) + + def harden_runtime(self, password, encoded): + pass + + +# RemovedInDjango51Warning. +class UnsaltedSHA1PasswordHasher(BasePasswordHasher): + """ + Very insecure algorithm that you should *never* use; store SHA1 hashes + with an empty salt. + + This class is implemented because Django used to accept such password + hashes. Some older Django installs still have these values lingering + around so we need to handle and upgrade them properly. + """ + + algorithm = "unsalted_sha1" + + def __init__(self, *args, **kwargs): + warnings.warn( + "django.contrib.auth.hashers.UnsaltedSHA1PasswordHasher is deprecated.", + RemovedInDjango51Warning, + stacklevel=2, + ) + super().__init__(*args, **kwargs) + + def salt(self): + return "" + + def encode(self, password, salt): + if salt != "": + raise ValueError("salt must be empty.") + hash = hashlib.sha1(password.encode()).hexdigest() + return "sha1$$%s" % hash + + def decode(self, encoded): + assert encoded.startswith("sha1$$") + return { + "algorithm": self.algorithm, + "hash": encoded[6:], + "salt": None, + } + + def verify(self, password, encoded): + encoded_2 = self.encode(password, "") + return constant_time_compare(encoded, encoded_2) + + def safe_summary(self, encoded): + decoded = self.decode(encoded) + return { + _("algorithm"): decoded["algorithm"], + _("hash"): mask_hash(decoded["hash"]), + } + + def harden_runtime(self, password, encoded): + pass + + +# RemovedInDjango51Warning. +class UnsaltedMD5PasswordHasher(BasePasswordHasher): + """ + Incredibly insecure algorithm that you should *never* use; stores unsalted + MD5 hashes without the algorithm prefix, also accepts MD5 hashes with an + empty salt. + + This class is implemented because Django used to store passwords this way + and to accept such password hashes. Some older Django installs still have + these values lingering around so we need to handle and upgrade them + properly. + """ + + algorithm = "unsalted_md5" + + def __init__(self, *args, **kwargs): + warnings.warn( + "django.contrib.auth.hashers.UnsaltedMD5PasswordHasher is deprecated.", + RemovedInDjango51Warning, + stacklevel=2, + ) + super().__init__(*args, **kwargs) + + def salt(self): + return "" + + def encode(self, password, salt): + if salt != "": + raise ValueError("salt must be empty.") + return hashlib.md5(password.encode()).hexdigest() + + def decode(self, encoded): + return { + "algorithm": self.algorithm, + "hash": encoded, + "salt": None, + } + + def verify(self, password, encoded): + if len(encoded) == 37: + encoded = encoded.removeprefix("md5$$") + encoded_2 = self.encode(password, "") + return constant_time_compare(encoded, encoded_2) + + def safe_summary(self, encoded): + decoded = self.decode(encoded) + return { + _("algorithm"): decoded["algorithm"], + _("hash"): mask_hash(decoded["hash"], show=3), + } + + def harden_runtime(self, password, encoded): + pass diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/af/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/af/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e8fd6ba Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/af/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/af/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/af/LC_MESSAGES/django.po new file mode 100644 index 0000000..7072cd9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/af/LC_MESSAGES/django.po @@ -0,0 +1,307 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# F Wolff , 2019-2020,2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-12-04 08:09+0000\n" +"Last-Translator: F Wolff , 2019-2020,2023\n" +"Language-Team: Afrikaans (http://app.transifex.com/django/django/language/" +"af/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: af\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Persoonlike inligting" + +msgid "Permissions" +msgstr "Toestemmings" + +msgid "Important dates" +msgstr "Belangrike datums" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(name)s-objek met primêre sleutel %(key)r bestaan nie." + +msgid "Password changed successfully." +msgstr "Wagwoord is suksesvol verander." + +#, python-format +msgid "Change password: %s" +msgstr "Verander wagwoord: %s" + +msgid "Authentication and Authorization" +msgstr "Waarmerking en magtiging" + +msgid "password" +msgstr "wagwoord" + +msgid "last login" +msgstr "laas aangemeld" + +msgid "No password set." +msgstr "Geen wagwoord gestel nie." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Ongeldige wagwoordformaat of onbekende hutsalgoritme." + +msgid "The two password fields didn’t match." +msgstr "Die twee wagwoordvelde stem nie ooreen nie" + +msgid "Password" +msgstr "Wagwoord" + +msgid "Password confirmation" +msgstr "Wagwoordbevestiging" + +msgid "Enter the same password as before, for verification." +msgstr "Tik die wagwoord net soos tevore om te bevestig." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Rou wagwoorde word nie gestoor nie, dus is daar geen manier om die gebruiker " +"se wagwoord te sien nie, maar die wagwoord kan gewysig word met hierdie vorm." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Tik asb. 'n korrekte %(username)s en wagwoord. Neem kennis dat altwee velde " +"moontlik kassensitief is." + +msgid "This account is inactive." +msgstr "Dié rekening is nie aktief nie." + +msgid "Email" +msgstr "E-pos" + +msgid "New password" +msgstr "Nuwe wagwoord" + +msgid "New password confirmation" +msgstr "Bevestiging van nuwe wagwoord" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Die ou wagwoord is verkeerd ingetik. Tik dit asb. weer in." + +msgid "Old password" +msgstr "Ou wagwoord" + +msgid "Password (again)" +msgstr "Wagwoord (weer)" + +msgid "algorithm" +msgstr "algoritme" + +msgid "iterations" +msgstr "iterasies" + +msgid "salt" +msgstr "sout" + +msgid "hash" +msgstr "hutswaarde" + +msgid "variety" +msgstr "variëteit" + +msgid "version" +msgstr "weergawe" + +msgid "memory cost" +msgstr "geheuekoste" + +msgid "time cost" +msgstr "tydkoste" + +msgid "parallelism" +msgstr "parallelisme" + +msgid "work factor" +msgstr "werkfaktor" + +msgid "checksum" +msgstr "kontrolesom" + +msgid "block size" +msgstr "blokgrootte" + +msgid "name" +msgstr "naam" + +msgid "content type" +msgstr "inhoudtipe" + +msgid "codename" +msgstr "kodenaam" + +msgid "permission" +msgstr "toestemming" + +msgid "permissions" +msgstr "toestemmings" + +msgid "group" +msgstr "groep" + +msgid "groups" +msgstr "groepe" + +msgid "superuser status" +msgstr "supergebruikerstatus" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Dui aan dat die gebruiker alle toestemmings het sonder om hulle eksplisiet " +"toe te ken." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Die groepe waaraan die gebruiker behoort. ’n Gebruiker sal alle toestemmings " +"hê wat aan elkeen van sy groepe gegee is." + +msgid "user permissions" +msgstr "gebruikertoestemmings" + +msgid "Specific permissions for this user." +msgstr "Spesifieke toestemmings vir dié gebruiker." + +msgid "username" +msgstr "gebruikernaam" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Vereis. Hoogstens 150 karakters. Slegs: letters, syfers en die karakters @/./" +"+/-/_" + +msgid "A user with that username already exists." +msgstr "’n Gebruiker met daardie gebruikernaam bestaan reeds." + +msgid "first name" +msgstr "naam" + +msgid "last name" +msgstr "van" + +msgid "email address" +msgstr "e-posadres" + +msgid "staff status" +msgstr "personeelstatus" + +msgid "Designates whether the user can log into this admin site." +msgstr "Dui aan of die gebruiker by dié adminwerf kan aanmeld." + +msgid "active" +msgstr "aktief" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Dui aan of dié gebruiker as aktief gesien moet word. Neem merkie weg in " +"plaas van om rekeninge te skrap." + +msgid "date joined" +msgstr "datum aangesluit" + +msgid "user" +msgstr "gebruiker" + +msgid "users" +msgstr "gebruikers" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Dié wagwoord is te kort. Dit moet ten minste %(min_length)d karakter bevat." +msgstr[1] "" +"Dié wagwoord is te kort. Dit moet ten minste %(min_length)d karakters bevat." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "’n Wagwoord moet ten minste %(min_length)d karakter bevat." +msgstr[1] "’n Wagwoord moet ten minste %(min_length)d karakters bevat." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Die wagwoord is te soortgelyk aan die %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" +"Die wagwoord mag nie soortgelyk wees aan u ander persoonlike inligting nie." + +msgid "This password is too common." +msgstr "Dié wagwoord is te algemeen." + +msgid "Your password can’t be a commonly used password." +msgstr "U wagwoord mag nie ’n algemeen gebruikte wagwoord wees nie." + +msgid "This password is entirely numeric." +msgstr "Dié wagwoord is heeltemal numeries." + +msgid "Your password can’t be entirely numeric." +msgstr "Die wagwoord mag nie geheel numeries wees nie." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Wagwoordherstel op %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Tik ’n geldige gebruikernaam. Dié waarde mag slegs hoof- en kleinletters " +"sonder aksente, syfers en die karakters @/./+/-/_ bevat." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Tik 'n geldige gebruikernaam. Dié waarde mag slegs letters, syfers en die " +"karakters @/./+/-/_ bevat." + +msgid "Logged out" +msgstr "Afgemeld" + +msgid "Password reset" +msgstr "Wagwoordherstel" + +msgid "Password reset sent" +msgstr "Wagwoordherstel gestuur" + +msgid "Enter new password" +msgstr "Tik nuwe wagwoord" + +msgid "Password reset unsuccessful" +msgstr "Herstel van wagwoord onsuksesvol" + +msgid "Password reset complete" +msgstr "Herstel van wagwoord is voltooi" + +msgid "Password change" +msgstr "Wagwoordverandering" + +msgid "Password change successful" +msgstr "Verandering van wagwoord was suksesvol" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ar/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ar/LC_MESSAGES/django.mo new file mode 100644 index 0000000..970d5e9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ar/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ar/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ar/LC_MESSAGES/django.po new file mode 100644 index 0000000..49ae8c6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ar/LC_MESSAGES/django.po @@ -0,0 +1,319 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ahmad Khayyat , 2013,2021 +# Bashar Al-Abdulhadi, 2015-2016,2021 +# Bashar Al-Abdulhadi, 2014 +# Eyad Toma , 2013 +# Jannis Leidel , 2011 +# Omar Lajam, 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2021-10-15 21:38+0000\n" +"Last-Translator: Bashar Al-Abdulhadi\n" +"Language-Team: Arabic (http://www.transifex.com/django/django/language/ar/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +msgid "Personal info" +msgstr "المعلومات الشخصية" + +msgid "Permissions" +msgstr "الصلاحيات" + +msgid "Important dates" +msgstr "تواريخ مهمة" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "العنصر من نوع %(name)s ذو الحقل الأساسي %(key)r غير موجود." + +msgid "Password changed successfully." +msgstr "تم تغيير كلمة المرور بنجاح." + +#, python-format +msgid "Change password: %s" +msgstr "غيّر كلمة المرور: %s" + +msgid "Authentication and Authorization" +msgstr "المصادقة والتفويض" + +msgid "password" +msgstr "كلمة المرور" + +msgid "last login" +msgstr "آخر دخول" + +msgid "No password set." +msgstr "لم يتم تعيين كلمة المرور." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" +"صيغة كلمة المرور غير صحيحة أو أن خوارزمية البعثرة (hashing) غير معروفة." + +msgid "The two password fields didn’t match." +msgstr "حقلا كلمة المرور غير متطابقين." + +msgid "Password" +msgstr "كلمة المرور" + +msgid "Password confirmation" +msgstr "تأكيد كلمة المرور" + +msgid "Enter the same password as before, for verification." +msgstr "أدخل كلمة المرور أعلاه مرة أخرى لتأكيدها." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"لا يتم حفظ كلمات المرور بصورتها الأصلية، لذلك لا يمكنك عرض كلمة مرور هذا " +"المستخدم، لكن يمكنك تغييرها باستخدام هذا النموذج" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "الرجاء إدخال %(username)s وكلمة السر الصحيحين." + +msgid "This account is inactive." +msgstr "هذا الحساب غير نشط." + +msgid "Email" +msgstr "بريد إلكتروني" + +msgid "New password" +msgstr "كلمة المرور الجديدة" + +msgid "New password confirmation" +msgstr "تأكيد كلمة المرور الجديدة" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "كلمة مرورك القديمة غير صحيحة. رجاءً أدخلها مرة أخرى." + +msgid "Old password" +msgstr "كلمة المرور القديمة" + +msgid "Password (again)" +msgstr "كلمة المرور (مجدداً)" + +msgid "algorithm" +msgstr "خوارزمية" + +msgid "iterations" +msgstr "التكرارات" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "منوّع" + +msgid "version" +msgstr "إصدار" + +msgid "memory cost" +msgstr "استهلاك الذاكرة" + +msgid "time cost" +msgstr "المدة المطلوبة" + +msgid "parallelism" +msgstr "التوازي" + +msgid "work factor" +msgstr "عامل العمل" + +msgid "checksum" +msgstr "تدقيق المجموع" + +msgid "block size" +msgstr "مقاس الكتله (البلوك)" + +msgid "name" +msgstr "الاسم" + +msgid "content type" +msgstr "نوع المحتوى" + +msgid "codename" +msgstr "الاسم الرمزي" + +msgid "permission" +msgstr "الصلاحية" + +msgid "permissions" +msgstr "الصلاحيات" + +msgid "group" +msgstr "مجموعة" + +msgid "groups" +msgstr "المجموعات" + +msgid "superuser status" +msgstr "حالة المستخدم الفائق" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"يقضي بأن هذا المستخدم يمتلك كافة الصلاحيات دون الحاجة لمنحها له تصريحاً." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"المجموعات التي ينتمي إليها هذا المستخدم. يحصل المستخدم على كافة الصلاحيات " +"الممنوحة لكل مجموعة ينتمي إليها." + +msgid "user permissions" +msgstr "صلاحيات المستخدم" + +msgid "Specific permissions for this user." +msgstr "صلاحيات خاصة بهذا المستخدم." + +msgid "username" +msgstr "اسم المستخدم" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "مطلوب. 150 رمزاً أو أقل، مكونة من حروف وأرقام و @/./+/-/_ فقط" + +msgid "A user with that username already exists." +msgstr "هناك مستخدم موجود مسبقاً بهذا الاسم." + +msgid "first name" +msgstr "الاسم الأول" + +msgid "last name" +msgstr "الاسم الأخير" + +msgid "email address" +msgstr "عنوان بريد إلكتروني" + +msgid "staff status" +msgstr "حالة الطاقم" + +msgid "Designates whether the user can log into this admin site." +msgstr "يحدد ما إذا كان يمكن للمستخدم الدخول إلى موقع الإدارة هذا." + +msgid "active" +msgstr "نشط" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"يحدد ما إذا كان المستخدم سيُعامل على أنّه نشط. أزل تحديد هذا الحقل بدلاً من حذف " +"الحسابات." + +msgid "date joined" +msgstr "تاريخ الانضمام" + +msgid "user" +msgstr "مستخدم" + +msgid "users" +msgstr "المستخدمون" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"كلمة المرور هذه قصيرة جدا. يجب أن تتكون من %(min_length)d حرف على الأقل." +msgstr[1] "" +"كلمة المرور هذه قصيرة جدا. يجب أن تتكون من %(min_length)d حرف واحد على الأقل." +msgstr[2] "" +"كلمة المرور هذه قصيرة جدا. يجب أن تتكون من %(min_length)d حرفين على الأقل." +msgstr[3] "" +"كلمة المرور هذه قصيرة جدا. يجب أن تتكون من %(min_length)d حروف على الأقل." +msgstr[4] "" +"كلمة المرور هذه قصيرة جدا. يجب أن تتكون من %(min_length)d حرف على الأقل." +msgstr[5] "" +"كلمة المرور هذه قصيرة جداً. يجب أن تتكون من %(min_length)d رمزاً على الأقل." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "كلمة المرور الخاصة بك يجب أن تتضمن %(min_length)d حرف على الأقل." +msgstr[1] "" +"كلمة المرور الخاصة بك يجب أن تتضمن %(min_length)d حرف واحد على الأقل." +msgstr[2] "كلمة المرور الخاصة بك يجب أن تتضمن %(min_length)d حرفين على الأقل." +msgstr[3] "كلمة المرور الخاصة بك يجب أن تتضمن %(min_length)d حروف على الأقل." +msgstr[4] "كلمة المرور الخاصة بك يجب أن تتضمن %(min_length)d أحرف على الأقل." +msgstr[5] "يجب أن تتكون كلمة المرور من %(min_length)d رمزاً على الأقل." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "كلمة المرور مشابهة جداً لـ %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "لا يمكن لكلمة المرور أن تكون مشابهة للمعلومات الشخصية الأخرى." + +msgid "This password is too common." +msgstr "كلمة المرور هذه شائعة جداً." + +msgid "Your password can’t be a commonly used password." +msgstr "لا يمكن أن تكون كلمة المرور شائعة الاستخدام." + +msgid "This password is entirely numeric." +msgstr "كلمة المرور هذه تتكون من أرقام فقط." + +msgid "Your password can’t be entirely numeric." +msgstr "لا يمكن أن تكون كلمة المرور مكونة من أرقام فقط." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "إعادة تعيين كلمة المرور على %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"أدخل اسم مستخدم صحيحاً. يمكن أن يتكون اسم المستخدم من أحرف إنجليزية وأرقام و " +"الرموز @/./+/-/_ فقط." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"أدخل اسم مستخدم صحيحاً. يمكن أن يتكون اسم المستخدم من حروف وأرقام و الرموز " +"@/./+/-/_ فقط." + +msgid "Logged out" +msgstr "تم الخروج" + +msgid "Password reset" +msgstr "إعادة ضبط كلمة المرور" + +msgid "Password reset sent" +msgstr " تم ارسال إعادة ضبط كلمة المرور" + +msgid "Enter new password" +msgstr "أدخل كلمة المرور الجديدة" + +msgid "Password reset unsuccessful" +msgstr "فشل عملية إعادة تعيين كلمة المرور" + +msgid "Password reset complete" +msgstr "تمت إعادة ضبط كلمة المرور" + +msgid "Password change" +msgstr "تغيير كلمة المرور" + +msgid "Password change successful" +msgstr "تم تغيير كلمة المرور بنجاح" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ar_DZ/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ar_DZ/LC_MESSAGES/django.mo new file mode 100644 index 0000000..203bf07 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ar_DZ/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ar_DZ/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ar_DZ/LC_MESSAGES/django.po new file mode 100644 index 0000000..c2b9f34 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ar_DZ/LC_MESSAGES/django.po @@ -0,0 +1,320 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jihad Bahmaid Al-Halki, 2022 +# Riterix , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2022-07-25 08:09+0000\n" +"Last-Translator: Jihad Bahmaid Al-Halki\n" +"Language-Team: Arabic (Algeria) (http://www.transifex.com/django/django/" +"language/ar_DZ/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar_DZ\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +msgid "Personal info" +msgstr "المعلومات الشخصية" + +msgid "Permissions" +msgstr "الصلاحيات" + +msgid "Important dates" +msgstr "تواريخ مهمة" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "العنصر %(name)s الذي به الحقل الأساسي %(key)r غير موجود." + +msgid "Password changed successfully." +msgstr "تم تغيير كلمة المرور بنجاح." + +#, python-format +msgid "Change password: %s" +msgstr "غيّر كلمة المرور: %s" + +msgid "Authentication and Authorization" +msgstr "المصادقة والتخويل" + +msgid "password" +msgstr "كلمة المرور" + +msgid "last login" +msgstr "آخر دخول" + +msgid "No password set." +msgstr "لا يوجد كلمة سر حتى الآن." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "تنسيق كلمة المرور غير صالح أو خوارزمية التجزئة غير معروفة." + +msgid "The two password fields didn’t match." +msgstr "حقلا كلمتي المرور غير متطابقين." + +msgid "Password" +msgstr "كلمة المرور" + +msgid "Password confirmation" +msgstr "تأكيد كلمة المرور" + +msgid "Enter the same password as before, for verification." +msgstr "أدخل كلمة المرور أعلاه مرة أخرى لتأكيدها." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"لا يتم تخزين كلمات المرور الخام ، لذلك لا توجد طريقة لرؤية كلمة مرور هذا " +"المستخدم ، ولكن يمكنك تغيير كلمة المرور باستخدام هذا " +"النموذج." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"الرجاء إدخال %(username)s وكلمة المرور الصحيحين. لاحظ أن كلا الحقلين قد يكون " +"حساسًا لحالة الأحرف." + +msgid "This account is inactive." +msgstr "هذا الحساب غير نشط." + +msgid "Email" +msgstr "بريد إلكتروني" + +msgid "New password" +msgstr "كلمة المرور الجديدة" + +msgid "New password confirmation" +msgstr "تأكيد كلمة المرور الجديدة" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "كلمة مرورك القديمة غير صحيحة. رجاءً أدخلها مرة أخرى." + +msgid "Old password" +msgstr "كلمة المرور القديمة" + +msgid "Password (again)" +msgstr "كلمة المرور (مجدداً)" + +msgid "algorithm" +msgstr "خوارزمية" + +msgid "iterations" +msgstr "التكرارات" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "تنوع" + +msgid "version" +msgstr "إصدار" + +msgid "memory cost" +msgstr "تكلفة الذاكرة" + +msgid "time cost" +msgstr "تكلفة الوقت" + +msgid "parallelism" +msgstr "تواز" + +msgid "work factor" +msgstr "عامل العمل" + +msgid "checksum" +msgstr "تدقيق المجموع" + +msgid "block size" +msgstr "حجم البلوك (Block)" + +msgid "name" +msgstr "الاسم" + +msgid "content type" +msgstr "نوع المحتوى" + +msgid "codename" +msgstr "الاسم الرمزي" + +msgid "permission" +msgstr "الصلاحية" + +msgid "permissions" +msgstr "الصلاحيات" + +msgid "group" +msgstr "مجموعة" + +msgid "groups" +msgstr "المجموعات" + +msgid "superuser status" +msgstr "حالة المستخدم الخارق" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"حدد بأن هذا المستخدم يمتلك كافة الصلاحيات دون الحاجة لتحديدها له تصريحا." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"المجموعات التي ينتمي إليها هذا المستخدم. ويمكن للمستخدم الحصول على كافة " +"الأذونات الممنوحة لكل من مجموعاتهم." + +msgid "user permissions" +msgstr "صلاحيات المستخدم" + +msgid "Specific permissions for this user." +msgstr "صلاحيات خاصة لهذا المستخدم." + +msgid "username" +msgstr "اسم المستخدم" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "مطلوب. 150 حرف أو أقل. الحروف والأرقام و @ /. / + / - / _ فقط." + +msgid "A user with that username already exists." +msgstr "هناك مستخدم موجود مسبقاً بهذا الاسم." + +msgid "first name" +msgstr "الاسم الأول" + +msgid "last name" +msgstr "الاسم الأخير" + +msgid "email address" +msgstr "عنوان بريد إلكتروني" + +msgid "staff status" +msgstr "حالة الطاقم" + +msgid "Designates whether the user can log into this admin site." +msgstr "يحدد ما إذا كان المستخدم يستطيع الدخول إلى موقع الإدارة هذا." + +msgid "active" +msgstr "نشط" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"يحدد ما إذا كان المستخدم سيُعامل على أنّه نشط. أزل تحديد ها الخيار بدلاً من حذف " +"الحسابات." + +msgid "date joined" +msgstr "تاريخ الانضمام" + +msgid "user" +msgstr "مستخدم" + +msgid "users" +msgstr "المستخدمين" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"كلمة المرور هذه قصيرة جدا. يجب أن تتكون من %(min_length)d حرف على الأقل." +msgstr[1] "" +"كلمة المرور هذه قصيرة جدا. يجب أن تتكون من %(min_length)d حرف واحد على الأقل." +msgstr[2] "" +"كلمة المرور هذه قصيرة جدا. يجب أن تتكون من %(min_length)d حرفين على الأقل." +msgstr[3] "" +"كلمة المرور هذه قصيرة جدا. يجب أن تتكون من %(min_length)d حروف على الأقل." +msgstr[4] "" +"كلمة المرور هذه قصيرة جدا. يجب أن تتكون من %(min_length)d حرف على الأقل." +msgstr[5] "" +"كلمة المرور هذه قصيرة جدا. يجب أن تتكون من %(min_length)d حرف على الأقل." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "كلمة المرور الخاصة بك يجب أن تتضمن %(min_length)d حرف على الأقل." +msgstr[1] "" +"كلمة المرور الخاصة بك يجب أن تتضمن %(min_length)d حرف واحد على الأقل." +msgstr[2] "كلمة المرور الخاصة بك يجب أن تتضمن %(min_length)d حرفين على الأقل." +msgstr[3] "كلمة المرور الخاصة بك يجب أن تتضمن %(min_length)d حروف على الأقل." +msgstr[4] "كلمة المرور الخاصة بك يجب أن تتضمن %(min_length)d أحرف على الأقل." +msgstr[5] "كلمة المرور الخاصة بك يجب أن تتضمن %(min_length)d حرف على الأقل." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "كلمة المرور هذه مشابة جدا لـ %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" +"كلمة المرور الخاصة بكم لا يمكن أن تكون مشابة لأي من المعلومات الشخصية الأخرى " +"الخاصة بك." + +msgid "This password is too common." +msgstr "كلمة المرور هذه شائعة جدا." + +msgid "Your password can’t be a commonly used password." +msgstr "كلمة المرور الخاصة بك لا يمكن أن تكون كلمة مرور مستخدمة بشكل شائع." + +msgid "This password is entirely numeric." +msgstr "كلمة المرور هذه تتكون من أرقام فقط." + +msgid "Your password can’t be entirely numeric." +msgstr "كلمة المرور الخاصة بك لا يمكن أن تكون أرقام فقط." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "إعادة تعيين كلمة المرور على %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"أدخل اسم مستخدم صالح. قد تحتوي هذه القيمة على الأحرف الإنجليزية والأرقام " +"والأحرف @ /. / + / - / _." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"أدخل اسم مستخدم صالح. قد تحتوي هذه القيمة على الأحرف والأرقام والأحرف @ /. / " +"+ / - / _." + +msgid "Logged out" +msgstr "تم الخروج" + +msgid "Password reset" +msgstr "إعادة ضبط كلمة المرور" + +msgid "Password reset sent" +msgstr "إعادة ضبط كلمة المرور تم ارسالها" + +msgid "Enter new password" +msgstr "أدخل كلمة المرور الجديدة" + +msgid "Password reset unsuccessful" +msgstr "فشل عملية إعادة تعيين كلمة المرور" + +msgid "Password reset complete" +msgstr "تم إعادة ضبط كلمة المرور بنجاح" + +msgid "Password change" +msgstr "تغيير كلمة المرور" + +msgid "Password change successful" +msgstr "تم تغيير كلمة المرور بنجاح" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ast/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ast/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e5f1ace Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ast/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ast/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ast/LC_MESSAGES/django.po new file mode 100644 index 0000000..f845205 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ast/LC_MESSAGES/django.po @@ -0,0 +1,284 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ḷḷumex03 , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-09-24 14:24+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Asturian (http://www.transifex.com/django/django/language/" +"ast/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ast\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Información personal" + +msgid "Permissions" +msgstr "Permisos" + +msgid "Important dates" +msgstr "Dates importantes" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "Contraseña camudada con ésitu." + +#, python-format +msgid "Change password: %s" +msgstr "Camudar contraseña: %s" + +msgid "Authentication and Authorization" +msgstr "" + +msgid "password" +msgstr "contraseña" + +msgid "last login" +msgstr "aniciu de sesión caberu" + +msgid "No password set." +msgstr "Nun s'afitó la contraseña." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Formatu de contraseña inválidu o algoritmu hash inválidu." + +msgid "The two password fields didn't match." +msgstr "Nun concasen los dos campos de contraseña." + +msgid "Password" +msgstr "Contraseña" + +msgid "Password confirmation" +msgstr "Confirmación de contraseña" + +msgid "Enter the same password as before, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" + +msgid "This account is inactive." +msgstr "Esta cuenta ta inactiva" + +msgid "Email" +msgstr "Corréu" + +msgid "New password" +msgstr "Contraseña nueva" + +msgid "New password confirmation" +msgstr "" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" + +msgid "Old password" +msgstr "" + +msgid "Password (again)" +msgstr "" + +msgid "algorithm" +msgstr "algoritmu" + +msgid "iterations" +msgstr "" + +msgid "salt" +msgstr "" + +msgid "hash" +msgstr "" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "" + +msgid "checksum" +msgstr "suma de comprobación" + +msgid "name" +msgstr "nome" + +msgid "content type" +msgstr "" + +msgid "codename" +msgstr "" + +msgid "permission" +msgstr "permisu" + +msgid "permissions" +msgstr "permisos" + +msgid "group" +msgstr "grupu" + +msgid "groups" +msgstr "grupos" + +msgid "superuser status" +msgstr "estáu de superusuariu" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "permisos d'usuariu" + +msgid "Specific permissions for this user." +msgstr "" + +msgid "username" +msgstr "nome d'usuariu" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "Yá esiste un usuariu con esi nome d'usuariu." + +msgid "first name" +msgstr "nome" + +msgid "last name" +msgstr "apellíos" + +msgid "email address" +msgstr "direición de corréu" + +msgid "staff status" +msgstr "" + +msgid "Designates whether the user can log into this admin site." +msgstr "" + +msgid "active" +msgstr "activu" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" + +msgid "date joined" +msgstr "" + +msgid "user" +msgstr "usuariu" + +msgid "users" +msgstr "usuarios" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "" + +msgid "Your password can't be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "" + +msgid "Your password can't be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "" + +msgid "Your password can't be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "" + +msgid "Password reset" +msgstr "" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "" + +msgid "Password reset unsuccessful" +msgstr "" + +msgid "Password reset complete" +msgstr "" + +msgid "Password change" +msgstr "" + +msgid "Password change successful" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/az/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/az/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c14fb27 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/az/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/az/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/az/LC_MESSAGES/django.po new file mode 100644 index 0000000..7dd8670 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/az/LC_MESSAGES/django.po @@ -0,0 +1,304 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ali Ismayilov , 2011 +# Emin Mastizada , 2018,2020 +# Emin Mastizada , 2016 +# Nicat Məmmədov , 2022 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2022-07-25 08:09+0000\n" +"Last-Translator: Nicat Məmmədov \n" +"Language-Team: Azerbaijani (http://www.transifex.com/django/django/language/" +"az/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: az\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Şəxsi məlumat" + +msgid "Permissions" +msgstr "İcazələr" + +msgid "Important dates" +msgstr "Vacib tarixlər" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "Əsas %(key)r açarı ilə %(name)s obyekti mövcud deyil." + +msgid "Password changed successfully." +msgstr "Şifrə uğurla dəyişdirildi." + +#, python-format +msgid "Change password: %s" +msgstr "Şifrəni dəyiş: %s" + +msgid "Authentication and Authorization" +msgstr "Təsdiqləmə və Səlahiyyət" + +msgid "password" +msgstr "şifrə" + +msgid "last login" +msgstr "son dəfə daxil olub" + +msgid "No password set." +msgstr "Şifrə təyin olunmayıb." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Xətalı şifrə formatı və ya bilinməyən heş alqoritması." + +msgid "The two password fields didn’t match." +msgstr "Şifrə xanalarının dəyərləri eyni deyil." + +msgid "Password" +msgstr "Şifrə" + +msgid "Password confirmation" +msgstr "Şifrənin təsdiqi" + +msgid "Enter the same password as before, for verification." +msgstr "Təsdiqləmək üçün əvvəlki ilə eyni şifrəni daxil edin." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Şifrələr açıq formada saxlanılmadığı üçün bu istifadəçinin şifrəsini görmək " +"mümkün deyil, amma bu formadan istifadə edərək şifrəni " +"dəyişə bilərsiz." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Lütfən düzgün %(username)s və şifrə daxil edin. Nəzərə alın ki, hər ikisi də " +"böyük-kiçik hərflərə həssasdırlar." + +msgid "This account is inactive." +msgstr "Bu hesab qeyri-aktivdir." + +msgid "Email" +msgstr "E-poçt" + +msgid "New password" +msgstr "Yeni şifrə" + +msgid "New password confirmation" +msgstr "Yeni şifrənin təsdiqi" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Köhnə şifrəni yanlış daxil etdiniz. Zəhmət olmasa bir daha yoxlayın." + +msgid "Old password" +msgstr "Köhnə şifrə" + +msgid "Password (again)" +msgstr "Şifrə (bir daha)" + +msgid "algorithm" +msgstr "alqoritm" + +msgid "iterations" +msgstr "təkrarlama" + +msgid "salt" +msgstr "duz" + +msgid "hash" +msgstr "heş" + +msgid "variety" +msgstr "müxtəliflik" + +msgid "version" +msgstr "versiya" + +msgid "memory cost" +msgstr "yaddaş xərci" + +msgid "time cost" +msgstr "vaxt xərci" + +msgid "parallelism" +msgstr "paralellik" + +msgid "work factor" +msgstr "iş faktoru" + +msgid "checksum" +msgstr "yoxlama dəyəri" + +msgid "block size" +msgstr "" + +msgid "name" +msgstr "ad" + +msgid "content type" +msgstr "məzmun növü" + +msgid "codename" +msgstr "kod adı" + +msgid "permission" +msgstr "icazə" + +msgid "permissions" +msgstr "icazələr" + +msgid "group" +msgstr "qrup" + +msgid "groups" +msgstr "qruplar" + +msgid "superuser status" +msgstr "superistifadəçi statusu" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "İstifadəçiyə bütün icazələri verir." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Bu istifadəçinin aid olduğu qruplar. İstifadə bu qruplardan hər birinə " +"verilən bütün icazələri alacaq." + +msgid "user permissions" +msgstr "səlahiyyətləri" + +msgid "Specific permissions for this user." +msgstr "Bu istifadəçiyə aid xüsusi icazələr." + +msgid "username" +msgstr "istifadəçi adı" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "Tələb edilir. Ən az 150 simvol. Ancaq hərf, rəqəm və @/./+/-/_." + +msgid "A user with that username already exists." +msgstr "Bu istifadəçi adı altında başqa istifadəçi var." + +msgid "first name" +msgstr "ad" + +msgid "last name" +msgstr "soyad" + +msgid "email address" +msgstr "e-poçt ünvanı" + +msgid "staff status" +msgstr "admin statusu" + +msgid "Designates whether the user can log into this admin site." +msgstr "İstifadəçinin admin panelinə daxil olub, olmayacağını təyin edir." + +msgid "active" +msgstr "Aktiv" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"İstifadəçinin aktiv və ya qeyri-aktiv olmasını təyin edir. Hesabları silmək " +"əvəzinə bundan istifadə edin." + +msgid "date joined" +msgstr "qoşulub" + +msgid "user" +msgstr "istifadəçi" + +msgid "users" +msgstr "istifadəçilər" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "Bu parol çox qısadır. Ən az %(min_length)d işarə olmalıdır." +msgstr[1] "" +"Bu şifrə çox qısadır. Ən az %(min_length)d simvoldan ibarət olmalıdır." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Parolunuz ən az %(min_length)d işarə olmalıdır." +msgstr[1] "Şifrəniz ən az %(min_length)d simvoldan ibarət olmalıdır." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Şifrəniz %(verbose_name)s ilə çox bənzərdir." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Şifrəniz digər şəxsi məlumatlarınıza çox bənzərdir." + +msgid "This password is too common." +msgstr "Bu şifrə çox asandır." + +msgid "Your password can’t be a commonly used password." +msgstr "Şifrəniz çox istifadə edilən, ümumişlək olmamalıdır." + +msgid "This password is entirely numeric." +msgstr "Bu şifrə ancaq rəqəmlərdən ibarətdir." + +msgid "Your password can’t be entirely numeric." +msgstr "Şifrəniz ancaq rəqəmlərdən ibarət ola bilməz." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "%(site_name)s, şifrənin sıfırlanması" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"Düzgün istifadəçi adı daxil edin. Bu dəyən ancaq İngiliscə hərflərdən, rəqəm " +"və @/./+/-/_ işarətlərindən ibarət ola bilər." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Düzgün istifadəçi adı daxil edin. Bu dəyən ancaq hərf, rəqəm və @/./+/-/_ " +"işarətlərindən ibarət ola bilər." + +msgid "Logged out" +msgstr "Çıxdınız" + +msgid "Password reset" +msgstr "Şifrənin sıfırlanması" + +msgid "Password reset sent" +msgstr "Şifrə sıfırlanması göndərildi" + +msgid "Enter new password" +msgstr "Yeni şifrəni daxil edin" + +msgid "Password reset unsuccessful" +msgstr "Şifrə sıfırlanması uğursuz oldu" + +msgid "Password reset complete" +msgstr "Şifrə sıfırlanması tamamlandı" + +msgid "Password change" +msgstr "Şifrənin dəyişdirilməsi" + +msgid "Password change successful" +msgstr "Şifrə uğurla dəyişdirildi" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/be/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/be/LC_MESSAGES/django.mo new file mode 100644 index 0000000..42c2a0c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/be/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/be/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/be/LC_MESSAGES/django.po new file mode 100644 index 0000000..692bea2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/be/LC_MESSAGES/django.po @@ -0,0 +1,313 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Viktar Palstsiuk , 2015 +# znotdead , 2016-2017,2019,2021,2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-04-25 08:09+0000\n" +"Last-Translator: znotdead , 2016-2017,2019,2021,2023\n" +"Language-Team: Belarusian (http://www.transifex.com/django/django/language/" +"be/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: be\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || " +"(n%100>=11 && n%100<=14)? 2 : 3);\n" + +msgid "Personal info" +msgstr "Асабістыя зьвесткі" + +msgid "Permissions" +msgstr "Дазволы" + +msgid "Important dates" +msgstr "Важныя даты" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "Аб'ект %(name)s з першасным ключом %(key)r не існуе." + +msgid "Password changed successfully." +msgstr "Пароль зьмянілі." + +#, python-format +msgid "Change password: %s" +msgstr "Зьмяніць пароль: %s" + +msgid "Authentication and Authorization" +msgstr "Аўтэнтыфікацыя і аўтарызацыя" + +msgid "password" +msgstr "пароль" + +msgid "last login" +msgstr "апошні раз уваходзіў" + +msgid "No password set." +msgstr "Пароль не зададзены." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Няправільны фармат паролю або невядомы алгарытм хэшавання." + +msgid "The two password fields didn’t match." +msgstr "Не супадаюць паролі ў двух палях." + +msgid "Password" +msgstr "Пароль" + +msgid "Password confirmation" +msgstr "Пацьвердзіце пароль" + +msgid "Enter the same password as before, for verification." +msgstr "Дзеля пэўнасьці набярыце такі самы пароль яшчэ раз." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Паролі не захоўваюцца ў такім выглядзе, як іх набралі, таму ўбачыць пароль " +"карыстальніка нельга, але яго можна зьмяніць выкарыстоўваючыгэту форму ." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Калі ласка, увядзіце правільны %(username)s і пароль. Адзначым, што абодва " +"палі могуць быць адчувальныя да рэгістра." + +msgid "This account is inactive." +msgstr "Рахунак ня дзейнічае." + +msgid "Email" +msgstr "Электронная пошта" + +msgid "New password" +msgstr "Новы пароль" + +msgid "New password confirmation" +msgstr "Пацьвердзіце новы пароль" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Пазначылі неадпаведны стары пароль. Набярыце яго зноўку." + +msgid "Old password" +msgstr "Стары пароль" + +msgid "Password (again)" +msgstr "Пароль (яшчэ раз)" + +msgid "algorithm" +msgstr "альґарытм" + +msgid "iterations" +msgstr "паўтарэньні" + +msgid "salt" +msgstr "соль" + +msgid "hash" +msgstr "скарот" + +msgid "variety" +msgstr "мноства" + +msgid "version" +msgstr "версія" + +msgid "memory cost" +msgstr "кошт памяці" + +msgid "time cost" +msgstr "кошт часу" + +msgid "parallelism" +msgstr "паралелізм" + +msgid "work factor" +msgstr "множнік працы" + +msgid "checksum" +msgstr "кантрольная сума" + +msgid "block size" +msgstr "памер блока" + +msgid "name" +msgstr "назва" + +msgid "content type" +msgstr "від змесціва" + +msgid "codename" +msgstr "найменьне" + +msgid "permission" +msgstr "дазвол" + +msgid "permissions" +msgstr "дазволы" + +msgid "group" +msgstr "суполка" + +msgid "groups" +msgstr "суполкі" + +msgid "superuser status" +msgstr "становішча спраўніка" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Паказвае, ці мае карыстальнік усе дазволы без таго, каб іх яўна прызначаць." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Суполкі, у якія ўваходзіць карыстальнік. Карыстальнік атрымае дазволы, якія " +"мае кожная ягоная суполка." + +msgid "user permissions" +msgstr "дазволы карыстальніка" + +msgid "Specific permissions for this user." +msgstr "Адмысловыя правы для гэтага карыстальніка." + +msgid "username" +msgstr "імя карыстальніка" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "Абавязковае поле. Да 150 знакаў. Толькі літары, лічбы ды @/./+/-/_." + +msgid "A user with that username already exists." +msgstr "Карыстальнік з такім іменем ужо існуе." + +msgid "first name" +msgstr "імя" + +msgid "last name" +msgstr "прозьвішча" + +msgid "email address" +msgstr "адрас электроннай пошты" + +msgid "staff status" +msgstr "становішча" + +msgid "Designates whether the user can log into this admin site." +msgstr "Паказвае, ці можа карыстальнік ўваходзіць на кіраўнічую пляцоўку." + +msgid "active" +msgstr "дзейны" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Паказвае, ці трэба ставіцца да карыстальніка як да дзейнага. Замест таго " +"каб, каб выдаляць рахунак, зраіце карыстальніка нядзейным." + +msgid "date joined" +msgstr "калі далучылі" + +msgid "user" +msgstr "карыстальнік" + +msgid "users" +msgstr "карыстальнікі" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Гэты пароль занадта кароткі. Ён павінен мець не менш %(min_length)d сімвал." +msgstr[1] "" +"Гэты пароль занадта кароткі. Ён павінен мець не менш %(min_length)d сімвала." +msgstr[2] "" +"Гэты пароль занадта кароткі. Ён павінен мець не менш %(min_length)d сімвалаў." +msgstr[3] "" +"Гэты пароль занадта кароткі. Ён павінен мець не менш %(min_length)d сімвалаў." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Ваш пароль павінен мець не менш %(min_length)d сімвал." +msgstr[1] "Ваш пароль павінен мець не менш %(min_length)d сімвала." +msgstr[2] "Ваш пароль павінен мець не менш %(min_length)d сімвалаў." +msgstr[3] "Ваш пароль павінен мець не менш %(min_length)d сімвалаў." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Пароль занадта падобны да %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" +"Ваш пароль ня можа быць занадта падобным да вашай іншай асабістай інфармацыі." + +msgid "This password is too common." +msgstr "Гэты пароль занадта распаўсюджаны." + +msgid "Your password can’t be a commonly used password." +msgstr "Ваш пароль ня можа быць адным з шырока распаўсюджаных пароляў." + +msgid "This password is entirely numeric." +msgstr "Гэты пароль цалкам лікавы." + +msgid "Your password can’t be entirely numeric." +msgstr "Ваш пароль ня можа быць цалкам лікавым." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Узнавіць пароль на %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Увядзіце імя карыстальніка. Гэта значэнне можа ўтрымліваць толькі малыя " +"літары a-z і вялікія літары A-Z, лічбы і сімвалы @/./+/-/_." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Увядзіце імя карыстальніка. Гэта значэнне можа ўтрымліваць толькі літары, " +"лічбы і сімвалы @/./+/-/_." + +msgid "Logged out" +msgstr "Не ўвайшоў" + +msgid "Password reset" +msgstr "Аднаўленне пароля" + +msgid "Password reset sent" +msgstr "Запыт на аднаўленне пароля адасланы" + +msgid "Enter new password" +msgstr "Пазначце новы пароль" + +msgid "Password reset unsuccessful" +msgstr "Не ўдалося аднавіць пароль" + +msgid "Password reset complete" +msgstr "Аднаўленне пароля скончана" + +msgid "Password change" +msgstr "Змена пароля" + +msgid "Password change successful" +msgstr "Змена пароля прайшла паспяхова" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/bg/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/bg/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8587fcf Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/bg/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/bg/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/bg/LC_MESSAGES/django.po new file mode 100644 index 0000000..d80b51b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/bg/LC_MESSAGES/django.po @@ -0,0 +1,311 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# arneatec , 2022-2023 +# Boris Chervenkov , 2012 +# Georgi Kostadinov , 2012 +# Jannis Leidel , 2011 +# Lyuboslav Petrov , 2014 +# Todor Lubenov , 2015 +# Venelin Stoykov , 2015-2016 +# vestimir , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-12-04 08:09+0000\n" +"Last-Translator: arneatec , 2022-2023\n" +"Language-Team: Bulgarian (http://app.transifex.com/django/django/language/" +"bg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Лична информация" + +msgid "Permissions" +msgstr "Права" + +msgid "Important dates" +msgstr "Важни дати" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(name)s обект с първичен ключ %(key)r не съществува." + +msgid "Password changed successfully." +msgstr "Паролата беше променена успешно. " + +#, python-format +msgid "Change password: %s" +msgstr "Промени парола: %s" + +msgid "Authentication and Authorization" +msgstr "Аутентикация и оторизация" + +msgid "password" +msgstr "парола" + +msgid "last login" +msgstr "последно вписване" + +msgid "No password set." +msgstr "Не е зададена парола." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Невалиден формат за парола или неизвестен алгоритъм за хеширане." + +msgid "The two password fields didn’t match." +msgstr "Двете полета за паролата не съвпадат. " + +msgid "Password" +msgstr "Парола" + +msgid "Password confirmation" +msgstr "Потвърждение на паролата" + +msgid "Enter the same password as before, for verification." +msgstr "Въведете същата парола като преди, за да потвърдите." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Паролите не се съхраняват в чист вид, така че е невъзможно да видите " +"паролата на този потребител, но можете да промените паролата чрез този формуляр." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Моля, въведете правилните %(username)s и парола. Имайте предвид, че и двете " +"полета могат да бъдат с малки или главни букви." + +msgid "This account is inactive." +msgstr "Този профил е неактивен." + +msgid "Email" +msgstr "Имейл" + +msgid "New password" +msgstr "Нова парола" + +msgid "New password confirmation" +msgstr "Потвърждение на новата парола" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Въвели сте погрешна стара парола. Въведете я отново. " + +msgid "Old password" +msgstr "Стара парола" + +msgid "Password (again)" +msgstr "Парола (отново)" + +msgid "algorithm" +msgstr "алгоритъм" + +msgid "iterations" +msgstr "повторения" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "хеш" + +msgid "variety" +msgstr "разнообразие" + +msgid "version" +msgstr "версия" + +msgid "memory cost" +msgstr "разход памет" + +msgid "time cost" +msgstr "разход време" + +msgid "parallelism" +msgstr "паралелизъм" + +msgid "work factor" +msgstr "работен фактор" + +msgid "checksum" +msgstr "чексума" + +msgid "block size" +msgstr "размер на блока" + +msgid "name" +msgstr "име" + +msgid "content type" +msgstr "тип на съдържанието" + +msgid "codename" +msgstr "код" + +msgid "permission" +msgstr "право" + +msgid "permissions" +msgstr "права" + +msgid "group" +msgstr "група" + +msgid "groups" +msgstr "групи" + +msgid "superuser status" +msgstr "статут на супер-потребител" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Указва, че този потребител има всички права (без да има нужда да се " +"изброяват изрично)." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Групите на които този потребител принадлежи. Потребителят ще получи всички " +"разрешения, дадени на всяка една от своите групи." + +msgid "user permissions" +msgstr "права на потребител" + +msgid "Specific permissions for this user." +msgstr "Специфични права за този потребител" + +msgid "username" +msgstr "потребител" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "Задължително. 150 знака или по-малко. Букви, цифри и @/./+/-/_ ." + +msgid "A user with that username already exists." +msgstr "Потребител с това потребителско име вече съществува. " + +msgid "first name" +msgstr "собствено име" + +msgid "last name" +msgstr "фамилно име" + +msgid "email address" +msgstr "имейл адрес" + +msgid "staff status" +msgstr "статус на персонал" + +msgid "Designates whether the user can log into this admin site." +msgstr "Указва дали този потребител има достъп до административния панел." + +msgid "active" +msgstr "активен" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Указва дали този потребител трябва да се третира като активен. Премахнете " +"тази отметката, вместо да изтривате профили." + +msgid "date joined" +msgstr "дата на регистриране" + +msgid "user" +msgstr "потребител" + +msgid "users" +msgstr "потребители" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Паролата е прекалено къса. Трябва да съдържа поне %(min_length)d символ." +msgstr[1] "" +"Паролата е прекалено къса. Трябва да съдържа поне %(min_length)d символа." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Вашата парола трябва да съдържа поне %(min_length)d символ." +msgstr[1] "Вашата парола трябва да съдържа поне %(min_length)d символа." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Паролата е много подобна на %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Вашата парола не може да прилича на останалата Ви лична информация." + +msgid "This password is too common." +msgstr "Тази парола е често срещана." + +msgid "Your password can’t be a commonly used password." +msgstr "Вашата парола не може да бъде често срещана." + +msgid "This password is entirely numeric." +msgstr "Тази парола е изцяло от цифри." + +msgid "Your password can’t be entirely numeric." +msgstr "Вашата парола не може да бъде само от цифри." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Промяна на парола за %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Въведете валидно потребителско име. То може да съдържа неударени малки a-z и " +"големи A-Z букви, цифри и @/./+/-/_ символи." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Въведете валидно потребителско име. То може да съдържа само букви, цифри и " +"@/./+/-/_ символи." + +msgid "Logged out" +msgstr "Извън системата" + +msgid "Password reset" +msgstr "Забравена парола" + +msgid "Password reset sent" +msgstr "Нулиране на паролата е изпратено" + +msgid "Enter new password" +msgstr "Въведете нова парола" + +msgid "Password reset unsuccessful" +msgstr "Неуспешна промяна на паролата " + +msgid "Password reset complete" +msgstr "Промяната на парола завърши" + +msgid "Password change" +msgstr "Промяна на парола" + +msgid "Password change successful" +msgstr "Паролата е сменена успешно" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/bn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/bn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9bb6607 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/bn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/bn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/bn/LC_MESSAGES/django.po new file mode 100644 index 0000000..26e37cb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/bn/LC_MESSAGES/django.po @@ -0,0 +1,286 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Tahmid Rafi , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-09-24 14:24+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Bengali (http://www.transifex.com/django/django/language/" +"bn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "ব্যক্তিগত তথ্য" + +msgid "Permissions" +msgstr "অনুমোদন" + +msgid "Important dates" +msgstr "গুরুত্বপূর্ণ তারিখ" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "পাসওয়ার্ড বদল সফল হয়েছে।" + +#, python-format +msgid "Change password: %s" +msgstr "পাসওয়ার্ড বদলানঃ %s" + +msgid "Authentication and Authorization" +msgstr "" + +msgid "password" +msgstr "পাসওয়ার্ড" + +msgid "last login" +msgstr "সর্বশেষ প্রবেশ" + +msgid "No password set." +msgstr "কোনো পাসওয়ার্ড সেট করা হয় নি।" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "অবৈধ পাসওয়ার্ড ফরম্যাট অথবা অজ্ঞাত হ্যাশিং অ্যালগরিদম।" + +msgid "The two password fields didn't match." +msgstr "পাসওয়ার্ড দুটো মেলেনি।" + +msgid "Password" +msgstr "পাসওয়ার্ড" + +msgid "Password confirmation" +msgstr "পাসওয়ার্ড নিশ্চিত করুন" + +msgid "Enter the same password as before, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" + +msgid "This account is inactive." +msgstr "এই একাউন্টটি কার্যকর নয়।" + +msgid "Email" +msgstr "" + +msgid "New password" +msgstr "নতুন পাসওয়ার্ড" + +msgid "New password confirmation" +msgstr "নতুন পাসওয়ার্ড নিশ্চিতকরণ" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" +"আপনার পুরনো পাসওয়ার্ড ঠিকভাবে প্রবেশ করানো হয়নি। অনুগ্রহপূর্বক সঠিক পাসওয়ার্ড দিন।" + +msgid "Old password" +msgstr "পুরনো পাসওয়ার্ড" + +msgid "Password (again)" +msgstr "পাসওয়ার্ড (পুনরায়)" + +msgid "algorithm" +msgstr "অ্যালগরিদম" + +msgid "iterations" +msgstr "ইটারেশন" + +msgid "salt" +msgstr "সল্ট" + +msgid "hash" +msgstr "হ্যাশ" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "" + +msgid "checksum" +msgstr "চেকসাম" + +msgid "name" +msgstr "নাম" + +msgid "content type" +msgstr "" + +msgid "codename" +msgstr "কোডনাম" + +msgid "permission" +msgstr "অনুমোদন" + +msgid "permissions" +msgstr "অনুমোদন" + +msgid "group" +msgstr "দল" + +msgid "groups" +msgstr "দল সমূহ" + +msgid "superuser status" +msgstr "সুপারইউজার মর্যাদা" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "সদস্যকে সকল ধরণের অনুমতি প্রদান করে।" + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "সদস্যের অনুমোদন সমূহ" + +msgid "Specific permissions for this user." +msgstr "এই ব্যবহারকারীর জন্য নির্দিষ্ট পারমিশন।" + +msgid "username" +msgstr "সদস্যনাম" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "এই সদস্যনামে একজন সদস্য আছেন।" + +msgid "first name" +msgstr "প্রথম নাম" + +msgid "last name" +msgstr "শেষ নাম" + +msgid "email address" +msgstr "ইমেইল অ্যাড্রেস" + +msgid "staff status" +msgstr "স্টাফ মর্যাদা" + +msgid "Designates whether the user can log into this admin site." +msgstr "সদস্যকে প্রশাসন সাইটে প্রবেশাধিকার প্রদান।" + +msgid "active" +msgstr "সচল" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "সদস্যকে সচল হিসেবে নির্ধারণ করুন। একাউন্ট মুছে ফেলার বদলে এটি ব্যবহার করুন।" + +msgid "date joined" +msgstr "যোগদানের তারিখ" + +msgid "user" +msgstr "সদস্য" + +msgid "users" +msgstr "সদস্যগণ" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "" + +msgid "Your password can't be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "" + +msgid "Your password can't be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "" + +msgid "Your password can't be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "প্রস্থান সম্পন্ন" + +msgid "Password reset" +msgstr "পাসওয়ার্ড রিসেট" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "নতুন পাসওয়ার্ড দিন" + +msgid "Password reset unsuccessful" +msgstr "পাসওয়ার্ড রিসেট সফল হয়নি" + +msgid "Password reset complete" +msgstr "পাসওয়ার্ড রিসেট সম্পন্ন হয়েছে" + +msgid "Password change" +msgstr "পাসওয়ার্ড পরিবর্তন" + +msgid "Password change successful" +msgstr "পাসওয়ার্ড পরিবর্তন সফল হয়েছে" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/br/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/br/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ff11ddb Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/br/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/br/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/br/LC_MESSAGES/django.po new file mode 100644 index 0000000..287f92c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/br/LC_MESSAGES/django.po @@ -0,0 +1,293 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Fulup , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-09-24 14:24+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Breton (http://www.transifex.com/django/django/language/br/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: br\n" +"Plural-Forms: nplurals=5; plural=((n%10 == 1) && (n%100 != 11) && (n%100 !" +"=71) && (n%100 !=91) ? 0 :(n%10 == 2) && (n%100 != 12) && (n%100 !=72) && (n" +"%100 !=92) ? 1 :(n%10 ==3 || n%10==4 || n%10==9) && (n%100 < 10 || n% 100 > " +"19) && (n%100 < 70 || n%100 > 79) && (n%100 < 90 || n%100 > 99) ? 2 :(n != 0 " +"&& n % 1000000 == 0) ? 3 : 4);\n" + +msgid "Personal info" +msgstr "" + +msgid "Permissions" +msgstr "" + +msgid "Important dates" +msgstr "" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "" + +#, python-format +msgid "Change password: %s" +msgstr "" + +msgid "Authentication and Authorization" +msgstr "" + +msgid "password" +msgstr "ger-tremen" + +msgid "last login" +msgstr "kevreet da ziwezhañ" + +msgid "No password set." +msgstr "" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" + +msgid "The two password fields didn't match." +msgstr "" + +msgid "Password" +msgstr "Ger-tremen" + +msgid "Password confirmation" +msgstr "" + +msgid "Enter the same password as before, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" + +msgid "This account is inactive." +msgstr "" + +msgid "Email" +msgstr "" + +msgid "New password" +msgstr "Ger-tremen nevez" + +msgid "New password confirmation" +msgstr "Kadarnaat ar ger-tremen nevez" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" + +msgid "Old password" +msgstr "Ger-tremen kozh" + +msgid "Password (again)" +msgstr "Ger-tremen (adarre)" + +msgid "algorithm" +msgstr "" + +msgid "iterations" +msgstr "" + +msgid "salt" +msgstr "" + +msgid "hash" +msgstr "" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "" + +msgid "checksum" +msgstr "" + +msgid "name" +msgstr "anv" + +msgid "content type" +msgstr "" + +msgid "codename" +msgstr "" + +msgid "permission" +msgstr "" + +msgid "permissions" +msgstr "" + +msgid "group" +msgstr "strollad" + +msgid "groups" +msgstr "strolladoù" + +msgid "superuser status" +msgstr "" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "" + +msgid "Specific permissions for this user." +msgstr "" + +msgid "username" +msgstr "" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "" + +msgid "first name" +msgstr "anv-bihan" + +msgid "last name" +msgstr "anv-familh" + +msgid "email address" +msgstr "" + +msgid "staff status" +msgstr "" + +msgid "Designates whether the user can log into this admin site." +msgstr "" + +msgid "active" +msgstr "" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" + +msgid "date joined" +msgstr "" + +msgid "user" +msgstr "implijer" + +msgid "users" +msgstr "implijerien" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "" + +msgid "Your password can't be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "" + +msgid "Your password can't be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "" + +msgid "Your password can't be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "Digevreet" + +msgid "Password reset" +msgstr "" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "" + +msgid "Password reset unsuccessful" +msgstr "" + +msgid "Password reset complete" +msgstr "" + +msgid "Password change" +msgstr "" + +msgid "Password change successful" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/bs/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/bs/LC_MESSAGES/django.mo new file mode 100644 index 0000000..cb49f5c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/bs/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/bs/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/bs/LC_MESSAGES/django.po new file mode 100644 index 0000000..672e234 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/bs/LC_MESSAGES/django.po @@ -0,0 +1,296 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Arza Grbic , 2021 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2021-09-27 17:56+0000\n" +"Last-Translator: Arza Grbic \n" +"Language-Team: Bosnian (http://www.transifex.com/django/django/language/" +"bs/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bs\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Personal info" +msgstr "Lični podaci" + +msgid "Permissions" +msgstr "Dozvole" + +msgid "Important dates" +msgstr "Važni datumi" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(name)s objekat sa primarnim ključem %(key)r ne postoji." + +msgid "Password changed successfully." +msgstr "Lozinka uspješno izmjenjena." + +#, python-format +msgid "Change password: %s" +msgstr "Izmjeni lozinku: %s" + +msgid "Authentication and Authorization" +msgstr "" + +msgid "password" +msgstr "lozinka" + +msgid "last login" +msgstr "posljednja prijava" + +msgid "No password set." +msgstr "Lozinka nije postavljena." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Neispravan format lozinke ili nepoznat hashing algoritam." + +msgid "The two password fields didn’t match." +msgstr "" + +msgid "Password" +msgstr "Lozinka" + +msgid "Password confirmation" +msgstr "Potvrda lozinke" + +msgid "Enter the same password as before, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" + +msgid "This account is inactive." +msgstr "Ovaj nalog je neaktivan." + +msgid "Email" +msgstr "" + +msgid "New password" +msgstr "Nova lozinka" + +msgid "New password confirmation" +msgstr "Potvrda nove lozinke" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Vaša stara lozinka nije pravilno unesena. Unesite je ponovo." + +msgid "Old password" +msgstr "Stara lozinka" + +msgid "Password (again)" +msgstr "Lozinka (ponovite)" + +msgid "algorithm" +msgstr "" + +msgid "iterations" +msgstr "" + +msgid "salt" +msgstr "" + +msgid "hash" +msgstr "" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "" + +msgid "checksum" +msgstr "" + +msgid "block size" +msgstr "" + +msgid "name" +msgstr "ime" + +msgid "content type" +msgstr "" + +msgid "codename" +msgstr "šifra dozvole" + +msgid "permission" +msgstr "dozvola" + +msgid "permissions" +msgstr "dozvole" + +msgid "group" +msgstr "grupa" + +msgid "groups" +msgstr "grupe" + +msgid "superuser status" +msgstr "status administratora" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Označava da li korisnik ima sve dozvole bez dodjeljivanja pojedinačnih " +"dozvola." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "korisničke dozvole" + +msgid "Specific permissions for this user." +msgstr "" + +msgid "username" +msgstr "korisničko ime" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "Korisnik sa tim korisničkim imenom već postoji." + +msgid "first name" +msgstr "ime" + +msgid "last name" +msgstr "prezime" + +msgid "email address" +msgstr "" + +msgid "staff status" +msgstr "status člana uredništva" + +msgid "Designates whether the user can log into this admin site." +msgstr "" +"Označava da li korisnik može da se prijavi na ovaj sajt za administraciju." + +msgid "active" +msgstr "aktivan" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Označava da li se korisnik smatra aktivnim. Uklnote izbor sa ovog polja " +"umjesto da brišete nalog." + +msgid "date joined" +msgstr "datum registracije" + +msgid "user" +msgstr "korisnik" + +msgid "users" +msgstr "korisnici" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "" + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "" + +msgid "Your password can’t be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "" + +msgid "Your password can’t be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "Odjavljen" + +msgid "Password reset" +msgstr "" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "" + +msgid "Password reset unsuccessful" +msgstr "" + +msgid "Password reset complete" +msgstr "" + +msgid "Password change" +msgstr "" + +msgid "Password change successful" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ca/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ca/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c53f782 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ca/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ca/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ca/LC_MESSAGES/django.po new file mode 100644 index 0000000..ae4a6d5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ca/LC_MESSAGES/django.po @@ -0,0 +1,316 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Antoni Aloy , 2015,2017,2021 +# Carles Barrobés , 2011-2012,2014-2015 +# Carles Pina Estany, 2022 +# Gil Obradors Via , 2019 +# Gil Obradors Via , 2019-2020 +# Jannis Leidel , 2011 +# Marc Compte , 2021 +# Roger Pons , 2015 +# Xavier RG , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2022-07-25 08:09+0000\n" +"Last-Translator: Carles Pina Estany\n" +"Language-Team: Catalan (http://www.transifex.com/django/django/language/" +"ca/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ca\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Informació personal" + +msgid "Permissions" +msgstr "Permisos" + +msgid "Important dates" +msgstr "Dates importants" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "No existeix cap objecte %(name)s amb la clau primària %(key)r." + +msgid "Password changed successfully." +msgstr "Contrasenya canviada amb èxit" + +#, python-format +msgid "Change password: %s" +msgstr "Canviar contrasenya: %s" + +msgid "Authentication and Authorization" +msgstr "Autenticació i Autorització" + +msgid "password" +msgstr "contrasenya" + +msgid "last login" +msgstr "últim inici de sessió" + +msgid "No password set." +msgstr "No s'ha establert la clau." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Format de contrasenya incorrecte o algorisme de hash desconegut." + +msgid "The two password fields didn’t match." +msgstr "Els dos camps de contrasenya no coincideixen." + +msgid "Password" +msgstr "Contrasenya" + +msgid "Password confirmation" +msgstr "Confirmació de contrasenya" + +msgid "Enter the same password as before, for verification." +msgstr "Introduïu la mateixa contrasenya d'abans, com a verificació." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Les contrasenyes no es guarden en text clar, així que no hi ha forma de " +"conèixer-les, però pots canviar la contrasenya utilitzant " +"aquest formulari." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Si us plau, introduïu un %(username)s i clau correctes. Observeu que ambdós " +"camps poden ser sensibles a majúscules." + +msgid "This account is inactive." +msgstr "Aquest compte està inactiu" + +msgid "Email" +msgstr "Correu electrònic" + +msgid "New password" +msgstr "Contrasenya nova" + +msgid "New password confirmation" +msgstr "Confirmació de contrasenya nova" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" +"La vostra antiga contrasenya no és correcta. Si us plau, introduïu-la de nou." + +msgid "Old password" +msgstr "Contrasenya antiga" + +msgid "Password (again)" +msgstr "Contrasenya (de nou)" + +msgid "algorithm" +msgstr "algorisme" + +msgid "iterations" +msgstr "iteracions" + +msgid "salt" +msgstr "sal" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "varietat" + +msgid "version" +msgstr "versió" + +msgid "memory cost" +msgstr "cost de memòria" + +msgid "time cost" +msgstr "cost de temps" + +msgid "parallelism" +msgstr "paralelisme" + +msgid "work factor" +msgstr "factor de treball" + +msgid "checksum" +msgstr "suma de comprovació" + +msgid "block size" +msgstr "mida de bloc" + +msgid "name" +msgstr "nom" + +msgid "content type" +msgstr "tipus de contingut" + +msgid "codename" +msgstr "nom en clau" + +msgid "permission" +msgstr "permís" + +msgid "permissions" +msgstr "permisos" + +msgid "group" +msgstr "grup" + +msgid "groups" +msgstr "grups" + +msgid "superuser status" +msgstr "estat de superusuari" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Designa que aquest usuari té tots els permisos sense assignar-los " +"explícitament." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Els grups als que pertany l'usuari. Un usuari tindrà tots els permisos de " +"cadascun dels seus grups." + +msgid "user permissions" +msgstr "permisos de l'usuari" + +msgid "Specific permissions for this user." +msgstr "Permisos específics per a aquest usuari." + +msgid "username" +msgstr "nom d'usuari" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "Obligatori. 150 o menys caràcters. Només lletres, dígits i @/./+/-/_." + +msgid "A user with that username already exists." +msgstr "Ja existeix un usuari amb aquest nom." + +msgid "first name" +msgstr "nom propi" + +msgid "last name" +msgstr "cognoms" + +msgid "email address" +msgstr "adreça de correu electrònic" + +msgid "staff status" +msgstr "membre del personal" + +msgid "Designates whether the user can log into this admin site." +msgstr "Designa si l'usuari pot entrar al lloc administratiu." + +msgid "active" +msgstr "actiu" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Designa si aquest usuari ha de ser tractat com a actiu. Deseleccioneu-ho " +"enlloc d'esborrar comptes d'usuari." + +msgid "date joined" +msgstr "data d'incorporació" + +msgid "user" +msgstr "usuari" + +msgid "users" +msgstr "usuaris" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"La contrasenya és massa curta. Ha de tenir al menys %(min_length)d caràcter." +msgstr[1] "" +"La contrasenya és massa curta. Ha de tenir un mínim de %(min_length)d " +"caràcters." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "La contrasenya és ha de tenir al menys %(min_length)d caràcter." +msgstr[1] "La contrasenya ha de tenir un mínim de %(min_length)d caràcters." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "La contrasenya és massa semblant a %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" +"La teva contrasenya no pot ser tan similar a alguna de la teva informació " +"personal" + +msgid "This password is too common." +msgstr "Aquesta contrasenya és massa comuna." + +msgid "Your password can’t be a commonly used password." +msgstr "La teva contrasenya no pot ser la típica contrasenya comuna." + +msgid "This password is entirely numeric." +msgstr "La contrasenya està formada només per números." + +msgid "Your password can’t be entirely numeric." +msgstr "La teva contrasenya no potser únicament numèrica." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Reinicialitzar la contrasenya a %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"Introdueixi un nom d'usuari vàlid. Aquest valor pot contenir sols lletres, " +"números i els caràcters @/./+/-/_ " + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Introdueixi un nom d'usuari vàlid. Aquest valor pot contenir sols lletres, " +"números i els caràcters @/./+/-/_ " + +msgid "Logged out" +msgstr "Sessió finalitzada" + +msgid "Password reset" +msgstr "Restablir contrasenya" + +msgid "Password reset sent" +msgstr "Restabliment de contrasenya enviat" + +msgid "Enter new password" +msgstr "Introduïu la nova contrasenya" + +msgid "Password reset unsuccessful" +msgstr "Restabliment de contrasenya fallat" + +msgid "Password reset complete" +msgstr "Contrasenya restablerta" + +msgid "Password change" +msgstr "Canvi de contrasenya" + +msgid "Password change successful" +msgstr "Contrasenya canviada amb èxit" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ckb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ckb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..588aaa8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ckb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ckb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ckb/LC_MESSAGES/django.po new file mode 100644 index 0000000..1fc0bb3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ckb/LC_MESSAGES/django.po @@ -0,0 +1,304 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Swara , 2022 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-04-25 08:09+0000\n" +"Last-Translator: Swara , 2022\n" +"Language-Team: Central Kurdish (http://www.transifex.com/django/django/" +"language/ckb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ckb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "زانیاریی کەسی" + +msgid "Permissions" +msgstr "ڕێگەپێدانەکان" + +msgid "Important dates" +msgstr "بەروارە گرنگەکان" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(name)s ئۆبجێکت لەگەڵ کلیلی سەرەکیی %(key)r بوونی نیە." + +msgid "Password changed successfully." +msgstr "تێپەڕەوشە بەسەرکەوتوویی گۆڕدرا." + +#, python-format +msgid "Change password: %s" +msgstr "گۆڕینی تێپەڕەوشەی: %s" + +msgid "Authentication and Authorization" +msgstr "ڕەسەنایەتی و ڕێگەپێدان" + +msgid "password" +msgstr "تێپەڕەوشە" + +msgid "last login" +msgstr "دوا چوونەژوورەوە" + +msgid "No password set." +msgstr "تێپەڕەوشە جێگیرنەکراوە." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "شێوازی تێپەڕەوشە نادروستە یان ئەلگۆریتمێکی هاشکراوی نەناسراوە." + +msgid "The two password fields didn’t match." +msgstr "هەردوو خانەی تێپەڕەوشە وەک یەک نین." + +msgid "Password" +msgstr "تێپەڕەوشە" + +msgid "Password confirmation" +msgstr "دووپاتکردنەوەی تێپەڕەوشە" + +msgid "Enter the same password as before, for verification." +msgstr "بۆ پشتڕاستکردنەوە هەمان تێپەڕەوشەی پێشوو بنوسە." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"تێپەڕەوشەی خاو هەڵناگیرێت, لەبەرئەوە هیچ ڕێگەیەک نییە بۆ بینینی تێپەڕەوشەی " +"ئەم بەکارهێنەرە, بەڵام دەتوانیت تێپەڕەوشەکە بگۆڕیت بە بەکارهێنانی ئەم فۆڕمە." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"تکایە %(username)s و تێپەڕەوشەی دروست بنوسە. لەوانەیە هەردوو خانەکە پێویستی " +"بە دۆخی هەستیار بێت بۆ پیتەکان." + +msgid "This account is inactive." +msgstr "ئەم هەژمارە ناچالاکە." + +msgid "Email" +msgstr "ئیمەیڵ" + +msgid "New password" +msgstr "تێپەڕەوشەی نوێ" + +msgid "New password confirmation" +msgstr "دووپاتکردنەوەی تێپەڕەوشەی نوێ" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "تێپەڕەوشە کۆنەکەت بە هەڵە نوسراوە. تکایە دووبارە بینوسەوە." + +msgid "Old password" +msgstr "تێپەڕەوشەی کۆن" + +msgid "Password (again)" +msgstr "تێپەڕەوشە(دووبارە)" + +msgid "algorithm" +msgstr "ئەلگۆریتم" + +msgid "iterations" +msgstr "دووبارەکردنەوەکان" + +msgid "salt" +msgstr "خوێ" + +msgid "hash" +msgstr "په‌یژه‌" + +msgid "variety" +msgstr "هەمەچەشنی" + +msgid "version" +msgstr "وەشان" + +msgid "memory cost" +msgstr "تێچووی بیرگە" + +msgid "time cost" +msgstr "تێچووی کات" + +msgid "parallelism" +msgstr "هاوتەریبی" + +msgid "work factor" +msgstr "هۆکاری کار" + +msgid "checksum" +msgstr "کۆی پشکنین" + +msgid "block size" +msgstr "قەبارەی بلۆک" + +msgid "name" +msgstr "ناو" + +msgid "content type" +msgstr "جۆری ناوەڕۆک" + +msgid "codename" +msgstr "ناوی کۆد" + +msgid "permission" +msgstr "ڕێگەپێدان" + +msgid "permissions" +msgstr "ڕێگەپێدانەکان" + +msgid "group" +msgstr "گرووپ" + +msgid "groups" +msgstr "گرووپەکان" + +msgid "superuser status" +msgstr "باری بەرزەبەکارهێنەر" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"دیاری دەکات کە ئەم بەکارهێنەرە هەموو مۆڵەتەکانی هەیە بەبێ ئەوەی بە تایبەتی " +"پێی بسپێردرێت." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"ئەو گروپانەی ئەم بەکارهێنەرە سەر بەو گروپانەیە. بەکارهێنەرێک هەموو ئەو " +"مۆڵەتانە وەردەگرێت کە بە هەریەک لەو گروپانە دەدرێت." + +msgid "user permissions" +msgstr "ڕێگەپێدانەکانی بەکارهێنەر" + +msgid "Specific permissions for this user." +msgstr "ڕێگەپێدانە تایبەتەکان بۆ ئەم بەکارهێنەرە." + +msgid "username" +msgstr "ناوی بەکارهێنەر" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "داواکراوە. 150 پیت یان کەمتر. تەنها پیت، ژمارە و @/./+/-/_ بێت." + +msgid "A user with that username already exists." +msgstr "بەکارهێنەرەکە بە هەمان ناوی بەکارهێنەرەوە پێشتر هەیە." + +msgid "first name" +msgstr "ناوی یەکەم" + +msgid "last name" +msgstr "ناوی دووەم" + +msgid "email address" +msgstr "ناونیشانی ئیمەیڵ" + +msgid "staff status" +msgstr "باری ستاف" + +msgid "Designates whether the user can log into this admin site." +msgstr "" +"دیاری دەکات کە ئایا بەکارهێنەر دەتوانێت بچێتە ناو بەڕێوەبەرایەتی ئەم " +"پێگەیەوە." + +msgid "active" +msgstr "چالاک" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"دیاری دەکات کە ئایا ئەم بەکارهێنەرە دەبێت وەک چالاک مامەڵەی لەگەڵدا بکرێت " +"یان نا. لەبری سڕینەوەی هەژمارەکان ئەمە هەڵمەبژێرە." + +msgid "date joined" +msgstr "بەرواری پەیوەستبوون" + +msgid "user" +msgstr "بەکارهێنەر" + +msgid "users" +msgstr "بەکارهێنەر" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"ئەم تێپەڕەوشە زۆر کورتە. دەبێت لانیکەم پێکبێت لە %(min_length)d نوسە." +msgstr[1] "" +"ئەم تێپەڕەوشە زۆر کورتە. دەبێت لانیکەم پێکبێت لە %(min_length)d نوسە." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "تێپەڕەوشەکەت دەبێت لانیکەم لە %(min_length)d نوسە پێک بێت." +msgstr[1] "تێپەڕەوشەکەت دەبێت لانیکەم لە %(min_length)d نوسە پێک بێت." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "ئەم تێپەڕەوشەیە زۆر هاوشێوەی %(verbose_name)sیە." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "‫تێپەڕەوشەکەت نابێت لەگەڵ زانیارییە کەسییەکانت زۆر چوونیەک بێت.‬" + +msgid "This password is too common." +msgstr "ئەم تێپەڕەوشەیە زۆر باوە." + +msgid "Your password can’t be a commonly used password." +msgstr "تێپەڕەوشەکەت ناتوانێت تێپەڕەوشەیەکی باو بێت." + +msgid "This password is entirely numeric." +msgstr "ئەم تێپەڕەوشەیە بە تەواوی ژمارەیە." + +msgid "Your password can’t be entirely numeric." +msgstr "تێپەڕەوشەکەت نابێت بە تەواوی ژمارە بێت" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "تێپەڕەوشەکەت دانرایەوە لە %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"ناوی بەکارهێنەرێکی دروست بنوسە. ئەم بەهایە لەوانەیە تەنها پیت و ژمارە و " +"پیتەکانی @/./+/-/_ لەخۆبگرێت." + +msgid "Logged out" +msgstr "چوونەدەرەوە" + +msgid "Password reset" +msgstr "دانانەوەی تێپەڕەوشە" + +msgid "Password reset sent" +msgstr "دانانەوەی تێپەڕەوشە نێردرا" + +msgid "Enter new password" +msgstr "تێپەڕەوشەی نوێ بنوسە" + +msgid "Password reset unsuccessful" +msgstr "دانانەوەی تێپەڕەوشە سەرکەوتوو نەبوو" + +msgid "Password reset complete" +msgstr "دانانەوەی تێپەڕەوشە تەواو بوو" + +msgid "Password change" +msgstr "گۆڕینی تێپەڕەوشە" + +msgid "Password change successful" +msgstr "تێپەڕەوشە بەسەرکەوتوویی گۆڕدرا" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/cs/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/cs/LC_MESSAGES/django.mo new file mode 100644 index 0000000..71403ae Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/cs/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/cs/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/cs/LC_MESSAGES/django.po new file mode 100644 index 0000000..78b6fc4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/cs/LC_MESSAGES/django.po @@ -0,0 +1,309 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jan Munclinger , 2013 +# Jannis Leidel , 2011 +# Tomáš Ehrlich , 2015 +# Vláďa Macek , 2013-2014 +# Vláďa Macek , 2015-2017,2019,2021-2022 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2022-01-04 18:49+0000\n" +"Last-Translator: Vláďa Macek \n" +"Language-Team: Czech (http://www.transifex.com/django/django/language/cs/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cs\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n " +"<= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n" + +msgid "Personal info" +msgstr "Osobní údaje" + +msgid "Permissions" +msgstr "Oprávnění" + +msgid "Important dates" +msgstr "Důležitá data" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "Položka \"%(name)s\" s primárním klíčem \"%(key)r\" neexistuje." + +msgid "Password changed successfully." +msgstr "Změna hesla byla úspěšná." + +#, python-format +msgid "Change password: %s" +msgstr "Heslo pro uživatele %s: změnit" + +msgid "Authentication and Authorization" +msgstr "Autentizace a autorizace" + +msgid "password" +msgstr "heslo" + +msgid "last login" +msgstr "poslední přihlášení" + +msgid "No password set." +msgstr "Heslo nenastaveno." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Neplatný formát hesla nebo neplatný hashovací algoritmus." + +msgid "The two password fields didn’t match." +msgstr "Hesla se neshodují." + +msgid "Password" +msgstr "Heslo" + +msgid "Password confirmation" +msgstr "Potvrzení hesla" + +msgid "Enter the same password as before, for verification." +msgstr "Zadejte pro ověření stejné heslo jako předtím." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Hesla se neukládají přímo a tak je nelze zobrazit. Je ale možné je změnit " +"pomocí tohoto formuláře." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Zadejte správnou hodnotu pole %(username)s a heslo. Pozor, obě pole mohou " +"rozlišovat malá a velká písmena." + +msgid "This account is inactive." +msgstr "Tento účet je neaktivní." + +msgid "Email" +msgstr "E-mail" + +msgid "New password" +msgstr "Nové heslo" + +msgid "New password confirmation" +msgstr "Potvrzení nového hesla" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Vaše současné heslo nebylo zadáno správně. Zkuste to znovu." + +msgid "Old password" +msgstr "Současné heslo" + +msgid "Password (again)" +msgstr "Heslo (znovu)" + +msgid "algorithm" +msgstr "algoritmus" + +msgid "iterations" +msgstr "iterace" + +msgid "salt" +msgstr "hodnota salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "varieta" + +msgid "version" +msgstr "verze" + +msgid "memory cost" +msgstr "spotřeba paměti" + +msgid "time cost" +msgstr "časový náklad" + +msgid "parallelism" +msgstr "paralelismus" + +msgid "work factor" +msgstr "faktor práce" + +msgid "checksum" +msgstr "kontrolní součet" + +msgid "block size" +msgstr "velikost bloku" + +msgid "name" +msgstr "název" + +msgid "content type" +msgstr "typ obsahu" + +msgid "codename" +msgstr "kódový název" + +msgid "permission" +msgstr "oprávnění" + +msgid "permissions" +msgstr "oprávnění" + +msgid "group" +msgstr "skupina" + +msgid "groups" +msgstr "skupiny" + +msgid "superuser status" +msgstr "superuživatel" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Určuje, že uživatel má veškerá oprávnění bez jejich explicitního přiřazení." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Skupiny, do kterých tento uživatel patří. Uživatel dostane všechna oprávnění " +"udělená každé z jeho skupin." + +msgid "user permissions" +msgstr "uživatelská oprávnění" + +msgid "Specific permissions for this user." +msgstr "Konkrétní oprávnění tohoto uživatele." + +msgid "username" +msgstr "uživatelské jméno" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Požadováno. 150 znaků nebo méně. Pouze písmena, číslice a znaky @/./+/-/_." + +msgid "A user with that username already exists." +msgstr "Uživatel s tímto jménem již existuje." + +msgid "first name" +msgstr "křestní jméno" + +msgid "last name" +msgstr "příjmení" + +msgid "email address" +msgstr "e-mailová adresa" + +msgid "staff status" +msgstr "administrační přístup" + +msgid "Designates whether the user can log into this admin site." +msgstr "Určuje, zda se uživatel může přihlásit do správy tohoto webu." + +msgid "active" +msgstr "aktivní" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Určuje, zda bude uživatel považován za aktivního. Použijte tuto možnost " +"místo odstranění účtů." + +msgid "date joined" +msgstr "datum registrace" + +msgid "user" +msgstr "uživatel" + +msgid "users" +msgstr "uživatelé" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "Heslo je příliš krátké. Musí mít délku aspoň %(min_length)d znak." +msgstr[1] "Heslo je příliš krátké. Musí mít délku aspoň %(min_length)d znaky." +msgstr[2] "Heslo je příliš krátké. Musí mít délku aspoň %(min_length)d znaků." +msgstr[3] "Heslo je příliš krátké. Musí mít délku aspoň %(min_length)d znaků." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Heslo musí mít délku aspoň %(min_length)d znak." +msgstr[1] "Heslo musí mít délku aspoň %(min_length)d znaky." +msgstr[2] "Heslo musí mít délku aspoň %(min_length)d znaků." +msgstr[3] "Heslo musí mít délku aspoň %(min_length)d znaků." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Heslo je příliš podobné obsahu pole %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Heslo nemůže být příliš podobné jinému údaji ve vašem účtu." + +msgid "This password is too common." +msgstr "Heslo je příliš běžné." + +msgid "Your password can’t be a commonly used password." +msgstr "Vaše heslo nemůže být takové, které je často používané." + +msgid "This password is entirely numeric." +msgstr "Heslo se skládá pouze z čísel." + +msgid "Your password can’t be entirely numeric." +msgstr "Vaše heslo nemůže být čistě číselné." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Obnovení hesla na webu %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"Zadejte platné uživatelské jméno. Hodnota může obsahovat pouze písmena bez " +"diakritiky, tj. háčků a čárek, číslice a znaky @/./+/-/_." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Zadejte platné uživatelské jméno. Hodnota může obsahovat pouze písmena, " +"číslice a znaky @/./+/-/_." + +msgid "Logged out" +msgstr "Odhlášeno" + +msgid "Password reset" +msgstr "Obnovení hesla" + +msgid "Password reset sent" +msgstr "Zpráva s obnovením hesla byla odeslána" + +msgid "Enter new password" +msgstr "Zadejte nové heslo" + +msgid "Password reset unsuccessful" +msgstr "Obnovení hesla bylo neúspěšné" + +msgid "Password reset complete" +msgstr "Heslo bylo obnoveno" + +msgid "Password change" +msgstr "Změna hesla" + +msgid "Password change successful" +msgstr "Změna hesla byla úspěšná" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/cy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/cy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..6221fd3 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/cy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/cy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/cy/LC_MESSAGES/django.po new file mode 100644 index 0000000..ee4ea46 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/cy/LC_MESSAGES/django.po @@ -0,0 +1,294 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Maredudd ap Gwyndaf , 2013-2014 +# pjrobertson, 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-09-24 14:24+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Welsh (http://www.transifex.com/django/django/language/cy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cy\n" +"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != " +"11) ? 2 : 3;\n" + +msgid "Personal info" +msgstr "Gwybodaeth bersonol" + +msgid "Permissions" +msgstr "Hawliau" + +msgid "Important dates" +msgstr "Dyddiadau pwysig" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "Newidwyd y gyfrinair." + +#, python-format +msgid "Change password: %s" +msgstr "Newid cyfrinair: %s" + +msgid "Authentication and Authorization" +msgstr "Dilysu ac Awdurdodi" + +msgid "password" +msgstr "cyfrinair" + +msgid "last login" +msgstr "mewngofnod diwethaf" + +msgid "No password set." +msgstr "Cyfrinair heb ei osod." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Fformat cyfrinair annilys neu algorithm hashio anhysbys." + +msgid "The two password fields didn't match." +msgstr "Nid oedd y ddau faes cyfrinair yr un peth." + +msgid "Password" +msgstr "Cyfrinair" + +msgid "Password confirmation" +msgstr "Cadarnhad cyfrinair" + +msgid "Enter the same password as before, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Teipiwch yr %(username)s a chyfrinair cywir ar gyfer cyfrif staff. Noder y " +"gall y ddau faes fod yn sensitif i lythrennau bach a llythrennau bras." + +msgid "This account is inactive." +msgstr "Mae'r cyfrif yn anweithredol." + +msgid "Email" +msgstr "Ebost" + +msgid "New password" +msgstr "Cyfrinair newydd" + +msgid "New password confirmation" +msgstr "Cadarnhad cyfrinair newydd" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Rhoddwydd eich hen gyfrinair yn anghywir. Triwch eto." + +msgid "Old password" +msgstr "Hen gyfrinair" + +msgid "Password (again)" +msgstr "Cyfrinair (eto)" + +msgid "algorithm" +msgstr "algorithm" + +msgid "iterations" +msgstr "iteriadau" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "ffactor gwaith" + +msgid "checksum" +msgstr "prawfswm" + +msgid "name" +msgstr "enw" + +msgid "content type" +msgstr "" + +msgid "codename" +msgstr "enw arwyddol" + +msgid "permission" +msgstr "hawl" + +msgid "permissions" +msgstr "hawliau" + +msgid "group" +msgstr "grŵp" + +msgid "groups" +msgstr "grwpiau" + +msgid "superuser status" +msgstr "statws uwchddefnyddiwr" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "Dynoda bod gan y defnyddiwr yr holl hawliau heb eu dynodi'n benodol." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "hawliau defnyddiwr" + +msgid "Specific permissions for this user." +msgstr "Caniatâd penodol ar gyfer y defnyddiwr hwn." + +msgid "username" +msgstr "enw defnyddiwr" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "Mae'r enw defnyddiwr yn bodoli'n barod." + +msgid "first name" +msgstr "enw cyntaf" + +msgid "last name" +msgstr "cyfenw" + +msgid "email address" +msgstr "cyfeiriad ebost" + +msgid "staff status" +msgstr "statws staff" + +msgid "Designates whether the user can log into this admin site." +msgstr "Dynoda os gall y defnyddiwr fewngofnodi i'r adran weinyddol." + +msgid "active" +msgstr "gweithredol" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Dynoda os ydy'r defnyddiwr yn weithredol. Dad-ddewiswch hwn yn lle dileu " +"cyfrifon." + +msgid "date joined" +msgstr "dyddiad ymuno" + +msgid "user" +msgstr "defnyddiwr" + +msgid "users" +msgstr "defnyddwyr" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "" + +msgid "Your password can't be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "" + +msgid "Your password can't be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "" + +msgid "Your password can't be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Ailosod cyfrinar ar %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "Allgofnodwyd" + +msgid "Password reset" +msgstr "Ailosod cyfrinair" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "Rhowch gyfrinair newydd" + +msgid "Password reset unsuccessful" +msgstr "Ailosod y cyfrinair yn aflwyddiannus" + +msgid "Password reset complete" +msgstr "Cwblhawyd ailosod y cyfrinair" + +msgid "Password change" +msgstr "Newid cyfrinair" + +msgid "Password change successful" +msgstr "Newid cyfrinair yn llwyddianus" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/da/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/da/LC_MESSAGES/django.mo new file mode 100644 index 0000000..861a1c2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/da/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/da/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/da/LC_MESSAGES/django.po new file mode 100644 index 0000000..25db711 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/da/LC_MESSAGES/django.po @@ -0,0 +1,309 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Christian Joergensen , 2012 +# Erik Ramsgaard Wognsen , 2021,2023 +# Erik Ramsgaard Wognsen , 2013-2017,2019 +# Jannis Leidel , 2011 +# 85794379431c3e0f5c85c0e72a78d45b_658ddd9, 2013 +# tiktuk , 2018 +# valberg , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-04-25 08:09+0000\n" +"Last-Translator: Erik Ramsgaard Wognsen , 2021,2023\n" +"Language-Team: Danish (http://www.transifex.com/django/django/language/da/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: da\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Personlig information" + +msgid "Permissions" +msgstr "Rettigheder" + +msgid "Important dates" +msgstr "Vigtige datoer" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "Der findes ikke et %(name)s-objekt med primærnøgle %(key)r." + +msgid "Password changed successfully." +msgstr "Adgangskoden blev ændret." + +#, python-format +msgid "Change password: %s" +msgstr "Skift adgangskode: %s" + +msgid "Authentication and Authorization" +msgstr "Godkendelse og autorisation" + +msgid "password" +msgstr "adgangskode" + +msgid "last login" +msgstr "sidst logget ind" + +msgid "No password set." +msgstr "Ingen adgangskode valgt." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Ugyldigt adgangskodeformat eller hashing-algoritme." + +msgid "The two password fields didn’t match." +msgstr "De to adgangskoder var ikke identiske." + +msgid "Password" +msgstr "Adgangskode" + +msgid "Password confirmation" +msgstr "Bekræftelse af adgangskode" + +msgid "Enter the same password as before, for verification." +msgstr "Indtast den samme adgangskode som før, for bekræftelse." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Rå adgangskoder gemmes ikke, så det er ikke muligt at se denne brugers " +"adgangskode, men du kan ændre adgangskoden ved hjælp af denne " +"formular." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Indtast venligst korrekt %(username)s og adgangskode. Bemærk at begge felter " +"kan være versalfølsomme." + +msgid "This account is inactive." +msgstr "Denne konto er inaktiv." + +msgid "Email" +msgstr "E-mail" + +msgid "New password" +msgstr "Ny adgangskode" + +msgid "New password confirmation" +msgstr "Bekræftelse af ny adgangskode" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" +"Din gamle adgangskode blev ikke indtastet korrekt. Indtast den venligst igen." + +msgid "Old password" +msgstr "Gammel adgangskode" + +msgid "Password (again)" +msgstr "Adgangskode (igen)" + +msgid "algorithm" +msgstr "algoritme" + +msgid "iterations" +msgstr "iterationer" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "variation" + +msgid "version" +msgstr "version" + +msgid "memory cost" +msgstr "hukommelsesomkostning" + +msgid "time cost" +msgstr "tidsomkostning" + +msgid "parallelism" +msgstr "parallelitet" + +msgid "work factor" +msgstr "work factor" + +msgid "checksum" +msgstr "tjeksum" + +msgid "block size" +msgstr "blokstørrelse" + +msgid "name" +msgstr "navn" + +msgid "content type" +msgstr "indholdstype" + +msgid "codename" +msgstr "kodenavn" + +msgid "permission" +msgstr "rettighed" + +msgid "permissions" +msgstr "rettigheder" + +msgid "group" +msgstr "gruppe" + +msgid "groups" +msgstr "grupper" + +msgid "superuser status" +msgstr "superbrugerstatus" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Bestemmer at denne bruger har alle rettigheder uden at tildele dem eksplicit." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Grupperne som denne bruger hører til. En bruger får alle rettigheder givet " +"til hver af hans/hendes grupper." + +msgid "user permissions" +msgstr "rettigheder" + +msgid "Specific permissions for this user." +msgstr "Specifikke rettigheder for denne bruger." + +msgid "username" +msgstr "brugernavn" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "Påkrævet. Højst 150 tegn. Kun bogstaver og cifre samt @/./+/-/_" + +msgid "A user with that username already exists." +msgstr "En bruger med dette brugernavn findes allerede." + +msgid "first name" +msgstr "fornavn" + +msgid "last name" +msgstr "efternavn" + +msgid "email address" +msgstr "e-mail-adresse" + +msgid "staff status" +msgstr "admin-status" + +msgid "Designates whether the user can log into this admin site." +msgstr "Bestemmer om brugeren kan logge ind på dette administrationswebsite." + +msgid "active" +msgstr "aktiv" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Bestemmer om brugeren skal behandles som aktiv. Fravælg dette frem for at " +"slette en konto." + +msgid "date joined" +msgstr "dato for registrering" + +msgid "user" +msgstr "bruger" + +msgid "users" +msgstr "brugere" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Denne adgangskode er for kort. Den skal indeholde mindst %(min_length)d tegn." +msgstr[1] "" +"Denne adgangskode er for kort. Den skal indeholde mindst %(min_length)d tegn." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Din adgangskode skal indeholde mindst %(min_length)d tegn." +msgstr[1] "Din adgangskode skal indeholde mindst %(min_length)d tegn." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Din adgangskode minder for meget om din/dit %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Din adgangskode må ikke minde om dine andre personlige oplysninger." + +msgid "This password is too common." +msgstr "Denne adgangskode er for almindelig." + +msgid "Your password can’t be a commonly used password." +msgstr "Din adgangskode må ikke være en ofte anvendt adgangskode." + +msgid "This password is entirely numeric." +msgstr "Denne adgangskode er udelukkende numerisk." + +msgid "Your password can’t be entirely numeric." +msgstr "Din adgangskode må ikke være udelukkende numerisk." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Adgangskode nulstillet på %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Indtast et gyldigt brugernavn. Denne værdi må kun indeholde små bogstaver a-" +"z og store bogstaver A-Z uden accenter, samt cifre og tegnene @/./+/-/_." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Indtast et gyldigt brugernavn. Denne værdi må kun indeholde bogstaver, cifre " +"og tegnene @/./+/-/_." + +msgid "Logged out" +msgstr "Logget ud" + +msgid "Password reset" +msgstr "Nulstilling af adgangskode" + +msgid "Password reset sent" +msgstr "Nulstilling af kodeord sendt" + +msgid "Enter new password" +msgstr "Indtast ny adgangskode" + +msgid "Password reset unsuccessful" +msgstr "Adgangskoden blev ikke nulstillet" + +msgid "Password reset complete" +msgstr "Nulstilling af adgangskode fuldført" + +msgid "Password change" +msgstr "Ændring af adgangskode" + +msgid "Password change successful" +msgstr "Adgangskoden blev ændret" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/de/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/de/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3f68c10 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/de/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/de/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/de/LC_MESSAGES/django.po new file mode 100644 index 0000000..777ff13 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/de/LC_MESSAGES/django.po @@ -0,0 +1,318 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# André Hagenbruch, 2011 +# Florian Apolloner , 2012 +# Florian Apolloner , 2021,2023 +# jnns, 2013 +# Jannis Leidel , 2013-2017,2020,2023 +# jnns, 2016 +# Jens Neuhaus , 2016 +# Markus Holtermann , 2023 +# Markus Holtermann , 2013,2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-04-25 08:09+0000\n" +"Last-Translator: Jannis Leidel , 2013-2017,2020,2023\n" +"Language-Team: German (http://www.transifex.com/django/django/language/de/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Persönliche Informationen" + +msgid "Permissions" +msgstr "Berechtigungen" + +msgid "Important dates" +msgstr "Wichtige Daten" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(name)s-Objekt mit Primärschlüssel %(key)r ist nicht vorhanden." + +msgid "Password changed successfully." +msgstr "Passwort erfolgreich geändert." + +#, python-format +msgid "Change password: %s" +msgstr "Passwort ändern: %s" + +msgid "Authentication and Authorization" +msgstr "Authentifizierung und Autorisierung" + +msgid "password" +msgstr "Passwort" + +msgid "last login" +msgstr "Letzte Anmeldung" + +msgid "No password set." +msgstr "Kein Passwort gesetzt." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Ungültiges Passwortformat oder unbekannter Hashing-Algorithmus." + +msgid "The two password fields didn’t match." +msgstr "Die beiden Passwörter sind nicht identisch." + +msgid "Password" +msgstr "Passwort" + +msgid "Password confirmation" +msgstr "Passwort bestätigen" + +msgid "Enter the same password as before, for verification." +msgstr "Bitte das selbe Passwort zur Bestätigung erneut eingeben." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Die Passwörter werden nicht im Klartext gespeichert und können daher nicht " +"dargestellt, sondern nur mit diesem Formular geändert " +"werden." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Bitte %(username)s und Passwort eingeben. Beide Felder berücksichtigen die " +"Groß-/Kleinschreibung." + +msgid "This account is inactive." +msgstr "Dieser Benutzer ist inaktiv." + +msgid "Email" +msgstr "E-Mail-Adresse" + +msgid "New password" +msgstr "Neues Passwort" + +msgid "New password confirmation" +msgstr "Neues Passwort bestätigen" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Das alte Passwort war falsch. Bitte neu eingeben." + +msgid "Old password" +msgstr "Altes Passwort" + +msgid "Password (again)" +msgstr "Passwort (wiederholen)" + +msgid "algorithm" +msgstr "Algorithmus" + +msgid "iterations" +msgstr "Wiederholungen" + +msgid "salt" +msgstr "Salt" + +msgid "hash" +msgstr "Hash" + +msgid "variety" +msgstr "Vielfalt" + +msgid "version" +msgstr "Version" + +msgid "memory cost" +msgstr "Speicherbedarf" + +msgid "time cost" +msgstr "Zeitbedarf" + +msgid "parallelism" +msgstr "Parallelität" + +msgid "work factor" +msgstr "Arbeitsfaktor" + +msgid "checksum" +msgstr "Prüfsumme" + +msgid "block size" +msgstr "Blockgröße" + +msgid "name" +msgstr "Name" + +msgid "content type" +msgstr "Inhaltstyp" + +msgid "codename" +msgstr "Codename" + +msgid "permission" +msgstr "Berechtigung" + +msgid "permissions" +msgstr "Berechtigungen" + +msgid "group" +msgstr "Gruppe" + +msgid "groups" +msgstr "Gruppen" + +msgid "superuser status" +msgstr "Administrator-Status" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Legt fest, dass der Benutzer alle Berechtigungen hat, ohne diese einzeln " +"zuweisen zu müssen." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Die Gruppen, denen der Benutzer angehört. Ein Benutzer bekommt alle " +"Berechtigungen dieser Gruppen." + +msgid "user permissions" +msgstr "Berechtigungen" + +msgid "Specific permissions for this user." +msgstr "Spezifische Berechtigungen für diesen Benutzer." + +msgid "username" +msgstr "Benutzername" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Erforderlich. 150 Zeichen oder weniger. Nur Buchstaben, Ziffern und @/./+/-/" +"_." + +msgid "A user with that username already exists." +msgstr "Dieser Benutzername ist bereits vergeben." + +msgid "first name" +msgstr "Vorname" + +msgid "last name" +msgstr "Nachname" + +msgid "email address" +msgstr "E-Mail-Adresse" + +msgid "staff status" +msgstr "Mitarbeiter-Status" + +msgid "Designates whether the user can log into this admin site." +msgstr "" +"Legt fest, ob sich der Benutzer an der Administrationsseite anmelden kann." + +msgid "active" +msgstr "Aktiv" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Legt fest, ob dieser Benutzer aktiv ist. Kann deaktiviert werden, anstatt " +"Benutzer zu löschen." + +msgid "date joined" +msgstr "Mitglied seit" + +msgid "user" +msgstr "Benutzer" + +msgid "users" +msgstr "Benutzer" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Dieses Passwort ist zu kurz. Es muss mindestens %(min_length)d Zeichen " +"enthalten." +msgstr[1] "" +"Dieses Passwort ist zu kurz. Es muss mindestens %(min_length)d Zeichen " +"enthalten." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Das Passwort muss mindestens %(min_length)d Zeichen enthalten." +msgstr[1] "Das Passwort muss mindestens %(min_length)d Zeichen enthalten." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Das Passwort ist zu ähnlich zu %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" +"Das Passwort darf nicht zu ähnlich zu anderen persönlichen Informationen " +"sein." + +msgid "This password is too common." +msgstr "Dieses Passwort ist zu üblich." + +msgid "Your password can’t be a commonly used password." +msgstr "Das Passwort darf nicht allgemein üblich sein." + +msgid "This password is entirely numeric." +msgstr "Dieses Passwort ist komplett numerisch. " + +msgid "Your password can’t be entirely numeric." +msgstr "Das Passwort darf nicht komplett aus Ziffern bestehen." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Passwort auf %(site_name)s zurücksetzen" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Bitte einen gültigen Benutzernamen eingeben, bestehend aus kleinen und " +"großen Buchstaben (A-Z, a-z, ohne Sonderzeichen), Ziffern und @/./+/-/_." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Bitte einen gültigen Benutzernamen eingeben, bestehend aus Buchstaben, " +"Ziffern und @/./+/-/_." + +msgid "Logged out" +msgstr "Abgemeldet" + +msgid "Password reset" +msgstr "Passwort zurücksetzen" + +msgid "Password reset sent" +msgstr "E-Mail zum Passwort zurücksetzen abgesendet" + +msgid "Enter new password" +msgstr "Neues Passwort eingeben" + +msgid "Password reset unsuccessful" +msgstr "Passwort nicht erfolgreich zurückgesetzt" + +msgid "Password reset complete" +msgstr "Passwort zurücksetzen abgeschlossen" + +msgid "Password change" +msgstr "Passwort ändern" + +msgid "Password change successful" +msgstr "Passwort erfolgreich geändert" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/dsb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/dsb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4730259 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/dsb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/dsb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/dsb/LC_MESSAGES/django.po new file mode 100644 index 0000000..a2cf9e9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/dsb/LC_MESSAGES/django.po @@ -0,0 +1,320 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Michael Wolf , 2016-2017,2020-2021,2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-04-25 08:09+0000\n" +"Last-Translator: Michael Wolf , " +"2016-2017,2020-2021,2023\n" +"Language-Team: Lower Sorbian (http://www.transifex.com/django/django/" +"language/dsb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: dsb\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || " +"n%100==4 ? 2 : 3);\n" + +msgid "Personal info" +msgstr "Wósobinske informacije" + +msgid "Permissions" +msgstr "Pšawa" + +msgid "Important dates" +msgstr "Wažne daty" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "Objekt %(name)s z primarnym klucom %(key)r njeeksistěrujo." + +msgid "Password changed successfully." +msgstr "Gronidło jo se změniło." + +#, python-format +msgid "Change password: %s" +msgstr "Gronidło změniś: %s" + +msgid "Authentication and Authorization" +msgstr "Awtentifikacija a awtorizacija" + +msgid "password" +msgstr "gronidło" + +msgid "last login" +msgstr "slědne pśizjawjenje" + +msgid "No password set." +msgstr "Žedno gronidło nastajone." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Njepłaśiwy gronidłowy format abo njeznaty kontrolny algoritmus." + +msgid "The two password fields didn’t match." +msgstr "Dwě gronidlowej póli njejstej jadnakej." + +msgid "Password" +msgstr "Gronidło" + +msgid "Password confirmation" +msgstr "Gronidłowe wobkšuśenje" + +msgid "Enter the same password as before, for verification." +msgstr "Zapódajśo to samske gronidło, za pśespytanje." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Grube gronidła se njeskładuju, togodla njejo móžno, gronidło wužywarja " +"wiźeś, ale móžośo gronidło z pomocu toś togo formulara " +"změniś." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Pšosym zapódajśo pšawe %(username)s a gronidło. Źiwajśo na to, až wobej póli " +"móžotej mjazy wjeliko- a małopisanim rozeznawaś." + +msgid "This account is inactive." +msgstr "Toś to konto jo inaktiwne." + +msgid "Email" +msgstr "E-mail" + +msgid "New password" +msgstr "Nowe gronidło" + +msgid "New password confirmation" +msgstr "Wobkšuśenje nowego gronidła" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" +"Wašo stare gronidło jo se wopak zapódało. Pšosym zapódajśo jo hyšći raz." + +msgid "Old password" +msgstr "Stare gronidło" + +msgid "Password (again)" +msgstr "Gronidło (znowego)" + +msgid "algorithm" +msgstr "algoritmus" + +msgid "iterations" +msgstr "wóspjetowanja" + +msgid "salt" +msgstr "sol" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "warianta" + +msgid "version" +msgstr "wersija" + +msgid "memory cost" +msgstr "składowa pśetrjeba" + +msgid "time cost" +msgstr "casowa pśetrjeba" + +msgid "parallelism" +msgstr "paralelizm" + +msgid "work factor" +msgstr "źěłowy faktor" + +msgid "checksum" +msgstr "kontrolna suma" + +msgid "block size" +msgstr "blokowa wjelikosć" + +msgid "name" +msgstr "mě" + +msgid "content type" +msgstr "wopśimjeśowy typ" + +msgid "codename" +msgstr "kodowe mě" + +msgid "permission" +msgstr "pšawo" + +msgid "permissions" +msgstr "pšawa" + +msgid "group" +msgstr "kupka" + +msgid "groups" +msgstr "kupki" + +msgid "superuser status" +msgstr "status superwužywarja" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Wóznamjenijo, lěc toś ten wužywaŕ ma wšykne pšawa bźez togo, aby mógał je " +"pśipokazaś." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Kupki, ku kótarymž toś ten wužywaŕ słuša. Wužywaŕ dóstanjo wšykne pšawa, " +"kótarež jomu kupki dawaju." + +msgid "user permissions" +msgstr "wužywarske pšawa" + +msgid "Specific permissions for this user." +msgstr "Wěste pšawa za toś togo wužywarja." + +msgid "username" +msgstr "wužywarske mě" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "Trěbne. 150 znamuškow abo mjenjej. Jano pismiki, cyfry a @/./+/-/_." + +msgid "A user with that username already exists." +msgstr "Wužywaŕ z toś tym wužywarskim mjenim južo eksistěrujo." + +msgid "first name" +msgstr "pśedmě" + +msgid "last name" +msgstr "familijowe mě" + +msgid "email address" +msgstr "e-mailowa adresa" + +msgid "staff status" +msgstr "personalny status" + +msgid "Designates whether the user can log into this admin site." +msgstr "" +"Wóznamjenijo, lěc wužywaŕ móžo se pla administratorowego sedła pśizjawiś." + +msgid "active" +msgstr "aktiwny" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Wóznamjenijo, lěc deje z toś tym wužywarjom ako z aktiwnym wobchadás. " +"Znjemóžniśo to město togo, aby konta wulašował." + +msgid "date joined" +msgstr "cłonk wót" + +msgid "user" +msgstr "wužywaŕ" + +msgid "users" +msgstr "wužywarje" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Toś to gronidło jo pśekrotke. Musy nanejmjenjej %(min_length)d znamuško " +"wopśimowaś." +msgstr[1] "" +"Toś to gronidło jo pśekrotke. Musy nanejmjenjej %(min_length)d znamušce " +"wopśimowaś." +msgstr[2] "" +"Toś to gronidło jo pśekrotke. Musy nanejmjenjej %(min_length)d znamuška " +"wopśimowaś." +msgstr[3] "" +"Toś to gronidło jo pśekrotke. Musy nanejmjenjej %(min_length)d znamuškow " +"wopśimowaś." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Wašo gronidło musy nanejmjenjej %(min_length)d znamuško wopśimowaś." +msgstr[1] "Wašo gronidło musy nanejmjenjej %(min_length)d znamušce wopśimowaś." +msgstr[2] "Wašo gronidło musy nanejmjenjej %(min_length)d znamuška wopśimowaś." +msgstr[3] "" +"Wašo gronidło musy nanejmjenjej %(min_length)d znamuškow wopśimowaś." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Gronidło jo na %(verbose_name)s pśepódobne." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Wašo gronidło njesmějo na waše druge wósobinske daty pśepódobne byś." + +msgid "This password is too common." +msgstr "Toś to gronidło jo pśepowšykne." + +msgid "Your password can’t be a commonly used password." +msgstr "Wašo gronidło njesmějo cesto wužywane gronidło byś." + +msgid "This password is entirely numeric." +msgstr "Toś to gronidło jo cele numeriske." + +msgid "Your password can’t be entirely numeric." +msgstr "Wašo gronidło njesmějo cele numeriske byś." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Slědkstajenje gronidła na %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Zapódajśo płaśiwe wužywaŕske mě. Toś ta gódnota smějo jano małomismiki a-z a " +"wjelikopismiki A-Z bźez diakritiskich znamuškow, licby a znamuška @/./+/-/_ " +"wopśimowaś." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Zapódajśo płaśiwe wužywarske mě. Toś ta gódnota smějo jano pismiki, licby a " +"znamuška @/./+/-/_ wopśimowaś." + +msgid "Logged out" +msgstr "Wótzjawjony" + +msgid "Password reset" +msgstr "Slědkstajenje gronidła" + +msgid "Password reset sent" +msgstr "Slědkstajenje gronidła wótpósłane" + +msgid "Enter new password" +msgstr "Zapódajśo nowe gronidło" + +msgid "Password reset unsuccessful" +msgstr "Slědkstajenje gronidła njejo se raźiło" + +msgid "Password reset complete" +msgstr "Slědkstajenje gronidła dokóńcone" + +msgid "Password change" +msgstr "Změnjenje gronidła" + +msgid "Password change successful" +msgstr "Gronidło jo se wuspěšnje změniło" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/el/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/el/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9d25fe6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/el/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/el/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/el/LC_MESSAGES/django.po new file mode 100644 index 0000000..f74a71f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/el/LC_MESSAGES/django.po @@ -0,0 +1,320 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Apostolis Bessas , 2013 +# Claude Paroz , 2017 +# Dimitris Glezos , 2011-2012 +# Giannis Meletakis , 2015 +# glogiotatidis , 2011 +# Jannis Leidel , 2011 +# Nick Mavrakis , 2018 +# Pãnoș , 2014 +# Pãnoș , 2016 +# Serafeim Papastefanos , 2021 +# Yorgos Pagles , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2021-09-22 09:22+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Greek (http://www.transifex.com/django/django/language/el/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: el\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Προσωπικές πληροφορίες" + +msgid "Permissions" +msgstr "Δικαιώματα" + +msgid "Important dates" +msgstr "Σημαντικές ημερομηνίες" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "Το αντικείμενο %(name)s με πρωτεύον κλειδί %(key)r δεν υπάρχει." + +msgid "Password changed successfully." +msgstr "Το συνθηματικό αλλάχτηκε με επιτυχία." + +#, python-format +msgid "Change password: %s" +msgstr "Αλλαγή συνθηματικού: %s" + +msgid "Authentication and Authorization" +msgstr "Πιστοποίηση και Εξουσιοδότηση" + +msgid "password" +msgstr "συνθηματικό" + +msgid "last login" +msgstr "τελευταία σύνδεση" + +msgid "No password set." +msgstr "Δεν έχει τεθεί συνθηματικό." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Μη έγκυρη μορφή συνθηματικού ή άγνωστος αλγόριθμος hashing." + +msgid "The two password fields didn’t match." +msgstr "Τα δύο πεδία κωδικών δεν ταιριάζουν." + +msgid "Password" +msgstr "Συνθηματικό" + +msgid "Password confirmation" +msgstr "Επιβεβαίωση συνθηματικού" + +msgid "Enter the same password as before, for verification." +msgstr "Εισάγετε το ίδιο συνθηματικό όπως πρίν, για επιβεβαίωση." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Οι ακατέργαστοι κωδικοί δεν αποθηκεύονται, οπότε δεν υπάρχει τρόπος να δείτε " +"τον κωδικό αυτού του χρήστη, αλλά μπορείτε να τον αλλάξετε χρησιμοποιώντας " +"αυτή τη φόρμα." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Παρακαλώ εισάγετε ένα σωστό %(username)s και κωδικό. Σημειωτέον ότι και τα " +"δύο πεδία κάνουν διάκριση μεταξύ πεζών-κεφαλαίων." + +msgid "This account is inactive." +msgstr "Αυτός ο λογαριασμός είναι ανενεργός." + +msgid "Email" +msgstr "Email" + +msgid "New password" +msgstr "Νέο συνθηματικό" + +msgid "New password confirmation" +msgstr "Επιβεβαίωση νέου συνθηματικού" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Το παλιό συνθηματικό σας δόθηκε λανθασμένα. Παρακαλώ δοκιμάστε ξανά." + +msgid "Old password" +msgstr "Παλιό συνθηματικό" + +msgid "Password (again)" +msgstr "Συνθηματικό (ξανά)" + +msgid "algorithm" +msgstr "αλγόριθμος" + +msgid "iterations" +msgstr "Επαναλήψεις" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "ποικιλία" + +msgid "version" +msgstr "έκδοση" + +msgid "memory cost" +msgstr "κόστος μνήμης" + +msgid "time cost" +msgstr "χρονικό κόστος" + +msgid "parallelism" +msgstr "παραλληλισμός" + +msgid "work factor" +msgstr "work factor" + +msgid "checksum" +msgstr "checksum" + +msgid "block size" +msgstr "" + +msgid "name" +msgstr "όνομα" + +msgid "content type" +msgstr "τύπος περιεχομένου" + +msgid "codename" +msgstr "κωδικό όνομα" + +msgid "permission" +msgstr "δικαίωμα" + +msgid "permissions" +msgstr "διακαιώματα" + +msgid "group" +msgstr "ομάδα" + +msgid "groups" +msgstr "ομάδες" + +msgid "superuser status" +msgstr "κατάσταση υπερχρήστη" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Υποδηλώνει ότι ο συγκεκριμένος χρήστης έχει όλα τα δικαιώματα χωρίς να " +"χρειάζεται να τα παραχωρήσετε ξεχωριστά." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Οι ομάδες που ανοίκει ο χρήστης. Ένας χρήστης θα έχει όλες τις άδειες που " +"έχουν δωθεί σε κάθε μια από τις ομάδες." + +msgid "user permissions" +msgstr "δικαιώματα χρήστη" + +msgid "Specific permissions for this user." +msgstr "Συγκεκριμένα δικαιώματα για αυτόν τον χρήστη." + +msgid "username" +msgstr "όνομα χρήστη" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Απαραίτητο. 150 ή λιγότερους χαρακτήρες. Μόνο γράμματα, ψηφία και @/./+/-/_." + +msgid "A user with that username already exists." +msgstr "Υπάρχει ήδη ένας χρήστης με αυτό το όνομα." + +msgid "first name" +msgstr "όνομα" + +msgid "last name" +msgstr "επώνυμο" + +msgid "email address" +msgstr "διεύθυνση email" + +msgid "staff status" +msgstr "Κατάσταση προσωπικού" + +msgid "Designates whether the user can log into this admin site." +msgstr "Ορίζει αν ο χρήστης μπορεί να συνδεθεί στο χώρο διαχείρισης." + +msgid "active" +msgstr "ενεργό" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Υποδηλώνει αν ο συγκεκριμένος χρήστης μπορεί να θεωρηθεί ενεργός. Προτιμήστε " +"την επεπιλογή αυτής της επιλογής αντί του να πραγματοποιήσετε διαγραφή του " +"χρήστη." + +msgid "date joined" +msgstr "ημερομηνία ένταξης" + +msgid "user" +msgstr "χρήστης" + +msgid "users" +msgstr "χρήστες" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Αυτό το συνθηματικό είναι πολύ μικρό. Πρέπει να περιέχει τουλάχιστον " +"%(min_length)d χαρακτήρα." +msgstr[1] "" +"Αυτό το συνθηματικό είναι πολύ μικρό. Πρέπει να περιέχει τουλάχιστον " +"%(min_length)d χαρακτήρες." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +"Το συνθηματικό σας πρέπει να έχει τουλάχιστον %(min_length)d χαρακτήρα." +msgstr[1] "" +"Το συνθηματικό σας πρέπει να έχει τουλάχιστον %(min_length)d χαρακτήρες." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Το συνθηματικό μοιάζει πολύ με το %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" +"Ο κωδικός σας δεν μπορεί να μοιάζει τόσο με τα άλλα προσωπικά σας στοιχεία." + +msgid "This password is too common." +msgstr "Πολύ κοινό συνθηματικό." + +msgid "Your password can’t be a commonly used password." +msgstr "Ο κωδικός σας δεν μπορεί να είναι τόσο συνηθισμένος." + +msgid "This password is entirely numeric." +msgstr "Αυτό το συνθηματικό αποτελείται μόνο απο αριθμούς." + +msgid "Your password can’t be entirely numeric." +msgstr "Ο κωδικός σας δε μπορεί να αποτελείται μόνον από αριθμούς." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Επαναφορά συνθηματικού για το %(site_name)s " + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"Εισάγετε ένα έγκυρο όνομα χρήστη. Θα πρέπει να περιέχει μόνο Αγγλικούς " +"χαρακτήρες, αριθμούς και τους χαρακτήρες @/./+/-/_." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Εισάγετε ένα έγκυρο όνομα χρήστη. Θα πρέπει να περιέχει μόνο γράμματα, " +"αριθμούς και τους χαρακτήρες @/./+/-/_ characters." + +msgid "Logged out" +msgstr "Έγινε αποσύνδεση" + +msgid "Password reset" +msgstr "Επαναφορά συνθηματικού" + +msgid "Password reset sent" +msgstr "Η επαναφορά συνθηματικού εστάλει" + +msgid "Enter new password" +msgstr "Εισάγετε νεό συνθηματικό" + +msgid "Password reset unsuccessful" +msgstr "Ανεπιτυχής επαναφορά κωδικού" + +msgid "Password reset complete" +msgstr "Ολοκλήρωση επαναφοράς συνθηματικού" + +msgid "Password change" +msgstr "Αλλαγή συνθηματικού" + +msgid "Password change successful" +msgstr "Επιτυχής αλλαγή συνθηματικού" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/en/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/en/LC_MESSAGES/django.mo new file mode 100644 index 0000000..08a7b68 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/en/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/en/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/en/LC_MESSAGES/django.po new file mode 100644 index 0000000..8b15915 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/en/LC_MESSAGES/django.po @@ -0,0 +1,375 @@ +# This file is distributed under the same license as the Django package. +# +msgid "" +msgstr "" +"Project-Id-Version: Django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2010-05-13 15:35+0200\n" +"Last-Translator: Django team\n" +"Language-Team: English \n" +"Language: en\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: contrib/auth/admin.py:49 +msgid "Personal info" +msgstr "" + +#: contrib/auth/admin.py:51 +msgid "Permissions" +msgstr "" + +#: contrib/auth/admin.py:62 +msgid "Important dates" +msgstr "" + +#: contrib/auth/admin.py:156 +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +#: contrib/auth/admin.py:168 +msgid "Password changed successfully." +msgstr "" + +#: contrib/auth/admin.py:189 +#, python-format +msgid "Change password: %s" +msgstr "" + +#: contrib/auth/apps.py:16 +msgid "Authentication and Authorization" +msgstr "" + +#: contrib/auth/base_user.py:58 +msgid "password" +msgstr "" + +#: contrib/auth/base_user.py:59 +msgid "last login" +msgstr "" + +#: contrib/auth/forms.py:41 +msgid "No password set." +msgstr "" + +#: contrib/auth/forms.py:49 +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" + +#: contrib/auth/forms.py:91 contrib/auth/forms.py:379 contrib/auth/forms.py:457 +msgid "The two password fields didn’t match." +msgstr "" + +#: contrib/auth/forms.py:94 contrib/auth/forms.py:166 contrib/auth/forms.py:201 +#: contrib/auth/forms.py:461 +msgid "Password" +msgstr "" + +#: contrib/auth/forms.py:100 +msgid "Password confirmation" +msgstr "" + +#: contrib/auth/forms.py:103 contrib/auth/forms.py:472 +msgid "Enter the same password as before, for verification." +msgstr "" + +#: contrib/auth/forms.py:168 +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" + +#: contrib/auth/forms.py:208 +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" + +#: contrib/auth/forms.py:211 +msgid "This account is inactive." +msgstr "" + +#: contrib/auth/forms.py:276 +msgid "Email" +msgstr "" + +#: contrib/auth/forms.py:382 +msgid "New password" +msgstr "" + +#: contrib/auth/forms.py:388 +msgid "New password confirmation" +msgstr "" + +#: contrib/auth/forms.py:425 +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" + +#: contrib/auth/forms.py:429 +msgid "Old password" +msgstr "" + +#: contrib/auth/forms.py:469 +msgid "Password (again)" +msgstr "" + +#: contrib/auth/hashers.py:327 contrib/auth/hashers.py:420 +#: contrib/auth/hashers.py:510 contrib/auth/hashers.py:605 +#: contrib/auth/hashers.py:665 contrib/auth/hashers.py:707 +#: contrib/auth/hashers.py:765 contrib/auth/hashers.py:820 +#: contrib/auth/hashers.py:878 +msgid "algorithm" +msgstr "" + +#: contrib/auth/hashers.py:328 +msgid "iterations" +msgstr "" + +#: contrib/auth/hashers.py:329 contrib/auth/hashers.py:426 +#: contrib/auth/hashers.py:512 contrib/auth/hashers.py:609 +#: contrib/auth/hashers.py:666 contrib/auth/hashers.py:708 +#: contrib/auth/hashers.py:879 +msgid "salt" +msgstr "" + +#: contrib/auth/hashers.py:330 contrib/auth/hashers.py:427 +#: contrib/auth/hashers.py:610 contrib/auth/hashers.py:667 +#: contrib/auth/hashers.py:709 contrib/auth/hashers.py:766 +#: contrib/auth/hashers.py:821 contrib/auth/hashers.py:880 +msgid "hash" +msgstr "" + +#: contrib/auth/hashers.py:421 +msgid "variety" +msgstr "" + +#: contrib/auth/hashers.py:422 +msgid "version" +msgstr "" + +#: contrib/auth/hashers.py:423 +msgid "memory cost" +msgstr "" + +#: contrib/auth/hashers.py:424 +msgid "time cost" +msgstr "" + +#: contrib/auth/hashers.py:425 contrib/auth/hashers.py:608 +msgid "parallelism" +msgstr "" + +#: contrib/auth/hashers.py:511 contrib/auth/hashers.py:606 +msgid "work factor" +msgstr "" + +#: contrib/auth/hashers.py:513 +msgid "checksum" +msgstr "" + +#: contrib/auth/hashers.py:607 +msgid "block size" +msgstr "" + +#: contrib/auth/models.py:62 contrib/auth/models.py:116 +msgid "name" +msgstr "" + +#: contrib/auth/models.py:66 +msgid "content type" +msgstr "" + +#: contrib/auth/models.py:68 +msgid "codename" +msgstr "" + +#: contrib/auth/models.py:73 +msgid "permission" +msgstr "" + +#: contrib/auth/models.py:74 contrib/auth/models.py:119 +msgid "permissions" +msgstr "" + +#: contrib/auth/models.py:126 +msgid "group" +msgstr "" + +#: contrib/auth/models.py:127 contrib/auth/models.py:258 +msgid "groups" +msgstr "" + +#: contrib/auth/models.py:249 +msgid "superuser status" +msgstr "" + +#: contrib/auth/models.py:252 +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" + +#: contrib/auth/models.py:261 +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +#: contrib/auth/models.py:269 +msgid "user permissions" +msgstr "" + +#: contrib/auth/models.py:271 +msgid "Specific permissions for this user." +msgstr "" + +#: contrib/auth/models.py:345 +msgid "username" +msgstr "" + +#: contrib/auth/models.py:349 +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +#: contrib/auth/models.py:353 +msgid "A user with that username already exists." +msgstr "" + +#: contrib/auth/models.py:356 +msgid "first name" +msgstr "" + +#: contrib/auth/models.py:357 +msgid "last name" +msgstr "" + +#: contrib/auth/models.py:358 +msgid "email address" +msgstr "" + +#: contrib/auth/models.py:360 +msgid "staff status" +msgstr "" + +#: contrib/auth/models.py:362 +msgid "Designates whether the user can log into this admin site." +msgstr "" + +#: contrib/auth/models.py:365 +msgid "active" +msgstr "" + +#: contrib/auth/models.py:368 +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" + +#: contrib/auth/models.py:372 +msgid "date joined" +msgstr "" + +#: contrib/auth/models.py:381 +msgid "user" +msgstr "" + +#: contrib/auth/models.py:382 +msgid "users" +msgstr "" + +#: contrib/auth/password_validation.py:111 +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +msgstr[1] "" + +#: contrib/auth/password_validation.py:123 +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +msgstr[1] "" + +#: contrib/auth/password_validation.py:206 +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "" + +#: contrib/auth/password_validation.py:213 +msgid "Your password can’t be too similar to your other personal information." +msgstr "" + +#: contrib/auth/password_validation.py:245 +msgid "This password is too common." +msgstr "" + +#: contrib/auth/password_validation.py:250 +msgid "Your password can’t be a commonly used password." +msgstr "" + +#: contrib/auth/password_validation.py:261 +msgid "This password is entirely numeric." +msgstr "" + +#: contrib/auth/password_validation.py:266 +msgid "Your password can’t be entirely numeric." +msgstr "" + +#: contrib/auth/templates/registration/password_reset_subject.txt:2 +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "" + +#: contrib/auth/validators.py:12 +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" + +#: contrib/auth/validators.py:22 +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +#: contrib/auth/views.py:178 +msgid "Logged out" +msgstr "" + +#: contrib/auth/views.py:237 +msgid "Password reset" +msgstr "" + +#: contrib/auth/views.py:264 +msgid "Password reset sent" +msgstr "" + +#: contrib/auth/views.py:274 +msgid "Enter new password" +msgstr "" + +#: contrib/auth/views.py:346 +msgid "Password reset unsuccessful" +msgstr "" + +#: contrib/auth/views.py:355 +msgid "Password reset complete" +msgstr "" + +#: contrib/auth/views.py:367 +msgid "Password change" +msgstr "" + +#: contrib/auth/views.py:390 +msgid "Password change successful" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/en_AU/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/en_AU/LC_MESSAGES/django.mo new file mode 100644 index 0000000..bdd8328 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/en_AU/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/en_AU/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/en_AU/LC_MESSAGES/django.po new file mode 100644 index 0000000..ba933b7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/en_AU/LC_MESSAGES/django.po @@ -0,0 +1,306 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Tom Fifield , 2014 +# Tom Fifield , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2021-09-22 09:22+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: English (Australia) (http://www.transifex.com/django/django/" +"language/en_AU/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_AU\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Personal info" + +msgid "Permissions" +msgstr "Permissions" + +msgid "Important dates" +msgstr "Important dates" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(name)s object with primary key %(key)r does not exist." + +msgid "Password changed successfully." +msgstr "Password changed successfully." + +#, python-format +msgid "Change password: %s" +msgstr "Change password: %s" + +msgid "Authentication and Authorization" +msgstr "Authentication and Authorisation" + +msgid "password" +msgstr "password" + +msgid "last login" +msgstr "last login" + +msgid "No password set." +msgstr "No password set." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Invalid password format or unknown hashing algorithm." + +msgid "The two password fields didn’t match." +msgstr "The two password fields didn’t match." + +msgid "Password" +msgstr "Password" + +msgid "Password confirmation" +msgstr "Password confirmation" + +msgid "Enter the same password as before, for verification." +msgstr "Enter the same password as before, for verification." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." + +msgid "This account is inactive." +msgstr "This account is inactive." + +msgid "Email" +msgstr "Email" + +msgid "New password" +msgstr "New password" + +msgid "New password confirmation" +msgstr "New password confirmation" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Your old password was entered incorrectly. Please enter it again." + +msgid "Old password" +msgstr "Old password" + +msgid "Password (again)" +msgstr "Password (again)" + +msgid "algorithm" +msgstr "algorithm" + +msgid "iterations" +msgstr "iterations" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "variety" + +msgid "version" +msgstr "version" + +msgid "memory cost" +msgstr "memory cost" + +msgid "time cost" +msgstr "time cost" + +msgid "parallelism" +msgstr "parallelism" + +msgid "work factor" +msgstr "work factor" + +msgid "checksum" +msgstr "checksum" + +msgid "block size" +msgstr "" + +msgid "name" +msgstr "name" + +msgid "content type" +msgstr "content type" + +msgid "codename" +msgstr "codename" + +msgid "permission" +msgstr "permission" + +msgid "permissions" +msgstr "permissions" + +msgid "group" +msgstr "group" + +msgid "groups" +msgstr "groups" + +msgid "superuser status" +msgstr "superuser status" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Designates that this user has all permissions without explicitly assigning " +"them." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." + +msgid "user permissions" +msgstr "user permissions" + +msgid "Specific permissions for this user." +msgstr "Specific permissions for this user." + +msgid "username" +msgstr "username" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." + +msgid "A user with that username already exists." +msgstr "A user with that username already exists." + +msgid "first name" +msgstr "first name" + +msgid "last name" +msgstr "last name" + +msgid "email address" +msgstr "email address" + +msgid "staff status" +msgstr "staff status" + +msgid "Designates whether the user can log into this admin site." +msgstr "Designates whether the user can log into this admin site." + +msgid "active" +msgstr "active" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." + +msgid "date joined" +msgstr "date joined" + +msgid "user" +msgstr "user" + +msgid "users" +msgstr "users" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgstr[1] "" +"This password is too short. It must contain at least %(min_length)d " +"characters." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Your password must contain at least %(min_length)d character." +msgstr[1] "Your password must contain at least %(min_length)d characters." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "The password is too similar to the %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Your password can’t be too similar to your other personal information." + +msgid "This password is too common." +msgstr "This password is too common." + +msgid "Your password can’t be a commonly used password." +msgstr "Your password can’t be a commonly used password." + +msgid "This password is entirely numeric." +msgstr "This password is entirely numeric." + +msgid "Your password can’t be entirely numeric." +msgstr "Your password can’t be entirely numeric." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Password reset on %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." + +msgid "Logged out" +msgstr "Logged out" + +msgid "Password reset" +msgstr "Password reset" + +msgid "Password reset sent" +msgstr "Password reset sent" + +msgid "Enter new password" +msgstr "Enter new password" + +msgid "Password reset unsuccessful" +msgstr "Password reset unsuccessful" + +msgid "Password reset complete" +msgstr "Password reset complete" + +msgid "Password change" +msgstr "Password change" + +msgid "Password change successful" +msgstr "Password change successful" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/en_GB/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/en_GB/LC_MESSAGES/django.mo new file mode 100644 index 0000000..59ed277 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/en_GB/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/en_GB/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/en_GB/LC_MESSAGES/django.po new file mode 100644 index 0000000..a374f29 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/en_GB/LC_MESSAGES/django.po @@ -0,0 +1,289 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# jon_atkinson , 2011-2012 +# Ross Poulton , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-09-24 14:24+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: English (United Kingdom) (http://www.transifex.com/django/" +"django/language/en_GB/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_GB\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Personal info" + +msgid "Permissions" +msgstr "Permissions" + +msgid "Important dates" +msgstr "Important dates" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "Password changed successfully." + +#, python-format +msgid "Change password: %s" +msgstr "Change password: %s" + +msgid "Authentication and Authorization" +msgstr "" + +msgid "password" +msgstr "password" + +msgid "last login" +msgstr "last login" + +msgid "No password set." +msgstr "" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" + +msgid "The two password fields didn't match." +msgstr "The two password fields didn't match." + +msgid "Password" +msgstr "Password" + +msgid "Password confirmation" +msgstr "Password confirmation" + +msgid "Enter the same password as before, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" + +msgid "This account is inactive." +msgstr "This account is inactive." + +msgid "Email" +msgstr "" + +msgid "New password" +msgstr "New password" + +msgid "New password confirmation" +msgstr "New password confirmation" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Your old password was entered incorrectly. Please enter it again." + +msgid "Old password" +msgstr "Old password" + +msgid "Password (again)" +msgstr "Password (again)" + +msgid "algorithm" +msgstr "algorithm" + +msgid "iterations" +msgstr "iterations" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "work factor" + +msgid "checksum" +msgstr "checksum" + +msgid "name" +msgstr "name" + +msgid "content type" +msgstr "" + +msgid "codename" +msgstr "codename" + +msgid "permission" +msgstr "permission" + +msgid "permissions" +msgstr "permissions" + +msgid "group" +msgstr "group" + +msgid "groups" +msgstr "groups" + +msgid "superuser status" +msgstr "superuser status" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Designates that this user has all permissions without explicitly assigning " +"them." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "user permissions" + +msgid "Specific permissions for this user." +msgstr "" + +msgid "username" +msgstr "username" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "A user with that username already exists." + +msgid "first name" +msgstr "first name" + +msgid "last name" +msgstr "last name" + +msgid "email address" +msgstr "" + +msgid "staff status" +msgstr "staff status" + +msgid "Designates whether the user can log into this admin site." +msgstr "Designates whether the user can log into this admin site." + +msgid "active" +msgstr "active" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." + +msgid "date joined" +msgstr "date joined" + +msgid "user" +msgstr "user" + +msgid "users" +msgstr "users" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "" + +msgid "Your password can't be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "" + +msgid "Your password can't be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "" + +msgid "Your password can't be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Password reset on %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "Logged out" + +msgid "Password reset" +msgstr "" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "" + +msgid "Password reset unsuccessful" +msgstr "" + +msgid "Password reset complete" +msgstr "" + +msgid "Password change" +msgstr "" + +msgid "Password change successful" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/eo/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/eo/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5fe6729 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/eo/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/eo/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/eo/LC_MESSAGES/django.po new file mode 100644 index 0000000..82a84ad --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/eo/LC_MESSAGES/django.po @@ -0,0 +1,310 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Batist D 🐍 , 2012-2013 +# Batist D 🐍 , 2013-2019 +# Matthieu Desplantes , 2021 +# Meiyer , 2022 +# Robin van der Vliet , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2022-04-25 08:09+0000\n" +"Last-Translator: Meiyer , 2022\n" +"Language-Team: Esperanto (http://www.transifex.com/django/django/language/" +"eo/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eo\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Personaj informoj" + +msgid "Permissions" +msgstr "Permesoj" + +msgid "Important dates" +msgstr "Gravaj datoj" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "Objekto %(name)skun ĉefŝlosilo %(key)r ne ekzistas." + +msgid "Password changed successfully." +msgstr "Pasvorto suksese ŝanĝita." + +#, python-format +msgid "Change password: %s" +msgstr "Ŝanĝi pasvorton: %s" + +msgid "Authentication and Authorization" +msgstr "Aŭtentigo kaj rajtigo" + +msgid "password" +msgstr "pasvorto" + +msgid "last login" +msgstr "lasta ensaluto" + +msgid "No password set." +msgstr "Neniu pasvorto agordita." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Nevalida pasvorta formato, aŭ nekonata haketa algoritmo." + +msgid "The two password fields didn’t match." +msgstr "La du pasvortaj kampoj ne kongruas." + +msgid "Password" +msgstr "Pasvorto" + +msgid "Password confirmation" +msgstr "Pasvorta konfirmo" + +msgid "Enter the same password as before, for verification." +msgstr "Entajpu la saman pasvorton kiel supre, por konfirmo." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"La pasvortoj ne estas konservitaj en klara formo, do ne eblas vidi la " +"pasvorton de ĉi tiu uzanto, sed vi povas ŝanĝi la pasvorton per ĉi tiu formularo." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Bonvolu enigi ĝustan %(username)sn kaj pasvorton. Notu, ke ambaŭ kampoj " +"povas esti usklecodistingaj." + +msgid "This account is inactive." +msgstr "Ĉi tiu konto ne estas aktiva." + +msgid "Email" +msgstr "Retpoŝto" + +msgid "New password" +msgstr "Nova pasvorto" + +msgid "New password confirmation" +msgstr "Nova pasvorto por konfirmo" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" +"Via malnova pasvorto estis tajpita malĝuste. Bonvolu denove entajpi ĝin." + +msgid "Old password" +msgstr "Malnova pasvorto" + +msgid "Password (again)" +msgstr "Pasvorto (denove)" + +msgid "algorithm" +msgstr "algoritmo" + +msgid "iterations" +msgstr "iteracioj" + +msgid "salt" +msgstr "salo" + +msgid "hash" +msgstr "haketo" + +msgid "variety" +msgstr "diverseco" + +msgid "version" +msgstr "versio" + +msgid "memory cost" +msgstr "memor-kosto" + +msgid "time cost" +msgstr "tempo-kosto" + +msgid "parallelism" +msgstr "paralelismo" + +msgid "work factor" +msgstr "laborfaktoro" + +msgid "checksum" +msgstr "kontrolsumo" + +msgid "block size" +msgstr "blok-grandeco" + +msgid "name" +msgstr "nomo" + +msgid "content type" +msgstr "enhava tipo" + +msgid "codename" +msgstr "kodnomo" + +msgid "permission" +msgstr "permeso" + +msgid "permissions" +msgstr "permesoj" + +msgid "group" +msgstr "grupo" + +msgid "groups" +msgstr "grupoj" + +msgid "superuser status" +msgstr "ĉefuzanta statuso" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Indikas ke tiu ĉi uzanto havas ĉiujn permesojn, sen eksplicite atribui ilin." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"La grupoj al kiuj tiu ĉi uzanto apartenas. Uzanto akiros ĉiujn permesojn " +"atribuitajn al ĉiu el tiuj grupoj." + +msgid "user permissions" +msgstr "uzantaj permesoj" + +msgid "Specific permissions for this user." +msgstr "Specifaj permesoj por tiu ĉi uzanto." + +msgid "username" +msgstr "salutnomo" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "Petita. 150 signoj aŭ malpli. Nur literoj, ciferoj kaj @/./+/-/_." + +msgid "A user with that username already exists." +msgstr "Uzanto kun sama salutnomo jam ekzistas." + +msgid "first name" +msgstr "persona nomo" + +msgid "last name" +msgstr "familia nomo" + +msgid "email address" +msgstr "retpoŝta adreso" + +msgid "staff status" +msgstr "personara statuso" + +msgid "Designates whether the user can log into this admin site." +msgstr "Indikas ĉu la uzanto povas saluti en ĉi-tiu administranta retejo." + +msgid "active" +msgstr "aktiva" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Indikas ĉu la uzanto devus esti traktita kiel aktiva. Malmarku tion ĉi " +"anstataŭ forigi kontojn." + +msgid "date joined" +msgstr "dato de aliĝo" + +msgid "user" +msgstr "uzanto" + +msgid "users" +msgstr "uzantoj" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Tiu pasvorto estas tro mallonga. Ĝi devas enhavi almenaŭ %(min_length)d " +"signon." +msgstr[1] "" +"Tiu pasvorto estas tro mallonga. Ĝi devas enhavi almenaŭ %(min_length)d " +"signojn." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Via pasvorto devas enhavi almenaŭ %(min_length)d signon." +msgstr[1] "Via pasvorto devas enhavi almenaŭ %(min_length)d signojn." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "La pasvorto estas tro simila al la %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Via pasvorto ne povas esti tro simila al viaj aliaj personaj informoj." + +msgid "This password is too common." +msgstr "Tiu pasvorto estas tro kutima." + +msgid "Your password can’t be a commonly used password." +msgstr "Via pasvorto ne povas esti ofte uzata pasvorto." + +msgid "This password is entirely numeric." +msgstr "Tiu ĉi pasvorto konsistas nur el ciferoj." + +msgid "Your password can’t be entirely numeric." +msgstr "Via pasvorto ne povas konsisti nur el ciferoj." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Pasvorta rekomencigo ĉe %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"Enigu salutnomon en ĝusta formo. Ĉi tiu valoro povas enhavi nur " +"sensupersignajn literojn, ciferojn kaj la signojn @/./+/-/_." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Enigu salutnomon en ĝusta formo. Ĉi tiu valoro povas enhavi nur literojn, " +"ciferojn kaj la signojn @/./+/-/_." + +msgid "Logged out" +msgstr "Adiaŭita" + +msgid "Password reset" +msgstr "Restarigo de pasvorto" + +msgid "Password reset sent" +msgstr "Restarigo de pasvorto sendita" + +msgid "Enter new password" +msgstr "Enigu novan pasvorton" + +msgid "Password reset unsuccessful" +msgstr "Restarigo de pasvorto malsukcesa" + +msgid "Password reset complete" +msgstr "Restarigo de pasvorto plenumita" + +msgid "Password change" +msgstr "Pasvorta ŝanĝo" + +msgid "Password change successful" +msgstr "Pasvorto sukcese ŝanĝita" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es/LC_MESSAGES/django.mo new file mode 100644 index 0000000..27db448 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es/LC_MESSAGES/django.po new file mode 100644 index 0000000..f6d0875 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es/LC_MESSAGES/django.po @@ -0,0 +1,326 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# albertoalcolea , 2014 +# Antoni Aloy , 2012-2013,2015-2017 +# e4db27214f7e7544f2022c647b585925_bb0e321, 2015-2016 +# e4db27214f7e7544f2022c647b585925_bb0e321, 2020 +# Ernesto Rico Schmidt , 2017 +# guillem , 2012 +# Igor Támara , 2015 +# Jannis Leidel , 2011 +# Josue Naaman Nistal Guerra , 2014 +# Leonardo J. Caballero G. , 2011 +# Uriel Medina , 2020-2021,2023 +# Veronicabh , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-12-04 08:09+0000\n" +"Last-Translator: Uriel Medina , 2020-2021,2023\n" +"Language-Team: Spanish (http://app.transifex.com/django/django/language/" +"es/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Información personal" + +msgid "Permissions" +msgstr "Permisos" + +msgid "Important dates" +msgstr "Fechas importantes" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "el objeto %(name)s con clave primaria %(key)r no existe." + +msgid "Password changed successfully." +msgstr "La contraseña se ha cambiado con éxito." + +#, python-format +msgid "Change password: %s" +msgstr "Cambiar contraseña: %s" + +msgid "Authentication and Authorization" +msgstr "Autenticación y autorización" + +msgid "password" +msgstr "contraseña" + +msgid "last login" +msgstr "último inicio de sesión" + +msgid "No password set." +msgstr "No se ha establecido la clave." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Formato de clave incorrecto o algoritmo de hash desconocido." + +msgid "The two password fields didn’t match." +msgstr "Los dos campos de contraseña no coinciden." + +msgid "Password" +msgstr "Contraseña" + +msgid "Password confirmation" +msgstr "Contraseña (confirmación)" + +msgid "Enter the same password as before, for verification." +msgstr "Para verificar, introduzca la misma contraseña anterior." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Las contraseñas no se almacenan en bruto, así que no hay manera de ver la " +"contraseña del usuario, pero se puede cambiar la contraseña mediante este formulario." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Por favor, introduzca un %(username)s y clave correctos. Observe que ambos " +"campos pueden ser sensibles a mayúsculas." + +msgid "This account is inactive." +msgstr "Esta cuenta está inactiva." + +msgid "Email" +msgstr "Correo electrónico" + +msgid "New password" +msgstr "Contraseña nueva" + +msgid "New password confirmation" +msgstr "Contraseña nueva (confirmación)" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" +"Su contraseña antigua es incorrecta. Por favor, vuelva a introducirla. " + +msgid "Old password" +msgstr "Contraseña antigua" + +msgid "Password (again)" +msgstr "Contraseña (de nuevo)" + +msgid "algorithm" +msgstr "algoritmo" + +msgid "iterations" +msgstr "iteraciones" + +msgid "salt" +msgstr "salto" + +msgid "hash" +msgstr "función resumen" + +msgid "variety" +msgstr "variedad" + +msgid "version" +msgstr "versión" + +msgid "memory cost" +msgstr "coste de memoria" + +msgid "time cost" +msgstr "coste de tiempo" + +msgid "parallelism" +msgstr "paralelismo" + +msgid "work factor" +msgstr "factor trabajo" + +msgid "checksum" +msgstr "suma de verificación" + +msgid "block size" +msgstr "tamaño de bloque" + +msgid "name" +msgstr "nombre" + +msgid "content type" +msgstr "tipo de contenido" + +msgid "codename" +msgstr "nombre en código" + +msgid "permission" +msgstr "permiso" + +msgid "permissions" +msgstr "permisos" + +msgid "group" +msgstr "grupo" + +msgid "groups" +msgstr "grupos" + +msgid "superuser status" +msgstr "estado de superusuario" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Indica que este usuario tiene todos los permisos sin asignárselos " +"explícitamente." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Los grupos a los que pertenece este usuario. Un usuario tendrá todos los " +"permisos asignados a cada uno de sus grupos." + +msgid "user permissions" +msgstr "permisos de usuario" + +msgid "Specific permissions for this user." +msgstr "Permisos específicos para este usuario." + +msgid "username" +msgstr "nombre de usuario" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Requerido. 150 carácteres como máximo. Únicamente letras, dígitos y @/./+/-/" +"_ " + +msgid "A user with that username already exists." +msgstr "Ya existe un usuario con este nombre." + +msgid "first name" +msgstr "nombre" + +msgid "last name" +msgstr "apellidos" + +msgid "email address" +msgstr "dirección de correo electrónico" + +msgid "staff status" +msgstr "es staff" + +msgid "Designates whether the user can log into this admin site." +msgstr "Indica si el usuario puede entrar en este sitio de administración." + +msgid "active" +msgstr "activo" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Indica si el usuario debe ser tratado como activo. Desmarque esta opción en " +"lugar de borrar la cuenta." + +msgid "date joined" +msgstr "fecha de alta" + +msgid "user" +msgstr "usuario" + +msgid "users" +msgstr "usuarios" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Esta contraseña es demasiado corta. Debe contener al menos %(min_length)d " +"caracter." +msgstr[1] "" +"Esta contraseña es demasiado corta. Debe contener al menos %(min_length)d " +"caracteres." +msgstr[2] "" +"Esta contraseña es demasiado corta. Debe contener al menos %(min_length)d " +"caracteres." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Su contraseña debe contener al menos %(min_length)d caracter." +msgstr[1] "Su contraseña debe contener al menos %(min_length)d caracteres." +msgstr[2] "Su contraseña debe contener al menos %(min_length)d caracteres." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "La contraseña es demasiado similar a la de %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" +"Su contraseña no puede asemejarse tanto a su otra información personal." + +msgid "This password is too common." +msgstr "Esta contraseña es demasiado común." + +msgid "Your password can’t be a commonly used password." +msgstr "Su contraseña no puede ser una clave utilizada comúnmente." + +msgid "This password is entirely numeric." +msgstr "Esta contraseña es completamente numérica." + +msgid "Your password can’t be entirely numeric." +msgstr "Su contraseña no puede ser completamente numérica." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Contraseña restablecida en %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Introduzca un nombre de usuario válido. Este valor solo puede contener " +"letras mayúsculas y minúsculas de la A la Z (excepto las acentuadas), " +"números y los caracteres @/./+/-/_." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Introduza un nombre de usuario válido. Este valor puede contener únicamente " +"letras, números y los caracteres @/./+/-/_ " + +msgid "Logged out" +msgstr "Sesión terminada" + +msgid "Password reset" +msgstr "Restablecer contraseña" + +msgid "Password reset sent" +msgstr "Restablecimiento de contraseña enviado" + +msgid "Enter new password" +msgstr "Escriba la nueva contraseña" + +msgid "Password reset unsuccessful" +msgstr "Restablecimiento de contraseñas fallido" + +msgid "Password reset complete" +msgstr "Restablecimiento de contraseña completado" + +msgid "Password change" +msgstr "Cambiar contraseña" + +msgid "Password change successful" +msgstr "Contraseña cambiada correctamente" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es_AR/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es_AR/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d985402 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es_AR/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es_AR/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es_AR/LC_MESSAGES/django.po new file mode 100644 index 0000000..bd89b28 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es_AR/LC_MESSAGES/django.po @@ -0,0 +1,319 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Ramiro Morales, 2013-2017,2019,2021,2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-12-04 08:09+0000\n" +"Last-Translator: Ramiro Morales, 2013-2017,2019,2021,2023\n" +"Language-Team: Spanish (Argentina) (http://app.transifex.com/django/django/" +"language/es_AR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_AR\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Información personal" + +msgid "Permissions" +msgstr "Permisos" + +msgid "Important dates" +msgstr "Fechas importantes" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "No existe un objeto %(name)s con una clave primaria %(key)r." + +msgid "Password changed successfully." +msgstr "Cambio de contraseña exitoso" + +#, python-format +msgid "Change password: %s" +msgstr "Cambiar contraseña: %s" + +msgid "Authentication and Authorization" +msgstr "Autenticación y Autorización" + +msgid "password" +msgstr "contraseña" + +msgid "last login" +msgstr "último ingreso" + +msgid "No password set." +msgstr "No se ha establecido una contraseña." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Formato de contraseña inválido o algoritmo de hashing desconocido." + +msgid "The two password fields didn’t match." +msgstr "Los dos campos de contraseñas no coinciden entre si." + +msgid "Password" +msgstr "Contraseña" + +msgid "Password confirmation" +msgstr "Confirmación de contraseña" + +msgid "Enter the same password as before, for verification." +msgstr "" +"Introduzca la misma contraseña nuevamente, para poder verificar la misma." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"El sistema no almacena las contraseñas originales por lo cual no es posible " +"visualizar la contraseña de este usuario, pero puede modificarla usando este formulario." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Por favor introduzca un %(username)s y una contraseña correctos. Tenga en " +"cuenta que ambos campos son sensibles a mayúsculas/minúsculas." + +msgid "This account is inactive." +msgstr "Esta cuenta está inactiva." + +msgid "Email" +msgstr "Email" + +msgid "New password" +msgstr "Contraseña nueva" + +msgid "New password confirmation" +msgstr "Confirmación de contraseña nueva" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" +"La antigua contraseña introducida es incorrecta. Por favor introdúzcala " +"nuevamente." + +msgid "Old password" +msgstr "Contraseña antigua" + +msgid "Password (again)" +msgstr "Contraseña (de nuevo)" + +msgid "algorithm" +msgstr "algoritmo" + +msgid "iterations" +msgstr "iteraciones" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "variedad" + +msgid "version" +msgstr "versión" + +msgid "memory cost" +msgstr "costo en memoria" + +msgid "time cost" +msgstr "costo en tiempo" + +msgid "parallelism" +msgstr "paralelismo" + +msgid "work factor" +msgstr "work factor" + +msgid "checksum" +msgstr "suma de verificación" + +msgid "block size" +msgstr "tamaño de bloque" + +msgid "name" +msgstr "nombre" + +msgid "content type" +msgstr "tipo de contenido" + +msgid "codename" +msgstr "nombre en código" + +msgid "permission" +msgstr "permiso" + +msgid "permissions" +msgstr "permisos" + +msgid "group" +msgstr "grupo" + +msgid "groups" +msgstr "grupos" + +msgid "superuser status" +msgstr "es superusuario" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Indica que este usuario posee todos los permisos sin que sea necesario " +"asignarle los mismos en forma explícita." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Grupos a los cuales pertenece este usuario. Un usuario obtiene todos los " +"permisos otorgados a cada uno de los grupos a los cuales pertenece." + +msgid "user permissions" +msgstr "permisos de usuario" + +msgid "Specific permissions for this user." +msgstr "Permisos específicos de este usuario" + +msgid "username" +msgstr "nombre de usuario" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Obligatorio. Longitud máxima de 150 caracteres. Solo puede estar formado por " +"letras, números y los caracteres @/./+/-/_." + +msgid "A user with that username already exists." +msgstr "Ya existe un usuario con ese nombre." + +msgid "first name" +msgstr "nombre" + +msgid "last name" +msgstr "apellido" + +msgid "email address" +msgstr "Dirección de email" + +msgid "staff status" +msgstr "es staff" + +msgid "Designates whether the user can log into this admin site." +msgstr "Indica si el usuario puede ingresar a este sitio de administración." + +msgid "active" +msgstr "activo" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Indica si el usuario debe ser tratado como un usuario activo. Desactive este " +"campo en lugar de eliminar usuarios." + +msgid "date joined" +msgstr "fecha de creación" + +msgid "user" +msgstr "usuario" + +msgid "users" +msgstr "usuarios" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"La contraseña es demasiado corta. Debe contener por lo menos %(min_length)d " +"caracter." +msgstr[1] "" +"La contraseña es demasiado corta. Debe contener por lo menos %(min_length)d " +"caracteres." +msgstr[2] "" +"La contraseña es demasiado corta. Debe contener por lo menos %(min_length)d " +"caracteres." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Su contraseña debe contener por lo menos %(min_length)d caracter." +msgstr[1] "Su contraseña debe contener por lo menos %(min_length)d caracteres." +msgstr[2] "Su contraseña debe contener por lo menos %(min_length)d caracteres." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "La contraseña es muy similar a %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" +"Su contraseña no puede ser similar a otros componentes de su información " +"personal." + +msgid "This password is too common." +msgstr "La contraseña tiene un valor demasiado común." + +msgid "Your password can’t be a commonly used password." +msgstr "Su contraseña no puede ser una contraseña usada muy comúnmente." + +msgid "This password is entirely numeric." +msgstr "La contraseña está formada completamente por dígitos." + +msgid "Your password can’t be entirely numeric." +msgstr "Su contraseña no puede estar formada exclusivamente por números." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Reinicio de contraseña en %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Introduzca un nombre de usuario válido. Este valor solo puede contener " +"letras mayúsculas y minúsculas de la A la Z (excepto las acentuadas), " +"números y los caracteres @/./+/-/_." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Introduzca un nombre de usuario válido. Este valor solo puede contener " +"letras, números y los caracteres @/./+/-/_." + +msgid "Logged out" +msgstr "Sesión cerrada" + +msgid "Password reset" +msgstr "Reinicio de contraseña" + +msgid "Password reset sent" +msgstr "Se ha enviado un email de reinicialización de contraseña" + +msgid "Enter new password" +msgstr "Introduzca nueva contraseña" + +msgid "Password reset unsuccessful" +msgstr "Reinicio de contraseña fallido" + +msgid "Password reset complete" +msgstr "Reinicio de contraseña completado" + +msgid "Password change" +msgstr "Cambio de contraseña" + +msgid "Password change successful" +msgstr "Cambio de contraseña exitoso" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es_CO/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es_CO/LC_MESSAGES/django.mo new file mode 100644 index 0000000..deb2dd1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es_CO/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es_CO/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es_CO/LC_MESSAGES/django.po new file mode 100644 index 0000000..46adfb2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es_CO/LC_MESSAGES/django.po @@ -0,0 +1,304 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# albertoalcolea , 2014 +# Ernesto Avilés Vázquez , 2015 +# guillem , 2012 +# Igor Támara , 2015 +# Jannis Leidel , 2011 +# Josue Naaman Nistal Guerra , 2014 +# Leonardo J. Caballero G. , 2011 +# Veronicabh , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-09-24 14:24+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Spanish (Colombia) (http://www.transifex.com/django/django/" +"language/es_CO/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_CO\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Información personal" + +msgid "Permissions" +msgstr "Permisos" + +msgid "Important dates" +msgstr "Fechas importantes" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "el objeto %(name)s con clave primaria %(key)r no existe." + +msgid "Password changed successfully." +msgstr "La contraseña se ha cambiado con éxito." + +#, python-format +msgid "Change password: %s" +msgstr "Cambiar contraseña: %s" + +msgid "Authentication and Authorization" +msgstr "Autenticación y autorización" + +msgid "password" +msgstr "contraseña" + +msgid "last login" +msgstr "último inicio de sesión" + +msgid "No password set." +msgstr "No se ha establecido la clave." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Formato de clave incorrecto o algoritmo de hash desconocido." + +msgid "The two password fields didn't match." +msgstr "Los dos campos de contraseña no coinciden." + +msgid "Password" +msgstr "Contraseña" + +msgid "Password confirmation" +msgstr "Contraseña (confirmación)" + +msgid "Enter the same password as before, for verification." +msgstr "Para verificar, ingrese la misma contraseña anterior." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Por favor, introduzca un %(username)s y clave correctos. Observe que ambos " +"campos pueden ser sensibles a mayúsculas." + +msgid "This account is inactive." +msgstr "Esta cuenta está inactiva." + +msgid "Email" +msgstr "Correo electrónico" + +msgid "New password" +msgstr "Contraseña nueva" + +msgid "New password confirmation" +msgstr "Contraseña nueva (confirmación)" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Su contraseña antigua es incorrecta. Por favor, vuelva a introducirla." + +msgid "Old password" +msgstr "Contraseña antigua" + +msgid "Password (again)" +msgstr "Contraseña (de nuevo)" + +msgid "algorithm" +msgstr "algoritmo" + +msgid "iterations" +msgstr "iteraciones" + +msgid "salt" +msgstr "sal" + +msgid "hash" +msgstr "función resumen" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "factor trabajo" + +msgid "checksum" +msgstr "suma de verificación" + +msgid "name" +msgstr "nombre" + +msgid "content type" +msgstr "tipo de contenido" + +msgid "codename" +msgstr "nombre en código" + +msgid "permission" +msgstr "permiso" + +msgid "permissions" +msgstr "permisos" + +msgid "group" +msgstr "grupo" + +msgid "groups" +msgstr "grupos" + +msgid "superuser status" +msgstr "es superusuario" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Indica que este usuario tiene todos los permisos sin asignárselos " +"explícitamente." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Los grupos a los que pertenece este usuario. Un usuario tendrá todos los " +"permisos asignados a cada uno de sus grupos." + +msgid "user permissions" +msgstr "permisos de usuario" + +msgid "Specific permissions for this user." +msgstr "Permisos específicos para este usuario." + +msgid "username" +msgstr "nombre de usuario" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "Ya existe un usuario con este nombre." + +msgid "first name" +msgstr "nombre" + +msgid "last name" +msgstr "apellidos" + +msgid "email address" +msgstr "dirección de correo electrónico" + +msgid "staff status" +msgstr "es staff" + +msgid "Designates whether the user can log into this admin site." +msgstr "Indica si el usuario puede entrar en este sitio de administración." + +msgid "active" +msgstr "activo" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Indica si el usuario debe ser tratado como activo. Desmarque esta opción en " +"lugar de borrar la cuenta." + +msgid "date joined" +msgstr "fecha de alta" + +msgid "user" +msgstr "usuario" + +msgid "users" +msgstr "usuarios" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Esta contraseña es demasiado corta. Debe contener al menos %(min_length)d " +"carácter." +msgstr[1] "" +"Esta contraseña es demasiado corta. Debe contener al menos %(min_length)d " +"caracteres." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Su contraseña debe contener por lo menos %(min_length)d carácter." +msgstr[1] "Su contraseña debe contener por lo menos %(min_length)d caracteres." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "La contraseña es muy parecida a %(verbose_name)s." + +msgid "Your password can't be too similar to your other personal information." +msgstr "" +"Su contraseña no puede asemejarse tanto a su otra información personal." + +msgid "This password is too common." +msgstr "Esta contraseña es demasiado común." + +msgid "Your password can't be a commonly used password." +msgstr "La contraseña no puede ser una contraseña de uso común." + +msgid "This password is entirely numeric." +msgstr "Esta contraseña es completamente numérica." + +msgid "Your password can't be entirely numeric." +msgstr "Su contraseña no puede ser completamente numérica." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Contraseña restablecida en %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "Sesión terminada" + +msgid "Password reset" +msgstr "Restablecer contraseña" + +msgid "Password reset sent" +msgstr "Restablecimiento de contraseña enviado" + +msgid "Enter new password" +msgstr "Escriba la nueva contraseña" + +msgid "Password reset unsuccessful" +msgstr "Restablecimiento de contraseñas fallido" + +msgid "Password reset complete" +msgstr "Restablecimiento de contraseña completado" + +msgid "Password change" +msgstr "Cambiar contraseña" + +msgid "Password change successful" +msgstr "Contraseña cambiada correctamente" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es_MX/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es_MX/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7cccb78 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es_MX/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es_MX/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es_MX/LC_MESSAGES/django.po new file mode 100644 index 0000000..db9be6e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es_MX/LC_MESSAGES/django.po @@ -0,0 +1,312 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Abe Estrada, 2011-2012 +# Claude Paroz , 2017 +# Jesús Bautista , 2019 +# Juan Pablo Flores , 2016 +# zodman , 2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-12-26 17:00+0000\n" +"Last-Translator: Jesús Bautista \n" +"Language-Team: Spanish (Mexico) (http://www.transifex.com/django/django/" +"language/es_MX/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_MX\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Información personal" + +msgid "Permissions" +msgstr "Permisos" + +msgid "Important dates" +msgstr "Fechas importantes" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "No existe un objeto %(name)s con una clave primaria %(key)r." + +msgid "Password changed successfully." +msgstr "Cambio de contraseña exitoso" + +#, python-format +msgid "Change password: %s" +msgstr "Cambiar contraseña: %s" + +msgid "Authentication and Authorization" +msgstr "Autenticación y Autorización" + +msgid "password" +msgstr "contraseña" + +msgid "last login" +msgstr "último ingreso" + +msgid "No password set." +msgstr "No se ha establecido ninguna contraseña." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Formato de contraseña no válido o algoritmo de hash desconocido." + +msgid "The two password fields didn’t match." +msgstr "Los dos campos de contraseña no coinciden." + +msgid "Password" +msgstr "Contraseña" + +msgid "Password confirmation" +msgstr "Confirmación de contraseña" + +msgid "Enter the same password as before, for verification." +msgstr "Para verificar, introduzca la misma contraseña que introdujo antes." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Las contraseñas sin procesar no se almacenan, por lo que no hay forma de ver " +"la contraseña de este usuario, pero puede cambiarla usando este formulario. " + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Por favor introduzca %(username)s y contraseña correctos. Note que puede que " +"ambos campos sean estrictos en relación a diferencias entre mayúsculas y " +"minúsculas." + +msgid "This account is inactive." +msgstr "Esta cuenta está inactiva." + +msgid "Email" +msgstr "Correo Electrónico" + +msgid "New password" +msgstr "Contraseña nueva" + +msgid "New password confirmation" +msgstr "Confirmación de contraseña nueva" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" +"La antigua contraseña introducida es incorrecta. Por favor introdúzcala " +"nuevamente." + +msgid "Old password" +msgstr "Contraseña antigua" + +msgid "Password (again)" +msgstr "Contraseña (de nuevo)" + +msgid "algorithm" +msgstr "algoritmo" + +msgid "iterations" +msgstr "repeticiones" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "variedad" + +msgid "version" +msgstr "versión" + +msgid "memory cost" +msgstr "costo en memoria" + +msgid "time cost" +msgstr "costo en tiempo" + +msgid "parallelism" +msgstr "Paralelismo" + +msgid "work factor" +msgstr "factor trabajo" + +msgid "checksum" +msgstr "checksum" + +msgid "name" +msgstr "nombre" + +msgid "content type" +msgstr "tipo de contenido" + +msgid "codename" +msgstr "nombre código" + +msgid "permission" +msgstr "permiso" + +msgid "permissions" +msgstr "permisos" + +msgid "group" +msgstr "grupo" + +msgid "groups" +msgstr "grupos" + +msgid "superuser status" +msgstr "es superusuario" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Indica que este usuario posee todos los permisos sin que sea necesario " +"asignarle los mismos en forma explícita." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Los grupos a los que pertenece este usuario. Un usuario obtendrá todos los " +"permisos concedidos para cada uno de su grupo." + +msgid "user permissions" +msgstr "permisos de usuario" + +msgid "Specific permissions for this user." +msgstr "Permisos específicos para este usuario" + +msgid "username" +msgstr "nombre de usuario" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Obligatorio. Longitud máxima 150 caracteres alfanuméricos. Letras, dígitos y " +"@/./+/-/_ únicamente." + +msgid "A user with that username already exists." +msgstr "Ya existe un usuario con ese nombre." + +msgid "first name" +msgstr "nombre" + +msgid "last name" +msgstr "apellido" + +msgid "email address" +msgstr "Dirección de correo electrónico" + +msgid "staff status" +msgstr "es staff" + +msgid "Designates whether the user can log into this admin site." +msgstr "Indica si el usuario puede ingresar a este sitio de administración." + +msgid "active" +msgstr "activo" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Indica si el usuario debe ser tratado como un usuario activo. Desactive este " +"campo en lugar de eliminar usuarios." + +msgid "date joined" +msgstr "fecha de creación" + +msgid "user" +msgstr "usuario" + +msgid "users" +msgstr "usuarios" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"La contraseña es muy corta. Debe contener al menos %(min_length)d caracter." +msgstr[1] "" +"La contraseña es muy corta. Debe contener al menos %(min_length)d caracteres." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +"Tu contraseña es muy corta. Debe contener al menos %(min_length)d caracter." +msgstr[1] "" +"Su contraseña es muy corta. Debe contener al menos %(min_length)d caracteres." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "La contraseña es muy similar a %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Su contraseña no puede ser muy similar a su otra información personal." + +msgid "This password is too common." +msgstr "Esta contraseña es muy común." + +msgid "Your password can’t be a commonly used password." +msgstr "Su contraseña no puede ser una contraseña de uso común." + +msgid "This password is entirely numeric." +msgstr "Esta contraseña es totalmente numérica." + +msgid "Your password can’t be entirely numeric." +msgstr "Su contraseña no puede ser completamente numérica." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Restablecimiento de la contraseña en %(site_name)s " + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"Ingrese un nombre de usuario válido. Este sólo puede contener letras en " +"inglés, números y caracteres @ /. / + / - / _." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Ingrese un nombre de usuario válido. Este puede contener sólo letras, " +"números y caracteres @ /. / + / - / _." + +msgid "Logged out" +msgstr "Sesión cerrada" + +msgid "Password reset" +msgstr "Restablecer contraseña" + +msgid "Password reset sent" +msgstr "Restablecimiento de contraseña enviado" + +msgid "Enter new password" +msgstr "Introduzca la nueva contraseña" + +msgid "Password reset unsuccessful" +msgstr "Restablecimiento de contraseña no exitosa" + +msgid "Password reset complete" +msgstr "Reinicialización de contraseña completada" + +msgid "Password change" +msgstr "Cambio de contraseña" + +msgid "Password change successful" +msgstr "Cambio de contraseña exitoso" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es_VE/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es_VE/LC_MESSAGES/django.mo new file mode 100644 index 0000000..11f27e4 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es_VE/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es_VE/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es_VE/LC_MESSAGES/django.po new file mode 100644 index 0000000..0e963c5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/es_VE/LC_MESSAGES/django.po @@ -0,0 +1,304 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Eduardo , 2017 +# Leonardo J. Caballero G. , 2016 +# Yoel Acevedo, 2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-09-24 14:24+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Spanish (Venezuela) (http://www.transifex.com/django/django/" +"language/es_VE/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_VE\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Información personal" + +msgid "Permissions" +msgstr "Permisos" + +msgid "Important dates" +msgstr "Fechas importantes" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "el objeto %(name)s con clave primaria %(key)r no existe." + +msgid "Password changed successfully." +msgstr "La contraseña se ha cambiado con éxito." + +#, python-format +msgid "Change password: %s" +msgstr "Cambiar contraseña: %s" + +msgid "Authentication and Authorization" +msgstr "Autenticación y autorización" + +msgid "password" +msgstr "contraseña" + +msgid "last login" +msgstr "último inicio de sesión" + +msgid "No password set." +msgstr "No se ha establecido la clave." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Formato de clave incorrecto o algoritmo de hash desconocido." + +msgid "The two password fields didn't match." +msgstr "Los dos campos de contraseña no coinciden." + +msgid "Password" +msgstr "Contraseña" + +msgid "Password confirmation" +msgstr "Contraseña (confirmación)" + +msgid "Enter the same password as before, for verification." +msgstr "Para verificar, ingrese la misma contraseña anterior." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Por favor, introduzca un %(username)s y clave correctos. Observe que ambos " +"campos pueden ser sensibles a mayúsculas." + +msgid "This account is inactive." +msgstr "Esta cuenta está inactiva." + +msgid "Email" +msgstr "Correo electrónico" + +msgid "New password" +msgstr "Contraseña nueva" + +msgid "New password confirmation" +msgstr "Contraseña nueva (confirmación)" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Su contraseña antigua es incorrecta. Por favor, vuelva a introducirla." + +msgid "Old password" +msgstr "Contraseña antigua" + +msgid "Password (again)" +msgstr "Contraseña (de nuevo)" + +msgid "algorithm" +msgstr "algoritmo" + +msgid "iterations" +msgstr "iteraciones" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "función resumen" + +msgid "variety" +msgstr "variedad" + +msgid "version" +msgstr "versión" + +msgid "memory cost" +msgstr "costo de memoria" + +msgid "time cost" +msgstr "costo de tiempo" + +msgid "parallelism" +msgstr "paralelismo" + +msgid "work factor" +msgstr "factor trabajo" + +msgid "checksum" +msgstr "suma de verificación" + +msgid "name" +msgstr "nombre" + +msgid "content type" +msgstr "tipo de contenido" + +msgid "codename" +msgstr "nombre en código" + +msgid "permission" +msgstr "permiso" + +msgid "permissions" +msgstr "permisos" + +msgid "group" +msgstr "grupo" + +msgid "groups" +msgstr "grupos" + +msgid "superuser status" +msgstr "estatus de superusuario" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Indica que este usuario tiene todos los permisos sin asignárselos " +"explícitamente." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Los grupos a los que pertenece este usuario. Un usuario tendrá todos los " +"permisos asignados a cada uno de sus grupos." + +msgid "user permissions" +msgstr "permisos de usuario" + +msgid "Specific permissions for this user." +msgstr "Permisos específicos para este usuario." + +msgid "username" +msgstr "nombre de usuario" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Requerido. 150 caracteres o menos. Letras, dígitos y @/./+/-/_ solamente. " + +msgid "A user with that username already exists." +msgstr "Ya existe un usuario con este nombre." + +msgid "first name" +msgstr "nombre" + +msgid "last name" +msgstr "apellidos" + +msgid "email address" +msgstr "dirección de correo electrónico" + +msgid "staff status" +msgstr "estatus staff" + +msgid "Designates whether the user can log into this admin site." +msgstr "Indica si el usuario puede entrar en este sitio de administración." + +msgid "active" +msgstr "activo" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Indica si el usuario debe ser tratado como activo. Desmarque esta opción en " +"lugar de borrar la cuenta." + +msgid "date joined" +msgstr "fecha de alta" + +msgid "user" +msgstr "usuario" + +msgid "users" +msgstr "usuarios" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Esta contraseña es demasiado corta. Debe contener al menos %(min_length)d " +"carácter." +msgstr[1] "" +"Esta contraseña es demasiado corta. Debe contener al menos %(min_length)d " +"caracteres." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Su contraseña debe contener por lo menos %(min_length)d carácter." +msgstr[1] "Su contraseña debe contener por lo menos %(min_length)d caracteres." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "La contraseña es muy parecida a %(verbose_name)s." + +msgid "Your password can't be too similar to your other personal information." +msgstr "" +"Su contraseña no puede asemejarse tanto a su otra información personal." + +msgid "This password is too common." +msgstr "Esta contraseña es demasiado común." + +msgid "Your password can't be a commonly used password." +msgstr "La contraseña no puede ser una contraseña de uso común." + +msgid "This password is entirely numeric." +msgstr "Esta contraseña es completamente numérica." + +msgid "Your password can't be entirely numeric." +msgstr "Su contraseña no puede ser completamente numérica." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Contraseña restablecida en %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"Introduzca un nombre de usuario válido. Este solo puede contener letras del " +"alfabeto en ingles, números y los caracteres @/./+/-/_" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Introduzca un nombre de usuario válido. Este solo puede contener letras, " +"números y los caracteres @/./+/-/_" + +msgid "Logged out" +msgstr "Sesión terminada" + +msgid "Password reset" +msgstr "Restablecer contraseña" + +msgid "Password reset sent" +msgstr "Restablecimiento de contraseña enviado" + +msgid "Enter new password" +msgstr "Escriba la nueva contraseña" + +msgid "Password reset unsuccessful" +msgstr "Restablecimiento de contraseñas fallido" + +msgid "Password reset complete" +msgstr "Restablecimiento de contraseña completado" + +msgid "Password change" +msgstr "Cambiar contraseña" + +msgid "Password change successful" +msgstr "Contraseña cambiada correctamente" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/et/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/et/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3f13c02 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/et/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/et/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/et/LC_MESSAGES/django.po new file mode 100644 index 0000000..604a407 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/et/LC_MESSAGES/django.po @@ -0,0 +1,309 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Janno Liivak , 2013,2015 +# madisvain , 2011 +# Martin , 2015,2023 +# Martin , 2016-2017 +# Marti Raudsepp , 2014,2016 +# Ragnar Rebase , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-12-04 08:09+0000\n" +"Last-Translator: Martin , 2015,2023\n" +"Language-Team: Estonian (http://app.transifex.com/django/django/language/" +"et/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: et\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Isiklikud andmd" + +msgid "Permissions" +msgstr "Õigused" + +msgid "Important dates" +msgstr "Tähtsad kuupäevad" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(name)s objekt primaarvõtmega %(key)r ei eksisteeri." + +msgid "Password changed successfully." +msgstr "Salasõna edukalt muudetud." + +#, python-format +msgid "Change password: %s" +msgstr "Muuda salasõna: %s" + +msgid "Authentication and Authorization" +msgstr "Autentimine ja Volitamine" + +msgid "password" +msgstr "salasõna" + +msgid "last login" +msgstr "viimane sisenemine" + +msgid "No password set." +msgstr "Parool on määramata." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Lubamatu parooli formaat või tundmatu räsialgoritm." + +msgid "The two password fields didn’t match." +msgstr "Sisestatud paroolid polnud identsed." + +msgid "Password" +msgstr "Salasõna" + +msgid "Password confirmation" +msgstr "Salasõna kinnitus" + +msgid "Enter the same password as before, for verification." +msgstr "" +"Sisestage sama salasõna uuesti veendumaks, et sisestamisel ei tekkinud vigu" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Salasõnu ei salvestata töötlemata kujul, seega puudub võimalus selle " +"kasutaja salasõna nägemiseks, kuid saate seda muuta kasutades seda vormi." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Palun sisestage õige %(username)s ja parool. Teadke, et mõlemad väljad " +"võivad olla tõstutundlikud." + +msgid "This account is inactive." +msgstr "See konto ei ole aktiivne." + +msgid "Email" +msgstr "E-post" + +msgid "New password" +msgstr "Uus salasõna" + +msgid "New password confirmation" +msgstr "Uue salasõna kinnitus" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Te sisestasite oma vana parooli vigaselt. Palun sisestage see uuesti." + +msgid "Old password" +msgstr "Vana salasõna" + +msgid "Password (again)" +msgstr "Salasõna (uuesti)" + +msgid "algorithm" +msgstr "algoritm" + +msgid "iterations" +msgstr "iteratsioone" + +msgid "salt" +msgstr "sool" + +msgid "hash" +msgstr "räsi" + +msgid "variety" +msgstr "liik" + +msgid "version" +msgstr "versioon" + +msgid "memory cost" +msgstr "mälukasutus" + +msgid "time cost" +msgstr "ajakulu" + +msgid "parallelism" +msgstr "parallelism" + +msgid "work factor" +msgstr "töötegur" + +msgid "checksum" +msgstr "kontrollsumma" + +msgid "block size" +msgstr "ploki pikkus" + +msgid "name" +msgstr "nimi" + +msgid "content type" +msgstr "sisutüüp" + +msgid "codename" +msgstr "koodnimi" + +msgid "permission" +msgstr "õigus" + +msgid "permissions" +msgstr "õigused" + +msgid "group" +msgstr "grupp" + +msgid "groups" +msgstr "grupid" + +msgid "superuser status" +msgstr "superkasutaja staatus" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "Määrab, kas see kasutaja omab automaatselt ja alati kõiki õigus." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Grupid, millesse antud kasutaja kuulub. Kasutaja pärib kõik õigused, mis on " +"määratud igale tema grupile." + +msgid "user permissions" +msgstr "kasutajaõigused" + +msgid "Specific permissions for this user." +msgstr "Spetsiaalsed õigused sellele kasutajale." + +msgid "username" +msgstr "kasutajatunnus" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Nõutav. 150 märki või vähem. Ainult tähed, numbrid ja @/./+/-/_ tähemärgid." + +msgid "A user with that username already exists." +msgstr "Sama kasutajatunnusega kasutaja on juba olemas." + +msgid "first name" +msgstr "eesnimi" + +msgid "last name" +msgstr "perenimi" + +msgid "email address" +msgstr "e-posti aadress" + +msgid "staff status" +msgstr "personalistaatus" + +msgid "Designates whether the user can log into this admin site." +msgstr "" +"Määrab, kas kasutaja saab sisse logida sellesse admininistreerimisliidesesse." + +msgid "active" +msgstr "aktiivne" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Määrab, kas see konto on aktiivne. Kustutamise asemel lihtsalt deaktiveerige " +"konto." + +msgid "date joined" +msgstr "liitumise kuupäev" + +msgid "user" +msgstr "kasutaja" + +msgid "users" +msgstr "kasutajad" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Salasõna on liiga lühike. Selles peab olema vähemalt %(min_length)d täht." +msgstr[1] "" +"Salasõna on liiga lühike. Selles peab olema vähemalt %(min_length)d tähte." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Salasõna peab sisaldama vähemalt %(min_length)d tähte." +msgstr[1] "Salasõna peab sisaldama vähemalt %(min_length)d tähte." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Salasõna ja %(verbose_name)s on liiga sarnased." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Salasõna ei tohi olla liialt sarnane teie isiklike andmetega." + +msgid "This password is too common." +msgstr "Salasõna on liiga teada-tuntud." + +msgid "Your password can’t be a commonly used password." +msgstr "Salasõna ei tohi olla üks enimlevinud salasõnadest." + +msgid "This password is entirely numeric." +msgstr "See salasõna koosneb ainult numbritest." + +msgid "Your password can’t be entirely numeric." +msgstr "Salasõna ei tohi koosneda ainult numbritest." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Uue salasõna loomine saidil %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Sisesta korrektne kasutajatunnus. See väärtus võib sisaldada ainult tähti, " +"numbreid ja @/./+/-/_ tähemärke." + +msgid "Logged out" +msgstr "Välja logitud" + +msgid "Password reset" +msgstr "Uue salasõna loomine" + +msgid "Password reset sent" +msgstr "Salasõna lähtestamine saadetud" + +msgid "Enter new password" +msgstr "Sisesta uus salasõna" + +msgid "Password reset unsuccessful" +msgstr "Uue salasõna loomine ebaõnnestus" + +msgid "Password reset complete" +msgstr "Uue salasõna loomine lõpetatud" + +msgid "Password change" +msgstr "Salasõna muutmine" + +msgid "Password change successful" +msgstr "Salasõna muutmine õnnestus" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/eu/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/eu/LC_MESSAGES/django.mo new file mode 100644 index 0000000..354c6bb Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/eu/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/eu/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/eu/LC_MESSAGES/django.po new file mode 100644 index 0000000..093ba2e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/eu/LC_MESSAGES/django.po @@ -0,0 +1,311 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Aitzol Naberan , 2013 +# Eneko Illarramendi , 2017,2023 +# Jannis Leidel , 2011 +# julen, 2015 +# Urtzi Odriozola , 2016-2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-12-04 08:09+0000\n" +"Last-Translator: Eneko Illarramendi , 2017,2023\n" +"Language-Team: Basque (http://app.transifex.com/django/django/language/eu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Informazio pertsonala" + +msgid "Permissions" +msgstr "Baimenak" + +msgid "Important dates" +msgstr "Data garrantzitsuak" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "Ez dago %(key)r gakodun %(name)s objekturik." + +msgid "Password changed successfully." +msgstr "Ondo aldatu da pasahitza." + +#, python-format +msgid "Change password: %s" +msgstr "Pasahitza aldatu: %s" + +msgid "Authentication and Authorization" +msgstr "Autentikazio eta baimentzea" + +msgid "password" +msgstr "pasahitza" + +msgid "last login" +msgstr "azken sarrera" + +msgid "No password set." +msgstr "Pasahitza ezarri gabe." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Pasahitz formatu baliogabea edo hash algoritmo ezezaguna." + +msgid "The two password fields didn’t match." +msgstr "Bi pasahitzak ez datoz bat." + +msgid "Password" +msgstr "Pasahitza" + +msgid "Password confirmation" +msgstr "Pasahitza berretsi" + +msgid "Enter the same password as before, for verification." +msgstr "Idatzi aurreko pasahitz bera, egiaztapenerako." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Pasahitz gordinak ez direnez jasotzen ez dago erabiltzaile honen pasahitza " +"ikusterik, baina pasahitza aldatu dezakezu hemen." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Mesedez idatzi %(username)s eta pasahitz egokiak. Maiskula eta minuskulak " +"ondo bereiztu." + +msgid "This account is inactive." +msgstr "Kontu hau az dago aktibo." + +msgid "Email" +msgstr "Emaila" + +msgid "New password" +msgstr "Pasahitz berria" + +msgid "New password confirmation" +msgstr "Pasahitz berria berretsi" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Zure pasahitz zaharra ez da zuzena. Idatzi ezazu berriro." + +msgid "Old password" +msgstr "Pasahitz zaharra" + +msgid "Password (again)" +msgstr "Pasahitza (berriro)" + +msgid "algorithm" +msgstr "algoritmoak" + +msgid "iterations" +msgstr "iterazioak" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "aldaera" + +msgid "version" +msgstr "bertsioa" + +msgid "memory cost" +msgstr "memoria kostua" + +msgid "time cost" +msgstr "denbora kostua" + +msgid "parallelism" +msgstr "paralelismoa" + +msgid "work factor" +msgstr "work factor" + +msgid "checksum" +msgstr "checksum" + +msgid "block size" +msgstr "blokearen tamaina" + +msgid "name" +msgstr "izena" + +msgid "content type" +msgstr "eduki mota" + +msgid "codename" +msgstr "kode izena" + +msgid "permission" +msgstr "baimena" + +msgid "permissions" +msgstr "baimenak" + +msgid "group" +msgstr "taldea" + +msgid "groups" +msgstr "taldeak" + +msgid "superuser status" +msgstr "Erabiltzaile nagusia" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Erabiltzaileari baimen guztiak esleitzeko banan-banan aukeratu behar izan " +"gabe." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Erabiltzailea zein taldetakoa den. Erabiltzaileak bere talde bakoitzari " +"emandako baimen guztiak jasoko ditu." + +msgid "user permissions" +msgstr "Erabiltzailearen baimenak" + +msgid "Specific permissions for this user." +msgstr "Erabiltzaile honentzako baimenak." + +msgid "username" +msgstr "erabiltzailea" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Beharrezkoa. 150 karaktere edo gutxiago. Hizki, zenbaki eta @/./+/-/_ " +"bakarrik." + +msgid "A user with that username already exists." +msgstr "Erabiltzaile izen hori ez dago eskuragarri." + +msgid "first name" +msgstr "izena" + +msgid "last name" +msgstr "abizena" + +msgid "email address" +msgstr "helbide elektronikoa" + +msgid "staff status" +msgstr "Arduradun egoera" + +msgid "Designates whether the user can log into this admin site." +msgstr "" +"Erabiltzaileak kudeaketa gune honetan sartzeko baimena duen edo ez " +"adierazten du." + +msgid "active" +msgstr "Aktiboa" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Erabiltzaile bat aktibo gisa tratatu edo ez zehazten du. Ezgaitu hau kontuak " +"ezabatu beharrean." + +msgid "date joined" +msgstr "erregistro eguna" + +msgid "user" +msgstr "erabiltzailea" + +msgid "users" +msgstr "erabiltzaileak" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Pasahitz hau laburregia da. Gutxienez karaktere %(min_length)d izan behar du." +msgstr[1] "" +"Pasahitz hau laburregia da. Gutxienez %(min_length)d karaktere izan behar " +"ditu." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Zure pasahitzak gutxienez karaktere %(min_length)d eduki behar du." +msgstr[1] "" +"Zure pasahitzak gutxienez %(min_length)d karaktere eduki behar ditu." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Zure pasahitza %(verbose_name)s-(r)en oso antzekoa da." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" +"Zure pasahitzak ezin du zure beste informazio pertsonalaren antzekoegia izan." + +msgid "This password is too common." +msgstr "Pasahitz hau arruntegia da." + +msgid "Your password can’t be a commonly used password." +msgstr "Zure pasahitzak ezin du pasahitz arrunt bat izan." + +msgid "This password is entirely numeric." +msgstr "Zure pasahitza osorik zenbakizkoa da." + +msgid "Your password can’t be entirely numeric." +msgstr "Zure pasahitzak ezin du guztiz zenbakizkoa izan." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Pasahitza berrezarri %(site_name)s webgunean" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Idatzi baleko erabiltzaile izen bat. Eremu honetan hizki, zenbaki eta @/./" +"+/-/_ karaktereak bakarrik erabili daitezke." + +msgid "Logged out" +msgstr "Sesiotik kanpo" + +msgid "Password reset" +msgstr "Pasahitz-berrezartzea" + +msgid "Password reset sent" +msgstr "Pasahitz-berrezartzea bidalita" + +msgid "Enter new password" +msgstr "Idatzi pasahitz berria" + +msgid "Password reset unsuccessful" +msgstr "Pasahitza ez da ondo berrezarri" + +msgid "Password reset complete" +msgstr "Pasahitz-berrezartzea burututa" + +msgid "Password change" +msgstr "Pasahitz-aldaketa" + +msgid "Password change successful" +msgstr "Pasahitza ondo aldatu da" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/fa/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/fa/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9fa962e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/fa/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/fa/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/fa/LC_MESSAGES/django.po new file mode 100644 index 0000000..ef45334 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/fa/LC_MESSAGES/django.po @@ -0,0 +1,313 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ahmad Hosseini , 2020 +# Ali Nikneshan , 2015 +# Eric Hamiter , 2013 +# Farshad Asadpour, 2021 +# Jannis Leidel , 2011 +# cef32bddc4c7e18de7e89af20a3a57ef_18bb97f, 2015 +# MJafar Mashhadi , 2018 +# Pouya Abbassi, 2016 +# Reza Mohammadi , 2013-2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2021-11-19 17:35+0000\n" +"Last-Translator: Farshad Asadpour\n" +"Language-Team: Persian (http://www.transifex.com/django/django/language/" +"fa/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fa\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Personal info" +msgstr "اطلاعات شخصی" + +msgid "Permissions" +msgstr "اجازه‌ها" + +msgid "Important dates" +msgstr "تاریخ‌های مهم" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "شیء %(name)s با کلید اصلی %(key)r وجود ندارد." + +msgid "Password changed successfully." +msgstr "گذرواژه با موفقیت تغییر یافت." + +#, python-format +msgid "Change password: %s" +msgstr "تغییر گذرواژه: %s" + +msgid "Authentication and Authorization" +msgstr "بررسی اصالت و اجازه‌ها" + +msgid "password" +msgstr "گذرواژه" + +msgid "last login" +msgstr "آخرین ورود" + +msgid "No password set." +msgstr "هیچ رمزی انتخاب نشده است." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "رمز نامعتبر یا الگوریتم رمزنگاری ناشناس" + +msgid "The two password fields didn’t match." +msgstr "دو فیلد گذرواژه با هم مطابقت ندارند." + +msgid "Password" +msgstr "گذرواژه" + +msgid "Password confirmation" +msgstr "تأیید گذرواژه" + +msgid "Enter the same password as before, for verification." +msgstr "برای تائید، رمز عبور قبلی را وارد کنید." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"گذرواژه‌ها به صورت خام نگهداری نمی‌شوند لذا راهی برای مشاهدهٔ گذرواژهٔ این کاربر " +"وجود ندارد، اما می‌توانید آن را با این فرم تغییر دهید." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"لطفا %(username)s و گذرواژه‌ای قابل قبول وارد کنید.\n" +"توجه داشته باشید که ممکن است هر دو به کوچکی و بزرگی حروف حساس باشند." + +msgid "This account is inactive." +msgstr "این حساب غیر فعال است." + +msgid "Email" +msgstr "ایمیل" + +msgid "New password" +msgstr "گذرواژهٔ جدید" + +msgid "New password confirmation" +msgstr "تأیید گذرواژهٔ جدید" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "گذرواژهٔ قدیمی‌تان اشتباه وارد شد. لطفاً دوباره وارد کنید." + +msgid "Old password" +msgstr "گذرواژهٔ قدیمی" + +msgid "Password (again)" +msgstr "گذرواژه (تکرار)" + +msgid "algorithm" +msgstr "الگوریتم" + +msgid "iterations" +msgstr "تکرار" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "تنوع" + +msgid "version" +msgstr "نسخه" + +msgid "memory cost" +msgstr "هزینه‌ی حافظه" + +msgid "time cost" +msgstr "هزینه‌ی زمان" + +msgid "parallelism" +msgstr "موازات" + +msgid "work factor" +msgstr "عامل کار" + +msgid "checksum" +msgstr "جمع کنترلی" + +msgid "block size" +msgstr "اندازه بلاک" + +msgid "name" +msgstr "نام" + +msgid "content type" +msgstr "نوع محتوی" + +msgid "codename" +msgstr "نام کد" + +msgid "permission" +msgstr "اجازه" + +msgid "permissions" +msgstr "اجازه‌ها" + +msgid "group" +msgstr "گروه" + +msgid "groups" +msgstr "گروه‌ها" + +msgid "superuser status" +msgstr "ابرکاربر" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"نشان می‌دهد که این کاربر همهٔ اجازه‌ها را دارد بدون آنکه به صراحت به او اختصاص " +"داده شده باشد." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"گروه‌هایی که این کاربر به آنها تعلق دارد. کاربر تمام اجازه‌های مرتبط با این " +"گروه‌ها را دریافت خواهد کرد." + +msgid "user permissions" +msgstr "اجازه‌های کاربر" + +msgid "Specific permissions for this user." +msgstr "اجازه‌های خاص این کاربر." + +msgid "username" +msgstr "نام کاربری" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "الزامی. 150 کاراکتر یا کمتر. فقط شامل حروف، اعداد، و علامات @/./+/-/_" + +msgid "A user with that username already exists." +msgstr "کاربری با آن نام کاربری وجود دارد." + +msgid "first name" +msgstr "نام" + +msgid "last name" +msgstr "نام خانوادگی" + +msgid "email address" +msgstr "آدرس ایمیل" + +msgid "staff status" +msgstr "وضعیت کارمندی" + +msgid "Designates whether the user can log into this admin site." +msgstr "نشان می‌دهد که آیا این کاربر می‌تواند وارد این وبگاه مدیریت شود یا خیر." + +msgid "active" +msgstr "فعال" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"نشان می‌دهد که آیا این کاربر اجازهٔ فعالیت دارد یا خیر. به جای حذف کاربر این " +"تیک را بردارید." + +msgid "date joined" +msgstr "تاریخ پیوستن" + +msgid "user" +msgstr "کاربر" + +msgid "users" +msgstr "کاربرها" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"این رمز عبور خیلی کوتاه است. رمز عبور می‌بایست حداقل از %(min_length)d حرف " +"تشکیل شده باشد." +msgstr[1] "" +"این رمز عبور خیلی کوتاه است. رمز عبور می‌بایست حداقل از %(min_length)d حرف " +"تشکیل شده باشد." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "رمز عبور شما می‌بایست حداقل از %(min_length)d حرف تشکیل شده باشد." +msgstr[1] "رمز عبور شما می‌بایست حداقل از %(min_length)d حرف تشکیل شده باشد." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "این رمز عبور بسیار شبیه %(verbose_name)s می‌باشد." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "گذرواژه شما نمی‌تواند شبیه سایر اطلاعات شخصی شما باشد." + +msgid "This password is too common." +msgstr "این رمز عبور بسیار رایج است." + +msgid "Your password can’t be a commonly used password." +msgstr "گذرواژه شما نمی تواند یک گذرواژه معمول باشد." + +msgid "This password is entirely numeric." +msgstr "رمز شما کلا عدد است" + +msgid "Your password can’t be entirely numeric." +msgstr "گذرواژه شما نمی تواند کلا عدد باشد" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "بازیابی گذرواژه در %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"یک نام کاربری معتبر وارد کنید. این مقدار میتواند فقط شامل حروف الفبای " +"انگلیسی، اعداد، و علامات @/./+/-/_ باشد." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"یک نام کاربری معتبر وارد کنید. این مقدار میتواند فقط شامل حروف، اعداد، و " +"علامات @/./+/-/_ باشد." + +msgid "Logged out" +msgstr "خارج شدید" + +msgid "Password reset" +msgstr "ایجاد گذرواژهٔ جدید" + +msgid "Password reset sent" +msgstr "تقاضای ریست رمز فرستاده شد" + +msgid "Enter new password" +msgstr "ورود گذرواژهٔ جدید" + +msgid "Password reset unsuccessful" +msgstr "گذرواژهٔ جدید ایجاد نشد." + +msgid "Password reset complete" +msgstr "گذرواژهٔ جدید ایجاد شد" + +msgid "Password change" +msgstr "تغییر گذرواژه" + +msgid "Password change successful" +msgstr "گذرواژه تغییر یافت." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/fi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/fi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..469ab20 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/fi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/fi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/fi/LC_MESSAGES/django.po new file mode 100644 index 0000000..a13720b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/fi/LC_MESSAGES/django.po @@ -0,0 +1,309 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Aarni Koskela, 2015,2017-2018,2020-2021 +# Antti Kaihola , 2011 +# Jannis Leidel , 2011 +# Klaus Dahlén , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2021-11-22 15:17+0000\n" +"Last-Translator: Aarni Koskela\n" +"Language-Team: Finnish (http://www.transifex.com/django/django/language/" +"fi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Henkilökohtaiset tiedot" + +msgid "Permissions" +msgstr "Oikeudet" + +msgid "Important dates" +msgstr "Tärkeät päivämäärät" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(name)s perusavaimella %(key)r ei ole olemassa." + +msgid "Password changed successfully." +msgstr "Salasana muutettu onnistuneesti." + +#, python-format +msgid "Change password: %s" +msgstr "Vaihda salasana: %s" + +msgid "Authentication and Authorization" +msgstr "Kirjautuminen ja oikeudet" + +msgid "password" +msgstr "salasana" + +msgid "last login" +msgstr "viimeisin kirjautuminen" + +msgid "No password set." +msgstr "Salasanaa ei ole asetettu." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Tuntematon salasanamuoto tai tuntematon hajakoodausalgoritmi." + +msgid "The two password fields didn’t match." +msgstr "Salasanakentät eivät täsmänneet." + +msgid "Password" +msgstr "Salasana" + +msgid "Password confirmation" +msgstr "Salasanan vahvistaminen" + +msgid "Enter the same password as before, for verification." +msgstr "Syötä sama salasana tarkistuksen vuoksi toistamiseen." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Salasanoja ei tallenneta selkokielisinä, joten tämän käyttäjän salasanaa on " +"mahdoton nähdä, mutta voit vaihtaa salasanan käyttämällä tätä " +"lomaketta." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Ole hyvä ja syötä kelvollinen %(username)s ja salasana. Huomaa että " +"kummassakin kentässä isoilla ja pienillä kirjaimilla saattaa olla merkitystä." + +msgid "This account is inactive." +msgstr "Tämä käyttäjätili ei ole voimassa." + +msgid "Email" +msgstr "Sähköposti" + +msgid "New password" +msgstr "Uusi salasana" + +msgid "New password confirmation" +msgstr "Uusi salasana uudelleen" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Vanha salasana on virheellinen. Yritä uudelleen." + +msgid "Old password" +msgstr "Vanha salasana" + +msgid "Password (again)" +msgstr "Salasana toistamiseen" + +msgid "algorithm" +msgstr "algoritmi" + +msgid "iterations" +msgstr "iteraatioita" + +msgid "salt" +msgstr "suola" + +msgid "hash" +msgstr "tiiviste" + +msgid "variety" +msgstr "variaatio" + +msgid "version" +msgstr "versio" + +msgid "memory cost" +msgstr "muistihinta" + +msgid "time cost" +msgstr "aikahinta" + +msgid "parallelism" +msgstr "rinnakkaisuus" + +msgid "work factor" +msgstr "työmäärä" + +msgid "checksum" +msgstr "tarkistussumma" + +msgid "block size" +msgstr "lohkokoko" + +msgid "name" +msgstr "nimi" + +msgid "content type" +msgstr "sisältötyyppi" + +msgid "codename" +msgstr "tunniste" + +msgid "permission" +msgstr "oikeus" + +msgid "permissions" +msgstr "oikeudet" + +msgid "group" +msgstr "ryhmä" + +msgid "groups" +msgstr "ryhmät" + +msgid "superuser status" +msgstr "pääkäyttäjä" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Antaa käyttäjälle kaikki oikeudet ilman, että niitä täytyy erikseen luetella." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Käyttäjäryhmät joihin tämä käyttäjä kuuluu. Käyttäjä saa käyttöoikeudet " +"kaikista käyttäjäryhmistä, joihin hän kuuluu." + +msgid "user permissions" +msgstr "käyttäjän oikeudet" + +msgid "Specific permissions for this user." +msgstr "Tämän käyttäjän spesifit oikeudet." + +msgid "username" +msgstr "käyttäjätunnus" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Vaaditaan. Enintään 150 merkkiä. Vain kirjaimet, numerot ja @/./+/-/_ ovat " +"sallittuja." + +msgid "A user with that username already exists." +msgstr "Käyttäjätunnus on jo rekisteröity." + +msgid "first name" +msgstr "etunimi" + +msgid "last name" +msgstr "sukunimi" + +msgid "email address" +msgstr "sähköpostiosoite" + +msgid "staff status" +msgstr "ylläpitäjä" + +msgid "Designates whether the user can log into this admin site." +msgstr "Määrittää, pääseekö käyttäjä tähän sivuston ylläpito-osioon." + +msgid "active" +msgstr "voimassa" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Määrää, voiko käyttäjä kirjautua sisään. Tällä voi estää käyttäjätilin " +"käytön poistamatta sitä." + +msgid "date joined" +msgstr "liittynyt" + +msgid "user" +msgstr "käyttäjä" + +msgid "users" +msgstr "käyttäjät" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Tämä salasana on liian lyhyt. Sen tulee sisältää ainakin %(min_length)d " +"merkki." +msgstr[1] "" +"Tämä salasana on liian lyhyt. Sen tulee sisältää ainakin %(min_length)d " +"merkkiä." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Salasanasi tulee sisältää ainakin %(min_length)d merkki." +msgstr[1] "Salasanasi tulee sisältää ainakin %(min_length)d merkkiä." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Salasana on liian lähellä kohdetta %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Salasanasi ei voi olla liian samankaltainen muiden tietojesi kanssa." + +msgid "This password is too common." +msgstr "Tämä salasana on liian yleinen." + +msgid "Your password can’t be a commonly used password." +msgstr "Salasanasi ei voi olla yleisesti käytetty salasana." + +msgid "This password is entirely numeric." +msgstr "Tämä salasana on kokonaan numeerinen." + +msgid "Your password can’t be entirely numeric." +msgstr "Salasanasi ei voi olla kokonaan numeerinen." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Salasanan nollaus sivustolla %(site_name)s " + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"Syötä kelvollinen käyttäjänimi (vain englannin kirjaimet, numerot ja merkit " +"@/./+/-/_)." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Syötä kelvollinen käyttäjänimi (vain kirjaimet, numerot ja merkit @/./+/-/_)." + +msgid "Logged out" +msgstr "Kirjautunut ulos" + +msgid "Password reset" +msgstr "Salasanan nollaus" + +msgid "Password reset sent" +msgstr "Salasanan nollausviesti lähetetty" + +msgid "Enter new password" +msgstr "Syötä uusi salasana" + +msgid "Password reset unsuccessful" +msgstr "Salasanan nollaus ei onnistunut" + +msgid "Password reset complete" +msgstr "Salasanan nollaus valmis" + +msgid "Password change" +msgstr "Salasanan vaihtaminen" + +msgid "Password change successful" +msgstr "Salasanan vaihtaminen onnistui" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/fr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/fr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b69f2c1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/fr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/fr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 0000000..bd652e6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,323 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Claude Paroz , 2013-2019,2021,2023 +# Claude Paroz , 2013 +# Jannis Leidel , 2011 +# mlorant , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-04-25 08:09+0000\n" +"Last-Translator: Claude Paroz , 2013-2019,2021,2023\n" +"Language-Team: French (http://www.transifex.com/django/django/language/fr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Personal info" +msgstr "Informations personnelles" + +msgid "Permissions" +msgstr "Permissions" + +msgid "Important dates" +msgstr "Dates importantes" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "L'objet %(name)s avec la clef primaire %(key)r n’existe pas." + +msgid "Password changed successfully." +msgstr "Mot de passe modifié avec succès" + +#, python-format +msgid "Change password: %s" +msgstr "Modifier le mot de passe : %s" + +msgid "Authentication and Authorization" +msgstr "Authentification et autorisation" + +msgid "password" +msgstr "mot de passe" + +msgid "last login" +msgstr "dernière connexion" + +msgid "No password set." +msgstr "Aucun mot de passe défini." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" +"Format de mot de passe non valide ou algorithme de hachage non reconnu." + +msgid "The two password fields didn’t match." +msgstr "Les deux mots de passe ne correspondent pas." + +msgid "Password" +msgstr "Mot de passe" + +msgid "Password confirmation" +msgstr "Confirmation du mot de passe" + +msgid "Enter the same password as before, for verification." +msgstr "Saisissez le même mot de passe que précédemment, pour vérification." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Les mots de passe ne sont pas enregistrés en clair, ce qui ne permet pas " +"d’afficher le mot de passe de cet utilisateur, mais il est possible de le " +"changer en utilisant ce formulaire. " + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Saisissez un %(username)s et un mot de passe valides. Remarquez que chacun " +"de ces champs est sensible à la casse (différenciation des majuscules/" +"minuscules)." + +msgid "This account is inactive." +msgstr "Ce compte est inactif." + +msgid "Email" +msgstr "Courriel" + +msgid "New password" +msgstr "Nouveau mot de passe" + +msgid "New password confirmation" +msgstr "Confirmation du nouveau mot de passe" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Votre ancien mot de passe est incorrect. Veuillez le rectifier." + +msgid "Old password" +msgstr "Ancien mot de passe" + +msgid "Password (again)" +msgstr "Mot de passe (à nouveau)" + +msgid "algorithm" +msgstr "algorithme" + +msgid "iterations" +msgstr "itérations" + +msgid "salt" +msgstr "salage" + +msgid "hash" +msgstr "empreinte" + +msgid "variety" +msgstr "variété" + +msgid "version" +msgstr "version" + +msgid "memory cost" +msgstr "coût mémoire" + +msgid "time cost" +msgstr "coût temps" + +msgid "parallelism" +msgstr "parallélisme" + +msgid "work factor" +msgstr "facteur travail" + +msgid "checksum" +msgstr "somme de contrôle" + +msgid "block size" +msgstr "taille de bloc" + +msgid "name" +msgstr "nom" + +msgid "content type" +msgstr "type de contenu" + +msgid "codename" +msgstr "nom de code" + +msgid "permission" +msgstr "permission" + +msgid "permissions" +msgstr "permissions" + +msgid "group" +msgstr "groupe" + +msgid "groups" +msgstr "groupes" + +msgid "superuser status" +msgstr "statut super-utilisateur" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Précise que l’utilisateur possède toutes les permissions sans les assigner " +"explicitement." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Les groupes dont fait partie cet utilisateur. Celui-ci obtient tous les " +"droits de tous les groupes auxquels il appartient." + +msgid "user permissions" +msgstr "permissions de l’utilisateur" + +msgid "Specific permissions for this user." +msgstr "Permissions spécifiques à cet utilisateur." + +msgid "username" +msgstr "nom d’utilisateur" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Requis. 150 caractères maximum. Uniquement des lettres, nombres et les " +"caractères « @ », « . », « + », « - » et « _ »." + +msgid "A user with that username already exists." +msgstr "Un utilisateur avec ce nom existe déjà." + +msgid "first name" +msgstr "prénom" + +msgid "last name" +msgstr "nom" + +msgid "email address" +msgstr "adresse électronique" + +msgid "staff status" +msgstr "statut équipe" + +msgid "Designates whether the user can log into this admin site." +msgstr "Précise si l’utilisateur peut se connecter à ce site d'administration." + +msgid "active" +msgstr "actif" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Précise si l’utilisateur doit être considéré comme actif. Décochez ceci " +"plutôt que de supprimer le compte." + +msgid "date joined" +msgstr "date d’inscription" + +msgid "user" +msgstr "utilisateur" + +msgid "users" +msgstr "utilisateurs" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Ce mot de passe est trop court. Il doit contenir au minimum %(min_length)d " +"caractère." +msgstr[1] "" +"Ce mot de passe est trop court. Il doit contenir au minimum %(min_length)d " +"caractères." +msgstr[2] "" +"Ce mot de passe est trop court. Il doit contenir au minimum %(min_length)d " +"caractères." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +"Votre mot de passe doit contenir au minimum %(min_length)d caractère." +msgstr[1] "" +"Votre mot de passe doit contenir au minimum %(min_length)d caractères." +msgstr[2] "" +"Votre mot de passe doit contenir au minimum %(min_length)d caractères." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Le mot de passe est trop semblable au champ « %(verbose_name)s »." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" +"Votre mot de passe ne peut pas trop ressembler à vos autres informations " +"personnelles." + +msgid "This password is too common." +msgstr "Ce mot de passe est trop courant." + +msgid "Your password can’t be a commonly used password." +msgstr "" +"Votre mot de passe ne peut pas être un mot de passe couramment utilisé." + +msgid "This password is entirely numeric." +msgstr "Ce mot de passe est entièrement numérique." + +msgid "Your password can’t be entirely numeric." +msgstr "Votre mot de passe ne peut pas être entièrement numérique." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Réinitialisation du mot de passe sur %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Saisissez un nom d’utilisateur valide. Il ne peut contenir que des lettres " +"non accentuées (de a à z ou de A à Z), des nombres ou les caractères « @ », " +"« . », « + », « - » et « _ »." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Saisissez un nom d’utilisateur valide. Il ne peut contenir que des lettres, " +"des nombres ou les caractères « @ », « . », « + », « - » et « _ »." + +msgid "Logged out" +msgstr "Déconnecté" + +msgid "Password reset" +msgstr "Réinitialisation du mot de passe" + +msgid "Password reset sent" +msgstr "Message de réinitialisation du mot de passe envoyé" + +msgid "Enter new password" +msgstr "Saisissez un nouveau mot de passe" + +msgid "Password reset unsuccessful" +msgstr "Échec lors de la mise à jour du mot de passe" + +msgid "Password reset complete" +msgstr "Mise à jour du mot de passe terminée" + +msgid "Password change" +msgstr "Modification du mot de passe" + +msgid "Password change successful" +msgstr "Mot de passe modifié avec succès" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/fy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/fy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2331e0e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/fy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/fy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/fy/LC_MESSAGES/django.po new file mode 100644 index 0000000..576ed79 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/fy/LC_MESSAGES/django.po @@ -0,0 +1,226 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-03-18 09:16+0100\n" +"PO-Revision-Date: 2015-03-18 10:30+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Western Frisian (http://www.transifex.com/projects/p/django/" +"language/fy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fy\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "" + +msgid "Permissions" +msgstr "" + +msgid "Important dates" +msgstr "" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "" + +#, python-format +msgid "Change password: %s" +msgstr "" + +msgid "Authentication and Authorization" +msgstr "" + +msgid "No password set." +msgstr "" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" + +msgid "The two password fields didn't match." +msgstr "" + +msgid "Password" +msgstr "" + +msgid "Password confirmation" +msgstr "" + +msgid "Enter the same password as above, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this " +"form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" + +msgid "This account is inactive." +msgstr "" + +msgid "Email" +msgstr "" + +msgid "New password" +msgstr "" + +msgid "New password confirmation" +msgstr "" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" + +msgid "Old password" +msgstr "" + +msgid "Password (again)" +msgstr "" + +msgid "algorithm" +msgstr "" + +msgid "iterations" +msgstr "" + +msgid "salt" +msgstr "" + +msgid "hash" +msgstr "" + +msgid "work factor" +msgstr "" + +msgid "checksum" +msgstr "" + +msgid "name" +msgstr "" + +msgid "codename" +msgstr "" + +msgid "permission" +msgstr "" + +msgid "permissions" +msgstr "" + +msgid "group" +msgstr "" + +msgid "groups" +msgstr "" + +msgid "password" +msgstr "" + +msgid "last login" +msgstr "" + +msgid "superuser status" +msgstr "" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "" + +msgid "Specific permissions for this user." +msgstr "" + +msgid "username" +msgstr "" + +msgid "Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers and @/./" +"+/-/_ characters." +msgstr "" + +msgid "A user with that username already exists." +msgstr "" + +msgid "first name" +msgstr "" + +msgid "last name" +msgstr "" + +msgid "email address" +msgstr "" + +msgid "staff status" +msgstr "" + +msgid "Designates whether the user can log into this admin site." +msgstr "" + +msgid "active" +msgstr "" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" + +msgid "date joined" +msgstr "" + +msgid "user" +msgstr "" + +msgid "users" +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "" + +msgid "Logged out" +msgstr "" + +msgid "Password reset" +msgstr "" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "" + +msgid "Password reset unsuccessful" +msgstr "" + +msgid "Password reset complete" +msgstr "" + +msgid "Password change" +msgstr "" + +msgid "Password change successful" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ga/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ga/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3221b18 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ga/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ga/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ga/LC_MESSAGES/django.po new file mode 100644 index 0000000..a91375a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ga/LC_MESSAGES/django.po @@ -0,0 +1,298 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Michael Thornhill , 2012,2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-09-24 14:24+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Irish (http://www.transifex.com/django/django/language/ga/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ga\n" +"Plural-Forms: nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : " +"4);\n" + +msgid "Personal info" +msgstr "Eolas pearsantach" + +msgid "Permissions" +msgstr "Ceada" + +msgid "Important dates" +msgstr "Dáta tábhactach" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "Focal faire aithraithe rathúil" + +#, python-format +msgid "Change password: %s" +msgstr "Athraigh focal faire: %s" + +msgid "Authentication and Authorization" +msgstr "" + +msgid "password" +msgstr "focal faire" + +msgid "last login" +msgstr "logáil deirneach" + +msgid "No password set." +msgstr "" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" + +msgid "The two password fields didn't match." +msgstr "Níl an dá focla faire comhoiriúnigh" + +msgid "Password" +msgstr "Focal faire" + +msgid "Password confirmation" +msgstr "Focal faire deimhniú" + +msgid "Enter the same password as before, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" + +msgid "This account is inactive." +msgstr "Tá an cuntas seo neamhghníomhach." + +msgid "Email" +msgstr "Ríomhphost" + +msgid "New password" +msgstr "Focal faire nua" + +msgid "New password confirmation" +msgstr "Deimnhiú focal faire nua" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" +"Cuireadh do sean-focal faire isteach go mícheart. Iontráil isteach é arís." + +msgid "Old password" +msgstr "Sean-focal faire " + +msgid "Password (again)" +msgstr "Focal faire (arís)" + +msgid "algorithm" +msgstr "algartam" + +msgid "iterations" +msgstr "atriallta" + +msgid "salt" +msgstr "salann" + +msgid "hash" +msgstr "haiseáil" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "fachtóir oibre" + +msgid "checksum" +msgstr "suim sheiceála" + +msgid "name" +msgstr "ainm" + +msgid "content type" +msgstr "" + +msgid "codename" +msgstr "Ainm cód" + +msgid "permission" +msgstr "cead" + +msgid "permissions" +msgstr "ceada" + +msgid "group" +msgstr "grúpa" + +msgid "groups" +msgstr "grúpa" + +msgid "superuser status" +msgstr "stádas forúsáideoir" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Sainíonn go bhfuil gach ceada ag an úsáideoir seo gan iad a cur le go " +"díreach." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "ceada úsáideoira" + +msgid "Specific permissions for this user." +msgstr "" + +msgid "username" +msgstr "Ainm úsáideoir" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "In ann do úsáideoir leis an ainm úsáideora." + +msgid "first name" +msgstr "ainm baiste" + +msgid "last name" +msgstr "sloinne" + +msgid "email address" +msgstr "seoladh r-phoist" + +msgid "staff status" +msgstr "stádas foirne" + +msgid "Designates whether the user can log into this admin site." +msgstr "" +"Sainigh an bhfuil cead ag an úsáideoir logáil isteach go dtí an suíomh " +"riaracháin seo." + +msgid "active" +msgstr "gníomhach" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Sainíonn an bhfuil an úsáideoir gníomhach. Míroghnaigh seo in aineonn de " +"scriseadh cuntasí." + +msgid "date joined" +msgstr "Dáta teacht isteach" + +msgid "user" +msgstr "úsáideoir" + +msgid "users" +msgstr "úsáideora" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "" + +msgid "Your password can't be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "" + +msgid "Your password can't be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "" + +msgid "Your password can't be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Athshocraigh focal faire ar %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "Logáilte amach" + +msgid "Password reset" +msgstr "Pasfhocal athshocrú" + +msgid "Password reset sent" +msgstr "Pasfhocal athshocrú sheoladh" + +msgid "Enter new password" +msgstr "" + +msgid "Password reset unsuccessful" +msgstr "" + +msgid "Password reset complete" +msgstr "" + +msgid "Password change" +msgstr "" + +msgid "Password change successful" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/gd/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/gd/LC_MESSAGES/django.mo new file mode 100644 index 0000000..edc9d7b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/gd/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/gd/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/gd/LC_MESSAGES/django.po new file mode 100644 index 0000000..8883456 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/gd/LC_MESSAGES/django.po @@ -0,0 +1,337 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# GunChleoc, 2015-2017,2021 +# GunChleoc, 2015 +# GunChleoc, 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2021-10-27 12:55+0000\n" +"Last-Translator: GunChleoc\n" +"Language-Team: Gaelic, Scottish (http://www.transifex.com/django/django/" +"language/gd/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: gd\n" +"Plural-Forms: nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : " +"(n > 2 && n < 20) ? 2 : 3;\n" + +msgid "Personal info" +msgstr "Fiosrachadh pearsanta" + +msgid "Permissions" +msgstr "Ceadan" + +msgid "Important dates" +msgstr "Cinn-là chudromach" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "Chan eil oibseact %(name)s air a bheil prìomh-iuchair %(key)r ann." + +msgid "Password changed successfully." +msgstr "Chaidh am facal-faire atharrachadh gu soirbheachail." + +#, python-format +msgid "Change password: %s" +msgstr "Atharraich am facal-faire: %s" + +msgid "Authentication and Authorization" +msgstr "Dearbhadh is ùghdarrachadh" + +msgid "password" +msgstr "facal-faire" + +msgid "last login" +msgstr "an clàradh a-steach mu dheireadh" + +msgid "No password set." +msgstr "Cha deach facal-faire a shuidheachadh." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" +"Tha fòrmat mì-dhligheach air an fhacal-fhaire no chan aithne dhuinn algairim " +"a’ hais." + +msgid "The two password fields didn’t match." +msgstr "Cha robh an dà fhacal-faire co-ionnann." + +msgid "Password" +msgstr "Facal-faire" + +msgid "Password confirmation" +msgstr "Dearbhadh an fhacail-fhaire" + +msgid "Enter the same password as before, for verification." +msgstr "Cuir an t-aon fhacal-faire a-steach a-rithist gus a dhearbhadh." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Cha dèid faclan-faire amh a shàbhaladh ’s mar sin chan eil dòigh ann gus " +"facal-faire a’ chleachdaiche seo a shealltainn. ’S urrainn dhut am facal-" +"faire atharrachadh co-dhiù leis an fhoirm seo." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Cuir a-steach %(username)s agus facal-faire ceart. Thoir an aire gum bi aire " +"do litrichean mòra ’s beaga air an dà raon, ma dh’fhaoidte." + +msgid "This account is inactive." +msgstr "Chan eil an cunntas seo gnìomhach." + +msgid "Email" +msgstr "Post-d" + +msgid "New password" +msgstr "Facal-faire ùr" + +msgid "New password confirmation" +msgstr "Dearbhadh an fhacail-fhaire ùir" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" +"Cha do chuir thu an seann fhacal-faire a-steach mar bu chòir. Cuir a-steach " +"e a-rithist." + +msgid "Old password" +msgstr "An seann fhacal-faire" + +msgid "Password (again)" +msgstr "Facal-faire (a-rithist)" + +msgid "algorithm" +msgstr "algairim" + +msgid "iterations" +msgstr "ath-thriallan" + +msgid "salt" +msgstr "salann" + +msgid "hash" +msgstr "hais" + +msgid "variety" +msgstr "eug-samhail" + +msgid "version" +msgstr "tionndadh" + +msgid "memory cost" +msgstr "cosgais cuimhne" + +msgid "time cost" +msgstr "cosgais ùine" + +msgid "parallelism" +msgstr "co-shìneadh" + +msgid "work factor" +msgstr "factar obrachaidh" + +msgid "checksum" +msgstr "àireamh dhearbhaidh" + +msgid "block size" +msgstr "meud nam blocaichean" + +msgid "name" +msgstr "ainm" + +msgid "content type" +msgstr "seòrsa susbainte" + +msgid "codename" +msgstr "ainm-còd" + +msgid "permission" +msgstr "cead" + +msgid "permissions" +msgstr "ceadan" + +msgid "group" +msgstr "buidheann" + +msgid "groups" +msgstr "buidhnean" + +msgid "superuser status" +msgstr "staid superuser" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Iomruinidh seo gu bheil a h-uile aig a’ chleachdaiche seo gun a bhith ’gan " +"iomruineadh fa leth." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Am buidheann ris a bhuineas an cleachdaiche seo. Gheibh cleachdaiche a h-" +"uile cead a chaidh a thoirt dha ghin dhe na buidhnean aige." + +msgid "user permissions" +msgstr "ceadan a’ chleachdaiche" + +msgid "Specific permissions for this user." +msgstr "Ceadan sònraichte airson a’ chleachdaiche seo." + +msgid "username" +msgstr "ainm-cleachdaiche" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Riatanach. 150 caractar air a char as motha. Litrichean, àireamhan agus @/./" +"+/-/_ a-mhàin." + +msgid "A user with that username already exists." +msgstr "Tha cleachdaiche air a bheil an t-ainm-cleachdaiche seo ann mar-tha." + +msgid "first name" +msgstr "ainm" + +msgid "last name" +msgstr "sloinneadh" + +msgid "email address" +msgstr "seòladh puist-d" + +msgid "staff status" +msgstr "inbhe luchd-obrach" + +msgid "Designates whether the user can log into this admin site." +msgstr "" +"Iomruinidh seo an urrainn dhan chleachdaiche seo clàradh a-steach gu làrach " +"nan rianairean gus nach urrainn." + +msgid "active" +msgstr "staid ghnìomhach" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Iomruinidh seo an dèid dèiligeadh ris a’ cleachdaiche seo mar fhear " +"gnìomhach gus nach dèid. Neo-thagh seo seach an cunntas a sguabadh às." + +msgid "date joined" +msgstr "fhuair e ballrachd" + +msgid "user" +msgstr "cleachdaiche" + +msgid "users" +msgstr "cleachdaichean" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Tha am facal-faire seo ro ghoirid. Feumaidh %(min_length)d charactar a bhith " +"ann air a char as lugha." +msgstr[1] "" +"Tha am facal-faire seo ro ghoirid. Feumaidh %(min_length)d charactar a bhith " +"ann air a char as lugha." +msgstr[2] "" +"Tha am facal-faire seo ro ghoirid. Feumaidh %(min_length)d caractaran a " +"bhith ann air a char as lugha." +msgstr[3] "" +"Tha am facal-faire seo ro ghoirid. Feumaidh %(min_length)d caractar a bhith " +"ann air a char as lugha." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +"Feumaidh %(min_length)d charactar a bhith san fhacal-fhaire agad air a char " +"as lugha." +msgstr[1] "" +"Feumaidh %(min_length)d charactar a bhith san fhacal-fhaire agad air a char " +"as lugha." +msgstr[2] "" +"Feumaidh %(min_length)d caractaran a bhith san fhacal-fhaire agad air a char " +"as lugha." +msgstr[3] "" +"Feumaidh %(min_length)d caractar a bhith san fhacal-fhaire agad air a char " +"as lugha." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Tha am facal-faire agad ro choltach ri %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" +"Chan fhaod am facal-faire agad a bhith ro choltach ris an fhiosrachadh " +"phearsanta eile agad." + +msgid "This password is too common." +msgstr "Tha am facal-faire seo ro chumanta." + +msgid "Your password can’t be a commonly used password." +msgstr "" +"Chan fhaod thu facal-faire a chleachdadh a chleachd mòran daoine mar-thà." + +msgid "This password is entirely numeric." +msgstr "Chan eil ach àireamhan san fhacal-fhaire seo." + +msgid "Your password can’t be entirely numeric." +msgstr "" +"Feumaidh caractaran a bhith san fhacal-fhaire agad nach eil ’nan àireamhan." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Ath-shuidheachadh an fhacail-fhaire air %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"Cuir a-steach ainm-cleachdaiche dligheach. Chan fhaod ach litrichean gun " +"sràcan, àireamhan is caractaran @/./+/-/_ a bhith ’na bhroinn." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Cuir a-steach ainm-cleachdaiche dligheach. Chan fhaod ach litrichean, " +"àireamhan is caractaran @/./+/-/_ a bhith ’na bhroinn." + +msgid "Logged out" +msgstr "Air a clàradh a-mach" + +msgid "Password reset" +msgstr "Ath-shuidheachadh an fhacail-fhaire" + +msgid "Password reset sent" +msgstr "Chaidh ath-shuidheachadh an fhacail-fhaire a chur" + +msgid "Enter new password" +msgstr "Cuir a-steach facal-faire ùr" + +msgid "Password reset unsuccessful" +msgstr "Cha deach le ath-shuidheachadh an facail-faire" + +msgid "Password reset complete" +msgstr "Tha ath-shuidheachadh an fhacail-fhaire deiseil" + +msgid "Password change" +msgstr "Atharrachadh an facail-fhaire" + +msgid "Password change successful" +msgstr "Chaidh am facal-faire atharrachadh gu soirbheachail" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/gl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/gl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4387835 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/gl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/gl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/gl/LC_MESSAGES/django.po new file mode 100644 index 0000000..3fa92e7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/gl/LC_MESSAGES/django.po @@ -0,0 +1,314 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# fasouto , 2011 +# fonso , 2011,2013 +# fasouto , 2019 +# Jannis Leidel , 2011 +# Leandro Regueiro , 2011,2013 +# X Bello , 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-04-25 08:09+0000\n" +"Last-Translator: X Bello , 2023\n" +"Language-Team: Galician (http://www.transifex.com/django/django/language/" +"gl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: gl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Información persoal" + +msgid "Permissions" +msgstr "Permisos" + +msgid "Important dates" +msgstr "Datas importantes" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "O obxeto %(name)s ca clave primaria %(key)r non existe." + +msgid "Password changed successfully." +msgstr "O contrasinal cambiouse correctamente." + +#, python-format +msgid "Change password: %s" +msgstr "Cambiar o contrasinal: %s" + +msgid "Authentication and Authorization" +msgstr "Autenticación e Autorización" + +msgid "password" +msgstr "contrasinal" + +msgid "last login" +msgstr "última sesión" + +msgid "No password set." +msgstr "Non se configurou ningún contrasinal." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Formato de contrasinal non válido ou algoritmo de hash descoñecido." + +msgid "The two password fields didn’t match." +msgstr "Os dous campos de contrasinal non coinciden." + +msgid "Password" +msgstr "Contrasinal" + +msgid "Password confirmation" +msgstr "Confirmación do contrasinal" + +msgid "Enter the same password as before, for verification." +msgstr "Introduza o mesmo contrasinal que antes, para verificalo." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Non se gardan os contrasinais sen cifrar, de maneira que non se pode ver o " +"contrasinal deste usuario, pero pode modificar o contrasinal mediante este formulario." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Por favor, insira un %(username)s e contrasinal correctos. Teña en conta que " +"ambos os dous campos poden distinguir maiúsculas e minúsculas." + +msgid "This account is inactive." +msgstr "Esta conta está inactiva." + +msgid "Email" +msgstr "Correo electrónico" + +msgid "New password" +msgstr "Novo contrasinal" + +msgid "New password confirmation" +msgstr "Confirmación do novo contrasinal" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Inseriu incorrectamente o seu contrasinal actual. Insírao de novo." + +msgid "Old password" +msgstr "Contrasinal antigo" + +msgid "Password (again)" +msgstr "Contrasinal (outra vez)" + +msgid "algorithm" +msgstr "algoritmo" + +msgid "iterations" +msgstr "iteracións" + +msgid "salt" +msgstr "sal" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "variedade" + +msgid "version" +msgstr "versión" + +msgid "memory cost" +msgstr "custo de memoria" + +msgid "time cost" +msgstr "coste temporal" + +msgid "parallelism" +msgstr "paralelismo" + +msgid "work factor" +msgstr "factor de traballo" + +msgid "checksum" +msgstr "suma de verificación" + +msgid "block size" +msgstr "tamaño de bloque" + +msgid "name" +msgstr "nome" + +msgid "content type" +msgstr "tipo de contido" + +msgid "codename" +msgstr "código" + +msgid "permission" +msgstr "permiso" + +msgid "permissions" +msgstr "permisos" + +msgid "group" +msgstr "grupo" + +msgid "groups" +msgstr "grupos" + +msgid "superuser status" +msgstr "estatus de superusuario" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Indica que este usuario ten todos os permisos sen asignarllos explicitamente." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Os grupos ós que pertence este usuario. Un usuario terá todos os permisos " +"outorgados a cada un dos seus grupos." + +msgid "user permissions" +msgstr "permisos de usuario" + +msgid "Specific permissions for this user." +msgstr "Permisos específicos para este usuario" + +msgid "username" +msgstr "nome de usuario" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "Requerido. 150 caracteres ou menos. So letras, díxitos e @/./+/-/_." + +msgid "A user with that username already exists." +msgstr "Xa existe un usuario con ese nome de usuario." + +msgid "first name" +msgstr "nome" + +msgid "last name" +msgstr "apelidos" + +msgid "email address" +msgstr "enderezo de correo electrónico" + +msgid "staff status" +msgstr "membro do persoal" + +msgid "Designates whether the user can log into this admin site." +msgstr "Indica se o usuario pode acceder a este sitio de administración." + +msgid "active" +msgstr "activo" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Determina se este usuario se debe considerar activo. Deseleccione isto en " +"vez de borrar contas de usuario." + +msgid "date joined" +msgstr "data de rexistro" + +msgid "user" +msgstr "usuario" + +msgid "users" +msgstr "usuarios" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Este contrasinal é moi curto. Ten que conter polo menos %(min_length)d " +"caracter." +msgstr[1] "" +"Este contrasinal é moi curto. Ten que conter polo menos %(min_length)d " +"caracteres." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +"O seu contrasinal ten que conter polo menos %(min_length)d caracter." +msgstr[1] "" +"O seu contrasinal ten que conter polo menos %(min_length)d caracteres." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "O contrasinal parécese demasiado a %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" +"O seu contrasinal non pode ser tan semellante ó resto da información persal." + +msgid "This password is too common." +msgstr "Este contrasinal é moi común." + +msgid "Your password can’t be a commonly used password." +msgstr "O seu contrasinal non pode ser un contrasinal de uso habitual." + +msgid "This password is entirely numeric." +msgstr "Este constrasinal só ten números." + +msgid "Your password can’t be entirely numeric." +msgstr "O seu contrasinal non pode ser únicamente numérico." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Cambio de contrasinal en %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Introduza un nome de usuario válido. Este valor so pode conter letras sen " +"acentos minúsculas do a ó z e maíusculas do A ó Z, números e os caracteres " +"@/./+/-/_." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Introduza un nome de usuario válido. Este valor pode conter so letras, " +"números e os caracteres @/./+/-/_." + +msgid "Logged out" +msgstr "Rematou a sesión" + +msgid "Password reset" +msgstr "Recuperar o contrasinal" + +msgid "Password reset sent" +msgstr "Enviada recuperación de contrasinal" + +msgid "Enter new password" +msgstr "Introduza novo contrasinal" + +msgid "Password reset unsuccessful" +msgstr "Fallóu a recuperación do contrasinal" + +msgid "Password reset complete" +msgstr "Completouse a recuperación do contrasinal" + +msgid "Password change" +msgstr "Cambio de contrasinal" + +msgid "Password change successful" +msgstr "O contrasinal cambiouse correctamente" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/he/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/he/LC_MESSAGES/django.mo new file mode 100644 index 0000000..cf03e16 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/he/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/he/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/he/LC_MESSAGES/django.po new file mode 100644 index 0000000..a76646a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/he/LC_MESSAGES/django.po @@ -0,0 +1,307 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# 534b44a19bf18d20b71ecc4eb77c572f_db336e9 , 2011-2012 +# Jannis Leidel , 2011 +# Meir Kriheli , 2012-2015,2017,2019,2023 +# אורי רודברג , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-12-04 08:09+0000\n" +"Last-Translator: Meir Kriheli , " +"2012-2015,2017,2019,2023\n" +"Language-Team: Hebrew (http://app.transifex.com/django/django/language/he/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: he\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % " +"1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;\n" + +msgid "Personal info" +msgstr "מידע אישי" + +msgid "Permissions" +msgstr "הרשאות" + +msgid "Important dates" +msgstr "תאריכים חשובים" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "הפריט %(name)s עם המפתח הראשי %(key)r אינו קיים." + +msgid "Password changed successfully." +msgstr "הסיסמה שונתה בהצלחה." + +#, python-format +msgid "Change password: %s" +msgstr "שינוי סיסמה: %s" + +msgid "Authentication and Authorization" +msgstr "אימות והרשאות" + +msgid "password" +msgstr "סיסמה" + +msgid "last login" +msgstr "כניסה אחרונה" + +msgid "No password set." +msgstr "לא נקבעה סיסמה." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "תחביר סיסמה בלתי-חוקי או אלגוריתם גיבוב לא ידוע." + +msgid "The two password fields didn’t match." +msgstr "שני שדות הסיסמה אינם זהים." + +msgid "Password" +msgstr "סיסמה" + +msgid "Password confirmation" +msgstr "אימות סיסמה" + +msgid "Enter the same password as before, for verification." +msgstr "יש להזין את אותה סיסמה כמו קודם, לאימות." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"הסיסמאות אינן נשמרות באופן חשוף, כך שאין דרך לראות את סיסמת המשתמש, אבל ניתן " +"לשנות את הסיסמה בעזרת טופס זה." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"נא להזין %(username)s וסיסמה נכונים. נא לשים לב כי שני השדות רגישים לאותיות " +"גדולות/קטנות." + +msgid "This account is inactive." +msgstr "חשבון זה אינו פעיל." + +msgid "Email" +msgstr "דוא\"ל" + +msgid "New password" +msgstr "סיסמה חדשה" + +msgid "New password confirmation" +msgstr "אימות סיסמה חדשה" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "סיסמתך הישנה הוזנה בצורה שגויה. נא להזינה שוב." + +msgid "Old password" +msgstr "סיסמה ישנה" + +msgid "Password (again)" +msgstr "סיסמה (שוב)" + +msgid "algorithm" +msgstr "אלגוריתם" + +msgid "iterations" +msgstr "חזרות" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "גיבוב" + +msgid "variety" +msgstr "מגוון" + +msgid "version" +msgstr "גרסה" + +msgid "memory cost" +msgstr "עלות זכרון" + +msgid "time cost" +msgstr "עלות זמן" + +msgid "parallelism" +msgstr "מקבילות" + +msgid "work factor" +msgstr "work factor" + +msgid "checksum" +msgstr "סיכום ביקורת" + +msgid "block size" +msgstr "גודל בלוק" + +msgid "name" +msgstr "שם" + +msgid "content type" +msgstr "סוג תוכן" + +msgid "codename" +msgstr "שם קוד" + +msgid "permission" +msgstr "הרשאה" + +msgid "permissions" +msgstr "הרשאות" + +msgid "group" +msgstr "קבוצה" + +msgid "groups" +msgstr "קבוצות" + +msgid "superuser status" +msgstr "סטטוס משתמש על" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "מציין שלמשתמש זה יש את כל ההרשאות ללא הצורך המפורש בהענקתן." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"הקבוצות שמשתמש זה שייך אליהן. משתמש יקבל את כל ההרשאות המוקצות לכל אחת " +"מהקבוצות שלו/שלה." + +msgid "user permissions" +msgstr "הרשאות משתמש" + +msgid "Specific permissions for this user." +msgstr "הרשאות ספציפיות למשתמש זה." + +msgid "username" +msgstr "שם משתמש" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "שדה חובה. 150 תווים או פחות. אותיות, ספרות ו-@/./+/-/_ בלבד." + +msgid "A user with that username already exists." +msgstr "משתמש עם שם משתמש זה קיים כבר" + +msgid "first name" +msgstr "שם פרטי" + +msgid "last name" +msgstr "שם משפחה" + +msgid "email address" +msgstr "כתובת דוא\"ל" + +msgid "staff status" +msgstr "סטטוס איש צוות" + +msgid "Designates whether the user can log into this admin site." +msgstr "מציין האם המשתמש יכול להתחבר לאתר הניהול." + +msgid "active" +msgstr "פעיל" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"מציין האם יש להתייחס למשתמש כפעיל. יש לבטל בחירה זו במקום למחוק חשבונות " +"משתמשים." + +msgid "date joined" +msgstr "תאריך הצטרפות" + +msgid "user" +msgstr "משתמש" + +msgid "users" +msgstr "משתמשים" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "סיסמה זו קצרה מדי. היא חייבת להכיל לפחות תו %(min_length)d." +msgstr[1] "סיסמה זו קצרה מדי. היא חייבת להכיל לפחות %(min_length)d תווים." +msgstr[2] "סיסמה זו קצרה מדי. היא חייבת להכיל לפחות %(min_length)d תווים." +msgstr[3] "סיסמה זו קצרה מדי. היא חייבת להכיל לפחות %(min_length)d תווים." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "הסיסמה שלך חייבת להכיל לפחות תו %(min_length)d." +msgstr[1] "הסיסמה שלך חייבת להכיל לפחות %(min_length)d תווים." +msgstr[2] "הסיסמה שלך חייבת להכיל לפחות %(min_length)d תווים." +msgstr[3] "הסיסמה שלך חייבת להכיל לפחות %(min_length)d תווים." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "סיסמה זו דומה מדי ל-%(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "הסיסמה שלך לא יכולה להיות דומה מדי למידע אישי אחר שלך." + +msgid "This password is too common." +msgstr "סיסמה זו נפוצה מדי." + +msgid "Your password can’t be a commonly used password." +msgstr "הסיסמה שלך לא יכולה להיות סיסמה שכיחה." + +msgid "This password is entirely numeric." +msgstr "סיסמה זו מכילה רק ספרות." + +msgid "Your password can’t be entirely numeric." +msgstr "הסיסמה שלך לא יכולה להכיל רק ספרות." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "החלפת הסיסמה ב-%(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"יש להזין שם משתמש חוקי. ערך זה יכול להכיל אותיות אנגליות, ספרות והתווים @/./" +"+/-/_ בלבד." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"יש להזין שם משתמש חוקי. ערך זה יכול להכיל אותיות, ספרות והתווים @/./+/-/_ " +"בלבד." + +msgid "Logged out" +msgstr "יצאת מהמערכת" + +msgid "Password reset" +msgstr "איפוס סיסמה" + +msgid "Password reset sent" +msgstr "איפוס הסיסמה נשלח." + +msgid "Enter new password" +msgstr "הזנת סיסמה חדשה" + +msgid "Password reset unsuccessful" +msgstr "איפוס הסיסמה נכשל" + +msgid "Password reset complete" +msgstr "איפוס הסיסמה הושלם" + +msgid "Password change" +msgstr "שינוי סיסמה" + +msgid "Password change successful" +msgstr "הסיסמה שונתה בהצלחה" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8966d0c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hi/LC_MESSAGES/django.po new file mode 100644 index 0000000..b631985 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hi/LC_MESSAGES/django.po @@ -0,0 +1,290 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# alkuma , 2013 +# Chandan kumar , 2012 +# Jannis Leidel , 2011 +# Sandeep Satavlekar , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-09-24 14:24+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Hindi (http://www.transifex.com/django/django/language/hi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "व्यक्तिगत सूचना" + +msgid "Permissions" +msgstr "अनुमतियाँ" + +msgid "Important dates" +msgstr "महत्त्वपूर्ण तिथियाँ" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "शब्दकूट बदली कामयाब" + +#, python-format +msgid "Change password: %s" +msgstr "शब्दकूट बदलें: %s" + +msgid "Authentication and Authorization" +msgstr "" + +msgid "password" +msgstr "शब्दकूट" + +msgid "last login" +msgstr "पिछला लॉगिन" + +msgid "No password set." +msgstr "कोई कूटशब्द नहीं।" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "अवैध कूटशब्द प्रारूप या अज्ञात द्रुतान्वेषण कलन विधि" + +msgid "The two password fields didn't match." +msgstr "यह दो शब्दकूट क्षेत्रों का मेल नहीं होता " + +msgid "Password" +msgstr "कूटशब्द" + +msgid "Password confirmation" +msgstr "कूटशब्द पुष्टि" + +msgid "Enter the same password as before, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "कृपया सही %(username)s व कूटशब्द भरें। भरते समय लघु और दीर्घ अक्षरों का ध्यान रखें।" + +msgid "This account is inactive." +msgstr "यस खाता सुस्त है" + +msgid "Email" +msgstr "डाक पता" + +msgid "New password" +msgstr "नया शब्दकूट" + +msgid "New password confirmation" +msgstr "नया शब्दकूट पुष्टि" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "आपने पुराना शब्दकूट गलत दर्ज किया है । कृपया फिर से दर्ज करें" + +msgid "Old password" +msgstr "पुराना शब्दकूट" + +msgid "Password (again)" +msgstr "शब्दकूट (दुबारा)" + +msgid "algorithm" +msgstr "अलगोरिथम" + +msgid "iterations" +msgstr "पुनरूक्तियाँ" + +msgid "salt" +msgstr "साल्ट" + +msgid "hash" +msgstr "हैश" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "कार्य फ़ैक्टर" + +msgid "checksum" +msgstr "चेकसम" + +msgid "name" +msgstr "नाम" + +msgid "content type" +msgstr "" + +msgid "codename" +msgstr "कोडनेम" + +msgid "permission" +msgstr "अनुमति" + +msgid "permissions" +msgstr "अनुमतियाँ" + +msgid "group" +msgstr "वर्ग" + +msgid "groups" +msgstr "वर्गों" + +msgid "superuser status" +msgstr "सर्वोच्च प्रयोक्ता स्थिति" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"निर्दिष्ट करता है कि जो इस उपयोगकर्ता के पास सभी अनुमतियाँ उन्हें बिना बताए स्पष्ट रूप से " +"निर्धारित है." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "प्रयोक्ता अनुमतियाँ" + +msgid "Specific permissions for this user." +msgstr "" + +msgid "username" +msgstr "प्रयोक्ता नाम" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "इस नाम के साथ प्रवोक्ता अस्तित्व है" + +msgid "first name" +msgstr "पहला नाम" + +msgid "last name" +msgstr "आखिरी नाम" + +msgid "email address" +msgstr "डाक पता" + +msgid "staff status" +msgstr "कर्मचारी स्थिति" + +msgid "Designates whether the user can log into this admin site." +msgstr "तय करता हैं की उपयोगकर्ता इस साईट प्रशासन में प्रवेश कर सकता हैं या नहीं |" + +msgid "active" +msgstr "सक्रिय" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"निर्दिष्ट करता है कि क्या इस उपयोगकर्ता को सक्रिय माना जाना चाहिए.खातों को हटाने की " +"बजाय इस अचयनित करे." + +msgid "date joined" +msgstr "तिथि भरती" + +msgid "user" +msgstr "उपभोक्ता" + +msgid "users" +msgstr "उपभोक्ताऐं" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "" + +msgid "Your password can't be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "" + +msgid "Your password can't be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "" + +msgid "Your password can't be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "%(site_name)s पर कूटशब्द को पुनःठीक करे" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "लाग्ड आउट " + +msgid "Password reset" +msgstr "" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "" + +msgid "Password reset unsuccessful" +msgstr "" + +msgid "Password reset complete" +msgstr "" + +msgid "Password change" +msgstr "" + +msgid "Password change successful" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..706a16d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hr/LC_MESSAGES/django.po new file mode 100644 index 0000000..f6711db --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hr/LC_MESSAGES/django.po @@ -0,0 +1,306 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bojan Mihelač , 2012 +# Davor Lučić , 2012 +# Jannis Leidel , 2011 +# Mislav Cimperšak , 2013,2015 +# Nino , 2013 +# senko , 2012 +# zmasek , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-09-24 14:24+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Croatian (http://www.transifex.com/django/django/language/" +"hr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hr\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +msgid "Personal info" +msgstr "Osobni podaci" + +msgid "Permissions" +msgstr "Privilegije" + +msgid "Important dates" +msgstr "Važni datumi" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "Unos %(name)s sa primarnim ključem %(key)r ne postoji." + +msgid "Password changed successfully." +msgstr "Lozinka uspješno promijenjena." + +#, python-format +msgid "Change password: %s" +msgstr "Promijeni lozinku: %s" + +msgid "Authentication and Authorization" +msgstr "" + +msgid "password" +msgstr "lozinka" + +msgid "last login" +msgstr "posljednja prijava" + +msgid "No password set." +msgstr "Lozinka nije postavljena." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Neispravan format lozinke ili nepoznati hashing algoritam." + +msgid "The two password fields didn't match." +msgstr "Dva polja za lozinku nisu jednaka." + +msgid "Password" +msgstr "Lozinka" + +msgid "Password confirmation" +msgstr "Potvrda lozinke" + +msgid "Enter the same password as before, for verification." +msgstr "Unesite istu lozinku, za potvrdu." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Unesite ispravno %(username)s i lozinku. Imajte na umu da oba polja mogu " +"biti velika i mala slova." + +msgid "This account is inactive." +msgstr "Ovaj korisnički račun nije aktivan." + +msgid "Email" +msgstr "E-mail" + +msgid "New password" +msgstr "Nova lozinka" + +msgid "New password confirmation" +msgstr "Potvrda nove lozinke" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Vaša stara lozinka je pogrešno unesena. Molim unesite ponovo." + +msgid "Old password" +msgstr "Stara lozinka" + +msgid "Password (again)" +msgstr "Lozinka (unesi ponovo)" + +msgid "algorithm" +msgstr "algoritam" + +msgid "iterations" +msgstr "iteracije" + +msgid "salt" +msgstr "slučajna vrijednost" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "količina rada" + +msgid "checksum" +msgstr "zbroj za provjeru" + +msgid "name" +msgstr "ime" + +msgid "content type" +msgstr "tip sadržaja" + +msgid "codename" +msgstr "kodno ime" + +msgid "permission" +msgstr "privilegija" + +msgid "permissions" +msgstr "privilegije" + +msgid "group" +msgstr "grupa" + +msgid "groups" +msgstr "grupe" + +msgid "superuser status" +msgstr "superuser status" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Određuje da ovaj korisnik ima sve privilegije te uklanja potrebu da se " +"privilegije unose eksplicitno/ručno." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Grupe kojima ovaj korisnik pripada. Korisnik će imati sve privilegije grupa " +"kojima pripada." + +msgid "user permissions" +msgstr "privilegije korisnika" + +msgid "Specific permissions for this user." +msgstr "Određene privilegije za korisnika." + +msgid "username" +msgstr "korisničko ime" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "Korisnik sa navedenim imenom već postoji." + +msgid "first name" +msgstr "ime" + +msgid "last name" +msgstr "prezime" + +msgid "email address" +msgstr "e-mail adresa" + +msgid "staff status" +msgstr "status osoblja" + +msgid "Designates whether the user can log into this admin site." +msgstr "Određuje može li se korisnik prijaviti na ove stranice administracije." + +msgid "active" +msgstr "aktivan" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Određuje treba li se ovaj korisnik tretirati kao aktivan korisnik. Koristite " +"ovu opciju umjesto brisanja korisničkih računa." + +msgid "date joined" +msgstr "datum učlanjenja" + +msgid "user" +msgstr "korisnik" + +msgid "users" +msgstr "korisnici" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Lozinka nije dovoljno dugačka. Mora sadržavati minimalno %(min_length)d znak." +msgstr[1] "" +"Lozinka nije dovoljno dugačka. Mora sadržavati minimalno %(min_length)d " +"znaka." +msgstr[2] "" +"Lozinka nije dovoljno dugačka. Mora sadržavati minimalno %(min_length)d " +"znakova." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Lozinka mora sadržavati minimalno %(min_length)d znak." +msgstr[1] "Lozinka mora sadržavati minimalno %(min_length)d znaka." +msgstr[2] "Lozinka mora sadržavati minimalno %(min_length)d znakova." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "" + +msgid "Your password can't be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "" + +msgid "Your password can't be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "Lozinka se u potpunosti sastoji od brojeva." + +msgid "Your password can't be entirely numeric." +msgstr "Lozinka se ne smije u potpunosti sastojati od brojeva." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Resetiranje lozinke na %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "Niste logirani" + +msgid "Password reset" +msgstr "Resetiranje lozinke" + +msgid "Password reset sent" +msgstr "Resetiranje lozinke poslano" + +msgid "Enter new password" +msgstr "Unesite novu lozinku" + +msgid "Password reset unsuccessful" +msgstr "Resetiranje lozinke neuspješno" + +msgid "Password reset complete" +msgstr "Resetiranje lozinke završeno" + +msgid "Password change" +msgstr "Promjena lozinke" + +msgid "Password change successful" +msgstr "Promjena lozinke uspješna" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hsb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hsb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5b76e7b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hsb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hsb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hsb/LC_MESSAGES/django.po new file mode 100644 index 0000000..1293c03 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hsb/LC_MESSAGES/django.po @@ -0,0 +1,317 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Michael Wolf , 2016-2017,2019,2021,2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-04-25 08:09+0000\n" +"Last-Translator: Michael Wolf , " +"2016-2017,2019,2021,2023\n" +"Language-Team: Upper Sorbian (http://www.transifex.com/django/django/" +"language/hsb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hsb\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || " +"n%100==4 ? 2 : 3);\n" + +msgid "Personal info" +msgstr "Wosobinske informacije" + +msgid "Permissions" +msgstr "Prawa" + +msgid "Important dates" +msgstr "Wažne daty" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "Objekt %(name)s z primarnym klučom %(key)r njeeksistuje." + +msgid "Password changed successfully." +msgstr "Hesło je so wuspěšnje změniło." + +#, python-format +msgid "Change password: %s" +msgstr "Hesło změnić: %s" + +msgid "Authentication and Authorization" +msgstr "Awtentifikacija a awtorizacija" + +msgid "password" +msgstr "hesło" + +msgid "last login" +msgstr "poslednje přizjewjenje" + +msgid "No password set." +msgstr "Žane hesło nastajene." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Njepłaćiwy hesłowy format abo njeznaty kontrolny algoritmus." + +msgid "The two password fields didn’t match." +msgstr "Dwě heslowej poli sej njewotpowědujetej." + +msgid "Password" +msgstr "Hesło" + +msgid "Password confirmation" +msgstr "Hesłowe wobkrućenje" + +msgid "Enter the same password as before, for verification." +msgstr "Zapodajće samsne hesło kaž do toho, za přepruwowanje." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Hrube hesła so njeskładuja, tohodla njeda so hesło tutoho wužwarja widźeć, " +"ale móžeće hesło z pomocu tutoho formulara změnić. " + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Prošu zapodajće korektne %(username)s a hesło. Dźiwajće na to, zo wobě poli " +"móžetej mjez wulko- a małopisanjom rozeznawać." + +msgid "This account is inactive." +msgstr "Tute konto je inaktiwne." + +msgid "Email" +msgstr "E-mejl" + +msgid "New password" +msgstr "Nowe hesło" + +msgid "New password confirmation" +msgstr "Wobkrućenje noweho hesła" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Waše stare hesło je so wopak zapodało. Prošu zapodajće jo hišće raz." + +msgid "Old password" +msgstr "Stare hesło" + +msgid "Password (again)" +msgstr "Hesło (znowa)" + +msgid "algorithm" +msgstr "algoritmus" + +msgid "iterations" +msgstr "wospjetowanja" + +msgid "salt" +msgstr "sól" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "warianta" + +msgid "version" +msgstr "wersija" + +msgid "memory cost" +msgstr "Składowa přetrjeba" + +msgid "time cost" +msgstr "Časowa přetrjeba" + +msgid "parallelism" +msgstr "paralelizm" + +msgid "work factor" +msgstr "dźěłowy faktor" + +msgid "checksum" +msgstr "pruwowanska suma" + +msgid "block size" +msgstr "blokowa wulkosć" + +msgid "name" +msgstr "mjeno" + +msgid "content type" +msgstr "wobsahowy typ" + +msgid "codename" +msgstr "kodowe mjeno" + +msgid "permission" +msgstr "prawo" + +msgid "permissions" +msgstr "prawa" + +msgid "group" +msgstr "skupina" + +msgid "groups" +msgstr "skupiny" + +msgid "superuser status" +msgstr "status superwužiwarja" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Woznamjenja, zo tutón wužiwar ma wšě prawa bjez toho, zo by móhł je " +"eksplicitnje připokazać." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Skupiny, ke kotrymž wužiwar słuša. Wužiwar dóstanje wšě prawa, kotrež jemu " +"skupiny dawaja." + +msgid "user permissions" +msgstr "wužiwarske prawa" + +msgid "Specific permissions for this user." +msgstr "Wěste prawa za tutoho wužiwarja." + +msgid "username" +msgstr "wužiwarske mjeno" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "Trěbne. 150 znamješkow abo mjenje. Jenož pismiki, cyfry a @/./+/-/_." + +msgid "A user with that username already exists." +msgstr "Wužiwar z tutym mjenom hižo eksistuje." + +msgid "first name" +msgstr "předmjeno" + +msgid "last name" +msgstr "swójbne mjeno" + +msgid "email address" +msgstr "e-mejlowa adresa" + +msgid "staff status" +msgstr "personalny status" + +msgid "Designates whether the user can log into this admin site." +msgstr "" +"Woznamjenja, hač wužiwar móže so pola administratoroweho sydła přizjewić." + +msgid "active" +msgstr "aktiwny" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Woznamjenja, hač maja z wužiwarjom jako aktiwnym wobchadźeć. Znjemóžńće to " +"město toho, zo byšće konto zhašał." + +msgid "date joined" +msgstr "čłon wot" + +msgid "user" +msgstr "wužiwar" + +msgid "users" +msgstr "wužiwarjo" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Tute hesło je překrótke. Dyrbi znajmjeńša %(min_length)d znamješko " +"wobsahować." +msgstr[1] "" +"Tute hesło je překrótke. Dyrbi znajmjeńša %(min_length)d znamješce " +"wobsahować." +msgstr[2] "" +"Tute hesło je překrótke. Dyrbi znajmjeńša %(min_length)d znamješka " +"wobsahować." +msgstr[3] "" +"Tute hesło je překrótke. Dyrbi znajmjeńša %(min_length)d znamješkow " +"wobsahować." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Waše hesło dyrbi znajmjeńša %(min_length)d znamješko měć." +msgstr[1] "Waše hesło dyrbi znajmjeńša %(min_length)d znamješce měć." +msgstr[2] "Waše hesło dyrbi znajmjeńša %(min_length)d znamješka měć." +msgstr[3] "Waše hesło dyrbi znajmjeńša %(min_length)d znamješkow měć." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Hesło je na %(verbose_name)s přepodobne." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Waše hesło njemóže na waše druhe wosobinske informacije podobne być." + +msgid "This password is too common." +msgstr "Tute hesło je přehuste," + +msgid "Your password can’t be a commonly used password." +msgstr "Waše hesło njemóže husto wužwane hesło być." + +msgid "This password is entirely numeric." +msgstr "Tute hesło je cyle numeriske." + +msgid "Your password can’t be entirely numeric." +msgstr "Waše hesło njemóže cyle numeriske być." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Hesło je so na %(site_name)s wróćo stajiło." + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Zapodajće płaćiwe wužiwarske mjeno. Tuta hódnota smě jenož małopismiki bjez " +"diakritiskich znamješkow a-z a wulkopismiki A-Z, ličby a znamješka @/./+/-/_ " +"wobsahować." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Zapodajće płaćiwe wužiwarske mjeno. Tuta hódnota smě jenož pismiki, ličby a " +"znamješka @/./+/-/_ wobsahować." + +msgid "Logged out" +msgstr "Wotzjewjeny" + +msgid "Password reset" +msgstr "Wróćostajenje hesła" + +msgid "Password reset sent" +msgstr "Wróćostajenje hesła jo se wotpósłało." + +msgid "Enter new password" +msgstr "Zapodajće nowe hesło" + +msgid "Password reset unsuccessful" +msgstr "Wróćostajenje hesła njeje so poradźiło" + +msgid "Password reset complete" +msgstr "Wróćostajenje hesła je zakónčene" + +msgid "Password change" +msgstr "Změnjenje hesła" + +msgid "Password change successful" +msgstr "Hesło je so wuspěšnje změniło" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hu/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hu/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5ee4b6f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hu/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hu/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hu/LC_MESSAGES/django.po new file mode 100644 index 0000000..ccfdcf3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hu/LC_MESSAGES/django.po @@ -0,0 +1,312 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# András Veres-Szentkirályi, 2016-2017 +# Balázs R, 2023 +# Istvan Farkas , 2019 +# Jannis Leidel , 2011 +# János R, 2014 +# Szilveszter Farkas , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-12-04 08:09+0000\n" +"Last-Translator: Balázs R, 2023\n" +"Language-Team: Hungarian (http://app.transifex.com/django/django/language/" +"hu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Személyes információ" + +msgid "Permissions" +msgstr "Jogosultságok" + +msgid "Important dates" +msgstr "Fontos dátumok" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(name)s objektum %(key)r elsődleges kulccsal nem létezik." + +msgid "Password changed successfully." +msgstr "Sikeres jelszóváltoztatás." + +#, python-format +msgid "Change password: %s" +msgstr "Jelszó megváltoztatása: %s" + +msgid "Authentication and Authorization" +msgstr "Hitelesítés és engedélyezés" + +msgid "password" +msgstr "jelszó" + +msgid "last login" +msgstr "utolsó bejelentkezés" + +msgid "No password set." +msgstr "Nincs jelszó beállítva." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Érvénytelen jelszóformátum vagy ismeretlen hash-algoritmus." + +msgid "The two password fields didn’t match." +msgstr "A beírt két jelszó nem egyezik." + +msgid "Password" +msgstr "Jelszó" + +msgid "Password confirmation" +msgstr "Jelszó megerősítése" + +msgid "Enter the same password as before, for verification." +msgstr "Írja be az előbb megadott jelszót, ellenőrzés céljából." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"A jelszavakat olvasható formában nem tároljuk, így egy felhasználó jelszavát " +"nem lehet mgnézni, de át lehet állítani ezzel az űrlappal." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Írjon be egy helyes %(username)s és jelszót. Mindkét mező kisbetű-nagybetű " +"érzékeny lehet." + +msgid "This account is inactive." +msgstr "Ez a fiók inaktív." + +msgid "Email" +msgstr "E-mail" + +msgid "New password" +msgstr "Új jelszó" + +msgid "New password confirmation" +msgstr "Új jelszó megerősítése" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "A régi jelszó hibásan lett megadva. Írja be újra." + +msgid "Old password" +msgstr "Régi jelszó" + +msgid "Password (again)" +msgstr "Jelszó újra" + +msgid "algorithm" +msgstr "algoritmus" + +msgid "iterations" +msgstr "iterációk" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "változat" + +msgid "version" +msgstr "verzió" + +msgid "memory cost" +msgstr "memória költség" + +msgid "time cost" +msgstr "idő költség" + +msgid "parallelism" +msgstr "párhuzamosság" + +msgid "work factor" +msgstr "erősség" + +msgid "checksum" +msgstr "ellenőrző összeg" + +msgid "block size" +msgstr "blokk méret" + +msgid "name" +msgstr "név" + +msgid "content type" +msgstr "tartalom típusa" + +msgid "codename" +msgstr "kódnév" + +msgid "permission" +msgstr "jogosultság" + +msgid "permissions" +msgstr "jogosultságok" + +msgid "group" +msgstr "csoport" + +msgid "groups" +msgstr "csoportok" + +msgid "superuser status" +msgstr "rendszergazda státusz" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Megadja, hogy ez a felhasználó rendelkezik-e minden jogosultsággal anélkül, " +"hogy azt külön meg kellene adni." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"A csoportok, amelyekhez a felhasználó tartozik. A felhasználó minden egyes " +"csoportja jogosultságaival rendelkezni fog." + +msgid "user permissions" +msgstr "felhasználói jogosultságok" + +msgid "Specific permissions for this user." +msgstr "A felhasználó egyedi jogosultságai." + +msgid "username" +msgstr "felhasználónév" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Kötelező. Legfeljebb 150 karakter. Betűk, számok és @/./+/-/_ karakterek." + +msgid "A user with that username already exists." +msgstr "Létezik már egy felhasználó ezzel a névvel." + +msgid "first name" +msgstr "keresztnév" + +msgid "last name" +msgstr "vezetéknév" + +msgid "email address" +msgstr "e-mail cím" + +msgid "staff status" +msgstr "személyzet státusz" + +msgid "Designates whether the user can log into this admin site." +msgstr "" +"Megadja, hogy a felhasználó bejelentkezhet-e erre az adminisztrációs oldalra." + +msgid "active" +msgstr "aktív" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Megadja, hogy a felhasználó aktív-e. Állítsa át ezt az értéket a fiók " +"törlése helyett." + +msgid "date joined" +msgstr "csatlakozás dátuma" + +msgid "user" +msgstr "felhasználó" + +msgid "users" +msgstr "felhasználók" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Ez a jelszó túl rövid. Legalább %(min_length)d karakter hosszú legyen." +msgstr[1] "" +"Ez a jelszó túl rövid. Legalább %(min_length)d karakter hosszú legyen." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +"A jelszavának legalább %(min_length)d karakter hosszúnak kell lennie." +msgstr[1] "" +"A jelszavának legalább %(min_length)d karakter hosszúnak kell lennie." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "A jelszava túlságosan hasonlít a következőhöz: %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "A jelszó nem lehet hasonló a személyes adatok egyikéhez sem." + +msgid "This password is too common." +msgstr "Ez a jelszó túlságosan gyakori." + +msgid "Your password can’t be a commonly used password." +msgstr "A jelszó nem lehet a túl gyakran használt jelszavak közül." + +msgid "This password is entirely numeric." +msgstr "A jelszava kizárólag számjegyekből áll." + +msgid "Your password can’t be entirely numeric." +msgstr "A jelszó nem állhat csak számjegyekből." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Jelszó újragenerálása ezen az oldalon: %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Írjon be egy érvényes felhasználónevet, mely csak ékezetmentes betűket, " +"számokat és @/./+/-/_ karaktereket tartalmazhat." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Írjon be egy érvényes felhasználónevet, mely csak betűket, számokat és @/./" +"+/-/_ karaktereket tartalmazhat." + +msgid "Logged out" +msgstr "Kijelentkezve" + +msgid "Password reset" +msgstr "Jelszó újragenerálása" + +msgid "Password reset sent" +msgstr "Jelszó beállítás infók elküldve" + +msgid "Enter new password" +msgstr "Írja be az új jelszavát" + +msgid "Password reset unsuccessful" +msgstr "Jelszó beállítása sikertelen" + +msgid "Password reset complete" +msgstr "Jelszó beállítása kész" + +msgid "Password change" +msgstr "Jelszó megváltoztatása" + +msgid "Password change successful" +msgstr "Sikeres jelszóváltoztatás" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9ca530a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hy/LC_MESSAGES/django.po new file mode 100644 index 0000000..f4c9717 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/hy/LC_MESSAGES/django.po @@ -0,0 +1,295 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ruben Harutyunov , 2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2018-11-11 20:11+0000\n" +"Last-Translator: Ruben Harutyunov \n" +"Language-Team: Armenian (http://www.transifex.com/django/django/language/" +"hy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hy\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Անձնական տվյալներ" + +msgid "Permissions" +msgstr "Իրավունքներ" + +msgid "Important dates" +msgstr "Կարևոր ամսաթվեր" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(key)r հիմնական բանալով %(name)s օբյեկտ գոյություն չունի։" + +msgid "Password changed successfully." +msgstr "Գաղտնաբառը հաջողությամբ փոխվեց։" + +#, python-format +msgid "Change password: %s" +msgstr "Փոխել գաղտնաբառը․ %s" + +msgid "Authentication and Authorization" +msgstr "Նույնականացում և Լիազորում" + +msgid "password" +msgstr "գաղտնաբառ" + +msgid "last login" +msgstr "վերջին մուտք" + +msgid "No password set." +msgstr "Գաղտնաբառը նշված չէ։" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Գաղտնաբառի սխալ ֆորմատ, կամ անհայտ հեշավորման ալգորիթմ։" + +msgid "The two password fields didn't match." +msgstr "Երկու գաղտնաբառերը չեն համապատասխանում իրար։" + +msgid "Password" +msgstr "Գաղտնաբառ" + +msgid "Password confirmation" +msgstr "Գաղտնաբառը նորից" + +msgid "Enter the same password as before, for verification." +msgstr "Մուտքագրեք հին գաղտնաբառը, ստուգման համար։" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Մուտքագրեք ճիշտ %(username)s և գաղտնաբառ։ Երկու դաշտերն էլ տառաշարազգայուն " +"են։" + +msgid "This account is inactive." +msgstr "Այս օգտագործողը ակտիվ չէ։" + +msgid "Email" +msgstr "Email" + +msgid "New password" +msgstr "Նոր գաղտնաբառ" + +msgid "New password confirmation" +msgstr "Նոր գաղտնաբառը նորից" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Հին գաղտնաբառը սխալ է։ Մուտքագրեք նորից։" + +msgid "Old password" +msgstr "Հին գաղտնաբառ" + +msgid "Password (again)" +msgstr "Գաղտնաբառ (նորից)" + +msgid "algorithm" +msgstr "ալգորիթմ" + +msgid "iterations" +msgstr "իտերացիաներ" + +msgid "salt" +msgstr "աղ" + +msgid "hash" +msgstr "հեշ" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "տևողություն" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "աշխատանքային ֆակտոր" + +msgid "checksum" +msgstr "checksum" + +msgid "name" +msgstr "անուն" + +msgid "content type" +msgstr "պարունակության տիպ" + +msgid "codename" +msgstr "կոդային անուն" + +msgid "permission" +msgstr "իրավունքնե" + +msgid "permissions" +msgstr "իրավունքներ" + +msgid "group" +msgstr "խումբ" + +msgid "groups" +msgstr "խմբեր" + +msgid "superuser status" +msgstr "սուպերօգտագործողի կարգավիճակ" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Ցույց է տալիս, որ օգտագործողը ունի բոլոր իրավունքները, առանց նրանց նշման։" + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Խումբը, որին պատկանում է օգտագործողը։ Օգտագործողը ստանում է իր խմբին տրված " +"բոլոր իրավունքները։" + +msgid "user permissions" +msgstr "օգտագործողի իրավունքները" + +msgid "Specific permissions for this user." +msgstr "Օգտագործողի հատուկ իրավունքները։" + +msgid "username" +msgstr "օգտագործողի անուն" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "Այդ անունով օգտագործող արդեն գոյություն ունի։" + +msgid "first name" +msgstr "անուն" + +msgid "last name" +msgstr "ազգանուն" + +msgid "email address" +msgstr "email հասցե" + +msgid "staff status" +msgstr "անձնակազմի կարգավիճակ" + +msgid "Designates whether the user can log into this admin site." +msgstr "" +"Ցույց է տալիս, թե արդյոք օգտագործողը կարոզ է մուտք գործել ադմինիստրավորման " +"բաժին։" + +msgid "active" +msgstr "ակտիվ" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Ցույց է տալիս, թե արդյոք օգտագործողին կարելի է համարել ակտիվ։ Ապընտրեք, " +"օգտագործողին հեռացնելու փոխարեն։" + +msgid "date joined" +msgstr "միացել է" + +msgid "user" +msgstr "օգտագործող" + +msgid "users" +msgstr "օգտագործողներ" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Գաղտնաբառը շատ կարճ է։ Այն պետք է պարունակի ամենաքիչը %(min_length)d նիշ։" +msgstr[1] "" +"Գաղտնաբառը շատ կարճ է։ Այն պետք է պարունակի ամենաքիչը %(min_length)d նիշ։" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Գաղտնաբառը պետք է պարունակի ամենաքիչը %(min_length)d նիշ։" +msgstr[1] "Գաղտնաբառը պետք է պարունակի ամենաքիչը %(min_length)d նիշ։" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Գաղտնաբառը շատ նման է %(verbose_name)s֊ին։" + +msgid "Your password can't be too similar to your other personal information." +msgstr "Գաղտնաբառը չի կարող շատ նման լինել ձեր անձնական ինֆորմացիային։" + +msgid "This password is too common." +msgstr "Գաղտնաբառը շատ տարածված է։" + +msgid "Your password can't be a commonly used password." +msgstr "Գաղտնաբառը չպետք է լինի տարածված գաղտնաբառերից մեկը։" + +msgid "This password is entirely numeric." +msgstr "Գաղտնաբառը բաղկացած է միայն թվերից։" + +msgid "Your password can't be entirely numeric." +msgstr "Գաղտնաբառը չպետք է բաղկացած լինի միայն թվերից։" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Գաղտնաբառի փոփոխում %(site_name)s կայքում։" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "Դուք դուրս եք եկել" + +msgid "Password reset" +msgstr "Գաղտնաբառի փոփոխում" + +msgid "Password reset sent" +msgstr "Գաղտնաբառի փոփոխման հղումն ուղարկված է" + +msgid "Enter new password" +msgstr "Մուտքագրեք նոր գաղտնաբառը" + +msgid "Password reset unsuccessful" +msgstr "Գաղտնաբառի փոփոխումը չի ավարտվել հաջողությամբ" + +msgid "Password reset complete" +msgstr "Գաղտնաբառի փոփոխումը ավարտված է" + +msgid "Password change" +msgstr "Գաղտնաբառի փոփոխում" + +msgid "Password change successful" +msgstr "Գաղտնաբառի փոփոխումը ավարտվել է հաջողությամբ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ia/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ia/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4566c4b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ia/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ia/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ia/LC_MESSAGES/django.po new file mode 100644 index 0000000..16eeda8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ia/LC_MESSAGES/django.po @@ -0,0 +1,310 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Martijn Dekker , 2012,2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2021-09-22 09:22+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Interlingua (http://www.transifex.com/django/django/language/" +"ia/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ia\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Information personal" + +msgid "Permissions" +msgstr "Permissiones" + +msgid "Important dates" +msgstr "Datas importante" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "Le objecto %(name)s con le clave primari %(key)r non existe." + +msgid "Password changed successfully." +msgstr "Le cambio del contrasigno ha succedite." + +#, python-format +msgid "Change password: %s" +msgstr "Cambia contrasigno: %s" + +msgid "Authentication and Authorization" +msgstr "Authentication e autorisation" + +msgid "password" +msgstr "contrasigno" + +msgid "last login" +msgstr "ultime session" + +msgid "No password set." +msgstr "Nulle contrasigno definite." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" +"Le formato del contrasigno es invalide o le algorithmo de hash es incognite." + +msgid "The two password fields didn’t match." +msgstr "Le duo campos de contrasigno non es identic." + +msgid "Password" +msgstr "Contrasigno" + +msgid "Password confirmation" +msgstr "Confirma contrasigno" + +msgid "Enter the same password as before, for verification." +msgstr "Scribe le mesme contrasigno que antea, pro verification." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Le contrasignos non es immagazinate in forma de texto simple, dunque il non " +"es possibile vider le contrasigno de iste usator, ma tu pote cambiar le " +"contrasigno con iste formulario." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Per favor entra un %(username)s e contrasigno correcte. Nota que ambe campos " +"pote distinguer inter majusculas e minusculas." + +msgid "This account is inactive." +msgstr "Iste conto es inactive." + +msgid "Email" +msgstr "E-mail" + +msgid "New password" +msgstr "Nove contrasigno" + +msgid "New password confirmation" +msgstr "Confirma nove contrasigno" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Le ancian contrasigno non es correcte. Per favor scribe lo de novo." + +msgid "Old password" +msgstr "Ancian contrasigno" + +msgid "Password (again)" +msgstr "Contrasigno (de novo)" + +msgid "algorithm" +msgstr "algorithmo" + +msgid "iterations" +msgstr "iterationes" + +msgid "salt" +msgstr "sal" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "varietate" + +msgid "version" +msgstr "version" + +msgid "memory cost" +msgstr "costo de memoria" + +msgid "time cost" +msgstr "costo de tempore" + +msgid "parallelism" +msgstr "parallelismo" + +msgid "work factor" +msgstr "factor de labor" + +msgid "checksum" +msgstr "summa de controlo" + +msgid "block size" +msgstr "" + +msgid "name" +msgstr "nomine" + +msgid "content type" +msgstr "typo de contento" + +msgid "codename" +msgstr "nomine de codice" + +msgid "permission" +msgstr "permission" + +msgid "permissions" +msgstr "permissiones" + +msgid "group" +msgstr "gruppo" + +msgid "groups" +msgstr "gruppos" + +msgid "superuser status" +msgstr "stato de superusator" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Indica que iste usator ha tote le permissiones sin assignar los " +"explicitemente." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Le gruppos al quales iste usator pertine. Un usator recipe tote le " +"permissiones concedite a cata un de su gruppos." + +msgid "user permissions" +msgstr "permissiones de usator" + +msgid "Specific permissions for this user." +msgstr "Permissiones specific pro iste usator." + +msgid "username" +msgstr "nomine de usator" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Obligatori. 150 characteres o minus. Litteras, cifras e @/./+/-/_ solmente." + +msgid "A user with that username already exists." +msgstr "Un usator con iste nomine de usator jam existe." + +msgid "first name" +msgstr "prenomine" + +msgid "last name" +msgstr "nomine de familia" + +msgid "email address" +msgstr "adresse de e-mail" + +msgid "staff status" +msgstr "stato de personal" + +msgid "Designates whether the user can log into this admin site." +msgstr "Indica si le usator pote aperir session in iste sito administrative." + +msgid "active" +msgstr "active" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Indica si iste usator debe esser tractate como active. Dismarca isto in vice " +"de deler contos." + +msgid "date joined" +msgstr "data de inscription" + +msgid "user" +msgstr "usator" + +msgid "users" +msgstr "usatores" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Le contrasigno es troppo curte. Debe continer al minus %(min_length)d " +"character." +msgstr[1] "" +"Le contrasigno es troppo curte. Debe continer al minus %(min_length)d " +"characteres." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Le contrasigno debe continer al minus %(min_length)d character." +msgstr[1] "Le contrasigno debe continer al minus %(min_length)d characteres." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Le contrasigno es troppo simile al %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" +"Le contrasigno non pote esser troppo similar a tu altere informationes " +"personal." + +msgid "This password is too common." +msgstr "Iste contrasigno es troppo commun." + +msgid "Your password can’t be a commonly used password." +msgstr "Le contrasigno non pote esser un contrasigno communmente usate." + +msgid "This password is entirely numeric." +msgstr "Iste contrasigno es toto numeric." + +msgid "Your password can’t be entirely numeric." +msgstr "Le contrasigno non pote esser toto numeric." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Reinitialisation del contrasigno in %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"Entra un nomine de usator valide. Pote continer solmente litteras anglese, " +"numeros e le characteres @/./+/-/_." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Entra un nomine de usator valide. Pote continer solmente litteras, numeros e " +"le characteres @/./+/-/_." + +msgid "Logged out" +msgstr "Session claudite" + +msgid "Password reset" +msgstr "Reinitialisation del contrasigno" + +msgid "Password reset sent" +msgstr "Reinitialisation del contrasigno inviate" + +msgid "Enter new password" +msgstr "Scribe nove contrasigno" + +msgid "Password reset unsuccessful" +msgstr "Reinitialisation de contrasigno fallite" + +msgid "Password reset complete" +msgstr "Contrasigno reinitialisate con successo" + +msgid "Password change" +msgstr "Cambio de contrasigno" + +msgid "Password change successful" +msgstr "Contrasigno cambiate con successo" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/id/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/id/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f74e3d6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/id/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/id/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/id/LC_MESSAGES/django.po new file mode 100644 index 0000000..22e62aa --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/id/LC_MESSAGES/django.po @@ -0,0 +1,307 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Fery Setiawan , 2015-2016,2018,2020-2021,2023 +# Jannis Leidel , 2011 +# oon arfiandwi (OonID) , 2016 +# rodin , 2011,2013 +# rodin , 2013-2016 +# sag᠎e , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-12-04 08:09+0000\n" +"Last-Translator: Fery Setiawan , " +"2015-2016,2018,2020-2021,2023\n" +"Language-Team: Indonesian (http://app.transifex.com/django/django/language/" +"id/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: id\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Personal info" +msgstr "Informasi pribadi" + +msgid "Permissions" +msgstr "Hak akses" + +msgid "Important dates" +msgstr "Tanggal penting" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "Objek %(name)s dengan primary key %(key)r tidak ditemukan." + +msgid "Password changed successfully." +msgstr "Sandi berhasil diubah." + +#, python-format +msgid "Change password: %s" +msgstr "Ganti sandi: %s" + +msgid "Authentication and Authorization" +msgstr "Autentikasi dan Otorisasi" + +msgid "password" +msgstr "sandi" + +msgid "last login" +msgstr "masuk terakhir" + +msgid "No password set." +msgstr "Belum ada sandi yang disetel." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Format sandi tidak valid atau algoritma hash yang tidak dikenal." + +msgid "The two password fields didn’t match." +msgstr "Dua bidang sandi tidak cocok." + +msgid "Password" +msgstr "Sandi" + +msgid "Password confirmation" +msgstr "Konfirmasi sandi" + +msgid "Enter the same password as before, for verification." +msgstr "Masukkan sandi yang sama seperti sebelumnya, untuk verifikasi." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Sandi mentah tidak disimpan, jadi tidak ada cara melihat sandi pengguna ini, " +"tetapi anda dapat merubah sandi menggunakan formulir ini." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Masukkan nama pengguna %(username)s dan sandi yang benar. Huruf besar/kecil " +"pada bidang ini berpengaruh." + +msgid "This account is inactive." +msgstr "Akun ini tidak aktif." + +msgid "Email" +msgstr "Email" + +msgid "New password" +msgstr "Sandi baru" + +msgid "New password confirmation" +msgstr "Konfirmasi sandi baru" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Sandi lama Anda yang dimasukkan salah. Masukkan sekali lagi." + +msgid "Old password" +msgstr "Sandi lama" + +msgid "Password (again)" +msgstr "Sandi (ulangi)" + +msgid "algorithm" +msgstr "algoritme" + +msgid "iterations" +msgstr "iterasi" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "keanekaragaman" + +msgid "version" +msgstr "versi" + +msgid "memory cost" +msgstr "biaya memori" + +msgid "time cost" +msgstr "biaya waktu" + +msgid "parallelism" +msgstr "sifat paralel" + +msgid "work factor" +msgstr "faktor kerja" + +msgid "checksum" +msgstr "ceksum" + +msgid "block size" +msgstr "ukuran blok" + +msgid "name" +msgstr "nama" + +msgid "content type" +msgstr "jenis isi" + +msgid "codename" +msgstr "namasandi" + +msgid "permission" +msgstr "hak akses" + +msgid "permissions" +msgstr "hak akses" + +msgid "group" +msgstr "grup" + +msgid "groups" +msgstr "grup" + +msgid "superuser status" +msgstr "status superuser" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Menentukan apakah pengguna memiliki semua hak akses tanpa perlu diberikan " +"secara manual." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Grup tempat pengguna ini dikelompokkan. Pengguna akan mendapatkan semua hak " +"akses yang diberikan pada grup mereka." + +msgid "user permissions" +msgstr "hak akses pengguna" + +msgid "Specific permissions for this user." +msgstr "Hak akses khusus untuk pengguna ini." + +msgid "username" +msgstr "nama pengguna" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "Wajib. 150 karakter atau sedikit. Hanya huruf, angka, dan @/./+/-/_." + +msgid "A user with that username already exists." +msgstr "Seorang pengguna dengan nama pengguna tersebut sudah ada." + +msgid "first name" +msgstr "nama depan" + +msgid "last name" +msgstr "nama belakang" + +msgid "email address" +msgstr "alamat email" + +msgid "staff status" +msgstr "status staf" + +msgid "Designates whether the user can log into this admin site." +msgstr "Menentukan apakah pengguna berhak masuk ke situs administrasi ini." + +msgid "active" +msgstr "aktif" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Menentukan apakah pengguna dianggap aktif. Hapus pilihan ini tanpa perlu " +"menghapus akunnya." + +msgid "date joined" +msgstr "tanggal daftar" + +msgid "user" +msgstr "pengguna" + +msgid "users" +msgstr "pengguna" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Kata sandi terlalu singkat. Kata sandi harus memuat setidaknya " +"%(min_length)d karakter." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Kata sandi Anda harus memuat setidaknya %(min_length)d karakter." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Kata sandi terlalu mirip dengan %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Sandi anda tidak dapat terlalu mirip terhadap informasi pribadi anda." + +msgid "This password is too common." +msgstr "Kata sandi ini terlalu umum." + +msgid "Your password can’t be a commonly used password." +msgstr "Sandi anda tidak dapat berupa sandi umum digunakan." + +msgid "This password is entirely numeric." +msgstr "Kata sandi ini seluruhnya terdiri dari angka." + +msgid "Your password can’t be entirely numeric." +msgstr "Sandi anda tidak bisa sepenuhnya numerik." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Penyetelan ulang sandi di %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Masukkan nama pengguna sah. Nilai ini mungkin menggandung tanpa tekanan " +"huruf kecil a-z dan huruf besar A-Z, angka dan karakter @/./+/-/_." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Masukkan nama pengguna valid. Nilai ini hanya boleh mengandung karakter, " +"angka, dan karakter @/./+/-/_." + +msgid "Logged out" +msgstr "Keluar" + +msgid "Password reset" +msgstr "Setel ulang sandi" + +msgid "Password reset sent" +msgstr "Penyetelan ulang kata sandi telah dikirim" + +msgid "Enter new password" +msgstr "Masukkan sandi baru" + +msgid "Password reset unsuccessful" +msgstr "Penyetelan ulang sandi gagal" + +msgid "Password reset complete" +msgstr "Penyetelan ulang sandi selesai" + +msgid "Password change" +msgstr "Ubah sandi" + +msgid "Password change successful" +msgstr "Pengubahan sandi berhasil" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/io/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/io/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1e0a163 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/io/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/io/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/io/LC_MESSAGES/django.po new file mode 100644 index 0000000..031f2c4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/io/LC_MESSAGES/django.po @@ -0,0 +1,226 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-03-18 09:16+0100\n" +"PO-Revision-Date: 2015-03-18 10:30+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Ido (http://www.transifex.com/projects/p/django/language/" +"io/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: io\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "" + +msgid "Permissions" +msgstr "" + +msgid "Important dates" +msgstr "" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "" + +#, python-format +msgid "Change password: %s" +msgstr "" + +msgid "Authentication and Authorization" +msgstr "" + +msgid "No password set." +msgstr "" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" + +msgid "The two password fields didn't match." +msgstr "" + +msgid "Password" +msgstr "" + +msgid "Password confirmation" +msgstr "" + +msgid "Enter the same password as above, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this " +"form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" + +msgid "This account is inactive." +msgstr "" + +msgid "Email" +msgstr "" + +msgid "New password" +msgstr "" + +msgid "New password confirmation" +msgstr "" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" + +msgid "Old password" +msgstr "" + +msgid "Password (again)" +msgstr "" + +msgid "algorithm" +msgstr "" + +msgid "iterations" +msgstr "" + +msgid "salt" +msgstr "" + +msgid "hash" +msgstr "" + +msgid "work factor" +msgstr "" + +msgid "checksum" +msgstr "" + +msgid "name" +msgstr "" + +msgid "codename" +msgstr "" + +msgid "permission" +msgstr "" + +msgid "permissions" +msgstr "" + +msgid "group" +msgstr "" + +msgid "groups" +msgstr "" + +msgid "password" +msgstr "" + +msgid "last login" +msgstr "" + +msgid "superuser status" +msgstr "" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "" + +msgid "Specific permissions for this user." +msgstr "" + +msgid "username" +msgstr "" + +msgid "Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers and @/./" +"+/-/_ characters." +msgstr "" + +msgid "A user with that username already exists." +msgstr "" + +msgid "first name" +msgstr "" + +msgid "last name" +msgstr "" + +msgid "email address" +msgstr "" + +msgid "staff status" +msgstr "" + +msgid "Designates whether the user can log into this admin site." +msgstr "" + +msgid "active" +msgstr "" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" + +msgid "date joined" +msgstr "" + +msgid "user" +msgstr "" + +msgid "users" +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "" + +msgid "Logged out" +msgstr "" + +msgid "Password reset" +msgstr "" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "" + +msgid "Password reset unsuccessful" +msgstr "" + +msgid "Password reset complete" +msgstr "" + +msgid "Password change" +msgstr "" + +msgid "Password change successful" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/is/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/is/LC_MESSAGES/django.mo new file mode 100644 index 0000000..57229a4 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/is/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/is/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/is/LC_MESSAGES/django.po new file mode 100644 index 0000000..a0dff94 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/is/LC_MESSAGES/django.po @@ -0,0 +1,307 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Hafsteinn Einarsson , 2011-2012 +# Jannis Leidel , 2011 +# Logi Ragnarsson , 2012 +# Thordur Sigurdsson , 2016-2017,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-11-20 05:04+0000\n" +"Last-Translator: Thordur Sigurdsson \n" +"Language-Team: Icelandic (http://www.transifex.com/django/django/language/" +"is/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: is\n" +"Plural-Forms: nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);\n" + +msgid "Personal info" +msgstr "Persónuupplýsingar" + +msgid "Permissions" +msgstr "Réttindi" + +msgid "Important dates" +msgstr "Mikilvægar dagsetningar" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(name)s hlutur með lykilinn %(key)r er ekki til." + +msgid "Password changed successfully." +msgstr "Breyting á lykilorði tókst." + +#, python-format +msgid "Change password: %s" +msgstr "Breyta lykilorði: %s" + +msgid "Authentication and Authorization" +msgstr "Auðkenning og réttindi" + +msgid "password" +msgstr "lykilorð" + +msgid "last login" +msgstr "síðasta innskráning" + +msgid "No password set." +msgstr "Ekkert lykilorð skráð." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Ógilt snið á lykilorði eða óþekkt hökkunaralgrím." + +msgid "The two password fields didn’t match." +msgstr "Lykilorðin tvö pössuðu ekki saman." + +msgid "Password" +msgstr "Lykilorð" + +msgid "Password confirmation" +msgstr "Staðfesting lykilorðs" + +msgid "Enter the same password as before, for verification." +msgstr "Settu inn sama lykilorð og áður til staðfestingar." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Lykilorð eru aðeins geymd dulkóðuð, svo ekki er hægt að sjá lykilorð þessa " +"notanda, en þú getur breytt lykilorðinu með þessu eyðublaði." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Vinsamlegast sláðu inn rétt %(username)s og lykilorð. Takið eftir að í báðum " +"reitum skipta há- og lágstafir máli." + +msgid "This account is inactive." +msgstr "Þessi reikningur er óvirkur." + +msgid "Email" +msgstr "Netfang" + +msgid "New password" +msgstr "Nýtt lykilorð" + +msgid "New password confirmation" +msgstr "Nýtt lykilorð (endurtekið)" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Gamla lykilorðið var vitlaust. Vinsamlegast reyndu aftur." + +msgid "Old password" +msgstr "Gamalt lykilorð" + +msgid "Password (again)" +msgstr "Lykilorð (aftur)" + +msgid "algorithm" +msgstr "algrím" + +msgid "iterations" +msgstr "ítranir" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hashtafla" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "útgáfa" + +msgid "memory cost" +msgstr "minnisnotkun" + +msgid "time cost" +msgstr "tímalengd" + +msgid "parallelism" +msgstr "samhliða vinnsla" + +msgid "work factor" +msgstr "vinnustuðull" + +msgid "checksum" +msgstr "varsumma" + +msgid "name" +msgstr "nafn" + +msgid "content type" +msgstr "efnistag" + +msgid "codename" +msgstr "vinnuheiti" + +msgid "permission" +msgstr "réttindi" + +msgid "permissions" +msgstr "réttindi" + +msgid "group" +msgstr "hópur" + +msgid "groups" +msgstr "hópar" + +msgid "superuser status" +msgstr "staða ofurnotanda" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Til marks um að notandinn hafi öll réttindi án þess að taka þau sérstaklega " +"fram." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Hópar sem þessi notandi tilheyrir. Notandi fær allan aðgangsrétt sem fylgir " +"hverjum hóp sem hann/hún er skráð(ur) í." + +msgid "user permissions" +msgstr "réttindi" + +msgid "Specific permissions for this user." +msgstr "Sértæk réttindi fyrir þennan notanda." + +msgid "username" +msgstr "notandanafn" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Nauðsynlegt að fylla út. 150 stafir eða færri. Bókstafir (ekki broddstafir), " +"tölustafir og @/./+/-/_ aðeins leyft." + +msgid "A user with that username already exists." +msgstr "Notandi með þetta notendanafn er nú þegar til." + +msgid "first name" +msgstr "skírnarnafn" + +msgid "last name" +msgstr "eftirnafn" + +msgid "email address" +msgstr "netfang" + +msgid "staff status" +msgstr "staða starfsmanns" + +msgid "Designates whether the user can log into this admin site." +msgstr "" +"Segir til um hvort notandinn getur skráð sig inn á þetta stjórnunarsvæði." + +msgid "active" +msgstr "virkur" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Til marks um að notandinn sé virkur. Taktu hakið úr þessum möguleika til að " +"eyða aðgangi." + +msgid "date joined" +msgstr "skráning dags." + +msgid "user" +msgstr "notandi" + +msgid "users" +msgstr "notendur" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Þetta lykilorð er of stutt. Það verður að vera minnst %(min_length)d stafur." +msgstr[1] "" +"Þetta lykilorð er of stutt. Það verður að vera minnst %(min_length)d stafir." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Lykilorðið verður að vera minnst %(min_length)d stafur." +msgstr[1] "Lykilorðið verður að vera minnst %(min_length)d stafir." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Lykilorðið er of líkt %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Lykilorðið má ekki vera of líkt þínum persónuupplýsingum." + +msgid "This password is too common." +msgstr "Þetta lykilorð er of algengt." + +msgid "Your password can’t be a commonly used password." +msgstr "Lykilorðið má ekki vera algengt lykilorð." + +msgid "This password is entirely numeric." +msgstr "Þetta lykilorð er eingöngu tölustafir." + +msgid "Your password can’t be entirely numeric." +msgstr "Lykilorðið má ekki vera eingöngu tölustafir." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Lykilorð endursett á %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"Sláðu inn gilt notandanafn. Þessi reitur má aðeins innihalda bókstafi (ekki " +"broddstafi), tölustafi og @/./+/-/_ táknin" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Sláðu inn gilt notandanafn. Þessi reitur má aðeins innihalda bókstafi, " +"tölustafi og @/./+/-/_ táknin" + +msgid "Logged out" +msgstr "Útskráð(ur)" + +msgid "Password reset" +msgstr "Lykilorð endursett" + +msgid "Password reset sent" +msgstr "Endurstilling lykilorðs send" + +msgid "Enter new password" +msgstr "Sláðu inn nýtt lykilorð" + +msgid "Password reset unsuccessful" +msgstr "Endurstilling á lykilorði mistókst" + +msgid "Password reset complete" +msgstr "Endurstilling lykilorðs tókst" + +msgid "Password change" +msgstr "Breyta lykilorði" + +msgid "Password change successful" +msgstr "Breyting á lykilorði tókst" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/it/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/it/LC_MESSAGES/django.mo new file mode 100644 index 0000000..af1146e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/it/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/it/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/it/LC_MESSAGES/django.po new file mode 100644 index 0000000..05f6885 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/it/LC_MESSAGES/django.po @@ -0,0 +1,322 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Davide Targa , 2021 +# Federico Capoano , 2011 +# Flavio Curella , 2013-2014 +# Jannis Leidel , 2011 +# Luciano De Falco Alfano, 2016 +# Marco Bonetti, 2014 +# palmux , 2015,2019 +# Paolo Melchiorre , 2023 +# Mattia Procopio , 2015 +# Stefano Brentegani , 2015,2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-04-25 08:09+0000\n" +"Last-Translator: Paolo Melchiorre , 2023\n" +"Language-Team: Italian (http://www.transifex.com/django/django/language/" +"it/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: it\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Informazioni personali" + +msgid "Permissions" +msgstr "Permessi" + +msgid "Important dates" +msgstr "Date importanti" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "L'oggetto %(name)s con chiave primaria %(key)r non esiste." + +msgid "Password changed successfully." +msgstr "La password è stata modificata correttamente." + +#, python-format +msgid "Change password: %s" +msgstr "Modifica la password: %s" + +msgid "Authentication and Authorization" +msgstr "Autenticazione e Autorizzazione " + +msgid "password" +msgstr "password" + +msgid "last login" +msgstr "ultimo accesso" + +msgid "No password set." +msgstr "Nessuna password impostata." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Formato di password non valido o algoritmo di hash sconosciuto." + +msgid "The two password fields didn’t match." +msgstr "I due campi password non corrispondono." + +msgid "Password" +msgstr "Password" + +msgid "Password confirmation" +msgstr "Conferma password" + +msgid "Enter the same password as before, for verification." +msgstr "Inserisci la stessa password inserita sopra, come verifica." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Le password grezze non vengono salvate, quindi non è possibile visualizzare " +"la password di questo utente, ma è possibile modificarla utilizzando questo form." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Inserisci %(username)s e password corretti. In entrambi i campi le maiuscole " +"potrebbero essere significative." + +msgid "This account is inactive." +msgstr "Questo account non è attivo." + +msgid "Email" +msgstr "Email" + +msgid "New password" +msgstr "Nuova password" + +msgid "New password confirmation" +msgstr "Conferma nuova password" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" +"La password attuale non è stata inserita correttamente. Riprova per favore." + +msgid "Old password" +msgstr "Password attuale" + +msgid "Password (again)" +msgstr "Password (di nuovo)" + +msgid "algorithm" +msgstr "algoritmo" + +msgid "iterations" +msgstr "iterazioni" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "varietà" + +msgid "version" +msgstr "versione" + +msgid "memory cost" +msgstr "impegno di memoria" + +msgid "time cost" +msgstr "impiego di tempo" + +msgid "parallelism" +msgstr "parallelismo" + +msgid "work factor" +msgstr "work factor" + +msgid "checksum" +msgstr "checksum" + +msgid "block size" +msgstr "dimensione del blocco" + +msgid "name" +msgstr "nome" + +msgid "content type" +msgstr "content type" + +msgid "codename" +msgstr "nome in codice" + +msgid "permission" +msgstr "permesso" + +msgid "permissions" +msgstr "permessi" + +msgid "group" +msgstr "gruppo" + +msgid "groups" +msgstr "gruppi" + +msgid "superuser status" +msgstr "privilegi di superutente" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Attribuisce all'utente tutti i privilegi, senza che sia necessario " +"assegnarli esplicitamente." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"I gruppi a cui appartiene l'utente. L'utente eredita tutti i permessi " +"assegnati a ciascuno dei suoi gruppi." + +msgid "user permissions" +msgstr "privilegi utente" + +msgid "Specific permissions for this user." +msgstr "Permessi specifici per questo utente." + +msgid "username" +msgstr "nome utente" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "Obbligatorio. 150 caratteri o meno.Solo lettere, cifre e @/./+/-/_" + +msgid "A user with that username already exists." +msgstr "Un utente con questo nome è già presente." + +msgid "first name" +msgstr "nome" + +msgid "last name" +msgstr "cognome" + +msgid "email address" +msgstr "indirizzo email" + +msgid "staff status" +msgstr "privilegi di staff" + +msgid "Designates whether the user can log into this admin site." +msgstr "Stabilisce se l'utente può accedere a questo sito di amministrazione." + +msgid "active" +msgstr "attivo" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Stabilisce se l'utente debba essere considerato attivo. Deseleziona qui, " +"piuttosto che cancellare gli account." + +msgid "date joined" +msgstr "iscritto in data" + +msgid "user" +msgstr "utente" + +msgid "users" +msgstr "utenti" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Questa password è troppo corta. Deve contenere almeno %(min_length)d " +"carattere." +msgstr[1] "" +"Questa password è troppo corta. Deve contenere almeno %(min_length)d " +"caratteri." +msgstr[2] "" +"Questa password è troppo corta. Deve contenere almeno %(min_length)d " +"caratteri." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "La tua password deve contenere almeno %(min_length)d carattere." +msgstr[1] "La tua password deve contenere almeno %(min_length)d caratteri." +msgstr[2] "La tua password deve contenere almeno %(min_length)d caratteri." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "La password è troppo simile a %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" +"La tua password non può essere troppo simile alle altre tue informazioni " +"personali." + +msgid "This password is too common." +msgstr "Questa password è troppo comune." + +msgid "Your password can’t be a commonly used password." +msgstr "La tua password non può essere una password comunemente usata." + +msgid "This password is entirely numeric." +msgstr "Questa password è interamente numerica." + +msgid "Your password can’t be entirely numeric." +msgstr "La tua password non può essere interamente numerica." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Password reset su %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Inserisci un nome utente valido. Questo valore può contenere solo lettere " +"non accentate minuscole a-z e maiuscole A-Z, numeri ed i caratteri @/./+/-/_." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Immetti un nome utente valido. Questo campo può contenere solo lettere " +"dell'alfabeto inglese, numeri e caratteri @/./+/-/_ ." + +msgid "Logged out" +msgstr "Accesso annullato" + +msgid "Password reset" +msgstr "Reimposta la password" + +msgid "Password reset sent" +msgstr "Istruzioni per il recupero della password inviate" + +msgid "Enter new password" +msgstr "Inserisci la nuova password" + +msgid "Password reset unsuccessful" +msgstr "Password non reimpostata" + +msgid "Password reset complete" +msgstr "Password reimpostata" + +msgid "Password change" +msgstr "Modifica password" + +msgid "Password change successful" +msgstr "Password modificata correttamente" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ja/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ja/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a6d3789 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ja/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ja/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ja/LC_MESSAGES/django.po new file mode 100644 index 0000000..a1cbcfc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ja/LC_MESSAGES/django.po @@ -0,0 +1,303 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# arupakan125 , 2020 +# Masashi SHIBATA , 2017 +# Nikita K , 2019 +# Shinya Okano , 2013-2016,2021,2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-04-25 08:09+0000\n" +"Last-Translator: Shinya Okano , 2013-2016,2021,2023\n" +"Language-Team: Japanese (http://www.transifex.com/django/django/language/" +"ja/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ja\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Personal info" +msgstr "個人情報" + +msgid "Permissions" +msgstr "パーミッション" + +msgid "Important dates" +msgstr "重要な日程" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "主キーが %(key)r である %(name)s オブジェクトは存在しません。" + +msgid "Password changed successfully." +msgstr "パスワードを変更しました" + +#, python-format +msgid "Change password: %s" +msgstr "パスワードの変更: %s" + +msgid "Authentication and Authorization" +msgstr "認証と認可" + +msgid "password" +msgstr "パスワード" + +msgid "last login" +msgstr "最終ログイン" + +msgid "No password set." +msgstr "パスワードは設定されませんでした。" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "無効なパスワードか不明なハッシュアルゴリズムです。" + +msgid "The two password fields didn’t match." +msgstr "確認用パスワードが一致しません。" + +msgid "Password" +msgstr "パスワード" + +msgid "Password confirmation" +msgstr "パスワード(確認用)" + +msgid "Enter the same password as before, for verification." +msgstr "確認のため、再度パスワードを入力してください。" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"生のパスワードは格納されていないため、このユーザのパスワードを確認する方法は" +"ありません。しかしこのフォームを使用してパスワードを変更で" +"きます。" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"正しい%(username)sとパスワードを入力してください。どちらのフィールドも大文字" +"と小文字は区別されます。" + +msgid "This account is inactive." +msgstr "アカウントが無効です。" + +msgid "Email" +msgstr "メールアドレス" + +msgid "New password" +msgstr "新しいパスワード" + +msgid "New password confirmation" +msgstr "新しいパスワード(確認用)" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "元のパスワードが間違っています。もう一度入力してください。" + +msgid "Old password" +msgstr "元のパスワード" + +msgid "Password (again)" +msgstr "パスワード(確認用)" + +msgid "algorithm" +msgstr "アルゴリズム" + +msgid "iterations" +msgstr "イテレーション" + +msgid "salt" +msgstr "ソルト" + +msgid "hash" +msgstr "ハッシュ" + +msgid "variety" +msgstr "多様性" + +msgid "version" +msgstr "バージョン" + +msgid "memory cost" +msgstr "メモリーコスト" + +msgid "time cost" +msgstr "時間コスト" + +msgid "parallelism" +msgstr "並行性" + +msgid "work factor" +msgstr "ワークファクター" + +msgid "checksum" +msgstr "チェックサム" + +msgid "block size" +msgstr "ブロックサイズ" + +msgid "name" +msgstr "名前" + +msgid "content type" +msgstr "コンテンツタイプ" + +msgid "codename" +msgstr "コード名" + +msgid "permission" +msgstr "パーミッション" + +msgid "permissions" +msgstr "パーミッション" + +msgid "group" +msgstr "グループ" + +msgid "groups" +msgstr "グループ" + +msgid "superuser status" +msgstr "スーパーユーザー権限" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "全ての権限を持っているとみなされます。" + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"このユーザーが所属するグループ。ユーザーはそれぞれのグループに付与されたすべ" +"ての権限を持ちます。" + +msgid "user permissions" +msgstr "ユーザーパーミッション" + +msgid "Specific permissions for this user." +msgstr "このユーザーの持つ権限です。" + +msgid "username" +msgstr "ユーザー名" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"この項目は必須です。半角アルファベット、半角数字、@/./+/-/_ で150文字以下にし" +"てください。" + +msgid "A user with that username already exists." +msgstr "同じユーザー名が既に登録済みです。" + +msgid "first name" +msgstr "名" + +msgid "last name" +msgstr "姓" + +msgid "email address" +msgstr "メールアドレス" + +msgid "staff status" +msgstr "スタッフ権限" + +msgid "Designates whether the user can log into this admin site." +msgstr "ユーザーが管理サイトにログイン可能かどうかを示します。" + +msgid "active" +msgstr "有効" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"ユーザーがアクティブかどうかを示します。アカウントを削除する代わりに選択を解" +"除してください。" + +msgid "date joined" +msgstr "登録日" + +msgid "user" +msgstr "ユーザー" + +msgid "users" +msgstr "ユーザー" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "このパスワードは短すぎます。最低 %(min_length)d 文字以上必要です。" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "パスワードは最低 %(min_length)d 文字以上必要です。" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "このパスワードは %(verbose_name)s と似すぎています。" + +msgid "Your password can’t be too similar to your other personal information." +msgstr "あなたの他の個人情報と似ているパスワードにはできません。" + +msgid "This password is too common." +msgstr "このパスワードは一般的すぎます。" + +msgid "Your password can’t be a commonly used password." +msgstr "よく使われるパスワードにはできません。" + +msgid "This password is entirely numeric." +msgstr "このパスワードは数字しか使われていません。" + +msgid "Your password can’t be entirely numeric." +msgstr "数字だけのパスワードにはできません。" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "%(site_name)s のパスワードリセット" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"有効なユーザー名を入力してください。アクセント記号を除いた半角英数、 @/./+/-/" +"_ を使用できます。" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"有効なユーザー名を入力してください。半角英数、 @/./+/-/_ を使用できます。" + +msgid "Logged out" +msgstr "ログアウト" + +msgid "Password reset" +msgstr "パスワードをリセット" + +msgid "Password reset sent" +msgstr "パスワードリセットを送信しました" + +msgid "Enter new password" +msgstr "新しいパスワードを入力してください" + +msgid "Password reset unsuccessful" +msgstr "パスワードのリセットに失敗しました" + +msgid "Password reset complete" +msgstr "パスワードがリセットされました" + +msgid "Password change" +msgstr "パスワードの変更" + +msgid "Password change successful" +msgstr "パスワードを変更しました" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ka/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ka/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8a9eb52 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ka/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ka/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ka/LC_MESSAGES/django.po new file mode 100644 index 0000000..0a27602 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ka/LC_MESSAGES/django.po @@ -0,0 +1,302 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# André Bouatchidzé , 2013-2015 +# Demetre Barbakadze, 2023 +# Jannis Leidel , 2011 +# Tornike Beradze , 2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-12-04 08:09+0000\n" +"Last-Translator: Demetre Barbakadze, 2023\n" +"Language-Team: Georgian (http://app.transifex.com/django/django/language/" +"ka/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ka\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +msgid "Personal info" +msgstr "პირადი ინფორმაცია" + +msgid "Permissions" +msgstr "უფლებები" + +msgid "Important dates" +msgstr "მნიშვნელოვანი თარიღები" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(name)s ობიექტი პირველადი გასაღებით %(key)r არ არსებობს." + +msgid "Password changed successfully." +msgstr "პაროლი წარმატებით შეიცვალა." + +#, python-format +msgid "Change password: %s" +msgstr "შევცვალოთ პაროლი: %s" + +msgid "Authentication and Authorization" +msgstr "იდენტიფიკაცია და ავტორიზაცია" + +msgid "password" +msgstr "პაროლი" + +msgid "last login" +msgstr "ბოლო შესვლა" + +msgid "No password set." +msgstr "არ არის დაყენებული პაროლი." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "არასწორი პაროლის ფორმატი ან უცნობი ჰეშირების ალგორითმი." + +msgid "The two password fields didn’t match." +msgstr "ორი პაროლის ველი ერთმანეთს არ ემთხვევა" + +msgid "Password" +msgstr "პაროლი" + +msgid "Password confirmation" +msgstr "პაროლის დამოწმება" + +msgid "Enter the same password as before, for verification." +msgstr "გაიმეორეთ იგივე პაროლი ვერიფიკაციისთვის." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"გთხოვთ, შეიყვანოთ სწორი %(username)s და პაროლი. იქონიეთ მხედველობაში, რომ " +"ორივე ველი ითვალისწინებს მთავრულს." + +msgid "This account is inactive." +msgstr "თქვენი ანგარიში არააქტიურია." + +msgid "Email" +msgstr "ელ. ფოსტა" + +msgid "New password" +msgstr "ახალი პაროლი" + +msgid "New password confirmation" +msgstr "ახალი პაროლის დამოწმება" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "თქვენი ძველი პაროლი შეყვანილია არასწორად. გთხოვთ, შეიყვანოთ ხელახლა." + +msgid "Old password" +msgstr "ძველი პაროლი" + +msgid "Password (again)" +msgstr "პაროლი (განმეორებით)" + +msgid "algorithm" +msgstr "ალგორითმი" + +msgid "iterations" +msgstr "იტერაციები" + +msgid "salt" +msgstr "მარილი" + +msgid "hash" +msgstr "ჰეში" + +msgid "variety" +msgstr "მრავალფეროვნება" + +msgid "version" +msgstr "ვერსია" + +msgid "memory cost" +msgstr "საჭირო მეხსიერების რაოდენობა" + +msgid "time cost" +msgstr "საჭირო დროის რაოდენობა" + +msgid "parallelism" +msgstr "პარალელიზმი" + +msgid "work factor" +msgstr "სამუშაო ფაქტორი" + +msgid "checksum" +msgstr "საკონტროლო ჯამი" + +msgid "block size" +msgstr "" + +msgid "name" +msgstr "სახელი" + +msgid "content type" +msgstr "კონტენტის ტიპი" + +msgid "codename" +msgstr "კოდური სახელი" + +msgid "permission" +msgstr "უფლება" + +msgid "permissions" +msgstr "უფლებები" + +msgid "group" +msgstr "ჯგუფი" + +msgid "groups" +msgstr "ჯგუფები" + +msgid "superuser status" +msgstr "სუპერმომხმარებლის სტატუსი" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "განსაზღვრავს, რომ ამ მომხმარებელს აქვს ყველა უფლება." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"ჯგუფები, რომლებსაც მიეკუთვნება ეს მომხმარებელი. მომხმარებელი მიიღებს ყველა " +"უფლებას, რომელიც მინიჭებული აქვს მის თითოეულ ჯგუფს." + +msgid "user permissions" +msgstr "მომხმარებლის უფლებები" + +msgid "Specific permissions for this user." +msgstr "სპეციფიური უფლებები ამ მომხმარებლისთვის." + +msgid "username" +msgstr "მომხმარებლის სახელი" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"აუცილებელი. 150 სიმბოლ ან ნაკლები. მხოლოდ ასოები, ციფრები ან @/./+/-/_ ." + +msgid "A user with that username already exists." +msgstr "მომხმარებელი ამ სახელით უკვე არსებობს." + +msgid "first name" +msgstr "სახელი" + +msgid "last name" +msgstr "გვარი" + +msgid "email address" +msgstr "ელ. ფოსტის მისამართი" + +msgid "staff status" +msgstr "თანამშრომლობის სტატუსი" + +msgid "Designates whether the user can log into this admin site." +msgstr "" +"განსაზღვრავს, აქვს თუ არა მომხმარებელს ადმინისტრირების საიტზე შესვლის უფლება." + +msgid "active" +msgstr "აქტიურია" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"განსაზღვრავს, რომ მომხმარებელი გააქტიურებულია. მომხმარებლის წაშლის მაგივრად " +"გადანიშნეთ ეს დროშა." + +msgid "date joined" +msgstr "გაწევრიანების თარიღი" + +msgid "user" +msgstr "მომხმარებელი" + +msgid "users" +msgstr "მომხმარებლები" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"პაროლი ძალიან მოკლეა. მინიმუმ %(min_length)dსიმბოლოს უნდა შეიცავდეს." +msgstr[1] "" +"პაროლი ძალიან მოკლეა. მინიმუმ %(min_length)dსიმბოლოს უნდა შეიცავდეს." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +"პაროლი ძალიან მოკლეა. მინიმუმ %(min_length)d სიმბოლოს უნდა შეიცავდეს." +msgstr[1] "" +"პაროლი ძალიან მოკლეა. მინიმუმ %(min_length)d სიმბოლოს უნდა შეიცავდეს." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "პაროლი ძალიან გავს %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "პაროლი ძალიან გავს თქვენს პერსონალურ ინფორმაციას." + +msgid "This password is too common." +msgstr "ეს პაროლი ხშირად გამოიყენება." + +msgid "Your password can’t be a commonly used password." +msgstr "თქვენი პაროლი არ უნდა იყოს ხშირად გამოყენებადი." + +msgid "This password is entirely numeric." +msgstr "პაროლი მხოლოდ ციფრებისგან შედგება." + +msgid "Your password can’t be entirely numeric." +msgstr "თქვენი პაროლი არ შეიძლება შეიცავდეს მხოლოდ ციფრებს." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "პაროლის თავიდან დაყენება %(site_name)s-ზე" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "გამოსული ხართ" + +msgid "Password reset" +msgstr "პაროლის აღდგენა" + +msgid "Password reset sent" +msgstr "პაროლის აღდგენა გაგზავნილია" + +msgid "Enter new password" +msgstr "შეიყვანეთ ახალი პაროლი" + +msgid "Password reset unsuccessful" +msgstr "პაროლის აღდგენა წარუმატებლად დასრულდა" + +msgid "Password reset complete" +msgstr "პაროლის აღდგენა დასრულებულია" + +msgid "Password change" +msgstr "პაროლის შეცვლა" + +msgid "Password change successful" +msgstr "პაროლი წარმატებით შეიცვალა" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/kab/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/kab/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3333309 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/kab/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/kab/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/kab/LC_MESSAGES/django.po new file mode 100644 index 0000000..7456e93 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/kab/LC_MESSAGES/django.po @@ -0,0 +1,287 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-10-06 11:56+0000\n" +"Last-Translator: Muḥend Belqasem \n" +"Language-Team: Kabyle (http://www.transifex.com/django/django/language/" +"kab/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kab\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Talɣut tudmawant" + +msgid "Permissions" +msgstr "Tisirag" + +msgid "Important dates" +msgstr "Izemzen ixataren" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "" + +#, python-format +msgid "Change password: %s" +msgstr "Snifel awal uffir: %s" + +msgid "Authentication and Authorization" +msgstr "" + +msgid "password" +msgstr "awal uffir" + +msgid "last login" +msgstr "tuqqna taneggarut" + +msgid "No password set." +msgstr "" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" + +msgid "The two password fields didn't match." +msgstr "" + +msgid "Password" +msgstr "Awal n uɛeddi" + +msgid "Password confirmation" +msgstr "Asentem n wawal uffir" + +msgid "Enter the same password as before, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" + +msgid "This account is inactive." +msgstr "Amidan-agi ur yermid ara." + +msgid "Email" +msgstr "E-mail" + +msgid "New password" +msgstr "Awal uffir amaynut" + +msgid "New password confirmation" +msgstr "Asentem n wawal uffir amaynut" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" + +msgid "Old password" +msgstr "Awal uffir aqbuṛ" + +msgid "Password (again)" +msgstr "Mot de passe (bis)" + +msgid "algorithm" +msgstr "" + +msgid "iterations" +msgstr "" + +msgid "salt" +msgstr "" + +msgid "hash" +msgstr "" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "lqem" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "tasqamt n wakud" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "" + +msgid "checksum" +msgstr "" + +msgid "name" +msgstr "isem" + +msgid "content type" +msgstr "anaw n ugbur" + +msgid "codename" +msgstr "" + +msgid "permission" +msgstr "tasiregt" + +msgid "permissions" +msgstr "tisirag" + +msgid "group" +msgstr "agraw" + +msgid "groups" +msgstr "igrawen" + +msgid "superuser status" +msgstr "addad n unebdal" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Yemmal-d d akken aseqdac-agi ɣur-s akk tisirag war ma ttwanefkent-as s wudem " +"aflalay." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "tisirag n useqdac" + +msgid "Specific permissions for this user." +msgstr "" + +msgid "username" +msgstr "isem n useqdac" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "Tansa-agi imayl tella yakan." + +msgid "first name" +msgstr "isem" + +msgid "last name" +msgstr "Isem aneggaru" + +msgid "email address" +msgstr "tansa imayl" + +msgid "staff status" +msgstr "" + +msgid "Designates whether the user can log into this admin site." +msgstr "" + +msgid "active" +msgstr "urmid" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Yettwag ma yella aseqdac-agi yezmer ad yettwammel d urmid neɣ ala. Kkes " +"afran deg umḍiq n tukksa n umiḍan." + +msgid "date joined" +msgstr "azemz n ujerred" + +msgid "user" +msgstr "aseqdac" + +msgid "users" +msgstr "Iseqdaceniseqdacen" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "" + +msgid "Your password can't be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "" + +msgid "Your password can't be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "" + +msgid "Your password can't be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "Yeffeɣ" + +msgid "Password reset" +msgstr "Awennez n wawal uffir" + +msgid "Password reset sent" +msgstr "Tulsa n wennez n wawal uffir tettwazen" + +msgid "Enter new password" +msgstr "Sekcem awal n uffir amaynut" + +msgid "Password reset unsuccessful" +msgstr "tulsa n uwennez n wawal uffir tedda" + +msgid "Password reset complete" +msgstr "Awennez n wawal uffir yemmed" + +msgid "Password change" +msgstr "Abeddel n wawal uffir" + +msgid "Password change successful" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/kk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/kk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..49d95d9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/kk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/kk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/kk/LC_MESSAGES/django.po new file mode 100644 index 0000000..0710977 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/kk/LC_MESSAGES/django.po @@ -0,0 +1,285 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# yun_man_ger , 2011 +# Zhazira , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-09-24 14:24+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Kazakh (http://www.transifex.com/django/django/language/kk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kk\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +msgid "Personal info" +msgstr "Жеке мағлұмат" + +msgid "Permissions" +msgstr "Рұқсаттар" + +msgid "Important dates" +msgstr "Маңызды даталар" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "Құпия сөз ойдағыдай өзгертілді." + +#, python-format +msgid "Change password: %s" +msgstr "Құпия сөзді өзгерту: %s" + +msgid "Authentication and Authorization" +msgstr "" + +msgid "password" +msgstr "құпия сөз" + +msgid "last login" +msgstr "соңғы кіруі" + +msgid "No password set." +msgstr "" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" + +msgid "The two password fields didn't match." +msgstr "Енгізілген құпия сөздер бірдей емес." + +msgid "Password" +msgstr "Құпия сөз" + +msgid "Password confirmation" +msgstr "Құпия сөз құптамасы" + +msgid "Enter the same password as before, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" + +msgid "This account is inactive." +msgstr "Бұл тіркелгі белсенді емес." + +msgid "Email" +msgstr "" + +msgid "New password" +msgstr "Жаңа құпия сөз" + +msgid "New password confirmation" +msgstr "Жаңа құпия сөз құптамасы" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Ескі құпия сөз қате енгізілді. Қайтадан енгізіңіз." + +msgid "Old password" +msgstr "Ескі құпия сөз" + +msgid "Password (again)" +msgstr "Құпия сөз (қайтадан)" + +msgid "algorithm" +msgstr "" + +msgid "iterations" +msgstr "" + +msgid "salt" +msgstr "" + +msgid "hash" +msgstr "" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "" + +msgid "checksum" +msgstr "" + +msgid "name" +msgstr "атау" + +msgid "content type" +msgstr "" + +msgid "codename" +msgstr "кодтық атау" + +msgid "permission" +msgstr "рұқсат" + +msgid "permissions" +msgstr "рұқсаттар" + +msgid "group" +msgstr "топ" + +msgid "groups" +msgstr "топтар" + +msgid "superuser status" +msgstr "әкімші мәртебесі" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "Бұл қолданушының бүкіл рұқсаттарымен тағайындалатындығын білдіреді." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "қолданушы рұқсаттары" + +msgid "Specific permissions for this user." +msgstr "" + +msgid "username" +msgstr "Қолданушы атауы" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "Осындай атаумен қолданушы бар." + +msgid "first name" +msgstr "аты" + +msgid "last name" +msgstr "жөні" + +msgid "email address" +msgstr "" + +msgid "staff status" +msgstr "қызметкер мәртебесі" + +msgid "Designates whether the user can log into this admin site." +msgstr "Қолданушының басқарушы сайтына кіре алатындығын білдіреді." + +msgid "active" +msgstr "белсенді" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Қолданушы белсенді болуын білдіреді. Тіркілгіні өшірмей мынаны алып тастаңыз." + +msgid "date joined" +msgstr "тіркелген күн-айы" + +msgid "user" +msgstr "қолданушы" + +msgid "users" +msgstr "қолданушылар" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "" + +msgid "Your password can't be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "" + +msgid "Your password can't be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "" + +msgid "Your password can't be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "%(site_name)s торапта құпия сөзді өзгерту" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "Шығу орындалды" + +msgid "Password reset" +msgstr "" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "" + +msgid "Password reset unsuccessful" +msgstr "" + +msgid "Password reset complete" +msgstr "" + +msgid "Password change" +msgstr "" + +msgid "Password change successful" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/km/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/km/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1628754 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/km/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/km/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/km/LC_MESSAGES/django.po new file mode 100644 index 0000000..26beb5a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/km/LC_MESSAGES/django.po @@ -0,0 +1,281 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-09-24 14:24+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Khmer (http://www.transifex.com/django/django/language/km/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: km\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Personal info" +msgstr "ព័ត៌មានផ្ទាល់ខ្លួន" + +msgid "Permissions" +msgstr "ការអនុញ្ញាត" + +msgid "Important dates" +msgstr "កាលបរិច្ឆេទសំខាន់" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "" + +#, python-format +msgid "Change password: %s" +msgstr "" + +msgid "Authentication and Authorization" +msgstr "" + +msgid "password" +msgstr "ពាក្យសំងាត់" + +msgid "last login" +msgstr "ការពិនិត្យចូលកន្លងមក" + +msgid "No password set." +msgstr "" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" + +msgid "The two password fields didn't match." +msgstr "" + +msgid "Password" +msgstr "ពាក្យសំងាត់" + +msgid "Password confirmation" +msgstr "" + +msgid "Enter the same password as before, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" + +msgid "This account is inactive." +msgstr "ឈ្មោះសមាជិកនេះ​លែងដំណើរការ" + +msgid "Email" +msgstr "" + +msgid "New password" +msgstr "" + +msgid "New password confirmation" +msgstr "" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" + +msgid "Old password" +msgstr "" + +msgid "Password (again)" +msgstr "ពាក្យសំងាត់ (ម្តងទៀត)" + +msgid "algorithm" +msgstr "" + +msgid "iterations" +msgstr "" + +msgid "salt" +msgstr "" + +msgid "hash" +msgstr "" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "" + +msgid "checksum" +msgstr "" + +msgid "name" +msgstr "ឈ្មោះ" + +msgid "content type" +msgstr "" + +msgid "codename" +msgstr "ឈ្មោះលេខកូត" + +msgid "permission" +msgstr "អនុញ្ញាត" + +msgid "permissions" +msgstr "អនុញ្ញាត" + +msgid "group" +msgstr "ក្រុម" + +msgid "groups" +msgstr "ក្រុម" + +msgid "superuser status" +msgstr "ស្ថានភាពអ្នកគ្រងគ្រង" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "កំណត់អោយសមាជិកនេះមានសិទ្ធិទាំងអស់។" + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "ការអនុញ្ញាតអោយសមាជិក" + +msgid "Specific permissions for this user." +msgstr "" + +msgid "username" +msgstr "ឈ្មោះជាសមាជិក" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "" + +msgid "first name" +msgstr "នាម" + +msgid "last name" +msgstr "គោត្តនាម" + +msgid "email address" +msgstr "" + +msgid "staff status" +msgstr "ស្ថានភាពបុគ្គលិក" + +msgid "Designates whether the user can log into this admin site." +msgstr "កំណត់អោយសមាជិកអាចចូលមកប្រើប្រាស់ទំព័រគ្រប់គ្រងនេះ។" + +msgid "active" +msgstr "សកម្ម" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" + +msgid "date joined" +msgstr "កាលបរិច្ឆេទចូលរួម" + +msgid "user" +msgstr "សមាជិក" + +msgid "users" +msgstr "សមាជិក" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "" + +msgid "Your password can't be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "" + +msgid "Your password can't be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "" + +msgid "Your password can't be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "ចាកចេញ" + +msgid "Password reset" +msgstr "" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "" + +msgid "Password reset unsuccessful" +msgstr "" + +msgid "Password reset complete" +msgstr "" + +msgid "Password change" +msgstr "" + +msgid "Password change successful" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/kn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/kn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..be5a6de Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/kn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/kn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/kn/LC_MESSAGES/django.po new file mode 100644 index 0000000..e24561e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/kn/LC_MESSAGES/django.po @@ -0,0 +1,285 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# karthikbgl , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-09-24 14:24+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Kannada (http://www.transifex.com/django/django/language/" +"kn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kn\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Personal info" +msgstr "ವೈಯುಕ್ತಿಕ ಮಾಹಿತಿ" + +msgid "Permissions" +msgstr "ಅನುಮತಿಗಳು" + +msgid "Important dates" +msgstr "ಮಹತ್ವದ ದಿನಾಂಕಗಳು" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "ಪಾಸ್ವರ್ಡ್ ಸಫಲವಾಗಿ ಬದಲಾಯಿಸಲಾಯಿತು" + +#, python-format +msgid "Change password: %s" +msgstr "ಪಾಸ್ವರ್ಡ್ ಬದಲಾಯಿಸಲು: %s" + +msgid "Authentication and Authorization" +msgstr "" + +msgid "password" +msgstr "ಪ್ರವೇಶಪದ" + +msgid "last login" +msgstr "ಕಡೇ ಸಾರಿ ಒಳಬಂದದ್ದು" + +msgid "No password set." +msgstr "" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" + +msgid "The two password fields didn't match." +msgstr "ಎರಡು ಪ್ರವೇಶಪದ ಕ್ಷೇತ್ರಗಳ ಹೊಂದಿಕೆಯಾಗುತ್ತಿಲ್ಲ" + +msgid "Password" +msgstr "ಪ್ರವೇಶಪದ" + +msgid "Password confirmation" +msgstr "ಪಾಸ್ವರ್ಡ್ ಖಚಿತತೆ" + +msgid "Enter the same password as before, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" + +msgid "This account is inactive." +msgstr "ಈ ಖಾತೆಯು ನಿಷ್ಕ್ರಿಯವಾಗಿದೆ" + +msgid "Email" +msgstr "" + +msgid "New password" +msgstr "ಹೊಸ ಪ್ರವೇಶಪದ" + +msgid "New password confirmation" +msgstr "ಹೊಸ ಪ್ರವೇಶಪದ ಖಚಿತತೆ" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "ನಿಮ್ಮ ಹಳೆಯ ಪ್ರವೇಶಪದ ತಪ್ಪಾಗಿ ಪ್ರವೇಶಿಸಲಾಗಿದೆ ಮತ್ತೆ ದಯವಿಟ್ಟು ನಮೂದಿಸಿ" + +msgid "Old password" +msgstr "ಹಳೆಯ ಪ್ರವೇಶಪದ" + +msgid "Password (again)" +msgstr "ಪ್ರವೇಶಪದ(ಇನ್ನೊಮ್ಮೆ)" + +msgid "algorithm" +msgstr "" + +msgid "iterations" +msgstr "" + +msgid "salt" +msgstr "" + +msgid "hash" +msgstr "" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "" + +msgid "checksum" +msgstr "" + +msgid "name" +msgstr "ಹೆಸರು" + +msgid "content type" +msgstr "" + +msgid "codename" +msgstr "ಸಾಂಕೇತಿಕ ಹೆಸರು" + +msgid "permission" +msgstr "ಅನುಮತಿ" + +msgid "permissions" +msgstr "ಅನುಮತಿಗಳು" + +msgid "group" +msgstr "ಗುಂಪು" + +msgid "groups" +msgstr "ಗುಂಪುಗಳು" + +msgid "superuser status" +msgstr "ಮಹಾಬಳಕೆದಾರನ ಸ್ಧಿತಿ" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"ಈ ಸದಸ್ಯರು ಸುವ್ಯಕ್ತವಾಗಿ ನೀಡದಿದ್ದರೂ ಎಲ್ಲಾ ಅನುಮತಿಗಳನ್ನು ಪಡೆದಿರುವರು ಎಂಬುದನ್ನು " +"ಸೂಚಿಸುತ್ತದೆ." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "ಬಳಕೆದಾರ ಅನುಮತಿಗಳು" + +msgid "Specific permissions for this user." +msgstr "" + +msgid "username" +msgstr "ಬಳಕೆದಾರ-ಹೆಸರು" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "ಆ ಬಳಕೆದಾರಹೆಸರು ಒಂದು ಬಳಕೆದಾರ ಈಗಾಗಲೇ ಅಸ್ತಿತ್ವದಲ್ಲಿದೆ." + +msgid "first name" +msgstr "ಮೊದಲ ಹೆಸರು" + +msgid "last name" +msgstr "ಕೊನೆಯ ಹೆಸರು" + +msgid "email address" +msgstr "" + +msgid "staff status" +msgstr "ಸಿಬ್ಬಂದಿ ಸ್ಥಿತಿ" + +msgid "Designates whether the user can log into this admin site." +msgstr "ಬಲಕೆದಾರರು ಈ ಆಡಳಿತ ತಾಣಕ್ಕೆ ಪ್ರವೇಶಪಡೆಯಬಹುದೇ ಎಂಬುದನ್ನು ತಿಳಿಸುತ್ತದೆ." + +msgid "active" +msgstr "ಸಕ್ರಿಯ" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" + +msgid "date joined" +msgstr "ಸೇರಿದ ದಿನಾಂಕ" + +msgid "user" +msgstr "ಬಳಕೆದಾರ" + +msgid "users" +msgstr "ಬಳಕೆದಾರರು" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "" + +msgid "Your password can't be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "" + +msgid "Your password can't be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "" + +msgid "Your password can't be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "ಹೊರಬರಲಾಗಿದೆ" + +msgid "Password reset" +msgstr "" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "" + +msgid "Password reset unsuccessful" +msgstr "" + +msgid "Password reset complete" +msgstr "" + +msgid "Password change" +msgstr "" + +msgid "Password change successful" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ko/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ko/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a3422c6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ko/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ko/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ko/LC_MESSAGES/django.po new file mode 100644 index 0000000..689a045 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ko/LC_MESSAGES/django.po @@ -0,0 +1,309 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bumsoo Kim , 2017 +# Churow Park , 2020 +# Jiyoon, Ha , 2016 +# DaHae Sung , 2016 +# 코딩 영, 2021 +# Geonho Kim / Leo Kim , 2019 +# Ian Y. Choi , 2015 +# Jannis Leidel , 2011 +# Le Tartuffe , 2014,2016 +# Jiyoon, Ha , 2016 +# JunGu Kang , 2015 +# Kagami Sascha Rosylight , 2017 +# minsung kang, 2015 +# Seoeun(Sun☀️) Hong, 2023 +# Woo-Jing, Seok , 2016 +# seungho, kim , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-12-04 08:09+0000\n" +"Last-Translator: Seoeun(Sun☀️) Hong, 2023\n" +"Language-Team: Korean (http://app.transifex.com/django/django/language/ko/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ko\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Personal info" +msgstr "개인정보" + +msgid "Permissions" +msgstr "권한" + +msgid "Important dates" +msgstr "중요한 일정" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "Primary key %(key)r인 개체 %(name)s이/가 존재하지 않습니다." + +msgid "Password changed successfully." +msgstr "비밀번호가 변경되었습니다." + +#, python-format +msgid "Change password: %s" +msgstr "비밀번호 변경: %s" + +msgid "Authentication and Authorization" +msgstr "인증 및 권한" + +msgid "password" +msgstr "비밀번호" + +msgid "last login" +msgstr "마지막 로그인" + +msgid "No password set." +msgstr "비밀번호가 설정되지 않습니다." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "잘못된 비밀번호 형식이거나 알 수 없는 해싱 알고리즘 입니다." + +msgid "The two password fields didn’t match." +msgstr "비밀번호가 일치하지 않습니다." + +msgid "Password" +msgstr "비밀번호" + +msgid "Password confirmation" +msgstr "비밀번호 확인" + +msgid "Enter the same password as before, for verification." +msgstr "확인을 위해 이전과 동일한 비밀번호를 입력하세요. " + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"원본 비밀번호는 저장되지 않으므로, 해당 사용자의 비밀번호를 확인할 수 없습니" +"다. 다만 이 폼을 사용하여 비밀번호를 변경할 수 있습니다." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"올바른 %(username)s와/과 비밀번호를 입력하십시오. 두 필드 모두 대문자와 소문" +"자를 구별합니다." + +msgid "This account is inactive." +msgstr "이 계정은 유효하지 않습니다." + +msgid "Email" +msgstr "이메일" + +msgid "New password" +msgstr "새 비밀번호" + +msgid "New password confirmation" +msgstr "새 비밀번호 (확인)" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "기존 비밀번호를 잘못 입력하셨습니다. 다시 입력해 주세요." + +msgid "Old password" +msgstr "기존 비밀번호" + +msgid "Password (again)" +msgstr "비밀번호 (확인)" + +msgid "algorithm" +msgstr "알고리즘" + +msgid "iterations" +msgstr "반복" + +msgid "salt" +msgstr "솔트" + +msgid "hash" +msgstr "해시" + +msgid "variety" +msgstr "종류" + +msgid "version" +msgstr "버젼" + +msgid "memory cost" +msgstr "메모리 비용" + +msgid "time cost" +msgstr "시간비용" + +msgid "parallelism" +msgstr "병행" + +msgid "work factor" +msgstr "워크 팩터" + +msgid "checksum" +msgstr "체크섬" + +msgid "block size" +msgstr "블록 크기" + +msgid "name" +msgstr "이름" + +msgid "content type" +msgstr "콘텐츠 타입" + +msgid "codename" +msgstr "코드명" + +msgid "permission" +msgstr "허가" + +msgid "permissions" +msgstr "허가" + +msgid "group" +msgstr "그룹" + +msgid "groups" +msgstr "그룹" + +msgid "superuser status" +msgstr "최상위 사용자 권한" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "해당 사용자에게 모든 권한을 허가합니다." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"이 사용자가 속한 그룹. 사용자는 그룹에 부여된 모든 권한을 물려 받습니다." + +msgid "user permissions" +msgstr "사용자 권한" + +msgid "Specific permissions for this user." +msgstr "이 사용자를 위한 특정 권한." + +msgid "username" +msgstr "사용자 이름" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "150자 이하 문자, 숫자 그리고 @/./+/-/_만 가능합니다." + +msgid "A user with that username already exists." +msgstr "해당 사용자 이름은 이미 존재합니다." + +msgid "first name" +msgstr "이름" + +msgid "last name" +msgstr "성" + +msgid "email address" +msgstr "이메일 주소" + +msgid "staff status" +msgstr "스태프 권한" + +msgid "Designates whether the user can log into this admin site." +msgstr "사용자가 관리사이트에 로그인이 가능한지를 나타냅니다." + +msgid "active" +msgstr "활성" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"이 사용자가 활성화되어 있는지를 나타냅니다. 계정을 삭제하는 대신 이것을 선택 " +"해제하세요." + +msgid "date joined" +msgstr "등록일" + +msgid "user" +msgstr "사용자" + +msgid "users" +msgstr "사용자(들)" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"비밀번호가 너무 짧습니다. 최소 %(min_length)d 문자를 포함해야 합니다." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "비밀번호는 최소 %(min_length)d자 이상이어야 합니다." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "비밀번호가 %(verbose_name)s와 너무 유사합니다." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "다른 개인 정보와 유사한 비밀번호는 사용할 수 없습니다." + +msgid "This password is too common." +msgstr "비밀번호가 너무 일상적인 단어입니다." + +msgid "Your password can’t be a commonly used password." +msgstr "통상적으로 자주 사용되는 비밀번호는 사용할 수 없습니다." + +msgid "This password is entirely numeric." +msgstr "비밀번호가 전부 숫자로 되어 있습니다." + +msgid "Your password can’t be entirely numeric." +msgstr "숫자로만 이루어진 비밀번호는 사용할 수 없습니다." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "%(site_name)s의 비밀번호 재설정" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"유효한 사용자명을 입력하세요. 영문자나 숫자, @/./+/-/_기호만 가능합니다." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"유효한 사용자 이름을 입력하세요. 이곳에는 문자, 숫자, @/./+/-/_만 가능합니다." + +msgid "Logged out" +msgstr "로그아웃" + +msgid "Password reset" +msgstr "비밀번호 초기화" + +msgid "Password reset sent" +msgstr "새 비밀번호가 전송되었습니다." + +msgid "Enter new password" +msgstr "새 비밀번호 입력" + +msgid "Password reset unsuccessful" +msgstr "비밀번호 초기화를 실패하였습니다." + +msgid "Password reset complete" +msgstr "비밀번호가 초기화 완료" + +msgid "Password change" +msgstr "비밀번호 변경" + +msgid "Password change successful" +msgstr "비밀번호를 변경하였습니다." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ky/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ky/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7742edd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ky/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ky/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ky/LC_MESSAGES/django.po new file mode 100644 index 0000000..2c6a640 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ky/LC_MESSAGES/django.po @@ -0,0 +1,299 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Soyuzbek Orozbek uulu , 2020-2021 +# Soyuzbek Orozbek uulu , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2021-11-27 14:11+0000\n" +"Last-Translator: Soyuzbek Orozbek uulu \n" +"Language-Team: Kyrgyz (http://www.transifex.com/django/django/language/ky/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ky\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Personal info" +msgstr "Өздүк маалымат" + +msgid "Permissions" +msgstr "Жеткилер" + +msgid "Important dates" +msgstr "Маанилүү күндөр" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "ID%(key)r болгон %(name)s табылган жок." + +msgid "Password changed successfully." +msgstr "Сырсөз ийгиликтүү өзгөрдү." + +#, python-format +msgid "Change password: %s" +msgstr "сырсөздү өзгөрт: %s" + +msgid "Authentication and Authorization" +msgstr "Катталуу жана жетки алуу" + +msgid "password" +msgstr "сырсөз" + +msgid "last login" +msgstr "акыркы кирүү" + +msgid "No password set." +msgstr "сырсөз жок." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Туура эмес сырсөз калыбы же белгисиз бекитүү алгоритми" + +msgid "The two password fields didn’t match." +msgstr "Сырсөздүн эки талаасы бири бирине окшош болбой жатат." + +msgid "Password" +msgstr "Сырсөз" + +msgid "Password confirmation" +msgstr "Сырсөз тастыктоосу" + +msgid "Enter the same password as before, for verification." +msgstr "Тастыктоо үчүн жогоруга окшош сырсөз тер." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Сырсөздөр кам түрүндө сакталбайт, мындан улам сиз аны эч качан көрө " +"албайсыз. Бирок аны сиз бул формду колдонуп өзгөртсөңүз " +"болот." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Туура %(username)s жана сырсөз тер. Алар экөө тең СезГичТүү болушу мүмкүн." + +msgid "This account is inactive." +msgstr "Бул эсеп жанык эмес." + +msgid "Email" +msgstr "экат" + +msgid "New password" +msgstr "Жаңы сырсөз" + +msgid "New password confirmation" +msgstr "Жаңы сырсөз тастыктоосу" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Сиздин эски сырсөзүңүз туура эмес терилди. Кайрадан териңиз." + +msgid "Old password" +msgstr "Эски сырсөз" + +msgid "Password (again)" +msgstr "сырсөз (кайра)" + +msgid "algorithm" +msgstr "алгоритм" + +msgid "iterations" +msgstr "аттоолор" + +msgid "salt" +msgstr "туз" + +msgid "hash" +msgstr "бекитүү" + +msgid "variety" +msgstr "тууралык" + +msgid "version" +msgstr "муун" + +msgid "memory cost" +msgstr "эс баасы" + +msgid "time cost" +msgstr "убакыт баасы" + +msgid "parallelism" +msgstr "удаалык" + +msgid "work factor" +msgstr "жумуш фактору" + +msgid "checksum" +msgstr "текшерүү" + +msgid "block size" +msgstr "блок өлчөмү" + +msgid "name" +msgstr "аты" + +msgid "content type" +msgstr "мазмун түрү" + +msgid "codename" +msgstr "кодаты" + +msgid "permission" +msgstr "жетки" + +msgid "permissions" +msgstr "жеткилер" + +msgid "group" +msgstr "тайпа" + +msgid "groups" +msgstr "тайпалар" + +msgid "superuser status" +msgstr "супер колдонуучу акыбалы" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "Бул колдонуучуга бүт жеткилер берилишин көмүскө түрдө аныктайт." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Колдонуучунун тиешелүү болгон тайпасы. Колдонуучу тайпасына берилген бүт " +"жеткилерге ээ болот." + +msgid "user permissions" +msgstr "колдонуучу жеткиси" + +msgid "Specific permissions for this user." +msgstr "Бул колдонуучу үчүн кээ бир жеткилер" + +msgid "username" +msgstr "колдонуучу аты" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "Талап кылынат. 150 же аз арип, сан жана @/./+/-/_ лар гана." + +msgid "A user with that username already exists." +msgstr "Бул колдонуучу аты мурдатан эле бар" + +msgid "first name" +msgstr "аты" + +msgid "last name" +msgstr "атасынын аты" + +msgid "email address" +msgstr "эдарек" + +msgid "staff status" +msgstr "кызматкер статусу" + +msgid "Designates whether the user can log into this admin site." +msgstr "Колдонуучу башкаруу сайтына киришин же кире албашын дайындайт." + +msgid "active" +msgstr "жанык" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Бул колдонуучунун активдүүлүгүн дайындайт. Бул аккаунтту өчүрүү үчүн бул " +"жердеги тандоону алып салыңыз." + +msgid "date joined" +msgstr "кошулуу күнү" + +msgid "user" +msgstr "колдонуучу" + +msgid "users" +msgstr "колдонуучулар" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Бул сырсөз өтө эле кыска. Ал өзүнө жок дегенде %(min_length)d символ камтышы " +"керек." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Сиздин сырсөз жок дегенде %(min_length)d символ камтышы керек." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Сырсөз жана %(verbose_name)s өтө эле окшош." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Сиздин сырсөз башка жеке маалыматыңызга окшош болбоосу керек." + +msgid "This password is too common." +msgstr "Бул сырсөз өтө эле жалпы" + +msgid "Your password can’t be a commonly used password." +msgstr "Сиздин сырсөз өтө эле жалпы колдонуудагы сырсөз болбоосу керек." + +msgid "This password is entirely numeric." +msgstr "Бул сырсөз жалаң сандан турат." + +msgid "Your password can’t be entirely numeric." +msgstr "Сиздин сырсөз жалаң эле сандардан турбашы керек." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "%(site_name)s дан сырсөздү жокко чыгырыңыз" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"Туура колдонуучу атын киргизиңиз. Бул маани жалаң латын арибин, сан жана @/./" +"+/-/_ белгилерин камтый алат." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Туура колдонуучу атын киргизиңиз. Бул маани жалаң арип, сан жана @/./+/-/_ " +"белгилерин камтый алат." + +msgid "Logged out" +msgstr "Катталып чыкты" + +msgid "Password reset" +msgstr "Сырсөдү жокко чыгаруу" + +msgid "Password reset sent" +msgstr "Сырсөз жок кылууга жөнөтүлдү" + +msgid "Enter new password" +msgstr "Жаңы сырсөз киргиз" + +msgid "Password reset unsuccessful" +msgstr "Сырсөздү жокко чыгаруу ийгиликсиз" + +msgid "Password reset complete" +msgstr "Сырсөздү жокко чыгаруу аяктады" + +msgid "Password change" +msgstr "Сырсөз өзгөртүү" + +msgid "Password change successful" +msgstr "Сырсөздү жокко чыгаруу ийгиликтүү" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/lb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/lb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3adcc2c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/lb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/lb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/lb/LC_MESSAGES/django.po new file mode 100644 index 0000000..382e9e8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/lb/LC_MESSAGES/django.po @@ -0,0 +1,226 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-03-18 09:16+0100\n" +"PO-Revision-Date: 2015-03-18 10:30+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Luxembourgish (http://www.transifex.com/projects/p/django/" +"language/lb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "" + +msgid "Permissions" +msgstr "" + +msgid "Important dates" +msgstr "" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "" + +#, python-format +msgid "Change password: %s" +msgstr "" + +msgid "Authentication and Authorization" +msgstr "" + +msgid "No password set." +msgstr "" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" + +msgid "The two password fields didn't match." +msgstr "" + +msgid "Password" +msgstr "" + +msgid "Password confirmation" +msgstr "" + +msgid "Enter the same password as above, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this " +"form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" + +msgid "This account is inactive." +msgstr "" + +msgid "Email" +msgstr "" + +msgid "New password" +msgstr "" + +msgid "New password confirmation" +msgstr "" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" + +msgid "Old password" +msgstr "" + +msgid "Password (again)" +msgstr "" + +msgid "algorithm" +msgstr "" + +msgid "iterations" +msgstr "" + +msgid "salt" +msgstr "" + +msgid "hash" +msgstr "" + +msgid "work factor" +msgstr "" + +msgid "checksum" +msgstr "" + +msgid "name" +msgstr "" + +msgid "codename" +msgstr "" + +msgid "permission" +msgstr "" + +msgid "permissions" +msgstr "" + +msgid "group" +msgstr "" + +msgid "groups" +msgstr "" + +msgid "password" +msgstr "" + +msgid "last login" +msgstr "" + +msgid "superuser status" +msgstr "" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "" + +msgid "Specific permissions for this user." +msgstr "" + +msgid "username" +msgstr "" + +msgid "Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers and @/./" +"+/-/_ characters." +msgstr "" + +msgid "A user with that username already exists." +msgstr "" + +msgid "first name" +msgstr "" + +msgid "last name" +msgstr "" + +msgid "email address" +msgstr "" + +msgid "staff status" +msgstr "" + +msgid "Designates whether the user can log into this admin site." +msgstr "" + +msgid "active" +msgstr "" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" + +msgid "date joined" +msgstr "" + +msgid "user" +msgstr "" + +msgid "users" +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "" + +msgid "Logged out" +msgstr "" + +msgid "Password reset" +msgstr "" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "" + +msgid "Password reset unsuccessful" +msgstr "" + +msgid "Password reset complete" +msgstr "" + +msgid "Password change" +msgstr "" + +msgid "Password change successful" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/lt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/lt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..fd83d5d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/lt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/lt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/lt/LC_MESSAGES/django.po new file mode 100644 index 0000000..5bc0c45 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/lt/LC_MESSAGES/django.po @@ -0,0 +1,320 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# lauris , 2011 +# Matas Dailyda , 2015-2017 +# naktinis , 2012 +# Nikolajus Krauklis , 2013 +# Simonas Kazlauskas , 2012-2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-11-16 08:45+0000\n" +"Last-Translator: Matas Dailyda \n" +"Language-Team: Lithuanian (http://www.transifex.com/django/django/language/" +"lt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lt\n" +"Plural-Forms: nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < " +"11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? " +"1 : n % 1 != 0 ? 2: 3);\n" + +msgid "Personal info" +msgstr "Asmeninė informacija" + +msgid "Permissions" +msgstr "Leidimai" + +msgid "Important dates" +msgstr "Svarbios datos" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "Įrašas %(name)s su pirminiu raktu %(key)r neegzistuoja." + +msgid "Password changed successfully." +msgstr "Slaptažodis pakeistas sėkmingai." + +#, python-format +msgid "Change password: %s" +msgstr "Pakeisti slaptažodį: %s" + +msgid "Authentication and Authorization" +msgstr "Autentifikacija ir įgaliojimai" + +msgid "password" +msgstr "slaptažodis" + +msgid "last login" +msgstr "paskutinį kartą prisijungęs" + +msgid "No password set." +msgstr "Slaptažodis nenustatytas" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Neteisingas slaptažodžio formatas arba nežinomas maišos algoritmas." + +msgid "The two password fields didn't match." +msgstr "Slaptažodžio laukai nesutapo" + +msgid "Password" +msgstr "Slaptažodis" + +msgid "Password confirmation" +msgstr "Slaptažodžio patvirtinimas" + +msgid "Enter the same password as before, for verification." +msgstr "Patikrinimui įveskite tokį patį slaptažodį, kaip anksčiau." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" +"Neužkoduoti slaptažodžiai nėra saugomi, todėl galimybės pasižiūrėti šio " +"vartotojo slaptažodį nėra, bet galite slaptažodį pakeisti naudodamiesi šia forma." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Įveskite teisingą %(username)s ir slaptažodį. Abiejuose laukuose didžiosios " +"mažosios raidės skiriasi." + +msgid "This account is inactive." +msgstr "Ši paskyra yra neaktyvi." + +msgid "Email" +msgstr "El. paštas" + +msgid "New password" +msgstr "Naujas slaptažodis" + +msgid "New password confirmation" +msgstr "Naujo slaptažodžio patvirtinimas" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Blogai įvestas senas slaptažodis. Bandykite dar kartą." + +msgid "Old password" +msgstr "Senas slaptažodis" + +msgid "Password (again)" +msgstr "Slaptažodis (dar kartą)" + +msgid "algorithm" +msgstr "algoritmas" + +msgid "iterations" +msgstr "iteracijos" + +msgid "salt" +msgstr "druska" + +msgid "hash" +msgstr "maiša" + +msgid "variety" +msgstr "įvairovė" + +msgid "version" +msgstr "versija" + +msgid "memory cost" +msgstr "atminties sąnaudos" + +msgid "time cost" +msgstr "laiko sąnaudos" + +msgid "parallelism" +msgstr "paralelizmas" + +msgid "work factor" +msgstr "darbo faktorius" + +msgid "checksum" +msgstr "kontrolinė suma" + +msgid "name" +msgstr "vardas" + +msgid "content type" +msgstr "turinio tipas" + +msgid "codename" +msgstr "kodinis vardas" + +msgid "permission" +msgstr "leidimas" + +msgid "permissions" +msgstr "leidimai" + +msgid "group" +msgstr "grupė" + +msgid "groups" +msgstr "grupės" + +msgid "superuser status" +msgstr "supervartotojo statusas" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "Pažymi, kad šis vartotojas turi visas teises be specialių nustatymų." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Grupės, kurioms šis vartotojas priklauso. Vartotojas gaus visas teises, " +"kurios yra suteiktos jo grupėms." + +msgid "user permissions" +msgstr "vartotojo leidimai" + +msgid "Specific permissions for this user." +msgstr "Specifiniai šio vartotojo leidimai." + +msgid "username" +msgstr "vartotojo vardas" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Privalomas. 150 arba mažiau simbolių. Raidės, skaičiai bei @/./+/-/_ " +"simboliai." + +msgid "A user with that username already exists." +msgstr "Jau egzistuoja vartotojas su tokiu vardu." + +msgid "first name" +msgstr "vardas" + +msgid "last name" +msgstr "pavardė" + +msgid "email address" +msgstr "El. pašto adresas" + +msgid "staff status" +msgstr "personalo statusas" + +msgid "Designates whether the user can log into this admin site." +msgstr "Nurodo ar vartotojas gali prisijungti prie administravimo puslapio." + +msgid "active" +msgstr "aktyvus" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Nurodo ar vartotojas yra aktyvuotas. Užuot pašalinę vartotoją, galite nuimti " +"šią žymę." + +msgid "date joined" +msgstr "data, kada prisijungė" + +msgid "user" +msgstr "vartotojas" + +msgid "users" +msgstr "vartotojai" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Šis slaptažodis yra per trumpas. Jį turi sudaryti bent %(min_length)d " +"simbolis." +msgstr[1] "" +"Šis slaptažodis yra per trumpas. Jį turi sudaryti bent %(min_length)d " +"simboliai." +msgstr[2] "" +"Šis slaptažodis yra per trumpas. Jį turi sudaryti bent %(min_length)d " +"simbolių." +msgstr[3] "" +"Šis slaptažodis yra per trumpas. Jį turi sudaryti bent %(min_length)d " +"simbolių." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Jūsų slaptažodį turi sudaryti bent %(min_length)d simbolis." +msgstr[1] "Jūsų slaptažodį turi sudaryti bent %(min_length)d simboliai." +msgstr[2] "Jūsų slaptažodį turi sudaryti bent %(min_length)d simbolių." +msgstr[3] "Jūsų slaptažodį turi sudaryti bent %(min_length)d simbolių." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Slaptažodis pernelyg panašus į %(verbose_name)s." + +msgid "Your password can't be too similar to your other personal information." +msgstr "" +"Jūsų slaptažodis negali būti pernelyg panašus į kitą jūsų asmeninę " +"informaciją." + +msgid "This password is too common." +msgstr "Šis slaptažodis yra per dažnai pasitaikantis." + +msgid "Your password can't be a commonly used password." +msgstr "Jūsų slaptažodis negali būti dažnai naudojamu slaptažodžiu." + +msgid "This password is entirely numeric." +msgstr "Šis slaptažodis sudarytas tik iš skaitmenų." + +msgid "Your password can't be entirely numeric." +msgstr "Jūsų slaptažodis negali būti sudarytas tik iš skaitmenų." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Slaptažodis atkurtas ant %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"Įveskite korektišką vartotojo vardą. Ši reikšmė gali turėti tik angliško " +"alfabeto raides, skaičius ir @/./+/-/_ simbolius." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Įveskite korektišką vartotojo vardą. Ši reikšmė gali turėti tik raides, " +"skaičius ir @/./+/-/_ simbolius." + +msgid "Logged out" +msgstr "Atsijungęs" + +msgid "Password reset" +msgstr "Slaptažodžio atstatymas" + +msgid "Password reset sent" +msgstr "Slaptažodžio atstatymas išsiųstas" + +msgid "Enter new password" +msgstr "Įveskite naują slaptažodį" + +msgid "Password reset unsuccessful" +msgstr "Slaptažodžio atstatymas nesėkmingas" + +msgid "Password reset complete" +msgstr "Slaptažodžio atstatymas baigtas" + +msgid "Password change" +msgstr "Slaptažodžio keitimas" + +msgid "Password change successful" +msgstr "Slaptažodis sėkmingai pakeistas" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/lv/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/lv/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8d9d49f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/lv/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/lv/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/lv/LC_MESSAGES/django.po new file mode 100644 index 0000000..2c8e742 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/lv/LC_MESSAGES/django.po @@ -0,0 +1,313 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Edgars Voroboks , 2023 +# Edgars Voroboks , 2017,2022 +# Edgars Voroboks , 2017 +# Jannis Leidel , 2011 +# Edgars Voroboks , 2019,2021 +# peterisb , 2016 +# Pēteris Caune, 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-04-25 08:09+0000\n" +"Last-Translator: Pēteris Caune, 2023\n" +"Language-Team: Latvian (http://www.transifex.com/django/django/language/" +"lv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lv\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : " +"2);\n" + +msgid "Personal info" +msgstr "Personīgā informācija" + +msgid "Permissions" +msgstr "Tiesības" + +msgid "Important dates" +msgstr "Svarīgi datumi" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(name)s objekts ar primāro atslēgu %(key)r neeksistē." + +msgid "Password changed successfully." +msgstr "Parole nomainīta sekmīgi." + +#, python-format +msgid "Change password: %s" +msgstr "Paroles maiņa: %s" + +msgid "Authentication and Authorization" +msgstr "Autentifikācija un autorizācija" + +msgid "password" +msgstr "parole" + +msgid "last login" +msgstr "pēdējoreiz pieslēdzies" + +msgid "No password set." +msgstr "Nav norādīta parole" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Nederīgs paroles formāts vai nezināms hash algoritms." + +msgid "The two password fields didn’t match." +msgstr "Paroles lauki nesakrita." + +msgid "Password" +msgstr "Parole" + +msgid "Password confirmation" +msgstr "Paroles apstiprinājums" + +msgid "Enter the same password as before, for verification." +msgstr "Ievadi iepriekš norādīto paroli verifikācijai." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Paroles netiek glabātas brīvā tekstā, tāpēc nav iespējams apskatīt lietotāja " +"paroli, bet jūs varat to nomainīt, izmantojot šo formu." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Lūdzu ievadiet korektu informāciju laukos %(username)s un parole. Ņemiet " +"vērā, ka abi ievades lauki ir reģistrjutīgi." + +msgid "This account is inactive." +msgstr "Šis konts nav aktīvs." + +msgid "Email" +msgstr "E-pasts" + +msgid "New password" +msgstr "Jaunā parole" + +msgid "New password confirmation" +msgstr "Jaunās parole vēlreiz" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" +"Jūsu iepriekšējā parole netika ievadīta korekti. Lūdzu ievadiet to atkārtoti." + +msgid "Old password" +msgstr "Vecā parole" + +msgid "Password (again)" +msgstr "Parole (vēlreiz)" + +msgid "algorithm" +msgstr "algoritms" + +msgid "iterations" +msgstr "iterācijas" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "dažādība" + +msgid "version" +msgstr "versija" + +msgid "memory cost" +msgstr "atmiņas izmaksas" + +msgid "time cost" +msgstr "laika izmaksas" + +msgid "parallelism" +msgstr "paralēlisms" + +msgid "work factor" +msgstr "darba faktors" + +msgid "checksum" +msgstr "kontrolsumma" + +msgid "block size" +msgstr "bloka izmērs" + +msgid "name" +msgstr "nosaukums" + +msgid "content type" +msgstr "satura tips" + +msgid "codename" +msgstr "kods" + +msgid "permission" +msgstr "tiesība" + +msgid "permissions" +msgstr "tiesības" + +msgid "group" +msgstr "grupa" + +msgid "groups" +msgstr "grupas" + +msgid "superuser status" +msgstr "superlietotāja statuss" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Nosaka, ka lietotājam ir visas tiesības arī bez to atsevišķas piešķiršanas." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Grupas, kurām lietotājs pieder. Lietotājam būs visas tiesības, kuras ir " +"piešķirtas grupām, kurām tas pieder." + +msgid "user permissions" +msgstr "lietotāja tiesības" + +msgid "Specific permissions for this user." +msgstr "Lietotāja specifiskās tiesības." + +msgid "username" +msgstr "lietotājvārds" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "Obligāts. 150 vai mazāk zīmes. Tikai burti, cipari un @/./+/-/_ ." + +msgid "A user with that username already exists." +msgstr "Lietotājs ar šādu lietotāja vārdu jau eksistē." + +msgid "first name" +msgstr "vārds" + +msgid "last name" +msgstr "uzvārds" + +msgid "email address" +msgstr "e-pasta adrese" + +msgid "staff status" +msgstr "personāla statuss" + +msgid "Designates whether the user can log into this admin site." +msgstr "" +"Atzīmējiet, ja vēlaties, lai lietotājs var pieslēgties administrācijas lapā." + +msgid "active" +msgstr "aktīvs" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Nosaka, vai lietotājs ir aktīvs. Lietojiet šo kā alternatīvu kontu dzēšanai." + +msgid "date joined" +msgstr "datums, kad pievienojies" + +msgid "user" +msgstr "lietotājs" + +msgid "users" +msgstr "lietotāji" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Šī parole ir pārāk īsa. Tai ir jābūt vismaz %(min_length)d zīmes garai." +msgstr[1] "" +"Šī parole ir pārāk īsa. Tai ir jābūt vismaz %(min_length)d zīmi garai.." +msgstr[2] "" +"Šī parole ir pārāk īsa. Tai ir jābūt vismaz %(min_length)d zīmēm garai." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Parolei ir jābūt vismaz %(min_length)d zīmēm garai." +msgstr[1] "Parolei ir jābūt vismaz %(min_length)d zīmi garai." +msgstr[2] "Parolei ir jābūt vismaz %(min_length)d zīmēm garai." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Parole ir pārāk līdzīga %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Parole nedrīkst būt pārāk līdzīga pārējai personīgajai informācijai." + +msgid "This password is too common." +msgstr "Parole ir pārāk bieži lietota." + +msgid "Your password can’t be a commonly used password." +msgstr "Parole nedrīkst būt no bieži lietotu paroļu saraksta." + +msgid "This password is entirely numeric." +msgstr "Parole sastāv tikai no cipariem." + +msgid "Your password can’t be entirely numeric." +msgstr "Parole nedrīkst sastāvēt tikai no cipariem." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Paroles pārstatīšana %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Ievadi derīgu lietotāja vārdu. Šī vērtība var saturēt tikai mazos a-z un " +"lielos A-Z burtus bez diakritiskajām zīmēm, ciparus un @/./+/-/_ simbolus." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Ievadi derīgu lietotāja vārdu. Šī vērtība var saturēt tikai burtus, ciparus " +"un @/./+/-/_ simbolus." + +msgid "Logged out" +msgstr "Atslēdzies" + +msgid "Password reset" +msgstr "Paroles atiestatīšana" + +msgid "Password reset sent" +msgstr "Paroles atiestatīšanas informācija nosūtīta" + +msgid "Enter new password" +msgstr "Ievadiet jauno paroli" + +msgid "Password reset unsuccessful" +msgstr "Paroles atiestatīšana nesekmīga" + +msgid "Password reset complete" +msgstr "Paroles atiestatīšana pabeigta" + +msgid "Password change" +msgstr "Paroles maiņa" + +msgid "Password change successful" +msgstr "Paroles maiņa sekmīga" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/mk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/mk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4909b20 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/mk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/mk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/mk/LC_MESSAGES/django.po new file mode 100644 index 0000000..a991af0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/mk/LC_MESSAGES/django.po @@ -0,0 +1,308 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# dekomote , 2015 +# Jannis Leidel , 2011 +# Vasil Vangelovski , 2016-2017 +# Vasil Vangelovski , 2013-2015 +# Vasil Vangelovski , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-09-24 14:24+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Macedonian (http://www.transifex.com/django/django/language/" +"mk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mk\n" +"Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n" + +msgid "Personal info" +msgstr "Лични информации" + +msgid "Permissions" +msgstr "Привилегии" + +msgid "Important dates" +msgstr "Важни датуми" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "Не постои %(name)s објект со примарен клуч %(key)r." + +msgid "Password changed successfully." +msgstr "Успешна промена на лозинката." + +#, python-format +msgid "Change password: %s" +msgstr "Промени лозинка: %s" + +msgid "Authentication and Authorization" +msgstr "Автентикација и авторизација" + +msgid "password" +msgstr "лозинка" + +msgid "last login" +msgstr "последна најава" + +msgid "No password set." +msgstr "Нема зададена лозинка." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Невалиден формат на лозинка или непознат алгоритам за хеширање." + +msgid "The two password fields didn't match." +msgstr "Двете полиња со лозинките не се совпаѓаат." + +msgid "Password" +msgstr "Лозинка" + +msgid "Password confirmation" +msgstr "Потврда на лозинка" + +msgid "Enter the same password as before, for verification." +msgstr "Внесете ја истата лозинка како претходно, за верификација." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Ве молиме внесете ја точно %(username)s и лозинка. Имајте на ум дека двете " +"полиња може да бидат со мали букви." + +msgid "This account is inactive." +msgstr "Оваа сметка е неактивна." + +msgid "Email" +msgstr "Email" + +msgid "New password" +msgstr "Нова лозинка" + +msgid "New password confirmation" +msgstr "Потврда за нова лозинка" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" +"Не ја внесовте точно вашата стара лозинка. Ве молам внесете ја повторно." + +msgid "Old password" +msgstr "Стара лозинка" + +msgid "Password (again)" +msgstr "Лозинка (повторно)" + +msgid "algorithm" +msgstr "алгоритам" + +msgid "iterations" +msgstr "повторувања" + +msgid "salt" +msgstr "случаен клуч" + +msgid "hash" +msgstr "хеш" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "верзија" + +msgid "memory cost" +msgstr "просторна (мемориска) комплексност" + +msgid "time cost" +msgstr "временска комплексност" + +msgid "parallelism" +msgstr "паралелизам" + +msgid "work factor" +msgstr "фактор на работа" + +msgid "checksum" +msgstr "проверка" + +msgid "name" +msgstr "име" + +msgid "content type" +msgstr "тип содржина" + +msgid "codename" +msgstr "кодно име" + +msgid "permission" +msgstr "привилегија" + +msgid "permissions" +msgstr "привилегии" + +msgid "group" +msgstr "група" + +msgid "groups" +msgstr "групи" + +msgid "superuser status" +msgstr "статус на суперкорисник" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Означува дека овој корисник ги има сите привилегии без експлицитно да се " +"доделуваат сите." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Групите на коишто припаѓа овој корисник. Корисникот ќе ги добие сите " +"пермисии на секоја од избраните групи." + +msgid "user permissions" +msgstr "кориснички привилегии" + +msgid "Specific permissions for this user." +msgstr "Специфични дозволи за овој корисник." + +msgid "username" +msgstr "корисничко име" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Задолжително. 150 или помалку знаци. Единствено букви, бројки и @/./+/-/_ ." + +msgid "A user with that username already exists." +msgstr "Веќе постои корисник со тоа корисничко име." + +msgid "first name" +msgstr "име" + +msgid "last name" +msgstr "презиме" + +msgid "email address" +msgstr "email адреса" + +msgid "staff status" +msgstr "статус на администраторите" + +msgid "Designates whether the user can log into this admin site." +msgstr "" +"Означува дали корисникот може да се логира во сајтот за администрација." + +msgid "active" +msgstr "активен" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Означува дали корисникот треба да биде активен. Одштиклирајте го ова наместо " +"да бришете корисници." + +msgid "date joined" +msgstr "датум на зачленување" + +msgid "user" +msgstr "корисник" + +msgid "users" +msgstr "корисници" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Оваа лозинка е премногу кратка. Мора да содржи најмалку %(min_length)d " +"карактер." +msgstr[1] "" +"Оваа лозинка е премногу кратка. Мора да содржи најмалку %(min_length)d " +"карактери." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Вашата лозинка мора да содржи најмалку %(min_length)d карактер." +msgstr[1] "Вашата лозинка мора да содржи најмалку %(min_length)d карактери." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Лозинката е премногу слична со %(verbose_name)s." + +msgid "Your password can't be too similar to your other personal information." +msgstr "" +"Вашата лозинка не смее да биде премногу слична со други лични информации." + +msgid "This password is too common." +msgstr "Оваа лозинка е премногу често користена." + +msgid "Your password can't be a commonly used password." +msgstr "Вашата лозинка не смее да биде лозинка која се користи многу често." + +msgid "This password is entirely numeric." +msgstr "Оваа лозинка содржи само цифри." + +msgid "Your password can't be entirely numeric." +msgstr "Вашата лозинка не може да содржи само цифри." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Ресетирање на лозинка за %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"Внесете валидно корисничко име. Оваа вредност може да содржи само латински " +"букви, бројки и @/./+/-/_ знаци." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Внесете валидно корисничко име. Оваа вредност може да содржи само букви, " +"бројки и @/./+/-/_ знаци." + +msgid "Logged out" +msgstr "Одјавен" + +msgid "Password reset" +msgstr "Ресетирање на лозинка" + +msgid "Password reset sent" +msgstr "Испратено информации за ресетирање лозинка" + +msgid "Enter new password" +msgstr "Внесете нова лозинка" + +msgid "Password reset unsuccessful" +msgstr "Неуспешно ресетирање на лозинка" + +msgid "Password reset complete" +msgstr "Ресетирањето на лозинката е завршено" + +msgid "Password change" +msgstr "Промена на лозинка" + +msgid "Password change successful" +msgstr "Успешна промена на лозинка" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ml/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ml/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d247f8e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ml/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ml/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ml/LC_MESSAGES/django.po new file mode 100644 index 0000000..b407d06 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ml/LC_MESSAGES/django.po @@ -0,0 +1,303 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# David Forgoz , 2012 +# Hrishikesh , 2019 +# Jannis Leidel , 2011 +# Rag sagar , 2016 +# Rajeesh Nair , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2019-03-03 09:43+0000\n" +"Last-Translator: Hrishikesh \n" +"Language-Team: Malayalam (http://www.transifex.com/django/django/language/" +"ml/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ml\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "വ്യക്തിപരമായ വിവരങ്ങള്‍" + +msgid "Permissions" +msgstr "അനുമതികള്‍" + +msgid "Important dates" +msgstr "പ്രധാന തീയതികള്‍" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(key)r പ്രൈമറി കീയായുള്ള %(name)s ന്റെ ഒബ്ജക്റ്റ് നിലവിലില്ല." + +msgid "Password changed successfully." +msgstr "പാസ്സ്‌വേഡ് മാറ്റിയിരിക്കുന്നു." + +#, python-format +msgid "Change password: %s" +msgstr "പാസ്സ്‌വേഡ് മാറ്റുക: %s" + +msgid "Authentication and Authorization" +msgstr "ആധികാരികതയും അധികാരപ്പെടുത്തലും" + +msgid "password" +msgstr "പാസ്സ്‌വേഡ്" + +msgid "last login" +msgstr "അവസാനമായി ലോഗിന്‍ ചെയ്തത്" + +msgid "No password set." +msgstr "പാസ്സ്‌വേഡ് സജ്ജീകരിച്ചിട്ടില്ല." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" +"പാസ്സ്‌വേഡിന്റെ ഫോർമാറ്റ് ശെരിയല്ലാതിരിക്കുകയോ അറിയാത്ത ഹാഷിങ്ങ് അൽഗോരിതം ഉപയോഗിക്കുകയോ " +"ചെയ്തിരിക്കുന്നു." + +msgid "The two password fields didn't match." +msgstr "രണ്ട് പാസ്സ്‌വേഡ് ഫീൽഡുകളും തമ്മിൽ ചേരുന്നില്ല." + +msgid "Password" +msgstr "പാസ്സ്‌വേഡ്" + +msgid "Password confirmation" +msgstr "പാസ്സ്‌വേഡ് ഉറപ്പാക്കല്‍" + +msgid "Enter the same password as before, for verification." +msgstr "നേരത്തെ നല്കിയ രഹസ്യവാക്ക് പരിശോധിക്കനായി പിന്നെയും നല്കുക. " + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"ദയവായി ശരിയായ %(username)s ഉം രഹസ്യവാക്കും നല്കുക. രണ്ട് കള്ളികളിലും വലിയക്ഷരങ്ങളും " +"ചെറിയക്ഷരങ്ങളും വെവ്വേറെയായിരിക്കും." + +msgid "This account is inactive." +msgstr "ഈ അക്കൗണ്ട് മരവിപ്പിച്ചതാണ്." + +msgid "Email" +msgstr "ഈമെയിൽ" + +msgid "New password" +msgstr "പുതിയ പാസ്‌വേര്‍ഡ്" + +msgid "New password confirmation" +msgstr "പുതിയ പാസ്‌വേര്‍ഡ് ഉറപ്പാക്കല്‍" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "നിങ്ങളുടെ പഴയ പാസ്‌വേര്‍ഡ് തെറ്റായാണ് നല്കിയത്. തിരുത്തുക." + +msgid "Old password" +msgstr "പഴയ പാസ്‌വേര്‍ഡ്" + +msgid "Password (again)" +msgstr "പാസ്‌വേര്‍ഡ് (വീണ്ടും)" + +msgid "algorithm" +msgstr "അല്‍ഗോരിതം" + +msgid "iterations" +msgstr "പുനരാവൃത്തികള്‍" + +msgid "salt" +msgstr "സോള്‍ട്ട്" + +msgid "hash" +msgstr "ഹാഷ്" + +msgid "variety" +msgstr "തരം" + +msgid "version" +msgstr "പതിപ്പ്" + +msgid "memory cost" +msgstr "മെമ്മറി ചിലവ്" + +msgid "time cost" +msgstr "സമയത്തിന്റെ ചിലവ്" + +msgid "parallelism" +msgstr "സമാന്തരമായി" + +msgid "work factor" +msgstr "വര്‍ക്ക് ഫാക്ടര്‍" + +msgid "checksum" +msgstr "ചെക്‍സം" + +msgid "name" +msgstr "പേര്" + +msgid "content type" +msgstr "കണ്ടന്റ് ടൈപ്പ്" + +msgid "codename" +msgstr "കോഡ്-നാമം" + +msgid "permission" +msgstr "അനുമതി" + +msgid "permissions" +msgstr "അനുമതികള്‍" + +msgid "group" +msgstr "ഗ്രൂപ്പ്" + +msgid "groups" +msgstr "ഗ്രൂപ്പുകള്‍" + +msgid "superuser status" +msgstr "സൂപ്പര്‍-യൂസര്‍ പദവി" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "ഈ ഉപയോക്താവിന് എടുത്തു പറയാതെ തന്നെ എല്ലാ അനുമതികളും ലഭിക്കുന്നതാണെന്ന് വ്യക്തമാക്കുന്നു" + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"ഈ ഉപയോക്താവ് ഭാഗമായിട്ടുള്ള ഗ്രൂപ്പുകൾ. ഒരു ഉപയോക്താവ് ഭാഗമായിട്ടുള്ള ഓരോ ഗ്രൂപ്പിലേ അനുമതികളും " +"ആ ഉപയോക്താവിനു ലഭിക്കുന്നതാണ്." + +msgid "user permissions" +msgstr "യൂസര്‍ (ഉപയോക്താവ്)നുള്ള അനുമതികള്‍" + +msgid "Specific permissions for this user." +msgstr "ഈ ഉപയോക്താവിനു മാത്രമായുള്ള അനുമതികൾ." + +msgid "username" +msgstr "യൂസര്‍ നാമം (ഉപയോക്ത്രു നാമം)" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"നിര്‍ബന്ധം. 150 ഓ അതില്‍ കുറവോ അക്ഷരങ്ങള്‍, അക്കങ്ങള്‍, പിന്നെ @/./+/-/_ എന്നിവയും മാത്രം." + +msgid "A user with that username already exists." +msgstr "ആ പേരുള്ള ഒരു ഉപയോക്താവ് നിലവിലുണ്ട്." + +msgid "first name" +msgstr "പേര് - ആദ്യഭാഗം" + +msgid "last name" +msgstr "പേര് - അന്ത്യഭാഗം" + +msgid "email address" +msgstr "ഈമെയിൽ വിലാസം" + +msgid "staff status" +msgstr "സ്റ്റാഫ് പദവി" + +msgid "Designates whether the user can log into this admin site." +msgstr "ഈ യൂസര്‍ക്ക് ഈ അഡ്മിന്‍ സൈറ്റിലേക്ക് പ്രവേശിക്കാമോ എന്നു വ്യക്തമാക്കാന്‍" + +msgid "active" +msgstr "സജീവം" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"ഈ യൂസര്‍ സജീവമാണോയെന്ന് വ്യക്തമാക്കുന്നു. അക്കൗണ്ട് ഡിലീറ്റ് ചെയ്യുന്നതിനു പകരം ഇത് ഒഴിവാക്കുക." + +msgid "date joined" +msgstr "ചേര്‍ന്ന തീയതി" + +msgid "user" +msgstr "യൂസര്‍ (ഉപയോക്താവ്)" + +msgid "users" +msgstr "യൂസേര്‍സ് (ഉപയോക്താക്കള്‍)" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"ഈ രഹസ്യവാക്ക് വളരെ ചെറുതാണ്. രഹസ്യവാക്കിൽ കുറഞ്ഞത് %(min_length)d അക്ഷരമെങ്കിലും വേണം." +msgstr[1] "" +"ഈ രഹസ്യവാക്ക് വളരെ ചെറുതാണ്. രഹസ്യവാക്കിൽ കുറഞ്ഞത് %(min_length)d അക്ഷരങ്ങളെങ്കിലും വേണം." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "താങ്കളുടെ രഹസ്യവാക്കിൽ കുറഞ്ഞത് %(min_length)d അക്ഷരമെങ്കിലും ഉണ്ടാവണം." +msgstr[1] "താങ്കളുടെ രഹസ്യവാക്കിൽ കുറഞ്ഞത് %(min_length)d അക്ഷരങ്ങളെങ്കിലും ഉണ്ടാവണം." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "ഈ രഹസ്യവാക്കിനു %(verbose_name)s ആയി  വളരെ സാമ്യം കാണുന്നു." + +msgid "Your password can't be too similar to your other personal information." +msgstr "" +"താങ്കളുടെ മറ്റു വ്യക്തി വിവരുങ്ങളുമായി താങ്കളുടെ രഹസ്യവാക്കിനു ഒരുപാട് സാമ്യമുണ്ടാകാൻ പാടില്ല." + +msgid "This password is too common." +msgstr "ഈ രഹസ്യവാക്ക് വളരെ സാധാരണമാണ്." + +msgid "Your password can't be a commonly used password." +msgstr "താങ്കളുടെ രഹസ്യവാക്ക് വളരെ സാധാരണമായ ഒരു രഹസ്യവാക്കാകാൻ പാടില്ല." + +msgid "This password is entirely numeric." +msgstr "ഈ രഹസ്യവാക്ക് മുഴുവനും അക്കങ്ങൾ മാത്രമാണ്." + +msgid "Your password can't be entirely numeric." +msgstr "താങ്കളുടെ രഹസ്യവാക്ക് മുഴുവനായി അക്കങ്ങൾ മാത്രമാകാൻ പാടില്ല." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "%(site_name)s ലെ പാസ്‌വേര്‍ഡ് മാറ്റിയിരിക്കുന്നു" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"ശരിയായ ഉപയോക്ത്രു നാമം നല്കുക. ഇതിൽ ഇംഗ്ഗ്ലീഷ് അക്ഷരങ്ങളും അക്കങ്ങളും പിന്നെ @/./+/-/_ " +"എന്നിവയും മാത്രമേ അനുവദനീയമായുള്ളൂ." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"ശരിയായ ഉപയോക്ത്രു നാമം നല്കുക. ഇതിൽ അക്ഷരങ്ങളും അക്കങ്ങളും പിന്നെ @/./+/-/_ എന്നിവയും " +"മാത്രമേ അനുവദനീയമായുള്ളൂ." + +msgid "Logged out" +msgstr "ലോഗ്-ഔട്ട് ചെയ്തു (പുറത്തിറങ്ങി)" + +msgid "Password reset" +msgstr "രഹസ്യവാക്ക് പുനർക്രമീകരിക്കുക." + +msgid "Password reset sent" +msgstr "രഹസ്യവാക്ക് പുനർക്രമീകരിക്കാൻ അയച്ചു" + +msgid "Enter new password" +msgstr "പുതിയ രഹസ്യവാക്ക് നല്കുക" + +msgid "Password reset unsuccessful" +msgstr "രഹസ്യവാക്ക് പുനർക്രമീകരണം പരാജയപ്പെട്ടിരിക്കുന്നു." + +msgid "Password reset complete" +msgstr "രഹസ്യവാക്ക് പുനർക്രമീകരണം പൂർത്തിയായി." + +msgid "Password change" +msgstr "രഹസ്യവാക്ക് മാറ്റം" + +msgid "Password change successful" +msgstr "രഹസ്യവാക്ക് വിജയകരമായി മാറ്റിയിരിക്കുന്നു." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/mn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/mn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0c2a3c8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/mn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/mn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/mn/LC_MESSAGES/django.po new file mode 100644 index 0000000..76deb1e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/mn/LC_MESSAGES/django.po @@ -0,0 +1,310 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bayarkhuu Bataa, 2015,2017 +# Delgermurun Purevkhuuu , 2013 +# dolugen , 2016 +# Jannis Leidel , 2011 +# miigaa ... , 2015 +# Zorig , 2013-2014,2017 +# Анхбаяр Анхаа , 2015 +# Баясгалан Цэвлээ , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-10-19 13:49+0000\n" +"Last-Translator: Bayarkhuu Bataa\n" +"Language-Team: Mongolian (http://www.transifex.com/django/django/language/" +"mn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Хувийн мэдээлэл" + +msgid "Permissions" +msgstr "Эрхүүд" + +msgid "Important dates" +msgstr "Чухал огноо" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(key)r анхдагч түлхүүртэй %(name)s обьект олдсонгүй." + +msgid "Password changed successfully." +msgstr "Нууц үг амжилттай өөрчлөгдлөө." + +#, python-format +msgid "Change password: %s" +msgstr "Нууц үг өөрчлөх: %s" + +msgid "Authentication and Authorization" +msgstr "Нэвтрэлт ба зөвшөөрөл" + +msgid "password" +msgstr "нууц үг" + +msgid "last login" +msgstr "сүүлд нэвтэрсэн" + +msgid "No password set." +msgstr "Нууц үг тохируулаагүй." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Нууц үгийн буруу формат эсвэл үл мэдэгдэх хаш алгоритм байна." + +msgid "The two password fields didn't match." +msgstr "Хоёр нууц үг зөрж байна." + +msgid "Password" +msgstr "Нууц үг " + +msgid "Password confirmation" +msgstr "Нууц үгийн баталгаажуулалт" + +msgid "Enter the same password as before, for verification." +msgstr "Баталгаажуулахын тулд дээрх нууц үгээ ахин оруулна уу." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" +"Хэрэглэгчийн нууц үгийг хувиргалгүйгээр хадгалдаггүй учир шууд харах " +"боломжгүй, гэхдээ энэ маягт ашиглан өөрчилж болно." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Зөв %(username)s, нууц үг оруулна уу. Том жижиг үсэг ялгаатай болохыг " +"анхаарна уу." + +msgid "This account is inactive." +msgstr "Энэ бүртгэл идэвхгүй байна." + +msgid "Email" +msgstr "Имэйл" + +msgid "New password" +msgstr "Шинэ нууц үг" + +msgid "New password confirmation" +msgstr "Шинэ нууц үгийн баталгаажуулалт" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Хуучин нууц үгээ буруу оруулсан байна. Ахин оруулна уу." + +msgid "Old password" +msgstr "Хуучин нууц үг" + +msgid "Password (again)" +msgstr "Нууц үг (давтан)" + +msgid "algorithm" +msgstr "алгоритм" + +msgid "iterations" +msgstr "давталтууд" + +msgid "salt" +msgstr "давс" + +msgid "hash" +msgstr "хаш" + +msgid "variety" +msgstr "боломж" + +msgid "version" +msgstr "хувилбар" + +msgid "memory cost" +msgstr "санах ойн өртөг" + +msgid "time cost" +msgstr "цагын зардал" + +msgid "parallelism" +msgstr "зэрэгцүүлэлт" + +msgid "work factor" +msgstr "ажлын байгуулагч" + +msgid "checksum" +msgstr "шалгах дүн" + +msgid "name" +msgstr "нэр" + +msgid "content type" +msgstr "агуулгын төрөл" + +msgid "codename" +msgstr "Код" + +msgid "permission" +msgstr "зөвшөөрөл" + +msgid "permissions" +msgstr "зөвшөөрлүүд" + +msgid "group" +msgstr "бүлэг " + +msgid "groups" +msgstr "бүлгүүд" + +msgid "superuser status" +msgstr "Удирдлагын төлөв" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "Энэ хэрэглэгчид бүх зөвшөөрөл байгааг ил тод харуулалгүй тодорхойлно. " + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Хэрэглэгчийн харьяалагдах бүлгүүд. Хэрэглэгчид сонгосон бүлгийн бүх эрх " +"зөвшөөрөгдөх болно. " + +msgid "user permissions" +msgstr "хэрэглэгчийн эрхүүд" + +msgid "Specific permissions for this user." +msgstr "Хэрэглэгчид тодорхойлж өгсөн эрх" + +msgid "username" +msgstr "хэрэглэгчийн нэр" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Заавал. 150 ба түүнээс бага үсэгтэй. Зөвхөн латин үсэг, тоо болон @/./+/-/_ " +"тэмдэгтүүдийг зөвшөөрнө." + +msgid "A user with that username already exists." +msgstr "Ийм хэрэглэгчийн нэртэй хэрэглэгч өмнө нь бүртгүүлсэн байна." + +msgid "first name" +msgstr "нэр" + +msgid "last name" +msgstr "овог" + +msgid "email address" +msgstr "имэйл хаяг" + +msgid "staff status" +msgstr "Хэрэглэгчдийн төлөв" + +msgid "Designates whether the user can log into this admin site." +msgstr "" +"Уг удирдлагын сайт руу хэрэглэгч нэвтрэх боломжтой эсэхийг тодорхойлно." + +msgid "active" +msgstr "идэвхтэй" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Энэ хэрэглэгчийг идэвхтэй болгох эсэхийг тодорхойлно. Бүртгэлийг нь устгахын " +"оронд сонгохгүй байхад л хангалттай." + +msgid "date joined" +msgstr "бүртгүүлсэн огноо" + +msgid "user" +msgstr "хэрэглэгч " + +msgid "users" +msgstr "хэрэглэгчид" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Нууц үг хэтэрхий богино байна. Хамгийн багадаа %(min_length)d тэмдэгтээс " +"бүрдэх ёстой." +msgstr[1] "" +"Нууц үг хэтэрхий богино байна. Хамгийн багадаа %(min_length)d тэмдэгтээс " +"бүрдэх ёстой." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Нууц хамгийн багадаа %(min_length)d тэмдэгтээс бүрдэх ёстой." +msgstr[1] "Нууц хамгийн багадаа %(min_length)d тэмдэгтээс бүрдэх ёстой." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Нууц үг %(verbose_name)s мэдээлэлтэй хэтэрхий адилхан байна." + +msgid "Your password can't be too similar to your other personal information." +msgstr "Таны нууц үг бусад хувийн мэдээлэлтэй төстэй байж болохгүй." + +msgid "This password is too common." +msgstr "Энэ нууц үг хэтэрхий нийтлэг байна." + +msgid "Your password can't be a commonly used password." +msgstr "Таны нууц үг хүмүүсийн нийтлэг ашигладаг нууц үг байж болохгүй." + +msgid "This password is entirely numeric." +msgstr "Нууц үг дан тооноос бүрдсэн байна." + +msgid "Your password can't be entirely numeric." +msgstr "Таны нууц үг бүхэлдээ тооноос бүрдэж болохгүй." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "%(site_name)s cайт дээрх нууц үг шинэчлэлт" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"Зөв хэрэглэгчийн нэр оруулна уу. Англи хэлний үсэг, тоо болон @ . + - _ " +"тэмдэгтүүдийг ашиглаж болно." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Зөв хэрэглэгчийн нэр оруулна уу. Англи хэлний үсэг, тоо болон @ . + - _ " +"тэмдэгтүүдийг ашиглаж болно." + +msgid "Logged out" +msgstr "Гарсан" + +msgid "Password reset" +msgstr "Нууц үг шинэчлэх" + +msgid "Password reset sent" +msgstr "Нууц үг шинэчлэх хүсэлт илгээгдлээ" + +msgid "Enter new password" +msgstr "Шинэ нууц үг оруулах" + +msgid "Password reset unsuccessful" +msgstr "Нууц үг шинэчлэлт амжилтгүй боллоо" + +msgid "Password reset complete" +msgstr "Нууц үг шинэчилж дууслаа" + +msgid "Password change" +msgstr "Нууц үг солих" + +msgid "Password change successful" +msgstr "Нууц үг амжилттай солилоо" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/mr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/mr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f33dd23 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/mr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/mr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/mr/LC_MESSAGES/django.po new file mode 100644 index 0000000..16b3e27 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/mr/LC_MESSAGES/django.po @@ -0,0 +1,226 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-03-18 09:16+0100\n" +"PO-Revision-Date: 2015-03-18 10:30+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Marathi (http://www.transifex.com/projects/p/django/language/" +"mr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mr\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "" + +msgid "Permissions" +msgstr "" + +msgid "Important dates" +msgstr "" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "" + +#, python-format +msgid "Change password: %s" +msgstr "" + +msgid "Authentication and Authorization" +msgstr "" + +msgid "No password set." +msgstr "" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" + +msgid "The two password fields didn't match." +msgstr "" + +msgid "Password" +msgstr "" + +msgid "Password confirmation" +msgstr "" + +msgid "Enter the same password as above, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this " +"form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" + +msgid "This account is inactive." +msgstr "" + +msgid "Email" +msgstr "" + +msgid "New password" +msgstr "" + +msgid "New password confirmation" +msgstr "" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" + +msgid "Old password" +msgstr "" + +msgid "Password (again)" +msgstr "" + +msgid "algorithm" +msgstr "" + +msgid "iterations" +msgstr "" + +msgid "salt" +msgstr "" + +msgid "hash" +msgstr "" + +msgid "work factor" +msgstr "" + +msgid "checksum" +msgstr "" + +msgid "name" +msgstr "" + +msgid "codename" +msgstr "" + +msgid "permission" +msgstr "" + +msgid "permissions" +msgstr "" + +msgid "group" +msgstr "" + +msgid "groups" +msgstr "" + +msgid "password" +msgstr "" + +msgid "last login" +msgstr "" + +msgid "superuser status" +msgstr "" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "" + +msgid "Specific permissions for this user." +msgstr "" + +msgid "username" +msgstr "" + +msgid "Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers and @/./" +"+/-/_ characters." +msgstr "" + +msgid "A user with that username already exists." +msgstr "" + +msgid "first name" +msgstr "" + +msgid "last name" +msgstr "" + +msgid "email address" +msgstr "" + +msgid "staff status" +msgstr "" + +msgid "Designates whether the user can log into this admin site." +msgstr "" + +msgid "active" +msgstr "" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" + +msgid "date joined" +msgstr "" + +msgid "user" +msgstr "" + +msgid "users" +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "" + +msgid "Logged out" +msgstr "" + +msgid "Password reset" +msgstr "" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "" + +msgid "Password reset unsuccessful" +msgstr "" + +msgid "Password reset complete" +msgstr "" + +msgid "Password change" +msgstr "" + +msgid "Password change successful" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ms/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ms/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ff5fb70 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ms/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ms/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ms/LC_MESSAGES/django.po new file mode 100644 index 0000000..b05dc59 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ms/LC_MESSAGES/django.po @@ -0,0 +1,313 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jafry Hisham, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2021-11-16 14:43+0000\n" +"Last-Translator: Jafry Hisham\n" +"Language-Team: Malay (http://www.transifex.com/django/django/language/ms/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ms\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Personal info" +msgstr "Info peribadi" + +msgid "Permissions" +msgstr "Kebenaran" + +msgid "Important dates" +msgstr "Tarikh-tarikh penting" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "Objek %(name)s dengan kunci utama %(key)r tidak wujud." + +msgid "Password changed successfully." +msgstr "Kata laluan berjaya ditukar." + +#, python-format +msgid "Change password: %s" +msgstr "Tukar kata laluan: %s" + +msgid "Authentication and Authorization" +msgstr "Pengesahan dan Kebenaran" + +msgid "password" +msgstr "kata laluan" + +msgid "last login" +msgstr "log masuk terakhir" + +msgid "No password set." +msgstr "Kata laluan tidak ditetapkan." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" +"Format kata laluan tidak sah atau algoritma hash yang tidak dapat dipastikan." + +msgid "The two password fields didn’t match." +msgstr "Medan kedua-dua kata laluan tidak sepadan." + +msgid "Password" +msgstr "Kata laluan" + +msgid "Password confirmation" +msgstr "Pengesahan kata laluan" + +msgid "Enter the same password as before, for verification." +msgstr "" +"Masukkan kata laluan yang sama seperti sebelumnya, bagi tujuan pengesahan." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Kata laluan mentah tidak disimpan, maka tiada cara untuk melihat kata laluan " +"pengguna, tetapi anda boleh menukar kata laluan menggunakan borang ini." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Sila masukkan %(username)s dan kata laluan yang betul. Ambil perhatian " +"bahawa kedua-dua medan berkemungkinan kes-sensitif. " + +msgid "This account is inactive." +msgstr "Akaun ini tidak aktif." + +msgid "Email" +msgstr "Emel" + +msgid "New password" +msgstr "Kata laluan baru" + +msgid "New password confirmation" +msgstr "Pengesahan kata laluan baru" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" +"Kata laluan lama anda tidak dimasukkan dengan betul. Sila masukkan sekali " +"lagi." + +msgid "Old password" +msgstr "Kata laluan lama" + +msgid "Password (again)" +msgstr "Kata laluan (sekali lagi)" + +msgid "algorithm" +msgstr "algortima" + +msgid "iterations" +msgstr "lelaran" + +msgid "salt" +msgstr "garam" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "kepelbagaian" + +msgid "version" +msgstr "versi" + +msgid "memory cost" +msgstr "kos memori" + +msgid "time cost" +msgstr "kos masa" + +msgid "parallelism" +msgstr "parallelisma" + +msgid "work factor" +msgstr "faktor kerja" + +msgid "checksum" +msgstr "checksum" + +msgid "block size" +msgstr "saiz blok" + +msgid "name" +msgstr "nama" + +msgid "content type" +msgstr "jenis kandungan" + +msgid "codename" +msgstr "nama kod" + +msgid "permission" +msgstr "kebenaran" + +msgid "permissions" +msgstr "kebenaran" + +msgid "group" +msgstr "kumpulan" + +msgid "groups" +msgstr "kumpulan-kumpulan" + +msgid "superuser status" +msgstr "status pengguna hebat" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Menentukan bahawa pengguna ini mempunyai semua kebenaran tanpa memberikannya " +"secara eksplisit." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Pengguna ini adalah ahli kepada kumpulan-kumpulan ini. Pengguna akan " +"mewarisi semua kebenaran yang diberikan kepada kumpulan-kumpulan ini." + +msgid "user permissions" +msgstr "kebenaran penguna" + +msgid "Specific permissions for this user." +msgstr "Kebenaran-kebenaran spesifik bagi pengguna ini." + +msgid "username" +msgstr "nama pengguna" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Diperlukan. 150 karakter atau kurang. Huruf, digit dan @/./+/-/_ sahaja." + +msgid "A user with that username already exists." +msgstr "Pengguna dengan nama pengguna ini sudah wujud." + +msgid "first name" +msgstr "nama pertama" + +msgid "last name" +msgstr "nama akhir" + +msgid "email address" +msgstr "alamat emel" + +msgid "staff status" +msgstr "status staf" + +msgid "Designates whether the user can log into this admin site." +msgstr "Menentukan samada pengguna ini boleh log masuk ke laman pentadbiran." + +msgid "active" +msgstr "aktif" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Menentukan samada pengguna ini patut dilayan sebagai aktif. Padam pilihan " +"ini daripada menghapuskan terus akaun pengguna." + +msgid "date joined" +msgstr "tarikh serta" + +msgid "user" +msgstr "pengguna" + +msgid "users" +msgstr "pengguna-pengguna" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Kata laluan ini terlalu singkat. Ia harus mempunyai sekurang-kurangnya " +"%(min_length)d karakter." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +"Kata laluan anda harus mempunyai sekurang-kurangnya %(min_length)d karakter." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Kata laluan ini hampir sama dengan %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" +"Kata laluan anda tidak boleh hampir sama dengan maklumat peribadi anda yang " +"lain." + +msgid "This password is too common." +msgstr "Kata laluan anda terlalu singkat." + +msgid "Your password can’t be a commonly used password." +msgstr "" +"Kata laluan anda tidak boleh sama dengan kata laluan yang terlalu biasa " +"digunakan." + +msgid "This password is entirely numeric." +msgstr "Aksara kata laluan ini kesemuanya terdiri daripada nombor." + +msgid "Your password can’t be entirely numeric." +msgstr "" +"Kata laluan anda tidak boleh terdiri daripada aksara nombor secara " +"sepenuhnya." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Penetapan semula kata laluan di %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"Masukkan nama pengguna yang sah. Nilai ini hanya boleh mengandungi huruf " +"bahasa Inggeris, nombor, dan karakter-karakter @/./+/-/_ ." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Masukkan nama pengguna yang sah. Nilai boleh mengandungi huruf, mombor, dan " +"karakter-karakter @/./+/-/_ ." + +msgid "Logged out" +msgstr "Telah di log keluar" + +msgid "Password reset" +msgstr "Penetapan semula kata laluan" + +msgid "Password reset sent" +msgstr "Penetapan semula kata laluan telah dihantar" + +msgid "Enter new password" +msgstr "Masukkan kata laluan yang baru" + +msgid "Password reset unsuccessful" +msgstr "Penetapan semula kata laluan tidak berjaya " + +msgid "Password reset complete" +msgstr "Penetapan semula kata laluan telah lengkap" + +msgid "Password change" +msgstr "Penukaran kata laluan" + +msgid "Password change successful" +msgstr "Penukaran kata laluan berjaya dilakukan" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/my/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/my/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a08a819 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/my/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/my/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/my/LC_MESSAGES/django.po new file mode 100644 index 0000000..400768c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/my/LC_MESSAGES/django.po @@ -0,0 +1,282 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Yhal Htet Aung , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-09-24 14:24+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Burmese (http://www.transifex.com/django/django/language/" +"my/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: my\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Personal info" +msgstr "ကိုယ်ရေးအချက်အလက်" + +msgid "Permissions" +msgstr "ခွင့်ပြုချက်များ" + +msgid "Important dates" +msgstr "အရေးကြီးနေ့စွဲများ" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "" + +#, python-format +msgid "Change password: %s" +msgstr "" + +msgid "Authentication and Authorization" +msgstr "" + +msgid "password" +msgstr "" + +msgid "last login" +msgstr "" + +msgid "No password set." +msgstr "" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" + +msgid "The two password fields didn't match." +msgstr "" + +msgid "Password" +msgstr "စကားဝှက်" + +msgid "Password confirmation" +msgstr "" + +msgid "Enter the same password as before, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" + +msgid "This account is inactive." +msgstr "" + +msgid "Email" +msgstr "အီးမေးလ်" + +msgid "New password" +msgstr "" + +msgid "New password confirmation" +msgstr "" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" + +msgid "Old password" +msgstr "" + +msgid "Password (again)" +msgstr "" + +msgid "algorithm" +msgstr "ပံုသေနည်း" + +msgid "iterations" +msgstr "" + +msgid "salt" +msgstr "" + +msgid "hash" +msgstr "" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "" + +msgid "checksum" +msgstr "" + +msgid "name" +msgstr "နာမည်" + +msgid "content type" +msgstr "" + +msgid "codename" +msgstr "" + +msgid "permission" +msgstr "" + +msgid "permissions" +msgstr "" + +msgid "group" +msgstr "အုပ်စု" + +msgid "groups" +msgstr "အုပ်စုများ" + +msgid "superuser status" +msgstr "" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "" + +msgid "Specific permissions for this user." +msgstr "" + +msgid "username" +msgstr "" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "" + +msgid "first name" +msgstr "" + +msgid "last name" +msgstr "" + +msgid "email address" +msgstr "" + +msgid "staff status" +msgstr "" + +msgid "Designates whether the user can log into this admin site." +msgstr "" + +msgid "active" +msgstr "" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" + +msgid "date joined" +msgstr "" + +msgid "user" +msgstr "" + +msgid "users" +msgstr "" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "" + +msgid "Your password can't be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "" + +msgid "Your password can't be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "" + +msgid "Your password can't be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "" + +msgid "Password reset" +msgstr "" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "" + +msgid "Password reset unsuccessful" +msgstr "" + +msgid "Password reset complete" +msgstr "" + +msgid "Password change" +msgstr "" + +msgid "Password change successful" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/nb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/nb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..cb00302 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/nb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/nb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/nb/LC_MESSAGES/django.po new file mode 100644 index 0000000..b388399 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/nb/LC_MESSAGES/django.po @@ -0,0 +1,302 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# jensadne , 2014 +# Jon, 2015-2016 +# Jon, 2017,2020,2022 +# Jon, 2013 +# Sigurd Gartmann , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-04-25 08:09+0000\n" +"Last-Translator: Jon, 2017,2020,2022\n" +"Language-Team: Norwegian Bokmål (http://www.transifex.com/django/django/" +"language/nb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Personlig informasjon" + +msgid "Permissions" +msgstr "Rettigheter" + +msgid "Important dates" +msgstr "Viktige datoer" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(name)s-objekt med primærnøkkelen %(key)r finnes ikke." + +msgid "Password changed successfully." +msgstr "Passordet er endret." + +#, python-format +msgid "Change password: %s" +msgstr "Endre passord: %s" + +msgid "Authentication and Authorization" +msgstr "Autentisering og autorisasjon" + +msgid "password" +msgstr "passord" + +msgid "last login" +msgstr "siste innlogging" + +msgid "No password set." +msgstr "Passord ikke satt." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Ugyldig passordformat eller ukjent hash-algoritme." + +msgid "The two password fields didn’t match." +msgstr "De to passordfeltene er ikke like." + +msgid "Password" +msgstr "Passord" + +msgid "Password confirmation" +msgstr "Passordbekreftelse" + +msgid "Enter the same password as before, for verification." +msgstr "Skriv inn det samme passordet som tidligere, for verifisering." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Selve passordet lagres ikke, så det finnes ingen måte å se denne brukerens " +"passord på. Du kan endre passordet med dette skjemaet." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Vennligst oppgi korrekt %(username)s og passord. Merk at det kan være " +"forskjell på små og store bokstaver." + +msgid "This account is inactive." +msgstr "Denne kontoen er inaktiv." + +msgid "Email" +msgstr "E-post" + +msgid "New password" +msgstr "Nytt passord" + +msgid "New password confirmation" +msgstr "Bekreft nytt passord" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Ditt gamle passord er galt. Vennligst prøv igjen." + +msgid "Old password" +msgstr "Gammelt passord" + +msgid "Password (again)" +msgstr "Passord (gjenta)" + +msgid "algorithm" +msgstr "algoritme" + +msgid "iterations" +msgstr "iterasjoner" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "variasjon" + +msgid "version" +msgstr "versjon" + +msgid "memory cost" +msgstr "minnekostnad" + +msgid "time cost" +msgstr "tidskostnad" + +msgid "parallelism" +msgstr "parallellitet" + +msgid "work factor" +msgstr "arbeidsfaktor" + +msgid "checksum" +msgstr "sjekksum" + +msgid "block size" +msgstr "blokkstørrelse" + +msgid "name" +msgstr "navn" + +msgid "content type" +msgstr "innholdstype" + +msgid "codename" +msgstr "kodenavn" + +msgid "permission" +msgstr "rettighet" + +msgid "permissions" +msgstr "rettigheter" + +msgid "group" +msgstr "gruppe" + +msgid "groups" +msgstr "grupper" + +msgid "superuser status" +msgstr "superbruker" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Angir at denne brukeren har alle rettigheter uten å eksplisitt sette dem." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Gruppene denne brukeren er tilknyttet. En bruker vil ha alle rettigheter " +"tilhørende gruppene han/hun er medlem av." + +msgid "user permissions" +msgstr "Brukerrettigheter" + +msgid "Specific permissions for this user." +msgstr "Spesifikke tilganger for denne brukeren." + +msgid "username" +msgstr "brukernavn" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "Påkrevet. 150 tegn eller færre. Kun bokstaver, tall og @/./+/-/_." + +msgid "A user with that username already exists." +msgstr "Det eksisterer allerede en bruker med dette brukernavnet." + +msgid "first name" +msgstr "fornavn" + +msgid "last name" +msgstr "etternavn" + +msgid "email address" +msgstr "e-postadresse" + +msgid "staff status" +msgstr "administrasjonsstatus" + +msgid "Designates whether the user can log into this admin site." +msgstr "Angir at brukeren kan logge inn på denne administrasjonssiden." + +msgid "active" +msgstr "aktiv" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Angir at denne brukeren er aktiv. Avmerk denne i stedet for å slette kontoen." + +msgid "date joined" +msgstr "registrert" + +msgid "user" +msgstr "bruker" + +msgid "users" +msgstr "brukere" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "Passordet er for kort. Det må bestå av minst %(min_length)d tegn." +msgstr[1] "Passordet er for kort. Det må bestå av minst %(min_length)d tegn." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Passordet ditt må bestå av minst %(min_length)d tegn." +msgstr[1] "Passordet ditt må bestå av minst %(min_length)d tegn." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Passordet er for likt %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Passordet ditt kan ikke være for likt dine andre personopplysninger." + +msgid "This password is too common." +msgstr "Dette passordet er for vanlig." + +msgid "Your password can’t be a commonly used password." +msgstr "Passordet ditt kan ikke være et ofte brukt passord." + +msgid "This password is entirely numeric." +msgstr "Dette passordet inneholder bare tall." + +msgid "Your password can’t be entirely numeric." +msgstr "Passordet ditt kan ikke inneholde bare tall." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Passord-nullstilling på %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Oppgi et gyldig brukernavn. Denne verdien kan kun inneholde bokstaver, tall " +"og @/./+/-/_" + +msgid "Logged out" +msgstr "Logget ut" + +msgid "Password reset" +msgstr "Tilbakestilling av passord" + +msgid "Password reset sent" +msgstr "Passord-nullstilling sendt" + +msgid "Enter new password" +msgstr "Skriv inn nytt passord" + +msgid "Password reset unsuccessful" +msgstr "Tilbakestilling av passord feilet" + +msgid "Password reset complete" +msgstr "Tilbakestilling av passord fullført" + +msgid "Password change" +msgstr "Passordbytte" + +msgid "Password change successful" +msgstr "Passordbytte gjennomført" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ne/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ne/LC_MESSAGES/django.mo new file mode 100644 index 0000000..6d0eb4a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ne/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ne/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ne/LC_MESSAGES/django.po new file mode 100644 index 0000000..6555827 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ne/LC_MESSAGES/django.po @@ -0,0 +1,286 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Sagar Chalise , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-12-15 05:39+0000\n" +"Last-Translator: Sagar Chalise \n" +"Language-Team: Nepali (http://www.transifex.com/django/django/language/ne/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ne\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "व्यक्तिगत विवरण" + +msgid "Permissions" +msgstr "अनुमतिहरु" + +msgid "Important dates" +msgstr "महत्वपूर्ण मितिहरु" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "पासवर्ड सफलतापूर्वक फेरिएको छ ।" + +#, python-format +msgid "Change password: %s" +msgstr "पासवर्ड फेर्नुहोस : %s" + +msgid "Authentication and Authorization" +msgstr "प्रमाणीकरण तथा अनुमति" + +msgid "password" +msgstr "पासवर्ड" + +msgid "last login" +msgstr "पूर्व लगिन" + +msgid "No password set." +msgstr "पासवर्ड राखिएको छैन ।" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "अमान्य पासवर्ड स्वरूप वा अज्ञात ह्यासिङ अलगोरिदम ।" + +msgid "The two password fields didn’t match." +msgstr "" + +msgid "Password" +msgstr "पासवर्ड" + +msgid "Password confirmation" +msgstr "पासवर्ड पुष्टि" + +msgid "Enter the same password as before, for verification." +msgstr "प्रमाणित गर्न पुन: उही पासवर्ड राख्नु होस ।" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"पासवर्ड जस्ताको त्यस्तै राखेको हुँदैन, त्यसैले हेर्न मिल्दैन । पासवर्ड परिवर्तन गर्न यो फारम भर्नु होस ।" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "कृपया सही %(username)s र पासवर्ड राख्नु होस । " + +msgid "This account is inactive." +msgstr "यो खाता सक्रिय छैन । " + +msgid "Email" +msgstr "ई-मेल" + +msgid "New password" +msgstr "नयाँ पासवर्ड" + +msgid "New password confirmation" +msgstr "नयाँ पासवर्ड पुष्टि" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "तपाईको पुरानो पासवर्ड गलत भयो । कृपया पुन: हाल्नुहोस । " + +msgid "Old password" +msgstr "पुरानो पासवर्ड" + +msgid "Password (again)" +msgstr "पासवर्ड (पुन:)" + +msgid "algorithm" +msgstr "अल्गोरिदम" + +msgid "iterations" +msgstr "पुनरावृत्ति" + +msgid "salt" +msgstr "साल्ट" + +msgid "hash" +msgstr "ह्यास" + +msgid "variety" +msgstr "विविध" + +msgid "version" +msgstr "भर्जन" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "समय" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "वर्क फ्याक्टर" + +msgid "checksum" +msgstr "चेकसम" + +msgid "name" +msgstr "नाम" + +msgid "content type" +msgstr "कन्टेन्ट टाइप" + +msgid "codename" +msgstr "कोडनेम" + +msgid "permission" +msgstr "अनुमति" + +msgid "permissions" +msgstr "अनुमति" + +msgid "group" +msgstr "समुह" + +msgid "groups" +msgstr "समुहहरु" + +msgid "superuser status" +msgstr "प्रधान प्रयोगकर्ता प्रतिष्ठा " + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "प्रयोग कर्ताका अनुमति " + +msgid "Specific permissions for this user." +msgstr "यो प्रयोगकर्ताको लागि तोकिएको अनुमति ।" + +msgid "username" +msgstr "प्रयोगकर्ता नाम" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "आवश्यक । बढिमा १५० वटा (अक्षर, अंक तथा '@/./+/-/_ ' मात्र)" + +msgid "A user with that username already exists." +msgstr "त्यो प्रयोगकर्ता नाम भएका व्यक्ति पहिले नै छन् ।" + +msgid "first name" +msgstr "नाम" + +msgid "last name" +msgstr "थर" + +msgid "email address" +msgstr "ई-मेल ठेगाना" + +msgid "staff status" +msgstr "स्टाफ प्रतिष्ठा " + +msgid "Designates whether the user can log into this admin site." +msgstr "" + +msgid "active" +msgstr "सक्रिय " + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" + +msgid "date joined" +msgstr "दर्ता भएको मिति" + +msgid "user" +msgstr "प्रयोगकर्ता" + +msgid "users" +msgstr "प्रयोगकर्ता" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "पासवर्ड छोटो भयो । कम्तीमा %(min_length)d लम्बाई हुनु पर्दछ ।" +msgstr[1] "पासवर्ड छोटो भयो । कम्तीमा %(min_length)d लम्बाई हुनु पर्दछ ।" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "पासवर्डमा कम्तीमा पनि %(min_length)d अक्षर हुनु पर्छ । " +msgstr[1] "पासवर्डमा कम्तीमा पनि %(min_length)d अक्षरहरू हुनु पर्छ । " + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "%(verbose_name)s संग मिल्दो पासवर्ड भयो ।" + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "यो पासवर्ड साधारण भयो ।" + +msgid "Your password can’t be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "यो पासवर्डमा अंक मात्र छ ।" + +msgid "Your password can’t be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "%(site_name)s को पासवर्ड पून: राख्नु " + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"उपयुक्त प्रयोगकर्ता नाम राख्नु होस । अङ्ग्रेजी अक्षर, अङ्क र @/./+/-/_ मात्र मान्य छन् ।" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "उपयुक्त प्रयोगकर्ता नाम राख्नु होस । अक्षर, अङ्क र @/./+/-/_ मात्र मान्य छन् ।" + +msgid "Logged out" +msgstr "लग आउट " + +msgid "Password reset" +msgstr "पासवर्ड पून: दर्ता" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "नयाँ पासवर्ड राख्नु होस ।" + +msgid "Password reset unsuccessful" +msgstr "" + +msgid "Password reset complete" +msgstr "" + +msgid "Password change" +msgstr "पासवर्ड फेर्नु" + +msgid "Password change successful" +msgstr "पासवर्ड फेर्न सफल" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/nl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/nl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a3dd8c6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/nl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/nl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/nl/LC_MESSAGES/django.po new file mode 100644 index 0000000..f1524f3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/nl/LC_MESSAGES/django.po @@ -0,0 +1,318 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bas Peschier , 2013 +# Erik Romijn , 2013 +# Erik Romijn , 2013 +# Evelijn Saaltink , 2016 +# Harro van der Klauw , 2012 +# Ilja Maas , 2015 +# jaap3 , 2016 +# Jannis Leidel , 2011 +# 6a27f10aef159701c7a5ff07f0fb0a78_05545ed , 2011-2012 +# 8de006b1b0894aab6aef71979dcd8bd6_5c6b207 , 2015 +# Tino de Bruijn , 2011 +# Tonnes , 2019,2022-2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-12-04 08:09+0000\n" +"Last-Translator: Tonnes , 2019,2022-2023\n" +"Language-Team: Dutch (http://app.transifex.com/django/django/language/nl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Persoonlijke gegevens" + +msgid "Permissions" +msgstr "Rechten" + +msgid "Important dates" +msgstr "Belangrijke datums" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(name)s-object met primaire sleutel %(key)r bestaat niet." + +msgid "Password changed successfully." +msgstr "Het wachtwoord is gewijzigd." + +#, python-format +msgid "Change password: %s" +msgstr "Wachtwoord wijzigen: %s" + +msgid "Authentication and Authorization" +msgstr "Authenticatie en autorisatie" + +msgid "password" +msgstr "wachtwoord" + +msgid "last login" +msgstr "laatste aanmelding" + +msgid "No password set." +msgstr "Er is geen wachtwoord ingesteld." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Ongeldige wachtwoordindeling of onbekend hash-algoritme." + +msgid "The two password fields didn’t match." +msgstr "De twee wachtwoordvelden komen niet overeen." + +msgid "Password" +msgstr "Wachtwoord" + +msgid "Password confirmation" +msgstr "Bevestiging wachtwoord" + +msgid "Enter the same password as before, for verification." +msgstr "Voer ter verificatie nogmaals het wachtwoord in." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Wachtwoorden worden niet als tekst opgeslagen, dus u kunt het wachtwoord van " +"deze gebruiker niet zien. U kunt het wel wijzigen via dit " +"formulier." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Voer een juiste %(username)s en wachtwoord in. Let op dat beide velden " +"hoofdlettergevoelig zijn." + +msgid "This account is inactive." +msgstr "Deze account is inactief." + +msgid "Email" +msgstr "E-mailadres" + +msgid "New password" +msgstr "Nieuw wachtwoord" + +msgid "New password confirmation" +msgstr "Nieuw wachtwoord bevestigen" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Uw oude wachtwoord is niet juist ingevoerd. Voer het opnieuw in." + +msgid "Old password" +msgstr "Oud wachtwoord" + +msgid "Password (again)" +msgstr "Wachtwoord (nogmaals)" + +msgid "algorithm" +msgstr "algoritme" + +msgid "iterations" +msgstr "iteraties" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "variatie" + +msgid "version" +msgstr "versie" + +msgid "memory cost" +msgstr "geheugenkosten" + +msgid "time cost" +msgstr "tijdskosten" + +msgid "parallelism" +msgstr "evenwijdigheid" + +msgid "work factor" +msgstr "arbeidsfactor" + +msgid "checksum" +msgstr "checksum" + +msgid "block size" +msgstr "blokgrootte" + +msgid "name" +msgstr "naam" + +msgid "content type" +msgstr "inhoudstype" + +msgid "codename" +msgstr "codenaam" + +msgid "permission" +msgstr "recht" + +msgid "permissions" +msgstr "rechten" + +msgid "group" +msgstr "groep" + +msgid "groups" +msgstr "groepen" + +msgid "superuser status" +msgstr "supergebruikerstatus" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Bepaalt dat deze gebruiker alle rechten heeft, zonder deze expliciet toe te " +"wijzen." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"De groep waartoe deze gebruiker behoort. Gebruikers krijgen alle rechten " +"behorende bij hun groepen." + +msgid "user permissions" +msgstr "gebruikersrechten" + +msgid "Specific permissions for this user." +msgstr "Specifieke rechten voor deze gebruiker." + +msgid "username" +msgstr "gebruikersnaam" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Vereist. 150 tekens of minder. Alleen letters, cijfers en de tekens @/,/+/-/" +"_ zijn toegestaan." + +msgid "A user with that username already exists." +msgstr "Er bestaat al een gebruiker met deze gebruikersnaam." + +msgid "first name" +msgstr "voornaam" + +msgid "last name" +msgstr "achternaam" + +msgid "email address" +msgstr "e-mailadres" + +msgid "staff status" +msgstr "stafstatus" + +msgid "Designates whether the user can log into this admin site." +msgstr "Bepaalt of de gebruiker zich op deze beheerwebsite kan aanmelden." + +msgid "active" +msgstr "actief" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Bepaalt of deze gebruiker als actief dient te worden behandeld. U kunt dit " +"uitvinken in plaats van een gebruiker te verwijderen." + +msgid "date joined" +msgstr "datum toegetreden" + +msgid "user" +msgstr "gebruiker" + +msgid "users" +msgstr "gebruikers" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Dit wachtwoord is te kort. De minimale lengte is %(min_length)d teken." +msgstr[1] "" +"Dit wachtwoord is te kort. De minimale lengte is %(min_length)d tekens." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Uw wachtwoord moet minstens %(min_length)d teken lang zijn." +msgstr[1] "Uw wachtwoord moet minstens %(min_length)d tekens lang zijn." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Het wachtwoord lijkt te veel op de %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" +"Uw wachtwoord mag niet te veel op uw andere persoonlijke gegevens lijken." + +msgid "This password is too common." +msgstr "Dit wachtwoord is te algemeen." + +msgid "Your password can’t be a commonly used password." +msgstr "Uw wachtwoord mag geen veelgebruikt wachtwoord zijn." + +msgid "This password is entirely numeric." +msgstr "Dit wachtwoord bevat alleen cijfers." + +msgid "Your password can’t be entirely numeric." +msgstr "Uw wachtwoord mag niet volledig uit cijfers bestaan." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Wachtwoordherinitialisatie voor %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Voer een geldige gebruikersnaam in. Deze waarde mag alleen de kleine letters " +"a-z en hoofdletters A-Z zonder accenten, cijfers en de tekens @/./+/-/_ " +"bevatten." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Voer een geldige gebruikersnaam in. Deze waarde mag alleen letters, cijfers " +"en de tekens @/./+/-/_ bevatten." + +msgid "Logged out" +msgstr "Afgemeld" + +msgid "Password reset" +msgstr "Wachtwoordherinitialisatie" + +msgid "Password reset sent" +msgstr "Wachtwoordherinitialisatie verstuurd" + +msgid "Enter new password" +msgstr "Voer nieuw wachtwoord in" + +msgid "Password reset unsuccessful" +msgstr "Wachtwoordherinitialisatie mislukt" + +msgid "Password reset complete" +msgstr "Wachtwoordherinitialisatie voltooid" + +msgid "Password change" +msgstr "Wachtwoordwijziging" + +msgid "Password change successful" +msgstr "Wachtwoordwijziging is geslaagd" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/nn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/nn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..33f7a50 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/nn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/nn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/nn/LC_MESSAGES/django.po new file mode 100644 index 0000000..3216de3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/nn/LC_MESSAGES/django.po @@ -0,0 +1,301 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Sivert Olstad, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2021-11-12 08:38+0000\n" +"Last-Translator: Sivert Olstad\n" +"Language-Team: Norwegian Nynorsk (http://www.transifex.com/django/django/" +"language/nn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Personleg informasjon" + +msgid "Permissions" +msgstr "Løyve" + +msgid "Important dates" +msgstr "Viktige datoar" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(name)s-objekt med primærnøkkelen %(key)r eksisterer ikkje." + +msgid "Password changed successfully." +msgstr "Passordet er endra." + +#, python-format +msgid "Change password: %s" +msgstr "Endre passord: %s" + +msgid "Authentication and Authorization" +msgstr "Stadfesting og Autorisasjon" + +msgid "password" +msgstr "passord" + +msgid "last login" +msgstr "siste innlogging" + +msgid "No password set." +msgstr "Passord ikkje sett." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Ugyldig passordformat eller ukjend hash-algoritme." + +msgid "The two password fields didn’t match." +msgstr "Dei to passordfelta er ikkje like." + +msgid "Password" +msgstr "Passord" + +msgid "Password confirmation" +msgstr "Stadfesting av passord" + +msgid "Enter the same password as before, for verification." +msgstr "Skriv inn det samme passordet som før, for verifisering." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Sjølve passordet vert ikkje lagra, så det finnast ingen måte å sjå denne " +"brukaren sitt passord, men du kan endra passordet med dette " +"skjemaet." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Oppgje korrekt %(username)s og passord. Merk at det er skilnad på små og " +"store bokstavar." + +msgid "This account is inactive." +msgstr "Denne kontoen er inaktiv." + +msgid "Email" +msgstr "E-post" + +msgid "New password" +msgstr "Nytt passord" + +msgid "New password confirmation" +msgstr "Stadfest nytt passord" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Det gamle passordet er feil. Prøv omatt." + +msgid "Old password" +msgstr "Gammalt passord" + +msgid "Password (again)" +msgstr "Passord (gjenta)" + +msgid "algorithm" +msgstr "algoritme" + +msgid "iterations" +msgstr "iterasjonar" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "variasjon" + +msgid "version" +msgstr "versjon" + +msgid "memory cost" +msgstr "minnekostnad" + +msgid "time cost" +msgstr "tidskostnad" + +msgid "parallelism" +msgstr "parallellitet" + +msgid "work factor" +msgstr "arbeidsfaktor" + +msgid "checksum" +msgstr "kontrollsum" + +msgid "block size" +msgstr "blokkstorleik" + +msgid "name" +msgstr "namn" + +msgid "content type" +msgstr "innhaldstype" + +msgid "codename" +msgstr "kodenamn" + +msgid "permission" +msgstr "løyve" + +msgid "permissions" +msgstr "løyve" + +msgid "group" +msgstr "gruppe" + +msgid "groups" +msgstr "grupper" + +msgid "superuser status" +msgstr "superbrukar" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "Angir at denne brukaren har alle løyve utan å eksplisitt sette dei." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Gruppene brukaren tilhøyrer. Brukarar får løyva til gruppene dei er med i." + +msgid "user permissions" +msgstr "Brukerløyve" + +msgid "Specific permissions for this user." +msgstr "Løyva til denne brukaren." + +msgid "username" +msgstr "brukarnamn" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "Nødvendig. 150 teikn eller færre. Berre bokstavar, tall @/./+/-/_." + +msgid "A user with that username already exists." +msgstr "Det eksisterar allereie ein brukar med dette brukernamnet." + +msgid "first name" +msgstr "fornamn" + +msgid "last name" +msgstr "etternamn" + +msgid "email address" +msgstr "e-postadresse" + +msgid "staff status" +msgstr "administrasjonsstatus" + +msgid "Designates whether the user can log into this admin site." +msgstr "Angir at brukaren kan logge inn på denne administrasjonssida." + +msgid "active" +msgstr "aktiv" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Angir at denne brukaren er aktiv. Avmerk denne i staden for å slette kontoen." + +msgid "date joined" +msgstr "registrert" + +msgid "user" +msgstr "brukar" + +msgid "users" +msgstr "brukarar" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Dette passordet er for stutt. Det må innehalde minst %(min_length)d teikn." +msgstr[1] "" +"Dette passordet er for stutt. Det må innehalde minst %(min_length)d teikn." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Passordet ditt må innehalde minst %(min_length)d teikn." +msgstr[1] "Passordet ditt må innehalde minst %(min_length)d teikn." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Passordet er for likt %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Passordet ditt kan ikkje vere for likt dine andre personopplysingar." + +msgid "This password is too common." +msgstr "Dette passordet er for vanleg." + +msgid "Your password can’t be a commonly used password." +msgstr "Passordet ditt kan ikkje vere eit ofte brukt passord." + +msgid "This password is entirely numeric." +msgstr "Dette passordet innehalder berre tal." + +msgid "Your password can’t be entirely numeric." +msgstr "Passordet ditt kan ikkje innehalde berre tal." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Passordnullstilling på %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"Oppgje eit gyldig brukarnamn. Denne verdien kan berre innehalde bokstavar, " +"tal, og @/./+/-/_ teikn." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Oppgje eit gyldig brukarnamn. Denne verdien kan berre innehalde bokstavar, " +"tal, og @/./+/-/_ teikn." + +msgid "Logged out" +msgstr "Logga ut" + +msgid "Password reset" +msgstr "Nullstill passord" + +msgid "Password reset sent" +msgstr "Passordnullstilling utsendt" + +msgid "Enter new password" +msgstr "Oppgje nytt passord" + +msgid "Password reset unsuccessful" +msgstr "Passordet vart ikkje nullstilt" + +msgid "Password reset complete" +msgstr "Passord nullstilt" + +msgid "Password change" +msgstr "Endre passord" + +msgid "Password change successful" +msgstr "Passord endra" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/os/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/os/LC_MESSAGES/django.mo new file mode 100644 index 0000000..062d3a9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/os/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/os/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/os/LC_MESSAGES/django.po new file mode 100644 index 0000000..e762d72 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/os/LC_MESSAGES/django.po @@ -0,0 +1,288 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Soslan Khubulov , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-09-24 14:24+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Ossetic (http://www.transifex.com/django/django/language/" +"os/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: os\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Персоналон инфо" + +msgid "Permissions" +msgstr "Бартӕ" + +msgid "Important dates" +msgstr "Ахсджиаг бонтӕ" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "Пароль ивд ӕрцыд." + +#, python-format +msgid "Change password: %s" +msgstr "Фӕив пароль: %s" + +msgid "Authentication and Authorization" +msgstr "" + +msgid "password" +msgstr "пароль" + +msgid "last login" +msgstr "фӕстаг бахызт" + +msgid "No password set." +msgstr "Ницы пароль уыд ӕвӕрд." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Паролы формат раст нӕу, кӕнӕ хӕшты алгоритм бӕрӕг нӕу." + +msgid "The two password fields didn't match." +msgstr "Дыууӕ паролы ӕмхуызӕн не сты." + +msgid "Password" +msgstr "Пароль" + +msgid "Password confirmation" +msgstr "Паролы бӕлвырдгӕнӕн" + +msgid "Enter the same password as before, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Дӕ хорзӕхӕй, раст %(username)s ӕмӕ пароль бафысс. Дӕ сӕры дар уый, ӕмӕ дыууӕ " +"дӕр гӕнӕн ис стыр ӕмӕ гыццыл дамгъӕтӕ ӕвзарой." + +msgid "This account is inactive." +msgstr "Ацы аккаунт ницы архайы." + +msgid "Email" +msgstr "Электрон пост" + +msgid "New password" +msgstr "Ног пароль" + +msgid "New password confirmation" +msgstr "Нӕуӕг паролы бӕлвырдгӕнӕн" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Дӕ зӕронд пароль раст амынд нӕу. Дӕ хорзӕхӕй, нӕуӕгӕй йӕ бафысс." + +msgid "Old password" +msgstr "Зӕронд пароль" + +msgid "Password (again)" +msgstr "Пароль (ногӕй)" + +msgid "algorithm" +msgstr "алгоритм" + +msgid "iterations" +msgstr "итерацитӕ" + +msgid "salt" +msgstr "цӕхх" + +msgid "hash" +msgstr "хӕш" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "куысты фактор" + +msgid "checksum" +msgstr "бӕлвырдсуммӕ" + +msgid "name" +msgstr "ном" + +msgid "content type" +msgstr "" + +msgid "codename" +msgstr "кодном" + +msgid "permission" +msgstr "бар" + +msgid "permissions" +msgstr "бартӕ" + +msgid "group" +msgstr "къорд" + +msgid "groups" +msgstr "къордтӕ" + +msgid "superuser status" +msgstr "хистӕр архайӕджы статус" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "Ацы архайӕгӕн алы бар дӕр дӕтты, цӕмӕй сӕ хицӕнӕй дӕттын ма хъӕуа." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "архайӕджы бартӕ" + +msgid "Specific permissions for this user." +msgstr "" + +msgid "username" +msgstr "фӕсномыг" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "Ахӕм фӕсномыгимӕ архайӕг нырид ис." + +msgid "first name" +msgstr "ном" + +msgid "last name" +msgstr "мыггаг" + +msgid "email address" +msgstr "электрон посты адрис" + +msgid "staff status" +msgstr "куысты уавӕр" + +msgid "Designates whether the user can log into this admin site." +msgstr "Бӕрӕг кӕны архайӕгӕн йӕ бон у ацы армдарӕн сайтмӕ хизын, ӕви нӕ." + +msgid "active" +msgstr "активон" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Бӕрӕг кӕны ацы архайӕгы хъӕуы нымайын активоныл, ӕви нӕ. Йӕ нысан ын сис " +"хафыны бӕсты." + +msgid "date joined" +msgstr "баиуы бон" + +msgid "user" +msgstr "архайӕг" + +msgid "users" +msgstr "архайджытӕ" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "" + +msgid "Your password can't be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "" + +msgid "Your password can't be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "" + +msgid "Your password can't be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "%(site_name)s-ы нӕуӕг пароль ӕвӕрӕн" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "Рахизын" + +msgid "Password reset" +msgstr "" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "" + +msgid "Password reset unsuccessful" +msgstr "" + +msgid "Password reset complete" +msgstr "" + +msgid "Password change" +msgstr "" + +msgid "Password change successful" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/pa/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/pa/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9a043b6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/pa/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/pa/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/pa/LC_MESSAGES/django.po new file mode 100644 index 0000000..8a18a6f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/pa/LC_MESSAGES/django.po @@ -0,0 +1,285 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# A S Alam , 2013 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-09-24 14:24+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Panjabi (Punjabi) (http://www.transifex.com/django/django/" +"language/pa/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pa\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "ਨਿੱਜੀ ਜਾਣਕਾਰੀ" + +msgid "Permissions" +msgstr "ਅਧਿਕਾਰ" + +msgid "Important dates" +msgstr "ਖਾਸ ਮਿਤੀਆਂ" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "ਪਾਸਵਰਡ ਠੀਕ ਤਰ੍ਹਾਂ ਬਦਲਿਆ ਗਿਆ ਹੈ।" + +#, python-format +msgid "Change password: %s" +msgstr "ਪਾਸਵਰਡ ਬਦਲੋ: %s" + +msgid "Authentication and Authorization" +msgstr "" + +msgid "password" +msgstr "ਪਾਸਵਰਡ" + +msgid "last login" +msgstr "ਆਖਰੀ ਲਾਗਇਨ" + +msgid "No password set." +msgstr "ਕੋਈ ਪਾਸਵਰਡ ਸੈੱਟ ਨਹੀਂ।" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "ਗਲਤ ਪਾਸਵਰਡ ਫਾਰਮੈਟ ਜਾਂ ਅਣਜਾਣ ਹੈਸ਼ ਐਲੋਗਰਿਥਮ ਹੈ।" + +msgid "The two password fields didn't match." +msgstr "ਦੋਵੇਂ ਪਾਸਵਰਡ ਖੇਤਰ ਮਿਲਦੇ ਨਹੀਂ ਹਨ।" + +msgid "Password" +msgstr "ਪਾਸਵਰਡ" + +msgid "Password confirmation" +msgstr "ਪਾਸਵਰਡ ਪੁਸ਼ਟੀ" + +msgid "Enter the same password as before, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" + +msgid "This account is inactive." +msgstr "ਇਹ ਅਕਾਊਂਟ ਗ਼ੈਰ-ਸਰਗਰਮ ਹੈ।" + +msgid "Email" +msgstr "ਈਮੇਲ" + +msgid "New password" +msgstr "ਨਵਾਂ ਪਾਸਵਰਡ" + +msgid "New password confirmation" +msgstr "ਨਵਾਂ ਪਾਸਵਰਡ ਪੁਸ਼ਟੀ" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "ਤੁਹਾਡਾ ਪੁਰਾਣਾ ਪਾਸਵਰਡ ਗਲਤ ਦਿੱਤਾ ਗਿਆ ਸੀ। ਇਸ ਨੂੰ ਫੇਰ ਦਿਉ ਜੀ।" + +msgid "Old password" +msgstr "ਪੁਰਾਣਾ ਪਾਸਵਰਡ" + +msgid "Password (again)" +msgstr "ਪਾਸਵਰਡ (ਫੇਰ)" + +msgid "algorithm" +msgstr "ਐਲਗੋਰਿਥਮ" + +msgid "iterations" +msgstr "" + +msgid "salt" +msgstr "ਸਾਲਟ" + +msgid "hash" +msgstr "ਹੈਸ਼" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "ਵਰਕ ਫੈਕਟਰ" + +msgid "checksum" +msgstr "ਚੈਕਸਮ" + +msgid "name" +msgstr "ਨਾਂ" + +msgid "content type" +msgstr "" + +msgid "codename" +msgstr "ਕੋਡ-ਨਾਂ" + +msgid "permission" +msgstr "ਅਧਿਕਾਰ" + +msgid "permissions" +msgstr "ਅਧਿਕਾਰ" + +msgid "group" +msgstr "ਗਰੁੱਪ" + +msgid "groups" +msgstr "ਗਰੁੱਪ" + +msgid "superuser status" +msgstr "ਸੁਪਰਯੂਜ਼ਰ ਹਾਲਤ" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "ਯੂਜ਼ਰ ਅਧਿਕਾਰ" + +msgid "Specific permissions for this user." +msgstr "" + +msgid "username" +msgstr "ਯੂਜ਼ਰ ਨਾਂ" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "ਉਸ ਯੂਜ਼ਰ ਨਾਂ ਨਾਲ ਯੂਜ਼ਰ ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ।" + +msgid "first name" +msgstr "ਪਹਿਲਾਂ ਨਾਂ" + +msgid "last name" +msgstr "ਆਖਰੀ ਨਾਂ" + +msgid "email address" +msgstr "ਈਮੇਲ ਐਡਰੈਸ" + +msgid "staff status" +msgstr "ਸਟਾਫ ਹਾਲਤ" + +msgid "Designates whether the user can log into this admin site." +msgstr "" + +msgid "active" +msgstr "ਸਰਗਰਮ" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" + +msgid "date joined" +msgstr "ਜੁਆਇੰਨ ਕਰਨ ਦੀ ਮਿਤੀ" + +msgid "user" +msgstr "ਯੂਜ਼ਰ" + +msgid "users" +msgstr "ਯੂਜ਼ਰ" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "" + +msgid "Your password can't be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "" + +msgid "Your password can't be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "" + +msgid "Your password can't be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "ਲਾਗ ਆਉਟ ਕੀਤਾ" + +msgid "Password reset" +msgstr "" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "" + +msgid "Password reset unsuccessful" +msgstr "" + +msgid "Password reset complete" +msgstr "" + +msgid "Password change" +msgstr "" + +msgid "Password change successful" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/pl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/pl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..21adcc3 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/pl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/pl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/pl/LC_MESSAGES/django.po new file mode 100644 index 0000000..4861a43 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/pl/LC_MESSAGES/django.po @@ -0,0 +1,327 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# angularcircle, 2011,2013 +# Jannis Leidel , 2011 +# Janusz Harkot , 2015 +# Karol , 2012 +# Maciej Olko , 2014 +# Maciej Olko , 2016-2017,2019,2021 +# Maciej Olko , 2023 +# Maciej Olko , 2014-2015 +# Mariusz Felisiak , 2023 +# muszalski , 2016 +# c10516f0462e552b4c3672569f0745a7_cc5cca2 <841826256cd8f47d0e443806a8e56601_19204>, 2014 +# Mattia Procopio , 2014 +# Roman Barczyński, 2012 +# Tomasz Kajtoch , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-04-25 08:09+0000\n" +"Last-Translator: Mariusz Felisiak , 2023\n" +"Language-Team: Polish (http://www.transifex.com/django/django/language/pl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pl\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && " +"(n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && " +"n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" + +msgid "Personal info" +msgstr "Informacje osobiste" + +msgid "Permissions" +msgstr "Uprawnienia" + +msgid "Important dates" +msgstr "Ważne daty" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "Obiekt %(name)s o kluczu podstawowym %(key)r nie istnieje." + +msgid "Password changed successfully." +msgstr "Hasło zostało zmienione pomyślnie." + +#, python-format +msgid "Change password: %s" +msgstr "Zmień hasło: %s" + +msgid "Authentication and Authorization" +msgstr "Uwierzytelnienie i autoryzacja" + +msgid "password" +msgstr "hasło" + +msgid "last login" +msgstr "ostatnie logowanie" + +msgid "No password set." +msgstr "Nie ustawiono hasła." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" +"Format hasła jest niewłaściwy, bądź zastosowana została nieznana funkcja " +"skrótu (hash)." + +msgid "The two password fields didn’t match." +msgstr "Hasła w obu polach nie są zgodne." + +msgid "Password" +msgstr "Hasło" + +msgid "Password confirmation" +msgstr "Potwierdzenie hasła" + +msgid "Enter the same password as before, for verification." +msgstr "Wprowadź to samo hasło ponownie, dla weryfikacji." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Nie przechowujemy surowych haseł, więc nie da się zobaczyć hasła tego " +"użytkownika. Możesz jednak je zmienić używając tego " +"formularza." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Wprowadź poprawne wartości pól %(username)s oraz hasło. Uwaga: wielkość " +"liter ma znaczenie." + +msgid "This account is inactive." +msgstr "To konto jest nieaktywne." + +msgid "Email" +msgstr "Adres e-mail" + +msgid "New password" +msgstr "Nowe hasło" + +msgid "New password confirmation" +msgstr "Nowe hasło (powtórz)" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Podane stare hasło jest niepoprawne. Proszę podać je jeszcze raz." + +msgid "Old password" +msgstr "Stare hasło" + +msgid "Password (again)" +msgstr "Hasło (powtórz)" + +msgid "algorithm" +msgstr "algorytm" + +msgid "iterations" +msgstr "iteracje" + +msgid "salt" +msgstr "sól" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "odmiana" + +msgid "version" +msgstr "wersja" + +msgid "memory cost" +msgstr "koszt pamięci" + +msgid "time cost" +msgstr "koszt czasu" + +msgid "parallelism" +msgstr "zrównoleglenie" + +msgid "work factor" +msgstr "work factor" + +msgid "checksum" +msgstr "suma kontrolna" + +msgid "block size" +msgstr "rozmiar bloku" + +msgid "name" +msgstr "nazwa" + +msgid "content type" +msgstr "typ zawartości" + +msgid "codename" +msgstr "nazwa kodowa" + +msgid "permission" +msgstr "uprawnienie" + +msgid "permissions" +msgstr "uprawnienia" + +msgid "group" +msgstr "grupa" + +msgid "groups" +msgstr "grupy" + +msgid "superuser status" +msgstr "status superużytkownika" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Oznacza, że ten użytkownik ma wszystkie uprawnienia bez ich jawnego " +"przypisywania." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Grupy do których należy użytkownik. Użytkownik otrzyma wszystkie uprawnienia " +"przypisane do każdej z jego grup." + +msgid "user permissions" +msgstr "uprawnienia użytkownika" + +msgid "Specific permissions for this user." +msgstr "Szczególne uprawnienia dla tego użytkownika." + +msgid "username" +msgstr "nazwa użytkownika" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "Wymagana. 150 lub mniej znaków. Jedynie litery, cyfry i @/./+/-/_." + +msgid "A user with that username already exists." +msgstr "Użytkownik o tej nazwie już istnieje." + +msgid "first name" +msgstr "imię" + +msgid "last name" +msgstr "nazwisko" + +msgid "email address" +msgstr "adres e-mail" + +msgid "staff status" +msgstr "w zespole" + +msgid "Designates whether the user can log into this admin site." +msgstr "Określa czy użytkownik może zalogować się do panelu administracyjnego." + +msgid "active" +msgstr "aktywny" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Określa czy użytkownika należy uważać za aktywnego. Odznacz zamiast usuwać " +"konto." + +msgid "date joined" +msgstr "data dołączenia" + +msgid "user" +msgstr "użytkownik" + +msgid "users" +msgstr "użytkownicy" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"To hasło jest za krótkie. Musi zawierać co najmniej %(min_length)d znak." +msgstr[1] "" +"To hasło jest za krótkie. Musi zawierać co najmniej %(min_length)d znaki." +msgstr[2] "" +"To hasło jest za krótkie. Musi zawierać co najmniej %(min_length)d znaków." +msgstr[3] "" +"To hasło jest za krótkie. Musi zawierać co najmniej %(min_length)d znaków." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Twoje hasło musi zawierać co najmniej %(min_length)d znak." +msgstr[1] "Twoje hasło musi zawierać co najmniej %(min_length)d znaki." +msgstr[2] "Twoje hasło musi zawierać co najmniej %(min_length)d znaków." +msgstr[3] "Twoje hasło musi zawierać co najmniej %(min_length)d znaków." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Hasło jest zbyt podobne do %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" +"Twoje hasło nie może być zbyt podobne do twoich innych danych osobistych." + +msgid "This password is too common." +msgstr "To hasło jest zbyt powszechne." + +msgid "Your password can’t be a commonly used password." +msgstr "Twoje hasło nie może być powszechnie używanym hasłem." + +msgid "This password is entirely numeric." +msgstr "Hasło składa się wyłącznie z cyfr." + +msgid "Your password can’t be entirely numeric." +msgstr "Twoje hasło nie może składać się tylko z cyfr." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Reset hasła dla konta na stronie %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Wprowadź poprawną nazwę użytkownika. Wartość może zawierać jedynie małe a-z " +"i duże A-Z litery bez znaków diakrytycznych, cyfry, i znaki @/./+/-/_." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Wprowadź poprawną nazwę użytkownika. Wartość może zawierać jedynie litery, " +"cyfry i znaki @/./+/-/_." + +msgid "Logged out" +msgstr "Wylogowany(-na)" + +msgid "Password reset" +msgstr "Zresetowanie hasła" + +msgid "Password reset sent" +msgstr "Potwierdzenie zresetowania hasła zostało wysłane" + +msgid "Enter new password" +msgstr "Wprowadź nowe haslo" + +msgid "Password reset unsuccessful" +msgstr "Resetowanie hasła nie powiodło się" + +msgid "Password reset complete" +msgstr "Resetowanie hasła zakończone" + +msgid "Password change" +msgstr "Zmiana hasła" + +msgid "Password change successful" +msgstr "Hasło zostało zmienione pomyślnie" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/pt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/pt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..06e08e0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/pt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/pt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/pt/LC_MESSAGES/django.po new file mode 100644 index 0000000..2a21196 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/pt/LC_MESSAGES/django.po @@ -0,0 +1,314 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Claude Paroz , 2017 +# Jannis Leidel , 2011 +# jorgecarleitao , 2015 +# Nuno Mariz , 2013,2015,2017,2023 +# Raúl Pedro Fernandes Santos, 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-12-04 08:09+0000\n" +"Last-Translator: Nuno Mariz , 2013,2015,2017,2023\n" +"Language-Team: Portuguese (http://app.transifex.com/django/django/language/" +"pt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Informação pessoal" + +msgid "Permissions" +msgstr "Permissões" + +msgid "Important dates" +msgstr "Datas importantes" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "O objecto %(name)s com a chave primária %(key)r não existe." + +msgid "Password changed successfully." +msgstr "Palavra-passe modificada com sucesso." + +#, python-format +msgid "Change password: %s" +msgstr "Modificar a palavra-passe: %s" + +msgid "Authentication and Authorization" +msgstr "Autenticação e Autorização" + +msgid "password" +msgstr "palavra-passe" + +msgid "last login" +msgstr "última entrada" + +msgid "No password set." +msgstr "Nenhuma palavra-chave definida." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Formato de palavra-chave inválido ou função de mistura desconhecida." + +msgid "The two password fields didn’t match." +msgstr "As duas palavra-passe não coincidem." + +msgid "Password" +msgstr "Palavra-passe" + +msgid "Password confirmation" +msgstr "Confirmação da palavra-passe" + +msgid "Enter the same password as before, for verification." +msgstr "Introduza a palavra-passe como acima, para verificação." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Por favor introduza o %(username)s e password corretos. Tenha em atenção às " +"maiúsculas e minúsculas." + +msgid "This account is inactive." +msgstr "Esta conta não está activa." + +msgid "Email" +msgstr "Email" + +msgid "New password" +msgstr "Nova palavra-passe" + +msgid "New password confirmation" +msgstr "Confirmação da nova palavra-passe" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" +"A sua palavra-passe antiga foi introduzida incorretamente. Por favor tente " +"novamente." + +msgid "Old password" +msgstr "Palavra-passe antiga" + +msgid "Password (again)" +msgstr "Palavra-passe (novamente)" + +msgid "algorithm" +msgstr "algoritmo" + +msgid "iterations" +msgstr "iterações" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "variedade" + +msgid "version" +msgstr "versão" + +msgid "memory cost" +msgstr "custo da memória" + +msgid "time cost" +msgstr "custo de tempo" + +msgid "parallelism" +msgstr "paralelismo" + +msgid "work factor" +msgstr "fator trabalho" + +msgid "checksum" +msgstr "verificação" + +msgid "block size" +msgstr "tamanho do bloco" + +msgid "name" +msgstr "nome" + +msgid "content type" +msgstr "tipo de conteúdo" + +msgid "codename" +msgstr "nome de código" + +msgid "permission" +msgstr "permissão" + +msgid "permissions" +msgstr "permissões" + +msgid "group" +msgstr "grupo" + +msgid "groups" +msgstr "grupos" + +msgid "superuser status" +msgstr "Status de superuser" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Define se este utilizador tem todas as permissões sem explicitamente as " +"atribuir." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Os grupos que este utilizador pertence. Um utilizador terá todas as " +"permissões concedidas a cada um dos seus grupos." + +msgid "user permissions" +msgstr "permissões do utilizador" + +msgid "Specific permissions for this user." +msgstr "Permissões específicas para este utilizador." + +msgid "username" +msgstr "utilizador" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "Obrigatório. 150 carateres ou menos. Apenas letras, dígitos @/./+/-/_." + +msgid "A user with that username already exists." +msgstr "Já existe um utilizador com esse nome." + +msgid "first name" +msgstr "primeiro nome" + +msgid "last name" +msgstr "último nome" + +msgid "email address" +msgstr "endereço de email" + +msgid "staff status" +msgstr "status de equipa" + +msgid "Designates whether the user can log into this admin site." +msgstr "Define se o utilizador pode usar a administração do site." + +msgid "active" +msgstr "ativo" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Defina se este utilizador deva ser tratado como ativo. Não selecione em vez " +"de remover as contas." + +msgid "date joined" +msgstr "data de registo" + +msgid "user" +msgstr "utilizador" + +msgid "users" +msgstr "utilizadores" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Esta palavra-passe é muito curta. Deve conter pelo menos %(min_length)d " +"caractere." +msgstr[1] "" +"Esta palavra-passe é muito curta. Deve conter pelo menos %(min_length)d " +"caracteres." +msgstr[2] "" +"Esta palavra-passe é muito curta. Deve conter pelo menos %(min_length)d " +"caracteres." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +"A sua palavra-passe deve conter pelo menos %(min_length)d caractere." +msgstr[1] "" +"A sua palavra-passe deve conter pelo menos %(min_length)d caracteres." +msgstr[2] "" +"A sua palavra-passe deve conter pelo menos %(min_length)d caracteres." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "A palavra-passe é muito semelhante ao %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "Esta palavra-passe é muito comum." + +msgid "Your password can’t be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "Esta palavra-passe é inteiramente numérica." + +msgid "Your password can’t be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Redefinição de palavra-passe em %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Insira um nome de utilizador válido. Este valor apenas deverá conter letras, " +"números e carateres @/./+/-/_." + +msgid "Logged out" +msgstr "Saiu" + +msgid "Password reset" +msgstr "Gerar nova palavra-passe" + +msgid "Password reset sent" +msgstr "Redefinição de palavra-passe enviada" + +msgid "Enter new password" +msgstr "Introduza nova palavra-passe" + +msgid "Password reset unsuccessful" +msgstr "A mudança da palavra-passe não foi bem sucedida" + +msgid "Password reset complete" +msgstr "Geração de nova palavra-passe completa" + +msgid "Password change" +msgstr "Mudança de palavra-passe" + +msgid "Password change successful" +msgstr "Mudança de palavra-passe bem sucedida" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/pt_BR/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/pt_BR/LC_MESSAGES/django.mo new file mode 100644 index 0000000..35f0116 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/pt_BR/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/pt_BR/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/pt_BR/LC_MESSAGES/django.po new file mode 100644 index 0000000..2fd5867 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/pt_BR/LC_MESSAGES/django.po @@ -0,0 +1,333 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Allisson Azevedo , 2014 +# Amanda Savluchinske , 2019 +# amcorreia , 2018 +# Camilo B. Moreira , 2017 +# Carlos C. Leite , 2016 +# Filipe Cifali , 2016 +# Claudemiro Alves Feitosa Neto , 2015 +# dudanogueira , 2012 +# dudanogueira , 2014 +# Eduardo Cereto Carvalho, 2013 +# Elyézer Rezende , 2013 +# Evandro da Costa , 2023 +# Fábio C. Barrionuevo da Luz , 2015 +# gilberto dos santos alves , 2013 +# fa9e10542e458baef0599ae856e43651_13d2225, 2012 +# Guilherme , 2022 +# Jannis Leidel , 2011 +# Lucas Infante , 2015 +# Rafael Fontenelle , 2022 +# Sandro , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-12-04 08:09+0000\n" +"Last-Translator: Evandro da Costa , 2023\n" +"Language-Team: Portuguese (Brazil) (http://app.transifex.com/django/django/" +"language/pt_BR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt_BR\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Personal info" +msgstr "Informações pessoais" + +msgid "Permissions" +msgstr "Permissões" + +msgid "Important dates" +msgstr "Datas importantes" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "objeto %(name)s com chave primária %(key)r não existe." + +msgid "Password changed successfully." +msgstr "Senha modificada com sucesso." + +#, python-format +msgid "Change password: %s" +msgstr "Alterar senha: %s" + +msgid "Authentication and Authorization" +msgstr "Autenticação e Autorização" + +msgid "password" +msgstr "senha" + +msgid "last login" +msgstr "último login" + +msgid "No password set." +msgstr "Nenhuma senha definida." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Formato de senha inválido ou algoritmo de hash desconhecido." + +msgid "The two password fields didn’t match." +msgstr "Os dois campos de senha não correspondem." + +msgid "Password" +msgstr "Senha" + +msgid "Password confirmation" +msgstr "Confirmação de senha" + +msgid "Enter the same password as before, for verification." +msgstr "Informe a mesma senha informada anteriormente, para verificação." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Senhas brutas não são armazenadas, então não há como visualizar a senha " +"desse usuário, porém você pode mudar a senha usando esse " +"form." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Por favor, entre com um %(username)s e senha corretos. Note que ambos os " +"campos diferenciam maiúsculas e minúsculas." + +msgid "This account is inactive." +msgstr "Esta conta está inativa." + +msgid "Email" +msgstr "Email" + +msgid "New password" +msgstr "Nova senha" + +msgid "New password confirmation" +msgstr "Confirmação da nova senha" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" +"A senha antiga foi digitada incorretamente. Por favor, informe-a novamente." + +msgid "Old password" +msgstr "Senha antiga" + +msgid "Password (again)" +msgstr "Senha (novamente)" + +msgid "algorithm" +msgstr "algoritmo" + +msgid "iterations" +msgstr "iterações" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "variedade" + +msgid "version" +msgstr "versão" + +msgid "memory cost" +msgstr "custo de memória" + +msgid "time cost" +msgstr "custo de tempo" + +msgid "parallelism" +msgstr "paralelismo" + +msgid "work factor" +msgstr "fator de trabalho" + +msgid "checksum" +msgstr "checksum" + +msgid "block size" +msgstr "tamanho de bloco" + +msgid "name" +msgstr "nome" + +msgid "content type" +msgstr "tipo de conteúdo" + +msgid "codename" +msgstr "apelido" + +msgid "permission" +msgstr "permissão" + +msgid "permissions" +msgstr "permissões" + +msgid "group" +msgstr "grupo" + +msgid "groups" +msgstr "grupos" + +msgid "superuser status" +msgstr "status de superusuário" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Indica que este usuário tem todas as permissões sem atribuí-las " +"explicitamente." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Os grupos que este usuário pertence. Um usuário terá todas as permissões " +"concedidas a cada um dos seus grupos." + +msgid "user permissions" +msgstr "permissões do usuário" + +msgid "Specific permissions for this user." +msgstr "Permissões específicas para este usuário." + +msgid "username" +msgstr "usuário" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Obrigatório. 150 caracteres ou menos. Letras, números e @/./+/-/_ apenas." + +msgid "A user with that username already exists." +msgstr "Um usuário com este nome de usuário já existe." + +msgid "first name" +msgstr "primeiro nome" + +msgid "last name" +msgstr "último nome" + +msgid "email address" +msgstr "endereço de email" + +msgid "staff status" +msgstr "membro da equipe" + +msgid "Designates whether the user can log into this admin site." +msgstr "Indica que usuário consegue acessar este site de administração." + +msgid "active" +msgstr "ativo" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Indica que o usuário será tratado como ativo. Ao invés de excluir contas de " +"usuário, desmarque isso." + +msgid "date joined" +msgstr "data de registro" + +msgid "user" +msgstr "usuário" + +msgid "users" +msgstr "usuários" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Esta senha é muito curta. Ela precisa conter pelo menos %(min_length)d " +"caracteres." +msgstr[1] "" +"Esta senha é muito curta. Ela precisa conter pelo menos %(min_length)d " +"caracteres." +msgstr[2] "" +"Esta senha é muito curta. Ela precisa conter pelo menos %(min_length)d " +"caracteres." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Sua senha precisa conter pelo menos %(min_length)d caracteres." +msgstr[1] "Sua senha precisa conter pelo menos %(min_length)d caracteres." +msgstr[2] "Sua senha precisa conter pelo menos %(min_length)d caracteres." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "A senha é muito parecida com %(verbose_name)s" + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" +"Sua senha não pode ser muito parecida com o resto das suas informações " +"pessoais." + +msgid "This password is too common." +msgstr "Esta senha é muito comum." + +msgid "Your password can’t be a commonly used password." +msgstr "Sua senha não pode ser uma senha comumente utilizada." + +msgid "This password is entirely numeric." +msgstr "Esta senha é inteiramente numérica." + +msgid "Your password can’t be entirely numeric." +msgstr "Sua senha não pode ser inteiramente numérica." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Redefinição de senha em %(site_name)s " + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Insira um nome de usuário válido. Este valor pode conter apenas letras, " +"números e os caracteres @/./+/-/_." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Informe um nome de usuário válido. Este valor pode conter apenas letras, " +"números e os seguintes caracteres @/./+/-/_." + +msgid "Logged out" +msgstr "Sessão encerrada" + +msgid "Password reset" +msgstr "Redefinição de senha" + +msgid "Password reset sent" +msgstr "Redefinição de senha enviada" + +msgid "Enter new password" +msgstr "Digite a nova senha" + +msgid "Password reset unsuccessful" +msgstr "Redefinição de senha sem sucesso" + +msgid "Password reset complete" +msgstr "Redefinição de senha completa" + +msgid "Password change" +msgstr "Alteração de Senha" + +msgid "Password change successful" +msgstr "Mudança de senha bem sucedida" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ro/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ro/LC_MESSAGES/django.mo new file mode 100644 index 0000000..bdaa778 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ro/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ro/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ro/LC_MESSAGES/django.po new file mode 100644 index 0000000..dc39194 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ro/LC_MESSAGES/django.po @@ -0,0 +1,320 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bogdan Mateescu, 2018 +# Daniel Ursache-Dogariu, 2011 +# Denis Darii , 2011 +# Eugenol Man , 2020 +# Jannis Leidel , 2011 +# razvan ionescu , 2015 +# Razvan Stefanescu , 2016-2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-07-15 11:11+0000\n" +"Last-Translator: Eugenol Man \n" +"Language-Team: Romanian (http://www.transifex.com/django/django/language/" +"ro/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ro\n" +"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?" +"2:1));\n" + +msgid "Personal info" +msgstr "Informații personale" + +msgid "Permissions" +msgstr "Permisiuni" + +msgid "Important dates" +msgstr "Date importante" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "Obiectul %(name)s cu cheia primară %(key)r nu există." + +msgid "Password changed successfully." +msgstr "Parolă schimbată cu succes." + +#, python-format +msgid "Change password: %s" +msgstr "Schimbă parola: %s" + +msgid "Authentication and Authorization" +msgstr "Autentificare și autorizare" + +msgid "password" +msgstr "parolă" + +msgid "last login" +msgstr "ultima autentificare" + +msgid "No password set." +msgstr "Parola nu este setată." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" +"Parolă nu are formatarea corectă sau algoritmul de criptare nu este cunoscut." + +msgid "The two password fields didn’t match." +msgstr "Cele două parole nu corespund." + +msgid "Password" +msgstr "Parolă" + +msgid "Password confirmation" +msgstr "Confirmare parolă" + +msgid "Enter the same password as before, for verification." +msgstr "Introduceți parola precedentă pentru confirmare." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Parolele nu sunt salvate în clar așa că nu poți vedea parola. O poți schimba " +"de aici." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Introduceți vă rog un %(username)s corect și o parolă. Reţineţi că ambele " +"câmpuri pot fi sensibile la litere mari şi mici." + +msgid "This account is inactive." +msgstr "Acest cont este inactiv." + +msgid "Email" +msgstr "Email" + +msgid "New password" +msgstr "Parolă nouă" + +msgid "New password confirmation" +msgstr "Confirmarea parolă nouă" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Parola veche a fost introdusă greșit. Introduceți-o din nou." + +msgid "Old password" +msgstr "Parolă veche" + +msgid "Password (again)" +msgstr "Parolă (din nou)" + +msgid "algorithm" +msgstr "algoritm" + +msgid "iterations" +msgstr "iterații" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "varietate" + +msgid "version" +msgstr "versiune" + +msgid "memory cost" +msgstr "memorie necesară" + +msgid "time cost" +msgstr "timp necesar" + +msgid "parallelism" +msgstr "paralelism" + +msgid "work factor" +msgstr "factor de efort" + +msgid "checksum" +msgstr "sumă de control" + +msgid "name" +msgstr "nume" + +msgid "content type" +msgstr "tip de conținut" + +msgid "codename" +msgstr "nume de cod" + +msgid "permission" +msgstr "permisiune" + +msgid "permissions" +msgstr "permisiuni" + +msgid "group" +msgstr "grup" + +msgid "groups" +msgstr "grupuri" + +msgid "superuser status" +msgstr "stare superutilizator" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Marchează daca acest utilizator are toate permisiunile, fără a le mai " +"selecta explicit." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Grupurile din care face parte acest utilizator. Un utilizator va obține " +"drepturile de acces corespunzătoare grupurilor din care face parte." + +msgid "user permissions" +msgstr "permisiuni utilizator" + +msgid "Specific permissions for this user." +msgstr "Drepturile de access specifice acestui utilizator." + +msgid "username" +msgstr "nume utilizator" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Obligatoriu. 150 de caractere sau mai puține. Numai litere, cifre și @/./+/-/" +"_." + +msgid "A user with that username already exists." +msgstr "Un utilizator cu acest nume de utilizator există deja." + +msgid "first name" +msgstr "Prenume" + +msgid "last name" +msgstr "Nume" + +msgid "email address" +msgstr "adresă de email" + +msgid "staff status" +msgstr "stare autorizare" + +msgid "Designates whether the user can log into this admin site." +msgstr "" +"Marchează dacă utilizatorul se poate autentifica în acest site de " +"administrare." + +msgid "active" +msgstr "activ" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Desemnează dacă acest utilizator trebuie tratat ca activ. Deselectaţi " +"această opţiune în loc să ştergeţi conturi." + +msgid "date joined" +msgstr "data înscrierii" + +msgid "user" +msgstr "utilizator" + +msgid "users" +msgstr "utilizatori" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Parola este prea scurtă. Trebuie să conțină cel puțin %(min_length)d " +"caracter." +msgstr[1] "" +"Parola este prea scurtă. Trebuie să conțină cel puțin %(min_length)d " +"caractere." +msgstr[2] "" +"Parola este prea scurtă. Trebuie să conțină cel puțin %(min_length)d de " +"caractere." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Parola trebuie să conțină cel puțin %(min_length)d caracter." +msgstr[1] "Parola trebuie să conțină cel puțin %(min_length)d caractere." +msgstr[2] "Parola trebuie să conțină cel puțin %(min_length)d de caractere." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Parola este prea asemănătoare cu %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" +"Nu este recomandabil ca parola sa fie asemănătoare cu celelalte date " +"personale." + +msgid "This password is too common." +msgstr "Această parolă este prea răspândită." + +msgid "Your password can’t be a commonly used password." +msgstr "Parola nu poate fi atât de comună. " + +msgid "This password is entirely numeric." +msgstr "Acestă parolă este compusă exclusiv din elemente numerice." + +msgid "Your password can’t be entirely numeric." +msgstr "Parola nu poate fi doar cu numere." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Resetează parola pentru %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"Vă rugăm să folosiți un nume acceptat. Această valoare poate conține doar " +"litere, cifre și caracterele @/./+/-/_." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Vă rugăm să folosiți un nume acceptat. Această valoare poate conține doar " +"litere, cifre și caracterele @/./+/-/_" + +msgid "Logged out" +msgstr "Deautentificat" + +msgid "Password reset" +msgstr "Resetază parola" + +msgid "Password reset sent" +msgstr "Cerea de resetare a parolei trimisă cu succes" + +msgid "Enter new password" +msgstr "Introduceți noua parolă" + +msgid "Password reset unsuccessful" +msgstr "Resetarea parolei nu a avut succes." + +msgid "Password reset complete" +msgstr "Parola a fost resetată." + +msgid "Password change" +msgstr "Schimbare parolă" + +msgid "Password change successful" +msgstr "Schimbarea parolei a fost efectuată cu succes" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ru/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ru/LC_MESSAGES/django.mo new file mode 100644 index 0000000..447f166 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ru/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ru/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ru/LC_MESSAGES/django.po new file mode 100644 index 0000000..a7f209d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ru/LC_MESSAGES/django.po @@ -0,0 +1,324 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# crazyzubr , 2020 +# Ivan Khomutov , 2017 +# Jannis Leidel , 2011 +# Алексей Борискин , 2012-2015,2022-2023 +# Андрей Щуров , 2016 +# Влад Мещеряков , 2021 +# Bobsans , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-12-04 08:09+0000\n" +"Last-Translator: Алексей Борискин , 2012-2015,2022-2023\n" +"Language-Team: Russian (http://app.transifex.com/django/django/language/" +"ru/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ru\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || " +"(n%100>=11 && n%100<=14)? 2 : 3);\n" + +msgid "Personal info" +msgstr "Персональная информация" + +msgid "Permissions" +msgstr "Права доступа" + +msgid "Important dates" +msgstr "Важные даты" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(name)s с первичным ключом %(key)r не существует." + +msgid "Password changed successfully." +msgstr "Пароль успешно изменен." + +#, python-format +msgid "Change password: %s" +msgstr "Изменить пароль: %s" + +msgid "Authentication and Authorization" +msgstr "Пользователи и группы" + +msgid "password" +msgstr "пароль" + +msgid "last login" +msgstr "последний вход" + +msgid "No password set." +msgstr "Пароль не задан." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Неизвестный формат пароля или алгоритм хеширования." + +msgid "The two password fields didn’t match." +msgstr "Введенные пароли не совпадают." + +msgid "Password" +msgstr "Пароль" + +msgid "Password confirmation" +msgstr "Подтверждение пароля" + +msgid "Enter the same password as before, for verification." +msgstr "Для подтверждения введите, пожалуйста, пароль ещё раз." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Пароли хранятся в зашифрованном виде, поэтому нет возможности посмотреть " +"пароль этого пользователя, но вы можете изменить его используя эту форму." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Пожалуйста, введите правильные %(username)s и пароль. Оба поля могут быть " +"чувствительны к регистру." + +msgid "This account is inactive." +msgstr "Эта учетная запись отключена." + +msgid "Email" +msgstr "Адрес электронной почты" + +msgid "New password" +msgstr "Новый пароль" + +msgid "New password confirmation" +msgstr "Подтверждение нового пароля" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Ваш старый пароль введен неправильно. Пожалуйста, введите его снова." + +msgid "Old password" +msgstr "Старый пароль" + +msgid "Password (again)" +msgstr "Пароль (еще раз)" + +msgid "algorithm" +msgstr "алгоритм" + +msgid "iterations" +msgstr "итерации" + +msgid "salt" +msgstr "соль" + +msgid "hash" +msgstr "хэш" + +msgid "variety" +msgstr "множество" + +msgid "version" +msgstr "версия" + +msgid "memory cost" +msgstr "затраты памяти" + +msgid "time cost" +msgstr "затраты времени" + +msgid "parallelism" +msgstr "параллелизм" + +msgid "work factor" +msgstr "рабочий фактор" + +msgid "checksum" +msgstr "контрольная сумма" + +msgid "block size" +msgstr "размер блока" + +msgid "name" +msgstr "имя" + +msgid "content type" +msgstr "тип содержимого" + +msgid "codename" +msgstr "кодовое название" + +msgid "permission" +msgstr "право" + +msgid "permissions" +msgstr "права" + +msgid "group" +msgstr "группа" + +msgid "groups" +msgstr "группы" + +msgid "superuser status" +msgstr "статус суперпользователя" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "Указывает, что пользователь имеет все права без явного их назначения." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Группы, к которым принадлежит данный пользователь. Пользователь получит все " +"права, указанные в каждой из его/её групп." + +msgid "user permissions" +msgstr "права пользователя" + +msgid "Specific permissions for this user." +msgstr "Индивидуальные права данного пользователя." + +msgid "username" +msgstr "имя пользователя" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Обязательное поле. Не более 150 символов. Только буквы, цифры и символы @/./" +"+/-/_." + +msgid "A user with that username already exists." +msgstr "Пользователь с таким именем уже существует." + +msgid "first name" +msgstr "имя" + +msgid "last name" +msgstr "фамилия" + +msgid "email address" +msgstr "адрес электронной почты" + +msgid "staff status" +msgstr "статус персонала" + +msgid "Designates whether the user can log into this admin site." +msgstr "" +"Отметьте, если пользователь может входить в административную часть сайта." + +msgid "active" +msgstr "активный" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Отметьте, если пользователь должен считаться активным. Уберите эту отметку " +"вместо удаления учётной записи." + +msgid "date joined" +msgstr "дата регистрации" + +msgid "user" +msgstr "пользователь" + +msgid "users" +msgstr "пользователи" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Введённый пароль слишком короткий. Он должен содержать как минимум " +"%(min_length)d символ." +msgstr[1] "" +"Введённый пароль слишком короткий. Он должен содержать как минимум " +"%(min_length)d символа." +msgstr[2] "" +"Введённый пароль слишком короткий. Он должен содержать как минимум " +"%(min_length)d символов." +msgstr[3] "" +"Введённый пароль слишком короткий. Он должен содержать как минимум " +"%(min_length)d символов." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Ваш пароль должен содержать как минимум %(min_length)d символ." +msgstr[1] "Ваш пароль должен содержать как минимум %(min_length)d символа." +msgstr[2] "Ваш пароль должен содержать как минимум %(min_length)d символов." +msgstr[3] "Ваш пароль должен содержать как минимум %(min_length)d символов." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Введённый пароль слишком похож на %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Пароль не должен быть слишком похож на другую вашу личную информацию." + +msgid "This password is too common." +msgstr "Введённый пароль слишком широко распространён." + +msgid "Your password can’t be a commonly used password." +msgstr "Пароль не должен быть слишком простым и распространенным." + +msgid "This password is entirely numeric." +msgstr "Введённый пароль состоит только из цифр." + +msgid "Your password can’t be entirely numeric." +msgstr "Пароль не может состоять только из цифр." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Сброс пароля на %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Введите правильное имя пользователя. Это значение может содержать только " +"строчные буквы латиницы a-z без умляутов, прописные буквы A-Z, цифры и " +"символы @/./+/-/_." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Введите правильное имя пользователя. Оно может содержать только буквы, цифры " +"и знаки @/./+/-/_." + +msgid "Logged out" +msgstr "Не авторизован" + +msgid "Password reset" +msgstr "Восстановление пароля" + +msgid "Password reset sent" +msgstr "Письмо с инструкциями по восстановлению пароля отправлено" + +msgid "Enter new password" +msgstr "Введите новый пароль" + +msgid "Password reset unsuccessful" +msgstr "Ошибка восстановления пароля" + +msgid "Password reset complete" +msgstr "Восстановление пароля завершено" + +msgid "Password change" +msgstr "Изменение пароля" + +msgid "Password change successful" +msgstr "Пароль успешно изменен" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..fa6e2e0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sk/LC_MESSAGES/django.po new file mode 100644 index 0000000..63483a7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sk/LC_MESSAGES/django.po @@ -0,0 +1,315 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Adam Zahradník, 2023 +# Jannis Leidel , 2011 +# 18f25ad6fa9930fc67cb11aca9d16a27, 2012-2014 +# Marian Andre , 2015,2017 +# Martin Tóth , 2017-2018,2023 +# Peter Kuma, 2021 +# Richard von Kellner, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-12-04 08:09+0000\n" +"Last-Translator: Martin Tóth , 2017-2018,2023\n" +"Language-Team: Slovak (http://app.transifex.com/django/django/language/sk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n " +">= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);\n" + +msgid "Personal info" +msgstr "Osobné údaje" + +msgid "Permissions" +msgstr "Práva" + +msgid "Important dates" +msgstr "Dôležité dátumy" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "Objekt %(name)s s primárnym kľúčom %(key)r neexistuje." + +msgid "Password changed successfully." +msgstr "Heslo úspešne zmenené." + +#, python-format +msgid "Change password: %s" +msgstr "Zmeniť heslo: %s" + +msgid "Authentication and Authorization" +msgstr "Autentifikácia a autorizácia" + +msgid "password" +msgstr "heslo" + +msgid "last login" +msgstr "naposledy prihlásený" + +msgid "No password set." +msgstr "Žiadne heslo." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Neplatný formát hesla alebo neznámy hašovací algoritmus." + +msgid "The two password fields didn’t match." +msgstr "Heslo a jeho potvrdenie sa nezhodujú." + +msgid "Password" +msgstr "Heslo" + +msgid "Password confirmation" +msgstr "Potvrdenie hesla" + +msgid "Enter the same password as before, for verification." +msgstr "Kvôli overeniu, znovu zadajte rovnaké heslo." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Heslá v pôvodnom tvare nie sú ukladané, takže neexistuje spôsob zobraziť " +"heslo užívateľa. Môžete ho však zmeniť pomocou tohoto " +"formulára." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Zadajte prosím správne %(username)s a heslo. Všimnite si, že obe polia môžu " +"obsahovať veľké a malé písmená." + +msgid "This account is inactive." +msgstr "Tento účet je neaktívny." + +msgid "Email" +msgstr "E-mail" + +msgid "New password" +msgstr "Nové heslo" + +msgid "New password confirmation" +msgstr "Potvrdenie nového hesla" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Nezadali ste správne svoje staré heslo. Napíšte ho znovu, prosím." + +msgid "Old password" +msgstr "Staré heslo" + +msgid "Password (again)" +msgstr "Heslo (znova)" + +msgid "algorithm" +msgstr "algoritmus" + +msgid "iterations" +msgstr "iterácie" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "druh" + +msgid "version" +msgstr "verzia" + +msgid "memory cost" +msgstr "pamäťová náročnosť" + +msgid "time cost" +msgstr "časová náročnosť" + +msgid "parallelism" +msgstr "paralelizmus" + +msgid "work factor" +msgstr "faktor práce" + +msgid "checksum" +msgstr "kontrolný súčet" + +msgid "block size" +msgstr "veľkosť bloku" + +msgid "name" +msgstr "meno" + +msgid "content type" +msgstr "typ obsahu" + +msgid "codename" +msgstr "kódové meno" + +msgid "permission" +msgstr "oprávnenie" + +msgid "permissions" +msgstr "oprávnenia" + +msgid "group" +msgstr "skupina" + +msgid "groups" +msgstr "skupiny" + +msgid "superuser status" +msgstr "status superpoužívateľa" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Určuje, či používateľ získava automaticky všetky práva aj bez priameho " +"priradenia." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Skupiny do ktorých používateľ patrí. Používateľ dostane všetky oprávnenia z " +"každej z jeho skupín." + +msgid "user permissions" +msgstr "používateľské oprávnenia" + +msgid "Specific permissions for this user." +msgstr "Konkrétne oprávnenia pre tohto používateľa." + +msgid "username" +msgstr "používateľské meno" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "Povinné. 150 znakov alebo menej. Iba písmená, číslice a @/./+/-/_." + +msgid "A user with that username already exists." +msgstr "Používateľ s takým používateľským menom už existuje." + +msgid "first name" +msgstr "krstné meno" + +msgid "last name" +msgstr "priezvisko" + +msgid "email address" +msgstr "e-mailová adresa" + +msgid "staff status" +msgstr "správcovský prístup" + +msgid "Designates whether the user can log into this admin site." +msgstr "Určuje, či sa používateľ môže prihlásiť do správy stránok." + +msgid "active" +msgstr "aktívny" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Určuje, či je účet aktívny. Odškrtnite, ak chcete vypnúť používateľský účet." + +msgid "date joined" +msgstr "dátum registrácie" + +msgid "user" +msgstr "používateľ" + +msgid "users" +msgstr "používatelia" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Toto heslo je príliš krátke. Musí obsahovať aspoň %(min_length)d znak." +msgstr[1] "" +"Toto heslo je príliš krátke. Musí obsahovať aspoň %(min_length)d znaky." +msgstr[2] "" +"Toto heslo je príliš krátke. Musí obsahovať aspoň %(min_length)d znakov." +msgstr[3] "" +"Toto heslo je príliš krátke. Musí obsahovať aspoň %(min_length)d znakov." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Vaše heslo musí obsahovať aspoň %(min_length)d znak." +msgstr[1] "Vaše heslo musí obsahovať aspoň %(min_length)d znaky." +msgstr[2] "Vaše heslo musí obsahovať aspoň %(min_length)d znakov." +msgstr[3] "Vaše heslo musí obsahovať aspoň %(min_length)d znakov." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Heslo sa príliš podobá na %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Vaše heslo sa nesmie príliš podobať na ostatné osobné informácie." + +msgid "This password is too common." +msgstr "Toto heslo je používané príliš často." + +msgid "Your password can’t be a commonly used password." +msgstr "Vaše heslo nemôže byť jedno z často používaných hesiel." + +msgid "This password is entirely numeric." +msgstr "Toto heslo pozostáva iba z číslic." + +msgid "Your password can’t be entirely numeric." +msgstr "Vaše heslo nemôže pozostávať iba z číslic." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Obnovenie hesla pre %(site_name)s " + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Zadajte platné používateľské meno. Môže obsahovať len písmená bez " +"diakritiky, číslice a znaky @/./+/-/_." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Zadajte platné používateľské meno. Táto hodnota môže obsahovať len písmená, " +"číslice a znaky @/./+/-/_." + +msgid "Logged out" +msgstr "Odhlásený" + +msgid "Password reset" +msgstr "Obnovenie hesla" + +msgid "Password reset sent" +msgstr "Obnovenie hesla odoslané" + +msgid "Enter new password" +msgstr "Zadajte nové heslo" + +msgid "Password reset unsuccessful" +msgstr "Obnovenie hesla sa nepodarilo" + +msgid "Password reset complete" +msgstr "Obnovenie hesla ukončené" + +msgid "Password change" +msgstr "Zmena hesla" + +msgid "Password change successful" +msgstr "Zmena hesla úspešná" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9337ec7 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sl/LC_MESSAGES/django.po new file mode 100644 index 0000000..5f9fd7a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sl/LC_MESSAGES/django.po @@ -0,0 +1,312 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Andrej Marsetič, 2022-2023 +# Jannis Leidel , 2011 +# Jure Cuhalev , 2012 +# Primoz Verdnik , 2017 +# zejn , 2013,2016-2017 +# zejn , 2011-2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-12-04 08:09+0000\n" +"Last-Translator: Andrej Marsetič, 2022-2023\n" +"Language-Team: Slovenian (http://app.transifex.com/django/django/language/" +"sl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sl\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || " +"n%100==4 ? 2 : 3);\n" + +msgid "Personal info" +msgstr "Osebni podatki" + +msgid "Permissions" +msgstr "Dovoljenja" + +msgid "Important dates" +msgstr "Pomembni datumi" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "Objekt %(name)s z glavnim ključem %(key)r ne obstaja." + +msgid "Password changed successfully." +msgstr "Geslo je uspešno spremenjeno." + +#, python-format +msgid "Change password: %s" +msgstr "Spremeni geslo: %s" + +msgid "Authentication and Authorization" +msgstr "Avtentikacija in avtorizacija" + +msgid "password" +msgstr "geslo" + +msgid "last login" +msgstr "zadnja prijava" + +msgid "No password set." +msgstr "Geslo ni nastavljeno." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Neveljavna oblika gesla ali neznan algoritem razpršila." + +msgid "The two password fields didn’t match." +msgstr "Polji za geslo se nista ujemali." + +msgid "Password" +msgstr "Geslo" + +msgid "Password confirmation" +msgstr "Potrditev gesla" + +msgid "Enter the same password as before, for verification." +msgstr "Vnesite isto geslo kot prej, za preverjanje." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Neobdelana gesla niso shranjena, zato gesla tega uporabnika ni mogoče " +"videti, vendar lahko geslo spremenite z uporabotega obrazca." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Vnesite veljavno %(username)s in geslo. Opomba: obe polji upoštevata " +"velikost črk." + +msgid "This account is inactive." +msgstr "Ta uporabniški račun ni dejaven." + +msgid "Email" +msgstr "Elektronski naslov" + +msgid "New password" +msgstr "Novo geslo" + +msgid "New password confirmation" +msgstr "Potrditev novega gesla" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Vaše staro geslo ni vneseno pravilno. Poskusite znova." + +msgid "Old password" +msgstr "Staro geslo" + +msgid "Password (again)" +msgstr "Geslo (znova)" + +msgid "algorithm" +msgstr "algoritem" + +msgid "iterations" +msgstr "ponovitev" + +msgid "salt" +msgstr "naključna vrednost" + +msgid "hash" +msgstr "razpršilo" + +msgid "variety" +msgstr "pestrost" + +msgid "version" +msgstr "različica" + +msgid "memory cost" +msgstr "pomnilniška zahtevnost" + +msgid "time cost" +msgstr "časovna zahtevnost" + +msgid "parallelism" +msgstr "paralelnost" + +msgid "work factor" +msgstr "faktor obremenitve" + +msgid "checksum" +msgstr "nadzorna vsota" + +msgid "block size" +msgstr "velikost bloka" + +msgid "name" +msgstr "ime" + +msgid "content type" +msgstr "vrsta vsebine" + +msgid "codename" +msgstr "kodno ime" + +msgid "permission" +msgstr "dovoljenje" + +msgid "permissions" +msgstr "dovoljenja" + +msgid "group" +msgstr "skupina" + +msgid "groups" +msgstr "skupine" + +msgid "superuser status" +msgstr "stanje skrbnika" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Določi, da bo uporabnik imel vsa dovoljenja, ne da bi mu jih posebej " +"dodelili." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Skupine, katerih član je ta uporabnik. Uporabnik pridobi vsa dovoljenja, " +"povezana z vsako izmed skupin." + +msgid "user permissions" +msgstr "uporabniška dovoljenja" + +msgid "Specific permissions for this user." +msgstr "Dovoljenja specifična za tega uporabnika." + +msgid "username" +msgstr "uporabniško ime" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "Zahtevano. 150 znakov ali manj. Le črke, števke in znaki @/./+/-/_." + +msgid "A user with that username already exists." +msgstr "Uporabnik s tem uporabniškim imenom že obstaja." + +msgid "first name" +msgstr "ime" + +msgid "last name" +msgstr "priimek" + +msgid "email address" +msgstr "elektronski naslov" + +msgid "staff status" +msgstr "stanje osebja" + +msgid "Designates whether the user can log into this admin site." +msgstr "Določi, ali se sme uporabnik prijaviti kot skrbnik." + +msgid "active" +msgstr "dejaven" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Določi, ali je uporabnik dejaven. Možnost je priročna in preprečuje brisanje " +"računov." + +msgid "date joined" +msgstr "vpisan od" + +msgid "user" +msgstr "uporabnik" + +msgid "users" +msgstr "uporabniki" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "To geslo je prekratko. Imeti mora vsaj %(min_length)d znak." +msgstr[1] "To geslo je prekratko. Imeti mora vsaj %(min_length)d znaka." +msgstr[2] "To geslo je prekratko. Imeti mora vsaj %(min_length)d znake." +msgstr[3] "To geslo je prekratko. Imeti mora vsaj %(min_length)d znakov." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Vaše geslo mora imeti vsaj %(min_length)d znak." +msgstr[1] "Vaše geslo mora imeti vsaj %(min_length)d znaka." +msgstr[2] "Vaše geslo mora imeti vsaj %(min_length)d znake." +msgstr[3] "Vaše geslo mora imeti vsaj %(min_length)d znakov." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Geslo je preveč podobno %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Vaše geslo ne sme biti preveč podobno vašim drugim osebnim podatkom." + +msgid "This password is too common." +msgstr "Geslo je eno izmed preveč pogosto uporabljanih." + +msgid "Your password can’t be a commonly used password." +msgstr "Vaše geslo ne sme biti pogosto uporabljeno geslo." + +msgid "This password is entirely numeric." +msgstr "Vaše geslo je sestavljeno samo iz števk." + +msgid "Your password can’t be entirely numeric." +msgstr "Vaše geslo ne sme biti v celoti sestavljeno iz številk." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Geslo na %(site_name)s je ponastavljeno." + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Vnesite veljavno uporabniško ime. Ta vrednost lahko vsebuje samo nenaglašene " +"male črke a–z in velike črke A–Z, številke in znake @/./+/-/_." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Vnesite veljavno uporabniško ime. Ta vrednost sme vsebovati le črke, števke " +"in znake @/./+/-/_." + +msgid "Logged out" +msgstr "Odjavljen" + +msgid "Password reset" +msgstr "Ponastavi geslo" + +msgid "Password reset sent" +msgstr "Navodila za ponastavitev gesla so bila poslana" + +msgid "Enter new password" +msgstr "Vnesite novo geslo" + +msgid "Password reset unsuccessful" +msgstr "Ponastavitev gesla ni uspela" + +msgid "Password reset complete" +msgstr "Ponastavitev gesla zaključena" + +msgid "Password change" +msgstr "Sprememba gesla" + +msgid "Password change successful" +msgstr "Sprememba gesla je uspela" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sq/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sq/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8f64e2e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sq/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sq/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sq/LC_MESSAGES/django.po new file mode 100644 index 0000000..fa5eb0f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sq/LC_MESSAGES/django.po @@ -0,0 +1,313 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Besnik Bleta , 2011,2015 +# Besnik Bleta , 2023 +# Besnik Bleta , 2015,2017,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-12-04 08:09+0000\n" +"Last-Translator: Besnik Bleta , 2023\n" +"Language-Team: Albanian (http://app.transifex.com/django/django/language/" +"sq/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sq\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Të dhëna personale" + +msgid "Permissions" +msgstr "Leje" + +msgid "Important dates" +msgstr "Të dhëna të rëndësishme" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "S’ekziston objekt %(name)s me kyç parësor %(key)r." + +msgid "Password changed successfully." +msgstr "Fjalëkalimi u ndryshua me sukses." + +#, python-format +msgid "Change password: %s" +msgstr "Ndryshoni fjalëkalimin: %s" + +msgid "Authentication and Authorization" +msgstr "Mirëfilltësim dhe Autorizim" + +msgid "password" +msgstr "fjalëkalim" + +msgid "last login" +msgstr "hyrja e fundit" + +msgid "No password set." +msgstr "S’ka fjalëkalim të caktuar." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Format i pavlefshëm fjalëkalimi ose algoritëm i panjohur hashi." + +msgid "The two password fields didn’t match." +msgstr "Dy fushat për fjalëkalim s’u përputhën." + +msgid "Password" +msgstr "Fjalëkalim" + +msgid "Password confirmation" +msgstr "Ripohim fjalëkalimi" + +msgid "Enter the same password as before, for verification." +msgstr "Jepni, për verifikim, të njëjtin fjalëkalim si më parë." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Nuk depozitohen fjalëkalime të papërpunuar, ndaj s’ka ndonjë mënyrë për të " +"parë fjalëkalimin e këtij përdoruesi, por mund ta ndryshoni fjalëkalimin " +"duke përdorur këtë formular." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Ju lutemi, jepni një %(username)s dhe një fjalëkalim të saktë. Kini parasysh " +"se që të dyja fushat mund të jenë të ndjeshme ndaj shkrimit me shkronja të " +"mëdha ose të vogla." + +msgid "This account is inactive." +msgstr "Kjo llogari s’është aktive." + +msgid "Email" +msgstr "Email" + +msgid "New password" +msgstr "Fjalëkalim i ri" + +msgid "New password confirmation" +msgstr "Ripohim fjalëkalimi të ri" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" +"Fjalëkalimi juaj i vjetër u dha pasaktësisht. Ju lutemi, jepeni sërish." + +msgid "Old password" +msgstr "Fjalëkalim i vjetër" + +msgid "Password (again)" +msgstr "Fjalëkalim (sërish)" + +msgid "algorithm" +msgstr "algoritëm" + +msgid "iterations" +msgstr "përsëritje" + +msgid "salt" +msgstr "kripë" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "larmi" + +msgid "version" +msgstr "version" + +msgid "memory cost" +msgstr "kosto kujtese" + +msgid "time cost" +msgstr "kosto në kohë" + +msgid "parallelism" +msgstr "paralelizëm" + +msgid "work factor" +msgstr "" + +msgid "checksum" +msgstr "checksum" + +msgid "block size" +msgstr "madhësi blloku" + +msgid "name" +msgstr "emër" + +msgid "content type" +msgstr "lloj lënde" + +msgid "codename" +msgstr "emër i koduar" + +msgid "permission" +msgstr "leje" + +msgid "permissions" +msgstr "leje" + +msgid "group" +msgstr "grup" + +msgid "groups" +msgstr "grupe" + +msgid "superuser status" +msgstr "gjendje superpërdoruesi" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Përcakton që ky përdorues ka krejt lejet, pa ia akorduar ato shprehimisht." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Grupet te të cilët bën pjesë ky përdorues. Një përdorues do të gëzojë krejt " +"lejet e akorduara secilit te këto grupe." + +msgid "user permissions" +msgstr "leje përdoruesi" + +msgid "Specific permissions for this user." +msgstr "Leje specifike për këtë përdorues." + +msgid "username" +msgstr "emër përdoruesi" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"E domosdoshme. 150 ose më pak shenja. Vetëm shkronja, shifra, dhe @/./+/-/_ ." + +msgid "A user with that username already exists." +msgstr "Ka tashmë një emër të tillë përdoruesi." + +msgid "first name" +msgstr "emër" + +msgid "last name" +msgstr "mbiemër" + +msgid "email address" +msgstr "adresë email" + +msgid "staff status" +msgstr "vend në ekip" + +msgid "Designates whether the user can log into this admin site." +msgstr "Përcakton nëse mund të hyjë ose jo përdoruesi te ky sajt administrimi." + +msgid "active" +msgstr "veprues" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Përcakton nëse ky përdorues do të duhej trajtuar si aktiv. Shpërzgjidheni " +"këtë, në vend se të fshihni llogari." + +msgid "date joined" +msgstr "datë anëtarësimi" + +msgid "user" +msgstr "përdorues" + +msgid "users" +msgstr "përdorues" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Ky fjalëkalim është shumë i shkurtër. Duhet të përmbajë të paktën " +"%(min_length)d shenjë." +msgstr[1] "" +"Ky fjalëkalim është shumë i shkurtër. Duhet të përmbajë të paktën " +"%(min_length)d shenja." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Fjalëkalimi juaj duhet të përmbajë të paktën %(min_length)d shenjë." +msgstr[1] "Fjalëkalimi juaj duhet të përmbajë të paktën %(min_length)d shenja." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Fjalëkalimi është shumë i ngjashëm me %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" +"Fjalëkalimi juaj s’mund të jetë shumë i ngjashëm me të dhëna të tjera tuajat " +"personale." + +msgid "This password is too common." +msgstr "Ky fjalëkalim është shumë i rëndomtë." + +msgid "Your password can’t be a commonly used password." +msgstr "Fjalëkalimi juaj s’mund të jetë një fjalëkalim i përdorur rëndom." + +msgid "This password is entirely numeric." +msgstr "Ky fjalëkalim është tërësisht numerik." + +msgid "Your password can’t be entirely numeric." +msgstr "Fjalëkalimi juaj s’mund të jetë tërësisht numerik." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Ricaktim fjalëkalimi për te %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Jepni një emër përdoruesi të vlefshëm. Kjo vlerë mund të përmbajë vetëm " +"shkronja pa theks, me të vogla, a-z dhe të mëdha, A-Z, numra dhe shenjat @/./" +"+/-/_ ." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Jepni një emër përdoruesi të vlefshëm. Kjo vlerë mund të përmbajë vetëm " +"shkronja, numra dhe shenjat @/./+/-/_ ." + +msgid "Logged out" +msgstr "I dalë" + +msgid "Password reset" +msgstr "Ricaktim fjalëkalimi" + +msgid "Password reset sent" +msgstr "U dërgua ricaktim fjalëkalimi" + +msgid "Enter new password" +msgstr "Jepni fjalëkalimin e ri" + +msgid "Password reset unsuccessful" +msgstr "Ricaktimi i fjalëkalimit nuk pati sukses" + +msgid "Password reset complete" +msgstr "Ricaktimi i fjalëkalimit u plotësua" + +msgid "Password change" +msgstr "Ndryshim fjalëkalimi" + +msgid "Password change successful" +msgstr "Ndryshim i suksesshëm fjalëkalimi" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..106347a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sr/LC_MESSAGES/django.po new file mode 100644 index 0000000..9a770c5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sr/LC_MESSAGES/django.po @@ -0,0 +1,313 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Igor Jerosimić, 2020-2021,2023 +# Jannis Leidel , 2011 +# Janos Guljas , 2011-2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-12-04 08:09+0000\n" +"Last-Translator: Igor Jerosimić, 2020-2021,2023\n" +"Language-Team: Serbian (http://app.transifex.com/django/django/language/" +"sr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Personal info" +msgstr "Лични подаци" + +msgid "Permissions" +msgstr "Дозволе" + +msgid "Important dates" +msgstr "Важни датуми" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(name)s објекат са примарним кључем %(key)r не постоји." + +msgid "Password changed successfully." +msgstr "Лозинка успешно измењена." + +#, python-format +msgid "Change password: %s" +msgstr "Измени лозинку: %s" + +msgid "Authentication and Authorization" +msgstr "Аутентикација и Ауторизација" + +msgid "password" +msgstr "лозинка" + +msgid "last login" +msgstr "последња пријава" + +msgid "No password set." +msgstr "Лозинка није унета." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Инвалидан формат лозинке или непознат hashing алгоритам." + +msgid "The two password fields didn’t match." +msgstr "Два поља за лозинке се не поклапају." + +msgid "Password" +msgstr "Лозинка" + +msgid "Password confirmation" +msgstr "Потврда лозинке" + +msgid "Enter the same password as before, for verification." +msgstr "Унесите исту лозинку као малопре ради верификације." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Лозинке се не чувају у изворном облику па не постоји могућност приказа " +"лозинке овог корисника, али можете променити лозинку коришћењем ове форме." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Молим вас унесите исправно %(username)s и лозинку. Обратите пажњу да мала и " +"велика слова представљају различите карактере." + +msgid "This account is inactive." +msgstr "Овај налог је неактиван." + +msgid "Email" +msgstr "И-мејл" + +msgid "New password" +msgstr "Нова лозинка" + +msgid "New password confirmation" +msgstr "Потврда нове лозинке" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Ваша стара лознка није правилно унесена. Унесите је поново." + +msgid "Old password" +msgstr "Стара лозинка" + +msgid "Password (again)" +msgstr "Лозинка (поновите)" + +msgid "algorithm" +msgstr "алгоритам" + +msgid "iterations" +msgstr "итерације" + +msgid "salt" +msgstr "зачин" + +msgid "hash" +msgstr "хеш" + +msgid "variety" +msgstr "варијанта" + +msgid "version" +msgstr "верзија" + +msgid "memory cost" +msgstr "меморијска захтевност" + +msgid "time cost" +msgstr "временска захтевност" + +msgid "parallelism" +msgstr "паралелизам" + +msgid "work factor" +msgstr "фактор сложености" + +msgid "checksum" +msgstr "сума за проверу" + +msgid "block size" +msgstr "величина блока" + +msgid "name" +msgstr "име" + +msgid "content type" +msgstr "тип садржаја" + +msgid "codename" +msgstr "шифра дозволе" + +msgid "permission" +msgstr "дозвола" + +msgid "permissions" +msgstr "дозволе" + +msgid "group" +msgstr "група" + +msgid "groups" +msgstr "групе" + +msgid "superuser status" +msgstr "статус администратора" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Указује да корисник има све дозволе без додељивања појединачних дозвола." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Групе којима припада овај корисник. Корисник ће добити све дозволе које су " +"дате групама којима припада." + +msgid "user permissions" +msgstr "корисникове дозволе" + +msgid "Specific permissions for this user." +msgstr "Дозволе које се односе на овог корисника." + +msgid "username" +msgstr "корисничко име" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Обавезан податак. 150 карактера или мање. Дозвољена су само слова, цифре и " +"карактери @/./+/-/_ ." + +msgid "A user with that username already exists." +msgstr "Корисник са тим корисничким именом већ постоји." + +msgid "first name" +msgstr "име" + +msgid "last name" +msgstr "презиме" + +msgid "email address" +msgstr "и-мејл адреса" + +msgid "staff status" +msgstr "статус члана посаде" + +msgid "Designates whether the user can log into this admin site." +msgstr "Указује да корисник може да се пријави на овај сајт за администрацију." + +msgid "active" +msgstr "активан" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Означава да ли се корисник сматра активним. Деселектујте ово уместо да " +"бришете налог." + +msgid "date joined" +msgstr "датум регистрације" + +msgid "user" +msgstr "корисник" + +msgid "users" +msgstr "корисници" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Ова лозинка је превише кратка, мора садржати најмање %(min_length)d карактер." +msgstr[1] "" +"Ова лозинка је превише кратка, мора садржати најмање %(min_length)d " +"карактера." +msgstr[2] "" +"Ова лозинка је превише кратка, мора садржати најмање %(min_length)d " +"карактера." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Ваша лозинка мора садржати најмање %(min_length)d карактер." +msgstr[1] "Ваша лозинка мора садржати најмање %(min_length)d карактера." +msgstr[2] "Ваша лозинка мора садржати најмање %(min_length)d карактера." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Лозинка је превише слична пољу '%(verbose_name)s'." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Ваша лозинка не може бити слична вашим личним подацима." + +msgid "This password is too common." +msgstr "Ова лозинка је међу најчешће коришћеним лозинкама." + +msgid "Your password can’t be a commonly used password." +msgstr "Ваша лозинка не може бити међу најчешће коришћеним лозинкама." + +msgid "This password is entirely numeric." +msgstr "Ова лозинка садржи само цифре." + +msgid "Your password can’t be entirely numeric." +msgstr "Ваша лозинка не може садржати само цифре." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Ресетовање лозинке на сајту %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Унесите исправно корисничко име. Оно може садржати само неакцентована мала " +"слова a-z и велика слова A-Z, цифре и карактере @/./+/-/_ ." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Унесите исправно корисничко име. Оно може садржати само слова, цифре и " +"карактере @/./+/-/_ ." + +msgid "Logged out" +msgstr "Одјављен" + +msgid "Password reset" +msgstr "Ресет лозинке" + +msgid "Password reset sent" +msgstr "Захтев за ресет лозинке је послат" + +msgid "Enter new password" +msgstr "Унесите нову лозинку" + +msgid "Password reset unsuccessful" +msgstr "Неуспешан ресет лозинке" + +msgid "Password reset complete" +msgstr "Ресет лозинке је завршен" + +msgid "Password change" +msgstr "Промена лозинке" + +msgid "Password change successful" +msgstr "Лозинка је успешно промењена" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sr_Latn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sr_Latn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f335b55 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sr_Latn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sr_Latn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sr_Latn/LC_MESSAGES/django.po new file mode 100644 index 0000000..fdfda7d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sr_Latn/LC_MESSAGES/django.po @@ -0,0 +1,299 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Igor Jerosimić, 2021,2023 +# Jannis Leidel , 2011 +# Janos Guljas , 2011-2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-12-04 08:09+0000\n" +"Last-Translator: Igor Jerosimić, 2021,2023\n" +"Language-Team: Serbian (Latin) (http://app.transifex.com/django/django/" +"language/sr@latin/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr@latin\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Personal info" +msgstr "Lični podaci" + +msgid "Permissions" +msgstr "Dozvole" + +msgid "Important dates" +msgstr "Važni datumi" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "Lozinka uspešno izmenjena." + +#, python-format +msgid "Change password: %s" +msgstr "Izmeni lozinku: %s" + +msgid "Authentication and Authorization" +msgstr "Autentikacija i Autorizacija" + +msgid "password" +msgstr "lozinka" + +msgid "last login" +msgstr "poslednja prijava" + +msgid "No password set." +msgstr "Lozinka nije uneta." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Neispravan format lozinke ili nepoznat heš algoritam." + +msgid "The two password fields didn’t match." +msgstr "Dva polja za lozinke se ne poklapaju." + +msgid "Password" +msgstr "Lozinka" + +msgid "Password confirmation" +msgstr "Potvrda lozinke" + +msgid "Enter the same password as before, for verification." +msgstr "Unesite istu lozinku kao malopre radi verifikacije." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" + +msgid "This account is inactive." +msgstr "Ovaj nalog je neaktivan." + +msgid "Email" +msgstr "I-mejl" + +msgid "New password" +msgstr "Nova lozinka" + +msgid "New password confirmation" +msgstr "Potvrda nove lozinke" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Vaša stara loznka nije pravilno unesena. Unesite je ponovo." + +msgid "Old password" +msgstr "Stara lozinka" + +msgid "Password (again)" +msgstr "Lozinka (ponovite)" + +msgid "algorithm" +msgstr "algoritam" + +msgid "iterations" +msgstr "iteracije" + +msgid "salt" +msgstr "začin" + +msgid "hash" +msgstr "heš" + +msgid "variety" +msgstr "varijanta" + +msgid "version" +msgstr "verzija" + +msgid "memory cost" +msgstr "memorijska zahtevnost" + +msgid "time cost" +msgstr "vremenska zahtevnost" + +msgid "parallelism" +msgstr "paralelizam" + +msgid "work factor" +msgstr "faktor rada" + +msgid "checksum" +msgstr "suma za proveru" + +msgid "block size" +msgstr "veličina bloka" + +msgid "name" +msgstr "ime" + +msgid "content type" +msgstr "tip sadržaja" + +msgid "codename" +msgstr "šifra dozvole" + +msgid "permission" +msgstr "dozvola" + +msgid "permissions" +msgstr "dozvole" + +msgid "group" +msgstr "grupa" + +msgid "groups" +msgstr "grupe" + +msgid "superuser status" +msgstr "status administratora" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Označava da li korisnik ima sve dozvole bez dodeljivanja pojedinačnih " +"dozvola." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Grupe kojima pripada ovaj korisnik. Korisnik će dobiti sve dozvole koje su " +"date grupama kojima pripada." + +msgid "user permissions" +msgstr "korisničke dozvole" + +msgid "Specific permissions for this user." +msgstr "Dozvole koje se odnose na ovog korisnika." + +msgid "username" +msgstr "korisničko ime" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "Korisnik sa tim korisničkim imenom već postoji." + +msgid "first name" +msgstr "ime" + +msgid "last name" +msgstr "prezime" + +msgid "email address" +msgstr "Adresa e-pošte:" + +msgid "staff status" +msgstr "status člana posade" + +msgid "Designates whether the user can log into this admin site." +msgstr "" +"Označava da li korisnik može da se prijavi na ovaj sajt za administraciju." + +msgid "active" +msgstr "aktivan" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Označava da li se korisnik smatra aktivnim. Deselektujte ovo umesto da " +"brišete nalog." + +msgid "date joined" +msgstr "datum registracije" + +msgid "user" +msgstr "korisnik" + +msgid "users" +msgstr "korisnici" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "" + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "" + +msgid "Your password can’t be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "" + +msgid "Your password can’t be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Resetovanje lozinke na sajtu %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "Odjavljen" + +msgid "Password reset" +msgstr "" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "" + +msgid "Password reset unsuccessful" +msgstr "" + +msgid "Password reset complete" +msgstr "" + +msgid "Password change" +msgstr "" + +msgid "Password change successful" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sv/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sv/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4461738 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sv/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sv/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sv/LC_MESSAGES/django.po new file mode 100644 index 0000000..8f2ed9d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sv/LC_MESSAGES/django.po @@ -0,0 +1,317 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Albin Larsson , 2022 +# Alex Nordlund , 2012 +# Cybjit , 2012 +# Jannis Leidel , 2011 +# Jonathan Lindén, 2015 +# Jonathan Lindén, 2014 +# Mattias Hansson , 2016 +# nip3o , 2014 +# Petter Strandmark , 2019 +# Samuel Linde , 2011 +# Thomas Lundqvist, 2013,2016 +# Tomas Lööw , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2022-07-25 08:09+0000\n" +"Last-Translator: Albin Larsson \n" +"Language-Team: Swedish (http://www.transifex.com/django/django/language/" +"sv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sv\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Personlig information" + +msgid "Permissions" +msgstr "Rättigheter" + +msgid "Important dates" +msgstr "Viktiga datum" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(name)s-objekt med primärnyckel %(key)r finns inte." + +msgid "Password changed successfully." +msgstr "Lösenordet ändrades framgångsrikt." + +#, python-format +msgid "Change password: %s" +msgstr "Ändra lösenord: %s" + +msgid "Authentication and Authorization" +msgstr "Autentisering och auktorisering" + +msgid "password" +msgstr "lösenord" + +msgid "last login" +msgstr "senaste inloggning" + +msgid "No password set." +msgstr "Inget lösenord angivet." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Ogiltigt lösenordsformat eller okänd hashalgoritm." + +msgid "The two password fields didn’t match." +msgstr "De två lösenordsfälten stämmer inte överens." + +msgid "Password" +msgstr "Lösenord" + +msgid "Password confirmation" +msgstr "Lösenordsbekräftelse" + +msgid "Enter the same password as before, for verification." +msgstr "Fyll i samma lösenord som tidigare för verifiering." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Lösenord lagras inte direkt, så det finns inget sätt att se denna användares " +"lösenord, men du kan ändra lösenorden med detta formulär." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Ange ett korrekt %(username)s och lösenord. Observera att båda fälten är " +"skiftlägeskänsliga." + +msgid "This account is inactive." +msgstr "Detta konto är inaktivt." + +msgid "Email" +msgstr "E-postadress" + +msgid "New password" +msgstr "Nytt lösenord" + +msgid "New password confirmation" +msgstr "Bekräfta nytt lösenord" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Ditt gamla lösenord var felaktigt ifyllt. Var vänlig fyll i det igen." + +msgid "Old password" +msgstr "Gammalt lösenord" + +msgid "Password (again)" +msgstr "Lösenord (igen)" + +msgid "algorithm" +msgstr "algoritm" + +msgid "iterations" +msgstr "iterationer" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "variation" + +msgid "version" +msgstr "version" + +msgid "memory cost" +msgstr "minneskostnad" + +msgid "time cost" +msgstr "tidskostnad" + +msgid "parallelism" +msgstr "parallellism" + +msgid "work factor" +msgstr "arbetsfaktor" + +msgid "checksum" +msgstr "kontrollsumma" + +msgid "block size" +msgstr "blockstorlek" + +msgid "name" +msgstr "namn" + +msgid "content type" +msgstr "innehållstyp" + +msgid "codename" +msgstr "kodnamn" + +msgid "permission" +msgstr "rättighet" + +msgid "permissions" +msgstr "rättigheter" + +msgid "group" +msgstr "grupp" + +msgid "groups" +msgstr "grupper" + +msgid "superuser status" +msgstr "superanvändare" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Anger att denna användare har alla rättigheter utan att uttryckligen " +"tilldela dem." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"De grupper som användaren är medlem i. Användare får tillgång till alla " +"rättigheter som deras grupper har." + +msgid "user permissions" +msgstr "användarättigheter" + +msgid "Specific permissions for this user." +msgstr "Specifika rättigheter för denna användare." + +msgid "username" +msgstr "användarnamn" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Obligatoriskt. 150 tecken eller färre. Endast bokstäver, siffror och @/./+/-/" +"_." + +msgid "A user with that username already exists." +msgstr "En användare med det användarnamnet finns redan." + +msgid "first name" +msgstr "förnamn" + +msgid "last name" +msgstr "efternamn" + +msgid "email address" +msgstr "e-postadress" + +msgid "staff status" +msgstr "personalstatus" + +msgid "Designates whether the user can log into this admin site." +msgstr "Avgör om användaren kan logga in på denna adminsida." + +msgid "active" +msgstr "aktiv" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Anger om användaren skall betraktas som aktiv. Avmarkera detta istället för " +"att ta bort konton." + +msgid "date joined" +msgstr "registreringsdatum" + +msgid "user" +msgstr "användare" + +msgid "users" +msgstr "användare" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Detta lösenord är för kort. Det måste innehålla minst %(min_length)d tecken." +msgstr[1] "" +"Detta lösenord är för kort. Det måste innehålla minst %(min_length)d tecken." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Ditt lösenord måste innehålla minst %(min_length)d tecken." +msgstr[1] "Ditt lösenord måste innehålla minst %(min_length)d tecken." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Ditt lösenord är alltför likt %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" +"Ditt lösenord kan inte vara alltför likt din övriga personliga information." + +msgid "This password is too common." +msgstr "Detta lösenord är alldeles för vanligt." + +msgid "Your password can’t be a commonly used password." +msgstr "Ditt lösenord kan inte vara ett allmänt använt lösenord." + +msgid "This password is entirely numeric." +msgstr "Detta lösenord är enbart numeriskt." + +msgid "Your password can’t be entirely numeric." +msgstr "Ditt lösenord kan inte bara vara numeriskt." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Lösenord nollställt på %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"Fyll i ett giltigt användarnamn. Detta värde får endast innehålla bokstäver " +"a-z, siffror och @/./+/-/_." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Fyll i ett giltigt användarnamn. Detta värde får endast innehålla bokstäver, " +"siffror och @/./+/-/_." + +msgid "Logged out" +msgstr "Utloggad" + +msgid "Password reset" +msgstr "Nollställ lösenord" + +msgid "Password reset sent" +msgstr "Lösenordsnollställning skickad" + +msgid "Enter new password" +msgstr "Nytt lösenord" + +msgid "Password reset unsuccessful" +msgstr "Lösenordsnollställning misslyckad" + +msgid "Password reset complete" +msgstr "Nollställning av lösenord klar" + +msgid "Password change" +msgstr "Ändra lösenord" + +msgid "Password change successful" +msgstr "Lösenordet ändrades" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sw/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sw/LC_MESSAGES/django.mo new file mode 100644 index 0000000..712fea0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sw/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sw/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sw/LC_MESSAGES/django.po new file mode 100644 index 0000000..20e517d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/sw/LC_MESSAGES/django.po @@ -0,0 +1,287 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Machaku , 2012-2014 +# Machaku , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-09-24 14:24+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Swahili (http://www.transifex.com/django/django/language/" +"sw/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sw\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Taarifa binafsi" + +msgid "Permissions" +msgstr "Ruhusa" + +msgid "Important dates" +msgstr "Tarehe muhimu" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "Nenosiri limebadilishwa kwa mafanikio" + +#, python-format +msgid "Change password: %s" +msgstr "Badilisha nenosiri: %s" + +msgid "Authentication and Authorization" +msgstr "Utambulisho na Idhini" + +msgid "password" +msgstr "nenosiri" + +msgid "last login" +msgstr "kuingia kwa mara ya mwisho" + +msgid "No password set." +msgstr "Hakuna nenosiri lililowekwa." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Muundo batili wa nenosiri au algorithm ya ku-'hash' isiyotambulika" + +msgid "The two password fields didn't match." +msgstr "Sehemu mbili za nenosiri hazikufanana" + +msgid "Password" +msgstr "Nenosiri" + +msgid "Password confirmation" +msgstr "Uthibitisho wa nenosiri" + +msgid "Enter the same password as before, for verification." +msgstr "Rudia kuingiza nenosiri ili kuhakiki" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Tafadhali sahihisha %(username)s na nywila. Kumbuka kuzinazingatia herufi " +"kubwa na ndogo katika sehemu zote mbili." + +msgid "This account is inactive." +msgstr "Akaunti hii si hai." + +msgid "Email" +msgstr "Barua pepe" + +msgid "New password" +msgstr "Nywila mpya" + +msgid "New password confirmation" +msgstr "Uthibitisho wa nywila mpya" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Nywila yako ya zamani imekosewa. Tafadhali ingiza tena." + +msgid "Old password" +msgstr "Nywila ya zamani" + +msgid "Password (again)" +msgstr "Nywila (tena)" + +msgid "algorithm" +msgstr "alogarithimu" + +msgid "iterations" +msgstr "mizunguko" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "kazi inayohitajika" + +msgid "checksum" +msgstr "checksum" + +msgid "name" +msgstr "jina" + +msgid "content type" +msgstr "" + +msgid "codename" +msgstr "jina la msimbo" + +msgid "permission" +msgstr "ruhusa" + +msgid "permissions" +msgstr "ruhusa" + +msgid "group" +msgstr "kundi" + +msgid "groups" +msgstr "makundi" + +msgid "superuser status" +msgstr "hadhi ya mtumiaji wa juu" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "Teua mtumiaji huyu kuwa na ruhusa zote pasipo kuziainisha wazi." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "ruhusa za mtumiaji" + +msgid "Specific permissions for this user." +msgstr "Ruhusa mahususi kwa mtumiaji huyu" + +msgid "username" +msgstr "jina la mtumiaji" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "Tayari kuna anayetumia hilo jina la mtumiaji." + +msgid "first name" +msgstr "jina la kwanza" + +msgid "last name" +msgstr "jina la mwisho" + +msgid "email address" +msgstr "anuani ya barua pepe" + +msgid "staff status" +msgstr "hadhi ya utawala" + +msgid "Designates whether the user can log into this admin site." +msgstr "Teua kama mtumiaji anaweza kuingia katika tovuti ya utawala." + +msgid "active" +msgstr "hai" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr " " + +msgid "date joined" +msgstr "tarehe ya kujiunga" + +msgid "user" +msgstr "mtumiaji" + +msgid "users" +msgstr "watumiaji" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Neno siri hili linafanana sana na %(verbose_name)s." + +msgid "Your password can't be too similar to your other personal information." +msgstr "Nenosiri lako haliwezi kuwa linafanana sana na taarifa zako binafsi" + +msgid "This password is too common." +msgstr "Nenosiri hili ni la kawaida mno." + +msgid "Your password can't be a commonly used password." +msgstr "Nenosiri lako hairuhusiwi kuwa ambalo hutumika mara kwa mara." + +msgid "This password is entirely numeric." +msgstr "Nenosiri hili lina namba tupu." + +msgid "Your password can't be entirely numeric." +msgstr "Nenosiri lako haliwezi kuwa la namba tu." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Kuseti upya nywila ya %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "Umetoka" + +msgid "Password reset" +msgstr "Kuseti nywila upya" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "Ingiza nywila mpya" + +msgid "Password reset unsuccessful" +msgstr "Imeshindikana kuseti nywila upya" + +msgid "Password reset complete" +msgstr "Kuset nywila upya kumekamilika" + +msgid "Password change" +msgstr "Kubadilisha nywila" + +msgid "Password change successful" +msgstr "Imeshindikana kubadilisha nywila" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ta/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ta/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7707095 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ta/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ta/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ta/LC_MESSAGES/django.po new file mode 100644 index 0000000..3e89f57 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ta/LC_MESSAGES/django.po @@ -0,0 +1,283 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-09-24 14:24+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Tamil (http://www.transifex.com/django/django/language/ta/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ta\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "தனிப்பட்ட விவரம்" + +msgid "Permissions" +msgstr "அனுமதிகள்" + +msgid "Important dates" +msgstr "முக்கியமான தேதிகள்" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "" + +#, python-format +msgid "Change password: %s" +msgstr "" + +msgid "Authentication and Authorization" +msgstr "" + +msgid "password" +msgstr "கடவுச்சொல்" + +msgid "last login" +msgstr "கடைசி உள்நுழைவு" + +msgid "No password set." +msgstr "" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" + +msgid "The two password fields didn't match." +msgstr "" + +msgid "Password" +msgstr "கடவுச்சொல்" + +msgid "Password confirmation" +msgstr "" + +msgid "Enter the same password as before, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" + +msgid "This account is inactive." +msgstr "இந்த கணக்கு செயல்பட துவங்கவில்லை" + +msgid "Email" +msgstr "" + +msgid "New password" +msgstr "" + +msgid "New password confirmation" +msgstr "" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" + +msgid "Old password" +msgstr "" + +msgid "Password (again)" +msgstr "கடவுச்சொல்(மறுபடியும்)" + +msgid "algorithm" +msgstr "" + +msgid "iterations" +msgstr "" + +msgid "salt" +msgstr "" + +msgid "hash" +msgstr "" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "" + +msgid "checksum" +msgstr "" + +msgid "name" +msgstr "பெயர்" + +msgid "content type" +msgstr "" + +msgid "codename" +msgstr "குறிமுறை பெயர்" + +msgid "permission" +msgstr "அனுமதி" + +msgid "permissions" +msgstr "அனுமதிகள்" + +msgid "group" +msgstr "குழு" + +msgid "groups" +msgstr "குழுக்கள்" + +msgid "superuser status" +msgstr "மேலாளர் இருப்பு நிலை" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "இந்த பயனருக்கு எல்லா அங்கீகாரங்களும் வழங்கப்படவில்லை." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "பயனர் அனுமதிகள்" + +msgid "Specific permissions for this user." +msgstr "" + +msgid "username" +msgstr "பயனர் பெயர்" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "" + +msgid "first name" +msgstr "முதல் பெயர்" + +msgid "last name" +msgstr "கடைசி பெயர்" + +msgid "email address" +msgstr "" + +msgid "staff status" +msgstr "பணியாளர் நிலை" + +msgid "Designates whether the user can log into this admin site." +msgstr "பயனர், 'மேலாளலர்' பக்கத்தில் நுழைவதை முடிவு செய்கிறது" + +msgid "active" +msgstr "செயல்படும்" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" + +msgid "date joined" +msgstr "சேர்ந்த தேதி" + +msgid "user" +msgstr "பயனர்" + +msgid "users" +msgstr "பயனர்கள்" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "" + +msgid "Your password can't be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "" + +msgid "Your password can't be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "" + +msgid "Your password can't be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "வெளியே வந்துவீட்டீர்" + +msgid "Password reset" +msgstr "" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "" + +msgid "Password reset unsuccessful" +msgstr "" + +msgid "Password reset complete" +msgstr "" + +msgid "Password change" +msgstr "" + +msgid "Password change successful" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/te/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/te/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4aad473 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/te/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/te/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/te/LC_MESSAGES/django.po new file mode 100644 index 0000000..d50487c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/te/LC_MESSAGES/django.po @@ -0,0 +1,285 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# bhaskar teja yerneni , 2011 +# Jannis Leidel , 2011 +# వీవెన్ , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-09-24 14:24+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Telugu (http://www.transifex.com/django/django/language/te/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: te\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "వ్యక్తిగత సమాచారం " + +msgid "Permissions" +msgstr "అనుమతులు" + +msgid "Important dates" +msgstr "ముఖ్యమైన తేదీలు" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "సంకేతపదాన్ని విజయవంతంగా మార్చారు." + +#, python-format +msgid "Change password: %s" +msgstr "సంకేతపదాన్ని మార్చుకోండి: %s" + +msgid "Authentication and Authorization" +msgstr "" + +msgid "password" +msgstr "సంకేతపదం" + +msgid "last login" +msgstr "చివరి ప్రవేశం" + +msgid "No password set." +msgstr "" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" + +msgid "The two password fields didn't match." +msgstr "ఈ రెండు అనుమతి పదాలు అసమానమైనంగ ఉన్నాయి" + +msgid "Password" +msgstr "సంకేతపదం" + +msgid "Password confirmation" +msgstr "సంకేపదపు నిర్ధారణ" + +msgid "Enter the same password as before, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" + +msgid "This account is inactive." +msgstr "ఈ ఖాతా అచేతనమైనది" + +msgid "Email" +msgstr "" + +msgid "New password" +msgstr "కొత్త సంకేతపదం" + +msgid "New password confirmation" +msgstr "కొత్త సంకేతపదపు నిర్ధారణ" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" + +msgid "Old password" +msgstr "పాత సంకేతపదం" + +msgid "Password (again)" +msgstr "సంకేతపదం (మళ్ళీ)" + +msgid "algorithm" +msgstr "" + +msgid "iterations" +msgstr "" + +msgid "salt" +msgstr "" + +msgid "hash" +msgstr "" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "" + +msgid "checksum" +msgstr "" + +msgid "name" +msgstr "పేరు" + +msgid "content type" +msgstr "" + +msgid "codename" +msgstr "సంహితనామము" + +msgid "permission" +msgstr "అనుమతి" + +msgid "permissions" +msgstr "అనుమతులు" + +msgid "group" +msgstr "గుంపు" + +msgid "groups" +msgstr "గుంపులు" + +msgid "superuser status" +msgstr "" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "వాడుకరి అనుమతులు" + +msgid "Specific permissions for this user." +msgstr "" + +msgid "username" +msgstr "వాడుకరిపేరు" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "ఈ నామముతొ ఇంకొ వినియొగదారి ఉన్నరు" + +msgid "first name" +msgstr "మొదటి పేరు" + +msgid "last name" +msgstr "ఇంటి పేరు" + +msgid "email address" +msgstr "" + +msgid "staff status" +msgstr "ఉద్యోగస్తుల స్థితి" + +msgid "Designates whether the user can log into this admin site." +msgstr "" + +msgid "active" +msgstr "క్రియాశీలం" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" + +msgid "date joined" +msgstr "చేరిన తేదీ" + +msgid "user" +msgstr "వాడుకరి" + +msgid "users" +msgstr "వాడుకరులు" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "" + +msgid "Your password can't be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "" + +msgid "Your password can't be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "" + +msgid "Your password can't be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "నిష్క్రమించారు" + +msgid "Password reset" +msgstr "" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "" + +msgid "Password reset unsuccessful" +msgstr "" + +msgid "Password reset complete" +msgstr "" + +msgid "Password change" +msgstr "" + +msgid "Password change successful" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/tg/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/tg/LC_MESSAGES/django.mo new file mode 100644 index 0000000..301132d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/tg/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/tg/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/tg/LC_MESSAGES/django.po new file mode 100644 index 0000000..984b969 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/tg/LC_MESSAGES/django.po @@ -0,0 +1,299 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Surush Sufiew , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-05-15 00:26+0000\n" +"Last-Translator: Surush Sufiew \n" +"Language-Team: Tajik (http://www.transifex.com/django/django/language/tg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Маълумоти хусусӣ" + +msgid "Permissions" +msgstr "Салоҳият" + +msgid "Important dates" +msgstr "Санаҳои муҳим" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(name)s бо калидҳои ягонаи(pk) %(key)r вуҷуд надорад." + +msgid "Password changed successfully." +msgstr "Рамз муваффақона иваз карда шуд." + +#, python-format +msgid "Change password: %s" +msgstr "Ивазкунии рамз: %s" + +msgid "Authentication and Authorization" +msgstr "Истифодабарандагон ва гурӯҳҳо" + +msgid "password" +msgstr "рамз" + +msgid "last login" +msgstr "охирин вуруд" + +msgid "No password set." +msgstr "Рамзро ворид созед." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Формати рамз ё алгоритми ҳеш(hash) ношинос аст." + +msgid "The two password fields didn’t match." +msgstr "" + +msgid "Password" +msgstr "Рамз" + +msgid "Password confirmation" +msgstr "Тасдиқи рамз" + +msgid "Enter the same password as before, for verification." +msgstr "Барои тасдиқсозӣ хоҳишмандем, бори дигар рамзро ворид созед." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Хоҳишмандем %(username)s ва рамзро дуруст ворид созед. Ҳарду майдон " +"духӯра(case-sensitive) ҳастанд." + +msgid "This account is inactive." +msgstr "Ин ҳисоби корбарӣ хомӯш аст." + +msgid "Email" +msgstr "Суроғаи почтаи электронӣ" + +msgid "New password" +msgstr "Рамзи нав" + +msgid "New password confirmation" +msgstr "Тасдиқи рамзи нав" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" +"Рамзи пешинаро нодуруст ворид кардед. Хоҳишмандем аз нав шакли дурусташро " +"ворид созед." + +msgid "Old password" +msgstr "Рамзи кӯҳна" + +msgid "Password (again)" +msgstr "Рамз (такроран)" + +msgid "algorithm" +msgstr "алгоритм" + +msgid "iterations" +msgstr "итератсияҳо" + +msgid "salt" +msgstr "намак" + +msgid "hash" +msgstr "ҳэш" + +msgid "variety" +msgstr "маҷмӯа" + +msgid "version" +msgstr "версия" + +msgid "memory cost" +msgstr "истифодаи ҳофиза" + +msgid "time cost" +msgstr "истифодаи вақт" + +msgid "parallelism" +msgstr "параллелизм" + +msgid "work factor" +msgstr "омили корӣ" + +msgid "checksum" +msgstr "натиҷаи санҷиш" + +msgid "name" +msgstr "ном" + +msgid "content type" +msgstr "намуди контент" + +msgid "codename" +msgstr "номи рамзӣ" + +msgid "permission" +msgstr "салоҳият" + +msgid "permissions" +msgstr "салоҳият" + +msgid "group" +msgstr "гурӯҳ" + +msgid "groups" +msgstr "гурӯҳҳо" + +msgid "superuser status" +msgstr "статуси истифодабарӣ аввалиндараҷа(superuser)" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "Нишон медиҳад, ки истифодабаранда дорои ҳама гуна салоҳиятҳост." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Гуруҳҳое, ки истифодабарандаи мазкур ба онҳо шомил аст.Истифодабаранда ҳамаи " +"салоҳиятҳои дар гуруҳҳо мавҷудбударо дорост" + +msgid "user permissions" +msgstr "ҳуқуқҳои истифодабаранда" + +msgid "Specific permissions for this user." +msgstr "салоҳиятҳои шахсии истифодабаранда" + +msgid "username" +msgstr "номи истифодабаранда" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Майдони пуркаданаш зарурӣ. На беш аз 150 аломат. Танҳо аз ҳарфҳо, рақамҳо ва " +"аломатҳо @/./+/-/_." + +msgid "A user with that username already exists." +msgstr "Чунин номи истифодабаранда алакай вуҷуд дорад." + +msgid "first name" +msgstr "ном" + +msgid "last name" +msgstr "насаб" + +msgid "email address" +msgstr "суроғаи почтаи электронӣ" + +msgid "staff status" +msgstr "статуси шахс" + +msgid "Designates whether the user can log into this admin site." +msgstr "" +"Қайд кунед, агар истифодабаранда ҳуқуқи воридшавӣ ба қисми маъмурии сомонаро " +"дошта бошад." + +msgid "active" +msgstr "фаъол" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Қайд кунед, агар истифодабаранда фаъол ҳисобида шавад. Қайдро бекор кунед, " +"дар ҳолати нест сохтани ҳисоби корбарӣ" + +msgid "date joined" +msgstr "санаи бақайдгирӣ" + +msgid "user" +msgstr "истифодабаранда" + +msgid "users" +msgstr "истифодабарандаҳо" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Рамзи воридкардашуда ба %(verbose_name)s монанд аст." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "Рамзи воридкардашуда хеле серистеъмол аст." + +msgid "Your password can’t be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "Рамзи воридкардашуда танҳо аз рақамҳо иборат аст." + +msgid "Your password can’t be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Барҳамдиҳии рамз дар сайти мазкур %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"Номи истифодабарандаро дуруст ворид созед. Қимати ин майдон бояд танҳоаз " +"ҳуруфи англисӣ, рақамҳо ва аломатҳо @/./+/-/_ иборат бошад." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Номи истифодабарандаро дуруст ворид созед. Қимати ин майдон бояд танҳоаз " +"ҳарфҳо, рақамҳо ва аломатҳо @/./+/-/_ иборат бошад." + +msgid "Logged out" +msgstr "Рухсатшуда(Logged out)" + +msgid "Password reset" +msgstr "Барқарорсозии рамз" + +msgid "Password reset sent" +msgstr "Мактуби дастурамал оиди барқарорсозии рамз равон карда шуд." + +msgid "Enter new password" +msgstr "Рамзи навро ворид созед" + +msgid "Password reset unsuccessful" +msgstr "Мушкилӣ ҳангоми барқарорсозии рамз." + +msgid "Password reset complete" +msgstr "Барқарорсозии рамз ба анҷом расид." + +msgid "Password change" +msgstr "Ивази рамз" + +msgid "Password change successful" +msgstr "рамз муваффақона иваз карда шуд" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/th/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/th/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5f96948 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/th/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/th/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/th/LC_MESSAGES/django.po new file mode 100644 index 0000000..79da789 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/th/LC_MESSAGES/django.po @@ -0,0 +1,282 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Kowit Charoenratchatabhan , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-11-29 04:33+0000\n" +"Last-Translator: Kowit Charoenratchatabhan \n" +"Language-Team: Thai (http://www.transifex.com/django/django/language/th/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: th\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Personal info" +msgstr "ข้อมูลส่วนตัว" + +msgid "Permissions" +msgstr "สิทธิ์" + +msgid "Important dates" +msgstr "วันที่ที่สำคัญ" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "เปลี่ยนรหัสผ่านสำเร็จแล้ว" + +#, python-format +msgid "Change password: %s" +msgstr "เปลี่ยนรหัสผ่าน: %s " + +msgid "Authentication and Authorization" +msgstr "การตรวจสอบและอนุมัติ" + +msgid "password" +msgstr "รหัสผ่าน" + +msgid "last login" +msgstr "เข้าสู่ระบบครั้งสุดท้าย" + +msgid "No password set." +msgstr "ไม่ได้ตั้งค่ารหัสผ่าน" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "รูปแบบรหัสผ่านไม่ถูกต้อง หรือไม่รู้จักแฮชอัลกอริทึมนี้" + +msgid "The two password fields didn't match." +msgstr "รหัสผ่านไม่ตรงกัน" + +msgid "Password" +msgstr "รหัสผ่าน" + +msgid "Password confirmation" +msgstr "ยืนยันรหัสผ่าน" + +msgid "Enter the same password as before, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "กรุณาใส่ %(username)s และรหัสผ่านที่ถูกต้อง มีการแยกแยะตัวพิมพ์ใหญ่-เล็ก" + +msgid "This account is inactive." +msgstr "บัญชีนี้ไม่ทำงาน" + +msgid "Email" +msgstr "อีเมล" + +msgid "New password" +msgstr "รหัสผ่านใหม่" + +msgid "New password confirmation" +msgstr "ยืนยันการตั้งรหัสผ่านใหม่" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "ใส่รหัสผ่านเก่าผิด กรุณาใส่รหัสผ่านอีกครั้ง" + +msgid "Old password" +msgstr "รหัสผ่านเก่า" + +msgid "Password (again)" +msgstr "รหัสผ่าน (อีกครั้ง)" + +msgid "algorithm" +msgstr "algorithm" + +msgid "iterations" +msgstr "iterations" + +msgid "salt" +msgstr "salt" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "ปัจจัยการทำงาน" + +msgid "checksum" +msgstr "checksum" + +msgid "name" +msgstr "ชื่อ" + +msgid "content type" +msgstr "" + +msgid "codename" +msgstr "รหัสชื่อ" + +msgid "permission" +msgstr "สิทธิ์" + +msgid "permissions" +msgstr "สิทธิ์" + +msgid "group" +msgstr "กลุ่ม" + +msgid "groups" +msgstr "กลุ่ม" + +msgid "superuser status" +msgstr "สถานะผู้ใช้พิเศษ" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "กำหนดสิทธิ์ทุกอย่างให้ผู้ใช้ โดยไม่ต้องการมอบหมายอย่างเป็นทางการ" + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "สิทธิ์ของผู้ใช้" + +msgid "Specific permissions for this user." +msgstr "สิทธิ์ที่เฉพาะเจาะจงสำหรับผู้ใช้นี้" + +msgid "username" +msgstr "ชื่อผู้ใช้" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "ชื่อผู้ใช้นั้นได้ถูกใช้ไปแล้ว" + +msgid "first name" +msgstr "ชื่อ" + +msgid "last name" +msgstr "นามสกุล" + +msgid "email address" +msgstr "ที่อยู่อีเมล" + +msgid "staff status" +msgstr "สถานะของพนักงาน" + +msgid "Designates whether the user can log into this admin site." +msgstr "กำหนดผู้ที่จะเข้ามาใช้งานในส่วนของผู้ดูแลระบบ" + +msgid "active" +msgstr "ใช้งานได้" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "กำหนดให้ผู้ใช้มีสถานะที่สามารถเข้ามาใช้งานได้ เลือกออกแทนที่จะลบชื่อผู้ใช้ทิ้งไป " + +msgid "date joined" +msgstr "วันที่เข้าร่วม" + +msgid "user" +msgstr "ผู้ใช้" + +msgid "users" +msgstr "ผู้ใช้" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "" + +msgid "Your password can't be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "" + +msgid "Your password can't be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "" + +msgid "Your password can't be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "รีเซ็ตรหัสผ่านบน %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "ออกจากระบบ" + +msgid "Password reset" +msgstr "รีเซ็ตรหัสผ่าน" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "ป้อนรหัสผ่านใหม่" + +msgid "Password reset unsuccessful" +msgstr "ตั้งรหัสผ่านใหม่ไม่สำเร็จ" + +msgid "Password reset complete" +msgstr "รีเซ็ตรหัสผ่านเสร็จสมบูรณ์" + +msgid "Password change" +msgstr "เปลี่ยนรหัสผ่าน" + +msgid "Password change successful" +msgstr "เปลี่ยนรหัสผ่านสำเร็จ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/tk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/tk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a1e0ec3 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/tk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/tk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/tk/LC_MESSAGES/django.po new file mode 100644 index 0000000..f4a7bbb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/tk/LC_MESSAGES/django.po @@ -0,0 +1,307 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Resul , 2020 +# Resul , 2022-2023 +# Welbeck Garli , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-12-04 08:09+0000\n" +"Last-Translator: Resul , 2022-2023\n" +"Language-Team: Turkmen (http://app.transifex.com/django/django/language/" +"tk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tk\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "Şahsy maglumat" + +msgid "Permissions" +msgstr "Rugsatlar" + +msgid "Important dates" +msgstr "Möhüm seneler" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "Esasy açary %(key)r bolan %(name)s obýekt ýok." + +msgid "Password changed successfully." +msgstr "Parol üstünlikli üýtgedildi." + +#, python-format +msgid "Change password: %s" +msgstr "Paroly üýtgetmek: %s" + +msgid "Authentication and Authorization" +msgstr "Şahsyýet tanamak we Ygtyýarnama" + +msgid "password" +msgstr "parol" + +msgid "last login" +msgstr "soňky giriş" + +msgid "No password set." +msgstr "Parol goýulmady." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Nädogry parol formaty ýa-da näbelli hashing algoritmi." + +msgid "The two password fields didn’t match." +msgstr "Iki parol meýdançasy gabat gelmedi." + +msgid "Password" +msgstr "Parol" + +msgid "Password confirmation" +msgstr "Parol tassyklamasy" + +msgid "Enter the same password as before, for verification." +msgstr "Barlamak üçin öňküsi ýaly paroly giriziň." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Çig parollar saklanmaýar, şonuň üçin bu ulanyjynyň parolyny görmegiň " +"mümkinçiligi ýok, ýöne şu formany ulanyp üýtgedip " +"bilersiňiz." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Haýyş, dogry %(username)s we paroly giriziň. Iki meýdançanyň hem baş-setir " +"harpa duýgur bolup biljekdigine üns beriň." + +msgid "This account is inactive." +msgstr "Bu hasap hereketsiz." + +msgid "Email" +msgstr "E-mail" + +msgid "New password" +msgstr "Täze parol" + +msgid "New password confirmation" +msgstr "Täze parol tassyklamasy" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" +"Köne parolyňyz nädogry girizildi. Gaýtadan girizmegiňizi haýyş edýäris." + +msgid "Old password" +msgstr "Köne parol" + +msgid "Password (again)" +msgstr "Parol (gaýtadan)" + +msgid "algorithm" +msgstr "algoritm" + +msgid "iterations" +msgstr "gaýtalama" + +msgid "salt" +msgstr "duz" + +msgid "hash" +msgstr "hash" + +msgid "variety" +msgstr "dürlülik" + +msgid "version" +msgstr "wersiýa" + +msgid "memory cost" +msgstr "ýadyň bahasy" + +msgid "time cost" +msgstr "wagt bahasy" + +msgid "parallelism" +msgstr "parallellik" + +msgid "work factor" +msgstr "iş faktory" + +msgid "checksum" +msgstr "çek" + +msgid "block size" +msgstr "blok ölçegi" + +msgid "name" +msgstr "at" + +msgid "content type" +msgstr "mazmunyň görnüşi" + +msgid "codename" +msgstr "kod ady" + +msgid "permission" +msgstr "rugsat" + +msgid "permissions" +msgstr "rugsatlar" + +msgid "group" +msgstr "topar" + +msgid "groups" +msgstr "toparlar" + +msgid "superuser status" +msgstr "superuser ýagdaýy" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Bu ulanyjynyň aç-açan bellemezden ähli rugsatlarynyň bardygyny belleýär." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Bu ulanyjynyň degişli toparlary. Ulanyjy her bir topara berlen ähli " +"rugsatlary alar." + +msgid "user permissions" +msgstr "ulanyjy rugsatlary" + +msgid "Specific permissions for this user." +msgstr "Bu ulanyjy üçin ýörite rugsatlar." + +msgid "username" +msgstr "ulanyjy ady" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Gerekli. 150 harp ýa-da azyrak. Diňe harplar, sanlar we @/./+/-/_ mümkin." + +msgid "A user with that username already exists." +msgstr "Bu ulanyjy adyny ulanýan ulanyjy eýýäm bar." + +msgid "first name" +msgstr "at" + +msgid "last name" +msgstr "familiýa" + +msgid "email address" +msgstr "email salgy" + +msgid "staff status" +msgstr "işgärleriň ýagdaýy" + +msgid "Designates whether the user can log into this admin site." +msgstr "Ulanyjynyň bu administrator sahypasyna girip biljekdigini kesgitleýär." + +msgid "active" +msgstr "işjeň" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Bu ulanyja işjeň garalmalydygyny ýa-da ýokdugyny kesgitleýär. Hasaplary " +"pozmagyň ýerine şuny saýlaň." + +msgid "date joined" +msgstr "goşulan senesi" + +msgid "user" +msgstr "ulanyjy" + +msgid "users" +msgstr "ulanyjylar" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Bu parol gaty gysga. Iň azyndan %(min_length)d nyşandan ybarat bolmaly." +msgstr[1] "" +"Bu parol gaty gysga. Iň azyndan %(min_length)d nyşandan ybarat bolmaly." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Parolyňyzda azyndan %(min_length)d nyşan bolmaly." +msgstr[1] "Parolyňyzda azyndan %(min_length)d nyşan bolmaly." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Parol %(verbose_name)s-e gaty meňzeýär." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Parolyňyz beýleki şahsy maglumatlaryňyza gaty meňzeş bolmaly däl." + +msgid "This password is too common." +msgstr "Bu parol gaty ýygy ulanylýar." + +msgid "Your password can’t be a commonly used password." +msgstr "Parolyňyz köplenç ulanylýan parol bolmaly däl." + +msgid "This password is entirely numeric." +msgstr "Bu parol diňe sanlardan ybarat." + +msgid "Your password can’t be entirely numeric." +msgstr "Parolyňyz diňe sanlardan ybarat bolup bilmez." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "%(site_name)s-de paroly täzeden düzüldi" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Dogry ulanyjy adyny giriziň. Bu bahada diňe aksentsiz kiçi a-z harplary we " +"uly A-Z harplary, sanlar we @/./+/-/_ nyşanlary bolup biler." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Dogry ulanyjy adyny giriziň. Bu bahada diňe harplar, sanlar we @/./+/-/_ " +"nyşanlary bolup biler." + +msgid "Logged out" +msgstr "Çykyldy" + +msgid "Password reset" +msgstr "Paroly täzeden düzmek" + +msgid "Password reset sent" +msgstr "Paroly täzeden düzmek boýunça görkezmeler iberildi" + +msgid "Enter new password" +msgstr "Täze parol giriziň" + +msgid "Password reset unsuccessful" +msgstr "Paroly täzeden düzüp bolmady" + +msgid "Password reset complete" +msgstr "Paroly täzeden düzüldi" + +msgid "Password change" +msgstr "Parol üýtgetmek" + +msgid "Password change successful" +msgstr "Parol üýtgetmek üstünlikli tamamlandy" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/tr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/tr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..09b4e47 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/tr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/tr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/tr/LC_MESSAGES/django.po new file mode 100644 index 0000000..734662d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/tr/LC_MESSAGES/django.po @@ -0,0 +1,313 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ahmet Emre Aladağ , 2013 +# BouRock, 2015-2017,2019-2021,2023 +# BouRock, 2014-2015 +# Caner Başaran , 2013 +# Cihad GÜNDOĞDU , 2014 +# Gökmen Görgen , 2013 +# Jannis Leidel , 2011 +# Metin Amiroff , 2012 +# Murat Çorlu , 2012 +# U. Ozan Basar , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-04-25 08:09+0000\n" +"Last-Translator: BouRock, 2015-2017,2019-2021,2023\n" +"Language-Team: Turkish (http://www.transifex.com/django/django/language/" +"tr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Personal info" +msgstr "Kişisel bilgiler" + +msgid "Permissions" +msgstr "İzinler" + +msgid "Important dates" +msgstr "Önemli tarihler" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(key)r birincil anahtarı olan %(name)s nesnesi mevcut değil." + +msgid "Password changed successfully." +msgstr "Parola başarılı olarak değiştirildi." + +#, python-format +msgid "Change password: %s" +msgstr "Parolayı değiştir: %s" + +msgid "Authentication and Authorization" +msgstr "Kimlik Doğrulama ve Yetkilendirme" + +msgid "password" +msgstr "parola" + +msgid "last login" +msgstr "son oturum açma" + +msgid "No password set." +msgstr "Ayarlı parola yok." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Geçersiz parola biçimi veya bilinmeyen adresleme algoritması." + +msgid "The two password fields didn’t match." +msgstr "İki parola alanı eşleşmedi." + +msgid "Password" +msgstr "Parola" + +msgid "Password confirmation" +msgstr "Parola onayı" + +msgid "Enter the same password as before, for verification." +msgstr "Doğrulama için önceki gibi aynı parolayı girin." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Ham parolalar saklanmaz, bu yüzden bu kullanıcının parolasını görmenin yolu " +"yoktur, fakat bu formu kullanarak parolayı " +"değiştirebilirsiniz." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Lütfen doğru %(username)s ve parola girin. Her iki alanın da büyük/küçük " +"harfe duyarlı olabileceğini unutmayın." + +msgid "This account is inactive." +msgstr "Bu hesap devre dışı." + +msgid "Email" +msgstr "E-posta" + +msgid "New password" +msgstr "Yeni parola" + +msgid "New password confirmation" +msgstr "Yeni parola onayı" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Eski parolanız yanlış girildi. Lütfen tekrar girin." + +msgid "Old password" +msgstr "Eski parola" + +msgid "Password (again)" +msgstr "Parola (tekrar)" + +msgid "algorithm" +msgstr "algoritma" + +msgid "iterations" +msgstr "yinelemeler" + +msgid "salt" +msgstr "tuz" + +msgid "hash" +msgstr "adresleme" + +msgid "variety" +msgstr "çeşitlilik" + +msgid "version" +msgstr "sürüm" + +msgid "memory cost" +msgstr "bellek maliyeti" + +msgid "time cost" +msgstr "zaman maliyeti" + +msgid "parallelism" +msgstr "paralellik" + +msgid "work factor" +msgstr "iş faktörü" + +msgid "checksum" +msgstr "sağlama" + +msgid "block size" +msgstr "blok boyutu" + +msgid "name" +msgstr "adı" + +msgid "content type" +msgstr "içerik türü" + +msgid "codename" +msgstr "kod adı" + +msgid "permission" +msgstr "izin" + +msgid "permissions" +msgstr "izinler" + +msgid "group" +msgstr "grup" + +msgid "groups" +msgstr "gruplar" + +msgid "superuser status" +msgstr "süper kullanıcı durumu" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Bu kullanıcıya ayrı ayrı izin atamadan tüm izinlerin verilip verilmeyeceğini " +"belirler." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Bu kullanıcının ait olduğu gruplar. Bir kullanıcı kendi gruplarının her " +"birine verilmiş olan tüm izinleri alacak." + +msgid "user permissions" +msgstr "kullanıcı izinleri" + +msgid "Specific permissions for this user." +msgstr "Bu kullanıcı için belirli izinler." + +msgid "username" +msgstr "kullanıcı adı" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Zorunlu. 150 karakter ya da daha az olmalı. Sadece harfler, rakamlar ve @/./" +"+/-/_ karakterleri kullanılabilir." + +msgid "A user with that username already exists." +msgstr "Bu kullanıcı adında bir kullanıcı zaten mevcut." + +msgid "first name" +msgstr "adı" + +msgid "last name" +msgstr "soyadı" + +msgid "email address" +msgstr "e-posta adresi" + +msgid "staff status" +msgstr "görev durumu" + +msgid "Designates whether the user can log into this admin site." +msgstr "Kullanıcının bu yönetici sitesine oturum açıp açamayacağını belirler." + +msgid "active" +msgstr "etkin" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Bu kullanıcının etkin olarak işlem görüp görmediğini belirler. Hesapları " +"silmek yerine bunun işaretini kaldırın." + +msgid "date joined" +msgstr "katılma tarihi" + +msgid "user" +msgstr "kullanıcı" + +msgid "users" +msgstr "kullanıcılar" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "Bu parola çok kısa. En az %(min_length)d karakter içermek zorunda." +msgstr[1] "Bu parola çok kısa. En az %(min_length)d karakter içermek zorunda." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Parolanız en az %(min_length)d karakter içermek zorunda." +msgstr[1] "Parolanız en az %(min_length)d karakter içermek zorundadır." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Parolanız %(verbose_name)s ile çok benzerdir." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Parolanız diğer kişisel bilgileriniz ile çok benzer olamaz." + +msgid "This password is too common." +msgstr "Bu parola çok geneldir." + +msgid "Your password can’t be a commonly used password." +msgstr "Parolanız yaygın olarak kullanılan bir parola olamaz." + +msgid "This password is entirely numeric." +msgstr "Bu parola tamamıyla sayısaldır." + +msgid "Your password can’t be entirely numeric." +msgstr "Parolanız tamamıyla sayısal olamaz." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "%(site_name)s sitesinde parola sıfırlama" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Geçerli bir kullanıcı adı girin. Bu değer sadece aksansız küçük a-z ve büyük " +"A-Z harfleri, sayıları, ve @/./+/-/_ karakterlerini içerebilir." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Geçerli bir kullanıcı adı girin. Bu değer sadece harfleri, sayıları, ve @/./" +"+/-/_ karakterlerini içerebilir." + +msgid "Logged out" +msgstr "Oturum kapatıldı" + +msgid "Password reset" +msgstr "Parolayı sıfırla" + +msgid "Password reset sent" +msgstr "Parola sıfırlama gönderildi" + +msgid "Enter new password" +msgstr "Yeni parolayı girin" + +msgid "Password reset unsuccessful" +msgstr "Parola sıfırlama başarısız" + +msgid "Password reset complete" +msgstr "Parola sıfırlama tamamlandı" + +msgid "Password change" +msgstr "Parola değiştirme" + +msgid "Password change successful" +msgstr "Parola değiştirme başarılı" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/tt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/tt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c2d43fd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/tt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/tt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/tt/LC_MESSAGES/django.po new file mode 100644 index 0000000..189846a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/tt/LC_MESSAGES/django.po @@ -0,0 +1,281 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# v_ildar , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-09-24 14:24+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Tatar (http://www.transifex.com/django/django/language/tt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tt\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Personal info" +msgstr "" + +msgid "Permissions" +msgstr "" + +msgid "Important dates" +msgstr "" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "" + +#, python-format +msgid "Change password: %s" +msgstr "" + +msgid "Authentication and Authorization" +msgstr "" + +msgid "password" +msgstr "серсүз" + +msgid "last login" +msgstr "" + +msgid "No password set." +msgstr "" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" + +msgid "The two password fields didn't match." +msgstr "" + +msgid "Password" +msgstr "Серсүз" + +msgid "Password confirmation" +msgstr "" + +msgid "Enter the same password as before, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" + +msgid "This account is inactive." +msgstr "" + +msgid "Email" +msgstr "Эл. почта" + +msgid "New password" +msgstr "Яңа серсүз" + +msgid "New password confirmation" +msgstr "" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" + +msgid "Old password" +msgstr "Иске серсүз" + +msgid "Password (again)" +msgstr "Серсүз (тагын бер тапкыр)" + +msgid "algorithm" +msgstr "" + +msgid "iterations" +msgstr "" + +msgid "salt" +msgstr "" + +msgid "hash" +msgstr "" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "" + +msgid "checksum" +msgstr "" + +msgid "name" +msgstr "исем" + +msgid "content type" +msgstr "" + +msgid "codename" +msgstr "" + +msgid "permission" +msgstr "" + +msgid "permissions" +msgstr "" + +msgid "group" +msgstr "" + +msgid "groups" +msgstr "" + +msgid "superuser status" +msgstr "" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "" + +msgid "Specific permissions for this user." +msgstr "" + +msgid "username" +msgstr "кулланучы исеме" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "" + +msgid "first name" +msgstr "" + +msgid "last name" +msgstr "" + +msgid "email address" +msgstr "эл. почта адресы" + +msgid "staff status" +msgstr "" + +msgid "Designates whether the user can log into this admin site." +msgstr "" + +msgid "active" +msgstr "" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" + +msgid "date joined" +msgstr "" + +msgid "user" +msgstr "кулланучы" + +msgid "users" +msgstr "кулланучылар" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "" + +msgid "Your password can't be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "" + +msgid "Your password can't be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "" + +msgid "Your password can't be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "" + +msgid "Password reset" +msgstr "Серсүзне торгызу" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "Яңа серсүзне кертегез" + +msgid "Password reset unsuccessful" +msgstr "" + +msgid "Password reset complete" +msgstr "" + +msgid "Password change" +msgstr "Серсүзне үзгәртү" + +msgid "Password change successful" +msgstr "Серсүз уңышлы рәвештә үзгәртелгән" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/udm/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/udm/LC_MESSAGES/django.mo new file mode 100644 index 0000000..040fd65 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/udm/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/udm/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/udm/LC_MESSAGES/django.po new file mode 100644 index 0000000..c5605af --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/udm/LC_MESSAGES/django.po @@ -0,0 +1,226 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-03-18 09:16+0100\n" +"PO-Revision-Date: 2015-03-18 10:30+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Udmurt (http://www.transifex.com/projects/p/django/language/" +"udm/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: udm\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Personal info" +msgstr "" + +msgid "Permissions" +msgstr "" + +msgid "Important dates" +msgstr "" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "" + +#, python-format +msgid "Change password: %s" +msgstr "" + +msgid "Authentication and Authorization" +msgstr "" + +msgid "No password set." +msgstr "" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" + +msgid "The two password fields didn't match." +msgstr "" + +msgid "Password" +msgstr "" + +msgid "Password confirmation" +msgstr "" + +msgid "Enter the same password as above, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this " +"form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" + +msgid "This account is inactive." +msgstr "" + +msgid "Email" +msgstr "" + +msgid "New password" +msgstr "" + +msgid "New password confirmation" +msgstr "" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" + +msgid "Old password" +msgstr "" + +msgid "Password (again)" +msgstr "" + +msgid "algorithm" +msgstr "" + +msgid "iterations" +msgstr "" + +msgid "salt" +msgstr "" + +msgid "hash" +msgstr "" + +msgid "work factor" +msgstr "" + +msgid "checksum" +msgstr "" + +msgid "name" +msgstr "" + +msgid "codename" +msgstr "" + +msgid "permission" +msgstr "" + +msgid "permissions" +msgstr "" + +msgid "group" +msgstr "" + +msgid "groups" +msgstr "" + +msgid "password" +msgstr "" + +msgid "last login" +msgstr "" + +msgid "superuser status" +msgstr "" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "" + +msgid "Specific permissions for this user." +msgstr "" + +msgid "username" +msgstr "" + +msgid "Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers and @/./" +"+/-/_ characters." +msgstr "" + +msgid "A user with that username already exists." +msgstr "" + +msgid "first name" +msgstr "" + +msgid "last name" +msgstr "" + +msgid "email address" +msgstr "" + +msgid "staff status" +msgstr "" + +msgid "Designates whether the user can log into this admin site." +msgstr "" + +msgid "active" +msgstr "" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" + +msgid "date joined" +msgstr "" + +msgid "user" +msgstr "" + +msgid "users" +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "" + +msgid "Logged out" +msgstr "" + +msgid "Password reset" +msgstr "" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "" + +msgid "Password reset unsuccessful" +msgstr "" + +msgid "Password reset complete" +msgstr "" + +msgid "Password change" +msgstr "" + +msgid "Password change successful" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ug/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ug/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2228f92 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ug/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ug/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ug/LC_MESSAGES/django.po new file mode 100644 index 0000000..ef15de3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ug/LC_MESSAGES/django.po @@ -0,0 +1,312 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Abduqadir Abliz , 2023 +# Azat, 2023 +# Murat Orhun , 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-12-04 08:09+0000\n" +"Last-Translator: Azat, 2023\n" +"Language-Team: Uyghur (http://app.transifex.com/django/django/language/ug/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ug\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "شەخسىي ئۇچۇر" + +msgid "Permissions" +msgstr "ئىمتىيازلار" + +msgid "Important dates" +msgstr "مۇھىم چېسلا" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(key)r ئاساسىي ئاچقۇچى بار %(name)s ئوبيېكت مەۋجۇت ئەمەس." + +msgid "Password changed successfully." +msgstr "پارول مۇۋەپپەقىيەتلىك ئۆزگەرتىلدى." + +#, python-format +msgid "Change password: %s" +msgstr "پارول ئۆزگەرتىش: %s" + +msgid "Authentication and Authorization" +msgstr "دەلىللەش ۋە ھوقۇق بېرىش" + +msgid "password" +msgstr "پارول" + +msgid "last login" +msgstr "ئاخىرقى كىرگەن ۋاقتى" + +msgid "No password set." +msgstr "پارول تەڭشەلمىگەن." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" +"ئىناۋەتسىز پارول پىچىمى ياكى يوچۇن مۇكەممەللىكىنى تەكشۈرۈش ھېسابلاش ئۇسۇلى." + +msgid "The two password fields didn’t match." +msgstr "ئىككى پارول بۆلىكى ماس كەلمىدى." + +msgid "Password" +msgstr "پارول" + +msgid "Password confirmation" +msgstr "پارول جەزملەش" + +msgid "Enter the same password as before, for verification." +msgstr "دەلىللەش ئۈچۈن، ئىلگىرىكى ئوخشاش ئىمنى قايتا كىرگۈزۈڭ." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"ئەسلى پارول سىستېمىغا ساقلانمايدۇ، شۇڭلاشقا بۇ ئىشلەتكۈچى ئىشلەتكەن پارولىنى " +"كۆرگىلى بولمايدۇ، ئەمما بۇ جەدۋەل نى ئىشلىتىپ پارولنى " +"ئۆزگەرتەلەيسىز." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Please enter a correct %(username)s and password. دىققەت ھەر ئىككى بۆلەك چوڭ " +"كىچىك يېزىلىشنى پەرقلەندۈرۈشى مۇمكىن." + +msgid "This account is inactive." +msgstr "بۇ ھېسابات ئاكتىپلانمىغان." + +msgid "Email" +msgstr "ئېلخەت" + +msgid "New password" +msgstr "يېڭى پارول" + +msgid "New password confirmation" +msgstr "يېڭى پارول جەزملەش" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "كونا پارولنى توغرا كىرگۈزمىدىڭىز. قايتا كىرگۈزۈڭ." + +msgid "Old password" +msgstr "كونا پارول" + +msgid "Password (again)" +msgstr "پارول (قايتا)" + +msgid "algorithm" +msgstr "ئالگورىزىم" + +msgid "iterations" +msgstr "تەكرارلاش" + +msgid "salt" +msgstr "تۇز" + +msgid "hash" +msgstr "خەش" + +msgid "variety" +msgstr "كۆپ خىللىقى" + +msgid "version" +msgstr "نەشرى" + +msgid "memory cost" +msgstr "ئەسلەك سەرپىياتى" + +msgid "time cost" +msgstr "ۋاقىت سەرپىياتى" + +msgid "parallelism" +msgstr "ئوخشاشلىق" + +msgid "work factor" +msgstr "شىفىرلاش ئامىلى" + +msgid "checksum" +msgstr "تەكشۈرۈش يىغىندىسى" + +msgid "block size" +msgstr "بۆلەك چوڭلۇقى" + +msgid "name" +msgstr "ئىسمى" + +msgid "content type" +msgstr "مەزمۇن تىپى" + +msgid "codename" +msgstr "كود ئىسمى" + +msgid "permission" +msgstr "ھوقۇق" + +msgid "permissions" +msgstr "ھوقۇق" + +msgid "group" +msgstr "گۇرۇپپا" + +msgid "groups" +msgstr "گۇرۇپپىلار" + +msgid "superuser status" +msgstr "ئالاھىدە ئىشلەتكۈچى ھالىتى" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"بۇ ئىشلەتكۈچىنىڭ كۆڭۈلدىكى ئەھۋالدا ئېنىق تەقسىملەنمىگەنلىرىدىن باشقا ئىگە " +"بولىدىغان ھوقۇقلىرىنى بەلگىلەيدۇ." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"بۇ ئىشلەتكۈچى گۇرۇپپىغا تەۋە. ئۇ ئىشلەتكۈچى شۇ گۇرۇپپا ئىگە بولغان " +"ھوقۇقلارنىڭ ھەممىسىگە ئېرىشىدۇ." + +msgid "user permissions" +msgstr "ئىشلەتكۈچى ھوقۇقلىرى" + +msgid "Specific permissions for this user." +msgstr "بۇ ئىشلەتكۈچىگە بېرىلگەن مۇئەييەن ھوقۇقلار." + +msgid "username" +msgstr "ئىشلەتكۈچى ئاتى" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"زۆرۈر: 150 ھەرپ ياكى ئاز. ھەرپ، سان ۋە «@»، «.»، «-»، «_» لارنىلا ئۆز ئىچىگە " +"ئالىدۇ." + +msgid "A user with that username already exists." +msgstr "بۇ ئىسىمدىكى ئىشلەتكۈچى مەۋجۇت." + +msgid "first name" +msgstr "ئاتى" + +msgid "last name" +msgstr "تەگئات" + +msgid "email address" +msgstr "ئېلخەت ئادرېسى" + +msgid "staff status" +msgstr "خىزمەت ھالىتى" + +msgid "Designates whether the user can log into this admin site." +msgstr "بۇ ئىشلەتكۈچىنىڭ مەزكۇر باشقۇرۇش بېكىتىگە كىرەلىشىنى بەلگىلەيدۇ." + +msgid "active" +msgstr "ئاكتىپ" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"ئىشلەتكۈچىنىڭ ئاكتىپلىقىنى بەلگىلەيدۇ، بۇ تاللانمىسا ھېسابات ئۆچۈرۈلىدۇ." + +msgid "date joined" +msgstr "كىرگەن چېسلا" + +msgid "user" +msgstr "ئىشلەتكۈچى" + +msgid "users" +msgstr "ئىشلەتكۈچىلەر" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"پارول بەك قىسقا. ئۇ ئاز دېگەندە %(min_length)d ھەرپنى ئۆز ئىچىگە ئالىدۇ." +msgstr[1] "" +"پارول بەك قىسقا. ئۇ ئاز دېگەندە %(min_length)d ھەرپنى ئۆز ئىچىگە ئالىدۇ." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +"سىز بەلگىلىگەن پارول ئاز دېگەندە %(min_length)d ھەرپنى ئۆز ئىچىگە ئېلىشى " +"كېرەك." +msgstr[1] "" +"سىز بەلگىلىگەن پارول ئاز دېگەندە %(min_length)d ھەرپنى ئۆز ئىچىگە ئېلىشى " +"كېرەك." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "پارول %(verbose_name)s غا بەك ئوخشايدۇ." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "سىز ئىشلەتكەن پارول باشقا ئۇچۇرلىرىڭىزغا بەك ئوخشاپ كەتسە بولمايدۇ." + +msgid "This password is too common." +msgstr "بۇ پارول بەك كۆپ ئۇچرايدۇ." + +msgid "Your password can’t be a commonly used password." +msgstr "سىز ئىشلەتكەن پارول كۆپ ئۇچرايدىغان ئىم بولسا بولمايدۇ." + +msgid "This password is entirely numeric." +msgstr "بۇ پارول پەقەت سانلا بار." + +msgid "Your password can’t be entirely numeric." +msgstr "سىز ئىشلەتكەن پارول ساندىنلا تەركىپ تاپسا بولمايدۇ." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "%(site_name)s ئىشلەتكەن پارول ئەسلىگە قايتۇرۇلىدۇ" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"ئىناۋەتلىك ئىشلەتكۈچى ئاتىنى كىرگۈزۈڭ. This value may contain only " +"unaccented lowercase a-z and uppercase A-Z letters, numbers, and @/./+/-/_ " +"characters." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"ئىناۋەتلىك ئىشلەتكۈچى ئاتىنى كىرگۈزۈڭ. This value may contain only letters, " +"numbers, and @/./+/-/_ characters." + +msgid "Logged out" +msgstr "تىزىمدىن چىقىڭ" + +msgid "Password reset" +msgstr "پارولنى ئەسلىگە قايتۇرۇش" + +msgid "Password reset sent" +msgstr "پارولنى ئەسلىگە قايتۇرۇش يوللاندى" + +msgid "Enter new password" +msgstr "يېڭى پارول كىرگۈزۈڭ" + +msgid "Password reset unsuccessful" +msgstr "پارولنى ئەسلىگە قايتۇرۇش مەغلۇپ بولدى" + +msgid "Password reset complete" +msgstr "پارولنى ئەسلىگە قايتۇرۇش تامام" + +msgid "Password change" +msgstr "پارولنى ئۆزگەرتىش" + +msgid "Password change successful" +msgstr "پارول مۇۋەپپەقىيەتلىك ئۆزگەردى" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/uk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/uk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9141222 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/uk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/uk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/uk/LC_MESSAGES/django.po new file mode 100644 index 0000000..2192b73 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/uk/LC_MESSAGES/django.po @@ -0,0 +1,323 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# captain_m4l , 2012 +# Igor Melnyk, 2014-2015 +# Illia Volochii , 2021,2023 +# Jannis Leidel , 2011 +# Kirill Gagarski , 2015 +# Max V. Stotsky , 2014 +# captain_m4l , 2012 +# Mykola Zamkovoi , 2014,2021 +# Alex Bolotov , 2013 +# Vitaliy Kozlovskyi , 2015 +# Zoriana Zaiats, 2016-2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-04-25 08:09+0000\n" +"Last-Translator: Illia Volochii , 2021,2023\n" +"Language-Team: Ukrainian (http://www.transifex.com/django/django/language/" +"uk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: uk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != " +"11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % " +"100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || " +"(n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n" + +msgid "Personal info" +msgstr "Особиста інформація" + +msgid "Permissions" +msgstr "Дозволи" + +msgid "Important dates" +msgstr "Важливі дати" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(name)s об'єкт з первинним ключем %(key)r не існує." + +msgid "Password changed successfully." +msgstr "Пароль успішно змінено." + +#, python-format +msgid "Change password: %s" +msgstr "Змінити пароль: %s" + +msgid "Authentication and Authorization" +msgstr "Аутентифікація та авторизація" + +msgid "password" +msgstr "пароль" + +msgid "last login" +msgstr "останній вхід" + +msgid "No password set." +msgstr "Пароль не встановлено." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Невірний формат пароля або невідомий алгоритм хешування." + +msgid "The two password fields didn’t match." +msgstr "Паролі не збігаються" + +msgid "Password" +msgstr "Пароль" + +msgid "Password confirmation" +msgstr "Підтвердження пароля" + +msgid "Enter the same password as before, for verification." +msgstr "Введіть той же пароль, що і раніше, для підтвердження." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Паролі не зберігаються у відкритому вигляді, тому немає можливості " +"переглянути пароль цього користувача, але ви можете змінити пароль за " +"допомогою цієї форми." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Будь ласка, введіть правильні %(username)s та пароль. Зауважте, що обидва " +"поля чутливі до регістру." + +msgid "This account is inactive." +msgstr "Цей запис користувача не активний." + +msgid "Email" +msgstr "Email" + +msgid "New password" +msgstr "Новий пароль" + +msgid "New password confirmation" +msgstr "Новий пароль (підтвердження)" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" +"Старий пароль було введено неправильно. Будь ласка, введіть його знову." + +msgid "Old password" +msgstr "Старий пароль" + +msgid "Password (again)" +msgstr "Пароль (ще раз)" + +msgid "algorithm" +msgstr "алгоритм" + +msgid "iterations" +msgstr "ітерації" + +msgid "salt" +msgstr "сіль" + +msgid "hash" +msgstr "хеш" + +msgid "variety" +msgstr "різноманітність" + +msgid "version" +msgstr "версія" + +msgid "memory cost" +msgstr "витрати пам’яті" + +msgid "time cost" +msgstr "витрати часу" + +msgid "parallelism" +msgstr "паралелізм" + +msgid "work factor" +msgstr "робочий фактор" + +msgid "checksum" +msgstr "контрольна сума" + +msgid "block size" +msgstr "розмір блоку" + +msgid "name" +msgstr "ім'я" + +msgid "content type" +msgstr "тип вмісту" + +msgid "codename" +msgstr "код" + +msgid "permission" +msgstr "дозвіл" + +msgid "permissions" +msgstr "дозволи" + +msgid "group" +msgstr "група" + +msgid "groups" +msgstr "групи" + +msgid "superuser status" +msgstr "статус суперкористувача" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "Визначає, що цей користувач має всі дозволи без їх точного зазначення." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Групи, до яких належить користувач. Користувач отримає всі дозволи, що " +"вказані в кожній з його груп." + +msgid "user permissions" +msgstr "дозволи користувача" + +msgid "Specific permissions for this user." +msgstr "Особливі права доступу для цього користувача." + +msgid "username" +msgstr "ім'я користувача" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"Необхідно: 150 або менше символів. тільки букви, цифри та знаки @/./+/-/_." + +msgid "A user with that username already exists." +msgstr "Користувач з таким ім'ям вже існує." + +msgid "first name" +msgstr "ім'я" + +msgid "last name" +msgstr "прізвище" + +msgid "email address" +msgstr "email адреса" + +msgid "staff status" +msgstr "статус персоналу" + +msgid "Designates whether the user can log into this admin site." +msgstr "Визначає, чи може користувач увійти до цього сайту адміністрування." + +msgid "active" +msgstr "активний" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Визначає, чи можна цього користувача вважати діючим. Заберіть галочку, " +"замість видалення запису користувача." + +msgid "date joined" +msgstr "дата приєднання" + +msgid "user" +msgstr "користувач" + +msgid "users" +msgstr "користувачі" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +"Пароль надто короткий. Він повинен містити як мінімум %(min_length)d символ" +msgstr[1] "" +"Пароль надто короткий. Він повинен містити як мінімум %(min_length)d символи" +msgstr[2] "" +"Пароль надто короткий. Він повинен містити як мінімум %(min_length)d символів" +msgstr[3] "" +"Пароль надто короткий. Він повинен містити як мінімум %(min_length)d символів" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Ваш пароль повинен містити як мінімум %(min_length)d символ" +msgstr[1] "Ваш пароль повинен містити як мінімум %(min_length)d символи" +msgstr[2] "Ваш пароль повинен містити як мінімум %(min_length)d символів" +msgstr[3] "Ваш пароль повинен містити як мінімум %(min_length)d символів" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Пароль надто схожий на %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Пароль не може бути надто схожим на іншу особисту інформацію." + +msgid "This password is too common." +msgstr "Пароль надто відомий." + +msgid "Your password can’t be a commonly used password." +msgstr "Пароль не може бути одним із дуже поширених." + +msgid "This password is entirely numeric." +msgstr "Цей пароль повністю складається із цифр." + +msgid "Your password can’t be entirely numeric." +msgstr "Пароль не може складається лише із цифр." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Скидання пароля на %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "" +"Введіть коректне ім'я користувача. Значення цього поля може складатися лише " +"з малих літер a‒z і великих A‒Z, цифр, а також з символів @/./+/-/_." + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Введіть коректне ім'я користувача. Значення цього поля може складатися лише " +"з літер, цифр, а також з символів: @/./+/-/_." + +msgid "Logged out" +msgstr "Вихід" + +msgid "Password reset" +msgstr "Перевстановлення паролю" + +msgid "Password reset sent" +msgstr "Скидання пароля відправлено" + +msgid "Enter new password" +msgstr "Введіть новий пароль" + +msgid "Password reset unsuccessful" +msgstr "Пароль не перевстановлено" + +msgid "Password reset complete" +msgstr "Пароль перевстановлено" + +msgid "Password change" +msgstr "Зміна паролю" + +msgid "Password change successful" +msgstr "Пароль успішно змінено" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ur/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ur/LC_MESSAGES/django.mo new file mode 100644 index 0000000..cfa37da Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ur/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ur/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ur/LC_MESSAGES/django.po new file mode 100644 index 0000000..241f7b2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/ur/LC_MESSAGES/django.po @@ -0,0 +1,282 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-09-24 13:46+0200\n" +"PO-Revision-Date: 2017-09-24 14:24+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Urdu (http://www.transifex.com/django/django/language/ur/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ur\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Personal info" +msgstr "" + +msgid "Permissions" +msgstr "" + +msgid "Important dates" +msgstr "" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "" + +msgid "Password changed successfully." +msgstr "" + +#, python-format +msgid "Change password: %s" +msgstr "" + +msgid "Authentication and Authorization" +msgstr "" + +msgid "password" +msgstr "" + +msgid "last login" +msgstr "" + +msgid "No password set." +msgstr "" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "" + +msgid "The two password fields didn't match." +msgstr "" + +msgid "Password" +msgstr "لفظ اجازت" + +msgid "Password confirmation" +msgstr "" + +msgid "Enter the same password as before, for verification." +msgstr "" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user's " +"password, but you can change the password using this form." +msgstr "" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" + +msgid "This account is inactive." +msgstr "" + +msgid "Email" +msgstr "" + +msgid "New password" +msgstr "نیا لفظ اجازت" + +msgid "New password confirmation" +msgstr "" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" + +msgid "Old password" +msgstr "پرانا لفظ اجازت" + +msgid "Password (again)" +msgstr "لفظ اجازت (دوبارہ)" + +msgid "algorithm" +msgstr "" + +msgid "iterations" +msgstr "" + +msgid "salt" +msgstr "" + +msgid "hash" +msgstr "" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "" + +msgid "checksum" +msgstr "" + +msgid "name" +msgstr "" + +msgid "content type" +msgstr "" + +msgid "codename" +msgstr "" + +msgid "permission" +msgstr "" + +msgid "permissions" +msgstr "" + +msgid "group" +msgstr "" + +msgid "groups" +msgstr "" + +msgid "superuser status" +msgstr "" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "" + +msgid "Specific permissions for this user." +msgstr "" + +msgid "username" +msgstr "" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "" + +msgid "first name" +msgstr "" + +msgid "last name" +msgstr "" + +msgid "email address" +msgstr "" + +msgid "staff status" +msgstr "" + +msgid "Designates whether the user can log into this admin site." +msgstr "" + +msgid "active" +msgstr "" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" + +msgid "date joined" +msgstr "" + +msgid "user" +msgstr "" + +msgid "users" +msgstr "" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "" + +msgid "Your password can't be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "" + +msgid "Your password can't be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "" + +msgid "Your password can't be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "" + +msgid "Password reset" +msgstr "" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "" + +msgid "Password reset unsuccessful" +msgstr "" + +msgid "Password reset complete" +msgstr "" + +msgid "Password change" +msgstr "" + +msgid "Password change successful" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/uz/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/uz/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f4048ee Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/uz/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/uz/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/uz/LC_MESSAGES/django.po new file mode 100644 index 0000000..24b1b8b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/uz/LC_MESSAGES/django.po @@ -0,0 +1,287 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bedilbek Khamidov , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-12-29 16:31+0000\n" +"Last-Translator: Bedilbek Khamidov \n" +"Language-Team: Uzbek (http://www.transifex.com/django/django/language/uz/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: uz\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Personal info" +msgstr "Shaxsiy ma'lumotlar" + +msgid "Permissions" +msgstr "Ruhsatnomalar" + +msgid "Important dates" +msgstr "Muhim sanalar" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "%(key)r asosiy kalitli %(name)s obyekt mavjud emas" + +msgid "Password changed successfully." +msgstr "Parol muvaffaqiyatli o'zgartirildi." + +#, python-format +msgid "Change password: %s" +msgstr "Parolni o'zgartirish: %s" + +msgid "Authentication and Authorization" +msgstr "Autentifikatsiya va Avtorizatsiya" + +msgid "password" +msgstr "parol" + +msgid "last login" +msgstr "oxirgi kirish" + +msgid "No password set." +msgstr "Hech qanday parol qo'yilmagan." + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Noto'g'ri parol formati yoki noma'lum heshlash algoritmi ishlatilgan." + +msgid "The two password fields didn’t match." +msgstr "Ikkala parol maydoni bir-biriga mos kelmadi." + +msgid "Password" +msgstr "Parol" + +msgid "Password confirmation" +msgstr "Parolni tasdiqlash" + +msgid "Enter the same password as before, for verification." +msgstr "Tekshirish uchun avvalgi parolni kiriting.." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Xom parollar saqlanmaydi, shuning uchun bu foydanaluvchining parolini " +"ko'rishni iloji yo'q, lekin siz shu formadan foydalanib " +"parolni o'zgartirishingiz mumkin. " + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Iltimos, to'g'ri %(username)s va parolni kiriting. Ahamiyat bering, ikkala " +"maydonlar ham katta-kichik harfga sezgir bo'lishi mumkin." + +msgid "This account is inactive." +msgstr "Bu akkaunt nofaol" + +msgid "Email" +msgstr "Elektron pochta" + +msgid "New password" +msgstr "Yangi parol" + +msgid "New password confirmation" +msgstr "Yangi parolni tasdiqlash" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "" +"Sizning eski parolingiz noto'g'ri kiritilgan edi. Iltimos, qaytadan kiriting." + +msgid "Old password" +msgstr "" + +msgid "Password (again)" +msgstr "" + +msgid "algorithm" +msgstr "" + +msgid "iterations" +msgstr "" + +msgid "salt" +msgstr "" + +msgid "hash" +msgstr "" + +msgid "variety" +msgstr "" + +msgid "version" +msgstr "" + +msgid "memory cost" +msgstr "" + +msgid "time cost" +msgstr "" + +msgid "parallelism" +msgstr "" + +msgid "work factor" +msgstr "" + +msgid "checksum" +msgstr "" + +msgid "name" +msgstr "" + +msgid "content type" +msgstr "" + +msgid "codename" +msgstr "" + +msgid "permission" +msgstr "" + +msgid "permissions" +msgstr "" + +msgid "group" +msgstr "" + +msgid "groups" +msgstr "" + +msgid "superuser status" +msgstr "" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" + +msgid "user permissions" +msgstr "" + +msgid "Specific permissions for this user." +msgstr "" + +msgid "username" +msgstr "" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" + +msgid "A user with that username already exists." +msgstr "" + +msgid "first name" +msgstr "" + +msgid "last name" +msgstr "" + +msgid "email address" +msgstr "" + +msgid "staff status" +msgstr "" + +msgid "Designates whether the user can log into this admin site." +msgstr "" + +msgid "active" +msgstr "" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" + +msgid "date joined" +msgstr "" + +msgid "user" +msgstr "" + +msgid "users" +msgstr "" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "" + +msgid "Your password can’t be too similar to your other personal information." +msgstr "" + +msgid "This password is too common." +msgstr "" + +msgid "Your password can’t be a commonly used password." +msgstr "" + +msgid "This password is entirely numeric." +msgstr "" + +msgid "Your password can’t be entirely numeric." +msgstr "" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" + +msgid "Logged out" +msgstr "" + +msgid "Password reset" +msgstr "" + +msgid "Password reset sent" +msgstr "" + +msgid "Enter new password" +msgstr "" + +msgid "Password reset unsuccessful" +msgstr "" + +msgid "Password reset complete" +msgstr "" + +msgid "Password change" +msgstr "" + +msgid "Password change successful" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/vi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/vi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..eb31978 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/vi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/vi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/vi/LC_MESSAGES/django.po new file mode 100644 index 0000000..a6b540a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/vi/LC_MESSAGES/django.po @@ -0,0 +1,305 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Anh Phan , 2013 +# Tran , 2011 +# Tran Van , 2012 +# tinnguyen121221, 2021 +# xgenvn , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-09-21 10:22+0200\n" +"PO-Revision-Date: 2021-12-23 17:49+0000\n" +"Last-Translator: tinnguyen121221\n" +"Language-Team: Vietnamese (http://www.transifex.com/django/django/language/" +"vi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: vi\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Personal info" +msgstr "Thông tin cá nhân" + +msgid "Permissions" +msgstr "Quyền" + +msgid "Important dates" +msgstr "Những ngày quan trọng" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr " Đối tượng %(name)s với khóa chính %(key)r không tồn tại." + +msgid "Password changed successfully." +msgstr "Mật khẩu thay đổi thành công" + +#, python-format +msgid "Change password: %s" +msgstr "Thay đổi mật khẩu: %s" + +msgid "Authentication and Authorization" +msgstr "Xác thực và ủy quyền" + +msgid "password" +msgstr "Mật khẩu" + +msgid "last login" +msgstr "Lần cuối đăng nhập" + +msgid "No password set." +msgstr "Chưa đặt mật khẩu" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "Định dạng của mật khẩu không đúng hoặc thuật toán hash chưa rõ ràng." + +msgid "The two password fields didn’t match." +msgstr "Hai trường mật khẩu không giống nhau." + +msgid "Password" +msgstr "Mật khẩu" + +msgid "Password confirmation" +msgstr "Xác nhận mật khẩu" + +msgid "Enter the same password as before, for verification." +msgstr "Nhập lại mật khẩu để xác nhận." + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"Mật khẩu không được lưu trữ, vì vậy không có cách nào để xem mật khẩu của " +"người dùng, nhưng bạn có thể dùng biểu mẫu này để thay " +"đổi." + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "" +"Vui lòng điền vào %(username)s và mật khẩu chính xác. Chú ý rằng cả hai " +"khung thông tin đều phân biệt chữ hoa và chữ thường." + +msgid "This account is inactive." +msgstr "Tài khoản này chưa được kích hoạt." + +msgid "Email" +msgstr "Email" + +msgid "New password" +msgstr "Mật khẩu mới" + +msgid "New password confirmation" +msgstr "Xác nhận mật khẩu mới" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "Mật khẩu cũ không chính xác. Hãy nhập lại lần nữa" + +msgid "Old password" +msgstr "Mật khẩu cũ" + +msgid "Password (again)" +msgstr "Nhập lại mật khẩu" + +msgid "algorithm" +msgstr "thuật toán" + +msgid "iterations" +msgstr "lặp lại" + +msgid "salt" +msgstr "Mã salt" + +msgid "hash" +msgstr "băm" + +msgid "variety" +msgstr "variety" + +msgid "version" +msgstr "version" + +msgid "memory cost" +msgstr "memory cost" + +msgid "time cost" +msgstr "time cost" + +msgid "parallelism" +msgstr "parallelism" + +msgid "work factor" +msgstr "yếu tố công việc" + +msgid "checksum" +msgstr "kiểm tra" + +msgid "block size" +msgstr "block size" + +msgid "name" +msgstr "Tên" + +msgid "content type" +msgstr "kiểu nội dung" + +msgid "codename" +msgstr "tên mã" + +msgid "permission" +msgstr "cho phép" + +msgid "permissions" +msgstr "cho phép" + +msgid "group" +msgstr "Nhóm" + +msgid "groups" +msgstr "Các nhóm" + +msgid "superuser status" +msgstr "trạng thái superuser" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "" +"Định rằng người dùng này có tất cả các quyền mà không gán cho họ một cách cụ " +"thể." + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "" +"Các nhóm người dùng này thuộc về. Người dùng sẽ nhận được tất cả các quyền " +"được cấp cho mỗi nhóm." + +msgid "user permissions" +msgstr "quyền của người sử dụng" + +msgid "Specific permissions for this user." +msgstr "Quyền hạn cụ thể cho người dùng này." + +msgid "username" +msgstr "Tên đăng nhập" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "Yêu cầu. 150 ký tự hoặc ít hơn. Chỉ là chữ cái, chữ số và @/./+/-/_." + +msgid "A user with that username already exists." +msgstr "Tên đăng nhập đã được sử dụng" + +msgid "first name" +msgstr "Tên" + +msgid "last name" +msgstr "Họ" + +msgid "email address" +msgstr "địa chỉ email" + +msgid "staff status" +msgstr "tình trạng nhân viên" + +msgid "Designates whether the user can log into this admin site." +msgstr "Chỉ định người dùng nào được phép truy cập vào trang admin." + +msgid "active" +msgstr "Kích hoạt" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "" +"Chỉ định xem người dùng này phải được coi là đang hoạt động. Bạn nên bỏ chọn " +"này thay vì xóa tài khoản." + +msgid "date joined" +msgstr "Ngày tham gia" + +msgid "user" +msgstr "Người dùng" + +msgid "users" +msgstr "người sử dụng" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "Mật khẩu quá ngắn. Nó phải chứa ít nhất %(min_length)d ký tự." + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "Mật khẩu của bạn phải chứa ít nhất %(min_length)d ký tự." + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "Mật khẩu quá giống với %(verbose_name)s." + +msgid "Your password can’t be too similar to your other personal information." +msgstr "Mật khẩu của bạn không được quá giống với thông tin cá nhân khác." + +msgid "This password is too common." +msgstr "Mật khẩu này quá phổ biến." + +msgid "Your password can’t be a commonly used password." +msgstr "Mật khẩu của bạn không được là mật khẩu được dùng phổ biến." + +msgid "This password is entirely numeric." +msgstr "Mật khẩu này hoàn toàn là số." + +msgid "Your password can’t be entirely numeric." +msgstr "Mật khẩu của bạn không được hoàn toàn bằng số." + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "Đặt lại mật khẩu trên %(site_name)s" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "" +"Điền tên đăng nhập hợp lệ. Giá trị này chỉ có thể chứa các chữ cái tiếng " +"Anh, số, và các ký tự @/./+/-/_" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"Điền tên đăng nhập hợp lệ. Giá trị này chỉ có thể chứa các chữ cái, số, và " +"các ký tự @/./+/-/_" + +msgid "Logged out" +msgstr "Đã thoát" + +msgid "Password reset" +msgstr "Đặt lại mật khẩu" + +msgid "Password reset sent" +msgstr "Đã gửi hướng dẫn đặt lại mật khẩu" + +msgid "Enter new password" +msgstr "Nhập mật khẩu mới" + +msgid "Password reset unsuccessful" +msgstr "Đặt lại mật khẩu thành công" + +msgid "Password reset complete" +msgstr "Đặt lại mật khẩu hoàn chỉnh" + +msgid "Password change" +msgstr "Thay đổi mật khẩu" + +msgid "Password change successful" +msgstr "Thay đổi mật khẩu thành công" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/zh_Hans/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/zh_Hans/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d4d2485 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/zh_Hans/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/zh_Hans/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/zh_Hans/LC_MESSAGES/django.po new file mode 100644 index 0000000..000822e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/zh_Hans/LC_MESSAGES/django.po @@ -0,0 +1,305 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bo Li , 2020 +# lanbla , 2021 +# David , 2019 +# ausaki , 2017 +# jamin M , 2019 +# Jannis Leidel , 2011 +# Kaiqi Zhu, 2023 +# Kevin Sze , 2012 +# Lele Long , 2011,2015 +# Liping Wang , 2016-2017 +# mozillazg , 2016 +# Lemon Li , 2012-2013 +# Wentao Han , 2020 +# hizyn , 2016 +# ced773123cfad7b4e8b79ca80f736af9, 2011 +# Kevin Sze , 2012 +# 高乐喆 , 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-17 03:19-0500\n" +"PO-Revision-Date: 2023-12-04 08:09+0000\n" +"Last-Translator: Kaiqi Zhu, 2023\n" +"Language-Team: Chinese (China) (http://app.transifex.com/django/django/" +"language/zh_CN/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_CN\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Personal info" +msgstr "个人信息" + +msgid "Permissions" +msgstr "权限" + +msgid "Important dates" +msgstr "重要日期" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "具有主键 %(key)r 的对象 %(name)s 不存在。" + +msgid "Password changed successfully." +msgstr "密码修改成功。" + +#, python-format +msgid "Change password: %s" +msgstr "修改密码:%s" + +msgid "Authentication and Authorization" +msgstr "认证和授权" + +msgid "password" +msgstr "密码" + +msgid "last login" +msgstr "上次登录" + +msgid "No password set." +msgstr "密码未设置。" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "不可用的密码格式或未知的哈希算法。" + +msgid "The two password fields didn’t match." +msgstr "输入的两个密码不一致。" + +msgid "Password" +msgstr "密码" + +msgid "Password confirmation" +msgstr "密码确认" + +msgid "Enter the same password as before, for verification." +msgstr "为了校验,请输入与上面相同的密码。" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"密码原文未存储在系统中,因此无法看到该用户的密码。然而你可以通过这个表单来修改密码。" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "请输入一个正确的%(username)s和密码。注意,两者都区分大小写。" + +msgid "This account is inactive." +msgstr "该帐号未激活。" + +msgid "Email" +msgstr "电子邮件" + +msgid "New password" +msgstr "新密码" + +msgid "New password confirmation" +msgstr "新密码确认" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "你的旧密码不正确。请重新输入。" + +msgid "Old password" +msgstr "旧密码" + +msgid "Password (again)" +msgstr "密码(重复)" + +msgid "algorithm" +msgstr "算法" + +msgid "iterations" +msgstr "迭代次数" + +msgid "salt" +msgstr "盐" + +msgid "hash" +msgstr "哈希" + +msgid "variety" +msgstr "多样性" + +msgid "version" +msgstr "版本" + +msgid "memory cost" +msgstr "内存花销" + +msgid "time cost" +msgstr "时间花销" + +msgid "parallelism" +msgstr "对比" + +msgid "work factor" +msgstr "加密因子" + +msgid "checksum" +msgstr "校验和" + +msgid "block size" +msgstr "块大小" + +msgid "name" +msgstr "名称" + +msgid "content type" +msgstr "内容类型" + +msgid "codename" +msgstr "代码名称" + +msgid "permission" +msgstr "权限" + +msgid "permissions" +msgstr "权限" + +msgid "group" +msgstr "组" + +msgid "groups" +msgstr "组" + +msgid "superuser status" +msgstr "超级用户状态" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "指明该用户缺省拥有所有权限。" + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "该用户归属的组。一个用户将得到其归属的组的所有权限。" + +msgid "user permissions" +msgstr "用户权限" + +msgid "Specific permissions for this user." +msgstr "这个用户的特定权限。" + +msgid "username" +msgstr "用户名" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "" +"必填;长度为150个字符或以下;只能包含字母、数字、特殊字符“@”、“.”、“-”和“_”。" + +msgid "A user with that username already exists." +msgstr "已存在一位使用该名字的用户。" + +msgid "first name" +msgstr "名字" + +msgid "last name" +msgstr "姓氏" + +msgid "email address" +msgstr "电子邮件地址" + +msgid "staff status" +msgstr "工作人员状态" + +msgid "Designates whether the user can log into this admin site." +msgstr "指明用户是否可以登录到这个管理站点。" + +msgid "active" +msgstr "有效" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "指明用户是否被认为是活跃的。以反选代替删除帐号。" + +msgid "date joined" +msgstr "加入日期" + +msgid "user" +msgstr "用户" + +msgid "users" +msgstr "用户" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "密码长度太短。密码必须包含至少 %(min_length)d 个字符。" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "你的密码必须包含至少 %(min_length)d 个字符。" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "密码跟 %(verbose_name)s 太相似了。" + +msgid "Your password can’t be too similar to your other personal information." +msgstr "你的密码不能与你的其他个人信息太相似。" + +msgid "This password is too common." +msgstr "这个密码太常见了。" + +msgid "Your password can’t be a commonly used password." +msgstr "你的密码不能是一个常见密码。" + +msgid "This password is entirely numeric." +msgstr "密码只包含数字。" + +msgid "Your password can’t be entirely numeric." +msgstr "你的密码不能全都是数字。" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "重置 %(site_name)s 的密码" + +msgid "" +"Enter a valid username. This value may contain only unaccented lowercase a-z " +"and uppercase A-Z letters, numbers, and @/./+/-/_ characters." +msgstr "请输入合法的用户名。只能包含小写和大写字母、数字和@/./+/-/_符号。" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "" +"请输入合法的用户名。只能包含英文字母、数字、特殊字符“@”、“.”、“-”和“_”。" + +msgid "Logged out" +msgstr "登出" + +msgid "Password reset" +msgstr "重置密码" + +msgid "Password reset sent" +msgstr "密码重置链接已经发送。" + +msgid "Enter new password" +msgstr "输入新密码" + +msgid "Password reset unsuccessful" +msgstr "密码重置失败" + +msgid "Password reset complete" +msgstr "密码重置完成" + +msgid "Password change" +msgstr "密码更改" + +msgid "Password change successful" +msgstr "密码更改成功" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/zh_Hant/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/zh_Hant/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c127d27 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/zh_Hant/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/zh_Hant/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/zh_Hant/LC_MESSAGES/django.po new file mode 100644 index 0000000..2542623 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/locale/zh_Hant/LC_MESSAGES/django.po @@ -0,0 +1,291 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Chen Chun-Chia , 2015 +# Claude Paroz , 2016 +# ilay , 2012 +# Jannis Leidel , 2011 +# tcc , 2011 +# Tzu-ping Chung , 2016-2017,2019 +# Yeh-Yung , 2013 +# Yeh-Yung , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-09-18 09:03+0000\n" +"Last-Translator: Tzu-ping Chung \n" +"Language-Team: Chinese (Taiwan) (http://www.transifex.com/django/django/" +"language/zh_TW/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_TW\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Personal info" +msgstr "個人資訊" + +msgid "Permissions" +msgstr "權限" + +msgid "Important dates" +msgstr "重要日期" + +#, python-format +msgid "%(name)s object with primary key %(key)r does not exist." +msgstr "主鍵 %(key)r 的 %(name)s 物件不存在。" + +msgid "Password changed successfully." +msgstr "密碼修改成功" + +#, python-format +msgid "Change password: %s" +msgstr "修改密碼: %s" + +msgid "Authentication and Authorization" +msgstr "認證與授權" + +msgid "password" +msgstr "密碼" + +msgid "last login" +msgstr "上次登入" + +msgid "No password set." +msgstr "無設定密碼。" + +msgid "Invalid password format or unknown hashing algorithm." +msgstr "無效的密碼格式或不知名的雜湊演算法。" + +msgid "The two password fields didn’t match." +msgstr "兩個密碼欄位不相符。" + +msgid "Password" +msgstr "密碼" + +msgid "Password confirmation" +msgstr "密碼確認" + +msgid "Enter the same password as before, for verification." +msgstr "為檢查用,請輸入與前面相同的密碼。" + +msgid "" +"Raw passwords are not stored, so there is no way to see this user’s " +"password, but you can change the password using this form." +msgstr "" +"原始密碼尚未儲存,因此無法存取此帳號的密碼,但你可以透過這個表" +"單來變更密碼。" + +#, python-format +msgid "" +"Please enter a correct %(username)s and password. Note that both fields may " +"be case-sensitive." +msgstr "輸入正確的 %(username)s 和密碼。請注意兩者皆區分大小寫。" + +msgid "This account is inactive." +msgstr "這個帳戶未啟用" + +msgid "Email" +msgstr "電子信箱" + +msgid "New password" +msgstr "新密碼" + +msgid "New password confirmation" +msgstr "新密碼確認" + +msgid "Your old password was entered incorrectly. Please enter it again." +msgstr "你的舊密碼不正確。請重新輸入。" + +msgid "Old password" +msgstr "舊密碼" + +msgid "Password (again)" +msgstr "密碼(重複)" + +msgid "algorithm" +msgstr "演算法" + +msgid "iterations" +msgstr "迭代" + +msgid "salt" +msgstr "隨機值" + +msgid "hash" +msgstr "哈希碼" + +msgid "variety" +msgstr "變種" + +msgid "version" +msgstr "版本" + +msgid "memory cost" +msgstr "記憶體用量" + +msgid "time cost" +msgstr "耗時" + +msgid "parallelism" +msgstr "平行性" + +msgid "work factor" +msgstr "作用因素" + +msgid "checksum" +msgstr "校驗" + +msgid "name" +msgstr "名稱" + +msgid "content type" +msgstr "內容類型" + +msgid "codename" +msgstr "代碼" + +msgid "permission" +msgstr "權限" + +msgid "permissions" +msgstr "權限" + +msgid "group" +msgstr "群組" + +msgid "groups" +msgstr "群組" + +msgid "superuser status" +msgstr "超級使用者狀態" + +msgid "" +"Designates that this user has all permissions without explicitly assigning " +"them." +msgstr "指定是否使用者可以登入到這個管理網站" + +msgid "" +"The groups this user belongs to. A user will get all permissions granted to " +"each of their groups." +msgstr "此為帳號可加入的群組。其所屬的群組將授予該帳號對應的權限。" + +msgid "user permissions" +msgstr "使用者權限" + +msgid "Specific permissions for this user." +msgstr "本使用者的專屬權限。" + +msgid "username" +msgstr "使用者名稱" + +msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." +msgstr "必要的。150 個字或更少,只包含字母、數字和 @/./+/-/_。" + +msgid "A user with that username already exists." +msgstr "一個相同名稱的使用者已經存在。" + +msgid "first name" +msgstr "名字" + +msgid "last name" +msgstr "姓氏" + +msgid "email address" +msgstr "電子信箱" + +msgid "staff status" +msgstr "工作人員狀態" + +msgid "Designates whether the user can log into this admin site." +msgstr "指定是否使用者可以登入此管理網站。" + +msgid "active" +msgstr "有效" + +msgid "" +"Designates whether this user should be treated as active. Unselect this " +"instead of deleting accounts." +msgstr "指定使用者是否有效。請取消選擇而不是刪除帳號。" + +msgid "date joined" +msgstr "加入日期" + +msgid "user" +msgstr "使用者" + +msgid "users" +msgstr "使用者" + +#, python-format +msgid "" +"This password is too short. It must contain at least %(min_length)d " +"character." +msgid_plural "" +"This password is too short. It must contain at least %(min_length)d " +"characters." +msgstr[0] "這個密碼過短。請至少使用 %(min_length)d 個字元。" + +#, python-format +msgid "Your password must contain at least %(min_length)d character." +msgid_plural "Your password must contain at least %(min_length)d characters." +msgstr[0] "你的密碼必須包含至少 %(min_length)d 個字元。" + +#, python-format +msgid "The password is too similar to the %(verbose_name)s." +msgstr "這個密碼與%(verbose_name)s太相近。" + +msgid "Your password can’t be too similar to your other personal information." +msgstr "你的密碼不能與其他個人資訊太相近。" + +msgid "This password is too common." +msgstr "這個密碼太普通。" + +msgid "Your password can’t be a commonly used password." +msgstr "你不能使用常見的密碼。" + +msgid "This password is entirely numeric." +msgstr "這個密碼只包含數字。" + +msgid "Your password can’t be entirely numeric." +msgstr "你的密碼不能完全是數字。" + +#, python-format +msgid "Password reset on %(site_name)s" +msgstr "在 %(site_name)s 進行密碼重置" + +msgid "" +"Enter a valid username. This value may contain only English letters, " +"numbers, and @/./+/-/_ characters." +msgstr "輸入合法的使用者名稱。只能包含英語字母、數字和 @/./+/-/_ 字元。" + +msgid "" +"Enter a valid username. This value may contain only letters, numbers, and " +"@/./+/-/_ characters." +msgstr "輸入合法的使用者名稱。只能包含字母、數字和 @/./+/-/_ 字元。" + +msgid "Logged out" +msgstr "登出" + +msgid "Password reset" +msgstr "密碼重設" + +msgid "Password reset sent" +msgstr "已送出密碼重設" + +msgid "Enter new password" +msgstr "輸入新的密碼" + +msgid "Password reset unsuccessful" +msgstr "密碼重設失敗" + +msgid "Password reset complete" +msgstr "密碼重設成功" + +msgid "Password change" +msgstr "變更密碼" + +msgid "Password change successful" +msgstr "成功變更密碼" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/management/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/management/__init__.py new file mode 100644 index 0000000..ad31a6e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/management/__init__.py @@ -0,0 +1,175 @@ +""" +Creates permissions for all installed apps that need permissions. +""" +import getpass +import unicodedata + +from django.apps import apps as global_apps +from django.contrib.auth import get_permission_codename +from django.contrib.contenttypes.management import create_contenttypes +from django.core import exceptions +from django.db import DEFAULT_DB_ALIAS, router + + +def _get_all_permissions(opts): + """ + Return (codename, name) for all permissions in the given opts. + """ + return [*_get_builtin_permissions(opts), *opts.permissions] + + +def _get_builtin_permissions(opts): + """ + Return (codename, name) for all autogenerated permissions. + By default, this is ('add', 'change', 'delete', 'view') + """ + perms = [] + for action in opts.default_permissions: + perms.append( + ( + get_permission_codename(action, opts), + "Can %s %s" % (action, opts.verbose_name_raw), + ) + ) + return perms + + +def create_permissions( + app_config, + verbosity=2, + interactive=True, + using=DEFAULT_DB_ALIAS, + apps=global_apps, + **kwargs, +): + if not app_config.models_module: + return + + # Ensure that contenttypes are created for this app. Needed if + # 'django.contrib.auth' is in INSTALLED_APPS before + # 'django.contrib.contenttypes'. + create_contenttypes( + app_config, + verbosity=verbosity, + interactive=interactive, + using=using, + apps=apps, + **kwargs, + ) + + app_label = app_config.label + try: + app_config = apps.get_app_config(app_label) + ContentType = apps.get_model("contenttypes", "ContentType") + Permission = apps.get_model("auth", "Permission") + except LookupError: + return + + if not router.allow_migrate_model(using, Permission): + return + + # This will hold the permissions we're looking for as + # (content_type, (codename, name)) + searched_perms = [] + # The codenames and ctypes that should exist. + ctypes = set() + for klass in app_config.get_models(): + # Force looking up the content types in the current database + # before creating foreign keys to them. + ctype = ContentType.objects.db_manager(using).get_for_model( + klass, for_concrete_model=False + ) + + ctypes.add(ctype) + for perm in _get_all_permissions(klass._meta): + searched_perms.append((ctype, perm)) + + # Find all the Permissions that have a content_type for a model we're + # looking for. We don't need to check for codenames since we already have + # a list of the ones we're going to create. + all_perms = set( + Permission.objects.using(using) + .filter( + content_type__in=ctypes, + ) + .values_list("content_type", "codename") + ) + + perms = [] + for ct, (codename, name) in searched_perms: + if (ct.pk, codename) not in all_perms: + permission = Permission() + permission._state.db = using + permission.codename = codename + permission.name = name + permission.content_type = ct + perms.append(permission) + + Permission.objects.using(using).bulk_create(perms) + if verbosity >= 2: + for perm in perms: + print("Adding permission '%s'" % perm) + + +def get_system_username(): + """ + Return the current system user's username, or an empty string if the + username could not be determined. + """ + try: + result = getpass.getuser() + except (ImportError, KeyError): + # KeyError will be raised by os.getpwuid() (called by getuser()) + # if there is no corresponding entry in the /etc/passwd file + # (a very restricted chroot environment, for example). + return "" + return result + + +def get_default_username(check_db=True, database=DEFAULT_DB_ALIAS): + """ + Try to determine the current system user's username to use as a default. + + :param check_db: If ``True``, requires that the username does not match an + existing ``auth.User`` (otherwise returns an empty string). + :param database: The database where the unique check will be performed. + :returns: The username, or an empty string if no username can be + determined or the suggested username is already taken. + """ + # This file is used in apps.py, it should not trigger models import. + from django.contrib.auth import models as auth_app + + # If the User model has been swapped out, we can't make any assumptions + # about the default user name. + if auth_app.User._meta.swapped: + return "" + + default_username = get_system_username() + try: + default_username = ( + unicodedata.normalize("NFKD", default_username) + .encode("ascii", "ignore") + .decode("ascii") + .replace(" ", "") + .lower() + ) + except UnicodeDecodeError: + return "" + + # Run the username validator + try: + auth_app.User._meta.get_field("username").run_validators(default_username) + except exceptions.ValidationError: + return "" + + # Don't return the default username if it is already taken. + if check_db and default_username: + try: + auth_app.User._default_manager.db_manager(database).get( + username=default_username, + ) + except auth_app.User.DoesNotExist: + pass + else: + return "" + return default_username diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/management/commands/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/management/commands/changepassword.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/management/commands/changepassword.py new file mode 100644 index 0000000..669d8cf --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/management/commands/changepassword.py @@ -0,0 +1,81 @@ +import getpass + +from django.contrib.auth import get_user_model +from django.contrib.auth.password_validation import validate_password +from django.core.exceptions import ValidationError +from django.core.management.base import BaseCommand, CommandError +from django.db import DEFAULT_DB_ALIAS + +UserModel = get_user_model() + + +class Command(BaseCommand): + help = "Change a user's password for django.contrib.auth." + requires_migrations_checks = True + requires_system_checks = [] + + def _get_pass(self, prompt="Password: "): + p = getpass.getpass(prompt=prompt) + if not p: + raise CommandError("aborted") + return p + + def add_arguments(self, parser): + parser.add_argument( + "username", + nargs="?", + help=( + "Username to change password for; by default, it's the current " + "username." + ), + ) + parser.add_argument( + "--database", + default=DEFAULT_DB_ALIAS, + help='Specifies the database to use. Default is "default".', + ) + + def handle(self, *args, **options): + if options["username"]: + username = options["username"] + else: + username = getpass.getuser() + + try: + u = UserModel._default_manager.using(options["database"]).get( + **{UserModel.USERNAME_FIELD: username} + ) + except UserModel.DoesNotExist: + raise CommandError("user '%s' does not exist" % username) + + self.stdout.write("Changing password for user '%s'" % u) + + MAX_TRIES = 3 + count = 0 + p1, p2 = 1, 2 # To make them initially mismatch. + password_validated = False + while (p1 != p2 or not password_validated) and count < MAX_TRIES: + p1 = self._get_pass() + p2 = self._get_pass("Password (again): ") + if p1 != p2: + self.stdout.write("Passwords do not match. Please try again.") + count += 1 + # Don't validate passwords that don't match. + continue + try: + validate_password(p2, u) + except ValidationError as err: + self.stderr.write("\n".join(err.messages)) + count += 1 + else: + password_validated = True + + if count == MAX_TRIES: + raise CommandError( + "Aborting password change for user '%s' after %s attempts" % (u, count) + ) + + u.set_password(p1) + u.save() + + return "Password changed successfully for user '%s'" % u diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/management/commands/createsuperuser.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/management/commands/createsuperuser.py new file mode 100644 index 0000000..6d650cc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/management/commands/createsuperuser.py @@ -0,0 +1,311 @@ +""" +Management utility to create superusers. +""" +import getpass +import os +import sys + +from django.contrib.auth import get_user_model +from django.contrib.auth.management import get_default_username +from django.contrib.auth.password_validation import validate_password +from django.core import exceptions +from django.core.management.base import BaseCommand, CommandError +from django.db import DEFAULT_DB_ALIAS +from django.utils.functional import cached_property +from django.utils.text import capfirst + + +class NotRunningInTTYException(Exception): + pass + + +PASSWORD_FIELD = "password" + + +class Command(BaseCommand): + help = "Used to create a superuser." + requires_migrations_checks = True + stealth_options = ("stdin",) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.UserModel = get_user_model() + self.username_field = self.UserModel._meta.get_field( + self.UserModel.USERNAME_FIELD + ) + + def add_arguments(self, parser): + parser.add_argument( + "--%s" % self.UserModel.USERNAME_FIELD, + help="Specifies the login for the superuser.", + ) + parser.add_argument( + "--noinput", + "--no-input", + action="store_false", + dest="interactive", + help=( + "Tells Django to NOT prompt the user for input of any kind. " + "You must use --%s with --noinput, along with an option for " + "any other required field. Superusers created with --noinput will " + "not be able to log in until they're given a valid password." + % self.UserModel.USERNAME_FIELD + ), + ) + parser.add_argument( + "--database", + default=DEFAULT_DB_ALIAS, + help='Specifies the database to use. Default is "default".', + ) + for field_name in self.UserModel.REQUIRED_FIELDS: + field = self.UserModel._meta.get_field(field_name) + if field.many_to_many: + if ( + field.remote_field.through + and not field.remote_field.through._meta.auto_created + ): + raise CommandError( + "Required field '%s' specifies a many-to-many " + "relation through model, which is not supported." % field_name + ) + else: + parser.add_argument( + "--%s" % field_name, + action="append", + help=( + "Specifies the %s for the superuser. Can be used " + "multiple times." % field_name, + ), + ) + else: + parser.add_argument( + "--%s" % field_name, + help="Specifies the %s for the superuser." % field_name, + ) + + def execute(self, *args, **options): + self.stdin = options.get("stdin", sys.stdin) # Used for testing + return super().execute(*args, **options) + + def handle(self, *args, **options): + username = options[self.UserModel.USERNAME_FIELD] + database = options["database"] + user_data = {} + verbose_field_name = self.username_field.verbose_name + try: + self.UserModel._meta.get_field(PASSWORD_FIELD) + except exceptions.FieldDoesNotExist: + pass + else: + # If not provided, create the user with an unusable password. + user_data[PASSWORD_FIELD] = None + try: + if options["interactive"]: + # Same as user_data but without many to many fields and with + # foreign keys as fake model instances instead of raw IDs. + fake_user_data = {} + if hasattr(self.stdin, "isatty") and not self.stdin.isatty(): + raise NotRunningInTTYException + default_username = get_default_username(database=database) + if username: + error_msg = self._validate_username( + username, verbose_field_name, database + ) + if error_msg: + self.stderr.write(error_msg) + username = None + elif username == "": + raise CommandError( + "%s cannot be blank." % capfirst(verbose_field_name) + ) + # Prompt for username. + while username is None: + message = self._get_input_message( + self.username_field, default_username + ) + username = self.get_input_data( + self.username_field, message, default_username + ) + if username: + error_msg = self._validate_username( + username, verbose_field_name, database + ) + if error_msg: + self.stderr.write(error_msg) + username = None + continue + user_data[self.UserModel.USERNAME_FIELD] = username + fake_user_data[self.UserModel.USERNAME_FIELD] = ( + self.username_field.remote_field.model(username) + if self.username_field.remote_field + else username + ) + # Prompt for required fields. + for field_name in self.UserModel.REQUIRED_FIELDS: + field = self.UserModel._meta.get_field(field_name) + user_data[field_name] = options[field_name] + if user_data[field_name] is not None: + user_data[field_name] = field.clean(user_data[field_name], None) + while user_data[field_name] is None: + message = self._get_input_message(field) + input_value = self.get_input_data(field, message) + user_data[field_name] = input_value + if field.many_to_many and input_value: + if not input_value.strip(): + user_data[field_name] = None + self.stderr.write("Error: This field cannot be blank.") + continue + user_data[field_name] = [ + pk.strip() for pk in input_value.split(",") + ] + + if not field.many_to_many: + fake_user_data[field_name] = user_data[field_name] + # Wrap any foreign keys in fake model instances. + if field.many_to_one: + fake_user_data[field_name] = field.remote_field.model( + user_data[field_name] + ) + + # Prompt for a password if the model has one. + while PASSWORD_FIELD in user_data and user_data[PASSWORD_FIELD] is None: + password = getpass.getpass() + password2 = getpass.getpass("Password (again): ") + if password != password2: + self.stderr.write("Error: Your passwords didn't match.") + # Don't validate passwords that don't match. + continue + if password.strip() == "": + self.stderr.write("Error: Blank passwords aren't allowed.") + # Don't validate blank passwords. + continue + try: + validate_password(password2, self.UserModel(**fake_user_data)) + except exceptions.ValidationError as err: + self.stderr.write("\n".join(err.messages)) + response = input( + "Bypass password validation and create user anyway? [y/N]: " + ) + if response.lower() != "y": + continue + user_data[PASSWORD_FIELD] = password + else: + # Non-interactive mode. + # Use password from environment variable, if provided. + if ( + PASSWORD_FIELD in user_data + and "DJANGO_SUPERUSER_PASSWORD" in os.environ + ): + user_data[PASSWORD_FIELD] = os.environ["DJANGO_SUPERUSER_PASSWORD"] + # Use username from environment variable, if not provided in + # options. + if username is None: + username = os.environ.get( + "DJANGO_SUPERUSER_" + self.UserModel.USERNAME_FIELD.upper() + ) + if username is None: + raise CommandError( + "You must use --%s with --noinput." + % self.UserModel.USERNAME_FIELD + ) + else: + error_msg = self._validate_username( + username, verbose_field_name, database + ) + if error_msg: + raise CommandError(error_msg) + + user_data[self.UserModel.USERNAME_FIELD] = username + for field_name in self.UserModel.REQUIRED_FIELDS: + env_var = "DJANGO_SUPERUSER_" + field_name.upper() + value = options[field_name] or os.environ.get(env_var) + field = self.UserModel._meta.get_field(field_name) + if not value: + if field.blank and ( + options[field_name] == "" or os.environ.get(env_var) == "" + ): + continue + raise CommandError( + "You must use --%s with --noinput." % field_name + ) + user_data[field_name] = field.clean(value, None) + if field.many_to_many and isinstance(user_data[field_name], str): + user_data[field_name] = [ + pk.strip() for pk in user_data[field_name].split(",") + ] + + self.UserModel._default_manager.db_manager(database).create_superuser( + **user_data + ) + if options["verbosity"] >= 1: + self.stdout.write("Superuser created successfully.") + except KeyboardInterrupt: + self.stderr.write("\nOperation cancelled.") + sys.exit(1) + except exceptions.ValidationError as e: + raise CommandError("; ".join(e.messages)) + except NotRunningInTTYException: + self.stdout.write( + "Superuser creation skipped due to not running in a TTY. " + "You can run `manage.py createsuperuser` in your project " + "to create one manually." + ) + + def get_input_data(self, field, message, default=None): + """ + Override this method if you want to customize data inputs or + validation exceptions. + """ + raw_value = input(message) + if default and raw_value == "": + raw_value = default + try: + val = field.clean(raw_value, None) + except exceptions.ValidationError as e: + self.stderr.write("Error: %s" % "; ".join(e.messages)) + val = None + + return val + + def _get_input_message(self, field, default=None): + return "%s%s%s: " % ( + capfirst(field.verbose_name), + " (leave blank to use '%s')" % default if default else "", + " (%s.%s)" + % ( + field.remote_field.model._meta.object_name, + field.m2m_target_field_name() + if field.many_to_many + else field.remote_field.field_name, + ) + if field.remote_field + else "", + ) + + @cached_property + def username_is_unique(self): + if self.username_field.unique: + return True + return any( + len(unique_constraint.fields) == 1 + and unique_constraint.fields[0] == self.username_field.name + for unique_constraint in self.UserModel._meta.total_unique_constraints + ) + + def _validate_username(self, username, verbose_field_name, database): + """Validate username. If invalid, return a string error message.""" + if self.username_is_unique: + try: + self.UserModel._default_manager.db_manager(database).get_by_natural_key( + username + ) + except self.UserModel.DoesNotExist: + pass + else: + return "Error: That %s is already taken." % verbose_field_name + if not username: + return "%s cannot be blank." % capfirst(verbose_field_name) + try: + self.username_field.clean(username, None) + except exceptions.ValidationError as e: + return "; ".join(e.messages) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/middleware.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/middleware.py new file mode 100644 index 0000000..6b8dd43 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/middleware.py @@ -0,0 +1,137 @@ +from functools import partial + +from django.contrib import auth +from django.contrib.auth import load_backend +from django.contrib.auth.backends import RemoteUserBackend +from django.core.exceptions import ImproperlyConfigured +from django.utils.deprecation import MiddlewareMixin +from django.utils.functional import SimpleLazyObject + + +def get_user(request): + if not hasattr(request, "_cached_user"): + request._cached_user = auth.get_user(request) + return request._cached_user + + +async def auser(request): + if not hasattr(request, "_acached_user"): + request._acached_user = await auth.aget_user(request) + return request._acached_user + + +class AuthenticationMiddleware(MiddlewareMixin): + def process_request(self, request): + if not hasattr(request, "session"): + raise ImproperlyConfigured( + "The Django authentication middleware requires session " + "middleware to be installed. Edit your MIDDLEWARE setting to " + "insert " + "'django.contrib.sessions.middleware.SessionMiddleware' before " + "'django.contrib.auth.middleware.AuthenticationMiddleware'." + ) + request.user = SimpleLazyObject(lambda: get_user(request)) + request.auser = partial(auser, request) + + +class RemoteUserMiddleware(MiddlewareMixin): + """ + Middleware for utilizing web-server-provided authentication. + + If request.user is not authenticated, then this middleware attempts to + authenticate the username passed in the ``REMOTE_USER`` request header. + If authentication is successful, the user is automatically logged in to + persist the user in the session. + + The header used is configurable and defaults to ``REMOTE_USER``. Subclass + this class and change the ``header`` attribute if you need to use a + different header. + """ + + # Name of request header to grab username from. This will be the key as + # used in the request.META dictionary, i.e. the normalization of headers to + # all uppercase and the addition of "HTTP_" prefix apply. + header = "REMOTE_USER" + force_logout_if_no_header = True + + def process_request(self, request): + # AuthenticationMiddleware is required so that request.user exists. + if not hasattr(request, "user"): + raise ImproperlyConfigured( + "The Django remote user auth middleware requires the" + " authentication middleware to be installed. Edit your" + " MIDDLEWARE setting to insert" + " 'django.contrib.auth.middleware.AuthenticationMiddleware'" + " before the RemoteUserMiddleware class." + ) + try: + username = request.META[self.header] + except KeyError: + # If specified header doesn't exist then remove any existing + # authenticated remote-user, or return (leaving request.user set to + # AnonymousUser by the AuthenticationMiddleware). + if self.force_logout_if_no_header and request.user.is_authenticated: + self._remove_invalid_user(request) + return + # If the user is already authenticated and that user is the user we are + # getting passed in the headers, then the correct user is already + # persisted in the session and we don't need to continue. + if request.user.is_authenticated: + if request.user.get_username() == self.clean_username(username, request): + return + else: + # An authenticated user is associated with the request, but + # it does not match the authorized user in the header. + self._remove_invalid_user(request) + + # We are seeing this user for the first time in this session, attempt + # to authenticate the user. + user = auth.authenticate(request, remote_user=username) + if user: + # User is valid. Set request.user and persist user in the session + # by logging the user in. + request.user = user + auth.login(request, user) + + def clean_username(self, username, request): + """ + Allow the backend to clean the username, if the backend defines a + clean_username method. + """ + backend_str = request.session[auth.BACKEND_SESSION_KEY] + backend = auth.load_backend(backend_str) + try: + username = backend.clean_username(username) + except AttributeError: # Backend has no clean_username method. + pass + return username + + def _remove_invalid_user(self, request): + """ + Remove the current authenticated user in the request which is invalid + but only if the user is authenticated via the RemoteUserBackend. + """ + try: + stored_backend = load_backend( + request.session.get(auth.BACKEND_SESSION_KEY, "") + ) + except ImportError: + # backend failed to load + auth.logout(request) + else: + if isinstance(stored_backend, RemoteUserBackend): + auth.logout(request) + + +class PersistentRemoteUserMiddleware(RemoteUserMiddleware): + """ + Middleware for web-server provided authentication on logon pages. + + Like RemoteUserMiddleware but keeps the user authenticated even if + the header (``REMOTE_USER``) is not found in the request. Useful + for setups when the external authentication via ``REMOTE_USER`` + is only expected to happen on some "logon" URL and the rest of + the application wants to use Django's authentication mechanism. + """ + + force_logout_if_no_header = False diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0001_initial.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0001_initial.py new file mode 100644 index 0000000..cfeaa3a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0001_initial.py @@ -0,0 +1,204 @@ +import django.contrib.auth.models +from django.contrib.auth import validators +from django.db import migrations, models +from django.utils import timezone + + +class Migration(migrations.Migration): + dependencies = [ + ("contenttypes", "__first__"), + ] + + operations = [ + migrations.CreateModel( + name="Permission", + fields=[ + ( + "id", + models.AutoField( + verbose_name="ID", + serialize=False, + auto_created=True, + primary_key=True, + ), + ), + ("name", models.CharField(max_length=50, verbose_name="name")), + ( + "content_type", + models.ForeignKey( + to="contenttypes.ContentType", + on_delete=models.CASCADE, + verbose_name="content type", + ), + ), + ("codename", models.CharField(max_length=100, verbose_name="codename")), + ], + options={ + "ordering": [ + "content_type__app_label", + "content_type__model", + "codename", + ], + "unique_together": {("content_type", "codename")}, + "verbose_name": "permission", + "verbose_name_plural": "permissions", + }, + managers=[ + ("objects", django.contrib.auth.models.PermissionManager()), + ], + ), + migrations.CreateModel( + name="Group", + fields=[ + ( + "id", + models.AutoField( + verbose_name="ID", + serialize=False, + auto_created=True, + primary_key=True, + ), + ), + ( + "name", + models.CharField(unique=True, max_length=80, verbose_name="name"), + ), + ( + "permissions", + models.ManyToManyField( + to="auth.Permission", verbose_name="permissions", blank=True + ), + ), + ], + options={ + "verbose_name": "group", + "verbose_name_plural": "groups", + }, + managers=[ + ("objects", django.contrib.auth.models.GroupManager()), + ], + ), + migrations.CreateModel( + name="User", + fields=[ + ( + "id", + models.AutoField( + verbose_name="ID", + serialize=False, + auto_created=True, + primary_key=True, + ), + ), + ("password", models.CharField(max_length=128, verbose_name="password")), + ( + "last_login", + models.DateTimeField( + default=timezone.now, verbose_name="last login" + ), + ), + ( + "is_superuser", + models.BooleanField( + default=False, + help_text=( + "Designates that this user has all permissions without " + "explicitly assigning them." + ), + verbose_name="superuser status", + ), + ), + ( + "username", + models.CharField( + help_text=( + "Required. 30 characters or fewer. Letters, digits and " + "@/./+/-/_ only." + ), + unique=True, + max_length=30, + verbose_name="username", + validators=[validators.UnicodeUsernameValidator()], + ), + ), + ( + "first_name", + models.CharField( + max_length=30, verbose_name="first name", blank=True + ), + ), + ( + "last_name", + models.CharField( + max_length=30, verbose_name="last name", blank=True + ), + ), + ( + "email", + models.EmailField( + max_length=75, verbose_name="email address", blank=True + ), + ), + ( + "is_staff", + models.BooleanField( + default=False, + help_text=( + "Designates whether the user can log into this admin site." + ), + verbose_name="staff status", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + verbose_name="active", + help_text=( + "Designates whether this user should be treated as active. " + "Unselect this instead of deleting accounts." + ), + ), + ), + ( + "date_joined", + models.DateTimeField( + default=timezone.now, verbose_name="date joined" + ), + ), + ( + "groups", + models.ManyToManyField( + to="auth.Group", + verbose_name="groups", + blank=True, + related_name="user_set", + related_query_name="user", + help_text=( + "The groups this user belongs to. A user will get all " + "permissions granted to each of their groups." + ), + ), + ), + ( + "user_permissions", + models.ManyToManyField( + to="auth.Permission", + verbose_name="user permissions", + blank=True, + help_text="Specific permissions for this user.", + related_name="user_set", + related_query_name="user", + ), + ), + ], + options={ + "swappable": "AUTH_USER_MODEL", + "verbose_name": "user", + "verbose_name_plural": "users", + }, + managers=[ + ("objects", django.contrib.auth.models.UserManager()), + ], + ), + ] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0002_alter_permission_name_max_length.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0002_alter_permission_name_max_length.py new file mode 100644 index 0000000..67a9560 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0002_alter_permission_name_max_length.py @@ -0,0 +1,15 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("auth", "0001_initial"), + ] + + operations = [ + migrations.AlterField( + model_name="permission", + name="name", + field=models.CharField(max_length=255, verbose_name="name"), + ), + ] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0003_alter_user_email_max_length.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0003_alter_user_email_max_length.py new file mode 100644 index 0000000..13d437e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0003_alter_user_email_max_length.py @@ -0,0 +1,17 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("auth", "0002_alter_permission_name_max_length"), + ] + + operations = [ + migrations.AlterField( + model_name="user", + name="email", + field=models.EmailField( + max_length=254, verbose_name="email address", blank=True + ), + ), + ] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0004_alter_user_username_opts.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0004_alter_user_username_opts.py new file mode 100644 index 0000000..f3fe36a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0004_alter_user_username_opts.py @@ -0,0 +1,27 @@ +from django.contrib.auth import validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("auth", "0003_alter_user_email_max_length"), + ] + + # No database changes; modifies validators and error_messages (#13147). + operations = [ + migrations.AlterField( + model_name="user", + name="username", + field=models.CharField( + error_messages={"unique": "A user with that username already exists."}, + max_length=30, + validators=[validators.UnicodeUsernameValidator()], + help_text=( + "Required. 30 characters or fewer. Letters, digits and @/./+/-/_ " + "only." + ), + unique=True, + verbose_name="username", + ), + ), + ] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0005_alter_user_last_login_null.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0005_alter_user_last_login_null.py new file mode 100644 index 0000000..42b584e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0005_alter_user_last_login_null.py @@ -0,0 +1,17 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("auth", "0004_alter_user_username_opts"), + ] + + operations = [ + migrations.AlterField( + model_name="user", + name="last_login", + field=models.DateTimeField( + null=True, verbose_name="last login", blank=True + ), + ), + ] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0006_require_contenttypes_0002.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0006_require_contenttypes_0002.py new file mode 100644 index 0000000..2032c11 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0006_require_contenttypes_0002.py @@ -0,0 +1,13 @@ +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("auth", "0005_alter_user_last_login_null"), + ("contenttypes", "0002_remove_content_type_name"), + ] + + operations = [ + # Ensure the contenttypes migration is applied before sending + # post_migrate signals (which create ContentTypes). + ] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0007_alter_validators_add_error_messages.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0007_alter_validators_add_error_messages.py new file mode 100644 index 0000000..ca01080 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0007_alter_validators_add_error_messages.py @@ -0,0 +1,26 @@ +from django.contrib.auth import validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("auth", "0006_require_contenttypes_0002"), + ] + + operations = [ + migrations.AlterField( + model_name="user", + name="username", + field=models.CharField( + error_messages={"unique": "A user with that username already exists."}, + help_text=( + "Required. 30 characters or fewer. Letters, digits and @/./+/-/_ " + "only." + ), + max_length=30, + unique=True, + validators=[validators.UnicodeUsernameValidator()], + verbose_name="username", + ), + ), + ] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0008_alter_user_username_max_length.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0008_alter_user_username_max_length.py new file mode 100644 index 0000000..caac0f1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0008_alter_user_username_max_length.py @@ -0,0 +1,26 @@ +from django.contrib.auth import validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("auth", "0007_alter_validators_add_error_messages"), + ] + + operations = [ + migrations.AlterField( + model_name="user", + name="username", + field=models.CharField( + error_messages={"unique": "A user with that username already exists."}, + help_text=( + "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ " + "only." + ), + max_length=150, + unique=True, + validators=[validators.UnicodeUsernameValidator()], + verbose_name="username", + ), + ), + ] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0009_alter_user_last_name_max_length.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0009_alter_user_last_name_max_length.py new file mode 100644 index 0000000..d347829 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0009_alter_user_last_name_max_length.py @@ -0,0 +1,17 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("auth", "0008_alter_user_username_max_length"), + ] + + operations = [ + migrations.AlterField( + model_name="user", + name="last_name", + field=models.CharField( + blank=True, max_length=150, verbose_name="last name" + ), + ), + ] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0010_alter_group_name_max_length.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0010_alter_group_name_max_length.py new file mode 100644 index 0000000..8ba2744 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0010_alter_group_name_max_length.py @@ -0,0 +1,15 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("auth", "0009_alter_user_last_name_max_length"), + ] + + operations = [ + migrations.AlterField( + model_name="group", + name="name", + field=models.CharField(max_length=150, unique=True, verbose_name="name"), + ), + ] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0011_update_proxy_permissions.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0011_update_proxy_permissions.py new file mode 100644 index 0000000..aa6ddd5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0011_update_proxy_permissions.py @@ -0,0 +1,76 @@ +import sys + +from django.core.management.color import color_style +from django.db import IntegrityError, migrations, transaction +from django.db.models import Q + +WARNING = """ + A problem arose migrating proxy model permissions for {old} to {new}. + + Permission(s) for {new} already existed. + Codenames Q: {query} + + Ensure to audit ALL permissions for {old} and {new}. +""" + + +def update_proxy_model_permissions(apps, schema_editor, reverse=False): + """ + Update the content_type of proxy model permissions to use the ContentType + of the proxy model. + """ + style = color_style() + Permission = apps.get_model("auth", "Permission") + ContentType = apps.get_model("contenttypes", "ContentType") + alias = schema_editor.connection.alias + for Model in apps.get_models(): + opts = Model._meta + if not opts.proxy: + continue + proxy_default_permissions_codenames = [ + "%s_%s" % (action, opts.model_name) for action in opts.default_permissions + ] + permissions_query = Q(codename__in=proxy_default_permissions_codenames) + for codename, name in opts.permissions: + permissions_query |= Q(codename=codename, name=name) + content_type_manager = ContentType.objects.db_manager(alias) + concrete_content_type = content_type_manager.get_for_model( + Model, for_concrete_model=True + ) + proxy_content_type = content_type_manager.get_for_model( + Model, for_concrete_model=False + ) + old_content_type = proxy_content_type if reverse else concrete_content_type + new_content_type = concrete_content_type if reverse else proxy_content_type + try: + with transaction.atomic(using=alias): + Permission.objects.using(alias).filter( + permissions_query, + content_type=old_content_type, + ).update(content_type=new_content_type) + except IntegrityError: + old = "{}_{}".format(old_content_type.app_label, old_content_type.model) + new = "{}_{}".format(new_content_type.app_label, new_content_type.model) + sys.stdout.write( + style.WARNING(WARNING.format(old=old, new=new, query=permissions_query)) + ) + + +def revert_proxy_model_permissions(apps, schema_editor): + """ + Update the content_type of proxy model permissions to use the ContentType + of the concrete model. + """ + update_proxy_model_permissions(apps, schema_editor, reverse=True) + + +class Migration(migrations.Migration): + dependencies = [ + ("auth", "0010_alter_group_name_max_length"), + ("contenttypes", "0002_remove_content_type_name"), + ] + operations = [ + migrations.RunPython( + update_proxy_model_permissions, revert_proxy_model_permissions + ), + ] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0012_alter_user_first_name_max_length.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0012_alter_user_first_name_max_length.py new file mode 100644 index 0000000..1014f20 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/0012_alter_user_first_name_max_length.py @@ -0,0 +1,17 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("auth", "0011_update_proxy_permissions"), + ] + + operations = [ + migrations.AlterField( + model_name="user", + name="first_name", + field=models.CharField( + blank=True, max_length=150, verbose_name="first name" + ), + ), + ] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/mixins.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/mixins.py new file mode 100644 index 0000000..0e46000 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/mixins.py @@ -0,0 +1,135 @@ +from urllib.parse import urlparse + +from django.conf import settings +from django.contrib.auth import REDIRECT_FIELD_NAME +from django.contrib.auth.views import redirect_to_login +from django.core.exceptions import ImproperlyConfigured, PermissionDenied +from django.shortcuts import resolve_url + + +class AccessMixin: + """ + Abstract CBV mixin that gives access mixins the same customizable + functionality. + """ + + login_url = None + permission_denied_message = "" + raise_exception = False + redirect_field_name = REDIRECT_FIELD_NAME + + def get_login_url(self): + """ + Override this method to override the login_url attribute. + """ + login_url = self.login_url or settings.LOGIN_URL + if not login_url: + raise ImproperlyConfigured( + f"{self.__class__.__name__} is missing the login_url attribute. Define " + f"{self.__class__.__name__}.login_url, settings.LOGIN_URL, or override " + f"{self.__class__.__name__}.get_login_url()." + ) + return str(login_url) + + def get_permission_denied_message(self): + """ + Override this method to override the permission_denied_message attribute. + """ + return self.permission_denied_message + + def get_redirect_field_name(self): + """ + Override this method to override the redirect_field_name attribute. + """ + return self.redirect_field_name + + def handle_no_permission(self): + if self.raise_exception or self.request.user.is_authenticated: + raise PermissionDenied(self.get_permission_denied_message()) + + path = self.request.build_absolute_uri() + resolved_login_url = resolve_url(self.get_login_url()) + # If the login url is the same scheme and net location then use the + # path as the "next" url. + login_scheme, login_netloc = urlparse(resolved_login_url)[:2] + current_scheme, current_netloc = urlparse(path)[:2] + if (not login_scheme or login_scheme == current_scheme) and ( + not login_netloc or login_netloc == current_netloc + ): + path = self.request.get_full_path() + return redirect_to_login( + path, + resolved_login_url, + self.get_redirect_field_name(), + ) + + +class LoginRequiredMixin(AccessMixin): + """Verify that the current user is authenticated.""" + + def dispatch(self, request, *args, **kwargs): + if not request.user.is_authenticated: + return self.handle_no_permission() + return super().dispatch(request, *args, **kwargs) + + +class PermissionRequiredMixin(AccessMixin): + """Verify that the current user has all specified permissions.""" + + permission_required = None + + def get_permission_required(self): + """ + Override this method to override the permission_required attribute. + Must return an iterable. + """ + if self.permission_required is None: + raise ImproperlyConfigured( + f"{self.__class__.__name__} is missing the " + f"permission_required attribute. Define " + f"{self.__class__.__name__}.permission_required, or override " + f"{self.__class__.__name__}.get_permission_required()." + ) + if isinstance(self.permission_required, str): + perms = (self.permission_required,) + else: + perms = self.permission_required + return perms + + def has_permission(self): + """ + Override this method to customize the way permissions are checked. + """ + perms = self.get_permission_required() + return self.request.user.has_perms(perms) + + def dispatch(self, request, *args, **kwargs): + if not self.has_permission(): + return self.handle_no_permission() + return super().dispatch(request, *args, **kwargs) + + +class UserPassesTestMixin(AccessMixin): + """ + Deny a request with a permission error if the test_func() method returns + False. + """ + + def test_func(self): + raise NotImplementedError( + "{} is missing the implementation of the test_func() method.".format( + self.__class__.__name__ + ) + ) + + def get_test_func(self): + """ + Override this method to use a different test_func method. + """ + return self.test_func + + def dispatch(self, request, *args, **kwargs): + user_test_result = self.get_test_func()() + if not user_test_result: + return self.handle_no_permission() + return super().dispatch(request, *args, **kwargs) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/models.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/models.py new file mode 100644 index 0000000..85330e2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/models.py @@ -0,0 +1,499 @@ +from django.apps import apps +from django.contrib import auth +from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager +from django.contrib.auth.hashers import make_password +from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import PermissionDenied +from django.core.mail import send_mail +from django.db import models +from django.db.models.manager import EmptyManager +from django.utils import timezone +from django.utils.itercompat import is_iterable +from django.utils.translation import gettext_lazy as _ + +from .validators import UnicodeUsernameValidator + + +def update_last_login(sender, user, **kwargs): + """ + A signal receiver which updates the last_login date for + the user logging in. + """ + user.last_login = timezone.now() + user.save(update_fields=["last_login"]) + + +class PermissionManager(models.Manager): + use_in_migrations = True + + def get_by_natural_key(self, codename, app_label, model): + return self.get( + codename=codename, + content_type=ContentType.objects.db_manager(self.db).get_by_natural_key( + app_label, model + ), + ) + + +class Permission(models.Model): + """ + The permissions system provides a way to assign permissions to specific + users and groups of users. + + The permission system is used by the Django admin site, but may also be + useful in your own code. The Django admin site uses permissions as follows: + + - The "add" permission limits the user's ability to view the "add" form + and add an object. + - The "change" permission limits a user's ability to view the change + list, view the "change" form and change an object. + - The "delete" permission limits the ability to delete an object. + - The "view" permission limits the ability to view an object. + + Permissions are set globally per type of object, not per specific object + instance. It is possible to say "Mary may change news stories," but it's + not currently possible to say "Mary may change news stories, but only the + ones she created herself" or "Mary may only change news stories that have a + certain status or publication date." + + The permissions listed above are automatically created for each model. + """ + + name = models.CharField(_("name"), max_length=255) + content_type = models.ForeignKey( + ContentType, + models.CASCADE, + verbose_name=_("content type"), + ) + codename = models.CharField(_("codename"), max_length=100) + + objects = PermissionManager() + + class Meta: + verbose_name = _("permission") + verbose_name_plural = _("permissions") + unique_together = [["content_type", "codename"]] + ordering = ["content_type__app_label", "content_type__model", "codename"] + + def __str__(self): + return "%s | %s" % (self.content_type, self.name) + + def natural_key(self): + return (self.codename,) + self.content_type.natural_key() + + natural_key.dependencies = ["contenttypes.contenttype"] + + +class GroupManager(models.Manager): + """ + The manager for the auth's Group model. + """ + + use_in_migrations = True + + def get_by_natural_key(self, name): + return self.get(name=name) + + +class Group(models.Model): + """ + Groups are a generic way of categorizing users to apply permissions, or + some other label, to those users. A user can belong to any number of + groups. + + A user in a group automatically has all the permissions granted to that + group. For example, if the group 'Site editors' has the permission + can_edit_home_page, any user in that group will have that permission. + + Beyond permissions, groups are a convenient way to categorize users to + apply some label, or extended functionality, to them. For example, you + could create a group 'Special users', and you could write code that would + do special things to those users -- such as giving them access to a + members-only portion of your site, or sending them members-only email + messages. + """ + + name = models.CharField(_("name"), max_length=150, unique=True) + permissions = models.ManyToManyField( + Permission, + verbose_name=_("permissions"), + blank=True, + ) + + objects = GroupManager() + + class Meta: + verbose_name = _("group") + verbose_name_plural = _("groups") + + def __str__(self): + return self.name + + def natural_key(self): + return (self.name,) + + +class UserManager(BaseUserManager): + use_in_migrations = True + + def _create_user(self, username, email, password, **extra_fields): + """ + Create and save a user with the given username, email, and password. + """ + if not username: + raise ValueError("The given username must be set") + email = self.normalize_email(email) + # Lookup the real model class from the global app registry so this + # manager method can be used in migrations. This is fine because + # managers are by definition working on the real model. + GlobalUserModel = apps.get_model( + self.model._meta.app_label, self.model._meta.object_name + ) + username = GlobalUserModel.normalize_username(username) + user = self.model(username=username, email=email, **extra_fields) + user.password = make_password(password) + user.save(using=self._db) + return user + + def create_user(self, username, email=None, password=None, **extra_fields): + extra_fields.setdefault("is_staff", False) + extra_fields.setdefault("is_superuser", False) + return self._create_user(username, email, password, **extra_fields) + + def create_superuser(self, username, email=None, password=None, **extra_fields): + extra_fields.setdefault("is_staff", True) + extra_fields.setdefault("is_superuser", True) + + if extra_fields.get("is_staff") is not True: + raise ValueError("Superuser must have is_staff=True.") + if extra_fields.get("is_superuser") is not True: + raise ValueError("Superuser must have is_superuser=True.") + + return self._create_user(username, email, password, **extra_fields) + + def with_perm( + self, perm, is_active=True, include_superusers=True, backend=None, obj=None + ): + if backend is None: + backends = auth._get_backends(return_tuples=True) + if len(backends) == 1: + backend, _ = backends[0] + else: + raise ValueError( + "You have multiple authentication backends configured and " + "therefore must provide the `backend` argument." + ) + elif not isinstance(backend, str): + raise TypeError( + "backend must be a dotted import path string (got %r)." % backend + ) + else: + backend = auth.load_backend(backend) + if hasattr(backend, "with_perm"): + return backend.with_perm( + perm, + is_active=is_active, + include_superusers=include_superusers, + obj=obj, + ) + return self.none() + + +# A few helper functions for common logic between User and AnonymousUser. +def _user_get_permissions(user, obj, from_name): + permissions = set() + name = "get_%s_permissions" % from_name + for backend in auth.get_backends(): + if hasattr(backend, name): + permissions.update(getattr(backend, name)(user, obj)) + return permissions + + +def _user_has_perm(user, perm, obj): + """ + A backend can raise `PermissionDenied` to short-circuit permission checking. + """ + for backend in auth.get_backends(): + if not hasattr(backend, "has_perm"): + continue + try: + if backend.has_perm(user, perm, obj): + return True + except PermissionDenied: + return False + return False + + +def _user_has_module_perms(user, app_label): + """ + A backend can raise `PermissionDenied` to short-circuit permission checking. + """ + for backend in auth.get_backends(): + if not hasattr(backend, "has_module_perms"): + continue + try: + if backend.has_module_perms(user, app_label): + return True + except PermissionDenied: + return False + return False + + +class PermissionsMixin(models.Model): + """ + Add the fields and methods necessary to support the Group and Permission + models using the ModelBackend. + """ + + is_superuser = models.BooleanField( + _("superuser status"), + default=False, + help_text=_( + "Designates that this user has all permissions without " + "explicitly assigning them." + ), + ) + groups = models.ManyToManyField( + Group, + verbose_name=_("groups"), + blank=True, + help_text=_( + "The groups this user belongs to. A user will get all permissions " + "granted to each of their groups." + ), + related_name="user_set", + related_query_name="user", + ) + user_permissions = models.ManyToManyField( + Permission, + verbose_name=_("user permissions"), + blank=True, + help_text=_("Specific permissions for this user."), + related_name="user_set", + related_query_name="user", + ) + + class Meta: + abstract = True + + def get_user_permissions(self, obj=None): + """ + Return a list of permission strings that this user has directly. + Query all available auth backends. If an object is passed in, + return only permissions matching this object. + """ + return _user_get_permissions(self, obj, "user") + + def get_group_permissions(self, obj=None): + """ + Return a list of permission strings that this user has through their + groups. Query all available auth backends. If an object is passed in, + return only permissions matching this object. + """ + return _user_get_permissions(self, obj, "group") + + def get_all_permissions(self, obj=None): + return _user_get_permissions(self, obj, "all") + + def has_perm(self, perm, obj=None): + """ + Return True if the user has the specified permission. Query all + available auth backends, but return immediately if any backend returns + True. Thus, a user who has permission from a single auth backend is + assumed to have permission in general. If an object is provided, check + permissions for that object. + """ + # Active superusers have all permissions. + if self.is_active and self.is_superuser: + return True + + # Otherwise we need to check the backends. + return _user_has_perm(self, perm, obj) + + def has_perms(self, perm_list, obj=None): + """ + Return True if the user has each of the specified permissions. If + object is passed, check if the user has all required perms for it. + """ + if not is_iterable(perm_list) or isinstance(perm_list, str): + raise ValueError("perm_list must be an iterable of permissions.") + return all(self.has_perm(perm, obj) for perm in perm_list) + + def has_module_perms(self, app_label): + """ + Return True if the user has any permissions in the given app label. + Use similar logic as has_perm(), above. + """ + # Active superusers have all permissions. + if self.is_active and self.is_superuser: + return True + + return _user_has_module_perms(self, app_label) + + +class AbstractUser(AbstractBaseUser, PermissionsMixin): + """ + An abstract base class implementing a fully featured User model with + admin-compliant permissions. + + Username and password are required. Other fields are optional. + """ + + username_validator = UnicodeUsernameValidator() + + username = models.CharField( + _("username"), + max_length=150, + unique=True, + help_text=_( + "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only." + ), + validators=[username_validator], + error_messages={ + "unique": _("A user with that username already exists."), + }, + ) + first_name = models.CharField(_("first name"), max_length=150, blank=True) + last_name = models.CharField(_("last name"), max_length=150, blank=True) + email = models.EmailField(_("email address"), blank=True) + is_staff = models.BooleanField( + _("staff status"), + default=False, + help_text=_("Designates whether the user can log into this admin site."), + ) + is_active = models.BooleanField( + _("active"), + default=True, + help_text=_( + "Designates whether this user should be treated as active. " + "Unselect this instead of deleting accounts." + ), + ) + date_joined = models.DateTimeField(_("date joined"), default=timezone.now) + + objects = UserManager() + + EMAIL_FIELD = "email" + USERNAME_FIELD = "username" + REQUIRED_FIELDS = ["email"] + + class Meta: + verbose_name = _("user") + verbose_name_plural = _("users") + abstract = True + + def clean(self): + super().clean() + self.email = self.__class__.objects.normalize_email(self.email) + + def get_full_name(self): + """ + Return the first_name plus the last_name, with a space in between. + """ + full_name = "%s %s" % (self.first_name, self.last_name) + return full_name.strip() + + def get_short_name(self): + """Return the short name for the user.""" + return self.first_name + + def email_user(self, subject, message, from_email=None, **kwargs): + """Send an email to this user.""" + send_mail(subject, message, from_email, [self.email], **kwargs) + + +class User(AbstractUser): + """ + Users within the Django authentication system are represented by this + model. + + Username and password are required. Other fields are optional. + """ + + class Meta(AbstractUser.Meta): + swappable = "AUTH_USER_MODEL" + + +class AnonymousUser: + id = None + pk = None + username = "" + is_staff = False + is_active = False + is_superuser = False + _groups = EmptyManager(Group) + _user_permissions = EmptyManager(Permission) + + def __str__(self): + return "AnonymousUser" + + def __eq__(self, other): + return isinstance(other, self.__class__) + + def __hash__(self): + return 1 # instances always return the same hash value + + def __int__(self): + raise TypeError( + "Cannot cast AnonymousUser to int. Are you trying to use it in place of " + "User?" + ) + + def save(self): + raise NotImplementedError( + "Django doesn't provide a DB representation for AnonymousUser." + ) + + def delete(self): + raise NotImplementedError( + "Django doesn't provide a DB representation for AnonymousUser." + ) + + def set_password(self, raw_password): + raise NotImplementedError( + "Django doesn't provide a DB representation for AnonymousUser." + ) + + def check_password(self, raw_password): + raise NotImplementedError( + "Django doesn't provide a DB representation for AnonymousUser." + ) + + @property + def groups(self): + return self._groups + + @property + def user_permissions(self): + return self._user_permissions + + def get_user_permissions(self, obj=None): + return _user_get_permissions(self, obj, "user") + + def get_group_permissions(self, obj=None): + return set() + + def get_all_permissions(self, obj=None): + return _user_get_permissions(self, obj, "all") + + def has_perm(self, perm, obj=None): + return _user_has_perm(self, perm, obj=obj) + + def has_perms(self, perm_list, obj=None): + if not is_iterable(perm_list) or isinstance(perm_list, str): + raise ValueError("perm_list must be an iterable of permissions.") + return all(self.has_perm(perm, obj) for perm in perm_list) + + def has_module_perms(self, module): + return _user_has_module_perms(self, module) + + @property + def is_anonymous(self): + return True + + @property + def is_authenticated(self): + return False + + def get_username(self): + return self.username diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/password_validation.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/password_validation.py new file mode 100644 index 0000000..06f8fcc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/password_validation.py @@ -0,0 +1,266 @@ +import functools +import gzip +import re +from difflib import SequenceMatcher +from pathlib import Path + +from django.conf import settings +from django.core.exceptions import ( + FieldDoesNotExist, + ImproperlyConfigured, + ValidationError, +) +from django.utils.functional import cached_property, lazy +from django.utils.html import format_html, format_html_join +from django.utils.module_loading import import_string +from django.utils.translation import gettext as _ +from django.utils.translation import ngettext + + +@functools.cache +def get_default_password_validators(): + return get_password_validators(settings.AUTH_PASSWORD_VALIDATORS) + + +def get_password_validators(validator_config): + validators = [] + for validator in validator_config: + try: + klass = import_string(validator["NAME"]) + except ImportError: + msg = ( + "The module in NAME could not be imported: %s. Check your " + "AUTH_PASSWORD_VALIDATORS setting." + ) + raise ImproperlyConfigured(msg % validator["NAME"]) + validators.append(klass(**validator.get("OPTIONS", {}))) + + return validators + + +def validate_password(password, user=None, password_validators=None): + """ + Validate that the password meets all validator requirements. + + If the password is valid, return ``None``. + If the password is invalid, raise ValidationError with all error messages. + """ + errors = [] + if password_validators is None: + password_validators = get_default_password_validators() + for validator in password_validators: + try: + validator.validate(password, user) + except ValidationError as error: + errors.append(error) + if errors: + raise ValidationError(errors) + + +def password_changed(password, user=None, password_validators=None): + """ + Inform all validators that have implemented a password_changed() method + that the password has been changed. + """ + if password_validators is None: + password_validators = get_default_password_validators() + for validator in password_validators: + password_changed = getattr(validator, "password_changed", lambda *a: None) + password_changed(password, user) + + +def password_validators_help_texts(password_validators=None): + """ + Return a list of all help texts of all configured validators. + """ + help_texts = [] + if password_validators is None: + password_validators = get_default_password_validators() + for validator in password_validators: + help_texts.append(validator.get_help_text()) + return help_texts + + +def _password_validators_help_text_html(password_validators=None): + """ + Return an HTML string with all help texts of all configured validators + in an
      . + """ + help_texts = password_validators_help_texts(password_validators) + help_items = format_html_join( + "", "
    • {}
    • ", ((help_text,) for help_text in help_texts) + ) + return format_html("
        {}
      ", help_items) if help_items else "" + + +password_validators_help_text_html = lazy(_password_validators_help_text_html, str) + + +class MinimumLengthValidator: + """ + Validate that the password is of a minimum length. + """ + + def __init__(self, min_length=8): + self.min_length = min_length + + def validate(self, password, user=None): + if len(password) < self.min_length: + raise ValidationError( + ngettext( + "This password is too short. It must contain at least " + "%(min_length)d character.", + "This password is too short. It must contain at least " + "%(min_length)d characters.", + self.min_length, + ), + code="password_too_short", + params={"min_length": self.min_length}, + ) + + def get_help_text(self): + return ngettext( + "Your password must contain at least %(min_length)d character.", + "Your password must contain at least %(min_length)d characters.", + self.min_length, + ) % {"min_length": self.min_length} + + +def exceeds_maximum_length_ratio(password, max_similarity, value): + """ + Test that value is within a reasonable range of password. + + The following ratio calculations are based on testing SequenceMatcher like + this: + + for i in range(0,6): + print(10**i, SequenceMatcher(a='A', b='A'*(10**i)).quick_ratio()) + + which yields: + + 1 1.0 + 10 0.18181818181818182 + 100 0.019801980198019802 + 1000 0.001998001998001998 + 10000 0.00019998000199980003 + 100000 1.999980000199998e-05 + + This means a length_ratio of 10 should never yield a similarity higher than + 0.2, for 100 this is down to 0.02 and for 1000 it is 0.002. This can be + calculated via 2 / length_ratio. As a result we avoid the potentially + expensive sequence matching. + """ + pwd_len = len(password) + length_bound_similarity = max_similarity / 2 * pwd_len + value_len = len(value) + return pwd_len >= 10 * value_len and value_len < length_bound_similarity + + +class UserAttributeSimilarityValidator: + """ + Validate that the password is sufficiently different from the user's + attributes. + + If no specific attributes are provided, look at a sensible list of + defaults. Attributes that don't exist are ignored. Comparison is made to + not only the full attribute value, but also its components, so that, for + example, a password is validated against either part of an email address, + as well as the full address. + """ + + DEFAULT_USER_ATTRIBUTES = ("username", "first_name", "last_name", "email") + + def __init__(self, user_attributes=DEFAULT_USER_ATTRIBUTES, max_similarity=0.7): + self.user_attributes = user_attributes + if max_similarity < 0.1: + raise ValueError("max_similarity must be at least 0.1") + self.max_similarity = max_similarity + + def validate(self, password, user=None): + if not user: + return + + password = password.lower() + for attribute_name in self.user_attributes: + value = getattr(user, attribute_name, None) + if not value or not isinstance(value, str): + continue + value_lower = value.lower() + value_parts = re.split(r"\W+", value_lower) + [value_lower] + for value_part in value_parts: + if exceeds_maximum_length_ratio( + password, self.max_similarity, value_part + ): + continue + if ( + SequenceMatcher(a=password, b=value_part).quick_ratio() + >= self.max_similarity + ): + try: + verbose_name = str( + user._meta.get_field(attribute_name).verbose_name + ) + except FieldDoesNotExist: + verbose_name = attribute_name + raise ValidationError( + _("The password is too similar to the %(verbose_name)s."), + code="password_too_similar", + params={"verbose_name": verbose_name}, + ) + + def get_help_text(self): + return _( + "Your password can’t be too similar to your other personal information." + ) + + +class CommonPasswordValidator: + """ + Validate that the password is not a common password. + + The password is rejected if it occurs in a provided list of passwords, + which may be gzipped. The list Django ships with contains 20000 common + passwords (lowercased and deduplicated), created by Royce Williams: + https://gist.github.com/roycewilliams/226886fd01572964e1431ac8afc999ce + The password list must be lowercased to match the comparison in validate(). + """ + + @cached_property + def DEFAULT_PASSWORD_LIST_PATH(self): + return Path(__file__).resolve().parent / "common-passwords.txt.gz" + + def __init__(self, password_list_path=DEFAULT_PASSWORD_LIST_PATH): + if password_list_path is CommonPasswordValidator.DEFAULT_PASSWORD_LIST_PATH: + password_list_path = self.DEFAULT_PASSWORD_LIST_PATH + try: + with gzip.open(password_list_path, "rt", encoding="utf-8") as f: + self.passwords = {x.strip() for x in f} + except OSError: + with open(password_list_path) as f: + self.passwords = {x.strip() for x in f} + + def validate(self, password, user=None): + if password.lower().strip() in self.passwords: + raise ValidationError( + _("This password is too common."), + code="password_too_common", + ) + + def get_help_text(self): + return _("Your password can’t be a commonly used password.") + + +class NumericPasswordValidator: + """ + Validate that the password is not entirely numeric. + """ + + def validate(self, password, user=None): + if password.isdigit(): + raise ValidationError( + _("This password is entirely numeric."), + code="password_entirely_numeric", + ) + + def get_help_text(self): + return _("Your password can’t be entirely numeric.") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/signals.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/signals.py new file mode 100644 index 0000000..ed669f9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/signals.py @@ -0,0 +1,5 @@ +from django.dispatch import Signal + +user_logged_in = Signal() +user_login_failed = Signal() +user_logged_out = Signal() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/templates/auth/widgets/read_only_password_hash.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/templates/auth/widgets/read_only_password_hash.html new file mode 100644 index 0000000..c73042b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/templates/auth/widgets/read_only_password_hash.html @@ -0,0 +1,5 @@ + +{% for entry in summary %} +{{ entry.label }}{% if entry.value %}: {{ entry.value }}{% endif %} +{% endfor %} +
  • diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/templates/registration/password_reset_subject.txt b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/templates/registration/password_reset_subject.txt new file mode 100644 index 0000000..eb30fcb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/templates/registration/password_reset_subject.txt @@ -0,0 +1,3 @@ +{% load i18n %}{% autoescape off %} +{% blocktranslate %}Password reset on {{ site_name }}{% endblocktranslate %} +{% endautoescape %} \ No newline at end of file diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/tokens.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/tokens.py new file mode 100644 index 0000000..09cc2b5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/tokens.py @@ -0,0 +1,132 @@ +from datetime import datetime + +from django.conf import settings +from django.utils.crypto import constant_time_compare, salted_hmac +from django.utils.http import base36_to_int, int_to_base36 + + +class PasswordResetTokenGenerator: + """ + Strategy object used to generate and check tokens for the password + reset mechanism. + """ + + key_salt = "django.contrib.auth.tokens.PasswordResetTokenGenerator" + algorithm = None + _secret = None + _secret_fallbacks = None + + def __init__(self): + self.algorithm = self.algorithm or "sha256" + + def _get_secret(self): + return self._secret or settings.SECRET_KEY + + def _set_secret(self, secret): + self._secret = secret + + secret = property(_get_secret, _set_secret) + + def _get_fallbacks(self): + if self._secret_fallbacks is None: + return settings.SECRET_KEY_FALLBACKS + return self._secret_fallbacks + + def _set_fallbacks(self, fallbacks): + self._secret_fallbacks = fallbacks + + secret_fallbacks = property(_get_fallbacks, _set_fallbacks) + + def make_token(self, user): + """ + Return a token that can be used once to do a password reset + for the given user. + """ + return self._make_token_with_timestamp( + user, + self._num_seconds(self._now()), + self.secret, + ) + + def check_token(self, user, token): + """ + Check that a password reset token is correct for a given user. + """ + if not (user and token): + return False + # Parse the token + try: + ts_b36, _ = token.split("-") + except ValueError: + return False + + try: + ts = base36_to_int(ts_b36) + except ValueError: + return False + + # Check that the timestamp/uid has not been tampered with + for secret in [self.secret, *self.secret_fallbacks]: + if constant_time_compare( + self._make_token_with_timestamp(user, ts, secret), + token, + ): + break + else: + return False + + # Check the timestamp is within limit. + if (self._num_seconds(self._now()) - ts) > settings.PASSWORD_RESET_TIMEOUT: + return False + + return True + + def _make_token_with_timestamp(self, user, timestamp, secret): + # timestamp is number of seconds since 2001-1-1. Converted to base 36, + # this gives us a 6 digit string until about 2069. + ts_b36 = int_to_base36(timestamp) + hash_string = salted_hmac( + self.key_salt, + self._make_hash_value(user, timestamp), + secret=secret, + algorithm=self.algorithm, + ).hexdigest()[ + ::2 + ] # Limit to shorten the URL. + return "%s-%s" % (ts_b36, hash_string) + + def _make_hash_value(self, user, timestamp): + """ + Hash the user's primary key, email (if available), and some user state + that's sure to change after a password reset to produce a token that is + invalidated when it's used: + 1. The password field will change upon a password reset (even if the + same password is chosen, due to password salting). + 2. The last_login field will usually be updated very shortly after + a password reset. + Failing those things, settings.PASSWORD_RESET_TIMEOUT eventually + invalidates the token. + + Running this data through salted_hmac() prevents password cracking + attempts using the reset token, provided the secret isn't compromised. + """ + # Truncate microseconds so that tokens are consistent even if the + # database doesn't support microseconds. + login_timestamp = ( + "" + if user.last_login is None + else user.last_login.replace(microsecond=0, tzinfo=None) + ) + email_field = user.get_email_field_name() + email = getattr(user, email_field, "") or "" + return f"{user.pk}{user.password}{login_timestamp}{timestamp}{email}" + + def _num_seconds(self, dt): + return int((dt - datetime(2001, 1, 1)).total_seconds()) + + def _now(self): + # Used for mocking in tests + return datetime.now() + + +default_token_generator = PasswordResetTokenGenerator() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/urls.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/urls.py new file mode 100644 index 0000000..699ba61 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/urls.py @@ -0,0 +1,36 @@ +# The views used below are normally mapped in the AdminSite instance. +# This URLs file is used to provide a reliable view deployment for test purposes. +# It is also provided as a convenience to those who want to deploy these URLs +# elsewhere. + +from django.contrib.auth import views +from django.urls import path + +urlpatterns = [ + path("login/", views.LoginView.as_view(), name="login"), + path("logout/", views.LogoutView.as_view(), name="logout"), + path( + "password_change/", views.PasswordChangeView.as_view(), name="password_change" + ), + path( + "password_change/done/", + views.PasswordChangeDoneView.as_view(), + name="password_change_done", + ), + path("password_reset/", views.PasswordResetView.as_view(), name="password_reset"), + path( + "password_reset/done/", + views.PasswordResetDoneView.as_view(), + name="password_reset_done", + ), + path( + "reset///", + views.PasswordResetConfirmView.as_view(), + name="password_reset_confirm", + ), + path( + "reset/done/", + views.PasswordResetCompleteView.as_view(), + name="password_reset_complete", + ), +] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/validators.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/validators.py new file mode 100644 index 0000000..bf3894a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/validators.py @@ -0,0 +1,25 @@ +import re + +from django.core import validators +from django.utils.deconstruct import deconstructible +from django.utils.translation import gettext_lazy as _ + + +@deconstructible +class ASCIIUsernameValidator(validators.RegexValidator): + regex = r"^[\w.@+-]+\Z" + message = _( + "Enter a valid username. This value may contain only unaccented lowercase a-z " + "and uppercase A-Z letters, numbers, and @/./+/-/_ characters." + ) + flags = re.ASCII + + +@deconstructible +class UnicodeUsernameValidator(validators.RegexValidator): + regex = r"^[\w.@+-]+\Z" + message = _( + "Enter a valid username. This value may contain only letters, " + "numbers, and @/./+/-/_ characters." + ) + flags = 0 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/views.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/views.py new file mode 100644 index 0000000..0d16104 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/auth/views.py @@ -0,0 +1,379 @@ +from urllib.parse import urlparse, urlunparse + +from django.conf import settings + +# Avoid shadowing the login() and logout() views below. +from django.contrib.auth import REDIRECT_FIELD_NAME, get_user_model +from django.contrib.auth import login as auth_login +from django.contrib.auth import logout as auth_logout +from django.contrib.auth import update_session_auth_hash +from django.contrib.auth.decorators import login_required +from django.contrib.auth.forms import ( + AuthenticationForm, + PasswordChangeForm, + PasswordResetForm, + SetPasswordForm, +) +from django.contrib.auth.tokens import default_token_generator +from django.contrib.sites.shortcuts import get_current_site +from django.core.exceptions import ImproperlyConfigured, ValidationError +from django.http import HttpResponseRedirect, QueryDict +from django.shortcuts import resolve_url +from django.urls import reverse_lazy +from django.utils.decorators import method_decorator +from django.utils.http import url_has_allowed_host_and_scheme, urlsafe_base64_decode +from django.utils.translation import gettext_lazy as _ +from django.views.decorators.cache import never_cache +from django.views.decorators.csrf import csrf_protect +from django.views.decorators.debug import sensitive_post_parameters +from django.views.generic.base import TemplateView +from django.views.generic.edit import FormView + +UserModel = get_user_model() + + +class RedirectURLMixin: + next_page = None + redirect_field_name = REDIRECT_FIELD_NAME + success_url_allowed_hosts = set() + + def get_success_url(self): + return self.get_redirect_url() or self.get_default_redirect_url() + + def get_redirect_url(self): + """Return the user-originating redirect URL if it's safe.""" + redirect_to = self.request.POST.get( + self.redirect_field_name, self.request.GET.get(self.redirect_field_name) + ) + url_is_safe = url_has_allowed_host_and_scheme( + url=redirect_to, + allowed_hosts=self.get_success_url_allowed_hosts(), + require_https=self.request.is_secure(), + ) + return redirect_to if url_is_safe else "" + + def get_success_url_allowed_hosts(self): + return {self.request.get_host(), *self.success_url_allowed_hosts} + + def get_default_redirect_url(self): + """Return the default redirect URL.""" + if self.next_page: + return resolve_url(self.next_page) + raise ImproperlyConfigured("No URL to redirect to. Provide a next_page.") + + +class LoginView(RedirectURLMixin, FormView): + """ + Display the login form and handle the login action. + """ + + form_class = AuthenticationForm + authentication_form = None + template_name = "registration/login.html" + redirect_authenticated_user = False + extra_context = None + + @method_decorator(sensitive_post_parameters()) + @method_decorator(csrf_protect) + @method_decorator(never_cache) + def dispatch(self, request, *args, **kwargs): + if self.redirect_authenticated_user and self.request.user.is_authenticated: + redirect_to = self.get_success_url() + if redirect_to == self.request.path: + raise ValueError( + "Redirection loop for authenticated user detected. Check that " + "your LOGIN_REDIRECT_URL doesn't point to a login page." + ) + return HttpResponseRedirect(redirect_to) + return super().dispatch(request, *args, **kwargs) + + def get_default_redirect_url(self): + """Return the default redirect URL.""" + if self.next_page: + return resolve_url(self.next_page) + else: + return resolve_url(settings.LOGIN_REDIRECT_URL) + + def get_form_class(self): + return self.authentication_form or self.form_class + + def get_form_kwargs(self): + kwargs = super().get_form_kwargs() + kwargs["request"] = self.request + return kwargs + + def form_valid(self, form): + """Security check complete. Log the user in.""" + auth_login(self.request, form.get_user()) + return HttpResponseRedirect(self.get_success_url()) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + current_site = get_current_site(self.request) + context.update( + { + self.redirect_field_name: self.get_redirect_url(), + "site": current_site, + "site_name": current_site.name, + **(self.extra_context or {}), + } + ) + return context + + +class LogoutView(RedirectURLMixin, TemplateView): + """ + Log out the user and display the 'You are logged out' message. + """ + + http_method_names = ["post", "options"] + template_name = "registration/logged_out.html" + extra_context = None + + @method_decorator(csrf_protect) + @method_decorator(never_cache) + def dispatch(self, request, *args, **kwargs): + return super().dispatch(request, *args, **kwargs) + + def post(self, request, *args, **kwargs): + """Logout may be done via POST.""" + auth_logout(request) + redirect_to = self.get_success_url() + if redirect_to != request.get_full_path(): + # Redirect to target page once the session has been cleared. + return HttpResponseRedirect(redirect_to) + return super().get(request, *args, **kwargs) + + def get_default_redirect_url(self): + """Return the default redirect URL.""" + if self.next_page: + return resolve_url(self.next_page) + elif settings.LOGOUT_REDIRECT_URL: + return resolve_url(settings.LOGOUT_REDIRECT_URL) + else: + return self.request.path + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + current_site = get_current_site(self.request) + context.update( + { + "site": current_site, + "site_name": current_site.name, + "title": _("Logged out"), + "subtitle": None, + **(self.extra_context or {}), + } + ) + return context + + +def logout_then_login(request, login_url=None): + """ + Log out the user if they are logged in. Then redirect to the login page. + """ + login_url = resolve_url(login_url or settings.LOGIN_URL) + return LogoutView.as_view(next_page=login_url)(request) + + +def redirect_to_login(next, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME): + """ + Redirect the user to the login page, passing the given 'next' page. + """ + resolved_url = resolve_url(login_url or settings.LOGIN_URL) + + login_url_parts = list(urlparse(resolved_url)) + if redirect_field_name: + querystring = QueryDict(login_url_parts[4], mutable=True) + querystring[redirect_field_name] = next + login_url_parts[4] = querystring.urlencode(safe="/") + + return HttpResponseRedirect(urlunparse(login_url_parts)) + + +# Class-based password reset views +# - PasswordResetView sends the mail +# - PasswordResetDoneView shows a success message for the above +# - PasswordResetConfirmView checks the link the user clicked and +# prompts for a new password +# - PasswordResetCompleteView shows a success message for the above + + +class PasswordContextMixin: + extra_context = None + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context.update( + {"title": self.title, "subtitle": None, **(self.extra_context or {})} + ) + return context + + +class PasswordResetView(PasswordContextMixin, FormView): + email_template_name = "registration/password_reset_email.html" + extra_email_context = None + form_class = PasswordResetForm + from_email = None + html_email_template_name = None + subject_template_name = "registration/password_reset_subject.txt" + success_url = reverse_lazy("password_reset_done") + template_name = "registration/password_reset_form.html" + title = _("Password reset") + token_generator = default_token_generator + + @method_decorator(csrf_protect) + def dispatch(self, *args, **kwargs): + return super().dispatch(*args, **kwargs) + + def form_valid(self, form): + opts = { + "use_https": self.request.is_secure(), + "token_generator": self.token_generator, + "from_email": self.from_email, + "email_template_name": self.email_template_name, + "subject_template_name": self.subject_template_name, + "request": self.request, + "html_email_template_name": self.html_email_template_name, + "extra_email_context": self.extra_email_context, + } + form.save(**opts) + return super().form_valid(form) + + +INTERNAL_RESET_SESSION_TOKEN = "_password_reset_token" + + +class PasswordResetDoneView(PasswordContextMixin, TemplateView): + template_name = "registration/password_reset_done.html" + title = _("Password reset sent") + + +class PasswordResetConfirmView(PasswordContextMixin, FormView): + form_class = SetPasswordForm + post_reset_login = False + post_reset_login_backend = None + reset_url_token = "set-password" + success_url = reverse_lazy("password_reset_complete") + template_name = "registration/password_reset_confirm.html" + title = _("Enter new password") + token_generator = default_token_generator + + @method_decorator(sensitive_post_parameters()) + @method_decorator(never_cache) + def dispatch(self, *args, **kwargs): + if "uidb64" not in kwargs or "token" not in kwargs: + raise ImproperlyConfigured( + "The URL path must contain 'uidb64' and 'token' parameters." + ) + + self.validlink = False + self.user = self.get_user(kwargs["uidb64"]) + + if self.user is not None: + token = kwargs["token"] + if token == self.reset_url_token: + session_token = self.request.session.get(INTERNAL_RESET_SESSION_TOKEN) + if self.token_generator.check_token(self.user, session_token): + # If the token is valid, display the password reset form. + self.validlink = True + return super().dispatch(*args, **kwargs) + else: + if self.token_generator.check_token(self.user, token): + # Store the token in the session and redirect to the + # password reset form at a URL without the token. That + # avoids the possibility of leaking the token in the + # HTTP Referer header. + self.request.session[INTERNAL_RESET_SESSION_TOKEN] = token + redirect_url = self.request.path.replace( + token, self.reset_url_token + ) + return HttpResponseRedirect(redirect_url) + + # Display the "Password reset unsuccessful" page. + return self.render_to_response(self.get_context_data()) + + def get_user(self, uidb64): + try: + # urlsafe_base64_decode() decodes to bytestring + uid = urlsafe_base64_decode(uidb64).decode() + user = UserModel._default_manager.get(pk=uid) + except ( + TypeError, + ValueError, + OverflowError, + UserModel.DoesNotExist, + ValidationError, + ): + user = None + return user + + def get_form_kwargs(self): + kwargs = super().get_form_kwargs() + kwargs["user"] = self.user + return kwargs + + def form_valid(self, form): + user = form.save() + del self.request.session[INTERNAL_RESET_SESSION_TOKEN] + if self.post_reset_login: + auth_login(self.request, user, self.post_reset_login_backend) + return super().form_valid(form) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + if self.validlink: + context["validlink"] = True + else: + context.update( + { + "form": None, + "title": _("Password reset unsuccessful"), + "validlink": False, + } + ) + return context + + +class PasswordResetCompleteView(PasswordContextMixin, TemplateView): + template_name = "registration/password_reset_complete.html" + title = _("Password reset complete") + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["login_url"] = resolve_url(settings.LOGIN_URL) + return context + + +class PasswordChangeView(PasswordContextMixin, FormView): + form_class = PasswordChangeForm + success_url = reverse_lazy("password_change_done") + template_name = "registration/password_change_form.html" + title = _("Password change") + + @method_decorator(sensitive_post_parameters()) + @method_decorator(csrf_protect) + @method_decorator(login_required) + def dispatch(self, *args, **kwargs): + return super().dispatch(*args, **kwargs) + + def get_form_kwargs(self): + kwargs = super().get_form_kwargs() + kwargs["user"] = self.request.user + return kwargs + + def form_valid(self, form): + form.save() + # Updating the password logs out all other sessions for the user + # except the current one. + update_session_auth_hash(self.request, form.user) + return super().form_valid(form) + + +class PasswordChangeDoneView(PasswordContextMixin, TemplateView): + template_name = "registration/password_change_done.html" + title = _("Password change successful") + + @method_decorator(login_required) + def dispatch(self, *args, **kwargs): + return super().dispatch(*args, **kwargs) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/admin.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/admin.py new file mode 100644 index 0000000..617d6d2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/admin.py @@ -0,0 +1,143 @@ +from functools import partial + +from django.contrib.admin.checks import InlineModelAdminChecks +from django.contrib.admin.options import InlineModelAdmin, flatten_fieldsets +from django.contrib.contenttypes.fields import GenericForeignKey +from django.contrib.contenttypes.forms import ( + BaseGenericInlineFormSet, + generic_inlineformset_factory, +) +from django.core import checks +from django.core.exceptions import FieldDoesNotExist +from django.forms import ALL_FIELDS +from django.forms.models import modelform_defines_fields + + +class GenericInlineModelAdminChecks(InlineModelAdminChecks): + def _check_exclude_of_parent_model(self, obj, parent_model): + # There's no FK to exclude, so no exclusion checks are required. + return [] + + def _check_relation(self, obj, parent_model): + # There's no FK, but we do need to confirm that the ct_field and + # ct_fk_field are valid, and that they are part of a GenericForeignKey. + + gfks = [ + f + for f in obj.model._meta.private_fields + if isinstance(f, GenericForeignKey) + ] + if not gfks: + return [ + checks.Error( + "'%s' has no GenericForeignKey." % obj.model._meta.label, + obj=obj.__class__, + id="admin.E301", + ) + ] + else: + # Check that the ct_field and ct_fk_fields exist + try: + obj.model._meta.get_field(obj.ct_field) + except FieldDoesNotExist: + return [ + checks.Error( + "'ct_field' references '%s', which is not a field on '%s'." + % ( + obj.ct_field, + obj.model._meta.label, + ), + obj=obj.__class__, + id="admin.E302", + ) + ] + + try: + obj.model._meta.get_field(obj.ct_fk_field) + except FieldDoesNotExist: + return [ + checks.Error( + "'ct_fk_field' references '%s', which is not a field on '%s'." + % ( + obj.ct_fk_field, + obj.model._meta.label, + ), + obj=obj.__class__, + id="admin.E303", + ) + ] + + # There's one or more GenericForeignKeys; make sure that one of them + # uses the right ct_field and ct_fk_field. + for gfk in gfks: + if gfk.ct_field == obj.ct_field and gfk.fk_field == obj.ct_fk_field: + return [] + + return [ + checks.Error( + "'%s' has no GenericForeignKey using content type field '%s' and " + "object ID field '%s'." + % ( + obj.model._meta.label, + obj.ct_field, + obj.ct_fk_field, + ), + obj=obj.__class__, + id="admin.E304", + ) + ] + + +class GenericInlineModelAdmin(InlineModelAdmin): + ct_field = "content_type" + ct_fk_field = "object_id" + formset = BaseGenericInlineFormSet + + checks_class = GenericInlineModelAdminChecks + + def get_formset(self, request, obj=None, **kwargs): + if "fields" in kwargs: + fields = kwargs.pop("fields") + else: + fields = flatten_fieldsets(self.get_fieldsets(request, obj)) + exclude = [*(self.exclude or []), *self.get_readonly_fields(request, obj)] + if ( + self.exclude is None + and hasattr(self.form, "_meta") + and self.form._meta.exclude + ): + # Take the custom ModelForm's Meta.exclude into account only if the + # GenericInlineModelAdmin doesn't define its own. + exclude.extend(self.form._meta.exclude) + exclude = exclude or None + can_delete = self.can_delete and self.has_delete_permission(request, obj) + defaults = { + "ct_field": self.ct_field, + "fk_field": self.ct_fk_field, + "form": self.form, + "formfield_callback": partial(self.formfield_for_dbfield, request=request), + "formset": self.formset, + "extra": self.get_extra(request, obj), + "can_delete": can_delete, + "can_order": False, + "fields": fields, + "min_num": self.get_min_num(request, obj), + "max_num": self.get_max_num(request, obj), + "exclude": exclude, + **kwargs, + } + + if defaults["fields"] is None and not modelform_defines_fields( + defaults["form"] + ): + defaults["fields"] = ALL_FIELDS + + return generic_inlineformset_factory(self.model, **defaults) + + +class GenericStackedInline(GenericInlineModelAdmin): + template = "admin/edit_inline/stacked.html" + + +class GenericTabularInline(GenericInlineModelAdmin): + template = "admin/edit_inline/tabular.html" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/apps.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/apps.py new file mode 100644 index 0000000..11dfb91 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/apps.py @@ -0,0 +1,22 @@ +from django.apps import AppConfig +from django.contrib.contenttypes.checks import ( + check_generic_foreign_keys, + check_model_name_lengths, +) +from django.core import checks +from django.db.models.signals import post_migrate, pre_migrate +from django.utils.translation import gettext_lazy as _ + +from .management import create_contenttypes, inject_rename_contenttypes_operations + + +class ContentTypesConfig(AppConfig): + default_auto_field = "django.db.models.AutoField" + name = "django.contrib.contenttypes" + verbose_name = _("Content Types") + + def ready(self): + pre_migrate.connect(inject_rename_contenttypes_operations, sender=self) + post_migrate.connect(create_contenttypes) + checks.register(check_generic_foreign_keys, checks.Tags.models) + checks.register(check_model_name_lengths, checks.Tags.models) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/checks.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/checks.py new file mode 100644 index 0000000..753c5d2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/checks.py @@ -0,0 +1,46 @@ +from itertools import chain + +from django.apps import apps +from django.core.checks import Error + + +def check_generic_foreign_keys(app_configs=None, **kwargs): + from .fields import GenericForeignKey + + if app_configs is None: + models = apps.get_models() + else: + models = chain.from_iterable( + app_config.get_models() for app_config in app_configs + ) + errors = [] + fields = ( + obj + for model in models + for obj in vars(model).values() + if isinstance(obj, GenericForeignKey) + ) + for field in fields: + errors.extend(field.check()) + return errors + + +def check_model_name_lengths(app_configs=None, **kwargs): + if app_configs is None: + models = apps.get_models() + else: + models = chain.from_iterable( + app_config.get_models() for app_config in app_configs + ) + errors = [] + for model in models: + if len(model._meta.model_name) > 100: + errors.append( + Error( + "Model names must be at most 100 characters (got %d)." + % (len(model._meta.model_name),), + obj=model, + id="contenttypes.E005", + ) + ) + return errors diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/fields.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/fields.py new file mode 100644 index 0000000..1b6abb9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/fields.py @@ -0,0 +1,847 @@ +import functools +import itertools +import warnings +from collections import defaultdict + +from asgiref.sync import sync_to_async + +from django.contrib.contenttypes.models import ContentType +from django.core import checks +from django.core.exceptions import FieldDoesNotExist, ObjectDoesNotExist +from django.db import DEFAULT_DB_ALIAS, models, router, transaction +from django.db.models import DO_NOTHING, ForeignObject, ForeignObjectRel +from django.db.models.base import ModelBase, make_foreign_order_accessors +from django.db.models.fields.mixins import FieldCacheMixin +from django.db.models.fields.related import ( + ReverseManyToOneDescriptor, + lazy_related_operation, +) +from django.db.models.query_utils import PathInfo +from django.db.models.sql import AND +from django.db.models.sql.where import WhereNode +from django.db.models.utils import AltersData +from django.utils.deprecation import RemovedInDjango60Warning +from django.utils.functional import cached_property + + +class GenericForeignKey(FieldCacheMixin): + """ + Provide a generic many-to-one relation through the ``content_type`` and + ``object_id`` fields. + + This class also doubles as an accessor to the related object (similar to + ForwardManyToOneDescriptor) by adding itself as a model attribute. + """ + + # Field flags + auto_created = False + concrete = False + editable = False + hidden = False + + is_relation = True + many_to_many = False + many_to_one = True + one_to_many = False + one_to_one = False + related_model = None + remote_field = None + + def __init__( + self, ct_field="content_type", fk_field="object_id", for_concrete_model=True + ): + self.ct_field = ct_field + self.fk_field = fk_field + self.for_concrete_model = for_concrete_model + self.editable = False + self.rel = None + self.column = None + + def contribute_to_class(self, cls, name, **kwargs): + self.name = name + self.model = cls + cls._meta.add_field(self, private=True) + setattr(cls, name, self) + + def get_filter_kwargs_for_object(self, obj): + """See corresponding method on Field""" + return { + self.fk_field: getattr(obj, self.fk_field), + self.ct_field: getattr(obj, self.ct_field), + } + + def get_forward_related_filter(self, obj): + """See corresponding method on RelatedField""" + return { + self.fk_field: obj.pk, + self.ct_field: ContentType.objects.get_for_model(obj).pk, + } + + def __str__(self): + model = self.model + return "%s.%s" % (model._meta.label, self.name) + + def check(self, **kwargs): + return [ + *self._check_field_name(), + *self._check_object_id_field(), + *self._check_content_type_field(), + ] + + def _check_field_name(self): + if self.name.endswith("_"): + return [ + checks.Error( + "Field names must not end with an underscore.", + obj=self, + id="fields.E001", + ) + ] + else: + return [] + + def _check_object_id_field(self): + try: + self.model._meta.get_field(self.fk_field) + except FieldDoesNotExist: + return [ + checks.Error( + "The GenericForeignKey object ID references the " + "nonexistent field '%s'." % self.fk_field, + obj=self, + id="contenttypes.E001", + ) + ] + else: + return [] + + def _check_content_type_field(self): + """ + Check if field named `field_name` in model `model` exists and is a + valid content_type field (is a ForeignKey to ContentType). + """ + try: + field = self.model._meta.get_field(self.ct_field) + except FieldDoesNotExist: + return [ + checks.Error( + "The GenericForeignKey content type references the " + "nonexistent field '%s.%s'." + % (self.model._meta.object_name, self.ct_field), + obj=self, + id="contenttypes.E002", + ) + ] + else: + if not isinstance(field, models.ForeignKey): + return [ + checks.Error( + "'%s.%s' is not a ForeignKey." + % (self.model._meta.object_name, self.ct_field), + hint=( + "GenericForeignKeys must use a ForeignKey to " + "'contenttypes.ContentType' as the 'content_type' field." + ), + obj=self, + id="contenttypes.E003", + ) + ] + elif field.remote_field.model != ContentType: + return [ + checks.Error( + "'%s.%s' is not a ForeignKey to 'contenttypes.ContentType'." + % (self.model._meta.object_name, self.ct_field), + hint=( + "GenericForeignKeys must use a ForeignKey to " + "'contenttypes.ContentType' as the 'content_type' field." + ), + obj=self, + id="contenttypes.E004", + ) + ] + else: + return [] + + def get_cache_name(self): + return self.name + + def get_content_type(self, obj=None, id=None, using=None, model=None): + if obj is not None: + return ContentType.objects.db_manager(obj._state.db).get_for_model( + obj, for_concrete_model=self.for_concrete_model + ) + elif id is not None: + return ContentType.objects.db_manager(using).get_for_id(id) + elif model is not None: + return ContentType.objects.db_manager(using).get_for_model( + model, for_concrete_model=self.for_concrete_model + ) + else: + # This should never happen. I love comments like this, don't you? + raise Exception("Impossible arguments to GFK.get_content_type!") + + def get_prefetch_queryset(self, instances, queryset=None): + warnings.warn( + "get_prefetch_queryset() is deprecated. Use get_prefetch_querysets() " + "instead.", + RemovedInDjango60Warning, + stacklevel=2, + ) + if queryset is None: + return self.get_prefetch_querysets(instances) + return self.get_prefetch_querysets(instances, [queryset]) + + def get_prefetch_querysets(self, instances, querysets=None): + custom_queryset_dict = {} + if querysets is not None: + for queryset in querysets: + ct_id = self.get_content_type( + model=queryset.query.model, using=queryset.db + ).pk + if ct_id in custom_queryset_dict: + raise ValueError( + "Only one queryset is allowed for each content type." + ) + custom_queryset_dict[ct_id] = queryset + + # For efficiency, group the instances by content type and then do one + # query per model + fk_dict = defaultdict(set) + # We need one instance for each group in order to get the right db: + instance_dict = {} + ct_attname = self.model._meta.get_field(self.ct_field).get_attname() + for instance in instances: + # We avoid looking for values if either ct_id or fkey value is None + ct_id = getattr(instance, ct_attname) + if ct_id is not None: + fk_val = getattr(instance, self.fk_field) + if fk_val is not None: + fk_dict[ct_id].add(fk_val) + instance_dict[ct_id] = instance + + ret_val = [] + for ct_id, fkeys in fk_dict.items(): + if ct_id in custom_queryset_dict: + # Return values from the custom queryset, if provided. + ret_val.extend(custom_queryset_dict[ct_id].filter(pk__in=fkeys)) + else: + instance = instance_dict[ct_id] + ct = self.get_content_type(id=ct_id, using=instance._state.db) + ret_val.extend(ct.get_all_objects_for_this_type(pk__in=fkeys)) + + # For doing the join in Python, we have to match both the FK val and the + # content type, so we use a callable that returns a (fk, class) pair. + def gfk_key(obj): + ct_id = getattr(obj, ct_attname) + if ct_id is None: + return None + else: + model = self.get_content_type( + id=ct_id, using=obj._state.db + ).model_class() + return ( + model._meta.pk.get_prep_value(getattr(obj, self.fk_field)), + model, + ) + + return ( + ret_val, + lambda obj: (obj.pk, obj.__class__), + gfk_key, + True, + self.name, + False, + ) + + def __get__(self, instance, cls=None): + if instance is None: + return self + + # Don't use getattr(instance, self.ct_field) here because that might + # reload the same ContentType over and over (#5570). Instead, get the + # content type ID here, and later when the actual instance is needed, + # use ContentType.objects.get_for_id(), which has a global cache. + f = self.model._meta.get_field(self.ct_field) + ct_id = getattr(instance, f.get_attname(), None) + pk_val = getattr(instance, self.fk_field) + + rel_obj = self.get_cached_value(instance, default=None) + if rel_obj is None and self.is_cached(instance): + return rel_obj + if rel_obj is not None: + ct_match = ( + ct_id == self.get_content_type(obj=rel_obj, using=instance._state.db).id + ) + pk_match = ct_match and rel_obj._meta.pk.to_python(pk_val) == rel_obj.pk + if pk_match: + return rel_obj + else: + rel_obj = None + if ct_id is not None: + ct = self.get_content_type(id=ct_id, using=instance._state.db) + try: + rel_obj = ct.get_object_for_this_type(pk=pk_val) + except ObjectDoesNotExist: + pass + self.set_cached_value(instance, rel_obj) + return rel_obj + + def __set__(self, instance, value): + ct = None + fk = None + if value is not None: + ct = self.get_content_type(obj=value) + fk = value.pk + + setattr(instance, self.ct_field, ct) + setattr(instance, self.fk_field, fk) + self.set_cached_value(instance, value) + + +class GenericRel(ForeignObjectRel): + """ + Used by GenericRelation to store information about the relation. + """ + + def __init__( + self, + field, + to, + related_name=None, + related_query_name=None, + limit_choices_to=None, + ): + super().__init__( + field, + to, + related_name=related_query_name or "+", + related_query_name=related_query_name, + limit_choices_to=limit_choices_to, + on_delete=DO_NOTHING, + ) + + +class GenericRelation(ForeignObject): + """ + Provide a reverse to a relation created by a GenericForeignKey. + """ + + # Field flags + auto_created = False + empty_strings_allowed = False + + many_to_many = False + many_to_one = False + one_to_many = True + one_to_one = False + + rel_class = GenericRel + + mti_inherited = False + + def __init__( + self, + to, + object_id_field="object_id", + content_type_field="content_type", + for_concrete_model=True, + related_query_name=None, + limit_choices_to=None, + **kwargs, + ): + kwargs["rel"] = self.rel_class( + self, + to, + related_query_name=related_query_name, + limit_choices_to=limit_choices_to, + ) + + # Reverse relations are always nullable (Django can't enforce that a + # foreign key on the related model points to this model). + kwargs["null"] = True + kwargs["blank"] = True + kwargs["on_delete"] = models.CASCADE + kwargs["editable"] = False + kwargs["serialize"] = False + + # This construct is somewhat of an abuse of ForeignObject. This field + # represents a relation from pk to object_id field. But, this relation + # isn't direct, the join is generated reverse along foreign key. So, + # the from_field is object_id field, to_field is pk because of the + # reverse join. + super().__init__(to, from_fields=[object_id_field], to_fields=[], **kwargs) + + self.object_id_field_name = object_id_field + self.content_type_field_name = content_type_field + self.for_concrete_model = for_concrete_model + + def check(self, **kwargs): + return [ + *super().check(**kwargs), + *self._check_generic_foreign_key_existence(), + ] + + def _is_matching_generic_foreign_key(self, field): + """ + Return True if field is a GenericForeignKey whose content type and + object id fields correspond to the equivalent attributes on this + GenericRelation. + """ + return ( + isinstance(field, GenericForeignKey) + and field.ct_field == self.content_type_field_name + and field.fk_field == self.object_id_field_name + ) + + def _check_generic_foreign_key_existence(self): + target = self.remote_field.model + if isinstance(target, ModelBase): + fields = target._meta.private_fields + if any(self._is_matching_generic_foreign_key(field) for field in fields): + return [] + else: + return [ + checks.Error( + "The GenericRelation defines a relation with the model " + "'%s', but that model does not have a GenericForeignKey." + % target._meta.label, + obj=self, + id="contenttypes.E004", + ) + ] + else: + return [] + + def resolve_related_fields(self): + self.to_fields = [self.model._meta.pk.name] + return [ + ( + self.remote_field.model._meta.get_field(self.object_id_field_name), + self.model._meta.pk, + ) + ] + + def _get_path_info_with_parent(self, filtered_relation): + """ + Return the path that joins the current model through any parent models. + The idea is that if you have a GFK defined on a parent model then we + need to join the parent model first, then the child model. + """ + # With an inheritance chain ChildTag -> Tag and Tag defines the + # GenericForeignKey, and a TaggedItem model has a GenericRelation to + # ChildTag, then we need to generate a join from TaggedItem to Tag + # (as Tag.object_id == TaggedItem.pk), and another join from Tag to + # ChildTag (as that is where the relation is to). Do this by first + # generating a join to the parent model, then generating joins to the + # child models. + path = [] + opts = self.remote_field.model._meta.concrete_model._meta + parent_opts = opts.get_field(self.object_id_field_name).model._meta + target = parent_opts.pk + path.append( + PathInfo( + from_opts=self.model._meta, + to_opts=parent_opts, + target_fields=(target,), + join_field=self.remote_field, + m2m=True, + direct=False, + filtered_relation=filtered_relation, + ) + ) + # Collect joins needed for the parent -> child chain. This is easiest + # to do if we collect joins for the child -> parent chain and then + # reverse the direction (call to reverse() and use of + # field.remote_field.get_path_info()). + parent_field_chain = [] + while parent_opts != opts: + field = opts.get_ancestor_link(parent_opts.model) + parent_field_chain.append(field) + opts = field.remote_field.model._meta + parent_field_chain.reverse() + for field in parent_field_chain: + path.extend(field.remote_field.path_infos) + return path + + def get_path_info(self, filtered_relation=None): + opts = self.remote_field.model._meta + object_id_field = opts.get_field(self.object_id_field_name) + if object_id_field.model != opts.model: + return self._get_path_info_with_parent(filtered_relation) + else: + target = opts.pk + return [ + PathInfo( + from_opts=self.model._meta, + to_opts=opts, + target_fields=(target,), + join_field=self.remote_field, + m2m=True, + direct=False, + filtered_relation=filtered_relation, + ) + ] + + def get_reverse_path_info(self, filtered_relation=None): + opts = self.model._meta + from_opts = self.remote_field.model._meta + return [ + PathInfo( + from_opts=from_opts, + to_opts=opts, + target_fields=(opts.pk,), + join_field=self, + m2m=False, + direct=False, + filtered_relation=filtered_relation, + ) + ] + + def value_to_string(self, obj): + qs = getattr(obj, self.name).all() + return str([instance.pk for instance in qs]) + + def contribute_to_class(self, cls, name, **kwargs): + kwargs["private_only"] = True + super().contribute_to_class(cls, name, **kwargs) + self.model = cls + # Disable the reverse relation for fields inherited by subclasses of a + # model in multi-table inheritance. The reverse relation points to the + # field of the base model. + if self.mti_inherited: + self.remote_field.related_name = "+" + self.remote_field.related_query_name = None + setattr(cls, self.name, ReverseGenericManyToOneDescriptor(self.remote_field)) + + # Add get_RELATED_order() and set_RELATED_order() to the model this + # field belongs to, if the model on the other end of this relation + # is ordered with respect to its corresponding GenericForeignKey. + if not cls._meta.abstract: + + def make_generic_foreign_order_accessors(related_model, model): + if self._is_matching_generic_foreign_key( + model._meta.order_with_respect_to + ): + make_foreign_order_accessors(model, related_model) + + lazy_related_operation( + make_generic_foreign_order_accessors, + self.model, + self.remote_field.model, + ) + + def set_attributes_from_rel(self): + pass + + def get_internal_type(self): + return "ManyToManyField" + + def get_content_type(self): + """ + Return the content type associated with this field's model. + """ + return ContentType.objects.get_for_model( + self.model, for_concrete_model=self.for_concrete_model + ) + + def get_extra_restriction(self, alias, remote_alias): + field = self.remote_field.model._meta.get_field(self.content_type_field_name) + contenttype_pk = self.get_content_type().pk + lookup = field.get_lookup("exact")(field.get_col(remote_alias), contenttype_pk) + return WhereNode([lookup], connector=AND) + + def bulk_related_objects(self, objs, using=DEFAULT_DB_ALIAS): + """ + Return all objects related to ``objs`` via this ``GenericRelation``. + """ + return self.remote_field.model._base_manager.db_manager(using).filter( + **{ + "%s__pk" + % self.content_type_field_name: ContentType.objects.db_manager(using) + .get_for_model(self.model, for_concrete_model=self.for_concrete_model) + .pk, + "%s__in" % self.object_id_field_name: [obj.pk for obj in objs], + } + ) + + +class ReverseGenericManyToOneDescriptor(ReverseManyToOneDescriptor): + """ + Accessor to the related objects manager on the one-to-many relation created + by GenericRelation. + + In the example:: + + class Post(Model): + comments = GenericRelation(Comment) + + ``post.comments`` is a ReverseGenericManyToOneDescriptor instance. + """ + + @cached_property + def related_manager_cls(self): + return create_generic_related_manager( + self.rel.model._default_manager.__class__, + self.rel, + ) + + +def create_generic_related_manager(superclass, rel): + """ + Factory function to create a manager that subclasses another manager + (generally the default manager of a given model) and adds behaviors + specific to generic relations. + """ + + class GenericRelatedObjectManager(superclass, AltersData): + def __init__(self, instance=None): + super().__init__() + + self.instance = instance + + self.model = rel.model + self.get_content_type = functools.partial( + ContentType.objects.db_manager(instance._state.db).get_for_model, + for_concrete_model=rel.field.for_concrete_model, + ) + self.content_type = self.get_content_type(instance) + self.content_type_field_name = rel.field.content_type_field_name + self.object_id_field_name = rel.field.object_id_field_name + self.prefetch_cache_name = rel.field.attname + self.pk_val = instance.pk + + self.core_filters = { + "%s__pk" % self.content_type_field_name: self.content_type.id, + self.object_id_field_name: self.pk_val, + } + + def __call__(self, *, manager): + manager = getattr(self.model, manager) + manager_class = create_generic_related_manager(manager.__class__, rel) + return manager_class(instance=self.instance) + + do_not_call_in_templates = True + + def __str__(self): + return repr(self) + + def _apply_rel_filters(self, queryset): + """ + Filter the queryset for the instance this manager is bound to. + """ + db = self._db or router.db_for_read(self.model, instance=self.instance) + return queryset.using(db).filter(**self.core_filters) + + def _remove_prefetched_objects(self): + try: + self.instance._prefetched_objects_cache.pop(self.prefetch_cache_name) + except (AttributeError, KeyError): + pass # nothing to clear from cache + + def get_queryset(self): + try: + return self.instance._prefetched_objects_cache[self.prefetch_cache_name] + except (AttributeError, KeyError): + queryset = super().get_queryset() + return self._apply_rel_filters(queryset) + + def get_prefetch_queryset(self, instances, queryset=None): + warnings.warn( + "get_prefetch_queryset() is deprecated. Use get_prefetch_querysets() " + "instead.", + RemovedInDjango60Warning, + stacklevel=2, + ) + if queryset is None: + return self.get_prefetch_querysets(instances) + return self.get_prefetch_querysets(instances, [queryset]) + + def get_prefetch_querysets(self, instances, querysets=None): + if querysets and len(querysets) != 1: + raise ValueError( + "querysets argument of get_prefetch_querysets() should have a " + "length of 1." + ) + queryset = querysets[0] if querysets else super().get_queryset() + queryset._add_hints(instance=instances[0]) + queryset = queryset.using(queryset._db or self._db) + # Group instances by content types. + content_type_queries = [ + models.Q.create( + [ + (f"{self.content_type_field_name}__pk", content_type_id), + (f"{self.object_id_field_name}__in", {obj.pk for obj in objs}), + ] + ) + for content_type_id, objs in itertools.groupby( + sorted(instances, key=lambda obj: self.get_content_type(obj).pk), + lambda obj: self.get_content_type(obj).pk, + ) + ] + query = models.Q.create(content_type_queries, connector=models.Q.OR) + # We (possibly) need to convert object IDs to the type of the + # instances' PK in order to match up instances: + object_id_converter = instances[0]._meta.pk.to_python + content_type_id_field_name = "%s_id" % self.content_type_field_name + return ( + queryset.filter(query), + lambda relobj: ( + object_id_converter(getattr(relobj, self.object_id_field_name)), + getattr(relobj, content_type_id_field_name), + ), + lambda obj: (obj.pk, self.get_content_type(obj).pk), + False, + self.prefetch_cache_name, + False, + ) + + def add(self, *objs, bulk=True): + self._remove_prefetched_objects() + db = router.db_for_write(self.model, instance=self.instance) + + def check_and_update_obj(obj): + if not isinstance(obj, self.model): + raise TypeError( + "'%s' instance expected, got %r" + % (self.model._meta.object_name, obj) + ) + setattr(obj, self.content_type_field_name, self.content_type) + setattr(obj, self.object_id_field_name, self.pk_val) + + if bulk: + pks = [] + for obj in objs: + if obj._state.adding or obj._state.db != db: + raise ValueError( + "%r instance isn't saved. Use bulk=False or save " + "the object first." % obj + ) + check_and_update_obj(obj) + pks.append(obj.pk) + + self.model._base_manager.using(db).filter(pk__in=pks).update( + **{ + self.content_type_field_name: self.content_type, + self.object_id_field_name: self.pk_val, + } + ) + else: + with transaction.atomic(using=db, savepoint=False): + for obj in objs: + check_and_update_obj(obj) + obj.save() + + add.alters_data = True + + async def aadd(self, *objs, bulk=True): + return await sync_to_async(self.add)(*objs, bulk=bulk) + + aadd.alters_data = True + + def remove(self, *objs, bulk=True): + if not objs: + return + self._clear(self.filter(pk__in=[o.pk for o in objs]), bulk) + + remove.alters_data = True + + async def aremove(self, *objs, bulk=True): + return await sync_to_async(self.remove)(*objs, bulk=bulk) + + aremove.alters_data = True + + def clear(self, *, bulk=True): + self._clear(self, bulk) + + clear.alters_data = True + + async def aclear(self, *, bulk=True): + return await sync_to_async(self.clear)(bulk=bulk) + + aclear.alters_data = True + + def _clear(self, queryset, bulk): + self._remove_prefetched_objects() + db = router.db_for_write(self.model, instance=self.instance) + queryset = queryset.using(db) + if bulk: + # `QuerySet.delete()` creates its own atomic block which + # contains the `pre_delete` and `post_delete` signal handlers. + queryset.delete() + else: + with transaction.atomic(using=db, savepoint=False): + for obj in queryset: + obj.delete() + + _clear.alters_data = True + + def set(self, objs, *, bulk=True, clear=False): + # Force evaluation of `objs` in case it's a queryset whose value + # could be affected by `manager.clear()`. Refs #19816. + objs = tuple(objs) + + db = router.db_for_write(self.model, instance=self.instance) + with transaction.atomic(using=db, savepoint=False): + if clear: + self.clear() + self.add(*objs, bulk=bulk) + else: + old_objs = set(self.using(db).all()) + new_objs = [] + for obj in objs: + if obj in old_objs: + old_objs.remove(obj) + else: + new_objs.append(obj) + + self.remove(*old_objs) + self.add(*new_objs, bulk=bulk) + + set.alters_data = True + + async def aset(self, objs, *, bulk=True, clear=False): + return await sync_to_async(self.set)(objs, bulk=bulk, clear=clear) + + aset.alters_data = True + + def create(self, **kwargs): + self._remove_prefetched_objects() + kwargs[self.content_type_field_name] = self.content_type + kwargs[self.object_id_field_name] = self.pk_val + db = router.db_for_write(self.model, instance=self.instance) + return super().using(db).create(**kwargs) + + create.alters_data = True + + async def acreate(self, **kwargs): + return await sync_to_async(self.create)(**kwargs) + + acreate.alters_data = True + + def get_or_create(self, **kwargs): + kwargs[self.content_type_field_name] = self.content_type + kwargs[self.object_id_field_name] = self.pk_val + db = router.db_for_write(self.model, instance=self.instance) + return super().using(db).get_or_create(**kwargs) + + get_or_create.alters_data = True + + async def aget_or_create(self, **kwargs): + return await sync_to_async(self.get_or_create)(**kwargs) + + aget_or_create.alters_data = True + + def update_or_create(self, **kwargs): + kwargs[self.content_type_field_name] = self.content_type + kwargs[self.object_id_field_name] = self.pk_val + db = router.db_for_write(self.model, instance=self.instance) + return super().using(db).update_or_create(**kwargs) + + update_or_create.alters_data = True + + async def aupdate_or_create(self, **kwargs): + return await sync_to_async(self.update_or_create)(**kwargs) + + aupdate_or_create.alters_data = True + + return GenericRelatedObjectManager diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/forms.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/forms.py new file mode 100644 index 0000000..c0ff4f7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/forms.py @@ -0,0 +1,133 @@ +from django.contrib.contenttypes.models import ContentType +from django.db import models +from django.forms import ModelForm, modelformset_factory +from django.forms.models import BaseModelFormSet + + +class BaseGenericInlineFormSet(BaseModelFormSet): + """ + A formset for generic inline objects to a parent. + """ + + def __init__( + self, + data=None, + files=None, + instance=None, + save_as_new=False, + prefix=None, + queryset=None, + **kwargs, + ): + opts = self.model._meta + self.instance = instance + self.rel_name = ( + opts.app_label + + "-" + + opts.model_name + + "-" + + self.ct_field.name + + "-" + + self.ct_fk_field.name + ) + self.save_as_new = save_as_new + if self.instance is None or self.instance.pk is None: + qs = self.model._default_manager.none() + else: + if queryset is None: + queryset = self.model._default_manager + qs = queryset.filter( + **{ + self.ct_field.name: ContentType.objects.get_for_model( + self.instance, for_concrete_model=self.for_concrete_model + ), + self.ct_fk_field.name: self.instance.pk, + } + ) + super().__init__(queryset=qs, data=data, files=files, prefix=prefix, **kwargs) + + def initial_form_count(self): + if self.save_as_new: + return 0 + return super().initial_form_count() + + @classmethod + def get_default_prefix(cls): + opts = cls.model._meta + return ( + opts.app_label + + "-" + + opts.model_name + + "-" + + cls.ct_field.name + + "-" + + cls.ct_fk_field.name + ) + + def save_new(self, form, commit=True): + setattr( + form.instance, + self.ct_field.get_attname(), + ContentType.objects.get_for_model(self.instance).pk, + ) + setattr(form.instance, self.ct_fk_field.get_attname(), self.instance.pk) + return form.save(commit=commit) + + +def generic_inlineformset_factory( + model, + form=ModelForm, + formset=BaseGenericInlineFormSet, + ct_field="content_type", + fk_field="object_id", + fields=None, + exclude=None, + extra=3, + can_order=False, + can_delete=True, + max_num=None, + formfield_callback=None, + validate_max=False, + for_concrete_model=True, + min_num=None, + validate_min=False, + absolute_max=None, + can_delete_extra=True, +): + """ + Return a ``GenericInlineFormSet`` for the given kwargs. + + You must provide ``ct_field`` and ``fk_field`` if they are different from + the defaults ``content_type`` and ``object_id`` respectively. + """ + opts = model._meta + # if there is no field called `ct_field` let the exception propagate + ct_field = opts.get_field(ct_field) + if ( + not isinstance(ct_field, models.ForeignKey) + or ct_field.remote_field.model != ContentType + ): + raise Exception("fk_name '%s' is not a ForeignKey to ContentType" % ct_field) + fk_field = opts.get_field(fk_field) # let the exception propagate + exclude = [*(exclude or []), ct_field.name, fk_field.name] + FormSet = modelformset_factory( + model, + form=form, + formfield_callback=formfield_callback, + formset=formset, + extra=extra, + can_delete=can_delete, + can_order=can_order, + fields=fields, + exclude=exclude, + max_num=max_num, + validate_max=validate_max, + min_num=min_num, + validate_min=validate_min, + absolute_max=absolute_max, + can_delete_extra=can_delete_extra, + ) + FormSet.ct_field = ct_field + FormSet.ct_fk_field = fk_field + FormSet.for_concrete_model = for_concrete_model + return FormSet diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/af/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/af/LC_MESSAGES/django.mo new file mode 100644 index 0000000..69309f8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/af/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/af/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/af/LC_MESSAGES/django.po new file mode 100644 index 0000000..84dfccf --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/af/LC_MESSAGES/django.po @@ -0,0 +1,42 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# F Wolff , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2019-01-04 18:49+0000\n" +"Last-Translator: F Wolff \n" +"Language-Team: Afrikaans (http://www.transifex.com/django/django/language/" +"af/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: af\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Inhoudtipes" + +msgid "python model class name" +msgstr "python-modelklasnaam" + +msgid "content type" +msgstr "inhoudtipe" + +msgid "content types" +msgstr "inhoudtipes" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Inhoudtipe %(ct_id)s-objek het geen geassosieerde model nie" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "Inhoudtipe %(ct_id)s-objek %(obj_id)s bestaan nie" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "%(ct_name)s-objekte het nie 'n get_absolute_url()-metode nie" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ar/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ar/LC_MESSAGES/django.mo new file mode 100644 index 0000000..612d4a0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ar/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ar/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ar/LC_MESSAGES/django.po new file mode 100644 index 0000000..afebdd7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ar/LC_MESSAGES/django.po @@ -0,0 +1,46 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bashar Al-Abdulhadi, 2014 +# Jannis Leidel , 2011 +# AlMeer , 2014 +# Muaaz Alsaied, 2020 +# صفا الفليج , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-04-06 19:57+0000\n" +"Last-Translator: صفا الفليج \n" +"Language-Team: Arabic (http://www.transifex.com/django/django/language/ar/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +msgid "Content Types" +msgstr "أنواع المحتوى" + +msgid "python model class name" +msgstr "اسم صنف النموذج في بايثون" + +msgid "content type" +msgstr "نوع المحتوى" + +msgid "content types" +msgstr "أنواع المحتوى" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "ليس لكائن نوع المحتوى %(ct_id)s أيّ نموذج مرتبط" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "كائن نوع المحتوى %(ct_id)s بالمعرّف %(obj_id)s غير موجود" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "ليس لكائنات %(ct_name)s الدالة التابِعة get_absolute_url()‎" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ar_DZ/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ar_DZ/LC_MESSAGES/django.mo new file mode 100644 index 0000000..fc230ca Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ar_DZ/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ar_DZ/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ar_DZ/LC_MESSAGES/django.po new file mode 100644 index 0000000..276a4d4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ar_DZ/LC_MESSAGES/django.po @@ -0,0 +1,43 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Riterix , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-12-14 18:35+0000\n" +"Last-Translator: Riterix \n" +"Language-Team: Arabic (Algeria) (http://www.transifex.com/django/django/" +"language/ar_DZ/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar_DZ\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +msgid "Content Types" +msgstr "نوع المحتوى" + +msgid "python model class name" +msgstr "اسم صنف النموذج في python" + +msgid "content type" +msgstr "نوع البيانات" + +msgid "content types" +msgstr "أنواع البيانات" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "لا يوجد كائن مرتبط بنوع البيانات %(ct_id)s ." + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "نوع المحتوى %(ct_id)s الكائن %(obj_id)s غير موجود" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "%(ct_name)s كائن لا يحتوي على دالة get_absolute_url() ." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ast/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ast/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a91316d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ast/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ast/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ast/LC_MESSAGES/django.po new file mode 100644 index 0000000..9e00e7b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ast/LC_MESSAGES/django.po @@ -0,0 +1,42 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ḷḷumex03 , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-20 02:41+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Asturian (http://www.transifex.com/django/django/language/" +"ast/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ast\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "" + +msgid "python model class name" +msgstr "nome de modelu de clas python" + +msgid "content type" +msgstr "triba de conteníu" + +msgid "content types" +msgstr "tribes de conteníu" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/az/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/az/LC_MESSAGES/django.mo new file mode 100644 index 0000000..cac6053 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/az/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/az/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/az/LC_MESSAGES/django.po new file mode 100644 index 0000000..993c107 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/az/LC_MESSAGES/django.po @@ -0,0 +1,44 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ali Ismayilov , 2011 +# Emin Mastizada , 2020 +# Emin Mastizada , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-01-12 07:28+0000\n" +"Last-Translator: Emin Mastizada \n" +"Language-Team: Azerbaijani (http://www.transifex.com/django/django/language/" +"az/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: az\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Məzmun Növləri" + +msgid "python model class name" +msgstr "python modelinin sinif (class) adı" + +msgid "content type" +msgstr "məzmun tipi" + +msgid "content types" +msgstr "məzmun tipləri" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "%(ct_id)s Məzmun növü obyektinə bağlı model yoxdur" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "%(ct_id)s məzmun növlü %(obj_id)s obyekti mövcut deyil" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "%(ct_name)s obyektlərinin get_absolute_url() metodu yoxdur" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/be/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/be/LC_MESSAGES/django.mo new file mode 100644 index 0000000..6ffe799 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/be/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/be/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/be/LC_MESSAGES/django.po new file mode 100644 index 0000000..1b869da --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/be/LC_MESSAGES/django.po @@ -0,0 +1,45 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Viktar Palstsiuk , 2015 +# znotdead , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-10-16 18:24+0000\n" +"Last-Translator: znotdead \n" +"Language-Team: Belarusian (http://www.transifex.com/django/django/language/" +"be/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: be\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n" +"%100>=11 && n%100<=14)? 2 : 3);\n" + +msgid "Content Types" +msgstr "Тыпы кантэнту" + +msgid "python model class name" +msgstr "назва клясы пітонавае мадэлі" + +msgid "content type" +msgstr "від зьмесьціва" + +msgid "content types" +msgstr "віды зьмесьціва" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Аб’ект са зьмесьцівам віду %(ct_id)s не зьвязалі з мадэльлю" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Аб’ект %(obj_id)s са зьмесьцівам віду %(ct_id)s не існуе" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "Аб’екты %(ct_name)s ня маюць спосабу «get_absolute_url()»" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/bg/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/bg/LC_MESSAGES/django.mo new file mode 100644 index 0000000..20e9b66 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/bg/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/bg/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/bg/LC_MESSAGES/django.po new file mode 100644 index 0000000..9169509 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/bg/LC_MESSAGES/django.po @@ -0,0 +1,46 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# arneatec , 2022 +# Boris Chervenkov , 2012 +# Georgi Kostadinov , 2012 +# Jannis Leidel , 2011 +# vestimir , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2022-01-13 18:20+0000\n" +"Last-Translator: arneatec \n" +"Language-Team: Bulgarian (http://www.transifex.com/django/django/language/" +"bg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Типове съдържание" + +msgid "python model class name" +msgstr "име на класа на модела в Python" + +msgid "content type" +msgstr "тип на съдържанието" + +msgid "content types" +msgstr "типове съдържание" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Обект с тип на съдържанието %(ct_id)s няма асоцииран модел." + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Обект %(obj_id)s с тип на съдържанието %(ct_id)s не съществува." + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "%(ct_name)s обекти нямат метода get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/bn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/bn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4a2a89a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/bn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/bn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/bn/LC_MESSAGES/django.po new file mode 100644 index 0000000..01f8cb1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/bn/LC_MESSAGES/django.po @@ -0,0 +1,43 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Tahmid Rafi , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Tahmid Rafi \n" +"Language-Team: Bengali (http://www.transifex.com/django/django/language/" +"bn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "কনটেন্ট টাইপসমূহ" + +msgid "python model class name" +msgstr "পাইথন মডেল ক্লাসের নাম" + +msgid "content type" +msgstr "কনটেন্ট টাইপ" + +msgid "content types" +msgstr "কনটেন্ট টাইপ সমূহ" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "কনটেন্ট টাইপ %(ct_id)s অবজেক্টের সাথে সংযুক্ত কোনো মডেল নেই" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "%(ct_name)s অবজেক্টের কোনো get_absolute_url() মেথড নেই" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/br/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/br/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ebb4b38 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/br/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/br/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/br/LC_MESSAGES/django.po new file mode 100644 index 0000000..15a3dfd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/br/LC_MESSAGES/django.po @@ -0,0 +1,45 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Irriep Nala Novram , 2018-2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2019-03-12 14:31+0000\n" +"Last-Translator: Irriep Nala Novram \n" +"Language-Team: Breton (http://www.transifex.com/django/django/language/br/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: br\n" +"Plural-Forms: nplurals=5; plural=((n%10 == 1) && (n%100 != 11) && (n%100 !" +"=71) && (n%100 !=91) ? 0 :(n%10 == 2) && (n%100 != 12) && (n%100 !=72) && (n" +"%100 !=92) ? 1 :(n%10 ==3 || n%10==4 || n%10==9) && (n%100 < 10 || n% 100 > " +"19) && (n%100 < 70 || n%100 > 79) && (n%100 < 90 || n%100 > 99) ? 2 :(n != 0 " +"&& n % 1000000 == 0) ? 3 : 4);\n" + +msgid "Content Types" +msgstr "Doareoù endalc'had" + +msgid "python model class name" +msgstr "anv klas model python" + +msgid "content type" +msgstr "doare endalc'had" + +msgid "content types" +msgstr "doareoù endalc'had" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Doare endalc'had an objed %(ct_id)s n'eus tamm skouer kevelet gantañ" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "Doare endalc'had %(ct_id)s an objed %(obj_id)s n'eus ket anezhañ" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "An objedoù %(ct_name)s n'o deus ket un hentenn get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/bs/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/bs/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8206fb8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/bs/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/bs/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/bs/LC_MESSAGES/django.po new file mode 100644 index 0000000..d8a69a5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/bs/LC_MESSAGES/django.po @@ -0,0 +1,43 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Bosnian (http://www.transifex.com/django/django/language/" +"bs/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bs\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Content Types" +msgstr "" + +msgid "python model class name" +msgstr "ime python klase modela" + +msgid "content type" +msgstr "tip sadržaja" + +msgid "content types" +msgstr "tipovi sadržaja" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ca/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ca/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2a67471 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ca/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ca/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ca/LC_MESSAGES/django.po new file mode 100644 index 0000000..5d6f7f3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ca/LC_MESSAGES/django.po @@ -0,0 +1,44 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Carles Barrobés , 2012,2014 +# Jannis Leidel , 2011 +# Manel Clos , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-04-28 20:05+0000\n" +"Last-Translator: Manel Clos \n" +"Language-Team: Catalan (http://www.transifex.com/django/django/language/" +"ca/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ca\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Tipus de Contingut" + +msgid "python model class name" +msgstr "nom de la classe del model en python" + +msgid "content type" +msgstr "tipus de contingut" + +msgid "content types" +msgstr "tipus de continguts" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "L'objecte del tipus de contingut %(ct_id)s no té un model associat" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "L'objecte %(obj_id)s del tipus de contingut %(ct_id)s no existeix" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "Els objectes %(ct_name)s no tenen el mètode get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ckb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ckb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..866e8ed Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ckb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ckb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ckb/LC_MESSAGES/django.po new file mode 100644 index 0000000..6bd611d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ckb/LC_MESSAGES/django.po @@ -0,0 +1,42 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Swara , 2022 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2023-04-24 19:22+0000\n" +"Last-Translator: Swara , 2022\n" +"Language-Team: Central Kurdish (http://www.transifex.com/django/django/" +"language/ckb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ckb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "جۆرەکانی ناوەڕۆک" + +msgid "python model class name" +msgstr "ناوی پۆلی مۆدێلی پایسۆن" + +msgid "content type" +msgstr "جۆری ناوەڕۆک" + +msgid "content types" +msgstr "جۆرەکانی ناوەڕۆک" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "ئۆبجێکی جۆری ناوەڕۆکی %(ct_id)s هیچ مۆدێلێکی پەیوەستکراوی نییە" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "جۆری ناوەڕۆکی %(ct_id)s ئۆبجێکتی %(obj_id)s بوونی نیە" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "ئۆبجێکتەکانی %(ct_name)s ڕێچکەی get_absolute_url() ی نیە" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/cs/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/cs/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f0ac28e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/cs/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/cs/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/cs/LC_MESSAGES/django.po new file mode 100644 index 0000000..d327a5e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/cs/LC_MESSAGES/django.po @@ -0,0 +1,44 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Vláďa Macek , 2012,2014 +# Vláďa Macek , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-09-19 09:23+0000\n" +"Last-Translator: Vláďa Macek \n" +"Language-Team: Czech (http://www.transifex.com/django/django/language/cs/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cs\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n " +"<= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n" + +msgid "Content Types" +msgstr "Typy obsahu" + +msgid "python model class name" +msgstr "název třídy modelu v Pythonu" + +msgid "content type" +msgstr "typ obsahu" + +msgid "content types" +msgstr "typy obsahu" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Typ obsahu %(ct_id)s nemá přidružený model." + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Objekt %(obj_id)s typu obsahu %(ct_id)s neexistuje." + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "Objektům typu %(ct_name)s chybí metoda get_absolute_url()." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/cy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/cy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d72e975 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/cy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/cy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/cy/LC_MESSAGES/django.po new file mode 100644 index 0000000..9b868d2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/cy/LC_MESSAGES/django.po @@ -0,0 +1,43 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Maredudd ap Gwyndaf , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Maredudd ap Gwyndaf \n" +"Language-Team: Welsh (http://www.transifex.com/django/django/language/cy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cy\n" +"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != " +"11) ? 2 : 3;\n" + +msgid "Content Types" +msgstr "Mathau Cynnwys" + +msgid "python model class name" +msgstr "end dosbarth model python" + +msgid "content type" +msgstr "math cynnwys" + +msgid "content types" +msgstr "mathau cynnwys" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Does dim model cysylltiedig gyda gwrthrych math cynnwys %(ct_id)s" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "Nid ydy gwrthrych %(obj_id)s math cynnwys %(ct_id)s yn bodoli" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "Does dim swyddogaeth get_absolute_url() gyda'r gwrthrych %(ct_name)s" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/da/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/da/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5f5511b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/da/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/da/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/da/LC_MESSAGES/django.po new file mode 100644 index 0000000..f10de28 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/da/LC_MESSAGES/django.po @@ -0,0 +1,43 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Erik Wognsen , 2014,2019 +# Jannis Leidel , 2011 +# Kristian Øllegaard , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-09-17 18:00+0000\n" +"Last-Translator: Erik Wognsen \n" +"Language-Team: Danish (http://www.transifex.com/django/django/language/da/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: da\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Indholdstyper" + +msgid "python model class name" +msgstr "klassenavn i Python-model" + +msgid "content type" +msgstr "indholdstype" + +msgid "content types" +msgstr "indholdstyper" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Indholdstype %(ct_id)s-objekt har ingen tilhørende model" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Indholdstype %(ct_id)s-objekt %(obj_id)s findes ikke" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr " %(ct_name)s-objekter har ikke en get_absolute_url()-metode" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/de/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/de/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c098e03 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/de/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/de/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/de/LC_MESSAGES/django.po new file mode 100644 index 0000000..8d50c70 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/de/LC_MESSAGES/django.po @@ -0,0 +1,42 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# André Hagenbruch, 2012 +# Jannis Leidel , 2011,2013-2014,2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-01-17 22:43+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: German (http://www.transifex.com/django/django/language/de/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Inhaltstypen" + +msgid "python model class name" +msgstr "Python Modell-Klassenname" + +msgid "content type" +msgstr "Inhaltstyp" + +msgid "content types" +msgstr "Inhaltstypen" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Objekt des Inhaltstyps %(ct_id)s hat kein dazugehöriges Modell" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Objekt %(obj_id)s des Inhaltstyps %(ct_id)s ist nicht vorhanden" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr " %(ct_name)s Objekte haben keine get_absolute_url ()-Methode" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/dsb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/dsb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3ecc064 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/dsb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/dsb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/dsb/LC_MESSAGES/django.po new file mode 100644 index 0000000..fa40165 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/dsb/LC_MESSAGES/django.po @@ -0,0 +1,43 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Michael Wolf , 2016,2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-02-25 16:03+0000\n" +"Last-Translator: Michael Wolf \n" +"Language-Team: Lower Sorbian (http://www.transifex.com/django/django/" +"language/dsb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: dsb\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" + +msgid "Content Types" +msgstr "Wopśimjeśowe typy" + +msgid "python model class name" +msgstr "klasowe mě pythonowe modela" + +msgid "content type" +msgstr "wopśimjeśowy typ" + +msgid "content types" +msgstr "wopśimjeśowe typy" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Objekt wopśimjeśowego typa %(ct_id)s njama zwězany model" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Objekt %(obj_id)s wopśimjeśowego typa %(ct_id)s njeeksistěrujo" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "Objekty %(ct_name)s njamaju metodu get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/el/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/el/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d49b9f6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/el/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/el/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/el/LC_MESSAGES/django.po new file mode 100644 index 0000000..fc107e8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/el/LC_MESSAGES/django.po @@ -0,0 +1,45 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Nikolas Demiridis , 2014 +# Pãnoș , 2014 +# Pãnoș , 2016,2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-05-04 07:05+0000\n" +"Last-Translator: Pãnoș \n" +"Language-Team: Greek (http://www.transifex.com/django/django/language/el/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: el\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Τύποι Περιεχομένου" + +msgid "python model class name" +msgstr "όνομα κλάσης μοντέλου python" + +msgid "content type" +msgstr "τύπος περιεχομένου" + +msgid "content types" +msgstr "τύποι περιεχομένου" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "" +"Το αντικείμενο %(ct_id)s τύπου περιεχομένου δεν έχει συσχετισμένο μοντέλο" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Το αντικείμενο %(obj_id)s τύπου περιεχομένου %(ct_id)s δεν υπάρχει" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "τα αντικείμενα %(ct_name)s δεν έχουν μέθοδο get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/en/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/en/LC_MESSAGES/django.mo new file mode 100644 index 0000000..08a7b68 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/en/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/en/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/en/LC_MESSAGES/django.po new file mode 100644 index 0000000..cee0237 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/en/LC_MESSAGES/django.po @@ -0,0 +1,45 @@ +# This file is distributed under the same license as the Django package. +# +msgid "" +msgstr "" +"Project-Id-Version: Django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2010-05-13 15:35+0200\n" +"Last-Translator: Django team\n" +"Language-Team: English \n" +"Language: en\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: contrib/contenttypes/apps.py:16 +msgid "Content Types" +msgstr "" + +#: contrib/contenttypes/models.py:135 +msgid "python model class name" +msgstr "" + +#: contrib/contenttypes/models.py:139 +msgid "content type" +msgstr "" + +#: contrib/contenttypes/models.py:140 +msgid "content types" +msgstr "" + +#: contrib/contenttypes/views.py:18 +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "" + +#: contrib/contenttypes/views.py:24 +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "" + +#: contrib/contenttypes/views.py:32 +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/en_AU/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/en_AU/LC_MESSAGES/django.mo new file mode 100644 index 0000000..fcc2fc5 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/en_AU/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/en_AU/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/en_AU/LC_MESSAGES/django.po new file mode 100644 index 0000000..19d5c16 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/en_AU/LC_MESSAGES/django.po @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:11+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: English (Australia) (http://www.transifex.com/projects/p/" +"django/language/en_AU/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_AU\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "" + +msgid "python model class name" +msgstr "" + +msgid "content type" +msgstr "" + +msgid "content types" +msgstr "" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/en_GB/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/en_GB/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f4b2043 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/en_GB/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/en_GB/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/en_GB/LC_MESSAGES/django.po new file mode 100644 index 0000000..7e385be --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/en_GB/LC_MESSAGES/django.po @@ -0,0 +1,43 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# jon_atkinson , 2011 +# Ross Poulton , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: English (United Kingdom) (http://www.transifex.com/django/" +"django/language/en_GB/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_GB\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "" + +msgid "python model class name" +msgstr "python model class name" + +msgid "content type" +msgstr "content type" + +msgid "content types" +msgstr "content types" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Content type %(ct_id)s object has no associated model" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "Content type %(ct_id)s object %(obj_id)s doesn't exist" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "%(ct_name)s objects don't have a get_absolute_url() method" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/eo/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/eo/LC_MESSAGES/django.mo new file mode 100644 index 0000000..152620e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/eo/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/eo/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/eo/LC_MESSAGES/django.po new file mode 100644 index 0000000..f64e0fa --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/eo/LC_MESSAGES/django.po @@ -0,0 +1,43 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Batist D 🐍 , 2014 +# Meiyer , 2022 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2022-04-24 19:22+0000\n" +"Last-Translator: Meiyer , 2022\n" +"Language-Team: Esperanto (http://www.transifex.com/django/django/language/" +"eo/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eo\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Enhavaj tipoj" + +msgid "python model class name" +msgstr "klasa nomo de pitona modelo" + +msgid "content type" +msgstr "enhava tipo" + +msgid "content types" +msgstr "enhavaj tipoj" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Objekto kun enhava tipo %(ct_id)s ne havas modelojn asociitajn kun ĝi" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Objekto %(obj_id)s kun enhava tipo %(ct_id)s ne ekzistas" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "Objektoj %(ct_name)s ne havas metodon get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5bdc5a2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es/LC_MESSAGES/django.po new file mode 100644 index 0000000..dd7398b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es/LC_MESSAGES/django.po @@ -0,0 +1,46 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Antoni Aloy , 2012 +# Jannis Leidel , 2011 +# Josue Naaman Nistal Guerra , 2014 +# Uriel Medina , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-09-25 17:13+0000\n" +"Last-Translator: Uriel Medina \n" +"Language-Team: Spanish (http://www.transifex.com/django/django/language/" +"es/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Tipos de contenido" + +msgid "python model class name" +msgstr "nombre de la clase modelo de python" + +msgid "content type" +msgstr "tipo de contenido" + +msgid "content types" +msgstr "tipos de contenido" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "" +"El objeto de tipo de contenido %(ct_id)s no tiene ningún modelo asociado." + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "El tipo de contenido %(ct_id)s del objeto %(obj_id)s no existe" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "%(ct_name)s objetos no tienen un método get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es_AR/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es_AR/LC_MESSAGES/django.mo new file mode 100644 index 0000000..12eec9c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es_AR/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es_AR/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es_AR/LC_MESSAGES/django.po new file mode 100644 index 0000000..d048560 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es_AR/LC_MESSAGES/django.po @@ -0,0 +1,43 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Ramiro Morales, 2012,2014-2015,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-10-01 10:21+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Spanish (Argentina) (http://www.transifex.com/django/django/" +"language/es_AR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_AR\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Tipos de Contenido" + +msgid "python model class name" +msgstr "nombre de la clase Python del modelo" + +msgid "content type" +msgstr "tipo de contenido" + +msgid "content types" +msgstr "tipos de contenido" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "El objeto Tipo de contenido %(ct_id)s no tiene un modelo asociado" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "El objeto Tipo de contenido %(ct_id)s %(obj_id)s no existe" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "Los objetos %(ct_name)s no tienen un método get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es_CO/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es_CO/LC_MESSAGES/django.mo new file mode 100644 index 0000000..66b7631 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es_CO/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es_CO/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es_CO/LC_MESSAGES/django.po new file mode 100644 index 0000000..e386b5c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es_CO/LC_MESSAGES/django.po @@ -0,0 +1,43 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Carlos Muñoz , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-20 03:01+0000\n" +"Last-Translator: Carlos Muñoz \n" +"Language-Team: Spanish (Colombia) (http://www.transifex.com/django/django/" +"language/es_CO/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_CO\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Tipos de contenido" + +msgid "python model class name" +msgstr "nombre de la clase modelo de python" + +msgid "content type" +msgstr "tipo de contenido" + +msgid "content types" +msgstr "tipos de contenido" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "" +"El objeto de tipo de contenido %(ct_id)s no tiene ningún modelo asociado." + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "El objeto de tipo de contenido %(ct_id)s objeto %(obj_id)s no existe" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "El objeto %(ct_name)s no tiene un método get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es_MX/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es_MX/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1361168 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es_MX/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es_MX/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es_MX/LC_MESSAGES/django.po new file mode 100644 index 0000000..905c9ea --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es_MX/LC_MESSAGES/django.po @@ -0,0 +1,44 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Abe Estrada, 2011-2012 +# Jesús Bautista , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-12-25 05:47+0000\n" +"Last-Translator: Jesús Bautista \n" +"Language-Team: Spanish (Mexico) (http://www.transifex.com/django/django/" +"language/es_MX/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_MX\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Tipos de Contenido" + +msgid "python model class name" +msgstr "nombre de la clase python del modelo" + +msgid "content type" +msgstr "tipo de contenido" + +msgid "content types" +msgstr "tipos de contenido" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "" +"Los objetos con el tipo de contenido %(ct_id)s no tienen un modelo asociado" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es_VE/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es_VE/LC_MESSAGES/django.mo new file mode 100644 index 0000000..78ad5f8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es_VE/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es_VE/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es_VE/LC_MESSAGES/django.po new file mode 100644 index 0000000..e86c178 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/es_VE/LC_MESSAGES/django.po @@ -0,0 +1,44 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Eduardo , 2017 +# Yoel Acevedo, 2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-20 03:01+0000\n" +"Last-Translator: Eduardo \n" +"Language-Team: Spanish (Venezuela) (http://www.transifex.com/django/django/" +"language/es_VE/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_VE\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Tipos de contenido" + +msgid "python model class name" +msgstr "nombre de la clase del modelo de python" + +msgid "content type" +msgstr "tipo de contenido" + +msgid "content types" +msgstr "tipos de contenido" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "" +"El objeto de tipo de contenido %(ct_id)s no tiene ningún modelo asociado" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "El objeto de tipo de contenido %(ct_id)s objeto %(obj_id)s no existe" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "El objeto %(ct_name)s no tiene un método get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/et/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/et/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e4ec019 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/et/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/et/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/et/LC_MESSAGES/django.po new file mode 100644 index 0000000..d90ea9a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/et/LC_MESSAGES/django.po @@ -0,0 +1,45 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Janno Liivak , 2013 +# Marti Raudsepp , 2014 +# Ragnar Rebase , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-12-28 01:46+0000\n" +"Last-Translator: Ragnar Rebase \n" +"Language-Team: Estonian (http://www.transifex.com/django/django/language/" +"et/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: et\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Sisutüübid" + +msgid "python model class name" +msgstr "pythoni mudeli klassinimi" + +msgid "content type" +msgstr "sisutüüp" + +msgid "content types" +msgstr "sisutüübid" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Sisutüübi %(ct_id)s objektil puudub seos mudeliga" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Sisutüübi %(ct_id)s objekti %(obj_id)s pole olemas" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "%(ct_name)s objektidel pole get_absolute_url() meetodit" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/eu/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/eu/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5883d06 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/eu/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/eu/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/eu/LC_MESSAGES/django.po new file mode 100644 index 0000000..07146e9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/eu/LC_MESSAGES/django.po @@ -0,0 +1,43 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Aitzol Naberan , 2012 +# Eneko Illarramendi , 2017 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Eneko Illarramendi \n" +"Language-Team: Basque (http://www.transifex.com/django/django/language/eu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Eduki Motak" + +msgid "python model class name" +msgstr "python model class izena" + +msgid "content type" +msgstr "eduki mota" + +msgid "content types" +msgstr "eduki motak" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "%(ct_id)s eduki motak ez dauka lotutako eredurik" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "%(ct_id)s eduki motako %(obj_id)s objekturik ez da existitzen" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "%(ct_name)s objektuek ez daukate get_absolute_url() metodorik" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/fa/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/fa/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c11cd46 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/fa/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/fa/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/fa/LC_MESSAGES/django.po new file mode 100644 index 0000000..f4bea17 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/fa/LC_MESSAGES/django.po @@ -0,0 +1,45 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ali Nikneshan , 2012 +# Jannis Leidel , 2011 +# rahim agh , 2020 +# Reza Mohammadi , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-05-27 09:31+0000\n" +"Last-Translator: rahim agh \n" +"Language-Team: Persian (http://www.transifex.com/django/django/language/" +"fa/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fa\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Content Types" +msgstr "نوع‌های محتوا" + +msgid "python model class name" +msgstr "نام پایتونی کلاس مدل" + +msgid "content type" +msgstr "نوع محتوا" + +msgid "content types" +msgstr "نوع‌های محتوا" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "نوع محتوای %(ct_id)s به هیچ مدلی مرتبط نشده است" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "شیء %(obj_id)s از نمونه محتوای %(ct_id)s وجود ندارد" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "شیء %(ct_name)s متد get_absolute_url() را ندارد" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/fi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/fi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..af15679 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/fi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/fi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/fi/LC_MESSAGES/django.po new file mode 100644 index 0000000..ea4db91 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/fi/LC_MESSAGES/django.po @@ -0,0 +1,44 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Aarni Koskela, 2015,2020 +# Jannis Leidel , 2011 +# Klaus Dahlén , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-12-09 06:31+0000\n" +"Last-Translator: Aarni Koskela\n" +"Language-Team: Finnish (http://www.transifex.com/django/django/language/" +"fi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Sisältötyypit" + +msgid "python model class name" +msgstr "mallin python-luokan nimi" + +msgid "content type" +msgstr "sisältötyyppi" + +msgid "content types" +msgstr "sisältötyypit" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Sisältötyypin %(ct_id)s objektiin ei ole liitetty mallia" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Sisältötyypin %(ct_id)s objektia %(obj_id)s ei ole olemassa" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "%(ct_name)s-objekteilla ei ole get_absolute_url()-metodia" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/fr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/fr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2de1e4a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/fr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/fr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 0000000..2f355d1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,43 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Claude Paroz , 2014,2019 +# Claude Paroz , 2012 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-09-18 15:50+0000\n" +"Last-Translator: Claude Paroz \n" +"Language-Team: French (http://www.transifex.com/django/django/language/fr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Content Types" +msgstr "Types de contenus" + +msgid "python model class name" +msgstr "nom de la classe python du modèle" + +msgid "content type" +msgstr "type de contenu" + +msgid "content types" +msgstr "types de contenu" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "L'objet type de contenu %(ct_id)s n'a pas de modèle associé" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "L'objet %(obj_id)s du type de contenu %(ct_id)s n’existe pas" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "Les objets %(ct_name)s n’ont pas de méthode get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/fy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/fy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..489bbab Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/fy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/fy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/fy/LC_MESSAGES/django.po new file mode 100644 index 0000000..6e549c3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/fy/LC_MESSAGES/django.po @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:13+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Western Frisian (http://www.transifex.com/projects/p/django/" +"language/fy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fy\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "" + +msgid "python model class name" +msgstr "" + +msgid "content type" +msgstr "" + +msgid "content types" +msgstr "" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ga/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ga/LC_MESSAGES/django.mo new file mode 100644 index 0000000..6b0363a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ga/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ga/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ga/LC_MESSAGES/django.po new file mode 100644 index 0000000..8641190 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ga/LC_MESSAGES/django.po @@ -0,0 +1,44 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Luke Blaney , 2019 +# Michael Thornhill , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2019-06-22 21:48+0000\n" +"Last-Translator: Luke Blaney \n" +"Language-Team: Irish (http://www.transifex.com/django/django/language/ga/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ga\n" +"Plural-Forms: nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : " +"4);\n" + +msgid "Content Types" +msgstr "Cineál Inneachair" + +msgid "python model class name" +msgstr "píotón samhail aicme ainm" + +msgid "content type" +msgstr "tíopa inneachar " + +msgid "content types" +msgstr "tíopaI inneachair" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Ní bhaineann samhail leis an cineál inneachar %(ct_id)s" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "Níl cineál inneachar %(ct_id)s oibiacht %(obj_id)s ann" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "Níl modh get_absolute_url() ag %(ct_name)s oibiachtaí" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/gd/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/gd/LC_MESSAGES/django.mo new file mode 100644 index 0000000..05d9baf Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/gd/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/gd/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/gd/LC_MESSAGES/django.po new file mode 100644 index 0000000..825730b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/gd/LC_MESSAGES/django.po @@ -0,0 +1,45 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# GunChleoc, 2015 +# GunChleoc, 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-12-13 12:51+0000\n" +"Last-Translator: GunChleoc\n" +"Language-Team: Gaelic, Scottish (http://www.transifex.com/django/django/" +"language/gd/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: gd\n" +"Plural-Forms: nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : " +"(n > 2 && n < 20) ? 2 : 3;\n" + +msgid "Content Types" +msgstr "Seòrsaichean susbainte" + +msgid "python model class name" +msgstr "ainm clas air modail python" + +msgid "content type" +msgstr "seòrsa susbainte" + +msgid "content types" +msgstr "seòrsaichean susbainte" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "" +"Chan eil modail co-cheangailte ris an oibseact le seòrsa susbaint %(ct_id)s" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Chan eil an oibseact %(obj_id)s le seòrsa susbaint %(ct_id)s ann" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "Chan eil am modh get_absolute_url() aig na h-oibseactan %(ct_name)s" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/gl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/gl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5ecd343 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/gl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/gl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/gl/LC_MESSAGES/django.po new file mode 100644 index 0000000..18f962e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/gl/LC_MESSAGES/django.po @@ -0,0 +1,45 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# fonso , 2013 +# Jannis Leidel , 2011 +# Leandro Regueiro , 2013 +# X Bello , 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2023-04-24 19:22+0000\n" +"Last-Translator: X Bello , 2023\n" +"Language-Team: Galician (http://www.transifex.com/django/django/language/" +"gl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: gl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Tipos de Contido" + +msgid "python model class name" +msgstr "nome en Python da clase do modelo" + +msgid "content type" +msgstr "tipo de contido" + +msgid "content types" +msgstr "tipos de contido" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "O obxecto de tipo de contido %(ct_id)s non ten un modelo asociado" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "O obxecto %(obj_id)s con tipo de contido %(ct_id)s non existe" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "Os obxectos %(ct_name)s non teñen un método get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/he/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/he/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0bcdcd3 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/he/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/he/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/he/LC_MESSAGES/django.po new file mode 100644 index 0000000..43bd82e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/he/LC_MESSAGES/django.po @@ -0,0 +1,43 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Meir Kriheli , 2012,2014,2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-08-02 13:30+0000\n" +"Last-Translator: Meir Kriheli \n" +"Language-Team: Hebrew (http://www.transifex.com/django/django/language/he/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: he\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % " +"1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;\n" + +msgid "Content Types" +msgstr "סוגי תוכן" + +msgid "python model class name" +msgstr "שם ה־class של מודל פייתון" + +msgid "content type" +msgstr "סוג תוכן" + +msgid "content types" +msgstr "סוגי תוכן" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "לא משוייך מודל לאובייקט מסוג התוכן %(ct_id)s" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "סוג תוכן %(ct_id)s אובייקט %(obj_id)s אינו קיים" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "אובייקטי %(ct_name)s אינם כוללים מתודת get_absolute_url()‎" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4af5d95 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hi/LC_MESSAGES/django.po new file mode 100644 index 0000000..aabdaf4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hi/LC_MESSAGES/django.po @@ -0,0 +1,42 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Chandan kumar , 2012 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Hindi (http://www.transifex.com/django/django/language/hi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "" + +msgid "python model class name" +msgstr "पैथॉन मॉडल क्लास नाम" + +msgid "content type" +msgstr "विषय-सूची प्रकार" + +msgid "content types" +msgstr "विषय-सूचियाँ प्रकार" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "सामग्री प्रकार के %(ct_id)s ऑब्जेक्ट कोई संबद्ध मॉडल नहीं है।" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "सामग्री प्रकार %(ct_id)s वस्तु %(obj_id)s मौजूद नहीं है." + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "%(ct_name)s वस्तुओं की get_absolute_url() विधि नहीं है." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1fa258e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hr/LC_MESSAGES/django.po new file mode 100644 index 0000000..8acf7e8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hr/LC_MESSAGES/django.po @@ -0,0 +1,45 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bojan Mihelač , 2012 +# Jannis Leidel , 2011 +# Mislav Cimperšak , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Mislav Cimperšak \n" +"Language-Team: Croatian (http://www.transifex.com/django/django/language/" +"hr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hr\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +msgid "Content Types" +msgstr "Tipovi sadržaja" + +msgid "python model class name" +msgstr "ime klase (class) python modela" + +msgid "content type" +msgstr "tip sadržaja" + +msgid "content types" +msgstr "tipovi sadržaja" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Tip sadržaja %(ct_id)s objekt nema pridruženi model" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "Tip sadržaja %(ct_id)s objekt %(obj_id)s ne postoji" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "%(ct_name)s objekti nemaju get_absolute_url() metodu" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hsb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hsb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..349357f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hsb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hsb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hsb/LC_MESSAGES/django.po new file mode 100644 index 0000000..a0f3feb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hsb/LC_MESSAGES/django.po @@ -0,0 +1,43 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Michael Wolf , 2016,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-09-21 19:25+0000\n" +"Last-Translator: Michael Wolf \n" +"Language-Team: Upper Sorbian (http://www.transifex.com/django/django/" +"language/hsb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hsb\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" + +msgid "Content Types" +msgstr "Wobsahowe typy" + +msgid "python model class name" +msgstr "klasowe mjeno pythonoweho modela" + +msgid "content type" +msgstr "wobsahowy typ" + +msgid "content types" +msgstr "wobsahowe typy" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Objekt wobsahoweho typa %(ct_id)s nima zwjazany model" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Objekt %(obj_id)s wobsahoweho typa %(ct_id)s njeeksistuje" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "Objekty %(ct_name)s nimaja metodu get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hu/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hu/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ece0a5e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hu/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hu/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hu/LC_MESSAGES/django.po new file mode 100644 index 0000000..7c4a800 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hu/LC_MESSAGES/django.po @@ -0,0 +1,46 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# András Veres-Szentkirályi, 2016 +# Attila Nagy <>, 2012 +# Istvan Farkas , 2019 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-11-18 09:29+0000\n" +"Last-Translator: Istvan Farkas \n" +"Language-Team: Hungarian (http://www.transifex.com/django/django/language/" +"hu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Tartalom típusok" + +msgid "python model class name" +msgstr "python modell osztály neve" + +msgid "content type" +msgstr "tartalom típusa" + +msgid "content types" +msgstr "tartalom típusok" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "A %(ct_id)s tartalomtípus-objektumhoz nincsenek modellek hozzárendelve" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "A(z) %(ct_id)s típusú %(obj_id)s objektum nem létezik" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "" +"%(ct_name)s objektumok esetén nincs beállítva a get_absolute_url() metódus." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a62ddff Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hy/LC_MESSAGES/django.po new file mode 100644 index 0000000..63b9e93 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/hy/LC_MESSAGES/django.po @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2018-11-01 20:28+0000\n" +"Last-Translator: Ruben Harutyunov \n" +"Language-Team: Armenian (http://www.transifex.com/django/django/language/" +"hy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hy\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Պարունակության տիպեր" + +msgid "python model class name" +msgstr "python մոդելի դասի անուն" + +msgid "content type" +msgstr "պարունակության տիպ" + +msgid "content types" +msgstr "պարունակության տիպեր" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Պարունակության տիպ %(ct_id)s օբյեկտը չունի իր հետ կապված մոդել" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "Պարունակության տիպ %(ct_id)s %(obj_id)s օբյեկտը գոյություն չունի" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "%(ct_name)s օբյեկտները չունեն get_absolute_url() մեթոդ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ia/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ia/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2eec9aa Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ia/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ia/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ia/LC_MESSAGES/django.po new file mode 100644 index 0000000..cf2a5e4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ia/LC_MESSAGES/django.po @@ -0,0 +1,42 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Martijn Dekker , 2012,2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2021-12-24 19:22+0000\n" +"Last-Translator: Martijn Dekker \n" +"Language-Team: Interlingua (http://www.transifex.com/django/django/language/" +"ia/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ia\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Typos de contento" + +msgid "python model class name" +msgstr "nomine del classe del modello Python" + +msgid "content type" +msgstr "typo de contento" + +msgid "content types" +msgstr "typos de contento" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Le objecto del typo de contento %(ct_id)s non ha un modello associate" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Le objecto %(obj_id)s del typo de contento %(ct_id)s non existe" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "Objectos %(ct_name)s non ha un methodo get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/id/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/id/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ea0373e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/id/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/id/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/id/LC_MESSAGES/django.po new file mode 100644 index 0000000..c6db9d4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/id/LC_MESSAGES/django.po @@ -0,0 +1,46 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Fery Setiawan , 2020 +# Jannis Leidel , 2011 +# M Asep Indrayana , 2015 +# rodin , 2011-2012 +# rodin , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-02-06 02:33+0000\n" +"Last-Translator: Fery Setiawan \n" +"Language-Team: Indonesian (http://www.transifex.com/django/django/language/" +"id/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: id\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Content Types" +msgstr "Jenis Konten" + +msgid "python model class name" +msgstr "nama kelas model python" + +msgid "content type" +msgstr "tipe konten" + +msgid "content types" +msgstr "tipe konten" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Tipe konten objek %(ct_id)s tidak memiliki model yang terkait" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Jenis isi %(ct_id)s object %(obj_id)s tidak ada" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "objek %(ct_name)s tidak memiliki metode get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/io/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/io/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0b6b123 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/io/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/io/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/io/LC_MESSAGES/django.po new file mode 100644 index 0000000..b70d8d6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/io/LC_MESSAGES/django.po @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Viko Bartero , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-20 01:58+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Ido (http://www.transifex.com/django/django/language/io/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: io\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "" + +msgid "python model class name" +msgstr "klaso nomo dil python modelo" + +msgid "content type" +msgstr "kontenajo tipo" + +msgid "content types" +msgstr "kontenajo tipi" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "La objekto kun kontenajo tipo %(ct_id)s ne havas relatita modelo" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "La objekto %(obj_id)s kun kontenajo tipo %(ct_id)s ne existas" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "La objekti %(ct_name)s ne havas get_absolute_url() metodo" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/is/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/is/LC_MESSAGES/django.mo new file mode 100644 index 0000000..97eb95c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/is/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/is/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/is/LC_MESSAGES/django.po new file mode 100644 index 0000000..a691279 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/is/LC_MESSAGES/django.po @@ -0,0 +1,44 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Hafsteinn Einarsson , 2012 +# Jannis Leidel , 2011 +# Thordur Sigurdsson , 2016,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-11-20 05:05+0000\n" +"Last-Translator: Thordur Sigurdsson \n" +"Language-Team: Icelandic (http://www.transifex.com/django/django/language/" +"is/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: is\n" +"Plural-Forms: nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);\n" + +msgid "Content Types" +msgstr "Efnistög" + +msgid "python model class name" +msgstr "python eininga klasa nafn" + +msgid "content type" +msgstr "efnistag" + +msgid "content types" +msgstr "efnistög" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Gerð innihalds %(ct_id)s hefur ekkert tengt módel" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Gerð innihalds %(ct_id)s hlutar %(obj_id)s er ekki til" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "%(ct_name)s hlutir hafa ekki get_absolute_url () aðferð" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/it/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/it/LC_MESSAGES/django.mo new file mode 100644 index 0000000..dcdb640 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/it/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/it/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/it/LC_MESSAGES/django.po new file mode 100644 index 0000000..8984cb0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/it/LC_MESSAGES/django.po @@ -0,0 +1,46 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Marco Bonetti, 2014 +# Mirco Grillo , 2020 +# Nicola Larosa , 2012 +# Stefano Brentegani , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-07-23 09:00+0000\n" +"Last-Translator: Mirco Grillo \n" +"Language-Team: Italian (http://www.transifex.com/django/django/language/" +"it/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: it\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Content Type" + +msgid "python model class name" +msgstr "nome della classe del modello Python" + +msgid "content type" +msgstr "content type" + +msgid "content types" +msgstr "content type" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "L'oggetto con content type %(ct_id)s non ha alcun modello associato" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "L'oggetto %(obj_id)s con content type %(ct_id)s non esiste" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "Gli oggetti %(ct_name)s non hanno un metodo get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ja/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ja/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7a0ce28 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ja/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ja/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ja/LC_MESSAGES/django.po new file mode 100644 index 0000000..af29839 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ja/LC_MESSAGES/django.po @@ -0,0 +1,47 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Shinya Okano , 2012,2014 +# Takuya N , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-02-07 16:03+0000\n" +"Last-Translator: Takuya N \n" +"Language-Team: Japanese (http://www.transifex.com/django/django/language/" +"ja/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ja\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Content Types" +msgstr "コンテンツタイプ" + +msgid "python model class name" +msgstr "Python モデルクラス名" + +msgid "content type" +msgstr "コンテンツタイプ" + +msgid "content types" +msgstr "コンテンツタイプ" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "" +"コンテンツタイプ %(ct_id)s のオブジェクトは、関連付けられたモデルを持っていま" +"せん" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "コンテンツタイプ %(ct_id)s のオブジェクト %(obj_id)s は存在しません" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "" +"%(ct_name)s のオブジェクトは get_absolute_url() メソッドを持っていません" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ka/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ka/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5545459 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ka/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ka/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ka/LC_MESSAGES/django.po new file mode 100644 index 0000000..e2f1396 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ka/LC_MESSAGES/django.po @@ -0,0 +1,43 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# André Bouatchidzé , 2013,2015 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: André Bouatchidzé \n" +"Language-Team: Georgian (http://www.transifex.com/django/django/language/" +"ka/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ka\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +msgid "Content Types" +msgstr "კონტენტის ტიპები" + +msgid "python model class name" +msgstr "python-ის მოდელის კლასის სახელი" + +msgid "content type" +msgstr "კონტენტის ტიპი" + +msgid "content types" +msgstr "კონტენტის ტიპები" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "კონტენტის ტიპის %(ct_id)s ობიექტს არ გააჩნია ასოცირებული მოდელი" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "კონტენტის ტიპის %(ct_id)s ობიექტი %(obj_id)s არ არსებობს" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "%(ct_name)s ობიექტებს არ გააჩნიათ მეთოდი get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/kk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/kk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..889b0a0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/kk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/kk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/kk/LC_MESSAGES/django.po new file mode 100644 index 0000000..af1c9f9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/kk/LC_MESSAGES/django.po @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Nurlan Rakhimzhanov , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Kazakh (http://www.transifex.com/django/django/language/kk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kk\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +msgid "Content Types" +msgstr "" + +msgid "python model class name" +msgstr "питонның үлгі классның аты" + +msgid "content type" +msgstr "мазмұн түрі" + +msgid "content types" +msgstr "мазмұн түрлері" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/km/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/km/LC_MESSAGES/django.mo new file mode 100644 index 0000000..6e6775c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/km/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/km/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/km/LC_MESSAGES/django.po new file mode 100644 index 0000000..674077a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/km/LC_MESSAGES/django.po @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Khmer (http://www.transifex.com/django/django/language/km/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: km\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Content Types" +msgstr "" + +msgid "python model class name" +msgstr "ឈ្មោះ python model class" + +msgid "content type" +msgstr "ប្រភេទអត្ថន័យ" + +msgid "content types" +msgstr "ប្រភេទអត្ថន័យ" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/kn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/kn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..00951f1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/kn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/kn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/kn/LC_MESSAGES/django.po new file mode 100644 index 0000000..d4bde11 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/kn/LC_MESSAGES/django.po @@ -0,0 +1,42 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Kannada (http://www.transifex.com/django/django/language/" +"kn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kn\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Content Types" +msgstr "" + +msgid "python model class name" +msgstr "ಪೈಥಾನ್ ಮಾಡೆಲ್ ಕ್ಲಾಸಿನ ಹೆಸರು" + +msgid "content type" +msgstr "ಒಳವಿಷಯದ ಬಗೆ" + +msgid "content types" +msgstr "ಒಳವಿಷಯದ ಬಗೆಗಳು" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ko/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ko/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f8f00ba Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ko/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ko/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ko/LC_MESSAGES/django.po new file mode 100644 index 0000000..8cef428 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ko/LC_MESSAGES/django.po @@ -0,0 +1,43 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Le Tartuffe , 2014 +# Yang Chan Woo , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-09-17 08:01+0000\n" +"Last-Translator: Yang Chan Woo \n" +"Language-Team: Korean (http://www.transifex.com/django/django/language/ko/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ko\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Content Types" +msgstr "콘텐츠 타입" + +msgid "python model class name" +msgstr "python 모델 클래스 명" + +msgid "content type" +msgstr "콘텐츠 타입" + +msgid "content types" +msgstr "콘텐츠 타입(들)" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "콘텐츠 타입 %(ct_id)s 객체는 관련 모델이 없습니다" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "콘텐츠 타입 %(ct_id)s객체%(obj_id)s는 존재하지 않습니다." + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "%(ct_name)s객체들은 get_absolute_url() 메소드가 없습니다." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ky/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ky/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f9cd081 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ky/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ky/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ky/LC_MESSAGES/django.po new file mode 100644 index 0000000..9c6495a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ky/LC_MESSAGES/django.po @@ -0,0 +1,42 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Soyuzbek Orozbek uulu , 2020 +# Soyuzbek Orozbek uulu , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-05-23 06:00+0000\n" +"Last-Translator: Soyuzbek Orozbek uulu \n" +"Language-Team: Kyrgyz (http://www.transifex.com/django/django/language/ky/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ky\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Content Types" +msgstr "Мазмун түрү" + +msgid "python model class name" +msgstr "питон модел класс ысымы" + +msgid "content type" +msgstr "мазмун түрү" + +msgid "content types" +msgstr "мазмун түрлөрү" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "%(ct_id)s мазмун түрүнүн өзүнө байланышкан модели жок." + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "%(ct_id)sмазмун түрүнүн %(obj_id)sобектисинде жашабайт." + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "%(ct_name)sобекттеринде get_absolute_url() ыкмасы жок" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/lb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/lb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5b7937f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/lb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/lb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/lb/LC_MESSAGES/django.po new file mode 100644 index 0000000..69819b7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/lb/LC_MESSAGES/django.po @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:12+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Luxembourgish (http://www.transifex.com/projects/p/django/" +"language/lb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "" + +msgid "python model class name" +msgstr "" + +msgid "content type" +msgstr "" + +msgid "content types" +msgstr "" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/lt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/lt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8c70382 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/lt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/lt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/lt/LC_MESSAGES/django.po new file mode 100644 index 0000000..8c8de9c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/lt/LC_MESSAGES/django.po @@ -0,0 +1,46 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Matas Dailyda , 2015 +# Simonas Kazlauskas , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Matas Dailyda \n" +"Language-Team: Lithuanian (http://www.transifex.com/django/django/language/" +"lt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lt\n" +"Plural-Forms: nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < " +"11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? " +"1 : n % 1 != 0 ? 2: 3);\n" + +msgid "Content Types" +msgstr "Turinio tipai" + +msgid "python model class name" +msgstr "python modelio klasės vardas" + +msgid "content type" +msgstr "turinio tipas" + +msgid "content types" +msgstr "turinio tipai" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Tūrinio tipo %(ct_id)s objektas neturi priskirto modelio" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "Tūrinio tipo %(ct_id)s objektas %(obj_id)s neegzistuoja" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "%(ct_name)s objektai neturi get_absolute_url() metodo" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/lv/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/lv/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4a5565f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/lv/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/lv/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/lv/LC_MESSAGES/django.po new file mode 100644 index 0000000..b91627e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/lv/LC_MESSAGES/django.po @@ -0,0 +1,45 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# NullIsNot0 , 2019 +# peterisb , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-11-07 07:19+0000\n" +"Last-Translator: NullIsNot0 \n" +"Language-Team: Latvian (http://www.transifex.com/django/django/language/" +"lv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lv\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : " +"2);\n" + +msgid "Content Types" +msgstr "Satura tipi" + +msgid "python model class name" +msgstr "python modeļa klases nosaukums" + +msgid "content type" +msgstr "satura tips" + +msgid "content types" +msgstr "satura tipi" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Satura tipa %(ct_id)s objektam nav asociētā modeļa" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Satura tipa %(ct_id)s objekts %(obj_id)s neeksistē" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "%(ct_name)s objekti nesatur get_absolute_url() metodi" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/mk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/mk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ca4d926 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/mk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/mk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/mk/LC_MESSAGES/django.po new file mode 100644 index 0000000..e8a455b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/mk/LC_MESSAGES/django.po @@ -0,0 +1,44 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Vasil Vangelovski , 2014 +# Vasil Vangelovski , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: dekomote \n" +"Language-Team: Macedonian (http://www.transifex.com/django/django/language/" +"mk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mk\n" +"Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n" + +msgid "Content Types" +msgstr "Типови содржини" + +msgid "python model class name" +msgstr "име на класата за python моделoт" + +msgid "content type" +msgstr "тип на содржина" + +msgid "content types" +msgstr "типови содржини" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Типот на содржина %(ct_id)s објект нема асоциран модел" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "Типот на содржина %(ct_id)s објект %(obj_id)s не постои" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "%(ct_name)s објекти немаат get_absolute_url() метод" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ml/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ml/LC_MESSAGES/django.mo new file mode 100644 index 0000000..70458b6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ml/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ml/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ml/LC_MESSAGES/django.po new file mode 100644 index 0000000..873523d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ml/LC_MESSAGES/django.po @@ -0,0 +1,43 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Rajeesh Nair , 2011-2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Malayalam (http://www.transifex.com/django/django/language/" +"ml/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ml\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "" + +msgid "python model class name" +msgstr "പൈത്തണ്‍ മോഡല്‍ ക്ളാസ്സിന്റെ പേര്" + +msgid "content type" +msgstr "ഏതു തരം ഉള്ളടക്കം" + +msgid "content types" +msgstr "ഏതൊക്കെ തരം ഉള്ളടക്കം" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "കണ്ടന്റ് ടൈപ്പ് %(ct_id)s വസ്തുവിന് അനുബന്ധമായ മോഡല്‍ ഇല്ല." + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "കണ്ടന്റ് ടൈപ്പ് %(ct_id)s വസ്തു %(obj_id)s നിലവിലില്ല" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "%(ct_name)s വസ്തുക്കള്‍ക്ക് get_absolute_url() രീതി ഇല്ല." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/mn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/mn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..bb640e9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/mn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/mn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/mn/LC_MESSAGES/django.po new file mode 100644 index 0000000..266a85b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/mn/LC_MESSAGES/django.po @@ -0,0 +1,46 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bayarkhuu Bataa, 2017 +# Jannis Leidel , 2011 +# Zorig , 2014 +# Анхбаяр Анхаа , 2011-2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-10-19 14:01+0000\n" +"Last-Translator: Bayarkhuu Bataa\n" +"Language-Team: Mongolian (http://www.transifex.com/django/django/language/" +"mn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Агуулгын төрөл" + +msgid "python model class name" +msgstr "пайтоны моделын классын нэр" + +msgid "content type" +msgstr "агуулгын төрөл" + +msgid "content types" +msgstr "агуулгын төрлүүд" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "%(ct_id)s төрлийн холбоотой модель олдсонгүй" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "%(ct_id)s төрлийн %(obj_id)s объект олдсонгүй" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "" +"%(ct_name)s объектууд дээр get_absolute_url() функцийг тодорхойлоогүй байна." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/mr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/mr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..183b3d1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/mr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/mr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/mr/LC_MESSAGES/django.po new file mode 100644 index 0000000..822bd2e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/mr/LC_MESSAGES/django.po @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:12+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Marathi (http://www.transifex.com/projects/p/django/language/" +"mr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mr\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "" + +msgid "python model class name" +msgstr "" + +msgid "content type" +msgstr "" + +msgid "content types" +msgstr "" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ms/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ms/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3d28522 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ms/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ms/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ms/LC_MESSAGES/django.po new file mode 100644 index 0000000..1aa74e0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ms/LC_MESSAGES/django.po @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jafry Hisham, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2021-11-16 12:42+0000\n" +"Last-Translator: Jafry Hisham\n" +"Language-Team: Malay (http://www.transifex.com/django/django/language/ms/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ms\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Content Types" +msgstr "Jenis kandungan" + +msgid "python model class name" +msgstr "nama kelas model python" + +msgid "content type" +msgstr "jenis kandungan" + +msgid "content types" +msgstr "jenis-jenis kandungan" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Jenis kandungan %(ct_id)s tidak mempunyai model yang berkaitan" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Jenis kandungan %(ct_id)s objek %(obj_id)s tidak wujud" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "Objek-objek %(ct_name)s tidak mempunyai kaedah get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/my/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/my/LC_MESSAGES/django.mo new file mode 100644 index 0000000..03d84f2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/my/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/my/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/my/LC_MESSAGES/django.po new file mode 100644 index 0000000..e5fc0fc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/my/LC_MESSAGES/django.po @@ -0,0 +1,42 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Yhal Htet Aung , 2013,2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Yhal Htet Aung \n" +"Language-Team: Burmese (http://www.transifex.com/django/django/language/" +"my/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: my\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Content Types" +msgstr "အကြောင်းအရာအမျိုးအစားများ" + +msgid "python model class name" +msgstr "စပါးကြီးမော်ဒယ်အမျိုးအစားနာမည်" + +msgid "content type" +msgstr "အကြောင်းအရာအမျိုးအစား" + +msgid "content types" +msgstr "အကြောင်းအရာအမျိုးအစားများ" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "အကြောင်းအရာအမျိုးအစား %(ct_id)s အရာဝတ္ထုမှာဆက်နွယ်သောမော်ဒယ်မရှိ" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "အကြောင်းအရာအမျိုးအစား %(ct_id)s အရာဝတ္ထု %(obj_id)s မတည်ရှိနေ" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "%(ct_name)s အရာဝတ္ထုများ get_absolute_url() နည်းလမ်းမရှိ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/nb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/nb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d058fce Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/nb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/nb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/nb/LC_MESSAGES/django.po new file mode 100644 index 0000000..f1485a8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/nb/LC_MESSAGES/django.po @@ -0,0 +1,46 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# jensadne , 2014 +# Jon , 2020 +# Jon , 2012 +# Sigurd Gartmann , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-01-21 12:15+0000\n" +"Last-Translator: Jon \n" +"Language-Team: Norwegian Bokmål (http://www.transifex.com/django/django/" +"language/nb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Innholdstyper" + +msgid "python model class name" +msgstr "python-modellklassenavn" + +msgid "content type" +msgstr "innholdstype" + +msgid "content types" +msgstr "innholdstyper" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Innholdstype %(ct_id)s objekt har ingen assosiert model" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Innholdstype %(ct_id)s objekt %(obj_id)s finnes ikke" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "%(ct_name)s-objekter har ikke get_absolute_url()-metode" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ne/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ne/LC_MESSAGES/django.mo new file mode 100644 index 0000000..6e855c7 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ne/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ne/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ne/LC_MESSAGES/django.po new file mode 100644 index 0000000..6ecdd03 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ne/LC_MESSAGES/django.po @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Sagar Chalise , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Sagar Chalise \n" +"Language-Team: Nepali (http://www.transifex.com/django/django/language/ne/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ne\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "कन्टेन्ट टाइपहरु" + +msgid "python model class name" +msgstr "पाइथन मोडेल क्लासको नाम" + +msgid "content type" +msgstr "कन्टेन्ट टाइप" + +msgid "content types" +msgstr "कन्टेन्ट टाइपहरु" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "कन्टेन्ट टाइप %(ct_id)s वस्तु सँग सम्बन्धित मोडेल छैन ।" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "कन्टेन्ट टाइप %(ct_id)s वस्तु %(obj_id)s छैन ।" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "%(ct_name)s वस्तुमा get_absolute_url() तरिका छैन ।" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/nl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/nl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e5e33f1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/nl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/nl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/nl/LC_MESSAGES/django.po new file mode 100644 index 0000000..2dade66 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/nl/LC_MESSAGES/django.po @@ -0,0 +1,44 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Harro van der Klauw , 2012 +# Jannis Leidel , 2011 +# Sander Steffann , 2015 +# Tonnes , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-09-17 08:44+0000\n" +"Last-Translator: Tonnes \n" +"Language-Team: Dutch (http://www.transifex.com/django/django/language/nl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Inhoudstypen" + +msgid "python model class name" +msgstr "klassenaam van pythonmodel" + +msgid "content type" +msgstr "inhoudstype" + +msgid "content types" +msgstr "inhoudstypen" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Object van inhoudstype %(ct_id)s heeft geen bijbehorend model" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Object %(obj_id)s van inhoudstype %(ct_id)s bestaat niet" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "%(ct_name)s-objecten hebben geen get_absolute_url()-methode" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/nn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/nn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c60510c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/nn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/nn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/nn/LC_MESSAGES/django.po new file mode 100644 index 0000000..c441b43 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/nn/LC_MESSAGES/django.po @@ -0,0 +1,44 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# jensadne , 2013 +# Sivert Olstad, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2021-10-21 18:49+0000\n" +"Last-Translator: Sivert Olstad\n" +"Language-Team: Norwegian Nynorsk (http://www.transifex.com/django/django/" +"language/nn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Innhaldstypar" + +msgid "python model class name" +msgstr "python-modell klassenamn" + +msgid "content type" +msgstr "innhaldstype" + +msgid "content types" +msgstr "innhaldstypar" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Innhaldstype %(ct_id)s-objektet har ingen modell knytta til seg" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Innhaldstype %(ct_id)s-objekt %(obj_id)s eksisterer ikkje" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "%(ct_name)s-objekt har ikkje ein get_absolute_url() metode" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/os/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/os/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3e44b4b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/os/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/os/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/os/LC_MESSAGES/django.po new file mode 100644 index 0000000..bdeabb6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/os/LC_MESSAGES/django.po @@ -0,0 +1,42 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Soslan Khubulov , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Ossetic (http://www.transifex.com/django/django/language/" +"os/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: os\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "" + +msgid "python model class name" +msgstr "python моделы классы ном" + +msgid "content type" +msgstr "мидисы хуыз" + +msgid "content types" +msgstr "мидисы хуызтӕ" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "%(ct_id)s мидисы хуызы объектӕн ӕмбӕлгӕ модел нӕй" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "%(ct_id)s мидисы хуызы объект %(obj_id)s нӕй" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "%(ct_name)s объекттӕн get_absolute_url() метод нӕй" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/pa/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/pa/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9221827 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/pa/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/pa/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/pa/LC_MESSAGES/django.po new file mode 100644 index 0000000..7eb0a2c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/pa/LC_MESSAGES/django.po @@ -0,0 +1,42 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Panjabi (Punjabi) (http://www.transifex.com/django/django/" +"language/pa/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pa\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "" + +msgid "python model class name" +msgstr "ਪਾਈਥਨ ਮਾਡਲ ਕਲਾਸ ਨਾਂ" + +msgid "content type" +msgstr "ਸਮੱਗਰੀ ਕਿਸਮ" + +msgid "content types" +msgstr "ਸਮੱਗਰੀ ਕਿਸਮ" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/pl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/pl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..00e6a51 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/pl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/pl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/pl/LC_MESSAGES/django.po new file mode 100644 index 0000000..0c26fb2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/pl/LC_MESSAGES/django.po @@ -0,0 +1,47 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# sidewinder , 2014 +# angularcircle, 2012 +# Jannis Leidel , 2011 +# m_aciek , 2019 +# Tomasz Kajtoch , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-11-11 14:09+0000\n" +"Last-Translator: m_aciek \n" +"Language-Team: Polish (http://www.transifex.com/django/django/language/pl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pl\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n" +"%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n" +"%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" + +msgid "Content Types" +msgstr "Typy Zawartości" + +msgid "python model class name" +msgstr "Nazwa klasy modelu pythona" + +msgid "content type" +msgstr "typ zawartości" + +msgid "content types" +msgstr "typy zawartości" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Obiekt typu zawartości %(ct_id)s nie posiada przypisanego modelu" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Obiekt %(obj_id)s typu zawartości %(ct_id)s nie istnieje" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "Obiekty %(ct_name)s nie posiadają metody get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/pt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/pt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2ba31b9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/pt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/pt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/pt/LC_MESSAGES/django.po new file mode 100644 index 0000000..95e193d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/pt/LC_MESSAGES/django.po @@ -0,0 +1,44 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Nuno Mariz , 2011-2012 +# Raúl Pedro Fernandes Santos, 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Portuguese (http://www.transifex.com/django/django/language/" +"pt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Tipos de Conteúdo" + +msgid "python model class name" +msgstr "nome da classe do model em python" + +msgid "content type" +msgstr "tipo de conteúdo" + +msgid "content types" +msgstr "tipos de conteúdos" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Objeto do tipo de conteúdo %(ct_id)s não tem nenhum model associado" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "Objeto %(obj_id)s do tipo de conteúdo %(ct_id)s não existe" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "Objetos %(ct_name)s não tem um método get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/pt_BR/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/pt_BR/LC_MESSAGES/django.mo new file mode 100644 index 0000000..eec927d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/pt_BR/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/pt_BR/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/pt_BR/LC_MESSAGES/django.po new file mode 100644 index 0000000..26b3adf --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/pt_BR/LC_MESSAGES/django.po @@ -0,0 +1,46 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Allisson Azevedo , 2014 +# Carlos C. Leite , 2016,2019 +# semente, 2012 +# Jannis Leidel , 2011 +# Rafael Fontenelle , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2021-01-17 06:36+0000\n" +"Last-Translator: Rafael Fontenelle \n" +"Language-Team: Portuguese (Brazil) (http://www.transifex.com/django/django/" +"language/pt_BR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt_BR\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Content Types" +msgstr "Tipos de Conteúdo" + +msgid "python model class name" +msgstr "nome da classe de modelo em python" + +msgid "content type" +msgstr "tipo de conteúdo" + +msgid "content types" +msgstr "tipos de conteúdo" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Objeto do tipo de conteúdo %(ct_id)s não tem nenhum model associado" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "O objeto %(obj_id)s do tipo de conteúdo %(ct_id)s não existe." + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "os objetos %(ct_name)s não têm o método get_absolute_url()." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ro/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ro/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7d41295 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ro/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ro/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ro/LC_MESSAGES/django.po new file mode 100644 index 0000000..2c32c7e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ro/LC_MESSAGES/django.po @@ -0,0 +1,45 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Daniel Ursache-Dogariu, 2011 +# Denis Darii , 2014 +# Razvan Stefanescu , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Razvan Stefanescu \n" +"Language-Team: Romanian (http://www.transifex.com/django/django/language/" +"ro/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ro\n" +"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?" +"2:1));\n" + +msgid "Content Types" +msgstr "Tipuri de conținut" + +msgid "python model class name" +msgstr "nume clasă model Python" + +msgid "content type" +msgstr "tip conținut" + +msgid "content types" +msgstr "tipuri conținut" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Tipul de conținut %(ct_id)s nu are nici un model asociat" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "Content type %(ct_id)s object %(obj_id)s doesn't exist" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "Obiectele %(ct_name)s nu au o metodă get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ru/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ru/LC_MESSAGES/django.mo new file mode 100644 index 0000000..27f7ed2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ru/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ru/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ru/LC_MESSAGES/django.po new file mode 100644 index 0000000..0d36e2a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ru/LC_MESSAGES/django.po @@ -0,0 +1,47 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Eugene , 2012 +# crazyzubr , 2020 +# Jannis Leidel , 2011 +# Алексей Борискин , 2012,2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-05-14 18:22+0000\n" +"Last-Translator: crazyzubr \n" +"Language-Team: Russian (http://www.transifex.com/django/django/language/" +"ru/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ru\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n" +"%100>=11 && n%100<=14)? 2 : 3);\n" + +msgid "Content Types" +msgstr "Типы содержимого" + +msgid "python model class name" +msgstr "имя класса модели" + +msgid "content type" +msgstr "тип содержимого" + +msgid "content types" +msgstr "типы содержимого" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Тип содержимого %(ct_id)s не имеет связанной модели" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Объекта типа %(ct_id)s с идентификатором %(obj_id)s не существует" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "Объекты типа \"%(ct_name)s\" не имеют метода get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c2fa5a9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sk/LC_MESSAGES/django.po new file mode 100644 index 0000000..c66f9ba --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sk/LC_MESSAGES/django.po @@ -0,0 +1,45 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Marian Andre , 2012 +# Martin Tóth , 2017,2023 +# Peter Kuma, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2023-12-04 19:22+0000\n" +"Last-Translator: Martin Tóth , 2017,2023\n" +"Language-Team: Slovak (http://app.transifex.com/django/django/language/sk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n " +">= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);\n" + +msgid "Content Types" +msgstr "Typy Obsahu" + +msgid "python model class name" +msgstr "pythonovské meno triedy modelu" + +msgid "content type" +msgstr "typ obsahu" + +msgid "content types" +msgstr "typy obsahu" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Objekt typu obsahu %(ct_id)s nemá pridružený model" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Objekt %(obj_id)s typu obsahu %(ct_id)s neexistuje" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr " Objekty %(ct_name)s nemajú metódu get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..6253ab0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sl/LC_MESSAGES/django.po new file mode 100644 index 0000000..d13e0dc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sl/LC_MESSAGES/django.po @@ -0,0 +1,45 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# zejn , 2016 +# zejn , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Primož Verdnik \n" +"Language-Team: Slovenian (http://www.transifex.com/django/django/language/" +"sl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sl\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" + +msgid "Content Types" +msgstr "vrste vsebine" + +msgid "python model class name" +msgstr "ime razreda modela python" + +msgid "content type" +msgstr "vrsta vsebine" + +msgid "content types" +msgstr "vrste vsebine" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Predmet vrste vsebine %(ct_id)s nima določenega povezanega modela" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "Predmet %(obj_id)s vrste %(ct_id)s ne obstaja" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "Predmeti vrste %(ct_name)s nimajo določila get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sq/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sq/LC_MESSAGES/django.mo new file mode 100644 index 0000000..cbc3393 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sq/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sq/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sq/LC_MESSAGES/django.po new file mode 100644 index 0000000..37e4727 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sq/LC_MESSAGES/django.po @@ -0,0 +1,43 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Besnik , 2011 +# Besnik , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-09-18 09:52+0000\n" +"Last-Translator: Besnik \n" +"Language-Team: Albanian (http://www.transifex.com/django/django/language/" +"sq/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sq\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Lloje Lënde" + +msgid "python model class name" +msgstr "emër klase modeli python" + +msgid "content type" +msgstr "lloj lënde" + +msgid "content types" +msgstr "lloje lënde" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Objekti për lloj lënde %(ct_id)s s’ka model të përshoqëruar" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Objekti %(obj_id)s për lloj lënde %(ct_id)s s’ekziston" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "Objektet %(ct_name)s s’përmbajnë ndonjë metodë get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9a10067 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sr/LC_MESSAGES/django.po new file mode 100644 index 0000000..02aae70 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sr/LC_MESSAGES/django.po @@ -0,0 +1,46 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Branko Kokanovic , 2018 +# Igor Jerosimić, 2020 +# Jannis Leidel , 2011 +# Janos Guljas , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-01-21 20:40+0000\n" +"Last-Translator: Igor Jerosimić\n" +"Language-Team: Serbian (http://www.transifex.com/django/django/language/" +"sr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Content Types" +msgstr "Типови садржаја" + +msgid "python model class name" +msgstr "име python класе модела" + +msgid "content type" +msgstr "тип садржаја" + +msgid "content types" +msgstr "типови садржаја" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Тип садржаја %(ct_id)s нема асоцирани модел" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Тип садржаја %(ct_id)s објекта %(obj_id)s не постоји" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "Објекти %(ct_name)s немају get_absolute_url() метод" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sr_Latn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sr_Latn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a97478b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sr_Latn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sr_Latn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sr_Latn/LC_MESSAGES/django.po new file mode 100644 index 0000000..926478e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sr_Latn/LC_MESSAGES/django.po @@ -0,0 +1,45 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Igor Jerosimić, 2019-2020 +# Jannis Leidel , 2011 +# Janos Guljas , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-01-21 20:49+0000\n" +"Last-Translator: Igor Jerosimić\n" +"Language-Team: Serbian (Latin) (http://www.transifex.com/django/django/" +"language/sr@latin/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr@latin\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Content Types" +msgstr "Tipovi sadržaja" + +msgid "python model class name" +msgstr "ime python klase modela" + +msgid "content type" +msgstr "tip sadržaja" + +msgid "content types" +msgstr "tipovi sadržaja" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Tip sadržaja %(ct_id)s nema asocirani model" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Tip sadržaja %(ct_id)s objekta %(obj_id)s ne postoji" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "Objekti %(ct_name)s nemaju get_absolute_url() metod" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sv/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sv/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b4fe3a8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sv/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sv/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sv/LC_MESSAGES/django.po new file mode 100644 index 0000000..8cdfa8d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sv/LC_MESSAGES/django.po @@ -0,0 +1,46 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Albin Larsson , 2022 +# Andreas Pelme , 2012 +# Jannis Leidel , 2011 +# Jonathan Lindén, 2014 +# Thomas Lundqvist, 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2022-07-24 19:22+0000\n" +"Last-Translator: Albin Larsson \n" +"Language-Team: Swedish (http://www.transifex.com/django/django/language/" +"sv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sv\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Innehållstyper" + +msgid "python model class name" +msgstr "klassnamn för Python-modell" + +msgid "content type" +msgstr "innehållstyp" + +msgid "content types" +msgstr "innehållstyper" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Innehållstypens %(ct_id)s har ingen associerad modell." + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Innehållstypens %(ct_id)s objekt %(obj_id)s finns inte" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "%(ct_name)s objekt har inte en get_absolute_url()-metod" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sw/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sw/LC_MESSAGES/django.mo new file mode 100644 index 0000000..dcd2203 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sw/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sw/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sw/LC_MESSAGES/django.po new file mode 100644 index 0000000..4f9d8bc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/sw/LC_MESSAGES/django.po @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Swahili (http://www.transifex.com/django/django/language/" +"sw/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sw\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "" + +msgid "python model class name" +msgstr "" + +msgid "content type" +msgstr "aina ya maudhui" + +msgid "content types" +msgstr "aina ya maudhui" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ta/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ta/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8438101 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ta/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ta/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ta/LC_MESSAGES/django.po new file mode 100644 index 0000000..5a524c3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ta/LC_MESSAGES/django.po @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Tamil (http://www.transifex.com/django/django/language/ta/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ta\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "" + +msgid "python model class name" +msgstr "python model class name" + +msgid "content type" +msgstr "பொருளடக்க வகை" + +msgid "content types" +msgstr "பொருளடக்க வகைகள்" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/te/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/te/LC_MESSAGES/django.mo new file mode 100644 index 0000000..732d4e9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/te/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/te/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/te/LC_MESSAGES/django.po new file mode 100644 index 0000000..ca476cd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/te/LC_MESSAGES/django.po @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Telugu (http://www.transifex.com/django/django/language/te/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: te\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "" + +msgid "python model class name" +msgstr "పైతాన్ మొడల్ క్లాస్ పేరు" + +msgid "content type" +msgstr "సూచన రకం" + +msgid "content types" +msgstr "సూచన రకాలు" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/tg/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/tg/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8f0140d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/tg/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/tg/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/tg/LC_MESSAGES/django.po new file mode 100644 index 0000000..9150d44 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/tg/LC_MESSAGES/django.po @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Surush Sufiew , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-05-15 00:27+0000\n" +"Last-Translator: Surush Sufiew \n" +"Language-Team: Tajik (http://www.transifex.com/django/django/language/tg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Намуди контент" + +msgid "python model class name" +msgstr "номи класси модел" + +msgid "content type" +msgstr "намуди контент" + +msgid "content types" +msgstr "намуди контентҳо" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Намуди контенти %(ct_id)s модели алоқаманд надорад" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/th/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/th/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7e443b0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/th/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/th/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/th/LC_MESSAGES/django.po new file mode 100644 index 0000000..8ab409e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/th/LC_MESSAGES/django.po @@ -0,0 +1,42 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Kowit Charoenratchatabhan , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Thai (http://www.transifex.com/django/django/language/th/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: th\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Content Types" +msgstr "" + +msgid "python model class name" +msgstr "python model class name" + +msgid "content type" +msgstr "content type" + +msgid "content types" +msgstr "content types" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "ประเภทของเนื้อหา %(ct_id)s ไม่มีอ็อบเจ็กที่มีรูปแบบที่เกี่ยวข้อง" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "ไม่มีประเภทของเนื้อหา %(ct_id)s วัตถุ %(obj_id)s" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "%(ct_name)s ไม่มีเมธอด get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/tk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/tk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0bafb07 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/tk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/tk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/tk/LC_MESSAGES/django.po new file mode 100644 index 0000000..44d8f80 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/tk/LC_MESSAGES/django.po @@ -0,0 +1,42 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Resulkary , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-07-07 20:28+0000\n" +"Last-Translator: Resulkary \n" +"Language-Team: Turkmen (http://www.transifex.com/django/django/language/" +"tk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tk\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "Mazmunyň görnüşleri" + +msgid "python model class name" +msgstr "python model synpynyň ady" + +msgid "content type" +msgstr "mazmunyň görnüşi" + +msgid "content types" +msgstr "mazmunyň görnüşleri" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Mazmun görnüşi %(ct_id)s obýekti bilen baglanyşykly model ýok" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "Mazmun görnüşi %(ct_id)s %(obj_id)s ýok" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "%(ct_name)s obýektlerde get_absolute_url() metody ýok" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/tr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/tr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..18bcd94 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/tr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/tr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/tr/LC_MESSAGES/django.po new file mode 100644 index 0000000..b33b267 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/tr/LC_MESSAGES/django.po @@ -0,0 +1,45 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# BouRock, 2019 +# BouRock, 2014 +# Jannis Leidel , 2011 +# Murat Çorlu , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-09-17 08:00+0000\n" +"Last-Translator: BouRock\n" +"Language-Team: Turkish (http://www.transifex.com/django/django/language/" +"tr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Content Types" +msgstr "İçerik Türleri" + +msgid "python model class name" +msgstr "python model sınıfı adı" + +msgid "content type" +msgstr "içerik türü" + +msgid "content types" +msgstr "içerik türleri" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "İçerik türü %(ct_id)s nesnesi ilişkilendirilmiş modele sahip değil" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "İçerik türü %(ct_id)s nesne %(obj_id)s mevcut değil" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "%(ct_name)s nesneleri bir get_absolute_url() yöntemine sahip değiller" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/tt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/tt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f45a1f2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/tt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/tt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/tt/LC_MESSAGES/django.po new file mode 100644 index 0000000..90a5004 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/tt/LC_MESSAGES/django.po @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Azat Khasanshin , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Tatar (http://www.transifex.com/django/django/language/tt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tt\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Content Types" +msgstr "" + +msgid "python model class name" +msgstr "модель классының исеме" + +msgid "content type" +msgstr "эчтәлек тибы" + +msgid "content types" +msgstr "эчтәлек тиблары" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/udm/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/udm/LC_MESSAGES/django.mo new file mode 100644 index 0000000..af7ab53 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/udm/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/udm/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/udm/LC_MESSAGES/django.po new file mode 100644 index 0000000..a8f7e88 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/udm/LC_MESSAGES/django.po @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:13+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Udmurt (http://www.transifex.com/projects/p/django/language/" +"udm/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: udm\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Content Types" +msgstr "" + +msgid "python model class name" +msgstr "" + +msgid "content type" +msgstr "" + +msgid "content types" +msgstr "" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ug/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ug/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f81e7c0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ug/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ug/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ug/LC_MESSAGES/django.po new file mode 100644 index 0000000..ad21e41 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ug/LC_MESSAGES/django.po @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Abduqadir Abliz , 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2023-12-04 19:22+0000\n" +"Last-Translator: Abduqadir Abliz , 2023\n" +"Language-Team: Uyghur (http://app.transifex.com/django/django/language/ug/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ug\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "مەزمۇن تىپلىرى" + +msgid "python model class name" +msgstr "python مودېلىنىڭ سىنىپ ئىسمى" + +msgid "content type" +msgstr "مەزمۇن تىپى" + +msgid "content types" +msgstr "مەزمۇن تىپلىرى" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "مەزمۇن تىپى %(ct_id)s ئوبيېكتىنىڭ باغلانغان مودېلى يوق" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "مەزمۇن تىپى %(ct_id)s ئوبيېكت %(obj_id)s مەۋجۇت ئەمەس" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "%(ct_name)s ئوبيېكتى get_absolute_url() ئۇسۇلى يوق" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/uk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/uk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5ca84fa Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/uk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/uk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/uk/LC_MESSAGES/django.po new file mode 100644 index 0000000..a798bb1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/uk/LC_MESSAGES/django.po @@ -0,0 +1,49 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Oleksandr Chernihov , 2014 +# Illia Volochii , 2021 +# Jannis Leidel , 2011 +# Sergey Lysach , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2021-01-20 00:17+0000\n" +"Last-Translator: Illia Volochii \n" +"Language-Team: Ukrainian (http://www.transifex.com/django/django/language/" +"uk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: uk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != " +"11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % " +"100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || " +"(n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n" + +msgid "Content Types" +msgstr "Типи вмісту" + +msgid "python model class name" +msgstr "імʼя класу моделі" + +msgid "content type" +msgstr "тип вмісту" + +msgid "content types" +msgstr "типи вмісту" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Тип вмісту %(ct_id)s не має пов'язанної моделі" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "" +"Обʼєкт з ідентифікатором %(ct_id)s, що має тип вмісту %(obj_id)s не існує" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "Обʼєкт типу %(ct_name)s не має методу get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ur/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ur/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f6ff919 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ur/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ur/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ur/LC_MESSAGES/django.po new file mode 100644 index 0000000..075af1f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/ur/LC_MESSAGES/django.po @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Mansoorulhaq Mansoor , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Urdu (http://www.transifex.com/django/django/language/ur/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ur\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Content Types" +msgstr "" + +msgid "python model class name" +msgstr "پائثان کے ماڈل کی کلاس کا نام" + +msgid "content type" +msgstr "مضمون کی قسم" + +msgid "content types" +msgstr "مضمون کی اقسام" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "" + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/vi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/vi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1cc06c6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/vi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/vi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/vi/LC_MESSAGES/django.po new file mode 100644 index 0000000..6dbef52 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/vi/LC_MESSAGES/django.po @@ -0,0 +1,45 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Tran , 2011 +# Tran Van , 2013 +# xgenvn , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Tran Van \n" +"Language-Team: Vietnamese (http://www.transifex.com/django/django/language/" +"vi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: vi\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Content Types" +msgstr "Các loại nội dung" + +msgid "python model class name" +msgstr "tên lớp mô hình python" + +msgid "content type" +msgstr "kiểu nội dung" + +msgid "content types" +msgstr "kiểu nội dung" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "Đối tượng của kiểu nội dung %(ct_id)s không có model tương ứng" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" +msgstr "Đối tượng %(obj_id)s của Kiểu nội dung %(ct_id)s không tồn tại." + +#, python-format +msgid "%(ct_name)s objects don't have a get_absolute_url() method" +msgstr "Đối tượng %(ct_name)s không có phương thức get_absolute_url()" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/zh_Hans/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/zh_Hans/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7f9dc8c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/zh_Hans/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/zh_Hans/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/zh_Hans/LC_MESSAGES/django.po new file mode 100644 index 0000000..2acb647 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/zh_Hans/LC_MESSAGES/django.po @@ -0,0 +1,46 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Ronald White , 2014 +# slene , 2011 +# wolf ice , 2020 +# Kevin Sze , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-03-04 02:33+0000\n" +"Last-Translator: wolf ice \n" +"Language-Team: Chinese (China) (http://www.transifex.com/django/django/" +"language/zh_CN/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_CN\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Content Types" +msgstr "内容类型" + +msgid "python model class name" +msgstr "python 模型类名" + +msgid "content type" +msgstr "内容类型" + +msgid "content types" +msgstr "内容类型" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "内容类型 %(ct_id)s 对象没有关联的模型" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "内容类型%(ct_id)s对象%(obj_id)s不存在" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "%(ct_name)s对象不包含get_absolute_url()方法" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/zh_Hant/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/zh_Hant/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7c1e8b8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/zh_Hant/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/zh_Hant/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/zh_Hant/LC_MESSAGES/django.po new file mode 100644 index 0000000..e6e918b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/locale/zh_Hant/LC_MESSAGES/django.po @@ -0,0 +1,44 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# ilay , 2012 +# Jannis Leidel , 2011 +# Tzu-ping Chung , 2016,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-09-18 09:00+0000\n" +"Last-Translator: Tzu-ping Chung \n" +"Language-Team: Chinese (Taiwan) (http://www.transifex.com/django/django/" +"language/zh_TW/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_TW\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Content Types" +msgstr "內容類型" + +msgid "python model class name" +msgstr "python model 類別名稱" + +msgid "content type" +msgstr "內容類型" + +msgid "content types" +msgstr "內容類型" + +#, python-format +msgid "Content type %(ct_id)s object has no associated model" +msgstr "內容類型 %(ct_id)s 的物件沒有關聯的資料模型" + +#, python-format +msgid "Content type %(ct_id)s object %(obj_id)s doesn’t exist" +msgstr "內容類型 %(ct_id)s 的物件 %(obj_id)s 不存在" + +#, python-format +msgid "%(ct_name)s objects don’t have a get_absolute_url() method" +msgstr "%(ct_name)s 的物件沒有 get_absolute_url() 方法" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/management/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/management/__init__.py new file mode 100644 index 0000000..903b9ab --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/management/__init__.py @@ -0,0 +1,145 @@ +from django.apps import apps as global_apps +from django.db import DEFAULT_DB_ALIAS, IntegrityError, migrations, router, transaction + + +class RenameContentType(migrations.RunPython): + def __init__(self, app_label, old_model, new_model): + self.app_label = app_label + self.old_model = old_model + self.new_model = new_model + super().__init__(self.rename_forward, self.rename_backward) + + def _rename(self, apps, schema_editor, old_model, new_model): + ContentType = apps.get_model("contenttypes", "ContentType") + db = schema_editor.connection.alias + if not router.allow_migrate_model(db, ContentType): + return + + try: + content_type = ContentType.objects.db_manager(db).get_by_natural_key( + self.app_label, old_model + ) + except ContentType.DoesNotExist: + pass + else: + content_type.model = new_model + try: + with transaction.atomic(using=db): + content_type.save(using=db, update_fields={"model"}) + except IntegrityError: + # Gracefully fallback if a stale content type causes a + # conflict as remove_stale_contenttypes will take care of + # asking the user what should be done next. + content_type.model = old_model + else: + # Clear the cache as the `get_by_natural_key()` call will cache + # the renamed ContentType instance by its old model name. + ContentType.objects.clear_cache() + + def rename_forward(self, apps, schema_editor): + self._rename(apps, schema_editor, self.old_model, self.new_model) + + def rename_backward(self, apps, schema_editor): + self._rename(apps, schema_editor, self.new_model, self.old_model) + + +def inject_rename_contenttypes_operations( + plan=None, apps=global_apps, using=DEFAULT_DB_ALIAS, **kwargs +): + """ + Insert a `RenameContentType` operation after every planned `RenameModel` + operation. + """ + if plan is None: + return + + # Determine whether or not the ContentType model is available. + try: + ContentType = apps.get_model("contenttypes", "ContentType") + except LookupError: + available = False + else: + if not router.allow_migrate_model(using, ContentType): + return + available = True + + for migration, backward in plan: + if (migration.app_label, migration.name) == ("contenttypes", "0001_initial"): + # There's no point in going forward if the initial contenttypes + # migration is unapplied as the ContentType model will be + # unavailable from this point. + if backward: + break + else: + available = True + continue + # The ContentType model is not available yet. + if not available: + continue + inserts = [] + for index, operation in enumerate(migration.operations): + if isinstance(operation, migrations.RenameModel): + operation = RenameContentType( + migration.app_label, + operation.old_name_lower, + operation.new_name_lower, + ) + inserts.append((index + 1, operation)) + for inserted, (index, operation) in enumerate(inserts): + migration.operations.insert(inserted + index, operation) + + +def get_contenttypes_and_models(app_config, using, ContentType): + if not router.allow_migrate_model(using, ContentType): + return None, None + + ContentType.objects.clear_cache() + + content_types = { + ct.model: ct + for ct in ContentType.objects.using(using).filter(app_label=app_config.label) + } + app_models = {model._meta.model_name: model for model in app_config.get_models()} + return content_types, app_models + + +def create_contenttypes( + app_config, + verbosity=2, + interactive=True, + using=DEFAULT_DB_ALIAS, + apps=global_apps, + **kwargs, +): + """ + Create content types for models in the given app. + """ + if not app_config.models_module: + return + + app_label = app_config.label + try: + app_config = apps.get_app_config(app_label) + ContentType = apps.get_model("contenttypes", "ContentType") + except LookupError: + return + + content_types, app_models = get_contenttypes_and_models( + app_config, using, ContentType + ) + + if not app_models: + return + + cts = [ + ContentType( + app_label=app_label, + model=model_name, + ) + for (model_name, model) in app_models.items() + if model_name not in content_types + ] + ContentType.objects.using(using).bulk_create(cts) + if verbosity >= 2: + for ct in cts: + print("Adding content type '%s | %s'" % (ct.app_label, ct.model)) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/management/commands/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/management/commands/remove_stale_contenttypes.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/management/commands/remove_stale_contenttypes.py new file mode 100644 index 0000000..51de847 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/management/commands/remove_stale_contenttypes.py @@ -0,0 +1,112 @@ +import itertools + +from django.apps import apps +from django.contrib.contenttypes.models import ContentType +from django.core.management import BaseCommand +from django.db import DEFAULT_DB_ALIAS, router +from django.db.models.deletion import Collector + + +class Command(BaseCommand): + help = "Deletes stale content types in the database." + + def add_arguments(self, parser): + parser.add_argument( + "--noinput", + "--no-input", + action="store_false", + dest="interactive", + help="Tells Django to NOT prompt the user for input of any kind.", + ) + parser.add_argument( + "--database", + default=DEFAULT_DB_ALIAS, + help='Nominates the database to use. Defaults to the "default" database.', + ) + parser.add_argument( + "--include-stale-apps", + action="store_true", + default=False, + help=( + "Deletes stale content types including ones from previously " + "installed apps that have been removed from INSTALLED_APPS." + ), + ) + + def handle(self, **options): + db = options["database"] + include_stale_apps = options["include_stale_apps"] + interactive = options["interactive"] + verbosity = options["verbosity"] + + if not router.allow_migrate_model(db, ContentType): + return + ContentType.objects.clear_cache() + + apps_content_types = itertools.groupby( + ContentType.objects.using(db).order_by("app_label", "model"), + lambda obj: obj.app_label, + ) + for app_label, content_types in apps_content_types: + if not include_stale_apps and app_label not in apps.app_configs: + continue + to_remove = [ct for ct in content_types if ct.model_class() is None] + # Confirm that the content type is stale before deletion. + using = router.db_for_write(ContentType) + if to_remove: + if interactive: + ct_info = [] + for ct in to_remove: + ct_info.append( + " - Content type for %s.%s" % (ct.app_label, ct.model) + ) + collector = NoFastDeleteCollector(using=using, origin=ct) + collector.collect([ct]) + + for obj_type, objs in collector.data.items(): + if objs != {ct}: + ct_info.append( + " - %s %s object(s)" + % ( + len(objs), + obj_type._meta.label, + ) + ) + content_type_display = "\n".join(ct_info) + self.stdout.write( + "Some content types in your database are stale and can be " + "deleted.\n" + "Any objects that depend on these content types will also be " + "deleted.\n" + "The content types and dependent objects that would be deleted " + "are:\n\n" + f"{content_type_display}\n\n" + "This list doesn't include any cascade deletions to data " + "outside of Django's\n" + "models (uncommon).\n\n" + "Are you sure you want to delete these content types?\n" + "If you're unsure, answer 'no'." + ) + ok_to_delete = input("Type 'yes' to continue, or 'no' to cancel: ") + else: + ok_to_delete = "yes" + + if ok_to_delete == "yes": + for ct in to_remove: + if verbosity >= 2: + self.stdout.write( + "Deleting stale content type '%s | %s'" + % (ct.app_label, ct.model) + ) + ct.delete() + else: + if verbosity >= 2: + self.stdout.write("Stale content types remain.") + + +class NoFastDeleteCollector(Collector): + def can_fast_delete(self, *args, **kwargs): + """ + Always load related objects to display them when showing confirmation. + """ + return False diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/migrations/0001_initial.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/migrations/0001_initial.py new file mode 100644 index 0000000..7ea39d4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/migrations/0001_initial.py @@ -0,0 +1,45 @@ +import django.contrib.contenttypes.models +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [] + + operations = [ + migrations.CreateModel( + name="ContentType", + fields=[ + ( + "id", + models.AutoField( + verbose_name="ID", + serialize=False, + auto_created=True, + primary_key=True, + ), + ), + ("name", models.CharField(max_length=100)), + ("app_label", models.CharField(max_length=100)), + ( + "model", + models.CharField( + max_length=100, verbose_name="python model class name" + ), + ), + ], + options={ + "ordering": ("name",), + "db_table": "django_content_type", + "verbose_name": "content type", + "verbose_name_plural": "content types", + }, + bases=(models.Model,), + managers=[ + ("objects", django.contrib.contenttypes.models.ContentTypeManager()), + ], + ), + migrations.AlterUniqueTogether( + name="contenttype", + unique_together={("app_label", "model")}, + ), + ] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/migrations/0002_remove_content_type_name.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/migrations/0002_remove_content_type_name.py new file mode 100644 index 0000000..29f0474 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/migrations/0002_remove_content_type_name.py @@ -0,0 +1,42 @@ +from django.db import migrations, models + + +def add_legacy_name(apps, schema_editor): + alias = schema_editor.connection.alias + ContentType = apps.get_model("contenttypes", "ContentType") + for ct in ContentType.objects.using(alias): + try: + ct.name = apps.get_model(ct.app_label, ct.model)._meta.object_name + except LookupError: + ct.name = ct.model + ct.save() + + +class Migration(migrations.Migration): + dependencies = [ + ("contenttypes", "0001_initial"), + ] + + operations = [ + migrations.AlterModelOptions( + name="contenttype", + options={ + "verbose_name": "content type", + "verbose_name_plural": "content types", + }, + ), + migrations.AlterField( + model_name="contenttype", + name="name", + field=models.CharField(max_length=100, null=True), + ), + migrations.RunPython( + migrations.RunPython.noop, + add_legacy_name, + hints={"model_name": "contenttype"}, + ), + migrations.RemoveField( + model_name="contenttype", + name="name", + ), + ] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/migrations/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/models.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/models.py new file mode 100644 index 0000000..0d98ed3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/models.py @@ -0,0 +1,193 @@ +from collections import defaultdict + +from django.apps import apps +from django.db import models +from django.db.models import Q +from django.utils.translation import gettext_lazy as _ + + +class ContentTypeManager(models.Manager): + use_in_migrations = True + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + # Cache shared by all the get_for_* methods to speed up + # ContentType retrieval. + self._cache = {} + + def get_by_natural_key(self, app_label, model): + try: + ct = self._cache[self.db][(app_label, model)] + except KeyError: + ct = self.get(app_label=app_label, model=model) + self._add_to_cache(self.db, ct) + return ct + + def _get_opts(self, model, for_concrete_model): + if for_concrete_model: + model = model._meta.concrete_model + return model._meta + + def _get_from_cache(self, opts): + key = (opts.app_label, opts.model_name) + return self._cache[self.db][key] + + def get_for_model(self, model, for_concrete_model=True): + """ + Return the ContentType object for a given model, creating the + ContentType if necessary. Lookups are cached so that subsequent lookups + for the same model don't hit the database. + """ + opts = self._get_opts(model, for_concrete_model) + try: + return self._get_from_cache(opts) + except KeyError: + pass + + # The ContentType entry was not found in the cache, therefore we + # proceed to load or create it. + try: + # Start with get() and not get_or_create() in order to use + # the db_for_read (see #20401). + ct = self.get(app_label=opts.app_label, model=opts.model_name) + except self.model.DoesNotExist: + # Not found in the database; we proceed to create it. This time + # use get_or_create to take care of any race conditions. + ct, created = self.get_or_create( + app_label=opts.app_label, + model=opts.model_name, + ) + self._add_to_cache(self.db, ct) + return ct + + def get_for_models(self, *models, for_concrete_models=True): + """ + Given *models, return a dictionary mapping {model: content_type}. + """ + results = {} + # Models that aren't already in the cache grouped by app labels. + needed_models = defaultdict(set) + # Mapping of opts to the list of models requiring it. + needed_opts = defaultdict(list) + for model in models: + opts = self._get_opts(model, for_concrete_models) + try: + ct = self._get_from_cache(opts) + except KeyError: + needed_models[opts.app_label].add(opts.model_name) + needed_opts[opts].append(model) + else: + results[model] = ct + if needed_opts: + # Lookup required content types from the DB. + condition = Q( + *( + Q(("app_label", app_label), ("model__in", models)) + for app_label, models in needed_models.items() + ), + _connector=Q.OR, + ) + cts = self.filter(condition) + for ct in cts: + opts_models = needed_opts.pop( + ct._meta.apps.get_model(ct.app_label, ct.model)._meta, [] + ) + for model in opts_models: + results[model] = ct + self._add_to_cache(self.db, ct) + # Create content types that weren't in the cache or DB. + for opts, opts_models in needed_opts.items(): + ct = self.create( + app_label=opts.app_label, + model=opts.model_name, + ) + self._add_to_cache(self.db, ct) + for model in opts_models: + results[model] = ct + return results + + def get_for_id(self, id): + """ + Lookup a ContentType by ID. Use the same shared cache as get_for_model + (though ContentTypes are not created on-the-fly by get_by_id). + """ + try: + ct = self._cache[self.db][id] + except KeyError: + # This could raise a DoesNotExist; that's correct behavior and will + # make sure that only correct ctypes get stored in the cache dict. + ct = self.get(pk=id) + self._add_to_cache(self.db, ct) + return ct + + def clear_cache(self): + """ + Clear out the content-type cache. + """ + self._cache.clear() + + def _add_to_cache(self, using, ct): + """Insert a ContentType into the cache.""" + # Note it's possible for ContentType objects to be stale; model_class() + # will return None. Hence, there is no reliance on + # model._meta.app_label here, just using the model fields instead. + key = (ct.app_label, ct.model) + self._cache.setdefault(using, {})[key] = ct + self._cache.setdefault(using, {})[ct.id] = ct + + +class ContentType(models.Model): + app_label = models.CharField(max_length=100) + model = models.CharField(_("python model class name"), max_length=100) + objects = ContentTypeManager() + + class Meta: + verbose_name = _("content type") + verbose_name_plural = _("content types") + db_table = "django_content_type" + unique_together = [["app_label", "model"]] + + def __str__(self): + return self.app_labeled_name + + @property + def name(self): + model = self.model_class() + if not model: + return self.model + return str(model._meta.verbose_name) + + @property + def app_labeled_name(self): + model = self.model_class() + if not model: + return self.model + return "%s | %s" % ( + model._meta.app_config.verbose_name, + model._meta.verbose_name, + ) + + def model_class(self): + """Return the model class for this type of content.""" + try: + return apps.get_model(self.app_label, self.model) + except LookupError: + return None + + def get_object_for_this_type(self, **kwargs): + """ + Return an object of this type for the keyword arguments given. + Basically, this is a proxy around this object_type's get_object() model + method. The ObjectNotExist exception, if thrown, will not be caught, + so code that calls this method should catch it. + """ + return self.model_class()._base_manager.using(self._state.db).get(**kwargs) + + def get_all_objects_for_this_type(self, **kwargs): + """ + Return all objects of this type for the keyword arguments given. + """ + return self.model_class()._base_manager.using(self._state.db).filter(**kwargs) + + def natural_key(self): + return (self.app_label, self.model) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/prefetch.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/prefetch.py new file mode 100644 index 0000000..b02ed3b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/prefetch.py @@ -0,0 +1,36 @@ +from django.db.models import Prefetch +from django.db.models.query import ModelIterable, RawQuerySet + + +class GenericPrefetch(Prefetch): + def __init__(self, lookup, querysets=None, to_attr=None): + for queryset in querysets: + if queryset is not None and ( + isinstance(queryset, RawQuerySet) + or ( + hasattr(queryset, "_iterable_class") + and not issubclass(queryset._iterable_class, ModelIterable) + ) + ): + raise ValueError( + "Prefetch querysets cannot use raw(), values(), and values_list()." + ) + self.querysets = querysets + super().__init__(lookup, to_attr=to_attr) + + def __getstate__(self): + obj_dict = self.__dict__.copy() + obj_dict["querysets"] = [] + for queryset in self.querysets: + if queryset is not None: + queryset = queryset._chain() + # Prevent the QuerySet from being evaluated + queryset._result_cache = [] + queryset._prefetch_done = True + obj_dict["querysets"].append(queryset) + return obj_dict + + def get_current_querysets(self, level): + if self.get_current_prefetch_to(level) == self.prefetch_to: + return self.querysets + return None diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/views.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/views.py new file mode 100644 index 0000000..bfde73c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/contenttypes/views.py @@ -0,0 +1,88 @@ +from django.apps import apps +from django.contrib.contenttypes.models import ContentType +from django.contrib.sites.shortcuts import get_current_site +from django.core.exceptions import ObjectDoesNotExist +from django.http import Http404, HttpResponseRedirect +from django.utils.translation import gettext as _ + + +def shortcut(request, content_type_id, object_id): + """ + Redirect to an object's page based on a content-type ID and an object ID. + """ + # Look up the object, making sure it's got a get_absolute_url() function. + try: + content_type = ContentType.objects.get(pk=content_type_id) + if not content_type.model_class(): + raise Http404( + _("Content type %(ct_id)s object has no associated model") + % {"ct_id": content_type_id} + ) + obj = content_type.get_object_for_this_type(pk=object_id) + except (ObjectDoesNotExist, ValueError): + raise Http404( + _("Content type %(ct_id)s object %(obj_id)s doesn’t exist") + % {"ct_id": content_type_id, "obj_id": object_id} + ) + + try: + get_absolute_url = obj.get_absolute_url + except AttributeError: + raise Http404( + _("%(ct_name)s objects don’t have a get_absolute_url() method") + % {"ct_name": content_type.name} + ) + absurl = get_absolute_url() + + # Try to figure out the object's domain, so we can do a cross-site redirect + # if necessary. + + # If the object actually defines a domain, we're done. + if absurl.startswith(("http://", "https://", "//")): + return HttpResponseRedirect(absurl) + + # Otherwise, we need to introspect the object's relationships for a + # relation to the Site object + try: + object_domain = get_current_site(request).domain + except ObjectDoesNotExist: + object_domain = None + + if apps.is_installed("django.contrib.sites"): + Site = apps.get_model("sites.Site") + opts = obj._meta + + for field in opts.many_to_many: + # Look for a many-to-many relationship to Site. + if field.remote_field.model is Site: + site_qs = getattr(obj, field.name).all() + if object_domain and site_qs.filter(domain=object_domain).exists(): + # The current site's domain matches a site attached to the + # object. + break + # Caveat: In the case of multiple related Sites, this just + # selects the *first* one, which is arbitrary. + site = site_qs.first() + if site: + object_domain = site.domain + break + else: + # No many-to-many relationship to Site found. Look for a + # many-to-one relationship to Site. + for field in obj._meta.fields: + if field.remote_field and field.remote_field.model is Site: + try: + site = getattr(obj, field.name) + except Site.DoesNotExist: + continue + if site is not None: + object_domain = site.domain + break + + # If all that malarkey found an object domain, use it. Otherwise, fall back + # to whatever get_absolute_url() returned. + if object_domain is not None: + protocol = request.scheme + return HttpResponseRedirect("%s://%s%s" % (protocol, object_domain, absurl)) + else: + return HttpResponseRedirect(absurl) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/admin.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/admin.py new file mode 100644 index 0000000..5bbc2ad --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/admin.py @@ -0,0 +1,22 @@ +from django.contrib import admin +from django.contrib.flatpages.forms import FlatpageForm +from django.contrib.flatpages.models import FlatPage +from django.utils.translation import gettext_lazy as _ + + +@admin.register(FlatPage) +class FlatPageAdmin(admin.ModelAdmin): + form = FlatpageForm + fieldsets = ( + (None, {"fields": ("url", "title", "content", "sites")}), + ( + _("Advanced options"), + { + "classes": ("collapse",), + "fields": ("registration_required", "template_name"), + }, + ), + ) + list_display = ("url", "title") + list_filter = ("sites", "registration_required") + search_fields = ("url", "title") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/apps.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/apps.py new file mode 100644 index 0000000..eb9f470 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/apps.py @@ -0,0 +1,8 @@ +from django.apps import AppConfig +from django.utils.translation import gettext_lazy as _ + + +class FlatPagesConfig(AppConfig): + default_auto_field = "django.db.models.AutoField" + name = "django.contrib.flatpages" + verbose_name = _("Flat Pages") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/forms.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/forms.py new file mode 100644 index 0000000..136fd02 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/forms.py @@ -0,0 +1,74 @@ +from django import forms +from django.conf import settings +from django.contrib.flatpages.models import FlatPage +from django.core.exceptions import ValidationError +from django.utils.translation import gettext +from django.utils.translation import gettext_lazy as _ + + +class FlatpageForm(forms.ModelForm): + url = forms.RegexField( + label=_("URL"), + max_length=100, + regex=r"^[-\w/.~]+$", + help_text=_( + "Example: “/about/contact/”. Make sure to have leading and trailing " + "slashes." + ), + error_messages={ + "invalid": _( + "This value must contain only letters, numbers, dots, " + "underscores, dashes, slashes or tildes." + ), + }, + ) + + class Meta: + model = FlatPage + fields = "__all__" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + if not self._trailing_slash_required(): + self.fields["url"].help_text = _( + "Example: “/about/contact”. Make sure to have a leading slash." + ) + + def _trailing_slash_required(self): + return ( + settings.APPEND_SLASH + and "django.middleware.common.CommonMiddleware" in settings.MIDDLEWARE + ) + + def clean_url(self): + url = self.cleaned_data["url"] + if not url.startswith("/"): + raise ValidationError( + gettext("URL is missing a leading slash."), + code="missing_leading_slash", + ) + if self._trailing_slash_required() and not url.endswith("/"): + raise ValidationError( + gettext("URL is missing a trailing slash."), + code="missing_trailing_slash", + ) + return url + + def clean(self): + url = self.cleaned_data.get("url") + sites = self.cleaned_data.get("sites") + + same_url = FlatPage.objects.filter(url=url) + if self.instance.pk: + same_url = same_url.exclude(pk=self.instance.pk) + + if sites and same_url.filter(sites__in=sites).exists(): + for site in sites: + if same_url.filter(sites=site).exists(): + raise ValidationError( + _("Flatpage with url %(url)s already exists for site %(site)s"), + code="duplicate_url", + params={"url": url, "site": site}, + ) + + return super().clean() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/af/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/af/LC_MESSAGES/django.mo new file mode 100644 index 0000000..aef2cab Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/af/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/af/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/af/LC_MESSAGES/django.po new file mode 100644 index 0000000..dbad306 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/af/LC_MESSAGES/django.po @@ -0,0 +1,89 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# F Wolff , 2019,2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2023-12-04 19:03+0000\n" +"Last-Translator: F Wolff , 2019,2023\n" +"Language-Team: Afrikaans (http://app.transifex.com/django/django/language/" +"af/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: af\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Gevorderde keuses" + +msgid "Flat Pages" +msgstr "Plat bladsye" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Voorbeeld “/about/kontak/”. Maak seker dat dit begin en eindig met ’n " +"skuinsstreep." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Hierdie waarde moet slegs letters, syfers, punte, onderstrepies, " +"koppeltekens, skuinsstrepe of tildes bevat." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" +"Voorbeeld “/about/kontak/”. Maak seker dat dit begin met ’n skuinsstreep." + +msgid "URL is missing a leading slash." +msgstr "’n Skuinsstreep ontbreek vooraan URL." + +msgid "URL is missing a trailing slash." +msgstr "’n Skuinsstreep ontbreek agteraan URL." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Plat bladsy met URL %(url)s bestaan reeds vir die werf %(site)s" + +msgid "title" +msgstr "titel" + +msgid "content" +msgstr "inhoud" + +msgid "enable comments" +msgstr "aktiveer opmerkings" + +msgid "template name" +msgstr "sjabloonnaam" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Voorbeeld “/flatpages/kontakbladsy.html”. As dit weggelaat word, sal die " +"stelsel “flatpages/default.html” gebruik." + +msgid "registration required" +msgstr "registrasie benodig" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"As hierdie gemerk is, sal slegs aangemelde gebruikers die bladsy kan bekyk." + +msgid "sites" +msgstr "werwe" + +msgid "flat page" +msgstr "plat bladsy" + +msgid "flat pages" +msgstr "plat bladsye" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ar/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ar/LC_MESSAGES/django.mo new file mode 100644 index 0000000..be793de Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ar/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ar/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ar/LC_MESSAGES/django.po new file mode 100644 index 0000000..984d77d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ar/LC_MESSAGES/django.po @@ -0,0 +1,91 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bashar Al-Abdulhadi, 2015 +# Bashar Al-Abdulhadi, 2014 +# Eyad Toma , 2013 +# Jannis Leidel , 2011 +# Muaaz Alsaied, 2020 +# Ossama Khayat , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-04-02 11:30+0000\n" +"Last-Translator: Muaaz Alsaied\n" +"Language-Team: Arabic (http://www.transifex.com/django/django/language/ar/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +msgid "Advanced options" +msgstr "خيارات متقدّمة" + +msgid "Flat Pages" +msgstr "صفحات مسطحة" + +msgid "URL" +msgstr "رابط" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "مثال: “/about/contact/”. تأكد من وضع فواصل مائلة في البداية والنهاية." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"يجب أن تحتوي هذه القيمة الأحرف والأرقام والنقاط وعلامات _ و - و / أو ~ فقط." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "مثال: “/about/contact/”. تأكد من وضع فواصل مائلة في البداية." + +msgid "URL is missing a leading slash." +msgstr "العنوان URL يفقد رمز / في بدايته." + +msgid "URL is missing a trailing slash." +msgstr "العنوان URL يفقد رمز / في نهايته." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "الصفحة ذو العنوان %(url)s موجودة سابقاً في موقع %(site)s" + +msgid "title" +msgstr "العنوان" + +msgid "content" +msgstr "المحتوى" + +msgid "enable comments" +msgstr "السماح بالتعليقات" + +msgid "template name" +msgstr "اسم القالب" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"مثال: “flatpages/contact_page.html”. إن لم يكن هذا موجوداً، فسوف يستخدم " +"النظام 'flatpages/default.html'." + +msgid "registration required" +msgstr "التسجيل مطلوب" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"إذا كان هذا الخيار محددا، فإن المستخدمين الداخلين فقط سيتمكنون من مشاهدة " +"الصفحة." + +msgid "sites" +msgstr "المواقع" + +msgid "flat page" +msgstr "صفحة مسطحة" + +msgid "flat pages" +msgstr "صفحات مسطحة" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ar_DZ/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ar_DZ/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e494972 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ar_DZ/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ar_DZ/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ar_DZ/LC_MESSAGES/django.po new file mode 100644 index 0000000..8e87c9b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ar_DZ/LC_MESSAGES/django.po @@ -0,0 +1,87 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Riterix , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-12-14 18:57+0000\n" +"Last-Translator: Riterix \n" +"Language-Team: Arabic (Algeria) (http://www.transifex.com/django/django/" +"language/ar_DZ/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar_DZ\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +msgid "Advanced options" +msgstr "خيارات متقدمة" + +msgid "Flat Pages" +msgstr "صفحات مسطحة" + +msgid "URL" +msgstr "رابط" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "مثال: '/about/contact/'. تأكد من وضع شرطات في البداية والنهاية." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"يجب أن تحتوي هذه القيمة الأحرف والأرقام والنقاط وعلامات _ و - و / أو ~ فقط." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "مثال: '/about/contact/'. تأكد من وضع شرطات في البداية." + +msgid "URL is missing a leading slash." +msgstr "العنوان URL يفقد رمز / في بدايته." + +msgid "URL is missing a trailing slash." +msgstr "العنوان URL يفقد رمز / في نهايته." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "الصفحة ذو العنوان %(url)s موجودة سابقاً في موقع %(site)s" + +msgid "title" +msgstr "العنوان" + +msgid "content" +msgstr "المحتوى" + +msgid "enable comments" +msgstr "السماح بالتعليقات" + +msgid "template name" +msgstr "اسم القالب" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"مثال: 'flatpages/contact_page.html'. إن لم تكن الصفحة موجودة، فسوف يستخدم " +"النظام 'flatpages/default.html'." + +msgid "registration required" +msgstr "التسجيل مطلوب" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"إذا كان هذا الخيار محددا، فإن المستخدمين الداخلين فقط سيتمكنون من مشاهدة " +"الصفحة." + +msgid "sites" +msgstr "المواقع" + +msgid "flat page" +msgstr "صفحة مسطحة" + +msgid "flat pages" +msgstr "صفحات مسطحة" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ast/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ast/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4fcf510 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ast/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ast/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ast/LC_MESSAGES/django.po new file mode 100644 index 0000000..3b618d0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ast/LC_MESSAGES/django.po @@ -0,0 +1,80 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ḷḷumex03 , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-23 19:51+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Asturian (http://www.transifex.com/django/django/language/" +"ast/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ast\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Opciones avanzaes" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" + +msgid "URL is missing a leading slash." +msgstr "" + +msgid "URL is missing a trailing slash." +msgstr "" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" + +msgid "title" +msgstr "títulu" + +msgid "content" +msgstr "conteníu" + +msgid "enable comments" +msgstr "habilitar comentarios" + +msgid "template name" +msgstr "" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" + +msgid "registration required" +msgstr "requierse rexistru" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Si esto ta conseñao, namái los usuarios con sesión aniciada podrán ver la " +"páxina." + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "" + +msgid "flat pages" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/az/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/az/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c122551 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/az/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/az/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/az/LC_MESSAGES/django.po new file mode 100644 index 0000000..e2d56f8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/az/LC_MESSAGES/django.po @@ -0,0 +1,93 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ali Ismayilov , 2011 +# Dimitris Glezos , 2012 +# Emin Mastizada , 2018,2020 +# Emin Mastizada , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-01-12 07:27+0000\n" +"Last-Translator: Emin Mastizada \n" +"Language-Team: Azerbaijani (http://www.transifex.com/django/django/language/" +"az/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: az\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Əlavə imkanlar" + +msgid "Flat Pages" +msgstr "Flat Səhifələr" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Məsələn, “/about/contact/”. Əvvəldə və sondakı kəsr xəttinin olmasına diqqət " +"edin." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Burada yalnız hərf, rəqəm, nöqtə, altdan xətt, defis, kəsr xətti və ya " +"tildadan istifadə etmək olar." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" +"Məsələn, “/about/contact”. Əvvəldəki kəsr xəttinin olmasına diqqət edin." + +msgid "URL is missing a leading slash." +msgstr "Ünvan başlanğıcında çəp xətt əksikdir." + +msgid "URL is missing a trailing slash." +msgstr "Ünvan sonunda çəp xətt əksikdir." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "%(site)s saytı üçün artıq %(url)s ünvanlı Flatpage mövcuddur" + +msgid "title" +msgstr "başlıq" + +msgid "content" +msgstr "məzmun" + +msgid "enable comments" +msgstr "şərhlər olsun" + +msgid "template name" +msgstr "şablonun adı" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Məsələn, “flatpages/contact_page.html”. Əgər təchiz edilməsə, sistem " +"“flatpages/default.html” işlədəcək." + +msgid "registration required" +msgstr "ancaq qeydiyyatlılar üçün" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Əgər bura quş qoysanız, ancaq qeydiyyatdan keçib sayta daxil olmuş " +"istifadəçilər bu səhifəni görə biləcəklər." + +msgid "sites" +msgstr "saytlar" + +msgid "flat page" +msgstr "adi səhifə" + +msgid "flat pages" +msgstr "adi səhifələr" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/be/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/be/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5c02d66 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/be/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/be/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/be/LC_MESSAGES/django.po new file mode 100644 index 0000000..f32e3c1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/be/LC_MESSAGES/django.po @@ -0,0 +1,92 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# znotdead , 2016,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-10-16 18:27+0000\n" +"Last-Translator: znotdead \n" +"Language-Team: Belarusian (http://www.transifex.com/django/django/language/" +"be/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: be\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n" +"%100>=11 && n%100<=14)? 2 : 3);\n" + +msgid "Advanced options" +msgstr "Адмысловыя можнасьці" + +msgid "Flat Pages" +msgstr "Нязменныя Бачыны" + +msgid "URL" +msgstr "Сеціўная спасылка" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Прыклад: «/about/contact/». Упэўніцеся, што адрас пачынаецца й заканчваецца " +"рыскаю «/»." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Дазваляюцца толькі літары, лічбы, кропкі, знак падкрэсьліваньня, злучкі, " +"нахіленыя рыскі, тыльды." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" +"Прыклад: «/about/contact/». Упэўніцеся, што адрас пачынаецца рыскаю «/»." + +msgid "URL is missing a leading slash." +msgstr "Спасылка не пачынаецца з рыскі «/»." + +msgid "URL is missing a trailing slash." +msgstr "Спасылка не заканчваецца рыскаю «/»." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "На пляцоўцы «%(site)s» ужо існуе нязьменная бачына з адрасам «%(url)s»" + +msgid "title" +msgstr "назва" + +msgid "content" +msgstr "зьмесьціва" + +msgid "enable comments" +msgstr "дазволіць выказваньні" + +msgid "template name" +msgstr "назва шаблёну" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Прыклад: “flatpages/contact_page.html”. Калі не пазначаць нічога, сыстэма " +"будзе ўжываць “flatpages/default.html”." + +msgid "registration required" +msgstr "трэба запісацца" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Калі абраць гэта, бачыну змогуць пабачыць толькі тыя карыстальнікі, што " +"апазналіся." + +msgid "sites" +msgstr "сайты" + +msgid "flat page" +msgstr "нязьменная бачына" + +msgid "flat pages" +msgstr "нязьменныя бачыны" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/bg/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/bg/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e7633dd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/bg/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/bg/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/bg/LC_MESSAGES/django.po new file mode 100644 index 0000000..f7e3535 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/bg/LC_MESSAGES/django.po @@ -0,0 +1,92 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# arneatec , 2022 +# Jannis Leidel , 2011 +# Venelin Stoykov , 2016 +# vestimir , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2022-01-14 11:31+0000\n" +"Last-Translator: arneatec \n" +"Language-Team: Bulgarian (http://www.transifex.com/django/django/language/" +"bg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Допълнителни опции" + +msgid "Flat Pages" +msgstr "Информативни страници" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Пример: \"/about/contact/\". Началната и крайната наклонена чертичка са " +"задължителни." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Тази стойност трябва да съдържа само букви, цифри, точки, долни тирета, " +"тирета, наклонени черти или тилди." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" +"Пример: \"/about/contact/\". Началната наклонена чертичка е задължителна. " + +msgid "URL is missing a leading slash." +msgstr "В URL липсва начална наклонена черта." + +msgid "URL is missing a trailing slash." +msgstr "В URL липсва завършваща наклонена черта." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Flatpage с url %(url)s вече съществува за сайт %(site)s" + +msgid "title" +msgstr "заглавие" + +msgid "content" +msgstr "съдържание" + +msgid "enable comments" +msgstr "позволяване на коментари" + +msgid "template name" +msgstr "име на шаблон" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Пример: \"flatpages/contact_page.html\". Ако това не е указано, системата " +"ще използва \"flatpages/default.html\". " + +msgid "registration required" +msgstr "изисква се регистрация" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Ако това е чекнато, само логнати потребители ще могат да виждат страницата. " + +msgid "sites" +msgstr "сайтове" + +msgid "flat page" +msgstr "информативна страница" + +msgid "flat pages" +msgstr "информативни страници" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/bn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/bn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9465be4 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/bn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/bn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/bn/LC_MESSAGES/django.po new file mode 100644 index 0000000..7885c6c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/bn/LC_MESSAGES/django.po @@ -0,0 +1,83 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Tahmid Rafi , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Bengali (http://www.transifex.com/django/django/language/" +"bn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "এডভান্সড অপশন" + +msgid "Flat Pages" +msgstr "ফ্ল্যাট পেজ" + +msgid "URL" +msgstr "ইউআরএল (URL)" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "উদাহরণঃ '/about/contact/'। শুরু এবং শেষের স্ল্যাশগুলো আবশ্যক।" + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"এই মানটিতে শুধুমাত্র বর্ণ, অঙ্ক, পিরিয়ড, আন্ডারস্কোর, ড্যাশ, স্ল্যাশ অথবা টিল্ড " +"ক্যারেক্টার থাকতে পারবে।" + +msgid "URL is missing a leading slash." +msgstr "ইউআরএল টির শুরুর স্ল্যাশ চিহ্নটি দেওয়া হয় নি।" + +msgid "URL is missing a trailing slash." +msgstr "ইউআরএল টির শেষের স্ল্যাশ চিহ্নটি দেওয়া হয় নি।" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "%(site)s সাইটের জন্য %(url)s ইউআরএল এর ফ্ল্যাটপেজ আগেই তৈরী করা হয়েছ।" + +msgid "title" +msgstr "শিরোনাম" + +msgid "content" +msgstr "কনটেন্ট" + +msgid "enable comments" +msgstr "মন্তব্য প্রদান সচল করুন" + +msgid "template name" +msgstr "টেমপ্লেট নাম" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"উদাহরণঃ ’flatpage/contact_page.html'। এটি যদি খালি থাকে, তবে সিস্টেম " +"’flatpage/default.html' ব্যবহার করবে।" + +msgid "registration required" +msgstr "নিবন্ধন আবশ্যক" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "এটি চেক করা হলে, শুধুমাত্র লগইন করা সদস্যরা পাতাটি দেখতে সমর্থ হবেন।" + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "ফ্লাট পাতা" + +msgid "flat pages" +msgstr "ফ্লাট পাতা সমূহ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/br/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/br/LC_MESSAGES/django.mo new file mode 100644 index 0000000..48e491e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/br/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/br/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/br/LC_MESSAGES/django.po new file mode 100644 index 0000000..8fb6f1f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/br/LC_MESSAGES/django.po @@ -0,0 +1,95 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Fulup , 2012 +# Irriep Nala Novram , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2019-03-12 14:19+0000\n" +"Last-Translator: Irriep Nala Novram \n" +"Language-Team: Breton (http://www.transifex.com/django/django/language/br/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: br\n" +"Plural-Forms: nplurals=5; plural=((n%10 == 1) && (n%100 != 11) && (n%100 !" +"=71) && (n%100 !=91) ? 0 :(n%10 == 2) && (n%100 != 12) && (n%100 !=72) && (n" +"%100 !=92) ? 1 :(n%10 ==3 || n%10==4 || n%10==9) && (n%100 < 10 || n% 100 > " +"19) && (n%100 < 70 || n%100 > 79) && (n%100 < 90 || n%100 > 99) ? 2 :(n != 0 " +"&& n % 1000000 == 0) ? 3 : 4);\n" + +msgid "Advanced options" +msgstr "Dibarzhioù araokaet" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"Da skouer: '/diwar-benn/darempred/'. Bezit sur da gaout beskellioù \"/\" e " +"penn-kentañ hag e fin ar chadenn." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"An dalvoudegezh-mañ a c'hall enderc'hel lizherennoù hepken, sifroù, pikoù, " +"barrennigoù islinennañ, beskellioù pe tildeoù c'hoazh." + +msgid "Example: '/about/contact'. Make sure to have a leading slash." +msgstr "" + +msgid "URL is missing a leading slash." +msgstr "An URL a vank enni ur veskell \"/\" en he fenn-kentañ." + +msgid "URL is missing a trailing slash." +msgstr "An URL a vank enni ur veskell \"/\" en he dilost." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" +"Ar bajenn difiñv d'an URL %(url)s a zo anezhi e-barzh al lec'hienn %(site)s " +"endeo" + +msgid "title" +msgstr "titl" + +msgid "content" +msgstr "danvez" + +msgid "enable comments" +msgstr "aotren an evezhiadennoù" + +msgid "template name" +msgstr "anv patrom" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"Da skouer : 'flatpages/contact_page.html'. Ma neket pourvezet, ar sistem a " +"raio gant 'flatpages/default.html'." + +msgid "registration required" +msgstr "enskrivadur rekiset" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Ma vez kochet, ar bajenn a c'hallo bezañ gwelet gant an implijerien kevreet " +"hepken." + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "pajenn difiñv" + +msgid "flat pages" +msgstr "pajennoù difiñv" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/bs/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/bs/LC_MESSAGES/django.mo new file mode 100644 index 0000000..752f8f3 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/bs/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/bs/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/bs/LC_MESSAGES/django.po new file mode 100644 index 0000000..ddc6823 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/bs/LC_MESSAGES/django.po @@ -0,0 +1,88 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Filip Dupanović , 2011 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Bosnian (http://www.transifex.com/django/django/language/" +"bs/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bs\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Advanced options" +msgstr "Napredna podešavanja" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"Primjer: '/about/contact/'. Pazite na to da postoje i početne i završne kose " +"crte." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Ova vrijednost smije samo sadržati slova, brijeve, tačke, donje crte, crte, " +"kose crte i tilde." + +msgid "URL is missing a leading slash." +msgstr "" + +msgid "URL is missing a trailing slash." +msgstr "" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" + +msgid "title" +msgstr "naslov" + +msgid "content" +msgstr "sadržaj" + +msgid "enable comments" +msgstr "omogući komentare" + +msgid "template name" +msgstr "naziv obrazca" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"Primjer: 'flatpages/contact_page.html'. Ako ovo ostavite praznim, sistem će " +"koristiti 'flatpages/default.html'." + +msgid "registration required" +msgstr "registracija obavezna" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Ako je ovo obilježeno, samo će prijavljeni korisnici moći da vide ovu " +"stranicu." + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "statična stranica" + +msgid "flat pages" +msgstr "statične stranice" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ca/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ca/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9d5dcc1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ca/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ca/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ca/LC_MESSAGES/django.po new file mode 100644 index 0000000..ff25561 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ca/LC_MESSAGES/django.po @@ -0,0 +1,93 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Antoni Aloy , 2011 +# Carles Barrobés , 2012,2014 +# Gil Obradors Via , 2019 +# Jannis Leidel , 2011 +# Manel Clos , 2020 +# Roger Pons , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-04-28 20:26+0000\n" +"Last-Translator: Manel Clos \n" +"Language-Team: Catalan (http://www.transifex.com/django/django/language/" +"ca/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ca\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Opcions avançades" + +msgid "Flat Pages" +msgstr "Pàgines Estàtiques" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Exemple: '/about/contact/'. Assegureu-vos de posar les barres al principi i " +"al final." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Aquest valor sols pot contenir lletres, nombres, punts, subratllats, guions, " +"barres o accents." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" +"Exemple: '/about/contact/'. Assegureu-vos de posar la barra al principi." + +msgid "URL is missing a leading slash." +msgstr "La URL no comença amb \"/\"." + +msgid "URL is missing a trailing slash." +msgstr "La URL no acaba amb \"/\"." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Ja hi ha una pàgina estàtica amb la URL %(url)s per al lloc %(site)s" + +msgid "title" +msgstr "títol" + +msgid "content" +msgstr "contingut" + +msgid "enable comments" +msgstr "habilitar comentaris" + +msgid "template name" +msgstr "nom de la plantilla" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Exemple: 'flatpages/contact_page.html'. Si no es proporciona, el sistema " +"utilitzarà 'flatpages/default.html'." + +msgid "registration required" +msgstr "cal estar registrat" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "Si està marcat, només els usuaris registrats podran veure la pàgina." + +msgid "sites" +msgstr "llocs" + +msgid "flat page" +msgstr "pàgina estàtica" + +msgid "flat pages" +msgstr "pàgines estàtiques" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ckb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ckb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1448347 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ckb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ckb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ckb/LC_MESSAGES/django.po new file mode 100644 index 0000000..42548f9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ckb/LC_MESSAGES/django.po @@ -0,0 +1,88 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# kosar tofiq , 2020 +# Swara , 2022 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2023-04-24 19:03+0000\n" +"Last-Translator: Swara , 2022\n" +"Language-Team: Central Kurdish (http://www.transifex.com/django/django/" +"language/ckb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ckb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "هەڵبژاردنە پێشکەوتووەکان" + +msgid "Flat Pages" +msgstr "لاپەڕە تەختەکان" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "نمونە: “/about/contact/”. دڵنیابە کە هێڵی لاری پێش و پاشت نوسیوە." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"ئەم بەهایە دەبێت تەنها پیت، ژمارە، خاڵ، ژێر هێڵ، هێڵ، هێڵی لار یان پێچ " +"لەخۆبگرێت." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "نمونە: “/about/contact”. دڵنیابە کە هێڵی لاری پێشەوەت نوسیوە" + +msgid "URL is missing a leading slash." +msgstr "URL هێڵێکی لاری سەرەتای تێدا نییە." + +msgid "URL is missing a trailing slash." +msgstr "URL هێڵێکی لاری لە دواوە کەمە." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "لاپەڕەی تەخت لەگەڵ url %(url)s پێشتر بوونی هەیە بۆ پێگەی %(site)s" + +msgid "title" +msgstr "ناونیشان" + +msgid "content" +msgstr "ناوەخن" + +msgid "enable comments" +msgstr "چالاککردنی سەرنجەکان" + +msgid "template name" +msgstr "ناوی ڕووکار" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"نمونە: “flatpages/contact_page.html”. ئەگەر ئەمە دابین نەکراوە, سیستەمەکە " +"“flatpages/default.html” بەکاردەهێنێت." + +msgid "registration required" +msgstr "تۆمارکردن داواکراوە" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"ئەگەر ئەمە هەڵبژێردرابێت، ئەوا تەنها ئەو بەکارهێنەرانەی لە ژوورەوەن دەتوانن " +"ئەم لاپەڕە ببینن." + +msgid "sites" +msgstr "ماڵپەڕەکان" + +msgid "flat page" +msgstr "لاپەڕەی تەخت" + +msgid "flat pages" +msgstr "لاپەڕە تەختەکان" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/cs/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/cs/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2a73798 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/cs/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/cs/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/cs/LC_MESSAGES/django.po new file mode 100644 index 0000000..abf9bed --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/cs/LC_MESSAGES/django.po @@ -0,0 +1,89 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Vláďa Macek , 2011-2012,2014 +# Vláďa Macek , 2015,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-09-19 09:23+0000\n" +"Last-Translator: Vláďa Macek \n" +"Language-Team: Czech (http://www.transifex.com/django/django/language/cs/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cs\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n " +"<= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n" + +msgid "Advanced options" +msgstr "Pokročilá nastavení" + +msgid "Flat Pages" +msgstr "Statické stránky" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Příklad: \"/about/contact/\". Ujistěte se, že máte počáteční a konečná " +"lomítka." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Tato hodnota musí obsahovat pouze písmena, číslice, tečky, podtržítka, " +"pomlčky, lomítka nebo vlnovky." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "Příklad: \"/about/contact\". Úvodní lomítko je důležité." + +msgid "URL is missing a leading slash." +msgstr "V adrese URL chybí úvodní lomítko." + +msgid "URL is missing a trailing slash." +msgstr "V adrese URL chybí koncové lomítko." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Flat stránka s adresou %(url)s pro web %(site)s již existuje." + +msgid "title" +msgstr "titulek" + +msgid "content" +msgstr "obsah" + +msgid "enable comments" +msgstr "povolit komentáře" + +msgid "template name" +msgstr "název šablony" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Příklad: \"flatpages/kontaktni_stranka.html\". Pokud toto není zadáno, bude " +"použita šablona \"flatpages/default.html\"." + +msgid "registration required" +msgstr "nutná registrace" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "Určuje, že tuto stránku uvidí pouze přihlášení uživatelé." + +msgid "sites" +msgstr "weby" + +msgid "flat page" +msgstr "statická stránka" + +msgid "flat pages" +msgstr "statické stránky" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/cy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/cy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..dbc7227 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/cy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/cy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/cy/LC_MESSAGES/django.po new file mode 100644 index 0000000..b910e11 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/cy/LC_MESSAGES/django.po @@ -0,0 +1,88 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Maredudd ap Gwyndaf , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Welsh (http://www.transifex.com/django/django/language/cy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cy\n" +"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != " +"11) ? 2 : 3;\n" + +msgid "Advanced options" +msgstr "Opsiynau uwch" + +msgid "Flat Pages" +msgstr "Tudalennau Fflat" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"Enghraifft: '/amdanom/cyswllt/'. Sicrhewch fod gennych slaesau ar y dechrau " +"a'r diwedd." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Gall y gwerth hwn ond gynnwys llythrennau, rhifau, dotiau, tanlinellau, " +"llinellau doriad, slaesau neu tildeau." + +msgid "URL is missing a leading slash." +msgstr "Mae'r slaes ar goll ar ddechrau'r URL." + +msgid "URL is missing a trailing slash." +msgstr "Mae slaes ar goll ar ddiwedd yr URL." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" +"Mae flatpage gyda'r url %(url)s yn bodoli yn barod am y safle %(site)s" + +msgid "title" +msgstr "teitl" + +msgid "content" +msgstr "cynnwys" + +msgid "enable comments" +msgstr "galluogi sylwadau" + +msgid "template name" +msgstr "enw'r templed" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"Enghraifft: 'flatpages/tudalen_cyswllt.html'. Os na ddarparir hyn, bydd y " +"system yn defnyddio 'flatpages/default.html'." + +msgid "registration required" +msgstr "cofrestriad gofynnol" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Os ticir hwn, dim ond defnyddwyr sydd wedi mewngofnodi bydd yn gallu gweld y " +"dudalen." + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "tudalen fflat" + +msgid "flat pages" +msgstr "tudalennau fflat" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/da/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/da/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0e7f50d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/da/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/da/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/da/LC_MESSAGES/django.po new file mode 100644 index 0000000..133810a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/da/LC_MESSAGES/django.po @@ -0,0 +1,92 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Christian Joergensen , 2012 +# Erik Wognsen , 2012,2014-2015,2019 +# Finn Gruwier Larsen, 2011 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-09-17 18:11+0000\n" +"Last-Translator: Erik Wognsen \n" +"Language-Team: Danish (http://www.transifex.com/django/django/language/da/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: da\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Avancerede muligheder" + +msgid "Flat Pages" +msgstr "Flade sider" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Eksempel: “/om/kontakt/”. Vær opmærksom på, at der skal være skråstreg både " +"først og sidst." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Denne værdi må kun indeholde bogstaver, tal, punktum, understreger, " +"bindestreger, skråstreger eller tilder." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" +"Eksempel: “/om/kontakt/”. Vær opmærksom på, at der skal være skråstreg først." + +msgid "URL is missing a leading slash." +msgstr "URL mangler en skråstreg i starten." + +msgid "URL is missing a trailing slash." +msgstr "URL mangler en afsluttende skråstreg." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "En flad side med URL'en %(url)s eksisterer allerede for siden %(site)s" + +msgid "title" +msgstr "titel" + +msgid "content" +msgstr "indhold" + +msgid "enable comments" +msgstr "tillad kommentarer" + +msgid "template name" +msgstr "skabelonnavn" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Eksempel: “flatpages/kontaktside”. Hvis dette ikke gives bruger systemet " +"“flatpages/default”." + +msgid "registration required" +msgstr "registrering påkrævet" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Hvis denne boks er markeret, vil kun brugere der er logget ind, kunne se " +"siden." + +msgid "sites" +msgstr "websider" + +msgid "flat page" +msgstr "flad side" + +msgid "flat pages" +msgstr "flade sider" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/de/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/de/LC_MESSAGES/django.mo new file mode 100644 index 0000000..bd863e2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/de/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/de/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/de/LC_MESSAGES/django.po new file mode 100644 index 0000000..9aac43b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/de/LC_MESSAGES/django.po @@ -0,0 +1,92 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# André Hagenbruch, 2012 +# Jannis Leidel , 2011,2013-2017,2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-01-17 23:00+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: German (http://www.transifex.com/django/django/language/de/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Erweiterte Optionen" + +msgid "Flat Pages" +msgstr "Flat Pages" + +msgid "URL" +msgstr "Adresse (URL)" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Beispiel: „/about/contact/“. Wichtig: Am Anfang und Ende muss ein " +"Schrägstrich („/“) stehen." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Dieser Wert darf nur Buchstaben, Ziffern, Punkte, Unterstriche, " +"Bindestriche, Schrägstriche und Tilden enthalten." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" +"Beispiel: „/about/contact“. Wichtig: Am Anfang muss ein Schrägstrich („/“) " +"stehen." + +msgid "URL is missing a leading slash." +msgstr "Der URL fehlt ein vorangestellter Schrägstrich." + +msgid "URL is missing a trailing slash." +msgstr "Der URL fehlt ein abschließender Schrägstrich." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" +"Flatpage mit der URL %(url)s ist für die Website %(site)s bereits vorhanden" + +msgid "title" +msgstr "Titel" + +msgid "content" +msgstr "Inhalt" + +msgid "enable comments" +msgstr "Kommentare aktivieren" + +msgid "template name" +msgstr "Name des Templates" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Beispiel: „flatpages/contact_page.html“. Wenn dieses Feld nicht gesetzt ist, " +"wird standardmäßig „flatpages/default.html“ benutzt." + +msgid "registration required" +msgstr "Registrierung erforderlich" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Wenn hier ein Haken gesetzt ist, können nur angemeldete Benutzer die Seite " +"sehen." + +msgid "sites" +msgstr "Websites" + +msgid "flat page" +msgstr "Flat Page" + +msgid "flat pages" +msgstr "Flat Pages" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/dsb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/dsb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..61c6eb0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/dsb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/dsb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/dsb/LC_MESSAGES/django.po new file mode 100644 index 0000000..c6fc553 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/dsb/LC_MESSAGES/django.po @@ -0,0 +1,90 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Michael Wolf , 2016,2019-2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-02-25 16:06+0000\n" +"Last-Translator: Michael Wolf \n" +"Language-Team: Lower Sorbian (http://www.transifex.com/django/django/" +"language/dsb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: dsb\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" + +msgid "Advanced options" +msgstr "Rozšyrjone nastajenja" + +msgid "Flat Pages" +msgstr "Statiske boki" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Pśikład: „/about/contact/“. Pśeznańśo se, až sćo pódał wócynjajucu a " +"zacynjajucu nakósnu smužku." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Toś ta gódnota smějo jano pismiki, licby, dypki, pódsmužki, , wězawki, " +"nakósne smužki abo tildy wopśimowaś." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" +"Pśikład: „/about/contact“. Pśeznańśo se, až maśo wjeducu nakósnu smužku." + +msgid "URL is missing a leading slash." +msgstr "URL njama wócynjajucu nakósnu smužku." + +msgid "URL is missing a trailing slash." +msgstr "URL njama zacynjajucu nakósnu smužku." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Statiski bok z url %(url)s južo eksistěrujo za sedło %(site)s" + +msgid "title" +msgstr "titel" + +msgid "content" +msgstr "wopśimjeśe" + +msgid "enable comments" +msgstr "komentary zmóžniś" + +msgid "template name" +msgstr "mě pśedłogi" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Pśikład: „flatpages/contact_page.html“. Jolic to njejo pódane, buźo system " +"„flatpages/default.html“ wužywaś." + +msgid "registration required" +msgstr "registrěrowanje trěbne" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Jolic to jo zmóžnjone, mógu se jano pśizjawjone wužywarje bok woglědaś." + +msgid "sites" +msgstr "sedła" + +msgid "flat page" +msgstr "statiski bok" + +msgid "flat pages" +msgstr "statiske boki" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/el/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/el/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f9174a1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/el/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/el/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/el/LC_MESSAGES/django.po new file mode 100644 index 0000000..1f34dae --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/el/LC_MESSAGES/django.po @@ -0,0 +1,93 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Dimitris Glezos , 2011 +# Fotis Athineos , 2021 +# Jannis Leidel , 2011 +# Pãnoș , 2014 +# Pãnoș , 2016,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2021-08-04 06:27+0000\n" +"Last-Translator: Fotis Athineos \n" +"Language-Team: Greek (http://www.transifex.com/django/django/language/el/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: el\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Προχωρημένες επιλογές" + +msgid "Flat Pages" +msgstr "Απλές Σελίδες" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Παράδειγμα: “/about/contact/“. Βεβαιωθείτε ότι περιέχει καθέτους στην αρχή " +"και το τέλος." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Η τιμή αυτή πρέπει να περιέχει μόνο γράμματα, αριθμούς, τελείες, παύλες, " +"κάτω παύλες, καθέτους ή περισπωμένες." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" +"Παράδειγμα: “/about/contact/“. Βεβαιωθείτε ότι περιέχει κάθετο στην αρχή." + +msgid "URL is missing a leading slash." +msgstr "Λείπει μια αρχική κάθετος από την διεύθυνση." + +msgid "URL is missing a trailing slash." +msgstr "Λείπει μια τελική κάθετος από τη διεύθυνση." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" +"Υπάρχει ήδη Απλή σελίδα με διεύθυνση %(url)s για την ιστοσελίδα %(site)s" + +msgid "title" +msgstr "τίτλος" + +msgid "content" +msgstr "περιεχόμενο" + +msgid "enable comments" +msgstr "ενεργοποίηση σχολίων" + +msgid "template name" +msgstr "όνομα περιγράμματος" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Παράδειγμα: “flatpages/contact_page.html“. Αν δεν δηλωθεί, το σύστημα θα " +"χρησιμοποιήσει το “flatpages/default.html“." + +msgid "registration required" +msgstr "απαιτείται εγγραφή" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Εάν επιλεγεί, μόνο συνδεδεμένοι χρήστες θα μπορούν να βλέπουν τη σελίδα." + +msgid "sites" +msgstr "ιστότοποι" + +msgid "flat page" +msgstr "απλή σελίδα" + +msgid "flat pages" +msgstr "απλές σελίδες" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/en/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/en/LC_MESSAGES/django.mo new file mode 100644 index 0000000..08a7b68 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/en/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/en/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/en/LC_MESSAGES/django.po new file mode 100644 index 0000000..8fe158e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/en/LC_MESSAGES/django.po @@ -0,0 +1,96 @@ +# This file is distributed under the same license as the Django package. +# +msgid "" +msgstr "" +"Project-Id-Version: Django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2010-05-13 15:35+0200\n" +"Last-Translator: Django team\n" +"Language-Team: English \n" +"Language: en\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: contrib/flatpages/admin.py:12 +msgid "Advanced options" +msgstr "" + +#: contrib/flatpages/apps.py:7 +msgid "Flat Pages" +msgstr "" + +#: contrib/flatpages/forms.py:9 contrib/flatpages/models.py:9 +msgid "URL" +msgstr "" + +#: contrib/flatpages/forms.py:12 +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" + +#: contrib/flatpages/forms.py:15 +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" + +#: contrib/flatpages/forms.py:29 +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" + +#: contrib/flatpages/forms.py:42 +msgid "URL is missing a leading slash." +msgstr "" + +#: contrib/flatpages/forms.py:47 +msgid "URL is missing a trailing slash." +msgstr "" + +#: contrib/flatpages/forms.py:64 +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" + +#: contrib/flatpages/models.py:10 +msgid "title" +msgstr "" + +#: contrib/flatpages/models.py:11 +msgid "content" +msgstr "" + +#: contrib/flatpages/models.py:12 +msgid "enable comments" +msgstr "" + +#: contrib/flatpages/models.py:14 +msgid "template name" +msgstr "" + +#: contrib/flatpages/models.py:18 +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" + +#: contrib/flatpages/models.py:23 +msgid "registration required" +msgstr "" + +#: contrib/flatpages/models.py:24 +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" + +#: contrib/flatpages/models.py:27 +msgid "sites" +msgstr "" + +#: contrib/flatpages/models.py:31 +msgid "flat page" +msgstr "" + +#: contrib/flatpages/models.py:32 +msgid "flat pages" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/en_AU/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/en_AU/LC_MESSAGES/django.mo new file mode 100644 index 0000000..354cbe6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/en_AU/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/en_AU/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/en_AU/LC_MESSAGES/django.po new file mode 100644 index 0000000..9e09c70 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/en_AU/LC_MESSAGES/django.po @@ -0,0 +1,88 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Katie McLaughlin , 2021 +# Tom Fifield , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2021-06-23 07:20+0000\n" +"Last-Translator: Katie McLaughlin \n" +"Language-Team: English (Australia) (http://www.transifex.com/django/django/" +"language/en_AU/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_AU\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Advanced options" + +msgid "Flat Pages" +msgstr "Flat Pages" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "Example: “/about/contact”. Make sure to have a leading slash." + +msgid "URL is missing a leading slash." +msgstr "URL is missing a leading slash." + +msgid "URL is missing a trailing slash." +msgstr "URL is missing a trailing slash." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Flatpage with url %(url)s already exists for site %(site)s" + +msgid "title" +msgstr "title" + +msgid "content" +msgstr "content" + +msgid "enable comments" +msgstr "enable comments" + +msgid "template name" +msgstr "template name" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." + +msgid "registration required" +msgstr "registration required" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"If this is checked, only logged-in users will be able to view the page." + +msgid "sites" +msgstr "sites" + +msgid "flat page" +msgstr "flat page" + +msgid "flat pages" +msgstr "flat pages" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/en_GB/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/en_GB/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a85d1d1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/en_GB/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/en_GB/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/en_GB/LC_MESSAGES/django.po new file mode 100644 index 0000000..68b6158 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/en_GB/LC_MESSAGES/django.po @@ -0,0 +1,85 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# jon_atkinson , 2012 +# Ross Poulton , 2011-2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: English (United Kingdom) (http://www.transifex.com/django/" +"django/language/en_GB/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_GB\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Advanced options" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." + +msgid "URL is missing a leading slash." +msgstr "URL is missing a leading slash." + +msgid "URL is missing a trailing slash." +msgstr "URL is missing a trailing slash." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Flatpage with url %(url)s already exists for site %(site)s" + +msgid "title" +msgstr "title" + +msgid "content" +msgstr "content" + +msgid "enable comments" +msgstr "enable comments" + +msgid "template name" +msgstr "template name" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." + +msgid "registration required" +msgstr "registration required" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"If this is checked, only logged-in users will be able to view the page." + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "flat page" + +msgid "flat pages" +msgstr "flat pages" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/eo/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/eo/LC_MESSAGES/django.mo new file mode 100644 index 0000000..16e74c3 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/eo/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/eo/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/eo/LC_MESSAGES/django.po new file mode 100644 index 0000000..7a66172 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/eo/LC_MESSAGES/django.po @@ -0,0 +1,93 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Batist D 🐍 , 2011-2012 +# Batist D 🐍 , 2014-2015,2017,2019 +# Matthieu Desplantes , 2021 +# Meiyer , 2022 +# Robin van der Vliet , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2022-04-24 19:03+0000\n" +"Last-Translator: Meiyer , 2022\n" +"Language-Team: Esperanto (http://www.transifex.com/django/django/language/" +"eo/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eo\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Altnivelaj elektoj" + +msgid "Flat Pages" +msgstr "Simplaj paĝoj" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Ekzemple: “/about/contact/”. Certigu, ke estas suprenstrekoj komence kaj " +"fine." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Ĉi tiu valoro devus enhavi sole literojn, ciferojn, punktojn, substrekojn, " +"haltostrekojn, oblikvajn strekojn, aŭ tildojn." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "Ekzemple: “/about/contact”. Certigu, ke estas suprenstreko komence." + +msgid "URL is missing a leading slash." +msgstr "La strek-signo ‘/’ ne ĉeestas en la komenco de URL." + +msgid "URL is missing a trailing slash." +msgstr "La strek-signo ‘/’ ne ĉeestas en la fino de URL." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Simpla paĝo kun URL %(url)s jam ekzistas por la retejo %(site)s" + +msgid "title" +msgstr "titolo" + +msgid "content" +msgstr "enhavo" + +msgid "enable comments" +msgstr "ebligi rimarkojn" + +msgid "template name" +msgstr "nomo de ŝablono" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Ekzemple: “flatpages/contact_page.html”. Se la ŝablono ne estas indikita, " +"estos uzata “flatpages/default.html”." + +msgid "registration required" +msgstr "registriĝo postulita" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Kiam la marko-butono estas elektita, nur ensalutintaj uzantoj povas rigardi " +"la paĝon." + +msgid "sites" +msgstr "retejoj" + +msgid "flat page" +msgstr "simpla paĝo" + +msgid "flat pages" +msgstr "simplaj paĝoj" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es/LC_MESSAGES/django.mo new file mode 100644 index 0000000..33d67b0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es/LC_MESSAGES/django.po new file mode 100644 index 0000000..060a385 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es/LC_MESSAGES/django.po @@ -0,0 +1,93 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Antoni Aloy , 2011-2012 +# Ernesto Avilés, 2015 +# Ernesto Avilés, 2014 +# Ignacio José Lizarán Rus , 2019 +# Jannis Leidel , 2011 +# Uriel Medina , 2020 +# Veronicabh , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-09-25 17:43+0000\n" +"Last-Translator: Uriel Medina \n" +"Language-Team: Spanish (http://www.transifex.com/django/django/language/" +"es/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Opciones avanzadas" + +msgid "Flat Pages" +msgstr "Páginas estáticas" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Ejemplo: “/about/contact/”. Asegúrese de tener barras al principio y al " +"final." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Este valor solo puede contener letras, números, puntos, guiones bajos o " +"medios, barras o tildes." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "Ejemplo: \"/about/contact”. Asegúrese de tener una barra al principio." + +msgid "URL is missing a leading slash." +msgstr "A la URL le falta la barra inicial." + +msgid "URL is missing a trailing slash." +msgstr "A la URL le falta la barra final." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr " En el sitio %(site)s ya hay una pagina estática con la url %(url)s" + +msgid "title" +msgstr "título" + +msgid "content" +msgstr "contenido" + +msgid "enable comments" +msgstr "habilitar comentarios" + +msgid "template name" +msgstr "nombre de plantilla" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Ejemplo: \"flatpages/contact_page.html\". Si no se proporciona, el sistema " +"utilizará \"flatpages/default.html\"." + +msgid "registration required" +msgstr "Se requiere registro" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "Si está marcado, sólo los usuarios registrados podrán ver la página." + +msgid "sites" +msgstr "sitios" + +msgid "flat page" +msgstr "página estática" + +msgid "flat pages" +msgstr "páginas estáticas" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es_AR/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es_AR/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d28b2e4 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es_AR/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es_AR/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es_AR/LC_MESSAGES/django.po new file mode 100644 index 0000000..0c0d4a9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es_AR/LC_MESSAGES/django.po @@ -0,0 +1,89 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Ramiro Morales, 2011-2012,2014-2015,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-10-01 10:25+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Spanish (Argentina) (http://www.transifex.com/django/django/" +"language/es_AR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_AR\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Opciones avanzadas" + +msgid "Flat Pages" +msgstr "Páginas Estáticas" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Ejemplo: “/about/contact/”. Asegúrese de usar barras '/' al principio y al " +"final." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Este valor debe contener solamente letras, números, puntos, guiones bajos, " +"guiones (-), barras (/) o tildes." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" +"Ejemplo: “/about/contact”. Asegúrese de usar una barra ('/') al principio." + +msgid "URL is missing a leading slash." +msgstr "A la URL le falta una / al principio." + +msgid "URL is missing a trailing slash." +msgstr "A la URL le falta una / al final." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Ya existe una flatpage con url %(url)s para el sitio %(site)s" + +msgid "title" +msgstr "título" + +msgid "content" +msgstr "contenido" + +msgid "enable comments" +msgstr "activar comentarios" + +msgid "template name" +msgstr "nombre de plantilla" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Ejemplo: “flatpages/contact_page.html”. Si no lo proporciona, el sistema " +"usará “flatpages/default.html”." + +msgid "registration required" +msgstr "debe estar registrado" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "Si está marcado, sólo los usuarios registrados podrán ver la página." + +msgid "sites" +msgstr "sitios" + +msgid "flat page" +msgstr "página estática" + +msgid "flat pages" +msgstr "páginas estáticas" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es_CO/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es_CO/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0564ec3 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es_CO/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es_CO/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es_CO/LC_MESSAGES/django.po new file mode 100644 index 0000000..c977035 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es_CO/LC_MESSAGES/django.po @@ -0,0 +1,86 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ernesto Avilés Vázquez , 2014-2015 +# Jannis Leidel , 2011 +# Veronicabh , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-20 03:01+0000\n" +"Last-Translator: Carlos Muñoz \n" +"Language-Team: Spanish (Colombia) (http://www.transifex.com/django/django/" +"language/es_CO/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_CO\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Opciones avanzadas" + +msgid "Flat Pages" +msgstr "Páginas estáticas" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"Ejemplo: '/about/contact/'. Asegúrese de que pone barras al principio y al " +"final." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Este valor solo puede contener letras, números, puntos, guiones bajos o " +"medios, barras o tildes." + +msgid "URL is missing a leading slash." +msgstr "A la URL le falta la barra inicial." + +msgid "URL is missing a trailing slash." +msgstr "A la URL le falta la barra final." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr " En el sitio %(site)s ya hay un Flatpage con la url %(url)s" + +msgid "title" +msgstr "título" + +msgid "content" +msgstr "contenido" + +msgid "enable comments" +msgstr "habilitar comentarios" + +msgid "template name" +msgstr "nombre de plantilla" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"Ejemplo: 'flatpages/contact_page.html'. Si no se proporciona uno, el sistema " +"usará 'flatpages/default.html'." + +msgid "registration required" +msgstr "debe estar registrado" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "Si está marcado, sólo los usuarios registrados podrán ver la página." + +msgid "sites" +msgstr "sitios" + +msgid "flat page" +msgstr "página estática" + +msgid "flat pages" +msgstr "páginas estáticas" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es_MX/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es_MX/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9b3ce53 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es_MX/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es_MX/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es_MX/LC_MESSAGES/django.po new file mode 100644 index 0000000..1fbad5f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es_MX/LC_MESSAGES/django.po @@ -0,0 +1,84 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Abraham Estrada, 2011-2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Spanish (Mexico) (http://www.transifex.com/django/django/" +"language/es_MX/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_MX\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Opciones avanzadas" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"Ejemplo: '/acerca/contacto/'. Asegúrese de usar barras '/' al principio y al " +"final." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Este valor debe contener solamente letras, números, puntos, guiones bajos, " +"guiones (-), barras (/) o tildes." + +msgid "URL is missing a leading slash." +msgstr "A la URL le falta una diagonal al inicio" + +msgid "URL is missing a trailing slash." +msgstr "A la URL le falta una diagonal al final" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "La página con la url %(url)s ya existe para el sitio %(site)s" + +msgid "title" +msgstr "título" + +msgid "content" +msgstr "contenido" + +msgid "enable comments" +msgstr "activar comentarios" + +msgid "template name" +msgstr "nombre de la plantilla" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"Ejemplo: 'flatpages/pagina_contacto.html'. Si no lo proporciona, el sistema " +"usará 'flatpages/default.html'." + +msgid "registration required" +msgstr "necesario registrarse" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "Si está marcado, sólo los usuarios registrados podrán ver la página." + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "página estática" + +msgid "flat pages" +msgstr "páginas estática" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es_VE/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es_VE/LC_MESSAGES/django.mo new file mode 100644 index 0000000..daa82b4 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es_VE/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es_VE/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es_VE/LC_MESSAGES/django.po new file mode 100644 index 0000000..dbaf54b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/es_VE/LC_MESSAGES/django.po @@ -0,0 +1,85 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Leonardo J. Caballero G. , 2016 +# Leonardo J. Caballero G. , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Leonardo J. Caballero G. \n" +"Language-Team: Spanish (Venezuela) (http://www.transifex.com/django/django/" +"language/es_VE/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_VE\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Opciones avanzadas" + +msgid "Flat Pages" +msgstr "Páginas estáticas" + +msgid "URL" +msgstr "Dirección URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"Ejemplo: '/about/contact/'. Asegúrese de que pone barras al principio y al " +"final." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Este valor solo puede contener letras, números, puntos, guiones bajos o " +"medios, barras o tildes." + +msgid "URL is missing a leading slash." +msgstr "A la URL le falta la barra inicial." + +msgid "URL is missing a trailing slash." +msgstr "A la URL le falta la barra final." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "La página estática con la url %(url)s ya existe para el sitio %(site)s" + +msgid "title" +msgstr "título" + +msgid "content" +msgstr "contenido" + +msgid "enable comments" +msgstr "permitir comentarios" + +msgid "template name" +msgstr "nombre de la plantilla" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"Ejemplo: 'flatpages/contact_page.html'. Si no se proporciona uno, el sistema " +"usará 'flatpages/default.html'." + +msgid "registration required" +msgstr "es necesario registrarse" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "Si está marcado, sólo los usuarios registrados podrán ver la página." + +msgid "sites" +msgstr "sitios" + +msgid "flat page" +msgstr "página estática" + +msgid "flat pages" +msgstr "páginas estáticas" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/et/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/et/LC_MESSAGES/django.mo new file mode 100644 index 0000000..82b3c23 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/et/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/et/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/et/LC_MESSAGES/django.po new file mode 100644 index 0000000..da51a04 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/et/LC_MESSAGES/django.po @@ -0,0 +1,89 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Janno Liivak , 2013-2015 +# madisvain , 2011 +# Ragnar Rebase , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-12-28 02:36+0000\n" +"Last-Translator: Ragnar Rebase \n" +"Language-Team: Estonian (http://www.transifex.com/django/django/language/" +"et/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: et\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Lisavalikud" + +msgid "Flat Pages" +msgstr "Sisulehed" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Näide: “/about/contact/”. Veenduge, et URL algaks ja lõppeks kaldkriipsuga." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"See väärtus peab sisaldama ainult tähti, numbreid, punkte, alakriipse, " +"kriipse, kaldkriipse või tildeseid." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "Näide: “/about/contact”. Veenduge, et URL algaks kaldkriipsuga." + +msgid "URL is missing a leading slash." +msgstr "Internetiaadressil puudub alustav kaldkriips" + +msgid "URL is missing a trailing slash." +msgstr "Internetiaadressil puudub lõpetav kaldkriips" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Saidil %(site)s on sisuleht aadressiga %(url)s juba olemas" + +msgid "title" +msgstr "pealkiri" + +msgid "content" +msgstr "sisu" + +msgid "enable comments" +msgstr "võimalda kommentaarid" + +msgid "template name" +msgstr "mall" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Näide: “flatpages/contact_page.html”.  Kui mall on määramata, kasutatakse " +"vaikimisi malli “flatpages/default.html”." + +msgid "registration required" +msgstr "registreerumine nõutav" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "Kui see on valitud, näevad lehte ainult sisselogitud kasutajad" + +msgid "sites" +msgstr "saidid" + +msgid "flat page" +msgstr "sisuleht" + +msgid "flat pages" +msgstr "sisulehed" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/eu/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/eu/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b49fd45 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/eu/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/eu/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/eu/LC_MESSAGES/django.po new file mode 100644 index 0000000..66f3d48 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/eu/LC_MESSAGES/django.po @@ -0,0 +1,90 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Aitzol Naberan , 2011-2012 +# Eneko Illarramendi , 2017,2019 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2019-01-22 10:01+0000\n" +"Last-Translator: Eneko Illarramendi \n" +"Language-Team: Basque (http://www.transifex.com/django/django/language/eu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Aukera aurreratuak" + +msgid "Flat Pages" +msgstr "Flatpage-ak" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"Adibidez: '/about/contact/'. Ziurta zaitez '/' karaktera hasieran eta " +"bukaeran dagoela." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Eremu honetan soilik hizki, zenbaki, puntu, azpimarra, marra, / edo ~ egon " +"daitezke." + +msgid "Example: '/about/contact'. Make sure to have a leading slash." +msgstr "Adibidez: '/about/contact'. Ez ahaztu hasieran barra bat gehitzea." + +msgid "URL is missing a leading slash." +msgstr "URLak hasierako / falta du." + +msgid "URL is missing a trailing slash." +msgstr "URLk bukaerako / falta du." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "%(site)s webgunean dagoeneko existitzende %(url)s urldun Flatpage bat" + +msgid "title" +msgstr "izenburua" + +msgid "content" +msgstr "edukia" + +msgid "enable comments" +msgstr "komentarioak onartu" + +msgid "template name" +msgstr "plantila izena" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"Adibidez: 'flatpages/contact_page.html'. Hau zehazten ez bada, sistemak " +"'flatpages/default.html' erabiliko du." + +msgid "registration required" +msgstr "erregistratzea beharrezkoa da" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Hau markatuta badago, erregistratutako erabiltzaileek bakarrik ikusiko dute " +"orria." + +msgid "sites" +msgstr "webguneak" + +msgid "flat page" +msgstr "flat page" + +msgid "flat pages" +msgstr "flat pages" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/fa/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/fa/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d884e7e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/fa/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/fa/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/fa/LC_MESSAGES/django.po new file mode 100644 index 0000000..cf0477c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/fa/LC_MESSAGES/django.po @@ -0,0 +1,92 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ali Nikneshan , 2011-2012 +# Ali Vakilzade , 2015 +# Fariman Ghaedi , 2019 +# Jannis Leidel , 2011 +# rahim agh , 2021 +# Reza Mohammadi , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2021-04-19 03:16+0000\n" +"Last-Translator: rahim agh \n" +"Language-Team: Persian (http://www.transifex.com/django/django/language/" +"fa/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fa\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Advanced options" +msgstr "گزینه‌های پیشرفته" + +msgid "Flat Pages" +msgstr "صفحات تخت" + +msgid "URL" +msgstr "نشانی اینترنتی" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"مثال: '/about/contact/'. مطمئن شوید که اسلش را هم در ابتدا و هم در انتها " +"گذاشته‌اید." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "این مقدار فقط باید حاوی حروف، اعداد، خط زیر، خط تیره و یا اسلش باشد." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "مثال: 'about/contact/'. مطمئن شوید که یک اسلش در ابتدا وجود دارد. " + +msgid "URL is missing a leading slash." +msgstr "در آدرس اسلش آغازین فراموش شده است." + +msgid "URL is missing a trailing slash." +msgstr "در آدرس اسلش پایانی فراموش شده است." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "صفحه تخت با آدرس %(url)s برای سایت %(site)s وجود دارد " + +msgid "title" +msgstr "عنوان" + +msgid "content" +msgstr "محتوا" + +msgid "enable comments" +msgstr "فعال کردن نظرات" + +msgid "template name" +msgstr "نام قالب" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"مثال: 'flatpages/contact_page.html'. اگر این مشخص نشود، سیستم از 'flatpages/" +"default.html' استفاده خواهد کرد." + +msgid "registration required" +msgstr "عضویت لازم است" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"اگر این انتخاب شود، فقط کاربران وارد شده خواهند توانست این صفحه را مشاهده " +"نمایند." + +msgid "sites" +msgstr "وب‌گاه‌ها" + +msgid "flat page" +msgstr "صفحه تخت" + +msgid "flat pages" +msgstr "صفحات تخت" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/fi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/fi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c71b4ec Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/fi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/fi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/fi/LC_MESSAGES/django.po new file mode 100644 index 0000000..789cd92 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/fi/LC_MESSAGES/django.po @@ -0,0 +1,92 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Aarni Koskela, 2015,2020 +# Jannis Leidel , 2011 +# Klaus Dahlén , 2012 +# Ville Säävuori , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-12-09 06:32+0000\n" +"Last-Translator: Aarni Koskela\n" +"Language-Team: Finnish (http://www.transifex.com/django/django/language/" +"fi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Lisäasetukset" + +msgid "Flat Pages" +msgstr "Tekstisivut" + +msgid "URL" +msgstr "URL-osoite" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Esimerkki: '/tietoja/yhteystiedot/'. Varmista että sekä alussa että lopussa " +"on kauttaviiva." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Tämä arvo saa sisältää vain kirjaimia, numeroita, pisteitä sekä ala-, tavu-, " +"kautta- ja aaltoviivoja." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" +"Esimerkki: \"/tietoja/yhteystiedot/\". Varmista että alussa on kauttaviiva." + +msgid "URL is missing a leading slash." +msgstr "URL:n alusta puuttuu kauttaviiva." + +msgid "URL is missing a trailing slash." +msgstr "URL:n lopusta puuttuu kauttaviiva." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Sivustolla %(site)s on jo sivu, jonka URL on %(url)s" + +msgid "title" +msgstr "otsikko" + +msgid "content" +msgstr "sisältö" + +msgid "enable comments" +msgstr "salli kommentit" + +msgid "template name" +msgstr "mallipohjan nimi" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Esimerkiksi: \"flatpages/yhteydenotto.html'\" Jos tämä jätetään tyhjäksi, " +"käytetään oletuspohjaa \"flatpages/default.html\"." + +msgid "registration required" +msgstr "vaaditaan rekisteröityminen" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Jos tämä kohta on valittu, vain sisäänkirjautuneet käyttäjät näkevät sivun." + +msgid "sites" +msgstr "sivustot" + +msgid "flat page" +msgstr "tekstisivu" + +msgid "flat pages" +msgstr "tekstisivut" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/fr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/fr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..41ed7dc Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/fr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/fr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 0000000..fb72ed9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,93 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Simon Charette , 2012 +# Claude Paroz , 2014-2015,2019 +# Claude Paroz , 2011 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-09-18 16:02+0000\n" +"Last-Translator: Claude Paroz \n" +"Language-Team: French (http://www.transifex.com/django/django/language/fr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Advanced options" +msgstr "Options avancées" + +msgid "Flat Pages" +msgstr "Pages statiques" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Par exemple, « /a_propos/contact/ ». Vérifiez la présence du caractère « / » " +"en début et en fin de chaîne." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Cette valeur ne peut contenir que des lettres, des chiffres, des points, des " +"soulignés, des tirets, des barres obliques ou des tildes." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" +"Par exemple, « /a_propos/contact ». Vérifiez la présence du caractère « / » " +"en début de chaîne." + +msgid "URL is missing a leading slash." +msgstr "Le caractère « / » n'est pas présent en début de chaîne." + +msgid "URL is missing a trailing slash." +msgstr "Le caractère « / » n'est pas présent en fin de chaîne." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "La page statique à l’URL %(url)s existe déjà pour le site %(site)s" + +msgid "title" +msgstr "titre" + +msgid "content" +msgstr "contenu" + +msgid "enable comments" +msgstr "autoriser les commentaires" + +msgid "template name" +msgstr "nom du gabarit" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Par exemple, « flatpages/contact_page.html ». Sans définition, le système " +"utilisera « flatpages/default.html »." + +msgid "registration required" +msgstr "enregistrement requis" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Si coché, seuls les utilisateurs connectés auront la possibilité de voir " +"cette page." + +msgid "sites" +msgstr "sites" + +msgid "flat page" +msgstr "page statique" + +msgid "flat pages" +msgstr "pages statiques" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/fy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/fy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d130f4e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/fy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/fy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/fy/LC_MESSAGES/django.po new file mode 100644 index 0000000..29912b3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/fy/LC_MESSAGES/django.po @@ -0,0 +1,74 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-03-18 09:16+0100\n" +"PO-Revision-Date: 2015-03-18 08:34+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Western Frisian (http://www.transifex.com/projects/p/django/" +"language/fy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fy\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" + +msgid "URL is missing a leading slash." +msgstr "" + +msgid "URL is missing a trailing slash." +msgstr "" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" + +msgid "title" +msgstr "" + +msgid "content" +msgstr "" + +msgid "enable comments" +msgstr "" + +msgid "template name" +msgstr "" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" + +msgid "registration required" +msgstr "" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" + +msgid "flat page" +msgstr "" + +msgid "flat pages" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ga/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ga/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8e80c10 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ga/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ga/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ga/LC_MESSAGES/django.po new file mode 100644 index 0000000..3f0b097 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ga/LC_MESSAGES/django.po @@ -0,0 +1,87 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Michael Thornhill , 2011-2012,2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Irish (http://www.transifex.com/django/django/language/ga/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ga\n" +"Plural-Forms: nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : " +"4);\n" + +msgid "Advanced options" +msgstr "Ard-rogha" + +msgid "Flat Pages" +msgstr "Leathanaigh Maol" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"Sampla '/about/contact/' Déan cinnte go bhfuil príomhslaid agus cúlslais " +"agat." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Ní mór an luach a bhfuil ach litreacha, uimhreacha, poncanna, béim, dashes, " +"slaiseanna nó thilde." + +msgid "URL is missing a leading slash." +msgstr "Tá slais tosaigh in easnamh ag an URL." + +msgid "URL is missing a trailing slash." +msgstr "Tá slais deireanach in easnamh ag an URL." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Tá flatpage le url %(url)s ann cheana le suíomh %(site)s." + +msgid "title" +msgstr "teideal" + +msgid "content" +msgstr "inneachar" + +msgid "enable comments" +msgstr "Cuir nótaí tráchta ar chumas" + +msgid "template name" +msgstr "ainm an teimpléid" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"Sampla: 'flatpages/contact_page.html'. Muna bhfuil sé ar soláthair, bainfidh " +"an córás úsáid as 'flatpages/default.html'." + +msgid "registration required" +msgstr "clárúchán riachtanach" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Dá mbéadh é seo seicailte, ní beidh ach úsáideora logáilte isteach in ann an " +"leathanach seo a fheiceail" + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "leacleathanach" + +msgid "flat pages" +msgstr "leacleathanaigh" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/gd/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/gd/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c430c58 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/gd/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/gd/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/gd/LC_MESSAGES/django.po new file mode 100644 index 0000000..1e99447 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/gd/LC_MESSAGES/django.po @@ -0,0 +1,95 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# GunChleoc, 2015 +# GunChleoc, 2015 +# GunChleoc, 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-12-13 12:47+0000\n" +"Last-Translator: GunChleoc\n" +"Language-Team: Gaelic, Scottish (http://www.transifex.com/django/django/" +"language/gd/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: gd\n" +"Plural-Forms: nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : " +"(n > 2 && n < 20) ? 2 : 3;\n" + +msgid "Advanced options" +msgstr "Roghainnean adhartach" + +msgid "Flat Pages" +msgstr "Duilleagan rèidhe" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Mar eisimpleir: “/mu-dheidhinn/fios-thugainn/”. Dèan cinnteach gum bi slais " +"air an toiseach ’s air an deireadh." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Chan fhaod ach litrichean, àireamhan, puingean, fo-loidhnichean, tàthanan, " +"slaisichean is tuinn a bhith san luach." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" +"Mar eisimpleir: “/mu-dheidhinn/fios-thugainn/”. Dèan cinnteach gum bi slais " +"air an toiseach ’s air an deireadh." + +msgid "URL is missing a leading slash." +msgstr "Tha slais a dhìth air thoiseach an URL." + +msgid "URL is missing a trailing slash." +msgstr "Tha slais a dhìth air deireadh an URL." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" +"Tha duilleag rèidh le url %(url)s ann mar-tà airson na làraich %(site)s" + +msgid "title" +msgstr "tiotal" + +msgid "content" +msgstr "susbaint" + +msgid "enable comments" +msgstr "cuir beachdan an comas" + +msgid "template name" +msgstr "ainm na teamplaid" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Ball-eisimpleir: “flatpages/duilleag_fios_thugainn.html”. Mura dèid seo a " +"sholar-cleachdaidh an siostam “flatpages/default.html”." + +msgid "registration required" +msgstr "tha clàradh riatanach" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Ma tha cromag ris, chan faic ach na chleachdaichean a chlàraich a-steach an " +"duilleag seo." + +msgid "sites" +msgstr "làraichean" + +msgid "flat page" +msgstr "duilleag rèidh" + +msgid "flat pages" +msgstr "duilleagan rèidhe" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/gl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/gl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4b784c2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/gl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/gl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/gl/LC_MESSAGES/django.po new file mode 100644 index 0000000..22b733a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/gl/LC_MESSAGES/django.po @@ -0,0 +1,89 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# fasouto , 2011 +# fonso , 2011,2013 +# Jannis Leidel , 2011 +# Leandro Regueiro , 2013 +# X Bello , 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2023-04-24 19:03+0000\n" +"Last-Translator: X Bello , 2023\n" +"Language-Team: Galician (http://www.transifex.com/django/django/language/" +"gl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: gl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Opcións avanzadas" + +msgid "Flat Pages" +msgstr "Páxinas simples" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "Exemplo: “/about/contact”. Lembre incluír as barras inicial e final." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Este valor soamente pode conter letras, números, puntos, guións baixos, " +"guións, barras inclinadas e tiles do eñe (~)." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "Exemplo: “/about/contact”. Lembre incluír a barra inicial." + +msgid "URL is missing a leading slash." +msgstr "Falta unha barra inclinada no principio da URL." + +msgid "URL is missing a trailing slash." +msgstr "Falta unha barra inclinada no final da URL." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Xa existe unha páxina simple con url %(url)s no sitio %(site)s" + +msgid "title" +msgstr "título" + +msgid "content" +msgstr "contido" + +msgid "enable comments" +msgstr "activar comentarios" + +msgid "template name" +msgstr "nome da plantilla" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Exemplo: “flatpages/contact_page.html”. Se non se especifica, o sistema " +"usará “flatpages/default.html”." + +msgid "registration required" +msgstr "require rexistro" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "Se se marca, só poderán ver a páxina os usuarios identificados." + +msgid "sites" +msgstr "sitios" + +msgid "flat page" +msgstr "páxina simple" + +msgid "flat pages" +msgstr "páxinas simples" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/he/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/he/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4d5347e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/he/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/he/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/he/LC_MESSAGES/django.po new file mode 100644 index 0000000..e703c63 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/he/LC_MESSAGES/django.po @@ -0,0 +1,87 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# 534b44a19bf18d20b71ecc4eb77c572f_db336e9 , 2011 +# Jannis Leidel , 2011 +# Meir Kriheli , 2012,2014-2015,2019-2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-08-02 13:26+0000\n" +"Last-Translator: Meir Kriheli \n" +"Language-Team: Hebrew (http://www.transifex.com/django/django/language/he/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: he\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % " +"1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;\n" + +msgid "Advanced options" +msgstr "אפשרויות מתקדמות" + +msgid "Flat Pages" +msgstr "דפים פשוטים" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "דוגמה: “/about/contact/”. יש לוודא שמכיל קווים נטויים בהתחלה ובסוף." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"הערך הזאת חייב להכיל רק אותיות, מספרים, נקודות, מקפים, קווים תחתונים, חתכים " +"או סימני טילדה בלבד." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "דוגמה: “‎/about/contact”. יש לוודא שמכיל קו נטוי בהתחלה." + +msgid "URL is missing a leading slash." +msgstr "חסר קו נטוי בתחילת URL." + +msgid "URL is missing a trailing slash." +msgstr "חסר קו נטוי בסוף URL." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "קיים כבר דף פשוט עם url %(url)s עבור אתר %(site)s" + +msgid "title" +msgstr "כותרת" + +msgid "content" +msgstr "תוכן" + +msgid "enable comments" +msgstr "אפשר תגובות" + +msgid "template name" +msgstr "שם תבנית" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"דוגמה: “flatpages/contact_page.html”. אם לא צוין, המערכת תשתמש ב־“flatpages/" +"default.html”." + +msgid "registration required" +msgstr "הרשמה נדרשת" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "אם מסומן, רק משתמשים מחוברים יוכלו לצפות בדף." + +msgid "sites" +msgstr "אתרים" + +msgid "flat page" +msgstr "דף פשוט" + +msgid "flat pages" +msgstr "דפים פשוטים" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ca42d15 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hi/LC_MESSAGES/django.po new file mode 100644 index 0000000..1851834 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hi/LC_MESSAGES/django.po @@ -0,0 +1,81 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Chandan kumar , 2012 +# Jannis Leidel , 2011 +# Sandeep Satavlekar , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Hindi (http://www.transifex.com/django/django/language/hi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "उन्नत विकल्प" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "अग्रणी है और अनुगामी स्लैश का होना सुनिश्चित करें. उदाहरण: '/about/contact/'" + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "इस मूल्य में सिर्फ वर्णाक्षर, अंक, बिंदु, रेखांकन, डैश, स्लैश और टिल्ड्स ही होने चाहिए" + +msgid "URL is missing a leading slash." +msgstr "यूआरएल से प्रमुख स्लैश गायब है." + +msgid "URL is missing a trailing slash." +msgstr "यूआरएल से अनुगामी स्लैश गायब है." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "%(site)s साइट के लिए %(url)s यूआरएल के साथ चपटापृष्ट मौजूद है." + +msgid "title" +msgstr "शीर्षक" + +msgid "content" +msgstr "विषय सूची" + +msgid "enable comments" +msgstr "टिप्पणियां सक्षम करें" + +msgid "template name" +msgstr "सांचे का नाम" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"उदाहरण: 'flatpages/contact_page.html'. यदि यह जिक्र नहीं किया तो यह प्रणाली " +"'flatpages/default.html' का प्रयोग करेगी. ." + +msgid "registration required" +msgstr "पंजीकरण आवश्यक" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "अगर इस जाँच की है, केवल लॉग इन करने वालों के लिए पृष्ठ देखने में सक्षम हो जाएगा." + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "चपटा पृष्ट" + +msgid "flat pages" +msgstr "चपटे पृष्ट" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d310400 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hr/LC_MESSAGES/django.po new file mode 100644 index 0000000..7e7c163 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hr/LC_MESSAGES/django.po @@ -0,0 +1,88 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# aljosa , 2011-2012 +# Jannis Leidel , 2011 +# Mislav Cimperšak , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Mislav Cimperšak \n" +"Language-Team: Croatian (http://www.transifex.com/django/django/language/" +"hr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hr\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +msgid "Advanced options" +msgstr "Napredne opcije" + +msgid "Flat Pages" +msgstr "Statične stranice" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"Primjer: '/about/contact/'. Provjerite ako imate prvi i preostale slash-eve " +"(/)." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Ova vrijednost može sadržavati samo slova, brojeve, točke, podvlake, crtice, " +"kose crte ili tilde." + +msgid "URL is missing a leading slash." +msgstr "URL-u nedostaje početni /." + +msgid "URL is missing a trailing slash." +msgstr "URL-u nedostaje / na kraju." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Stranica sa URL-om %(url)s već postoji za web %(site)s" + +msgid "title" +msgstr "naslov" + +msgid "content" +msgstr "sadržaj" + +msgid "enable comments" +msgstr "uključi komentare" + +msgid "template name" +msgstr "ime template-a" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"Primjer: 'flatpages/contact_page.html'. Ako navedeno nije definirano sistem " +"će koristiti 'flatpages/default.html'." + +msgid "registration required" +msgstr "registracija obavezna" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Ako je ovo selektirano samo logirani korisnici moći će vidjeti ovu stranicu." + +msgid "sites" +msgstr "stranice" + +msgid "flat page" +msgstr "statična stranica" + +msgid "flat pages" +msgstr "statične stranice" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hsb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hsb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b8111a2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hsb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hsb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hsb/LC_MESSAGES/django.po new file mode 100644 index 0000000..3df5cab --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hsb/LC_MESSAGES/django.po @@ -0,0 +1,89 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Michael Wolf , 2016,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-09-21 19:28+0000\n" +"Last-Translator: Michael Wolf \n" +"Language-Team: Upper Sorbian (http://www.transifex.com/django/django/" +"language/hsb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hsb\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" + +msgid "Advanced options" +msgstr "Rozšěrjene nastajenja" + +msgid "Flat Pages" +msgstr "Statiske strony" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Přikład: '/about/contact/'. Přeswědčće so, zo sće wočinjace a začinjace " +"nakósne smužki podał." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Tuta hódnota smě jenož pismiki, ličby, dypki, podsmužki, wjazawki, nakósne " +"smužki abo tildy wobsahować." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "Přikład: 'about/contact'. Zawěsćće, zo maće nawodnu nakósnu smužku." + +msgid "URL is missing a leading slash." +msgstr "URL wočinjacu nakósnu smužku nima." + +msgid "URL is missing a trailing slash." +msgstr "URL začinjacu nakósnu smužku nima." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Statiska strona z url %(url)s hižo za sydło %(site)s eksistuje" + +msgid "title" +msgstr "titul" + +msgid "content" +msgstr "wobsah" + +msgid "enable comments" +msgstr "komentary zmóžnić" + +msgid "template name" +msgstr "mjeno předłohi" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Přikład: 'flatpages/contact_page.html'. Jeli to njeje podate, budźe system " +"'flatpages/default.html' wužiwać." + +msgid "registration required" +msgstr "registrowanje trěbne" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Jeli to je zmóžnjene, móža sej jenož přizjewjeni wužiwarjo stronu wobhladać." + +msgid "sites" +msgstr "sydła" + +msgid "flat page" +msgstr "statiska strona" + +msgid "flat pages" +msgstr "statiske strony" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hu/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hu/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ccf6f73 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hu/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hu/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hu/LC_MESSAGES/django.po new file mode 100644 index 0000000..ebc44ba --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hu/LC_MESSAGES/django.po @@ -0,0 +1,94 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# András Veres-Szentkirályi, 2016,2019 +# Istvan Farkas , 2019 +# Jannis Leidel , 2011 +# Szilveszter Farkas , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-11-18 10:16+0000\n" +"Last-Translator: Istvan Farkas \n" +"Language-Team: Hungarian (http://www.transifex.com/django/django/language/" +"hu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "További beállítások" + +msgid "Flat Pages" +msgstr "Egyszerű oldalak" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Példa: \"/rolunk/kapcsolat/\" Bizonyosodjon meg róla, hogy a kezdő és záró " +"\"/\" karakterek a helyükön vannak." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Ez az érték csak betűt, számot, pontot, aláhúzást, kötőjelet, perjelet, vagy " +"hullámot tartalmazhat." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" +"Példa: \"/rolunk/kapcsolat\". Bizonyosodjon meg róla, hogy \"/\" karakterrel " +"kezdődik." + +msgid "URL is missing a leading slash." +msgstr "AZ URL-ből hiányzik a kezdő perjel." + +msgid "URL is missing a trailing slash." +msgstr "AZ URL-ből hiányzik a záró perjel." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "%(site)s honlapon már létezik egyszerű oldal ezzel az URL-lel: %(url)s" + +msgid "title" +msgstr "cím" + +msgid "content" +msgstr "tartalom" + +msgid "enable comments" +msgstr "megjegyzések engedélyezése" + +msgid "template name" +msgstr "sablon neve" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Példa: \"flatpages/contact_page.html\". Ha ez nincs megadva, a rendszer a " +"\"flatpages/default.html\" értéket fogja használni." + +msgid "registration required" +msgstr "regisztráció szükséges" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Ha ez be van jelölve, csak bejelentkezett felhasználó tudja az oldalt " +"megnézni." + +msgid "sites" +msgstr "honlapok" + +msgid "flat page" +msgstr "egyszerű oldal" + +msgid "flat pages" +msgstr "egyszerű oldalak" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..447dc4e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hy/LC_MESSAGES/django.po new file mode 100644 index 0000000..7e9ee66 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/hy/LC_MESSAGES/django.po @@ -0,0 +1,84 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2018-11-01 20:34+0000\n" +"Last-Translator: Ruben Harutyunov \n" +"Language-Team: Armenian (http://www.transifex.com/django/django/language/" +"hy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hy\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Ընդլայնված կարգավորումներ" + +msgid "Flat Pages" +msgstr "Պարզ էջեր" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"Օրինակ․ '/about/contact/'։ Համոզվեք, որ մուտքագրել եք սկզբի և վերջի թեք " +"գծերը։" + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Այս արժեքը պետք է պարունակի միայն տառեր, թվեր, կետեր, ընդգծումներ, գծեր, թեք " +"գծեր կամ ալիքանշաններ։" + +msgid "URL is missing a leading slash." +msgstr "URL֊ը չունի սկզբի թեք գիծ։" + +msgid "URL is missing a trailing slash." +msgstr "URL֊ը չունի վերջի թեք գիծ։" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "%(url)s url֊ով էջ արդեն գոյություն ունի %(site)s կայքի համար" + +msgid "title" +msgstr "վերնագիր" + +msgid "content" +msgstr "պարունակություն" + +msgid "enable comments" +msgstr "միացնել մեկնաբանությունները" + +msgid "template name" +msgstr "template֊ի անունը" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"Օրինակ․ 'flatpages/contact_page.html'։ Եթե տրամադրված չէ, համակարգը " +"կօգտագործի 'flatpages/default.html' ֆայլը։" + +msgid "registration required" +msgstr "պահանջվում է գրանցվել" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Եթե սա նշված է, միայն մուտք գործած օգտագործողները կկարողանան դիտել էջը։" + +msgid "sites" +msgstr "կայքեր" + +msgid "flat page" +msgstr "պարզ էջ" + +msgid "flat pages" +msgstr "պարզ էջեր" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ia/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ia/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8b37130 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ia/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ia/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ia/LC_MESSAGES/django.po new file mode 100644 index 0000000..3df229d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ia/LC_MESSAGES/django.po @@ -0,0 +1,77 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Interlingua (http://www.transifex.com/django/django/language/" +"ia/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ia\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" + +msgid "URL is missing a leading slash." +msgstr "" + +msgid "URL is missing a trailing slash." +msgstr "" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" + +msgid "title" +msgstr "" + +msgid "content" +msgstr "" + +msgid "enable comments" +msgstr "" + +msgid "template name" +msgstr "" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" + +msgid "registration required" +msgstr "" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "" + +msgid "flat pages" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/id/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/id/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4426268 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/id/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/id/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/id/LC_MESSAGES/django.po new file mode 100644 index 0000000..9057580 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/id/LC_MESSAGES/django.po @@ -0,0 +1,90 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Fery Setiawan , 2015-2016,2019-2020 +# Jannis Leidel , 2011 +# rodin , 2011-2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-02-06 02:33+0000\n" +"Last-Translator: Fery Setiawan \n" +"Language-Team: Indonesian (http://www.transifex.com/django/django/language/" +"id/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: id\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Advanced options" +msgstr "Opsi lanjutan" + +msgid "Flat Pages" +msgstr "Halaman Tetap" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Contoh: “/about/contact/”. Pastikan memiliki awalan dan akhiran garis miring." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Nilai hanya hanya dapat berisi huruf, angka, titik, garis bawah, tanda " +"minus, garis miring, atau tanda tilde." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "Contoh: “/about/contact”. Pastikan memiliki awalan garis miring." + +msgid "URL is missing a leading slash." +msgstr "Tidak ada garis miring awal pada URL." + +msgid "URL is missing a trailing slash." +msgstr "Tidak ada garis miring akhir pada URL." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Laman tetap %(url)s sudah ada untuk situs %(site)s" + +msgid "title" +msgstr "judul" + +msgid "content" +msgstr "isi" + +msgid "enable comments" +msgstr "aktifkan komentar" + +msgid "template name" +msgstr "nama templat" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Contoh: “flatpages/contact_page.html”. Jika tidak disediakan, sistem akan " +"menggunakan “flatpages/default.html”." + +msgid "registration required" +msgstr "pendaftaran diwajibkan" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Jika dipilih, hanya pengguna ter-otentikasi yang bisa mengunjungi halaman " +"ini." + +msgid "sites" +msgstr "situs" + +msgid "flat page" +msgstr "laman tetap" + +msgid "flat pages" +msgstr "laman tetap" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/io/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/io/LC_MESSAGES/django.mo new file mode 100644 index 0000000..37ef71d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/io/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/io/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/io/LC_MESSAGES/django.po new file mode 100644 index 0000000..78e3fd0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/io/LC_MESSAGES/django.po @@ -0,0 +1,74 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-03-18 09:16+0100\n" +"PO-Revision-Date: 2015-03-18 08:34+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Ido (http://www.transifex.com/projects/p/django/language/" +"io/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: io\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" + +msgid "URL is missing a leading slash." +msgstr "" + +msgid "URL is missing a trailing slash." +msgstr "" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" + +msgid "title" +msgstr "" + +msgid "content" +msgstr "" + +msgid "enable comments" +msgstr "" + +msgid "template name" +msgstr "" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" + +msgid "registration required" +msgstr "" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" + +msgid "flat page" +msgstr "" + +msgid "flat pages" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/is/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/is/LC_MESSAGES/django.mo new file mode 100644 index 0000000..32956d2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/is/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/is/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/is/LC_MESSAGES/django.po new file mode 100644 index 0000000..fbc5a03 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/is/LC_MESSAGES/django.po @@ -0,0 +1,87 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Hafsteinn Einarsson , 2011-2012 +# Jannis Leidel , 2011 +# Thordur Sigurdsson , 2016,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-11-20 05:07+0000\n" +"Last-Translator: Thordur Sigurdsson \n" +"Language-Team: Icelandic (http://www.transifex.com/django/django/language/" +"is/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: is\n" +"Plural-Forms: nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);\n" + +msgid "Advanced options" +msgstr "Ítarlegar stillingar" + +msgid "Flat Pages" +msgstr "Flatskrár" + +msgid "URL" +msgstr "Veffang" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "Dæmi: '/about/contact/'. Passaðu að hafa skástrik fremst og aftast." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Þessi reitur má aðeins innihalda bókstafi (ekki broddstafi), tölustafi og " +"táknin . / - _ og ~." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "Dæmi: '/about/contact'. Passaðu að hafa skástrik fremst." + +msgid "URL is missing a leading slash." +msgstr "Skástrik vantar fremst í slóð" + +msgid "URL is missing a trailing slash." +msgstr "Skástrik vantar aftast í slóð" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "'Flatpage' með slóðina %(url)s er þegar til fyrir síðuna %(site)s" + +msgid "title" +msgstr "titill" + +msgid "content" +msgstr "innihald" + +msgid "enable comments" +msgstr "virkja athugasemdir" + +msgid "template name" +msgstr "nafn sniðmáts" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Dæmi: 'flatpages/contact_page.html'. Ef ekkert er gefið upp mun kerfið nota " +"'flatpages/default.html'." + +msgid "registration required" +msgstr "skráning nauðsynleg" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "Ef þetta er valið geta eingöngu innskráðir notendur séð síðuna." + +msgid "sites" +msgstr "vefir" + +msgid "flat page" +msgstr "flatskrá" + +msgid "flat pages" +msgstr "flatskrár" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/it/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/it/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7bc06b2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/it/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/it/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/it/LC_MESSAGES/django.po new file mode 100644 index 0000000..606a8d2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/it/LC_MESSAGES/django.po @@ -0,0 +1,92 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Carlo Miron , 2019 +# Jannis Leidel , 2011 +# Marco Bonetti, 2014 +# Mirco Grillo , 2020 +# palmux , 2015,2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2021-01-15 16:01+0000\n" +"Last-Translator: palmux \n" +"Language-Team: Italian (http://www.transifex.com/django/django/language/" +"it/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: it\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Opzioni avanzate" + +msgid "Flat Pages" +msgstr "Flat Pages" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Per esempio: '/about/contact'. Assicurati che inizi e finisca con uno slash." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Questo valore deve contenere solo lettere, numeri, punti, underscore, " +"trattini, barre diagonali o tilde." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "Per esempio: '/about/contact'. Assicurati che inizi con uno slash." + +msgid "URL is missing a leading slash." +msgstr "Manca una barra iniziale nella URL." + +msgid "URL is missing a trailing slash." +msgstr "Manca una barra finale nella URL." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "La flatpage con url %(url)s esiste già per il sito %(site)s" + +msgid "title" +msgstr "titolo" + +msgid "content" +msgstr "contenuto" + +msgid "enable comments" +msgstr "abilita commenti" + +msgid "template name" +msgstr "nome template" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Esempio: \"flatpages/contact_page.html\". Se non specificato, il sistema " +"userà \"flatpages/default.html\"." + +msgid "registration required" +msgstr "registrazione obbligatoria" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Se selezionato, solo gli utenti che hanno effettuato l'accesso potranno " +"vedere la pagina." + +msgid "sites" +msgstr "siti" + +msgid "flat page" +msgstr "flat page" + +msgid "flat pages" +msgstr "flat pages" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ja/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ja/LC_MESSAGES/django.mo new file mode 100644 index 0000000..6369ad4 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ja/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ja/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ja/LC_MESSAGES/django.po new file mode 100644 index 0000000..67b7abd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ja/LC_MESSAGES/django.po @@ -0,0 +1,90 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Shinichi Katsumata , 2019 +# Shinya Okano , 2012,2014-2015 +# Takuya N , 2020 +# Tetsuya Morimoto , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-02-07 16:07+0000\n" +"Last-Translator: Takuya N \n" +"Language-Team: Japanese (http://www.transifex.com/django/django/language/" +"ja/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ja\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Advanced options" +msgstr "詳細設定" + +msgid "Flat Pages" +msgstr "フラットページ" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"例: “/about/contact/”. 先頭と最後にスラッシュがあるか確認してください。" + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"この値は文字、数字、ドット、アンダースコア、ダッシュ、スラッシュかチルダのみ" +"でなければいけません。" + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "例: “/about/contact”. 先頭にスラッシュがあるか確認してください。" + +msgid "URL is missing a leading slash." +msgstr "URLの先頭はスラッシュが必要です。" + +msgid "URL is missing a trailing slash." +msgstr "URLの末尾はスラッシュが必要です。" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "URL %(url)s のフラットページは %(site)s のサイトに既に存在しています。" + +msgid "title" +msgstr "タイトル" + +msgid "content" +msgstr "内容" + +msgid "enable comments" +msgstr "コメントを有効にする" + +msgid "template name" +msgstr "テンプレート名" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"例: “flatpages/contact_page.html”. 指定しなければ、デフォルト値の “flatpages/" +"default.html” を使います。" + +msgid "registration required" +msgstr "登録が必要です" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "チェックした場合、ログインしたユーザーだけがページを参照できます。" + +msgid "sites" +msgstr "サイト" + +msgid "flat page" +msgstr "フラットページ" + +msgid "flat pages" +msgstr "フラットページ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ka/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ka/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9b20adf Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ka/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ka/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ka/LC_MESSAGES/django.po new file mode 100644 index 0000000..3bf4bcc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ka/LC_MESSAGES/django.po @@ -0,0 +1,88 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# André Bouatchidzé , 2013 +# avsd05 , 2011 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Georgian (http://www.transifex.com/django/django/language/" +"ka/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ka\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +msgid "Advanced options" +msgstr "დამატებითი პარამეტრები" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"მაგალითი: '/about/contact/'. ყურადღება მიაქციეთ დახრილ ხაზებს თავში და " +"ბოლოში." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"ეს მნიშვნელობა უნდა შეიცავდეს მხოლოდ ლათინურ ასოებს, ციფრებს, წერტილებს, " +"ხაზგასმის ნიშნებს, დეფისებს, დახრილ ხაზებს და ტილდებს." + +msgid "URL is missing a leading slash." +msgstr "URL-ს დასაწყისში აკლია დახრილი ხაზი." + +msgid "URL is missing a trailing slash." +msgstr "URL-ს ბოლოში აკლია დახრილი ხაზი." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "უბრალო გვერდი url-ით %(url)s უკვე არსებობს საიტისთვის %(site)s" + +msgid "title" +msgstr "სათაური" + +msgid "content" +msgstr "კონტენტი" + +msgid "enable comments" +msgstr "ჩავრთოთ კომენტარები" + +msgid "template name" +msgstr "შაბლონის სახელი" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"მაგალითი: 'flatpages/contact_page.html'. თუ იგი მითითებული არ არის, " +"გამოყენებული იქნება 'flatpages/default.html'." + +msgid "registration required" +msgstr "რეგისტრაცია აუცილებელია" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"თუ ეს დროშა ჩართულია, მხოლო შემოსულ მომხმარებლებს ექნებათ გვერდის " +"დათვალიერების საშუალება." + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "უბრალო გვერდი" + +msgid "flat pages" +msgstr "უბრალო გვერდები" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/kk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/kk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f8ef043 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/kk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/kk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/kk/LC_MESSAGES/django.po new file mode 100644 index 0000000..4135eca --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/kk/LC_MESSAGES/django.po @@ -0,0 +1,88 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Leo Trubach , 2017 +# yun_man_ger , 2011 +# Zhazira , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2019-01-18 00:18+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Kazakh (http://www.transifex.com/django/django/language/kk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kk\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +msgid "Advanced options" +msgstr "Толық опциялар" + +msgid "Flat Pages" +msgstr "Жай беттер" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"Мысал: '/about/contact/'. Басында және аяғында слэштің болуын тексеріңіз." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Бұл мән тек әріптерден, сандардан, нүктелерден, төменгі сызықтардан, " +"сызықшалардан, слэштерден немесе тильдалардан құралуы тиіс. " + +msgid "Example: '/about/contact'. Make sure to have a leading slash." +msgstr "" + +msgid "URL is missing a leading slash." +msgstr "URLдың басында бөлшек белгісі жоқ" + +msgid "URL is missing a trailing slash." +msgstr "URLдың аяғында бөлшек белгісі жоқ" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "%(url)s url'ымен жайбет %(site)s сайтта бұрыннан бар" + +msgid "title" +msgstr "атау" + +msgid "content" +msgstr "мазмұн" + +msgid "enable comments" +msgstr "комментарийларды рұқсат ету" + +msgid "template name" +msgstr "шаблон атауы" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"Мысал: 'flatpages/contact_page.html'. Ештенке берілмесе, 'flatpages/default." +"html' қолданылады." + +msgid "registration required" +msgstr "тіркеу қажетті" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Бұл белгіленген жағдайда, тек енген қолданушылар ғана бетті көре алады." + +msgid "sites" +msgstr "сайттар" + +msgid "flat page" +msgstr "Жай бет" + +msgid "flat pages" +msgstr "Жай беттер" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/km/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/km/LC_MESSAGES/django.mo new file mode 100644 index 0000000..73e5fa3 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/km/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/km/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/km/LC_MESSAGES/django.po new file mode 100644 index 0000000..8ed4eee --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/km/LC_MESSAGES/django.po @@ -0,0 +1,80 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Khmer (http://www.transifex.com/django/django/language/km/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: km\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Advanced options" +msgstr "" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "អាស័យដ្ឋានគេហទំព័រ(URL)" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"ឧទាហរណ៍  '/about/contact/' ។ ត្រូវប្រាកដថាមានសញ្ញា / ទាំងនៅផ្នែកខាងមុខ និង ខាងក្រោយ។" + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" + +msgid "URL is missing a leading slash." +msgstr "" + +msgid "URL is missing a trailing slash." +msgstr "" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" + +msgid "title" +msgstr "ចំណងជើង" + +msgid "content" +msgstr "អត្ថន័យ" + +msgid "enable comments" +msgstr "អនុញ្ញាត" + +msgid "template name" +msgstr "ឈ្មោះឯកសារគំរូ" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"ឧទាហរណ៍ 'flatpages/contact_page.html'។ ប្រសិនឯកសារនេះមិនមានទេ​" +" នោះឯកសារ 'flatpages/default.html'នឹងត្រូវប្រើ។" + +msgid "registration required" +msgstr "ត្រូវការសមាជិកភាព" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "ប្រសិនជាចុចជ្រើសរើសយកជំរើសនេះ នោះ មានតែសមាជិកទេដែលអាចមើលទំព័រនេះបាន​។" + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "ទំព័ថ្មី" + +msgid "flat pages" +msgstr "ទំព័ថ្មី" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/kn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/kn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ed64a6b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/kn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/kn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/kn/LC_MESSAGES/django.po new file mode 100644 index 0000000..83198cc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/kn/LC_MESSAGES/django.po @@ -0,0 +1,82 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Kannada (http://www.transifex.com/django/django/language/" +"kn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kn\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Advanced options" +msgstr "" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"ಉದಾ:'/about/contact/'. ಮೊದಲು ಮತ್ತು ಕೊನೆಯಲ್ಲಿ ಓರೆಗೆರೆ (/) ಇರುವಂತೆ ನೋಡಿಕೊಳ್ಳಿ." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" + +msgid "URL is missing a leading slash." +msgstr "" + +msgid "URL is missing a trailing slash." +msgstr "" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" + +msgid "title" +msgstr "ಶೀರ್ಷಿಕೆ" + +msgid "content" +msgstr "ಒಳವಿಷಯ" + +msgid "enable comments" +msgstr "ಟಿಪ್ಪಣಿಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ" + +msgid "template name" +msgstr "ಟೆಂಪ್ಲೇಟಿನ ಹೆಸರು" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"ಉದಾ:'flatpages/contact_page.html'. ಇದನ್ನು ಕೊಡದಿದ್ದರೆ ಗಣಕವ್ಯವಸ್ಥೆಯು 'flatpages/" +"default.html' ಅನ್ನು ಬಳಸುವದು." + +msgid "registration required" +msgstr "ನೋಂದಾವಣೆ ಅಗತ್ಯವಿದೆ." + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"ಇದರಲ್ಲಿ ಗುರುತು ಮಾಡಿದರೆ, ಒಳಬಂದ (ಲಾಗಿನ್ ಆದ) ಬಳಕೆದಾರರು ಮಾತ್ರ ಪುಟವನ್ನು ನೋಡಬಹುದು." + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "ಚಪ್ಪಟೆ ಪುಟ" + +msgid "flat pages" +msgstr "ಚಪ್ಪಟೆ ಪುಟಗಳು" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ko/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ko/LC_MESSAGES/django.mo new file mode 100644 index 0000000..6f13b0d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ko/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ko/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ko/LC_MESSAGES/django.po new file mode 100644 index 0000000..f0f117a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ko/LC_MESSAGES/django.po @@ -0,0 +1,90 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jiyoon, Ha , 2016 +# Ian Y. Choi , 2015 +# Jaehong Kim , 2011 +# Jannis Leidel , 2011 +# Jay Oh , 2020 +# Le Tartuffe , 2014 +# Jonghwa Seo , 2019 +# JunGu Kang , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-07-04 14:22+0000\n" +"Last-Translator: Jay Oh \n" +"Language-Team: Korean (http://www.transifex.com/django/django/language/ko/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ko\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Advanced options" +msgstr "고급 옵션" + +msgid "Flat Pages" +msgstr "플랫 페이지" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "앞, 뒤에 슬래시(/)를 넣으세요. 예:'/about/contact/' " + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"이 문자열은 문자, 숫자, 점, 언더스코어, 대쉬, 슬래시, 틸드만 사용해야 합니다." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "맨앞에 슬래시(/)를 반드시 넣으세요. 예: '/about/contact'" + +msgid "URL is missing a leading slash." +msgstr "URL 맨 앞의 슬래시가 없습니다." + +msgid "URL is missing a trailing slash." +msgstr "URL 맨 뒤의 슬래시가 없습니다." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "%(site)s 사이트에 %(url)s 을/를 사용한 플랫 페이지가 이미 존재합니다." + +msgid "title" +msgstr "제목" + +msgid "content" +msgstr "내용" + +msgid "enable comments" +msgstr "사용 가능한 코멘트" + +msgid "template name" +msgstr "템플릿 이름" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"예: 'flatpages/contact_page.html' 를 사용할 수 없는 경우 시스템이 'flatpages/" +"default.html' 을/를 사용합니다." + +msgid "registration required" +msgstr "등록이 필요합니다" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "체크할 경우, 로그인한 사용자만 해당 페이지를 볼 수 있습니다." + +msgid "sites" +msgstr "사이트" + +msgid "flat page" +msgstr "플랫 페이지" + +msgid "flat pages" +msgstr "플랫 페이지들" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ky/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ky/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c4aa02f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ky/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ky/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ky/LC_MESSAGES/django.po new file mode 100644 index 0000000..7f420f3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ky/LC_MESSAGES/django.po @@ -0,0 +1,89 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Soyuzbek Orozbek uulu , 2020 +# Soyuzbek Orozbek uulu , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-05-23 06:23+0000\n" +"Last-Translator: Soyuzbek Orozbek uulu \n" +"Language-Team: Kyrgyz (http://www.transifex.com/django/django/language/ky/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ky\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Advanced options" +msgstr "Дагы мүмкүнчүлүктөр" + +msgid "Flat Pages" +msgstr "Туруктуу барактар" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Мисалы: “/about/contact/”. Башында жана аягында бөлчөк бар экендигин " +"текшериңиз." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Бул маани жалаң арип, сан, чекит, астсызык, сызык, бөлчөк же тилда камтый " +"алат." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "Мисалы: “/about/contact”. Башында бөлчөк бар экендигин текшериңиз." + +msgid "URL is missing a leading slash." +msgstr "URL башында бөлчөгү жок." + +msgid "URL is missing a trailing slash." +msgstr "URL аягында бөлчөгү жок." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "%(url)s URLдүү барак %(site)sсайтында мурдатан эле бар." + +msgid "title" +msgstr "наам" + +msgid "content" +msgstr "мазмун" + +msgid "enable comments" +msgstr "пикирлерди күйгүзүү" + +msgid "template name" +msgstr "калып аты" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Мисалы: “flatpages/contact_page.html”. Эгер бул көрсөтүлбөсө, систем " +"“flatpages/default.html” колдоно берет." + +msgid "registration required" +msgstr "катталуу талап кылынат." + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Эгер бул тандалса жалаң гана катталып кирген колдонуучулар бул баракты көрө " +"алышат." + +msgid "sites" +msgstr "сайттар" + +msgid "flat page" +msgstr "туруктуу барак" + +msgid "flat pages" +msgstr "туруктуу барактар" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/lb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/lb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1367568 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/lb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/lb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/lb/LC_MESSAGES/django.po new file mode 100644 index 0000000..cbacfee --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/lb/LC_MESSAGES/django.po @@ -0,0 +1,77 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Luxembourgish (http://www.transifex.com/django/django/" +"language/lb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" + +msgid "URL is missing a leading slash." +msgstr "" + +msgid "URL is missing a trailing slash." +msgstr "" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" + +msgid "title" +msgstr "" + +msgid "content" +msgstr "" + +msgid "enable comments" +msgstr "" + +msgid "template name" +msgstr "" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" + +msgid "registration required" +msgstr "" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "" + +msgid "flat pages" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/lt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/lt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..fe4c1e4 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/lt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/lt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/lt/LC_MESSAGES/django.po new file mode 100644 index 0000000..16e75aa --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/lt/LC_MESSAGES/django.po @@ -0,0 +1,94 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Kostas , 2011 +# Matas Dailyda , 2015,2019 +# Simonas Kazlauskas , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2019-01-18 10:34+0000\n" +"Last-Translator: Matas Dailyda \n" +"Language-Team: Lithuanian (http://www.transifex.com/django/django/language/" +"lt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lt\n" +"Plural-Forms: nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < " +"11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? " +"1 : n % 1 != 0 ? 2: 3);\n" + +msgid "Advanced options" +msgstr "Sudėtingesni nustatymai" + +msgid "Flat Pages" +msgstr "Paprasti puslapiai" + +msgid "URL" +msgstr "Nuoroda" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"Pavyzdžiui: '/about/contact/'. Įsitikink, kad yra pasvirieji brūkšniai " +"pradžioj ir gale." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Ši reikšmė gali būti sudaryta tik iš raidžių, skaičių, pabraukimų, brūkšnių " +"ir/arba pasvirų brūkšnių." + +msgid "Example: '/about/contact'. Make sure to have a leading slash." +msgstr "" +"Pavizdys: '/apie/kontaktai'. Įsitikinkite kad pradžioje būtų pasvirasis " +"brūkšnys." + +msgid "URL is missing a leading slash." +msgstr "Nuorodos pradžioje trūksta pasvirojo brūkšnio." + +msgid "URL is missing a trailing slash." +msgstr "Nuorodos pabaigoje trūksta pasvirojo brūkšnio." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Paprastas puslapis su adresu %(url)s %(site)s puslapyje jau egzistuoja" + +msgid "title" +msgstr "pavadinimas" + +msgid "content" +msgstr "turinys" + +msgid "enable comments" +msgstr "įjungti komentavimą" + +msgid "template name" +msgstr "šablono vardas" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"Pavyzdžiui: 'flatpages/contact_page.html'. Jeigu bus nenurodytas, sistema " +"naudos 'flatpages/default.html'." + +msgid "registration required" +msgstr "registracija privaloma" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "Jeigu pažymėta, tik prisijungę vartotojai galės matyti šį puslapį." + +msgid "sites" +msgstr "tinklalapiai" + +msgid "flat page" +msgstr "paprastas puslapis" + +msgid "flat pages" +msgstr "paprasti puslapiai" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/lv/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/lv/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d7ce9c2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/lv/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/lv/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/lv/LC_MESSAGES/django.po new file mode 100644 index 0000000..12260ec --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/lv/LC_MESSAGES/django.po @@ -0,0 +1,93 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# NullIsNot0 , 2019 +# peterisb , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-11-07 07:17+0000\n" +"Last-Translator: NullIsNot0 \n" +"Language-Team: Latvian (http://www.transifex.com/django/django/language/" +"lv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lv\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : " +"2);\n" + +msgid "Advanced options" +msgstr "Papildus opcijas" + +msgid "Flat Pages" +msgstr "Vienkāršās lapas" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Piemēram: “/about/contact/”. Pārliecinieties, ka esat ievietojuši sākuma un " +"beigu slīpsvītras." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Šai vērtība ir jāsatur tikai burtus, ciparus, punktus, pasvītrojumi, " +"domuzīmes, slīpsvītras vai tildes simboli." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" +"Piemēram: “/about/contact”. Pārliecinieties, ka esat ievietojuši sākuma " +"slīpsvītru." + +msgid "URL is missing a leading slash." +msgstr "URL trūkst sākuma slīpsvītra." + +msgid "URL is missing a trailing slash." +msgstr "URL trūkst beigu slīpsvītra." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Vienkāršā lapa ar url %(url)s jau eksistē vietnei %(site)s" + +msgid "title" +msgstr "virsraksts" + +msgid "content" +msgstr "saturs" + +msgid "enable comments" +msgstr "ieslēgt komentārus" + +msgid "template name" +msgstr "šablona nosaukums" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Piemēram: “flatpages/contact_page.html”. Ja tas nav norādīts, sistēma lietos " +"“flatpages/default.html”." + +msgid "registration required" +msgstr "reģistrācija obligāta" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Ja šis ir atzīmēts, tikai pieslēgušies lietotāji, varēs piekļūt šai lapu." + +msgid "sites" +msgstr "vietnes" + +msgid "flat page" +msgstr "vienkārša lapa" + +msgid "flat pages" +msgstr "vienkāršas lapas" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/mk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/mk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..68d4a8b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/mk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/mk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/mk/LC_MESSAGES/django.po new file mode 100644 index 0000000..b612fb2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/mk/LC_MESSAGES/django.po @@ -0,0 +1,90 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Vasil Vangelovski , 2016 +# Vasil Vangelovski , 2014 +# Vasil Vangelovski , 2011-2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Vasil Vangelovski \n" +"Language-Team: Macedonian (http://www.transifex.com/django/django/language/" +"mk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mk\n" +"Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n" + +msgid "Advanced options" +msgstr "Напредни можности" + +msgid "Flat Pages" +msgstr "Статични страници" + +msgid "URL" +msgstr "Веб адреса" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"На пр. „/за_сајтот/контакт/“. Осигурајте се дека имате коса црта и на крајот " +"и на почетокот." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Оваа вредност смее да има само букви, бројки, долни црти, црти, коси црти " +"или тилди." + +msgid "URL is missing a leading slash." +msgstr "На веб адресата и недостасува почетна црта." + +msgid "URL is missing a trailing slash." +msgstr "На веб адресата и недостасува завршна црта." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" +"Статична страница со веб адреса %(url)s веќе постои за сајтот %(site)s" + +msgid "title" +msgstr "наслов" + +msgid "content" +msgstr "содржина" + +msgid "enable comments" +msgstr "овозможи коментари" + +msgid "template name" +msgstr "име на шаблон" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"На пр. „flatpages/kontakt.html'. Ако не го внесете ова, системот ќе користи " +"„flatpages/default.html“." + +msgid "registration required" +msgstr "потребна е регистрација" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Ако ова е штиклирано, само најавените корисници ќе можат да ја гледаат оваа " +"страница." + +msgid "sites" +msgstr "сајтови" + +msgid "flat page" +msgstr "статична страница" + +msgid "flat pages" +msgstr "статични страници" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ml/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ml/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d4cf1e3 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ml/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ml/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ml/LC_MESSAGES/django.po new file mode 100644 index 0000000..4d5fd10 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ml/LC_MESSAGES/django.po @@ -0,0 +1,89 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Aby Thomas , 2014 +# Hrishikesh , 2019-2020 +# Jannis Leidel , 2011 +# Rajeesh Nair , 2011-2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-05-13 21:22+0000\n" +"Last-Translator: Hrishikesh \n" +"Language-Team: Malayalam (http://www.transifex.com/django/django/language/" +"ml/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ml\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "സങ്കീർണ്ണമായ ഓപ്ഷനുകൾ" + +msgid "Flat Pages" +msgstr "ഫ്ലാറ്റ് പേജുകൾ" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"ഉദാഹരണം: “/about/contact/”. തുടക്കത്തിലും അവസാനവും സ്ലാഷുകൾ ഉണ്ടെന്ന് ഉറപ്പുവരുത്തുക." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"ഇതിൽ അക്ഷരങ്ങൾ, നമ്പറുകൾ, കുത്തുകൾ, അണ്ടർസ്കോറുകൾ, ഡാഷുകൾ, സ്ലാഷുകൾ അതുമല്ലെങ്കിൽ ടിൽഡുകൾ " +"എന്നിവ മാത്രമേ അനുവദിക്കുള്ളൂ." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "ഉദാഹരണം: “/about/contact”. തുടക്കത്തിൽ ഒരു സ്ലാഷ് ഉണ്ടെന്ന് ഉറപ്പുവരുത്തുക." + +msgid "URL is missing a leading slash." +msgstr "URLന്റെ മുന്‍വശത്ത് ഒരു സ്ലാഷിന്റെ കുറവുണ്ട്." + +msgid "URL is missing a trailing slash." +msgstr "URLന്റെ പിന്‍വശത്ത് ഒരു സ്ലാഷിന്റെ കുറവുണ്ട്." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "%(site)s എന്ന സൈറ്റിനു %(url)s എന്ന url ഉള്ള ഫ്ലാറ്റ്പേജ് നിലവിലുണ്ട്" + +msgid "title" +msgstr "ശീര്‍ഷകം" + +msgid "content" +msgstr "ഉള്ളടക്കം" + +msgid "enable comments" +msgstr "അഭിപ്രായങ്ങള്‍ അനുവദിക്കുക" + +msgid "template name" +msgstr "ടെമ്പ്ലേറ്റിന്റെ പേര്" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"ഉദാ: 'flatpages/contact_page.html'. ഇതു നല്കിയില്ലെങ്കില്‍, പകരമായി 'flatpages/" +"default.html' ആയിരിക്കും ഉപയോഗിക്കുക." + +msgid "registration required" +msgstr "രജിസ്ട്രേഷന്‍ ആവശ്യമാണ്" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "ഇതു ടിക് ചെയ്താല്‍ പിന്നെ ലോഗ്-ഇന്‍ ചെയ്ത യൂസര്‍ക്കു മാത്രമേ ഈ പേജ് കാണാന്‍ കഴിയൂ." + +msgid "sites" +msgstr "സൈറ്റുകൾ" + +msgid "flat page" +msgstr "ഫ്ളാറ്റ് പേജ്" + +msgid "flat pages" +msgstr "ഫ്ളാറ്റ് പേജുകള്‍" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/mn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/mn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a9c8f09 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/mn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/mn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/mn/LC_MESSAGES/django.po new file mode 100644 index 0000000..1dedfe1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/mn/LC_MESSAGES/django.po @@ -0,0 +1,92 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Zorig, 2014,2016 +# Zorig, 2019 +# Анхбаяр Анхаа , 2011-2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2019-02-19 02:15+0000\n" +"Last-Translator: Zorig\n" +"Language-Team: Mongolian (http://www.transifex.com/django/django/language/" +"mn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Дээд хэрэглээний сонголтууд" + +msgid "Flat Pages" +msgstr "Дан хуудас" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"Жишээ: '/about/contact/'. Хөтлөх буюу зам заах ташуу зураас байх хэрэгтэй." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Энэ хэсэгт зөвхөн үсэг, тоо, цэг, доогуур зураас, налуу зураасууд бичих " +"боломжтой. " + +msgid "Example: '/about/contact'. Make sure to have a leading slash." +msgstr "" +"Жишээ: '/about/contact/'. Хөтлөх буюу зам заах ташуу зураас байх хэрэгтэй." + +msgid "URL is missing a leading slash." +msgstr "URL ийн эхний slash ийг мартсан байна." + +msgid "URL is missing a trailing slash." +msgstr "URL ийн арийн slash ийг мартсан байна" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Хуудасны хаяг %(url)s %(site)s дээр давхардаж байна." + +msgid "title" +msgstr "гарчиг" + +msgid "content" +msgstr "агуулга" + +msgid "enable comments" +msgstr "санал сэтгэгдэл үлдээх боломжтой болгох" + +msgid "template name" +msgstr "загварын нэр" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"Жишээ: 'flatpages/contact_page.html'. Хэрэв ийм зүйл гарч ирэхгүй бол систем " +"'flatpages/default.html'-ийг хэрэглэнэ." + +msgid "registration required" +msgstr "бүртгэгдсэн хэрэглэгчид үзнэ" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Үүнийг чагтлавал зөвхөн сайтад нэвтэрсэн хэрэглэгч сайтыг харах боломжтой " +"болно." + +msgid "sites" +msgstr "сайтууд" + +msgid "flat page" +msgstr "өөрчлөлтгүй хуудас" + +msgid "flat pages" +msgstr "өөрчлөлтгүй хуудаснууд" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/mr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/mr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7d4393d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/mr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/mr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/mr/LC_MESSAGES/django.po new file mode 100644 index 0000000..f2bed7f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/mr/LC_MESSAGES/django.po @@ -0,0 +1,74 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-03-18 09:16+0100\n" +"PO-Revision-Date: 2015-03-18 08:34+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Marathi (http://www.transifex.com/projects/p/django/language/" +"mr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mr\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" + +msgid "URL is missing a leading slash." +msgstr "" + +msgid "URL is missing a trailing slash." +msgstr "" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" + +msgid "title" +msgstr "" + +msgid "content" +msgstr "" + +msgid "enable comments" +msgstr "" + +msgid "template name" +msgstr "" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" + +msgid "registration required" +msgstr "" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" + +msgid "flat page" +msgstr "" + +msgid "flat pages" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ms/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ms/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7af7bbd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ms/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ms/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ms/LC_MESSAGES/django.po new file mode 100644 index 0000000..4315687 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ms/LC_MESSAGES/django.po @@ -0,0 +1,87 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jafry Hisham, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2021-11-16 12:59+0000\n" +"Last-Translator: Jafry Hisham\n" +"Language-Team: Malay (http://www.transifex.com/django/django/language/ms/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ms\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Advanced options" +msgstr "Pilihan lanjut" + +msgid "Flat Pages" +msgstr "Muka rata" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Contoh: \"/berkenaan/hubungi/\". Pastikan ada sempang awalan dan akhiran." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Niali ini hanya boleh mengandugi huruf, nombor, titik, garis-bawah, " +"sengkang, sempang atau tilde." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "Contoh: \"/berkenaan/hubungi\". Pastikan ada sempang awalan." + +msgid "URL is missing a leading slash." +msgstr "URL tidak mempunyai sempang awalan." + +msgid "URL is missing a trailing slash." +msgstr "URL tidak mempunyai sempang akhiran." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Mukarata dengan url %(url)s sudah wujud bagi laman %(site)s" + +msgid "title" +msgstr "tajuk" + +msgid "content" +msgstr "kandungan" + +msgid "enable comments" +msgstr "hidupkan komen" + +msgid "template name" +msgstr "nama templat" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Contoh: \"mukarata/ruangan_hubungi.html\". Sekiranya ini tidak diberikam, " +"sistem akan menggunakan \"flatpages/defulat.html\"." + +msgid "registration required" +msgstr "Pendaftaran diperlukan" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Sekiranya ini ditanda, hanya pengguna yang log-masuk sahaja akan dapat " +"melihat ruangan ini." + +msgid "sites" +msgstr "laman-laman" + +msgid "flat page" +msgstr "muka rata" + +msgid "flat pages" +msgstr "muka rata" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/my/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/my/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a959d4c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/my/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/my/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/my/LC_MESSAGES/django.po new file mode 100644 index 0000000..e46bfbe --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/my/LC_MESSAGES/django.po @@ -0,0 +1,77 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Burmese (http://www.transifex.com/django/django/language/" +"my/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: my\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Advanced options" +msgstr "" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "ယူအာအယ်" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" + +msgid "URL is missing a leading slash." +msgstr "" + +msgid "URL is missing a trailing slash." +msgstr "" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" + +msgid "title" +msgstr "" + +msgid "content" +msgstr "" + +msgid "enable comments" +msgstr "" + +msgid "template name" +msgstr "" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" + +msgid "registration required" +msgstr "" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "" + +msgid "flat pages" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/nb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/nb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4383609 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/nb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/nb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/nb/LC_MESSAGES/django.po new file mode 100644 index 0000000..b6eba01 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/nb/LC_MESSAGES/django.po @@ -0,0 +1,91 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# jensadne , 2014 +# Jon , 2015 +# Jon , 2019-2020 +# Jon , 2011-2012 +# Sigurd Gartmann , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-01-21 12:12+0000\n" +"Last-Translator: Jon \n" +"Language-Team: Norwegian Bokmål (http://www.transifex.com/django/django/" +"language/nb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Avanserte innstillinger" + +msgid "Flat Pages" +msgstr "Flatsider" + +msgid "URL" +msgstr "Nettadresse" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Eksempel: \"/om/kontakt/\". Kontroller at det er en skråstrek foran og bak." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Dette feltet kan kun inneholde bokstaver, nummer, skilletegn, understreker, " +"bindestreker, skråstreker eller tilder." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "Eksempel: \"/om/kontakt\". Kontroller at det er en skråstrek foran." + +msgid "URL is missing a leading slash." +msgstr "URL mangler innledende skråstrek." + +msgid "URL is missing a trailing slash." +msgstr "URL mangler avsluttende skråstrek." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Flatside med URL-en %(url)s finnes allerede for siden %(site)s" + +msgid "title" +msgstr "tittel" + +msgid "content" +msgstr "innhold" + +msgid "enable comments" +msgstr "tillat kommentarer" + +msgid "template name" +msgstr "malnavn" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Eksempel: \"flatpages/contact_page.html\". Hvis denne ikke er gitt, vil " +"\"flatpages/default.html\" bli brukt." + +msgid "registration required" +msgstr "krever registrering" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "Hvis denne er krysset av, kan kun innloggede brukere se siden." + +msgid "sites" +msgstr "nettsteder" + +msgid "flat page" +msgstr "flatside" + +msgid "flat pages" +msgstr "flatsider" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ne/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ne/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e435dd8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ne/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ne/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ne/LC_MESSAGES/django.po new file mode 100644 index 0000000..54ec75f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ne/LC_MESSAGES/django.po @@ -0,0 +1,77 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Sagar Chalise , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Sagar Chalise \n" +"Language-Team: Nepali (http://www.transifex.com/django/django/language/ne/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ne\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "उदाहरणका लागि: '/about/contact/' । अगाडि र पछाडि '/' राख्न नभुल्नुहोला ।" + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "यो मानमा अंक, वर्ण, थोप्लो, अन्डरस्कोर, ड्यास, स्ल्यास र टिल्ड मात्र हुनुपर्दछ ।" + +msgid "URL is missing a leading slash." +msgstr "" + +msgid "URL is missing a trailing slash." +msgstr "" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" + +msgid "title" +msgstr "शीर्षक" + +msgid "content" +msgstr "विषय" + +msgid "enable comments" +msgstr "प्रतिकृयाको लागि मञ्जुरी दिनुहोस" + +msgid "template name" +msgstr "टेम्प्लेटको नाम" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" + +msgid "registration required" +msgstr "दर्ता अनिवार्य छ ।" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" + +msgid "sites" +msgstr "साइटहरु" + +msgid "flat page" +msgstr "" + +msgid "flat pages" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/nl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/nl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..af4bd8a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/nl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/nl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/nl/LC_MESSAGES/django.po new file mode 100644 index 0000000..2f06f80 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/nl/LC_MESSAGES/django.po @@ -0,0 +1,92 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Harro van der Klauw , 2012 +# Ilja Maas , 2015 +# Jannis Leidel , 2011 +# Jeffrey Gelens , 2012 +# Sander Steffann , 2015 +# Tino de Bruijn , 2011 +# Tonnes , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-09-17 08:52+0000\n" +"Last-Translator: Tonnes \n" +"Language-Team: Dutch (http://www.transifex.com/django/django/language/nl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Geavanceerde opties" + +msgid "Flat Pages" +msgstr "Platte pagina's" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "Voorbeeld: ‘/about/contact/’. Zorg voor slashes aan het begin en eind." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Deze waarde mag alleen letters, cijfers, punten, liggende streepjes, " +"streepjes, slashes of tildes bevatten." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "Voorbeeld: ‘/about/contact’. Zorg voor een slash aan het begin." + +msgid "URL is missing a leading slash." +msgstr "In de URL ontbreekt een beginslash." + +msgid "URL is missing a trailing slash." +msgstr "In de URL ontbreekt een eindslash." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Platte pagina met URL %(url)s bestaat al voor website %(site)s" + +msgid "title" +msgstr "titel" + +msgid "content" +msgstr "inhoud" + +msgid "enable comments" +msgstr "opmerkingen toestaan" + +msgid "template name" +msgstr "sjabloonnaam" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Voorbeeld: ‘flatpages/contact_page.html’. Als dit niet is opgegeven, wordt " +"‘flatpages/default.html’ gebruikt." + +msgid "registration required" +msgstr "registratie vereist" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Als dit is aangevinkt, kunnen alleen aangemelde gebruikers de pagina " +"bekijken." + +msgid "sites" +msgstr "websites" + +msgid "flat page" +msgstr "platte pagina" + +msgid "flat pages" +msgstr "platte pagina's" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/nn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/nn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a62a709 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/nn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/nn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/nn/LC_MESSAGES/django.po new file mode 100644 index 0000000..55c92ea --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/nn/LC_MESSAGES/django.po @@ -0,0 +1,90 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# hgrimelid , 2011 +# Jannis Leidel , 2011 +# Sivert Olstad, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2021-11-12 08:48+0000\n" +"Last-Translator: Sivert Olstad\n" +"Language-Team: Norwegian Nynorsk (http://www.transifex.com/django/django/" +"language/nn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Avanserte innstillingar" + +msgid "Flat Pages" +msgstr "Flatsider" + +msgid "URL" +msgstr "Nettadresse" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Eksempel: “/om/kontakt/”. Kontroller at det er ein skråstrek framanfor og " +"bak." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Dette feltet kan berre innehalde bokstavar, nummer, skilleteikn, " +"understrekar, bindestrekar, skråstrekar eller tilder." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" +"Eksempel: “/om/kontakt/”. Kontroller at det er ein skråstrek framanfor." + +msgid "URL is missing a leading slash." +msgstr "Nettadressa manglar ein skråstrek framanfor." + +msgid "URL is missing a trailing slash." +msgstr "Nettadressa manglar ein skråstrek bak." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Flatside med nettadresse %(url)s eksisterer allereie for sida %(site)s" + +msgid "title" +msgstr "tittel" + +msgid "content" +msgstr "innhald" + +msgid "enable comments" +msgstr "tillat kommentarer" + +msgid "template name" +msgstr "malnamn" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Døme: “flatpages/contact_page.html”. Dersom denne ikkje er oppgjeve vert " +"“flatpages/default.html” brukt." + +msgid "registration required" +msgstr "krevar registrering" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "Dersom denne er kryssa av, kan berre innlogga brukarar sjå sida." + +msgid "sites" +msgstr "nettstadar" + +msgid "flat page" +msgstr "flatside" + +msgid "flat pages" +msgstr "flatsider" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/os/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/os/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5d25b6b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/os/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/os/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/os/LC_MESSAGES/django.po new file mode 100644 index 0000000..aaa9895 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/os/LC_MESSAGES/django.po @@ -0,0 +1,86 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Soslan Khubulov , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Ossetic (http://www.transifex.com/django/django/language/" +"os/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: os\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Флдӕр фадӕттӕ" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"Цӕвиттон: '/about/contact/'. Дӕ хъус дар цӕмӕ дзы сӕйраг ӕмӕ хицӕнгӕнаг " +"слӕштӕ уой." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Ам хъуамӕ ӕрмӕст дамгъӕтӕ, стъӕлфытӕ, бынылхӕххытӕ, дефистӕ, слӕштӕ ӕмӕ " +"тильдӕтӕ уой." + +msgid "URL is missing a leading slash." +msgstr "URL-ы сӕйраг слӕш нӕй." + +msgid "URL is missing a trailing slash." +msgstr "URL-ы хицӕнгӕнаг слӕш нӕй." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "%(url)s url-имӕ тъӕпӕнфарс нырид ис %(site)s сайтӕн" + +msgid "title" +msgstr "сӕр" + +msgid "content" +msgstr "мидис" + +msgid "enable comments" +msgstr "хъуыдытӕ баиу кӕнын" + +msgid "template name" +msgstr "хуызӕгы ном" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"Цӕвиттон: 'flatpages/contact_page.html'. Кӕд ай лӕвӕрд нӕу, уӕд системӕ " +"сӕвӕрдзӕн 'flatpages/default.html'." + +msgid "registration required" +msgstr "регистраци хъӕуы" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Кӕд ай нысангонд у, уӕд ацы фарс ӕрмӕст системӕмӕ хызт архайджытӕн уыдзӕнис " +"бар уынын." + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "тъӕпӕн фарс" + +msgid "flat pages" +msgstr "тъӕпӕн фӕрстӕ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/pa/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/pa/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c20a520 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/pa/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/pa/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/pa/LC_MESSAGES/django.po new file mode 100644 index 0000000..ab56520 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/pa/LC_MESSAGES/django.po @@ -0,0 +1,78 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Panjabi (Punjabi) (http://www.transifex.com/django/django/" +"language/pa/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pa\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "ਤਕਨੀਕੀ ਚੋਣਾਂ" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" + +msgid "URL is missing a leading slash." +msgstr "" + +msgid "URL is missing a trailing slash." +msgstr "" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" + +msgid "title" +msgstr "ਟਾਈਟਲ" + +msgid "content" +msgstr "ਸਮੱਗਰੀ" + +msgid "enable comments" +msgstr "ਟਿੱਪਣੀਆਂ ਚਾਲੂ" + +msgid "template name" +msgstr "ਟੈਪਲੇਟ ਨਾਂ" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" + +msgid "registration required" +msgstr "ਰਜਿਸਟਰੇਸ਼ਨ ਲੋੜੀਦੀ ਹੈ" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "" + +msgid "flat pages" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/pl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/pl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..74b2580 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/pl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/pl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/pl/LC_MESSAGES/django.po new file mode 100644 index 0000000..51f2bfb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/pl/LC_MESSAGES/django.po @@ -0,0 +1,96 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# angularcircle, 2012 +# angularcircle, 2012 +# Jannis Leidel , 2011 +# Janusz Harkot , 2015 +# m_aciek , 2019 +# Tomasz Kajtoch , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-11-11 14:08+0000\n" +"Last-Translator: m_aciek \n" +"Language-Team: Polish (http://www.transifex.com/django/django/language/pl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pl\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n" +"%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n" +"%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" + +msgid "Advanced options" +msgstr "Opcje zaawansowane" + +msgid "Flat Pages" +msgstr "Strony statyczne" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Przykład: „/about/contact/”. Upewnij się, że wpisałeś początkowy i końcowy " +"ukośnik." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"To pole może zawierać jedynie litery, cyfry, kropki, podkreślenia, myślniki, " +"ukośniki i tyldy." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" +"Przykład: „/about/contact”. Upewnij się, że wpisałeś początkowy ukośnik." + +msgid "URL is missing a leading slash." +msgstr "W URL-u brakuje początkowego ukośnika." + +msgid "URL is missing a trailing slash." +msgstr "W URL-u brakuje końcowego ukośnika." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" +"Strona statyczna o adresie %(url)s została już utworzona dla strony %(site)s" + +msgid "title" +msgstr "tytuł" + +msgid "content" +msgstr "zawartość" + +msgid "enable comments" +msgstr "włącz komentarze" + +msgid "template name" +msgstr "nazwa szablonu" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Przykład: „flatpages/contact_page.html”. Jeżeli nie zostanie podane, system " +"użyje „flatpages/default.html”." + +msgid "registration required" +msgstr "wymagana rejestracja" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Jeżeli zaznaczone - tylko zalogowani użytkownicy będą mogli zobaczyć stronę." + +msgid "sites" +msgstr "strony" + +msgid "flat page" +msgstr "strona statyczna" + +msgid "flat pages" +msgstr "strony statyczne" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/pt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/pt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ffc8ef0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/pt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/pt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/pt/LC_MESSAGES/django.po new file mode 100644 index 0000000..e1f707d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/pt/LC_MESSAGES/django.po @@ -0,0 +1,87 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Nuno Mariz , 2011-2012,2015 +# Raúl Pedro Fernandes Santos, 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Nuno Mariz \n" +"Language-Team: Portuguese (http://www.transifex.com/django/django/language/" +"pt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Opções avançadas" + +msgid "Flat Pages" +msgstr "Páginas Simples" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"Exemplo: '/about/contact/'. Verifique se possui as barras no inicio e no fim." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Este valor apenas poderá conter letras, números, pontos, underscores, " +"hífenes, barras ou tils." + +msgid "URL is missing a leading slash." +msgstr "Está a faltar a barra inicial no URL." + +msgid "URL is missing a trailing slash." +msgstr "Está a faltar a barra final no URL." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "A página plana com o url %(url)s já existe no site %(site)s" + +msgid "title" +msgstr "título" + +msgid "content" +msgstr "conteúdo" + +msgid "enable comments" +msgstr "permitir comentários" + +msgid "template name" +msgstr "nome da template" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"Exemplo: 'flatpages/contact_page.html'. Se não for fornecido, o sistema " +"usará: 'flatpages/default.html'." + +msgid "registration required" +msgstr "é necessário registo" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Se estiver selecionado, apenas utilizadores autenticados poderão ver esta " +"página." + +msgid "sites" +msgstr "site" + +msgid "flat page" +msgstr "página plana" + +msgid "flat pages" +msgstr "páginas planas" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/pt_BR/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/pt_BR/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3677d3d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/pt_BR/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/pt_BR/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/pt_BR/LC_MESSAGES/django.po new file mode 100644 index 0000000..e28cabe --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/pt_BR/LC_MESSAGES/django.po @@ -0,0 +1,98 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Allisson Azevedo , 2014 +# Amanda Savluchinske , 2019 +# andrewsmedina , 2013 +# dudanogueira , 2019 +# Eduardo Cereto Carvalho, 2011 +# Fábio C. Barrionuevo da Luz , 2013 +# semente, 2012-2013 +# Jannis Leidel , 2011 +# Lucas Infante , 2015 +# Rafael Fontenelle , 2021 +# Sergio Oliveira , 2013 +# Thiago Avelino , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2021-01-17 06:37+0000\n" +"Last-Translator: Rafael Fontenelle \n" +"Language-Team: Portuguese (Brazil) (http://www.transifex.com/django/django/" +"language/pt_BR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt_BR\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Advanced options" +msgstr "Opções avançadas" + +msgid "Flat Pages" +msgstr "Páginas Planas" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Exemplo: “/about/contact/”. Certifique-se de ter barras no início e no final." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Este valor deve conter apenas letras, números, pontos, sublinhados, traços, " +"barras ou til." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "Exemplo: “/about/contact”. Certifique-se de ter uma barra no início." + +msgid "URL is missing a leading slash." +msgstr "Está faltando uma barra no início da URL." + +msgid "URL is missing a trailing slash." +msgstr "Está faltando uma barra no final da URL." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Uma flatpage com a URL %(url)s já existe para o site %(site)s" + +msgid "title" +msgstr "título" + +msgid "content" +msgstr "conteúdo" + +msgid "enable comments" +msgstr "habilitar comentários" + +msgid "template name" +msgstr "nome do template" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Exemplo: “flatpages/contact_page.html”. Se isso não for fornecido, o sistema " +"utilizará “flatpages/default.html”." + +msgid "registration required" +msgstr "registro obrigatório" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Se estiver assinalado, apenas usuários autenticados poderão ver a página." + +msgid "sites" +msgstr "sites" + +msgid "flat page" +msgstr "página plana" + +msgid "flat pages" +msgstr "páginas planas" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ro/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ro/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b8d7ae8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ro/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ro/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ro/LC_MESSAGES/django.po new file mode 100644 index 0000000..6631911 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ro/LC_MESSAGES/django.po @@ -0,0 +1,96 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bogdan Mateescu, 2019 +# Daniel Ursache-Dogariu, 2011 +# Denis Darii , 2014 +# Jannis Leidel , 2011 +# Razvan Stefanescu , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2019-01-18 12:01+0000\n" +"Last-Translator: Bogdan Mateescu\n" +"Language-Team: Romanian (http://www.transifex.com/django/django/language/" +"ro/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ro\n" +"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?" +"2:1));\n" + +msgid "Advanced options" +msgstr "Opțiuni avansate" + +msgid "Flat Pages" +msgstr "Pagini Statice" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"Exemplu: '/despre/contact/'. Asigurați-vă că sunt bare oblice la început și " +"la sfârșit." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Această valoare trebuie să conţină doar litere, numere, puncte, linii joase, " +"cratime, bare oblice sau tilde." + +msgid "Example: '/about/contact'. Make sure to have a leading slash." +msgstr "" +"Exemplu: '/despre/contact'. Asigurați-vă că sunt bare oblice la început și " +"la sfârșit." + +msgid "URL is missing a leading slash." +msgstr "În URL lipseste slashul inițial." + +msgid "URL is missing a trailing slash." +msgstr "În URL lipseste slashul final." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Pagina Flat cu url-ul %(url)s există deja pentru saitul %(site)s" + +msgid "title" +msgstr "titlu" + +msgid "content" +msgstr "conținut" + +msgid "enable comments" +msgstr "permite comentarii" + +msgid "template name" +msgstr "nume șablon" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"Exemplu: 'flatpages/contact_page.html'. Dacă aceasta nu există, sistemul va " +"folosi 'flatpages/default.html'." + +msgid "registration required" +msgstr "necesită înregistrare" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Dacă aceasta este bifată, numai utilizatorii autentificați vor putea vedea " +"pagina." + +msgid "sites" +msgstr "pagini" + +msgid "flat page" +msgstr "pagină statică" + +msgid "flat pages" +msgstr "pagini statice" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ru/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ru/LC_MESSAGES/django.mo new file mode 100644 index 0000000..669d7e1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ru/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ru/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ru/LC_MESSAGES/django.po new file mode 100644 index 0000000..bfe344c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ru/LC_MESSAGES/django.po @@ -0,0 +1,95 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Eugene , 2012 +# crazyzubr , 2020 +# Jannis Leidel , 2011 +# Mike Yumatov , 2011 +# Алексей Борискин , 2012,2014-2015,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-05-14 18:19+0000\n" +"Last-Translator: crazyzubr \n" +"Language-Team: Russian (http://www.transifex.com/django/django/language/" +"ru/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ru\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n" +"%100>=11 && n%100<=14)? 2 : 3);\n" + +msgid "Advanced options" +msgstr "Расширенные настройки" + +msgid "Flat Pages" +msgstr "Простые страницы" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Пример: “/about/contact/”. Убедитесь, что ввели начальную и конечную косые " +"черты." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Значение должно состоять только из букв, цифр и символов точки, " +"подчеркивания, тире, косой черты и тильды." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" +"Пример: “/about/contact”. Убедитесь, что в начале адреса находится косая " +"черта." + +msgid "URL is missing a leading slash." +msgstr "В начале URL отсутствует косая черта" + +msgid "URL is missing a trailing slash." +msgstr "В конце URL отсутствует косая черта" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Простая страница с адресом %(url)s уже существует для сайта %(site)s" + +msgid "title" +msgstr "заголовок" + +msgid "content" +msgstr "содержимое" + +msgid "enable comments" +msgstr "включить комментарии" + +msgid "template name" +msgstr "имя шаблона" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Пример: “flatpages/contact_page.html“. Если не указано, система будет " +"использовать “flatpages/default.html“." + +msgid "registration required" +msgstr "требуется регистрация" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "Если отмечено, только вошедшие пользователи смогут видеть страницу." + +msgid "sites" +msgstr "сайты" + +msgid "flat page" +msgstr "простая страница" + +msgid "flat pages" +msgstr "простые страницы" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e4b7636 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sk/LC_MESSAGES/django.po new file mode 100644 index 0000000..bcd4c8b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sk/LC_MESSAGES/django.po @@ -0,0 +1,92 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Marian Andre , 2011-2012,2014 +# Martin Tóth , 2017,2023 +# Peter Kuma, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2023-12-04 19:03+0000\n" +"Last-Translator: Martin Tóth , 2017,2023\n" +"Language-Team: Slovak (http://app.transifex.com/django/django/language/sk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n " +">= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);\n" + +msgid "Advanced options" +msgstr "Pokročilé nastavenia" + +msgid "Flat Pages" +msgstr "Statické stránky" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Príklad: „/about/contact/“. Zabezpečte, aby boli lomky na začiatku a na " +"konci." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Táto hodnota musí obsahovať len písmená, číslice, bodky, podčiarovníky, " +"pomlčky, lomky alebo vlnovky." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "Príklad: „/about/contact“. Zabezpečte, aby bola lomka na začiatku." + +msgid "URL is missing a leading slash." +msgstr "V URL chýba úvodná lomka." + +msgid "URL is missing a trailing slash." +msgstr "V URL chýba koncová lomka." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Statická stránka s url %(url)s pre sídlo %(site)s už existuje." + +msgid "title" +msgstr "názov" + +msgid "content" +msgstr "obsah" + +msgid "enable comments" +msgstr "povoliť komentáre" + +msgid "template name" +msgstr "názov šablóny" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Príklad: „flatpages/contact_page.html“. Ak nie je uvedené, systém použije " +"„flatpages/default.html“." + +msgid "registration required" +msgstr "nutná registrácia" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Ak je toto zaškrtnuté, na stránku budú mať prístup len prihlásení " +"používatelia." + +msgid "sites" +msgstr "sídla" + +msgid "flat page" +msgstr "statická stránka" + +msgid "flat pages" +msgstr "statické stránky" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4bae321 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sl/LC_MESSAGES/django.po new file mode 100644 index 0000000..af01899 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sl/LC_MESSAGES/django.po @@ -0,0 +1,93 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Andrej Marsetič, 2022 +# iElectric , 2011 +# Jannis Leidel , 2011 +# zejn , 2016 +# zejn , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2023-04-24 19:03+0000\n" +"Last-Translator: Andrej Marsetič, 2022\n" +"Language-Team: Slovenian (http://www.transifex.com/django/django/language/" +"sl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sl\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || " +"n%100==4 ? 2 : 3);\n" + +msgid "Advanced options" +msgstr "Napredne možnosti" + +msgid "Flat Pages" +msgstr "enostavne strani" + +msgid "URL" +msgstr "Naslov URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Primer: “/o-nas/kontakt/”. Prepričajte se, da imate začetne in končne " +"poševnice." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Vsebina lahko vsebuje samo črke, številke, pike, podčrtaje, poševnice, " +"črtice in tilde." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" +"Primer: “/o-nas/kontakt/”. Prepričajte se, da imate poševnico na začetku." + +msgid "URL is missing a leading slash." +msgstr "Na začetku naslov URL manjka poševnica." + +msgid "URL is missing a trailing slash." +msgstr "Na koncu naslova URL manjka poševnica." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Enostavna stran na naslovu %(url)s že obstaja na strani %(site)s" + +msgid "title" +msgstr "naslov" + +msgid "content" +msgstr "vsebina" + +msgid "enable comments" +msgstr "omogoči opombe" + +msgid "template name" +msgstr "ime predloge" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Primer: »flatpages/contact_page.html«. Če je to polje prazno, bo sistem " +"uporabil »flatpages/default.html«." + +msgid "registration required" +msgstr "zahtevana je registracija" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "Izbrana možnost omogoča ogled strani le prijavljenim uporabnikom." + +msgid "sites" +msgstr "strani" + +msgid "flat page" +msgstr "enostavna stran" + +msgid "flat pages" +msgstr "enostavne strani" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sq/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sq/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d404e6b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sq/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sq/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sq/LC_MESSAGES/django.po new file mode 100644 index 0000000..0f5aee0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sq/LC_MESSAGES/django.po @@ -0,0 +1,89 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Besnik , 2011,2015 +# Besnik , 2015,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-09-18 09:51+0000\n" +"Last-Translator: Besnik \n" +"Language-Team: Albanian (http://www.transifex.com/django/django/language/" +"sq/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sq\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Mundësi të mëtejshme" + +msgid "Flat Pages" +msgstr "Faqe të Thjeshta" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Shembull: “/rreth/kontakt/”. Sigurohuni që vendosni pjerraket përkatëse." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Kjo vlerë duhet të përmbajë vetëm shkronja, numra, pika, nënvija, vija " +"ndarëse, pjerrake ose shenjën afërsisht." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "Shembull: “/mbi/kontakt”. Sigurohuni që keni pjerrake paraprirëse." + +msgid "URL is missing a leading slash." +msgstr "URL-së i mungon një pjerrake në krye." + +msgid "URL is missing a trailing slash." +msgstr "URL-së i mungon një pjerrake në fund." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Ka tashmë një flatpage me url %(url)s për sajtin %(site)s" + +msgid "title" +msgstr "titull" + +msgid "content" +msgstr "lëndë" + +msgid "enable comments" +msgstr "aktivizo komente" + +msgid "template name" +msgstr "emër gjedheje" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Shembull: “flatpages/contact_page.html”. Nëse s’është dhënë një e tillë, " +"sistemi do të përdorë 'flatpages/default.html'." + +msgid "registration required" +msgstr "lypset regjistrim" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Po iu vu shenjë kësaj, faqen do të jenë në gjendje ta shohin vetëm " +"përdoruesit që kanë bërë hyrjen." + +msgid "sites" +msgstr "sajte" + +msgid "flat page" +msgstr "faqe e thjeshtë" + +msgid "flat pages" +msgstr "faqe të thjeshta" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f5b96db Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sr/LC_MESSAGES/django.po new file mode 100644 index 0000000..46cb525 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sr/LC_MESSAGES/django.po @@ -0,0 +1,92 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Branko Kokanovic , 2018 +# Igor Jerosimić, 2019-2020 +# Jannis Leidel , 2011 +# Janos Guljas , 2011-2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-01-21 20:41+0000\n" +"Last-Translator: Igor Jerosimić\n" +"Language-Team: Serbian (http://www.transifex.com/django/django/language/" +"sr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Advanced options" +msgstr "Напредна подешавања" + +msgid "Flat Pages" +msgstr "Флет странице" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Пример: \"/about/contact/\". Пазите на то да постоје почетне и завршне косе " +"црте." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Унета вредност може садржати само слова, бројке, тачке, доње црте, црте, " +"знаке разломка или тилде." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "Пример: '/about/contact/'. Пазите на то да постоји почетна коса црта." + +msgid "URL is missing a leading slash." +msgstr "Недостаје коса црта на почетку URL-а." + +msgid "URL is missing a trailing slash." +msgstr "Недостаје коса црта на крају URL-а." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Страница са адресом %(url)s већ постоји за сајт %(site)s" + +msgid "title" +msgstr "наслов" + +msgid "content" +msgstr "садржај" + +msgid "enable comments" +msgstr "омогући коментарисање" + +msgid "template name" +msgstr "назив темплејта" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Пример: \"flatpages/contact_page.html\". Ако ово оставите празним, систем ће " +"користити \"flatpages/default.html\"." + +msgid "registration required" +msgstr "потребна регистрација" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Ако је ово обележено, само ће пријављени корисници моћи да виде ову страницу." + +msgid "sites" +msgstr "сајтови" + +msgid "flat page" +msgstr "флет страница" + +msgid "flat pages" +msgstr "флет странице" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sr_Latn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sr_Latn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..733de55 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sr_Latn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sr_Latn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sr_Latn/LC_MESSAGES/django.po new file mode 100644 index 0000000..b059b29 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sr_Latn/LC_MESSAGES/django.po @@ -0,0 +1,93 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Igor Jerosimić, 2019-2020 +# Jannis Leidel , 2011 +# Janos Guljas , 2011-2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-01-21 20:48+0000\n" +"Last-Translator: Igor Jerosimić\n" +"Language-Team: Serbian (Latin) (http://www.transifex.com/django/django/" +"language/sr@latin/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr@latin\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Advanced options" +msgstr "Napredna podešavanja" + +msgid "Flat Pages" +msgstr "Flet stranice" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Primer: \"/about/contact/\". Pazite na to da postoje početne i završne kose " +"crte." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Uneta vrednost može sadržati samo slova, brojke, tačke, donje crte, crte, " +"znake razlomka ili tilde." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" +"Primer: \"/about/contact/\". Pazite na to da postoji početna kosa crta." + +msgid "URL is missing a leading slash." +msgstr "Nedostaje kosa crta na početku URL-a." + +msgid "URL is missing a trailing slash." +msgstr "Nedostaje kosa crta na kraju URL-a." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Stranica sa adresom %(url)s već postoji za sajt %(site)s" + +msgid "title" +msgstr "naslov" + +msgid "content" +msgstr "sadržaj" + +msgid "enable comments" +msgstr "omogući komentarisanje" + +msgid "template name" +msgstr "naziv templejta" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Primer: \"flatpages/contact_page.html\". Ako ovo ostavite praznim, sistem će " +"koristiti \"flatpages/contact_page.html\"." + +msgid "registration required" +msgstr "potrebna registracija" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Ako je ovo obeleženo, samo će prijavljeni korisnici moći da vide ovu " +"stranicu." + +msgid "sites" +msgstr "sajtovi" + +msgid "flat page" +msgstr "flet stranica" + +msgid "flat pages" +msgstr "flet stranice" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sv/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sv/LC_MESSAGES/django.mo new file mode 100644 index 0000000..483a758 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sv/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sv/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sv/LC_MESSAGES/django.po new file mode 100644 index 0000000..2e772d0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sv/LC_MESSAGES/django.po @@ -0,0 +1,92 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Albin Larsson , 2022 +# Andreas Pelme , 2011-2012 +# Jannis Leidel , 2011 +# Jonathan Lindén, 2014 +# Petter Strandmark , 2019 +# Thomas Lundqvist, 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2022-07-24 19:03+0000\n" +"Last-Translator: Albin Larsson \n" +"Language-Team: Swedish (http://www.transifex.com/django/django/language/" +"sv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sv\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Avancerade inställningar" + +msgid "Flat Pages" +msgstr "Statiska sidor" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Exempel: \"/om/kontakt/\". Se till att ha inledande och avslutande " +"snedstreck." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Detta värde får endast innehålla bokstäver, siffror, punkter, understreck, " +"bindestreck, snedstreck och tilde." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "Exempel: \"/om/kontakt/\". Se till att ett inledande snedstreck." + +msgid "URL is missing a leading slash." +msgstr "URL:en saknar ett inledande snedstreck." + +msgid "URL is missing a trailing slash." +msgstr "URL:en saknar ett avslutande snedstreck." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Statisk sida med %(url)s finns redan för webbplatsen %(site)s" + +msgid "title" +msgstr "titel" + +msgid "content" +msgstr "innehåll" + +msgid "enable comments" +msgstr "aktivera kommentarer" + +msgid "template name" +msgstr "mallnamn" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Exempel: 'sidor/kontaktsida.html'. Om detta inte fylls i kommer systemet att " +"använda 'flatpages/default.html'." + +msgid "registration required" +msgstr "registrering krävs" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "Om detta bockas för kommer endast inloggade användare kunna se sidan." + +msgid "sites" +msgstr "webbplatser" + +msgid "flat page" +msgstr "statisk sida" + +msgid "flat pages" +msgstr "statiska sidor" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sw/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sw/LC_MESSAGES/django.mo new file mode 100644 index 0000000..fcf11e5 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sw/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sw/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sw/LC_MESSAGES/django.po new file mode 100644 index 0000000..564ec06 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/sw/LC_MESSAGES/django.po @@ -0,0 +1,83 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Machaku , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Swahili (http://www.transifex.com/django/django/language/" +"sw/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sw\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Chaguzi za kiwango cha juu" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"Mfano: '/about/contact/'. Hakikisha unaweka mkwaju mwanzoni na mwishoni." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" + +msgid "URL is missing a leading slash." +msgstr "URL imekosa mkwaju mwishoni" + +msgid "URL is missing a trailing slash." +msgstr "URL imekosa mkwaju mwanzoni" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" + +msgid "title" +msgstr "kichwa" + +msgid "content" +msgstr "maudhui" + +msgid "enable comments" +msgstr "ruhusu maoni" + +msgid "template name" +msgstr "jina la templeti" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"Mfano: 'flatpages/contact_page.html'. Ikiwa hii haitaainishwa mfumo utatumia " +"'flatpages/default.html'." + +msgid "registration required" +msgstr "usajili unahitajika" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Ikiwa hii itatikiwa ni watumiaji waliosajiliwa tuu ndio watakaoweza kuuona " +"ukurasa huo" + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "" + +msgid "flat pages" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ta/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ta/LC_MESSAGES/django.mo new file mode 100644 index 0000000..bf8dadf Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ta/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ta/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ta/LC_MESSAGES/django.po new file mode 100644 index 0000000..ab745cd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ta/LC_MESSAGES/django.po @@ -0,0 +1,80 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Tamil (http://www.transifex.com/django/django/language/ta/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ta\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "உதாரணம்: '/about/contact/'. முன்னும் பின்னும் '/' உள்ளதை உறுதி செய்க." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" + +msgid "URL is missing a leading slash." +msgstr "" + +msgid "URL is missing a trailing slash." +msgstr "" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" + +msgid "title" +msgstr "தலைப்பு" + +msgid "content" +msgstr "பொருளடக்கம்" + +msgid "enable comments" +msgstr "விமர்சனங்களை செயலாக்கு" + +msgid "template name" +msgstr "வார்ப்புரு பெயர்" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"உதாரணம் 'flatpages/contact_page'. இது இல்லையெனில் 'flatpages/default' என்பதே " +"பயன்படுத்தப்படும்.ப்படும்." + +msgid "registration required" +msgstr "முன்பதிவு தேவை" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"இது தெரிவு செய்யப்பட்டிருந்தால், உள்நுழைந்த பயனர்கள் மட்டுமே இந்தப் பக்கத்தை பார்க்க முடியும்." + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "எளிய பக்கம்" + +msgid "flat pages" +msgstr "எளிய பக்கங்கள்" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/te/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/te/LC_MESSAGES/django.mo new file mode 100644 index 0000000..76d634c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/te/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/te/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/te/LC_MESSAGES/django.po new file mode 100644 index 0000000..0d38aae --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/te/LC_MESSAGES/django.po @@ -0,0 +1,79 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Telugu (http://www.transifex.com/django/django/language/te/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: te\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" + +msgid "URL is missing a leading slash." +msgstr "" + +msgid "URL is missing a trailing slash." +msgstr "" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" + +msgid "title" +msgstr "పట్టము" + +msgid "content" +msgstr "సూచన " + +msgid "enable comments" +msgstr "" + +msgid "template name" +msgstr "" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"ఉదాహరణ: 'flatpages/contact_page.html'.ఇది ఇవ్వకపోతే సిస్టం 'flatpages/default." +"html' ని వాడుకుంటడి" + +msgid "registration required" +msgstr "నమొదు చేయటము అవసరం" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "ఇది చెక్ చేసి ఉంటే కేవలం లాగ్గడ్ ఇన్ యూజర్లు పేజి చూడలేస్తారు" + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "" + +msgid "flat pages" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/tg/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/tg/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2ce72c0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/tg/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/tg/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/tg/LC_MESSAGES/django.po new file mode 100644 index 0000000..e0f76cc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/tg/LC_MESSAGES/django.po @@ -0,0 +1,86 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Surush Sufiew , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-05-15 00:29+0000\n" +"Last-Translator: Surush Sufiew \n" +"Language-Team: Tajik (http://www.transifex.com/django/django/language/tg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Танзимоти васеъ" + +msgid "Flat Pages" +msgstr "Саҳифаҳои муқарарӣ" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Қимат бояд танҳо аз ҳарф, рақам, ва аломатҳои нуқта, зерхат, дефис, слеш ва " +"зада иборат бошад." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" + +msgid "URL is missing a leading slash." +msgstr "Дар аввали URL слеш(/) мавҷуд нест" + +msgid "URL is missing a trailing slash." +msgstr "Дар охири URL слеш(/) мавҷуд нест" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" +"Саҳифаи муқарарӣ бо чунин суроға %(url)s барои сомонаи %(site)s алакай " +"мавҷуд аст." + +msgid "title" +msgstr "сархат" + +msgid "content" +msgstr "контент" + +msgid "enable comments" +msgstr "фаъолсозии 'андешаҳо'" + +msgid "template name" +msgstr "номи нусха" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" + +msgid "registration required" +msgstr "Бақайдгирӣ талаб карда мешавад" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Агар қайд шуда бошад, танҳо истифодабарандагони рухсатдор метавонанд аз " +"назар гузаронанд." + +msgid "sites" +msgstr "сомонаҳо" + +msgid "flat page" +msgstr "саҳифаи муқарарӣ" + +msgid "flat pages" +msgstr "саҳифаҳои муқарарӣ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/th/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/th/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f477c9b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/th/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/th/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/th/LC_MESSAGES/django.po new file mode 100644 index 0000000..be7808a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/th/LC_MESSAGES/django.po @@ -0,0 +1,80 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Kowit Charoenratchatabhan , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Kowit Charoenratchatabhan \n" +"Language-Team: Thai (http://www.transifex.com/django/django/language/th/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: th\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Advanced options" +msgstr "ตัวเลือกเพิ่มเติม" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "ตัวอย่าง: '/about/contact/'. ต้องแน่ใจว่าขึ้นต้นและลงท้ายด้วยเครื่องหมาย /" + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "ค่านี้จะต้องประกอบด้วยตัวอักษร, ตัวเลข, จุด, ขีดขีดกลาง, เครื่องหมาย / หรือตัวหนอน" + +msgid "URL is missing a leading slash." +msgstr "เครื่องหมาย \"/\" นำหน้า URL หายไป" + +msgid "URL is missing a trailing slash." +msgstr "เครื่องหมาย \"/\" ตามหลัง URL หายไป" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "หน้าเรียบชื่อ %(url)s ถูกใช้ไปแล้วสำหรับ %(site)s" + +msgid "title" +msgstr "หัวข้อ" + +msgid "content" +msgstr "เนื้อหา" + +msgid "enable comments" +msgstr "ใช้งานข้อติชม" + +msgid "template name" +msgstr "ชื่อเทมเพลต" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"ตัวอย่าง: 'flatpages/contact_page.html' ถ้าไม่ได้ถูกใช้ ระบบจะใช้ 'flatpages/default." +"html' " + +msgid "registration required" +msgstr "ต้องลงทะเบียนก่อน" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "ถ้าถูกเลือก ผู้ใช้ที่ลงทะเบียนเข้าสู่ระบบเท่านั้นที่จะสามารถดูหน้านี้" + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "หน้าเรียบ" + +msgid "flat pages" +msgstr "หน้าเรียบ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/tk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/tk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2248000 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/tk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/tk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/tk/LC_MESSAGES/django.po new file mode 100644 index 0000000..ba5baf3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/tk/LC_MESSAGES/django.po @@ -0,0 +1,83 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Welbeck Garli , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-07-15 16:35+0000\n" +"Last-Translator: Welbeck Garli \n" +"Language-Team: Turkmen (http://www.transifex.com/django/django/language/" +"tk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tk\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "Has çylşyrymly wariantlar" + +msgid "Flat Pages" +msgstr "Tekiz Sahypalar" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Meselem: \"about/contact/\". Dogry we yzygiderli çyzgylaryň bardygyna göz " +"ýetiriň." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" + +msgid "URL is missing a leading slash." +msgstr "" + +msgid "URL is missing a trailing slash." +msgstr "" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" + +msgid "title" +msgstr "" + +msgid "content" +msgstr "" + +msgid "enable comments" +msgstr "" + +msgid "template name" +msgstr "" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" + +msgid "registration required" +msgstr "" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "" + +msgid "flat pages" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/tr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/tr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..920fcc4 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/tr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/tr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/tr/LC_MESSAGES/django.po new file mode 100644 index 0000000..7ccae22 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/tr/LC_MESSAGES/django.po @@ -0,0 +1,94 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# BouRock, 2015,2019 +# BouRock, 2014 +# Jannis Leidel , 2011 +# Metin Amiroff , 2011 +# Murat Çorlu , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-09-17 08:28+0000\n" +"Last-Translator: BouRock\n" +"Language-Team: Turkish (http://www.transifex.com/django/django/language/" +"tr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Advanced options" +msgstr "Gelişmiş seçenekler" + +msgid "Flat Pages" +msgstr "Düz Sayfalar" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Örnek: “/hakkinda/iletisim/”. Başında ve sonunda bölü işareti olduğundan " +"emin olun." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Bu değer sadece harfler, sayılar, noktalar, altçizgiler, tireler, bölme veya " +"yaklaşık işaretleri içermek zorundadır." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" +"Örnek: “/hakkinda/iletisim”. Başında bölü işareti olduğundan emin olun." + +msgid "URL is missing a leading slash." +msgstr "URL başında bölü işareti eksik." + +msgid "URL is missing a trailing slash." +msgstr "URL sonunda bölü işareti eksik." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "%(url)s adresli düz sayfa %(site)s sitesinde zaten mevcut" + +msgid "title" +msgstr "başlık" + +msgid "content" +msgstr "içerik" + +msgid "enable comments" +msgstr "yorumları etkinleştir" + +msgid "template name" +msgstr "şablon adı" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Örnek: “flatpages/contact_page.html”. Eğer bu şekilde yazılmazsa, sistem " +"“flatpages/default.html” olarak kullanacak." + +msgid "registration required" +msgstr "kayıt olma gerekli" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Eğer bu işaretlenirse, sadece oturum açan kullanıcılar sayfayı " +"görüntüleyebilecektir." + +msgid "sites" +msgstr "siteler" + +msgid "flat page" +msgstr "düz sayfa" + +msgid "flat pages" +msgstr "düz sayfalar" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/tt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/tt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..038f647 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/tt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/tt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/tt/LC_MESSAGES/django.po new file mode 100644 index 0000000..0754d68 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/tt/LC_MESSAGES/django.po @@ -0,0 +1,84 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Azat Khasanshin , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Tatar (http://www.transifex.com/django/django/language/tt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tt\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Advanced options" +msgstr "Өстәмә көйләүләр" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"Үрнәк: '/about/contact/'. Алдынгы һәм арттагы авыш сызыкларын кертүне " +"тикшерегез." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Бу кыйммәт тик хәрефләрдән, саннардан һәм нокта, астына сызу, тире, авыш " +"сызык, тильда билгеләреннән генә тора ала." + +msgid "URL is missing a leading slash." +msgstr "" + +msgid "URL is missing a trailing slash." +msgstr "" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" + +msgid "title" +msgstr "башлам" + +msgid "content" +msgstr "эчтәлек" + +msgid "enable comments" +msgstr "фикерләрне ялгарга" + +msgid "template name" +msgstr "шаблон исеме" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"Үрнәк: 'flatpages/contact_page.html'. Күрсәтелгән булмаса, система " +"'flatpages/defalut.html' кулланыр." + +msgid "registration required" +msgstr "теркәлү кирәк" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Билгеләнгән булса, фәкать кергән кулланучылар гына сәхифәне күрә алырлар." + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "гади сәхифә" + +msgid "flat pages" +msgstr "гади сәхифәләр" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/udm/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/udm/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4613a37 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/udm/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/udm/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/udm/LC_MESSAGES/django.po new file mode 100644 index 0000000..45fb893 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/udm/LC_MESSAGES/django.po @@ -0,0 +1,77 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Udmurt (http://www.transifex.com/django/django/language/" +"udm/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: udm\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Advanced options" +msgstr "" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" + +msgid "URL is missing a leading slash." +msgstr "" + +msgid "URL is missing a trailing slash." +msgstr "" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" + +msgid "title" +msgstr "" + +msgid "content" +msgstr "" + +msgid "enable comments" +msgstr "" + +msgid "template name" +msgstr "" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" + +msgid "registration required" +msgstr "" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "" + +msgid "flat pages" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ug/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ug/LC_MESSAGES/django.mo new file mode 100644 index 0000000..422f871 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ug/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ug/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ug/LC_MESSAGES/django.po new file mode 100644 index 0000000..c4a1e71 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ug/LC_MESSAGES/django.po @@ -0,0 +1,85 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Azat, 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2023-12-04 19:03+0000\n" +"Last-Translator: Azat, 2023\n" +"Language-Team: Uyghur (http://app.transifex.com/django/django/language/ug/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ug\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "ئالىي تاللانما" + +msgid "Flat Pages" +msgstr "تەكشى بەتلەر" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"مىسال: “/about/contact/”. باش قىسمى ۋە ئاخىر قىسمىدا سىزىق بولۇشى كېرەك." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"بۇ قىممەت پەقەت ھەرپلەر، سانلار، نۇقتىلار، ئاستى سىزىقلار، سىزىقلار، يانتۇ " +"سىزىقلار ياكى تىلدىلاردىن تۈزۈلگەن بولۇشى كېرەك." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "مىسال: “/about/contact”. باش قىسمىدا سىزىق بولۇشى كېرەك." + +msgid "URL is missing a leading slash." +msgstr "URL نىڭ باش قىسمىدا سىزىق يوق." + +msgid "URL is missing a trailing slash." +msgstr "URL نىڭ ئاخىر قىسمىدا سىزىق يوق." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "%(site)s تور بېكىتى ئۈچۈن %(url)ss URL ئادرېسلىق تەك بەت مەۋجۇت." + +msgid "title" +msgstr "ماۋزۇ" + +msgid "content" +msgstr "مەزمۇن" + +msgid "enable comments" +msgstr "ئىنكاسلارنى قوزغىتىڭ" + +msgid "template name" +msgstr "قېلىپ ئاتى" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"مىسال: “flatpages/contact_page.html”. ئەگەر بۇ تەمىنلەنمىسە، سىستېما " +"“flatpages/default.html” نى ئىشلىتىدۇ." + +msgid "registration required" +msgstr "تىزىملىتىش زۆرۈر" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "ئەگەر بۇ تاللانسا، پەقەت كىرگەن ئىشلەتكۈچىلەر بەتنى كۆرەلەيدۇ." + +msgid "sites" +msgstr "بېكەتلەر" + +msgid "flat page" +msgstr "تەكشى بەت" + +msgid "flat pages" +msgstr "تەكشى بەتلەر" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/uk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/uk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..72d6b06 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/uk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/uk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/uk/LC_MESSAGES/django.po new file mode 100644 index 0000000..8ba1e76 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/uk/LC_MESSAGES/django.po @@ -0,0 +1,99 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Oleksandr Chernihov , 2014 +# Illia Volochii , 2021 +# Jannis Leidel , 2011 +# Panasoft, 2016 +# Sergey Lysach , 2011-2012 +# tarasyyyk , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2021-01-20 00:29+0000\n" +"Last-Translator: Illia Volochii \n" +"Language-Team: Ukrainian (http://www.transifex.com/django/django/language/" +"uk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: uk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != " +"11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % " +"100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || " +"(n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n" + +msgid "Advanced options" +msgstr "Додаткові опції" + +msgid "Flat Pages" +msgstr "Прості сторінки" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "" +"Наприклад, “/about/contact/”. Переконайтеся у наявності скісної риски на " +"початку та вкінці." + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"Це значення повинне містити тільки літери, цифри, крапки, підкреслення, " +"тире, косі риси чи тільди." + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "" +"Наприклад, “/about/contact/”. Переконайтеся у наявності скісної риски на " +"початку." + +msgid "URL is missing a leading slash." +msgstr "На початку URL відсутня коса риса." + +msgid "URL is missing a trailing slash." +msgstr "В кінці URL відсутня коса риса." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "Проста сторінка з адресою %(url)s вже існує для сайту %(site)s" + +msgid "title" +msgstr "заголовок" + +msgid "content" +msgstr "зміст" + +msgid "enable comments" +msgstr "увімкнути коментарі" + +msgid "template name" +msgstr "ім'я шаблона" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"Наприклад, “/about/contact/”. Якщо не вказано, система використовуватиме " +"“flatpages/default.html”." + +msgid "registration required" +msgstr "потрібна реєстрація" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Якщо тут є галочка, тільки користувачі, що увійшли, зможуть переглядати цю " +"сторінку." + +msgid "sites" +msgstr "сайти" + +msgid "flat page" +msgstr "проста сторінка" + +msgid "flat pages" +msgstr "прості сторінки" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ur/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ur/LC_MESSAGES/django.mo new file mode 100644 index 0000000..dfb3755 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ur/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ur/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ur/LC_MESSAGES/django.po new file mode 100644 index 0000000..73d30d3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/ur/LC_MESSAGES/django.po @@ -0,0 +1,84 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Mansoorulhaq Mansoor , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Urdu (http://www.transifex.com/django/django/language/ur/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ur\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Advanced options" +msgstr "اعلٰی اختیارات" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "یو آر ایل (URL(" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" +"مثال: '/about/contact/'۔ یقین کر لیں کہ سابقہ اور لاحقہ سلیش موجود ھے۔" + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"اس قیمت (ویلیو) کا صرف حروف، نمبروں، نقاط، انڈرسکور، ڈیش، سلیش، یا ٹائلڈ پر " +"مشتمل ھونا ضروری ھے۔" + +msgid "URL is missing a leading slash." +msgstr "" + +msgid "URL is missing a trailing slash." +msgstr "" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" + +msgid "title" +msgstr "عنوان" + +msgid "content" +msgstr "مضمون" + +msgid "enable comments" +msgstr "تبصرے فعال کریں" + +msgid "template name" +msgstr "قالب کا نام" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" +"مثال: 'flatpages/contact_page.html'۔ اگر یہ مھیا نھیں کیا گیا تو سسٹم " +"'flatpages/default.html' استعمال کرے گا۔" + +msgid "registration required" +msgstr "رجسٹریشن ضروری ھے" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"اگر یہ فعال ھے تو صرف اندر آئے ھوئے (logged-in) صارفین یہ صفحہ دیکھنے کے " +"قابل ھوں گے۔" + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "ھموار صفحہ" + +msgid "flat pages" +msgstr "ھموار صفحے" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/vi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/vi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..cbee5e4 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/vi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/vi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/vi/LC_MESSAGES/django.po new file mode 100644 index 0000000..9caf553 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/vi/LC_MESSAGES/django.po @@ -0,0 +1,82 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# toi ta , 2016 +# Tran , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: toi ta \n" +"Language-Team: Vietnamese (http://www.transifex.com/django/django/language/" +"vi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: vi\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Advanced options" +msgstr "Các tùy chọn nâng cao" + +msgid "Flat Pages" +msgstr "" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "" + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" + +msgid "URL is missing a leading slash." +msgstr "" + +msgid "URL is missing a trailing slash." +msgstr "" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "" + +msgid "title" +msgstr "tiêu đề" + +msgid "content" +msgstr "nội dung" + +msgid "enable comments" +msgstr "mở bình luận" + +msgid "template name" +msgstr "tên thiết kế" + +msgid "" +"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " +"will use 'flatpages/default.html'." +msgstr "" + +msgid "registration required" +msgstr "Bạn cần phải cần đăng kí" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "" +"Nếu bạn đánh dấu vào đây, chỉ những tài khoản đã đăng nhập mới có thể xem " +"được trang này." + +msgid "sites" +msgstr "" + +msgid "flat page" +msgstr "" + +msgid "flat pages" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/zh_Hans/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/zh_Hans/LC_MESSAGES/django.mo new file mode 100644 index 0000000..58e3c9e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/zh_Hans/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/zh_Hans/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/zh_Hans/LC_MESSAGES/django.po new file mode 100644 index 0000000..a1e058b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/zh_Hans/LC_MESSAGES/django.po @@ -0,0 +1,89 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Lele Long , 2011 +# mozillazg , 2016 +# Ronald White , 2014 +# Suntravel Chris , 2019 +# wolf ice , 2020 +# Kevin Sze , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-03-04 04:05+0000\n" +"Last-Translator: wolf ice \n" +"Language-Team: Chinese (China) (http://www.transifex.com/django/django/" +"language/zh_CN/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_CN\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Advanced options" +msgstr "高级选项" + +msgid "Flat Pages" +msgstr "简单页面" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "例如:“/about/contact/”。确保有开头和结尾的斜杠。" + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "该值必须只能包含字母,数字,点号,下划线,破折号,和" + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "例如:“/about/contact”。确保有一个开头的斜杠。" + +msgid "URL is missing a leading slash." +msgstr "URL头部缺失斜线." + +msgid "URL is missing a trailing slash." +msgstr "URL尾部缺失斜线." + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "带有url %(url)s的Flatpage已经存在于站点 %(site)s" + +msgid "title" +msgstr "标题" + +msgid "content" +msgstr "内容" + +msgid "enable comments" +msgstr "允许评论" + +msgid "template name" +msgstr "模板名称" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"例如:“flatpages/contact_page.html”。如果它未被提供,系统将使用“flatpages/" +"default.html”。" + +msgid "registration required" +msgstr "请先注册" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "如果被选中,仅登录用户才可以查看此页。" + +msgid "sites" +msgstr "站点" + +msgid "flat page" +msgstr "简单页面" + +msgid "flat pages" +msgstr "简单页面" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/zh_Hant/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/zh_Hant/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8a1653e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/zh_Hant/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/zh_Hant/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/zh_Hant/LC_MESSAGES/django.po new file mode 100644 index 0000000..cc55578 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/locale/zh_Hant/LC_MESSAGES/django.po @@ -0,0 +1,87 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# ilay , 2012 +# Jannis Leidel , 2011 +# 619e61dbdb61c57213f62815aaf60e01, 2011 +# Tzu-ping Chung , 2016,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-09-18 09:03+0000\n" +"Last-Translator: Tzu-ping Chung \n" +"Language-Team: Chinese (Taiwan) (http://www.transifex.com/django/django/" +"language/zh_TW/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_TW\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Advanced options" +msgstr "進階選項" + +msgid "Flat Pages" +msgstr "簡平頁面" + +msgid "URL" +msgstr "URL" + +msgid "" +"Example: “/about/contact/”. Make sure to have leading and trailing slashes." +msgstr "例如:「/about/contact/」。注意必須包含開頭與結束的斜線。" + +msgid "" +"This value must contain only letters, numbers, dots, underscores, dashes, " +"slashes or tildes." +msgstr "" +"此欄位只能有: 英文字母、數字、點(.)、底線(_)、刪節號(-)、斜線(/)、波浪號(~)。" + +msgid "Example: “/about/contact”. Make sure to have a leading slash." +msgstr "例如:「/about/contact」。注意必須包含開頭的斜線。" + +msgid "URL is missing a leading slash." +msgstr "URL 缺少前導的斜線。" + +msgid "URL is missing a trailing slash." +msgstr "URL 缺少一個斜線。" + +#, python-format +msgid "Flatpage with url %(url)s already exists for site %(site)s" +msgstr "網站 %(site)s 已經存在一個浮動頁面,其位址為 %(url)s。" + +msgid "title" +msgstr "標題" + +msgid "content" +msgstr "內容" + +msgid "enable comments" +msgstr "啟用評論" + +msgid "template name" +msgstr "模板名稱" + +msgid "" +"Example: “flatpages/contact_page.html”. If this isn’t provided, the system " +"will use “flatpages/default.html”." +msgstr "" +"例如:「flatpages/contact_page.html」。若不提供,系統會使用「flatpages/" +"default.html」。" + +msgid "registration required" +msgstr "請先註冊" + +msgid "If this is checked, only logged-in users will be able to view the page." +msgstr "如果此項被選取,則只有登入的使用者可以檢視頁面。" + +msgid "sites" +msgstr "網站" + +msgid "flat page" +msgstr "簡平頁面" + +msgid "flat pages" +msgstr "簡平頁面" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/middleware.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/middleware.py new file mode 100644 index 0000000..9c6a727 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/middleware.py @@ -0,0 +1,20 @@ +from django.conf import settings +from django.contrib.flatpages.views import flatpage +from django.http import Http404 +from django.utils.deprecation import MiddlewareMixin + + +class FlatpageFallbackMiddleware(MiddlewareMixin): + def process_response(self, request, response): + if response.status_code != 404: + return response # No need to check for a flatpage for non-404 responses. + try: + return flatpage(request, request.path_info) + # Return the original response if any errors happened. Because this + # is a middleware, we can't assume the errors will be caught elsewhere. + except Http404: + return response + except Exception: + if settings.DEBUG: + raise + return response diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/migrations/0001_initial.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/migrations/0001_initial.py new file mode 100644 index 0000000..db95098 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/migrations/0001_initial.py @@ -0,0 +1,68 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("sites", "0001_initial"), + ] + + operations = [ + migrations.CreateModel( + name="FlatPage", + fields=[ + ( + "id", + models.AutoField( + verbose_name="ID", + serialize=False, + auto_created=True, + primary_key=True, + ), + ), + ( + "url", + models.CharField(max_length=100, verbose_name="URL", db_index=True), + ), + ("title", models.CharField(max_length=200, verbose_name="title")), + ("content", models.TextField(verbose_name="content", blank=True)), + ( + "enable_comments", + models.BooleanField(default=False, verbose_name="enable comments"), + ), + ( + "template_name", + models.CharField( + help_text=( + "Example: “flatpages/contact_page.html”. If this isn’t " + "provided, the system will use “flatpages/default.html”." + ), + max_length=70, + verbose_name="template name", + blank=True, + ), + ), + ( + "registration_required", + models.BooleanField( + default=False, + help_text=( + "If this is checked, only logged-in users will be able to " + "view the page." + ), + verbose_name="registration required", + ), + ), + ( + "sites", + models.ManyToManyField(to="sites.Site", verbose_name="sites"), + ), + ], + options={ + "ordering": ["url"], + "db_table": "django_flatpage", + "verbose_name": "flat page", + "verbose_name_plural": "flat pages", + }, + bases=(models.Model,), + ), + ] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/migrations/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/models.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/models.py new file mode 100644 index 0000000..d001cd1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/models.py @@ -0,0 +1,49 @@ +from django.contrib.sites.models import Site +from django.db import models +from django.urls import NoReverseMatch, get_script_prefix, reverse +from django.utils.encoding import iri_to_uri +from django.utils.translation import gettext_lazy as _ + + +class FlatPage(models.Model): + url = models.CharField(_("URL"), max_length=100, db_index=True) + title = models.CharField(_("title"), max_length=200) + content = models.TextField(_("content"), blank=True) + enable_comments = models.BooleanField(_("enable comments"), default=False) + template_name = models.CharField( + _("template name"), + max_length=70, + blank=True, + help_text=_( + "Example: “flatpages/contact_page.html”. If this isn’t provided, " + "the system will use “flatpages/default.html”." + ), + ) + registration_required = models.BooleanField( + _("registration required"), + help_text=_( + "If this is checked, only logged-in users will be able to view the page." + ), + default=False, + ) + sites = models.ManyToManyField(Site, verbose_name=_("sites")) + + class Meta: + db_table = "django_flatpage" + verbose_name = _("flat page") + verbose_name_plural = _("flat pages") + ordering = ["url"] + + def __str__(self): + return "%s -- %s" % (self.url, self.title) + + def get_absolute_url(self): + from .views import flatpage + + for url in (self.url.lstrip("/"), self.url): + try: + return reverse(flatpage, kwargs={"url": url}) + except NoReverseMatch: + pass + # Handle script prefix manually because we bypass reverse() + return iri_to_uri(get_script_prefix().rstrip("/") + self.url) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/sitemaps.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/sitemaps.py new file mode 100644 index 0000000..405507c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/sitemaps.py @@ -0,0 +1,14 @@ +from django.apps import apps as django_apps +from django.contrib.sitemaps import Sitemap +from django.core.exceptions import ImproperlyConfigured + + +class FlatPageSitemap(Sitemap): + def items(self): + if not django_apps.is_installed("django.contrib.sites"): + raise ImproperlyConfigured( + "FlatPageSitemap requires django.contrib.sites, which isn't installed." + ) + Site = django_apps.get_model("sites.Site") + current_site = Site.objects.get_current() + return current_site.flatpage_set.filter(registration_required=False) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/templatetags/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/templatetags/flatpages.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/templatetags/flatpages.py new file mode 100644 index 0000000..9ec6b88 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/templatetags/flatpages.py @@ -0,0 +1,101 @@ +from django import template +from django.conf import settings +from django.contrib.flatpages.models import FlatPage +from django.contrib.sites.shortcuts import get_current_site + +register = template.Library() + + +class FlatpageNode(template.Node): + def __init__(self, context_name, starts_with=None, user=None): + self.context_name = context_name + if starts_with: + self.starts_with = template.Variable(starts_with) + else: + self.starts_with = None + if user: + self.user = template.Variable(user) + else: + self.user = None + + def render(self, context): + if "request" in context: + site_pk = get_current_site(context["request"]).pk + else: + site_pk = settings.SITE_ID + flatpages = FlatPage.objects.filter(sites__id=site_pk) + # If a prefix was specified, add a filter + if self.starts_with: + flatpages = flatpages.filter( + url__startswith=self.starts_with.resolve(context) + ) + + # If the provided user is not authenticated, or no user + # was provided, filter the list to only public flatpages. + if self.user: + user = self.user.resolve(context) + if not user.is_authenticated: + flatpages = flatpages.filter(registration_required=False) + else: + flatpages = flatpages.filter(registration_required=False) + + context[self.context_name] = flatpages + return "" + + +@register.tag +def get_flatpages(parser, token): + """ + Retrieve all flatpage objects available for the current site and + visible to the specific user (or visible to all users if no user is + specified). Populate the template context with them in a variable + whose name is defined by the ``as`` clause. + + An optional ``for`` clause controls the user whose permissions are used in + determining which flatpages are visible. + + An optional argument, ``starts_with``, limits the returned flatpages to + those beginning with a particular base URL. This argument can be a variable + or a string, as it resolves from the template context. + + Syntax:: + + {% get_flatpages ['url_starts_with'] [for user] as context_name %} + + Example usage:: + + {% get_flatpages as flatpages %} + {% get_flatpages for someuser as flatpages %} + {% get_flatpages '/about/' as about_pages %} + {% get_flatpages prefix as about_pages %} + {% get_flatpages '/about/' for someuser as about_pages %} + """ + bits = token.split_contents() + syntax_message = ( + "%(tag_name)s expects a syntax of %(tag_name)s " + "['url_starts_with'] [for user] as context_name" % {"tag_name": bits[0]} + ) + # Must have at 3-6 bits in the tag + if 3 <= len(bits) <= 6: + # If there's an even number of bits, there's no prefix + if len(bits) % 2 == 0: + prefix = bits[1] + else: + prefix = None + + # The very last bit must be the context name + if bits[-2] != "as": + raise template.TemplateSyntaxError(syntax_message) + context_name = bits[-1] + + # If there are 5 or 6 bits, there is a user defined + if len(bits) >= 5: + if bits[-4] != "for": + raise template.TemplateSyntaxError(syntax_message) + user = bits[-3] + else: + user = None + + return FlatpageNode(context_name, starts_with=prefix, user=user) + else: + raise template.TemplateSyntaxError(syntax_message) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/urls.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/urls.py new file mode 100644 index 0000000..d4480b3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/urls.py @@ -0,0 +1,6 @@ +from django.contrib.flatpages import views +from django.urls import path + +urlpatterns = [ + path("", views.flatpage, name="django.contrib.flatpages.views.flatpage"), +] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/views.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/views.py new file mode 100644 index 0000000..776f179 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/flatpages/views.py @@ -0,0 +1,70 @@ +from django.conf import settings +from django.contrib.flatpages.models import FlatPage +from django.contrib.sites.shortcuts import get_current_site +from django.http import Http404, HttpResponse, HttpResponsePermanentRedirect +from django.shortcuts import get_object_or_404 +from django.template import loader +from django.utils.safestring import mark_safe +from django.views.decorators.csrf import csrf_protect + +DEFAULT_TEMPLATE = "flatpages/default.html" + +# This view is called from FlatpageFallbackMiddleware.process_response +# when a 404 is raised, which often means CsrfViewMiddleware.process_view +# has not been called even if CsrfViewMiddleware is installed. So we need +# to use @csrf_protect, in case the template needs {% csrf_token %}. +# However, we can't just wrap this view; if no matching flatpage exists, +# or a redirect is required for authentication, the 404 needs to be returned +# without any CSRF checks. Therefore, we only +# CSRF protect the internal implementation. + + +def flatpage(request, url): + """ + Public interface to the flat page view. + + Models: `flatpages.flatpages` + Templates: Uses the template defined by the ``template_name`` field, + or :template:`flatpages/default.html` if template_name is not defined. + Context: + flatpage + `flatpages.flatpages` object + """ + if not url.startswith("/"): + url = "/" + url + site_id = get_current_site(request).id + try: + f = get_object_or_404(FlatPage, url=url, sites=site_id) + except Http404: + if not url.endswith("/") and settings.APPEND_SLASH: + url += "/" + f = get_object_or_404(FlatPage, url=url, sites=site_id) + return HttpResponsePermanentRedirect("%s/" % request.path) + else: + raise + return render_flatpage(request, f) + + +@csrf_protect +def render_flatpage(request, f): + """ + Internal interface to the flat page view. + """ + # If registration is required for accessing this page, and the user isn't + # logged in, redirect to the login page. + if f.registration_required and not request.user.is_authenticated: + from django.contrib.auth.views import redirect_to_login + + return redirect_to_login(request.path) + if f.template_name: + template = loader.select_template((f.template_name, DEFAULT_TEMPLATE)) + else: + template = loader.get_template(DEFAULT_TEMPLATE) + + # To avoid having to always use the "|safe" filter in flatpage templates, + # mark the title and content as already safe (since they are raw HTML + # content in the first place). + f.title = mark_safe(f.title) + f.content = mark_safe(f.content) + + return HttpResponse(template.render({"flatpage": f}, request)) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/apps.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/apps.py new file mode 100644 index 0000000..6282501 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/apps.py @@ -0,0 +1,14 @@ +from django.apps import AppConfig +from django.core import serializers +from django.utils.translation import gettext_lazy as _ + + +class GISConfig(AppConfig): + default_auto_field = "django.db.models.AutoField" + name = "django.contrib.gis" + verbose_name = _("GIS") + + def ready(self): + serializers.BUILTIN_SERIALIZERS.setdefault( + "geojson", "django.contrib.gis.serializers.geojson" + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/base/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/base/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/base/adapter.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/base/adapter.py new file mode 100644 index 0000000..b472e3a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/base/adapter.py @@ -0,0 +1,26 @@ +class WKTAdapter: + """ + An adaptor for Geometries sent to the MySQL and Oracle database backends. + """ + + def __init__(self, geom): + self.wkt = geom.wkt + self.srid = geom.srid + + def __eq__(self, other): + return ( + isinstance(other, WKTAdapter) + and self.wkt == other.wkt + and self.srid == other.srid + ) + + def __hash__(self): + return hash((self.wkt, self.srid)) + + def __str__(self): + return self.wkt + + @classmethod + def _fix_polygon(cls, poly): + # Hook for Oracle. + return poly diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/base/features.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/base/features.py new file mode 100644 index 0000000..cc4ce10 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/base/features.py @@ -0,0 +1,111 @@ +import re + +from django.contrib.gis.db import models + + +class BaseSpatialFeatures: + gis_enabled = True + + # Does the database contain a SpatialRefSys model to store SRID information? + has_spatialrefsys_table = True + + # Does the backend support the django.contrib.gis.utils.add_srs_entry() utility? + supports_add_srs_entry = True + # Does the backend introspect GeometryField to its subtypes? + supports_geometry_field_introspection = True + + # Does the database have a geography type? + supports_geography = False + # Does the backend support storing 3D geometries? + supports_3d_storage = False + # Reference implementation of 3D functions is: + # https://postgis.net/docs/PostGIS_Special_Functions_Index.html#PostGIS_3D_Functions + supports_3d_functions = False + # Does the database support SRID transform operations? + supports_transform = True + # Can geometry fields be null? + supports_null_geometries = True + # Are empty geometries supported? + supports_empty_geometries = False + # Can the function be applied on geodetic coordinate systems? + supports_distance_geodetic = True + supports_length_geodetic = True + supports_perimeter_geodetic = False + supports_area_geodetic = True + # Is the database able to count vertices on polygons (with `num_points`)? + supports_num_points_poly = True + + # Does the backend support expressions for specifying distance in the + # dwithin lookup? + supports_dwithin_distance_expr = True + + # Does the database have raster support? + supports_raster = False + + # Does the database support a unique index on geometry fields? + supports_geometry_field_unique_index = True + + # Can SchemaEditor alter geometry fields? + can_alter_geometry_field = True + + # Do the database functions/aggregates support the tolerance parameter? + supports_tolerance_parameter = False + + # Set of options that AsGeoJSON() doesn't support. + unsupported_geojson_options = {} + + # Does Intersection() return None (rather than an empty GeometryCollection) + # for empty results? + empty_intersection_returns_none = True + + @property + def supports_bbcontains_lookup(self): + return "bbcontains" in self.connection.ops.gis_operators + + @property + def supports_contained_lookup(self): + return "contained" in self.connection.ops.gis_operators + + @property + def supports_crosses_lookup(self): + return "crosses" in self.connection.ops.gis_operators + + @property + def supports_distances_lookups(self): + return self.has_Distance_function + + @property + def supports_dwithin_lookup(self): + return "dwithin" in self.connection.ops.gis_operators + + @property + def supports_relate_lookup(self): + return "relate" in self.connection.ops.gis_operators + + @property + def supports_isvalid_lookup(self): + return self.has_IsValid_function + + # Is the aggregate supported by the database? + @property + def supports_collect_aggr(self): + return models.Collect not in self.connection.ops.disallowed_aggregates + + @property + def supports_extent_aggr(self): + return models.Extent not in self.connection.ops.disallowed_aggregates + + @property + def supports_make_line_aggr(self): + return models.MakeLine not in self.connection.ops.disallowed_aggregates + + @property + def supports_union_aggr(self): + return models.Union not in self.connection.ops.disallowed_aggregates + + def __getattr__(self, name): + m = re.match(r"has_(\w*)_function$", name) + if m: + func_name = m[1] + return func_name not in self.connection.ops.unsupported_functions + raise AttributeError diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/base/models.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/base/models.py new file mode 100644 index 0000000..589c872 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/base/models.py @@ -0,0 +1,140 @@ +from django.contrib.gis import gdal + + +class SpatialRefSysMixin: + """ + The SpatialRefSysMixin is a class used by the database-dependent + SpatialRefSys objects to reduce redundant code. + """ + + @property + def srs(self): + """ + Return a GDAL SpatialReference object. + """ + # TODO: Is caching really necessary here? Is complexity worth it? + if hasattr(self, "_srs"): + # Returning a clone of the cached SpatialReference object. + return self._srs.clone() + else: + # Attempting to cache a SpatialReference object. + + # Trying to get from WKT first. + try: + self._srs = gdal.SpatialReference(self.wkt) + return self.srs + except Exception as e: + msg = e + + try: + self._srs = gdal.SpatialReference(self.proj4text) + return self.srs + except Exception as e: + msg = e + + raise Exception( + "Could not get OSR SpatialReference from WKT: %s\nError:\n%s" + % (self.wkt, msg) + ) + + @property + def ellipsoid(self): + """ + Return a tuple of the ellipsoid parameters: + (semimajor axis, semiminor axis, and inverse flattening). + """ + return self.srs.ellipsoid + + @property + def name(self): + "Return the projection name." + return self.srs.name + + @property + def spheroid(self): + "Return the spheroid name for this spatial reference." + return self.srs["spheroid"] + + @property + def datum(self): + "Return the datum for this spatial reference." + return self.srs["datum"] + + @property + def projected(self): + "Is this Spatial Reference projected?" + return self.srs.projected + + @property + def local(self): + "Is this Spatial Reference local?" + return self.srs.local + + @property + def geographic(self): + "Is this Spatial Reference geographic?" + return self.srs.geographic + + @property + def linear_name(self): + "Return the linear units name." + return self.srs.linear_name + + @property + def linear_units(self): + "Return the linear units." + return self.srs.linear_units + + @property + def angular_name(self): + "Return the name of the angular units." + return self.srs.angular_name + + @property + def angular_units(self): + "Return the angular units." + return self.srs.angular_units + + @property + def units(self): + "Return a tuple of the units and the name." + if self.projected or self.local: + return (self.linear_units, self.linear_name) + elif self.geographic: + return (self.angular_units, self.angular_name) + else: + return (None, None) + + @classmethod + def get_units(cls, wkt): + """ + Return a tuple of (unit_value, unit_name) for the given WKT without + using any of the database fields. + """ + return gdal.SpatialReference(wkt).units + + @classmethod + def get_spheroid(cls, wkt, string=True): + """ + Class method used by GeometryField on initialization to + retrieve the `SPHEROID[..]` parameters from the given WKT. + """ + srs = gdal.SpatialReference(wkt) + sphere_params = srs.ellipsoid + sphere_name = srs["spheroid"] + + if not string: + return sphere_name, sphere_params + else: + # `string` parameter used to place in format acceptable by PostGIS + if len(sphere_params) == 3: + radius, flattening = sphere_params[0], sphere_params[2] + else: + radius, flattening = sphere_params + return 'SPHEROID["%s",%s,%s]' % (sphere_name, radius, flattening) + + def __str__(self): + """ + Return the string representation, a 'pretty' OGC WKT. + """ + return str(self.srs) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/base/operations.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/base/operations.py new file mode 100644 index 0000000..fafdf60 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/base/operations.py @@ -0,0 +1,210 @@ +from django.contrib.gis.db.models import GeometryField +from django.contrib.gis.db.models.functions import Distance +from django.contrib.gis.measure import Area as AreaMeasure +from django.contrib.gis.measure import Distance as DistanceMeasure +from django.db import NotSupportedError +from django.utils.functional import cached_property + + +class BaseSpatialOperations: + # Quick booleans for the type of this spatial backend, and + # an attribute for the spatial database version tuple (if applicable) + postgis = False + spatialite = False + mariadb = False + mysql = False + oracle = False + spatial_version = None + + # How the geometry column should be selected. + select = "%s" + + @cached_property + def select_extent(self): + return self.select + + # Aggregates + disallowed_aggregates = () + + geom_func_prefix = "" + + # Mapping between Django function names and backend names, when names do not + # match; used in spatial_function_name(). + function_names = {} + + # Set of known unsupported functions of the backend + unsupported_functions = { + "Area", + "AsGeoJSON", + "AsGML", + "AsKML", + "AsSVG", + "Azimuth", + "BoundingCircle", + "Centroid", + "ClosestPoint", + "Difference", + "Distance", + "Envelope", + "FromWKB", + "FromWKT", + "GeoHash", + "GeometryDistance", + "Intersection", + "IsEmpty", + "IsValid", + "Length", + "LineLocatePoint", + "MakeValid", + "MemSize", + "NumGeometries", + "NumPoints", + "Perimeter", + "PointOnSurface", + "Reverse", + "Scale", + "SnapToGrid", + "SymDifference", + "Transform", + "Translate", + "Union", + } + + # Constructors + from_text = False + + # Default conversion functions for aggregates; will be overridden if implemented + # for the spatial backend. + def convert_extent(self, box, srid): + raise NotImplementedError( + "Aggregate extent not implemented for this spatial backend." + ) + + def convert_extent3d(self, box, srid): + raise NotImplementedError( + "Aggregate 3D extent not implemented for this spatial backend." + ) + + # For quoting column values, rather than columns. + def geo_quote_name(self, name): + return "'%s'" % name + + # GeometryField operations + def geo_db_type(self, f): + """ + Return the database column type for the geometry field on + the spatial backend. + """ + raise NotImplementedError( + "subclasses of BaseSpatialOperations must provide a geo_db_type() method" + ) + + def get_distance(self, f, value, lookup_type): + """ + Return the distance parameters for the given geometry field, + lookup value, and lookup type. + """ + raise NotImplementedError( + "Distance operations not available on this spatial backend." + ) + + def get_geom_placeholder(self, f, value, compiler): + """ + Return the placeholder for the given geometry field with the given + value. Depending on the spatial backend, the placeholder may contain a + stored procedure call to the transformation function of the spatial + backend. + """ + + def transform_value(value, field): + return value is not None and value.srid != field.srid + + if hasattr(value, "as_sql"): + return ( + "%s(%%s, %s)" % (self.spatial_function_name("Transform"), f.srid) + if transform_value(value.output_field, f) + else "%s" + ) + if transform_value(value, f): + # Add Transform() to the SQL placeholder. + return "%s(%s(%%s,%s), %s)" % ( + self.spatial_function_name("Transform"), + self.from_text, + value.srid, + f.srid, + ) + elif self.connection.features.has_spatialrefsys_table: + return "%s(%%s,%s)" % (self.from_text, f.srid) + else: + # For backwards compatibility on MySQL (#27464). + return "%s(%%s)" % self.from_text + + def check_expression_support(self, expression): + if isinstance(expression, self.disallowed_aggregates): + raise NotSupportedError( + "%s spatial aggregation is not supported by this database backend." + % expression.name + ) + super().check_expression_support(expression) + + def spatial_aggregate_name(self, agg_name): + raise NotImplementedError( + "Aggregate support not implemented for this spatial backend." + ) + + def spatial_function_name(self, func_name): + if func_name in self.unsupported_functions: + raise NotSupportedError( + "This backend doesn't support the %s function." % func_name + ) + return self.function_names.get(func_name, self.geom_func_prefix + func_name) + + # Routines for getting the OGC-compliant models. + def geometry_columns(self): + raise NotImplementedError( + "Subclasses of BaseSpatialOperations must provide a geometry_columns() " + "method." + ) + + def spatial_ref_sys(self): + raise NotImplementedError( + "subclasses of BaseSpatialOperations must a provide spatial_ref_sys() " + "method" + ) + + distance_expr_for_lookup = staticmethod(Distance) + + def get_db_converters(self, expression): + converters = super().get_db_converters(expression) + if isinstance(expression.output_field, GeometryField): + converters.append(self.get_geometry_converter(expression)) + return converters + + def get_geometry_converter(self, expression): + raise NotImplementedError( + "Subclasses of BaseSpatialOperations must provide a " + "get_geometry_converter() method." + ) + + def get_area_att_for_field(self, field): + if field.geodetic(self.connection): + if self.connection.features.supports_area_geodetic: + return "sq_m" + raise NotImplementedError( + "Area on geodetic coordinate systems not supported." + ) + else: + units_name = field.units_name(self.connection) + if units_name: + return AreaMeasure.unit_attname(units_name) + + def get_distance_att_for_field(self, field): + dist_att = None + if field.geodetic(self.connection): + if self.connection.features.supports_distance_geodetic: + dist_att = "m" + else: + units = field.units_name(self.connection) + if units: + dist_att = DistanceMeasure.unit_attname(units) + return dist_att diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/mysql/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/mysql/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/mysql/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/mysql/base.py new file mode 100644 index 0000000..4abc052 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/mysql/base.py @@ -0,0 +1,14 @@ +from django.db.backends.mysql.base import DatabaseWrapper as MySQLDatabaseWrapper + +from .features import DatabaseFeatures +from .introspection import MySQLIntrospection +from .operations import MySQLOperations +from .schema import MySQLGISSchemaEditor + + +class DatabaseWrapper(MySQLDatabaseWrapper): + SchemaEditorClass = MySQLGISSchemaEditor + # Classes instantiated in __init__(). + features_class = DatabaseFeatures + introspection_class = MySQLIntrospection + ops_class = MySQLOperations diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/mysql/features.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/mysql/features.py new file mode 100644 index 0000000..cd99420 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/mysql/features.py @@ -0,0 +1,21 @@ +from django.contrib.gis.db.backends.base.features import BaseSpatialFeatures +from django.db.backends.mysql.features import DatabaseFeatures as MySQLDatabaseFeatures +from django.utils.functional import cached_property + + +class DatabaseFeatures(BaseSpatialFeatures, MySQLDatabaseFeatures): + empty_intersection_returns_none = False + has_spatialrefsys_table = False + supports_add_srs_entry = False + supports_distance_geodetic = False + supports_length_geodetic = False + supports_area_geodetic = False + supports_transform = False + supports_null_geometries = False + supports_num_points_poly = False + unsupported_geojson_options = {"crs"} + + @cached_property + def supports_geometry_field_unique_index(self): + # Not supported in MySQL since https://dev.mysql.com/worklog/task/?id=11808 + return self.connection.mysql_is_mariadb diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/mysql/introspection.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/mysql/introspection.py new file mode 100644 index 0000000..4d6aea7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/mysql/introspection.py @@ -0,0 +1,33 @@ +from MySQLdb.constants import FIELD_TYPE + +from django.contrib.gis.gdal import OGRGeomType +from django.db.backends.mysql.introspection import DatabaseIntrospection + + +class MySQLIntrospection(DatabaseIntrospection): + # Updating the data_types_reverse dictionary with the appropriate + # type for Geometry fields. + data_types_reverse = DatabaseIntrospection.data_types_reverse.copy() + data_types_reverse[FIELD_TYPE.GEOMETRY] = "GeometryField" + + def get_geometry_type(self, table_name, description): + with self.connection.cursor() as cursor: + # In order to get the specific geometry type of the field, + # we introspect on the table definition using `DESCRIBE`. + cursor.execute("DESCRIBE %s" % self.connection.ops.quote_name(table_name)) + # Increment over description info until we get to the geometry + # column. + for column, typ, null, key, default, extra in cursor.fetchall(): + if column == description.name: + # Using OGRGeomType to convert from OGC name to Django field. + # MySQL does not support 3D or SRIDs, so the field params + # are empty. + field_type = OGRGeomType(typ).django + field_params = {} + break + return field_type, field_params + + def supports_spatial_index(self, cursor, table_name): + # Supported with MyISAM, Aria, or InnoDB. + storage_engine = self.get_storage_engine(cursor, table_name) + return storage_engine in ("MyISAM", "Aria", "InnoDB") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/mysql/operations.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/mysql/operations.py new file mode 100644 index 0000000..886db60 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/mysql/operations.py @@ -0,0 +1,130 @@ +from django.contrib.gis.db import models +from django.contrib.gis.db.backends.base.adapter import WKTAdapter +from django.contrib.gis.db.backends.base.operations import BaseSpatialOperations +from django.contrib.gis.db.backends.utils import SpatialOperator +from django.contrib.gis.geos.geometry import GEOSGeometryBase +from django.contrib.gis.geos.prototypes.io import wkb_r +from django.contrib.gis.measure import Distance +from django.db.backends.mysql.operations import DatabaseOperations +from django.utils.functional import cached_property + + +class MySQLOperations(BaseSpatialOperations, DatabaseOperations): + name = "mysql" + geom_func_prefix = "ST_" + + Adapter = WKTAdapter + + @cached_property + def mariadb(self): + return self.connection.mysql_is_mariadb + + @cached_property + def mysql(self): + return not self.connection.mysql_is_mariadb + + @cached_property + def select(self): + return self.geom_func_prefix + "AsBinary(%s)" + + @cached_property + def from_text(self): + return self.geom_func_prefix + "GeomFromText" + + @cached_property + def gis_operators(self): + operators = { + "bbcontains": SpatialOperator( + func="MBRContains" + ), # For consistency w/PostGIS API + "bboverlaps": SpatialOperator(func="MBROverlaps"), # ... + "contained": SpatialOperator(func="MBRWithin"), # ... + "contains": SpatialOperator(func="ST_Contains"), + "crosses": SpatialOperator(func="ST_Crosses"), + "disjoint": SpatialOperator(func="ST_Disjoint"), + "equals": SpatialOperator(func="ST_Equals"), + "exact": SpatialOperator(func="ST_Equals"), + "intersects": SpatialOperator(func="ST_Intersects"), + "overlaps": SpatialOperator(func="ST_Overlaps"), + "same_as": SpatialOperator(func="ST_Equals"), + "touches": SpatialOperator(func="ST_Touches"), + "within": SpatialOperator(func="ST_Within"), + } + if self.connection.mysql_is_mariadb: + operators["relate"] = SpatialOperator(func="ST_Relate") + return operators + + disallowed_aggregates = ( + models.Collect, + models.Extent, + models.Extent3D, + models.MakeLine, + models.Union, + ) + + function_names = { + "FromWKB": "ST_GeomFromWKB", + "FromWKT": "ST_GeomFromText", + } + + @cached_property + def unsupported_functions(self): + unsupported = { + "AsGML", + "AsKML", + "AsSVG", + "Azimuth", + "BoundingCircle", + "ClosestPoint", + "ForcePolygonCW", + "GeometryDistance", + "IsEmpty", + "LineLocatePoint", + "MakeValid", + "MemSize", + "Perimeter", + "PointOnSurface", + "Reverse", + "Scale", + "SnapToGrid", + "Transform", + "Translate", + } + if self.connection.mysql_is_mariadb: + unsupported.remove("PointOnSurface") + unsupported.update({"GeoHash", "IsValid"}) + return unsupported + + def geo_db_type(self, f): + return f.geom_type + + def get_distance(self, f, value, lookup_type): + value = value[0] + if isinstance(value, Distance): + if f.geodetic(self.connection): + raise ValueError( + "Only numeric values of degree units are allowed on " + "geodetic distance queries." + ) + dist_param = getattr( + value, Distance.unit_attname(f.units_name(self.connection)) + ) + else: + dist_param = value + return [dist_param] + + def get_geometry_converter(self, expression): + read = wkb_r().read + srid = expression.output_field.srid + if srid == -1: + srid = None + geom_class = expression.output_field.geom_class + + def converter(value, expression, connection): + if value is not None: + geom = GEOSGeometryBase(read(memoryview(value)), geom_class) + if srid: + geom.srid = srid + return geom + + return converter diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/mysql/schema.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/mysql/schema.py new file mode 100644 index 0000000..1c9fe0e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/mysql/schema.py @@ -0,0 +1,87 @@ +import logging + +from django.contrib.gis.db.models import GeometryField +from django.db import OperationalError +from django.db.backends.mysql.schema import DatabaseSchemaEditor + +logger = logging.getLogger("django.contrib.gis") + + +class MySQLGISSchemaEditor(DatabaseSchemaEditor): + sql_add_spatial_index = "CREATE SPATIAL INDEX %(index)s ON %(table)s(%(column)s)" + sql_drop_spatial_index = "DROP INDEX %(index)s ON %(table)s" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.geometry_sql = [] + + def skip_default(self, field): + # Geometry fields are stored as BLOB/TEXT, for which MySQL < 8.0.13 + # doesn't support defaults. + if ( + isinstance(field, GeometryField) + and not self._supports_limited_data_type_defaults + ): + return True + return super().skip_default(field) + + def quote_value(self, value): + if isinstance(value, self.connection.ops.Adapter): + return super().quote_value(str(value)) + return super().quote_value(value) + + def column_sql(self, model, field, include_default=False): + column_sql = super().column_sql(model, field, include_default) + # MySQL doesn't support spatial indexes on NULL columns + if isinstance(field, GeometryField) and field.spatial_index and not field.null: + qn = self.connection.ops.quote_name + db_table = model._meta.db_table + self.geometry_sql.append( + self.sql_add_spatial_index + % { + "index": qn(self._create_spatial_index_name(model, field)), + "table": qn(db_table), + "column": qn(field.column), + } + ) + return column_sql + + def create_model(self, model): + super().create_model(model) + self.create_spatial_indexes() + + def add_field(self, model, field): + super().add_field(model, field) + self.create_spatial_indexes() + + def remove_field(self, model, field): + if isinstance(field, GeometryField) and field.spatial_index: + qn = self.connection.ops.quote_name + sql = self.sql_drop_spatial_index % { + "index": qn(self._create_spatial_index_name(model, field)), + "table": qn(model._meta.db_table), + } + try: + self.execute(sql) + except OperationalError: + logger.error( + "Couldn't remove spatial index: %s (may be expected " + "if your storage engine doesn't support them).", + sql, + ) + + super().remove_field(model, field) + + def _create_spatial_index_name(self, model, field): + return "%s_%s_id" % (model._meta.db_table, field.column) + + def create_spatial_indexes(self): + for sql in self.geometry_sql: + try: + self.execute(sql) + except OperationalError: + logger.error( + f"Cannot create SPATIAL INDEX {sql}. Only MyISAM, Aria, and InnoDB " + f"support them.", + ) + self.geometry_sql = [] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/oracle/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/oracle/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/oracle/adapter.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/oracle/adapter.py new file mode 100644 index 0000000..0bf1164 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/oracle/adapter.py @@ -0,0 +1,61 @@ +from django.contrib.gis.db.backends.base.adapter import WKTAdapter +from django.contrib.gis.geos import GeometryCollection, Polygon +from django.db.backends.oracle.oracledb_any import oracledb + + +class OracleSpatialAdapter(WKTAdapter): + input_size = oracledb.CLOB + + def __init__(self, geom): + """ + Oracle requires that polygon rings are in proper orientation. This + affects spatial operations and an invalid orientation may cause + failures. Correct orientations are: + * Outer ring - counter clockwise + * Inner ring(s) - clockwise + """ + if isinstance(geom, Polygon): + if self._polygon_must_be_fixed(geom): + geom = self._fix_polygon(geom) + elif isinstance(geom, GeometryCollection): + if any( + isinstance(g, Polygon) and self._polygon_must_be_fixed(g) for g in geom + ): + geom = self._fix_geometry_collection(geom) + + self.wkt = geom.wkt + self.srid = geom.srid + + @staticmethod + def _polygon_must_be_fixed(poly): + return not poly.empty and ( + not poly.exterior_ring.is_counterclockwise + or any(x.is_counterclockwise for x in poly) + ) + + @classmethod + def _fix_polygon(cls, poly, clone=True): + """Fix single polygon orientation as described in __init__().""" + if clone: + poly = poly.clone() + + if not poly.exterior_ring.is_counterclockwise: + poly.exterior_ring = list(reversed(poly.exterior_ring)) + + for i in range(1, len(poly)): + if poly[i].is_counterclockwise: + poly[i] = list(reversed(poly[i])) + + return poly + + @classmethod + def _fix_geometry_collection(cls, coll): + """ + Fix polygon orientations in geometry collections as described in + __init__(). + """ + coll = coll.clone() + for i, geom in enumerate(coll): + if isinstance(geom, Polygon): + coll[i] = cls._fix_polygon(geom, clone=False) + return coll diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/oracle/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/oracle/base.py new file mode 100644 index 0000000..d43516a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/oracle/base.py @@ -0,0 +1,14 @@ +from django.db.backends.oracle.base import DatabaseWrapper as OracleDatabaseWrapper + +from .features import DatabaseFeatures +from .introspection import OracleIntrospection +from .operations import OracleOperations +from .schema import OracleGISSchemaEditor + + +class DatabaseWrapper(OracleDatabaseWrapper): + SchemaEditorClass = OracleGISSchemaEditor + # Classes instantiated in __init__(). + features_class = DatabaseFeatures + introspection_class = OracleIntrospection + ops_class = OracleOperations diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/oracle/features.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/oracle/features.py new file mode 100644 index 0000000..f346d93 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/oracle/features.py @@ -0,0 +1,28 @@ +from django.contrib.gis.db.backends.base.features import BaseSpatialFeatures +from django.db.backends.oracle.features import ( + DatabaseFeatures as OracleDatabaseFeatures, +) +from django.utils.functional import cached_property + + +class DatabaseFeatures(BaseSpatialFeatures, OracleDatabaseFeatures): + supports_add_srs_entry = False + supports_geometry_field_introspection = False + supports_geometry_field_unique_index = False + supports_perimeter_geodetic = True + supports_dwithin_distance_expr = False + supports_tolerance_parameter = True + unsupported_geojson_options = {"bbox", "crs", "precision"} + + @cached_property + def django_test_skips(self): + skips = super().django_test_skips + skips.update( + { + "Oracle doesn't support spatial operators in constraints.": { + "gis_tests.gis_migrations.test_operations.OperationTests." + "test_add_check_constraint", + }, + } + ) + return skips diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/oracle/introspection.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/oracle/introspection.py new file mode 100644 index 0000000..bf299b1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/oracle/introspection.py @@ -0,0 +1,46 @@ +from django.db.backends.oracle.introspection import DatabaseIntrospection +from django.db.backends.oracle.oracledb_any import oracledb +from django.utils.functional import cached_property + + +class OracleIntrospection(DatabaseIntrospection): + # Associating any OBJECTVAR instances with GeometryField. This won't work + # right on Oracle objects that aren't MDSYS.SDO_GEOMETRY, but it is the + # only object type supported within Django anyways. + @cached_property + def data_types_reverse(self): + return { + **super().data_types_reverse, + oracledb.DB_TYPE_OBJECT: "GeometryField", + } + + def get_geometry_type(self, table_name, description): + with self.connection.cursor() as cursor: + # Querying USER_SDO_GEOM_METADATA to get the SRID and dimension information. + try: + cursor.execute( + 'SELECT "DIMINFO", "SRID" FROM "USER_SDO_GEOM_METADATA" ' + 'WHERE "TABLE_NAME"=%s AND "COLUMN_NAME"=%s', + (table_name.upper(), description.name.upper()), + ) + row = cursor.fetchone() + except Exception as exc: + raise Exception( + "Could not find entry in USER_SDO_GEOM_METADATA " + 'corresponding to "%s"."%s"' % (table_name, description.name) + ) from exc + + # TODO: Research way to find a more specific geometry field type for + # the column's contents. + field_type = "GeometryField" + + # Getting the field parameters. + field_params = {} + dim, srid = row + if srid != 4326: + field_params["srid"] = srid + # Size of object array (SDO_DIM_ARRAY) is number of dimensions. + dim = dim.size() + if dim != 2: + field_params["dim"] = dim + return field_type, field_params diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/oracle/models.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/oracle/models.py new file mode 100644 index 0000000..f06f731 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/oracle/models.py @@ -0,0 +1,64 @@ +""" + The GeometryColumns and SpatialRefSys models for the Oracle spatial + backend. + + It should be noted that Oracle Spatial does not have database tables + named according to the OGC standard, so the closest analogs are used. + For example, the `USER_SDO_GEOM_METADATA` is used for the GeometryColumns + model and the `SDO_COORD_REF_SYS` is used for the SpatialRefSys model. +""" +from django.contrib.gis.db import models +from django.contrib.gis.db.backends.base.models import SpatialRefSysMixin + + +class OracleGeometryColumns(models.Model): + "Maps to the Oracle USER_SDO_GEOM_METADATA table." + table_name = models.CharField(max_length=32) + column_name = models.CharField(max_length=1024) + srid = models.IntegerField(primary_key=True) + # TODO: Add support for `diminfo` column (type MDSYS.SDO_DIM_ARRAY). + + class Meta: + app_label = "gis" + db_table = "USER_SDO_GEOM_METADATA" + managed = False + + def __str__(self): + return "%s - %s (SRID: %s)" % (self.table_name, self.column_name, self.srid) + + @classmethod + def table_name_col(cls): + """ + Return the name of the metadata column used to store the feature table + name. + """ + return "table_name" + + @classmethod + def geom_col_name(cls): + """ + Return the name of the metadata column used to store the feature + geometry column. + """ + return "column_name" + + +class OracleSpatialRefSys(models.Model, SpatialRefSysMixin): + "Maps to the Oracle MDSYS.CS_SRS table." + cs_name = models.CharField(max_length=68) + srid = models.IntegerField(primary_key=True) + auth_srid = models.IntegerField() + auth_name = models.CharField(max_length=256) + wktext = models.CharField(max_length=2046) + # Optional geometry representing the bounds of this coordinate + # system. By default, all are NULL in the table. + cs_bounds = models.PolygonField(null=True) + + class Meta: + app_label = "gis" + db_table = "CS_SRS" + managed = False + + @property + def wkt(self): + return self.wktext diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/oracle/operations.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/oracle/operations.py new file mode 100644 index 0000000..ed86985 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/oracle/operations.py @@ -0,0 +1,246 @@ +""" + This module contains the spatial lookup types, and the `get_geo_where_clause` + routine for Oracle Spatial. + + Please note that WKT support is broken on the XE version, and thus + this backend will not work on such platforms. Specifically, XE lacks + support for an internal JVM, and Java libraries are required to use + the WKT constructors. +""" +import re + +from django.contrib.gis.db import models +from django.contrib.gis.db.backends.base.operations import BaseSpatialOperations +from django.contrib.gis.db.backends.oracle.adapter import OracleSpatialAdapter +from django.contrib.gis.db.backends.utils import SpatialOperator +from django.contrib.gis.geos.geometry import GEOSGeometry, GEOSGeometryBase +from django.contrib.gis.geos.prototypes.io import wkb_r +from django.contrib.gis.measure import Distance +from django.db.backends.oracle.operations import DatabaseOperations + +DEFAULT_TOLERANCE = "0.05" + + +class SDOOperator(SpatialOperator): + sql_template = "%(func)s(%(lhs)s, %(rhs)s) = 'TRUE'" + + +class SDODWithin(SpatialOperator): + sql_template = "SDO_WITHIN_DISTANCE(%(lhs)s, %(rhs)s, %%s) = 'TRUE'" + + +class SDODisjoint(SpatialOperator): + sql_template = ( + "SDO_GEOM.RELATE(%%(lhs)s, 'DISJOINT', %%(rhs)s, %s) = 'DISJOINT'" + % DEFAULT_TOLERANCE + ) + + +class SDORelate(SpatialOperator): + sql_template = "SDO_RELATE(%(lhs)s, %(rhs)s, 'mask=%(mask)s') = 'TRUE'" + + def check_relate_argument(self, arg): + masks = ( + "TOUCH|OVERLAPBDYDISJOINT|OVERLAPBDYINTERSECT|EQUAL|INSIDE|COVEREDBY|" + "CONTAINS|COVERS|ANYINTERACT|ON" + ) + mask_regex = re.compile(r"^(%s)(\+(%s))*$" % (masks, masks), re.I) + if not isinstance(arg, str) or not mask_regex.match(arg): + raise ValueError('Invalid SDO_RELATE mask: "%s"' % arg) + + def as_sql(self, connection, lookup, template_params, sql_params): + template_params["mask"] = sql_params[-1] + return super().as_sql(connection, lookup, template_params, sql_params[:-1]) + + +class OracleOperations(BaseSpatialOperations, DatabaseOperations): + name = "oracle" + oracle = True + disallowed_aggregates = (models.Collect, models.Extent3D, models.MakeLine) + + Adapter = OracleSpatialAdapter + + extent = "SDO_AGGR_MBR" + unionagg = "SDO_AGGR_UNION" + + from_text = "SDO_GEOMETRY" + + function_names = { + "Area": "SDO_GEOM.SDO_AREA", + "AsGeoJSON": "SDO_UTIL.TO_GEOJSON", + "AsWKB": "SDO_UTIL.TO_WKBGEOMETRY", + "AsWKT": "SDO_UTIL.TO_WKTGEOMETRY", + "BoundingCircle": "SDO_GEOM.SDO_MBC", + "Centroid": "SDO_GEOM.SDO_CENTROID", + "Difference": "SDO_GEOM.SDO_DIFFERENCE", + "Distance": "SDO_GEOM.SDO_DISTANCE", + "Envelope": "SDO_GEOM_MBR", + "FromWKB": "SDO_UTIL.FROM_WKBGEOMETRY", + "FromWKT": "SDO_UTIL.FROM_WKTGEOMETRY", + "Intersection": "SDO_GEOM.SDO_INTERSECTION", + "IsValid": "SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT", + "Length": "SDO_GEOM.SDO_LENGTH", + "NumGeometries": "SDO_UTIL.GETNUMELEM", + "NumPoints": "SDO_UTIL.GETNUMVERTICES", + "Perimeter": "SDO_GEOM.SDO_LENGTH", + "PointOnSurface": "SDO_GEOM.SDO_POINTONSURFACE", + "Reverse": "SDO_UTIL.REVERSE_LINESTRING", + "SymDifference": "SDO_GEOM.SDO_XOR", + "Transform": "SDO_CS.TRANSFORM", + "Union": "SDO_GEOM.SDO_UNION", + } + + # We want to get SDO Geometries as WKT because it is much easier to + # instantiate GEOS proxies from WKT than SDO_GEOMETRY(...) strings. + # However, this adversely affects performance (i.e., Java is called + # to convert to WKT on every query). If someone wishes to write a + # SDO_GEOMETRY(...) parser in Python, let me know =) + select = "SDO_UTIL.TO_WKBGEOMETRY(%s)" + + gis_operators = { + "contains": SDOOperator(func="SDO_CONTAINS"), + "coveredby": SDOOperator(func="SDO_COVEREDBY"), + "covers": SDOOperator(func="SDO_COVERS"), + "disjoint": SDODisjoint(), + "intersects": SDOOperator( + func="SDO_OVERLAPBDYINTERSECT" + ), # TODO: Is this really the same as ST_Intersects()? + "equals": SDOOperator(func="SDO_EQUAL"), + "exact": SDOOperator(func="SDO_EQUAL"), + "overlaps": SDOOperator(func="SDO_OVERLAPS"), + "same_as": SDOOperator(func="SDO_EQUAL"), + # Oracle uses a different syntax, e.g., 'mask=inside+touch' + "relate": SDORelate(), + "touches": SDOOperator(func="SDO_TOUCH"), + "within": SDOOperator(func="SDO_INSIDE"), + "dwithin": SDODWithin(), + } + + unsupported_functions = { + "AsKML", + "AsSVG", + "Azimuth", + "ClosestPoint", + "ForcePolygonCW", + "GeoHash", + "GeometryDistance", + "IsEmpty", + "LineLocatePoint", + "MakeValid", + "MemSize", + "Scale", + "SnapToGrid", + "Translate", + } + + def geo_quote_name(self, name): + return super().geo_quote_name(name).upper() + + def convert_extent(self, clob): + if clob: + # Generally, Oracle returns a polygon for the extent -- however, + # it can return a single point if there's only one Point in the + # table. + ext_geom = GEOSGeometry(memoryview(clob.read())) + gtype = str(ext_geom.geom_type) + if gtype == "Polygon": + # Construct the 4-tuple from the coordinates in the polygon. + shell = ext_geom.shell + ll, ur = shell[0][:2], shell[2][:2] + elif gtype == "Point": + ll = ext_geom.coords[:2] + ur = ll + else: + raise Exception( + "Unexpected geometry type returned for extent: %s" % gtype + ) + xmin, ymin = ll + xmax, ymax = ur + return (xmin, ymin, xmax, ymax) + else: + return None + + def geo_db_type(self, f): + """ + Return the geometry database type for Oracle. Unlike other spatial + backends, no stored procedure is necessary and it's the same for all + geometry types. + """ + return "MDSYS.SDO_GEOMETRY" + + def get_distance(self, f, value, lookup_type): + """ + Return the distance parameters given the value and the lookup type. + On Oracle, geometry columns with a geodetic coordinate system behave + implicitly like a geography column, and thus meters will be used as + the distance parameter on them. + """ + if not value: + return [] + value = value[0] + if isinstance(value, Distance): + if f.geodetic(self.connection): + dist_param = value.m + else: + dist_param = getattr( + value, Distance.unit_attname(f.units_name(self.connection)) + ) + else: + dist_param = value + + # dwithin lookups on Oracle require a special string parameter + # that starts with "distance=". + if lookup_type == "dwithin": + dist_param = "distance=%s" % dist_param + + return [dist_param] + + def get_geom_placeholder(self, f, value, compiler): + if value is None: + return "NULL" + return super().get_geom_placeholder(f, value, compiler) + + def spatial_aggregate_name(self, agg_name): + """ + Return the spatial aggregate SQL name. + """ + agg_name = "unionagg" if agg_name.lower() == "union" else agg_name.lower() + return getattr(self, agg_name) + + # Routines for getting the OGC-compliant models. + def geometry_columns(self): + from django.contrib.gis.db.backends.oracle.models import OracleGeometryColumns + + return OracleGeometryColumns + + def spatial_ref_sys(self): + from django.contrib.gis.db.backends.oracle.models import OracleSpatialRefSys + + return OracleSpatialRefSys + + def modify_insert_params(self, placeholder, params): + """Drop out insert parameters for NULL placeholder. Needed for Oracle Spatial + backend due to #10888. + """ + if placeholder == "NULL": + return [] + return super().modify_insert_params(placeholder, params) + + def get_geometry_converter(self, expression): + read = wkb_r().read + srid = expression.output_field.srid + if srid == -1: + srid = None + geom_class = expression.output_field.geom_class + + def converter(value, expression, connection): + if value is not None: + geom = GEOSGeometryBase(read(memoryview(value.read())), geom_class) + if srid: + geom.srid = srid + return geom + + return converter + + def get_area_att_for_field(self, field): + return "sq_m" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/oracle/schema.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/oracle/schema.py new file mode 100644 index 0000000..c9192d0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/oracle/schema.py @@ -0,0 +1,121 @@ +from django.contrib.gis.db.models import GeometryField +from django.db.backends.oracle.schema import DatabaseSchemaEditor +from django.db.backends.utils import strip_quotes, truncate_name + + +class OracleGISSchemaEditor(DatabaseSchemaEditor): + sql_add_geometry_metadata = """ + INSERT INTO USER_SDO_GEOM_METADATA + ("TABLE_NAME", "COLUMN_NAME", "DIMINFO", "SRID") + VALUES ( + %(table)s, + %(column)s, + MDSYS.SDO_DIM_ARRAY( + MDSYS.SDO_DIM_ELEMENT('LONG', %(dim0)s, %(dim2)s, %(tolerance)s), + MDSYS.SDO_DIM_ELEMENT('LAT', %(dim1)s, %(dim3)s, %(tolerance)s) + ), + %(srid)s + )""" + sql_add_spatial_index = ( + "CREATE INDEX %(index)s ON %(table)s(%(column)s) " + "INDEXTYPE IS MDSYS.SPATIAL_INDEX" + ) + sql_drop_spatial_index = "DROP INDEX %(index)s" + sql_clear_geometry_table_metadata = ( + "DELETE FROM USER_SDO_GEOM_METADATA WHERE TABLE_NAME = %(table)s" + ) + sql_clear_geometry_field_metadata = ( + "DELETE FROM USER_SDO_GEOM_METADATA WHERE TABLE_NAME = %(table)s " + "AND COLUMN_NAME = %(column)s" + ) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.geometry_sql = [] + + def geo_quote_name(self, name): + return self.connection.ops.geo_quote_name(name) + + def quote_value(self, value): + if isinstance(value, self.connection.ops.Adapter): + return super().quote_value(str(value)) + return super().quote_value(value) + + def column_sql(self, model, field, include_default=False): + column_sql = super().column_sql(model, field, include_default) + if isinstance(field, GeometryField): + db_table = model._meta.db_table + self.geometry_sql.append( + self.sql_add_geometry_metadata + % { + "table": self.geo_quote_name(db_table), + "column": self.geo_quote_name(field.column), + "dim0": field._extent[0], + "dim1": field._extent[1], + "dim2": field._extent[2], + "dim3": field._extent[3], + "tolerance": field._tolerance, + "srid": field.srid, + } + ) + if field.spatial_index: + self.geometry_sql.append( + self.sql_add_spatial_index + % { + "index": self.quote_name( + self._create_spatial_index_name(model, field) + ), + "table": self.quote_name(db_table), + "column": self.quote_name(field.column), + } + ) + return column_sql + + def create_model(self, model): + super().create_model(model) + self.run_geometry_sql() + + def delete_model(self, model): + super().delete_model(model) + self.execute( + self.sql_clear_geometry_table_metadata + % { + "table": self.geo_quote_name(model._meta.db_table), + } + ) + + def add_field(self, model, field): + super().add_field(model, field) + self.run_geometry_sql() + + def remove_field(self, model, field): + if isinstance(field, GeometryField): + self.execute( + self.sql_clear_geometry_field_metadata + % { + "table": self.geo_quote_name(model._meta.db_table), + "column": self.geo_quote_name(field.column), + } + ) + if field.spatial_index: + self.execute( + self.sql_drop_spatial_index + % { + "index": self.quote_name( + self._create_spatial_index_name(model, field) + ), + } + ) + super().remove_field(model, field) + + def run_geometry_sql(self): + for sql in self.geometry_sql: + self.execute(sql) + self.geometry_sql = [] + + def _create_spatial_index_name(self, model, field): + # Oracle doesn't allow object names > 30 characters. Use this scheme + # instead of self._create_index_name() for backwards compatibility. + return truncate_name( + "%s_%s_id" % (strip_quotes(model._meta.db_table), field.column), 30 + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/adapter.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/adapter.py new file mode 100644 index 0000000..c95f903 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/adapter.py @@ -0,0 +1,62 @@ +""" + This object provides quoting for GEOS geometries into PostgreSQL/PostGIS. +""" +from django.contrib.gis.db.backends.postgis.pgraster import to_pgraster +from django.contrib.gis.geos import GEOSGeometry +from django.db.backends.postgresql.psycopg_any import sql + + +class PostGISAdapter: + def __init__(self, obj, geography=False): + """ + Initialize on the spatial object. + """ + self.is_geometry = isinstance(obj, (GEOSGeometry, PostGISAdapter)) + + # Getting the WKB (in string form, to allow easy pickling of + # the adaptor) and the SRID from the geometry or raster. + if self.is_geometry: + self.ewkb = bytes(obj.ewkb) + else: + self.ewkb = to_pgraster(obj) + + self.srid = obj.srid + self.geography = geography + + def __conform__(self, proto): + """Does the given protocol conform to what Psycopg2 expects?""" + from psycopg2.extensions import ISQLQuote + + if proto == ISQLQuote: + return self + else: + raise Exception( + "Error implementing psycopg2 protocol. Is psycopg2 installed?" + ) + + def __eq__(self, other): + return isinstance(other, PostGISAdapter) and self.ewkb == other.ewkb + + def __hash__(self): + return hash(self.ewkb) + + def __str__(self): + return self.getquoted().decode() + + @classmethod + def _fix_polygon(cls, poly): + return poly + + def getquoted(self): + """ + Return a properly quoted string for use in PostgreSQL/PostGIS. + """ + if self.is_geometry: + # Psycopg will figure out whether to use E'\\000' or '\000'. + return b"%s(%s)" % ( + b"ST_GeogFromWKB" if self.geography else b"ST_GeomFromEWKB", + sql.quote(self.ewkb).encode(), + ) + else: + # For rasters, add explicit type cast to WKB string. + return b"'%s'::raster" % self.ewkb.hex().encode() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/base.py new file mode 100644 index 0000000..8360c0e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/base.py @@ -0,0 +1,161 @@ +from functools import lru_cache + +from django.db.backends.base.base import NO_DB_ALIAS +from django.db.backends.postgresql.base import DatabaseWrapper as PsycopgDatabaseWrapper +from django.db.backends.postgresql.features import ( + DatabaseFeatures as PsycopgDatabaseFeatures, +) +from django.db.backends.postgresql.introspection import ( + DatabaseIntrospection as PsycopgDatabaseIntrospection, +) +from django.db.backends.postgresql.operations import ( + DatabaseOperations as PsycopgDatabaseOperations, +) +from django.db.backends.postgresql.psycopg_any import is_psycopg3 + +from .adapter import PostGISAdapter +from .features import DatabaseFeatures +from .introspection import PostGISIntrospection +from .operations import PostGISOperations +from .schema import PostGISSchemaEditor + +if is_psycopg3: + from psycopg.adapt import Dumper + from psycopg.pq import Format + from psycopg.types import TypeInfo + from psycopg.types.string import TextBinaryLoader, TextLoader + + class GeometryType: + pass + + class GeographyType: + pass + + class RasterType: + pass + + class BaseTextDumper(Dumper): + def dump(self, obj): + # Return bytes as hex for text formatting + return obj.ewkb.hex().encode() + + class BaseBinaryDumper(Dumper): + format = Format.BINARY + + def dump(self, obj): + return obj.ewkb + + @lru_cache + def postgis_adapters(geo_oid, geog_oid, raster_oid): + class BaseDumper(Dumper): + def __init_subclass__(cls, base_dumper): + super().__init_subclass__() + + cls.GeometryDumper = type( + "GeometryDumper", (base_dumper,), {"oid": geo_oid} + ) + cls.GeographyDumper = type( + "GeographyDumper", (base_dumper,), {"oid": geog_oid} + ) + cls.RasterDumper = type( + "RasterDumper", (BaseTextDumper,), {"oid": raster_oid} + ) + + def get_key(self, obj, format): + if obj.is_geometry: + return GeographyType if obj.geography else GeometryType + else: + return RasterType + + def upgrade(self, obj, format): + if obj.is_geometry: + if obj.geography: + return self.GeographyDumper(GeographyType) + else: + return self.GeometryDumper(GeometryType) + else: + return self.RasterDumper(RasterType) + + def dump(self, obj): + raise NotImplementedError + + class PostGISTextDumper(BaseDumper, base_dumper=BaseTextDumper): + pass + + class PostGISBinaryDumper(BaseDumper, base_dumper=BaseBinaryDumper): + format = Format.BINARY + + return PostGISTextDumper, PostGISBinaryDumper + + +class DatabaseWrapper(PsycopgDatabaseWrapper): + SchemaEditorClass = PostGISSchemaEditor + features_class = DatabaseFeatures + ops_class = PostGISOperations + introspection_class = PostGISIntrospection + + _type_infos = { + "geometry": {}, + "geography": {}, + "raster": {}, + } + + def __init__(self, *args, **kwargs): + if kwargs.get("alias", "") == NO_DB_ALIAS: + # Don't initialize PostGIS-specific stuff for non-db connections. + self.features_class = PsycopgDatabaseFeatures + self.ops_class = PsycopgDatabaseOperations + self.introspection_class = PsycopgDatabaseIntrospection + + super().__init__(*args, **kwargs) + + def prepare_database(self): + super().prepare_database() + # Check that postgis extension is installed. + with self.cursor() as cursor: + cursor.execute("SELECT 1 FROM pg_extension WHERE extname = %s", ["postgis"]) + if bool(cursor.fetchone()): + return + cursor.execute("CREATE EXTENSION IF NOT EXISTS postgis") + if is_psycopg3: + # Ensure adapters are registers if PostGIS is used within this + # connection. + self.register_geometry_adapters(self.connection, True) + + def get_new_connection(self, conn_params): + connection = super().get_new_connection(conn_params) + if is_psycopg3: + self.register_geometry_adapters(connection) + return connection + + if is_psycopg3: + + def _register_type(self, pg_connection, typename): + registry = self._type_infos[typename] + try: + info = registry[self.alias] + except KeyError: + info = TypeInfo.fetch(pg_connection, typename) + registry[self.alias] = info + + if info: # Can be None if the type does not exist (yet). + info.register(pg_connection) + pg_connection.adapters.register_loader(info.oid, TextLoader) + pg_connection.adapters.register_loader(info.oid, TextBinaryLoader) + + return info.oid if info else None + + def register_geometry_adapters(self, pg_connection, clear_caches=False): + if clear_caches: + for typename in self._type_infos: + self._type_infos[typename].pop(self.alias, None) + + geo_oid = self._register_type(pg_connection, "geometry") + geog_oid = self._register_type(pg_connection, "geography") + raster_oid = self._register_type(pg_connection, "raster") + + PostGISTextDumper, PostGISBinaryDumper = postgis_adapters( + geo_oid, geog_oid, raster_oid + ) + pg_connection.adapters.register_dumper(PostGISAdapter, PostGISTextDumper) + pg_connection.adapters.register_dumper(PostGISAdapter, PostGISBinaryDumper) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/const.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/const.py new file mode 100644 index 0000000..2f4393d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/const.py @@ -0,0 +1,62 @@ +""" +PostGIS to GDAL conversion constant definitions +""" +# Lookup to convert pixel type values from GDAL to PostGIS +GDAL_TO_POSTGIS = [None, 4, 6, 5, 8, 7, 10, 11, None, None, None, None] + +# Lookup to convert pixel type values from PostGIS to GDAL +POSTGIS_TO_GDAL = [1, 1, 1, 3, 1, 3, 2, 5, 4, None, 6, 7, None, None] + +# Struct pack structure for raster header, the raster header has the +# following structure: +# +# Endianness, PostGIS raster version, number of bands, scale, origin, +# skew, srid, width, and height. +# +# Scale, origin, and skew have x and y values. PostGIS currently uses +# a fixed endianness (1) and there is only one version (0). +POSTGIS_HEADER_STRUCTURE = "B H H d d d d d d i H H" + +# Lookup values to convert GDAL pixel types to struct characters. This is +# used to pack and unpack the pixel values of PostGIS raster bands. +GDAL_TO_STRUCT = [ + None, + "B", + "H", + "h", + "L", + "l", + "f", + "d", + None, + None, + None, + None, +] + +# Size of the packed value in bytes for different numerical types. +# This is needed to cut chunks of band data out of PostGIS raster strings +# when decomposing them into GDALRasters. +# See https://docs.python.org/library/struct.html#format-characters +STRUCT_SIZE = { + "b": 1, # Signed char + "B": 1, # Unsigned char + "?": 1, # _Bool + "h": 2, # Short + "H": 2, # Unsigned short + "i": 4, # Integer + "I": 4, # Unsigned Integer + "l": 4, # Long + "L": 4, # Unsigned Long + "f": 4, # Float + "d": 8, # Double +} + +# Pixel type specifies type of pixel values in a band. Storage flag specifies +# whether the band data is stored as part of the datum or is to be found on the +# server's filesystem. There are currently 11 supported pixel value types, so 4 +# bits are enough to account for all. Reserve the upper 4 bits for generic +# flags. See +# https://trac.osgeo.org/postgis/wiki/WKTRaster/RFC/RFC1_V0SerialFormat#Pixeltypeandstorageflag +BANDTYPE_PIXTYPE_MASK = 0x0F +BANDTYPE_FLAG_HASNODATA = 1 << 6 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/features.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/features.py new file mode 100644 index 0000000..d96e939 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/features.py @@ -0,0 +1,13 @@ +from django.contrib.gis.db.backends.base.features import BaseSpatialFeatures +from django.db.backends.postgresql.features import ( + DatabaseFeatures as PsycopgDatabaseFeatures, +) + + +class DatabaseFeatures(BaseSpatialFeatures, PsycopgDatabaseFeatures): + supports_geography = True + supports_3d_storage = True + supports_3d_functions = True + supports_raster = True + supports_empty_geometries = True + empty_intersection_returns_none = False diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/introspection.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/introspection.py new file mode 100644 index 0000000..766c0fa --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/introspection.py @@ -0,0 +1,71 @@ +from django.contrib.gis.gdal import OGRGeomType +from django.db.backends.postgresql.introspection import DatabaseIntrospection + + +class PostGISIntrospection(DatabaseIntrospection): + postgis_oid_lookup = {} # Populated when introspection is performed. + + ignored_tables = DatabaseIntrospection.ignored_tables + [ + "geography_columns", + "geometry_columns", + "raster_columns", + "spatial_ref_sys", + "raster_overviews", + ] + + def get_field_type(self, data_type, description): + if not self.postgis_oid_lookup: + # Query PostgreSQL's pg_type table to determine the OID integers + # for the PostGIS data types used in reverse lookup (the integers + # may be different across versions). To prevent unnecessary + # requests upon connection initialization, the `data_types_reverse` + # dictionary isn't updated until introspection is performed here. + with self.connection.cursor() as cursor: + cursor.execute( + "SELECT oid, typname " + "FROM pg_type " + "WHERE typname IN ('geometry', 'geography')" + ) + self.postgis_oid_lookup = dict(cursor.fetchall()) + self.data_types_reverse.update( + (oid, "GeometryField") for oid in self.postgis_oid_lookup + ) + return super().get_field_type(data_type, description) + + def get_geometry_type(self, table_name, description): + """ + The geometry type OID used by PostGIS does not indicate the particular + type of field that a geometry column is (e.g., whether it's a + PointField or a PolygonField). Thus, this routine queries the PostGIS + metadata tables to determine the geometry type. + """ + with self.connection.cursor() as cursor: + cursor.execute( + """ + SELECT t.coord_dimension, t.srid, t.type FROM ( + SELECT * FROM geometry_columns + UNION ALL + SELECT * FROM geography_columns + ) AS t WHERE t.f_table_name = %s AND t.f_geometry_column = %s + """, + (table_name, description.name), + ) + row = cursor.fetchone() + if not row: + raise Exception( + 'Could not find a geometry or geography column for "%s"."%s"' + % (table_name, description.name) + ) + dim, srid, field_type = row + # OGRGeomType does not require GDAL and makes it easy to convert + # from OGC geom type name to Django field. + field_type = OGRGeomType(field_type).django + # Getting any GeometryField keyword arguments that are not the default. + field_params = {} + if self.postgis_oid_lookup.get(description.type_code) == "geography": + field_params["geography"] = True + if srid != 4326: + field_params["srid"] = srid + if dim != 2: + field_params["dim"] = dim + return field_type, field_params diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/models.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/models.py new file mode 100644 index 0000000..b7b5682 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/models.py @@ -0,0 +1,72 @@ +""" + The GeometryColumns and SpatialRefSys models for the PostGIS backend. +""" +from django.contrib.gis.db.backends.base.models import SpatialRefSysMixin +from django.db import models + + +class PostGISGeometryColumns(models.Model): + """ + The 'geometry_columns' view from PostGIS. See the PostGIS + documentation at Ch. 4.3.2. + """ + + f_table_catalog = models.CharField(max_length=256) + f_table_schema = models.CharField(max_length=256) + f_table_name = models.CharField(max_length=256) + f_geometry_column = models.CharField(max_length=256) + coord_dimension = models.IntegerField() + srid = models.IntegerField(primary_key=True) + type = models.CharField(max_length=30) + + class Meta: + app_label = "gis" + db_table = "geometry_columns" + managed = False + + def __str__(self): + return "%s.%s - %dD %s field (SRID: %d)" % ( + self.f_table_name, + self.f_geometry_column, + self.coord_dimension, + self.type, + self.srid, + ) + + @classmethod + def table_name_col(cls): + """ + Return the name of the metadata column used to store the feature table + name. + """ + return "f_table_name" + + @classmethod + def geom_col_name(cls): + """ + Return the name of the metadata column used to store the feature + geometry column. + """ + return "f_geometry_column" + + +class PostGISSpatialRefSys(models.Model, SpatialRefSysMixin): + """ + The 'spatial_ref_sys' table from PostGIS. See the PostGIS + documentation at Ch. 4.2.1. + """ + + srid = models.IntegerField(primary_key=True) + auth_name = models.CharField(max_length=256) + auth_srid = models.IntegerField() + srtext = models.CharField(max_length=2048) + proj4text = models.CharField(max_length=2048) + + class Meta: + app_label = "gis" + db_table = "spatial_ref_sys" + managed = False + + @property + def wkt(self): + return self.srtext diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/operations.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/operations.py new file mode 100644 index 0000000..b68db37 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/operations.py @@ -0,0 +1,423 @@ +import re + +from django.conf import settings +from django.contrib.gis.db.backends.base.operations import BaseSpatialOperations +from django.contrib.gis.db.backends.utils import SpatialOperator +from django.contrib.gis.db.models import GeometryField, RasterField +from django.contrib.gis.gdal import GDALRaster +from django.contrib.gis.geos.geometry import GEOSGeometryBase +from django.contrib.gis.geos.prototypes.io import wkb_r +from django.contrib.gis.measure import Distance +from django.core.exceptions import ImproperlyConfigured +from django.db import NotSupportedError, ProgrammingError +from django.db.backends.postgresql.operations import DatabaseOperations +from django.db.backends.postgresql.psycopg_any import is_psycopg3 +from django.db.models import Func, Value +from django.utils.functional import cached_property +from django.utils.version import get_version_tuple + +from .adapter import PostGISAdapter +from .models import PostGISGeometryColumns, PostGISSpatialRefSys +from .pgraster import from_pgraster + +# Identifier to mark raster lookups as bilateral. +BILATERAL = "bilateral" + + +class PostGISOperator(SpatialOperator): + def __init__(self, geography=False, raster=False, **kwargs): + # Only a subset of the operators and functions are available for the + # geography type. Lookups that don't support geography will be cast to + # geometry. + self.geography = geography + # Only a subset of the operators and functions are available for the + # raster type. Lookups that don't support raster will be converted to + # polygons. If the raster argument is set to BILATERAL, then the + # operator cannot handle mixed geom-raster lookups. + self.raster = raster + super().__init__(**kwargs) + + def as_sql(self, connection, lookup, template_params, *args): + template_params = self.check_raster(lookup, template_params) + template_params = self.check_geography(lookup, template_params) + return super().as_sql(connection, lookup, template_params, *args) + + def check_raster(self, lookup, template_params): + spheroid = lookup.rhs_params and lookup.rhs_params[-1] == "spheroid" + + # Check which input is a raster. + lhs_is_raster = lookup.lhs.field.geom_type == "RASTER" + rhs_is_raster = isinstance(lookup.rhs, GDALRaster) + + # Look for band indices and inject them if provided. + if lookup.band_lhs is not None and lhs_is_raster: + if not self.func: + raise ValueError( + "Band indices are not allowed for this operator, it works on bbox " + "only." + ) + template_params["lhs"] = "%s, %s" % ( + template_params["lhs"], + lookup.band_lhs, + ) + + if lookup.band_rhs is not None and rhs_is_raster: + if not self.func: + raise ValueError( + "Band indices are not allowed for this operator, it works on bbox " + "only." + ) + template_params["rhs"] = "%s, %s" % ( + template_params["rhs"], + lookup.band_rhs, + ) + + # Convert rasters to polygons if necessary. + if not self.raster or spheroid: + # Operators without raster support. + if lhs_is_raster: + template_params["lhs"] = "ST_Polygon(%s)" % template_params["lhs"] + if rhs_is_raster: + template_params["rhs"] = "ST_Polygon(%s)" % template_params["rhs"] + elif self.raster == BILATERAL: + # Operators with raster support but don't support mixed (rast-geom) + # lookups. + if lhs_is_raster and not rhs_is_raster: + template_params["lhs"] = "ST_Polygon(%s)" % template_params["lhs"] + elif rhs_is_raster and not lhs_is_raster: + template_params["rhs"] = "ST_Polygon(%s)" % template_params["rhs"] + + return template_params + + def check_geography(self, lookup, template_params): + """Convert geography fields to geometry types, if necessary.""" + if lookup.lhs.output_field.geography and not self.geography: + template_params["lhs"] += "::geometry" + return template_params + + +class ST_Polygon(Func): + function = "ST_Polygon" + + def __init__(self, expr): + super().__init__(expr) + expr = self.source_expressions[0] + if isinstance(expr, Value) and not expr._output_field_or_none: + self.source_expressions[0] = Value( + expr.value, output_field=RasterField(srid=expr.value.srid) + ) + + @cached_property + def output_field(self): + return GeometryField(srid=self.source_expressions[0].field.srid) + + +class PostGISOperations(BaseSpatialOperations, DatabaseOperations): + name = "postgis" + postgis = True + geom_func_prefix = "ST_" + + Adapter = PostGISAdapter + + collect = geom_func_prefix + "Collect" + extent = geom_func_prefix + "Extent" + extent3d = geom_func_prefix + "3DExtent" + length3d = geom_func_prefix + "3DLength" + makeline = geom_func_prefix + "MakeLine" + perimeter3d = geom_func_prefix + "3DPerimeter" + unionagg = geom_func_prefix + "Union" + + gis_operators = { + "bbcontains": PostGISOperator(op="~", raster=True), + "bboverlaps": PostGISOperator(op="&&", geography=True, raster=True), + "contained": PostGISOperator(op="@", raster=True), + "overlaps_left": PostGISOperator(op="&<", raster=BILATERAL), + "overlaps_right": PostGISOperator(op="&>", raster=BILATERAL), + "overlaps_below": PostGISOperator(op="&<|"), + "overlaps_above": PostGISOperator(op="|&>"), + "left": PostGISOperator(op="<<"), + "right": PostGISOperator(op=">>"), + "strictly_below": PostGISOperator(op="<<|"), + "strictly_above": PostGISOperator(op="|>>"), + "same_as": PostGISOperator(op="~=", raster=BILATERAL), + "exact": PostGISOperator(op="~=", raster=BILATERAL), # alias of same_as + "contains": PostGISOperator(func="ST_Contains", raster=BILATERAL), + "contains_properly": PostGISOperator( + func="ST_ContainsProperly", raster=BILATERAL + ), + "coveredby": PostGISOperator( + func="ST_CoveredBy", geography=True, raster=BILATERAL + ), + "covers": PostGISOperator(func="ST_Covers", geography=True, raster=BILATERAL), + "crosses": PostGISOperator(func="ST_Crosses"), + "disjoint": PostGISOperator(func="ST_Disjoint", raster=BILATERAL), + "equals": PostGISOperator(func="ST_Equals"), + "intersects": PostGISOperator( + func="ST_Intersects", geography=True, raster=BILATERAL + ), + "overlaps": PostGISOperator(func="ST_Overlaps", raster=BILATERAL), + "relate": PostGISOperator(func="ST_Relate"), + "touches": PostGISOperator(func="ST_Touches", raster=BILATERAL), + "within": PostGISOperator(func="ST_Within", raster=BILATERAL), + "dwithin": PostGISOperator(func="ST_DWithin", geography=True, raster=BILATERAL), + } + + unsupported_functions = set() + + select = "%s" if is_psycopg3 else "%s::bytea" + + select_extent = None + + @cached_property + def function_names(self): + function_names = { + "AsWKB": "ST_AsBinary", + "AsWKT": "ST_AsText", + "BoundingCircle": "ST_MinimumBoundingCircle", + "FromWKB": "ST_GeomFromWKB", + "FromWKT": "ST_GeomFromText", + "NumPoints": "ST_NPoints", + } + return function_names + + @cached_property + def spatial_version(self): + """Determine the version of the PostGIS library.""" + # Trying to get the PostGIS version because the function + # signatures will depend on the version used. The cost + # here is a database query to determine the version, which + # can be mitigated by setting `POSTGIS_VERSION` with a 3-tuple + # comprising user-supplied values for the major, minor, and + # subminor revision of PostGIS. + if hasattr(settings, "POSTGIS_VERSION"): + version = settings.POSTGIS_VERSION + else: + # Run a basic query to check the status of the connection so we're + # sure we only raise the error below if the problem comes from + # PostGIS and not from PostgreSQL itself (see #24862). + self._get_postgis_func("version") + + try: + vtup = self.postgis_version_tuple() + except ProgrammingError: + raise ImproperlyConfigured( + 'Cannot determine PostGIS version for database "%s" ' + 'using command "SELECT postgis_lib_version()". ' + "GeoDjango requires at least PostGIS version 2.5. " + "Was the database created from a spatial database " + "template?" % self.connection.settings_dict["NAME"] + ) + version = vtup[1:] + return version + + def convert_extent(self, box): + """ + Return a 4-tuple extent for the `Extent` aggregate by converting + the bounding box text returned by PostGIS (`box` argument), for + example: "BOX(-90.0 30.0, -85.0 40.0)". + """ + if box is None: + return None + ll, ur = box[4:-1].split(",") + xmin, ymin = map(float, ll.split()) + xmax, ymax = map(float, ur.split()) + return (xmin, ymin, xmax, ymax) + + def convert_extent3d(self, box3d): + """ + Return a 6-tuple extent for the `Extent3D` aggregate by converting + the 3d bounding-box text returned by PostGIS (`box3d` argument), for + example: "BOX3D(-90.0 30.0 1, -85.0 40.0 2)". + """ + if box3d is None: + return None + ll, ur = box3d[6:-1].split(",") + xmin, ymin, zmin = map(float, ll.split()) + xmax, ymax, zmax = map(float, ur.split()) + return (xmin, ymin, zmin, xmax, ymax, zmax) + + def geo_db_type(self, f): + """ + Return the database field type for the given spatial field. + """ + if f.geom_type == "RASTER": + return "raster" + + # Type-based geometries. + # TODO: Support 'M' extension. + if f.dim == 3: + geom_type = f.geom_type + "Z" + else: + geom_type = f.geom_type + if f.geography: + if f.srid != 4326: + raise NotSupportedError( + "PostGIS only supports geography columns with an SRID of 4326." + ) + + return "geography(%s,%d)" % (geom_type, f.srid) + else: + return "geometry(%s,%d)" % (geom_type, f.srid) + + def get_distance(self, f, dist_val, lookup_type): + """ + Retrieve the distance parameters for the given geometry field, + distance lookup value, and the distance lookup type. + + This is the most complex implementation of the spatial backends due to + what is supported on geodetic geometry columns vs. what's available on + projected geometry columns. In addition, it has to take into account + the geography column type. + """ + # Getting the distance parameter + value = dist_val[0] + + # Shorthand boolean flags. + geodetic = f.geodetic(self.connection) + geography = f.geography + + if isinstance(value, Distance): + if geography: + dist_param = value.m + elif geodetic: + if lookup_type == "dwithin": + raise ValueError( + "Only numeric values of degree units are " + "allowed on geographic DWithin queries." + ) + dist_param = value.m + else: + dist_param = getattr( + value, Distance.unit_attname(f.units_name(self.connection)) + ) + else: + # Assuming the distance is in the units of the field. + dist_param = value + + return [dist_param] + + def get_geom_placeholder(self, f, value, compiler): + """ + Provide a proper substitution value for Geometries or rasters that are + not in the SRID of the field. Specifically, this routine will + substitute in the ST_Transform() function call. + """ + transform_func = self.spatial_function_name("Transform") + if hasattr(value, "as_sql"): + if value.field.srid == f.srid: + placeholder = "%s" + else: + placeholder = "%s(%%s, %s)" % (transform_func, f.srid) + return placeholder + + # Get the srid for this object + if value is None: + value_srid = None + else: + value_srid = value.srid + + # Adding Transform() to the SQL placeholder if the value srid + # is not equal to the field srid. + if value_srid is None or value_srid == f.srid: + placeholder = "%s" + else: + placeholder = "%s(%%s, %s)" % (transform_func, f.srid) + + return placeholder + + def _get_postgis_func(self, func): + """ + Helper routine for calling PostGIS functions and returning their result. + """ + # Close out the connection. See #9437. + with self.connection.temporary_connection() as cursor: + cursor.execute("SELECT %s()" % func) + return cursor.fetchone()[0] + + def postgis_geos_version(self): + "Return the version of the GEOS library used with PostGIS." + return self._get_postgis_func("postgis_geos_version") + + def postgis_lib_version(self): + "Return the version number of the PostGIS library used with PostgreSQL." + return self._get_postgis_func("postgis_lib_version") + + def postgis_proj_version(self): + """Return the version of the PROJ library used with PostGIS.""" + return self._get_postgis_func("postgis_proj_version") + + def postgis_version(self): + "Return PostGIS version number and compile-time options." + return self._get_postgis_func("postgis_version") + + def postgis_full_version(self): + "Return PostGIS version number and compile-time options." + return self._get_postgis_func("postgis_full_version") + + def postgis_version_tuple(self): + """ + Return the PostGIS version as a tuple (version string, major, + minor, subminor). + """ + version = self.postgis_lib_version() + return (version,) + get_version_tuple(version) + + def proj_version_tuple(self): + """ + Return the version of PROJ used by PostGIS as a tuple of the + major, minor, and subminor release numbers. + """ + proj_regex = re.compile(r"(\d+)\.(\d+)\.(\d+)") + proj_ver_str = self.postgis_proj_version() + m = proj_regex.search(proj_ver_str) + if m: + return tuple(map(int, m.groups())) + else: + raise Exception("Could not determine PROJ version from PostGIS.") + + def spatial_aggregate_name(self, agg_name): + if agg_name == "Extent3D": + return self.extent3d + else: + return self.geom_func_prefix + agg_name + + # Routines for getting the OGC-compliant models. + def geometry_columns(self): + return PostGISGeometryColumns + + def spatial_ref_sys(self): + return PostGISSpatialRefSys + + def parse_raster(self, value): + """Convert a PostGIS HEX String into a dict readable by GDALRaster.""" + return from_pgraster(value) + + def distance_expr_for_lookup(self, lhs, rhs, **kwargs): + return super().distance_expr_for_lookup( + self._normalize_distance_lookup_arg(lhs), + self._normalize_distance_lookup_arg(rhs), + **kwargs, + ) + + @staticmethod + def _normalize_distance_lookup_arg(arg): + is_raster = ( + arg.field.geom_type == "RASTER" + if hasattr(arg, "field") + else isinstance(arg, GDALRaster) + ) + return ST_Polygon(arg) if is_raster else arg + + def get_geometry_converter(self, expression): + read = wkb_r().read + geom_class = expression.output_field.geom_class + + def converter(value, expression, connection): + if isinstance(value, str): # Coming from hex strings. + value = value.encode("ascii") + return None if value is None else GEOSGeometryBase(read(value), geom_class) + + return converter + + def get_area_att_for_field(self, field): + return "sq_m" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/pgraster.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/pgraster.py new file mode 100644 index 0000000..c231b48 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/pgraster.py @@ -0,0 +1,152 @@ +import struct + +from django.core.exceptions import ValidationError + +from .const import ( + BANDTYPE_FLAG_HASNODATA, + BANDTYPE_PIXTYPE_MASK, + GDAL_TO_POSTGIS, + GDAL_TO_STRUCT, + POSTGIS_HEADER_STRUCTURE, + POSTGIS_TO_GDAL, + STRUCT_SIZE, +) + + +def pack(structure, data): + """ + Pack data into hex string with little endian format. + """ + return struct.pack("<" + structure, *data) + + +def unpack(structure, data): + """ + Unpack little endian hexlified binary string into a list. + """ + return struct.unpack("<" + structure, bytes.fromhex(data)) + + +def chunk(data, index): + """ + Split a string into two parts at the input index. + """ + return data[:index], data[index:] + + +def from_pgraster(data): + """ + Convert a PostGIS HEX String into a dictionary. + """ + if data is None: + return + + # Split raster header from data + header, data = chunk(data, 122) + header = unpack(POSTGIS_HEADER_STRUCTURE, header) + + # Parse band data + bands = [] + pixeltypes = [] + while data: + # Get pixel type for this band + pixeltype_with_flags, data = chunk(data, 2) + pixeltype_with_flags = unpack("B", pixeltype_with_flags)[0] + pixeltype = pixeltype_with_flags & BANDTYPE_PIXTYPE_MASK + + # Convert datatype from PostGIS to GDAL & get pack type and size + pixeltype = POSTGIS_TO_GDAL[pixeltype] + pack_type = GDAL_TO_STRUCT[pixeltype] + pack_size = 2 * STRUCT_SIZE[pack_type] + + # Parse band nodata value. The nodata value is part of the + # PGRaster string even if the nodata flag is True, so it always + # has to be chunked off the data string. + nodata, data = chunk(data, pack_size) + nodata = unpack(pack_type, nodata)[0] + + # Chunk and unpack band data (pack size times nr of pixels) + band, data = chunk(data, pack_size * header[10] * header[11]) + band_result = {"data": bytes.fromhex(band)} + + # Set the nodata value if the nodata flag is set. + if pixeltype_with_flags & BANDTYPE_FLAG_HASNODATA: + band_result["nodata_value"] = nodata + + # Append band data to band list + bands.append(band_result) + + # Store pixeltype of this band in pixeltypes array + pixeltypes.append(pixeltype) + + # Check that all bands have the same pixeltype. + # This is required by GDAL. PostGIS rasters could have different pixeltypes + # for bands of the same raster. + if len(set(pixeltypes)) != 1: + raise ValidationError("Band pixeltypes are not all equal.") + + return { + "srid": int(header[9]), + "width": header[10], + "height": header[11], + "datatype": pixeltypes[0], + "origin": (header[5], header[6]), + "scale": (header[3], header[4]), + "skew": (header[7], header[8]), + "bands": bands, + } + + +def to_pgraster(rast): + """ + Convert a GDALRaster into PostGIS Raster format. + """ + # Prepare the raster header data as a tuple. The first two numbers are + # the endianness and the PostGIS Raster Version, both are fixed by + # PostGIS at the moment. + rasterheader = ( + 1, + 0, + len(rast.bands), + rast.scale.x, + rast.scale.y, + rast.origin.x, + rast.origin.y, + rast.skew.x, + rast.skew.y, + rast.srs.srid, + rast.width, + rast.height, + ) + + # Pack raster header. + result = pack(POSTGIS_HEADER_STRUCTURE, rasterheader) + + for band in rast.bands: + # The PostGIS raster band header has exactly two elements, a 8BUI byte + # and the nodata value. + # + # The 8BUI stores both the PostGIS pixel data type and a nodata flag. + # It is composed as the datatype with BANDTYPE_FLAG_HASNODATA (1 << 6) + # for existing nodata values: + # 8BUI_VALUE = PG_PIXEL_TYPE (0-11) | BANDTYPE_FLAG_HASNODATA + # + # For example, if the byte value is 71, then the datatype is + # 71 & ~BANDTYPE_FLAG_HASNODATA = 7 (32BSI) + # and the nodata value is True. + structure = "B" + GDAL_TO_STRUCT[band.datatype()] + + # Get band pixel type in PostGIS notation + pixeltype = GDAL_TO_POSTGIS[band.datatype()] + + # Set the nodata flag + if band.nodata_value is not None: + pixeltype |= BANDTYPE_FLAG_HASNODATA + + # Pack band header + bandheader = pack(structure, (pixeltype, band.nodata_value or 0)) + + # Add packed header and band data to result + result += bandheader + band.data(as_memoryview=True) + + return result diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/schema.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/schema.py new file mode 100644 index 0000000..5464c85 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/postgis/schema.py @@ -0,0 +1,81 @@ +from django.db.backends.postgresql.schema import DatabaseSchemaEditor +from django.db.models.expressions import Col, Func + + +class PostGISSchemaEditor(DatabaseSchemaEditor): + geom_index_type = "GIST" + geom_index_ops_nd = "GIST_GEOMETRY_OPS_ND" + rast_index_template = "ST_ConvexHull(%(expressions)s)" + + sql_alter_column_to_3d = ( + "ALTER COLUMN %(column)s TYPE %(type)s USING ST_Force3D(%(column)s)::%(type)s" + ) + sql_alter_column_to_2d = ( + "ALTER COLUMN %(column)s TYPE %(type)s USING ST_Force2D(%(column)s)::%(type)s" + ) + + def geo_quote_name(self, name): + return self.connection.ops.geo_quote_name(name) + + def _field_should_be_indexed(self, model, field): + if getattr(field, "spatial_index", False): + return True + return super()._field_should_be_indexed(model, field) + + def _create_index_sql(self, model, *, fields=None, **kwargs): + if fields is None or len(fields) != 1 or not hasattr(fields[0], "geodetic"): + return super()._create_index_sql(model, fields=fields, **kwargs) + + field = fields[0] + expressions = None + opclasses = None + if field.geom_type == "RASTER": + # For raster fields, wrap index creation SQL statement with ST_ConvexHull. + # Indexes on raster columns are based on the convex hull of the raster. + expressions = Func(Col(None, field), template=self.rast_index_template) + fields = None + elif field.dim > 2 and not field.geography: + # Use "nd" ops which are fast on multidimensional cases + opclasses = [self.geom_index_ops_nd] + name = kwargs.get("name") + if not name: + name = self._create_index_name(model._meta.db_table, [field.column], "_id") + + return super()._create_index_sql( + model, + fields=fields, + name=name, + using=" USING %s" % self.geom_index_type, + opclasses=opclasses, + expressions=expressions, + ) + + def _alter_column_type_sql( + self, table, old_field, new_field, new_type, old_collation, new_collation + ): + """ + Special case when dimension changed. + """ + if not hasattr(old_field, "dim") or not hasattr(new_field, "dim"): + return super()._alter_column_type_sql( + table, old_field, new_field, new_type, old_collation, new_collation + ) + + if old_field.dim == 2 and new_field.dim == 3: + sql_alter = self.sql_alter_column_to_3d + elif old_field.dim == 3 and new_field.dim == 2: + sql_alter = self.sql_alter_column_to_2d + else: + sql_alter = self.sql_alter_column_type + return ( + ( + sql_alter + % { + "column": self.quote_name(new_field.column), + "type": new_type, + "collation": "", + }, + [], + ), + [], + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/adapter.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/adapter.py new file mode 100644 index 0000000..91d14dc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/adapter.py @@ -0,0 +1,10 @@ +from django.contrib.gis.db.backends.base.adapter import WKTAdapter +from django.db.backends.sqlite3.base import Database + + +class SpatiaLiteAdapter(WKTAdapter): + "SQLite adapter for geometry objects." + + def __conform__(self, protocol): + if protocol is Database.PrepareProtocol: + return str(self) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/base.py new file mode 100644 index 0000000..3359a7a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/base.py @@ -0,0 +1,79 @@ +from ctypes.util import find_library + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.db.backends.sqlite3.base import DatabaseWrapper as SQLiteDatabaseWrapper + +from .client import SpatiaLiteClient +from .features import DatabaseFeatures +from .introspection import SpatiaLiteIntrospection +from .operations import SpatiaLiteOperations +from .schema import SpatialiteSchemaEditor + + +class DatabaseWrapper(SQLiteDatabaseWrapper): + SchemaEditorClass = SpatialiteSchemaEditor + # Classes instantiated in __init__(). + client_class = SpatiaLiteClient + features_class = DatabaseFeatures + introspection_class = SpatiaLiteIntrospection + ops_class = SpatiaLiteOperations + + def __init__(self, *args, **kwargs): + # Trying to find the location of the SpatiaLite library. + # Here we are figuring out the path to the SpatiaLite library + # (`libspatialite`). If it's not in the system library path (e.g., it + # cannot be found by `ctypes.util.find_library`), then it may be set + # manually in the settings via the `SPATIALITE_LIBRARY_PATH` setting. + self.lib_spatialite_paths = [ + name + for name in [ + getattr(settings, "SPATIALITE_LIBRARY_PATH", None), + "mod_spatialite.so", + "mod_spatialite", + find_library("spatialite"), + ] + if name is not None + ] + super().__init__(*args, **kwargs) + + def get_new_connection(self, conn_params): + conn = super().get_new_connection(conn_params) + # Enabling extension loading on the SQLite connection. + try: + conn.enable_load_extension(True) + except AttributeError: + raise ImproperlyConfigured( + "SpatiaLite requires SQLite to be configured to allow " + "extension loading." + ) + # Load the SpatiaLite library extension on the connection. + for path in self.lib_spatialite_paths: + try: + conn.load_extension(path) + except Exception: + if getattr(settings, "SPATIALITE_LIBRARY_PATH", None): + raise ImproperlyConfigured( + "Unable to load the SpatiaLite library extension " + "as specified in your SPATIALITE_LIBRARY_PATH setting." + ) + continue + else: + break + else: + raise ImproperlyConfigured( + "Unable to load the SpatiaLite library extension. " + "Library names tried: %s" % ", ".join(self.lib_spatialite_paths) + ) + return conn + + def prepare_database(self): + super().prepare_database() + # Check if spatial metadata have been initialized in the database + with self.cursor() as cursor: + cursor.execute("PRAGMA table_info(geometry_columns);") + if cursor.fetchall() == []: + if self.ops.spatial_version < (5,): + cursor.execute("SELECT InitSpatialMetaData(1)") + else: + cursor.execute("SELECT InitSpatialMetaDataFull(1)") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/client.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/client.py new file mode 100644 index 0000000..527fe15 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/client.py @@ -0,0 +1,5 @@ +from django.db.backends.sqlite3.client import DatabaseClient + + +class SpatiaLiteClient(DatabaseClient): + executable_name = "spatialite" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/features.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/features.py new file mode 100644 index 0000000..9504bb0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/features.py @@ -0,0 +1,26 @@ +from django.contrib.gis.db.backends.base.features import BaseSpatialFeatures +from django.db.backends.sqlite3.features import ( + DatabaseFeatures as SQLiteDatabaseFeatures, +) +from django.utils.functional import cached_property + + +class DatabaseFeatures(BaseSpatialFeatures, SQLiteDatabaseFeatures): + can_alter_geometry_field = False # Not implemented + supports_3d_storage = True + + @cached_property + def supports_area_geodetic(self): + return bool(self.connection.ops.geom_lib_version()) + + @cached_property + def django_test_skips(self): + skips = super().django_test_skips + skips.update( + { + "SpatiaLite doesn't support distance lookups with Distance objects.": { + "gis_tests.geogapp.tests.GeographyTest.test02_distance_lookup", + }, + } + ) + return skips diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/introspection.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/introspection.py new file mode 100644 index 0000000..8d0003f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/introspection.py @@ -0,0 +1,82 @@ +from django.contrib.gis.gdal import OGRGeomType +from django.db.backends.sqlite3.introspection import ( + DatabaseIntrospection, + FlexibleFieldLookupDict, +) + + +class GeoFlexibleFieldLookupDict(FlexibleFieldLookupDict): + """ + Subclass that includes updates the `base_data_types_reverse` dict + for geometry field types. + """ + + base_data_types_reverse = { + **FlexibleFieldLookupDict.base_data_types_reverse, + "point": "GeometryField", + "linestring": "GeometryField", + "polygon": "GeometryField", + "multipoint": "GeometryField", + "multilinestring": "GeometryField", + "multipolygon": "GeometryField", + "geometrycollection": "GeometryField", + } + + +class SpatiaLiteIntrospection(DatabaseIntrospection): + data_types_reverse = GeoFlexibleFieldLookupDict() + + def get_geometry_type(self, table_name, description): + with self.connection.cursor() as cursor: + # Querying the `geometry_columns` table to get additional metadata. + cursor.execute( + "SELECT coord_dimension, srid, geometry_type " + "FROM geometry_columns " + "WHERE f_table_name=%s AND f_geometry_column=%s", + (table_name, description.name), + ) + row = cursor.fetchone() + if not row: + raise Exception( + 'Could not find a geometry column for "%s"."%s"' + % (table_name, description.name) + ) + + # OGRGeomType does not require GDAL and makes it easy to convert + # from OGC geom type name to Django field. + ogr_type = row[2] + if isinstance(ogr_type, int) and ogr_type > 1000: + # SpatiaLite uses SFSQL 1.2 offsets 1000 (Z), 2000 (M), and + # 3000 (ZM) to indicate the presence of higher dimensional + # coordinates (M not yet supported by Django). + ogr_type = ogr_type % 1000 + OGRGeomType.wkb25bit + field_type = OGRGeomType(ogr_type).django + + # Getting any GeometryField keyword arguments that are not the default. + dim = row[0] + srid = row[1] + field_params = {} + if srid != 4326: + field_params["srid"] = srid + if (isinstance(dim, str) and "Z" in dim) or dim == 3: + field_params["dim"] = 3 + return field_type, field_params + + def get_constraints(self, cursor, table_name): + constraints = super().get_constraints(cursor, table_name) + cursor.execute( + "SELECT f_geometry_column " + "FROM geometry_columns " + "WHERE f_table_name=%s AND spatial_index_enabled=1", + (table_name,), + ) + for row in cursor.fetchall(): + constraints["%s__spatial__index" % row[0]] = { + "columns": [row[0]], + "primary_key": False, + "unique": False, + "foreign_key": None, + "check": False, + "index": True, + } + return constraints diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/models.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/models.py new file mode 100644 index 0000000..7cc98ae --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/models.py @@ -0,0 +1,70 @@ +""" + The GeometryColumns and SpatialRefSys models for the SpatiaLite backend. +""" +from django.contrib.gis.db.backends.base.models import SpatialRefSysMixin +from django.db import models + + +class SpatialiteGeometryColumns(models.Model): + """ + The 'geometry_columns' table from SpatiaLite. + """ + + f_table_name = models.CharField(max_length=256) + f_geometry_column = models.CharField(max_length=256) + coord_dimension = models.IntegerField() + srid = models.IntegerField(primary_key=True) + spatial_index_enabled = models.IntegerField() + type = models.IntegerField(db_column="geometry_type") + + class Meta: + app_label = "gis" + db_table = "geometry_columns" + managed = False + + def __str__(self): + return "%s.%s - %dD %s field (SRID: %d)" % ( + self.f_table_name, + self.f_geometry_column, + self.coord_dimension, + self.type, + self.srid, + ) + + @classmethod + def table_name_col(cls): + """ + Return the name of the metadata column used to store the feature table + name. + """ + return "f_table_name" + + @classmethod + def geom_col_name(cls): + """ + Return the name of the metadata column used to store the feature + geometry column. + """ + return "f_geometry_column" + + +class SpatialiteSpatialRefSys(models.Model, SpatialRefSysMixin): + """ + The 'spatial_ref_sys' table from SpatiaLite. + """ + + srid = models.IntegerField(primary_key=True) + auth_name = models.CharField(max_length=256) + auth_srid = models.IntegerField() + ref_sys_name = models.CharField(max_length=256) + proj4text = models.CharField(max_length=2048) + srtext = models.CharField(max_length=2048) + + class Meta: + app_label = "gis" + db_table = "spatial_ref_sys" + managed = False + + @property + def wkt(self): + return self.srtext diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/operations.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/operations.py new file mode 100644 index 0000000..0b8b26a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/operations.py @@ -0,0 +1,227 @@ +""" +SQL functions reference lists: +https://www.gaia-gis.it/gaia-sins/spatialite-sql-4.3.0.html +""" +from django.contrib.gis.db import models +from django.contrib.gis.db.backends.base.operations import BaseSpatialOperations +from django.contrib.gis.db.backends.spatialite.adapter import SpatiaLiteAdapter +from django.contrib.gis.db.backends.utils import SpatialOperator +from django.contrib.gis.geos.geometry import GEOSGeometry, GEOSGeometryBase +from django.contrib.gis.geos.prototypes.io import wkb_r +from django.contrib.gis.measure import Distance +from django.core.exceptions import ImproperlyConfigured +from django.db.backends.sqlite3.operations import DatabaseOperations +from django.utils.functional import cached_property +from django.utils.version import get_version_tuple + + +class SpatialiteNullCheckOperator(SpatialOperator): + def as_sql(self, connection, lookup, template_params, sql_params): + sql, params = super().as_sql(connection, lookup, template_params, sql_params) + return "%s > 0" % sql, params + + +class SpatiaLiteOperations(BaseSpatialOperations, DatabaseOperations): + name = "spatialite" + spatialite = True + + Adapter = SpatiaLiteAdapter + + collect = "Collect" + extent = "Extent" + makeline = "MakeLine" + unionagg = "GUnion" + + from_text = "GeomFromText" + + gis_operators = { + # Binary predicates + "equals": SpatialiteNullCheckOperator(func="Equals"), + "disjoint": SpatialiteNullCheckOperator(func="Disjoint"), + "touches": SpatialiteNullCheckOperator(func="Touches"), + "crosses": SpatialiteNullCheckOperator(func="Crosses"), + "within": SpatialiteNullCheckOperator(func="Within"), + "overlaps": SpatialiteNullCheckOperator(func="Overlaps"), + "contains": SpatialiteNullCheckOperator(func="Contains"), + "intersects": SpatialiteNullCheckOperator(func="Intersects"), + "relate": SpatialiteNullCheckOperator(func="Relate"), + "coveredby": SpatialiteNullCheckOperator(func="CoveredBy"), + "covers": SpatialiteNullCheckOperator(func="Covers"), + # Returns true if B's bounding box completely contains A's bounding box. + "contained": SpatialOperator(func="MbrWithin"), + # Returns true if A's bounding box completely contains B's bounding box. + "bbcontains": SpatialOperator(func="MbrContains"), + # Returns true if A's bounding box overlaps B's bounding box. + "bboverlaps": SpatialOperator(func="MbrOverlaps"), + # These are implemented here as synonyms for Equals + "same_as": SpatialiteNullCheckOperator(func="Equals"), + "exact": SpatialiteNullCheckOperator(func="Equals"), + # Distance predicates + "dwithin": SpatialOperator(func="PtDistWithin"), + } + + disallowed_aggregates = (models.Extent3D,) + + select = "CAST (AsEWKB(%s) AS BLOB)" + + function_names = { + "AsWKB": "St_AsBinary", + "ForcePolygonCW": "ST_ForceLHR", + "FromWKB": "ST_GeomFromWKB", + "FromWKT": "ST_GeomFromText", + "Length": "ST_Length", + "LineLocatePoint": "ST_Line_Locate_Point", + "NumPoints": "ST_NPoints", + "Reverse": "ST_Reverse", + "Scale": "ScaleCoords", + "Translate": "ST_Translate", + "Union": "ST_Union", + } + + @cached_property + def unsupported_functions(self): + unsupported = {"BoundingCircle", "GeometryDistance", "IsEmpty", "MemSize"} + if not self.geom_lib_version(): + unsupported |= {"Azimuth", "GeoHash", "MakeValid"} + return unsupported + + @cached_property + def spatial_version(self): + """Determine the version of the SpatiaLite library.""" + try: + version = self.spatialite_version_tuple()[1:] + except Exception as exc: + raise ImproperlyConfigured( + 'Cannot determine the SpatiaLite version for the "%s" database. ' + "Was the SpatiaLite initialization SQL loaded on this database?" + % (self.connection.settings_dict["NAME"],) + ) from exc + if version < (4, 3, 0): + raise ImproperlyConfigured("GeoDjango supports SpatiaLite 4.3.0 and above.") + return version + + def convert_extent(self, box): + """ + Convert the polygon data received from SpatiaLite to min/max values. + """ + if box is None: + return None + shell = GEOSGeometry(box).shell + xmin, ymin = shell[0][:2] + xmax, ymax = shell[2][:2] + return (xmin, ymin, xmax, ymax) + + def geo_db_type(self, f): + """ + Return None because geometry columns are added via the + `AddGeometryColumn` stored procedure on SpatiaLite. + """ + return None + + def get_distance(self, f, value, lookup_type): + """ + Return the distance parameters for the given geometry field, + lookup value, and lookup type. + """ + if not value: + return [] + value = value[0] + if isinstance(value, Distance): + if f.geodetic(self.connection): + if lookup_type == "dwithin": + raise ValueError( + "Only numeric values of degree units are allowed on " + "geographic DWithin queries." + ) + dist_param = value.m + else: + dist_param = getattr( + value, Distance.unit_attname(f.units_name(self.connection)) + ) + else: + dist_param = value + return [dist_param] + + def _get_spatialite_func(self, func): + """ + Helper routine for calling SpatiaLite functions and returning + their result. + Any error occurring in this method should be handled by the caller. + """ + cursor = self.connection._cursor() + try: + cursor.execute("SELECT %s" % func) + row = cursor.fetchone() + finally: + cursor.close() + return row[0] + + def geos_version(self): + "Return the version of GEOS used by SpatiaLite as a string." + return self._get_spatialite_func("geos_version()") + + def proj_version(self): + """Return the version of the PROJ library used by SpatiaLite.""" + return self._get_spatialite_func("proj4_version()") + + def lwgeom_version(self): + """Return the version of LWGEOM library used by SpatiaLite.""" + return self._get_spatialite_func("lwgeom_version()") + + def rttopo_version(self): + """Return the version of RTTOPO library used by SpatiaLite.""" + return self._get_spatialite_func("rttopo_version()") + + def geom_lib_version(self): + """ + Return the version of the version-dependant geom library used by + SpatiaLite. + """ + if self.spatial_version >= (5,): + return self.rttopo_version() + else: + return self.lwgeom_version() + + def spatialite_version(self): + "Return the SpatiaLite library version as a string." + return self._get_spatialite_func("spatialite_version()") + + def spatialite_version_tuple(self): + """ + Return the SpatiaLite version as a tuple (version string, major, + minor, subminor). + """ + version = self.spatialite_version() + return (version,) + get_version_tuple(version) + + def spatial_aggregate_name(self, agg_name): + """ + Return the spatial aggregate SQL template and function for the + given Aggregate instance. + """ + agg_name = "unionagg" if agg_name.lower() == "union" else agg_name.lower() + return getattr(self, agg_name) + + # Routines for getting the OGC-compliant models. + def geometry_columns(self): + from django.contrib.gis.db.backends.spatialite.models import ( + SpatialiteGeometryColumns, + ) + + return SpatialiteGeometryColumns + + def spatial_ref_sys(self): + from django.contrib.gis.db.backends.spatialite.models import ( + SpatialiteSpatialRefSys, + ) + + return SpatialiteSpatialRefSys + + def get_geometry_converter(self, expression): + geom_class = expression.output_field.geom_class + read = wkb_r().read + + def converter(value, expression, connection): + return None if value is None else GEOSGeometryBase(read(value), geom_class) + + return converter diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/schema.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/schema.py new file mode 100644 index 0000000..fb2c569 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/spatialite/schema.py @@ -0,0 +1,194 @@ +from django.db import DatabaseError +from django.db.backends.sqlite3.schema import DatabaseSchemaEditor + + +class SpatialiteSchemaEditor(DatabaseSchemaEditor): + sql_add_geometry_column = ( + "SELECT AddGeometryColumn(%(table)s, %(column)s, %(srid)s, " + "%(geom_type)s, %(dim)s, %(null)s)" + ) + sql_add_spatial_index = "SELECT CreateSpatialIndex(%(table)s, %(column)s)" + sql_drop_spatial_index = "DROP TABLE idx_%(table)s_%(column)s" + sql_recover_geometry_metadata = ( + "SELECT RecoverGeometryColumn(%(table)s, %(column)s, %(srid)s, " + "%(geom_type)s, %(dim)s)" + ) + sql_remove_geometry_metadata = "SELECT DiscardGeometryColumn(%(table)s, %(column)s)" + sql_discard_geometry_columns = ( + "DELETE FROM %(geom_table)s WHERE f_table_name = %(table)s" + ) + sql_update_geometry_columns = ( + "UPDATE %(geom_table)s SET f_table_name = %(new_table)s " + "WHERE f_table_name = %(old_table)s" + ) + + geometry_tables = [ + "geometry_columns", + "geometry_columns_auth", + "geometry_columns_time", + "geometry_columns_statistics", + ] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.geometry_sql = [] + + def geo_quote_name(self, name): + return self.connection.ops.geo_quote_name(name) + + def column_sql(self, model, field, include_default=False): + from django.contrib.gis.db.models import GeometryField + + if not isinstance(field, GeometryField): + return super().column_sql(model, field, include_default) + + # Geometry columns are created by the `AddGeometryColumn` function + self.geometry_sql.append( + self.sql_add_geometry_column + % { + "table": self.geo_quote_name(model._meta.db_table), + "column": self.geo_quote_name(field.column), + "srid": field.srid, + "geom_type": self.geo_quote_name(field.geom_type), + "dim": field.dim, + "null": int(not field.null), + } + ) + + if field.spatial_index: + self.geometry_sql.append( + self.sql_add_spatial_index + % { + "table": self.quote_name(model._meta.db_table), + "column": self.quote_name(field.column), + } + ) + return None, None + + def remove_geometry_metadata(self, model, field): + self.execute( + self.sql_remove_geometry_metadata + % { + "table": self.quote_name(model._meta.db_table), + "column": self.quote_name(field.column), + } + ) + self.execute( + self.sql_drop_spatial_index + % { + "table": model._meta.db_table, + "column": field.column, + } + ) + + def create_model(self, model): + super().create_model(model) + # Create geometry columns + for sql in self.geometry_sql: + self.execute(sql) + self.geometry_sql = [] + + def delete_model(self, model, **kwargs): + from django.contrib.gis.db.models import GeometryField + + # Drop spatial metadata (dropping the table does not automatically remove them) + for field in model._meta.local_fields: + if isinstance(field, GeometryField): + self.remove_geometry_metadata(model, field) + # Make sure all geom stuff is gone + for geom_table in self.geometry_tables: + try: + self.execute( + self.sql_discard_geometry_columns + % { + "geom_table": geom_table, + "table": self.quote_name(model._meta.db_table), + } + ) + except DatabaseError: + pass + super().delete_model(model, **kwargs) + + def add_field(self, model, field): + from django.contrib.gis.db.models import GeometryField + + if isinstance(field, GeometryField): + # Populate self.geometry_sql + self.column_sql(model, field) + for sql in self.geometry_sql: + self.execute(sql) + self.geometry_sql = [] + else: + super().add_field(model, field) + + def remove_field(self, model, field): + from django.contrib.gis.db.models import GeometryField + + # NOTE: If the field is a geometry field, the table is just recreated, + # the parent's remove_field can't be used cause it will skip the + # recreation if the field does not have a database type. Geometry fields + # do not have a db type cause they are added and removed via stored + # procedures. + if isinstance(field, GeometryField): + self._remake_table(model, delete_field=field) + else: + super().remove_field(model, field) + + def alter_db_table(self, model, old_db_table, new_db_table): + from django.contrib.gis.db.models import GeometryField + + if old_db_table == new_db_table or ( + self.connection.features.ignores_table_name_case + and old_db_table.lower() == new_db_table.lower() + ): + return + # Remove geometry-ness from temp table + for field in model._meta.local_fields: + if isinstance(field, GeometryField): + self.execute( + self.sql_remove_geometry_metadata + % { + "table": self.quote_name(old_db_table), + "column": self.quote_name(field.column), + } + ) + # Alter table + super().alter_db_table(model, old_db_table, new_db_table) + # Repoint any straggler names + for geom_table in self.geometry_tables: + try: + self.execute( + self.sql_update_geometry_columns + % { + "geom_table": geom_table, + "old_table": self.quote_name(old_db_table), + "new_table": self.quote_name(new_db_table), + } + ) + except DatabaseError: + pass + # Re-add geometry-ness and rename spatial index tables + for field in model._meta.local_fields: + if isinstance(field, GeometryField): + self.execute( + self.sql_recover_geometry_metadata + % { + "table": self.geo_quote_name(new_db_table), + "column": self.geo_quote_name(field.column), + "srid": field.srid, + "geom_type": self.geo_quote_name(field.geom_type), + "dim": field.dim, + } + ) + if getattr(field, "spatial_index", False): + self.execute( + self.sql_rename_table + % { + "old_table": self.quote_name( + "idx_%s_%s" % (old_db_table, field.column) + ), + "new_table": self.quote_name( + "idx_%s_%s" % (new_db_table, field.column) + ), + } + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/utils.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/utils.py new file mode 100644 index 0000000..ffb7420 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/backends/utils.py @@ -0,0 +1,28 @@ +""" +A collection of utility routines and classes used by the spatial +backends. +""" + + +class SpatialOperator: + """ + Class encapsulating the behavior specific to a GIS operation (used by lookups). + """ + + sql_template = None + + def __init__(self, op=None, func=None): + self.op = op + self.func = func + + @property + def default_template(self): + if self.func: + return "%(func)s(%(lhs)s, %(rhs)s)" + else: + return "%(lhs)s %(op)s %(rhs)s" + + def as_sql(self, connection, lookup, template_params, sql_params): + sql_template = self.sql_template or lookup.sql_template or self.default_template + template_params.update({"op": self.op, "func": self.func}) + return sql_template % template_params, sql_params diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/models/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/models/__init__.py new file mode 100644 index 0000000..0d5d45d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/models/__init__.py @@ -0,0 +1,30 @@ +from django.db.models import * # NOQA isort:skip +from django.db.models import __all__ as models_all # isort:skip +import django.contrib.gis.db.models.functions # NOQA +import django.contrib.gis.db.models.lookups # NOQA +from django.contrib.gis.db.models.aggregates import * # NOQA +from django.contrib.gis.db.models.aggregates import __all__ as aggregates_all +from django.contrib.gis.db.models.fields import ( + GeometryCollectionField, + GeometryField, + LineStringField, + MultiLineStringField, + MultiPointField, + MultiPolygonField, + PointField, + PolygonField, + RasterField, +) + +__all__ = models_all + aggregates_all +__all__ += [ + "GeometryCollectionField", + "GeometryField", + "LineStringField", + "MultiLineStringField", + "MultiPointField", + "MultiPolygonField", + "PointField", + "PolygonField", + "RasterField", +] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/models/aggregates.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/models/aggregates.py new file mode 100644 index 0000000..7ba2e75 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/models/aggregates.py @@ -0,0 +1,98 @@ +from django.contrib.gis.db.models.fields import ( + ExtentField, + GeometryCollectionField, + GeometryField, + LineStringField, +) +from django.db.models import Aggregate, Func, Value +from django.utils.functional import cached_property + +__all__ = ["Collect", "Extent", "Extent3D", "MakeLine", "Union"] + + +class GeoAggregate(Aggregate): + function = None + is_extent = False + + @cached_property + def output_field(self): + return self.output_field_class(self.source_expressions[0].output_field.srid) + + def as_sql(self, compiler, connection, function=None, **extra_context): + # this will be called again in parent, but it's needed now - before + # we get the spatial_aggregate_name + connection.ops.check_expression_support(self) + return super().as_sql( + compiler, + connection, + function=function or connection.ops.spatial_aggregate_name(self.name), + **extra_context, + ) + + def as_oracle(self, compiler, connection, **extra_context): + if not self.is_extent: + tolerance = self.extra.get("tolerance") or getattr(self, "tolerance", 0.05) + clone = self.copy() + source_expressions = self.get_source_expressions() + if self.filter: + source_expressions.pop() + spatial_type_expr = Func( + *source_expressions, + Value(tolerance), + function="SDOAGGRTYPE", + output_field=self.output_field, + ) + source_expressions = [spatial_type_expr] + if self.filter: + source_expressions.append(self.filter) + clone.set_source_expressions(source_expressions) + return clone.as_sql(compiler, connection, **extra_context) + return self.as_sql(compiler, connection, **extra_context) + + def resolve_expression( + self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False + ): + c = super().resolve_expression(query, allow_joins, reuse, summarize, for_save) + for field in c.get_source_fields(): + if not hasattr(field, "geom_type"): + raise ValueError( + "Geospatial aggregates only allowed on geometry fields." + ) + return c + + +class Collect(GeoAggregate): + name = "Collect" + output_field_class = GeometryCollectionField + + +class Extent(GeoAggregate): + name = "Extent" + is_extent = "2D" + + def __init__(self, expression, **extra): + super().__init__(expression, output_field=ExtentField(), **extra) + + def convert_value(self, value, expression, connection): + return connection.ops.convert_extent(value) + + +class Extent3D(GeoAggregate): + name = "Extent3D" + is_extent = "3D" + + def __init__(self, expression, **extra): + super().__init__(expression, output_field=ExtentField(), **extra) + + def convert_value(self, value, expression, connection): + return connection.ops.convert_extent3d(value) + + +class MakeLine(GeoAggregate): + name = "MakeLine" + output_field_class = LineStringField + + +class Union(GeoAggregate): + name = "Union" + output_field_class = GeometryField diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/models/fields.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/models/fields.py new file mode 100644 index 0000000..889c1cf --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/models/fields.py @@ -0,0 +1,436 @@ +from collections import defaultdict, namedtuple + +from django.contrib.gis import forms, gdal +from django.contrib.gis.db.models.proxy import SpatialProxy +from django.contrib.gis.gdal.error import GDALException +from django.contrib.gis.geos import ( + GeometryCollection, + GEOSException, + GEOSGeometry, + LineString, + MultiLineString, + MultiPoint, + MultiPolygon, + Point, + Polygon, +) +from django.core.exceptions import ImproperlyConfigured +from django.db.models import Field +from django.utils.translation import gettext_lazy as _ + +# Local cache of the spatial_ref_sys table, which holds SRID data for each +# spatial database alias. This cache exists so that the database isn't queried +# for SRID info each time a distance query is constructed. +_srid_cache = defaultdict(dict) + + +SRIDCacheEntry = namedtuple( + "SRIDCacheEntry", ["units", "units_name", "spheroid", "geodetic"] +) + + +def get_srid_info(srid, connection): + """ + Return the units, unit name, and spheroid WKT associated with the + given SRID from the `spatial_ref_sys` (or equivalent) spatial database + table for the given database connection. These results are cached. + """ + from django.contrib.gis.gdal import SpatialReference + + global _srid_cache + + try: + # The SpatialRefSys model for the spatial backend. + SpatialRefSys = connection.ops.spatial_ref_sys() + except NotImplementedError: + SpatialRefSys = None + + alias, get_srs = ( + ( + connection.alias, + lambda srid: SpatialRefSys.objects.using(connection.alias) + .get(srid=srid) + .srs, + ) + if SpatialRefSys + else (None, SpatialReference) + ) + if srid not in _srid_cache[alias]: + srs = get_srs(srid) + units, units_name = srs.units + _srid_cache[alias][srid] = SRIDCacheEntry( + units=units, + units_name=units_name, + spheroid='SPHEROID["%s",%s,%s]' + % (srs["spheroid"], srs.semi_major, srs.inverse_flattening), + geodetic=srs.geographic, + ) + + return _srid_cache[alias][srid] + + +class BaseSpatialField(Field): + """ + The Base GIS Field. + + It's used as a base class for GeometryField and RasterField. Defines + properties that are common to all GIS fields such as the characteristics + of the spatial reference system of the field. + """ + + description = _("The base GIS field.") + empty_strings_allowed = False + + def __init__(self, verbose_name=None, srid=4326, spatial_index=True, **kwargs): + """ + The initialization function for base spatial fields. Takes the following + as keyword arguments: + + srid: + The spatial reference system identifier, an OGC standard. + Defaults to 4326 (WGS84). + + spatial_index: + Indicates whether to create a spatial index. Defaults to True. + Set this instead of 'db_index' for geographic fields since index + creation is different for geometry columns. + """ + + # Setting the index flag with the value of the `spatial_index` keyword. + self.spatial_index = spatial_index + + # Setting the SRID and getting the units. Unit information must be + # easily available in the field instance for distance queries. + self.srid = srid + + # Setting the verbose_name keyword argument with the positional + # first parameter, so this works like normal fields. + kwargs["verbose_name"] = verbose_name + + super().__init__(**kwargs) + + def deconstruct(self): + name, path, args, kwargs = super().deconstruct() + # Always include SRID for less fragility; include spatial index if it's + # not the default value. + kwargs["srid"] = self.srid + if self.spatial_index is not True: + kwargs["spatial_index"] = self.spatial_index + return name, path, args, kwargs + + def db_type(self, connection): + return connection.ops.geo_db_type(self) + + def spheroid(self, connection): + return get_srid_info(self.srid, connection).spheroid + + def units(self, connection): + return get_srid_info(self.srid, connection).units + + def units_name(self, connection): + return get_srid_info(self.srid, connection).units_name + + def geodetic(self, connection): + """ + Return true if this field's SRID corresponds with a coordinate + system that uses non-projected units (e.g., latitude/longitude). + """ + return get_srid_info(self.srid, connection).geodetic + + def get_placeholder(self, value, compiler, connection): + """ + Return the placeholder for the spatial column for the + given value. + """ + return connection.ops.get_geom_placeholder(self, value, compiler) + + def get_srid(self, obj): + """ + Return the default SRID for the given geometry or raster, taking into + account the SRID set for the field. For example, if the input geometry + or raster doesn't have an SRID, then the SRID of the field will be + returned. + """ + srid = obj.srid # SRID of given geometry. + if srid is None or self.srid == -1 or (srid == -1 and self.srid != -1): + return self.srid + else: + return srid + + def get_db_prep_value(self, value, connection, *args, **kwargs): + if value is None: + return None + return connection.ops.Adapter( + super().get_db_prep_value(value, connection, *args, **kwargs), + **( + {"geography": True} + if self.geography and connection.features.supports_geography + else {} + ), + ) + + def get_raster_prep_value(self, value, is_candidate): + """ + Return a GDALRaster if conversion is successful, otherwise return None. + """ + if isinstance(value, gdal.GDALRaster): + return value + elif is_candidate: + try: + return gdal.GDALRaster(value) + except GDALException: + pass + elif isinstance(value, dict): + try: + return gdal.GDALRaster(value) + except GDALException: + raise ValueError( + "Couldn't create spatial object from lookup value '%s'." % value + ) + + def get_prep_value(self, value): + obj = super().get_prep_value(value) + if obj is None: + return None + # When the input is not a geometry or raster, attempt to construct one + # from the given string input. + if isinstance(obj, GEOSGeometry): + pass + else: + # Check if input is a candidate for conversion to raster or geometry. + is_candidate = isinstance(obj, (bytes, str)) or hasattr( + obj, "__geo_interface__" + ) + # Try to convert the input to raster. + raster = self.get_raster_prep_value(obj, is_candidate) + + if raster: + obj = raster + elif is_candidate: + try: + obj = GEOSGeometry(obj) + except (GEOSException, GDALException): + raise ValueError( + "Couldn't create spatial object from lookup value '%s'." % obj + ) + else: + raise ValueError( + "Cannot use object with type %s for a spatial lookup parameter." + % type(obj).__name__ + ) + + # Assigning the SRID value. + obj.srid = self.get_srid(obj) + return obj + + +class GeometryField(BaseSpatialField): + """ + The base Geometry field -- maps to the OpenGIS Specification Geometry type. + """ + + description = _( + "The base Geometry field — maps to the OpenGIS Specification Geometry type." + ) + form_class = forms.GeometryField + # The OpenGIS Geometry name. + geom_type = "GEOMETRY" + geom_class = None + + def __init__( + self, + verbose_name=None, + dim=2, + geography=False, + *, + extent=(-180.0, -90.0, 180.0, 90.0), + tolerance=0.05, + **kwargs, + ): + """ + The initialization function for geometry fields. In addition to the + parameters from BaseSpatialField, it takes the following as keyword + arguments: + + dim: + The number of dimensions for this geometry. Defaults to 2. + + extent: + Customize the extent, in a 4-tuple of WGS 84 coordinates, for the + geometry field entry in the `USER_SDO_GEOM_METADATA` table. Defaults + to (-180.0, -90.0, 180.0, 90.0). + + tolerance: + Define the tolerance, in meters, to use for the geometry field + entry in the `USER_SDO_GEOM_METADATA` table. Defaults to 0.05. + """ + # Setting the dimension of the geometry field. + self.dim = dim + + # Is this a geography rather than a geometry column? + self.geography = geography + + # Oracle-specific private attributes for creating the entry in + # `USER_SDO_GEOM_METADATA` + self._extent = extent + self._tolerance = tolerance + + super().__init__(verbose_name=verbose_name, **kwargs) + + def deconstruct(self): + name, path, args, kwargs = super().deconstruct() + # Include kwargs if they're not the default values. + if self.dim != 2: + kwargs["dim"] = self.dim + if self.geography is not False: + kwargs["geography"] = self.geography + if self._extent != (-180.0, -90.0, 180.0, 90.0): + kwargs["extent"] = self._extent + if self._tolerance != 0.05: + kwargs["tolerance"] = self._tolerance + return name, path, args, kwargs + + def contribute_to_class(self, cls, name, **kwargs): + super().contribute_to_class(cls, name, **kwargs) + + # Setup for lazy-instantiated Geometry object. + setattr( + cls, + self.attname, + SpatialProxy(self.geom_class or GEOSGeometry, self, load_func=GEOSGeometry), + ) + + def formfield(self, **kwargs): + defaults = { + "form_class": self.form_class, + "geom_type": self.geom_type, + "srid": self.srid, + **kwargs, + } + if self.dim > 2 and not getattr( + defaults["form_class"].widget, "supports_3d", False + ): + defaults.setdefault("widget", forms.Textarea) + return super().formfield(**defaults) + + def select_format(self, compiler, sql, params): + """ + Return the selection format string, depending on the requirements + of the spatial backend. For example, Oracle and MySQL require custom + selection formats in order to retrieve geometries in OGC WKB. + """ + if not compiler.query.subquery: + return compiler.connection.ops.select % sql, params + return sql, params + + +# The OpenGIS Geometry Type Fields +class PointField(GeometryField): + geom_type = "POINT" + geom_class = Point + form_class = forms.PointField + description = _("Point") + + +class LineStringField(GeometryField): + geom_type = "LINESTRING" + geom_class = LineString + form_class = forms.LineStringField + description = _("Line string") + + +class PolygonField(GeometryField): + geom_type = "POLYGON" + geom_class = Polygon + form_class = forms.PolygonField + description = _("Polygon") + + +class MultiPointField(GeometryField): + geom_type = "MULTIPOINT" + geom_class = MultiPoint + form_class = forms.MultiPointField + description = _("Multi-point") + + +class MultiLineStringField(GeometryField): + geom_type = "MULTILINESTRING" + geom_class = MultiLineString + form_class = forms.MultiLineStringField + description = _("Multi-line string") + + +class MultiPolygonField(GeometryField): + geom_type = "MULTIPOLYGON" + geom_class = MultiPolygon + form_class = forms.MultiPolygonField + description = _("Multi polygon") + + +class GeometryCollectionField(GeometryField): + geom_type = "GEOMETRYCOLLECTION" + geom_class = GeometryCollection + form_class = forms.GeometryCollectionField + description = _("Geometry collection") + + +class ExtentField(Field): + "Used as a return value from an extent aggregate" + + description = _("Extent Aggregate Field") + + def get_internal_type(self): + return "ExtentField" + + def select_format(self, compiler, sql, params): + select = compiler.connection.ops.select_extent + return select % sql if select else sql, params + + +class RasterField(BaseSpatialField): + """ + Raster field for GeoDjango -- evaluates into GDALRaster objects. + """ + + description = _("Raster Field") + geom_type = "RASTER" + geography = False + + def _check_connection(self, connection): + # Make sure raster fields are used only on backends with raster support. + if ( + not connection.features.gis_enabled + or not connection.features.supports_raster + ): + raise ImproperlyConfigured( + "Raster fields require backends with raster support." + ) + + def db_type(self, connection): + self._check_connection(connection) + return super().db_type(connection) + + def from_db_value(self, value, expression, connection): + return connection.ops.parse_raster(value) + + def contribute_to_class(self, cls, name, **kwargs): + super().contribute_to_class(cls, name, **kwargs) + # Setup for lazy-instantiated Raster object. For large querysets, the + # instantiation of all GDALRasters can potentially be expensive. This + # delays the instantiation of the objects to the moment of evaluation + # of the raster attribute. + setattr(cls, self.attname, SpatialProxy(gdal.GDALRaster, self)) + + def get_transform(self, name): + from django.contrib.gis.db.models.lookups import RasterBandTransform + + try: + band_index = int(name) + return type( + "SpecificRasterBandTransform", + (RasterBandTransform,), + {"band_index": band_index}, + ) + except ValueError: + pass + return super().get_transform(name) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/models/functions.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/models/functions.py new file mode 100644 index 0000000..bd02e37 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/models/functions.py @@ -0,0 +1,568 @@ +from decimal import Decimal + +from django.contrib.gis.db.models.fields import BaseSpatialField, GeometryField +from django.contrib.gis.db.models.sql import AreaField, DistanceField +from django.contrib.gis.geos import GEOSGeometry +from django.core.exceptions import FieldError +from django.db import NotSupportedError +from django.db.models import ( + BinaryField, + BooleanField, + FloatField, + Func, + IntegerField, + TextField, + Transform, + Value, +) +from django.db.models.functions import Cast +from django.utils.functional import cached_property + +NUMERIC_TYPES = (int, float, Decimal) + + +class GeoFuncMixin: + function = None + geom_param_pos = (0,) + + def __init__(self, *expressions, **extra): + super().__init__(*expressions, **extra) + + # Ensure that value expressions are geometric. + for pos in self.geom_param_pos: + expr = self.source_expressions[pos] + if not isinstance(expr, Value): + continue + try: + output_field = expr.output_field + except FieldError: + output_field = None + geom = expr.value + if ( + not isinstance(geom, GEOSGeometry) + or output_field + and not isinstance(output_field, GeometryField) + ): + raise TypeError( + "%s function requires a geometric argument in position %d." + % (self.name, pos + 1) + ) + if not geom.srid and not output_field: + raise ValueError("SRID is required for all geometries.") + if not output_field: + self.source_expressions[pos] = Value( + geom, output_field=GeometryField(srid=geom.srid) + ) + + @property + def name(self): + return self.__class__.__name__ + + @cached_property + def geo_field(self): + return self.source_expressions[self.geom_param_pos[0]].field + + def as_sql(self, compiler, connection, function=None, **extra_context): + if self.function is None and function is None: + function = connection.ops.spatial_function_name(self.name) + return super().as_sql(compiler, connection, function=function, **extra_context) + + def resolve_expression(self, *args, **kwargs): + res = super().resolve_expression(*args, **kwargs) + if not self.geom_param_pos: + return res + + # Ensure that expressions are geometric. + source_fields = res.get_source_fields() + for pos in self.geom_param_pos: + field = source_fields[pos] + if not isinstance(field, GeometryField): + raise TypeError( + "%s function requires a GeometryField in position %s, got %s." + % ( + self.name, + pos + 1, + type(field).__name__, + ) + ) + + base_srid = res.geo_field.srid + for pos in self.geom_param_pos[1:]: + expr = res.source_expressions[pos] + expr_srid = expr.output_field.srid + if expr_srid != base_srid: + # Automatic SRID conversion so objects are comparable. + res.source_expressions[pos] = Transform( + expr, base_srid + ).resolve_expression(*args, **kwargs) + return res + + def _handle_param(self, value, param_name="", check_types=None): + if not hasattr(value, "resolve_expression"): + if check_types and not isinstance(value, check_types): + raise TypeError( + "The %s parameter has the wrong type: should be %s." + % (param_name, check_types) + ) + return value + + +class GeoFunc(GeoFuncMixin, Func): + pass + + +class GeomOutputGeoFunc(GeoFunc): + @cached_property + def output_field(self): + return GeometryField(srid=self.geo_field.srid) + + +class SQLiteDecimalToFloatMixin: + """ + By default, Decimal values are converted to str by the SQLite backend, which + is not acceptable by the GIS functions expecting numeric values. + """ + + def as_sqlite(self, compiler, connection, **extra_context): + copy = self.copy() + copy.set_source_expressions( + [ + Value(float(expr.value)) + if hasattr(expr, "value") and isinstance(expr.value, Decimal) + else expr + for expr in copy.get_source_expressions() + ] + ) + return copy.as_sql(compiler, connection, **extra_context) + + +class OracleToleranceMixin: + tolerance = 0.05 + + def as_oracle(self, compiler, connection, **extra_context): + tolerance = Value( + self._handle_param( + self.extra.get("tolerance", self.tolerance), + "tolerance", + NUMERIC_TYPES, + ) + ) + clone = self.copy() + clone.set_source_expressions([*self.get_source_expressions(), tolerance]) + return clone.as_sql(compiler, connection, **extra_context) + + +class Area(OracleToleranceMixin, GeoFunc): + arity = 1 + + @cached_property + def output_field(self): + return AreaField(self.geo_field) + + def as_sql(self, compiler, connection, **extra_context): + if not connection.features.supports_area_geodetic and self.geo_field.geodetic( + connection + ): + raise NotSupportedError( + "Area on geodetic coordinate systems not supported." + ) + return super().as_sql(compiler, connection, **extra_context) + + def as_sqlite(self, compiler, connection, **extra_context): + if self.geo_field.geodetic(connection): + extra_context["template"] = "%(function)s(%(expressions)s, %(spheroid)d)" + extra_context["spheroid"] = True + return self.as_sql(compiler, connection, **extra_context) + + +class Azimuth(GeoFunc): + output_field = FloatField() + arity = 2 + geom_param_pos = (0, 1) + + +class AsGeoJSON(GeoFunc): + output_field = TextField() + + def __init__(self, expression, bbox=False, crs=False, precision=8, **extra): + expressions = [expression] + if precision is not None: + expressions.append(self._handle_param(precision, "precision", int)) + options = 0 + if crs and bbox: + options = 3 + elif bbox: + options = 1 + elif crs: + options = 2 + expressions.append(options) + super().__init__(*expressions, **extra) + + def as_oracle(self, compiler, connection, **extra_context): + source_expressions = self.get_source_expressions() + clone = self.copy() + clone.set_source_expressions(source_expressions[:1]) + return super(AsGeoJSON, clone).as_sql(compiler, connection, **extra_context) + + +class AsGML(GeoFunc): + geom_param_pos = (1,) + output_field = TextField() + + def __init__(self, expression, version=2, precision=8, **extra): + expressions = [version, expression] + if precision is not None: + expressions.append(self._handle_param(precision, "precision", int)) + super().__init__(*expressions, **extra) + + def as_oracle(self, compiler, connection, **extra_context): + source_expressions = self.get_source_expressions() + version = source_expressions[0] + clone = self.copy() + clone.set_source_expressions([source_expressions[1]]) + extra_context["function"] = ( + "SDO_UTIL.TO_GML311GEOMETRY" + if version.value == 3 + else "SDO_UTIL.TO_GMLGEOMETRY" + ) + return super(AsGML, clone).as_sql(compiler, connection, **extra_context) + + +class AsKML(GeoFunc): + output_field = TextField() + + def __init__(self, expression, precision=8, **extra): + expressions = [expression] + if precision is not None: + expressions.append(self._handle_param(precision, "precision", int)) + super().__init__(*expressions, **extra) + + +class AsSVG(GeoFunc): + output_field = TextField() + + def __init__(self, expression, relative=False, precision=8, **extra): + relative = ( + relative if hasattr(relative, "resolve_expression") else int(relative) + ) + expressions = [ + expression, + relative, + self._handle_param(precision, "precision", int), + ] + super().__init__(*expressions, **extra) + + +class AsWKB(GeoFunc): + output_field = BinaryField() + arity = 1 + + +class AsWKT(GeoFunc): + output_field = TextField() + arity = 1 + + +class BoundingCircle(OracleToleranceMixin, GeomOutputGeoFunc): + def __init__(self, expression, num_seg=48, **extra): + super().__init__(expression, num_seg, **extra) + + def as_oracle(self, compiler, connection, **extra_context): + clone = self.copy() + clone.set_source_expressions([self.get_source_expressions()[0]]) + return super(BoundingCircle, clone).as_oracle( + compiler, connection, **extra_context + ) + + +class Centroid(OracleToleranceMixin, GeomOutputGeoFunc): + arity = 1 + + +class ClosestPoint(GeomOutputGeoFunc): + arity = 2 + geom_param_pos = (0, 1) + + +class Difference(OracleToleranceMixin, GeomOutputGeoFunc): + arity = 2 + geom_param_pos = (0, 1) + + +class DistanceResultMixin: + @cached_property + def output_field(self): + return DistanceField(self.geo_field) + + def source_is_geography(self): + return self.geo_field.geography and self.geo_field.srid == 4326 + + +class Distance(DistanceResultMixin, OracleToleranceMixin, GeoFunc): + geom_param_pos = (0, 1) + spheroid = None + + def __init__(self, expr1, expr2, spheroid=None, **extra): + expressions = [expr1, expr2] + if spheroid is not None: + self.spheroid = self._handle_param(spheroid, "spheroid", bool) + super().__init__(*expressions, **extra) + + def as_postgresql(self, compiler, connection, **extra_context): + clone = self.copy() + function = None + expr2 = clone.source_expressions[1] + geography = self.source_is_geography() + if expr2.output_field.geography != geography: + if isinstance(expr2, Value): + expr2.output_field.geography = geography + else: + clone.source_expressions[1] = Cast( + expr2, + GeometryField(srid=expr2.output_field.srid, geography=geography), + ) + + if not geography and self.geo_field.geodetic(connection): + # Geometry fields with geodetic (lon/lat) coordinates need special + # distance functions. + if self.spheroid: + # DistanceSpheroid is more accurate and resource intensive than + # DistanceSphere. + function = connection.ops.spatial_function_name("DistanceSpheroid") + # Replace boolean param by the real spheroid of the base field + clone.source_expressions.append( + Value(self.geo_field.spheroid(connection)) + ) + else: + function = connection.ops.spatial_function_name("DistanceSphere") + return super(Distance, clone).as_sql( + compiler, connection, function=function, **extra_context + ) + + def as_sqlite(self, compiler, connection, **extra_context): + if self.geo_field.geodetic(connection): + # SpatiaLite returns NULL instead of zero on geodetic coordinates + extra_context[ + "template" + ] = "COALESCE(%(function)s(%(expressions)s, %(spheroid)s), 0)" + extra_context["spheroid"] = int(bool(self.spheroid)) + return super().as_sql(compiler, connection, **extra_context) + + +class Envelope(GeomOutputGeoFunc): + arity = 1 + + +class ForcePolygonCW(GeomOutputGeoFunc): + arity = 1 + + +class FromWKB(GeoFunc): + output_field = GeometryField(srid=0) + arity = 1 + geom_param_pos = () + + +class FromWKT(GeoFunc): + output_field = GeometryField(srid=0) + arity = 1 + geom_param_pos = () + + +class GeoHash(GeoFunc): + output_field = TextField() + + def __init__(self, expression, precision=None, **extra): + expressions = [expression] + if precision is not None: + expressions.append(self._handle_param(precision, "precision", int)) + super().__init__(*expressions, **extra) + + def as_mysql(self, compiler, connection, **extra_context): + clone = self.copy() + # If no precision is provided, set it to the maximum. + if len(clone.source_expressions) < 2: + clone.source_expressions.append(Value(100)) + return clone.as_sql(compiler, connection, **extra_context) + + +class GeometryDistance(GeoFunc): + output_field = FloatField() + arity = 2 + function = "" + arg_joiner = " <-> " + geom_param_pos = (0, 1) + + +class Intersection(OracleToleranceMixin, GeomOutputGeoFunc): + arity = 2 + geom_param_pos = (0, 1) + + +@BaseSpatialField.register_lookup +class IsEmpty(GeoFuncMixin, Transform): + lookup_name = "isempty" + output_field = BooleanField() + + +@BaseSpatialField.register_lookup +class IsValid(OracleToleranceMixin, GeoFuncMixin, Transform): + lookup_name = "isvalid" + output_field = BooleanField() + + def as_oracle(self, compiler, connection, **extra_context): + sql, params = super().as_oracle(compiler, connection, **extra_context) + return "CASE %s WHEN 'TRUE' THEN 1 ELSE 0 END" % sql, params + + +class Length(DistanceResultMixin, OracleToleranceMixin, GeoFunc): + def __init__(self, expr1, spheroid=True, **extra): + self.spheroid = spheroid + super().__init__(expr1, **extra) + + def as_sql(self, compiler, connection, **extra_context): + if ( + self.geo_field.geodetic(connection) + and not connection.features.supports_length_geodetic + ): + raise NotSupportedError( + "This backend doesn't support Length on geodetic fields" + ) + return super().as_sql(compiler, connection, **extra_context) + + def as_postgresql(self, compiler, connection, **extra_context): + clone = self.copy() + function = None + if self.source_is_geography(): + clone.source_expressions.append(Value(self.spheroid)) + elif self.geo_field.geodetic(connection): + # Geometry fields with geodetic (lon/lat) coordinates need length_spheroid + function = connection.ops.spatial_function_name("LengthSpheroid") + clone.source_expressions.append(Value(self.geo_field.spheroid(connection))) + else: + dim = min(f.dim for f in self.get_source_fields() if f) + if dim > 2: + function = connection.ops.length3d + return super(Length, clone).as_sql( + compiler, connection, function=function, **extra_context + ) + + def as_sqlite(self, compiler, connection, **extra_context): + function = None + if self.geo_field.geodetic(connection): + function = "GeodesicLength" if self.spheroid else "GreatCircleLength" + return super().as_sql(compiler, connection, function=function, **extra_context) + + +class LineLocatePoint(GeoFunc): + output_field = FloatField() + arity = 2 + geom_param_pos = (0, 1) + + +class MakeValid(GeomOutputGeoFunc): + pass + + +class MemSize(GeoFunc): + output_field = IntegerField() + arity = 1 + + +class NumGeometries(GeoFunc): + output_field = IntegerField() + arity = 1 + + +class NumPoints(GeoFunc): + output_field = IntegerField() + arity = 1 + + +class Perimeter(DistanceResultMixin, OracleToleranceMixin, GeoFunc): + arity = 1 + + def as_postgresql(self, compiler, connection, **extra_context): + function = None + if self.geo_field.geodetic(connection) and not self.source_is_geography(): + raise NotSupportedError( + "ST_Perimeter cannot use a non-projected non-geography field." + ) + dim = min(f.dim for f in self.get_source_fields()) + if dim > 2: + function = connection.ops.perimeter3d + return super().as_sql(compiler, connection, function=function, **extra_context) + + def as_sqlite(self, compiler, connection, **extra_context): + if self.geo_field.geodetic(connection): + raise NotSupportedError("Perimeter cannot use a non-projected field.") + return super().as_sql(compiler, connection, **extra_context) + + +class PointOnSurface(OracleToleranceMixin, GeomOutputGeoFunc): + arity = 1 + + +class Reverse(GeoFunc): + arity = 1 + + +class Scale(SQLiteDecimalToFloatMixin, GeomOutputGeoFunc): + def __init__(self, expression, x, y, z=0.0, **extra): + expressions = [ + expression, + self._handle_param(x, "x", NUMERIC_TYPES), + self._handle_param(y, "y", NUMERIC_TYPES), + ] + if z != 0.0: + expressions.append(self._handle_param(z, "z", NUMERIC_TYPES)) + super().__init__(*expressions, **extra) + + +class SnapToGrid(SQLiteDecimalToFloatMixin, GeomOutputGeoFunc): + def __init__(self, expression, *args, **extra): + nargs = len(args) + expressions = [expression] + if nargs in (1, 2): + expressions.extend( + [self._handle_param(arg, "", NUMERIC_TYPES) for arg in args] + ) + elif nargs == 4: + # Reverse origin and size param ordering + expressions += [ + *(self._handle_param(arg, "", NUMERIC_TYPES) for arg in args[2:]), + *(self._handle_param(arg, "", NUMERIC_TYPES) for arg in args[0:2]), + ] + else: + raise ValueError("Must provide 1, 2, or 4 arguments to `SnapToGrid`.") + super().__init__(*expressions, **extra) + + +class SymDifference(OracleToleranceMixin, GeomOutputGeoFunc): + arity = 2 + geom_param_pos = (0, 1) + + +class Transform(GeomOutputGeoFunc): + def __init__(self, expression, srid, **extra): + expressions = [ + expression, + self._handle_param(srid, "srid", int), + ] + if "output_field" not in extra: + extra["output_field"] = GeometryField(srid=srid) + super().__init__(*expressions, **extra) + + +class Translate(Scale): + def as_sqlite(self, compiler, connection, **extra_context): + clone = self.copy() + if len(self.source_expressions) < 4: + # Always provide the z parameter for ST_Translate + clone.source_expressions.append(Value(0)) + return super(Translate, clone).as_sqlite(compiler, connection, **extra_context) + + +class Union(OracleToleranceMixin, GeomOutputGeoFunc): + arity = 2 + geom_param_pos = (0, 1) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/models/lookups.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/models/lookups.py new file mode 100644 index 0000000..b9686fa --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/models/lookups.py @@ -0,0 +1,395 @@ +from django.contrib.gis.db.models.fields import BaseSpatialField +from django.contrib.gis.measure import Distance +from django.db import NotSupportedError +from django.db.models import Expression, Lookup, Transform +from django.db.models.sql.query import Query +from django.utils.regex_helper import _lazy_re_compile + + +class RasterBandTransform(Transform): + def as_sql(self, compiler, connection): + return compiler.compile(self.lhs) + + +class GISLookup(Lookup): + sql_template = None + transform_func = None + distance = False + band_rhs = None + band_lhs = None + + def __init__(self, lhs, rhs): + rhs, *self.rhs_params = rhs if isinstance(rhs, (list, tuple)) else [rhs] + super().__init__(lhs, rhs) + self.template_params = {} + self.process_rhs_params() + + def process_rhs_params(self): + if self.rhs_params: + # Check if a band index was passed in the query argument. + if len(self.rhs_params) == (2 if self.lookup_name == "relate" else 1): + self.process_band_indices() + elif len(self.rhs_params) > 1: + raise ValueError("Tuple too long for lookup %s." % self.lookup_name) + elif isinstance(self.lhs, RasterBandTransform): + self.process_band_indices(only_lhs=True) + + def process_band_indices(self, only_lhs=False): + """ + Extract the lhs band index from the band transform class and the rhs + band index from the input tuple. + """ + # PostGIS band indices are 1-based, so the band index needs to be + # increased to be consistent with the GDALRaster band indices. + if only_lhs: + self.band_rhs = 1 + self.band_lhs = self.lhs.band_index + 1 + return + + if isinstance(self.lhs, RasterBandTransform): + self.band_lhs = self.lhs.band_index + 1 + else: + self.band_lhs = 1 + + self.band_rhs, *self.rhs_params = self.rhs_params + + def get_db_prep_lookup(self, value, connection): + # get_db_prep_lookup is called by process_rhs from super class + return ("%s", [connection.ops.Adapter(value)]) + + def process_rhs(self, compiler, connection): + if isinstance(self.rhs, Query): + # If rhs is some Query, don't touch it. + return super().process_rhs(compiler, connection) + if isinstance(self.rhs, Expression): + self.rhs = self.rhs.resolve_expression(compiler.query) + rhs, rhs_params = super().process_rhs(compiler, connection) + placeholder = connection.ops.get_geom_placeholder( + self.lhs.output_field, self.rhs, compiler + ) + return placeholder % rhs, rhs_params + + def get_rhs_op(self, connection, rhs): + # Unlike BuiltinLookup, the GIS get_rhs_op() implementation should return + # an object (SpatialOperator) with an as_sql() method to allow for more + # complex computations (where the lhs part can be mixed in). + return connection.ops.gis_operators[self.lookup_name] + + def as_sql(self, compiler, connection): + lhs_sql, lhs_params = self.process_lhs(compiler, connection) + rhs_sql, rhs_params = self.process_rhs(compiler, connection) + sql_params = (*lhs_params, *rhs_params) + + template_params = { + "lhs": lhs_sql, + "rhs": rhs_sql, + "value": "%s", + **self.template_params, + } + rhs_op = self.get_rhs_op(connection, rhs_sql) + return rhs_op.as_sql(connection, self, template_params, sql_params) + + +# ------------------ +# Geometry operators +# ------------------ + + +@BaseSpatialField.register_lookup +class OverlapsLeftLookup(GISLookup): + """ + The overlaps_left operator returns true if A's bounding box overlaps or is to the + left of B's bounding box. + """ + + lookup_name = "overlaps_left" + + +@BaseSpatialField.register_lookup +class OverlapsRightLookup(GISLookup): + """ + The 'overlaps_right' operator returns true if A's bounding box overlaps or is to the + right of B's bounding box. + """ + + lookup_name = "overlaps_right" + + +@BaseSpatialField.register_lookup +class OverlapsBelowLookup(GISLookup): + """ + The 'overlaps_below' operator returns true if A's bounding box overlaps or is below + B's bounding box. + """ + + lookup_name = "overlaps_below" + + +@BaseSpatialField.register_lookup +class OverlapsAboveLookup(GISLookup): + """ + The 'overlaps_above' operator returns true if A's bounding box overlaps or is above + B's bounding box. + """ + + lookup_name = "overlaps_above" + + +@BaseSpatialField.register_lookup +class LeftLookup(GISLookup): + """ + The 'left' operator returns true if A's bounding box is strictly to the left + of B's bounding box. + """ + + lookup_name = "left" + + +@BaseSpatialField.register_lookup +class RightLookup(GISLookup): + """ + The 'right' operator returns true if A's bounding box is strictly to the right + of B's bounding box. + """ + + lookup_name = "right" + + +@BaseSpatialField.register_lookup +class StrictlyBelowLookup(GISLookup): + """ + The 'strictly_below' operator returns true if A's bounding box is strictly below B's + bounding box. + """ + + lookup_name = "strictly_below" + + +@BaseSpatialField.register_lookup +class StrictlyAboveLookup(GISLookup): + """ + The 'strictly_above' operator returns true if A's bounding box is strictly above B's + bounding box. + """ + + lookup_name = "strictly_above" + + +@BaseSpatialField.register_lookup +class SameAsLookup(GISLookup): + """ + The "~=" operator is the "same as" operator. It tests actual geometric + equality of two features. So if A and B are the same feature, + vertex-by-vertex, the operator returns true. + """ + + lookup_name = "same_as" + + +BaseSpatialField.register_lookup(SameAsLookup, "exact") + + +@BaseSpatialField.register_lookup +class BBContainsLookup(GISLookup): + """ + The 'bbcontains' operator returns true if A's bounding box completely contains + by B's bounding box. + """ + + lookup_name = "bbcontains" + + +@BaseSpatialField.register_lookup +class BBOverlapsLookup(GISLookup): + """ + The 'bboverlaps' operator returns true if A's bounding box overlaps B's + bounding box. + """ + + lookup_name = "bboverlaps" + + +@BaseSpatialField.register_lookup +class ContainedLookup(GISLookup): + """ + The 'contained' operator returns true if A's bounding box is completely contained + by B's bounding box. + """ + + lookup_name = "contained" + + +# ------------------ +# Geometry functions +# ------------------ + + +@BaseSpatialField.register_lookup +class ContainsLookup(GISLookup): + lookup_name = "contains" + + +@BaseSpatialField.register_lookup +class ContainsProperlyLookup(GISLookup): + lookup_name = "contains_properly" + + +@BaseSpatialField.register_lookup +class CoveredByLookup(GISLookup): + lookup_name = "coveredby" + + +@BaseSpatialField.register_lookup +class CoversLookup(GISLookup): + lookup_name = "covers" + + +@BaseSpatialField.register_lookup +class CrossesLookup(GISLookup): + lookup_name = "crosses" + + +@BaseSpatialField.register_lookup +class DisjointLookup(GISLookup): + lookup_name = "disjoint" + + +@BaseSpatialField.register_lookup +class EqualsLookup(GISLookup): + lookup_name = "equals" + + +@BaseSpatialField.register_lookup +class IntersectsLookup(GISLookup): + lookup_name = "intersects" + + +@BaseSpatialField.register_lookup +class OverlapsLookup(GISLookup): + lookup_name = "overlaps" + + +@BaseSpatialField.register_lookup +class RelateLookup(GISLookup): + lookup_name = "relate" + sql_template = "%(func)s(%(lhs)s, %(rhs)s, %%s)" + pattern_regex = _lazy_re_compile(r"^[012TF*]{9}$") + + def process_rhs(self, compiler, connection): + # Check the pattern argument + pattern = self.rhs_params[0] + backend_op = connection.ops.gis_operators[self.lookup_name] + if hasattr(backend_op, "check_relate_argument"): + backend_op.check_relate_argument(pattern) + elif not isinstance(pattern, str) or not self.pattern_regex.match(pattern): + raise ValueError('Invalid intersection matrix pattern "%s".' % pattern) + sql, params = super().process_rhs(compiler, connection) + return sql, params + [pattern] + + +@BaseSpatialField.register_lookup +class TouchesLookup(GISLookup): + lookup_name = "touches" + + +@BaseSpatialField.register_lookup +class WithinLookup(GISLookup): + lookup_name = "within" + + +class DistanceLookupBase(GISLookup): + distance = True + sql_template = "%(func)s(%(lhs)s, %(rhs)s) %(op)s %(value)s" + + def process_rhs_params(self): + if not 1 <= len(self.rhs_params) <= 3: + raise ValueError( + "2, 3, or 4-element tuple required for '%s' lookup." % self.lookup_name + ) + elif len(self.rhs_params) == 3 and self.rhs_params[2] != "spheroid": + raise ValueError( + "For 4-element tuples the last argument must be the 'spheroid' " + "directive." + ) + + # Check if the second parameter is a band index. + if len(self.rhs_params) > 1 and self.rhs_params[1] != "spheroid": + self.process_band_indices() + + def process_distance(self, compiler, connection): + dist_param = self.rhs_params[0] + return ( + compiler.compile(dist_param.resolve_expression(compiler.query)) + if hasattr(dist_param, "resolve_expression") + else ( + "%s", + connection.ops.get_distance( + self.lhs.output_field, self.rhs_params, self.lookup_name + ), + ) + ) + + +@BaseSpatialField.register_lookup +class DWithinLookup(DistanceLookupBase): + lookup_name = "dwithin" + sql_template = "%(func)s(%(lhs)s, %(rhs)s, %(value)s)" + + def process_distance(self, compiler, connection): + dist_param = self.rhs_params[0] + if ( + not connection.features.supports_dwithin_distance_expr + and hasattr(dist_param, "resolve_expression") + and not isinstance(dist_param, Distance) + ): + raise NotSupportedError( + "This backend does not support expressions for specifying " + "distance in the dwithin lookup." + ) + return super().process_distance(compiler, connection) + + def process_rhs(self, compiler, connection): + dist_sql, dist_params = self.process_distance(compiler, connection) + self.template_params["value"] = dist_sql + rhs_sql, params = super().process_rhs(compiler, connection) + return rhs_sql, params + dist_params + + +class DistanceLookupFromFunction(DistanceLookupBase): + def as_sql(self, compiler, connection): + spheroid = ( + len(self.rhs_params) == 2 and self.rhs_params[-1] == "spheroid" + ) or None + distance_expr = connection.ops.distance_expr_for_lookup( + self.lhs, self.rhs, spheroid=spheroid + ) + sql, params = compiler.compile(distance_expr.resolve_expression(compiler.query)) + dist_sql, dist_params = self.process_distance(compiler, connection) + return ( + "%(func)s %(op)s %(dist)s" % {"func": sql, "op": self.op, "dist": dist_sql}, + params + dist_params, + ) + + +@BaseSpatialField.register_lookup +class DistanceGTLookup(DistanceLookupFromFunction): + lookup_name = "distance_gt" + op = ">" + + +@BaseSpatialField.register_lookup +class DistanceGTELookup(DistanceLookupFromFunction): + lookup_name = "distance_gte" + op = ">=" + + +@BaseSpatialField.register_lookup +class DistanceLTLookup(DistanceLookupFromFunction): + lookup_name = "distance_lt" + op = "<" + + +@BaseSpatialField.register_lookup +class DistanceLTELookup(DistanceLookupFromFunction): + lookup_name = "distance_lte" + op = "<=" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/models/proxy.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/models/proxy.py new file mode 100644 index 0000000..4db365d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/models/proxy.py @@ -0,0 +1,83 @@ +""" +The SpatialProxy object allows for lazy-geometries and lazy-rasters. The proxy +uses Python descriptors for instantiating and setting Geometry or Raster +objects corresponding to geographic model fields. + +Thanks to Robert Coup for providing this functionality (see #4322). +""" +from django.db.models.query_utils import DeferredAttribute + + +class SpatialProxy(DeferredAttribute): + def __init__(self, klass, field, load_func=None): + """ + Initialize on the given Geometry or Raster class (not an instance) + and the corresponding field. + """ + self._klass = klass + self._load_func = load_func or klass + super().__init__(field) + + def __get__(self, instance, cls=None): + """ + Retrieve the geometry or raster, initializing it using the + corresponding class specified during initialization and the value of + the field. Currently, GEOS or OGR geometries as well as GDALRasters are + supported. + """ + if instance is None: + # Accessed on a class, not an instance + return self + + # Getting the value of the field. + try: + geo_value = instance.__dict__[self.field.attname] + except KeyError: + geo_value = super().__get__(instance, cls) + + if isinstance(geo_value, self._klass): + geo_obj = geo_value + elif (geo_value is None) or (geo_value == ""): + geo_obj = None + else: + # Otherwise, a geometry or raster object is built using the field's + # contents, and the model's corresponding attribute is set. + geo_obj = self._load_func(geo_value) + setattr(instance, self.field.attname, geo_obj) + return geo_obj + + def __set__(self, instance, value): + """ + Retrieve the proxied geometry or raster with the corresponding class + specified during initialization. + + To set geometries, use values of None, HEXEWKB, or WKT. + To set rasters, use JSON or dict values. + """ + # The geographic type of the field. + gtype = self.field.geom_type + + if gtype == "RASTER" and ( + value is None or isinstance(value, (str, dict, self._klass)) + ): + # For raster fields, ensure input is None or a string, dict, or + # raster instance. + pass + elif isinstance(value, self._klass): + # The geometry type must match that of the field -- unless the + # general GeometryField is used. + if value.srid is None: + # Assigning the field SRID if the geometry has no SRID. + value.srid = self.field.srid + elif value is None or isinstance(value, (str, memoryview)): + # Set geometries with None, WKT, HEX, or WKB + pass + else: + raise TypeError( + "Cannot set %s SpatialProxy (%s) with value of type: %s" + % (instance.__class__.__name__, gtype, type(value)) + ) + + # Setting the objects dictionary with the value, and returning. + instance.__dict__[self.field.attname] = value + return value diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/models/sql/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/models/sql/__init__.py new file mode 100644 index 0000000..1376e8d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/models/sql/__init__.py @@ -0,0 +1,6 @@ +from django.contrib.gis.db.models.sql.conversion import AreaField, DistanceField + +__all__ = [ + "AreaField", + "DistanceField", +] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/models/sql/conversion.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/models/sql/conversion.py new file mode 100644 index 0000000..be71231 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/db/models/sql/conversion.py @@ -0,0 +1,73 @@ +""" +This module holds simple classes to convert geospatial values from the +database. +""" +from decimal import Decimal + +from django.contrib.gis.measure import Area, Distance +from django.db import models + + +class AreaField(models.FloatField): + "Wrapper for Area values." + + def __init__(self, geo_field): + super().__init__() + self.geo_field = geo_field + + def get_prep_value(self, value): + if not isinstance(value, Area): + raise ValueError("AreaField only accepts Area measurement objects.") + return value + + def get_db_prep_value(self, value, connection, prepared=False): + if value is None: + return + area_att = connection.ops.get_area_att_for_field(self.geo_field) + return getattr(value, area_att) if area_att else value + + def from_db_value(self, value, expression, connection): + if value is None: + return + # If the database returns a Decimal, convert it to a float as expected + # by the Python geometric objects. + if isinstance(value, Decimal): + value = float(value) + # If the units are known, convert value into area measure. + area_att = connection.ops.get_area_att_for_field(self.geo_field) + return Area(**{area_att: value}) if area_att else value + + def get_internal_type(self): + return "AreaField" + + +class DistanceField(models.FloatField): + "Wrapper for Distance values." + + def __init__(self, geo_field): + super().__init__() + self.geo_field = geo_field + + def get_prep_value(self, value): + if isinstance(value, Distance): + return value + return super().get_prep_value(value) + + def get_db_prep_value(self, value, connection, prepared=False): + if not isinstance(value, Distance): + return value + distance_att = connection.ops.get_distance_att_for_field(self.geo_field) + if not distance_att: + raise ValueError( + "Distance measure is supplied, but units are unknown for result." + ) + return getattr(value, distance_att) + + def from_db_value(self, value, expression, connection): + if value is None: + return + distance_att = connection.ops.get_distance_att_for_field(self.geo_field) + return Distance(**{distance_att: value}) if distance_att else value + + def get_internal_type(self): + return "DistanceField" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/feeds.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/feeds.py new file mode 100644 index 0000000..ebd4511 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/feeds.py @@ -0,0 +1,151 @@ +from django.contrib.syndication.views import Feed as BaseFeed +from django.utils.feedgenerator import Atom1Feed, Rss201rev2Feed + + +class GeoFeedMixin: + """ + This mixin provides the necessary routines for SyndicationFeed subclasses + to produce simple GeoRSS or W3C Geo elements. + """ + + def georss_coords(self, coords): + """ + In GeoRSS coordinate pairs are ordered by lat/lon and separated by + a single white space. Given a tuple of coordinates, return a string + GeoRSS representation. + """ + return " ".join("%f %f" % (coord[1], coord[0]) for coord in coords) + + def add_georss_point(self, handler, coords, w3c_geo=False): + """ + Adds a GeoRSS point with the given coords using the given handler. + Handles the differences between simple GeoRSS and the more popular + W3C Geo specification. + """ + if w3c_geo: + lon, lat = coords[:2] + handler.addQuickElement("geo:lat", "%f" % lat) + handler.addQuickElement("geo:lon", "%f" % lon) + else: + handler.addQuickElement("georss:point", self.georss_coords((coords,))) + + def add_georss_element(self, handler, item, w3c_geo=False): + """Add a GeoRSS XML element using the given item and handler.""" + # Getting the Geometry object. + geom = item.get("geometry") + if geom is not None: + if isinstance(geom, (list, tuple)): + # Special case if a tuple/list was passed in. The tuple may be + # a point or a box + box_coords = None + if isinstance(geom[0], (list, tuple)): + # Box: ( (X0, Y0), (X1, Y1) ) + if len(geom) == 2: + box_coords = geom + else: + raise ValueError("Only should be two sets of coordinates.") + else: + if len(geom) == 2: + # Point: (X, Y) + self.add_georss_point(handler, geom, w3c_geo=w3c_geo) + elif len(geom) == 4: + # Box: (X0, Y0, X1, Y1) + box_coords = (geom[:2], geom[2:]) + else: + raise ValueError("Only should be 2 or 4 numeric elements.") + # If a GeoRSS box was given via tuple. + if box_coords is not None: + if w3c_geo: + raise ValueError( + "Cannot use simple GeoRSS box in W3C Geo feeds." + ) + handler.addQuickElement( + "georss:box", self.georss_coords(box_coords) + ) + else: + # Getting the lowercase geometry type. + gtype = str(geom.geom_type).lower() + if gtype == "point": + self.add_georss_point(handler, geom.coords, w3c_geo=w3c_geo) + else: + if w3c_geo: + raise ValueError("W3C Geo only supports Point geometries.") + # For formatting consistent w/the GeoRSS simple standard: + # http://georss.org/1.0#simple + if gtype in ("linestring", "linearring"): + handler.addQuickElement( + "georss:line", self.georss_coords(geom.coords) + ) + elif gtype in ("polygon",): + # Only support the exterior ring. + handler.addQuickElement( + "georss:polygon", self.georss_coords(geom[0].coords) + ) + else: + raise ValueError( + 'Geometry type "%s" not supported.' % geom.geom_type + ) + + +# ### SyndicationFeed subclasses ### +class GeoRSSFeed(Rss201rev2Feed, GeoFeedMixin): + def rss_attributes(self): + attrs = super().rss_attributes() + attrs["xmlns:georss"] = "http://www.georss.org/georss" + return attrs + + def add_item_elements(self, handler, item): + super().add_item_elements(handler, item) + self.add_georss_element(handler, item) + + def add_root_elements(self, handler): + super().add_root_elements(handler) + self.add_georss_element(handler, self.feed) + + +class GeoAtom1Feed(Atom1Feed, GeoFeedMixin): + def root_attributes(self): + attrs = super().root_attributes() + attrs["xmlns:georss"] = "http://www.georss.org/georss" + return attrs + + def add_item_elements(self, handler, item): + super().add_item_elements(handler, item) + self.add_georss_element(handler, item) + + def add_root_elements(self, handler): + super().add_root_elements(handler) + self.add_georss_element(handler, self.feed) + + +class W3CGeoFeed(Rss201rev2Feed, GeoFeedMixin): + def rss_attributes(self): + attrs = super().rss_attributes() + attrs["xmlns:geo"] = "http://www.w3.org/2003/01/geo/wgs84_pos#" + return attrs + + def add_item_elements(self, handler, item): + super().add_item_elements(handler, item) + self.add_georss_element(handler, item, w3c_geo=True) + + def add_root_elements(self, handler): + super().add_root_elements(handler) + self.add_georss_element(handler, self.feed, w3c_geo=True) + + +# ### Feed subclass ### +class Feed(BaseFeed): + """ + This is a subclass of the `Feed` from `django.contrib.syndication`. + This allows users to define a `geometry(obj)` and/or `item_geometry(item)` + methods on their own subclasses so that geo-referenced information may + placed in the feed. + """ + + feed_type = GeoRSSFeed + + def feed_extra_kwargs(self, obj): + return {"geometry": self._get_dynamic_attr("geometry", obj)} + + def item_extra_kwargs(self, item): + return {"geometry": self._get_dynamic_attr("item_geometry", item)} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/forms/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/forms/__init__.py new file mode 100644 index 0000000..c07720b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/forms/__init__.py @@ -0,0 +1,13 @@ +from django.forms import * # NOQA + +from .fields import ( # NOQA + GeometryCollectionField, + GeometryField, + LineStringField, + MultiLineStringField, + MultiPointField, + MultiPolygonField, + PointField, + PolygonField, +) +from .widgets import BaseGeometryWidget, OpenLayersWidget, OSMWidget # NOQA diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/forms/fields.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/forms/fields.py new file mode 100644 index 0000000..1fd3153 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/forms/fields.py @@ -0,0 +1,144 @@ +from django import forms +from django.contrib.gis.gdal import GDALException +from django.contrib.gis.geos import GEOSException, GEOSGeometry +from django.core.exceptions import ValidationError +from django.utils.translation import gettext_lazy as _ + +from .widgets import OpenLayersWidget + + +class GeometryField(forms.Field): + """ + This is the basic form field for a Geometry. Any textual input that is + accepted by GEOSGeometry is accepted by this form. By default, + this includes WKT, HEXEWKB, WKB (in a buffer), and GeoJSON. + """ + + widget = OpenLayersWidget + geom_type = "GEOMETRY" + + default_error_messages = { + "required": _("No geometry value provided."), + "invalid_geom": _("Invalid geometry value."), + "invalid_geom_type": _("Invalid geometry type."), + "transform_error": _( + "An error occurred when transforming the geometry " + "to the SRID of the geometry form field." + ), + } + + def __init__(self, *, srid=None, geom_type=None, **kwargs): + self.srid = srid + if geom_type is not None: + self.geom_type = geom_type + super().__init__(**kwargs) + self.widget.attrs["geom_type"] = self.geom_type + + def to_python(self, value): + """Transform the value to a Geometry object.""" + if value in self.empty_values: + return None + + if not isinstance(value, GEOSGeometry): + if hasattr(self.widget, "deserialize"): + try: + value = self.widget.deserialize(value) + except GDALException: + value = None + else: + try: + value = GEOSGeometry(value) + except (GEOSException, ValueError, TypeError): + value = None + if value is None: + raise ValidationError( + self.error_messages["invalid_geom"], code="invalid_geom" + ) + + # Try to set the srid + if not value.srid: + try: + value.srid = self.widget.map_srid + except AttributeError: + if self.srid: + value.srid = self.srid + return value + + def clean(self, value): + """ + Validate that the input value can be converted to a Geometry object + and return it. Raise a ValidationError if the value cannot be + instantiated as a Geometry. + """ + geom = super().clean(value) + if geom is None: + return geom + + # Ensuring that the geometry is of the correct type (indicated + # using the OGC string label). + if ( + str(geom.geom_type).upper() != self.geom_type + and self.geom_type != "GEOMETRY" + ): + raise ValidationError( + self.error_messages["invalid_geom_type"], code="invalid_geom_type" + ) + + # Transforming the geometry if the SRID was set. + if self.srid and self.srid != -1 and self.srid != geom.srid: + try: + geom.transform(self.srid) + except GEOSException: + raise ValidationError( + self.error_messages["transform_error"], code="transform_error" + ) + + return geom + + def has_changed(self, initial, data): + """Compare geographic value of data with its initial value.""" + + try: + data = self.to_python(data) + initial = self.to_python(initial) + except ValidationError: + return True + + # Only do a geographic comparison if both values are available + if initial and data: + data.transform(initial.srid) + # If the initial value was not added by the browser, the geometry + # provided may be slightly different, the first time it is saved. + # The comparison is done with a very low tolerance. + return not initial.equals_exact(data, tolerance=0.000001) + else: + # Check for change of state of existence + return bool(initial) != bool(data) + + +class GeometryCollectionField(GeometryField): + geom_type = "GEOMETRYCOLLECTION" + + +class PointField(GeometryField): + geom_type = "POINT" + + +class MultiPointField(GeometryField): + geom_type = "MULTIPOINT" + + +class LineStringField(GeometryField): + geom_type = "LINESTRING" + + +class MultiLineStringField(GeometryField): + geom_type = "MULTILINESTRING" + + +class PolygonField(GeometryField): + geom_type = "POLYGON" + + +class MultiPolygonField(GeometryField): + geom_type = "MULTIPOLYGON" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/forms/widgets.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/forms/widgets.py new file mode 100644 index 0000000..49ca487 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/forms/widgets.py @@ -0,0 +1,140 @@ +import logging +import warnings + +from django.conf import settings +from django.contrib.gis import gdal +from django.contrib.gis.geometry import json_regex +from django.contrib.gis.geos import GEOSException, GEOSGeometry +from django.forms.widgets import Widget +from django.utils import translation +from django.utils.deprecation import RemovedInDjango51Warning + +logger = logging.getLogger("django.contrib.gis") + + +class BaseGeometryWidget(Widget): + """ + The base class for rich geometry widgets. + Render a map using the WKT of the geometry. + """ + + geom_type = "GEOMETRY" + map_srid = 4326 + map_width = 600 # RemovedInDjango51Warning + map_height = 400 # RemovedInDjango51Warning + display_raw = False + + supports_3d = False + template_name = "" # set on subclasses + + def __init__(self, attrs=None): + self.attrs = {} + for key in ("geom_type", "map_srid", "map_width", "map_height", "display_raw"): + self.attrs[key] = getattr(self, key) + if ( + (attrs and ("map_width" in attrs or "map_height" in attrs)) + or self.map_width != 600 + or self.map_height != 400 + ): + warnings.warn( + "The map_height and map_width widget attributes are deprecated. Please " + "use CSS to size map widgets.", + category=RemovedInDjango51Warning, + stacklevel=2, + ) + if attrs: + self.attrs.update(attrs) + + def serialize(self, value): + return value.wkt if value else "" + + def deserialize(self, value): + try: + return GEOSGeometry(value) + except (GEOSException, ValueError, TypeError) as err: + logger.error("Error creating geometry from value '%s' (%s)", value, err) + return None + + def get_context(self, name, value, attrs): + context = super().get_context(name, value, attrs) + # If a string reaches here (via a validation error on another + # field) then just reconstruct the Geometry. + if value and isinstance(value, str): + value = self.deserialize(value) + + if value: + # Check that srid of value and map match + if value.srid and value.srid != self.map_srid: + try: + ogr = value.ogr + ogr.transform(self.map_srid) + value = ogr + except gdal.GDALException as err: + logger.error( + "Error transforming geometry from srid '%s' to srid '%s' (%s)", + value.srid, + self.map_srid, + err, + ) + + geom_type = gdal.OGRGeomType(self.attrs["geom_type"]).name + context.update( + self.build_attrs( + self.attrs, + { + "name": name, + "module": "geodjango_%s" % name.replace("-", "_"), # JS-safe + "serialized": self.serialize(value), + "geom_type": "Geometry" if geom_type == "Unknown" else geom_type, + "STATIC_URL": settings.STATIC_URL, + "LANGUAGE_BIDI": translation.get_language_bidi(), + **(attrs or {}), + }, + ) + ) + return context + + +class OpenLayersWidget(BaseGeometryWidget): + template_name = "gis/openlayers.html" + map_srid = 3857 + + class Media: + css = { + "all": ( + "https://cdn.jsdelivr.net/npm/ol@v7.2.2/ol.css", + "gis/css/ol3.css", + ) + } + js = ( + "https://cdn.jsdelivr.net/npm/ol@v7.2.2/dist/ol.js", + "gis/js/OLMapWidget.js", + ) + + def serialize(self, value): + return value.json if value else "" + + def deserialize(self, value): + geom = super().deserialize(value) + # GeoJSON assumes WGS84 (4326). Use the map's SRID instead. + if geom and json_regex.match(value) and self.map_srid != 4326: + geom.srid = self.map_srid + return geom + + +class OSMWidget(OpenLayersWidget): + """ + An OpenLayers/OpenStreetMap-based widget. + """ + + template_name = "gis/openlayers-osm.html" + default_lon = 5 + default_lat = 47 + default_zoom = 12 + + def __init__(self, attrs=None): + super().__init__() + for key in ("default_lon", "default_lat", "default_zoom"): + self.attrs[key] = getattr(self, key) + if attrs: + self.attrs.update(attrs) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/LICENSE b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/LICENSE new file mode 100644 index 0000000..30d410e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2007-2009, Justin Bronn +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of OGRGeometry nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/__init__.py new file mode 100644 index 0000000..9ed6e31 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/__init__.py @@ -0,0 +1,58 @@ +""" + This module houses ctypes interfaces for GDAL objects. The following GDAL + objects are supported: + + CoordTransform: Used for coordinate transformations from one spatial + reference system to another. + + Driver: Wraps an OGR data source driver. + + DataSource: Wrapper for the OGR data source object, supports + OGR-supported data sources. + + Envelope: A ctypes structure for bounding boxes (GDAL library + not required). + + OGRGeometry: Object for accessing OGR Geometry functionality. + + OGRGeomType: A class for representing the different OGR Geometry + types (GDAL library not required). + + SpatialReference: Represents OSR Spatial Reference objects. + + The GDAL library will be imported from the system path using the default + library name for the current OS. The default library path may be overridden + by setting `GDAL_LIBRARY_PATH` in your settings with the path to the GDAL C + library on your system. +""" +from django.contrib.gis.gdal.datasource import DataSource +from django.contrib.gis.gdal.driver import Driver +from django.contrib.gis.gdal.envelope import Envelope +from django.contrib.gis.gdal.error import GDALException, SRSException, check_err +from django.contrib.gis.gdal.geometries import OGRGeometry +from django.contrib.gis.gdal.geomtype import OGRGeomType +from django.contrib.gis.gdal.libgdal import ( + GDAL_VERSION, + gdal_full_version, + gdal_version, +) +from django.contrib.gis.gdal.raster.source import GDALRaster +from django.contrib.gis.gdal.srs import AxisOrder, CoordTransform, SpatialReference + +__all__ = ( + "AxisOrder", + "Driver", + "DataSource", + "CoordTransform", + "Envelope", + "GDALException", + "GDALRaster", + "GDAL_VERSION", + "OGRGeometry", + "OGRGeomType", + "SpatialReference", + "SRSException", + "check_err", + "gdal_version", + "gdal_full_version", +) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/base.py new file mode 100644 index 0000000..74a2689 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/base.py @@ -0,0 +1,6 @@ +from django.contrib.gis.gdal.error import GDALException +from django.contrib.gis.ptr import CPointerBase + + +class GDALBase(CPointerBase): + null_ptr_exception_class = GDALException diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/datasource.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/datasource.py new file mode 100644 index 0000000..dfd043a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/datasource.py @@ -0,0 +1,126 @@ +""" + DataSource is a wrapper for the OGR Data Source object, which provides + an interface for reading vector geometry data from many different file + formats (including ESRI shapefiles). + + When instantiating a DataSource object, use the filename of a + GDAL-supported data source. For example, a SHP file or a + TIGER/Line file from the government. + + The ds_driver keyword is used internally when a ctypes pointer + is passed in directly. + + Example: + ds = DataSource('/home/foo/bar.shp') + for layer in ds: + for feature in layer: + # Getting the geometry for the feature. + g = feature.geom + + # Getting the 'description' field for the feature. + desc = feature['description'] + + # We can also increment through all of the fields + # attached to this feature. + for field in feature: + # Get the name of the field (e.g. 'description') + nm = field.name + + # Get the type (integer) of the field, e.g. 0 => OFTInteger + t = field.type + + # Returns the value the field; OFTIntegers return ints, + # OFTReal returns floats, all else returns string. + val = field.value +""" +from ctypes import byref +from pathlib import Path + +from django.contrib.gis.gdal.base import GDALBase +from django.contrib.gis.gdal.driver import Driver +from django.contrib.gis.gdal.error import GDALException +from django.contrib.gis.gdal.layer import Layer +from django.contrib.gis.gdal.prototypes import ds as capi +from django.utils.encoding import force_bytes, force_str + + +# For more information, see the OGR C API documentation: +# https://gdal.org/api/vector_c_api.html +# +# The OGR_DS_* routines are relevant here. +class DataSource(GDALBase): + "Wraps an OGR Data Source object." + destructor = capi.destroy_ds + + def __init__(self, ds_input, ds_driver=False, write=False, encoding="utf-8"): + # The write flag. + if write: + self._write = 1 + else: + self._write = 0 + # See also https://gdal.org/development/rfc/rfc23_ogr_unicode.html + self.encoding = encoding + + Driver.ensure_registered() + + if isinstance(ds_input, (str, Path)): + # The data source driver is a void pointer. + ds_driver = Driver.ptr_type() + try: + # OGROpen will auto-detect the data source type. + ds = capi.open_ds(force_bytes(ds_input), self._write, byref(ds_driver)) + except GDALException: + # Making the error message more clear rather than something + # like "Invalid pointer returned from OGROpen". + raise GDALException('Could not open the datasource at "%s"' % ds_input) + elif isinstance(ds_input, self.ptr_type) and isinstance( + ds_driver, Driver.ptr_type + ): + ds = ds_input + else: + raise GDALException("Invalid data source input type: %s" % type(ds_input)) + + if ds: + self.ptr = ds + self.driver = Driver(ds_driver) + else: + # Raise an exception if the returned pointer is NULL + raise GDALException('Invalid data source file "%s"' % ds_input) + + def __getitem__(self, index): + "Allows use of the index [] operator to get a layer at the index." + if isinstance(index, str): + try: + layer = capi.get_layer_by_name(self.ptr, force_bytes(index)) + except GDALException: + raise IndexError("Invalid OGR layer name given: %s." % index) + elif isinstance(index, int): + if 0 <= index < self.layer_count: + layer = capi.get_layer(self._ptr, index) + else: + raise IndexError( + "Index out of range when accessing layers in a datasource: %s." + % index + ) + else: + raise TypeError("Invalid index type: %s" % type(index)) + return Layer(layer, self) + + def __len__(self): + "Return the number of layers within the data source." + return self.layer_count + + def __str__(self): + "Return OGR GetName and Driver for the Data Source." + return "%s (%s)" % (self.name, self.driver) + + @property + def layer_count(self): + "Return the number of layers in the data source." + return capi.get_layer_count(self._ptr) + + @property + def name(self): + "Return the name of the data source." + name = capi.get_ds_name(self._ptr) + return force_str(name, self.encoding, strings_only=True) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/driver.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/driver.py new file mode 100644 index 0000000..0ce7a2c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/driver.py @@ -0,0 +1,103 @@ +from ctypes import c_void_p + +from django.contrib.gis.gdal.base import GDALBase +from django.contrib.gis.gdal.error import GDALException +from django.contrib.gis.gdal.prototypes import ds as vcapi +from django.contrib.gis.gdal.prototypes import raster as rcapi +from django.utils.encoding import force_bytes, force_str + + +class Driver(GDALBase): + """ + Wrap a GDAL/OGR Data Source Driver. + For more information, see the C API documentation: + https://gdal.org/api/vector_c_api.html + https://gdal.org/api/raster_c_api.html + """ + + # Case-insensitive aliases for some GDAL/OGR Drivers. + # For a complete list of original driver names see + # https://gdal.org/drivers/vector/ + # https://gdal.org/drivers/raster/ + _alias = { + # vector + "esri": "ESRI Shapefile", + "shp": "ESRI Shapefile", + "shape": "ESRI Shapefile", + "tiger": "TIGER", + "tiger/line": "TIGER", + # raster + "tiff": "GTiff", + "tif": "GTiff", + "jpeg": "JPEG", + "jpg": "JPEG", + } + + def __init__(self, dr_input): + """ + Initialize an GDAL/OGR driver on either a string or integer input. + """ + if isinstance(dr_input, str): + # If a string name of the driver was passed in + self.ensure_registered() + + # Checking the alias dictionary (case-insensitive) to see if an + # alias exists for the given driver. + if dr_input.lower() in self._alias: + name = self._alias[dr_input.lower()] + else: + name = dr_input + + # Attempting to get the GDAL/OGR driver by the string name. + for iface in (vcapi, rcapi): + driver = c_void_p(iface.get_driver_by_name(force_bytes(name))) + if driver: + break + elif isinstance(dr_input, int): + self.ensure_registered() + for iface in (vcapi, rcapi): + driver = iface.get_driver(dr_input) + if driver: + break + elif isinstance(dr_input, c_void_p): + driver = dr_input + else: + raise GDALException( + "Unrecognized input type for GDAL/OGR Driver: %s" % type(dr_input) + ) + + # Making sure we get a valid pointer to the OGR Driver + if not driver: + raise GDALException( + "Could not initialize GDAL/OGR Driver on input: %s" % dr_input + ) + self.ptr = driver + + def __str__(self): + return self.name + + @classmethod + def ensure_registered(cls): + """ + Attempt to register all the data source drivers. + """ + # Only register all if the driver counts are 0 (or else all drivers + # will be registered over and over again) + if not vcapi.get_driver_count(): + vcapi.register_all() + if not rcapi.get_driver_count(): + rcapi.register_all() + + @classmethod + def driver_count(cls): + """ + Return the number of GDAL/OGR data source drivers registered. + """ + return vcapi.get_driver_count() + rcapi.get_driver_count() + + @property + def name(self): + """ + Return description/name string for this driver. + """ + return force_str(rcapi.get_driver_description(self.ptr)) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/envelope.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/envelope.py new file mode 100644 index 0000000..4c2c1e4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/envelope.py @@ -0,0 +1,203 @@ +""" + The GDAL/OGR library uses an Envelope structure to hold the bounding + box information for a geometry. The envelope (bounding box) contains + two pairs of coordinates, one for the lower left coordinate and one + for the upper right coordinate: + + +----------o Upper right; (max_x, max_y) + | | + | | + | | + Lower left (min_x, min_y) o----------+ +""" +from ctypes import Structure, c_double + +from django.contrib.gis.gdal.error import GDALException + + +# The OGR definition of an Envelope is a C structure containing four doubles. +# See the 'ogr_core.h' source file for more information: +# https://gdal.org/doxygen/ogr__core_8h_source.html +class OGREnvelope(Structure): + "Represent the OGREnvelope C Structure." + _fields_ = [ + ("MinX", c_double), + ("MaxX", c_double), + ("MinY", c_double), + ("MaxY", c_double), + ] + + +class Envelope: + """ + The Envelope object is a C structure that contains the minimum and + maximum X, Y coordinates for a rectangle bounding box. The naming + of the variables is compatible with the OGR Envelope structure. + """ + + def __init__(self, *args): + """ + The initialization function may take an OGREnvelope structure, 4-element + tuple or list, or 4 individual arguments. + """ + + if len(args) == 1: + if isinstance(args[0], OGREnvelope): + # OGREnvelope (a ctypes Structure) was passed in. + self._envelope = args[0] + elif isinstance(args[0], (tuple, list)): + # A tuple was passed in. + if len(args[0]) != 4: + raise GDALException( + "Incorrect number of tuple elements (%d)." % len(args[0]) + ) + else: + self._from_sequence(args[0]) + else: + raise TypeError("Incorrect type of argument: %s" % type(args[0])) + elif len(args) == 4: + # Individual parameters passed in. + # Thanks to ww for the help + self._from_sequence([float(a) for a in args]) + else: + raise GDALException("Incorrect number (%d) of arguments." % len(args)) + + # Checking the x,y coordinates + if self.min_x > self.max_x: + raise GDALException("Envelope minimum X > maximum X.") + if self.min_y > self.max_y: + raise GDALException("Envelope minimum Y > maximum Y.") + + def __eq__(self, other): + """ + Return True if the envelopes are equivalent; can compare against + other Envelopes and 4-tuples. + """ + if isinstance(other, Envelope): + return ( + (self.min_x == other.min_x) + and (self.min_y == other.min_y) + and (self.max_x == other.max_x) + and (self.max_y == other.max_y) + ) + elif isinstance(other, tuple) and len(other) == 4: + return ( + (self.min_x == other[0]) + and (self.min_y == other[1]) + and (self.max_x == other[2]) + and (self.max_y == other[3]) + ) + else: + raise GDALException("Equivalence testing only works with other Envelopes.") + + def __str__(self): + "Return a string representation of the tuple." + return str(self.tuple) + + def _from_sequence(self, seq): + "Initialize the C OGR Envelope structure from the given sequence." + self._envelope = OGREnvelope() + self._envelope.MinX = seq[0] + self._envelope.MinY = seq[1] + self._envelope.MaxX = seq[2] + self._envelope.MaxY = seq[3] + + def expand_to_include(self, *args): + """ + Modify the envelope to expand to include the boundaries of + the passed-in 2-tuple (a point), 4-tuple (an extent) or + envelope. + """ + # We provide a number of different signatures for this method, + # and the logic here is all about converting them into a + # 4-tuple single parameter which does the actual work of + # expanding the envelope. + if len(args) == 1: + if isinstance(args[0], Envelope): + return self.expand_to_include(args[0].tuple) + elif hasattr(args[0], "x") and hasattr(args[0], "y"): + return self.expand_to_include( + args[0].x, args[0].y, args[0].x, args[0].y + ) + elif isinstance(args[0], (tuple, list)): + # A tuple was passed in. + if len(args[0]) == 2: + return self.expand_to_include( + (args[0][0], args[0][1], args[0][0], args[0][1]) + ) + elif len(args[0]) == 4: + (minx, miny, maxx, maxy) = args[0] + if minx < self._envelope.MinX: + self._envelope.MinX = minx + if miny < self._envelope.MinY: + self._envelope.MinY = miny + if maxx > self._envelope.MaxX: + self._envelope.MaxX = maxx + if maxy > self._envelope.MaxY: + self._envelope.MaxY = maxy + else: + raise GDALException( + "Incorrect number of tuple elements (%d)." % len(args[0]) + ) + else: + raise TypeError("Incorrect type of argument: %s" % type(args[0])) + elif len(args) == 2: + # An x and an y parameter were passed in + return self.expand_to_include((args[0], args[1], args[0], args[1])) + elif len(args) == 4: + # Individual parameters passed in. + return self.expand_to_include(args) + else: + raise GDALException("Incorrect number (%d) of arguments." % len(args[0])) + + @property + def min_x(self): + "Return the value of the minimum X coordinate." + return self._envelope.MinX + + @property + def min_y(self): + "Return the value of the minimum Y coordinate." + return self._envelope.MinY + + @property + def max_x(self): + "Return the value of the maximum X coordinate." + return self._envelope.MaxX + + @property + def max_y(self): + "Return the value of the maximum Y coordinate." + return self._envelope.MaxY + + @property + def ur(self): + "Return the upper-right coordinate." + return (self.max_x, self.max_y) + + @property + def ll(self): + "Return the lower-left coordinate." + return (self.min_x, self.min_y) + + @property + def tuple(self): + "Return a tuple representing the envelope." + return (self.min_x, self.min_y, self.max_x, self.max_y) + + @property + def wkt(self): + "Return WKT representing a Polygon for this envelope." + # TODO: Fix significant figures. + return "POLYGON((%s %s,%s %s,%s %s,%s %s,%s %s))" % ( + self.min_x, + self.min_y, + self.min_x, + self.max_y, + self.max_x, + self.max_y, + self.max_x, + self.min_y, + self.min_x, + self.min_y, + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/error.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/error.py new file mode 100644 index 0000000..df19c2e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/error.py @@ -0,0 +1,61 @@ +""" + This module houses the GDAL & SRS Exception objects, and the + check_err() routine which checks the status code returned by + GDAL/OGR methods. +""" + + +# #### GDAL & SRS Exceptions #### +class GDALException(Exception): + pass + + +class SRSException(Exception): + pass + + +# #### GDAL/OGR error checking codes and routine #### + +# OGR Error Codes +OGRERR_DICT = { + 1: (GDALException, "Not enough data."), + 2: (GDALException, "Not enough memory."), + 3: (GDALException, "Unsupported geometry type."), + 4: (GDALException, "Unsupported operation."), + 5: (GDALException, "Corrupt data."), + 6: (GDALException, "OGR failure."), + 7: (SRSException, "Unsupported SRS."), + 8: (GDALException, "Invalid handle."), +} + +# CPL Error Codes +# https://gdal.org/api/cpl.html#cpl-error-h +CPLERR_DICT = { + 1: (GDALException, "AppDefined"), + 2: (GDALException, "OutOfMemory"), + 3: (GDALException, "FileIO"), + 4: (GDALException, "OpenFailed"), + 5: (GDALException, "IllegalArg"), + 6: (GDALException, "NotSupported"), + 7: (GDALException, "AssertionFailed"), + 8: (GDALException, "NoWriteAccess"), + 9: (GDALException, "UserInterrupt"), + 10: (GDALException, "ObjectNull"), +} + +ERR_NONE = 0 + + +def check_err(code, cpl=False): + """ + Check the given CPL/OGRERR and raise an exception where appropriate. + """ + err_dict = CPLERR_DICT if cpl else OGRERR_DICT + + if code == ERR_NONE: + return + elif code in err_dict: + e, msg = err_dict[code] + raise e(msg) + else: + raise GDALException('Unknown error code: "%s"' % code) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/feature.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/feature.py new file mode 100644 index 0000000..6f08969 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/feature.py @@ -0,0 +1,120 @@ +from django.contrib.gis.gdal.base import GDALBase +from django.contrib.gis.gdal.error import GDALException +from django.contrib.gis.gdal.field import Field +from django.contrib.gis.gdal.geometries import OGRGeometry, OGRGeomType +from django.contrib.gis.gdal.prototypes import ds as capi +from django.contrib.gis.gdal.prototypes import geom as geom_api +from django.utils.encoding import force_bytes, force_str + + +# For more information, see the OGR C API source code: +# https://gdal.org/api/vector_c_api.html +# +# The OGR_F_* routines are relevant here. +class Feature(GDALBase): + """ + This class that wraps an OGR Feature, needs to be instantiated + from a Layer object. + """ + + destructor = capi.destroy_feature + + def __init__(self, feat, layer): + """ + Initialize Feature from a pointer and its Layer object. + """ + if not feat: + raise GDALException("Cannot create OGR Feature, invalid pointer given.") + self.ptr = feat + self._layer = layer + + def __getitem__(self, index): + """ + Get the Field object at the specified index, which may be either + an integer or the Field's string label. Note that the Field object + is not the field's _value_ -- use the `get` method instead to + retrieve the value (e.g. an integer) instead of a Field instance. + """ + if isinstance(index, str): + i = self.index(index) + elif 0 <= index < self.num_fields: + i = index + else: + raise IndexError( + "Index out of range when accessing field in a feature: %s." % index + ) + return Field(self, i) + + def __len__(self): + "Return the count of fields in this feature." + return self.num_fields + + def __str__(self): + "The string name of the feature." + return "Feature FID %d in Layer<%s>" % (self.fid, self.layer_name) + + def __eq__(self, other): + "Do equivalence testing on the features." + return bool(capi.feature_equal(self.ptr, other._ptr)) + + # #### Feature Properties #### + @property + def encoding(self): + return self._layer._ds.encoding + + @property + def fid(self): + "Return the feature identifier." + return capi.get_fid(self.ptr) + + @property + def layer_name(self): + "Return the name of the layer for the feature." + name = capi.get_feat_name(self._layer._ldefn) + return force_str(name, self.encoding, strings_only=True) + + @property + def num_fields(self): + "Return the number of fields in the Feature." + return capi.get_feat_field_count(self.ptr) + + @property + def fields(self): + "Return a list of fields in the Feature." + return [ + force_str( + capi.get_field_name(capi.get_field_defn(self._layer._ldefn, i)), + self.encoding, + strings_only=True, + ) + for i in range(self.num_fields) + ] + + @property + def geom(self): + "Return the OGR Geometry for this Feature." + # Retrieving the geometry pointer for the feature. + geom_ptr = capi.get_feat_geom_ref(self.ptr) + return OGRGeometry(geom_api.clone_geom(geom_ptr)) + + @property + def geom_type(self): + "Return the OGR Geometry Type for this Feature." + return OGRGeomType(capi.get_fd_geom_type(self._layer._ldefn)) + + # #### Feature Methods #### + def get(self, field): + """ + Return the value of the field, instead of an instance of the Field + object. May take a string of the field name or a Field object as + parameters. + """ + field_name = getattr(field, "name", field) + return self[field_name].value + + def index(self, field_name): + "Return the index of the given field name." + i = capi.get_field_index(self.ptr, force_bytes(field_name)) + if i < 0: + raise IndexError("Invalid OFT field name given: %s." % field_name) + return i diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/field.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/field.py new file mode 100644 index 0000000..5374f6c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/field.py @@ -0,0 +1,253 @@ +from ctypes import byref, c_int +from datetime import date, datetime, time + +from django.contrib.gis.gdal.base import GDALBase +from django.contrib.gis.gdal.error import GDALException +from django.contrib.gis.gdal.prototypes import ds as capi +from django.utils.encoding import force_str + + +# For more information, see the OGR C API source code: +# https://gdal.org/api/vector_c_api.html +# +# The OGR_Fld_* routines are relevant here. +class Field(GDALBase): + """ + Wrap an OGR Field. Needs to be instantiated from a Feature object. + """ + + def __init__(self, feat, index): + """ + Initialize on the feature object and the integer index of + the field within the feature. + """ + # Setting the feature pointer and index. + self._feat = feat + self._index = index + + # Getting the pointer for this field. + fld_ptr = capi.get_feat_field_defn(feat.ptr, index) + if not fld_ptr: + raise GDALException("Cannot create OGR Field, invalid pointer given.") + self.ptr = fld_ptr + + # Setting the class depending upon the OGR Field Type (OFT) + self.__class__ = OGRFieldTypes[self.type] + + def __str__(self): + "Return the string representation of the Field." + return str(self.value).strip() + + # #### Field Methods #### + def as_double(self): + "Retrieve the Field's value as a double (float)." + return ( + capi.get_field_as_double(self._feat.ptr, self._index) + if self.is_set + else None + ) + + def as_int(self, is_64=False): + "Retrieve the Field's value as an integer." + if is_64: + return ( + capi.get_field_as_integer64(self._feat.ptr, self._index) + if self.is_set + else None + ) + else: + return ( + capi.get_field_as_integer(self._feat.ptr, self._index) + if self.is_set + else None + ) + + def as_string(self): + "Retrieve the Field's value as a string." + if not self.is_set: + return None + string = capi.get_field_as_string(self._feat.ptr, self._index) + return force_str(string, encoding=self._feat.encoding, strings_only=True) + + def as_datetime(self): + "Retrieve the Field's value as a tuple of date & time components." + if not self.is_set: + return None + yy, mm, dd, hh, mn, ss, tz = [c_int() for i in range(7)] + status = capi.get_field_as_datetime( + self._feat.ptr, + self._index, + byref(yy), + byref(mm), + byref(dd), + byref(hh), + byref(mn), + byref(ss), + byref(tz), + ) + if status: + return (yy, mm, dd, hh, mn, ss, tz) + else: + raise GDALException( + "Unable to retrieve date & time information from the field." + ) + + # #### Field Properties #### + @property + def is_set(self): + "Return True if the value of this field isn't null, False otherwise." + return capi.is_field_set(self._feat.ptr, self._index) + + @property + def name(self): + "Return the name of this Field." + name = capi.get_field_name(self.ptr) + return force_str(name, encoding=self._feat.encoding, strings_only=True) + + @property + def precision(self): + "Return the precision of this Field." + return capi.get_field_precision(self.ptr) + + @property + def type(self): + "Return the OGR type of this Field." + return capi.get_field_type(self.ptr) + + @property + def type_name(self): + "Return the OGR field type name for this Field." + return capi.get_field_type_name(self.type) + + @property + def value(self): + "Return the value of this Field." + # Default is to get the field as a string. + return self.as_string() + + @property + def width(self): + "Return the width of this Field." + return capi.get_field_width(self.ptr) + + +# ### The Field sub-classes for each OGR Field type. ### +class OFTInteger(Field): + _bit64 = False + + @property + def value(self): + "Return an integer contained in this field." + return self.as_int(self._bit64) + + @property + def type(self): + """ + GDAL uses OFTReals to represent OFTIntegers in created + shapefiles -- forcing the type here since the underlying field + type may actually be OFTReal. + """ + return 0 + + +class OFTReal(Field): + @property + def value(self): + "Return a float contained in this field." + return self.as_double() + + +# String & Binary fields, just subclasses +class OFTString(Field): + pass + + +class OFTWideString(Field): + pass + + +class OFTBinary(Field): + pass + + +# OFTDate, OFTTime, OFTDateTime fields. +class OFTDate(Field): + @property + def value(self): + "Return a Python `date` object for the OFTDate field." + try: + yy, mm, dd, hh, mn, ss, tz = self.as_datetime() + return date(yy.value, mm.value, dd.value) + except (TypeError, ValueError, GDALException): + return None + + +class OFTDateTime(Field): + @property + def value(self): + "Return a Python `datetime` object for this OFTDateTime field." + # TODO: Adapt timezone information. + # See https://lists.osgeo.org/pipermail/gdal-dev/2006-February/007990.html + # The `tz` variable has values of: 0=unknown, 1=localtime (ambiguous), + # 100=GMT, 104=GMT+1, 80=GMT-5, etc. + try: + yy, mm, dd, hh, mn, ss, tz = self.as_datetime() + return datetime(yy.value, mm.value, dd.value, hh.value, mn.value, ss.value) + except (TypeError, ValueError, GDALException): + return None + + +class OFTTime(Field): + @property + def value(self): + "Return a Python `time` object for this OFTTime field." + try: + yy, mm, dd, hh, mn, ss, tz = self.as_datetime() + return time(hh.value, mn.value, ss.value) + except (ValueError, GDALException): + return None + + +class OFTInteger64(OFTInteger): + _bit64 = True + + +# List fields are also just subclasses +class OFTIntegerList(Field): + pass + + +class OFTRealList(Field): + pass + + +class OFTStringList(Field): + pass + + +class OFTWideStringList(Field): + pass + + +class OFTInteger64List(Field): + pass + + +# Class mapping dictionary for OFT Types and reverse mapping. +OGRFieldTypes = { + 0: OFTInteger, + 1: OFTIntegerList, + 2: OFTReal, + 3: OFTRealList, + 4: OFTString, + 5: OFTStringList, + 6: OFTWideString, + 7: OFTWideStringList, + 8: OFTBinary, + 9: OFTDate, + 10: OFTTime, + 11: OFTDateTime, + 12: OFTInteger64, + 13: OFTInteger64List, +} +ROGRFieldTypes = {cls: num for num, cls in OGRFieldTypes.items()} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/geometries.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/geometries.py new file mode 100644 index 0000000..f74dc68 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/geometries.py @@ -0,0 +1,743 @@ +""" + The OGRGeometry is a wrapper for using the OGR Geometry class + (see https://gdal.org/api/ogrgeometry_cpp.html#_CPPv411OGRGeometry). + OGRGeometry may be instantiated when reading geometries from OGR Data Sources + (e.g. SHP files), or when given OGC WKT (a string). + + While the 'full' API is not present yet, the API is "pythonic" unlike + the traditional and "next-generation" OGR Python bindings. One major + advantage OGR Geometries have over their GEOS counterparts is support + for spatial reference systems and their transformation. + + Example: + >>> from django.contrib.gis.gdal import OGRGeometry, OGRGeomType, SpatialReference + >>> wkt1, wkt2 = 'POINT(-90 30)', 'POLYGON((0 0, 5 0, 5 5, 0 5)' + >>> pnt = OGRGeometry(wkt1) + >>> print(pnt) + POINT (-90 30) + >>> mpnt = OGRGeometry(OGRGeomType('MultiPoint'), SpatialReference('WGS84')) + >>> mpnt.add(wkt1) + >>> mpnt.add(wkt1) + >>> print(mpnt) + MULTIPOINT (-90 30,-90 30) + >>> print(mpnt.srs.name) + WGS 84 + >>> print(mpnt.srs.proj) + +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs + >>> mpnt.transform(SpatialReference('NAD27')) + >>> print(mpnt.proj) + +proj=longlat +ellps=clrk66 +datum=NAD27 +no_defs + >>> print(mpnt) + MULTIPOINT (-89.99993037860248 29.99979788655764,-89.99993037860248 29.99979788655764) + + The OGRGeomType class is to make it easy to specify an OGR geometry type: + >>> from django.contrib.gis.gdal import OGRGeomType + >>> gt1 = OGRGeomType(3) # Using an integer for the type + >>> gt2 = OGRGeomType('Polygon') # Using a string + >>> gt3 = OGRGeomType('POLYGON') # It's case-insensitive + >>> print(gt1 == 3, gt1 == 'Polygon') # Equivalence works w/non-OGRGeomType objects + True True +""" +import sys +from binascii import b2a_hex +from ctypes import byref, c_char_p, c_double, c_ubyte, c_void_p, string_at + +from django.contrib.gis.gdal.base import GDALBase +from django.contrib.gis.gdal.envelope import Envelope, OGREnvelope +from django.contrib.gis.gdal.error import GDALException, SRSException +from django.contrib.gis.gdal.geomtype import OGRGeomType +from django.contrib.gis.gdal.prototypes import geom as capi +from django.contrib.gis.gdal.prototypes import srs as srs_api +from django.contrib.gis.gdal.srs import CoordTransform, SpatialReference +from django.contrib.gis.geometry import hex_regex, json_regex, wkt_regex +from django.utils.encoding import force_bytes + + +# For more information, see the OGR C API source code: +# https://gdal.org/api/vector_c_api.html +# +# The OGR_G_* routines are relevant here. +class OGRGeometry(GDALBase): + """Encapsulate an OGR geometry.""" + + destructor = capi.destroy_geom + + def __init__(self, geom_input, srs=None): + """Initialize Geometry on either WKT or an OGR pointer as input.""" + str_instance = isinstance(geom_input, str) + + # If HEX, unpack input to a binary buffer. + if str_instance and hex_regex.match(geom_input): + geom_input = memoryview(bytes.fromhex(geom_input)) + str_instance = False + + # Constructing the geometry, + if str_instance: + wkt_m = wkt_regex.match(geom_input) + json_m = json_regex.match(geom_input) + if wkt_m: + if wkt_m["srid"]: + # If there's EWKT, set the SRS w/value of the SRID. + srs = int(wkt_m["srid"]) + if wkt_m["type"].upper() == "LINEARRING": + # OGR_G_CreateFromWkt doesn't work with LINEARRING WKT. + # See https://trac.osgeo.org/gdal/ticket/1992. + g = capi.create_geom(OGRGeomType(wkt_m["type"]).num) + capi.import_wkt(g, byref(c_char_p(wkt_m["wkt"].encode()))) + else: + g = capi.from_wkt( + byref(c_char_p(wkt_m["wkt"].encode())), None, byref(c_void_p()) + ) + elif json_m: + g = self._from_json(geom_input.encode()) + else: + # Seeing if the input is a valid short-hand string + # (e.g., 'Point', 'POLYGON'). + OGRGeomType(geom_input) + g = capi.create_geom(OGRGeomType(geom_input).num) + elif isinstance(geom_input, memoryview): + # WKB was passed in + g = self._from_wkb(geom_input) + elif isinstance(geom_input, OGRGeomType): + # OGRGeomType was passed in, an empty geometry will be created. + g = capi.create_geom(geom_input.num) + elif isinstance(geom_input, self.ptr_type): + # OGR pointer (c_void_p) was the input. + g = geom_input + else: + raise GDALException( + "Invalid input type for OGR Geometry construction: %s" + % type(geom_input) + ) + + # Now checking the Geometry pointer before finishing initialization + # by setting the pointer for the object. + if not g: + raise GDALException( + "Cannot create OGR Geometry from input: %s" % geom_input + ) + self.ptr = g + + # Assigning the SpatialReference object to the geometry, if valid. + if srs: + self.srs = srs + + # Setting the class depending upon the OGR Geometry Type + self.__class__ = GEO_CLASSES[self.geom_type.num] + + # Pickle routines + def __getstate__(self): + srs = self.srs + if srs: + srs = srs.wkt + else: + srs = None + return bytes(self.wkb), srs + + def __setstate__(self, state): + wkb, srs = state + ptr = capi.from_wkb(wkb, None, byref(c_void_p()), len(wkb)) + if not ptr: + raise GDALException("Invalid OGRGeometry loaded from pickled state.") + self.ptr = ptr + self.srs = srs + + @classmethod + def _from_wkb(cls, geom_input): + return capi.from_wkb( + bytes(geom_input), None, byref(c_void_p()), len(geom_input) + ) + + @staticmethod + def _from_json(geom_input): + return capi.from_json(geom_input) + + @classmethod + def from_bbox(cls, bbox): + "Construct a Polygon from a bounding box (4-tuple)." + x0, y0, x1, y1 = bbox + return OGRGeometry( + "POLYGON((%s %s, %s %s, %s %s, %s %s, %s %s))" + % (x0, y0, x0, y1, x1, y1, x1, y0, x0, y0) + ) + + @staticmethod + def from_json(geom_input): + return OGRGeometry(OGRGeometry._from_json(force_bytes(geom_input))) + + @classmethod + def from_gml(cls, gml_string): + return cls(capi.from_gml(force_bytes(gml_string))) + + # ### Geometry set-like operations ### + # g = g1 | g2 + def __or__(self, other): + "Return the union of the two geometries." + return self.union(other) + + # g = g1 & g2 + def __and__(self, other): + "Return the intersection of this Geometry and the other." + return self.intersection(other) + + # g = g1 - g2 + def __sub__(self, other): + "Return the difference this Geometry and the other." + return self.difference(other) + + # g = g1 ^ g2 + def __xor__(self, other): + "Return the symmetric difference of this Geometry and the other." + return self.sym_difference(other) + + def __eq__(self, other): + "Is this Geometry equal to the other?" + return isinstance(other, OGRGeometry) and self.equals(other) + + def __str__(self): + "WKT is used for the string representation." + return self.wkt + + # #### Geometry Properties #### + @property + def dimension(self): + "Return 0 for points, 1 for lines, and 2 for surfaces." + return capi.get_dims(self.ptr) + + def _get_coord_dim(self): + "Return the coordinate dimension of the Geometry." + return capi.get_coord_dim(self.ptr) + + def _set_coord_dim(self, dim): + "Set the coordinate dimension of this Geometry." + if dim not in (2, 3): + raise ValueError("Geometry dimension must be either 2 or 3") + capi.set_coord_dim(self.ptr, dim) + + coord_dim = property(_get_coord_dim, _set_coord_dim) + + @property + def geom_count(self): + "Return the number of elements in this Geometry." + return capi.get_geom_count(self.ptr) + + @property + def point_count(self): + "Return the number of Points in this Geometry." + return capi.get_point_count(self.ptr) + + @property + def num_points(self): + "Alias for `point_count` (same name method in GEOS API.)" + return self.point_count + + @property + def num_coords(self): + "Alias for `point_count`." + return self.point_count + + @property + def geom_type(self): + "Return the Type for this Geometry." + return OGRGeomType(capi.get_geom_type(self.ptr)) + + @property + def geom_name(self): + "Return the Name of this Geometry." + return capi.get_geom_name(self.ptr) + + @property + def area(self): + "Return the area for a LinearRing, Polygon, or MultiPolygon; 0 otherwise." + return capi.get_area(self.ptr) + + @property + def envelope(self): + "Return the envelope for this Geometry." + # TODO: Fix Envelope() for Point geometries. + return Envelope(capi.get_envelope(self.ptr, byref(OGREnvelope()))) + + @property + def empty(self): + return capi.is_empty(self.ptr) + + @property + def extent(self): + "Return the envelope as a 4-tuple, instead of as an Envelope object." + return self.envelope.tuple + + # #### SpatialReference-related Properties #### + + # The SRS property + def _get_srs(self): + "Return the Spatial Reference for this Geometry." + try: + srs_ptr = capi.get_geom_srs(self.ptr) + return SpatialReference(srs_api.clone_srs(srs_ptr)) + except SRSException: + return None + + def _set_srs(self, srs): + "Set the SpatialReference for this geometry." + # Do not have to clone the `SpatialReference` object pointer because + # when it is assigned to this `OGRGeometry` it's internal OGR + # reference count is incremented, and will likewise be released + # (decremented) when this geometry's destructor is called. + if isinstance(srs, SpatialReference): + srs_ptr = srs.ptr + elif isinstance(srs, (int, str)): + sr = SpatialReference(srs) + srs_ptr = sr.ptr + elif srs is None: + srs_ptr = None + else: + raise TypeError( + "Cannot assign spatial reference with object of type: %s" % type(srs) + ) + capi.assign_srs(self.ptr, srs_ptr) + + srs = property(_get_srs, _set_srs) + + # The SRID property + def _get_srid(self): + srs = self.srs + if srs: + return srs.srid + return None + + def _set_srid(self, srid): + if isinstance(srid, int) or srid is None: + self.srs = srid + else: + raise TypeError("SRID must be set with an integer.") + + srid = property(_get_srid, _set_srid) + + # #### Output Methods #### + def _geos_ptr(self): + from django.contrib.gis.geos import GEOSGeometry + + return GEOSGeometry._from_wkb(self.wkb) + + @property + def geos(self): + "Return a GEOSGeometry object from this OGRGeometry." + from django.contrib.gis.geos import GEOSGeometry + + return GEOSGeometry(self._geos_ptr(), self.srid) + + @property + def gml(self): + "Return the GML representation of the Geometry." + return capi.to_gml(self.ptr) + + @property + def hex(self): + "Return the hexadecimal representation of the WKB (a string)." + return b2a_hex(self.wkb).upper() + + @property + def json(self): + """ + Return the GeoJSON representation of this Geometry. + """ + return capi.to_json(self.ptr) + + geojson = json + + @property + def kml(self): + "Return the KML representation of the Geometry." + return capi.to_kml(self.ptr, None) + + @property + def wkb_size(self): + "Return the size of the WKB buffer." + return capi.get_wkbsize(self.ptr) + + @property + def wkb(self): + "Return the WKB representation of the Geometry." + if sys.byteorder == "little": + byteorder = 1 # wkbNDR (from ogr_core.h) + else: + byteorder = 0 # wkbXDR + sz = self.wkb_size + # Creating the unsigned character buffer, and passing it in by reference. + buf = (c_ubyte * sz)() + capi.to_wkb(self.ptr, byteorder, byref(buf)) + # Returning a buffer of the string at the pointer. + return memoryview(string_at(buf, sz)) + + @property + def wkt(self): + "Return the WKT representation of the Geometry." + return capi.to_wkt(self.ptr, byref(c_char_p())) + + @property + def ewkt(self): + "Return the EWKT representation of the Geometry." + srs = self.srs + if srs and srs.srid: + return "SRID=%s;%s" % (srs.srid, self.wkt) + else: + return self.wkt + + # #### Geometry Methods #### + def clone(self): + "Clone this OGR Geometry." + return OGRGeometry(capi.clone_geom(self.ptr), self.srs) + + def close_rings(self): + """ + If there are any rings within this geometry that have not been + closed, this routine will do so by adding the starting point at the + end. + """ + # Closing the open rings. + capi.geom_close_rings(self.ptr) + + def transform(self, coord_trans, clone=False): + """ + Transform this geometry to a different spatial reference system. + May take a CoordTransform object, a SpatialReference object, string + WKT or PROJ, and/or an integer SRID. By default, return nothing + and transform the geometry in-place. However, if the `clone` keyword is + set, return a transformed clone of this geometry. + """ + if clone: + klone = self.clone() + klone.transform(coord_trans) + return klone + + # Depending on the input type, use the appropriate OGR routine + # to perform the transformation. + if isinstance(coord_trans, CoordTransform): + capi.geom_transform(self.ptr, coord_trans.ptr) + elif isinstance(coord_trans, SpatialReference): + capi.geom_transform_to(self.ptr, coord_trans.ptr) + elif isinstance(coord_trans, (int, str)): + sr = SpatialReference(coord_trans) + capi.geom_transform_to(self.ptr, sr.ptr) + else: + raise TypeError( + "Transform only accepts CoordTransform, " + "SpatialReference, string, and integer objects." + ) + + # #### Topology Methods #### + def _topology(self, func, other): + """A generalized function for topology operations, takes a GDAL function and + the other geometry to perform the operation on.""" + if not isinstance(other, OGRGeometry): + raise TypeError( + "Must use another OGRGeometry object for topology operations!" + ) + + # Returning the output of the given function with the other geometry's + # pointer. + return func(self.ptr, other.ptr) + + def intersects(self, other): + "Return True if this geometry intersects with the other." + return self._topology(capi.ogr_intersects, other) + + def equals(self, other): + "Return True if this geometry is equivalent to the other." + return self._topology(capi.ogr_equals, other) + + def disjoint(self, other): + "Return True if this geometry and the other are spatially disjoint." + return self._topology(capi.ogr_disjoint, other) + + def touches(self, other): + "Return True if this geometry touches the other." + return self._topology(capi.ogr_touches, other) + + def crosses(self, other): + "Return True if this geometry crosses the other." + return self._topology(capi.ogr_crosses, other) + + def within(self, other): + "Return True if this geometry is within the other." + return self._topology(capi.ogr_within, other) + + def contains(self, other): + "Return True if this geometry contains the other." + return self._topology(capi.ogr_contains, other) + + def overlaps(self, other): + "Return True if this geometry overlaps the other." + return self._topology(capi.ogr_overlaps, other) + + # #### Geometry-generation Methods #### + def _geomgen(self, gen_func, other=None): + "A helper routine for the OGR routines that generate geometries." + if isinstance(other, OGRGeometry): + return OGRGeometry(gen_func(self.ptr, other.ptr), self.srs) + else: + return OGRGeometry(gen_func(self.ptr), self.srs) + + @property + def boundary(self): + "Return the boundary of this geometry." + return self._geomgen(capi.get_boundary) + + @property + def convex_hull(self): + """ + Return the smallest convex Polygon that contains all the points in + this Geometry. + """ + return self._geomgen(capi.geom_convex_hull) + + def difference(self, other): + """ + Return a new geometry consisting of the region which is the difference + of this geometry and the other. + """ + return self._geomgen(capi.geom_diff, other) + + def intersection(self, other): + """ + Return a new geometry consisting of the region of intersection of this + geometry and the other. + """ + return self._geomgen(capi.geom_intersection, other) + + def sym_difference(self, other): + """ + Return a new geometry which is the symmetric difference of this + geometry and the other. + """ + return self._geomgen(capi.geom_sym_diff, other) + + def union(self, other): + """ + Return a new geometry consisting of the region which is the union of + this geometry and the other. + """ + return self._geomgen(capi.geom_union, other) + + +# The subclasses for OGR Geometry. +class Point(OGRGeometry): + def _geos_ptr(self): + from django.contrib.gis import geos + + return geos.Point._create_empty() if self.empty else super()._geos_ptr() + + @classmethod + def _create_empty(cls): + return capi.create_geom(OGRGeomType("point").num) + + @property + def x(self): + "Return the X coordinate for this Point." + return capi.getx(self.ptr, 0) + + @property + def y(self): + "Return the Y coordinate for this Point." + return capi.gety(self.ptr, 0) + + @property + def z(self): + "Return the Z coordinate for this Point." + if self.coord_dim == 3: + return capi.getz(self.ptr, 0) + + @property + def tuple(self): + "Return the tuple of this point." + if self.coord_dim == 2: + return (self.x, self.y) + elif self.coord_dim == 3: + return (self.x, self.y, self.z) + + coords = tuple + + +class LineString(OGRGeometry): + def __getitem__(self, index): + "Return the Point at the given index." + if 0 <= index < self.point_count: + x, y, z = c_double(), c_double(), c_double() + capi.get_point(self.ptr, index, byref(x), byref(y), byref(z)) + dim = self.coord_dim + if dim == 1: + return (x.value,) + elif dim == 2: + return (x.value, y.value) + elif dim == 3: + return (x.value, y.value, z.value) + else: + raise IndexError( + "Index out of range when accessing points of a line string: %s." % index + ) + + def __len__(self): + "Return the number of points in the LineString." + return self.point_count + + @property + def tuple(self): + "Return the tuple representation of this LineString." + return tuple(self[i] for i in range(len(self))) + + coords = tuple + + def _listarr(self, func): + """ + Internal routine that returns a sequence (list) corresponding with + the given function. + """ + return [func(self.ptr, i) for i in range(len(self))] + + @property + def x(self): + "Return the X coordinates in a list." + return self._listarr(capi.getx) + + @property + def y(self): + "Return the Y coordinates in a list." + return self._listarr(capi.gety) + + @property + def z(self): + "Return the Z coordinates in a list." + if self.coord_dim == 3: + return self._listarr(capi.getz) + + +# LinearRings are used in Polygons. +class LinearRing(LineString): + pass + + +class Polygon(OGRGeometry): + def __len__(self): + "Return the number of interior rings in this Polygon." + return self.geom_count + + def __getitem__(self, index): + "Get the ring at the specified index." + if 0 <= index < self.geom_count: + return OGRGeometry( + capi.clone_geom(capi.get_geom_ref(self.ptr, index)), self.srs + ) + else: + raise IndexError( + "Index out of range when accessing rings of a polygon: %s." % index + ) + + # Polygon Properties + @property + def shell(self): + "Return the shell of this Polygon." + return self[0] # First ring is the shell + + exterior_ring = shell + + @property + def tuple(self): + "Return a tuple of LinearRing coordinate tuples." + return tuple(self[i].tuple for i in range(self.geom_count)) + + coords = tuple + + @property + def point_count(self): + "Return the number of Points in this Polygon." + # Summing up the number of points in each ring of the Polygon. + return sum(self[i].point_count for i in range(self.geom_count)) + + @property + def centroid(self): + "Return the centroid (a Point) of this Polygon." + # The centroid is a Point, create a geometry for this. + p = OGRGeometry(OGRGeomType("Point")) + capi.get_centroid(self.ptr, p.ptr) + return p + + +# Geometry Collection base class. +class GeometryCollection(OGRGeometry): + "The Geometry Collection class." + + def __getitem__(self, index): + "Get the Geometry at the specified index." + if 0 <= index < self.geom_count: + return OGRGeometry( + capi.clone_geom(capi.get_geom_ref(self.ptr, index)), self.srs + ) + else: + raise IndexError( + "Index out of range when accessing geometry in a collection: %s." + % index + ) + + def __len__(self): + "Return the number of geometries in this Geometry Collection." + return self.geom_count + + def add(self, geom): + "Add the geometry to this Geometry Collection." + if isinstance(geom, OGRGeometry): + if isinstance(geom, self.__class__): + for g in geom: + capi.add_geom(self.ptr, g.ptr) + else: + capi.add_geom(self.ptr, geom.ptr) + elif isinstance(geom, str): + tmp = OGRGeometry(geom) + capi.add_geom(self.ptr, tmp.ptr) + else: + raise GDALException("Must add an OGRGeometry.") + + @property + def point_count(self): + "Return the number of Points in this Geometry Collection." + # Summing up the number of points in each geometry in this collection + return sum(self[i].point_count for i in range(self.geom_count)) + + @property + def tuple(self): + "Return a tuple representation of this Geometry Collection." + return tuple(self[i].tuple for i in range(self.geom_count)) + + coords = tuple + + +# Multiple Geometry types. +class MultiPoint(GeometryCollection): + pass + + +class MultiLineString(GeometryCollection): + pass + + +class MultiPolygon(GeometryCollection): + pass + + +# Class mapping dictionary (using the OGRwkbGeometryType as the key) +GEO_CLASSES = { + 1: Point, + 2: LineString, + 3: Polygon, + 4: MultiPoint, + 5: MultiLineString, + 6: MultiPolygon, + 7: GeometryCollection, + 101: LinearRing, + 1 + OGRGeomType.wkb25bit: Point, + 2 + OGRGeomType.wkb25bit: LineString, + 3 + OGRGeomType.wkb25bit: Polygon, + 4 + OGRGeomType.wkb25bit: MultiPoint, + 5 + OGRGeomType.wkb25bit: MultiLineString, + 6 + OGRGeomType.wkb25bit: MultiPolygon, + 7 + OGRGeomType.wkb25bit: GeometryCollection, +} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/geomtype.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/geomtype.py new file mode 100644 index 0000000..8b77caf --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/geomtype.py @@ -0,0 +1,95 @@ +from django.contrib.gis.gdal.error import GDALException + + +class OGRGeomType: + "Encapsulate OGR Geometry Types." + + wkb25bit = -2147483648 + + # Dictionary of acceptable OGRwkbGeometryType s and their string names. + _types = { + 0: "Unknown", + 1: "Point", + 2: "LineString", + 3: "Polygon", + 4: "MultiPoint", + 5: "MultiLineString", + 6: "MultiPolygon", + 7: "GeometryCollection", + 100: "None", + 101: "LinearRing", + 102: "PointZ", + 1 + wkb25bit: "Point25D", + 2 + wkb25bit: "LineString25D", + 3 + wkb25bit: "Polygon25D", + 4 + wkb25bit: "MultiPoint25D", + 5 + wkb25bit: "MultiLineString25D", + 6 + wkb25bit: "MultiPolygon25D", + 7 + wkb25bit: "GeometryCollection25D", + } + # Reverse type dictionary, keyed by lowercase of the name. + _str_types = {v.lower(): k for k, v in _types.items()} + + def __init__(self, type_input): + "Figure out the correct OGR Type based upon the input." + if isinstance(type_input, OGRGeomType): + num = type_input.num + elif isinstance(type_input, str): + type_input = type_input.lower() + if type_input == "geometry": + type_input = "unknown" + num = self._str_types.get(type_input) + if num is None: + raise GDALException('Invalid OGR String Type "%s"' % type_input) + elif isinstance(type_input, int): + if type_input not in self._types: + raise GDALException("Invalid OGR Integer Type: %d" % type_input) + num = type_input + else: + raise TypeError("Invalid OGR input type given.") + + # Setting the OGR geometry type number. + self.num = num + + def __str__(self): + "Return the value of the name property." + return self.name + + def __eq__(self, other): + """ + Do an equivalence test on the OGR type with the given + other OGRGeomType, the short-hand string, or the integer. + """ + if isinstance(other, OGRGeomType): + return self.num == other.num + elif isinstance(other, str): + return self.name.lower() == other.lower() + elif isinstance(other, int): + return self.num == other + else: + return False + + @property + def name(self): + "Return a short-hand string form of the OGR Geometry type." + return self._types[self.num] + + @property + def django(self): + "Return the Django GeometryField for this OGR Type." + s = self.name.replace("25D", "") + if s in ("LinearRing", "None"): + return None + elif s == "Unknown": + s = "Geometry" + elif s == "PointZ": + s = "Point" + return s + "Field" + + def to_multi(self): + """ + Transform Point, LineString, Polygon, and their 25D equivalents + to their Multi... counterpart. + """ + if self.name.startswith(("Point", "LineString", "Polygon")): + self.num += 3 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/layer.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/layer.py new file mode 100644 index 0000000..1afa046 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/layer.py @@ -0,0 +1,234 @@ +from ctypes import byref, c_double + +from django.contrib.gis.gdal.base import GDALBase +from django.contrib.gis.gdal.envelope import Envelope, OGREnvelope +from django.contrib.gis.gdal.error import GDALException, SRSException +from django.contrib.gis.gdal.feature import Feature +from django.contrib.gis.gdal.field import OGRFieldTypes +from django.contrib.gis.gdal.geometries import OGRGeometry +from django.contrib.gis.gdal.geomtype import OGRGeomType +from django.contrib.gis.gdal.prototypes import ds as capi +from django.contrib.gis.gdal.prototypes import geom as geom_api +from django.contrib.gis.gdal.prototypes import srs as srs_api +from django.contrib.gis.gdal.srs import SpatialReference +from django.utils.encoding import force_bytes, force_str + + +# For more information, see the OGR C API source code: +# https://gdal.org/api/vector_c_api.html +# +# The OGR_L_* routines are relevant here. +class Layer(GDALBase): + """ + A class that wraps an OGR Layer, needs to be instantiated from a DataSource + object. + """ + + def __init__(self, layer_ptr, ds): + """ + Initialize on an OGR C pointer to the Layer and the `DataSource` object + that owns this layer. The `DataSource` object is required so that a + reference to it is kept with this Layer. This prevents garbage + collection of the `DataSource` while this Layer is still active. + """ + if not layer_ptr: + raise GDALException("Cannot create Layer, invalid pointer given") + self.ptr = layer_ptr + self._ds = ds + self._ldefn = capi.get_layer_defn(self._ptr) + # Does the Layer support random reading? + self._random_read = self.test_capability(b"RandomRead") + + def __getitem__(self, index): + "Get the Feature at the specified index." + if isinstance(index, int): + # An integer index was given -- we cannot do a check based on the + # number of features because the beginning and ending feature IDs + # are not guaranteed to be 0 and len(layer)-1, respectively. + if index < 0: + raise IndexError("Negative indices are not allowed on OGR Layers.") + return self._make_feature(index) + elif isinstance(index, slice): + # A slice was given + start, stop, stride = index.indices(self.num_feat) + return [self._make_feature(fid) for fid in range(start, stop, stride)] + else: + raise TypeError( + "Integers and slices may only be used when indexing OGR Layers." + ) + + def __iter__(self): + "Iterate over each Feature in the Layer." + # ResetReading() must be called before iteration is to begin. + capi.reset_reading(self._ptr) + for i in range(self.num_feat): + yield Feature(capi.get_next_feature(self._ptr), self) + + def __len__(self): + "The length is the number of features." + return self.num_feat + + def __str__(self): + "The string name of the layer." + return self.name + + def _make_feature(self, feat_id): + """ + Helper routine for __getitem__ that constructs a Feature from the given + Feature ID. If the OGR Layer does not support random-access reading, + then each feature of the layer will be incremented through until the + a Feature is found matching the given feature ID. + """ + if self._random_read: + # If the Layer supports random reading, return. + try: + return Feature(capi.get_feature(self.ptr, feat_id), self) + except GDALException: + pass + else: + # Random access isn't supported, have to increment through + # each feature until the given feature ID is encountered. + for feat in self: + if feat.fid == feat_id: + return feat + # Should have returned a Feature, raise an IndexError. + raise IndexError("Invalid feature id: %s." % feat_id) + + # #### Layer properties #### + @property + def extent(self): + "Return the extent (an Envelope) of this layer." + env = OGREnvelope() + capi.get_extent(self.ptr, byref(env), 1) + return Envelope(env) + + @property + def name(self): + "Return the name of this layer in the Data Source." + name = capi.get_fd_name(self._ldefn) + return force_str(name, self._ds.encoding, strings_only=True) + + @property + def num_feat(self, force=1): + "Return the number of features in the Layer." + return capi.get_feature_count(self.ptr, force) + + @property + def num_fields(self): + "Return the number of fields in the Layer." + return capi.get_field_count(self._ldefn) + + @property + def geom_type(self): + "Return the geometry type (OGRGeomType) of the Layer." + return OGRGeomType(capi.get_fd_geom_type(self._ldefn)) + + @property + def srs(self): + "Return the Spatial Reference used in this Layer." + try: + ptr = capi.get_layer_srs(self.ptr) + return SpatialReference(srs_api.clone_srs(ptr)) + except SRSException: + return None + + @property + def fields(self): + """ + Return a list of string names corresponding to each of the Fields + available in this Layer. + """ + return [ + force_str( + capi.get_field_name(capi.get_field_defn(self._ldefn, i)), + self._ds.encoding, + strings_only=True, + ) + for i in range(self.num_fields) + ] + + @property + def field_types(self): + """ + Return a list of the types of fields in this Layer. For example, + return the list [OFTInteger, OFTReal, OFTString] for an OGR layer that + has an integer, a floating-point, and string fields. + """ + return [ + OGRFieldTypes[capi.get_field_type(capi.get_field_defn(self._ldefn, i))] + for i in range(self.num_fields) + ] + + @property + def field_widths(self): + "Return a list of the maximum field widths for the features." + return [ + capi.get_field_width(capi.get_field_defn(self._ldefn, i)) + for i in range(self.num_fields) + ] + + @property + def field_precisions(self): + "Return the field precisions for the features." + return [ + capi.get_field_precision(capi.get_field_defn(self._ldefn, i)) + for i in range(self.num_fields) + ] + + def _get_spatial_filter(self): + try: + return OGRGeometry(geom_api.clone_geom(capi.get_spatial_filter(self.ptr))) + except GDALException: + return None + + def _set_spatial_filter(self, filter): + if isinstance(filter, OGRGeometry): + capi.set_spatial_filter(self.ptr, filter.ptr) + elif isinstance(filter, (tuple, list)): + if not len(filter) == 4: + raise ValueError("Spatial filter list/tuple must have 4 elements.") + # Map c_double onto params -- if a bad type is passed in it + # will be caught here. + xmin, ymin, xmax, ymax = map(c_double, filter) + capi.set_spatial_filter_rect(self.ptr, xmin, ymin, xmax, ymax) + elif filter is None: + capi.set_spatial_filter(self.ptr, None) + else: + raise TypeError( + "Spatial filter must be either an OGRGeometry instance, a 4-tuple, or " + "None." + ) + + spatial_filter = property(_get_spatial_filter, _set_spatial_filter) + + # #### Layer Methods #### + def get_fields(self, field_name): + """ + Return a list containing the given field name for every Feature + in the Layer. + """ + if field_name not in self.fields: + raise GDALException("invalid field name: %s" % field_name) + return [feat.get(field_name) for feat in self] + + def get_geoms(self, geos=False): + """ + Return a list containing the OGRGeometry for every Feature in + the Layer. + """ + if geos: + from django.contrib.gis.geos import GEOSGeometry + + return [GEOSGeometry(feat.geom.wkb) for feat in self] + else: + return [feat.geom for feat in self] + + def test_capability(self, capability): + """ + Return a bool indicating whether the this Layer supports the given + capability (a string). Valid capability strings include: + 'RandomRead', 'SequentialWrite', 'RandomWrite', 'FastSpatialFilter', + 'FastFeatureCount', 'FastGetExtent', 'CreateField', 'Transactions', + 'DeleteFeature', and 'FastSetNextByIndex'. + """ + return bool(capi.test_capability(self.ptr, force_bytes(capability))) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/libgdal.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/libgdal.py new file mode 100644 index 0000000..30cba0f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/libgdal.py @@ -0,0 +1,140 @@ +import logging +import os +import re +from ctypes import CDLL, CFUNCTYPE, c_char_p, c_int +from ctypes.util import find_library + +from django.contrib.gis.gdal.error import GDALException +from django.core.exceptions import ImproperlyConfigured + +logger = logging.getLogger("django.contrib.gis") + +# Custom library path set? +try: + from django.conf import settings + + lib_path = settings.GDAL_LIBRARY_PATH +except (AttributeError, ImportError, ImproperlyConfigured, OSError): + lib_path = None + +if lib_path: + lib_names = None +elif os.name == "nt": + # Windows NT shared libraries + lib_names = [ + "gdal307", + "gdal306", + "gdal305", + "gdal304", + "gdal303", + "gdal302", + "gdal301", + "gdal300", + "gdal204", + ] +elif os.name == "posix": + # *NIX library names. + lib_names = [ + "gdal", + "GDAL", + "gdal3.7.0", + "gdal3.6.0", + "gdal3.5.0", + "gdal3.4.0", + "gdal3.3.0", + "gdal3.2.0", + "gdal3.1.0", + "gdal3.0.0", + "gdal2.4.0", + ] +else: + raise ImproperlyConfigured('GDAL is unsupported on OS "%s".' % os.name) + +# Using the ctypes `find_library` utility to find the +# path to the GDAL library from the list of library names. +if lib_names: + for lib_name in lib_names: + lib_path = find_library(lib_name) + if lib_path is not None: + break + +if lib_path is None: + raise ImproperlyConfigured( + 'Could not find the GDAL library (tried "%s"). Is GDAL installed? ' + "If it is, try setting GDAL_LIBRARY_PATH in your settings." + % '", "'.join(lib_names) + ) + +# This loads the GDAL/OGR C library +lgdal = CDLL(lib_path) + +# On Windows, the GDAL binaries have some OSR routines exported with +# STDCALL, while others are not. Thus, the library will also need to +# be loaded up as WinDLL for said OSR functions that require the +# different calling convention. +if os.name == "nt": + from ctypes import WinDLL + + lwingdal = WinDLL(lib_path) + + +def std_call(func): + """ + Return the correct STDCALL function for certain OSR routines on Win32 + platforms. + """ + if os.name == "nt": + return lwingdal[func] + else: + return lgdal[func] + + +# #### Version-information functions. #### + +# Return GDAL library version information with the given key. +_version_info = std_call("GDALVersionInfo") +_version_info.argtypes = [c_char_p] +_version_info.restype = c_char_p + + +def gdal_version(): + "Return only the GDAL version number information." + return _version_info(b"RELEASE_NAME") + + +def gdal_full_version(): + "Return the full GDAL version information." + return _version_info(b"") + + +def gdal_version_info(): + ver = gdal_version() + m = re.match(rb"^(?P\d+)\.(?P\d+)(?:\.(?P\d+))?", ver) + if not m: + raise GDALException('Could not parse GDAL version string "%s"' % ver) + major, minor, subminor = m.groups() + return (int(major), int(minor), subminor and int(subminor)) + + +GDAL_VERSION = gdal_version_info() + +# Set library error handling so as errors are logged +CPLErrorHandler = CFUNCTYPE(None, c_int, c_int, c_char_p) + + +def err_handler(error_class, error_number, message): + logger.error("GDAL_ERROR %d: %s", error_number, message) + + +err_handler = CPLErrorHandler(err_handler) + + +def function(name, args, restype): + func = std_call(name) + func.argtypes = args + func.restype = restype + return func + + +set_error_handler = function("CPLSetErrorHandler", [CPLErrorHandler], CPLErrorHandler) +set_error_handler(err_handler) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/prototypes/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/prototypes/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/prototypes/ds.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/prototypes/ds.py new file mode 100644 index 0000000..bc5250e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/prototypes/ds.py @@ -0,0 +1,99 @@ +""" + This module houses the ctypes function prototypes for OGR DataSource + related data structures. OGR_Dr_*, OGR_DS_*, OGR_L_*, OGR_F_*, + OGR_Fld_* routines are relevant here. +""" +from ctypes import POINTER, c_char_p, c_double, c_int, c_long, c_void_p + +from django.contrib.gis.gdal.envelope import OGREnvelope +from django.contrib.gis.gdal.libgdal import lgdal +from django.contrib.gis.gdal.prototypes.generation import ( + bool_output, + const_string_output, + double_output, + geom_output, + int64_output, + int_output, + srs_output, + void_output, + voidptr_output, +) + +c_int_p = POINTER(c_int) # shortcut type + +# Driver Routines +register_all = void_output(lgdal.OGRRegisterAll, [], errcheck=False) +cleanup_all = void_output(lgdal.OGRCleanupAll, [], errcheck=False) +get_driver = voidptr_output(lgdal.OGRGetDriver, [c_int]) +get_driver_by_name = voidptr_output( + lgdal.OGRGetDriverByName, [c_char_p], errcheck=False +) +get_driver_count = int_output(lgdal.OGRGetDriverCount, []) +get_driver_name = const_string_output( + lgdal.OGR_Dr_GetName, [c_void_p], decoding="ascii" +) + +# DataSource +open_ds = voidptr_output(lgdal.OGROpen, [c_char_p, c_int, POINTER(c_void_p)]) +destroy_ds = void_output(lgdal.OGR_DS_Destroy, [c_void_p], errcheck=False) +release_ds = void_output(lgdal.OGRReleaseDataSource, [c_void_p]) +get_ds_name = const_string_output(lgdal.OGR_DS_GetName, [c_void_p]) +get_layer = voidptr_output(lgdal.OGR_DS_GetLayer, [c_void_p, c_int]) +get_layer_by_name = voidptr_output(lgdal.OGR_DS_GetLayerByName, [c_void_p, c_char_p]) +get_layer_count = int_output(lgdal.OGR_DS_GetLayerCount, [c_void_p]) + +# Layer Routines +get_extent = void_output(lgdal.OGR_L_GetExtent, [c_void_p, POINTER(OGREnvelope), c_int]) +get_feature = voidptr_output(lgdal.OGR_L_GetFeature, [c_void_p, c_long]) +get_feature_count = int_output(lgdal.OGR_L_GetFeatureCount, [c_void_p, c_int]) +get_layer_defn = voidptr_output(lgdal.OGR_L_GetLayerDefn, [c_void_p]) +get_layer_srs = srs_output(lgdal.OGR_L_GetSpatialRef, [c_void_p]) +get_next_feature = voidptr_output(lgdal.OGR_L_GetNextFeature, [c_void_p]) +reset_reading = void_output(lgdal.OGR_L_ResetReading, [c_void_p], errcheck=False) +test_capability = int_output(lgdal.OGR_L_TestCapability, [c_void_p, c_char_p]) +get_spatial_filter = geom_output(lgdal.OGR_L_GetSpatialFilter, [c_void_p]) +set_spatial_filter = void_output( + lgdal.OGR_L_SetSpatialFilter, [c_void_p, c_void_p], errcheck=False +) +set_spatial_filter_rect = void_output( + lgdal.OGR_L_SetSpatialFilterRect, + [c_void_p, c_double, c_double, c_double, c_double], + errcheck=False, +) + +# Feature Definition Routines +get_fd_geom_type = int_output(lgdal.OGR_FD_GetGeomType, [c_void_p]) +get_fd_name = const_string_output(lgdal.OGR_FD_GetName, [c_void_p]) +get_feat_name = const_string_output(lgdal.OGR_FD_GetName, [c_void_p]) +get_field_count = int_output(lgdal.OGR_FD_GetFieldCount, [c_void_p]) +get_field_defn = voidptr_output(lgdal.OGR_FD_GetFieldDefn, [c_void_p, c_int]) + +# Feature Routines +clone_feature = voidptr_output(lgdal.OGR_F_Clone, [c_void_p]) +destroy_feature = void_output(lgdal.OGR_F_Destroy, [c_void_p], errcheck=False) +feature_equal = int_output(lgdal.OGR_F_Equal, [c_void_p, c_void_p]) +get_feat_geom_ref = geom_output(lgdal.OGR_F_GetGeometryRef, [c_void_p]) +get_feat_field_count = int_output(lgdal.OGR_F_GetFieldCount, [c_void_p]) +get_feat_field_defn = voidptr_output(lgdal.OGR_F_GetFieldDefnRef, [c_void_p, c_int]) +get_fid = int_output(lgdal.OGR_F_GetFID, [c_void_p]) +get_field_as_datetime = int_output( + lgdal.OGR_F_GetFieldAsDateTime, + [c_void_p, c_int, c_int_p, c_int_p, c_int_p, c_int_p, c_int_p, c_int_p], +) +get_field_as_double = double_output(lgdal.OGR_F_GetFieldAsDouble, [c_void_p, c_int]) +get_field_as_integer = int_output(lgdal.OGR_F_GetFieldAsInteger, [c_void_p, c_int]) +get_field_as_integer64 = int64_output( + lgdal.OGR_F_GetFieldAsInteger64, [c_void_p, c_int] +) +is_field_set = bool_output(lgdal.OGR_F_IsFieldSetAndNotNull, [c_void_p, c_int]) +get_field_as_string = const_string_output( + lgdal.OGR_F_GetFieldAsString, [c_void_p, c_int] +) +get_field_index = int_output(lgdal.OGR_F_GetFieldIndex, [c_void_p, c_char_p]) + +# Field Routines +get_field_name = const_string_output(lgdal.OGR_Fld_GetNameRef, [c_void_p]) +get_field_precision = int_output(lgdal.OGR_Fld_GetPrecision, [c_void_p]) +get_field_type = int_output(lgdal.OGR_Fld_GetType, [c_void_p]) +get_field_type_name = const_string_output(lgdal.OGR_GetFieldTypeName, [c_int]) +get_field_width = int_output(lgdal.OGR_Fld_GetWidth, [c_void_p]) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/prototypes/errcheck.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/prototypes/errcheck.py new file mode 100644 index 0000000..52bb7cb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/prototypes/errcheck.py @@ -0,0 +1,141 @@ +""" + This module houses the error-checking routines used by the GDAL + ctypes prototypes. +""" +from ctypes import c_void_p, string_at + +from django.contrib.gis.gdal.error import GDALException, SRSException, check_err +from django.contrib.gis.gdal.libgdal import lgdal + + +# Helper routines for retrieving pointers and/or values from +# arguments passed in by reference. +def arg_byref(args, offset=-1): + "Return the pointer argument's by-reference value." + return args[offset]._obj.value + + +def ptr_byref(args, offset=-1): + "Return the pointer argument passed in by-reference." + return args[offset]._obj + + +# ### String checking Routines ### +def check_const_string(result, func, cargs, offset=None, cpl=False): + """ + Similar functionality to `check_string`, but does not free the pointer. + """ + if offset: + check_err(result, cpl=cpl) + ptr = ptr_byref(cargs, offset) + return ptr.value + else: + return result + + +def check_string(result, func, cargs, offset=-1, str_result=False): + """ + Check the string output returned from the given function, and free + the string pointer allocated by OGR. The `str_result` keyword + may be used when the result is the string pointer, otherwise + the OGR error code is assumed. The `offset` keyword may be used + to extract the string pointer passed in by-reference at the given + slice offset in the function arguments. + """ + if str_result: + # For routines that return a string. + ptr = result + if not ptr: + s = None + else: + s = string_at(result) + else: + # Error-code return specified. + check_err(result) + ptr = ptr_byref(cargs, offset) + # Getting the string value + s = ptr.value + # Correctly freeing the allocated memory behind GDAL pointer + # with the VSIFree routine. + if ptr: + lgdal.VSIFree(ptr) + return s + + +# ### DataSource, Layer error-checking ### + + +# ### Envelope checking ### +def check_envelope(result, func, cargs, offset=-1): + "Check a function that returns an OGR Envelope by reference." + return ptr_byref(cargs, offset) + + +# ### Geometry error-checking routines ### +def check_geom(result, func, cargs): + "Check a function that returns a geometry." + # OGR_G_Clone may return an integer, even though the + # restype is set to c_void_p + if isinstance(result, int): + result = c_void_p(result) + if not result: + raise GDALException( + 'Invalid geometry pointer returned from "%s".' % func.__name__ + ) + return result + + +def check_geom_offset(result, func, cargs, offset=-1): + "Check the geometry at the given offset in the C parameter list." + check_err(result) + geom = ptr_byref(cargs, offset=offset) + return check_geom(geom, func, cargs) + + +# ### Spatial Reference error-checking routines ### +def check_srs(result, func, cargs): + if isinstance(result, int): + result = c_void_p(result) + if not result: + raise SRSException( + 'Invalid spatial reference pointer returned from "%s".' % func.__name__ + ) + return result + + +# ### Other error-checking routines ### +def check_arg_errcode(result, func, cargs, cpl=False): + """ + The error code is returned in the last argument, by reference. + Check its value with `check_err` before returning the result. + """ + check_err(arg_byref(cargs), cpl=cpl) + return result + + +def check_errcode(result, func, cargs, cpl=False): + """ + Check the error code returned (c_int). + """ + check_err(result, cpl=cpl) + + +def check_pointer(result, func, cargs): + "Make sure the result pointer is valid." + if isinstance(result, int): + result = c_void_p(result) + if result: + return result + else: + raise GDALException('Invalid pointer returned from "%s"' % func.__name__) + + +def check_str_arg(result, func, cargs): + """ + This is for the OSRGet[Angular|Linear]Units functions, which + require that the returned string pointer not be freed. This + returns both the double and string values. + """ + dbl = result + ptr = cargs[-1]._obj + return dbl, ptr.value.decode() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/prototypes/generation.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/prototypes/generation.py new file mode 100644 index 0000000..230e56f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/prototypes/generation.py @@ -0,0 +1,177 @@ +""" + This module contains functions that generate ctypes prototypes for the + GDAL routines. +""" +from ctypes import POINTER, c_bool, c_char_p, c_double, c_int, c_int64, c_void_p +from functools import partial + +from django.contrib.gis.gdal.prototypes.errcheck import ( + check_arg_errcode, + check_const_string, + check_errcode, + check_geom, + check_geom_offset, + check_pointer, + check_srs, + check_str_arg, + check_string, +) + + +class gdal_char_p(c_char_p): + pass + + +def bool_output(func, argtypes, errcheck=None): + """Generate a ctypes function that returns a boolean value.""" + func.argtypes = argtypes + func.restype = c_bool + if errcheck: + func.errcheck = errcheck + return func + + +def double_output(func, argtypes, errcheck=False, strarg=False, cpl=False): + "Generate a ctypes function that returns a double value." + func.argtypes = argtypes + func.restype = c_double + if errcheck: + func.errcheck = partial(check_arg_errcode, cpl=cpl) + if strarg: + func.errcheck = check_str_arg + return func + + +def geom_output(func, argtypes, offset=None): + """ + Generate a function that returns a Geometry either by reference + or directly (if the return_geom keyword is set to True). + """ + # Setting the argument types + func.argtypes = argtypes + + if not offset: + # When a geometry pointer is directly returned. + func.restype = c_void_p + func.errcheck = check_geom + else: + # Error code returned, geometry is returned by-reference. + func.restype = c_int + + def geomerrcheck(result, func, cargs): + return check_geom_offset(result, func, cargs, offset) + + func.errcheck = geomerrcheck + + return func + + +def int_output(func, argtypes, errcheck=None): + "Generate a ctypes function that returns an integer value." + func.argtypes = argtypes + func.restype = c_int + if errcheck: + func.errcheck = errcheck + return func + + +def int64_output(func, argtypes): + "Generate a ctypes function that returns a 64-bit integer value." + func.argtypes = argtypes + func.restype = c_int64 + return func + + +def srs_output(func, argtypes): + """ + Generate a ctypes prototype for the given function with + the given C arguments that returns a pointer to an OGR + Spatial Reference System. + """ + func.argtypes = argtypes + func.restype = c_void_p + func.errcheck = check_srs + return func + + +def const_string_output(func, argtypes, offset=None, decoding=None, cpl=False): + func.argtypes = argtypes + if offset: + func.restype = c_int + else: + func.restype = c_char_p + + def _check_const(result, func, cargs): + res = check_const_string(result, func, cargs, offset=offset, cpl=cpl) + if res and decoding: + res = res.decode(decoding) + return res + + func.errcheck = _check_const + + return func + + +def string_output(func, argtypes, offset=-1, str_result=False, decoding=None): + """ + Generate a ctypes prototype for the given function with the + given argument types that returns a string from a GDAL pointer. + The `const` flag indicates whether the allocated pointer should + be freed via the GDAL library routine VSIFree -- but only applies + only when `str_result` is True. + """ + func.argtypes = argtypes + if str_result: + # Use subclass of c_char_p so the error checking routine + # can free the memory at the pointer's address. + func.restype = gdal_char_p + else: + # Error code is returned + func.restype = c_int + + # Dynamically defining our error-checking function with the + # given offset. + def _check_str(result, func, cargs): + res = check_string(result, func, cargs, offset=offset, str_result=str_result) + if res and decoding: + res = res.decode(decoding) + return res + + func.errcheck = _check_str + return func + + +def void_output(func, argtypes, errcheck=True, cpl=False): + """ + For functions that don't only return an error code that needs to + be examined. + """ + if argtypes: + func.argtypes = argtypes + if errcheck: + # `errcheck` keyword may be set to False for routines that + # return void, rather than a status code. + func.restype = c_int + func.errcheck = partial(check_errcode, cpl=cpl) + else: + func.restype = None + + return func + + +def voidptr_output(func, argtypes, errcheck=True): + "For functions that return c_void_p." + func.argtypes = argtypes + func.restype = c_void_p + if errcheck: + func.errcheck = check_pointer + return func + + +def chararray_output(func, argtypes, errcheck=True): + """For functions that return a c_char_p array.""" + func.argtypes = argtypes + func.restype = POINTER(c_char_p) + if errcheck: + func.errcheck = check_pointer + return func diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/prototypes/geom.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/prototypes/geom.py new file mode 100644 index 0000000..06c2a75 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/prototypes/geom.py @@ -0,0 +1,139 @@ +from ctypes import POINTER, c_char_p, c_double, c_int, c_void_p + +from django.contrib.gis.gdal.envelope import OGREnvelope +from django.contrib.gis.gdal.libgdal import lgdal +from django.contrib.gis.gdal.prototypes.errcheck import check_envelope +from django.contrib.gis.gdal.prototypes.generation import ( + const_string_output, + double_output, + geom_output, + int_output, + srs_output, + string_output, + void_output, +) + + +# ### Generation routines specific to this module ### +def env_func(f, argtypes): + "For getting OGREnvelopes." + f.argtypes = argtypes + f.restype = None + f.errcheck = check_envelope + return f + + +def pnt_func(f): + "For accessing point information." + return double_output(f, [c_void_p, c_int]) + + +def topology_func(f): + f.argtypes = [c_void_p, c_void_p] + f.restype = c_int + f.errcheck = lambda result, func, cargs: bool(result) + return f + + +# ### OGR_G ctypes function prototypes ### + +# GeoJSON routines. +from_json = geom_output(lgdal.OGR_G_CreateGeometryFromJson, [c_char_p]) +to_json = string_output( + lgdal.OGR_G_ExportToJson, [c_void_p], str_result=True, decoding="ascii" +) +to_kml = string_output( + lgdal.OGR_G_ExportToKML, [c_void_p, c_char_p], str_result=True, decoding="ascii" +) + +# GetX, GetY, GetZ all return doubles. +getx = pnt_func(lgdal.OGR_G_GetX) +gety = pnt_func(lgdal.OGR_G_GetY) +getz = pnt_func(lgdal.OGR_G_GetZ) + +# Geometry creation routines. +from_wkb = geom_output( + lgdal.OGR_G_CreateFromWkb, [c_char_p, c_void_p, POINTER(c_void_p), c_int], offset=-2 +) +from_wkt = geom_output( + lgdal.OGR_G_CreateFromWkt, + [POINTER(c_char_p), c_void_p, POINTER(c_void_p)], + offset=-1, +) +from_gml = geom_output(lgdal.OGR_G_CreateFromGML, [c_char_p]) +create_geom = geom_output(lgdal.OGR_G_CreateGeometry, [c_int]) +clone_geom = geom_output(lgdal.OGR_G_Clone, [c_void_p]) +get_geom_ref = geom_output(lgdal.OGR_G_GetGeometryRef, [c_void_p, c_int]) +get_boundary = geom_output(lgdal.OGR_G_GetBoundary, [c_void_p]) +geom_convex_hull = geom_output(lgdal.OGR_G_ConvexHull, [c_void_p]) +geom_diff = geom_output(lgdal.OGR_G_Difference, [c_void_p, c_void_p]) +geom_intersection = geom_output(lgdal.OGR_G_Intersection, [c_void_p, c_void_p]) +geom_sym_diff = geom_output(lgdal.OGR_G_SymmetricDifference, [c_void_p, c_void_p]) +geom_union = geom_output(lgdal.OGR_G_Union, [c_void_p, c_void_p]) + +# Geometry modification routines. +add_geom = void_output(lgdal.OGR_G_AddGeometry, [c_void_p, c_void_p]) +import_wkt = void_output(lgdal.OGR_G_ImportFromWkt, [c_void_p, POINTER(c_char_p)]) + +# Destroys a geometry +destroy_geom = void_output(lgdal.OGR_G_DestroyGeometry, [c_void_p], errcheck=False) + +# Geometry export routines. +to_wkb = void_output( + lgdal.OGR_G_ExportToWkb, None, errcheck=True +) # special handling for WKB. +to_wkt = string_output( + lgdal.OGR_G_ExportToWkt, [c_void_p, POINTER(c_char_p)], decoding="ascii" +) +to_gml = string_output( + lgdal.OGR_G_ExportToGML, [c_void_p], str_result=True, decoding="ascii" +) +get_wkbsize = int_output(lgdal.OGR_G_WkbSize, [c_void_p]) + +# Geometry spatial-reference related routines. +assign_srs = void_output( + lgdal.OGR_G_AssignSpatialReference, [c_void_p, c_void_p], errcheck=False +) +get_geom_srs = srs_output(lgdal.OGR_G_GetSpatialReference, [c_void_p]) + +# Geometry properties +get_area = double_output(lgdal.OGR_G_GetArea, [c_void_p]) +get_centroid = void_output(lgdal.OGR_G_Centroid, [c_void_p, c_void_p]) +get_dims = int_output(lgdal.OGR_G_GetDimension, [c_void_p]) +get_coord_dim = int_output(lgdal.OGR_G_GetCoordinateDimension, [c_void_p]) +set_coord_dim = void_output( + lgdal.OGR_G_SetCoordinateDimension, [c_void_p, c_int], errcheck=False +) +is_empty = int_output( + lgdal.OGR_G_IsEmpty, [c_void_p], errcheck=lambda result, func, cargs: bool(result) +) + +get_geom_count = int_output(lgdal.OGR_G_GetGeometryCount, [c_void_p]) +get_geom_name = const_string_output( + lgdal.OGR_G_GetGeometryName, [c_void_p], decoding="ascii" +) +get_geom_type = int_output(lgdal.OGR_G_GetGeometryType, [c_void_p]) +get_point_count = int_output(lgdal.OGR_G_GetPointCount, [c_void_p]) +get_point = void_output( + lgdal.OGR_G_GetPoint, + [c_void_p, c_int, POINTER(c_double), POINTER(c_double), POINTER(c_double)], + errcheck=False, +) +geom_close_rings = void_output(lgdal.OGR_G_CloseRings, [c_void_p], errcheck=False) + +# Topology routines. +ogr_contains = topology_func(lgdal.OGR_G_Contains) +ogr_crosses = topology_func(lgdal.OGR_G_Crosses) +ogr_disjoint = topology_func(lgdal.OGR_G_Disjoint) +ogr_equals = topology_func(lgdal.OGR_G_Equals) +ogr_intersects = topology_func(lgdal.OGR_G_Intersects) +ogr_overlaps = topology_func(lgdal.OGR_G_Overlaps) +ogr_touches = topology_func(lgdal.OGR_G_Touches) +ogr_within = topology_func(lgdal.OGR_G_Within) + +# Transformation routines. +geom_transform = void_output(lgdal.OGR_G_Transform, [c_void_p, c_void_p]) +geom_transform_to = void_output(lgdal.OGR_G_TransformTo, [c_void_p, c_void_p]) + +# For retrieving the envelope of the geometry. +get_envelope = env_func(lgdal.OGR_G_GetEnvelope, [c_void_p, POINTER(OGREnvelope)]) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/prototypes/raster.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/prototypes/raster.py new file mode 100644 index 0000000..59b930c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/prototypes/raster.py @@ -0,0 +1,177 @@ +""" +This module houses the ctypes function prototypes for GDAL DataSource (raster) +related data structures. +""" +from ctypes import POINTER, c_bool, c_char_p, c_double, c_int, c_void_p +from functools import partial + +from django.contrib.gis.gdal.libgdal import std_call +from django.contrib.gis.gdal.prototypes.generation import ( + chararray_output, + const_string_output, + double_output, + int_output, + void_output, + voidptr_output, +) + +# For more detail about c function names and definitions see +# https://gdal.org/api/raster_c_api.html +# https://gdal.org/doxygen/gdalwarper_8h.html +# https://gdal.org/api/gdal_utils.html + +# Prepare partial functions that use cpl error codes +void_output = partial(void_output, cpl=True) +const_string_output = partial(const_string_output, cpl=True) +double_output = partial(double_output, cpl=True) + +# Raster Driver Routines +register_all = void_output(std_call("GDALAllRegister"), [], errcheck=False) +get_driver = voidptr_output(std_call("GDALGetDriver"), [c_int]) +get_driver_by_name = voidptr_output( + std_call("GDALGetDriverByName"), [c_char_p], errcheck=False +) +get_driver_count = int_output(std_call("GDALGetDriverCount"), []) +get_driver_description = const_string_output(std_call("GDALGetDescription"), [c_void_p]) + +# Raster Data Source Routines +create_ds = voidptr_output( + std_call("GDALCreate"), [c_void_p, c_char_p, c_int, c_int, c_int, c_int, c_void_p] +) +open_ds = voidptr_output(std_call("GDALOpen"), [c_char_p, c_int]) +close_ds = void_output(std_call("GDALClose"), [c_void_p], errcheck=False) +flush_ds = int_output(std_call("GDALFlushCache"), [c_void_p]) +copy_ds = voidptr_output( + std_call("GDALCreateCopy"), + [c_void_p, c_char_p, c_void_p, c_int, POINTER(c_char_p), c_void_p, c_void_p], +) +add_band_ds = void_output(std_call("GDALAddBand"), [c_void_p, c_int]) +get_ds_description = const_string_output(std_call("GDALGetDescription"), [c_void_p]) +get_ds_driver = voidptr_output(std_call("GDALGetDatasetDriver"), [c_void_p]) +get_ds_info = const_string_output(std_call("GDALInfo"), [c_void_p, c_void_p]) +get_ds_xsize = int_output(std_call("GDALGetRasterXSize"), [c_void_p]) +get_ds_ysize = int_output(std_call("GDALGetRasterYSize"), [c_void_p]) +get_ds_raster_count = int_output(std_call("GDALGetRasterCount"), [c_void_p]) +get_ds_raster_band = voidptr_output(std_call("GDALGetRasterBand"), [c_void_p, c_int]) +get_ds_projection_ref = const_string_output( + std_call("GDALGetProjectionRef"), [c_void_p] +) +set_ds_projection_ref = void_output(std_call("GDALSetProjection"), [c_void_p, c_char_p]) +get_ds_geotransform = void_output( + std_call("GDALGetGeoTransform"), [c_void_p, POINTER(c_double * 6)], errcheck=False +) +set_ds_geotransform = void_output( + std_call("GDALSetGeoTransform"), [c_void_p, POINTER(c_double * 6)] +) + +get_ds_metadata = chararray_output( + std_call("GDALGetMetadata"), [c_void_p, c_char_p], errcheck=False +) +set_ds_metadata = void_output( + std_call("GDALSetMetadata"), [c_void_p, POINTER(c_char_p), c_char_p] +) +get_ds_metadata_domain_list = chararray_output( + std_call("GDALGetMetadataDomainList"), [c_void_p], errcheck=False +) +get_ds_metadata_item = const_string_output( + std_call("GDALGetMetadataItem"), [c_void_p, c_char_p, c_char_p] +) +set_ds_metadata_item = const_string_output( + std_call("GDALSetMetadataItem"), [c_void_p, c_char_p, c_char_p, c_char_p] +) +free_dsl = void_output(std_call("CSLDestroy"), [POINTER(c_char_p)], errcheck=False) + +# Raster Band Routines +band_io = void_output( + std_call("GDALRasterIO"), + [ + c_void_p, + c_int, + c_int, + c_int, + c_int, + c_int, + c_void_p, + c_int, + c_int, + c_int, + c_int, + c_int, + ], +) +get_band_xsize = int_output(std_call("GDALGetRasterBandXSize"), [c_void_p]) +get_band_ysize = int_output(std_call("GDALGetRasterBandYSize"), [c_void_p]) +get_band_index = int_output(std_call("GDALGetBandNumber"), [c_void_p]) +get_band_description = const_string_output(std_call("GDALGetDescription"), [c_void_p]) +get_band_ds = voidptr_output(std_call("GDALGetBandDataset"), [c_void_p]) +get_band_datatype = int_output(std_call("GDALGetRasterDataType"), [c_void_p]) +get_band_color_interp = int_output( + std_call("GDALGetRasterColorInterpretation"), [c_void_p] +) +get_band_nodata_value = double_output( + std_call("GDALGetRasterNoDataValue"), [c_void_p, POINTER(c_int)] +) +set_band_nodata_value = void_output( + std_call("GDALSetRasterNoDataValue"), [c_void_p, c_double] +) +delete_band_nodata_value = void_output( + std_call("GDALDeleteRasterNoDataValue"), [c_void_p] +) +get_band_statistics = void_output( + std_call("GDALGetRasterStatistics"), + [ + c_void_p, + c_int, + c_int, + POINTER(c_double), + POINTER(c_double), + POINTER(c_double), + POINTER(c_double), + c_void_p, + c_void_p, + ], +) +compute_band_statistics = void_output( + std_call("GDALComputeRasterStatistics"), + [ + c_void_p, + c_int, + POINTER(c_double), + POINTER(c_double), + POINTER(c_double), + POINTER(c_double), + c_void_p, + c_void_p, + ], +) + +# Reprojection routine +reproject_image = void_output( + std_call("GDALReprojectImage"), + [ + c_void_p, + c_char_p, + c_void_p, + c_char_p, + c_int, + c_double, + c_double, + c_void_p, + c_void_p, + c_void_p, + ], +) +auto_create_warped_vrt = voidptr_output( + std_call("GDALAutoCreateWarpedVRT"), + [c_void_p, c_char_p, c_char_p, c_int, c_double, c_void_p], +) + +# Create VSI gdal raster files from in-memory buffers. +# https://gdal.org/api/cpl.html#cpl-vsi-h +create_vsi_file_from_mem_buffer = voidptr_output( + std_call("VSIFileFromMemBuffer"), [c_char_p, c_void_p, c_int, c_int] +) +get_mem_buffer_from_vsi_file = voidptr_output( + std_call("VSIGetMemFileBuffer"), [c_char_p, POINTER(c_int), c_bool] +) +unlink_vsi_file = int_output(std_call("VSIUnlink"), [c_char_p]) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/prototypes/srs.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/prototypes/srs.py new file mode 100644 index 0000000..721eba8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/prototypes/srs.py @@ -0,0 +1,109 @@ +from ctypes import POINTER, c_char_p, c_int, c_void_p + +from django.contrib.gis.gdal.libgdal import GDAL_VERSION, lgdal, std_call +from django.contrib.gis.gdal.prototypes.generation import ( + const_string_output, + double_output, + int_output, + srs_output, + string_output, + void_output, +) + + +# Shortcut generation for routines with known parameters. +def srs_double(f): + """ + Create a function prototype for the OSR routines that take + the OSRSpatialReference object and return a double value. + """ + return double_output(f, [c_void_p, POINTER(c_int)], errcheck=True) + + +def units_func(f): + """ + Create a ctypes function prototype for OSR units functions, e.g., + OSRGetAngularUnits, OSRGetLinearUnits. + """ + return double_output(f, [c_void_p, POINTER(c_char_p)], strarg=True) + + +# Creation & destruction. +clone_srs = srs_output(std_call("OSRClone"), [c_void_p]) +new_srs = srs_output(std_call("OSRNewSpatialReference"), [c_char_p]) +release_srs = void_output(lgdal.OSRRelease, [c_void_p], errcheck=False) +destroy_srs = void_output( + std_call("OSRDestroySpatialReference"), [c_void_p], errcheck=False +) +srs_validate = void_output(lgdal.OSRValidate, [c_void_p]) + +if GDAL_VERSION >= (3, 0): + set_axis_strategy = void_output( + lgdal.OSRSetAxisMappingStrategy, [c_void_p, c_int], errcheck=False + ) + +# Getting the semi_major, semi_minor, and flattening functions. +semi_major = srs_double(lgdal.OSRGetSemiMajor) +semi_minor = srs_double(lgdal.OSRGetSemiMinor) +invflattening = srs_double(lgdal.OSRGetInvFlattening) + +# WKT, PROJ, EPSG, XML importation routines. +from_wkt = void_output(lgdal.OSRImportFromWkt, [c_void_p, POINTER(c_char_p)]) +from_proj = void_output(lgdal.OSRImportFromProj4, [c_void_p, c_char_p]) +from_epsg = void_output(std_call("OSRImportFromEPSG"), [c_void_p, c_int]) +from_xml = void_output(lgdal.OSRImportFromXML, [c_void_p, c_char_p]) +from_user_input = void_output(std_call("OSRSetFromUserInput"), [c_void_p, c_char_p]) + +# Morphing to/from ESRI WKT. +morph_to_esri = void_output(lgdal.OSRMorphToESRI, [c_void_p]) +morph_from_esri = void_output(lgdal.OSRMorphFromESRI, [c_void_p]) + +# Identifying the EPSG +identify_epsg = void_output(lgdal.OSRAutoIdentifyEPSG, [c_void_p]) + +# Getting the angular_units, linear_units functions +linear_units = units_func(lgdal.OSRGetLinearUnits) +angular_units = units_func(lgdal.OSRGetAngularUnits) + +# For exporting to WKT, PROJ, "Pretty" WKT, and XML. +to_wkt = string_output( + std_call("OSRExportToWkt"), [c_void_p, POINTER(c_char_p)], decoding="utf-8" +) +to_proj = string_output( + std_call("OSRExportToProj4"), [c_void_p, POINTER(c_char_p)], decoding="ascii" +) +to_pretty_wkt = string_output( + std_call("OSRExportToPrettyWkt"), + [c_void_p, POINTER(c_char_p), c_int], + offset=-2, + decoding="utf-8", +) + +to_xml = string_output( + lgdal.OSRExportToXML, + [c_void_p, POINTER(c_char_p), c_char_p], + offset=-2, + decoding="utf-8", +) + +# String attribute retrieval routines. +get_attr_value = const_string_output( + std_call("OSRGetAttrValue"), [c_void_p, c_char_p, c_int], decoding="utf-8" +) +get_auth_name = const_string_output( + lgdal.OSRGetAuthorityName, [c_void_p, c_char_p], decoding="ascii" +) +get_auth_code = const_string_output( + lgdal.OSRGetAuthorityCode, [c_void_p, c_char_p], decoding="ascii" +) + +# SRS Properties +isgeographic = int_output(lgdal.OSRIsGeographic, [c_void_p]) +islocal = int_output(lgdal.OSRIsLocal, [c_void_p]) +isprojected = int_output(lgdal.OSRIsProjected, [c_void_p]) + +# Coordinate transformation +new_ct = srs_output(std_call("OCTNewCoordinateTransformation"), [c_void_p, c_void_p]) +destroy_ct = void_output( + std_call("OCTDestroyCoordinateTransformation"), [c_void_p], errcheck=False +) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/raster/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/raster/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/raster/band.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/raster/band.py new file mode 100644 index 0000000..c3ec960 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/raster/band.py @@ -0,0 +1,273 @@ +from ctypes import byref, c_double, c_int, c_void_p + +from django.contrib.gis.gdal.error import GDALException +from django.contrib.gis.gdal.prototypes import raster as capi +from django.contrib.gis.gdal.raster.base import GDALRasterBase +from django.contrib.gis.shortcuts import numpy +from django.utils.encoding import force_str + +from .const import ( + GDAL_COLOR_TYPES, + GDAL_INTEGER_TYPES, + GDAL_PIXEL_TYPES, + GDAL_TO_CTYPES, +) + + +class GDALBand(GDALRasterBase): + """ + Wrap a GDAL raster band, needs to be obtained from a GDALRaster object. + """ + + def __init__(self, source, index): + self.source = source + self._ptr = capi.get_ds_raster_band(source._ptr, index) + + def _flush(self): + """ + Call the flush method on the Band's parent raster and force a refresh + of the statistics attribute when requested the next time. + """ + self.source._flush() + self._stats_refresh = True + + @property + def description(self): + """ + Return the description string of the band. + """ + return force_str(capi.get_band_description(self._ptr)) + + @property + def width(self): + """ + Width (X axis) in pixels of the band. + """ + return capi.get_band_xsize(self._ptr) + + @property + def height(self): + """ + Height (Y axis) in pixels of the band. + """ + return capi.get_band_ysize(self._ptr) + + @property + def pixel_count(self): + """ + Return the total number of pixels in this band. + """ + return self.width * self.height + + _stats_refresh = False + + def statistics(self, refresh=False, approximate=False): + """ + Compute statistics on the pixel values of this band. + + The return value is a tuple with the following structure: + (minimum, maximum, mean, standard deviation). + + If approximate=True, the statistics may be computed based on overviews + or a subset of image tiles. + + If refresh=True, the statistics will be computed from the data directly, + and the cache will be updated where applicable. + + For empty bands (where all pixel values are nodata), all statistics + values are returned as None. + + For raster formats using Persistent Auxiliary Metadata (PAM) services, + the statistics might be cached in an auxiliary file. + """ + # Prepare array with arguments for capi function + smin, smax, smean, sstd = c_double(), c_double(), c_double(), c_double() + stats_args = [ + self._ptr, + c_int(approximate), + byref(smin), + byref(smax), + byref(smean), + byref(sstd), + c_void_p(), + c_void_p(), + ] + + if refresh or self._stats_refresh: + func = capi.compute_band_statistics + else: + # Add additional argument to force computation if there is no + # existing PAM file to take the values from. + force = True + stats_args.insert(2, c_int(force)) + func = capi.get_band_statistics + + # Computation of statistics fails for empty bands. + try: + func(*stats_args) + result = smin.value, smax.value, smean.value, sstd.value + except GDALException: + result = (None, None, None, None) + + self._stats_refresh = False + + return result + + @property + def min(self): + """ + Return the minimum pixel value for this band. + """ + return self.statistics()[0] + + @property + def max(self): + """ + Return the maximum pixel value for this band. + """ + return self.statistics()[1] + + @property + def mean(self): + """ + Return the mean of all pixel values of this band. + """ + return self.statistics()[2] + + @property + def std(self): + """ + Return the standard deviation of all pixel values of this band. + """ + return self.statistics()[3] + + @property + def nodata_value(self): + """ + Return the nodata value for this band, or None if it isn't set. + """ + # Get value and nodata exists flag + nodata_exists = c_int() + value = capi.get_band_nodata_value(self._ptr, nodata_exists) + if not nodata_exists: + value = None + # If the pixeltype is an integer, convert to int + elif self.datatype() in GDAL_INTEGER_TYPES: + value = int(value) + return value + + @nodata_value.setter + def nodata_value(self, value): + """ + Set the nodata value for this band. + """ + if value is None: + capi.delete_band_nodata_value(self._ptr) + elif not isinstance(value, (int, float)): + raise ValueError("Nodata value must be numeric or None.") + else: + capi.set_band_nodata_value(self._ptr, value) + self._flush() + + def datatype(self, as_string=False): + """ + Return the GDAL Pixel Datatype for this band. + """ + dtype = capi.get_band_datatype(self._ptr) + if as_string: + dtype = GDAL_PIXEL_TYPES[dtype] + return dtype + + def color_interp(self, as_string=False): + """Return the GDAL color interpretation for this band.""" + color = capi.get_band_color_interp(self._ptr) + if as_string: + color = GDAL_COLOR_TYPES[color] + return color + + def data(self, data=None, offset=None, size=None, shape=None, as_memoryview=False): + """ + Read or writes pixel values for this band. Blocks of data can + be accessed by specifying the width, height and offset of the + desired block. The same specification can be used to update + parts of a raster by providing an array of values. + + Allowed input data types are bytes, memoryview, list, tuple, and array. + """ + offset = offset or (0, 0) + size = size or (self.width - offset[0], self.height - offset[1]) + shape = shape or size + if any(x <= 0 for x in size): + raise ValueError("Offset too big for this raster.") + + if size[0] > self.width or size[1] > self.height: + raise ValueError("Size is larger than raster.") + + # Create ctypes type array generator + ctypes_array = GDAL_TO_CTYPES[self.datatype()] * (shape[0] * shape[1]) + + if data is None: + # Set read mode + access_flag = 0 + # Prepare empty ctypes array + data_array = ctypes_array() + else: + # Set write mode + access_flag = 1 + + # Instantiate ctypes array holding the input data + if isinstance(data, (bytes, memoryview)) or ( + numpy and isinstance(data, numpy.ndarray) + ): + data_array = ctypes_array.from_buffer_copy(data) + else: + data_array = ctypes_array(*data) + + # Access band + capi.band_io( + self._ptr, + access_flag, + offset[0], + offset[1], + size[0], + size[1], + byref(data_array), + shape[0], + shape[1], + self.datatype(), + 0, + 0, + ) + + # Return data as numpy array if possible, otherwise as list + if data is None: + if as_memoryview: + return memoryview(data_array) + elif numpy: + # reshape() needs a reshape parameter with the height first. + return numpy.frombuffer( + data_array, dtype=numpy.dtype(data_array) + ).reshape(tuple(reversed(size))) + else: + return list(data_array) + else: + self._flush() + + +class BandList(list): + def __init__(self, source): + self.source = source + super().__init__() + + def __iter__(self): + for idx in range(1, len(self) + 1): + yield GDALBand(self.source, idx) + + def __len__(self): + return capi.get_ds_raster_count(self.source._ptr) + + def __getitem__(self, index): + try: + return GDALBand(self.source, index + 1) + except GDALException: + raise GDALException("Unable to get band index %d" % index) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/raster/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/raster/base.py new file mode 100644 index 0000000..3d95c90 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/raster/base.py @@ -0,0 +1,77 @@ +from django.contrib.gis.gdal.base import GDALBase +from django.contrib.gis.gdal.prototypes import raster as capi + + +class GDALRasterBase(GDALBase): + """ + Attributes that exist on both GDALRaster and GDALBand. + """ + + @property + def metadata(self): + """ + Return the metadata for this raster or band. The return value is a + nested dictionary, where the first-level key is the metadata domain and + the second-level is the metadata item names and values for that domain. + """ + # The initial metadata domain list contains the default domain. + # The default is returned if domain name is None. + domain_list = ["DEFAULT"] + + # Get additional metadata domains from the raster. + meta_list = capi.get_ds_metadata_domain_list(self._ptr) + if meta_list: + # The number of domains is unknown, so retrieve data until there + # are no more values in the ctypes array. + counter = 0 + domain = meta_list[counter] + while domain: + domain_list.append(domain.decode()) + counter += 1 + domain = meta_list[counter] + + # Free domain list array. + capi.free_dsl(meta_list) + + # Retrieve metadata values for each domain. + result = {} + for domain in domain_list: + # Get metadata for this domain. + data = capi.get_ds_metadata( + self._ptr, + (None if domain == "DEFAULT" else domain.encode()), + ) + if not data: + continue + # The number of metadata items is unknown, so retrieve data until + # there are no more values in the ctypes array. + domain_meta = {} + counter = 0 + item = data[counter] + while item: + key, val = item.decode().split("=") + domain_meta[key] = val + counter += 1 + item = data[counter] + # The default domain values are returned if domain is None. + result[domain or "DEFAULT"] = domain_meta + return result + + @metadata.setter + def metadata(self, value): + """ + Set the metadata. Update only the domains that are contained in the + value dictionary. + """ + # Loop through domains. + for domain, metadata in value.items(): + # Set the domain to None for the default, otherwise encode. + domain = None if domain == "DEFAULT" else domain.encode() + # Set each metadata entry separately. + for meta_name, meta_value in metadata.items(): + capi.set_ds_metadata_item( + self._ptr, + meta_name.encode(), + meta_value.encode() if meta_value else None, + domain, + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/raster/const.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/raster/const.py new file mode 100644 index 0000000..dccc9cf --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/raster/const.py @@ -0,0 +1,104 @@ +""" +GDAL - Constant definitions +""" +from ctypes import ( + c_double, + c_float, + c_int8, + c_int16, + c_int32, + c_int64, + c_ubyte, + c_uint16, + c_uint32, + c_uint64, +) + +# See https://gdal.org/api/raster_c_api.html#_CPPv412GDALDataType +GDAL_PIXEL_TYPES = { + 0: "GDT_Unknown", # Unknown or unspecified type + 1: "GDT_Byte", # Eight bit unsigned integer + 2: "GDT_UInt16", # Sixteen bit unsigned integer + 3: "GDT_Int16", # Sixteen bit signed integer + 4: "GDT_UInt32", # Thirty-two bit unsigned integer + 5: "GDT_Int32", # Thirty-two bit signed integer + 6: "GDT_Float32", # Thirty-two bit floating point + 7: "GDT_Float64", # Sixty-four bit floating point + 8: "GDT_CInt16", # Complex Int16 + 9: "GDT_CInt32", # Complex Int32 + 10: "GDT_CFloat32", # Complex Float32 + 11: "GDT_CFloat64", # Complex Float64 + 12: "GDT_UInt64", # 64 bit unsigned integer (GDAL 3.5+). + 13: "GDT_Int64", # 64 bit signed integer (GDAL 3.5+). + 14: "GDT_Int8", # 8 bit signed integer (GDAL 3.7+). +} + +# A list of gdal datatypes that are integers. +GDAL_INTEGER_TYPES = [1, 2, 3, 4, 5, 12, 13, 14] + +# Lookup values to convert GDAL pixel type indices into ctypes objects. +# The GDAL band-io works with ctypes arrays to hold data to be written +# or to hold the space for data to be read into. The lookup below helps +# selecting the right ctypes object for a given gdal pixel type. +GDAL_TO_CTYPES = [ + None, + c_ubyte, + c_uint16, + c_int16, + c_uint32, + c_int32, + c_float, + c_double, + None, + None, + None, + None, + c_uint64, + c_int64, + c_int8, +] + +# List of resampling algorithms that can be used to warp a GDALRaster. +GDAL_RESAMPLE_ALGORITHMS = { + "NearestNeighbour": 0, + "Bilinear": 1, + "Cubic": 2, + "CubicSpline": 3, + "Lanczos": 4, + "Average": 5, + "Mode": 6, +} + +# See https://gdal.org/api/raster_c_api.html#_CPPv415GDALColorInterp +GDAL_COLOR_TYPES = { + 0: "GCI_Undefined", # Undefined, default value, i.e. not known + 1: "GCI_GrayIndex", # Grayscale + 2: "GCI_PaletteIndex", # Paletted + 3: "GCI_RedBand", # Red band of RGBA image + 4: "GCI_GreenBand", # Green band of RGBA image + 5: "GCI_BlueBand", # Blue band of RGBA image + 6: "GCI_AlphaBand", # Alpha (0=transparent, 255=opaque) + 7: "GCI_HueBand", # Hue band of HLS image + 8: "GCI_SaturationBand", # Saturation band of HLS image + 9: "GCI_LightnessBand", # Lightness band of HLS image + 10: "GCI_CyanBand", # Cyan band of CMYK image + 11: "GCI_MagentaBand", # Magenta band of CMYK image + 12: "GCI_YellowBand", # Yellow band of CMYK image + 13: "GCI_BlackBand", # Black band of CMLY image + 14: "GCI_YCbCr_YBand", # Y Luminance + 15: "GCI_YCbCr_CbBand", # Cb Chroma + 16: "GCI_YCbCr_CrBand", # Cr Chroma, also GCI_Max +} + +# GDAL virtual filesystems prefix. +VSI_FILESYSTEM_PREFIX = "/vsi" + +# Fixed base path for buffer-based GDAL in-memory files. +VSI_MEM_FILESYSTEM_BASE_PATH = "/vsimem/" + +# Should the memory file system take ownership of the buffer, freeing it when +# the file is deleted? (No, GDALRaster.__del__() will delete the buffer.) +VSI_TAKE_BUFFER_OWNERSHIP = False + +# Should a VSI file be removed when retrieving its buffer? +VSI_DELETE_BUFFER_ON_READ = False diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/raster/source.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/raster/source.py new file mode 100644 index 0000000..b33eb11 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/raster/source.py @@ -0,0 +1,541 @@ +import json +import os +import sys +import uuid +from ctypes import ( + addressof, + byref, + c_buffer, + c_char_p, + c_double, + c_int, + c_void_p, + string_at, +) +from pathlib import Path + +from django.contrib.gis.gdal.driver import Driver +from django.contrib.gis.gdal.error import GDALException +from django.contrib.gis.gdal.prototypes import raster as capi +from django.contrib.gis.gdal.raster.band import BandList +from django.contrib.gis.gdal.raster.base import GDALRasterBase +from django.contrib.gis.gdal.raster.const import ( + GDAL_RESAMPLE_ALGORITHMS, + VSI_DELETE_BUFFER_ON_READ, + VSI_FILESYSTEM_PREFIX, + VSI_MEM_FILESYSTEM_BASE_PATH, + VSI_TAKE_BUFFER_OWNERSHIP, +) +from django.contrib.gis.gdal.srs import SpatialReference, SRSException +from django.contrib.gis.geometry import json_regex +from django.utils.encoding import force_bytes, force_str +from django.utils.functional import cached_property + + +class TransformPoint(list): + indices = { + "origin": (0, 3), + "scale": (1, 5), + "skew": (2, 4), + } + + def __init__(self, raster, prop): + x = raster.geotransform[self.indices[prop][0]] + y = raster.geotransform[self.indices[prop][1]] + super().__init__([x, y]) + self._raster = raster + self._prop = prop + + @property + def x(self): + return self[0] + + @x.setter + def x(self, value): + gtf = self._raster.geotransform + gtf[self.indices[self._prop][0]] = value + self._raster.geotransform = gtf + + @property + def y(self): + return self[1] + + @y.setter + def y(self, value): + gtf = self._raster.geotransform + gtf[self.indices[self._prop][1]] = value + self._raster.geotransform = gtf + + +class GDALRaster(GDALRasterBase): + """ + Wrap a raster GDAL Data Source object. + """ + + destructor = capi.close_ds + + def __init__(self, ds_input, write=False): + self._write = 1 if write else 0 + Driver.ensure_registered() + + # Preprocess json inputs. This converts json strings to dictionaries, + # which are parsed below the same way as direct dictionary inputs. + if isinstance(ds_input, str) and json_regex.match(ds_input): + ds_input = json.loads(ds_input) + + # If input is a valid file path, try setting file as source. + if isinstance(ds_input, (str, Path)): + ds_input = str(ds_input) + if not ds_input.startswith(VSI_FILESYSTEM_PREFIX) and not os.path.exists( + ds_input + ): + raise GDALException( + 'Unable to read raster source input "%s".' % ds_input + ) + try: + # GDALOpen will auto-detect the data source type. + self._ptr = capi.open_ds(force_bytes(ds_input), self._write) + except GDALException as err: + raise GDALException( + 'Could not open the datasource at "{}" ({}).'.format(ds_input, err) + ) + elif isinstance(ds_input, bytes): + # Create a new raster in write mode. + self._write = 1 + # Get size of buffer. + size = sys.getsizeof(ds_input) + # Pass data to ctypes, keeping a reference to the ctypes object so + # that the vsimem file remains available until the GDALRaster is + # deleted. + self._ds_input = c_buffer(ds_input) + # Create random name to reference in vsimem filesystem. + vsi_path = os.path.join(VSI_MEM_FILESYSTEM_BASE_PATH, str(uuid.uuid4())) + # Create vsimem file from buffer. + capi.create_vsi_file_from_mem_buffer( + force_bytes(vsi_path), + byref(self._ds_input), + size, + VSI_TAKE_BUFFER_OWNERSHIP, + ) + # Open the new vsimem file as a GDALRaster. + try: + self._ptr = capi.open_ds(force_bytes(vsi_path), self._write) + except GDALException: + # Remove the broken file from the VSI filesystem. + capi.unlink_vsi_file(force_bytes(vsi_path)) + raise GDALException("Failed creating VSI raster from the input buffer.") + elif isinstance(ds_input, dict): + # A new raster needs to be created in write mode + self._write = 1 + + # Create driver (in memory by default) + driver = Driver(ds_input.get("driver", "MEM")) + + # For out of memory drivers, check filename argument + if driver.name != "MEM" and "name" not in ds_input: + raise GDALException( + 'Specify name for creation of raster with driver "{}".'.format( + driver.name + ) + ) + + # Check if width and height where specified + if "width" not in ds_input or "height" not in ds_input: + raise GDALException( + "Specify width and height attributes for JSON or dict input." + ) + + # Check if srid was specified + if "srid" not in ds_input: + raise GDALException("Specify srid for JSON or dict input.") + + # Create null terminated gdal options array. + papsz_options = [] + for key, val in ds_input.get("papsz_options", {}).items(): + option = "{}={}".format(key, val) + papsz_options.append(option.upper().encode()) + papsz_options.append(None) + + # Convert papszlist to ctypes array. + papsz_options = (c_char_p * len(papsz_options))(*papsz_options) + + # Create GDAL Raster + self._ptr = capi.create_ds( + driver._ptr, + force_bytes(ds_input.get("name", "")), + ds_input["width"], + ds_input["height"], + ds_input.get("nr_of_bands", len(ds_input.get("bands", []))), + ds_input.get("datatype", 6), + byref(papsz_options), + ) + + # Set band data if provided + for i, band_input in enumerate(ds_input.get("bands", [])): + band = self.bands[i] + if "nodata_value" in band_input: + band.nodata_value = band_input["nodata_value"] + # Instantiate band filled with nodata values if only + # partial input data has been provided. + if band.nodata_value is not None and ( + "data" not in band_input + or "size" in band_input + or "shape" in band_input + ): + band.data(data=(band.nodata_value,), shape=(1, 1)) + # Set band data values from input. + band.data( + data=band_input.get("data"), + size=band_input.get("size"), + shape=band_input.get("shape"), + offset=band_input.get("offset"), + ) + + # Set SRID + self.srs = ds_input.get("srid") + + # Set additional properties if provided + if "origin" in ds_input: + self.origin.x, self.origin.y = ds_input["origin"] + + if "scale" in ds_input: + self.scale.x, self.scale.y = ds_input["scale"] + + if "skew" in ds_input: + self.skew.x, self.skew.y = ds_input["skew"] + elif isinstance(ds_input, c_void_p): + # Instantiate the object using an existing pointer to a gdal raster. + self._ptr = ds_input + else: + raise GDALException( + 'Invalid data source input type: "{}".'.format(type(ds_input)) + ) + + def __del__(self): + if self.is_vsi_based: + # Remove the temporary file from the VSI in-memory filesystem. + capi.unlink_vsi_file(force_bytes(self.name)) + super().__del__() + + def __str__(self): + return self.name + + def __repr__(self): + """ + Short-hand representation because WKB may be very large. + """ + return "" % hex(addressof(self._ptr)) + + def _flush(self): + """ + Flush all data from memory into the source file if it exists. + The data that needs flushing are geotransforms, coordinate systems, + nodata_values and pixel values. This function will be called + automatically wherever it is needed. + """ + # Raise an Exception if the value is being changed in read mode. + if not self._write: + raise GDALException( + "Raster needs to be opened in write mode to change values." + ) + capi.flush_ds(self._ptr) + + @property + def vsi_buffer(self): + if not ( + self.is_vsi_based and self.name.startswith(VSI_MEM_FILESYSTEM_BASE_PATH) + ): + return None + # Prepare an integer that will contain the buffer length. + out_length = c_int() + # Get the data using the vsi file name. + dat = capi.get_mem_buffer_from_vsi_file( + force_bytes(self.name), + byref(out_length), + VSI_DELETE_BUFFER_ON_READ, + ) + # Read the full buffer pointer. + return string_at(dat, out_length.value) + + @cached_property + def is_vsi_based(self): + return self._ptr and self.name.startswith(VSI_FILESYSTEM_PREFIX) + + @property + def name(self): + """ + Return the name of this raster. Corresponds to filename + for file-based rasters. + """ + return force_str(capi.get_ds_description(self._ptr)) + + @cached_property + def driver(self): + """ + Return the GDAL Driver used for this raster. + """ + ds_driver = capi.get_ds_driver(self._ptr) + return Driver(ds_driver) + + @property + def width(self): + """ + Width (X axis) in pixels. + """ + return capi.get_ds_xsize(self._ptr) + + @property + def height(self): + """ + Height (Y axis) in pixels. + """ + return capi.get_ds_ysize(self._ptr) + + @property + def srs(self): + """ + Return the SpatialReference used in this GDALRaster. + """ + try: + wkt = capi.get_ds_projection_ref(self._ptr) + if not wkt: + return None + return SpatialReference(wkt, srs_type="wkt") + except SRSException: + return None + + @srs.setter + def srs(self, value): + """ + Set the spatial reference used in this GDALRaster. The input can be + a SpatialReference or any parameter accepted by the SpatialReference + constructor. + """ + if isinstance(value, SpatialReference): + srs = value + elif isinstance(value, (int, str)): + srs = SpatialReference(value) + else: + raise ValueError("Could not create a SpatialReference from input.") + capi.set_ds_projection_ref(self._ptr, srs.wkt.encode()) + self._flush() + + @property + def srid(self): + """ + Shortcut to access the srid of this GDALRaster. + """ + return self.srs.srid + + @srid.setter + def srid(self, value): + """ + Shortcut to set this GDALRaster's srs from an srid. + """ + self.srs = value + + @property + def geotransform(self): + """ + Return the geotransform of the data source. + Return the default geotransform if it does not exist or has not been + set previously. The default is [0.0, 1.0, 0.0, 0.0, 0.0, -1.0]. + """ + # Create empty ctypes double array for data + gtf = (c_double * 6)() + capi.get_ds_geotransform(self._ptr, byref(gtf)) + return list(gtf) + + @geotransform.setter + def geotransform(self, values): + "Set the geotransform for the data source." + if len(values) != 6 or not all(isinstance(x, (int, float)) for x in values): + raise ValueError("Geotransform must consist of 6 numeric values.") + # Create ctypes double array with input and write data + values = (c_double * 6)(*values) + capi.set_ds_geotransform(self._ptr, byref(values)) + self._flush() + + @property + def origin(self): + """ + Coordinates of the raster origin. + """ + return TransformPoint(self, "origin") + + @property + def scale(self): + """ + Pixel scale in units of the raster projection. + """ + return TransformPoint(self, "scale") + + @property + def skew(self): + """ + Skew of pixels (rotation parameters). + """ + return TransformPoint(self, "skew") + + @property + def extent(self): + """ + Return the extent as a 4-tuple (xmin, ymin, xmax, ymax). + """ + # Calculate boundary values based on scale and size + xval = self.origin.x + self.scale.x * self.width + yval = self.origin.y + self.scale.y * self.height + # Calculate min and max values + xmin = min(xval, self.origin.x) + xmax = max(xval, self.origin.x) + ymin = min(yval, self.origin.y) + ymax = max(yval, self.origin.y) + + return xmin, ymin, xmax, ymax + + @property + def bands(self): + return BandList(self) + + def warp(self, ds_input, resampling="NearestNeighbour", max_error=0.0): + """ + Return a warped GDALRaster with the given input characteristics. + + The input is expected to be a dictionary containing the parameters + of the target raster. Allowed values are width, height, SRID, origin, + scale, skew, datatype, driver, and name (filename). + + By default, the warp functions keeps all parameters equal to the values + of the original source raster. For the name of the target raster, the + name of the source raster will be used and appended with + _copy. + source_driver_name. + + In addition, the resampling algorithm can be specified with the "resampling" + input parameter. The default is NearestNeighbor. For a list of all options + consult the GDAL_RESAMPLE_ALGORITHMS constant. + """ + # Get the parameters defining the geotransform, srid, and size of the raster + ds_input.setdefault("width", self.width) + ds_input.setdefault("height", self.height) + ds_input.setdefault("srid", self.srs.srid) + ds_input.setdefault("origin", self.origin) + ds_input.setdefault("scale", self.scale) + ds_input.setdefault("skew", self.skew) + # Get the driver, name, and datatype of the target raster + ds_input.setdefault("driver", self.driver.name) + + if "name" not in ds_input: + ds_input["name"] = self.name + "_copy." + self.driver.name + + if "datatype" not in ds_input: + ds_input["datatype"] = self.bands[0].datatype() + + # Instantiate raster bands filled with nodata values. + ds_input["bands"] = [{"nodata_value": bnd.nodata_value} for bnd in self.bands] + + # Create target raster + target = GDALRaster(ds_input, write=True) + + # Select resampling algorithm + algorithm = GDAL_RESAMPLE_ALGORITHMS[resampling] + + # Reproject image + capi.reproject_image( + self._ptr, + self.srs.wkt.encode(), + target._ptr, + target.srs.wkt.encode(), + algorithm, + 0.0, + max_error, + c_void_p(), + c_void_p(), + c_void_p(), + ) + + # Make sure all data is written to file + target._flush() + + return target + + def clone(self, name=None): + """Return a clone of this GDALRaster.""" + if name: + clone_name = name + elif self.driver.name != "MEM": + clone_name = self.name + "_copy." + self.driver.name + else: + clone_name = os.path.join(VSI_MEM_FILESYSTEM_BASE_PATH, str(uuid.uuid4())) + return GDALRaster( + capi.copy_ds( + self.driver._ptr, + force_bytes(clone_name), + self._ptr, + c_int(), + c_char_p(), + c_void_p(), + c_void_p(), + ), + write=self._write, + ) + + def transform( + self, srs, driver=None, name=None, resampling="NearestNeighbour", max_error=0.0 + ): + """ + Return a copy of this raster reprojected into the given spatial + reference system. + """ + # Convert the resampling algorithm name into an algorithm id + algorithm = GDAL_RESAMPLE_ALGORITHMS[resampling] + + if isinstance(srs, SpatialReference): + target_srs = srs + elif isinstance(srs, (int, str)): + target_srs = SpatialReference(srs) + else: + raise TypeError( + "Transform only accepts SpatialReference, string, and integer " + "objects." + ) + + if target_srs.srid == self.srid and (not driver or driver == self.driver.name): + return self.clone(name) + # Create warped virtual dataset in the target reference system + target = capi.auto_create_warped_vrt( + self._ptr, + self.srs.wkt.encode(), + target_srs.wkt.encode(), + algorithm, + max_error, + c_void_p(), + ) + target = GDALRaster(target) + + # Construct the target warp dictionary from the virtual raster + data = { + "srid": target_srs.srid, + "width": target.width, + "height": target.height, + "origin": [target.origin.x, target.origin.y], + "scale": [target.scale.x, target.scale.y], + "skew": [target.skew.x, target.skew.y], + } + + # Set the driver and filepath if provided + if driver: + data["driver"] = driver + + if name: + data["name"] = name + + # Warp the raster into new srid + return self.warp(data, resampling=resampling, max_error=max_error) + + @property + def info(self): + """ + Return information about this raster in a string format equivalent + to the output of the gdalinfo command line utility. + """ + return capi.get_ds_info(self.ptr, None).decode() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/srs.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/srs.py new file mode 100644 index 0000000..cd0554e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/gdal/srs.py @@ -0,0 +1,365 @@ +""" + The Spatial Reference class, represents OGR Spatial Reference objects. + + Example: + >>> from django.contrib.gis.gdal import SpatialReference + >>> srs = SpatialReference('WGS84') + >>> print(srs) + GEOGCS["WGS 84", + DATUM["WGS_1984", + SPHEROID["WGS 84",6378137,298.257223563, + AUTHORITY["EPSG","7030"]], + TOWGS84[0,0,0,0,0,0,0], + AUTHORITY["EPSG","6326"]], + PRIMEM["Greenwich",0, + AUTHORITY["EPSG","8901"]], + UNIT["degree",0.01745329251994328, + AUTHORITY["EPSG","9122"]], + AUTHORITY["EPSG","4326"]] + >>> print(srs.proj) + +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs + >>> print(srs.ellipsoid) + (6378137.0, 6356752.3142451793, 298.25722356300003) + >>> print(srs.projected, srs.geographic) + False True + >>> srs.import_epsg(32140) + >>> print(srs.name) + NAD83 / Texas South Central +""" +from ctypes import byref, c_char_p, c_int +from enum import IntEnum +from types import NoneType + +from django.contrib.gis.gdal.base import GDALBase +from django.contrib.gis.gdal.error import SRSException +from django.contrib.gis.gdal.libgdal import GDAL_VERSION +from django.contrib.gis.gdal.prototypes import srs as capi +from django.utils.encoding import force_bytes, force_str + + +class AxisOrder(IntEnum): + TRADITIONAL = 0 + AUTHORITY = 1 + + +class SpatialReference(GDALBase): + """ + A wrapper for the OGRSpatialReference object. According to the GDAL web site, + the SpatialReference object "provide[s] services to represent coordinate + systems (projections and datums) and to transform between them." + """ + + destructor = capi.release_srs + + def __init__(self, srs_input="", srs_type="user", axis_order=None): + """ + Create a GDAL OSR Spatial Reference object from the given input. + The input may be string of OGC Well Known Text (WKT), an integer + EPSG code, a PROJ string, and/or a projection "well known" shorthand + string (one of 'WGS84', 'WGS72', 'NAD27', 'NAD83'). + """ + if not isinstance(axis_order, (NoneType, AxisOrder)): + raise ValueError( + "SpatialReference.axis_order must be an AxisOrder instance." + ) + self.axis_order = axis_order or AxisOrder.TRADITIONAL + if srs_type == "wkt": + self.ptr = capi.new_srs(c_char_p(b"")) + self.import_wkt(srs_input) + if self.axis_order == AxisOrder.TRADITIONAL and GDAL_VERSION >= (3, 0): + capi.set_axis_strategy(self.ptr, self.axis_order) + elif self.axis_order != AxisOrder.TRADITIONAL and GDAL_VERSION < (3, 0): + raise ValueError("%s is not supported in GDAL < 3.0." % self.axis_order) + return + elif isinstance(srs_input, str): + try: + # If SRID is a string, e.g., '4326', then make acceptable + # as user input. + srid = int(srs_input) + srs_input = "EPSG:%d" % srid + except ValueError: + pass + elif isinstance(srs_input, int): + # EPSG integer code was input. + srs_type = "epsg" + elif isinstance(srs_input, self.ptr_type): + srs = srs_input + srs_type = "ogr" + else: + raise TypeError('Invalid SRS type "%s"' % srs_type) + + if srs_type == "ogr": + # Input is already an SRS pointer. + srs = srs_input + else: + # Creating a new SRS pointer, using the string buffer. + buf = c_char_p(b"") + srs = capi.new_srs(buf) + + # If the pointer is NULL, throw an exception. + if not srs: + raise SRSException( + "Could not create spatial reference from: %s" % srs_input + ) + else: + self.ptr = srs + + if self.axis_order == AxisOrder.TRADITIONAL and GDAL_VERSION >= (3, 0): + capi.set_axis_strategy(self.ptr, self.axis_order) + elif self.axis_order != AxisOrder.TRADITIONAL and GDAL_VERSION < (3, 0): + raise ValueError("%s is not supported in GDAL < 3.0." % self.axis_order) + # Importing from either the user input string or an integer SRID. + if srs_type == "user": + self.import_user_input(srs_input) + elif srs_type == "epsg": + self.import_epsg(srs_input) + + def __getitem__(self, target): + """ + Return the value of the given string attribute node, None if the node + doesn't exist. Can also take a tuple as a parameter, (target, child), + where child is the index of the attribute in the WKT. For example: + + >>> wkt = 'GEOGCS["WGS 84", DATUM["WGS_1984, ... AUTHORITY["EPSG","4326"]]' + >>> srs = SpatialReference(wkt) # could also use 'WGS84', or 4326 + >>> print(srs['GEOGCS']) + WGS 84 + >>> print(srs['DATUM']) + WGS_1984 + >>> print(srs['AUTHORITY']) + EPSG + >>> print(srs['AUTHORITY', 1]) # The authority value + 4326 + >>> print(srs['TOWGS84', 4]) # the fourth value in this wkt + 0 + >>> # For the units authority, have to use the pipe symbole. + >>> print(srs['UNIT|AUTHORITY']) + EPSG + >>> print(srs['UNIT|AUTHORITY', 1]) # The authority value for the units + 9122 + """ + if isinstance(target, tuple): + return self.attr_value(*target) + else: + return self.attr_value(target) + + def __str__(self): + "Use 'pretty' WKT." + return self.pretty_wkt + + # #### SpatialReference Methods #### + def attr_value(self, target, index=0): + """ + The attribute value for the given target node (e.g. 'PROJCS'). The index + keyword specifies an index of the child node to return. + """ + if not isinstance(target, str) or not isinstance(index, int): + raise TypeError + return capi.get_attr_value(self.ptr, force_bytes(target), index) + + def auth_name(self, target): + "Return the authority name for the given string target node." + return capi.get_auth_name( + self.ptr, target if target is None else force_bytes(target) + ) + + def auth_code(self, target): + "Return the authority code for the given string target node." + return capi.get_auth_code( + self.ptr, target if target is None else force_bytes(target) + ) + + def clone(self): + "Return a clone of this SpatialReference object." + return SpatialReference(capi.clone_srs(self.ptr), axis_order=self.axis_order) + + def from_esri(self): + "Morph this SpatialReference from ESRI's format to EPSG." + capi.morph_from_esri(self.ptr) + + def identify_epsg(self): + """ + This method inspects the WKT of this SpatialReference, and will + add EPSG authority nodes where an EPSG identifier is applicable. + """ + capi.identify_epsg(self.ptr) + + def to_esri(self): + "Morph this SpatialReference to ESRI's format." + capi.morph_to_esri(self.ptr) + + def validate(self): + "Check to see if the given spatial reference is valid." + capi.srs_validate(self.ptr) + + # #### Name & SRID properties #### + @property + def name(self): + "Return the name of this Spatial Reference." + if self.projected: + return self.attr_value("PROJCS") + elif self.geographic: + return self.attr_value("GEOGCS") + elif self.local: + return self.attr_value("LOCAL_CS") + else: + return None + + @property + def srid(self): + "Return the SRID of top-level authority, or None if undefined." + try: + return int(self.auth_code(target=None)) + except (TypeError, ValueError): + return None + + # #### Unit Properties #### + @property + def linear_name(self): + "Return the name of the linear units." + units, name = capi.linear_units(self.ptr, byref(c_char_p())) + return name + + @property + def linear_units(self): + "Return the value of the linear units." + units, name = capi.linear_units(self.ptr, byref(c_char_p())) + return units + + @property + def angular_name(self): + "Return the name of the angular units." + units, name = capi.angular_units(self.ptr, byref(c_char_p())) + return name + + @property + def angular_units(self): + "Return the value of the angular units." + units, name = capi.angular_units(self.ptr, byref(c_char_p())) + return units + + @property + def units(self): + """ + Return a 2-tuple of the units value and the units name. Automatically + determine whether to return the linear or angular units. + """ + units, name = None, None + if self.projected or self.local: + units, name = capi.linear_units(self.ptr, byref(c_char_p())) + elif self.geographic: + units, name = capi.angular_units(self.ptr, byref(c_char_p())) + if name is not None: + name = force_str(name) + return (units, name) + + # #### Spheroid/Ellipsoid Properties #### + @property + def ellipsoid(self): + """ + Return a tuple of the ellipsoid parameters: + (semimajor axis, semiminor axis, and inverse flattening) + """ + return (self.semi_major, self.semi_minor, self.inverse_flattening) + + @property + def semi_major(self): + "Return the Semi Major Axis for this Spatial Reference." + return capi.semi_major(self.ptr, byref(c_int())) + + @property + def semi_minor(self): + "Return the Semi Minor Axis for this Spatial Reference." + return capi.semi_minor(self.ptr, byref(c_int())) + + @property + def inverse_flattening(self): + "Return the Inverse Flattening for this Spatial Reference." + return capi.invflattening(self.ptr, byref(c_int())) + + # #### Boolean Properties #### + @property + def geographic(self): + """ + Return True if this SpatialReference is geographic + (root node is GEOGCS). + """ + return bool(capi.isgeographic(self.ptr)) + + @property + def local(self): + "Return True if this SpatialReference is local (root node is LOCAL_CS)." + return bool(capi.islocal(self.ptr)) + + @property + def projected(self): + """ + Return True if this SpatialReference is a projected coordinate system + (root node is PROJCS). + """ + return bool(capi.isprojected(self.ptr)) + + # #### Import Routines ##### + def import_epsg(self, epsg): + "Import the Spatial Reference from the EPSG code (an integer)." + capi.from_epsg(self.ptr, epsg) + + def import_proj(self, proj): + """Import the Spatial Reference from a PROJ string.""" + capi.from_proj(self.ptr, proj) + + def import_user_input(self, user_input): + "Import the Spatial Reference from the given user input string." + capi.from_user_input(self.ptr, force_bytes(user_input)) + + def import_wkt(self, wkt): + "Import the Spatial Reference from OGC WKT (string)" + capi.from_wkt(self.ptr, byref(c_char_p(force_bytes(wkt)))) + + def import_xml(self, xml): + "Import the Spatial Reference from an XML string." + capi.from_xml(self.ptr, xml) + + # #### Export Properties #### + @property + def wkt(self): + "Return the WKT representation of this Spatial Reference." + return capi.to_wkt(self.ptr, byref(c_char_p())) + + @property + def pretty_wkt(self, simplify=0): + "Return the 'pretty' representation of the WKT." + return capi.to_pretty_wkt(self.ptr, byref(c_char_p()), simplify) + + @property + def proj(self): + """Return the PROJ representation for this Spatial Reference.""" + return capi.to_proj(self.ptr, byref(c_char_p())) + + @property + def proj4(self): + "Alias for proj()." + return self.proj + + @property + def xml(self, dialect=""): + "Return the XML representation of this Spatial Reference." + return capi.to_xml(self.ptr, byref(c_char_p()), force_bytes(dialect)) + + +class CoordTransform(GDALBase): + "The coordinate system transformation object." + destructor = capi.destroy_ct + + def __init__(self, source, target): + "Initialize on a source and target SpatialReference objects." + if not isinstance(source, SpatialReference) or not isinstance( + target, SpatialReference + ): + raise TypeError("source and target must be of type SpatialReference") + self.ptr = capi.new_ct(source._ptr, target._ptr) + self._srs1_name = source.name + self._srs2_name = target.name + + def __str__(self): + return 'Transform from "%s" to "%s"' % (self._srs1_name, self._srs2_name) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geoip2/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geoip2/__init__.py new file mode 100644 index 0000000..71b71f6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geoip2/__init__.py @@ -0,0 +1,24 @@ +""" +This module houses the GeoIP2 object, a wrapper for the MaxMind GeoIP2(R) +Python API (https://geoip2.readthedocs.io/). This is an alternative to the +Python GeoIP2 interface provided by MaxMind. + +GeoIP(R) is a registered trademark of MaxMind, Inc. + +For IP-based geolocation, this module requires the GeoLite2 Country and City +datasets, in binary format (CSV will not work!). The datasets may be +downloaded from MaxMind at https://dev.maxmind.com/geoip/geoip2/geolite2/. +Grab GeoLite2-Country.mmdb.gz and GeoLite2-City.mmdb.gz, and unzip them in the +directory corresponding to settings.GEOIP_PATH. +""" +__all__ = ["HAS_GEOIP2"] + +try: + import geoip2 # NOQA +except ImportError: + HAS_GEOIP2 = False +else: + from .base import GeoIP2, GeoIP2Exception + + HAS_GEOIP2 = True + __all__ += ["GeoIP2", "GeoIP2Exception"] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geoip2/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geoip2/base.py new file mode 100644 index 0000000..b360f12 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geoip2/base.py @@ -0,0 +1,240 @@ +import socket + +import geoip2.database + +from django.conf import settings +from django.core.exceptions import ValidationError +from django.core.validators import validate_ipv46_address +from django.utils._os import to_path + +from .resources import City, Country + +# Creating the settings dictionary with any settings, if needed. +GEOIP_SETTINGS = { + "GEOIP_PATH": getattr(settings, "GEOIP_PATH", None), + "GEOIP_CITY": getattr(settings, "GEOIP_CITY", "GeoLite2-City.mmdb"), + "GEOIP_COUNTRY": getattr(settings, "GEOIP_COUNTRY", "GeoLite2-Country.mmdb"), +} + + +class GeoIP2Exception(Exception): + pass + + +class GeoIP2: + # The flags for GeoIP memory caching. + # Try MODE_MMAP_EXT, MODE_MMAP, MODE_FILE in that order. + MODE_AUTO = 0 + # Use the C extension with memory map. + MODE_MMAP_EXT = 1 + # Read from memory map. Pure Python. + MODE_MMAP = 2 + # Read database as standard file. Pure Python. + MODE_FILE = 4 + # Load database into memory. Pure Python. + MODE_MEMORY = 8 + cache_options = frozenset( + (MODE_AUTO, MODE_MMAP_EXT, MODE_MMAP, MODE_FILE, MODE_MEMORY) + ) + + # Paths to the city & country binary databases. + _city_file = "" + _country_file = "" + + # Initially, pointers to GeoIP file references are NULL. + _city = None + _country = None + + def __init__(self, path=None, cache=0, country=None, city=None): + """ + Initialize the GeoIP object. No parameters are required to use default + settings. Keyword arguments may be passed in to customize the locations + of the GeoIP datasets. + + * path: Base directory to where GeoIP data is located or the full path + to where the city or country data files (*.mmdb) are located. + Assumes that both the city and country data sets are located in + this directory; overrides the GEOIP_PATH setting. + + * cache: The cache settings when opening up the GeoIP datasets. May be + an integer in (0, 1, 2, 4, 8) corresponding to the MODE_AUTO, + MODE_MMAP_EXT, MODE_MMAP, MODE_FILE, and MODE_MEMORY, + `GeoIPOptions` C API settings, respectively. Defaults to 0, + meaning MODE_AUTO. + + * country: The name of the GeoIP country data file. Defaults to + 'GeoLite2-Country.mmdb'; overrides the GEOIP_COUNTRY setting. + + * city: The name of the GeoIP city data file. Defaults to + 'GeoLite2-City.mmdb'; overrides the GEOIP_CITY setting. + """ + # Checking the given cache option. + if cache not in self.cache_options: + raise GeoIP2Exception("Invalid GeoIP caching option: %s" % cache) + + # Getting the GeoIP data path. + path = path or GEOIP_SETTINGS["GEOIP_PATH"] + if not path: + raise GeoIP2Exception( + "GeoIP path must be provided via parameter or the GEOIP_PATH setting." + ) + + path = to_path(path) + if path.is_dir(): + # Constructing the GeoIP database filenames using the settings + # dictionary. If the database files for the GeoLite country + # and/or city datasets exist, then try to open them. + country_db = path / (country or GEOIP_SETTINGS["GEOIP_COUNTRY"]) + if country_db.is_file(): + self._country = geoip2.database.Reader(str(country_db), mode=cache) + self._country_file = country_db + + city_db = path / (city or GEOIP_SETTINGS["GEOIP_CITY"]) + if city_db.is_file(): + self._city = geoip2.database.Reader(str(city_db), mode=cache) + self._city_file = city_db + if not self._reader: + raise GeoIP2Exception("Could not load a database from %s." % path) + elif path.is_file(): + # Otherwise, some detective work will be needed to figure out + # whether the given database path is for the GeoIP country or city + # databases. + reader = geoip2.database.Reader(str(path), mode=cache) + db_type = reader.metadata().database_type + + if "City" in db_type: + # GeoLite City database detected. + self._city = reader + self._city_file = path + elif "Country" in db_type: + # GeoIP Country database detected. + self._country = reader + self._country_file = path + else: + raise GeoIP2Exception( + "Unable to recognize database edition: %s" % db_type + ) + else: + raise GeoIP2Exception("GeoIP path must be a valid file or directory.") + + @property + def _reader(self): + return self._country or self._city + + @property + def _country_or_city(self): + if self._country: + return self._country.country + else: + return self._city.city + + def __del__(self): + # Cleanup any GeoIP file handles lying around. + if self._reader: + self._reader.close() + + def __repr__(self): + meta = self._reader.metadata() + version = "[v%s.%s]" % ( + meta.binary_format_major_version, + meta.binary_format_minor_version, + ) + return ( + '<%(cls)s %(version)s _country_file="%(country)s", _city_file="%(city)s">' + % { + "cls": self.__class__.__name__, + "version": version, + "country": self._country_file, + "city": self._city_file, + } + ) + + def _check_query(self, query, city=False, city_or_country=False): + "Check the query and database availability." + # Making sure a string was passed in for the query. + if not isinstance(query, str): + raise TypeError( + "GeoIP query must be a string, not type %s" % type(query).__name__ + ) + + # Extra checks for the existence of country and city databases. + if city_or_country and not (self._country or self._city): + raise GeoIP2Exception("Invalid GeoIP country and city data files.") + elif city and not self._city: + raise GeoIP2Exception("Invalid GeoIP city data file: %s" % self._city_file) + + # Return the query string back to the caller. GeoIP2 only takes IP addresses. + try: + validate_ipv46_address(query) + except ValidationError: + query = socket.gethostbyname(query) + + return query + + def city(self, query): + """ + Return a dictionary of city information for the given IP address or + Fully Qualified Domain Name (FQDN). Some information in the dictionary + may be undefined (None). + """ + enc_query = self._check_query(query, city=True) + return City(self._city.city(enc_query)) + + def country_code(self, query): + "Return the country code for the given IP Address or FQDN." + return self.country(query)["country_code"] + + def country_name(self, query): + "Return the country name for the given IP Address or FQDN." + return self.country(query)["country_name"] + + def country(self, query): + """ + Return a dictionary with the country code and name when given an + IP address or a Fully Qualified Domain Name (FQDN). For example, both + '24.124.1.80' and 'djangoproject.com' are valid parameters. + """ + # Returning the country code and name + enc_query = self._check_query(query, city_or_country=True) + return Country(self._country_or_city(enc_query)) + + # #### Coordinate retrieval routines #### + def coords(self, query, ordering=("longitude", "latitude")): + cdict = self.city(query) + if cdict is None: + return None + else: + return tuple(cdict[o] for o in ordering) + + def lon_lat(self, query): + "Return a tuple of the (longitude, latitude) for the given query." + return self.coords(query) + + def lat_lon(self, query): + "Return a tuple of the (latitude, longitude) for the given query." + return self.coords(query, ("latitude", "longitude")) + + def geos(self, query): + "Return a GEOS Point object for the given query." + ll = self.lon_lat(query) + if ll: + # Allows importing and using GeoIP2() when GEOS is not installed. + from django.contrib.gis.geos import Point + + return Point(ll, srid=4326) + else: + return None + + # #### GeoIP Database Information Routines #### + @property + def info(self): + "Return information about the GeoIP library and databases in use." + meta = self._reader.metadata() + return "GeoIP Library:\n\t%s.%s\n" % ( + meta.binary_format_major_version, + meta.binary_format_minor_version, + ) + + @classmethod + def open(cls, full_path, cache): + return GeoIP2(full_path, cache) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geoip2/resources.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geoip2/resources.py new file mode 100644 index 0000000..74f4228 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geoip2/resources.py @@ -0,0 +1,22 @@ +def City(response): + return { + "city": response.city.name, + "continent_code": response.continent.code, + "continent_name": response.continent.name, + "country_code": response.country.iso_code, + "country_name": response.country.name, + "dma_code": response.location.metro_code, + "is_in_european_union": response.country.is_in_european_union, + "latitude": response.location.latitude, + "longitude": response.location.longitude, + "postal_code": response.postal.code, + "region": response.subdivisions[0].iso_code if response.subdivisions else None, + "time_zone": response.location.time_zone, + } + + +def Country(response): + return { + "country_code": response.country.iso_code, + "country_name": response.country.name, + } diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geometry.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geometry.py new file mode 100644 index 0000000..b5caf04 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geometry.py @@ -0,0 +1,17 @@ +import re + +from django.utils.regex_helper import _lazy_re_compile + +# Regular expression for recognizing HEXEWKB and WKT. A prophylactic measure +# to prevent potentially malicious input from reaching the underlying C +# library. Not a substitute for good web security programming practices. +hex_regex = _lazy_re_compile(r"^[0-9A-F]+$", re.I) +wkt_regex = _lazy_re_compile( + r"^(SRID=(?P\-?[0-9]+);)?" + r"(?P" + r"(?PPOINT|LINESTRING|LINEARRING|POLYGON|MULTIPOINT|" + r"MULTILINESTRING|MULTIPOLYGON|GEOMETRYCOLLECTION)" + r"[ACEGIMLONPSRUTYZ0-9,.+() -]+)$", + re.I, +) +json_regex = _lazy_re_compile(r"^(\s+)?\{.*}(\s+)?$", re.DOTALL) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/LICENSE b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/LICENSE new file mode 100644 index 0000000..0479b07 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2007-2009 Justin Bronn +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of GEOSGeometry nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/__init__.py new file mode 100644 index 0000000..27de1ca --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/__init__.py @@ -0,0 +1,18 @@ +""" +The GeoDjango GEOS module. Please consult the GeoDjango documentation +for more details: https://docs.djangoproject.com/en/dev/ref/contrib/gis/geos/ +""" +from .collections import ( # NOQA + GeometryCollection, + MultiLineString, + MultiPoint, + MultiPolygon, +) +from .error import GEOSException # NOQA +from .factory import fromfile, fromstr # NOQA +from .geometry import GEOSGeometry, hex_regex, wkt_regex # NOQA +from .io import WKBReader, WKBWriter, WKTReader, WKTWriter # NOQA +from .libgeos import geos_version # NOQA +from .linestring import LinearRing, LineString # NOQA +from .point import Point # NOQA +from .polygon import Polygon # NOQA diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/base.py new file mode 100644 index 0000000..b7466ba --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/base.py @@ -0,0 +1,6 @@ +from django.contrib.gis.geos.error import GEOSException +from django.contrib.gis.ptr import CPointerBase + + +class GEOSBase(CPointerBase): + null_ptr_exception_class = GEOSException diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/collections.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/collections.py new file mode 100644 index 0000000..abfec8a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/collections.py @@ -0,0 +1,120 @@ +""" + This module houses the Geometry Collection objects: + GeometryCollection, MultiPoint, MultiLineString, and MultiPolygon +""" +from django.contrib.gis.geos import prototypes as capi +from django.contrib.gis.geos.geometry import GEOSGeometry, LinearGeometryMixin +from django.contrib.gis.geos.libgeos import GEOM_PTR +from django.contrib.gis.geos.linestring import LinearRing, LineString +from django.contrib.gis.geos.point import Point +from django.contrib.gis.geos.polygon import Polygon + + +class GeometryCollection(GEOSGeometry): + _typeid = 7 + + def __init__(self, *args, **kwargs): + "Initialize a Geometry Collection from a sequence of Geometry objects." + # Checking the arguments + if len(args) == 1: + # If only one geometry provided or a list of geometries is provided + # in the first argument. + if isinstance(args[0], (tuple, list)): + init_geoms = args[0] + else: + init_geoms = args + else: + init_geoms = args + + # Ensuring that only the permitted geometries are allowed in this collection + # this is moved to list mixin super class + self._check_allowed(init_geoms) + + # Creating the geometry pointer array. + collection = self._create_collection(len(init_geoms), init_geoms) + super().__init__(collection, **kwargs) + + def __iter__(self): + "Iterate over each Geometry in the Collection." + for i in range(len(self)): + yield self[i] + + def __len__(self): + "Return the number of geometries in this Collection." + return self.num_geom + + # ### Methods for compatibility with ListMixin ### + def _create_collection(self, length, items): + # Creating the geometry pointer array. + geoms = (GEOM_PTR * length)( + *[ + # this is a little sloppy, but makes life easier + # allow GEOSGeometry types (python wrappers) or pointer types + capi.geom_clone(getattr(g, "ptr", g)) + for g in items + ] + ) + return capi.create_collection(self._typeid, geoms, length) + + def _get_single_internal(self, index): + return capi.get_geomn(self.ptr, index) + + def _get_single_external(self, index): + "Return the Geometry from this Collection at the given index (0-based)." + # Checking the index and returning the corresponding GEOS geometry. + return GEOSGeometry( + capi.geom_clone(self._get_single_internal(index)), srid=self.srid + ) + + def _set_list(self, length, items): + "Create a new collection, and destroy the contents of the previous pointer." + prev_ptr = self.ptr + srid = self.srid + self.ptr = self._create_collection(length, items) + if srid: + self.srid = srid + capi.destroy_geom(prev_ptr) + + _set_single = GEOSGeometry._set_single_rebuild + _assign_extended_slice = GEOSGeometry._assign_extended_slice_rebuild + + @property + def kml(self): + "Return the KML for this Geometry Collection." + return "%s" % "".join(g.kml for g in self) + + @property + def tuple(self): + "Return a tuple of all the coordinates in this Geometry Collection" + return tuple(g.tuple for g in self) + + coords = tuple + + +# MultiPoint, MultiLineString, and MultiPolygon class definitions. +class MultiPoint(GeometryCollection): + _allowed = Point + _typeid = 4 + + +class MultiLineString(LinearGeometryMixin, GeometryCollection): + _allowed = (LineString, LinearRing) + _typeid = 5 + + +class MultiPolygon(GeometryCollection): + _allowed = Polygon + _typeid = 6 + + +# Setting the allowed types here since GeometryCollection is defined before +# its subclasses. +GeometryCollection._allowed = ( + Point, + LineString, + LinearRing, + Polygon, + MultiPoint, + MultiLineString, + MultiPolygon, +) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/coordseq.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/coordseq.py new file mode 100644 index 0000000..0ff4ecb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/coordseq.py @@ -0,0 +1,210 @@ +""" + This module houses the GEOSCoordSeq object, which is used internally + by GEOSGeometry to house the actual coordinates of the Point, + LineString, and LinearRing geometries. +""" +from ctypes import byref, c_byte, c_double, c_uint + +from django.contrib.gis.geos import prototypes as capi +from django.contrib.gis.geos.base import GEOSBase +from django.contrib.gis.geos.error import GEOSException +from django.contrib.gis.geos.libgeos import CS_PTR +from django.contrib.gis.shortcuts import numpy + + +class GEOSCoordSeq(GEOSBase): + "The internal representation of a list of coordinates inside a Geometry." + + ptr_type = CS_PTR + + def __init__(self, ptr, z=False): + "Initialize from a GEOS pointer." + if not isinstance(ptr, CS_PTR): + raise TypeError("Coordinate sequence should initialize with a CS_PTR.") + self._ptr = ptr + self._z = z + + def __iter__(self): + "Iterate over each point in the coordinate sequence." + for i in range(self.size): + yield self[i] + + def __len__(self): + "Return the number of points in the coordinate sequence." + return self.size + + def __str__(self): + "Return the string representation of the coordinate sequence." + return str(self.tuple) + + def __getitem__(self, index): + "Return the coordinate sequence value at the given index." + self._checkindex(index) + return self._point_getter(index) + + def __setitem__(self, index, value): + "Set the coordinate sequence value at the given index." + # Checking the input value + if isinstance(value, (list, tuple)): + pass + elif numpy and isinstance(value, numpy.ndarray): + pass + else: + raise TypeError( + "Must set coordinate with a sequence (list, tuple, or numpy array)." + ) + # Checking the dims of the input + if self.dims == 3 and self._z: + n_args = 3 + point_setter = self._set_point_3d + else: + n_args = 2 + point_setter = self._set_point_2d + if len(value) != n_args: + raise TypeError("Dimension of value does not match.") + self._checkindex(index) + point_setter(index, value) + + # #### Internal Routines #### + def _checkindex(self, index): + "Check the given index." + if not (0 <= index < self.size): + raise IndexError("invalid GEOS Geometry index: %s" % index) + + def _checkdim(self, dim): + "Check the given dimension." + if dim < 0 or dim > 2: + raise GEOSException('invalid ordinate dimension "%d"' % dim) + + def _get_x(self, index): + return capi.cs_getx(self.ptr, index, byref(c_double())) + + def _get_y(self, index): + return capi.cs_gety(self.ptr, index, byref(c_double())) + + def _get_z(self, index): + return capi.cs_getz(self.ptr, index, byref(c_double())) + + def _set_x(self, index, value): + capi.cs_setx(self.ptr, index, value) + + def _set_y(self, index, value): + capi.cs_sety(self.ptr, index, value) + + def _set_z(self, index, value): + capi.cs_setz(self.ptr, index, value) + + @property + def _point_getter(self): + return self._get_point_3d if self.dims == 3 and self._z else self._get_point_2d + + def _get_point_2d(self, index): + return (self._get_x(index), self._get_y(index)) + + def _get_point_3d(self, index): + return (self._get_x(index), self._get_y(index), self._get_z(index)) + + def _set_point_2d(self, index, value): + x, y = value + self._set_x(index, x) + self._set_y(index, y) + + def _set_point_3d(self, index, value): + x, y, z = value + self._set_x(index, x) + self._set_y(index, y) + self._set_z(index, z) + + # #### Ordinate getting and setting routines #### + def getOrdinate(self, dimension, index): + "Return the value for the given dimension and index." + self._checkindex(index) + self._checkdim(dimension) + return capi.cs_getordinate(self.ptr, index, dimension, byref(c_double())) + + def setOrdinate(self, dimension, index, value): + "Set the value for the given dimension and index." + self._checkindex(index) + self._checkdim(dimension) + capi.cs_setordinate(self.ptr, index, dimension, value) + + def getX(self, index): + "Get the X value at the index." + return self.getOrdinate(0, index) + + def setX(self, index, value): + "Set X with the value at the given index." + self.setOrdinate(0, index, value) + + def getY(self, index): + "Get the Y value at the given index." + return self.getOrdinate(1, index) + + def setY(self, index, value): + "Set Y with the value at the given index." + self.setOrdinate(1, index, value) + + def getZ(self, index): + "Get Z with the value at the given index." + return self.getOrdinate(2, index) + + def setZ(self, index, value): + "Set Z with the value at the given index." + self.setOrdinate(2, index, value) + + # ### Dimensions ### + @property + def size(self): + "Return the size of this coordinate sequence." + return capi.cs_getsize(self.ptr, byref(c_uint())) + + @property + def dims(self): + "Return the dimensions of this coordinate sequence." + return capi.cs_getdims(self.ptr, byref(c_uint())) + + @property + def hasz(self): + """ + Return whether this coordinate sequence is 3D. This property value is + inherited from the parent Geometry. + """ + return self._z + + # ### Other Methods ### + def clone(self): + "Clone this coordinate sequence." + return GEOSCoordSeq(capi.cs_clone(self.ptr), self.hasz) + + @property + def kml(self): + "Return the KML representation for the coordinates." + # Getting the substitution string depending on whether the coordinates have + # a Z dimension. + if self.hasz: + substr = "%s,%s,%s " + else: + substr = "%s,%s,0 " + return ( + "%s" + % "".join(substr % self[i] for i in range(len(self))).strip() + ) + + @property + def tuple(self): + "Return a tuple version of this coordinate sequence." + n = self.size + get_point = self._point_getter + if n == 1: + return get_point(0) + return tuple(get_point(i) for i in range(n)) + + @property + def is_counterclockwise(self): + """Return whether this coordinate sequence is counterclockwise.""" + ret = c_byte() + if not capi.cs_is_ccw(self.ptr, byref(ret)): + raise GEOSException( + 'Error encountered in GEOS C function "%s".' % capi.cs_is_ccw.func_name + ) + return ret.value == 1 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/error.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/error.py new file mode 100644 index 0000000..af2ac2f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/error.py @@ -0,0 +1,3 @@ +class GEOSException(Exception): + "The base GEOS exception, indicates a GEOS-related error." + pass diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/factory.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/factory.py new file mode 100644 index 0000000..2c1c247 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/factory.py @@ -0,0 +1,33 @@ +from django.contrib.gis.geos.geometry import GEOSGeometry, hex_regex, wkt_regex + + +def fromfile(file_h): + """ + Given a string file name, returns a GEOSGeometry. The file may contain WKB, + WKT, or HEX. + """ + # If given a file name, get a real handle. + if isinstance(file_h, str): + with open(file_h, "rb") as file_h: + buf = file_h.read() + else: + buf = file_h.read() + + # If we get WKB need to wrap in memoryview(), so run through regexes. + if isinstance(buf, bytes): + try: + decoded = buf.decode() + except UnicodeDecodeError: + pass + else: + if wkt_regex.match(decoded) or hex_regex.match(decoded): + return GEOSGeometry(decoded) + else: + return GEOSGeometry(buf) + + return GEOSGeometry(memoryview(buf)) + + +def fromstr(string, **kwargs): + "Given a string value, return a GEOSGeometry object." + return GEOSGeometry(string, **kwargs) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/geometry.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/geometry.py new file mode 100644 index 0000000..00b36af --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/geometry.py @@ -0,0 +1,779 @@ +""" + This module contains the 'base' GEOSGeometry object -- all GEOS Geometries + inherit from this object. +""" +import re +from ctypes import addressof, byref, c_double + +from django.contrib.gis import gdal +from django.contrib.gis.geometry import hex_regex, json_regex, wkt_regex +from django.contrib.gis.geos import prototypes as capi +from django.contrib.gis.geos.base import GEOSBase +from django.contrib.gis.geos.coordseq import GEOSCoordSeq +from django.contrib.gis.geos.error import GEOSException +from django.contrib.gis.geos.libgeos import GEOM_PTR, geos_version_tuple +from django.contrib.gis.geos.mutable_list import ListMixin +from django.contrib.gis.geos.prepared import PreparedGeometry +from django.contrib.gis.geos.prototypes.io import ewkb_w, wkb_r, wkb_w, wkt_r, wkt_w +from django.utils.deconstruct import deconstructible +from django.utils.encoding import force_bytes, force_str + + +class GEOSGeometryBase(GEOSBase): + _GEOS_CLASSES = None + + ptr_type = GEOM_PTR + destructor = capi.destroy_geom + has_cs = False # Only Point, LineString, LinearRing have coordinate sequences + + def __init__(self, ptr, cls): + self._ptr = ptr + + # Setting the class type (e.g., Point, Polygon, etc.) + if type(self) in (GEOSGeometryBase, GEOSGeometry): + if cls is None: + if GEOSGeometryBase._GEOS_CLASSES is None: + # Inner imports avoid import conflicts with GEOSGeometry. + from .collections import ( + GeometryCollection, + MultiLineString, + MultiPoint, + MultiPolygon, + ) + from .linestring import LinearRing, LineString + from .point import Point + from .polygon import Polygon + + GEOSGeometryBase._GEOS_CLASSES = { + 0: Point, + 1: LineString, + 2: LinearRing, + 3: Polygon, + 4: MultiPoint, + 5: MultiLineString, + 6: MultiPolygon, + 7: GeometryCollection, + } + cls = GEOSGeometryBase._GEOS_CLASSES[self.geom_typeid] + self.__class__ = cls + self._post_init() + + def _post_init(self): + "Perform post-initialization setup." + # Setting the coordinate sequence for the geometry (will be None on + # geometries that do not have coordinate sequences) + self._cs = ( + GEOSCoordSeq(capi.get_cs(self.ptr), self.hasz) if self.has_cs else None + ) + + def __copy__(self): + """ + Return a clone because the copy of a GEOSGeometry may contain an + invalid pointer location if the original is garbage collected. + """ + return self.clone() + + def __deepcopy__(self, memodict): + """ + The `deepcopy` routine is used by the `Node` class of django.utils.tree; + thus, the protocol routine needs to be implemented to return correct + copies (clones) of these GEOS objects, which use C pointers. + """ + return self.clone() + + def __str__(self): + "EWKT is used for the string representation." + return self.ewkt + + def __repr__(self): + "Short-hand representation because WKT may be very large." + return "<%s object at %s>" % (self.geom_type, hex(addressof(self.ptr))) + + # Pickling support + def _to_pickle_wkb(self): + return bytes(self.wkb) + + def _from_pickle_wkb(self, wkb): + return wkb_r().read(memoryview(wkb)) + + def __getstate__(self): + # The pickled state is simply a tuple of the WKB (in string form) + # and the SRID. + return self._to_pickle_wkb(), self.srid + + def __setstate__(self, state): + # Instantiating from the tuple state that was pickled. + wkb, srid = state + ptr = self._from_pickle_wkb(wkb) + if not ptr: + raise GEOSException("Invalid Geometry loaded from pickled state.") + self.ptr = ptr + self._post_init() + self.srid = srid + + @classmethod + def _from_wkb(cls, wkb): + return wkb_r().read(wkb) + + @staticmethod + def from_ewkt(ewkt): + ewkt = force_bytes(ewkt) + srid = None + parts = ewkt.split(b";", 1) + if len(parts) == 2: + srid_part, wkt = parts + match = re.match(rb"SRID=(?P\-?\d+)", srid_part) + if not match: + raise ValueError("EWKT has invalid SRID part.") + srid = int(match["srid"]) + else: + wkt = ewkt + if not wkt: + raise ValueError("Expected WKT but got an empty string.") + return GEOSGeometry(GEOSGeometry._from_wkt(wkt), srid=srid) + + @staticmethod + def _from_wkt(wkt): + return wkt_r().read(wkt) + + @classmethod + def from_gml(cls, gml_string): + return gdal.OGRGeometry.from_gml(gml_string).geos + + # Comparison operators + def __eq__(self, other): + """ + Equivalence testing, a Geometry may be compared with another Geometry + or an EWKT representation. + """ + if isinstance(other, str): + try: + other = GEOSGeometry.from_ewkt(other) + except (ValueError, GEOSException): + return False + return ( + isinstance(other, GEOSGeometry) + and self.srid == other.srid + and self.equals_exact(other) + ) + + def __hash__(self): + return hash((self.srid, self.wkt)) + + # ### Geometry set-like operations ### + # Thanks to Sean Gillies for inspiration: + # http://lists.gispython.org/pipermail/community/2007-July/001034.html + # g = g1 | g2 + def __or__(self, other): + "Return the union of this Geometry and the other." + return self.union(other) + + # g = g1 & g2 + def __and__(self, other): + "Return the intersection of this Geometry and the other." + return self.intersection(other) + + # g = g1 - g2 + def __sub__(self, other): + "Return the difference this Geometry and the other." + return self.difference(other) + + # g = g1 ^ g2 + def __xor__(self, other): + "Return the symmetric difference of this Geometry and the other." + return self.sym_difference(other) + + # #### Coordinate Sequence Routines #### + @property + def coord_seq(self): + "Return a clone of the coordinate sequence for this Geometry." + if self.has_cs: + return self._cs.clone() + + # #### Geometry Info #### + @property + def geom_type(self): + "Return a string representing the Geometry type, e.g. 'Polygon'" + return capi.geos_type(self.ptr).decode() + + @property + def geom_typeid(self): + "Return an integer representing the Geometry type." + return capi.geos_typeid(self.ptr) + + @property + def num_geom(self): + "Return the number of geometries in the Geometry." + return capi.get_num_geoms(self.ptr) + + @property + def num_coords(self): + "Return the number of coordinates in the Geometry." + return capi.get_num_coords(self.ptr) + + @property + def num_points(self): + "Return the number points, or coordinates, in the Geometry." + return self.num_coords + + @property + def dims(self): + "Return the dimension of this Geometry (0=point, 1=line, 2=surface)." + return capi.get_dims(self.ptr) + + def normalize(self, clone=False): + """ + Convert this Geometry to normal form (or canonical form). + If the `clone` keyword is set, then the geometry is not modified and a + normalized clone of the geometry is returned instead. + """ + if clone: + clone = self.clone() + capi.geos_normalize(clone.ptr) + return clone + capi.geos_normalize(self.ptr) + + def make_valid(self): + """ + Attempt to create a valid representation of a given invalid geometry + without losing any of the input vertices. + """ + return GEOSGeometry(capi.geos_makevalid(self.ptr), srid=self.srid) + + # #### Unary predicates #### + @property + def empty(self): + """ + Return a boolean indicating whether the set of points in this Geometry + are empty. + """ + return capi.geos_isempty(self.ptr) + + @property + def hasz(self): + "Return whether the geometry has a 3D dimension." + return capi.geos_hasz(self.ptr) + + @property + def ring(self): + "Return whether or not the geometry is a ring." + return capi.geos_isring(self.ptr) + + @property + def simple(self): + "Return false if the Geometry isn't simple." + return capi.geos_issimple(self.ptr) + + @property + def valid(self): + "Test the validity of this Geometry." + return capi.geos_isvalid(self.ptr) + + @property + def valid_reason(self): + """ + Return a string containing the reason for any invalidity. + """ + return capi.geos_isvalidreason(self.ptr).decode() + + # #### Binary predicates. #### + def contains(self, other): + "Return true if other.within(this) returns true." + return capi.geos_contains(self.ptr, other.ptr) + + def covers(self, other): + """ + Return True if the DE-9IM Intersection Matrix for the two geometries is + T*****FF*, *T****FF*, ***T**FF*, or ****T*FF*. If either geometry is + empty, return False. + """ + return capi.geos_covers(self.ptr, other.ptr) + + def crosses(self, other): + """ + Return true if the DE-9IM intersection matrix for the two Geometries + is T*T****** (for a point and a curve,a point and an area or a line and + an area) 0******** (for two curves). + """ + return capi.geos_crosses(self.ptr, other.ptr) + + def disjoint(self, other): + """ + Return true if the DE-9IM intersection matrix for the two Geometries + is FF*FF****. + """ + return capi.geos_disjoint(self.ptr, other.ptr) + + def equals(self, other): + """ + Return true if the DE-9IM intersection matrix for the two Geometries + is T*F**FFF*. + """ + return capi.geos_equals(self.ptr, other.ptr) + + def equals_exact(self, other, tolerance=0): + """ + Return true if the two Geometries are exactly equal, up to a + specified tolerance. + """ + return capi.geos_equalsexact(self.ptr, other.ptr, float(tolerance)) + + def equals_identical(self, other): + """ + Return true if the two Geometries are point-wise equivalent. + """ + if geos_version_tuple() < (3, 12): + raise GEOSException( + "GEOSGeometry.equals_identical() requires GEOS >= 3.12.0." + ) + return capi.geos_equalsidentical(self.ptr, other.ptr) + + def intersects(self, other): + "Return true if disjoint return false." + return capi.geos_intersects(self.ptr, other.ptr) + + def overlaps(self, other): + """ + Return true if the DE-9IM intersection matrix for the two Geometries + is T*T***T** (for two points or two surfaces) 1*T***T** (for two curves). + """ + return capi.geos_overlaps(self.ptr, other.ptr) + + def relate_pattern(self, other, pattern): + """ + Return true if the elements in the DE-9IM intersection matrix for the + two Geometries match the elements in pattern. + """ + if not isinstance(pattern, str) or len(pattern) > 9: + raise GEOSException("invalid intersection matrix pattern") + return capi.geos_relatepattern(self.ptr, other.ptr, force_bytes(pattern)) + + def touches(self, other): + """ + Return true if the DE-9IM intersection matrix for the two Geometries + is FT*******, F**T***** or F***T****. + """ + return capi.geos_touches(self.ptr, other.ptr) + + def within(self, other): + """ + Return true if the DE-9IM intersection matrix for the two Geometries + is T*F**F***. + """ + return capi.geos_within(self.ptr, other.ptr) + + # #### SRID Routines #### + @property + def srid(self): + "Get the SRID for the geometry. Return None if no SRID is set." + s = capi.geos_get_srid(self.ptr) + if s == 0: + return None + else: + return s + + @srid.setter + def srid(self, srid): + "Set the SRID for the geometry." + capi.geos_set_srid(self.ptr, 0 if srid is None else srid) + + # #### Output Routines #### + @property + def ewkt(self): + """ + Return the EWKT (SRID + WKT) of the Geometry. + """ + srid = self.srid + return "SRID=%s;%s" % (srid, self.wkt) if srid else self.wkt + + @property + def wkt(self): + "Return the WKT (Well-Known Text) representation of this Geometry." + return wkt_w(dim=3 if self.hasz else 2, trim=True).write(self).decode() + + @property + def hex(self): + """ + Return the WKB of this Geometry in hexadecimal form. Please note + that the SRID is not included in this representation because it is not + a part of the OGC specification (use the `hexewkb` property instead). + """ + # A possible faster, all-python, implementation: + # str(self.wkb).encode('hex') + return wkb_w(dim=3 if self.hasz else 2).write_hex(self) + + @property + def hexewkb(self): + """ + Return the EWKB of this Geometry in hexadecimal form. This is an + extension of the WKB specification that includes SRID value that are + a part of this geometry. + """ + return ewkb_w(dim=3 if self.hasz else 2).write_hex(self) + + @property + def json(self): + """ + Return GeoJSON representation of this Geometry. + """ + return self.ogr.json + + geojson = json + + @property + def wkb(self): + """ + Return the WKB (Well-Known Binary) representation of this Geometry + as a Python memoryview. SRID and Z values are not included, use the + `ewkb` property instead. + """ + return wkb_w(3 if self.hasz else 2).write(self) + + @property + def ewkb(self): + """ + Return the EWKB representation of this Geometry as a Python memoryview. + This is an extension of the WKB specification that includes any SRID + value that are a part of this geometry. + """ + return ewkb_w(3 if self.hasz else 2).write(self) + + @property + def kml(self): + "Return the KML representation of this Geometry." + gtype = self.geom_type + return "<%s>%s" % (gtype, self.coord_seq.kml, gtype) + + @property + def prepared(self): + """ + Return a PreparedGeometry corresponding to this geometry -- it is + optimized for the contains, intersects, and covers operations. + """ + return PreparedGeometry(self) + + # #### GDAL-specific output routines #### + def _ogr_ptr(self): + return gdal.OGRGeometry._from_wkb(self.wkb) + + @property + def ogr(self): + "Return the OGR Geometry for this Geometry." + return gdal.OGRGeometry(self._ogr_ptr(), self.srs) + + @property + def srs(self): + "Return the OSR SpatialReference for SRID of this Geometry." + if self.srid: + try: + return gdal.SpatialReference(self.srid) + except (gdal.GDALException, gdal.SRSException): + pass + return None + + @property + def crs(self): + "Alias for `srs` property." + return self.srs + + def transform(self, ct, clone=False): + """ + Requires GDAL. Transform the geometry according to the given + transformation object, which may be an integer SRID, and WKT or + PROJ string. By default, transform the geometry in-place and return + nothing. However if the `clone` keyword is set, don't modify the + geometry and return a transformed clone instead. + """ + srid = self.srid + + if ct == srid: + # short-circuit where source & dest SRIDs match + if clone: + return self.clone() + else: + return + + if isinstance(ct, gdal.CoordTransform): + # We don't care about SRID because CoordTransform presupposes + # source SRS. + srid = None + elif srid is None or srid < 0: + raise GEOSException("Calling transform() with no SRID set is not supported") + + # Creating an OGR Geometry, which is then transformed. + g = gdal.OGRGeometry(self._ogr_ptr(), srid) + g.transform(ct) + # Getting a new GEOS pointer + ptr = g._geos_ptr() + if clone: + # User wants a cloned transformed geometry returned. + return GEOSGeometry(ptr, srid=g.srid) + if ptr: + # Reassigning pointer, and performing post-initialization setup + # again due to the reassignment. + capi.destroy_geom(self.ptr) + self.ptr = ptr + self._post_init() + self.srid = g.srid + else: + raise GEOSException("Transformed WKB was invalid.") + + # #### Topology Routines #### + def _topology(self, gptr): + "Return Geometry from the given pointer." + return GEOSGeometry(gptr, srid=self.srid) + + @property + def boundary(self): + "Return the boundary as a newly allocated Geometry object." + return self._topology(capi.geos_boundary(self.ptr)) + + def buffer(self, width, quadsegs=8): + """ + Return a geometry that represents all points whose distance from this + Geometry is less than or equal to distance. Calculations are in the + Spatial Reference System of this Geometry. The optional third parameter sets + the number of segment used to approximate a quarter circle (defaults to 8). + (Text from PostGIS documentation at ch. 6.1.3) + """ + return self._topology(capi.geos_buffer(self.ptr, width, quadsegs)) + + def buffer_with_style( + self, width, quadsegs=8, end_cap_style=1, join_style=1, mitre_limit=5.0 + ): + """ + Same as buffer() but allows customizing the style of the memoryview. + + End cap style can be round (1), flat (2), or square (3). + Join style can be round (1), mitre (2), or bevel (3). + Mitre ratio limit only affects mitered join style. + """ + return self._topology( + capi.geos_bufferwithstyle( + self.ptr, width, quadsegs, end_cap_style, join_style, mitre_limit + ), + ) + + @property + def centroid(self): + """ + The centroid is equal to the centroid of the set of component Geometries + of highest dimension (since the lower-dimension geometries contribute zero + "weight" to the centroid). + """ + return self._topology(capi.geos_centroid(self.ptr)) + + @property + def convex_hull(self): + """ + Return the smallest convex Polygon that contains all the points + in the Geometry. + """ + return self._topology(capi.geos_convexhull(self.ptr)) + + def difference(self, other): + """ + Return a Geometry representing the points making up this Geometry + that do not make up other. + """ + return self._topology(capi.geos_difference(self.ptr, other.ptr)) + + @property + def envelope(self): + "Return the envelope for this geometry (a polygon)." + return self._topology(capi.geos_envelope(self.ptr)) + + def intersection(self, other): + "Return a Geometry representing the points shared by this Geometry and other." + return self._topology(capi.geos_intersection(self.ptr, other.ptr)) + + @property + def point_on_surface(self): + "Compute an interior point of this Geometry." + return self._topology(capi.geos_pointonsurface(self.ptr)) + + def relate(self, other): + "Return the DE-9IM intersection matrix for this Geometry and the other." + return capi.geos_relate(self.ptr, other.ptr).decode() + + def simplify(self, tolerance=0.0, preserve_topology=False): + """ + Return the Geometry, simplified using the Douglas-Peucker algorithm + to the specified tolerance (higher tolerance => less points). If no + tolerance provided, defaults to 0. + + By default, don't preserve topology - e.g. polygons can be split, + collapse to lines or disappear holes can be created or disappear, and + lines can cross. By specifying preserve_topology=True, the result will + have the same dimension and number of components as the input. This is + significantly slower. + """ + if preserve_topology: + return self._topology(capi.geos_preservesimplify(self.ptr, tolerance)) + else: + return self._topology(capi.geos_simplify(self.ptr, tolerance)) + + def sym_difference(self, other): + """ + Return a set combining the points in this Geometry not in other, + and the points in other not in this Geometry. + """ + return self._topology(capi.geos_symdifference(self.ptr, other.ptr)) + + @property + def unary_union(self): + "Return the union of all the elements of this geometry." + return self._topology(capi.geos_unary_union(self.ptr)) + + def union(self, other): + "Return a Geometry representing all the points in this Geometry and other." + return self._topology(capi.geos_union(self.ptr, other.ptr)) + + # #### Other Routines #### + @property + def area(self): + "Return the area of the Geometry." + return capi.geos_area(self.ptr, byref(c_double())) + + def distance(self, other): + """ + Return the distance between the closest points on this Geometry + and the other. Units will be in those of the coordinate system of + the Geometry. + """ + if not isinstance(other, GEOSGeometry): + raise TypeError("distance() works only on other GEOS Geometries.") + return capi.geos_distance(self.ptr, other.ptr, byref(c_double())) + + @property + def extent(self): + """ + Return the extent of this geometry as a 4-tuple, consisting of + (xmin, ymin, xmax, ymax). + """ + from .point import Point + + env = self.envelope + if isinstance(env, Point): + xmin, ymin = env.tuple + xmax, ymax = xmin, ymin + else: + xmin, ymin = env[0][0] + xmax, ymax = env[0][2] + return (xmin, ymin, xmax, ymax) + + @property + def length(self): + """ + Return the length of this Geometry (e.g., 0 for point, or the + circumference of a Polygon). + """ + return capi.geos_length(self.ptr, byref(c_double())) + + def clone(self): + "Clone this Geometry." + return GEOSGeometry(capi.geom_clone(self.ptr)) + + +class LinearGeometryMixin: + """ + Used for LineString and MultiLineString. + """ + + def interpolate(self, distance): + return self._topology(capi.geos_interpolate(self.ptr, distance)) + + def interpolate_normalized(self, distance): + return self._topology(capi.geos_interpolate_normalized(self.ptr, distance)) + + def project(self, point): + from .point import Point + + if not isinstance(point, Point): + raise TypeError("locate_point argument must be a Point") + return capi.geos_project(self.ptr, point.ptr) + + def project_normalized(self, point): + from .point import Point + + if not isinstance(point, Point): + raise TypeError("locate_point argument must be a Point") + return capi.geos_project_normalized(self.ptr, point.ptr) + + @property + def merged(self): + """ + Return the line merge of this Geometry. + """ + return self._topology(capi.geos_linemerge(self.ptr)) + + @property + def closed(self): + """ + Return whether or not this Geometry is closed. + """ + return capi.geos_isclosed(self.ptr) + + +@deconstructible +class GEOSGeometry(GEOSGeometryBase, ListMixin): + "A class that, generally, encapsulates a GEOS geometry." + + def __init__(self, geo_input, srid=None): + """ + The base constructor for GEOS geometry objects. It may take the + following inputs: + + * strings: + - WKT + - HEXEWKB (a PostGIS-specific canonical form) + - GeoJSON (requires GDAL) + * memoryview: + - WKB + + The `srid` keyword specifies the Source Reference Identifier (SRID) + number for this Geometry. If not provided, it defaults to None. + """ + input_srid = None + if isinstance(geo_input, bytes): + geo_input = force_str(geo_input) + if isinstance(geo_input, str): + wkt_m = wkt_regex.match(geo_input) + if wkt_m: + # Handle WKT input. + if wkt_m["srid"]: + input_srid = int(wkt_m["srid"]) + g = self._from_wkt(force_bytes(wkt_m["wkt"])) + elif hex_regex.match(geo_input): + # Handle HEXEWKB input. + g = wkb_r().read(force_bytes(geo_input)) + elif json_regex.match(geo_input): + # Handle GeoJSON input. + ogr = gdal.OGRGeometry.from_json(geo_input) + g = ogr._geos_ptr() + input_srid = ogr.srid + else: + raise ValueError("String input unrecognized as WKT EWKT, and HEXEWKB.") + elif isinstance(geo_input, GEOM_PTR): + # When the input is a pointer to a geometry (GEOM_PTR). + g = geo_input + elif isinstance(geo_input, memoryview): + # When the input is a memoryview (WKB). + g = wkb_r().read(geo_input) + elif isinstance(geo_input, GEOSGeometry): + g = capi.geom_clone(geo_input.ptr) + else: + raise TypeError("Improper geometry input type: %s" % type(geo_input)) + + if not g: + raise GEOSException("Could not initialize GEOS Geometry with given input.") + + input_srid = input_srid or capi.geos_get_srid(g) or None + if input_srid and srid and input_srid != srid: + raise ValueError("Input geometry already has SRID: %d." % input_srid) + + super().__init__(g, None) + # Set the SRID, if given. + srid = input_srid or srid + if srid and isinstance(srid, int): + self.srid = srid diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/io.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/io.py new file mode 100644 index 0000000..d789806 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/io.py @@ -0,0 +1,27 @@ +""" +Module that holds classes for performing I/O operations on GEOS geometry +objects. Specifically, this has Python implementations of WKB/WKT +reader and writer classes. +""" +from django.contrib.gis.geos.geometry import GEOSGeometry +from django.contrib.gis.geos.prototypes.io import ( + WKBWriter, + WKTWriter, + _WKBReader, + _WKTReader, +) + +__all__ = ["WKBWriter", "WKTWriter", "WKBReader", "WKTReader"] + + +# Public classes for (WKB|WKT)Reader, which return GEOSGeometry +class WKBReader(_WKBReader): + def read(self, wkb): + "Return a GEOSGeometry for the given WKB buffer." + return GEOSGeometry(super().read(wkb)) + + +class WKTReader(_WKTReader): + def read(self, wkt): + "Return a GEOSGeometry for the given WKT string." + return GEOSGeometry(super().read(wkt)) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/libgeos.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/libgeos.py new file mode 100644 index 0000000..1121b4f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/libgeos.py @@ -0,0 +1,174 @@ +""" + This module houses the ctypes initialization procedures, as well + as the notice and error handler function callbacks (get called + when an error occurs in GEOS). + + This module also houses GEOS Pointer utilities, including + get_pointer_arr(), and GEOM_PTR. +""" +import logging +import os +from ctypes import CDLL, CFUNCTYPE, POINTER, Structure, c_char_p +from ctypes.util import find_library + +from django.core.exceptions import ImproperlyConfigured +from django.utils.functional import SimpleLazyObject, cached_property +from django.utils.version import get_version_tuple + +logger = logging.getLogger("django.contrib.gis") + + +def load_geos(): + # Custom library path set? + try: + from django.conf import settings + + lib_path = settings.GEOS_LIBRARY_PATH + except (AttributeError, ImportError, ImproperlyConfigured, OSError): + lib_path = None + + # Setting the appropriate names for the GEOS-C library. + if lib_path: + lib_names = None + elif os.name == "nt": + # Windows NT libraries + lib_names = ["geos_c", "libgeos_c-1"] + elif os.name == "posix": + # *NIX libraries + lib_names = ["geos_c", "GEOS"] + else: + raise ImportError('Unsupported OS "%s"' % os.name) + + # Using the ctypes `find_library` utility to find the path to the GEOS + # shared library. This is better than manually specifying each library name + # and extension (e.g., libgeos_c.[so|so.1|dylib].). + if lib_names: + for lib_name in lib_names: + lib_path = find_library(lib_name) + if lib_path is not None: + break + + # No GEOS library could be found. + if lib_path is None: + raise ImportError( + 'Could not find the GEOS library (tried "%s"). ' + "Try setting GEOS_LIBRARY_PATH in your settings." % '", "'.join(lib_names) + ) + # Getting the GEOS C library. The C interface (CDLL) is used for + # both *NIX and Windows. + # See the GEOS C API source code for more details on the library function calls: + # https://libgeos.org/doxygen/geos__c_8h_source.html + _lgeos = CDLL(lib_path) + # Here we set up the prototypes for the initGEOS_r and finishGEOS_r + # routines. These functions aren't actually called until they are + # attached to a GEOS context handle -- this actually occurs in + # geos/prototypes/threadsafe.py. + _lgeos.initGEOS_r.restype = CONTEXT_PTR + _lgeos.finishGEOS_r.argtypes = [CONTEXT_PTR] + # Set restype for compatibility across 32 and 64-bit platforms. + _lgeos.GEOSversion.restype = c_char_p + return _lgeos + + +# The notice and error handler C function callback definitions. +# Supposed to mimic the GEOS message handler (C below): +# typedef void (*GEOSMessageHandler)(const char *fmt, ...); +NOTICEFUNC = CFUNCTYPE(None, c_char_p, c_char_p) + + +def notice_h(fmt, lst): + fmt, lst = fmt.decode(), lst.decode() + try: + warn_msg = fmt % lst + except TypeError: + warn_msg = fmt + logger.warning("GEOS_NOTICE: %s\n", warn_msg) + + +notice_h = NOTICEFUNC(notice_h) + +ERRORFUNC = CFUNCTYPE(None, c_char_p, c_char_p) + + +def error_h(fmt, lst): + fmt, lst = fmt.decode(), lst.decode() + try: + err_msg = fmt % lst + except TypeError: + err_msg = fmt + logger.error("GEOS_ERROR: %s\n", err_msg) + + +error_h = ERRORFUNC(error_h) + +# #### GEOS Geometry C data structures, and utility functions. #### + + +# Opaque GEOS geometry structures, used for GEOM_PTR and CS_PTR +class GEOSGeom_t(Structure): + pass + + +class GEOSPrepGeom_t(Structure): + pass + + +class GEOSCoordSeq_t(Structure): + pass + + +class GEOSContextHandle_t(Structure): + pass + + +# Pointers to opaque GEOS geometry structures. +GEOM_PTR = POINTER(GEOSGeom_t) +PREPGEOM_PTR = POINTER(GEOSPrepGeom_t) +CS_PTR = POINTER(GEOSCoordSeq_t) +CONTEXT_PTR = POINTER(GEOSContextHandle_t) + + +lgeos = SimpleLazyObject(load_geos) + + +class GEOSFuncFactory: + """ + Lazy loading of GEOS functions. + """ + + argtypes = None + restype = None + errcheck = None + + def __init__(self, func_name, *, restype=None, errcheck=None, argtypes=None): + self.func_name = func_name + if restype is not None: + self.restype = restype + if errcheck is not None: + self.errcheck = errcheck + if argtypes is not None: + self.argtypes = argtypes + + def __call__(self, *args): + return self.func(*args) + + @cached_property + def func(self): + from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc + + func = GEOSFunc(self.func_name) + func.argtypes = self.argtypes or [] + func.restype = self.restype + if self.errcheck: + func.errcheck = self.errcheck + return func + + +def geos_version(): + """Return the string version of the GEOS library.""" + return lgeos.GEOSversion() + + +def geos_version_tuple(): + """Return the GEOS version as a tuple (major, minor, subminor).""" + return get_version_tuple(geos_version().decode()) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/linestring.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/linestring.py new file mode 100644 index 0000000..78a265c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/linestring.py @@ -0,0 +1,193 @@ +from django.contrib.gis.geos import prototypes as capi +from django.contrib.gis.geos.coordseq import GEOSCoordSeq +from django.contrib.gis.geos.error import GEOSException +from django.contrib.gis.geos.geometry import GEOSGeometry, LinearGeometryMixin +from django.contrib.gis.geos.point import Point +from django.contrib.gis.shortcuts import numpy + + +class LineString(LinearGeometryMixin, GEOSGeometry): + _init_func = capi.create_linestring + _minlength = 2 + has_cs = True + + def __init__(self, *args, **kwargs): + """ + Initialize on the given sequence -- may take lists, tuples, NumPy arrays + of X,Y pairs, or Point objects. If Point objects are used, ownership is + _not_ transferred to the LineString object. + + Examples: + ls = LineString((1, 1), (2, 2)) + ls = LineString([(1, 1), (2, 2)]) + ls = LineString(array([(1, 1), (2, 2)])) + ls = LineString(Point(1, 1), Point(2, 2)) + """ + # If only one argument provided, set the coords array appropriately + if len(args) == 1: + coords = args[0] + else: + coords = args + + if not ( + isinstance(coords, (tuple, list)) + or numpy + and isinstance(coords, numpy.ndarray) + ): + raise TypeError("Invalid initialization input for LineStrings.") + + # If SRID was passed in with the keyword arguments + srid = kwargs.get("srid") + + ncoords = len(coords) + if not ncoords: + super().__init__(self._init_func(None), srid=srid) + return + + if ncoords < self._minlength: + raise ValueError( + "%s requires at least %d points, got %s." + % ( + self.__class__.__name__, + self._minlength, + ncoords, + ) + ) + + numpy_coords = not isinstance(coords, (tuple, list)) + if numpy_coords: + shape = coords.shape # Using numpy's shape. + if len(shape) != 2: + raise TypeError("Too many dimensions.") + self._checkdim(shape[1]) + ndim = shape[1] + else: + # Getting the number of coords and the number of dimensions -- which + # must stay the same, e.g., no LineString((1, 2), (1, 2, 3)). + ndim = None + # Incrementing through each of the coordinates and verifying + for coord in coords: + if not isinstance(coord, (tuple, list, Point)): + raise TypeError( + "Each coordinate should be a sequence (list or tuple)" + ) + + if ndim is None: + ndim = len(coord) + self._checkdim(ndim) + elif len(coord) != ndim: + raise TypeError("Dimension mismatch.") + + # Creating a coordinate sequence object because it is easier to + # set the points using its methods. + cs = GEOSCoordSeq(capi.create_cs(ncoords, ndim), z=bool(ndim == 3)) + point_setter = cs._set_point_3d if ndim == 3 else cs._set_point_2d + + for i in range(ncoords): + if numpy_coords: + point_coords = coords[i, :] + elif isinstance(coords[i], Point): + point_coords = coords[i].tuple + else: + point_coords = coords[i] + point_setter(i, point_coords) + + # Calling the base geometry initialization with the returned pointer + # from the function. + super().__init__(self._init_func(cs.ptr), srid=srid) + + def __iter__(self): + "Allow iteration over this LineString." + for i in range(len(self)): + yield self[i] + + def __len__(self): + "Return the number of points in this LineString." + return len(self._cs) + + def _get_single_external(self, index): + return self._cs[index] + + _get_single_internal = _get_single_external + + def _set_list(self, length, items): + ndim = self._cs.dims + hasz = self._cs.hasz # I don't understand why these are different + srid = self.srid + + # create a new coordinate sequence and populate accordingly + cs = GEOSCoordSeq(capi.create_cs(length, ndim), z=hasz) + for i, c in enumerate(items): + cs[i] = c + + ptr = self._init_func(cs.ptr) + if ptr: + capi.destroy_geom(self.ptr) + self.ptr = ptr + if srid is not None: + self.srid = srid + self._post_init() + else: + # can this happen? + raise GEOSException("Geometry resulting from slice deletion was invalid.") + + def _set_single(self, index, value): + self._cs[index] = value + + def _checkdim(self, dim): + if dim not in (2, 3): + raise TypeError("Dimension mismatch.") + + # #### Sequence Properties #### + @property + def tuple(self): + "Return a tuple version of the geometry from the coordinate sequence." + return self._cs.tuple + + coords = tuple + + def _listarr(self, func): + """ + Return a sequence (list) corresponding with the given function. + Return a numpy array if possible. + """ + lst = [func(i) for i in range(len(self))] + if numpy: + return numpy.array(lst) # ARRRR! + else: + return lst + + @property + def array(self): + "Return a numpy array for the LineString." + return self._listarr(self._cs.__getitem__) + + @property + def x(self): + "Return a list or numpy array of the X variable." + return self._listarr(self._cs.getX) + + @property + def y(self): + "Return a list or numpy array of the Y variable." + return self._listarr(self._cs.getY) + + @property + def z(self): + "Return a list or numpy array of the Z variable." + if not self.hasz: + return None + else: + return self._listarr(self._cs.getZ) + + +# LinearRings are LineStrings used within Polygons. +class LinearRing(LineString): + _minlength = 4 + _init_func = capi.create_linearring + + @property + def is_counterclockwise(self): + if self.empty: + raise ValueError("Orientation of an empty LinearRing cannot be determined.") + return self._cs.is_counterclockwise diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/mutable_list.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/mutable_list.py new file mode 100644 index 0000000..36131fe --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/mutable_list.py @@ -0,0 +1,314 @@ +# Copyright (c) 2008-2009 Aryeh Leib Taurog, all rights reserved. +# Released under the New BSD license. +""" +This module contains a base type which provides list-style mutations +without specific data storage methods. + +See also http://static.aryehleib.com/oldsite/MutableLists.html + +Author: Aryeh Leib Taurog. +""" +from functools import total_ordering + + +@total_ordering +class ListMixin: + """ + A base class which provides complete list interface. + Derived classes must call ListMixin's __init__() function + and implement the following: + + function _get_single_external(self, i): + Return single item with index i for general use. + The index i will always satisfy 0 <= i < len(self). + + function _get_single_internal(self, i): + Same as above, but for use within the class [Optional] + Note that if _get_single_internal and _get_single_internal return + different types of objects, _set_list must distinguish + between the two and handle each appropriately. + + function _set_list(self, length, items): + Recreate the entire object. + + NOTE: items may be a generator which calls _get_single_internal. + Therefore, it is necessary to cache the values in a temporary: + temp = list(items) + before clobbering the original storage. + + function _set_single(self, i, value): + Set the single item at index i to value [Optional] + If left undefined, all mutations will result in rebuilding + the object using _set_list. + + function __len__(self): + Return the length + + int _minlength: + The minimum legal length [Optional] + + int _maxlength: + The maximum legal length [Optional] + + type or tuple _allowed: + A type or tuple of allowed item types [Optional] + """ + + _minlength = 0 + _maxlength = None + + # ### Python initialization and special list interface methods ### + + def __init__(self, *args, **kwargs): + if not hasattr(self, "_get_single_internal"): + self._get_single_internal = self._get_single_external + + if not hasattr(self, "_set_single"): + self._set_single = self._set_single_rebuild + self._assign_extended_slice = self._assign_extended_slice_rebuild + + super().__init__(*args, **kwargs) + + def __getitem__(self, index): + "Get the item(s) at the specified index/slice." + if isinstance(index, slice): + return [ + self._get_single_external(i) for i in range(*index.indices(len(self))) + ] + else: + index = self._checkindex(index) + return self._get_single_external(index) + + def __delitem__(self, index): + "Delete the item(s) at the specified index/slice." + if not isinstance(index, (int, slice)): + raise TypeError("%s is not a legal index" % index) + + # calculate new length and dimensions + origLen = len(self) + if isinstance(index, int): + index = self._checkindex(index) + indexRange = [index] + else: + indexRange = range(*index.indices(origLen)) + + newLen = origLen - len(indexRange) + newItems = ( + self._get_single_internal(i) for i in range(origLen) if i not in indexRange + ) + + self._rebuild(newLen, newItems) + + def __setitem__(self, index, val): + "Set the item(s) at the specified index/slice." + if isinstance(index, slice): + self._set_slice(index, val) + else: + index = self._checkindex(index) + self._check_allowed((val,)) + self._set_single(index, val) + + # ### Special methods for arithmetic operations ### + def __add__(self, other): + "add another list-like object" + return self.__class__([*self, *other]) + + def __radd__(self, other): + "add to another list-like object" + return other.__class__([*other, *self]) + + def __iadd__(self, other): + "add another list-like object to self" + self.extend(other) + return self + + def __mul__(self, n): + "multiply" + return self.__class__(list(self) * n) + + def __rmul__(self, n): + "multiply" + return self.__class__(list(self) * n) + + def __imul__(self, n): + "multiply" + if n <= 0: + del self[:] + else: + cache = list(self) + for i in range(n - 1): + self.extend(cache) + return self + + def __eq__(self, other): + olen = len(other) + for i in range(olen): + try: + c = self[i] == other[i] + except IndexError: + # self must be shorter + return False + if not c: + return False + return len(self) == olen + + def __lt__(self, other): + olen = len(other) + for i in range(olen): + try: + c = self[i] < other[i] + except IndexError: + # self must be shorter + return True + if c: + return c + elif other[i] < self[i]: + return False + return len(self) < olen + + # ### Public list interface Methods ### + # ## Non-mutating ## + def count(self, val): + "Standard list count method" + count = 0 + for i in self: + if val == i: + count += 1 + return count + + def index(self, val): + "Standard list index method" + for i in range(0, len(self)): + if self[i] == val: + return i + raise ValueError("%s not found in object" % val) + + # ## Mutating ## + def append(self, val): + "Standard list append method" + self[len(self) :] = [val] + + def extend(self, vals): + "Standard list extend method" + self[len(self) :] = vals + + def insert(self, index, val): + "Standard list insert method" + if not isinstance(index, int): + raise TypeError("%s is not a legal index" % index) + self[index:index] = [val] + + def pop(self, index=-1): + "Standard list pop method" + result = self[index] + del self[index] + return result + + def remove(self, val): + "Standard list remove method" + del self[self.index(val)] + + def reverse(self): + "Standard list reverse method" + self[:] = self[-1::-1] + + def sort(self, key=None, reverse=False): + "Standard list sort method" + self[:] = sorted(self, key=key, reverse=reverse) + + # ### Private routines ### + def _rebuild(self, newLen, newItems): + if newLen and newLen < self._minlength: + raise ValueError("Must have at least %d items" % self._minlength) + if self._maxlength is not None and newLen > self._maxlength: + raise ValueError("Cannot have more than %d items" % self._maxlength) + + self._set_list(newLen, newItems) + + def _set_single_rebuild(self, index, value): + self._set_slice(slice(index, index + 1, 1), [value]) + + def _checkindex(self, index): + length = len(self) + if 0 <= index < length: + return index + if -length <= index < 0: + return index + length + raise IndexError("invalid index: %s" % index) + + def _check_allowed(self, items): + if hasattr(self, "_allowed"): + if False in [isinstance(val, self._allowed) for val in items]: + raise TypeError("Invalid type encountered in the arguments.") + + def _set_slice(self, index, values): + "Assign values to a slice of the object" + try: + valueList = list(values) + except TypeError: + raise TypeError("can only assign an iterable to a slice") + + self._check_allowed(valueList) + + origLen = len(self) + start, stop, step = index.indices(origLen) + + # CAREFUL: index.step and step are not the same! + # step will never be None + if index.step is None: + self._assign_simple_slice(start, stop, valueList) + else: + self._assign_extended_slice(start, stop, step, valueList) + + def _assign_extended_slice_rebuild(self, start, stop, step, valueList): + "Assign an extended slice by rebuilding entire list" + indexList = range(start, stop, step) + # extended slice, only allow assigning slice of same size + if len(valueList) != len(indexList): + raise ValueError( + "attempt to assign sequence of size %d " + "to extended slice of size %d" % (len(valueList), len(indexList)) + ) + + # we're not changing the length of the sequence + newLen = len(self) + newVals = dict(zip(indexList, valueList)) + + def newItems(): + for i in range(newLen): + if i in newVals: + yield newVals[i] + else: + yield self._get_single_internal(i) + + self._rebuild(newLen, newItems()) + + def _assign_extended_slice(self, start, stop, step, valueList): + "Assign an extended slice by re-assigning individual items" + indexList = range(start, stop, step) + # extended slice, only allow assigning slice of same size + if len(valueList) != len(indexList): + raise ValueError( + "attempt to assign sequence of size %d " + "to extended slice of size %d" % (len(valueList), len(indexList)) + ) + + for i, val in zip(indexList, valueList): + self._set_single(i, val) + + def _assign_simple_slice(self, start, stop, valueList): + "Assign a simple slice; Can assign slice of any length" + origLen = len(self) + stop = max(start, stop) + newLen = origLen - stop + start + len(valueList) + + def newItems(): + for i in range(origLen + 1): + if i == start: + yield from valueList + + if i < origLen: + if i < start or i >= stop: + yield self._get_single_internal(i) + + self._rebuild(newLen, newItems()) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/point.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/point.py new file mode 100644 index 0000000..06b2668 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/point.py @@ -0,0 +1,162 @@ +from ctypes import c_uint + +from django.contrib.gis import gdal +from django.contrib.gis.geos import prototypes as capi +from django.contrib.gis.geos.error import GEOSException +from django.contrib.gis.geos.geometry import GEOSGeometry + + +class Point(GEOSGeometry): + _minlength = 2 + _maxlength = 3 + has_cs = True + + def __init__(self, x=None, y=None, z=None, srid=None): + """ + The Point object may be initialized with either a tuple, or individual + parameters. + + For example: + >>> p = Point((5, 23)) # 2D point, passed in as a tuple + >>> p = Point(5, 23, 8) # 3D point, passed in with individual parameters + """ + if x is None: + coords = [] + elif isinstance(x, (tuple, list)): + # Here a tuple or list was passed in under the `x` parameter. + coords = x + elif isinstance(x, (float, int)) and isinstance(y, (float, int)): + # Here X, Y, and (optionally) Z were passed in individually, as parameters. + if isinstance(z, (float, int)): + coords = [x, y, z] + else: + coords = [x, y] + else: + raise TypeError("Invalid parameters given for Point initialization.") + + point = self._create_point(len(coords), coords) + + # Initializing using the address returned from the GEOS + # createPoint factory. + super().__init__(point, srid=srid) + + def _to_pickle_wkb(self): + return None if self.empty else super()._to_pickle_wkb() + + def _from_pickle_wkb(self, wkb): + return self._create_empty() if wkb is None else super()._from_pickle_wkb(wkb) + + def _ogr_ptr(self): + return ( + gdal.geometries.Point._create_empty() if self.empty else super()._ogr_ptr() + ) + + @classmethod + def _create_empty(cls): + return cls._create_point(None, None) + + @classmethod + def _create_point(cls, ndim, coords): + """ + Create a coordinate sequence, set X, Y, [Z], and create point + """ + if not ndim: + return capi.create_point(None) + + if ndim < 2 or ndim > 3: + raise TypeError("Invalid point dimension: %s" % ndim) + + cs = capi.create_cs(c_uint(1), c_uint(ndim)) + i = iter(coords) + capi.cs_setx(cs, 0, next(i)) + capi.cs_sety(cs, 0, next(i)) + if ndim == 3: + capi.cs_setz(cs, 0, next(i)) + + return capi.create_point(cs) + + def _set_list(self, length, items): + ptr = self._create_point(length, items) + if ptr: + srid = self.srid + capi.destroy_geom(self.ptr) + self._ptr = ptr + if srid is not None: + self.srid = srid + self._post_init() + else: + # can this happen? + raise GEOSException("Geometry resulting from slice deletion was invalid.") + + def _set_single(self, index, value): + self._cs.setOrdinate(index, 0, value) + + def __iter__(self): + "Iterate over coordinates of this Point." + for i in range(len(self)): + yield self[i] + + def __len__(self): + "Return the number of dimensions for this Point (either 0, 2 or 3)." + if self.empty: + return 0 + if self.hasz: + return 3 + else: + return 2 + + def _get_single_external(self, index): + if index == 0: + return self.x + elif index == 1: + return self.y + elif index == 2: + return self.z + + _get_single_internal = _get_single_external + + @property + def x(self): + "Return the X component of the Point." + return self._cs.getOrdinate(0, 0) + + @x.setter + def x(self, value): + "Set the X component of the Point." + self._cs.setOrdinate(0, 0, value) + + @property + def y(self): + "Return the Y component of the Point." + return self._cs.getOrdinate(1, 0) + + @y.setter + def y(self, value): + "Set the Y component of the Point." + self._cs.setOrdinate(1, 0, value) + + @property + def z(self): + "Return the Z component of the Point." + return self._cs.getOrdinate(2, 0) if self.hasz else None + + @z.setter + def z(self, value): + "Set the Z component of the Point." + if not self.hasz: + raise GEOSException("Cannot set Z on 2D Point.") + self._cs.setOrdinate(2, 0, value) + + # ### Tuple setting and retrieval routines. ### + @property + def tuple(self): + "Return a tuple of the point." + return self._cs.tuple + + @tuple.setter + def tuple(self, tup): + "Set the coordinates of the point with the given tuple." + self._cs[0] = tup + + # The tuple and coords properties + coords = tuple diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/polygon.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/polygon.py new file mode 100644 index 0000000..6f76b57 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/polygon.py @@ -0,0 +1,189 @@ +from django.contrib.gis.geos import prototypes as capi +from django.contrib.gis.geos.geometry import GEOSGeometry +from django.contrib.gis.geos.libgeos import GEOM_PTR +from django.contrib.gis.geos.linestring import LinearRing + + +class Polygon(GEOSGeometry): + _minlength = 1 + + def __init__(self, *args, **kwargs): + """ + Initialize on an exterior ring and a sequence of holes (both + instances may be either LinearRing instances, or a tuple/list + that may be constructed into a LinearRing). + + Examples of initialization, where shell, hole1, and hole2 are + valid LinearRing geometries: + >>> from django.contrib.gis.geos import LinearRing, Polygon + >>> shell = hole1 = hole2 = LinearRing() + >>> poly = Polygon(shell, hole1, hole2) + >>> poly = Polygon(shell, (hole1, hole2)) + + >>> # Example where a tuple parameters are used: + >>> poly = Polygon(((0, 0), (0, 10), (10, 10), (10, 0), (0, 0)), + ... ((4, 4), (4, 6), (6, 6), (6, 4), (4, 4))) + """ + if not args: + super().__init__(self._create_polygon(0, None), **kwargs) + return + + # Getting the ext_ring and init_holes parameters from the argument list + ext_ring, *init_holes = args + n_holes = len(init_holes) + + # If initialized as Polygon(shell, (LinearRing, LinearRing)) + # [for backward-compatibility] + if n_holes == 1 and isinstance(init_holes[0], (tuple, list)): + if not init_holes[0]: + init_holes = () + n_holes = 0 + elif isinstance(init_holes[0][0], LinearRing): + init_holes = init_holes[0] + n_holes = len(init_holes) + + polygon = self._create_polygon(n_holes + 1, [ext_ring, *init_holes]) + super().__init__(polygon, **kwargs) + + def __iter__(self): + "Iterate over each ring in the polygon." + for i in range(len(self)): + yield self[i] + + def __len__(self): + "Return the number of rings in this Polygon." + return self.num_interior_rings + 1 + + @classmethod + def from_bbox(cls, bbox): + "Construct a Polygon from a bounding box (4-tuple)." + x0, y0, x1, y1 = bbox + for z in bbox: + if not isinstance(z, (float, int)): + return GEOSGeometry( + "POLYGON((%s %s, %s %s, %s %s, %s %s, %s %s))" + % (x0, y0, x0, y1, x1, y1, x1, y0, x0, y0) + ) + return Polygon(((x0, y0), (x0, y1), (x1, y1), (x1, y0), (x0, y0))) + + # ### These routines are needed for list-like operation w/ListMixin ### + def _create_polygon(self, length, items): + # Instantiate LinearRing objects if necessary, but don't clone them yet + # _construct_ring will throw a TypeError if a parameter isn't a valid ring + # If we cloned the pointers here, we wouldn't be able to clean up + # in case of error. + if not length: + return capi.create_empty_polygon() + + rings = [] + for r in items: + if isinstance(r, GEOM_PTR): + rings.append(r) + else: + rings.append(self._construct_ring(r)) + + shell = self._clone(rings.pop(0)) + + n_holes = length - 1 + if n_holes: + holes_param = (GEOM_PTR * n_holes)(*[self._clone(r) for r in rings]) + else: + holes_param = None + + return capi.create_polygon(shell, holes_param, n_holes) + + def _clone(self, g): + if isinstance(g, GEOM_PTR): + return capi.geom_clone(g) + else: + return capi.geom_clone(g.ptr) + + def _construct_ring( + self, + param, + msg=( + "Parameter must be a sequence of LinearRings or objects that can " + "initialize to LinearRings" + ), + ): + "Try to construct a ring from the given parameter." + if isinstance(param, LinearRing): + return param + try: + return LinearRing(param) + except TypeError: + raise TypeError(msg) + + def _set_list(self, length, items): + # Getting the current pointer, replacing with the newly constructed + # geometry, and destroying the old geometry. + prev_ptr = self.ptr + srid = self.srid + self.ptr = self._create_polygon(length, items) + if srid: + self.srid = srid + capi.destroy_geom(prev_ptr) + + def _get_single_internal(self, index): + """ + Return the ring at the specified index. The first index, 0, will + always return the exterior ring. Indices > 0 will return the + interior ring at the given index (e.g., poly[1] and poly[2] would + return the first and second interior ring, respectively). + + CAREFUL: Internal/External are not the same as Interior/Exterior! + Return a pointer from the existing geometries for use internally by the + object's methods. _get_single_external() returns a clone of the same + geometry for use by external code. + """ + if index == 0: + return capi.get_extring(self.ptr) + else: + # Getting the interior ring, have to subtract 1 from the index. + return capi.get_intring(self.ptr, index - 1) + + def _get_single_external(self, index): + return GEOSGeometry( + capi.geom_clone(self._get_single_internal(index)), srid=self.srid + ) + + _set_single = GEOSGeometry._set_single_rebuild + _assign_extended_slice = GEOSGeometry._assign_extended_slice_rebuild + + # #### Polygon Properties #### + @property + def num_interior_rings(self): + "Return the number of interior rings." + # Getting the number of rings + return capi.get_nrings(self.ptr) + + def _get_ext_ring(self): + "Get the exterior ring of the Polygon." + return self[0] + + def _set_ext_ring(self, ring): + "Set the exterior ring of the Polygon." + self[0] = ring + + # Properties for the exterior ring/shell. + exterior_ring = property(_get_ext_ring, _set_ext_ring) + shell = exterior_ring + + @property + def tuple(self): + "Get the tuple for each ring in this Polygon." + return tuple(self[i].tuple for i in range(len(self))) + + coords = tuple + + @property + def kml(self): + "Return the KML representation of this Polygon." + inner_kml = "".join( + "%s" % self[i + 1].kml + for i in range(self.num_interior_rings) + ) + return "%s%s" % ( + self[0].kml, + inner_kml, + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prepared.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prepared.py new file mode 100644 index 0000000..9c77d8a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prepared.py @@ -0,0 +1,51 @@ +from .base import GEOSBase +from .prototypes import prepared as capi + + +class PreparedGeometry(GEOSBase): + """ + A geometry that is prepared for performing certain operations. + At the moment this includes the contains covers, and intersects + operations. + """ + + ptr_type = capi.PREPGEOM_PTR + destructor = capi.prepared_destroy + + def __init__(self, geom): + # Keeping a reference to the original geometry object to prevent it + # from being garbage collected which could then crash the prepared one + # See #21662 + self._base_geom = geom + from .geometry import GEOSGeometry + + if not isinstance(geom, GEOSGeometry): + raise TypeError + self.ptr = capi.geos_prepare(geom.ptr) + + def contains(self, other): + return capi.prepared_contains(self.ptr, other.ptr) + + def contains_properly(self, other): + return capi.prepared_contains_properly(self.ptr, other.ptr) + + def covers(self, other): + return capi.prepared_covers(self.ptr, other.ptr) + + def intersects(self, other): + return capi.prepared_intersects(self.ptr, other.ptr) + + def crosses(self, other): + return capi.prepared_crosses(self.ptr, other.ptr) + + def disjoint(self, other): + return capi.prepared_disjoint(self.ptr, other.ptr) + + def overlaps(self, other): + return capi.prepared_overlaps(self.ptr, other.ptr) + + def touches(self, other): + return capi.prepared_touches(self.ptr, other.ptr) + + def within(self, other): + return capi.prepared_within(self.ptr, other.ptr) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/__init__.py new file mode 100644 index 0000000..3e980b9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/__init__.py @@ -0,0 +1,67 @@ +""" + This module contains all of the GEOS ctypes function prototypes. Each + prototype handles the interaction between the GEOS library and Python + via ctypes. +""" + +from django.contrib.gis.geos.prototypes.coordseq import ( # NOQA + create_cs, + cs_clone, + cs_getdims, + cs_getordinate, + cs_getsize, + cs_getx, + cs_gety, + cs_getz, + cs_is_ccw, + cs_setordinate, + cs_setx, + cs_sety, + cs_setz, + get_cs, +) +from django.contrib.gis.geos.prototypes.geom import ( # NOQA + create_collection, + create_empty_polygon, + create_linearring, + create_linestring, + create_point, + create_polygon, + destroy_geom, + geom_clone, + geos_get_srid, + geos_makevalid, + geos_normalize, + geos_set_srid, + geos_type, + geos_typeid, + get_dims, + get_extring, + get_geomn, + get_intring, + get_nrings, + get_num_coords, + get_num_geoms, +) +from django.contrib.gis.geos.prototypes.misc import * # NOQA +from django.contrib.gis.geos.prototypes.predicates import ( # NOQA + geos_contains, + geos_covers, + geos_crosses, + geos_disjoint, + geos_equals, + geos_equalsexact, + geos_equalsidentical, + geos_hasz, + geos_intersects, + geos_isclosed, + geos_isempty, + geos_isring, + geos_issimple, + geos_isvalid, + geos_overlaps, + geos_relatepattern, + geos_touches, + geos_within, +) +from django.contrib.gis.geos.prototypes.topology import * # NOQA diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/coordseq.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/coordseq.py new file mode 100644 index 0000000..ed05de9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/coordseq.py @@ -0,0 +1,95 @@ +from ctypes import POINTER, c_byte, c_double, c_int, c_uint + +from django.contrib.gis.geos.libgeos import CS_PTR, GEOM_PTR, GEOSFuncFactory +from django.contrib.gis.geos.prototypes.errcheck import GEOSException, last_arg_byref + + +# ## Error-checking routines specific to coordinate sequences. ## +def check_cs_op(result, func, cargs): + "Check the status code of a coordinate sequence operation." + if result == 0: + raise GEOSException("Could not set value on coordinate sequence") + else: + return result + + +def check_cs_get(result, func, cargs): + "Check the coordinate sequence retrieval." + check_cs_op(result, func, cargs) + # Object in by reference, return its value. + return last_arg_byref(cargs) + + +# ## Coordinate sequence prototype factory classes. ## +class CsInt(GEOSFuncFactory): + "For coordinate sequence routines that return an integer." + argtypes = [CS_PTR, POINTER(c_uint)] + restype = c_int + errcheck = staticmethod(check_cs_get) + + +class CsOperation(GEOSFuncFactory): + "For coordinate sequence operations." + restype = c_int + + def __init__(self, *args, ordinate=False, get=False, **kwargs): + if get: + # Get routines have double parameter passed-in by reference. + errcheck = check_cs_get + dbl_param = POINTER(c_double) + else: + errcheck = check_cs_op + dbl_param = c_double + + if ordinate: + # Get/Set ordinate routines have an extra uint parameter. + argtypes = [CS_PTR, c_uint, c_uint, dbl_param] + else: + argtypes = [CS_PTR, c_uint, dbl_param] + + super().__init__( + *args, **{**kwargs, "errcheck": errcheck, "argtypes": argtypes} + ) + + +class CsOutput(GEOSFuncFactory): + restype = CS_PTR + + @staticmethod + def errcheck(result, func, cargs): + if not result: + raise GEOSException( + "Error encountered checking Coordinate Sequence returned from GEOS " + 'C function "%s".' % func.__name__ + ) + return result + + +# ## Coordinate Sequence ctypes prototypes ## + +# Coordinate Sequence constructors & cloning. +cs_clone = CsOutput("GEOSCoordSeq_clone", argtypes=[CS_PTR]) +create_cs = CsOutput("GEOSCoordSeq_create", argtypes=[c_uint, c_uint]) +get_cs = CsOutput("GEOSGeom_getCoordSeq", argtypes=[GEOM_PTR]) + +# Getting, setting ordinate +cs_getordinate = CsOperation("GEOSCoordSeq_getOrdinate", ordinate=True, get=True) +cs_setordinate = CsOperation("GEOSCoordSeq_setOrdinate", ordinate=True) + +# For getting, x, y, z +cs_getx = CsOperation("GEOSCoordSeq_getX", get=True) +cs_gety = CsOperation("GEOSCoordSeq_getY", get=True) +cs_getz = CsOperation("GEOSCoordSeq_getZ", get=True) + +# For setting, x, y, z +cs_setx = CsOperation("GEOSCoordSeq_setX") +cs_sety = CsOperation("GEOSCoordSeq_setY") +cs_setz = CsOperation("GEOSCoordSeq_setZ") + +# These routines return size & dimensions. +cs_getsize = CsInt("GEOSCoordSeq_getSize") +cs_getdims = CsInt("GEOSCoordSeq_getDimensions") + +cs_is_ccw = GEOSFuncFactory( + "GEOSCoordSeq_isCCW", restype=c_int, argtypes=[CS_PTR, POINTER(c_byte)] +) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/errcheck.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/errcheck.py new file mode 100644 index 0000000..a527f51 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/errcheck.py @@ -0,0 +1,95 @@ +""" + Error checking functions for GEOS ctypes prototype functions. +""" +from ctypes import c_void_p, string_at + +from django.contrib.gis.geos.error import GEOSException +from django.contrib.gis.geos.libgeos import GEOSFuncFactory + +# Getting the `free` routine used to free the memory allocated for +# string pointers returned by GEOS. +free = GEOSFuncFactory("GEOSFree") +free.argtypes = [c_void_p] + + +def last_arg_byref(args): + "Return the last C argument's value by reference." + return args[-1]._obj.value + + +def check_dbl(result, func, cargs): + "Check the status code and returns the double value passed in by reference." + # Checking the status code + if result != 1: + return None + # Double passed in by reference, return its value. + return last_arg_byref(cargs) + + +def check_geom(result, func, cargs): + "Error checking on routines that return Geometries." + if not result: + raise GEOSException( + 'Error encountered checking Geometry returned from GEOS C function "%s".' + % func.__name__ + ) + return result + + +def check_minus_one(result, func, cargs): + "Error checking on routines that should not return -1." + if result == -1: + raise GEOSException( + 'Error encountered in GEOS C function "%s".' % func.__name__ + ) + else: + return result + + +def check_predicate(result, func, cargs): + "Error checking for unary/binary predicate functions." + if result == 1: + return True + elif result == 0: + return False + else: + raise GEOSException( + 'Error encountered on GEOS C predicate function "%s".' % func.__name__ + ) + + +def check_sized_string(result, func, cargs): + """ + Error checking for routines that return explicitly sized strings. + + This frees the memory allocated by GEOS at the result pointer. + """ + if not result: + raise GEOSException( + 'Invalid string pointer returned by GEOS C function "%s"' % func.__name__ + ) + # A c_size_t object is passed in by reference for the second + # argument on these routines, and its needed to determine the + # correct size. + s = string_at(result, last_arg_byref(cargs)) + # Freeing the memory allocated within GEOS + free(result) + return s + + +def check_string(result, func, cargs): + """ + Error checking for routines that return strings. + + This frees the memory allocated by GEOS at the result pointer. + """ + if not result: + raise GEOSException( + 'Error encountered checking string return value in GEOS C function "%s".' + % func.__name__ + ) + # Getting the string value at the pointer address. + s = string_at(result) + # Freeing the memory allocated within GEOS + free(result) + return s diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/geom.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/geom.py new file mode 100644 index 0000000..a456acd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/geom.py @@ -0,0 +1,91 @@ +from ctypes import POINTER, c_char_p, c_int, c_ubyte, c_uint + +from django.contrib.gis.geos.libgeos import CS_PTR, GEOM_PTR, GEOSFuncFactory +from django.contrib.gis.geos.prototypes.errcheck import ( + check_geom, + check_minus_one, + check_string, +) + +# This is the return type used by binary output (WKB, HEX) routines. +c_uchar_p = POINTER(c_ubyte) + + +# We create a simple subclass of c_char_p here because when the response +# type is set to c_char_p, you get a _Python_ string and there's no way +# to access the string's address inside the error checking function. +# In other words, you can't free the memory allocated inside GEOS. Previously, +# the return type would just be omitted and the integer address would be +# used -- but this allows us to be specific in the function definition and +# keeps the reference so it may be free'd. +class geos_char_p(c_char_p): + pass + + +# ### ctypes factory classes ### +class GeomOutput(GEOSFuncFactory): + "For GEOS routines that return a geometry." + restype = GEOM_PTR + errcheck = staticmethod(check_geom) + + +class IntFromGeom(GEOSFuncFactory): + "Argument is a geometry, return type is an integer." + argtypes = [GEOM_PTR] + restype = c_int + errcheck = staticmethod(check_minus_one) + + +class StringFromGeom(GEOSFuncFactory): + "Argument is a Geometry, return type is a string." + argtypes = [GEOM_PTR] + restype = geos_char_p + errcheck = staticmethod(check_string) + + +# ### ctypes prototypes ### + +# The GEOS geometry type, typeid, num_coordinates and number of geometries +geos_makevalid = GeomOutput("GEOSMakeValid", argtypes=[GEOM_PTR]) +geos_normalize = IntFromGeom("GEOSNormalize") +geos_type = StringFromGeom("GEOSGeomType") +geos_typeid = IntFromGeom("GEOSGeomTypeId") +get_dims = GEOSFuncFactory("GEOSGeom_getDimensions", argtypes=[GEOM_PTR], restype=c_int) +get_num_coords = IntFromGeom("GEOSGetNumCoordinates") +get_num_geoms = IntFromGeom("GEOSGetNumGeometries") + +# Geometry creation factories +create_point = GeomOutput("GEOSGeom_createPoint", argtypes=[CS_PTR]) +create_linestring = GeomOutput("GEOSGeom_createLineString", argtypes=[CS_PTR]) +create_linearring = GeomOutput("GEOSGeom_createLinearRing", argtypes=[CS_PTR]) + +# Polygon and collection creation routines need argument types defined +# for compatibility with some platforms, e.g. macOS ARM64. With argtypes +# defined, arrays are automatically cast and byref() calls are not needed. +create_polygon = GeomOutput( + "GEOSGeom_createPolygon", + argtypes=[GEOM_PTR, POINTER(GEOM_PTR), c_uint], +) +create_empty_polygon = GeomOutput("GEOSGeom_createEmptyPolygon", argtypes=[]) +create_collection = GeomOutput( + "GEOSGeom_createCollection", + argtypes=[c_int, POINTER(GEOM_PTR), c_uint], +) + +# Ring routines +get_extring = GeomOutput("GEOSGetExteriorRing", argtypes=[GEOM_PTR]) +get_intring = GeomOutput("GEOSGetInteriorRingN", argtypes=[GEOM_PTR, c_int]) +get_nrings = IntFromGeom("GEOSGetNumInteriorRings") + +# Collection Routines +get_geomn = GeomOutput("GEOSGetGeometryN", argtypes=[GEOM_PTR, c_int]) + +# Cloning +geom_clone = GEOSFuncFactory("GEOSGeom_clone", argtypes=[GEOM_PTR], restype=GEOM_PTR) + +# Destruction routine. +destroy_geom = GEOSFuncFactory("GEOSGeom_destroy", argtypes=[GEOM_PTR]) + +# SRID routines +geos_get_srid = GEOSFuncFactory("GEOSGetSRID", argtypes=[GEOM_PTR], restype=c_int) +geos_set_srid = GEOSFuncFactory("GEOSSetSRID", argtypes=[GEOM_PTR, c_int]) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/io.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/io.py new file mode 100644 index 0000000..efe9ec1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/io.py @@ -0,0 +1,369 @@ +import threading +from ctypes import POINTER, Structure, byref, c_byte, c_char_p, c_int, c_size_t + +from django.contrib.gis.geos.base import GEOSBase +from django.contrib.gis.geos.libgeos import ( + GEOM_PTR, + GEOSFuncFactory, + geos_version_tuple, +) +from django.contrib.gis.geos.prototypes.errcheck import ( + check_geom, + check_sized_string, + check_string, +) +from django.contrib.gis.geos.prototypes.geom import c_uchar_p, geos_char_p +from django.utils.encoding import force_bytes +from django.utils.functional import SimpleLazyObject + + +# ### The WKB/WKT Reader/Writer structures and pointers ### +class WKTReader_st(Structure): + pass + + +class WKTWriter_st(Structure): + pass + + +class WKBReader_st(Structure): + pass + + +class WKBWriter_st(Structure): + pass + + +WKT_READ_PTR = POINTER(WKTReader_st) +WKT_WRITE_PTR = POINTER(WKTWriter_st) +WKB_READ_PTR = POINTER(WKBReader_st) +WKB_WRITE_PTR = POINTER(WKBReader_st) + +# WKTReader routines +wkt_reader_create = GEOSFuncFactory("GEOSWKTReader_create", restype=WKT_READ_PTR) +wkt_reader_destroy = GEOSFuncFactory("GEOSWKTReader_destroy", argtypes=[WKT_READ_PTR]) + +wkt_reader_read = GEOSFuncFactory( + "GEOSWKTReader_read", + argtypes=[WKT_READ_PTR, c_char_p], + restype=GEOM_PTR, + errcheck=check_geom, +) +# WKTWriter routines +wkt_writer_create = GEOSFuncFactory("GEOSWKTWriter_create", restype=WKT_WRITE_PTR) +wkt_writer_destroy = GEOSFuncFactory("GEOSWKTWriter_destroy", argtypes=[WKT_WRITE_PTR]) + +wkt_writer_write = GEOSFuncFactory( + "GEOSWKTWriter_write", + argtypes=[WKT_WRITE_PTR, GEOM_PTR], + restype=geos_char_p, + errcheck=check_string, +) + +wkt_writer_get_outdim = GEOSFuncFactory( + "GEOSWKTWriter_getOutputDimension", argtypes=[WKT_WRITE_PTR], restype=c_int +) +wkt_writer_set_outdim = GEOSFuncFactory( + "GEOSWKTWriter_setOutputDimension", argtypes=[WKT_WRITE_PTR, c_int] +) + +wkt_writer_set_trim = GEOSFuncFactory( + "GEOSWKTWriter_setTrim", argtypes=[WKT_WRITE_PTR, c_byte] +) +wkt_writer_set_precision = GEOSFuncFactory( + "GEOSWKTWriter_setRoundingPrecision", argtypes=[WKT_WRITE_PTR, c_int] +) + +# WKBReader routines +wkb_reader_create = GEOSFuncFactory("GEOSWKBReader_create", restype=WKB_READ_PTR) +wkb_reader_destroy = GEOSFuncFactory("GEOSWKBReader_destroy", argtypes=[WKB_READ_PTR]) + + +class WKBReadFunc(GEOSFuncFactory): + # Although the function definitions take `const unsigned char *` + # as their parameter, we use c_char_p here so the function may + # take Python strings directly as parameters. Inside Python there + # is not a difference between signed and unsigned characters, so + # it is not a problem. + argtypes = [WKB_READ_PTR, c_char_p, c_size_t] + restype = GEOM_PTR + errcheck = staticmethod(check_geom) + + +wkb_reader_read = WKBReadFunc("GEOSWKBReader_read") +wkb_reader_read_hex = WKBReadFunc("GEOSWKBReader_readHEX") + +# WKBWriter routines +wkb_writer_create = GEOSFuncFactory("GEOSWKBWriter_create", restype=WKB_WRITE_PTR) +wkb_writer_destroy = GEOSFuncFactory("GEOSWKBWriter_destroy", argtypes=[WKB_WRITE_PTR]) + + +# WKB Writing prototypes. +class WKBWriteFunc(GEOSFuncFactory): + argtypes = [WKB_WRITE_PTR, GEOM_PTR, POINTER(c_size_t)] + restype = c_uchar_p + errcheck = staticmethod(check_sized_string) + + +wkb_writer_write = WKBWriteFunc("GEOSWKBWriter_write") +wkb_writer_write_hex = WKBWriteFunc("GEOSWKBWriter_writeHEX") + + +# WKBWriter property getter/setter prototypes. +class WKBWriterGet(GEOSFuncFactory): + argtypes = [WKB_WRITE_PTR] + restype = c_int + + +class WKBWriterSet(GEOSFuncFactory): + argtypes = [WKB_WRITE_PTR, c_int] + + +wkb_writer_get_byteorder = WKBWriterGet("GEOSWKBWriter_getByteOrder") +wkb_writer_set_byteorder = WKBWriterSet("GEOSWKBWriter_setByteOrder") +wkb_writer_get_outdim = WKBWriterGet("GEOSWKBWriter_getOutputDimension") +wkb_writer_set_outdim = WKBWriterSet("GEOSWKBWriter_setOutputDimension") +wkb_writer_get_include_srid = WKBWriterGet( + "GEOSWKBWriter_getIncludeSRID", restype=c_byte +) +wkb_writer_set_include_srid = WKBWriterSet( + "GEOSWKBWriter_setIncludeSRID", argtypes=[WKB_WRITE_PTR, c_byte] +) + + +# ### Base I/O Class ### +class IOBase(GEOSBase): + "Base class for GEOS I/O objects." + + def __init__(self): + # Getting the pointer with the constructor. + self.ptr = self._constructor() + # Loading the real destructor function at this point as doing it in + # __del__ is too late (import error). + self.destructor.func + + +# ### Base WKB/WKT Reading and Writing objects ### + + +# Non-public WKB/WKT reader classes for internal use because +# their `read` methods return _pointers_ instead of GEOSGeometry +# objects. +class _WKTReader(IOBase): + _constructor = wkt_reader_create + ptr_type = WKT_READ_PTR + destructor = wkt_reader_destroy + + def read(self, wkt): + if not isinstance(wkt, (bytes, str)): + raise TypeError + return wkt_reader_read(self.ptr, force_bytes(wkt)) + + +class _WKBReader(IOBase): + _constructor = wkb_reader_create + ptr_type = WKB_READ_PTR + destructor = wkb_reader_destroy + + def read(self, wkb): + "Return a _pointer_ to C GEOS Geometry object from the given WKB." + if isinstance(wkb, memoryview): + wkb_s = bytes(wkb) + return wkb_reader_read(self.ptr, wkb_s, len(wkb_s)) + elif isinstance(wkb, bytes): + return wkb_reader_read_hex(self.ptr, wkb, len(wkb)) + elif isinstance(wkb, str): + wkb_s = wkb.encode() + return wkb_reader_read_hex(self.ptr, wkb_s, len(wkb_s)) + else: + raise TypeError + + +def default_trim_value(): + """ + GEOS changed the default value in 3.12.0. Can be replaced by True when + 3.12.0 becomes the minimum supported version. + """ + return geos_version_tuple() >= (3, 12) + + +DEFAULT_TRIM_VALUE = SimpleLazyObject(default_trim_value) + + +# ### WKB/WKT Writer Classes ### +class WKTWriter(IOBase): + _constructor = wkt_writer_create + ptr_type = WKT_WRITE_PTR + destructor = wkt_writer_destroy + _precision = None + + def __init__(self, dim=2, trim=False, precision=None): + super().__init__() + self._trim = DEFAULT_TRIM_VALUE + self.trim = trim + if precision is not None: + self.precision = precision + self.outdim = dim + + def write(self, geom): + "Return the WKT representation of the given geometry." + return wkt_writer_write(self.ptr, geom.ptr) + + @property + def outdim(self): + return wkt_writer_get_outdim(self.ptr) + + @outdim.setter + def outdim(self, new_dim): + if new_dim not in (2, 3): + raise ValueError("WKT output dimension must be 2 or 3") + wkt_writer_set_outdim(self.ptr, new_dim) + + @property + def trim(self): + return self._trim + + @trim.setter + def trim(self, flag): + if bool(flag) != self._trim: + self._trim = bool(flag) + wkt_writer_set_trim(self.ptr, self._trim) + + @property + def precision(self): + return self._precision + + @precision.setter + def precision(self, precision): + if (not isinstance(precision, int) or precision < 0) and precision is not None: + raise AttributeError( + "WKT output rounding precision must be non-negative integer or None." + ) + if precision != self._precision: + self._precision = precision + wkt_writer_set_precision(self.ptr, -1 if precision is None else precision) + + +class WKBWriter(IOBase): + _constructor = wkb_writer_create + ptr_type = WKB_WRITE_PTR + destructor = wkb_writer_destroy + geos_version = geos_version_tuple() + + def __init__(self, dim=2): + super().__init__() + self.outdim = dim + + def _handle_empty_point(self, geom): + from django.contrib.gis.geos import Point + + if isinstance(geom, Point) and geom.empty: + if self.srid: + # PostGIS uses POINT(NaN NaN) for WKB representation of empty + # points. Use it for EWKB as it's a PostGIS specific format. + # https://trac.osgeo.org/postgis/ticket/3181 + geom = Point(float("NaN"), float("NaN"), srid=geom.srid) + else: + raise ValueError("Empty point is not representable in WKB.") + return geom + + def write(self, geom): + "Return the WKB representation of the given geometry." + geom = self._handle_empty_point(geom) + wkb = wkb_writer_write(self.ptr, geom.ptr, byref(c_size_t())) + return memoryview(wkb) + + def write_hex(self, geom): + "Return the HEXEWKB representation of the given geometry." + geom = self._handle_empty_point(geom) + wkb = wkb_writer_write_hex(self.ptr, geom.ptr, byref(c_size_t())) + return wkb + + # ### WKBWriter Properties ### + + # Property for getting/setting the byteorder. + def _get_byteorder(self): + return wkb_writer_get_byteorder(self.ptr) + + def _set_byteorder(self, order): + if order not in (0, 1): + raise ValueError( + "Byte order parameter must be 0 (Big Endian) or 1 (Little Endian)." + ) + wkb_writer_set_byteorder(self.ptr, order) + + byteorder = property(_get_byteorder, _set_byteorder) + + # Property for getting/setting the output dimension. + @property + def outdim(self): + return wkb_writer_get_outdim(self.ptr) + + @outdim.setter + def outdim(self, new_dim): + if new_dim not in (2, 3): + raise ValueError("WKB output dimension must be 2 or 3") + wkb_writer_set_outdim(self.ptr, new_dim) + + # Property for getting/setting the include srid flag. + @property + def srid(self): + return bool(wkb_writer_get_include_srid(self.ptr)) + + @srid.setter + def srid(self, include): + wkb_writer_set_include_srid(self.ptr, bool(include)) + + +# `ThreadLocalIO` object holds instances of the WKT and WKB reader/writer +# objects that are local to the thread. The `GEOSGeometry` internals +# access these instances by calling the module-level functions, defined +# below. +class ThreadLocalIO(threading.local): + wkt_r = None + wkt_w = None + wkb_r = None + wkb_w = None + ewkb_w = None + + +thread_context = ThreadLocalIO() + + +# These module-level routines return the I/O object that is local to the +# thread. If the I/O object does not exist yet it will be initialized. +def wkt_r(): + thread_context.wkt_r = thread_context.wkt_r or _WKTReader() + return thread_context.wkt_r + + +def wkt_w(dim=2, trim=False, precision=None): + if not thread_context.wkt_w: + thread_context.wkt_w = WKTWriter(dim=dim, trim=trim, precision=precision) + else: + thread_context.wkt_w.outdim = dim + thread_context.wkt_w.trim = trim + thread_context.wkt_w.precision = precision + return thread_context.wkt_w + + +def wkb_r(): + thread_context.wkb_r = thread_context.wkb_r or _WKBReader() + return thread_context.wkb_r + + +def wkb_w(dim=2): + if not thread_context.wkb_w: + thread_context.wkb_w = WKBWriter(dim=dim) + else: + thread_context.wkb_w.outdim = dim + return thread_context.wkb_w + + +def ewkb_w(dim=2): + if not thread_context.ewkb_w: + thread_context.ewkb_w = WKBWriter(dim=dim) + thread_context.ewkb_w.srid = True + else: + thread_context.ewkb_w.outdim = dim + return thread_context.ewkb_w diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/misc.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/misc.py new file mode 100644 index 0000000..fccd0ec --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/misc.py @@ -0,0 +1,34 @@ +""" + This module is for the miscellaneous GEOS routines, particularly the + ones that return the area, distance, and length. +""" +from ctypes import POINTER, c_double, c_int + +from django.contrib.gis.geos.libgeos import GEOM_PTR, GEOSFuncFactory +from django.contrib.gis.geos.prototypes.errcheck import check_dbl, check_string +from django.contrib.gis.geos.prototypes.geom import geos_char_p + +__all__ = ["geos_area", "geos_distance", "geos_length", "geos_isvalidreason"] + + +class DblFromGeom(GEOSFuncFactory): + """ + Argument is a Geometry, return type is double that is passed + in by reference as the last argument. + """ + + restype = c_int # Status code returned + errcheck = staticmethod(check_dbl) + + +# ### ctypes prototypes ### + +# Area, distance, and length prototypes. +geos_area = DblFromGeom("GEOSArea", argtypes=[GEOM_PTR, POINTER(c_double)]) +geos_distance = DblFromGeom( + "GEOSDistance", argtypes=[GEOM_PTR, GEOM_PTR, POINTER(c_double)] +) +geos_length = DblFromGeom("GEOSLength", argtypes=[GEOM_PTR, POINTER(c_double)]) +geos_isvalidreason = GEOSFuncFactory( + "GEOSisValidReason", restype=geos_char_p, errcheck=check_string, argtypes=[GEOM_PTR] +) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/predicates.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/predicates.py new file mode 100644 index 0000000..32b7901 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/predicates.py @@ -0,0 +1,48 @@ +""" + This module houses the GEOS ctypes prototype functions for the + unary and binary predicate operations on geometries. +""" +from ctypes import c_byte, c_char_p, c_double + +from django.contrib.gis.geos.libgeos import GEOM_PTR, GEOSFuncFactory +from django.contrib.gis.geos.prototypes.errcheck import check_predicate + + +# ## Binary & unary predicate factories ## +class UnaryPredicate(GEOSFuncFactory): + "For GEOS unary predicate functions." + argtypes = [GEOM_PTR] + restype = c_byte + errcheck = staticmethod(check_predicate) + + +class BinaryPredicate(UnaryPredicate): + "For GEOS binary predicate functions." + argtypes = [GEOM_PTR, GEOM_PTR] + + +# ## Unary Predicates ## +geos_hasz = UnaryPredicate("GEOSHasZ") +geos_isclosed = UnaryPredicate("GEOSisClosed") +geos_isempty = UnaryPredicate("GEOSisEmpty") +geos_isring = UnaryPredicate("GEOSisRing") +geos_issimple = UnaryPredicate("GEOSisSimple") +geos_isvalid = UnaryPredicate("GEOSisValid") + +# ## Binary Predicates ## +geos_contains = BinaryPredicate("GEOSContains") +geos_covers = BinaryPredicate("GEOSCovers") +geos_crosses = BinaryPredicate("GEOSCrosses") +geos_disjoint = BinaryPredicate("GEOSDisjoint") +geos_equals = BinaryPredicate("GEOSEquals") +geos_equalsexact = BinaryPredicate( + "GEOSEqualsExact", argtypes=[GEOM_PTR, GEOM_PTR, c_double] +) +geos_equalsidentical = BinaryPredicate("GEOSEqualsIdentical") +geos_intersects = BinaryPredicate("GEOSIntersects") +geos_overlaps = BinaryPredicate("GEOSOverlaps") +geos_relatepattern = BinaryPredicate( + "GEOSRelatePattern", argtypes=[GEOM_PTR, GEOM_PTR, c_char_p] +) +geos_touches = BinaryPredicate("GEOSTouches") +geos_within = BinaryPredicate("GEOSWithin") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/prepared.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/prepared.py new file mode 100644 index 0000000..4fdfab3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/prepared.py @@ -0,0 +1,26 @@ +from ctypes import c_byte + +from django.contrib.gis.geos.libgeos import GEOM_PTR, PREPGEOM_PTR, GEOSFuncFactory +from django.contrib.gis.geos.prototypes.errcheck import check_predicate + +# Prepared geometry constructor and destructors. +geos_prepare = GEOSFuncFactory("GEOSPrepare", argtypes=[GEOM_PTR], restype=PREPGEOM_PTR) +prepared_destroy = GEOSFuncFactory("GEOSPreparedGeom_destroy", argtypes=[PREPGEOM_PTR]) + + +# Prepared geometry binary predicate support. +class PreparedPredicate(GEOSFuncFactory): + argtypes = [PREPGEOM_PTR, GEOM_PTR] + restype = c_byte + errcheck = staticmethod(check_predicate) + + +prepared_contains = PreparedPredicate("GEOSPreparedContains") +prepared_contains_properly = PreparedPredicate("GEOSPreparedContainsProperly") +prepared_covers = PreparedPredicate("GEOSPreparedCovers") +prepared_crosses = PreparedPredicate("GEOSPreparedCrosses") +prepared_disjoint = PreparedPredicate("GEOSPreparedDisjoint") +prepared_intersects = PreparedPredicate("GEOSPreparedIntersects") +prepared_overlaps = PreparedPredicate("GEOSPreparedOverlaps") +prepared_touches = PreparedPredicate("GEOSPreparedTouches") +prepared_within = PreparedPredicate("GEOSPreparedWithin") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/threadsafe.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/threadsafe.py new file mode 100644 index 0000000..d4f7ffb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/threadsafe.py @@ -0,0 +1,77 @@ +import threading + +from django.contrib.gis.geos.base import GEOSBase +from django.contrib.gis.geos.libgeos import CONTEXT_PTR, error_h, lgeos, notice_h + + +class GEOSContextHandle(GEOSBase): + """Represent a GEOS context handle.""" + + ptr_type = CONTEXT_PTR + destructor = lgeos.finishGEOS_r + + def __init__(self): + # Initializing the context handler for this thread with + # the notice and error handler. + self.ptr = lgeos.initGEOS_r(notice_h, error_h) + + +# Defining a thread-local object and creating an instance +# to hold a reference to GEOSContextHandle for this thread. +class GEOSContext(threading.local): + handle = None + + +thread_context = GEOSContext() + + +class GEOSFunc: + """ + Serve as a wrapper for GEOS C Functions. Use thread-safe function + variants when available. + """ + + def __init__(self, func_name): + # GEOS thread-safe function signatures end with '_r' and take an + # additional context handle parameter. + self.cfunc = getattr(lgeos, func_name + "_r") + # Create a reference to thread_context so it's not garbage-collected + # before an attempt to call this object. + self.thread_context = thread_context + + def __call__(self, *args): + # Create a context handle if one doesn't exist for this thread. + self.thread_context.handle = self.thread_context.handle or GEOSContextHandle() + # Call the threaded GEOS routine with the pointer of the context handle + # as the first argument. + return self.cfunc(self.thread_context.handle.ptr, *args) + + def __str__(self): + return self.cfunc.__name__ + + # argtypes property + def _get_argtypes(self): + return self.cfunc.argtypes + + def _set_argtypes(self, argtypes): + self.cfunc.argtypes = [CONTEXT_PTR, *argtypes] + + argtypes = property(_get_argtypes, _set_argtypes) + + # restype property + def _get_restype(self): + return self.cfunc.restype + + def _set_restype(self, restype): + self.cfunc.restype = restype + + restype = property(_get_restype, _set_restype) + + # errcheck property + def _get_errcheck(self): + return self.cfunc.errcheck + + def _set_errcheck(self, errcheck): + self.cfunc.errcheck = errcheck + + errcheck = property(_get_errcheck, _set_errcheck) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/topology.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/topology.py new file mode 100644 index 0000000..e61eae9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/geos/prototypes/topology.py @@ -0,0 +1,72 @@ +""" + This module houses the GEOS ctypes prototype functions for the + topological operations on geometries. +""" +from ctypes import c_double, c_int + +from django.contrib.gis.geos.libgeos import GEOM_PTR, GEOSFuncFactory +from django.contrib.gis.geos.prototypes.errcheck import ( + check_geom, + check_minus_one, + check_string, +) +from django.contrib.gis.geos.prototypes.geom import geos_char_p + + +class Topology(GEOSFuncFactory): + "For GEOS unary topology functions." + argtypes = [GEOM_PTR] + restype = GEOM_PTR + errcheck = staticmethod(check_geom) + + +# Topology Routines +geos_boundary = Topology("GEOSBoundary") +geos_buffer = Topology("GEOSBuffer", argtypes=[GEOM_PTR, c_double, c_int]) +geos_bufferwithstyle = Topology( + "GEOSBufferWithStyle", argtypes=[GEOM_PTR, c_double, c_int, c_int, c_int, c_double] +) +geos_centroid = Topology("GEOSGetCentroid") +geos_convexhull = Topology("GEOSConvexHull") +geos_difference = Topology("GEOSDifference", argtypes=[GEOM_PTR, GEOM_PTR]) +geos_envelope = Topology("GEOSEnvelope") +geos_intersection = Topology("GEOSIntersection", argtypes=[GEOM_PTR, GEOM_PTR]) +geos_linemerge = Topology("GEOSLineMerge") +geos_pointonsurface = Topology("GEOSPointOnSurface") +geos_preservesimplify = Topology( + "GEOSTopologyPreserveSimplify", argtypes=[GEOM_PTR, c_double] +) +geos_simplify = Topology("GEOSSimplify", argtypes=[GEOM_PTR, c_double]) +geos_symdifference = Topology("GEOSSymDifference", argtypes=[GEOM_PTR, GEOM_PTR]) +geos_union = Topology("GEOSUnion", argtypes=[GEOM_PTR, GEOM_PTR]) + +geos_unary_union = GEOSFuncFactory( + "GEOSUnaryUnion", argtypes=[GEOM_PTR], restype=GEOM_PTR +) + +# GEOSRelate returns a string, not a geometry. +geos_relate = GEOSFuncFactory( + "GEOSRelate", + argtypes=[GEOM_PTR, GEOM_PTR], + restype=geos_char_p, + errcheck=check_string, +) + +# Linear referencing routines +geos_project = GEOSFuncFactory( + "GEOSProject", + argtypes=[GEOM_PTR, GEOM_PTR], + restype=c_double, + errcheck=check_minus_one, +) +geos_interpolate = Topology("GEOSInterpolate", argtypes=[GEOM_PTR, c_double]) + +geos_project_normalized = GEOSFuncFactory( + "GEOSProjectNormalized", + argtypes=[GEOM_PTR, GEOM_PTR], + restype=c_double, + errcheck=check_minus_one, +) +geos_interpolate_normalized = Topology( + "GEOSInterpolateNormalized", argtypes=[GEOM_PTR, c_double] +) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/af/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/af/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2a67e8f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/af/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/af/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/af/LC_MESSAGES/django.po new file mode 100644 index 0000000..83320bb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/af/LC_MESSAGES/django.po @@ -0,0 +1,82 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# F Wolff , 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: F Wolff , 2023\n" +"Language-Team: Afrikaans (http://app.transifex.com/django/django/language/" +"af/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: af\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Die basis-GIS-veld" + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "" + +msgid "Line string" +msgstr "" + +msgid "Polygon" +msgstr "" + +msgid "Multi-point" +msgstr "" + +msgid "Multi-line string" +msgstr "" + +msgid "Multi polygon" +msgstr "" + +msgid "Geometry collection" +msgstr "" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "" + +msgid "Invalid geometry value." +msgstr "" + +msgid "Invalid geometry type." +msgstr "" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" + +msgid "Delete all Features" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "" + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ar/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ar/LC_MESSAGES/django.mo new file mode 100644 index 0000000..083951f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ar/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ar/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ar/LC_MESSAGES/django.po new file mode 100644 index 0000000..092b5df --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ar/LC_MESSAGES/django.po @@ -0,0 +1,89 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bashar Al-Abdulhadi, 2015-2016 +# Bashar Al-Abdulhadi, 2014 +# Eyad Toma , 2013 +# Jannis Leidel , 2011 +# Muaaz Alsaied, 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-04-02 11:32+0000\n" +"Last-Translator: Muaaz Alsaied\n" +"Language-Team: Arabic (http://www.transifex.com/django/django/language/ar/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +msgid "GIS" +msgstr "نظم المعلومات الجغرافية GIS" + +msgid "The base GIS field." +msgstr "حقل نظم المعلومات الجغرافية الرئيسي" + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "قاعدة حقل Geometry -- مُرتبط بنوع مواصفات OpenGIS الهندسية." + +msgid "Point" +msgstr "نقطة إحداثية" + +msgid "Line string" +msgstr "سطر تسلسل أحرف" + +msgid "Polygon" +msgstr "مُضلّع إحداثي" + +msgid "Multi-point" +msgstr "نقاط إحداثية" + +msgid "Multi-line string" +msgstr "تسلسل أحرف متعدد الأسطر" + +msgid "Multi polygon" +msgstr "مجموعة مُضلعات إحداثية" + +msgid "Geometry collection" +msgstr "مجموعة إحداثية" + +msgid "Extent Aggregate Field" +msgstr "حقل مجموع التحصيل" + +msgid "Raster Field" +msgstr "حقل خطوط المسح التسامتي" + +msgid "No geometry value provided." +msgstr "لم تُدخل أي أحداثيات." + +msgid "Invalid geometry value." +msgstr "الإحداثيات غير صحيحة." + +msgid "Invalid geometry type." +msgstr "نوع الإحداثيات غير صحيح." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "حدث خطأ أثناء تحويل geometry إلى حقل SRID." + +msgid "Delete all Features" +msgstr "حذف جميع المميزات" + +msgid "WKT debugging window:" +msgstr "نافذة تدقيق WKT:" + +msgid "Debugging window (serialized value)" +msgstr "نافذة التدقيق (قيمة تسلسلية)" + +msgid "No feeds are registered." +msgstr "لا موجز مسجّل" + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Slug %r غير مسجّل." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ar_DZ/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ar_DZ/LC_MESSAGES/django.mo new file mode 100644 index 0000000..55a61ec Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ar_DZ/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ar_DZ/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ar_DZ/LC_MESSAGES/django.po new file mode 100644 index 0000000..c1d13f8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ar_DZ/LC_MESSAGES/django.po @@ -0,0 +1,88 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Riterix , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-12-14 22:46+0000\n" +"Last-Translator: Riterix \n" +"Language-Team: Arabic (Algeria) (http://www.transifex.com/django/django/" +"language/ar_DZ/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar_DZ\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +msgid "GIS" +msgstr "نظم المعلومات الجغرافية GIS" + +msgid "The base GIS field." +msgstr "حقل نظم المعلومات الجغرافية الرئيسي" + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"قاعدة الحقل الهندسي ترتكز لمواصفات نوع OpenGIS (نظم المعلومات الجغرافية " +"المفتوحة) الهندسية." + +msgid "Point" +msgstr "نقطة إحداثية" + +msgid "Line string" +msgstr "سطر تسلسل أحرف" + +msgid "Polygon" +msgstr "مُضلّع إحداثي" + +msgid "Multi-point" +msgstr "نقاط إحداثية" + +msgid "Multi-line string" +msgstr "تسلسل أحرف متعدد الأسطر" + +msgid "Multi polygon" +msgstr "مجموعة مُضلعات إحداثية" + +msgid "Geometry collection" +msgstr "مجموعة إحداثية" + +msgid "Extent Aggregate Field" +msgstr "حقل مجموع التحصيل\"" + +msgid "Raster Field" +msgstr "حقل خطوط المسح التسامتي" + +msgid "No geometry value provided." +msgstr "لم تُدخل أي أحداثيات." + +msgid "Invalid geometry value." +msgstr "الإحداثيات غير صحيحة." + +msgid "Invalid geometry type." +msgstr "نوع الإحداثيات غير صحيح." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "حدث خطأ أثناء تحويل geometry إلى حقل SRID." + +msgid "Delete all Features" +msgstr "حذف جميع المميزات" + +msgid "WKT debugging window:" +msgstr "نافذة تدقيق WKT:" + +msgid "Debugging window (serialized value)" +msgstr "نافذة التدقيق (قيمة تسلسلية)" + +msgid "No feeds are registered." +msgstr "لا موجز مسجّل" + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Slug %r غير مسجّل" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ast/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ast/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4a347ba Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ast/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ast/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ast/LC_MESSAGES/django.po new file mode 100644 index 0000000..cf0ea5b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ast/LC_MESSAGES/django.po @@ -0,0 +1,85 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ḷḷumex03 , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-23 19:51+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Asturian (http://www.transifex.com/django/django/language/" +"ast/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ast\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "Puntu" + +msgid "Line string" +msgstr "" + +msgid "Polygon" +msgstr "Polígonu" + +msgid "Multi-point" +msgstr "" + +msgid "Multi-line string" +msgstr "" + +msgid "Multi polygon" +msgstr "" + +msgid "Geometry collection" +msgstr "" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "Nun s'apurrió'l valor de xeometría." + +msgid "Invalid geometry value." +msgstr "Valor de xeometría inválidu." + +msgid "Invalid geometry type." +msgstr "Triba de xeometría inválida." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "Nun hai feeds rexistraos" + +#, python-format +msgid "Slug %r isn't registered." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/az/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/az/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1f2b3a9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/az/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/az/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/az/LC_MESSAGES/django.po new file mode 100644 index 0000000..83f1eb2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/az/LC_MESSAGES/django.po @@ -0,0 +1,88 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ali Ismayilov , 2011 +# Emin Mastizada , 2018,2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-01-12 07:23+0000\n" +"Last-Translator: Emin Mastizada \n" +"Language-Team: Azerbaijani (http://www.transifex.com/django/django/language/" +"az/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: az\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Təməl GIS sahəsi (field)." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Təməl Həndəsə sahəsi — OpenGIS Specification Geometry növünə işarətlənir." + +msgid "Point" +msgstr "Nöqtə" + +msgid "Line string" +msgstr "Xətt" + +msgid "Polygon" +msgstr "Poliqon" + +msgid "Multi-point" +msgstr "Nöqtələr" + +msgid "Multi-line string" +msgstr "Xətlər" + +msgid "Multi polygon" +msgstr "Poliqonlar" + +msgid "Geometry collection" +msgstr "Fiqurlar çoxluğu" + +msgid "Extent Aggregate Field" +msgstr "Aqreqat Sahəsini Genişləndir" + +msgid "Raster Field" +msgstr "Rastr Sahəsi" + +msgid "No geometry value provided." +msgstr "Həndəsi qiyməti verilməyib." + +msgid "Invalid geometry value." +msgstr "Həndəsi qiyməti düzgün deyil." + +msgid "Invalid geometry type." +msgstr "Həndəsi tipi düzgün deyil." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Fiquru vərəqənin fiqur sahəsinin SRID qiymətinə çevirərkən xəta baş verdi." + +msgid "Delete all Features" +msgstr "Bütün Xüsusiyyətləri sil" + +msgid "WKT debugging window:" +msgstr "WKT sazlama pəncərəsi:" + +msgid "Debugging window (serialized value)" +msgstr "Sazlama pəncərəsi (seriallaşdırılmış dəyər)" + +msgid "No feeds are registered." +msgstr "Qeyd edilmiş axın yoxdur." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "%r slug-ı qeyd edilməyib." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/be/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/be/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4773ef6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/be/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/be/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/be/LC_MESSAGES/django.po new file mode 100644 index 0000000..2886c34 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/be/LC_MESSAGES/django.po @@ -0,0 +1,87 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Viktar Palstsiuk , 2014-2015 +# znotdead , 2016,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: znotdead , 2016,2019\n" +"Language-Team: Belarusian (http://app.transifex.com/django/django/language/" +"be/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: be\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || " +"(n%100>=11 && n%100<=14)? 2 : 3);\n" + +msgid "GIS" +msgstr "ГІС" + +msgid "The base GIS field." +msgstr "Галоўнае поле ГІС." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Галоўнае геаметрычнае поле — адлюстроўвае геамэтрычныя віды паводле " +"спэцыфікацыі «OpenGIS»." + +msgid "Point" +msgstr "Пункт" + +msgid "Line string" +msgstr "Ломаная" + +msgid "Polygon" +msgstr "Шматкутнік" + +msgid "Multi-point" +msgstr "Набор пунктаў" + +msgid "Multi-line string" +msgstr "Набор ломаных" + +msgid "Multi polygon" +msgstr "Набор шматкутнікаў" + +msgid "Geometry collection" +msgstr "Набор ґеамэтрычных аб’ектаў" + +msgid "Extent Aggregate Field" +msgstr "Поле аб'яднанай плошчы" + +msgid "Raster Field" +msgstr "Растравае поле" + +msgid "No geometry value provided." +msgstr "Не пазначылі значэньне ґеамэтрыі." + +msgid "Invalid geometry value." +msgstr "Хібнае значэньне ґеамэтрыі." + +msgid "Invalid geometry type." +msgstr "Хібны від ґеамэтрыі." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "Не ўдалося ператварыць ґеамэтрыю ў SRID." + +msgid "Delete all Features" +msgstr "Выдаліць усе аб’екты" + +msgid "Debugging window (serialized value)" +msgstr "Акно адладкі (сэрыялізаванае значэньне)" + +msgid "No feeds are registered." +msgstr "Няма запісаных стужак." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Біркі %r няма ў запісаных." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/bg/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/bg/LC_MESSAGES/django.mo new file mode 100644 index 0000000..fded0fd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/bg/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/bg/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/bg/LC_MESSAGES/django.po new file mode 100644 index 0000000..4775661 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/bg/LC_MESSAGES/django.po @@ -0,0 +1,87 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Georgi Kostadinov , 2012 +# Todor Lubenov , 2016,2020 +# Todor Lubenov , 2011,2015,2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Todor Lubenov , 2011,2015,2021\n" +"Language-Team: Bulgarian (http://app.transifex.com/django/django/language/" +"bg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Базово ГИС поле." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Базово Геометричнно поле — карти от OpenGIS Specification Geometry тип." + +msgid "Point" +msgstr "Точка" + +msgid "Line string" +msgstr "Линеен елемент" + +msgid "Polygon" +msgstr "Полигон" + +msgid "Multi-point" +msgstr "Комплексна-точка" + +msgid "Multi-line string" +msgstr "Комплексен-линеен елемент" + +msgid "Multi polygon" +msgstr "Комплексен полигон" + +msgid "Geometry collection" +msgstr "Геометрична колекция" + +msgid "Extent Aggregate Field" +msgstr "Разшири Полето за обединяване" + +msgid "Raster Field" +msgstr "Растерно Поле" + +msgid "No geometry value provided." +msgstr "Няма предоставена геометрична стойност." + +msgid "Invalid geometry value." +msgstr "Невалидна геометрична стойност." + +msgid "Invalid geometry type." +msgstr "Невалиден геометричен тип." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Възникна грешка при трансформиране на геометрията на SRID от полето " +"геометрия." + +msgid "Delete all Features" +msgstr "Изтрий всички обекти" + +msgid "Debugging window (serialized value)" +msgstr "Debugging прозорец (сериализирана стойност)" + +msgid "No feeds are registered." +msgstr "Няма регистрирани фийда." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Slug %r не е регистриран." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/bn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/bn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1168ac4 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/bn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/bn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/bn/LC_MESSAGES/django.po new file mode 100644 index 0000000..037e7d9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/bn/LC_MESSAGES/django.po @@ -0,0 +1,86 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Tahmid Rafi , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Bengali (http://www.transifex.com/django/django/language/" +"bn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "জিআইএস" + +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "বিন্দু" + +msgid "Line string" +msgstr "" + +msgid "Polygon" +msgstr "বহুভুজ" + +msgid "Multi-point" +msgstr "" + +msgid "Multi-line string" +msgstr "" + +msgid "Multi polygon" +msgstr "" + +msgid "Geometry collection" +msgstr "" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "কোন জ্যামিতিক মান দেয়া হয়নি।" + +msgid "Invalid geometry value." +msgstr "জ্যামিতিক মানটি বৈধ নয়।" + +msgid "Invalid geometry type." +msgstr "জ্যামিতিক নমুনাটি বৈধ নয়।" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "" + +#, python-format +msgid "Slug %r isn't registered." +msgstr "%r স্লাগটি রেজিস্টারকৃত নয়।" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/br/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/br/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0829bd0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/br/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/br/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/br/LC_MESSAGES/django.po new file mode 100644 index 0000000..d29da14 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/br/LC_MESSAGES/django.po @@ -0,0 +1,91 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Fulup , 2012 +# Irriep Nala Novram , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2019-03-12 14:10+0000\n" +"Last-Translator: Irriep Nala Novram \n" +"Language-Team: Breton (http://www.transifex.com/django/django/language/br/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: br\n" +"Plural-Forms: nplurals=5; plural=((n%10 == 1) && (n%100 != 11) && (n%100 !" +"=71) && (n%100 !=91) ? 0 :(n%10 == 2) && (n%100 != 12) && (n%100 !=72) && (n" +"%100 !=92) ? 1 :(n%10 ==3 || n%10==4 || n%10==9) && (n%100 < 10 || n% 100 > " +"19) && (n%100 < 70 || n%100 > 79) && (n%100 < 90 || n%100 > 99) ? 2 :(n != 0 " +"&& n % 1000000 == 0) ? 3 : 4);\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "Pik" + +msgid "Line string" +msgstr "Chadenn segmant" + +msgid "Polygon" +msgstr "Poligon" + +msgid "Multi-point" +msgstr "Liespik" + +msgid "Multi-line string" +msgstr "Lies chadenn segmant" + +msgid "Multi polygon" +msgstr "Liespoligon" + +msgid "Geometry collection" +msgstr "Dastumad mentoniezh" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "Talvoudegezh mentoniezh roet ebet." + +msgid "Invalid geometry value." +msgstr "Talvoudegezh mentoniezh direizh." + +msgid "Invalid geometry type." +msgstr "Doare mentoniezh direizh." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Ur fazi a zo c'hoarvezet da vare treuzfurmadur an objed mentoniezhel e-barzh " +"ar vaezienn stumm mentoniezhel SRID." + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "" + +#, python-format +msgid "Slug %r isn't registered." +msgstr "Neket enrollet ar \"slug\" %r." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/bs/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/bs/LC_MESSAGES/django.mo new file mode 100644 index 0000000..df48c3d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/bs/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/bs/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/bs/LC_MESSAGES/django.po new file mode 100644 index 0000000..e6a8de2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/bs/LC_MESSAGES/django.po @@ -0,0 +1,88 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Bosnian (http://www.transifex.com/django/django/language/" +"bs/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bs\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "Tačka" + +msgid "Line string" +msgstr "Linijska nit" + +msgid "Polygon" +msgstr "Poligon" + +msgid "Multi-point" +msgstr "Multi-point" + +msgid "Multi-line string" +msgstr "Višelinijska nit" + +msgid "Multi polygon" +msgstr "Multi poligon" + +msgid "Geometry collection" +msgstr "Geometrijska kolekcija" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "Niste zadali parametre za geometriju." + +msgid "Invalid geometry value." +msgstr "Neispravan parametar za geometriju." + +msgid "Invalid geometry type." +msgstr "Nepostojeći tip geometrije." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Došlo je do greške tokom pretvaranje geometrije u SRID geometrijskom polja " +"obrazca." + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "" + +#, python-format +msgid "Slug %r isn't registered." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ca/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ca/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5eca653 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ca/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ca/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ca/LC_MESSAGES/django.po new file mode 100644 index 0000000..8406866 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ca/LC_MESSAGES/django.po @@ -0,0 +1,91 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Antoni Aloy , 2012,2015 +# Carles Barrobés , 2012,2014 +# duub qnnp, 2015 +# Jannis Leidel , 2011 +# Manel Clos , 2020 +# Roger Pons , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Manel Clos , 2020\n" +"Language-Team: Catalan (http://app.transifex.com/django/django/language/" +"ca/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ca\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "El camp base de GIS" + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"El camp base Geometry -- correspon al tipus Geometry de l'especificació " +"OpenGIS." + +msgid "Point" +msgstr "Punt" + +msgid "Line string" +msgstr "Cadena de línies" + +msgid "Polygon" +msgstr "Polígon" + +msgid "Multi-point" +msgstr "Multi-punt" + +msgid "Multi-line string" +msgstr "Cadena de multi-línies" + +msgid "Multi polygon" +msgstr "Multi polígon" + +msgid "Geometry collection" +msgstr "Col·leció de geometria" + +msgid "Extent Aggregate Field" +msgstr "Estén camp agregat" + +msgid "Raster Field" +msgstr "Camp de mapa de bits" + +msgid "No geometry value provided." +msgstr "No s'ha indicat cap valor de geometria." + +msgid "Invalid geometry value." +msgstr "Valor de geometria invàlid." + +msgid "Invalid geometry type." +msgstr "Tipus de geometria invàlid." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"S'ha produït un error en transformar la geometria al SRID del camp de " +"geometria del formulari." + +msgid "Delete all Features" +msgstr "Elimina totes les característiques" + +msgid "Debugging window (serialized value)" +msgstr "Finestra de depuració (valor serialitzat)" + +msgid "No feeds are registered." +msgstr "No s'han registrat canal de contingut" + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "El 'slug' %r no està registrat" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ckb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ckb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..912945f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ckb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ckb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ckb/LC_MESSAGES/django.po new file mode 100644 index 0000000..2d7b7e3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ckb/LC_MESSAGES/django.po @@ -0,0 +1,86 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# kosar tofiq , 2020 +# Swara , 2022 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Swara , 2022\n" +"Language-Team: Central Kurdish (http://app.transifex.com/django/django/" +"language/ckb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ckb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "خانەی بنەڕەتی GIS." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"خانەی بنەڕەتی ئەندازەیی - نەخشەکان بۆ جۆری تایبەتمەندیە ئەندازەییەکانی " +"OpenGIS." + +msgid "Point" +msgstr "خاڵ" + +msgid "Line string" +msgstr "هێڵی ڕیزبه‌ند" + +msgid "Polygon" +msgstr "فرەگۆشە" + +msgid "Multi-point" +msgstr "فرەخاڵ" + +msgid "Multi-line string" +msgstr "ڕیزبەندی فرەهێڵ" + +msgid "Multi polygon" +msgstr "فرەگۆشە" + +msgid "Geometry collection" +msgstr "کۆکراوەی ئەندازەیی" + +msgid "Extent Aggregate Field" +msgstr "خانەی کۆکراوەی فراوان" + +msgid "Raster Field" +msgstr "خانەی ڕاستەر" + +msgid "No geometry value provided." +msgstr "هیچ بەهایەکی ئەندازەیی دابیننەکراوە." + +msgid "Invalid geometry value." +msgstr "بەهای ئەندازەیی نادروستە." + +msgid "Invalid geometry type." +msgstr "جۆری ئەندازەیی نادروستە." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"هەڵەیەک ڕوویدا لە کاتی گۆڕینی ئەندازەییەکە بۆ SRID ی خانەی فۆڕمی ئەندازەیی." + +msgid "Delete all Features" +msgstr "سڕینەوەی هەموو تایبتمەندیەکان" + +msgid "Debugging window (serialized value)" +msgstr "پەنجەرەی هەڵەدۆزینەوە (بەهای زنجیرەیی)" + +msgid "No feeds are registered." +msgstr "هیچ پێدانێک تۆمارنەکراوە." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "سلەگی %r تۆمارنەکراوە." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/cs/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/cs/LC_MESSAGES/django.mo new file mode 100644 index 0000000..cc89d69 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/cs/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/cs/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/cs/LC_MESSAGES/django.po new file mode 100644 index 0000000..b22d732 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/cs/LC_MESSAGES/django.po @@ -0,0 +1,88 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Vláďa Macek , 2012,2014 +# Vláďa Macek , 2015,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Vláďa Macek , 2015,2019\n" +"Language-Team: Czech (http://app.transifex.com/django/django/language/cs/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cs\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n " +"<= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Základní pole GIS" + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Základní geometrické datové pole — mapuje se na typ OpenGIS Specification " +"Geometry." + +msgid "Point" +msgstr "Bod" + +msgid "Line string" +msgstr "Úsek čáry" + +msgid "Polygon" +msgstr "Polygon" + +msgid "Multi-point" +msgstr "Mnohonásobný bod" + +msgid "Multi-line string" +msgstr "Mnohonásobný úsek čáry" + +msgid "Multi polygon" +msgstr "Mnohonásobný polygon" + +msgid "Geometry collection" +msgstr "Kolekce geometrií" + +msgid "Extent Aggregate Field" +msgstr "Pole Extent Aggregate" + +msgid "Raster Field" +msgstr "Pole Raster" + +msgid "No geometry value provided." +msgstr "Hodnota geometrie nezadána." + +msgid "Invalid geometry value." +msgstr "Neplatná hodnota geometrie." + +msgid "Invalid geometry type." +msgstr "Neplatný typ geometrie." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Nastala chyba při transformaci geometrie na identifikátor SRID geometrického " +"formulářového pole." + +msgid "Delete all Features" +msgstr "Odstranit všechny vlastnosti" + +msgid "Debugging window (serialized value)" +msgstr "Ladicí okno (serializovaná hodnota)" + +msgid "No feeds are registered." +msgstr "Žádné dávky nejsou registrované." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Identifikátor %r není registrován." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/cy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/cy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..50cd7c4 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/cy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/cy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/cy/LC_MESSAGES/django.po new file mode 100644 index 0000000..a12d85f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/cy/LC_MESSAGES/django.po @@ -0,0 +1,86 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Maredudd ap Gwyndaf , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-23 19:51+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Welsh (http://www.transifex.com/django/django/language/cy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cy\n" +"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != " +"11) ? 2 : 3;\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "Pwynt" + +msgid "Line string" +msgstr "Llinyn llinell" + +msgid "Polygon" +msgstr "Polygon" + +msgid "Multi-point" +msgstr "Aml-bwynt" + +msgid "Multi-line string" +msgstr "Llinyn aml-linell" + +msgid "Multi polygon" +msgstr "Aml-bolygon" + +msgid "Geometry collection" +msgstr "Casgliad geometreg" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "Ni ddarparwyd gwerth geometreg" + +msgid "Invalid geometry value." +msgstr "Gwerth geometreg annilys" + +msgid "Invalid geometry type." +msgstr "Math geometreg annilys" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Roedd gwall tra'n trawsnewid y geometreg i SRID y maes ffurflen geometreg." + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "Does dim un llif wedi ei gofrestru." + +#, python-format +msgid "Slug %r isn't registered." +msgstr "Malwen %r heb ei gofrestru." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/da/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/da/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a489e6f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/da/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/da/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/da/LC_MESSAGES/django.po new file mode 100644 index 0000000..4e1999c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/da/LC_MESSAGES/django.po @@ -0,0 +1,86 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Erik Ramsgaard Wognsen , 2012,2014-2015,2019 +# Finn Gruwier Larsen, 2011 +# Jannis Leidel , 2011 +# Kristian Øllegaard , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Erik Ramsgaard Wognsen , " +"2012,2014-2015,2019\n" +"Language-Team: Danish (http://app.transifex.com/django/django/language/da/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: da\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Basis-GIS-feltet." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "Basisgeometrifeltet — mapper til OpenGIS Specification Geometry-typen." + +msgid "Point" +msgstr "Punkt" + +msgid "Line string" +msgstr "Linjesegment" + +msgid "Polygon" +msgstr "Polygon" + +msgid "Multi-point" +msgstr "Multipunkt" + +msgid "Multi-line string" +msgstr "Multilinjesegment" + +msgid "Multi polygon" +msgstr "Multipolygon" + +msgid "Geometry collection" +msgstr "Geometrisamling" + +msgid "Extent Aggregate Field" +msgstr "Extent Aggregate-felt" + +msgid "Raster Field" +msgstr "Raster-felt" + +msgid "No geometry value provided." +msgstr "Ingen værdi givet for geometri." + +msgid "Invalid geometry value." +msgstr "Ugyldig geometriværdi." + +msgid "Invalid geometry type." +msgstr "Ugyldig gemometritype." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Der opstod en fejl ved transformation af geometrien til formularfeltets SRID" + +msgid "Delete all Features" +msgstr "Slet alle Features" + +msgid "Debugging window (serialized value)" +msgstr "Fejlsøgninsvindue (serialiseret værdi)" + +msgid "No feeds are registered." +msgstr "Ingen feeds registrerede." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "\"Slug\" %r er ikke registreret." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/de/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/de/LC_MESSAGES/django.mo new file mode 100644 index 0000000..166c1f0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/de/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/de/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/de/LC_MESSAGES/django.po new file mode 100644 index 0000000..54b4b20 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/de/LC_MESSAGES/django.po @@ -0,0 +1,86 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# André Hagenbruch, 2012 +# Jannis Leidel , 2011-2012,2014-2015,2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Jannis Leidel , " +"2011-2012,2014-2015,2020\n" +"Language-Team: German (http://app.transifex.com/django/django/language/de/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Das Basis-GIS-Feld." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Das Basis-GIS-Feld – verwendet den Geometrie-Typ der OpenGIS-Spezifikation." + +msgid "Point" +msgstr "Punkt" + +msgid "Line string" +msgstr "Linienzug" + +msgid "Polygon" +msgstr "Polygon" + +msgid "Multi-point" +msgstr "Mehrere Punkte" + +msgid "Multi-line string" +msgstr "Mehrere Linienzüge" + +msgid "Multi polygon" +msgstr "Mehrere Polygone" + +msgid "Geometry collection" +msgstr "Sammlung geometrischer Objekte" + +msgid "Extent Aggregate Field" +msgstr "Ausmaße-Aggregat-Feld" + +msgid "Raster Field" +msgstr "Raster-Feld" + +msgid "No geometry value provided." +msgstr "Kein geometrischer Wert gegeben." + +msgid "Invalid geometry value." +msgstr "Ungültiger geometrischer Wert." + +msgid "Invalid geometry type." +msgstr "Ungültiger geometrischer Typ." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Ein Fehler ist beim Umwandeln der Geometrie-Werte in die SRID des Geometrie-" +"Formularfeldes aufgetreten." + +msgid "Delete all Features" +msgstr "Alles löschen" + +msgid "Debugging window (serialized value)" +msgstr "Debugging-Fenster (serialisierter Wert)" + +msgid "No feeds are registered." +msgstr "Keine Feeds registriert." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Kürzel %r ist nicht registriert." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/dsb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/dsb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d8372f6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/dsb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/dsb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/dsb/LC_MESSAGES/django.po new file mode 100644 index 0000000..e3a8b17 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/dsb/LC_MESSAGES/django.po @@ -0,0 +1,86 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Michael Wolf , 2016,2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Michael Wolf , 2016,2020\n" +"Language-Team: Lower Sorbian (http://app.transifex.com/django/django/" +"language/dsb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: dsb\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || " +"n%100==4 ? 2 : 3);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Bazowe pólo GIS." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Bazowe geometrijowe pólo -- wužywa geometrijowy typ specifikacije OpenGIS." + +msgid "Point" +msgstr "Dypk" + +msgid "Line string" +msgstr "Cera" + +msgid "Polygon" +msgstr "Wjelerožk" + +msgid "Multi-point" +msgstr "Někotare dypki" + +msgid "Multi-line string" +msgstr "Někotare cery" + +msgid "Multi polygon" +msgstr "Někotare wjelerožki" + +msgid "Geometry collection" +msgstr "Geometrijowa zběrka" + +msgid "Extent Aggregate Field" +msgstr "Pólo „Extent Aggregate" + +msgid "Raster Field" +msgstr "Rasterowe pólo" + +msgid "No geometry value provided." +msgstr "Žedna geometrijowa gódnota pódana." + +msgid "Invalid geometry value." +msgstr "Njepłaśiwa geometrijowa gódnota." + +msgid "Invalid geometry type." +msgstr "Njepłaśiwy geometrijowy typ." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Zmólka jo se nastała, gaž geometrija jo se do SRID póla geometrijowego " +"formulara pśetwóriła." + +msgid "Delete all Features" +msgstr "Wšykne funkcije lašowaś" + +msgid "Debugging window (serialized value)" +msgstr "Wokno pytanja zmólkow (serializěrowana gódnota)" + +msgid "No feeds are registered." +msgstr "Žedne kanale njejsu zregistrěrowane." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Adresowe mě %r njejo zregistrěrowane." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/el/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/el/LC_MESSAGES/django.mo new file mode 100644 index 0000000..dcddabb Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/el/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/el/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/el/LC_MESSAGES/django.po new file mode 100644 index 0000000..776107e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/el/LC_MESSAGES/django.po @@ -0,0 +1,91 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Anastasiadis Stavros , 2014 +# Dimitris Glezos , 2011 +# Elena Andreou , 2016 +# Fotis Athineos , 2021 +# Kostas Papadimitriou , 2012 +# Nick Mavrakis , 2016 +# Pãnoș , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Fotis Athineos , 2021\n" +"Language-Team: Greek (http://app.transifex.com/django/django/language/el/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: el\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr " Γεωγραφικά Συστήματα Πληροφορίας" + +msgid "The base GIS field." +msgstr "Το βασικό GIS πεδίο." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Το βασικό Γεωμετρικό πεδίο — αντιστοιχεί στον τύπο της Γεωμετρικής " +"Προδιαγραφής OpenGIS." + +msgid "Point" +msgstr "Σημείο" + +msgid "Line string" +msgstr "Γραμμή string" + +msgid "Polygon" +msgstr "Πολύγωνο" + +msgid "Multi-point" +msgstr "Πολλαπλό σημείο" + +msgid "Multi-line string" +msgstr "Multi-line string" + +msgid "Multi polygon" +msgstr "Πολλαπλό πολύγωνο" + +msgid "Geometry collection" +msgstr "Συλλογή γεωμετριών" + +msgid "Extent Aggregate Field" +msgstr "Πεδίο Extent Aggregate" + +msgid "Raster Field" +msgstr "Πεδίο Raster" + +msgid "No geometry value provided." +msgstr "Δε δόθηκε τιμή γεωμετρίας." + +msgid "Invalid geometry value." +msgstr "Άκυρη γεωμετρική τιμή." + +msgid "Invalid geometry type." +msgstr "Άκυρος γεωμετρικός τύπος." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Παρουσιάστηκε σφάλμα κατά τη μετατροπή της γεωμετρίας στο SRID του πεδίου " +"της φόρμας γεωμετρίας." + +msgid "Delete all Features" +msgstr "Διαγραφή όλων των αντικειμένων" + +msgid "Debugging window (serialized value)" +msgstr "Παράθυρο αποσφαλμάτωσης (σειριακή τιμή)" + +msgid "No feeds are registered." +msgstr "Δεν υπάρχουν εγγεγραμμένες ροές ειδήσεων." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Το slug %r δεν έχει καταχωρηθεί." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/en/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/en/LC_MESSAGES/django.mo new file mode 100644 index 0000000..08a7b68 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/en/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/en/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/en/LC_MESSAGES/django.po new file mode 100644 index 0000000..c6e3d72 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/en/LC_MESSAGES/django.po @@ -0,0 +1,98 @@ +# This file is distributed under the same license as the Django package. +# +msgid "" +msgstr "" +"Project-Id-Version: Django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2010-05-13 15:35+0200\n" +"Last-Translator: Django team\n" +"Language-Team: English \n" +"Language: en\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: contrib/gis/apps.py:9 +msgid "GIS" +msgstr "" + +#: contrib/gis/db/models/fields.py:81 +msgid "The base GIS field." +msgstr "" + +#: contrib/gis/db/models/fields.py:233 +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" + +#: contrib/gis/db/models/fields.py:332 +msgid "Point" +msgstr "" + +#: contrib/gis/db/models/fields.py:339 +msgid "Line string" +msgstr "" + +#: contrib/gis/db/models/fields.py:346 +msgid "Polygon" +msgstr "" + +#: contrib/gis/db/models/fields.py:353 +msgid "Multi-point" +msgstr "" + +#: contrib/gis/db/models/fields.py:360 +msgid "Multi-line string" +msgstr "" + +#: contrib/gis/db/models/fields.py:367 +msgid "Multi polygon" +msgstr "" + +#: contrib/gis/db/models/fields.py:374 +msgid "Geometry collection" +msgstr "" + +#: contrib/gis/db/models/fields.py:380 +msgid "Extent Aggregate Field" +msgstr "" + +#: contrib/gis/db/models/fields.py:395 +msgid "Raster Field" +msgstr "" + +#: contrib/gis/forms/fields.py:21 +msgid "No geometry value provided." +msgstr "" + +#: contrib/gis/forms/fields.py:22 +msgid "Invalid geometry value." +msgstr "" + +#: contrib/gis/forms/fields.py:23 +msgid "Invalid geometry type." +msgstr "" + +#: contrib/gis/forms/fields.py:25 +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" + +#: contrib/gis/templates/gis/openlayers.html:6 +msgid "Delete all Features" +msgstr "" + +#: contrib/gis/templates/gis/openlayers.html:7 +msgid "Debugging window (serialized value)" +msgstr "" + +#: contrib/gis/views.py:8 +msgid "No feeds are registered." +msgstr "" + +#: contrib/gis/views.py:14 +#, python-format +msgid "Slug %r isn’t registered." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/en_AU/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/en_AU/LC_MESSAGES/django.mo new file mode 100644 index 0000000..49b5343 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/en_AU/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/en_AU/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/en_AU/LC_MESSAGES/django.po new file mode 100644 index 0000000..d107919 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/en_AU/LC_MESSAGES/django.po @@ -0,0 +1,80 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-03-18 09:16+0100\n" +"PO-Revision-Date: 2015-03-18 08:35+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: English (Australia) (http://www.transifex.com/projects/p/" +"django/language/en_AU/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_AU\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "" + +msgid "Line string" +msgstr "" + +msgid "Polygon" +msgstr "" + +msgid "Multi-point" +msgstr "" + +msgid "Multi-line string" +msgstr "" + +msgid "Multi polygon" +msgstr "" + +msgid "Geometry collection" +msgstr "" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "" + +msgid "Invalid geometry value." +msgstr "" + +msgid "Invalid geometry type." +msgstr "" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Google Maps via GeoDjango" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "" + +#, python-format +msgid "Slug %r isn't registered." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/en_GB/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/en_GB/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0f30967 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/en_GB/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/en_GB/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/en_GB/LC_MESSAGES/django.po new file mode 100644 index 0000000..0fe8230 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/en_GB/LC_MESSAGES/django.po @@ -0,0 +1,88 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# jon_atkinson , 2011 +# Ross Poulton , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: English (United Kingdom) (http://www.transifex.com/django/" +"django/language/en_GB/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_GB\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "Point" + +msgid "Line string" +msgstr "Line string" + +msgid "Polygon" +msgstr "Polygon" + +msgid "Multi-point" +msgstr "Multi-point" + +msgid "Multi-line string" +msgstr "Multi-line string" + +msgid "Multi polygon" +msgstr "Multi polygon" + +msgid "Geometry collection" +msgstr "Geometry collection" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "No geometry value provided." + +msgid "Invalid geometry value." +msgstr "Invalid geometry value." + +msgid "Invalid geometry type." +msgstr "Invalid geometry type." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "No feeds are registered." + +#, python-format +msgid "Slug %r isn't registered." +msgstr "Slug %r isn't registered." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/eo/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/eo/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b96c9c2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/eo/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/eo/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/eo/LC_MESSAGES/django.po new file mode 100644 index 0000000..16ef0c1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/eo/LC_MESSAGES/django.po @@ -0,0 +1,86 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Batist D 🐍 , 2012 +# Batist D 🐍 , 2014-2015 +# Mariusz Felisiak , 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Mariusz Felisiak , 2023\n" +"Language-Team: Esperanto (http://app.transifex.com/django/django/language/" +"eo/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eo\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "La baza GIS kampo." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "La baza Geometry kampo — korelas al la OpenGIS Specifa Geometrio tipo." + +msgid "Point" +msgstr "Punkto" + +msgid "Line string" +msgstr "Liniŝnuro" + +msgid "Polygon" +msgstr "Plurangulo" + +msgid "Multi-point" +msgstr "Multpunkto" + +msgid "Multi-line string" +msgstr "Multlinia ŝnuro" + +msgid "Multi polygon" +msgstr "Multplurangulo" + +msgid "Geometry collection" +msgstr "Geometriaro" + +msgid "Extent Aggregate Field" +msgstr "Etenda kunmetita kampo" + +msgid "Raster Field" +msgstr "Rastruma kampo" + +msgid "No geometry value provided." +msgstr "Neniu geometria valoro provizas." + +msgid "Invalid geometry value." +msgstr "Malvalida geometria valoro." + +msgid "Invalid geometry type." +msgstr "Malvalida geometria tipo." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Eraro okazis dum transformi la geometrion al la SRID de la geometria forma " +"kampo." + +msgid "Delete all Features" +msgstr "Forigi ĉiuj trajtoj" + +msgid "Debugging window (serialized value)" +msgstr "Elcimigita fenestro (seriigita valoro)" + +msgid "No feeds are registered." +msgstr "Neniu fluo estas registrita." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Ĵetonvorto %r ne estas registrita." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c32e28c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es/LC_MESSAGES/django.po new file mode 100644 index 0000000..fa2c02d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es/LC_MESSAGES/django.po @@ -0,0 +1,92 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Antoni Aloy , 2012,2015-2016,2019 +# e4db27214f7e7544f2022c647b585925_bb0e321, 2015 +# e4db27214f7e7544f2022c647b585925_bb0e321, 2020 +# Igor Támara , 2015 +# Jannis Leidel , 2011 +# Josue Naaman Nistal Guerra , 2014 +# Marc Garcia , 2011 +# Uriel Medina , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Uriel Medina , 2020\n" +"Language-Team: Spanish (http://app.transifex.com/django/django/language/" +"es/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "El campo GIS base." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"El campo base Geometry — coincide con el tipo OpenGIS Specification Geometry." + +msgid "Point" +msgstr "Punto" + +msgid "Line string" +msgstr "Cadena de línea" + +msgid "Polygon" +msgstr "Polígono" + +msgid "Multi-point" +msgstr "Punto múltiple" + +msgid "Multi-line string" +msgstr "Cadena de línea múltiple" + +msgid "Multi polygon" +msgstr "Polígono múltiple" + +msgid "Geometry collection" +msgstr "Colección de \"Geometry\"" + +msgid "Extent Aggregate Field" +msgstr "Extensión de campo agregado" + +msgid "Raster Field" +msgstr "Campo Raster" + +msgid "No geometry value provided." +msgstr "No se indico ningún valor de geometría." + +msgid "Invalid geometry value." +msgstr "Valor de geometría inválido." + +msgid "Invalid geometry type." +msgstr "Tipo de geometría inválido." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Ocurrió un error al transformar la geometria al SRID de la geometria del " +"campo de formulario." + +msgid "Delete all Features" +msgstr "Borrar todos los elementos" + +msgid "Debugging window (serialized value)" +msgstr "Ventana de depuración (valores serializados)" + +msgid "No feeds are registered." +msgstr "No se han registrado canales de contenido." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "El slug %r no está registrado." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es_AR/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es_AR/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2dd6730 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es_AR/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es_AR/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es_AR/LC_MESSAGES/django.po new file mode 100644 index 0000000..7853f22 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es_AR/LC_MESSAGES/django.po @@ -0,0 +1,87 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Ramiro Morales, 2012,2014-2015,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Ramiro Morales, 2012,2014-2015,2019\n" +"Language-Team: Spanish (Argentina) (http://app.transifex.com/django/django/" +"language/es_AR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_AR\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "SIG" + +msgid "The base GIS field." +msgstr "El campo GIS base" + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"El campo Geometry base — corresponde al tipo Geometry de la especificación " +"OpenGIS." + +msgid "Point" +msgstr "Punto" + +msgid "Line string" +msgstr "Secuencia de líneas" + +msgid "Polygon" +msgstr "Polígono" + +msgid "Multi-point" +msgstr "Multi-punto" + +msgid "Multi-line string" +msgstr "Cadena multi-línea" + +msgid "Multi polygon" +msgstr "Multi polígono" + +msgid "Geometry collection" +msgstr "Colección de Geometry's" + +msgid "Extent Aggregate Field" +msgstr "Campo Extent Aggregate" + +msgid "Raster Field" +msgstr "Campo Raster" + +msgid "No geometry value provided." +msgstr "No se ha proporcionado un valor de geometría." + +msgid "Invalid geometry value." +msgstr "Valor de geometría no válido." + +msgid "Invalid geometry type." +msgstr "Tipo de geometría no válido." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Ha ocurrido un error mientras se transformaba la geometría al SRID del campo " +"de formulario de la misma." + +msgid "Delete all Features" +msgstr "Eliminar todas las Features" + +msgid "Debugging window (serialized value)" +msgstr "Ventana de depuración (valor serializado)" + +msgid "No feeds are registered." +msgstr "No se han registrado feeds." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "El slug %r no está registrado." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es_CO/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es_CO/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e1bba32 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es_CO/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es_CO/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es_CO/LC_MESSAGES/django.po new file mode 100644 index 0000000..96f3d6d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es_CO/LC_MESSAGES/django.po @@ -0,0 +1,90 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Antoni Aloy , 2012,2015 +# e4db27214f7e7544f2022c647b585925_bb0e321, 2015 +# Igor Támara , 2015 +# Jannis Leidel , 2011 +# Josue Naaman Nistal Guerra , 2014 +# Marc Garcia , 2011 +# Mariusz Felisiak , 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Mariusz Felisiak , 2023\n" +"Language-Team: Spanish (Colombia) (http://app.transifex.com/django/django/" +"language/es_CO/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_CO\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "El campo GIS base." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "Punto" + +msgid "Line string" +msgstr "Cadena de línea" + +msgid "Polygon" +msgstr "Polígono" + +msgid "Multi-point" +msgstr "Punto múltiple" + +msgid "Multi-line string" +msgstr "Cadena de línea múltiple" + +msgid "Multi polygon" +msgstr "Polígono múltiple" + +msgid "Geometry collection" +msgstr "Colección de \"Geometry\"" + +msgid "Extent Aggregate Field" +msgstr "Extensión de campo agregado" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "No se indico ningún valor de geometría." + +msgid "Invalid geometry value." +msgstr "Valor de geometría inválido." + +msgid "Invalid geometry type." +msgstr "Tipo de geometría inválido." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Ocurrió un error al transformar la geometria al SRID de la geometria del " +"campo de formulario." + +msgid "Delete all Features" +msgstr "Borrar todos los elementos" + +msgid "Debugging window (serialized value)" +msgstr "Ventana de depuración (valores serializados)" + +msgid "No feeds are registered." +msgstr "No se han registrado canales de contenido." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "El slug %r no está registrado." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es_MX/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es_MX/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e0696d5 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es_MX/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es_MX/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es_MX/LC_MESSAGES/django.po new file mode 100644 index 0000000..85698c5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es_MX/LC_MESSAGES/django.po @@ -0,0 +1,87 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Abraham Estrada, 2011-2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Spanish (Mexico) (http://www.transifex.com/django/django/" +"language/es_MX/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_MX\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "Punto" + +msgid "Line string" +msgstr "Secuencia de líneas" + +msgid "Polygon" +msgstr "Polígono" + +msgid "Multi-point" +msgstr "Multi-punto" + +msgid "Multi-line string" +msgstr "Cadena multi-línea" + +msgid "Multi polygon" +msgstr "Multi polígonos" + +msgid "Geometry collection" +msgstr "Colección de geometrías" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "No se ha proporcionado un valor de geometría." + +msgid "Invalid geometry value." +msgstr "Valor de geometría no válido." + +msgid "Invalid geometry type." +msgstr "Tipo de geometría no válido." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Ha ocurrido un error mientras se transformaba la geometría al SRID del campo " +"de formulario de la misma." + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "No hay feeds registrados." + +#, python-format +msgid "Slug %r isn't registered." +msgstr "El slug %r no está registrado." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es_VE/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es_VE/LC_MESSAGES/django.mo new file mode 100644 index 0000000..23ec22d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es_VE/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es_VE/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es_VE/LC_MESSAGES/django.po new file mode 100644 index 0000000..7d4117d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/es_VE/LC_MESSAGES/django.po @@ -0,0 +1,80 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-03-18 09:16+0100\n" +"PO-Revision-Date: 2015-03-18 08:35+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Spanish (Venezuela) (http://www.transifex.com/projects/p/" +"django/language/es_VE/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_VE\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "" + +msgid "Line string" +msgstr "" + +msgid "Polygon" +msgstr "" + +msgid "Multi-point" +msgstr "" + +msgid "Multi-line string" +msgstr "" + +msgid "Multi polygon" +msgstr "" + +msgid "Geometry collection" +msgstr "" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "" + +msgid "Invalid geometry value." +msgstr "" + +msgid "Invalid geometry type." +msgstr "" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Google Maps via GeoDjango" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "" + +#, python-format +msgid "Slug %r isn't registered." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/et/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/et/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f052b4c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/et/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/et/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/et/LC_MESSAGES/django.po new file mode 100644 index 0000000..5eeb1e3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/et/LC_MESSAGES/django.po @@ -0,0 +1,88 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# eallik , 2011 +# Jannis Leidel , 2011 +# Janno Liivak , 2013-2015 +# madisvain , 2011 +# Martin , 2015 +# Ragnar Rebase , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Ragnar Rebase , 2019\n" +"Language-Team: Estonian (http://app.transifex.com/django/django/language/" +"et/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: et\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Baas GIS väli." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Baas Geomeetria väli -- ühildub OpenGIS Spetsifikatsiooni Geomeetria tüübiga." + +msgid "Point" +msgstr "Punkt" + +msgid "Line string" +msgstr "Üherea tekst" + +msgid "Polygon" +msgstr "Polügon" + +msgid "Multi-point" +msgstr "Multi-punkt" + +msgid "Multi-line string" +msgstr "Mitmerealine string" + +msgid "Multi polygon" +msgstr "Multi-polügon" + +msgid "Geometry collection" +msgstr "Geomeetriakogum" + +msgid "Extent Aggregate Field" +msgstr "Laiendi Agregeeritud Väli" + +msgid "Raster Field" +msgstr "Rastri Väli" + +msgid "No geometry value provided." +msgstr "Geomeetriline väärtus puudub." + +msgid "Invalid geometry value." +msgstr "Vigane geomeetriline väärtus." + +msgid "Invalid geometry type." +msgstr "Vigane geomeetriline tüüp." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "Geomeetria teisendamisel geomeetria vormivälja SRID-ks tekkis viga." + +msgid "Delete all Features" +msgstr "Kustuta kõik Vahendid" + +msgid "Debugging window (serialized value)" +msgstr "Siluri aken (järjestikväärtus)" + +msgid "No feeds are registered." +msgstr "Ühtegi voogu pole registreeritud." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Nälk %r ei ole registeeritud." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/eu/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/eu/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9118c75 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/eu/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/eu/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/eu/LC_MESSAGES/django.po new file mode 100644 index 0000000..c45fe36 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/eu/LC_MESSAGES/django.po @@ -0,0 +1,84 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Aitzol Naberan , 2011-2012 +# Eneko Illarramendi , 2017 +# Urtzi Odriozola , 2017,2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Urtzi Odriozola , 2017,2021\n" +"Language-Team: Basque (http://app.transifex.com/django/django/language/eu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Oinarrizko GIS eremua." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Oinarrizko Geometria eremua — OpenGIS zehaztapeneko Geomtry motarentzat mapak" + +msgid "Point" +msgstr "Puntua" + +msgid "Line string" +msgstr "Lerro string-a" + +msgid "Polygon" +msgstr "Poligonoa" + +msgid "Multi-point" +msgstr "Puntu anitz" + +msgid "Multi-line string" +msgstr "Lerro-anitzeko string-a" + +msgid "Multi polygon" +msgstr "Multi poligonoa" + +msgid "Geometry collection" +msgstr "Geometria bilduma" + +msgid "Extent Aggregate Field" +msgstr "Eremu agregatu hedatua" + +msgid "Raster Field" +msgstr "Raster eremua" + +msgid "No geometry value provided." +msgstr "Ez fa geometria baliorik eman." + +msgid "Invalid geometry value." +msgstr "Geometria balio okera." + +msgid "Invalid geometry type." +msgstr "Geometria mota okerra." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "Errore bat gertatu da geometria bere form eremuaren SRIDra biurtzean." + +msgid "Delete all Features" +msgstr "Ezabatu ezaugarri guztiak" + +msgid "Debugging window (serialized value)" +msgstr "Arazketa leihoa (balio serializatua)" + +msgid "No feeds are registered." +msgstr "Ez dago jariorik erregistratuta." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "%r sluga ez dago erregistratuta." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/fa/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/fa/LC_MESSAGES/django.mo new file mode 100644 index 0000000..51f9f5f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/fa/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/fa/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/fa/LC_MESSAGES/django.po new file mode 100644 index 0000000..966ddad --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/fa/LC_MESSAGES/django.po @@ -0,0 +1,87 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ali Nikneshan , 2012-2013,2020 +# Alireza Savand , 2013 +# Ali Vakilzade , 2015 +# Jannis Leidel , 2011 +# Pouya Abbassi, 2016 +# Saeed , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Ali Nikneshan , 2012-2013,2020\n" +"Language-Team: Persian (http://app.transifex.com/django/django/language/" +"fa/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fa\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "GIS" +msgstr "جی‌آی‌اس" + +msgid "The base GIS field." +msgstr "پایه‌ی سیستم اطلاعات جغرافیایی میدانی." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "پایه‌ی فیلد هندسی --نوع خاص هندسه‌ی نقشه‌ها‌ی نوع OpenGIS" + +msgid "Point" +msgstr "نقطه" + +msgid "Line string" +msgstr "رشته خط" + +msgid "Polygon" +msgstr "چندضلعی" + +msgid "Multi-point" +msgstr "چند نقطه ای" + +msgid "Multi-line string" +msgstr "چند خط رشته" + +msgid "Multi polygon" +msgstr "چندین چند ضلعی " + +msgid "Geometry collection" +msgstr "مجموعه هندسی" + +msgid "Extent Aggregate Field" +msgstr "تراکم وسعت حوزه‌ی " + +msgid "Raster Field" +msgstr "حوزه‌ی شطرنجی" + +msgid "No geometry value provided." +msgstr "مقدار جغرافیایی‌ای مقرر نشده است." + +msgid "Invalid geometry value." +msgstr "مقدار جغرافیایی نامعتبر" + +msgid "Invalid geometry type." +msgstr "نوعِ جغرافیایی نامعتبر" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "مشکلی در هنگام انتقال مختصات هندسی از فیلد به SRID رخ داد." + +msgid "Delete all Features" +msgstr "حذف همه‌ی اشیاء" + +msgid "Debugging window (serialized value)" +msgstr "پنجره‌ی اشکال زدایی (ارزش متوالی)" + +msgid "No feeds are registered." +msgstr "هیچ فیدی ثبت شده است." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Slug %r ثبت نشده" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/fi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/fi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..180a3a2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/fi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/fi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/fi/LC_MESSAGES/django.po new file mode 100644 index 0000000..dc67108 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/fi/LC_MESSAGES/django.po @@ -0,0 +1,84 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Aarni Koskela, 2015,2020 +# Antti Kaihola , 2011 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Aarni Koskela, 2015,2020\n" +"Language-Team: Finnish (http://app.transifex.com/django/django/language/" +"fi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "Paikkatietojärjestelmä" + +msgid "The base GIS field." +msgstr "GIS-peruskenttä." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "Geometriaperuskenttä – vastaa OpenGIS-määrittelyn geometriatyyppiä." + +msgid "Point" +msgstr "Piste" + +msgid "Line string" +msgstr "Murtoviiva" + +msgid "Polygon" +msgstr "Polygoni" + +msgid "Multi-point" +msgstr "Monipiste" + +msgid "Multi-line string" +msgstr "Monimurtoviiva" + +msgid "Multi polygon" +msgstr "Monipolygoni" + +msgid "Geometry collection" +msgstr "Geometriakokoelma" + +msgid "Extent Aggregate Field" +msgstr "Laajuusaggregaattikenttä" + +msgid "Raster Field" +msgstr "Rasterikenttä" + +msgid "No geometry value provided." +msgstr "Geometria-arvoa ei annettu." + +msgid "Invalid geometry value." +msgstr "Virheellinen geometria-arvo." + +msgid "Invalid geometry type." +msgstr "Virheellinen geometriatyyppi." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "Kentän SRID-muunnoksessa tapahtui virhe." + +msgid "Delete all Features" +msgstr "Poista kaikki ominaisuudet" + +msgid "Debugging window (serialized value)" +msgstr "Debuggausikkuna (sarjoitettu arvo)" + +msgid "No feeds are registered." +msgstr "Syötteitä ei ole rekisteröity." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Lyhytnimeä %r ei ole rekisteröity." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/fr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/fr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d1bff9f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/fr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/fr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 0000000..6b9c044 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,87 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Claude Paroz , 2014-2015,2017,2019 +# Claude Paroz , 2012 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Claude Paroz , 2014-2015,2017,2019\n" +"Language-Team: French (http://app.transifex.com/django/django/language/fr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "GIS" +msgstr "SIG" + +msgid "The base GIS field." +msgstr "Le champ SIG de base." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Le champ géométrique de base, correspond au type Geometry de la " +"spécification OpenGIS." + +msgid "Point" +msgstr "Point" + +msgid "Line string" +msgstr "Chaîne de segment" + +msgid "Polygon" +msgstr "Polygone" + +msgid "Multi-point" +msgstr "Multipoint" + +msgid "Multi-line string" +msgstr "Chaîne multisegment" + +msgid "Multi polygon" +msgstr "Multipolygone" + +msgid "Geometry collection" +msgstr "Collection géométrique" + +msgid "Extent Aggregate Field" +msgstr "Champ d’agrégation d’étendue" + +msgid "Raster Field" +msgstr "Champ matriciel" + +msgid "No geometry value provided." +msgstr "Aucune valeur géométrique fournie." + +msgid "Invalid geometry value." +msgstr "Valeur géométrique non valide." + +msgid "Invalid geometry type." +msgstr "Type de géométrie non valide." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Une erreur est survenue lors de la transformation de l’objet géométrique " +"dans le SRID du champ de formulaire géométrique." + +msgid "Delete all Features" +msgstr "Supprimer toutes les localisations" + +msgid "Debugging window (serialized value)" +msgstr "Fenêtre de débogage (valeur sérialisée)" + +msgid "No feeds are registered." +msgstr "Aucun flux enregistré." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Le slug %r n’est pas enregistré." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/fy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/fy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..19b093b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/fy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/fy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/fy/LC_MESSAGES/django.po new file mode 100644 index 0000000..9426d48 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/fy/LC_MESSAGES/django.po @@ -0,0 +1,80 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-03-18 09:16+0100\n" +"PO-Revision-Date: 2015-03-18 08:35+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Western Frisian (http://www.transifex.com/projects/p/django/" +"language/fy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fy\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "" + +msgid "Line string" +msgstr "" + +msgid "Polygon" +msgstr "" + +msgid "Multi-point" +msgstr "" + +msgid "Multi-line string" +msgstr "" + +msgid "Multi polygon" +msgstr "" + +msgid "Geometry collection" +msgstr "" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "" + +msgid "Invalid geometry value." +msgstr "" + +msgid "Invalid geometry type." +msgstr "" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Google Maps via GeoDjango" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "" + +#, python-format +msgid "Slug %r isn't registered." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ga/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ga/LC_MESSAGES/django.mo new file mode 100644 index 0000000..846f0d5 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ga/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ga/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ga/LC_MESSAGES/django.po new file mode 100644 index 0000000..e8de66a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ga/LC_MESSAGES/django.po @@ -0,0 +1,88 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Michael Thornhill , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Irish (http://www.transifex.com/django/django/language/ga/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ga\n" +"Plural-Forms: nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : " +"4);\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "Pointe" + +msgid "Line string" +msgstr "Líne teaghrán" + +msgid "Polygon" +msgstr "Polagán" + +msgid "Multi-point" +msgstr "Il-phointe" + +msgid "Multi-line string" +msgstr "Il-líne teaghrán" + +msgid "Multi polygon" +msgstr "Il polagán" + +msgid "Geometry collection" +msgstr "Céimseata bhailiú" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "Ní soláthair méid geoiméadracht" + +msgid "Invalid geometry value." +msgstr "Méid geoiméadracht neamhbhailí" + +msgid "Invalid geometry type." +msgstr "Tíopa geoiméadracht neamhbhailí" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Tharla earráid ag claochlú an geoiméadracht go dtí SRID an réimse fhoirm " +"geoiméadracht." + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "Níl fothaí cláraithe." + +#, python-format +msgid "Slug %r isn't registered." +msgstr "Níl slug %r cláraithe." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/gd/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/gd/LC_MESSAGES/django.mo new file mode 100644 index 0000000..477fb2c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/gd/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/gd/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/gd/LC_MESSAGES/django.po new file mode 100644 index 0000000..fc2d14a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/gd/LC_MESSAGES/django.po @@ -0,0 +1,89 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# GunChleoc, 2015-2016 +# GunChleoc, 2015 +# GunChleoc, 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: GunChleoc, 2015\n" +"Language-Team: Gaelic, Scottish (http://app.transifex.com/django/django/" +"language/gd/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: gd\n" +"Plural-Forms: nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : " +"(n > 2 && n < 20) ? 2 : 3;\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Bun-raon GIS." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Bun-raon geomatrais – thèid a mhapachadh dhan t-seòrsa geomatrais a chaidh a " +"shònrachadh le OpenGIS." + +msgid "Point" +msgstr "Puing" + +msgid "Line string" +msgstr "Sreang loidhne" + +msgid "Polygon" +msgstr "Ioma-cheàrnach" + +msgid "Multi-point" +msgstr "Iomadh-phuing" + +msgid "Multi-line string" +msgstr "Sreang ioma-loidhne" + +msgid "Multi polygon" +msgstr "Iomadh ioma-cheàrnach" + +msgid "Geometry collection" +msgstr "Cruinneachadh geomatrais" + +msgid "Extent Aggregate Field" +msgstr "Raon agragaid a tha ann" + +msgid "Raster Field" +msgstr "Raon raster" + +msgid "No geometry value provided." +msgstr "Cha deach luach geomatrais a shònrachadh." + +msgid "Invalid geometry value." +msgstr "Luach geomatrais mì-dhligheach." + +msgid "Invalid geometry type." +msgstr "Seòrsa geomatrais mì-dhligheach." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Thachair mearachd le thar-mhùthadh a’ gheomatrais gun SRID aig raon foirme " +"a’ gheomatrais." + +msgid "Delete all Features" +msgstr "Sguab às a h-uile gleus" + +msgid "Debugging window (serialized value)" +msgstr "Uinneag dì-bhugachaidh (luach sreathaichte)" + +msgid "No feeds are registered." +msgstr "Cha deach inbhir a shònrachadh." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Cha deach an sluga %r a chlàradh." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/gl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/gl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..eddd528 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/gl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/gl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/gl/LC_MESSAGES/django.po new file mode 100644 index 0000000..af564c2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/gl/LC_MESSAGES/django.po @@ -0,0 +1,89 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# fasouto , 2011 +# fonso , 2013 +# Leandro Regueiro , 2013 +# X Bello , 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: X Bello , 2023\n" +"Language-Team: Galician (http://app.transifex.com/django/django/language/" +"gl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: gl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "SIX" + +msgid "The base GIS field." +msgstr "O cambo básico de XIS." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"O cambo básico Geometry — correspónese co tipo Geometry da especificación " +"OpenGIS." + +msgid "Point" +msgstr "Punto" + +msgid "Line string" +msgstr "Secuencia de liñas" + +msgid "Polygon" +msgstr "Polígono" + +msgid "Multi-point" +msgstr "Punto múltiple" + +msgid "Multi-line string" +msgstr "Cadea multi-liña" + +msgid "Multi polygon" +msgstr "Multi polígono" + +msgid "Geometry collection" +msgstr "Colección de xeometrías" + +msgid "Extent Aggregate Field" +msgstr "Campo de Agregación de Extensión" + +msgid "Raster Field" +msgstr "Campo de Raster" + +msgid "No geometry value provided." +msgstr "Non se proporcionou un valor de xeometría." + +msgid "Invalid geometry value." +msgstr "Valor xeométrico non válido." + +msgid "Invalid geometry type." +msgstr "Tipo xeométrico non válido." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Atopouse un erro mentras se trasnformaba a xeometría ó SRID do campo " +"xeométrico do formulario." + +msgid "Delete all Features" +msgstr "Eliminar tódalas Propiedades" + +msgid "Debugging window (serialized value)" +msgstr "Ventá de depurado (valor serializado)" + +msgid "No feeds are registered." +msgstr "Non hai feeds rexistradas." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "O slug %r non está rexistrado." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/he/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/he/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e479683 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/he/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/he/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/he/LC_MESSAGES/django.po new file mode 100644 index 0000000..489e8c4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/he/LC_MESSAGES/django.po @@ -0,0 +1,83 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Meir Kriheli , 2012,2014-2015,2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Meir Kriheli , 2012,2014-2015,2020\n" +"Language-Team: Hebrew (http://app.transifex.com/django/django/language/he/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: he\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % " +"1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;\n" + +msgid "GIS" +msgstr "מערכת מידע גאוגרפית" + +msgid "The base GIS field." +msgstr "שדה GIS הבסיסי." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "שדה Geometry הבסיסי —ממופה לטיפוס OpenGIS Specification Geometry." + +msgid "Point" +msgstr "נקודה" + +msgid "Line string" +msgstr "מחרוזת קו" + +msgid "Polygon" +msgstr "פוליגון" + +msgid "Multi-point" +msgstr "מרובה־נקודות" + +msgid "Multi-line string" +msgstr "מחרוזת קו מרובת שורות" + +msgid "Multi polygon" +msgstr "פוליגון מרובה" + +msgid "Geometry collection" +msgstr "אוסף גיאומטרי" + +msgid "Extent Aggregate Field" +msgstr "שדה Extent Aggregate" + +msgid "Raster Field" +msgstr "שדה Raster" + +msgid "No geometry value provided." +msgstr "לא סופק ערך גיאומטרי." + +msgid "Invalid geometry value." +msgstr "ערך גאומטרי שגוי." + +msgid "Invalid geometry type." +msgstr "סוג גיאומטרי שגוי." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "הייתה בעיה עם השינוי של הצורה לסוג של השדה." + +msgid "Delete all Features" +msgstr "מחיקת כל התכונות" + +msgid "Debugging window (serialized value)" +msgstr "חלון ניפוי שגיאות (serialized value)" + +msgid "No feeds are registered." +msgstr "לא נרשמו פידים." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "ה־Slug %r אינו רשום." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8d267a5 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hi/LC_MESSAGES/django.po new file mode 100644 index 0000000..7209a61 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hi/LC_MESSAGES/django.po @@ -0,0 +1,86 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Chandan kumar , 2012 +# Sandeep Satavlekar , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Hindi (http://www.transifex.com/django/django/language/hi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "बिंदु" + +msgid "Line string" +msgstr "पंक्ति शृंखला" + +msgid "Polygon" +msgstr "बहुभुज" + +msgid "Multi-point" +msgstr "बहु बिंदु" + +msgid "Multi-line string" +msgstr "बहु - पंक्ति शृंखला" + +msgid "Multi polygon" +msgstr "बहु बहुभुज" + +msgid "Geometry collection" +msgstr "ज्यामिति संग्रह" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "कोई ज्यामिति मूल्य प्रदान नहीं की है." + +msgid "Invalid geometry value." +msgstr "अवैध ज्यामिति मूल्य." + +msgid "Invalid geometry type." +msgstr "अवैध ज्यामिति प्रकार" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"ज्यामिति को ज्यामिति प्रपत्र फ़ील्ड के SRID में परिवर्तित करते वक़्त एक ग़लती हो गयी ." + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "कोई फ़ीड पंजीकृत नहीं हैं." + +#, python-format +msgid "Slug %r isn't registered." +msgstr "स्लग %r पंजीकृत नहीं है." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f98a3be Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hr/LC_MESSAGES/django.po new file mode 100644 index 0000000..7c844b6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hr/LC_MESSAGES/django.po @@ -0,0 +1,91 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# berislavlopac , 2012 +# Davor Lučić , 2012 +# Filip Cuk , 2016 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Croatian (http://www.transifex.com/django/django/language/" +"hr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hr\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "Točka" + +msgid "Line string" +msgstr "Linija (Line string)" + +msgid "Polygon" +msgstr "Poligon" + +msgid "Multi-point" +msgstr "Više točaka" + +msgid "Multi-line string" +msgstr "Više linija (Line string)" + +msgid "Multi polygon" +msgstr "Više poligona" + +msgid "Geometry collection" +msgstr "Geometrijska kolekcija" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "Geometrijska vrijednost nije priložena." + +msgid "Invalid geometry value." +msgstr "Neispravna geometrijska vrijednost." + +msgid "Invalid geometry type." +msgstr "Neispravan geometrijski tip." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Došlo je do greške pri transformaciji geometrije na SRID geometrijskog polja " +"forme." + +msgid "Delete all Features" +msgstr "Izbriši sve značajke" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "Nema registriranih izvora." + +#, python-format +msgid "Slug %r isn't registered." +msgstr "Slug %r nije registriran." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hsb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hsb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b50e758 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hsb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hsb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hsb/LC_MESSAGES/django.po new file mode 100644 index 0000000..66d0357 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hsb/LC_MESSAGES/django.po @@ -0,0 +1,87 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Michael Wolf , 2016,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Michael Wolf , 2016,2019\n" +"Language-Team: Upper Sorbian (http://app.transifex.com/django/django/" +"language/hsb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hsb\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || " +"n%100==4 ? 2 : 3);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Bazowe polo GIS." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Bazowe geometrijowe polo -- zarysowane do geometrijoweho typa specifikacije " +"OpenGIS. " + +msgid "Point" +msgstr "Dypk" + +msgid "Line string" +msgstr "Čara" + +msgid "Polygon" +msgstr "Wjeleróžk" + +msgid "Multi-point" +msgstr "Wjacore dypki" + +msgid "Multi-line string" +msgstr "Wjacore čary" + +msgid "Multi polygon" +msgstr "Wjacore wjelróžki" + +msgid "Geometry collection" +msgstr "Geometrijowa zběrka" + +msgid "Extent Aggregate Field" +msgstr "Polo „extent aggregate“" + +msgid "Raster Field" +msgstr "Rasterowe polo" + +msgid "No geometry value provided." +msgstr "Žana geometrijowa hódnota podata." + +msgid "Invalid geometry value." +msgstr "Njepłaćiwa geometrijowa hódnota." + +msgid "Invalid geometry type." +msgstr "Njepłaćiwy geometrijowy typ." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Zmylk je wustupił, hdyž so geometrija do SRID pola geometrijoweho formulara " +"přetwori." + +msgid "Delete all Features" +msgstr "Wšě funkcije zhašeć" + +msgid "Debugging window (serialized value)" +msgstr "Wokno pytanja zmylkow (serijalizowana hódnota)" + +msgid "No feeds are registered." +msgstr "Žane kanale zregistrowane." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Adresowe mjeno %r njeje zregistrowane." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hu/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hu/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ec2e8a2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hu/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hu/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hu/LC_MESSAGES/django.po new file mode 100644 index 0000000..9e7799e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hu/LC_MESSAGES/django.po @@ -0,0 +1,88 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# András Veres-Szentkirályi, 2016 +# Istvan Farkas , 2019 +# Jannis Leidel , 2011 +# Kristóf Gruber <>, 2012 +# Szilveszter Farkas , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Istvan Farkas , 2019\n" +"Language-Team: Hungarian (http://app.transifex.com/django/django/language/" +"hu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Az alap GIS mező." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Az alap geometria mező - az OpenGIS Specification Geometry formátumnak " +"megfelelően." + +msgid "Point" +msgstr "Pont" + +msgid "Line string" +msgstr "Vonallánc" + +msgid "Polygon" +msgstr "Poligon" + +msgid "Multi-point" +msgstr "Multi-pont" + +msgid "Multi-line string" +msgstr "Többes vonallánc" + +msgid "Multi polygon" +msgstr "Multi-poligon" + +msgid "Geometry collection" +msgstr "Geometria gyűjtemény" + +msgid "Extent Aggregate Field" +msgstr "Terület összegző mező" + +msgid "Raster Field" +msgstr "Raszter mező" + +msgid "No geometry value provided." +msgstr "Geometriai adat nem került megadásra." + +msgid "Invalid geometry value." +msgstr "Érvénytelen geometriai érték." + +msgid "Invalid geometry type." +msgstr "Érvénytelen geometriai típus." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "Hiba történt a geometriai transzformáció során." + +msgid "Delete all Features" +msgstr "Minden Feature törlése" + +msgid "Debugging window (serialized value)" +msgstr "Debug ablak (szerializált érték)" + +msgid "No feeds are registered." +msgstr "Nincs regisztrált feed." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "A(z) %r domain-darabka nincs regisztrálva." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..cecc0a9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hy/LC_MESSAGES/django.po new file mode 100644 index 0000000..21a69f7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/hy/LC_MESSAGES/django.po @@ -0,0 +1,81 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Django team\n" +"Language-Team: Armenian (http://app.transifex.com/django/django/language/" +"hy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hy\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "ԱՏՀ" + +msgid "The base GIS field." +msgstr "ԱՏՀ֊ի գլխավոր դաշտ" + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "Կետ" + +msgid "Line string" +msgstr "Թեք" + +msgid "Polygon" +msgstr "Բազմանկյուն" + +msgid "Multi-point" +msgstr "Կետերի հավաքածու" + +msgid "Multi-line string" +msgstr "Թեքերի հավաքածու" + +msgid "Multi polygon" +msgstr "Բազմանկյունների հավաքածու" + +msgid "Geometry collection" +msgstr "Երկրաչափական օբյեկտների հավաքածու" + +msgid "Extent Aggregate Field" +msgstr "Մակերեսի կամ ծավալի խմբավորման դաշտ" + +msgid "Raster Field" +msgstr "Պատկերացանցի դաշտ" + +msgid "No geometry value provided." +msgstr "Երկարաչափական արժեք չի տրամադրվել։" + +msgid "Invalid geometry value." +msgstr "Երկարաչափական օյբեկտի սխալ արժեք։" + +msgid "Invalid geometry type." +msgstr "Երկարաչափական օյբեկտի տիպ։" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "Երկարաչափական օյբեկտի SRID ձևափոխելու ժամանակ առաջացել է սխալլ։" + +msgid "Delete all Features" +msgstr "Հեռացնել բոլոր օբյեկտները" + +msgid "Debugging window (serialized value)" +msgstr "Կարգաբերման պատուհան (սերիալիզացված արժեքներ)" + +msgid "No feeds are registered." +msgstr "Չկան գրանցված feed֊եր։" + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ia/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ia/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d0867b7 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ia/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ia/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ia/LC_MESSAGES/django.po new file mode 100644 index 0000000..cd08566 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ia/LC_MESSAGES/django.po @@ -0,0 +1,87 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Mariusz Felisiak , 2023 +# Martijn Dekker , 2012,2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Mariusz Felisiak , 2023\n" +"Language-Team: Interlingua (http://app.transifex.com/django/django/language/" +"ia/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ia\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field." +msgstr "Le campo GIS de base." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Le campo Geometry de base. Corresponde al typo geometric del specification " +"OpenGIS." + +msgid "Point" +msgstr "Puncto" + +msgid "Line string" +msgstr "Texto de linea" + +msgid "Polygon" +msgstr "Polygono" + +msgid "Multi-point" +msgstr "Plure punctos" + +msgid "Multi-line string" +msgstr "Texto con plure lineas" + +msgid "Multi polygon" +msgstr "Plure polygonos" + +msgid "Geometry collection" +msgstr "Collection geometric" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "Nulle valor geometric fornite." + +msgid "Invalid geometry value." +msgstr "Valor geometric invalide." + +msgid "Invalid geometry type." +msgstr "Typo geometric invalide." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Un error occurreva durante le transformation del geometria al SRID del campo " +"del formulario geometric." + +msgid "Delete all Features" +msgstr "Deler tote le elementos" + +msgid "Debugging window (serialized value)" +msgstr "Fenestra pro debugging (valor serialisate)" + +msgid "No feeds are registered." +msgstr "Nulle syndication es registrate." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Le denotation %r non es registrate." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/id/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/id/LC_MESSAGES/django.mo new file mode 100644 index 0000000..03412db Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/id/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/id/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/id/LC_MESSAGES/django.po new file mode 100644 index 0000000..8907759 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/id/LC_MESSAGES/django.po @@ -0,0 +1,90 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Fery Setiawan , 2016 +# Jannis Leidel , 2011 +# M Asep Indrayana , 2015 +# rodin , 2011-2012 +# rodin , 2015-2016 +# sag᠎e , 2019 +# Sutrisno Efendi , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: sag᠎e , 2019\n" +"Language-Team: Indonesian (http://app.transifex.com/django/django/language/" +"id/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: id\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Bidang GIS dasar." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Bidang Geometri dasar — memetakan ke jenis OpenGIS Specification Geometry." + +msgid "Point" +msgstr "Point" + +msgid "Line string" +msgstr "Line string" + +msgid "Polygon" +msgstr "Polygon" + +msgid "Multi-point" +msgstr "Multi-point" + +msgid "Multi-line string" +msgstr "Multi-line string" + +msgid "Multi polygon" +msgstr "Multi polygon" + +msgid "Geometry collection" +msgstr "Geometry collection" + +msgid "Extent Aggregate Field" +msgstr "perpanjang Bidang Pengumpulan" + +msgid "Raster Field" +msgstr "Bidang Raster" + +msgid "No geometry value provided." +msgstr "Nilai geometri tidak disediakan." + +msgid "Invalid geometry value." +msgstr "Nilai geometri salah." + +msgid "Invalid geometry type." +msgstr "Tipe geometri salah." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Galat terjadi saat mentransformasi geometri ke SRID bidang formulir geometri." + +msgid "Delete all Features" +msgstr "Hapus semua Fitur" + +msgid "Debugging window (serialized value)" +msgstr "Jendela mencari dan memperbaiki kesalahan (nilai bersambung)" + +msgid "No feeds are registered." +msgstr "Tidak ada umpan terdaftar." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Slug %r tidak terdaftar." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/io/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/io/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a5371ba Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/io/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/io/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/io/LC_MESSAGES/django.po new file mode 100644 index 0000000..97432bf --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/io/LC_MESSAGES/django.po @@ -0,0 +1,80 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-03-18 09:16+0100\n" +"PO-Revision-Date: 2015-03-18 08:35+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Ido (http://www.transifex.com/projects/p/django/language/" +"io/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: io\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "" + +msgid "Line string" +msgstr "" + +msgid "Polygon" +msgstr "" + +msgid "Multi-point" +msgstr "" + +msgid "Multi-line string" +msgstr "" + +msgid "Multi polygon" +msgstr "" + +msgid "Geometry collection" +msgstr "" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "" + +msgid "Invalid geometry value." +msgstr "" + +msgid "Invalid geometry type." +msgstr "" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Google Maps via GeoDjango" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "" + +#, python-format +msgid "Slug %r isn't registered." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/is/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/is/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7f198ce Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/is/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/is/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/is/LC_MESSAGES/django.po new file mode 100644 index 0000000..0ea0986 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/is/LC_MESSAGES/django.po @@ -0,0 +1,87 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Hafsteinn Einarsson , 2011-2012 +# Jannis Leidel , 2011 +# Thordur Sigurdsson , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-11-20 05:37+0000\n" +"Last-Translator: Thordur Sigurdsson \n" +"Language-Team: Icelandic (http://www.transifex.com/django/django/language/" +"is/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: is\n" +"Plural-Forms: nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "Grunn GIS reitur — varpast í OpenGIS rúmgerð." + +msgid "Point" +msgstr "Punktur" + +msgid "Line string" +msgstr "Lína" + +msgid "Polygon" +msgstr "Marghyrningur" + +msgid "Multi-point" +msgstr "Punktar" + +msgid "Multi-line string" +msgstr "Línur" + +msgid "Multi polygon" +msgstr "Marghyrningar" + +msgid "Geometry collection" +msgstr "Rúmsafn" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "Ekkert rúmgildi gefið." + +msgid "Invalid geometry value." +msgstr "Ógild rúmeining" + +msgid "Invalid geometry type." +msgstr "Ógild rúmmálsgerð." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "Villa kom upp við að varpa rúmgildi í SRID reitsins." + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "Engir listar (feeds) eru skráðir" + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/it/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/it/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d454db4 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/it/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/it/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/it/LC_MESSAGES/django.po new file mode 100644 index 0000000..c86f18f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/it/LC_MESSAGES/django.po @@ -0,0 +1,94 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# yakky , 2015 +# Jannis Leidel , 2011 +# Marco Bonetti, 2014 +# Mirco Grillo , 2020 +# Nicola Larosa , 2012 +# palmux , 2015 +# Mattia Procopio , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-07-23 08:59+0000\n" +"Last-Translator: Mirco Grillo \n" +"Language-Team: Italian (http://www.transifex.com/django/django/language/" +"it/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: it\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Il campo GIS base." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Il campo Geometry -- corrisponde al tipo Geometry delle specifiche OpenGIS." + +msgid "Point" +msgstr "Punto" + +msgid "Line string" +msgstr "Stringa linea" + +msgid "Polygon" +msgstr "Poligono" + +msgid "Multi-point" +msgstr "Multipunto" + +msgid "Multi-line string" +msgstr "Stringa multilinea" + +msgid "Multi polygon" +msgstr "Multi poligono" + +msgid "Geometry collection" +msgstr "Raccolta Geometry" + +msgid "Extent Aggregate Field" +msgstr "Campo di aggregazione esteso" + +msgid "Raster Field" +msgstr "Campo raster" + +msgid "No geometry value provided." +msgstr "Nessun valore geometrico fornito." + +msgid "Invalid geometry value." +msgstr "Valore geometrico non valido." + +msgid "Invalid geometry type." +msgstr "Tipo geometrico non valido." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Si è verificato un errore durante la trasformazione della geometria nello " +"SRID del campo geometria della form." + +msgid "Delete all Features" +msgstr "Cancella tutti gli oggetti" + +msgid "WKT debugging window:" +msgstr "Finestra di debug WKT:" + +msgid "Debugging window (serialized value)" +msgstr "Finestra di debug (valore serializzato)" + +msgid "No feeds are registered." +msgstr "Non ci sono feed registrati." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Lo slug %r non è registrato." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ja/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ja/LC_MESSAGES/django.mo new file mode 100644 index 0000000..831f423 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ja/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ja/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ja/LC_MESSAGES/django.po new file mode 100644 index 0000000..2a0d6cd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ja/LC_MESSAGES/django.po @@ -0,0 +1,86 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Shinya Okano , 2012,2014-2015 +# Takuya N , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Takuya N , 2020\n" +"Language-Team: Japanese (http://app.transifex.com/django/django/language/" +"ja/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ja\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "GIS" +msgstr "地理情報システム" + +msgid "The base GIS field." +msgstr "基底GISフィールド" + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "基底GISフィールド — OpenGIS で決められた地形タイプに対応します。" + +msgid "Point" +msgstr "点" + +msgid "Line string" +msgstr "線" + +msgid "Polygon" +msgstr "ポリゴン" + +msgid "Multi-point" +msgstr "複数の点" + +msgid "Multi-line string" +msgstr "複数の線" + +msgid "Multi polygon" +msgstr "複数のポリゴン" + +msgid "Geometry collection" +msgstr "地形の集合" + +msgid "Extent Aggregate Field" +msgstr "広さ集計フィールド" + +msgid "Raster Field" +msgstr "ラスターフィールド" + +msgid "No geometry value provided." +msgstr "geometry値がありません。" + +msgid "Invalid geometry value." +msgstr "geometry値が不正です" + +msgid "Invalid geometry type." +msgstr "geometryタイプが不正です。" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"geometry を geometry フォームフィールドの SRID に変換しようとしてエラーが起き" +"ました。" + +msgid "Delete all Features" +msgstr "すべての機能を削除" + +msgid "Debugging window (serialized value)" +msgstr "デバッグウィンドウ(シリアライズされた値)" + +msgid "No feeds are registered." +msgstr "フィードが登録されていません。" + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "スラグ %r は登録されていません。" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ka/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ka/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b684ee9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ka/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ka/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ka/LC_MESSAGES/django.po new file mode 100644 index 0000000..31bb23c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ka/LC_MESSAGES/django.po @@ -0,0 +1,87 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# André Bouatchidzé , 2013,2015 +# avsd05 , 2011 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Georgian (http://www.transifex.com/django/django/language/" +"ka/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ka\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "წერტილი" + +msgid "Line string" +msgstr "ხაზის მასივი" + +msgid "Polygon" +msgstr "მრავალკუთხედი" + +msgid "Multi-point" +msgstr "წერტილების სიმრავლე" + +msgid "Multi-line string" +msgstr "ხაზების სიმრავლის მასივი" + +msgid "Multi polygon" +msgstr "მრავალკუთხედების სიმრავლე" + +msgid "Geometry collection" +msgstr "გეომეტრიული კოლექცია" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "გეომეტრიის მნიშვნელობა მოცემული არ არის." + +msgid "Invalid geometry value." +msgstr "გეომეტრიის მნიშვნელობა არასწორია." + +msgid "Invalid geometry type." +msgstr "გეომეტრიის ტიპი არასწორია." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "ველიდან გეომეტრიის SRID-ში გადაყვანისას მოხდა შეცდომა." + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "არცერთი ფიდი არ არის რეგისტრირებული." + +#, python-format +msgid "Slug %r isn't registered." +msgstr "სლაგი %r არ არის რეგისტრირებული." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/kk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/kk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c750301 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/kk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/kk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/kk/LC_MESSAGES/django.po new file mode 100644 index 0000000..2666802 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/kk/LC_MESSAGES/django.po @@ -0,0 +1,85 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# yun_man_ger , 2011 +# Zhazira , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Kazakh (http://www.transifex.com/django/django/language/kk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kk\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "Нүкте" + +msgid "Line string" +msgstr "Сынық" + +msgid "Polygon" +msgstr "Көпбұрыш" + +msgid "Multi-point" +msgstr "Нүкте жинағы" + +msgid "Multi-line string" +msgstr "Сынықтар жинағы" + +msgid "Multi polygon" +msgstr "Көпбұрыш жинағы" + +msgid "Geometry collection" +msgstr "Геометриялық объект жинағы" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "Геметрия мәні берілген жоқ" + +msgid "Invalid geometry value." +msgstr "Геометрия мәні дұрыс емес" + +msgid "Invalid geometry type." +msgstr "Геометрия түрі дұрыс емес" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "Геометрияны SRID-ге өзгерту кезінде қате шықты." + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "" + +#, python-format +msgid "Slug %r isn't registered." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/km/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/km/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4ae545a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/km/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/km/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/km/LC_MESSAGES/django.po new file mode 100644 index 0000000..d5d5980 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/km/LC_MESSAGES/django.po @@ -0,0 +1,80 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-03-18 09:16+0100\n" +"PO-Revision-Date: 2015-03-18 08:35+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Khmer (http://www.transifex.com/projects/p/django/language/" +"km/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: km\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "" + +msgid "Line string" +msgstr "" + +msgid "Polygon" +msgstr "" + +msgid "Multi-point" +msgstr "" + +msgid "Multi-line string" +msgstr "" + +msgid "Multi polygon" +msgstr "" + +msgid "Geometry collection" +msgstr "" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "" + +msgid "Invalid geometry value." +msgstr "" + +msgid "Invalid geometry type." +msgstr "" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Google Maps via GeoDjango" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "" + +#, python-format +msgid "Slug %r isn't registered." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/kn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/kn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..be4f674 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/kn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/kn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/kn/LC_MESSAGES/django.po new file mode 100644 index 0000000..0ec1b16 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/kn/LC_MESSAGES/django.po @@ -0,0 +1,80 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-03-18 09:16+0100\n" +"PO-Revision-Date: 2015-03-18 08:35+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Kannada (http://www.transifex.com/projects/p/django/language/" +"kn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kn\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "" + +msgid "Line string" +msgstr "" + +msgid "Polygon" +msgstr "" + +msgid "Multi-point" +msgstr "" + +msgid "Multi-line string" +msgstr "" + +msgid "Multi polygon" +msgstr "" + +msgid "Geometry collection" +msgstr "" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "" + +msgid "Invalid geometry value." +msgstr "" + +msgid "Invalid geometry type." +msgstr "" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Google Maps via GeoDjango" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "" + +#, python-format +msgid "Slug %r isn't registered." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ko/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ko/LC_MESSAGES/django.mo new file mode 100644 index 0000000..29545de Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ko/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ko/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ko/LC_MESSAGES/django.po new file mode 100644 index 0000000..004cde1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ko/LC_MESSAGES/django.po @@ -0,0 +1,88 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jiyoon, Ha , 2016 +# Jaehong Kim , 2011 +# Jannis Leidel , 2011 +# Jay Oh , 2020 +# Le Tartuffe , 2014 +# JunGu Kang , 2015 +# 이지현 , 2017 +# minsung kang, 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Jay Oh , 2020\n" +"Language-Team: Korean (http://app.transifex.com/django/django/language/ko/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ko\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "기본 GIS 필드" + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "기본 지리 정보 필드 — 오픈GIS에 특화된 지리 정보 형식의 맵" + +msgid "Point" +msgstr "위치" + +msgid "Line string" +msgstr "한줄 문자열" + +msgid "Polygon" +msgstr "다각형" + +msgid "Multi-point" +msgstr "다중 위치" + +msgid "Multi-line string" +msgstr "여러줄 문자열" + +msgid "Multi polygon" +msgstr "복수 다각형" + +msgid "Geometry collection" +msgstr "지리적 위치 모음" + +msgid "Extent Aggregate Field" +msgstr "확장 집계 필드" + +msgid "Raster Field" +msgstr "래스터 필드" + +msgid "No geometry value provided." +msgstr "지리 값이 없습니다." + +msgid "Invalid geometry value." +msgstr "잘못된 지리 값." + +msgid "Invalid geometry type." +msgstr "잘못된 지리 형식." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "Geometry를 geometry 필드의 SRID로 변환하는 도중 오류가 발생하였습니다." + +msgid "Delete all Features" +msgstr "모든 기능 삭제" + +msgid "Debugging window (serialized value)" +msgstr "디버깅 창 (연속된 값)" + +msgid "No feeds are registered." +msgstr "등록된 피드가 없습니다." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "%r 이/가 등록되지 않았습니다." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ky/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ky/LC_MESSAGES/django.mo new file mode 100644 index 0000000..6b61583 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ky/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ky/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ky/LC_MESSAGES/django.po new file mode 100644 index 0000000..3e453c7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ky/LC_MESSAGES/django.po @@ -0,0 +1,83 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Soyuzbek orozbek uulu , 2020 +# Soyuzbek orozbek uulu , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Soyuzbek orozbek uulu , 2020\n" +"Language-Team: Kyrgyz (http://app.transifex.com/django/django/language/ky/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ky\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Негизги GIS талаасы" + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"негизги Геометр талаасы — OpenGIS Геометрдик көрсөтмөлө тибине дал келет." + +msgid "Point" +msgstr "Чекит" + +msgid "Line string" +msgstr "Сап сызыгы" + +msgid "Polygon" +msgstr "Көпбурчтук" + +msgid "Multi-point" +msgstr "Көп чекит" + +msgid "Multi-line string" +msgstr "Көпсап" + +msgid "Multi polygon" +msgstr "Көп көпбурчтук" + +msgid "Geometry collection" +msgstr "Геометр жыйындысы" + +msgid "Extent Aggregate Field" +msgstr "Кошумча Агрегат талаасы" + +msgid "Raster Field" +msgstr "Растр Талаасы" + +msgid "No geometry value provided." +msgstr "геометр маани тейленбейт." + +msgid "Invalid geometry value." +msgstr "Ката геометр маани." + +msgid "Invalid geometry type." +msgstr "Ката геометр тиби." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "геометр аймагынын маанисин SRID ге которгондо ката чыкты." + +msgid "Delete all Features" +msgstr "Бүт касиеттерди өчүр" + +msgid "Debugging window (serialized value)" +msgstr "Оңдоо терезеси (кысымдалган маани)" + +msgid "No feeds are registered." +msgstr "Кадамдар катталган эмес." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "%r слагы катталган эмес." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/lb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/lb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f91c361 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/lb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/lb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/lb/LC_MESSAGES/django.po new file mode 100644 index 0000000..40fd9e2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/lb/LC_MESSAGES/django.po @@ -0,0 +1,80 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-03-18 09:16+0100\n" +"PO-Revision-Date: 2015-03-18 08:35+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Luxembourgish (http://www.transifex.com/projects/p/django/" +"language/lb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "" + +msgid "Line string" +msgstr "" + +msgid "Polygon" +msgstr "" + +msgid "Multi-point" +msgstr "" + +msgid "Multi-line string" +msgstr "" + +msgid "Multi polygon" +msgstr "" + +msgid "Geometry collection" +msgstr "" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "" + +msgid "Invalid geometry value." +msgstr "" + +msgid "Invalid geometry type." +msgstr "" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Google Maps via GeoDjango" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "" + +#, python-format +msgid "Slug %r isn't registered." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/lt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/lt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4505fa6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/lt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/lt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/lt/LC_MESSAGES/django.po new file mode 100644 index 0000000..dff04ab --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/lt/LC_MESSAGES/django.po @@ -0,0 +1,89 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Kostas , 2011 +# lauris , 2011 +# Mariusz Felisiak , 2023 +# Matas Dailyda , 2015 +# Simonas Kazlauskas , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Mariusz Felisiak , 2023\n" +"Language-Team: Lithuanian (http://app.transifex.com/django/django/language/" +"lt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lt\n" +"Plural-Forms: nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < " +"11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? " +"1 : n % 1 != 0 ? 2: 3);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Bazinis GIS laukas." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Bazinis geometrijos laukas — atvaizduoja OpenGIS Specification Geometry tipą." + +msgid "Point" +msgstr "Taškas" + +msgid "Line string" +msgstr "Atkarpa" + +msgid "Polygon" +msgstr "Daugiakampis" + +msgid "Multi-point" +msgstr "Taškų aibė" + +msgid "Multi-line string" +msgstr "Atkarpų aibė" + +msgid "Multi polygon" +msgstr "Daugiakampių aibė" + +msgid "Geometry collection" +msgstr "Geometrinė kolekcija" + +msgid "Extent Aggregate Field" +msgstr "Išplėsti agregato lauką" + +msgid "Raster Field" +msgstr "Rastro laukas" + +msgid "No geometry value provided." +msgstr "Nenurodyta geometrinė reikšmė" + +msgid "Invalid geometry value." +msgstr "Netinkama geometrinė reikšmė" + +msgid "Invalid geometry type." +msgstr "Netinkamas geometrinis tipas" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "Įvyko klaida pertvarkant geometrijos lauko SRID geometriją." + +msgid "Delete all Features" +msgstr "Pašalinti visas ypatybes" + +msgid "Debugging window (serialized value)" +msgstr "Derinimo langas (serijomis išdėstytos reikšmės)" + +msgid "No feeds are registered." +msgstr "Nėra užregistruotų srautų." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Adresas %r neregistruotas." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/lv/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/lv/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c154ca5 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/lv/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/lv/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/lv/LC_MESSAGES/django.po new file mode 100644 index 0000000..37565d0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/lv/LC_MESSAGES/django.po @@ -0,0 +1,87 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Edgars Voroboks , 2019 +# peterisb , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Edgars Voroboks , 2019\n" +"Language-Team: Latvian (http://app.transifex.com/django/django/language/" +"lv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lv\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : " +"2);\n" + +msgid "GIS" +msgstr "ĢIS" + +msgid "The base GIS field." +msgstr "ĢIS bāzes lauks." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Bāzes Ģeometrijas lauks -- atbilst OpenGIS specifikācijas Geometry tipam." + +msgid "Point" +msgstr "Punkts" + +msgid "Line string" +msgstr "Līniju virkne" + +msgid "Polygon" +msgstr "Daudzstūris" + +msgid "Multi-point" +msgstr "Vairāki punkti" + +msgid "Multi-line string" +msgstr "Vairāku rindu virkne" + +msgid "Multi polygon" +msgstr "Vairāki daudzstūri" + +msgid "Geometry collection" +msgstr "Ģeometrijas kolekcija" + +msgid "Extent Aggregate Field" +msgstr "Apjoma agregācijas lauks" + +msgid "Raster Field" +msgstr "Rastra lauks" + +msgid "No geometry value provided." +msgstr "Nav norādīta ģeometrijas vērtība." + +msgid "Invalid geometry value." +msgstr "Nekorekta ģeometrijas vērtība." + +msgid "Invalid geometry type." +msgstr "Nekorekts ģeometrijas tips." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Sastapta kļūda, pārveidojot ģeometriju uz ģeometriskās formas lauka SRID." + +msgid "Delete all Features" +msgstr "Dzēst visus objektus" + +msgid "Debugging window (serialized value)" +msgstr "Atkļūdošanas logs (serializēta vērtība)" + +msgid "No feeds are registered." +msgstr "Nav reģistrētu barotņu." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Vienkāršotais nosaukums %r nav reģistrēts." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/mk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/mk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ff5e5c3 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/mk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/mk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/mk/LC_MESSAGES/django.po new file mode 100644 index 0000000..03934c6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/mk/LC_MESSAGES/django.po @@ -0,0 +1,91 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# dekomote , 2015 +# Jannis Leidel , 2011 +# Mariusz Felisiak , 2023 +# Vasil Vangelovski , 2016 +# Vasil Vangelovski , 2014 +# Vasil Vangelovski , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Mariusz Felisiak , 2023\n" +"Language-Team: Macedonian (http://app.transifex.com/django/django/language/" +"mk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mk\n" +"Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n" + +msgid "GIS" +msgstr "ГИС" + +msgid "The base GIS field." +msgstr "Базичното ГИС поле." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Базичното геметриско поле — мапира директно на геометриско поле од OpenGIS " +"спецификацијата." + +msgid "Point" +msgstr "Точка" + +msgid "Line string" +msgstr "Линиска нишка" + +msgid "Polygon" +msgstr "Полигон" + +msgid "Multi-point" +msgstr "Повеќе точки" + +msgid "Multi-line string" +msgstr "Повеќе-линиска нишка" + +msgid "Multi polygon" +msgstr "Повеќе полигони" + +msgid "Geometry collection" +msgstr "Колекција од геометриски објекти" + +msgid "Extent Aggregate Field" +msgstr "Поле за агрегација по плоштина или периметар" + +msgid "Raster Field" +msgstr "Растер поле" + +msgid "No geometry value provided." +msgstr "Не е внесена геометриска вредност." + +msgid "Invalid geometry value." +msgstr "Невалидна геометриска вредност." + +msgid "Invalid geometry type." +msgstr "Невалиден геометриски тип." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Се појави грешка при трансформација на геометриската вредност во SRID од " +"геометриското поле" + +msgid "Delete all Features" +msgstr "Избриши ги сите карактеристики" + +msgid "Debugging window (serialized value)" +msgstr "Прозор за дебагирање (серијализирана вредност)" + +msgid "No feeds are registered." +msgstr "Нема регистрирани фидови." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Краткото име (slug) %r не е регистрирано" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ml/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ml/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8972f2a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ml/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ml/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ml/LC_MESSAGES/django.po new file mode 100644 index 0000000..ad8251e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ml/LC_MESSAGES/django.po @@ -0,0 +1,88 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Aby Thomas , 2014 +# Jannis Leidel , 2011 +# Rajeesh Nair , 2011-2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Malayalam (http://www.transifex.com/django/django/language/" +"ml/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ml\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "ജി.ഐ.എസ്" + +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "ബിന്ദു" + +msgid "Line string" +msgstr "രേഖാ സ്ട്രിങ്ങ്" + +msgid "Polygon" +msgstr "ബഹുഭുജം" + +msgid "Multi-point" +msgstr "ബഹുബിന്ദു" + +msgid "Multi-line string" +msgstr "ബഹു രേഖാ സ്ട്രിങ്ങ്" + +msgid "Multi polygon" +msgstr "ബഹു ബഹുഭുജം" + +msgid "Geometry collection" +msgstr "ജ്യാമിതി ശേഖരം" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "ജ്യാമിതീയ മൂല്യമൊന്നും തന്നിട്ടില്ല." + +msgid "Invalid geometry value." +msgstr "തെറ്റായ ജ്യാമിതീയ മൂല്യം." + +msgid "Invalid geometry type." +msgstr "തെറ്റായ തരം ജ്യാമിതി." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"ജ്യാമിതീയ രൂപത്തെ ജ്യാമിതി കളത്തിന്റെ SRID-ലേക്കു മാറ്റുമ്പോള്‍ എന്തോ തകരാറു സംഭവിച്ചിട്ടുണ്ട്." + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr " ഫീഡുകളൊന്നും രജിസ്റ്റര്‍ ചെയ്തിട്ടില്ല." + +#, python-format +msgid "Slug %r isn't registered." +msgstr "%r എന്ന സ്ലഗ് രജിസ്റ്റര്‍ ചെയ്തിട്ടില്ല." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/mn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/mn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2ebb08f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/mn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/mn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/mn/LC_MESSAGES/django.po new file mode 100644 index 0000000..83403a4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/mn/LC_MESSAGES/django.po @@ -0,0 +1,91 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Baskhuu Lodoikhuu , 2011 +# Jannis Leidel , 2011 +# Mariusz Felisiak , 2023 +# Zorig, 2014,2016 +# Анхбаяр Анхаа , 2011-2012,2015 +# Баясгалан Цэвлээ , 2011,2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Mariusz Felisiak , 2023\n" +"Language-Team: Mongolian (http://app.transifex.com/django/django/language/" +"mn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "Газар зүйн мэдээлэл" + +msgid "The base GIS field." +msgstr "Ерөнхий GIS талбар" + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Үндсэн Geometry талбар — OpenGIS газрын зургын Геометрын дүрсны онцгой " +"төрөлтэй байна." + +msgid "Point" +msgstr "Цэг" + +msgid "Line string" +msgstr "Тэмдэгт мөр" + +msgid "Polygon" +msgstr "Олон өнцөгт" + +msgid "Multi-point" +msgstr "Олон цэг" + +msgid "Multi-line string" +msgstr "Олон мөр бүхий тэмтэгт мөр" + +msgid "Multi polygon" +msgstr "Олон өнцөгтийн олонлог" + +msgid "Geometry collection" +msgstr "Дүрсний цуглуулга" + +msgid "Extent Aggregate Field" +msgstr "Aggregate талбарыг өргөтгөх" + +msgid "Raster Field" +msgstr "Растер талбар" + +msgid "No geometry value provided." +msgstr "Дүрс оруулаагүй байна." + +msgid "Invalid geometry value." +msgstr "Буруу дүрс байна." + +msgid "Invalid geometry type." +msgstr "Дүрсийн төрөл буруу байна." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"An error occurred when transforming the geometry to the SRID дүрсний форм " +"талбарын SRID утгыг хөрвүүлэхэд алдаа гарлаа." + +msgid "Delete all Features" +msgstr "Бүх онцлогүүдыг устгах" + +msgid "Debugging window (serialized value)" +msgstr "Шинжлэх цонх (дугаарлагдсан утга) " + +msgid "No feeds are registered." +msgstr "Бүртгэгдсэн feeds байхгүй байна." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "%r слаг бүгтгэгдээгүй байна" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/mr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/mr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0fc4a9c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/mr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/mr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/mr/LC_MESSAGES/django.po new file mode 100644 index 0000000..83ef357 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/mr/LC_MESSAGES/django.po @@ -0,0 +1,80 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-03-18 09:16+0100\n" +"PO-Revision-Date: 2015-03-18 08:35+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Marathi (http://www.transifex.com/projects/p/django/language/" +"mr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mr\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "" + +msgid "Line string" +msgstr "" + +msgid "Polygon" +msgstr "" + +msgid "Multi-point" +msgstr "" + +msgid "Multi-line string" +msgstr "" + +msgid "Multi polygon" +msgstr "" + +msgid "Geometry collection" +msgstr "" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "" + +msgid "Invalid geometry value." +msgstr "" + +msgid "Invalid geometry type." +msgstr "" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Google Maps via GeoDjango" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "" + +#, python-format +msgid "Slug %r isn't registered." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ms/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ms/LC_MESSAGES/django.mo new file mode 100644 index 0000000..63a382e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ms/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ms/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ms/LC_MESSAGES/django.po new file mode 100644 index 0000000..756ca99 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ms/LC_MESSAGES/django.po @@ -0,0 +1,84 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jafry Hisham, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Jafry Hisham, 2021\n" +"Language-Team: Malay (http://app.transifex.com/django/django/language/ms/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ms\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Medan asas GIS" + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Medan asas geometri - disuaikan ke jenis Spesifikasi Geometri OpenGIS ." + +msgid "Point" +msgstr "Titik" + +msgid "Line string" +msgstr "Rentetan baris" + +msgid "Polygon" +msgstr "Polygon" + +msgid "Multi-point" +msgstr "Berbilang-titik" + +msgid "Multi-line string" +msgstr "Rentetan berbilang-baris" + +msgid "Multi polygon" +msgstr "Berbilang polygon" + +msgid "Geometry collection" +msgstr "Koleksi geometri" + +msgid "Extent Aggregate Field" +msgstr "Medan Agregat Takat" + +msgid "Raster Field" +msgstr "Medan Raster" + +msgid "No geometry value provided." +msgstr "Tiada nilai geometri diberikan." + +msgid "Invalid geometry value." +msgstr "Nilai geometri tidak sah." + +msgid "Invalid geometry type." +msgstr "Jenis geometri tidak sah." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Ralat telah berlaku semasa mengubah geometri kepada SRID geometri medan " +"borang." + +msgid "Delete all Features" +msgstr "Hapuskan semua Ciri-cri" + +msgid "Debugging window (serialized value)" +msgstr "Tingkap penyahpijatan (nilai bersiri)" + +msgid "No feeds are registered." +msgstr "Tiada feed didaftarkan." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Slug %r tidak didaftarkan." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/my/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/my/LC_MESSAGES/django.mo new file mode 100644 index 0000000..443434b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/my/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/my/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/my/LC_MESSAGES/django.po new file mode 100644 index 0000000..3fbc0ee --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/my/LC_MESSAGES/django.po @@ -0,0 +1,85 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Yhal Htet Aung , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-20 03:01+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Burmese (http://www.transifex.com/django/django/language/" +"my/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: my\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "GIS" +msgstr "ဂျီအိုင်အက်စ်" + +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "" + +msgid "Line string" +msgstr "" + +msgid "Polygon" +msgstr "" + +msgid "Multi-point" +msgstr "" + +msgid "Multi-line string" +msgstr "" + +msgid "Multi polygon" +msgstr "" + +msgid "Geometry collection" +msgstr "" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "" + +msgid "Invalid geometry value." +msgstr "" + +msgid "Invalid geometry type." +msgstr "" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "" + +#, python-format +msgid "Slug %r isn't registered." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/nb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/nb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4220ad8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/nb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/nb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/nb/LC_MESSAGES/django.po new file mode 100644 index 0000000..e347e78 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/nb/LC_MESSAGES/django.po @@ -0,0 +1,88 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# jensadne , 2014 +# Jon, 2015 +# Jon, 2020 +# Jon, 2011-2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Jon, 2020\n" +"Language-Team: Norwegian Bokmål (http://app.transifex.com/django/django/" +"language/nb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "GIS-basefeltet." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Geometry-basefeltet - tilordnes til OpenGIS Specification Geometry-typen." + +msgid "Point" +msgstr "Punkt" + +msgid "Line string" +msgstr "Linje-string" + +msgid "Polygon" +msgstr "Polygon" + +msgid "Multi-point" +msgstr "Multipunkt" + +msgid "Multi-line string" +msgstr "Multilinje-string" + +msgid "Multi polygon" +msgstr "Multi-polygon" + +msgid "Geometry collection" +msgstr "Geometri-samling" + +msgid "Extent Aggregate Field" +msgstr "Extent Aggregate-felt" + +msgid "Raster Field" +msgstr "Raster-felt" + +msgid "No geometry value provided." +msgstr "Ingen geometriverdi oppgitt." + +msgid "Invalid geometry value." +msgstr "Ugyldig geometriverdi" + +msgid "Invalid geometry type." +msgstr "Ugyldig geometritype" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"En feil oppstod ved transformering av geometrien til SRID fra geometrifeltet." + +msgid "Delete all Features" +msgstr "Slett alle Features" + +msgid "Debugging window (serialized value)" +msgstr "Debugging-vindu (serialisert verdi)" + +msgid "No feeds are registered." +msgstr "Ingen feeds er registrert." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Slug %r er ikke registrert." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ne/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ne/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9ebdb54 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ne/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ne/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ne/LC_MESSAGES/django.po new file mode 100644 index 0000000..07e9468 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ne/LC_MESSAGES/django.po @@ -0,0 +1,84 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Sagar Chalise , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Nepali (http://www.transifex.com/django/django/language/ne/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ne\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "बिन्दु" + +msgid "Line string" +msgstr "" + +msgid "Polygon" +msgstr "बहुभुज" + +msgid "Multi-point" +msgstr "" + +msgid "Multi-line string" +msgstr "" + +msgid "Multi polygon" +msgstr "" + +msgid "Geometry collection" +msgstr "ज्यामिति संकलन" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "ज्यामिति मान उपलब्ध छैन ।" + +msgid "Invalid geometry value." +msgstr "उनुपयुक्त ज्यामिति मान" + +msgid "Invalid geometry type." +msgstr "उनुपयुक्त ज्यामिति प्रकार" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "" + +#, python-format +msgid "Slug %r isn't registered." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/nl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/nl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4ad8805 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/nl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/nl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/nl/LC_MESSAGES/django.po new file mode 100644 index 0000000..cace53f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/nl/LC_MESSAGES/django.po @@ -0,0 +1,91 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Blue , 2011 +# Harro van der Klauw , 2012 +# Ilja Maas , 2015 +# Jannis Leidel , 2011 +# 6a27f10aef159701c7a5ff07f0fb0a78_05545ed , 2011 +# 8de006b1b0894aab6aef71979dcd8bd6_5c6b207 , 2015 +# Tonnes , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Tonnes , 2019\n" +"Language-Team: Dutch (http://app.transifex.com/django/django/language/nl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Het basis-GIS-veld." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Het basis-Geometrie-veld – correspondeert met het Geometrie-type van de " +"OpenGIS-specificatie." + +msgid "Point" +msgstr "Punt" + +msgid "Line string" +msgstr "Tekenreeks" + +msgid "Polygon" +msgstr "Polygoon" + +msgid "Multi-point" +msgstr "Multipunt" + +msgid "Multi-line string" +msgstr "Multi-tekenreeks" + +msgid "Multi polygon" +msgstr "Multi-polygoon" + +msgid "Geometry collection" +msgstr "Geometrie-verzameling" + +msgid "Extent Aggregate Field" +msgstr "Gebieds-aggregatieveld" + +msgid "Raster Field" +msgstr "Rasterveld" + +msgid "No geometry value provided." +msgstr "Geen geometriewaarde opgegeven." + +msgid "Invalid geometry value." +msgstr "Ongeldige geometriewaarde." + +msgid "Invalid geometry type." +msgstr "Ongeldig geometrietype." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Er is een fout opgetreden bij het omvormen van de geometrie naar de SRID van " +"het geometrieveld." + +msgid "Delete all Features" +msgstr "Alle kenmerken verwijderen" + +msgid "Debugging window (serialized value)" +msgstr "Debugvenster (geserialiseerde waarde)" + +msgid "No feeds are registered." +msgstr "Er zijn geen feeds geregistreerd." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Slug %r is niet geregistreerd." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/nn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/nn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0676ecd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/nn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/nn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/nn/LC_MESSAGES/django.po new file mode 100644 index 0000000..fcb77a6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/nn/LC_MESSAGES/django.po @@ -0,0 +1,87 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Sivert Olstad, 2021 +# Vibeke Uthaug, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Vibeke Uthaug, 2021\n" +"Language-Team: Norwegian Nynorsk (http://app.transifex.com/django/django/" +"language/nn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "GIS-basefeltet" + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Geometry-basefeltet - tilordnes til OpenGIS Specification Geometry-typen." + +msgid "Point" +msgstr "Punkt" + +msgid "Line string" +msgstr "Linjestreng" + +msgid "Polygon" +msgstr "Polygon" + +msgid "Multi-point" +msgstr "Fleirpunkt" + +msgid "Multi-line string" +msgstr "Fleirlinje-streng" + +msgid "Multi polygon" +msgstr "Multi-polygon" + +msgid "Geometry collection" +msgstr "Geometrisamling" + +msgid "Extent Aggregate Field" +msgstr "Extent Aggregate-felt" + +msgid "Raster Field" +msgstr "Raster-felt" + +msgid "No geometry value provided." +msgstr "Ingen geometriverdi oppgjeve." + +msgid "Invalid geometry value." +msgstr "Ugyldig geometriverdi." + +msgid "Invalid geometry type." +msgstr "Ugyldig geometritype." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Det oppstod ein feil ved transformering av geometrien til SRID frå " +"geometrifeltet." + +msgid "Delete all Features" +msgstr "Slett alle Features" + +msgid "Debugging window (serialized value)" +msgstr "Feilsøking-vindauge (serialisert verdi)" + +msgid "No feeds are registered." +msgstr "Ingen feeds er registrert." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Slug %r er ikkje registrert." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/os/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/os/LC_MESSAGES/django.mo new file mode 100644 index 0000000..47f4a0f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/os/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/os/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/os/LC_MESSAGES/django.po new file mode 100644 index 0000000..65c7267 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/os/LC_MESSAGES/django.po @@ -0,0 +1,87 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Soslan Khubulov , 2013 +# Soslan Khubulov , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Ossetic (http://www.transifex.com/django/django/language/" +"os/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: os\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "Стъӕлф" + +msgid "Line string" +msgstr "Хаахы рӕнхъ" + +msgid "Polygon" +msgstr "Бирӕкъуымон" + +msgid "Multi-point" +msgstr "Бирӕ-стъӕлф" + +msgid "Multi-line string" +msgstr "Бирӕ-хаххы рӕнхъ" + +msgid "Multi polygon" +msgstr "Бирӕ бирӕкъуымон" + +msgid "Geometry collection" +msgstr "Геометриты ӕмбырд" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "Геометрийы бӕрц амынд нӕу." + +msgid "Invalid geometry value." +msgstr "Геометрийы бӕрц раст нӕу." + +msgid "Invalid geometry type." +msgstr "Геометрийы хуыз раст нӕу." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Рӕдыд ӕрцыд SRID геометри формӕйы бынаты геометримӕ ивд куы цыдис, уӕд." + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "Ницы лӕсӕн уыд регистрацигонд." + +#, python-format +msgid "Slug %r isn't registered." +msgstr "Слаг %r регистрацигонд нӕу." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/pa/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/pa/LC_MESSAGES/django.mo new file mode 100644 index 0000000..cc74c58 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/pa/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/pa/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/pa/LC_MESSAGES/django.po new file mode 100644 index 0000000..544c783 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/pa/LC_MESSAGES/django.po @@ -0,0 +1,86 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# A S Alam , 2013 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Panjabi (Punjabi) (http://www.transifex.com/django/django/" +"language/pa/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pa\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "ਪੁਆਇੰਟ" + +msgid "Line string" +msgstr "ਲਾਈਨ ਸਤਰ" + +msgid "Polygon" +msgstr "ਬਹੁਭੁਜ" + +msgid "Multi-point" +msgstr "ਕਈ-ਪੁਆਇੰਟ" + +msgid "Multi-line string" +msgstr "" + +msgid "Multi polygon" +msgstr "ਮਲਟੀ ਬਹੁ-ਭੁਜ" + +msgid "Geometry collection" +msgstr "ਜੁਮੈਟਰੀ ਭੰਡਾਰ" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "ਕੋਈ ਜੁਮੈਟਰੀ ਮੁੱਲ ਨਹੀਂ ਦਿੱਤਾ ਗਿਆ।" + +msgid "Invalid geometry value." +msgstr "ਗਲਤ ਜੁਮੈਟਰੀ ਮੁੱਲ।" + +msgid "Invalid geometry type." +msgstr "ਗਲਤ ਜੁਮੈਟਰੀ ਕਿਸਮ।" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "ਕੋਈ ਫੀਡ ਰਜਿਸਟਰ ਨਹੀਂ ਹੈ।" + +#, python-format +msgid "Slug %r isn't registered." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/pl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/pl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5f15e70 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/pl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/pl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/pl/LC_MESSAGES/django.po new file mode 100644 index 0000000..6c3efec --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/pl/LC_MESSAGES/django.po @@ -0,0 +1,92 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# angularcircle, 2012 +# Jannis Leidel , 2011 +# Janusz Harkot , 2015 +# Piotr Jakimiak , 2015 +# Maciej Olko , 2019 +# Maciej Olko , 2015 +# Mattia Procopio , 2014 +# Tomasz Kajtoch , 2016-2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Maciej Olko , 2019\n" +"Language-Team: Polish (http://app.transifex.com/django/django/language/pl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pl\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && " +"(n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && " +"n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Pole bazowe GIS." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "Pole bazowe Geometrii — mapowane na typ Geometry specyfikacji OpenGIS." + +msgid "Point" +msgstr "Punkt" + +msgid "Line string" +msgstr "Ścieżka" + +msgid "Polygon" +msgstr "Wielokąt" + +msgid "Multi-point" +msgstr "Zbiór punktów" + +msgid "Multi-line string" +msgstr "Zbiór ścieżek" + +msgid "Multi polygon" +msgstr "Zbiór wielokątów" + +msgid "Geometry collection" +msgstr "Zbiór geometrii" + +msgid "Extent Aggregate Field" +msgstr "Pole Zasięgu Agregacji" + +msgid "Raster Field" +msgstr "Pole Rastrowe" + +msgid "No geometry value provided." +msgstr "Brak wartości geometrii." + +msgid "Invalid geometry value." +msgstr "Błędna wartość geometrii." + +msgid "Invalid geometry type." +msgstr "Błędny typ geometrii." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Wystąpił błąd podczas przekształcania geometrii do SRID pola formularza " +"geometrii." + +msgid "Delete all Features" +msgstr "Usuń wszystkie Elementy" + +msgid "Debugging window (serialized value)" +msgstr "Okno debugowania (wartość zserializowana)" + +msgid "No feeds are registered." +msgstr "Brak zarejestrowanych kanałów informacyjnych." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Slug %r nie jest zarejestrowany." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/pt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/pt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..709f372 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/pt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/pt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/pt/LC_MESSAGES/django.po new file mode 100644 index 0000000..c4c1e12 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/pt/LC_MESSAGES/django.po @@ -0,0 +1,95 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Claudio Fernandes , 2015 +# Jannis Leidel , 2011 +# jorgecarleitao , 2015 +# Manuela Silva , 2015 +# Nuno Mariz , 2011-2012,2015 +# Paulo Köch , 2011 +# Raúl Pedro Fernandes Santos, 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Portuguese (http://www.transifex.com/django/django/language/" +"pt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "SIG" + +msgid "The base GIS field." +msgstr "O campo GIS base." + +msgid "" +"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +msgstr "" +"O campo de Geometria base -- mapeia para o tipo de Geometria de " +"Especificação do OpenGIS." + +msgid "Point" +msgstr "Ponto" + +msgid "Line string" +msgstr "Linha" + +msgid "Polygon" +msgstr "Polígono" + +msgid "Multi-point" +msgstr "Multi-ponto" + +msgid "Multi-line string" +msgstr "Multi-linha" + +msgid "Multi polygon" +msgstr "Multi-polígono" + +msgid "Geometry collection" +msgstr "Coleção geométrica" + +msgid "Extent Aggregate Field" +msgstr "Extender Campo Agregado" + +msgid "Raster Field" +msgstr "Campo Raster" + +msgid "No geometry value provided." +msgstr "Não foi submetido nenhum valor do tipo geometria." + +msgid "Invalid geometry value." +msgstr "Valor inválido de geometria." + +msgid "Invalid geometry type." +msgstr "Tipo inválido de geometria." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Ocorreu um erro na transformação da geometria para o SRID da geometria do " +"campo do formulário." + +msgid "Delete all Features" +msgstr "Eliminar todas as Caraterísticas" + +msgid "WKT debugging window:" +msgstr "Janela de depuração de WKT:" + +msgid "Debugging window (serialized value)" +msgstr "Janela de depuração (valor serializado)" + +msgid "No feeds are registered." +msgstr "Nenhum feed está registado." + +#, python-format +msgid "Slug %r isn't registered." +msgstr "O slug %r não está registado." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/pt_BR/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/pt_BR/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3ea91a5 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/pt_BR/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/pt_BR/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/pt_BR/LC_MESSAGES/django.po new file mode 100644 index 0000000..d807a0b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/pt_BR/LC_MESSAGES/django.po @@ -0,0 +1,94 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Allisson Azevedo , 2014 +# Carlos E C Leite - Cadu , 2015-2016,2019 +# Eduardo Cereto Carvalho, 2011 +# semente, 2012 +# Jannis Leidel , 2011 +# Lucas Infante , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-10-09 16:09+0000\n" +"Last-Translator: Carlos E C Leite - Cadu \n" +"Language-Team: Portuguese (Brazil) (http://www.transifex.com/django/django/" +"language/pt_BR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt_BR\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "O campo GIS base." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"O campo Geometry básico - aponta para o tipo OpenGis Specification " +"Geometry. " + +msgid "Point" +msgstr "Ponto" + +msgid "Line string" +msgstr "Linha string" + +msgid "Polygon" +msgstr "Polígono" + +msgid "Multi-point" +msgstr "Multiponto" + +msgid "Multi-line string" +msgstr "Multilinha string" + +msgid "Multi polygon" +msgstr "Multipolígono" + +msgid "Geometry collection" +msgstr "Coleção geométrica" + +msgid "Extent Aggregate Field" +msgstr "Campo agregado extendido" + +msgid "Raster Field" +msgstr "Campo Raster." + +msgid "No geometry value provided." +msgstr "Nenhum valor geométrico fornecido." + +msgid "Invalid geometry value." +msgstr "Valor geométrico inválido." + +msgid "Invalid geometry type." +msgstr "Tipo geométrico inválido." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Ocorreu um erro ao transformar a geometria para o SRID do campo de " +"formulário de geometria." + +msgid "Delete all Features" +msgstr "Deletar todas os elementos" + +msgid "WKT debugging window:" +msgstr "Janela de debug WKT" + +msgid "Debugging window (serialized value)" +msgstr "Janela de debug (valor seralizado)" + +msgid "No feeds are registered." +msgstr "Nenhum feed foi registrado." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "O Slug %r não está registrado." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ro/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ro/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d5bfb30 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ro/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ro/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ro/LC_MESSAGES/django.po new file mode 100644 index 0000000..ae9d157 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ro/LC_MESSAGES/django.po @@ -0,0 +1,89 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bogdan Mateescu, 2019 +# Daniel Ursache-Dogariu, 2011 +# Denis Darii , 2011,2014 +# Eugenol Man , 2020 +# Razvan Stefanescu , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Eugenol Man , 2020\n" +"Language-Team: Romanian (http://app.transifex.com/django/django/language/" +"ro/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ro\n" +"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?" +"2:1));\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Câmpul GIS de bază." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "Punct" + +msgid "Line string" +msgstr "Șir linii" + +msgid "Polygon" +msgstr "Poligon" + +msgid "Multi-point" +msgstr "Multi-punct" + +msgid "Multi-line string" +msgstr "Șir multi-linie" + +msgid "Multi polygon" +msgstr "Multi poligon" + +msgid "Geometry collection" +msgstr "Colecție geometrie" + +msgid "Extent Aggregate Field" +msgstr "Câmp agregat extins" + +msgid "Raster Field" +msgstr "Câmp raster" + +msgid "No geometry value provided." +msgstr "Nicio valoare geometrică furnizată." + +msgid "Invalid geometry value." +msgstr "Valoare geometrică nevalidă." + +msgid "Invalid geometry type." +msgstr "Tip geometric nevalid." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"A avut loc o eroare la transformarea geometriei în SRID-ul câmpului " +"geometric al formularului." + +msgid "Delete all Features" +msgstr "Șterge toate Entitățile" + +msgid "Debugging window (serialized value)" +msgstr "Fereastra de depanare (valoare serializată)" + +msgid "No feeds are registered." +msgstr "Nici un feed registrat." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Slug %r nu este înregistrat." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ru/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ru/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1f92476 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ru/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ru/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ru/LC_MESSAGES/django.po new file mode 100644 index 0000000..1674643 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ru/LC_MESSAGES/django.po @@ -0,0 +1,91 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Eugene , 2012 +# eXtractor , 2015 +# crazyzubr , 2020 +# Jannis Leidel , 2011 +# Алексей Борискин , 2012,2014-2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: crazyzubr , 2020\n" +"Language-Team: Russian (http://app.transifex.com/django/django/language/" +"ru/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ru\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || " +"(n%100>=11 && n%100<=14)? 2 : 3);\n" + +msgid "GIS" +msgstr "ГИС" + +msgid "The base GIS field." +msgstr "Базовое ГИС-поле." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Базовое геометрическое поле. Соответствует типу OpenGIS Specification " +"Geometry." + +msgid "Point" +msgstr "Точка" + +msgid "Line string" +msgstr "Ломаная" + +msgid "Polygon" +msgstr "Многоугольник" + +msgid "Multi-point" +msgstr "Набор точек" + +msgid "Multi-line string" +msgstr "Набор ломаных" + +msgid "Multi polygon" +msgstr "Набор многоугольников" + +msgid "Geometry collection" +msgstr "Набор геометрических объектов" + +msgid "Extent Aggregate Field" +msgstr "Поле, агрегирующее площадь или объём" + +msgid "Raster Field" +msgstr "Растровое поле" + +msgid "No geometry value provided." +msgstr "Не указано значение геометрии." + +msgid "Invalid geometry value." +msgstr "Неверное значение геометрии." + +msgid "Invalid geometry type." +msgstr "Неверный тип геометрического объекта." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Произошла ошибка во время преобразования геометрического объекта в SRID." + +msgid "Delete all Features" +msgstr "Удалить все объекты" + +msgid "Debugging window (serialized value)" +msgstr "Отладочное окно (сериализованные значения)" + +msgid "No feeds are registered." +msgstr "Нет зарегистрированных фидов." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Слаг %r не зарегистрирован." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9a6c2f5 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sk/LC_MESSAGES/django.po new file mode 100644 index 0000000..5a6c87c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sk/LC_MESSAGES/django.po @@ -0,0 +1,86 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# 18f25ad6fa9930fc67cb11aca9d16a27, 2012 +# Marian Andre , 2015,2017 +# Martin Tóth , 2017,2023 +# Štefan Lučivjanský , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Martin Tóth , 2017,2023\n" +"Language-Team: Slovak (http://app.transifex.com/django/django/language/sk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n " +">= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Základné GIS pole." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "Základné pole Geometry — mapuje na typ OpenGIS Specification Geometry." + +msgid "Point" +msgstr "Bod" + +msgid "Line string" +msgstr "Čiara" + +msgid "Polygon" +msgstr "Polygón" + +msgid "Multi-point" +msgstr "Viacero bodov" + +msgid "Multi-line string" +msgstr "Viacero čiar" + +msgid "Multi polygon" +msgstr "Viacero polygónov" + +msgid "Geometry collection" +msgstr "Goemetrická kolekcia" + +msgid "Extent Aggregate Field" +msgstr "Rozšírené agregátne pole" + +msgid "Raster Field" +msgstr "Rastrové Pole" + +msgid "No geometry value provided." +msgstr "Nie je zadaná žiadna geometrická hodnota." + +msgid "Invalid geometry value." +msgstr "Chybná geometrická hodnota." + +msgid "Invalid geometry type." +msgstr "Chybný geometrický typ." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "Nastala chyba pri prevode geometrie do SRID z formulárového poľa." + +msgid "Delete all Features" +msgstr "Odstrániť všetky vlastnosti" + +msgid "Debugging window (serialized value)" +msgstr "Ladiace okno (serializovaná hodnota)" + +msgid "No feeds are registered." +msgstr "Žiadne kanály nie sú registrované." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Identifikátor %r nie je registrovaný." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b19dd7f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sl/LC_MESSAGES/django.po new file mode 100644 index 0000000..e4551dd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sl/LC_MESSAGES/django.po @@ -0,0 +1,89 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Mariusz Felisiak , 2023 +# Primoz Verdnik , 2017 +# zejn , 2016 +# zejn , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Mariusz Felisiak , 2023\n" +"Language-Team: Slovenian (http://app.transifex.com/django/django/language/" +"sl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sl\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || " +"n%100==4 ? 2 : 3);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Osnovno GIS polje" + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "Osnovno polje GIS — se preslika v vrsto Geometry po določilih OpenGIS." + +msgid "Point" +msgstr "Točka" + +msgid "Line string" +msgstr "Črtni niz" + +msgid "Polygon" +msgstr "Mnogokotnik" + +msgid "Multi-point" +msgstr "Več-točkovi predmet" + +msgid "Multi-line string" +msgstr "Več črtni niz" + +msgid "Multi polygon" +msgstr "Večkratni mnogokotnikov" + +msgid "Geometry collection" +msgstr "Zbirka likov" + +msgid "Extent Aggregate Field" +msgstr "Polje z agregiranim območjem" + +msgid "Raster Field" +msgstr "Rastersko polje" + +msgid "No geometry value provided." +msgstr "Ni navedene geometrijske vrednosti." + +msgid "Invalid geometry value." +msgstr "Neveljavna geometrijska vrednost." + +msgid "Invalid geometry type." +msgstr "Neveljavna vrsta geometrije." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Med pretvarjanjem geometrijskega zapisa v SRID geometrijskega polja je " +"prišlo do napake." + +msgid "Delete all Features" +msgstr "Pobriši vse atribute" + +msgid "Debugging window (serialized value)" +msgstr "Okno za razhroščevanje (serializirana vrednost)" + +msgid "No feeds are registered." +msgstr "Ni vpisanih virov." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Okrajšava %r ni vpisana." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sq/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sq/LC_MESSAGES/django.mo new file mode 100644 index 0000000..caf727f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sq/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sq/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sq/LC_MESSAGES/django.po new file mode 100644 index 0000000..42cf2e9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sq/LC_MESSAGES/django.po @@ -0,0 +1,85 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Besnik Bleta , 2011,2015 +# Besnik Bleta , 2015,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Besnik Bleta , 2015,2019\n" +"Language-Team: Albanian (http://app.transifex.com/django/django/language/" +"sq/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sq\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Fusha GIS bazë." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "Pikë" + +msgid "Line string" +msgstr "Varg vije" + +msgid "Polygon" +msgstr "Shumëkëndësh" + +msgid "Multi-point" +msgstr "Multi-pika" + +msgid "Multi-line string" +msgstr "Varg multi-vijë" + +msgid "Multi polygon" +msgstr "Multi shumëkëndësh" + +msgid "Geometry collection" +msgstr "Përmbledhje gjeometrie" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "S’u dha vlerë gjeometrie." + +msgid "Invalid geometry value." +msgstr "Vlerë e pavlefshme gjeometrie." + +msgid "Invalid geometry type." +msgstr "Lloj i pavlefshëm gjeometrie." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Ndodhi një gabim gjatë shndërrimit të gjeometrisë në fushë SRID formulari " +"gjeometrie." + +msgid "Delete all Features" +msgstr "Fshiji krejt Veçoritë" + +msgid "Debugging window (serialized value)" +msgstr "Dritare diagnostikimi (vlerë e serializuar)" + +msgid "No feeds are registered." +msgstr "S’ka prurje të regjistruara." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Identifikuesi %r s’është i regjistruar." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3fbf09a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sr/LC_MESSAGES/django.po new file mode 100644 index 0000000..5915452 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sr/LC_MESSAGES/django.po @@ -0,0 +1,87 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Branko Kokanovic , 2018 +# Igor Jerosimić, 2020 +# Jannis Leidel , 2011 +# Janos Guljas , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Igor Jerosimić, 2020\n" +"Language-Team: Serbian (http://app.transifex.com/django/django/language/" +"sr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Основна GIS поља." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Основно геометријско поље - мапира тип геометрије по „OpenGIS“ спецификацији." + +msgid "Point" +msgstr "Тачка" + +msgid "Line string" +msgstr "Линија" + +msgid "Polygon" +msgstr "Полигон" + +msgid "Multi-point" +msgstr "Више тачака" + +msgid "Multi-line string" +msgstr "Више линија" + +msgid "Multi polygon" +msgstr "Више полигона" + +msgid "Geometry collection" +msgstr "Колекција геопметријских облика" + +msgid "Extent Aggregate Field" +msgstr "Проширено збирно поље" + +msgid "Raster Field" +msgstr "Растерско поље" + +msgid "No geometry value provided." +msgstr "Нисте задали параметре за геометрију." + +msgid "Invalid geometry value." +msgstr "Неисправан параметар за геометрију." + +msgid "Invalid geometry type." +msgstr "Непостојећи тип геометрије." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "Грешка се десила током трансформације геометрије на „SRID“ тип поља." + +msgid "Delete all Features" +msgstr "Обриши сва својства" + +msgid "Debugging window (serialized value)" +msgstr "Прозор за отклањање грешака (серијализована вредност)" + +msgid "No feeds are registered." +msgstr "Нема регистрованих фидова." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Слаг %r није регистрован." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sr_Latn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sr_Latn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..baff02a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sr_Latn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sr_Latn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sr_Latn/LC_MESSAGES/django.po new file mode 100644 index 0000000..8ab0744 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sr_Latn/LC_MESSAGES/django.po @@ -0,0 +1,87 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Igor Jerosimić, 2019-2020 +# Jannis Leidel , 2011 +# Janos Guljas , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Igor Jerosimić, 2019-2020\n" +"Language-Team: Serbian (Latin) (http://app.transifex.com/django/django/" +"language/sr@latin/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr@latin\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Osnovno GIS polje." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Osnovno geometrijsko polje -- mapira tip geometrije po \"OpenGIS\" " +"specifikaciji." + +msgid "Point" +msgstr "Tačka" + +msgid "Line string" +msgstr "Linija" + +msgid "Polygon" +msgstr "Poligon" + +msgid "Multi-point" +msgstr "Više tačaka" + +msgid "Multi-line string" +msgstr "Više linija" + +msgid "Multi polygon" +msgstr "Više poligona" + +msgid "Geometry collection" +msgstr "Kolekcija geopmetrijskih oblika" + +msgid "Extent Aggregate Field" +msgstr "Prošireno zbirno polje" + +msgid "Raster Field" +msgstr "Rastersko polje" + +msgid "No geometry value provided." +msgstr "Niste zadali parametre za geometriju." + +msgid "Invalid geometry value." +msgstr "Neispravan parametar za geometriju." + +msgid "Invalid geometry type." +msgstr "Nepostojeći tip geometrije." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "Greška se desila tokom transformacije geometrije na „SRID“ tip polja." + +msgid "Delete all Features" +msgstr "Obriši sva svojstva" + +msgid "Debugging window (serialized value)" +msgstr "Prozor za otklanjanje grešaka (serijalizovana vrednost)" + +msgid "No feeds are registered." +msgstr "Nema registrovanih fidova." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Slag %r nije registrovan." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sv/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sv/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3a9473d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sv/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sv/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sv/LC_MESSAGES/django.po new file mode 100644 index 0000000..c98dc92 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sv/LC_MESSAGES/django.po @@ -0,0 +1,90 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Albin Larsson , 2022 +# Andreas Pelme , 2011-2012 +# Jannis Leidel , 2011 +# Jonathan Lindén, 2015 +# Jonathan Lindén, 2014 +# Petter Strandmark , 2019 +# Thomas Lundqvist, 2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Albin Larsson , 2022\n" +"Language-Team: Swedish (http://app.transifex.com/django/django/language/" +"sv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sv\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Basklassen för GIS-fält." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Basklassen för geometri-fält -- motsvarar ”Geometry”-typen i OpenGIS-" +"specifikationen." + +msgid "Point" +msgstr "Punkt" + +msgid "Line string" +msgstr "Linjesegment" + +msgid "Polygon" +msgstr "Polygon" + +msgid "Multi-point" +msgstr "Multipunkt" + +msgid "Multi-line string" +msgstr "Multilinjesegment" + +msgid "Multi polygon" +msgstr "Multipolygon" + +msgid "Geometry collection" +msgstr "Geometrisamling" + +msgid "Extent Aggregate Field" +msgstr "Fält för sammanlagd yta" + +msgid "Raster Field" +msgstr "Rasterfält" + +msgid "No geometry value provided." +msgstr "Inget geometriskt värde angivet." + +msgid "Invalid geometry value." +msgstr "Ogiltigt geometrivärde." + +msgid "Invalid geometry type." +msgstr "Ogiltig geometrityp" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "Ett fel uppstod under transformering till SRID:t hos formulärsfältet." + +msgid "Delete all Features" +msgstr "Ta bort alla attribut" + +msgid "Debugging window (serialized value)" +msgstr "Felsökningsfönster (serialiserat värde)" + +msgid "No feeds are registered." +msgstr "Inga flöden är registrerade." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Slugen %r är inte registrerad." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sw/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sw/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1e7ac9f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sw/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sw/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sw/LC_MESSAGES/django.po new file mode 100644 index 0000000..04d75bb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/sw/LC_MESSAGES/django.po @@ -0,0 +1,87 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Machaku , 2013-2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Swahili (http://www.transifex.com/django/django/language/" +"sw/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sw\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "Nukta" + +msgid "Line string" +msgstr "Mstari" + +msgid "Polygon" +msgstr "Poligoni" + +msgid "Multi-point" +msgstr "Nukta zaidi ya moja" + +msgid "Multi-line string" +msgstr "Mstari zaidi ya mmoja. " + +msgid "Multi polygon" +msgstr "Poligoni zaidi ya moja" + +msgid "Geometry collection" +msgstr "Mkusanyiko wa jiometri" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "Hakuna thamani ya jiometri iliyotolewa" + +msgid "Invalid geometry value." +msgstr "Thamani batili ya jiometri." + +msgid "Invalid geometry type." +msgstr "Aina batili ya jiometri." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Hitilafu imetokea wakati wa kubadilisha jiometri kuwa SRID ya sehemu ya fomu " +"ya jiometri." + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "Hakuna mlisho uliosajiliwa." + +#, python-format +msgid "Slug %r isn't registered." +msgstr "Slagi %r haijasajiliwa" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ta/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ta/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7964f32 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ta/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ta/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ta/LC_MESSAGES/django.po new file mode 100644 index 0000000..9c2577c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ta/LC_MESSAGES/django.po @@ -0,0 +1,80 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-03-18 09:16+0100\n" +"PO-Revision-Date: 2015-03-18 08:35+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Tamil (http://www.transifex.com/projects/p/django/language/" +"ta/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ta\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "" + +msgid "Line string" +msgstr "" + +msgid "Polygon" +msgstr "" + +msgid "Multi-point" +msgstr "" + +msgid "Multi-line string" +msgstr "" + +msgid "Multi polygon" +msgstr "" + +msgid "Geometry collection" +msgstr "" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "" + +msgid "Invalid geometry value." +msgstr "" + +msgid "Invalid geometry type." +msgstr "" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Google Maps via GeoDjango" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "" + +#, python-format +msgid "Slug %r isn't registered." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/te/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/te/LC_MESSAGES/django.mo new file mode 100644 index 0000000..20bc7f0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/te/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/te/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/te/LC_MESSAGES/django.po new file mode 100644 index 0000000..0797c2f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/te/LC_MESSAGES/django.po @@ -0,0 +1,84 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Telugu (http://www.transifex.com/django/django/language/te/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: te\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "" + +msgid "Line string" +msgstr "" + +msgid "Polygon" +msgstr "" + +msgid "Multi-point" +msgstr "" + +msgid "Multi-line string" +msgstr "" + +msgid "Multi polygon" +msgstr "" + +msgid "Geometry collection" +msgstr "" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "క్షెత్రగనిత మూల్యము ఇవ్వలెదు." + +msgid "Invalid geometry value." +msgstr "సరికాని క్షేత్రగణిత మూల్యము." + +msgid "Invalid geometry type." +msgstr "సరికాని క్షేత్రగణిత రకం." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "" + +#, python-format +msgid "Slug %r isn't registered." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/tg/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/tg/LC_MESSAGES/django.mo new file mode 100644 index 0000000..257eae1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/tg/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/tg/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/tg/LC_MESSAGES/django.po new file mode 100644 index 0000000..e05714b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/tg/LC_MESSAGES/django.po @@ -0,0 +1,84 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Surush Sufiew , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-05-15 01:08+0000\n" +"Last-Translator: Surush Sufiew \n" +"Language-Team: Tajik (http://www.transifex.com/django/django/language/tg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Майдони асосии GIS" + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "" + +msgid "Line string" +msgstr "" + +msgid "Polygon" +msgstr "" + +msgid "Multi-point" +msgstr "" + +msgid "Multi-line string" +msgstr "" + +msgid "Multi polygon" +msgstr "" + +msgid "Geometry collection" +msgstr "" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "" + +msgid "Invalid geometry value." +msgstr "" + +msgid "Invalid geometry type." +msgstr "Шакли нодурусти геометрӣ" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "" + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/th/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/th/LC_MESSAGES/django.mo new file mode 100644 index 0000000..de8d4c5 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/th/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/th/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/th/LC_MESSAGES/django.po new file mode 100644 index 0000000..40355c2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/th/LC_MESSAGES/django.po @@ -0,0 +1,86 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Kowit Charoenratchatabhan , 2012 +# Vichai Vongvorakul , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Thai (http://www.transifex.com/django/django/language/th/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: th\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "จุด" + +msgid "Line string" +msgstr "สายสตริง" + +msgid "Polygon" +msgstr "รูปหลายเหลี่ยม" + +msgid "Multi-point" +msgstr "หลาย ๆ จุด" + +msgid "Multi-line string" +msgstr "สตริงหลายบรรทัด" + +msgid "Multi polygon" +msgstr "รูปหลายเหลี่ยมหลายรูป" + +msgid "Geometry collection" +msgstr "คอลเลกชันรูปทรงเรขาคณิต" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "ไม่พบข้อมูลพิกัด" + +msgid "Invalid geometry value." +msgstr "ค่าพิกัดผิดพลาด " + +msgid "Invalid geometry type." +msgstr "ขนิดข้อมูลพิกัดผิดพลาด" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "ข้อผิดพลาดที่เกิดขึ้นเมื่อการเปลี่ยนรูปทรงเรขาคณิตที่ SRID ของเขตข้อมูลฟอร์มเรขาคณิต" + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "ไม่มีฟีดที่ลงทะเบียน" + +#, python-format +msgid "Slug %r isn't registered." +msgstr "Slug %r ไม่ได้ลงทะเบียน" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/tr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/tr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..46268b5 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/tr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/tr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/tr/LC_MESSAGES/django.po new file mode 100644 index 0000000..455bffb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/tr/LC_MESSAGES/django.po @@ -0,0 +1,88 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# BouRock, 2015,2019 +# BouRock, 2014-2015 +# Jannis Leidel , 2011 +# Murat Çorlu , 2012 +# Murat Sahin , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: BouRock, 2015,2019\n" +"Language-Team: Turkish (http://app.transifex.com/django/django/language/" +"tr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "Temel GIS alanı." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "Temel Geometri alanı — OpenGIS Özellikleri Geometri türüyle eşlenir." + +msgid "Point" +msgstr "Nokta" + +msgid "Line string" +msgstr "Satır dizgisi" + +msgid "Polygon" +msgstr "Çokgen" + +msgid "Multi-point" +msgstr "Çok noktalı" + +msgid "Multi-line string" +msgstr "Çok satırlı dizgi" + +msgid "Multi polygon" +msgstr "Çoklu çokgen" + +msgid "Geometry collection" +msgstr "Geometri koleksiyonu" + +msgid "Extent Aggregate Field" +msgstr "Toplama Alanını Genişlet" + +msgid "Raster Field" +msgstr "Tarama Alanı" + +msgid "No geometry value provided." +msgstr "Verilen hiç geometri değeri yok." + +msgid "Invalid geometry value." +msgstr "Geçersiz geometri değeri." + +msgid "Invalid geometry type." +msgstr "Geçersiz geometri türü." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"Geometri verisi geometri form alanının SRID değerine dönüştürülürken bir " +"hata meydana geldi." + +msgid "Delete all Features" +msgstr "Tüm Özellikleri Sil" + +msgid "Debugging window (serialized value)" +msgstr "Hata ayıklama penceresi (serileştirilmiş değer)" + +msgid "No feeds are registered." +msgstr "Hiçbir besleme kayıtlı değil." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "%r kısaltması kayıtlı değil." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/tt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/tt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..618bfb7 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/tt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/tt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/tt/LC_MESSAGES/django.po new file mode 100644 index 0000000..c54e9f2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/tt/LC_MESSAGES/django.po @@ -0,0 +1,85 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Azat Khasanshin , 2011 +# v_ildar , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Tatar (http://www.transifex.com/django/django/language/tt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tt\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "GIS" +msgstr "ГИС" + +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "Нокта" + +msgid "Line string" +msgstr "Сынык сызык" + +msgid "Polygon" +msgstr "Күппочмак" + +msgid "Multi-point" +msgstr "Нокта җыелмасы" + +msgid "Multi-line string" +msgstr "Сынык сызыклар җыелмасы" + +msgid "Multi polygon" +msgstr "Күппочмаклар җыелмасы" + +msgid "Geometry collection" +msgstr "Геометрик объектлар җыелмасы" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "Геометрик кыйммәт күрсәтелмәгән." + +msgid "Invalid geometry value." +msgstr "Дөрес булмаган геометрик кыйммәт." + +msgid "Invalid geometry type." +msgstr "Дөрес булмаган геометрик тип." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "Геометриядән SRIDгә үзгәртү вакытында хата килеп чыкты." + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "" + +#, python-format +msgid "Slug %r isn't registered." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/udm/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/udm/LC_MESSAGES/django.mo new file mode 100644 index 0000000..192c21c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/udm/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/udm/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/udm/LC_MESSAGES/django.po new file mode 100644 index 0000000..1208f91 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/udm/LC_MESSAGES/django.po @@ -0,0 +1,80 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-03-18 09:16+0100\n" +"PO-Revision-Date: 2015-03-18 08:35+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Udmurt (http://www.transifex.com/projects/p/django/language/" +"udm/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: udm\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "" + +msgid "Line string" +msgstr "" + +msgid "Polygon" +msgstr "" + +msgid "Multi-point" +msgstr "" + +msgid "Multi-line string" +msgstr "" + +msgid "Multi polygon" +msgstr "" + +msgid "Geometry collection" +msgstr "" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "" + +msgid "Invalid geometry value." +msgstr "" + +msgid "Invalid geometry type." +msgstr "" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Google Maps via GeoDjango" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "" + +#, python-format +msgid "Slug %r isn't registered." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ug/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ug/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0dff815 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ug/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ug/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ug/LC_MESSAGES/django.po new file mode 100644 index 0000000..b64a663 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ug/LC_MESSAGES/django.po @@ -0,0 +1,86 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Abduqadir Abliz , 2023 +# Azat, 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Azat, 2023\n" +"Language-Team: Uyghur (http://app.transifex.com/django/django/language/ug/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ug\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "ئاساسىي GIS بۆلىكى." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"ئاساسىي گېئومېتىرىيە سۆز بۆلىكى_OpenGIS ئۆلچەملىك گېئومېتىرىيە تىپىدە ئەكس " +"ئەتتۈرىدۇ." + +msgid "Point" +msgstr "نۇقتا" + +msgid "Line string" +msgstr "قۇر تىزىقى" + +msgid "Polygon" +msgstr "كۆپ تەرەپلىك" + +msgid "Multi-point" +msgstr "كۆپ نۇقتا" + +msgid "Multi-line string" +msgstr "كۆپ قۇر تىزىقى" + +msgid "Multi polygon" +msgstr "نۇرغۇن كۆپ تەرەپلىك" + +msgid "Geometry collection" +msgstr "گېئومېتىرىيە توپلىمى" + +msgid "Extent Aggregate Field" +msgstr "كېڭەيتىلگەن يىغىندا سۆز بۆلىكى" + +msgid "Raster Field" +msgstr "راستىر ساھەسى" + +msgid "No geometry value provided." +msgstr "گېئومېتىرىيە قىممىتى تەمىنلەنمىگەن." + +msgid "Invalid geometry value." +msgstr "گېئومېتىرىيە قىممىتى ئىناۋەتسىز." + +msgid "Invalid geometry type." +msgstr "ئىناۋەتسىز گېئومېتىرىيە تىپى" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"گىئومېتىرىيەلىك شەكىلنى گىئومېتىرىيە جەدۋەل سۆز بۆلىكىدىكى SRID غا " +"ئايلاندۇرغاندا خاتالىق كۆرۈلدى." + +msgid "Delete all Features" +msgstr "ھەممە ئىقتىدارلارنى ئۆچۈر" + +msgid "Debugging window (serialized value)" +msgstr "تەڭشەش كۆزنىكى (سېرىللاشتۇرۇلغان قىممەت)" + +msgid "No feeds are registered." +msgstr "ھېچقانداق مەنبە خەتلەتمىگەن." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Slug %r تىزىملىتىلمىغان." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/uk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/uk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..cd5c40d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/uk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/uk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/uk/LC_MESSAGES/django.po new file mode 100644 index 0000000..f894c66 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/uk/LC_MESSAGES/django.po @@ -0,0 +1,93 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Denis Podlesniy , 2016 +# Illia Volochii , 2021 +# Jannis Leidel , 2011 +# Kirill Gagarski , 2016 +# Max V. Stotsky , 2014 +# Roman Kozlovskyi , 2012 +# Sergey Lysach , 2011 +# Андрей Костенко , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Illia Volochii , 2021\n" +"Language-Team: Ukrainian (http://app.transifex.com/django/django/language/" +"uk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: uk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != " +"11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % " +"100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || " +"(n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n" + +msgid "GIS" +msgstr "ГІС" + +msgid "The base GIS field." +msgstr "Базове GIS поле." + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "" +"Базове поле Geometry, яке відповідає типу Geometry із специфікації OpenGIS" + +msgid "Point" +msgstr "Точка" + +msgid "Line string" +msgstr "Ламана" + +msgid "Polygon" +msgstr "Багатокутник" + +msgid "Multi-point" +msgstr "Набір точок" + +msgid "Multi-line string" +msgstr "Набір ламаних" + +msgid "Multi polygon" +msgstr "Набір багатокутників" + +msgid "Geometry collection" +msgstr "Набір геометричних об'єктів" + +msgid "Extent Aggregate Field" +msgstr "Поле, агрегуюче площу чи об'єм" + +msgid "Raster Field" +msgstr "Растрове поле" + +msgid "No geometry value provided." +msgstr "Не задано геометричне значення." + +msgid "Invalid geometry value." +msgstr "Невірне геометричне значення." + +msgid "Invalid geometry type." +msgstr "Невірний геометричний тип." + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "Помилка при перетворенні геометрії до SRID геометричного поля форми." + +msgid "Delete all Features" +msgstr "Видалити всі Features" + +msgid "Debugging window (serialized value)" +msgstr "Вікно налагождення (серіалізоване значення)" + +msgid "No feeds are registered." +msgstr "Немає зареєстрованих підписок." + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "Слаг %r не зареєстрований." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ur/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ur/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4b2b784 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ur/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ur/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ur/LC_MESSAGES/django.po new file mode 100644 index 0000000..bb78f46 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/ur/LC_MESSAGES/django.po @@ -0,0 +1,86 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Mansoorulhaq Mansoor , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Urdu (http://www.transifex.com/django/django/language/ur/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ur\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "نقطہ" + +msgid "Line string" +msgstr "لائن سٹرنگ" + +msgid "Polygon" +msgstr "پولی گان" + +msgid "Multi-point" +msgstr "کثیر النقاط" + +msgid "Multi-line string" +msgstr "متعدد لائنوں والا سٹرنگ" + +msgid "Multi polygon" +msgstr "ملٹی پولی گان" + +msgid "Geometry collection" +msgstr "جیومیٹری کا ذخیرہ" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "کوئی جیومیٹری ویلیو مھیا نھیں کی گئی۔" + +msgid "Invalid geometry value." +msgstr "غلط جیومیٹری ویلیو۔" + +msgid "Invalid geometry type." +msgstr "غلط جیومیٹری ٹائپ" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "" +"جیومیٹری کو جیومیٹری کے فارم کے SRID خانے میں تبدیل کرتے ھوئےکوئی خرابی واقع " +"ھو گئی ھے۔" + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "" + +#, python-format +msgid "Slug %r isn't registered." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/vi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/vi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0295e89 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/vi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/vi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/vi/LC_MESSAGES/django.po new file mode 100644 index 0000000..adfc6b5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/vi/LC_MESSAGES/django.po @@ -0,0 +1,87 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Thanh Le Viet , 2013 +# Tran , 2011 +# Tran Van , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-01-19 16:49+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Vietnamese (http://www.transifex.com/django/django/language/" +"vi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: vi\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "GIS" +msgstr "" + +msgid "The base GIS field." +msgstr "" + +msgid "" +"The base Geometry field -- maps to the OpenGIS Specification Geometry type." +msgstr "" + +msgid "Point" +msgstr "Điểm" + +msgid "Line string" +msgstr "Đường" + +msgid "Polygon" +msgstr "Đa giác" + +msgid "Multi-point" +msgstr "Đa điểm" + +msgid "Multi-line string" +msgstr "Multi-line string" + +msgid "Multi polygon" +msgstr "Multi polygon" + +msgid "Geometry collection" +msgstr "Kiểu hình học" + +msgid "Extent Aggregate Field" +msgstr "" + +msgid "Raster Field" +msgstr "" + +msgid "No geometry value provided." +msgstr "Không có giá trị geometry" + +msgid "Invalid geometry value." +msgstr "Giá trị geometry không hợp lệ" + +msgid "Invalid geometry type." +msgstr "Kiểu geometry không hợp lệ" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "Có lỗi khi chuyển đổi hình học từ SRID của trường geometry" + +msgid "Delete all Features" +msgstr "" + +msgid "WKT debugging window:" +msgstr "" + +msgid "Debugging window (serialized value)" +msgstr "" + +msgid "No feeds are registered." +msgstr "Không có feed nào được đăng kí" + +#, python-format +msgid "Slug %r isn't registered." +msgstr "Slug %r không được đăng kí" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/zh_Hans/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/zh_Hans/LC_MESSAGES/django.mo new file mode 100644 index 0000000..cffabb2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/zh_Hans/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/zh_Hans/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/zh_Hans/LC_MESSAGES/django.po new file mode 100644 index 0000000..6411c6b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/zh_Hans/LC_MESSAGES/django.po @@ -0,0 +1,90 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Daniel Duan , 2011 +# Jannis Leidel , 2011 +# Lei Yang , 2011 +# Lele Long , 2011,2015 +# mozillazg , 2016 +# Ronald White , 2014 +# wolf ice , 2020 +# Kevin Sze , 2012 +# 航 柯 , 2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: wolf ice , 2020\n" +"Language-Team: Chinese (China) (http://app.transifex.com/django/django/" +"language/zh_CN/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_CN\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "基础 GIS 字段。" + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "基本几何字段—映射到OpenGIS规范几何类型。" + +msgid "Point" +msgstr "点" + +msgid "Line string" +msgstr "行字串" + +msgid "Polygon" +msgstr "多边形" + +msgid "Multi-point" +msgstr "多点" + +msgid "Multi-line string" +msgstr "多行字符串" + +msgid "Multi polygon" +msgstr "多个多边形" + +msgid "Geometry collection" +msgstr "几何集合" + +msgid "Extent Aggregate Field" +msgstr "扩展聚集字段" + +msgid "Raster Field" +msgstr "光栅字段" + +msgid "No geometry value provided." +msgstr "未提供几何信息。" + +msgid "Invalid geometry value." +msgstr "无效几何信息。" + +msgid "Invalid geometry type." +msgstr "无效几何类型。" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "几何形状转换SRID字段将发生错误" + +msgid "Delete all Features" +msgstr "删除所有要素" + +msgid "Debugging window (serialized value)" +msgstr "调试窗口(已序列化的值)" + +msgid "No feeds are registered." +msgstr "没有已注册的源。" + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "字段 %r没被注册" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/zh_Hant/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/zh_Hant/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d282a94 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/zh_Hant/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/zh_Hant/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/zh_Hant/LC_MESSAGES/django.po new file mode 100644 index 0000000..d976cfd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/locale/zh_Hant/LC_MESSAGES/django.po @@ -0,0 +1,86 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Chen Chun-Chia , 2015 +# ilay , 2012 +# Jannis Leidel , 2011 +# 619e61dbdb61c57213f62815aaf60e01, 2011 +# Tzu-ping Chung , 2016,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:45+0000\n" +"Last-Translator: Tzu-ping Chung , 2016,2019\n" +"Language-Team: Chinese (Taiwan) (http://app.transifex.com/django/django/" +"language/zh_TW/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_TW\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "GIS" +msgstr "GIS" + +msgid "The base GIS field." +msgstr "基礎 GIS 欄位。" + +msgid "" +"The base Geometry field — maps to the OpenGIS Specification Geometry type." +msgstr "基本的 Geometry 欄位——對應於 OpenGIS 規格的 Geometry 類型。" + +msgid "Point" +msgstr "Point 類別" + +msgid "Line string" +msgstr "Line string 類別" + +msgid "Polygon" +msgstr "Polygon 類別" + +msgid "Multi-point" +msgstr "Multi-point 類別" + +msgid "Multi-line string" +msgstr "Multi-line string 類別" + +msgid "Multi polygon" +msgstr "Multi polygon 類別" + +msgid "Geometry collection" +msgstr "Geometry collection (幾何型別之叢集) 類別" + +msgid "Extent Aggregate Field" +msgstr "聚集程度欄位" + +msgid "Raster Field" +msgstr "柵格欄位" + +msgid "No geometry value provided." +msgstr "沒有幾何資訊。" + +msgid "Invalid geometry value." +msgstr "無效的幾何參數。" + +msgid "Invalid geometry type." +msgstr "無效的幾何類型。" + +msgid "" +"An error occurred when transforming the geometry to the SRID of the geometry " +"form field." +msgstr "當把目前地理資訊-GIS,轉成空間參考識別碼-SRID時發生錯誤。" + +msgid "Delete all Features" +msgstr "刪除所有特徵" + +msgid "Debugging window (serialized value)" +msgstr "除錯視窗 (序列化值)" + +msgid "No feeds are registered." +msgstr "沒有已註冊的 feed。" + +#, python-format +msgid "Slug %r isn’t registered." +msgstr "嵌入式語法 %r 尚未註冊。" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/management/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/management/commands/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/management/commands/inspectdb.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/management/commands/inspectdb.py new file mode 100644 index 0000000..1bcc1a0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/management/commands/inspectdb.py @@ -0,0 +1,18 @@ +from django.core.management.commands.inspectdb import Command as InspectDBCommand + + +class Command(InspectDBCommand): + db_module = "django.contrib.gis.db" + + def get_field_type(self, connection, table_name, row): + field_type, field_params, field_notes = super().get_field_type( + connection, table_name, row + ) + if field_type == "GeometryField": + # Getting a more specific field type and any additional parameters + # from the `get_geometry_type` routine for the spatial backend. + field_type, geo_params = connection.introspection.get_geometry_type( + table_name, row + ) + field_params.update(geo_params) + return field_type, field_params, field_notes diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/management/commands/ogrinspect.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/management/commands/ogrinspect.py new file mode 100644 index 0000000..2d2bd63 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/management/commands/ogrinspect.py @@ -0,0 +1,164 @@ +import argparse + +from django.contrib.gis import gdal +from django.core.management.base import BaseCommand, CommandError +from django.utils.inspect import get_func_args + + +class LayerOptionAction(argparse.Action): + """ + Custom argparse action for the `ogrinspect` `layer_key` keyword option + which may be an integer or a string. + """ + + def __call__(self, parser, namespace, value, option_string=None): + try: + setattr(namespace, self.dest, int(value)) + except ValueError: + setattr(namespace, self.dest, value) + + +class ListOptionAction(argparse.Action): + """ + Custom argparse action for `ogrinspect` keywords that require + a string list. If the string is 'True'/'true' then the option + value will be a boolean instead. + """ + + def __call__(self, parser, namespace, value, option_string=None): + if value.lower() == "true": + setattr(namespace, self.dest, True) + else: + setattr(namespace, self.dest, value.split(",")) + + +class Command(BaseCommand): + help = ( + "Inspects the given OGR-compatible data source (e.g., a shapefile) and " + "outputs\na GeoDjango model with the given model name. For example:\n" + " ./manage.py ogrinspect zipcode.shp Zipcode" + ) + + requires_system_checks = [] + + def add_arguments(self, parser): + parser.add_argument("data_source", help="Path to the data source.") + parser.add_argument("model_name", help="Name of the model to create.") + parser.add_argument( + "--blank", + action=ListOptionAction, + default=False, + help="Use a comma separated list of OGR field names to add " + "the `blank=True` option to the field definition. Set to `true` " + "to apply to all applicable fields.", + ) + parser.add_argument( + "--decimal", + action=ListOptionAction, + default=False, + help="Use a comma separated list of OGR float fields to " + "generate `DecimalField` instead of the default " + "`FloatField`. Set to `true` to apply to all OGR float fields.", + ) + parser.add_argument( + "--geom-name", + default="geom", + help="Specifies the model name for the Geometry Field (defaults to `geom`)", + ) + parser.add_argument( + "--layer", + dest="layer_key", + action=LayerOptionAction, + default=0, + help="The key for specifying which layer in the OGR data " + "source to use. Defaults to 0 (the first layer). May be " + "an integer or a string identifier for the layer.", + ) + parser.add_argument( + "--multi-geom", + action="store_true", + help="Treat the geometry in the data source as a geometry collection.", + ) + parser.add_argument( + "--name-field", + help="Specifies a field name to return for the __str__() method.", + ) + parser.add_argument( + "--no-imports", + action="store_false", + dest="imports", + help="Do not include `from django.contrib.gis.db import models` statement.", + ) + parser.add_argument( + "--null", + action=ListOptionAction, + default=False, + help="Use a comma separated list of OGR field names to add " + "the `null=True` option to the field definition. Set to `true` " + "to apply to all applicable fields.", + ) + parser.add_argument( + "--srid", + help="The SRID to use for the Geometry Field. If it can be " + "determined, the SRID of the data source is used.", + ) + parser.add_argument( + "--mapping", + action="store_true", + help="Generate mapping dictionary for use with `LayerMapping`.", + ) + + def handle(self, *args, **options): + data_source, model_name = options.pop("data_source"), options.pop("model_name") + + # Getting the OGR DataSource from the string parameter. + try: + ds = gdal.DataSource(data_source) + except gdal.GDALException as msg: + raise CommandError(msg) + + # Returning the output of ogrinspect with the given arguments + # and options. + from django.contrib.gis.utils.ogrinspect import _ogrinspect, mapping + + # Filter options to params accepted by `_ogrinspect` + ogr_options = { + k: v + for k, v in options.items() + if k in get_func_args(_ogrinspect) and v is not None + } + output = [s for s in _ogrinspect(ds, model_name, **ogr_options)] + + if options["mapping"]: + # Constructing the keyword arguments for `mapping`, and + # calling it on the data source. + kwargs = { + "geom_name": options["geom_name"], + "layer_key": options["layer_key"], + "multi_geom": options["multi_geom"], + } + mapping_dict = mapping(ds, **kwargs) + # This extra legwork is so that the dictionary definition comes + # out in the same order as the fields in the model definition. + rev_mapping = {v: k for k, v in mapping_dict.items()} + output.extend( + [ + "", + "", + "# Auto-generated `LayerMapping` dictionary for %s model" + % model_name, + "%s_mapping = {" % model_name.lower(), + ] + ) + output.extend( + " '%s': '%s'," % (rev_mapping[ogr_fld], ogr_fld) + for ogr_fld in ds[options["layer_key"]].fields + ) + output.extend( + [ + " '%s': '%s'," + % (options["geom_name"], mapping_dict[options["geom_name"]]), + "}", + ] + ) + return "\n".join(output) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/measure.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/measure.py new file mode 100644 index 0000000..590a802 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/measure.py @@ -0,0 +1,368 @@ +# Copyright (c) 2007, Robert Coup +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of Distance nor the names of its contributors may be used +# to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +""" +Distance and Area objects to allow for sensible and convenient calculation +and conversions. + +Authors: Robert Coup, Justin Bronn, Riccardo Di Virgilio + +Inspired by GeoPy (https://github.com/geopy/geopy) +and Geoff Biggs' PhD work on dimensioned units for robotics. +""" +from decimal import Decimal +from functools import total_ordering + +__all__ = ["A", "Area", "D", "Distance"] + +NUMERIC_TYPES = (int, float, Decimal) +AREA_PREFIX = "sq_" + + +def pretty_name(obj): + return obj.__name__ if obj.__class__ == type else obj.__class__.__name__ + + +@total_ordering +class MeasureBase: + STANDARD_UNIT = None + ALIAS = {} + UNITS = {} + LALIAS = {} + + def __init__(self, default_unit=None, **kwargs): + value, self._default_unit = self.default_units(kwargs) + setattr(self, self.STANDARD_UNIT, value) + if default_unit and isinstance(default_unit, str): + self._default_unit = default_unit + + def _get_standard(self): + return getattr(self, self.STANDARD_UNIT) + + def _set_standard(self, value): + setattr(self, self.STANDARD_UNIT, value) + + standard = property(_get_standard, _set_standard) + + def __getattr__(self, name): + if name in self.UNITS: + return self.standard / self.UNITS[name] + else: + raise AttributeError("Unknown unit type: %s" % name) + + def __repr__(self): + return "%s(%s=%s)" % ( + pretty_name(self), + self._default_unit, + getattr(self, self._default_unit), + ) + + def __str__(self): + return "%s %s" % (getattr(self, self._default_unit), self._default_unit) + + # **** Comparison methods **** + + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.standard == other.standard + else: + return NotImplemented + + def __hash__(self): + return hash(self.standard) + + def __lt__(self, other): + if isinstance(other, self.__class__): + return self.standard < other.standard + else: + return NotImplemented + + # **** Operators methods **** + + def __add__(self, other): + if isinstance(other, self.__class__): + return self.__class__( + default_unit=self._default_unit, + **{self.STANDARD_UNIT: (self.standard + other.standard)}, + ) + else: + raise TypeError( + "%(class)s must be added with %(class)s" % {"class": pretty_name(self)} + ) + + def __iadd__(self, other): + if isinstance(other, self.__class__): + self.standard += other.standard + return self + else: + raise TypeError( + "%(class)s must be added with %(class)s" % {"class": pretty_name(self)} + ) + + def __sub__(self, other): + if isinstance(other, self.__class__): + return self.__class__( + default_unit=self._default_unit, + **{self.STANDARD_UNIT: (self.standard - other.standard)}, + ) + else: + raise TypeError( + "%(class)s must be subtracted from %(class)s" + % {"class": pretty_name(self)} + ) + + def __isub__(self, other): + if isinstance(other, self.__class__): + self.standard -= other.standard + return self + else: + raise TypeError( + "%(class)s must be subtracted from %(class)s" + % {"class": pretty_name(self)} + ) + + def __mul__(self, other): + if isinstance(other, NUMERIC_TYPES): + return self.__class__( + default_unit=self._default_unit, + **{self.STANDARD_UNIT: (self.standard * other)}, + ) + else: + raise TypeError( + "%(class)s must be multiplied with number" + % {"class": pretty_name(self)} + ) + + def __imul__(self, other): + if isinstance(other, NUMERIC_TYPES): + self.standard *= float(other) + return self + else: + raise TypeError( + "%(class)s must be multiplied with number" + % {"class": pretty_name(self)} + ) + + def __rmul__(self, other): + return self * other + + def __truediv__(self, other): + if isinstance(other, self.__class__): + return self.standard / other.standard + if isinstance(other, NUMERIC_TYPES): + return self.__class__( + default_unit=self._default_unit, + **{self.STANDARD_UNIT: (self.standard / other)}, + ) + else: + raise TypeError( + "%(class)s must be divided with number or %(class)s" + % {"class": pretty_name(self)} + ) + + def __itruediv__(self, other): + if isinstance(other, NUMERIC_TYPES): + self.standard /= float(other) + return self + else: + raise TypeError( + "%(class)s must be divided with number" % {"class": pretty_name(self)} + ) + + def __bool__(self): + return bool(self.standard) + + def default_units(self, kwargs): + """ + Return the unit value and the default units specified + from the given keyword arguments dictionary. + """ + val = 0.0 + default_unit = self.STANDARD_UNIT + for unit, value in kwargs.items(): + if not isinstance(value, float): + value = float(value) + if unit in self.UNITS: + val += self.UNITS[unit] * value + default_unit = unit + elif unit in self.ALIAS: + u = self.ALIAS[unit] + val += self.UNITS[u] * value + default_unit = u + else: + lower = unit.lower() + if lower in self.UNITS: + val += self.UNITS[lower] * value + default_unit = lower + elif lower in self.LALIAS: + u = self.LALIAS[lower] + val += self.UNITS[u] * value + default_unit = u + else: + raise AttributeError("Unknown unit type: %s" % unit) + return val, default_unit + + @classmethod + def unit_attname(cls, unit_str): + """ + Retrieve the unit attribute name for the given unit string. + For example, if the given unit string is 'metre', return 'm'. + Raise an AttributeError if an attribute cannot be found. + """ + lower = unit_str.lower() + if unit_str in cls.UNITS: + return unit_str + elif lower in cls.UNITS: + return lower + elif lower in cls.LALIAS: + return cls.LALIAS[lower] + else: + raise AttributeError(f"Unknown unit type: {unit_str}") + + +class Distance(MeasureBase): + STANDARD_UNIT = "m" + UNITS = { + "chain": 20.1168, + "chain_benoit": 20.116782, + "chain_sears": 20.1167645, + "british_chain_benoit": 20.1167824944, + "british_chain_sears": 20.1167651216, + "british_chain_sears_truncated": 20.116756, + "cm": 0.01, + "british_ft": 0.304799471539, + "british_yd": 0.914398414616, + "clarke_ft": 0.3047972654, + "clarke_link": 0.201166195164, + "fathom": 1.8288, + "ft": 0.3048, + "furlong": 201.168, + "german_m": 1.0000135965, + "gold_coast_ft": 0.304799710181508, + "indian_yd": 0.914398530744, + "inch": 0.0254, + "km": 1000.0, + "link": 0.201168, + "link_benoit": 0.20116782, + "link_sears": 0.20116765, + "m": 1.0, + "mi": 1609.344, + "mm": 0.001, + "nm": 1852.0, + "nm_uk": 1853.184, + "rod": 5.0292, + "sears_yd": 0.91439841, + "survey_ft": 0.304800609601, + "um": 0.000001, + "yd": 0.9144, + } + + # Unit aliases for `UNIT` terms encountered in Spatial Reference WKT. + ALIAS = { + "centimeter": "cm", + "foot": "ft", + "inches": "inch", + "kilometer": "km", + "kilometre": "km", + "meter": "m", + "metre": "m", + "micrometer": "um", + "micrometre": "um", + "millimeter": "mm", + "millimetre": "mm", + "mile": "mi", + "yard": "yd", + "British chain (Benoit 1895 B)": "british_chain_benoit", + "British chain (Sears 1922)": "british_chain_sears", + "British chain (Sears 1922 truncated)": "british_chain_sears_truncated", + "British foot (Sears 1922)": "british_ft", + "British foot": "british_ft", + "British yard (Sears 1922)": "british_yd", + "British yard": "british_yd", + "Clarke's Foot": "clarke_ft", + "Clarke's link": "clarke_link", + "Chain (Benoit)": "chain_benoit", + "Chain (Sears)": "chain_sears", + "Foot (International)": "ft", + "Furrow Long": "furlong", + "German legal metre": "german_m", + "Gold Coast foot": "gold_coast_ft", + "Indian yard": "indian_yd", + "Link (Benoit)": "link_benoit", + "Link (Sears)": "link_sears", + "Nautical Mile": "nm", + "Nautical Mile (UK)": "nm_uk", + "US survey foot": "survey_ft", + "U.S. Foot": "survey_ft", + "Yard (Indian)": "indian_yd", + "Yard (Sears)": "sears_yd", + } + LALIAS = {k.lower(): v for k, v in ALIAS.items()} + + def __mul__(self, other): + if isinstance(other, self.__class__): + return Area( + default_unit=AREA_PREFIX + self._default_unit, + **{AREA_PREFIX + self.STANDARD_UNIT: (self.standard * other.standard)}, + ) + elif isinstance(other, NUMERIC_TYPES): + return self.__class__( + default_unit=self._default_unit, + **{self.STANDARD_UNIT: (self.standard * other)}, + ) + else: + raise TypeError( + "%(distance)s must be multiplied with number or %(distance)s" + % { + "distance": pretty_name(self.__class__), + } + ) + + +class Area(MeasureBase): + STANDARD_UNIT = AREA_PREFIX + Distance.STANDARD_UNIT + # Getting the square units values and the alias dictionary. + UNITS = {"%s%s" % (AREA_PREFIX, k): v**2 for k, v in Distance.UNITS.items()} + ALIAS = {k: "%s%s" % (AREA_PREFIX, v) for k, v in Distance.ALIAS.items()} + LALIAS = {k.lower(): v for k, v in ALIAS.items()} + + def __truediv__(self, other): + if isinstance(other, NUMERIC_TYPES): + return self.__class__( + default_unit=self._default_unit, + **{self.STANDARD_UNIT: (self.standard / other)}, + ) + else: + raise TypeError( + "%(class)s must be divided by a number" % {"class": pretty_name(self)} + ) + + +# Shortcuts +D = Distance +A = Area diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/ptr.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/ptr.py new file mode 100644 index 0000000..6754701 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/ptr.py @@ -0,0 +1,41 @@ +from ctypes import c_void_p + + +class CPointerBase: + """ + Base class for objects that have a pointer access property + that controls access to the underlying C pointer. + """ + + _ptr = None # Initially the pointer is NULL. + ptr_type = c_void_p + destructor = None + null_ptr_exception_class = AttributeError + + @property + def ptr(self): + # Raise an exception if the pointer isn't valid so that NULL pointers + # aren't passed to routines -- that's very bad. + if self._ptr: + return self._ptr + raise self.null_ptr_exception_class( + "NULL %s pointer encountered." % self.__class__.__name__ + ) + + @ptr.setter + def ptr(self, ptr): + # Only allow the pointer to be set with pointers of the compatible + # type or None (NULL). + if not (ptr is None or isinstance(ptr, self.ptr_type)): + raise TypeError("Incompatible pointer type: %s." % type(ptr)) + self._ptr = ptr + + def __del__(self): + """ + Free the memory used by the C++ object. + """ + if self.destructor and self._ptr: + try: + self.destructor(self.ptr) + except (AttributeError, ImportError, TypeError): + pass # Some part might already have been garbage collected diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/serializers/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/serializers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/serializers/geojson.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/serializers/geojson.py new file mode 100644 index 0000000..072ee9d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/serializers/geojson.py @@ -0,0 +1,81 @@ +import json + +from django.contrib.gis.gdal import CoordTransform, SpatialReference +from django.core.serializers.base import SerializerDoesNotExist +from django.core.serializers.json import Serializer as JSONSerializer + + +class Serializer(JSONSerializer): + """ + Convert a queryset to GeoJSON, http://geojson.org/ + """ + + def _init_options(self): + super()._init_options() + self.geometry_field = self.json_kwargs.pop("geometry_field", None) + self.id_field = self.json_kwargs.pop("id_field", None) + self.srid = self.json_kwargs.pop("srid", 4326) + if ( + self.selected_fields is not None + and self.geometry_field is not None + and self.geometry_field not in self.selected_fields + ): + self.selected_fields = [*self.selected_fields, self.geometry_field] + + def start_serialization(self): + self._init_options() + self._cts = {} # cache of CoordTransform's + self.stream.write( + '{"type": "FeatureCollection", ' + '"crs": {"type": "name", "properties": {"name": "EPSG:%d"}},' + ' "features": [' % self.srid + ) + + def end_serialization(self): + self.stream.write("]}") + + def start_object(self, obj): + super().start_object(obj) + self._geometry = None + if self.geometry_field is None: + # Find the first declared geometry field + for field in obj._meta.fields: + if hasattr(field, "geom_type"): + self.geometry_field = field.name + break + + def get_dump_object(self, obj): + data = { + "type": "Feature", + "id": obj.pk if self.id_field is None else getattr(obj, self.id_field), + "properties": self._current, + } + if ( + self.selected_fields is None or "pk" in self.selected_fields + ) and "pk" not in data["properties"]: + data["properties"]["pk"] = obj._meta.pk.value_to_string(obj) + if self._geometry: + if self._geometry.srid != self.srid: + # If needed, transform the geometry in the srid of the global + # geojson srid. + if self._geometry.srid not in self._cts: + srs = SpatialReference(self.srid) + self._cts[self._geometry.srid] = CoordTransform( + self._geometry.srs, srs + ) + self._geometry.transform(self._cts[self._geometry.srid]) + data["geometry"] = json.loads(self._geometry.geojson) + else: + data["geometry"] = None + return data + + def handle_field(self, obj, field): + if field.name == self.geometry_field: + self._geometry = field.value_from_object(obj) + else: + super().handle_field(obj, field) + + +class Deserializer: + def __init__(self, *args, **kwargs): + raise SerializerDoesNotExist("geojson is a serialization-only serializer") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/shortcuts.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/shortcuts.py new file mode 100644 index 0000000..33ff2ac --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/shortcuts.py @@ -0,0 +1,40 @@ +import zipfile +from io import BytesIO + +from django.conf import settings +from django.http import HttpResponse +from django.template import loader + +# NumPy supported? +try: + import numpy +except ImportError: + numpy = False + + +def compress_kml(kml): + "Return compressed KMZ from the given KML string." + kmz = BytesIO() + with zipfile.ZipFile(kmz, "a", zipfile.ZIP_DEFLATED) as zf: + zf.writestr("doc.kml", kml.encode(settings.DEFAULT_CHARSET)) + kmz.seek(0) + return kmz.read() + + +def render_to_kml(*args, **kwargs): + "Render the response as KML (using the correct MIME type)." + return HttpResponse( + loader.render_to_string(*args, **kwargs), + content_type="application/vnd.google-earth.kml+xml", + ) + + +def render_to_kmz(*args, **kwargs): + """ + Compress the KML content and return as KMZ (using the correct + MIME type). + """ + return HttpResponse( + compress_kml(loader.render_to_string(*args, **kwargs)), + content_type="application/vnd.google-earth.kmz", + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/sitemaps/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/sitemaps/__init__.py new file mode 100644 index 0000000..3654bfc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/sitemaps/__init__.py @@ -0,0 +1,4 @@ +# Geo-enabled Sitemap classes. +from django.contrib.gis.sitemaps.kml import KMLSitemap, KMZSitemap + +__all__ = ["KMLSitemap", "KMZSitemap"] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/sitemaps/kml.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/sitemaps/kml.py new file mode 100644 index 0000000..a84b5ae --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/sitemaps/kml.py @@ -0,0 +1,78 @@ +from django.apps import apps +from django.contrib.gis.db.models import GeometryField +from django.contrib.sitemaps import Sitemap +from django.db import models +from django.urls import reverse + + +class KMLSitemap(Sitemap): + """ + A minimal hook to produce KML sitemaps. + """ + + geo_format = "kml" + + def __init__(self, locations=None): + # If no locations specified, then we try to build for + # every model in installed applications. + self.locations = self._build_kml_sources(locations) + + def _build_kml_sources(self, sources): + """ + Go through the given sources and return a 3-tuple of the application + label, module name, and field name of every GeometryField encountered + in the sources. + + If no sources are provided, then all models. + """ + kml_sources = [] + if sources is None: + sources = apps.get_models() + for source in sources: + if isinstance(source, models.base.ModelBase): + for field in source._meta.fields: + if isinstance(field, GeometryField): + kml_sources.append( + ( + source._meta.app_label, + source._meta.model_name, + field.name, + ) + ) + elif isinstance(source, (list, tuple)): + if len(source) != 3: + raise ValueError( + "Must specify a 3-tuple of (app_label, module_name, " + "field_name)." + ) + kml_sources.append(source) + else: + raise TypeError("KML Sources must be a model or a 3-tuple.") + return kml_sources + + def get_urls(self, page=1, site=None, protocol=None): + """ + This method is overridden so the appropriate `geo_format` attribute + is placed on each URL element. + """ + urls = Sitemap.get_urls(self, page=page, site=site, protocol=protocol) + for url in urls: + url["geo_format"] = self.geo_format + return urls + + def items(self): + return self.locations + + def location(self, obj): + return reverse( + "django.contrib.gis.sitemaps.views.%s" % self.geo_format, + kwargs={ + "label": obj[0], + "model": obj[1], + "field_name": obj[2], + }, + ) + + +class KMZSitemap(KMLSitemap): + geo_format = "kmz" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/sitemaps/views.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/sitemaps/views.py new file mode 100644 index 0000000..17eb54e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/sitemaps/views.py @@ -0,0 +1,65 @@ +from django.apps import apps +from django.contrib.gis.db.models import GeometryField +from django.contrib.gis.db.models.functions import AsKML, Transform +from django.contrib.gis.shortcuts import render_to_kml, render_to_kmz +from django.core.exceptions import FieldDoesNotExist +from django.db import DEFAULT_DB_ALIAS, connections +from django.http import Http404 + + +def kml(request, label, model, field_name=None, compress=False, using=DEFAULT_DB_ALIAS): + """ + This view generates KML for the given app label, model, and field name. + + The field name must be that of a geographic field. + """ + placemarks = [] + try: + klass = apps.get_model(label, model) + except LookupError: + raise Http404( + 'You must supply a valid app label and module name. Got "%s.%s"' + % (label, model) + ) + + if field_name: + try: + field = klass._meta.get_field(field_name) + if not isinstance(field, GeometryField): + raise FieldDoesNotExist + except FieldDoesNotExist: + raise Http404("Invalid geometry field.") + + connection = connections[using] + + if connection.features.has_AsKML_function: + # Database will take care of transformation. + placemarks = klass._default_manager.using(using).annotate(kml=AsKML(field_name)) + else: + # If the database offers no KML method, we use the `kml` + # attribute of the lazy geometry instead. + placemarks = [] + if connection.features.has_Transform_function: + qs = klass._default_manager.using(using).annotate( + **{"%s_4326" % field_name: Transform(field_name, 4326)} + ) + field_name += "_4326" + else: + qs = klass._default_manager.using(using).all() + for mod in qs: + mod.kml = getattr(mod, field_name).kml + placemarks.append(mod) + + # Getting the render function and rendering to the correct. + if compress: + render = render_to_kmz + else: + render = render_to_kml + return render("gis/kml/placemarks.kml", {"places": placemarks}) + + +def kmz(request, label, model, field_name=None, using=DEFAULT_DB_ALIAS): + """ + Return KMZ for the given app label, model, and field name. + """ + return kml(request, label, model, field_name, compress=True, using=using) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/static/gis/css/ol3.css b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/static/gis/css/ol3.css new file mode 100644 index 0000000..ac8f0a8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/static/gis/css/ol3.css @@ -0,0 +1,39 @@ +.dj_map_wrapper { + position: relative; + float: left; +} +html[dir="rtl"] .dj_map_wrapper { + float: right; +} + +.switch-type { + background-repeat: no-repeat; + cursor: pointer; + top: 0.5em; + width: 22px; + height: 20px; +} + +.type-Point { + background-image: url("../img/draw_point_off.svg"); + right: 5px; +} +.type-Point.type-active { + background-image: url("../img/draw_point_on.svg"); +} + +.type-LineString { + background-image: url("../img/draw_line_off.svg"); + right: 30px; +} +.type-LineString.type-active { + background-image: url("../img/draw_line_on.svg"); +} + +.type-Polygon { + background-image: url("../img/draw_polygon_off.svg"); + right: 55px; +} +.type-Polygon.type-active { + background-image: url("../img/draw_polygon_on.svg"); +} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/static/gis/img/draw_line_off.svg b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/static/gis/img/draw_line_off.svg new file mode 100644 index 0000000..c403af6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/static/gis/img/draw_line_off.svg @@ -0,0 +1 @@ + diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/static/gis/img/draw_line_on.svg b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/static/gis/img/draw_line_on.svg new file mode 100644 index 0000000..5eb0d6d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/static/gis/img/draw_line_on.svg @@ -0,0 +1 @@ + diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/static/gis/img/draw_point_off.svg b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/static/gis/img/draw_point_off.svg new file mode 100644 index 0000000..5a29034 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/static/gis/img/draw_point_off.svg @@ -0,0 +1 @@ + diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/static/gis/img/draw_point_on.svg b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/static/gis/img/draw_point_on.svg new file mode 100644 index 0000000..f006524 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/static/gis/img/draw_point_on.svg @@ -0,0 +1 @@ + diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/static/gis/img/draw_polygon_off.svg b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/static/gis/img/draw_polygon_off.svg new file mode 100644 index 0000000..b02dd35 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/static/gis/img/draw_polygon_off.svg @@ -0,0 +1 @@ + diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/static/gis/img/draw_polygon_on.svg b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/static/gis/img/draw_polygon_on.svg new file mode 100644 index 0000000..303a02a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/static/gis/img/draw_polygon_on.svg @@ -0,0 +1 @@ + diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/static/gis/js/OLMapWidget.js b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/static/gis/js/OLMapWidget.js new file mode 100644 index 0000000..b750327 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/static/gis/js/OLMapWidget.js @@ -0,0 +1,238 @@ +/* global ol */ +'use strict'; +class GeometryTypeControl extends ol.control.Control { + // Map control to switch type when geometry type is unknown + constructor(opt_options) { + const options = opt_options || {}; + + const element = document.createElement('div'); + element.className = 'switch-type type-' + options.type + ' ol-control ol-unselectable'; + if (options.active) { + element.classList.add("type-active"); + } + + super({ + element: element, + target: options.target + }); + const self = this; + const switchType = function(e) { + e.preventDefault(); + if (options.widget.currentGeometryType !== self) { + options.widget.map.removeInteraction(options.widget.interactions.draw); + options.widget.interactions.draw = new ol.interaction.Draw({ + features: options.widget.featureCollection, + type: options.type + }); + options.widget.map.addInteraction(options.widget.interactions.draw); + options.widget.currentGeometryType.element.classList.remove('type-active'); + options.widget.currentGeometryType = self; + element.classList.add("type-active"); + } + }; + + element.addEventListener('click', switchType, false); + element.addEventListener('touchstart', switchType, false); + } +} + +// TODO: allow deleting individual features (#8972) +class MapWidget { + constructor(options) { + this.map = null; + this.interactions = {draw: null, modify: null}; + this.typeChoices = false; + this.ready = false; + + // Default options + this.options = { + default_lat: 0, + default_lon: 0, + default_zoom: 12, + is_collection: options.geom_name.includes('Multi') || options.geom_name.includes('Collection') + }; + + // Altering using user-provided options + for (const property in options) { + if (options.hasOwnProperty(property)) { + this.options[property] = options[property]; + } + } + if (!options.base_layer) { + this.options.base_layer = new ol.layer.Tile({source: new ol.source.OSM()}); + } + + // RemovedInDjango51Warning: when the deprecation ends, remove setting + // width/height (3 lines below). + const mapContainer = document.getElementById(this.options.map_id); + mapContainer.style.width = `${mapContainer.dataset.width}px`; + mapContainer.style.height = `${mapContainer.dataset.height}px`; + this.map = this.createMap(); + this.featureCollection = new ol.Collection(); + this.featureOverlay = new ol.layer.Vector({ + map: this.map, + source: new ol.source.Vector({ + features: this.featureCollection, + useSpatialIndex: false // improve performance + }), + updateWhileAnimating: true, // optional, for instant visual feedback + updateWhileInteracting: true // optional, for instant visual feedback + }); + + // Populate and set handlers for the feature container + const self = this; + this.featureCollection.on('add', function(event) { + const feature = event.element; + feature.on('change', function() { + self.serializeFeatures(); + }); + if (self.ready) { + self.serializeFeatures(); + if (!self.options.is_collection) { + self.disableDrawing(); // Only allow one feature at a time + } + } + }); + + const initial_value = document.getElementById(this.options.id).value; + if (initial_value) { + const jsonFormat = new ol.format.GeoJSON(); + const features = jsonFormat.readFeatures('{"type": "Feature", "geometry": ' + initial_value + '}'); + const extent = ol.extent.createEmpty(); + features.forEach(function(feature) { + this.featureOverlay.getSource().addFeature(feature); + ol.extent.extend(extent, feature.getGeometry().getExtent()); + }, this); + // Center/zoom the map + this.map.getView().fit(extent, {minResolution: 1}); + } else { + this.map.getView().setCenter(this.defaultCenter()); + } + this.createInteractions(); + if (initial_value && !this.options.is_collection) { + this.disableDrawing(); + } + const clearNode = document.getElementById(this.map.getTarget()).nextElementSibling; + if (clearNode.classList.contains('clear_features')) { + clearNode.querySelector('a').addEventListener('click', (ev) => { + ev.preventDefault(); + self.clearFeatures(); + }); + } + this.ready = true; + } + + createMap() { + return new ol.Map({ + target: this.options.map_id, + layers: [this.options.base_layer], + view: new ol.View({ + zoom: this.options.default_zoom + }) + }); + } + + createInteractions() { + // Initialize the modify interaction + this.interactions.modify = new ol.interaction.Modify({ + features: this.featureCollection, + deleteCondition: function(event) { + return ol.events.condition.shiftKeyOnly(event) && + ol.events.condition.singleClick(event); + } + }); + + // Initialize the draw interaction + let geomType = this.options.geom_name; + if (geomType === "Geometry" || geomType === "GeometryCollection") { + // Default to Point, but create icons to switch type + geomType = "Point"; + this.currentGeometryType = new GeometryTypeControl({widget: this, type: "Point", active: true}); + this.map.addControl(this.currentGeometryType); + this.map.addControl(new GeometryTypeControl({widget: this, type: "LineString", active: false})); + this.map.addControl(new GeometryTypeControl({widget: this, type: "Polygon", active: false})); + this.typeChoices = true; + } + this.interactions.draw = new ol.interaction.Draw({ + features: this.featureCollection, + type: geomType + }); + + this.map.addInteraction(this.interactions.draw); + this.map.addInteraction(this.interactions.modify); + } + + defaultCenter() { + const center = [this.options.default_lon, this.options.default_lat]; + if (this.options.map_srid) { + return ol.proj.transform(center, 'EPSG:4326', this.map.getView().getProjection()); + } + return center; + } + + enableDrawing() { + this.interactions.draw.setActive(true); + if (this.typeChoices) { + // Show geometry type icons + const divs = document.getElementsByClassName("switch-type"); + for (let i = 0; i !== divs.length; i++) { + divs[i].style.visibility = "visible"; + } + } + } + + disableDrawing() { + if (this.interactions.draw) { + this.interactions.draw.setActive(false); + if (this.typeChoices) { + // Hide geometry type icons + const divs = document.getElementsByClassName("switch-type"); + for (let i = 0; i !== divs.length; i++) { + divs[i].style.visibility = "hidden"; + } + } + } + } + + clearFeatures() { + this.featureCollection.clear(); + // Empty textarea widget + document.getElementById(this.options.id).value = ''; + this.enableDrawing(); + } + + serializeFeatures() { + // Three use cases: GeometryCollection, multigeometries, and single geometry + let geometry = null; + const features = this.featureOverlay.getSource().getFeatures(); + if (this.options.is_collection) { + if (this.options.geom_name === "GeometryCollection") { + const geometries = []; + for (let i = 0; i < features.length; i++) { + geometries.push(features[i].getGeometry()); + } + geometry = new ol.geom.GeometryCollection(geometries); + } else { + geometry = features[0].getGeometry().clone(); + for (let j = 1; j < features.length; j++) { + switch (geometry.getType()) { + case "MultiPoint": + geometry.appendPoint(features[j].getGeometry().getPoint(0)); + break; + case "MultiLineString": + geometry.appendLineString(features[j].getGeometry().getLineString(0)); + break; + case "MultiPolygon": + geometry.appendPolygon(features[j].getGeometry().getPolygon(0)); + } + } + } + } else { + if (features[0]) { + geometry = features[0].getGeometry(); + } + } + const jsonFormat = new ol.format.GeoJSON(); + document.getElementById(this.options.id).value = jsonFormat.writeGeometry(geometry); + } +} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/templates/gis/kml/base.kml b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/templates/gis/kml/base.kml new file mode 100644 index 0000000..374404c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/templates/gis/kml/base.kml @@ -0,0 +1,6 @@ + + +{% block name %}{% endblock %} +{% block placemarks %}{% endblock %} + + diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/templates/gis/kml/placemarks.kml b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/templates/gis/kml/placemarks.kml new file mode 100644 index 0000000..ea2ac19 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/templates/gis/kml/placemarks.kml @@ -0,0 +1,8 @@ +{% extends "gis/kml/base.kml" %} +{% block placemarks %}{% for place in places %} + + {% if place.name %}{{ place.name }}{% else %}{{ place }}{% endif %} + {% if place.description %}{{ place.description }}{% else %}{{ place }}{% endif %} + {{ place.kml|safe }} + {% endfor %}{% endblock %} + diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/templates/gis/openlayers-osm.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/templates/gis/openlayers-osm.html new file mode 100644 index 0000000..88b1c8c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/templates/gis/openlayers-osm.html @@ -0,0 +1,12 @@ +{% extends "gis/openlayers.html" %} +{% load l10n %} + +{% block options %}{{ block.super }} +options['default_lon'] = {{ default_lon|unlocalize }}; +options['default_lat'] = {{ default_lat|unlocalize }}; +options['default_zoom'] = {{ default_zoom|unlocalize }}; +{% endblock %} + +{% block base_layer %} +var base_layer = new ol.layer.Tile({source: new ol.source.OSM()}); +{% endblock %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/templates/gis/openlayers.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/templates/gis/openlayers.html new file mode 100644 index 0000000..2849813 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/templates/gis/openlayers.html @@ -0,0 +1,33 @@ +{% load i18n l10n %} + +
    + {# RemovedInDjango51Warning: when the deprecation ends, remove data-width and data-height attributes. #} +
    + {% if not disabled %}{% translate "Delete all Features" %}{% endif %} + {% if display_raw %}

    {% translate "Debugging window (serialized value)" %}

    {% endif %} + + +
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/utils/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/utils/__init__.py new file mode 100644 index 0000000..12f032c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/utils/__init__.py @@ -0,0 +1,24 @@ +""" + This module contains useful utilities for GeoDjango. +""" +from django.contrib.gis.utils.ogrinfo import ogrinfo +from django.contrib.gis.utils.ogrinspect import mapping, ogrinspect +from django.contrib.gis.utils.srs import add_srs_entry +from django.core.exceptions import ImproperlyConfigured + +__all__ = [ + "add_srs_entry", + "mapping", + "ogrinfo", + "ogrinspect", +] + +try: + # LayerMapping requires DJANGO_SETTINGS_MODULE to be set, + # and ImproperlyConfigured is raised if that's not the case. + from django.contrib.gis.utils.layermapping import LayerMapError, LayerMapping + + __all__ += ["LayerMapError", "LayerMapping"] + +except ImproperlyConfigured: + pass diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/utils/layermapping.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/utils/layermapping.py new file mode 100644 index 0000000..2dcf839 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/utils/layermapping.py @@ -0,0 +1,724 @@ +# LayerMapping -- A Django Model/OGR Layer Mapping Utility +""" + The LayerMapping class provides a way to map the contents of OGR + vector files (e.g. SHP files) to Geographic-enabled Django models. + + For more information, please consult the GeoDjango documentation: + https://docs.djangoproject.com/en/dev/ref/contrib/gis/layermapping/ +""" +import sys +from decimal import Decimal +from decimal import InvalidOperation as DecimalInvalidOperation +from pathlib import Path + +from django.contrib.gis.db.models import GeometryField +from django.contrib.gis.gdal import ( + CoordTransform, + DataSource, + GDALException, + OGRGeometry, + OGRGeomType, + SpatialReference, +) +from django.contrib.gis.gdal.field import ( + OFTDate, + OFTDateTime, + OFTInteger, + OFTInteger64, + OFTReal, + OFTString, + OFTTime, +) +from django.core.exceptions import FieldDoesNotExist, ObjectDoesNotExist +from django.db import connections, models, router, transaction +from django.utils.encoding import force_str + + +# LayerMapping exceptions. +class LayerMapError(Exception): + pass + + +class InvalidString(LayerMapError): + pass + + +class InvalidDecimal(LayerMapError): + pass + + +class InvalidInteger(LayerMapError): + pass + + +class MissingForeignKey(LayerMapError): + pass + + +class LayerMapping: + "A class that maps OGR Layers to GeoDjango Models." + + # Acceptable 'base' types for a multi-geometry type. + MULTI_TYPES = { + 1: OGRGeomType("MultiPoint"), + 2: OGRGeomType("MultiLineString"), + 3: OGRGeomType("MultiPolygon"), + OGRGeomType("Point25D").num: OGRGeomType("MultiPoint25D"), + OGRGeomType("LineString25D").num: OGRGeomType("MultiLineString25D"), + OGRGeomType("Polygon25D").num: OGRGeomType("MultiPolygon25D"), + } + # Acceptable Django field types and corresponding acceptable OGR + # counterparts. + FIELD_TYPES = { + models.AutoField: OFTInteger, + models.BigAutoField: OFTInteger64, + models.SmallAutoField: OFTInteger, + models.BooleanField: (OFTInteger, OFTReal, OFTString), + models.IntegerField: (OFTInteger, OFTReal, OFTString), + models.FloatField: (OFTInteger, OFTReal), + models.DateField: OFTDate, + models.DateTimeField: OFTDateTime, + models.EmailField: OFTString, + models.TimeField: OFTTime, + models.DecimalField: (OFTInteger, OFTReal), + models.CharField: OFTString, + models.SlugField: OFTString, + models.TextField: OFTString, + models.URLField: OFTString, + models.UUIDField: OFTString, + models.BigIntegerField: (OFTInteger, OFTReal, OFTString), + models.SmallIntegerField: (OFTInteger, OFTReal, OFTString), + models.PositiveBigIntegerField: (OFTInteger, OFTReal, OFTString), + models.PositiveIntegerField: (OFTInteger, OFTReal, OFTString), + models.PositiveSmallIntegerField: (OFTInteger, OFTReal, OFTString), + } + + def __init__( + self, + model, + data, + mapping, + layer=0, + source_srs=None, + encoding="utf-8", + transaction_mode="commit_on_success", + transform=True, + unique=None, + using=None, + ): + """ + A LayerMapping object is initialized using the given Model (not an instance), + a DataSource (or string path to an OGR-supported data file), and a mapping + dictionary. See the module level docstring for more details and keyword + argument usage. + """ + # Getting the DataSource and the associated Layer. + if isinstance(data, (str, Path)): + self.ds = DataSource(data, encoding=encoding) + else: + self.ds = data + self.layer = self.ds[layer] + + self.using = using if using is not None else router.db_for_write(model) + connection = connections[self.using] + self.spatial_backend = connection.ops + + # Setting the mapping & model attributes. + self.mapping = mapping + self.model = model + + # Checking the layer -- initialization of the object will fail if + # things don't check out before hand. + self.check_layer() + + # Getting the geometry column associated with the model (an + # exception will be raised if there is no geometry column). + if connection.features.supports_transform: + self.geo_field = self.geometry_field() + else: + transform = False + + # Checking the source spatial reference system, and getting + # the coordinate transformation object (unless the `transform` + # keyword is set to False) + if transform: + self.source_srs = self.check_srs(source_srs) + self.transform = self.coord_transform() + else: + self.transform = transform + + # Setting the encoding for OFTString fields, if specified. + if encoding: + # Making sure the encoding exists, if not a LookupError + # exception will be thrown. + from codecs import lookup + + lookup(encoding) + self.encoding = encoding + else: + self.encoding = None + + if unique: + self.check_unique(unique) + transaction_mode = "autocommit" # Has to be set to autocommit. + self.unique = unique + else: + self.unique = None + + # Setting the transaction decorator with the function in the + # transaction modes dictionary. + self.transaction_mode = transaction_mode + if transaction_mode == "autocommit": + self.transaction_decorator = None + elif transaction_mode == "commit_on_success": + self.transaction_decorator = transaction.atomic + else: + raise LayerMapError("Unrecognized transaction mode: %s" % transaction_mode) + + # #### Checking routines used during initialization #### + def check_fid_range(self, fid_range): + "Check the `fid_range` keyword." + if fid_range: + if isinstance(fid_range, (tuple, list)): + return slice(*fid_range) + elif isinstance(fid_range, slice): + return fid_range + else: + raise TypeError + else: + return None + + def check_layer(self): + """ + Check the Layer metadata and ensure that it's compatible with the + mapping information and model. Unlike previous revisions, there is no + need to increment through each feature in the Layer. + """ + # The geometry field of the model is set here. + # TODO: Support more than one geometry field / model. However, this + # depends on the GDAL Driver in use. + self.geom_field = False + self.fields = {} + + # Getting lists of the field names and the field types available in + # the OGR Layer. + ogr_fields = self.layer.fields + ogr_field_types = self.layer.field_types + + # Function for determining if the OGR mapping field is in the Layer. + def check_ogr_fld(ogr_map_fld): + try: + idx = ogr_fields.index(ogr_map_fld) + except ValueError: + raise LayerMapError( + 'Given mapping OGR field "%s" not found in OGR Layer.' % ogr_map_fld + ) + return idx + + # No need to increment through each feature in the model, simply check + # the Layer metadata against what was given in the mapping dictionary. + for field_name, ogr_name in self.mapping.items(): + # Ensuring that a corresponding field exists in the model + # for the given field name in the mapping. + try: + model_field = self.model._meta.get_field(field_name) + except FieldDoesNotExist: + raise LayerMapError( + 'Given mapping field "%s" not in given Model fields.' % field_name + ) + + # Getting the string name for the Django field class (e.g., 'PointField'). + fld_name = model_field.__class__.__name__ + + if isinstance(model_field, GeometryField): + if self.geom_field: + raise LayerMapError( + "LayerMapping does not support more than one GeometryField per " + "model." + ) + + # Getting the coordinate dimension of the geometry field. + coord_dim = model_field.dim + + try: + if coord_dim == 3: + gtype = OGRGeomType(ogr_name + "25D") + else: + gtype = OGRGeomType(ogr_name) + except GDALException: + raise LayerMapError( + 'Invalid mapping for GeometryField "%s".' % field_name + ) + + # Making sure that the OGR Layer's Geometry is compatible. + ltype = self.layer.geom_type + if not ( + ltype.name.startswith(gtype.name) + or self.make_multi(ltype, model_field) + ): + raise LayerMapError( + "Invalid mapping geometry; model has %s%s, " + "layer geometry type is %s." + % (fld_name, "(dim=3)" if coord_dim == 3 else "", ltype) + ) + + # Setting the `geom_field` attribute w/the name of the model field + # that is a Geometry. Also setting the coordinate dimension + # attribute. + self.geom_field = field_name + self.coord_dim = coord_dim + fields_val = model_field + elif isinstance(model_field, models.ForeignKey): + if isinstance(ogr_name, dict): + # Is every given related model mapping field in the Layer? + rel_model = model_field.remote_field.model + for rel_name, ogr_field in ogr_name.items(): + idx = check_ogr_fld(ogr_field) + try: + rel_model._meta.get_field(rel_name) + except FieldDoesNotExist: + raise LayerMapError( + 'ForeignKey mapping field "%s" not in %s fields.' + % (rel_name, rel_model.__class__.__name__) + ) + fields_val = rel_model + else: + raise TypeError("ForeignKey mapping must be of dictionary type.") + else: + # Is the model field type supported by LayerMapping? + if model_field.__class__ not in self.FIELD_TYPES: + raise LayerMapError( + 'Django field type "%s" has no OGR mapping (yet).' % fld_name + ) + + # Is the OGR field in the Layer? + idx = check_ogr_fld(ogr_name) + ogr_field = ogr_field_types[idx] + + # Can the OGR field type be mapped to the Django field type? + if not issubclass(ogr_field, self.FIELD_TYPES[model_field.__class__]): + raise LayerMapError( + 'OGR field "%s" (of type %s) cannot be mapped to Django %s.' + % (ogr_field, ogr_field.__name__, fld_name) + ) + fields_val = model_field + + self.fields[field_name] = fields_val + + def check_srs(self, source_srs): + "Check the compatibility of the given spatial reference object." + + if isinstance(source_srs, SpatialReference): + sr = source_srs + elif isinstance(source_srs, self.spatial_backend.spatial_ref_sys()): + sr = source_srs.srs + elif isinstance(source_srs, (int, str)): + sr = SpatialReference(source_srs) + else: + # Otherwise just pulling the SpatialReference from the layer + sr = self.layer.srs + + if not sr: + raise LayerMapError("No source reference system defined.") + else: + return sr + + def check_unique(self, unique): + "Check the `unique` keyword parameter -- may be a sequence or string." + if isinstance(unique, (list, tuple)): + # List of fields to determine uniqueness with + for attr in unique: + if attr not in self.mapping: + raise ValueError + elif isinstance(unique, str): + # Only a single field passed in. + if unique not in self.mapping: + raise ValueError + else: + raise TypeError( + "Unique keyword argument must be set with a tuple, list, or string." + ) + + # Keyword argument retrieval routines #### + def feature_kwargs(self, feat): + """ + Given an OGR Feature, return a dictionary of keyword arguments for + constructing the mapped model. + """ + # The keyword arguments for model construction. + kwargs = {} + + # Incrementing through each model field and OGR field in the + # dictionary mapping. + for field_name, ogr_name in self.mapping.items(): + model_field = self.fields[field_name] + + if isinstance(model_field, GeometryField): + # Verify OGR geometry. + try: + val = self.verify_geom(feat.geom, model_field) + except GDALException: + raise LayerMapError("Could not retrieve geometry from feature.") + elif isinstance(model_field, models.base.ModelBase): + # The related _model_, not a field was passed in -- indicating + # another mapping for the related Model. + val = self.verify_fk(feat, model_field, ogr_name) + else: + # Otherwise, verify OGR Field type. + val = self.verify_ogr_field(feat[ogr_name], model_field) + + # Setting the keyword arguments for the field name with the + # value obtained above. + kwargs[field_name] = val + + return kwargs + + def unique_kwargs(self, kwargs): + """ + Given the feature keyword arguments (from `feature_kwargs`), construct + and return the uniqueness keyword arguments -- a subset of the feature + kwargs. + """ + if isinstance(self.unique, str): + return {self.unique: kwargs[self.unique]} + else: + return {fld: kwargs[fld] for fld in self.unique} + + # #### Verification routines used in constructing model keyword arguments. #### + def verify_ogr_field(self, ogr_field, model_field): + """ + Verify if the OGR Field contents are acceptable to the model field. If + they are, return the verified value, otherwise raise an exception. + """ + if isinstance(ogr_field, OFTString) and isinstance( + model_field, (models.CharField, models.TextField) + ): + if self.encoding and ogr_field.value is not None: + # The encoding for OGR data sources may be specified here + # (e.g., 'cp437' for Census Bureau boundary files). + val = force_str(ogr_field.value, self.encoding) + else: + val = ogr_field.value + if ( + model_field.max_length + and val is not None + and len(val) > model_field.max_length + ): + raise InvalidString( + "%s model field maximum string length is %s, given %s characters." + % (model_field.name, model_field.max_length, len(val)) + ) + elif isinstance(ogr_field, OFTReal) and isinstance( + model_field, models.DecimalField + ): + try: + # Creating an instance of the Decimal value to use. + d = Decimal(str(ogr_field.value)) + except DecimalInvalidOperation: + raise InvalidDecimal( + "Could not construct decimal from: %s" % ogr_field.value + ) + + # Getting the decimal value as a tuple. + dtup = d.as_tuple() + digits = dtup[1] + d_idx = dtup[2] # index where the decimal is + + # Maximum amount of precision, or digits to the left of the decimal. + max_prec = model_field.max_digits - model_field.decimal_places + + # Getting the digits to the left of the decimal place for the + # given decimal. + if d_idx < 0: + n_prec = len(digits[:d_idx]) + else: + n_prec = len(digits) + d_idx + + # If we have more than the maximum digits allowed, then throw an + # InvalidDecimal exception. + if n_prec > max_prec: + raise InvalidDecimal( + "A DecimalField with max_digits %d, decimal_places %d must " + "round to an absolute value less than 10^%d." + % (model_field.max_digits, model_field.decimal_places, max_prec) + ) + val = d + elif isinstance(ogr_field, (OFTReal, OFTString)) and isinstance( + model_field, models.IntegerField + ): + # Attempt to convert any OFTReal and OFTString value to an OFTInteger. + try: + val = int(ogr_field.value) + except ValueError: + raise InvalidInteger( + "Could not construct integer from: %s" % ogr_field.value + ) + else: + val = ogr_field.value + return val + + def verify_fk(self, feat, rel_model, rel_mapping): + """ + Given an OGR Feature, the related model and its dictionary mapping, + retrieve the related model for the ForeignKey mapping. + """ + # TODO: It is expensive to retrieve a model for every record -- + # explore if an efficient mechanism exists for caching related + # ForeignKey models. + + # Constructing and verifying the related model keyword arguments. + fk_kwargs = {} + for field_name, ogr_name in rel_mapping.items(): + fk_kwargs[field_name] = self.verify_ogr_field( + feat[ogr_name], rel_model._meta.get_field(field_name) + ) + + # Attempting to retrieve and return the related model. + try: + return rel_model.objects.using(self.using).get(**fk_kwargs) + except ObjectDoesNotExist: + raise MissingForeignKey( + "No ForeignKey %s model found with keyword arguments: %s" + % (rel_model.__name__, fk_kwargs) + ) + + def verify_geom(self, geom, model_field): + """ + Verify the geometry -- construct and return a GeometryCollection + if necessary (for example if the model field is MultiPolygonField while + the mapped shapefile only contains Polygons). + """ + # Downgrade a 3D geom to a 2D one, if necessary. + if self.coord_dim != geom.coord_dim: + geom.coord_dim = self.coord_dim + + if self.make_multi(geom.geom_type, model_field): + # Constructing a multi-geometry type to contain the single geometry + multi_type = self.MULTI_TYPES[geom.geom_type.num] + g = OGRGeometry(multi_type) + g.add(geom) + else: + g = geom + + # Transforming the geometry with our Coordinate Transformation object, + # but only if the class variable `transform` is set w/a CoordTransform + # object. + if self.transform: + g.transform(self.transform) + + # Returning the WKT of the geometry. + return g.wkt + + # #### Other model methods #### + def coord_transform(self): + "Return the coordinate transformation object." + SpatialRefSys = self.spatial_backend.spatial_ref_sys() + try: + # Getting the target spatial reference system + target_srs = ( + SpatialRefSys.objects.using(self.using) + .get(srid=self.geo_field.srid) + .srs + ) + + # Creating the CoordTransform object + return CoordTransform(self.source_srs, target_srs) + except Exception as exc: + raise LayerMapError( + "Could not translate between the data source and model geometry." + ) from exc + + def geometry_field(self): + "Return the GeometryField instance associated with the geographic column." + # Use `get_field()` on the model's options so that we + # get the correct field instance if there's model inheritance. + opts = self.model._meta + return opts.get_field(self.geom_field) + + def make_multi(self, geom_type, model_field): + """ + Given the OGRGeomType for a geometry and its associated GeometryField, + determine whether the geometry should be turned into a GeometryCollection. + """ + return ( + geom_type.num in self.MULTI_TYPES + and model_field.__class__.__name__ == "Multi%s" % geom_type.django + ) + + def save( + self, + verbose=False, + fid_range=False, + step=False, + progress=False, + silent=False, + stream=sys.stdout, + strict=False, + ): + """ + Save the contents from the OGR DataSource Layer into the database + according to the mapping dictionary given at initialization. + + Keyword Parameters: + verbose: + If set, information will be printed subsequent to each model save + executed on the database. + + fid_range: + May be set with a slice or tuple of (begin, end) feature ID's to map + from the data source. In other words, this keyword enables the user + to selectively import a subset range of features in the geographic + data source. + + step: + If set with an integer, transactions will occur at every step + interval. For example, if step=1000, a commit would occur after + the 1,000th feature, the 2,000th feature etc. + + progress: + When this keyword is set, status information will be printed giving + the number of features processed and successfully saved. By default, + progress information will pe printed every 1000 features processed, + however, this default may be overridden by setting this keyword with an + integer for the desired interval. + + stream: + Status information will be written to this file handle. Defaults to + using `sys.stdout`, but any object with a `write` method is supported. + + silent: + By default, non-fatal error notifications are printed to stdout, but + this keyword may be set to disable these notifications. + + strict: + Execution of the model mapping will cease upon the first error + encountered. The default behavior is to attempt to continue. + """ + # Getting the default Feature ID range. + default_range = self.check_fid_range(fid_range) + + # Setting the progress interval, if requested. + if progress: + if progress is True or not isinstance(progress, int): + progress_interval = 1000 + else: + progress_interval = progress + + def _save(feat_range=default_range, num_feat=0, num_saved=0): + if feat_range: + layer_iter = self.layer[feat_range] + else: + layer_iter = self.layer + + for feat in layer_iter: + num_feat += 1 + # Getting the keyword arguments + try: + kwargs = self.feature_kwargs(feat) + except LayerMapError as msg: + # Something borked the validation + if strict: + raise + elif not silent: + stream.write( + "Ignoring Feature ID %s because: %s\n" % (feat.fid, msg) + ) + else: + # Constructing the model using the keyword args + is_update = False + if self.unique: + # If we want unique models on a particular field, handle the + # geometry appropriately. + try: + # Getting the keyword arguments and retrieving + # the unique model. + u_kwargs = self.unique_kwargs(kwargs) + m = self.model.objects.using(self.using).get(**u_kwargs) + is_update = True + + # Getting the geometry (in OGR form), creating + # one from the kwargs WKT, adding in additional + # geometries, and update the attribute with the + # just-updated geometry WKT. + geom_value = getattr(m, self.geom_field) + if geom_value is None: + geom = OGRGeometry(kwargs[self.geom_field]) + else: + geom = geom_value.ogr + new = OGRGeometry(kwargs[self.geom_field]) + for g in new: + geom.add(g) + setattr(m, self.geom_field, geom.wkt) + except ObjectDoesNotExist: + # No unique model exists yet, create. + m = self.model(**kwargs) + else: + m = self.model(**kwargs) + + try: + # Attempting to save. + m.save(using=self.using) + num_saved += 1 + if verbose: + stream.write( + "%s: %s\n" % ("Updated" if is_update else "Saved", m) + ) + except Exception as msg: + if strict: + # Bailing out if the `strict` keyword is set. + if not silent: + stream.write( + "Failed to save the feature (id: %s) into the " + "model with the keyword arguments:\n" % feat.fid + ) + stream.write("%s\n" % kwargs) + raise + elif not silent: + stream.write( + "Failed to save %s:\n %s\nContinuing\n" % (kwargs, msg) + ) + + # Printing progress information, if requested. + if progress and num_feat % progress_interval == 0: + stream.write( + "Processed %d features, saved %d ...\n" % (num_feat, num_saved) + ) + + # Only used for status output purposes -- incremental saving uses the + # values returned here. + return num_saved, num_feat + + if self.transaction_decorator is not None: + _save = self.transaction_decorator(_save) + + nfeat = self.layer.num_feat + if step and isinstance(step, int) and step < nfeat: + # Incremental saving is requested at the given interval (step) + if default_range: + raise LayerMapError( + "The `step` keyword may not be used in conjunction with the " + "`fid_range` keyword." + ) + beg, num_feat, num_saved = (0, 0, 0) + indices = range(step, nfeat, step) + n_i = len(indices) + + for i, end in enumerate(indices): + # Constructing the slice to use for this step; the last slice is + # special (e.g, [100:] instead of [90:100]). + if i + 1 == n_i: + step_slice = slice(beg, None) + else: + step_slice = slice(beg, end) + + try: + num_feat, num_saved = _save(step_slice, num_feat, num_saved) + beg = end + except Exception: # Deliberately catch everything + stream.write( + "%s\nFailed to save slice: %s\n" % ("=-" * 20, step_slice) + ) + raise + else: + # Otherwise, just calling the previously defined _save() function. + _save() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/utils/ogrinfo.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/utils/ogrinfo.py new file mode 100644 index 0000000..eafa23c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/utils/ogrinfo.py @@ -0,0 +1,53 @@ +""" +This module includes some utility functions for inspecting the layout +of a GDAL data source -- the functionality is analogous to the output +produced by the `ogrinfo` utility. +""" + +from django.contrib.gis.gdal import DataSource +from django.contrib.gis.gdal.geometries import GEO_CLASSES + + +def ogrinfo(data_source, num_features=10): + """ + Walk the available layers in the supplied `data_source`, displaying + the fields for the first `num_features` features. + """ + + # Checking the parameters. + if isinstance(data_source, str): + data_source = DataSource(data_source) + elif isinstance(data_source, DataSource): + pass + else: + raise Exception( + "Data source parameter must be a string or a DataSource object." + ) + + for i, layer in enumerate(data_source): + print("data source : %s" % data_source.name) + print("==== layer %s" % i) + print(" shape type: %s" % GEO_CLASSES[layer.geom_type.num].__name__) + print(" # features: %s" % len(layer)) + print(" srs: %s" % layer.srs) + extent_tup = layer.extent.tuple + print(" extent: %s - %s" % (extent_tup[0:2], extent_tup[2:4])) + print("Displaying the first %s features ====" % num_features) + + width = max(*map(len, layer.fields)) + fmt = " %%%ss: %%s" % width + for j, feature in enumerate(layer[:num_features]): + print("=== Feature %s" % j) + for fld_name in layer.fields: + type_name = feature[fld_name].type_name + output = fmt % (fld_name, type_name) + val = feature.get(fld_name) + if val: + if isinstance(val, str): + val_fmt = ' ("%s")' + else: + val_fmt = " (%s)" + output += val_fmt % val + else: + output += " (None)" + print(output) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/utils/ogrinspect.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/utils/ogrinspect.py new file mode 100644 index 0000000..40ca0cb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/utils/ogrinspect.py @@ -0,0 +1,267 @@ +""" +This module is for inspecting OGR data sources and generating either +models for GeoDjango and/or mapping dictionaries for use with the +`LayerMapping` utility. +""" +from django.contrib.gis.gdal import DataSource +from django.contrib.gis.gdal.field import ( + OFTDate, + OFTDateTime, + OFTInteger, + OFTInteger64, + OFTReal, + OFTString, + OFTTime, +) + + +def mapping(data_source, geom_name="geom", layer_key=0, multi_geom=False): + """ + Given a DataSource, generate a dictionary that may be used + for invoking the LayerMapping utility. + + Keyword Arguments: + `geom_name` => The name of the geometry field to use for the model. + + `layer_key` => The key for specifying which layer in the DataSource to use; + defaults to 0 (the first layer). May be an integer index or a string + identifier for the layer. + + `multi_geom` => Boolean (default: False) - specify as multigeometry. + """ + if isinstance(data_source, str): + # Instantiating the DataSource from the string. + data_source = DataSource(data_source) + elif isinstance(data_source, DataSource): + pass + else: + raise TypeError( + "Data source parameter must be a string or a DataSource object." + ) + + # Creating the dictionary. + _mapping = {} + + # Generating the field name for each field in the layer. + for field in data_source[layer_key].fields: + mfield = field.lower() + if mfield[-1:] == "_": + mfield += "field" + _mapping[mfield] = field + gtype = data_source[layer_key].geom_type + if multi_geom: + gtype.to_multi() + _mapping[geom_name] = str(gtype).upper() + return _mapping + + +def ogrinspect(*args, **kwargs): + """ + Given a data source (either a string or a DataSource object) and a string + model name this function will generate a GeoDjango model. + + Usage: + + >>> from django.contrib.gis.utils import ogrinspect + >>> ogrinspect('/path/to/shapefile.shp','NewModel') + + ...will print model definition to stout + + or put this in a Python script and use to redirect the output to a new + model like: + + $ python generate_model.py > myapp/models.py + + # generate_model.py + from django.contrib.gis.utils import ogrinspect + shp_file = 'data/mapping_hacks/world_borders.shp' + model_name = 'WorldBorders' + + print(ogrinspect(shp_file, model_name, multi_geom=True, srid=4326, + geom_name='shapes', blank=True)) + + Required Arguments + `datasource` => string or DataSource object to file pointer + + `model name` => string of name of new model class to create + + Optional Keyword Arguments + `geom_name` => For specifying the model name for the Geometry Field. + Otherwise will default to `geom` + + `layer_key` => The key for specifying which layer in the DataSource to use; + defaults to 0 (the first layer). May be an integer index or a string + identifier for the layer. + + `srid` => The SRID to use for the Geometry Field. If it can be determined, + the SRID of the datasource is used. + + `multi_geom` => Boolean (default: False) - specify as multigeometry. + + `name_field` => String - specifies a field name to return for the + __str__() method (which will be generated if specified). + + `imports` => Boolean (default: True) - set to False to omit the + `from django.contrib.gis.db import models` code from the + autogenerated models thus avoiding duplicated imports when building + more than one model by batching ogrinspect() + + `decimal` => Boolean or sequence (default: False). When set to True + all generated model fields corresponding to the `OFTReal` type will + be `DecimalField` instead of `FloatField`. A sequence of specific + field names to generate as `DecimalField` may also be used. + + `blank` => Boolean or sequence (default: False). When set to True all + generated model fields will have `blank=True`. If the user wants to + give specific fields to have blank, then a list/tuple of OGR field + names may be used. + + `null` => Boolean (default: False) - When set to True all generated + model fields will have `null=True`. If the user wants to specify + give specific fields to have null, then a list/tuple of OGR field + names may be used. + + Note: Call the _ogrinspect() helper to do the heavy lifting. + """ + return "\n".join(_ogrinspect(*args, **kwargs)) + + +def _ogrinspect( + data_source, + model_name, + geom_name="geom", + layer_key=0, + srid=None, + multi_geom=False, + name_field=None, + imports=True, + decimal=False, + blank=False, + null=False, +): + """ + Helper routine for `ogrinspect` that generates GeoDjango models corresponding + to the given data source. See the `ogrinspect` docstring for more details. + """ + # Getting the DataSource + if isinstance(data_source, str): + data_source = DataSource(data_source) + elif isinstance(data_source, DataSource): + pass + else: + raise TypeError( + "Data source parameter must be a string or a DataSource object." + ) + + # Getting the layer corresponding to the layer key and getting + # a string listing of all OGR fields in the Layer. + layer = data_source[layer_key] + ogr_fields = layer.fields + + # Creating lists from the `null`, `blank`, and `decimal` + # keyword arguments. + def process_kwarg(kwarg): + if isinstance(kwarg, (list, tuple)): + return [s.lower() for s in kwarg] + elif kwarg: + return [s.lower() for s in ogr_fields] + else: + return [] + + null_fields = process_kwarg(null) + blank_fields = process_kwarg(blank) + decimal_fields = process_kwarg(decimal) + + # Gets the `null` and `blank` keywords for the given field name. + def get_kwargs_str(field_name): + kwlist = [] + if field_name.lower() in null_fields: + kwlist.append("null=True") + if field_name.lower() in blank_fields: + kwlist.append("blank=True") + if kwlist: + return ", " + ", ".join(kwlist) + else: + return "" + + # For those wishing to disable the imports. + if imports: + yield "# This is an auto-generated Django model module created by ogrinspect." + yield "from django.contrib.gis.db import models" + yield "" + yield "" + + yield "class %s(models.Model):" % model_name + + for field_name, width, precision, field_type in zip( + ogr_fields, layer.field_widths, layer.field_precisions, layer.field_types + ): + # The model field name. + mfield = field_name.lower() + if mfield[-1:] == "_": + mfield += "field" + + # Getting the keyword args string. + kwargs_str = get_kwargs_str(field_name) + + if field_type is OFTReal: + # By default OFTReals are mapped to `FloatField`, however, they + # may also be mapped to `DecimalField` if specified in the + # `decimal` keyword. + if field_name.lower() in decimal_fields: + yield ( + " %s = models.DecimalField(max_digits=%d, decimal_places=%d%s)" + ) % ( + mfield, + width, + precision, + kwargs_str, + ) + else: + yield " %s = models.FloatField(%s)" % (mfield, kwargs_str[2:]) + elif field_type is OFTInteger: + yield " %s = models.IntegerField(%s)" % (mfield, kwargs_str[2:]) + elif field_type is OFTInteger64: + yield " %s = models.BigIntegerField(%s)" % (mfield, kwargs_str[2:]) + elif field_type is OFTString: + yield " %s = models.CharField(max_length=%s%s)" % ( + mfield, + width, + kwargs_str, + ) + elif field_type is OFTDate: + yield " %s = models.DateField(%s)" % (mfield, kwargs_str[2:]) + elif field_type is OFTDateTime: + yield " %s = models.DateTimeField(%s)" % (mfield, kwargs_str[2:]) + elif field_type is OFTTime: + yield " %s = models.TimeField(%s)" % (mfield, kwargs_str[2:]) + else: + raise TypeError("Unknown field type %s in %s" % (field_type, mfield)) + + # TODO: Autodetection of multigeometry types (see #7218). + gtype = layer.geom_type + if multi_geom: + gtype.to_multi() + geom_field = gtype.django + + # Setting up the SRID keyword string. + if srid is None: + if layer.srs is None: + srid_str = "srid=-1" + else: + srid = layer.srs.srid + if srid is None: + srid_str = "srid=-1" + elif srid == 4326: + # WGS84 is already the default. + srid_str = "" + else: + srid_str = "srid=%s" % srid + else: + srid_str = "srid=%s" % srid + + yield " %s = models.%s(%s)" % (geom_name, geom_field, srid_str) + + if name_field: + yield "" + yield " def __str__(self): return self.%s" % name_field diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/utils/srs.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/utils/srs.py new file mode 100644 index 0000000..2204767 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/utils/srs.py @@ -0,0 +1,78 @@ +from django.contrib.gis.gdal import SpatialReference +from django.db import DEFAULT_DB_ALIAS, connections + + +def add_srs_entry( + srs, auth_name="EPSG", auth_srid=None, ref_sys_name=None, database=None +): + """ + Take a GDAL SpatialReference system and add its information to the + `spatial_ref_sys` table of the spatial backend. Doing this enables + database-level spatial transformations for the backend. Thus, this utility + is useful for adding spatial reference systems not included by default with + the backend: + + >>> from django.contrib.gis.utils import add_srs_entry + >>> add_srs_entry(3857) + + Keyword Arguments: + auth_name: + This keyword may be customized with the value of the `auth_name` field. + Defaults to 'EPSG'. + + auth_srid: + This keyword may be customized with the value of the `auth_srid` field. + Defaults to the SRID determined by GDAL. + + ref_sys_name: + For SpatiaLite users only, sets the value of the `ref_sys_name` field. + Defaults to the name determined by GDAL. + + database: + The name of the database connection to use; the default is the value + of `django.db.DEFAULT_DB_ALIAS` (at the time of this writing, its value + is 'default'). + """ + database = database or DEFAULT_DB_ALIAS + connection = connections[database] + + if not hasattr(connection.ops, "spatial_version"): + raise Exception("The `add_srs_entry` utility only works with spatial backends.") + if not connection.features.supports_add_srs_entry: + raise Exception("This utility does not support your database backend.") + SpatialRefSys = connection.ops.spatial_ref_sys() + + # If argument is not a `SpatialReference` instance, use it as parameter + # to construct a `SpatialReference` instance. + if not isinstance(srs, SpatialReference): + srs = SpatialReference(srs) + + if srs.srid is None: + raise Exception( + "Spatial reference requires an SRID to be " + "compatible with the spatial backend." + ) + + # Initializing the keyword arguments dictionary for both PostGIS + # and SpatiaLite. + kwargs = { + "srid": srs.srid, + "auth_name": auth_name, + "auth_srid": auth_srid or srs.srid, + "proj4text": srs.proj4, + } + # Backend-specific fields for the SpatialRefSys model. + srs_field_names = {f.name for f in SpatialRefSys._meta.get_fields()} + if "srtext" in srs_field_names: + kwargs["srtext"] = srs.wkt + if "ref_sys_name" in srs_field_names: + # SpatiaLite specific + kwargs["ref_sys_name"] = ref_sys_name or srs.name + + # Creating the spatial_ref_sys model. + try: + # Try getting via SRID only, because using all kwargs may + # differ from exact wkt/proj in database. + SpatialRefSys.objects.using(database).get(srid=srs.srid) + except SpatialRefSys.DoesNotExist: + SpatialRefSys.objects.using(database).create(**kwargs) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/views.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/views.py new file mode 100644 index 0000000..346fb5b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/gis/views.py @@ -0,0 +1,22 @@ +from django.http import Http404 +from django.utils.translation import gettext as _ + + +def feed(request, url, feed_dict=None): + """Provided for backwards compatibility.""" + if not feed_dict: + raise Http404(_("No feeds are registered.")) + + slug = url.partition("/")[0] + try: + f = feed_dict[slug] + except KeyError: + raise Http404(_("Slug %r isn’t registered.") % slug) + + instance = f() + instance.feed_url = getattr(f, "feed_url", None) or request.path + instance.title_template = f.title_template or ("feeds/%s_title.html" % slug) + instance.description_template = f.description_template or ( + "feeds/%s_description.html" % slug + ) + return instance(request) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/apps.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/apps.py new file mode 100644 index 0000000..817ae96 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/apps.py @@ -0,0 +1,7 @@ +from django.apps import AppConfig +from django.utils.translation import gettext_lazy as _ + + +class HumanizeConfig(AppConfig): + name = "django.contrib.humanize" + verbose_name = _("Humanize") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/af/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/af/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d3f79ac Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/af/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/af/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/af/LC_MESSAGES/django.po new file mode 100644 index 0000000..087f017 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/af/LC_MESSAGES/django.po @@ -0,0 +1,328 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# F Wolff , 2019,2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:40+0000\n" +"Last-Translator: F Wolff , 2019,2023\n" +"Language-Team: Afrikaans (http://app.transifex.com/django/django/language/" +"af/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: af\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Humanise" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}de" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}ste" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}ste" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}ste" + +#. Translators: Ordinal format when value ends with 3, e.g. 83rd, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}ste" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}ste" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}ste" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}ste" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}ste" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}ste" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}ste" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s miljoen" +msgstr[1] "%(value)s miljoen" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s miljard" +msgstr[1] "%(value)s miljard" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s biljoen" +msgstr[1] "%(value)s biljoen" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s biljard" +msgstr[1] "%(value)s biljard" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s triljoen" +msgstr[1] "%(value)s triljoen" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s triljard" +msgstr[1] "%(value)s triljard" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s kwadriljoen" +msgstr[1] "%(value)s kwadriljoen" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s kwadriljard" +msgstr[1] "%(value)s kwadriljard" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s kwintiljoen" +msgstr[1] "%(value)s kwintiljoen" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s kwinteljard" +msgstr[1] "%(value)s kwinteljard" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "" +msgstr[1] "" + +msgid "one" +msgstr "een" + +msgid "two" +msgstr "twee" + +msgid "three" +msgstr "drie" + +msgid "four" +msgstr "vier" + +msgid "five" +msgstr "vyf" + +msgid "six" +msgstr "ses" + +msgid "seven" +msgstr "sewe" + +msgid "eight" +msgstr "agt" + +msgid "nine" +msgstr "nege" + +msgid "today" +msgstr "vandag" + +msgid "tomorrow" +msgstr "môre" + +msgid "yesterday" +msgstr "gister" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s gelede" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "’n uur gelede" +msgstr[1] "%(count)s uur gelede" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "’n minuut gelede" +msgstr[1] "%(count)s minute gelede" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "’n sekonde gelede" +msgstr[1] "%(count)s sekondes gelede" + +msgid "now" +msgstr "nou" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "oor ’n sekonde" +msgstr[1] "oor %(count)s sekondes" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "oor ’n minuut" +msgstr[1] "oor %(count)s minute" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "oor ’n uur" +msgstr[1] "oor %(count)s ure" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "oor %(delta)s" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d jaar" +msgstr[1] "%(num)d jaar" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d maand" +msgstr[1] "%(num)d maande" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d week" +msgstr[1] "%(num)d weke" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dag" +msgstr[1] "%(num)d dae" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d uur" +msgstr[1] "%(num)d uur" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuut" +msgstr[1] "%(num)d minute" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d jaar" +msgstr[1] "%(num)d jaar" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d maand" +msgstr[1] "%(num)d maande" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d week" +msgstr[1] "%(num)d weke" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dag" +msgstr[1] "%(num)d dae" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d uur" +msgstr[1] "%(num)d uur" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuut" +msgstr[1] "%(num)d minute" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ar/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ar/LC_MESSAGES/django.mo new file mode 100644 index 0000000..169bb73 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ar/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ar/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ar/LC_MESSAGES/django.po new file mode 100644 index 0000000..94c7f87 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ar/LC_MESSAGES/django.po @@ -0,0 +1,449 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bashar Al-Abdulhadi, 2020-2021 +# Bashar Al-Abdulhadi, 2014 +# Eyad Toma , 2013 +# Jannis Leidel , 2011 +# Muaaz Alsaied, 2020 +# Ossama Khayat , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2021-10-15 21:36+0000\n" +"Last-Translator: Bashar Al-Abdulhadi\n" +"Language-Team: Arabic (http://www.transifex.com/django/django/language/ar/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +msgid "Humanize" +msgstr "عمل صفة بشرية" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s مليون" +msgstr[1] "%(value)s مليون" +msgstr[2] "%(value)s مليون" +msgstr[3] "%(value)s ملايين" +msgstr[4] "%(value)s مليون" +msgstr[5] "%(value)s مليون" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s مليار" +msgstr[1] "%(value)s مليار" +msgstr[2] "%(value)s مليار" +msgstr[3] "%(value)s مليار" +msgstr[4] "%(value)s مليار" +msgstr[5] "%(value)s مليار" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s ترليون" +msgstr[1] "%(value)s ترليون" +msgstr[2] "%(value)s ترليون" +msgstr[3] "%(value)s ترليون" +msgstr[4] "%(value)s ترليون" +msgstr[5] "%(value)s ترليون" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s كوادرليون" +msgstr[1] "%(value)s كوادرليون" +msgstr[2] "%(value)s كوادرليون" +msgstr[3] "%(value)s كوادرليون" +msgstr[4] "%(value)s كوادرليون" +msgstr[5] "%(value)s كوادرليون" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s كوينتيليون" +msgstr[1] "%(value)s كوينتيليون" +msgstr[2] "%(value)s كوينتيليون" +msgstr[3] "%(value)s كوينتيليون" +msgstr[4] "%(value)s كوينتيليون" +msgstr[5] "%(value)s كوينتيليون" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s سكستيليون" +msgstr[1] "%(value)s سكستيليون" +msgstr[2] "%(value)s سكستيليون" +msgstr[3] "%(value)s سكستيليون" +msgstr[4] "%(value)s سكستيليون" +msgstr[5] "%(value)s سكستيليون" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s سبتيليون" +msgstr[1] "%(value)s سبتيليون" +msgstr[2] "%(value)s سبتيليون" +msgstr[3] "%(value)s سبتيليون" +msgstr[4] "%(value)s سبتيليون" +msgstr[5] "%(value)s سبتيليون" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s أقتيليون" +msgstr[1] "%(value)s أقتيليون" +msgstr[2] "%(value)s أقتيليون" +msgstr[3] "%(value)s أقتيليون" +msgstr[4] "%(value)s أقتيليون" +msgstr[5] "%(value)s أقتيليون" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s نانليون" +msgstr[1] "%(value)s نانليون" +msgstr[2] "%(value)s نانليون" +msgstr[3] "%(value)s نانليون" +msgstr[4] "%(value)s نانليون" +msgstr[5] "%(value)s نانليون" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s ديسيليون" +msgstr[1] "%(value)s ديسيليون" +msgstr[2] "%(value)s ديسيليون" +msgstr[3] "%(value)s ديسيليون" +msgstr[4] "%(value)s ديسيليون" +msgstr[5] "%(value)s ديسيليون" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s جوجول" +msgstr[1] "%(value)s جوجول" +msgstr[2] "%(value)s جوجول" +msgstr[3] "%(value)s جوجول" +msgstr[4] "%(value)s جوجول" +msgstr[5] "%(value)s جوجول" + +msgid "one" +msgstr "واحد" + +msgid "two" +msgstr "إثنان" + +msgid "three" +msgstr "ثلالثة" + +msgid "four" +msgstr "أربعة" + +msgid "five" +msgstr "خمسة" + +msgid "six" +msgstr "ستة" + +msgid "seven" +msgstr "سبعة" + +msgid "eight" +msgstr "ثمانية" + +msgid "nine" +msgstr "تسعة" + +msgid "today" +msgstr "اليوم" + +msgid "tomorrow" +msgstr "غداً" + +msgid "yesterday" +msgstr "أمس" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s مضت" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "منذ %(count)s ساعة" +msgstr[1] "منذ ساعة" +msgstr[2] "منذ %(count)s ساعة" +msgstr[3] "منذ %(count)s ساعة" +msgstr[4] "منذ %(count)s ساعة" +msgstr[5] "منذ %(count)s ساعة" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "منذ %(count)s دقيقة" +msgstr[1] "منذ دقيقة" +msgstr[2] "منذ %(count)s دقيقة" +msgstr[3] "منذ %(count)s دقيقة" +msgstr[4] "منذ %(count)s دقيقة" +msgstr[5] "منذ %(count)s دقيقة" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "منذ %(count)s ثانية" +msgstr[1] "منذ ثانية" +msgstr[2] "منذ %(count)s ثانيتين" +msgstr[3] "منذ %(count)s ثواني" +msgstr[4] "منذ %(count)s ثانية" +msgstr[5] "منذ %(count)s ثانية" + +msgid "now" +msgstr "الآن" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "%(count)s ثواني من الآن" +msgstr[1] "منذ ثانية من الآن" +msgstr[2] "%(count)s ثواني من الآن" +msgstr[3] "%(count)s ثواني من الآن" +msgstr[4] "%(count)s ثواني من الآن" +msgstr[5] "%(count)s ثواني من الآن" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "%(count)s دقائق من الآن" +msgstr[1] "منذ دقيقة من الآن" +msgstr[2] "%(count)s دقائق من الآن" +msgstr[3] "%(count)s دقائق من الآن" +msgstr[4] "%(count)s دقائق من الآن" +msgstr[5] "%(count)s دقائق من الآن" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "%(count)s ساعات من الآن" +msgstr[1] "منذ ساعة من الآن" +msgstr[2] "%(count)s ساعات من الآن" +msgstr[3] "%(count)s ساعات من الآن" +msgstr[4] "%(count)s ساعات من الآن" +msgstr[5] "%(count)s ساعات من الآن" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s من الآن" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d سنة" +msgstr[1] "%(num)d سنة" +msgstr[2] "%(num)d سنتين" +msgstr[3] "%(num)d سنوات" +msgstr[4] "%(num)d سنوات" +msgstr[5] "%(num)d سنوات" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d شهر" +msgstr[1] "%(num)d شهر" +msgstr[2] "%(num)d شهرين" +msgstr[3] "%(num)d أشهر" +msgstr[4] "%(num)d أشهر" +msgstr[5] "%(num)d أشهر" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d أسبوع" +msgstr[1] "%(num)d أسبوع" +msgstr[2] "%(num)d أسبوعين" +msgstr[3] "%(num)d أسابيع" +msgstr[4] "%(num)d أسبوع" +msgstr[5] "%(num)d أسابيع" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d يوم" +msgstr[1] "%(num)d يوم" +msgstr[2] "%(num)d يومين" +msgstr[3] "%(num)d أيام" +msgstr[4] "%(num)d يوم" +msgstr[5] "%(num)d أيام" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d ساعة" +msgstr[1] "%(num)d ساعة" +msgstr[2] "%(num)d ساعتين" +msgstr[3] "%(num)d ساعات" +msgstr[4] "%(num)d ساعة" +msgstr[5] "%(num)d ساعات" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d دقيقة" +msgstr[1] "%(num)d دقيقة" +msgstr[2] "%(num)d دقيقتين" +msgstr[3] "%(num)d دقائق" +msgstr[4] "%(num)d دقيقة" +msgstr[5] "%(num)d دقيقة" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d سنة" +msgstr[1] "%(num)d سنة" +msgstr[2] "%(num)d سنتين" +msgstr[3] "%(num)d سنوات" +msgstr[4] "%(num)d سنة" +msgstr[5] "%(num)d سنوات" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d شهر" +msgstr[1] "%(num)d شهر" +msgstr[2] "%(num)d شهرين" +msgstr[3] "%(num)d أشهر" +msgstr[4] "%(num)d شهر" +msgstr[5] "%(num)d أشهر" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d أسبوع" +msgstr[1] "%(num)d أسبوع" +msgstr[2] "%(num)d أسبوعين" +msgstr[3] "%(num)d أسابيع" +msgstr[4] "%(num)d أسبوع" +msgstr[5] "%(num)d أسابيع" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d يوم" +msgstr[1] "%(num)d يوم" +msgstr[2] "%(num)d يومين" +msgstr[3] "%(num)d أيام" +msgstr[4] "%(num)d يوم" +msgstr[5] "%(num)d أيام" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d ساعة" +msgstr[1] "%(num)d ساعة" +msgstr[2] "%(num)d ساعتين" +msgstr[3] "%(num)d ساعات" +msgstr[4] "%(num)d ساعة" +msgstr[5] "%(num)d ساعات" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d دقيقة" +msgstr[1] "%(num)d دقيقة" +msgstr[2] "%(num)d دقيقتين" +msgstr[3] "%(num)d دقائق" +msgstr[4] "%(num)d دقيقة" +msgstr[5] "%(num)d دقيقة" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ar_DZ/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ar_DZ/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d61abbd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ar_DZ/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ar_DZ/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ar_DZ/LC_MESSAGES/django.po new file mode 100644 index 0000000..4e4c151 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ar_DZ/LC_MESSAGES/django.po @@ -0,0 +1,555 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Riterix , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2019-12-16 02:59+0000\n" +"Last-Translator: Riterix \n" +"Language-Team: Arabic (Algeria) (http://www.transifex.com/django/django/" +"language/ar_DZ/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar_DZ\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +msgid "Humanize" +msgstr "عمل صفة بشرية" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f مليون" +msgstr[1] "%(value).1f مليون" +msgstr[2] "%(value).1f مليونان" +msgstr[3] "%(value).1f مليون" +msgstr[4] "%(value).1f مليون" +msgstr[5] "%(value).1f مليون" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s مليون" +msgstr[1] "%(value)s مليون" +msgstr[2] "%(value)s مليون" +msgstr[3] "%(value)s ملايين" +msgstr[4] "%(value)s مليون" +msgstr[5] "%(value)s مليون" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f مليار" +msgstr[1] "%(value).1f مليار" +msgstr[2] "%(value).1f ملياران" +msgstr[3] "%(value).1f مليار" +msgstr[4] "%(value).1f مليار" +msgstr[5] "%(value).1f مليار" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s مليار" +msgstr[1] "%(value)s مليار" +msgstr[2] "%(value)s مليار" +msgstr[3] "%(value)s مليار" +msgstr[4] "%(value)s مليار" +msgstr[5] "%(value)s مليار" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f ترليون" +msgstr[1] "%(value).1f ترليون" +msgstr[2] "%(value).1f ترليونان" +msgstr[3] "%(value).1f ترليونات" +msgstr[4] "%(value).1f ترليون" +msgstr[5] "%(value).1f ترليون" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s ترليون" +msgstr[1] "%(value)s ترليون" +msgstr[2] "%(value)s ترليون" +msgstr[3] "%(value)s ترليون" +msgstr[4] "%(value)s ترليون" +msgstr[5] "%(value)s ترليون" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f كوادرليون" +msgstr[1] "%(value).1f كوادرليون" +msgstr[2] "%(value).1f كوادرليون" +msgstr[3] "%(value).1f كوادرليون" +msgstr[4] "%(value).1f كوادرليون" +msgstr[5] "%(value).1f كوادرليون" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s كوادرليون" +msgstr[1] "%(value)s كوادرليون" +msgstr[2] "%(value)s كوادرليون" +msgstr[3] "%(value)s كوادرليون" +msgstr[4] "%(value)s كوادرليون" +msgstr[5] "%(value)s كوادرليون" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f كوينتيليون" +msgstr[1] "%(value).1f كوينتيليون" +msgstr[2] "%(value).1f كوينتيليون" +msgstr[3] "%(value).1f كوينتيليون" +msgstr[4] "%(value).1f كوينتيليون" +msgstr[5] "%(value).1f كوينتيليون" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s كوينتيليون" +msgstr[1] "%(value)s كوينتيليون" +msgstr[2] "%(value)s كوينتيليون" +msgstr[3] "%(value)s كوينتيليون" +msgstr[4] "%(value)s كوينتيليون" +msgstr[5] "%(value)s كوينتيليون" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f سكستيليون" +msgstr[1] "%(value).1f سكستيليون" +msgstr[2] "%(value).1f سكستيليون" +msgstr[3] "%(value).1f سكستيليون" +msgstr[4] "%(value).1f سكستيليون" +msgstr[5] "%(value).1f سكستيليون" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s سكستيليون" +msgstr[1] "%(value)s سكستيليون" +msgstr[2] "%(value)s سكستيليون" +msgstr[3] "%(value)s سكستيليون" +msgstr[4] "%(value)s سكستيليون" +msgstr[5] "%(value)s سكستيليون" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f سبتيليون" +msgstr[1] "%(value).1f سبتيليون" +msgstr[2] "%(value).1f سبتيليون" +msgstr[3] "%(value).1f سبتيليون" +msgstr[4] "%(value).1f سبتيليون" +msgstr[5] "%(value).1f سبتيليون" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s سبتيليون" +msgstr[1] "%(value)s سبتيليون" +msgstr[2] "%(value)s سبتيليون" +msgstr[3] "%(value)s سبتيليون" +msgstr[4] "%(value)s سبتيليون" +msgstr[5] "%(value)s سبتيليون" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f أقتيليون" +msgstr[1] "%(value).1f أقتيليون" +msgstr[2] "%(value).1f أقتيليون" +msgstr[3] "%(value).1f أقتيليون" +msgstr[4] "%(value).1f أقتيليون" +msgstr[5] "%(value).1f أقتيليون" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s أقتيليون" +msgstr[1] "%(value)s أقتيليون" +msgstr[2] "%(value)s أقتيليون" +msgstr[3] "%(value)s أقتيليون" +msgstr[4] "%(value)s أقتيليون" +msgstr[5] "%(value)s أقتيليون" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f نانليون" +msgstr[1] "%(value).1f نانليون" +msgstr[2] "%(value).1f نانليون" +msgstr[3] "%(value).1f نانليون" +msgstr[4] "%(value).1f نانليون" +msgstr[5] "%(value).1f نانليون" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s نانليون" +msgstr[1] "%(value)s نانليون" +msgstr[2] "%(value)s نانليون" +msgstr[3] "%(value)s نانليون" +msgstr[4] "%(value)s نانليون" +msgstr[5] "%(value)s نانليون" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f ديسيليون" +msgstr[1] "%(value).1f ديسيليون" +msgstr[2] "%(value).1f ديسيليون" +msgstr[3] "%(value).1f ديسيليون" +msgstr[4] "%(value).1f ديسيليون" +msgstr[5] "%(value).1f ديسيليون" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s ديسيليون" +msgstr[1] "%(value)s ديسيليون" +msgstr[2] "%(value)s ديسيليون" +msgstr[3] "%(value)s ديسيليون" +msgstr[4] "%(value)s ديسيليون" +msgstr[5] "%(value)s ديسيليون" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f جوجول" +msgstr[1] "%(value).1f جوجول" +msgstr[2] "%(value).1f جوجول" +msgstr[3] "%(value).1f جوجول" +msgstr[4] "%(value).1f جوجول" +msgstr[5] "%(value).1f جوجول" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s جوجول" +msgstr[1] "%(value)s جوجول" +msgstr[2] "%(value)s جوجول" +msgstr[3] "%(value)s جوجول" +msgstr[4] "%(value)s جوجول" +msgstr[5] "%(value)s جوجول" + +msgid "one" +msgstr "واحد" + +msgid "two" +msgstr "إثنان" + +msgid "three" +msgstr "ثلالثة" + +msgid "four" +msgstr "أربعة" + +msgid "five" +msgstr "خمسة" + +msgid "six" +msgstr "ستة" + +msgid "seven" +msgstr "سبعة" + +msgid "eight" +msgstr "ثمانية" + +msgid "nine" +msgstr "تسعة" + +msgid "today" +msgstr "اليوم" + +msgid "tomorrow" +msgstr "غداً" + +msgid "yesterday" +msgstr "أمس" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s مضت" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "منذ %(count)s ساعة" +msgstr[1] "منذ ساعة" +msgstr[2] "منذ %(count)s ساعة" +msgstr[3] "منذ %(count)s ساعة" +msgstr[4] "منذ %(count)s ساعة" +msgstr[5] "منذ %(count)s ساعة" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "منذ %(count)s دقيقة" +msgstr[1] "منذ دقيقة" +msgstr[2] "منذ %(count)s دقيقة" +msgstr[3] "منذ %(count)s دقيقة" +msgstr[4] "منذ %(count)s دقيقة" +msgstr[5] "منذ %(count)s دقيقة" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "منذ %(count)s ثانية" +msgstr[1] "منذ ثانية" +msgstr[2] "منذ %(count)s ثانيتين" +msgstr[3] "منذ %(count)s ثواني" +msgstr[4] "منذ %(count)s ثانية" +msgstr[5] "منذ %(count)s ثانية" + +msgid "now" +msgstr "الآن" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "%(count)s ثواني من الآن" +msgstr[1] "منذ ثانية من الآن" +msgstr[2] "%(count)s ثواني من الآن" +msgstr[3] "%(count)s ثواني من الآن" +msgstr[4] "%(count)s ثواني من الآن" +msgstr[5] "%(count)s ثواني من الآن" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "%(count)s دقائق من الآن" +msgstr[1] "منذ دقيقة من الآن" +msgstr[2] "%(count)s دقائق من الآن" +msgstr[3] "%(count)s دقائق من الآن" +msgstr[4] "%(count)s دقائق من الآن" +msgstr[5] "%(count)s دقائق من الآن" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "%(count)s ساعات من الآن" +msgstr[1] "منذ ساعة من الآن" +msgstr[2] "%(count)s ساعات من الآن" +msgstr[3] "%(count)s ساعات من الآن" +msgstr[4] "%(count)s ساعات من الآن" +msgstr[5] "%(count)s ساعات من الآن" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s من الآن" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d سنة" +msgstr[1] "%d سنة" +msgstr[2] "%d سنتين" +msgstr[3] "%d سنوات" +msgstr[4] "%d سنة" +msgstr[5] "%d سنة" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d شهر" +msgstr[1] "%d شهر" +msgstr[2] "%d شهرين" +msgstr[3] "%d أشهر" +msgstr[4] "%d شهر" +msgstr[5] "%d شهر" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d اسبوع" +msgstr[1] "%d اسبوع" +msgstr[2] "%d أسبوعين" +msgstr[3] "%d أسابيع" +msgstr[4] "%d اسبوع" +msgstr[5] "%d اسبوع" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d يوم" +msgstr[1] "%d يوم" +msgstr[2] "%d يومان" +msgstr[3] "%d أيام" +msgstr[4] "%d يوم" +msgstr[5] "%d يوم" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d ساعة" +msgstr[1] "%d ساعة واحدة" +msgstr[2] "%d ساعتين" +msgstr[3] "%d ساعات" +msgstr[4] "%d ساعة" +msgstr[5] "%d ساعة" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d دقيقة" +msgstr[1] "%d دقيقة" +msgstr[2] "%d دقيقتين" +msgstr[3] "%d دقائق" +msgstr[4] "%d دقيقة" +msgstr[5] "%d دقيقة" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d سنة" +msgstr[1] "%d سنة" +msgstr[2] "%d سنتين" +msgstr[3] "%d سنوات" +msgstr[4] "%d سنة" +msgstr[5] "%d سنة" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d شهر" +msgstr[1] "%d شهر" +msgstr[2] "%d شهرين" +msgstr[3] "%d أشهر" +msgstr[4] "%d شهر" +msgstr[5] "%d شهر" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d أسبوع" +msgstr[1] "%d أسبوع" +msgstr[2] "%d أسبوعين" +msgstr[3] "%d أسابيع" +msgstr[4] "%d أسبوع" +msgstr[5] "%d أسبوع" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d يوم" +msgstr[1] "%d يوم" +msgstr[2] "%d يومان" +msgstr[3] "%d أيام" +msgstr[4] "%d يوم" +msgstr[5] "%d يوم" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d ساعة" +msgstr[1] "%d ساعة واحدة" +msgstr[2] "%d ساعتين" +msgstr[3] "%d ساعات" +msgstr[4] "%d ساعة" +msgstr[5] "%d ساعة" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d دقيقة" +msgstr[1] "%d دقيقة" +msgstr[2] "%d دقيقتين" +msgstr[3] "%d دقائق" +msgstr[4] "%d دقيقة" +msgstr[5] "%d دقيقة" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ast/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ast/LC_MESSAGES/django.mo new file mode 100644 index 0000000..049aab2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ast/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ast/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ast/LC_MESSAGES/django.po new file mode 100644 index 0000000..50f4794 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ast/LC_MESSAGES/django.po @@ -0,0 +1,262 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ḷḷumex03 , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 19:51+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Asturian (http://www.transifex.com/django/django/language/" +"ast/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ast\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "" + +msgid "th" +msgstr "ᵘ" + +msgid "st" +msgstr "ᵘ" + +msgid "nd" +msgstr "ᵘ" + +msgid "rd" +msgstr "ᵘ" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f millón" +msgstr[1] "%(value).1f millones" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s millón" +msgstr[1] "%(value)s millones" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f billón" +msgstr[1] "%(value).1f billones" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s billón" +msgstr[1] "%(value)s billones" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f trillón" +msgstr[1] "%(value).1f trillones" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s trillón" +msgstr[1] "%(value)s trillones" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f cuatrillón" +msgstr[1] "%(value).1f cuatrillones" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s cuatrillón" +msgstr[1] "%(value)s cuatrillones" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f quintillón" +msgstr[1] "%(value).1f quintillones" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s quintillón" +msgstr[1] "%(value)s quintillones" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f sextillón" +msgstr[1] "%(value).1f sextillones" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s sextillón" +msgstr[1] "%(value)s sextillones" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f septillón" +msgstr[1] "%(value).1f septillones" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septillón" +msgstr[1] "%(value)s septillones" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f octillón" +msgstr[1] "%(value).1f octillones" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s octillón" +msgstr[1] "%(value)s octillones" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f nonillón" +msgstr[1] "%(value).1f nonillones" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s nonillón" +msgstr[1] "%(value)s nonillones" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f decillón" +msgstr[1] "%(value).1f decillones" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s decillón" +msgstr[1] "%(value)s decillones" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f gúgol" +msgstr[1] "%(value).1f gúgol" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s gúgol" +msgstr[1] "%(value)s gúgol" + +msgid "one" +msgstr "un" + +msgid "two" +msgstr "dos" + +msgid "three" +msgstr "trés" + +msgid "four" +msgstr "cuatro" + +msgid "five" +msgstr "cinco" + +msgid "six" +msgstr "seis" + +msgid "seven" +msgstr "siete" + +msgid "eight" +msgstr "ocho" + +msgid "nine" +msgstr "nueve" + +msgid "today" +msgstr "güei" + +msgid "tomorrow" +msgstr "mañana" + +msgid "yesterday" +msgstr "ayeri" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "hai %(delta)s" + +msgid "now" +msgstr "agora" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "%(delta)s dende agora" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/az/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/az/LC_MESSAGES/django.mo new file mode 100644 index 0000000..251d93f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/az/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/az/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/az/LC_MESSAGES/django.po new file mode 100644 index 0000000..2729a9b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/az/LC_MESSAGES/django.po @@ -0,0 +1,332 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ali Ismayilov , 2011 +# Claude Paroz , 2013 +# Emin Mastizada , 2018,2020 +# Emin Mastizada , 2016 +# Nicat Məmmədov , 2022 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2022-07-24 18:40+0000\n" +"Last-Translator: Nicat Məmmədov \n" +"Language-Team: Azerbaijani (http://www.transifex.com/django/django/language/" +"az/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: az\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "İnsanlaşdır" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}ci" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}ci" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}cü" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}cü" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}ci" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}cı" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}ci" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}ci" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}cu" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s milyon" +msgstr[1] "%(value)s milyon" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s milyard" +msgstr[1] "%(value)s milyard" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s trilyon" +msgstr[1] "%(value)s trilyon" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s kvadrilyon" +msgstr[1] "%(value)s kvadrilyon" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s kvintilyon" +msgstr[1] "%(value)s kvintilyon" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s sekstilyon" +msgstr[1] "%(value)s sekstilyon" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septilyon" +msgstr[1] "%(value)s septilyon" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s oktilyon" +msgstr[1] "%(value)s oktilyon" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s nonilyon" +msgstr[1] "%(value)s nonilyon" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s deçilyon" +msgstr[1] "%(value)s deçilyon" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s quqol" +msgstr[1] "%(value)s quqol" + +msgid "one" +msgstr "bir" + +msgid "two" +msgstr "iki" + +msgid "three" +msgstr "üç" + +msgid "four" +msgstr "dörd" + +msgid "five" +msgstr "beş" + +msgid "six" +msgstr "altı" + +msgid "seven" +msgstr "yeddi" + +msgid "eight" +msgstr "səkkiz" + +msgid "nine" +msgstr "doqquz" + +msgid "today" +msgstr "bu gün" + +msgid "tomorrow" +msgstr "sabah" + +msgid "yesterday" +msgstr "dünən" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s əvvəl" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "bir saat əvvəl" +msgstr[1] "%(count)s saat əvvəl" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "bir dəqiqə əvvəl" +msgstr[1] "%(count)s dəqiqə əvvəl" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "bir saniyə əvvəl" +msgstr[1] "%(count)s saniyə əvvəl" + +msgid "now" +msgstr "indi" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "bir saniyə sonra" +msgstr[1] "%(count)s saniyə sonra" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "bir dəqiqə sonra" +msgstr[1] "%(count)s dəqiqə sonra" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "bir saat sonra" +msgstr[1] "%(count)s saat sonra" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s bundan sonra" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d il" +msgstr[1] "%(num)d il" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d ay" +msgstr[1] "%(num)d ay" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d həftə" +msgstr[1] "%(num)d həftə" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d gün" +msgstr[1] "%(num)d gün" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d saat" +msgstr[1] "%(num)d saat" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d dəqiqə" +msgstr[1] "%(num)d dəqiqə" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d il" +msgstr[1] "%(num)d il" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d ay" +msgstr[1] "%(num)d ay" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d həftə" +msgstr[1] "%(num)d həftə" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d gün" +msgstr[1] "%(num)d gün" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d saat" +msgstr[1] "%(num)d saat" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d dəqiqə" +msgstr[1] "%(num)d dəqiqə" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/be/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/be/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ed7b846 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/be/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/be/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/be/LC_MESSAGES/django.po new file mode 100644 index 0000000..565b5b3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/be/LC_MESSAGES/django.po @@ -0,0 +1,389 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Viktar Palstsiuk , 2014-2015 +# znotdead , 2019,2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2021-09-22 16:47+0000\n" +"Last-Translator: znotdead \n" +"Language-Team: Belarusian (http://www.transifex.com/django/django/language/" +"be/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: be\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n" +"%100>=11 && n%100<=14)? 2 : 3);\n" + +msgid "Humanize" +msgstr "Ачалавечваньне" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}ы" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}ы" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}ы" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}і" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}і" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}ы" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}ы" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}ы" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}ы" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}ы" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}ы" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s мільён" +msgstr[1] "%(value)s мільёны" +msgstr[2] "%(value)s мільёнаў" +msgstr[3] "%(value)s мільёнаў" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value).s мільярд" +msgstr[1] "%(value)s мільярды" +msgstr[2] "%(value)s мільярдаў" +msgstr[3] "%(value)s мільярдаў" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s трыльён" +msgstr[1] "%(value)s трыльёны" +msgstr[2] "%(value)s трыльёнаў" +msgstr[3] "%(value)s трыльёнаў" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s квадрыльён" +msgstr[1] "%(value)s квадрыльёны" +msgstr[2] "%(value)s квадрыльёнаў" +msgstr[3] "%(value)s квадрыльёнаў" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s квінтыльён" +msgstr[1] "%(value)s квінтыльёны" +msgstr[2] "%(value)s квінтыльёнаў" +msgstr[3] "%(value)s квінтыльёнаў" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s сэкстыльён" +msgstr[1] "%(value)s сэкстыльёны" +msgstr[2] "%(value)s сэкстыльёнаў" +msgstr[3] "%(value)s сэкстыльёнаў" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s сэптыльён" +msgstr[1] "%(value)s сэптыльёны" +msgstr[2] "%(value)s сэптыльёнаў" +msgstr[3] "%(value)s сэптыльёнаў" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s актыльён" +msgstr[1] "%(value)s актыльёны" +msgstr[2] "%(value)s актыльёнаў" +msgstr[3] "%(value)s актыльёнаў" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s нанільён" +msgstr[1] "%(value)s нанільёны" +msgstr[2] "%(value)s нанільёнаў" +msgstr[3] "%(value)s нанільёнаў" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s дэцыльён" +msgstr[1] "%(value)s дэцыльёны" +msgstr[2] "%(value)s дэцыльёнаў" +msgstr[3] "%(value)s дэцыльёнаў" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s ґуґал" +msgstr[1] "%(value)s ґуґлы" +msgstr[2] "%(value)s ґуґлаў" +msgstr[3] "%(value)s ґуґлаў" + +msgid "one" +msgstr "адзін" + +msgid "two" +msgstr "два" + +msgid "three" +msgstr "тры" + +msgid "four" +msgstr "чатыры" + +msgid "five" +msgstr "пяць" + +msgid "six" +msgstr "шэсьць" + +msgid "seven" +msgstr "сем" + +msgid "eight" +msgstr "восем" + +msgid "nine" +msgstr "дзевяць" + +msgid "today" +msgstr "сёньня" + +msgid "tomorrow" +msgstr "заўтра" + +msgid "yesterday" +msgstr "ўчора" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s таму" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "%(count)s гадзіну таму" +msgstr[1] "%(count)s гадзіны таму" +msgstr[2] "%(count)s гадзінаў таму" +msgstr[3] "%(count)s гадзінаў таму" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "%(count)s хвіліну таму" +msgstr[1] "%(count)s хвіліны таму" +msgstr[2] "%(count)s хвілінаў таму" +msgstr[3] "%(count)s хвілінаў таму" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "%(count)s сэкунду таму" +msgstr[1] "%(count)s сэкунды таму" +msgstr[2] "%(count)s сэкундаў таму" +msgstr[3] "%(count)s сэкундаў таму" + +msgid "now" +msgstr "зараз" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "праз %(count)s сэкунду" +msgstr[1] "праз %(count)s сэкунды" +msgstr[2] "праз %(count)s сэкундаў" +msgstr[3] "праз %(count)s сэкундаў" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "праз %(count)s хвіліну" +msgstr[1] "праз %(count)s хвіліны" +msgstr[2] "праз %(count)s хвілінаў" +msgstr[3] "праз %(count)s хвілінаў" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "праз %(count)s гадзіну" +msgstr[1] "праз %(count)s гадзіны" +msgstr[2] "праз %(count)s гадзінаў" +msgstr[3] "праз %(count)s гадзінаў" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "праз %(delta)s" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d год" +msgstr[1] "%(num)d гадоў" +msgstr[2] "%(num)d гадоў" +msgstr[3] "%(num)d гадоў" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d месяц" +msgstr[1] "%(num)d месяцаў" +msgstr[2] "%(num)d месяцаў" +msgstr[3] "%(num)d месяцаў" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d тыдзень" +msgstr[1] "%(num)d тыдняў" +msgstr[2] "%(num)d тыдняў" +msgstr[3] "%(num)d тыдняў" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d дзень" +msgstr[1] "%(num)d дзён" +msgstr[2] "%(num)d дзён" +msgstr[3] "%(num)d дзён" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d гадзіна" +msgstr[1] "%(num)d гадзін" +msgstr[2] "%(num)d гадзін" +msgstr[3] "%(num)d гадзін" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d хвіліна" +msgstr[1] "%(num)d хвілін" +msgstr[2] "%(num)d хвілін" +msgstr[3] "%(num)d хвілін" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d год" +msgstr[1] "%(num)d гадоў" +msgstr[2] "%(num)d гадоў" +msgstr[3] "%(num)d гадоў" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d месяц" +msgstr[1] "%(num)d месяцаў" +msgstr[2] "%(num)d месяцаў" +msgstr[3] "%(num)d месяцаў" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d тыдзень" +msgstr[1] "%(num)d тыдняў" +msgstr[2] "%(num)d тыдняў" +msgstr[3] "%(num)d тыдняў" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d дзень" +msgstr[1] "%(num)d дзён" +msgstr[2] "%(num)d дзён" +msgstr[3] "%(num)d дзён" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d гадзіна" +msgstr[1] "%(num)d гадзін" +msgstr[2] "%(num)d гадзін" +msgstr[3] "%(num)d гадзін" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d хвіліна" +msgstr[1] "%(num)d хвілін" +msgstr[2] "%(num)d хвілін" +msgstr[3] "%(num)d хвілін" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/bg/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/bg/LC_MESSAGES/django.mo new file mode 100644 index 0000000..85cdff8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/bg/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/bg/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/bg/LC_MESSAGES/django.po new file mode 100644 index 0000000..a4f6ad6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/bg/LC_MESSAGES/django.po @@ -0,0 +1,332 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# arneatec , 2022 +# Georgi Kostadinov , 2012 +# Jannis Leidel , 2011 +# Todor Lubenov , 2011,2015 +# Venelin Stoykov , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2022-01-14 11:48+0000\n" +"Last-Translator: arneatec \n" +"Language-Team: Bulgarian (http://www.transifex.com/django/django/language/" +"bg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Очовечаване" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}ти" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}ен" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}ви" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}ри" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}ти" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}ти" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}ти" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}ти" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}ми" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}ми" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}ти" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s милион" +msgstr[1] "%(value)s милиона" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s милиард" +msgstr[1] "%(value)s милиарда" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s трилион" +msgstr[1] "%(value)s трилиона" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s квадрилион" +msgstr[1] "%(value)s квадрилиона" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s квинтилион" +msgstr[1] "%(value)s квинтилиона" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s секстилион" +msgstr[1] "%(value)s секстилиона" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s септилион" +msgstr[1] "%(value)s септилиона" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s октилион" +msgstr[1] "%(value)s октилиона" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s нонилион" +msgstr[1] "%(value)s нонилиона" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s децилион" +msgstr[1] "%(value)s децилиона" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s гугол" +msgstr[1] "%(value)s гугола" + +msgid "one" +msgstr "един" + +msgid "two" +msgstr "два" + +msgid "three" +msgstr "три" + +msgid "four" +msgstr "четири" + +msgid "five" +msgstr "пет" + +msgid "six" +msgstr "шест" + +msgid "seven" +msgstr "седем" + +msgid "eight" +msgstr "осем" + +msgid "nine" +msgstr "девет" + +msgid "today" +msgstr "днес" + +msgid "tomorrow" +msgstr "утре" + +msgid "yesterday" +msgstr "вчера" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "преди %(delta)s" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "преди един час" +msgstr[1] "преди %(count)s часа" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "преди минута" +msgstr[1] "преди %(count)s минути" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "преди секунда" +msgstr[1] "преди %(count)s секунди" + +msgid "now" +msgstr "сега" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "след секунда" +msgstr[1] "след %(count)s секунди" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "след минута" +msgstr[1] "след %(count)s минути" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "след един час" +msgstr[1] "след %(count)s часа" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "след %(delta)s" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d година" +msgstr[1] "%(num)d години" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d месец" +msgstr[1] "%(num)d месеца" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d седмица" +msgstr[1] "%(num)d седмици" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d ден" +msgstr[1] "%(num)d дни" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d час" +msgstr[1] "%(num)d часа" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d минута" +msgstr[1] "%(num)d минути" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d година" +msgstr[1] "%(num)d години" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d месец" +msgstr[1] "%(num)d месеца" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d седмица" +msgstr[1] "%(num)d седмици" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d ден" +msgstr[1] "%(num)d дни" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d час" +msgstr[1] "%(num)d часа" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d минута" +msgstr[1] "%(num)d минути" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/bn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/bn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..042122a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/bn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/bn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/bn/LC_MESSAGES/django.po new file mode 100644 index 0000000..2b60f57 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/bn/LC_MESSAGES/django.po @@ -0,0 +1,263 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Tahmid Rafi , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Tahmid Rafi \n" +"Language-Team: Bengali (http://www.transifex.com/django/django/language/" +"bn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "" + +msgid "th" +msgstr "তম" + +msgid "st" +msgstr "ম" + +msgid "nd" +msgstr "য়" + +msgid "rd" +msgstr "য়" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f মিলিয়ন" +msgstr[1] "%(value).1f মিলিয়ন" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s মিলিয়ন" +msgstr[1] "%(value)s মিলিয়ন" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f বিলিয়ন" +msgstr[1] "%(value).1f বিলিয়ন" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s বিলিয়ন" +msgstr[1] "%(value)s বিলিয়ন" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f ট্রিলিয়ন" +msgstr[1] "%(value).1f ট্রিলিয়ন" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s ট্রিলিয়ন" +msgstr[1] "%(value)s ট্রিলিয়ন" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s কোয়াড্রিলিয়ন" +msgstr[1] "%(value)s কোয়াড্রিলিয়ন" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s কুইন্টিলিয়ন" +msgstr[1] "%(value)s কুইন্টিলিয়ন" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s সেক্সটিলিয়ন" +msgstr[1] "%(value)s সেক্সটিলিয়ন" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s সেপ্টিলিয়ন" +msgstr[1] "%(value)s সেপ্টিলিয়ন" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s অক্টিলিয়ন" +msgstr[1] "%(value)s অক্টিলিয়ন" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s ননিলিয়ন" +msgstr[1] "%(value)s ননিলিয়ন" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s ডেসিলিয়ন" +msgstr[1] "%(value)s ডেসিলিয়ন" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s গোগোল" +msgstr[1] "%(value)s গোগোল" + +msgid "one" +msgstr "এক" + +msgid "two" +msgstr "দুই" + +msgid "three" +msgstr "তিন" + +msgid "four" +msgstr "চার" + +msgid "five" +msgstr "পাঁচ" + +msgid "six" +msgstr "ছয়" + +msgid "seven" +msgstr "সাত" + +msgid "eight" +msgstr "আট" + +msgid "nine" +msgstr "নয়" + +msgid "today" +msgstr "আজ" + +msgid "tomorrow" +msgstr "আগামীকাল" + +msgid "yesterday" +msgstr "গতকাল" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "%(delta)s আগে" + +msgid "now" +msgstr "এখন" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "এক সেকেন্ড আগে" +msgstr[1] "%(count)s সেকেন্ড আগে" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "এক মিনিট আগে" +msgstr[1] "%(count)s মিনিট আগে" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "এক ঘন্টা আগে" +msgstr[1] "%(count)s ঘন্টা আগে" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "এখন থেকে %(delta)s পরে" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "এখন থেকে এক সেকেন্ড পরে" +msgstr[1] "এখন থেকে %(count)s সেকেন্ড পরে" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "এখন থেকে এক মিনিট পরে" +msgstr[1] "এখন থেকে %(count)s মিনিট পরে" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "এখন থেকে এক ঘন্টা পরে" +msgstr[1] "এখন থেকে %(count)s ঘন্টা পরে" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/br/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/br/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e45c05a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/br/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/br/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/br/LC_MESSAGES/django.po new file mode 100644 index 0000000..8f85745 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/br/LC_MESSAGES/django.po @@ -0,0 +1,517 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Fulup , 2012,2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2018-09-29 08:30+0000\n" +"Last-Translator: Claude Paroz \n" +"Language-Team: Breton (http://www.transifex.com/django/django/language/br/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: br\n" +"Plural-Forms: nplurals=5; plural=((n%10 == 1) && (n%100 != 11) && (n%100 !" +"=71) && (n%100 !=91) ? 0 :(n%10 == 2) && (n%100 != 12) && (n%100 !=72) && (n" +"%100 !=92) ? 1 :(n%10 ==3 || n%10==4 || n%10==9) && (n%100 < 10 || n% 100 > " +"19) && (n%100 < 70 || n%100 > 79) && (n%100 < 90 || n%100 > 99) ? 2 :(n != 0 " +"&& n % 1000000 == 0) ? 3 : 4);\n" + +msgid "Humanize" +msgstr "Denelaat" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f milion" +msgstr[1] "%(value).1f milion" +msgstr[2] "%(value).1f milion" +msgstr[3] "%(value).1f milion" +msgstr[4] "%(value).1f milion" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s million" +msgstr[1] "%(value)s million" +msgstr[2] "%(value)s million" +msgstr[3] "%(value)s million" +msgstr[4] "%(value)s million" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f miliard" +msgstr[1] "%(value).1f miliard" +msgstr[2] "%(value).1f miliard" +msgstr[3] "%(value).1f miliard" +msgstr[4] "%(value).1f miliard" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s miliard" +msgstr[1] "%(value)s miliard" +msgstr[2] "%(value)s miliard" +msgstr[3] "%(value)s miliard" +msgstr[4] "%(value)s miliard" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f bilion" +msgstr[1] "%(value).1f bilion" +msgstr[2] "%(value).1f bilion" +msgstr[3] "%(value).1f bilion" +msgstr[4] "%(value).1f bilion" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s bilion" +msgstr[1] "%(value)s bilion" +msgstr[2] "%(value)s bilion" +msgstr[3] "%(value)s bilion" +msgstr[4] "%(value)s bilion" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f c'hadrilion" +msgstr[1] "%(value).1f kadrilion" +msgstr[2] "%(value).1f kadrilion" +msgstr[3] "%(value).1f kadrilion" +msgstr[4] "%(value).1f kadrilion" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s c'hadrilion" +msgstr[1] "%(value)s kadrilion" +msgstr[2] "%(value)s kadrilion" +msgstr[3] "%(value)s kadrilion" +msgstr[4] "%(value)s kadrilion" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f c'hintilion" +msgstr[1] "%(value).1f kintilion" +msgstr[2] "%(value).1f kintilion" +msgstr[3] "%(value).1f kintilion" +msgstr[4] "%(value).1f kintilion" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s c'hintilion" +msgstr[1] "%(value)s kintilion" +msgstr[2] "%(value)s kintilion" +msgstr[3] "%(value)s kintilion" +msgstr[4] "%(value)s kintilion" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f sekstilion" +msgstr[1] "%(value).1f sekstilion" +msgstr[2] "%(value).1f sekstilion" +msgstr[3] "%(value).1f sekstilion" +msgstr[4] "%(value).1f sekstilion" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s sekstilion" +msgstr[1] "%(value)s sekstilion" +msgstr[2] "%(value)s sekstilion" +msgstr[3] "%(value)s sekstilion" +msgstr[4] "%(value)s sekstilion" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f septilion" +msgstr[1] "%(value).1f septilion" +msgstr[2] "%(value).1f septilion" +msgstr[3] "%(value).1f septilion" +msgstr[4] "%(value).1f septilion" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septilion" +msgstr[1] "%(value)s septilion" +msgstr[2] "%(value)s septilion" +msgstr[3] "%(value)s septilion" +msgstr[4] "%(value)s septilion" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f oktilion" +msgstr[1] "%(value).1f oktilion" +msgstr[2] "%(value).1f oktilion" +msgstr[3] "%(value).1f oktilion" +msgstr[4] "%(value).1f oktilion" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s oktilion" +msgstr[1] "%(value)s oktilion" +msgstr[2] "%(value)s oktilion" +msgstr[3] "%(value)s oktilion" +msgstr[4] "%(value)s oktilion" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f nonilion" +msgstr[1] "%(value).1f nonilion" +msgstr[2] "%(value).1f nonilion" +msgstr[3] "%(value).1f nonilion" +msgstr[4] "%(value).1f nonilion" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s nonilion" +msgstr[1] "%(value)s nonilion" +msgstr[2] "%(value)s nonilion" +msgstr[3] "%(value)s nonilion" +msgstr[4] "%(value)s nonilion" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f dekilion" +msgstr[1] "%(value).1f dekilion" +msgstr[2] "%(value).1f dekilion" +msgstr[3] "%(value).1f dekilion" +msgstr[4] "%(value).1f dekilion" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s dekilion" +msgstr[1] "%(value)s dekilion" +msgstr[2] "%(value)s dekilion" +msgstr[3] "%(value)s dekilion" +msgstr[4] "%(value)s dekilion" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f gogol" +msgstr[1] "%(value).1f gogol" +msgstr[2] "%(value).1f gogol" +msgstr[3] "%(value).1f gogol" +msgstr[4] "%(value).1f gogol" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s gogol" +msgstr[1] "%(value)s gogol" +msgstr[2] "%(value)s gogol" +msgstr[3] "%(value)s gogol" +msgstr[4] "%(value)s gogol" + +msgid "one" +msgstr "unan" + +msgid "two" +msgstr "daou" + +msgid "three" +msgstr "tri" + +msgid "four" +msgstr "pevar" + +msgid "five" +msgstr "pemp" + +msgid "six" +msgstr "c'hwec'h" + +msgid "seven" +msgstr "seizh" + +msgid "eight" +msgstr "eizh" + +msgid "nine" +msgstr "nav" + +msgid "today" +msgstr "hiziv" + +msgid "tomorrow" +msgstr "warc'hoazh" + +msgid "yesterday" +msgstr "dec'h" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "%(count)s eurvezh zo" +msgstr[1] "%(count)s eurvezh zo" +msgstr[2] "%(count)s eurvezh zo" +msgstr[3] "%(count)s eurvezh zo" +msgstr[4] "%(count)s eurvezh zo" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "%(count)s munud zo" +msgstr[1] "%(count)s munud zo" +msgstr[2] "%(count)s munud zo" +msgstr[3] "%(count)s munud zo" +msgstr[4] "%(count)s munud zo" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "%(count)s eilenn zo" +msgstr[1] "%(count)s eilenn zo" +msgstr[2] "%(count)s eilenn zo" +msgstr[3] "%(count)s eilenn zo" +msgstr[4] "%(count)s eilenn zo" + +msgid "now" +msgstr "bremañ" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "a-benn %(count)s eilenn" +msgstr[1] "a-benn %(count)s eilenn" +msgstr[2] "a-benn %(count)s eilenn" +msgstr[3] "a-benn %(count)s eilenn" +msgstr[4] "a-benn %(count)s eilenn" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "a-benn %(count)s munud" +msgstr[1] "a-benn %(count)s munud" +msgstr[2] "a-benn %(count)s munud" +msgstr[3] "a-benn %(count)s munud" +msgstr[4] "a-benn %(count)s munud" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "a-benn %(count)s eurvezh" +msgstr[1] "a-benn %(count)s eurvezh" +msgstr[2] "a-benn %(count)s eurvezh" +msgstr[3] "a-benn %(count)s eurvezh" +msgstr[4] "a-benn %(count)s eurvezh" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/bs/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/bs/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b3a7647 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/bs/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/bs/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/bs/LC_MESSAGES/django.po new file mode 100644 index 0000000..51108e9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/bs/LC_MESSAGES/django.po @@ -0,0 +1,292 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Filip Dupanović , 2011 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Bosnian (http://www.transifex.com/django/django/language/" +"bs/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bs\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Humanize" +msgstr "" + +msgid "th" +msgstr "-i" + +msgid "st" +msgstr "-vi" + +msgid "nd" +msgstr "-i" + +msgid "rd" +msgstr "-i" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f million" +msgstr[1] "%(value).1f miliona" +msgstr[2] "%(value).1f miliona" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f milijarda" +msgstr[1] "%(value).1f milijarde" +msgstr[2] "%(value).1f milijardi" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f bilion" +msgstr[1] "%(value).1f biliona" +msgstr[2] "%(value).1f biliona" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +msgid "one" +msgstr "jedan" + +msgid "two" +msgstr "dva" + +msgid "three" +msgstr "tri" + +msgid "four" +msgstr "četiri" + +msgid "five" +msgstr "pet" + +msgid "six" +msgstr "šest" + +msgid "seven" +msgstr "sedam" + +msgid "eight" +msgstr "osam" + +msgid "nine" +msgstr "devet" + +msgid "today" +msgstr "deset" + +msgid "tomorrow" +msgstr "sutra" + +msgid "yesterday" +msgstr "jučer" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "" + +msgid "now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ca/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ca/LC_MESSAGES/django.mo new file mode 100644 index 0000000..348f920 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ca/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ca/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ca/LC_MESSAGES/django.po new file mode 100644 index 0000000..4befcc6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ca/LC_MESSAGES/django.po @@ -0,0 +1,332 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Antoni Aloy , 2011-2012,2019,2021 +# Carles Barrobés , 2011,2014 +# GerardoGa , 2018 +# Gil Obradors Via , 2019 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2021-10-27 09:05+0000\n" +"Last-Translator: Antoni Aloy \n" +"Language-Team: Catalan (http://www.transifex.com/django/django/language/" +"ca/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ca\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Humanitzar" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}è" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}è" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}r" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}n" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}r" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}è" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}è" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}è" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}è" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}è" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}è" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s milió" +msgstr[1] "%(value)s milions" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s miliard" +msgstr[1] "%(value)s miliards" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s bilió" +msgstr[1] "%(value)s bilió" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s quadrilió" +msgstr[1] "%(value)s quadrilions" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s quintilió" +msgstr[1] "%(value)s quintilions" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s sextilió" +msgstr[1] "%(value)s sextilions" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septilió" +msgstr[1] "%(value)s septilions" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s octilió" +msgstr[1] "%(value)s octilions" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s nonilió" +msgstr[1] "%(value)s nonilions" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s decilió" +msgstr[1] "%(value)s decilions" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" +msgstr[1] "%(value)s googols" + +msgid "one" +msgstr "un" + +msgid "two" +msgstr "dos" + +msgid "three" +msgstr "tres" + +msgid "four" +msgstr "quatre" + +msgid "five" +msgstr "cinc" + +msgid "six" +msgstr "sis" + +msgid "seven" +msgstr "set" + +msgid "eight" +msgstr "vuit" + +msgid "nine" +msgstr "nou" + +msgid "today" +msgstr "avui" + +msgid "tomorrow" +msgstr "demà" + +msgid "yesterday" +msgstr "ahir" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "Fa %(delta)s " + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "fa una hora" +msgstr[1] "fa %(count)s hores" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "fa un minut" +msgstr[1] "fa %(count)s minuts" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "fa un segon" +msgstr[1] "fa %(count)s segons" + +msgid "now" +msgstr "ara" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "d'aquí a un segon" +msgstr[1] "d'aquí a %(count)s segons" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "d'aquí a un minut" +msgstr[1] "d'aquí a %(count)s minuts" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "d'aquí a una hora" +msgstr[1] "d'aquí a %(count)s hores" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "fa %(delta)s" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d any" +msgstr[1] "%(num)d anys" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mes" +msgstr[1] "%(num)d mesos" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d setmana" +msgstr[1] "%(num)d setmanes" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dia" +msgstr[1] "%(num)d dies" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hora" +msgstr[1] "%(num)d hores" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minut" +msgstr[1] "%(num)d minuts" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d any" +msgstr[1] "%(num)d anys" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mes" +msgstr[1] "%(num)d mesos" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d setmana" +msgstr[1] "%(num)d setmanes" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dia" +msgstr[1] "%(num)d dies" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hora" +msgstr[1] "%(num)d hores" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minut" +msgstr[1] "%(num)d minuts" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ckb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ckb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e087c72 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ckb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ckb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ckb/LC_MESSAGES/django.po new file mode 100644 index 0000000..40e3e60 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ckb/LC_MESSAGES/django.po @@ -0,0 +1,329 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# kosar tofiq , 2020 +# Swara , 2022 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2023-04-24 18:40+0000\n" +"Last-Translator: Swara , 2022\n" +"Language-Team: Central Kurdish (http://www.transifex.com/django/django/" +"language/ckb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ckb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "بەمرۆڤایەتیکردن" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "‫{}th" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "‫{}th" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "‫{}st" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "‫{}nd" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "‫{}rd" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "‫{}th" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "‫{}th" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "‫{}th" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "‫{}th" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "‫{}th" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "‫{}th" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s ملیۆن" +msgstr[1] "%(value)s ملیۆن" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "‫%(value)s بلیۆن" +msgstr[1] "‫%(value)s بلیۆن" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "‫%(value)s تریلۆن" +msgstr[1] "‫%(value)s تریلۆن" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "‫%(value)s کوادرلیۆن" +msgstr[1] "‫%(value)s کوادرلیۆن" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "‫%(value)s کوینترلیۆن" +msgstr[1] "‫%(value)s کوینترلیۆن" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "‫%(value)s شەش تریلۆن" +msgstr[1] "‫%(value)s شەش تریلۆن" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "‫%(value)s سێپتریلۆن" +msgstr[1] "‫%(value)s سێپتریلۆن" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "‫%(value)s ئۆکتریلیۆن" +msgstr[1] "‫%(value)s ئۆکتریلیۆن" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "‫%(value)s نۆنتریلۆن" +msgstr[1] "‫%(value)s نۆنتریلۆن" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "‫%(value)s دێستریلیۆن" +msgstr[1] "‫%(value)s دێستریلیۆن" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "‫%(value)s گوگۆڵ" +msgstr[1] "‫%(value)s گوگۆڵ" + +msgid "one" +msgstr "یەک" + +msgid "two" +msgstr "دوو" + +msgid "three" +msgstr "سێ" + +msgid "four" +msgstr "چوار" + +msgid "five" +msgstr "پێنج" + +msgid "six" +msgstr "شەش" + +msgid "seven" +msgstr "حەوت" + +msgid "eight" +msgstr "هەشت" + +msgid "nine" +msgstr "نۆ" + +msgid "today" +msgstr "ئەمڕۆ" + +msgid "tomorrow" +msgstr "سبەینێ" + +msgid "yesterday" +msgstr "دوێنێ" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s پێشتر" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "کاتژمێرێک پێشتر" +msgstr[1] "‫%(count)s کاتژمێر پێشتر" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "خولەکێک پێشتر" +msgstr[1] "‫%(count)s خولەک پێشتر" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "چرکەیەک پێشتر" +msgstr[1] "‫%(count)s چرکە پێشتر" + +msgid "now" +msgstr "ئێستا" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "چرکەیەک لە ئێستاوە" +msgstr[1] "‫%(count)s چرکە لە ئێستاوە" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "خولەکێک لە ئێستاوە" +msgstr[1] "‫%(count)s خولەک لە ئێستاوە" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "کاتژمێرێک لە ئێستاوە" +msgstr[1] "‫%(count)s کاتژمێر لە ئێستاوە" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s لە ئێستاوە" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "‫%(num)d ساڵ" +msgstr[1] "‫%(num)d ساڵ" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "‫%(num)d مانگ" +msgstr[1] "‫%(num)d مانگ" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "‫%(num)d هەفتە" +msgstr[1] "‫%(num)d هەفتە" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "‫%(num)d ڕۆژ" +msgstr[1] "‫%(num)d ڕۆژ" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "‫%(num)d کاتژمێر" +msgstr[1] "‫%(num)d کاتژمێر" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "‫%(num)d خولەک" +msgstr[1] "‫%(num)d خولەک" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "‫%(num)d ساڵ" +msgstr[1] "‫%(num)d ساڵ" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "‫%(num)d مانگ" +msgstr[1] "‫%(num)d مانگ" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "‫%(num)d هەفتە" +msgstr[1] "‫%(num)d هەفتە" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "‫%(num)d ڕۆژ" +msgstr[1] "‫%(num)d ڕۆژ" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "‫%(num)d کاتژمێر" +msgstr[1] "‫%(num)d کاتژمێر" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "‫%(num)d خولەک" +msgstr[1] "‫%(num)d خولەک" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/cs/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/cs/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4b46222 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/cs/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/cs/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/cs/LC_MESSAGES/django.po new file mode 100644 index 0000000..f61b7e5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/cs/LC_MESSAGES/django.po @@ -0,0 +1,388 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Vláďa Macek , 2011,2014 +# Vláďa Macek , 2018,2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-03-18 23:35+0000\n" +"Last-Translator: Vláďa Macek \n" +"Language-Team: Czech (http://www.transifex.com/django/django/language/cs/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cs\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n " +"<= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n" + +msgid "Humanize" +msgstr "Polidštění" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}." + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] " %(value)s milion" +msgstr[1] " %(value)s miliony" +msgstr[2] " %(value)s milionů" +msgstr[3] " %(value)s milionů" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s miliarda" +msgstr[1] "%(value)s miliardy" +msgstr[2] "%(value)s miliard" +msgstr[3] "%(value)s miliard" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s bilion" +msgstr[1] "%(value)s biliony" +msgstr[2] "%(value)s bilionů" +msgstr[3] "%(value)s bilionů" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s biliarda" +msgstr[1] "%(value)s biliardy" +msgstr[2] "%(value)s biliard" +msgstr[3] "%(value)s biliard" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s trilion" +msgstr[1] "%(value)s triliony" +msgstr[2] "%(value)s trilionů" +msgstr[3] "%(value)s trilionů" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s triliarda" +msgstr[1] "%(value)s triliardy" +msgstr[2] "%(value)s triliard" +msgstr[3] "%(value)s triliard" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s kvadrilion" +msgstr[1] "%(value)s kvadriliony" +msgstr[2] "%(value)s kvadrilionů" +msgstr[3] "%(value)s kvadrilionů" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s kvadriliarda" +msgstr[1] "%(value)s kvadriliardy" +msgstr[2] "%(value)s kvadriliard" +msgstr[3] "%(value)s kvadriliard" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s kvintilion" +msgstr[1] "%(value)s kvintiliony" +msgstr[2] "%(value)s kvintilionů" +msgstr[3] "%(value)s kvintilionů" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s kvintiliarda" +msgstr[1] "%(value)s kvintiliardy" +msgstr[2] "%(value)s kvintiliard" +msgstr[3] "%(value)s kvintiliard" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" +msgstr[1] "%(value)s googoly" +msgstr[2] "%(value)s googolů" +msgstr[3] "%(value)s googolů" + +msgid "one" +msgstr "jedna" + +msgid "two" +msgstr "dvě" + +msgid "three" +msgstr "tři" + +msgid "four" +msgstr "čtyři" + +msgid "five" +msgstr "pět" + +msgid "six" +msgstr "šest" + +msgid "seven" +msgstr "sedm" + +msgid "eight" +msgstr "osm" + +msgid "nine" +msgstr "devět" + +msgid "today" +msgstr "dnes" + +msgid "tomorrow" +msgstr "zítra" + +msgid "yesterday" +msgstr "včera" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "před %(delta)s" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "před hodinou" +msgstr[1] "před %(count)s hodinami" +msgstr[2] "o %(count)s hodin dříve" +msgstr[3] "před %(count)s hodinami" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "před minutou" +msgstr[1] "před %(count)s minutami" +msgstr[2] "o %(count)s minuty dříve" +msgstr[3] "před %(count)s minutami" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "před sekundou" +msgstr[1] "před %(count)s sekundami" +msgstr[2] "o %(count)s sekundy dříve" +msgstr[3] "před %(count)s sekundami" + +msgid "now" +msgstr "nyní" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "za sekundu" +msgstr[1] "za %(count)s sekundy" +msgstr[2] "za %(count)s sekundy" +msgstr[3] "za %(count)s sekund" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "za minutu" +msgstr[1] "za %(count)s minuty" +msgstr[2] "za %(count)s minuty" +msgstr[3] "za %(count)s minut" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "za hodinu" +msgstr[1] "za %(count)s hodiny" +msgstr[2] "za %(count)s hodiny" +msgstr[3] "za %(count)s hodin" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "za %(delta)s" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d rokem" +msgstr[1] "%(num)d lety" +msgstr[2] "%(num)d rokem" +msgstr[3] "%(num)d lety" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d měsícem" +msgstr[1] "%(num)d měsíci" +msgstr[2] "%(num)d měsícem" +msgstr[3] "%(num)d měsíci" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d týdnem" +msgstr[1] "%(num)d týdny" +msgstr[2] "%(num)d týdny" +msgstr[3] "%(num)d týdny" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dnem" +msgstr[1] "%(num)d dny" +msgstr[2] "%(num)d dny" +msgstr[3] "%(num)d dny" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hodinou" +msgstr[1] "%(num)d hodinami" +msgstr[2] "%(num)d hodinami" +msgstr[3] "%(num)d hodinami" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minutou" +msgstr[1] "%(num)d minutami" +msgstr[2] "%(num)d minutami" +msgstr[3] "%(num)d minutami" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d rok" +msgstr[1] "%(num)d roky" +msgstr[2] "%(num)d let" +msgstr[3] "%(num)d let" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d měsíc" +msgstr[1] "%(num)d měsíce" +msgstr[2] "%(num)d měsíců" +msgstr[3] "%(num)d měsíců" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d týden" +msgstr[1] "%(num)d týdny" +msgstr[2] "%(num)d týdnů" +msgstr[3] "%(num)d týdnů" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d den" +msgstr[1] "%(num)d dny" +msgstr[2] "%(num)d dní" +msgstr[3] "%(num)d dní" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hodina" +msgstr[1] "%(num)d hodiny" +msgstr[2] "%(num)d hodin" +msgstr[3] "%(num)d hodin" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuta" +msgstr[1] "%(num)d minuty" +msgstr[2] "%(num)d minut" +msgstr[3] "%(num)d minut" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/cy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/cy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..aceed48 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/cy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/cy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/cy/LC_MESSAGES/django.po new file mode 100644 index 0000000..6dd10e8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/cy/LC_MESSAGES/django.po @@ -0,0 +1,318 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Maredudd ap Gwyndaf , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 19:21+0000\n" +"Last-Translator: Maredudd ap Gwyndaf \n" +"Language-Team: Welsh (http://www.transifex.com/django/django/language/cy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cy\n" +"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != " +"11) ? 2 : 3;\n" + +msgid "Humanize" +msgstr "Dynoli" + +msgid "th" +msgstr "edd" + +msgid "st" +msgstr "af" + +msgid "nd" +msgstr "ail" + +msgid "rd" +msgstr "ydd" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f miliwn" +msgstr[1] "%(value).1f miliwn" +msgstr[2] "%(value).1f miliwn" +msgstr[3] "%(value).1f miliwn" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s miliwn" +msgstr[1] "%(value)s miliwn" +msgstr[2] "%(value)s miliwn" +msgstr[3] "%(value)s miliwn" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f biliwn" +msgstr[1] "%(value).1f biliwn" +msgstr[2] "%(value).1f biliwn" +msgstr[3] "%(value).1f biliwn" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s biliwn" +msgstr[1] "%(value)s biliwn" +msgstr[2] "%(value)s biliwn" +msgstr[3] "%(value)s biliwn" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f triliwn" +msgstr[1] "%(value).1f triliwn" +msgstr[2] "%(value).1f triliwn" +msgstr[3] "%(value).1f triliwn" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s triliwn" +msgstr[1] "%(value)s triliwn" +msgstr[2] "%(value)s triliwn" +msgstr[3] "%(value)s triliwn" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f cwadriliwn" +msgstr[1] "%(value).1f cwadriliwn" +msgstr[2] "%(value).1f cwadriliwn" +msgstr[3] "%(value).1f cwadriliwn" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s cwadriliwn" +msgstr[1] "%(value)s cwadriliwn" +msgstr[2] "%(value)s cwadriliwn" +msgstr[3] "%(value)s cwadriliwn" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f cwintiliwn" +msgstr[1] "%(value).1f cwintiliwn" +msgstr[2] "%(value).1f cwintiliwn" +msgstr[3] "%(value).1f cwintiliwn" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s cwintiliwn" +msgstr[1] "%(value)s cwintiliwn" +msgstr[2] "%(value)s cwintiliwn" +msgstr[3] "%(value)s cwintiliwn" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f secstiliwnfm" +msgstr[1] "%(value).1f secstiliwnfm" +msgstr[2] "%(value).1f secstiliwnfm" +msgstr[3] "%(value).1f secstiliwnfm" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s secstiliwn" +msgstr[1] "%(value)s secstiliwn" +msgstr[2] "%(value)s secstiliwn" +msgstr[3] "%(value)s secstiliwn" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f septiliwn" +msgstr[1] "%(value).1f septiliwn" +msgstr[2] "%(value).1f septiliwn" +msgstr[3] "%(value).1f septiliwn" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septiliwn" +msgstr[1] "%(value)s septiliwn" +msgstr[2] "%(value)s septiliwn" +msgstr[3] "%(value)s septiliwn" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f octiliwn" +msgstr[1] "%(value).1f octiliwn" +msgstr[2] "%(value).1f octiliwn" +msgstr[3] "%(value).1f octiliwn" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s octiliwn" +msgstr[1] "%(value)s octiliwn" +msgstr[2] "%(value)s octiliwn" +msgstr[3] "%(value)s octiliwn" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f noniliwn" +msgstr[1] "%(value).1f noniliwn" +msgstr[2] "%(value).1f noniliwn" +msgstr[3] "%(value).1f noniliwn" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s noniliwn" +msgstr[1] "%(value)s noniliwn" +msgstr[2] "%(value)s noniliwn" +msgstr[3] "%(value)s noniliwn" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f dengiliwn" +msgstr[1] "%(value).1f dengiliwn" +msgstr[2] "%(value).1f dengiliwn" +msgstr[3] "%(value).1f dengiliwn" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s dengiliwn" +msgstr[1] "%(value)s dengiliwn" +msgstr[2] "%(value)s dengiliwn" +msgstr[3] "%(value)s dengiliwn" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f gwgol" +msgstr[1] "%(value).1f gwgol" +msgstr[2] "%(value).1f gwgol" +msgstr[3] "%(value).1f gwgol" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s gwgol" +msgstr[1] "%(value)s gwgol" +msgstr[2] "%(value)s gwgol" +msgstr[3] "%(value)s gwgol" + +msgid "one" +msgstr "un" + +msgid "two" +msgstr "dau" + +msgid "three" +msgstr "tri" + +msgid "four" +msgstr "pedwar" + +msgid "five" +msgstr "pump" + +msgid "six" +msgstr "chwech" + +msgid "seven" +msgstr "saith" + +msgid "eight" +msgstr "wyth" + +msgid "nine" +msgstr "naw" + +msgid "today" +msgstr "heddiw" + +msgid "tomorrow" +msgstr "fory" + +msgid "yesterday" +msgstr "ddoe" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "%(delta)s yn ôl" + +msgid "now" +msgstr "nawr" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "un eiliad yn ôl" +msgstr[1] "%(count)s eiliad yn ôl" +msgstr[2] "%(count)s eiliad yn ôl" +msgstr[3] "%(count)s eiliad yn ôl" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "un munud yn ôl" +msgstr[1] "%(count)s munud yn ôl" +msgstr[2] "%(count)s munud yn ôl" +msgstr[3] "%(count)s munud yn ôl" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "un awr yn ôl" +msgstr[1] "%(count)s awr yn ôl" +msgstr[2] "%(count)s awr yn ôl" +msgstr[3] "%(count)s awr yn ôl" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "%(delta)s o nawr" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "un eiliad o nawr" +msgstr[1] "%(count)s eiliad o nawr" +msgstr[2] "%(count)s eiliad o nawr" +msgstr[3] "%(count)s eiliad o nawr" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "un munud o nawr" +msgstr[1] "%(count)s funud o nawr" +msgstr[2] "%(count)s munud o nawr" +msgstr[3] "%(count)s munud o nawr" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "un awr o nawr" +msgstr[1] "%(count)s awr o nawr" +msgstr[2] "%(count)s awr o nawr" +msgstr[3] "%(count)s awr o nawr" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/da/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/da/LC_MESSAGES/django.mo new file mode 100644 index 0000000..bb8cd61 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/da/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/da/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/da/LC_MESSAGES/django.po new file mode 100644 index 0000000..8ad82a0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/da/LC_MESSAGES/django.po @@ -0,0 +1,331 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Christian Joergensen , 2012 +# Erik Ramsgaard Wognsen , 2021 +# Erik Ramsgaard Wognsen , 2014,2018 +# Jannis Leidel , 2011 +# valberg , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2021-09-23 21:30+0000\n" +"Last-Translator: Erik Ramsgaard Wognsen \n" +"Language-Team: Danish (http://www.transifex.com/django/django/language/da/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: da\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Menneskeliggør" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}." + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s million" +msgstr[1] "%(value)s millioner" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s milliard" +msgstr[1] "%(value)s milliarder" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s billion" +msgstr[1] "%(value)s billioner" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s billiard" +msgstr[1] "%(value)s billiarder" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s trillion" +msgstr[1] "%(value)s trillioner" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s trilliard" +msgstr[1] "%(value)s trilliarder" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s kvadrillion" +msgstr[1] "%(value)s kvadrillioner" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s kvadrilliard" +msgstr[1] "%(value)s kvadrilliarder" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s kvintillion" +msgstr[1] "%(value)s kvintillioner" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s kvintilliard" +msgstr[1] "%(value)s kvintilliarder" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s gogol" +msgstr[1] "%(value)s gogoler" + +msgid "one" +msgstr "en" + +msgid "two" +msgstr "to" + +msgid "three" +msgstr "tre" + +msgid "four" +msgstr "fire" + +msgid "five" +msgstr "fem" + +msgid "six" +msgstr "seks" + +msgid "seven" +msgstr "syv" + +msgid "eight" +msgstr "otte" + +msgid "nine" +msgstr "ni" + +msgid "today" +msgstr "i dag" + +msgid "tomorrow" +msgstr "i morgen" + +msgid "yesterday" +msgstr "i går" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s siden" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "en time siden" +msgstr[1] "%(count)s timer siden" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "et minut siden" +msgstr[1] "%(count)s minutter siden" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "et sekund siden" +msgstr[1] "%(count)s sekunder siden" + +msgid "now" +msgstr "nu" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "om et sekund" +msgstr[1] "om %(count)s sekunder" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "om et minut" +msgstr[1] "om %(count)s minutter" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "om en time" +msgstr[1] "om %(count)s timer" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s fra nu af" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d år" +msgstr[1] "%(num)d år" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d måned" +msgstr[1] "%(num)d måneder" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d uge" +msgstr[1] "%(num)d uger" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dag" +msgstr[1] "%(num)d dage" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d time" +msgstr[1] "%(num)d timer" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minut" +msgstr[1] "%(num)d minutter" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d år" +msgstr[1] "%(num)d år" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d måned" +msgstr[1] "%(num)d måneder" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d uge" +msgstr[1] "%(num)d uger" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dag" +msgstr[1] "%(num)d dage" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d time" +msgstr[1] "%(num)d timer" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minut" +msgstr[1] "%(num)d minutter" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/de/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/de/LC_MESSAGES/django.mo new file mode 100644 index 0000000..df46d3c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/de/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/de/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/de/LC_MESSAGES/django.po new file mode 100644 index 0000000..1fa0a64 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/de/LC_MESSAGES/django.po @@ -0,0 +1,330 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# André Hagenbruch, 2011 +# Claude Paroz , 2013 +# Florian Apolloner , 2021 +# Jannis Leidel , 2011,2013-2014,2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2021-11-28 17:20+0000\n" +"Last-Translator: Raphael Michel \n" +"Language-Team: German (http://www.transifex.com/django/django/language/de/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Humanize" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}." + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s Million" +msgstr[1] "%(value)s Millionen" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s Milliarde" +msgstr[1] "%(value)s Milliarden" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s Billion" +msgstr[1] "%(value)s Billionen" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s Billiarde" +msgstr[1] "%(value)s Billiarden" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s Trillion" +msgstr[1] "%(value)s Trillionen" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s Trilliarde" +msgstr[1] "%(value)s Trilliarden" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s Quadrillion" +msgstr[1] "%(value)s Quadrillionen" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s Quadrilliarde" +msgstr[1] "%(value)s Quadrilliarden" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s Quintillion" +msgstr[1] "%(value)s Quintillionen" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s Quintilliarde" +msgstr[1] "%(value)s Quintilliarden" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s Sedezilliarde" +msgstr[1] "%(value)s Sedezilliarden" + +msgid "one" +msgstr "eins" + +msgid "two" +msgstr "zwei" + +msgid "three" +msgstr "drei" + +msgid "four" +msgstr "vier" + +msgid "five" +msgstr "fünf" + +msgid "six" +msgstr "sechs" + +msgid "seven" +msgstr "sieben" + +msgid "eight" +msgstr "acht" + +msgid "nine" +msgstr "neun" + +msgid "today" +msgstr "heute" + +msgid "tomorrow" +msgstr "morgen" + +msgid "yesterday" +msgstr "gestern" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s her" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "vor einer Stunde" +msgstr[1] "vor %(count)s Stunden" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "vor einer Minute" +msgstr[1] "vor %(count)s Minuten" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "vor einer Sekunde" +msgstr[1] "vor %(count)s Sekunden" + +msgid "now" +msgstr "jetzt" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "in einer Sekunde" +msgstr[1] "in %(count)s Sekunden" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "in einer Minute" +msgstr[1] "in %(count)s Minuten" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "in einer Stunde" +msgstr[1] "in %(count)s Stunden" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s von jetzt an" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d Jahr" +msgstr[1] "%(num)d Jahre" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d Monat" +msgstr[1] "%(num)d Monate" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d Woche" +msgstr[1] "%(num)d Wochen" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d Tage" +msgstr[1] "%(num)d Tage" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d Stunde" +msgstr[1] "%(num)d Stunden" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d Minute" +msgstr[1] "%(num)d Minuten" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d Jahr" +msgstr[1] "%(num)d Jahre" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d Monat" +msgstr[1] "%(num)d Monate" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d Woche" +msgstr[1] "%(num)d Wochen" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d Tag" +msgstr[1] "%(num)d Tage" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d Stunde" +msgstr[1] "%(num)d Stunden" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d Minute" +msgstr[1] "%(num)d Minuten" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/dsb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/dsb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..bbd9821 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/dsb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/dsb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/dsb/LC_MESSAGES/django.po new file mode 100644 index 0000000..11ab238 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/dsb/LC_MESSAGES/django.po @@ -0,0 +1,387 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Michael Wolf , 2016,2018,2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2021-09-28 19:07+0000\n" +"Last-Translator: Michael Wolf \n" +"Language-Team: Lower Sorbian (http://www.transifex.com/django/django/" +"language/dsb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: dsb\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" + +msgid "Humanize" +msgstr "Humanize" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}." + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s milion" +msgstr[1] "%(value)s miliona" +msgstr[2] "%(value)s miliony" +msgstr[3] "%(value)s milionow" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s miliarda" +msgstr[1] "%(value)s miliarźe" +msgstr[2] "%(value)s miliardy" +msgstr[3] "%(value)s miliardow" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s bilion" +msgstr[1] "%(value)s biliona" +msgstr[2] "%(value)s biliony" +msgstr[3] "%(value)s bilionow" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s biliarda" +msgstr[1] "%(value)s biliarźe" +msgstr[2] "%(value)s biliardy" +msgstr[3] "%(value)s biliardow" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s trilion" +msgstr[1] "%(value)s triliona" +msgstr[2] "%(value)s triliony" +msgstr[3] "%(value)s trilionow" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s triliarda" +msgstr[1] "%(value)s triliarźe" +msgstr[2] "%(value)s triliardy" +msgstr[3] "%(value)s triliardow" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s kwadrilion" +msgstr[1] "%(value)s kwadriliona" +msgstr[2] "%(value)s kwadriliony" +msgstr[3] "%(value)s kwadrilionow" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s kwadriliarda" +msgstr[1] "%(value)s kwadriliarźe" +msgstr[2] "%(value)s kwadriliardy" +msgstr[3] "%(value)s kwadriliardow" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s kwintilion" +msgstr[1] "%(value)s kwintiliona" +msgstr[2] "%(value)s kwintiliony" +msgstr[3] "%(value)s kwintilionow" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s kwintiliarda" +msgstr[1] "%(value)s kwintiliarźe" +msgstr[2] "%(value)s kwintiliardy" +msgstr[3] "%(value)s kwintiliardow" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s sedeciliarda" +msgstr[1] "%(value)s sedeciliarźe" +msgstr[2] "%(value)s sedeciliardy" +msgstr[3] "%(value)s sedeciliardow" + +msgid "one" +msgstr "jaden" + +msgid "two" +msgstr "dwa" + +msgid "three" +msgstr "tśi" + +msgid "four" +msgstr "styri" + +msgid "five" +msgstr "pěś" + +msgid "six" +msgstr "šesć" + +msgid "seven" +msgstr "sedym" + +msgid "eight" +msgstr "wósym" + +msgid "nine" +msgstr "źewjeś" + +msgid "today" +msgstr "źinsa" + +msgid "tomorrow" +msgstr "witśe" + +msgid "yesterday" +msgstr "cora" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "pśed %(delta)s" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "Pśed %(count)s góźinu" +msgstr[1] "Pśed %(count)s góźinoma" +msgstr[2] "Pśed %(count)s góźinami" +msgstr[3] "Pśed %(count)s góźinami" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "Pśed %(count)s minutu" +msgstr[1] "Pśed %(count)s minutoma" +msgstr[2] "Pśed %(count)s minutami" +msgstr[3] "Pśed %(count)s minutami" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "Pśed %(count)s sekundu" +msgstr[1] "Pśed %(count)s sekundoma" +msgstr[2] "Pśed %(count)s sekundami" +msgstr[3] "Pśed %(count)s sekundami" + +msgid "now" +msgstr "něnto" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "za %(count)s sekundu" +msgstr[1] "za %(count)s sekunźe" +msgstr[2] "za %(count)s sekundy" +msgstr[3] "za %(count)s sekundow" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "za %(count)s minutu" +msgstr[1] "za %(count)s minuśe" +msgstr[2] "za %(count)s minuty" +msgstr[3] "za %(count)s minutow" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "za %(count)s góźinu" +msgstr[1] "za %(count)s góźinje" +msgstr[2] "za %(count)s góźiny" +msgstr[3] "za %(count)s góźin" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s wótněnta" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d lěto" +msgstr[1] "%(num)d lěśe" +msgstr[2] "%(num)d lěta" +msgstr[3] "%(num)d lět" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mjasec" +msgstr[1] "%(num)d mjaseca" +msgstr[2] "%(num)d mjasece" +msgstr[3] "%(num)dmjasecow" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d tyźeń" +msgstr[1] "%(num)d tyźenja" +msgstr[2] "%(num)d tyźenje" +msgstr[3] "%(num)d tyźenjow" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d źeń" +msgstr[1] "%(num)d dnja" +msgstr[2] "%(num)d dny" +msgstr[3] "%(num)d dnjow" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d góźina" +msgstr[1] "%(num)d góźinje" +msgstr[2] "%(num)d góźiny" +msgstr[3] "%(num)d góźin" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuta" +msgstr[1] "%(num)d minuśe" +msgstr[2] "%(num)d minuty" +msgstr[3] "%(num)d minutow" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d lěto" +msgstr[1] "%(num)d lěśe" +msgstr[2] "%(num)d lěta" +msgstr[3] "%(num)d lět" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mjasec" +msgstr[1] "%(num)d mjaseca" +msgstr[2] "%(num)d mjasece" +msgstr[3] "%(num)dmjasecow" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d tyźeń" +msgstr[1] "%(num)d tyźenja" +msgstr[2] "%(num)d tyźenje" +msgstr[3] "%(num)d tyźenjow" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d źeń" +msgstr[1] "%(num)d dnja" +msgstr[2] "%(num)d dny" +msgstr[3] "%(num)d dnjow" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d góźina" +msgstr[1] "%(num)d góźinje" +msgstr[2] "%(num)d góźiny" +msgstr[3] "%(num)d góźin" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuta" +msgstr[1] "%(num)d minuśe" +msgstr[2] "%(num)d minuty" +msgstr[3] "%(num)d minutow" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/el/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/el/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5b4868f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/el/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/el/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/el/LC_MESSAGES/django.po new file mode 100644 index 0000000..6f1d0aa --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/el/LC_MESSAGES/django.po @@ -0,0 +1,398 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Dimitris Glezos , 2011 +# Jannis Leidel , 2011 +# Kostas Papadimitriou , 2012 +# Nick Mavrakis , 2018 +# Nikolas Demiridis , 2014 +# Pãnoș , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2018-09-22 10:19+0000\n" +"Last-Translator: Nick Mavrakis \n" +"Language-Team: Greek (http://www.transifex.com/django/django/language/el/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: el\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Εξανθρώπιση" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}ο" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}ο" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}ο" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}ο" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}ο" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}ο" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}ο" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}ο" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}ο" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}ο" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}ο" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f εκατομμύριο" +msgstr[1] "%(value).1f εκατομμύρια" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] " %(value)s εκατομμύριο" +msgstr[1] " %(value)s εκατομμύρια" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f δισεκατομμύριο" +msgstr[1] "%(value).1f δισεκατομμύρια" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s δισεκατομμύριο" +msgstr[1] "%(value)s δισεκατομμύρια" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f τρισεκατομμύριο" +msgstr[1] "%(value).1f τρισεκατομμύρια" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s τρισεκατομμύριο" +msgstr[1] "%(value)s τρισεκατομμύρια" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f τετράκις εκατομμύριο" +msgstr[1] "%(value).1f τετράκις εκατομμύρια" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s τετράκις εκατομμύριο" +msgstr[1] "%(value)s τετράκις εκατομμύρια" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f πεντάκις εκατομμύριo" +msgstr[1] "%(value).1f πεντάκις εκατομμύρια" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s πεντάκις εκατομμύριo" +msgstr[1] "%(value)s πεντάκις εκατομμύρια" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f εξάκις εκατομμύριo" +msgstr[1] "%(value).1f εξάκις εκατομμύρια" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s εξάκις εκατομμύριo" +msgstr[1] "%(value)s εξάκις εκατομμύρια" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f επτάκις εκατομμύριο" +msgstr[1] "%(value).1f επτάκις εκατομμύρια" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s επτάκις εκατομμύριο" +msgstr[1] "%(value)s επτάκις εκατομμύρια" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f οκτάκις εκατομμύριο" +msgstr[1] "%(value).1f οκτάκις εκατομμύρια" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s οκτάκις εκατομμύριο" +msgstr[1] "%(value)s οκτάκις εκατομμύρια" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f εννεάκις εκατομμύριο" +msgstr[1] "%(value).1f εννεάκις εκατομμύρια" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s εννεάκις εκατομμύριο" +msgstr[1] "%(value)s εννεάκις εκατομμύρια" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f δεκάκις εκατομμύριο" +msgstr[1] "%(value).1f δεκάκις εκατομμύρια" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s δεκάκις εκατομμύριο" +msgstr[1] "%(value)s δεκάκις εκατομμύρια" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f googol" +msgstr[1] "%(value).1f googol" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" +msgstr[1] "%(value)s googol" + +msgid "one" +msgstr "ένα" + +msgid "two" +msgstr "δύο" + +msgid "three" +msgstr "τρία" + +msgid "four" +msgstr "τέσσερα" + +msgid "five" +msgstr "πέντε" + +msgid "six" +msgstr "έξι" + +msgid "seven" +msgstr "εφτά" + +msgid "eight" +msgstr "οκτώ" + +msgid "nine" +msgstr "εννιά" + +msgid "today" +msgstr "σήμερα" + +msgid "tomorrow" +msgstr "αύριο" + +msgid "yesterday" +msgstr "χθες" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "πριν από %(delta)s" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "μια ώρα πρίν" +msgstr[1] "%(count)s ώρες πρίν" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "ένα λεπτό πρίν" +msgstr[1] "%(count)s λεπτά πρίν" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "ένα δευτερόλεπτο πρίν" +msgstr[1] "%(count)s δευτερόλεπτα πρίν" + +msgid "now" +msgstr "τώρα" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "ένα δευτερόλεπτο από τώρα" +msgstr[1] "%(count)s δευτερόλεπτα από τώρα" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "ένα λεπτό από τώρα" +msgstr[1] "%(count)s λεπτά από τώρα" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "μία ώρα από τώρα" +msgstr[1] "%(count)s ώρες από τώρα" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "σε %(delta)s" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d χρόνος" +msgstr[1] "%d χρόνια" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d μήνας" +msgstr[1] "%d μήνες" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d εβδομάδα" +msgstr[1] "%d εβδομάδες" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d μέρα" +msgstr[1] "%d μέρες" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d ώρα" +msgstr[1] "%d ώρες" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d λεπτό" +msgstr[1] "%d λεπτά" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d χρόνος" +msgstr[1] "%d χρόνια" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d μήνας" +msgstr[1] "%d μήνες" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d εβδομάδα" +msgstr[1] "%d εβδομάδες" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d μέρα" +msgstr[1] "%d μέρες" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d ώρα" +msgstr[1] "%d ώρες" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d λεπτό" +msgstr[1] "%d λεπτά" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/en/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/en/LC_MESSAGES/django.mo new file mode 100644 index 0000000..08a7b68 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/en/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/en/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/en/LC_MESSAGES/django.po new file mode 100644 index 0000000..fa868e7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/en/LC_MESSAGES/django.po @@ -0,0 +1,378 @@ +# This file is distributed under the same license as the Django package. +# +msgid "" +msgstr "" +"Project-Id-Version: Django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2010-05-13 15:35+0200\n" +"Last-Translator: Django team\n" +"Language-Team: English \n" +"Language: en\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: contrib/humanize/apps.py:7 +msgid "Humanize" +msgstr "" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +#: contrib/humanize/templatetags/humanize.py:35 +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +#: contrib/humanize/templatetags/humanize.py:39 +msgctxt "ordinal 0" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +#: contrib/humanize/templatetags/humanize.py:41 +msgctxt "ordinal 1" +msgid "{}st" +msgstr "" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +#: contrib/humanize/templatetags/humanize.py:43 +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "" + +#. Translators: Ordinal format when value ends with 3, e.g. 83rd, except 13. +#: contrib/humanize/templatetags/humanize.py:45 +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +#: contrib/humanize/templatetags/humanize.py:47 +msgctxt "ordinal 4" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +#: contrib/humanize/templatetags/humanize.py:49 +msgctxt "ordinal 5" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +#: contrib/humanize/templatetags/humanize.py:51 +msgctxt "ordinal 6" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +#: contrib/humanize/templatetags/humanize.py:53 +msgctxt "ordinal 7" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +#: contrib/humanize/templatetags/humanize.py:55 +msgctxt "ordinal 8" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +#: contrib/humanize/templatetags/humanize.py:57 +msgctxt "ordinal 9" +msgid "{}th" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:88 +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:89 +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:90 +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:94 +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:100 +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:105 +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:109 +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:111 +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:112 +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:113 +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:114 +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:158 +msgid "one" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:159 +msgid "two" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:160 +msgid "three" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:161 +msgid "four" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:162 +msgid "five" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:163 +msgid "six" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:164 +msgid "seven" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:165 +msgid "eight" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:166 +msgid "nine" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:188 +msgid "today" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:190 +msgid "tomorrow" +msgstr "" + +#: contrib/humanize/templatetags/humanize.py:192 +msgid "yesterday" +msgstr "" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 weeks' +#: contrib/humanize/templatetags/humanize.py:210 +#, python-format +msgid "%(delta)s ago" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#: contrib/humanize/templatetags/humanize.py:213 +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#: contrib/humanize/templatetags/humanize.py:216 +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#: contrib/humanize/templatetags/humanize.py:219 +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:220 +msgid "now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#: contrib/humanize/templatetags/humanize.py:224 +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#: contrib/humanize/templatetags/humanize.py:229 +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#: contrib/humanize/templatetags/humanize.py:234 +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 weeks' +#: contrib/humanize/templatetags/humanize.py:237 +#, python-format +msgid "%(delta)s from now" +msgstr "" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#: contrib/humanize/templatetags/humanize.py:242 +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:245 +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:248 +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:250 +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:252 +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:255 +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "" +msgstr[1] "" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s from now' +#: contrib/humanize/templatetags/humanize.py:262 +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:265 +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:268 +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:271 +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:274 +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "" +msgstr[1] "" + +#: contrib/humanize/templatetags/humanize.py:277 +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "" +msgstr[1] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/en_AU/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/en_AU/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b381a0f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/en_AU/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/en_AU/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/en_AU/LC_MESSAGES/django.po new file mode 100644 index 0000000..6417eb8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/en_AU/LC_MESSAGES/django.po @@ -0,0 +1,328 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Tom Fifield , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2021-09-22 07:22+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: English (Australia) (http://www.transifex.com/django/django/" +"language/en_AU/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_AU\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Humanise" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}th" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}th" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}st" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}nd" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}rd" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}th" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}th" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}th" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}th" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}th" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}th" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "" +msgstr[1] "" + +msgid "one" +msgstr "" + +msgid "two" +msgstr "" + +msgid "three" +msgstr "" + +msgid "four" +msgstr "" + +msgid "five" +msgstr "" + +msgid "six" +msgstr "" + +msgid "seven" +msgstr "" + +msgid "eight" +msgstr "" + +msgid "nine" +msgstr "" + +msgid "today" +msgstr "" + +msgid "tomorrow" +msgstr "" + +msgid "yesterday" +msgstr "" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" +msgstr[1] "" + +msgid "now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "" +msgstr[1] "" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "" +msgstr[1] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/en_GB/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/en_GB/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0901a67 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/en_GB/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/en_GB/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/en_GB/LC_MESSAGES/django.po new file mode 100644 index 0000000..1098658 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/en_GB/LC_MESSAGES/django.po @@ -0,0 +1,263 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# bfirsh , 2011 +# jon_atkinson , 2011-2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: English (United Kingdom) (http://www.transifex.com/django/" +"django/language/en_GB/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_GB\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "" + +msgid "th" +msgstr "th" + +msgid "st" +msgstr "st" + +msgid "nd" +msgstr "nd" + +msgid "rd" +msgstr "rd" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f million" +msgstr[1] "%(value).1f million" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s million" +msgstr[1] "%(value)s million" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f billion" +msgstr[1] "%(value).1f billion" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s billion" +msgstr[1] "%(value)s billion" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f trillion" +msgstr[1] "%(value).1f trillion" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s trillion" +msgstr[1] "%(value)s trillion" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f quadrillion" +msgstr[1] "%(value).1f quadrillion" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s quadrillion" +msgstr[1] "%(value)s quadrillion" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f quintillion" +msgstr[1] "%(value).1f quintillion" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s quintillion" +msgstr[1] "%(value)s quintillion" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f sextillion" +msgstr[1] "%(value).1f sextillion" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s sextillion" +msgstr[1] "%(value)s sextillion" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f septillion" +msgstr[1] "%(value).1f septillion" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septillion" +msgstr[1] "%(value)s septillion" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f octillion" +msgstr[1] "%(value).1f octillion" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s octillion" +msgstr[1] "%(value)s octillion" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f nonillion" +msgstr[1] "%(value).1f nonillion" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s nonillion" +msgstr[1] "%(value)s nonillion" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f decillion" +msgstr[1] "%(value).1f decillion" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s decillion" +msgstr[1] "%(value)s decillion" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f googol" +msgstr[1] "%(value).1f googol" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" +msgstr[1] "%(value)s googol" + +msgid "one" +msgstr "one" + +msgid "two" +msgstr "two" + +msgid "three" +msgstr "three" + +msgid "four" +msgstr "four" + +msgid "five" +msgstr "five" + +msgid "six" +msgstr "six" + +msgid "seven" +msgstr "seven" + +msgid "eight" +msgstr "eight" + +msgid "nine" +msgstr "nine" + +msgid "today" +msgstr "today" + +msgid "tomorrow" +msgstr "tomorrow" + +msgid "yesterday" +msgstr "yesterday" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "%(delta)s ago" + +msgid "now" +msgstr "now" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "%(delta)s from now" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/eo/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/eo/LC_MESSAGES/django.mo new file mode 100644 index 0000000..6c0df78 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/eo/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/eo/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/eo/LC_MESSAGES/django.po new file mode 100644 index 0000000..4f13eb3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/eo/LC_MESSAGES/django.po @@ -0,0 +1,394 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Baptiste Darthenay , 2014,2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2018-05-24 15:17+0000\n" +"Last-Translator: Baptiste Darthenay \n" +"Language-Team: Esperanto (http://www.transifex.com/django/django/language/" +"eo/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eo\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Humanigi" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}a" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}a" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}a" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}a" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}a" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}a" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}a" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}a" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}a" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}a" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}a" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f milionoj" +msgstr[1] "%(value).1f milionoj" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s milionoj" +msgstr[1] "%(value)s milionoj" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f miliardoj" +msgstr[1] "%(value).1f miliardoj" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s miliardoj" +msgstr[1] "%(value)s miliardoj" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f triiliono" +msgstr[1] "%(value).1f triiliono" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s triilionoj" +msgstr[1] "%(value)s triilionoj" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f kvariliono" +msgstr[1] "%(value).1f kvariliono" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s kvarilionoj" +msgstr[1] "%(value)s kvarilionoj" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f kvinilionoj" +msgstr[1] "%(value).1f kvinilionoj" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s kvinilionoj" +msgstr[1] "%(value)s kvinilionoj" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f sesilionoj" +msgstr[1] "%(value).1f sesilionoj" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s sesilionoj" +msgstr[1] "%(value)s sesilionoj" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f sepilionoj" +msgstr[1] "%(value).1f sepilionoj" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s sepilionoj" +msgstr[1] "%(value)s sepilionoj" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f okilionoj" +msgstr[1] "%(value).1f okilionoj" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s okilionoj" +msgstr[1] "%(value)s okilionoj" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f naŭilionoj" +msgstr[1] "%(value).1f naŭilionoj" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s naŭilionoj" +msgstr[1] "%(value)s naŭilionoj" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f dekilionoj" +msgstr[1] "%(value).1f dekilionoj" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s dekilionoj" +msgstr[1] "%(value)s dekilionoj" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f guglo" +msgstr[1] "%(value).1f guglo" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s gugloj" +msgstr[1] "%(value)s gugloj" + +msgid "one" +msgstr "unu" + +msgid "two" +msgstr "du" + +msgid "three" +msgstr "tri" + +msgid "four" +msgstr "kvar" + +msgid "five" +msgstr "kvin" + +msgid "six" +msgstr "ses" + +msgid "seven" +msgstr "sep" + +msgid "eight" +msgstr "ok" + +msgid "nine" +msgstr "naŭ" + +msgid "today" +msgstr "hodiaŭ" + +msgid "tomorrow" +msgstr "morgaŭ" + +msgid "yesterday" +msgstr "hieraŭ" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "antaŭ %(delta)s" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "horo antaŭe" +msgstr[1] "%(count)s horoj antaŭe" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "minuto antaŭe" +msgstr[1] "%(count)s minutoj antaŭe" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "sekundo antaŭe" +msgstr[1] "%(count)s sekundoj antaŭe" + +msgid "now" +msgstr "nun" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "post sekundo" +msgstr[1] "post %(count)s sekundoj" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "post minuto" +msgstr[1] "post %(count)s minutoj" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "post horo" +msgstr[1] "post %(count)s horoj" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "antaŭ %(delta)s" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d jaro" +msgstr[1] "%d jaroj" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d monato" +msgstr[1] "%d monatoj" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d semajno" +msgstr[1] "%d semajnoj" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d tago" +msgstr[1] "%d tagoj" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d horo" +msgstr[1] "%d horoj" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d minuto" +msgstr[1] "%d minutoj" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d jaro" +msgstr[1] "%d jaroj" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d monato" +msgstr[1] "%d monatoj" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d semajno" +msgstr[1] "%d semajnoj" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d tago" +msgstr[1] "%d tagoj" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d horo" +msgstr[1] "%d horoj" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d minuto" +msgstr[1] "%d minutoj" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8946e3a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es/LC_MESSAGES/django.po new file mode 100644 index 0000000..b4faf18 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es/LC_MESSAGES/django.po @@ -0,0 +1,365 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Antoni Aloy , 2012 +# e4db27214f7e7544f2022c647b585925_bb0e321, 2014 +# Ignacio José Lizarán Rus , 2019 +# Jannis Leidel , 2011 +# Leonardo J. Caballero G. , 2011 +# Luigy, 2019 +# ntrrgc , 2014 +# Uriel Medina , 2020-2021 +# Veronicabh , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2022-04-24 18:40+0000\n" +"Last-Translator: Uriel Medina , 2020-2021\n" +"Language-Team: Spanish (http://www.transifex.com/django/django/language/" +"es/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Humanizar" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}º" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s millon" +msgstr[1] "%(value)s millones" +msgstr[2] "%(value)s millones" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s millardo" +msgstr[1] "%(value)s millardos" +msgstr[2] "%(value)s millardos" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s billón" +msgstr[1] "%(value)s billones" +msgstr[2] "%(value)s billones" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s billardos" +msgstr[1] "%(value)s billardos" +msgstr[2] "%(value)s billardos" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s trillón" +msgstr[1] "%(value)s trillones" +msgstr[2] "%(value)s trillones" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s trillardo" +msgstr[1] "%(value)s trillardos" +msgstr[2] "%(value)s trillardos" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s cuatrillón" +msgstr[1] "%(value)s cuatrillones" +msgstr[2] "%(value)s cuatrillones" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s cuatrillardo" +msgstr[1] "%(value)s cuatrillardos" +msgstr[2] "%(value)s cuatrillardos" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s quintillón" +msgstr[1] "%(value)s quintillones" +msgstr[2] "%(value)s quintillones" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s quintillardo" +msgstr[1] "%(value)s quintillardos" +msgstr[2] "%(value)s quintillardos" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] " %(value)s googol" +msgstr[1] " %(value)s gúgoles" +msgstr[2] " %(value)s gúgoles" + +msgid "one" +msgstr "uno" + +msgid "two" +msgstr "dos" + +msgid "three" +msgstr "tres" + +msgid "four" +msgstr "cuatro" + +msgid "five" +msgstr "cinco" + +msgid "six" +msgstr "seis" + +msgid "seven" +msgstr "siete" + +msgid "eight" +msgstr "ocho" + +msgid "nine" +msgstr "nueve" + +msgid "today" +msgstr "hoy" + +msgid "tomorrow" +msgstr "mañana" + +msgid "yesterday" +msgstr "ayer" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "hace %(delta)s" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "hace una hora" +msgstr[1] "hace %(count)s horas" +msgstr[2] "hace %(count)s horas" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "hace un minuto" +msgstr[1] "hace %(count)s minutos" +msgstr[2] "hace %(count)s minutos" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "hace un segundo" +msgstr[1] "hace %(count)s segundos" +msgstr[2] "hace %(count)s segundos" + +msgid "now" +msgstr "ahora" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "un segundo a partir de ahora" +msgstr[1] "%(count)s segundos a partir de ahora" +msgstr[2] "%(count)s segundos a partir de ahora" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "un minuto a partir de ahora" +msgstr[1] "%(count)s minutos a partir de ahora" +msgstr[2] "%(count)s minutos a partir de ahora" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "una hora a partir de ahora" +msgstr[1] "%(count)s horas a partir de ahora" +msgstr[2] "%(count)s horas a partir de ahora" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s desde ahora" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d año" +msgstr[1] "%(num)d años" +msgstr[2] "%(num)d años" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mes" +msgstr[1] "%(num)d meses" +msgstr[2] "%(num)d meses" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d semana" +msgstr[1] "%(num)d semanas" +msgstr[2] "%(num)d semanas" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d día" +msgstr[1] "%(num)d días" +msgstr[2] "%(num)d días" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hora" +msgstr[1] "%(num)d horas" +msgstr[2] "%(num)d horas" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuto" +msgstr[1] "%(num)d minutos" +msgstr[2] "%(num)d minutos" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d año" +msgstr[1] "%(num)d años" +msgstr[2] "%(num)d años" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mes" +msgstr[1] "%(num)d meses" +msgstr[2] "%(num)d meses" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d semana" +msgstr[1] "%(num)d semanas" +msgstr[2] "%(num)d semanas" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d día" +msgstr[1] "%(num)d días" +msgstr[2] "%(num)d días" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hora" +msgstr[1] "%(num)d horas" +msgstr[2] "%(num)d horas" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuto" +msgstr[1] "%(num)d minutos" +msgstr[2] "%(num)d minutos" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es_AR/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es_AR/LC_MESSAGES/django.mo new file mode 100644 index 0000000..62767df Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es_AR/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es_AR/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es_AR/LC_MESSAGES/django.po new file mode 100644 index 0000000..11624ab --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es_AR/LC_MESSAGES/django.po @@ -0,0 +1,332 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Claude Paroz , 2017 +# Jannis Leidel , 2011 +# lardissone , 2014 +# lardissone , 2014 +# Ramiro Morales, 2012,2014-2015,2018,2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2021-11-19 15:15+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Spanish (Argentina) (http://www.transifex.com/django/django/" +"language/es_AR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_AR\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Humanización" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}.º" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}.º" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}.º" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}.º" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}.º" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}.º" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}.º" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}.º" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}.º" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}.º" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}.º" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s millón" +msgstr[1] "%(value)s millones" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s millardo" +msgstr[1] "%(value)s millardos" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s billón" +msgstr[1] "%(value)s billones" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s mil billones" +msgstr[1] "%(value)s miles de billones" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s trillón" +msgstr[1] "%(value)s trilliones" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s mil trillones" +msgstr[1] "%(value)s miles de trillones" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s cuatrillón" +msgstr[1] "%(value)s cuatrillones" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s mil cuatrillones" +msgstr[1] "%(value)s miles de cuatrillones" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s quintillón" +msgstr[1] "%(value)s quintillones" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s mil quintillones" +msgstr[1] "%(value)s miles de quintillones" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s \"gúgol\"" +msgstr[1] "%(value)s \"gúgols\"" + +msgid "one" +msgstr "uno" + +msgid "two" +msgstr "dos" + +msgid "three" +msgstr "tres" + +msgid "four" +msgstr "cuatro" + +msgid "five" +msgstr "cinco" + +msgid "six" +msgstr "seis" + +msgid "seven" +msgstr "siete" + +msgid "eight" +msgstr "ocho" + +msgid "nine" +msgstr "nueve" + +msgid "today" +msgstr "hoy" + +msgid "tomorrow" +msgstr "mañana" + +msgid "yesterday" +msgstr "ayer" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "hace %(delta)s" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "hace una hora" +msgstr[1] "hace %(count)s horas" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "hace un minuto" +msgstr[1] "hace %(count)s minutos" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "hace un segundo" +msgstr[1] "hace %(count)s segundos" + +msgid "now" +msgstr "ahora" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "dentro de un segundo" +msgstr[1] "dentro de %(count)s segundos" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "dentro de un minuto" +msgstr[1] "dentro de %(count)s minutos" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "dentro de una hora" +msgstr[1] "dentro de %(count)s horas" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "dentro de %(delta)s" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d año" +msgstr[1] "%(num)d años" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mes" +msgstr[1] "%(num)d meses" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d semana" +msgstr[1] "%(num)d semanas" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d día" +msgstr[1] "%(num)d días" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hora" +msgstr[1] "%(num)d horas" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuto" +msgstr[1] "%(num)d minutos" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d año" +msgstr[1] "%(num)d años" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mes" +msgstr[1] "%(num)d meses" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d semana" +msgstr[1] "%(num)d semanas" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d día" +msgstr[1] "%(num)d días" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hora" +msgstr[1] "%(num)d horas" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuto" +msgstr[1] "%(num)d minutos" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es_CO/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es_CO/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3a00392 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es_CO/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es_CO/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es_CO/LC_MESSAGES/django.po new file mode 100644 index 0000000..75648b1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es_CO/LC_MESSAGES/django.po @@ -0,0 +1,267 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Antoni Aloy , 2012 +# Ernesto Avilés Vázquez , 2014 +# Jannis Leidel , 2011 +# Leonardo J. Caballero G. , 2011 +# ntrrgc , 2014 +# Veronicabh , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 21:47+0000\n" +"Last-Translator: Carlos Muñoz \n" +"Language-Team: Spanish (Colombia) (http://www.transifex.com/django/django/" +"language/es_CO/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_CO\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Humanizar" + +msgid "th" +msgstr "º" + +msgid "st" +msgstr "º" + +msgid "nd" +msgstr "º" + +msgid "rd" +msgstr "º" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f millón" +msgstr[1] "%(value).1f millón" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s millón" +msgstr[1] "%(value)s millones" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f millardo" +msgstr[1] "%(value).1f millardos" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s millardo" +msgstr[1] "%(value)s millardos" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f billón" +msgstr[1] "%(value).1f billón" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s billón" +msgstr[1] "%(value)s billones" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f billardo" +msgstr[1] "%(value).1f billardos" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s billardos" +msgstr[1] "%(value)s billardos" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f trillón" +msgstr[1] "%(value).1f trillones" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s trillón" +msgstr[1] "%(value)s trillones" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f trillardo" +msgstr[1] "%(value).1f trillardos" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s trillardo" +msgstr[1] "%(value)s trillardos" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f cuatrillón" +msgstr[1] "%(value).1f cuatrillones" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s cuatrillón" +msgstr[1] "%(value)s cuatrillones" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f cuatrillardo" +msgstr[1] "%(value).1f cuatrillardos" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s cuatrillardo" +msgstr[1] "%(value)s cuatrillardos" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f quintillón" +msgstr[1] "%(value).1f quintillones" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s quintillón" +msgstr[1] "%(value)s quintillones" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f quintillardo" +msgstr[1] "%(value).1f quintillardos" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s quintillardo" +msgstr[1] "%(value)s quintillardos" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f googol" +msgstr[1] "%(value).1f googol" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] " %(value)s googol" +msgstr[1] " %(value)s googol" + +msgid "one" +msgstr "uno" + +msgid "two" +msgstr "dos" + +msgid "three" +msgstr "tres" + +msgid "four" +msgstr "cuatro" + +msgid "five" +msgstr "cinco" + +msgid "six" +msgstr "seis" + +msgid "seven" +msgstr "siete" + +msgid "eight" +msgstr "ocho" + +msgid "nine" +msgstr "nueve" + +msgid "today" +msgstr "hoy" + +msgid "tomorrow" +msgstr "mañana" + +msgid "yesterday" +msgstr "ayer" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "hace %(delta)s" + +msgid "now" +msgstr "ahora" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "hace un segundo" +msgstr[1] "hace %(count)s segundos" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "hace un minuto" +msgstr[1] "hace %(count)s minutos" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "hace una hora" +msgstr[1] "hace %(count)s horas" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "%(delta)s a partir de ahora" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "un segundo a partir de ahora" +msgstr[1] "%(count)s segundos a partir de ahora" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "un minuto a partir de ahora" +msgstr[1] "%(count)s minutos a partir de ahora" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "una hora a partir de ahora" +msgstr[1] "%(count)s horas a partir de ahora" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es_MX/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es_MX/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b5199ef Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es_MX/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es_MX/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es_MX/LC_MESSAGES/django.po new file mode 100644 index 0000000..b3f666b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es_MX/LC_MESSAGES/django.po @@ -0,0 +1,264 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Abraham Estrada, 2011-2012 +# Alex Dzul , 2015 +# Juan Pablo Flores , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 18:03+0000\n" +"Last-Translator: Juan Pablo Flores \n" +"Language-Team: Spanish (Mexico) (http://www.transifex.com/django/django/" +"language/es_MX/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_MX\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Humanizar" + +msgid "th" +msgstr "to" + +msgid "st" +msgstr "ro" + +msgid "nd" +msgstr "do" + +msgid "rd" +msgstr "ro" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f millón" +msgstr[1] "%(value).1f millones" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s millones" +msgstr[1] "%(value)s millones" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f billón" +msgstr[1] "%(value).1f billones" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s billiones" +msgstr[1] "%(value)s billiones" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f trillón" +msgstr[1] "%(value).1f trillones" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s trilliones" +msgstr[1] "%(value)s trilliones" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f cuatrillón" +msgstr[1] "%(value).1f cuatrillones" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s cuatrillón" +msgstr[1] "%(value)s cuatrillones" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f quintillón" +msgstr[1] "%(value).1f quintillones" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s quintillón" +msgstr[1] "%(value)s quintillones" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f sextillón" +msgstr[1] "%(value).1f sextillones" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s sextillón" +msgstr[1] "%(value)s sextillones" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f septillón" +msgstr[1] "%(value).1f septillones" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septillón" +msgstr[1] "%(value)s septillones" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f octillón" +msgstr[1] "%(value).1f octillones" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s octillón" +msgstr[1] "%(value)s octillones" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f nonillion" +msgstr[1] "%(value).1f nonillion" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s nonillón" +msgstr[1] "%(value)s nonillones" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f decillón" +msgstr[1] "%(value).1f decillones" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s decillón" +msgstr[1] "%(value)s decillones" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f googol" +msgstr[1] "%(value).1f googoles" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" +msgstr[1] "%(value)s googoles" + +msgid "one" +msgstr "uno" + +msgid "two" +msgstr "dos" + +msgid "three" +msgstr "tres" + +msgid "four" +msgstr "cuatro" + +msgid "five" +msgstr "cinco" + +msgid "six" +msgstr "seis" + +msgid "seven" +msgstr "siete" + +msgid "eight" +msgstr "ocho" + +msgid "nine" +msgstr "nueve" + +msgid "today" +msgstr "hoy" + +msgid "tomorrow" +msgstr "mañana" + +msgid "yesterday" +msgstr "ayer" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "hace %(delta)s" + +msgid "now" +msgstr "ahora" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "hace un segundo" +msgstr[1] "Hace %(count)s segundos" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "hace un minuto" +msgstr[1] "Hace %(count)s minutos" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "hace una hora" +msgstr[1] "Hace %(count)s horas" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "%(delta)s a partir de ahora" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "Un segundo desde ahora" +msgstr[1] "%(count)s desde ahora" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es_VE/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es_VE/LC_MESSAGES/django.mo new file mode 100644 index 0000000..31bccab Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es_VE/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es_VE/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es_VE/LC_MESSAGES/django.po new file mode 100644 index 0000000..d5ebd03 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/es_VE/LC_MESSAGES/django.po @@ -0,0 +1,262 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Eduardo , 2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 21:47+0000\n" +"Last-Translator: Eduardo \n" +"Language-Team: Spanish (Venezuela) (http://www.transifex.com/django/django/" +"language/es_VE/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_VE\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Humanizar" + +msgid "th" +msgstr "" + +msgid "st" +msgstr "" + +msgid "nd" +msgstr "" + +msgid "rd" +msgstr "" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "" +msgstr[1] "" + +msgid "one" +msgstr "uno" + +msgid "two" +msgstr "dos" + +msgid "three" +msgstr "tres" + +msgid "four" +msgstr "cuatro" + +msgid "five" +msgstr "cinco" + +msgid "six" +msgstr "seis" + +msgid "seven" +msgstr "siete" + +msgid "eight" +msgstr "ocho" + +msgid "nine" +msgstr "nueve" + +msgid "today" +msgstr "hoy" + +msgid "tomorrow" +msgstr "mañana" + +msgid "yesterday" +msgstr "ayer" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "" + +msgid "now" +msgstr "ahora" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/et/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/et/LC_MESSAGES/django.mo new file mode 100644 index 0000000..85274d0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/et/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/et/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/et/LC_MESSAGES/django.po new file mode 100644 index 0000000..16cf8fb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/et/LC_MESSAGES/django.po @@ -0,0 +1,334 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Claude Paroz , 2013 +# Jannis Leidel , 2011 +# Janno Liivak , 2013 +# Martin , 2021 +# Martin , 2019 +# Marti Raudsepp , 2014 +# Ragnar Rebase , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2021-11-19 08:47+0000\n" +"Last-Translator: Martin \n" +"Language-Team: Estonian (http://www.transifex.com/django/django/language/" +"et/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: et\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Inimlikustamine" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}." + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s miljon" +msgstr[1] "%(value)s miljonit" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s miljard" +msgstr[1] "%(value)s miljardit" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s triljon" +msgstr[1] "%(value)s triljonit" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s kvadriljon" +msgstr[1] "%(value)s kvadriljonit" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s kvintiljon" +msgstr[1] "%(value)s kvintiljonit" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s sekstiljon" +msgstr[1] "%(value)s sekstiljonit" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septiljon" +msgstr[1] "%(value)s septiljonit" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s oktiljon" +msgstr[1] "%(value)s oktiljonit" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s noniljon" +msgstr[1] "%(value)s noniljonit" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s detsiljon" +msgstr[1] "%(value)s detsiljonit" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" +msgstr[1] "%(value)s googolit" + +msgid "one" +msgstr "üks" + +msgid "two" +msgstr "kaks" + +msgid "three" +msgstr "kolm" + +msgid "four" +msgstr "neli" + +msgid "five" +msgstr "viis" + +msgid "six" +msgstr "kuus" + +msgid "seven" +msgstr "seitse" + +msgid "eight" +msgstr "kaheksa" + +msgid "nine" +msgstr "üheksa" + +msgid "today" +msgstr "täna" + +msgid "tomorrow" +msgstr "homme" + +msgid "yesterday" +msgstr "eile" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s tagasi" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "tund tagasi" +msgstr[1] "%(count)s tundi tagasi" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "minut tagasi" +msgstr[1] "%(count)s minutit tagasi" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "sekund tagasi" +msgstr[1] "%(count)s sekundit tagasi" + +msgid "now" +msgstr "praegu" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "sekund praegusest hetkest" +msgstr[1] "%(count)s sekundit praegusest hetkest" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "minut praegusest hetkest" +msgstr[1] "%(count)s minutit praegusest hetkest" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "tund praegusest hetkest" +msgstr[1] "%(count)s tundi praegusest hetkest" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s praegusest hetkest" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d aasta" +msgstr[1] "%(num)d aastat" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d kuu" +msgstr[1] "%(num)d kuud" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d nädal" +msgstr[1] "%(num)d nädalat" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d päev" +msgstr[1] "%(num)d päeva" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d tund" +msgstr[1] "%(num)d tundi" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minut" +msgstr[1] "%(num)d minutit" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d aasta" +msgstr[1] "%(num)d aastat" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d kuu" +msgstr[1] "%(num)d kuud" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d nädal" +msgstr[1] "%(num)d nädalat" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d päev" +msgstr[1] "%(num)d päeva" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d tund" +msgstr[1] "%(num)d tundi" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minut" +msgstr[1] "%(num)d minutit" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/eu/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/eu/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d167d67 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/eu/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/eu/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/eu/LC_MESSAGES/django.po new file mode 100644 index 0000000..b8ed0c5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/eu/LC_MESSAGES/django.po @@ -0,0 +1,331 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Aitzol Naberan , 2011-2012,2016 +# Ander Martinez , 2014 +# Eneko Illarramendi , 2017-2018,2022 +# Jannis Leidel , 2011 +# julen, 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2022-07-24 18:40+0000\n" +"Last-Translator: Eneko Illarramendi \n" +"Language-Team: Basque (http://www.transifex.com/django/django/language/eu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Humanizatu" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}." + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "milioi %(value)s" +msgstr[1] "%(value)s milioi" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "bilioi %(value)s" +msgstr[1] "%(value)s bilioi" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "trilioi %(value)s" +msgstr[1] "%(value)s trilioi" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "kuatrilioi %(value)s" +msgstr[1] "%(value)s kuatrilioi" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "kintilioi %(value)s" +msgstr[1] "%(value)s kintilioi" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "sextilioi %(value)s" +msgstr[1] "%(value)s sextilioi" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "septilioi %(value)s" +msgstr[1] "%(value)s septilioi" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "octillioi %(value)s" +msgstr[1] " %(value)s octilioi" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "nonilioi %(value)s" +msgstr[1] "%(value)s nonilioi" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "dezilioi %(value)s " +msgstr[1] "%(value)s dezilioi" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "googol %(value)s" +msgstr[1] "%(value)s googol" + +msgid "one" +msgstr "bat" + +msgid "two" +msgstr "bi" + +msgid "three" +msgstr "hiru" + +msgid "four" +msgstr "lau" + +msgid "five" +msgstr "bost" + +msgid "six" +msgstr "sei" + +msgid "seven" +msgstr "zazpi" + +msgid "eight" +msgstr "zortzi" + +msgid "nine" +msgstr "bederatzi" + +msgid "today" +msgstr "gaur" + +msgid "tomorrow" +msgstr "bihar" + +msgid "yesterday" +msgstr "atzo" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "duela %(delta)s" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "duela ordubete" +msgstr[1] "duela %(count)s ordu" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "duela minutu bat" +msgstr[1] "duela %(count)s minutu" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "duela segundu bat" +msgstr[1] "duela %(count)s segundu" + +msgid "now" +msgstr "orain" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "segundu bat barru" +msgstr[1] "%(count)s segundu barru" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "minutu bat barru" +msgstr[1] "%(count)s minutu barru" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "ordubete barru" +msgstr[1] "%(count)s ordu barru" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s barru" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] " urte %(num)d" +msgstr[1] "%(num)d urte" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "hilabete %(num)d" +msgstr[1] "%(num)d hilabete" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "aste %(num)d" +msgstr[1] "%(num)d aste" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "egun %(num)d" +msgstr[1] "%(num)d egun" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "ordu %(num)d" +msgstr[1] "%(num)d ordu" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "minutu %(num)d" +msgstr[1] "%(num)d minutu" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "urte %(num)d" +msgstr[1] "%(num)d urte" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "hilabete %(num)d" +msgstr[1] "%(num)d hilabete" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "aste %(num)d" +msgstr[1] "%(num)d aste" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "egun %(num)d" +msgstr[1] "%(num)d egun" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "ordu %(num)d" +msgstr[1] "%(num)d ordu" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "minutu %(num)d" +msgstr[1] "%(num)d minutu" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/fa/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/fa/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b8fe938 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/fa/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/fa/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/fa/LC_MESSAGES/django.po new file mode 100644 index 0000000..25daae9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/fa/LC_MESSAGES/django.po @@ -0,0 +1,335 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ali Nikneshan , 2012 +# Alireza Savand , 2012 +# Claude Paroz , 2013 +# Eshagh , 2022 +# Jannis Leidel , 2011 +# MJafar Mashhadi , 2018 +# Mohammad Hossein Mojtahedi , 2016 +# Reza Mohammadi , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2022-07-24 18:40+0000\n" +"Last-Translator: Eshagh \n" +"Language-Team: Persian (http://www.transifex.com/django/django/language/" +"fa/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fa\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Humanize" +msgstr "انسانی‌سازی" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}م" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}م" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}ین" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}م" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}م" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}م" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}م" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}م" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}م" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}م" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}م" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s میلیون" +msgstr[1] "%(value)s میلیون" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s میلیارد" +msgstr[1] "%(value)s میلیارد" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s تریلیون" +msgstr[1] "%(value)s تریلیون" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s کوادریلیون" +msgstr[1] "%(value)s کوادریلیون" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s کوانتینیوم" +msgstr[1] "%(value)s کوانتینیوم" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s با ۲۱ صفر" +msgstr[1] "%(value)s با ۲۱ صفر" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s سپتیلیون" +msgstr[1] "%(value)s سپتیلیون" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s octillion" +msgstr[1] "%(value)s octillion" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s با ۵۴ صفر" +msgstr[1] "%(value)s با ۵۴ صفر" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s با شصت صفر" +msgstr[1] "%(value)s با شصت صفر" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s گوگُل" +msgstr[1] "%(value)s گوگُل" + +msgid "one" +msgstr "یک" + +msgid "two" +msgstr "دو" + +msgid "three" +msgstr "سه" + +msgid "four" +msgstr "چهار" + +msgid "five" +msgstr "پنج" + +msgid "six" +msgstr "شش" + +msgid "seven" +msgstr "هفت" + +msgid "eight" +msgstr "هشت" + +msgid "nine" +msgstr "نُه" + +msgid "today" +msgstr "امروز" + +msgid "tomorrow" +msgstr "فردا" + +msgid "yesterday" +msgstr "دیروز" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s پیش" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "%(count)s ساعت پیش" +msgstr[1] "%(count)s ساعت پیش" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "%(count)s دقیقه پیش" +msgstr[1] "%(count)s دقیقه پیش" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "%(count)s ثانیه پیش" +msgstr[1] "%(count)s ثانیه پیش" + +msgid "now" +msgstr "اکنون" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "%(count)s ثانیه دیگر" +msgstr[1] "%(count)s ثانیه دیگر" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "%(count)s دقیقه دیگر" +msgstr[1] "%(count)s دقیقه دیگر" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "%(count)s ساعت دیگر" +msgstr[1] "%(count)s ساعت دیگر" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s دیگر" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d سال" +msgstr[1] "%(num)d سال" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d ماه" +msgstr[1] "%(num)d ماه" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d هفته" +msgstr[1] "%(num)d هفته" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d روز" +msgstr[1] "%(num)d روز" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d ساعت" +msgstr[1] "%(num)d ساعت" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d دقیقه" +msgstr[1] "%(num)d دقیقه" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d سال" +msgstr[1] "%(num)d سال" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d ماه" +msgstr[1] "%(num)d ماه" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d هفته" +msgstr[1] "%(num)d هفته" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d روز" +msgstr[1] "%(num)d روز" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d ساعت" +msgstr[1] "%(num)d ساعت" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d دقیقه" +msgstr[1] "%(num)d دقیقه" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/fi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/fi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..54466b8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/fi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/fi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/fi/LC_MESSAGES/django.po new file mode 100644 index 0000000..aee5335 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/fi/LC_MESSAGES/django.po @@ -0,0 +1,331 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Aarni Koskela, 2015,2020-2021 +# Antti Kaihola , 2011 +# Jannis Leidel , 2011 +# Lasse Liehu , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2021-11-22 15:15+0000\n" +"Last-Translator: Aarni Koskela\n" +"Language-Team: Finnish (http://www.transifex.com/django/django/language/" +"fi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Ihmistys" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}." + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s miljoona" +msgstr[1] "%(value)s miljoonaa" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s miljardi" +msgstr[1] "%(value)s miljardia" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s biljoona" +msgstr[1] "%(value)s biljoonaa" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s kvadriljoona" +msgstr[1] "%(value)s kvadriljoonaa" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s kvintiljoona" +msgstr[1] "%(value)s kvintiljoonaa" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s sekstiljoona" +msgstr[1] "%(value)s sekstiljoonaa" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septiljoona" +msgstr[1] "%(value)s septiljoonaa" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s oktiljoona" +msgstr[1] "%(value)s oktiljoonaa" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s noniljoona" +msgstr[1] "%(value)s noniljoonaa" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s dekiljoona" +msgstr[1] "%(value)s dekiljoonaa" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" +msgstr[1] "%(value)s googolia" + +msgid "one" +msgstr "yksi" + +msgid "two" +msgstr "kaksi" + +msgid "three" +msgstr "kolme" + +msgid "four" +msgstr "neljä" + +msgid "five" +msgstr "viisi" + +msgid "six" +msgstr "kuusi" + +msgid "seven" +msgstr "seitsemän" + +msgid "eight" +msgstr "kahdeksan" + +msgid "nine" +msgstr "yhdeksän" + +msgid "today" +msgstr "tänään" + +msgid "tomorrow" +msgstr "huomenna" + +msgid "yesterday" +msgstr "eilen" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s sitten" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "tunti sitten" +msgstr[1] "%(count)s tuntia sitten" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "minuutti sitten" +msgstr[1] "%(count)s minuuttia sitten" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "sekunti sitten" +msgstr[1] "%(count)s sekuntia sitten" + +msgid "now" +msgstr "nyt" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "sekunnin päästä" +msgstr[1] "%(count)s sekunnin päästä" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "minuutin päästä" +msgstr[1] "%(count)s minuutin päästä" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "tunnin päästä" +msgstr[1] "%(count)s tunnin päästä" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s nykyhetkestä" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d vuosi" +msgstr[1] "%(num)d vuotta" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)dkuukausi" +msgstr[1] "%(num)dkuukautta" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d viikko" +msgstr[1] "%(num)d viikkoa" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)dpäivä" +msgstr[1] "%(num)d päivää" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d tunti" +msgstr[1] "%(num)d tuntia" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuutti" +msgstr[1] "%(num)d minuuttia" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d vuosi" +msgstr[1] "%(num)d vuotta" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d kuukausi" +msgstr[1] "%(num)d kuukautta " + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d viikko" +msgstr[1] "%(num)d viikkoa" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d päivä" +msgstr[1] "%(num)d päivää" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d tunti" +msgstr[1] "%(num)d tuntia" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuutti" +msgstr[1] "%(num)d minuuttia" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/fr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/fr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..eb8e731 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/fr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/fr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 0000000..c5a7e2a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,360 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Claude Paroz , 2013-2014,2018-2019,2021 +# Claude Paroz , 2011 +# Jannis Leidel , 2011 +# Jean-Baptiste Mora, 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2023-04-24 18:40+0000\n" +"Last-Translator: Claude Paroz , " +"2013-2014,2018-2019,2021\n" +"Language-Team: French (http://www.transifex.com/django/django/language/fr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Humanize" +msgstr "Humanisation" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}e" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}e" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}er" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}e" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}e" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}e" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}e" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}e" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}e" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}e" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}e" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s million" +msgstr[1] "%(value)s millions" +msgstr[2] "%(value)s millions" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s milliard" +msgstr[1] "%(value)s milliards" +msgstr[2] "%(value)s milliards" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s billion" +msgstr[1] "%(value)s billions" +msgstr[2] "%(value)s billions" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s quadrillion" +msgstr[1] "%(value)s quadrillions" +msgstr[2] "%(value)s quadrillions" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s quintillion" +msgstr[1] "%(value)s quintillions" +msgstr[2] "%(value)s quintillions" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s sextillion" +msgstr[1] "%(value)s sextillion" +msgstr[2] "%(value)s sextillion" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septillion" +msgstr[1] "%(value)s septillions" +msgstr[2] "%(value)s septillions" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s octillion" +msgstr[1] "%(value)s octillions" +msgstr[2] "%(value)s octillions" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s nonillion" +msgstr[1] "%(value)s nonillions" +msgstr[2] "%(value)s nonillions" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s décillion" +msgstr[1] "%(value)s décillions" +msgstr[2] "%(value)s décillions" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s gogol" +msgstr[1] "%(value)s gogols" +msgstr[2] "%(value)s gogols" + +msgid "one" +msgstr "un" + +msgid "two" +msgstr "deux" + +msgid "three" +msgstr "trois" + +msgid "four" +msgstr "quatre" + +msgid "five" +msgstr "cinq" + +msgid "six" +msgstr "six" + +msgid "seven" +msgstr "sept" + +msgid "eight" +msgstr "huit" + +msgid "nine" +msgstr "neuf" + +msgid "today" +msgstr "aujourd'hui" + +msgid "tomorrow" +msgstr "demain" + +msgid "yesterday" +msgstr "hier" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "il y a %(delta)s" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "il y a une heure" +msgstr[1] "il y a %(count)s heures" +msgstr[2] "il y a %(count)s heures" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "il y a une minute" +msgstr[1] "il y a %(count)s minutes" +msgstr[2] "il y a %(count)s minutes" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "il y a une seconde" +msgstr[1] "il y a %(count)s secondes" +msgstr[2] "il y a %(count)s secondes" + +msgid "now" +msgstr "maintenant" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "dans une seconde" +msgstr[1] "dans %(count)s secondes" +msgstr[2] "dans %(count)s secondes" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "dans une minute" +msgstr[1] "dans %(count)s minutes" +msgstr[2] "dans %(count)s minutes" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "dans une heure" +msgstr[1] "dans %(count)s heures" +msgstr[2] "dans %(count)s heures" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "dans %(delta)s" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d année" +msgstr[1] "%(num)d années" +msgstr[2] "%(num)d années" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mois" +msgstr[1] "%(num)d mois" +msgstr[2] "%(num)d mois" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d semaine" +msgstr[1] "%(num)d semaines" +msgstr[2] "%(num)d semaines" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d jour" +msgstr[1] "%(num)d jours" +msgstr[2] "%(num)d jours" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d heure" +msgstr[1] "%(num)d heures" +msgstr[2] "%(num)d heures" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minute" +msgstr[1] "%(num)d minutes" +msgstr[2] "%(num)d minutes" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d année" +msgstr[1] "%(num)d années" +msgstr[2] "%(num)d années" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mois" +msgstr[1] "%(num)d mois" +msgstr[2] "%(num)d mois" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d semaine" +msgstr[1] "%(num)d semaines" +msgstr[2] "%(num)d semaines" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d jour" +msgstr[1] "%(num)d jours" +msgstr[2] "%(num)d jours" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d heure" +msgstr[1] "%(num)d heures" +msgstr[2] "%(num)d heures" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minute" +msgstr[1] "%(num)d minutes" +msgstr[2] "%(num)d minutes" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/fy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/fy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..489bbab Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/fy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/fy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/fy/LC_MESSAGES/django.po new file mode 100644 index 0000000..2ae2bf8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/fy/LC_MESSAGES/django.po @@ -0,0 +1,261 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:13+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Western Frisian (http://www.transifex.com/projects/p/django/" +"language/fy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fy\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "" + +msgid "th" +msgstr "" + +msgid "st" +msgstr "" + +msgid "nd" +msgstr "" + +msgid "rd" +msgstr "" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "" +msgstr[1] "" + +msgid "one" +msgstr "" + +msgid "two" +msgstr "" + +msgid "three" +msgstr "" + +msgid "four" +msgstr "" + +msgid "five" +msgstr "" + +msgid "six" +msgstr "" + +msgid "seven" +msgstr "" + +msgid "eight" +msgstr "" + +msgid "nine" +msgstr "" + +msgid "today" +msgstr "" + +msgid "tomorrow" +msgstr "" + +msgid "yesterday" +msgstr "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "" + +msgid "now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ga/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ga/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1fb51b9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ga/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ga/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ga/LC_MESSAGES/django.po new file mode 100644 index 0000000..5108ded --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ga/LC_MESSAGES/django.po @@ -0,0 +1,516 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Luke Blaney , 2019 +# Michael Thornhill , 2011-2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2019-06-22 21:44+0000\n" +"Last-Translator: Luke Blaney \n" +"Language-Team: Irish (http://www.transifex.com/django/django/language/ga/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ga\n" +"Plural-Forms: nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : " +"4);\n" + +msgid "Humanize" +msgstr "" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}ú" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}ú" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}ú" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}ú" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}ú" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}ú" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}ú" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}ú" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}ú" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}ú" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}ú" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f milliún" +msgstr[1] "%(value).1f milliún" +msgstr[2] "%(value).1f milliún" +msgstr[3] "%(value).1f milliún" +msgstr[4] "%(value).1f milliún" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] " %(value)s milliún" +msgstr[1] " %(value)s milliún" +msgstr[2] " %(value)s milliún" +msgstr[3] " %(value)s milliún" +msgstr[4] " %(value)s milliún" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f billiún" +msgstr[1] "%(value).1f billiún" +msgstr[2] "%(value).1f billiún" +msgstr[3] "%(value).1f billiún" +msgstr[4] "%(value).1f billiún" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] " %(value)s billiún" +msgstr[1] " %(value)s billiún" +msgstr[2] " %(value)s billiún" +msgstr[3] " %(value)s billiún" +msgstr[4] " %(value)s billiún" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f trilliún" +msgstr[1] "%(value).1f trilliún" +msgstr[2] "%(value).1f trilliún" +msgstr[3] "%(value).1f trilliún" +msgstr[4] "%(value).1f trilliún" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] " %(value)s trilliún" +msgstr[1] " %(value)s trilliún" +msgstr[2] " %(value)s trilliún" +msgstr[3] " %(value)s trilliún" +msgstr[4] " %(value)s trilliún" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f quadrilliún" +msgstr[1] "%(value).1f quadrilliún" +msgstr[2] "%(value).1f quadrilliún" +msgstr[3] "%(value).1f quadrilliún" +msgstr[4] "%(value).1f quadrilliún" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s quadrilliún" +msgstr[1] "%(value)s quadrilliún" +msgstr[2] "%(value)s quadrilliún" +msgstr[3] "%(value)s quadrilliún" +msgstr[4] "%(value)s quadrilliún" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f quintillion" +msgstr[1] "%(value).1f quintillion" +msgstr[2] "%(value).1f quintillion" +msgstr[3] "%(value).1f quintillion" +msgstr[4] "%(value).1f quintillion" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s quintillion" +msgstr[1] "%(value)s quintillion" +msgstr[2] "%(value)s quintillion" +msgstr[3] "%(value)s quintillion" +msgstr[4] "%(value)s quintillion" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f sextillion" +msgstr[1] "%(value).1f sextillion" +msgstr[2] "%(value).1f sextillion" +msgstr[3] "%(value).1f sextillion" +msgstr[4] "%(value).1f sextillion" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s sextillion" +msgstr[1] "%(value)s sextillion" +msgstr[2] "%(value)s sextillion" +msgstr[3] "%(value)s sextillion" +msgstr[4] "%(value)s sextillion" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f septillion" +msgstr[1] "%(value).1f septillion" +msgstr[2] "%(value).1f septillion" +msgstr[3] "%(value).1f septillion" +msgstr[4] "%(value).1f septillion" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septillion" +msgstr[1] "%(value)s septillion" +msgstr[2] "%(value)s septillion" +msgstr[3] "%(value)s septillion" +msgstr[4] "%(value)s septillion" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f octillion" +msgstr[1] "%(value).1f octillion" +msgstr[2] "%(value).1f octillion" +msgstr[3] "%(value).1f octillion" +msgstr[4] "%(value).1f octillion" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s octillion" +msgstr[1] "%(value)s octillion" +msgstr[2] "%(value)s octillion" +msgstr[3] "%(value)s octillion" +msgstr[4] "%(value)s octillion" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f nonillion" +msgstr[1] "%(value).1f nonillion" +msgstr[2] "%(value).1f nonillion" +msgstr[3] "%(value).1f nonillion" +msgstr[4] "%(value).1f nonillion" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s nonillion" +msgstr[1] "%(value)s nonillion" +msgstr[2] "%(value)s nonillion" +msgstr[3] "%(value)s nonillion" +msgstr[4] "%(value)s nonillion" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f decillion" +msgstr[1] "%(value).1f decillion" +msgstr[2] "%(value).1f decillion" +msgstr[3] "%(value).1f decillion" +msgstr[4] "%(value).1f decillion" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s decillion" +msgstr[1] "%(value)s decillion" +msgstr[2] "%(value)s decillion" +msgstr[3] "%(value)s decillion" +msgstr[4] "%(value)s decillion" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f googol" +msgstr[1] "%(value).1f googol" +msgstr[2] "%(value).1f googol" +msgstr[3] "%(value).1f googol" +msgstr[4] "%(value).1f googol" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" +msgstr[1] "%(value)s googol" +msgstr[2] "%(value)s googol" +msgstr[3] "%(value)s googol" +msgstr[4] "%(value)s googol" + +msgid "one" +msgstr "aon" + +msgid "two" +msgstr "dó" + +msgid "three" +msgstr "trí" + +msgid "four" +msgstr "ceathair" + +msgid "five" +msgstr "cúig" + +msgid "six" +msgstr "sé" + +msgid "seven" +msgstr "seacht" + +msgid "eight" +msgstr "ocht" + +msgid "nine" +msgstr "naoi" + +msgid "today" +msgstr "inniu" + +msgid "tomorrow" +msgstr "amárach" + +msgid "yesterday" +msgstr "inné" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +msgid "now" +msgstr "anois" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/gd/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/gd/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8c2fac1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/gd/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/gd/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/gd/LC_MESSAGES/django.po new file mode 100644 index 0000000..7101512 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/gd/LC_MESSAGES/django.po @@ -0,0 +1,389 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# GunChleoc, 2021 +# GunChleoc, 2015 +# GunChleoc, 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2021-12-24 18:40+0000\n" +"Last-Translator: GunChleoc\n" +"Language-Team: Gaelic, Scottish (http://www.transifex.com/django/django/" +"language/gd/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: gd\n" +"Plural-Forms: nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : " +"(n > 2 && n < 20) ? 2 : 3;\n" + +msgid "Humanize" +msgstr "Humanize" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}mh" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}mh" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}d" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}na" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}s" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}mh" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}mh" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}mh" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}mh" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}mh" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}mh" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s mhillean" +msgstr[1] "%(value)s mhillean" +msgstr[2] "%(value)s milleanan" +msgstr[3] "%(value)s millean" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s bhillean" +msgstr[1] "%(value)s bhillean" +msgstr[2] "%(value)s billeanan" +msgstr[3] "%(value)s billean" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s trillean" +msgstr[1] "%(value)s thrillean" +msgstr[2] "%(value)s trilleanan" +msgstr[3] "%(value)s trillean" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s quadrillean" +msgstr[1] "%(value)s quadrillean" +msgstr[2] "%(value)s quadrilleanan" +msgstr[3] "%(value)s quadrillean" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s quintillean" +msgstr[1] "%(value)s quintillean" +msgstr[2] "%(value)s quintilleanan" +msgstr[3] "%(value)s quintillean" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s sextillean" +msgstr[1] "%(value)s shextillean" +msgstr[2] "%(value)s sextilleanan" +msgstr[3] "%(value)s sextillean" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septillean" +msgstr[1] "%(value)s sheptillean" +msgstr[2] "%(value)s septilleanan" +msgstr[3] "%(value)s septillean" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s octillean" +msgstr[1] "%(value)s octillean" +msgstr[2] "%(value)s octilleanan" +msgstr[3] "%(value)s octillean" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s nonillean" +msgstr[1] "%(value)s nonillean" +msgstr[2] "%(value)s nonilleanan" +msgstr[3] "%(value)s nonillean" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s decillean" +msgstr[1] "%(value)s dhecillean" +msgstr[2] "%(value)s decilleanan" +msgstr[3] "%(value)s decillean" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s ghoogol" +msgstr[1] "%(value)s ghoogol" +msgstr[2] "%(value)s googolan" +msgstr[3] "%(value)s googol" + +msgid "one" +msgstr "aon" + +msgid "two" +msgstr "dà" + +msgid "three" +msgstr "trì" + +msgid "four" +msgstr "ceithir" + +msgid "five" +msgstr "còig" + +msgid "six" +msgstr "sia" + +msgid "seven" +msgstr "seachd" + +msgid "eight" +msgstr "ochd" + +msgid "nine" +msgstr "naoidh" + +msgid "today" +msgstr "an-diugh" + +msgid "tomorrow" +msgstr "a-màireach" + +msgid "yesterday" +msgstr "an-dè" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s air ais" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "%(count)s uair a thìde air ais" +msgstr[1] "%(count)s uair a thìde air ais" +msgstr[2] "%(count)s uairean a thìde air ais" +msgstr[3] "%(count)s uair a thìde air ais" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "%(count)s mhionaid air ais" +msgstr[1] "%(count)s mhionaid air ais" +msgstr[2] "%(count)s mionaidean air ais" +msgstr[3] "%(count)s mionaid air ais" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "%(count)s diog air ais" +msgstr[1] "%(count)s dhiog air ais" +msgstr[2] "%(count)s diogan air ais" +msgstr[3] "%(count)s diog air ais" + +msgid "now" +msgstr "an-dràsta" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "an ceann %(count)s diog" +msgstr[1] "an ceann %(count)s dhiog" +msgstr[2] "an ceann %(count)s diogan" +msgstr[3] "an ceann %(count)s diog" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "an ceann %(count)s mhionaid" +msgstr[1] "an ceann %(count)s mhionaid" +msgstr[2] "an ceann %(count)s mionaidean" +msgstr[3] "an ceann %(count)s mionaid" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "an ceann %(count)s uair a thìde" +msgstr[1] "an ceann %(count)s uair a thìde" +msgstr[2] "an ceann %(count)s uairean a thìde" +msgstr[3] "an ceann %(count)s uair a thìde" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "an ceann %(delta)s" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d bhliadhna" +msgstr[1] "%(num)d bhliadhna" +msgstr[2] "%(num)d bliadhnaichean" +msgstr[3] "%(num)d bliadhna" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mhìos" +msgstr[1] "%(num)d mhìos" +msgstr[2] "%(num)d mìosan" +msgstr[3] "%(num)d mìos" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d seachdain" +msgstr[1] "%(num)d sheachdain" +msgstr[2] "%(num)d seachdainean" +msgstr[3] "%(num)d seachdain" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d latha" +msgstr[1] "%(num)d latha" +msgstr[2] "%(num)d làithean" +msgstr[3] "%(num)d latha" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d uair a thìde" +msgstr[1] "%(num)d uair a thìde" +msgstr[2] "%(num)d uairean a thìde" +msgstr[3] "%(num)d uair a thìde" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d mhionaid" +msgstr[1] "%(num)d mhionaid" +msgstr[2] "%(num)d mionaidean" +msgstr[3] "%(num)d mionaid" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d bhliadhna" +msgstr[1] "%(num)d bhliadhna" +msgstr[2] "%(num)d bliadhnaichean" +msgstr[3] "%(num)d bliadhna" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mhìos" +msgstr[1] "%(num)d mhìos" +msgstr[2] "%(num)d mìosan" +msgstr[3] "%(num)d mìos" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d seachdain" +msgstr[1] "%(num)d sheachdain" +msgstr[2] "%(num)d seachdainean" +msgstr[3] "%(num)d seachdain" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d latha" +msgstr[1] "%(num)d latha" +msgstr[2] "%(num)d làithean" +msgstr[3] "%(num)d latha" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d uair a thìde" +msgstr[1] "%(num)d uair a thìde" +msgstr[2] "%(num)d uairean a thìde" +msgstr[3] "%(num)d uair a thìde" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d mhionaid" +msgstr[1] "%(num)d mhionaid" +msgstr[2] "%(num)d mionaidean" +msgstr[3] "%(num)d mionaid" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/gl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/gl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..30c0d5c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/gl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/gl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/gl/LC_MESSAGES/django.po new file mode 100644 index 0000000..b024007 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/gl/LC_MESSAGES/django.po @@ -0,0 +1,332 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# fasouto , 2011 +# fonso , 2013 +# Jannis Leidel , 2011 +# Leandro Regueiro , 2011,2013 +# X Bello , 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2023-04-24 18:40+0000\n" +"Last-Translator: X Bello , 2023\n" +"Language-Team: Galician (http://www.transifex.com/django/django/language/" +"gl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: gl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Humanización" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}º" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s millón" +msgstr[1] "%(value)s millóns" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s mil millóns" +msgstr[1] "%(value)s mil millóns" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s billón" +msgstr[1] "%(value)s billóns" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s trillón" +msgstr[1] "%(value)s trillóns" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s cuadrillón" +msgstr[1] "%(value)s cuadrillóns" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s quintillón" +msgstr[1] "%(value)s quintillóns" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s sextillón" +msgstr[1] "%(value)s sextillóns" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s septillón" +msgstr[1] "%(value)s septillóns" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s octillón" +msgstr[1] "%(value)s octillóns" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s nonillón" +msgstr[1] "%(value)s nonillóns" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s gúgol" +msgstr[1] "%(value)s gúgols" + +msgid "one" +msgstr "un" + +msgid "two" +msgstr "dous" + +msgid "three" +msgstr "tres" + +msgid "four" +msgstr "catro" + +msgid "five" +msgstr "cinco" + +msgid "six" +msgstr "seis" + +msgid "seven" +msgstr "sete" + +msgid "eight" +msgstr "oito" + +msgid "nine" +msgstr "nove" + +msgid "today" +msgstr "hoxe" + +msgid "tomorrow" +msgstr "mañá" + +msgid "yesterday" +msgstr "onte" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "fai %(delta)s" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "Fai unha hora" +msgstr[1] "Fai %(count)s horas" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "Fai un minuto" +msgstr[1] "Fai %(count)s minutos" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "Fai un segundo" +msgstr[1] "Fai %(count)s segundos" + +msgid "now" +msgstr "agora" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "Dentro dun segundo" +msgstr[1] "Dentro de %(count)s segundos" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "Dentro dun minuto" +msgstr[1] "Dentro de %(count)s minutos" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "Dentro dunha hora" +msgstr[1] "Dentro de %(count)s horas" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "dentro de %(delta)s" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d ano" +msgstr[1] "%(num)d anos" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mes" +msgstr[1] "%(num)d meses" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d semana" +msgstr[1] "%(num)d semanas" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d día" +msgstr[1] "%(num)d días" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hora" +msgstr[1] "%(num)d horas" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuto" +msgstr[1] "%(num)d minutos" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d ano" +msgstr[1] "%(num)d anos" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mes" +msgstr[1] "%(num)d meses" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d semana" +msgstr[1] "%(num)d semanas" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d día" +msgstr[1] "%(num)d días" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hora" +msgstr[1] "%(num)d horas" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuto" +msgstr[1] "%(num)d minutos" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/he/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/he/LC_MESSAGES/django.mo new file mode 100644 index 0000000..cbd4232 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/he/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/he/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/he/LC_MESSAGES/django.po new file mode 100644 index 0000000..3fb1327 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/he/LC_MESSAGES/django.po @@ -0,0 +1,389 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Alex Gaynor , 2011 +# Jannis Leidel , 2011 +# Meir Kriheli , 2012,2014,2019 +# Uri Rodberg , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2021-09-22 07:22+0000\n" +"Last-Translator: Uri Rodberg \n" +"Language-Team: Hebrew (http://www.transifex.com/django/django/language/he/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: he\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % " +"1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;\n" + +msgid "Humanize" +msgstr "האנשה" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "ה־{}" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "ה־{}" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "ה־{}" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "ה־{}" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "ה־{}" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "ה־{}" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "ה־{}" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "ה־{}" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "ה־{}" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "ה־{}" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "ה־{}" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "מיליון" +msgstr[1] "%(value)s מיליון" +msgstr[2] "%(value)s מיליון" +msgstr[3] "%(value)s מיליון" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "מיליארד" +msgstr[1] "%(value)s מיליארד" +msgstr[2] "%(value)s מיליארד" +msgstr[3] "%(value)s מיליארד" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "טריליון" +msgstr[1] "%(value)s טריליון" +msgstr[2] "%(value)s טריליון" +msgstr[3] "%(value)s טריליון" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "קוודריליון" +msgstr[1] "%(value)s קוודריליון" +msgstr[2] "%(value)s קוודריליון" +msgstr[3] "%(value)s קוודריליון" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "קווינטיליון" +msgstr[1] "%(value)s קווינטיליון" +msgstr[2] "%(value)s קווינטיליון" +msgstr[3] "%(value)s קווינטיליון" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "סקסטיליון" +msgstr[1] "%(value)s סקסטיליון" +msgstr[2] "%(value)s סקסטיליון" +msgstr[3] "%(value)s סקסטיליון" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "ספטיליון" +msgstr[1] "%(value)s ספטיליון" +msgstr[2] "%(value)s ספטיליון" +msgstr[3] "%(value)s ספטיליון" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "אוקטיליון" +msgstr[1] "%(value)s אוקטיליון" +msgstr[2] "%(value)s אוקטיליון" +msgstr[3] "%(value)s אוקטיליון" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "נוניליון" +msgstr[1] "%(value)s נוניליון" +msgstr[2] "%(value)s נוניליון" +msgstr[3] "%(value)s נוניליון" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "דציליון" +msgstr[1] "%(value)s דציליון" +msgstr[2] "%(value)s דציליון" +msgstr[3] "%(value)s דציליון" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "גוגול" +msgstr[1] "%(value)s גוגול" +msgstr[2] "%(value)s גוגול" +msgstr[3] "%(value)s גוגול" + +msgid "one" +msgstr "אחד" + +msgid "two" +msgstr "שניים" + +msgid "three" +msgstr "שלושה" + +msgid "four" +msgstr "ארבעה" + +msgid "five" +msgstr "חמישה" + +msgid "six" +msgstr "שישה" + +msgid "seven" +msgstr "שבעה" + +msgid "eight" +msgstr "שמונה" + +msgid "nine" +msgstr "תשעה" + +msgid "today" +msgstr "היום" + +msgid "tomorrow" +msgstr "מחר" + +msgid "yesterday" +msgstr "אתמול" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "לפני %(delta)s" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "לפני שעה" +msgstr[1] "לפני שעתיים" +msgstr[2] "לפני %(count)s שעות" +msgstr[3] "לפני %(count)s שעות" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "לפני דקה" +msgstr[1] "לפני %(count)s דקות" +msgstr[2] "לפני %(count)s דקות" +msgstr[3] "לפני %(count)s דקות" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "לפני שנייה" +msgstr[1] "לפני %(count)s שניות" +msgstr[2] "לפני %(count)s שניות" +msgstr[3] "לפני %(count)s שניות" + +msgid "now" +msgstr "עכשיו" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "בעוד שנייה" +msgstr[1] "בעוד %(count)s שניות" +msgstr[2] "בעוד %(count)s שניות" +msgstr[3] "בעוד %(count)s שניות" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "בעוד דקה" +msgstr[1] "בעוד %(count)s דקות" +msgstr[2] "בעוד %(count)s דקות" +msgstr[3] "בעוד %(count)s דקות" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "בעוד שעה" +msgstr[1] "בעוד שעתיים" +msgstr[2] "בעוד %(count)s שעות" +msgstr[3] "בעוד %(count)s שעות" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "בעוד %(delta)s" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "שנה" +msgstr[1] "שנתיים" +msgstr[2] "%(num)d שנים" +msgstr[3] "%(num)d שנים" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "חודש" +msgstr[1] "חודשיים" +msgstr[2] "%(num)d חודשים" +msgstr[3] "%(num)d חודשים" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "שבוע" +msgstr[1] "שבועיים" +msgstr[2] "%(num)d שבועות" +msgstr[3] "%(num)d שבועות" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "יום" +msgstr[1] "יומיים" +msgstr[2] "%(num)d ימים" +msgstr[3] "%(num)d ימים" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "שעה" +msgstr[1] "שעתיים" +msgstr[2] "%(num)d שעות" +msgstr[3] "%(num)d שעות" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "דקה" +msgstr[1] "%(num)d דקות" +msgstr[2] "%(num)d דקות" +msgstr[3] "%(num)d דקות" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "שנה" +msgstr[1] "שנתיים" +msgstr[2] "%(num)d שנים" +msgstr[3] "%(num)d שנים" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "חודש" +msgstr[1] "חודשיים" +msgstr[2] "%(num)d חודשים" +msgstr[3] "%(num)d חודשים" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "שבוע" +msgstr[1] "שבועיים" +msgstr[2] "%(num)d שבועות" +msgstr[3] "%(num)d שבועות" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "יום" +msgstr[1] "יומיים" +msgstr[2] "%(num)d ימים" +msgstr[3] "%(num)d ימים" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "שעה" +msgstr[1] "שעתיים" +msgstr[2] "%(num)d שעות" +msgstr[3] "%(num)d שעות" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "דקה" +msgstr[1] "%(num)d דקות" +msgstr[2] "%(num)d דקות" +msgstr[3] "%(num)d דקות" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3217de2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hi/LC_MESSAGES/django.po new file mode 100644 index 0000000..52551e6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hi/LC_MESSAGES/django.po @@ -0,0 +1,263 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Chandan kumar , 2012 +# Jannis Leidel , 2011 +# Sandeep Satavlekar , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Hindi (http://www.transifex.com/django/django/language/hi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "" + +msgid "th" +msgstr "वाँ" + +msgid "st" +msgstr "ला" + +msgid "nd" +msgstr "रा" + +msgid "rd" +msgstr "रा" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f मिलियन" +msgstr[1] "%(value).1f मिलियन" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s मिलियन" +msgstr[1] "%(value)s मिलियन" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f बिलियन" +msgstr[1] "%(value).1f बिलियन" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s बिलियन" +msgstr[1] "%(value)s बिलियन" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f खरब" +msgstr[1] "%(value).1f खरब" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s खरब" +msgstr[1] "%(value)s खरब" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f करोड़ शंख" +msgstr[1] "%(value).1f करोड़ शंख" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s करोड़ शंख" +msgstr[1] "%(value)s करोड़ शंख" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f कुइनतिलिअन " +msgstr[1] "%(value).1f कुइनतिलिअन " + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s कुइनतिलिअन " +msgstr[1] "%(value)s कुइनतिलिअन " + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f सेक्सतिलियन" +msgstr[1] "%(value).1f सेक्सतिलियन" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s सेक्सतिलियन" +msgstr[1] "%(value)s सेक्सतिलियन" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f सेपतिलियन " +msgstr[1] "%(value).1f सेपतिलियन " + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s सेपतिलियन " +msgstr[1] "%(value)s सेपतिलियन " + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f ओकतिलियन " +msgstr[1] "%(value).1f ओकतिलियन " + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s ओकतिलियन " +msgstr[1] "%(value)s ओकतिलियन " + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f नोनिलियन" +msgstr[1] "%(value).1f नोनिलियन" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s नोनिलियन" +msgstr[1] "%(value)s नोनिलियन" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f देसीलियन" +msgstr[1] "%(value).1f देसीलियन" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s देसीलियन" +msgstr[1] "%(value)s देसीलियन" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f गोगोल" +msgstr[1] "%(value).1f गोगोल" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s गोगोल" +msgstr[1] "%(value)s गोगोल" + +msgid "one" +msgstr "एक" + +msgid "two" +msgstr "दो" + +msgid "three" +msgstr "तीन" + +msgid "four" +msgstr "चार" + +msgid "five" +msgstr "पाँच" + +msgid "six" +msgstr "छह" + +msgid "seven" +msgstr "सात" + +msgid "eight" +msgstr "आठ" + +msgid "nine" +msgstr "नौ" + +msgid "today" +msgstr "आज" + +msgid "tomorrow" +msgstr "कल" + +msgid "yesterday" +msgstr "कल (बीता)" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "%(delta)s पहले" + +msgid "now" +msgstr "अभी" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "%(delta)s अब से" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..99793a8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hr/LC_MESSAGES/django.po new file mode 100644 index 0000000..635ea6d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hr/LC_MESSAGES/django.po @@ -0,0 +1,291 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Mislav Cimperšak , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 21:47+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Croatian (http://www.transifex.com/django/django/language/" +"hr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hr\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +msgid "Humanize" +msgstr "" + +msgid "th" +msgstr "" + +msgid "st" +msgstr "" + +msgid "nd" +msgstr "" + +msgid "rd" +msgstr "" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +msgid "one" +msgstr "jedan" + +msgid "two" +msgstr "dva" + +msgid "three" +msgstr "tri" + +msgid "four" +msgstr "četiri" + +msgid "five" +msgstr "pet" + +msgid "six" +msgstr "šest" + +msgid "seven" +msgstr "sedam" + +msgid "eight" +msgstr "osam" + +msgid "nine" +msgstr "devet" + +msgid "today" +msgstr "danas" + +msgid "tomorrow" +msgstr "sutra" + +msgid "yesterday" +msgstr "jučer" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "prije %(delta)s" + +msgid "now" +msgstr "sad" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "prije %(count)s sekunde" +msgstr[1] "prije %(count)s sekundi" +msgstr[2] "prije %(count)s sekundi" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "prije %(count)s minute" +msgstr[1] "prije %(count)s minute" +msgstr[2] "prije %(count)s minuta" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hsb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hsb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d9618ca Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hsb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hsb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hsb/LC_MESSAGES/django.po new file mode 100644 index 0000000..7446faa --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hsb/LC_MESSAGES/django.po @@ -0,0 +1,387 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Michael Wolf , 2016,2018,2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2021-09-28 18:41+0000\n" +"Last-Translator: Michael Wolf \n" +"Language-Team: Upper Sorbian (http://www.transifex.com/django/django/" +"language/hsb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hsb\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" + +msgid "Humanize" +msgstr "Humanize" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}." + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s milion" +msgstr[1] "%(value)s milionaj" +msgstr[2] "%(value)s miliony" +msgstr[3] "%(value)s milionow" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s miliarda" +msgstr[1] "%(value)s miliardźe" +msgstr[2] "%(value)s miliardy" +msgstr[3] "%(value)s miliardow" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s bilion" +msgstr[1] "%(value)s bilionaj" +msgstr[2] "%(value)s biliony" +msgstr[3] "%(value)s bilionow" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s biliarda" +msgstr[1] "%(value)s biliardźe" +msgstr[2] "%(value)s biliardy" +msgstr[3] "%(value)s biliardow" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s trilion" +msgstr[1] "%(value)s trilionaj" +msgstr[2] "%(value)s triliony" +msgstr[3] "%(value)s trilionow" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s triliarda" +msgstr[1] "%(value)s triliardźe" +msgstr[2] "%(value)s triliardy" +msgstr[3] "%(value)s triliardow" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s kwadrilion" +msgstr[1] "%(value)s kwadrilionaj" +msgstr[2] "%(value)s kwadriliony" +msgstr[3] "%(value)s kwadrilionow" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s kwadriliarda" +msgstr[1] "%(value)s kwadriliardźe" +msgstr[2] "%(value)s kwadriliardy" +msgstr[3] "%(value)s kwadriliardow" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s kwintilion" +msgstr[1] "%(value)s kwintilionaj" +msgstr[2] "%(value)s kwintiliony" +msgstr[3] "%(value)s kwintilionow" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s kwintiliarda" +msgstr[1] "%(value)s kwintiliardźe" +msgstr[2] "%(value)s kwintiliardy" +msgstr[3] "%(value)s kwintiliardow" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s sedeciliarda" +msgstr[1] "%(value)s sedeciliardźe" +msgstr[2] "%(value)s sedeciliardy" +msgstr[3] "%(value)s sedeciliardow" + +msgid "one" +msgstr "jedyn" + +msgid "two" +msgstr "dwaj" + +msgid "three" +msgstr "tři" + +msgid "four" +msgstr "štyri" + +msgid "five" +msgstr "pjeć" + +msgid "six" +msgstr "šěsć" + +msgid "seven" +msgstr "sydom" + +msgid "eight" +msgstr "wosom" + +msgid "nine" +msgstr "dźewjeć" + +msgid "today" +msgstr "dźensa" + +msgid "tomorrow" +msgstr "jutře" + +msgid "yesterday" +msgstr "wčera" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "Před %(delta)s" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "před %(count)s hodźinu" +msgstr[1] "před %(count)s hodźinomaj" +msgstr[2] "před %(count)s hodźinami" +msgstr[3] "před %(count)s hodźinami" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "před %(count)s mjeńšinu" +msgstr[1] "před %(count)s mjeńšinomaj" +msgstr[2] "před %(count)s mjeńšinami" +msgstr[3] "před %(count)s mjeńšinami" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "před %(count)s sekundu" +msgstr[1] "před %(count)s sekundomaj" +msgstr[2] "před %(count)s sekundami" +msgstr[3] "před %(count)s sekundami" + +msgid "now" +msgstr "nětko" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "za %(count)s sekundu" +msgstr[1] "za %(count)s sekundźe" +msgstr[2] "za %(count)s sekundy" +msgstr[3] "za %(count)s sekundow" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "za %(count)s mjeńšinu" +msgstr[1] "za %(count)s mjeńšinje" +msgstr[2] "za %(count)s mjeńšiny" +msgstr[3] "za %(count)s mjeńšin" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "za %(count)s hodźinu" +msgstr[1] "za %(count)s hodźinje" +msgstr[2] "za %(count)s hodźiny" +msgstr[3] "za %(count)s hodźin" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s wotnětka" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d lěto" +msgstr[1] "%(num)d lěće" +msgstr[2] "%(num)d lěta" +msgstr[3] "%(num)d lět" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d měsac" +msgstr[1] "%(num)d měsacaj" +msgstr[2] "%(num)d měsacy" +msgstr[3] "%(num)d měsacow" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d tydźeń" +msgstr[1] "%(num)d njedźeli" +msgstr[2] "%(num)d njedźele" +msgstr[3] "%(num)d njedźel" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dźeń" +msgstr[1] "%(num)d dnjej" +msgstr[2] "%(num)d dny" +msgstr[3] "%(num)d dnjow" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hodźina" +msgstr[1] "%(num)d hodźinje" +msgstr[2] "%(num)d hodźiny" +msgstr[3] "%(num)d hodźin" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d mjeńšina" +msgstr[1] "%(num)d mjeńšinje" +msgstr[2] "%(num)d mjeńšiny" +msgstr[3] "%(num)d mjeńšin" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d lěto" +msgstr[1] "%(num)d lěće" +msgstr[2] "%(num)d lěta" +msgstr[3] "%(num)d lět" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d měsac" +msgstr[1] "%(num)d měsacaj" +msgstr[2] "%(num)d měsacy" +msgstr[3] "%(num)d měsacow" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d tydźeń" +msgstr[1] "%(num)d njedźeli" +msgstr[2] "%(num)d njedźele" +msgstr[3] "%(num)d njedźel" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dźeń" +msgstr[1] "%(num)d dnjej" +msgstr[2] "%(num)d dny" +msgstr[3] "%(num)d dnjow" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hodźina" +msgstr[1] "%(num)d hodźinje" +msgstr[2] "%(num)d hodźiny" +msgstr[3] "%(num)d hodźin" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d mjeńšina" +msgstr[1] "%(num)d mjeńšinje" +msgstr[2] "%(num)d mjeńšiny" +msgstr[3] "%(num)d mjeńšin" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hu/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hu/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e2052fb Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hu/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hu/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hu/LC_MESSAGES/django.po new file mode 100644 index 0000000..01c7ff4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hu/LC_MESSAGES/django.po @@ -0,0 +1,332 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# András Veres-Szentkirályi, 2016,2018 +# Attila Nagy <>, 2012 +# Balázs R, 2023 +# Jannis Leidel , 2011 +# János R, 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:40+0000\n" +"Last-Translator: Balázs R, 2023\n" +"Language-Team: Hungarian (http://app.transifex.com/django/django/language/" +"hu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Emberi formázás" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 3, e.g. 83rd, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}." + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s millió" +msgstr[1] "%(value)s millió" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] " %(value)s milliárd" +msgstr[1] " %(value)s milliárd" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s billió" +msgstr[1] "%(value)s billió" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s billiárd" +msgstr[1] "%(value)s billiárd" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s trillió" +msgstr[1] "%(value)s trillió" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s trilliárd" +msgstr[1] "%(value)s trilliárd" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s kvadrillió" +msgstr[1] "%(value)s kvadrillió" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s kvadrilliárd" +msgstr[1] "%(value)s kvadrilliárd" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s kvintillió" +msgstr[1] "%(value)s kvintillió" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s kvintilliárd" +msgstr[1] "%(value)s kvintilliárd" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" +msgstr[1] "%(value)s googol" + +msgid "one" +msgstr "egy" + +msgid "two" +msgstr "kettő" + +msgid "three" +msgstr "három" + +msgid "four" +msgstr "négy" + +msgid "five" +msgstr "öt" + +msgid "six" +msgstr "hat" + +msgid "seven" +msgstr "hét" + +msgid "eight" +msgstr "nyolc" + +msgid "nine" +msgstr "kilenc" + +msgid "today" +msgstr "ma" + +msgid "tomorrow" +msgstr "holnap" + +msgid "yesterday" +msgstr "tegnap" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr " %(delta)s ezelőtt" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "egy órája" +msgstr[1] "%(count)s órája" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "egy perce" +msgstr[1] "%(count)s perce" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "egy másodperce" +msgstr[1] "%(count)s másodperce" + +msgid "now" +msgstr "most" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "egy másodperc múlva" +msgstr[1] "%(count)s másodperc múlva" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "egy perc múlva" +msgstr[1] "%(count)s perc múlva" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "egy óra múlva" +msgstr[1] "%(count)s óra múlva" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s múlva" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d évvel" +msgstr[1] "%(num)d évvel" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d hónappal" +msgstr[1] "%(num)d hónappal" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d héttel" +msgstr[1] "%(num)d héttel" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d nappal" +msgstr[1] "%(num)d nappal" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d órával" +msgstr[1] "%(num)d órával" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d perccel" +msgstr[1] "%(num)d perccel" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d év" +msgstr[1] "%(num)d év" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d hónap" +msgstr[1] "%(num)d hónap" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d hét" +msgstr[1] "%(num)d hét" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d nap" +msgstr[1] "%(num)d nap" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d óra" +msgstr[1] "%(num)d óra" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d perc" +msgstr[1] "%(num)d perc" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b41d6f8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hy/LC_MESSAGES/django.po new file mode 100644 index 0000000..ebd773e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/hy/LC_MESSAGES/django.po @@ -0,0 +1,395 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Artur Saroyan <>, 2012 +# Ruben Harutyunov , 2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2018-11-11 20:06+0000\n" +"Last-Translator: Ruben Harutyunov \n" +"Language-Team: Armenian (http://www.transifex.com/django/django/language/" +"hy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hy\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}րդ" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}րդ" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}ին" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}րդ" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}րդ" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}րդ" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}րդ" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}րդ" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}րդ" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}րդ" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}րդ" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1fմիլիոն" +msgstr[1] "%(value).1fմիլիոն" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "" +msgstr[1] "" + +msgid "one" +msgstr "մեկ" + +msgid "two" +msgstr "երկու" + +msgid "three" +msgstr "երեք" + +msgid "four" +msgstr "չորս" + +msgid "five" +msgstr "հինգ" + +msgid "six" +msgstr "վեց" + +msgid "seven" +msgstr "յոթ" + +msgid "eight" +msgstr "ութ" + +msgid "nine" +msgstr "ինը" + +msgid "today" +msgstr "այսօր" + +msgid "tomorrow" +msgstr "վաղը" + +msgid "yesterday" +msgstr "երեկ" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" +msgstr[1] "" + +msgid "now" +msgstr "հիմա" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ia/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ia/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9e1f250 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ia/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ia/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ia/LC_MESSAGES/django.po new file mode 100644 index 0000000..cc7aec5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ia/LC_MESSAGES/django.po @@ -0,0 +1,262 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Martijn Dekker , 2012,2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Martijn Dekker \n" +"Language-Team: Interlingua (http://www.transifex.com/django/django/language/" +"ia/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ia\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Humanisar" + +msgid "th" +msgstr "e" + +msgid "st" +msgstr "me" + +msgid "nd" +msgstr "nde" + +msgid "rd" +msgstr "tie" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f million" +msgstr[1] "%(value).1f milliones" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s million" +msgstr[1] "%(value)s milliones" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f milliardo" +msgstr[1] "%(value).1f milliardos" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s milliardo" +msgstr[1] "%(value)s milliardos" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f billion" +msgstr[1] "%(value).1f billiones" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s billion" +msgstr[1] "%(value)s billiones" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f billiardo" +msgstr[1] "%(value).1f billiardos" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s billiardo" +msgstr[1] "%(value)s billiardos" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f trillion" +msgstr[1] "%(value).1f trilliones" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s trillion" +msgstr[1] "%(value)s trilliones" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f trilliardo" +msgstr[1] "%(value).1f trilliardos" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s trilliardo" +msgstr[1] "%(value)s trilliardos" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f quadrillion" +msgstr[1] "%(value).1f quadrilliones" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s quadrillion" +msgstr[1] "%(value)s quadrilliones" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f quadrilliardo" +msgstr[1] "%(value).1f quadrilliardos" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s quadrilliardo" +msgstr[1] "%(value)s quadrilliardos" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f quintillion" +msgstr[1] "%(value).1f quintilliones" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s quintillion" +msgstr[1] "%(value)s quintilliones" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f quintilliardo" +msgstr[1] "%(value).1f quintilliardos" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s quintilliardo" +msgstr[1] "%(value)s quintilliardos" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f googol" +msgstr[1] "%(value).1f googoles" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" +msgstr[1] "%(value)s googoles" + +msgid "one" +msgstr "un" + +msgid "two" +msgstr "duo" + +msgid "three" +msgstr "tres" + +msgid "four" +msgstr "quatro" + +msgid "five" +msgstr "cinque" + +msgid "six" +msgstr "sex" + +msgid "seven" +msgstr "septe" + +msgid "eight" +msgstr "octo" + +msgid "nine" +msgstr "novem" + +msgid "today" +msgstr "hodie" + +msgid "tomorrow" +msgstr "deman" + +msgid "yesterday" +msgstr "heri" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "%(delta)s retro" + +msgid "now" +msgstr "ora" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "un secunda retro" +msgstr[1] "%(count)s secundas retro" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "un minuta retro" +msgstr[1] "%(count)s minutas retro" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "un hora retro" +msgstr[1] "%(count)s horas retro" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "in %(delta)s" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "un secunda desde ora" +msgstr[1] "%(count)s secundas desde ora" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "un minuta desde ora" +msgstr[1] "%(count)s minutas desde ora" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "un hora desde ora" +msgstr[1] "%(count)s horas desde ora" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/id/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/id/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c464dc7 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/id/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/id/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/id/LC_MESSAGES/django.po new file mode 100644 index 0000000..8acb99d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/id/LC_MESSAGES/django.po @@ -0,0 +1,304 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Fery Setiawan , 2016,2018,2021 +# Jannis Leidel , 2011 +# rodin , 2011-2012 +# rodin , 2014 +# sag᠎e , 2019 +# Sutrisno Efendi , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2021-10-06 09:17+0000\n" +"Last-Translator: Fery Setiawan \n" +"Language-Team: Indonesian (http://www.transifex.com/django/django/language/" +"id/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: id\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Humanize" +msgstr "Memanusiawikan" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "ke-{}" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "ke-{}" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "ke-{}" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "ke-{}" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "ke-{}" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "ke-{}" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "ke-{}" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "ke-{}" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "ke-{}" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "ke-{}" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "ke-{}" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s juta" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s miliar" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s triliun" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s kuadriliun" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s kuintiliun" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s sekstiliun" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septiliun" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s oktiliun" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s noniliun" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s desiliun" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" + +msgid "one" +msgstr "satu" + +msgid "two" +msgstr "dua" + +msgid "three" +msgstr "tiga" + +msgid "four" +msgstr "empat" + +msgid "five" +msgstr "lima" + +msgid "six" +msgstr "enam" + +msgid "seven" +msgstr "tujuh" + +msgid "eight" +msgstr "delapan" + +msgid "nine" +msgstr "sembilan" + +msgid "today" +msgstr "hari ini" + +msgid "tomorrow" +msgstr "besok" + +msgid "yesterday" +msgstr "kemarin" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s yang lalu" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "%(count)s jam yang lalu" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "%(count)s menit yang lalu" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "%(count)s detik yang lalu" + +msgid "now" +msgstr "sekarang" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "%(count)s detik dari sekarang" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "%(count)s menit dari sekarang" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "%(count)s jam dari sekarang" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s dari sekarang" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d tahun" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d bulan" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d minggu" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d hari" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d jam" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d menit" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d tahun" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d bulan" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d minggu" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d hari" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d jam" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d menit" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/io/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/io/LC_MESSAGES/django.mo new file mode 100644 index 0000000..fba64da Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/io/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/io/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/io/LC_MESSAGES/django.po new file mode 100644 index 0000000..046e775 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/io/LC_MESSAGES/django.po @@ -0,0 +1,261 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:11+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Ido (http://www.transifex.com/projects/p/django/language/" +"io/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: io\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "" + +msgid "th" +msgstr "" + +msgid "st" +msgstr "" + +msgid "nd" +msgstr "" + +msgid "rd" +msgstr "" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "" +msgstr[1] "" + +msgid "one" +msgstr "" + +msgid "two" +msgstr "" + +msgid "three" +msgstr "" + +msgid "four" +msgstr "" + +msgid "five" +msgstr "" + +msgid "six" +msgstr "" + +msgid "seven" +msgstr "" + +msgid "eight" +msgstr "" + +msgid "nine" +msgstr "" + +msgid "today" +msgstr "" + +msgid "tomorrow" +msgstr "" + +msgid "yesterday" +msgstr "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "" + +msgid "now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/is/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/is/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b22c4ad Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/is/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/is/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/is/LC_MESSAGES/django.po new file mode 100644 index 0000000..d9b14c0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/is/LC_MESSAGES/django.po @@ -0,0 +1,399 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# gudmundur , 2012 +# Hafsteinn Einarsson , 2012 +# Jannis Leidel , 2011 +# Matt R, 2018 +# Thordur Sigurdsson , 2016,2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-05-17 11:49+0200\n" +"PO-Revision-Date: 2018-05-18 03:49+0000\n" +"Last-Translator: Thordur Sigurdsson \n" +"Language-Team: Icelandic (http://www.transifex.com/django/django/language/" +"is/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: is\n" +"Plural-Forms: nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);\n" + +msgid "Humanize" +msgstr "" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}." + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f milljón" +msgstr[1] "%(value).1f milljónir" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s milljón" +msgstr[1] "%(value)s milljónir" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f milljarður" +msgstr[1] "%(value).1f milljarðar" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s milljarður" +msgstr[1] "%(value)s milljarðar" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f billjarður" +msgstr[1] "%(value).1f billjónir" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s billjón" +msgstr[1] "%(value)s billjónir" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f billjarður" +msgstr[1] "%(value).1f billjarðar" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s billjarður" +msgstr[1] "%(value)s billjarðar" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f trilljón" +msgstr[1] "%(value).1f trilljónir" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s trilljón" +msgstr[1] "%(value)s trilljónir" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f trilljarður" +msgstr[1] "%(value).1f trilljarðar" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s trilljarður" +msgstr[1] "%(value)s trilljarðar" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f kvaðrilljón" +msgstr[1] "%(value).1f kvaðrilljónir" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s kvaðrilljón" +msgstr[1] "%(value)s kvaðrilljónir" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f kvaðrilljarður" +msgstr[1] "%(value).1f kvaðrilljarðar" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s kvaðrilljarður" +msgstr[1] "%(value)s kvaðrilljarðar" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f kvintilljón" +msgstr[1] "%(value).1f kvintilljónir" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s kvintilljón" +msgstr[1] "%(value)s kvintilljónir" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f kvintilljarður" +msgstr[1] "%(value).1f kvintilljarðar" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s kvintilljarður" +msgstr[1] "%(value)s kvintilljarðar" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f googol" +msgstr[1] "%(value).1f googol" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" +msgstr[1] "%(value)s googol" + +msgid "one" +msgstr "einn" + +msgid "two" +msgstr "tveir" + +msgid "three" +msgstr "þrír" + +msgid "four" +msgstr "fjórir" + +msgid "five" +msgstr "fimm" + +msgid "six" +msgstr "sex" + +msgid "seven" +msgstr "sjö" + +msgid "eight" +msgstr "átta" + +msgid "nine" +msgstr "níu" + +msgid "today" +msgstr "í dag" + +msgid "tomorrow" +msgstr "á morgun" + +msgid "yesterday" +msgstr "í gær" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "" + +#. Translators: 'naturaltime-past' strings will be included in +#. '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" + +msgid "now" +msgstr "núna" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "" + +#. Translators: 'naturaltime-future' strings will be included in +#. '%(delta)s from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/it/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/it/LC_MESSAGES/django.mo new file mode 100644 index 0000000..efebe27 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/it/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/it/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/it/LC_MESSAGES/django.po new file mode 100644 index 0000000..4e1c222 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/it/LC_MESSAGES/django.po @@ -0,0 +1,368 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Carlo Miron , 2014 +# Carlo Miron , 2018 +# Davide Targa , 2021 +# Federico Capoano , 2011 +# Jannis Leidel , 2011 +# Luca Manlio De Lisi , 2011 +# Marco Bonetti, 2014 +# Mirco Grillo , 2018 +# Nicola Larosa , 2011 +# palmux , 2015 +# Paolo Melchiorre , 2023 +# Stefano Brentegani , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2023-04-24 18:40+0000\n" +"Last-Translator: Paolo Melchiorre , 2023\n" +"Language-Team: Italian (http://www.transifex.com/django/django/language/" +"it/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: it\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Umanizzazione " + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}esimo" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}esimo" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}esimo" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}esimo" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}esimo" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}esimo" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}esimo" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}esimo" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}esimo" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}esimo" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}esimo" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s milione" +msgstr[1] "%(value)s milioni" +msgstr[2] "%(value)s milioni" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s miliardo" +msgstr[1] "%(value)s miliardi" +msgstr[2] "%(value)s miliardi" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s migliaio di miliardi" +msgstr[1] "%(value)s migliaia di miliardi" +msgstr[2] "%(value)s migliaia di miliardi" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s milione di miliardi" +msgstr[1] "%(value)s milioni di miliardi" +msgstr[2] "%(value)s milioni di miliardi" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s miliardo di miliardi" +msgstr[1] "%(value)s miliardi di miliardi" +msgstr[2] "%(value)s miliardi di miliardi" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s migliaio di miliardi di miliardi" +msgstr[1] "%(value)s migliaia di miliardi di miliardi" +msgstr[2] "%(value)s migliaia di miliardi di miliardi" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s milione di miliardi di miliardi" +msgstr[1] "%(value)s milioni di miliardi di miliardi" +msgstr[2] "%(value)s milioni di miliardi di miliardi" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s miliardo di miliardi di miliardi" +msgstr[1] "%(value)s miliardi di miliardi di miliardi" +msgstr[2] "%(value)s miliardi di miliardi di miliardi" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s migliaio di miliardi di miliardi di miliardi" +msgstr[1] "%(value)s migliaia di miliardi di miliardi di miliardi" +msgstr[2] "%(value)s migliaia di miliardi di miliardi di miliardi" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s milione di miliardi di miliardi di miliardi" +msgstr[1] "%(value)s milioni di miliardi di miliardi di miliardi" +msgstr[2] "%(value)s milioni di miliardi di miliardi di miliardi" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" +msgstr[1] "%(value)s googol" +msgstr[2] "%(value)s googol" + +msgid "one" +msgstr "uno" + +msgid "two" +msgstr "due" + +msgid "three" +msgstr "tre" + +msgid "four" +msgstr "quattro" + +msgid "five" +msgstr "cinque" + +msgid "six" +msgstr "sei" + +msgid "seven" +msgstr "sette" + +msgid "eight" +msgstr "otto" + +msgid "nine" +msgstr "nove" + +msgid "today" +msgstr "oggi" + +msgid "tomorrow" +msgstr "domani" + +msgid "yesterday" +msgstr "ieri" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s fa" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "un ora fa" +msgstr[1] "%(count)s ore fa" +msgstr[2] "%(count)s ore fa" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "un minuto fa" +msgstr[1] "%(count)s minuti fa" +msgstr[2] "%(count)s minuti fa" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "un secondo fa" +msgstr[1] "%(count)s secondi fa" +msgstr[2] "%(count)s secondi fa" + +msgid "now" +msgstr "adesso" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "tra un secondo" +msgstr[1] "tra %(count)s secondi" +msgstr[2] "tra %(count)s secondi" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "tra un minuto" +msgstr[1] "tra %(count)s minuti" +msgstr[2] "tra %(count)s minuti" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "tra un'ora" +msgstr[1] "tra %(count)s ore" +msgstr[2] "tra %(count)s ore" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s da adesso" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d anno" +msgstr[1] "%(num)d anni" +msgstr[2] "%(num)d anni" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mese" +msgstr[1] "%(num)d mesi" +msgstr[2] "%(num)d mesi" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d settimana" +msgstr[1] "%(num)d settimane" +msgstr[2] "%(num)d settimane" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d giorno" +msgstr[1] "%(num)d giorni" +msgstr[2] "%(num)d giorni" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d ora" +msgstr[1] "%(num)d ore" +msgstr[2] "%(num)d ore" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuto" +msgstr[1] "%(num)d minuti" +msgstr[2] "%(num)d minuti" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d anno" +msgstr[1] "%(num)d anni" +msgstr[2] "%(num)d anni" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mese" +msgstr[1] "%(num)d mesi" +msgstr[2] "%(num)d mesi" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d settimana" +msgstr[1] "%(num)d settimane" +msgstr[2] "%(num)d settimane" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d giorno" +msgstr[1] "%(num)d giorni" +msgstr[2] "%(num)d giorni" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d ora" +msgstr[1] "%(num)d ore" +msgstr[2] "%(num)d ore" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuto" +msgstr[1] "%(num)d minuti" +msgstr[2] "%(num)d minuti" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ja/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ja/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0e043b9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ja/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ja/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ja/LC_MESSAGES/django.po new file mode 100644 index 0000000..f077d0a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ja/LC_MESSAGES/django.po @@ -0,0 +1,301 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Jonas Obrist , 2012 +# Shinya Okano , 2012-2014,2018,2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2021-10-13 11:44+0000\n" +"Last-Translator: Shinya Okano \n" +"Language-Team: Japanese (http://www.transifex.com/django/django/language/" +"ja/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ja\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Humanize" +msgstr "ヒューマナイズ" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}番目" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}番目" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}番目" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}番目" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}番目" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}番目" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}番目" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}番目" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}番目" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}番目" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}番目" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s ミリオン" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s ビリオン" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s トリリオン" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] " %(value)s クァドリリオン" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s クインテリオン" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s セクスティリオン" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s セプティリオン" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s オクティリオン" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s ノニリオン" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s デシリオン" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s グーゴル" + +msgid "one" +msgstr "1" + +msgid "two" +msgstr "2" + +msgid "three" +msgstr "3" + +msgid "four" +msgstr "4" + +msgid "five" +msgstr "5" + +msgid "six" +msgstr "6" + +msgid "seven" +msgstr "7" + +msgid "eight" +msgstr "8" + +msgid "nine" +msgstr "9" + +msgid "today" +msgstr "今日" + +msgid "tomorrow" +msgstr "明日" + +msgid "yesterday" +msgstr "昨日" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s前" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "%(count)s時間前" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "%(count)s分前" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "%(count)s秒前" + +msgid "now" +msgstr "今" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "今から%(count)s秒" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "今から%(count)s分" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "今から%(count)s時間" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "今から%(delta)s" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d年" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)dヶ月" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d週間" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d日" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d時間" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d分" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d年" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)dヶ月" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d週間" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d日" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d時間" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d分" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ka/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ka/LC_MESSAGES/django.mo new file mode 100644 index 0000000..61fb3e0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ka/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ka/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ka/LC_MESSAGES/django.po new file mode 100644 index 0000000..e9cbf25 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ka/LC_MESSAGES/django.po @@ -0,0 +1,395 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# André Bouatchidzé , 2013-2015 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2018-05-18 01:38+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Georgian (http://www.transifex.com/django/django/language/" +"ka/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ka\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +msgid "Humanize" +msgstr "ჰუმანიზირება" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f მილიონი" +msgstr[1] "%(value).1f მილიონი" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s მილიონი" +msgstr[1] "%(value)s მილიონი" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f მილიარდი" +msgstr[1] "%(value).1f მილიარდი" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s მილიარდი" +msgstr[1] "%(value)s მილიარდი" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f ტრილიონი" +msgstr[1] "%(value).1f ტრილიონი" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s ტრილიონი" +msgstr[1] "%(value)s ტრილიონი" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f კვადრილიონი" +msgstr[1] "%(value).1f კვადრილიონი" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s კვადრილიონი" +msgstr[1] "%(value)s კვადრილიონი" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f კვინტილიონი" +msgstr[1] "%(value).1f კვინტილიონი" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s კვინტილიონი" +msgstr[1] "%(value)s კვინტილიონი" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f სექსტილიონი" +msgstr[1] "%(value).1f სექსტილიონი" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s სექსტილიონი" +msgstr[1] "%(value)s სექსტილიონი" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f სეპტილიონი" +msgstr[1] "%(value).1f სეპტილიონი" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s სეპტილიონი" +msgstr[1] "%(value)s სეპტილიონი" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f ოქტილიონი" +msgstr[1] "%(value).1f ოქტილიონი" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s ოქტილიონი" +msgstr[1] "%(value)s ოქტილიონი" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f ნონილიონი" +msgstr[1] "%(value).1f ნონილიონი" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s ნონილიონი" +msgstr[1] "%(value)s ნონილიონი" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f დეცილიონი" +msgstr[1] "%(value).1f დეცილიონი" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s დეცილიონი" +msgstr[1] "%(value)s დეცილიონი" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f გუგოლი" +msgstr[1] "%(value).1f გუგოლი" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s გუგოლი" +msgstr[1] "%(value)s გუგოლი" + +msgid "one" +msgstr "ერთი" + +msgid "two" +msgstr "ორი" + +msgid "three" +msgstr "სამი" + +msgid "four" +msgstr "ოთხი" + +msgid "five" +msgstr "ხუთი" + +msgid "six" +msgstr "ექვსი" + +msgid "seven" +msgstr "შვიდი" + +msgid "eight" +msgstr "რვა" + +msgid "nine" +msgstr "ცხრა" + +msgid "today" +msgstr "დღეს" + +msgid "tomorrow" +msgstr "ხვალ" + +msgid "yesterday" +msgstr "გუშინ" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "%(count)s საათის წინ" +msgstr[1] "%(count)s საათის წინ" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "%(count)s წუთის წინ" +msgstr[1] "%(count)s წუთის წინ" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "%(count)s წამის წინ" +msgstr[1] "%(count)s წამის წინ" + +msgid "now" +msgstr "ახლა" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "%(count)s წამში" +msgstr[1] "%(count)s წამში" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "%(count)s წუთში" +msgstr[1] "%(count)s წუთში" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "%(count)s საათში" +msgstr[1] "%(count)s საათში" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/kk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/kk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4e22806 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/kk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/kk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/kk/LC_MESSAGES/django.po new file mode 100644 index 0000000..75a6a38 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/kk/LC_MESSAGES/django.po @@ -0,0 +1,394 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Leo Trubach , 2017 +# yun_man_ger , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2018-05-18 01:38+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Kazakh (http://www.transifex.com/django/django/language/kk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kk\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +msgid "Humanize" +msgstr "" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f миллион" +msgstr[1] "%(value).1f миллион" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s миллион" +msgstr[1] "%(value)s миллион" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f миллиард" +msgstr[1] "%(value).1f миллиард" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s миллиард" +msgstr[1] "%(value)s миллиард" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f триллион" +msgstr[1] "%(value).1f триллион" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s trillion" +msgstr[1] "%(value)s trillion" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f квадриллион" +msgstr[1] "%(value).1f квадриллион" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s квадриллион" +msgstr[1] "%(value)s квадриллион" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f квинтиллион" +msgstr[1] "%(value).1f квинтиллион" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s квинтиллион" +msgstr[1] "%(value)s квинтиллион" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "" +msgstr[1] "" + +msgid "one" +msgstr "бір" + +msgid "two" +msgstr "екі" + +msgid "three" +msgstr "үш" + +msgid "four" +msgstr "төрт" + +msgid "five" +msgstr "бес" + +msgid "six" +msgstr "алты" + +msgid "seven" +msgstr "жеті" + +msgid "eight" +msgstr "сегіз" + +msgid "nine" +msgstr "тоғыз" + +msgid "today" +msgstr "бүгін" + +msgid "tomorrow" +msgstr "ерте" + +msgid "yesterday" +msgstr "кеше" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" +msgstr[1] "" + +msgid "now" +msgstr "кәзір" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/km/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/km/LC_MESSAGES/django.mo new file mode 100644 index 0000000..482b022 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/km/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/km/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/km/LC_MESSAGES/django.po new file mode 100644 index 0000000..0aab550 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/km/LC_MESSAGES/django.po @@ -0,0 +1,233 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:11+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Khmer (http://www.transifex.com/projects/p/django/language/" +"km/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: km\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Humanize" +msgstr "" + +msgid "th" +msgstr "" + +msgid "st" +msgstr "" + +msgid "nd" +msgstr "" + +msgid "rd" +msgstr "" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "" + +msgid "one" +msgstr "" + +msgid "two" +msgstr "" + +msgid "three" +msgstr "" + +msgid "four" +msgstr "" + +msgid "five" +msgstr "" + +msgid "six" +msgstr "" + +msgid "seven" +msgstr "" + +msgid "eight" +msgstr "" + +msgid "nine" +msgstr "" + +msgid "today" +msgstr "" + +msgid "tomorrow" +msgstr "" + +msgid "yesterday" +msgstr "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "" + +msgid "now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/kn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/kn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b75cf46 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/kn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/kn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/kn/LC_MESSAGES/django.po new file mode 100644 index 0000000..9e7eeb9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/kn/LC_MESSAGES/django.po @@ -0,0 +1,233 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:11+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Kannada (http://www.transifex.com/projects/p/django/language/" +"kn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kn\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Humanize" +msgstr "" + +msgid "th" +msgstr "" + +msgid "st" +msgstr "" + +msgid "nd" +msgstr "" + +msgid "rd" +msgstr "" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "" + +msgid "one" +msgstr "" + +msgid "two" +msgstr "" + +msgid "three" +msgstr "" + +msgid "four" +msgstr "" + +msgid "five" +msgstr "" + +msgid "six" +msgstr "" + +msgid "seven" +msgstr "" + +msgid "eight" +msgstr "" + +msgid "nine" +msgstr "" + +msgid "today" +msgstr "" + +msgid "tomorrow" +msgstr "" + +msgid "yesterday" +msgstr "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "" + +msgid "now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ko/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ko/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1c311bb Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ko/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ko/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ko/LC_MESSAGES/django.po new file mode 100644 index 0000000..82cda2d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ko/LC_MESSAGES/django.po @@ -0,0 +1,304 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ian Y. Choi , 2015 +# Jannis Leidel , 2011 +# Le Tartuffe , 2014 +# JunGu Kang , 2015 +# Seho Noh , 2018 +# 정훈 이, 2021 +# Jrog , 2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2021-12-24 18:40+0000\n" +"Last-Translator: 정훈 이\n" +"Language-Team: Korean (http://www.transifex.com/django/django/language/ko/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ko\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Humanize" +msgstr "인간화" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}번째" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}번째" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}번째" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}번째" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}번째" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}번째" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}번째" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}번째" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}번째" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}번째" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}번째" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s 백만" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s 십억" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s 조" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s 천조" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s 백경" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s 섹틸리언-10의21제곱" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s 셉틸리언-10의 24제곱" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s 옥틸리언-10의 27제곱" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s 노닐리언-10의30제곱" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s 디실리언-10의 33제곱" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s 구골-10의 100제곱" + +msgid "one" +msgstr "1" + +msgid "two" +msgstr "2" + +msgid "three" +msgstr "3" + +msgid "four" +msgstr "4" + +msgid "five" +msgstr "5" + +msgid "six" +msgstr "6" + +msgid "seven" +msgstr "7" + +msgid "eight" +msgstr "8" + +msgid "nine" +msgstr "9" + +msgid "today" +msgstr "오늘" + +msgid "tomorrow" +msgstr "내일" + +msgid "yesterday" +msgstr "어제" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s 전" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "%(count)s 시간 전" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "%(count)s 분 전" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "%(count)s 초 전" + +msgid "now" +msgstr "지금" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "지금부터 %(count)s 초" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "지금부터 %(count)s 분" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "지금부터 %(count)s 시간" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "지금부터 %(delta)s" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d년" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d개월" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d주" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d일" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d시간" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d분" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d년" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d개월" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d주" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d일" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d시간" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d분" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ky/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ky/LC_MESSAGES/django.mo new file mode 100644 index 0000000..669a321 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ky/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ky/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ky/LC_MESSAGES/django.po new file mode 100644 index 0000000..1308815 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ky/LC_MESSAGES/django.po @@ -0,0 +1,299 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Soyuzbek Orozbek uulu , 2021 +# Soyuzbek Orozbek uulu , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2021-11-27 14:11+0000\n" +"Last-Translator: Soyuzbek Orozbek uulu \n" +"Language-Team: Kyrgyz (http://www.transifex.com/django/django/language/ky/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ky\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Humanize" +msgstr "Инсандаштыруу" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}нчы" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}үнчү" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}инчи" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}инчи" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}үнчү" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}үнчү" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}инчи" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}нчы" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}инчи" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}инчи" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}унчу" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)sмиллион" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)sмиллиард" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)sтриллион" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)sквадриллион" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)sквинтиллион" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)sсекстиллион" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)sсептиллион" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)sоктиллион" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)sнонтиллион" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)sдесилион" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)sгугл" + +msgid "one" +msgstr "бир" + +msgid "two" +msgstr "эки" + +msgid "three" +msgstr "үч" + +msgid "four" +msgstr "төрт" + +msgid "five" +msgstr "беш" + +msgid "six" +msgstr "алты" + +msgid "seven" +msgstr "жети" + +msgid "eight" +msgstr "сегиз" + +msgid "nine" +msgstr "тогуз" + +msgid "today" +msgstr "бүгүн" + +msgid "tomorrow" +msgstr "эртең" + +msgid "yesterday" +msgstr "кечээ" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s мурда" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "%(count)sсаат мурда" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "%(count)sмүнөт мурда" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "%(count)sсекунд мурда" + +msgid "now" +msgstr "азыр" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "мындан%(count)sсекунд мурда" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "мындан%(count)sмүнөт мурда" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "мындан%(count)sсаат мурда" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "мындан %(delta)s мурда" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d жыл" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d ай" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d апта" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d күн" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d саат" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d мүнөт" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d жыл" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d ай" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d апта" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d күн" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d саат" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d мүнөт" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/lb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/lb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5b7937f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/lb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/lb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/lb/LC_MESSAGES/django.po new file mode 100644 index 0000000..32550de --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/lb/LC_MESSAGES/django.po @@ -0,0 +1,261 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:12+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Luxembourgish (http://www.transifex.com/projects/p/django/" +"language/lb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "" + +msgid "th" +msgstr "" + +msgid "st" +msgstr "" + +msgid "nd" +msgstr "" + +msgid "rd" +msgstr "" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "" +msgstr[1] "" + +msgid "one" +msgstr "" + +msgid "two" +msgstr "" + +msgid "three" +msgstr "" + +msgid "four" +msgstr "" + +msgid "five" +msgstr "" + +msgid "six" +msgstr "" + +msgid "seven" +msgstr "" + +msgid "eight" +msgstr "" + +msgid "nine" +msgstr "" + +msgid "today" +msgstr "" + +msgid "tomorrow" +msgstr "" + +msgid "yesterday" +msgstr "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "" + +msgid "now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/lt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/lt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d6f5ca2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/lt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/lt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/lt/LC_MESSAGES/django.po new file mode 100644 index 0000000..a9fa708 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/lt/LC_MESSAGES/django.po @@ -0,0 +1,477 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Matas Dailyda , 2015,2018 +# Simonas Kazlauskas , 2013-2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2018-05-18 08:22+0000\n" +"Last-Translator: Matas Dailyda \n" +"Language-Team: Lithuanian (http://www.transifex.com/django/django/language/" +"lt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lt\n" +"Plural-Forms: nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < " +"11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? " +"1 : n % 1 != 0 ? 2: 3);\n" + +msgid "Humanize" +msgstr "Sužmoginti" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}-as" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}-as" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}-as" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}-as" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}-as" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}-as" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}-as" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}-as" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}-as" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}-as" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}-as" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f milijonas" +msgstr[1] "%(value).1f milijonai" +msgstr[2] "%(value).1f milijonų" +msgstr[3] "%(value).1f milijonų" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s milijonas" +msgstr[1] "%(value)s milijonai" +msgstr[2] "%(value)s milijonų" +msgstr[3] "%(value)s milijonų" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f milijardas" +msgstr[1] "%(value).1f milijardai" +msgstr[2] "%(value).1f milijardų" +msgstr[3] "%(value).1f milijardų" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s milijardas" +msgstr[1] "%(value)s milijardai" +msgstr[2] "%(value)s milijardų" +msgstr[3] "%(value)s milijardų" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f trilijonas" +msgstr[1] "%(value).1f trilijonai" +msgstr[2] "%(value).1f trilijonų" +msgstr[3] "%(value).1f trilijonų" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s trilijonas" +msgstr[1] "%(value)s trilijonai" +msgstr[2] "%(value)s trilijonų" +msgstr[3] "%(value)s trilijonų" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f kvadrilijonas" +msgstr[1] "%(value).1f kvadrilijonai" +msgstr[2] "%(value).1f kvadrilijonų" +msgstr[3] "%(value).1f kvadrilijonų" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s kvadrilijonas" +msgstr[1] "%(value)s kvadrilijonai" +msgstr[2] "%(value)s kvadrilijonų" +msgstr[3] "%(value)s kvadrilijonų" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f kvintilijonas" +msgstr[1] "%(value).1f kvintilijonai" +msgstr[2] "%(value).1f kvintilijonų" +msgstr[3] "%(value).1f kvintilijonų" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s kvintilijonas" +msgstr[1] "%(value)s kvintilijonai" +msgstr[2] "%(value)s kvintilijonų" +msgstr[3] "%(value)s kvintilijonų" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f sikstilijonas" +msgstr[1] "%(value).1f sikstilijonai" +msgstr[2] "%(value).1f sikstilijonų" +msgstr[3] "%(value).1f sikstilijonų" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s sikstilijonas" +msgstr[1] "%(value)s sikstilijonai" +msgstr[2] "%(value)s sikstilijonų" +msgstr[3] "%(value)s sikstilijonų" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f septilijonas" +msgstr[1] "%(value).1f septilijonai" +msgstr[2] "%(value).1f septilijonų" +msgstr[3] "%(value).1f septilijonų" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septilijonas" +msgstr[1] "%(value)s septilijonai" +msgstr[2] "%(value)s septilijonų" +msgstr[3] "%(value)s septilijonų" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f oktilijonas" +msgstr[1] "%(value).1f oktilijonai" +msgstr[2] "%(value).1f oktilijonų" +msgstr[3] "%(value).1f oktilijonų" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s oktilijonas" +msgstr[1] "%(value)s oktilijonai" +msgstr[2] "%(value)s oktilijonų" +msgstr[3] "%(value)s oktilijonų" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f naintilijonas" +msgstr[1] "%(value).1f naintilijonai" +msgstr[2] "%(value).1f naintilijonų" +msgstr[3] "%(value).1f naintilijonų" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s naintilijonas" +msgstr[1] "%(value)s naintilijonai" +msgstr[2] "%(value)s naintilijonų" +msgstr[3] "%(value)s naintilijonų" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f decilijonas" +msgstr[1] "%(value).1f decilijonai" +msgstr[2] "%(value).1f decilijonų" +msgstr[3] "%(value).1f decilijonų" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s decilijonas" +msgstr[1] "%(value)s decilijonai" +msgstr[2] "%(value)s decilijonų" +msgstr[3] "%(value)s decilijonų" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f gugolas" +msgstr[1] "%(value).1f gugolai" +msgstr[2] "%(value).1f gugolų" +msgstr[3] "%(value).1f gugolų" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s gugolas" +msgstr[1] "%(value)s gugolai" +msgstr[2] "%(value)s gugolų" +msgstr[3] "%(value)s gugolų" + +msgid "one" +msgstr "vienas" + +msgid "two" +msgstr "du" + +msgid "three" +msgstr "trys" + +msgid "four" +msgstr "keturi" + +msgid "five" +msgstr "penki" + +msgid "six" +msgstr "šeši" + +msgid "seven" +msgstr "septyni" + +msgid "eight" +msgstr "aštuoni" + +msgid "nine" +msgstr "devyni" + +msgid "today" +msgstr "šiandien" + +msgid "tomorrow" +msgstr "rytoj" + +msgid "yesterday" +msgstr "vakar" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "prieš %(delta)s" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "prieš %(count)s valandą" +msgstr[1] "prieš %(count)s valandas" +msgstr[2] "prieš %(count)s valandų" +msgstr[3] "prieš %(count)s valandų" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "prieš %(count)s minutę" +msgstr[1] "prieš %(count)s minutes" +msgstr[2] "prieš %(count)s minučių" +msgstr[3] "prieš %(count)s minučių" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "prieš %(count)s sekundę" +msgstr[1] "prieš %(count)s sekundes" +msgstr[2] "prieš %(count)s sekundžių" +msgstr[3] "prieš %(count)s sekundžių" + +msgid "now" +msgstr "dabar" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "%(count)s sekundė nuo dabar" +msgstr[1] "%(count)s sekundes nuo dabar" +msgstr[2] "%(count)s skundžių nuo dabar" +msgstr[3] "%(count)s skundžių nuo dabar" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "%(count)s minutė nuo dabar" +msgstr[1] "%(count)s minutės nuo dabar" +msgstr[2] "%(count)s minučių nuo dabar" +msgstr[3] "%(count)s minučių nuo dabar" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "%(count)s valandą nuo dabar" +msgstr[1] "%(count)s valandos nuo dabar" +msgstr[2] "%(count)s valandų nuo dabar" +msgstr[3] "%(count)s valandų nuo dabar" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s nuo dabar" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d metus" +msgstr[1] "%d metus" +msgstr[2] "%d metų" +msgstr[3] "%d metų" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d mėnesį" +msgstr[1] "%d mėnesius" +msgstr[2] "%d mėnesių" +msgstr[3] "%d mėnesių" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d savaitę" +msgstr[1] "%d savaites" +msgstr[2] "%d savaičių" +msgstr[3] "%d savaičių" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d dieną" +msgstr[1] "%d dienas" +msgstr[2] "%d dienų" +msgstr[3] "%d dienų" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d valandą" +msgstr[1] "%d valandas" +msgstr[2] "%d valandų" +msgstr[3] "%d valandų" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d minutę" +msgstr[1] "%d minutes" +msgstr[2] "%d minučių" +msgstr[3] "%d minučių" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d metus" +msgstr[1] "%d metus" +msgstr[2] "%d metų" +msgstr[3] "%d metų" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d mėnesį" +msgstr[1] "%d mėnesius" +msgstr[2] "%d mėnesių" +msgstr[3] "%d mėnesių" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d savaitę" +msgstr[1] "%d savaites" +msgstr[2] "%d savaičių" +msgstr[3] "%d savaičių" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d dieną" +msgstr[1] "%d dienas" +msgstr[2] "%d dienų" +msgstr[3] "%d dienų" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d valandą" +msgstr[1] "%d valandas" +msgstr[2] "%d valandų" +msgstr[3] "%d valandų" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d minutė" +msgstr[1] "%d minutes" +msgstr[2] "%d minučių" +msgstr[3] "%d minučių" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/lv/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/lv/LC_MESSAGES/django.mo new file mode 100644 index 0000000..29d2e78 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/lv/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/lv/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/lv/LC_MESSAGES/django.po new file mode 100644 index 0000000..50569e5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/lv/LC_MESSAGES/django.po @@ -0,0 +1,363 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# NullIsNot0 , 2017 +# NullIsNot0 , 2017-2018 +# Jannis Leidel , 2011 +# NullIsNot0 , 2021 +# peterisb , 2016 +# peterisb , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2021-10-06 05:15+0000\n" +"Last-Translator: NullIsNot0 \n" +"Language-Team: Latvian (http://www.transifex.com/django/django/language/" +"lv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lv\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : " +"2);\n" + +msgid "Humanize" +msgstr "Padarīt cilvēcīgu" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s miljonu" +msgstr[1] "%(value)s miljons" +msgstr[2] "%(value)s miljonu" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s miljardu" +msgstr[1] "%(value)s miljards" +msgstr[2] "%(value)s miljardu" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s triljonu" +msgstr[1] "%(value)s triljons" +msgstr[2] "%(value)s triljonu" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s kvadriljonu" +msgstr[1] "%(value)s kvadriljons" +msgstr[2] "%(value)s kvadriljonu" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s kvintiljonu" +msgstr[1] "%(value)s kvintiljons" +msgstr[2] "%(value)s kvintiljonu" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s sekstiljonu" +msgstr[1] "%(value)s sekstiljons" +msgstr[2] "%(value)s sekstiljonu" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septiljonu" +msgstr[1] "%(value)s septiljons" +msgstr[2] "%(value)s septiljonu" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s oktiljonu" +msgstr[1] "%(value)s oktiljons" +msgstr[2] "%(value)s oktiljonu" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s noniljonu" +msgstr[1] "%(value)s noniljons" +msgstr[2] "%(value)s noniljonu" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s dekaljonu" +msgstr[1] "%(value)s dekaljons" +msgstr[2] "%(value)s dekaljonu" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s gugolu" +msgstr[1] "%(value)s gugols" +msgstr[2] "%(value)s gugolu" + +msgid "one" +msgstr "viens" + +msgid "two" +msgstr "divi" + +msgid "three" +msgstr "trīs" + +msgid "four" +msgstr "četri" + +msgid "five" +msgstr "pieci" + +msgid "six" +msgstr "seši" + +msgid "seven" +msgstr "septiņi" + +msgid "eight" +msgstr "astoņi" + +msgid "nine" +msgstr "deviņi" + +msgid "today" +msgstr "šodien" + +msgid "tomorrow" +msgstr "rīt" + +msgid "yesterday" +msgstr "vakar" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "pirms %(delta)s" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "pirms %(count)s stundas" +msgstr[1] "pirms %(count)s stundām" +msgstr[2] "pirms %(count)s stundām" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "pirms %(count)s minūtes" +msgstr[1] "pirms %(count)s minūtēm" +msgstr[2] "pirms %(count)s minūtēm" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "pirms %(count)s sekundes" +msgstr[1] "pirms %(count)s sekundēm" +msgstr[2] "pirms %(count)s sekundēm" + +msgid "now" +msgstr "tagad" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "pēc %(count)s sekundes" +msgstr[1] "pēc %(count)s sekundēm" +msgstr[2] "pēc %(count)s sekundēm" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "pēc %(count)s minūtes" +msgstr[1] "pēc %(count)s minūtēm" +msgstr[2] "pēc %(count)s minūtēm" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "pēc %(count)s stundas" +msgstr[1] "pēc %(count)s stundām" +msgstr[2] "pēc %(count)s stundām" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "pēc %(delta)s" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d gadi" +msgstr[1] "%(num)d gads" +msgstr[2] "%(num)d gadi" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mēneši" +msgstr[1] "%(num)d mēnesis" +msgstr[2] "%(num)d mēneši" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d nedēļas" +msgstr[1] "%(num)d nedēļa" +msgstr[2] "%(num)d nedēļas" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dienas" +msgstr[1] "%(num)d diena" +msgstr[2] "%(num)d dienas" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d stundas" +msgstr[1] "%(num)d stunda" +msgstr[2] "%(num)d stundas" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minūtes" +msgstr[1] "%(num)d minūte" +msgstr[2] "%(num)d minūtes" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d gadi" +msgstr[1] "%(num)d gads" +msgstr[2] "%(num)d gadi" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mēneši" +msgstr[1] "%(num)d mēnesis" +msgstr[2] "%(num)d mēneši" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d nedēļas" +msgstr[1] "%(num)d nedēļa" +msgstr[2] "%(num)d nedēļas" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dienas" +msgstr[1] "%(num)d diena" +msgstr[2] "%(num)d dienas" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d stundas" +msgstr[1] "%(num)d stunda" +msgstr[2] "%(num)d stundas" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minūtes" +msgstr[1] "%(num)d minūte" +msgstr[2] "%(num)d minūtes" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/mk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/mk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..cc6bfbd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/mk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/mk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/mk/LC_MESSAGES/django.po new file mode 100644 index 0000000..136b20b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/mk/LC_MESSAGES/django.po @@ -0,0 +1,262 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Vasil Vangelovski , 2013-2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 19:05+0000\n" +"Last-Translator: dekomote \n" +"Language-Team: Macedonian (http://www.transifex.com/django/django/language/" +"mk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mk\n" +"Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n" + +msgid "Humanize" +msgstr "Хуманизирање" + +msgid "th" +msgstr "ти" + +msgid "st" +msgstr "ви" + +msgid "nd" +msgstr "ри" + +msgid "rd" +msgstr "ти" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f милион" +msgstr[1] "%(value).1f милиони" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s милион" +msgstr[1] "%(value)s милиони" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f милијарда" +msgstr[1] "%(value).1f милијарди" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s милијарда" +msgstr[1] "%(value)s милијарди" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f трилион" +msgstr[1] "%(value).1f трилиони" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s трилион" +msgstr[1] "%(value)s трилиони" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f квадрилион" +msgstr[1] "%(value).1f квадрилиони" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s квадрилион" +msgstr[1] "%(value)s квадрилиони" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f квинтилион" +msgstr[1] "%(value).1f квинтилиони" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s квинтилион" +msgstr[1] "%(value)s квинтилиони" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f секстилион" +msgstr[1] "%(value).1f секстилиони" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s секстилион" +msgstr[1] "%(value)s секстилиони" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f септилион" +msgstr[1] "%(value).1f септилиони" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s септилион" +msgstr[1] "%(value)s септилиони" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f октилион" +msgstr[1] "%(value).1f октилиони" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s октилион" +msgstr[1] "%(value)s октилиони" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f нонилион" +msgstr[1] "%(value).1f нонилиони" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s нонилион" +msgstr[1] "%(value)s нонилиони" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f децилион" +msgstr[1] "%(value).1f децилиони" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s децилион" +msgstr[1] "%(value)s децилиони" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f гугол" +msgstr[1] "%(value).1f гуголи" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s гугол" +msgstr[1] "%(value)s гуголи" + +msgid "one" +msgstr "еден" + +msgid "two" +msgstr "две" + +msgid "three" +msgstr "три" + +msgid "four" +msgstr "четри" + +msgid "five" +msgstr "пет" + +msgid "six" +msgstr "шест" + +msgid "seven" +msgstr "седум" + +msgid "eight" +msgstr "осум" + +msgid "nine" +msgstr "девет" + +msgid "today" +msgstr "денес" + +msgid "tomorrow" +msgstr "утре" + +msgid "yesterday" +msgstr "вчера" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "пред %(delta)s" + +msgid "now" +msgstr "сега" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "пред %(count)s секундa" +msgstr[1] "пред %(count)s секунди" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "пред %(count)s минутa" +msgstr[1] "пред %(count)s минути" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "пред %(count)s час" +msgstr[1] "пред %(count)s часа" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "%(delta)s од сега" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "за %(count)s секундa од сега" +msgstr[1] "за %(count)s секунди од сега" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "за %(count)s минута од сега" +msgstr[1] "за %(count)s минути од сега" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "за %(count)s час од сега" +msgstr[1] "за %(count)s часа од сега" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ml/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ml/LC_MESSAGES/django.mo new file mode 100644 index 0000000..13cc9ae Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ml/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ml/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ml/LC_MESSAGES/django.po new file mode 100644 index 0000000..3c844a8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ml/LC_MESSAGES/django.po @@ -0,0 +1,396 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Hrishikesh , 2020 +# Jannis Leidel , 2011 +# Rajeesh Nair , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2020-05-13 21:29+0000\n" +"Last-Translator: Hrishikesh \n" +"Language-Team: Malayalam (http://www.transifex.com/django/django/language/" +"ml/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ml\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "ഹ്യൂമനൈസ്" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f ദശലക്ഷം" +msgstr[1] "%(value).1f ദശലക്ഷം" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s ദശലക്ഷം" +msgstr[1] "%(value)s ദശലക്ഷം" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f ശതകോടി" +msgstr[1] "%(value).1f ശതകോടി" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s ശതകോടി" +msgstr[1] "%(value)s ശതകോടി" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f ട്രില്ല്യണ്‍ (ലക്ഷം കോടി)" +msgstr[1] "%(value).1f ട്രില്ല്യണ്‍ (ലക്ഷം കോടി)" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s ലക്ഷം കോടി" +msgstr[1] "%(value)s ലക്ഷം കോടി" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f ക്വാഡ്രില്ല്യണ്‍" +msgstr[1] "%(value).1f ക്വാഡ്രില്ല്യണ്‍" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s ക്വാഡ്രില്ല്യണ്‍" +msgstr[1] "%(value)s ക്വാഡ്രില്ല്യണ്‍" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f ക്വിന്റില്ല്യണ്‍" +msgstr[1] "%(value).1f ക്വിന്റില്ല്യണ്‍" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s ക്വിന്റില്ല്യണ്‍" +msgstr[1] "%(value)s ക്വിന്റില്ല്യണ്‍" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f സെക്സ്റ്റില്ല്യണ്‍" +msgstr[1] "%(value).1f സെക്സ്റ്റില്ല്യണ്‍" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s സെക്സ്റ്റില്ല്യണ്‍" +msgstr[1] "%(value)s സെക്സ്റ്റില്ല്യണ്‍" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f സെപ്റ്റില്ല്യണ്‍" +msgstr[1] "%(value).1f സെപ്റ്റില്ല്യണ്‍" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s സെപ്റ്റില്ല്യണ്‍" +msgstr[1] "%(value)s സെപ്റ്റില്ല്യണ്‍" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f ഒക്റ്റില്ല്യണ്‍" +msgstr[1] "%(value).1f ഒക്റ്റില്ല്യണ്‍" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s ഒക്റ്റില്ല്യണ്‍" +msgstr[1] "%(value)s ഒക്റ്റില്ല്യണ്‍" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f നോനില്ല്യണ്‍" +msgstr[1] "%(value).1f നോനില്ല്യണ്‍" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s നോനില്ല്യണ്‍" +msgstr[1] "%(value)s നോനില്ല്യണ്‍" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f ഡെസില്ല്യണ്‍" +msgstr[1] "%(value).1f ഡെസില്ല്യണ്‍" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s ഡെസില്ല്യണ്‍" +msgstr[1] "%(value)s ഡെസില്ല്യണ്‍" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f ഗൂഗോള്‍" +msgstr[1] "%(value).1f ഗൂഗോള്‍" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s ഗൂഗോള്‍" +msgstr[1] "%(value)s ഗൂഗോള്‍" + +msgid "one" +msgstr "ഒന്ന്" + +msgid "two" +msgstr "രണ്ട്" + +msgid "three" +msgstr "മൂന്ന്" + +msgid "four" +msgstr "നാല്" + +msgid "five" +msgstr "അഞ്ച്" + +msgid "six" +msgstr "ആറ്" + +msgid "seven" +msgstr "ഏഴ്" + +msgid "eight" +msgstr "എട്ട്" + +msgid "nine" +msgstr "ഒന്‍പത്" + +msgid "today" +msgstr "ഇന്ന്" + +msgid "tomorrow" +msgstr "നാളെ" + +msgid "yesterday" +msgstr "ഇന്നലെ" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" +msgstr[1] "" + +msgid "now" +msgstr "ഇപ്പോള്‍" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/mn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/mn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..de62154 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/mn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/mn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/mn/LC_MESSAGES/django.po new file mode 100644 index 0000000..8b2de47 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/mn/LC_MESSAGES/django.po @@ -0,0 +1,398 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bayarkhuu Bataa, 2014 +# Bayarkhuu Bataa, 2013 +# Zorig, 2013 +# Zorig, 2019 +# Анхбаяр Анхаа , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2019-02-19 02:28+0000\n" +"Last-Translator: Zorig\n" +"Language-Team: Mongolian (http://www.transifex.com/django/django/language/" +"mn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Хүнчлэх" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{} дэхь" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{} дэхь" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{} дэхь" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{} дахь" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{} дахь" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{} дахь" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{} дэхь" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{} дэхь" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{} дэхь" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{} дэхь" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{} дэхь" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f сая" +msgstr[1] "%(value).1f сая" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s сая" +msgstr[1] "%(value)s сая" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f тэрбум" +msgstr[1] "%(value).1f тэрбум" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s тэрбум" +msgstr[1] "%(value)s тэрбум" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f наяд" +msgstr[1] "%(value).1f наяд" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s наяд" +msgstr[1] "%(value)s наяд" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f тунамал" +msgstr[1] "%(value).1f тунамал" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s тунамал" +msgstr[1] "%(value)s тунамал" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f их ингүүмэл " +msgstr[1] "%(value).1f их ингүүмэл " + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s их ингүүмэл " +msgstr[1] "%(value)s их ингүүмэл " + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f ялгаруулагч" +msgstr[1] "%(value).1f ялгаруулагч" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s ялгаруулагч" +msgstr[1] "%(value)s ялгаруулагч" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f их өөр дээр " +msgstr[1] "%(value).1f их өөр дээр " + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s их өөр дээр " +msgstr[1] "%(value)s их өөр дээр " + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f өөр дээр " +msgstr[1] "%(value).1f өөр дээр " + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s өөр дээр " +msgstr[1] "%(value)s өөр дээр " + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f их шалтгааны үзэгдэл" +msgstr[1] "%(value).1f их шалтгааны үзэгдэл" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s их шалтгааны үзэгдэл" +msgstr[1] "%(value)s их шалтгааны үзэгдэл" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f эрхэт" +msgstr[1] "%(value).1f эрхэт" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s эрхэт" +msgstr[1] "%(value)s эрхэт" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f googol" +msgstr[1] "%(value).1f googol" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" +msgstr[1] "%(value)s googol" + +msgid "one" +msgstr "нэг" + +msgid "two" +msgstr "хоёр" + +msgid "three" +msgstr "гурав" + +msgid "four" +msgstr "дөрөв" + +msgid "five" +msgstr "тав" + +msgid "six" +msgstr "зургаа" + +msgid "seven" +msgstr "долоо" + +msgid "eight" +msgstr "найм" + +msgid "nine" +msgstr "ес" + +msgid "today" +msgstr "өнөөдөр" + +msgid "tomorrow" +msgstr "маргааш" + +msgid "yesterday" +msgstr "өчигдөр" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s ѳмнѳ" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "1 цагийн өмнө" +msgstr[1] "%(count)s цагийн өмнө" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "1 минутын өмнө" +msgstr[1] "%(count)s минутын өмнө" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "1 секундын өмнө" +msgstr[1] "%(count)s секундын өмнө" + +msgid "now" +msgstr "одоо" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "1 секундын дараа" +msgstr[1] "%(count)s секундын дараа" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "1 минутын дараа" +msgstr[1] "%(count)s минутын дараа" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "1 цагийн дараа" +msgstr[1] "%(count)s цагийн дараа" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "одооноос %(delta)s " + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d жил" +msgstr[1] "%d жилүүд" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d сар" +msgstr[1] "%d сар" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d долоо хоног" +msgstr[1] "%d долоо хоног" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d өдөр" +msgstr[1] "%d өдөр" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d цаг" +msgstr[1] "%d цаг" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d минут" +msgstr[1] "%d минут" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d жил" +msgstr[1] "%d жил" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d сар" +msgstr[1] "%d сар" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d долоо хоног" +msgstr[1] "%d долоо хоног" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d өдөр" +msgstr[1] "%d өдөр" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d цаг" +msgstr[1] "%d цаг" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d минут" +msgstr[1] "%d минут" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/mr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/mr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..183b3d1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/mr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/mr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/mr/LC_MESSAGES/django.po new file mode 100644 index 0000000..b042b29 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/mr/LC_MESSAGES/django.po @@ -0,0 +1,261 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:12+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Marathi (http://www.transifex.com/projects/p/django/language/" +"mr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mr\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "" + +msgid "th" +msgstr "" + +msgid "st" +msgstr "" + +msgid "nd" +msgstr "" + +msgid "rd" +msgstr "" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "" +msgstr[1] "" + +msgid "one" +msgstr "" + +msgid "two" +msgstr "" + +msgid "three" +msgstr "" + +msgid "four" +msgstr "" + +msgid "five" +msgstr "" + +msgid "six" +msgstr "" + +msgid "seven" +msgstr "" + +msgid "eight" +msgstr "" + +msgid "nine" +msgstr "" + +msgid "today" +msgstr "" + +msgid "tomorrow" +msgstr "" + +msgid "yesterday" +msgstr "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "" + +msgid "now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ms/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ms/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1384c6b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ms/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ms/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ms/LC_MESSAGES/django.po new file mode 100644 index 0000000..e1101d4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ms/LC_MESSAGES/django.po @@ -0,0 +1,299 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# alternativespeak , 2012 +# Jafry Hisham, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2021-12-24 18:40+0000\n" +"Last-Translator: Jafry Hisham\n" +"Language-Team: Malay (http://www.transifex.com/django/django/language/ms/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ms\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Humanize" +msgstr "Memanusiakan" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "ke{}" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "ke{}" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "ke{}" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "ke{}" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "ke{}" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "ke{}" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "ke{}" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "ke{}" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "ke{}" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "ke{}" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "ke{}" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s juta" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s bilion" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s trilion" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s kuadrilion" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s kuintilion" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)ssextilion" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septilion" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s oktilion" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s nontilion" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)sdesilion" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" + +msgid "one" +msgstr "satu" + +msgid "two" +msgstr "dua" + +msgid "three" +msgstr "tiga" + +msgid "four" +msgstr "empat" + +msgid "five" +msgstr "lima" + +msgid "six" +msgstr "enam" + +msgid "seven" +msgstr "tujuh" + +msgid "eight" +msgstr "lapan" + +msgid "nine" +msgstr "sembilan" + +msgid "today" +msgstr "hari ini" + +msgid "tomorrow" +msgstr "esok" + +msgid "yesterday" +msgstr "semalam" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s yang lalu" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "%(count)s yang lalu" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "%(count)s minit yang lalu" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "%(count)s saat yang lalu" + +msgid "now" +msgstr "sekarang" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "%(count)s saat dari sekarang" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "%(count)s minit dari sekarang" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "%(count)s jam dari sekarang" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s dari sekarang" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d tahun" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d bulan" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d minggu" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d hari" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d jam" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minit" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d tahun" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d bulan" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d minggu" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d hari" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d jam" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minit" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/my/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/my/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d26a6d2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/my/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/my/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/my/LC_MESSAGES/django.po new file mode 100644 index 0000000..a3fe48c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/my/LC_MESSAGES/django.po @@ -0,0 +1,234 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Yhal Htet Aung , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Burmese (http://www.transifex.com/django/django/language/" +"my/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: my\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Humanize" +msgstr "" + +msgid "th" +msgstr "မြောက်" + +msgid "st" +msgstr "မြောက်" + +msgid "nd" +msgstr "မြောက်" + +msgid "rd" +msgstr "မြောက်" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f မီလီယံ" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s မီလီယံ" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f ဘီလီယံ" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s ဘီလီယံ" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f တရီလျံ" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s တရီလျံ" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f ကွပ်ဒရီလျံ" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s ကွပ်ဒရီလျံ" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f ကွင့်တီလျံ" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s ကွင့်တီလျံ" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f ဆက်တီလျံ" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s ဆက်တီလျံ" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f ဆပ်တီလျံ" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s ဆပ်တီလျံ" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f အော့တီလျံ" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s အော့တီလျံ" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f နိုနီလျံ" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s နိုနီလျံ" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f ဒက်စီလျံ" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s ဒက်စီလျံ" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f ဂူးဂေါ်" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s ဂူးဂေါ်" + +msgid "one" +msgstr "တစ်" + +msgid "two" +msgstr "နှစ်" + +msgid "three" +msgstr "သံုး" + +msgid "four" +msgstr "လေး" + +msgid "five" +msgstr "ငါး" + +msgid "six" +msgstr "ခြောက်" + +msgid "seven" +msgstr "ခုနစ်" + +msgid "eight" +msgstr "ရှစ်" + +msgid "nine" +msgstr "ကိုး" + +msgid "today" +msgstr "ယနေ့" + +msgid "tomorrow" +msgstr "မနက်ဖြန်" + +msgid "yesterday" +msgstr "မနေ့" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "%(delta)s အခါက" + +msgid "now" +msgstr "ယခု" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "%(delta)s ယခုမှ" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/nb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/nb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..71f60b2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/nb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/nb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/nb/LC_MESSAGES/django.po new file mode 100644 index 0000000..1212f9c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/nb/LC_MESSAGES/django.po @@ -0,0 +1,331 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Jon, 2014 +# Jon, 2018,2022 +# Jon, 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2023-04-24 18:40+0000\n" +"Last-Translator: Jon, 2018,2022\n" +"Language-Team: Norwegian Bokmål (http://www.transifex.com/django/django/" +"language/nb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Humanize" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}." + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s million" +msgstr[1] "%(value)s millioner" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s milliard" +msgstr[1] "%(value)s milliarder" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s billion" +msgstr[1] "%(value)s billioner" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s kvadrillion" +msgstr[1] "%(value)s kvadrillioner" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s kvintillion" +msgstr[1] "%(value)s kvintillioner" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s sekstillion" +msgstr[1] "%(value)s sekstillioner" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septillion" +msgstr[1] "%(value)s septillioner" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s oktillion" +msgstr[1] "%(value)s oktillioner" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s nonillion" +msgstr[1] "%(value)s nonillioner" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s desillion" +msgstr[1] "%(value)s desillioner" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" +msgstr[1] "%(value)s googoler" + +msgid "one" +msgstr "én" + +msgid "two" +msgstr "to" + +msgid "three" +msgstr "tre" + +msgid "four" +msgstr "fire" + +msgid "five" +msgstr "fem" + +msgid "six" +msgstr "seks" + +msgid "seven" +msgstr "sju" + +msgid "eight" +msgstr "åtte" + +msgid "nine" +msgstr "ni" + +msgid "today" +msgstr "i dag" + +msgid "tomorrow" +msgstr "i morgen" + +msgid "yesterday" +msgstr "i går" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s siden" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "en time siden" +msgstr[1] "%(count)s timer siden" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "et minutt siden" +msgstr[1] "%(count)s minutter siden" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "et sekund siden" +msgstr[1] "%(count)s sekunder siden" + +msgid "now" +msgstr "nå" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "et sekund fra nå" +msgstr[1] "%(count)s sekunder fra nå" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "et minutt fra nå" +msgstr[1] "%(count)s minutter fra nå" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "en time fra nå" +msgstr[1] "%(count)s timer fra nå" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s fra nå" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d år" +msgstr[1] "%(num)d år" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d måned" +msgstr[1] "%(num)d måneder" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d uke" +msgstr[1] "%(num)d uker" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dag" +msgstr[1] "%(num)d dager" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d time" +msgstr[1] "%(num)d timer" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minutt" +msgstr[1] "%(num)d minutter" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d år" +msgstr[1] "%(num)d år" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d måned" +msgstr[1] "%(num)d måneder" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d uke" +msgstr[1] "%(num)d uker" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dag" +msgstr[1] "%(num)d dager" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d time" +msgstr[1] "%(num)d timer" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minutt" +msgstr[1] "%(num)d minutter" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ne/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ne/LC_MESSAGES/django.mo new file mode 100644 index 0000000..24deec3 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ne/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ne/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ne/LC_MESSAGES/django.po new file mode 100644 index 0000000..d3c9c95 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ne/LC_MESSAGES/django.po @@ -0,0 +1,395 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Paras Nath Chaudhary , 2012 +# Sagar Chalise , 2019 +# Sandesh Rana , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2019-12-15 05:39+0000\n" +"Last-Translator: Sagar Chalise \n" +"Language-Team: Nepali (http://www.transifex.com/django/django/language/ne/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ne\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "मानवीय बनाउनुहोस्" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s मिलियन" +msgstr[1] "%(value)s मिलियन" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s अरब" +msgstr[1] "%(value)s अरब" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s खरब" +msgstr[1] "%(value)s खरब" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s करोड़ शंख" +msgstr[1] "%(value)s करोड़ शंख" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "" +msgstr[1] "" + +msgid "one" +msgstr "एक " + +msgid "two" +msgstr "दुई " + +msgid "three" +msgstr "तीन " + +msgid "four" +msgstr "चार " + +msgid "five" +msgstr "पाँच " + +msgid "six" +msgstr "छ " + +msgid "seven" +msgstr "सात " + +msgid "eight" +msgstr "आठ " + +msgid "nine" +msgstr "नौ " + +msgid "today" +msgstr "आज" + +msgid "tomorrow" +msgstr "भोली" + +msgid "yesterday" +msgstr "हिजो" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)sपहिले" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "एक घण्टा अघि" +msgstr[1] "%(count)s घण्टा अघि" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "एक मिनेट अघि" +msgstr[1] "%(count)s मिनेट अघि" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "एक सेकेन्ड अघि" +msgstr[1] "%(count)s सेकेन्ड अघि" + +msgid "now" +msgstr "अहिले" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "एक सेकेन्ड पछि" +msgstr[1] "%(count)s सेकेन्ड पछि" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "एक मिनेट पछि" +msgstr[1] "%(count)s मिनेट पछि" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "एक घण्टा पछि" +msgstr[1] "%(count)s घण्टा पछि" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s अबदेखि" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d बर्ष" +msgstr[1] "%d बर्षहरु" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d महिना" +msgstr[1] "%d महिनाहरु" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d हप्ता" +msgstr[1] "%d हप्ताहरु" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d दिन" +msgstr[1] "%d दिनहरु" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d घण्टा" +msgstr[1] "%d घण्टाहरू" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d मिनेट" +msgstr[1] "%d मिनेटहरू " + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d बर्ष" +msgstr[1] "%d बर्षहरु" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d महिना" +msgstr[1] "%d महिनाहरु" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d हप्ता" +msgstr[1] "%d हप्ताहरु" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d दिन" +msgstr[1] "%d दिनहरु" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d घण्टा" +msgstr[1] "%d घण्टाहरू" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d मिनेट" +msgstr[1] "%d मिनेटहरू " diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/nl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/nl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a702bfa Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/nl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/nl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/nl/LC_MESSAGES/django.po new file mode 100644 index 0000000..c88cf1d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/nl/LC_MESSAGES/django.po @@ -0,0 +1,332 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Blue , 2011-2012 +# Jannis Leidel , 2011 +# 6a27f10aef159701c7a5ff07f0fb0a78_05545ed , 2014 +# 8de006b1b0894aab6aef71979dcd8bd6_5c6b207 , 2015 +# Tino de Bruijn , 2012 +# Tonnes , 2019,2022 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2022-07-24 18:40+0000\n" +"Last-Translator: Tonnes \n" +"Language-Team: Dutch (http://www.transifex.com/django/django/language/nl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Vermenselijken" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}e" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}e" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}e" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}e" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}e" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}e" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}e" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}e" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}e" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}e" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}e" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s miljoen" +msgstr[1] "%(value)s miljoen" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s miljard" +msgstr[1] "%(value)s miljard" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s biljoen" +msgstr[1] "%(value)s biljoen" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s biljard" +msgstr[1] "%(value)s biljard" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s triljoen" +msgstr[1] "%(value)s triljoen" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s triljard" +msgstr[1] "%(value)s triljard" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s quadriljoen" +msgstr[1] "%(value)s quadriljoen" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s quadriljard" +msgstr[1] "%(value)s quadriljard" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s quintiljoen" +msgstr[1] "%(value)s quintiljoen" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s quintiljard" +msgstr[1] "%(value)s quintiljard" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" +msgstr[1] "%(value)s googol" + +msgid "one" +msgstr "één" + +msgid "two" +msgstr "twee" + +msgid "three" +msgstr "drie" + +msgid "four" +msgstr "vier" + +msgid "five" +msgstr "vijf" + +msgid "six" +msgstr "zes" + +msgid "seven" +msgstr "zeven" + +msgid "eight" +msgstr "acht" + +msgid "nine" +msgstr "negen" + +msgid "today" +msgstr "vandaag" + +msgid "tomorrow" +msgstr "morgen" + +msgid "yesterday" +msgstr "gisteren" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s geleden" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "een uur geleden" +msgstr[1] "%(count)s uur geleden" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "een minuut geleden" +msgstr[1] "%(count)s minuten geleden" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "een seconde geleden" +msgstr[1] "%(count)s seconden geleden" + +msgid "now" +msgstr "nu" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "over een seconde" +msgstr[1] "over %(count)s seconden" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "over een minuut" +msgstr[1] "over %(count)s minuten" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "over een uur" +msgstr[1] "over %(count)s uur" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "over %(delta)s" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d jaar" +msgstr[1] "%(num)d jaar" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d maand" +msgstr[1] "%(num)d maanden" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d week" +msgstr[1] "%(num)d weken" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dag" +msgstr[1] "%(num)d dagen" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d uur" +msgstr[1] "%(num)d uur" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuut" +msgstr[1] "%(num)d minuten" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d jaar" +msgstr[1] "%(num)d jaar" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d maand" +msgstr[1] "%(num)d maanden" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d week" +msgstr[1] "%(num)d weken" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dag" +msgstr[1] "%(num)d dagen" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d uur" +msgstr[1] "%(num)d uur" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuut" +msgstr[1] "%(num)d minuten" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/nn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/nn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2b358c4 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/nn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/nn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/nn/LC_MESSAGES/django.po new file mode 100644 index 0000000..30d7558 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/nn/LC_MESSAGES/django.po @@ -0,0 +1,330 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Sivert Olstad, 2021-2022 +# velmont , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2022-07-24 18:40+0000\n" +"Last-Translator: Sivert Olstad\n" +"Language-Team: Norwegian Nynorsk (http://www.transifex.com/django/django/" +"language/nn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Humanize" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}." + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s million" +msgstr[1] "%(value)s millionar" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s milliard" +msgstr[1] "%(value)s milliardar" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s billion" +msgstr[1] "%(value)s billionar" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s kvadrillion" +msgstr[1] "%(value)s kvadrillionar" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s kvintillion" +msgstr[1] "%(value)s kvintillionar" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s sekstillion" +msgstr[1] "%(value)s sekstillionar" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septillion" +msgstr[1] "%(value)s septillionar" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s oktillion" +msgstr[1] "%(value)s oktillionar" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s nonillion" +msgstr[1] "%(value)s nonillionar" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s desillion" +msgstr[1] "%(value)s desillionar" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" +msgstr[1] "%(value)s googolar" + +msgid "one" +msgstr "éin" + +msgid "two" +msgstr "to" + +msgid "three" +msgstr "tre" + +msgid "four" +msgstr "fire" + +msgid "five" +msgstr "fem" + +msgid "six" +msgstr "seks" + +msgid "seven" +msgstr "sju" + +msgid "eight" +msgstr "åtte" + +msgid "nine" +msgstr "ni" + +msgid "today" +msgstr "i dag" + +msgid "tomorrow" +msgstr "i morgon" + +msgid "yesterday" +msgstr "i går" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s sidan" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "ein time sidan" +msgstr[1] "%(count)s timar sidan" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "eitt minutt sidan" +msgstr[1] "%(count)s minutt sidan" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "eitt sekund sidan" +msgstr[1] "%(count)s sekund sidan" + +msgid "now" +msgstr "no" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "eitt sekund frå no" +msgstr[1] "%(count)s sekund frå no" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "eitt minutt frå no" +msgstr[1] "%(count)s minutt frå no" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "ein time frå no" +msgstr[1] "%(count)s timar frå no" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s frå no" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d år" +msgstr[1] "%(num)d år" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d månad" +msgstr[1] "%(num)d månader" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d veke" +msgstr[1] "%(num)d veker" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dag" +msgstr[1] "%(num)d dagar" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d time" +msgstr[1] "%(num)d timar" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minutt" +msgstr[1] "%(num)d minutt" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d år" +msgstr[1] "%(num)d år" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d månad" +msgstr[1] "%(num)d månader" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d veke" +msgstr[1] "%(num)d veker" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dag" +msgstr[1] "%(num)d dagar" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d time" +msgstr[1] "%(num)d timar" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minutt" +msgstr[1] "%(num)d minutt" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/os/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/os/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c156f1a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/os/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/os/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/os/LC_MESSAGES/django.po new file mode 100644 index 0000000..186ac89 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/os/LC_MESSAGES/django.po @@ -0,0 +1,262 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Soslan Khubulov , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Ossetic (http://www.transifex.com/django/django/language/" +"os/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: os\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "" + +msgid "th" +msgstr "-ӕм" + +msgid "st" +msgstr "-аг" + +msgid "nd" +msgstr "-аг" + +msgid "rd" +msgstr "-аг" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f милуан" +msgstr[1] "%(value).1f милуан" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s милуан" +msgstr[1] "%(value)s милуан" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f биллон" +msgstr[1] "%(value).1f биллион" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s биллион" +msgstr[1] "%(value)s биллион" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f триллион" +msgstr[1] "%(value).1f триллион" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s триллион" +msgstr[1] "%(value)s триллион" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f къуадриллион" +msgstr[1] "%(value).1f къуадриллион" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s къуадриллион" +msgstr[1] "%(value)s къуадриллион" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f къуинтиллион" +msgstr[1] "%(value).1f къуинтиллион" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s къуинтиллион" +msgstr[1] "%(value)s къуинтиллион" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f секстиллион" +msgstr[1] "%(value).1f секстиллион" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s секстиллион" +msgstr[1] "%(value)s секстиллион" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f септиллион" +msgstr[1] "%(value).1f септиллион" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s септиллион" +msgstr[1] "%(value)s септиллион" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f октиллион" +msgstr[1] "%(value).1f октиллион" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s октиллион" +msgstr[1] "%(value)s октиллион" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f нониллион" +msgstr[1] "%(value).1f нониллион" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s нониллион" +msgstr[1] "%(value)s нониллион" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f дециллион" +msgstr[1] "%(value).1f дециллион" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s дециллион" +msgstr[1] "%(value)s дециллион" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f гугол" +msgstr[1] "%(value).1f гугол" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s гугол" +msgstr[1] "%(value)s гугол" + +msgid "one" +msgstr "иу" + +msgid "two" +msgstr "дыууӕ" + +msgid "three" +msgstr "ӕртӕ" + +msgid "four" +msgstr "цыппар" + +msgid "five" +msgstr "фондз" + +msgid "six" +msgstr "ӕхсӕз" + +msgid "seven" +msgstr "авд" + +msgid "eight" +msgstr "аст" + +msgid "nine" +msgstr "фараст" + +msgid "today" +msgstr "абон" + +msgid "tomorrow" +msgstr "сом" + +msgid "yesterday" +msgstr "знон" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "%(delta)s раздӕр" + +msgid "now" +msgstr "ныр" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "%(delta)s енырӕй" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/pa/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/pa/LC_MESSAGES/django.mo new file mode 100644 index 0000000..84c6571 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/pa/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/pa/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/pa/LC_MESSAGES/django.po new file mode 100644 index 0000000..d37c9ae --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/pa/LC_MESSAGES/django.po @@ -0,0 +1,263 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# A S Alam , 2013 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Panjabi (Punjabi) (http://www.transifex.com/django/django/" +"language/pa/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pa\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "" + +msgid "th" +msgstr "ਵਾਂ" + +msgid "st" +msgstr "ਲਾਂ" + +msgid "nd" +msgstr "ਜਾ" + +msgid "rd" +msgstr "ਜਾ" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f ਮਿਲੀਅਨ" +msgstr[1] "%(value).1f ਮਿਲੀਅਨ" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s ਮਿਲੀਅਨ" +msgstr[1] "%(value)s ਮਿਲੀਅਨ" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f ਬਿਲੀਅਨ" +msgstr[1] "%(value).1f ਬਿਲੀਅਨ" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f ਟਰਲੀਅਨ" +msgstr[1] "%(value).1f ਟਰਲੀਅਨ" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "" +msgstr[1] "" + +msgid "one" +msgstr "ਇੱਕ" + +msgid "two" +msgstr "ਦੋ" + +msgid "three" +msgstr "ਤਿੰਨ" + +msgid "four" +msgstr "ਚਾਰ" + +msgid "five" +msgstr "ਪੰਜ" + +msgid "six" +msgstr "ਛੇ" + +msgid "seven" +msgstr "ਸੱਤ" + +msgid "eight" +msgstr "ਅੱਠ" + +msgid "nine" +msgstr "ਨੌ" + +msgid "today" +msgstr "ਅੱਜ" + +msgid "tomorrow" +msgstr "ਭਲਕੇ" + +msgid "yesterday" +msgstr "ਕੱਲ੍ਹ" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "" + +msgid "now" +msgstr "ਹੁਣ" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/pl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/pl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9e8495f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/pl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/pl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/pl/LC_MESSAGES/django.po new file mode 100644 index 0000000..ab0ab92 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/pl/LC_MESSAGES/django.po @@ -0,0 +1,394 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Adam Stachowicz , 2015 +# angularcircle, 2011 +# angularcircle, 2014 +# Jannis Leidel , 2011 +# m_aciek , 2018,2021 +# Piotr Meuś , 2014 +# Roman Barczyński, 2012 +# Tomasz Kajtoch , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2021-09-23 19:40+0000\n" +"Last-Translator: m_aciek \n" +"Language-Team: Polish (http://www.transifex.com/django/django/language/pl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pl\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n" +"%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n" +"%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" + +msgid "Humanize" +msgstr "Humanizacja" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}." + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s milion" +msgstr[1] "%(value)s miliony" +msgstr[2] "%(value)s milionów" +msgstr[3] "%(value)s milionów" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s miliard" +msgstr[1] "%(value)s miliardy" +msgstr[2] "%(value)s miliardów" +msgstr[3] "%(value)s miliardów" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s kwintylion" +msgstr[1] "%(value)s biliony" +msgstr[2] "%(value)s kwintylionów" +msgstr[3] "%(value)s kwintylionów" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s kwadrylion" +msgstr[1] "%(value)s biliardy" +msgstr[2] "%(value)s kwadrylionów" +msgstr[3] "%(value)s kwadrylionów" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s trylion" +msgstr[1] "%(value)s tryliony" +msgstr[2] "%(value)s trylionyów" +msgstr[3] "%(value)s trylionyów" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] " %(value)s tryliard" +msgstr[1] "%(value)s tryliardy" +msgstr[2] "%(value)s tryliardów" +msgstr[3] "%(value)s tryliardów" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septylion" +msgstr[1] "%(value)s septyliony" +msgstr[2] "%(value)s septylionów" +msgstr[3] "%(value)s septylionów" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s kwadryliard" +msgstr[1] "%(value)s kwardyliardy" +msgstr[2] "%(value)s kwadryliardów" +msgstr[3] "%(value)s kwadryliardów" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s kwintylion" +msgstr[1] "%(value)s kwintyliony" +msgstr[2] "%(value)s kwintylionów" +msgstr[3] "%(value)s kwintylionów" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s kwintyliard" +msgstr[1] "%(value)s kwintyliardy" +msgstr[2] "%(value)s kwintyliardów" +msgstr[3] "%(value)s kwintyliardów" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" +msgstr[1] "%(value)s googole" +msgstr[2] "%(value)s googolów" +msgstr[3] "%(value)s googolów" + +msgid "one" +msgstr "jeden" + +msgid "two" +msgstr "dwa" + +msgid "three" +msgstr "trzy" + +msgid "four" +msgstr "cztery" + +msgid "five" +msgstr "pięć" + +msgid "six" +msgstr "sześć" + +msgid "seven" +msgstr "siedem" + +msgid "eight" +msgstr "osiem" + +msgid "nine" +msgstr "dziewięć" + +msgid "today" +msgstr "dzisiaj" + +msgid "tomorrow" +msgstr "jutro" + +msgid "yesterday" +msgstr "wczoraj" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s temu" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "godzinę temu" +msgstr[1] "%(count)s godziny temu" +msgstr[2] "%(count)s godzin temu" +msgstr[3] "%(count)s godzin temu" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "minutę temu" +msgstr[1] "%(count)s minuty temu" +msgstr[2] "%(count)s minut temu" +msgstr[3] "%(count)s minut temu" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "sekundę temu" +msgstr[1] "%(count)s sekundy temu" +msgstr[2] "%(count)s sekund temu" +msgstr[3] "%(count)s sekund temu" + +msgid "now" +msgstr "teraz" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "za sekundę" +msgstr[1] "za %(count)s sekundy" +msgstr[2] "za %(count)s sekund" +msgstr[3] "za %(count)s sekund" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "za minutę" +msgstr[1] "za %(count)s minuty" +msgstr[2] "za %(count)s minut" +msgstr[3] "za %(count)s minut" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "za godzinę" +msgstr[1] "za %(count)s godziny" +msgstr[2] "za %(count)s godzin" +msgstr[3] "za %(count)s godzin" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "za %(delta)s" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d rok" +msgstr[1] "%(num)d lata" +msgstr[2] "%(num)d lat" +msgstr[3] "%(num)d roku" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d miesiąc" +msgstr[1] "%(num)d miesiące" +msgstr[2] "%(num)d miesięcy" +msgstr[3] "%(num)d miesiąca" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d tydzień" +msgstr[1] "%(num)d tygodnie" +msgstr[2] "%(num)d tygodni" +msgstr[3] "%(num)d tygodnia" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dzień" +msgstr[1] "%(num)d dni" +msgstr[2] "%(num)d dni" +msgstr[3] "%(num)d dnia" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d godzinę" +msgstr[1] "%(num)d godziny" +msgstr[2] "%(num)d godzin" +msgstr[3] "%(num)d godziny" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minutę" +msgstr[1] "%(num)d minuty" +msgstr[2] "%(num)d minut" +msgstr[3] "%(num)d minuty" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d rok" +msgstr[1] "%(num)d lata" +msgstr[2] "%(num)d lat" +msgstr[3] "%(num)d roku" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d miesiąc" +msgstr[1] "%(num)d miesiące" +msgstr[2] "%(num)d miesięcy" +msgstr[3] "%(num)dmiesiąca" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d tydzień" +msgstr[1] "%(num)d tygodnie" +msgstr[2] "%(num)d tygodni" +msgstr[3] "%(num)d tygodnia" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dzień" +msgstr[1] "%(num)d dni" +msgstr[2] "%(num)d dni" +msgstr[3] "%(num)d dnia" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d godzinę" +msgstr[1] "%(num)d godziny" +msgstr[2] "%(num)d godzin" +msgstr[3] "%(num)d godziny" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minutę" +msgstr[1] "%(num)d minuty" +msgstr[2] "%(num)d minut" +msgstr[3] "%(num)d minuty" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/pt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/pt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d1c67dd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/pt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/pt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/pt/LC_MESSAGES/django.po new file mode 100644 index 0000000..8a9d8b4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/pt/LC_MESSAGES/django.po @@ -0,0 +1,398 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Henrique Azevedo , 2018 +# Jannis Leidel , 2011 +# jorgecarleitao , 2014 +# Nuno Mariz , 2012-2013,2018 +# Raúl Pedro Fernandes Santos, 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2018-12-20 15:27+0000\n" +"Last-Translator: Nuno Mariz \n" +"Language-Team: Portuguese (http://www.transifex.com/django/django/language/" +"pt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Humanizar" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}.º" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}.º" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}.º" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}.º" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}.º" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}.º" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}.º" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}.º" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}.º" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}.º" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}.º" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f milhão" +msgstr[1] "%(value).1f milhões" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s milhão" +msgstr[1] "%(value)s milhões" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f bilião" +msgstr[1] "%(value).1f biliões" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s bilião" +msgstr[1] "%(value)s biliões" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f trilião" +msgstr[1] "%(value).1f triliões" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s trilião" +msgstr[1] "%(value)s triliões" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f quadrilião" +msgstr[1] "%(value).1f quatriliões" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s quadrilião" +msgstr[1] "%(value)s quatriliões" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f quintilião" +msgstr[1] "%(value).1f quintiliões" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s quintilião" +msgstr[1] "%(value)s quintiliões" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f sextilião" +msgstr[1] "%(value).1f sextiliões" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s sextilião" +msgstr[1] "%(value)s sextiliões" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f septilião" +msgstr[1] "%(value).1f septiliões" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septilião" +msgstr[1] "%(value)s septiliões" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f octilião" +msgstr[1] "%(value).1f octiliões" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s octilião" +msgstr[1] "%(value)s octiliões" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f nonilião" +msgstr[1] "%(value).1f noniliões" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s nonilião" +msgstr[1] "%(value)s noniliões" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f decilião" +msgstr[1] "%(value).1f deciliões" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s decilião" +msgstr[1] "%(value)s deciliões" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f googol" +msgstr[1] "%(value).1f googol" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" +msgstr[1] "%(value)s googol" + +msgid "one" +msgstr "um" + +msgid "two" +msgstr "dois" + +msgid "three" +msgstr "três" + +msgid "four" +msgstr "quatro" + +msgid "five" +msgstr "cinco" + +msgid "six" +msgstr "seis" + +msgid "seven" +msgstr "sete" + +msgid "eight" +msgstr "oito" + +msgid "nine" +msgstr "nove" + +msgid "today" +msgstr "hoje" + +msgid "tomorrow" +msgstr "amanhã" + +msgid "yesterday" +msgstr "ontem" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s atrás" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "há uma hora atrás" +msgstr[1] "há %(count)s horas atrás" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "há um minuto atrás" +msgstr[1] "há %(count)s minutos atrás" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "há um segundo atrás" +msgstr[1] "há %(count)s segundos atrás" + +msgid "now" +msgstr "agora" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "daqui a um segundo" +msgstr[1] "daqui a %(count)s segundos" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "daqui a um minuto" +msgstr[1] "daqui a %(count)s minutos" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "daqui a uma hora" +msgstr[1] "daqui a %(count)s horas" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s a partir de agora" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d ano" +msgstr[1] "%d anos" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d meses" +msgstr[1] "%d meses" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d semanas" +msgstr[1] "%d semanas" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d dia" +msgstr[1] "%d dias" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d horas" +msgstr[1] "%d horas" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d minuto" +msgstr[1] "%d minutos" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d ano" +msgstr[1] "%d anos" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d mês" +msgstr[1] "%d meses" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d semana" +msgstr[1] "%d semanas" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d dia" +msgstr[1] "%d dias" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d hora" +msgstr[1] "%d horas" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d minuto" +msgstr[1] "%d minutos" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/pt_BR/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/pt_BR/LC_MESSAGES/django.mo new file mode 100644 index 0000000..eb35f0e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/pt_BR/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/pt_BR/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/pt_BR/LC_MESSAGES/django.po new file mode 100644 index 0000000..53e9b28 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/pt_BR/LC_MESSAGES/django.po @@ -0,0 +1,365 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Allisson Azevedo , 2014 +# bruno.devpod , 2014 +# Eduardo Cereto Carvalho, 2012 +# Erick Mesquita, 2023 +# semente, 2012-2013 +# Jannis Leidel , 2011 +# Rafael Fontenelle , 2022 +# Sandro , 2011 +# Francisco Petry Rauber , 2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2023-04-24 18:40+0000\n" +"Last-Translator: Erick Mesquita, 2023\n" +"Language-Team: Portuguese (Brazil) (http://www.transifex.com/django/django/" +"language/pt_BR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt_BR\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Humanize" +msgstr "Humanizar" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}º" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}º" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s milhão" +msgstr[1] "%(value)s milhões" +msgstr[2] "%(value)s milhões" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s bilhão" +msgstr[1] "%(value)s bilhões" +msgstr[2] "%(value)s bilhões" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s trilhão" +msgstr[1] "%(value)s trilhões" +msgstr[2] "%(value)s trilhões" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s quadrilhão" +msgstr[1] "%(value)s quadrilhões" +msgstr[2] "%(value)s quadrilhões" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s quintilhão" +msgstr[1] "%(value)s quintilhões" +msgstr[2] "%(value)s quintilhões" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s sextilhão" +msgstr[1] "%(value)s sextilhões" +msgstr[2] "%(value)s sextilhões" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septilhão" +msgstr[1] "%(value)s septilhões" +msgstr[2] "%(value)s septilhões" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s octilhão" +msgstr[1] "%(value)s octilhões" +msgstr[2] "%(value)s octilhões" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s nonilhão" +msgstr[1] "%(value)s nonilhões" +msgstr[2] "%(value)s nonilhões" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s decilhão" +msgstr[1] "%(value)s decilhões" +msgstr[2] "%(value)s decilhões" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" +msgstr[1] "%(value)s googol" +msgstr[2] "%(value)s googol" + +msgid "one" +msgstr "um" + +msgid "two" +msgstr "dois" + +msgid "three" +msgstr "três" + +msgid "four" +msgstr "quatro" + +msgid "five" +msgstr "cinco" + +msgid "six" +msgstr "seis" + +msgid "seven" +msgstr "sete" + +msgid "eight" +msgstr "oito" + +msgid "nine" +msgstr "nove" + +msgid "today" +msgstr "hoje" + +msgid "tomorrow" +msgstr "amanhã" + +msgid "yesterday" +msgstr "ontem" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)satrás" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "uma hora atrás" +msgstr[1] "%(count)s horas atrás" +msgstr[2] "%(count)s horas atrás" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "um minuto atrás" +msgstr[1] "%(count)s minutos atrás" +msgstr[2] "%(count)s minutos atrás" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "um segundo atrás" +msgstr[1] "%(count)s segundos atrás" +msgstr[2] "%(count)s segundos atrás" + +msgid "now" +msgstr "agora" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "um segundo a partir de agora" +msgstr[1] "%(count)s segundos a partir de agora" +msgstr[2] "%(count)s segundos a partir de agora" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "um minuto a partir de agora" +msgstr[1] "%(count)s minutos a partir de agora" +msgstr[2] "%(count)s minutos a partir de agora" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "uma hora a partir de agora" +msgstr[1] "%(count)s horas a partir de agora" +msgstr[2] "%(count)s horas a partir de agora" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s a partir de agora" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d ano" +msgstr[1] "%(num)d anos" +msgstr[2] "%(num)d anos" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mês" +msgstr[1] "%(num)d meses" +msgstr[2] "%(num)d meses" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d semana" +msgstr[1] "%(num)d semanas" +msgstr[2] "%(num)d semanas" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dia" +msgstr[1] "%(num)d dias" +msgstr[2] "%(num)d dias" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hora" +msgstr[1] "%(num)d horas" +msgstr[2] "%(num)d horas" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuto" +msgstr[1] "%(num)d minutos" +msgstr[2] "%(num)d minutos" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d ano" +msgstr[1] "%(num)d anos" +msgstr[2] "%(num)d anos" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mês" +msgstr[1] "%(num)d mses" +msgstr[2] "%(num)d meses" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d semana" +msgstr[1] "%(num)d semanas" +msgstr[2] "%(num)d semanas" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dia" +msgstr[1] "%(num)d dias" +msgstr[2] "%(num)d dias" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hora" +msgstr[1] "%(num)d horas" +msgstr[2] "%(num)d horas" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuto" +msgstr[1] "%(num)d minutos" +msgstr[2] "%(num)d minutos" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ro/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ro/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ded2647 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ro/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ro/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ro/LC_MESSAGES/django.po new file mode 100644 index 0000000..efc883a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ro/LC_MESSAGES/django.po @@ -0,0 +1,440 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bogdan Mateescu, 2018 +# Daniel Ursache-Dogariu, 2011 +# Denis Darii , 2014 +# Jannis Leidel , 2011 +# Razvan Stefanescu , 2016 +# Sorin Sbarnea, 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2018-05-18 06:45+0000\n" +"Last-Translator: Bogdan Mateescu\n" +"Language-Team: Romanian (http://www.transifex.com/django/django/language/" +"ro/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ro\n" +"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?" +"2:1));\n" + +msgid "Humanize" +msgstr "Umanizare" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "al {}-lea" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "al {}-lea" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "al {}-lea" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "al {}-lea" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "al {}-lea" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "al {}-lea" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "al {}-lea" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "al {}-lea" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "al {}-lea" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "al {}-lea" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f milion" +msgstr[1] "%(value).1f milioane" +msgstr[2] "%(value).1f de milioane" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s milion" +msgstr[1] "%(value)s milioane" +msgstr[2] "%(value)s de milioane" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f miliard" +msgstr[1] "%(value).1f miliarde" +msgstr[2] "%(value).1f de miliarde" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s miliard" +msgstr[1] "%(value)s miliarde" +msgstr[2] "%(value)s de miliarde" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f trilion" +msgstr[1] "%(value).1f trilioane" +msgstr[2] "%(value).1f de trilioane" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s trilion" +msgstr[1] "%(value)s trilioane" +msgstr[2] "%(value)s de trilioane" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f cuadrilion" +msgstr[1] "%(value).1f cuadrilioane" +msgstr[2] "%(value).1f de cuadrilioane" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s cuadrilion" +msgstr[1] "%(value)s cuadrilioane" +msgstr[2] "%(value)s de cuadrilioane" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f cuntilion" +msgstr[1] "%(value).1f cuntilioane" +msgstr[2] "%(value).1f de cuntilioane" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s cuntilion" +msgstr[1] "%(value)s cuntilioane" +msgstr[2] "%(value)s de cuntilioane" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f sextilion" +msgstr[1] "%(value).1f sextilioane" +msgstr[2] "%(value).1f de sextilioane" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s sextilion" +msgstr[1] "%(value)s sextilioane" +msgstr[2] "%(value)s de sextilioane" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f septilion" +msgstr[1] "%(value).1f septilioane" +msgstr[2] "%(value).1f de septilioane" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septilion" +msgstr[1] "%(value)s septilioane" +msgstr[2] "%(value)s de septilioane" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f octilion" +msgstr[1] "%(value).1f octilioane" +msgstr[2] "%(value).1f de octilioane" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s octilion" +msgstr[1] "%(value)s octilioane" +msgstr[2] "%(value)s de octilioane" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f nonilion" +msgstr[1] "%(value).1f nonilioane" +msgstr[2] "%(value).1f de nonilioane" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s nonilion" +msgstr[1] "%(value)s nonilioane" +msgstr[2] "%(value)s de nonilioane" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f decilion" +msgstr[1] "%(value).1f decilioane" +msgstr[2] "%(value).1f de decilioane" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s decilion" +msgstr[1] "%(value)s decilioane" +msgstr[2] "%(value)s de decilioane" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f googol" +msgstr[1] "%(value).1f googol" +msgstr[2] "%(value).1f de googol" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" +msgstr[1] "%(value)s googol" +msgstr[2] "%(value)s de googol" + +msgid "one" +msgstr "unu" + +msgid "two" +msgstr "doi" + +msgid "three" +msgstr "trei" + +msgid "four" +msgstr "patru" + +msgid "five" +msgstr "cinci" + +msgid "six" +msgstr "șase" + +msgid "seven" +msgstr "șapte" + +msgid "eight" +msgstr "opt" + +msgid "nine" +msgstr "nouă" + +msgid "today" +msgstr "astăzi" + +msgid "tomorrow" +msgstr "mâine" + +msgid "yesterday" +msgstr "ieri" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "Acum %(delta)s" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "Acum o oră" +msgstr[1] "Acum %(count)s ore" +msgstr[2] "Acum %(count)s de ore" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "Acum un minut" +msgstr[1] "Acum %(count)s minute" +msgstr[2] "Acum %(count)s de minute" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "Acum o secundă" +msgstr[1] "Acum %(count)s secunde" +msgstr[2] "Acum %(count)s de secunde" + +msgid "now" +msgstr "acum" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "Într-o secundă" +msgstr[1] "În %(count)s secunde" +msgstr[2] "În %(count)s de secunde" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "Într-un minut" +msgstr[1] "În %(count)s minute" +msgstr[2] "În %(count)s de minute" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "Într-o oră" +msgstr[1] "În %(count)s ore" +msgstr[2] "În %(count)s de ore" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "În %(delta)s" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d an" +msgstr[1] "%d ani" +msgstr[2] "%d de ani" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d lună" +msgstr[1] "%d luni" +msgstr[2] "%d de luni" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d săptămână" +msgstr[1] "%d săptămâni" +msgstr[2] "%d de săptămâni" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d zi" +msgstr[1] "%d zile" +msgstr[2] "%d de zile" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d oră" +msgstr[1] "%d ore" +msgstr[2] "%d de ore" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d minut" +msgstr[1] "%d minute" +msgstr[2] "%d de minute" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d an" +msgstr[1] "%d ani" +msgstr[2] "%d de ani" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d lună" +msgstr[1] "%d luni" +msgstr[2] "%d de luni" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d săptămână" +msgstr[1] "%d săptămâni" +msgstr[2] "%d de săptămâni" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d zi" +msgstr[1] "%d zile" +msgstr[2] "%d de zile" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d oră" +msgstr[1] "%d ore" +msgstr[2] "%d de ore" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d minut" +msgstr[1] "%d minute" +msgstr[2] "%d de minute" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ru/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ru/LC_MESSAGES/django.mo new file mode 100644 index 0000000..edd7505 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ru/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ru/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ru/LC_MESSAGES/django.po new file mode 100644 index 0000000..51839a3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ru/LC_MESSAGES/django.po @@ -0,0 +1,396 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Mingun , 2014 +# Dimmus , 2011 +# Eugene , 2012 +# Grigory Fateyev (aka greg) , 2018 +# Jannis Leidel , 2011 +# Mingun , 2014 +# SeryiMysh , 2018 +# Алексей Борискин , 2012,2014,2022 +# Bobsans , 2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2022-04-24 18:40+0000\n" +"Last-Translator: Алексей Борискин , 2012,2014,2022\n" +"Language-Team: Russian (http://www.transifex.com/django/django/language/" +"ru/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ru\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || " +"(n%100>=11 && n%100<=14)? 2 : 3);\n" + +msgid "Humanize" +msgstr "Приведение значений к виду, понятному человеку" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}-й" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}-й" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}-й" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}-й" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}-й" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}-й" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}-й" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}-й" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}-й" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}-й" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}-й" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s миллион" +msgstr[1] "%(value)s миллиона" +msgstr[2] "%(value)s миллионов" +msgstr[3] "%(value)s миллионов" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s миллиард" +msgstr[1] "%(value)s миллиарда" +msgstr[2] "%(value)s миллиардов" +msgstr[3] "%(value)s миллиардов" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s триллион" +msgstr[1] "%(value)s триллиона" +msgstr[2] "%(value)s триллионов" +msgstr[3] "%(value)s триллионов" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s квадриллион" +msgstr[1] "%(value)s квадриллиона" +msgstr[2] "%(value)s квадриллионов" +msgstr[3] "%(value)s квадриллионов" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s квинтиллион" +msgstr[1] "%(value)s квинтиллиона" +msgstr[2] "%(value)s квинтиллионов" +msgstr[3] "%(value)s квинтиллионов" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s секстиллион" +msgstr[1] "%(value)s секстиллиона" +msgstr[2] "%(value)s секстиллионов" +msgstr[3] "%(value)s секстиллионов" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s септиллион" +msgstr[1] "%(value)s септиллиона" +msgstr[2] "%(value)s септиллионов" +msgstr[3] "%(value)s септиллионов" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s октиллион" +msgstr[1] "%(value)s октиллиона" +msgstr[2] "%(value)s октиллионов" +msgstr[3] "%(value)s октиллионов" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s нониллион" +msgstr[1] "%(value)s нониллиона" +msgstr[2] "%(value)s нониллионов" +msgstr[3] "%(value)s нониллионов" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s дециллион" +msgstr[1] "%(value)s дециллиона" +msgstr[2] "%(value)s дециллионов" +msgstr[3] "%(value)s дециллионов" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s гугол" +msgstr[1] "%(value)s гугола" +msgstr[2] "%(value)s гуголов" +msgstr[3] "%(value)s гуголов" + +msgid "one" +msgstr "один" + +msgid "two" +msgstr "два" + +msgid "three" +msgstr "три" + +msgid "four" +msgstr "четыре" + +msgid "five" +msgstr "пять" + +msgid "six" +msgstr "шесть" + +msgid "seven" +msgstr "семь" + +msgid "eight" +msgstr "восемь" + +msgid "nine" +msgstr "девять" + +msgid "today" +msgstr "сегодня" + +msgid "tomorrow" +msgstr "завтра" + +msgid "yesterday" +msgstr "вчера" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s назад" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "%(count)s час назад" +msgstr[1] "%(count)s часа назад" +msgstr[2] "%(count)s часов назад" +msgstr[3] "%(count)s часов назад" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "%(count)s минуту назад" +msgstr[1] "%(count)s минуты назад" +msgstr[2] "%(count)s минут назад" +msgstr[3] "%(count)s минут назад" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "%(count)s секунду назад" +msgstr[1] "%(count)s секунды назад" +msgstr[2] "%(count)s секунд назад" +msgstr[3] "%(count)s секунд назад" + +msgid "now" +msgstr "сейчас" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "через %(count)s секунду" +msgstr[1] "через %(count)s секунды" +msgstr[2] "через %(count)s секунд" +msgstr[3] "через %(count)s секунд" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "через %(count)s минуту" +msgstr[1] "через %(count)s минуты" +msgstr[2] "через %(count)s минут" +msgstr[3] "через %(count)s минут" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "через %(count)s час" +msgstr[1] "через %(count)s часа" +msgstr[2] "через %(count)s часов" +msgstr[3] "через %(count)s часов" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "через %(delta)s" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d год" +msgstr[1] "%(num)d года" +msgstr[2] "%(num)d лет" +msgstr[3] "%(num)d лет" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d месяц" +msgstr[1] "%(num)d месяца" +msgstr[2] "%(num)d месяцев" +msgstr[3] "%(num)d месяцев" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d неделю" +msgstr[1] "%(num)d недели" +msgstr[2] "%(num)d недель" +msgstr[3] "%(num)d недель" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d день" +msgstr[1] "%(num)d дня" +msgstr[2] "%(num)d дней" +msgstr[3] "%(num)d дней" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d час" +msgstr[1] "%(num)d часа" +msgstr[2] "%(num)d часов" +msgstr[3] "%(num)d часов" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d минуту" +msgstr[1] "%(num)d минуты" +msgstr[2] "%(num)d минут" +msgstr[3] "%(num)d минут" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d год" +msgstr[1] "%(num)d года" +msgstr[2] "%(num)d лет" +msgstr[3] "%(num)d лет" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d месяц" +msgstr[1] "%(num)d месяца" +msgstr[2] "%(num)d месяцев" +msgstr[3] "%(num)d месяцев" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d неделю" +msgstr[1] "%(num)d недели" +msgstr[2] "%(num)d недель" +msgstr[3] "%(num)d недель" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d день" +msgstr[1] "%(num)d дня" +msgstr[2] "%(num)d дней" +msgstr[3] "%(num)d дней" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d час" +msgstr[1] "%(num)d часа" +msgstr[2] "%(num)d часов" +msgstr[3] "%(num)d часов" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d минуту" +msgstr[1] "%(num)d минуты" +msgstr[2] "%(num)d минут" +msgstr[3] "%(num)d минут" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..561afb1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sk/LC_MESSAGES/django.po new file mode 100644 index 0000000..5591cae --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sk/LC_MESSAGES/django.po @@ -0,0 +1,390 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Adam Zahradník, 2023 +# Claude Paroz , 2013 +# Jannis Leidel , 2011 +# Marian Andre , 2012-2013 +# Martin Tóth , 2017-2019,2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:40+0000\n" +"Last-Translator: Martin Tóth , 2017-2019,2023\n" +"Language-Team: Slovak (http://app.transifex.com/django/django/language/sk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n " +">= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);\n" + +msgid "Humanize" +msgstr "Poľudštenie" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 3, e.g. 83rd, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}." + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s milión" +msgstr[1] "%(value)s milióny" +msgstr[2] "%(value)s miliónov" +msgstr[3] "%(value)s miliónov" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s miliarda" +msgstr[1] "%(value)s miliardy" +msgstr[2] "%(value)s miliárd" +msgstr[3] "%(value)s miliárd" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s bilión" +msgstr[1] "%(value)s bilióny" +msgstr[2] "%(value)s biliónov" +msgstr[3] "%(value)s biliónov" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s biliarda" +msgstr[1] "%(value)s biliardy" +msgstr[2] "%(value)s biliárd" +msgstr[3] "%(value)s biliárd" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s trilión" +msgstr[1] "%(value)s trilióny" +msgstr[2] "%(value)s triliónov" +msgstr[3] "%(value)s triliónov" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s triliarda" +msgstr[1] "%(value)s triliardy" +msgstr[2] "%(value)s triliárd" +msgstr[3] "%(value)s triliárd" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s kvadrilión" +msgstr[1] "%(value)s kvadrilióny" +msgstr[2] "%(value)s kvadriliónov" +msgstr[3] "%(value)s kvadriliónov" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s kvadriliarda" +msgstr[1] "%(value)s kvadriliardy" +msgstr[2] "%(value)s kvadriliárd" +msgstr[3] "%(value)s kvadriliárd" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s kvintilión" +msgstr[1] "%(value)s kvintilióny" +msgstr[2] "%(value)s kvintiliónov" +msgstr[3] "%(value)s kvintiliónov" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s kvintiliarda" +msgstr[1] "%(value)s kvintiliardy" +msgstr[2] "%(value)s kvintiliárd" +msgstr[3] "%(value)s kvintiliárd" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" +msgstr[1] "%(value)s googol" +msgstr[2] "%(value)s googol" +msgstr[3] "%(value)s googol" + +msgid "one" +msgstr "jeden" + +msgid "two" +msgstr "dva" + +msgid "three" +msgstr "tri" + +msgid "four" +msgstr "štyri" + +msgid "five" +msgstr "päť" + +msgid "six" +msgstr "šesť" + +msgid "seven" +msgstr "sedem" + +msgid "eight" +msgstr "osem" + +msgid "nine" +msgstr "deväť" + +msgid "today" +msgstr "dnes" + +msgid "tomorrow" +msgstr "zajtra" + +msgid "yesterday" +msgstr "včera" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "pred %(delta)s" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "pred hodinou" +msgstr[1] "pred %(count)s hodinami" +msgstr[2] "pred %(count)s hodinami" +msgstr[3] "pred %(count)s hodinami" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "pred minútou" +msgstr[1] "pred %(count)s minútami" +msgstr[2] "pred %(count)s minútami" +msgstr[3] "pred %(count)s minútami" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "pred sekundou" +msgstr[1] "pred %(count)s sekundami" +msgstr[2] "pred %(count)s sekundami" +msgstr[3] "pred %(count)s sekundami" + +msgid "now" +msgstr "teraz" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "o sekundu" +msgstr[1] "o %(count)s sekundy" +msgstr[2] "o %(count)s sekúnd" +msgstr[3] "o %(count)s sekúnd" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "o minútu" +msgstr[1] "o %(count)s minúty" +msgstr[2] "o %(count)s minút" +msgstr[3] "o %(count)s minút" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "o hodinu" +msgstr[1] "o %(count)s hodiny" +msgstr[2] "o %(count)s hodín" +msgstr[3] "o %(count)s hodín" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "o %(delta)s" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d rokom" +msgstr[1] "%(num)d rokmi" +msgstr[2] "%(num)d rokmi" +msgstr[3] "%(num)d rokmi" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mesiacom" +msgstr[1] "%(num)d mesiacmi" +msgstr[2] "%(num)d mesiacmi" +msgstr[3] "%(num)d mesiacmi" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d týždňom" +msgstr[1] "%(num)d týždňami" +msgstr[2] "%(num)d týždňami" +msgstr[3] "%(num)d týždňami" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dňom" +msgstr[1] "%(num)d dňami" +msgstr[2] "%(num)d dňami" +msgstr[3] "%(num)d dňami" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hodinou" +msgstr[1] "%(num)d hodinami" +msgstr[2] "%(num)d hodinami" +msgstr[3] "%(num)d hodinami" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minútou" +msgstr[1] "%(num)d minútami" +msgstr[2] "%(num)d minútami" +msgstr[3] "%(num)d minútami" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d rok" +msgstr[1] "%(num)d roky" +msgstr[2] "%(num)d rokov" +msgstr[3] "%(num)d rokov" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mesiac" +msgstr[1] "%(num)d mesiace" +msgstr[2] "%(num)d mesiacov" +msgstr[3] "%(num)d mesiacov" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d týždeň" +msgstr[1] "%(num)d týždne" +msgstr[2] "%(num)d týždňov" +msgstr[3] "%(num)d týždňov" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d deň" +msgstr[1] "%(num)d dni" +msgstr[2] "%(num)d dní" +msgstr[3] "%(num)d dní" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d hodinu" +msgstr[1] "%(num)d hodiny" +msgstr[2] "%(num)d hodín" +msgstr[3] "%(num)d hodín" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minútu" +msgstr[1] "%(num)d minúty" +msgstr[2] "%(num)d minút" +msgstr[3] "%(num)d minút" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2526b74 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sl/LC_MESSAGES/django.po new file mode 100644 index 0000000..3d50a93 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sl/LC_MESSAGES/django.po @@ -0,0 +1,392 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Andrej Marsetič, 2022-2023 +# Jannis Leidel , 2011 +# Jure Cuhalev , 2011 +# Primoz Verdnik , 2013-2014 +# zejn , 2016 +# zejn , 2011,2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:40+0000\n" +"Last-Translator: Andrej Marsetič, 2022-2023\n" +"Language-Team: Slovenian (http://app.transifex.com/django/django/language/" +"sl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sl\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || " +"n%100==4 ? 2 : 3);\n" + +msgid "Humanize" +msgstr "Počloveči" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "" + +#. Translators: Ordinal format when value ends with 3, e.g. 83rd, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s milijon" +msgstr[1] "%(value)s milijona" +msgstr[2] "%(value)s milijoni" +msgstr[3] "%(value)s milijonov" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s miljarda" +msgstr[1] "%(value)s miljardi" +msgstr[2] "%(value)s miljarde" +msgstr[3] "%(value)s miljard" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s triljon" +msgstr[1] "%(value)s triljona" +msgstr[2] "%(value)s triljoni" +msgstr[3] "%(value)s triljonov" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s kvadrilijon" +msgstr[1] "%(value)s kvadrilijona" +msgstr[2] "%(value)s kvadrilijoni" +msgstr[3] "%(value)s kvadrilijonov" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s kvintilijon" +msgstr[1] "%(value)s kvintilijona" +msgstr[2] "%(value)s kvintilijoni" +msgstr[3] "%(value)s kvintilijonov" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s sekstilijon" +msgstr[1] "%(value)s sekstilijona" +msgstr[2] "%(value)s sekstilijoni" +msgstr[3] "%(value)s sekstilijonov" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septilijon" +msgstr[1] "%(value)s septilijona" +msgstr[2] "%(value)s septilijoni" +msgstr[3] "%(value)s septilijonov" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s oktilijon" +msgstr[1] "%(value)s oktilijona" +msgstr[2] "%(value)s oktilijoni" +msgstr[3] "%(value)s oktilijonov" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s nonilijon" +msgstr[1] "%(value)s nonilijona" +msgstr[2] "%(value)s nonilijoni" +msgstr[3] "%(value)s nonilijonov" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s decilijon" +msgstr[1] "%(value)s decilijona" +msgstr[2] "%(value)s decilijoni" +msgstr[3] "%(value)s decilijonov" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s gugol" +msgstr[1] "%(value)s gugola" +msgstr[2] "%(value)s gugoli" +msgstr[3] "%(value)s gugolov" + +msgid "one" +msgstr "ena" + +msgid "two" +msgstr "dve" + +msgid "three" +msgstr "tri" + +msgid "four" +msgstr "štiri" + +msgid "five" +msgstr "pet" + +msgid "six" +msgstr "šest" + +msgid "seven" +msgstr "sedem" + +msgid "eight" +msgstr "osem" + +msgid "nine" +msgstr "devet" + +msgid "today" +msgstr "danes" + +msgid "tomorrow" +msgstr "jutri" + +msgid "yesterday" +msgstr "včeraj" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "pred %(delta)s" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "pred %(count)s uro" +msgstr[1] "pred %(count)s urama" +msgstr[2] "pred %(count)s urami" +msgstr[3] "pred %(count)s urami" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "pred %(count)s minuto" +msgstr[1] "pred %(count)s minutama" +msgstr[2] "pred %(count)s minutami" +msgstr[3] "pred %(count)s minutami" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "pred %(count)s sekundo" +msgstr[1] "pred %(count)s sekundama" +msgstr[2] "pred %(count)s sekundami" +msgstr[3] "pred %(count)s sekundami" + +msgid "now" +msgstr "zdaj" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "čez %(count)s sekundo" +msgstr[1] "čez %(count)s sekundi" +msgstr[2] "čez %(count)s sekunde" +msgstr[3] "čez %(count)s sekund" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "čez %(count)s minuto" +msgstr[1] "čez %(count)s minuti" +msgstr[2] "čez %(count)s minute" +msgstr[3] "čez %(count)s minut" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "čez %(count)s uro" +msgstr[1] "čez %(count)s uri" +msgstr[2] "čez %(count)s ure" +msgstr[3] "čez %(count)s ur" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)sod zdaj" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d leto" +msgstr[1] "%(num)d leti" +msgstr[2] "%(num)d let" +msgstr[3] "%(num)d let" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mesec" +msgstr[1] "%(num)d meseca" +msgstr[2] "%(num)d mesecev" +msgstr[3] "%(num)d mesecev" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d teden" +msgstr[1] "%(num)d tedna" +msgstr[2] "%(num)d tednov" +msgstr[3] "%(num)d tednov" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dan" +msgstr[1] "%(num)d dneva" +msgstr[2] "%(num)d dni" +msgstr[3] "%(num)d dni" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d ura" +msgstr[1] "%(num)d uri" +msgstr[2] "%(num)d ur" +msgstr[3] "%(num)d ur" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuta" +msgstr[1] "%(num)d minuti" +msgstr[2] "%(num)d minut" +msgstr[3] "%(num)d minut" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d leto" +msgstr[1] "%(num)d leti" +msgstr[2] "%(num)d let" +msgstr[3] "%(num)d let" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d mesec" +msgstr[1] "%(num)d meseca" +msgstr[2] "%(num)d mesecev" +msgstr[3] "%(num)d mesecev" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d teden" +msgstr[1] "%(num)d tedena" +msgstr[2] "%(num)d tedne" +msgstr[3] "%(num)d tedne" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dan" +msgstr[1] "%(num)d dneva" +msgstr[2] "%(num)d dni" +msgstr[3] "%(num)d dni" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d ura" +msgstr[1] "%(num)d uri" +msgstr[2] "%(num)d ure" +msgstr[3] "%(num)d ure" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minuta" +msgstr[1] "%(num)d minuti" +msgstr[2] "%(num)d minut" +msgstr[3] "%(num)d minut" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sq/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sq/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f7e3c3b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sq/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sq/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sq/LC_MESSAGES/django.po new file mode 100644 index 0000000..a62e51f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sq/LC_MESSAGES/django.po @@ -0,0 +1,395 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Besnik , 2011,2015 +# Besnik , 2015,2018-2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2019-03-12 07:59+0000\n" +"Last-Translator: Besnik \n" +"Language-Team: Albanian (http://www.transifex.com/django/django/language/" +"sq/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sq\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Jepi Formë Njerëzore" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "-të" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "-të" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "-të" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "-të" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "-të" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "-të" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "-të" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "-të" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "-të" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "-të" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f milion" +msgstr[1] "%(value).1f milionë" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s milion" +msgstr[1] "%(value)s milionë" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f miliard" +msgstr[1] "%(value).1f miliardë" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s miliard" +msgstr[1] "%(value)s miliardë" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f trilion" +msgstr[1] "%(value).1f trilionë" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s trilion" +msgstr[1] "%(value)s trilionë" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f kuadrilion" +msgstr[1] "%(value).1f kuadrilionë" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s kuadrilion" +msgstr[1] "%(value)s kuadrilionë" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f kuintilion" +msgstr[1] "%(value).1f kuintilionë" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s kuintilionë" +msgstr[1] "%(value)s kuintilionë" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f sestilion" +msgstr[1] "%(value).1f sestilionë" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s sestilion" +msgstr[1] "%(value)s sestilionë" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f septilion" +msgstr[1] "%(value).1f septilionë" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septilion" +msgstr[1] "%(value)s septilionë" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f oktilion" +msgstr[1] "%(value).1f oktilionë" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s oktilion" +msgstr[1] "%(value)s oktilionë" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f nonilion" +msgstr[1] "%(value).1f nonilionë" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s nonilion" +msgstr[1] "%(value)s nonilionë" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f decilion" +msgstr[1] "%(value).1f decilionë" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s decilion" +msgstr[1] "%(value)s decilionë" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f gugol" +msgstr[1] "%(value).1f gugolë" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s gugol" +msgstr[1] "%(value)s gugolë" + +msgid "one" +msgstr "një" + +msgid "two" +msgstr "dy" + +msgid "three" +msgstr "tre" + +msgid "four" +msgstr "katër" + +msgid "five" +msgstr "pesë" + +msgid "six" +msgstr "gjashtë" + +msgid "seven" +msgstr "shtatë" + +msgid "eight" +msgstr "tetë" + +msgid "nine" +msgstr "nëntë" + +msgid "today" +msgstr "sot" + +msgid "tomorrow" +msgstr "nesër" + +msgid "yesterday" +msgstr "dje" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s më parë" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "një orë më parë" +msgstr[1] "%(count)s orë më parë" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "një minutë më parë" +msgstr[1] "%(count)s minuta më parë" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "një sekondë më parë" +msgstr[1] "%(count)s sekonda më parë" + +msgid "now" +msgstr "tani" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "një sekondë më parë" +msgstr[1] "%(count)s sekonda më parë" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "për një minutë" +msgstr[1] "për %(count)s minuta" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "për një orë" +msgstr[1] "për %(count)s orë" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s nga tani" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d vit" +msgstr[1] "%d vjet" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d muaj" +msgstr[1] "%d muaj" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d javë" +msgstr[1] "%d javë" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d ditë" +msgstr[1] "%d ditë" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d orë" +msgstr[1] "%d orë" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d minutë" +msgstr[1] "%d minuta" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d vit" +msgstr[1] "%d vjet" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d muaj" +msgstr[1] "%d muaj" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d javë" +msgstr[1] "%d javë" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d ditë" +msgstr[1] "%d ditë" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d orë" +msgstr[1] "%d orë" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d minutë" +msgstr[1] "%d minuta" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..df50722 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sr/LC_MESSAGES/django.po new file mode 100644 index 0000000..f7726cc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sr/LC_MESSAGES/django.po @@ -0,0 +1,359 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Branko Kokanovic , 2018 +# Igor Jerosimić, 2021,2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:40+0000\n" +"Last-Translator: Igor Jerosimić, 2021,2023\n" +"Language-Team: Serbian (http://app.transifex.com/django/django/language/" +"sr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Humanize" +msgstr "Улепшавање" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}-ти" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}-ти" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}-и" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}-и" + +#. Translators: Ordinal format when value ends with 3, e.g. 83rd, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}-и" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}-и" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}-и" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}-и" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}-и" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}-и" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}-и" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s милион" +msgstr[1] "%(value)s милиона" +msgstr[2] "%(value)s милиона" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s милијарда" +msgstr[1] "%(value)s милијарде" +msgstr[2] "%(value)s милијарди" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s билион" +msgstr[1] "%(value)s билиона" +msgstr[2] "%(value)s билиона" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s билијарда" +msgstr[1] "%(value)s билијарде" +msgstr[2] "%(value)s билијарди" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s трилион" +msgstr[1] "%(value)s трилиона" +msgstr[2] "%(value)s трилиона" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s трилијарда" +msgstr[1] "%(value)s трилијарде" +msgstr[2] "%(value)s трилијарди" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)sквадрилион " +msgstr[1] "%(value)sквадрилиона " +msgstr[2] "%(value)sквадрилиона " + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)sквадрилијарда " +msgstr[1] "%(value)sквадрилијарде " +msgstr[2] "%(value)sквадрилијарди " + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)sквантилион " +msgstr[1] "%(value)sквантилиона " +msgstr[2] "%(value)sквантилиона " + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)sквантилијарда " +msgstr[1] "%(value)sквантилијарде " +msgstr[2] "%(value)sквантилијарди " + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s гугол" +msgstr[1] "%(value)s гугола" +msgstr[2] "%(value)s гугола" + +msgid "one" +msgstr "један" + +msgid "two" +msgstr "два" + +msgid "three" +msgstr "три" + +msgid "four" +msgstr "четири" + +msgid "five" +msgstr "пет" + +msgid "six" +msgstr "шест" + +msgid "seven" +msgstr "седам" + +msgid "eight" +msgstr "осам" + +msgid "nine" +msgstr "девет" + +msgid "today" +msgstr "данас" + +msgid "tomorrow" +msgstr "сутра" + +msgid "yesterday" +msgstr "јуче" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "пре %(delta)s" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "пре %(count)s сата" +msgstr[1] "пре %(count)s сата" +msgstr[2] "пре %(count)s сати" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "пре %(count)s минута" +msgstr[1] "пре %(count)s минута" +msgstr[2] "пре %(count)s минута" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "пре %(count)s секунде" +msgstr[1] "пре %(count)s секунде" +msgstr[2] "пре %(count)s секунди" + +msgid "now" +msgstr "сада" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "%(count)s секунда од сад" +msgstr[1] "%(count)s секунде од сада" +msgstr[2] "%(count)s секунди од сада" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "%(count)s минут од сад" +msgstr[1] "%(count)s минута од сада" +msgstr[2] "%(count)s минута од сада" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "%(count)s сат од сад" +msgstr[1] "%(count)s сата од сада" +msgstr[2] "%(count)s сати од сада" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s од сад" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d година" +msgstr[1] "%(num)d године" +msgstr[2] "%(num)d година" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d месец" +msgstr[1] "%(num)d месеца" +msgstr[2] "%(num)d месеци" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d недеља" +msgstr[1] "%(num)d недеље" +msgstr[2] "%(num)d недеља" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d дан" +msgstr[1] "%(num)d дана" +msgstr[2] "%(num)d дана" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d сат" +msgstr[1] "%(num)d сата" +msgstr[2] "%(num)d сати" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d минут" +msgstr[1] "%(num)d минута" +msgstr[2] "%(num)d минута" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d година" +msgstr[1] "%(num)d године" +msgstr[2] "%(num)d година" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d месец" +msgstr[1] "%(num)d месеца" +msgstr[2] "%(num)d месеци" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d недеља" +msgstr[1] "%(num)d недеље" +msgstr[2] "%(num)d недеља" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d дан" +msgstr[1] "%(num)d дана" +msgstr[2] "%(num)d дана" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d сат" +msgstr[1] "%(num)d сата" +msgstr[2] "%(num)d сати" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d минут" +msgstr[1] "%(num)d минута" +msgstr[2] "%(num)d минута" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sr_Latn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sr_Latn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e40470b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sr_Latn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sr_Latn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sr_Latn/LC_MESSAGES/django.po new file mode 100644 index 0000000..02cf707 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sr_Latn/LC_MESSAGES/django.po @@ -0,0 +1,358 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Igor Jerosimić, 2021,2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:40+0000\n" +"Last-Translator: Igor Jerosimić, 2021,2023\n" +"Language-Team: Serbian (Latin) (http://app.transifex.com/django/django/" +"language/sr@latin/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr@latin\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Humanize" +msgstr "Humanizovanje" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}-ti" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}-ti" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "" + +#. Translators: Ordinal format when value ends with 3, e.g. 83rd, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +msgid "one" +msgstr "jedan" + +msgid "two" +msgstr "dva" + +msgid "three" +msgstr "tri" + +msgid "four" +msgstr "četiri" + +msgid "five" +msgstr "pet" + +msgid "six" +msgstr "šest" + +msgid "seven" +msgstr "sedam" + +msgid "eight" +msgstr "osam" + +msgid "nine" +msgstr "devet" + +msgid "today" +msgstr "danas" + +msgid "tomorrow" +msgstr "sutra" + +msgid "yesterday" +msgstr "juče" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +msgid "now" +msgstr "sada" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sv/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sv/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a670a62 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sv/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sv/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sv/LC_MESSAGES/django.po new file mode 100644 index 0000000..eda2164 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sv/LC_MESSAGES/django.po @@ -0,0 +1,335 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Albin Larsson , 2022 +# Andreas Pelme , 2011-2012,2014 +# Elias Johnstone , 2022 +# Jannis Leidel , 2011 +# Johan Rohdin, 2021 +# Jonathan Lindén, 2014 +# Petter Strandmark , 2019 +# Rasmus Précenth , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2022-07-24 18:40+0000\n" +"Last-Translator: Elias Johnstone \n" +"Language-Team: Swedish (http://www.transifex.com/django/django/language/" +"sv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sv\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Humanisera" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}:e" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}:e" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}:a" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}:a" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}:e" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}:e" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}:e" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}:e" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}:e" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}:e" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}:e" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s miljon" +msgstr[1] "%(value)s miljoner" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s miljard" +msgstr[1] "%(value)s miljarder" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s triljon" +msgstr[1] "%(value)s triljoner" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s biljard" +msgstr[1] "%(value)s biljarder" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s kvintiljon" +msgstr[1] "%(value)s kvintiljoner" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s triljard" +msgstr[1] "%(value)s triljarder" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s kvadriljon" +msgstr[1] "%(value)s kvadriljoner" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s kvadriljard" +msgstr[1] "%(value)s kvadriljarder" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s kvintiljon" +msgstr[1] "%(value)s kvintiljoner" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s kvintiljard" +msgstr[1] "%(value)s kvintiljarder" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" +msgstr[1] "%(value)s googoler" + +msgid "one" +msgstr "ett" + +msgid "two" +msgstr "två" + +msgid "three" +msgstr "tre" + +msgid "four" +msgstr "fyra" + +msgid "five" +msgstr "fem" + +msgid "six" +msgstr "sex" + +msgid "seven" +msgstr "sju" + +msgid "eight" +msgstr "åtta" + +msgid "nine" +msgstr "nio" + +msgid "today" +msgstr "i dag" + +msgid "tomorrow" +msgstr "i morgon" + +msgid "yesterday" +msgstr "i går" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s sedan" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "en timme sedan" +msgstr[1] "%(count)s timmar sedan" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "en minut sedan" +msgstr[1] "%(count)s minuter sedan" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "en sekund sedan" +msgstr[1] "%(count)s sekunder sedan" + +msgid "now" +msgstr "nu" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "en sekund från nu" +msgstr[1] "om %(count)s sekunder" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "en minut från nu" +msgstr[1] "om %(count)s minuter" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "en timme från nu" +msgstr[1] "om %(count)s timmar" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "om %(delta)s" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d år" +msgstr[1] "%(num)d år" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d månad" +msgstr[1] "%(num)d månader" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d vecka" +msgstr[1] "%(num)d veckor" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dag" +msgstr[1] "%(num)d dagar" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d timme" +msgstr[1] "%(num)d timmar" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minut" +msgstr[1] "%(num)d minuter" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d år" +msgstr[1] "%(num)d år" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d månad" +msgstr[1] "%(num)d månader" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d vecka" +msgstr[1] "%(num)d veckor" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d dag" +msgstr[1] "%(num)d dagar" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d timme" +msgstr[1] "%(num)d timmar" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minut" +msgstr[1] "%(num)d minuter" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sw/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sw/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c0b7891 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sw/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sw/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sw/LC_MESSAGES/django.po new file mode 100644 index 0000000..5852ab3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/sw/LC_MESSAGES/django.po @@ -0,0 +1,262 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Machaku , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Swahili (http://www.transifex.com/django/django/language/" +"sw/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sw\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Weka kibinadamu" + +msgid "th" +msgstr " " + +msgid "st" +msgstr " " + +msgid "nd" +msgstr " " + +msgid "rd" +msgstr " " + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "milioni %(value).1f" +msgstr[1] "milioni %(value).1f" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "milioni %(value)s" +msgstr[1] "milioni %(value)s" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "bilioni %(value).1f" +msgstr[1] "bilioni %(value).1f" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "bilioni %(value)s" +msgstr[1] "bilioni %(value)s" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "trilioni %(value).1f" +msgstr[1] "trilioni %(value).1f" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "trilioni %(value)s" +msgstr[1] "trilioni %(value)s" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "kuadrilioni %(value).1f" +msgstr[1] "kuadrilioni %(value).1f" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "kuadrilioni %(value)s" +msgstr[1] "kuadrilioni %(value)s" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "kuintilioni %(value).1f" +msgstr[1] "kuintilioni %(value).1f" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "kuintilioni %(value)s" +msgstr[1] "kuintilioni %(value)s" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "seksitilioni %(value).1f" +msgstr[1] "seksitilioni %(value).1f" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "seksitilioni %(value)s" +msgstr[1] "seksitilioni %(value)s" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "septilioni %(value).1f" +msgstr[1] "septilioni %(value).1f" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "septilioni %(value)s" +msgstr[1] "septilioni %(value)s" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f oktilioni" +msgstr[1] "%(value).1f oktilioni" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "oktilioni %(value)s" +msgstr[1] "oktilioni %(value)s" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "nonilioni %(value).1f" +msgstr[1] "nonilioni %(value).1f" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "nonilioni %(value)s" +msgstr[1] "nonilioni %(value)s" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "desilioni %(value).1f" +msgstr[1] "desilioni %(value).1f" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "desilioni %(value)s" +msgstr[1] "desilioni %(value)s" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "gogoli %(value).1f" +msgstr[1] "gogoli %(value).1f" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "gogoli %(value)s" +msgstr[1] "gogoli %(value)s" + +msgid "one" +msgstr "moja" + +msgid "two" +msgstr "mbili" + +msgid "three" +msgstr "tatu" + +msgid "four" +msgstr "nne" + +msgid "five" +msgstr "tano" + +msgid "six" +msgstr "sita" + +msgid "seven" +msgstr "saba" + +msgid "eight" +msgstr "nane" + +msgid "nine" +msgstr "tisa" + +msgid "today" +msgstr "leo" + +msgid "tomorrow" +msgstr "kesho" + +msgid "yesterday" +msgstr "jana" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "%(delta)s zilizopita" + +msgid "now" +msgstr "sasa" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "Sekunde iliyopita" +msgstr[1] "Sekunde %(count)s zilizopita" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "Dakika iliyopita" +msgstr[1] "Dakika %(count)s zilizopita" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "Saa lililopita" +msgstr[1] "Masaa %(count)s yaliyopita" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "%(delta)s kutoka sasa" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "Sekunde moja kutoka sasa" +msgstr[1] "Sekunde %(count)s kutoka sasa" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "Dakika moja kutoka sasa" +msgstr[1] "Dakika %(count)s kutoka sasa" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "Saa limoja kutoka sasa " +msgstr[1] "Masaa %(count)s kutoka sasa" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ta/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ta/LC_MESSAGES/django.mo new file mode 100644 index 0000000..77e9f9b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ta/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ta/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ta/LC_MESSAGES/django.po new file mode 100644 index 0000000..36a253d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ta/LC_MESSAGES/django.po @@ -0,0 +1,261 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:12+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Tamil (http://www.transifex.com/projects/p/django/language/" +"ta/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ta\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "" + +msgid "th" +msgstr "" + +msgid "st" +msgstr "" + +msgid "nd" +msgstr "" + +msgid "rd" +msgstr "" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "" +msgstr[1] "" + +msgid "one" +msgstr "" + +msgid "two" +msgstr "" + +msgid "three" +msgstr "" + +msgid "four" +msgstr "" + +msgid "five" +msgstr "" + +msgid "six" +msgstr "" + +msgid "seven" +msgstr "" + +msgid "eight" +msgstr "" + +msgid "nine" +msgstr "" + +msgid "today" +msgstr "" + +msgid "tomorrow" +msgstr "" + +msgid "yesterday" +msgstr "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "" + +msgid "now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/te/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/te/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e7439a3 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/te/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/te/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/te/LC_MESSAGES/django.po new file mode 100644 index 0000000..ad1ccdb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/te/LC_MESSAGES/django.po @@ -0,0 +1,262 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# bhaskar teja yerneni , 2011 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Telugu (http://www.transifex.com/django/django/language/te/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: te\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "" + +msgid "th" +msgstr "వ" + +msgid "st" +msgstr "వ" + +msgid "nd" +msgstr "వ" + +msgid "rd" +msgstr "వ" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "" +msgstr[1] "" + +msgid "one" +msgstr "ఒక్కటి" + +msgid "two" +msgstr "రెండు" + +msgid "three" +msgstr "మూడు" + +msgid "four" +msgstr "నాలుగు" + +msgid "five" +msgstr "ఐదు" + +msgid "six" +msgstr "ఆరు" + +msgid "seven" +msgstr "ఏడు" + +msgid "eight" +msgstr "ఎనిమిది " + +msgid "nine" +msgstr "తొమ్మిది" + +msgid "today" +msgstr "ఈ రోజు" + +msgid "tomorrow" +msgstr "రెపు" + +msgid "yesterday" +msgstr "నిన్న" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "%(delta)s క్రితము" + +msgid "now" +msgstr "ఇప్పుడు " + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "ఇప్పటినుండి %(delta)s కు" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/tg/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/tg/LC_MESSAGES/django.mo new file mode 100644 index 0000000..76b769b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/tg/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/tg/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/tg/LC_MESSAGES/django.po new file mode 100644 index 0000000..de792ea --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/tg/LC_MESSAGES/django.po @@ -0,0 +1,393 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Surush Sufiew , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2020-05-15 00:31+0000\n" +"Last-Translator: Surush Sufiew \n" +"Language-Team: Tajik (http://www.transifex.com/django/django/language/tg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Ба шакли оммафаҳм овардани қимат" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}-ум" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}-ум" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}-ум" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}-ум" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}-ум" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}-ум" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}-ум" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}-ум" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}-ум" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}-ум" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}-ум" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "" +msgstr[1] "" + +msgid "one" +msgstr "як" + +msgid "two" +msgstr "ду" + +msgid "three" +msgstr "се" + +msgid "four" +msgstr "чор" + +msgid "five" +msgstr "панҷ" + +msgid "six" +msgstr "шаш" + +msgid "seven" +msgstr "ҳафт" + +msgid "eight" +msgstr "ҳашт" + +msgid "nine" +msgstr "нуҳ" + +msgid "today" +msgstr "имрӯз" + +msgid "tomorrow" +msgstr "пагоҳ" + +msgid "yesterday" +msgstr "дирӯз" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s пеш" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" +msgstr[1] "" + +msgid "now" +msgstr "ҳозир" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "баъд аз %(delta)s" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" +msgstr[1] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/th/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/th/LC_MESSAGES/django.mo new file mode 100644 index 0000000..6c11ee0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/th/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/th/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/th/LC_MESSAGES/django.po new file mode 100644 index 0000000..e713265 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/th/LC_MESSAGES/django.po @@ -0,0 +1,357 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Kowit Charoenratchatabhan , 2012,2018 +# Perry Roper , 2017 +# sipp11 , 2014 +# Vichai Vongvorakul , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2018-05-18 01:38+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Thai (http://www.transifex.com/django/django/language/th/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: th\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Humanize" +msgstr "ทำเป็นภาษามนุษย์" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f หนึ่งล้าน" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s ล้าน" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f สิบล้าน" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s พันล้าน" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f ร้อยล้าน" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] " %(value)s ล้านล้าน" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f quadrillion" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s quadrillion" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f quintillion" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s quintillion" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f sextillion" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s sextillion" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f septillion" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septillion" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f octillion" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s octillion" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f nonillion" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s nonillion" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f decillion" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s decillion" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f googol" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" + +msgid "one" +msgstr "หนึ่ง" + +msgid "two" +msgstr "สอง" + +msgid "three" +msgstr "สาม" + +msgid "four" +msgstr "สี่" + +msgid "five" +msgstr "ห้า" + +msgid "six" +msgstr "หก" + +msgid "seven" +msgstr "เจ็ด" + +msgid "eight" +msgstr "แปด" + +msgid "nine" +msgstr "เก้า" + +msgid "today" +msgstr "วันนี้" + +msgid "tomorrow" +msgstr "พรุ่งนี้" + +msgid "yesterday" +msgstr "เมื่อวานนี้" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "%(count)s ชั่วโมงที่ผ่านมา" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "%(count)s นาทีที่ผ่านมา" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "%(count)s วินาทีที่ผ่านมา" + +msgid "now" +msgstr "ขณะนี้" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "%(count)s วินาทีต่อจากนี้" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "%(count)s นาทีต่อจากนี้" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "%(count)s ชั่วโมงต่อจากนี้" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/tk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/tk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5df0030 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/tk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/tk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/tk/LC_MESSAGES/django.po new file mode 100644 index 0000000..7901342 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/tk/LC_MESSAGES/django.po @@ -0,0 +1,328 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Resul , 2022 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2023-04-24 18:40+0000\n" +"Last-Translator: Resul , 2022\n" +"Language-Team: Turkmen (http://www.transifex.com/django/django/language/" +"tk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tk\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "Düşnüklileşdir" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}-nji" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}-nji" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}-inji" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}-nji" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}-nji" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}-nji" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}-nji" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}-njy" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}-nji" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}-nji" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}-njy" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s million" +msgstr[1] "%(value)s million" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s milliard" +msgstr[1] "%(value)s milliard" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s trillion" +msgstr[1] "%(value)s trillion" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s kwadrillion" +msgstr[1] "%(value)s kwadrillion" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s kwintillion" +msgstr[1] "%(value)s kwintillion" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s sekstillion" +msgstr[1] "%(value)s sekstillion" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septillion" +msgstr[1] "%(value)s septillion" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s oktillion" +msgstr[1] "%(value)s oktillion" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s nonillion" +msgstr[1] "%(value)s nonillion" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s desillion" +msgstr[1] "%(value)s desillion" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" +msgstr[1] "%(value)s googol" + +msgid "one" +msgstr "bir" + +msgid "two" +msgstr "iki" + +msgid "three" +msgstr "üç" + +msgid "four" +msgstr "dört" + +msgid "five" +msgstr "bäş" + +msgid "six" +msgstr "alty" + +msgid "seven" +msgstr "ýedi" + +msgid "eight" +msgstr "sekiz" + +msgid "nine" +msgstr "dokuz" + +msgid "today" +msgstr "şu gün" + +msgid "tomorrow" +msgstr "ertir" + +msgid "yesterday" +msgstr "düýn" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s öň" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "bir sagat öň" +msgstr[1] "%(count)s sagat öň" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "bir minut öň" +msgstr[1] "%(count)s minut öň" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "bir sekunt öň" +msgstr[1] "%(count)s sekunt öň" + +msgid "now" +msgstr "şu wagt" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "şu wagtdan bir sekunt soň" +msgstr[1] "şu wagtdan %(count)s sekunt soň" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "şu wagtdan bir minut soň" +msgstr[1] "şu wagtdan %(count)s minut soň" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "şu wagtdan bir sagat soň" +msgstr[1] "şu wagtdan  %(count)s sagat soň" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "şu wagtdan %(delta)s soň" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d ýyl" +msgstr[1] "%(num)d ýyl" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d aý" +msgstr[1] "%(num)d aý" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d hepde" +msgstr[1] "%(num)d hepde" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d gün" +msgstr[1] "%(num)d gün" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d sagat" +msgstr[1] "%(num)d sagat" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minut" +msgstr[1] "%(num)d minut" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d ýyl" +msgstr[1] "%(num)d ýyl" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d aý" +msgstr[1] "%(num)d aý" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d hepde" +msgstr[1] "%(num)d hepde" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d gün" +msgstr[1] "%(num)d gün" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d sagat" +msgstr[1] "%(num)d sagat" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d minut" +msgstr[1] "%(num)d minut" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/tr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/tr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..348e992 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/tr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/tr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/tr/LC_MESSAGES/django.po new file mode 100644 index 0000000..ef2b605 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/tr/LC_MESSAGES/django.po @@ -0,0 +1,333 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ahmet Emre Aladağ , 2013 +# BouRock, 2018,2021 +# BouRock, 2014 +# Jannis Leidel , 2011 +# Metin Amiroff , 2012 +# Murat Sahin , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2021-09-22 17:36+0000\n" +"Last-Translator: BouRock\n" +"Language-Team: Turkish (http://www.transifex.com/django/django/language/" +"tr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Humanize" +msgstr "İnsansı" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}." + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}." + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s milyon" +msgstr[1] "%(value)s milyon" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s milyar" +msgstr[1] "%(value)s milyar" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s trilyon" +msgstr[1] "%(value)s trilyon" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s katrilyon" +msgstr[1] "%(value)s katrilyon" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s kentilyon" +msgstr[1] "%(value)s kentilyon" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s seksilyon" +msgstr[1] "%(value)s seksilyon" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s septilyon" +msgstr[1] "%(value)s septilyon" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s oktilyon" +msgstr[1] "%(value)s oktilyon" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s nonilyon" +msgstr[1] "%(value)s nonilyon" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s desilyon" +msgstr[1] "%(value)s desilyon" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s googol" +msgstr[1] "%(value)s googol" + +msgid "one" +msgstr "bir" + +msgid "two" +msgstr "iki" + +msgid "three" +msgstr "üç" + +msgid "four" +msgstr "dört" + +msgid "five" +msgstr "beş" + +msgid "six" +msgstr "altı" + +msgid "seven" +msgstr "yedi" + +msgid "eight" +msgstr "sekiz" + +msgid "nine" +msgstr "dokuz" + +msgid "today" +msgstr "bugün" + +msgid "tomorrow" +msgstr "yarın" + +msgid "yesterday" +msgstr "dün" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s önce" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "bir saat önce" +msgstr[1] "%(count)s saat önce" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "bir dakika önce" +msgstr[1] "%(count)s dakika önce" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "bir saniye önce" +msgstr[1] "%(count)s saniye önce" + +msgid "now" +msgstr "şimdi" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "şu andan itibaren bir saniye" +msgstr[1] "şu andan itibaren %(count)s saniye" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "şu andan itibaren bir dakika" +msgstr[1] "şu andan itibaren %(count)s dakika" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "şu andan itibaren bir saat" +msgstr[1] "şu andan itibaren %(count)s saat" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "şu andan itibaren %(delta)s" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d yıl" +msgstr[1] "%(num)d yıl" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d ay" +msgstr[1] "%(num)d ay" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d hafta" +msgstr[1] "%(num)d hafta" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d gün" +msgstr[1] "%(num)d gün" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d saat" +msgstr[1] "%(num)d saat" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d dakika" +msgstr[1] "%(num)d dakika" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d yıl" +msgstr[1] "%(num)d yıl" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d ay" +msgstr[1] "%(num)d ay" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d hafta" +msgstr[1] "%(num)d hafta" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d gün" +msgstr[1] "%(num)d gün" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d saat" +msgstr[1] "%(num)d saat" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d dakika" +msgstr[1] "%(num)d dakika" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/tt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/tt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..98df56f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/tt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/tt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/tt/LC_MESSAGES/django.po new file mode 100644 index 0000000..96c72ad --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/tt/LC_MESSAGES/django.po @@ -0,0 +1,233 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Azat Khasanshin , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Tatar (http://www.transifex.com/django/django/language/tt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tt\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Humanize" +msgstr "" + +msgid "th" +msgstr "че" + +msgid "st" +msgstr "че" + +msgid "nd" +msgstr "че" + +msgid "rd" +msgstr "че" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f миллион" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s миллион" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f миллиард" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s миллиард" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f триллион" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s триллион" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f квадриллион" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s квадриллион" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f квинтиллион" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s квинтиллион" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f секстиллион" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s секстиллион" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f септиллион" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s септиллион" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f октиллион" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s октиллион" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f нониллион" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s нониллион" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f дециллион" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s дециллион" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f дециллион" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s гугол" + +msgid "one" +msgstr "бер" + +msgid "two" +msgstr "ике" + +msgid "three" +msgstr "өч" + +msgid "four" +msgstr "дүрт" + +msgid "five" +msgstr "биш" + +msgid "six" +msgstr "алты" + +msgid "seven" +msgstr "җиде" + +msgid "eight" +msgstr "сигез" + +msgid "nine" +msgstr "тугыз" + +msgid "today" +msgstr "бүген" + +msgid "tomorrow" +msgstr "иртәгә" + +msgid "yesterday" +msgstr "кичә" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "%(delta)s элек" + +msgid "now" +msgstr "хәзер" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "хәзердән %(delta)s" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/udm/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/udm/LC_MESSAGES/django.mo new file mode 100644 index 0000000..af7ab53 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/udm/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/udm/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/udm/LC_MESSAGES/django.po new file mode 100644 index 0000000..3508cf8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/udm/LC_MESSAGES/django.po @@ -0,0 +1,233 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:13+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Udmurt (http://www.transifex.com/projects/p/django/language/" +"udm/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: udm\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Humanize" +msgstr "" + +msgid "th" +msgstr "" + +msgid "st" +msgstr "" + +msgid "nd" +msgstr "" + +msgid "rd" +msgstr "" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "" + +msgid "one" +msgstr "" + +msgid "two" +msgstr "" + +msgid "three" +msgstr "" + +msgid "four" +msgstr "" + +msgid "five" +msgstr "" + +msgid "six" +msgstr "" + +msgid "seven" +msgstr "" + +msgid "eight" +msgstr "" + +msgid "nine" +msgstr "" + +msgid "today" +msgstr "" + +msgid "tomorrow" +msgstr "" + +msgid "yesterday" +msgstr "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "" + +msgid "now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ug/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ug/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1cc8dd1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ug/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ug/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ug/LC_MESSAGES/django.po new file mode 100644 index 0000000..3216ca1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ug/LC_MESSAGES/django.po @@ -0,0 +1,328 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Abduqadir Abliz , 2023 +# Azat, 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-18 11:41-0300\n" +"PO-Revision-Date: 2023-12-04 18:40+0000\n" +"Last-Translator: Azat, 2023\n" +"Language-Team: Uyghur (http://app.transifex.com/django/django/language/ug/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ug\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "ئىنسانلاشتۇرۇش" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}جى" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}جى" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}جى" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}جى" + +#. Translators: Ordinal format when value ends with 3, e.g. 83rd, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}جى" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}جى" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}جى" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}جى" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}جى" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}جى" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}جى" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s مىليون" +msgstr[1] "%(value)s مىليون" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s مىليارد" +msgstr[1] "%(value)s مىليارد" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s تىرىليون" +msgstr[1] "%(value)s تىرىليون" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s كۋادىرىللىيۇن" +msgstr[1] "%(value)s كۋادىرىللىيۇن" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s كۈيىنتىللىيون" +msgstr[1] "%(value)s كۈيىنتىللىيون" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s سېكستىللىيون" +msgstr[1] "%(value)s سېكستىللىيون" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s سېكستىللىيون" +msgstr[1] "%(value)s سېكستىللىيون" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s ئوكتىلىيون" +msgstr[1] "%(value)s ئوكتىلىيون" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s نونىللىيون" +msgstr[1] "%(value)s نونىللىيون" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s دېكىللىيون" +msgstr[1] "%(value)s دېكىللىيون" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s گۇگول " +msgstr[1] "%(value)s گۇگول" + +msgid "one" +msgstr "بىر" + +msgid "two" +msgstr "ئىككى" + +msgid "three" +msgstr "ئۈچ" + +msgid "four" +msgstr "تۆت" + +msgid "five" +msgstr "بەش" + +msgid "six" +msgstr "ئالتە" + +msgid "seven" +msgstr "يەتتە" + +msgid "eight" +msgstr "سەككىز" + +msgid "nine" +msgstr "توققۇز" + +msgid "today" +msgstr "بۈگۈن" + +msgid "tomorrow" +msgstr "ئەتە" + +msgid "yesterday" +msgstr "تۈنۈگۈن" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s ئىلگىرى" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "1 سائەت ئىلگىرى" +msgstr[1] "%(count)s سائەت ئىلگىرى" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "1 مىنۇت ئىلگىرى" +msgstr[1] "%(count)s مىنۇت ئىلگىرى" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "1 سېكۇنت ئىلگىرى" +msgstr[1] "%(count)s سېكۇنت ئىلگىرى" + +msgid "now" +msgstr "ھازىر" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "1 سېكۇنتتىن كېيىن" +msgstr[1] "%(count)s سېكۇنتتىن كېيىن" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "1 مىنۇتتىن كېيىن" +msgstr[1] "%(count)s مىنۇتتىن كېيىن" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "1 سائەتتىن كېيىن" +msgstr[1] "%(count)s سائەتتىن كېيىن" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s دىن كېيىن" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d يىل" +msgstr[1] "%(num)d يىل" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d ئاي" +msgstr[1] "%(num)d ئاي" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d ھەپتە" +msgstr[1] "%(num)d ھەپتە" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d كۈن" +msgstr[1] "%(num)d كۈن" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d سائەت" +msgstr[1] "%(num)d سائەت" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d مىنۇت" +msgstr[1] "%(num)d مىنۇت" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d يىل" +msgstr[1] "%(num)d يىل" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d ئاي" +msgstr[1] "%(num)d ئاي" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d ھەپتە" +msgstr[1] "%(num)d ھەپتە" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d كۈن" +msgstr[1] "%(num)d كۈن" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d سائەت" +msgstr[1] "%(num)d سائەت" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d مىنۇت" +msgstr[1] "%(num)d مىنۇت" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/uk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/uk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1662778 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/uk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/uk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/uk/LC_MESSAGES/django.po new file mode 100644 index 0000000..d4c86fd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/uk/LC_MESSAGES/django.po @@ -0,0 +1,395 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Oleksandr Chernihov , 2014 +# Illia Volochii , 2022 +# Kirill Gagarski , 2014 +# Max V. Stotsky , 2014 +# Mykola Zamkovoi , 2014 +# Alex Bolotov , 2013 +# tarasyyyk , 2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2022-07-24 18:40+0000\n" +"Last-Translator: Illia Volochii \n" +"Language-Team: Ukrainian (http://www.transifex.com/django/django/language/" +"uk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: uk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != " +"11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % " +"100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || " +"(n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n" + +msgid "Humanize" +msgstr "Олюднювати" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "{}ий" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "{}ть" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "{}ий" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "{}ий" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "{}ій" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "{}ий" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "{}ий" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "{}ий" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "{}ий" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "{}ий" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "{}ий" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s мільйон" +msgstr[1] "%(value)s мільйони" +msgstr[2] "%(value)s мільйонів" +msgstr[3] "%(value)s мільйонів" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s мільярд" +msgstr[1] "%(value)s мільярди" +msgstr[2] "%(value)s мільярдів" +msgstr[3] "%(value)s мільярдів" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s трильйон" +msgstr[1] "%(value)s трильйони" +msgstr[2] "%(value)s трильйонів" +msgstr[3] "%(value)s трильйонів" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s квадрильйон" +msgstr[1] "%(value)s квадрильйони" +msgstr[2] "%(value)s квадрильйонів" +msgstr[3] "%(value)s квадрильйонів" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s квінтильйон" +msgstr[1] "%(value)s квінтильйони" +msgstr[2] "%(value)s квінтильйонів" +msgstr[3] "%(value)s квінтильйонів" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s секстильйон" +msgstr[1] "%(value)s секстильйони" +msgstr[2] "%(value)s секстильйонів" +msgstr[3] "%(value)s секстильйонів" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s септильйон" +msgstr[1] "%(value)s септильйони" +msgstr[2] "%(value)s септильйонів" +msgstr[3] "%(value)s септильйонів" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s октильйон" +msgstr[1] "%(value)s октильйони" +msgstr[2] "%(value)s октильйонів" +msgstr[3] "%(value)s октильйонів" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s нонільйон" +msgstr[1] "%(value)s нонільйони" +msgstr[2] "%(value)s нонільйонів" +msgstr[3] "%(value)s нонільйонів" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s децильйон" +msgstr[1] "%(value)s децильйони" +msgstr[2] "%(value)s децильйонів" +msgstr[3] "%(value)s децильйонів" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s гугол" +msgstr[1] "%(value)s гуголи" +msgstr[2] "%(value)s гуголів" +msgstr[3] "%(value)s гуголів" + +msgid "one" +msgstr "один" + +msgid "two" +msgstr "два" + +msgid "three" +msgstr "три" + +msgid "four" +msgstr "чотири" + +msgid "five" +msgstr "п'ять" + +msgid "six" +msgstr "шість" + +msgid "seven" +msgstr "сім" + +msgid "eight" +msgstr "вісім" + +msgid "nine" +msgstr "дев'ять" + +msgid "today" +msgstr "сьогодні" + +msgid "tomorrow" +msgstr "завтра" + +msgid "yesterday" +msgstr "вчора" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s тому" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "%(count)s годину тому" +msgstr[1] "%(count)s години тому" +msgstr[2] "%(count)s годин тому" +msgstr[3] "%(count)s годин тому" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "%(count)s хвилину тому" +msgstr[1] "%(count)s хвилини тому" +msgstr[2] "%(count)s хвилин тому" +msgstr[3] "%(count)s хвилин тому" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "%(count)s секунду тому" +msgstr[1] "%(count)s секунди тому" +msgstr[2] "%(count)s секунд тому" +msgstr[3] "%(count)s секунд тому" + +msgid "now" +msgstr "зараз" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "%(count)s секунда від цього часу" +msgstr[1] "%(count)s секунди від цього часу" +msgstr[2] "%(count)s секунд від цього часу" +msgstr[3] "%(count)s секунд від цього часу" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "%(count)s хвилина від цього часу" +msgstr[1] "%(count)s хвилини від цього часу" +msgstr[2] "%(count)s хвилин від цього часу" +msgstr[3] "%(count)s хвилин від цього часу" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "%(count)s година від цього часу" +msgstr[1] "%(count)s години від цього часу" +msgstr[2] "%(count)s годин від цього часу" +msgstr[3] "%(count)s годин від цього часу" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "через %(delta)s" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d рік" +msgstr[1] "%(num)d роки" +msgstr[2] "%(num)d років" +msgstr[3] "%(num)d років" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d місяць" +msgstr[1] "%(num)d місяці" +msgstr[2] "%(num)d місяців" +msgstr[3] "%(num)d місяців" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d тиждень" +msgstr[1] "%(num)d тижні" +msgstr[2] "%(num)d тижнів" +msgstr[3] "%(num)d тижнів" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d день" +msgstr[1] "%(num)d дні" +msgstr[2] "%(num)d днів" +msgstr[3] "%(num)d днів" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d година" +msgstr[1] "%(num)d години" +msgstr[2] "%(num)d годин" +msgstr[3] "%(num)d годин" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d хвилина" +msgstr[1] "%(num)d хвилини" +msgstr[2] "%(num)d хвилин" +msgstr[3] "%(num)d хвилин" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d рік" +msgstr[1] "%(num)d роки" +msgstr[2] "%(num)d років" +msgstr[3] "%(num)d років" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d місяць" +msgstr[1] "%(num)d місяці" +msgstr[2] "%(num)d місяців" +msgstr[3] "%(num)d місяців" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d тиждень" +msgstr[1] "%(num)d тижні" +msgstr[2] "%(num)d тижнів" +msgstr[3] "%(num)d тижнів" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d день" +msgstr[1] "%(num)d дні" +msgstr[2] "%(num)d днів" +msgstr[3] "%(num)d днів" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d година" +msgstr[1] "%(num)d години" +msgstr[2] "%(num)d годин" +msgstr[3] "%(num)d годин" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d хвилина" +msgstr[1] "%(num)d хвилини" +msgstr[2] "%(num)d хвилин" +msgstr[3] "%(num)d хвилин" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ur/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ur/LC_MESSAGES/django.mo new file mode 100644 index 0000000..078d2e9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ur/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ur/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ur/LC_MESSAGES/django.po new file mode 100644 index 0000000..2e889dd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/ur/LC_MESSAGES/django.po @@ -0,0 +1,261 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Mansoorulhaq Mansoor , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Urdu (http://www.transifex.com/django/django/language/ur/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ur\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Humanize" +msgstr "" + +msgid "th" +msgstr "واں" + +msgid "st" +msgstr "پہلا" + +msgid "nd" +msgstr "دوسرا" + +msgid "rd" +msgstr "تیسرا" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f ملین" +msgstr[1] "%(value).1f ملین" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f بلین" +msgstr[1] "%(value).1f بلین" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f ٹریلین" +msgstr[1] "%(value).1f ٹریلین" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "" +msgstr[1] "" + +msgid "one" +msgstr "ایک" + +msgid "two" +msgstr "دو" + +msgid "three" +msgstr "تین" + +msgid "four" +msgstr "چار" + +msgid "five" +msgstr "پانچ" + +msgid "six" +msgstr "چھ" + +msgid "seven" +msgstr "سات" + +msgid "eight" +msgstr "آتھ" + +msgid "nine" +msgstr "نو" + +msgid "today" +msgstr "آج" + +msgid "tomorrow" +msgstr "آئندہ کل" + +msgid "yesterday" +msgstr "گزستہ کل" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "" + +msgid "now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" +msgstr[1] "" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" +msgstr[1] "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/uz/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/uz/LC_MESSAGES/django.mo new file mode 100644 index 0000000..179f657 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/uz/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/uz/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/uz/LC_MESSAGES/django.po new file mode 100644 index 0000000..b85d5b8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/uz/LC_MESSAGES/django.po @@ -0,0 +1,353 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# A'zam Mamatmurodov , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2019-11-13 09:18+0000\n" +"Last-Translator: A'zam Mamatmurodov \n" +"Language-Team: Uzbek (http://www.transifex.com/django/django/language/uz/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: uz\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Humanize" +msgstr "" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "" + +msgid "one" +msgstr "bir" + +msgid "two" +msgstr "ikki" + +msgid "three" +msgstr "uch" + +msgid "four" +msgstr "to'rt" + +msgid "five" +msgstr "besh" + +msgid "six" +msgstr "olti" + +msgid "seven" +msgstr "yetti" + +msgid "eight" +msgstr "sakkiz" + +msgid "nine" +msgstr "to'qqiz" + +msgid "today" +msgstr "o'n" + +msgid "tomorrow" +msgstr "ertaga" + +msgid "yesterday" +msgstr "kecha" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s oldin" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "%(count)s soat oldin" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "%(count)s daqiqa oldin" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "%(count)s soniya oldin" + +msgid "now" +msgstr "hozir" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d yil" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d oy" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d hafta" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d kun" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d soat" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d daqiqa" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d yil" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d oy" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d hafta" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d kun" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d soat" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d daqiqa" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/vi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/vi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7c0b900 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/vi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/vi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/vi/LC_MESSAGES/django.po new file mode 100644 index 0000000..4b7cd6e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/vi/LC_MESSAGES/django.po @@ -0,0 +1,235 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# xgenvn , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Tran Van \n" +"Language-Team: Vietnamese (http://www.transifex.com/django/django/language/" +"vi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: vi\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Humanize" +msgstr "Humanize" + +msgid "th" +msgstr "th" + +msgid "st" +msgstr "st" + +msgid "nd" +msgstr "nd" + +msgid "rd" +msgstr "rd" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f triệu" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s triệu" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f tỷ" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s tỷ" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f nghìn tỷ" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s nghìn tỷ" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f triệu tỷ" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s triệu tỷ" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f tỷ tỷ" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s tỷ tỷ" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f nghìn tỷ tỷ" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s nghỉn tỷ tỷ" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f triệu tỷ tỷ" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s triệu tỷ tỷ" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f tỷ tỷ tỷ" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s tỷ tỷ tỷ" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f nghìn tỷ tỷ tỷ" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s nghỉn tỷ tỷ tỷ" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f triệu tỷ tỷ tỷ" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s triệu tỷ tỷ tỷ" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f tỷ tỷ tỷ tỷ" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s tỷ tỷ tỷ tỷ" + +msgid "one" +msgstr "Một" + +msgid "two" +msgstr "Hai" + +msgid "three" +msgstr "Ba" + +msgid "four" +msgstr "Bốn" + +msgid "five" +msgstr "Năm" + +msgid "six" +msgstr "Sáu" + +msgid "seven" +msgstr "Bảy" + +msgid "eight" +msgstr "Tám" + +msgid "nine" +msgstr "Chín" + +msgid "today" +msgstr "Hôm nay" + +msgid "tomorrow" +msgstr "Ngày mai" + +msgid "yesterday" +msgstr "Hôm qua" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s ago" +msgstr "cách đây %(delta)s" + +msgid "now" +msgstr "vừa mới đây" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "%(count)s giây trước" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "%(count)s phút trước" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "%(count)s giờ trước" + +#, python-format +msgctxt "naturaltime" +msgid "%(delta)s from now" +msgstr "%(delta)s sau" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "%(count)s giây sau" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "%(count)s phút sau" + +#. Translators: please keep a non-breaking space (U+00A0) +#. between count and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "%(count)s giờ sau" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/zh_Hans/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/zh_Hans/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e0e6617 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/zh_Hans/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/zh_Hans/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/zh_Hans/LC_MESSAGES/django.po new file mode 100644 index 0000000..abbb1b0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/zh_Hans/LC_MESSAGES/django.po @@ -0,0 +1,308 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# lanbla , 2021 +# Jannis Leidel , 2011 +# Jenny Qian , 2018 +# Lele Long , 2015 +# Ronald White , 2014 +# Suntravel Chris , 2019 +# wang zhao <672565116@qq.com>, 2018 +# Xiang Yu , 2014 +# ced773123cfad7b4e8b79ca80f736af9, 2011 +# Kevin Sze , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-04-07 14:40+0200\n" +"PO-Revision-Date: 2021-11-22 03:16+0000\n" +"Last-Translator: lanbla \n" +"Language-Team: Chinese (China) (http://www.transifex.com/django/django/" +"language/zh_CN/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_CN\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Humanize" +msgstr "人性化" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "第{}" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "第{}" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "第{}" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "第{}" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "第{}" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "第{}" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "第{}" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "第{}" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "第{}" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "第{}" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "第{}" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s 百万" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s 十亿" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s 万亿" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s 1000的5次方" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s 1000的4次方" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s 1000的7次方" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s 1000的8次方" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s 1000的9次方" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s 1000的10次方" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s 1000的11次方" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s 10的100次方" + +msgid "one" +msgstr "一" + +msgid "two" +msgstr "二" + +msgid "three" +msgstr "三" + +msgid "four" +msgstr "四" + +msgid "five" +msgstr "五" + +msgid "six" +msgstr "六" + +msgid "seven" +msgstr "七" + +msgid "eight" +msgstr "八" + +msgid "nine" +msgstr "九" + +msgid "today" +msgstr "今天" + +msgid "tomorrow" +msgstr "明天" + +msgid "yesterday" +msgstr "昨天" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s前" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "%(count)s小时之前" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "%(count)s分钟之前" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "%(count)s秒之前" + +msgid "now" +msgstr "现在" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "%(count)s秒以后" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "%(count)s分钟以后" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "%(count)s小时以后" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s之后" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d 年" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d 月" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d 周" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d 日" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d 小时" + +#, python-format +msgctxt "naturaltime-past" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d 分钟" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d year" +msgid_plural "%(num)d years" +msgstr[0] "%(num)d 年" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d month" +msgid_plural "%(num)d months" +msgstr[0] "%(num)d 月" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d week" +msgid_plural "%(num)d weeks" +msgstr[0] "%(num)d 周" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d day" +msgid_plural "%(num)d days" +msgstr[0] "%(num)d 日" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d hour" +msgid_plural "%(num)d hours" +msgstr[0] "%(num)d 小时" + +#, python-format +msgctxt "naturaltime-future" +msgid "%(num)d minute" +msgid_plural "%(num)d minutes" +msgstr[0] "%(num)d 分钟" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/zh_Hant/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/zh_Hant/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2be75b5 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/zh_Hant/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/zh_Hant/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/zh_Hant/LC_MESSAGES/django.po new file mode 100644 index 0000000..0944649 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/locale/zh_Hant/LC_MESSAGES/django.po @@ -0,0 +1,358 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Chen Chun-Chia , 2015 +# Jannis Leidel , 2011 +# tcc , 2011 +# Tzu-ping Chung , 2016,2019 +# Yeh-Yung , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-01-16 20:42+0100\n" +"PO-Revision-Date: 2019-09-18 09:08+0000\n" +"Last-Translator: Tzu-ping Chung \n" +"Language-Team: Chinese (Taiwan) (http://www.transifex.com/django/django/" +"language/zh_TW/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_TW\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Humanize" +msgstr "人性化" + +#. Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). +msgctxt "ordinal 11, 12, 13" +msgid "{}th" +msgstr "第{}" + +#. Translators: Ordinal format when value ends with 0, e.g. 80th. +msgctxt "ordinal 0" +msgid "{}th" +msgstr "第{}" + +#. Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. +msgctxt "ordinal 1" +msgid "{}st" +msgstr "第{}" + +#. Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. +msgctxt "ordinal 2" +msgid "{}nd" +msgstr "第{}" + +#. Translators: Ordinal format when value ends with 3, e.g. 83th, except 13. +msgctxt "ordinal 3" +msgid "{}rd" +msgstr "第{}" + +#. Translators: Ordinal format when value ends with 4, e.g. 84th. +msgctxt "ordinal 4" +msgid "{}th" +msgstr "第{}" + +#. Translators: Ordinal format when value ends with 5, e.g. 85th. +msgctxt "ordinal 5" +msgid "{}th" +msgstr "第{}" + +#. Translators: Ordinal format when value ends with 6, e.g. 86th. +msgctxt "ordinal 6" +msgid "{}th" +msgstr "第{}" + +#. Translators: Ordinal format when value ends with 7, e.g. 87th. +msgctxt "ordinal 7" +msgid "{}th" +msgstr "第{}" + +#. Translators: Ordinal format when value ends with 8, e.g. 88th. +msgctxt "ordinal 8" +msgid "{}th" +msgstr "第{}" + +#. Translators: Ordinal format when value ends with 9, e.g. 89th. +msgctxt "ordinal 9" +msgid "{}th" +msgstr "第{}" + +#, python-format +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f 百萬" + +#, python-format +msgid "%(value)s million" +msgid_plural "%(value)s million" +msgstr[0] "%(value)s 百萬" + +#, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f 十億" + +#, python-format +msgid "%(value)s billion" +msgid_plural "%(value)s billion" +msgstr[0] "%(value)s 十億" + +#, python-format +msgid "%(value).1f trillion" +msgid_plural "%(value).1f trillion" +msgstr[0] "%(value).1f 兆" + +#, python-format +msgid "%(value)s trillion" +msgid_plural "%(value)s trillion" +msgstr[0] "%(value)s 兆" + +#, python-format +msgid "%(value).1f quadrillion" +msgid_plural "%(value).1f quadrillion" +msgstr[0] "%(value).1f 千兆" + +#, python-format +msgid "%(value)s quadrillion" +msgid_plural "%(value)s quadrillion" +msgstr[0] "%(value)s 千兆" + +#, python-format +msgid "%(value).1f quintillion" +msgid_plural "%(value).1f quintillion" +msgstr[0] "%(value).1f 百京" + +#, python-format +msgid "%(value)s quintillion" +msgid_plural "%(value)s quintillion" +msgstr[0] "%(value)s 百京" + +#, python-format +msgid "%(value).1f sextillion" +msgid_plural "%(value).1f sextillion" +msgstr[0] "%(value).1f 十垓" + +#, python-format +msgid "%(value)s sextillion" +msgid_plural "%(value)s sextillion" +msgstr[0] "%(value)s 十垓" + +#, python-format +msgid "%(value).1f septillion" +msgid_plural "%(value).1f septillion" +msgstr[0] "%(value).1f 秭" + +#, python-format +msgid "%(value)s septillion" +msgid_plural "%(value)s septillion" +msgstr[0] "%(value)s 秭" + +#, python-format +msgid "%(value).1f octillion" +msgid_plural "%(value).1f octillion" +msgstr[0] "%(value).1f 千秭" + +#, python-format +msgid "%(value)s octillion" +msgid_plural "%(value)s octillion" +msgstr[0] "%(value)s 千秭" + +#, python-format +msgid "%(value).1f nonillion" +msgid_plural "%(value).1f nonillion" +msgstr[0] "%(value).1f 百穰" + +#, python-format +msgid "%(value)s nonillion" +msgid_plural "%(value)s nonillion" +msgstr[0] "%(value)s 百穰" + +#, python-format +msgid "%(value).1f decillion" +msgid_plural "%(value).1f decillion" +msgstr[0] "%(value).1f 十溝" + +#, python-format +msgid "%(value)s decillion" +msgid_plural "%(value)s decillion" +msgstr[0] "%(value)s 十溝" + +#, python-format +msgid "%(value).1f googol" +msgid_plural "%(value).1f googol" +msgstr[0] "%(value).1f 穰大數" + +#, python-format +msgid "%(value)s googol" +msgid_plural "%(value)s googol" +msgstr[0] "%(value)s 穰大數" + +msgid "one" +msgstr "一" + +msgid "two" +msgstr "二" + +msgid "three" +msgstr "三" + +msgid "four" +msgstr "四" + +msgid "five" +msgstr "五" + +msgid "six" +msgstr "六" + +msgid "seven" +msgstr "七" + +msgid "eight" +msgstr "八" + +msgid "nine" +msgstr "九" + +msgid "today" +msgstr "今天" + +msgid "tomorrow" +msgstr "明天" + +msgid "yesterday" +msgstr "昨天" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s ago" +msgstr "%(delta)s前" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour ago" +msgid_plural "%(count)s hours ago" +msgstr[0] "%(count)s 小時前" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute ago" +msgid_plural "%(count)s minutes ago" +msgstr[0] "%(count)s 分鐘前" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second ago" +msgid_plural "%(count)s seconds ago" +msgstr[0] "%(count)s 秒前" + +msgid "now" +msgstr "現在" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a second from now" +msgid_plural "%(count)s seconds from now" +msgstr[0] "%(count)s 秒後" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "a minute from now" +msgid_plural "%(count)s minutes from now" +msgstr[0] "%(count)s 分鐘後" + +#. Translators: please keep a non-breaking space (U+00A0) between count +#. and time unit. +#, python-format +msgid "an hour from now" +msgid_plural "%(count)s hours from now" +msgstr[0] "%(count)s 小時後" + +#. Translators: delta will contain a string like '2 months' or '1 month, 2 +#. weeks' +#, python-format +msgid "%(delta)s from now" +msgstr "%(delta)s後" + +#. Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' +#, python-format +msgctxt "naturaltime-past" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d 年" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d 個月" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d 週" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d 天" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d 小時" + +#, python-format +msgctxt "naturaltime-past" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d 分" + +#. Translators: 'naturaltime-future' strings will be included in '%(delta)s +#. from now' +#, python-format +msgctxt "naturaltime-future" +msgid "%d year" +msgid_plural "%d years" +msgstr[0] "%d 年" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d month" +msgid_plural "%d months" +msgstr[0] "%d 個月" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d week" +msgid_plural "%d weeks" +msgstr[0] "%d 週" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d day" +msgid_plural "%d days" +msgstr[0] "%d 天" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d hour" +msgid_plural "%d hours" +msgstr[0] "%d 小時" + +#, python-format +msgctxt "naturaltime-future" +msgid "%d minute" +msgid_plural "%d minutes" +msgstr[0] "%d 分" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/templatetags/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/templatetags/humanize.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/templatetags/humanize.py new file mode 100644 index 0000000..2322477 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/humanize/templatetags/humanize.py @@ -0,0 +1,322 @@ +import re +from datetime import date, datetime, timezone +from decimal import Decimal + +from django import template +from django.template import defaultfilters +from django.utils.formats import number_format +from django.utils.safestring import mark_safe +from django.utils.timezone import is_aware +from django.utils.translation import gettext as _ +from django.utils.translation import ( + gettext_lazy, + ngettext, + ngettext_lazy, + npgettext_lazy, + pgettext, + round_away_from_one, +) + +register = template.Library() + + +@register.filter(is_safe=True) +def ordinal(value): + """ + Convert an integer to its ordinal as a string. 1 is '1st', 2 is '2nd', + 3 is '3rd', etc. Works for any integer. + """ + try: + value = int(value) + except (TypeError, ValueError): + return value + if value % 100 in (11, 12, 13): + # Translators: Ordinal format for 11 (11th), 12 (12th), and 13 (13th). + value = pgettext("ordinal 11, 12, 13", "{}th").format(value) + else: + templates = ( + # Translators: Ordinal format when value ends with 0, e.g. 80th. + pgettext("ordinal 0", "{}th"), + # Translators: Ordinal format when value ends with 1, e.g. 81st, except 11. + pgettext("ordinal 1", "{}st"), + # Translators: Ordinal format when value ends with 2, e.g. 82nd, except 12. + pgettext("ordinal 2", "{}nd"), + # Translators: Ordinal format when value ends with 3, e.g. 83rd, except 13. + pgettext("ordinal 3", "{}rd"), + # Translators: Ordinal format when value ends with 4, e.g. 84th. + pgettext("ordinal 4", "{}th"), + # Translators: Ordinal format when value ends with 5, e.g. 85th. + pgettext("ordinal 5", "{}th"), + # Translators: Ordinal format when value ends with 6, e.g. 86th. + pgettext("ordinal 6", "{}th"), + # Translators: Ordinal format when value ends with 7, e.g. 87th. + pgettext("ordinal 7", "{}th"), + # Translators: Ordinal format when value ends with 8, e.g. 88th. + pgettext("ordinal 8", "{}th"), + # Translators: Ordinal format when value ends with 9, e.g. 89th. + pgettext("ordinal 9", "{}th"), + ) + value = templates[value % 10].format(value) + # Mark value safe so i18n does not break with or see #19988 + return mark_safe(value) + + +@register.filter(is_safe=True) +def intcomma(value, use_l10n=True): + """ + Convert an integer to a string containing commas every three digits. + For example, 3000 becomes '3,000' and 45000 becomes '45,000'. + """ + if use_l10n: + try: + if not isinstance(value, (float, Decimal)): + value = int(value) + except (TypeError, ValueError): + return intcomma(value, False) + else: + return number_format(value, use_l10n=True, force_grouping=True) + orig = str(value) + new = re.sub(r"^(-?\d+)(\d{3})", r"\g<1>,\g<2>", orig) + if orig == new: + return new + else: + return intcomma(new, use_l10n) + + +# A tuple of standard large number to their converters +intword_converters = ( + (6, lambda number: ngettext("%(value)s million", "%(value)s million", number)), + (9, lambda number: ngettext("%(value)s billion", "%(value)s billion", number)), + (12, lambda number: ngettext("%(value)s trillion", "%(value)s trillion", number)), + ( + 15, + lambda number: ngettext( + "%(value)s quadrillion", "%(value)s quadrillion", number + ), + ), + ( + 18, + lambda number: ngettext( + "%(value)s quintillion", "%(value)s quintillion", number + ), + ), + ( + 21, + lambda number: ngettext("%(value)s sextillion", "%(value)s sextillion", number), + ), + ( + 24, + lambda number: ngettext("%(value)s septillion", "%(value)s septillion", number), + ), + (27, lambda number: ngettext("%(value)s octillion", "%(value)s octillion", number)), + (30, lambda number: ngettext("%(value)s nonillion", "%(value)s nonillion", number)), + (33, lambda number: ngettext("%(value)s decillion", "%(value)s decillion", number)), + (100, lambda number: ngettext("%(value)s googol", "%(value)s googol", number)), +) + + +@register.filter(is_safe=False) +def intword(value): + """ + Convert a large integer to a friendly text representation. Works best + for numbers over 1 million. For example, 1000000 becomes '1.0 million', + 1200000 becomes '1.2 million' and '1200000000' becomes '1.2 billion'. + """ + try: + value = int(value) + except (TypeError, ValueError): + return value + + abs_value = abs(value) + if abs_value < 1000000: + return value + + for exponent, converter in intword_converters: + large_number = 10**exponent + if abs_value < large_number * 1000: + new_value = value / large_number + rounded_value = round_away_from_one(new_value) + return converter(abs(rounded_value)) % { + "value": defaultfilters.floatformat(new_value, 1), + } + return value + + +@register.filter(is_safe=True) +def apnumber(value): + """ + For numbers 1-9, return the number spelled out. Otherwise, return the + number. This follows Associated Press style. + """ + try: + value = int(value) + except (TypeError, ValueError): + return value + if not 0 < value < 10: + return value + return ( + _("one"), + _("two"), + _("three"), + _("four"), + _("five"), + _("six"), + _("seven"), + _("eight"), + _("nine"), + )[value - 1] + + +# Perform the comparison in the default time zone when USE_TZ = True +# (unless a specific time zone has been applied with the |timezone filter). +@register.filter(expects_localtime=True) +def naturalday(value, arg=None): + """ + For date values that are tomorrow, today or yesterday compared to + present day return representing string. Otherwise, return a string + formatted according to settings.DATE_FORMAT. + """ + tzinfo = getattr(value, "tzinfo", None) + try: + value = date(value.year, value.month, value.day) + except AttributeError: + # Passed value wasn't a date object + return value + today = datetime.now(tzinfo).date() + delta = value - today + if delta.days == 0: + return _("today") + elif delta.days == 1: + return _("tomorrow") + elif delta.days == -1: + return _("yesterday") + return defaultfilters.date(value, arg) + + +# This filter doesn't require expects_localtime=True because it deals properly +# with both naive and aware datetimes. Therefore avoid the cost of conversion. +@register.filter +def naturaltime(value): + """ + For date and time values show how many seconds, minutes, or hours ago + compared to current timestamp return representing string. + """ + return NaturalTimeFormatter.string_for(value) + + +class NaturalTimeFormatter: + time_strings = { + # Translators: delta will contain a string like '2 months' or '1 month, 2 weeks' + "past-day": gettext_lazy("%(delta)s ago"), + # Translators: please keep a non-breaking space (U+00A0) between count + # and time unit. + "past-hour": ngettext_lazy("an hour ago", "%(count)s hours ago", "count"), + # Translators: please keep a non-breaking space (U+00A0) between count + # and time unit. + "past-minute": ngettext_lazy("a minute ago", "%(count)s minutes ago", "count"), + # Translators: please keep a non-breaking space (U+00A0) between count + # and time unit. + "past-second": ngettext_lazy("a second ago", "%(count)s seconds ago", "count"), + "now": gettext_lazy("now"), + # Translators: please keep a non-breaking space (U+00A0) between count + # and time unit. + "future-second": ngettext_lazy( + "a second from now", "%(count)s seconds from now", "count" + ), + # Translators: please keep a non-breaking space (U+00A0) between count + # and time unit. + "future-minute": ngettext_lazy( + "a minute from now", "%(count)s minutes from now", "count" + ), + # Translators: please keep a non-breaking space (U+00A0) between count + # and time unit. + "future-hour": ngettext_lazy( + "an hour from now", "%(count)s hours from now", "count" + ), + # Translators: delta will contain a string like '2 months' or '1 month, 2 weeks' + "future-day": gettext_lazy("%(delta)s from now"), + } + past_substrings = { + # Translators: 'naturaltime-past' strings will be included in '%(delta)s ago' + "year": npgettext_lazy( + "naturaltime-past", "%(num)d year", "%(num)d years", "num" + ), + "month": npgettext_lazy( + "naturaltime-past", "%(num)d month", "%(num)d months", "num" + ), + "week": npgettext_lazy( + "naturaltime-past", "%(num)d week", "%(num)d weeks", "num" + ), + "day": npgettext_lazy("naturaltime-past", "%(num)d day", "%(num)d days", "num"), + "hour": npgettext_lazy( + "naturaltime-past", "%(num)d hour", "%(num)d hours", "num" + ), + "minute": npgettext_lazy( + "naturaltime-past", "%(num)d minute", "%(num)d minutes", "num" + ), + } + future_substrings = { + # Translators: 'naturaltime-future' strings will be included in + # '%(delta)s from now'. + "year": npgettext_lazy( + "naturaltime-future", "%(num)d year", "%(num)d years", "num" + ), + "month": npgettext_lazy( + "naturaltime-future", "%(num)d month", "%(num)d months", "num" + ), + "week": npgettext_lazy( + "naturaltime-future", "%(num)d week", "%(num)d weeks", "num" + ), + "day": npgettext_lazy( + "naturaltime-future", "%(num)d day", "%(num)d days", "num" + ), + "hour": npgettext_lazy( + "naturaltime-future", "%(num)d hour", "%(num)d hours", "num" + ), + "minute": npgettext_lazy( + "naturaltime-future", "%(num)d minute", "%(num)d minutes", "num" + ), + } + + @classmethod + def string_for(cls, value): + if not isinstance(value, date): # datetime is a subclass of date + return value + + now = datetime.now(timezone.utc if is_aware(value) else None) + if value < now: + delta = now - value + if delta.days != 0: + return cls.time_strings["past-day"] % { + "delta": defaultfilters.timesince( + value, now, time_strings=cls.past_substrings + ), + } + elif delta.seconds == 0: + return cls.time_strings["now"] + elif delta.seconds < 60: + return cls.time_strings["past-second"] % {"count": delta.seconds} + elif delta.seconds // 60 < 60: + count = delta.seconds // 60 + return cls.time_strings["past-minute"] % {"count": count} + else: + count = delta.seconds // 60 // 60 + return cls.time_strings["past-hour"] % {"count": count} + else: + delta = value - now + if delta.days != 0: + return cls.time_strings["future-day"] % { + "delta": defaultfilters.timeuntil( + value, now, time_strings=cls.future_substrings + ), + } + elif delta.seconds == 0: + return cls.time_strings["now"] + elif delta.seconds < 60: + return cls.time_strings["future-second"] % {"count": delta.seconds} + elif delta.seconds // 60 < 60: + count = delta.seconds // 60 + return cls.time_strings["future-minute"] % {"count": count} + else: + count = delta.seconds // 60 // 60 + return cls.time_strings["future-hour"] % {"count": count} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/__init__.py new file mode 100644 index 0000000..3b62e0b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/__init__.py @@ -0,0 +1,3 @@ +from django.contrib.messages.api import * # NOQA +from django.contrib.messages.constants import * # NOQA +from django.contrib.messages.storage.base import Message # NOQA diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/api.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/api.py new file mode 100644 index 0000000..7a67e8b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/api.py @@ -0,0 +1,127 @@ +from django.contrib.messages import constants +from django.contrib.messages.storage import default_storage + +__all__ = ( + "add_message", + "get_messages", + "get_level", + "set_level", + "debug", + "info", + "success", + "warning", + "error", + "MessageFailure", +) + + +class MessageFailure(Exception): + pass + + +def add_message(request, level, message, extra_tags="", fail_silently=False): + """ + Attempt to add a message to the request using the 'messages' app. + """ + try: + messages = request._messages + except AttributeError: + if not hasattr(request, "META"): + raise TypeError( + "add_message() argument must be an HttpRequest object, not " + "'%s'." % request.__class__.__name__ + ) + if not fail_silently: + raise MessageFailure( + "You cannot add messages without installing " + "django.contrib.messages.middleware.MessageMiddleware" + ) + else: + return messages.add(level, message, extra_tags) + + +def get_messages(request): + """ + Return the message storage on the request if it exists, otherwise return + an empty list. + """ + return getattr(request, "_messages", []) + + +def get_level(request): + """ + Return the minimum level of messages to be recorded. + + The default level is the ``MESSAGE_LEVEL`` setting. If this is not found, + use the ``INFO`` level. + """ + storage = getattr(request, "_messages", default_storage(request)) + return storage.level + + +def set_level(request, level): + """ + Set the minimum level of messages to be recorded, and return ``True`` if + the level was recorded successfully. + + If set to ``None``, use the default level (see the get_level() function). + """ + if not hasattr(request, "_messages"): + return False + request._messages.level = level + return True + + +def debug(request, message, extra_tags="", fail_silently=False): + """Add a message with the ``DEBUG`` level.""" + add_message( + request, + constants.DEBUG, + message, + extra_tags=extra_tags, + fail_silently=fail_silently, + ) + + +def info(request, message, extra_tags="", fail_silently=False): + """Add a message with the ``INFO`` level.""" + add_message( + request, + constants.INFO, + message, + extra_tags=extra_tags, + fail_silently=fail_silently, + ) + + +def success(request, message, extra_tags="", fail_silently=False): + """Add a message with the ``SUCCESS`` level.""" + add_message( + request, + constants.SUCCESS, + message, + extra_tags=extra_tags, + fail_silently=fail_silently, + ) + + +def warning(request, message, extra_tags="", fail_silently=False): + """Add a message with the ``WARNING`` level.""" + add_message( + request, + constants.WARNING, + message, + extra_tags=extra_tags, + fail_silently=fail_silently, + ) + + +def error(request, message, extra_tags="", fail_silently=False): + """Add a message with the ``ERROR`` level.""" + add_message( + request, + constants.ERROR, + message, + extra_tags=extra_tags, + fail_silently=fail_silently, + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/apps.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/apps.py new file mode 100644 index 0000000..5bda152 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/apps.py @@ -0,0 +1,19 @@ +from django.apps import AppConfig +from django.contrib.messages.storage import base +from django.contrib.messages.utils import get_level_tags +from django.core.signals import setting_changed +from django.utils.functional import SimpleLazyObject +from django.utils.translation import gettext_lazy as _ + + +def update_level_tags(setting, **kwargs): + if setting == "MESSAGE_TAGS": + base.LEVEL_TAGS = SimpleLazyObject(get_level_tags) + + +class MessagesConfig(AppConfig): + name = "django.contrib.messages" + verbose_name = _("Messages") + + def ready(self): + setting_changed.connect(update_level_tags) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/constants.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/constants.py new file mode 100644 index 0000000..92c9242 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/constants.py @@ -0,0 +1,21 @@ +DEBUG = 10 +INFO = 20 +SUCCESS = 25 +WARNING = 30 +ERROR = 40 + +DEFAULT_TAGS = { + DEBUG: "debug", + INFO: "info", + SUCCESS: "success", + WARNING: "warning", + ERROR: "error", +} + +DEFAULT_LEVELS = { + "DEBUG": DEBUG, + "INFO": INFO, + "SUCCESS": SUCCESS, + "WARNING": WARNING, + "ERROR": ERROR, +} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/context_processors.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/context_processors.py new file mode 100644 index 0000000..e01cc31 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/context_processors.py @@ -0,0 +1,13 @@ +from django.contrib.messages.api import get_messages +from django.contrib.messages.constants import DEFAULT_LEVELS + + +def messages(request): + """ + Return a lazy 'messages' context variable as well as + 'DEFAULT_MESSAGE_LEVELS'. + """ + return { + "messages": get_messages(request), + "DEFAULT_MESSAGE_LEVELS": DEFAULT_LEVELS, + } diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/middleware.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/middleware.py new file mode 100644 index 0000000..0087031 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/middleware.py @@ -0,0 +1,26 @@ +from django.conf import settings +from django.contrib.messages.storage import default_storage +from django.utils.deprecation import MiddlewareMixin + + +class MessageMiddleware(MiddlewareMixin): + """ + Middleware that handles temporary messages. + """ + + def process_request(self, request): + request._messages = default_storage(request) + + def process_response(self, request, response): + """ + Update the storage backend (i.e., save the messages). + + Raise ValueError if not all messages could be stored and DEBUG is True. + """ + # A higher middleware layer may return a request which does not contain + # messages storage, so make no assumption that it will be there. + if hasattr(request, "_messages"): + unstored_messages = request._messages.update(response) + if unstored_messages and settings.DEBUG: + raise ValueError("Not all temporary messages could be stored.") + return response diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/storage/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/storage/__init__.py new file mode 100644 index 0000000..373dbba --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/storage/__init__.py @@ -0,0 +1,12 @@ +from django.conf import settings +from django.utils.module_loading import import_string + + +def default_storage(request): + """ + Callable with the same interface as the storage classes. + + This isn't just default_storage = import_string(settings.MESSAGE_STORAGE) + to avoid accessing the settings at the module level. + """ + return import_string(settings.MESSAGE_STORAGE)(request) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/storage/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/storage/base.py new file mode 100644 index 0000000..5d89acf --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/storage/base.py @@ -0,0 +1,183 @@ +from django.conf import settings +from django.contrib.messages import constants, utils +from django.utils.functional import SimpleLazyObject + +LEVEL_TAGS = SimpleLazyObject(utils.get_level_tags) + + +class Message: + """ + Represent an actual message that can be stored in any of the supported + storage classes (typically session- or cookie-based) and rendered in a view + or template. + """ + + def __init__(self, level, message, extra_tags=None): + self.level = int(level) + self.message = message + self.extra_tags = extra_tags + + def _prepare(self): + """ + Prepare the message for serialization by forcing the ``message`` + and ``extra_tags`` to str in case they are lazy translations. + """ + self.message = str(self.message) + self.extra_tags = str(self.extra_tags) if self.extra_tags is not None else None + + def __eq__(self, other): + if not isinstance(other, Message): + return NotImplemented + return self.level == other.level and self.message == other.message + + def __str__(self): + return str(self.message) + + def __repr__(self): + extra_tags = f", extra_tags={self.extra_tags!r}" if self.extra_tags else "" + return f"Message(level={self.level}, message={self.message!r}{extra_tags})" + + @property + def tags(self): + return " ".join(tag for tag in [self.extra_tags, self.level_tag] if tag) + + @property + def level_tag(self): + return LEVEL_TAGS.get(self.level, "") + + +class BaseStorage: + """ + This is the base backend for temporary message storage. + + This is not a complete class; to be a usable storage backend, it must be + subclassed and the two methods ``_get`` and ``_store`` overridden. + """ + + def __init__(self, request, *args, **kwargs): + self.request = request + self._queued_messages = [] + self.used = False + self.added_new = False + super().__init__(*args, **kwargs) + + def __len__(self): + return len(self._loaded_messages) + len(self._queued_messages) + + def __iter__(self): + self.used = True + if self._queued_messages: + self._loaded_messages.extend(self._queued_messages) + self._queued_messages = [] + return iter(self._loaded_messages) + + def __contains__(self, item): + return item in self._loaded_messages or item in self._queued_messages + + def __repr__(self): + return f"<{self.__class__.__qualname__}: request={self.request!r}>" + + @property + def _loaded_messages(self): + """ + Return a list of loaded messages, retrieving them first if they have + not been loaded yet. + """ + if not hasattr(self, "_loaded_data"): + messages, all_retrieved = self._get() + self._loaded_data = messages or [] + return self._loaded_data + + def _get(self, *args, **kwargs): + """ + Retrieve a list of stored messages. Return a tuple of the messages + and a flag indicating whether or not all the messages originally + intended to be stored in this storage were, in fact, stored and + retrieved; e.g., ``(messages, all_retrieved)``. + + **This method must be implemented by a subclass.** + + If it is possible to tell if the backend was not used (as opposed to + just containing no messages) then ``None`` should be returned in + place of ``messages``. + """ + raise NotImplementedError( + "subclasses of BaseStorage must provide a _get() method" + ) + + def _store(self, messages, response, *args, **kwargs): + """ + Store a list of messages and return a list of any messages which could + not be stored. + + One type of object must be able to be stored, ``Message``. + + **This method must be implemented by a subclass.** + """ + raise NotImplementedError( + "subclasses of BaseStorage must provide a _store() method" + ) + + def _prepare_messages(self, messages): + """ + Prepare a list of messages for storage. + """ + for message in messages: + message._prepare() + + def update(self, response): + """ + Store all unread messages. + + If the backend has yet to be iterated, store previously stored messages + again. Otherwise, only store messages added after the last iteration. + """ + self._prepare_messages(self._queued_messages) + if self.used: + return self._store(self._queued_messages, response) + elif self.added_new: + messages = self._loaded_messages + self._queued_messages + return self._store(messages, response) + + def add(self, level, message, extra_tags=""): + """ + Queue a message to be stored. + + The message is only queued if it contained something and its level is + not less than the recording level (``self.level``). + """ + if not message: + return + # Check that the message level is not less than the recording level. + level = int(level) + if level < self.level: + return + # Add the message. + self.added_new = True + message = Message(level, message, extra_tags=extra_tags) + self._queued_messages.append(message) + + def _get_level(self): + """ + Return the minimum recorded level. + + The default level is the ``MESSAGE_LEVEL`` setting. If this is + not found, the ``INFO`` level is used. + """ + if not hasattr(self, "_level"): + self._level = getattr(settings, "MESSAGE_LEVEL", constants.INFO) + return self._level + + def _set_level(self, value=None): + """ + Set a custom minimum recorded level. + + If set to ``None``, the default level will be used (see the + ``_get_level`` method). + """ + if value is None and hasattr(self, "_level"): + del self._level + else: + self._level = int(value) + + level = property(_get_level, _set_level, _set_level) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/storage/cookie.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/storage/cookie.py new file mode 100644 index 0000000..2008b31 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/storage/cookie.py @@ -0,0 +1,248 @@ +import binascii +import json + +from django.conf import settings +from django.contrib.messages.storage.base import BaseStorage, Message +from django.core import signing +from django.http import SimpleCookie +from django.utils.safestring import SafeData, mark_safe + + +class MessageEncoder(json.JSONEncoder): + """ + Compactly serialize instances of the ``Message`` class as JSON. + """ + + message_key = "__json_message" + + def default(self, obj): + if isinstance(obj, Message): + # Using 0/1 here instead of False/True to produce more compact json + is_safedata = 1 if isinstance(obj.message, SafeData) else 0 + message = [self.message_key, is_safedata, obj.level, obj.message] + if obj.extra_tags is not None: + message.append(obj.extra_tags) + return message + return super().default(obj) + + +class MessageDecoder(json.JSONDecoder): + """ + Decode JSON that includes serialized ``Message`` instances. + """ + + def process_messages(self, obj): + if isinstance(obj, list) and obj: + if obj[0] == MessageEncoder.message_key: + if obj[1]: + obj[3] = mark_safe(obj[3]) + return Message(*obj[2:]) + return [self.process_messages(item) for item in obj] + if isinstance(obj, dict): + return {key: self.process_messages(value) for key, value in obj.items()} + return obj + + def decode(self, s, **kwargs): + decoded = super().decode(s, **kwargs) + return self.process_messages(decoded) + + +class MessagePartSerializer: + def dumps(self, obj): + return [ + json.dumps( + o, + separators=(",", ":"), + cls=MessageEncoder, + ) + for o in obj + ] + + +class MessagePartGatherSerializer: + def dumps(self, obj): + """ + The parameter is an already serialized list of Message objects. No need + to serialize it again, only join the list together and encode it. + """ + return ("[" + ",".join(obj) + "]").encode("latin-1") + + +class MessageSerializer: + def loads(self, data): + return json.loads(data.decode("latin-1"), cls=MessageDecoder) + + +class CookieStorage(BaseStorage): + """ + Store messages in a cookie. + """ + + cookie_name = "messages" + # uwsgi's default configuration enforces a maximum size of 4kb for all the + # HTTP headers. In order to leave some room for other cookies and headers, + # restrict the session cookie to 1/2 of 4kb. See #18781. + max_cookie_size = 2048 + not_finished = "__messagesnotfinished__" + not_finished_json = json.dumps("__messagesnotfinished__") + key_salt = "django.contrib.messages" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.signer = signing.get_cookie_signer(salt=self.key_salt) + + def _get(self, *args, **kwargs): + """ + Retrieve a list of messages from the messages cookie. If the + not_finished sentinel value is found at the end of the message list, + remove it and return a result indicating that not all messages were + retrieved by this storage. + """ + data = self.request.COOKIES.get(self.cookie_name) + messages = self._decode(data) + all_retrieved = not (messages and messages[-1] == self.not_finished) + if messages and not all_retrieved: + # remove the sentinel value + messages.pop() + return messages, all_retrieved + + def _update_cookie(self, encoded_data, response): + """ + Either set the cookie with the encoded data if there is any data to + store, or delete the cookie. + """ + if encoded_data: + response.set_cookie( + self.cookie_name, + encoded_data, + domain=settings.SESSION_COOKIE_DOMAIN, + secure=settings.SESSION_COOKIE_SECURE or None, + httponly=settings.SESSION_COOKIE_HTTPONLY or None, + samesite=settings.SESSION_COOKIE_SAMESITE, + ) + else: + response.delete_cookie( + self.cookie_name, + domain=settings.SESSION_COOKIE_DOMAIN, + samesite=settings.SESSION_COOKIE_SAMESITE, + ) + + def _store(self, messages, response, remove_oldest=True, *args, **kwargs): + """ + Store the messages to a cookie and return a list of any messages which + could not be stored. + + If the encoded data is larger than ``max_cookie_size``, remove + messages until the data fits (these are the messages which are + returned), and add the not_finished sentinel value to indicate as much. + """ + unstored_messages = [] + serialized_messages = MessagePartSerializer().dumps(messages) + encoded_data = self._encode_parts(serialized_messages) + if self.max_cookie_size: + # data is going to be stored eventually by SimpleCookie, which + # adds its own overhead, which we must account for. + cookie = SimpleCookie() # create outside the loop + + def is_too_large_for_cookie(data): + return data and len(cookie.value_encode(data)[1]) > self.max_cookie_size + + def compute_msg(some_serialized_msg): + return self._encode_parts( + some_serialized_msg + [self.not_finished_json], + encode_empty=True, + ) + + if is_too_large_for_cookie(encoded_data): + if remove_oldest: + idx = bisect_keep_right( + serialized_messages, + fn=lambda m: is_too_large_for_cookie(compute_msg(m)), + ) + unstored_messages = messages[:idx] + encoded_data = compute_msg(serialized_messages[idx:]) + else: + idx = bisect_keep_left( + serialized_messages, + fn=lambda m: is_too_large_for_cookie(compute_msg(m)), + ) + unstored_messages = messages[idx:] + encoded_data = compute_msg(serialized_messages[:idx]) + + self._update_cookie(encoded_data, response) + return unstored_messages + + def _encode_parts(self, messages, encode_empty=False): + """ + Return an encoded version of the serialized messages list which can be + stored as plain text. + + Since the data will be retrieved from the client-side, the encoded data + also contains a hash to ensure that the data was not tampered with. + """ + if messages or encode_empty: + return self.signer.sign_object( + messages, serializer=MessagePartGatherSerializer, compress=True + ) + + def _encode(self, messages, encode_empty=False): + """ + Return an encoded version of the messages list which can be stored as + plain text. + + Proxies MessagePartSerializer.dumps and _encoded_parts. + """ + serialized_messages = MessagePartSerializer().dumps(messages) + return self._encode_parts(serialized_messages, encode_empty=encode_empty) + + def _decode(self, data): + """ + Safely decode an encoded text stream back into a list of messages. + + If the encoded text stream contained an invalid hash or was in an + invalid format, return None. + """ + if not data: + return None + try: + return self.signer.unsign_object(data, serializer=MessageSerializer) + except (signing.BadSignature, binascii.Error, json.JSONDecodeError): + pass + # Mark the data as used (so it gets removed) since something was wrong + # with the data. + self.used = True + return None + + +def bisect_keep_left(a, fn): + """ + Find the index of the first element from the start of the array that + verifies the given condition. + The function is applied from the start of the array to the pivot. + """ + lo = 0 + hi = len(a) + while lo < hi: + mid = (lo + hi) // 2 + if fn(a[: mid + 1]): + hi = mid + else: + lo = mid + 1 + return lo + + +def bisect_keep_right(a, fn): + """ + Find the index of the first element from the end of the array that verifies + the given condition. + The function is applied from the pivot to the end of array. + """ + lo = 0 + hi = len(a) + while lo < hi: + mid = (lo + hi) // 2 + if fn(a[mid:]): + lo = mid + 1 + else: + hi = mid + return lo diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/storage/fallback.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/storage/fallback.py new file mode 100644 index 0000000..44e26fa --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/storage/fallback.py @@ -0,0 +1,56 @@ +from django.contrib.messages.storage.base import BaseStorage +from django.contrib.messages.storage.cookie import CookieStorage +from django.contrib.messages.storage.session import SessionStorage + + +class FallbackStorage(BaseStorage): + """ + Try to store all messages in the first backend. Store any unstored + messages in each subsequent backend. + """ + + storage_classes = (CookieStorage, SessionStorage) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.storages = [ + storage_class(*args, **kwargs) for storage_class in self.storage_classes + ] + self._used_storages = set() + + def _get(self, *args, **kwargs): + """ + Get a single list of messages from all storage backends. + """ + all_messages = [] + for storage in self.storages: + messages, all_retrieved = storage._get() + # If the backend hasn't been used, no more retrieval is necessary. + if messages is None: + break + if messages: + self._used_storages.add(storage) + all_messages.extend(messages) + # If this storage class contained all the messages, no further + # retrieval is necessary + if all_retrieved: + break + return all_messages, all_retrieved + + def _store(self, messages, response, *args, **kwargs): + """ + Store the messages and return any unstored messages after trying all + backends. + + For each storage backend, any messages not stored are passed on to the + next backend. + """ + for storage in self.storages: + if messages: + messages = storage._store(messages, response, remove_oldest=False) + # Even if there are no more messages, continue iterating to ensure + # storages which contained messages are flushed. + elif storage in self._used_storages: + storage._store([], response) + self._used_storages.remove(storage) + return messages diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/storage/session.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/storage/session.py new file mode 100644 index 0000000..3271c92 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/storage/session.py @@ -0,0 +1,52 @@ +import json + +from django.contrib.messages.storage.base import BaseStorage +from django.contrib.messages.storage.cookie import MessageDecoder, MessageEncoder +from django.core.exceptions import ImproperlyConfigured + + +class SessionStorage(BaseStorage): + """ + Store messages in the session (that is, django.contrib.sessions). + """ + + session_key = "_messages" + + def __init__(self, request, *args, **kwargs): + if not hasattr(request, "session"): + raise ImproperlyConfigured( + "The session-based temporary message storage requires session " + "middleware to be installed, and come before the message " + "middleware in the MIDDLEWARE list." + ) + super().__init__(request, *args, **kwargs) + + def _get(self, *args, **kwargs): + """ + Retrieve a list of messages from the request's session. This storage + always stores everything it is given, so return True for the + all_retrieved flag. + """ + return ( + self.deserialize_messages(self.request.session.get(self.session_key)), + True, + ) + + def _store(self, messages, response, *args, **kwargs): + """ + Store a list of messages to the request's session. + """ + if messages: + self.request.session[self.session_key] = self.serialize_messages(messages) + else: + self.request.session.pop(self.session_key, None) + return [] + + def serialize_messages(self, messages): + encoder = MessageEncoder() + return encoder.encode(messages) + + def deserialize_messages(self, data): + if data and isinstance(data, str): + return json.loads(data, cls=MessageDecoder) + return data diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/test.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/test.py new file mode 100644 index 0000000..3a69f54 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/test.py @@ -0,0 +1,8 @@ +from .api import get_messages + + +class MessagesTestMixin: + def assertMessages(self, response, expected_messages, *, ordered=True): + request_messages = list(get_messages(response.wsgi_request)) + assertion = self.assertEqual if ordered else self.assertCountEqual + assertion(request_messages, expected_messages) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/utils.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/utils.py new file mode 100644 index 0000000..0dd8873 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/utils.py @@ -0,0 +1,12 @@ +from django.conf import settings +from django.contrib.messages import constants + + +def get_level_tags(): + """ + Return the message level tags. + """ + return { + **constants.DEFAULT_TAGS, + **getattr(settings, "MESSAGE_TAGS", {}), + } diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/views.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/views.py new file mode 100644 index 0000000..38dee9b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/messages/views.py @@ -0,0 +1,19 @@ +from django.contrib import messages + + +class SuccessMessageMixin: + """ + Add a success message on successful form submission. + """ + + success_message = "" + + def form_valid(self, form): + response = super().form_valid(form) + success_message = self.get_success_message(form.cleaned_data) + if success_message: + messages.success(self.request, success_message) + return response + + def get_success_message(self, cleaned_data): + return self.success_message % cleaned_data diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/aggregates/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/aggregates/__init__.py new file mode 100644 index 0000000..4bfbd52 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/aggregates/__init__.py @@ -0,0 +1,2 @@ +from .general import * # NOQA +from .statistics import * # NOQA diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/aggregates/general.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/aggregates/general.py new file mode 100644 index 0000000..c8eea10 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/aggregates/general.py @@ -0,0 +1,98 @@ +import json +import warnings + +from django.contrib.postgres.fields import ArrayField +from django.db.models import Aggregate, BooleanField, JSONField, TextField, Value +from django.utils.deprecation import RemovedInDjango51Warning + +from .mixins import OrderableAggMixin + +__all__ = [ + "ArrayAgg", + "BitAnd", + "BitOr", + "BitXor", + "BoolAnd", + "BoolOr", + "JSONBAgg", + "StringAgg", +] + + +class ArrayAgg(OrderableAggMixin, Aggregate): + function = "ARRAY_AGG" + template = "%(function)s(%(distinct)s%(expressions)s %(ordering)s)" + allow_distinct = True + + @property + def output_field(self): + return ArrayField(self.source_expressions[0].output_field) + + +class BitAnd(Aggregate): + function = "BIT_AND" + + +class BitOr(Aggregate): + function = "BIT_OR" + + +class BitXor(Aggregate): + function = "BIT_XOR" + + +class BoolAnd(Aggregate): + function = "BOOL_AND" + output_field = BooleanField() + + +class BoolOr(Aggregate): + function = "BOOL_OR" + output_field = BooleanField() + + +class JSONBAgg(OrderableAggMixin, Aggregate): + function = "JSONB_AGG" + template = "%(function)s(%(distinct)s%(expressions)s %(ordering)s)" + allow_distinct = True + output_field = JSONField() + + # RemovedInDjango51Warning: When the deprecation ends, remove __init__(). + def __init__(self, *expressions, default=None, **extra): + super().__init__(*expressions, default=default, **extra) + if ( + isinstance(default, Value) + and isinstance(default.value, str) + and not isinstance(default.output_field, JSONField) + ): + value = default.value + try: + decoded = json.loads(value) + except json.JSONDecodeError: + warnings.warn( + "Passing a Value() with an output_field that isn't a JSONField as " + "JSONBAgg(default) is deprecated. Pass default=" + f"Value({value!r}, output_field=JSONField()) instead.", + stacklevel=2, + category=RemovedInDjango51Warning, + ) + self.default.output_field = self.output_field + else: + self.default = Value(decoded, self.output_field) + warnings.warn( + "Passing an encoded JSON string as JSONBAgg(default) is " + f"deprecated. Pass default={decoded!r} instead.", + stacklevel=2, + category=RemovedInDjango51Warning, + ) + + +class StringAgg(OrderableAggMixin, Aggregate): + function = "STRING_AGG" + template = "%(function)s(%(distinct)s%(expressions)s %(ordering)s)" + allow_distinct = True + output_field = TextField() + + def __init__(self, expression, delimiter, **extra): + delimiter_expr = Value(str(delimiter)) + super().__init__(expression, delimiter_expr, **extra) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/aggregates/mixins.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/aggregates/mixins.py new file mode 100644 index 0000000..340a917 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/aggregates/mixins.py @@ -0,0 +1,29 @@ +from django.db.models.expressions import OrderByList + + +class OrderableAggMixin: + def __init__(self, *expressions, ordering=(), **extra): + if isinstance(ordering, (list, tuple)): + self.order_by = OrderByList(*ordering) + else: + self.order_by = OrderByList(ordering) + super().__init__(*expressions, **extra) + + def resolve_expression(self, *args, **kwargs): + self.order_by = self.order_by.resolve_expression(*args, **kwargs) + return super().resolve_expression(*args, **kwargs) + + def get_source_expressions(self): + if self.order_by.source_expressions: + return super().get_source_expressions() + [self.order_by] + return super().get_source_expressions() + + def set_source_expressions(self, exprs): + if isinstance(exprs[-1], OrderByList): + *exprs, self.order_by = exprs + return super().set_source_expressions(exprs) + + def as_sql(self, compiler, connection): + order_by_sql, order_by_params = compiler.compile(self.order_by) + sql, sql_params = super().as_sql(compiler, connection, ordering=order_by_sql) + return sql, (*sql_params, *order_by_params) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/aggregates/statistics.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/aggregates/statistics.py new file mode 100644 index 0000000..3dc442b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/aggregates/statistics.py @@ -0,0 +1,75 @@ +from django.db.models import Aggregate, FloatField, IntegerField + +__all__ = [ + "CovarPop", + "Corr", + "RegrAvgX", + "RegrAvgY", + "RegrCount", + "RegrIntercept", + "RegrR2", + "RegrSlope", + "RegrSXX", + "RegrSXY", + "RegrSYY", + "StatAggregate", +] + + +class StatAggregate(Aggregate): + output_field = FloatField() + + def __init__(self, y, x, output_field=None, filter=None, default=None): + if not x or not y: + raise ValueError("Both y and x must be provided.") + super().__init__( + y, x, output_field=output_field, filter=filter, default=default + ) + + +class Corr(StatAggregate): + function = "CORR" + + +class CovarPop(StatAggregate): + def __init__(self, y, x, sample=False, filter=None, default=None): + self.function = "COVAR_SAMP" if sample else "COVAR_POP" + super().__init__(y, x, filter=filter, default=default) + + +class RegrAvgX(StatAggregate): + function = "REGR_AVGX" + + +class RegrAvgY(StatAggregate): + function = "REGR_AVGY" + + +class RegrCount(StatAggregate): + function = "REGR_COUNT" + output_field = IntegerField() + empty_result_set_value = 0 + + +class RegrIntercept(StatAggregate): + function = "REGR_INTERCEPT" + + +class RegrR2(StatAggregate): + function = "REGR_R2" + + +class RegrSlope(StatAggregate): + function = "REGR_SLOPE" + + +class RegrSXX(StatAggregate): + function = "REGR_SXX" + + +class RegrSXY(StatAggregate): + function = "REGR_SXY" + + +class RegrSYY(StatAggregate): + function = "REGR_SYY" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/apps.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/apps.py new file mode 100644 index 0000000..a8ee3fb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/apps.py @@ -0,0 +1,84 @@ +from django.apps import AppConfig +from django.core.signals import setting_changed +from django.db import connections +from django.db.backends.postgresql.psycopg_any import RANGE_TYPES +from django.db.backends.signals import connection_created +from django.db.migrations.writer import MigrationWriter +from django.db.models import CharField, OrderBy, TextField +from django.db.models.functions import Collate +from django.db.models.indexes import IndexExpression +from django.utils.translation import gettext_lazy as _ + +from .indexes import OpClass +from .lookups import ( + SearchLookup, + TrigramSimilar, + TrigramStrictWordSimilar, + TrigramWordSimilar, + Unaccent, +) +from .serializers import RangeSerializer +from .signals import register_type_handlers + + +def uninstall_if_needed(setting, value, enter, **kwargs): + """ + Undo the effects of PostgresConfig.ready() when django.contrib.postgres + is "uninstalled" by override_settings(). + """ + if ( + not enter + and setting == "INSTALLED_APPS" + and "django.contrib.postgres" not in set(value) + ): + connection_created.disconnect(register_type_handlers) + CharField._unregister_lookup(Unaccent) + TextField._unregister_lookup(Unaccent) + CharField._unregister_lookup(SearchLookup) + TextField._unregister_lookup(SearchLookup) + CharField._unregister_lookup(TrigramSimilar) + TextField._unregister_lookup(TrigramSimilar) + CharField._unregister_lookup(TrigramWordSimilar) + TextField._unregister_lookup(TrigramWordSimilar) + CharField._unregister_lookup(TrigramStrictWordSimilar) + TextField._unregister_lookup(TrigramStrictWordSimilar) + # Disconnect this receiver until the next time this app is installed + # and ready() connects it again to prevent unnecessary processing on + # each setting change. + setting_changed.disconnect(uninstall_if_needed) + MigrationWriter.unregister_serializer(RANGE_TYPES) + + +class PostgresConfig(AppConfig): + name = "django.contrib.postgres" + verbose_name = _("PostgreSQL extensions") + + def ready(self): + setting_changed.connect(uninstall_if_needed) + # Connections may already exist before we are called. + for conn in connections.all(initialized_only=True): + if conn.vendor == "postgresql": + conn.introspection.data_types_reverse.update( + { + 3904: "django.contrib.postgres.fields.IntegerRangeField", + 3906: "django.contrib.postgres.fields.DecimalRangeField", + 3910: "django.contrib.postgres.fields.DateTimeRangeField", + 3912: "django.contrib.postgres.fields.DateRangeField", + 3926: "django.contrib.postgres.fields.BigIntegerRangeField", + } + ) + if conn.connection is not None: + register_type_handlers(conn) + connection_created.connect(register_type_handlers) + CharField.register_lookup(Unaccent) + TextField.register_lookup(Unaccent) + CharField.register_lookup(SearchLookup) + TextField.register_lookup(SearchLookup) + CharField.register_lookup(TrigramSimilar) + TextField.register_lookup(TrigramSimilar) + CharField.register_lookup(TrigramWordSimilar) + TextField.register_lookup(TrigramWordSimilar) + CharField.register_lookup(TrigramStrictWordSimilar) + TextField.register_lookup(TrigramStrictWordSimilar) + MigrationWriter.register_serializer(RANGE_TYPES, RangeSerializer) + IndexExpression.register_wrappers(OrderBy, OpClass, Collate) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/constraints.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/constraints.py new file mode 100644 index 0000000..c61072b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/constraints.py @@ -0,0 +1,227 @@ +from types import NoneType + +from django.contrib.postgres.indexes import OpClass +from django.core.exceptions import ValidationError +from django.db import DEFAULT_DB_ALIAS, NotSupportedError +from django.db.backends.ddl_references import Expressions, Statement, Table +from django.db.models import BaseConstraint, Deferrable, F, Q +from django.db.models.expressions import Exists, ExpressionList +from django.db.models.indexes import IndexExpression +from django.db.models.lookups import PostgresOperatorLookup +from django.db.models.sql import Query + +__all__ = ["ExclusionConstraint"] + + +class ExclusionConstraintExpression(IndexExpression): + template = "%(expressions)s WITH %(operator)s" + + +class ExclusionConstraint(BaseConstraint): + template = ( + "CONSTRAINT %(name)s EXCLUDE USING %(index_type)s " + "(%(expressions)s)%(include)s%(where)s%(deferrable)s" + ) + + def __init__( + self, + *, + name, + expressions, + index_type=None, + condition=None, + deferrable=None, + include=None, + violation_error_code=None, + violation_error_message=None, + ): + if index_type and index_type.lower() not in {"gist", "spgist"}: + raise ValueError( + "Exclusion constraints only support GiST or SP-GiST indexes." + ) + if not expressions: + raise ValueError( + "At least one expression is required to define an exclusion " + "constraint." + ) + if not all( + isinstance(expr, (list, tuple)) and len(expr) == 2 for expr in expressions + ): + raise ValueError("The expressions must be a list of 2-tuples.") + if not isinstance(condition, (NoneType, Q)): + raise ValueError("ExclusionConstraint.condition must be a Q instance.") + if not isinstance(deferrable, (NoneType, Deferrable)): + raise ValueError( + "ExclusionConstraint.deferrable must be a Deferrable instance." + ) + if not isinstance(include, (NoneType, list, tuple)): + raise ValueError("ExclusionConstraint.include must be a list or tuple.") + self.expressions = expressions + self.index_type = index_type or "GIST" + self.condition = condition + self.deferrable = deferrable + self.include = tuple(include) if include else () + super().__init__( + name=name, + violation_error_code=violation_error_code, + violation_error_message=violation_error_message, + ) + + def _get_expressions(self, schema_editor, query): + expressions = [] + for idx, (expression, operator) in enumerate(self.expressions): + if isinstance(expression, str): + expression = F(expression) + expression = ExclusionConstraintExpression(expression, operator=operator) + expression.set_wrapper_classes(schema_editor.connection) + expressions.append(expression) + return ExpressionList(*expressions).resolve_expression(query) + + def _get_condition_sql(self, compiler, schema_editor, query): + if self.condition is None: + return None + where = query.build_where(self.condition) + sql, params = where.as_sql(compiler, schema_editor.connection) + return sql % tuple(schema_editor.quote_value(p) for p in params) + + def constraint_sql(self, model, schema_editor): + query = Query(model, alias_cols=False) + compiler = query.get_compiler(connection=schema_editor.connection) + expressions = self._get_expressions(schema_editor, query) + table = model._meta.db_table + condition = self._get_condition_sql(compiler, schema_editor, query) + include = [ + model._meta.get_field(field_name).column for field_name in self.include + ] + return Statement( + self.template, + table=Table(table, schema_editor.quote_name), + name=schema_editor.quote_name(self.name), + index_type=self.index_type, + expressions=Expressions( + table, expressions, compiler, schema_editor.quote_value + ), + where=" WHERE (%s)" % condition if condition else "", + include=schema_editor._index_include_sql(model, include), + deferrable=schema_editor._deferrable_constraint_sql(self.deferrable), + ) + + def create_sql(self, model, schema_editor): + self.check_supported(schema_editor) + return Statement( + "ALTER TABLE %(table)s ADD %(constraint)s", + table=Table(model._meta.db_table, schema_editor.quote_name), + constraint=self.constraint_sql(model, schema_editor), + ) + + def remove_sql(self, model, schema_editor): + return schema_editor._delete_constraint_sql( + schema_editor.sql_delete_check, + model, + schema_editor.quote_name(self.name), + ) + + def check_supported(self, schema_editor): + if ( + self.include + and self.index_type.lower() == "spgist" + and not schema_editor.connection.features.supports_covering_spgist_indexes + ): + raise NotSupportedError( + "Covering exclusion constraints using an SP-GiST index " + "require PostgreSQL 14+." + ) + + def deconstruct(self): + path, args, kwargs = super().deconstruct() + kwargs["expressions"] = self.expressions + if self.condition is not None: + kwargs["condition"] = self.condition + if self.index_type.lower() != "gist": + kwargs["index_type"] = self.index_type + if self.deferrable: + kwargs["deferrable"] = self.deferrable + if self.include: + kwargs["include"] = self.include + return path, args, kwargs + + def __eq__(self, other): + if isinstance(other, self.__class__): + return ( + self.name == other.name + and self.index_type == other.index_type + and self.expressions == other.expressions + and self.condition == other.condition + and self.deferrable == other.deferrable + and self.include == other.include + and self.violation_error_code == other.violation_error_code + and self.violation_error_message == other.violation_error_message + ) + return super().__eq__(other) + + def __repr__(self): + return "<%s: index_type=%s expressions=%s name=%s%s%s%s%s%s>" % ( + self.__class__.__qualname__, + repr(self.index_type), + repr(self.expressions), + repr(self.name), + "" if self.condition is None else " condition=%s" % self.condition, + "" if self.deferrable is None else " deferrable=%r" % self.deferrable, + "" if not self.include else " include=%s" % repr(self.include), + ( + "" + if self.violation_error_code is None + else " violation_error_code=%r" % self.violation_error_code + ), + ( + "" + if self.violation_error_message is None + or self.violation_error_message == self.default_violation_error_message + else " violation_error_message=%r" % self.violation_error_message + ), + ) + + def validate(self, model, instance, exclude=None, using=DEFAULT_DB_ALIAS): + queryset = model._default_manager.using(using) + replacement_map = instance._get_field_value_map( + meta=model._meta, exclude=exclude + ) + replacements = {F(field): value for field, value in replacement_map.items()} + lookups = [] + for idx, (expression, operator) in enumerate(self.expressions): + if isinstance(expression, str): + expression = F(expression) + if exclude: + if isinstance(expression, F): + if expression.name in exclude: + return + else: + for expr in expression.flatten(): + if isinstance(expr, F) and expr.name in exclude: + return + rhs_expression = expression.replace_expressions(replacements) + # Remove OpClass because it only has sense during the constraint + # creation. + if isinstance(expression, OpClass): + expression = expression.get_source_expressions()[0] + if isinstance(rhs_expression, OpClass): + rhs_expression = rhs_expression.get_source_expressions()[0] + lookup = PostgresOperatorLookup(lhs=expression, rhs=rhs_expression) + lookup.postgres_operator = operator + lookups.append(lookup) + queryset = queryset.filter(*lookups) + model_class_pk = instance._get_pk_val(model._meta) + if not instance._state.adding and model_class_pk is not None: + queryset = queryset.exclude(pk=model_class_pk) + if not self.condition: + if queryset.exists(): + raise ValidationError( + self.get_violation_error_message(), code=self.violation_error_code + ) + else: + if (self.condition & Exists(queryset.filter(self.condition))).check( + replacement_map, using=using + ): + raise ValidationError( + self.get_violation_error_message(), code=self.violation_error_code + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/expressions.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/expressions.py new file mode 100644 index 0000000..469f4e9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/expressions.py @@ -0,0 +1,14 @@ +from django.contrib.postgres.fields import ArrayField +from django.db.models import Subquery +from django.utils.functional import cached_property + + +class ArraySubquery(Subquery): + template = "ARRAY(%(subquery)s)" + + def __init__(self, queryset, **kwargs): + super().__init__(queryset, **kwargs) + + @cached_property + def output_field(self): + return ArrayField(self.query.output_field) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/fields/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/fields/__init__.py new file mode 100644 index 0000000..ef11027 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/fields/__init__.py @@ -0,0 +1,5 @@ +from .array import * # NOQA +from .citext import * # NOQA +from .hstore import * # NOQA +from .jsonb import * # NOQA +from .ranges import * # NOQA diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/fields/array.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/fields/array.py new file mode 100644 index 0000000..c8e8e13 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/fields/array.py @@ -0,0 +1,365 @@ +import json + +from django.contrib.postgres import lookups +from django.contrib.postgres.forms import SimpleArrayField +from django.contrib.postgres.validators import ArrayMaxLengthValidator +from django.core import checks, exceptions +from django.db.models import Field, Func, IntegerField, Transform, Value +from django.db.models.fields.mixins import CheckFieldDefaultMixin +from django.db.models.lookups import Exact, In +from django.utils.translation import gettext_lazy as _ + +from ..utils import prefix_validation_error +from .utils import AttributeSetter + +__all__ = ["ArrayField"] + + +class ArrayField(CheckFieldDefaultMixin, Field): + empty_strings_allowed = False + default_error_messages = { + "item_invalid": _("Item %(nth)s in the array did not validate:"), + "nested_array_mismatch": _("Nested arrays must have the same length."), + } + _default_hint = ("list", "[]") + + def __init__(self, base_field, size=None, **kwargs): + self.base_field = base_field + self.db_collation = getattr(self.base_field, "db_collation", None) + self.size = size + if self.size: + self.default_validators = [ + *self.default_validators, + ArrayMaxLengthValidator(self.size), + ] + # For performance, only add a from_db_value() method if the base field + # implements it. + if hasattr(self.base_field, "from_db_value"): + self.from_db_value = self._from_db_value + super().__init__(**kwargs) + + @property + def model(self): + try: + return self.__dict__["model"] + except KeyError: + raise AttributeError( + "'%s' object has no attribute 'model'" % self.__class__.__name__ + ) + + @model.setter + def model(self, model): + self.__dict__["model"] = model + self.base_field.model = model + + @classmethod + def _choices_is_value(cls, value): + return isinstance(value, (list, tuple)) or super()._choices_is_value(value) + + def check(self, **kwargs): + errors = super().check(**kwargs) + if self.base_field.remote_field: + errors.append( + checks.Error( + "Base field for array cannot be a related field.", + obj=self, + id="postgres.E002", + ) + ) + else: + # Remove the field name checks as they are not needed here. + base_checks = self.base_field.check() + if base_checks: + error_messages = "\n ".join( + "%s (%s)" % (base_check.msg, base_check.id) + for base_check in base_checks + if isinstance(base_check, checks.Error) + ) + if error_messages: + errors.append( + checks.Error( + "Base field for array has errors:\n %s" % error_messages, + obj=self, + id="postgres.E001", + ) + ) + warning_messages = "\n ".join( + "%s (%s)" % (base_check.msg, base_check.id) + for base_check in base_checks + if isinstance(base_check, checks.Warning) + ) + if warning_messages: + errors.append( + checks.Warning( + "Base field for array has warnings:\n %s" + % warning_messages, + obj=self, + id="postgres.W004", + ) + ) + return errors + + def set_attributes_from_name(self, name): + super().set_attributes_from_name(name) + self.base_field.set_attributes_from_name(name) + + @property + def description(self): + return "Array of %s" % self.base_field.description + + def db_type(self, connection): + size = self.size or "" + return "%s[%s]" % (self.base_field.db_type(connection), size) + + def cast_db_type(self, connection): + size = self.size or "" + return "%s[%s]" % (self.base_field.cast_db_type(connection), size) + + def db_parameters(self, connection): + db_params = super().db_parameters(connection) + db_params["collation"] = self.db_collation + return db_params + + def get_placeholder(self, value, compiler, connection): + return "%s::{}".format(self.db_type(connection)) + + def get_db_prep_value(self, value, connection, prepared=False): + if isinstance(value, (list, tuple)): + return [ + self.base_field.get_db_prep_value(i, connection, prepared=False) + for i in value + ] + return value + + def deconstruct(self): + name, path, args, kwargs = super().deconstruct() + if path == "django.contrib.postgres.fields.array.ArrayField": + path = "django.contrib.postgres.fields.ArrayField" + kwargs.update( + { + "base_field": self.base_field.clone(), + "size": self.size, + } + ) + return name, path, args, kwargs + + def to_python(self, value): + if isinstance(value, str): + # Assume we're deserializing + vals = json.loads(value) + value = [self.base_field.to_python(val) for val in vals] + return value + + def _from_db_value(self, value, expression, connection): + if value is None: + return value + return [ + self.base_field.from_db_value(item, expression, connection) + for item in value + ] + + def value_to_string(self, obj): + values = [] + vals = self.value_from_object(obj) + base_field = self.base_field + + for val in vals: + if val is None: + values.append(None) + else: + obj = AttributeSetter(base_field.attname, val) + values.append(base_field.value_to_string(obj)) + return json.dumps(values) + + def get_transform(self, name): + transform = super().get_transform(name) + if transform: + return transform + if "_" not in name: + try: + index = int(name) + except ValueError: + pass + else: + index += 1 # postgres uses 1-indexing + return IndexTransformFactory(index, self.base_field) + try: + start, end = name.split("_") + start = int(start) + 1 + end = int(end) # don't add one here because postgres slices are weird + except ValueError: + pass + else: + return SliceTransformFactory(start, end) + + def validate(self, value, model_instance): + super().validate(value, model_instance) + for index, part in enumerate(value): + try: + self.base_field.validate(part, model_instance) + except exceptions.ValidationError as error: + raise prefix_validation_error( + error, + prefix=self.error_messages["item_invalid"], + code="item_invalid", + params={"nth": index + 1}, + ) + if isinstance(self.base_field, ArrayField): + if len({len(i) for i in value}) > 1: + raise exceptions.ValidationError( + self.error_messages["nested_array_mismatch"], + code="nested_array_mismatch", + ) + + def run_validators(self, value): + super().run_validators(value) + for index, part in enumerate(value): + try: + self.base_field.run_validators(part) + except exceptions.ValidationError as error: + raise prefix_validation_error( + error, + prefix=self.error_messages["item_invalid"], + code="item_invalid", + params={"nth": index + 1}, + ) + + def formfield(self, **kwargs): + return super().formfield( + **{ + "form_class": SimpleArrayField, + "base_field": self.base_field.formfield(), + "max_length": self.size, + **kwargs, + } + ) + + +class ArrayRHSMixin: + def __init__(self, lhs, rhs): + # Don't wrap arrays that contains only None values, psycopg doesn't + # allow this. + if isinstance(rhs, (tuple, list)) and any(self._rhs_not_none_values(rhs)): + expressions = [] + for value in rhs: + if not hasattr(value, "resolve_expression"): + field = lhs.output_field + value = Value(field.base_field.get_prep_value(value)) + expressions.append(value) + rhs = Func( + *expressions, + function="ARRAY", + template="%(function)s[%(expressions)s]", + ) + super().__init__(lhs, rhs) + + def process_rhs(self, compiler, connection): + rhs, rhs_params = super().process_rhs(compiler, connection) + cast_type = self.lhs.output_field.cast_db_type(connection) + return "%s::%s" % (rhs, cast_type), rhs_params + + def _rhs_not_none_values(self, rhs): + for x in rhs: + if isinstance(x, (list, tuple)): + yield from self._rhs_not_none_values(x) + elif x is not None: + yield True + + +@ArrayField.register_lookup +class ArrayContains(ArrayRHSMixin, lookups.DataContains): + pass + + +@ArrayField.register_lookup +class ArrayContainedBy(ArrayRHSMixin, lookups.ContainedBy): + pass + + +@ArrayField.register_lookup +class ArrayExact(ArrayRHSMixin, Exact): + pass + + +@ArrayField.register_lookup +class ArrayOverlap(ArrayRHSMixin, lookups.Overlap): + pass + + +@ArrayField.register_lookup +class ArrayLenTransform(Transform): + lookup_name = "len" + output_field = IntegerField() + + def as_sql(self, compiler, connection): + lhs, params = compiler.compile(self.lhs) + # Distinguish NULL and empty arrays + return ( + "CASE WHEN %(lhs)s IS NULL THEN NULL ELSE " + "coalesce(array_length(%(lhs)s, 1), 0) END" + ) % {"lhs": lhs}, params * 2 + + +@ArrayField.register_lookup +class ArrayInLookup(In): + def get_prep_lookup(self): + values = super().get_prep_lookup() + if hasattr(values, "resolve_expression"): + return values + # In.process_rhs() expects values to be hashable, so convert lists + # to tuples. + prepared_values = [] + for value in values: + if hasattr(value, "resolve_expression"): + prepared_values.append(value) + else: + prepared_values.append(tuple(value)) + return prepared_values + + +class IndexTransform(Transform): + def __init__(self, index, base_field, *args, **kwargs): + super().__init__(*args, **kwargs) + self.index = index + self.base_field = base_field + + def as_sql(self, compiler, connection): + lhs, params = compiler.compile(self.lhs) + if not lhs.endswith("]"): + lhs = "(%s)" % lhs + return "%s[%%s]" % lhs, (*params, self.index) + + @property + def output_field(self): + return self.base_field + + +class IndexTransformFactory: + def __init__(self, index, base_field): + self.index = index + self.base_field = base_field + + def __call__(self, *args, **kwargs): + return IndexTransform(self.index, self.base_field, *args, **kwargs) + + +class SliceTransform(Transform): + def __init__(self, start, end, *args, **kwargs): + super().__init__(*args, **kwargs) + self.start = start + self.end = end + + def as_sql(self, compiler, connection): + lhs, params = compiler.compile(self.lhs) + if not lhs.endswith("]"): + lhs = "(%s)" % lhs + return "%s[%%s:%%s]" % lhs, (*params, self.start, self.end) + + +class SliceTransformFactory: + def __init__(self, start, end): + self.start = start + self.end = end + + def __call__(self, *args, **kwargs): + return SliceTransform(self.start, self.end, *args, **kwargs) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/fields/citext.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/fields/citext.py new file mode 100644 index 0000000..2dac257 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/fields/citext.py @@ -0,0 +1,78 @@ +import warnings + +from django.db.models import CharField, EmailField, TextField +from django.test.utils import ignore_warnings +from django.utils.deprecation import RemovedInDjango51Warning + +__all__ = ["CICharField", "CIEmailField", "CIText", "CITextField"] + + +# RemovedInDjango51Warning. +class CIText: + def __init__(self, *args, **kwargs): + warnings.warn( + "django.contrib.postgres.fields.CIText mixin is deprecated.", + RemovedInDjango51Warning, + stacklevel=2, + ) + super().__init__(*args, **kwargs) + + def get_internal_type(self): + return "CI" + super().get_internal_type() + + def db_type(self, connection): + return "citext" + + +class CICharField(CIText, CharField): + system_check_deprecated_details = { + "msg": ( + "django.contrib.postgres.fields.CICharField is deprecated. Support for it " + "(except in historical migrations) will be removed in Django 5.1." + ), + "hint": ( + 'Use CharField(db_collation="…") with a case-insensitive non-deterministic ' + "collation instead." + ), + "id": "fields.W905", + } + + def __init__(self, *args, **kwargs): + with ignore_warnings(category=RemovedInDjango51Warning): + super().__init__(*args, **kwargs) + + +class CIEmailField(CIText, EmailField): + system_check_deprecated_details = { + "msg": ( + "django.contrib.postgres.fields.CIEmailField is deprecated. Support for it " + "(except in historical migrations) will be removed in Django 5.1." + ), + "hint": ( + 'Use EmailField(db_collation="…") with a case-insensitive ' + "non-deterministic collation instead." + ), + "id": "fields.W906", + } + + def __init__(self, *args, **kwargs): + with ignore_warnings(category=RemovedInDjango51Warning): + super().__init__(*args, **kwargs) + + +class CITextField(CIText, TextField): + system_check_deprecated_details = { + "msg": ( + "django.contrib.postgres.fields.CITextField is deprecated. Support for it " + "(except in historical migrations) will be removed in Django 5.1." + ), + "hint": ( + 'Use TextField(db_collation="…") with a case-insensitive non-deterministic ' + "collation instead." + ), + "id": "fields.W907", + } + + def __init__(self, *args, **kwargs): + with ignore_warnings(category=RemovedInDjango51Warning): + super().__init__(*args, **kwargs) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/fields/hstore.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/fields/hstore.py new file mode 100644 index 0000000..cfc156a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/fields/hstore.py @@ -0,0 +1,112 @@ +import json + +from django.contrib.postgres import forms, lookups +from django.contrib.postgres.fields.array import ArrayField +from django.core import exceptions +from django.db.models import Field, TextField, Transform +from django.db.models.fields.mixins import CheckFieldDefaultMixin +from django.utils.translation import gettext_lazy as _ + +__all__ = ["HStoreField"] + + +class HStoreField(CheckFieldDefaultMixin, Field): + empty_strings_allowed = False + description = _("Map of strings to strings/nulls") + default_error_messages = { + "not_a_string": _("The value of “%(key)s” is not a string or null."), + } + _default_hint = ("dict", "{}") + + def db_type(self, connection): + return "hstore" + + def get_transform(self, name): + transform = super().get_transform(name) + if transform: + return transform + return KeyTransformFactory(name) + + def validate(self, value, model_instance): + super().validate(value, model_instance) + for key, val in value.items(): + if not isinstance(val, str) and val is not None: + raise exceptions.ValidationError( + self.error_messages["not_a_string"], + code="not_a_string", + params={"key": key}, + ) + + def to_python(self, value): + if isinstance(value, str): + value = json.loads(value) + return value + + def value_to_string(self, obj): + return json.dumps(self.value_from_object(obj)) + + def formfield(self, **kwargs): + return super().formfield( + **{ + "form_class": forms.HStoreField, + **kwargs, + } + ) + + def get_prep_value(self, value): + value = super().get_prep_value(value) + + if isinstance(value, dict): + prep_value = {} + for key, val in value.items(): + key = str(key) + if val is not None: + val = str(val) + prep_value[key] = val + value = prep_value + + if isinstance(value, list): + value = [str(item) for item in value] + + return value + + +HStoreField.register_lookup(lookups.DataContains) +HStoreField.register_lookup(lookups.ContainedBy) +HStoreField.register_lookup(lookups.HasKey) +HStoreField.register_lookup(lookups.HasKeys) +HStoreField.register_lookup(lookups.HasAnyKeys) + + +class KeyTransform(Transform): + output_field = TextField() + + def __init__(self, key_name, *args, **kwargs): + super().__init__(*args, **kwargs) + self.key_name = key_name + + def as_sql(self, compiler, connection): + lhs, params = compiler.compile(self.lhs) + return "(%s -> %%s)" % lhs, tuple(params) + (self.key_name,) + + +class KeyTransformFactory: + def __init__(self, key_name): + self.key_name = key_name + + def __call__(self, *args, **kwargs): + return KeyTransform(self.key_name, *args, **kwargs) + + +@HStoreField.register_lookup +class KeysTransform(Transform): + lookup_name = "keys" + function = "akeys" + output_field = ArrayField(TextField()) + + +@HStoreField.register_lookup +class ValuesTransform(Transform): + lookup_name = "values" + function = "avals" + output_field = ArrayField(TextField()) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/fields/jsonb.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/fields/jsonb.py new file mode 100644 index 0000000..760b5d8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/fields/jsonb.py @@ -0,0 +1,14 @@ +from django.db.models import JSONField as BuiltinJSONField + +__all__ = ["JSONField"] + + +class JSONField(BuiltinJSONField): + system_check_removed_details = { + "msg": ( + "django.contrib.postgres.fields.JSONField is removed except for " + "support in historical migrations." + ), + "hint": "Use django.db.models.JSONField instead.", + "id": "fields.E904", + } diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/fields/ranges.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/fields/ranges.py new file mode 100644 index 0000000..fbb6012 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/fields/ranges.py @@ -0,0 +1,383 @@ +import datetime +import json + +from django.contrib.postgres import forms, lookups +from django.db import models +from django.db.backends.postgresql.psycopg_any import ( + DateRange, + DateTimeTZRange, + NumericRange, + Range, +) +from django.db.models.functions import Cast +from django.db.models.lookups import PostgresOperatorLookup + +from .utils import AttributeSetter + +__all__ = [ + "RangeField", + "IntegerRangeField", + "BigIntegerRangeField", + "DecimalRangeField", + "DateTimeRangeField", + "DateRangeField", + "RangeBoundary", + "RangeOperators", +] + + +class RangeBoundary(models.Expression): + """A class that represents range boundaries.""" + + def __init__(self, inclusive_lower=True, inclusive_upper=False): + self.lower = "[" if inclusive_lower else "(" + self.upper = "]" if inclusive_upper else ")" + + def as_sql(self, compiler, connection): + return "'%s%s'" % (self.lower, self.upper), [] + + +class RangeOperators: + # https://www.postgresql.org/docs/current/functions-range.html#RANGE-OPERATORS-TABLE + EQUAL = "=" + NOT_EQUAL = "<>" + CONTAINS = "@>" + CONTAINED_BY = "<@" + OVERLAPS = "&&" + FULLY_LT = "<<" + FULLY_GT = ">>" + NOT_LT = "&>" + NOT_GT = "&<" + ADJACENT_TO = "-|-" + + +class RangeField(models.Field): + empty_strings_allowed = False + + def __init__(self, *args, **kwargs): + if "default_bounds" in kwargs: + raise TypeError( + f"Cannot use 'default_bounds' with {self.__class__.__name__}." + ) + # Initializing base_field here ensures that its model matches the model + # for self. + if hasattr(self, "base_field"): + self.base_field = self.base_field() + super().__init__(*args, **kwargs) + + @property + def model(self): + try: + return self.__dict__["model"] + except KeyError: + raise AttributeError( + "'%s' object has no attribute 'model'" % self.__class__.__name__ + ) + + @model.setter + def model(self, model): + self.__dict__["model"] = model + self.base_field.model = model + + @classmethod + def _choices_is_value(cls, value): + return isinstance(value, (list, tuple)) or super()._choices_is_value(value) + + def get_placeholder(self, value, compiler, connection): + return "%s::{}".format(self.db_type(connection)) + + def get_prep_value(self, value): + if value is None: + return None + elif isinstance(value, Range): + return value + elif isinstance(value, (list, tuple)): + return self.range_type(value[0], value[1]) + return value + + def to_python(self, value): + if isinstance(value, str): + # Assume we're deserializing + vals = json.loads(value) + for end in ("lower", "upper"): + if end in vals: + vals[end] = self.base_field.to_python(vals[end]) + value = self.range_type(**vals) + elif isinstance(value, (list, tuple)): + value = self.range_type(value[0], value[1]) + return value + + def set_attributes_from_name(self, name): + super().set_attributes_from_name(name) + self.base_field.set_attributes_from_name(name) + + def value_to_string(self, obj): + value = self.value_from_object(obj) + if value is None: + return None + if value.isempty: + return json.dumps({"empty": True}) + base_field = self.base_field + result = {"bounds": value._bounds} + for end in ("lower", "upper"): + val = getattr(value, end) + if val is None: + result[end] = None + else: + obj = AttributeSetter(base_field.attname, val) + result[end] = base_field.value_to_string(obj) + return json.dumps(result) + + def formfield(self, **kwargs): + kwargs.setdefault("form_class", self.form_field) + return super().formfield(**kwargs) + + +CANONICAL_RANGE_BOUNDS = "[)" + + +class ContinuousRangeField(RangeField): + """ + Continuous range field. It allows specifying default bounds for list and + tuple inputs. + """ + + def __init__(self, *args, default_bounds=CANONICAL_RANGE_BOUNDS, **kwargs): + if default_bounds not in ("[)", "(]", "()", "[]"): + raise ValueError("default_bounds must be one of '[)', '(]', '()', or '[]'.") + self.default_bounds = default_bounds + super().__init__(*args, **kwargs) + + def get_prep_value(self, value): + if isinstance(value, (list, tuple)): + return self.range_type(value[0], value[1], self.default_bounds) + return super().get_prep_value(value) + + def formfield(self, **kwargs): + kwargs.setdefault("default_bounds", self.default_bounds) + return super().formfield(**kwargs) + + def deconstruct(self): + name, path, args, kwargs = super().deconstruct() + if self.default_bounds and self.default_bounds != CANONICAL_RANGE_BOUNDS: + kwargs["default_bounds"] = self.default_bounds + return name, path, args, kwargs + + +class IntegerRangeField(RangeField): + base_field = models.IntegerField + range_type = NumericRange + form_field = forms.IntegerRangeField + + def db_type(self, connection): + return "int4range" + + +class BigIntegerRangeField(RangeField): + base_field = models.BigIntegerField + range_type = NumericRange + form_field = forms.IntegerRangeField + + def db_type(self, connection): + return "int8range" + + +class DecimalRangeField(ContinuousRangeField): + base_field = models.DecimalField + range_type = NumericRange + form_field = forms.DecimalRangeField + + def db_type(self, connection): + return "numrange" + + +class DateTimeRangeField(ContinuousRangeField): + base_field = models.DateTimeField + range_type = DateTimeTZRange + form_field = forms.DateTimeRangeField + + def db_type(self, connection): + return "tstzrange" + + +class DateRangeField(RangeField): + base_field = models.DateField + range_type = DateRange + form_field = forms.DateRangeField + + def db_type(self, connection): + return "daterange" + + +class RangeContains(lookups.DataContains): + def get_prep_lookup(self): + if not isinstance(self.rhs, (list, tuple, Range)): + return Cast(self.rhs, self.lhs.field.base_field) + return super().get_prep_lookup() + + +RangeField.register_lookup(RangeContains) +RangeField.register_lookup(lookups.ContainedBy) +RangeField.register_lookup(lookups.Overlap) + + +class DateTimeRangeContains(PostgresOperatorLookup): + """ + Lookup for Date/DateTimeRange containment to cast the rhs to the correct + type. + """ + + lookup_name = "contains" + postgres_operator = RangeOperators.CONTAINS + + def process_rhs(self, compiler, connection): + # Transform rhs value for db lookup. + if isinstance(self.rhs, datetime.date): + value = models.Value(self.rhs) + self.rhs = value.resolve_expression(compiler.query) + return super().process_rhs(compiler, connection) + + def as_postgresql(self, compiler, connection): + sql, params = super().as_postgresql(compiler, connection) + # Cast the rhs if needed. + cast_sql = "" + if ( + isinstance(self.rhs, models.Expression) + and self.rhs._output_field_or_none + and + # Skip cast if rhs has a matching range type. + not isinstance( + self.rhs._output_field_or_none, self.lhs.output_field.__class__ + ) + ): + cast_internal_type = self.lhs.output_field.base_field.get_internal_type() + cast_sql = "::{}".format(connection.data_types.get(cast_internal_type)) + return "%s%s" % (sql, cast_sql), params + + +DateRangeField.register_lookup(DateTimeRangeContains) +DateTimeRangeField.register_lookup(DateTimeRangeContains) + + +class RangeContainedBy(PostgresOperatorLookup): + lookup_name = "contained_by" + type_mapping = { + "smallint": "int4range", + "integer": "int4range", + "bigint": "int8range", + "double precision": "numrange", + "numeric": "numrange", + "date": "daterange", + "timestamp with time zone": "tstzrange", + } + postgres_operator = RangeOperators.CONTAINED_BY + + def process_rhs(self, compiler, connection): + rhs, rhs_params = super().process_rhs(compiler, connection) + # Ignore precision for DecimalFields. + db_type = self.lhs.output_field.cast_db_type(connection).split("(")[0] + cast_type = self.type_mapping[db_type] + return "%s::%s" % (rhs, cast_type), rhs_params + + def process_lhs(self, compiler, connection): + lhs, lhs_params = super().process_lhs(compiler, connection) + if isinstance(self.lhs.output_field, models.FloatField): + lhs = "%s::numeric" % lhs + elif isinstance(self.lhs.output_field, models.SmallIntegerField): + lhs = "%s::integer" % lhs + return lhs, lhs_params + + def get_prep_lookup(self): + return RangeField().get_prep_value(self.rhs) + + +models.DateField.register_lookup(RangeContainedBy) +models.DateTimeField.register_lookup(RangeContainedBy) +models.IntegerField.register_lookup(RangeContainedBy) +models.FloatField.register_lookup(RangeContainedBy) +models.DecimalField.register_lookup(RangeContainedBy) + + +@RangeField.register_lookup +class FullyLessThan(PostgresOperatorLookup): + lookup_name = "fully_lt" + postgres_operator = RangeOperators.FULLY_LT + + +@RangeField.register_lookup +class FullGreaterThan(PostgresOperatorLookup): + lookup_name = "fully_gt" + postgres_operator = RangeOperators.FULLY_GT + + +@RangeField.register_lookup +class NotLessThan(PostgresOperatorLookup): + lookup_name = "not_lt" + postgres_operator = RangeOperators.NOT_LT + + +@RangeField.register_lookup +class NotGreaterThan(PostgresOperatorLookup): + lookup_name = "not_gt" + postgres_operator = RangeOperators.NOT_GT + + +@RangeField.register_lookup +class AdjacentToLookup(PostgresOperatorLookup): + lookup_name = "adjacent_to" + postgres_operator = RangeOperators.ADJACENT_TO + + +@RangeField.register_lookup +class RangeStartsWith(models.Transform): + lookup_name = "startswith" + function = "lower" + + @property + def output_field(self): + return self.lhs.output_field.base_field + + +@RangeField.register_lookup +class RangeEndsWith(models.Transform): + lookup_name = "endswith" + function = "upper" + + @property + def output_field(self): + return self.lhs.output_field.base_field + + +@RangeField.register_lookup +class IsEmpty(models.Transform): + lookup_name = "isempty" + function = "isempty" + output_field = models.BooleanField() + + +@RangeField.register_lookup +class LowerInclusive(models.Transform): + lookup_name = "lower_inc" + function = "LOWER_INC" + output_field = models.BooleanField() + + +@RangeField.register_lookup +class LowerInfinite(models.Transform): + lookup_name = "lower_inf" + function = "LOWER_INF" + output_field = models.BooleanField() + + +@RangeField.register_lookup +class UpperInclusive(models.Transform): + lookup_name = "upper_inc" + function = "UPPER_INC" + output_field = models.BooleanField() + + +@RangeField.register_lookup +class UpperInfinite(models.Transform): + lookup_name = "upper_inf" + function = "UPPER_INF" + output_field = models.BooleanField() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/fields/utils.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/fields/utils.py new file mode 100644 index 0000000..82da93e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/fields/utils.py @@ -0,0 +1,3 @@ +class AttributeSetter: + def __init__(self, name, value): + setattr(self, name, value) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/forms/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/forms/__init__.py new file mode 100644 index 0000000..bb2685e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/forms/__init__.py @@ -0,0 +1,3 @@ +from .array import * # NOQA +from .hstore import * # NOQA +from .ranges import * # NOQA diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/forms/array.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/forms/array.py new file mode 100644 index 0000000..ddb022a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/forms/array.py @@ -0,0 +1,251 @@ +import copy +from itertools import chain + +from django import forms +from django.contrib.postgres.validators import ( + ArrayMaxLengthValidator, + ArrayMinLengthValidator, +) +from django.core.exceptions import ValidationError +from django.utils.translation import gettext_lazy as _ + +from ..utils import prefix_validation_error + + +class SimpleArrayField(forms.CharField): + default_error_messages = { + "item_invalid": _("Item %(nth)s in the array did not validate:"), + } + + def __init__( + self, base_field, *, delimiter=",", max_length=None, min_length=None, **kwargs + ): + self.base_field = base_field + self.delimiter = delimiter + super().__init__(**kwargs) + if min_length is not None: + self.min_length = min_length + self.validators.append(ArrayMinLengthValidator(int(min_length))) + if max_length is not None: + self.max_length = max_length + self.validators.append(ArrayMaxLengthValidator(int(max_length))) + + def clean(self, value): + value = super().clean(value) + return [self.base_field.clean(val) for val in value] + + def prepare_value(self, value): + if isinstance(value, list): + return self.delimiter.join( + str(self.base_field.prepare_value(v)) for v in value + ) + return value + + def to_python(self, value): + if isinstance(value, list): + items = value + elif value: + items = value.split(self.delimiter) + else: + items = [] + errors = [] + values = [] + for index, item in enumerate(items): + try: + values.append(self.base_field.to_python(item)) + except ValidationError as error: + errors.append( + prefix_validation_error( + error, + prefix=self.error_messages["item_invalid"], + code="item_invalid", + params={"nth": index + 1}, + ) + ) + if errors: + raise ValidationError(errors) + return values + + def validate(self, value): + super().validate(value) + errors = [] + for index, item in enumerate(value): + try: + self.base_field.validate(item) + except ValidationError as error: + errors.append( + prefix_validation_error( + error, + prefix=self.error_messages["item_invalid"], + code="item_invalid", + params={"nth": index + 1}, + ) + ) + if errors: + raise ValidationError(errors) + + def run_validators(self, value): + super().run_validators(value) + errors = [] + for index, item in enumerate(value): + try: + self.base_field.run_validators(item) + except ValidationError as error: + errors.append( + prefix_validation_error( + error, + prefix=self.error_messages["item_invalid"], + code="item_invalid", + params={"nth": index + 1}, + ) + ) + if errors: + raise ValidationError(errors) + + def has_changed(self, initial, data): + try: + value = self.to_python(data) + except ValidationError: + pass + else: + if initial in self.empty_values and value in self.empty_values: + return False + return super().has_changed(initial, data) + + +class SplitArrayWidget(forms.Widget): + template_name = "postgres/widgets/split_array.html" + + def __init__(self, widget, size, **kwargs): + self.widget = widget() if isinstance(widget, type) else widget + self.size = size + super().__init__(**kwargs) + + @property + def is_hidden(self): + return self.widget.is_hidden + + def value_from_datadict(self, data, files, name): + return [ + self.widget.value_from_datadict(data, files, "%s_%s" % (name, index)) + for index in range(self.size) + ] + + def value_omitted_from_data(self, data, files, name): + return all( + self.widget.value_omitted_from_data(data, files, "%s_%s" % (name, index)) + for index in range(self.size) + ) + + def id_for_label(self, id_): + # See the comment for RadioSelect.id_for_label() + if id_: + id_ += "_0" + return id_ + + def get_context(self, name, value, attrs=None): + attrs = {} if attrs is None else attrs + context = super().get_context(name, value, attrs) + if self.is_localized: + self.widget.is_localized = self.is_localized + value = value or [] + context["widget"]["subwidgets"] = [] + final_attrs = self.build_attrs(attrs) + id_ = final_attrs.get("id") + for i in range(max(len(value), self.size)): + try: + widget_value = value[i] + except IndexError: + widget_value = None + if id_: + final_attrs = {**final_attrs, "id": "%s_%s" % (id_, i)} + context["widget"]["subwidgets"].append( + self.widget.get_context(name + "_%s" % i, widget_value, final_attrs)[ + "widget" + ] + ) + return context + + @property + def media(self): + return self.widget.media + + def __deepcopy__(self, memo): + obj = super().__deepcopy__(memo) + obj.widget = copy.deepcopy(self.widget) + return obj + + @property + def needs_multipart_form(self): + return self.widget.needs_multipart_form + + +class SplitArrayField(forms.Field): + default_error_messages = { + "item_invalid": _("Item %(nth)s in the array did not validate:"), + } + + def __init__(self, base_field, size, *, remove_trailing_nulls=False, **kwargs): + self.base_field = base_field + self.size = size + self.remove_trailing_nulls = remove_trailing_nulls + widget = SplitArrayWidget(widget=base_field.widget, size=size) + kwargs.setdefault("widget", widget) + super().__init__(**kwargs) + + def _remove_trailing_nulls(self, values): + index = None + if self.remove_trailing_nulls: + for i, value in reversed(list(enumerate(values))): + if value in self.base_field.empty_values: + index = i + else: + break + if index is not None: + values = values[:index] + return values, index + + def to_python(self, value): + value = super().to_python(value) + return [self.base_field.to_python(item) for item in value] + + def clean(self, value): + cleaned_data = [] + errors = [] + if not any(value) and self.required: + raise ValidationError(self.error_messages["required"]) + max_size = max(self.size, len(value)) + for index in range(max_size): + item = value[index] + try: + cleaned_data.append(self.base_field.clean(item)) + except ValidationError as error: + errors.append( + prefix_validation_error( + error, + self.error_messages["item_invalid"], + code="item_invalid", + params={"nth": index + 1}, + ) + ) + cleaned_data.append(None) + else: + errors.append(None) + cleaned_data, null_index = self._remove_trailing_nulls(cleaned_data) + if null_index is not None: + errors = errors[:null_index] + errors = list(filter(None, errors)) + if errors: + raise ValidationError(list(chain.from_iterable(errors))) + return cleaned_data + + def has_changed(self, initial, data): + try: + data = self.to_python(data) + except ValidationError: + pass + else: + data, _ = self._remove_trailing_nulls(data) + if initial in self.empty_values and data in self.empty_values: + return False + return super().has_changed(initial, data) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/forms/hstore.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/forms/hstore.py new file mode 100644 index 0000000..6a20f7b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/forms/hstore.py @@ -0,0 +1,59 @@ +import json + +from django import forms +from django.core.exceptions import ValidationError +from django.utils.translation import gettext_lazy as _ + +__all__ = ["HStoreField"] + + +class HStoreField(forms.CharField): + """ + A field for HStore data which accepts dictionary JSON input. + """ + + widget = forms.Textarea + default_error_messages = { + "invalid_json": _("Could not load JSON data."), + "invalid_format": _("Input must be a JSON dictionary."), + } + + def prepare_value(self, value): + if isinstance(value, dict): + return json.dumps(value) + return value + + def to_python(self, value): + if not value: + return {} + if not isinstance(value, dict): + try: + value = json.loads(value) + except json.JSONDecodeError: + raise ValidationError( + self.error_messages["invalid_json"], + code="invalid_json", + ) + + if not isinstance(value, dict): + raise ValidationError( + self.error_messages["invalid_format"], + code="invalid_format", + ) + + # Cast everything to strings for ease. + for key, val in value.items(): + if val is not None: + val = str(val) + value[key] = val + return value + + def has_changed(self, initial, data): + """ + Return True if data differs from initial. + """ + # For purposes of seeing whether something has changed, None is + # the same as an empty dict, if the data or initial value we get + # is None, replace it w/ {}. + initial_value = self.to_python(initial) + return super().has_changed(initial_value, data) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/forms/ranges.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/forms/ranges.py new file mode 100644 index 0000000..3017f08 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/forms/ranges.py @@ -0,0 +1,119 @@ +from django import forms +from django.core import exceptions +from django.db.backends.postgresql.psycopg_any import ( + DateRange, + DateTimeTZRange, + NumericRange, +) +from django.forms.widgets import HiddenInput, MultiWidget +from django.utils.translation import gettext_lazy as _ + +__all__ = [ + "BaseRangeField", + "IntegerRangeField", + "DecimalRangeField", + "DateTimeRangeField", + "DateRangeField", + "HiddenRangeWidget", + "RangeWidget", +] + + +class RangeWidget(MultiWidget): + def __init__(self, base_widget, attrs=None): + widgets = (base_widget, base_widget) + super().__init__(widgets, attrs) + + def decompress(self, value): + if value: + return (value.lower, value.upper) + return (None, None) + + +class HiddenRangeWidget(RangeWidget): + """A widget that splits input into two inputs.""" + + def __init__(self, attrs=None): + super().__init__(HiddenInput, attrs) + + +class BaseRangeField(forms.MultiValueField): + default_error_messages = { + "invalid": _("Enter two valid values."), + "bound_ordering": _( + "The start of the range must not exceed the end of the range." + ), + } + hidden_widget = HiddenRangeWidget + + def __init__(self, **kwargs): + if "widget" not in kwargs: + kwargs["widget"] = RangeWidget(self.base_field.widget) + if "fields" not in kwargs: + kwargs["fields"] = [ + self.base_field(required=False), + self.base_field(required=False), + ] + kwargs.setdefault("required", False) + kwargs.setdefault("require_all_fields", False) + self.range_kwargs = {} + if default_bounds := kwargs.pop("default_bounds", None): + self.range_kwargs = {"bounds": default_bounds} + super().__init__(**kwargs) + + def prepare_value(self, value): + lower_base, upper_base = self.fields + if isinstance(value, self.range_type): + return [ + lower_base.prepare_value(value.lower), + upper_base.prepare_value(value.upper), + ] + if value is None: + return [ + lower_base.prepare_value(None), + upper_base.prepare_value(None), + ] + return value + + def compress(self, values): + if not values: + return None + lower, upper = values + if lower is not None and upper is not None and lower > upper: + raise exceptions.ValidationError( + self.error_messages["bound_ordering"], + code="bound_ordering", + ) + try: + range_value = self.range_type(lower, upper, **self.range_kwargs) + except TypeError: + raise exceptions.ValidationError( + self.error_messages["invalid"], + code="invalid", + ) + else: + return range_value + + +class IntegerRangeField(BaseRangeField): + default_error_messages = {"invalid": _("Enter two whole numbers.")} + base_field = forms.IntegerField + range_type = NumericRange + + +class DecimalRangeField(BaseRangeField): + default_error_messages = {"invalid": _("Enter two numbers.")} + base_field = forms.DecimalField + range_type = NumericRange + + +class DateTimeRangeField(BaseRangeField): + default_error_messages = {"invalid": _("Enter two valid date/times.")} + base_field = forms.DateTimeField + range_type = DateTimeTZRange + + +class DateRangeField(BaseRangeField): + default_error_messages = {"invalid": _("Enter two valid dates.")} + base_field = forms.DateField + range_type = DateRange diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/functions.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/functions.py new file mode 100644 index 0000000..f001a04 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/functions.py @@ -0,0 +1,11 @@ +from django.db.models import DateTimeField, Func, UUIDField + + +class RandomUUID(Func): + template = "GEN_RANDOM_UUID()" + output_field = UUIDField() + + +class TransactionNow(Func): + template = "CURRENT_TIMESTAMP" + output_field = DateTimeField() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/indexes.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/indexes.py new file mode 100644 index 0000000..363a943 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/indexes.py @@ -0,0 +1,242 @@ +from django.db import NotSupportedError +from django.db.models import Func, Index +from django.utils.functional import cached_property + +__all__ = [ + "BloomIndex", + "BrinIndex", + "BTreeIndex", + "GinIndex", + "GistIndex", + "HashIndex", + "SpGistIndex", +] + + +class PostgresIndex(Index): + @cached_property + def max_name_length(self): + # Allow an index name longer than 30 characters when the suffix is + # longer than the usual 3 character limit. The 30 character limit for + # cross-database compatibility isn't applicable to PostgreSQL-specific + # indexes. + return Index.max_name_length - len(Index.suffix) + len(self.suffix) + + def create_sql(self, model, schema_editor, using="", **kwargs): + self.check_supported(schema_editor) + statement = super().create_sql( + model, schema_editor, using=" USING %s" % (using or self.suffix), **kwargs + ) + with_params = self.get_with_params() + if with_params: + statement.parts["extra"] = " WITH (%s)%s" % ( + ", ".join(with_params), + statement.parts["extra"], + ) + return statement + + def check_supported(self, schema_editor): + pass + + def get_with_params(self): + return [] + + +class BloomIndex(PostgresIndex): + suffix = "bloom" + + def __init__(self, *expressions, length=None, columns=(), **kwargs): + super().__init__(*expressions, **kwargs) + if len(self.fields) > 32: + raise ValueError("Bloom indexes support a maximum of 32 fields.") + if not isinstance(columns, (list, tuple)): + raise ValueError("BloomIndex.columns must be a list or tuple.") + if len(columns) > len(self.fields): + raise ValueError("BloomIndex.columns cannot have more values than fields.") + if not all(0 < col <= 4095 for col in columns): + raise ValueError( + "BloomIndex.columns must contain integers from 1 to 4095.", + ) + if length is not None and not 0 < length <= 4096: + raise ValueError( + "BloomIndex.length must be None or an integer from 1 to 4096.", + ) + self.length = length + self.columns = columns + + def deconstruct(self): + path, args, kwargs = super().deconstruct() + if self.length is not None: + kwargs["length"] = self.length + if self.columns: + kwargs["columns"] = self.columns + return path, args, kwargs + + def get_with_params(self): + with_params = [] + if self.length is not None: + with_params.append("length = %d" % self.length) + if self.columns: + with_params.extend( + "col%d = %d" % (i, v) for i, v in enumerate(self.columns, start=1) + ) + return with_params + + +class BrinIndex(PostgresIndex): + suffix = "brin" + + def __init__( + self, *expressions, autosummarize=None, pages_per_range=None, **kwargs + ): + if pages_per_range is not None and pages_per_range <= 0: + raise ValueError("pages_per_range must be None or a positive integer") + self.autosummarize = autosummarize + self.pages_per_range = pages_per_range + super().__init__(*expressions, **kwargs) + + def deconstruct(self): + path, args, kwargs = super().deconstruct() + if self.autosummarize is not None: + kwargs["autosummarize"] = self.autosummarize + if self.pages_per_range is not None: + kwargs["pages_per_range"] = self.pages_per_range + return path, args, kwargs + + def get_with_params(self): + with_params = [] + if self.autosummarize is not None: + with_params.append( + "autosummarize = %s" % ("on" if self.autosummarize else "off") + ) + if self.pages_per_range is not None: + with_params.append("pages_per_range = %d" % self.pages_per_range) + return with_params + + +class BTreeIndex(PostgresIndex): + suffix = "btree" + + def __init__(self, *expressions, fillfactor=None, **kwargs): + self.fillfactor = fillfactor + super().__init__(*expressions, **kwargs) + + def deconstruct(self): + path, args, kwargs = super().deconstruct() + if self.fillfactor is not None: + kwargs["fillfactor"] = self.fillfactor + return path, args, kwargs + + def get_with_params(self): + with_params = [] + if self.fillfactor is not None: + with_params.append("fillfactor = %d" % self.fillfactor) + return with_params + + +class GinIndex(PostgresIndex): + suffix = "gin" + + def __init__( + self, *expressions, fastupdate=None, gin_pending_list_limit=None, **kwargs + ): + self.fastupdate = fastupdate + self.gin_pending_list_limit = gin_pending_list_limit + super().__init__(*expressions, **kwargs) + + def deconstruct(self): + path, args, kwargs = super().deconstruct() + if self.fastupdate is not None: + kwargs["fastupdate"] = self.fastupdate + if self.gin_pending_list_limit is not None: + kwargs["gin_pending_list_limit"] = self.gin_pending_list_limit + return path, args, kwargs + + def get_with_params(self): + with_params = [] + if self.gin_pending_list_limit is not None: + with_params.append( + "gin_pending_list_limit = %d" % self.gin_pending_list_limit + ) + if self.fastupdate is not None: + with_params.append("fastupdate = %s" % ("on" if self.fastupdate else "off")) + return with_params + + +class GistIndex(PostgresIndex): + suffix = "gist" + + def __init__(self, *expressions, buffering=None, fillfactor=None, **kwargs): + self.buffering = buffering + self.fillfactor = fillfactor + super().__init__(*expressions, **kwargs) + + def deconstruct(self): + path, args, kwargs = super().deconstruct() + if self.buffering is not None: + kwargs["buffering"] = self.buffering + if self.fillfactor is not None: + kwargs["fillfactor"] = self.fillfactor + return path, args, kwargs + + def get_with_params(self): + with_params = [] + if self.buffering is not None: + with_params.append("buffering = %s" % ("on" if self.buffering else "off")) + if self.fillfactor is not None: + with_params.append("fillfactor = %d" % self.fillfactor) + return with_params + + +class HashIndex(PostgresIndex): + suffix = "hash" + + def __init__(self, *expressions, fillfactor=None, **kwargs): + self.fillfactor = fillfactor + super().__init__(*expressions, **kwargs) + + def deconstruct(self): + path, args, kwargs = super().deconstruct() + if self.fillfactor is not None: + kwargs["fillfactor"] = self.fillfactor + return path, args, kwargs + + def get_with_params(self): + with_params = [] + if self.fillfactor is not None: + with_params.append("fillfactor = %d" % self.fillfactor) + return with_params + + +class SpGistIndex(PostgresIndex): + suffix = "spgist" + + def __init__(self, *expressions, fillfactor=None, **kwargs): + self.fillfactor = fillfactor + super().__init__(*expressions, **kwargs) + + def deconstruct(self): + path, args, kwargs = super().deconstruct() + if self.fillfactor is not None: + kwargs["fillfactor"] = self.fillfactor + return path, args, kwargs + + def get_with_params(self): + with_params = [] + if self.fillfactor is not None: + with_params.append("fillfactor = %d" % self.fillfactor) + return with_params + + def check_supported(self, schema_editor): + if ( + self.include + and not schema_editor.connection.features.supports_covering_spgist_indexes + ): + raise NotSupportedError("Covering SP-GiST indexes require PostgreSQL 14+.") + + +class OpClass(Func): + template = "%(expressions)s %(name)s" + + def __init__(self, expression, name): + super().__init__(expression, name=name) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/jinja2/postgres/widgets/split_array.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/jinja2/postgres/widgets/split_array.html new file mode 100644 index 0000000..32fda82 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/jinja2/postgres/widgets/split_array.html @@ -0,0 +1 @@ +{% include 'django/forms/widgets/multiwidget.html' %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/af/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/af/LC_MESSAGES/django.mo new file mode 100644 index 0000000..483338d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/af/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/af/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/af/LC_MESSAGES/django.po new file mode 100644 index 0000000..4ebf5dd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/af/LC_MESSAGES/django.po @@ -0,0 +1,104 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# F Wolff , 2019-2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Afrikaans (http://www.transifex.com/django/django/language/" +"af/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: af\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL-uitbreidings" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Item %(nth)s in die skikking kon nie valideer nie:" + +msgid "Nested arrays must have the same length." +msgstr "Geneste skikkings moet dieselfde lengte hê." + +msgid "Map of strings to strings/nulls" +msgstr "Woordeboek van stringe na stringe/nulls" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Die waarde “%(key)s” is nie 'n string of null nie." + +msgid "Could not load JSON data." +msgstr "Kon nie JSON-data laai nie." + +msgid "Input must be a JSON dictionary." +msgstr "Toevoer moet 'n JSON-woordeboek wees." + +msgid "Enter two valid values." +msgstr "Gee twee geldige waardes." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Die begin van die omvang mag nie die einde van die omvang oorskry nie." + +msgid "Enter two whole numbers." +msgstr "Tik twee heelgetalle in." + +msgid "Enter two numbers." +msgstr "Tik twee getalle in." + +msgid "Enter two valid date/times." +msgstr "Tik twee geldige datum/tydwaardes in." + +msgid "Enter two valid dates." +msgstr "Tik twee geldige datums in." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Lys bevat %(show_value)d item, maar moet hoogstens %(limit_value)d bevat." +msgstr[1] "" +"Lys bevat %(show_value)d items, maar moet hoogstens %(limit_value)d bevat." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Lys bevat %(show_value)d item, maar moet minstens %(limit_value)d bevat." +msgstr[1] "" +"Lys bevat %(show_value)d items, maar moet minstens %(limit_value)d bevat." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Sommige sleutels het ontbreek: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Sommige onbekende sleutels is voorsien: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" +"Maak seker dat dié omvang heeltemal kleiner of gelyk is aan %(limit_value)s." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "" +"Maak seker dat dié omvang heeltemal groter of gelyk is aan %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ar/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ar/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e5e383d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ar/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ar/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ar/LC_MESSAGES/django.po new file mode 100644 index 0000000..5e0aad7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ar/LC_MESSAGES/django.po @@ -0,0 +1,131 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bashar Al-Abdulhadi, 2015-2017 +# Muaaz Alsaied, 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Arabic (http://www.transifex.com/django/django/language/ar/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +msgid "PostgreSQL extensions" +msgstr "ملحقات PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "العنصر %(nth)s في المتسلسلة لم يحقق التالي: " + +msgid "Nested arrays must have the same length." +msgstr "يجب أن تكون المجموعات المتداخلة بنفس الطول." + +msgid "Map of strings to strings/nulls" +msgstr "ترابط strings بـ strings/nulls" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "قيمة \"%(key)s\" ليست string أو null." + +msgid "Could not load JSON data." +msgstr "لا يمكن عرض بيانات JSON." + +msgid "Input must be a JSON dictionary." +msgstr "المُدخل يجب أن يكون بصيغة بصيغة قاموس JSON." + +msgid "Enter two valid values." +msgstr "إدخال قيمتين صالحتين." + +msgid "The start of the range must not exceed the end of the range." +msgstr "بداية المدى يجب ألا تتجاوز نهاية المدى." + +msgid "Enter two whole numbers." +msgstr "أدخل رقمين كاملين." + +msgid "Enter two numbers." +msgstr "أدخل رقمين." + +msgid "Enter two valid date/times." +msgstr "أدخل تاريخين/وقتين صحيحين." + +msgid "Enter two valid dates." +msgstr "أدخل تاريخين صحيحين." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"القائمة تحتوي على %(show_value)d عنصر, يجب أن لا تحتوي على أكثر من " +"%(limit_value)d." +msgstr[1] "" +"القائمة تحتوي على %(show_value)d عنصر, يجب أن لا تحتوي على أكثر من " +"%(limit_value)d." +msgstr[2] "" +"القائمة تحتوي على %(show_value)d عنصرين, يجب أن لا تحتوي على أكثر من " +"%(limit_value)d." +msgstr[3] "" +"القائمة تحتوي على %(show_value)d عناصر, يجب أن لا تحتوي على أكثر من " +"%(limit_value)d." +msgstr[4] "" +"القائمة تحتوي على %(show_value)d عنصر, يجب أن لا تحتوي على أكثر من " +"%(limit_value)d." +msgstr[5] "" +"القائمة تحتوي على %(show_value)d عنصر, يجب أن لا تحتوي على أكثر من " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"القائمة تحتوي على %(show_value)d عنصر, يجب أن لا تحتوي على أقل من " +"%(limit_value)d." +msgstr[1] "" +"القائمة تحتوي على %(show_value)d عنصر, يجب أن لا تحتوي على أقل من " +"%(limit_value)d." +msgstr[2] "" +"القائمة تحتوي على %(show_value)d عنصرين, يجب أن لا تحتوي على أقل من " +"%(limit_value)d." +msgstr[3] "" +"القائمة تحتوي على %(show_value)d عناصر, يجب أن لا تحتوي على أقل من " +"%(limit_value)d." +msgstr[4] "" +"القائمة تحتوي على %(show_value)d عنصر, يجب أن لا تحتوي على أقل من " +"%(limit_value)d." +msgstr[5] "" +"القائمة تحتوي على %(show_value)d عنصر, يجب أن لا تحتوي على أقل من " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "بعض المفاتيح مفقودة: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "بعض المفاتيح المزوّدة غير معرّفه: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "تأكد من أن هذا المدى أقل من أو يساوي %(limit_value)s." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "تأكد من أن هذا المدى أكثر من أو يساوي %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ar_DZ/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ar_DZ/LC_MESSAGES/django.mo new file mode 100644 index 0000000..cd38cf9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ar_DZ/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ar_DZ/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ar_DZ/LC_MESSAGES/django.po new file mode 100644 index 0000000..87021fe --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ar_DZ/LC_MESSAGES/django.po @@ -0,0 +1,131 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Riterix , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Arabic (Algeria) (http://www.transifex.com/django/django/" +"language/ar_DZ/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar_DZ\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +msgid "PostgreSQL extensions" +msgstr "ملحقات PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "العنصر %(nth)s في المجموعة لم يتم التحقق منه: " + +msgid "Nested arrays must have the same length." +msgstr "يجب أن تكون المجموعات المتداخلة بنفس الطول." + +msgid "Map of strings to strings/nulls" +msgstr "خريطة السلاسل إلى سلاسل / بلا قيم" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "قيمة \\\"%(key)s\\\" ليست سلسلة أو بلا قيمة." + +msgid "Could not load JSON data." +msgstr "لا يمكن عرض بيانات JSON." + +msgid "Input must be a JSON dictionary." +msgstr "المُدخل يجب أن يكون بصيغة بصيغة قاموس JSON." + +msgid "Enter two valid values." +msgstr "إدخال قيمتين صالحتين." + +msgid "The start of the range must not exceed the end of the range." +msgstr "بداية المدى يجب ألا تتجاوز نهاية المدى." + +msgid "Enter two whole numbers." +msgstr "أدخل رقمين كاملين." + +msgid "Enter two numbers." +msgstr "أدخل رقمين." + +msgid "Enter two valid date/times." +msgstr "أدخل تاريخين/وقتين صحيحين." + +msgid "Enter two valid dates." +msgstr "أدخل تاريخين صحيحين." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"القائمة تحتوي على %(show_value)d عنصر, يجب أن لا تحتوي على أكثر من " +"%(limit_value)d." +msgstr[1] "" +"القائمة تحتوي على %(show_value)d عنصر, يجب أن لا تحتوي على أكثر من " +"%(limit_value)d." +msgstr[2] "" +"القائمة تحتوي على %(show_value)d عنصرين, يجب أن لا تحتوي على أكثر من " +"%(limit_value)d." +msgstr[3] "" +"القائمة تحتوي على %(show_value)d عناصر, يجب أن لا تحتوي على أكثر من " +"%(limit_value)d." +msgstr[4] "" +"القائمة تحتوي على %(show_value)d عنصر, يجب أن لا تحتوي على أكثر من " +"%(limit_value)d." +msgstr[5] "" +"القائمة تحتوي على %(show_value)d عنصر, يجب أن لا تحتوي على أكثر من " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"القائمة تحتوي على %(show_value)d عنصر, يجب أن لا تحتوي على أقل من " +"%(limit_value)d." +msgstr[1] "" +"القائمة تحتوي على %(show_value)d عنصر, يجب أن لا تحتوي على أقل من " +"%(limit_value)d." +msgstr[2] "" +"القائمة تحتوي على %(show_value)d عنصرين, يجب أن لا تحتوي على أقل من " +"%(limit_value)d." +msgstr[3] "" +"القائمة تحتوي على %(show_value)d عناصر, يجب أن لا تحتوي على أقل من " +"%(limit_value)d." +msgstr[4] "" +"القائمة تحتوي على %(show_value)d عنصر, يجب أن لا تحتوي على أقل من " +"%(limit_value)d." +msgstr[5] "" +"القائمة تحتوي على %(show_value)d عنصر, يجب أن لا تحتوي على أقل من " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "بعض المفاتيح مفقودة: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "بعض المفاتيح المزوّدة غير معرّفه: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "تأكد من أن هذا المدى أقل من أو يساوي %(limit_value)s." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "تأكد من أن هذا المدى أكثر من أو يساوي %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/az/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/az/LC_MESSAGES/django.mo new file mode 100644 index 0000000..97350a2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/az/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/az/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/az/LC_MESSAGES/django.po new file mode 100644 index 0000000..418da3a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/az/LC_MESSAGES/django.po @@ -0,0 +1,102 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Emin Mastizada , 2018,2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Azerbaijani (http://www.transifex.com/django/django/language/" +"az/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: az\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL uzantıları" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Array-dəki %(nth)s element təsdiqlənə bilmir:" + +msgid "Nested arrays must have the same length." +msgstr "İç-içə array-lərin uzunluğu eyni olmalıdır." + +msgid "Map of strings to strings/nulls" +msgstr "String-lərin string/null-lara xəritələnmə cədvəli" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "“%(key)s” dəyəri string və ya null deyil." + +msgid "Could not load JSON data." +msgstr "JSON məlumat yüklənə bilmir." + +msgid "Input must be a JSON dictionary." +msgstr "Giriş JSON lüğət olmalıdır." + +msgid "Enter two valid values." +msgstr "İki düzgün dəyər daxil edin." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Aralığın başlanğıcı bitişindən böyük ola bilməz." + +msgid "Enter two whole numbers." +msgstr "İki tam rəqəm daxil edin." + +msgid "Enter two numbers." +msgstr "İki rəqəm daxil edin." + +msgid "Enter two valid date/times." +msgstr "İki düzgün tarix/vaxt daxil edin." + +msgid "Enter two valid dates." +msgstr "İki düzgün tarix daxil edin." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Siyahıda %(show_value)d element var, ən çox %(limit_value)d ola bilər." +msgstr[1] "" +"Siyahıda %(show_value)d element var, ən çox %(limit_value)d ola bilər." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Siyahıda %(show_value)d element var, ən az %(limit_value)d ola bilər." +msgstr[1] "" +"Siyahıda %(show_value)d element var, ən az %(limit_value)d ola bilər." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Bəzi açarlar əksikdir: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Bəzi bilinməyən açarlar təchiz edilib: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "Bu aralığın %(limit_value)s və ya daha az olduğuna əmin olun." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "Bu aralığın %(limit_value)s və ya daha böyük olduğuna əmin olun." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/be/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/be/LC_MESSAGES/django.mo new file mode 100644 index 0000000..cf342c7 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/be/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/be/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/be/LC_MESSAGES/django.po new file mode 100644 index 0000000..6cafe79 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/be/LC_MESSAGES/django.po @@ -0,0 +1,120 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Viktar Palstsiuk , 2015 +# znotdead , 2016-2017,2019,2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-19 09:22+0000\n" +"Last-Translator: znotdead , 2016-2017,2019,2023\n" +"Language-Team: Belarusian (http://www.transifex.com/django/django/language/" +"be/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: be\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || " +"(n%100>=11 && n%100<=14)? 2 : 3);\n" + +msgid "PostgreSQL extensions" +msgstr "Пашырэнні PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Элемент масіву нумар %(nth)s не прайшоў праверкі:" + +msgid "Nested arrays must have the same length." +msgstr "Укладзенныя масівы павінны мець аднолькавую даўжыню." + +msgid "Map of strings to strings/nulls" +msgstr "Адпаведнасць радкоў у радкі/нулі" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Значэнне “%(key)s” не з'яўляецца радком ці null." + +msgid "Could not load JSON data." +msgstr "Не атрымалася загрузіць дадзеныя JSON." + +msgid "Input must be a JSON dictionary." +msgstr "Значэнне павінна быць JSON слоўнікам. " + +msgid "Enter two valid values." +msgstr "Увядзіце два сапраўдных значэнні." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Пачатак дыяпазону не павінен перавышаць канец дыяпазону." + +msgid "Enter two whole numbers." +msgstr "Увядзіце два цэлых лікі." + +msgid "Enter two numbers." +msgstr "Увядзіце два лікі." + +msgid "Enter two valid date/times." +msgstr "Увядзіце дзве/два сапраўдных даты/часу." + +msgid "Enter two valid dates." +msgstr "Увядзіце дзве сапраўдных даты." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Спіс мае %(show_value)d элемент, ён павінен мець не болей чым " +"%(limit_value)d." +msgstr[1] "" +"Спіс мае %(show_value)d элемента, ён павінен мець не болей чым " +"%(limit_value)d." +msgstr[2] "" +"Спіс мае %(show_value)d элементаў, ён павінен мець не болей чым " +"%(limit_value)d." +msgstr[3] "" +"Спіс мае %(show_value)d элементаў, ён павінен мець не болей чым " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Спіс мае %(show_value)d элемент, ён павінен мець не менш чым %(limit_value)d." +msgstr[1] "" +"Спіс мае %(show_value)d элемента, ён павінен мець не менш чым " +"%(limit_value)d." +msgstr[2] "" +"Спіс мае %(show_value)d элементаў, ён павінен мець не менш чым " +"%(limit_value)d." +msgstr[3] "" +"Спіс мае %(show_value)d элементаў, ён павінен мець не менш чым " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Не хапае нейкіх ключоў: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Дадзены нейкія невядомыя ключы: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "" +"Пераканайцеся, што верхняя мяжа дыяпазону не перавышае %(limit_value)s." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "Пераканайцеся, што ніжняя мяжа дыяпазону не менш за %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/bg/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/bg/LC_MESSAGES/django.mo new file mode 100644 index 0000000..6a39b64 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/bg/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/bg/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/bg/LC_MESSAGES/django.po new file mode 100644 index 0000000..1b25e0a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/bg/LC_MESSAGES/django.po @@ -0,0 +1,110 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# arneatec , 2022-2023 +# Todor Lubenov , 2015 +# Venelin Stoykov , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-12-04 09:22+0000\n" +"Last-Translator: arneatec , 2022-2023\n" +"Language-Team: Bulgarian (http://app.transifex.com/django/django/language/" +"bg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL разширения" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Елемент %(nth)s в масива не се валидира:" + +msgid "Nested arrays must have the same length." +msgstr "Вложените масиви трябва да имат еднаква дължина." + +msgid "Map of strings to strings/nulls" +msgstr "Мап от стрингове към стрингове/null-ове" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Стойността на “%(key)s” не е стринг или null." + +msgid "Could not load JSON data." +msgstr "Не можа да зареди JSON данни." + +msgid "Input must be a JSON dictionary." +msgstr "Входните данни трябва да са JSON речник." + +msgid "Enter two valid values." +msgstr "Въведете две валидни стойности." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Началото на обхвата не трябва да превишава края му." + +msgid "Enter two whole numbers." +msgstr "Въведете две цели числа." + +msgid "Enter two numbers." +msgstr "Въведете две числа." + +msgid "Enter two valid date/times." +msgstr "Въведете две валидни дати/времена." + +msgid "Enter two valid dates." +msgstr "Въведете две коректни дати." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Списъкът съдържа %(show_value)d елемент, а трябва да има не повече от " +"%(limit_value)d." +msgstr[1] "" +"Списъкът съдържа %(show_value)d елемента, а трябва да има не повече от " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Списъкът съдържа %(show_value)d елемент, а трябва да има поне " +"%(limit_value)d." +msgstr[1] "" +"Списъкът съдържа %(show_value)d елемента, а трябва да има поне " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Някои ключове липсват: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Бяха предоставени някои неизвестни ключове: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "" +"Уверете се, че горната граница на диапазона не е по-голяма от " +"%(limit_value)s." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "" +"Уверете се, че горната граница на диапазона не е по-малка от %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ca/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ca/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3de632f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ca/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ca/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ca/LC_MESSAGES/django.po new file mode 100644 index 0000000..52d90b8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ca/LC_MESSAGES/django.po @@ -0,0 +1,112 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Antoni Aloy , 2015,2017 +# duub qnnp, 2015 +# Gil Obradors Via , 2019 +# Manel Clos , 2020 +# Roger Pons , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Catalan (http://www.transifex.com/django/django/language/" +"ca/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ca\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "Extensions de PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "L'element %(nth)s de la matriu no s'ha pogut validar:" + +msgid "Nested arrays must have the same length." +msgstr "Les matrius niades han de tenir la mateixa longitud." + +msgid "Map of strings to strings/nulls" +msgstr "Mapa de cadenes a cadenes/nuls" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "El valor de \"%(key)s\" no és ni una cadena ni un nul." + +msgid "Could not load JSON data." +msgstr "No es poden carregar les dades JSON" + +msgid "Input must be a JSON dictionary." +msgstr "L'entrada ha de ser un diccionari JSON" + +msgid "Enter two valid values." +msgstr "Introdueixi dos valors vàlids." + +msgid "The start of the range must not exceed the end of the range." +msgstr "L'inici del rang no pot excedir el seu final." + +msgid "Enter two whole numbers." +msgstr "Introduïu dos números enters positius." + +msgid "Enter two numbers." +msgstr "Introduïu dos números." + +msgid "Enter two valid date/times." +msgstr "Introduïu dues data/hora vàlides." + +msgid "Enter two valid dates." +msgstr "Introduïu dos dates vàlides." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"La llista conté %(show_value)d element, no n'hauria de tenir més de " +"%(limit_value)d." +msgstr[1] "" +"La llista conté %(show_value)d elements, no n'hauria de tenir més de " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"La llista conté %(show_value)d element, no n'hauria de contenir menys de " +"%(limit_value)d." +msgstr[1] "" +"La llista conté %(show_value)d elements, no n'hauria de contenir menys de " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Algunes claus no hi són: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "S'han facilitat claus desconegudes: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" +"Asseguri's que aquest rang és completament menor o igual a %(limit_value)s." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "" +"Asseguri's que aquest rang és completament major o igual a %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ckb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ckb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..652b8fd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ckb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ckb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ckb/LC_MESSAGES/django.po new file mode 100644 index 0000000..4c93f29 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ckb/LC_MESSAGES/django.po @@ -0,0 +1,101 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Swara , 2022 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-19 09:22+0000\n" +"Last-Translator: Swara , 2022\n" +"Language-Team: Central Kurdish (http://www.transifex.com/django/django/" +"language/ckb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ckb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "پێوەکراوەکانی PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "بڕگەی%(nth)s لەناو ڕیزەکەدا پشتڕاست نەکراوەتەوە:" + +msgid "Nested arrays must have the same length." +msgstr "ڕیزی هێلانەکراو دەبێت هەمان درێژی هەبێت." + +msgid "Map of strings to strings/nulls" +msgstr "نەخشەی ده‌قه‌ڕیزبه‌ندەکان بۆ دەقەڕیزبەندەکان/بەتاڵەکان" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "بەهای “%(key)s” نە دەقەڕیزبەندە نە بەتاڵ." + +msgid "Could not load JSON data." +msgstr "نەتوانرا داتاکانی JSON باربکرێت." + +msgid "Input must be a JSON dictionary." +msgstr "دەرخواردە دەبێت فەرهەنگی JSON بێت." + +msgid "Enter two valid values." +msgstr "دوو بەهای دروست بنوسە." + +msgid "The start of the range must not exceed the end of the range." +msgstr "نابێت سەرەتای ڕێژەکە لە کۆتایی ڕێژەکە زیاتر بێت." + +msgid "Enter two whole numbers." +msgstr "دوو ژمارەی تەواو بنوسە." + +msgid "Enter two numbers." +msgstr "دوو ژمارە بنوسە." + +msgid "Enter two valid date/times." +msgstr "دوو بەروار/کاتی دروست بنوسە." + +msgid "Enter two valid dates." +msgstr "دوو بەرواری دروست بنوسە." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"لیست پێکدێت لە %(show_value)d بڕگە، دەبێت زیاتر نەبێت لە %(limit_value)d." +msgstr[1] "" +"لیست پێکدێت لە %(show_value)d بڕگە، دەبێت زیاتر نەبێت لە %(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"لیست پێکدێت لە %(show_value)d بڕگە، دەبێت کەمتر نەبێت لە %(limit_value)d." +msgstr[1] "" +"لیست پێکدێت لە %(show_value)d بڕگە، دەبێت کەمتر نەبێت لە %(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "هەندێک کلیل نەمابوون: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "هەندێک کلیلی نەناسراو دابین کران: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/cs/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/cs/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a56d0b4 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/cs/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/cs/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/cs/LC_MESSAGES/django.po new file mode 100644 index 0000000..6a3c9d1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/cs/LC_MESSAGES/django.po @@ -0,0 +1,119 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Tomáš Ehrlich , 2015 +# Vláďa Macek , 2015-2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Czech (http://www.transifex.com/django/django/language/cs/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cs\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n " +"<= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n" + +msgid "PostgreSQL extensions" +msgstr "Rozšíření pro PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Položka č. %(nth)s v seznamu je neplatná:" + +msgid "Nested arrays must have the same length." +msgstr "Vnořená pole musejí mít stejnou délku." + +msgid "Map of strings to strings/nulls" +msgstr "Mapování řetězců na řetězce či hodnoty NULL" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Hodnota s klíčem \"%(key)s\" není řetězec ani NULL." + +msgid "Could not load JSON data." +msgstr "Data typu JSON nelze načíst." + +msgid "Input must be a JSON dictionary." +msgstr "Vstup musí být slovník formátu JSON." + +msgid "Enter two valid values." +msgstr "Zadejte dvě platné hodnoty." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Počáteční hodnota rozsahu nemůže být vyšší než koncová hodnota." + +msgid "Enter two whole numbers." +msgstr "Zadejte dvě celá čísla." + +msgid "Enter two numbers." +msgstr "Zadejte dvě čísla." + +msgid "Enter two valid date/times." +msgstr "Zadejte dvě platné hodnoty data nebo času." + +msgid "Enter two valid dates." +msgstr "Zadejte dvě platná data." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Seznam obsahuje %(show_value)d položku, ale neměl by obsahovat více než " +"%(limit_value)d." +msgstr[1] "" +"Seznam obsahuje %(show_value)d položky, ale neměl by obsahovat více než " +"%(limit_value)d." +msgstr[2] "" +"Seznam obsahuje %(show_value)d položek, ale neměl by obsahovat více než " +"%(limit_value)d." +msgstr[3] "" +"Seznam obsahuje %(show_value)d položek, ale neměl by obsahovat více než " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Seznam obsahuje %(show_value)d položku, ale neměl by obsahovat méně než " +"%(limit_value)d." +msgstr[1] "" +"Seznam obsahuje %(show_value)d položky, ale neměl by obsahovat méně než " +"%(limit_value)d." +msgstr[2] "" +"Seznam obsahuje %(show_value)d položek, ale neměl by obsahovat méně než " +"%(limit_value)d." +msgstr[3] "" +"Seznam obsahuje %(show_value)d položek, ale neměl by obsahovat méně než " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Některé klíče chybí: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Byly zadány neznámé klíče: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "Nejvyšší hodnota rozsahu musí být menší nebo rovna %(limit_value)s." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "Nejnižší hodnota rozsahu musí být větší nebo rovna %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/da/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/da/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7991704 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/da/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/da/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/da/LC_MESSAGES/django.po new file mode 100644 index 0000000..268fd75 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/da/LC_MESSAGES/django.po @@ -0,0 +1,106 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Erik Ramsgaard Wognsen , 2023 +# Erik Ramsgaard Wognsen , 2015-2020 +# valberg , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-19 09:22+0000\n" +"Last-Translator: Erik Ramsgaard Wognsen , 2023\n" +"Language-Team: Danish (http://www.transifex.com/django/django/language/da/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: da\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL-udvidelser" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Element %(nth)s i array'et blev ikke valideret:" + +msgid "Nested arrays must have the same length." +msgstr "Indlejrede arrays skal have den samme længde." + +msgid "Map of strings to strings/nulls" +msgstr "Afbildning fra strenge til strenge/nulls" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Værdien af “%(key)s” er ikke en streng eller null." + +msgid "Could not load JSON data." +msgstr "Kunne ikke indlæse JSON-data." + +msgid "Input must be a JSON dictionary." +msgstr "Input skal være et JSON-dictionary." + +msgid "Enter two valid values." +msgstr "Indtast to gyldige værdier." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Starten af intervallet kan ikke overstige slutningen af intervallet." + +msgid "Enter two whole numbers." +msgstr "Indtast to heltal." + +msgid "Enter two numbers." +msgstr "Indtast to tal." + +msgid "Enter two valid date/times." +msgstr "Indtast to gyldige dato/tider." + +msgid "Enter two valid dates." +msgstr "Indtast to gyldige datoer." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Listen indeholder %(show_value)d element, en bør ikke indeholde mere end " +"%(limit_value)d." +msgstr[1] "" +"Listen indeholder %(show_value)d elementer, den bør ikke indeholde mere end " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Listen indeholder %(show_value)d element, den bør ikke indeholde mindre end " +"%(limit_value)d." +msgstr[1] "" +"Listen indeholder %(show_value)d elementer, den bør ikke indeholde mindre " +"end %(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Nøgler mangler: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Ukendte nøgler angivet: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "Intervallets øvre grænse må ikke være større end %(limit_value)s." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "Intervallets nedre grænse må ikke være mindre end %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/de/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/de/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8f40b1c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/de/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/de/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/de/LC_MESSAGES/django.po new file mode 100644 index 0000000..6114f47 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/de/LC_MESSAGES/django.po @@ -0,0 +1,111 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Florian Apolloner , 2023 +# Jannis Leidel , 2015-2018,2020 +# Jens Neuhaus , 2016 +# Markus Holtermann , 2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-19 09:22+0000\n" +"Last-Translator: Florian Apolloner , 2023\n" +"Language-Team: German (http://www.transifex.com/django/django/language/de/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL-Erweiterungen" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Element %(nth)s im Array konnte nicht validiert werden:" + +msgid "Nested arrays must have the same length." +msgstr "Verschachtelte Arrays müssen die gleiche Länge haben." + +msgid "Map of strings to strings/nulls" +msgstr "Zuordnung von Zeichenketten zu Zeichenketten/NULLs" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Der Wert für „%(key)s“ ist keine Zeichenkette oder NULL." + +msgid "Could not load JSON data." +msgstr "Konnte JSON-Daten nicht laden." + +msgid "Input must be a JSON dictionary." +msgstr "Eingabe muss ein JSON-Dictionary sein." + +msgid "Enter two valid values." +msgstr "Bitte zwei gültige Werte eingeben." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Der Anfang des Wertbereichs darf nicht das Ende überschreiten." + +msgid "Enter two whole numbers." +msgstr "Bitte zwei ganze Zahlen eingeben." + +msgid "Enter two numbers." +msgstr "Bitte zwei Zahlen eingeben." + +msgid "Enter two valid date/times." +msgstr "Bitte zwei gültige Datum/Uhrzeit-Werte eingeben." + +msgid "Enter two valid dates." +msgstr "Bitte zwei gültige Kalenderdaten eingeben." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Liste enthält %(show_value)d Element, es sollte aber nicht mehr als " +"%(limit_value)d enthalten." +msgstr[1] "" +"Liste enthält %(show_value)d Elemente, es sollte aber nicht mehr als " +"%(limit_value)d enthalten." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Liste enthält %(show_value)d Element, es sollte aber nicht weniger als " +"%(limit_value)d enthalten." +msgstr[1] "" +"Liste enthält %(show_value)d Elemente, es sollte aber nicht weniger als " +"%(limit_value)d enthalten." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Einige Werte fehlen: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Einige unbekannte Werte wurden eingegeben: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "" +"Bitte sicherstellen, dass die obere Grenze des Bereichs nicht größer als " +"%(limit_value)s ist." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "" +"Bitte sicherstellen, dass die untere Grenze des Bereichs nicht kleiner als " +"%(limit_value)s ist." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/dsb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/dsb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d3902b9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/dsb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/dsb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/dsb/LC_MESSAGES/django.po new file mode 100644 index 0000000..b165905 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/dsb/LC_MESSAGES/django.po @@ -0,0 +1,118 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Michael Wolf , 2016-2018,2020,2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-19 09:22+0000\n" +"Last-Translator: Michael Wolf , 2016-2018,2020,2023\n" +"Language-Team: Lower Sorbian (http://www.transifex.com/django/django/" +"language/dsb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: dsb\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || " +"n%100==4 ? 2 : 3);\n" + +msgid "PostgreSQL extensions" +msgstr "Rozšyrjenja PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Zapisk %(nth)sw pólnej wariabli njejo se wobkšuśił:" + +msgid "Nested arrays must have the same length." +msgstr "Zakašćikowane pólne wariable muse tu samsku dłujkosć měś." + +msgid "Map of strings to strings/nulls" +msgstr "Konwertěrowanje znamuškowych rjeśazkow do znamuškowych rjeśazkow/nulow" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Gódnota „%(key)s“ njejo znamuškowy rjeśazk abo null." + +msgid "Could not load JSON data." +msgstr "JSON-daty njejsu se zacytowaś dali." + +msgid "Input must be a JSON dictionary." +msgstr "Zapódaśe musy JSON-słownik byś." + +msgid "Enter two valid values." +msgstr "Zapódajśo dwě płaśiwej gódnośe." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Zachopjeńk wobcerka njesmějo kóńc wobcerka pśekšocyś." + +msgid "Enter two whole numbers." +msgstr "Zapódajśo dwě cełej licbje." + +msgid "Enter two numbers." +msgstr "Zapódajśo dwě licbje." + +msgid "Enter two valid date/times." +msgstr "Zapódajśo dwě płaśiwej datowej/casowej pódaśi." + +msgid "Enter two valid dates." +msgstr "Zapódajśo dwě płaśiwej datowej pódaśi." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Lisćina wopśimujo %(show_value)d element, wóna njeby dejała wěcej ako " +"%(limit_value)d wopśimowaś." +msgstr[1] "" +"Lisćina wopśimujo %(show_value)d elementa, wóna njeby dejała wěcej ako " +"%(limit_value)d wopśimowaś." +msgstr[2] "" +"Lisćina wopśimujo %(show_value)d elementy, wóna njeby dejała wěcej ako " +"%(limit_value)d wopśimowaś." +msgstr[3] "" +"Lisćina wopśimujo %(show_value)d elementow, wóna njeby dejała wěcej ako " +"%(limit_value)d wopśimowaś." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Lisćina wopśimujo %(show_value)d element, wóna njeby dejała mjenjej ako " +"%(limit_value)d wopśimowaś." +msgstr[1] "" +"Lisćina wopśimujo %(show_value)d elementa, wóna njeby dejała mjenjej ako " +"%(limit_value)d wopśimowaś." +msgstr[2] "" +"Lisćina wopśimujo %(show_value)d elementy, wóna njeby dejała mjenjej ako " +"%(limit_value)d wopśimowaś." +msgstr[3] "" +"Lisćina wopśimujo %(show_value)d elementow, wóna njeby dejała mjenjej ako " +"%(limit_value)d wopśimowaś." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Někotare kluce feluju: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Někotare njeznate kluce su se pódali: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "Zawěsććo, až górna granica wobceŕka njejo wětša ako %(limit_value)s." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "Zawěsććo, až dolna granica wobceŕka njejo mjeńša ako %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/el/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/el/LC_MESSAGES/django.mo new file mode 100644 index 0000000..baa62ce Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/el/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/el/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/el/LC_MESSAGES/django.po new file mode 100644 index 0000000..5996c4e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/el/LC_MESSAGES/django.po @@ -0,0 +1,111 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Fotis Athineos , 2021 +# Giannis Meletakis , 2015 +# Nick Mavrakis , 2017-2018 +# Nick Mavrakis , 2016 +# Pãnoș , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2021-08-04 06:26+0000\n" +"Last-Translator: Fotis Athineos \n" +"Language-Team: Greek (http://www.transifex.com/django/django/language/el/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: el\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "Επεκτάσεις της PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "To στοιχείο %(nth)s στον πίνακα δεν είναι έγκυρο:" + +msgid "Nested arrays must have the same length." +msgstr "Οι ένθετοι πίνακες πρέπει να έχουν το ίδιο μήκος." + +msgid "Map of strings to strings/nulls" +msgstr "Αντιστοίχιση strings σε strings/nulls" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Η τιμή του “%(key)s“ δεν είναι string ή null." + +msgid "Could not load JSON data." +msgstr "Αδύνατη η φόρτωση των δεδομένων JSON." + +msgid "Input must be a JSON dictionary." +msgstr "Το input πρέπει να είναι ένα έγκυρο JSON dictionary." + +msgid "Enter two valid values." +msgstr "Εισάγετε δύο έγκυρες τιμές." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Η αρχή του range δεν πρέπει να ξεπερνά το τέλος του range." + +msgid "Enter two whole numbers." +msgstr "Εισάγετε δυο ολόκληρους αριθμούς." + +msgid "Enter two numbers." +msgstr "Εισάγετε δυο αριθμούς." + +msgid "Enter two valid date/times." +msgstr "Εισάγετε δύο έγκυρες ημερομηνίες/ώρες." + +msgid "Enter two valid dates." +msgstr "Εισάγετε δυο έγκυρες ημερομηνίες." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Η λίστα περιέχει %(show_value)d στοιχείο και δεν πρέπει να περιέχει πάνω από " +"%(limit_value)d." +msgstr[1] "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Η λίστα περιέχει %(show_value)d στοιχεία και δεν πρέπει να περιέχει λιγότερα " +"από %(limit_value)d." +msgstr[1] "" +"Η λίστα περιέχει %(show_value)d στοιχεία και δεν πρέπει να περιέχει λιγότερα " +"από %(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Έλειπαν μερικά κλειδιά: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Δόθηκαν μέρικά άγνωστα κλειδιά: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" +"Βεβαιωθείτε ότι το range είναι αυστηρά μικρότερο ή ίσο από %(limit_value)s." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "" +"Βεβαιωθείτε ότι το range είναι αυστηρά μεγαλύτερο ή ίσο από %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/en/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/en/LC_MESSAGES/django.mo new file mode 100644 index 0000000..08a7b68 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/en/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/en/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/en/LC_MESSAGES/django.po new file mode 100644 index 0000000..eaf0ad7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/en/LC_MESSAGES/django.po @@ -0,0 +1,114 @@ +# This file is distributed under the same license as the Django package. +# +msgid "" +msgstr "" +"Project-Id-Version: Django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2015-01-18 20:56+0100\n" +"Last-Translator: Django team\n" +"Language-Team: English \n" +"Language: en\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: contrib/postgres/apps.py:54 +msgid "PostgreSQL extensions" +msgstr "" + +#: contrib/postgres/fields/array.py:21 contrib/postgres/forms/array.py:17 +#: contrib/postgres/forms/array.py:185 +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "" + +#: contrib/postgres/fields/array.py:22 +msgid "Nested arrays must have the same length." +msgstr "" + +#: contrib/postgres/fields/hstore.py:15 +msgid "Map of strings to strings/nulls" +msgstr "" + +#: contrib/postgres/fields/hstore.py:17 +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "" + +#: contrib/postgres/forms/hstore.py:17 +msgid "Could not load JSON data." +msgstr "" + +#: contrib/postgres/forms/hstore.py:18 +msgid "Input must be a JSON dictionary." +msgstr "" + +#: contrib/postgres/forms/ranges.py:42 +msgid "Enter two valid values." +msgstr "" + +#: contrib/postgres/forms/ranges.py:44 +msgid "The start of the range must not exceed the end of the range." +msgstr "" + +#: contrib/postgres/forms/ranges.py:99 +msgid "Enter two whole numbers." +msgstr "" + +#: contrib/postgres/forms/ranges.py:105 +msgid "Enter two numbers." +msgstr "" + +#: contrib/postgres/forms/ranges.py:111 +msgid "Enter two valid date/times." +msgstr "" + +#: contrib/postgres/forms/ranges.py:117 +msgid "Enter two valid dates." +msgstr "" + +#: contrib/postgres/validators.py:15 +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +msgstr[1] "" + +#: contrib/postgres/validators.py:25 +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +msgstr[1] "" + +#: contrib/postgres/validators.py:38 +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "" + +#: contrib/postgres/validators.py:39 +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "" + +#: contrib/postgres/validators.py:81 +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "" + +#: contrib/postgres/validators.py:90 +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/en_AU/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/en_AU/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1ac0ada Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/en_AU/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/en_AU/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/en_AU/LC_MESSAGES/django.po new file mode 100644 index 0000000..cdae855 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/en_AU/LC_MESSAGES/django.po @@ -0,0 +1,109 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Tom Fifield , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2021-04-11 13:16+0000\n" +"Last-Translator: Tom Fifield \n" +"Language-Team: English (Australia) (http://www.transifex.com/django/django/" +"language/en_AU/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_AU\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL extensions" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Item %(nth)s in the array did not validate:" + +msgid "Nested arrays must have the same length." +msgstr "Nested arrays must have the same length." + +msgid "Map of strings to strings/nulls" +msgstr "Map of strings to strings/nulls" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "The value of “%(key)s” is not a string or null." + +msgid "Could not load JSON data." +msgstr "Could not load JSON data." + +msgid "Input must be a JSON dictionary." +msgstr "Input must be a JSON dictionary." + +msgid "Enter two valid values." +msgstr "Enter two valid values." + +msgid "The start of the range must not exceed the end of the range." +msgstr "The start of the range must not exceed the end of the range." + +msgid "Enter two whole numbers." +msgstr "Enter two whole numbers." + +msgid "Enter two numbers." +msgstr "Enter two numbers." + +msgid "Enter two valid date/times." +msgstr "Enter two valid date/times." + +msgid "Enter two valid dates." +msgstr "Enter two valid dates." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgstr[1] "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgstr[1] "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Some keys were missing: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Some unknown keys were provided: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" +"Ensure that this range is completely less than or equal to %(limit_value)s." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/eo/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/eo/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2126b26 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/eo/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/eo/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/eo/LC_MESSAGES/django.po new file mode 100644 index 0000000..e21c5a7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/eo/LC_MESSAGES/django.po @@ -0,0 +1,109 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Baptiste Darthenay , 2015-2017,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Esperanto (http://www.transifex.com/django/django/language/" +"eo/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eo\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL kromaĵoj" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Elemento %(nth)s en la tabelo ne estas valida:" + +msgid "Nested arrays must have the same length." +msgstr "Ingitaj tabeloj devas havi la saman grandon." + +msgid "Map of strings to strings/nulls" +msgstr "Kongruo de signoĉenoj al signoĉenoj/nulvaloroj" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "" + +msgid "Could not load JSON data." +msgstr "Malsukcesis ŝarĝi la JSON datumojn." + +msgid "Input must be a JSON dictionary." +msgstr "La enigo devas esti JSON vortaro." + +msgid "Enter two valid values." +msgstr "Enigu du validajn valorojn." + +msgid "The start of the range must not exceed the end of the range." +msgstr "La komenco de la intervalo ne devas superi la finon de la intervalo." + +msgid "Enter two whole numbers." +msgstr "Enigu du entjeroj." + +msgid "Enter two numbers." +msgstr "Enigu du nombroj." + +msgid "Enter two valid date/times." +msgstr "Enigu du validajn dato/horojn." + +msgid "Enter two valid dates." +msgstr "Enigu du validajn datojn." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"La listo enhavas %(show_value)d eron, kaj ne devas enhavi pli ol " +"%(limit_value)d." +msgstr[1] "" +"La listo enhavas %(show_value)d erojn, kaj ne devas enhavi pli ol " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"La listo enhavas %(show_value)d erojn, kaj devas enhavi pli ol " +"%(limit_value)d." +msgstr[1] "" +"La listo enhavas %(show_value)d erojn, kaj devas enhavi pli ol " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Kelkaj ŝlosiloj mankas: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Kelkaj nekonataj ŝlosiloj estis provizitaj: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" +"Bv kontroli, ke la tuta intervalo estas malpli alta aŭ egala al " +"%(limit_value)s." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "" +"Bv kontroli, ke la tuta intervalo estas pli alta aŭ egala al %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/es/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/es/LC_MESSAGES/django.mo new file mode 100644 index 0000000..120367b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/es/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/es/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/es/LC_MESSAGES/django.po new file mode 100644 index 0000000..7af29ed --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/es/LC_MESSAGES/django.po @@ -0,0 +1,121 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Antoni Aloy , 2015,2017 +# e4db27214f7e7544f2022c647b585925_bb0e321, 2015 +# Ignacio José Lizarán Rus , 2019 +# Igor Támara , 2015 +# Pablo, 2015 +# Uriel Medina , 2020,2023 +# Veronicabh , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-19 09:22+0000\n" +"Last-Translator: Uriel Medina , 2020,2023\n" +"Language-Team: Spanish (http://www.transifex.com/django/django/language/" +"es/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "Extensiones de PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "El elemento %(nth)s del arreglo no se pudo validar:" + +msgid "Nested arrays must have the same length." +msgstr "Los arreglos anidados deben tener la misma longitud." + +msgid "Map of strings to strings/nulls" +msgstr "Mapa de cadenas a cadenas/nulos" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "El valor de “%(key)s” no es una cadena ni es nulo." + +msgid "Could not load JSON data." +msgstr "No se pududieron cargar los datos JSON." + +msgid "Input must be a JSON dictionary." +msgstr "La entrada debe ser un diccionario JSON" + +msgid "Enter two valid values." +msgstr "Introduzca dos valores válidos." + +msgid "The start of the range must not exceed the end of the range." +msgstr "El comienzo del rango no puede exceder su final." + +msgid "Enter two whole numbers." +msgstr "Ingrese dos números enteros." + +msgid "Enter two numbers." +msgstr "Ingrese dos números." + +msgid "Enter two valid date/times." +msgstr "Ingrese dos fechas/horas válidas." + +msgid "Enter two valid dates." +msgstr "Ingrese dos fechas válidas." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"La lista contiene %(show_value)d elemento, no debería contener más de " +"%(limit_value)d." +msgstr[1] "" +"La lista contiene %(show_value)d elementos, no debería contener más de " +"%(limit_value)d." +msgstr[2] "" +"La lista contiene %(show_value)d elementos, no debería contener más de " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"La lista contiene %(show_value)d elemento, no debería contener menos de " +"%(limit_value)d." +msgstr[1] "" +"La lista contiene %(show_value)d elementos, no debería contener menos de " +"%(limit_value)d." +msgstr[2] "" +"La lista contiene %(show_value)d elementos, no debería contener menos de " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Faltan algunas claves: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Se facilitaron algunas claves desconocidas: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "" +"Asegúrese de que el límite superior del rango no sea mayor que " +"%(limit_value)s." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "" +"Asegúrese de que el límite inferior del rango no sea inferior a " +"%(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/es_AR/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/es_AR/LC_MESSAGES/django.mo new file mode 100644 index 0000000..fa3e3bd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/es_AR/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/es_AR/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/es_AR/LC_MESSAGES/django.po new file mode 100644 index 0000000..8125696 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/es_AR/LC_MESSAGES/django.po @@ -0,0 +1,115 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ramiro Morales, 2015-2019,2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-12-04 09:22+0000\n" +"Last-Translator: Ramiro Morales, 2015-2019,2023\n" +"Language-Team: Spanish (Argentina) (http://app.transifex.com/django/django/" +"language/es_AR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_AR\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "Extensiones PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "La validación del ítem %(nth)s del arreglo falló:" + +msgid "Nested arrays must have the same length." +msgstr "Los arreglos anidados deben ser de la misma longitud." + +msgid "Map of strings to strings/nulls" +msgstr "Mapa de cadenas a cadenas/nulos" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "El valor de \"%(key)s” no es una cadena o nulo." + +msgid "Could not load JSON data." +msgstr "No se han podido cargar los datos JSON." + +msgid "Input must be a JSON dictionary." +msgstr "debe ser un diccionario JSON." + +msgid "Enter two valid values." +msgstr "Introduzca dos valores válidos." + +msgid "The start of the range must not exceed the end of the range." +msgstr "El inicio del rango no debe ser mayor que el fin del rango." + +msgid "Enter two whole numbers." +msgstr "Introduzca dos números enteros." + +msgid "Enter two numbers." +msgstr "Introduzca dos números." + +msgid "Enter two valid date/times." +msgstr "Introduzca dos fechas/horas válidas." + +msgid "Enter two valid dates." +msgstr "Introduzca dos fechas válidas." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"La lista contiene %(show_value)d ítem, debe contener no mas de " +"%(limit_value)d." +msgstr[1] "" +"La lista contiene %(show_value)d ítems, debe contener no mas de " +"%(limit_value)d." +msgstr[2] "" +"La lista contiene %(show_value)d ítems, debe contener no mas de " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"La lista contiene %(show_value)d ítem, debe contener no mas de " +"%(limit_value)d." +msgstr[1] "" +"La lista contiene %(show_value)d ítems, debe contener no menos de " +"%(limit_value)d." +msgstr[2] "" +"La lista contiene %(show_value)d ítems, debe contener no menos de " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "No se encontraron algunas llaves: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Algunas de las llaves provistas son desconocidas: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "" +"Asegúrese de que el límite superior del rango no sea mayor que " +"%(limit_value)s." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "" +"Asegúrese de que el límite inferior del rango no sea menor que " +"%(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/es_CO/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/es_CO/LC_MESSAGES/django.mo new file mode 100644 index 0000000..927d16a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/es_CO/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/es_CO/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/es_CO/LC_MESSAGES/django.po new file mode 100644 index 0000000..1b8157f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/es_CO/LC_MESSAGES/django.po @@ -0,0 +1,112 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Antoni Aloy , 2015 +# Ernesto Avilés, 2015 +# Igor Támara , 2015 +# Pablo, 2015 +# Veronicabh , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Spanish (Colombia) (http://www.transifex.com/django/django/" +"language/es_CO/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_CO\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "Extensiones de PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "" + +msgid "Nested arrays must have the same length." +msgstr "Los arreglos anidados deben tener la misma longitud." + +msgid "Map of strings to strings/nulls" +msgstr "" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "" + +msgid "Could not load JSON data." +msgstr "No se pududieron cargar los datos JSON." + +msgid "Input must be a JSON dictionary." +msgstr "" + +msgid "Enter two valid values." +msgstr "Ingrese dos valores válidos." + +msgid "The start of the range must not exceed the end of the range." +msgstr "El comienzo del rango no puede exceder su final." + +msgid "Enter two whole numbers." +msgstr "Ingrese dos números enteros." + +msgid "Enter two numbers." +msgstr "Ingrese dos números." + +msgid "Enter two valid date/times." +msgstr "Ingrese dos fechas/horas válidas." + +msgid "Enter two valid dates." +msgstr "Ingrese dos fechas válidas." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"La lista contiene %(show_value)d elemento, no debería contener más de " +"%(limit_value)d." +msgstr[1] "" +"La lista contiene %(show_value)d elementos, no debería contener más de " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"La lista contiene %(show_value)d elemento, no debería contener menos de " +"%(limit_value)d." +msgstr[1] "" +"La lista contiene %(show_value)d elementos, no debería contener menos de " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Faltan algunas claves: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Se facilitaron algunas claves desconocidas: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "Asegúrese de que este rango es menor o igual que %(limit_value)s." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "" +"Asegúrese de que este rango es efectivamente mayor o igual que " +"%(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/es_MX/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/es_MX/LC_MESSAGES/django.mo new file mode 100644 index 0000000..294ebd2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/es_MX/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/es_MX/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/es_MX/LC_MESSAGES/django.po new file mode 100644 index 0000000..cf16864 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/es_MX/LC_MESSAGES/django.po @@ -0,0 +1,98 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Alex Dzul , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Spanish (Mexico) (http://www.transifex.com/django/django/" +"language/es_MX/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_MX\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "Extensiones PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "" + +msgid "Nested arrays must have the same length." +msgstr "" + +msgid "Map of strings to strings/nulls" +msgstr "" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "" + +msgid "Could not load JSON data." +msgstr "" + +msgid "Input must be a JSON dictionary." +msgstr "" + +msgid "Enter two valid values." +msgstr "Ingrese dos valores válidos" + +msgid "The start of the range must not exceed the end of the range." +msgstr "" + +msgid "Enter two whole numbers." +msgstr "" + +msgid "Enter two numbers." +msgstr "Ingrese dos números" + +msgid "Enter two valid date/times." +msgstr "" + +msgid "Enter two valid dates." +msgstr "Ingrese dos fechas válidas" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/et/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/et/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e912083 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/et/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/et/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/et/LC_MESSAGES/django.po new file mode 100644 index 0000000..6c3e66c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/et/LC_MESSAGES/django.po @@ -0,0 +1,111 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Martin Pajuste , 2015 +# Martin Pajuste , 2017 +# Marti Raudsepp , 2015-2016 +# Ragnar Rebase , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Estonian (http://www.transifex.com/django/django/language/" +"et/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: et\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL laiendused" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Element %(nth)s massiivis pole korrektne:" + +msgid "Nested arrays must have the same length." +msgstr "Mitmemõõtmelised massiivid peavad olema sama pikad." + +msgid "Map of strings to strings/nulls" +msgstr "Teisendus sõnedest sõnedeks/tühjadeks" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Võtme “%(key)s” väärtus ei ole sõne ega tühi." + +msgid "Could not load JSON data." +msgstr "Ei saanud laadida JSON andmeid." + +msgid "Input must be a JSON dictionary." +msgstr "Sisend peab olema JSON sõnastik." + +msgid "Enter two valid values." +msgstr "Sisesta kaks korrektset väärtust." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Vahemiku algus ei või olla suurem kui vahemiku lõpp." + +msgid "Enter two whole numbers." +msgstr "Sisesta kaks täisarvu." + +msgid "Enter two numbers." +msgstr "Sisesta kaks arvu." + +msgid "Enter two valid date/times." +msgstr "Sisesta kaks korrektset kuupäeva ja kellaaega." + +msgid "Enter two valid dates." +msgstr "Sisesta kaks korrektset kuupäeva." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Nimekiri sisaldab %(show_value)d elementi, ei tohiks olla rohkem kui " +"%(limit_value)d." +msgstr[1] "" +"Nimekiri sisaldab %(show_value)d elementi, ei tohiks olla rohkem kui " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Nimekiri sisaldab %(show_value)d elementi, ei tohiks olla vähem kui " +"%(limit_value)d." +msgstr[1] "" +"Nimekiri sisaldab %(show_value)d elementi, ei tohiks olla vähem kui " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Puuduvad võtmeväärtused: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Tundmatud võtmeväärtused: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" +"Veendu, et see vahemik on täielikult väiksem või võrdne kui %(limit_value)s." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "" +"Veendu, et see vahemik on täielikult suurem või võrdne kui %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/eu/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/eu/LC_MESSAGES/django.mo new file mode 100644 index 0000000..776c2f4 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/eu/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/eu/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/eu/LC_MESSAGES/django.po new file mode 100644 index 0000000..89b8acb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/eu/LC_MESSAGES/django.po @@ -0,0 +1,108 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Eneko Illarramendi , 2017-2018 +# Urtzi Odriozola , 2017,2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2021-03-18 15:48+0000\n" +"Last-Translator: Urtzi Odriozola \n" +"Language-Team: Basque (http://www.transifex.com/django/django/language/eu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL hedapenak" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Array-ko %(nth)s elementua ez da balekoa:" + +msgid "Nested arrays must have the same length." +msgstr "Array habiaratuek luzera bera izan behar dute." + +msgid "Map of strings to strings/nulls" +msgstr "String-etik string/null-era mapa" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "”%(key)s”-ren balioa ez da string bat, edo null." + +msgid "Could not load JSON data." +msgstr "Ezin izan dira JSON datuak kargatu." + +msgid "Input must be a JSON dictionary." +msgstr "Sarrera JSON hiztegi bat izan behar da." + +msgid "Enter two valid values." +msgstr "Idatzi bi baleko balio." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Tartearen hasierak ezin du amaierako tartearen balioa gainditu." + +msgid "Enter two whole numbers." +msgstr "Idatzi bi zenbaki oso." + +msgid "Enter two numbers." +msgstr "Idatzi bi zenbaki." + +msgid "Enter two valid date/times." +msgstr "Idatzi bi baleko data/ordu." + +msgid "Enter two valid dates." +msgstr "Idatzi bi baleko data." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Zerrendak elementu %(show_value)d du, ez lituzke %(limit_value)dbaino " +"gehiago izan behar." +msgstr[1] "" +"Zerrendak %(show_value)d elementu ditu, ez lituzke %(limit_value)d baino " +"gehiago izan behar." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Zerrendak elementu %(show_value)d du, ez lituzke %(limit_value)d baino " +"gutxiago izan behar." +msgstr[1] "" +"Zerrendak %(show_value)d elementu ditu, ez lituzke %(limit_value)d baino " +"gutxiago izan behar." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Gako batzuk falta dira: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Gako ezezagun batzuk eman dira: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" +"Ziurtatu guztiz tarte hau %(limit_value)s baino txikiagoa edo berdina dela." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "" +"Ziurtatu guztiz tarte hau %(limit_value)s baino handiagoa edo berdina dela." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/fa/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/fa/LC_MESSAGES/django.mo new file mode 100644 index 0000000..26bd1e5 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/fa/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/fa/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/fa/LC_MESSAGES/django.po new file mode 100644 index 0000000..e9b404e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/fa/LC_MESSAGES/django.po @@ -0,0 +1,108 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ali Nikneshan , 2015 +# MJafar Mashhadi , 2018 +# Mohammad Hossein Mojtahedi , 2016 +# Pouya Abbassi, 2016 +# rahim agh , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-27 09:32+0000\n" +"Last-Translator: rahim agh \n" +"Language-Team: Persian (http://www.transifex.com/django/django/language/" +"fa/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fa\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "PostgreSQL extensions" +msgstr "ملحقات Postgres" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "عضو %(nth)sم آرایه معتبر نیست:" + +msgid "Nested arrays must have the same length." +msgstr "آرایه های تو در تو باید هم سایز باشند" + +msgid "Map of strings to strings/nulls" +msgstr "نگاشتی از رشته به رشته/هیچمقدار" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "مقدار \"%(key)s\" یک رشته حرفی یا null نیست." + +msgid "Could not load JSON data." +msgstr "امکان بارگزاری داده های JSON نیست." + +msgid "Input must be a JSON dictionary." +msgstr "مقدار ورودی باید یک دیکشنری JSON باشد." + +msgid "Enter two valid values." +msgstr "دو مقدار معتبر وارد کنید" + +msgid "The start of the range must not exceed the end of the range." +msgstr "مقدار شروع بازه باید از پایان کوچکتر باشد" + +msgid "Enter two whole numbers." +msgstr "دو عدد کامل وارد کنید" + +msgid "Enter two numbers." +msgstr "دو عدد وارد کنید" + +msgid "Enter two valid date/times." +msgstr "دو تاریخ/ساعت معتبر وارد کنید" + +msgid "Enter two valid dates." +msgstr "دو تاریخ معتبر وارد کنید" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"لیست شامل %(show_value)d مورد است. ولی باید حداکثر شامل %(limit_value)d مورد " +"باشد." +msgstr[1] "" +"لیست شامل %(show_value)d مورد است. ولی باید حداکثر شامل %(limit_value)d مورد " +"باشد." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"لیست شامل %(show_value)d است، نباید کمتر از %(limit_value)d را شامل شود." +msgstr[1] "" +"لیست شامل %(show_value)d است، نباید کمتر از %(limit_value)d را شامل شود." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "برخی کلیدها یافت نشدند: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "برخی کلیدهای ارائه شده ناشناخته‌اند: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "اطمیمنان حاصل کنید که این رنج، کوچکتر یا برابر با %(limit_value)s است." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "اطمینان حاصل کنید که رنج، بزرگتر یا برابر با %(limit_value)s است." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/fi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/fi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..856bf2b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/fi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/fi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/fi/LC_MESSAGES/django.po new file mode 100644 index 0000000..ce5af05 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/fi/LC_MESSAGES/django.po @@ -0,0 +1,110 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Aarni Koskela, 2015,2017,2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-12-09 06:30+0000\n" +"Last-Translator: Aarni Koskela\n" +"Language-Team: Finnish (http://www.transifex.com/django/django/language/" +"fi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL-laajennukset" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Taulukon %(nth)s alkio ei ole kelvollinen:" + +msgid "Nested arrays must have the same length." +msgstr "Sisäkkäisillä taulukoilla tulee olla sama pituus." + +msgid "Map of strings to strings/nulls" +msgstr "Kartta merkkijonoista merkkijonoihin tai tyhjiin (null)" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Avaimen \"%(key)s\" arvo ei ole merkkijono tai tyhjä (null)." + +msgid "Could not load JSON data." +msgstr "JSON-dataa ei voitu ladata." + +msgid "Input must be a JSON dictionary." +msgstr "Syötteen tulee olla JSON-sanakirja." + +msgid "Enter two valid values." +msgstr "Anna kaksi oikeaa arvoa." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Alueen alku pitää olla pienempi kuin alueen loppu." + +msgid "Enter two whole numbers." +msgstr "Anna kaksi kokonaislukua." + +msgid "Enter two numbers." +msgstr "Anna kaksi lukua." + +msgid "Enter two valid date/times." +msgstr "Anna kaksi oikeaa päivämäärää/kellonaikaa." + +msgid "Enter two valid dates." +msgstr "Anna kaksi oikeaa päivämäärää." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Listassa on %(show_value)d arvo, mutta siinä ei saa olla enempää kuin " +"%(limit_value)d." +msgstr[1] "" +"Listassa on %(show_value)d arvoa, mutta siinä ei saa olla enempää kuin " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Listassa on %(show_value)d arvo, mutta siinä ei saa olla vähempää kuin " +"%(limit_value)d arvoa." +msgstr[1] "" +"Listassa on %(show_value)d arvoa, mutta siinä ei saa olla vähempää kuin " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Joitain avaimia puuttuu: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Tuntemattomia avaimia annettiin: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" +"Tämän alueen tulee olla kokonaisuudessaan yhtäsuuri tai pienempi kuin " +"%(limit_value)s." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "" +"Tämän alueen tulee olla kokonaisuudessaan yhtäsuuri tai suurempi kuin " +"%(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/fr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/fr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b4230ed Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/fr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/fr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 0000000..a0e4724 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,114 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Claude Paroz , 2015-2019,2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-19 09:22+0000\n" +"Last-Translator: Claude Paroz , 2015-2019,2023\n" +"Language-Team: French (http://www.transifex.com/django/django/language/fr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "PostgreSQL extensions" +msgstr "Extensions PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "L'élément n°%(nth)s du tableau n’est pas valide :" + +msgid "Nested arrays must have the same length." +msgstr "Les tableaux imbriqués doivent être de même longueur." + +msgid "Map of strings to strings/nulls" +msgstr "Correspondances clé/valeur (chaînes ou valeurs nulles)" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "La valeur de « %(key)s » n’est pas une chaîne, ni une valeur nulle." + +msgid "Could not load JSON data." +msgstr "Impossible de charger les données JSON." + +msgid "Input must be a JSON dictionary." +msgstr "Le contenu saisi doit être un dictionnaire JSON." + +msgid "Enter two valid values." +msgstr "Saisissez deux valeurs valides." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Le début de l’intervalle ne peut pas dépasser la fin de l'intervalle." + +msgid "Enter two whole numbers." +msgstr "Saisissez deux nombres entiers." + +msgid "Enter two numbers." +msgstr "Saisissez deux nombres." + +msgid "Enter two valid date/times." +msgstr "Saisissez deux dates/heures valides." + +msgid "Enter two valid dates." +msgstr "Saisissez deux dates valides." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"La liste contient %(show_value)d élément, mais elle ne devrait pas en " +"contenir plus de %(limit_value)d." +msgstr[1] "" +"La liste contient %(show_value)d éléments, mais elle ne devrait pas en " +"contenir plus de %(limit_value)d." +msgstr[2] "" +"La liste contient %(show_value)d éléments, mais elle ne devrait pas en " +"contenir plus de %(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"La liste contient %(show_value)d élément, mais elle doit en contenir au " +"moins %(limit_value)d." +msgstr[1] "" +"La liste contient %(show_value)d éléments, mais elle doit en contenir au " +"moins %(limit_value)d." +msgstr[2] "" +"La liste contient %(show_value)d éléments, mais elle doit en contenir au " +"moins %(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Certaines clés sont manquantes : %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Certaines clés inconnues ont été fournies : %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "" +"S’assure que la limite supérieure de l’intervalle n’est pas plus grande que " +"%(limit_value)s." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "" +"S’assure que la limite inférieure de l’intervalle n’est pas plus petite que " +"%(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/gd/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/gd/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9e8b0fd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/gd/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/gd/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/gd/LC_MESSAGES/django.po new file mode 100644 index 0000000..29b9050 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/gd/LC_MESSAGES/django.po @@ -0,0 +1,125 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# GunChleoc, 2016-2017 +# GunChleoc, 2015 +# GunChleoc, 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Gaelic, Scottish (http://www.transifex.com/django/django/" +"language/gd/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: gd\n" +"Plural-Forms: nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : " +"(n > 2 && n < 20) ? 2 : 3;\n" + +msgid "PostgreSQL extensions" +msgstr "Leudachain PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Cha deach le dearbhadh an nì %(nth)s san arraigh:" + +msgid "Nested arrays must have the same length." +msgstr "Feumaidh an aon fhaid a bhith aig a h-uile arraigh neadaichte." + +msgid "Map of strings to strings/nulls" +msgstr "Mapaichean de shreangan gu sreangan/luachan null" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Chan eil an luach air %(key)s ’na shreang no null." + +msgid "Could not load JSON data." +msgstr "Cha deach leinn dàta JSON a luchdadh." + +msgid "Input must be a JSON dictionary." +msgstr "Feumaidh an t-ion-chur a bhith 'na fhaclair JSON." + +msgid "Enter two valid values." +msgstr "Cuir a-steach dà luach dligheach." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Chan fhaod toiseach na rainse a bith nas motha na deireadh na rainse." + +msgid "Enter two whole numbers." +msgstr "Cuir a-steach dà àireamh shlàn." + +msgid "Enter two numbers." +msgstr "Cuir a-steach dà àireamh." + +msgid "Enter two valid date/times." +msgstr "Cuir a-steach dà cheann-là ’s àm dligheach." + +msgid "Enter two valid dates." +msgstr "Cuir a-steach dà cheann-là dligheach." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Tha %(show_value)d nì air an liosta ach cha bu chòir corr is %(limit_value)d " +"a bhith oirre." +msgstr[1] "" +"Tha %(show_value)d nì air an liosta ach cha bu chòir corr is %(limit_value)d " +"a bhith oirre." +msgstr[2] "" +"Tha %(show_value)d nithean air an liosta ach cha bu chòir corr is " +"%(limit_value)d a bhith oirre." +msgstr[3] "" +"Tha %(show_value)d nì air an liosta ach cha bu chòir corr is %(limit_value)d " +"a bhith oirre." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Tha %(show_value)d nì air an liosta ach cha bu chòir nas lugha na " +"%(limit_value)d a bhith oirre." +msgstr[1] "" +"Tha %(show_value)d nì air an liosta ach cha bu chòir nas lugha na " +"%(limit_value)d a bhith oirre." +msgstr[2] "" +"Tha %(show_value)d nithean air an liosta ach cha bu chòir nas lugha na " +"%(limit_value)d a bhith oirre." +msgstr[3] "" +"Tha %(show_value)d nì air an liosta ach cha bu chòir nas lugha na " +"%(limit_value)d a bhith oirre." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Bha cuid a dh’iuchraichean a dhìth: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Chaidh iuchraichean nach aithne dhuinn a shònrachadh: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" +"Dèan cinnteach gu bheil an rainse seo nas lugha na no co-ionnan ri " +"%(limit_value)s air fad." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "" +"Dèan cinnteach gu bheil an rainse seo nas motha na no co-ionnan ri " +"%(limit_value)s air fad." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/gl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/gl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c90b428 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/gl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/gl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/gl/LC_MESSAGES/django.po new file mode 100644 index 0000000..0fb8d3b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/gl/LC_MESSAGES/django.po @@ -0,0 +1,108 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# fasouto , 2017 +# X Bello , 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-19 09:22+0000\n" +"Last-Translator: X Bello , 2023\n" +"Language-Team: Galician (http://www.transifex.com/django/django/language/" +"gl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: gl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "Extensión de PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "O %(nth)s elemento do array non validóu:" + +msgid "Nested arrays must have the same length." +msgstr "Os arrais aniñados teñen que ter a mesma lonxitude." + +msgid "Map of strings to strings/nulls" +msgstr "Mapeo de strings a strings/nulos" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "O valor de “%(key)s” non é un string ou nulo." + +msgid "Could not load JSON data." +msgstr "Non se puderon cargar os datos JSON." + +msgid "Input must be a JSON dictionary." +msgstr "A entrada ten que ser un diccionario JSON." + +msgid "Enter two valid values." +msgstr "Introduza dous valores válidos." + +msgid "The start of the range must not exceed the end of the range." +msgstr "O comezo do rango non pode superar o fin do rango." + +msgid "Enter two whole numbers." +msgstr "Introduza dous números completos." + +msgid "Enter two numbers." +msgstr "Insira dous números." + +msgid "Enter two valid date/times." +msgstr "Insira dúas datas/horas válidas." + +msgid "Enter two valid dates." +msgstr "Insira dúas datas válidas." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"A lista contén %(show_value)d elemento, non debería conter máis de " +"%(limit_value)d." +msgstr[1] "" +"A lista contén %(show_value)d elementos, non debería conter máis de " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"A lista contén %(show_value)d elemento, non debería conter menos de " +"%(limit_value)d." +msgstr[1] "" +"A lista contén %(show_value)d elementos, non debería conter menos de " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Faltan algunhas chaves: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Facilitáronse algunhas chaves descoñecidas: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "" +"Asegúrese de que o límite superior do rango non é maior que %(limit_value)s." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "" +"Asegúrese de que o límite inferior do rango non é menor que %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/he/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/he/LC_MESSAGES/django.mo new file mode 100644 index 0000000..30f0e16 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/he/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/he/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/he/LC_MESSAGES/django.po new file mode 100644 index 0000000..c59ea67 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/he/LC_MESSAGES/django.po @@ -0,0 +1,110 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Meir Kriheli , 2015,2017,2019,2023 +# אורי רודברג , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-12-04 09:22+0000\n" +"Last-Translator: Meir Kriheli , 2015,2017,2019,2023\n" +"Language-Team: Hebrew (http://app.transifex.com/django/django/language/he/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: he\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % " +"1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;\n" + +msgid "PostgreSQL extensions" +msgstr "הרחבות PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "פריט %(nth)s במערך לא עבר בדיקת חוקיות: " + +msgid "Nested arrays must have the same length." +msgstr "מערכים מקוננים חייבים להיות באותו האורך." + +msgid "Map of strings to strings/nulls" +msgstr "מיפוי מחרוזות אל מחרוזות/nulls." + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "הערך של \"%(key)s\" אינו מחרוזת או null." + +msgid "Could not load JSON data." +msgstr "לא ניתן לטעון מידע JSON." + +msgid "Input must be a JSON dictionary." +msgstr "הקלט חייב להיות מילון JSON." + +msgid "Enter two valid values." +msgstr "נא להזין שני ערכים חוקיים." + +msgid "The start of the range must not exceed the end of the range." +msgstr "התחלת טווח אינה יכולה גדולה יותר מסופו." + +msgid "Enter two whole numbers." +msgstr "נא להזין שני מספרים שלמים." + +msgid "Enter two numbers." +msgstr "נא להזין שני מספרים." + +msgid "Enter two valid date/times." +msgstr "נא להזין שני תאריך/שעה חוקיים." + +msgid "Enter two valid dates." +msgstr "נא להזין שני תאריכים חוקיים." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"הרשימה מכילה פריט %(show_value)d, עליה להכיל לא יותר מ-%(limit_value)d." +msgstr[1] "" +"הרשימה מכילה %(show_value)d פריטים, עליה להכיל לא יותר מ-%(limit_value)d." +msgstr[2] "" +"הרשימה מכילה %(show_value)d פריטים, עליה להכיל לא יותר מ-%(limit_value)d." +msgstr[3] "" +"הרשימה מכילה %(show_value)d פריטים, עליה להכיל לא יותר מ-%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"הרשימה מכילה פריט %(show_value)d, עליה להכיל לא פחות מ-%(limit_value)d." +msgstr[1] "" +"הרשימה מכילה %(show_value)d פריטים, עליה להכיל לא פחות מ-%(limit_value)d." +msgstr[2] "" +"הרשימה מכילה %(show_value)d פריטים, עליה להכיל לא פחות מ-%(limit_value)d." +msgstr[3] "" +"הרשימה מכילה %(show_value)d פריטים, עליה להכיל לא פחות מ-%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "חלק מהמפתחות חסרים: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "סופקו מספר מפתחות לא ידועים: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "נא לוודא שהגבול העליון של הטווח אינו גדול מ־%(limit_value)s." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "נא לוודא שהגבול התחתון של הטווח אינו קטן מ־%(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/hr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/hr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..99c9fde Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/hr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/hr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/hr/LC_MESSAGES/django.po new file mode 100644 index 0000000..b48912b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/hr/LC_MESSAGES/django.po @@ -0,0 +1,102 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Filip Cuk , 2016 +# Mislav Cimperšak , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Croatian (http://www.transifex.com/django/django/language/" +"hr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hr\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +msgid "PostgreSQL extensions" +msgstr "" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "" + +msgid "Nested arrays must have the same length." +msgstr "" + +msgid "Map of strings to strings/nulls" +msgstr "" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "" + +msgid "Could not load JSON data." +msgstr "JSON podatci neuspješno učitani." + +msgid "Input must be a JSON dictionary." +msgstr "" + +msgid "Enter two valid values." +msgstr "Unesite 2 ispravne vrijednosti." + +msgid "The start of the range must not exceed the end of the range." +msgstr "" + +msgid "Enter two whole numbers." +msgstr "Unesite dva cijela broja." + +msgid "Enter two numbers." +msgstr "Unesite dva broja." + +msgid "Enter two valid date/times." +msgstr "Unesite dva ispravna datuma/vremena." + +msgid "Enter two valid dates." +msgstr "Unesite dva ispravna datuma." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/hsb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/hsb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1bad454 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/hsb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/hsb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/hsb/LC_MESSAGES/django.po new file mode 100644 index 0000000..62280f1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/hsb/LC_MESSAGES/django.po @@ -0,0 +1,118 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Michael Wolf , 2016-2019,2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-19 09:22+0000\n" +"Last-Translator: Michael Wolf , 2016-2019,2023\n" +"Language-Team: Upper Sorbian (http://www.transifex.com/django/django/" +"language/hsb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hsb\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || " +"n%100==4 ? 2 : 3);\n" + +msgid "PostgreSQL extensions" +msgstr "Rozšěrjenja PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Zapisk %(nth)s w pólnym wariabli njeje so wokrućił:" + +msgid "Nested arrays must have the same length." +msgstr "Zakašćikowane pólne wariable maja samsnu dołhosć." + +msgid "Map of strings to strings/nulls" +msgstr "Konwertowanje znamješkowych rjećazkow do znamješkowych rjećazkow/nulow" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Hódnota \" %(key)s\" znamješkowy rjećazk abo null njeje." + +msgid "Could not load JSON data." +msgstr "JSON-daty njedachu so začitać." + +msgid "Input must be a JSON dictionary." +msgstr "Zapodaće dyrbi JSON-słownik być." + +msgid "Enter two valid values." +msgstr "Zapodajće dwě płaćiwej hódnoće." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Spočatk wobłuka njesmě kónc wobłuka překročić." + +msgid "Enter two whole numbers." +msgstr "Zapodajće dwě cyłej ličbje." + +msgid "Enter two numbers." +msgstr "Zapodajće dwě ličbje." + +msgid "Enter two valid date/times." +msgstr "Zapódajće dwě płaćiwej datowej/časowej podaći." + +msgid "Enter two valid dates." +msgstr "Zapodajće dwě płaćiwej datowej podaći." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Lisćina %(show_value)d element wobsahuje, wona njeměła wjace hač " +"%(limit_value)d wobsahować." +msgstr[1] "" +"Lisćina %(show_value)d elementaj wobsahuje, wona njeměła wjace hač " +"%(limit_value)d wobsahować." +msgstr[2] "" +"Lisćina %(show_value)d elementy wobsahuje, wona njeměła wjace hač " +"%(limit_value)d wobsahować." +msgstr[3] "" +"Lisćina %(show_value)d elementow wobsahuje, wona njeměła wjace hač " +"%(limit_value)d wobsahować." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Lisćina %(show_value)d element wobsahuje, wona njeměła mjenje hač " +"%(limit_value)d wobsahować." +msgstr[1] "" +"Lisćina %(show_value)d elementaj wobsahuje, wona njeměła mjenje hač " +"%(limit_value)d wobsahować." +msgstr[2] "" +"Lisćina %(show_value)d elementy wobsahuje, wona njeměła mjenje hač " +"%(limit_value)d wobsahować." +msgstr[3] "" +"Lisćina %(show_value)d elementow wobsahuje, wona njeměła mjenje hač " +"%(limit_value)d wobsahować." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Někotre kluče faluje: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Někotre njeznate kluče su so podali: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "Zawěsćće, zo hornja hranica wobłuka njeje wjetša hač %(limit_value)s." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "Zawěsćće, zo delnja hranica wobłuka njeje mjeńša hač %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/hu/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/hu/LC_MESSAGES/django.mo new file mode 100644 index 0000000..675614c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/hu/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/hu/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/hu/LC_MESSAGES/django.po new file mode 100644 index 0000000..1adb7d1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/hu/LC_MESSAGES/django.po @@ -0,0 +1,110 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Akos Zsolt Hochrein , 2018 +# András Veres-Szentkirályi, 2016 +# Balázs R, 2023 +# Dóra Szendrei , 2017 +# Istvan Farkas , 2019 +# János R, 2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-12-04 09:22+0000\n" +"Last-Translator: Balázs R, 2023\n" +"Language-Team: Hungarian (http://app.transifex.com/django/django/language/" +"hu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL kiterjesztések" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "A tömb %(nth)s-ik eleme érvénytelen:" + +msgid "Nested arrays must have the same length." +msgstr "A belső tömböknek egyforma hosszúaknak kell lenniük." + +msgid "Map of strings to strings/nulls" +msgstr "String-string/null leképezés" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "A(z) \"%(key)s\" nem karakterlánc, vagy null." + +msgid "Could not load JSON data." +msgstr "JSON adat betöltése sikertelen." + +msgid "Input must be a JSON dictionary." +msgstr "A bemenetnek JSON szótárnak kell lennie." + +msgid "Enter two valid values." +msgstr "Adjon meg két érvényes értéket." + +msgid "The start of the range must not exceed the end of the range." +msgstr "A tartomány eleje nem lehet nagyobb a tartomány végénél." + +msgid "Enter two whole numbers." +msgstr "Adjon meg két egész számot." + +msgid "Enter two numbers." +msgstr "Adjon meg két számot." + +msgid "Enter two valid date/times." +msgstr "Adjon meg két érvényes dátumot/időt." + +msgid "Enter two valid dates." +msgstr "Adjon meg két érvényes dátumot." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"A lista %(show_value)d elemet tartalmaz, legfeljebb %(limit_value)d lehetne." +msgstr[1] "" +"A lista %(show_value)d elemet tartalmaz, legfeljebb %(limit_value)d lehetne." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"A lista %(show_value)d elemet tartalmaz, legalább %(limit_value)d kellene." +msgstr[1] "" +"A lista %(show_value)d elemet tartalmaz, legalább %(limit_value)d kellene." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Néhány kulcs hiányzik: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Néhány ismeretlen kulcs érkezett: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "" +"Bizonyosodjon meg arról, hogy a tartomány felső határa nem nagyobb, mint " +"%(limit_value)s." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "" +"Bizonyosodjon meg arról, hogy a tartomány alsó határa nem kisebb, mint " +"%(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/hy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/hy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..fe0d7ab Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/hy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/hy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/hy/LC_MESSAGES/django.po new file mode 100644 index 0000000..7b7fe80 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/hy/LC_MESSAGES/django.po @@ -0,0 +1,109 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Armenian (http://www.transifex.com/django/django/language/" +"hy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hy\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL հավելվածներ" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "" + +msgid "Nested arrays must have the same length." +msgstr "Ներդրված մասսիվները պետք է ունենան նույն երկարությունը" + +msgid "Map of strings to strings/nulls" +msgstr "" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "" + +msgid "Could not load JSON data." +msgstr "Չհաջողվեց բեռնել JSON տվյալները" + +msgid "Input must be a JSON dictionary." +msgstr "" + +msgid "Enter two valid values." +msgstr "Մուտքագրեք երկու վավերական արժեք" + +msgid "The start of the range must not exceed the end of the range." +msgstr "Ինտերվալի սկիզբը չպետք է գերազանցի նրա ավարտը" + +msgid "Enter two whole numbers." +msgstr "Մուտքագրեք երկու ամբողջ թիվ" + +msgid "Enter two numbers." +msgstr "Մուտքագրեք երկու թիվ" + +msgid "Enter two valid date/times." +msgstr "Մուտքագրեք երկու ճիշտ ամսաթվեր/ժամանակ" + +msgid "Enter two valid dates." +msgstr "Մուտքագրեք երկու ճիշտ ամսաթվեր" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Ցուցակը պարունակում է %(show_value)d էլեմենտը, բայց այն պետք է պարունակի " +"%(limit_value)d֊ից ոչ ավելի էլեմենտ" +msgstr[1] "" +"Ցուցակը պարունակում է %(show_value)d էլեմենտները, բայց այն պետք է պարունակի " +"%(limit_value)d֊ից ոչ ավելի էլեմենտ" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Ցուցակը պարունակում է %(show_value)d էլեմենտը, բայց այն պետք է պարունակի " +"%(limit_value)d֊ից ոչ պակաս էլեմենտ" +msgstr[1] "" +"Ցուցակը պարունակում է %(show_value)d էլեմենտը, բայց այն պետք է պարունակի " +"%(limit_value)d֊ից ոչ պակաս էլեմենտ" + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Որոշ բանալիներ պակասում են՝ %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Տրամադրվել են որոշ անհայտ բանալիներ՝ %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" +"Համոզվեք, որ տիրույթին պատկանող արժեքները փոքր են, կամ հավասար " +"%(limit_value)s֊ի" + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "" +"Համոզվեք, որ տիրույթին պատկանող արժեքները մեծ են, կամ հավասար " +"%(limit_value)s֊ի" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ia/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ia/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e26e0b3 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ia/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ia/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ia/LC_MESSAGES/django.po new file mode 100644 index 0000000..68829ff --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ia/LC_MESSAGES/django.po @@ -0,0 +1,98 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Martijn Dekker , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Interlingua (http://www.transifex.com/django/django/language/" +"ia/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ia\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "Extensiones PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "" + +msgid "Nested arrays must have the same length." +msgstr "Arrays annidate debe haber le mesme longitude." + +msgid "Map of strings to strings/nulls" +msgstr "" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "" + +msgid "Could not load JSON data." +msgstr "" + +msgid "Input must be a JSON dictionary." +msgstr "" + +msgid "Enter two valid values." +msgstr "" + +msgid "The start of the range must not exceed the end of the range." +msgstr "" + +msgid "Enter two whole numbers." +msgstr "" + +msgid "Enter two numbers." +msgstr "" + +msgid "Enter two valid date/times." +msgstr "" + +msgid "Enter two valid dates." +msgstr "" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/id/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/id/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b8f6c66 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/id/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/id/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/id/LC_MESSAGES/django.po new file mode 100644 index 0000000..a059510 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/id/LC_MESSAGES/django.po @@ -0,0 +1,109 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Fery Setiawan , 2015-2018 +# M Asep Indrayana , 2015 +# oon arfiandwi , 2016 +# rodin , 2016 +# sage , 2019 +# Sutrisno Efendi , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Indonesian (http://www.transifex.com/django/django/language/" +"id/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: id\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "PostgreSQL extensions" +msgstr "Ekstensi PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Butir %(nth)s dalam larik tidak tervalidasi:" + +msgid "Nested arrays must have the same length." +msgstr "Array bersaran harus mempunyai panjang yang sama." + +msgid "Map of strings to strings/nulls" +msgstr "Pemetaan dari string ke string/null" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Nilai dari “%(key)s” bukan sebuah string atau null." + +msgid "Could not load JSON data." +msgstr "Tidak dapat memuat data JSON." + +msgid "Input must be a JSON dictionary." +msgstr "Masukan harus kamus JSON." + +msgid "Enter two valid values." +msgstr "Masukkan dua nilai yang valid." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Awal jangkauan harus tidak melebihi akhir jangkauan." + +msgid "Enter two whole numbers." +msgstr "Masukkan dua buah bilangan bulat." + +msgid "Enter two numbers." +msgstr "Masukkan dua buah bilangan." + +msgid "Enter two valid date/times." +msgstr "Masukan dua buah tanggal/waktu." + +msgid "Enter two valid dates." +msgstr "Masukan dua buah tanggal yang benar." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Daftar mengandung %(show_value)d butir, seharusnya mengandung tidak lebih " +"dari %(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Daftar mengandung%(show_value)d butir, seharusnya mengandung tidak kurang " +"dari %(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Beberapa kunci hilang: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Beberapa kunci yang tidak dikenali diberikan: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" +"Pastikan bahwa jangkauan ini sepenuhnya kurang dari atau sama dengan " +"%(limit_value)s." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "" +"Pastikan bahwa jangkauan ini sepenuhnya lebih dari atau sama dengan " +"%(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/is/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/is/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9f6a21e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/is/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/is/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/is/LC_MESSAGES/django.po new file mode 100644 index 0000000..a1ccb7c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/is/LC_MESSAGES/django.po @@ -0,0 +1,108 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Thordur Sigurdsson , 2016-2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Icelandic (http://www.transifex.com/django/django/language/" +"is/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: is\n" +"Plural-Forms: nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL viðbætur" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Hlutur %(nth)s í listanum er ógildur:" + +msgid "Nested arrays must have the same length." +msgstr "Faldaðir (nested) listar verða að vera af sömu lengd." + +msgid "Map of strings to strings/nulls" +msgstr "Möppun strengja í strengi/null" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Gildið á \"%(key)s\" er ekki strengur eða null." + +msgid "Could not load JSON data." +msgstr "Gat ekki hlaðið inn JSON gögnum." + +msgid "Input must be a JSON dictionary." +msgstr "Inntak verður að vera JSON hlutur (dictionary)." + +msgid "Enter two valid values." +msgstr "Sláðu inn tvö gild gildi." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Upphaf bils má ekki ná yfir endalok bils." + +msgid "Enter two whole numbers." +msgstr "Sláðu inn tvær heilar tölur." + +msgid "Enter two numbers." +msgstr "Sláðu inn tvær tölur." + +msgid "Enter two valid date/times." +msgstr "Sláðu inn tvær gildar dagsetningar ásamt tíma." + +msgid "Enter two valid dates." +msgstr "Sláðu inn tvær gildar dagsetningar." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Listinn inniheldur %(show_value)d hlut, en má ekki innihalda fleiri en " +"%(limit_value)d." +msgstr[1] "" +"Listinn inniheldur %(show_value)d hluti, en má ekki innihalda fleiri en " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Listinn inniheldur %(show_value)d hlut, en má ekki innihalda færri en " +"%(limit_value)d." +msgstr[1] "" +"Listinn inniheldur %(show_value)d hluti, en má ekki innihalda færri en " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Þessa lykla vantar: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Þessir óþekktu lyklar fundust: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" +"Gakktu úr skugga um að þetta bil sé minna eða jafnt og %(limit_value)s." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "" +"Gakktu úr skugga um að þetta bil sé stærra eða jafnt og %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/it/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/it/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c0f2bcd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/it/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/it/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/it/LC_MESSAGES/django.po new file mode 100644 index 0000000..5d082ca --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/it/LC_MESSAGES/django.po @@ -0,0 +1,122 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# 0d21a39e384d88c2313b89b5042c04cb, 2017 +# Flavio Curella , 2016 +# Mirco Grillo , 2018,2020 +# palmux , 2015 +# Paolo Melchiorre , 2023 +# Mattia Procopio , 2015 +# Stefano Brentegani , 2015-2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-19 09:22+0000\n" +"Last-Translator: Paolo Melchiorre , 2023\n" +"Language-Team: Italian (http://www.transifex.com/django/django/language/" +"it/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: it\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "Estensioni per PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "L'elemento %(nth)s dell'array non è stato convalidato:" + +msgid "Nested arrays must have the same length." +msgstr "Gli array annidati devono avere la stessa lunghezza." + +msgid "Map of strings to strings/nulls" +msgstr "Mappa di stringhe a stringhe/null" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Il valore di \"%(key)s\" non è una stringa o nullo." + +msgid "Could not load JSON data." +msgstr "Caricamento dati JSON fallito." + +msgid "Input must be a JSON dictionary." +msgstr "L'input deve essere un dizionario JSON." + +msgid "Enter two valid values." +msgstr "Inserisci due valori validi." + +msgid "The start of the range must not exceed the end of the range." +msgstr "" +"Il valore iniziale dell'intervallo non può essere superiore al valore finale." + +msgid "Enter two whole numbers." +msgstr "Inserisci due numeri interi." + +msgid "Enter two numbers." +msgstr "Inserisci due numeri." + +msgid "Enter two valid date/times." +msgstr "Inserisci due valori data/ora validi." + +msgid "Enter two valid dates." +msgstr "Inserisci due date valide." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"La lista contiene %(show_value)d oggetto, non dovrebbe contenerne più di " +"%(limit_value)d." +msgstr[1] "" +"La lista contiene %(show_value)d elementi, e dovrebbe contenerne al massimo " +"%(limit_value)d." +msgstr[2] "" +"La lista contiene %(show_value)d elementi, e dovrebbe contenerne al massimo " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"La lista contiene %(show_value)d oggetto, non dovrebbe contenerne meno di " +"%(limit_value)d." +msgstr[1] "" +"La lista contiene %(show_value)d oggetti, e dovrebbe contenerne almeno " +"%(limit_value)d." +msgstr[2] "" +"La lista contiene %(show_value)d oggetti, e dovrebbe contenerne almeno " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Alcune chiavi risultano mancanti: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Sono state fornite alcune chiavi sconosciute: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "" +"Assicurarsi che il limite superiore dell'intervallo non sia maggiore di " +"%(limit_value)s." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "" +"Assicurarsi che il limite inferiore dell'intervallo non sia inferiore a " +"%(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ja/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ja/LC_MESSAGES/django.mo new file mode 100644 index 0000000..fa79bbd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ja/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ja/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ja/LC_MESSAGES/django.po new file mode 100644 index 0000000..fb73aac --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ja/LC_MESSAGES/django.po @@ -0,0 +1,100 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Shinya Okano , 2015-2018,2023 +# Takuya N , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-19 09:22+0000\n" +"Last-Translator: Shinya Okano , 2015-2018,2023\n" +"Language-Team: Japanese (http://www.transifex.com/django/django/language/" +"ja/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ja\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL拡張" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "配列内のアイテム %(nth)s は検証できませんでした:" + +msgid "Nested arrays must have the same length." +msgstr "ネストした配列は同じ長さにしなければなりません。" + +msgid "Map of strings to strings/nulls" +msgstr "文字列と文字列/NULLのマップ" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "“%(key)s” の値は文字列または NULL ではありません。" + +msgid "Could not load JSON data." +msgstr "JSONデータを読み込めませんでした。" + +msgid "Input must be a JSON dictionary." +msgstr "JSON辞書を入力しなければなりません。" + +msgid "Enter two valid values." +msgstr "2つの値を正しく入力してください。" + +msgid "The start of the range must not exceed the end of the range." +msgstr "範囲の開始は、範囲の終わりを超えてはなりません。" + +msgid "Enter two whole numbers." +msgstr "2つの整数を入力してください。" + +msgid "Enter two numbers." +msgstr "2つの数値を入力してください。" + +msgid "Enter two valid date/times." +msgstr "2つの日付/時間を入力してください。" + +msgid "Enter two valid dates." +msgstr "2つの日付を入力してください。" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"リストには%(show_value)d個のアイテムが含まれますが、%(limit_value)d個までしか" +"含められません。" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"リストには%(show_value)d個のアイテムが含まれますが、%(limit_value)d個までしか" +"含められません。" + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "いくつかのキーが欠落しています: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "いくつかの不明なキーがあります: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "範囲の上限が%(limit_value)sを超えないようにしてください。" + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "範囲の下限が%(limit_value)sより小さくならないようにしてください。" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ka/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ka/LC_MESSAGES/django.mo new file mode 100644 index 0000000..510f545 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ka/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ka/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ka/LC_MESSAGES/django.po new file mode 100644 index 0000000..d1ae6c8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ka/LC_MESSAGES/django.po @@ -0,0 +1,98 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# André Bouatchidzé , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Georgian (http://www.transifex.com/django/django/language/" +"ka/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ka\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL-ის გაფართოებები" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "" + +msgid "Nested arrays must have the same length." +msgstr "" + +msgid "Map of strings to strings/nulls" +msgstr "" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "" + +msgid "Could not load JSON data." +msgstr "" + +msgid "Input must be a JSON dictionary." +msgstr "" + +msgid "Enter two valid values." +msgstr "" + +msgid "The start of the range must not exceed the end of the range." +msgstr "" + +msgid "Enter two whole numbers." +msgstr "შეიყვანეთ ორი მთელი რიცხვი." + +msgid "Enter two numbers." +msgstr "შეიყვანეთ ორი რიცხვი." + +msgid "Enter two valid date/times." +msgstr "" + +msgid "Enter two valid dates." +msgstr "" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/kk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/kk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..22c521b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/kk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/kk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/kk/LC_MESSAGES/django.po new file mode 100644 index 0000000..f5deca2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/kk/LC_MESSAGES/django.po @@ -0,0 +1,97 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Leo Trubach , 2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Kazakh (http://www.transifex.com/django/django/language/kk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kk\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL кеңейтулері" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "" + +msgid "Nested arrays must have the same length." +msgstr "Бір-бірін ішіне салынған ауқымдардың ұзындықтары бірдей болу керек" + +msgid "Map of strings to strings/nulls" +msgstr "" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "" + +msgid "Could not load JSON data." +msgstr "" + +msgid "Input must be a JSON dictionary." +msgstr "" + +msgid "Enter two valid values." +msgstr "" + +msgid "The start of the range must not exceed the end of the range." +msgstr "" + +msgid "Enter two whole numbers." +msgstr "" + +msgid "Enter two numbers." +msgstr "" + +msgid "Enter two valid date/times." +msgstr "" + +msgid "Enter two valid dates." +msgstr "" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ko/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ko/LC_MESSAGES/django.mo new file mode 100644 index 0000000..af8e218 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ko/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ko/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ko/LC_MESSAGES/django.po new file mode 100644 index 0000000..9788384 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ko/LC_MESSAGES/django.po @@ -0,0 +1,105 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# hoseung2 , 2017 +# Gihun Ham , 2018 +# JunGu Kang , 2015 +# Kwangho Kim , 2019 +# 조민권 , 2016 +# minsung kang, 2015 +# Seoeun(Sun☀️) Hong, 2023 +# Subin Choi , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-12-04 09:22+0000\n" +"Last-Translator: Seoeun(Sun☀️) Hong, 2023\n" +"Language-Team: Korean (http://app.transifex.com/django/django/language/ko/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ko\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL 확장" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "배열 안에 있는 항목 1%(nth)s가 올바르지 않습니다:" + +msgid "Nested arrays must have the same length." +msgstr "네스팅된 배열은 반드시 같은 길이를 가져야 합니다." + +msgid "Map of strings to strings/nulls" +msgstr "문자열을 문자열/null 에 매핑" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "\"%(key)s\"의 값은 문자열 또는 널이 아닙니다." + +msgid "Could not load JSON data." +msgstr "JSON 데이터를 불러오지 못했습니다." + +msgid "Input must be a JSON dictionary." +msgstr "입력은 JSON 사전이어야만 합니다." + +msgid "Enter two valid values." +msgstr "유효한 두 값을 입력하세요." + +msgid "The start of the range must not exceed the end of the range." +msgstr "범위의 시작은 끝보다 클 수 없습니다." + +msgid "Enter two whole numbers." +msgstr "두 정수를 입력하세요." + +msgid "Enter two numbers." +msgstr "두 숫자를 입력하세요." + +msgid "Enter two valid date/times." +msgstr "올바른 날짜/시각 두 개를 입력하세요." + +msgid "Enter two valid dates." +msgstr "올바른 날짜 두 개를 입력하세요." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"리스트는 %(show_value)d 아이템들을 포함하며, %(limit_value)d를 초과해서 포함" +"할 수 없습니다." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"리스트는 %(show_value)d 아이템들을 포함하며, %(limit_value)d 이상 포함해야 합" +"니다." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "일부 키가 누락되어있습니다: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "일부 알 수 없는 키가 제공되었습니다. : %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "범위의 상한값이 %(limit_value)s보다 크지 않은지 확인하십시오." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "범위의 하한값이 %(limit_value)s보다 작지 않은지 확인하십시오." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ky/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ky/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a0edffd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ky/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ky/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ky/LC_MESSAGES/django.po new file mode 100644 index 0000000..72c0a48 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ky/LC_MESSAGES/django.po @@ -0,0 +1,100 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Soyuzbek Orozbek uulu , 2020 +# Soyuzbek Orozbek uulu , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-23 06:06+0000\n" +"Last-Translator: Soyuzbek Orozbek uulu \n" +"Language-Team: Kyrgyz (http://www.transifex.com/django/django/language/ky/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ky\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL кеңейтүүлөрү" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "%(nth)s нерсеси тизмекте туураланган эмес:" + +msgid "Nested arrays must have the same length." +msgstr "Кийишилген тизмектер окшош узундукта болуш керек." + +msgid "Map of strings to strings/nulls" +msgstr "сап -> сап\\боштук сөздүгү" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "%(key)sмааниси сап эмес же бош эмес." + +msgid "Could not load JSON data." +msgstr "JSON берилиши жүктөлбөй жатат." + +msgid "Input must be a JSON dictionary." +msgstr "Терүү JSON сөздүгү болуусу керек." + +msgid "Enter two valid values." +msgstr "Туура кош маани тер." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Чекебелдин башталышы бүтүшүн ашпоосу керек." + +msgid "Enter two whole numbers." +msgstr "Туура кош бүтүн сан тер." + +msgid "Enter two numbers." +msgstr "Кош сан тер." + +msgid "Enter two valid date/times." +msgstr "Туура кош күн\\убак тер." + +msgid "Enter two valid dates." +msgstr "Туура кош күн тер." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Тизме %(show_value)dнерсе камтыйт, бирок ал %(limit_value)dнерседен ашык " +"камтыбашы керек. " + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Тизме %(show_value)dнерсе камтыйт, бирок ал %(limit_value)dнерседен аз " +"камтыбашы керек. " + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Кээ бир ачкытарга %(keys)s жетишпе жатат" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Кээ бир белгисиз ачкычтар %(keys)s тейлейт" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "Чекебел %(limit_value)s дан ашпоосун текшериңиз." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "Чекебел жок дегенде %(limit_value)s экендигин текшериңиз." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/lt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/lt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0bd44f4 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/lt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/lt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/lt/LC_MESSAGES/django.po new file mode 100644 index 0000000..c34bd47 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/lt/LC_MESSAGES/django.po @@ -0,0 +1,120 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Matas Dailyda , 2015-2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Lithuanian (http://www.transifex.com/django/django/language/" +"lt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lt\n" +"Plural-Forms: nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < " +"11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? " +"1 : n % 1 != 0 ? 2: 3);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL plėtiniai" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "%(nth)s elementų masyve yra nevalidžių:" + +msgid "Nested arrays must have the same length." +msgstr "Iterpti vienas į kitą masyvai turi būti vienodo ilgio." + +msgid "Map of strings to strings/nulls" +msgstr "Susietos tekstinės reikšmės su tekstinėmis reikšmėmis/nulls" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "" + +msgid "Could not load JSON data." +msgstr "Nepavyko užkrauti JSON duomenų." + +msgid "Input must be a JSON dictionary." +msgstr "Įvestis turi būti JSON žodynas." + +msgid "Enter two valid values." +msgstr "Įveskite dvi tinkamas reikšmes." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Diapazono pradžia negali būti didesnė už diapazono pabaigą." + +msgid "Enter two whole numbers." +msgstr "Įveskite du sveikus skaičius." + +msgid "Enter two numbers." +msgstr "Įveskite du skaičius." + +msgid "Enter two valid date/times." +msgstr "Įveskite dvi tinkamas datas/laikus." + +msgid "Enter two valid dates." +msgstr "Įveskite dvi tinkamas datas." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Sąrašas turi %(show_value)d elementą. Sąrašas neturėtų turėti daugiau " +"elementų nei %(limit_value)d." +msgstr[1] "" +"Sąrašas turi %(show_value)d elementus. Sąrašas neturėtų turėti daugiau " +"elementų nei %(limit_value)d." +msgstr[2] "" +"Sąrašas turi %(show_value)d elementų. Sąrašas neturėtų turėti daugiau " +"elementų nei %(limit_value)d." +msgstr[3] "" +"Sąrašas turi %(show_value)d elementų. Sąrašas neturėtų turėti daugiau " +"elementų nei %(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Sąrašas turi %(show_value)d elementą. Sąrašas turėtų turėti daugiau elementų " +"nei %(limit_value)d." +msgstr[1] "" +"Sąrašas turi %(show_value)d elementus. Sąrašas turėtų turėti daugiau " +"elementų nei %(limit_value)d." +msgstr[2] "" +"Sąrašas turi %(show_value)d elementų. Sąrašas turėtų turėti daugiau elementų " +"nei %(limit_value)d." +msgstr[3] "" +"Sąrašas turi %(show_value)d elementų. Sąrašas turėtų turėti daugiau elementų " +"nei %(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Kai kurių reikšmių nėra: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Buvo pateiktos kelios nežinomos reikšmės: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "Įsitikinkite kad diapazonas yra mažesnis arba lygus %(limit_value)s." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "Įsitikinkite kad diapazonas yra didesnis arba lygus %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/lv/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/lv/LC_MESSAGES/django.mo new file mode 100644 index 0000000..14a1db4 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/lv/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/lv/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/lv/LC_MESSAGES/django.po new file mode 100644 index 0000000..ad92a4b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/lv/LC_MESSAGES/django.po @@ -0,0 +1,118 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Edgars Voroboks , 2023 +# Edgars Voroboks , 2017 +# Edgars Voroboks , 2018 +# Edgars Voroboks , 2019 +# peterisb , 2016-2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-19 09:22+0000\n" +"Last-Translator: Edgars Voroboks , 2023\n" +"Language-Team: Latvian (http://www.transifex.com/django/django/language/" +"lv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lv\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : " +"2);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL paplašinājums" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Masīva %(nth)s elements nav pareizs:" + +msgid "Nested arrays must have the same length." +msgstr "Iekļauto masīvu garumam jābūt vienādam." + +msgid "Map of strings to strings/nulls" +msgstr "Virkņu karte uz virknēm/tukšumiem" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "\"%(key)s\" vērtība nav teksta rinda vai nulles simbols." + +msgid "Could not load JSON data." +msgstr "Nevarēja ielādēt JSON datus." + +msgid "Input must be a JSON dictionary." +msgstr "Ieejošajiem datiem ir jābūt JSON vārdnīcai." + +msgid "Enter two valid values." +msgstr "Ievadi divas derīgas vērtības." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Diapazona sākums nedrīkst būt liekāks par beigām." + +msgid "Enter two whole numbers." +msgstr "Ievadiet divus veselus skaitļus." + +msgid "Enter two numbers." +msgstr "Ievadiet divus skaitļus." + +msgid "Enter two valid date/times." +msgstr "Ievadiet divus derīgus datumus/laikus." + +msgid "Enter two valid dates." +msgstr "Ievadiet divus korektus datumus." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Saraksts satur %(show_value)d ierakstus, bet tam jāsatur ne vairāk kā " +"%(limit_value)d." +msgstr[1] "" +"Saraksts satur %(show_value)d ierakstu, bet tam jāsatur ne vairāk kā " +"%(limit_value)d." +msgstr[2] "" +"Saraksts satur %(show_value)d ierakstus, bet tam jāsatur ne vairāk kā " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Saraksts satur %(show_value)d ierakstus, bet tam jāsatur vismaz " +"%(limit_value)d." +msgstr[1] "" +"Saraksts satur %(show_value)d ierakstu, bet tam jāsatur vismaz " +"%(limit_value)d." +msgstr[2] "" +"Saraksts satur %(show_value)d ierakstus, bet tam jāsatur vismaz " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Trūka dažas atslēgas: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Tika norādītas dažas nezināmas atslēgas: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "" +"Pārliecinieties, ka diapazona augšējā robeža nav lielāka par %(limit_value)s." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "" +"Pārliecinieties, ka diapazona apakšējā robeža nav mazāka par %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/mk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/mk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..30eac66 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/mk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/mk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/mk/LC_MESSAGES/django.po new file mode 100644 index 0000000..a320c46 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/mk/LC_MESSAGES/django.po @@ -0,0 +1,112 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# dekomote , 2015 +# Vasil Vangelovski , 2015-2017 +# Vasil Vangelovski , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Macedonian (http://www.transifex.com/django/django/language/" +"mk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mk\n" +"Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL eкстензии" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "" + +msgid "Nested arrays must have the same length." +msgstr "Вгнездени низи мораат да имаат иста должина." + +msgid "Map of strings to strings/nulls" +msgstr "" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "" + +msgid "Could not load JSON data." +msgstr "Не можеа да се вчитаат JSON податоци." + +msgid "Input must be a JSON dictionary." +msgstr "" + +msgid "Enter two valid values." +msgstr "Внесете две валидни вредности." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Почетокот на опсегот не смее да го надминува крајот на опсегот." + +msgid "Enter two whole numbers." +msgstr "Внесете два цели броеви." + +msgid "Enter two numbers." +msgstr "Внесете два броја." + +msgid "Enter two valid date/times." +msgstr "Внесете две валидни датуми/времиња" + +msgid "Enter two valid dates." +msgstr "Внесете два валидни датуми." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Листата соджи %(show_value)d елемент, не смее да содржи повеќе од " +"%(limit_value)d." +msgstr[1] "" +"Листата содржи %(show_value)d елементи, не треба да содржи повеќе од " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Листата содржи %(show_value)d елемент, не треба да содржи помалку од " +"%(limit_value)d." +msgstr[1] "" +"Листата содржи %(show_value)d елемент, не треба да содржи помалку од " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Некои клучеви недостигаа: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Беа дадени некои непознати клучеви: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" +"Осигурајте се дека овој опсег во целост е помал или еднаков на " +"%(limit_value)s." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "" +"Осигурајте се дека овој опсег во целост е поголем или еднаков на " +"%(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ml/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ml/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c7ae922 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ml/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ml/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ml/LC_MESSAGES/django.po new file mode 100644 index 0000000..93c6f92 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ml/LC_MESSAGES/django.po @@ -0,0 +1,98 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Hrishikesh , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-13 21:28+0000\n" +"Last-Translator: Hrishikesh \n" +"Language-Team: Malayalam (http://www.transifex.com/django/django/language/" +"ml/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ml\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL എക്സ്റ്റൻഷനുക" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "" + +msgid "Nested arrays must have the same length." +msgstr "നെസ്റ്റഡ് അറേകൾക്ക് ഒരേ ലെങ്ത്തായിരിക്കണം." + +msgid "Map of strings to strings/nulls" +msgstr "സ്ട്രിങ്ങുകളിൽ നിന്ന് സ്ട്രിങ്ങുകളിലേക്ക്/nulls ലേയ്ക്ക് ഉള്ള Map." + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "" + +msgid "Could not load JSON data." +msgstr "JSON ഡാറ്റ ലോഡുചെയ്യാനായില്ല." + +msgid "Input must be a JSON dictionary." +msgstr "ഇൻപുട്ട് നിർബന്ധമായു ഒരു JSON ഡിക്ഷ്ണറി ആയിരിക്കണം." + +msgid "Enter two valid values." +msgstr "ശരിയായ രണ്ട് വാല്യൂകൾ നൽകു" + +msgid "The start of the range must not exceed the end of the range." +msgstr "" + +msgid "Enter two whole numbers." +msgstr "രണ്ട് പൂർണ്ണസംഖ്യകൾ നൽകുക." + +msgid "Enter two numbers." +msgstr "" + +msgid "Enter two valid date/times." +msgstr "" + +msgid "Enter two valid dates." +msgstr "ശരിയായ രണ്ട് തീയതികൾ നകുക." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/mn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/mn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5f36705 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/mn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/mn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/mn/LC_MESSAGES/django.po new file mode 100644 index 0000000..326792e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/mn/LC_MESSAGES/django.po @@ -0,0 +1,111 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Zorig, 2016-2017 +# Zorig, 2019 +# Анхбаяр Анхаа , 2015 +# Баясгалан Цэвлээ , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Mongolian (http://www.transifex.com/django/django/language/" +"mn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL -ын өргөтгөлүүд" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Массивд байгаа %(nth)s буруу байна" + +msgid "Nested arrays must have the same length." +msgstr "Түүвэрлэсэн массив ижил урттай байх ёстой." + +msgid "Map of strings to strings/nulls" +msgstr "Тэмдэгтийг тэмдэгт/null руу заагч" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "" + +msgid "Could not load JSON data." +msgstr "JSON дата-г уншиж чадахгүй байна." + +msgid "Input must be a JSON dictionary." +msgstr "Оролт JSON dictionary байх ёстой." + +msgid "Enter two valid values." +msgstr "Хоёр зөв утга оруулна уу" + +msgid "The start of the range must not exceed the end of the range." +msgstr "Хүрээний эхлэл төгсгөлөөс хэтрэхгүй байх ёстой." + +msgid "Enter two whole numbers." +msgstr "Хоёр бүхэл тоон утга оруулна уу." + +msgid "Enter two numbers." +msgstr "Хоёр тоо оруулна уу." + +msgid "Enter two valid date/times." +msgstr "хоёр зөв огноо/цаг-ыг оруулна уу." + +msgid "Enter two valid dates." +msgstr "Хоёр зөв огноо оруулна уу" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Жагсаалтанд %(show_value)d зүйл байна, %(limit_value)d -ээс хэтрэхгүй байх " +"ёстой." +msgstr[1] "" +"Жагсаалтанд %(show_value)d зүйлүүд байна, %(limit_value)d -ээс хэтрэхгүй " +"байх ёстой." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Жагсаалтанд %(show_value)d зүйл байна, %(limit_value)d -ээс ихгүй байх ёстой." +msgstr[1] "" +"Жагсаалтанд %(show_value)d зүйлүүд байна, %(limit_value)d -ээс ихгүй байх " +"ёстой." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Зарим түлхүүр байхгүй байна: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Хэсэг үл мэдэгдэх түлхүүр байна: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" +"Энэ хүрээ нь %(limit_value)s -тэй бүрэн тэнцүү буюу түүнээс бага байгаа " +"эсэхийг шалгана уу" + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "" +"Энэ хүрээ нь %(limit_value)s -с их буюу тэнцүү байгаа эсэхийг шалгана уу" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ms/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ms/LC_MESSAGES/django.mo new file mode 100644 index 0000000..51c00af Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ms/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ms/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ms/LC_MESSAGES/django.po new file mode 100644 index 0000000..422eb13 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ms/LC_MESSAGES/django.po @@ -0,0 +1,100 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jafry Hisham, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2021-11-16 12:53+0000\n" +"Last-Translator: Jafry Hisham\n" +"Language-Team: Malay (http://www.transifex.com/django/django/language/ms/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ms\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "PostgreSQL extensions" +msgstr "Sambungan PoestgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "item %(nth)s didalam tatasusunan tidak disahkan:" + +msgid "Nested arrays must have the same length." +msgstr "Tatasusunan bersarang haruslah sama panjang." + +msgid "Map of strings to strings/nulls" +msgstr "Suaian rentetan ke rentetan/nulls" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Nilai \"%(key)s\" bukan rentetan atau adalah null." + +msgid "Could not load JSON data." +msgstr "Tidak dapat memuatkan data JSON." + +msgid "Input must be a JSON dictionary." +msgstr "Input mestilah dalam bentuk kamus JSON." + +msgid "Enter two valid values." +msgstr "Masukkan dua nilai yang sah." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Permulaan julat tidak boleh melebihi akhir julat." + +msgid "Enter two whole numbers." +msgstr "Masukkan dua nombor bulat." + +msgid "Enter two numbers." +msgstr "Masukkan duan nombor." + +msgid "Enter two valid date/times." +msgstr "Masukkan dua tarikh.masa yang sah." + +msgid "Enter two valid dates." +msgstr "Masukkan dua tarikh yang sah." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Senarai mempunyai %(show_value)d perkara, tetapi sepatutnya mempunyai lebih " +"daripada %(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Senarai mempunyai %(show_value)d perkara, tetapi ia sepatutnya mempunyai " +"tidak kurang daripaada %(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Sesetengah kunci hilang: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Sesetengah kunci yang diberikan tidak diketahui: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" +"Pastikan julat ini adalah kurang daripada atau sama dengan %(limit_value)s." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "Pastikan julat ini lebih daripada atau sama dengan %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/nb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/nb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a4b273a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/nb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/nb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/nb/LC_MESSAGES/django.po new file mode 100644 index 0000000..31cbb37 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/nb/LC_MESSAGES/django.po @@ -0,0 +1,107 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jon , 2015-2016 +# Jon , 2017-2018,2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Norwegian Bokmål (http://www.transifex.com/django/django/" +"language/nb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL-utvidelser" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Element %(nth)s i arrayen validerte ikke:" + +msgid "Nested arrays must have the same length." +msgstr "Nøstede arrays må ha samme lengde." + +msgid "Map of strings to strings/nulls" +msgstr "Oversikt over strenger til strenger/nulls" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Verdien av \"%(key)s\" er ikke en streng eller null." + +msgid "Could not load JSON data." +msgstr "Kunne ikke laste JSON-data." + +msgid "Input must be a JSON dictionary." +msgstr "Input må være en JSON-dictionary." + +msgid "Enter two valid values." +msgstr "Oppgi to gyldige verdier." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Starten på serien må ikke overstige enden av serien." + +msgid "Enter two whole numbers." +msgstr "Oppgi to heltall." + +msgid "Enter two numbers." +msgstr "Oppgi to tall." + +msgid "Enter two valid date/times." +msgstr "Oppgi to gyldige datoer og tidspunkter." + +msgid "Enter two valid dates." +msgstr "Oppgi to gyldige datoer." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Listen inneholder %(show_value)d element, den bør ikke inneholde mer enn " +"%(limit_value)d." +msgstr[1] "" +"Listen inneholder %(show_value)d elementer, den bør ikke inneholde mer enn " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Listen inneholder %(show_value)d element, den bør ikke inneholde færre enn " +"%(limit_value)d." +msgstr[1] "" +"Listen inneholder %(show_value)d elementer, den bør ikke inneholde færre enn " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Noen nøkler manglet: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Noen ukjente nøkler ble oppgitt: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "Sørg for at denne serien er helt mindre enn eller lik %(limit_value)s." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "Sørg for at denne serien er helt større enn eller lik %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ne/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ne/LC_MESSAGES/django.mo new file mode 100644 index 0000000..311ab17 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ne/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ne/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ne/LC_MESSAGES/django.po new file mode 100644 index 0000000..3ee263d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ne/LC_MESSAGES/django.po @@ -0,0 +1,96 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Nepali (http://www.transifex.com/django/django/language/ne/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ne\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "" + +msgid "Nested arrays must have the same length." +msgstr "" + +msgid "Map of strings to strings/nulls" +msgstr "" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "" + +msgid "Could not load JSON data." +msgstr "" + +msgid "Input must be a JSON dictionary." +msgstr "" + +msgid "Enter two valid values." +msgstr "दुई उपयुक्त मान राख्नु होस ।" + +msgid "The start of the range must not exceed the end of the range." +msgstr "" + +msgid "Enter two whole numbers." +msgstr "" + +msgid "Enter two numbers." +msgstr "दुई अङ्क राख्नु होस ।" + +msgid "Enter two valid date/times." +msgstr "दुई उपयुक्त मिति/समय राख्नु होस ।" + +msgid "Enter two valid dates." +msgstr "दुई उपयुक्त मिति राख्नु होस ।" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/nl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/nl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..61c3a25 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/nl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/nl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/nl/LC_MESSAGES/django.po new file mode 100644 index 0000000..e1fcfc2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/nl/LC_MESSAGES/django.po @@ -0,0 +1,112 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Evelijn Saaltink , 2016 +# Ilja Maas , 2015 +# 8de006b1b0894aab6aef71979dcd8bd6_5c6b207 , 2015 +# Tonnes , 2017,2019,2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-12-04 09:22+0000\n" +"Last-Translator: Tonnes , 2017,2019,2023\n" +"Language-Team: Dutch (http://app.transifex.com/django/django/language/nl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL-extensies" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Item %(nth)s in de matrix is niet gevalideerd:" + +msgid "Nested arrays must have the same length." +msgstr "Geneste matrices moeten dezelfde lengte hebben." + +msgid "Map of strings to strings/nulls" +msgstr "Toewijzing van tekenreeksen naar tekenreeksen/nulwaarden" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "De waarde van ‘%(key)s’ is geen tekenreeks of nul." + +msgid "Could not load JSON data." +msgstr "Kon JSON-gegevens niet laden." + +msgid "Input must be a JSON dictionary." +msgstr "Invoer moet een JSON-bibliotheek zijn." + +msgid "Enter two valid values." +msgstr "Voer twee geldige waarden in." + +msgid "The start of the range must not exceed the end of the range." +msgstr "" +"Het begin van het bereik mag niet groter zijn dan het einde van het bereik." + +msgid "Enter two whole numbers." +msgstr "Voer twee gehele getallen in." + +msgid "Enter two numbers." +msgstr "Voer twee getallen in." + +msgid "Enter two valid date/times." +msgstr "Voer twee geldige datums/tijden in." + +msgid "Enter two valid dates." +msgstr "Voer twee geldige datums in." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Lijst bevat %(show_value)d element, maar mag niet meer dan %(limit_value)d " +"elementen bevatten." +msgstr[1] "" +"Lijst bevat %(show_value)d elementen, maar mag niet meer dan %(limit_value)d " +"elementen bevatten." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Lijst bevat %(show_value)d element, maar mag niet minder dan %(limit_value)d " +"elementen bevatten." +msgstr[1] "" +"Lijst bevat %(show_value)d elementen, maar mag niet minder dan " +"%(limit_value)d elementen bevatten." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Sommige sleutels ontbreken: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Er zijn enkele onbekende sleutels opgegeven: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "" +"Zorg ervoor dat de bovengrens van het bereik niet hoger is dan " +"%(limit_value)s." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "" +"Zorg ervoor dat de ondergrens van het bereik niet lager is dan " +"%(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/nn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/nn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..52ea3d1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/nn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/nn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/nn/LC_MESSAGES/django.po new file mode 100644 index 0000000..aff9967 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/nn/LC_MESSAGES/django.po @@ -0,0 +1,106 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Sivert Olstad, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2021-11-16 22:21+0000\n" +"Last-Translator: Sivert Olstad\n" +"Language-Team: Norwegian Nynorsk (http://www.transifex.com/django/django/" +"language/nn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL-utvidingar" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Element %(nth)s i arrayen validerte ikkje:" + +msgid "Nested arrays must have the same length." +msgstr "Nysta arrayar må ha same lengde." + +msgid "Map of strings to strings/nulls" +msgstr "Oversyn over strenger til strenger/nulls" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Verdien til “%(key)s” er ikkje ein streng eller null." + +msgid "Could not load JSON data." +msgstr "Kunne ikkje laste JSON-data." + +msgid "Input must be a JSON dictionary." +msgstr "Inndata må vere ein JSON-dictionary." + +msgid "Enter two valid values." +msgstr "Oppgje to gyldige verdiar." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Starten på serien må ikkje overstige enden av serien." + +msgid "Enter two whole numbers." +msgstr "Oppgje to heiltal." + +msgid "Enter two numbers." +msgstr "Oppgje to tal." + +msgid "Enter two valid date/times." +msgstr "Oppgje to gyldige datoar/tidspunkt." + +msgid "Enter two valid dates." +msgstr "Oppgje to gyldige datoar." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Lista inneheld %(show_value)d element, den bør ikkje innehalde fleire enn " +"%(limit_value)d." +msgstr[1] "" +"Lista inneheld %(show_value)d element, den bør ikkje innehalde fleire enn " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Lista inneheld %(show_value)d element, den bør ikkje innehalde færre enn " +"%(limit_value)d." +msgstr[1] "" +"Lista inneheld %(show_value)d element, den bør ikkje innehalde færre enn " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Nokon nyklar mangla: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Nokon ukjende nyklar vart oppgjeve: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "Syrg for at serien er heilt mindre enn eller lik %(limit_value)s." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "Syrg for at serien er heilt større enn eller lik %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/pl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/pl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0a096ee Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/pl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/pl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/pl/LC_MESSAGES/django.po new file mode 100644 index 0000000..eb0c401 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/pl/LC_MESSAGES/django.po @@ -0,0 +1,127 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Dariusz Paluch , 2015 +# Janusz Harkot , 2015 +# Piotr Jakimiak , 2015 +# lobsterick , 2019 +# Maciej Olko , 2016-2019 +# Maciej Olko , 2023 +# Maciej Olko , 2015 +# Tomasz Kajtoch , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-19 09:22+0000\n" +"Last-Translator: Maciej Olko , 2023\n" +"Language-Team: Polish (http://www.transifex.com/django/django/language/pl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pl\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && " +"(n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && " +"n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" + +msgid "PostgreSQL extensions" +msgstr "Rozszerzenia PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Element %(nth)s w tablicy nie przeszedł walidacji:" + +msgid "Nested arrays must have the same length." +msgstr "Zagnieżdżone tablice muszą mieć tę samą długość." + +msgid "Map of strings to strings/nulls" +msgstr "Mapowanie ciągów znaków na ciągi znaków/nulle" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Wartość „%(key)s” nie jest ciągiem znaków ani nullem." + +msgid "Could not load JSON data." +msgstr "Nie można załadować danych JSON." + +msgid "Input must be a JSON dictionary." +msgstr "Wejście musi być słownikiem JSON." + +msgid "Enter two valid values." +msgstr "Podaj dwie poprawne wartości." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Początek zakresu nie może przekroczyć jego końca." + +msgid "Enter two whole numbers." +msgstr "Podaj dwie liczby całkowite." + +msgid "Enter two numbers." +msgstr "Podaj dwie liczby." + +msgid "Enter two valid date/times." +msgstr "Podaj dwie poprawne daty/godziny." + +msgid "Enter two valid dates." +msgstr "Podaj dwie poprawne daty." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Lista zawiera %(show_value)d element, a nie powinna zawierać więcej niż " +"%(limit_value)d." +msgstr[1] "" +"Lista zawiera %(show_value)d elementów, a nie powinna zawierać więcej niż " +"%(limit_value)d." +msgstr[2] "" +"Lista zawiera %(show_value)d elementów, a nie powinna zawierać więcej niż " +"%(limit_value)d." +msgstr[3] "" +"Lista zawiera %(show_value)d elementów, a nie powinna zawierać więcej niż " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Lista zawiera %(show_value)d element, a powinna zawierać nie mniej niż " +"%(limit_value)d." +msgstr[1] "" +"Lista zawiera %(show_value)d elementów, a powinna zawierać nie mniej niż " +"%(limit_value)d." +msgstr[2] "" +"Lista zawiera %(show_value)d elementów, a powinna zawierać nie mniej niż " +"%(limit_value)d." +msgstr[3] "" +"Lista zawiera %(show_value)d elementów, a powinna zawierać nie mniej niż " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Brak części kluczy: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Podano nieznane klucze: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "" +"Upewnij się, że górna granica zakresu nie jest większa niż %(limit_value)s." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "" +"Upewnij się, że dolna granica zakresu nie jest mniejsza niż %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/pt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/pt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7f6ed0d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/pt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/pt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/pt/LC_MESSAGES/django.po new file mode 100644 index 0000000..fce5ed8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/pt/LC_MESSAGES/django.po @@ -0,0 +1,107 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Claudio Fernandes , 2015 +# jorgecarleitao , 2015 +# Nuno Mariz , 2015,2017-2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Portuguese (http://www.transifex.com/django/django/language/" +"pt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "Extensões de PostgresSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Item %(nth)s na lista não validou:" + +msgid "Nested arrays must have the same length." +msgstr "As sub-listas têm de ter o mesmo tamanho." + +msgid "Map of strings to strings/nulls" +msgstr "Mapeamento de strings para strings/nulos" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "" + +msgid "Could not load JSON data." +msgstr "Não foi possível carregar os dados JSON." + +msgid "Input must be a JSON dictionary." +msgstr "A entrada deve ser um dicionário JSON." + +msgid "Enter two valid values." +msgstr "Introduza dois valores válidos." + +msgid "The start of the range must not exceed the end of the range." +msgstr "O início da gama não pode ser maior que o seu fim." + +msgid "Enter two whole numbers." +msgstr "Introduza dois números inteiros." + +msgid "Enter two numbers." +msgstr "Introduza dois números." + +msgid "Enter two valid date/times." +msgstr "Introduza duas datas/horas válidas." + +msgid "Enter two valid dates." +msgstr "Introduza duas datas válidas." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"A lista contém %(show_value)d item, não pode conter mais do que " +"%(limit_value)d." +msgstr[1] "" +"A lista contém %(show_value)d itens, não pode conter mais do que " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"A lista contém %(show_value)d item, tem de conter pelo menos %(limit_value)d." +msgstr[1] "" +"A lista contém %(show_value)d itens, tem de conter pelo menos " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Algumas chaves estão em falta: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Foram fornecidas algumas chaves desconhecidas: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "Garanta que esta gama é toda ela menor ou igual a %(limit_value)s." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "Garanta que esta gama é toda ela maior ou igual a %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/pt_BR/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/pt_BR/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3c39f56 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/pt_BR/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/pt_BR/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/pt_BR/LC_MESSAGES/django.po new file mode 100644 index 0000000..7b1b3a4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/pt_BR/LC_MESSAGES/django.po @@ -0,0 +1,123 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Andre Machado , 2016 +# Carlos C. Leite , 2016,2019 +# Claudemiro Alves Feitosa Neto , 2015 +# Fábio C. Barrionuevo da Luz , 2015 +# Jonas Rodrigues, 2023 +# Lucas Infante , 2015 +# Luiz Boaretto , 2017 +# Marcelo Moro Brondani , 2018 +# Rafael Ribeiro , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-19 09:22+0000\n" +"Last-Translator: Jonas Rodrigues, 2023\n" +"Language-Team: Portuguese (Brazil) (http://www.transifex.com/django/django/" +"language/pt_BR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt_BR\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "PostgreSQL extensions" +msgstr "Extensões para PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "O item %(nth)s na matriz não validou:" + +msgid "Nested arrays must have the same length." +msgstr "Matrizes aninhadas devem ter o mesmo comprimento." + +msgid "Map of strings to strings/nulls" +msgstr "Mapa de strings para strings/nulls" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "O valor da “%(key)s” não é string ou null." + +msgid "Could not load JSON data." +msgstr "Não foi possível carregar dados JSON." + +msgid "Input must be a JSON dictionary." +msgstr "Input deve ser um dicionário JSON" + +msgid "Enter two valid values." +msgstr "Insira dois valores válidos." + +msgid "The start of the range must not exceed the end of the range." +msgstr "O inicio do intervalo não deve exceder o fim do intervalo." + +msgid "Enter two whole numbers." +msgstr "Insira dois números cheios." + +msgid "Enter two numbers." +msgstr "Insira dois números" + +msgid "Enter two valid date/times." +msgstr "Insira duas datas/horas válidas." + +msgid "Enter two valid dates." +msgstr "Insira duas datas válidas." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"A lista contém um item %(show_value)d, não deveria conter mais que " +"%(limit_value)d." +msgstr[1] "" +"A lista contém itens %(show_value)d, não deveria conter mais que " +"%(limit_value)d." +msgstr[2] "" +"A lista contém itens %(show_value)d, não deveria conter mais que " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"A lista contém um item %(show_value)d, deveria conter não menos que " +"%(limit_value)d." +msgstr[1] "" +"A lista contém %(show_value)d itens, deveria conter não menos que " +"%(limit_value)d." +msgstr[2] "" +"A lista contém %(show_value)d itens, deveria conter não menos que " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Algumas chaves estavam faltando: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Algumas chaves desconhecidas foram fornecidos: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "" +"Certifique-se de que o limite superior do intervalo não seja maior que " +"%(limit_value)s." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "" +"Assegure-se de que o limite inferior do intervalo não seja menor que " +"%(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ro/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ro/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0c34adb Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ro/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ro/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ro/LC_MESSAGES/django.po new file mode 100644 index 0000000..ae8e69d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ro/LC_MESSAGES/django.po @@ -0,0 +1,120 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bogdan Mateescu, 2018 +# Eugenol Man , 2020 +# Razvan Stefanescu , 2015,2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-07-06 17:14+0000\n" +"Last-Translator: Eugenol Man \n" +"Language-Team: Romanian (http://www.transifex.com/django/django/language/" +"ro/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ro\n" +"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?" +"2:1));\n" + +msgid "PostgreSQL extensions" +msgstr "Extensiile PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Elementul %(nth)s din mulțime nu s-a validat:" + +msgid "Nested arrays must have the same length." +msgstr "Vectorii imbricați trebuie să aibă aceeași lungime." + +msgid "Map of strings to strings/nulls" +msgstr "Asociere de șiruri de caractere cu șiruri de caractere/null." + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Valoarea “%(key)s” nu este un sir sau zero." + +msgid "Could not load JSON data." +msgstr "Nu am putut încărca datele JSON." + +msgid "Input must be a JSON dictionary." +msgstr "Intrarea trebuie să fie un dicționar JSON valid." + +msgid "Enter two valid values." +msgstr "Introdu două valori valide." + +msgid "The start of the range must not exceed the end of the range." +msgstr "" +"Începutul intervalului nu trebuie să depășească sfârșitul intervalului." + +msgid "Enter two whole numbers." +msgstr "Introdu două numere întregi." + +msgid "Enter two numbers." +msgstr "Introdu două numere." + +msgid "Enter two valid date/times." +msgstr "Introdu două date / ore valide." + +msgid "Enter two valid dates." +msgstr "Introdu două date valide." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Lista conține %(show_value)d, nu ar trebui să conțină mai mult de " +"%(limit_value)d." +msgstr[1] "" +"Lista conține %(show_value)d, nu ar trebui să conțină mai mult de " +"%(limit_value)d." +msgstr[2] "" +"Lista conține %(show_value)d, nu ar trebui să conțină mai mult de " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Lista conține %(show_value)d, nu ar trebui să conțină mai puțin de " +"%(limit_value)d." +msgstr[1] "" +"Lista conține %(show_value)d, nu ar trebui să conțină mai puțin de " +"%(limit_value)d." +msgstr[2] "" +"Lista conține %(show_value)d, nu ar trebui să conțină mai puțin de " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Unele chei lipsesc: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Au fost furnizate chei necunoscute: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" +"Asigură-te că intervalul este în întregime mai mic sau egal cu " +"%(limit_value)s." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "" +"Asigură-te că intervalul este în întregime mai mare sau egal cu " +"%(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ru/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ru/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e74abd1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ru/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ru/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ru/LC_MESSAGES/django.po new file mode 100644 index 0000000..bc5bf33 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ru/LC_MESSAGES/django.po @@ -0,0 +1,131 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Eugene , 2016 +# eXtractor , 2015 +# crazyzubr , 2020 +# Kirill Gagarski , 2015 +# Вася Аникин , 2017 +# Алексей Борискин , 2015-2018,2023 +# Bobsans , 2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-12-04 09:22+0000\n" +"Last-Translator: Алексей Борискин , 2015-2018,2023\n" +"Language-Team: Russian (http://app.transifex.com/django/django/language/" +"ru/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ru\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || " +"(n%100>=11 && n%100<=14)? 2 : 3);\n" + +msgid "PostgreSQL extensions" +msgstr "Расширения PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Элемент %(nth)s в массиве не прошёл проверку:" + +msgid "Nested arrays must have the same length." +msgstr "Вложенные массивы должны иметь одинаковую длину." + +msgid "Map of strings to strings/nulls" +msgstr "" +"Ассоциативный массив со строковыми ключами и строковыми или отсутствующими " +"значениями." + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Значение “%(key)s” не является строкой или null." + +msgid "Could not load JSON data." +msgstr "Не удалось загрузить JSON-данные." + +msgid "Input must be a JSON dictionary." +msgstr "Значение должно быть JSON-словарём." + +msgid "Enter two valid values." +msgstr "Введите два правильных значения." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Начало диапазона не может превышать его предел." + +msgid "Enter two whole numbers." +msgstr "Введите два целых числа." + +msgid "Enter two numbers." +msgstr "Введите два числа." + +msgid "Enter two valid date/times." +msgstr "Введите две правильные даты со временем." + +msgid "Enter two valid dates." +msgstr "Введите две правильные даты." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Список содержит %(show_value)d элемент, однако количество элементов не " +"должно превышать %(limit_value)d." +msgstr[1] "" +"Список содержит %(show_value)d элемента, однако количество элементов не " +"должно превышать %(limit_value)d." +msgstr[2] "" +"Список содержит %(show_value)d элементов, однако количество элементов не " +"должно превышать %(limit_value)d." +msgstr[3] "" +"Список содержит %(show_value)d элементов, однако количество элементов не " +"должно превышать %(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Список содержит %(show_value)d элемент, однако количество элементов должно " +"быть не меньше %(limit_value)d." +msgstr[1] "" +"Список содержит %(show_value)d элемента, однако количество элементов должно " +"быть не меньше %(limit_value)d." +msgstr[2] "" +"Список содержит %(show_value)d элементов, однако количество элементов должно " +"быть не меньше %(limit_value)d." +msgstr[3] "" +"Список содержит %(show_value)d элементов, однако количество элементов должно " +"быть не меньше %(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Некоторые ключи пропущены: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "" +"Некоторые из предоставленных ключей не входят в список известных ключей: " +"%(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "" +"Убедитесь, что верхняя граница диапазона не больше, чем %(limit_value)s." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "" +"Убедитесь, что нижняя граница диапазона не меньше, чем %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..bad5729 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sk/LC_MESSAGES/django.po new file mode 100644 index 0000000..b9f5d4c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sk/LC_MESSAGES/django.po @@ -0,0 +1,121 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Adam Zahradník, 2023 +# Martin Tóth , 2017-2018,2023 +# Peter Stríž , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-12-04 09:22+0000\n" +"Last-Translator: Martin Tóth , 2017-2018,2023\n" +"Language-Team: Slovak (http://app.transifex.com/django/django/language/sk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n " +">= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL rozšírenia" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "%(nth)s. položka poľa je neplatná:" + +msgid "Nested arrays must have the same length." +msgstr "Vnorené polia musia mať rovnakú dĺžku." + +msgid "Map of strings to strings/nulls" +msgstr "Mapovanie reťazcov na reťazce/NULL" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Hodnota s kľúčom „%(key)s“ nie je reťazec ani NULL." + +msgid "Could not load JSON data." +msgstr "Údaje typu JSON sa nepodarilo načítať." + +msgid "Input must be a JSON dictionary." +msgstr "Vstup musí byť slovník vo formáte JSON." + +msgid "Enter two valid values." +msgstr "Zadajte dve platné hodnoty." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Začiatočná hodnota rozsahu nesmie býť vyššia ako koncová hodnota." + +msgid "Enter two whole numbers." +msgstr "Zadajte dve celé čísla." + +msgid "Enter two numbers." +msgstr "Zadajte dve čísla." + +msgid "Enter two valid date/times." +msgstr "Zadajte dva platné dátumy/časy." + +msgid "Enter two valid dates." +msgstr "Zadajte dva platné dátumy." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Zoznam obsahuje %(show_value)d položku, ale nemal by obsahovať viac ako " +"%(limit_value)d." +msgstr[1] "" +"Zoznam obsahuje %(show_value)d položku, ale nemal by obsahovať viac ako " +"%(limit_value)d." +msgstr[2] "" +"Zoznam obsahuje %(show_value)d položku, ale nemal by obsahovať viac ako " +"%(limit_value)d." +msgstr[3] "" +"Zoznam obsahuje %(show_value)d položku, ale nemal by obsahovať viac ako " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Zoznam obsahuje %(show_value)d položku, ale nemal by obsahovať menej ako " +"%(limit_value)d." +msgstr[1] "" +"Zoznam obsahuje %(show_value)d položku, ale nemal by obsahovať menej ako " +"%(limit_value)d." +msgstr[2] "" +"Zoznam obsahuje %(show_value)d položku, ale nemal by obsahovať menej ako " +"%(limit_value)d." +msgstr[3] "" +"Zoznam obsahuje %(show_value)d položku, ale nemal by obsahovať menej ako " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Niektoré kľúče chýbajú: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Boli zadané neznáme kľúče: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "" +"Uistite sa, že horná hranica rozsahu nie je väčšia ako %(limit_value)s." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "" +"Uistite sa, že dolná hranica rozsahu nie je menšia ako %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..47a41df Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sl/LC_MESSAGES/django.po new file mode 100644 index 0000000..b79c39a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sl/LC_MESSAGES/django.po @@ -0,0 +1,120 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Andrej Marsetič, 2022 +# Primoz Verdnik , 2017 +# zejn , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-19 09:22+0000\n" +"Last-Translator: Andrej Marsetič, 2022\n" +"Language-Team: Slovenian (http://www.transifex.com/django/django/language/" +"sl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sl\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || " +"n%100==4 ? 2 : 3);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL razširitve" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "" + +msgid "Nested arrays must have the same length." +msgstr "Gnezdeni seznami morajo imeti enako dolžino." + +msgid "Map of strings to strings/nulls" +msgstr "Preslikava nizev v nize/null" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Vrednost \"%(key)s\" ni niz ali ničelna vrednost." + +msgid "Could not load JSON data." +msgstr "Ni bilo mogoče naložiti JSON podatkov." + +msgid "Input must be a JSON dictionary." +msgstr "Vhodni podatek mora biti JSON objekt." + +msgid "Enter two valid values." +msgstr "Vnesite dve veljavni vrednosti." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Začetek območja mora biti po vrednosti manjši od konca območja." + +msgid "Enter two whole numbers." +msgstr "Vnesite dve celi števili." + +msgid "Enter two numbers." +msgstr "Vnesite dve števili." + +msgid "Enter two valid date/times." +msgstr "Vnesite dva veljavna datuma oz. točki v času." + +msgid "Enter two valid dates." +msgstr "Vnesite dva veljavna datuma." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Seznam vsebuje %(show_value)d element, moral pa bi jih imeti največ " +"%(limit_value)d." +msgstr[1] "" +"Seznam vsebuje %(show_value)d elementa, moral pa bi jih imeti največ " +"%(limit_value)d." +msgstr[2] "" +"Seznam vsebuje %(show_value)d elemente, moral pa bi jih imeti največ " +"%(limit_value)d." +msgstr[3] "" +"Seznam vsebuje %(show_value)d elementov, moral pa bi jih imeti največ " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Seznam vsebuje %(show_value)d element, moral pa bi jih najmanj " +"%(limit_value)d." +msgstr[1] "" +"Seznam vsebuje %(show_value)d elementa, moral pa bi jih najmanj " +"%(limit_value)d." +msgstr[2] "" +"Seznam vsebuje %(show_value)d elemente, moral pa bi jih najmanj " +"%(limit_value)d." +msgstr[3] "" +"Seznam vsebuje %(show_value)d elementov, moral pa bi jih najmanj " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Nekateri ključi manjkajo: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Navedeni so bili nekateri neznani ključi: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sq/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sq/LC_MESSAGES/django.mo new file mode 100644 index 0000000..898fc03 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sq/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sq/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sq/LC_MESSAGES/django.po new file mode 100644 index 0000000..cb77307 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sq/LC_MESSAGES/django.po @@ -0,0 +1,110 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Besnik Bleta , 2023 +# Besnik Bleta , 2017-2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-19 09:22+0000\n" +"Last-Translator: Besnik Bleta , 2023\n" +"Language-Team: Albanian (http://www.transifex.com/django/django/language/" +"sq/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sq\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "Zgjerime PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Objekti %(nth)s te vargu nuk u vleftësua:" + +msgid "Nested arrays must have the same length." +msgstr "Vargjet brenda vargjesh duhet të kenë të njëjtën gjatësi." + +msgid "Map of strings to strings/nulls" +msgstr "Hartë vargjesh te strings/nulls" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Vlera e “%(key)s” s’është varg ose nul." + +msgid "Could not load JSON data." +msgstr "S’u ngarkuan dot të dhëna JSON." + +msgid "Input must be a JSON dictionary." +msgstr "Vlera duhet të jetë një fjalor JSON." + +msgid "Enter two valid values." +msgstr "Jepni dy vlera të vlefshme." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Fillimi i një intervali s’duhet të tejkalojë fundin e një intervali." + +msgid "Enter two whole numbers." +msgstr "Jepni dy vlera të plota numrash." + +msgid "Enter two numbers." +msgstr "Jepni dy numra." + +msgid "Enter two valid date/times." +msgstr "Jepni dy data/kohë të vlefshme." + +msgid "Enter two valid dates." +msgstr "Jepni dy data të vlefshme." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Lista përmban %(show_value)d element, duhet të përmbajë jo më shumë se " +"%(limit_value)d." +msgstr[1] "" +"Lista përmban %(show_value)d elementë, duhet të përmbajë jo më shumë se " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Lista përmban %(show_value)d element, duhet të përmbajë jo më pak " +"%(limit_value)d." +msgstr[1] "" +"Lista përmban %(show_value)d elementë, duhet të përmbajë jo më pak " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Mungojnë ca kyçe: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Janë dhënë kyçe të panjohur: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "" +"Garantoni që kufiri i sipërm i intervalit të mos jetë më i madh se " +"%(limit_value)s." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "" +"Garantoni që kufiri i poshtëm i intervalit të mos jetë më i vogël se " +"%(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7d12ac8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sr/LC_MESSAGES/django.po new file mode 100644 index 0000000..b7d796c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sr/LC_MESSAGES/django.po @@ -0,0 +1,113 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Branko Kokanovic , 2018 +# Igor Jerosimić, 2020,2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-19 09:22+0000\n" +"Last-Translator: Igor Jerosimić, 2020,2023\n" +"Language-Team: Serbian (http://www.transifex.com/django/django/language/" +"sr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL екстензије" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Ставка %(nth)s у низу није валидирана:" + +msgid "Nested arrays must have the same length." +msgstr "Угњеждени низови морају да буду исте дужине." + +msgid "Map of strings to strings/nulls" +msgstr "Мапа знаковних ниски на знаковне ниске/null-ове" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Вредност “%(key)s” није знаковни низ или null." + +msgid "Could not load JSON data." +msgstr "Не могу да учитам JSON податке." + +msgid "Input must be a JSON dictionary." +msgstr "Улазна вредност мора бити JSON dict." + +msgid "Enter two valid values." +msgstr "Унесите две исправне вредности." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Почетак опсега не може бити преко краја опсега." + +msgid "Enter two whole numbers." +msgstr "Унесите два цела броја." + +msgid "Enter two numbers." +msgstr "Унесите два броја." + +msgid "Enter two valid date/times." +msgstr "Унесите два исправна датума/времена." + +msgid "Enter two valid dates." +msgstr "Унесите два исправна датума." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Листа садржи %(show_value)dставку, не би требало да садржи више од " +"%(limit_value)d." +msgstr[1] "" +"Листа садржи %(show_value)d ставке, не би требало да садржи више од " +"%(limit_value)d." +msgstr[2] "" +"Листа садржи %(show_value)d ставки, не би требало да садржи више од " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Листа садржи %(show_value)d ставку, не би требало да садржи мање од " +"%(limit_value)d." +msgstr[1] "" +"Листа садржи %(show_value)d ставке, не би требало да садржи мање од " +"%(limit_value)d." +msgstr[2] "" +"Листа садржи %(show_value)d ставки, не би требало да садржи мање од " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Неки кључеви недостају: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Дати су неки непознати кључеви: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "Осигурајте да горња граница опсега није већа од %(limit_value)s." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "Осигурајте да доња граница опсега није мања од %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sr_Latn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sr_Latn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..74a26e3 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sr_Latn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sr_Latn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sr_Latn/LC_MESSAGES/django.po new file mode 100644 index 0000000..ce65e27 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sr_Latn/LC_MESSAGES/django.po @@ -0,0 +1,112 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Igor Jerosimić, 2019-2020,2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-19 09:22+0000\n" +"Last-Translator: Igor Jerosimić, 2019-2020,2023\n" +"Language-Team: Serbian (Latin) (http://www.transifex.com/django/django/" +"language/sr@latin/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr@latin\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL ekstenzije" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Stavka %(nth)su nizu nije ispravna:" + +msgid "Nested arrays must have the same length." +msgstr "Ugnježdeni nizovi moraju da budu iste dužine." + +msgid "Map of strings to strings/nulls" +msgstr "Mapa znakovnih niski na znakovne niske/null-ove" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Vrednost \"%(key)s\" nije znakovni niz ili null." + +msgid "Could not load JSON data." +msgstr "Ne mogu da učitam JSON podatke." + +msgid "Input must be a JSON dictionary." +msgstr "Ulazna vrednost mora biti JSON dict." + +msgid "Enter two valid values." +msgstr "Unesite dve ispravne vrednosti." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Početak opsega ne može biti preko kraja opsega." + +msgid "Enter two whole numbers." +msgstr "Unesite dva cela broja." + +msgid "Enter two numbers." +msgstr "Unesite dva broja." + +msgid "Enter two valid date/times." +msgstr "Unesite dva ispravna datuma/vremena." + +msgid "Enter two valid dates." +msgstr "Unesite dva ispravna datuma." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Lista sadrži %(show_value)dstavku, ne bi trebalo da sadrži više od " +"%(limit_value)d." +msgstr[1] "" +"Lista sadrži %(show_value)dstavke, ne bi trebalo da sadrži više od " +"%(limit_value)d." +msgstr[2] "" +"Lista sadrži %(show_value)dstavki, ne bi trebalo da sadrži više od " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Lista sadrži %(show_value)dstavku, ne bi trebalo da sadrži manje od " +"%(limit_value)d." +msgstr[1] "" +"Lista sadrži %(show_value)dstavke, ne bi trebalo da sadrži manje od " +"%(limit_value)d." +msgstr[2] "" +"Lista sadrži %(show_value)dstavki, ne bi trebalo da sadrži manje od " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Neki ključevi nedostaju: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Dati su neki nepoznati ključevi: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "Osigurajte da gornja granica opsega nije veća od %(limit_value)s." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "Osigurajte da donja granica opsega nije manja od %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sv/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sv/LC_MESSAGES/django.mo new file mode 100644 index 0000000..725396d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sv/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sv/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sv/LC_MESSAGES/django.po new file mode 100644 index 0000000..a6cc037 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/sv/LC_MESSAGES/django.po @@ -0,0 +1,110 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Anders Hovmöller , 2023 +# Elias Johnstone , 2022 +# Gustaf Hansen , 2015 +# Jonathan Lindén, 2015 +# Petter Strandmark , 2019 +# Thomas Lundqvist, 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-19 09:22+0000\n" +"Last-Translator: Anders Hovmöller , 2023\n" +"Language-Team: Swedish (http://www.transifex.com/django/django/language/" +"sv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sv\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL-tillägg" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Element %(nth)s i arrayen gick inte att validera:" + +msgid "Nested arrays must have the same length." +msgstr "Flerdimensionella arrayer måste vara av samma längd" + +msgid "Map of strings to strings/nulls" +msgstr "Funktion från sträng till sträng/null" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Värdet av “%(key)s” är inte en sträng eller null." + +msgid "Could not load JSON data." +msgstr "Kunde inte ladda JSON-data." + +msgid "Input must be a JSON dictionary." +msgstr "Input måste vara en JSON-dictionary." + +msgid "Enter two valid values." +msgstr "Fyll i två giltiga värden" + +msgid "The start of the range must not exceed the end of the range." +msgstr "Starten av intervallet kan inte vara större än slutet av intervallet." + +msgid "Enter two whole numbers." +msgstr "Fyll i två heltal." + +msgid "Enter two numbers." +msgstr "Fyll i två tal." + +msgid "Enter two valid date/times." +msgstr "Fyll i två giltiga datum/tider." + +msgid "Enter two valid dates." +msgstr "Fyll i två giltiga datum." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Listan innehåller %(show_value)d objekt, men kan inte innehålla fler än " +"%(limit_value)d." +msgstr[1] "" +"Listan innehåller %(show_value)d objekt, men kan inte innehålla fler än " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Listan innehåller %(show_value)d objekt, men kan inte innehålla färre än " +"%(limit_value)d." +msgstr[1] "" +"Listan innehåller %(show_value)d objekt, men kan inte innehålla färre än " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Några nycklar saknades: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Några okända okända nycklar skickades: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "Säkerställ att den övre gränsen inte överstiger %(limit_value)s." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "Säkerställ att den undre gränsen inte understiger %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/tg/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/tg/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2e69e93 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/tg/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/tg/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/tg/LC_MESSAGES/django.po new file mode 100644 index 0000000..fffabf5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/tg/LC_MESSAGES/django.po @@ -0,0 +1,101 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Surush Sufiew , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-15 00:32+0000\n" +"Last-Translator: Surush Sufiew \n" +"Language-Team: Tajik (http://www.transifex.com/django/django/language/tg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "Расширения PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Элементи %(nth)s -и массив санҷишро нагузашт:" + +msgid "Nested arrays must have the same length." +msgstr "Массивҳои воридкардашуда бояд дарозиҳои якхела дошта бошанд." + +msgid "Map of strings to strings/nulls" +msgstr "Массивҳои strings ба strings/nulls" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "" + +msgid "Could not load JSON data." +msgstr "Боркунии JSON-додаҳо муяссар нашуд." + +msgid "Input must be a JSON dictionary." +msgstr "Қимматҳо бояд дар шакли JSON-луғатҳо ворид карда шаванд." + +msgid "Enter two valid values." +msgstr "Дуто қимати дуруст ворид созед." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Оғози фосила наметавонад қимати аз ҳудуди худ калонро қабул кунад." + +msgid "Enter two whole numbers." +msgstr "Дуто адади яклухтро ворид созед." + +msgid "Enter two numbers." +msgstr "Ду ададро ворид созед." + +msgid "Enter two valid date/times." +msgstr "Санаро бо вақт дуруст ворид кунед." + +msgid "Enter two valid dates." +msgstr "Дуто санаи дурустро ворид созед." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +msgstr[1] "" + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Баъзе аз калидҳо истисно карда шудаанд: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "" +"Баъзе аз калидҳои овардашуда ба руйхати калидҳои маъмул дохил нестанд: " +"%(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" +"Мутмаин гардед, ки ҳамаи қиматҳои мутаалиқ ба ин фосила, кам ё баробаранд ба:" +"%(limit_value)s." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "Мутмаин шавед ки ин фосила зиёд ё баробаранд ба: %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/tk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/tk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..06bda56 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/tk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/tk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/tk/LC_MESSAGES/django.po new file mode 100644 index 0000000..6253652 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/tk/LC_MESSAGES/django.po @@ -0,0 +1,107 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Resulkary , 2020 +# Welbeck Garli , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-07-15 16:27+0000\n" +"Last-Translator: Welbeck Garli \n" +"Language-Team: Turkmen (http://www.transifex.com/django/django/language/" +"tk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tk\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL giňeltmeleri" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "" + +msgid "Nested arrays must have the same length." +msgstr "Iç-içe massiwleriň deň uzynlygy bolmaly." + +msgid "Map of strings to strings/nulls" +msgstr "Setirleriň setirler/boşluklara kartasy" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "\"%(key)s\" netijesi setir ýa-da boş däl" + +msgid "Could not load JSON data." +msgstr "JSON maglumatlary ýükläp bolmady." + +msgid "Input must be a JSON dictionary." +msgstr "Giriş JSON sözlügi bolmaly." + +msgid "Enter two valid values." +msgstr "Iki sany dogry baha giriziň." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Aralygyň başlangyjy soňundan ýokary bolmaly däldir." + +msgid "Enter two whole numbers." +msgstr "iki sany esasy san giriziň." + +msgid "Enter two numbers." +msgstr "Iki sany san giriz" + +msgid "Enter two valid date/times." +msgstr "Iki sany dogry senäni/wagty giriziň." + +msgid "Enter two valid dates." +msgstr "Iki sany dogry sene giriziň." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Bu listda %(show_value)d element bar, asyl %(limit_value)ddan köp element " +"bolmaly däldir." +msgstr[1] "" +"Bu listda %(show_value)d element bar, asyl %(limit_value)ddan köp element " +"bolmaly däldir." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Bu listda %(show_value)d element bar, asyl %(limit_value)ddan az element " +"bolmaly däldir." +msgstr[1] "" +"Bu listda %(show_value)d element bar, asyl %(limit_value)ddan az element " +"bolmaly däldir." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Käbir açarlar ýok: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Käbir bilinmeýän açarlar girizilen: %(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "Şu iki aralygyň %(limit_value)s'a deň ýa-da azdygyna göz ýetiriň." + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "Şu iki aralygyň %(limit_value)s'a deň ýa-da köpdügine göz ýetiriň." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/tr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/tr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..849a5e7 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/tr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/tr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/tr/LC_MESSAGES/django.po new file mode 100644 index 0000000..e8c4ea9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/tr/LC_MESSAGES/django.po @@ -0,0 +1,109 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# BouRock, 2015-2019,2023 +# BouRock, 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-19 09:22+0000\n" +"Last-Translator: BouRock, 2015-2019,2023\n" +"Language-Team: Turkish (http://www.transifex.com/django/django/language/" +"tr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL uzantıları" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Dizilimdeki %(nth)s öğesi doğrulanmadı:" + +msgid "Nested arrays must have the same length." +msgstr "İç içe dizilimler aynı uzunlukta olmak zorunda." + +msgid "Map of strings to strings/nulls" +msgstr "Dizgiler/boşlar olarak dizgilerin eşlemesi" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "“%(key)s” değeri bir dizgi ya da boş değil." + +msgid "Could not load JSON data." +msgstr "JSON verisi yüklenemedi." + +msgid "Input must be a JSON dictionary." +msgstr "Bir JSON dizini girilmek zorundadır." + +msgid "Enter two valid values." +msgstr "Iki geçerli değer girin." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Aralığın başlangıcı aralığın bitişini aşmamak zorundadır." + +msgid "Enter two whole numbers." +msgstr "Bütün iki sayıyı girin." + +msgid "Enter two numbers." +msgstr "İki sayı girin." + +msgid "Enter two valid date/times." +msgstr "Geçerli iki tarih/saat girin." + +msgid "Enter two valid dates." +msgstr "Geçerli iki tarih girin." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Liste %(show_value)d öğe içeriyor, %(limit_value)d değerden daha fazla " +"içermemelidir." +msgstr[1] "" +"Liste %(show_value)d öğe içeriyor, %(limit_value)d değerden daha fazla " +"içermemelidir." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Liste %(show_value)d öğe içeriyor, %(limit_value)d değerden daha az " +"içermemelidir." +msgstr[1] "" +"Liste %(show_value)d öğe içeriyor, %(limit_value)d değerden daha az " +"içermemelidir." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Bazı anahtarlar eksik: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Bazı bilinmeyen anahtarlar verilmiş: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "" +"Aralığın üst sınırının %(limit_value)s değerinden büyük olmadığından emin " +"olun." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "" +"Aralığın alt sınırının %(limit_value)s değerinden az olmadığından emin olun." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ug/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ug/LC_MESSAGES/django.mo new file mode 100644 index 0000000..08b016e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ug/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ug/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ug/LC_MESSAGES/django.po new file mode 100644 index 0000000..c0a400b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/ug/LC_MESSAGES/django.po @@ -0,0 +1,107 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Abduqadir Abliz , 2023 +# Azat, 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-12-04 09:22+0000\n" +"Last-Translator: Azat, 2023\n" +"Language-Team: Uyghur (http://app.transifex.com/django/django/language/ug/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ug\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL كېڭەيتمىلەر" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "تىزىملىكتىكى %(nth)s تەرتىپلىك ئېلېمېنت توغرىلانمىدى:" + +msgid "Nested arrays must have the same length." +msgstr "ئىچكى تىزىملىكلەرنىڭ ئۇزۇنلۇقى ئوخشاش بولۇشى كېرەك." + +msgid "Map of strings to strings/nulls" +msgstr "تېكىستلەرنىڭ/نۇللارنىڭ خەرىتىسى" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "“%(key)s” نىڭ قىممىتى تېكىست ياكى نۇلل ئەمەس." + +msgid "Could not load JSON data." +msgstr "JSON سانلىق مەلۇماتنى يۈكلىيەلمىدى." + +msgid "Input must be a JSON dictionary." +msgstr "كىرگۈزۈلگىنى چوقۇم JSON لۇغىتى بولۇشى لازىم." + +msgid "Enter two valid values." +msgstr "ئىككى ئىناۋەتلىك قىممەت كىرگۈزۈلىدۇ." + +msgid "The start of the range must not exceed the end of the range." +msgstr "دائىرەنىڭ باشلىنىشى دائىرەنىڭ ئاخىرىدىن ئېشىپ كەتمەسلىكى كېرەك." + +msgid "Enter two whole numbers." +msgstr "ئىككى پۈتۈن سان كىرگۈزۈلىدۇ." + +msgid "Enter two numbers." +msgstr "ئىككى سان كىرگۈزۈلىدۇ." + +msgid "Enter two valid date/times." +msgstr "ئىناۋەتلىك ئىككى چېسلا/ۋاقىت كىرگۈزۈلىدۇ." + +msgid "Enter two valid dates." +msgstr "ئىككى ئىناۋەتلىك چېسلا كىرگۈزۈلىدۇ." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"تىزىملىك %(show_value)d تەرتىپلىك ئېلېمېنت ئۆز ئىچىگە ئالىدۇ، بۇنىڭدا " +"%(limit_value)d تەرتىپلىك ئېلېمېنتتىن ئاشماسلىكى كېرەك." +msgstr[1] "" +"تىزىملىك %(show_value)d تەرتىپلىك ئېلېمېنت ئۆز ئىچىگە ئالىدۇ، بۇنىڭدا " +"%(limit_value)d تەرتىپلىك ئېلېمېنتتىن ئاشماسلىكى كېرەك." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"تىزىملىك %(show_value)d تەرتىپلىك ئېلېمېنت ئۆز ئىچىگە ئالىدۇ، بۇنىڭدا " +"%(limit_value)d تەرتىپلىك ئېلېمېنتتىن كەم بولماسلىغى كېرەك." +msgstr[1] "" +"تىزىملىك %(show_value)d تەرتىپلىك ئېلېمېنت ئۆز ئىچىگە ئالىدۇ، بۇنىڭدا " +"%(limit_value)d تەرتىپلىك ئېلېمېنتتىن كەم بولماسلىغى كېرەك." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "بەزى ئاچقۇچلار يوق: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "بەزى ئاچقۇچلار تەمىنلەنمىگەن: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "" +"دائىرەنىڭ يۇقىرى چەكلىمىسى%(limit_value)s دىن چوڭ بولماسلىكىنى جەزملەڭ." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "" +"دائىرەنىڭ ئاستى چەكلىمىسى %(limit_value)s دىن ئاز بولماسلىكىنى جەزملەڭ." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/uk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/uk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..60e9d92 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/uk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/uk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/uk/LC_MESSAGES/django.po new file mode 100644 index 0000000..282a03b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/uk/LC_MESSAGES/django.po @@ -0,0 +1,126 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Andriy Sokolovskiy , 2015 +# Denis Podlesniy , 2016 +# Igor Melnyk, 2017 +# Illia Volochii , 2021,2023 +# Kirill Gagarski , 2015-2016 +# tarasyyyk , 2018 +# Zoriana Zaiats, 2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-19 09:22+0000\n" +"Last-Translator: Illia Volochii , 2021,2023\n" +"Language-Team: Ukrainian (http://www.transifex.com/django/django/language/" +"uk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: uk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != " +"11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % " +"100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || " +"(n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n" + +msgid "PostgreSQL extensions" +msgstr "Розширення PostgreSQL" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Елемент %(nth)s у масиві не коректний:" + +msgid "Nested arrays must have the same length." +msgstr "Вкладени масиви повинні бути одинакової довжини." + +msgid "Map of strings to strings/nulls" +msgstr "Асоціативний масив із рядків у рядки/обнулення" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "Значення “%(key)s” не є рядком чи null." + +msgid "Could not load JSON data." +msgstr "Не вдалося завантажити JSON-дані." + +msgid "Input must be a JSON dictionary." +msgstr "Значення повинне бути JSON-словником." + +msgid "Enter two valid values." +msgstr "Введіть два корректних значення." + +msgid "The start of the range must not exceed the end of the range." +msgstr "Початок діапазону не повинен перевищувати кінець діапазону." + +msgid "Enter two whole numbers." +msgstr "Введіть два ціліх числа." + +msgid "Enter two numbers." +msgstr "Введіть два числа." + +msgid "Enter two valid date/times." +msgstr "Введіть дві коректні дати з часом." + +msgid "Enter two valid dates." +msgstr "Введіть дві коректні дати." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" +"Список містить %(show_value)d елемент, кількість яких не має перевищувати " +"%(limit_value)d." +msgstr[1] "" +"Список містить %(show_value)d елементи, кількість яких не має перевищувати " +"%(limit_value)d." +msgstr[2] "" +"Список містить %(show_value)d елементів, кількість яких не має перевищувати " +"%(limit_value)d." +msgstr[3] "" +"Список містить %(show_value)d елементів, кількість яких не має перевищувати " +"%(limit_value)d." + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" +"Список містить %(show_value)d елемент, кількість яких не має бути не менша " +"%(limit_value)d." +msgstr[1] "" +"Список містить %(show_value)d елементів, кількість яких не має бути не менша " +"%(limit_value)d." +msgstr[2] "" +"Список містить %(show_value)d елемента, кількість яких не має бути не менша " +"%(limit_value)d." +msgstr[3] "" +"Список містить %(show_value)d елемента, кількість яких не має бути не менша " +"%(limit_value)d." + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "Не вистачає наступних ключів: %(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "Були надані наступні невідомі ключі: %(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "Переконайтеся, що верхня межа діапазону не перевищує %(limit_value)s." + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "Переконайтеся, що нижня межа діапазону не менша ніж %(limit_value)s." diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/uz/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/uz/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f2d4c0d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/uz/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/uz/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/uz/LC_MESSAGES/django.po new file mode 100644 index 0000000..ca8a24c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/uz/LC_MESSAGES/django.po @@ -0,0 +1,95 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Abdulaminkhon Khaydarov , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-07-25 17:13+0000\n" +"Last-Translator: Abdulaminkhon Khaydarov \n" +"Language-Team: Uzbek (http://www.transifex.com/django/django/language/uz/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: uz\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL kengaytmalar" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "Massiv %(nth)s elementi tasdiqlanmadi:" + +msgid "Nested arrays must have the same length." +msgstr "Ichki massivlar bir xil uzunlikda bo'lishi kerak." + +msgid "Map of strings to strings/nulls" +msgstr "" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "" + +msgid "Could not load JSON data." +msgstr "" + +msgid "Input must be a JSON dictionary." +msgstr "" + +msgid "Enter two valid values." +msgstr "" + +msgid "The start of the range must not exceed the end of the range." +msgstr "" + +msgid "Enter two whole numbers." +msgstr "" + +msgid "Enter two numbers." +msgstr "" + +msgid "Enter two valid date/times." +msgstr "" + +msgid "Enter two valid dates." +msgstr "" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "" + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "" + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/zh_Hans/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/zh_Hans/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3e0c140 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/zh_Hans/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/zh_Hans/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/zh_Hans/LC_MESSAGES/django.po new file mode 100644 index 0000000..ac0b4b8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/zh_Hans/LC_MESSAGES/django.po @@ -0,0 +1,100 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Lele Long , 2015,2017 +# Liping Wang , 2016 +# Liping Wang , 2016 +# wang zhao <672565116@qq.com>, 2018 +# wolf ice , 2020 +# 高乐喆 , 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-01-17 02:13-0600\n" +"PO-Revision-Date: 2023-04-19 09:22+0000\n" +"Last-Translator: 高乐喆 , 2023\n" +"Language-Team: Chinese (China) (http://www.transifex.com/django/django/" +"language/zh_CN/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_CN\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL 扩展。" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "数组中的%(nth)s项目没有验证:" + +msgid "Nested arrays must have the same length." +msgstr "嵌套数组必须是相同长度。" + +msgid "Map of strings to strings/nulls" +msgstr "字符串到字符串/空的映射" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "“%(key)s”的值不是一个字符串或null" + +msgid "Could not load JSON data." +msgstr "不能加载JSON数据。" + +msgid "Input must be a JSON dictionary." +msgstr "输入必须是JSON字典。" + +msgid "Enter two valid values." +msgstr "输入两个有效的值。" + +msgid "The start of the range must not exceed the end of the range." +msgstr "区间开头不能超过区间结尾。" + +msgid "Enter two whole numbers." +msgstr "输入两个整数。" + +msgid "Enter two numbers." +msgstr "输入两个数字。" + +msgid "Enter two valid date/times." +msgstr "输入两个有效的日期/时间。" + +msgid "Enter two valid dates." +msgstr "输入两个有效日期。" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "列表已包含 %(show_value)d 项,不应该超过 %(limit_value)d 项。" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "列表已包含 %(show_value)d 项,不应该少于 %(limit_value)d 项。" + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "某些键缺失:%(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "包含未知的键:%(keys)s" + +#, python-format +msgid "" +"Ensure that the upper bound of the range is not greater than %(limit_value)s." +msgstr "确保范围的上限不大于%(limit_value)s。" + +#, python-format +msgid "" +"Ensure that the lower bound of the range is not less than %(limit_value)s." +msgstr "确保范围的下限不小于%(limit_value)s。" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/zh_Hant/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/zh_Hant/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7e72afd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/zh_Hant/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/zh_Hant/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/zh_Hant/LC_MESSAGES/django.po new file mode 100644 index 0000000..5a6f178 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/locale/zh_Hant/LC_MESSAGES/django.po @@ -0,0 +1,97 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Chen Chun-Chia , 2015 +# Tzu-ping Chung , 2016-2017,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-05-11 20:56+0200\n" +"PO-Revision-Date: 2020-05-12 20:01+0000\n" +"Last-Translator: Transifex Bot <>\n" +"Language-Team: Chinese (Taiwan) (http://www.transifex.com/django/django/" +"language/zh_TW/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_TW\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "PostgreSQL extensions" +msgstr "PostgreSQL 擴充" + +#, python-format +msgid "Item %(nth)s in the array did not validate:" +msgstr "陣列中第 %(nth)s 個物件驗證失敗:" + +msgid "Nested arrays must have the same length." +msgstr "各嵌套陣列長度必須相同。" + +msgid "Map of strings to strings/nulls" +msgstr "字串與字串/空值的對應" + +#, python-format +msgid "The value of “%(key)s” is not a string or null." +msgstr "「%(key)s」並非字串或空值。" + +msgid "Could not load JSON data." +msgstr "無法載入 JSON 資料。" + +msgid "Input must be a JSON dictionary." +msgstr "必須輸入 JSON dictionary。" + +msgid "Enter two valid values." +msgstr "請輸入兩個有效的值" + +msgid "The start of the range must not exceed the end of the range." +msgstr "範圍的起始不可超過範圍的結束。" + +msgid "Enter two whole numbers." +msgstr "請輸入兩個整數" + +msgid "Enter two numbers." +msgstr "請輸入兩個數字" + +msgid "Enter two valid date/times." +msgstr "請輸入兩個有效的日期/時間" + +msgid "Enter two valid dates." +msgstr "請輸入兩個有效的日期" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no more than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no more than " +"%(limit_value)d." +msgstr[0] "串列包含 %(show_value)d 個物件,但不應包含多於 %(limit_value)d 個。" + +#, python-format +msgid "" +"List contains %(show_value)d item, it should contain no fewer than " +"%(limit_value)d." +msgid_plural "" +"List contains %(show_value)d items, it should contain no fewer than " +"%(limit_value)d." +msgstr[0] "串列包含 %(show_value)d 個物件,但應至少包含 %(limit_value)d 個。" + +#, python-format +msgid "Some keys were missing: %(keys)s" +msgstr "缺少鍵值:%(keys)s" + +#, python-format +msgid "Some unknown keys were provided: %(keys)s" +msgstr "包含不明鍵值:%(keys)s" + +#, python-format +msgid "" +"Ensure that this range is completely less than or equal to %(limit_value)s." +msgstr "請確認此範圍是否完全小於或等於 %(limit_value)s。" + +#, python-format +msgid "" +"Ensure that this range is completely greater than or equal to " +"%(limit_value)s." +msgstr "請確認此範圍是否完全大於或等於 %(limit_value)s。" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/lookups.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/lookups.py new file mode 100644 index 0000000..4e1783f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/lookups.py @@ -0,0 +1,78 @@ +from django.db.models import Transform +from django.db.models.lookups import PostgresOperatorLookup +from django.db.models.sql.query import Query + +from .search import SearchVector, SearchVectorExact, SearchVectorField + + +class DataContains(PostgresOperatorLookup): + lookup_name = "contains" + postgres_operator = "@>" + + +class ContainedBy(PostgresOperatorLookup): + lookup_name = "contained_by" + postgres_operator = "<@" + + +class Overlap(PostgresOperatorLookup): + lookup_name = "overlap" + postgres_operator = "&&" + + def get_prep_lookup(self): + from .expressions import ArraySubquery + + if isinstance(self.rhs, Query): + self.rhs = ArraySubquery(self.rhs) + return super().get_prep_lookup() + + +class HasKey(PostgresOperatorLookup): + lookup_name = "has_key" + postgres_operator = "?" + prepare_rhs = False + + +class HasKeys(PostgresOperatorLookup): + lookup_name = "has_keys" + postgres_operator = "?&" + + def get_prep_lookup(self): + return [str(item) for item in self.rhs] + + +class HasAnyKeys(HasKeys): + lookup_name = "has_any_keys" + postgres_operator = "?|" + + +class Unaccent(Transform): + bilateral = True + lookup_name = "unaccent" + function = "UNACCENT" + + +class SearchLookup(SearchVectorExact): + lookup_name = "search" + + def process_lhs(self, qn, connection): + if not isinstance(self.lhs.output_field, SearchVectorField): + config = getattr(self.rhs, "config", None) + self.lhs = SearchVector(self.lhs, config=config) + lhs, lhs_params = super().process_lhs(qn, connection) + return lhs, lhs_params + + +class TrigramSimilar(PostgresOperatorLookup): + lookup_name = "trigram_similar" + postgres_operator = "%%" + + +class TrigramWordSimilar(PostgresOperatorLookup): + lookup_name = "trigram_word_similar" + postgres_operator = "%%>" + + +class TrigramStrictWordSimilar(PostgresOperatorLookup): + lookup_name = "trigram_strict_word_similar" + postgres_operator = "%%>>" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/operations.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/operations.py new file mode 100644 index 0000000..5ac396b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/operations.py @@ -0,0 +1,333 @@ +from django.contrib.postgres.signals import ( + get_citext_oids, + get_hstore_oids, + register_type_handlers, +) +from django.db import NotSupportedError, router +from django.db.migrations import AddConstraint, AddIndex, RemoveIndex +from django.db.migrations.operations.base import Operation +from django.db.models.constraints import CheckConstraint + + +class CreateExtension(Operation): + reversible = True + + def __init__(self, name): + self.name = name + + def state_forwards(self, app_label, state): + pass + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + if schema_editor.connection.vendor != "postgresql" or not router.allow_migrate( + schema_editor.connection.alias, app_label + ): + return + if not self.extension_exists(schema_editor, self.name): + schema_editor.execute( + "CREATE EXTENSION IF NOT EXISTS %s" + % schema_editor.quote_name(self.name) + ) + # Clear cached, stale oids. + get_hstore_oids.cache_clear() + get_citext_oids.cache_clear() + # Registering new type handlers cannot be done before the extension is + # installed, otherwise a subsequent data migration would use the same + # connection. + register_type_handlers(schema_editor.connection) + if hasattr(schema_editor.connection, "register_geometry_adapters"): + schema_editor.connection.register_geometry_adapters( + schema_editor.connection.connection, True + ) + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + if not router.allow_migrate(schema_editor.connection.alias, app_label): + return + if self.extension_exists(schema_editor, self.name): + schema_editor.execute( + "DROP EXTENSION IF EXISTS %s" % schema_editor.quote_name(self.name) + ) + # Clear cached, stale oids. + get_hstore_oids.cache_clear() + get_citext_oids.cache_clear() + + def extension_exists(self, schema_editor, extension): + with schema_editor.connection.cursor() as cursor: + cursor.execute( + "SELECT 1 FROM pg_extension WHERE extname = %s", + [extension], + ) + return bool(cursor.fetchone()) + + def describe(self): + return "Creates extension %s" % self.name + + @property + def migration_name_fragment(self): + return "create_extension_%s" % self.name + + +class BloomExtension(CreateExtension): + def __init__(self): + self.name = "bloom" + + +class BtreeGinExtension(CreateExtension): + def __init__(self): + self.name = "btree_gin" + + +class BtreeGistExtension(CreateExtension): + def __init__(self): + self.name = "btree_gist" + + +class CITextExtension(CreateExtension): + def __init__(self): + self.name = "citext" + + +class CryptoExtension(CreateExtension): + def __init__(self): + self.name = "pgcrypto" + + +class HStoreExtension(CreateExtension): + def __init__(self): + self.name = "hstore" + + +class TrigramExtension(CreateExtension): + def __init__(self): + self.name = "pg_trgm" + + +class UnaccentExtension(CreateExtension): + def __init__(self): + self.name = "unaccent" + + +class NotInTransactionMixin: + def _ensure_not_in_transaction(self, schema_editor): + if schema_editor.connection.in_atomic_block: + raise NotSupportedError( + "The %s operation cannot be executed inside a transaction " + "(set atomic = False on the migration)." % self.__class__.__name__ + ) + + +class AddIndexConcurrently(NotInTransactionMixin, AddIndex): + """Create an index using PostgreSQL's CREATE INDEX CONCURRENTLY syntax.""" + + atomic = False + + def describe(self): + return "Concurrently create index %s on field(s) %s of model %s" % ( + self.index.name, + ", ".join(self.index.fields), + self.model_name, + ) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + self._ensure_not_in_transaction(schema_editor) + model = to_state.apps.get_model(app_label, self.model_name) + if self.allow_migrate_model(schema_editor.connection.alias, model): + schema_editor.add_index(model, self.index, concurrently=True) + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + self._ensure_not_in_transaction(schema_editor) + model = from_state.apps.get_model(app_label, self.model_name) + if self.allow_migrate_model(schema_editor.connection.alias, model): + schema_editor.remove_index(model, self.index, concurrently=True) + + +class RemoveIndexConcurrently(NotInTransactionMixin, RemoveIndex): + """Remove an index using PostgreSQL's DROP INDEX CONCURRENTLY syntax.""" + + atomic = False + + def describe(self): + return "Concurrently remove index %s from %s" % (self.name, self.model_name) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + self._ensure_not_in_transaction(schema_editor) + model = from_state.apps.get_model(app_label, self.model_name) + if self.allow_migrate_model(schema_editor.connection.alias, model): + from_model_state = from_state.models[app_label, self.model_name_lower] + index = from_model_state.get_index_by_name(self.name) + schema_editor.remove_index(model, index, concurrently=True) + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + self._ensure_not_in_transaction(schema_editor) + model = to_state.apps.get_model(app_label, self.model_name) + if self.allow_migrate_model(schema_editor.connection.alias, model): + to_model_state = to_state.models[app_label, self.model_name_lower] + index = to_model_state.get_index_by_name(self.name) + schema_editor.add_index(model, index, concurrently=True) + + +class CollationOperation(Operation): + def __init__(self, name, locale, *, provider="libc", deterministic=True): + self.name = name + self.locale = locale + self.provider = provider + self.deterministic = deterministic + + def state_forwards(self, app_label, state): + pass + + def deconstruct(self): + kwargs = {"name": self.name, "locale": self.locale} + if self.provider and self.provider != "libc": + kwargs["provider"] = self.provider + if self.deterministic is False: + kwargs["deterministic"] = self.deterministic + return ( + self.__class__.__qualname__, + [], + kwargs, + ) + + def create_collation(self, schema_editor): + args = {"locale": schema_editor.quote_name(self.locale)} + if self.provider != "libc": + args["provider"] = schema_editor.quote_name(self.provider) + if self.deterministic is False: + args["deterministic"] = "false" + schema_editor.execute( + "CREATE COLLATION %(name)s (%(args)s)" + % { + "name": schema_editor.quote_name(self.name), + "args": ", ".join( + f"{option}={value}" for option, value in args.items() + ), + } + ) + + def remove_collation(self, schema_editor): + schema_editor.execute( + "DROP COLLATION %s" % schema_editor.quote_name(self.name), + ) + + +class CreateCollation(CollationOperation): + """Create a collation.""" + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + if schema_editor.connection.vendor != "postgresql" or not router.allow_migrate( + schema_editor.connection.alias, app_label + ): + return + self.create_collation(schema_editor) + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + if not router.allow_migrate(schema_editor.connection.alias, app_label): + return + self.remove_collation(schema_editor) + + def describe(self): + return f"Create collation {self.name}" + + @property + def migration_name_fragment(self): + return "create_collation_%s" % self.name.lower() + + +class RemoveCollation(CollationOperation): + """Remove a collation.""" + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + if schema_editor.connection.vendor != "postgresql" or not router.allow_migrate( + schema_editor.connection.alias, app_label + ): + return + self.remove_collation(schema_editor) + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + if not router.allow_migrate(schema_editor.connection.alias, app_label): + return + self.create_collation(schema_editor) + + def describe(self): + return f"Remove collation {self.name}" + + @property + def migration_name_fragment(self): + return "remove_collation_%s" % self.name.lower() + + +class AddConstraintNotValid(AddConstraint): + """ + Add a table constraint without enforcing validation, using PostgreSQL's + NOT VALID syntax. + """ + + def __init__(self, model_name, constraint): + if not isinstance(constraint, CheckConstraint): + raise TypeError( + "AddConstraintNotValid.constraint must be a check constraint." + ) + super().__init__(model_name, constraint) + + def describe(self): + return "Create not valid constraint %s on model %s" % ( + self.constraint.name, + self.model_name, + ) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + model = from_state.apps.get_model(app_label, self.model_name) + if self.allow_migrate_model(schema_editor.connection.alias, model): + constraint_sql = self.constraint.create_sql(model, schema_editor) + if constraint_sql: + # Constraint.create_sql returns interpolated SQL which makes + # params=None a necessity to avoid escaping attempts on + # execution. + schema_editor.execute(str(constraint_sql) + " NOT VALID", params=None) + + @property + def migration_name_fragment(self): + return super().migration_name_fragment + "_not_valid" + + +class ValidateConstraint(Operation): + """Validate a table NOT VALID constraint.""" + + def __init__(self, model_name, name): + self.model_name = model_name + self.name = name + + def describe(self): + return "Validate constraint %s on model %s" % (self.name, self.model_name) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + model = from_state.apps.get_model(app_label, self.model_name) + if self.allow_migrate_model(schema_editor.connection.alias, model): + schema_editor.execute( + "ALTER TABLE %s VALIDATE CONSTRAINT %s" + % ( + schema_editor.quote_name(model._meta.db_table), + schema_editor.quote_name(self.name), + ) + ) + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + # PostgreSQL does not provide a way to make a constraint invalid. + pass + + def state_forwards(self, app_label, state): + pass + + @property + def migration_name_fragment(self): + return "%s_validate_%s" % (self.model_name.lower(), self.name.lower()) + + def deconstruct(self): + return ( + self.__class__.__name__, + [], + { + "model_name": self.model_name, + "name": self.name, + }, + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/search.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/search.py new file mode 100644 index 0000000..936709c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/search.py @@ -0,0 +1,381 @@ +from django.db.models import ( + CharField, + Expression, + Field, + FloatField, + Func, + Lookup, + TextField, + Value, +) +from django.db.models.expressions import CombinedExpression, register_combinable_fields +from django.db.models.functions import Cast, Coalesce + + +class SearchVectorExact(Lookup): + lookup_name = "exact" + + def process_rhs(self, qn, connection): + if not isinstance(self.rhs, (SearchQuery, CombinedSearchQuery)): + config = getattr(self.lhs, "config", None) + self.rhs = SearchQuery(self.rhs, config=config) + rhs, rhs_params = super().process_rhs(qn, connection) + return rhs, rhs_params + + def as_sql(self, qn, connection): + lhs, lhs_params = self.process_lhs(qn, connection) + rhs, rhs_params = self.process_rhs(qn, connection) + params = lhs_params + rhs_params + return "%s @@ %s" % (lhs, rhs), params + + +class SearchVectorField(Field): + def db_type(self, connection): + return "tsvector" + + +class SearchQueryField(Field): + def db_type(self, connection): + return "tsquery" + + +class _Float4Field(Field): + def db_type(self, connection): + return "float4" + + +class SearchConfig(Expression): + def __init__(self, config): + super().__init__() + if not hasattr(config, "resolve_expression"): + config = Value(config) + self.config = config + + @classmethod + def from_parameter(cls, config): + if config is None or isinstance(config, cls): + return config + return cls(config) + + def get_source_expressions(self): + return [self.config] + + def set_source_expressions(self, exprs): + (self.config,) = exprs + + def as_sql(self, compiler, connection): + sql, params = compiler.compile(self.config) + return "%s::regconfig" % sql, params + + +class SearchVectorCombinable: + ADD = "||" + + def _combine(self, other, connector, reversed): + if not isinstance(other, SearchVectorCombinable): + raise TypeError( + "SearchVector can only be combined with other SearchVector " + "instances, got %s." % type(other).__name__ + ) + if reversed: + return CombinedSearchVector(other, connector, self, self.config) + return CombinedSearchVector(self, connector, other, self.config) + + +register_combinable_fields( + SearchVectorField, SearchVectorCombinable.ADD, SearchVectorField, SearchVectorField +) + + +class SearchVector(SearchVectorCombinable, Func): + function = "to_tsvector" + arg_joiner = " || ' ' || " + output_field = SearchVectorField() + + def __init__(self, *expressions, config=None, weight=None): + super().__init__(*expressions) + self.config = SearchConfig.from_parameter(config) + if weight is not None and not hasattr(weight, "resolve_expression"): + weight = Value(weight) + self.weight = weight + + def resolve_expression( + self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False + ): + resolved = super().resolve_expression( + query, allow_joins, reuse, summarize, for_save + ) + if self.config: + resolved.config = self.config.resolve_expression( + query, allow_joins, reuse, summarize, for_save + ) + return resolved + + def as_sql(self, compiler, connection, function=None, template=None): + clone = self.copy() + clone.set_source_expressions( + [ + Coalesce( + expression + if isinstance(expression.output_field, (CharField, TextField)) + else Cast(expression, TextField()), + Value(""), + ) + for expression in clone.get_source_expressions() + ] + ) + config_sql = None + config_params = [] + if template is None: + if clone.config: + config_sql, config_params = compiler.compile(clone.config) + template = "%(function)s(%(config)s, %(expressions)s)" + else: + template = clone.template + sql, params = super(SearchVector, clone).as_sql( + compiler, + connection, + function=function, + template=template, + config=config_sql, + ) + extra_params = [] + if clone.weight: + weight_sql, extra_params = compiler.compile(clone.weight) + sql = "setweight({}, {})".format(sql, weight_sql) + + return sql, config_params + params + extra_params + + +class CombinedSearchVector(SearchVectorCombinable, CombinedExpression): + def __init__(self, lhs, connector, rhs, config, output_field=None): + self.config = config + super().__init__(lhs, connector, rhs, output_field) + + +class SearchQueryCombinable: + BITAND = "&&" + BITOR = "||" + + def _combine(self, other, connector, reversed): + if not isinstance(other, SearchQueryCombinable): + raise TypeError( + "SearchQuery can only be combined with other SearchQuery " + "instances, got %s." % type(other).__name__ + ) + if reversed: + return CombinedSearchQuery(other, connector, self, self.config) + return CombinedSearchQuery(self, connector, other, self.config) + + # On Combinable, these are not implemented to reduce confusion with Q. In + # this case we are actually (ab)using them to do logical combination so + # it's consistent with other usage in Django. + def __or__(self, other): + return self._combine(other, self.BITOR, False) + + def __ror__(self, other): + return self._combine(other, self.BITOR, True) + + def __and__(self, other): + return self._combine(other, self.BITAND, False) + + def __rand__(self, other): + return self._combine(other, self.BITAND, True) + + +class SearchQuery(SearchQueryCombinable, Func): + output_field = SearchQueryField() + SEARCH_TYPES = { + "plain": "plainto_tsquery", + "phrase": "phraseto_tsquery", + "raw": "to_tsquery", + "websearch": "websearch_to_tsquery", + } + + def __init__( + self, + value, + output_field=None, + *, + config=None, + invert=False, + search_type="plain", + ): + self.function = self.SEARCH_TYPES.get(search_type) + if self.function is None: + raise ValueError("Unknown search_type argument '%s'." % search_type) + if not hasattr(value, "resolve_expression"): + value = Value(value) + expressions = (value,) + self.config = SearchConfig.from_parameter(config) + if self.config is not None: + expressions = (self.config,) + expressions + self.invert = invert + super().__init__(*expressions, output_field=output_field) + + def as_sql(self, compiler, connection, function=None, template=None): + sql, params = super().as_sql(compiler, connection, function, template) + if self.invert: + sql = "!!(%s)" % sql + return sql, params + + def __invert__(self): + clone = self.copy() + clone.invert = not self.invert + return clone + + def __str__(self): + result = super().__str__() + return ("~%s" % result) if self.invert else result + + +class CombinedSearchQuery(SearchQueryCombinable, CombinedExpression): + def __init__(self, lhs, connector, rhs, config, output_field=None): + self.config = config + super().__init__(lhs, connector, rhs, output_field) + + def __str__(self): + return "(%s)" % super().__str__() + + +class SearchRank(Func): + function = "ts_rank" + output_field = FloatField() + + def __init__( + self, + vector, + query, + weights=None, + normalization=None, + cover_density=False, + ): + from .fields.array import ArrayField + + if not hasattr(vector, "resolve_expression"): + vector = SearchVector(vector) + if not hasattr(query, "resolve_expression"): + query = SearchQuery(query) + expressions = (vector, query) + if weights is not None: + if not hasattr(weights, "resolve_expression"): + weights = Value(weights) + weights = Cast(weights, ArrayField(_Float4Field())) + expressions = (weights,) + expressions + if normalization is not None: + if not hasattr(normalization, "resolve_expression"): + normalization = Value(normalization) + expressions += (normalization,) + if cover_density: + self.function = "ts_rank_cd" + super().__init__(*expressions) + + +class SearchHeadline(Func): + function = "ts_headline" + template = "%(function)s(%(expressions)s%(options)s)" + output_field = TextField() + + def __init__( + self, + expression, + query, + *, + config=None, + start_sel=None, + stop_sel=None, + max_words=None, + min_words=None, + short_word=None, + highlight_all=None, + max_fragments=None, + fragment_delimiter=None, + ): + if not hasattr(query, "resolve_expression"): + query = SearchQuery(query) + options = { + "StartSel": start_sel, + "StopSel": stop_sel, + "MaxWords": max_words, + "MinWords": min_words, + "ShortWord": short_word, + "HighlightAll": highlight_all, + "MaxFragments": max_fragments, + "FragmentDelimiter": fragment_delimiter, + } + self.options = { + option: value for option, value in options.items() if value is not None + } + expressions = (expression, query) + if config is not None: + config = SearchConfig.from_parameter(config) + expressions = (config,) + expressions + super().__init__(*expressions) + + def as_sql(self, compiler, connection, function=None, template=None): + options_sql = "" + options_params = [] + if self.options: + options_params.append( + ", ".join( + connection.ops.compose_sql(f"{option}=%s", [value]) + for option, value in self.options.items() + ) + ) + options_sql = ", %s" + sql, params = super().as_sql( + compiler, + connection, + function=function, + template=template, + options=options_sql, + ) + return sql, params + options_params + + +SearchVectorField.register_lookup(SearchVectorExact) + + +class TrigramBase(Func): + output_field = FloatField() + + def __init__(self, expression, string, **extra): + if not hasattr(string, "resolve_expression"): + string = Value(string) + super().__init__(expression, string, **extra) + + +class TrigramWordBase(Func): + output_field = FloatField() + + def __init__(self, string, expression, **extra): + if not hasattr(string, "resolve_expression"): + string = Value(string) + super().__init__(string, expression, **extra) + + +class TrigramSimilarity(TrigramBase): + function = "SIMILARITY" + + +class TrigramDistance(TrigramBase): + function = "" + arg_joiner = " <-> " + + +class TrigramWordDistance(TrigramWordBase): + function = "" + arg_joiner = " <<-> " + + +class TrigramStrictWordDistance(TrigramWordBase): + function = "" + arg_joiner = " <<<-> " + + +class TrigramWordSimilarity(TrigramWordBase): + function = "WORD_SIMILARITY" + + +class TrigramStrictWordSimilarity(TrigramWordBase): + function = "STRICT_WORD_SIMILARITY" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/serializers.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/serializers.py new file mode 100644 index 0000000..d04bfdb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/serializers.py @@ -0,0 +1,10 @@ +from django.db.migrations.serializer import BaseSerializer + + +class RangeSerializer(BaseSerializer): + def serialize(self): + module = self.value.__class__.__module__ + # Ranges are implemented in psycopg2._range but the public import + # location is psycopg2.extras. + module = "psycopg2.extras" if module == "psycopg2._range" else module + return "%s.%r" % (module, self.value), {"import %s" % module} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/signals.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/signals.py new file mode 100644 index 0000000..a3816d3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/signals.py @@ -0,0 +1,80 @@ +import functools + +from django.db import connections +from django.db.backends.base.base import NO_DB_ALIAS +from django.db.backends.postgresql.psycopg_any import is_psycopg3 + + +def get_type_oids(connection_alias, type_name): + with connections[connection_alias].cursor() as cursor: + cursor.execute( + "SELECT oid, typarray FROM pg_type WHERE typname = %s", (type_name,) + ) + oids = [] + array_oids = [] + for row in cursor: + oids.append(row[0]) + array_oids.append(row[1]) + return tuple(oids), tuple(array_oids) + + +@functools.lru_cache +def get_hstore_oids(connection_alias): + """Return hstore and hstore array OIDs.""" + return get_type_oids(connection_alias, "hstore") + + +@functools.lru_cache +def get_citext_oids(connection_alias): + """Return citext and citext array OIDs.""" + return get_type_oids(connection_alias, "citext") + + +if is_psycopg3: + from psycopg.types import TypeInfo, hstore + + def register_type_handlers(connection, **kwargs): + if connection.vendor != "postgresql" or connection.alias == NO_DB_ALIAS: + return + + oids, array_oids = get_hstore_oids(connection.alias) + for oid, array_oid in zip(oids, array_oids): + ti = TypeInfo("hstore", oid, array_oid) + hstore.register_hstore(ti, connection.connection) + + _, citext_oids = get_citext_oids(connection.alias) + for array_oid in citext_oids: + ti = TypeInfo("citext", 0, array_oid) + ti.register(connection.connection) + +else: + import psycopg2 + from psycopg2.extras import register_hstore + + def register_type_handlers(connection, **kwargs): + if connection.vendor != "postgresql" or connection.alias == NO_DB_ALIAS: + return + + oids, array_oids = get_hstore_oids(connection.alias) + # Don't register handlers when hstore is not available on the database. + # + # If someone tries to create an hstore field it will error there. This is + # necessary as someone may be using PSQL without extensions installed but + # be using other features of contrib.postgres. + # + # This is also needed in order to create the connection in order to install + # the hstore extension. + if oids: + register_hstore( + connection.connection, globally=True, oid=oids, array_oid=array_oids + ) + + oids, citext_oids = get_citext_oids(connection.alias) + # Don't register handlers when citext is not available on the database. + # + # The same comments in the above call to register_hstore() also apply here. + if oids: + array_type = psycopg2.extensions.new_array_type( + citext_oids, "citext[]", psycopg2.STRING + ) + psycopg2.extensions.register_type(array_type, None) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/templates/postgres/widgets/split_array.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/templates/postgres/widgets/split_array.html new file mode 100644 index 0000000..32fda82 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/templates/postgres/widgets/split_array.html @@ -0,0 +1 @@ +{% include 'django/forms/widgets/multiwidget.html' %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/utils.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/utils.py new file mode 100644 index 0000000..e4f4d81 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/utils.py @@ -0,0 +1,29 @@ +from django.core.exceptions import ValidationError +from django.utils.functional import SimpleLazyObject +from django.utils.text import format_lazy + + +def prefix_validation_error(error, prefix, code, params): + """ + Prefix a validation error message while maintaining the existing + validation data structure. + """ + if error.error_list == [error]: + error_params = error.params or {} + return ValidationError( + # We can't simply concatenate messages since they might require + # their associated parameters to be expressed correctly which + # is not something `format_lazy` does. For example, proxied + # ngettext calls require a count parameter and are converted + # to an empty string if they are missing it. + message=format_lazy( + "{} {}", + SimpleLazyObject(lambda: prefix % params), + SimpleLazyObject(lambda: error.message % error_params), + ), + code=code, + params={**error_params, **params}, + ) + return ValidationError( + [prefix_validation_error(e, prefix, code, params) for e in error.error_list] + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/validators.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/validators.py new file mode 100644 index 0000000..330b69b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/postgres/validators.py @@ -0,0 +1,91 @@ +from django.core.exceptions import ValidationError +from django.core.validators import ( + MaxLengthValidator, + MaxValueValidator, + MinLengthValidator, + MinValueValidator, +) +from django.utils.deconstruct import deconstructible +from django.utils.translation import gettext_lazy as _ +from django.utils.translation import ngettext_lazy + + +class ArrayMaxLengthValidator(MaxLengthValidator): + message = ngettext_lazy( + "List contains %(show_value)d item, it should contain no more than " + "%(limit_value)d.", + "List contains %(show_value)d items, it should contain no more than " + "%(limit_value)d.", + "show_value", + ) + + +class ArrayMinLengthValidator(MinLengthValidator): + message = ngettext_lazy( + "List contains %(show_value)d item, it should contain no fewer than " + "%(limit_value)d.", + "List contains %(show_value)d items, it should contain no fewer than " + "%(limit_value)d.", + "show_value", + ) + + +@deconstructible +class KeysValidator: + """A validator designed for HStore to require/restrict keys.""" + + messages = { + "missing_keys": _("Some keys were missing: %(keys)s"), + "extra_keys": _("Some unknown keys were provided: %(keys)s"), + } + strict = False + + def __init__(self, keys, strict=False, messages=None): + self.keys = set(keys) + self.strict = strict + if messages is not None: + self.messages = {**self.messages, **messages} + + def __call__(self, value): + keys = set(value) + missing_keys = self.keys - keys + if missing_keys: + raise ValidationError( + self.messages["missing_keys"], + code="missing_keys", + params={"keys": ", ".join(missing_keys)}, + ) + if self.strict: + extra_keys = keys - self.keys + if extra_keys: + raise ValidationError( + self.messages["extra_keys"], + code="extra_keys", + params={"keys": ", ".join(extra_keys)}, + ) + + def __eq__(self, other): + return ( + isinstance(other, self.__class__) + and self.keys == other.keys + and self.messages == other.messages + and self.strict == other.strict + ) + + +class RangeMaxValueValidator(MaxValueValidator): + def compare(self, a, b): + return a.upper is None or a.upper > b + + message = _( + "Ensure that the upper bound of the range is not greater than %(limit_value)s." + ) + + +class RangeMinValueValidator(MinValueValidator): + def compare(self, a, b): + return a.lower is None or a.lower < b + + message = _( + "Ensure that the lower bound of the range is not less than %(limit_value)s." + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/admin.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/admin.py new file mode 100644 index 0000000..39400ad --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/admin.py @@ -0,0 +1,10 @@ +from django.contrib import admin +from django.contrib.redirects.models import Redirect + + +@admin.register(Redirect) +class RedirectAdmin(admin.ModelAdmin): + list_display = ("old_path", "new_path") + list_filter = ("site",) + search_fields = ("old_path", "new_path") + radio_fields = {"site": admin.VERTICAL} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/apps.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/apps.py new file mode 100644 index 0000000..d770671 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/apps.py @@ -0,0 +1,8 @@ +from django.apps import AppConfig +from django.utils.translation import gettext_lazy as _ + + +class RedirectsConfig(AppConfig): + default_auto_field = "django.db.models.AutoField" + name = "django.contrib.redirects" + verbose_name = _("Redirects") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/af/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/af/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5df03ce Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/af/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/af/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/af/LC_MESSAGES/django.po new file mode 100644 index 0000000..379ef04 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/af/LC_MESSAGES/django.po @@ -0,0 +1,51 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Charl du Plessis , 2021 +# F Wolff , 2019,2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2023-12-04 18:32+0000\n" +"Last-Translator: F Wolff , 2019,2023\n" +"Language-Team: Afrikaans (http://app.transifex.com/django/django/language/" +"af/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: af\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Aansture" + +msgid "site" +msgstr "werf" + +msgid "redirect from" +msgstr "aanstuurvorm" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Hierdie moet ’n absolute pad wees met die domeinnaam uitgesluit. Soos " +"byvoorbeeld: “/events/search/”." + +msgid "redirect to" +msgstr "stuur aan na" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Hierdie kan óf 'n absolute pad wees (soos bo) óf ’n volledige URL wees wat " +"begin met ’n skema soos “https://”." + +msgid "redirect" +msgstr "aanstuur" + +msgid "redirects" +msgstr "aansture" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ar/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ar/LC_MESSAGES/django.mo new file mode 100644 index 0000000..97afd31 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ar/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ar/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ar/LC_MESSAGES/django.po new file mode 100644 index 0000000..523327a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ar/LC_MESSAGES/django.po @@ -0,0 +1,51 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bashar Al-Abdulhadi, 2016,2021 +# Bashar Al-Abdulhadi, 2014 +# Jannis Leidel , 2011 +# Muaaz Alsaied, 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-10-15 21:27+0000\n" +"Last-Translator: Bashar Al-Abdulhadi\n" +"Language-Team: Arabic (http://www.transifex.com/django/django/language/ar/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +msgid "Redirects" +msgstr "إعادات التوجيه" + +msgid "site" +msgstr "موقع" + +msgid "redirect from" +msgstr "إعادة التوجيه من" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "يجب أن يكون هذا مساراً مطلقاً وبدون اسم النطاق. مثال: “/events/search/”." + +msgid "redirect to" +msgstr "إعادة التوجيه إلى" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"يجب أن يكون هذا مسارا مطلقا (كما هو أعلاه) أو عنوانا كاملا يبدأ بالمقطع " +"“https://”." + +msgid "redirect" +msgstr "إعادة التوجيه" + +msgid "redirects" +msgstr "إعادات التوجيه" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ar_DZ/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ar_DZ/LC_MESSAGES/django.mo new file mode 100644 index 0000000..62162dd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ar_DZ/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ar_DZ/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ar_DZ/LC_MESSAGES/django.po new file mode 100644 index 0000000..6da32dd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ar_DZ/LC_MESSAGES/django.po @@ -0,0 +1,50 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jihad Bahmaid Al-Halki, 2022 +# Riterix , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2022-07-24 18:32+0000\n" +"Last-Translator: Jihad Bahmaid Al-Halki\n" +"Language-Team: Arabic (Algeria) (http://www.transifex.com/django/django/" +"language/ar_DZ/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar_DZ\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +msgid "Redirects" +msgstr "إعادات التوجيه" + +msgid "site" +msgstr "موقع" + +msgid "redirect from" +msgstr "إعادة التوجيه من" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "يجب أن يكون هذا مساراً مطلقاً وبدون اسم النطاق. مثال: '/events/search/'." + +msgid "redirect to" +msgstr "إعادة التوجيه إلى" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"قد يكون هذا المسار منتهي الصلاحية (كما هو موضح أعلاه) أو أن العنوان له بادئة " +"بصيغة مثل\"https://\"." + +msgid "redirect" +msgstr "إعادة التوجيه" + +msgid "redirects" +msgstr "إعادات التوجيه" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ast/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ast/LC_MESSAGES/django.mo new file mode 100644 index 0000000..6d2d993 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ast/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ast/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ast/LC_MESSAGES/django.po new file mode 100644 index 0000000..908c020 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ast/LC_MESSAGES/django.po @@ -0,0 +1,50 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ḷḷumex03 , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-23 19:51+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Asturian (http://www.transifex.com/django/django/language/" +"ast/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ast\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "" + +msgid "site" +msgstr "" + +msgid "redirect from" +msgstr "redireicionáu de" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"Esto debería ser un camín absolutu, escluyendo'l nome de dominiu. Exemplu: '/" +"events/search/'." + +msgid "redirect to" +msgstr "redireicionáu a" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"Esto pue tamién ser un camín absolutu (como enriba) o una URL completa " +"entamando con 'http://'." + +msgid "redirect" +msgstr "redireicionar" + +msgid "redirects" +msgstr "redireiciones" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/az/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/az/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8f00ebd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/az/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/az/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/az/LC_MESSAGES/django.po new file mode 100644 index 0000000..f1713bb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/az/LC_MESSAGES/django.po @@ -0,0 +1,50 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ali Ismayilov , 2011 +# Emin Mastizada , 2020 +# Emin Mastizada , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-01-12 06:46+0000\n" +"Last-Translator: Emin Mastizada \n" +"Language-Team: Azerbaijani (http://www.transifex.com/django/django/language/" +"az/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: az\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Yönləndirmələr" + +msgid "site" +msgstr "sayt" + +msgid "redirect from" +msgstr "buradan yönəlt" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "Bu, domen adı xaric, mütləq yol olmalıdır. Məsələn: “/events/search/”." + +msgid "redirect to" +msgstr "bura yönəlt" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"“http://”." +msgstr "" +"Bu həm mütləq yol (yuxarıdakı kimi), həm də “http://” ilə başlayan tam URL " +"ola bilər." + +msgid "redirect" +msgstr "yönəlt" + +msgid "redirects" +msgstr "yönəldir" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/be/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/be/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f8c704b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/be/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/be/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/be/LC_MESSAGES/django.po new file mode 100644 index 0000000..667bddc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/be/LC_MESSAGES/django.po @@ -0,0 +1,52 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Viktar Palstsiuk , 2015 +# znotdead , 2016,2019,2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-01-15 17:28+0000\n" +"Last-Translator: znotdead \n" +"Language-Team: Belarusian (http://www.transifex.com/django/django/language/" +"be/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: be\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n" +"%100>=11 && n%100<=14)? 2 : 3);\n" + +msgid "Redirects" +msgstr "Перанакіраванні" + +msgid "site" +msgstr "сайт" + +msgid "redirect from" +msgstr "накіраваць з" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Тут мусіць быць поўны шлях бяз назвы дамэна. Прыклад: “/events/search/”." + +msgid "redirect to" +msgstr "накіраваць да" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Тут, як і ўверсе, мусіць быць поўны шлях, або поўная сеціўная спасылка, якая " +"пачынаецца з “https://”." + +msgid "redirect" +msgstr "накіраваньне" + +msgid "redirects" +msgstr "накіраваньні" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/bg/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/bg/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f47e604 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/bg/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/bg/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/bg/LC_MESSAGES/django.po new file mode 100644 index 0000000..0fc628b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/bg/LC_MESSAGES/django.po @@ -0,0 +1,53 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# arneatec , 2022 +# Jannis Leidel , 2011 +# Venelin Stoykov , 2015 +# vestimir , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2022-01-14 11:55+0000\n" +"Last-Translator: arneatec \n" +"Language-Team: Bulgarian (http://www.transifex.com/django/django/language/" +"bg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Препратки" + +msgid "site" +msgstr "сайт" + +msgid "redirect from" +msgstr "препратка от" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Това трябва да бъде абсолютен път, без името на домейна. Пример: \"/events/" +"search/\"." + +msgid "redirect to" +msgstr "препратка към" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Това може да бъде или абсолютен път (като горното) или пълен URL, започващ " +"със схема, например \"https://\"." + +msgid "redirect" +msgstr "препратка" + +msgid "redirects" +msgstr "препратки" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/bn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/bn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3d5ed41 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/bn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/bn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/bn/LC_MESSAGES/django.po new file mode 100644 index 0000000..f7a9334 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/bn/LC_MESSAGES/django.po @@ -0,0 +1,48 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Bengali (http://www.transifex.com/django/django/language/" +"bn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "" + +msgid "site" +msgstr "" + +msgid "redirect from" +msgstr "রিডাইরেক্ট করা হবে" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"এর মান অবশ্যই এবসল্যুট পথ, ডোমেইন নাম বাদ দিয়ে, হতে হবে, উদাহরণঃ '/events/" +"search/'।" + +msgid "redirect to" +msgstr "রিডাইরেক্ট করুন" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "এর মান এবসল্যুট পথ (উপরের মত) অথবা পুরো URL পাথ ('http://' সহ) হতে পারে।" + +msgid "redirect" +msgstr "রিডাইরেক্ট" + +msgid "redirects" +msgstr "রিডাইরেক্ট" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/br/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/br/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3c20edc Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/br/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/br/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/br/LC_MESSAGES/django.po new file mode 100644 index 0000000..920f068 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/br/LC_MESSAGES/django.po @@ -0,0 +1,54 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Fulup , 2012 +# Irriep Nala Novram , 2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2018-10-19 23:15+0000\n" +"Last-Translator: Irriep Nala Novram \n" +"Language-Team: Breton (http://www.transifex.com/django/django/language/br/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: br\n" +"Plural-Forms: nplurals=5; plural=((n%10 == 1) && (n%100 != 11) && (n%100 !" +"=71) && (n%100 !=91) ? 0 :(n%10 == 2) && (n%100 != 12) && (n%100 !=72) && (n" +"%100 !=92) ? 1 :(n%10 ==3 || n%10==4 || n%10==9) && (n%100 < 10 || n% 100 > " +"19) && (n%100 < 70 || n%100 > 79) && (n%100 < 90 || n%100 > 99) ? 2 :(n != 0 " +"&& n % 1000000 == 0) ? 3 : 4);\n" + +msgid "Redirects" +msgstr "Adkasadennoù" + +msgid "site" +msgstr "lec'hienn" + +msgid "redirect from" +msgstr "adkaset eus" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"An dra-se a rankfe bezañ un hent absolud, en ur dennañ an holl anvioù " +"domani. Da skouer: '/events/search /'." + +msgid "redirect to" +msgstr "adkas da" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"An dra-se a c'hall bezañ un hent absolud (evel a-us) pe un URL klok o kregiñ " +"gant 'http://'." + +msgid "redirect" +msgstr "adkas" + +msgid "redirects" +msgstr "adkasoù" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/bs/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/bs/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f986b59 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/bs/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/bs/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/bs/LC_MESSAGES/django.po new file mode 100644 index 0000000..b4f065e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/bs/LC_MESSAGES/django.po @@ -0,0 +1,51 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Bosnian (http://www.transifex.com/django/django/language/" +"bs/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bs\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Redirects" +msgstr "" + +msgid "site" +msgstr "" + +msgid "redirect from" +msgstr "preusmjeren sa" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"Ovo mora biti apsolutna putanja bez imena domena. Na primjer: '/events/" +"search/'." + +msgid "redirect to" +msgstr "preusmjeri ka" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"Ovo može biti ili apsolutna putanja (kao gore) ili pun URL koji počinje sa " +"'http://'." + +msgid "redirect" +msgstr "preusmjeravanje" + +msgid "redirects" +msgstr "preusmjeravanja" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ca/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ca/LC_MESSAGES/django.mo new file mode 100644 index 0000000..fedd26a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ca/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ca/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ca/LC_MESSAGES/django.po new file mode 100644 index 0000000..e94f9c8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ca/LC_MESSAGES/django.po @@ -0,0 +1,54 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Antoni Aloy , 2021 +# Carles Barrobés , 2014 +# Jannis Leidel , 2011 +# Manel Clos , 2020 +# Roger Pons , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-10-27 09:06+0000\n" +"Last-Translator: Antoni Aloy \n" +"Language-Team: Catalan (http://www.transifex.com/django/django/language/" +"ca/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ca\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Redireccions" + +msgid "site" +msgstr "lloc" + +msgid "redirect from" +msgstr "redirecció des de" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Aquesta ruta hauria de ser una camí absolut, excloent-ne el nom del domini. " +"Exemple: '/events/search/'." + +msgid "redirect to" +msgstr "redirigir a" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Això pot ser bé una ruta absoluta (com a sobre) o una URL completa que " +"comenci per un esquema com 'https://'." + +msgid "redirect" +msgstr "redirecció" + +msgid "redirects" +msgstr "redireccions" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ckb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ckb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5e5fad9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ckb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ckb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ckb/LC_MESSAGES/django.po new file mode 100644 index 0000000..596f66d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ckb/LC_MESSAGES/django.po @@ -0,0 +1,49 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# kosar tofiq , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2023-04-24 18:32+0000\n" +"Last-Translator: kosar tofiq , 2021\n" +"Language-Team: Central Kurdish (http://www.transifex.com/django/django/" +"language/ckb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ckb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "ئاڕاستەکردنەوەکان" + +msgid "site" +msgstr "پێگە" + +msgid "redirect from" +msgstr "ئاڕاستەکردنەوە لە" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"ئەمە دەبێت ڕێجکەیەکی ڕەهابێت، بەبێ ناوی دۆمەین. نمونە: “/events/search/”." + +msgid "redirect to" +msgstr "ئاڕاستەکردنەوە بۆ" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"دەکرێت ئەمە یان ڕچکەی ڕەها بێت (وەکو سەرەوە) یان هەموو URL بێت کە بە سکیم " +"دەستپێبکات وەک “https://”." + +msgid "redirect" +msgstr "ئاڕاستەکردنەوە" + +msgid "redirects" +msgstr "ئاڕاستەکردنەوەکان" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/cs/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/cs/LC_MESSAGES/django.mo new file mode 100644 index 0000000..978d833 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/cs/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/cs/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/cs/LC_MESSAGES/django.po new file mode 100644 index 0000000..08c57c4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/cs/LC_MESSAGES/django.po @@ -0,0 +1,51 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Vláďa Macek , 2014 +# Vláďa Macek , 2015,2019,2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-03-18 23:14+0000\n" +"Last-Translator: Vláďa Macek \n" +"Language-Team: Czech (http://www.transifex.com/django/django/language/cs/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cs\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n " +"<= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n" + +msgid "Redirects" +msgstr "Přesměrování" + +msgid "site" +msgstr "web" + +msgid "redirect from" +msgstr "přesměrovat z" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Toto by měla být absolutní cesta bez domény. Příklad: \"/udalosti/hledat/\"." + +msgid "redirect to" +msgstr "přesměrovat na" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Toto by měla být buď absolutní cesta (jako výše) nebo plná adresa URL " +"začínající schématem, tedy například \"https://\"." + +msgid "redirect" +msgstr "přesměrování" + +msgid "redirects" +msgstr "přesměrování" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/cy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/cy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..737534d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/cy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/cy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/cy/LC_MESSAGES/django.po new file mode 100644 index 0000000..ab8a428 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/cy/LC_MESSAGES/django.po @@ -0,0 +1,51 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Maredudd ap Gwyndaf , 2012,2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Welsh (http://www.transifex.com/django/django/language/cy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cy\n" +"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != " +"11) ? 2 : 3;\n" + +msgid "Redirects" +msgstr "Ailgyfeiriadau" + +msgid "site" +msgstr "" + +msgid "redirect from" +msgstr "ailgyfeirio o" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"Dylai hon fod yn lwybr absoliwt, heb yr enw parth. Er enghraifft: '/" +"digwyddiadau/chwilio/'." + +msgid "redirect to" +msgstr "ailgyfeirio i" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"Gellir fod naill ai yn lwybr absoliwt (fel uchod) neu URL llawn yn dechrau â " +"'http://'." + +msgid "redirect" +msgstr "ailgyfeiriad" + +msgid "redirects" +msgstr "ailgyfeiriadau" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/da/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/da/LC_MESSAGES/django.mo new file mode 100644 index 0000000..dfe4c63 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/da/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/da/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/da/LC_MESSAGES/django.po new file mode 100644 index 0000000..0c6521c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/da/LC_MESSAGES/django.po @@ -0,0 +1,50 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Erik Ramsgaard Wognsen , 2021 +# Erik Ramsgaard Wognsen , 2014-2015,2019 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-01-15 18:30+0000\n" +"Last-Translator: Erik Ramsgaard Wognsen \n" +"Language-Team: Danish (http://www.transifex.com/django/django/language/da/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: da\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Omdirigeringer" + +msgid "site" +msgstr "webside" + +msgid "redirect from" +msgstr "omdiriger fra" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Dette skal være en absolut sti uden domænenavnet. Eksempel: “/nyheder/soeg/”" + +msgid "redirect to" +msgstr "omdiriger til" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Dette kan være enten en absolut sti (som ovenfor) eller en hel URL der " +"starter med en protokol, fx “https://”." + +msgid "redirect" +msgstr "omdiriger" + +msgid "redirects" +msgstr "omdirigeringer" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/de/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/de/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2db36dc Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/de/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/de/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/de/LC_MESSAGES/django.po new file mode 100644 index 0000000..78f928a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/de/LC_MESSAGES/django.po @@ -0,0 +1,51 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# André Hagenbruch, 2015 +# Florian Apolloner , 2021 +# Jannis Leidel , 2011,2013-2017,2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-11-28 17:21+0000\n" +"Last-Translator: Raphael Michel \n" +"Language-Team: German (http://www.transifex.com/django/django/language/de/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Umleitungen" + +msgid "site" +msgstr "Website" + +msgid "redirect from" +msgstr "Umleitung von" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Hier sollte ein absoluter Pfad stehen, ohne den Domainnamen. Beispiel: „/" +"events/search/“." + +msgid "redirect to" +msgstr "Umleitung nach" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Hier muss entweder ein absoluter Pfad (wie darüber) oder eine komplette URL " +"mit einem Schema, wie zum Beispiel „https://“, stehen." + +msgid "redirect" +msgstr "Umleitung" + +msgid "redirects" +msgstr "Umleitungen" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/dsb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/dsb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ab747ca Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/dsb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/dsb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/dsb/LC_MESSAGES/django.po new file mode 100644 index 0000000..06b51ff --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/dsb/LC_MESSAGES/django.po @@ -0,0 +1,51 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Michael Wolf , 2016,2020-2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-02-01 22:11+0000\n" +"Last-Translator: Michael Wolf \n" +"Language-Team: Lower Sorbian (http://www.transifex.com/django/django/" +"language/dsb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: dsb\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" + +msgid "Redirects" +msgstr "Dalejpósrědnjenja" + +msgid "site" +msgstr "sedło" + +msgid "redirect from" +msgstr "dalejpósrědnjenje wót" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"To by dejało absolutna sćažka byś, mimo domenowego mjenja. Pśikład: „/events/" +"search/“." + +msgid "redirect to" +msgstr "dalejpósrědnjenje do" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"To móžo pak absolutna sćažka byś (ako górjejce) pak dopołny URL, kótaryž " +"zachopina se z „https://“." + +msgid "redirect" +msgstr "dalejpósrědnjenje" + +msgid "redirects" +msgstr "dalejpósrědnjenja" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/el/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/el/LC_MESSAGES/django.mo new file mode 100644 index 0000000..89b919c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/el/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/el/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/el/LC_MESSAGES/django.po new file mode 100644 index 0000000..c1d13e7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/el/LC_MESSAGES/django.po @@ -0,0 +1,52 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Nick Mavrakis , 2016 +# Pãnoș , 2014 +# Serafeim Papastefanos , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-06-03 18:27+0000\n" +"Last-Translator: Serafeim Papastefanos \n" +"Language-Team: Greek (http://www.transifex.com/django/django/language/el/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: el\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Ανακατευθύνσεις" + +msgid "site" +msgstr "ιστότοπος" + +msgid "redirect from" +msgstr "ανακατεύθυνση από" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Πρέπει να είναι ένα απόλυτο μονοπάτι χωρίς το όνομα τομέα. Για παράδειγμα \"/" +"events/search\"." + +msgid "redirect to" +msgstr "ανακατεύθυνση προς" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Μπορεί να είναι είτε ένα απόλυτο μονοπάτι (όπως πιο πάνω) είτε ένα πλήρες " +"URL που ξεκινά με κατάλληλο σχημα πχ \"https://\"." + +msgid "redirect" +msgstr "ανακατεύθυνση" + +msgid "redirects" +msgstr "ανακατευθύνσεις" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/en/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/en/LC_MESSAGES/django.mo new file mode 100644 index 0000000..08a7b68 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/en/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/en/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/en/LC_MESSAGES/django.po new file mode 100644 index 0000000..01a3eb7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/en/LC_MESSAGES/django.po @@ -0,0 +1,50 @@ +# This file is distributed under the same license as the Django package. +# +msgid "" +msgstr "" +"Project-Id-Version: Django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2010-05-13 15:35+0200\n" +"Last-Translator: Django team\n" +"Language-Team: English \n" +"Language: en\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: contrib/redirects/apps.py:8 +msgid "Redirects" +msgstr "" + +#: contrib/redirects/models.py:7 +msgid "site" +msgstr "" + +#: contrib/redirects/models.py:9 +msgid "redirect from" +msgstr "" + +#: contrib/redirects/models.py:12 +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" + +#: contrib/redirects/models.py:15 +msgid "redirect to" +msgstr "" + +#: contrib/redirects/models.py:19 +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" + +#: contrib/redirects/models.py:25 +msgid "redirect" +msgstr "" + +#: contrib/redirects/models.py:26 +msgid "redirects" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/en_AU/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/en_AU/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f8b5bf1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/en_AU/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/en_AU/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/en_AU/LC_MESSAGES/django.po new file mode 100644 index 0000000..13be8ad --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/en_AU/LC_MESSAGES/django.po @@ -0,0 +1,50 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Tom Fifield , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-04-11 13:16+0000\n" +"Last-Translator: Tom Fifield \n" +"Language-Team: English (Australia) (http://www.transifex.com/django/django/" +"language/en_AU/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_AU\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Redirects" + +msgid "site" +msgstr "site" + +msgid "redirect from" +msgstr "redirect from" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." + +msgid "redirect to" +msgstr "redirect to" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." + +msgid "redirect" +msgstr "redirect" + +msgid "redirects" +msgstr "redirects" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/en_GB/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/en_GB/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c362746 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/en_GB/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/en_GB/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/en_GB/LC_MESSAGES/django.po new file mode 100644 index 0000000..d86a8e9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/en_GB/LC_MESSAGES/django.po @@ -0,0 +1,50 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ross Poulton , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: English (United Kingdom) (http://www.transifex.com/django/" +"django/language/en_GB/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_GB\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "" + +msgid "site" +msgstr "" + +msgid "redirect from" +msgstr "redirect from" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." + +msgid "redirect to" +msgstr "redirect to" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." + +msgid "redirect" +msgstr "redirect" + +msgid "redirects" +msgstr "redirects" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/eo/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/eo/LC_MESSAGES/django.mo new file mode 100644 index 0000000..dfe9412 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/eo/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/eo/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/eo/LC_MESSAGES/django.po new file mode 100644 index 0000000..72c4b91 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/eo/LC_MESSAGES/django.po @@ -0,0 +1,49 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Batist D 🐍 , 2011 +# Batist D 🐍 , 2014-2015 +# kristjan , 2011 +# Meiyer , 2022 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2022-04-24 18:32+0000\n" +"Last-Translator: Meiyer , 2022\n" +"Language-Team: Esperanto (http://www.transifex.com/django/django/language/" +"eo/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eo\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Alidirektigiloj" + +msgid "site" +msgstr "retejo" + +msgid "redirect from" +msgstr "alidirektigo de" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" + +msgid "redirect to" +msgstr "alidirektigo al" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" + +msgid "redirect" +msgstr "alidirektigilo" + +msgid "redirects" +msgstr "alidirektigiloj" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es/LC_MESSAGES/django.mo new file mode 100644 index 0000000..715b372 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es/LC_MESSAGES/django.po new file mode 100644 index 0000000..808849e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es/LC_MESSAGES/django.po @@ -0,0 +1,53 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# e4db27214f7e7544f2022c647b585925_bb0e321, 2015 +# e4db27214f7e7544f2022c647b585925_bb0e321, 2014 +# Jannis Leidel , 2011 +# Uriel Medina , 2020-2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-02-11 05:54+0000\n" +"Last-Translator: Uriel Medina \n" +"Language-Team: Spanish (http://www.transifex.com/django/django/language/" +"es/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Redirecciones" + +msgid "site" +msgstr "sitio" + +msgid "redirect from" +msgstr "redireccionar desde" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Esta debe ser una ruta absoluta, excluyendo el nombre de dominio. Ejemplo: “/" +"eventos/búsqueda/”." + +msgid "redirect to" +msgstr "redireccionar a" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Esto puede ser una ruta absoluta (como se indica arriba) o una URL completa " +"que comience con un esquema como \"https: //\"." + +msgid "redirect" +msgstr "redirección" + +msgid "redirects" +msgstr "redirecciones" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es_AR/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es_AR/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f690dc3 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es_AR/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es_AR/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es_AR/LC_MESSAGES/django.po new file mode 100644 index 0000000..1eb774c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es_AR/LC_MESSAGES/django.po @@ -0,0 +1,51 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Ramiro Morales, 2014-2015,2019,2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-03-21 13:00+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Spanish (Argentina) (http://www.transifex.com/django/django/" +"language/es_AR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_AR\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Redirecciones" + +msgid "site" +msgstr "sitio" + +msgid "redirect from" +msgstr "redirigir desde" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Esta ruta debe ser absoluta, excluyendo el nombre de dominio. Ejemplo: “/" +"events/search”." + +msgid "redirect to" +msgstr "redirigir a" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Esto puede ser bien una ruta absoluta (como arriba) o una URL completa que " +"empiece con un esquema, por ejemplo “https://”." + +msgid "redirect" +msgstr "redirección" + +msgid "redirects" +msgstr "redirecciones" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es_CO/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es_CO/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e591305 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es_CO/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es_CO/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es_CO/LC_MESSAGES/django.po new file mode 100644 index 0000000..2e84843 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es_CO/LC_MESSAGES/django.po @@ -0,0 +1,50 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Carlos Muñoz , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 22:02+0000\n" +"Last-Translator: Carlos Muñoz \n" +"Language-Team: Spanish (Colombia) (http://www.transifex.com/django/django/" +"language/es_CO/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_CO\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Redirecciones" + +msgid "site" +msgstr "sitio" + +msgid "redirect from" +msgstr "redirigir desde" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"Esta ruta debería ser absoluta, excluyendo el nombre de dominio. Ejemplo: '/" +"events/search/'." + +msgid "redirect to" +msgstr "redirigir a" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"Esto puede ser una ruta absoluta (como antes) o una URL completa que empiece " +"con 'http://'." + +msgid "redirect" +msgstr "redirección" + +msgid "redirects" +msgstr "redirecciones" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es_MX/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es_MX/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e7f3b41 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es_MX/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es_MX/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es_MX/LC_MESSAGES/django.po new file mode 100644 index 0000000..73c1eb2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es_MX/LC_MESSAGES/django.po @@ -0,0 +1,53 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Abe Estrada, 2011 +# Alex Dzul , 2015 +# Jesús Bautista , 2019 +# zodman , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-12-26 16:57+0000\n" +"Last-Translator: Jesús Bautista \n" +"Language-Team: Spanish (Mexico) (http://www.transifex.com/django/django/" +"language/es_MX/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_MX\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Redirección" + +msgid "site" +msgstr "sitio" + +msgid "redirect from" +msgstr "redirigir desde" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Esta debería ser una ruta absoluta, excluyendo el nombre de dominio. Por " +"ejemplo: \"/events/search/\"." + +msgid "redirect to" +msgstr "redirigir a" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"“http://”." +msgstr "" +"Esto puede ser una ruta absoluta (como arriba) o una URL completa que " +"comience con \"http://\"." + +msgid "redirect" +msgstr "redirigir" + +msgid "redirects" +msgstr "redirecciona" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es_VE/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es_VE/LC_MESSAGES/django.mo new file mode 100644 index 0000000..32f6e8f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es_VE/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es_VE/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es_VE/LC_MESSAGES/django.po new file mode 100644 index 0000000..392e5d3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/es_VE/LC_MESSAGES/django.po @@ -0,0 +1,42 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:12+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Spanish (Venezuela) (http://www.transifex.com/projects/p/" +"django/language/es_VE/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_VE\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "" + +msgid "redirect from" +msgstr "" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" + +msgid "redirect to" +msgstr "" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" + +msgid "redirect" +msgstr "" + +msgid "redirects" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/et/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/et/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b9b37ba Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/et/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/et/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/et/LC_MESSAGES/django.po new file mode 100644 index 0000000..43ed079 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/et/LC_MESSAGES/django.po @@ -0,0 +1,54 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Janno Liivak , 2015 +# Martin , 2021 +# Marti Raudsepp , 2014 +# Ragnar Rebase , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-11-22 11:23+0000\n" +"Last-Translator: Martin \n" +"Language-Team: Estonian (http://www.transifex.com/django/django/language/" +"et/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: et\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Ümbersuunamised" + +msgid "site" +msgstr "sait" + +msgid "redirect from" +msgstr "ümbersuunatav asukoht" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"See peaks olema absoluutne asukoht, v.a. domeeninimi. Näide: “/events/" +"search/”." + +msgid "redirect to" +msgstr "suuna aadressile" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"See võib olla kas absoluutne asukoht (nagu ülemine) või täielik URL, mis " +"algab skeemiga nagu “https://”." + +msgid "redirect" +msgstr "suunamine" + +msgid "redirects" +msgstr "suunamised" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/eu/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/eu/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a223a93 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/eu/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/eu/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/eu/LC_MESSAGES/django.po new file mode 100644 index 0000000..ccd0ffe --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/eu/LC_MESSAGES/django.po @@ -0,0 +1,51 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Eneko Illarramendi , 2017 +# Jannis Leidel , 2011 +# Urtzi Odriozola , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-03-18 15:50+0000\n" +"Last-Translator: Urtzi Odriozola \n" +"Language-Team: Basque (http://www.transifex.com/django/django/language/eu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Redirects" + +msgid "site" +msgstr "webgunea" + +msgid "redirect from" +msgstr "nondik berbidalia" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Honek “bide” absolutua izan behar du, domeinu izena kenduta. Adibidez: “/" +"events/search/”." + +msgid "redirect to" +msgstr "Nora berbidali" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Hau “bide“ absolutua (goian bezala) edo URL osoa , “https://”-rekin hasiz, " +"izan daiteke." + +msgid "redirect" +msgstr "berbidali" + +msgid "redirects" +msgstr "berbidali" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/fa/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/fa/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2b46809 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/fa/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/fa/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/fa/LC_MESSAGES/django.po new file mode 100644 index 0000000..0200108 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/fa/LC_MESSAGES/django.po @@ -0,0 +1,50 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ali Nikneshan , 2015 +# Ali Vakilzade , 2015 +# Jannis Leidel , 2011 +# rahim agh , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-04-19 03:19+0000\n" +"Last-Translator: rahim agh \n" +"Language-Team: Persian (http://www.transifex.com/django/django/language/" +"fa/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fa\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Redirects" +msgstr "باز-ارسال‌ها" + +msgid "site" +msgstr "سایت" + +msgid "redirect from" +msgstr "فرم ارسال به نشانی جدید" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "می‌بایست یک مسیر مطلق و بدون نام دامنه باشد. مانند: '/events/search/'." + +msgid "redirect to" +msgstr "ارسال به نشانی" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"می‌تواند یک مسیر مطلق (همانند بالا) و یا یک آدرس کامل با 'http://‎' باشد." + +msgid "redirect" +msgstr "باز-ارسال" + +msgid "redirects" +msgstr "باز-ارسال‌ها" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/fi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/fi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..355a427 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/fi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/fi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/fi/LC_MESSAGES/django.po new file mode 100644 index 0000000..a19d41c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/fi/LC_MESSAGES/django.po @@ -0,0 +1,52 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Aarni Koskela, 2015,2020-2021 +# Jannis Leidel , 2011 +# Klaus Dahlén , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-04-14 12:18+0000\n" +"Last-Translator: Aarni Koskela\n" +"Language-Team: Finnish (http://www.transifex.com/django/django/language/" +"fi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Edelleenohjaukset" + +msgid "site" +msgstr "sivusto" + +msgid "redirect from" +msgstr "ohjaa osoitteesta" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Tässä on käytettävä absoluuttista polkua ilman verkkotunnusta. Esimerkki: \"/" +"tapahtumat/haku/\"." + +msgid "redirect to" +msgstr "ohjaa osoitteeseen" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Tässä on käytettävä joko absoluuttista polkua (kuten yllä) tai täydellistä " +"URL-osoitetta joka alkaa skeemalla (esim. \"https://\")." + +msgid "redirect" +msgstr "edelleenohjaus" + +msgid "redirects" +msgstr "edelleenohjaukset" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/fr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/fr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4902f97 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/fr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/fr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 0000000..a9fdb05 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,50 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Claude Paroz , 2014-2015,2019,2021 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-03-02 13:17+0000\n" +"Last-Translator: Bruno Brouard \n" +"Language-Team: French (http://www.transifex.com/django/django/language/fr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Redirects" +msgstr "Redirections" + +msgid "site" +msgstr "site" + +msgid "redirect from" +msgstr "redirigé depuis" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Ceci doit être un chemin absolu, sans nom de domaine. Par exemple, « /" +"evenements/rechercher/ »." + +msgid "redirect to" +msgstr "redirigé vers" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Ceci peut être soit un chemin absolu (voir ci-dessus) soit une URL complète " +"débutant par un protocole tel que « https:// »." + +msgid "redirect" +msgstr "redirection" + +msgid "redirects" +msgstr "redirections" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/fy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/fy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..489bbab Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/fy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/fy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/fy/LC_MESSAGES/django.po new file mode 100644 index 0000000..ecf5b4b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/fy/LC_MESSAGES/django.po @@ -0,0 +1,42 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:13+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Western Frisian (http://www.transifex.com/projects/p/django/" +"language/fy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fy\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "" + +msgid "redirect from" +msgstr "" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" + +msgid "redirect to" +msgstr "" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" + +msgid "redirect" +msgstr "" + +msgid "redirects" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ga/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ga/LC_MESSAGES/django.mo new file mode 100644 index 0000000..52e3967 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ga/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ga/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ga/LC_MESSAGES/django.po new file mode 100644 index 0000000..8ad2ce1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ga/LC_MESSAGES/django.po @@ -0,0 +1,48 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Luke Blaney , 2019 +# Michael Thornhill , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2019-06-22 21:46+0000\n" +"Last-Translator: Luke Blaney \n" +"Language-Team: Irish (http://www.transifex.com/django/django/language/ga/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ga\n" +"Plural-Forms: nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : " +"4);\n" + +msgid "Redirects" +msgstr "Athsheolaidh" + +msgid "site" +msgstr "suíomh" + +msgid "redirect from" +msgstr "atreoraigh ó" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "Teastaíonn dearbhchosán gan ainm fearainn. Sampla '/events/search/'." + +msgid "redirect to" +msgstr "atreoraigh go dtí" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "Is féidir dearbhchosán nó URL lán ag tosnú le 'http://'." + +msgid "redirect" +msgstr "athsheol" + +msgid "redirects" +msgstr "atreoraithe" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/gd/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/gd/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e611c50 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/gd/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/gd/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/gd/LC_MESSAGES/django.po new file mode 100644 index 0000000..232e298 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/gd/LC_MESSAGES/django.po @@ -0,0 +1,52 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# GunChleoc, 2015 +# GunChleoc, 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-07-15 10:46+0000\n" +"Last-Translator: GunChleoc\n" +"Language-Team: Gaelic, Scottish (http://www.transifex.com/django/django/" +"language/gd/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: gd\n" +"Plural-Forms: nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : " +"(n > 2 && n < 20) ? 2 : 3;\n" + +msgid "Redirects" +msgstr "Ath-stiùiridhean" + +msgid "site" +msgstr "làrach" + +msgid "redirect from" +msgstr "ath-stiùireadh o" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Bu chòir seo a bhith ’na shlighe absaloideach as aonais ainm na h-àrainne. " +"Ball-eisimpleir: “/tachartasan/lorg/”." + +msgid "redirect to" +msgstr "ath-stiùireadh gu" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Faodaidh seo a bhith ’na shlighe absaloideach (mar a tha gu h-àrd) no ’na " +"URL slàn a thòisicheas le sgeama, can “https://”." + +msgid "redirect" +msgstr "ath-stiùireadh" + +msgid "redirects" +msgstr "ath-stiùiridhean" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/gl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/gl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c64e8e1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/gl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/gl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/gl/LC_MESSAGES/django.po new file mode 100644 index 0000000..0ad209f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/gl/LC_MESSAGES/django.po @@ -0,0 +1,52 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# fasouto , 2017,2019 +# Jannis Leidel , 2011 +# X Bello , 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2023-04-24 18:32+0000\n" +"Last-Translator: X Bello , 2023\n" +"Language-Team: Galician (http://www.transifex.com/django/django/language/" +"gl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: gl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Redireccións" + +msgid "site" +msgstr "sitio" + +msgid "redirect from" +msgstr "orixe da redirección" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Ten que ser unha ruta absoluta, sen o nome de cominio. Por exemplo: “/" +"eventos/busca/”." + +msgid "redirect to" +msgstr "destino da redirección" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Pode ser unha ruta absoluta (coma a de enriba) ou un URL completo que empece " +"por “https://”." + +msgid "redirect" +msgstr "redirección" + +msgid "redirects" +msgstr "redireccións" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/he/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/he/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c8e13ce Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/he/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/he/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/he/LC_MESSAGES/django.po new file mode 100644 index 0000000..fc05599 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/he/LC_MESSAGES/django.po @@ -0,0 +1,49 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Meir Kriheli , 2014-2015,2020,2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2023-12-04 18:32+0000\n" +"Last-Translator: Meir Kriheli , 2014-2015,2020,2023\n" +"Language-Team: Hebrew (http://app.transifex.com/django/django/language/he/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: he\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % " +"1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;\n" + +msgid "Redirects" +msgstr "הפניות" + +msgid "site" +msgstr "אתר" + +msgid "redirect from" +msgstr "הפניה מ" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "זה אמור להיות נתיב מלא, ללא שם המתחם. לדוגמה: “/events/search/”." + +msgid "redirect to" +msgstr "הפניה אל" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"זה יכול להיות נתיב מלא (כמו לעיל) או כתובת URL מלאה שמתחילה בסכימה כגון " +"\"https://\"." + +msgid "redirect" +msgstr "הפניה" + +msgid "redirects" +msgstr "הפניות" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..367e4a9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hi/LC_MESSAGES/django.po new file mode 100644 index 0000000..44b447f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hi/LC_MESSAGES/django.po @@ -0,0 +1,49 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Sandeep Satavlekar , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Hindi (http://www.transifex.com/django/django/language/hi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "" + +msgid "site" +msgstr "" + +msgid "redirect from" +msgstr "से अनुप्रेषित" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"डोमेन नाम को छोड़कर बाकि सब संपूर्ण पथ होना चाहिए | उदाहरण: '/events/search'" + +msgid "redirect to" +msgstr "को अनुप्रेषित" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"यह या तो एक संपूर्ण पथ (जैसा ऊपर निर्दिष्ट किया हैं ) हो सकता है या 'http://' के साथ " +"शुरू होनेवाला पूर्ण URL हो सकता है." + +msgid "redirect" +msgstr "पुनः प्रेषित" + +msgid "redirects" +msgstr "पुनः प्रेषित" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..65b8363 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hr/LC_MESSAGES/django.po new file mode 100644 index 0000000..75a97c3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hr/LC_MESSAGES/django.po @@ -0,0 +1,52 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Mislav Cimperšak , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Mislav Cimperšak \n" +"Language-Team: Croatian (http://www.transifex.com/django/django/language/" +"hr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hr\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +msgid "Redirects" +msgstr "Preusmjeravanja" + +msgid "site" +msgstr "stranica" + +msgid "redirect from" +msgstr "preusmjeri od" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"Ovo bi trebala biti apsolutna putanja, bez imena domene. Primjer: '/events/" +"search/'." + +msgid "redirect to" +msgstr "preusmjeri na" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"Ovo može biti ili apsolutna putanja (kao gore) ili potpuni URL koji počinje " +"sa 'http://'" + +msgid "redirect" +msgstr "preusmjeri" + +msgid "redirects" +msgstr "preusmjeravanja" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hsb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hsb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4e0312e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hsb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hsb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hsb/LC_MESSAGES/django.po new file mode 100644 index 0000000..4d22553 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hsb/LC_MESSAGES/django.po @@ -0,0 +1,51 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Michael Wolf , 2016,2019,2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-02-01 22:11+0000\n" +"Last-Translator: Michael Wolf \n" +"Language-Team: Upper Sorbian (http://www.transifex.com/django/django/" +"language/hsb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hsb\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" + +msgid "Redirects" +msgstr "Dalesposrědkowanja" + +msgid "site" +msgstr "sydło" + +msgid "redirect from" +msgstr "dalesposrědkowanje wot" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"To měło absolutna šćežka być, nimo domenoweho mjena. Přikład: \"/events/" +"search/\"." + +msgid "redirect to" +msgstr "dalesposrědkowanje do" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"To móže pak absolutna šćežka być (kaž horjeka) pak dospołny URL, kotryž so z " +"\"https:/\" započina." + +msgid "redirect" +msgstr "dalesposrědkowanje" + +msgid "redirects" +msgstr "dalesposrědkowanja" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hu/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hu/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8321e8b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hu/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hu/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hu/LC_MESSAGES/django.po new file mode 100644 index 0000000..8e778d4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hu/LC_MESSAGES/django.po @@ -0,0 +1,51 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# András Veres-Szentkirályi, 2016,2021 +# Istvan Farkas , 2019 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-04-01 15:20+0000\n" +"Last-Translator: András Veres-Szentkirályi\n" +"Language-Team: Hungarian (http://www.transifex.com/django/django/language/" +"hu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Átirányítások" + +msgid "site" +msgstr "honlap" + +msgid "redirect from" +msgstr "átirányítva innen" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Abszolút útvonal legyen, a domain név nélkül. Például: \"/cikk/keres/\"." + +msgid "redirect to" +msgstr "átirányítva ide" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Lehet abszolút útvonal is (mint feljebb), vagy teljes URL, amely \"https://" +"\"-sel kezdődik." + +msgid "redirect" +msgstr "átirányítás" + +msgid "redirects" +msgstr "átirányít" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f141d22 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hy/LC_MESSAGES/django.po new file mode 100644 index 0000000..a4ab584 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/hy/LC_MESSAGES/django.po @@ -0,0 +1,49 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2018-11-01 20:45+0000\n" +"Last-Translator: Ruben Harutyunov \n" +"Language-Team: Armenian (http://www.transifex.com/django/django/language/" +"hy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hy\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Վերահղում" + +msgid "site" +msgstr "կայք" + +msgid "redirect from" +msgstr "վերահղում" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"Սա պետք է լինի բացարձակ ճանապարհ, բացի տիրույթի անվանից։ Օրինակ․ '/events/" +"search/'։" + +msgid "redirect to" +msgstr "վերահղում" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"Սա կարող է լինել բացարձակ ճանապարհ կամ ամբողջական URL, որը սկսվում է " +"'http://'֊ով։" + +msgid "redirect" +msgstr "վերահղում" + +msgid "redirects" +msgstr "վերահղումներ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ia/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ia/LC_MESSAGES/django.mo new file mode 100644 index 0000000..6b3b87b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ia/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ia/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ia/LC_MESSAGES/django.po new file mode 100644 index 0000000..c4f1b40 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ia/LC_MESSAGES/django.po @@ -0,0 +1,50 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Martijn Dekker , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 22:02+0000\n" +"Last-Translator: Martijn Dekker \n" +"Language-Team: Interlingua (http://www.transifex.com/django/django/language/" +"ia/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ia\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Redirectiones" + +msgid "site" +msgstr "sito" + +msgid "redirect from" +msgstr "formulario de redirection" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"Isto debe esser un cammino absolute, excludente le nomine de dominio. " +"Exemplo: '/eventos/recerca'." + +msgid "redirect to" +msgstr "rediriger a" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"Isto pote esser o un cammino absolute (como supra) o un URL complete " +"comenciante con 'http://'." + +msgid "redirect" +msgstr "redirection" + +msgid "redirects" +msgstr "redirectiones" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/id/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/id/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e253951 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/id/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/id/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/id/LC_MESSAGES/django.po new file mode 100644 index 0000000..4ef7ed1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/id/LC_MESSAGES/django.po @@ -0,0 +1,52 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Fery Setiawan , 2015,2021 +# rodin , 2011 +# rodin , 2015 +# sag᠎e , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-09-14 00:29+0000\n" +"Last-Translator: Fery Setiawan \n" +"Language-Team: Indonesian (http://www.transifex.com/django/django/language/" +"id/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: id\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Redirects" +msgstr "Pengalihan" + +msgid "site" +msgstr "situs" + +msgid "redirect from" +msgstr "pengalihan dari" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Harus berupa lokasi absolut, tanpa nama domain. Contoh: “/events/search/”." + +msgid "redirect to" +msgstr "pengalihan ke" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Ini dapat berupa jalur mutlak (seperti diatas) atau URL lengkap diawali " +"dengan skema seperti “https://”." + +msgid "redirect" +msgstr "pengalihan" + +msgid "redirects" +msgstr "pengalihan" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/io/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/io/LC_MESSAGES/django.mo new file mode 100644 index 0000000..89f3bde Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/io/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/io/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/io/LC_MESSAGES/django.po new file mode 100644 index 0000000..b79e1d3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/io/LC_MESSAGES/django.po @@ -0,0 +1,48 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Viko Bartero , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-20 01:58+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Ido (http://www.transifex.com/django/django/language/io/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: io\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "" + +msgid "site" +msgstr "" + +msgid "redirect from" +msgstr "ridirektar de" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"Ico devas esar absoluta voyo, exkluzante la domeno nomo. Exemple: \"/eventi/" +"serchado/\"." + +msgid "redirect to" +msgstr "ridirektar a" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"Ico devas esar absoluta voyo (kam supre) o kompleta URL uzante \"http://\"." + +msgid "redirect" +msgstr "ridirekturo" + +msgid "redirects" +msgstr "ridirekturi" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/is/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/is/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5fa353f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/is/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/is/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/is/LC_MESSAGES/django.po new file mode 100644 index 0000000..29be147 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/is/LC_MESSAGES/django.po @@ -0,0 +1,49 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Thordur Sigurdsson , 2016,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-11-20 05:10+0000\n" +"Last-Translator: Thordur Sigurdsson \n" +"Language-Team: Icelandic (http://www.transifex.com/django/django/language/" +"is/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: is\n" +"Plural-Forms: nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);\n" + +msgid "Redirects" +msgstr "" + +msgid "site" +msgstr "vefur" + +msgid "redirect from" +msgstr "vísun frá" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "Þetta þarf að vera full slóð án lénsins. Dæmi: „/events/search/“." + +msgid "redirect to" +msgstr "vísa á" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"“http://”." +msgstr "" +"Þetta getur verið full slóð (eins og hér að ofan) eða veffang með „http://“ " +"fremst." + +msgid "redirect" +msgstr "vísun" + +msgid "redirects" +msgstr "vísanir" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/it/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/it/LC_MESSAGES/django.mo new file mode 100644 index 0000000..097ab6b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/it/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/it/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/it/LC_MESSAGES/django.po new file mode 100644 index 0000000..a201ce7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/it/LC_MESSAGES/django.po @@ -0,0 +1,53 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Marco Bonetti, 2014 +# Mirco Grillo , 2020 +# palmux , 2014-2015,2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-01-15 16:04+0000\n" +"Last-Translator: palmux \n" +"Language-Team: Italian (http://www.transifex.com/django/django/language/" +"it/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: it\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Redirezioni" + +msgid "site" +msgstr "sito" + +msgid "redirect from" +msgstr "redirezione da" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Deve essere un percorso assoluto, senza nome a dominio. Esempio: '/events/" +"search/'." + +msgid "redirect to" +msgstr "redirezione verso" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Può essere un percorso assoluto (come sopra) o un URL completo che inizia " +"con \"https: //\"." + +msgid "redirect" +msgstr "redirezione" + +msgid "redirects" +msgstr "redirezioni" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ja/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ja/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3b223b6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ja/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ja/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ja/LC_MESSAGES/django.po new file mode 100644 index 0000000..8c6ab2b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ja/LC_MESSAGES/django.po @@ -0,0 +1,51 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Goto Hayato , 2021 +# Jannis Leidel , 2011 +# Shinya Okano , 2014-2015 +# Takuya N , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-07-02 13:57+0000\n" +"Last-Translator: Goto Hayato \n" +"Language-Team: Japanese (http://www.transifex.com/django/django/language/" +"ja/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ja\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Redirects" +msgstr "リダイレクト" + +msgid "site" +msgstr "サイト" + +msgid "redirect from" +msgstr "リダイレクト元" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "“/events/search/” のように、ドメイン名を除いた絶対パスにします。 " + +msgid "redirect to" +msgstr "リダイレクト先" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"これは上のような絶対パスにも「 https:// 」のようなスキームで始まる完全な URL " +"にもすることができます。" + +msgid "redirect" +msgstr "リダイレクト" + +msgid "redirects" +msgstr "リダイレクト" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ka/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ka/LC_MESSAGES/django.mo new file mode 100644 index 0000000..475955e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ka/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ka/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ka/LC_MESSAGES/django.po new file mode 100644 index 0000000..bf76c7a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ka/LC_MESSAGES/django.po @@ -0,0 +1,50 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# André Bouatchidzé , 2015 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Georgian (http://www.transifex.com/django/django/language/" +"ka/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ka\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +msgid "Redirects" +msgstr "გადამისამართებები" + +msgid "site" +msgstr "" + +msgid "redirect from" +msgstr "გადამისამართება გვერდიდან" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"უნდა იყოს აბსოლუტური გზა დომენის სახელის გარეშე. მაგალითი: '/events/search/'." + +msgid "redirect to" +msgstr "გადამისამართება გვერდზე" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"უნდა იყოს აბსოლუტური გზა (როგორც ზემოთ) ან სრული URL, რომელიც იწყება " +"'http://' სტრიქონით." + +msgid "redirect" +msgstr "გადამისამართება" + +msgid "redirects" +msgstr "გადამისამართებები" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/kab/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/kab/LC_MESSAGES/django.mo new file mode 100644 index 0000000..63b7782 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/kab/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/kab/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/kab/LC_MESSAGES/django.po new file mode 100644 index 0000000..437f1a2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/kab/LC_MESSAGES/django.po @@ -0,0 +1,45 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-10-09 12:26+0000\n" +"Last-Translator: Slimane Amiri\n" +"Language-Team: Kabyle (http://www.transifex.com/django/django/language/" +"kab/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kab\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Iceggiɛen" + +msgid "site" +msgstr "asmel" + +msgid "redirect from" +msgstr "yettwaceggeɛ seg" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" + +msgid "redirect to" +msgstr "aceggeɛ ar" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" + +msgid "redirect" +msgstr "aceggeɛ" + +msgid "redirects" +msgstr "iceggiɛen" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/kk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/kk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..fb9d36f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/kk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/kk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/kk/LC_MESSAGES/django.po new file mode 100644 index 0000000..8c6af97 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/kk/LC_MESSAGES/django.po @@ -0,0 +1,48 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Leo Trubach , 2017 +# yun_man_ger , 2011 +# Zhazira , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Leo Trubach \n" +"Language-Team: Kazakh (http://www.transifex.com/django/django/language/kk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kk\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +msgid "Redirects" +msgstr "Қайта бағыттаулар" + +msgid "site" +msgstr "сайт" + +msgid "redirect from" +msgstr " бағыттау (қайдан)" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "Бұл домен атаусыз абсолюттік жол болу керек. Мысал: '/events/search/'." + +msgid "redirect to" +msgstr "бағыттау (қайда)" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"Бұл абсолюттік жол немесе 'http://'-мен басталатын толық URL бола алады." + +msgid "redirect" +msgstr "қайта бағыттау" + +msgid "redirects" +msgstr "қайта бағыттаулар" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/km/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/km/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e76f40f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/km/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/km/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/km/LC_MESSAGES/django.po new file mode 100644 index 0000000..75cf301 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/km/LC_MESSAGES/django.po @@ -0,0 +1,47 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Khmer (http://www.transifex.com/django/django/language/km/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: km\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Redirects" +msgstr "" + +msgid "site" +msgstr "" + +msgid "redirect from" +msgstr "នាំចេញពី" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"គួរតែជាផ្លូវពេញ (absolute path) ហើយមិនបញ្ជូលឈ្មោះ ដមែន (domain name​)។​ឧទាហរណ៍ '/" +"events/search/'។" + +msgid "redirect to" +msgstr "នាំចេញទៅ" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "អាចជាផ្លូវពេញ (absolute path) ឬក៏ URL ទាំងមូលដែលចាប់ផ្តើមជាមួយ 'http://'។" + +msgid "redirect" +msgstr "នាំចេញ" + +msgid "redirects" +msgstr "នាំចេញ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/kn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/kn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..24a289a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/kn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/kn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/kn/LC_MESSAGES/django.po new file mode 100644 index 0000000..bfeadbe --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/kn/LC_MESSAGES/django.po @@ -0,0 +1,47 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Rohith PR, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-08-03 10:56+0000\n" +"Last-Translator: Rohith PR\n" +"Language-Team: Kannada (http://www.transifex.com/django/django/language/" +"kn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kn\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Redirects" +msgstr "" + +msgid "site" +msgstr "ತಾಣ" + +msgid "redirect from" +msgstr "ಪುನರ್ನಿರ್ದೇಶನ ಇಲ್ಲಿಂದ->" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" + +msgid "redirect to" +msgstr "ಪುನರ್ನಿರ್ದೇಶನ ಇಲ್ಲಿಗೆ->" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" + +msgid "redirect" +msgstr "ಪುನರ್ನಿರ್ದೇಶನ" + +msgid "redirects" +msgstr "ಪುನರ್ನಿರ್ದೇಶನ(ಗಳು)" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ko/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ko/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d0a6f6d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ko/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ko/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ko/LC_MESSAGES/django.po new file mode 100644 index 0000000..2f2e380 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ko/LC_MESSAGES/django.po @@ -0,0 +1,55 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jiyoon, Ha , 2016 +# Jannis Leidel , 2011 +# Jay Oh , 2020 +# JunGu Kang , 2015 +# Kwangho Kim , 2019 +# minsung kang, 2015 +# 정훈 이, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-12-24 18:32+0000\n" +"Last-Translator: 정훈 이\n" +"Language-Team: Korean (http://www.transifex.com/django/django/language/ko/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ko\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Redirects" +msgstr "리다이렉트" + +msgid "site" +msgstr "사이트" + +msgid "redirect from" +msgstr "에서 리다이렉트" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"도메인 이름을 제외한 절대 경로여야 합니다.\n" +"예제: \"/events/search/\"." + +msgid "redirect to" +msgstr "(으)로 리다이렉트" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"(위와 같은) 절대경로 혹은 \"https://\" 같은 식으로 시작하는 완전한 URL 모두 " +"가능합니다." + +msgid "redirect" +msgstr "리다이렉트" + +msgid "redirects" +msgstr "리다이렉트" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ky/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ky/LC_MESSAGES/django.mo new file mode 100644 index 0000000..99bc33a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ky/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ky/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ky/LC_MESSAGES/django.po new file mode 100644 index 0000000..892f148 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ky/LC_MESSAGES/django.po @@ -0,0 +1,50 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Soyuzbek Orozbek uulu , 2020-2021 +# Soyuzbek Orozbek uulu , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-04-02 11:57+0000\n" +"Last-Translator: Soyuzbek Orozbek uulu \n" +"Language-Team: Kyrgyz (http://www.transifex.com/django/django/language/ky/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ky\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Redirects" +msgstr "Буруулар" + +msgid "site" +msgstr "сайт" + +msgid "redirect from" +msgstr "бурулуп келатат" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Бул доменди камтыбаган абсолюттук жол болуусу керек. Мисалы: “/events/" +"search/”." + +msgid "redirect to" +msgstr "Бул жакка бар" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Бул абсолюттук жол (жогорудай) же толук \"https://\" сыяктуу схема менен " +"башталган URL боло алат. " + +msgid "redirect" +msgstr "буруу" + +msgid "redirects" +msgstr "буруулар" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/lb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/lb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5b7937f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/lb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/lb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/lb/LC_MESSAGES/django.po new file mode 100644 index 0000000..c97c1c7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/lb/LC_MESSAGES/django.po @@ -0,0 +1,42 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:12+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Luxembourgish (http://www.transifex.com/projects/p/django/" +"language/lb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "" + +msgid "redirect from" +msgstr "" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" + +msgid "redirect to" +msgstr "" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" + +msgid "redirect" +msgstr "" + +msgid "redirects" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/lt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/lt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..294ce4c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/lt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/lt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/lt/LC_MESSAGES/django.po new file mode 100644 index 0000000..811c248 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/lt/LC_MESSAGES/django.po @@ -0,0 +1,53 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Matas Dailyda , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Matas Dailyda \n" +"Language-Team: Lithuanian (http://www.transifex.com/django/django/language/" +"lt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lt\n" +"Plural-Forms: nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < " +"11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? " +"1 : n % 1 != 0 ? 2: 3);\n" + +msgid "Redirects" +msgstr "Nukreipimai" + +msgid "site" +msgstr "tinklalapis" + +msgid "redirect from" +msgstr "nukreiptas (redirect) iš" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"Turi būti absoliutus adresas neįtraukiant domaino. Pavyzdžiui: '/events/" +"search/'." + +msgid "redirect to" +msgstr "nukreipti(redirect) į" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"Gali būti absoliutus adresas (kaip viršuj) arba pilnas URL pradedant " +"'http://'." + +msgid "redirect" +msgstr "nukreipti" + +msgid "redirects" +msgstr "nukreipia" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/lv/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/lv/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d204bf6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/lv/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/lv/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/lv/LC_MESSAGES/django.po new file mode 100644 index 0000000..89b3001 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/lv/LC_MESSAGES/django.po @@ -0,0 +1,53 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# NullIsNot0 , 2019,2021 +# peterisb , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-01-25 22:49+0000\n" +"Last-Translator: NullIsNot0 \n" +"Language-Team: Latvian (http://www.transifex.com/django/django/language/" +"lv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lv\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : " +"2);\n" + +msgid "Redirects" +msgstr "Pārvirzīšanas" + +msgid "site" +msgstr "vietne" + +msgid "redirect from" +msgstr "pārvirzīt(redirect) no" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Tam jābūt absolūtajam ceļam, atskaitot domēna vārdu. Piemēram: \"/notikumi/" +"meklet/\"." + +msgid "redirect to" +msgstr "pārvirzīt(redirect) uz" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Šis var būt vai nu absolūtais ceļš (kā augstāk), vai pilnais URL, kas sākas " +"ar \"https://\"." + +msgid "redirect" +msgstr "pārvirzīt" + +msgid "redirects" +msgstr "pārvirzījumi" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/mk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/mk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8353fbd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/mk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/mk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/mk/LC_MESSAGES/django.po new file mode 100644 index 0000000..57e8324 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/mk/LC_MESSAGES/django.po @@ -0,0 +1,52 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Vasil Vangelovski , 2016 +# Vasil Vangelovski , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Vasil Vangelovski \n" +"Language-Team: Macedonian (http://www.transifex.com/django/django/language/" +"mk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mk\n" +"Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n" + +msgid "Redirects" +msgstr "Пренасочувања" + +msgid "site" +msgstr "сајт" + +msgid "redirect from" +msgstr "пренасочи од" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"Ова треба да биде апсолутна патека без името на домејнот. На пр. „/nastani/" +"prebaraj/“." + +msgid "redirect to" +msgstr "пренасочи кон" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"Ова може да биде или апсолутна патека (како погоре) или цела адреса што " +"почнува со „http://“." + +msgid "redirect" +msgstr "пренасочување" + +msgid "redirects" +msgstr "пренасочувања" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ml/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ml/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5f3537a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ml/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ml/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ml/LC_MESSAGES/django.po new file mode 100644 index 0000000..dbfbca6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ml/LC_MESSAGES/django.po @@ -0,0 +1,51 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Hrishikesh , 2019 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2019-03-03 10:36+0000\n" +"Last-Translator: Hrishikesh \n" +"Language-Team: Malayalam (http://www.transifex.com/django/django/language/" +"ml/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ml\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "തിരിച്ചുവിടലുകൾ" + +msgid "site" +msgstr "സൈറ്റ്" + +msgid "redirect from" +msgstr "എവിടെ നിന്ന്" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"ഇത് ഡൊമൈനിന്റെ പേര് ഉൾപ്പെടാതെയുള്ള ഒരു അബ്സല്യൂട്ട് പാത്ത് ആയിരിക്കണം. ഉദാഹരണം: '/events/" +"search/'." + +msgid "redirect to" +msgstr "എങ്ങോട്ട്" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"ഇതൊരു അബ്സല്യൂട്ട് പാത്തോ (മുകളിലത്തേതു പോലെ) 'http://' എന്നു തുടങ്ങുന്ന ഒരു മുഴുവൻ യു.ആർ.എല്ലോ " +"ആവാം" + +msgid "redirect" +msgstr "തിരിച്ചുവിടൽ" + +msgid "redirects" +msgstr "തിരിച്ചുവിടലുകൾ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/mn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/mn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ecd0a04 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/mn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/mn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/mn/LC_MESSAGES/django.po new file mode 100644 index 0000000..3f474c4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/mn/LC_MESSAGES/django.po @@ -0,0 +1,52 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bayarkhuu Bataa, 2014 +# Jannis Leidel , 2011 +# Анхбаяр Анхаа , 2011,2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Анхбаяр Анхаа \n" +"Language-Team: Mongolian (http://www.transifex.com/django/django/language/" +"mn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Чиглүүлэлтүүд" + +msgid "site" +msgstr "сайт" + +msgid "redirect from" +msgstr "redirect хаанаас" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"Энэ нь домэйн нэр агуулаагүй абсолют зам байх ёстой. Жишээ нь: '/events/" +"search/'." + +msgid "redirect to" +msgstr "redirect хаашаа" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"Энэ нь (дээрхийн нэгэн адил) абсолют зам юм уу 'http://' гэж эхэлсэн бүтэн " +"URL байж болно. " + +msgid "redirect" +msgstr "redirect" + +msgid "redirects" +msgstr "redirect-ууд" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/mr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/mr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..183b3d1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/mr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/mr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/mr/LC_MESSAGES/django.po new file mode 100644 index 0000000..5477dd9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/mr/LC_MESSAGES/django.po @@ -0,0 +1,42 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:12+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Marathi (http://www.transifex.com/projects/p/django/language/" +"mr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mr\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "" + +msgid "redirect from" +msgstr "" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" + +msgid "redirect to" +msgstr "" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" + +msgid "redirect" +msgstr "" + +msgid "redirects" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ms/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ms/LC_MESSAGES/django.mo new file mode 100644 index 0000000..54eddda Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ms/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ms/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ms/LC_MESSAGES/django.po new file mode 100644 index 0000000..ef67357 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ms/LC_MESSAGES/django.po @@ -0,0 +1,49 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jafry Hisham, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-11-16 12:45+0000\n" +"Last-Translator: Jafry Hisham\n" +"Language-Team: Malay (http://www.transifex.com/django/django/language/ms/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ms\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Redirects" +msgstr "Lencongan-lencongan" + +msgid "site" +msgstr "laman" + +msgid "redirect from" +msgstr "borang lencongan" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Ini sepatutnya laluan mutlak, tidak termasuk nama domain. Contoh: \"/" +"peristiwa/cari/\"" + +msgid "redirect to" +msgstr "Lencong ke" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Ini boleh menjadi laluan mutlak (seperti diatas) atau URL penuh bermula " +"dengan skema seperti \"https://\"." + +msgid "redirect" +msgstr "lencongan" + +msgid "redirects" +msgstr "lencongan-lencongan" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/my/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/my/LC_MESSAGES/django.mo new file mode 100644 index 0000000..38a9b9f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/my/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/my/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/my/LC_MESSAGES/django.po new file mode 100644 index 0000000..dd18026 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/my/LC_MESSAGES/django.po @@ -0,0 +1,46 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Yhal Htet Aung , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 22:02+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Burmese (http://www.transifex.com/django/django/language/" +"my/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: my\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Redirects" +msgstr "ပြန်လည်ဝင်ရောက်များ" + +msgid "site" +msgstr "" + +msgid "redirect from" +msgstr "" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" + +msgid "redirect to" +msgstr "" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" + +msgid "redirect" +msgstr "" + +msgid "redirects" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/nb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/nb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0c2d5a1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/nb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/nb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/nb/LC_MESSAGES/django.po new file mode 100644 index 0000000..22579b2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/nb/LC_MESSAGES/django.po @@ -0,0 +1,54 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Jon, 2015 +# Jon, 2014 +# Jon, 2020-2021 +# Sigurd Gartmann , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-03-18 14:19+0000\n" +"Last-Translator: Jon\n" +"Language-Team: Norwegian Bokmål (http://www.transifex.com/django/django/" +"language/nb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Omadresseringer" + +msgid "site" +msgstr "nettsted" + +msgid "redirect from" +msgstr "omadresser fra" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Dette bør være en fullstendig sti uten domenenavn. Eksempel: \"/hendelser/" +"finn/\"." + +msgid "redirect to" +msgstr "omadresser til" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Dette kan være enten en full sti (som over) eller en full URL som starter " +"med en protokoll som “https://”." + +msgid "redirect" +msgstr "omadressering" + +msgid "redirects" +msgstr "omadresseringer" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ne/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ne/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b2c1863 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ne/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ne/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ne/LC_MESSAGES/django.po new file mode 100644 index 0000000..9a4164f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ne/LC_MESSAGES/django.po @@ -0,0 +1,47 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Paras Nath Chaudhary , 2012 +# Sagar Chalise , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Sagar Chalise \n" +"Language-Team: Nepali (http://www.transifex.com/django/django/language/ne/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ne\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "बाटो फेर्ने" + +msgid "site" +msgstr "साईट" + +msgid "redirect from" +msgstr "बाटो फेर्ने फरम" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "यो डोमेन नाम छोडेर, पूर्ण बाटो हुनुपर्छ । उदाहरण : '/events/search'" + +msgid "redirect to" +msgstr "बाटो फेर्नेको लागि" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"यो कि (माथीको जस्तै )पूर्ण बाटो हुनुपर्छ वा 'http://' बाट सुरुभएको पुरा हुनुपर्छ । " + +msgid "redirect" +msgstr "बाटो फेर्ने" + +msgid "redirects" +msgstr "बाटो फेर्ने" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/nl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/nl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e573bcd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/nl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/nl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/nl/LC_MESSAGES/django.po new file mode 100644 index 0000000..da242f7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/nl/LC_MESSAGES/django.po @@ -0,0 +1,52 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ilja Maas , 2015 +# Jannis Leidel , 2011 +# 8de006b1b0894aab6aef71979dcd8bd6_5c6b207 , 2015 +# Tonnes , 2019,2022 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2022-07-24 18:32+0000\n" +"Last-Translator: Tonnes \n" +"Language-Team: Dutch (http://www.transifex.com/django/django/language/nl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Omleidingen" + +msgid "site" +msgstr "website" + +msgid "redirect from" +msgstr "omgeleid via" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Dit moet een absoluut pad zijn, zonder de domeinnaam. Voorbeeld: ‘/events/" +"search/’." + +msgid "redirect to" +msgstr "omleiden naar" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Dit kan een absoluut pad zijn (zoals hierboven), of een volledige URL " +"beginnend met een schema, zoals ‘https://’." + +msgid "redirect" +msgstr "omleiding" + +msgid "redirects" +msgstr "omleidingen" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/nn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/nn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8eadeb0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/nn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/nn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/nn/LC_MESSAGES/django.po new file mode 100644 index 0000000..363e0ff --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/nn/LC_MESSAGES/django.po @@ -0,0 +1,50 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Sivert Olstad, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-11-11 10:05+0000\n" +"Last-Translator: Sivert Olstad\n" +"Language-Team: Norwegian Nynorsk (http://www.transifex.com/django/django/" +"language/nn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Omadresseringar" + +msgid "site" +msgstr "nettstad" + +msgid "redirect from" +msgstr "omadresser frå" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Dette bør vere ein fullstendig sti utan domenenavn. Døme: “/hendingar/finn/”." + +msgid "redirect to" +msgstr "omadresser til" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Dette kan enten vere ein fullstendig sti (som over), eller ei fullstendig " +"nettadresse som startar med eit skjema som “https://”." + +msgid "redirect" +msgstr "omadressering" + +msgid "redirects" +msgstr "omadresseringar" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/os/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/os/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f80ae2e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/os/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/os/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/os/LC_MESSAGES/django.po new file mode 100644 index 0000000..26f4042 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/os/LC_MESSAGES/django.po @@ -0,0 +1,49 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Soslan Khubulov , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:58+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Ossetic (http://www.transifex.com/django/django/language/" +"os/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: os\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "" + +msgid "site" +msgstr "" + +msgid "redirect from" +msgstr "арвитӕны формӕ" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"Ай хъуамӕ уа ӕнӕ домены ном абсолютон фӕт. Цӕвиддон: '/events/search/'." + +msgid "redirect to" +msgstr "арвитӕн ардӕм" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"Ай гӕнӕн ис уа абсолютон фӕт (куыд уӕлийӕ) кӕнӕ 'http://'-йӕ байдайгӕ " +"ӕнӕхъӕн URL." + +msgid "redirect" +msgstr "арвитӕн" + +msgid "redirects" +msgstr "арвитӕнтӕ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/pa/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/pa/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0481d7e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/pa/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/pa/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/pa/LC_MESSAGES/django.po new file mode 100644 index 0000000..a82e053 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/pa/LC_MESSAGES/django.po @@ -0,0 +1,47 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# A S Alam , 2013 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Panjabi (Punjabi) (http://www.transifex.com/django/django/" +"language/pa/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pa\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "" + +msgid "site" +msgstr "" + +msgid "redirect from" +msgstr "ਇਸ ਤੋਂ ਮੁੜ-ਡਾਇਰੈਕਟ" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" + +msgid "redirect to" +msgstr "ਇਸ ਵੱਲ ਡਾਇਰੈਕਟ" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" + +msgid "redirect" +msgstr "ਰੀ-ਡਾਇਰੈਕਟ" + +msgid "redirects" +msgstr "ਮੁੜ-ਡਾਇਰੈਕਟ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/pl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/pl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..113b2eb Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/pl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/pl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/pl/LC_MESSAGES/django.po new file mode 100644 index 0000000..9afa71c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/pl/LC_MESSAGES/django.po @@ -0,0 +1,54 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Janusz Harkot , 2014-2015 +# m_aciek , 2019,2021 +# Tomasz Kajtoch , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-09-06 21:50+0000\n" +"Last-Translator: m_aciek \n" +"Language-Team: Polish (http://www.transifex.com/django/django/language/pl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pl\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n" +"%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n" +"%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" + +msgid "Redirects" +msgstr "Przekierowania" + +msgid "site" +msgstr "strona" + +msgid "redirect from" +msgstr "przekieruj z" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Podaj ścieżkę bezwzględną pomijając nazwę domeny. Na przykład „/events/" +"search/”." + +msgid "redirect to" +msgstr "przekieruj na" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Może to być ścieżka bezwzględna (jak powyżej) lub pełny URL rozpoczynający " +"się schematem takim jak \"https://\"." + +msgid "redirect" +msgstr "przekierowanie" + +msgid "redirects" +msgstr "przekierowania" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/pt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/pt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..46be519 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/pt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/pt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/pt/LC_MESSAGES/django.po new file mode 100644 index 0000000..a557632 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/pt/LC_MESSAGES/django.po @@ -0,0 +1,52 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Nuno Mariz , 2011,2015 +# Raúl Pedro Fernandes Santos, 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Nuno Mariz \n" +"Language-Team: Portuguese (http://www.transifex.com/django/django/language/" +"pt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Redireccionamentos" + +msgid "site" +msgstr "site" + +msgid "redirect from" +msgstr "redirecionar de" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"Isto deverá ser um caminho absoluto, excluindo o domínio. Exemplo: '/events/" +"search/'." + +msgid "redirect to" +msgstr "redirecionar para" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"Isto poderá ser um caminho absoluto (como acima) ou um URL completo começado " +"por 'http://'." + +msgid "redirect" +msgstr "redirecionar" + +msgid "redirects" +msgstr "redireciona" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/pt_BR/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/pt_BR/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2eecaf9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/pt_BR/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/pt_BR/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/pt_BR/LC_MESSAGES/django.po new file mode 100644 index 0000000..83f9275 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/pt_BR/LC_MESSAGES/django.po @@ -0,0 +1,56 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Allisson Azevedo , 2014 +# Amanda Savluchinske , 2019 +# semente, 2013 +# Jannis Leidel , 2011 +# Lucas Infante , 2015 +# Rafael Fontenelle , 2021 +# R.J Lelis , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-01-17 05:46+0000\n" +"Last-Translator: Rafael Fontenelle \n" +"Language-Team: Portuguese (Brazil) (http://www.transifex.com/django/django/" +"language/pt_BR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt_BR\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Redirects" +msgstr "Redirecionamentos" + +msgid "site" +msgstr "site" + +msgid "redirect from" +msgstr "redirecionar de" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Este deve ser um caminho absoluto, excluindo o nome do domínio. Exemplo: \"/" +"events/search/\"." + +msgid "redirect to" +msgstr "redirecionar para" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Este pode ser um caminho absoluto (como acima) ou uma URL completa começando " +"com um esquema como \"https://\"." + +msgid "redirect" +msgstr "redirecionamento" + +msgid "redirects" +msgstr "redirecionamentos" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ro/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ro/LC_MESSAGES/django.mo new file mode 100644 index 0000000..bb9da5b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ro/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ro/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ro/LC_MESSAGES/django.po new file mode 100644 index 0000000..fbd2c98 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ro/LC_MESSAGES/django.po @@ -0,0 +1,54 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Daniel Ursache-Dogariu, 2011 +# Eugenol Man , 2020 +# Jannis Leidel , 2011 +# Razvan Stefanescu , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-07-15 11:20+0000\n" +"Last-Translator: Eugenol Man \n" +"Language-Team: Romanian (http://www.transifex.com/django/django/language/" +"ro/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ro\n" +"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?" +"2:1));\n" + +msgid "Redirects" +msgstr "Redirecționări" + +msgid "site" +msgstr "site" + +msgid "redirect from" +msgstr "redirecționat de la " + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Trebuie sa fie o cale absoluta, exeptand numele domeniului. Exemplu: “/" +"events/search/”." + +msgid "redirect to" +msgstr "redirecționat către" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"“http://”." +msgstr "" +"Poate fi cale absolută (ca mai sus) sau link URL complet, începând cu " +"“http://”." + +msgid "redirect" +msgstr "redirecționare" + +msgid "redirects" +msgstr "redirecționări" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ru/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ru/LC_MESSAGES/django.mo new file mode 100644 index 0000000..12be90b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ru/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ru/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ru/LC_MESSAGES/django.po new file mode 100644 index 0000000..7a95bbe --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ru/LC_MESSAGES/django.po @@ -0,0 +1,53 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# crazyzubr , 2020 +# Jannis Leidel , 2011 +# Panasoft, 2021 +# Алексей Борискин , 2014-2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-03-16 22:53+0000\n" +"Last-Translator: Panasoft\n" +"Language-Team: Russian (http://www.transifex.com/django/django/language/" +"ru/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ru\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n" +"%100>=11 && n%100<=14)? 2 : 3);\n" + +msgid "Redirects" +msgstr "Перенаправления" + +msgid "site" +msgstr "сайт" + +msgid "redirect from" +msgstr "перенаправить с" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "Нужно указать корневой относительный путь. Пример: “/events/search/”." + +msgid "redirect to" +msgstr "перенаправить на" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Это может быть либо абсолютный путь (как указано выше), либо полный URL-" +"адрес, начинающийся со схемы, такой как «https://»." + +msgid "redirect" +msgstr "перенаправление" + +msgid "redirects" +msgstr "перенаправления" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..16623d8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sk/LC_MESSAGES/django.po new file mode 100644 index 0000000..07ea9c9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sk/LC_MESSAGES/django.po @@ -0,0 +1,53 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Martin Tóth , 2017,2023 +# Peter Kuma, 2021 +# supowski , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2023-12-04 18:32+0000\n" +"Last-Translator: Martin Tóth , 2017,2023\n" +"Language-Team: Slovak (http://app.transifex.com/django/django/language/sk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n " +">= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);\n" + +msgid "Redirects" +msgstr "Presmerovania" + +msgid "site" +msgstr "sídlo" + +msgid "redirect from" +msgstr "presmerovať z" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Toto by sa mala byť absolútna cesta bez názvu domény. Napríklad: „/events/" +"search/“." + +msgid "redirect to" +msgstr "presmerovať na" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Toto môže byť buď absolútna cesta (ako vyššie), alebo úplné URL začínajúce " +"schémou ako „https://“." + +msgid "redirect" +msgstr "presmerovanie" + +msgid "redirects" +msgstr "presmerovania" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..41e11af Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sl/LC_MESSAGES/django.po new file mode 100644 index 0000000..e8da74c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sl/LC_MESSAGES/django.po @@ -0,0 +1,52 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# zejn , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Primož Verdnik \n" +"Language-Team: Slovenian (http://www.transifex.com/django/django/language/" +"sl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sl\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" + +msgid "Redirects" +msgstr "Preusmeritve" + +msgid "site" +msgstr "stran" + +msgid "redirect from" +msgstr "preusmeri iz" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"Pot mora biti navedena absolutno in brez imena domene. Primer: '/events/" +"search/'." + +msgid "redirect to" +msgstr "preusmeri na" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"Pot je lahko navedena absolutno (kot zgoraj) ali pa kot popoln naslov URL, " +"začet z 'http://'." + +msgid "redirect" +msgstr "preusmeri" + +msgid "redirects" +msgstr "preusmeritve" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sq/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sq/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0d944b5 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sq/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sq/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sq/LC_MESSAGES/django.po new file mode 100644 index 0000000..5f5b7f6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sq/LC_MESSAGES/django.po @@ -0,0 +1,52 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Besnik Bleta , 2011 +# Besnik Bleta , 2021 +# Besnik Bleta , 2015,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-01-15 13:55+0000\n" +"Last-Translator: Besnik Bleta \n" +"Language-Team: Albanian (http://www.transifex.com/django/django/language/" +"sq/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sq\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Ridrejtime" + +msgid "site" +msgstr "sajt" + +msgid "redirect from" +msgstr "ridrejtim prej" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Ky do të duhej të ishte shteg absolut, pa emrin e përkatësisë. Për shembull: " +"“/ngjarje/kërkim/”." + +msgid "redirect to" +msgstr "ridrejtim te" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Ky mund të jetë ose një shteg absolut (si më sipër), ose një URL e plotë që " +"fillon me një skemë të tillë si “http://”." + +msgid "redirect" +msgstr "ridrejtim" + +msgid "redirects" +msgstr "ridrejtime" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0054565 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sr/LC_MESSAGES/django.po new file mode 100644 index 0000000..bf812eb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sr/LC_MESSAGES/django.po @@ -0,0 +1,53 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Branko Kokanovic , 2018 +# Igor Jerosimić, 2020-2021 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-01-15 17:04+0000\n" +"Last-Translator: Igor Jerosimić\n" +"Language-Team: Serbian (http://www.transifex.com/django/django/language/" +"sr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Redirects" +msgstr "Преусмеравања" + +msgid "site" +msgstr "сајт" + +msgid "redirect from" +msgstr "преусмерен са" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Ово треба да буде апсолутна путања, искључујући име домена. Пример: “/events/" +"search/”." + +msgid "redirect to" +msgstr "преусмери ка" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Ово може да буде апсолутна путања (као изнад) или потпун URL који почиње са " +"шемом као нпр. “https://”." + +msgid "redirect" +msgstr "преусмеравање" + +msgid "redirects" +msgstr "преусмеравања" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sr_Latn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sr_Latn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..901715d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sr_Latn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sr_Latn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sr_Latn/LC_MESSAGES/django.po new file mode 100644 index 0000000..f1b3374 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sr_Latn/LC_MESSAGES/django.po @@ -0,0 +1,52 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Igor Jerosimić, 2019-2021 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-01-15 17:03+0000\n" +"Last-Translator: Igor Jerosimić\n" +"Language-Team: Serbian (Latin) (http://www.transifex.com/django/django/" +"language/sr@latin/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr@latin\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Redirects" +msgstr "Preusmeravanja" + +msgid "site" +msgstr "sajt" + +msgid "redirect from" +msgstr "preusmeren sa" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Ovo treba da bude apsolutna putanja, isključujući ime domena. Primer: “/" +"events/search/”." + +msgid "redirect to" +msgstr "preusmeri ka" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Ovo može da bude apsolutna putanja (kao iznad) ili potpun URL koji počinje " +"sa šemom kao npr. “https://”." + +msgid "redirect" +msgstr "preusmeravanje" + +msgid "redirects" +msgstr "preusmeravanja" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sv/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sv/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0017860 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sv/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sv/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sv/LC_MESSAGES/django.po new file mode 100644 index 0000000..9c4a8f9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sv/LC_MESSAGES/django.po @@ -0,0 +1,53 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Elias Johnstone , 2022 +# Jannis Leidel , 2011 +# Jonathan Lindén, 2014 +# Thomas Lundqvist, 2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2022-07-24 18:32+0000\n" +"Last-Translator: Elias Johnstone \n" +"Language-Team: Swedish (http://www.transifex.com/django/django/language/" +"sv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sv\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Omdirigeringar" + +msgid "site" +msgstr "webbplats" + +msgid "redirect from" +msgstr "omdirigera från" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Detta bör vara en absolut sökväg utan domännamnet. Exempel: '/handelser/" +"sok/'." + +msgid "redirect to" +msgstr "omdirigera till" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Detta kan vara antingen en absolut sökväg (som ovan) eller en fullständig " +"URL som börjar med 'https://'." + +msgid "redirect" +msgstr "omdirigera" + +msgid "redirects" +msgstr "omdirigeringar" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sw/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sw/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2344b93 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sw/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sw/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sw/LC_MESSAGES/django.po new file mode 100644 index 0000000..8c361de --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/sw/LC_MESSAGES/django.po @@ -0,0 +1,51 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Machaku, 2013-2014 +# Millicent Atieno Obwanda , 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2023-12-04 18:32+0000\n" +"Last-Translator: Millicent Atieno Obwanda , 2023\n" +"Language-Team: Swahili (http://app.transifex.com/django/django/language/" +"sw/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sw\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Maelekezo upya" + +msgid "site" +msgstr "Tovuti" + +msgid "redirect from" +msgstr "Imeelekezwa kutoka" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Hii inapaswa kuwa njia kamili, isiyojumuisha jina la uwanja. Mfano: '/events/" +"search/" + +msgid "redirect to" +msgstr "elekeza kwenda" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Hii inaweza kuwa njia kamili (kama ilivyoelezwa hapo juu) au URL kamili " +"ikiwa na mwanzo na mpango kama vile 'https://'." + +msgid "redirect" +msgstr "maelekezo upya" + +msgid "redirects" +msgstr "maelekezo upya" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ta/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ta/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e2a9b43 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ta/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ta/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ta/LC_MESSAGES/django.po new file mode 100644 index 0000000..156ade3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ta/LC_MESSAGES/django.po @@ -0,0 +1,49 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Tamil (http://www.transifex.com/django/django/language/ta/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ta\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "" + +msgid "site" +msgstr "" + +msgid "redirect from" +msgstr "லிருந்து திசைமாற்று" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"இது ஒரு முழுமையான பாதையாக இருக்கவேண்டும். இணையத்தளப்பெயராக இருக்கக்கூடாது. உதாரணம்:'/" +"events/search/'." + +msgid "redirect to" +msgstr "திரும்ப அனுப்பு" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"இது முழுமையான பாதையாக (மேலே உள்ளது போல) அல்லது \"http\"//\" என தொடங்கும் வலை " +"முகவரியாக இருக்கலாம்." + +msgid "redirect" +msgstr "திரும்ப அனுப்பு" + +msgid "redirects" +msgstr "திரும்ப அனுப்புகிறது. " diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/te/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/te/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2c23446 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/te/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/te/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/te/LC_MESSAGES/django.po new file mode 100644 index 0000000..dd102f2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/te/LC_MESSAGES/django.po @@ -0,0 +1,42 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:12+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Telugu (http://www.transifex.com/projects/p/django/language/" +"te/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: te\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "" + +msgid "redirect from" +msgstr "" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" + +msgid "redirect to" +msgstr "" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" + +msgid "redirect" +msgstr "" + +msgid "redirects" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/tg/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/tg/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c7908d6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/tg/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/tg/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/tg/LC_MESSAGES/django.po new file mode 100644 index 0000000..43e7c17 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/tg/LC_MESSAGES/django.po @@ -0,0 +1,45 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Surush Sufiew , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2020-05-15 00:33+0000\n" +"Last-Translator: Surush Sufiew \n" +"Language-Team: Tajik (http://www.transifex.com/django/django/language/tg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Самтдигаркунӣ(Redirects)" + +msgid "site" +msgstr "сомона" + +msgid "redirect from" +msgstr "Самтдигаркунӣ аз" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" + +msgid "redirect to" +msgstr "Самтдигаркунӣ ба" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"“http://”." +msgstr "" + +msgid "redirect" +msgstr "самтдигаркунӣ" + +msgid "redirects" +msgstr "самтдигаркунӣ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/th/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/th/LC_MESSAGES/django.mo new file mode 100644 index 0000000..247f902 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/th/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/th/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/th/LC_MESSAGES/django.po new file mode 100644 index 0000000..78ba247 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/th/LC_MESSAGES/django.po @@ -0,0 +1,46 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Kowit Charoenratchatabhan , 2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2018-05-06 08:37+0000\n" +"Last-Translator: Kowit Charoenratchatabhan \n" +"Language-Team: Thai (http://www.transifex.com/django/django/language/th/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: th\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Redirects" +msgstr "เปลี่ยนทิศทาง" + +msgid "site" +msgstr "ไซต์" + +msgid "redirect from" +msgstr "เปลี่ยนทิศทางจาก" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "พาธไม่รวมโดเมน ตัวอย่าง : '/events/search/'" + +msgid "redirect to" +msgstr "เปลี่ยนทิศทางไปที่" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "มันอาจจะเป็นพาธหรือ URL แบบเต็มที่ขึ้นต้นด้วย 'http://'." + +msgid "redirect" +msgstr "เปลี่ยนทิศทาง" + +msgid "redirects" +msgstr "เปลี่ยนทิศทาง" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/tk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/tk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..93c7662 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/tk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/tk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/tk/LC_MESSAGES/django.po new file mode 100644 index 0000000..202ce22 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/tk/LC_MESSAGES/django.po @@ -0,0 +1,50 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Resul , 2020 +# Welbeck Garli , 2022 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2022-07-24 18:32+0000\n" +"Last-Translator: Welbeck Garli \n" +"Language-Team: Turkmen (http://www.transifex.com/django/django/language/" +"tk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tk\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "Gaýtadan gönükdirmeler" + +msgid "site" +msgstr "sahypa" + +msgid "redirect from" +msgstr "gönükdirilen salgy" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Bu domen ady hasaba almazdan, doly ýol bolmaly. Mysal: “/wakalar/gozleg/”." + +msgid "redirect to" +msgstr "gönükdirilen salgy" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"(ýokarydaky ýaly) absolýut yzarlama ýa-da \"https://\" bilen başlanýan " +"sahypa gönükdirmesi bolup biler." + +msgid "redirect" +msgstr "gönükdirme" + +msgid "redirects" +msgstr "gönükdirmeler" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/tr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/tr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5a9237b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/tr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/tr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/tr/LC_MESSAGES/django.po new file mode 100644 index 0000000..87029e3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/tr/LC_MESSAGES/django.po @@ -0,0 +1,53 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# BouRock, 2015,2019,2021 +# BouRock, 2014 +# Cihad GÜNDOĞDU , 2014 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-01-16 19:34+0000\n" +"Last-Translator: BouRock\n" +"Language-Team: Turkish (http://www.transifex.com/django/django/language/" +"tr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Redirects" +msgstr "Yönlendirmeler" + +msgid "site" +msgstr "site" + +msgid "redirect from" +msgstr "yönlendirilen adres" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Bu, bir tam yol olmalıdır, etki alanı adı kullanılmadan yazılmalı. Örnek: “/" +"olaylar/arama/”." + +msgid "redirect to" +msgstr "yönlendirildiği adres" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Bu, ya bir tam yol (yukarıdaki gibi) ya da “https://” gibi bir şema ile " +"başlayan tam bir URL olabilir." + +msgid "redirect" +msgstr "yönlendirme" + +msgid "redirects" +msgstr "yönlendirmeler" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/tt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/tt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a1635b6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/tt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/tt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/tt/LC_MESSAGES/django.po new file mode 100644 index 0000000..d06da14 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/tt/LC_MESSAGES/django.po @@ -0,0 +1,48 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Azat Khasanshin , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Tatar (http://www.transifex.com/django/django/language/tt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tt\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Redirects" +msgstr "" + +msgid "site" +msgstr "" + +msgid "redirect from" +msgstr "бу сәхифәдән юнәлтергә:" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"Бу домен исеменнән тыш абсолүт юл булырга тиеш. Мәсәлән: '/events/search/'." + +msgid "redirect to" +msgstr "бу сәхифәгә юнәлтергә:" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"Бу я абсолүт юл (өстәге кебек), я 'http://' белән башланган тулы URL булырга " +"тиеш." + +msgid "redirect" +msgstr "юнәлтү" + +msgid "redirects" +msgstr "юнәлтүләр" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/udm/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/udm/LC_MESSAGES/django.mo new file mode 100644 index 0000000..af7ab53 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/udm/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/udm/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/udm/LC_MESSAGES/django.po new file mode 100644 index 0000000..3bfa4d1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/udm/LC_MESSAGES/django.po @@ -0,0 +1,42 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:13+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Udmurt (http://www.transifex.com/projects/p/django/language/" +"udm/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: udm\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Redirects" +msgstr "" + +msgid "redirect from" +msgstr "" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" + +msgid "redirect to" +msgstr "" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" + +msgid "redirect" +msgstr "" + +msgid "redirects" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ug/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ug/LC_MESSAGES/django.mo new file mode 100644 index 0000000..33f6838 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ug/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ug/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ug/LC_MESSAGES/django.po new file mode 100644 index 0000000..051920f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ug/LC_MESSAGES/django.po @@ -0,0 +1,50 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Abduqadir Abliz , 2023 +# Murat Orhun , 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2023-12-04 18:32+0000\n" +"Last-Translator: Murat Orhun , 2023\n" +"Language-Team: Uyghur (http://app.transifex.com/django/django/language/ug/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ug\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "قايتا نىشانلانغان" + +msgid "site" +msgstr "بېكەت" + +msgid "redirect from" +msgstr "قايتا نىشانلانغان مەنبەسى" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"بۇ مۇتلەق يول بولۇشى كېرەك، دائىرە نامىنى ئۆز ئىچىگە ئالمايدۇ. مەسىلە: «/" +"events/search/»." + +msgid "redirect to" +msgstr "قايتا نىشانلانغان مەنزىلى" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"بۇ مۇتلەق يول (يۇقىرىقىغا ئوخشاش) بولسا بولىدۇ ياكى «https://» دىن باشلانغان " +"تولۇق تور ئادرېسى بولسىمۇ بولىدۇ." + +msgid "redirect" +msgstr "قايتا نىشانلا" + +msgid "redirects" +msgstr "قايتا نىشانلانغانلار" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/uk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/uk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2a1fb7b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/uk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/uk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/uk/LC_MESSAGES/django.po new file mode 100644 index 0000000..c82f937 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/uk/LC_MESSAGES/django.po @@ -0,0 +1,56 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Oleksandr Chernihov , 2014 +# Illia Volochii , 2021 +# Jannis Leidel , 2011 +# Mykola Zamkovoi , 2014 +# Vitaliy Kozlovskyi , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-01-20 00:12+0000\n" +"Last-Translator: Illia Volochii \n" +"Language-Team: Ukrainian (http://www.transifex.com/django/django/language/" +"uk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: uk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != " +"11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % " +"100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || " +"(n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n" + +msgid "Redirects" +msgstr "Перенаправлення" + +msgid "site" +msgstr "сайт" + +msgid "redirect from" +msgstr "перенаправлення з" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Шлях має бути абсолютним без доменного імені. Наприклад, “/events/search/”." + +msgid "redirect to" +msgstr "перенаправлення до" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"Шлях може бути або абсолютним (як вказано вище), або повним URL (який " +"починається із схеми, як-от “https://”)." + +msgid "redirect" +msgstr "перенаправлення" + +msgid "redirects" +msgstr "перенаправлення" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ur/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ur/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4b302db Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ur/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ur/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ur/LC_MESSAGES/django.po new file mode 100644 index 0000000..bf3a9b2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/ur/LC_MESSAGES/django.po @@ -0,0 +1,46 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Mansoorulhaq Mansoor , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Urdu (http://www.transifex.com/django/django/language/ur/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ur\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Redirects" +msgstr "" + +msgid "site" +msgstr "" + +msgid "redirect from" +msgstr "سے ری ڈائریکٹ" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "یہ مطلق پاتھ ھونا چاھئے، بغیر ڈومین نام کے۔ مثلاً '/events/search/'" + +msgid "redirect to" +msgstr "ری ڈائریکٹ از طرف" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"یہ مطلق پاتھ ھو سکتا ھے (جیسے اوپر ھے) یا مکمل یو آر ایل (URL) بمع 'http://'۔" + +msgid "redirect" +msgstr "ری ڈائریکٹ" + +msgid "redirects" +msgstr "ری ڈائیکٹس" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/uz/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/uz/LC_MESSAGES/django.mo new file mode 100644 index 0000000..89aa2e0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/uz/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/uz/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/uz/LC_MESSAGES/django.po new file mode 100644 index 0000000..1357fa2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/uz/LC_MESSAGES/django.po @@ -0,0 +1,48 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bedilbek Khamidov , 2019 +# Nuruddin Iminokhunov , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-09-19 08:25+0000\n" +"Last-Translator: Bedilbek Khamidov \n" +"Language-Team: Uzbek (http://www.transifex.com/django/django/language/uz/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: uz\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Redirects" +msgstr "Redirektlar" + +msgid "site" +msgstr "sayt" + +msgid "redirect from" +msgstr "redirekt formasi" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "" +"Domen nomidan tashqari, bu mutlaq manzil bo'lishi kerak. \n" +"Masalan: “/events/search/”." + +msgid "redirect to" +msgstr "" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"“http://”." +msgstr "" + +msgid "redirect" +msgstr "" + +msgid "redirects" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/vi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/vi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ae80abd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/vi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/vi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/vi/LC_MESSAGES/django.po new file mode 100644 index 0000000..40e3ddb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/vi/LC_MESSAGES/django.po @@ -0,0 +1,49 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-09 17:42+0200\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Tran Van \n" +"Language-Team: Vietnamese (http://www.transifex.com/django/django/language/" +"vi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: vi\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Redirects" +msgstr "" + +msgid "site" +msgstr "" + +msgid "redirect from" +msgstr "Chuyển hướng từ" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: '/" +"events/search/'." +msgstr "" +"Đây phải là đường dẫn tuyệt đối, không bao gồm tên miền. Ví dụ: '/events/" +"search/'." + +msgid "redirect to" +msgstr "Chuyển hướng tới" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"'http://'." +msgstr "" +"Đây có thể là đường dẫn tuyệt đối hoặc địa chỉ đầy đủ bắt đầu với 'http://'" + +msgid "redirect" +msgstr "Chuyển hướng" + +msgid "redirects" +msgstr "Chuyển hướng" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/zh_Hans/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/zh_Hans/LC_MESSAGES/django.mo new file mode 100644 index 0000000..915e7c5 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/zh_Hans/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/zh_Hans/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/zh_Hans/LC_MESSAGES/django.po new file mode 100644 index 0000000..93e04fe --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/zh_Hans/LC_MESSAGES/django.po @@ -0,0 +1,53 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# HuanCheng Bai白宦成 , 2018 +# Jannis Leidel , 2011 +# mozillazg , 2016 +# Ronald White , 2014 +# Veoco , 2021 +# wolf ice , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-15 09:00+0100\n" +"PO-Revision-Date: 2021-02-07 04:22+0000\n" +"Last-Translator: Veoco \n" +"Language-Team: Chinese (China) (http://www.transifex.com/django/django/" +"language/zh_CN/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_CN\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Redirects" +msgstr "重定向" + +msgid "site" +msgstr "站点" + +msgid "redirect from" +msgstr "重定向自" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "这应该是绝对路径,不包括域名。例如:“/events/search/”。" + +msgid "redirect to" +msgstr "重定向到" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with a " +"scheme such as “https://”." +msgstr "" +"这可以是绝对路径(如上所述),也可以是一个以 “https://” 等协议开头的完整 " +"URL。" + +msgid "redirect" +msgstr "重定向" + +msgid "redirects" +msgstr "重定向" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/zh_Hant/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/zh_Hant/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2a650c9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/zh_Hant/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/zh_Hant/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/zh_Hant/LC_MESSAGES/django.po new file mode 100644 index 0000000..cb6c90f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/locale/zh_Hant/LC_MESSAGES/django.po @@ -0,0 +1,48 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Chen Chun-Chia , 2015 +# Jannis Leidel , 2011 +# Tzu-ping Chung , 2016,2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-08 17:27+0200\n" +"PO-Revision-Date: 2019-09-18 09:01+0000\n" +"Last-Translator: Tzu-ping Chung \n" +"Language-Team: Chinese (Taiwan) (http://www.transifex.com/django/django/" +"language/zh_TW/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_TW\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Redirects" +msgstr "重導向" + +msgid "site" +msgstr "網站" + +msgid "redirect from" +msgstr "重導向自" + +msgid "" +"This should be an absolute path, excluding the domain name. Example: “/" +"events/search/”." +msgstr "應該是一個絕對路徑,不包括網域。例如:「/events/search/」。" + +msgid "redirect to" +msgstr "重導向到" + +msgid "" +"This can be either an absolute path (as above) or a full URL starting with " +"“http://”." +msgstr "此可為一絕對路徑(如上)或一個以「http://」開頭的完整 URL。" + +msgid "redirect" +msgstr "重導向" + +msgid "redirects" +msgstr "重導向" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/middleware.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/middleware.py new file mode 100644 index 0000000..bc4fe9c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/middleware.py @@ -0,0 +1,50 @@ +from django.apps import apps +from django.conf import settings +from django.contrib.redirects.models import Redirect +from django.contrib.sites.shortcuts import get_current_site +from django.core.exceptions import ImproperlyConfigured +from django.http import HttpResponseGone, HttpResponsePermanentRedirect +from django.utils.deprecation import MiddlewareMixin + + +class RedirectFallbackMiddleware(MiddlewareMixin): + # Defined as class-level attributes to be subclassing-friendly. + response_gone_class = HttpResponseGone + response_redirect_class = HttpResponsePermanentRedirect + + def __init__(self, get_response): + if not apps.is_installed("django.contrib.sites"): + raise ImproperlyConfigured( + "You cannot use RedirectFallbackMiddleware when " + "django.contrib.sites is not installed." + ) + super().__init__(get_response) + + def process_response(self, request, response): + # No need to check for a redirect for non-404 responses. + if response.status_code != 404: + return response + + full_path = request.get_full_path() + current_site = get_current_site(request) + + r = None + try: + r = Redirect.objects.get(site=current_site, old_path=full_path) + except Redirect.DoesNotExist: + pass + if r is None and settings.APPEND_SLASH and not request.path.endswith("/"): + try: + r = Redirect.objects.get( + site=current_site, + old_path=request.get_full_path(force_append_slash=True), + ) + except Redirect.DoesNotExist: + pass + if r is not None: + if r.new_path == "": + return self.response_gone_class() + return self.response_redirect_class(r.new_path) + + # No redirect was found. Return the response. + return response diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/migrations/0001_initial.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/migrations/0001_initial.py new file mode 100644 index 0000000..7881d57 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/migrations/0001_initial.py @@ -0,0 +1,64 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("sites", "0001_initial"), + ] + + operations = [ + migrations.CreateModel( + name="Redirect", + fields=[ + ( + "id", + models.AutoField( + verbose_name="ID", + serialize=False, + auto_created=True, + primary_key=True, + ), + ), + ( + "site", + models.ForeignKey( + to="sites.Site", + on_delete=models.CASCADE, + verbose_name="site", + ), + ), + ( + "old_path", + models.CharField( + help_text=( + "This should be an absolute path, excluding the domain " + "name. Example: “/events/search/”." + ), + max_length=200, + verbose_name="redirect from", + db_index=True, + ), + ), + ( + "new_path", + models.CharField( + help_text=( + "This can be either an absolute path (as above) or a full " + "URL starting with “http://”." + ), + max_length=200, + verbose_name="redirect to", + blank=True, + ), + ), + ], + options={ + "ordering": ["old_path"], + "unique_together": {("site", "old_path")}, + "db_table": "django_redirect", + "verbose_name": "redirect", + "verbose_name_plural": "redirects", + }, + bases=(models.Model,), + ), + ] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/migrations/0002_alter_redirect_new_path_help_text.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/migrations/0002_alter_redirect_new_path_help_text.py new file mode 100644 index 0000000..9976366 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/migrations/0002_alter_redirect_new_path_help_text.py @@ -0,0 +1,23 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("redirects", "0001_initial"), + ] + + operations = [ + migrations.AlterField( + model_name="redirect", + name="new_path", + field=models.CharField( + blank=True, + help_text=( + "This can be either an absolute path (as above) or a full " + "URL starting with a scheme such as “https://”." + ), + max_length=200, + verbose_name="redirect to", + ), + ), + ] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/migrations/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/models.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/models.py new file mode 100644 index 0000000..1552414 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/redirects/models.py @@ -0,0 +1,35 @@ +from django.contrib.sites.models import Site +from django.db import models +from django.utils.translation import gettext_lazy as _ + + +class Redirect(models.Model): + site = models.ForeignKey(Site, models.CASCADE, verbose_name=_("site")) + old_path = models.CharField( + _("redirect from"), + max_length=200, + db_index=True, + help_text=_( + "This should be an absolute path, excluding the domain name. Example: " + "“/events/search/”." + ), + ) + new_path = models.CharField( + _("redirect to"), + max_length=200, + blank=True, + help_text=_( + "This can be either an absolute path (as above) or a full URL " + "starting with a scheme such as “https://”." + ), + ) + + class Meta: + verbose_name = _("redirect") + verbose_name_plural = _("redirects") + db_table = "django_redirect" + unique_together = [["site", "old_path"]] + ordering = ["old_path"] + + def __str__(self): + return "%s ---> %s" % (self.old_path, self.new_path) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/apps.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/apps.py new file mode 100644 index 0000000..83f0cef --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/apps.py @@ -0,0 +1,7 @@ +from django.apps import AppConfig +from django.utils.translation import gettext_lazy as _ + + +class SessionsConfig(AppConfig): + name = "django.contrib.sessions" + verbose_name = _("Sessions") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/backends/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/backends/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/backends/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/backends/base.py new file mode 100644 index 0000000..050e738 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/backends/base.py @@ -0,0 +1,365 @@ +import logging +import string +from datetime import datetime, timedelta + +from django.conf import settings +from django.core import signing +from django.utils import timezone +from django.utils.crypto import get_random_string +from django.utils.module_loading import import_string + +# session_key should not be case sensitive because some backends can store it +# on case insensitive file systems. +VALID_KEY_CHARS = string.ascii_lowercase + string.digits + + +class CreateError(Exception): + """ + Used internally as a consistent exception type to catch from save (see the + docstring for SessionBase.save() for details). + """ + + pass + + +class UpdateError(Exception): + """ + Occurs if Django tries to update a session that was deleted. + """ + + pass + + +class SessionBase: + """ + Base class for all Session classes. + """ + + TEST_COOKIE_NAME = "testcookie" + TEST_COOKIE_VALUE = "worked" + + __not_given = object() + + def __init__(self, session_key=None): + self._session_key = session_key + self.accessed = False + self.modified = False + self.serializer = import_string(settings.SESSION_SERIALIZER) + + def __contains__(self, key): + return key in self._session + + def __getitem__(self, key): + return self._session[key] + + def __setitem__(self, key, value): + self._session[key] = value + self.modified = True + + def __delitem__(self, key): + del self._session[key] + self.modified = True + + @property + def key_salt(self): + return "django.contrib.sessions." + self.__class__.__qualname__ + + def get(self, key, default=None): + return self._session.get(key, default) + + def pop(self, key, default=__not_given): + self.modified = self.modified or key in self._session + args = () if default is self.__not_given else (default,) + return self._session.pop(key, *args) + + def setdefault(self, key, value): + if key in self._session: + return self._session[key] + else: + self.modified = True + self._session[key] = value + return value + + def set_test_cookie(self): + self[self.TEST_COOKIE_NAME] = self.TEST_COOKIE_VALUE + + def test_cookie_worked(self): + return self.get(self.TEST_COOKIE_NAME) == self.TEST_COOKIE_VALUE + + def delete_test_cookie(self): + del self[self.TEST_COOKIE_NAME] + + def encode(self, session_dict): + "Return the given session dictionary serialized and encoded as a string." + return signing.dumps( + session_dict, + salt=self.key_salt, + serializer=self.serializer, + compress=True, + ) + + def decode(self, session_data): + try: + return signing.loads( + session_data, salt=self.key_salt, serializer=self.serializer + ) + except signing.BadSignature: + logger = logging.getLogger("django.security.SuspiciousSession") + logger.warning("Session data corrupted") + except Exception: + # ValueError, unpickling exceptions. If any of these happen, just + # return an empty dictionary (an empty session). + pass + return {} + + def update(self, dict_): + self._session.update(dict_) + self.modified = True + + def has_key(self, key): + return key in self._session + + def keys(self): + return self._session.keys() + + def values(self): + return self._session.values() + + def items(self): + return self._session.items() + + def clear(self): + # To avoid unnecessary persistent storage accesses, we set up the + # internals directly (loading data wastes time, since we are going to + # set it to an empty dict anyway). + self._session_cache = {} + self.accessed = True + self.modified = True + + def is_empty(self): + "Return True when there is no session_key and the session is empty." + try: + return not self._session_key and not self._session_cache + except AttributeError: + return True + + def _get_new_session_key(self): + "Return session key that isn't being used." + while True: + session_key = get_random_string(32, VALID_KEY_CHARS) + if not self.exists(session_key): + return session_key + + def _get_or_create_session_key(self): + if self._session_key is None: + self._session_key = self._get_new_session_key() + return self._session_key + + def _validate_session_key(self, key): + """ + Key must be truthy and at least 8 characters long. 8 characters is an + arbitrary lower bound for some minimal key security. + """ + return key and len(key) >= 8 + + def _get_session_key(self): + return self.__session_key + + def _set_session_key(self, value): + """ + Validate session key on assignment. Invalid values will set to None. + """ + if self._validate_session_key(value): + self.__session_key = value + else: + self.__session_key = None + + session_key = property(_get_session_key) + _session_key = property(_get_session_key, _set_session_key) + + def _get_session(self, no_load=False): + """ + Lazily load session from storage (unless "no_load" is True, when only + an empty dict is stored) and store it in the current instance. + """ + self.accessed = True + try: + return self._session_cache + except AttributeError: + if self.session_key is None or no_load: + self._session_cache = {} + else: + self._session_cache = self.load() + return self._session_cache + + _session = property(_get_session) + + def get_session_cookie_age(self): + return settings.SESSION_COOKIE_AGE + + def get_expiry_age(self, **kwargs): + """Get the number of seconds until the session expires. + + Optionally, this function accepts `modification` and `expiry` keyword + arguments specifying the modification and expiry of the session. + """ + try: + modification = kwargs["modification"] + except KeyError: + modification = timezone.now() + # Make the difference between "expiry=None passed in kwargs" and + # "expiry not passed in kwargs", in order to guarantee not to trigger + # self.load() when expiry is provided. + try: + expiry = kwargs["expiry"] + except KeyError: + expiry = self.get("_session_expiry") + + if not expiry: # Checks both None and 0 cases + return self.get_session_cookie_age() + if not isinstance(expiry, (datetime, str)): + return expiry + if isinstance(expiry, str): + expiry = datetime.fromisoformat(expiry) + delta = expiry - modification + return delta.days * 86400 + delta.seconds + + def get_expiry_date(self, **kwargs): + """Get session the expiry date (as a datetime object). + + Optionally, this function accepts `modification` and `expiry` keyword + arguments specifying the modification and expiry of the session. + """ + try: + modification = kwargs["modification"] + except KeyError: + modification = timezone.now() + # Same comment as in get_expiry_age + try: + expiry = kwargs["expiry"] + except KeyError: + expiry = self.get("_session_expiry") + + if isinstance(expiry, datetime): + return expiry + elif isinstance(expiry, str): + return datetime.fromisoformat(expiry) + expiry = expiry or self.get_session_cookie_age() + return modification + timedelta(seconds=expiry) + + def set_expiry(self, value): + """ + Set a custom expiration for the session. ``value`` can be an integer, + a Python ``datetime`` or ``timedelta`` object or ``None``. + + If ``value`` is an integer, the session will expire after that many + seconds of inactivity. If set to ``0`` then the session will expire on + browser close. + + If ``value`` is a ``datetime`` or ``timedelta`` object, the session + will expire at that specific future time. + + If ``value`` is ``None``, the session uses the global session expiry + policy. + """ + if value is None: + # Remove any custom expiration for this session. + try: + del self["_session_expiry"] + except KeyError: + pass + return + if isinstance(value, timedelta): + value = timezone.now() + value + if isinstance(value, datetime): + value = value.isoformat() + self["_session_expiry"] = value + + def get_expire_at_browser_close(self): + """ + Return ``True`` if the session is set to expire when the browser + closes, and ``False`` if there's an expiry date. Use + ``get_expiry_date()`` or ``get_expiry_age()`` to find the actual expiry + date/age, if there is one. + """ + if (expiry := self.get("_session_expiry")) is None: + return settings.SESSION_EXPIRE_AT_BROWSER_CLOSE + return expiry == 0 + + def flush(self): + """ + Remove the current session data from the database and regenerate the + key. + """ + self.clear() + self.delete() + self._session_key = None + + def cycle_key(self): + """ + Create a new session key, while retaining the current session data. + """ + data = self._session + key = self.session_key + self.create() + self._session_cache = data + if key: + self.delete(key) + + # Methods that child classes must implement. + + def exists(self, session_key): + """ + Return True if the given session_key already exists. + """ + raise NotImplementedError( + "subclasses of SessionBase must provide an exists() method" + ) + + def create(self): + """ + Create a new session instance. Guaranteed to create a new object with + a unique key and will have saved the result once (with empty data) + before the method returns. + """ + raise NotImplementedError( + "subclasses of SessionBase must provide a create() method" + ) + + def save(self, must_create=False): + """ + Save the session data. If 'must_create' is True, create a new session + object (or raise CreateError). Otherwise, only update an existing + object and don't create one (raise UpdateError if needed). + """ + raise NotImplementedError( + "subclasses of SessionBase must provide a save() method" + ) + + def delete(self, session_key=None): + """ + Delete the session data under this key. If the key is None, use the + current session key value. + """ + raise NotImplementedError( + "subclasses of SessionBase must provide a delete() method" + ) + + def load(self): + """ + Load the session data and return a dictionary. + """ + raise NotImplementedError( + "subclasses of SessionBase must provide a load() method" + ) + + @classmethod + def clear_expired(cls): + """ + Remove expired sessions from the session store. + + If this operation isn't possible on a given backend, it should raise + NotImplementedError. If it isn't necessary, because the backend has + a built-in expiration mechanism, it should be a no-op. + """ + raise NotImplementedError("This backend does not support clear_expired().") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/backends/cache.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/backends/cache.py new file mode 100644 index 0000000..0c9d244 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/backends/cache.py @@ -0,0 +1,85 @@ +from django.conf import settings +from django.contrib.sessions.backends.base import CreateError, SessionBase, UpdateError +from django.core.cache import caches + +KEY_PREFIX = "django.contrib.sessions.cache" + + +class SessionStore(SessionBase): + """ + A cache-based session store. + """ + + cache_key_prefix = KEY_PREFIX + + def __init__(self, session_key=None): + self._cache = caches[settings.SESSION_CACHE_ALIAS] + super().__init__(session_key) + + @property + def cache_key(self): + return self.cache_key_prefix + self._get_or_create_session_key() + + def load(self): + try: + session_data = self._cache.get(self.cache_key) + except Exception: + # Some backends (e.g. memcache) raise an exception on invalid + # cache keys. If this happens, reset the session. See #17810. + session_data = None + if session_data is not None: + return session_data + self._session_key = None + return {} + + def create(self): + # Because a cache can fail silently (e.g. memcache), we don't know if + # we are failing to create a new session because of a key collision or + # because the cache is missing. So we try for a (large) number of times + # and then raise an exception. That's the risk you shoulder if using + # cache backing. + for i in range(10000): + self._session_key = self._get_new_session_key() + try: + self.save(must_create=True) + except CreateError: + continue + self.modified = True + return + raise RuntimeError( + "Unable to create a new session key. " + "It is likely that the cache is unavailable." + ) + + def save(self, must_create=False): + if self.session_key is None: + return self.create() + if must_create: + func = self._cache.add + elif self._cache.get(self.cache_key) is not None: + func = self._cache.set + else: + raise UpdateError + result = func( + self.cache_key, + self._get_session(no_load=must_create), + self.get_expiry_age(), + ) + if must_create and not result: + raise CreateError + + def exists(self, session_key): + return ( + bool(session_key) and (self.cache_key_prefix + session_key) in self._cache + ) + + def delete(self, session_key=None): + if session_key is None: + if self.session_key is None: + return + session_key = self.session_key + self._cache.delete(self.cache_key_prefix + session_key) + + @classmethod + def clear_expired(cls): + pass diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/backends/cached_db.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/backends/cached_db.py new file mode 100644 index 0000000..3125a71 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/backends/cached_db.py @@ -0,0 +1,72 @@ +""" +Cached, database-backed sessions. +""" + +from django.conf import settings +from django.contrib.sessions.backends.db import SessionStore as DBStore +from django.core.cache import caches + +KEY_PREFIX = "django.contrib.sessions.cached_db" + + +class SessionStore(DBStore): + """ + Implement cached, database backed sessions. + """ + + cache_key_prefix = KEY_PREFIX + + def __init__(self, session_key=None): + self._cache = caches[settings.SESSION_CACHE_ALIAS] + super().__init__(session_key) + + @property + def cache_key(self): + return self.cache_key_prefix + self._get_or_create_session_key() + + def load(self): + try: + data = self._cache.get(self.cache_key) + except Exception: + # Some backends (e.g. memcache) raise an exception on invalid + # cache keys. If this happens, reset the session. See #17810. + data = None + + if data is None: + s = self._get_session_from_db() + if s: + data = self.decode(s.session_data) + self._cache.set( + self.cache_key, data, self.get_expiry_age(expiry=s.expire_date) + ) + else: + data = {} + return data + + def exists(self, session_key): + return ( + session_key + and (self.cache_key_prefix + session_key) in self._cache + or super().exists(session_key) + ) + + def save(self, must_create=False): + super().save(must_create) + self._cache.set(self.cache_key, self._session, self.get_expiry_age()) + + def delete(self, session_key=None): + super().delete(session_key) + if session_key is None: + if self.session_key is None: + return + session_key = self.session_key + self._cache.delete(self.cache_key_prefix + session_key) + + def flush(self): + """ + Remove the current session data from the database and regenerate the + key. + """ + self.clear() + self.delete(self.session_key) + self._session_key = None diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/backends/db.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/backends/db.py new file mode 100644 index 0000000..e1f6b69 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/backends/db.py @@ -0,0 +1,110 @@ +import logging + +from django.contrib.sessions.backends.base import CreateError, SessionBase, UpdateError +from django.core.exceptions import SuspiciousOperation +from django.db import DatabaseError, IntegrityError, router, transaction +from django.utils import timezone +from django.utils.functional import cached_property + + +class SessionStore(SessionBase): + """ + Implement database session store. + """ + + def __init__(self, session_key=None): + super().__init__(session_key) + + @classmethod + def get_model_class(cls): + # Avoids a circular import and allows importing SessionStore when + # django.contrib.sessions is not in INSTALLED_APPS. + from django.contrib.sessions.models import Session + + return Session + + @cached_property + def model(self): + return self.get_model_class() + + def _get_session_from_db(self): + try: + return self.model.objects.get( + session_key=self.session_key, expire_date__gt=timezone.now() + ) + except (self.model.DoesNotExist, SuspiciousOperation) as e: + if isinstance(e, SuspiciousOperation): + logger = logging.getLogger("django.security.%s" % e.__class__.__name__) + logger.warning(str(e)) + self._session_key = None + + def load(self): + s = self._get_session_from_db() + return self.decode(s.session_data) if s else {} + + def exists(self, session_key): + return self.model.objects.filter(session_key=session_key).exists() + + def create(self): + while True: + self._session_key = self._get_new_session_key() + try: + # Save immediately to ensure we have a unique entry in the + # database. + self.save(must_create=True) + except CreateError: + # Key wasn't unique. Try again. + continue + self.modified = True + return + + def create_model_instance(self, data): + """ + Return a new instance of the session model object, which represents the + current session state. Intended to be used for saving the session data + to the database. + """ + return self.model( + session_key=self._get_or_create_session_key(), + session_data=self.encode(data), + expire_date=self.get_expiry_date(), + ) + + def save(self, must_create=False): + """ + Save the current session data to the database. If 'must_create' is + True, raise a database error if the saving operation doesn't create a + new entry (as opposed to possibly updating an existing entry). + """ + if self.session_key is None: + return self.create() + data = self._get_session(no_load=must_create) + obj = self.create_model_instance(data) + using = router.db_for_write(self.model, instance=obj) + try: + with transaction.atomic(using=using): + obj.save( + force_insert=must_create, force_update=not must_create, using=using + ) + except IntegrityError: + if must_create: + raise CreateError + raise + except DatabaseError: + if not must_create: + raise UpdateError + raise + + def delete(self, session_key=None): + if session_key is None: + if self.session_key is None: + return + session_key = self.session_key + try: + self.model.objects.get(session_key=session_key).delete() + except self.model.DoesNotExist: + pass + + @classmethod + def clear_expired(cls): + cls.get_model_class().objects.filter(expire_date__lt=timezone.now()).delete() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/backends/file.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/backends/file.py new file mode 100644 index 0000000..d3ba8b1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/backends/file.py @@ -0,0 +1,210 @@ +import datetime +import logging +import os +import shutil +import tempfile + +from django.conf import settings +from django.contrib.sessions.backends.base import ( + VALID_KEY_CHARS, + CreateError, + SessionBase, + UpdateError, +) +from django.contrib.sessions.exceptions import InvalidSessionKey +from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation + + +class SessionStore(SessionBase): + """ + Implement a file based session store. + """ + + def __init__(self, session_key=None): + self.storage_path = self._get_storage_path() + self.file_prefix = settings.SESSION_COOKIE_NAME + super().__init__(session_key) + + @classmethod + def _get_storage_path(cls): + try: + return cls._storage_path + except AttributeError: + storage_path = ( + getattr(settings, "SESSION_FILE_PATH", None) or tempfile.gettempdir() + ) + # Make sure the storage path is valid. + if not os.path.isdir(storage_path): + raise ImproperlyConfigured( + "The session storage path %r doesn't exist. Please set your" + " SESSION_FILE_PATH setting to an existing directory in which" + " Django can store session data." % storage_path + ) + + cls._storage_path = storage_path + return storage_path + + def _key_to_file(self, session_key=None): + """ + Get the file associated with this session key. + """ + if session_key is None: + session_key = self._get_or_create_session_key() + + # Make sure we're not vulnerable to directory traversal. Session keys + # should always be md5s, so they should never contain directory + # components. + if not set(session_key).issubset(VALID_KEY_CHARS): + raise InvalidSessionKey("Invalid characters in session key") + + return os.path.join(self.storage_path, self.file_prefix + session_key) + + def _last_modification(self): + """ + Return the modification time of the file storing the session's content. + """ + modification = os.stat(self._key_to_file()).st_mtime + tz = datetime.timezone.utc if settings.USE_TZ else None + return datetime.datetime.fromtimestamp(modification, tz=tz) + + def _expiry_date(self, session_data): + """ + Return the expiry time of the file storing the session's content. + """ + return session_data.get("_session_expiry") or ( + self._last_modification() + + datetime.timedelta(seconds=self.get_session_cookie_age()) + ) + + def load(self): + session_data = {} + try: + with open(self._key_to_file(), encoding="ascii") as session_file: + file_data = session_file.read() + # Don't fail if there is no data in the session file. + # We may have opened the empty placeholder file. + if file_data: + try: + session_data = self.decode(file_data) + except (EOFError, SuspiciousOperation) as e: + if isinstance(e, SuspiciousOperation): + logger = logging.getLogger( + "django.security.%s" % e.__class__.__name__ + ) + logger.warning(str(e)) + self.create() + + # Remove expired sessions. + expiry_age = self.get_expiry_age(expiry=self._expiry_date(session_data)) + if expiry_age <= 0: + session_data = {} + self.delete() + self.create() + except (OSError, SuspiciousOperation): + self._session_key = None + return session_data + + def create(self): + while True: + self._session_key = self._get_new_session_key() + try: + self.save(must_create=True) + except CreateError: + continue + self.modified = True + return + + def save(self, must_create=False): + if self.session_key is None: + return self.create() + # Get the session data now, before we start messing + # with the file it is stored within. + session_data = self._get_session(no_load=must_create) + + session_file_name = self._key_to_file() + + try: + # Make sure the file exists. If it does not already exist, an + # empty placeholder file is created. + flags = os.O_WRONLY | getattr(os, "O_BINARY", 0) + if must_create: + flags |= os.O_EXCL | os.O_CREAT + fd = os.open(session_file_name, flags) + os.close(fd) + except FileNotFoundError: + if not must_create: + raise UpdateError + except FileExistsError: + if must_create: + raise CreateError + + # Write the session file without interfering with other threads + # or processes. By writing to an atomically generated temporary + # file and then using the atomic os.rename() to make the complete + # file visible, we avoid having to lock the session file, while + # still maintaining its integrity. + # + # Note: Locking the session file was explored, but rejected in part + # because in order to be atomic and cross-platform, it required a + # long-lived lock file for each session, doubling the number of + # files in the session storage directory at any given time. This + # rename solution is cleaner and avoids any additional overhead + # when reading the session data, which is the more common case + # unless SESSION_SAVE_EVERY_REQUEST = True. + # + # See ticket #8616. + dir, prefix = os.path.split(session_file_name) + + try: + output_file_fd, output_file_name = tempfile.mkstemp( + dir=dir, prefix=prefix + "_out_" + ) + renamed = False + try: + try: + os.write(output_file_fd, self.encode(session_data).encode()) + finally: + os.close(output_file_fd) + + # This will atomically rename the file (os.rename) if the OS + # supports it. Otherwise this will result in a shutil.copy2 + # and os.unlink (for example on Windows). See #9084. + shutil.move(output_file_name, session_file_name) + renamed = True + finally: + if not renamed: + os.unlink(output_file_name) + except (EOFError, OSError): + pass + + def exists(self, session_key): + return os.path.exists(self._key_to_file(session_key)) + + def delete(self, session_key=None): + if session_key is None: + if self.session_key is None: + return + session_key = self.session_key + try: + os.unlink(self._key_to_file(session_key)) + except OSError: + pass + + def clean(self): + pass + + @classmethod + def clear_expired(cls): + storage_path = cls._get_storage_path() + file_prefix = settings.SESSION_COOKIE_NAME + + for session_file in os.listdir(storage_path): + if not session_file.startswith(file_prefix): + continue + session_key = session_file.removeprefix(file_prefix) + session = cls(session_key) + # When an expired session is loaded, its file is removed, and a + # new file is immediately created. Prevent this by disabling + # the create() method. + session.create = lambda: None + session.load() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/backends/signed_cookies.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/backends/signed_cookies.py new file mode 100644 index 0000000..dc41c6f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/backends/signed_cookies.py @@ -0,0 +1,81 @@ +from django.contrib.sessions.backends.base import SessionBase +from django.core import signing + + +class SessionStore(SessionBase): + def load(self): + """ + Load the data from the key itself instead of fetching from some + external data store. Opposite of _get_session_key(), raise BadSignature + if signature fails. + """ + try: + return signing.loads( + self.session_key, + serializer=self.serializer, + # This doesn't handle non-default expiry dates, see #19201 + max_age=self.get_session_cookie_age(), + salt="django.contrib.sessions.backends.signed_cookies", + ) + except Exception: + # BadSignature, ValueError, or unpickling exceptions. If any of + # these happen, reset the session. + self.create() + return {} + + def create(self): + """ + To create a new key, set the modified flag so that the cookie is set + on the client for the current request. + """ + self.modified = True + + def save(self, must_create=False): + """ + To save, get the session key as a securely signed string and then set + the modified flag so that the cookie is set on the client for the + current request. + """ + self._session_key = self._get_session_key() + self.modified = True + + def exists(self, session_key=None): + """ + This method makes sense when you're talking to a shared resource, but + it doesn't matter when you're storing the information in the client's + cookie. + """ + return False + + def delete(self, session_key=None): + """ + To delete, clear the session key and the underlying data structure + and set the modified flag so that the cookie is set on the client for + the current request. + """ + self._session_key = "" + self._session_cache = {} + self.modified = True + + def cycle_key(self): + """ + Keep the same data but with a new key. Call save() and it will + automatically save a cookie with a new key at the end of the request. + """ + self.save() + + def _get_session_key(self): + """ + Instead of generating a random string, generate a secure url-safe + base64-encoded string of data as our session key. + """ + return signing.dumps( + self._session, + compress=True, + salt="django.contrib.sessions.backends.signed_cookies", + serializer=self.serializer, + ) + + @classmethod + def clear_expired(cls): + pass diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/base_session.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/base_session.py new file mode 100644 index 0000000..603d2fe --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/base_session.py @@ -0,0 +1,47 @@ +""" +This module allows importing AbstractBaseSession even +when django.contrib.sessions is not in INSTALLED_APPS. +""" +from django.db import models +from django.utils.translation import gettext_lazy as _ + + +class BaseSessionManager(models.Manager): + def encode(self, session_dict): + """ + Return the given session dictionary serialized and encoded as a string. + """ + session_store_class = self.model.get_session_store_class() + return session_store_class().encode(session_dict) + + def save(self, session_key, session_dict, expire_date): + s = self.model(session_key, self.encode(session_dict), expire_date) + if session_dict: + s.save() + else: + s.delete() # Clear sessions with no data. + return s + + +class AbstractBaseSession(models.Model): + session_key = models.CharField(_("session key"), max_length=40, primary_key=True) + session_data = models.TextField(_("session data")) + expire_date = models.DateTimeField(_("expire date"), db_index=True) + + objects = BaseSessionManager() + + class Meta: + abstract = True + verbose_name = _("session") + verbose_name_plural = _("sessions") + + def __str__(self): + return self.session_key + + @classmethod + def get_session_store_class(cls): + raise NotImplementedError + + def get_decoded(self): + session_store_class = self.get_session_store_class() + return session_store_class().decode(self.session_data) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/exceptions.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/exceptions.py new file mode 100644 index 0000000..8a4853c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/exceptions.py @@ -0,0 +1,19 @@ +from django.core.exceptions import BadRequest, SuspiciousOperation + + +class InvalidSessionKey(SuspiciousOperation): + """Invalid characters in session key""" + + pass + + +class SuspiciousSession(SuspiciousOperation): + """The session may be tampered with""" + + pass + + +class SessionInterrupted(BadRequest): + """The session was interrupted.""" + + pass diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/af/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/af/LC_MESSAGES/django.mo new file mode 100644 index 0000000..25d7ab6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/af/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/af/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/af/LC_MESSAGES/django.po new file mode 100644 index 0000000..09560cf --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/af/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# F Wolff , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2019-01-04 18:57+0000\n" +"Last-Translator: F Wolff \n" +"Language-Team: Afrikaans (http://www.transifex.com/django/django/language/" +"af/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: af\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Sessies" + +msgid "session key" +msgstr "sessiesleutel" + +msgid "session data" +msgstr "sessiedata" + +msgid "expire date" +msgstr "vervaldatum" + +msgid "session" +msgstr "sessie" + +msgid "sessions" +msgstr "sessies" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ar/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ar/LC_MESSAGES/django.mo new file mode 100644 index 0000000..027a065 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ar/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ar/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ar/LC_MESSAGES/django.po new file mode 100644 index 0000000..3108223 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ar/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bashar Al-Abdulhadi, 2014 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Arabic (http://www.transifex.com/django/django/language/ar/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +msgid "Sessions" +msgstr "جلسات" + +msgid "session key" +msgstr "مفتاح الجلسة" + +msgid "session data" +msgstr "بيانات الجلسة" + +msgid "expire date" +msgstr "تاريخ الانتهاء" + +msgid "session" +msgstr "جلسة" + +msgid "sessions" +msgstr "جلسات" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ar_DZ/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ar_DZ/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0f55320 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ar_DZ/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ar_DZ/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ar_DZ/LC_MESSAGES/django.po new file mode 100644 index 0000000..2ff47ed --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ar_DZ/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Riterix , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2019-12-14 22:50+0000\n" +"Last-Translator: Riterix \n" +"Language-Team: Arabic (Algeria) (http://www.transifex.com/django/django/" +"language/ar_DZ/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar_DZ\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +msgid "Sessions" +msgstr "جلسات" + +msgid "session key" +msgstr "مفتاح الجلسة" + +msgid "session data" +msgstr "بيانات الجلسة" + +msgid "expire date" +msgstr "تاريخ الانتهاء" + +msgid "session" +msgstr "جلسة" + +msgid "sessions" +msgstr "جلسات" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ast/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ast/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4b363bf Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ast/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ast/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ast/LC_MESSAGES/django.po new file mode 100644 index 0000000..57d8681 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ast/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ḷḷumex03 , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 19:51+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Asturian (http://www.transifex.com/django/django/language/" +"ast/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ast\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "" + +msgid "session key" +msgstr "clave de sesión" + +msgid "session data" +msgstr "datos de sesión" + +msgid "expire date" +msgstr "data de caducidá" + +msgid "session" +msgstr "sesión" + +msgid "sessions" +msgstr "sesiones" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/az/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/az/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9b488a3 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/az/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/az/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/az/LC_MESSAGES/django.po new file mode 100644 index 0000000..7ce647a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/az/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ali Ismayilov , 2011 +# Emin Mastizada , 2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2018-04-27 13:19+0000\n" +"Last-Translator: Emin Mastizada \n" +"Language-Team: Azerbaijani (http://www.transifex.com/django/django/language/" +"az/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: az\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Seanslar" + +msgid "session key" +msgstr "seans açarı" + +msgid "session data" +msgstr "seansın məlumatları" + +msgid "expire date" +msgstr "bitmə tarixi" + +msgid "session" +msgstr "seans" + +msgid "sessions" +msgstr "seanslar" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/be/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/be/LC_MESSAGES/django.mo new file mode 100644 index 0000000..100a157 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/be/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/be/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/be/LC_MESSAGES/django.po new file mode 100644 index 0000000..68d074a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/be/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Viktar Palstsiuk , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Viktar Palstsiuk \n" +"Language-Team: Belarusian (http://www.transifex.com/django/django/language/" +"be/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: be\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n" +"%100>=11 && n%100<=14)? 2 : 3);\n" + +msgid "Sessions" +msgstr "Сесіі" + +msgid "session key" +msgstr "ключ сэансу" + +msgid "session data" +msgstr "зьвесткі сэансу" + +msgid "expire date" +msgstr "тэрмін" + +msgid "session" +msgstr "сэсія" + +msgid "sessions" +msgstr "сэсіі" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/bg/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/bg/LC_MESSAGES/django.mo new file mode 100644 index 0000000..68e4b05 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/bg/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/bg/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/bg/LC_MESSAGES/django.po new file mode 100644 index 0000000..aeab9b8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/bg/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# arneatec , 2022 +# Jannis Leidel , 2011 +# vestimir , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2022-01-14 11:56+0000\n" +"Last-Translator: arneatec \n" +"Language-Team: Bulgarian (http://www.transifex.com/django/django/language/" +"bg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Сесии" + +msgid "session key" +msgstr "ключ на сесията" + +msgid "session data" +msgstr "данни от сесията" + +msgid "expire date" +msgstr "дата на изтичане на валидност" + +msgid "session" +msgstr "сесия" + +msgid "sessions" +msgstr "сесии" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/bn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/bn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c029c76 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/bn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/bn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/bn/LC_MESSAGES/django.po new file mode 100644 index 0000000..aa4a335 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/bn/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Bengali (http://www.transifex.com/django/django/language/" +"bn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "" + +msgid "session key" +msgstr "সেশন কি" + +msgid "session data" +msgstr "সেশন ডাটা" + +msgid "expire date" +msgstr "মেয়াদ শেষের তারিখ" + +msgid "session" +msgstr "সেশন" + +msgid "sessions" +msgstr "সেশনসমূহ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/br/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/br/LC_MESSAGES/django.mo new file mode 100644 index 0000000..777a187 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/br/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/br/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/br/LC_MESSAGES/django.po new file mode 100644 index 0000000..a6c8c04 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/br/LC_MESSAGES/django.po @@ -0,0 +1,40 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Fulup , 2012 +# Irriep Nala Novram , 2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2018-10-19 23:05+0000\n" +"Last-Translator: Irriep Nala Novram \n" +"Language-Team: Breton (http://www.transifex.com/django/django/language/br/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: br\n" +"Plural-Forms: nplurals=5; plural=((n%10 == 1) && (n%100 != 11) && (n%100 !" +"=71) && (n%100 !=91) ? 0 :(n%10 == 2) && (n%100 != 12) && (n%100 !=72) && (n" +"%100 !=92) ? 1 :(n%10 ==3 || n%10==4 || n%10==9) && (n%100 < 10 || n% 100 > " +"19) && (n%100 < 70 || n%100 > 79) && (n%100 < 90 || n%100 > 99) ? 2 :(n != 0 " +"&& n % 1000000 == 0) ? 3 : 4);\n" + +msgid "Sessions" +msgstr "Dalc'hoù" + +msgid "session key" +msgstr "alc'hwez dalc'h" + +msgid "session data" +msgstr "roadennoù an dalc'h" + +msgid "expire date" +msgstr "deiziad fin" + +msgid "session" +msgstr "dalc'h" + +msgid "sessions" +msgstr "dalc'hoù" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/bs/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/bs/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f167bc8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/bs/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/bs/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/bs/LC_MESSAGES/django.po new file mode 100644 index 0000000..2ba36a9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/bs/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Bosnian (http://www.transifex.com/django/django/language/" +"bs/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bs\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Sessions" +msgstr "" + +msgid "session key" +msgstr "ključ sesije" + +msgid "session data" +msgstr "podaci sesije" + +msgid "expire date" +msgstr "datum isteka" + +msgid "session" +msgstr "sesija" + +msgid "sessions" +msgstr "sesije" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ca/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ca/LC_MESSAGES/django.mo new file mode 100644 index 0000000..480400c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ca/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ca/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ca/LC_MESSAGES/django.po new file mode 100644 index 0000000..cd7ea3f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ca/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Carles Barrobés , 2014 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Catalan (http://www.transifex.com/django/django/language/" +"ca/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ca\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Sessions" + +msgid "session key" +msgstr "clau de la sessió" + +msgid "session data" +msgstr "dades de la sessió" + +msgid "expire date" +msgstr "data de caducitat" + +msgid "session" +msgstr "sessió" + +msgid "sessions" +msgstr "sessions" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ckb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ckb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..24a4cc6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ckb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ckb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ckb/LC_MESSAGES/django.po new file mode 100644 index 0000000..fb8d23a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ckb/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# kosar tofiq , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2023-04-24 18:26+0000\n" +"Last-Translator: kosar tofiq , 2020\n" +"Language-Team: Central Kurdish (http://www.transifex.com/django/django/" +"language/ckb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ckb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "کۆڕەکان" + +msgid "session key" +msgstr "کلیلی کۆڕ" + +msgid "session data" +msgstr "دراوەی کۆڕ" + +msgid "expire date" +msgstr "بەرواری بەسەرچوون" + +msgid "session" +msgstr "کۆڕ" + +msgid "sessions" +msgstr "کۆڕەکان" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/cs/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/cs/LC_MESSAGES/django.mo new file mode 100644 index 0000000..80a9b27 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/cs/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/cs/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/cs/LC_MESSAGES/django.po new file mode 100644 index 0000000..743e3e4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/cs/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Vláďa Macek , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Czech (http://www.transifex.com/django/django/language/cs/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cs\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n " +"<= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n" + +msgid "Sessions" +msgstr "Sezení" + +msgid "session key" +msgstr "klíč sezení" + +msgid "session data" +msgstr "data sezení" + +msgid "expire date" +msgstr "datum expirace" + +msgid "session" +msgstr "sezení" + +msgid "sessions" +msgstr "sezení" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/cy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/cy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d4bee0c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/cy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/cy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/cy/LC_MESSAGES/django.po new file mode 100644 index 0000000..efd21c2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/cy/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Maredudd ap Gwyndaf , 2013-2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Maredudd ap Gwyndaf \n" +"Language-Team: Welsh (http://www.transifex.com/django/django/language/cy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cy\n" +"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != " +"11) ? 2 : 3;\n" + +msgid "Sessions" +msgstr "Sesiynau" + +msgid "session key" +msgstr "allwedd sesiwn" + +msgid "session data" +msgstr "data sesiwn" + +msgid "expire date" +msgstr "dyddiad terfyn" + +msgid "session" +msgstr "sesiwn" + +msgid "sessions" +msgstr "sesiynau" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/da/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/da/LC_MESSAGES/django.mo new file mode 100644 index 0000000..489874b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/da/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/da/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/da/LC_MESSAGES/django.po new file mode 100644 index 0000000..8d1689c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/da/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Erik Wognsen , 2014 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Danish (http://www.transifex.com/django/django/language/da/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: da\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Sessioner" + +msgid "session key" +msgstr "sessionsnøgle" + +msgid "session data" +msgstr "sessionsdata" + +msgid "expire date" +msgstr "udløbsdato" + +msgid "session" +msgstr "session" + +msgid "sessions" +msgstr "sessioner" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/de/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/de/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3af9146 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/de/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/de/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/de/LC_MESSAGES/django.po new file mode 100644 index 0000000..a3153e6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/de/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011,2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: German (http://www.transifex.com/django/django/language/de/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Sessions" + +msgid "session key" +msgstr "Sitzungs-ID" + +msgid "session data" +msgstr "Sitzungsdaten" + +msgid "expire date" +msgstr "Verfallsdatum" + +msgid "session" +msgstr "Sitzung" + +msgid "sessions" +msgstr "Sitzungen" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/dsb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/dsb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..cb8a5e8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/dsb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/dsb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/dsb/LC_MESSAGES/django.po new file mode 100644 index 0000000..9e2a233 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/dsb/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Michael Wolf , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 00:02+0000\n" +"Last-Translator: Michael Wolf \n" +"Language-Team: Lower Sorbian (http://www.transifex.com/django/django/" +"language/dsb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: dsb\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" + +msgid "Sessions" +msgstr "Póseźenja" + +msgid "session key" +msgstr "pósejźeński kluc" + +msgid "session data" +msgstr "pósejźeńske daty" + +msgid "expire date" +msgstr "datum spadnjenja" + +msgid "session" +msgstr "pósejźenje" + +msgid "sessions" +msgstr "pósejźenja" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/el/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/el/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a8ef4ca Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/el/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/el/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/el/LC_MESSAGES/django.po new file mode 100644 index 0000000..3813c31 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/el/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Pãnoș , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Pãnoș \n" +"Language-Team: Greek (http://www.transifex.com/django/django/language/el/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: el\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Συνεδρίες" + +msgid "session key" +msgstr "κλειδί συνεδρίας" + +msgid "session data" +msgstr "δεδομένα συνεδρίας" + +msgid "expire date" +msgstr "ημερομηνία λήξης" + +msgid "session" +msgstr "συνεδρία" + +msgid "sessions" +msgstr "συνεδρίες" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/en/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/en/LC_MESSAGES/django.mo new file mode 100644 index 0000000..08a7b68 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/en/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/en/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/en/LC_MESSAGES/django.po new file mode 100644 index 0000000..2ce1872 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/en/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +msgid "" +msgstr "" +"Project-Id-Version: Django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2010-05-13 15:35+0200\n" +"Last-Translator: Django team\n" +"Language-Team: English \n" +"Language: en\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: contrib/sessions/apps.py:8 +msgid "Sessions" +msgstr "" + +#: contrib/sessions/models.py:44 +msgid "session key" +msgstr "" + +#: contrib/sessions/models.py:46 +msgid "session data" +msgstr "" + +#: contrib/sessions/models.py:47 +msgid "expire date" +msgstr "" + +#: contrib/sessions/models.py:52 +msgid "session" +msgstr "" + +#: contrib/sessions/models.py:53 +msgid "sessions" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/en_AU/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/en_AU/LC_MESSAGES/django.mo new file mode 100644 index 0000000..fbc756b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/en_AU/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/en_AU/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/en_AU/LC_MESSAGES/django.po new file mode 100644 index 0000000..da9a8d4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/en_AU/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Tom Fifield , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2021-04-11 13:15+0000\n" +"Last-Translator: Tom Fifield \n" +"Language-Team: English (Australia) (http://www.transifex.com/django/django/" +"language/en_AU/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_AU\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Sessions" + +msgid "session key" +msgstr "session key" + +msgid "session data" +msgstr "session data" + +msgid "expire date" +msgstr "expire date" + +msgid "session" +msgstr "session" + +msgid "sessions" +msgstr "sessions" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/en_GB/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/en_GB/LC_MESSAGES/django.mo new file mode 100644 index 0000000..fd83c31 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/en_GB/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/en_GB/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/en_GB/LC_MESSAGES/django.po new file mode 100644 index 0000000..ee4a40d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/en_GB/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ross Poulton , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: English (United Kingdom) (http://www.transifex.com/django/" +"django/language/en_GB/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_GB\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "" + +msgid "session key" +msgstr "session key" + +msgid "session data" +msgstr "session data" + +msgid "expire date" +msgstr "expire date" + +msgid "session" +msgstr "session" + +msgid "sessions" +msgstr "sessions" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/eo/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/eo/LC_MESSAGES/django.mo new file mode 100644 index 0000000..258b370 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/eo/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/eo/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/eo/LC_MESSAGES/django.po new file mode 100644 index 0000000..7c1ab40 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/eo/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Baptiste Darthenay , 2014 +# kristjan , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Esperanto (http://www.transifex.com/django/django/language/" +"eo/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eo\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Seancoj" + +msgid "session key" +msgstr "seanco-ŝlosilo" + +msgid "session data" +msgstr "seanco-datumo" + +msgid "expire date" +msgstr "senvalidiĝ-dato" + +msgid "session" +msgstr "seanco" + +msgid "sessions" +msgstr "seancoj" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es/LC_MESSAGES/django.mo new file mode 100644 index 0000000..20e0a1c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es/LC_MESSAGES/django.po new file mode 100644 index 0000000..85241b3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ernesto Avilés Vázquez , 2014 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Spanish (http://www.transifex.com/django/django/language/" +"es/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Sesiones" + +msgid "session key" +msgstr "clave de sesión" + +msgid "session data" +msgstr "datos de sesión" + +msgid "expire date" +msgstr "fecha de caducidad" + +msgid "session" +msgstr "sesión" + +msgid "sessions" +msgstr "sesiones" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es_AR/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es_AR/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4a94ca3 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es_AR/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es_AR/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es_AR/LC_MESSAGES/django.po new file mode 100644 index 0000000..3840a2d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es_AR/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Ramiro Morales, 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Spanish (Argentina) (http://www.transifex.com/django/django/" +"language/es_AR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_AR\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Sesiones" + +msgid "session key" +msgstr "clave de sesión" + +msgid "session data" +msgstr "datos de la sesión" + +msgid "expire date" +msgstr "fecha de caducidad" + +msgid "session" +msgstr "sesión" + +msgid "sessions" +msgstr "sesiones" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es_CO/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es_CO/LC_MESSAGES/django.mo new file mode 100644 index 0000000..238fe24 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es_CO/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es_CO/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es_CO/LC_MESSAGES/django.po new file mode 100644 index 0000000..5d2faab --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es_CO/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Carlos Muñoz , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 22:00+0000\n" +"Last-Translator: Carlos Muñoz \n" +"Language-Team: Spanish (Colombia) (http://www.transifex.com/django/django/" +"language/es_CO/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_CO\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Sesiones" + +msgid "session key" +msgstr "clave de sesión" + +msgid "session data" +msgstr "datos de sesión" + +msgid "expire date" +msgstr "fecha de caducidad" + +msgid "session" +msgstr "sesión" + +msgid "sessions" +msgstr "sesiones" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es_MX/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es_MX/LC_MESSAGES/django.mo new file mode 100644 index 0000000..33f2811 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es_MX/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es_MX/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es_MX/LC_MESSAGES/django.po new file mode 100644 index 0000000..cb53c81 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es_MX/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Abraham Estrada, 2011 +# zodman , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: zodman \n" +"Language-Team: Spanish (Mexico) (http://www.transifex.com/django/django/" +"language/es_MX/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_MX\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Sesiones" + +msgid "session key" +msgstr "clave de sesión" + +msgid "session data" +msgstr "datos de la sesión" + +msgid "expire date" +msgstr "fecha de caducidad" + +msgid "session" +msgstr "período de sesiones" + +msgid "sessions" +msgstr "sesiones" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es_VE/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es_VE/LC_MESSAGES/django.mo new file mode 100644 index 0000000..32f6e8f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es_VE/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es_VE/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es_VE/LC_MESSAGES/django.po new file mode 100644 index 0000000..ccd4d09 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/es_VE/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:12+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Spanish (Venezuela) (http://www.transifex.com/projects/p/" +"django/language/es_VE/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_VE\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "" + +msgid "session key" +msgstr "" + +msgid "session data" +msgstr "" + +msgid "expire date" +msgstr "" + +msgid "session" +msgstr "" + +msgid "sessions" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/et/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/et/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8d9fe06 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/et/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/et/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/et/LC_MESSAGES/django.po new file mode 100644 index 0000000..b7efce9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/et/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Marti Raudsepp , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Estonian (http://www.transifex.com/django/django/language/" +"et/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: et\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Sessioonid" + +msgid "session key" +msgstr "sessioonivõti" + +msgid "session data" +msgstr "sessiooni andmed" + +msgid "expire date" +msgstr "kehtivusaja lõpp" + +msgid "session" +msgstr "sessioon" + +msgid "sessions" +msgstr "sessioonid" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/eu/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/eu/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1d92fef Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/eu/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/eu/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/eu/LC_MESSAGES/django.po new file mode 100644 index 0000000..aafbe62 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/eu/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Eneko Illarramendi , 2017 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Eneko Illarramendi \n" +"Language-Team: Basque (http://www.transifex.com/django/django/language/eu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Sesioak" + +msgid "session key" +msgstr "sesioaren giltza" + +msgid "session data" +msgstr "sesioaren datuak" + +msgid "expire date" +msgstr "amaiera data" + +msgid "session" +msgstr "sesioa" + +msgid "sessions" +msgstr "sesioak" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/fa/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/fa/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c2fb662 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/fa/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/fa/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/fa/LC_MESSAGES/django.po new file mode 100644 index 0000000..276d2de --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/fa/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Reza Mohammadi , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Persian (http://www.transifex.com/django/django/language/" +"fa/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fa\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Sessions" +msgstr "نشست‌ها" + +msgid "session key" +msgstr "کلید نشست" + +msgid "session data" +msgstr "اطلاعات نشست" + +msgid "expire date" +msgstr "تاریخ انقضاء" + +msgid "session" +msgstr "نشست" + +msgid "sessions" +msgstr "نشست‌ها" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/fi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/fi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7273f8a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/fi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/fi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/fi/LC_MESSAGES/django.po new file mode 100644 index 0000000..40b2425 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/fi/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Klaus Dahlén , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Finnish (http://www.transifex.com/django/django/language/" +"fi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Istunnot" + +msgid "session key" +msgstr "istunnon avain" + +msgid "session data" +msgstr "istunnon tiedot" + +msgid "expire date" +msgstr "vanhenee" + +msgid "session" +msgstr "istunto" + +msgid "sessions" +msgstr "istunnot" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/fr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/fr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..753c301 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/fr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/fr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 0000000..cc4a9e6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Claude Paroz , 2014 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: French (http://www.transifex.com/django/django/language/fr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Sessions" +msgstr "Sessions" + +msgid "session key" +msgstr "clé de session" + +msgid "session data" +msgstr "données de session" + +msgid "expire date" +msgstr "date d'expiration" + +msgid "session" +msgstr "session" + +msgid "sessions" +msgstr "sessions" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/fy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/fy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..489bbab Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/fy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/fy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/fy/LC_MESSAGES/django.po new file mode 100644 index 0000000..6e216b3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/fy/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:13+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Western Frisian (http://www.transifex.com/projects/p/django/" +"language/fy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fy\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "" + +msgid "session key" +msgstr "" + +msgid "session data" +msgstr "" + +msgid "expire date" +msgstr "" + +msgid "session" +msgstr "" + +msgid "sessions" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ga/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ga/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2b854bd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ga/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ga/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ga/LC_MESSAGES/django.po new file mode 100644 index 0000000..e9e1278 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ga/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Luke Blaney , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2019-06-22 21:45+0000\n" +"Last-Translator: Luke Blaney \n" +"Language-Team: Irish (http://www.transifex.com/django/django/language/ga/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ga\n" +"Plural-Forms: nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : " +"4);\n" + +msgid "Sessions" +msgstr "Seisiúin" + +msgid "session key" +msgstr "eochair an seisiún" + +msgid "session data" +msgstr "sonraíocht an seisiún" + +msgid "expire date" +msgstr "Data dul as feidhm" + +msgid "session" +msgstr "seisiún" + +msgid "sessions" +msgstr "seisúin" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/gd/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/gd/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ef41ac8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/gd/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/gd/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/gd/LC_MESSAGES/django.po new file mode 100644 index 0000000..b291970 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/gd/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# GunChleoc, 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-22 17:29+0000\n" +"Last-Translator: GunChleoc\n" +"Language-Team: Gaelic, Scottish (http://www.transifex.com/django/django/" +"language/gd/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: gd\n" +"Plural-Forms: nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : " +"(n > 2 && n < 20) ? 2 : 3;\n" + +msgid "Sessions" +msgstr "Seiseanan" + +msgid "session key" +msgstr "iuchair an t-seisein" + +msgid "session data" +msgstr "dàta an t-seisein" + +msgid "expire date" +msgstr "falbhaidh an ùine air" + +msgid "session" +msgstr "seisean" + +msgid "sessions" +msgstr "seiseanan" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/gl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/gl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f620215 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/gl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/gl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/gl/LC_MESSAGES/django.po new file mode 100644 index 0000000..5e90f74 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/gl/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Leandro Regueiro , 2013 +# X Bello , 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2023-04-24 18:26+0000\n" +"Last-Translator: X Bello , 2023\n" +"Language-Team: Galician (http://www.transifex.com/django/django/language/" +"gl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: gl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Sesións" + +msgid "session key" +msgstr "chave da sesión" + +msgid "session data" +msgstr "datos da sesión" + +msgid "expire date" +msgstr "data de caducidade" + +msgid "session" +msgstr "sesión" + +msgid "sessions" +msgstr "sesións" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/he/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/he/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1cce904 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/he/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/he/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/he/LC_MESSAGES/django.po new file mode 100644 index 0000000..e8bd934 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/he/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Meir Kriheli , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Hebrew (http://www.transifex.com/django/django/language/he/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: he\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % " +"1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;\n" + +msgid "Sessions" +msgstr "התחברויות" + +msgid "session key" +msgstr "מפתח התחברות (session key)" + +msgid "session data" +msgstr "מידע התחברות (session data)" + +msgid "expire date" +msgstr "תאריך פג תוקף" + +msgid "session" +msgstr "התחברות" + +msgid "sessions" +msgstr "התחברויות" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..34947ca Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hi/LC_MESSAGES/django.po new file mode 100644 index 0000000..90a5061 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hi/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Sandeep Satavlekar , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Hindi (http://www.transifex.com/django/django/language/hi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "" + +msgid "session key" +msgstr "सत्र कुंजी" + +msgid "session data" +msgstr "सत्र सामग्री" + +msgid "expire date" +msgstr "समाप्ति तिथी" + +msgid "session" +msgstr "सत्र" + +msgid "sessions" +msgstr "सत्रें" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d697c5f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hr/LC_MESSAGES/django.po new file mode 100644 index 0000000..cb0405c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hr/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Mislav Cimperšak , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Mislav Cimperšak \n" +"Language-Team: Croatian (http://www.transifex.com/django/django/language/" +"hr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hr\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +msgid "Sessions" +msgstr "Sessions" + +msgid "session key" +msgstr "session ključ (key)" + +msgid "session data" +msgstr "session podaci" + +msgid "expire date" +msgstr "ističe na datum" + +msgid "session" +msgstr "session" + +msgid "sessions" +msgstr "sessions" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hsb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hsb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e2dcbe6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hsb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hsb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hsb/LC_MESSAGES/django.po new file mode 100644 index 0000000..04fd111 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hsb/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Michael Wolf , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 00:02+0000\n" +"Last-Translator: Michael Wolf \n" +"Language-Team: Upper Sorbian (http://www.transifex.com/django/django/" +"language/hsb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hsb\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" + +msgid "Sessions" +msgstr "Posedźenja" + +msgid "session key" +msgstr "posedźenski kluč" + +msgid "session data" +msgstr "posedźenske daty" + +msgid "expire date" +msgstr "datum spadnjenja" + +msgid "session" +msgstr "posedźenje" + +msgid "sessions" +msgstr "posedźenja" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hu/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hu/LC_MESSAGES/django.mo new file mode 100644 index 0000000..01e0540 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hu/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hu/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hu/LC_MESSAGES/django.po new file mode 100644 index 0000000..17623ec --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hu/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# András Veres-Szentkirályi, 2016 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: János R (Hangya)\n" +"Language-Team: Hungarian (http://www.transifex.com/django/django/language/" +"hu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Munkamenetek" + +msgid "session key" +msgstr "munkamenet kulcs" + +msgid "session data" +msgstr "munkamenet adat" + +msgid "expire date" +msgstr "lejárat dátuma" + +msgid "session" +msgstr "munkamenet" + +msgid "sessions" +msgstr "munkamenetek" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5845568 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hy/LC_MESSAGES/django.po new file mode 100644 index 0000000..9961a82 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/hy/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2018-11-01 20:47+0000\n" +"Last-Translator: Ruben Harutyunov \n" +"Language-Team: Armenian (http://www.transifex.com/django/django/language/" +"hy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hy\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Սեսսիաներ" + +msgid "session key" +msgstr "սեսսիայի բանալի" + +msgid "session data" +msgstr "սեսսիայի տվյալներ" + +msgid "expire date" +msgstr "պիտանիության ժամկետը" + +msgid "session" +msgstr "սեսսիա" + +msgid "sessions" +msgstr "սեսսիաներ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ia/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ia/LC_MESSAGES/django.mo new file mode 100644 index 0000000..24f465c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ia/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ia/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ia/LC_MESSAGES/django.po new file mode 100644 index 0000000..1e271ee --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ia/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Martijn Dekker , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 22:00+0000\n" +"Last-Translator: Martijn Dekker \n" +"Language-Team: Interlingua (http://www.transifex.com/django/django/language/" +"ia/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ia\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Sessiones" + +msgid "session key" +msgstr "clave de session" + +msgid "session data" +msgstr "datos de session" + +msgid "expire date" +msgstr "data de expiration" + +msgid "session" +msgstr "session" + +msgid "sessions" +msgstr "sessiones" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/id/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/id/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d02dea8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/id/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/id/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/id/LC_MESSAGES/django.po new file mode 100644 index 0000000..ef9b14f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/id/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# M Asep Indrayana , 2015 +# rodin , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: rodin \n" +"Language-Team: Indonesian (http://www.transifex.com/django/django/language/" +"id/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: id\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sessions" +msgstr "Sesi" + +msgid "session key" +msgstr "kunci sesi" + +msgid "session data" +msgstr "data sesi" + +msgid "expire date" +msgstr "tanggal kedaluwarsa" + +msgid "session" +msgstr "sesi" + +msgid "sessions" +msgstr "sesi" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/io/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/io/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e781b05 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/io/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/io/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/io/LC_MESSAGES/django.po new file mode 100644 index 0000000..8487664 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/io/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Viko Bartero , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-20 01:58+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Ido (http://www.transifex.com/django/django/language/io/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: io\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "" + +msgid "session key" +msgstr "sesiono klefo" + +msgid "session data" +msgstr "sesiono datumi" + +msgid "expire date" +msgstr "expiro dato" + +msgid "session" +msgstr "sesiono" + +msgid "sessions" +msgstr "sesioni" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/is/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/is/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a6dd863 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/is/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/is/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/is/LC_MESSAGES/django.po new file mode 100644 index 0000000..0bdaf5d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/is/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Icelandic (http://www.transifex.com/django/django/language/" +"is/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: is\n" +"Plural-Forms: nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);\n" + +msgid "Sessions" +msgstr "" + +msgid "session key" +msgstr "setulykill" + +msgid "session data" +msgstr "setugögn" + +msgid "expire date" +msgstr "fyrningardagsetning" + +msgid "session" +msgstr "seta" + +msgid "sessions" +msgstr "setur" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/it/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/it/LC_MESSAGES/django.mo new file mode 100644 index 0000000..33e2cd7 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/it/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/it/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/it/LC_MESSAGES/django.po new file mode 100644 index 0000000..3d8353c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/it/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Marco Bonetti, 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: palmux \n" +"Language-Team: Italian (http://www.transifex.com/django/django/language/" +"it/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: it\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Sessioni" + +msgid "session key" +msgstr "chiave di sessione" + +msgid "session data" +msgstr "dati di sessione" + +msgid "expire date" +msgstr "data di scadenza" + +msgid "session" +msgstr "sessione" + +msgid "sessions" +msgstr "sessioni" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ja/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ja/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0de4c29 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ja/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ja/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ja/LC_MESSAGES/django.po new file mode 100644 index 0000000..25ef99a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ja/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Shinya Okano , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Japanese (http://www.transifex.com/django/django/language/" +"ja/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ja\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sessions" +msgstr "セッション" + +msgid "session key" +msgstr "セッションキー" + +msgid "session data" +msgstr "セッションデータ" + +msgid "expire date" +msgstr "有効期限" + +msgid "session" +msgstr "セッション" + +msgid "sessions" +msgstr "セッション" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ka/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ka/LC_MESSAGES/django.mo new file mode 100644 index 0000000..be4e5d8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ka/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ka/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ka/LC_MESSAGES/django.po new file mode 100644 index 0000000..bcdcb5f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ka/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Georgian (http://www.transifex.com/django/django/language/" +"ka/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ka\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +msgid "Sessions" +msgstr "" + +msgid "session key" +msgstr "სესიის გასაღები" + +msgid "session data" +msgstr "სესიის მონაცემები" + +msgid "expire date" +msgstr "ამოწურვის თარიღი" + +msgid "session" +msgstr "სესია" + +msgid "sessions" +msgstr "სესიები" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/kab/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/kab/LC_MESSAGES/django.mo new file mode 100644 index 0000000..6f22bc4 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/kab/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/kab/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/kab/LC_MESSAGES/django.po new file mode 100644 index 0000000..b3aa45f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/kab/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-10-06 11:49+0000\n" +"Last-Translator: Muḥend Belqasem \n" +"Language-Team: Kabyle (http://www.transifex.com/django/django/language/" +"kab/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kab\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Tiɣimiyin" + +msgid "session key" +msgstr "tasarutt n tɣimit" + +msgid "session data" +msgstr "isefka n tɣimit" + +msgid "expire date" +msgstr "azemz n tgara" + +msgid "session" +msgstr "tiɣimit" + +msgid "sessions" +msgstr "tiɣimiyin" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/kk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/kk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f3b0c1b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/kk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/kk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/kk/LC_MESSAGES/django.po new file mode 100644 index 0000000..5777dc2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/kk/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Baurzhan Muftakhidinov , 2015 +# yun_man_ger , 2011 +# Zhazira , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Baurzhan Muftakhidinov \n" +"Language-Team: Kazakh (http://www.transifex.com/django/django/language/kk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kk\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +msgid "Sessions" +msgstr "Сессиялар" + +msgid "session key" +msgstr "сессия кілті" + +msgid "session data" +msgstr "сессия деректері" + +msgid "expire date" +msgstr "мерзімі аяқталу уақыты" + +msgid "session" +msgstr "сессия" + +msgid "sessions" +msgstr "сессиялар" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/km/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/km/LC_MESSAGES/django.mo new file mode 100644 index 0000000..af28c29 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/km/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/km/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/km/LC_MESSAGES/django.po new file mode 100644 index 0000000..1c1252c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/km/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Khmer (http://www.transifex.com/django/django/language/km/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: km\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sessions" +msgstr "" + +msgid "session key" +msgstr "លេខសំគាល់​រយះពេល​ពិនិត្យ​ចូល" + +msgid "session data" +msgstr "ទិន្នន័យរយះពេល​ពិនិត្យ​ចូល" + +msgid "expire date" +msgstr "ហួសពេលកំណត់" + +msgid "session" +msgstr "រយះពេល​ពិនិត្យ​ចូល" + +msgid "sessions" +msgstr "រយះពេល​ពិនិត្យ​ចូល" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/kn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/kn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..23b8948 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/kn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/kn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/kn/LC_MESSAGES/django.po new file mode 100644 index 0000000..0811ad8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/kn/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Rohith PR, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2021-08-03 10:50+0000\n" +"Last-Translator: Rohith PR\n" +"Language-Team: Kannada (http://www.transifex.com/django/django/language/" +"kn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kn\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Sessions" +msgstr "ಅಧಿವೇಶನಗಳು" + +msgid "session key" +msgstr "ಅಧಿವೇಶನದ ಕೀಲಿಕೈ" + +msgid "session data" +msgstr "ಅಧಿವೇಶನದ ದತ್ತಾಂಶ" + +msgid "expire date" +msgstr "ಅವಧಿಮೀರುವ ದಿನಾಂಕ" + +msgid "session" +msgstr "ಅಧಿವೇಶನ" + +msgid "sessions" +msgstr "ಅಧಿವೇಶನಗಳು" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ko/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ko/LC_MESSAGES/django.mo new file mode 100644 index 0000000..144d87c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ko/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ko/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ko/LC_MESSAGES/django.po new file mode 100644 index 0000000..74c622c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ko/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Chr0m3 , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Chr0m3 \n" +"Language-Team: Korean (http://www.transifex.com/django/django/language/ko/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ko\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sessions" +msgstr "세션" + +msgid "session key" +msgstr "세션 키" + +msgid "session data" +msgstr "세션 날짜" + +msgid "expire date" +msgstr "유효날짜" + +msgid "session" +msgstr "세션" + +msgid "sessions" +msgstr "세션" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ky/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ky/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f24928a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ky/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ky/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ky/LC_MESSAGES/django.po new file mode 100644 index 0000000..7d9feac --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ky/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Soyuzbek Orozbek uulu , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2020-05-23 06:08+0000\n" +"Last-Translator: Soyuzbek Orozbek uulu \n" +"Language-Team: Kyrgyz (http://www.transifex.com/django/django/language/ky/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ky\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sessions" +msgstr "Отурумдар" + +msgid "session key" +msgstr "отурум ачкычы" + +msgid "session data" +msgstr "отурум берилиши" + +msgid "expire date" +msgstr "мөөнөтү" + +msgid "session" +msgstr "отурум" + +msgid "sessions" +msgstr "отурумдар" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/lb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/lb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5b7937f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/lb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/lb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/lb/LC_MESSAGES/django.po new file mode 100644 index 0000000..e7c83d4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/lb/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:12+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Luxembourgish (http://www.transifex.com/projects/p/django/" +"language/lb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "" + +msgid "session key" +msgstr "" + +msgid "session data" +msgstr "" + +msgid "expire date" +msgstr "" + +msgid "session" +msgstr "" + +msgid "sessions" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/lt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/lt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..bfd37fb Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/lt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/lt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/lt/LC_MESSAGES/django.po new file mode 100644 index 0000000..0051e30 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/lt/LC_MESSAGES/django.po @@ -0,0 +1,39 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Matas Dailyda , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Matas Dailyda \n" +"Language-Team: Lithuanian (http://www.transifex.com/django/django/language/" +"lt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lt\n" +"Plural-Forms: nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < " +"11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? " +"1 : n % 1 != 0 ? 2: 3);\n" + +msgid "Sessions" +msgstr "Sesijos" + +msgid "session key" +msgstr "sesijos raktas" + +msgid "session data" +msgstr "sesijos data" + +msgid "expire date" +msgstr "galiojima data" + +msgid "session" +msgstr "sesija" + +msgid "sessions" +msgstr "sesijos" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/lv/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/lv/LC_MESSAGES/django.mo new file mode 100644 index 0000000..07f5308 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/lv/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/lv/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/lv/LC_MESSAGES/django.po new file mode 100644 index 0000000..45fdde5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/lv/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# peterisb , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: peterisb \n" +"Language-Team: Latvian (http://www.transifex.com/django/django/language/" +"lv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lv\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : " +"2);\n" + +msgid "Sessions" +msgstr "Sesijas" + +msgid "session key" +msgstr "sesijas atslēga" + +msgid "session data" +msgstr "sesijas dati" + +msgid "expire date" +msgstr "izbeigšanās datums" + +msgid "session" +msgstr "sesija" + +msgid "sessions" +msgstr "sesijas" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/mk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/mk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..bdf114e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/mk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/mk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/mk/LC_MESSAGES/django.po new file mode 100644 index 0000000..1e1162b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/mk/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Vasil Vangelovski , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Macedonian (http://www.transifex.com/django/django/language/" +"mk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mk\n" +"Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n" + +msgid "Sessions" +msgstr "Сесии" + +msgid "session key" +msgstr "сесиски клуч" + +msgid "session data" +msgstr "сесиски податоци" + +msgid "expire date" +msgstr "датум на истекување" + +msgid "session" +msgstr "сесија" + +msgid "sessions" +msgstr "сесии" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ml/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ml/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9710d02 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ml/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ml/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ml/LC_MESSAGES/django.po new file mode 100644 index 0000000..ecaa341 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ml/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Hrishikesh , 2019 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2019-03-03 10:00+0000\n" +"Last-Translator: Hrishikesh \n" +"Language-Team: Malayalam (http://www.transifex.com/django/django/language/" +"ml/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ml\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "സെഷനുകൾ" + +msgid "session key" +msgstr "സെഷന്‍ കീ" + +msgid "session data" +msgstr "സെഷനിലെ ഡാറ്റ" + +msgid "expire date" +msgstr "കാലാവധി തീരുന്ന തിയ്യതി" + +msgid "session" +msgstr "സെഷന്‍" + +msgid "sessions" +msgstr "സെഷനുകള്‍" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/mn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/mn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f214362 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/mn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/mn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/mn/LC_MESSAGES/django.po new file mode 100644 index 0000000..4ff7c35 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/mn/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bayarkhuu Bataa, 2014 +# Jannis Leidel , 2011 +# Анхбаяр Анхаа , 2011,2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2018-07-09 06:53+0000\n" +"Last-Translator: Анхбаяр Анхаа \n" +"Language-Team: Mongolian (http://www.transifex.com/django/django/language/" +"mn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Session-ууд" + +msgid "session key" +msgstr "session түлхүүр" + +msgid "session data" +msgstr "session өгөгдөл" + +msgid "expire date" +msgstr "дуусах хугацаа" + +msgid "session" +msgstr "session" + +msgid "sessions" +msgstr "session-ууд" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/mr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/mr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..183b3d1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/mr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/mr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/mr/LC_MESSAGES/django.po new file mode 100644 index 0000000..45b727e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/mr/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:12+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Marathi (http://www.transifex.com/projects/p/django/language/" +"mr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mr\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "" + +msgid "session key" +msgstr "" + +msgid "session data" +msgstr "" + +msgid "expire date" +msgstr "" + +msgid "session" +msgstr "" + +msgid "sessions" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ms/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ms/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f46c07b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ms/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ms/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ms/LC_MESSAGES/django.po new file mode 100644 index 0000000..4e3b6aa --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ms/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jafry Hisham, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2021-11-16 12:39+0000\n" +"Last-Translator: Jafry Hisham\n" +"Language-Team: Malay (http://www.transifex.com/django/django/language/ms/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ms\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sessions" +msgstr "Sesi-sesi" + +msgid "session key" +msgstr "Kunci sesi" + +msgid "session data" +msgstr "Data sesi" + +msgid "expire date" +msgstr "Tarikh tamat tempoh" + +msgid "session" +msgstr "sesi" + +msgid "sessions" +msgstr "sesi-sesi" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/my/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/my/LC_MESSAGES/django.mo new file mode 100644 index 0000000..73d049a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/my/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/my/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/my/LC_MESSAGES/django.po new file mode 100644 index 0000000..7457874 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/my/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Yhal Htet Aung , 2013,2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:50+0000\n" +"Last-Translator: Yhal Htet Aung \n" +"Language-Team: Burmese (http://www.transifex.com/django/django/language/" +"my/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: my\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sessions" +msgstr "ကြားကာလများ" + +msgid "session key" +msgstr "ကြားကာလသော့" + +msgid "session data" +msgstr "ကြားကာလအချက်အလက်" + +msgid "expire date" +msgstr "သက်တမ်းကုန်နေ့စွဲ" + +msgid "session" +msgstr "ကြားကာလ" + +msgid "sessions" +msgstr "ကြားကာလများ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/nb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/nb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..78c5727 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/nb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/nb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/nb/LC_MESSAGES/django.po new file mode 100644 index 0000000..7a6d5d0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/nb/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# jensadne , 2014 +# Jon , 2012 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Norwegian Bokmål (http://www.transifex.com/django/django/" +"language/nb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Økter" + +msgid "session key" +msgstr "øktnøkkel" + +msgid "session data" +msgstr "øktdata" + +msgid "expire date" +msgstr "utløpsdato" + +msgid "session" +msgstr "økt" + +msgid "sessions" +msgstr "økter" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ne/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ne/LC_MESSAGES/django.mo new file mode 100644 index 0000000..93ff678 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ne/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ne/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ne/LC_MESSAGES/django.po new file mode 100644 index 0000000..c2b6e8c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ne/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Paras Nath Chaudhary , 2012 +# Sagar Chalise , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Sagar Chalise \n" +"Language-Team: Nepali (http://www.transifex.com/django/django/language/ne/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ne\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "अवधिहरु" + +msgid "session key" +msgstr "अवधि साँचो" + +msgid "session data" +msgstr "अवधि विवरण" + +msgid "expire date" +msgstr "खारेज मिति" + +msgid "session" +msgstr "अवधि" + +msgid "sessions" +msgstr "अवधिहरु" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/nl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/nl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c44a8fc Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/nl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/nl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/nl/LC_MESSAGES/django.po new file mode 100644 index 0000000..60698e5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/nl/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Sander Steffann , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Sander Steffann \n" +"Language-Team: Dutch (http://www.transifex.com/django/django/language/nl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Sessies" + +msgid "session key" +msgstr "sessiesleutel" + +msgid "session data" +msgstr "sessiegegevens" + +msgid "expire date" +msgstr "verloopdatum" + +msgid "session" +msgstr "sessie" + +msgid "sessions" +msgstr "sessies" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/nn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/nn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..285d386 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/nn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/nn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/nn/LC_MESSAGES/django.po new file mode 100644 index 0000000..802d36d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/nn/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Sivert Olstad, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2021-10-26 12:34+0000\n" +"Last-Translator: Sivert Olstad\n" +"Language-Team: Norwegian Nynorsk (http://www.transifex.com/django/django/" +"language/nn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Sesjonar" + +msgid "session key" +msgstr "sesjonsnøkkel" + +msgid "session data" +msgstr "sesjonsdata" + +msgid "expire date" +msgstr "utløpsdato" + +msgid "session" +msgstr "sesjon" + +msgid "sessions" +msgstr "sesjonar" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/os/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/os/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4ab9e90 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/os/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/os/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/os/LC_MESSAGES/django.po new file mode 100644 index 0000000..0588ebb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/os/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Soslan Khubulov , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:58+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Ossetic (http://www.transifex.com/django/django/language/" +"os/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: os\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "" + +msgid "session key" +msgstr "сессийы амонӕн" + +msgid "session data" +msgstr "сессийы рардтӕ" + +msgid "expire date" +msgstr "фӕуды афон" + +msgid "session" +msgstr "сесси" + +msgid "sessions" +msgstr "сесситӕ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/pa/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/pa/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9c4c9da Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/pa/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/pa/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/pa/LC_MESSAGES/django.po new file mode 100644 index 0000000..3895f30 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/pa/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Panjabi (Punjabi) (http://www.transifex.com/django/django/" +"language/pa/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pa\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "" + +msgid "session key" +msgstr "ਸ਼ੈਸ਼ਨ ਕੁੰਜੀ" + +msgid "session data" +msgstr "ਸ਼ੈਸ਼ਨ ਡਾਟਾ" + +msgid "expire date" +msgstr "ਮਿਆਦ ਮਿਤੀ" + +msgid "session" +msgstr "ਸ਼ੈਸ਼ਨ" + +msgid "sessions" +msgstr "ਸ਼ੈਸ਼ਨ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/pl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/pl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b479f2b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/pl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/pl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/pl/LC_MESSAGES/django.po new file mode 100644 index 0000000..b72de94 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/pl/LC_MESSAGES/django.po @@ -0,0 +1,39 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Mattia Procopio , 2014 +# Tomasz Kajtoch , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Tomasz Kajtoch \n" +"Language-Team: Polish (http://www.transifex.com/django/django/language/pl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pl\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n" +"%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n" +"%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" + +msgid "Sessions" +msgstr "Sesje" + +msgid "session key" +msgstr "klucz sesji" + +msgid "session data" +msgstr "dane sesji" + +msgid "expire date" +msgstr "data wygaśnięcia sesji" + +msgid "session" +msgstr "sesja" + +msgid "sessions" +msgstr "sesje" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/pt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/pt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..bb50e3a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/pt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/pt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/pt/LC_MESSAGES/django.po new file mode 100644 index 0000000..69a3fa0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/pt/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Raúl Pedro Fernandes Santos, 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Portuguese (http://www.transifex.com/django/django/language/" +"pt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Sessões" + +msgid "session key" +msgstr "chave da sessão" + +msgid "session data" +msgstr "dados da sessão" + +msgid "expire date" +msgstr "data de expiração" + +msgid "session" +msgstr "sessão" + +msgid "sessions" +msgstr "sessões" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/pt_BR/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/pt_BR/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e4e0da1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/pt_BR/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/pt_BR/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/pt_BR/LC_MESSAGES/django.po new file mode 100644 index 0000000..ebe8e6a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/pt_BR/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Allisson Azevedo , 2014 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: andrewsmedina \n" +"Language-Team: Portuguese (Brazil) (http://www.transifex.com/django/django/" +"language/pt_BR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt_BR\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Sessions" +msgstr "Sessões" + +msgid "session key" +msgstr "chave da sessão" + +msgid "session data" +msgstr "dados da sessão" + +msgid "expire date" +msgstr "data de expiração" + +msgid "session" +msgstr "sessão" + +msgid "sessions" +msgstr "sessões" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ro/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ro/LC_MESSAGES/django.mo new file mode 100644 index 0000000..49ade94 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ro/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ro/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ro/LC_MESSAGES/django.po new file mode 100644 index 0000000..daae11e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ro/LC_MESSAGES/django.po @@ -0,0 +1,39 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Daniel Ursache-Dogariu, 2011 +# Jannis Leidel , 2011 +# Razvan Stefanescu , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Razvan Stefanescu \n" +"Language-Team: Romanian (http://www.transifex.com/django/django/language/" +"ro/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ro\n" +"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?" +"2:1));\n" + +msgid "Sessions" +msgstr "Sesiuni" + +msgid "session key" +msgstr "cheie sesiune" + +msgid "session data" +msgstr "date sesiune" + +msgid "expire date" +msgstr "dată expirare" + +msgid "session" +msgstr "sesiune" + +msgid "sessions" +msgstr "sesiuni" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ru/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ru/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8934770 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ru/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ru/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ru/LC_MESSAGES/django.po new file mode 100644 index 0000000..1f4a938 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ru/LC_MESSAGES/django.po @@ -0,0 +1,39 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Алексей Борискин , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Eugene MechanisM \n" +"Language-Team: Russian (http://www.transifex.com/django/django/language/" +"ru/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ru\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n" +"%100>=11 && n%100<=14)? 2 : 3);\n" + +msgid "Sessions" +msgstr "Сессии" + +msgid "session key" +msgstr "ключ сессии" + +msgid "session data" +msgstr "данные сессии" + +msgid "expire date" +msgstr "дата окончания" + +msgid "session" +msgstr "сессия" + +msgid "sessions" +msgstr "сессии" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..675f761 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sk/LC_MESSAGES/django.po new file mode 100644 index 0000000..ca01c84 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sk/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Martin Tóth , 2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Martin Tóth \n" +"Language-Team: Slovak (http://www.transifex.com/django/django/language/sk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n " +">= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);\n" + +msgid "Sessions" +msgstr "Relácie" + +msgid "session key" +msgstr "kľúč relácie" + +msgid "session data" +msgstr "údaje relácie" + +msgid "expire date" +msgstr "dátum vypršania platnosti" + +msgid "session" +msgstr "relácia" + +msgid "sessions" +msgstr "relácie" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a44169f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sl/LC_MESSAGES/django.po new file mode 100644 index 0000000..f06a9a2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sl/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# zejn , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Primož Verdnik \n" +"Language-Team: Slovenian (http://www.transifex.com/django/django/language/" +"sl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sl\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" + +msgid "Sessions" +msgstr "Seje" + +msgid "session key" +msgstr "ključ seje" + +msgid "session data" +msgstr "podatki seje" + +msgid "expire date" +msgstr "čas preteka" + +msgid "session" +msgstr "seja" + +msgid "sessions" +msgstr "seje" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sq/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sq/LC_MESSAGES/django.mo new file mode 100644 index 0000000..001dbcd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sq/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sq/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sq/LC_MESSAGES/django.po new file mode 100644 index 0000000..3299ef0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sq/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Besnik , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Besnik \n" +"Language-Team: Albanian (http://www.transifex.com/django/django/language/" +"sq/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sq\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Sesione" + +msgid "session key" +msgstr "kyç sesioni" + +msgid "session data" +msgstr "të dhëna sesioni" + +msgid "expire date" +msgstr "datë skadimi" + +msgid "session" +msgstr "sesion" + +msgid "sessions" +msgstr "sesione" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d89316d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sr/LC_MESSAGES/django.po new file mode 100644 index 0000000..97759a0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sr/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Branko Kokanovic , 2018 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2018-01-30 10:08+0000\n" +"Last-Translator: Branko Kokanovic \n" +"Language-Team: Serbian (http://www.transifex.com/django/django/language/" +"sr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Sessions" +msgstr "Сесије" + +msgid "session key" +msgstr "кључ сесије" + +msgid "session data" +msgstr "подаци сесије" + +msgid "expire date" +msgstr "датум застаревања" + +msgid "session" +msgstr "сесија" + +msgid "sessions" +msgstr "сесије" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sr_Latn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sr_Latn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..708ede0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sr_Latn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sr_Latn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sr_Latn/LC_MESSAGES/django.po new file mode 100644 index 0000000..1132d52 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sr_Latn/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Igor Jerosimić, 2019 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2019-06-27 12:40+0000\n" +"Last-Translator: Igor Jerosimić\n" +"Language-Team: Serbian (Latin) (http://www.transifex.com/django/django/" +"language/sr@latin/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr@latin\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Sessions" +msgstr "Sesije" + +msgid "session key" +msgstr "ključ sesije" + +msgid "session data" +msgstr "podaci sesije" + +msgid "expire date" +msgstr "datum zastarevanja" + +msgid "session" +msgstr "sesija" + +msgid "sessions" +msgstr "sesije" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sv/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sv/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b44d13a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sv/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sv/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sv/LC_MESSAGES/django.po new file mode 100644 index 0000000..bf18a34 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sv/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Jonathan Lindén, 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jonathan Lindén\n" +"Language-Team: Swedish (http://www.transifex.com/django/django/language/" +"sv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sv\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Sessioner" + +msgid "session key" +msgstr "sessionsnyckel" + +msgid "session data" +msgstr "sessionsdata" + +msgid "expire date" +msgstr "utgångsdatum" + +msgid "session" +msgstr "session" + +msgid "sessions" +msgstr "sessioner" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sw/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sw/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3b4e3a4 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sw/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sw/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sw/LC_MESSAGES/django.po new file mode 100644 index 0000000..f645ab4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/sw/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Machaku , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Swahili (http://www.transifex.com/django/django/language/" +"sw/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sw\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Vipindi" + +msgid "session key" +msgstr "ufunguo wa kipindi" + +msgid "session data" +msgstr "data za kipindi" + +msgid "expire date" +msgstr "tarehe ya mwisho ya matumizi" + +msgid "session" +msgstr "kipindi" + +msgid "sessions" +msgstr "vipindi" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ta/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ta/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a81d60d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ta/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ta/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ta/LC_MESSAGES/django.po new file mode 100644 index 0000000..21779b0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ta/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Tamil (http://www.transifex.com/django/django/language/ta/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ta\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "" + +msgid "session key" +msgstr "அமர்வு குறியீ" + +msgid "session data" +msgstr "அமர்வு தகவல்" + +msgid "expire date" +msgstr "காலாவதியாகும் தேதி" + +msgid "session" +msgstr "அமர்வு" + +msgid "sessions" +msgstr "அமர்வுகள்" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/te/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/te/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7a2be87 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/te/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/te/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/te/LC_MESSAGES/django.po new file mode 100644 index 0000000..c9832a4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/te/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# bhaskar teja yerneni , 2011 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Telugu (http://www.transifex.com/django/django/language/te/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: te\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "" + +msgid "session key" +msgstr "భాగము తాళంచెవి" + +msgid "session data" +msgstr "భాగము దత్తం" + +msgid "expire date" +msgstr "కాలం చెల్లు తేది." + +msgid "session" +msgstr "భాగము" + +msgid "sessions" +msgstr "భాగములు" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/tg/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/tg/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7a64c5b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/tg/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/tg/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/tg/LC_MESSAGES/django.po new file mode 100644 index 0000000..0860033 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/tg/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Surush Sufiew , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2020-05-15 00:34+0000\n" +"Last-Translator: Surush Sufiew \n" +"Language-Team: Tajik (http://www.transifex.com/django/django/language/tg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Сессияҳо" + +msgid "session key" +msgstr "калиди сессияҳо" + +msgid "session data" +msgstr "додаҳои сессияҳо" + +msgid "expire date" +msgstr "санаи анҷом" + +msgid "session" +msgstr "сессия" + +msgid "sessions" +msgstr "сессияҳо" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/th/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/th/LC_MESSAGES/django.mo new file mode 100644 index 0000000..462cce8 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/th/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/th/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/th/LC_MESSAGES/django.po new file mode 100644 index 0000000..9f7648f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/th/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Kowit Charoenratchatabhan , 2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2018-05-06 07:45+0000\n" +"Last-Translator: Kowit Charoenratchatabhan \n" +"Language-Team: Thai (http://www.transifex.com/django/django/language/th/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: th\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sessions" +msgstr "เซสชัน" + +msgid "session key" +msgstr "เซสชันคีย์" + +msgid "session data" +msgstr "ข้อมูลเซสชัน" + +msgid "expire date" +msgstr "วันหมดอายุ" + +msgid "session" +msgstr "เซสชัน" + +msgid "sessions" +msgstr "เซสชัน" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/tk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/tk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..18fdb60 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/tk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/tk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/tk/LC_MESSAGES/django.po new file mode 100644 index 0000000..f5ace16 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/tk/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Welbeck Garli , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2020-07-06 11:50+0000\n" +"Last-Translator: Resulkary \n" +"Language-Team: Turkmen (http://www.transifex.com/django/django/language/" +"tk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tk\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "Sessiýalar" + +msgid "session key" +msgstr "sessiýa açary" + +msgid "session data" +msgstr "sessiýa maglumaty" + +msgid "expire date" +msgstr "gutarýan senesi" + +msgid "session" +msgstr "sessiýa" + +msgid "sessions" +msgstr "sessiýalar" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/tr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/tr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3125a69 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/tr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/tr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/tr/LC_MESSAGES/django.po new file mode 100644 index 0000000..a23226b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/tr/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# BouRock, 2014 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Turkish (http://www.transifex.com/django/django/language/" +"tr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Sessions" +msgstr "Oturumlar" + +msgid "session key" +msgstr "oturum anahtarı" + +msgid "session data" +msgstr "oturum verisi" + +msgid "expire date" +msgstr "bitiş tarihi" + +msgid "session" +msgstr "oturum" + +msgid "sessions" +msgstr "oturumlar" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/tt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/tt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e552192 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/tt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/tt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/tt/LC_MESSAGES/django.po new file mode 100644 index 0000000..d74b9f4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/tt/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Azat Khasanshin , 2011 +# v_ildar , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Tatar (http://www.transifex.com/django/django/language/tt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tt\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sessions" +msgstr "Эш сеанслары" + +msgid "session key" +msgstr "эш сеансы ачкычы" + +msgid "session data" +msgstr "эш сеансы бирелмәләре" + +msgid "expire date" +msgstr "искерү көне" + +msgid "session" +msgstr "эш сеансы" + +msgid "sessions" +msgstr "эш сеанслары" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/udm/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/udm/LC_MESSAGES/django.mo new file mode 100644 index 0000000..af7ab53 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/udm/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/udm/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/udm/LC_MESSAGES/django.po new file mode 100644 index 0000000..d0a7115 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/udm/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:13+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Udmurt (http://www.transifex.com/projects/p/django/language/" +"udm/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: udm\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sessions" +msgstr "" + +msgid "session key" +msgstr "" + +msgid "session data" +msgstr "" + +msgid "expire date" +msgstr "" + +msgid "session" +msgstr "" + +msgid "sessions" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ug/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ug/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1a4986d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ug/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ug/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ug/LC_MESSAGES/django.po new file mode 100644 index 0000000..5ee4065 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ug/LC_MESSAGES/django.po @@ -0,0 +1,34 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2023-12-04 18:26+0000\n" +"Last-Translator: Django team\n" +"Language-Team: Uyghur (http://app.transifex.com/django/django/language/ug/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ug\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "ئەڭگىمە" + +msgid "session key" +msgstr "ئەڭگىمە ئاچقۇچى" + +msgid "session data" +msgstr "ئەڭگىمە سانلىق مەلۇماتى" + +msgid "expire date" +msgstr "ئاخىرلىشىش ۋاقتى" + +msgid "session" +msgstr "ئەڭگىمە" + +msgid "sessions" +msgstr "ئەڭگىمەلەر" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/uk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/uk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a2def30 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/uk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/uk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/uk/LC_MESSAGES/django.po new file mode 100644 index 0000000..befabf0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/uk/LC_MESSAGES/django.po @@ -0,0 +1,40 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Oleksandr Chernihov , 2014 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Mykola Zamkovoi \n" +"Language-Team: Ukrainian (http://www.transifex.com/django/django/language/" +"uk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: uk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != " +"11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % " +"100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || " +"(n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n" + +msgid "Sessions" +msgstr "Сесії" + +msgid "session key" +msgstr "ключ сесії" + +msgid "session data" +msgstr "дані сесії" + +msgid "expire date" +msgstr "термін придатності" + +msgid "session" +msgstr "сесія" + +msgid "sessions" +msgstr "сесії" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ur/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ur/LC_MESSAGES/django.mo new file mode 100644 index 0000000..493b9c2 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ur/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ur/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ur/LC_MESSAGES/django.po new file mode 100644 index 0000000..62f6255 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/ur/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Mansoorulhaq Mansoor , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Urdu (http://www.transifex.com/django/django/language/ur/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ur\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sessions" +msgstr "" + +msgid "session key" +msgstr "کلید نشست" + +msgid "session data" +msgstr "نشست کا ڈیٹا" + +msgid "expire date" +msgstr "مدت ختم ھونے کی تاریخ" + +msgid "session" +msgstr "نشست" + +msgid "sessions" +msgstr "نشستیں" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/uz/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/uz/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9346a6c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/uz/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/uz/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/uz/LC_MESSAGES/django.po new file mode 100644 index 0000000..47fa681 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/uz/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Nuruddin Iminokhunov , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 01:18+0000\n" +"Last-Translator: Nuruddin Iminokhunov \n" +"Language-Team: Uzbek (http://www.transifex.com/django/django/language/uz/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: uz\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sessions" +msgstr "Sessiyalar" + +msgid "session key" +msgstr "sessiya kaliti" + +msgid "session data" +msgstr "sessiya ma'lumotlari " + +msgid "expire date" +msgstr "tugash vaqti" + +msgid "session" +msgstr "sessiya" + +msgid "sessions" +msgstr "sessiyalar" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/vi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/vi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..69b82fd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/vi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/vi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/vi/LC_MESSAGES/django.po new file mode 100644 index 0000000..731d24c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/vi/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Thanh Le Viet , 2013 +# Tran Van , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Tran Van \n" +"Language-Team: Vietnamese (http://www.transifex.com/django/django/language/" +"vi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: vi\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sessions" +msgstr "" + +msgid "session key" +msgstr "session key" + +msgid "session data" +msgstr "session data" + +msgid "expire date" +msgstr "Ngày hết hạn" + +msgid "session" +msgstr "Phiên" + +msgid "sessions" +msgstr "session" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/zh_Hans/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/zh_Hans/LC_MESSAGES/django.mo new file mode 100644 index 0000000..4d762f6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/zh_Hans/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/zh_Hans/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/zh_Hans/LC_MESSAGES/django.po new file mode 100644 index 0000000..ee25859 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/zh_Hans/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Ronald White , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Chinese (China) (http://www.transifex.com/django/django/" +"language/zh_CN/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_CN\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sessions" +msgstr "会话" + +msgid "session key" +msgstr "会话密钥" + +msgid "session data" +msgstr "会话数据" + +msgid "expire date" +msgstr "过期时间" + +msgid "session" +msgstr "会话" + +msgid "sessions" +msgstr "会话" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/zh_Hant/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/zh_Hant/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ad83522 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/zh_Hant/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/zh_Hant/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/zh_Hant/LC_MESSAGES/django.po new file mode 100644 index 0000000..ef202b9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/locale/zh_Hant/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Chen Chun-Chia , 2015 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Chen Chun-Chia \n" +"Language-Team: Chinese (Taiwan) (http://www.transifex.com/django/django/" +"language/zh_TW/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_TW\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sessions" +msgstr "Sessions" + +msgid "session key" +msgstr "session 鍵值" + +msgid "session data" +msgstr "session 資料" + +msgid "expire date" +msgstr "到期日期" + +msgid "session" +msgstr "session" + +msgid "sessions" +msgstr "sessions" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/management/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/management/commands/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/management/commands/clearsessions.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/management/commands/clearsessions.py new file mode 100644 index 0000000..899f537 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/management/commands/clearsessions.py @@ -0,0 +1,21 @@ +from importlib import import_module + +from django.conf import settings +from django.core.management.base import BaseCommand, CommandError + + +class Command(BaseCommand): + help = ( + "Can be run as a cronjob or directly to clean out expired sessions " + "when the backend supports it." + ) + + def handle(self, **options): + engine = import_module(settings.SESSION_ENGINE) + try: + engine.SessionStore.clear_expired() + except NotImplementedError: + raise CommandError( + "Session engine '%s' doesn't support clearing expired " + "sessions." % settings.SESSION_ENGINE + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/middleware.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/middleware.py new file mode 100644 index 0000000..9c934f9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/middleware.py @@ -0,0 +1,77 @@ +import time +from importlib import import_module + +from django.conf import settings +from django.contrib.sessions.backends.base import UpdateError +from django.contrib.sessions.exceptions import SessionInterrupted +from django.utils.cache import patch_vary_headers +from django.utils.deprecation import MiddlewareMixin +from django.utils.http import http_date + + +class SessionMiddleware(MiddlewareMixin): + def __init__(self, get_response): + super().__init__(get_response) + engine = import_module(settings.SESSION_ENGINE) + self.SessionStore = engine.SessionStore + + def process_request(self, request): + session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME) + request.session = self.SessionStore(session_key) + + def process_response(self, request, response): + """ + If request.session was modified, or if the configuration is to save the + session every time, save the changes and set a session cookie or delete + the session cookie if the session has been emptied. + """ + try: + accessed = request.session.accessed + modified = request.session.modified + empty = request.session.is_empty() + except AttributeError: + return response + # First check if we need to delete this cookie. + # The session should be deleted only if the session is entirely empty. + if settings.SESSION_COOKIE_NAME in request.COOKIES and empty: + response.delete_cookie( + settings.SESSION_COOKIE_NAME, + path=settings.SESSION_COOKIE_PATH, + domain=settings.SESSION_COOKIE_DOMAIN, + samesite=settings.SESSION_COOKIE_SAMESITE, + ) + patch_vary_headers(response, ("Cookie",)) + else: + if accessed: + patch_vary_headers(response, ("Cookie",)) + if (modified or settings.SESSION_SAVE_EVERY_REQUEST) and not empty: + if request.session.get_expire_at_browser_close(): + max_age = None + expires = None + else: + max_age = request.session.get_expiry_age() + expires_time = time.time() + max_age + expires = http_date(expires_time) + # Save the session data and refresh the client cookie. + # Skip session save for 5xx responses. + if response.status_code < 500: + try: + request.session.save() + except UpdateError: + raise SessionInterrupted( + "The request's session was deleted before the " + "request completed. The user may have logged " + "out in a concurrent request, for example." + ) + response.set_cookie( + settings.SESSION_COOKIE_NAME, + request.session.session_key, + max_age=max_age, + expires=expires, + domain=settings.SESSION_COOKIE_DOMAIN, + path=settings.SESSION_COOKIE_PATH, + secure=settings.SESSION_COOKIE_SECURE or None, + httponly=settings.SESSION_COOKIE_HTTPONLY or None, + samesite=settings.SESSION_COOKIE_SAMESITE, + ) + return response diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/migrations/0001_initial.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/migrations/0001_initial.py new file mode 100644 index 0000000..42e382a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/migrations/0001_initial.py @@ -0,0 +1,37 @@ +import django.contrib.sessions.models +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [] + + operations = [ + migrations.CreateModel( + name="Session", + fields=[ + ( + "session_key", + models.CharField( + max_length=40, + serialize=False, + verbose_name="session key", + primary_key=True, + ), + ), + ("session_data", models.TextField(verbose_name="session data")), + ( + "expire_date", + models.DateTimeField(verbose_name="expire date", db_index=True), + ), + ], + options={ + "abstract": False, + "db_table": "django_session", + "verbose_name": "session", + "verbose_name_plural": "sessions", + }, + managers=[ + ("objects", django.contrib.sessions.models.SessionManager()), + ], + ), + ] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/migrations/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/models.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/models.py new file mode 100644 index 0000000..e786ab4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/models.py @@ -0,0 +1,35 @@ +from django.contrib.sessions.base_session import AbstractBaseSession, BaseSessionManager + + +class SessionManager(BaseSessionManager): + use_in_migrations = True + + +class Session(AbstractBaseSession): + """ + Django provides full support for anonymous sessions. The session + framework lets you store and retrieve arbitrary data on a + per-site-visitor basis. It stores data on the server side and + abstracts the sending and receiving of cookies. Cookies contain a + session ID -- not the data itself. + + The Django sessions framework is entirely cookie-based. It does + not fall back to putting session IDs in URLs. This is an intentional + design decision. Not only does that behavior make URLs ugly, it makes + your site vulnerable to session-ID theft via the "Referer" header. + + For complete documentation on using Sessions in your code, consult + the sessions documentation that is shipped with Django (also available + on the Django web site). + """ + + objects = SessionManager() + + @classmethod + def get_session_store_class(cls): + from django.contrib.sessions.backends.db import SessionStore + + return SessionStore + + class Meta(AbstractBaseSession.Meta): + db_table = "django_session" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/serializers.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/serializers.py new file mode 100644 index 0000000..16a248c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sessions/serializers.py @@ -0,0 +1,3 @@ +from django.core.signing import JSONSerializer as BaseJSONSerializer + +JSONSerializer = BaseJSONSerializer diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sitemaps/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sitemaps/__init__.py new file mode 100644 index 0000000..dd21d88 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sitemaps/__init__.py @@ -0,0 +1,200 @@ +from django.apps import apps as django_apps +from django.conf import settings +from django.core import paginator +from django.core.exceptions import ImproperlyConfigured +from django.utils import translation + + +class Sitemap: + # This limit is defined by Google. See the index documentation at + # https://www.sitemaps.org/protocol.html#index. + limit = 50000 + + # If protocol is None, the URLs in the sitemap will use the protocol + # with which the sitemap was requested. + protocol = None + + # Enables generating URLs for all languages. + i18n = False + + # Override list of languages to use. + languages = None + + # Enables generating alternate/hreflang links. + alternates = False + + # Add an alternate/hreflang link with value 'x-default'. + x_default = False + + def _get(self, name, item, default=None): + try: + attr = getattr(self, name) + except AttributeError: + return default + if callable(attr): + if self.i18n: + # Split the (item, lang_code) tuples again for the location, + # priority, lastmod and changefreq method calls. + item, lang_code = item + return attr(item) + return attr + + def get_languages_for_item(self, item): + """Languages for which this item is displayed.""" + return self._languages() + + def _languages(self): + if self.languages is not None: + return self.languages + return [lang_code for lang_code, _ in settings.LANGUAGES] + + def _items(self): + if self.i18n: + # Create (item, lang_code) tuples for all items and languages. + # This is necessary to paginate with all languages already considered. + items = [ + (item, lang_code) + for item in self.items() + for lang_code in self.get_languages_for_item(item) + ] + return items + return self.items() + + def _location(self, item, force_lang_code=None): + if self.i18n: + obj, lang_code = item + # Activate language from item-tuple or forced one before calling location. + with translation.override(force_lang_code or lang_code): + return self._get("location", item) + return self._get("location", item) + + @property + def paginator(self): + return paginator.Paginator(self._items(), self.limit) + + def items(self): + return [] + + def location(self, item): + return item.get_absolute_url() + + def get_protocol(self, protocol=None): + # Determine protocol + return self.protocol or protocol or "https" + + def get_domain(self, site=None): + # Determine domain + if site is None: + if django_apps.is_installed("django.contrib.sites"): + Site = django_apps.get_model("sites.Site") + try: + site = Site.objects.get_current() + except Site.DoesNotExist: + pass + if site is None: + raise ImproperlyConfigured( + "To use sitemaps, either enable the sites framework or pass " + "a Site/RequestSite object in your view." + ) + return site.domain + + def get_urls(self, page=1, site=None, protocol=None): + protocol = self.get_protocol(protocol) + domain = self.get_domain(site) + return self._urls(page, protocol, domain) + + def get_latest_lastmod(self): + if not hasattr(self, "lastmod"): + return None + if callable(self.lastmod): + try: + return max([self.lastmod(item) for item in self.items()], default=None) + except TypeError: + return None + else: + return self.lastmod + + def _urls(self, page, protocol, domain): + urls = [] + latest_lastmod = None + all_items_lastmod = True # track if all items have a lastmod + + paginator_page = self.paginator.page(page) + for item in paginator_page.object_list: + loc = f"{protocol}://{domain}{self._location(item)}" + priority = self._get("priority", item) + lastmod = self._get("lastmod", item) + + if all_items_lastmod: + all_items_lastmod = lastmod is not None + if all_items_lastmod and ( + latest_lastmod is None or lastmod > latest_lastmod + ): + latest_lastmod = lastmod + + url_info = { + "item": item, + "location": loc, + "lastmod": lastmod, + "changefreq": self._get("changefreq", item), + "priority": str(priority if priority is not None else ""), + "alternates": [], + } + + if self.i18n and self.alternates: + item_languages = self.get_languages_for_item(item[0]) + for lang_code in item_languages: + loc = f"{protocol}://{domain}{self._location(item, lang_code)}" + url_info["alternates"].append( + { + "location": loc, + "lang_code": lang_code, + } + ) + if self.x_default and settings.LANGUAGE_CODE in item_languages: + lang_code = settings.LANGUAGE_CODE + loc = f"{protocol}://{domain}{self._location(item, lang_code)}" + loc = loc.replace(f"/{lang_code}/", "/", 1) + url_info["alternates"].append( + { + "location": loc, + "lang_code": "x-default", + } + ) + + urls.append(url_info) + + if all_items_lastmod and latest_lastmod: + self.latest_lastmod = latest_lastmod + + return urls + + +class GenericSitemap(Sitemap): + priority = None + changefreq = None + + def __init__(self, info_dict, priority=None, changefreq=None, protocol=None): + self.queryset = info_dict["queryset"] + self.date_field = info_dict.get("date_field") + self.priority = self.priority or priority + self.changefreq = self.changefreq or changefreq + self.protocol = self.protocol or protocol + + def items(self): + # Make sure to return a clone; we don't want premature evaluation. + return self.queryset.filter() + + def lastmod(self, item): + if self.date_field is not None: + return getattr(item, self.date_field) + return None + + def get_latest_lastmod(self): + if self.date_field is not None: + return ( + self.queryset.order_by("-" + self.date_field) + .values_list(self.date_field, flat=True) + .first() + ) + return None diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sitemaps/apps.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sitemaps/apps.py new file mode 100644 index 0000000..70c200c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sitemaps/apps.py @@ -0,0 +1,8 @@ +from django.apps import AppConfig +from django.utils.translation import gettext_lazy as _ + + +class SiteMapsConfig(AppConfig): + default_auto_field = "django.db.models.AutoField" + name = "django.contrib.sitemaps" + verbose_name = _("Site Maps") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sitemaps/templates/sitemap.xml b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sitemaps/templates/sitemap.xml new file mode 100644 index 0000000..67b166a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sitemaps/templates/sitemap.xml @@ -0,0 +1,16 @@ + + +{% spaceless %} +{% for url in urlset %} + + {{ url.location }} + {% if url.lastmod %}{{ url.lastmod|date:"Y-m-d" }}{% endif %} + {% if url.changefreq %}{{ url.changefreq }}{% endif %} + {% if url.priority %}{{ url.priority }}{% endif %} + {% for alternate in url.alternates %} + + {% endfor %} + +{% endfor %} +{% endspaceless %} + diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sitemaps/templates/sitemap_index.xml b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sitemaps/templates/sitemap_index.xml new file mode 100644 index 0000000..b7abd12 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sitemaps/templates/sitemap_index.xml @@ -0,0 +1,13 @@ + + +{% spaceless %} +{% for site in sitemaps %} + + {{ site.location }} + {% if site.last_mod %} + {{ site.last_mod|date:"c" }} + {% endif %} + +{% endfor %} +{% endspaceless %} + diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sitemaps/views.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sitemaps/views.py new file mode 100644 index 0000000..166563b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sitemaps/views.py @@ -0,0 +1,140 @@ +import datetime +from dataclasses import dataclass +from functools import wraps + +from django.contrib.sites.shortcuts import get_current_site +from django.core.paginator import EmptyPage, PageNotAnInteger +from django.http import Http404 +from django.template.response import TemplateResponse +from django.urls import reverse +from django.utils import timezone +from django.utils.http import http_date + + +@dataclass +class SitemapIndexItem: + location: str + last_mod: bool = None + + +def x_robots_tag(func): + @wraps(func) + def inner(request, *args, **kwargs): + response = func(request, *args, **kwargs) + response.headers["X-Robots-Tag"] = "noindex, noodp, noarchive" + return response + + return inner + + +def _get_latest_lastmod(current_lastmod, new_lastmod): + """ + Returns the latest `lastmod` where `lastmod` can be either a date or a + datetime. + """ + if not isinstance(new_lastmod, datetime.datetime): + new_lastmod = datetime.datetime.combine(new_lastmod, datetime.time.min) + if timezone.is_naive(new_lastmod): + new_lastmod = timezone.make_aware(new_lastmod, datetime.timezone.utc) + return new_lastmod if current_lastmod is None else max(current_lastmod, new_lastmod) + + +@x_robots_tag +def index( + request, + sitemaps, + template_name="sitemap_index.xml", + content_type="application/xml", + sitemap_url_name="django.contrib.sitemaps.views.sitemap", +): + req_protocol = request.scheme + req_site = get_current_site(request) + + sites = [] # all sections' sitemap URLs + all_indexes_lastmod = True + latest_lastmod = None + for section, site in sitemaps.items(): + # For each section label, add links of all pages of its sitemap + # (usually generated by the `sitemap` view). + if callable(site): + site = site() + protocol = req_protocol if site.protocol is None else site.protocol + sitemap_url = reverse(sitemap_url_name, kwargs={"section": section}) + absolute_url = "%s://%s%s" % (protocol, req_site.domain, sitemap_url) + site_lastmod = site.get_latest_lastmod() + if all_indexes_lastmod: + if site_lastmod is not None: + latest_lastmod = _get_latest_lastmod(latest_lastmod, site_lastmod) + else: + all_indexes_lastmod = False + sites.append(SitemapIndexItem(absolute_url, site_lastmod)) + # Add links to all pages of the sitemap. + for page in range(2, site.paginator.num_pages + 1): + sites.append( + SitemapIndexItem("%s?p=%s" % (absolute_url, page), site_lastmod) + ) + # If lastmod is defined for all sites, set header so as + # ConditionalGetMiddleware is able to send 304 NOT MODIFIED + if all_indexes_lastmod and latest_lastmod: + headers = {"Last-Modified": http_date(latest_lastmod.timestamp())} + else: + headers = None + return TemplateResponse( + request, + template_name, + {"sitemaps": sites}, + content_type=content_type, + headers=headers, + ) + + +@x_robots_tag +def sitemap( + request, + sitemaps, + section=None, + template_name="sitemap.xml", + content_type="application/xml", +): + req_protocol = request.scheme + req_site = get_current_site(request) + + if section is not None: + if section not in sitemaps: + raise Http404("No sitemap available for section: %r" % section) + maps = [sitemaps[section]] + else: + maps = sitemaps.values() + page = request.GET.get("p", 1) + + lastmod = None + all_sites_lastmod = True + urls = [] + for site in maps: + try: + if callable(site): + site = site() + urls.extend(site.get_urls(page=page, site=req_site, protocol=req_protocol)) + if all_sites_lastmod: + site_lastmod = getattr(site, "latest_lastmod", None) + if site_lastmod is not None: + lastmod = _get_latest_lastmod(lastmod, site_lastmod) + else: + all_sites_lastmod = False + except EmptyPage: + raise Http404("Page %s empty" % page) + except PageNotAnInteger: + raise Http404("No page '%s'" % page) + # If lastmod is defined for all sites, set header so as + # ConditionalGetMiddleware is able to send 304 NOT MODIFIED + if all_sites_lastmod: + headers = {"Last-Modified": http_date(lastmod.timestamp())} if lastmod else None + else: + headers = None + return TemplateResponse( + request, + template_name, + {"urlset": urls}, + content_type=content_type, + headers=headers, + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/admin.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/admin.py new file mode 100644 index 0000000..53ad53d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/admin.py @@ -0,0 +1,8 @@ +from django.contrib import admin +from django.contrib.sites.models import Site + + +@admin.register(Site) +class SiteAdmin(admin.ModelAdmin): + list_display = ("domain", "name") + search_fields = ("domain", "name") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/apps.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/apps.py new file mode 100644 index 0000000..ac51a84 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/apps.py @@ -0,0 +1,17 @@ +from django.apps import AppConfig +from django.contrib.sites.checks import check_site_id +from django.core import checks +from django.db.models.signals import post_migrate +from django.utils.translation import gettext_lazy as _ + +from .management import create_default_site + + +class SitesConfig(AppConfig): + default_auto_field = "django.db.models.AutoField" + name = "django.contrib.sites" + verbose_name = _("Sites") + + def ready(self): + post_migrate.connect(create_default_site, sender=self) + checks.register(check_site_id, checks.Tags.sites) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/checks.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/checks.py new file mode 100644 index 0000000..66e8551 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/checks.py @@ -0,0 +1,14 @@ +from types import NoneType + +from django.conf import settings +from django.core.checks import Error + + +def check_site_id(app_configs, **kwargs): + if hasattr(settings, "SITE_ID") and not isinstance( + settings.SITE_ID, (NoneType, int) + ): + return [ + Error("The SITE_ID setting must be an integer", id="sites.E101"), + ] + return [] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/af/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/af/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d613267 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/af/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/af/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/af/LC_MESSAGES/django.po new file mode 100644 index 0000000..e4742e2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/af/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# F Wolff , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2019-01-04 18:46+0000\n" +"Last-Translator: F Wolff \n" +"Language-Team: Afrikaans (http://www.transifex.com/django/django/language/" +"af/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: af\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Werwe" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Die domeinnaam mag nie spasies of tab-karakters bevat nie." + +msgid "domain name" +msgstr "domeinnaam" + +msgid "display name" +msgstr "vertoonnaam" + +msgid "site" +msgstr "werf" + +msgid "sites" +msgstr "werwe" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ar/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ar/LC_MESSAGES/django.mo new file mode 100644 index 0000000..bc0ef77 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ar/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ar/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ar/LC_MESSAGES/django.po new file mode 100644 index 0000000..f04d717 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ar/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bashar Al-Abdulhadi, 2014 +# Eyad Toma , 2013 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Arabic (http://www.transifex.com/django/django/language/ar/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +msgid "Sites" +msgstr "المواقع" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "اسم النطاق يجب أن لا يحتوي على فراغات أو فراغات طويلة tabs." + +msgid "domain name" +msgstr "اسم النطاق" + +msgid "display name" +msgstr "اسم العرض" + +msgid "site" +msgstr "موقع" + +msgid "sites" +msgstr "المواقع" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ar_DZ/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ar_DZ/LC_MESSAGES/django.mo new file mode 100644 index 0000000..35e42fa Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ar_DZ/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ar_DZ/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ar_DZ/LC_MESSAGES/django.po new file mode 100644 index 0000000..815f973 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ar_DZ/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Riterix , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2019-12-14 22:52+0000\n" +"Last-Translator: Riterix \n" +"Language-Team: Arabic (Algeria) (http://www.transifex.com/django/django/" +"language/ar_DZ/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar_DZ\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +msgid "Sites" +msgstr "المواقع" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "اسم النطاق يجب أن لا يحتوي على فراغات أو فراغات طويلة tabs." + +msgid "domain name" +msgstr "اسم النطاق" + +msgid "display name" +msgstr "اسم العرض" + +msgid "site" +msgstr "موقع" + +msgid "sites" +msgstr "المواقع" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ast/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ast/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0f14b98 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ast/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ast/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ast/LC_MESSAGES/django.po new file mode 100644 index 0000000..4fff0b4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ast/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ḷḷumex03 , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 19:51+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Asturian (http://www.transifex.com/django/django/language/" +"ast/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ast\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "El nome de dominiu nun pue contener dengún espaciu o tabulación." + +msgid "domain name" +msgstr "nome de dominiu" + +msgid "display name" +msgstr "amosar nome" + +msgid "site" +msgstr "sitiu" + +msgid "sites" +msgstr "sitios" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/az/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/az/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0ec03f9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/az/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/az/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/az/LC_MESSAGES/django.po new file mode 100644 index 0000000..cd3d29b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/az/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ali Ismayilov , 2011 +# Emin Mastizada , 2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2018-04-27 17:01+0000\n" +"Last-Translator: Emin Mastizada \n" +"Language-Team: Azerbaijani (http://www.transifex.com/django/django/language/" +"az/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: az\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Saytlar" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Domen adında boşluq və tab boşluğu olmamalıdır." + +msgid "domain name" +msgstr "domen" + +msgid "display name" +msgstr "adı" + +msgid "site" +msgstr "sayt" + +msgid "sites" +msgstr "saytlar" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/be/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/be/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ec75cef Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/be/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/be/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/be/LC_MESSAGES/django.po new file mode 100644 index 0000000..8b44db3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/be/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Viktar Palstsiuk , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Viktar Palstsiuk \n" +"Language-Team: Belarusian (http://www.transifex.com/django/django/language/" +"be/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: be\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n" +"%100>=11 && n%100<=14)? 2 : 3);\n" + +msgid "Sites" +msgstr "Сайты" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Даменнае імя ня можа ўтрымліваць прабелы або сымбалі табуляцыі." + +msgid "domain name" +msgstr "назва дамэна" + +msgid "display name" +msgstr "бачная назва" + +msgid "site" +msgstr "сайт" + +msgid "sites" +msgstr "сайты" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/bg/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/bg/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b337e3d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/bg/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/bg/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/bg/LC_MESSAGES/django.po new file mode 100644 index 0000000..4ebb4ba --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/bg/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Lyuboslav Petrov , 2014 +# vestimir , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Bulgarian (http://www.transifex.com/django/django/language/" +"bg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Сайтове" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Името на домейна не може да съдържа никакви интервали или табулации." + +msgid "domain name" +msgstr "име на домейна" + +msgid "display name" +msgstr "наименование" + +msgid "site" +msgstr "сайт" + +msgid "sites" +msgstr "сайтове" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/bn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/bn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..11265f6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/bn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/bn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/bn/LC_MESSAGES/django.po new file mode 100644 index 0000000..2325fe3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/bn/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Tahmid Rafi , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Tahmid Rafi \n" +"Language-Team: Bengali (http://www.transifex.com/django/django/language/" +"bn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "সাইট" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "ডোমেইন নাম এ কোন স্পেস বা ট্যাব থাকতে পারবে না।" + +msgid "domain name" +msgstr "ডোমেইন নাম" + +msgid "display name" +msgstr "ডিসপ্লে নাম" + +msgid "site" +msgstr "সাইট" + +msgid "sites" +msgstr "সাইটসমূহ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/br/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/br/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e8547ba Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/br/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/br/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/br/LC_MESSAGES/django.po new file mode 100644 index 0000000..4294e2b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/br/LC_MESSAGES/django.po @@ -0,0 +1,40 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Fulup , 2012 +# Irriep Nala Novram , 2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2018-10-19 23:07+0000\n" +"Last-Translator: Irriep Nala Novram \n" +"Language-Team: Breton (http://www.transifex.com/django/django/language/br/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: br\n" +"Plural-Forms: nplurals=5; plural=((n%10 == 1) && (n%100 != 11) && (n%100 !" +"=71) && (n%100 !=91) ? 0 :(n%10 == 2) && (n%100 != 12) && (n%100 !=72) && (n" +"%100 !=92) ? 1 :(n%10 ==3 || n%10==4 || n%10==9) && (n%100 < 10 || n% 100 > " +"19) && (n%100 < 70 || n%100 > 79) && (n%100 < 90 || n%100 > 99) ? 2 :(n != 0 " +"&& n % 1000000 == 0) ? 3 : 4);\n" + +msgid "Sites" +msgstr "Lec'hiennoù" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "An anv domani n'hall na enderc'hel spasoù pe taolennadurioù." + +msgid "domain name" +msgstr "anv domani" + +msgid "display name" +msgstr "anv da ziskouez" + +msgid "site" +msgstr "lec'hienn" + +msgid "sites" +msgstr "lec'hiennoù" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/bs/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/bs/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1b76e2f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/bs/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/bs/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/bs/LC_MESSAGES/django.po new file mode 100644 index 0000000..7a10cea --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/bs/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Bosnian (http://www.transifex.com/django/django/language/" +"bs/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bs\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Sites" +msgstr "" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "" + +msgid "domain name" +msgstr "ime domena" + +msgid "display name" +msgstr "prikazano ime" + +msgid "site" +msgstr "sajt" + +msgid "sites" +msgstr "sajtovi" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ca/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ca/LC_MESSAGES/django.mo new file mode 100644 index 0000000..36107e0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ca/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ca/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ca/LC_MESSAGES/django.po new file mode 100644 index 0000000..22f2c13 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ca/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Antoni Aloy , 2013 +# Carles Barrobés , 2014 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Catalan (http://www.transifex.com/django/django/language/" +"ca/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ca\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Llocs" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "El nom de domini no pot contenir cap espai ni tabuladors." + +msgid "domain name" +msgstr "nom del domini" + +msgid "display name" +msgstr "nom per mostrar" + +msgid "site" +msgstr "lloc" + +msgid "sites" +msgstr "llocs" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ckb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ckb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9ae5e76 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ckb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ckb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ckb/LC_MESSAGES/django.po new file mode 100644 index 0000000..aeaca57 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ckb/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# kosar tofiq , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2023-04-24 18:05+0000\n" +"Last-Translator: kosar tofiq , 2020\n" +"Language-Team: Central Kurdish (http://www.transifex.com/django/django/" +"language/ckb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ckb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "ماڵپەڕەکان" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "ناوی دۆمەین نابێت بۆشایی یان تابی تێدابێت." + +msgid "domain name" +msgstr "ناوی دۆمەین" + +msgid "display name" +msgstr "ناوی پیشاندان" + +msgid "site" +msgstr "ماڵپەڕ" + +msgid "sites" +msgstr "ماڵپەڕەکان" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/cs/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/cs/LC_MESSAGES/django.mo new file mode 100644 index 0000000..26ea691 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/cs/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/cs/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/cs/LC_MESSAGES/django.po new file mode 100644 index 0000000..3fb2c3a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/cs/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Vláďa Macek , 2013-2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Czech (http://www.transifex.com/django/django/language/cs/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cs\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n " +"<= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n" + +msgid "Sites" +msgstr "Weby" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Název domény nemůže obsahovat mezery ani tabulátory." + +msgid "domain name" +msgstr "název domény" + +msgid "display name" +msgstr "zobrazený název" + +msgid "site" +msgstr "web" + +msgid "sites" +msgstr "weby" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/cy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/cy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d4b4ecd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/cy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/cy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/cy/LC_MESSAGES/django.po new file mode 100644 index 0000000..5e37db2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/cy/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Maredudd ap Gwyndaf , 2013-2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Maredudd ap Gwyndaf \n" +"Language-Team: Welsh (http://www.transifex.com/django/django/language/cy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cy\n" +"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != " +"11) ? 2 : 3;\n" + +msgid "Sites" +msgstr "Safleoedd" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Ni all yr enw parth gynnwys bylchau neu dabiau." + +msgid "domain name" +msgstr "enw parth" + +msgid "display name" +msgstr "enw arddangos" + +msgid "site" +msgstr "safle" + +msgid "sites" +msgstr "safleoedd" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/da/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/da/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2380ff3 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/da/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/da/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/da/LC_MESSAGES/django.po new file mode 100644 index 0000000..7626119 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/da/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Erik Wognsen , 2013-2014 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Danish (http://www.transifex.com/django/django/language/da/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: da\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Websider" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Domænenavnet må ikke indeholde mellemrum eller tabulatorer." + +msgid "domain name" +msgstr "domænenavn" + +msgid "display name" +msgstr "vist navn" + +msgid "site" +msgstr "webside" + +msgid "sites" +msgstr "websider" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/de/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/de/LC_MESSAGES/django.mo new file mode 100644 index 0000000..74e1685 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/de/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/de/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/de/LC_MESSAGES/django.po new file mode 100644 index 0000000..6029124 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/de/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011,2013-2014,2016 +# Markus Holtermann , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: German (http://www.transifex.com/django/django/language/de/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Websites" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Der Domainname darf keine Leerzeichen oder Tabs enthalten." + +msgid "domain name" +msgstr "Domainname" + +msgid "display name" +msgstr "Anzeigename" + +msgid "site" +msgstr "Website" + +msgid "sites" +msgstr "Websites" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/dsb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/dsb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8179a5c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/dsb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/dsb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/dsb/LC_MESSAGES/django.po new file mode 100644 index 0000000..b8706de --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/dsb/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Michael Wolf , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 00:02+0000\n" +"Last-Translator: Michael Wolf \n" +"Language-Team: Lower Sorbian (http://www.transifex.com/django/django/" +"language/dsb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: dsb\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" + +msgid "Sites" +msgstr "Sedła" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Domenowe mě njamóžo prozne znamjenja abo tabulatory wopśimowaś." + +msgid "domain name" +msgstr "domenowe mě" + +msgid "display name" +msgstr "zwobraznjeńske mě" + +msgid "site" +msgstr "sedło" + +msgid "sites" +msgstr "sedła" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/el/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/el/LC_MESSAGES/django.mo new file mode 100644 index 0000000..10479c1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/el/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/el/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/el/LC_MESSAGES/django.po new file mode 100644 index 0000000..94d8e19 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/el/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Nikolas Demiridis , 2014 +# Pãnoș , 2014 +# Pãnoș , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Pãnoș \n" +"Language-Team: Greek (http://www.transifex.com/django/django/language/el/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: el\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Ιστότοποι" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Το όνομα τομέα δεν μπορεί να περιέχει κενά." + +msgid "domain name" +msgstr "όνομα τομέα" + +msgid "display name" +msgstr "εμφανιζόμενο όνομα" + +msgid "site" +msgstr "ιστότοπος" + +msgid "sites" +msgstr "ιστότοποι" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/en/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/en/LC_MESSAGES/django.mo new file mode 100644 index 0000000..08a7b68 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/en/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/en/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/en/LC_MESSAGES/django.po new file mode 100644 index 0000000..3b1884c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/en/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +msgid "" +msgstr "" +"Project-Id-Version: Django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2010-05-13 15:35+0200\n" +"Last-Translator: Django team\n" +"Language-Team: English \n" +"Language: en\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: contrib/sites/apps.py:11 +msgid "Sites" +msgstr "" + +#: contrib/sites/models.py:30 +msgid "The domain name cannot contain any spaces or tabs." +msgstr "" + +#: contrib/sites/models.py:81 +msgid "domain name" +msgstr "" + +#: contrib/sites/models.py:83 +msgid "display name" +msgstr "" + +#: contrib/sites/models.py:88 +msgid "site" +msgstr "" + +#: contrib/sites/models.py:89 +msgid "sites" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/en_AU/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/en_AU/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e6e4917 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/en_AU/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/en_AU/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/en_AU/LC_MESSAGES/django.po new file mode 100644 index 0000000..0659ec5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/en_AU/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Tom Fifield , 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2021-04-11 13:15+0000\n" +"Last-Translator: Tom Fifield \n" +"Language-Team: English (Australia) (http://www.transifex.com/django/django/" +"language/en_AU/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_AU\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Sites" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "The domain name cannot contain any spaces or tabs." + +msgid "domain name" +msgstr "domain name" + +msgid "display name" +msgstr "display name" + +msgid "site" +msgstr "site" + +msgid "sites" +msgstr "sites" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/en_GB/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/en_GB/LC_MESSAGES/django.mo new file mode 100644 index 0000000..772da82 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/en_GB/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/en_GB/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/en_GB/LC_MESSAGES/django.po new file mode 100644 index 0000000..b212e34 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/en_GB/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ross Poulton , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: English (United Kingdom) (http://www.transifex.com/django/" +"django/language/en_GB/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_GB\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "" + +msgid "domain name" +msgstr "domain name" + +msgid "display name" +msgstr "display name" + +msgid "site" +msgstr "site" + +msgid "sites" +msgstr "sites" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/eo/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/eo/LC_MESSAGES/django.mo new file mode 100644 index 0000000..23a4700 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/eo/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/eo/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/eo/LC_MESSAGES/django.po new file mode 100644 index 0000000..a65e597 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/eo/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Baptiste Darthenay , 2013 +# Baptiste Darthenay , 2014 +# kristjan , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Esperanto (http://www.transifex.com/django/django/language/" +"eo/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eo\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Retejoj" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Tiu domajna nomo ne povas enteni nek spacojn nek tabojn." + +msgid "domain name" +msgstr "domajna nomo" + +msgid "display name" +msgstr "vidiga nomo" + +msgid "site" +msgstr "retejo" + +msgid "sites" +msgstr "retejoj" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8e3f12b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es/LC_MESSAGES/django.po new file mode 100644 index 0000000..89fbdbc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es/LC_MESSAGES/django.po @@ -0,0 +1,39 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# abraham.martin , 2014 +# Antoni Aloy , 2013 +# Ernesto Avilés Vázquez , 2014 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Spanish (http://www.transifex.com/django/django/language/" +"es/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Sitios" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "El nombre de dominio no puede contener espacios ni tabulaciones" + +msgid "domain name" +msgstr "nombre de dominio" + +msgid "display name" +msgstr "nombre a mostrar" + +msgid "site" +msgstr "sitio" + +msgid "sites" +msgstr "sitios" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es_AR/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es_AR/LC_MESSAGES/django.mo new file mode 100644 index 0000000..cc88304 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es_AR/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es_AR/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es_AR/LC_MESSAGES/django.po new file mode 100644 index 0000000..2ea4307 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es_AR/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Ramiro Morales, 2013-2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Ramiro Morales\n" +"Language-Team: Spanish (Argentina) (http://www.transifex.com/django/django/" +"language/es_AR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_AR\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Sitios" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "" +"El nombre de dominio no puede incluir espacios ni marcas de tabulación." + +msgid "domain name" +msgstr "nombre de dominio" + +msgid "display name" +msgstr "nombre para visualizar" + +msgid "site" +msgstr "sitio" + +msgid "sites" +msgstr "sitios" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es_CO/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es_CO/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1fff5d9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es_CO/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es_CO/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es_CO/LC_MESSAGES/django.po new file mode 100644 index 0000000..9344265 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es_CO/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Carlos Muñoz , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 21:51+0000\n" +"Last-Translator: Carlos Muñoz \n" +"Language-Team: Spanish (Colombia) (http://www.transifex.com/django/django/" +"language/es_CO/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_CO\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Sitios" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "El nombre de dominio no puede contener espacios y/o tabulaciones" + +msgid "domain name" +msgstr "nombre de dominio" + +msgid "display name" +msgstr "nombre a mostrar" + +msgid "site" +msgstr "sitio" + +msgid "sites" +msgstr "sitios" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es_MX/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es_MX/LC_MESSAGES/django.mo new file mode 100644 index 0000000..02a2e53 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es_MX/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es_MX/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es_MX/LC_MESSAGES/django.po new file mode 100644 index 0000000..29d4401 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es_MX/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Abraham Estrada, 2011 +# Carlos Castro , 2011 +# zodman , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: zodman \n" +"Language-Team: Spanish (Mexico) (http://www.transifex.com/django/django/" +"language/es_MX/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_MX\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Sitios" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "El nombre de dominio no puede contener espacios o tabulaciones." + +msgid "domain name" +msgstr "nombre del dominio" + +msgid "display name" +msgstr "nombre visible" + +msgid "site" +msgstr "sitio" + +msgid "sites" +msgstr "sitios" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es_VE/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es_VE/LC_MESSAGES/django.mo new file mode 100644 index 0000000..32f6e8f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es_VE/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es_VE/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es_VE/LC_MESSAGES/django.po new file mode 100644 index 0000000..a6b74fa --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/es_VE/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:12+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Spanish (Venezuela) (http://www.transifex.com/projects/p/" +"django/language/es_VE/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_VE\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "" + +msgid "domain name" +msgstr "" + +msgid "display name" +msgstr "" + +msgid "site" +msgstr "" + +msgid "sites" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/et/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/et/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3e3e38a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/et/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/et/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/et/LC_MESSAGES/django.po new file mode 100644 index 0000000..91ef8f3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/et/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Janno Liivak , 2013 +# Marti Raudsepp , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Estonian (http://www.transifex.com/django/django/language/" +"et/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: et\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Saidid" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Domeeni nimes ei tohi olla ei tühikuid ega tabeldusmärke." + +msgid "domain name" +msgstr "domeeninimi" + +msgid "display name" +msgstr "hüüdnimi" + +msgid "site" +msgstr "sait" + +msgid "sites" +msgstr "saidid" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/eu/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/eu/LC_MESSAGES/django.mo new file mode 100644 index 0000000..ca7a350 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/eu/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/eu/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/eu/LC_MESSAGES/django.po new file mode 100644 index 0000000..d7d4138 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/eu/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ander Martínez , 2013 +# Eneko Illarramendi , 2017 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Eneko Illarramendi \n" +"Language-Team: Basque (http://www.transifex.com/django/django/language/eu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Webguneak" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Domeinu izenak ezin du zuriunerik edo tabuladorerik eduki." + +msgid "domain name" +msgstr "domeinu-izena" + +msgid "display name" +msgstr "erakusteko izena" + +msgid "site" +msgstr "webgunea" + +msgid "sites" +msgstr "webguneak" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/fa/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/fa/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7bc004f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/fa/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/fa/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/fa/LC_MESSAGES/django.po new file mode 100644 index 0000000..ba91492 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/fa/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Mohammad Hossein Mojtahedi , 2013 +# Reza Mohammadi , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Persian (http://www.transifex.com/django/django/language/" +"fa/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fa\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Sites" +msgstr "وب‌گاه‌ها" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "نام دامنه نمی‌تواند حاوی فاصله یا پرش -tab- باشد." + +msgid "domain name" +msgstr "نام دامنه" + +msgid "display name" +msgstr "نام نمایش داده شده" + +msgid "site" +msgstr "وب‌گاه" + +msgid "sites" +msgstr "وب‌گاه‌ها" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/fi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/fi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..65ba6a0 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/fi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/fi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/fi/LC_MESSAGES/django.po new file mode 100644 index 0000000..13c88ce --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/fi/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Aarni Koskela, 2015 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Aarni Koskela\n" +"Language-Team: Finnish (http://www.transifex.com/django/django/language/" +"fi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Sivustot" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Verkkotunnus ei voi sisältää välilyöntejä tai sarkainmerkkejä." + +msgid "domain name" +msgstr "verkkotunnus" + +msgid "display name" +msgstr "näyttönimi" + +msgid "site" +msgstr "sivusto" + +msgid "sites" +msgstr "sivustot" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/fr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/fr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..54df18d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/fr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/fr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 0000000..26f86dc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Claude Paroz , 2014 +# Claude Paroz , 2013 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: French (http://www.transifex.com/django/django/language/fr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Sites" +msgstr "Sites" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Le nom de domaine ne peut pas contenir d'espace ni de tabulation." + +msgid "domain name" +msgstr "nom de domaine" + +msgid "display name" +msgstr "nom à afficher" + +msgid "site" +msgstr "site" + +msgid "sites" +msgstr "sites" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/fy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/fy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..489bbab Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/fy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/fy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/fy/LC_MESSAGES/django.po new file mode 100644 index 0000000..599ab98 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/fy/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:13+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Western Frisian (http://www.transifex.com/projects/p/django/" +"language/fy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fy\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "" + +msgid "domain name" +msgstr "" + +msgid "display name" +msgstr "" + +msgid "site" +msgstr "" + +msgid "sites" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ga/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ga/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c15ebef Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ga/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ga/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ga/LC_MESSAGES/django.po new file mode 100644 index 0000000..095d08d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ga/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Luke Blaney , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2019-06-22 21:46+0000\n" +"Last-Translator: Luke Blaney \n" +"Language-Team: Irish (http://www.transifex.com/django/django/language/ga/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ga\n" +"Plural-Forms: nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : " +"4);\n" + +msgid "Sites" +msgstr "Suíomhanna" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "" + +msgid "domain name" +msgstr "ainm fearainn" + +msgid "display name" +msgstr "ainm taispeáinta" + +msgid "site" +msgstr "suíomh" + +msgid "sites" +msgstr "suíomhanna" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/gd/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/gd/LC_MESSAGES/django.mo new file mode 100644 index 0000000..726462c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/gd/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/gd/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/gd/LC_MESSAGES/django.po new file mode 100644 index 0000000..6426918 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/gd/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# GunChleoc, 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-22 17:29+0000\n" +"Last-Translator: GunChleoc\n" +"Language-Team: Gaelic, Scottish (http://www.transifex.com/django/django/" +"language/gd/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: gd\n" +"Plural-Forms: nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : " +"(n > 2 && n < 20) ? 2 : 3;\n" + +msgid "Sites" +msgstr "Làraichean" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Chan fhaod beàrnan no tabaichean a bhith ann an ainm àrainne." + +msgid "domain name" +msgstr "ainm àrainne" + +msgid "display name" +msgstr "ainm taisbeanaidh" + +msgid "site" +msgstr "làrach" + +msgid "sites" +msgstr "làraichean" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/gl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/gl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a820edd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/gl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/gl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/gl/LC_MESSAGES/django.po new file mode 100644 index 0000000..ddf5436 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/gl/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Leandro Regueiro , 2013 +# X Bello , 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2023-04-24 18:05+0000\n" +"Last-Translator: X Bello , 2023\n" +"Language-Team: Galician (http://www.transifex.com/django/django/language/" +"gl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: gl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Sitios" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "O dominio non pode conter espazos nin tabulacións." + +msgid "domain name" +msgstr "dominio" + +msgid "display name" +msgstr "nome" + +msgid "site" +msgstr "sitio" + +msgid "sites" +msgstr "sitios" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/he/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/he/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3cdf5dc Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/he/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/he/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/he/LC_MESSAGES/django.po new file mode 100644 index 0000000..62de695 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/he/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Meir Kriheli , 2013-2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Hebrew (http://www.transifex.com/django/django/language/he/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: he\n" +"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % " +"1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;\n" + +msgid "Sites" +msgstr "אתרים" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "שם המתחם אינו יכול להכיל רווחים או טאבים." + +msgid "domain name" +msgstr "שם מתחם" + +msgid "display name" +msgstr "שם לתצוגה" + +msgid "site" +msgstr "אתר" + +msgid "sites" +msgstr "אתרים" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..699024a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hi/LC_MESSAGES/django.po new file mode 100644 index 0000000..437c402 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hi/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Hindi (http://www.transifex.com/django/django/language/hi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "" + +msgid "domain name" +msgstr "डोमेन नाम" + +msgid "display name" +msgstr "प्रदर्शन नाम" + +msgid "site" +msgstr "साइट" + +msgid "sites" +msgstr "साइट" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..90773e6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hr/LC_MESSAGES/django.po new file mode 100644 index 0000000..cd6a0dd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hr/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Mislav Cimperšak , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Mislav Cimperšak \n" +"Language-Team: Croatian (http://www.transifex.com/django/django/language/" +"hr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hr\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +msgid "Sites" +msgstr "Stranice" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Naziv domene ne može sadržavati razmake ili tabove." + +msgid "domain name" +msgstr "ime domene" + +msgid "display name" +msgstr "ime za prikaz" + +msgid "site" +msgstr "stranica" + +msgid "sites" +msgstr "stranice" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hsb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hsb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a6fc772 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hsb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hsb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hsb/LC_MESSAGES/django.po new file mode 100644 index 0000000..5ef2659 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hsb/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Michael Wolf , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 00:02+0000\n" +"Last-Translator: Michael Wolf \n" +"Language-Team: Upper Sorbian (http://www.transifex.com/django/django/" +"language/hsb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hsb\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" + +msgid "Sites" +msgstr "Sydła" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Domenowe mjeno njemóže mjezoty abo tabulatory wobsahować." + +msgid "domain name" +msgstr "domenowe mjeno" + +msgid "display name" +msgstr "zwobraznjenske mjeno" + +msgid "site" +msgstr "sydło" + +msgid "sites" +msgstr "sydła" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hu/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hu/LC_MESSAGES/django.mo new file mode 100644 index 0000000..bb2a102 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hu/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hu/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hu/LC_MESSAGES/django.po new file mode 100644 index 0000000..6a511f9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hu/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# András Veres-Szentkirályi, 2016 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: János R (Hangya)\n" +"Language-Team: Hungarian (http://www.transifex.com/django/django/language/" +"hu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Honlapok" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "A domainnév nem tartalmazhat szóközöket és tabulátorokat." + +msgid "domain name" +msgstr "tartománynév" + +msgid "display name" +msgstr "megjelenítendő név" + +msgid "site" +msgstr "honlap" + +msgid "sites" +msgstr "honlapok" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hy/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hy/LC_MESSAGES/django.mo new file mode 100644 index 0000000..17c2ef3 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hy/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hy/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hy/LC_MESSAGES/django.po new file mode 100644 index 0000000..adede4d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/hy/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Սմբատ Պետրոսյան , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 21:51+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Armenian (http://www.transifex.com/django/django/language/" +"hy/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hy\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Կայքեր" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Տիրույթի անվանում դաշտը չի կարող պարունակել բացատներ կամ թաբեր" + +msgid "domain name" +msgstr "Տիրույթի անվանում" + +msgid "display name" +msgstr "Ցուցադրվող անունը" + +msgid "site" +msgstr "կայք" + +msgid "sites" +msgstr "կայքեր" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ia/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ia/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d1251a1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ia/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ia/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ia/LC_MESSAGES/django.po new file mode 100644 index 0000000..b777ce6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ia/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Martijn Dekker , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 21:51+0000\n" +"Last-Translator: Martijn Dekker \n" +"Language-Team: Interlingua (http://www.transifex.com/django/django/language/" +"ia/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ia\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Sitos" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Le nomine de dominio non pote continer spatios o tabulationes." + +msgid "domain name" +msgstr "nomine de dominio" + +msgid "display name" +msgstr "nomine a monstrar" + +msgid "site" +msgstr "sito" + +msgid "sites" +msgstr "sitos" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/id/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/id/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5b6b923 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/id/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/id/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/id/LC_MESSAGES/django.po new file mode 100644 index 0000000..40228ed --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/id/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# M Asep Indrayana , 2015 +# rodin , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: rodin \n" +"Language-Team: Indonesian (http://www.transifex.com/django/django/language/" +"id/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: id\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sites" +msgstr "Situs" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Nama domain tidak dapat mengandung karakter spasi atau tab." + +msgid "domain name" +msgstr "nama domain" + +msgid "display name" +msgstr "nama yang ditampilkan" + +msgid "site" +msgstr "situs" + +msgid "sites" +msgstr "situs" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/io/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/io/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e22612f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/io/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/io/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/io/LC_MESSAGES/django.po new file mode 100644 index 0000000..3669499 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/io/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Viko Bartero , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-20 01:58+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Ido (http://www.transifex.com/django/django/language/io/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: io\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "La domeno nomo ne povas kontenar spaci, nek tab-signi." + +msgid "domain name" +msgstr "domeno nomo" + +msgid "display name" +msgstr "montrita nomo" + +msgid "site" +msgstr "ret-situo" + +msgid "sites" +msgstr "ret-situi" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/is/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/is/LC_MESSAGES/django.mo new file mode 100644 index 0000000..cbfa0fc Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/is/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/is/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/is/LC_MESSAGES/django.po new file mode 100644 index 0000000..201b4c0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/is/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Thordur Sigurdsson , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Thordur Sigurdsson \n" +"Language-Team: Icelandic (http://www.transifex.com/django/django/language/" +"is/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: is\n" +"Plural-Forms: nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);\n" + +msgid "Sites" +msgstr "Vefir" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Lénið má ekki innihalda bil eða dálkastafi (tab characters)." + +msgid "domain name" +msgstr "lén" + +msgid "display name" +msgstr "birtingarnafn" + +msgid "site" +msgstr "vefur" + +msgid "sites" +msgstr "vefir" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/it/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/it/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a370612 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/it/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/it/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/it/LC_MESSAGES/django.po new file mode 100644 index 0000000..49adfaf --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/it/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Marco Bonetti, 2014 +# Nicola Larosa , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Stefano Brentegani \n" +"Language-Team: Italian (http://www.transifex.com/django/django/language/" +"it/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: it\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Siti" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Il nome di dominio non può contenere spazi né tab." + +msgid "domain name" +msgstr "nome di dominio" + +msgid "display name" +msgstr "nome visualizzato" + +msgid "site" +msgstr "sito" + +msgid "sites" +msgstr "siti" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ja/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ja/LC_MESSAGES/django.mo new file mode 100644 index 0000000..6670c45 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ja/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ja/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ja/LC_MESSAGES/django.po new file mode 100644 index 0000000..335a1d7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ja/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Shinya Okano , 2013-2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Japanese (http://www.transifex.com/django/django/language/" +"ja/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ja\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sites" +msgstr "サイト" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "ドメイン名にスペース、タブを含めることはできません。" + +msgid "domain name" +msgstr "ドメイン名" + +msgid "display name" +msgstr "表示名" + +msgid "site" +msgstr "サイト" + +msgid "sites" +msgstr "サイト" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ka/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ka/LC_MESSAGES/django.mo new file mode 100644 index 0000000..c7eb889 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ka/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ka/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ka/LC_MESSAGES/django.po new file mode 100644 index 0000000..5d05019 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ka/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# André Bouatchidzé , 2015 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: André Bouatchidzé \n" +"Language-Team: Georgian (http://www.transifex.com/django/django/language/" +"ka/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ka\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +msgid "Sites" +msgstr "საიტები" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "დომენის სახელი არ შეიძლება შეიცავდეს ჰარებს ან ტაბულაციებს." + +msgid "domain name" +msgstr "დომენის სახელი" + +msgid "display name" +msgstr "საჩვენებელი სახელი" + +msgid "site" +msgstr "საიტი" + +msgid "sites" +msgstr "საიტები" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/kab/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/kab/LC_MESSAGES/django.mo new file mode 100644 index 0000000..3571d0d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/kab/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/kab/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/kab/LC_MESSAGES/django.po new file mode 100644 index 0000000..db4aa28 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/kab/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-10-06 11:44+0000\n" +"Last-Translator: Muḥend Belqasem \n" +"Language-Team: Kabyle (http://www.transifex.com/django/django/language/" +"kab/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kab\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Ismal" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Isem n taɣult ur izmir ara ad yegber isekkilen ilmawen n tirigliwin." + +msgid "domain name" +msgstr "isem n taɣult" + +msgid "display name" +msgstr "mefffer isem" + +msgid "site" +msgstr "asmel" + +msgid "sites" +msgstr "ismal" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/kk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/kk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..edfaf6d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/kk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/kk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/kk/LC_MESSAGES/django.po new file mode 100644 index 0000000..23c0f00 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/kk/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Leo Trubach , 2017 +# yun_man_ger , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Leo Trubach \n" +"Language-Team: Kazakh (http://www.transifex.com/django/django/language/kk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kk\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +msgid "Sites" +msgstr "Сайттар" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Домен атауының ішінде аралық және табуляция белілерге тыйым салынады" + +msgid "domain name" +msgstr "домен атауы" + +msgid "display name" +msgstr "бейнелеу атауы" + +msgid "site" +msgstr "сайт" + +msgid "sites" +msgstr "сайттар" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/km/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/km/LC_MESSAGES/django.mo new file mode 100644 index 0000000..bb7aa00 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/km/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/km/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/km/LC_MESSAGES/django.po new file mode 100644 index 0000000..a039e77 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/km/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Khmer (http://www.transifex.com/django/django/language/km/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: km\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sites" +msgstr "" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "" + +msgid "domain name" +msgstr "ឈ្មោះដមែន" + +msgid "display name" +msgstr "ឈ្មោះសំរាប់បង្ហាញ" + +msgid "site" +msgstr "គេហទំព័រ" + +msgid "sites" +msgstr "គេហទំព័រ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/kn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/kn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..0d41465 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/kn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/kn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/kn/LC_MESSAGES/django.po new file mode 100644 index 0000000..8ff543a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/kn/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Rohith PR, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2021-08-03 10:54+0000\n" +"Last-Translator: Rohith PR\n" +"Language-Team: Kannada (http://www.transifex.com/django/django/language/" +"kn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: kn\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Sites" +msgstr "ತಾಣಗಳು" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "" + +msgid "domain name" +msgstr "ಡೊಮೈನ್ ಹೆಸರು" + +msgid "display name" +msgstr "ತೋರಿಸುವ ಹೆಸರು" + +msgid "site" +msgstr "ತಾಣ" + +msgid "sites" +msgstr "ತಾಣಗಳು" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ko/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ko/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e697676 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ko/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ko/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ko/LC_MESSAGES/django.po new file mode 100644 index 0000000..de726db --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ko/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jiyoon, Ha , 2016 +# Jannis Leidel , 2011 +# Le Tartuffe , 2014 +# Chr0m3 , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jiyoon, Ha \n" +"Language-Team: Korean (http://www.transifex.com/django/django/language/ko/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ko\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sites" +msgstr "사이트" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "도메인 이름은 공백이나 탭을 포함 할 수 없습니다." + +msgid "domain name" +msgstr "도메인 명" + +msgid "display name" +msgstr "표시명" + +msgid "site" +msgstr "사이트" + +msgid "sites" +msgstr "사이트들" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ky/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ky/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7bb9164 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ky/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ky/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ky/LC_MESSAGES/django.po new file mode 100644 index 0000000..e38cf65 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ky/LC_MESSAGES/django.po @@ -0,0 +1,34 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2020-05-23 06:09+0000\n" +"Last-Translator: Soyuzbek Orozbek uulu \n" +"Language-Team: Kyrgyz (http://www.transifex.com/django/django/language/ky/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ky\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sites" +msgstr "Сайттар" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "домен аты боштук жана секирик камтый албайт." + +msgid "domain name" +msgstr "домен аты" + +msgid "display name" +msgstr "көрүнүү аты" + +msgid "site" +msgstr "сайт" + +msgid "sites" +msgstr "сайттар" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/lb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/lb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5b7937f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/lb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/lb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/lb/LC_MESSAGES/django.po new file mode 100644 index 0000000..9e43bb9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/lb/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:12+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Luxembourgish (http://www.transifex.com/projects/p/django/" +"language/lb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "" + +msgid "domain name" +msgstr "" + +msgid "display name" +msgstr "" + +msgid "site" +msgstr "" + +msgid "sites" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/lt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/lt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8cdaf71 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/lt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/lt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/lt/LC_MESSAGES/django.po new file mode 100644 index 0000000..afcb5ac --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/lt/LC_MESSAGES/django.po @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Kostas , 2011 +# Matas Dailyda , 2015 +# Simonas Kazlauskas , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Matas Dailyda \n" +"Language-Team: Lithuanian (http://www.transifex.com/django/django/language/" +"lt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lt\n" +"Plural-Forms: nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < " +"11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? " +"1 : n % 1 != 0 ? 2: 3);\n" + +msgid "Sites" +msgstr "Tinklalapiai" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Domene negali būti tarpų ar tabuliavimo ženklų." + +msgid "domain name" +msgstr "domeno vardas" + +msgid "display name" +msgstr "rodomas vardas" + +msgid "site" +msgstr "tinklalapis" + +msgid "sites" +msgstr "tinklalapiai" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/lv/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/lv/LC_MESSAGES/django.mo new file mode 100644 index 0000000..a3ffa5f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/lv/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/lv/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/lv/LC_MESSAGES/django.po new file mode 100644 index 0000000..65fceb0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/lv/LC_MESSAGES/django.po @@ -0,0 +1,39 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# edgars , 2011 +# Jannis Leidel , 2011 +# peterisb , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: peterisb \n" +"Language-Team: Latvian (http://www.transifex.com/django/django/language/" +"lv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lv\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : " +"2);\n" + +msgid "Sites" +msgstr "Vietnes" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Domēna nosaukumā nevar būt tukšumi vai tabulatori." + +msgid "domain name" +msgstr "domēna vārds" + +msgid "display name" +msgstr "attēlojamais vārds" + +msgid "site" +msgstr "vietne" + +msgid "sites" +msgstr "vietnes" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/mk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/mk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..15763b6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/mk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/mk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/mk/LC_MESSAGES/django.po new file mode 100644 index 0000000..ad7a47d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/mk/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Vasil Vangelovski , 2013-2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Macedonian (http://www.transifex.com/django/django/language/" +"mk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mk\n" +"Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n" + +msgid "Sites" +msgstr "Сајтови" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Домејнот не може да содржи празни места и табови." + +msgid "domain name" +msgstr "домејн" + +msgid "display name" +msgstr "име за приказ" + +msgid "site" +msgstr "сајт" + +msgid "sites" +msgstr "сајтови" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ml/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ml/LC_MESSAGES/django.mo new file mode 100644 index 0000000..d1d7170 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ml/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ml/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ml/LC_MESSAGES/django.po new file mode 100644 index 0000000..3e70265 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ml/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Hrishikesh , 2019 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2019-03-03 09:57+0000\n" +"Last-Translator: Hrishikesh \n" +"Language-Team: Malayalam (http://www.transifex.com/django/django/language/" +"ml/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ml\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "സൈറ്റുകൾ" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "ഡൊമൈനിന്റെ പേരിൽ സ്പെയ്സുകളോ ടാബുകളോ അനുവദനീയമല്ല." + +msgid "domain name" +msgstr "ഡൊമൈനിന്റെ പേര്" + +msgid "display name" +msgstr "കാഴ്ചയ്ക്കായുള്ള പേര്" + +msgid "site" +msgstr "സൈറ്റ്" + +msgid "sites" +msgstr "സൈറ്റുകള്‍" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/mn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/mn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..6b1748b Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/mn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/mn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/mn/LC_MESSAGES/django.po new file mode 100644 index 0000000..1ab16b7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/mn/LC_MESSAGES/django.po @@ -0,0 +1,39 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bayarbat.U , 2015 +# Jannis Leidel , 2011 +# Zorig , 2014 +# Анхбаяр Анхаа , 2011,2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Bayarbat.U \n" +"Language-Team: Mongolian (http://www.transifex.com/django/django/language/" +"mn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Вэб сайтууд" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Домэйн нэрэнд таб болон хоосон зай бичиж болохгүй." + +msgid "domain name" +msgstr "домэйн нэр" + +msgid "display name" +msgstr "харагдах нэр" + +msgid "site" +msgstr "сайт" + +msgid "sites" +msgstr "сайтууд" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/mr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/mr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..183b3d1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/mr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/mr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/mr/LC_MESSAGES/django.po new file mode 100644 index 0000000..fc1e2a9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/mr/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:12+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Marathi (http://www.transifex.com/projects/p/django/language/" +"mr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mr\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "" + +msgid "domain name" +msgstr "" + +msgid "display name" +msgstr "" + +msgid "site" +msgstr "" + +msgid "sites" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ms/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ms/LC_MESSAGES/django.mo new file mode 100644 index 0000000..57289a7 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ms/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ms/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ms/LC_MESSAGES/django.po new file mode 100644 index 0000000..250a2da --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ms/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jafry Hisham, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2021-11-16 12:40+0000\n" +"Last-Translator: Jafry Hisham\n" +"Language-Team: Malay (http://www.transifex.com/django/django/language/ms/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ms\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sites" +msgstr "Laman-laman" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Nama domain tidak boleh mengandungi ruang kosong atau tab." + +msgid "domain name" +msgstr "nama domain" + +msgid "display name" +msgstr "nama paparan" + +msgid "site" +msgstr "laman" + +msgid "sites" +msgstr "laman-laman" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/my/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/my/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e706a9d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/my/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/my/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/my/LC_MESSAGES/django.po new file mode 100644 index 0000000..4d75d5c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/my/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Yhal Htet Aung , 2013,2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:50+0000\n" +"Last-Translator: Yhal Htet Aung \n" +"Language-Team: Burmese (http://www.transifex.com/django/django/language/" +"my/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: my\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sites" +msgstr "ဆိုက်များ" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "ဒိုမိန်းနာမည်တွင်ကွက်လပ်(သို့)အမည်များမပါဝင်နိုင်။" + +msgid "domain name" +msgstr "ဒိုမိန်းနာမည်" + +msgid "display name" +msgstr "ပြသနာမည်" + +msgid "site" +msgstr "ဆိုက်" + +msgid "sites" +msgstr "ဆိုက်များ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/nb/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/nb/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b18fe64 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/nb/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/nb/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/nb/LC_MESSAGES/django.po new file mode 100644 index 0000000..281b517 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/nb/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Alexander Hansen , 2013 +# Jannis Leidel , 2011 +# Jon , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Norwegian Bokmål (http://www.transifex.com/django/django/" +"language/nb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Nettsteder" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Domenenavnet kan ikke inneholde mellomrom." + +msgid "domain name" +msgstr "domenenavn" + +msgid "display name" +msgstr "visningsnavn" + +msgid "site" +msgstr "nettsted" + +msgid "sites" +msgstr "nettsteder" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ne/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ne/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8ece467 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ne/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ne/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ne/LC_MESSAGES/django.po new file mode 100644 index 0000000..c0d04d1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ne/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Sagar Chalise , 2011 +# Santosh Purbey , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2020-01-21 09:32+0000\n" +"Last-Translator: Santosh Purbey \n" +"Language-Team: Nepali (http://www.transifex.com/django/django/language/ne/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ne\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "साइटहरु" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "डोमेनमा खाली ठाउँहरु हुनु हुँदैन ।" + +msgid "domain name" +msgstr "डोमेनको नाम" + +msgid "display name" +msgstr "देखिने नाम" + +msgid "site" +msgstr "साईट" + +msgid "sites" +msgstr "साईटहरू" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/nl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/nl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1f62384 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/nl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/nl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/nl/LC_MESSAGES/django.po new file mode 100644 index 0000000..073ed78 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/nl/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Bouke Haarsma , 2013 +# Jannis Leidel , 2011 +# Sander Steffann , 2015 +# Tonnes , 2019 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2019-02-24 16:01+0000\n" +"Last-Translator: Tonnes \n" +"Language-Team: Dutch (http://www.transifex.com/django/django/language/nl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Websites" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "De domeinnaam mag geen spaties of tabs bevatten." + +msgid "domain name" +msgstr "domeinnaam" + +msgid "display name" +msgstr "weergavenaam" + +msgid "site" +msgstr "website" + +msgid "sites" +msgstr "websites" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/nn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/nn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9f44459 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/nn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/nn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/nn/LC_MESSAGES/django.po new file mode 100644 index 0000000..22e6ec6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/nn/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Sivert Olstad, 2021 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2021-11-11 00:23+0000\n" +"Last-Translator: Sivert Olstad\n" +"Language-Team: Norwegian Nynorsk (http://www.transifex.com/django/django/" +"language/nn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Nettstader" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Domenenamnet kan ikkje innehalde mellomrom." + +msgid "domain name" +msgstr "domenenamn" + +msgid "display name" +msgstr "visingsnamn" + +msgid "site" +msgstr "nettstad" + +msgid "sites" +msgstr "nettstader" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/os/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/os/LC_MESSAGES/django.mo new file mode 100644 index 0000000..6dbbccd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/os/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/os/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/os/LC_MESSAGES/django.po new file mode 100644 index 0000000..f0bcd2a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/os/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Soslan Khubulov , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:58+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Ossetic (http://www.transifex.com/django/django/language/" +"os/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: os\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Домены номы ма хъуамӕ уой табтӕ ӕмӕ хъӕнтӕ." + +msgid "domain name" +msgstr "домены ном" + +msgid "display name" +msgstr "ӕвдисгӕ ном" + +msgid "site" +msgstr "сайт" + +msgid "sites" +msgstr "сайттӕ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/pa/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/pa/LC_MESSAGES/django.mo new file mode 100644 index 0000000..2d6701f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/pa/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/pa/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/pa/LC_MESSAGES/django.po new file mode 100644 index 0000000..0d685d4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/pa/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Panjabi (Punjabi) (http://www.transifex.com/django/django/" +"language/pa/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pa\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "" + +msgid "domain name" +msgstr "ਡੋਮੇਨ ਨਾਂ" + +msgid "display name" +msgstr "ਵੇਖਾਉਣ ਲਈ ਨਾਂ" + +msgid "site" +msgstr "ਸਾਈਟ" + +msgid "sites" +msgstr "ਸਾਈਟਾਂ" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/pl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/pl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b0339c9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/pl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/pl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/pl/LC_MESSAGES/django.po new file mode 100644 index 0000000..ca0cdf3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/pl/LC_MESSAGES/django.po @@ -0,0 +1,40 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# angularcircle, 2013 +# Jannis Leidel , 2011 +# Mattia Procopio , 2014 +# Tomasz Kajtoch , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Tomasz Kajtoch \n" +"Language-Team: Polish (http://www.transifex.com/django/django/language/pl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pl\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n" +"%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n" +"%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" + +msgid "Sites" +msgstr "Strony" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Nazwa domeny nie może zawierać spacji ani tabulatorów." + +msgid "domain name" +msgstr "nazwa domeny" + +msgid "display name" +msgstr "nazwa wyświetlana" + +msgid "site" +msgstr "strona" + +msgid "sites" +msgstr "strony" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/pt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/pt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..5d885d1 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/pt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/pt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/pt/LC_MESSAGES/django.po new file mode 100644 index 0000000..ba716ae --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/pt/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Nuno Mariz , 2013 +# Raúl Pedro Fernandes Santos, 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Portuguese (http://www.transifex.com/django/django/language/" +"pt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Sites" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "O nome do domínio não pode conter espaços ou tabulações." + +msgid "domain name" +msgstr "nome do domínio" + +msgid "display name" +msgstr "mostrar nome" + +msgid "site" +msgstr "site" + +msgid "sites" +msgstr "sites" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/pt_BR/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/pt_BR/LC_MESSAGES/django.mo new file mode 100644 index 0000000..81c6300 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/pt_BR/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/pt_BR/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/pt_BR/LC_MESSAGES/django.po new file mode 100644 index 0000000..e146026 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/pt_BR/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Allisson Azevedo , 2014 +# Eduardo Cereto Carvalho, 2013 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: andrewsmedina \n" +"Language-Team: Portuguese (Brazil) (http://www.transifex.com/django/django/" +"language/pt_BR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt_BR\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Sites" +msgstr "Sites" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "O nome do domínio não pode conter espaços ou tabulações." + +msgid "domain name" +msgstr "nome do domínio" + +msgid "display name" +msgstr "nome para exibição" + +msgid "site" +msgstr "site" + +msgid "sites" +msgstr "sites" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ro/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ro/LC_MESSAGES/django.mo new file mode 100644 index 0000000..7ebbf59 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ro/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ro/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ro/LC_MESSAGES/django.po new file mode 100644 index 0000000..d5579e3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ro/LC_MESSAGES/django.po @@ -0,0 +1,40 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Daniel Ursache-Dogariu, 2011 +# Denis Darii , 2014 +# Jannis Leidel , 2011 +# Razvan Stefanescu , 2015 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Razvan Stefanescu \n" +"Language-Team: Romanian (http://www.transifex.com/django/django/language/" +"ro/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ro\n" +"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?" +"2:1));\n" + +msgid "Sites" +msgstr "Pagini web" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Numele de domeniu nu poate conține spații sau tab-uri." + +msgid "domain name" +msgstr "nume domeniu" + +msgid "display name" +msgstr "nume afișat" + +msgid "site" +msgstr "pagină web" + +msgid "sites" +msgstr "pagini web" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ru/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ru/LC_MESSAGES/django.mo new file mode 100644 index 0000000..cd6daf4 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ru/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ru/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ru/LC_MESSAGES/django.po new file mode 100644 index 0000000..353ed76 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ru/LC_MESSAGES/django.po @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Eugene MechanisM , 2013 +# Eugene MechanisM , 2016 +# Jannis Leidel , 2011 +# Алексей Борискин , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Eugene MechanisM \n" +"Language-Team: Russian (http://www.transifex.com/django/django/language/" +"ru/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ru\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n" +"%100>=11 && n%100<=14)? 2 : 3);\n" + +msgid "Sites" +msgstr "Сайты" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Доменное имя не может содержать пробелы или табуляцию." + +msgid "domain name" +msgstr "доменное имя" + +msgid "display name" +msgstr "отображаемое имя" + +msgid "site" +msgstr "сайт" + +msgid "sites" +msgstr "сайты" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..fbcf69a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sk/LC_MESSAGES/django.po new file mode 100644 index 0000000..0f48ec9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sk/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Marian Andre , 2013 +# Martin Tóth , 2017 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Martin Tóth \n" +"Language-Team: Slovak (http://www.transifex.com/django/django/language/sk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n " +">= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);\n" + +msgid "Sites" +msgstr "Sídla" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Názov domény nemôže obsahovať medzery alebo tabulátory." + +msgid "domain name" +msgstr "názov domény" + +msgid "display name" +msgstr "zobrazené meno" + +msgid "site" +msgstr "sídlo" + +msgid "sites" +msgstr "sídla" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sl/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sl/LC_MESSAGES/django.mo new file mode 100644 index 0000000..77d008f Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sl/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sl/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sl/LC_MESSAGES/django.po new file mode 100644 index 0000000..7a69572 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sl/LC_MESSAGES/django.po @@ -0,0 +1,39 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Primož Verdnik , 2017 +# zejn , 2013,2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Primož Verdnik \n" +"Language-Team: Slovenian (http://www.transifex.com/django/django/language/" +"sl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sl\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" + +msgid "Sites" +msgstr "Strani" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Domena ne sme vsebovati presledkov ali tabulatorjev." + +msgid "domain name" +msgstr "ime domene" + +msgid "display name" +msgstr "prikazano ime" + +msgid "site" +msgstr "stran" + +msgid "sites" +msgstr "strani" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sq/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sq/LC_MESSAGES/django.mo new file mode 100644 index 0000000..cbd1a6a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sq/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sq/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sq/LC_MESSAGES/django.po new file mode 100644 index 0000000..3ce9830 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sq/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Besnik , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-11-29 23:00+0000\n" +"Last-Translator: Besnik \n" +"Language-Team: Albanian (http://www.transifex.com/django/django/language/" +"sq/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sq\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Sajte" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Emri i përkatësisë s’mund të përmbajë hapësira ose tabulacione." + +msgid "domain name" +msgstr "emër përkatësie" + +msgid "display name" +msgstr "emër shfaqjeje" + +msgid "site" +msgstr "sajt" + +msgid "sites" +msgstr "sajte" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8ac57bb Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sr/LC_MESSAGES/django.po new file mode 100644 index 0000000..47e2e65 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sr/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Branko Kokanovic , 2018 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2018-01-30 10:13+0000\n" +"Last-Translator: Branko Kokanovic \n" +"Language-Team: Serbian (http://www.transifex.com/django/django/language/" +"sr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Sites" +msgstr "Сајтови" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Име домена не може да садржи размаке ни табове." + +msgid "domain name" +msgstr "име домена" + +msgid "display name" +msgstr "приказано име" + +msgid "site" +msgstr "сајт" + +msgid "sites" +msgstr "сајтови" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sr_Latn/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sr_Latn/LC_MESSAGES/django.mo new file mode 100644 index 0000000..deabe45 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sr_Latn/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sr_Latn/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sr_Latn/LC_MESSAGES/django.po new file mode 100644 index 0000000..03d3db0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sr_Latn/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Igor Jerosimić, 2019 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2019-06-27 12:41+0000\n" +"Last-Translator: Igor Jerosimić\n" +"Language-Team: Serbian (Latin) (http://www.transifex.com/django/django/" +"language/sr@latin/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr@latin\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Sites" +msgstr "Sajtovi" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Ime domena ne može da sadrži razmake ni tabove." + +msgid "domain name" +msgstr "ime domena" + +msgid "display name" +msgstr "prikazano ime" + +msgid "site" +msgstr "sajt" + +msgid "sites" +msgstr "sajtovi" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sv/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sv/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9b09021 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sv/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sv/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sv/LC_MESSAGES/django.po new file mode 100644 index 0000000..d727d90 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sv/LC_MESSAGES/django.po @@ -0,0 +1,39 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Anders Hovmöller , 2023 +# Jannis Leidel , 2011 +# Jonathan Lindén, 2014 +# Thomas Lundqvist, 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2023-04-24 18:05+0000\n" +"Last-Translator: Anders Hovmöller , 2023\n" +"Language-Team: Swedish (http://www.transifex.com/django/django/language/" +"sv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sv\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Webbplatser" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Domännamnet kan inte innehålla mellanslag eller tab." + +msgid "domain name" +msgstr "domännamn" + +msgid "display name" +msgstr "visningsnamn" + +msgid "site" +msgstr "webbplats" + +msgid "sites" +msgstr "webbplatser" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sw/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sw/LC_MESSAGES/django.mo new file mode 100644 index 0000000..1447715 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sw/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sw/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sw/LC_MESSAGES/django.po new file mode 100644 index 0000000..c3206e9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/sw/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Machaku , 2013-2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Swahili (http://www.transifex.com/django/django/language/" +"sw/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sw\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Tovuti" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Jina la kikoa haliwezi kuwa na nafasi yeyote kati yake." + +msgid "domain name" +msgstr "jina la kikoa" + +msgid "display name" +msgstr "jina" + +msgid "site" +msgstr "tovuti" + +msgid "sites" +msgstr "tovuti" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ta/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ta/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9cdaa1e Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ta/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ta/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ta/LC_MESSAGES/django.po new file mode 100644 index 0000000..883c04a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ta/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Tamil (http://www.transifex.com/django/django/language/ta/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ta\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "" + +msgid "domain name" +msgstr "களப் பெயர்" + +msgid "display name" +msgstr "காட்டும் பெயர்" + +msgid "site" +msgstr "வலைத்தளம்" + +msgid "sites" +msgstr "வலைத்தளங்கள்" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/te/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/te/LC_MESSAGES/django.mo new file mode 100644 index 0000000..9be611d Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/te/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/te/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/te/LC_MESSAGES/django.po new file mode 100644 index 0000000..3598aa6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/te/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Telugu (http://www.transifex.com/django/django/language/te/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: te\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "" + +msgid "domain name" +msgstr "డొమైన్ నామము" + +msgid "display name" +msgstr "కనిపిచ్చే పేరు" + +msgid "site" +msgstr "సైట్" + +msgid "sites" +msgstr "సైట్లు" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/tg/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/tg/LC_MESSAGES/django.mo new file mode 100644 index 0000000..e557293 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/tg/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/tg/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/tg/LC_MESSAGES/django.po new file mode 100644 index 0000000..cc7f86e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/tg/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Surush Sufiew , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2020-05-15 00:35+0000\n" +"Last-Translator: Surush Sufiew \n" +"Language-Team: Tajik (http://www.transifex.com/django/django/language/tg/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tg\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Сомонаҳо" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Номи домен наметавонад аз фосилаҳо ва табулятсия иборат бошад." + +msgid "domain name" +msgstr "номи доменӣ" + +msgid "display name" +msgstr "номи инъикосшуда" + +msgid "site" +msgstr "сомона" + +msgid "sites" +msgstr "сомонаҳо" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/th/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/th/LC_MESSAGES/django.mo new file mode 100644 index 0000000..bd461b6 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/th/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/th/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/th/LC_MESSAGES/django.po new file mode 100644 index 0000000..89df6a6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/th/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Kowit Charoenratchatabhan , 2013,2018 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2018-05-06 08:37+0000\n" +"Last-Translator: Kowit Charoenratchatabhan \n" +"Language-Team: Thai (http://www.transifex.com/django/django/language/th/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: th\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sites" +msgstr "ไซต์" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "ชื่อโดนเมนต้องไม่ไม่ช่องว่างหรือแท็บ" + +msgid "domain name" +msgstr "ชื่อโดเมน" + +msgid "display name" +msgstr "ชื่อที่แสดง" + +msgid "site" +msgstr "ไซต์" + +msgid "sites" +msgstr "ไซต์" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/tk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/tk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..854a902 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/tk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/tk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/tk/LC_MESSAGES/django.po new file mode 100644 index 0000000..a54affa --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/tk/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Resulkary , 2020 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2020-07-06 11:50+0000\n" +"Last-Translator: Resulkary \n" +"Language-Team: Turkmen (http://www.transifex.com/django/django/language/" +"tk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tk\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "Sahypalar" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Domen adynda boşluklar ýa-da goýmalar bolup bilmez." + +msgid "domain name" +msgstr "domen ady" + +msgid "display name" +msgstr "görkezilýän ady" + +msgid "site" +msgstr "sahypa" + +msgid "sites" +msgstr "sahypalar" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/tr/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/tr/LC_MESSAGES/django.mo new file mode 100644 index 0000000..b077813 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/tr/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/tr/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/tr/LC_MESSAGES/django.po new file mode 100644 index 0000000..2372c14 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/tr/LC_MESSAGES/django.po @@ -0,0 +1,39 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Ahmet Emre Aladağ , 2014 +# BouRock, 2014 +# Caner Başaran , 2013 +# Jannis Leidel , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Turkish (http://www.transifex.com/django/django/language/" +"tr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Sites" +msgstr "Siteler" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Etki alanı adı, herhangi bir boşluk ya da sekme içeremez." + +msgid "domain name" +msgstr "etki alanı adı" + +msgid "display name" +msgstr "görünen isim" + +msgid "site" +msgstr "site" + +msgid "sites" +msgstr "siteler" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/tt/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/tt/LC_MESSAGES/django.mo new file mode 100644 index 0000000..384d79a Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/tt/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/tt/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/tt/LC_MESSAGES/django.po new file mode 100644 index 0000000..519ece3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/tt/LC_MESSAGES/django.po @@ -0,0 +1,36 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Azat Khasanshin , 2011 +# v_ildar , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Tatar (http://www.transifex.com/django/django/language/tt/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tt\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sites" +msgstr "Сайтлар" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "" + +msgid "domain name" +msgstr "домен исеме" + +msgid "display name" +msgstr "чагылдырылган исем" + +msgid "site" +msgstr "сайт" + +msgid "sites" +msgstr "сайтлар" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/udm/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/udm/LC_MESSAGES/django.mo new file mode 100644 index 0000000..af7ab53 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/udm/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/udm/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/udm/LC_MESSAGES/django.po new file mode 100644 index 0000000..26b17e7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/udm/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2014-10-05 20:13+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Udmurt (http://www.transifex.com/projects/p/django/language/" +"udm/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: udm\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sites" +msgstr "" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "" + +msgid "domain name" +msgstr "" + +msgid "display name" +msgstr "" + +msgid "site" +msgstr "" + +msgid "sites" +msgstr "" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ug/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ug/LC_MESSAGES/django.mo new file mode 100644 index 0000000..993ca82 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ug/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ug/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ug/LC_MESSAGES/django.po new file mode 100644 index 0000000..e5b00f8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ug/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Abduqadir Abliz , 2023 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2023-12-04 18:05+0000\n" +"Last-Translator: Abduqadir Abliz , 2023\n" +"Language-Team: Uyghur (http://app.transifex.com/django/django/language/ug/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ug\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "بېكەتلەر" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "دائىرە نامى ھەر قانداق بوشلۇق ياكى tab بوشلۇقنى ئۆز ئىچىگە ئالمايدۇ." + +msgid "domain name" +msgstr "دائىرە ئاتى" + +msgid "display name" +msgstr "كۆرسىتىش ئاتى" + +msgid "site" +msgstr "بېكەت" + +msgid "sites" +msgstr "بېكەتلەر" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/uk/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/uk/LC_MESSAGES/django.mo new file mode 100644 index 0000000..8ffb1b9 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/uk/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/uk/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/uk/LC_MESSAGES/django.po new file mode 100644 index 0000000..f98454c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/uk/LC_MESSAGES/django.po @@ -0,0 +1,41 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Oleksandr Chernihov , 2014 +# Jannis Leidel , 2011 +# Alex Bolotov , 2013 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Mykola Zamkovoi \n" +"Language-Team: Ukrainian (http://www.transifex.com/django/django/language/" +"uk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: uk\n" +"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != " +"11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % " +"100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || " +"(n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n" + +msgid "Sites" +msgstr "Сайти" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Доменне ім'я не може містити пробіли або символи табуляції." + +msgid "domain name" +msgstr "доменне ім'я" + +msgid "display name" +msgstr "відображуване ім'я" + +msgid "site" +msgstr "сайт" + +msgid "sites" +msgstr "сайти" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ur/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ur/LC_MESSAGES/django.mo new file mode 100644 index 0000000..733aebd Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ur/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ur/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ur/LC_MESSAGES/django.po new file mode 100644 index 0000000..b16ddb2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/ur/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Mansoorulhaq Mansoor , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Urdu (http://www.transifex.com/django/django/language/ur/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ur\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Sites" +msgstr "" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "" + +msgid "domain name" +msgstr "ڈومین کا نام" + +msgid "display name" +msgstr "ظاھر ھونے والا نام" + +msgid "site" +msgstr "سائٹ" + +msgid "sites" +msgstr "سائٹس" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/uz/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/uz/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f1c68e3 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/uz/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/uz/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/uz/LC_MESSAGES/django.po new file mode 100644 index 0000000..4f26906 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/uz/LC_MESSAGES/django.po @@ -0,0 +1,35 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Nuruddin Iminokhunov , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 01:18+0000\n" +"Last-Translator: Nuruddin Iminokhunov \n" +"Language-Team: Uzbek (http://www.transifex.com/django/django/language/uz/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: uz\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sites" +msgstr "Saytlar" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Domen ismi tab`lar va bo'shliqlarsiz bo'lishi kerak" + +msgid "domain name" +msgstr "domen nomi" + +msgid "display name" +msgstr "ko'rsatiladigan ismi" + +msgid "site" +msgstr "sayt" + +msgid "sites" +msgstr "saytlar" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/vi/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/vi/LC_MESSAGES/django.mo new file mode 100644 index 0000000..36fa075 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/vi/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/vi/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/vi/LC_MESSAGES/django.po new file mode 100644 index 0000000..6f7d6a0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/vi/LC_MESSAGES/django.po @@ -0,0 +1,38 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Thanh Le Viet , 2013 +# Tran , 2011 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-23 18:54+0000\n" +"Last-Translator: Tran Van \n" +"Language-Team: Vietnamese (http://www.transifex.com/django/django/language/" +"vi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: vi\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sites" +msgstr "" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "Tên miền không gồm kí tự trống hoặc tab" + +msgid "domain name" +msgstr "Tên miền" + +msgid "display name" +msgstr "Tên hiển thị" + +msgid "site" +msgstr "trang web" + +msgid "sites" +msgstr "các trang web" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/zh_Hans/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/zh_Hans/LC_MESSAGES/django.mo new file mode 100644 index 0000000..028280c Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/zh_Hans/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/zh_Hans/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/zh_Hans/LC_MESSAGES/django.po new file mode 100644 index 0000000..82f53fa --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/zh_Hans/LC_MESSAGES/django.po @@ -0,0 +1,37 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Jannis Leidel , 2011 +# Ronald White , 2014 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Jannis Leidel \n" +"Language-Team: Chinese (China) (http://www.transifex.com/django/django/" +"language/zh_CN/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_CN\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sites" +msgstr "站点" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "域名不能包含任何空格或制表符。" + +msgid "domain name" +msgstr "域名" + +msgid "display name" +msgstr "显示名称" + +msgid "site" +msgstr "站点" + +msgid "sites" +msgstr "站点" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/zh_Hant/LC_MESSAGES/django.mo b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/zh_Hant/LC_MESSAGES/django.mo new file mode 100644 index 0000000..f1c3d67 Binary files /dev/null and b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/zh_Hant/LC_MESSAGES/django.mo differ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/zh_Hant/LC_MESSAGES/django.po b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/zh_Hant/LC_MESSAGES/django.po new file mode 100644 index 0000000..d1a5583 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/locale/zh_Hant/LC_MESSAGES/django.po @@ -0,0 +1,39 @@ +# This file is distributed under the same license as the Django package. +# +# Translators: +# Chen Chun-Chia , 2015 +# Jannis Leidel , 2011 +# mail6543210 , 2013 +# Tzu-ping Chung , 2016 +msgid "" +msgstr "" +"Project-Id-Version: django\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-17 11:07+0100\n" +"PO-Revision-Date: 2017-09-19 16:40+0000\n" +"Last-Translator: Tzu-ping Chung \n" +"Language-Team: Chinese (Taiwan) (http://www.transifex.com/django/django/" +"language/zh_TW/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_TW\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Sites" +msgstr "網站" + +msgid "The domain name cannot contain any spaces or tabs." +msgstr "網域名稱不能包含空格或定位字元。" + +msgid "domain name" +msgstr "網域名稱" + +msgid "display name" +msgstr "顯示名稱" + +msgid "site" +msgstr "網站" + +msgid "sites" +msgstr "網站" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/management.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/management.py new file mode 100644 index 0000000..dd75bc1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/management.py @@ -0,0 +1,47 @@ +""" +Creates the default Site object. +""" + +from django.apps import apps as global_apps +from django.conf import settings +from django.core.management.color import no_style +from django.db import DEFAULT_DB_ALIAS, connections, router + + +def create_default_site( + app_config, + verbosity=2, + interactive=True, + using=DEFAULT_DB_ALIAS, + apps=global_apps, + **kwargs, +): + try: + Site = apps.get_model("sites", "Site") + except LookupError: + return + + if not router.allow_migrate_model(using, Site): + return + + if not Site.objects.using(using).exists(): + # The default settings set SITE_ID = 1, and some tests in Django's test + # suite rely on this value. However, if database sequences are reused + # (e.g. in the test suite after flush/syncdb), it isn't guaranteed that + # the next id will be 1, so we coerce it. See #15573 and #16353. This + # can also crop up outside of tests - see #15346. + if verbosity >= 2: + print("Creating example.com Site object") + Site( + pk=getattr(settings, "SITE_ID", 1), domain="example.com", name="example.com" + ).save(using=using) + + # We set an explicit pk instead of relying on auto-incrementation, + # so we need to reset the database sequence. See #17415. + sequence_sql = connections[using].ops.sequence_reset_sql(no_style(), [Site]) + if sequence_sql: + if verbosity >= 2: + print("Resetting sequence") + with connections[using].cursor() as cursor: + for command in sequence_sql: + cursor.execute(command) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/managers.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/managers.py new file mode 100644 index 0000000..ec28826 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/managers.py @@ -0,0 +1,65 @@ +from django.conf import settings +from django.core import checks +from django.core.exceptions import FieldDoesNotExist +from django.db import models + + +class CurrentSiteManager(models.Manager): + "Use this to limit objects to those associated with the current site." + + use_in_migrations = True + + def __init__(self, field_name=None): + super().__init__() + self.__field_name = field_name + + def check(self, **kwargs): + errors = super().check(**kwargs) + errors.extend(self._check_field_name()) + return errors + + def _check_field_name(self): + field_name = self._get_field_name() + try: + field = self.model._meta.get_field(field_name) + except FieldDoesNotExist: + return [ + checks.Error( + "CurrentSiteManager could not find a field named '%s'." + % field_name, + obj=self, + id="sites.E001", + ) + ] + + if not field.many_to_many and not isinstance(field, (models.ForeignKey)): + return [ + checks.Error( + "CurrentSiteManager cannot use '%s.%s' as it is not a foreign key " + "or a many-to-many field." + % (self.model._meta.object_name, field_name), + obj=self, + id="sites.E002", + ) + ] + + return [] + + def _get_field_name(self): + """Return self.__field_name or 'site' or 'sites'.""" + + if not self.__field_name: + try: + self.model._meta.get_field("site") + except FieldDoesNotExist: + self.__field_name = "sites" + else: + self.__field_name = "site" + return self.__field_name + + def get_queryset(self): + return ( + super() + .get_queryset() + .filter(**{self._get_field_name() + "__id": settings.SITE_ID}) + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/middleware.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/middleware.py new file mode 100644 index 0000000..bc3bf20 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/middleware.py @@ -0,0 +1,12 @@ +from django.utils.deprecation import MiddlewareMixin + +from .shortcuts import get_current_site + + +class CurrentSiteMiddleware(MiddlewareMixin): + """ + Middleware that sets `site` attribute to request object. + """ + + def process_request(self, request): + request.site = get_current_site(request) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/migrations/0001_initial.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/migrations/0001_initial.py new file mode 100644 index 0000000..a23f0f1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/migrations/0001_initial.py @@ -0,0 +1,43 @@ +import django.contrib.sites.models +from django.contrib.sites.models import _simple_domain_name_validator +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [] + + operations = [ + migrations.CreateModel( + name="Site", + fields=[ + ( + "id", + models.AutoField( + verbose_name="ID", + serialize=False, + auto_created=True, + primary_key=True, + ), + ), + ( + "domain", + models.CharField( + max_length=100, + verbose_name="domain name", + validators=[_simple_domain_name_validator], + ), + ), + ("name", models.CharField(max_length=50, verbose_name="display name")), + ], + options={ + "ordering": ["domain"], + "db_table": "django_site", + "verbose_name": "site", + "verbose_name_plural": "sites", + }, + bases=(models.Model,), + managers=[ + ("objects", django.contrib.sites.models.SiteManager()), + ], + ), + ] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/migrations/0002_alter_domain_unique.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/migrations/0002_alter_domain_unique.py new file mode 100644 index 0000000..e379a91 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/migrations/0002_alter_domain_unique.py @@ -0,0 +1,21 @@ +import django.contrib.sites.models +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("sites", "0001_initial"), + ] + + operations = [ + migrations.AlterField( + model_name="site", + name="domain", + field=models.CharField( + max_length=100, + unique=True, + validators=[django.contrib.sites.models._simple_domain_name_validator], + verbose_name="domain name", + ), + ), + ] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/migrations/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/models.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/models.py new file mode 100644 index 0000000..7f8bce9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/models.py @@ -0,0 +1,120 @@ +import string + +from django.core.exceptions import ImproperlyConfigured, ValidationError +from django.db import models +from django.db.models.signals import pre_delete, pre_save +from django.http.request import split_domain_port +from django.utils.translation import gettext_lazy as _ + +SITE_CACHE = {} + + +def _simple_domain_name_validator(value): + """ + Validate that the given value contains no whitespaces to prevent common + typos. + """ + checks = ((s in value) for s in string.whitespace) + if any(checks): + raise ValidationError( + _("The domain name cannot contain any spaces or tabs."), + code="invalid", + ) + + +class SiteManager(models.Manager): + use_in_migrations = True + + def _get_site_by_id(self, site_id): + if site_id not in SITE_CACHE: + site = self.get(pk=site_id) + SITE_CACHE[site_id] = site + return SITE_CACHE[site_id] + + def _get_site_by_request(self, request): + host = request.get_host() + try: + # First attempt to look up the site by host with or without port. + if host not in SITE_CACHE: + SITE_CACHE[host] = self.get(domain__iexact=host) + return SITE_CACHE[host] + except Site.DoesNotExist: + # Fallback to looking up site after stripping port from the host. + domain, port = split_domain_port(host) + if domain not in SITE_CACHE: + SITE_CACHE[domain] = self.get(domain__iexact=domain) + return SITE_CACHE[domain] + + def get_current(self, request=None): + """ + Return the current Site based on the SITE_ID in the project's settings. + If SITE_ID isn't defined, return the site with domain matching + request.get_host(). The ``Site`` object is cached the first time it's + retrieved from the database. + """ + from django.conf import settings + + if getattr(settings, "SITE_ID", ""): + site_id = settings.SITE_ID + return self._get_site_by_id(site_id) + elif request: + return self._get_site_by_request(request) + + raise ImproperlyConfigured( + 'You\'re using the Django "sites framework" without having ' + "set the SITE_ID setting. Create a site in your database and " + "set the SITE_ID setting or pass a request to " + "Site.objects.get_current() to fix this error." + ) + + def clear_cache(self): + """Clear the ``Site`` object cache.""" + global SITE_CACHE + SITE_CACHE = {} + + def get_by_natural_key(self, domain): + return self.get(domain=domain) + + +class Site(models.Model): + domain = models.CharField( + _("domain name"), + max_length=100, + validators=[_simple_domain_name_validator], + unique=True, + ) + name = models.CharField(_("display name"), max_length=50) + + objects = SiteManager() + + class Meta: + db_table = "django_site" + verbose_name = _("site") + verbose_name_plural = _("sites") + ordering = ["domain"] + + def __str__(self): + return self.domain + + def natural_key(self): + return (self.domain,) + + +def clear_site_cache(sender, **kwargs): + """ + Clear the cache (if primed) each time a site is saved or deleted. + """ + instance = kwargs["instance"] + using = kwargs["using"] + try: + del SITE_CACHE[instance.pk] + except KeyError: + pass + try: + del SITE_CACHE[Site.objects.using(using).get(pk=instance.pk).domain] + except (KeyError, Site.DoesNotExist): + pass + + +pre_save.connect(clear_site_cache, sender=Site) +pre_delete.connect(clear_site_cache, sender=Site) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/requests.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/requests.py new file mode 100644 index 0000000..a0c9c18 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/requests.py @@ -0,0 +1,20 @@ +class RequestSite: + """ + A class that shares the primary interface of Site (i.e., it has ``domain`` + and ``name`` attributes) but gets its data from an HttpRequest object + rather than from a database. + + The save() and delete() methods raise NotImplementedError. + """ + + def __init__(self, request): + self.domain = self.name = request.get_host() + + def __str__(self): + return self.domain + + def save(self, force_insert=False, force_update=False): + raise NotImplementedError("RequestSite cannot be saved.") + + def delete(self): + raise NotImplementedError("RequestSite cannot be deleted.") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/shortcuts.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/shortcuts.py new file mode 100644 index 0000000..d4b6510 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/sites/shortcuts.py @@ -0,0 +1,18 @@ +from django.apps import apps + +from .requests import RequestSite + + +def get_current_site(request): + """ + Check if contrib.sites is installed and return either the current + ``Site`` object or a ``RequestSite`` object based on the request. + """ + # Import is inside the function because its point is to avoid importing the + # Site models when django.contrib.sites isn't installed. + if apps.is_installed("django.contrib.sites"): + from .models import Site + + return Site.objects.get_current(request) + else: + return RequestSite(request) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/apps.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/apps.py new file mode 100644 index 0000000..08d827c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/apps.py @@ -0,0 +1,14 @@ +from django.apps import AppConfig +from django.contrib.staticfiles.checks import check_finders, check_storages +from django.core import checks +from django.utils.translation import gettext_lazy as _ + + +class StaticFilesConfig(AppConfig): + name = "django.contrib.staticfiles" + verbose_name = _("Static Files") + ignore_patterns = ["CVS", ".*", "*~"] + + def ready(self): + checks.register(check_finders, checks.Tags.staticfiles) + checks.register(check_storages, checks.Tags.staticfiles) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/checks.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/checks.py new file mode 100644 index 0000000..06b87c2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/checks.py @@ -0,0 +1,29 @@ +from django.conf import STATICFILES_STORAGE_ALIAS, settings +from django.contrib.staticfiles.finders import get_finders +from django.core.checks import Error + +E005 = Error( + f"The STORAGES setting must define a '{STATICFILES_STORAGE_ALIAS}' storage.", + id="staticfiles.E005", +) + + +def check_finders(app_configs=None, **kwargs): + """Check all registered staticfiles finders.""" + errors = [] + for finder in get_finders(): + try: + finder_errors = finder.check() + except NotImplementedError: + pass + else: + errors.extend(finder_errors) + return errors + + +def check_storages(app_configs=None, **kwargs): + """Ensure staticfiles is defined in STORAGES setting.""" + errors = [] + if STATICFILES_STORAGE_ALIAS not in settings.STORAGES: + errors.append(E005) + return errors diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/finders.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/finders.py new file mode 100644 index 0000000..112a81d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/finders.py @@ -0,0 +1,326 @@ +import functools +import os + +from django.apps import apps +from django.conf import settings +from django.contrib.staticfiles import utils +from django.core.checks import Error, Warning +from django.core.exceptions import ImproperlyConfigured +from django.core.files.storage import FileSystemStorage, Storage, default_storage +from django.utils._os import safe_join +from django.utils.functional import LazyObject, empty +from django.utils.module_loading import import_string + +# To keep track on which directories the finder has searched the static files. +searched_locations = [] + + +class BaseFinder: + """ + A base file finder to be used for custom staticfiles finder classes. + """ + + def check(self, **kwargs): + raise NotImplementedError( + "subclasses may provide a check() method to verify the finder is " + "configured correctly." + ) + + def find(self, path, all=False): + """ + Given a relative file path, find an absolute file path. + + If the ``all`` parameter is False (default) return only the first found + file path; if True, return a list of all found files paths. + """ + raise NotImplementedError( + "subclasses of BaseFinder must provide a find() method" + ) + + def list(self, ignore_patterns): + """ + Given an optional list of paths to ignore, return a two item iterable + consisting of the relative path and storage instance. + """ + raise NotImplementedError( + "subclasses of BaseFinder must provide a list() method" + ) + + +class FileSystemFinder(BaseFinder): + """ + A static files finder that uses the ``STATICFILES_DIRS`` setting + to locate files. + """ + + def __init__(self, app_names=None, *args, **kwargs): + # List of locations with static files + self.locations = [] + # Maps dir paths to an appropriate storage instance + self.storages = {} + for root in settings.STATICFILES_DIRS: + if isinstance(root, (list, tuple)): + prefix, root = root + else: + prefix = "" + if (prefix, root) not in self.locations: + self.locations.append((prefix, root)) + for prefix, root in self.locations: + filesystem_storage = FileSystemStorage(location=root) + filesystem_storage.prefix = prefix + self.storages[root] = filesystem_storage + super().__init__(*args, **kwargs) + + def check(self, **kwargs): + errors = [] + if not isinstance(settings.STATICFILES_DIRS, (list, tuple)): + errors.append( + Error( + "The STATICFILES_DIRS setting is not a tuple or list.", + hint="Perhaps you forgot a trailing comma?", + id="staticfiles.E001", + ) + ) + return errors + for root in settings.STATICFILES_DIRS: + if isinstance(root, (list, tuple)): + prefix, root = root + if prefix.endswith("/"): + errors.append( + Error( + "The prefix %r in the STATICFILES_DIRS setting must " + "not end with a slash." % prefix, + id="staticfiles.E003", + ) + ) + if settings.STATIC_ROOT and os.path.abspath( + settings.STATIC_ROOT + ) == os.path.abspath(root): + errors.append( + Error( + "The STATICFILES_DIRS setting should not contain the " + "STATIC_ROOT setting.", + id="staticfiles.E002", + ) + ) + if not os.path.isdir(root): + errors.append( + Warning( + f"The directory '{root}' in the STATICFILES_DIRS setting " + f"does not exist.", + id="staticfiles.W004", + ) + ) + return errors + + def find(self, path, all=False): + """ + Look for files in the extra locations as defined in STATICFILES_DIRS. + """ + matches = [] + for prefix, root in self.locations: + if root not in searched_locations: + searched_locations.append(root) + matched_path = self.find_location(root, path, prefix) + if matched_path: + if not all: + return matched_path + matches.append(matched_path) + return matches + + def find_location(self, root, path, prefix=None): + """ + Find a requested static file in a location and return the found + absolute path (or ``None`` if no match). + """ + if prefix: + prefix = "%s%s" % (prefix, os.sep) + if not path.startswith(prefix): + return None + path = path.removeprefix(prefix) + path = safe_join(root, path) + if os.path.exists(path): + return path + + def list(self, ignore_patterns): + """ + List all files in all locations. + """ + for prefix, root in self.locations: + # Skip nonexistent directories. + if os.path.isdir(root): + storage = self.storages[root] + for path in utils.get_files(storage, ignore_patterns): + yield path, storage + + +class AppDirectoriesFinder(BaseFinder): + """ + A static files finder that looks in the directory of each app as + specified in the source_dir attribute. + """ + + storage_class = FileSystemStorage + source_dir = "static" + + def __init__(self, app_names=None, *args, **kwargs): + # The list of apps that are handled + self.apps = [] + # Mapping of app names to storage instances + self.storages = {} + app_configs = apps.get_app_configs() + if app_names: + app_names = set(app_names) + app_configs = [ac for ac in app_configs if ac.name in app_names] + for app_config in app_configs: + app_storage = self.storage_class( + os.path.join(app_config.path, self.source_dir) + ) + if os.path.isdir(app_storage.location): + self.storages[app_config.name] = app_storage + if app_config.name not in self.apps: + self.apps.append(app_config.name) + super().__init__(*args, **kwargs) + + def list(self, ignore_patterns): + """ + List all files in all app storages. + """ + for storage in self.storages.values(): + if storage.exists(""): # check if storage location exists + for path in utils.get_files(storage, ignore_patterns): + yield path, storage + + def find(self, path, all=False): + """ + Look for files in the app directories. + """ + matches = [] + for app in self.apps: + app_location = self.storages[app].location + if app_location not in searched_locations: + searched_locations.append(app_location) + match = self.find_in_app(app, path) + if match: + if not all: + return match + matches.append(match) + return matches + + def find_in_app(self, app, path): + """ + Find a requested static file in an app's static locations. + """ + storage = self.storages.get(app) + # Only try to find a file if the source dir actually exists. + if storage and storage.exists(path): + matched_path = storage.path(path) + if matched_path: + return matched_path + + +class BaseStorageFinder(BaseFinder): + """ + A base static files finder to be used to extended + with an own storage class. + """ + + storage = None + + def __init__(self, storage=None, *args, **kwargs): + if storage is not None: + self.storage = storage + if self.storage is None: + raise ImproperlyConfigured( + "The staticfiles storage finder %r " + "doesn't have a storage class " + "assigned." % self.__class__ + ) + # Make sure we have a storage instance here. + if not isinstance(self.storage, (Storage, LazyObject)): + self.storage = self.storage() + super().__init__(*args, **kwargs) + + def find(self, path, all=False): + """ + Look for files in the default file storage, if it's local. + """ + try: + self.storage.path("") + except NotImplementedError: + pass + else: + if self.storage.location not in searched_locations: + searched_locations.append(self.storage.location) + if self.storage.exists(path): + match = self.storage.path(path) + if all: + match = [match] + return match + return [] + + def list(self, ignore_patterns): + """ + List all files of the storage. + """ + for path in utils.get_files(self.storage, ignore_patterns): + yield path, self.storage + + +class DefaultStorageFinder(BaseStorageFinder): + """ + A static files finder that uses the default storage backend. + """ + + storage = default_storage + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + base_location = getattr(self.storage, "base_location", empty) + if not base_location: + raise ImproperlyConfigured( + "The storage backend of the " + "staticfiles finder %r doesn't have " + "a valid location." % self.__class__ + ) + + +def find(path, all=False): + """ + Find a static file with the given path using all enabled finders. + + If ``all`` is ``False`` (default), return the first matching + absolute path (or ``None`` if no match). Otherwise return a list. + """ + searched_locations[:] = [] + matches = [] + for finder in get_finders(): + result = finder.find(path, all=all) + if not all and result: + return result + if not isinstance(result, (list, tuple)): + result = [result] + matches.extend(result) + if matches: + return matches + # No match. + return [] if all else None + + +def get_finders(): + for finder_path in settings.STATICFILES_FINDERS: + yield get_finder(finder_path) + + +@functools.cache +def get_finder(import_path): + """ + Import the staticfiles finder class described by import_path, where + import_path is the full Python path to the class. + """ + Finder = import_string(import_path) + if not issubclass(Finder, BaseFinder): + raise ImproperlyConfigured( + 'Finder "%s" is not a subclass of "%s"' % (Finder, BaseFinder) + ) + return Finder() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/handlers.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/handlers.py new file mode 100644 index 0000000..7394eff --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/handlers.py @@ -0,0 +1,115 @@ +from urllib.parse import urlparse +from urllib.request import url2pathname + +from asgiref.sync import sync_to_async + +from django.conf import settings +from django.contrib.staticfiles import utils +from django.contrib.staticfiles.views import serve +from django.core.handlers.asgi import ASGIHandler +from django.core.handlers.exception import response_for_exception +from django.core.handlers.wsgi import WSGIHandler, get_path_info +from django.http import Http404 + + +class StaticFilesHandlerMixin: + """ + Common methods used by WSGI and ASGI handlers. + """ + + # May be used to differentiate between handler types (e.g. in a + # request_finished signal) + handles_files = True + + def load_middleware(self): + # Middleware are already loaded for self.application; no need to reload + # them for self. + pass + + def get_base_url(self): + utils.check_settings() + return settings.STATIC_URL + + def _should_handle(self, path): + """ + Check if the path should be handled. Ignore the path if: + * the host is provided as part of the base_url + * the request's path isn't under the media path (or equal) + """ + return path.startswith(self.base_url[2]) and not self.base_url[1] + + def file_path(self, url): + """ + Return the relative path to the media file on disk for the given URL. + """ + relative_url = url.removeprefix(self.base_url[2]) + return url2pathname(relative_url) + + def serve(self, request): + """Serve the request path.""" + return serve(request, self.file_path(request.path), insecure=True) + + def get_response(self, request): + try: + return self.serve(request) + except Http404 as e: + return response_for_exception(request, e) + + async def get_response_async(self, request): + try: + return await sync_to_async(self.serve, thread_sensitive=False)(request) + except Http404 as e: + return await sync_to_async(response_for_exception, thread_sensitive=False)( + request, e + ) + + +class StaticFilesHandler(StaticFilesHandlerMixin, WSGIHandler): + """ + WSGI middleware that intercepts calls to the static files directory, as + defined by the STATIC_URL setting, and serves those files. + """ + + def __init__(self, application): + self.application = application + self.base_url = urlparse(self.get_base_url()) + super().__init__() + + def __call__(self, environ, start_response): + if not self._should_handle(get_path_info(environ)): + return self.application(environ, start_response) + return super().__call__(environ, start_response) + + +class ASGIStaticFilesHandler(StaticFilesHandlerMixin, ASGIHandler): + """ + ASGI application which wraps another and intercepts requests for static + files, passing them off to Django's static file serving. + """ + + def __init__(self, application): + self.application = application + self.base_url = urlparse(self.get_base_url()) + + async def __call__(self, scope, receive, send): + # Only even look at HTTP requests + if scope["type"] == "http" and self._should_handle(scope["path"]): + # Serve static content + # (the one thing super() doesn't do is __call__, apparently) + return await super().__call__(scope, receive, send) + # Hand off to the main app + return await self.application(scope, receive, send) + + async def get_response_async(self, request): + response = await super().get_response_async(request) + response._resource_closers.append(request.close) + # FileResponse is not async compatible. + if response.streaming and not response.is_async: + _iterator = response.streaming_content + + async def awrapper(): + for part in await sync_to_async(list)(_iterator): + yield part + + response.streaming_content = awrapper() + return response diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/management/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/management/commands/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/management/commands/collectstatic.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/management/commands/collectstatic.py new file mode 100644 index 0000000..c346038 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/management/commands/collectstatic.py @@ -0,0 +1,379 @@ +import os + +from django.apps import apps +from django.contrib.staticfiles.finders import get_finders +from django.contrib.staticfiles.storage import staticfiles_storage +from django.core.checks import Tags +from django.core.files.storage import FileSystemStorage +from django.core.management.base import BaseCommand, CommandError +from django.core.management.color import no_style +from django.utils.functional import cached_property + + +class Command(BaseCommand): + """ + Copies or symlinks static files from different locations to the + settings.STATIC_ROOT. + """ + + help = "Collect static files in a single location." + requires_system_checks = [Tags.staticfiles] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.copied_files = [] + self.symlinked_files = [] + self.unmodified_files = [] + self.post_processed_files = [] + self.storage = staticfiles_storage + self.style = no_style() + + @cached_property + def local(self): + try: + self.storage.path("") + except NotImplementedError: + return False + return True + + def add_arguments(self, parser): + parser.add_argument( + "--noinput", + "--no-input", + action="store_false", + dest="interactive", + help="Do NOT prompt the user for input of any kind.", + ) + parser.add_argument( + "--no-post-process", + action="store_false", + dest="post_process", + help="Do NOT post process collected files.", + ) + parser.add_argument( + "-i", + "--ignore", + action="append", + default=[], + dest="ignore_patterns", + metavar="PATTERN", + help="Ignore files or directories matching this glob-style " + "pattern. Use multiple times to ignore more.", + ) + parser.add_argument( + "-n", + "--dry-run", + action="store_true", + help="Do everything except modify the filesystem.", + ) + parser.add_argument( + "-c", + "--clear", + action="store_true", + help="Clear the existing files using the storage " + "before trying to copy or link the original file.", + ) + parser.add_argument( + "-l", + "--link", + action="store_true", + help="Create a symbolic link to each file instead of copying.", + ) + parser.add_argument( + "--no-default-ignore", + action="store_false", + dest="use_default_ignore_patterns", + help=( + "Don't ignore the common private glob-style patterns (defaults to " + "'CVS', '.*' and '*~')." + ), + ) + + def set_options(self, **options): + """ + Set instance variables based on an options dict + """ + self.interactive = options["interactive"] + self.verbosity = options["verbosity"] + self.symlink = options["link"] + self.clear = options["clear"] + self.dry_run = options["dry_run"] + ignore_patterns = options["ignore_patterns"] + if options["use_default_ignore_patterns"]: + ignore_patterns += apps.get_app_config("staticfiles").ignore_patterns + self.ignore_patterns = list({os.path.normpath(p) for p in ignore_patterns}) + self.post_process = options["post_process"] + + def collect(self): + """ + Perform the bulk of the work of collectstatic. + + Split off from handle() to facilitate testing. + """ + if self.symlink and not self.local: + raise CommandError("Can't symlink to a remote destination.") + + if self.clear: + self.clear_dir("") + + if self.symlink: + handler = self.link_file + else: + handler = self.copy_file + + found_files = {} + for finder in get_finders(): + for path, storage in finder.list(self.ignore_patterns): + # Prefix the relative path if the source storage contains it + if getattr(storage, "prefix", None): + prefixed_path = os.path.join(storage.prefix, path) + else: + prefixed_path = path + + if prefixed_path not in found_files: + found_files[prefixed_path] = (storage, path) + handler(path, prefixed_path, storage) + else: + self.log( + "Found another file with the destination path '%s'. It " + "will be ignored since only the first encountered file " + "is collected. If this is not what you want, make sure " + "every static file has a unique path." % prefixed_path, + level=1, + ) + + # Storage backends may define a post_process() method. + if self.post_process and hasattr(self.storage, "post_process"): + processor = self.storage.post_process(found_files, dry_run=self.dry_run) + for original_path, processed_path, processed in processor: + if isinstance(processed, Exception): + self.stderr.write("Post-processing '%s' failed!" % original_path) + # Add a blank line before the traceback, otherwise it's + # too easy to miss the relevant part of the error message. + self.stderr.write() + raise processed + if processed: + self.log( + "Post-processed '%s' as '%s'" % (original_path, processed_path), + level=2, + ) + self.post_processed_files.append(original_path) + else: + self.log("Skipped post-processing '%s'" % original_path) + + return { + "modified": self.copied_files + self.symlinked_files, + "unmodified": self.unmodified_files, + "post_processed": self.post_processed_files, + } + + def handle(self, **options): + self.set_options(**options) + message = ["\n"] + if self.dry_run: + message.append( + "You have activated the --dry-run option so no files will be " + "modified.\n\n" + ) + + message.append( + "You have requested to collect static files at the destination\n" + "location as specified in your settings" + ) + + if self.is_local_storage() and self.storage.location: + destination_path = self.storage.location + message.append(":\n\n %s\n\n" % destination_path) + should_warn_user = self.storage.exists(destination_path) and any( + self.storage.listdir(destination_path) + ) + else: + destination_path = None + message.append(".\n\n") + # Destination files existence not checked; play it safe and warn. + should_warn_user = True + + if self.interactive and should_warn_user: + if self.clear: + message.append("This will DELETE ALL FILES in this location!\n") + else: + message.append("This will overwrite existing files!\n") + + message.append( + "Are you sure you want to do this?\n\n" + "Type 'yes' to continue, or 'no' to cancel: " + ) + if input("".join(message)) != "yes": + raise CommandError("Collecting static files cancelled.") + + collected = self.collect() + + if self.verbosity >= 1: + modified_count = len(collected["modified"]) + unmodified_count = len(collected["unmodified"]) + post_processed_count = len(collected["post_processed"]) + return ( + "\n%(modified_count)s %(identifier)s %(action)s" + "%(destination)s%(unmodified)s%(post_processed)s." + ) % { + "modified_count": modified_count, + "identifier": "static file" + ("" if modified_count == 1 else "s"), + "action": "symlinked" if self.symlink else "copied", + "destination": ( + " to '%s'" % destination_path if destination_path else "" + ), + "unmodified": ( + ", %s unmodified" % unmodified_count + if collected["unmodified"] + else "" + ), + "post_processed": ( + collected["post_processed"] + and ", %s post-processed" % post_processed_count + or "" + ), + } + + def log(self, msg, level=2): + """ + Small log helper + """ + if self.verbosity >= level: + self.stdout.write(msg) + + def is_local_storage(self): + return isinstance(self.storage, FileSystemStorage) + + def clear_dir(self, path): + """ + Delete the given relative path using the destination storage backend. + """ + if not self.storage.exists(path): + return + + dirs, files = self.storage.listdir(path) + for f in files: + fpath = os.path.join(path, f) + if self.dry_run: + self.log("Pretending to delete '%s'" % fpath, level=1) + else: + self.log("Deleting '%s'" % fpath, level=1) + try: + full_path = self.storage.path(fpath) + except NotImplementedError: + self.storage.delete(fpath) + else: + if not os.path.exists(full_path) and os.path.lexists(full_path): + # Delete broken symlinks + os.unlink(full_path) + else: + self.storage.delete(fpath) + for d in dirs: + self.clear_dir(os.path.join(path, d)) + + def delete_file(self, path, prefixed_path, source_storage): + """ + Check if the target file should be deleted if it already exists. + """ + if self.storage.exists(prefixed_path): + try: + # When was the target file modified last time? + target_last_modified = self.storage.get_modified_time(prefixed_path) + except (OSError, NotImplementedError, AttributeError): + # The storage doesn't support get_modified_time() or failed + pass + else: + try: + # When was the source file modified last time? + source_last_modified = source_storage.get_modified_time(path) + except (OSError, NotImplementedError, AttributeError): + pass + else: + # The full path of the target file + if self.local: + full_path = self.storage.path(prefixed_path) + # If it's --link mode and the path isn't a link (i.e. + # the previous collectstatic wasn't with --link) or if + # it's non-link mode and the path is a link (i.e. the + # previous collectstatic was with --link), the old + # links/files must be deleted so it's not safe to skip + # unmodified files. + can_skip_unmodified_files = not ( + self.symlink ^ os.path.islink(full_path) + ) + else: + # In remote storages, skipping is only based on the + # modified times since symlinks aren't relevant. + can_skip_unmodified_files = True + # Avoid sub-second precision (see #14665, #19540) + file_is_unmodified = target_last_modified.replace( + microsecond=0 + ) >= source_last_modified.replace(microsecond=0) + if file_is_unmodified and can_skip_unmodified_files: + if prefixed_path not in self.unmodified_files: + self.unmodified_files.append(prefixed_path) + self.log("Skipping '%s' (not modified)" % path) + return False + # Then delete the existing file if really needed + if self.dry_run: + self.log("Pretending to delete '%s'" % path) + else: + self.log("Deleting '%s'" % path) + self.storage.delete(prefixed_path) + return True + + def link_file(self, path, prefixed_path, source_storage): + """ + Attempt to link ``path`` + """ + # Skip this file if it was already copied earlier + if prefixed_path in self.symlinked_files: + return self.log("Skipping '%s' (already linked earlier)" % path) + # Delete the target file if needed or break + if not self.delete_file(path, prefixed_path, source_storage): + return + # The full path of the source file + source_path = source_storage.path(path) + # Finally link the file + if self.dry_run: + self.log("Pretending to link '%s'" % source_path, level=1) + else: + self.log("Linking '%s'" % source_path, level=2) + full_path = self.storage.path(prefixed_path) + os.makedirs(os.path.dirname(full_path), exist_ok=True) + try: + if os.path.lexists(full_path): + os.unlink(full_path) + os.symlink(source_path, full_path) + except NotImplementedError: + import platform + + raise CommandError( + "Symlinking is not supported in this " + "platform (%s)." % platform.platform() + ) + except OSError as e: + raise CommandError(e) + if prefixed_path not in self.symlinked_files: + self.symlinked_files.append(prefixed_path) + + def copy_file(self, path, prefixed_path, source_storage): + """ + Attempt to copy ``path`` with storage + """ + # Skip this file if it was already copied earlier + if prefixed_path in self.copied_files: + return self.log("Skipping '%s' (already copied earlier)" % path) + # Delete the target file if needed or break + if not self.delete_file(path, prefixed_path, source_storage): + return + # The full path of the source file + source_path = source_storage.path(path) + # Finally start copying + if self.dry_run: + self.log("Pretending to copy '%s'" % source_path, level=1) + else: + self.log("Copying '%s'" % source_path, level=2) + with source_storage.open(path) as source_file: + self.storage.save(prefixed_path, source_file) + self.copied_files.append(prefixed_path) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/management/commands/findstatic.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/management/commands/findstatic.py new file mode 100644 index 0000000..97413a6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/management/commands/findstatic.py @@ -0,0 +1,48 @@ +import os + +from django.contrib.staticfiles import finders +from django.core.management.base import LabelCommand + + +class Command(LabelCommand): + help = "Finds the absolute paths for the given static file(s)." + label = "staticfile" + + def add_arguments(self, parser): + super().add_arguments(parser) + parser.add_argument( + "--first", + action="store_false", + dest="all", + help="Only return the first match for each static file.", + ) + + def handle_label(self, path, **options): + verbosity = options["verbosity"] + result = finders.find(path, all=options["all"]) + if verbosity >= 2: + searched_locations = ( + "\nLooking in the following locations:\n %s" + % "\n ".join([str(loc) for loc in finders.searched_locations]) + ) + else: + searched_locations = "" + if result: + if not isinstance(result, (list, tuple)): + result = [result] + result = (os.path.realpath(path) for path in result) + if verbosity >= 1: + file_list = "\n ".join(result) + return "Found '%s' here:\n %s%s" % ( + path, + file_list, + searched_locations, + ) + else: + return "\n".join(result) + else: + message = ["No matching file found for '%s'." % path] + if verbosity >= 2: + message.append(searched_locations) + if verbosity >= 1: + self.stderr.write("\n".join(message)) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/management/commands/runserver.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/management/commands/runserver.py new file mode 100644 index 0000000..fd9ddb1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/management/commands/runserver.py @@ -0,0 +1,36 @@ +from django.conf import settings +from django.contrib.staticfiles.handlers import StaticFilesHandler +from django.core.management.commands.runserver import Command as RunserverCommand + + +class Command(RunserverCommand): + help = ( + "Starts a lightweight web server for development and also serves static files." + ) + + def add_arguments(self, parser): + super().add_arguments(parser) + parser.add_argument( + "--nostatic", + action="store_false", + dest="use_static_handler", + help="Tells Django to NOT automatically serve static files at STATIC_URL.", + ) + parser.add_argument( + "--insecure", + action="store_true", + dest="insecure_serving", + help="Allows serving static files even if DEBUG is False.", + ) + + def get_handler(self, *args, **options): + """ + Return the static files serving handler wrapping the default handler, + if static files should be served. Otherwise return the default handler. + """ + handler = super().get_handler(*args, **options) + use_static_handler = options["use_static_handler"] + insecure_serving = options["insecure_serving"] + if use_static_handler and (settings.DEBUG or insecure_serving): + return StaticFilesHandler(handler) + return handler diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/storage.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/storage.py new file mode 100644 index 0000000..85172ea --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/storage.py @@ -0,0 +1,543 @@ +import json +import os +import posixpath +import re +from hashlib import md5 +from urllib.parse import unquote, urldefrag, urlsplit, urlunsplit + +from django.conf import STATICFILES_STORAGE_ALIAS, settings +from django.contrib.staticfiles.utils import check_settings, matches_patterns +from django.core.exceptions import ImproperlyConfigured +from django.core.files.base import ContentFile +from django.core.files.storage import FileSystemStorage, storages +from django.utils.functional import LazyObject + + +class StaticFilesStorage(FileSystemStorage): + """ + Standard file system storage for static files. + + The defaults for ``location`` and ``base_url`` are + ``STATIC_ROOT`` and ``STATIC_URL``. + """ + + def __init__(self, location=None, base_url=None, *args, **kwargs): + if location is None: + location = settings.STATIC_ROOT + if base_url is None: + base_url = settings.STATIC_URL + check_settings(base_url) + super().__init__(location, base_url, *args, **kwargs) + # FileSystemStorage fallbacks to MEDIA_ROOT when location + # is empty, so we restore the empty value. + if not location: + self.base_location = None + self.location = None + + def path(self, name): + if not self.location: + raise ImproperlyConfigured( + "You're using the staticfiles app " + "without having set the STATIC_ROOT " + "setting to a filesystem path." + ) + return super().path(name) + + +class HashedFilesMixin: + default_template = """url("%(url)s")""" + max_post_process_passes = 5 + support_js_module_import_aggregation = False + _js_module_import_aggregation_patterns = ( + "*.js", + ( + ( + ( + r"""(?Pimport(?s:(?P[\s\{].*?))""" + r"""\s*from\s*['"](?P[./].*?)["']\s*;)""" + ), + """import%(import)s from "%(url)s";""", + ), + ( + ( + r"""(?Pexport(?s:(?P[\s\{].*?))""" + r"""\s*from\s*["'](?P[./].*?)["']\s*;)""" + ), + """export%(exports)s from "%(url)s";""", + ), + ( + r"""(?Pimport\s*['"](?P[./].*?)["']\s*;)""", + """import"%(url)s";""", + ), + ( + r"""(?Pimport\(["'](?P.*?)["']\))""", + """import("%(url)s")""", + ), + ), + ) + patterns = ( + ( + "*.css", + ( + r"""(?Purl\(['"]{0,1}\s*(?P.*?)["']{0,1}\))""", + ( + r"""(?P@import\s*["']\s*(?P.*?)["'])""", + """@import url("%(url)s")""", + ), + ( + ( + r"(?m)^(?P/\*#[ \t]" + r"(?-i:sourceMappingURL)=(?P.*)[ \t]*\*/)$" + ), + "/*# sourceMappingURL=%(url)s */", + ), + ), + ), + ( + "*.js", + ( + ( + r"(?m)^(?P//# (?-i:sourceMappingURL)=(?P.*))$", + "//# sourceMappingURL=%(url)s", + ), + ), + ), + ) + keep_intermediate_files = True + + def __init__(self, *args, **kwargs): + if self.support_js_module_import_aggregation: + self.patterns += (self._js_module_import_aggregation_patterns,) + super().__init__(*args, **kwargs) + self._patterns = {} + self.hashed_files = {} + for extension, patterns in self.patterns: + for pattern in patterns: + if isinstance(pattern, (tuple, list)): + pattern, template = pattern + else: + template = self.default_template + compiled = re.compile(pattern, re.IGNORECASE) + self._patterns.setdefault(extension, []).append((compiled, template)) + + def file_hash(self, name, content=None): + """ + Return a hash of the file with the given name and optional content. + """ + if content is None: + return None + hasher = md5(usedforsecurity=False) + for chunk in content.chunks(): + hasher.update(chunk) + return hasher.hexdigest()[:12] + + def hashed_name(self, name, content=None, filename=None): + # `filename` is the name of file to hash if `content` isn't given. + # `name` is the base name to construct the new hashed filename from. + parsed_name = urlsplit(unquote(name)) + clean_name = parsed_name.path.strip() + filename = (filename and urlsplit(unquote(filename)).path.strip()) or clean_name + opened = content is None + if opened: + if not self.exists(filename): + raise ValueError( + "The file '%s' could not be found with %r." % (filename, self) + ) + try: + content = self.open(filename) + except OSError: + # Handle directory paths and fragments + return name + try: + file_hash = self.file_hash(clean_name, content) + finally: + if opened: + content.close() + path, filename = os.path.split(clean_name) + root, ext = os.path.splitext(filename) + file_hash = (".%s" % file_hash) if file_hash else "" + hashed_name = os.path.join(path, "%s%s%s" % (root, file_hash, ext)) + unparsed_name = list(parsed_name) + unparsed_name[2] = hashed_name + # Special casing for a @font-face hack, like url(myfont.eot?#iefix") + # http://www.fontspring.com/blog/the-new-bulletproof-font-face-syntax + if "?#" in name and not unparsed_name[3]: + unparsed_name[2] += "?" + return urlunsplit(unparsed_name) + + def _url(self, hashed_name_func, name, force=False, hashed_files=None): + """ + Return the non-hashed URL in DEBUG mode. + """ + if settings.DEBUG and not force: + hashed_name, fragment = name, "" + else: + clean_name, fragment = urldefrag(name) + if urlsplit(clean_name).path.endswith("/"): # don't hash paths + hashed_name = name + else: + args = (clean_name,) + if hashed_files is not None: + args += (hashed_files,) + hashed_name = hashed_name_func(*args) + + final_url = super().url(hashed_name) + + # Special casing for a @font-face hack, like url(myfont.eot?#iefix") + # http://www.fontspring.com/blog/the-new-bulletproof-font-face-syntax + query_fragment = "?#" in name # [sic!] + if fragment or query_fragment: + urlparts = list(urlsplit(final_url)) + if fragment and not urlparts[4]: + urlparts[4] = fragment + if query_fragment and not urlparts[3]: + urlparts[2] += "?" + final_url = urlunsplit(urlparts) + + return unquote(final_url) + + def url(self, name, force=False): + """ + Return the non-hashed URL in DEBUG mode. + """ + return self._url(self.stored_name, name, force) + + def url_converter(self, name, hashed_files, template=None): + """ + Return the custom URL converter for the given file name. + """ + if template is None: + template = self.default_template + + def converter(matchobj): + """ + Convert the matched URL to a normalized and hashed URL. + + This requires figuring out which files the matched URL resolves + to and calling the url() method of the storage. + """ + matches = matchobj.groupdict() + matched = matches["matched"] + url = matches["url"] + + # Ignore absolute/protocol-relative and data-uri URLs. + if re.match(r"^[a-z]+:", url): + return matched + + # Ignore absolute URLs that don't point to a static file (dynamic + # CSS / JS?). Note that STATIC_URL cannot be empty. + if url.startswith("/") and not url.startswith(settings.STATIC_URL): + return matched + + # Strip off the fragment so a path-like fragment won't interfere. + url_path, fragment = urldefrag(url) + + # Ignore URLs without a path + if not url_path: + return matched + + if url_path.startswith("/"): + # Otherwise the condition above would have returned prematurely. + assert url_path.startswith(settings.STATIC_URL) + target_name = url_path.removeprefix(settings.STATIC_URL) + else: + # We're using the posixpath module to mix paths and URLs conveniently. + source_name = name if os.sep == "/" else name.replace(os.sep, "/") + target_name = posixpath.join(posixpath.dirname(source_name), url_path) + + # Determine the hashed name of the target file with the storage backend. + hashed_url = self._url( + self._stored_name, + unquote(target_name), + force=True, + hashed_files=hashed_files, + ) + + transformed_url = "/".join( + url_path.split("/")[:-1] + hashed_url.split("/")[-1:] + ) + + # Restore the fragment that was stripped off earlier. + if fragment: + transformed_url += ("?#" if "?#" in url else "#") + fragment + + # Return the hashed version to the file + matches["url"] = unquote(transformed_url) + return template % matches + + return converter + + def post_process(self, paths, dry_run=False, **options): + """ + Post process the given dictionary of files (called from collectstatic). + + Processing is actually two separate operations: + + 1. renaming files to include a hash of their content for cache-busting, + and copying those files to the target storage. + 2. adjusting files which contain references to other files so they + refer to the cache-busting filenames. + + If either of these are performed on a file, then that file is considered + post-processed. + """ + # don't even dare to process the files if we're in dry run mode + if dry_run: + return + + # where to store the new paths + hashed_files = {} + + # build a list of adjustable files + adjustable_paths = [ + path for path in paths if matches_patterns(path, self._patterns) + ] + + # Adjustable files to yield at end, keyed by the original path. + processed_adjustable_paths = {} + + # Do a single pass first. Post-process all files once, yielding not + # adjustable files and exceptions, and collecting adjustable files. + for name, hashed_name, processed, _ in self._post_process( + paths, adjustable_paths, hashed_files + ): + if name not in adjustable_paths or isinstance(processed, Exception): + yield name, hashed_name, processed + else: + processed_adjustable_paths[name] = (name, hashed_name, processed) + + paths = {path: paths[path] for path in adjustable_paths} + substitutions = False + + for i in range(self.max_post_process_passes): + substitutions = False + for name, hashed_name, processed, subst in self._post_process( + paths, adjustable_paths, hashed_files + ): + # Overwrite since hashed_name may be newer. + processed_adjustable_paths[name] = (name, hashed_name, processed) + substitutions = substitutions or subst + + if not substitutions: + break + + if substitutions: + yield "All", None, RuntimeError("Max post-process passes exceeded.") + + # Store the processed paths + self.hashed_files.update(hashed_files) + + # Yield adjustable files with final, hashed name. + yield from processed_adjustable_paths.values() + + def _post_process(self, paths, adjustable_paths, hashed_files): + # Sort the files by directory level + def path_level(name): + return len(name.split(os.sep)) + + for name in sorted(paths, key=path_level, reverse=True): + substitutions = True + # use the original, local file, not the copied-but-unprocessed + # file, which might be somewhere far away, like S3 + storage, path = paths[name] + with storage.open(path) as original_file: + cleaned_name = self.clean_name(name) + hash_key = self.hash_key(cleaned_name) + + # generate the hash with the original content, even for + # adjustable files. + if hash_key not in hashed_files: + hashed_name = self.hashed_name(name, original_file) + else: + hashed_name = hashed_files[hash_key] + + # then get the original's file content.. + if hasattr(original_file, "seek"): + original_file.seek(0) + + hashed_file_exists = self.exists(hashed_name) + processed = False + + # ..to apply each replacement pattern to the content + if name in adjustable_paths: + old_hashed_name = hashed_name + try: + content = original_file.read().decode("utf-8") + except UnicodeDecodeError as exc: + yield name, None, exc, False + for extension, patterns in self._patterns.items(): + if matches_patterns(path, (extension,)): + for pattern, template in patterns: + converter = self.url_converter( + name, hashed_files, template + ) + try: + content = pattern.sub(converter, content) + except ValueError as exc: + yield name, None, exc, False + if hashed_file_exists: + self.delete(hashed_name) + # then save the processed result + content_file = ContentFile(content.encode()) + if self.keep_intermediate_files: + # Save intermediate file for reference + self._save(hashed_name, content_file) + hashed_name = self.hashed_name(name, content_file) + + if self.exists(hashed_name): + self.delete(hashed_name) + + saved_name = self._save(hashed_name, content_file) + hashed_name = self.clean_name(saved_name) + # If the file hash stayed the same, this file didn't change + if old_hashed_name == hashed_name: + substitutions = False + processed = True + + if not processed: + # or handle the case in which neither processing nor + # a change to the original file happened + if not hashed_file_exists: + processed = True + saved_name = self._save(hashed_name, original_file) + hashed_name = self.clean_name(saved_name) + + # and then set the cache accordingly + hashed_files[hash_key] = hashed_name + + yield name, hashed_name, processed, substitutions + + def clean_name(self, name): + return name.replace("\\", "/") + + def hash_key(self, name): + return name + + def _stored_name(self, name, hashed_files): + # Normalize the path to avoid multiple names for the same file like + # ../foo/bar.css and ../foo/../foo/bar.css which normalize to the same + # path. + name = posixpath.normpath(name) + cleaned_name = self.clean_name(name) + hash_key = self.hash_key(cleaned_name) + cache_name = hashed_files.get(hash_key) + if cache_name is None: + cache_name = self.clean_name(self.hashed_name(name)) + return cache_name + + def stored_name(self, name): + cleaned_name = self.clean_name(name) + hash_key = self.hash_key(cleaned_name) + cache_name = self.hashed_files.get(hash_key) + if cache_name: + return cache_name + # No cached name found, recalculate it from the files. + intermediate_name = name + for i in range(self.max_post_process_passes + 1): + cache_name = self.clean_name( + self.hashed_name(name, content=None, filename=intermediate_name) + ) + if intermediate_name == cache_name: + # Store the hashed name if there was a miss. + self.hashed_files[hash_key] = cache_name + return cache_name + else: + # Move on to the next intermediate file. + intermediate_name = cache_name + # If the cache name can't be determined after the max number of passes, + # the intermediate files on disk may be corrupt; avoid an infinite loop. + raise ValueError("The name '%s' could not be hashed with %r." % (name, self)) + + +class ManifestFilesMixin(HashedFilesMixin): + manifest_version = "1.1" # the manifest format standard + manifest_name = "staticfiles.json" + manifest_strict = True + keep_intermediate_files = False + + def __init__(self, *args, manifest_storage=None, **kwargs): + super().__init__(*args, **kwargs) + if manifest_storage is None: + manifest_storage = self + self.manifest_storage = manifest_storage + self.hashed_files, self.manifest_hash = self.load_manifest() + + def read_manifest(self): + try: + with self.manifest_storage.open(self.manifest_name) as manifest: + return manifest.read().decode() + except FileNotFoundError: + return None + + def load_manifest(self): + content = self.read_manifest() + if content is None: + return {}, "" + try: + stored = json.loads(content) + except json.JSONDecodeError: + pass + else: + version = stored.get("version") + if version in ("1.0", "1.1"): + return stored.get("paths", {}), stored.get("hash", "") + raise ValueError( + "Couldn't load manifest '%s' (version %s)" + % (self.manifest_name, self.manifest_version) + ) + + def post_process(self, *args, **kwargs): + self.hashed_files = {} + yield from super().post_process(*args, **kwargs) + if not kwargs.get("dry_run"): + self.save_manifest() + + def save_manifest(self): + self.manifest_hash = self.file_hash( + None, ContentFile(json.dumps(sorted(self.hashed_files.items())).encode()) + ) + payload = { + "paths": self.hashed_files, + "version": self.manifest_version, + "hash": self.manifest_hash, + } + if self.manifest_storage.exists(self.manifest_name): + self.manifest_storage.delete(self.manifest_name) + contents = json.dumps(payload).encode() + self.manifest_storage._save(self.manifest_name, ContentFile(contents)) + + def stored_name(self, name): + parsed_name = urlsplit(unquote(name)) + clean_name = parsed_name.path.strip() + hash_key = self.hash_key(clean_name) + cache_name = self.hashed_files.get(hash_key) + if cache_name is None: + if self.manifest_strict: + raise ValueError( + "Missing staticfiles manifest entry for '%s'" % clean_name + ) + cache_name = self.clean_name(self.hashed_name(name)) + unparsed_name = list(parsed_name) + unparsed_name[2] = cache_name + # Special casing for a @font-face hack, like url(myfont.eot?#iefix") + # http://www.fontspring.com/blog/the-new-bulletproof-font-face-syntax + if "?#" in name and not unparsed_name[3]: + unparsed_name[2] += "?" + return urlunsplit(unparsed_name) + + +class ManifestStaticFilesStorage(ManifestFilesMixin, StaticFilesStorage): + """ + A static file system storage backend which also saves + hashed copies of the files it saves. + """ + + pass + + +class ConfiguredStorage(LazyObject): + def _setup(self): + self._wrapped = storages[STATICFILES_STORAGE_ALIAS] + + +staticfiles_storage = ConfiguredStorage() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/testing.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/testing.py new file mode 100644 index 0000000..546a24a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/testing.py @@ -0,0 +1,13 @@ +from django.contrib.staticfiles.handlers import StaticFilesHandler +from django.test import LiveServerTestCase + + +class StaticLiveServerTestCase(LiveServerTestCase): + """ + Extend django.test.LiveServerTestCase to transparently overlay at test + execution-time the assets provided by the staticfiles app finders. This + means you don't need to run collectstatic before or as a part of your tests + setup. + """ + + static_handler = StaticFilesHandler diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/urls.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/urls.py new file mode 100644 index 0000000..6278f35 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/urls.py @@ -0,0 +1,19 @@ +from django.conf import settings +from django.conf.urls.static import static +from django.contrib.staticfiles.views import serve + +urlpatterns = [] + + +def staticfiles_urlpatterns(prefix=None): + """ + Helper function to return a URL pattern for serving static files. + """ + if prefix is None: + prefix = settings.STATIC_URL + return static(prefix, view=serve) + + +# Only append if urlpatterns are empty +if settings.DEBUG and not urlpatterns: + urlpatterns += staticfiles_urlpatterns() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/utils.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/utils.py new file mode 100644 index 0000000..efd67ac --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/utils.py @@ -0,0 +1,71 @@ +import fnmatch +import os + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured + + +def matches_patterns(path, patterns): + """ + Return True or False depending on whether the ``path`` should be + ignored (if it matches any pattern in ``ignore_patterns``). + """ + return any(fnmatch.fnmatchcase(path, pattern) for pattern in patterns) + + +def get_files(storage, ignore_patterns=None, location=""): + """ + Recursively walk the storage directories yielding the paths + of all files that should be copied. + """ + if ignore_patterns is None: + ignore_patterns = [] + directories, files = storage.listdir(location) + for fn in files: + # Match only the basename. + if matches_patterns(fn, ignore_patterns): + continue + if location: + fn = os.path.join(location, fn) + # Match the full file path. + if matches_patterns(fn, ignore_patterns): + continue + yield fn + for dir in directories: + if matches_patterns(dir, ignore_patterns): + continue + if location: + dir = os.path.join(location, dir) + yield from get_files(storage, ignore_patterns, dir) + + +def check_settings(base_url=None): + """ + Check if the staticfiles settings have sane values. + """ + if base_url is None: + base_url = settings.STATIC_URL + if not base_url: + raise ImproperlyConfigured( + "You're using the staticfiles app " + "without having set the required STATIC_URL setting." + ) + if settings.MEDIA_URL == base_url: + raise ImproperlyConfigured( + "The MEDIA_URL and STATIC_URL settings must have different values" + ) + if ( + settings.DEBUG + and settings.MEDIA_URL + and settings.STATIC_URL + and settings.MEDIA_URL.startswith(settings.STATIC_URL) + ): + raise ImproperlyConfigured( + "runserver can't serve media if MEDIA_URL is within STATIC_URL." + ) + if (settings.MEDIA_ROOT and settings.STATIC_ROOT) and ( + settings.MEDIA_ROOT == settings.STATIC_ROOT + ): + raise ImproperlyConfigured( + "The MEDIA_ROOT and STATIC_ROOT settings must have different values" + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/views.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/views.py new file mode 100644 index 0000000..83d04d4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/staticfiles/views.py @@ -0,0 +1,39 @@ +""" +Views and functions for serving static files. These are only to be used during +development, and SHOULD NOT be used in a production setting. + +""" +import os +import posixpath + +from django.conf import settings +from django.contrib.staticfiles import finders +from django.http import Http404 +from django.views import static + + +def serve(request, path, insecure=False, **kwargs): + """ + Serve static files below a given point in the directory structure or + from locations inferred from the staticfiles finders. + + To use, put a URL pattern such as:: + + from django.contrib.staticfiles import views + + path('', views.serve) + + in your URLconf. + + It uses the django.views.static.serve() view to serve the found files. + """ + if not settings.DEBUG and not insecure: + raise Http404 + normalized_path = posixpath.normpath(path).lstrip("/") + absolute_path = finders.find(normalized_path) + if not absolute_path: + if path.endswith("/") or path == "": + raise Http404("Directory indexes are not allowed here.") + raise Http404("'%s' could not be found" % path) + document_root, path = os.path.split(absolute_path) + return static.serve(request, path, document_root=document_root, **kwargs) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/syndication/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/syndication/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/syndication/apps.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/syndication/apps.py new file mode 100644 index 0000000..bb0f86a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/syndication/apps.py @@ -0,0 +1,7 @@ +from django.apps import AppConfig +from django.utils.translation import gettext_lazy as _ + + +class SyndicationConfig(AppConfig): + name = "django.contrib.syndication" + verbose_name = _("Syndication") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/syndication/views.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/syndication/views.py new file mode 100644 index 0000000..2378a14 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/contrib/syndication/views.py @@ -0,0 +1,234 @@ +from inspect import getattr_static, unwrap + +from django.contrib.sites.shortcuts import get_current_site +from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist +from django.http import Http404, HttpResponse +from django.template import TemplateDoesNotExist, loader +from django.utils import feedgenerator +from django.utils.encoding import iri_to_uri +from django.utils.html import escape +from django.utils.http import http_date +from django.utils.timezone import get_default_timezone, is_naive, make_aware +from django.utils.translation import get_language + + +def add_domain(domain, url, secure=False): + protocol = "https" if secure else "http" + if url.startswith("//"): + # Support network-path reference (see #16753) - RSS requires a protocol + url = "%s:%s" % (protocol, url) + elif not url.startswith(("http://", "https://", "mailto:")): + url = iri_to_uri("%s://%s%s" % (protocol, domain, url)) + return url + + +class FeedDoesNotExist(ObjectDoesNotExist): + pass + + +class Feed: + feed_type = feedgenerator.DefaultFeed + title_template = None + description_template = None + language = None + + def __call__(self, request, *args, **kwargs): + try: + obj = self.get_object(request, *args, **kwargs) + except ObjectDoesNotExist: + raise Http404("Feed object does not exist.") + feedgen = self.get_feed(obj, request) + response = HttpResponse(content_type=feedgen.content_type) + if hasattr(self, "item_pubdate") or hasattr(self, "item_updateddate"): + # if item_pubdate or item_updateddate is defined for the feed, set + # header so as ConditionalGetMiddleware is able to send 304 NOT MODIFIED + response.headers["Last-Modified"] = http_date( + feedgen.latest_post_date().timestamp() + ) + feedgen.write(response, "utf-8") + return response + + def item_title(self, item): + # Titles should be double escaped by default (see #6533) + return escape(str(item)) + + def item_description(self, item): + return str(item) + + def item_link(self, item): + try: + return item.get_absolute_url() + except AttributeError: + raise ImproperlyConfigured( + "Give your %s class a get_absolute_url() method, or define an " + "item_link() method in your Feed class." % item.__class__.__name__ + ) + + def item_enclosures(self, item): + enc_url = self._get_dynamic_attr("item_enclosure_url", item) + if enc_url: + enc = feedgenerator.Enclosure( + url=str(enc_url), + length=str(self._get_dynamic_attr("item_enclosure_length", item)), + mime_type=str(self._get_dynamic_attr("item_enclosure_mime_type", item)), + ) + return [enc] + return [] + + def _get_dynamic_attr(self, attname, obj, default=None): + try: + attr = getattr(self, attname) + except AttributeError: + return default + if callable(attr): + # Check co_argcount rather than try/excepting the function and + # catching the TypeError, because something inside the function + # may raise the TypeError. This technique is more accurate. + func = unwrap(attr) + try: + code = func.__code__ + except AttributeError: + func = unwrap(attr.__call__) + code = func.__code__ + # If function doesn't have arguments and it is not a static method, + # it was decorated without using @functools.wraps. + if not code.co_argcount and not isinstance( + getattr_static(self, func.__name__, None), staticmethod + ): + raise ImproperlyConfigured( + f"Feed method {attname!r} decorated by {func.__name__!r} needs to " + f"use @functools.wraps." + ) + if code.co_argcount == 2: # one argument is 'self' + return attr(obj) + else: + return attr() + return attr + + def feed_extra_kwargs(self, obj): + """ + Return an extra keyword arguments dictionary that is used when + initializing the feed generator. + """ + return {} + + def item_extra_kwargs(self, item): + """ + Return an extra keyword arguments dictionary that is used with + the `add_item` call of the feed generator. + """ + return {} + + def get_object(self, request, *args, **kwargs): + return None + + def get_context_data(self, **kwargs): + """ + Return a dictionary to use as extra context if either + ``self.description_template`` or ``self.item_template`` are used. + + Default implementation preserves the old behavior + of using {'obj': item, 'site': current_site} as the context. + """ + return {"obj": kwargs.get("item"), "site": kwargs.get("site")} + + def get_feed(self, obj, request): + """ + Return a feedgenerator.DefaultFeed object, fully populated, for + this feed. Raise FeedDoesNotExist for invalid parameters. + """ + current_site = get_current_site(request) + + link = self._get_dynamic_attr("link", obj) + link = add_domain(current_site.domain, link, request.is_secure()) + + feed = self.feed_type( + title=self._get_dynamic_attr("title", obj), + subtitle=self._get_dynamic_attr("subtitle", obj), + link=link, + description=self._get_dynamic_attr("description", obj), + language=self.language or get_language(), + feed_url=add_domain( + current_site.domain, + self._get_dynamic_attr("feed_url", obj) or request.path, + request.is_secure(), + ), + author_name=self._get_dynamic_attr("author_name", obj), + author_link=self._get_dynamic_attr("author_link", obj), + author_email=self._get_dynamic_attr("author_email", obj), + categories=self._get_dynamic_attr("categories", obj), + feed_copyright=self._get_dynamic_attr("feed_copyright", obj), + feed_guid=self._get_dynamic_attr("feed_guid", obj), + ttl=self._get_dynamic_attr("ttl", obj), + **self.feed_extra_kwargs(obj), + ) + + title_tmp = None + if self.title_template is not None: + try: + title_tmp = loader.get_template(self.title_template) + except TemplateDoesNotExist: + pass + + description_tmp = None + if self.description_template is not None: + try: + description_tmp = loader.get_template(self.description_template) + except TemplateDoesNotExist: + pass + + for item in self._get_dynamic_attr("items", obj): + context = self.get_context_data( + item=item, site=current_site, obj=obj, request=request + ) + if title_tmp is not None: + title = title_tmp.render(context, request) + else: + title = self._get_dynamic_attr("item_title", item) + if description_tmp is not None: + description = description_tmp.render(context, request) + else: + description = self._get_dynamic_attr("item_description", item) + link = add_domain( + current_site.domain, + self._get_dynamic_attr("item_link", item), + request.is_secure(), + ) + enclosures = self._get_dynamic_attr("item_enclosures", item) + author_name = self._get_dynamic_attr("item_author_name", item) + if author_name is not None: + author_email = self._get_dynamic_attr("item_author_email", item) + author_link = self._get_dynamic_attr("item_author_link", item) + else: + author_email = author_link = None + + tz = get_default_timezone() + + pubdate = self._get_dynamic_attr("item_pubdate", item) + if pubdate and is_naive(pubdate): + pubdate = make_aware(pubdate, tz) + + updateddate = self._get_dynamic_attr("item_updateddate", item) + if updateddate and is_naive(updateddate): + updateddate = make_aware(updateddate, tz) + + feed.add_item( + title=title, + link=link, + description=description, + unique_id=self._get_dynamic_attr("item_guid", item, link), + unique_id_is_permalink=self._get_dynamic_attr( + "item_guid_is_permalink", item + ), + enclosures=enclosures, + pubdate=pubdate, + updateddate=updateddate, + author_name=author_name, + author_email=author_email, + author_link=author_link, + comments=self._get_dynamic_attr("item_comments", item), + categories=self._get_dynamic_attr("item_categories", item), + item_copyright=self._get_dynamic_attr("item_copyright", item), + **self.item_extra_kwargs(item), + ) + return feed diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/asgi.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/asgi.py new file mode 100644 index 0000000..0d846cc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/asgi.py @@ -0,0 +1,13 @@ +import django +from django.core.handlers.asgi import ASGIHandler + + +def get_asgi_application(): + """ + The public interface to Django's ASGI support. Return an ASGI 3 callable. + + Avoids making django.core.handlers.ASGIHandler a public API, in case the + internal implementation changes or moves in the future. + """ + django.setup(set_prefix=False) + return ASGIHandler() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/__init__.py new file mode 100644 index 0000000..eb7fa5b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/__init__.py @@ -0,0 +1,66 @@ +""" +Caching framework. + +This package defines set of cache backends that all conform to a simple API. +In a nutshell, a cache is a set of values -- which can be any object that +may be pickled -- identified by string keys. For the complete API, see +the abstract BaseCache class in django.core.cache.backends.base. + +Client code should use the `cache` variable defined here to access the default +cache backend and look up non-default cache backends in the `caches` dict-like +object. + +See docs/topics/cache.txt for information on the public API. +""" +from django.core import signals +from django.core.cache.backends.base import ( + BaseCache, + CacheKeyWarning, + InvalidCacheBackendError, + InvalidCacheKey, +) +from django.utils.connection import BaseConnectionHandler, ConnectionProxy +from django.utils.module_loading import import_string + +__all__ = [ + "cache", + "caches", + "DEFAULT_CACHE_ALIAS", + "InvalidCacheBackendError", + "CacheKeyWarning", + "BaseCache", + "InvalidCacheKey", +] + +DEFAULT_CACHE_ALIAS = "default" + + +class CacheHandler(BaseConnectionHandler): + settings_name = "CACHES" + exception_class = InvalidCacheBackendError + + def create_connection(self, alias): + params = self.settings[alias].copy() + backend = params.pop("BACKEND") + location = params.pop("LOCATION", "") + try: + backend_cls = import_string(backend) + except ImportError as e: + raise InvalidCacheBackendError( + "Could not find backend '%s': %s" % (backend, e) + ) from e + return backend_cls(location, params) + + +caches = CacheHandler() + +cache = ConnectionProxy(caches, DEFAULT_CACHE_ALIAS) + + +def close_caches(**kwargs): + # Some caches need to do a cleanup at the end of a request cycle. If not + # implemented in a particular backend cache.close() is a no-op. + caches.close_all() + + +signals.request_finished.connect(close_caches) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/backends/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/backends/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/backends/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/backends/base.py new file mode 100644 index 0000000..09b0a5f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/backends/base.py @@ -0,0 +1,405 @@ +"Base Cache class." +import time +import warnings + +from asgiref.sync import sync_to_async + +from django.core.exceptions import ImproperlyConfigured +from django.utils.module_loading import import_string +from django.utils.regex_helper import _lazy_re_compile + + +class InvalidCacheBackendError(ImproperlyConfigured): + pass + + +class CacheKeyWarning(RuntimeWarning): + pass + + +class InvalidCacheKey(ValueError): + pass + + +# Stub class to ensure not passing in a `timeout` argument results in +# the default timeout +DEFAULT_TIMEOUT = object() + +# Memcached does not accept keys longer than this. +MEMCACHE_MAX_KEY_LENGTH = 250 + + +def default_key_func(key, key_prefix, version): + """ + Default function to generate keys. + + Construct the key used by all other methods. By default, prepend + the `key_prefix`. KEY_FUNCTION can be used to specify an alternate + function with custom key making behavior. + """ + return "%s:%s:%s" % (key_prefix, version, key) + + +def get_key_func(key_func): + """ + Function to decide which key function to use. + + Default to ``default_key_func``. + """ + if key_func is not None: + if callable(key_func): + return key_func + else: + return import_string(key_func) + return default_key_func + + +class BaseCache: + _missing_key = object() + + def __init__(self, params): + timeout = params.get("timeout", params.get("TIMEOUT", 300)) + if timeout is not None: + try: + timeout = int(timeout) + except (ValueError, TypeError): + timeout = 300 + self.default_timeout = timeout + + options = params.get("OPTIONS", {}) + max_entries = params.get("max_entries", options.get("MAX_ENTRIES", 300)) + try: + self._max_entries = int(max_entries) + except (ValueError, TypeError): + self._max_entries = 300 + + cull_frequency = params.get("cull_frequency", options.get("CULL_FREQUENCY", 3)) + try: + self._cull_frequency = int(cull_frequency) + except (ValueError, TypeError): + self._cull_frequency = 3 + + self.key_prefix = params.get("KEY_PREFIX", "") + self.version = params.get("VERSION", 1) + self.key_func = get_key_func(params.get("KEY_FUNCTION")) + + def get_backend_timeout(self, timeout=DEFAULT_TIMEOUT): + """ + Return the timeout value usable by this backend based upon the provided + timeout. + """ + if timeout == DEFAULT_TIMEOUT: + timeout = self.default_timeout + elif timeout == 0: + # ticket 21147 - avoid time.time() related precision issues + timeout = -1 + return None if timeout is None else time.time() + timeout + + def make_key(self, key, version=None): + """ + Construct the key used by all other methods. By default, use the + key_func to generate a key (which, by default, prepends the + `key_prefix' and 'version'). A different key function can be provided + at the time of cache construction; alternatively, you can subclass the + cache backend to provide custom key making behavior. + """ + if version is None: + version = self.version + + return self.key_func(key, self.key_prefix, version) + + def validate_key(self, key): + """ + Warn about keys that would not be portable to the memcached + backend. This encourages (but does not force) writing backend-portable + cache code. + """ + for warning in memcache_key_warnings(key): + warnings.warn(warning, CacheKeyWarning) + + def make_and_validate_key(self, key, version=None): + """Helper to make and validate keys.""" + key = self.make_key(key, version=version) + self.validate_key(key) + return key + + def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None): + """ + Set a value in the cache if the key does not already exist. If + timeout is given, use that timeout for the key; otherwise use the + default cache timeout. + + Return True if the value was stored, False otherwise. + """ + raise NotImplementedError( + "subclasses of BaseCache must provide an add() method" + ) + + async def aadd(self, key, value, timeout=DEFAULT_TIMEOUT, version=None): + return await sync_to_async(self.add, thread_sensitive=True)( + key, value, timeout, version + ) + + def get(self, key, default=None, version=None): + """ + Fetch a given key from the cache. If the key does not exist, return + default, which itself defaults to None. + """ + raise NotImplementedError("subclasses of BaseCache must provide a get() method") + + async def aget(self, key, default=None, version=None): + return await sync_to_async(self.get, thread_sensitive=True)( + key, default, version + ) + + def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None): + """ + Set a value in the cache. If timeout is given, use that timeout for the + key; otherwise use the default cache timeout. + """ + raise NotImplementedError("subclasses of BaseCache must provide a set() method") + + async def aset(self, key, value, timeout=DEFAULT_TIMEOUT, version=None): + return await sync_to_async(self.set, thread_sensitive=True)( + key, value, timeout, version + ) + + def touch(self, key, timeout=DEFAULT_TIMEOUT, version=None): + """ + Update the key's expiry time using timeout. Return True if successful + or False if the key does not exist. + """ + raise NotImplementedError( + "subclasses of BaseCache must provide a touch() method" + ) + + async def atouch(self, key, timeout=DEFAULT_TIMEOUT, version=None): + return await sync_to_async(self.touch, thread_sensitive=True)( + key, timeout, version + ) + + def delete(self, key, version=None): + """ + Delete a key from the cache and return whether it succeeded, failing + silently. + """ + raise NotImplementedError( + "subclasses of BaseCache must provide a delete() method" + ) + + async def adelete(self, key, version=None): + return await sync_to_async(self.delete, thread_sensitive=True)(key, version) + + def get_many(self, keys, version=None): + """ + Fetch a bunch of keys from the cache. For certain backends (memcached, + pgsql) this can be *much* faster when fetching multiple values. + + Return a dict mapping each key in keys to its value. If the given + key is missing, it will be missing from the response dict. + """ + d = {} + for k in keys: + val = self.get(k, self._missing_key, version=version) + if val is not self._missing_key: + d[k] = val + return d + + async def aget_many(self, keys, version=None): + """See get_many().""" + d = {} + for k in keys: + val = await self.aget(k, self._missing_key, version=version) + if val is not self._missing_key: + d[k] = val + return d + + def get_or_set(self, key, default, timeout=DEFAULT_TIMEOUT, version=None): + """ + Fetch a given key from the cache. If the key does not exist, + add the key and set it to the default value. The default value can + also be any callable. If timeout is given, use that timeout for the + key; otherwise use the default cache timeout. + + Return the value of the key stored or retrieved. + """ + val = self.get(key, self._missing_key, version=version) + if val is self._missing_key: + if callable(default): + default = default() + self.add(key, default, timeout=timeout, version=version) + # Fetch the value again to avoid a race condition if another caller + # added a value between the first get() and the add() above. + return self.get(key, default, version=version) + return val + + async def aget_or_set(self, key, default, timeout=DEFAULT_TIMEOUT, version=None): + """See get_or_set().""" + val = await self.aget(key, self._missing_key, version=version) + if val is self._missing_key: + if callable(default): + default = default() + await self.aadd(key, default, timeout=timeout, version=version) + # Fetch the value again to avoid a race condition if another caller + # added a value between the first aget() and the aadd() above. + return await self.aget(key, default, version=version) + return val + + def has_key(self, key, version=None): + """ + Return True if the key is in the cache and has not expired. + """ + return ( + self.get(key, self._missing_key, version=version) is not self._missing_key + ) + + async def ahas_key(self, key, version=None): + return ( + await self.aget(key, self._missing_key, version=version) + is not self._missing_key + ) + + def incr(self, key, delta=1, version=None): + """ + Add delta to value in the cache. If the key does not exist, raise a + ValueError exception. + """ + value = self.get(key, self._missing_key, version=version) + if value is self._missing_key: + raise ValueError("Key '%s' not found" % key) + new_value = value + delta + self.set(key, new_value, version=version) + return new_value + + async def aincr(self, key, delta=1, version=None): + """See incr().""" + value = await self.aget(key, self._missing_key, version=version) + if value is self._missing_key: + raise ValueError("Key '%s' not found" % key) + new_value = value + delta + await self.aset(key, new_value, version=version) + return new_value + + def decr(self, key, delta=1, version=None): + """ + Subtract delta from value in the cache. If the key does not exist, raise + a ValueError exception. + """ + return self.incr(key, -delta, version=version) + + async def adecr(self, key, delta=1, version=None): + return await self.aincr(key, -delta, version=version) + + def __contains__(self, key): + """ + Return True if the key is in the cache and has not expired. + """ + # This is a separate method, rather than just a copy of has_key(), + # so that it always has the same functionality as has_key(), even + # if a subclass overrides it. + return self.has_key(key) + + def set_many(self, data, timeout=DEFAULT_TIMEOUT, version=None): + """ + Set a bunch of values in the cache at once from a dict of key/value + pairs. For certain backends (memcached), this is much more efficient + than calling set() multiple times. + + If timeout is given, use that timeout for the key; otherwise use the + default cache timeout. + + On backends that support it, return a list of keys that failed + insertion, or an empty list if all keys were inserted successfully. + """ + for key, value in data.items(): + self.set(key, value, timeout=timeout, version=version) + return [] + + async def aset_many(self, data, timeout=DEFAULT_TIMEOUT, version=None): + for key, value in data.items(): + await self.aset(key, value, timeout=timeout, version=version) + return [] + + def delete_many(self, keys, version=None): + """ + Delete a bunch of values in the cache at once. For certain backends + (memcached), this is much more efficient than calling delete() multiple + times. + """ + for key in keys: + self.delete(key, version=version) + + async def adelete_many(self, keys, version=None): + for key in keys: + await self.adelete(key, version=version) + + def clear(self): + """Remove *all* values from the cache at once.""" + raise NotImplementedError( + "subclasses of BaseCache must provide a clear() method" + ) + + async def aclear(self): + return await sync_to_async(self.clear, thread_sensitive=True)() + + def incr_version(self, key, delta=1, version=None): + """ + Add delta to the cache version for the supplied key. Return the new + version. + """ + if version is None: + version = self.version + + value = self.get(key, self._missing_key, version=version) + if value is self._missing_key: + raise ValueError("Key '%s' not found" % key) + + self.set(key, value, version=version + delta) + self.delete(key, version=version) + return version + delta + + async def aincr_version(self, key, delta=1, version=None): + """See incr_version().""" + if version is None: + version = self.version + + value = await self.aget(key, self._missing_key, version=version) + if value is self._missing_key: + raise ValueError("Key '%s' not found" % key) + + await self.aset(key, value, version=version + delta) + await self.adelete(key, version=version) + return version + delta + + def decr_version(self, key, delta=1, version=None): + """ + Subtract delta from the cache version for the supplied key. Return the + new version. + """ + return self.incr_version(key, -delta, version) + + async def adecr_version(self, key, delta=1, version=None): + return await self.aincr_version(key, -delta, version) + + def close(self, **kwargs): + """Close the cache connection""" + pass + + async def aclose(self, **kwargs): + pass + + +memcached_error_chars_re = _lazy_re_compile(r"[\x00-\x20\x7f]") + + +def memcache_key_warnings(key): + if len(key) > MEMCACHE_MAX_KEY_LENGTH: + yield ( + "Cache key will cause errors if used with memcached: %r " + "(longer than %s)" % (key, MEMCACHE_MAX_KEY_LENGTH) + ) + if memcached_error_chars_re.search(key): + yield ( + "Cache key contains characters that will cause errors if used with " + f"memcached: {key!r}" + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/backends/db.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/backends/db.py new file mode 100644 index 0000000..f411051 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/backends/db.py @@ -0,0 +1,293 @@ +"Database cache backend." +import base64 +import pickle +from datetime import datetime, timezone + +from django.conf import settings +from django.core.cache.backends.base import DEFAULT_TIMEOUT, BaseCache +from django.db import DatabaseError, connections, models, router, transaction +from django.utils.timezone import now as tz_now + + +class Options: + """A class that will quack like a Django model _meta class. + + This allows cache operations to be controlled by the router + """ + + def __init__(self, table): + self.db_table = table + self.app_label = "django_cache" + self.model_name = "cacheentry" + self.verbose_name = "cache entry" + self.verbose_name_plural = "cache entries" + self.object_name = "CacheEntry" + self.abstract = False + self.managed = True + self.proxy = False + self.swapped = False + + +class BaseDatabaseCache(BaseCache): + def __init__(self, table, params): + super().__init__(params) + self._table = table + + class CacheEntry: + _meta = Options(table) + + self.cache_model_class = CacheEntry + + +class DatabaseCache(BaseDatabaseCache): + # This class uses cursors provided by the database connection. This means + # it reads expiration values as aware or naive datetimes, depending on the + # value of USE_TZ and whether the database supports time zones. The ORM's + # conversion and adaptation infrastructure is then used to avoid comparing + # aware and naive datetimes accidentally. + + pickle_protocol = pickle.HIGHEST_PROTOCOL + + def get(self, key, default=None, version=None): + return self.get_many([key], version).get(key, default) + + def get_many(self, keys, version=None): + if not keys: + return {} + + key_map = { + self.make_and_validate_key(key, version=version): key for key in keys + } + + db = router.db_for_read(self.cache_model_class) + connection = connections[db] + quote_name = connection.ops.quote_name + table = quote_name(self._table) + + with connection.cursor() as cursor: + cursor.execute( + "SELECT %s, %s, %s FROM %s WHERE %s IN (%s)" + % ( + quote_name("cache_key"), + quote_name("value"), + quote_name("expires"), + table, + quote_name("cache_key"), + ", ".join(["%s"] * len(key_map)), + ), + list(key_map), + ) + rows = cursor.fetchall() + + result = {} + expired_keys = [] + expression = models.Expression(output_field=models.DateTimeField()) + converters = connection.ops.get_db_converters( + expression + ) + expression.get_db_converters(connection) + for key, value, expires in rows: + for converter in converters: + expires = converter(expires, expression, connection) + if expires < tz_now(): + expired_keys.append(key) + else: + value = connection.ops.process_clob(value) + value = pickle.loads(base64.b64decode(value.encode())) + result[key_map.get(key)] = value + self._base_delete_many(expired_keys) + return result + + def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None): + key = self.make_and_validate_key(key, version=version) + self._base_set("set", key, value, timeout) + + def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None): + key = self.make_and_validate_key(key, version=version) + return self._base_set("add", key, value, timeout) + + def touch(self, key, timeout=DEFAULT_TIMEOUT, version=None): + key = self.make_and_validate_key(key, version=version) + return self._base_set("touch", key, None, timeout) + + def _base_set(self, mode, key, value, timeout=DEFAULT_TIMEOUT): + timeout = self.get_backend_timeout(timeout) + db = router.db_for_write(self.cache_model_class) + connection = connections[db] + quote_name = connection.ops.quote_name + table = quote_name(self._table) + + with connection.cursor() as cursor: + cursor.execute("SELECT COUNT(*) FROM %s" % table) + num = cursor.fetchone()[0] + now = tz_now() + now = now.replace(microsecond=0) + if timeout is None: + exp = datetime.max + else: + tz = timezone.utc if settings.USE_TZ else None + exp = datetime.fromtimestamp(timeout, tz=tz) + exp = exp.replace(microsecond=0) + if num > self._max_entries: + self._cull(db, cursor, now, num) + pickled = pickle.dumps(value, self.pickle_protocol) + # The DB column is expecting a string, so make sure the value is a + # string, not bytes. Refs #19274. + b64encoded = base64.b64encode(pickled).decode("latin1") + try: + # Note: typecasting for datetimes is needed by some 3rd party + # database backends. All core backends work without typecasting, + # so be careful about changes here - test suite will NOT pick + # regressions. + with transaction.atomic(using=db): + cursor.execute( + "SELECT %s, %s FROM %s WHERE %s = %%s" + % ( + quote_name("cache_key"), + quote_name("expires"), + table, + quote_name("cache_key"), + ), + [key], + ) + result = cursor.fetchone() + + if result: + current_expires = result[1] + expression = models.Expression( + output_field=models.DateTimeField() + ) + for converter in connection.ops.get_db_converters( + expression + ) + expression.get_db_converters(connection): + current_expires = converter( + current_expires, expression, connection + ) + + exp = connection.ops.adapt_datetimefield_value(exp) + if result and mode == "touch": + cursor.execute( + "UPDATE %s SET %s = %%s WHERE %s = %%s" + % (table, quote_name("expires"), quote_name("cache_key")), + [exp, key], + ) + elif result and ( + mode == "set" or (mode == "add" and current_expires < now) + ): + cursor.execute( + "UPDATE %s SET %s = %%s, %s = %%s WHERE %s = %%s" + % ( + table, + quote_name("value"), + quote_name("expires"), + quote_name("cache_key"), + ), + [b64encoded, exp, key], + ) + elif mode != "touch": + cursor.execute( + "INSERT INTO %s (%s, %s, %s) VALUES (%%s, %%s, %%s)" + % ( + table, + quote_name("cache_key"), + quote_name("value"), + quote_name("expires"), + ), + [key, b64encoded, exp], + ) + else: + return False # touch failed. + except DatabaseError: + # To be threadsafe, updates/inserts are allowed to fail silently + return False + else: + return True + + def delete(self, key, version=None): + key = self.make_and_validate_key(key, version=version) + return self._base_delete_many([key]) + + def delete_many(self, keys, version=None): + keys = [self.make_and_validate_key(key, version=version) for key in keys] + self._base_delete_many(keys) + + def _base_delete_many(self, keys): + if not keys: + return False + + db = router.db_for_write(self.cache_model_class) + connection = connections[db] + quote_name = connection.ops.quote_name + table = quote_name(self._table) + + with connection.cursor() as cursor: + cursor.execute( + "DELETE FROM %s WHERE %s IN (%s)" + % ( + table, + quote_name("cache_key"), + ", ".join(["%s"] * len(keys)), + ), + keys, + ) + return bool(cursor.rowcount) + + def has_key(self, key, version=None): + key = self.make_and_validate_key(key, version=version) + + db = router.db_for_read(self.cache_model_class) + connection = connections[db] + quote_name = connection.ops.quote_name + + now = tz_now().replace(microsecond=0, tzinfo=None) + + with connection.cursor() as cursor: + cursor.execute( + "SELECT %s FROM %s WHERE %s = %%s and %s > %%s" + % ( + quote_name("cache_key"), + quote_name(self._table), + quote_name("cache_key"), + quote_name("expires"), + ), + [key, connection.ops.adapt_datetimefield_value(now)], + ) + return cursor.fetchone() is not None + + def _cull(self, db, cursor, now, num): + if self._cull_frequency == 0: + self.clear() + else: + connection = connections[db] + table = connection.ops.quote_name(self._table) + cursor.execute( + "DELETE FROM %s WHERE %s < %%s" + % ( + table, + connection.ops.quote_name("expires"), + ), + [connection.ops.adapt_datetimefield_value(now)], + ) + deleted_count = cursor.rowcount + remaining_num = num - deleted_count + if remaining_num > self._max_entries: + cull_num = remaining_num // self._cull_frequency + cursor.execute( + connection.ops.cache_key_culling_sql() % table, [cull_num] + ) + last_cache_key = cursor.fetchone() + if last_cache_key: + cursor.execute( + "DELETE FROM %s WHERE %s < %%s" + % ( + table, + connection.ops.quote_name("cache_key"), + ), + [last_cache_key[0]], + ) + + def clear(self): + db = router.db_for_write(self.cache_model_class) + connection = connections[db] + table = connection.ops.quote_name(self._table) + with connection.cursor() as cursor: + cursor.execute("DELETE FROM %s" % table) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/backends/dummy.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/backends/dummy.py new file mode 100644 index 0000000..7b4d339 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/backends/dummy.py @@ -0,0 +1,34 @@ +"Dummy cache backend" + +from django.core.cache.backends.base import DEFAULT_TIMEOUT, BaseCache + + +class DummyCache(BaseCache): + def __init__(self, host, *args, **kwargs): + super().__init__(*args, **kwargs) + + def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None): + self.make_and_validate_key(key, version=version) + return True + + def get(self, key, default=None, version=None): + self.make_and_validate_key(key, version=version) + return default + + def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None): + self.make_and_validate_key(key, version=version) + + def touch(self, key, timeout=DEFAULT_TIMEOUT, version=None): + self.make_and_validate_key(key, version=version) + return False + + def delete(self, key, version=None): + self.make_and_validate_key(key, version=version) + return False + + def has_key(self, key, version=None): + self.make_and_validate_key(key, version=version) + return False + + def clear(self): + pass diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/backends/filebased.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/backends/filebased.py new file mode 100644 index 0000000..29d49c0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/backends/filebased.py @@ -0,0 +1,170 @@ +"File-based cache backend" +import glob +import os +import pickle +import random +import tempfile +import time +import zlib +from hashlib import md5 + +from django.core.cache.backends.base import DEFAULT_TIMEOUT, BaseCache +from django.core.files import locks +from django.core.files.move import file_move_safe + + +class FileBasedCache(BaseCache): + cache_suffix = ".djcache" + pickle_protocol = pickle.HIGHEST_PROTOCOL + + def __init__(self, dir, params): + super().__init__(params) + self._dir = os.path.abspath(dir) + self._createdir() + + def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None): + if self.has_key(key, version): + return False + self.set(key, value, timeout, version) + return True + + def get(self, key, default=None, version=None): + fname = self._key_to_file(key, version) + try: + with open(fname, "rb") as f: + if not self._is_expired(f): + return pickle.loads(zlib.decompress(f.read())) + except FileNotFoundError: + pass + return default + + def _write_content(self, file, timeout, value): + expiry = self.get_backend_timeout(timeout) + file.write(pickle.dumps(expiry, self.pickle_protocol)) + file.write(zlib.compress(pickle.dumps(value, self.pickle_protocol))) + + def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None): + self._createdir() # Cache dir can be deleted at any time. + fname = self._key_to_file(key, version) + self._cull() # make some room if necessary + fd, tmp_path = tempfile.mkstemp(dir=self._dir) + renamed = False + try: + with open(fd, "wb") as f: + self._write_content(f, timeout, value) + file_move_safe(tmp_path, fname, allow_overwrite=True) + renamed = True + finally: + if not renamed: + os.remove(tmp_path) + + def touch(self, key, timeout=DEFAULT_TIMEOUT, version=None): + try: + with open(self._key_to_file(key, version), "r+b") as f: + try: + locks.lock(f, locks.LOCK_EX) + if self._is_expired(f): + return False + else: + previous_value = pickle.loads(zlib.decompress(f.read())) + f.seek(0) + self._write_content(f, timeout, previous_value) + return True + finally: + locks.unlock(f) + except FileNotFoundError: + return False + + def delete(self, key, version=None): + return self._delete(self._key_to_file(key, version)) + + def _delete(self, fname): + if not fname.startswith(self._dir) or not os.path.exists(fname): + return False + try: + os.remove(fname) + except FileNotFoundError: + # The file may have been removed by another process. + return False + return True + + def has_key(self, key, version=None): + fname = self._key_to_file(key, version) + try: + with open(fname, "rb") as f: + return not self._is_expired(f) + except FileNotFoundError: + return False + + def _cull(self): + """ + Remove random cache entries if max_entries is reached at a ratio + of num_entries / cull_frequency. A value of 0 for CULL_FREQUENCY means + that the entire cache will be purged. + """ + filelist = self._list_cache_files() + num_entries = len(filelist) + if num_entries < self._max_entries: + return # return early if no culling is required + if self._cull_frequency == 0: + return self.clear() # Clear the cache when CULL_FREQUENCY = 0 + # Delete a random selection of entries + filelist = random.sample(filelist, int(num_entries / self._cull_frequency)) + for fname in filelist: + self._delete(fname) + + def _createdir(self): + # Set the umask because os.makedirs() doesn't apply the "mode" argument + # to intermediate-level directories. + old_umask = os.umask(0o077) + try: + os.makedirs(self._dir, 0o700, exist_ok=True) + finally: + os.umask(old_umask) + + def _key_to_file(self, key, version=None): + """ + Convert a key into a cache file path. Basically this is the + root cache path joined with the md5sum of the key and a suffix. + """ + key = self.make_and_validate_key(key, version=version) + return os.path.join( + self._dir, + "".join( + [ + md5(key.encode(), usedforsecurity=False).hexdigest(), + self.cache_suffix, + ] + ), + ) + + def clear(self): + """ + Remove all the cache files. + """ + for fname in self._list_cache_files(): + self._delete(fname) + + def _is_expired(self, f): + """ + Take an open cache file `f` and delete it if it's expired. + """ + try: + exp = pickle.load(f) + except EOFError: + exp = 0 # An empty file is considered expired. + if exp is not None and exp < time.time(): + f.close() # On Windows a file has to be closed before deleting + self._delete(f.name) + return True + return False + + def _list_cache_files(self): + """ + Get a list of paths to all the cache files. These are all the files + in the root cache dir that end on the cache_suffix. + """ + return [ + os.path.join(self._dir, fname) + for fname in glob.glob1(self._dir, "*%s" % self.cache_suffix) + ] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/backends/locmem.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/backends/locmem.py new file mode 100644 index 0000000..cbc8dba --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/backends/locmem.py @@ -0,0 +1,117 @@ +"Thread-safe in-memory cache backend." +import pickle +import time +from collections import OrderedDict +from threading import Lock + +from django.core.cache.backends.base import DEFAULT_TIMEOUT, BaseCache + +# Global in-memory store of cache data. Keyed by name, to provide +# multiple named local memory caches. +_caches = {} +_expire_info = {} +_locks = {} + + +class LocMemCache(BaseCache): + pickle_protocol = pickle.HIGHEST_PROTOCOL + + def __init__(self, name, params): + super().__init__(params) + self._cache = _caches.setdefault(name, OrderedDict()) + self._expire_info = _expire_info.setdefault(name, {}) + self._lock = _locks.setdefault(name, Lock()) + + def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None): + key = self.make_and_validate_key(key, version=version) + pickled = pickle.dumps(value, self.pickle_protocol) + with self._lock: + if self._has_expired(key): + self._set(key, pickled, timeout) + return True + return False + + def get(self, key, default=None, version=None): + key = self.make_and_validate_key(key, version=version) + with self._lock: + if self._has_expired(key): + self._delete(key) + return default + pickled = self._cache[key] + self._cache.move_to_end(key, last=False) + return pickle.loads(pickled) + + def _set(self, key, value, timeout=DEFAULT_TIMEOUT): + if len(self._cache) >= self._max_entries: + self._cull() + self._cache[key] = value + self._cache.move_to_end(key, last=False) + self._expire_info[key] = self.get_backend_timeout(timeout) + + def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None): + key = self.make_and_validate_key(key, version=version) + pickled = pickle.dumps(value, self.pickle_protocol) + with self._lock: + self._set(key, pickled, timeout) + + def touch(self, key, timeout=DEFAULT_TIMEOUT, version=None): + key = self.make_and_validate_key(key, version=version) + with self._lock: + if self._has_expired(key): + return False + self._expire_info[key] = self.get_backend_timeout(timeout) + return True + + def incr(self, key, delta=1, version=None): + key = self.make_and_validate_key(key, version=version) + with self._lock: + if self._has_expired(key): + self._delete(key) + raise ValueError("Key '%s' not found" % key) + pickled = self._cache[key] + value = pickle.loads(pickled) + new_value = value + delta + pickled = pickle.dumps(new_value, self.pickle_protocol) + self._cache[key] = pickled + self._cache.move_to_end(key, last=False) + return new_value + + def has_key(self, key, version=None): + key = self.make_and_validate_key(key, version=version) + with self._lock: + if self._has_expired(key): + self._delete(key) + return False + return True + + def _has_expired(self, key): + exp = self._expire_info.get(key, -1) + return exp is not None and exp <= time.time() + + def _cull(self): + if self._cull_frequency == 0: + self._cache.clear() + self._expire_info.clear() + else: + count = len(self._cache) // self._cull_frequency + for i in range(count): + key, _ = self._cache.popitem() + del self._expire_info[key] + + def _delete(self, key): + try: + del self._cache[key] + del self._expire_info[key] + except KeyError: + return False + return True + + def delete(self, key, version=None): + key = self.make_and_validate_key(key, version=version) + with self._lock: + return self._delete(key) + + def clear(self): + with self._lock: + self._cache.clear() + self._expire_info.clear() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/backends/memcached.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/backends/memcached.py new file mode 100644 index 0000000..6e2c761 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/backends/memcached.py @@ -0,0 +1,188 @@ +"Memcached cache backend" + +import re +import time + +from django.core.cache.backends.base import ( + DEFAULT_TIMEOUT, + BaseCache, + InvalidCacheKey, + memcache_key_warnings, +) +from django.utils.functional import cached_property + + +class BaseMemcachedCache(BaseCache): + def __init__(self, server, params, library, value_not_found_exception): + super().__init__(params) + if isinstance(server, str): + self._servers = re.split("[;,]", server) + else: + self._servers = server + + # Exception type raised by the underlying client library for a + # nonexistent key. + self.LibraryValueNotFoundException = value_not_found_exception + + self._lib = library + self._class = library.Client + self._options = params.get("OPTIONS") or {} + + @property + def client_servers(self): + return self._servers + + @cached_property + def _cache(self): + """ + Implement transparent thread-safe access to a memcached client. + """ + return self._class(self.client_servers, **self._options) + + def get_backend_timeout(self, timeout=DEFAULT_TIMEOUT): + """ + Memcached deals with long (> 30 days) timeouts in a special + way. Call this function to obtain a safe value for your timeout. + """ + if timeout == DEFAULT_TIMEOUT: + timeout = self.default_timeout + + if timeout is None: + # Using 0 in memcache sets a non-expiring timeout. + return 0 + elif int(timeout) == 0: + # Other cache backends treat 0 as set-and-expire. To achieve this + # in memcache backends, a negative timeout must be passed. + timeout = -1 + + if timeout > 2592000: # 60*60*24*30, 30 days + # See https://github.com/memcached/memcached/wiki/Programming#expiration + # "Expiration times can be set from 0, meaning "never expire", to + # 30 days. Any time higher than 30 days is interpreted as a Unix + # timestamp date. If you want to expire an object on January 1st of + # next year, this is how you do that." + # + # This means that we have to switch to absolute timestamps. + timeout += int(time.time()) + return int(timeout) + + def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None): + key = self.make_and_validate_key(key, version=version) + return self._cache.add(key, value, self.get_backend_timeout(timeout)) + + def get(self, key, default=None, version=None): + key = self.make_and_validate_key(key, version=version) + return self._cache.get(key, default) + + def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None): + key = self.make_and_validate_key(key, version=version) + if not self._cache.set(key, value, self.get_backend_timeout(timeout)): + # Make sure the key doesn't keep its old value in case of failure + # to set (memcached's 1MB limit). + self._cache.delete(key) + + def touch(self, key, timeout=DEFAULT_TIMEOUT, version=None): + key = self.make_and_validate_key(key, version=version) + return bool(self._cache.touch(key, self.get_backend_timeout(timeout))) + + def delete(self, key, version=None): + key = self.make_and_validate_key(key, version=version) + return bool(self._cache.delete(key)) + + def get_many(self, keys, version=None): + key_map = { + self.make_and_validate_key(key, version=version): key for key in keys + } + ret = self._cache.get_multi(key_map.keys()) + return {key_map[k]: v for k, v in ret.items()} + + def close(self, **kwargs): + # Many clients don't clean up connections properly. + self._cache.disconnect_all() + + def incr(self, key, delta=1, version=None): + key = self.make_and_validate_key(key, version=version) + try: + # Memcached doesn't support negative delta. + if delta < 0: + val = self._cache.decr(key, -delta) + else: + val = self._cache.incr(key, delta) + # Normalize an exception raised by the underlying client library to + # ValueError in the event of a nonexistent key when calling + # incr()/decr(). + except self.LibraryValueNotFoundException: + val = None + if val is None: + raise ValueError("Key '%s' not found" % key) + return val + + def set_many(self, data, timeout=DEFAULT_TIMEOUT, version=None): + safe_data = {} + original_keys = {} + for key, value in data.items(): + safe_key = self.make_and_validate_key(key, version=version) + safe_data[safe_key] = value + original_keys[safe_key] = key + failed_keys = self._cache.set_multi( + safe_data, self.get_backend_timeout(timeout) + ) + return [original_keys[k] for k in failed_keys] + + def delete_many(self, keys, version=None): + keys = [self.make_and_validate_key(key, version=version) for key in keys] + self._cache.delete_multi(keys) + + def clear(self): + self._cache.flush_all() + + def validate_key(self, key): + for warning in memcache_key_warnings(key): + raise InvalidCacheKey(warning) + + +class PyLibMCCache(BaseMemcachedCache): + "An implementation of a cache binding using pylibmc" + + def __init__(self, server, params): + import pylibmc + + super().__init__( + server, params, library=pylibmc, value_not_found_exception=pylibmc.NotFound + ) + + @property + def client_servers(self): + output = [] + for server in self._servers: + output.append(server.removeprefix("unix:")) + return output + + def touch(self, key, timeout=DEFAULT_TIMEOUT, version=None): + key = self.make_and_validate_key(key, version=version) + if timeout == 0: + return self._cache.delete(key) + return self._cache.touch(key, self.get_backend_timeout(timeout)) + + def close(self, **kwargs): + # libmemcached manages its own connections. Don't call disconnect_all() + # as it resets the failover state and creates unnecessary reconnects. + pass + + +class PyMemcacheCache(BaseMemcachedCache): + """An implementation of a cache binding using pymemcache.""" + + def __init__(self, server, params): + import pymemcache.serde + + super().__init__( + server, params, library=pymemcache, value_not_found_exception=KeyError + ) + self._class = self._lib.HashClient + self._options = { + "allow_unicode_keys": True, + "default_noreply": False, + "serde": pymemcache.serde.pickle_serde, + **self._options, + } diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/backends/redis.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/backends/redis.py new file mode 100644 index 0000000..eda8ac9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/backends/redis.py @@ -0,0 +1,233 @@ +"""Redis cache backend.""" + +import pickle +import random +import re + +from django.core.cache.backends.base import DEFAULT_TIMEOUT, BaseCache +from django.utils.functional import cached_property +from django.utils.module_loading import import_string + + +class RedisSerializer: + def __init__(self, protocol=None): + self.protocol = pickle.HIGHEST_PROTOCOL if protocol is None else protocol + + def dumps(self, obj): + # Only skip pickling for integers, a int subclasses as bool should be + # pickled. + if type(obj) is int: + return obj + return pickle.dumps(obj, self.protocol) + + def loads(self, data): + try: + return int(data) + except ValueError: + return pickle.loads(data) + + +class RedisCacheClient: + def __init__( + self, + servers, + serializer=None, + pool_class=None, + parser_class=None, + **options, + ): + import redis + + self._lib = redis + self._servers = servers + self._pools = {} + + self._client = self._lib.Redis + + if isinstance(pool_class, str): + pool_class = import_string(pool_class) + self._pool_class = pool_class or self._lib.ConnectionPool + + if isinstance(serializer, str): + serializer = import_string(serializer) + if callable(serializer): + serializer = serializer() + self._serializer = serializer or RedisSerializer() + + if isinstance(parser_class, str): + parser_class = import_string(parser_class) + parser_class = parser_class or self._lib.connection.DefaultParser + + self._pool_options = {"parser_class": parser_class, **options} + + def _get_connection_pool_index(self, write): + # Write to the first server. Read from other servers if there are more, + # otherwise read from the first server. + if write or len(self._servers) == 1: + return 0 + return random.randint(1, len(self._servers) - 1) + + def _get_connection_pool(self, write): + index = self._get_connection_pool_index(write) + if index not in self._pools: + self._pools[index] = self._pool_class.from_url( + self._servers[index], + **self._pool_options, + ) + return self._pools[index] + + def get_client(self, key=None, *, write=False): + # key is used so that the method signature remains the same and custom + # cache client can be implemented which might require the key to select + # the server, e.g. sharding. + pool = self._get_connection_pool(write) + return self._client(connection_pool=pool) + + def add(self, key, value, timeout): + client = self.get_client(key, write=True) + value = self._serializer.dumps(value) + + if timeout == 0: + if ret := bool(client.set(key, value, nx=True)): + client.delete(key) + return ret + else: + return bool(client.set(key, value, ex=timeout, nx=True)) + + def get(self, key, default): + client = self.get_client(key) + value = client.get(key) + return default if value is None else self._serializer.loads(value) + + def set(self, key, value, timeout): + client = self.get_client(key, write=True) + value = self._serializer.dumps(value) + if timeout == 0: + client.delete(key) + else: + client.set(key, value, ex=timeout) + + def touch(self, key, timeout): + client = self.get_client(key, write=True) + if timeout is None: + return bool(client.persist(key)) + else: + return bool(client.expire(key, timeout)) + + def delete(self, key): + client = self.get_client(key, write=True) + return bool(client.delete(key)) + + def get_many(self, keys): + client = self.get_client(None) + ret = client.mget(keys) + return { + k: self._serializer.loads(v) for k, v in zip(keys, ret) if v is not None + } + + def has_key(self, key): + client = self.get_client(key) + return bool(client.exists(key)) + + def incr(self, key, delta): + client = self.get_client(key, write=True) + if not client.exists(key): + raise ValueError("Key '%s' not found." % key) + return client.incr(key, delta) + + def set_many(self, data, timeout): + client = self.get_client(None, write=True) + pipeline = client.pipeline() + pipeline.mset({k: self._serializer.dumps(v) for k, v in data.items()}) + + if timeout is not None: + # Setting timeout for each key as redis does not support timeout + # with mset(). + for key in data: + pipeline.expire(key, timeout) + pipeline.execute() + + def delete_many(self, keys): + client = self.get_client(None, write=True) + client.delete(*keys) + + def clear(self): + client = self.get_client(None, write=True) + return bool(client.flushdb()) + + +class RedisCache(BaseCache): + def __init__(self, server, params): + super().__init__(params) + if isinstance(server, str): + self._servers = re.split("[;,]", server) + else: + self._servers = server + + self._class = RedisCacheClient + self._options = params.get("OPTIONS", {}) + + @cached_property + def _cache(self): + return self._class(self._servers, **self._options) + + def get_backend_timeout(self, timeout=DEFAULT_TIMEOUT): + if timeout == DEFAULT_TIMEOUT: + timeout = self.default_timeout + # The key will be made persistent if None used as a timeout. + # Non-positive values will cause the key to be deleted. + return None if timeout is None else max(0, int(timeout)) + + def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None): + key = self.make_and_validate_key(key, version=version) + return self._cache.add(key, value, self.get_backend_timeout(timeout)) + + def get(self, key, default=None, version=None): + key = self.make_and_validate_key(key, version=version) + return self._cache.get(key, default) + + def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None): + key = self.make_and_validate_key(key, version=version) + self._cache.set(key, value, self.get_backend_timeout(timeout)) + + def touch(self, key, timeout=DEFAULT_TIMEOUT, version=None): + key = self.make_and_validate_key(key, version=version) + return self._cache.touch(key, self.get_backend_timeout(timeout)) + + def delete(self, key, version=None): + key = self.make_and_validate_key(key, version=version) + return self._cache.delete(key) + + def get_many(self, keys, version=None): + key_map = { + self.make_and_validate_key(key, version=version): key for key in keys + } + ret = self._cache.get_many(key_map.keys()) + return {key_map[k]: v for k, v in ret.items()} + + def has_key(self, key, version=None): + key = self.make_and_validate_key(key, version=version) + return self._cache.has_key(key) + + def incr(self, key, delta=1, version=None): + key = self.make_and_validate_key(key, version=version) + return self._cache.incr(key, delta) + + def set_many(self, data, timeout=DEFAULT_TIMEOUT, version=None): + if not data: + return [] + safe_data = {} + for key, value in data.items(): + key = self.make_and_validate_key(key, version=version) + safe_data[key] = value + self._cache.set_many(safe_data, self.get_backend_timeout(timeout)) + return [] + + def delete_many(self, keys, version=None): + if not keys: + return + safe_keys = [self.make_and_validate_key(key, version=version) for key in keys] + self._cache.delete_many(safe_keys) + + def clear(self): + return self._cache.clear() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/utils.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/utils.py new file mode 100644 index 0000000..87f0f9c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/cache/utils.py @@ -0,0 +1,12 @@ +from hashlib import md5 + +TEMPLATE_FRAGMENT_KEY_TEMPLATE = "template.cache.%s.%s" + + +def make_template_fragment_key(fragment_name, vary_on=None): + hasher = md5(usedforsecurity=False) + if vary_on is not None: + for arg in vary_on: + hasher.update(str(arg).encode()) + hasher.update(b":") + return TEMPLATE_FRAGMENT_KEY_TEMPLATE % (fragment_name, hasher.hexdigest()) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/__init__.py new file mode 100644 index 0000000..998ab9d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/__init__.py @@ -0,0 +1,47 @@ +from .messages import ( + CRITICAL, + DEBUG, + ERROR, + INFO, + WARNING, + CheckMessage, + Critical, + Debug, + Error, + Info, + Warning, +) +from .registry import Tags, register, run_checks, tag_exists + +# Import these to force registration of checks +import django.core.checks.async_checks # NOQA isort:skip +import django.core.checks.caches # NOQA isort:skip +import django.core.checks.compatibility.django_4_0 # NOQA isort:skip +import django.core.checks.database # NOQA isort:skip +import django.core.checks.files # NOQA isort:skip +import django.core.checks.model_checks # NOQA isort:skip +import django.core.checks.security.base # NOQA isort:skip +import django.core.checks.security.csrf # NOQA isort:skip +import django.core.checks.security.sessions # NOQA isort:skip +import django.core.checks.templates # NOQA isort:skip +import django.core.checks.translation # NOQA isort:skip +import django.core.checks.urls # NOQA isort:skip + + +__all__ = [ + "CheckMessage", + "Debug", + "Info", + "Warning", + "Error", + "Critical", + "DEBUG", + "INFO", + "WARNING", + "ERROR", + "CRITICAL", + "register", + "run_checks", + "tag_exists", + "Tags", +] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/async_checks.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/async_checks.py new file mode 100644 index 0000000..a0e0186 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/async_checks.py @@ -0,0 +1,16 @@ +import os + +from . import Error, Tags, register + +E001 = Error( + "You should not set the DJANGO_ALLOW_ASYNC_UNSAFE environment variable in " + "deployment. This disables async safety protection.", + id="async.E001", +) + + +@register(Tags.async_support, deploy=True) +def check_async_unsafe(app_configs, **kwargs): + if os.environ.get("DJANGO_ALLOW_ASYNC_UNSAFE"): + return [E001] + return [] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/caches.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/caches.py new file mode 100644 index 0000000..c288a6f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/caches.py @@ -0,0 +1,76 @@ +import pathlib + +from django.conf import settings +from django.core.cache import DEFAULT_CACHE_ALIAS, caches +from django.core.cache.backends.filebased import FileBasedCache + +from . import Error, Tags, Warning, register + +E001 = Error( + "You must define a '%s' cache in your CACHES setting." % DEFAULT_CACHE_ALIAS, + id="caches.E001", +) + + +@register(Tags.caches) +def check_default_cache_is_configured(app_configs, **kwargs): + if DEFAULT_CACHE_ALIAS not in settings.CACHES: + return [E001] + return [] + + +@register(Tags.caches, deploy=True) +def check_cache_location_not_exposed(app_configs, **kwargs): + errors = [] + for name in ("MEDIA_ROOT", "STATIC_ROOT", "STATICFILES_DIRS"): + setting = getattr(settings, name, None) + if not setting: + continue + if name == "STATICFILES_DIRS": + paths = set() + for staticfiles_dir in setting: + if isinstance(staticfiles_dir, (list, tuple)): + _, staticfiles_dir = staticfiles_dir + paths.add(pathlib.Path(staticfiles_dir).resolve()) + else: + paths = {pathlib.Path(setting).resolve()} + for alias in settings.CACHES: + cache = caches[alias] + if not isinstance(cache, FileBasedCache): + continue + cache_path = pathlib.Path(cache._dir).resolve() + if any(path == cache_path for path in paths): + relation = "matches" + elif any(path in cache_path.parents for path in paths): + relation = "is inside" + elif any(cache_path in path.parents for path in paths): + relation = "contains" + else: + continue + errors.append( + Warning( + f"Your '{alias}' cache configuration might expose your cache " + f"or lead to corruption of your data because its LOCATION " + f"{relation} {name}.", + id="caches.W002", + ) + ) + return errors + + +@register(Tags.caches) +def check_file_based_cache_is_absolute(app_configs, **kwargs): + errors = [] + for alias, config in settings.CACHES.items(): + cache = caches[alias] + if not isinstance(cache, FileBasedCache): + continue + if not pathlib.Path(config["LOCATION"]).is_absolute(): + errors.append( + Warning( + f"Your '{alias}' cache LOCATION path is relative. Use an " + f"absolute path instead.", + id="caches.W003", + ) + ) + return errors diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/compatibility/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/compatibility/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/compatibility/django_4_0.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/compatibility/django_4_0.py new file mode 100644 index 0000000..79ee5fa --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/compatibility/django_4_0.py @@ -0,0 +1,20 @@ +from django.conf import settings + +from .. import Error, Tags, register + + +@register(Tags.compatibility) +def check_csrf_trusted_origins(app_configs, **kwargs): + errors = [] + for origin in settings.CSRF_TRUSTED_ORIGINS: + if "://" not in origin: + errors.append( + Error( + "As of Django 4.0, the values in the CSRF_TRUSTED_ORIGINS " + "setting must start with a scheme (usually http:// or " + "https://) but found %s. See the release notes for details." + % origin, + id="4_0.E001", + ) + ) + return errors diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/database.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/database.py new file mode 100644 index 0000000..d125f1e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/database.py @@ -0,0 +1,14 @@ +from django.db import connections + +from . import Tags, register + + +@register(Tags.database) +def check_database_backends(databases=None, **kwargs): + if databases is None: + return [] + issues = [] + for alias in databases: + conn = connections[alias] + issues.extend(conn.validation.check(**kwargs)) + return issues diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/files.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/files.py new file mode 100644 index 0000000..40dc745 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/files.py @@ -0,0 +1,19 @@ +from pathlib import Path + +from django.conf import settings + +from . import Error, Tags, register + + +@register(Tags.files) +def check_setting_file_upload_temp_dir(app_configs, **kwargs): + setting = getattr(settings, "FILE_UPLOAD_TEMP_DIR", None) + if setting and not Path(setting).is_dir(): + return [ + Error( + f"The FILE_UPLOAD_TEMP_DIR setting refers to the nonexistent " + f"directory '{setting}'.", + id="files.E001", + ), + ] + return [] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/messages.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/messages.py new file mode 100644 index 0000000..db7aa55 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/messages.py @@ -0,0 +1,81 @@ +# Levels +DEBUG = 10 +INFO = 20 +WARNING = 30 +ERROR = 40 +CRITICAL = 50 + + +class CheckMessage: + def __init__(self, level, msg, hint=None, obj=None, id=None): + if not isinstance(level, int): + raise TypeError("The first argument should be level.") + self.level = level + self.msg = msg + self.hint = hint + self.obj = obj + self.id = id + + def __eq__(self, other): + return isinstance(other, self.__class__) and all( + getattr(self, attr) == getattr(other, attr) + for attr in ["level", "msg", "hint", "obj", "id"] + ) + + def __str__(self): + from django.db import models + + if self.obj is None: + obj = "?" + elif isinstance(self.obj, models.base.ModelBase): + # We need to hardcode ModelBase and Field cases because its __str__ + # method doesn't return "applabel.modellabel" and cannot be changed. + obj = self.obj._meta.label + else: + obj = str(self.obj) + id = "(%s) " % self.id if self.id else "" + hint = "\n\tHINT: %s" % self.hint if self.hint else "" + return "%s: %s%s%s" % (obj, id, self.msg, hint) + + def __repr__(self): + return "<%s: level=%r, msg=%r, hint=%r, obj=%r, id=%r>" % ( + self.__class__.__name__, + self.level, + self.msg, + self.hint, + self.obj, + self.id, + ) + + def is_serious(self, level=ERROR): + return self.level >= level + + def is_silenced(self): + from django.conf import settings + + return self.id in settings.SILENCED_SYSTEM_CHECKS + + +class Debug(CheckMessage): + def __init__(self, *args, **kwargs): + super().__init__(DEBUG, *args, **kwargs) + + +class Info(CheckMessage): + def __init__(self, *args, **kwargs): + super().__init__(INFO, *args, **kwargs) + + +class Warning(CheckMessage): + def __init__(self, *args, **kwargs): + super().__init__(WARNING, *args, **kwargs) + + +class Error(CheckMessage): + def __init__(self, *args, **kwargs): + super().__init__(ERROR, *args, **kwargs) + + +class Critical(CheckMessage): + def __init__(self, *args, **kwargs): + super().__init__(CRITICAL, *args, **kwargs) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/model_checks.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/model_checks.py new file mode 100644 index 0000000..7a5bef9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/model_checks.py @@ -0,0 +1,227 @@ +import inspect +import types +from collections import defaultdict +from itertools import chain + +from django.apps import apps +from django.conf import settings +from django.core.checks import Error, Tags, Warning, register + + +@register(Tags.models) +def check_all_models(app_configs=None, **kwargs): + db_table_models = defaultdict(list) + indexes = defaultdict(list) + constraints = defaultdict(list) + errors = [] + if app_configs is None: + models = apps.get_models() + else: + models = chain.from_iterable( + app_config.get_models() for app_config in app_configs + ) + for model in models: + if model._meta.managed and not model._meta.proxy: + db_table_models[model._meta.db_table].append(model._meta.label) + if not inspect.ismethod(model.check): + errors.append( + Error( + "The '%s.check()' class method is currently overridden by %r." + % (model.__name__, model.check), + obj=model, + id="models.E020", + ) + ) + else: + errors.extend(model.check(**kwargs)) + for model_index in model._meta.indexes: + indexes[model_index.name].append(model._meta.label) + for model_constraint in model._meta.constraints: + constraints[model_constraint.name].append(model._meta.label) + if settings.DATABASE_ROUTERS: + error_class, error_id = Warning, "models.W035" + error_hint = ( + "You have configured settings.DATABASE_ROUTERS. Verify that %s " + "are correctly routed to separate databases." + ) + else: + error_class, error_id = Error, "models.E028" + error_hint = None + for db_table, model_labels in db_table_models.items(): + if len(model_labels) != 1: + model_labels_str = ", ".join(model_labels) + errors.append( + error_class( + "db_table '%s' is used by multiple models: %s." + % (db_table, model_labels_str), + obj=db_table, + hint=(error_hint % model_labels_str) if error_hint else None, + id=error_id, + ) + ) + for index_name, model_labels in indexes.items(): + if len(model_labels) > 1: + model_labels = set(model_labels) + errors.append( + Error( + "index name '%s' is not unique %s %s." + % ( + index_name, + "for model" if len(model_labels) == 1 else "among models:", + ", ".join(sorted(model_labels)), + ), + id="models.E029" if len(model_labels) == 1 else "models.E030", + ), + ) + for constraint_name, model_labels in constraints.items(): + if len(model_labels) > 1: + model_labels = set(model_labels) + errors.append( + Error( + "constraint name '%s' is not unique %s %s." + % ( + constraint_name, + "for model" if len(model_labels) == 1 else "among models:", + ", ".join(sorted(model_labels)), + ), + id="models.E031" if len(model_labels) == 1 else "models.E032", + ), + ) + return errors + + +def _check_lazy_references(apps, ignore=None): + """ + Ensure all lazy (i.e. string) model references have been resolved. + + Lazy references are used in various places throughout Django, primarily in + related fields and model signals. Identify those common cases and provide + more helpful error messages for them. + + The ignore parameter is used by StateApps to exclude swappable models from + this check. + """ + pending_models = set(apps._pending_operations) - (ignore or set()) + + # Short circuit if there aren't any errors. + if not pending_models: + return [] + + from django.db.models import signals + + model_signals = { + signal: name + for name, signal in vars(signals).items() + if isinstance(signal, signals.ModelSignal) + } + + def extract_operation(obj): + """ + Take a callable found in Apps._pending_operations and identify the + original callable passed to Apps.lazy_model_operation(). If that + callable was a partial, return the inner, non-partial function and + any arguments and keyword arguments that were supplied with it. + + obj is a callback defined locally in Apps.lazy_model_operation() and + annotated there with a `func` attribute so as to imitate a partial. + """ + operation, args, keywords = obj, [], {} + while hasattr(operation, "func"): + args.extend(getattr(operation, "args", [])) + keywords.update(getattr(operation, "keywords", {})) + operation = operation.func + return operation, args, keywords + + def app_model_error(model_key): + try: + apps.get_app_config(model_key[0]) + model_error = "app '%s' doesn't provide model '%s'" % model_key + except LookupError: + model_error = "app '%s' isn't installed" % model_key[0] + return model_error + + # Here are several functions which return CheckMessage instances for the + # most common usages of lazy operations throughout Django. These functions + # take the model that was being waited on as an (app_label, modelname) + # pair, the original lazy function, and its positional and keyword args as + # determined by extract_operation(). + + def field_error(model_key, func, args, keywords): + error_msg = ( + "The field %(field)s was declared with a lazy reference " + "to '%(model)s', but %(model_error)s." + ) + params = { + "model": ".".join(model_key), + "field": keywords["field"], + "model_error": app_model_error(model_key), + } + return Error(error_msg % params, obj=keywords["field"], id="fields.E307") + + def signal_connect_error(model_key, func, args, keywords): + error_msg = ( + "%(receiver)s was connected to the '%(signal)s' signal with a " + "lazy reference to the sender '%(model)s', but %(model_error)s." + ) + receiver = args[0] + # The receiver is either a function or an instance of class + # defining a `__call__` method. + if isinstance(receiver, types.FunctionType): + description = "The function '%s'" % receiver.__name__ + elif isinstance(receiver, types.MethodType): + description = "Bound method '%s.%s'" % ( + receiver.__self__.__class__.__name__, + receiver.__name__, + ) + else: + description = "An instance of class '%s'" % receiver.__class__.__name__ + signal_name = model_signals.get(func.__self__, "unknown") + params = { + "model": ".".join(model_key), + "receiver": description, + "signal": signal_name, + "model_error": app_model_error(model_key), + } + return Error(error_msg % params, obj=receiver.__module__, id="signals.E001") + + def default_error(model_key, func, args, keywords): + error_msg = ( + "%(op)s contains a lazy reference to %(model)s, but %(model_error)s." + ) + params = { + "op": func, + "model": ".".join(model_key), + "model_error": app_model_error(model_key), + } + return Error(error_msg % params, obj=func, id="models.E022") + + # Maps common uses of lazy operations to corresponding error functions + # defined above. If a key maps to None, no error will be produced. + # default_error() will be used for usages that don't appear in this dict. + known_lazy = { + ("django.db.models.fields.related", "resolve_related_class"): field_error, + ("django.db.models.fields.related", "set_managed"): None, + ("django.dispatch.dispatcher", "connect"): signal_connect_error, + } + + def build_error(model_key, func, args, keywords): + key = (func.__module__, func.__name__) + error_fn = known_lazy.get(key, default_error) + return error_fn(model_key, func, args, keywords) if error_fn else None + + return sorted( + filter( + None, + ( + build_error(model_key, *extract_operation(func)) + for model_key in pending_models + for func in apps._pending_operations[model_key] + ), + ), + key=lambda error: error.msg, + ) + + +@register(Tags.models) +def check_lazy_references(app_configs=None, **kwargs): + return _check_lazy_references(apps) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/registry.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/registry.py new file mode 100644 index 0000000..f4bdea8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/registry.py @@ -0,0 +1,117 @@ +from itertools import chain + +from django.utils.inspect import func_accepts_kwargs +from django.utils.itercompat import is_iterable + + +class Tags: + """ + Built-in tags for internal checks. + """ + + admin = "admin" + async_support = "async_support" + caches = "caches" + compatibility = "compatibility" + database = "database" + files = "files" + models = "models" + security = "security" + signals = "signals" + sites = "sites" + staticfiles = "staticfiles" + templates = "templates" + translation = "translation" + urls = "urls" + + +class CheckRegistry: + def __init__(self): + self.registered_checks = set() + self.deployment_checks = set() + + def register(self, check=None, *tags, **kwargs): + """ + Can be used as a function or a decorator. Register given function + `f` labeled with given `tags`. The function should receive **kwargs + and return list of Errors and Warnings. + + Example:: + + registry = CheckRegistry() + @registry.register('mytag', 'anothertag') + def my_check(app_configs, **kwargs): + # ... perform checks and collect `errors` ... + return errors + # or + registry.register(my_check, 'mytag', 'anothertag') + """ + + def inner(check): + if not func_accepts_kwargs(check): + raise TypeError( + "Check functions must accept keyword arguments (**kwargs)." + ) + check.tags = tags + checks = ( + self.deployment_checks + if kwargs.get("deploy") + else self.registered_checks + ) + checks.add(check) + return check + + if callable(check): + return inner(check) + else: + if check: + tags += (check,) + return inner + + def run_checks( + self, + app_configs=None, + tags=None, + include_deployment_checks=False, + databases=None, + ): + """ + Run all registered checks and return list of Errors and Warnings. + """ + errors = [] + checks = self.get_checks(include_deployment_checks) + + if tags is not None: + checks = [check for check in checks if not set(check.tags).isdisjoint(tags)] + + for check in checks: + new_errors = check(app_configs=app_configs, databases=databases) + if not is_iterable(new_errors): + raise TypeError( + "The function %r did not return a list. All functions " + "registered with the checks registry must return a list." % check, + ) + errors.extend(new_errors) + return errors + + def tag_exists(self, tag, include_deployment_checks=False): + return tag in self.tags_available(include_deployment_checks) + + def tags_available(self, deployment_checks=False): + return set( + chain.from_iterable( + check.tags for check in self.get_checks(deployment_checks) + ) + ) + + def get_checks(self, include_deployment_checks=False): + checks = list(self.registered_checks) + if include_deployment_checks: + checks.extend(self.deployment_checks) + return checks + + +registry = CheckRegistry() +register = registry.register +run_checks = registry.run_checks +tag_exists = registry.tag_exists diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/security/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/security/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/security/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/security/base.py new file mode 100644 index 0000000..f85adab --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/security/base.py @@ -0,0 +1,283 @@ +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured + +from .. import Error, Tags, Warning, register + +CROSS_ORIGIN_OPENER_POLICY_VALUES = { + "same-origin", + "same-origin-allow-popups", + "unsafe-none", +} +REFERRER_POLICY_VALUES = { + "no-referrer", + "no-referrer-when-downgrade", + "origin", + "origin-when-cross-origin", + "same-origin", + "strict-origin", + "strict-origin-when-cross-origin", + "unsafe-url", +} + +SECRET_KEY_INSECURE_PREFIX = "django-insecure-" +SECRET_KEY_MIN_LENGTH = 50 +SECRET_KEY_MIN_UNIQUE_CHARACTERS = 5 + +SECRET_KEY_WARNING_MSG = ( + f"Your %s has less than {SECRET_KEY_MIN_LENGTH} characters, less than " + f"{SECRET_KEY_MIN_UNIQUE_CHARACTERS} unique characters, or it's prefixed " + f"with '{SECRET_KEY_INSECURE_PREFIX}' indicating that it was generated " + f"automatically by Django. Please generate a long and random value, " + f"otherwise many of Django's security-critical features will be " + f"vulnerable to attack." +) + +W001 = Warning( + "You do not have 'django.middleware.security.SecurityMiddleware' " + "in your MIDDLEWARE so the SECURE_HSTS_SECONDS, " + "SECURE_CONTENT_TYPE_NOSNIFF, SECURE_REFERRER_POLICY, " + "SECURE_CROSS_ORIGIN_OPENER_POLICY, and SECURE_SSL_REDIRECT settings will " + "have no effect.", + id="security.W001", +) + +W002 = Warning( + "You do not have " + "'django.middleware.clickjacking.XFrameOptionsMiddleware' in your " + "MIDDLEWARE, so your pages will not be served with an " + "'x-frame-options' header. Unless there is a good reason for your " + "site to be served in a frame, you should consider enabling this " + "header to help prevent clickjacking attacks.", + id="security.W002", +) + +W004 = Warning( + "You have not set a value for the SECURE_HSTS_SECONDS setting. " + "If your entire site is served only over SSL, you may want to consider " + "setting a value and enabling HTTP Strict Transport Security. " + "Be sure to read the documentation first; enabling HSTS carelessly " + "can cause serious, irreversible problems.", + id="security.W004", +) + +W005 = Warning( + "You have not set the SECURE_HSTS_INCLUDE_SUBDOMAINS setting to True. " + "Without this, your site is potentially vulnerable to attack " + "via an insecure connection to a subdomain. Only set this to True if " + "you are certain that all subdomains of your domain should be served " + "exclusively via SSL.", + id="security.W005", +) + +W006 = Warning( + "Your SECURE_CONTENT_TYPE_NOSNIFF setting is not set to True, " + "so your pages will not be served with an " + "'X-Content-Type-Options: nosniff' header. " + "You should consider enabling this header to prevent the " + "browser from identifying content types incorrectly.", + id="security.W006", +) + +W008 = Warning( + "Your SECURE_SSL_REDIRECT setting is not set to True. " + "Unless your site should be available over both SSL and non-SSL " + "connections, you may want to either set this setting True " + "or configure a load balancer or reverse-proxy server " + "to redirect all connections to HTTPS.", + id="security.W008", +) + +W009 = Warning( + SECRET_KEY_WARNING_MSG % "SECRET_KEY", + id="security.W009", +) + +W018 = Warning( + "You should not have DEBUG set to True in deployment.", + id="security.W018", +) + +W019 = Warning( + "You have " + "'django.middleware.clickjacking.XFrameOptionsMiddleware' in your " + "MIDDLEWARE, but X_FRAME_OPTIONS is not set to 'DENY'. " + "Unless there is a good reason for your site to serve other parts of " + "itself in a frame, you should change it to 'DENY'.", + id="security.W019", +) + +W020 = Warning( + "ALLOWED_HOSTS must not be empty in deployment.", + id="security.W020", +) + +W021 = Warning( + "You have not set the SECURE_HSTS_PRELOAD setting to True. Without this, " + "your site cannot be submitted to the browser preload list.", + id="security.W021", +) + +W022 = Warning( + "You have not set the SECURE_REFERRER_POLICY setting. Without this, your " + "site will not send a Referrer-Policy header. You should consider " + "enabling this header to protect user privacy.", + id="security.W022", +) + +E023 = Error( + "You have set the SECURE_REFERRER_POLICY setting to an invalid value.", + hint="Valid values are: {}.".format(", ".join(sorted(REFERRER_POLICY_VALUES))), + id="security.E023", +) + +E024 = Error( + "You have set the SECURE_CROSS_ORIGIN_OPENER_POLICY setting to an invalid " + "value.", + hint="Valid values are: {}.".format( + ", ".join(sorted(CROSS_ORIGIN_OPENER_POLICY_VALUES)), + ), + id="security.E024", +) + +W025 = Warning(SECRET_KEY_WARNING_MSG, id="security.W025") + + +def _security_middleware(): + return "django.middleware.security.SecurityMiddleware" in settings.MIDDLEWARE + + +def _xframe_middleware(): + return ( + "django.middleware.clickjacking.XFrameOptionsMiddleware" in settings.MIDDLEWARE + ) + + +@register(Tags.security, deploy=True) +def check_security_middleware(app_configs, **kwargs): + passed_check = _security_middleware() + return [] if passed_check else [W001] + + +@register(Tags.security, deploy=True) +def check_xframe_options_middleware(app_configs, **kwargs): + passed_check = _xframe_middleware() + return [] if passed_check else [W002] + + +@register(Tags.security, deploy=True) +def check_sts(app_configs, **kwargs): + passed_check = not _security_middleware() or settings.SECURE_HSTS_SECONDS + return [] if passed_check else [W004] + + +@register(Tags.security, deploy=True) +def check_sts_include_subdomains(app_configs, **kwargs): + passed_check = ( + not _security_middleware() + or not settings.SECURE_HSTS_SECONDS + or settings.SECURE_HSTS_INCLUDE_SUBDOMAINS is True + ) + return [] if passed_check else [W005] + + +@register(Tags.security, deploy=True) +def check_sts_preload(app_configs, **kwargs): + passed_check = ( + not _security_middleware() + or not settings.SECURE_HSTS_SECONDS + or settings.SECURE_HSTS_PRELOAD is True + ) + return [] if passed_check else [W021] + + +@register(Tags.security, deploy=True) +def check_content_type_nosniff(app_configs, **kwargs): + passed_check = ( + not _security_middleware() or settings.SECURE_CONTENT_TYPE_NOSNIFF is True + ) + return [] if passed_check else [W006] + + +@register(Tags.security, deploy=True) +def check_ssl_redirect(app_configs, **kwargs): + passed_check = not _security_middleware() or settings.SECURE_SSL_REDIRECT is True + return [] if passed_check else [W008] + + +def _check_secret_key(secret_key): + return ( + len(set(secret_key)) >= SECRET_KEY_MIN_UNIQUE_CHARACTERS + and len(secret_key) >= SECRET_KEY_MIN_LENGTH + and not secret_key.startswith(SECRET_KEY_INSECURE_PREFIX) + ) + + +@register(Tags.security, deploy=True) +def check_secret_key(app_configs, **kwargs): + try: + secret_key = settings.SECRET_KEY + except (ImproperlyConfigured, AttributeError): + passed_check = False + else: + passed_check = _check_secret_key(secret_key) + return [] if passed_check else [W009] + + +@register(Tags.security, deploy=True) +def check_secret_key_fallbacks(app_configs, **kwargs): + warnings = [] + try: + fallbacks = settings.SECRET_KEY_FALLBACKS + except (ImproperlyConfigured, AttributeError): + warnings.append(Warning(W025.msg % "SECRET_KEY_FALLBACKS", id=W025.id)) + else: + for index, key in enumerate(fallbacks): + if not _check_secret_key(key): + warnings.append( + Warning(W025.msg % f"SECRET_KEY_FALLBACKS[{index}]", id=W025.id) + ) + return warnings + + +@register(Tags.security, deploy=True) +def check_debug(app_configs, **kwargs): + passed_check = not settings.DEBUG + return [] if passed_check else [W018] + + +@register(Tags.security, deploy=True) +def check_xframe_deny(app_configs, **kwargs): + passed_check = not _xframe_middleware() or settings.X_FRAME_OPTIONS == "DENY" + return [] if passed_check else [W019] + + +@register(Tags.security, deploy=True) +def check_allowed_hosts(app_configs, **kwargs): + return [] if settings.ALLOWED_HOSTS else [W020] + + +@register(Tags.security, deploy=True) +def check_referrer_policy(app_configs, **kwargs): + if _security_middleware(): + if settings.SECURE_REFERRER_POLICY is None: + return [W022] + # Support a comma-separated string or iterable of values to allow fallback. + if isinstance(settings.SECURE_REFERRER_POLICY, str): + values = {v.strip() for v in settings.SECURE_REFERRER_POLICY.split(",")} + else: + values = set(settings.SECURE_REFERRER_POLICY) + if not values <= REFERRER_POLICY_VALUES: + return [E023] + return [] + + +@register(Tags.security, deploy=True) +def check_cross_origin_opener_policy(app_configs, **kwargs): + if ( + _security_middleware() + and settings.SECURE_CROSS_ORIGIN_OPENER_POLICY is not None + and settings.SECURE_CROSS_ORIGIN_OPENER_POLICY + not in CROSS_ORIGIN_OPENER_POLICY_VALUES + ): + return [E024] + return [] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/security/csrf.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/security/csrf.py new file mode 100644 index 0000000..d00f225 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/security/csrf.py @@ -0,0 +1,67 @@ +import inspect + +from django.conf import settings + +from .. import Error, Tags, Warning, register + +W003 = Warning( + "You don't appear to be using Django's built-in " + "cross-site request forgery protection via the middleware " + "('django.middleware.csrf.CsrfViewMiddleware' is not in your " + "MIDDLEWARE). Enabling the middleware is the safest approach " + "to ensure you don't leave any holes.", + id="security.W003", +) + +W016 = Warning( + "You have 'django.middleware.csrf.CsrfViewMiddleware' in your " + "MIDDLEWARE, but you have not set CSRF_COOKIE_SECURE to True. " + "Using a secure-only CSRF cookie makes it more difficult for network " + "traffic sniffers to steal the CSRF token.", + id="security.W016", +) + + +def _csrf_middleware(): + return "django.middleware.csrf.CsrfViewMiddleware" in settings.MIDDLEWARE + + +@register(Tags.security, deploy=True) +def check_csrf_middleware(app_configs, **kwargs): + passed_check = _csrf_middleware() + return [] if passed_check else [W003] + + +@register(Tags.security, deploy=True) +def check_csrf_cookie_secure(app_configs, **kwargs): + passed_check = ( + settings.CSRF_USE_SESSIONS + or not _csrf_middleware() + or settings.CSRF_COOKIE_SECURE is True + ) + return [] if passed_check else [W016] + + +@register(Tags.security) +def check_csrf_failure_view(app_configs, **kwargs): + from django.middleware.csrf import _get_failure_view + + errors = [] + try: + view = _get_failure_view() + except ImportError: + msg = ( + "The CSRF failure view '%s' could not be imported." + % settings.CSRF_FAILURE_VIEW + ) + errors.append(Error(msg, id="security.E102")) + else: + try: + inspect.signature(view).bind(None, reason=None) + except TypeError: + msg = ( + "The CSRF failure view '%s' does not take the correct number of " + "arguments." % settings.CSRF_FAILURE_VIEW + ) + errors.append(Error(msg, id="security.E101")) + return errors diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/security/sessions.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/security/sessions.py new file mode 100644 index 0000000..f317d09 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/security/sessions.py @@ -0,0 +1,99 @@ +from django.conf import settings + +from .. import Tags, Warning, register + + +def add_session_cookie_message(message): + return message + ( + " Using a secure-only session cookie makes it more difficult for " + "network traffic sniffers to hijack user sessions." + ) + + +W010 = Warning( + add_session_cookie_message( + "You have 'django.contrib.sessions' in your INSTALLED_APPS, " + "but you have not set SESSION_COOKIE_SECURE to True." + ), + id="security.W010", +) + +W011 = Warning( + add_session_cookie_message( + "You have 'django.contrib.sessions.middleware.SessionMiddleware' " + "in your MIDDLEWARE, but you have not set " + "SESSION_COOKIE_SECURE to True." + ), + id="security.W011", +) + +W012 = Warning( + add_session_cookie_message("SESSION_COOKIE_SECURE is not set to True."), + id="security.W012", +) + + +def add_httponly_message(message): + return message + ( + " Using an HttpOnly session cookie makes it more difficult for " + "cross-site scripting attacks to hijack user sessions." + ) + + +W013 = Warning( + add_httponly_message( + "You have 'django.contrib.sessions' in your INSTALLED_APPS, " + "but you have not set SESSION_COOKIE_HTTPONLY to True.", + ), + id="security.W013", +) + +W014 = Warning( + add_httponly_message( + "You have 'django.contrib.sessions.middleware.SessionMiddleware' " + "in your MIDDLEWARE, but you have not set " + "SESSION_COOKIE_HTTPONLY to True." + ), + id="security.W014", +) + +W015 = Warning( + add_httponly_message("SESSION_COOKIE_HTTPONLY is not set to True."), + id="security.W015", +) + + +@register(Tags.security, deploy=True) +def check_session_cookie_secure(app_configs, **kwargs): + if settings.SESSION_COOKIE_SECURE is True: + return [] + errors = [] + if _session_app(): + errors.append(W010) + if _session_middleware(): + errors.append(W011) + if len(errors) > 1: + errors = [W012] + return errors + + +@register(Tags.security, deploy=True) +def check_session_cookie_httponly(app_configs, **kwargs): + if settings.SESSION_COOKIE_HTTPONLY is True: + return [] + errors = [] + if _session_app(): + errors.append(W013) + if _session_middleware(): + errors.append(W014) + if len(errors) > 1: + errors = [W015] + return errors + + +def _session_middleware(): + return "django.contrib.sessions.middleware.SessionMiddleware" in settings.MIDDLEWARE + + +def _session_app(): + return "django.contrib.sessions" in settings.INSTALLED_APPS diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/templates.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/templates.py new file mode 100644 index 0000000..681aa1f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/templates.py @@ -0,0 +1,75 @@ +import copy +from collections import defaultdict + +from django.conf import settings +from django.template.backends.django import get_template_tag_modules + +from . import Error, Tags, Warning, register + +E001 = Error( + "You have 'APP_DIRS': True in your TEMPLATES but also specify 'loaders' " + "in OPTIONS. Either remove APP_DIRS or remove the 'loaders' option.", + id="templates.E001", +) +E002 = Error( + "'string_if_invalid' in TEMPLATES OPTIONS must be a string but got: {} ({}).", + id="templates.E002", +) +W003 = Warning( + "{} is used for multiple template tag modules: {}", + id="templates.E003", +) + + +@register(Tags.templates) +def check_setting_app_dirs_loaders(app_configs, **kwargs): + return ( + [E001] + if any( + conf.get("APP_DIRS") and "loaders" in conf.get("OPTIONS", {}) + for conf in settings.TEMPLATES + ) + else [] + ) + + +@register(Tags.templates) +def check_string_if_invalid_is_string(app_configs, **kwargs): + errors = [] + for conf in settings.TEMPLATES: + string_if_invalid = conf.get("OPTIONS", {}).get("string_if_invalid", "") + if not isinstance(string_if_invalid, str): + error = copy.copy(E002) + error.msg = error.msg.format( + string_if_invalid, type(string_if_invalid).__name__ + ) + errors.append(error) + return errors + + +@register(Tags.templates) +def check_for_template_tags_with_the_same_name(app_configs, **kwargs): + errors = [] + libraries = defaultdict(set) + + for conf in settings.TEMPLATES: + custom_libraries = conf.get("OPTIONS", {}).get("libraries", {}) + for module_name, module_path in custom_libraries.items(): + libraries[module_name].add(module_path) + + for module_name, module_path in get_template_tag_modules(): + libraries[module_name].add(module_path) + + for library_name, items in libraries.items(): + if len(items) > 1: + errors.append( + Warning( + W003.msg.format( + repr(library_name), + ", ".join(repr(item) for item in sorted(items)), + ), + id=W003.id, + ) + ) + + return errors diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/translation.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/translation.py new file mode 100644 index 0000000..214e970 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/translation.py @@ -0,0 +1,66 @@ +from django.conf import settings +from django.utils.translation import get_supported_language_variant +from django.utils.translation.trans_real import language_code_re + +from . import Error, Tags, register + +E001 = Error( + "You have provided an invalid value for the LANGUAGE_CODE setting: {!r}.", + id="translation.E001", +) + +E002 = Error( + "You have provided an invalid language code in the LANGUAGES setting: {!r}.", + id="translation.E002", +) + +E003 = Error( + "You have provided an invalid language code in the LANGUAGES_BIDI setting: {!r}.", + id="translation.E003", +) + +E004 = Error( + "You have provided a value for the LANGUAGE_CODE setting that is not in " + "the LANGUAGES setting.", + id="translation.E004", +) + + +@register(Tags.translation) +def check_setting_language_code(app_configs, **kwargs): + """Error if LANGUAGE_CODE setting is invalid.""" + tag = settings.LANGUAGE_CODE + if not isinstance(tag, str) or not language_code_re.match(tag): + return [Error(E001.msg.format(tag), id=E001.id)] + return [] + + +@register(Tags.translation) +def check_setting_languages(app_configs, **kwargs): + """Error if LANGUAGES setting is invalid.""" + return [ + Error(E002.msg.format(tag), id=E002.id) + for tag, _ in settings.LANGUAGES + if not isinstance(tag, str) or not language_code_re.match(tag) + ] + + +@register(Tags.translation) +def check_setting_languages_bidi(app_configs, **kwargs): + """Error if LANGUAGES_BIDI setting is invalid.""" + return [ + Error(E003.msg.format(tag), id=E003.id) + for tag in settings.LANGUAGES_BIDI + if not isinstance(tag, str) or not language_code_re.match(tag) + ] + + +@register(Tags.translation) +def check_language_settings_consistent(app_configs, **kwargs): + """Error if language settings are not consistent with each other.""" + try: + get_supported_language_variant(settings.LANGUAGE_CODE) + except LookupError: + return [E004] + else: + return [] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/urls.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/urls.py new file mode 100644 index 0000000..34eff96 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/checks/urls.py @@ -0,0 +1,117 @@ +from collections import Counter + +from django.conf import settings + +from . import Error, Tags, Warning, register + + +@register(Tags.urls) +def check_url_config(app_configs, **kwargs): + if getattr(settings, "ROOT_URLCONF", None): + from django.urls import get_resolver + + resolver = get_resolver() + return check_resolver(resolver) + return [] + + +def check_resolver(resolver): + """ + Recursively check the resolver. + """ + check_method = getattr(resolver, "check", None) + if check_method is not None: + return check_method() + elif not hasattr(resolver, "resolve"): + return get_warning_for_invalid_pattern(resolver) + else: + return [] + + +@register(Tags.urls) +def check_url_namespaces_unique(app_configs, **kwargs): + """ + Warn if URL namespaces used in applications aren't unique. + """ + if not getattr(settings, "ROOT_URLCONF", None): + return [] + + from django.urls import get_resolver + + resolver = get_resolver() + all_namespaces = _load_all_namespaces(resolver) + counter = Counter(all_namespaces) + non_unique_namespaces = [n for n, count in counter.items() if count > 1] + errors = [] + for namespace in non_unique_namespaces: + errors.append( + Warning( + "URL namespace '{}' isn't unique. You may not be able to reverse " + "all URLs in this namespace".format(namespace), + id="urls.W005", + ) + ) + return errors + + +def _load_all_namespaces(resolver, parents=()): + """ + Recursively load all namespaces from URL patterns. + """ + url_patterns = getattr(resolver, "url_patterns", []) + namespaces = [ + ":".join(parents + (url.namespace,)) + for url in url_patterns + if getattr(url, "namespace", None) is not None + ] + for pattern in url_patterns: + namespace = getattr(pattern, "namespace", None) + current = parents + if namespace is not None: + current += (namespace,) + namespaces.extend(_load_all_namespaces(pattern, current)) + return namespaces + + +def get_warning_for_invalid_pattern(pattern): + """ + Return a list containing a warning that the pattern is invalid. + + describe_pattern() cannot be used here, because we cannot rely on the + urlpattern having regex or name attributes. + """ + if isinstance(pattern, str): + hint = ( + "Try removing the string '{}'. The list of urlpatterns should not " + "have a prefix string as the first element.".format(pattern) + ) + elif isinstance(pattern, tuple): + hint = "Try using path() instead of a tuple." + else: + hint = None + + return [ + Error( + "Your URL pattern {!r} is invalid. Ensure that urlpatterns is a list " + "of path() and/or re_path() instances.".format(pattern), + hint=hint, + id="urls.E004", + ) + ] + + +@register(Tags.urls) +def check_url_settings(app_configs, **kwargs): + errors = [] + for name in ("STATIC_URL", "MEDIA_URL"): + value = getattr(settings, name) + if value and not value.endswith("/"): + errors.append(E006(name)) + return errors + + +def E006(name): + return Error( + "The {} setting must end with a slash.".format(name), + id="urls.E006", + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/exceptions.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/exceptions.py new file mode 100644 index 0000000..2a2288f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/exceptions.py @@ -0,0 +1,254 @@ +""" +Global Django exception and warning classes. +""" +import operator + +from django.utils.hashable import make_hashable + + +class FieldDoesNotExist(Exception): + """The requested model field does not exist""" + + pass + + +class AppRegistryNotReady(Exception): + """The django.apps registry is not populated yet""" + + pass + + +class ObjectDoesNotExist(Exception): + """The requested object does not exist""" + + silent_variable_failure = True + + +class MultipleObjectsReturned(Exception): + """The query returned multiple objects when only one was expected.""" + + pass + + +class SuspiciousOperation(Exception): + """The user did something suspicious""" + + +class SuspiciousMultipartForm(SuspiciousOperation): + """Suspect MIME request in multipart form data""" + + pass + + +class SuspiciousFileOperation(SuspiciousOperation): + """A Suspicious filesystem operation was attempted""" + + pass + + +class DisallowedHost(SuspiciousOperation): + """HTTP_HOST header contains invalid value""" + + pass + + +class DisallowedRedirect(SuspiciousOperation): + """Redirect to scheme not in allowed list""" + + pass + + +class TooManyFieldsSent(SuspiciousOperation): + """ + The number of fields in a GET or POST request exceeded + settings.DATA_UPLOAD_MAX_NUMBER_FIELDS. + """ + + pass + + +class TooManyFilesSent(SuspiciousOperation): + """ + The number of fields in a GET or POST request exceeded + settings.DATA_UPLOAD_MAX_NUMBER_FILES. + """ + + pass + + +class RequestDataTooBig(SuspiciousOperation): + """ + The size of the request (excluding any file uploads) exceeded + settings.DATA_UPLOAD_MAX_MEMORY_SIZE. + """ + + pass + + +class RequestAborted(Exception): + """The request was closed before it was completed, or timed out.""" + + pass + + +class BadRequest(Exception): + """The request is malformed and cannot be processed.""" + + pass + + +class PermissionDenied(Exception): + """The user did not have permission to do that""" + + pass + + +class ViewDoesNotExist(Exception): + """The requested view does not exist""" + + pass + + +class MiddlewareNotUsed(Exception): + """This middleware is not used in this server configuration""" + + pass + + +class ImproperlyConfigured(Exception): + """Django is somehow improperly configured""" + + pass + + +class FieldError(Exception): + """Some kind of problem with a model field.""" + + pass + + +NON_FIELD_ERRORS = "__all__" + + +class ValidationError(Exception): + """An error while validating data.""" + + def __init__(self, message, code=None, params=None): + """ + The `message` argument can be a single error, a list of errors, or a + dictionary that maps field names to lists of errors. What we define as + an "error" can be either a simple string or an instance of + ValidationError with its message attribute set, and what we define as + list or dictionary can be an actual `list` or `dict` or an instance + of ValidationError with its `error_list` or `error_dict` attribute set. + """ + super().__init__(message, code, params) + + if isinstance(message, ValidationError): + if hasattr(message, "error_dict"): + message = message.error_dict + elif not hasattr(message, "message"): + message = message.error_list + else: + message, code, params = message.message, message.code, message.params + + if isinstance(message, dict): + self.error_dict = {} + for field, messages in message.items(): + if not isinstance(messages, ValidationError): + messages = ValidationError(messages) + self.error_dict[field] = messages.error_list + + elif isinstance(message, list): + self.error_list = [] + for message in message: + # Normalize plain strings to instances of ValidationError. + if not isinstance(message, ValidationError): + message = ValidationError(message) + if hasattr(message, "error_dict"): + self.error_list.extend(sum(message.error_dict.values(), [])) + else: + self.error_list.extend(message.error_list) + + else: + self.message = message + self.code = code + self.params = params + self.error_list = [self] + + @property + def message_dict(self): + # Trigger an AttributeError if this ValidationError + # doesn't have an error_dict. + getattr(self, "error_dict") + + return dict(self) + + @property + def messages(self): + if hasattr(self, "error_dict"): + return sum(dict(self).values(), []) + return list(self) + + def update_error_dict(self, error_dict): + if hasattr(self, "error_dict"): + for field, error_list in self.error_dict.items(): + error_dict.setdefault(field, []).extend(error_list) + else: + error_dict.setdefault(NON_FIELD_ERRORS, []).extend(self.error_list) + return error_dict + + def __iter__(self): + if hasattr(self, "error_dict"): + for field, errors in self.error_dict.items(): + yield field, list(ValidationError(errors)) + else: + for error in self.error_list: + message = error.message + if error.params: + message %= error.params + yield str(message) + + def __str__(self): + if hasattr(self, "error_dict"): + return repr(dict(self)) + return repr(list(self)) + + def __repr__(self): + return "ValidationError(%s)" % self + + def __eq__(self, other): + if not isinstance(other, ValidationError): + return NotImplemented + return hash(self) == hash(other) + + def __hash__(self): + if hasattr(self, "message"): + return hash( + ( + self.message, + self.code, + make_hashable(self.params), + ) + ) + if hasattr(self, "error_dict"): + return hash(make_hashable(self.error_dict)) + return hash(tuple(sorted(self.error_list, key=operator.attrgetter("message")))) + + +class EmptyResultSet(Exception): + """A database query predicate is impossible.""" + + pass + + +class FullResultSet(Exception): + """A database query predicate is matches everything.""" + + pass + + +class SynchronousOnlyOperation(Exception): + """The user tried to call a sync-only function from an async context.""" + + pass diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/__init__.py new file mode 100644 index 0000000..d046aca --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/__init__.py @@ -0,0 +1,3 @@ +from django.core.files.base import File + +__all__ = ["File"] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/base.py new file mode 100644 index 0000000..9682467 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/base.py @@ -0,0 +1,161 @@ +import os +from io import BytesIO, StringIO, UnsupportedOperation + +from django.core.files.utils import FileProxyMixin +from django.utils.functional import cached_property + + +class File(FileProxyMixin): + DEFAULT_CHUNK_SIZE = 64 * 2**10 + + def __init__(self, file, name=None): + self.file = file + if name is None: + name = getattr(file, "name", None) + self.name = name + if hasattr(file, "mode"): + self.mode = file.mode + + def __str__(self): + return self.name or "" + + def __repr__(self): + return "<%s: %s>" % (self.__class__.__name__, self or "None") + + def __bool__(self): + return bool(self.name) + + def __len__(self): + return self.size + + @cached_property + def size(self): + if hasattr(self.file, "size"): + return self.file.size + if hasattr(self.file, "name"): + try: + return os.path.getsize(self.file.name) + except (OSError, TypeError): + pass + if hasattr(self.file, "tell") and hasattr(self.file, "seek"): + pos = self.file.tell() + self.file.seek(0, os.SEEK_END) + size = self.file.tell() + self.file.seek(pos) + return size + raise AttributeError("Unable to determine the file's size.") + + def chunks(self, chunk_size=None): + """ + Read the file and yield chunks of ``chunk_size`` bytes (defaults to + ``File.DEFAULT_CHUNK_SIZE``). + """ + chunk_size = chunk_size or self.DEFAULT_CHUNK_SIZE + try: + self.seek(0) + except (AttributeError, UnsupportedOperation): + pass + + while True: + data = self.read(chunk_size) + if not data: + break + yield data + + def multiple_chunks(self, chunk_size=None): + """ + Return ``True`` if you can expect multiple chunks. + + NB: If a particular file representation is in memory, subclasses should + always return ``False`` -- there's no good reason to read from memory in + chunks. + """ + return self.size > (chunk_size or self.DEFAULT_CHUNK_SIZE) + + def __iter__(self): + # Iterate over this file-like object by newlines + buffer_ = None + for chunk in self.chunks(): + for line in chunk.splitlines(True): + if buffer_: + if endswith_cr(buffer_) and not equals_lf(line): + # Line split after a \r newline; yield buffer_. + yield buffer_ + # Continue with line. + else: + # Line either split without a newline (line + # continues after buffer_) or with \r\n + # newline (line == b'\n'). + line = buffer_ + line + # buffer_ handled, clear it. + buffer_ = None + + # If this is the end of a \n or \r\n line, yield. + if endswith_lf(line): + yield line + else: + buffer_ = line + + if buffer_ is not None: + yield buffer_ + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, tb): + self.close() + + def open(self, mode=None, *args, **kwargs): + if not self.closed: + self.seek(0) + elif self.name and os.path.exists(self.name): + self.file = open(self.name, mode or self.mode, *args, **kwargs) + else: + raise ValueError("The file cannot be reopened.") + return self + + def close(self): + self.file.close() + + +class ContentFile(File): + """ + A File-like object that takes just raw content, rather than an actual file. + """ + + def __init__(self, content, name=None): + stream_class = StringIO if isinstance(content, str) else BytesIO + super().__init__(stream_class(content), name=name) + self.size = len(content) + + def __str__(self): + return "Raw content" + + def __bool__(self): + return True + + def open(self, mode=None): + self.seek(0) + return self + + def close(self): + pass + + def write(self, data): + self.__dict__.pop("size", None) # Clear the computed size. + return self.file.write(data) + + +def endswith_cr(line): + """Return True if line (a text or bytestring) ends with '\r'.""" + return line.endswith("\r" if isinstance(line, str) else b"\r") + + +def endswith_lf(line): + """Return True if line (a text or bytestring) ends with '\n'.""" + return line.endswith("\n" if isinstance(line, str) else b"\n") + + +def equals_lf(line): + """Return True if line (a text or bytestring) equals '\n'.""" + return line == ("\n" if isinstance(line, str) else b"\n") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/images.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/images.py new file mode 100644 index 0000000..6a603f2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/images.py @@ -0,0 +1,88 @@ +""" +Utility functions for handling images. + +Requires Pillow as you might imagine. +""" +import struct +import zlib + +from django.core.files import File + + +class ImageFile(File): + """ + A mixin for use alongside django.core.files.base.File, which provides + additional features for dealing with images. + """ + + @property + def width(self): + return self._get_image_dimensions()[0] + + @property + def height(self): + return self._get_image_dimensions()[1] + + def _get_image_dimensions(self): + if not hasattr(self, "_dimensions_cache"): + close = self.closed + self.open() + self._dimensions_cache = get_image_dimensions(self, close=close) + return self._dimensions_cache + + +def get_image_dimensions(file_or_path, close=False): + """ + Return the (width, height) of an image, given an open file or a path. Set + 'close' to True to close the file at the end if it is initially in an open + state. + """ + from PIL import ImageFile as PillowImageFile + + p = PillowImageFile.Parser() + if hasattr(file_or_path, "read"): + file = file_or_path + file_pos = file.tell() + file.seek(0) + else: + try: + file = open(file_or_path, "rb") + except OSError: + return (None, None) + close = True + try: + # Most of the time Pillow only needs a small chunk to parse the image + # and get the dimensions, but with some TIFF files Pillow needs to + # parse the whole file. + chunk_size = 1024 + while 1: + data = file.read(chunk_size) + if not data: + break + try: + p.feed(data) + except zlib.error as e: + # ignore zlib complaining on truncated stream, just feed more + # data to parser (ticket #19457). + if e.args[0].startswith("Error -5"): + pass + else: + raise + except struct.error: + # Ignore PIL failing on a too short buffer when reads return + # less bytes than expected. Skip and feed more data to the + # parser (ticket #24544). + pass + except RuntimeError: + # e.g. "RuntimeError: could not create decoder object" for + # WebP files. A different chunk_size may work. + pass + if p.image: + return p.image.size + chunk_size *= 2 + return (None, None) + finally: + if close: + file.close() + else: + file.seek(file_pos) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/locks.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/locks.py new file mode 100644 index 0000000..c0f471f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/locks.py @@ -0,0 +1,127 @@ +""" +Portable file locking utilities. + +Based partially on an example by Jonathan Feignberg in the Python +Cookbook [1] (licensed under the Python Software License) and a ctypes port by +Anatoly Techtonik for Roundup [2] (license [3]). + +[1] https://code.activestate.com/recipes/65203/ +[2] https://sourceforge.net/p/roundup/code/ci/default/tree/roundup/backends/portalocker.py # NOQA +[3] https://sourceforge.net/p/roundup/code/ci/default/tree/COPYING.txt + +Example Usage:: + + >>> from django.core.files import locks + >>> with open('./file', 'wb') as f: + ... locks.lock(f, locks.LOCK_EX) + ... f.write('Django') +""" +import os + +__all__ = ("LOCK_EX", "LOCK_SH", "LOCK_NB", "lock", "unlock") + + +def _fd(f): + """Get a filedescriptor from something which could be a file or an fd.""" + return f.fileno() if hasattr(f, "fileno") else f + + +if os.name == "nt": + import msvcrt + from ctypes import ( + POINTER, + Structure, + Union, + WinDLL, + byref, + c_int64, + c_ulong, + c_void_p, + sizeof, + ) + from ctypes.wintypes import BOOL, DWORD, HANDLE + + LOCK_SH = 0 # the default + LOCK_NB = 0x1 # LOCKFILE_FAIL_IMMEDIATELY + LOCK_EX = 0x2 # LOCKFILE_EXCLUSIVE_LOCK + + # --- Adapted from the pyserial project --- + # detect size of ULONG_PTR + if sizeof(c_ulong) != sizeof(c_void_p): + ULONG_PTR = c_int64 + else: + ULONG_PTR = c_ulong + PVOID = c_void_p + + # --- Union inside Structure by stackoverflow:3480240 --- + class _OFFSET(Structure): + _fields_ = [("Offset", DWORD), ("OffsetHigh", DWORD)] + + class _OFFSET_UNION(Union): + _anonymous_ = ["_offset"] + _fields_ = [("_offset", _OFFSET), ("Pointer", PVOID)] + + class OVERLAPPED(Structure): + _anonymous_ = ["_offset_union"] + _fields_ = [ + ("Internal", ULONG_PTR), + ("InternalHigh", ULONG_PTR), + ("_offset_union", _OFFSET_UNION), + ("hEvent", HANDLE), + ] + + LPOVERLAPPED = POINTER(OVERLAPPED) + + # --- Define function prototypes for extra safety --- + kernel32 = WinDLL("kernel32") + LockFileEx = kernel32.LockFileEx + LockFileEx.restype = BOOL + LockFileEx.argtypes = [HANDLE, DWORD, DWORD, DWORD, DWORD, LPOVERLAPPED] + UnlockFileEx = kernel32.UnlockFileEx + UnlockFileEx.restype = BOOL + UnlockFileEx.argtypes = [HANDLE, DWORD, DWORD, DWORD, LPOVERLAPPED] + + def lock(f, flags): + hfile = msvcrt.get_osfhandle(_fd(f)) + overlapped = OVERLAPPED() + ret = LockFileEx(hfile, flags, 0, 0, 0xFFFF0000, byref(overlapped)) + return bool(ret) + + def unlock(f): + hfile = msvcrt.get_osfhandle(_fd(f)) + overlapped = OVERLAPPED() + ret = UnlockFileEx(hfile, 0, 0, 0xFFFF0000, byref(overlapped)) + return bool(ret) + +else: + try: + import fcntl + + LOCK_SH = fcntl.LOCK_SH # shared lock + LOCK_NB = fcntl.LOCK_NB # non-blocking + LOCK_EX = fcntl.LOCK_EX + except (ImportError, AttributeError): + # File locking is not supported. + LOCK_EX = LOCK_SH = LOCK_NB = 0 + + # Dummy functions that don't do anything. + def lock(f, flags): + # File is not locked + return False + + def unlock(f): + # File is unlocked + return True + + else: + + def lock(f, flags): + try: + fcntl.flock(_fd(f), flags) + return True + except BlockingIOError: + return False + + def unlock(f): + fcntl.flock(_fd(f), fcntl.LOCK_UN) + return True diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/move.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/move.py new file mode 100644 index 0000000..95d69f9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/move.py @@ -0,0 +1,102 @@ +""" +Move a file in the safest way possible:: + + >>> from django.core.files.move import file_move_safe + >>> file_move_safe("/tmp/old_file", "/tmp/new_file") +""" + +import os +from shutil import copymode, copystat + +from django.core.files import locks + +__all__ = ["file_move_safe"] + + +def _samefile(src, dst): + # Macintosh, Unix. + if hasattr(os.path, "samefile"): + try: + return os.path.samefile(src, dst) + except OSError: + return False + + # All other platforms: check for same pathname. + return os.path.normcase(os.path.abspath(src)) == os.path.normcase( + os.path.abspath(dst) + ) + + +def file_move_safe( + old_file_name, new_file_name, chunk_size=1024 * 64, allow_overwrite=False +): + """ + Move a file from one location to another in the safest way possible. + + First, try ``os.rename``, which is simple but will break across filesystems. + If that fails, stream manually from one file to another in pure Python. + + If the destination file exists and ``allow_overwrite`` is ``False``, raise + ``FileExistsError``. + """ + # There's no reason to move if we don't have to. + if _samefile(old_file_name, new_file_name): + return + + try: + if not allow_overwrite and os.access(new_file_name, os.F_OK): + raise FileExistsError( + "Destination file %s exists and allow_overwrite is False." + % new_file_name + ) + + os.rename(old_file_name, new_file_name) + return + except OSError: + # OSError happens with os.rename() if moving to another filesystem or + # when moving opened files on certain operating systems. + pass + + # first open the old file, so that it won't go away + with open(old_file_name, "rb") as old_file: + # now open the new file, not forgetting allow_overwrite + fd = os.open( + new_file_name, + ( + os.O_WRONLY + | os.O_CREAT + | getattr(os, "O_BINARY", 0) + | (os.O_EXCL if not allow_overwrite else 0) + ), + ) + try: + locks.lock(fd, locks.LOCK_EX) + current_chunk = None + while current_chunk != b"": + current_chunk = old_file.read(chunk_size) + os.write(fd, current_chunk) + finally: + locks.unlock(fd) + os.close(fd) + + try: + copystat(old_file_name, new_file_name) + except PermissionError: + # Certain filesystems (e.g. CIFS) fail to copy the file's metadata if + # the type of the destination filesystem isn't the same as the source + # filesystem. This also happens with some SELinux-enabled systems. + # Ignore that, but try to set basic permissions. + try: + copymode(old_file_name, new_file_name) + except PermissionError: + pass + + try: + os.remove(old_file_name) + except PermissionError as e: + # Certain operating systems (Cygwin and Windows) + # fail when deleting opened files, ignore it. (For the + # systems where this happens, temporary files will be auto-deleted + # on close anyway.) + if getattr(e, "winerror", 0) != 32: + raise diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/storage/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/storage/__init__.py new file mode 100644 index 0000000..d061d93 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/storage/__init__.py @@ -0,0 +1,46 @@ +import warnings + +from django.conf import DEFAULT_STORAGE_ALIAS, settings +from django.utils.deprecation import RemovedInDjango51Warning +from django.utils.functional import LazyObject +from django.utils.module_loading import import_string + +from .base import Storage +from .filesystem import FileSystemStorage +from .handler import InvalidStorageError, StorageHandler +from .memory import InMemoryStorage + +__all__ = ( + "FileSystemStorage", + "InMemoryStorage", + "Storage", + "DefaultStorage", + "default_storage", + "get_storage_class", + "InvalidStorageError", + "StorageHandler", + "storages", +) + +GET_STORAGE_CLASS_DEPRECATED_MSG = ( + "django.core.files.storage.get_storage_class is deprecated in favor of " + "using django.core.files.storage.storages." +) + + +def get_storage_class(import_path=None): + warnings.warn( + GET_STORAGE_CLASS_DEPRECATED_MSG, + RemovedInDjango51Warning, + stacklevel=2, + ) + return import_string(import_path or settings.DEFAULT_FILE_STORAGE) + + +class DefaultStorage(LazyObject): + def _setup(self): + self._wrapped = storages[DEFAULT_STORAGE_ALIAS] + + +storages = StorageHandler() +default_storage = DefaultStorage() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/storage/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/storage/base.py new file mode 100644 index 0000000..16ac22f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/storage/base.py @@ -0,0 +1,190 @@ +import os +import pathlib + +from django.core.exceptions import SuspiciousFileOperation +from django.core.files import File +from django.core.files.utils import validate_file_name +from django.utils.crypto import get_random_string +from django.utils.text import get_valid_filename + + +class Storage: + """ + A base storage class, providing some default behaviors that all other + storage systems can inherit or override, as necessary. + """ + + # The following methods represent a public interface to private methods. + # These shouldn't be overridden by subclasses unless absolutely necessary. + + def open(self, name, mode="rb"): + """Retrieve the specified file from storage.""" + return self._open(name, mode) + + def save(self, name, content, max_length=None): + """ + Save new content to the file specified by name. The content should be + a proper File object or any Python file-like object, ready to be read + from the beginning. + """ + # Get the proper name for the file, as it will actually be saved. + if name is None: + name = content.name + + if not hasattr(content, "chunks"): + content = File(content, name) + + name = self.get_available_name(name, max_length=max_length) + name = self._save(name, content) + # Ensure that the name returned from the storage system is still valid. + validate_file_name(name, allow_relative_path=True) + return name + + # These methods are part of the public API, with default implementations. + + def get_valid_name(self, name): + """ + Return a filename, based on the provided filename, that's suitable for + use in the target storage system. + """ + return get_valid_filename(name) + + def get_alternative_name(self, file_root, file_ext): + """ + Return an alternative filename, by adding an underscore and a random 7 + character alphanumeric string (before the file extension, if one + exists) to the filename. + """ + return "%s_%s%s" % (file_root, get_random_string(7), file_ext) + + def get_available_name(self, name, max_length=None): + """ + Return a filename that's free on the target storage system and + available for new content to be written to. + """ + name = str(name).replace("\\", "/") + dir_name, file_name = os.path.split(name) + if ".." in pathlib.PurePath(dir_name).parts: + raise SuspiciousFileOperation( + "Detected path traversal attempt in '%s'" % dir_name + ) + validate_file_name(file_name) + file_root, file_ext = os.path.splitext(file_name) + # If the filename already exists, generate an alternative filename + # until it doesn't exist. + # Truncate original name if required, so the new filename does not + # exceed the max_length. + while self.exists(name) or (max_length and len(name) > max_length): + # file_ext includes the dot. + name = os.path.join( + dir_name, self.get_alternative_name(file_root, file_ext) + ) + if max_length is None: + continue + # Truncate file_root if max_length exceeded. + truncation = len(name) - max_length + if truncation > 0: + file_root = file_root[:-truncation] + # Entire file_root was truncated in attempt to find an + # available filename. + if not file_root: + raise SuspiciousFileOperation( + 'Storage can not find an available filename for "%s". ' + "Please make sure that the corresponding file field " + 'allows sufficient "max_length".' % name + ) + name = os.path.join( + dir_name, self.get_alternative_name(file_root, file_ext) + ) + return name + + def generate_filename(self, filename): + """ + Validate the filename by calling get_valid_name() and return a filename + to be passed to the save() method. + """ + filename = str(filename).replace("\\", "/") + # `filename` may include a path as returned by FileField.upload_to. + dirname, filename = os.path.split(filename) + if ".." in pathlib.PurePath(dirname).parts: + raise SuspiciousFileOperation( + "Detected path traversal attempt in '%s'" % dirname + ) + return os.path.normpath(os.path.join(dirname, self.get_valid_name(filename))) + + def path(self, name): + """ + Return a local filesystem path where the file can be retrieved using + Python's built-in open() function. Storage systems that can't be + accessed using open() should *not* implement this method. + """ + raise NotImplementedError("This backend doesn't support absolute paths.") + + # The following methods form the public API for storage systems, but with + # no default implementations. Subclasses must implement *all* of these. + + def delete(self, name): + """ + Delete the specified file from the storage system. + """ + raise NotImplementedError( + "subclasses of Storage must provide a delete() method" + ) + + def exists(self, name): + """ + Return True if a file referenced by the given name already exists in the + storage system, or False if the name is available for a new file. + """ + raise NotImplementedError( + "subclasses of Storage must provide an exists() method" + ) + + def listdir(self, path): + """ + List the contents of the specified path. Return a 2-tuple of lists: + the first item being directories, the second item being files. + """ + raise NotImplementedError( + "subclasses of Storage must provide a listdir() method" + ) + + def size(self, name): + """ + Return the total size, in bytes, of the file specified by name. + """ + raise NotImplementedError("subclasses of Storage must provide a size() method") + + def url(self, name): + """ + Return an absolute URL where the file's contents can be accessed + directly by a web browser. + """ + raise NotImplementedError("subclasses of Storage must provide a url() method") + + def get_accessed_time(self, name): + """ + Return the last accessed time (as a datetime) of the file specified by + name. The datetime will be timezone-aware if USE_TZ=True. + """ + raise NotImplementedError( + "subclasses of Storage must provide a get_accessed_time() method" + ) + + def get_created_time(self, name): + """ + Return the creation time (as a datetime) of the file specified by name. + The datetime will be timezone-aware if USE_TZ=True. + """ + raise NotImplementedError( + "subclasses of Storage must provide a get_created_time() method" + ) + + def get_modified_time(self, name): + """ + Return the last modified time (as a datetime) of the file specified by + name. The datetime will be timezone-aware if USE_TZ=True. + """ + raise NotImplementedError( + "subclasses of Storage must provide a get_modified_time() method" + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/storage/filesystem.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/storage/filesystem.py new file mode 100644 index 0000000..85fc4ef --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/storage/filesystem.py @@ -0,0 +1,207 @@ +import os +from datetime import datetime, timezone +from urllib.parse import urljoin + +from django.conf import settings +from django.core.files import File, locks +from django.core.files.move import file_move_safe +from django.core.signals import setting_changed +from django.utils._os import safe_join +from django.utils.deconstruct import deconstructible +from django.utils.encoding import filepath_to_uri +from django.utils.functional import cached_property + +from .base import Storage +from .mixins import StorageSettingsMixin + + +@deconstructible(path="django.core.files.storage.FileSystemStorage") +class FileSystemStorage(Storage, StorageSettingsMixin): + """ + Standard filesystem storage + """ + + # The combination of O_CREAT and O_EXCL makes os.open() raise OSError if + # the file already exists before it's opened. + OS_OPEN_FLAGS = os.O_WRONLY | os.O_CREAT | os.O_EXCL | getattr(os, "O_BINARY", 0) + + def __init__( + self, + location=None, + base_url=None, + file_permissions_mode=None, + directory_permissions_mode=None, + ): + self._location = location + self._base_url = base_url + self._file_permissions_mode = file_permissions_mode + self._directory_permissions_mode = directory_permissions_mode + setting_changed.connect(self._clear_cached_properties) + + @cached_property + def base_location(self): + return self._value_or_setting(self._location, settings.MEDIA_ROOT) + + @cached_property + def location(self): + return os.path.abspath(self.base_location) + + @cached_property + def base_url(self): + if self._base_url is not None and not self._base_url.endswith("/"): + self._base_url += "/" + return self._value_or_setting(self._base_url, settings.MEDIA_URL) + + @cached_property + def file_permissions_mode(self): + return self._value_or_setting( + self._file_permissions_mode, settings.FILE_UPLOAD_PERMISSIONS + ) + + @cached_property + def directory_permissions_mode(self): + return self._value_or_setting( + self._directory_permissions_mode, settings.FILE_UPLOAD_DIRECTORY_PERMISSIONS + ) + + def _open(self, name, mode="rb"): + return File(open(self.path(name), mode)) + + def _save(self, name, content): + full_path = self.path(name) + + # Create any intermediate directories that do not exist. + directory = os.path.dirname(full_path) + try: + if self.directory_permissions_mode is not None: + # Set the umask because os.makedirs() doesn't apply the "mode" + # argument to intermediate-level directories. + old_umask = os.umask(0o777 & ~self.directory_permissions_mode) + try: + os.makedirs( + directory, self.directory_permissions_mode, exist_ok=True + ) + finally: + os.umask(old_umask) + else: + os.makedirs(directory, exist_ok=True) + except FileExistsError: + raise FileExistsError("%s exists and is not a directory." % directory) + + # There's a potential race condition between get_available_name and + # saving the file; it's possible that two threads might return the + # same name, at which point all sorts of fun happens. So we need to + # try to create the file, but if it already exists we have to go back + # to get_available_name() and try again. + + while True: + try: + # This file has a file path that we can move. + if hasattr(content, "temporary_file_path"): + file_move_safe(content.temporary_file_path(), full_path) + + # This is a normal uploadedfile that we can stream. + else: + # The current umask value is masked out by os.open! + fd = os.open(full_path, self.OS_OPEN_FLAGS, 0o666) + _file = None + try: + locks.lock(fd, locks.LOCK_EX) + for chunk in content.chunks(): + if _file is None: + mode = "wb" if isinstance(chunk, bytes) else "wt" + _file = os.fdopen(fd, mode) + _file.write(chunk) + finally: + locks.unlock(fd) + if _file is not None: + _file.close() + else: + os.close(fd) + except FileExistsError: + # A new name is needed if the file exists. + name = self.get_available_name(name) + full_path = self.path(name) + else: + # OK, the file save worked. Break out of the loop. + break + + if self.file_permissions_mode is not None: + os.chmod(full_path, self.file_permissions_mode) + + # Ensure the saved path is always relative to the storage root. + name = os.path.relpath(full_path, self.location) + # Ensure the moved file has the same gid as the storage root. + self._ensure_location_group_id(full_path) + # Store filenames with forward slashes, even on Windows. + return str(name).replace("\\", "/") + + def _ensure_location_group_id(self, full_path): + if os.name == "posix": + file_gid = os.stat(full_path).st_gid + location_gid = os.stat(self.location).st_gid + if file_gid != location_gid: + try: + os.chown(full_path, uid=-1, gid=location_gid) + except PermissionError: + pass + + def delete(self, name): + if not name: + raise ValueError("The name must be given to delete().") + name = self.path(name) + # If the file or directory exists, delete it from the filesystem. + try: + if os.path.isdir(name): + os.rmdir(name) + else: + os.remove(name) + except FileNotFoundError: + # FileNotFoundError is raised if the file or directory was removed + # concurrently. + pass + + def exists(self, name): + return os.path.lexists(self.path(name)) + + def listdir(self, path): + path = self.path(path) + directories, files = [], [] + with os.scandir(path) as entries: + for entry in entries: + if entry.is_dir(): + directories.append(entry.name) + else: + files.append(entry.name) + return directories, files + + def path(self, name): + return safe_join(self.location, name) + + def size(self, name): + return os.path.getsize(self.path(name)) + + def url(self, name): + if self.base_url is None: + raise ValueError("This file is not accessible via a URL.") + url = filepath_to_uri(name) + if url is not None: + url = url.lstrip("/") + return urljoin(self.base_url, url) + + def _datetime_from_timestamp(self, ts): + """ + If timezone support is enabled, make an aware datetime object in UTC; + otherwise make a naive one in the local timezone. + """ + tz = timezone.utc if settings.USE_TZ else None + return datetime.fromtimestamp(ts, tz=tz) + + def get_accessed_time(self, name): + return self._datetime_from_timestamp(os.path.getatime(self.path(name))) + + def get_created_time(self, name): + return self._datetime_from_timestamp(os.path.getctime(self.path(name))) + + def get_modified_time(self, name): + return self._datetime_from_timestamp(os.path.getmtime(self.path(name))) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/storage/handler.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/storage/handler.py new file mode 100644 index 0000000..ad2054c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/storage/handler.py @@ -0,0 +1,55 @@ +from django.conf import DEFAULT_STORAGE_ALIAS, STATICFILES_STORAGE_ALIAS, settings +from django.core.exceptions import ImproperlyConfigured +from django.utils.functional import cached_property +from django.utils.module_loading import import_string + + +class InvalidStorageError(ImproperlyConfigured): + pass + + +class StorageHandler: + def __init__(self, backends=None): + # backends is an optional dict of storage backend definitions + # (structured like settings.STORAGES). + self._backends = backends + self._storages = {} + + @cached_property + def backends(self): + if self._backends is None: + self._backends = settings.STORAGES.copy() + # RemovedInDjango51Warning. + if settings.is_overridden("DEFAULT_FILE_STORAGE"): + self._backends[DEFAULT_STORAGE_ALIAS] = { + "BACKEND": settings.DEFAULT_FILE_STORAGE + } + if settings.is_overridden("STATICFILES_STORAGE"): + self._backends[STATICFILES_STORAGE_ALIAS] = { + "BACKEND": settings.STATICFILES_STORAGE + } + return self._backends + + def __getitem__(self, alias): + try: + return self._storages[alias] + except KeyError: + try: + params = self.backends[alias] + except KeyError: + raise InvalidStorageError( + f"Could not find config for '{alias}' in settings.STORAGES." + ) + storage = self.create_storage(params) + self._storages[alias] = storage + return storage + + def create_storage(self, params): + params = params.copy() + backend = params.pop("BACKEND") + options = params.pop("OPTIONS", {}) + try: + storage_cls = import_string(backend) + except ImportError as e: + raise InvalidStorageError(f"Could not find backend {backend!r}: {e}") from e + return storage_cls(**options) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/storage/memory.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/storage/memory.py new file mode 100644 index 0000000..39a8aef --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/storage/memory.py @@ -0,0 +1,290 @@ +""" +Based on dj-inmemorystorage (BSD) by Cody Soyland, Seán Hayes, Tore Birkeland, +and Nick Presta. +""" + +import errno +import io +import os +import pathlib +from urllib.parse import urljoin + +from django.conf import settings +from django.core.files.base import ContentFile +from django.core.signals import setting_changed +from django.utils._os import safe_join +from django.utils.deconstruct import deconstructible +from django.utils.encoding import filepath_to_uri +from django.utils.functional import cached_property +from django.utils.timezone import now + +from .base import Storage +from .mixins import StorageSettingsMixin + +__all__ = ("InMemoryStorage",) + + +class TimingMixin: + def _initialize_times(self): + self.created_time = now() + self.accessed_time = self.created_time + self.modified_time = self.created_time + + def _update_accessed_time(self): + self.accessed_time = now() + + def _update_modified_time(self): + self.modified_time = now() + + +class InMemoryFileNode(ContentFile, TimingMixin): + """ + Helper class representing an in-memory file node. + + Handle unicode/bytes conversion during I/O operations and record creation, + modification, and access times. + """ + + def __init__(self, content="", name=""): + self.file = None + self._content_type = type(content) + self._initialize_stream() + self._initialize_times() + + def open(self, mode): + self._convert_stream_content(mode) + self._update_accessed_time() + return super().open(mode) + + def write(self, data): + super().write(data) + self._update_modified_time() + + def _initialize_stream(self): + """Initialize underlying stream according to the content type.""" + self.file = io.BytesIO() if self._content_type == bytes else io.StringIO() + + def _convert_stream_content(self, mode): + """Convert actual file content according to the opening mode.""" + new_content_type = bytes if "b" in mode else str + # No conversion needed. + if self._content_type == new_content_type: + return + + content = self.file.getvalue() + content = content.encode() if isinstance(content, str) else content.decode() + self._content_type = new_content_type + self._initialize_stream() + + self.file.write(content) + + +class InMemoryDirNode(TimingMixin): + """ + Helper class representing an in-memory directory node. + + Handle path navigation of directory trees, creating missing nodes if + needed. + """ + + def __init__(self): + self._children = {} + self._initialize_times() + + def resolve(self, path, create_if_missing=False, leaf_cls=None, check_exists=True): + """ + Navigate current directory tree, returning node matching path or + creating a new one, if missing. + - path: path of the node to search + - create_if_missing: create nodes if not exist. Defaults to False. + - leaf_cls: expected type of leaf node. Defaults to None. + - check_exists: if True and the leaf node does not exist, raise a + FileNotFoundError. Defaults to True. + """ + path_segments = list(pathlib.Path(path).parts) + current_node = self + + while path_segments: + path_segment = path_segments.pop(0) + # If current node is a file node and there are unprocessed + # segments, raise an error. + if isinstance(current_node, InMemoryFileNode): + path_segments = os.path.split(path) + current_path = "/".join( + path_segments[: path_segments.index(path_segment)] + ) + raise NotADirectoryError( + errno.ENOTDIR, os.strerror(errno.ENOTDIR), current_path + ) + current_node = current_node._resolve_child( + path_segment, + create_if_missing, + leaf_cls if len(path_segments) == 0 else InMemoryDirNode, + ) + if current_node is None: + break + + if current_node is None and check_exists: + raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), path) + + # If a leaf_cls is not None, check if leaf node is of right type. + if leaf_cls and not isinstance(current_node, leaf_cls): + error_cls, error_code = ( + (NotADirectoryError, errno.ENOTDIR) + if leaf_cls is InMemoryDirNode + else (IsADirectoryError, errno.EISDIR) + ) + raise error_cls(error_code, os.strerror(error_code), path) + + return current_node + + def _resolve_child(self, path_segment, create_if_missing, child_cls): + if create_if_missing: + self._update_accessed_time() + self._update_modified_time() + return self._children.setdefault(path_segment, child_cls()) + return self._children.get(path_segment) + + def listdir(self): + directories, files = [], [] + for name, entry in self._children.items(): + if isinstance(entry, InMemoryDirNode): + directories.append(name) + else: + files.append(name) + return directories, files + + def remove_child(self, name): + if name in self._children: + self._update_accessed_time() + self._update_modified_time() + del self._children[name] + + +@deconstructible(path="django.core.files.storage.InMemoryStorage") +class InMemoryStorage(Storage, StorageSettingsMixin): + """A storage saving files in memory.""" + + def __init__( + self, + location=None, + base_url=None, + file_permissions_mode=None, + directory_permissions_mode=None, + ): + self._location = location + self._base_url = base_url + self._file_permissions_mode = file_permissions_mode + self._directory_permissions_mode = directory_permissions_mode + self._root = InMemoryDirNode() + self._resolve( + self.base_location, create_if_missing=True, leaf_cls=InMemoryDirNode + ) + setting_changed.connect(self._clear_cached_properties) + + @cached_property + def base_location(self): + return self._value_or_setting(self._location, settings.MEDIA_ROOT) + + @cached_property + def location(self): + return os.path.abspath(self.base_location) + + @cached_property + def base_url(self): + if self._base_url is not None and not self._base_url.endswith("/"): + self._base_url += "/" + return self._value_or_setting(self._base_url, settings.MEDIA_URL) + + @cached_property + def file_permissions_mode(self): + return self._value_or_setting( + self._file_permissions_mode, settings.FILE_UPLOAD_PERMISSIONS + ) + + @cached_property + def directory_permissions_mode(self): + return self._value_or_setting( + self._directory_permissions_mode, settings.FILE_UPLOAD_DIRECTORY_PERMISSIONS + ) + + def _relative_path(self, name): + full_path = self.path(name) + return os.path.relpath(full_path, self.location) + + def _resolve(self, name, create_if_missing=False, leaf_cls=None, check_exists=True): + try: + relative_path = self._relative_path(name) + return self._root.resolve( + relative_path, + create_if_missing=create_if_missing, + leaf_cls=leaf_cls, + check_exists=check_exists, + ) + except NotADirectoryError as exc: + absolute_path = self.path(exc.filename) + raise FileExistsError(f"{absolute_path} exists and is not a directory.") + + def _open(self, name, mode="rb"): + create_if_missing = "w" in mode + file_node = self._resolve( + name, create_if_missing=create_if_missing, leaf_cls=InMemoryFileNode + ) + return file_node.open(mode) + + def _save(self, name, content): + file_node = self._resolve( + name, create_if_missing=True, leaf_cls=InMemoryFileNode + ) + fd = None + for chunk in content.chunks(): + if fd is None: + mode = "wb" if isinstance(chunk, bytes) else "wt" + fd = file_node.open(mode) + fd.write(chunk) + + if hasattr(content, "temporary_file_path"): + os.remove(content.temporary_file_path()) + + file_node.modified_time = now() + return self._relative_path(name).replace("\\", "/") + + def path(self, name): + return safe_join(self.location, name) + + def delete(self, name): + path, filename = os.path.split(name) + dir_node = self._resolve(path, check_exists=False) + if dir_node is None: + return None + dir_node.remove_child(filename) + + def exists(self, name): + return self._resolve(name, check_exists=False) is not None + + def listdir(self, path): + node = self._resolve(path, leaf_cls=InMemoryDirNode) + return node.listdir() + + def size(self, name): + return len(self._open(name, "rb").file.getvalue()) + + def url(self, name): + if self.base_url is None: + raise ValueError("This file is not accessible via a URL.") + url = filepath_to_uri(name) + if url is not None: + url = url.lstrip("/") + return urljoin(self.base_url, url) + + def get_accessed_time(self, name): + file_node = self._resolve(name) + return file_node.accessed_time + + def get_created_time(self, name): + file_node = self._resolve(name) + return file_node.created_time + + def get_modified_time(self, name): + file_node = self._resolve(name) + return file_node.modified_time diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/storage/mixins.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/storage/mixins.py new file mode 100644 index 0000000..663a163 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/storage/mixins.py @@ -0,0 +1,15 @@ +class StorageSettingsMixin: + def _clear_cached_properties(self, setting, **kwargs): + """Reset setting based property values.""" + if setting == "MEDIA_ROOT": + self.__dict__.pop("base_location", None) + self.__dict__.pop("location", None) + elif setting == "MEDIA_URL": + self.__dict__.pop("base_url", None) + elif setting == "FILE_UPLOAD_PERMISSIONS": + self.__dict__.pop("file_permissions_mode", None) + elif setting == "FILE_UPLOAD_DIRECTORY_PERMISSIONS": + self.__dict__.pop("directory_permissions_mode", None) + + def _value_or_setting(self, value, setting): + return setting if value is None else value diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/temp.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/temp.py new file mode 100644 index 0000000..5bd31dd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/temp.py @@ -0,0 +1,79 @@ +""" +The temp module provides a NamedTemporaryFile that can be reopened in the same +process on any platform. Most platforms use the standard Python +tempfile.NamedTemporaryFile class, but Windows users are given a custom class. + +This is needed because the Python implementation of NamedTemporaryFile uses the +O_TEMPORARY flag under Windows, which prevents the file from being reopened +if the same flag is not provided [1][2]. Note that this does not address the +more general issue of opening a file for writing and reading in multiple +processes in a manner that works across platforms. + +The custom version of NamedTemporaryFile doesn't support the same keyword +arguments available in tempfile.NamedTemporaryFile. + +1: https://mail.python.org/pipermail/python-list/2005-December/336957.html +2: https://bugs.python.org/issue14243 +""" + +import os +import tempfile + +from django.core.files.utils import FileProxyMixin + +__all__ = ( + "NamedTemporaryFile", + "gettempdir", +) + + +if os.name == "nt": + + class TemporaryFile(FileProxyMixin): + """ + Temporary file object constructor that supports reopening of the + temporary file in Windows. + + Unlike tempfile.NamedTemporaryFile from the standard library, + __init__() doesn't support the 'delete', 'buffering', 'encoding', or + 'newline' keyword arguments. + """ + + def __init__(self, mode="w+b", bufsize=-1, suffix="", prefix="", dir=None): + fd, name = tempfile.mkstemp(suffix=suffix, prefix=prefix, dir=dir) + self.name = name + self.file = os.fdopen(fd, mode, bufsize) + self.close_called = False + + # Because close can be called during shutdown + # we need to cache os.unlink and access it + # as self.unlink only + unlink = os.unlink + + def close(self): + if not self.close_called: + self.close_called = True + try: + self.file.close() + except OSError: + pass + try: + self.unlink(self.name) + except OSError: + pass + + def __del__(self): + self.close() + + def __enter__(self): + self.file.__enter__() + return self + + def __exit__(self, exc, value, tb): + self.file.__exit__(exc, value, tb) + + NamedTemporaryFile = TemporaryFile +else: + NamedTemporaryFile = tempfile.NamedTemporaryFile + +gettempdir = tempfile.gettempdir diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/uploadedfile.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/uploadedfile.py new file mode 100644 index 0000000..efbfcac --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/uploadedfile.py @@ -0,0 +1,150 @@ +""" +Classes representing uploaded files. +""" + +import os +from io import BytesIO + +from django.conf import settings +from django.core.files import temp as tempfile +from django.core.files.base import File +from django.core.files.utils import validate_file_name + +__all__ = ( + "UploadedFile", + "TemporaryUploadedFile", + "InMemoryUploadedFile", + "SimpleUploadedFile", +) + + +class UploadedFile(File): + """ + An abstract uploaded file (``TemporaryUploadedFile`` and + ``InMemoryUploadedFile`` are the built-in concrete subclasses). + + An ``UploadedFile`` object behaves somewhat like a file object and + represents some file data that the user submitted with a form. + """ + + def __init__( + self, + file=None, + name=None, + content_type=None, + size=None, + charset=None, + content_type_extra=None, + ): + super().__init__(file, name) + self.size = size + self.content_type = content_type + self.charset = charset + self.content_type_extra = content_type_extra + + def __repr__(self): + return "<%s: %s (%s)>" % (self.__class__.__name__, self.name, self.content_type) + + def _get_name(self): + return self._name + + def _set_name(self, name): + # Sanitize the file name so that it can't be dangerous. + if name is not None: + # Just use the basename of the file -- anything else is dangerous. + name = os.path.basename(name) + + # File names longer than 255 characters can cause problems on older OSes. + if len(name) > 255: + name, ext = os.path.splitext(name) + ext = ext[:255] + name = name[: 255 - len(ext)] + ext + + name = validate_file_name(name) + + self._name = name + + name = property(_get_name, _set_name) + + +class TemporaryUploadedFile(UploadedFile): + """ + A file uploaded to a temporary location (i.e. stream-to-disk). + """ + + def __init__(self, name, content_type, size, charset, content_type_extra=None): + _, ext = os.path.splitext(name) + file = tempfile.NamedTemporaryFile( + suffix=".upload" + ext, dir=settings.FILE_UPLOAD_TEMP_DIR + ) + super().__init__(file, name, content_type, size, charset, content_type_extra) + + def temporary_file_path(self): + """Return the full path of this file.""" + return self.file.name + + def close(self): + try: + return self.file.close() + except FileNotFoundError: + # The file was moved or deleted before the tempfile could unlink + # it. Still sets self.file.close_called and calls + # self.file.file.close() before the exception. + pass + + +class InMemoryUploadedFile(UploadedFile): + """ + A file uploaded into memory (i.e. stream-to-memory). + """ + + def __init__( + self, + file, + field_name, + name, + content_type, + size, + charset, + content_type_extra=None, + ): + super().__init__(file, name, content_type, size, charset, content_type_extra) + self.field_name = field_name + + def open(self, mode=None): + self.file.seek(0) + return self + + def chunks(self, chunk_size=None): + self.file.seek(0) + yield self.read() + + def multiple_chunks(self, chunk_size=None): + # Since it's in memory, we'll never have multiple chunks. + return False + + +class SimpleUploadedFile(InMemoryUploadedFile): + """ + A simple representation of a file, which just has content, size, and a name. + """ + + def __init__(self, name, content, content_type="text/plain"): + content = content or b"" + super().__init__( + BytesIO(content), None, name, content_type, len(content), None, None + ) + + @classmethod + def from_dict(cls, file_dict): + """ + Create a SimpleUploadedFile object from a dictionary with keys: + - filename + - content-type + - content + """ + return cls( + file_dict["filename"], + file_dict["content"], + file_dict.get("content-type", "text/plain"), + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/uploadhandler.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/uploadhandler.py new file mode 100644 index 0000000..b6c185e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/uploadhandler.py @@ -0,0 +1,251 @@ +""" +Base file upload handler classes, and the built-in concrete subclasses +""" +import os +from io import BytesIO + +from django.conf import settings +from django.core.files.uploadedfile import InMemoryUploadedFile, TemporaryUploadedFile +from django.utils.module_loading import import_string + +__all__ = [ + "UploadFileException", + "StopUpload", + "SkipFile", + "FileUploadHandler", + "TemporaryFileUploadHandler", + "MemoryFileUploadHandler", + "load_handler", + "StopFutureHandlers", +] + + +class UploadFileException(Exception): + """ + Any error having to do with uploading files. + """ + + pass + + +class StopUpload(UploadFileException): + """ + This exception is raised when an upload must abort. + """ + + def __init__(self, connection_reset=False): + """ + If ``connection_reset`` is ``True``, Django knows will halt the upload + without consuming the rest of the upload. This will cause the browser to + show a "connection reset" error. + """ + self.connection_reset = connection_reset + + def __str__(self): + if self.connection_reset: + return "StopUpload: Halt current upload." + else: + return "StopUpload: Consume request data, then halt." + + +class SkipFile(UploadFileException): + """ + This exception is raised by an upload handler that wants to skip a given file. + """ + + pass + + +class StopFutureHandlers(UploadFileException): + """ + Upload handlers that have handled a file and do not want future handlers to + run should raise this exception instead of returning None. + """ + + pass + + +class FileUploadHandler: + """ + Base class for streaming upload handlers. + """ + + chunk_size = 64 * 2**10 # : The default chunk size is 64 KB. + + def __init__(self, request=None): + self.file_name = None + self.content_type = None + self.content_length = None + self.charset = None + self.content_type_extra = None + self.request = request + + def handle_raw_input( + self, input_data, META, content_length, boundary, encoding=None + ): + """ + Handle the raw input from the client. + + Parameters: + + :input_data: + An object that supports reading via .read(). + :META: + ``request.META``. + :content_length: + The (integer) value of the Content-Length header from the + client. + :boundary: The boundary from the Content-Type header. Be sure to + prepend two '--'. + """ + pass + + def new_file( + self, + field_name, + file_name, + content_type, + content_length, + charset=None, + content_type_extra=None, + ): + """ + Signal that a new file has been started. + + Warning: As with any data from the client, you should not trust + content_length (and sometimes won't even get it). + """ + self.field_name = field_name + self.file_name = file_name + self.content_type = content_type + self.content_length = content_length + self.charset = charset + self.content_type_extra = content_type_extra + + def receive_data_chunk(self, raw_data, start): + """ + Receive data from the streamed upload parser. ``start`` is the position + in the file of the chunk. + """ + raise NotImplementedError( + "subclasses of FileUploadHandler must provide a receive_data_chunk() method" + ) + + def file_complete(self, file_size): + """ + Signal that a file has completed. File size corresponds to the actual + size accumulated by all the chunks. + + Subclasses should return a valid ``UploadedFile`` object. + """ + raise NotImplementedError( + "subclasses of FileUploadHandler must provide a file_complete() method" + ) + + def upload_complete(self): + """ + Signal that the upload is complete. Subclasses should perform cleanup + that is necessary for this handler. + """ + pass + + def upload_interrupted(self): + """ + Signal that the upload was interrupted. Subclasses should perform + cleanup that is necessary for this handler. + """ + pass + + +class TemporaryFileUploadHandler(FileUploadHandler): + """ + Upload handler that streams data into a temporary file. + """ + + def new_file(self, *args, **kwargs): + """ + Create the file object to append to as data is coming in. + """ + super().new_file(*args, **kwargs) + self.file = TemporaryUploadedFile( + self.file_name, self.content_type, 0, self.charset, self.content_type_extra + ) + + def receive_data_chunk(self, raw_data, start): + self.file.write(raw_data) + + def file_complete(self, file_size): + self.file.seek(0) + self.file.size = file_size + return self.file + + def upload_interrupted(self): + if hasattr(self, "file"): + temp_location = self.file.temporary_file_path() + try: + self.file.close() + os.remove(temp_location) + except FileNotFoundError: + pass + + +class MemoryFileUploadHandler(FileUploadHandler): + """ + File upload handler to stream uploads into memory (used for small files). + """ + + def handle_raw_input( + self, input_data, META, content_length, boundary, encoding=None + ): + """ + Use the content_length to signal whether or not this handler should be + used. + """ + # Check the content-length header to see if we should + # If the post is too large, we cannot use the Memory handler. + self.activated = content_length <= settings.FILE_UPLOAD_MAX_MEMORY_SIZE + + def new_file(self, *args, **kwargs): + super().new_file(*args, **kwargs) + if self.activated: + self.file = BytesIO() + raise StopFutureHandlers() + + def receive_data_chunk(self, raw_data, start): + """Add the data to the BytesIO file.""" + if self.activated: + self.file.write(raw_data) + else: + return raw_data + + def file_complete(self, file_size): + """Return a file object if this handler is activated.""" + if not self.activated: + return + + self.file.seek(0) + return InMemoryUploadedFile( + file=self.file, + field_name=self.field_name, + name=self.file_name, + content_type=self.content_type, + size=file_size, + charset=self.charset, + content_type_extra=self.content_type_extra, + ) + + +def load_handler(path, *args, **kwargs): + """ + Given a path to a handler, return an instance of that handler. + + E.g.:: + >>> from django.http import HttpRequest + >>> request = HttpRequest() + >>> load_handler( + ... 'django.core.files.uploadhandler.TemporaryFileUploadHandler', + ... request, + ... ) + + """ + return import_string(path)(*args, **kwargs) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/utils.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/utils.py new file mode 100644 index 0000000..611f932 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/files/utils.py @@ -0,0 +1,78 @@ +import os +import pathlib + +from django.core.exceptions import SuspiciousFileOperation + + +def validate_file_name(name, allow_relative_path=False): + # Remove potentially dangerous names + if os.path.basename(name) in {"", ".", ".."}: + raise SuspiciousFileOperation("Could not derive file name from '%s'" % name) + + if allow_relative_path: + # Use PurePosixPath() because this branch is checked only in + # FileField.generate_filename() where all file paths are expected to be + # Unix style (with forward slashes). + path = pathlib.PurePosixPath(name) + if path.is_absolute() or ".." in path.parts: + raise SuspiciousFileOperation( + "Detected path traversal attempt in '%s'" % name + ) + elif name != os.path.basename(name): + raise SuspiciousFileOperation("File name '%s' includes path elements" % name) + + return name + + +class FileProxyMixin: + """ + A mixin class used to forward file methods to an underlying file + object. The internal file object has to be called "file":: + + class FileProxy(FileProxyMixin): + def __init__(self, file): + self.file = file + """ + + encoding = property(lambda self: self.file.encoding) + fileno = property(lambda self: self.file.fileno) + flush = property(lambda self: self.file.flush) + isatty = property(lambda self: self.file.isatty) + newlines = property(lambda self: self.file.newlines) + read = property(lambda self: self.file.read) + readinto = property(lambda self: self.file.readinto) + readline = property(lambda self: self.file.readline) + readlines = property(lambda self: self.file.readlines) + seek = property(lambda self: self.file.seek) + tell = property(lambda self: self.file.tell) + truncate = property(lambda self: self.file.truncate) + write = property(lambda self: self.file.write) + writelines = property(lambda self: self.file.writelines) + + @property + def closed(self): + return not self.file or self.file.closed + + def readable(self): + if self.closed: + return False + if hasattr(self.file, "readable"): + return self.file.readable() + return True + + def writable(self): + if self.closed: + return False + if hasattr(self.file, "writable"): + return self.file.writable() + return "w" in getattr(self.file, "mode", "") + + def seekable(self): + if self.closed: + return False + if hasattr(self.file, "seekable"): + return self.file.seekable() + return True + + def __iter__(self): + return iter(self.file) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/handlers/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/handlers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/handlers/asgi.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/handlers/asgi.py new file mode 100644 index 0000000..7b0086f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/handlers/asgi.py @@ -0,0 +1,366 @@ +import asyncio +import logging +import sys +import tempfile +import traceback +from contextlib import aclosing + +from asgiref.sync import ThreadSensitiveContext, sync_to_async + +from django.conf import settings +from django.core import signals +from django.core.exceptions import RequestAborted, RequestDataTooBig +from django.core.handlers import base +from django.http import ( + FileResponse, + HttpRequest, + HttpResponse, + HttpResponseBadRequest, + HttpResponseServerError, + QueryDict, + parse_cookie, +) +from django.urls import set_script_prefix +from django.utils.functional import cached_property + +logger = logging.getLogger("django.request") + + +def get_script_prefix(scope): + """ + Return the script prefix to use from either the scope or a setting. + """ + if settings.FORCE_SCRIPT_NAME: + return settings.FORCE_SCRIPT_NAME + return scope.get("root_path", "") or "" + + +class ASGIRequest(HttpRequest): + """ + Custom request subclass that decodes from an ASGI-standard request dict + and wraps request body handling. + """ + + # Number of seconds until a Request gives up on trying to read a request + # body and aborts. + body_receive_timeout = 60 + + def __init__(self, scope, body_file): + self.scope = scope + self._post_parse_error = False + self._read_started = False + self.resolver_match = None + self.script_name = get_script_prefix(scope) + if self.script_name: + # TODO: Better is-prefix checking, slash handling? + self.path_info = scope["path"].removeprefix(self.script_name) + else: + self.path_info = scope["path"] + # The Django path is different from ASGI scope path args, it should + # combine with script name. + if self.script_name: + self.path = "%s/%s" % ( + self.script_name.rstrip("/"), + self.path_info.replace("/", "", 1), + ) + else: + self.path = scope["path"] + # HTTP basics. + self.method = self.scope["method"].upper() + # Ensure query string is encoded correctly. + query_string = self.scope.get("query_string", "") + if isinstance(query_string, bytes): + query_string = query_string.decode() + self.META = { + "REQUEST_METHOD": self.method, + "QUERY_STRING": query_string, + "SCRIPT_NAME": self.script_name, + "PATH_INFO": self.path_info, + # WSGI-expecting code will need these for a while + "wsgi.multithread": True, + "wsgi.multiprocess": True, + } + if self.scope.get("client"): + self.META["REMOTE_ADDR"] = self.scope["client"][0] + self.META["REMOTE_HOST"] = self.META["REMOTE_ADDR"] + self.META["REMOTE_PORT"] = self.scope["client"][1] + if self.scope.get("server"): + self.META["SERVER_NAME"] = self.scope["server"][0] + self.META["SERVER_PORT"] = str(self.scope["server"][1]) + else: + self.META["SERVER_NAME"] = "unknown" + self.META["SERVER_PORT"] = "0" + # Headers go into META. + for name, value in self.scope.get("headers", []): + name = name.decode("latin1") + if name == "content-length": + corrected_name = "CONTENT_LENGTH" + elif name == "content-type": + corrected_name = "CONTENT_TYPE" + else: + corrected_name = "HTTP_%s" % name.upper().replace("-", "_") + # HTTP/2 say only ASCII chars are allowed in headers, but decode + # latin1 just in case. + value = value.decode("latin1") + if corrected_name in self.META: + value = self.META[corrected_name] + "," + value + self.META[corrected_name] = value + # Pull out request encoding, if provided. + self._set_content_type_params(self.META) + # Directly assign the body file to be our stream. + self._stream = body_file + # Other bits. + self.resolver_match = None + + @cached_property + def GET(self): + return QueryDict(self.META["QUERY_STRING"]) + + def _get_scheme(self): + return self.scope.get("scheme") or super()._get_scheme() + + def _get_post(self): + if not hasattr(self, "_post"): + self._load_post_and_files() + return self._post + + def _set_post(self, post): + self._post = post + + def _get_files(self): + if not hasattr(self, "_files"): + self._load_post_and_files() + return self._files + + POST = property(_get_post, _set_post) + FILES = property(_get_files) + + @cached_property + def COOKIES(self): + return parse_cookie(self.META.get("HTTP_COOKIE", "")) + + def close(self): + super().close() + self._stream.close() + + +class ASGIHandler(base.BaseHandler): + """Handler for ASGI requests.""" + + request_class = ASGIRequest + # Size to chunk response bodies into for multiple response messages. + chunk_size = 2**16 + + def __init__(self): + super().__init__() + self.load_middleware(is_async=True) + + async def __call__(self, scope, receive, send): + """ + Async entrypoint - parses the request and hands off to get_response. + """ + # Serve only HTTP connections. + # FIXME: Allow to override this. + if scope["type"] != "http": + raise ValueError( + "Django can only handle ASGI/HTTP connections, not %s." % scope["type"] + ) + + async with ThreadSensitiveContext(): + await self.handle(scope, receive, send) + + async def handle(self, scope, receive, send): + """ + Handles the ASGI request. Called via the __call__ method. + """ + # Receive the HTTP request body as a stream object. + try: + body_file = await self.read_body(receive) + except RequestAborted: + return + # Request is complete and can be served. + set_script_prefix(get_script_prefix(scope)) + await signals.request_started.asend(sender=self.__class__, scope=scope) + # Get the request and check for basic issues. + request, error_response = self.create_request(scope, body_file) + if request is None: + body_file.close() + await self.send_response(error_response, send) + return + + async def process_request(request, send): + response = await self.run_get_response(request) + await self.send_response(response, send) + + # Try to catch a disconnect while getting response. + tasks = [ + # Check the status of these tasks and (optionally) terminate them + # in this order. The listen_for_disconnect() task goes first + # because it should not raise unexpected errors that would prevent + # us from cancelling process_request(). + asyncio.create_task(self.listen_for_disconnect(receive)), + asyncio.create_task(process_request(request, send)), + ] + await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED) + # Now wait on both tasks (they may have both finished by now). + for task in tasks: + if task.done(): + try: + task.result() + except RequestAborted: + # Ignore client disconnects. + pass + except AssertionError: + body_file.close() + raise + else: + # Allow views to handle cancellation. + task.cancel() + try: + await task + except asyncio.CancelledError: + # Task re-raised the CancelledError as expected. + pass + body_file.close() + + async def listen_for_disconnect(self, receive): + """Listen for disconnect from the client.""" + message = await receive() + if message["type"] == "http.disconnect": + raise RequestAborted() + # This should never happen. + assert False, "Invalid ASGI message after request body: %s" % message["type"] + + async def run_get_response(self, request): + """Get async response.""" + # Use the async mode of BaseHandler. + response = await self.get_response_async(request) + response._handler_class = self.__class__ + # Increase chunk size on file responses (ASGI servers handles low-level + # chunking). + if isinstance(response, FileResponse): + response.block_size = self.chunk_size + return response + + async def read_body(self, receive): + """Reads an HTTP body from an ASGI connection.""" + # Use the tempfile that auto rolls-over to a disk file as it fills up. + body_file = tempfile.SpooledTemporaryFile( + max_size=settings.FILE_UPLOAD_MAX_MEMORY_SIZE, mode="w+b" + ) + while True: + message = await receive() + if message["type"] == "http.disconnect": + body_file.close() + # Early client disconnect. + raise RequestAborted() + # Add a body chunk from the message, if provided. + if "body" in message: + body_file.write(message["body"]) + # Quit out if that's the end. + if not message.get("more_body", False): + break + body_file.seek(0) + return body_file + + def create_request(self, scope, body_file): + """ + Create the Request object and returns either (request, None) or + (None, response) if there is an error response. + """ + try: + return self.request_class(scope, body_file), None + except UnicodeDecodeError: + logger.warning( + "Bad Request (UnicodeDecodeError)", + exc_info=sys.exc_info(), + extra={"status_code": 400}, + ) + return None, HttpResponseBadRequest() + except RequestDataTooBig: + return None, HttpResponse("413 Payload too large", status=413) + + def handle_uncaught_exception(self, request, resolver, exc_info): + """Last-chance handler for exceptions.""" + # There's no WSGI server to catch the exception further up + # if this fails, so translate it into a plain text response. + try: + return super().handle_uncaught_exception(request, resolver, exc_info) + except Exception: + return HttpResponseServerError( + traceback.format_exc() if settings.DEBUG else "Internal Server Error", + content_type="text/plain", + ) + + async def send_response(self, response, send): + """Encode and send a response out over ASGI.""" + # Collect cookies into headers. Have to preserve header case as there + # are some non-RFC compliant clients that require e.g. Content-Type. + response_headers = [] + for header, value in response.items(): + if isinstance(header, str): + header = header.encode("ascii") + if isinstance(value, str): + value = value.encode("latin1") + response_headers.append((bytes(header), bytes(value))) + for c in response.cookies.values(): + response_headers.append( + (b"Set-Cookie", c.output(header="").encode("ascii").strip()) + ) + # Initial response message. + await send( + { + "type": "http.response.start", + "status": response.status_code, + "headers": response_headers, + } + ) + # Streaming responses need to be pinned to their iterator. + if response.streaming: + # - Consume via `__aiter__` and not `streaming_content` directly, to + # allow mapping of a sync iterator. + # - Use aclosing() when consuming aiter. + # See https://github.com/python/cpython/commit/6e8dcda + async with aclosing(aiter(response)) as content: + async for part in content: + for chunk, _ in self.chunk_bytes(part): + await send( + { + "type": "http.response.body", + "body": chunk, + # Ignore "more" as there may be more parts; instead, + # use an empty final closing message with False. + "more_body": True, + } + ) + # Final closing message. + await send({"type": "http.response.body"}) + # Other responses just need chunking. + else: + # Yield chunks of response. + for chunk, last in self.chunk_bytes(response.content): + await send( + { + "type": "http.response.body", + "body": chunk, + "more_body": not last, + } + ) + await sync_to_async(response.close, thread_sensitive=True)() + + @classmethod + def chunk_bytes(cls, data): + """ + Chunks some data up so it can be sent in reasonable size messages. + Yields (chunk, last_chunk) tuples. + """ + position = 0 + if not data: + yield data, True + return + while position < len(data): + yield ( + data[position : position + cls.chunk_size], + (position + cls.chunk_size) >= len(data), + ) + position += cls.chunk_size diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/handlers/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/handlers/base.py new file mode 100644 index 0000000..8911543 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/handlers/base.py @@ -0,0 +1,373 @@ +import asyncio +import logging +import types + +from asgiref.sync import async_to_sync, iscoroutinefunction, sync_to_async + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured, MiddlewareNotUsed +from django.core.signals import request_finished +from django.db import connections, transaction +from django.urls import get_resolver, set_urlconf +from django.utils.log import log_response +from django.utils.module_loading import import_string + +from .exception import convert_exception_to_response + +logger = logging.getLogger("django.request") + + +class BaseHandler: + _view_middleware = None + _template_response_middleware = None + _exception_middleware = None + _middleware_chain = None + + def load_middleware(self, is_async=False): + """ + Populate middleware lists from settings.MIDDLEWARE. + + Must be called after the environment is fixed (see __call__ in subclasses). + """ + self._view_middleware = [] + self._template_response_middleware = [] + self._exception_middleware = [] + + get_response = self._get_response_async if is_async else self._get_response + handler = convert_exception_to_response(get_response) + handler_is_async = is_async + for middleware_path in reversed(settings.MIDDLEWARE): + middleware = import_string(middleware_path) + middleware_can_sync = getattr(middleware, "sync_capable", True) + middleware_can_async = getattr(middleware, "async_capable", False) + if not middleware_can_sync and not middleware_can_async: + raise RuntimeError( + "Middleware %s must have at least one of " + "sync_capable/async_capable set to True." % middleware_path + ) + elif not handler_is_async and middleware_can_sync: + middleware_is_async = False + else: + middleware_is_async = middleware_can_async + try: + # Adapt handler, if needed. + adapted_handler = self.adapt_method_mode( + middleware_is_async, + handler, + handler_is_async, + debug=settings.DEBUG, + name="middleware %s" % middleware_path, + ) + mw_instance = middleware(adapted_handler) + except MiddlewareNotUsed as exc: + if settings.DEBUG: + if str(exc): + logger.debug("MiddlewareNotUsed(%r): %s", middleware_path, exc) + else: + logger.debug("MiddlewareNotUsed: %r", middleware_path) + continue + else: + handler = adapted_handler + + if mw_instance is None: + raise ImproperlyConfigured( + "Middleware factory %s returned None." % middleware_path + ) + + if hasattr(mw_instance, "process_view"): + self._view_middleware.insert( + 0, + self.adapt_method_mode(is_async, mw_instance.process_view), + ) + if hasattr(mw_instance, "process_template_response"): + self._template_response_middleware.append( + self.adapt_method_mode( + is_async, mw_instance.process_template_response + ), + ) + if hasattr(mw_instance, "process_exception"): + # The exception-handling stack is still always synchronous for + # now, so adapt that way. + self._exception_middleware.append( + self.adapt_method_mode(False, mw_instance.process_exception), + ) + + handler = convert_exception_to_response(mw_instance) + handler_is_async = middleware_is_async + + # Adapt the top of the stack, if needed. + handler = self.adapt_method_mode(is_async, handler, handler_is_async) + # We only assign to this when initialization is complete as it is used + # as a flag for initialization being complete. + self._middleware_chain = handler + + def adapt_method_mode( + self, + is_async, + method, + method_is_async=None, + debug=False, + name=None, + ): + """ + Adapt a method to be in the correct "mode": + - If is_async is False: + - Synchronous methods are left alone + - Asynchronous methods are wrapped with async_to_sync + - If is_async is True: + - Synchronous methods are wrapped with sync_to_async() + - Asynchronous methods are left alone + """ + if method_is_async is None: + method_is_async = iscoroutinefunction(method) + if debug and not name: + name = name or "method %s()" % method.__qualname__ + if is_async: + if not method_is_async: + if debug: + logger.debug("Synchronous handler adapted for %s.", name) + return sync_to_async(method, thread_sensitive=True) + elif method_is_async: + if debug: + logger.debug("Asynchronous handler adapted for %s.", name) + return async_to_sync(method) + return method + + def get_response(self, request): + """Return an HttpResponse object for the given HttpRequest.""" + # Setup default url resolver for this thread + set_urlconf(settings.ROOT_URLCONF) + response = self._middleware_chain(request) + response._resource_closers.append(request.close) + if response.status_code >= 400: + log_response( + "%s: %s", + response.reason_phrase, + request.path, + response=response, + request=request, + ) + return response + + async def get_response_async(self, request): + """ + Asynchronous version of get_response. + + Funneling everything, including WSGI, into a single async + get_response() is too slow. Avoid the context switch by using + a separate async response path. + """ + # Setup default url resolver for this thread. + set_urlconf(settings.ROOT_URLCONF) + response = await self._middleware_chain(request) + response._resource_closers.append(request.close) + if response.status_code >= 400: + await sync_to_async(log_response, thread_sensitive=False)( + "%s: %s", + response.reason_phrase, + request.path, + response=response, + request=request, + ) + return response + + def _get_response(self, request): + """ + Resolve and call the view, then apply view, exception, and + template_response middleware. This method is everything that happens + inside the request/response middleware. + """ + response = None + callback, callback_args, callback_kwargs = self.resolve_request(request) + + # Apply view middleware + for middleware_method in self._view_middleware: + response = middleware_method( + request, callback, callback_args, callback_kwargs + ) + if response: + break + + if response is None: + wrapped_callback = self.make_view_atomic(callback) + # If it is an asynchronous view, run it in a subthread. + if iscoroutinefunction(wrapped_callback): + wrapped_callback = async_to_sync(wrapped_callback) + try: + response = wrapped_callback(request, *callback_args, **callback_kwargs) + except Exception as e: + response = self.process_exception_by_middleware(e, request) + if response is None: + raise + + # Complain if the view returned None (a common error). + self.check_response(response, callback) + + # If the response supports deferred rendering, apply template + # response middleware and then render the response + if hasattr(response, "render") and callable(response.render): + for middleware_method in self._template_response_middleware: + response = middleware_method(request, response) + # Complain if the template response middleware returned None + # (a common error). + self.check_response( + response, + middleware_method, + name="%s.process_template_response" + % (middleware_method.__self__.__class__.__name__,), + ) + try: + response = response.render() + except Exception as e: + response = self.process_exception_by_middleware(e, request) + if response is None: + raise + + return response + + async def _get_response_async(self, request): + """ + Resolve and call the view, then apply view, exception, and + template_response middleware. This method is everything that happens + inside the request/response middleware. + """ + response = None + callback, callback_args, callback_kwargs = self.resolve_request(request) + + # Apply view middleware. + for middleware_method in self._view_middleware: + response = await middleware_method( + request, callback, callback_args, callback_kwargs + ) + if response: + break + + if response is None: + wrapped_callback = self.make_view_atomic(callback) + # If it is a synchronous view, run it in a subthread + if not iscoroutinefunction(wrapped_callback): + wrapped_callback = sync_to_async( + wrapped_callback, thread_sensitive=True + ) + try: + response = await wrapped_callback( + request, *callback_args, **callback_kwargs + ) + except Exception as e: + response = await sync_to_async( + self.process_exception_by_middleware, + thread_sensitive=True, + )(e, request) + if response is None: + raise + + # Complain if the view returned None or an uncalled coroutine. + self.check_response(response, callback) + + # If the response supports deferred rendering, apply template + # response middleware and then render the response + if hasattr(response, "render") and callable(response.render): + for middleware_method in self._template_response_middleware: + response = await middleware_method(request, response) + # Complain if the template response middleware returned None or + # an uncalled coroutine. + self.check_response( + response, + middleware_method, + name="%s.process_template_response" + % (middleware_method.__self__.__class__.__name__,), + ) + try: + if iscoroutinefunction(response.render): + response = await response.render() + else: + response = await sync_to_async( + response.render, thread_sensitive=True + )() + except Exception as e: + response = await sync_to_async( + self.process_exception_by_middleware, + thread_sensitive=True, + )(e, request) + if response is None: + raise + + # Make sure the response is not a coroutine + if asyncio.iscoroutine(response): + raise RuntimeError("Response is still a coroutine.") + return response + + def resolve_request(self, request): + """ + Retrieve/set the urlconf for the request. Return the view resolved, + with its args and kwargs. + """ + # Work out the resolver. + if hasattr(request, "urlconf"): + urlconf = request.urlconf + set_urlconf(urlconf) + resolver = get_resolver(urlconf) + else: + resolver = get_resolver() + # Resolve the view, and assign the match object back to the request. + resolver_match = resolver.resolve(request.path_info) + request.resolver_match = resolver_match + return resolver_match + + def check_response(self, response, callback, name=None): + """ + Raise an error if the view returned None or an uncalled coroutine. + """ + if not (response is None or asyncio.iscoroutine(response)): + return + if not name: + if isinstance(callback, types.FunctionType): # FBV + name = "The view %s.%s" % (callback.__module__, callback.__name__) + else: # CBV + name = "The view %s.%s.__call__" % ( + callback.__module__, + callback.__class__.__name__, + ) + if response is None: + raise ValueError( + "%s didn't return an HttpResponse object. It returned None " + "instead." % name + ) + elif asyncio.iscoroutine(response): + raise ValueError( + "%s didn't return an HttpResponse object. It returned an " + "unawaited coroutine instead. You may need to add an 'await' " + "into your view." % name + ) + + # Other utility methods. + + def make_view_atomic(self, view): + non_atomic_requests = getattr(view, "_non_atomic_requests", set()) + for alias, settings_dict in connections.settings.items(): + if settings_dict["ATOMIC_REQUESTS"] and alias not in non_atomic_requests: + if iscoroutinefunction(view): + raise RuntimeError( + "You cannot use ATOMIC_REQUESTS with async views." + ) + view = transaction.atomic(using=alias)(view) + return view + + def process_exception_by_middleware(self, exception, request): + """ + Pass the exception to the exception middleware. If no middleware + return a response for this exception, return None. + """ + for middleware_method in self._exception_middleware: + response = middleware_method(request, exception) + if response: + return response + return None + + +def reset_urlconf(sender, **kwargs): + """Reset the URLconf after each request is finished.""" + set_urlconf(None) + + +request_finished.connect(reset_urlconf) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/handlers/exception.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/handlers/exception.py new file mode 100644 index 0000000..a63291f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/handlers/exception.py @@ -0,0 +1,185 @@ +import logging +import sys +from functools import wraps + +from asgiref.sync import iscoroutinefunction, sync_to_async + +from django.conf import settings +from django.core import signals +from django.core.exceptions import ( + BadRequest, + PermissionDenied, + RequestDataTooBig, + SuspiciousOperation, + TooManyFieldsSent, + TooManyFilesSent, +) +from django.http import Http404 +from django.http.multipartparser import MultiPartParserError +from django.urls import get_resolver, get_urlconf +from django.utils.log import log_response +from django.views import debug + + +def convert_exception_to_response(get_response): + """ + Wrap the given get_response callable in exception-to-response conversion. + + All exceptions will be converted. All known 4xx exceptions (Http404, + PermissionDenied, MultiPartParserError, SuspiciousOperation) will be + converted to the appropriate response, and all other exceptions will be + converted to 500 responses. + + This decorator is automatically applied to all middleware to ensure that + no middleware leaks an exception and that the next middleware in the stack + can rely on getting a response instead of an exception. + """ + if iscoroutinefunction(get_response): + + @wraps(get_response) + async def inner(request): + try: + response = await get_response(request) + except Exception as exc: + response = await sync_to_async( + response_for_exception, thread_sensitive=False + )(request, exc) + return response + + return inner + else: + + @wraps(get_response) + def inner(request): + try: + response = get_response(request) + except Exception as exc: + response = response_for_exception(request, exc) + return response + + return inner + + +def response_for_exception(request, exc): + if isinstance(exc, Http404): + if settings.DEBUG: + response = debug.technical_404_response(request, exc) + else: + response = get_exception_response( + request, get_resolver(get_urlconf()), 404, exc + ) + + elif isinstance(exc, PermissionDenied): + response = get_exception_response( + request, get_resolver(get_urlconf()), 403, exc + ) + log_response( + "Forbidden (Permission denied): %s", + request.path, + response=response, + request=request, + exception=exc, + ) + + elif isinstance(exc, MultiPartParserError): + response = get_exception_response( + request, get_resolver(get_urlconf()), 400, exc + ) + log_response( + "Bad request (Unable to parse request body): %s", + request.path, + response=response, + request=request, + exception=exc, + ) + + elif isinstance(exc, BadRequest): + if settings.DEBUG: + response = debug.technical_500_response( + request, *sys.exc_info(), status_code=400 + ) + else: + response = get_exception_response( + request, get_resolver(get_urlconf()), 400, exc + ) + log_response( + "%s: %s", + str(exc), + request.path, + response=response, + request=request, + exception=exc, + ) + elif isinstance(exc, SuspiciousOperation): + if isinstance(exc, (RequestDataTooBig, TooManyFieldsSent, TooManyFilesSent)): + # POST data can't be accessed again, otherwise the original + # exception would be raised. + request._mark_post_parse_error() + + # The request logger receives events for any problematic request + # The security logger receives events for all SuspiciousOperations + security_logger = logging.getLogger( + "django.security.%s" % exc.__class__.__name__ + ) + security_logger.error( + str(exc), + exc_info=exc, + extra={"status_code": 400, "request": request}, + ) + if settings.DEBUG: + response = debug.technical_500_response( + request, *sys.exc_info(), status_code=400 + ) + else: + response = get_exception_response( + request, get_resolver(get_urlconf()), 400, exc + ) + + else: + signals.got_request_exception.send(sender=None, request=request) + response = handle_uncaught_exception( + request, get_resolver(get_urlconf()), sys.exc_info() + ) + log_response( + "%s: %s", + response.reason_phrase, + request.path, + response=response, + request=request, + exception=exc, + ) + + # Force a TemplateResponse to be rendered. + if not getattr(response, "is_rendered", True) and callable( + getattr(response, "render", None) + ): + response = response.render() + + return response + + +def get_exception_response(request, resolver, status_code, exception): + try: + callback = resolver.resolve_error_handler(status_code) + response = callback(request, exception=exception) + except Exception: + signals.got_request_exception.send(sender=None, request=request) + response = handle_uncaught_exception(request, resolver, sys.exc_info()) + + return response + + +def handle_uncaught_exception(request, resolver, exc_info): + """ + Processing for any otherwise uncaught exceptions (those that will + generate HTTP 500 responses). + """ + if settings.DEBUG_PROPAGATE_EXCEPTIONS: + raise + + if settings.DEBUG: + return debug.technical_500_response(request, *exc_info) + + # Return an HttpResponse that displays a friendly error message. + callback = resolver.resolve_error_handler(500) + return callback(request) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/handlers/wsgi.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/handlers/wsgi.py new file mode 100644 index 0000000..9324af0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/handlers/wsgi.py @@ -0,0 +1,207 @@ +from io import IOBase + +from django.conf import settings +from django.core import signals +from django.core.handlers import base +from django.http import HttpRequest, QueryDict, parse_cookie +from django.urls import set_script_prefix +from django.utils.encoding import repercent_broken_unicode +from django.utils.functional import cached_property +from django.utils.regex_helper import _lazy_re_compile + +_slashes_re = _lazy_re_compile(rb"/+") + + +class LimitedStream(IOBase): + """ + Wrap another stream to disallow reading it past a number of bytes. + + Based on the implementation from werkzeug.wsgi.LimitedStream + See https://github.com/pallets/werkzeug/blob/dbf78f67/src/werkzeug/wsgi.py#L828 + """ + + def __init__(self, stream, limit): + self._read = stream.read + self._readline = stream.readline + self._pos = 0 + self.limit = limit + + def read(self, size=-1, /): + _pos = self._pos + limit = self.limit + if _pos >= limit: + return b"" + if size == -1 or size is None: + size = limit - _pos + else: + size = min(size, limit - _pos) + data = self._read(size) + self._pos += len(data) + return data + + def readline(self, size=-1, /): + _pos = self._pos + limit = self.limit + if _pos >= limit: + return b"" + if size == -1 or size is None: + size = limit - _pos + else: + size = min(size, limit - _pos) + line = self._readline(size) + self._pos += len(line) + return line + + +class WSGIRequest(HttpRequest): + def __init__(self, environ): + script_name = get_script_name(environ) + # If PATH_INFO is empty (e.g. accessing the SCRIPT_NAME URL without a + # trailing slash), operate as if '/' was requested. + path_info = get_path_info(environ) or "/" + self.environ = environ + self.path_info = path_info + # be careful to only replace the first slash in the path because of + # http://test/something and http://test//something being different as + # stated in RFC 3986. + self.path = "%s/%s" % (script_name.rstrip("/"), path_info.replace("/", "", 1)) + self.META = environ + self.META["PATH_INFO"] = path_info + self.META["SCRIPT_NAME"] = script_name + self.method = environ["REQUEST_METHOD"].upper() + # Set content_type, content_params, and encoding. + self._set_content_type_params(environ) + try: + content_length = int(environ.get("CONTENT_LENGTH")) + except (ValueError, TypeError): + content_length = 0 + self._stream = LimitedStream(self.environ["wsgi.input"], content_length) + self._read_started = False + self.resolver_match = None + + def _get_scheme(self): + return self.environ.get("wsgi.url_scheme") + + @cached_property + def GET(self): + # The WSGI spec says 'QUERY_STRING' may be absent. + raw_query_string = get_bytes_from_wsgi(self.environ, "QUERY_STRING", "") + return QueryDict(raw_query_string, encoding=self._encoding) + + def _get_post(self): + if not hasattr(self, "_post"): + self._load_post_and_files() + return self._post + + def _set_post(self, post): + self._post = post + + @cached_property + def COOKIES(self): + raw_cookie = get_str_from_wsgi(self.environ, "HTTP_COOKIE", "") + return parse_cookie(raw_cookie) + + @property + def FILES(self): + if not hasattr(self, "_files"): + self._load_post_and_files() + return self._files + + POST = property(_get_post, _set_post) + + +class WSGIHandler(base.BaseHandler): + request_class = WSGIRequest + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.load_middleware() + + def __call__(self, environ, start_response): + set_script_prefix(get_script_name(environ)) + signals.request_started.send(sender=self.__class__, environ=environ) + request = self.request_class(environ) + response = self.get_response(request) + + response._handler_class = self.__class__ + + status = "%d %s" % (response.status_code, response.reason_phrase) + response_headers = [ + *response.items(), + *(("Set-Cookie", c.output(header="")) for c in response.cookies.values()), + ] + start_response(status, response_headers) + if getattr(response, "file_to_stream", None) is not None and environ.get( + "wsgi.file_wrapper" + ): + # If `wsgi.file_wrapper` is used the WSGI server does not call + # .close on the response, but on the file wrapper. Patch it to use + # response.close instead which takes care of closing all files. + response.file_to_stream.close = response.close + response = environ["wsgi.file_wrapper"]( + response.file_to_stream, response.block_size + ) + return response + + +def get_path_info(environ): + """Return the HTTP request's PATH_INFO as a string.""" + path_info = get_bytes_from_wsgi(environ, "PATH_INFO", "/") + + return repercent_broken_unicode(path_info).decode() + + +def get_script_name(environ): + """ + Return the equivalent of the HTTP request's SCRIPT_NAME environment + variable. If Apache mod_rewrite is used, return what would have been + the script name prior to any rewriting (so it's the script name as seen + from the client's perspective), unless the FORCE_SCRIPT_NAME setting is + set (to anything). + """ + if settings.FORCE_SCRIPT_NAME is not None: + return settings.FORCE_SCRIPT_NAME + + # If Apache's mod_rewrite had a whack at the URL, Apache set either + # SCRIPT_URL or REDIRECT_URL to the full resource URL before applying any + # rewrites. Unfortunately not every web server (lighttpd!) passes this + # information through all the time, so FORCE_SCRIPT_NAME, above, is still + # needed. + script_url = get_bytes_from_wsgi(environ, "SCRIPT_URL", "") or get_bytes_from_wsgi( + environ, "REDIRECT_URL", "" + ) + + if script_url: + if b"//" in script_url: + # mod_wsgi squashes multiple successive slashes in PATH_INFO, + # do the same with script_url before manipulating paths (#17133). + script_url = _slashes_re.sub(b"/", script_url) + path_info = get_bytes_from_wsgi(environ, "PATH_INFO", "") + script_name = script_url.removesuffix(path_info) + else: + script_name = get_bytes_from_wsgi(environ, "SCRIPT_NAME", "") + + return script_name.decode() + + +def get_bytes_from_wsgi(environ, key, default): + """ + Get a value from the WSGI environ dictionary as bytes. + + key and default should be strings. + """ + value = environ.get(key, default) + # Non-ASCII values in the WSGI environ are arbitrarily decoded with + # ISO-8859-1. This is wrong for Django websites where UTF-8 is the default. + # Re-encode to recover the original bytestring. + return value.encode("iso-8859-1") + + +def get_str_from_wsgi(environ, key, default): + """ + Get a value from the WSGI environ dictionary as str. + + key and default should be str objects. + """ + value = get_bytes_from_wsgi(environ, key, default) + return value.decode(errors="replace") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/__init__.py new file mode 100644 index 0000000..dc63e87 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/__init__.py @@ -0,0 +1,154 @@ +""" +Tools for sending email. +""" +from django.conf import settings + +# Imported for backwards compatibility and for the sake +# of a cleaner namespace. These symbols used to be in +# django/core/mail.py before the introduction of email +# backends and the subsequent reorganization (See #10355) +from django.core.mail.message import ( + DEFAULT_ATTACHMENT_MIME_TYPE, + BadHeaderError, + EmailMessage, + EmailMultiAlternatives, + SafeMIMEMultipart, + SafeMIMEText, + forbid_multi_line_headers, + make_msgid, +) +from django.core.mail.utils import DNS_NAME, CachedDnsName +from django.utils.module_loading import import_string + +__all__ = [ + "CachedDnsName", + "DNS_NAME", + "EmailMessage", + "EmailMultiAlternatives", + "SafeMIMEText", + "SafeMIMEMultipart", + "DEFAULT_ATTACHMENT_MIME_TYPE", + "make_msgid", + "BadHeaderError", + "forbid_multi_line_headers", + "get_connection", + "send_mail", + "send_mass_mail", + "mail_admins", + "mail_managers", +] + + +def get_connection(backend=None, fail_silently=False, **kwds): + """Load an email backend and return an instance of it. + + If backend is None (default), use settings.EMAIL_BACKEND. + + Both fail_silently and other keyword arguments are used in the + constructor of the backend. + """ + klass = import_string(backend or settings.EMAIL_BACKEND) + return klass(fail_silently=fail_silently, **kwds) + + +def send_mail( + subject, + message, + from_email, + recipient_list, + fail_silently=False, + auth_user=None, + auth_password=None, + connection=None, + html_message=None, +): + """ + Easy wrapper for sending a single message to a recipient list. All members + of the recipient list will see the other recipients in the 'To' field. + + If from_email is None, use the DEFAULT_FROM_EMAIL setting. + If auth_user is None, use the EMAIL_HOST_USER setting. + If auth_password is None, use the EMAIL_HOST_PASSWORD setting. + + Note: The API for this method is frozen. New code wanting to extend the + functionality should use the EmailMessage class directly. + """ + connection = connection or get_connection( + username=auth_user, + password=auth_password, + fail_silently=fail_silently, + ) + mail = EmailMultiAlternatives( + subject, message, from_email, recipient_list, connection=connection + ) + if html_message: + mail.attach_alternative(html_message, "text/html") + + return mail.send() + + +def send_mass_mail( + datatuple, fail_silently=False, auth_user=None, auth_password=None, connection=None +): + """ + Given a datatuple of (subject, message, from_email, recipient_list), send + each message to each recipient list. Return the number of emails sent. + + If from_email is None, use the DEFAULT_FROM_EMAIL setting. + If auth_user and auth_password are set, use them to log in. + If auth_user is None, use the EMAIL_HOST_USER setting. + If auth_password is None, use the EMAIL_HOST_PASSWORD setting. + + Note: The API for this method is frozen. New code wanting to extend the + functionality should use the EmailMessage class directly. + """ + connection = connection or get_connection( + username=auth_user, + password=auth_password, + fail_silently=fail_silently, + ) + messages = [ + EmailMessage(subject, message, sender, recipient, connection=connection) + for subject, message, sender, recipient in datatuple + ] + return connection.send_messages(messages) + + +def mail_admins( + subject, message, fail_silently=False, connection=None, html_message=None +): + """Send a message to the admins, as defined by the ADMINS setting.""" + if not settings.ADMINS: + return + if not all(isinstance(a, (list, tuple)) and len(a) == 2 for a in settings.ADMINS): + raise ValueError("The ADMINS setting must be a list of 2-tuples.") + mail = EmailMultiAlternatives( + "%s%s" % (settings.EMAIL_SUBJECT_PREFIX, subject), + message, + settings.SERVER_EMAIL, + [a[1] for a in settings.ADMINS], + connection=connection, + ) + if html_message: + mail.attach_alternative(html_message, "text/html") + mail.send(fail_silently=fail_silently) + + +def mail_managers( + subject, message, fail_silently=False, connection=None, html_message=None +): + """Send a message to the managers, as defined by the MANAGERS setting.""" + if not settings.MANAGERS: + return + if not all(isinstance(a, (list, tuple)) and len(a) == 2 for a in settings.MANAGERS): + raise ValueError("The MANAGERS setting must be a list of 2-tuples.") + mail = EmailMultiAlternatives( + "%s%s" % (settings.EMAIL_SUBJECT_PREFIX, subject), + message, + settings.SERVER_EMAIL, + [a[1] for a in settings.MANAGERS], + connection=connection, + ) + if html_message: + mail.attach_alternative(html_message, "text/html") + mail.send(fail_silently=fail_silently) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/backends/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/backends/__init__.py new file mode 100644 index 0000000..5973b49 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/backends/__init__.py @@ -0,0 +1 @@ +# Mail backends shipped with Django. diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/backends/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/backends/base.py new file mode 100644 index 0000000..b35b964 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/backends/base.py @@ -0,0 +1,62 @@ +"""Base email backend class.""" + + +class BaseEmailBackend: + """ + Base class for email backend implementations. + + Subclasses must at least overwrite send_messages(). + + open() and close() can be called indirectly by using a backend object as a + context manager: + + with backend as connection: + # do something with connection + pass + """ + + def __init__(self, fail_silently=False, **kwargs): + self.fail_silently = fail_silently + + def open(self): + """ + Open a network connection. + + This method can be overwritten by backend implementations to + open a network connection. + + It's up to the backend implementation to track the status of + a network connection if it's needed by the backend. + + This method can be called by applications to force a single + network connection to be used when sending mails. See the + send_messages() method of the SMTP backend for a reference + implementation. + + The default implementation does nothing. + """ + pass + + def close(self): + """Close a network connection.""" + pass + + def __enter__(self): + try: + self.open() + except Exception: + self.close() + raise + return self + + def __exit__(self, exc_type, exc_value, traceback): + self.close() + + def send_messages(self, email_messages): + """ + Send one or more EmailMessage objects and return the number of email + messages sent. + """ + raise NotImplementedError( + "subclasses of BaseEmailBackend must override send_messages() method" + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/backends/console.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/backends/console.py new file mode 100644 index 0000000..ee5dd28 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/backends/console.py @@ -0,0 +1,44 @@ +""" +Email backend that writes messages to console instead of sending them. +""" +import sys +import threading + +from django.core.mail.backends.base import BaseEmailBackend + + +class EmailBackend(BaseEmailBackend): + def __init__(self, *args, **kwargs): + self.stream = kwargs.pop("stream", sys.stdout) + self._lock = threading.RLock() + super().__init__(*args, **kwargs) + + def write_message(self, message): + msg = message.message() + msg_data = msg.as_bytes() + charset = ( + msg.get_charset().get_output_charset() if msg.get_charset() else "utf-8" + ) + msg_data = msg_data.decode(charset) + self.stream.write("%s\n" % msg_data) + self.stream.write("-" * 79) + self.stream.write("\n") + + def send_messages(self, email_messages): + """Write all messages to the stream in a thread-safe way.""" + if not email_messages: + return + msg_count = 0 + with self._lock: + try: + stream_created = self.open() + for message in email_messages: + self.write_message(message) + self.stream.flush() # flush after each message + msg_count += 1 + if stream_created: + self.close() + except Exception: + if not self.fail_silently: + raise + return msg_count diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/backends/dummy.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/backends/dummy.py new file mode 100644 index 0000000..7e47fe7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/backends/dummy.py @@ -0,0 +1,10 @@ +""" +Dummy email backend that does nothing. +""" + +from django.core.mail.backends.base import BaseEmailBackend + + +class EmailBackend(BaseEmailBackend): + def send_messages(self, email_messages): + return len(list(email_messages)) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/backends/filebased.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/backends/filebased.py new file mode 100644 index 0000000..3b2b037 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/backends/filebased.py @@ -0,0 +1,66 @@ +"""Email backend that writes messages to a file.""" + +import datetime +import os + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.core.mail.backends.console import EmailBackend as ConsoleEmailBackend + + +class EmailBackend(ConsoleEmailBackend): + def __init__(self, *args, file_path=None, **kwargs): + self._fname = None + if file_path is not None: + self.file_path = file_path + else: + self.file_path = getattr(settings, "EMAIL_FILE_PATH", None) + self.file_path = os.path.abspath(self.file_path) + try: + os.makedirs(self.file_path, exist_ok=True) + except FileExistsError: + raise ImproperlyConfigured( + "Path for saving email messages exists, but is not a directory: %s" + % self.file_path + ) + except OSError as err: + raise ImproperlyConfigured( + "Could not create directory for saving email messages: %s (%s)" + % (self.file_path, err) + ) + # Make sure that self.file_path is writable. + if not os.access(self.file_path, os.W_OK): + raise ImproperlyConfigured( + "Could not write to directory: %s" % self.file_path + ) + # Finally, call super(). + # Since we're using the console-based backend as a base, + # force the stream to be None, so we don't default to stdout + kwargs["stream"] = None + super().__init__(*args, **kwargs) + + def write_message(self, message): + self.stream.write(message.message().as_bytes() + b"\n") + self.stream.write(b"-" * 79) + self.stream.write(b"\n") + + def _get_filename(self): + """Return a unique file name.""" + if self._fname is None: + timestamp = datetime.datetime.now().strftime("%Y%m%d-%H%M%S") + fname = "%s-%s.log" % (timestamp, abs(id(self))) + self._fname = os.path.join(self.file_path, fname) + return self._fname + + def open(self): + if self.stream is None: + self.stream = open(self._get_filename(), "ab") + return True + return False + + def close(self): + try: + if self.stream is not None: + self.stream.close() + finally: + self.stream = None diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/backends/locmem.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/backends/locmem.py new file mode 100644 index 0000000..7667697 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/backends/locmem.py @@ -0,0 +1,31 @@ +""" +Backend for test environment. +""" + +from django.core import mail +from django.core.mail.backends.base import BaseEmailBackend + + +class EmailBackend(BaseEmailBackend): + """ + An email backend for use during test sessions. + + The test connection stores email messages in a dummy outbox, + rather than sending them out on the wire. + + The dummy outbox is accessible through the outbox instance attribute. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + if not hasattr(mail, "outbox"): + mail.outbox = [] + + def send_messages(self, messages): + """Redirect messages to the dummy outbox""" + msg_count = 0 + for message in messages: # .message() triggers header validation + message.message() + mail.outbox.append(message) + msg_count += 1 + return msg_count diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/backends/smtp.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/backends/smtp.py new file mode 100644 index 0000000..1ee4826 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/backends/smtp.py @@ -0,0 +1,161 @@ +"""SMTP email backend class.""" +import smtplib +import ssl +import threading + +from django.conf import settings +from django.core.mail.backends.base import BaseEmailBackend +from django.core.mail.message import sanitize_address +from django.core.mail.utils import DNS_NAME +from django.utils.functional import cached_property + + +class EmailBackend(BaseEmailBackend): + """ + A wrapper that manages the SMTP network connection. + """ + + def __init__( + self, + host=None, + port=None, + username=None, + password=None, + use_tls=None, + fail_silently=False, + use_ssl=None, + timeout=None, + ssl_keyfile=None, + ssl_certfile=None, + **kwargs, + ): + super().__init__(fail_silently=fail_silently) + self.host = host or settings.EMAIL_HOST + self.port = port or settings.EMAIL_PORT + self.username = settings.EMAIL_HOST_USER if username is None else username + self.password = settings.EMAIL_HOST_PASSWORD if password is None else password + self.use_tls = settings.EMAIL_USE_TLS if use_tls is None else use_tls + self.use_ssl = settings.EMAIL_USE_SSL if use_ssl is None else use_ssl + self.timeout = settings.EMAIL_TIMEOUT if timeout is None else timeout + self.ssl_keyfile = ( + settings.EMAIL_SSL_KEYFILE if ssl_keyfile is None else ssl_keyfile + ) + self.ssl_certfile = ( + settings.EMAIL_SSL_CERTFILE if ssl_certfile is None else ssl_certfile + ) + if self.use_ssl and self.use_tls: + raise ValueError( + "EMAIL_USE_TLS/EMAIL_USE_SSL are mutually exclusive, so only set " + "one of those settings to True." + ) + self.connection = None + self._lock = threading.RLock() + + @property + def connection_class(self): + return smtplib.SMTP_SSL if self.use_ssl else smtplib.SMTP + + @cached_property + def ssl_context(self): + if self.ssl_certfile or self.ssl_keyfile: + ssl_context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLS_CLIENT) + ssl_context.load_cert_chain(self.ssl_certfile, self.ssl_keyfile) + return ssl_context + else: + return ssl.create_default_context() + + def open(self): + """ + Ensure an open connection to the email server. Return whether or not a + new connection was required (True or False) or None if an exception + passed silently. + """ + if self.connection: + # Nothing to do if the connection is already open. + return False + + # If local_hostname is not specified, socket.getfqdn() gets used. + # For performance, we use the cached FQDN for local_hostname. + connection_params = {"local_hostname": DNS_NAME.get_fqdn()} + if self.timeout is not None: + connection_params["timeout"] = self.timeout + if self.use_ssl: + connection_params["context"] = self.ssl_context + try: + self.connection = self.connection_class( + self.host, self.port, **connection_params + ) + + # TLS/SSL are mutually exclusive, so only attempt TLS over + # non-secure connections. + if not self.use_ssl and self.use_tls: + self.connection.starttls(context=self.ssl_context) + if self.username and self.password: + self.connection.login(self.username, self.password) + return True + except OSError: + if not self.fail_silently: + raise + + def close(self): + """Close the connection to the email server.""" + if self.connection is None: + return + try: + try: + self.connection.quit() + except (ssl.SSLError, smtplib.SMTPServerDisconnected): + # This happens when calling quit() on a TLS connection + # sometimes, or when the connection was already disconnected + # by the server. + self.connection.close() + except smtplib.SMTPException: + if self.fail_silently: + return + raise + finally: + self.connection = None + + def send_messages(self, email_messages): + """ + Send one or more EmailMessage objects and return the number of email + messages sent. + """ + if not email_messages: + return 0 + with self._lock: + new_conn_created = self.open() + if not self.connection or new_conn_created is None: + # We failed silently on open(). + # Trying to send would be pointless. + return 0 + num_sent = 0 + try: + for message in email_messages: + sent = self._send(message) + if sent: + num_sent += 1 + finally: + if new_conn_created: + self.close() + return num_sent + + def _send(self, email_message): + """A helper method that does the actual sending.""" + if not email_message.recipients(): + return False + encoding = email_message.encoding or settings.DEFAULT_CHARSET + from_email = sanitize_address(email_message.from_email, encoding) + recipients = [ + sanitize_address(addr, encoding) for addr in email_message.recipients() + ] + message = email_message.message() + try: + self.connection.sendmail( + from_email, recipients, message.as_bytes(linesep="\r\n") + ) + except smtplib.SMTPException: + if not self.fail_silently: + raise + return False + return True diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/message.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/message.py new file mode 100644 index 0000000..4f8c93e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/message.py @@ -0,0 +1,495 @@ +import mimetypes +from email import charset as Charset +from email import encoders as Encoders +from email import generator, message_from_string +from email.errors import HeaderParseError +from email.header import Header +from email.headerregistry import Address, parser +from email.message import Message +from email.mime.base import MIMEBase +from email.mime.message import MIMEMessage +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText +from email.utils import formataddr, formatdate, getaddresses, make_msgid +from io import BytesIO, StringIO +from pathlib import Path + +from django.conf import settings +from django.core.mail.utils import DNS_NAME +from django.utils.encoding import force_str, punycode + +# Don't BASE64-encode UTF-8 messages so that we avoid unwanted attention from +# some spam filters. +utf8_charset = Charset.Charset("utf-8") +utf8_charset.body_encoding = None # Python defaults to BASE64 +utf8_charset_qp = Charset.Charset("utf-8") +utf8_charset_qp.body_encoding = Charset.QP + +# Default MIME type to use on attachments (if it is not explicitly given +# and cannot be guessed). +DEFAULT_ATTACHMENT_MIME_TYPE = "application/octet-stream" + +RFC5322_EMAIL_LINE_LENGTH_LIMIT = 998 + + +class BadHeaderError(ValueError): + pass + + +# Header names that contain structured address data (RFC 5322). +ADDRESS_HEADERS = { + "from", + "sender", + "reply-to", + "to", + "cc", + "bcc", + "resent-from", + "resent-sender", + "resent-to", + "resent-cc", + "resent-bcc", +} + + +def forbid_multi_line_headers(name, val, encoding): + """Forbid multi-line headers to prevent header injection.""" + encoding = encoding or settings.DEFAULT_CHARSET + val = str(val) # val may be lazy + if "\n" in val or "\r" in val: + raise BadHeaderError( + "Header values can't contain newlines (got %r for header %r)" % (val, name) + ) + try: + val.encode("ascii") + except UnicodeEncodeError: + if name.lower() in ADDRESS_HEADERS: + val = ", ".join( + sanitize_address(addr, encoding) for addr in getaddresses((val,)) + ) + else: + val = Header(val, encoding).encode() + else: + if name.lower() == "subject": + val = Header(val).encode() + return name, val + + +def sanitize_address(addr, encoding): + """ + Format a pair of (name, address) or an email address string. + """ + address = None + if not isinstance(addr, tuple): + addr = force_str(addr) + try: + token, rest = parser.get_mailbox(addr) + except (HeaderParseError, ValueError, IndexError): + raise ValueError('Invalid address "%s"' % addr) + else: + if rest: + # The entire email address must be parsed. + raise ValueError( + 'Invalid address; only %s could be parsed from "%s"' % (token, addr) + ) + nm = token.display_name or "" + localpart = token.local_part + domain = token.domain or "" + else: + nm, address = addr + if "@" not in address: + raise ValueError(f'Invalid address "{address}"') + localpart, domain = address.rsplit("@", 1) + + address_parts = nm + localpart + domain + if "\n" in address_parts or "\r" in address_parts: + raise ValueError("Invalid address; address parts cannot contain newlines.") + + # Avoid UTF-8 encode, if it's possible. + try: + nm.encode("ascii") + nm = Header(nm).encode() + except UnicodeEncodeError: + nm = Header(nm, encoding).encode() + try: + localpart.encode("ascii") + except UnicodeEncodeError: + localpart = Header(localpart, encoding).encode() + domain = punycode(domain) + + parsed_address = Address(username=localpart, domain=domain) + return formataddr((nm, parsed_address.addr_spec)) + + +class MIMEMixin: + def as_string(self, unixfrom=False, linesep="\n"): + """Return the entire formatted message as a string. + Optional `unixfrom' when True, means include the Unix From_ envelope + header. + + This overrides the default as_string() implementation to not mangle + lines that begin with 'From '. See bug #13433 for details. + """ + fp = StringIO() + g = generator.Generator(fp, mangle_from_=False) + g.flatten(self, unixfrom=unixfrom, linesep=linesep) + return fp.getvalue() + + def as_bytes(self, unixfrom=False, linesep="\n"): + """Return the entire formatted message as bytes. + Optional `unixfrom' when True, means include the Unix From_ envelope + header. + + This overrides the default as_bytes() implementation to not mangle + lines that begin with 'From '. See bug #13433 for details. + """ + fp = BytesIO() + g = generator.BytesGenerator(fp, mangle_from_=False) + g.flatten(self, unixfrom=unixfrom, linesep=linesep) + return fp.getvalue() + + +class SafeMIMEMessage(MIMEMixin, MIMEMessage): + def __setitem__(self, name, val): + # message/rfc822 attachments must be ASCII + name, val = forbid_multi_line_headers(name, val, "ascii") + MIMEMessage.__setitem__(self, name, val) + + +class SafeMIMEText(MIMEMixin, MIMEText): + def __init__(self, _text, _subtype="plain", _charset=None): + self.encoding = _charset + MIMEText.__init__(self, _text, _subtype=_subtype, _charset=_charset) + + def __setitem__(self, name, val): + name, val = forbid_multi_line_headers(name, val, self.encoding) + MIMEText.__setitem__(self, name, val) + + def set_payload(self, payload, charset=None): + if charset == "utf-8" and not isinstance(charset, Charset.Charset): + has_long_lines = any( + len(line.encode()) > RFC5322_EMAIL_LINE_LENGTH_LIMIT + for line in payload.splitlines() + ) + # Quoted-Printable encoding has the side effect of shortening long + # lines, if any (#22561). + charset = utf8_charset_qp if has_long_lines else utf8_charset + MIMEText.set_payload(self, payload, charset=charset) + + +class SafeMIMEMultipart(MIMEMixin, MIMEMultipart): + def __init__( + self, _subtype="mixed", boundary=None, _subparts=None, encoding=None, **_params + ): + self.encoding = encoding + MIMEMultipart.__init__(self, _subtype, boundary, _subparts, **_params) + + def __setitem__(self, name, val): + name, val = forbid_multi_line_headers(name, val, self.encoding) + MIMEMultipart.__setitem__(self, name, val) + + +class EmailMessage: + """A container for email information.""" + + content_subtype = "plain" + mixed_subtype = "mixed" + encoding = None # None => use settings default + + def __init__( + self, + subject="", + body="", + from_email=None, + to=None, + bcc=None, + connection=None, + attachments=None, + headers=None, + cc=None, + reply_to=None, + ): + """ + Initialize a single email message (which can be sent to multiple + recipients). + """ + if to: + if isinstance(to, str): + raise TypeError('"to" argument must be a list or tuple') + self.to = list(to) + else: + self.to = [] + if cc: + if isinstance(cc, str): + raise TypeError('"cc" argument must be a list or tuple') + self.cc = list(cc) + else: + self.cc = [] + if bcc: + if isinstance(bcc, str): + raise TypeError('"bcc" argument must be a list or tuple') + self.bcc = list(bcc) + else: + self.bcc = [] + if reply_to: + if isinstance(reply_to, str): + raise TypeError('"reply_to" argument must be a list or tuple') + self.reply_to = list(reply_to) + else: + self.reply_to = [] + self.from_email = from_email or settings.DEFAULT_FROM_EMAIL + self.subject = subject + self.body = body or "" + self.attachments = [] + if attachments: + for attachment in attachments: + if isinstance(attachment, MIMEBase): + self.attach(attachment) + else: + self.attach(*attachment) + self.extra_headers = headers or {} + self.connection = connection + + def get_connection(self, fail_silently=False): + from django.core.mail import get_connection + + if not self.connection: + self.connection = get_connection(fail_silently=fail_silently) + return self.connection + + def message(self): + encoding = self.encoding or settings.DEFAULT_CHARSET + msg = SafeMIMEText(self.body, self.content_subtype, encoding) + msg = self._create_message(msg) + msg["Subject"] = self.subject + msg["From"] = self.extra_headers.get("From", self.from_email) + self._set_list_header_if_not_empty(msg, "To", self.to) + self._set_list_header_if_not_empty(msg, "Cc", self.cc) + self._set_list_header_if_not_empty(msg, "Reply-To", self.reply_to) + + # Email header names are case-insensitive (RFC 2045), so we have to + # accommodate that when doing comparisons. + header_names = [key.lower() for key in self.extra_headers] + if "date" not in header_names: + # formatdate() uses stdlib methods to format the date, which use + # the stdlib/OS concept of a timezone, however, Django sets the + # TZ environment variable based on the TIME_ZONE setting which + # will get picked up by formatdate(). + msg["Date"] = formatdate(localtime=settings.EMAIL_USE_LOCALTIME) + if "message-id" not in header_names: + # Use cached DNS_NAME for performance + msg["Message-ID"] = make_msgid(domain=DNS_NAME) + for name, value in self.extra_headers.items(): + if name.lower() != "from": # From is already handled + msg[name] = value + return msg + + def recipients(self): + """ + Return a list of all recipients of the email (includes direct + addressees as well as Cc and Bcc entries). + """ + return [email for email in (self.to + self.cc + self.bcc) if email] + + def send(self, fail_silently=False): + """Send the email message.""" + if not self.recipients(): + # Don't bother creating the network connection if there's nobody to + # send to. + return 0 + return self.get_connection(fail_silently).send_messages([self]) + + def attach(self, filename=None, content=None, mimetype=None): + """ + Attach a file with the given filename and content. The filename can + be omitted and the mimetype is guessed, if not provided. + + If the first parameter is a MIMEBase subclass, insert it directly + into the resulting message attachments. + + For a text/* mimetype (guessed or specified), when a bytes object is + specified as content, decode it as UTF-8. If that fails, set the + mimetype to DEFAULT_ATTACHMENT_MIME_TYPE and don't decode the content. + """ + if isinstance(filename, MIMEBase): + if content is not None or mimetype is not None: + raise ValueError( + "content and mimetype must not be given when a MIMEBase " + "instance is provided." + ) + self.attachments.append(filename) + elif content is None: + raise ValueError("content must be provided.") + else: + mimetype = ( + mimetype + or mimetypes.guess_type(filename)[0] + or DEFAULT_ATTACHMENT_MIME_TYPE + ) + basetype, subtype = mimetype.split("/", 1) + + if basetype == "text": + if isinstance(content, bytes): + try: + content = content.decode() + except UnicodeDecodeError: + # If mimetype suggests the file is text but it's + # actually binary, read() raises a UnicodeDecodeError. + mimetype = DEFAULT_ATTACHMENT_MIME_TYPE + + self.attachments.append((filename, content, mimetype)) + + def attach_file(self, path, mimetype=None): + """ + Attach a file from the filesystem. + + Set the mimetype to DEFAULT_ATTACHMENT_MIME_TYPE if it isn't specified + and cannot be guessed. + + For a text/* mimetype (guessed or specified), decode the file's content + as UTF-8. If that fails, set the mimetype to + DEFAULT_ATTACHMENT_MIME_TYPE and don't decode the content. + """ + path = Path(path) + with path.open("rb") as file: + content = file.read() + self.attach(path.name, content, mimetype) + + def _create_message(self, msg): + return self._create_attachments(msg) + + def _create_attachments(self, msg): + if self.attachments: + encoding = self.encoding or settings.DEFAULT_CHARSET + body_msg = msg + msg = SafeMIMEMultipart(_subtype=self.mixed_subtype, encoding=encoding) + if self.body or body_msg.is_multipart(): + msg.attach(body_msg) + for attachment in self.attachments: + if isinstance(attachment, MIMEBase): + msg.attach(attachment) + else: + msg.attach(self._create_attachment(*attachment)) + return msg + + def _create_mime_attachment(self, content, mimetype): + """ + Convert the content, mimetype pair into a MIME attachment object. + + If the mimetype is message/rfc822, content may be an + email.Message or EmailMessage object, as well as a str. + """ + basetype, subtype = mimetype.split("/", 1) + if basetype == "text": + encoding = self.encoding or settings.DEFAULT_CHARSET + attachment = SafeMIMEText(content, subtype, encoding) + elif basetype == "message" and subtype == "rfc822": + # Bug #18967: Per RFC 2046 Section 5.2.1, message/rfc822 + # attachments must not be base64 encoded. + if isinstance(content, EmailMessage): + # convert content into an email.Message first + content = content.message() + elif not isinstance(content, Message): + # For compatibility with existing code, parse the message + # into an email.Message object if it is not one already. + content = message_from_string(force_str(content)) + + attachment = SafeMIMEMessage(content, subtype) + else: + # Encode non-text attachments with base64. + attachment = MIMEBase(basetype, subtype) + attachment.set_payload(content) + Encoders.encode_base64(attachment) + return attachment + + def _create_attachment(self, filename, content, mimetype=None): + """ + Convert the filename, content, mimetype triple into a MIME attachment + object. + """ + attachment = self._create_mime_attachment(content, mimetype) + if filename: + try: + filename.encode("ascii") + except UnicodeEncodeError: + filename = ("utf-8", "", filename) + attachment.add_header( + "Content-Disposition", "attachment", filename=filename + ) + return attachment + + def _set_list_header_if_not_empty(self, msg, header, values): + """ + Set msg's header, either from self.extra_headers, if present, or from + the values argument. + """ + if values: + try: + value = self.extra_headers[header] + except KeyError: + value = ", ".join(str(v) for v in values) + msg[header] = value + + +class EmailMultiAlternatives(EmailMessage): + """ + A version of EmailMessage that makes it easy to send multipart/alternative + messages. For example, including text and HTML versions of the text is + made easier. + """ + + alternative_subtype = "alternative" + + def __init__( + self, + subject="", + body="", + from_email=None, + to=None, + bcc=None, + connection=None, + attachments=None, + headers=None, + alternatives=None, + cc=None, + reply_to=None, + ): + """ + Initialize a single email message (which can be sent to multiple + recipients). + """ + super().__init__( + subject, + body, + from_email, + to, + bcc, + connection, + attachments, + headers, + cc, + reply_to, + ) + self.alternatives = alternatives or [] + + def attach_alternative(self, content, mimetype): + """Attach an alternative content representation.""" + if content is None or mimetype is None: + raise ValueError("Both content and mimetype must be provided.") + self.alternatives.append((content, mimetype)) + + def _create_message(self, msg): + return self._create_attachments(self._create_alternatives(msg)) + + def _create_alternatives(self, msg): + encoding = self.encoding or settings.DEFAULT_CHARSET + if self.alternatives: + body_msg = msg + msg = SafeMIMEMultipart( + _subtype=self.alternative_subtype, encoding=encoding + ) + if self.body: + msg.attach(body_msg) + for alternative in self.alternatives: + msg.attach(self._create_mime_attachment(*alternative)) + return msg diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/utils.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/utils.py new file mode 100644 index 0000000..8143c23 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/mail/utils.py @@ -0,0 +1,22 @@ +""" +Email message and email sending related helper functions. +""" + +import socket + +from django.utils.encoding import punycode + + +# Cache the hostname, but do it lazily: socket.getfqdn() can take a couple of +# seconds, which slows down the restart of the server. +class CachedDnsName: + def __str__(self): + return self.get_fqdn() + + def get_fqdn(self): + if not hasattr(self, "_fqdn"): + self._fqdn = punycode(socket.getfqdn()) + return self._fqdn + + +DNS_NAME = CachedDnsName() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/__init__.py new file mode 100644 index 0000000..0c16447 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/__init__.py @@ -0,0 +1,442 @@ +import functools +import os +import pkgutil +import sys +from argparse import ( + _AppendConstAction, + _CountAction, + _StoreConstAction, + _SubParsersAction, +) +from collections import defaultdict +from difflib import get_close_matches +from importlib import import_module + +import django +from django.apps import apps +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.core.management.base import ( + BaseCommand, + CommandError, + CommandParser, + handle_default_options, +) +from django.core.management.color import color_style +from django.utils import autoreload + + +def find_commands(management_dir): + """ + Given a path to a management directory, return a list of all the command + names that are available. + """ + command_dir = os.path.join(management_dir, "commands") + return [ + name + for _, name, is_pkg in pkgutil.iter_modules([command_dir]) + if not is_pkg and not name.startswith("_") + ] + + +def load_command_class(app_name, name): + """ + Given a command name and an application name, return the Command + class instance. Allow all errors raised by the import process + (ImportError, AttributeError) to propagate. + """ + module = import_module("%s.management.commands.%s" % (app_name, name)) + return module.Command() + + +@functools.cache +def get_commands(): + """ + Return a dictionary mapping command names to their callback applications. + + Look for a management.commands package in django.core, and in each + installed application -- if a commands package exists, register all + commands in that package. + + Core commands are always included. If a settings module has been + specified, also include user-defined commands. + + The dictionary is in the format {command_name: app_name}. Key-value + pairs from this dictionary can then be used in calls to + load_command_class(app_name, command_name) + + The dictionary is cached on the first call and reused on subsequent + calls. + """ + commands = {name: "django.core" for name in find_commands(__path__[0])} + + if not settings.configured: + return commands + + for app_config in reversed(apps.get_app_configs()): + path = os.path.join(app_config.path, "management") + commands.update({name: app_config.name for name in find_commands(path)}) + + return commands + + +def call_command(command_name, *args, **options): + """ + Call the given command, with the given options and args/kwargs. + + This is the primary API you should use for calling specific commands. + + `command_name` may be a string or a command object. Using a string is + preferred unless the command object is required for further processing or + testing. + + Some examples: + call_command('migrate') + call_command('shell', plain=True) + call_command('sqlmigrate', 'myapp') + + from django.core.management.commands import flush + cmd = flush.Command() + call_command(cmd, verbosity=0, interactive=False) + # Do something with cmd ... + """ + if isinstance(command_name, BaseCommand): + # Command object passed in. + command = command_name + command_name = command.__class__.__module__.split(".")[-1] + else: + # Load the command object by name. + try: + app_name = get_commands()[command_name] + except KeyError: + raise CommandError("Unknown command: %r" % command_name) + + if isinstance(app_name, BaseCommand): + # If the command is already loaded, use it directly. + command = app_name + else: + command = load_command_class(app_name, command_name) + + # Simulate argument parsing to get the option defaults (see #10080 for details). + parser = command.create_parser("", command_name) + # Use the `dest` option name from the parser option + opt_mapping = { + min(s_opt.option_strings).lstrip("-").replace("-", "_"): s_opt.dest + for s_opt in parser._actions + if s_opt.option_strings + } + arg_options = {opt_mapping.get(key, key): value for key, value in options.items()} + parse_args = [] + for arg in args: + if isinstance(arg, (list, tuple)): + parse_args += map(str, arg) + else: + parse_args.append(str(arg)) + + def get_actions(parser): + # Parser actions and actions from sub-parser choices. + for opt in parser._actions: + if isinstance(opt, _SubParsersAction): + for sub_opt in opt.choices.values(): + yield from get_actions(sub_opt) + else: + yield opt + + parser_actions = list(get_actions(parser)) + mutually_exclusive_required_options = { + opt + for group in parser._mutually_exclusive_groups + for opt in group._group_actions + if group.required + } + # Any required arguments which are passed in via **options must be passed + # to parse_args(). + for opt in parser_actions: + if opt.dest in options and ( + opt.required or opt in mutually_exclusive_required_options + ): + opt_dest_count = sum(v == opt.dest for v in opt_mapping.values()) + if opt_dest_count > 1: + raise TypeError( + f"Cannot pass the dest {opt.dest!r} that matches multiple " + f"arguments via **options." + ) + parse_args.append(min(opt.option_strings)) + if isinstance(opt, (_AppendConstAction, _CountAction, _StoreConstAction)): + continue + value = arg_options[opt.dest] + if isinstance(value, (list, tuple)): + parse_args += map(str, value) + else: + parse_args.append(str(value)) + defaults = parser.parse_args(args=parse_args) + defaults = dict(defaults._get_kwargs(), **arg_options) + # Raise an error if any unknown options were passed. + stealth_options = set(command.base_stealth_options + command.stealth_options) + dest_parameters = {action.dest for action in parser_actions} + valid_options = (dest_parameters | stealth_options).union(opt_mapping) + unknown_options = set(options) - valid_options + if unknown_options: + raise TypeError( + "Unknown option(s) for %s command: %s. " + "Valid options are: %s." + % ( + command_name, + ", ".join(sorted(unknown_options)), + ", ".join(sorted(valid_options)), + ) + ) + # Move positional args out of options to mimic legacy optparse + args = defaults.pop("args", ()) + if "skip_checks" not in options: + defaults["skip_checks"] = True + + return command.execute(*args, **defaults) + + +class ManagementUtility: + """ + Encapsulate the logic of the django-admin and manage.py utilities. + """ + + def __init__(self, argv=None): + self.argv = argv or sys.argv[:] + self.prog_name = os.path.basename(self.argv[0]) + if self.prog_name == "__main__.py": + self.prog_name = "python -m django" + self.settings_exception = None + + def main_help_text(self, commands_only=False): + """Return the script's main help text, as a string.""" + if commands_only: + usage = sorted(get_commands()) + else: + usage = [ + "", + "Type '%s help ' for help on a specific subcommand." + % self.prog_name, + "", + "Available subcommands:", + ] + commands_dict = defaultdict(lambda: []) + for name, app in get_commands().items(): + if app == "django.core": + app = "django" + else: + app = app.rpartition(".")[-1] + commands_dict[app].append(name) + style = color_style() + for app in sorted(commands_dict): + usage.append("") + usage.append(style.NOTICE("[%s]" % app)) + for name in sorted(commands_dict[app]): + usage.append(" %s" % name) + # Output an extra note if settings are not properly configured + if self.settings_exception is not None: + usage.append( + style.NOTICE( + "Note that only Django core commands are listed " + "as settings are not properly configured (error: %s)." + % self.settings_exception + ) + ) + + return "\n".join(usage) + + def fetch_command(self, subcommand): + """ + Try to fetch the given subcommand, printing a message with the + appropriate command called from the command line (usually + "django-admin" or "manage.py") if it can't be found. + """ + # Get commands outside of try block to prevent swallowing exceptions + commands = get_commands() + try: + app_name = commands[subcommand] + except KeyError: + if os.environ.get("DJANGO_SETTINGS_MODULE"): + # If `subcommand` is missing due to misconfigured settings, the + # following line will retrigger an ImproperlyConfigured exception + # (get_commands() swallows the original one) so the user is + # informed about it. + settings.INSTALLED_APPS + elif not settings.configured: + sys.stderr.write("No Django settings specified.\n") + possible_matches = get_close_matches(subcommand, commands) + sys.stderr.write("Unknown command: %r" % subcommand) + if possible_matches: + sys.stderr.write(". Did you mean %s?" % possible_matches[0]) + sys.stderr.write("\nType '%s help' for usage.\n" % self.prog_name) + sys.exit(1) + if isinstance(app_name, BaseCommand): + # If the command is already loaded, use it directly. + klass = app_name + else: + klass = load_command_class(app_name, subcommand) + return klass + + def autocomplete(self): + """ + Output completion suggestions for BASH. + + The output of this function is passed to BASH's `COMPREPLY` variable + and treated as completion suggestions. `COMPREPLY` expects a space + separated string as the result. + + The `COMP_WORDS` and `COMP_CWORD` BASH environment variables are used + to get information about the cli input. Please refer to the BASH + man-page for more information about this variables. + + Subcommand options are saved as pairs. A pair consists of + the long option string (e.g. '--exclude') and a boolean + value indicating if the option requires arguments. When printing to + stdout, an equal sign is appended to options which require arguments. + + Note: If debugging this function, it is recommended to write the debug + output in a separate file. Otherwise the debug output will be treated + and formatted as potential completion suggestions. + """ + # Don't complete if user hasn't sourced bash_completion file. + if "DJANGO_AUTO_COMPLETE" not in os.environ: + return + + cwords = os.environ["COMP_WORDS"].split()[1:] + cword = int(os.environ["COMP_CWORD"]) + + try: + curr = cwords[cword - 1] + except IndexError: + curr = "" + + subcommands = [*get_commands(), "help"] + options = [("--help", False)] + + # subcommand + if cword == 1: + print(" ".join(sorted(filter(lambda x: x.startswith(curr), subcommands)))) + # subcommand options + # special case: the 'help' subcommand has no options + elif cwords[0] in subcommands and cwords[0] != "help": + subcommand_cls = self.fetch_command(cwords[0]) + # special case: add the names of installed apps to options + if cwords[0] in ("dumpdata", "sqlmigrate", "sqlsequencereset", "test"): + try: + app_configs = apps.get_app_configs() + # Get the last part of the dotted path as the app name. + options.extend((app_config.label, 0) for app_config in app_configs) + except ImportError: + # Fail silently if DJANGO_SETTINGS_MODULE isn't set. The + # user will find out once they execute the command. + pass + parser = subcommand_cls.create_parser("", cwords[0]) + options.extend( + (min(s_opt.option_strings), s_opt.nargs != 0) + for s_opt in parser._actions + if s_opt.option_strings + ) + # filter out previously specified options from available options + prev_opts = {x.split("=")[0] for x in cwords[1 : cword - 1]} + options = (opt for opt in options if opt[0] not in prev_opts) + + # filter options by current input + options = sorted((k, v) for k, v in options if k.startswith(curr)) + for opt_label, require_arg in options: + # append '=' to options which require args + if require_arg: + opt_label += "=" + print(opt_label) + # Exit code of the bash completion function is never passed back to + # the user, so it's safe to always exit with 0. + # For more details see #25420. + sys.exit(0) + + def execute(self): + """ + Given the command-line arguments, figure out which subcommand is being + run, create a parser appropriate to that command, and run it. + """ + try: + subcommand = self.argv[1] + except IndexError: + subcommand = "help" # Display help if no arguments were given. + + # Preprocess options to extract --settings and --pythonpath. + # These options could affect the commands that are available, so they + # must be processed early. + parser = CommandParser( + prog=self.prog_name, + usage="%(prog)s subcommand [options] [args]", + add_help=False, + allow_abbrev=False, + ) + parser.add_argument("--settings") + parser.add_argument("--pythonpath") + parser.add_argument("args", nargs="*") # catch-all + try: + options, args = parser.parse_known_args(self.argv[2:]) + handle_default_options(options) + except CommandError: + pass # Ignore any option errors at this point. + + try: + settings.INSTALLED_APPS + except ImproperlyConfigured as exc: + self.settings_exception = exc + except ImportError as exc: + self.settings_exception = exc + + if settings.configured: + # Start the auto-reloading dev server even if the code is broken. + # The hardcoded condition is a code smell but we can't rely on a + # flag on the command class because we haven't located it yet. + if subcommand == "runserver" and "--noreload" not in self.argv: + try: + autoreload.check_errors(django.setup)() + except Exception: + # The exception will be raised later in the child process + # started by the autoreloader. Pretend it didn't happen by + # loading an empty list of applications. + apps.all_models = defaultdict(dict) + apps.app_configs = {} + apps.apps_ready = apps.models_ready = apps.ready = True + + # Remove options not compatible with the built-in runserver + # (e.g. options for the contrib.staticfiles' runserver). + # Changes here require manually testing as described in + # #27522. + _parser = self.fetch_command("runserver").create_parser( + "django", "runserver" + ) + _options, _args = _parser.parse_known_args(self.argv[2:]) + for _arg in _args: + self.argv.remove(_arg) + + # In all other cases, django.setup() is required to succeed. + else: + django.setup() + + self.autocomplete() + + if subcommand == "help": + if "--commands" in args: + sys.stdout.write(self.main_help_text(commands_only=True) + "\n") + elif not options.args: + sys.stdout.write(self.main_help_text() + "\n") + else: + self.fetch_command(options.args[0]).print_help( + self.prog_name, options.args[0] + ) + # Special-cases: We want 'django-admin --version' and + # 'django-admin --help' to work, for backwards compatibility. + elif subcommand == "version" or self.argv[1:] == ["--version"]: + sys.stdout.write(django.get_version() + "\n") + elif self.argv[1:] in (["--help"], ["-h"]): + sys.stdout.write(self.main_help_text() + "\n") + else: + self.fetch_command(subcommand).run_from_argv(self.argv) + + +def execute_from_command_line(argv=None): + """Run a ManagementUtility.""" + utility = ManagementUtility(argv) + utility.execute() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/base.py new file mode 100644 index 0000000..631c761 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/base.py @@ -0,0 +1,688 @@ +""" +Base classes for writing management commands (named commands which can +be executed through ``django-admin`` or ``manage.py``). +""" +import argparse +import os +import sys +from argparse import ArgumentParser, HelpFormatter +from functools import partial +from io import TextIOBase + +import django +from django.core import checks +from django.core.exceptions import ImproperlyConfigured +from django.core.management.color import color_style, no_style +from django.db import DEFAULT_DB_ALIAS, connections + +ALL_CHECKS = "__all__" + + +class CommandError(Exception): + """ + Exception class indicating a problem while executing a management + command. + + If this exception is raised during the execution of a management + command, it will be caught and turned into a nicely-printed error + message to the appropriate output stream (i.e., stderr); as a + result, raising this exception (with a sensible description of the + error) is the preferred way to indicate that something has gone + wrong in the execution of a command. + """ + + def __init__(self, *args, returncode=1, **kwargs): + self.returncode = returncode + super().__init__(*args, **kwargs) + + +class SystemCheckError(CommandError): + """ + The system check framework detected unrecoverable errors. + """ + + pass + + +class CommandParser(ArgumentParser): + """ + Customized ArgumentParser class to improve some error messages and prevent + SystemExit in several occasions, as SystemExit is unacceptable when a + command is called programmatically. + """ + + def __init__( + self, *, missing_args_message=None, called_from_command_line=None, **kwargs + ): + self.missing_args_message = missing_args_message + self.called_from_command_line = called_from_command_line + super().__init__(**kwargs) + + def parse_args(self, args=None, namespace=None): + # Catch missing argument for a better error message + if self.missing_args_message and not ( + args or any(not arg.startswith("-") for arg in args) + ): + self.error(self.missing_args_message) + return super().parse_args(args, namespace) + + def error(self, message): + if self.called_from_command_line: + super().error(message) + else: + raise CommandError("Error: %s" % message) + + def add_subparsers(self, **kwargs): + parser_class = kwargs.get("parser_class", type(self)) + if issubclass(parser_class, CommandParser): + kwargs["parser_class"] = partial( + parser_class, + called_from_command_line=self.called_from_command_line, + ) + return super().add_subparsers(**kwargs) + + +def handle_default_options(options): + """ + Include any default options that all commands should accept here + so that ManagementUtility can handle them before searching for + user commands. + """ + if options.settings: + os.environ["DJANGO_SETTINGS_MODULE"] = options.settings + if options.pythonpath: + sys.path.insert(0, options.pythonpath) + + +def no_translations(handle_func): + """Decorator that forces a command to run with translations deactivated.""" + + def wrapper(*args, **kwargs): + from django.utils import translation + + saved_locale = translation.get_language() + translation.deactivate_all() + try: + res = handle_func(*args, **kwargs) + finally: + if saved_locale is not None: + translation.activate(saved_locale) + return res + + return wrapper + + +class DjangoHelpFormatter(HelpFormatter): + """ + Customized formatter so that command-specific arguments appear in the + --help output before arguments common to all commands. + """ + + show_last = { + "--version", + "--verbosity", + "--traceback", + "--settings", + "--pythonpath", + "--no-color", + "--force-color", + "--skip-checks", + } + + def _reordered_actions(self, actions): + return sorted( + actions, key=lambda a: set(a.option_strings) & self.show_last != set() + ) + + def add_usage(self, usage, actions, *args, **kwargs): + super().add_usage(usage, self._reordered_actions(actions), *args, **kwargs) + + def add_arguments(self, actions): + super().add_arguments(self._reordered_actions(actions)) + + +class OutputWrapper(TextIOBase): + """ + Wrapper around stdout/stderr + """ + + @property + def style_func(self): + return self._style_func + + @style_func.setter + def style_func(self, style_func): + if style_func and self.isatty(): + self._style_func = style_func + else: + self._style_func = lambda x: x + + def __init__(self, out, ending="\n"): + self._out = out + self.style_func = None + self.ending = ending + + def __getattr__(self, name): + return getattr(self._out, name) + + def flush(self): + if hasattr(self._out, "flush"): + self._out.flush() + + def isatty(self): + return hasattr(self._out, "isatty") and self._out.isatty() + + def write(self, msg="", style_func=None, ending=None): + ending = self.ending if ending is None else ending + if ending and not msg.endswith(ending): + msg += ending + style_func = style_func or self.style_func + self._out.write(style_func(msg)) + + +class BaseCommand: + """ + The base class from which all management commands ultimately + derive. + + Use this class if you want access to all of the mechanisms which + parse the command-line arguments and work out what code to call in + response; if you don't need to change any of that behavior, + consider using one of the subclasses defined in this file. + + If you are interested in overriding/customizing various aspects of + the command-parsing and -execution behavior, the normal flow works + as follows: + + 1. ``django-admin`` or ``manage.py`` loads the command class + and calls its ``run_from_argv()`` method. + + 2. The ``run_from_argv()`` method calls ``create_parser()`` to get + an ``ArgumentParser`` for the arguments, parses them, performs + any environment changes requested by options like + ``pythonpath``, and then calls the ``execute()`` method, + passing the parsed arguments. + + 3. The ``execute()`` method attempts to carry out the command by + calling the ``handle()`` method with the parsed arguments; any + output produced by ``handle()`` will be printed to standard + output and, if the command is intended to produce a block of + SQL statements, will be wrapped in ``BEGIN`` and ``COMMIT``. + + 4. If ``handle()`` or ``execute()`` raised any exception (e.g. + ``CommandError``), ``run_from_argv()`` will instead print an error + message to ``stderr``. + + Thus, the ``handle()`` method is typically the starting point for + subclasses; many built-in commands and command types either place + all of their logic in ``handle()``, or perform some additional + parsing work in ``handle()`` and then delegate from it to more + specialized methods as needed. + + Several attributes affect behavior at various steps along the way: + + ``help`` + A short description of the command, which will be printed in + help messages. + + ``output_transaction`` + A boolean indicating whether the command outputs SQL + statements; if ``True``, the output will automatically be + wrapped with ``BEGIN;`` and ``COMMIT;``. Default value is + ``False``. + + ``requires_migrations_checks`` + A boolean; if ``True``, the command prints a warning if the set of + migrations on disk don't match the migrations in the database. + + ``requires_system_checks`` + A list or tuple of tags, e.g. [Tags.staticfiles, Tags.models]. System + checks registered in the chosen tags will be checked for errors prior + to executing the command. The value '__all__' can be used to specify + that all system checks should be performed. Default value is '__all__'. + + To validate an individual application's models + rather than all applications' models, call + ``self.check(app_configs)`` from ``handle()``, where ``app_configs`` + is the list of application's configuration provided by the + app registry. + + ``stealth_options`` + A tuple of any options the command uses which aren't defined by the + argument parser. + """ + + # Metadata about this command. + help = "" + + # Configuration shortcuts that alter various logic. + _called_from_command_line = False + output_transaction = False # Whether to wrap the output in a "BEGIN; COMMIT;" + requires_migrations_checks = False + requires_system_checks = "__all__" + # Arguments, common to all commands, which aren't defined by the argument + # parser. + base_stealth_options = ("stderr", "stdout") + # Command-specific options not defined by the argument parser. + stealth_options = () + suppressed_base_arguments = set() + + def __init__(self, stdout=None, stderr=None, no_color=False, force_color=False): + self.stdout = OutputWrapper(stdout or sys.stdout) + self.stderr = OutputWrapper(stderr or sys.stderr) + if no_color and force_color: + raise CommandError("'no_color' and 'force_color' can't be used together.") + if no_color: + self.style = no_style() + else: + self.style = color_style(force_color) + self.stderr.style_func = self.style.ERROR + if ( + not isinstance(self.requires_system_checks, (list, tuple)) + and self.requires_system_checks != ALL_CHECKS + ): + raise TypeError("requires_system_checks must be a list or tuple.") + + def get_version(self): + """ + Return the Django version, which should be correct for all built-in + Django commands. User-supplied commands can override this method to + return their own version. + """ + return django.get_version() + + def create_parser(self, prog_name, subcommand, **kwargs): + """ + Create and return the ``ArgumentParser`` which will be used to + parse the arguments to this command. + """ + kwargs.setdefault("formatter_class", DjangoHelpFormatter) + parser = CommandParser( + prog="%s %s" % (os.path.basename(prog_name), subcommand), + description=self.help or None, + missing_args_message=getattr(self, "missing_args_message", None), + called_from_command_line=getattr(self, "_called_from_command_line", None), + **kwargs, + ) + self.add_base_argument( + parser, + "--version", + action="version", + version=self.get_version(), + help="Show program's version number and exit.", + ) + self.add_base_argument( + parser, + "-v", + "--verbosity", + default=1, + type=int, + choices=[0, 1, 2, 3], + help=( + "Verbosity level; 0=minimal output, 1=normal output, 2=verbose output, " + "3=very verbose output" + ), + ) + self.add_base_argument( + parser, + "--settings", + help=( + "The Python path to a settings module, e.g. " + '"myproject.settings.main". If this isn\'t provided, the ' + "DJANGO_SETTINGS_MODULE environment variable will be used." + ), + ) + self.add_base_argument( + parser, + "--pythonpath", + help=( + "A directory to add to the Python path, e.g. " + '"/home/djangoprojects/myproject".' + ), + ) + self.add_base_argument( + parser, + "--traceback", + action="store_true", + help="Raise on CommandError exceptions.", + ) + self.add_base_argument( + parser, + "--no-color", + action="store_true", + help="Don't colorize the command output.", + ) + self.add_base_argument( + parser, + "--force-color", + action="store_true", + help="Force colorization of the command output.", + ) + if self.requires_system_checks: + parser.add_argument( + "--skip-checks", + action="store_true", + help="Skip system checks.", + ) + self.add_arguments(parser) + return parser + + def add_arguments(self, parser): + """ + Entry point for subclassed commands to add custom arguments. + """ + pass + + def add_base_argument(self, parser, *args, **kwargs): + """ + Call the parser's add_argument() method, suppressing the help text + according to BaseCommand.suppressed_base_arguments. + """ + for arg in args: + if arg in self.suppressed_base_arguments: + kwargs["help"] = argparse.SUPPRESS + break + parser.add_argument(*args, **kwargs) + + def print_help(self, prog_name, subcommand): + """ + Print the help message for this command, derived from + ``self.usage()``. + """ + parser = self.create_parser(prog_name, subcommand) + parser.print_help() + + def run_from_argv(self, argv): + """ + Set up any environment changes requested (e.g., Python path + and Django settings), then run this command. If the + command raises a ``CommandError``, intercept it and print it sensibly + to stderr. If the ``--traceback`` option is present or the raised + ``Exception`` is not ``CommandError``, raise it. + """ + self._called_from_command_line = True + parser = self.create_parser(argv[0], argv[1]) + + options = parser.parse_args(argv[2:]) + cmd_options = vars(options) + # Move positional args out of options to mimic legacy optparse + args = cmd_options.pop("args", ()) + handle_default_options(options) + try: + self.execute(*args, **cmd_options) + except CommandError as e: + if options.traceback: + raise + + # SystemCheckError takes care of its own formatting. + if isinstance(e, SystemCheckError): + self.stderr.write(str(e), lambda x: x) + else: + self.stderr.write("%s: %s" % (e.__class__.__name__, e)) + sys.exit(e.returncode) + finally: + try: + connections.close_all() + except ImproperlyConfigured: + # Ignore if connections aren't setup at this point (e.g. no + # configured settings). + pass + + def execute(self, *args, **options): + """ + Try to execute this command, performing system checks if needed (as + controlled by the ``requires_system_checks`` attribute, except if + force-skipped). + """ + if options["force_color"] and options["no_color"]: + raise CommandError( + "The --no-color and --force-color options can't be used together." + ) + if options["force_color"]: + self.style = color_style(force_color=True) + elif options["no_color"]: + self.style = no_style() + self.stderr.style_func = None + if options.get("stdout"): + self.stdout = OutputWrapper(options["stdout"]) + if options.get("stderr"): + self.stderr = OutputWrapper(options["stderr"]) + + if self.requires_system_checks and not options["skip_checks"]: + if self.requires_system_checks == ALL_CHECKS: + self.check() + else: + self.check(tags=self.requires_system_checks) + if self.requires_migrations_checks: + self.check_migrations() + output = self.handle(*args, **options) + if output: + if self.output_transaction: + connection = connections[options.get("database", DEFAULT_DB_ALIAS)] + output = "%s\n%s\n%s" % ( + self.style.SQL_KEYWORD(connection.ops.start_transaction_sql()), + output, + self.style.SQL_KEYWORD(connection.ops.end_transaction_sql()), + ) + self.stdout.write(output) + return output + + def check( + self, + app_configs=None, + tags=None, + display_num_errors=False, + include_deployment_checks=False, + fail_level=checks.ERROR, + databases=None, + ): + """ + Use the system check framework to validate entire Django project. + Raise CommandError for any serious message (error or critical errors). + If there are only light messages (like warnings), print them to stderr + and don't raise an exception. + """ + all_issues = checks.run_checks( + app_configs=app_configs, + tags=tags, + include_deployment_checks=include_deployment_checks, + databases=databases, + ) + + header, body, footer = "", "", "" + visible_issue_count = 0 # excludes silenced warnings + + if all_issues: + debugs = [ + e for e in all_issues if e.level < checks.INFO and not e.is_silenced() + ] + infos = [ + e + for e in all_issues + if checks.INFO <= e.level < checks.WARNING and not e.is_silenced() + ] + warnings = [ + e + for e in all_issues + if checks.WARNING <= e.level < checks.ERROR and not e.is_silenced() + ] + errors = [ + e + for e in all_issues + if checks.ERROR <= e.level < checks.CRITICAL and not e.is_silenced() + ] + criticals = [ + e + for e in all_issues + if checks.CRITICAL <= e.level and not e.is_silenced() + ] + sorted_issues = [ + (criticals, "CRITICALS"), + (errors, "ERRORS"), + (warnings, "WARNINGS"), + (infos, "INFOS"), + (debugs, "DEBUGS"), + ] + + for issues, group_name in sorted_issues: + if issues: + visible_issue_count += len(issues) + formatted = ( + self.style.ERROR(str(e)) + if e.is_serious() + else self.style.WARNING(str(e)) + for e in issues + ) + formatted = "\n".join(sorted(formatted)) + body += "\n%s:\n%s\n" % (group_name, formatted) + + if visible_issue_count: + header = "System check identified some issues:\n" + + if display_num_errors: + if visible_issue_count: + footer += "\n" + footer += "System check identified %s (%s silenced)." % ( + "no issues" + if visible_issue_count == 0 + else "1 issue" + if visible_issue_count == 1 + else "%s issues" % visible_issue_count, + len(all_issues) - visible_issue_count, + ) + + if any(e.is_serious(fail_level) and not e.is_silenced() for e in all_issues): + msg = self.style.ERROR("SystemCheckError: %s" % header) + body + footer + raise SystemCheckError(msg) + else: + msg = header + body + footer + + if msg: + if visible_issue_count: + self.stderr.write(msg, lambda x: x) + else: + self.stdout.write(msg) + + def check_migrations(self): + """ + Print a warning if the set of migrations on disk don't match the + migrations in the database. + """ + from django.db.migrations.executor import MigrationExecutor + + try: + executor = MigrationExecutor(connections[DEFAULT_DB_ALIAS]) + except ImproperlyConfigured: + # No databases are configured (or the dummy one) + return + + plan = executor.migration_plan(executor.loader.graph.leaf_nodes()) + if plan: + apps_waiting_migration = sorted( + {migration.app_label for migration, backwards in plan} + ) + self.stdout.write( + self.style.NOTICE( + "\nYou have %(unapplied_migration_count)s unapplied migration(s). " + "Your project may not work properly until you apply the " + "migrations for app(s): %(apps_waiting_migration)s." + % { + "unapplied_migration_count": len(plan), + "apps_waiting_migration": ", ".join(apps_waiting_migration), + } + ) + ) + self.stdout.write( + self.style.NOTICE("Run 'python manage.py migrate' to apply them.") + ) + + def handle(self, *args, **options): + """ + The actual logic of the command. Subclasses must implement + this method. + """ + raise NotImplementedError( + "subclasses of BaseCommand must provide a handle() method" + ) + + +class AppCommand(BaseCommand): + """ + A management command which takes one or more installed application labels + as arguments, and does something with each of them. + + Rather than implementing ``handle()``, subclasses must implement + ``handle_app_config()``, which will be called once for each application. + """ + + missing_args_message = "Enter at least one application label." + + def add_arguments(self, parser): + parser.add_argument( + "args", + metavar="app_label", + nargs="+", + help="One or more application label.", + ) + + def handle(self, *app_labels, **options): + from django.apps import apps + + try: + app_configs = [apps.get_app_config(app_label) for app_label in app_labels] + except (LookupError, ImportError) as e: + raise CommandError( + "%s. Are you sure your INSTALLED_APPS setting is correct?" % e + ) + output = [] + for app_config in app_configs: + app_output = self.handle_app_config(app_config, **options) + if app_output: + output.append(app_output) + return "\n".join(output) + + def handle_app_config(self, app_config, **options): + """ + Perform the command's actions for app_config, an AppConfig instance + corresponding to an application label given on the command line. + """ + raise NotImplementedError( + "Subclasses of AppCommand must provide a handle_app_config() method." + ) + + +class LabelCommand(BaseCommand): + """ + A management command which takes one or more arbitrary arguments + (labels) on the command line, and does something with each of + them. + + Rather than implementing ``handle()``, subclasses must implement + ``handle_label()``, which will be called once for each label. + + If the arguments should be names of installed applications, use + ``AppCommand`` instead. + """ + + label = "label" + missing_args_message = "Enter at least one %s." % label + + def add_arguments(self, parser): + parser.add_argument("args", metavar=self.label, nargs="+") + + def handle(self, *labels, **options): + output = [] + for label in labels: + label_output = self.handle_label(label, **options) + if label_output: + output.append(label_output) + return "\n".join(output) + + def handle_label(self, label, **options): + """ + Perform the command's actions for ``label``, which will be the + string as given on the command line. + """ + raise NotImplementedError( + "subclasses of LabelCommand must provide a handle_label() method" + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/color.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/color.py new file mode 100644 index 0000000..eef64b2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/color.py @@ -0,0 +1,120 @@ +""" +Sets up the terminal color scheme. +""" + +import functools +import os +import sys + +from django.utils import termcolors + +try: + import colorama + + # Avoid initializing colorama in non-Windows platforms. + colorama.just_fix_windows_console() +except ( + AttributeError, # colorama <= 0.4.6. + ImportError, # colorama is not installed. + # If just_fix_windows_console() accesses sys.stdout with + # WSGIRestrictedStdout. + OSError, +): + HAS_COLORAMA = False +else: + HAS_COLORAMA = True + + +def supports_color(): + """ + Return True if the running system's terminal supports color, + and False otherwise. + """ + + def vt_codes_enabled_in_windows_registry(): + """ + Check the Windows Registry to see if VT code handling has been enabled + by default, see https://superuser.com/a/1300251/447564. + """ + try: + # winreg is only available on Windows. + import winreg + except ImportError: + return False + else: + try: + reg_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Console") + reg_key_value, _ = winreg.QueryValueEx(reg_key, "VirtualTerminalLevel") + except FileNotFoundError: + return False + else: + return reg_key_value == 1 + + # isatty is not always implemented, #6223. + is_a_tty = hasattr(sys.stdout, "isatty") and sys.stdout.isatty() + + return is_a_tty and ( + sys.platform != "win32" + or (HAS_COLORAMA and getattr(colorama, "fixed_windows_console", False)) + or "ANSICON" in os.environ + or + # Windows Terminal supports VT codes. + "WT_SESSION" in os.environ + or + # Microsoft Visual Studio Code's built-in terminal supports colors. + os.environ.get("TERM_PROGRAM") == "vscode" + or vt_codes_enabled_in_windows_registry() + ) + + +class Style: + pass + + +def make_style(config_string=""): + """ + Create a Style object from the given config_string. + + If config_string is empty django.utils.termcolors.DEFAULT_PALETTE is used. + """ + + style = Style() + + color_settings = termcolors.parse_color_setting(config_string) + + # The nocolor palette has all available roles. + # Use that palette as the basis for populating + # the palette as defined in the environment. + for role in termcolors.PALETTES[termcolors.NOCOLOR_PALETTE]: + if color_settings: + format = color_settings.get(role, {}) + style_func = termcolors.make_style(**format) + else: + + def style_func(x): + return x + + setattr(style, role, style_func) + + # For backwards compatibility, + # set style for ERROR_OUTPUT == ERROR + style.ERROR_OUTPUT = style.ERROR + + return style + + +@functools.cache +def no_style(): + """ + Return a Style object with no color scheme. + """ + return make_style("nocolor") + + +def color_style(force_color=False): + """ + Return a Style object from the Django color scheme. + """ + if not force_color and not supports_color(): + return no_style() + return make_style(os.environ.get("DJANGO_COLORS", "")) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/check.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/check.py new file mode 100644 index 0000000..7624b85 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/check.py @@ -0,0 +1,83 @@ +from django.apps import apps +from django.core import checks +from django.core.checks.registry import registry +from django.core.management.base import BaseCommand, CommandError + + +class Command(BaseCommand): + help = "Checks the entire Django project for potential problems." + + requires_system_checks = [] + + def add_arguments(self, parser): + parser.add_argument("args", metavar="app_label", nargs="*") + parser.add_argument( + "--tag", + "-t", + action="append", + dest="tags", + help="Run only checks labeled with given tag.", + ) + parser.add_argument( + "--list-tags", + action="store_true", + help="List available tags.", + ) + parser.add_argument( + "--deploy", + action="store_true", + help="Check deployment settings.", + ) + parser.add_argument( + "--fail-level", + default="ERROR", + choices=["CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG"], + help=( + "Message level that will cause the command to exit with a " + "non-zero status. Default is ERROR." + ), + ) + parser.add_argument( + "--database", + action="append", + dest="databases", + help="Run database related checks against these aliases.", + ) + + def handle(self, *app_labels, **options): + include_deployment_checks = options["deploy"] + if options["list_tags"]: + self.stdout.write( + "\n".join(sorted(registry.tags_available(include_deployment_checks))) + ) + return + + if app_labels: + app_configs = [apps.get_app_config(app_label) for app_label in app_labels] + else: + app_configs = None + + tags = options["tags"] + if tags: + try: + invalid_tag = next( + tag + for tag in tags + if not checks.tag_exists(tag, include_deployment_checks) + ) + except StopIteration: + # no invalid tags + pass + else: + raise CommandError( + 'There is no system check with the "%s" tag.' % invalid_tag + ) + + self.check( + app_configs=app_configs, + tags=tags, + display_num_errors=True, + include_deployment_checks=include_deployment_checks, + fail_level=getattr(checks, options["fail_level"]), + databases=options["databases"], + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/compilemessages.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/compilemessages.py new file mode 100644 index 0000000..9ed3ef7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/compilemessages.py @@ -0,0 +1,195 @@ +import codecs +import concurrent.futures +import glob +import os +from pathlib import Path + +from django.core.management.base import BaseCommand, CommandError +from django.core.management.utils import find_command, is_ignored_path, popen_wrapper + + +def has_bom(fn): + with fn.open("rb") as f: + sample = f.read(4) + return sample.startswith( + (codecs.BOM_UTF8, codecs.BOM_UTF16_LE, codecs.BOM_UTF16_BE) + ) + + +def is_writable(path): + # Known side effect: updating file access/modified time to current time if + # it is writable. + try: + with open(path, "a"): + os.utime(path, None) + except OSError: + return False + return True + + +class Command(BaseCommand): + help = "Compiles .po files to .mo files for use with builtin gettext support." + + requires_system_checks = [] + + program = "msgfmt" + program_options = ["--check-format"] + + def add_arguments(self, parser): + parser.add_argument( + "--locale", + "-l", + action="append", + default=[], + help="Locale(s) to process (e.g. de_AT). Default is to process all. " + "Can be used multiple times.", + ) + parser.add_argument( + "--exclude", + "-x", + action="append", + default=[], + help="Locales to exclude. Default is none. Can be used multiple times.", + ) + parser.add_argument( + "--use-fuzzy", + "-f", + dest="fuzzy", + action="store_true", + help="Use fuzzy translations.", + ) + parser.add_argument( + "--ignore", + "-i", + action="append", + dest="ignore_patterns", + default=[], + metavar="PATTERN", + help="Ignore directories matching this glob-style pattern. " + "Use multiple times to ignore more.", + ) + + def handle(self, **options): + locale = options["locale"] + exclude = options["exclude"] + ignore_patterns = set(options["ignore_patterns"]) + self.verbosity = options["verbosity"] + if options["fuzzy"]: + self.program_options = self.program_options + ["-f"] + + if find_command(self.program) is None: + raise CommandError( + "Can't find %s. Make sure you have GNU gettext " + "tools 0.15 or newer installed." % self.program + ) + + basedirs = [os.path.join("conf", "locale"), "locale"] + if os.environ.get("DJANGO_SETTINGS_MODULE"): + from django.conf import settings + + basedirs.extend(settings.LOCALE_PATHS) + + # Walk entire tree, looking for locale directories + for dirpath, dirnames, filenames in os.walk(".", topdown=True): + for dirname in dirnames: + if is_ignored_path( + os.path.normpath(os.path.join(dirpath, dirname)), ignore_patterns + ): + dirnames.remove(dirname) + elif dirname == "locale": + basedirs.append(os.path.join(dirpath, dirname)) + + # Gather existing directories. + basedirs = set(map(os.path.abspath, filter(os.path.isdir, basedirs))) + + if not basedirs: + raise CommandError( + "This script should be run from the Django Git " + "checkout or your project or app tree, or with " + "the settings module specified." + ) + + # Build locale list + all_locales = [] + for basedir in basedirs: + locale_dirs = filter(os.path.isdir, glob.glob("%s/*" % basedir)) + all_locales.extend(map(os.path.basename, locale_dirs)) + + # Account for excluded locales + locales = locale or all_locales + locales = set(locales).difference(exclude) + + self.has_errors = False + for basedir in basedirs: + if locales: + dirs = [ + os.path.join(basedir, locale, "LC_MESSAGES") for locale in locales + ] + else: + dirs = [basedir] + locations = [] + for ldir in dirs: + for dirpath, dirnames, filenames in os.walk(ldir): + locations.extend( + (dirpath, f) for f in filenames if f.endswith(".po") + ) + if locations: + self.compile_messages(locations) + + if self.has_errors: + raise CommandError("compilemessages generated one or more errors.") + + def compile_messages(self, locations): + """ + Locations is a list of tuples: [(directory, file), ...] + """ + with concurrent.futures.ThreadPoolExecutor() as executor: + futures = [] + for i, (dirpath, f) in enumerate(locations): + po_path = Path(dirpath) / f + mo_path = po_path.with_suffix(".mo") + try: + if mo_path.stat().st_mtime >= po_path.stat().st_mtime: + if self.verbosity > 0: + self.stdout.write( + "File “%s” is already compiled and up to date." + % po_path + ) + continue + except FileNotFoundError: + pass + if self.verbosity > 0: + self.stdout.write("processing file %s in %s" % (f, dirpath)) + + if has_bom(po_path): + self.stderr.write( + "The %s file has a BOM (Byte Order Mark). Django only " + "supports .po files encoded in UTF-8 and without any BOM." + % po_path + ) + self.has_errors = True + continue + + # Check writability on first location + if i == 0 and not is_writable(mo_path): + self.stderr.write( + "The po files under %s are in a seemingly not writable " + "location. mo files will not be updated/created." % dirpath + ) + self.has_errors = True + return + + args = [self.program, *self.program_options, "-o", mo_path, po_path] + futures.append(executor.submit(popen_wrapper, args)) + + for future in concurrent.futures.as_completed(futures): + output, errors, status = future.result() + if status: + if self.verbosity > 0: + if errors: + self.stderr.write( + "Execution of %s failed: %s" % (self.program, errors) + ) + else: + self.stderr.write("Execution of %s failed" % self.program) + self.has_errors = True diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/createcachetable.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/createcachetable.py new file mode 100644 index 0000000..65ed168 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/createcachetable.py @@ -0,0 +1,130 @@ +from django.conf import settings +from django.core.cache import caches +from django.core.cache.backends.db import BaseDatabaseCache +from django.core.management.base import BaseCommand, CommandError +from django.db import ( + DEFAULT_DB_ALIAS, + DatabaseError, + connections, + models, + router, + transaction, +) + + +class Command(BaseCommand): + help = "Creates the tables needed to use the SQL cache backend." + + requires_system_checks = [] + + def add_arguments(self, parser): + parser.add_argument( + "args", + metavar="table_name", + nargs="*", + help=( + "Optional table names. Otherwise, settings.CACHES is used to find " + "cache tables." + ), + ) + parser.add_argument( + "--database", + default=DEFAULT_DB_ALIAS, + help="Nominates a database onto which the cache tables will be " + 'installed. Defaults to the "default" database.', + ) + parser.add_argument( + "--dry-run", + action="store_true", + help="Does not create the table, just prints the SQL that would be run.", + ) + + def handle(self, *tablenames, **options): + db = options["database"] + self.verbosity = options["verbosity"] + dry_run = options["dry_run"] + if tablenames: + # Legacy behavior, tablename specified as argument + for tablename in tablenames: + self.create_table(db, tablename, dry_run) + else: + for cache_alias in settings.CACHES: + cache = caches[cache_alias] + if isinstance(cache, BaseDatabaseCache): + self.create_table(db, cache._table, dry_run) + + def create_table(self, database, tablename, dry_run): + cache = BaseDatabaseCache(tablename, {}) + if not router.allow_migrate_model(database, cache.cache_model_class): + return + connection = connections[database] + + if tablename in connection.introspection.table_names(): + if self.verbosity > 0: + self.stdout.write("Cache table '%s' already exists." % tablename) + return + + fields = ( + # "key" is a reserved word in MySQL, so use "cache_key" instead. + models.CharField( + name="cache_key", max_length=255, unique=True, primary_key=True + ), + models.TextField(name="value"), + models.DateTimeField(name="expires", db_index=True), + ) + table_output = [] + index_output = [] + qn = connection.ops.quote_name + for f in fields: + field_output = [ + qn(f.name), + f.db_type(connection=connection), + "%sNULL" % ("NOT " if not f.null else ""), + ] + if f.primary_key: + field_output.append("PRIMARY KEY") + elif f.unique: + field_output.append("UNIQUE") + if f.db_index: + unique = "UNIQUE " if f.unique else "" + index_output.append( + "CREATE %sINDEX %s ON %s (%s);" + % ( + unique, + qn("%s_%s" % (tablename, f.name)), + qn(tablename), + qn(f.name), + ) + ) + table_output.append(" ".join(field_output)) + full_statement = ["CREATE TABLE %s (" % qn(tablename)] + for i, line in enumerate(table_output): + full_statement.append( + " %s%s" % (line, "," if i < len(table_output) - 1 else "") + ) + full_statement.append(");") + + full_statement = "\n".join(full_statement) + + if dry_run: + self.stdout.write(full_statement) + for statement in index_output: + self.stdout.write(statement) + return + + with transaction.atomic( + using=database, savepoint=connection.features.can_rollback_ddl + ): + with connection.cursor() as curs: + try: + curs.execute(full_statement) + except DatabaseError as e: + raise CommandError( + "Cache table '%s' could not be created.\nThe error was: %s." + % (tablename, e) + ) + for statement in index_output: + curs.execute(statement) + + if self.verbosity > 1: + self.stdout.write("Cache table '%s' created." % tablename) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/dbshell.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/dbshell.py new file mode 100644 index 0000000..bdb1305 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/dbshell.py @@ -0,0 +1,48 @@ +import subprocess + +from django.core.management.base import BaseCommand, CommandError +from django.db import DEFAULT_DB_ALIAS, connections + + +class Command(BaseCommand): + help = ( + "Runs the command-line client for specified database, or the " + "default database if none is provided." + ) + + requires_system_checks = [] + + def add_arguments(self, parser): + parser.add_argument( + "--database", + default=DEFAULT_DB_ALIAS, + help=( + "Nominates a database onto which to open a shell. Defaults to the " + '"default" database.' + ), + ) + parameters = parser.add_argument_group("parameters", prefix_chars="--") + parameters.add_argument("parameters", nargs="*") + + def handle(self, **options): + connection = connections[options["database"]] + try: + connection.client.runshell(options["parameters"]) + except FileNotFoundError: + # Note that we're assuming the FileNotFoundError relates to the + # command missing. It could be raised for some other reason, in + # which case this error message would be inaccurate. Still, this + # message catches the common case. + raise CommandError( + "You appear not to have the %r program installed or on your path." + % connection.client.executable_name + ) + except subprocess.CalledProcessError as e: + raise CommandError( + '"%s" returned non-zero exit status %s.' + % ( + " ".join(map(str, e.cmd)), + e.returncode, + ), + returncode=e.returncode, + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/diffsettings.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/diffsettings.py new file mode 100644 index 0000000..047e476 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/diffsettings.py @@ -0,0 +1,91 @@ +from django.core.management.base import BaseCommand + + +def module_to_dict(module, omittable=lambda k: k.startswith("_") or not k.isupper()): + """Convert a module namespace to a Python dictionary.""" + return {k: repr(getattr(module, k)) for k in dir(module) if not omittable(k)} + + +class Command(BaseCommand): + help = """Displays differences between the current settings.py and Django's + default settings.""" + + requires_system_checks = [] + + def add_arguments(self, parser): + parser.add_argument( + "--all", + action="store_true", + help=( + 'Display all settings, regardless of their value. In "hash" ' + 'mode, default values are prefixed by "###".' + ), + ) + parser.add_argument( + "--default", + metavar="MODULE", + help=( + "The settings module to compare the current settings against. Leave " + "empty to compare against Django's default settings." + ), + ) + parser.add_argument( + "--output", + default="hash", + choices=("hash", "unified"), + help=( + "Selects the output format. 'hash' mode displays each changed " + "setting, with the settings that don't appear in the defaults " + "followed by ###. 'unified' mode prefixes the default setting " + "with a minus sign, followed by the changed setting prefixed " + "with a plus sign." + ), + ) + + def handle(self, **options): + from django.conf import Settings, global_settings, settings + + # Because settings are imported lazily, we need to explicitly load them. + if not settings.configured: + settings._setup() + + user_settings = module_to_dict(settings._wrapped) + default = options["default"] + default_settings = module_to_dict( + Settings(default) if default else global_settings + ) + output_func = { + "hash": self.output_hash, + "unified": self.output_unified, + }[options["output"]] + return "\n".join(output_func(user_settings, default_settings, **options)) + + def output_hash(self, user_settings, default_settings, **options): + # Inspired by Postfix's "postconf -n". + output = [] + for key in sorted(user_settings): + if key not in default_settings: + output.append("%s = %s ###" % (key, user_settings[key])) + elif user_settings[key] != default_settings[key]: + output.append("%s = %s" % (key, user_settings[key])) + elif options["all"]: + output.append("### %s = %s" % (key, user_settings[key])) + return output + + def output_unified(self, user_settings, default_settings, **options): + output = [] + for key in sorted(user_settings): + if key not in default_settings: + output.append( + self.style.SUCCESS("+ %s = %s" % (key, user_settings[key])) + ) + elif user_settings[key] != default_settings[key]: + output.append( + self.style.ERROR("- %s = %s" % (key, default_settings[key])) + ) + output.append( + self.style.SUCCESS("+ %s = %s" % (key, user_settings[key])) + ) + elif options["all"]: + output.append(" %s = %s" % (key, user_settings[key])) + return output diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/dumpdata.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/dumpdata.py new file mode 100644 index 0000000..cc18351 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/dumpdata.py @@ -0,0 +1,281 @@ +import gzip +import os +import warnings + +from django.apps import apps +from django.core import serializers +from django.core.management.base import BaseCommand, CommandError +from django.core.management.utils import parse_apps_and_model_labels +from django.db import DEFAULT_DB_ALIAS, router + +try: + import bz2 + + has_bz2 = True +except ImportError: + has_bz2 = False + +try: + import lzma + + has_lzma = True +except ImportError: + has_lzma = False + + +class ProxyModelWarning(Warning): + pass + + +class Command(BaseCommand): + help = ( + "Output the contents of the database as a fixture of the given format " + "(using each model's default manager unless --all is specified)." + ) + + def add_arguments(self, parser): + parser.add_argument( + "args", + metavar="app_label[.ModelName]", + nargs="*", + help=( + "Restricts dumped data to the specified app_label or " + "app_label.ModelName." + ), + ) + parser.add_argument( + "--format", + default="json", + help="Specifies the output serialization format for fixtures.", + ) + parser.add_argument( + "--indent", + type=int, + help="Specifies the indent level to use when pretty-printing output.", + ) + parser.add_argument( + "--database", + default=DEFAULT_DB_ALIAS, + help="Nominates a specific database to dump fixtures from. " + 'Defaults to the "default" database.', + ) + parser.add_argument( + "-e", + "--exclude", + action="append", + default=[], + help="An app_label or app_label.ModelName to exclude " + "(use multiple --exclude to exclude multiple apps/models).", + ) + parser.add_argument( + "--natural-foreign", + action="store_true", + dest="use_natural_foreign_keys", + help="Use natural foreign keys if they are available.", + ) + parser.add_argument( + "--natural-primary", + action="store_true", + dest="use_natural_primary_keys", + help="Use natural primary keys if they are available.", + ) + parser.add_argument( + "-a", + "--all", + action="store_true", + dest="use_base_manager", + help=( + "Use Django's base manager to dump all models stored in the database, " + "including those that would otherwise be filtered or modified by a " + "custom manager." + ), + ) + parser.add_argument( + "--pks", + dest="primary_keys", + help="Only dump objects with given primary keys. Accepts a comma-separated " + "list of keys. This option only works when you specify one model.", + ) + parser.add_argument( + "-o", "--output", help="Specifies file to which the output is written." + ) + + def handle(self, *app_labels, **options): + format = options["format"] + indent = options["indent"] + using = options["database"] + excludes = options["exclude"] + output = options["output"] + show_traceback = options["traceback"] + use_natural_foreign_keys = options["use_natural_foreign_keys"] + use_natural_primary_keys = options["use_natural_primary_keys"] + use_base_manager = options["use_base_manager"] + pks = options["primary_keys"] + + if pks: + primary_keys = [pk.strip() for pk in pks.split(",")] + else: + primary_keys = [] + + excluded_models, excluded_apps = parse_apps_and_model_labels(excludes) + + if not app_labels: + if primary_keys: + raise CommandError("You can only use --pks option with one model") + app_list = dict.fromkeys( + app_config + for app_config in apps.get_app_configs() + if app_config.models_module is not None + and app_config not in excluded_apps + ) + else: + if len(app_labels) > 1 and primary_keys: + raise CommandError("You can only use --pks option with one model") + app_list = {} + for label in app_labels: + try: + app_label, model_label = label.split(".") + try: + app_config = apps.get_app_config(app_label) + except LookupError as e: + raise CommandError(str(e)) + if app_config.models_module is None or app_config in excluded_apps: + continue + try: + model = app_config.get_model(model_label) + except LookupError: + raise CommandError( + "Unknown model: %s.%s" % (app_label, model_label) + ) + + app_list_value = app_list.setdefault(app_config, []) + + # We may have previously seen an "all-models" request for + # this app (no model qualifier was given). In this case + # there is no need adding specific models to the list. + if app_list_value is not None and model not in app_list_value: + app_list_value.append(model) + except ValueError: + if primary_keys: + raise CommandError( + "You can only use --pks option with one model" + ) + # This is just an app - no model qualifier + app_label = label + try: + app_config = apps.get_app_config(app_label) + except LookupError as e: + raise CommandError(str(e)) + if app_config.models_module is None or app_config in excluded_apps: + continue + app_list[app_config] = None + + # Check that the serialization format exists; this is a shortcut to + # avoid collating all the objects and _then_ failing. + if format not in serializers.get_public_serializer_formats(): + try: + serializers.get_serializer(format) + except serializers.SerializerDoesNotExist: + pass + + raise CommandError("Unknown serialization format: %s" % format) + + def get_objects(count_only=False): + """ + Collate the objects to be serialized. If count_only is True, just + count the number of objects to be serialized. + """ + if use_natural_foreign_keys: + models = serializers.sort_dependencies( + app_list.items(), allow_cycles=True + ) + else: + # There is no need to sort dependencies when natural foreign + # keys are not used. + models = [] + for app_config, model_list in app_list.items(): + if model_list is None: + models.extend(app_config.get_models()) + else: + models.extend(model_list) + for model in models: + if model in excluded_models: + continue + if model._meta.proxy and model._meta.proxy_for_model not in models: + warnings.warn( + "%s is a proxy model and won't be serialized." + % model._meta.label, + category=ProxyModelWarning, + ) + if not model._meta.proxy and router.allow_migrate_model(using, model): + if use_base_manager: + objects = model._base_manager + else: + objects = model._default_manager + + queryset = objects.using(using).order_by(model._meta.pk.name) + if primary_keys: + queryset = queryset.filter(pk__in=primary_keys) + if count_only: + yield queryset.order_by().count() + else: + yield from queryset.iterator() + + try: + self.stdout.ending = None + progress_output = None + object_count = 0 + # If dumpdata is outputting to stdout, there is no way to display progress + if output and self.stdout.isatty() and options["verbosity"] > 0: + progress_output = self.stdout + object_count = sum(get_objects(count_only=True)) + if output: + file_root, file_ext = os.path.splitext(output) + compression_formats = { + ".bz2": (open, {}, file_root), + ".gz": (gzip.open, {}, output), + ".lzma": (open, {}, file_root), + ".xz": (open, {}, file_root), + ".zip": (open, {}, file_root), + } + if has_bz2: + compression_formats[".bz2"] = (bz2.open, {}, output) + if has_lzma: + compression_formats[".lzma"] = ( + lzma.open, + {"format": lzma.FORMAT_ALONE}, + output, + ) + compression_formats[".xz"] = (lzma.open, {}, output) + try: + open_method, kwargs, file_path = compression_formats[file_ext] + except KeyError: + open_method, kwargs, file_path = (open, {}, output) + if file_path != output: + file_name = os.path.basename(file_path) + warnings.warn( + f"Unsupported file extension ({file_ext}). " + f"Fixtures saved in '{file_name}'.", + RuntimeWarning, + ) + stream = open_method(file_path, "wt", **kwargs) + else: + stream = None + try: + serializers.serialize( + format, + get_objects(), + indent=indent, + use_natural_foreign_keys=use_natural_foreign_keys, + use_natural_primary_keys=use_natural_primary_keys, + stream=stream or self.stdout, + progress_output=progress_output, + object_count=object_count, + ) + finally: + if stream: + stream.close() + except Exception as e: + if show_traceback: + raise + raise CommandError("Unable to serialize database: %s" % e) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/flush.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/flush.py new file mode 100644 index 0000000..e9d440d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/flush.py @@ -0,0 +1,92 @@ +from importlib import import_module + +from django.apps import apps +from django.core.management.base import BaseCommand, CommandError +from django.core.management.color import no_style +from django.core.management.sql import emit_post_migrate_signal, sql_flush +from django.db import DEFAULT_DB_ALIAS, connections + + +class Command(BaseCommand): + help = ( + "Removes ALL DATA from the database, including data added during " + 'migrations. Does not achieve a "fresh install" state.' + ) + stealth_options = ("reset_sequences", "allow_cascade", "inhibit_post_migrate") + + def add_arguments(self, parser): + parser.add_argument( + "--noinput", + "--no-input", + action="store_false", + dest="interactive", + help="Tells Django to NOT prompt the user for input of any kind.", + ) + parser.add_argument( + "--database", + default=DEFAULT_DB_ALIAS, + help='Nominates a database to flush. Defaults to the "default" database.', + ) + + def handle(self, **options): + database = options["database"] + connection = connections[database] + verbosity = options["verbosity"] + interactive = options["interactive"] + # The following are stealth options used by Django's internals. + reset_sequences = options.get("reset_sequences", True) + allow_cascade = options.get("allow_cascade", False) + inhibit_post_migrate = options.get("inhibit_post_migrate", False) + + self.style = no_style() + + # Import the 'management' module within each installed app, to register + # dispatcher events. + for app_config in apps.get_app_configs(): + try: + import_module(".management", app_config.name) + except ImportError: + pass + + sql_list = sql_flush( + self.style, + connection, + reset_sequences=reset_sequences, + allow_cascade=allow_cascade, + ) + + if interactive: + confirm = input( + """You have requested a flush of the database. +This will IRREVERSIBLY DESTROY all data currently in the "%s" database, +and return each table to an empty state. +Are you sure you want to do this? + + Type 'yes' to continue, or 'no' to cancel: """ + % connection.settings_dict["NAME"] + ) + else: + confirm = "yes" + + if confirm == "yes": + try: + connection.ops.execute_sql_flush(sql_list) + except Exception as exc: + raise CommandError( + "Database %s couldn't be flushed. Possible reasons:\n" + " * The database isn't running or isn't configured correctly.\n" + " * At least one of the expected database tables doesn't exist.\n" + " * The SQL was invalid.\n" + "Hint: Look at the output of 'django-admin sqlflush'. " + "That's the SQL this command wasn't able to run." + % (connection.settings_dict["NAME"],) + ) from exc + + # Empty sql_list may signify an empty database and post_migrate + # would then crash. + if sql_list and not inhibit_post_migrate: + # Emit the post migrate signal. This allows individual applications to + # respond as if the database had been migrated from scratch. + emit_post_migrate_signal(verbosity, interactive, database) + else: + self.stdout.write("Flush cancelled.") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/inspectdb.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/inspectdb.py new file mode 100644 index 0000000..5c2ed53 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/inspectdb.py @@ -0,0 +1,414 @@ +import keyword +import re + +from django.core.management.base import BaseCommand, CommandError +from django.db import DEFAULT_DB_ALIAS, connections +from django.db.models.constants import LOOKUP_SEP + + +class Command(BaseCommand): + help = ( + "Introspects the database tables in the given database and outputs a Django " + "model module." + ) + requires_system_checks = [] + stealth_options = ("table_name_filter",) + db_module = "django.db" + + def add_arguments(self, parser): + parser.add_argument( + "table", + nargs="*", + type=str, + help="Selects what tables or views should be introspected.", + ) + parser.add_argument( + "--database", + default=DEFAULT_DB_ALIAS, + help=( + 'Nominates a database to introspect. Defaults to using the "default" ' + "database." + ), + ) + parser.add_argument( + "--include-partitions", + action="store_true", + help="Also output models for partition tables.", + ) + parser.add_argument( + "--include-views", + action="store_true", + help="Also output models for database views.", + ) + + def handle(self, **options): + try: + for line in self.handle_inspection(options): + self.stdout.write(line) + except NotImplementedError: + raise CommandError( + "Database inspection isn't supported for the currently selected " + "database backend." + ) + + def handle_inspection(self, options): + connection = connections[options["database"]] + # 'table_name_filter' is a stealth option + table_name_filter = options.get("table_name_filter") + + with connection.cursor() as cursor: + yield "# This is an auto-generated Django model module." + yield "# You'll have to do the following manually to clean this up:" + yield "# * Rearrange models' order" + yield "# * Make sure each model has one field with primary_key=True" + yield ( + "# * Make sure each ForeignKey and OneToOneField has `on_delete` set " + "to the desired behavior" + ) + yield ( + "# * Remove `managed = False` lines if you wish to allow " + "Django to create, modify, and delete the table" + ) + yield ( + "# Feel free to rename the models, but don't rename db_table values or " + "field names." + ) + yield "from %s import models" % self.db_module + known_models = [] + # Determine types of tables and/or views to be introspected. + types = {"t"} + if options["include_partitions"]: + types.add("p") + if options["include_views"]: + types.add("v") + table_info = connection.introspection.get_table_list(cursor) + table_info = {info.name: info for info in table_info if info.type in types} + + for table_name in options["table"] or sorted(name for name in table_info): + if table_name_filter is not None and callable(table_name_filter): + if not table_name_filter(table_name): + continue + try: + try: + relations = connection.introspection.get_relations( + cursor, table_name + ) + except NotImplementedError: + relations = {} + try: + constraints = connection.introspection.get_constraints( + cursor, table_name + ) + except NotImplementedError: + constraints = {} + primary_key_columns = ( + connection.introspection.get_primary_key_columns( + cursor, table_name + ) + ) + primary_key_column = ( + primary_key_columns[0] if primary_key_columns else None + ) + unique_columns = [ + c["columns"][0] + for c in constraints.values() + if c["unique"] and len(c["columns"]) == 1 + ] + table_description = connection.introspection.get_table_description( + cursor, table_name + ) + except Exception as e: + yield "# Unable to inspect table '%s'" % table_name + yield "# The error was: %s" % e + continue + + model_name = self.normalize_table_name(table_name) + yield "" + yield "" + yield "class %s(models.Model):" % model_name + known_models.append(model_name) + used_column_names = [] # Holds column names used in the table so far + column_to_field_name = {} # Maps column names to names of model fields + used_relations = set() # Holds foreign relations used in the table. + for row in table_description: + comment_notes = ( + [] + ) # Holds Field notes, to be displayed in a Python comment. + extra_params = {} # Holds Field parameters such as 'db_column'. + column_name = row.name + is_relation = column_name in relations + + att_name, params, notes = self.normalize_col_name( + column_name, used_column_names, is_relation + ) + extra_params.update(params) + comment_notes.extend(notes) + + used_column_names.append(att_name) + column_to_field_name[column_name] = att_name + + # Add primary_key and unique, if necessary. + if column_name == primary_key_column: + extra_params["primary_key"] = True + if len(primary_key_columns) > 1: + comment_notes.append( + "The composite primary key (%s) found, that is not " + "supported. The first column is selected." + % ", ".join(primary_key_columns) + ) + elif column_name in unique_columns: + extra_params["unique"] = True + + if is_relation: + ref_db_column, ref_db_table = relations[column_name] + if extra_params.pop("unique", False) or extra_params.get( + "primary_key" + ): + rel_type = "OneToOneField" + else: + rel_type = "ForeignKey" + ref_pk_column = ( + connection.introspection.get_primary_key_column( + cursor, ref_db_table + ) + ) + if ref_pk_column and ref_pk_column != ref_db_column: + extra_params["to_field"] = ref_db_column + rel_to = ( + "self" + if ref_db_table == table_name + else self.normalize_table_name(ref_db_table) + ) + if rel_to in known_models: + field_type = "%s(%s" % (rel_type, rel_to) + else: + field_type = "%s('%s'" % (rel_type, rel_to) + if rel_to in used_relations: + extra_params["related_name"] = "%s_%s_set" % ( + model_name.lower(), + att_name, + ) + used_relations.add(rel_to) + else: + # Calling `get_field_type` to get the field type string and any + # additional parameters and notes. + field_type, field_params, field_notes = self.get_field_type( + connection, table_name, row + ) + extra_params.update(field_params) + comment_notes.extend(field_notes) + + field_type += "(" + + # Don't output 'id = meta.AutoField(primary_key=True)', because + # that's assumed if it doesn't exist. + if att_name == "id" and extra_params == {"primary_key": True}: + if field_type == "AutoField(": + continue + elif ( + field_type + == connection.features.introspected_field_types["AutoField"] + + "(" + ): + comment_notes.append("AutoField?") + + # Add 'null' and 'blank', if the 'null_ok' flag was present in the + # table description. + if row.null_ok: # If it's NULL... + extra_params["blank"] = True + extra_params["null"] = True + + field_desc = "%s = %s%s" % ( + att_name, + # Custom fields will have a dotted path + "" if "." in field_type else "models.", + field_type, + ) + if field_type.startswith(("ForeignKey(", "OneToOneField(")): + field_desc += ", models.DO_NOTHING" + + # Add comment. + if connection.features.supports_comments and row.comment: + extra_params["db_comment"] = row.comment + + if extra_params: + if not field_desc.endswith("("): + field_desc += ", " + field_desc += ", ".join( + "%s=%r" % (k, v) for k, v in extra_params.items() + ) + field_desc += ")" + if comment_notes: + field_desc += " # " + " ".join(comment_notes) + yield " %s" % field_desc + comment = None + if info := table_info.get(table_name): + is_view = info.type == "v" + is_partition = info.type == "p" + if connection.features.supports_comments: + comment = info.comment + else: + is_view = False + is_partition = False + yield from self.get_meta( + table_name, + constraints, + column_to_field_name, + is_view, + is_partition, + comment, + ) + + def normalize_col_name(self, col_name, used_column_names, is_relation): + """ + Modify the column name to make it Python-compatible as a field name + """ + field_params = {} + field_notes = [] + + new_name = col_name.lower() + if new_name != col_name: + field_notes.append("Field name made lowercase.") + + if is_relation: + if new_name.endswith("_id"): + new_name = new_name.removesuffix("_id") + else: + field_params["db_column"] = col_name + + new_name, num_repl = re.subn(r"\W", "_", new_name) + if num_repl > 0: + field_notes.append("Field renamed to remove unsuitable characters.") + + if new_name.find(LOOKUP_SEP) >= 0: + while new_name.find(LOOKUP_SEP) >= 0: + new_name = new_name.replace(LOOKUP_SEP, "_") + if col_name.lower().find(LOOKUP_SEP) >= 0: + # Only add the comment if the double underscore was in the original name + field_notes.append( + "Field renamed because it contained more than one '_' in a row." + ) + + if new_name.startswith("_"): + new_name = "field%s" % new_name + field_notes.append("Field renamed because it started with '_'.") + + if new_name.endswith("_"): + new_name = "%sfield" % new_name + field_notes.append("Field renamed because it ended with '_'.") + + if keyword.iskeyword(new_name): + new_name += "_field" + field_notes.append("Field renamed because it was a Python reserved word.") + + if new_name[0].isdigit(): + new_name = "number_%s" % new_name + field_notes.append( + "Field renamed because it wasn't a valid Python identifier." + ) + + if new_name in used_column_names: + num = 0 + while "%s_%d" % (new_name, num) in used_column_names: + num += 1 + new_name = "%s_%d" % (new_name, num) + field_notes.append("Field renamed because of name conflict.") + + if col_name != new_name and field_notes: + field_params["db_column"] = col_name + + return new_name, field_params, field_notes + + def normalize_table_name(self, table_name): + """Translate the table name to a Python-compatible model name.""" + return re.sub(r"[^a-zA-Z0-9]", "", table_name.title()) + + def get_field_type(self, connection, table_name, row): + """ + Given the database connection, the table name, and the cursor row + description, this routine will return the given field type name, as + well as any additional keyword parameters and notes for the field. + """ + field_params = {} + field_notes = [] + + try: + field_type = connection.introspection.get_field_type(row.type_code, row) + except KeyError: + field_type = "TextField" + field_notes.append("This field type is a guess.") + + # Add max_length for all CharFields. + if field_type == "CharField" and row.display_size: + if (size := int(row.display_size)) and size > 0: + field_params["max_length"] = size + + if field_type in {"CharField", "TextField"} and row.collation: + field_params["db_collation"] = row.collation + + if field_type == "DecimalField": + if row.precision is None or row.scale is None: + field_notes.append( + "max_digits and decimal_places have been guessed, as this " + "database handles decimal fields as float" + ) + field_params["max_digits"] = ( + row.precision if row.precision is not None else 10 + ) + field_params["decimal_places"] = ( + row.scale if row.scale is not None else 5 + ) + else: + field_params["max_digits"] = row.precision + field_params["decimal_places"] = row.scale + + return field_type, field_params, field_notes + + def get_meta( + self, + table_name, + constraints, + column_to_field_name, + is_view, + is_partition, + comment, + ): + """ + Return a sequence comprising the lines of code necessary + to construct the inner Meta class for the model corresponding + to the given database table name. + """ + unique_together = [] + has_unsupported_constraint = False + for params in constraints.values(): + if params["unique"]: + columns = params["columns"] + if None in columns: + has_unsupported_constraint = True + columns = [ + x for x in columns if x is not None and x in column_to_field_name + ] + if len(columns) > 1: + unique_together.append( + str(tuple(column_to_field_name[c] for c in columns)) + ) + if is_view: + managed_comment = " # Created from a view. Don't remove." + elif is_partition: + managed_comment = " # Created from a partition. Don't remove." + else: + managed_comment = "" + meta = [""] + if has_unsupported_constraint: + meta.append(" # A unique constraint could not be introspected.") + meta += [ + " class Meta:", + " managed = False%s" % managed_comment, + " db_table = %r" % table_name, + ] + if unique_together: + tup = "(" + ", ".join(unique_together) + ",)" + meta += [" unique_together = %s" % tup] + if comment: + meta += [f" db_table_comment = {comment!r}"] + return meta diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/loaddata.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/loaddata.py new file mode 100644 index 0000000..bb46e8a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/loaddata.py @@ -0,0 +1,432 @@ +import functools +import glob +import gzip +import os +import sys +import warnings +import zipfile +from itertools import product + +from django.apps import apps +from django.conf import settings +from django.core import serializers +from django.core.exceptions import ImproperlyConfigured +from django.core.management.base import BaseCommand, CommandError +from django.core.management.color import no_style +from django.core.management.utils import parse_apps_and_model_labels +from django.db import ( + DEFAULT_DB_ALIAS, + DatabaseError, + IntegrityError, + connections, + router, + transaction, +) +from django.utils.functional import cached_property + +try: + import bz2 + + has_bz2 = True +except ImportError: + has_bz2 = False + +try: + import lzma + + has_lzma = True +except ImportError: + has_lzma = False + +READ_STDIN = "-" + + +class Command(BaseCommand): + help = "Installs the named fixture(s) in the database." + missing_args_message = ( + "No database fixture specified. Please provide the path of at least " + "one fixture in the command line." + ) + + def add_arguments(self, parser): + parser.add_argument( + "args", metavar="fixture", nargs="+", help="Fixture labels." + ) + parser.add_argument( + "--database", + default=DEFAULT_DB_ALIAS, + help=( + "Nominates a specific database to load fixtures into. Defaults to the " + '"default" database.' + ), + ) + parser.add_argument( + "--app", + dest="app_label", + help="Only look for fixtures in the specified app.", + ) + parser.add_argument( + "--ignorenonexistent", + "-i", + action="store_true", + dest="ignore", + help="Ignores entries in the serialized data for fields that do not " + "currently exist on the model.", + ) + parser.add_argument( + "-e", + "--exclude", + action="append", + default=[], + help=( + "An app_label or app_label.ModelName to exclude. Can be used multiple " + "times." + ), + ) + parser.add_argument( + "--format", + help="Format of serialized data when reading from stdin.", + ) + + def handle(self, *fixture_labels, **options): + self.ignore = options["ignore"] + self.using = options["database"] + self.app_label = options["app_label"] + self.verbosity = options["verbosity"] + self.excluded_models, self.excluded_apps = parse_apps_and_model_labels( + options["exclude"] + ) + self.format = options["format"] + + with transaction.atomic(using=self.using): + self.loaddata(fixture_labels) + + # Close the DB connection -- unless we're still in a transaction. This + # is required as a workaround for an edge case in MySQL: if the same + # connection is used to create tables, load data, and query, the query + # can return incorrect results. See Django #7572, MySQL #37735. + if transaction.get_autocommit(self.using): + connections[self.using].close() + + @cached_property + def compression_formats(self): + """A dict mapping format names to (open function, mode arg) tuples.""" + # Forcing binary mode may be revisited after dropping Python 2 support + # (see #22399). + compression_formats = { + None: (open, "rb"), + "gz": (gzip.GzipFile, "rb"), + "zip": (SingleZipReader, "r"), + "stdin": (lambda *args: sys.stdin, None), + } + if has_bz2: + compression_formats["bz2"] = (bz2.BZ2File, "r") + if has_lzma: + compression_formats["lzma"] = (lzma.LZMAFile, "r") + compression_formats["xz"] = (lzma.LZMAFile, "r") + return compression_formats + + def reset_sequences(self, connection, models): + """Reset database sequences for the given connection and models.""" + sequence_sql = connection.ops.sequence_reset_sql(no_style(), models) + if sequence_sql: + if self.verbosity >= 2: + self.stdout.write("Resetting sequences") + with connection.cursor() as cursor: + for line in sequence_sql: + cursor.execute(line) + + def loaddata(self, fixture_labels): + connection = connections[self.using] + + # Keep a count of the installed objects and fixtures + self.fixture_count = 0 + self.loaded_object_count = 0 + self.fixture_object_count = 0 + self.models = set() + + self.serialization_formats = serializers.get_public_serializer_formats() + + # Django's test suite repeatedly tries to load initial_data fixtures + # from apps that don't have any fixtures. Because disabling constraint + # checks can be expensive on some database (especially MSSQL), bail + # out early if no fixtures are found. + for fixture_label in fixture_labels: + if self.find_fixtures(fixture_label): + break + else: + return + + self.objs_with_deferred_fields = [] + with connection.constraint_checks_disabled(): + for fixture_label in fixture_labels: + self.load_label(fixture_label) + for obj in self.objs_with_deferred_fields: + obj.save_deferred_fields(using=self.using) + + # Since we disabled constraint checks, we must manually check for + # any invalid keys that might have been added + table_names = [model._meta.db_table for model in self.models] + try: + connection.check_constraints(table_names=table_names) + except Exception as e: + e.args = ("Problem installing fixtures: %s" % e,) + raise + + # If we found even one object in a fixture, we need to reset the + # database sequences. + if self.loaded_object_count > 0: + self.reset_sequences(connection, self.models) + + if self.verbosity >= 1: + if self.fixture_object_count == self.loaded_object_count: + self.stdout.write( + "Installed %d object(s) from %d fixture(s)" + % (self.loaded_object_count, self.fixture_count) + ) + else: + self.stdout.write( + "Installed %d object(s) (of %d) from %d fixture(s)" + % ( + self.loaded_object_count, + self.fixture_object_count, + self.fixture_count, + ) + ) + + def save_obj(self, obj): + """Save an object if permitted.""" + if ( + obj.object._meta.app_config in self.excluded_apps + or type(obj.object) in self.excluded_models + ): + return False + saved = False + if router.allow_migrate_model(self.using, obj.object.__class__): + saved = True + self.models.add(obj.object.__class__) + try: + obj.save(using=self.using) + # psycopg raises ValueError if data contains NUL chars. + except (DatabaseError, IntegrityError, ValueError) as e: + e.args = ( + "Could not load %(object_label)s(pk=%(pk)s): %(error_msg)s" + % { + "object_label": obj.object._meta.label, + "pk": obj.object.pk, + "error_msg": e, + }, + ) + raise + if obj.deferred_fields: + self.objs_with_deferred_fields.append(obj) + return saved + + def load_label(self, fixture_label): + """Load fixtures files for a given label.""" + show_progress = self.verbosity >= 3 + for fixture_file, fixture_dir, fixture_name in self.find_fixtures( + fixture_label + ): + _, ser_fmt, cmp_fmt = self.parse_name(os.path.basename(fixture_file)) + open_method, mode = self.compression_formats[cmp_fmt] + fixture = open_method(fixture_file, mode) + self.fixture_count += 1 + objects_in_fixture = 0 + loaded_objects_in_fixture = 0 + if self.verbosity >= 2: + self.stdout.write( + "Installing %s fixture '%s' from %s." + % (ser_fmt, fixture_name, humanize(fixture_dir)) + ) + try: + objects = serializers.deserialize( + ser_fmt, + fixture, + using=self.using, + ignorenonexistent=self.ignore, + handle_forward_references=True, + ) + + for obj in objects: + objects_in_fixture += 1 + if self.save_obj(obj): + loaded_objects_in_fixture += 1 + if show_progress: + self.stdout.write( + "\rProcessed %i object(s)." % loaded_objects_in_fixture, + ending="", + ) + except Exception as e: + if not isinstance(e, CommandError): + e.args = ( + "Problem installing fixture '%s': %s" % (fixture_file, e), + ) + raise + finally: + fixture.close() + + if objects_in_fixture and show_progress: + self.stdout.write() # Add a newline after progress indicator. + self.loaded_object_count += loaded_objects_in_fixture + self.fixture_object_count += objects_in_fixture + # Warn if the fixture we loaded contains 0 objects. + if objects_in_fixture == 0: + warnings.warn( + "No fixture data found for '%s'. (File format may be " + "invalid.)" % fixture_name, + RuntimeWarning, + ) + + def get_fixture_name_and_dirs(self, fixture_name): + dirname, basename = os.path.split(fixture_name) + if os.path.isabs(fixture_name): + fixture_dirs = [dirname] + else: + fixture_dirs = self.fixture_dirs + if os.path.sep in os.path.normpath(fixture_name): + fixture_dirs = [os.path.join(dir_, dirname) for dir_ in fixture_dirs] + return basename, fixture_dirs + + def get_targets(self, fixture_name, ser_fmt, cmp_fmt): + databases = [self.using, None] + cmp_fmts = self.compression_formats if cmp_fmt is None else [cmp_fmt] + ser_fmts = self.serialization_formats if ser_fmt is None else [ser_fmt] + return { + "%s.%s" + % ( + fixture_name, + ".".join([ext for ext in combo if ext]), + ) + for combo in product(databases, ser_fmts, cmp_fmts) + } + + def find_fixture_files_in_dir(self, fixture_dir, fixture_name, targets): + fixture_files_in_dir = [] + path = os.path.join(fixture_dir, fixture_name) + for candidate in glob.iglob(glob.escape(path) + "*"): + if os.path.basename(candidate) in targets: + # Save the fixture_dir and fixture_name for future error + # messages. + fixture_files_in_dir.append((candidate, fixture_dir, fixture_name)) + return fixture_files_in_dir + + @functools.cache + def find_fixtures(self, fixture_label): + """Find fixture files for a given label.""" + if fixture_label == READ_STDIN: + return [(READ_STDIN, None, READ_STDIN)] + + fixture_name, ser_fmt, cmp_fmt = self.parse_name(fixture_label) + if self.verbosity >= 2: + self.stdout.write("Loading '%s' fixtures..." % fixture_name) + + fixture_name, fixture_dirs = self.get_fixture_name_and_dirs(fixture_name) + targets = self.get_targets(fixture_name, ser_fmt, cmp_fmt) + fixture_files = [] + for fixture_dir in fixture_dirs: + if self.verbosity >= 2: + self.stdout.write("Checking %s for fixtures..." % humanize(fixture_dir)) + fixture_files_in_dir = self.find_fixture_files_in_dir( + fixture_dir, + fixture_name, + targets, + ) + if self.verbosity >= 2 and not fixture_files_in_dir: + self.stdout.write( + "No fixture '%s' in %s." % (fixture_name, humanize(fixture_dir)) + ) + + # Check kept for backwards-compatibility; it isn't clear why + # duplicates are only allowed in different directories. + if len(fixture_files_in_dir) > 1: + raise CommandError( + "Multiple fixtures named '%s' in %s. Aborting." + % (fixture_name, humanize(fixture_dir)) + ) + fixture_files.extend(fixture_files_in_dir) + + if not fixture_files: + raise CommandError("No fixture named '%s' found." % fixture_name) + + return fixture_files + + @cached_property + def fixture_dirs(self): + """ + Return a list of fixture directories. + + The list contains the 'fixtures' subdirectory of each installed + application, if it exists, the directories in FIXTURE_DIRS, and the + current directory. + """ + dirs = [] + fixture_dirs = settings.FIXTURE_DIRS + if len(fixture_dirs) != len(set(fixture_dirs)): + raise ImproperlyConfigured("settings.FIXTURE_DIRS contains duplicates.") + for app_config in apps.get_app_configs(): + app_label = app_config.label + app_dir = os.path.join(app_config.path, "fixtures") + if app_dir in [str(d) for d in fixture_dirs]: + raise ImproperlyConfigured( + "'%s' is a default fixture directory for the '%s' app " + "and cannot be listed in settings.FIXTURE_DIRS." + % (app_dir, app_label) + ) + + if self.app_label and app_label != self.app_label: + continue + if os.path.isdir(app_dir): + dirs.append(app_dir) + dirs.extend(fixture_dirs) + dirs.append("") + return [os.path.realpath(d) for d in dirs] + + def parse_name(self, fixture_name): + """ + Split fixture name in name, serialization format, compression format. + """ + if fixture_name == READ_STDIN: + if not self.format: + raise CommandError( + "--format must be specified when reading from stdin." + ) + return READ_STDIN, self.format, "stdin" + + parts = fixture_name.rsplit(".", 2) + + if len(parts) > 1 and parts[-1] in self.compression_formats: + cmp_fmt = parts[-1] + parts = parts[:-1] + else: + cmp_fmt = None + + if len(parts) > 1: + if parts[-1] in self.serialization_formats: + ser_fmt = parts[-1] + parts = parts[:-1] + else: + raise CommandError( + "Problem installing fixture '%s': %s is not a known " + "serialization format." % (".".join(parts[:-1]), parts[-1]) + ) + else: + ser_fmt = None + + name = ".".join(parts) + + return name, ser_fmt, cmp_fmt + + +class SingleZipReader(zipfile.ZipFile): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + if len(self.namelist()) != 1: + raise ValueError("Zip-compressed fixtures must contain one file.") + + def read(self): + return zipfile.ZipFile.read(self, self.namelist()[0]) + + +def humanize(dirname): + return "'%s'" % dirname if dirname else "absolute path" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/makemessages.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/makemessages.py new file mode 100644 index 0000000..dc3d402 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/makemessages.py @@ -0,0 +1,784 @@ +import glob +import os +import re +import sys +from functools import total_ordering +from itertools import dropwhile +from pathlib import Path + +import django +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.core.files.temp import NamedTemporaryFile +from django.core.management.base import BaseCommand, CommandError +from django.core.management.utils import ( + find_command, + handle_extensions, + is_ignored_path, + popen_wrapper, +) +from django.utils.encoding import DEFAULT_LOCALE_ENCODING +from django.utils.functional import cached_property +from django.utils.jslex import prepare_js_for_gettext +from django.utils.regex_helper import _lazy_re_compile +from django.utils.text import get_text_list +from django.utils.translation import templatize + +plural_forms_re = _lazy_re_compile( + r'^(?P"Plural-Forms.+?\\n")\s*$', re.MULTILINE | re.DOTALL +) +STATUS_OK = 0 +NO_LOCALE_DIR = object() + + +def check_programs(*programs): + for program in programs: + if find_command(program) is None: + raise CommandError( + "Can't find %s. Make sure you have GNU gettext tools 0.15 or " + "newer installed." % program + ) + + +def is_valid_locale(locale): + return re.match(r"^[a-z]+$", locale) or re.match(r"^[a-z]+_[A-Z].*$", locale) + + +@total_ordering +class TranslatableFile: + def __init__(self, dirpath, file_name, locale_dir): + self.file = file_name + self.dirpath = dirpath + self.locale_dir = locale_dir + + def __repr__(self): + return "<%s: %s>" % ( + self.__class__.__name__, + os.sep.join([self.dirpath, self.file]), + ) + + def __eq__(self, other): + return self.path == other.path + + def __lt__(self, other): + return self.path < other.path + + @property + def path(self): + return os.path.join(self.dirpath, self.file) + + +class BuildFile: + """ + Represent the state of a translatable file during the build process. + """ + + def __init__(self, command, domain, translatable): + self.command = command + self.domain = domain + self.translatable = translatable + + @cached_property + def is_templatized(self): + if self.domain == "djangojs": + return self.command.gettext_version < (0, 18, 3) + elif self.domain == "django": + file_ext = os.path.splitext(self.translatable.file)[1] + return file_ext != ".py" + return False + + @cached_property + def path(self): + return self.translatable.path + + @cached_property + def work_path(self): + """ + Path to a file which is being fed into GNU gettext pipeline. This may + be either a translatable or its preprocessed version. + """ + if not self.is_templatized: + return self.path + extension = { + "djangojs": "c", + "django": "py", + }.get(self.domain) + filename = "%s.%s" % (self.translatable.file, extension) + return os.path.join(self.translatable.dirpath, filename) + + def preprocess(self): + """ + Preprocess (if necessary) a translatable file before passing it to + xgettext GNU gettext utility. + """ + if not self.is_templatized: + return + + with open(self.path, encoding="utf-8") as fp: + src_data = fp.read() + + if self.domain == "djangojs": + content = prepare_js_for_gettext(src_data) + elif self.domain == "django": + content = templatize(src_data, origin=self.path[2:]) + + with open(self.work_path, "w", encoding="utf-8") as fp: + fp.write(content) + + def postprocess_messages(self, msgs): + """ + Postprocess messages generated by xgettext GNU gettext utility. + + Transform paths as if these messages were generated from original + translatable files rather than from preprocessed versions. + """ + if not self.is_templatized: + return msgs + + # Remove '.py' suffix + if os.name == "nt": + # Preserve '.\' prefix on Windows to respect gettext behavior + old_path = self.work_path + new_path = self.path + else: + old_path = self.work_path[2:] + new_path = self.path[2:] + + return re.sub( + r"^(#: .*)(" + re.escape(old_path) + r")", + lambda match: match[0].replace(old_path, new_path), + msgs, + flags=re.MULTILINE, + ) + + def cleanup(self): + """ + Remove a preprocessed copy of a translatable file (if any). + """ + if self.is_templatized: + # This check is needed for the case of a symlinked file and its + # source being processed inside a single group (locale dir); + # removing either of those two removes both. + if os.path.exists(self.work_path): + os.unlink(self.work_path) + + +def normalize_eols(raw_contents): + """ + Take a block of raw text that will be passed through str.splitlines() to + get universal newlines treatment. + + Return the resulting block of text with normalized `\n` EOL sequences ready + to be written to disk using current platform's native EOLs. + """ + lines_list = raw_contents.splitlines() + # Ensure last line has its EOL + if lines_list and lines_list[-1]: + lines_list.append("") + return "\n".join(lines_list) + + +def write_pot_file(potfile, msgs): + """ + Write the `potfile` with the `msgs` contents, making sure its format is + valid. + """ + pot_lines = msgs.splitlines() + if os.path.exists(potfile): + # Strip the header + lines = dropwhile(len, pot_lines) + else: + lines = [] + found, header_read = False, False + for line in pot_lines: + if not found and not header_read: + if "charset=CHARSET" in line: + found = True + line = line.replace("charset=CHARSET", "charset=UTF-8") + if not line and not found: + header_read = True + lines.append(line) + msgs = "\n".join(lines) + # Force newlines of POT files to '\n' to work around + # https://savannah.gnu.org/bugs/index.php?52395 + with open(potfile, "a", encoding="utf-8", newline="\n") as fp: + fp.write(msgs) + + +class Command(BaseCommand): + help = ( + "Runs over the entire source tree of the current directory and pulls out all " + "strings marked for translation. It creates (or updates) a message file in the " + "conf/locale (in the django tree) or locale (for projects and applications) " + "directory.\n\nYou must run this command with one of either the --locale, " + "--exclude, or --all options." + ) + + translatable_file_class = TranslatableFile + build_file_class = BuildFile + + requires_system_checks = [] + + msgmerge_options = ["-q", "--backup=none", "--previous", "--update"] + msguniq_options = ["--to-code=utf-8"] + msgattrib_options = ["--no-obsolete"] + xgettext_options = ["--from-code=UTF-8", "--add-comments=Translators"] + + def add_arguments(self, parser): + parser.add_argument( + "--locale", + "-l", + default=[], + action="append", + help=( + "Creates or updates the message files for the given locale(s) (e.g. " + "pt_BR). Can be used multiple times." + ), + ) + parser.add_argument( + "--exclude", + "-x", + default=[], + action="append", + help="Locales to exclude. Default is none. Can be used multiple times.", + ) + parser.add_argument( + "--domain", + "-d", + default="django", + help='The domain of the message files (default: "django").', + ) + parser.add_argument( + "--all", + "-a", + action="store_true", + help="Updates the message files for all existing locales.", + ) + parser.add_argument( + "--extension", + "-e", + dest="extensions", + action="append", + help='The file extension(s) to examine (default: "html,txt,py", or "js" ' + 'if the domain is "djangojs"). Separate multiple extensions with ' + "commas, or use -e multiple times.", + ) + parser.add_argument( + "--symlinks", + "-s", + action="store_true", + help="Follows symlinks to directories when examining source code " + "and templates for translation strings.", + ) + parser.add_argument( + "--ignore", + "-i", + action="append", + dest="ignore_patterns", + default=[], + metavar="PATTERN", + help="Ignore files or directories matching this glob-style pattern. " + "Use multiple times to ignore more.", + ) + parser.add_argument( + "--no-default-ignore", + action="store_false", + dest="use_default_ignore_patterns", + help=( + "Don't ignore the common glob-style patterns 'CVS', '.*', '*~' and " + "'*.pyc'." + ), + ) + parser.add_argument( + "--no-wrap", + action="store_true", + help="Don't break long message lines into several lines.", + ) + parser.add_argument( + "--no-location", + action="store_true", + help="Don't write '#: filename:line' lines.", + ) + parser.add_argument( + "--add-location", + choices=("full", "file", "never"), + const="full", + nargs="?", + help=( + "Controls '#: filename:line' lines. If the option is 'full' " + "(the default if not given), the lines include both file name " + "and line number. If it's 'file', the line number is omitted. If " + "it's 'never', the lines are suppressed (same as --no-location). " + "--add-location requires gettext 0.19 or newer." + ), + ) + parser.add_argument( + "--no-obsolete", + action="store_true", + help="Remove obsolete message strings.", + ) + parser.add_argument( + "--keep-pot", + action="store_true", + help="Keep .pot file after making messages. Useful when debugging.", + ) + + def handle(self, *args, **options): + locale = options["locale"] + exclude = options["exclude"] + self.domain = options["domain"] + self.verbosity = options["verbosity"] + process_all = options["all"] + extensions = options["extensions"] + self.symlinks = options["symlinks"] + + ignore_patterns = options["ignore_patterns"] + if options["use_default_ignore_patterns"]: + ignore_patterns += ["CVS", ".*", "*~", "*.pyc"] + self.ignore_patterns = list(set(ignore_patterns)) + + # Avoid messing with mutable class variables + if options["no_wrap"]: + self.msgmerge_options = self.msgmerge_options[:] + ["--no-wrap"] + self.msguniq_options = self.msguniq_options[:] + ["--no-wrap"] + self.msgattrib_options = self.msgattrib_options[:] + ["--no-wrap"] + self.xgettext_options = self.xgettext_options[:] + ["--no-wrap"] + if options["no_location"]: + self.msgmerge_options = self.msgmerge_options[:] + ["--no-location"] + self.msguniq_options = self.msguniq_options[:] + ["--no-location"] + self.msgattrib_options = self.msgattrib_options[:] + ["--no-location"] + self.xgettext_options = self.xgettext_options[:] + ["--no-location"] + if options["add_location"]: + if self.gettext_version < (0, 19): + raise CommandError( + "The --add-location option requires gettext 0.19 or later. " + "You have %s." % ".".join(str(x) for x in self.gettext_version) + ) + arg_add_location = "--add-location=%s" % options["add_location"] + self.msgmerge_options = self.msgmerge_options[:] + [arg_add_location] + self.msguniq_options = self.msguniq_options[:] + [arg_add_location] + self.msgattrib_options = self.msgattrib_options[:] + [arg_add_location] + self.xgettext_options = self.xgettext_options[:] + [arg_add_location] + + self.no_obsolete = options["no_obsolete"] + self.keep_pot = options["keep_pot"] + + if self.domain not in ("django", "djangojs"): + raise CommandError( + "currently makemessages only supports domains " + "'django' and 'djangojs'" + ) + if self.domain == "djangojs": + exts = extensions or ["js"] + else: + exts = extensions or ["html", "txt", "py"] + self.extensions = handle_extensions(exts) + + if (not locale and not exclude and not process_all) or self.domain is None: + raise CommandError( + "Type '%s help %s' for usage information." + % (os.path.basename(sys.argv[0]), sys.argv[1]) + ) + + if self.verbosity > 1: + self.stdout.write( + "examining files with the extensions: %s" + % get_text_list(list(self.extensions), "and") + ) + + self.invoked_for_django = False + self.locale_paths = [] + self.default_locale_path = None + if os.path.isdir(os.path.join("conf", "locale")): + self.locale_paths = [os.path.abspath(os.path.join("conf", "locale"))] + self.default_locale_path = self.locale_paths[0] + self.ignore_patterns.append("views/templates/i18n_catalog.js") + self.invoked_for_django = True + else: + if self.settings_available: + self.locale_paths.extend(settings.LOCALE_PATHS) + # Allow to run makemessages inside an app dir + if os.path.isdir("locale"): + self.locale_paths.append(os.path.abspath("locale")) + if self.locale_paths: + self.default_locale_path = self.locale_paths[0] + os.makedirs(self.default_locale_path, exist_ok=True) + + # Build locale list + looks_like_locale = re.compile(r"[a-z]{2}") + locale_dirs = filter( + os.path.isdir, glob.glob("%s/*" % self.default_locale_path) + ) + all_locales = [ + lang_code + for lang_code in map(os.path.basename, locale_dirs) + if looks_like_locale.match(lang_code) + ] + + # Account for excluded locales + if process_all: + locales = all_locales + else: + locales = locale or all_locales + locales = set(locales).difference(exclude) + + if locales: + check_programs("msguniq", "msgmerge", "msgattrib") + + check_programs("xgettext") + + try: + potfiles = self.build_potfiles() + + # Build po files for each selected locale + for locale in locales: + if not is_valid_locale(locale): + # Try to guess what valid locale it could be + # Valid examples are: en_GB, shi_Latn_MA and nl_NL-x-informal + + # Search for characters followed by a non character (i.e. separator) + match = re.match( + r"^(?P[a-zA-Z]+)" + r"(?P[^a-zA-Z])" + r"(?P.+)$", + locale, + ) + if match: + locale_parts = match.groupdict() + language = locale_parts["language"].lower() + territory = ( + locale_parts["territory"][:2].upper() + + locale_parts["territory"][2:] + ) + proposed_locale = f"{language}_{territory}" + else: + # It could be a language in uppercase + proposed_locale = locale.lower() + + # Recheck if the proposed locale is valid + if is_valid_locale(proposed_locale): + self.stdout.write( + "invalid locale %s, did you mean %s?" + % ( + locale, + proposed_locale, + ), + ) + else: + self.stdout.write("invalid locale %s" % locale) + + continue + if self.verbosity > 0: + self.stdout.write("processing locale %s" % locale) + for potfile in potfiles: + self.write_po_file(potfile, locale) + finally: + if not self.keep_pot: + self.remove_potfiles() + + @cached_property + def gettext_version(self): + # Gettext tools will output system-encoded bytestrings instead of UTF-8, + # when looking up the version. It's especially a problem on Windows. + out, err, status = popen_wrapper( + ["xgettext", "--version"], + stdout_encoding=DEFAULT_LOCALE_ENCODING, + ) + m = re.search(r"(\d+)\.(\d+)\.?(\d+)?", out) + if m: + return tuple(int(d) for d in m.groups() if d is not None) + else: + raise CommandError("Unable to get gettext version. Is it installed?") + + @cached_property + def settings_available(self): + try: + settings.LOCALE_PATHS + except ImproperlyConfigured: + if self.verbosity > 1: + self.stderr.write("Running without configured settings.") + return False + return True + + def build_potfiles(self): + """ + Build pot files and apply msguniq to them. + """ + file_list = self.find_files(".") + self.remove_potfiles() + self.process_files(file_list) + potfiles = [] + for path in self.locale_paths: + potfile = os.path.join(path, "%s.pot" % self.domain) + if not os.path.exists(potfile): + continue + args = ["msguniq"] + self.msguniq_options + [potfile] + msgs, errors, status = popen_wrapper(args) + if errors: + if status != STATUS_OK: + raise CommandError( + "errors happened while running msguniq\n%s" % errors + ) + elif self.verbosity > 0: + self.stdout.write(errors) + msgs = normalize_eols(msgs) + with open(potfile, "w", encoding="utf-8") as fp: + fp.write(msgs) + potfiles.append(potfile) + return potfiles + + def remove_potfiles(self): + for path in self.locale_paths: + pot_path = os.path.join(path, "%s.pot" % self.domain) + if os.path.exists(pot_path): + os.unlink(pot_path) + + def find_files(self, root): + """ + Get all files in the given root. Also check that there is a matching + locale dir for each file. + """ + all_files = [] + ignored_roots = [] + if self.settings_available: + ignored_roots = [ + os.path.normpath(p) + for p in (settings.MEDIA_ROOT, settings.STATIC_ROOT) + if p + ] + for dirpath, dirnames, filenames in os.walk( + root, topdown=True, followlinks=self.symlinks + ): + for dirname in dirnames[:]: + if ( + is_ignored_path( + os.path.normpath(os.path.join(dirpath, dirname)), + self.ignore_patterns, + ) + or os.path.join(os.path.abspath(dirpath), dirname) in ignored_roots + ): + dirnames.remove(dirname) + if self.verbosity > 1: + self.stdout.write("ignoring directory %s" % dirname) + elif dirname == "locale": + dirnames.remove(dirname) + self.locale_paths.insert( + 0, os.path.join(os.path.abspath(dirpath), dirname) + ) + for filename in filenames: + file_path = os.path.normpath(os.path.join(dirpath, filename)) + file_ext = os.path.splitext(filename)[1] + if file_ext not in self.extensions or is_ignored_path( + file_path, self.ignore_patterns + ): + if self.verbosity > 1: + self.stdout.write( + "ignoring file %s in %s" % (filename, dirpath) + ) + else: + locale_dir = None + for path in self.locale_paths: + if os.path.abspath(dirpath).startswith(os.path.dirname(path)): + locale_dir = path + break + locale_dir = locale_dir or self.default_locale_path or NO_LOCALE_DIR + all_files.append( + self.translatable_file_class(dirpath, filename, locale_dir) + ) + return sorted(all_files) + + def process_files(self, file_list): + """ + Group translatable files by locale directory and run pot file build + process for each group. + """ + file_groups = {} + for translatable in file_list: + file_group = file_groups.setdefault(translatable.locale_dir, []) + file_group.append(translatable) + for locale_dir, files in file_groups.items(): + self.process_locale_dir(locale_dir, files) + + def process_locale_dir(self, locale_dir, files): + """ + Extract translatable literals from the specified files, creating or + updating the POT file for a given locale directory. + + Use the xgettext GNU gettext utility. + """ + build_files = [] + for translatable in files: + if self.verbosity > 1: + self.stdout.write( + "processing file %s in %s" + % (translatable.file, translatable.dirpath) + ) + if self.domain not in ("djangojs", "django"): + continue + build_file = self.build_file_class(self, self.domain, translatable) + try: + build_file.preprocess() + except UnicodeDecodeError as e: + self.stdout.write( + "UnicodeDecodeError: skipped file %s in %s (reason: %s)" + % ( + translatable.file, + translatable.dirpath, + e, + ) + ) + continue + except BaseException: + # Cleanup before exit. + for build_file in build_files: + build_file.cleanup() + raise + build_files.append(build_file) + + if self.domain == "djangojs": + is_templatized = build_file.is_templatized + args = [ + "xgettext", + "-d", + self.domain, + "--language=%s" % ("C" if is_templatized else "JavaScript",), + "--keyword=gettext_noop", + "--keyword=gettext_lazy", + "--keyword=ngettext_lazy:1,2", + "--keyword=pgettext:1c,2", + "--keyword=npgettext:1c,2,3", + "--output=-", + ] + elif self.domain == "django": + args = [ + "xgettext", + "-d", + self.domain, + "--language=Python", + "--keyword=gettext_noop", + "--keyword=gettext_lazy", + "--keyword=ngettext_lazy:1,2", + "--keyword=pgettext:1c,2", + "--keyword=npgettext:1c,2,3", + "--keyword=pgettext_lazy:1c,2", + "--keyword=npgettext_lazy:1c,2,3", + "--output=-", + ] + else: + return + + input_files = [bf.work_path for bf in build_files] + with NamedTemporaryFile(mode="w+") as input_files_list: + input_files_list.write("\n".join(input_files)) + input_files_list.flush() + args.extend(["--files-from", input_files_list.name]) + args.extend(self.xgettext_options) + msgs, errors, status = popen_wrapper(args) + + if errors: + if status != STATUS_OK: + for build_file in build_files: + build_file.cleanup() + raise CommandError( + "errors happened while running xgettext on %s\n%s" + % ("\n".join(input_files), errors) + ) + elif self.verbosity > 0: + # Print warnings + self.stdout.write(errors) + + if msgs: + if locale_dir is NO_LOCALE_DIR: + for build_file in build_files: + build_file.cleanup() + file_path = os.path.normpath(build_files[0].path) + raise CommandError( + "Unable to find a locale path to store translations for " + "file %s. Make sure the 'locale' directory exists in an " + "app or LOCALE_PATHS setting is set." % file_path + ) + for build_file in build_files: + msgs = build_file.postprocess_messages(msgs) + potfile = os.path.join(locale_dir, "%s.pot" % self.domain) + write_pot_file(potfile, msgs) + + for build_file in build_files: + build_file.cleanup() + + def write_po_file(self, potfile, locale): + """ + Create or update the PO file for self.domain and `locale`. + Use contents of the existing `potfile`. + + Use msgmerge and msgattrib GNU gettext utilities. + """ + basedir = os.path.join(os.path.dirname(potfile), locale, "LC_MESSAGES") + os.makedirs(basedir, exist_ok=True) + pofile = os.path.join(basedir, "%s.po" % self.domain) + + if os.path.exists(pofile): + args = ["msgmerge"] + self.msgmerge_options + [pofile, potfile] + _, errors, status = popen_wrapper(args) + if errors: + if status != STATUS_OK: + raise CommandError( + "errors happened while running msgmerge\n%s" % errors + ) + elif self.verbosity > 0: + self.stdout.write(errors) + msgs = Path(pofile).read_text(encoding="utf-8") + else: + with open(potfile, encoding="utf-8") as fp: + msgs = fp.read() + if not self.invoked_for_django: + msgs = self.copy_plural_forms(msgs, locale) + msgs = normalize_eols(msgs) + msgs = msgs.replace( + "#. #-#-#-#-# %s.pot (PACKAGE VERSION) #-#-#-#-#\n" % self.domain, "" + ) + with open(pofile, "w", encoding="utf-8") as fp: + fp.write(msgs) + + if self.no_obsolete: + args = ["msgattrib"] + self.msgattrib_options + ["-o", pofile, pofile] + msgs, errors, status = popen_wrapper(args) + if errors: + if status != STATUS_OK: + raise CommandError( + "errors happened while running msgattrib\n%s" % errors + ) + elif self.verbosity > 0: + self.stdout.write(errors) + + def copy_plural_forms(self, msgs, locale): + """ + Copy plural forms header contents from a Django catalog of locale to + the msgs string, inserting it at the right place. msgs should be the + contents of a newly created .po file. + """ + django_dir = os.path.normpath(os.path.join(os.path.dirname(django.__file__))) + if self.domain == "djangojs": + domains = ("djangojs", "django") + else: + domains = ("django",) + for domain in domains: + django_po = os.path.join( + django_dir, "conf", "locale", locale, "LC_MESSAGES", "%s.po" % domain + ) + if os.path.exists(django_po): + with open(django_po, encoding="utf-8") as fp: + m = plural_forms_re.search(fp.read()) + if m: + plural_form_line = m["value"] + if self.verbosity > 1: + self.stdout.write("copying plural forms: %s" % plural_form_line) + lines = [] + found = False + for line in msgs.splitlines(): + if not found and (not line or plural_forms_re.search(line)): + line = plural_form_line + found = True + lines.append(line) + msgs = "\n".join(lines) + break + return msgs diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/makemigrations.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/makemigrations.py new file mode 100644 index 0000000..22498af --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/makemigrations.py @@ -0,0 +1,515 @@ +import os +import sys +import warnings +from itertools import takewhile + +from django.apps import apps +from django.conf import settings +from django.core.management.base import BaseCommand, CommandError, no_translations +from django.core.management.utils import run_formatters +from django.db import DEFAULT_DB_ALIAS, OperationalError, connections, router +from django.db.migrations import Migration +from django.db.migrations.autodetector import MigrationAutodetector +from django.db.migrations.loader import MigrationLoader +from django.db.migrations.migration import SwappableTuple +from django.db.migrations.optimizer import MigrationOptimizer +from django.db.migrations.questioner import ( + InteractiveMigrationQuestioner, + MigrationQuestioner, + NonInteractiveMigrationQuestioner, +) +from django.db.migrations.state import ProjectState +from django.db.migrations.utils import get_migration_name_timestamp +from django.db.migrations.writer import MigrationWriter + + +class Command(BaseCommand): + help = "Creates new migration(s) for apps." + + def add_arguments(self, parser): + parser.add_argument( + "args", + metavar="app_label", + nargs="*", + help="Specify the app label(s) to create migrations for.", + ) + parser.add_argument( + "--dry-run", + action="store_true", + help="Just show what migrations would be made; don't actually write them.", + ) + parser.add_argument( + "--merge", + action="store_true", + help="Enable fixing of migration conflicts.", + ) + parser.add_argument( + "--empty", + action="store_true", + help="Create an empty migration.", + ) + parser.add_argument( + "--noinput", + "--no-input", + action="store_false", + dest="interactive", + help="Tells Django to NOT prompt the user for input of any kind.", + ) + parser.add_argument( + "-n", + "--name", + help="Use this name for migration file(s).", + ) + parser.add_argument( + "--no-header", + action="store_false", + dest="include_header", + help="Do not add header comments to new migration file(s).", + ) + parser.add_argument( + "--check", + action="store_true", + dest="check_changes", + help=( + "Exit with a non-zero status if model changes are missing migrations " + "and don't actually write them. Implies --dry-run." + ), + ) + parser.add_argument( + "--scriptable", + action="store_true", + dest="scriptable", + help=( + "Divert log output and input prompts to stderr, writing only " + "paths of generated migration files to stdout." + ), + ) + parser.add_argument( + "--update", + action="store_true", + dest="update", + help=( + "Merge model changes into the latest migration and optimize the " + "resulting operations." + ), + ) + + @property + def log_output(self): + return self.stderr if self.scriptable else self.stdout + + def log(self, msg): + self.log_output.write(msg) + + @no_translations + def handle(self, *app_labels, **options): + self.written_files = [] + self.verbosity = options["verbosity"] + self.interactive = options["interactive"] + self.dry_run = options["dry_run"] + self.merge = options["merge"] + self.empty = options["empty"] + self.migration_name = options["name"] + if self.migration_name and not self.migration_name.isidentifier(): + raise CommandError("The migration name must be a valid Python identifier.") + self.include_header = options["include_header"] + check_changes = options["check_changes"] + if check_changes: + self.dry_run = True + self.scriptable = options["scriptable"] + self.update = options["update"] + # If logs and prompts are diverted to stderr, remove the ERROR style. + if self.scriptable: + self.stderr.style_func = None + + # Make sure the app they asked for exists + app_labels = set(app_labels) + has_bad_labels = False + for app_label in app_labels: + try: + apps.get_app_config(app_label) + except LookupError as err: + self.stderr.write(str(err)) + has_bad_labels = True + if has_bad_labels: + sys.exit(2) + + # Load the current graph state. Pass in None for the connection so + # the loader doesn't try to resolve replaced migrations from DB. + loader = MigrationLoader(None, ignore_no_migrations=True) + + # Raise an error if any migrations are applied before their dependencies. + consistency_check_labels = {config.label for config in apps.get_app_configs()} + # Non-default databases are only checked if database routers used. + aliases_to_check = ( + connections if settings.DATABASE_ROUTERS else [DEFAULT_DB_ALIAS] + ) + for alias in sorted(aliases_to_check): + connection = connections[alias] + if connection.settings_dict["ENGINE"] != "django.db.backends.dummy" and any( + # At least one model must be migrated to the database. + router.allow_migrate( + connection.alias, app_label, model_name=model._meta.object_name + ) + for app_label in consistency_check_labels + for model in apps.get_app_config(app_label).get_models() + ): + try: + loader.check_consistent_history(connection) + except OperationalError as error: + warnings.warn( + "Got an error checking a consistent migration history " + "performed for database connection '%s': %s" % (alias, error), + RuntimeWarning, + ) + # Before anything else, see if there's conflicting apps and drop out + # hard if there are any and they don't want to merge + conflicts = loader.detect_conflicts() + + # If app_labels is specified, filter out conflicting migrations for + # unspecified apps. + if app_labels: + conflicts = { + app_label: conflict + for app_label, conflict in conflicts.items() + if app_label in app_labels + } + + if conflicts and not self.merge: + name_str = "; ".join( + "%s in %s" % (", ".join(names), app) for app, names in conflicts.items() + ) + raise CommandError( + "Conflicting migrations detected; multiple leaf nodes in the " + "migration graph: (%s).\nTo fix them run " + "'python manage.py makemigrations --merge'" % name_str + ) + + # If they want to merge and there's nothing to merge, then politely exit + if self.merge and not conflicts: + self.log("No conflicts detected to merge.") + return + + # If they want to merge and there is something to merge, then + # divert into the merge code + if self.merge and conflicts: + return self.handle_merge(loader, conflicts) + + if self.interactive: + questioner = InteractiveMigrationQuestioner( + specified_apps=app_labels, + dry_run=self.dry_run, + prompt_output=self.log_output, + ) + else: + questioner = NonInteractiveMigrationQuestioner( + specified_apps=app_labels, + dry_run=self.dry_run, + verbosity=self.verbosity, + log=self.log, + ) + # Set up autodetector + autodetector = MigrationAutodetector( + loader.project_state(), + ProjectState.from_apps(apps), + questioner, + ) + + # If they want to make an empty migration, make one for each app + if self.empty: + if not app_labels: + raise CommandError( + "You must supply at least one app label when using --empty." + ) + # Make a fake changes() result we can pass to arrange_for_graph + changes = {app: [Migration("custom", app)] for app in app_labels} + changes = autodetector.arrange_for_graph( + changes=changes, + graph=loader.graph, + migration_name=self.migration_name, + ) + self.write_migration_files(changes) + return + + # Detect changes + changes = autodetector.changes( + graph=loader.graph, + trim_to_apps=app_labels or None, + convert_apps=app_labels or None, + migration_name=self.migration_name, + ) + + if not changes: + # No changes? Tell them. + if self.verbosity >= 1: + if app_labels: + if len(app_labels) == 1: + self.log("No changes detected in app '%s'" % app_labels.pop()) + else: + self.log( + "No changes detected in apps '%s'" + % ("', '".join(app_labels)) + ) + else: + self.log("No changes detected") + else: + if self.update: + self.write_to_last_migration_files(changes) + else: + self.write_migration_files(changes) + if check_changes: + sys.exit(1) + + def write_to_last_migration_files(self, changes): + loader = MigrationLoader(connections[DEFAULT_DB_ALIAS]) + new_changes = {} + update_previous_migration_paths = {} + for app_label, app_migrations in changes.items(): + # Find last migration. + leaf_migration_nodes = loader.graph.leaf_nodes(app=app_label) + if len(leaf_migration_nodes) == 0: + raise CommandError( + f"App {app_label} has no migration, cannot update last migration." + ) + leaf_migration_node = leaf_migration_nodes[0] + # Multiple leaf nodes have already been checked earlier in command. + leaf_migration = loader.graph.nodes[leaf_migration_node] + # Updated migration cannot be a squash migration, a dependency of + # another migration, and cannot be already applied. + if leaf_migration.replaces: + raise CommandError( + f"Cannot update squash migration '{leaf_migration}'." + ) + if leaf_migration_node in loader.applied_migrations: + raise CommandError( + f"Cannot update applied migration '{leaf_migration}'." + ) + depending_migrations = [ + migration + for migration in loader.disk_migrations.values() + if leaf_migration_node in migration.dependencies + ] + if depending_migrations: + formatted_migrations = ", ".join( + [f"'{migration}'" for migration in depending_migrations] + ) + raise CommandError( + f"Cannot update migration '{leaf_migration}' that migrations " + f"{formatted_migrations} depend on." + ) + # Build new migration. + for migration in app_migrations: + leaf_migration.operations.extend(migration.operations) + + for dependency in migration.dependencies: + if isinstance(dependency, SwappableTuple): + if settings.AUTH_USER_MODEL == dependency.setting: + leaf_migration.dependencies.append( + ("__setting__", "AUTH_USER_MODEL") + ) + else: + leaf_migration.dependencies.append(dependency) + elif dependency[0] != migration.app_label: + leaf_migration.dependencies.append(dependency) + # Optimize migration. + optimizer = MigrationOptimizer() + leaf_migration.operations = optimizer.optimize( + leaf_migration.operations, app_label + ) + # Update name. + previous_migration_path = MigrationWriter(leaf_migration).path + name_fragment = self.migration_name or leaf_migration.suggest_name() + suggested_name = leaf_migration.name[:4] + f"_{name_fragment}" + if leaf_migration.name == suggested_name: + new_name = leaf_migration.name + "_updated" + else: + new_name = suggested_name + leaf_migration.name = new_name + # Register overridden migration. + new_changes[app_label] = [leaf_migration] + update_previous_migration_paths[app_label] = previous_migration_path + + self.write_migration_files(new_changes, update_previous_migration_paths) + + def write_migration_files(self, changes, update_previous_migration_paths=None): + """ + Take a changes dict and write them out as migration files. + """ + directory_created = {} + for app_label, app_migrations in changes.items(): + if self.verbosity >= 1: + self.log(self.style.MIGRATE_HEADING("Migrations for '%s':" % app_label)) + for migration in app_migrations: + # Describe the migration + writer = MigrationWriter(migration, self.include_header) + if self.verbosity >= 1: + # Display a relative path if it's below the current working + # directory, or an absolute path otherwise. + migration_string = self.get_relative_path(writer.path) + self.log(" %s\n" % self.style.MIGRATE_LABEL(migration_string)) + for operation in migration.operations: + self.log(" - %s" % operation.describe()) + if self.scriptable: + self.stdout.write(migration_string) + if not self.dry_run: + # Write the migrations file to the disk. + migrations_directory = os.path.dirname(writer.path) + if not directory_created.get(app_label): + os.makedirs(migrations_directory, exist_ok=True) + init_path = os.path.join(migrations_directory, "__init__.py") + if not os.path.isfile(init_path): + open(init_path, "w").close() + # We just do this once per app + directory_created[app_label] = True + migration_string = writer.as_string() + with open(writer.path, "w", encoding="utf-8") as fh: + fh.write(migration_string) + self.written_files.append(writer.path) + if update_previous_migration_paths: + prev_path = update_previous_migration_paths[app_label] + rel_prev_path = self.get_relative_path(prev_path) + if writer.needs_manual_porting: + migration_path = self.get_relative_path(writer.path) + self.log( + self.style.WARNING( + f"Updated migration {migration_path} requires " + f"manual porting.\n" + f"Previous migration {rel_prev_path} was kept and " + f"must be deleted after porting functions manually." + ) + ) + else: + os.remove(prev_path) + self.log(f"Deleted {rel_prev_path}") + elif self.verbosity == 3: + # Alternatively, makemigrations --dry-run --verbosity 3 + # will log the migrations rather than saving the file to + # the disk. + self.log( + self.style.MIGRATE_HEADING( + "Full migrations file '%s':" % writer.filename + ) + ) + self.log(writer.as_string()) + run_formatters(self.written_files) + + @staticmethod + def get_relative_path(path): + try: + migration_string = os.path.relpath(path) + except ValueError: + migration_string = path + if migration_string.startswith(".."): + migration_string = path + return migration_string + + def handle_merge(self, loader, conflicts): + """ + Handles merging together conflicted migrations interactively, + if it's safe; otherwise, advises on how to fix it. + """ + if self.interactive: + questioner = InteractiveMigrationQuestioner(prompt_output=self.log_output) + else: + questioner = MigrationQuestioner(defaults={"ask_merge": True}) + + for app_label, migration_names in conflicts.items(): + # Grab out the migrations in question, and work out their + # common ancestor. + merge_migrations = [] + for migration_name in migration_names: + migration = loader.get_migration(app_label, migration_name) + migration.ancestry = [ + mig + for mig in loader.graph.forwards_plan((app_label, migration_name)) + if mig[0] == migration.app_label + ] + merge_migrations.append(migration) + + def all_items_equal(seq): + return all(item == seq[0] for item in seq[1:]) + + merge_migrations_generations = zip(*(m.ancestry for m in merge_migrations)) + common_ancestor_count = sum( + 1 + for common_ancestor_generation in takewhile( + all_items_equal, merge_migrations_generations + ) + ) + if not common_ancestor_count: + raise ValueError( + "Could not find common ancestor of %s" % migration_names + ) + # Now work out the operations along each divergent branch + for migration in merge_migrations: + migration.branch = migration.ancestry[common_ancestor_count:] + migrations_ops = ( + loader.get_migration(node_app, node_name).operations + for node_app, node_name in migration.branch + ) + migration.merged_operations = sum(migrations_ops, []) + # In future, this could use some of the Optimizer code + # (can_optimize_through) to automatically see if they're + # mergeable. For now, we always just prompt the user. + if self.verbosity > 0: + self.log(self.style.MIGRATE_HEADING("Merging %s" % app_label)) + for migration in merge_migrations: + self.log(self.style.MIGRATE_LABEL(" Branch %s" % migration.name)) + for operation in migration.merged_operations: + self.log(" - %s" % operation.describe()) + if questioner.ask_merge(app_label): + # If they still want to merge it, then write out an empty + # file depending on the migrations needing merging. + numbers = [ + MigrationAutodetector.parse_number(migration.name) + for migration in merge_migrations + ] + try: + biggest_number = max(x for x in numbers if x is not None) + except ValueError: + biggest_number = 1 + subclass = type( + "Migration", + (Migration,), + { + "dependencies": [ + (app_label, migration.name) + for migration in merge_migrations + ], + }, + ) + parts = ["%04i" % (biggest_number + 1)] + if self.migration_name: + parts.append(self.migration_name) + else: + parts.append("merge") + leaf_names = "_".join( + sorted(migration.name for migration in merge_migrations) + ) + if len(leaf_names) > 47: + parts.append(get_migration_name_timestamp()) + else: + parts.append(leaf_names) + migration_name = "_".join(parts) + new_migration = subclass(migration_name, app_label) + writer = MigrationWriter(new_migration, self.include_header) + + if not self.dry_run: + # Write the merge migrations file to the disk + with open(writer.path, "w", encoding="utf-8") as fh: + fh.write(writer.as_string()) + run_formatters([writer.path]) + if self.verbosity > 0: + self.log("\nCreated new merge migration %s" % writer.path) + if self.scriptable: + self.stdout.write(writer.path) + elif self.verbosity == 3: + # Alternatively, makemigrations --merge --dry-run --verbosity 3 + # will log the merge migrations rather than saving the file + # to the disk. + self.log( + self.style.MIGRATE_HEADING( + "Full merge migrations file '%s':" % writer.filename + ) + ) + self.log(writer.as_string()) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/migrate.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/migrate.py new file mode 100644 index 0000000..1541843 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/migrate.py @@ -0,0 +1,511 @@ +import sys +import time +from importlib import import_module + +from django.apps import apps +from django.core.management.base import BaseCommand, CommandError, no_translations +from django.core.management.sql import emit_post_migrate_signal, emit_pre_migrate_signal +from django.db import DEFAULT_DB_ALIAS, connections, router +from django.db.migrations.autodetector import MigrationAutodetector +from django.db.migrations.executor import MigrationExecutor +from django.db.migrations.loader import AmbiguityError +from django.db.migrations.state import ModelState, ProjectState +from django.utils.module_loading import module_has_submodule +from django.utils.text import Truncator + + +class Command(BaseCommand): + help = ( + "Updates database schema. Manages both apps with migrations and those without." + ) + requires_system_checks = [] + + def add_arguments(self, parser): + parser.add_argument( + "--skip-checks", + action="store_true", + help="Skip system checks.", + ) + parser.add_argument( + "app_label", + nargs="?", + help="App label of an application to synchronize the state.", + ) + parser.add_argument( + "migration_name", + nargs="?", + help="Database state will be brought to the state after that " + 'migration. Use the name "zero" to unapply all migrations.', + ) + parser.add_argument( + "--noinput", + "--no-input", + action="store_false", + dest="interactive", + help="Tells Django to NOT prompt the user for input of any kind.", + ) + parser.add_argument( + "--database", + default=DEFAULT_DB_ALIAS, + help=( + 'Nominates a database to synchronize. Defaults to the "default" ' + "database." + ), + ) + parser.add_argument( + "--fake", + action="store_true", + help="Mark migrations as run without actually running them.", + ) + parser.add_argument( + "--fake-initial", + action="store_true", + help=( + "Detect if tables already exist and fake-apply initial migrations if " + "so. Make sure that the current database schema matches your initial " + "migration before using this flag. Django will only check for an " + "existing table name." + ), + ) + parser.add_argument( + "--plan", + action="store_true", + help="Shows a list of the migration actions that will be performed.", + ) + parser.add_argument( + "--run-syncdb", + action="store_true", + help="Creates tables for apps without migrations.", + ) + parser.add_argument( + "--check", + action="store_true", + dest="check_unapplied", + help=( + "Exits with a non-zero status if unapplied migrations exist and does " + "not actually apply migrations." + ), + ) + parser.add_argument( + "--prune", + action="store_true", + dest="prune", + help="Delete nonexistent migrations from the django_migrations table.", + ) + + @no_translations + def handle(self, *args, **options): + database = options["database"] + if not options["skip_checks"]: + self.check(databases=[database]) + + self.verbosity = options["verbosity"] + self.interactive = options["interactive"] + + # Import the 'management' module within each installed app, to register + # dispatcher events. + for app_config in apps.get_app_configs(): + if module_has_submodule(app_config.module, "management"): + import_module(".management", app_config.name) + + # Get the database we're operating from + connection = connections[database] + + # Hook for backends needing any database preparation + connection.prepare_database() + # Work out which apps have migrations and which do not + executor = MigrationExecutor(connection, self.migration_progress_callback) + + # Raise an error if any migrations are applied before their dependencies. + executor.loader.check_consistent_history(connection) + + # Before anything else, see if there's conflicting apps and drop out + # hard if there are any + conflicts = executor.loader.detect_conflicts() + if conflicts: + name_str = "; ".join( + "%s in %s" % (", ".join(names), app) for app, names in conflicts.items() + ) + raise CommandError( + "Conflicting migrations detected; multiple leaf nodes in the " + "migration graph: (%s).\nTo fix them run " + "'python manage.py makemigrations --merge'" % name_str + ) + + # If they supplied command line arguments, work out what they mean. + run_syncdb = options["run_syncdb"] + target_app_labels_only = True + if options["app_label"]: + # Validate app_label. + app_label = options["app_label"] + try: + apps.get_app_config(app_label) + except LookupError as err: + raise CommandError(str(err)) + if run_syncdb: + if app_label in executor.loader.migrated_apps: + raise CommandError( + "Can't use run_syncdb with app '%s' as it has migrations." + % app_label + ) + elif app_label not in executor.loader.migrated_apps: + raise CommandError("App '%s' does not have migrations." % app_label) + + if options["app_label"] and options["migration_name"]: + migration_name = options["migration_name"] + if migration_name == "zero": + targets = [(app_label, None)] + else: + try: + migration = executor.loader.get_migration_by_prefix( + app_label, migration_name + ) + except AmbiguityError: + raise CommandError( + "More than one migration matches '%s' in app '%s'. " + "Please be more specific." % (migration_name, app_label) + ) + except KeyError: + raise CommandError( + "Cannot find a migration matching '%s' from app '%s'." + % (migration_name, app_label) + ) + target = (app_label, migration.name) + # Partially applied squashed migrations are not included in the + # graph, use the last replacement instead. + if ( + target not in executor.loader.graph.nodes + and target in executor.loader.replacements + ): + incomplete_migration = executor.loader.replacements[target] + target = incomplete_migration.replaces[-1] + targets = [target] + target_app_labels_only = False + elif options["app_label"]: + targets = [ + key for key in executor.loader.graph.leaf_nodes() if key[0] == app_label + ] + else: + targets = executor.loader.graph.leaf_nodes() + + if options["prune"]: + if not options["app_label"]: + raise CommandError( + "Migrations can be pruned only when an app is specified." + ) + if self.verbosity > 0: + self.stdout.write("Pruning migrations:", self.style.MIGRATE_HEADING) + to_prune = set(executor.loader.applied_migrations) - set( + executor.loader.disk_migrations + ) + squashed_migrations_with_deleted_replaced_migrations = [ + migration_key + for migration_key, migration_obj in executor.loader.replacements.items() + if any(replaced in to_prune for replaced in migration_obj.replaces) + ] + if squashed_migrations_with_deleted_replaced_migrations: + self.stdout.write( + self.style.NOTICE( + " Cannot use --prune because the following squashed " + "migrations have their 'replaces' attributes and may not " + "be recorded as applied:" + ) + ) + for migration in squashed_migrations_with_deleted_replaced_migrations: + app, name = migration + self.stdout.write(f" {app}.{name}") + self.stdout.write( + self.style.NOTICE( + " Re-run 'manage.py migrate' if they are not marked as " + "applied, and remove 'replaces' attributes in their " + "Migration classes." + ) + ) + else: + to_prune = sorted( + migration for migration in to_prune if migration[0] == app_label + ) + if to_prune: + for migration in to_prune: + app, name = migration + if self.verbosity > 0: + self.stdout.write( + self.style.MIGRATE_LABEL(f" Pruning {app}.{name}"), + ending="", + ) + executor.recorder.record_unapplied(app, name) + if self.verbosity > 0: + self.stdout.write(self.style.SUCCESS(" OK")) + elif self.verbosity > 0: + self.stdout.write(" No migrations to prune.") + + plan = executor.migration_plan(targets) + + if options["plan"]: + self.stdout.write("Planned operations:", self.style.MIGRATE_LABEL) + if not plan: + self.stdout.write(" No planned migration operations.") + else: + for migration, backwards in plan: + self.stdout.write(str(migration), self.style.MIGRATE_HEADING) + for operation in migration.operations: + message, is_error = self.describe_operation( + operation, backwards + ) + style = self.style.WARNING if is_error else None + self.stdout.write(" " + message, style) + if options["check_unapplied"]: + sys.exit(1) + return + if options["check_unapplied"]: + if plan: + sys.exit(1) + return + if options["prune"]: + return + + # At this point, ignore run_syncdb if there aren't any apps to sync. + run_syncdb = options["run_syncdb"] and executor.loader.unmigrated_apps + # Print some useful info + if self.verbosity >= 1: + self.stdout.write(self.style.MIGRATE_HEADING("Operations to perform:")) + if run_syncdb: + if options["app_label"]: + self.stdout.write( + self.style.MIGRATE_LABEL( + " Synchronize unmigrated app: %s" % app_label + ) + ) + else: + self.stdout.write( + self.style.MIGRATE_LABEL(" Synchronize unmigrated apps: ") + + (", ".join(sorted(executor.loader.unmigrated_apps))) + ) + if target_app_labels_only: + self.stdout.write( + self.style.MIGRATE_LABEL(" Apply all migrations: ") + + (", ".join(sorted({a for a, n in targets})) or "(none)") + ) + else: + if targets[0][1] is None: + self.stdout.write( + self.style.MIGRATE_LABEL(" Unapply all migrations: ") + + str(targets[0][0]) + ) + else: + self.stdout.write( + self.style.MIGRATE_LABEL(" Target specific migration: ") + + "%s, from %s" % (targets[0][1], targets[0][0]) + ) + + pre_migrate_state = executor._create_project_state(with_applied_migrations=True) + pre_migrate_apps = pre_migrate_state.apps + emit_pre_migrate_signal( + self.verbosity, + self.interactive, + connection.alias, + stdout=self.stdout, + apps=pre_migrate_apps, + plan=plan, + ) + + # Run the syncdb phase. + if run_syncdb: + if self.verbosity >= 1: + self.stdout.write( + self.style.MIGRATE_HEADING("Synchronizing apps without migrations:") + ) + if options["app_label"]: + self.sync_apps(connection, [app_label]) + else: + self.sync_apps(connection, executor.loader.unmigrated_apps) + + # Migrate! + if self.verbosity >= 1: + self.stdout.write(self.style.MIGRATE_HEADING("Running migrations:")) + if not plan: + if self.verbosity >= 1: + self.stdout.write(" No migrations to apply.") + # If there's changes that aren't in migrations yet, tell them + # how to fix it. + autodetector = MigrationAutodetector( + executor.loader.project_state(), + ProjectState.from_apps(apps), + ) + changes = autodetector.changes(graph=executor.loader.graph) + if changes: + self.stdout.write( + self.style.NOTICE( + " Your models in app(s): %s have changes that are not " + "yet reflected in a migration, and so won't be " + "applied." % ", ".join(repr(app) for app in sorted(changes)) + ) + ) + self.stdout.write( + self.style.NOTICE( + " Run 'manage.py makemigrations' to make new " + "migrations, and then re-run 'manage.py migrate' to " + "apply them." + ) + ) + fake = False + fake_initial = False + else: + fake = options["fake"] + fake_initial = options["fake_initial"] + post_migrate_state = executor.migrate( + targets, + plan=plan, + state=pre_migrate_state.clone(), + fake=fake, + fake_initial=fake_initial, + ) + # post_migrate signals have access to all models. Ensure that all models + # are reloaded in case any are delayed. + post_migrate_state.clear_delayed_apps_cache() + post_migrate_apps = post_migrate_state.apps + + # Re-render models of real apps to include relationships now that + # we've got a final state. This wouldn't be necessary if real apps + # models were rendered with relationships in the first place. + with post_migrate_apps.bulk_update(): + model_keys = [] + for model_state in post_migrate_apps.real_models: + model_key = model_state.app_label, model_state.name_lower + model_keys.append(model_key) + post_migrate_apps.unregister_model(*model_key) + post_migrate_apps.render_multiple( + [ModelState.from_model(apps.get_model(*model)) for model in model_keys] + ) + + # Send the post_migrate signal, so individual apps can do whatever they need + # to do at this point. + emit_post_migrate_signal( + self.verbosity, + self.interactive, + connection.alias, + stdout=self.stdout, + apps=post_migrate_apps, + plan=plan, + ) + + def migration_progress_callback(self, action, migration=None, fake=False): + if self.verbosity >= 1: + compute_time = self.verbosity > 1 + if action == "apply_start": + if compute_time: + self.start = time.monotonic() + self.stdout.write(" Applying %s..." % migration, ending="") + self.stdout.flush() + elif action == "apply_success": + elapsed = ( + " (%.3fs)" % (time.monotonic() - self.start) if compute_time else "" + ) + if fake: + self.stdout.write(self.style.SUCCESS(" FAKED" + elapsed)) + else: + self.stdout.write(self.style.SUCCESS(" OK" + elapsed)) + elif action == "unapply_start": + if compute_time: + self.start = time.monotonic() + self.stdout.write(" Unapplying %s..." % migration, ending="") + self.stdout.flush() + elif action == "unapply_success": + elapsed = ( + " (%.3fs)" % (time.monotonic() - self.start) if compute_time else "" + ) + if fake: + self.stdout.write(self.style.SUCCESS(" FAKED" + elapsed)) + else: + self.stdout.write(self.style.SUCCESS(" OK" + elapsed)) + elif action == "render_start": + if compute_time: + self.start = time.monotonic() + self.stdout.write(" Rendering model states...", ending="") + self.stdout.flush() + elif action == "render_success": + elapsed = ( + " (%.3fs)" % (time.monotonic() - self.start) if compute_time else "" + ) + self.stdout.write(self.style.SUCCESS(" DONE" + elapsed)) + + def sync_apps(self, connection, app_labels): + """Run the old syncdb-style operation on a list of app_labels.""" + with connection.cursor() as cursor: + tables = connection.introspection.table_names(cursor) + + # Build the manifest of apps and models that are to be synchronized. + all_models = [ + ( + app_config.label, + router.get_migratable_models( + app_config, connection.alias, include_auto_created=False + ), + ) + for app_config in apps.get_app_configs() + if app_config.models_module is not None and app_config.label in app_labels + ] + + def model_installed(model): + opts = model._meta + converter = connection.introspection.identifier_converter + return not ( + (converter(opts.db_table) in tables) + or ( + opts.auto_created + and converter(opts.auto_created._meta.db_table) in tables + ) + ) + + manifest = { + app_name: list(filter(model_installed, model_list)) + for app_name, model_list in all_models + } + + # Create the tables for each model + if self.verbosity >= 1: + self.stdout.write(" Creating tables...") + with connection.schema_editor() as editor: + for app_name, model_list in manifest.items(): + for model in model_list: + # Never install unmanaged models, etc. + if not model._meta.can_migrate(connection): + continue + if self.verbosity >= 3: + self.stdout.write( + " Processing %s.%s model" + % (app_name, model._meta.object_name) + ) + if self.verbosity >= 1: + self.stdout.write( + " Creating table %s" % model._meta.db_table + ) + editor.create_model(model) + + # Deferred SQL is executed when exiting the editor's context. + if self.verbosity >= 1: + self.stdout.write(" Running deferred SQL...") + + @staticmethod + def describe_operation(operation, backwards): + """Return a string that describes a migration operation for --plan.""" + prefix = "" + is_error = False + if hasattr(operation, "code"): + code = operation.reverse_code if backwards else operation.code + action = (code.__doc__ or "") if code else None + elif hasattr(operation, "sql"): + action = operation.reverse_sql if backwards else operation.sql + else: + action = "" + if backwards: + prefix = "Undo " + if action is not None: + action = str(action).replace("\n", "") + elif backwards: + action = "IRREVERSIBLE" + is_error = True + if action: + action = " -> " + action + truncated = Truncator(action) + return prefix + operation.describe() + truncated.chars(40), is_error diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/optimizemigration.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/optimizemigration.py new file mode 100644 index 0000000..2064dfb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/optimizemigration.py @@ -0,0 +1,129 @@ +import shutil +import sys + +from django.apps import apps +from django.core.management.base import BaseCommand, CommandError +from django.core.management.utils import run_formatters +from django.db import migrations +from django.db.migrations.exceptions import AmbiguityError +from django.db.migrations.loader import MigrationLoader +from django.db.migrations.optimizer import MigrationOptimizer +from django.db.migrations.writer import MigrationWriter +from django.utils.version import get_docs_version + + +class Command(BaseCommand): + help = "Optimizes the operations for the named migration." + + def add_arguments(self, parser): + parser.add_argument( + "app_label", + help="App label of the application to optimize the migration for.", + ) + parser.add_argument( + "migration_name", help="Migration name to optimize the operations for." + ) + parser.add_argument( + "--check", + action="store_true", + help="Exit with a non-zero status if the migration can be optimized.", + ) + + def handle(self, *args, **options): + verbosity = options["verbosity"] + app_label = options["app_label"] + migration_name = options["migration_name"] + check = options["check"] + + # Validate app_label. + try: + apps.get_app_config(app_label) + except LookupError as err: + raise CommandError(str(err)) + + # Load the current graph state. + loader = MigrationLoader(None) + if app_label not in loader.migrated_apps: + raise CommandError(f"App '{app_label}' does not have migrations.") + # Find a migration. + try: + migration = loader.get_migration_by_prefix(app_label, migration_name) + except AmbiguityError: + raise CommandError( + f"More than one migration matches '{migration_name}' in app " + f"'{app_label}'. Please be more specific." + ) + except KeyError: + raise CommandError( + f"Cannot find a migration matching '{migration_name}' from app " + f"'{app_label}'." + ) + + # Optimize the migration. + optimizer = MigrationOptimizer() + new_operations = optimizer.optimize(migration.operations, migration.app_label) + if len(migration.operations) == len(new_operations): + if verbosity > 0: + self.stdout.write("No optimizations possible.") + return + else: + if verbosity > 0: + self.stdout.write( + "Optimizing from %d operations to %d operations." + % (len(migration.operations), len(new_operations)) + ) + if check: + sys.exit(1) + + # Set the new migration optimizations. + migration.operations = new_operations + + # Write out the optimized migration file. + writer = MigrationWriter(migration) + migration_file_string = writer.as_string() + if writer.needs_manual_porting: + if migration.replaces: + raise CommandError( + "Migration will require manual porting but is already a squashed " + "migration.\nTransition to a normal migration first: " + "https://docs.djangoproject.com/en/%s/topics/migrations/" + "#squashing-migrations" % get_docs_version() + ) + # Make a new migration with those operations. + subclass = type( + "Migration", + (migrations.Migration,), + { + "dependencies": migration.dependencies, + "operations": new_operations, + "replaces": [(migration.app_label, migration.name)], + }, + ) + optimized_migration_name = "%s_optimized" % migration.name + optimized_migration = subclass(optimized_migration_name, app_label) + writer = MigrationWriter(optimized_migration) + migration_file_string = writer.as_string() + if verbosity > 0: + self.stdout.write( + self.style.MIGRATE_HEADING("Manual porting required") + "\n" + " Your migrations contained functions that must be manually " + "copied over,\n" + " as we could not safely copy their implementation.\n" + " See the comment at the top of the optimized migration for " + "details." + ) + if shutil.which("black"): + self.stdout.write( + self.style.WARNING( + "Optimized migration couldn't be formatted using the " + '"black" command. You can call it manually.' + ) + ) + with open(writer.path, "w", encoding="utf-8") as fh: + fh.write(migration_file_string) + run_formatters([writer.path]) + + if verbosity > 0: + self.stdout.write( + self.style.MIGRATE_HEADING(f"Optimized migration {writer.path}") + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/runserver.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/runserver.py new file mode 100644 index 0000000..26bbf29 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/runserver.py @@ -0,0 +1,186 @@ +import errno +import os +import re +import socket +import sys +from datetime import datetime + +from django.conf import settings +from django.core.management.base import BaseCommand, CommandError +from django.core.servers.basehttp import WSGIServer, get_internal_wsgi_application, run +from django.utils import autoreload +from django.utils.regex_helper import _lazy_re_compile + +naiveip_re = _lazy_re_compile( + r"""^(?: +(?P + (?P\d{1,3}(?:\.\d{1,3}){3}) | # IPv4 address + (?P\[[a-fA-F0-9:]+\]) | # IPv6 address + (?P[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*) # FQDN +):)?(?P\d+)$""", + re.X, +) + + +class Command(BaseCommand): + help = "Starts a lightweight web server for development." + + # Validation is called explicitly each time the server is reloaded. + requires_system_checks = [] + stealth_options = ("shutdown_message",) + suppressed_base_arguments = {"--verbosity", "--traceback"} + + default_addr = "127.0.0.1" + default_addr_ipv6 = "::1" + default_port = "8000" + protocol = "http" + server_cls = WSGIServer + + def add_arguments(self, parser): + parser.add_argument( + "addrport", nargs="?", help="Optional port number, or ipaddr:port" + ) + parser.add_argument( + "--ipv6", + "-6", + action="store_true", + dest="use_ipv6", + help="Tells Django to use an IPv6 address.", + ) + parser.add_argument( + "--nothreading", + action="store_false", + dest="use_threading", + help="Tells Django to NOT use threading.", + ) + parser.add_argument( + "--noreload", + action="store_false", + dest="use_reloader", + help="Tells Django to NOT use the auto-reloader.", + ) + parser.add_argument( + "--skip-checks", + action="store_true", + help="Skip system checks.", + ) + + def execute(self, *args, **options): + if options["no_color"]: + # We rely on the environment because it's currently the only + # way to reach WSGIRequestHandler. This seems an acceptable + # compromise considering `runserver` runs indefinitely. + os.environ["DJANGO_COLORS"] = "nocolor" + super().execute(*args, **options) + + def get_handler(self, *args, **options): + """Return the default WSGI handler for the runner.""" + return get_internal_wsgi_application() + + def handle(self, *args, **options): + if not settings.DEBUG and not settings.ALLOWED_HOSTS: + raise CommandError("You must set settings.ALLOWED_HOSTS if DEBUG is False.") + + self.use_ipv6 = options["use_ipv6"] + if self.use_ipv6 and not socket.has_ipv6: + raise CommandError("Your Python does not support IPv6.") + self._raw_ipv6 = False + if not options["addrport"]: + self.addr = "" + self.port = self.default_port + else: + m = re.match(naiveip_re, options["addrport"]) + if m is None: + raise CommandError( + '"%s" is not a valid port number ' + "or address:port pair." % options["addrport"] + ) + self.addr, _ipv4, _ipv6, _fqdn, self.port = m.groups() + if not self.port.isdigit(): + raise CommandError("%r is not a valid port number." % self.port) + if self.addr: + if _ipv6: + self.addr = self.addr[1:-1] + self.use_ipv6 = True + self._raw_ipv6 = True + elif self.use_ipv6 and not _fqdn: + raise CommandError('"%s" is not a valid IPv6 address.' % self.addr) + if not self.addr: + self.addr = self.default_addr_ipv6 if self.use_ipv6 else self.default_addr + self._raw_ipv6 = self.use_ipv6 + self.run(**options) + + def run(self, **options): + """Run the server, using the autoreloader if needed.""" + use_reloader = options["use_reloader"] + + if use_reloader: + autoreload.run_with_reloader(self.inner_run, **options) + else: + self.inner_run(None, **options) + + def inner_run(self, *args, **options): + # If an exception was silenced in ManagementUtility.execute in order + # to be raised in the child process, raise it now. + autoreload.raise_last_exception() + + threading = options["use_threading"] + # 'shutdown_message' is a stealth option. + shutdown_message = options.get("shutdown_message", "") + + if not options["skip_checks"]: + self.stdout.write("Performing system checks...\n\n") + self.check(display_num_errors=True) + # Need to check migrations here, so can't use the + # requires_migrations_check attribute. + self.check_migrations() + + try: + handler = self.get_handler(*args, **options) + run( + self.addr, + int(self.port), + handler, + ipv6=self.use_ipv6, + threading=threading, + on_bind=self.on_bind, + server_cls=self.server_cls, + ) + except OSError as e: + # Use helpful error messages instead of ugly tracebacks. + ERRORS = { + errno.EACCES: "You don't have permission to access that port.", + errno.EADDRINUSE: "That port is already in use.", + errno.EADDRNOTAVAIL: "That IP address can't be assigned to.", + } + try: + error_text = ERRORS[e.errno] + except KeyError: + error_text = e + self.stderr.write("Error: %s" % error_text) + # Need to use an OS exit because sys.exit doesn't work in a thread + os._exit(1) + except KeyboardInterrupt: + if shutdown_message: + self.stdout.write(shutdown_message) + sys.exit(0) + + def on_bind(self, server_port): + quit_command = "CTRL-BREAK" if sys.platform == "win32" else "CONTROL-C" + + if self._raw_ipv6: + addr = f"[{self.addr}]" + elif self.addr == "0": + addr = "0.0.0.0" + else: + addr = self.addr + + now = datetime.now().strftime("%B %d, %Y - %X") + version = self.get_version() + print( + f"{now}\n" + f"Django version {version}, using settings {settings.SETTINGS_MODULE!r}\n" + f"Starting development server at {self.protocol}://{addr}:{server_port}/\n" + f"Quit the server with {quit_command}.", + file=self.stdout, + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/sendtestemail.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/sendtestemail.py new file mode 100644 index 0000000..fbb2a78 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/sendtestemail.py @@ -0,0 +1,46 @@ +import socket + +from django.core.mail import mail_admins, mail_managers, send_mail +from django.core.management.base import BaseCommand +from django.utils import timezone + + +class Command(BaseCommand): + help = "Sends a test email to the email addresses specified as arguments." + missing_args_message = ( + "You must specify some email recipients, or pass the --managers or --admin " + "options." + ) + + def add_arguments(self, parser): + parser.add_argument( + "email", + nargs="*", + help="One or more email addresses to send a test email to.", + ) + parser.add_argument( + "--managers", + action="store_true", + help="Send a test email to the addresses specified in settings.MANAGERS.", + ) + parser.add_argument( + "--admins", + action="store_true", + help="Send a test email to the addresses specified in settings.ADMINS.", + ) + + def handle(self, *args, **kwargs): + subject = "Test email from %s on %s" % (socket.gethostname(), timezone.now()) + + send_mail( + subject=subject, + message="If you're reading this, it was successful.", + from_email=None, + recipient_list=kwargs["email"], + ) + + if kwargs["managers"]: + mail_managers(subject, "This email was sent to the site managers.") + + if kwargs["admins"]: + mail_admins(subject, "This email was sent to the site admins.") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/shell.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/shell.py new file mode 100644 index 0000000..f55b346 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/shell.py @@ -0,0 +1,139 @@ +import os +import select +import sys +import traceback + +from django.core.management import BaseCommand, CommandError +from django.utils.datastructures import OrderedSet + + +class Command(BaseCommand): + help = ( + "Runs a Python interactive interpreter. Tries to use IPython or " + "bpython, if one of them is available. Any standard input is executed " + "as code." + ) + + requires_system_checks = [] + shells = ["ipython", "bpython", "python"] + + def add_arguments(self, parser): + parser.add_argument( + "--no-startup", + action="store_true", + help=( + "When using plain Python, ignore the PYTHONSTARTUP environment " + "variable and ~/.pythonrc.py script." + ), + ) + parser.add_argument( + "-i", + "--interface", + choices=self.shells, + help=( + "Specify an interactive interpreter interface. Available options: " + '"ipython", "bpython", and "python"' + ), + ) + parser.add_argument( + "-c", + "--command", + help=( + "Instead of opening an interactive shell, run a command as Django and " + "exit." + ), + ) + + def ipython(self, options): + from IPython import start_ipython + + start_ipython(argv=[]) + + def bpython(self, options): + import bpython + + bpython.embed() + + def python(self, options): + import code + + # Set up a dictionary to serve as the environment for the shell. + imported_objects = {} + + # We want to honor both $PYTHONSTARTUP and .pythonrc.py, so follow system + # conventions and get $PYTHONSTARTUP first then .pythonrc.py. + if not options["no_startup"]: + for pythonrc in OrderedSet( + [os.environ.get("PYTHONSTARTUP"), os.path.expanduser("~/.pythonrc.py")] + ): + if not pythonrc: + continue + if not os.path.isfile(pythonrc): + continue + with open(pythonrc) as handle: + pythonrc_code = handle.read() + # Match the behavior of the cpython shell where an error in + # PYTHONSTARTUP prints an exception and continues. + try: + exec(compile(pythonrc_code, pythonrc, "exec"), imported_objects) + except Exception: + traceback.print_exc() + + # By default, this will set up readline to do tab completion and to read and + # write history to the .python_history file, but this can be overridden by + # $PYTHONSTARTUP or ~/.pythonrc.py. + try: + hook = sys.__interactivehook__ + except AttributeError: + # Match the behavior of the cpython shell where a missing + # sys.__interactivehook__ is ignored. + pass + else: + try: + hook() + except Exception: + # Match the behavior of the cpython shell where an error in + # sys.__interactivehook__ prints a warning and the exception + # and continues. + print("Failed calling sys.__interactivehook__") + traceback.print_exc() + + # Set up tab completion for objects imported by $PYTHONSTARTUP or + # ~/.pythonrc.py. + try: + import readline + import rlcompleter + + readline.set_completer(rlcompleter.Completer(imported_objects).complete) + except ImportError: + pass + + # Start the interactive interpreter. + code.interact(local=imported_objects) + + def handle(self, **options): + # Execute the command and exit. + if options["command"]: + exec(options["command"], globals()) + return + + # Execute stdin if it has anything to read and exit. + # Not supported on Windows due to select.select() limitations. + if ( + sys.platform != "win32" + and not sys.stdin.isatty() + and select.select([sys.stdin], [], [], 0)[0] + ): + exec(sys.stdin.read(), globals()) + return + + available_shells = ( + [options["interface"]] if options["interface"] else self.shells + ) + + for shell in available_shells: + try: + return getattr(self, shell)(options) + except ImportError: + pass + raise CommandError("Couldn't import {} interface.".format(shell)) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/showmigrations.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/showmigrations.py new file mode 100644 index 0000000..203f921 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/showmigrations.py @@ -0,0 +1,176 @@ +import sys + +from django.apps import apps +from django.core.management.base import BaseCommand +from django.db import DEFAULT_DB_ALIAS, connections +from django.db.migrations.loader import MigrationLoader +from django.db.migrations.recorder import MigrationRecorder + + +class Command(BaseCommand): + help = "Shows all available migrations for the current project" + + def add_arguments(self, parser): + parser.add_argument( + "app_label", + nargs="*", + help="App labels of applications to limit the output to.", + ) + parser.add_argument( + "--database", + default=DEFAULT_DB_ALIAS, + help=( + "Nominates a database to show migrations for. Defaults to the " + '"default" database.' + ), + ) + + formats = parser.add_mutually_exclusive_group() + formats.add_argument( + "--list", + "-l", + action="store_const", + dest="format", + const="list", + help=( + "Shows a list of all migrations and which are applied. " + "With a verbosity level of 2 or above, the applied datetimes " + "will be included." + ), + ) + formats.add_argument( + "--plan", + "-p", + action="store_const", + dest="format", + const="plan", + help=( + "Shows all migrations in the order they will be applied. With a " + "verbosity level of 2 or above all direct migration dependencies and " + "reverse dependencies (run_before) will be included." + ), + ) + + parser.set_defaults(format="list") + + def handle(self, *args, **options): + self.verbosity = options["verbosity"] + + # Get the database we're operating from + db = options["database"] + connection = connections[db] + + if options["format"] == "plan": + return self.show_plan(connection, options["app_label"]) + else: + return self.show_list(connection, options["app_label"]) + + def _validate_app_names(self, loader, app_names): + has_bad_names = False + for app_name in app_names: + try: + apps.get_app_config(app_name) + except LookupError as err: + self.stderr.write(str(err)) + has_bad_names = True + if has_bad_names: + sys.exit(2) + + def show_list(self, connection, app_names=None): + """ + Show a list of all migrations on the system, or only those of + some named apps. + """ + # Load migrations from disk/DB + loader = MigrationLoader(connection, ignore_no_migrations=True) + recorder = MigrationRecorder(connection) + recorded_migrations = recorder.applied_migrations() + graph = loader.graph + # If we were passed a list of apps, validate it + if app_names: + self._validate_app_names(loader, app_names) + # Otherwise, show all apps in alphabetic order + else: + app_names = sorted(loader.migrated_apps) + # For each app, print its migrations in order from oldest (roots) to + # newest (leaves). + for app_name in app_names: + self.stdout.write(app_name, self.style.MIGRATE_LABEL) + shown = set() + for node in graph.leaf_nodes(app_name): + for plan_node in graph.forwards_plan(node): + if plan_node not in shown and plan_node[0] == app_name: + # Give it a nice title if it's a squashed one + title = plan_node[1] + if graph.nodes[plan_node].replaces: + title += " (%s squashed migrations)" % len( + graph.nodes[plan_node].replaces + ) + applied_migration = loader.applied_migrations.get(plan_node) + # Mark it as applied/unapplied + if applied_migration: + if plan_node in recorded_migrations: + output = " [X] %s" % title + else: + title += " Run 'manage.py migrate' to finish recording." + output = " [-] %s" % title + if self.verbosity >= 2 and hasattr( + applied_migration, "applied" + ): + output += ( + " (applied at %s)" + % applied_migration.applied.strftime( + "%Y-%m-%d %H:%M:%S" + ) + ) + self.stdout.write(output) + else: + self.stdout.write(" [ ] %s" % title) + shown.add(plan_node) + # If we didn't print anything, then a small message + if not shown: + self.stdout.write(" (no migrations)", self.style.ERROR) + + def show_plan(self, connection, app_names=None): + """ + Show all known migrations (or only those of the specified app_names) + in the order they will be applied. + """ + # Load migrations from disk/DB + loader = MigrationLoader(connection) + graph = loader.graph + if app_names: + self._validate_app_names(loader, app_names) + targets = [key for key in graph.leaf_nodes() if key[0] in app_names] + else: + targets = graph.leaf_nodes() + plan = [] + seen = set() + + # Generate the plan + for target in targets: + for migration in graph.forwards_plan(target): + if migration not in seen: + node = graph.node_map[migration] + plan.append(node) + seen.add(migration) + + # Output + def print_deps(node): + out = [] + for parent in sorted(node.parents): + out.append("%s.%s" % parent.key) + if out: + return " ... (%s)" % ", ".join(out) + return "" + + for node in plan: + deps = "" + if self.verbosity >= 2: + deps = print_deps(node) + if node.key in loader.applied_migrations: + self.stdout.write("[X] %s.%s%s" % (node.key[0], node.key[1], deps)) + else: + self.stdout.write("[ ] %s.%s%s" % (node.key[0], node.key[1], deps)) + if not plan: + self.stdout.write("(no migrations)", self.style.ERROR) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/sqlflush.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/sqlflush.py new file mode 100644 index 0000000..bc82e1f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/sqlflush.py @@ -0,0 +1,29 @@ +from django.core.management.base import BaseCommand +from django.core.management.sql import sql_flush +from django.db import DEFAULT_DB_ALIAS, connections + + +class Command(BaseCommand): + help = ( + "Returns a list of the SQL statements required to return all tables in " + "the database to the state they were in just after they were installed." + ) + + output_transaction = True + + def add_arguments(self, parser): + super().add_arguments(parser) + parser.add_argument( + "--database", + default=DEFAULT_DB_ALIAS, + help=( + 'Nominates a database to print the SQL for. Defaults to the "default" ' + "database." + ), + ) + + def handle(self, **options): + sql_statements = sql_flush(self.style, connections[options["database"]]) + if not sql_statements and options["verbosity"] >= 1: + self.stderr.write("No tables found.") + return "\n".join(sql_statements) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/sqlmigrate.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/sqlmigrate.py new file mode 100644 index 0000000..2f69936 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/sqlmigrate.py @@ -0,0 +1,83 @@ +from django.apps import apps +from django.core.management.base import BaseCommand, CommandError +from django.db import DEFAULT_DB_ALIAS, connections +from django.db.migrations.loader import AmbiguityError, MigrationLoader + + +class Command(BaseCommand): + help = "Prints the SQL statements for the named migration." + + output_transaction = True + + def add_arguments(self, parser): + parser.add_argument( + "app_label", help="App label of the application containing the migration." + ) + parser.add_argument( + "migration_name", help="Migration name to print the SQL for." + ) + parser.add_argument( + "--database", + default=DEFAULT_DB_ALIAS, + help=( + 'Nominates a database to create SQL for. Defaults to the "default" ' + "database." + ), + ) + parser.add_argument( + "--backwards", + action="store_true", + help="Creates SQL to unapply the migration, rather than to apply it", + ) + + def execute(self, *args, **options): + # sqlmigrate doesn't support coloring its output but we need to force + # no_color=True so that the BEGIN/COMMIT statements added by + # output_transaction don't get colored either. + options["no_color"] = True + return super().execute(*args, **options) + + def handle(self, *args, **options): + # Get the database we're operating from + connection = connections[options["database"]] + + # Load up a loader to get all the migration data, but don't replace + # migrations. + loader = MigrationLoader(connection, replace_migrations=False) + + # Resolve command-line arguments into a migration + app_label, migration_name = options["app_label"], options["migration_name"] + # Validate app_label + try: + apps.get_app_config(app_label) + except LookupError as err: + raise CommandError(str(err)) + if app_label not in loader.migrated_apps: + raise CommandError("App '%s' does not have migrations" % app_label) + try: + migration = loader.get_migration_by_prefix(app_label, migration_name) + except AmbiguityError: + raise CommandError( + "More than one migration matches '%s' in app '%s'. Please be more " + "specific." % (migration_name, app_label) + ) + except KeyError: + raise CommandError( + "Cannot find a migration matching '%s' from app '%s'. Is it in " + "INSTALLED_APPS?" % (migration_name, app_label) + ) + target = (app_label, migration.name) + + # Show begin/end around output for atomic migrations, if the database + # supports transactional DDL. + self.output_transaction = ( + migration.atomic and connection.features.can_rollback_ddl + ) + + # Make a plan that represents just the requested migrations and show SQL + # for it + plan = [(loader.graph.nodes[target], options["backwards"])] + sql_statements = loader.collect_sql(plan) + if not sql_statements and options["verbosity"] >= 1: + self.stderr.write("No operations found.") + return "\n".join(sql_statements) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/sqlsequencereset.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/sqlsequencereset.py new file mode 100644 index 0000000..9653fa5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/sqlsequencereset.py @@ -0,0 +1,31 @@ +from django.core.management.base import AppCommand +from django.db import DEFAULT_DB_ALIAS, connections + + +class Command(AppCommand): + help = ( + "Prints the SQL statements for resetting sequences for the given app name(s)." + ) + + output_transaction = True + + def add_arguments(self, parser): + super().add_arguments(parser) + parser.add_argument( + "--database", + default=DEFAULT_DB_ALIAS, + help=( + 'Nominates a database to print the SQL for. Defaults to the "default" ' + "database." + ), + ) + + def handle_app_config(self, app_config, **options): + if app_config.models_module is None: + return + connection = connections[options["database"]] + models = app_config.get_models(include_auto_created=True) + statements = connection.ops.sequence_reset_sql(self.style, models) + if not statements and options["verbosity"] >= 1: + self.stderr.write("No sequences found.") + return "\n".join(statements) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/squashmigrations.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/squashmigrations.py new file mode 100644 index 0000000..6571cbc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/squashmigrations.py @@ -0,0 +1,267 @@ +import os +import shutil + +from django.apps import apps +from django.conf import settings +from django.core.management.base import BaseCommand, CommandError +from django.core.management.utils import run_formatters +from django.db import DEFAULT_DB_ALIAS, connections, migrations +from django.db.migrations.loader import AmbiguityError, MigrationLoader +from django.db.migrations.migration import SwappableTuple +from django.db.migrations.optimizer import MigrationOptimizer +from django.db.migrations.writer import MigrationWriter +from django.utils.version import get_docs_version + + +class Command(BaseCommand): + help = ( + "Squashes an existing set of migrations (from first until specified) into a " + "single new one." + ) + + def add_arguments(self, parser): + parser.add_argument( + "app_label", + help="App label of the application to squash migrations for.", + ) + parser.add_argument( + "start_migration_name", + nargs="?", + help=( + "Migrations will be squashed starting from and including this " + "migration." + ), + ) + parser.add_argument( + "migration_name", + help="Migrations will be squashed until and including this migration.", + ) + parser.add_argument( + "--no-optimize", + action="store_true", + help="Do not try to optimize the squashed operations.", + ) + parser.add_argument( + "--noinput", + "--no-input", + action="store_false", + dest="interactive", + help="Tells Django to NOT prompt the user for input of any kind.", + ) + parser.add_argument( + "--squashed-name", + help="Sets the name of the new squashed migration.", + ) + parser.add_argument( + "--no-header", + action="store_false", + dest="include_header", + help="Do not add a header comment to the new squashed migration.", + ) + + def handle(self, **options): + self.verbosity = options["verbosity"] + self.interactive = options["interactive"] + app_label = options["app_label"] + start_migration_name = options["start_migration_name"] + migration_name = options["migration_name"] + no_optimize = options["no_optimize"] + squashed_name = options["squashed_name"] + include_header = options["include_header"] + # Validate app_label. + try: + apps.get_app_config(app_label) + except LookupError as err: + raise CommandError(str(err)) + # Load the current graph state, check the app and migration they asked + # for exists. + loader = MigrationLoader(connections[DEFAULT_DB_ALIAS]) + if app_label not in loader.migrated_apps: + raise CommandError( + "App '%s' does not have migrations (so squashmigrations on " + "it makes no sense)" % app_label + ) + + migration = self.find_migration(loader, app_label, migration_name) + + # Work out the list of predecessor migrations + migrations_to_squash = [ + loader.get_migration(al, mn) + for al, mn in loader.graph.forwards_plan( + (migration.app_label, migration.name) + ) + if al == migration.app_label + ] + + if start_migration_name: + start_migration = self.find_migration( + loader, app_label, start_migration_name + ) + start = loader.get_migration( + start_migration.app_label, start_migration.name + ) + try: + start_index = migrations_to_squash.index(start) + migrations_to_squash = migrations_to_squash[start_index:] + except ValueError: + raise CommandError( + "The migration '%s' cannot be found. Maybe it comes after " + "the migration '%s'?\n" + "Have a look at:\n" + " python manage.py showmigrations %s\n" + "to debug this issue." % (start_migration, migration, app_label) + ) + + # Tell them what we're doing and optionally ask if we should proceed + if self.verbosity > 0 or self.interactive: + self.stdout.write( + self.style.MIGRATE_HEADING("Will squash the following migrations:") + ) + for migration in migrations_to_squash: + self.stdout.write(" - %s" % migration.name) + + if self.interactive: + answer = None + while not answer or answer not in "yn": + answer = input("Do you wish to proceed? [yN] ") + if not answer: + answer = "n" + break + else: + answer = answer[0].lower() + if answer != "y": + return + + # Load the operations from all those migrations and concat together, + # along with collecting external dependencies and detecting + # double-squashing + operations = [] + dependencies = set() + # We need to take all dependencies from the first migration in the list + # as it may be 0002 depending on 0001 + first_migration = True + for smigration in migrations_to_squash: + if smigration.replaces: + raise CommandError( + "You cannot squash squashed migrations! Please transition it to a " + "normal migration first: https://docs.djangoproject.com/en/%s/" + "topics/migrations/#squashing-migrations" % get_docs_version() + ) + operations.extend(smigration.operations) + for dependency in smigration.dependencies: + if isinstance(dependency, SwappableTuple): + if settings.AUTH_USER_MODEL == dependency.setting: + dependencies.add(("__setting__", "AUTH_USER_MODEL")) + else: + dependencies.add(dependency) + elif dependency[0] != smigration.app_label or first_migration: + dependencies.add(dependency) + first_migration = False + + if no_optimize: + if self.verbosity > 0: + self.stdout.write( + self.style.MIGRATE_HEADING("(Skipping optimization.)") + ) + new_operations = operations + else: + if self.verbosity > 0: + self.stdout.write(self.style.MIGRATE_HEADING("Optimizing...")) + + optimizer = MigrationOptimizer() + new_operations = optimizer.optimize(operations, migration.app_label) + + if self.verbosity > 0: + if len(new_operations) == len(operations): + self.stdout.write(" No optimizations possible.") + else: + self.stdout.write( + " Optimized from %s operations to %s operations." + % (len(operations), len(new_operations)) + ) + + # Work out the value of replaces (any squashed ones we're re-squashing) + # need to feed their replaces into ours + replaces = [] + for migration in migrations_to_squash: + if migration.replaces: + replaces.extend(migration.replaces) + else: + replaces.append((migration.app_label, migration.name)) + + # Make a new migration with those operations + subclass = type( + "Migration", + (migrations.Migration,), + { + "dependencies": dependencies, + "operations": new_operations, + "replaces": replaces, + }, + ) + if start_migration_name: + if squashed_name: + # Use the name from --squashed-name. + prefix, _ = start_migration.name.split("_", 1) + name = "%s_%s" % (prefix, squashed_name) + else: + # Generate a name. + name = "%s_squashed_%s" % (start_migration.name, migration.name) + new_migration = subclass(name, app_label) + else: + name = "0001_%s" % (squashed_name or "squashed_%s" % migration.name) + new_migration = subclass(name, app_label) + new_migration.initial = True + + # Write out the new migration file + writer = MigrationWriter(new_migration, include_header) + if os.path.exists(writer.path): + raise CommandError( + f"Migration {new_migration.name} already exists. Use a different name." + ) + with open(writer.path, "w", encoding="utf-8") as fh: + fh.write(writer.as_string()) + run_formatters([writer.path]) + + if self.verbosity > 0: + self.stdout.write( + self.style.MIGRATE_HEADING( + "Created new squashed migration %s" % writer.path + ) + + "\n" + " You should commit this migration but leave the old ones in place;\n" + " the new migration will be used for new installs. Once you are sure\n" + " all instances of the codebase have applied the migrations you " + "squashed,\n" + " you can delete them." + ) + if writer.needs_manual_porting: + self.stdout.write( + self.style.MIGRATE_HEADING("Manual porting required") + "\n" + " Your migrations contained functions that must be manually " + "copied over,\n" + " as we could not safely copy their implementation.\n" + " See the comment at the top of the squashed migration for " + "details." + ) + if shutil.which("black"): + self.stdout.write( + self.style.WARNING( + "Squashed migration couldn't be formatted using the " + '"black" command. You can call it manually.' + ) + ) + + def find_migration(self, loader, app_label, name): + try: + return loader.get_migration_by_prefix(app_label, name) + except AmbiguityError: + raise CommandError( + "More than one migration matches '%s' in app '%s'. Please be " + "more specific." % (name, app_label) + ) + except KeyError: + raise CommandError( + "Cannot find a migration matching '%s' from app '%s'." + % (name, app_label) + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/startapp.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/startapp.py new file mode 100644 index 0000000..e85833b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/startapp.py @@ -0,0 +1,14 @@ +from django.core.management.templates import TemplateCommand + + +class Command(TemplateCommand): + help = ( + "Creates a Django app directory structure for the given app name in " + "the current directory or optionally in the given directory." + ) + missing_args_message = "You must provide an application name." + + def handle(self, **options): + app_name = options.pop("name") + target = options.pop("directory") + super().handle("app", app_name, target, **options) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/startproject.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/startproject.py new file mode 100644 index 0000000..ca17fa5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/startproject.py @@ -0,0 +1,21 @@ +from django.core.checks.security.base import SECRET_KEY_INSECURE_PREFIX +from django.core.management.templates import TemplateCommand + +from ..utils import get_random_secret_key + + +class Command(TemplateCommand): + help = ( + "Creates a Django project directory structure for the given project " + "name in the current directory or optionally in the given directory." + ) + missing_args_message = "You must provide a project name." + + def handle(self, **options): + project_name = options.pop("name") + target = options.pop("directory") + + # Create a random SECRET_KEY to put it in the main settings. + options["secret_key"] = SECRET_KEY_INSECURE_PREFIX + get_random_secret_key() + + super().handle("project", project_name, target, **options) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/test.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/test.py new file mode 100644 index 0000000..2df6dbb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/test.py @@ -0,0 +1,71 @@ +import sys + +from django.conf import settings +from django.core.management.base import BaseCommand +from django.core.management.utils import get_command_line_option +from django.test.runner import get_max_test_processes +from django.test.utils import NullTimeKeeper, TimeKeeper, get_runner + + +class Command(BaseCommand): + help = "Discover and run tests in the specified modules or the current directory." + + # DiscoverRunner runs the checks after databases are set up. + requires_system_checks = [] + test_runner = None + + def run_from_argv(self, argv): + """ + Pre-parse the command line to extract the value of the --testrunner + option. This allows a test runner to define additional command line + arguments. + """ + self.test_runner = get_command_line_option(argv, "--testrunner") + super().run_from_argv(argv) + + def add_arguments(self, parser): + parser.add_argument( + "args", + metavar="test_label", + nargs="*", + help=( + "Module paths to test; can be modulename, modulename.TestCase or " + "modulename.TestCase.test_method" + ), + ) + parser.add_argument( + "--noinput", + "--no-input", + action="store_false", + dest="interactive", + help="Tells Django to NOT prompt the user for input of any kind.", + ) + parser.add_argument( + "--failfast", + action="store_true", + help="Tells Django to stop running the test suite after first failed test.", + ) + parser.add_argument( + "--testrunner", + help="Tells Django to use specified test runner class instead of " + "the one specified by the TEST_RUNNER setting.", + ) + + test_runner_class = get_runner(settings, self.test_runner) + + if hasattr(test_runner_class, "add_arguments"): + test_runner_class.add_arguments(parser) + + def handle(self, *test_labels, **options): + TestRunner = get_runner(settings, options["testrunner"]) + + time_keeper = TimeKeeper() if options.get("timing", False) else NullTimeKeeper() + parallel = options.get("parallel") + if parallel == "auto": + options["parallel"] = get_max_test_processes() + test_runner = TestRunner(**options) + with time_keeper.timed("Total run"): + failures = test_runner.run_tests(test_labels) + time_keeper.print_results() + if failures: + sys.exit(1) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/testserver.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/testserver.py new file mode 100644 index 0000000..a8a0376 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/commands/testserver.py @@ -0,0 +1,65 @@ +from django.core.management import call_command +from django.core.management.base import BaseCommand +from django.db import connection + + +class Command(BaseCommand): + help = "Runs a development server with data from the given fixture(s)." + + requires_system_checks = [] + + def add_arguments(self, parser): + parser.add_argument( + "args", + metavar="fixture", + nargs="*", + help="Path(s) to fixtures to load before running the server.", + ) + parser.add_argument( + "--noinput", + "--no-input", + action="store_false", + dest="interactive", + help="Tells Django to NOT prompt the user for input of any kind.", + ) + parser.add_argument( + "--addrport", + default="", + help="Port number or ipaddr:port to run the server on.", + ) + parser.add_argument( + "--ipv6", + "-6", + action="store_true", + dest="use_ipv6", + help="Tells Django to use an IPv6 address.", + ) + + def handle(self, *fixture_labels, **options): + verbosity = options["verbosity"] + interactive = options["interactive"] + + # Create a test database. + db_name = connection.creation.create_test_db( + verbosity=verbosity, autoclobber=not interactive, serialize=False + ) + + # Import the fixture data into the test database. + call_command("loaddata", *fixture_labels, verbosity=verbosity) + + # Run the development server. Turn off auto-reloading because it causes + # a strange error -- it causes this handle() method to be called + # multiple times. + shutdown_message = ( + "\nServer stopped.\nNote that the test database, %r, has not been " + "deleted. You can explore it on your own." % db_name + ) + use_threading = connection.features.test_db_allows_multiple_connections + call_command( + "runserver", + addrport=options["addrport"], + shutdown_message=shutdown_message, + use_reloader=False, + use_ipv6=options["use_ipv6"], + use_threading=use_threading, + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/sql.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/sql.py new file mode 100644 index 0000000..2375cc2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/sql.py @@ -0,0 +1,59 @@ +import sys + +from django.apps import apps +from django.db import models + + +def sql_flush(style, connection, reset_sequences=True, allow_cascade=False): + """ + Return a list of the SQL statements used to flush the database. + """ + tables = connection.introspection.django_table_names( + only_existing=True, include_views=False + ) + return connection.ops.sql_flush( + style, + tables, + reset_sequences=reset_sequences, + allow_cascade=allow_cascade, + ) + + +def emit_pre_migrate_signal(verbosity, interactive, db, **kwargs): + # Emit the pre_migrate signal for every application. + for app_config in apps.get_app_configs(): + if app_config.models_module is None: + continue + if verbosity >= 2: + stdout = kwargs.get("stdout", sys.stdout) + stdout.write( + "Running pre-migrate handlers for application %s" % app_config.label + ) + models.signals.pre_migrate.send( + sender=app_config, + app_config=app_config, + verbosity=verbosity, + interactive=interactive, + using=db, + **kwargs, + ) + + +def emit_post_migrate_signal(verbosity, interactive, db, **kwargs): + # Emit the post_migrate signal for every application. + for app_config in apps.get_app_configs(): + if app_config.models_module is None: + continue + if verbosity >= 2: + stdout = kwargs.get("stdout", sys.stdout) + stdout.write( + "Running post-migrate handlers for application %s" % app_config.label + ) + models.signals.post_migrate.send( + sender=app_config, + app_config=app_config, + verbosity=verbosity, + interactive=interactive, + using=db, + **kwargs, + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/templates.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/templates.py new file mode 100644 index 0000000..633eed7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/templates.py @@ -0,0 +1,402 @@ +import argparse +import mimetypes +import os +import posixpath +import shutil +import stat +import tempfile +from importlib.util import find_spec +from urllib.request import build_opener + +import django +from django.conf import settings +from django.core.management.base import BaseCommand, CommandError +from django.core.management.utils import ( + find_formatters, + handle_extensions, + run_formatters, +) +from django.template import Context, Engine +from django.utils import archive +from django.utils.http import parse_header_parameters +from django.utils.version import get_docs_version + + +class TemplateCommand(BaseCommand): + """ + Copy either a Django application layout template or a Django project + layout template into the specified directory. + + :param style: A color style object (see django.core.management.color). + :param app_or_project: The string 'app' or 'project'. + :param name: The name of the application or project. + :param directory: The directory to which the template should be copied. + :param options: The additional variables passed to project or app templates + """ + + requires_system_checks = [] + # The supported URL schemes + url_schemes = ["http", "https", "ftp"] + # Rewrite the following suffixes when determining the target filename. + rewrite_template_suffixes = ( + # Allow shipping invalid .py files without byte-compilation. + (".py-tpl", ".py"), + ) + + def add_arguments(self, parser): + parser.add_argument("name", help="Name of the application or project.") + parser.add_argument( + "directory", nargs="?", help="Optional destination directory" + ) + parser.add_argument( + "--template", help="The path or URL to load the template from." + ) + parser.add_argument( + "--extension", + "-e", + dest="extensions", + action="append", + default=["py"], + help='The file extension(s) to render (default: "py"). ' + "Separate multiple extensions with commas, or use " + "-e multiple times.", + ) + parser.add_argument( + "--name", + "-n", + dest="files", + action="append", + default=[], + help="The file name(s) to render. Separate multiple file names " + "with commas, or use -n multiple times.", + ) + parser.add_argument( + "--exclude", + "-x", + action="append", + default=argparse.SUPPRESS, + nargs="?", + const="", + help=( + "The directory name(s) to exclude, in addition to .git and " + "__pycache__. Can be used multiple times." + ), + ) + + def handle(self, app_or_project, name, target=None, **options): + self.app_or_project = app_or_project + self.a_or_an = "an" if app_or_project == "app" else "a" + self.paths_to_remove = [] + self.verbosity = options["verbosity"] + + self.validate_name(name) + + # if some directory is given, make sure it's nicely expanded + if target is None: + top_dir = os.path.join(os.getcwd(), name) + try: + os.makedirs(top_dir) + except FileExistsError: + raise CommandError("'%s' already exists" % top_dir) + except OSError as e: + raise CommandError(e) + else: + top_dir = os.path.abspath(os.path.expanduser(target)) + if app_or_project == "app": + self.validate_name(os.path.basename(top_dir), "directory") + if not os.path.exists(top_dir): + raise CommandError( + "Destination directory '%s' does not " + "exist, please create it first." % top_dir + ) + + # Find formatters, which are external executables, before input + # from the templates can sneak into the path. + formatter_paths = find_formatters() + + extensions = tuple(handle_extensions(options["extensions"])) + extra_files = [] + excluded_directories = [".git", "__pycache__"] + for file in options["files"]: + extra_files.extend(map(lambda x: x.strip(), file.split(","))) + if exclude := options.get("exclude"): + for directory in exclude: + excluded_directories.append(directory.strip()) + if self.verbosity >= 2: + self.stdout.write( + "Rendering %s template files with extensions: %s" + % (app_or_project, ", ".join(extensions)) + ) + self.stdout.write( + "Rendering %s template files with filenames: %s" + % (app_or_project, ", ".join(extra_files)) + ) + base_name = "%s_name" % app_or_project + base_subdir = "%s_template" % app_or_project + base_directory = "%s_directory" % app_or_project + camel_case_name = "camel_case_%s_name" % app_or_project + camel_case_value = "".join(x for x in name.title() if x != "_") + + context = Context( + { + **options, + base_name: name, + base_directory: top_dir, + camel_case_name: camel_case_value, + "docs_version": get_docs_version(), + "django_version": django.__version__, + }, + autoescape=False, + ) + + # Setup a stub settings environment for template rendering + if not settings.configured: + settings.configure() + django.setup() + + template_dir = self.handle_template(options["template"], base_subdir) + prefix_length = len(template_dir) + 1 + + for root, dirs, files in os.walk(template_dir): + path_rest = root[prefix_length:] + relative_dir = path_rest.replace(base_name, name) + if relative_dir: + target_dir = os.path.join(top_dir, relative_dir) + os.makedirs(target_dir, exist_ok=True) + + for dirname in dirs[:]: + if "exclude" not in options: + if dirname.startswith(".") or dirname == "__pycache__": + dirs.remove(dirname) + elif dirname in excluded_directories: + dirs.remove(dirname) + + for filename in files: + if filename.endswith((".pyo", ".pyc", ".py.class")): + # Ignore some files as they cause various breakages. + continue + old_path = os.path.join(root, filename) + new_path = os.path.join( + top_dir, relative_dir, filename.replace(base_name, name) + ) + for old_suffix, new_suffix in self.rewrite_template_suffixes: + if new_path.endswith(old_suffix): + new_path = new_path.removesuffix(old_suffix) + new_suffix + break # Only rewrite once + + if os.path.exists(new_path): + raise CommandError( + "%s already exists. Overlaying %s %s into an existing " + "directory won't replace conflicting files." + % ( + new_path, + self.a_or_an, + app_or_project, + ) + ) + + # Only render the Python files, as we don't want to + # accidentally render Django templates files + if new_path.endswith(extensions) or filename in extra_files: + with open(old_path, encoding="utf-8") as template_file: + content = template_file.read() + template = Engine().from_string(content) + content = template.render(context) + with open(new_path, "w", encoding="utf-8") as new_file: + new_file.write(content) + else: + shutil.copyfile(old_path, new_path) + + if self.verbosity >= 2: + self.stdout.write("Creating %s" % new_path) + try: + self.apply_umask(old_path, new_path) + self.make_writeable(new_path) + except OSError: + self.stderr.write( + "Notice: Couldn't set permission bits on %s. You're " + "probably using an uncommon filesystem setup. No " + "problem." % new_path, + self.style.NOTICE, + ) + + if self.paths_to_remove: + if self.verbosity >= 2: + self.stdout.write("Cleaning up temporary files.") + for path_to_remove in self.paths_to_remove: + if os.path.isfile(path_to_remove): + os.remove(path_to_remove) + else: + shutil.rmtree(path_to_remove) + + run_formatters([top_dir], **formatter_paths) + + def handle_template(self, template, subdir): + """ + Determine where the app or project templates are. + Use django.__path__[0] as the default because the Django install + directory isn't known. + """ + if template is None: + return os.path.join(django.__path__[0], "conf", subdir) + else: + template = template.removeprefix("file://") + expanded_template = os.path.expanduser(template) + expanded_template = os.path.normpath(expanded_template) + if os.path.isdir(expanded_template): + return expanded_template + if self.is_url(template): + # downloads the file and returns the path + absolute_path = self.download(template) + else: + absolute_path = os.path.abspath(expanded_template) + if os.path.exists(absolute_path): + return self.extract(absolute_path) + + raise CommandError( + "couldn't handle %s template %s." % (self.app_or_project, template) + ) + + def validate_name(self, name, name_or_dir="name"): + if name is None: + raise CommandError( + "you must provide {an} {app} name".format( + an=self.a_or_an, + app=self.app_or_project, + ) + ) + # Check it's a valid directory name. + if not name.isidentifier(): + raise CommandError( + "'{name}' is not a valid {app} {type}. Please make sure the " + "{type} is a valid identifier.".format( + name=name, + app=self.app_or_project, + type=name_or_dir, + ) + ) + # Check that __spec__ doesn't exist. + if find_spec(name) is not None: + raise CommandError( + "'{name}' conflicts with the name of an existing Python " + "module and cannot be used as {an} {app} {type}. Please try " + "another {type}.".format( + name=name, + an=self.a_or_an, + app=self.app_or_project, + type=name_or_dir, + ) + ) + + def download(self, url): + """ + Download the given URL and return the file name. + """ + + def cleanup_url(url): + tmp = url.rstrip("/") + filename = tmp.split("/")[-1] + if url.endswith("/"): + display_url = tmp + "/" + else: + display_url = url + return filename, display_url + + prefix = "django_%s_template_" % self.app_or_project + tempdir = tempfile.mkdtemp(prefix=prefix, suffix="_download") + self.paths_to_remove.append(tempdir) + filename, display_url = cleanup_url(url) + + if self.verbosity >= 2: + self.stdout.write("Downloading %s" % display_url) + + the_path = os.path.join(tempdir, filename) + opener = build_opener() + opener.addheaders = [("User-Agent", f"Django/{django.__version__}")] + try: + with opener.open(url) as source, open(the_path, "wb") as target: + headers = source.info() + target.write(source.read()) + except OSError as e: + raise CommandError( + "couldn't download URL %s to %s: %s" % (url, filename, e) + ) + + used_name = the_path.split("/")[-1] + + # Trying to get better name from response headers + content_disposition = headers["content-disposition"] + if content_disposition: + _, params = parse_header_parameters(content_disposition) + guessed_filename = params.get("filename") or used_name + else: + guessed_filename = used_name + + # Falling back to content type guessing + ext = self.splitext(guessed_filename)[1] + content_type = headers["content-type"] + if not ext and content_type: + ext = mimetypes.guess_extension(content_type) + if ext: + guessed_filename += ext + + # Move the temporary file to a filename that has better + # chances of being recognized by the archive utils + if used_name != guessed_filename: + guessed_path = os.path.join(tempdir, guessed_filename) + shutil.move(the_path, guessed_path) + return guessed_path + + # Giving up + return the_path + + def splitext(self, the_path): + """ + Like os.path.splitext, but takes off .tar, too + """ + base, ext = posixpath.splitext(the_path) + if base.lower().endswith(".tar"): + ext = base[-4:] + ext + base = base[:-4] + return base, ext + + def extract(self, filename): + """ + Extract the given file to a temporary directory and return + the path of the directory with the extracted content. + """ + prefix = "django_%s_template_" % self.app_or_project + tempdir = tempfile.mkdtemp(prefix=prefix, suffix="_extract") + self.paths_to_remove.append(tempdir) + if self.verbosity >= 2: + self.stdout.write("Extracting %s" % filename) + try: + archive.extract(filename, tempdir) + return tempdir + except (archive.ArchiveException, OSError) as e: + raise CommandError( + "couldn't extract file %s to %s: %s" % (filename, tempdir, e) + ) + + def is_url(self, template): + """Return True if the name looks like a URL.""" + if ":" not in template: + return False + scheme = template.split(":", 1)[0].lower() + return scheme in self.url_schemes + + def apply_umask(self, old_path, new_path): + current_umask = os.umask(0) + os.umask(current_umask) + current_mode = stat.S_IMODE(os.stat(old_path).st_mode) + os.chmod(new_path, current_mode & ~current_umask) + + def make_writeable(self, filename): + """ + Make sure that the file is writeable. + Useful if our source is read-only. + """ + if not os.access(filename, os.W_OK): + st = os.stat(filename) + new_permissions = stat.S_IMODE(st.st_mode) | stat.S_IWUSR + os.chmod(filename, new_permissions) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/utils.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/utils.py new file mode 100644 index 0000000..fca61f2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/management/utils.py @@ -0,0 +1,175 @@ +import fnmatch +import os +import shutil +import subprocess +from pathlib import Path +from subprocess import run + +from django.apps import apps as installed_apps +from django.utils.crypto import get_random_string +from django.utils.encoding import DEFAULT_LOCALE_ENCODING + +from .base import CommandError, CommandParser + + +def popen_wrapper(args, stdout_encoding="utf-8"): + """ + Friendly wrapper around Popen. + + Return stdout output, stderr output, and OS status code. + """ + try: + p = run(args, capture_output=True, close_fds=os.name != "nt") + except OSError as err: + raise CommandError("Error executing %s" % args[0]) from err + return ( + p.stdout.decode(stdout_encoding), + p.stderr.decode(DEFAULT_LOCALE_ENCODING, errors="replace"), + p.returncode, + ) + + +def handle_extensions(extensions): + """ + Organize multiple extensions that are separated with commas or passed by + using --extension/-e multiple times. + + For example: running 'django-admin makemessages -e js,txt -e xhtml -a' + would result in an extension list: ['.js', '.txt', '.xhtml'] + + >>> handle_extensions(['.html', 'html,js,py,py,py,.py', 'py,.py']) + {'.html', '.js', '.py'} + >>> handle_extensions(['.html, txt,.tpl']) + {'.html', '.tpl', '.txt'} + """ + ext_list = [] + for ext in extensions: + ext_list.extend(ext.replace(" ", "").split(",")) + for i, ext in enumerate(ext_list): + if not ext.startswith("."): + ext_list[i] = ".%s" % ext_list[i] + return set(ext_list) + + +def find_command(cmd, path=None, pathext=None): + if path is None: + path = os.environ.get("PATH", "").split(os.pathsep) + if isinstance(path, str): + path = [path] + # check if there are funny path extensions for executables, e.g. Windows + if pathext is None: + pathext = os.environ.get("PATHEXT", ".COM;.EXE;.BAT;.CMD").split(os.pathsep) + # don't use extensions if the command ends with one of them + for ext in pathext: + if cmd.endswith(ext): + pathext = [""] + break + # check if we find the command on PATH + for p in path: + f = os.path.join(p, cmd) + if os.path.isfile(f): + return f + for ext in pathext: + fext = f + ext + if os.path.isfile(fext): + return fext + return None + + +def get_random_secret_key(): + """ + Return a 50 character random string usable as a SECRET_KEY setting value. + """ + chars = "abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)" + return get_random_string(50, chars) + + +def parse_apps_and_model_labels(labels): + """ + Parse a list of "app_label.ModelName" or "app_label" strings into actual + objects and return a two-element tuple: + (set of model classes, set of app_configs). + Raise a CommandError if some specified models or apps don't exist. + """ + apps = set() + models = set() + + for label in labels: + if "." in label: + try: + model = installed_apps.get_model(label) + except LookupError: + raise CommandError("Unknown model: %s" % label) + models.add(model) + else: + try: + app_config = installed_apps.get_app_config(label) + except LookupError as e: + raise CommandError(str(e)) + apps.add(app_config) + + return models, apps + + +def get_command_line_option(argv, option): + """ + Return the value of a command line option (which should include leading + dashes, e.g. '--testrunner') from an argument list. Return None if the + option wasn't passed or if the argument list couldn't be parsed. + """ + parser = CommandParser(add_help=False, allow_abbrev=False) + parser.add_argument(option, dest="value") + try: + options, _ = parser.parse_known_args(argv[2:]) + except CommandError: + return None + else: + return options.value + + +def normalize_path_patterns(patterns): + """Normalize an iterable of glob style patterns based on OS.""" + patterns = [os.path.normcase(p) for p in patterns] + dir_suffixes = {"%s*" % path_sep for path_sep in {"/", os.sep}} + norm_patterns = [] + for pattern in patterns: + for dir_suffix in dir_suffixes: + if pattern.endswith(dir_suffix): + norm_patterns.append(pattern.removesuffix(dir_suffix)) + break + else: + norm_patterns.append(pattern) + return norm_patterns + + +def is_ignored_path(path, ignore_patterns): + """ + Check if the given path should be ignored or not based on matching + one of the glob style `ignore_patterns`. + """ + path = Path(path) + + def ignore(pattern): + return fnmatch.fnmatchcase(path.name, pattern) or fnmatch.fnmatchcase( + str(path), pattern + ) + + return any(ignore(pattern) for pattern in normalize_path_patterns(ignore_patterns)) + + +def find_formatters(): + return {"black_path": shutil.which("black")} + + +def run_formatters(written_files, black_path=(sentinel := object())): + """ + Run the black formatter on the specified files. + """ + # Use a sentinel rather than None, as which() returns None when not found. + if black_path is sentinel: + black_path = shutil.which("black") + if black_path: + subprocess.run( + [black_path, "--fast", "--", *written_files], + capture_output=True, + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/paginator.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/paginator.py new file mode 100644 index 0000000..7b3189c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/paginator.py @@ -0,0 +1,238 @@ +import collections.abc +import inspect +import warnings +from math import ceil + +from django.utils.functional import cached_property +from django.utils.inspect import method_has_no_args +from django.utils.translation import gettext_lazy as _ + + +class UnorderedObjectListWarning(RuntimeWarning): + pass + + +class InvalidPage(Exception): + pass + + +class PageNotAnInteger(InvalidPage): + pass + + +class EmptyPage(InvalidPage): + pass + + +class Paginator: + # Translators: String used to replace omitted page numbers in elided page + # range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10]. + ELLIPSIS = _("…") + default_error_messages = { + "invalid_page": _("That page number is not an integer"), + "min_page": _("That page number is less than 1"), + "no_results": _("That page contains no results"), + } + + def __init__( + self, + object_list, + per_page, + orphans=0, + allow_empty_first_page=True, + error_messages=None, + ): + self.object_list = object_list + self._check_object_list_is_ordered() + self.per_page = int(per_page) + self.orphans = int(orphans) + self.allow_empty_first_page = allow_empty_first_page + self.error_messages = ( + self.default_error_messages + if error_messages is None + else self.default_error_messages | error_messages + ) + + def __iter__(self): + for page_number in self.page_range: + yield self.page(page_number) + + def validate_number(self, number): + """Validate the given 1-based page number.""" + try: + if isinstance(number, float) and not number.is_integer(): + raise ValueError + number = int(number) + except (TypeError, ValueError): + raise PageNotAnInteger(self.error_messages["invalid_page"]) + if number < 1: + raise EmptyPage(self.error_messages["min_page"]) + if number > self.num_pages: + raise EmptyPage(self.error_messages["no_results"]) + return number + + def get_page(self, number): + """ + Return a valid page, even if the page argument isn't a number or isn't + in range. + """ + try: + number = self.validate_number(number) + except PageNotAnInteger: + number = 1 + except EmptyPage: + number = self.num_pages + return self.page(number) + + def page(self, number): + """Return a Page object for the given 1-based page number.""" + number = self.validate_number(number) + bottom = (number - 1) * self.per_page + top = bottom + self.per_page + if top + self.orphans >= self.count: + top = self.count + return self._get_page(self.object_list[bottom:top], number, self) + + def _get_page(self, *args, **kwargs): + """ + Return an instance of a single page. + + This hook can be used by subclasses to use an alternative to the + standard :cls:`Page` object. + """ + return Page(*args, **kwargs) + + @cached_property + def count(self): + """Return the total number of objects, across all pages.""" + c = getattr(self.object_list, "count", None) + if callable(c) and not inspect.isbuiltin(c) and method_has_no_args(c): + return c() + return len(self.object_list) + + @cached_property + def num_pages(self): + """Return the total number of pages.""" + if self.count == 0 and not self.allow_empty_first_page: + return 0 + hits = max(1, self.count - self.orphans) + return ceil(hits / self.per_page) + + @property + def page_range(self): + """ + Return a 1-based range of pages for iterating through within + a template for loop. + """ + return range(1, self.num_pages + 1) + + def _check_object_list_is_ordered(self): + """ + Warn if self.object_list is unordered (typically a QuerySet). + """ + ordered = getattr(self.object_list, "ordered", None) + if ordered is not None and not ordered: + obj_list_repr = ( + "{} {}".format( + self.object_list.model, self.object_list.__class__.__name__ + ) + if hasattr(self.object_list, "model") + else "{!r}".format(self.object_list) + ) + warnings.warn( + "Pagination may yield inconsistent results with an unordered " + "object_list: {}.".format(obj_list_repr), + UnorderedObjectListWarning, + stacklevel=3, + ) + + def get_elided_page_range(self, number=1, *, on_each_side=3, on_ends=2): + """ + Return a 1-based range of pages with some values elided. + + If the page range is larger than a given size, the whole range is not + provided and a compact form is returned instead, e.g. for a paginator + with 50 pages, if page 43 were the current page, the output, with the + default arguments, would be: + + 1, 2, …, 40, 41, 42, 43, 44, 45, 46, …, 49, 50. + """ + number = self.validate_number(number) + + if self.num_pages <= (on_each_side + on_ends) * 2: + yield from self.page_range + return + + if number > (1 + on_each_side + on_ends) + 1: + yield from range(1, on_ends + 1) + yield self.ELLIPSIS + yield from range(number - on_each_side, number + 1) + else: + yield from range(1, number + 1) + + if number < (self.num_pages - on_each_side - on_ends) - 1: + yield from range(number + 1, number + on_each_side + 1) + yield self.ELLIPSIS + yield from range(self.num_pages - on_ends + 1, self.num_pages + 1) + else: + yield from range(number + 1, self.num_pages + 1) + + +class Page(collections.abc.Sequence): + def __init__(self, object_list, number, paginator): + self.object_list = object_list + self.number = number + self.paginator = paginator + + def __repr__(self): + return "" % (self.number, self.paginator.num_pages) + + def __len__(self): + return len(self.object_list) + + def __getitem__(self, index): + if not isinstance(index, (int, slice)): + raise TypeError( + "Page indices must be integers or slices, not %s." + % type(index).__name__ + ) + # The object_list is converted to a list so that if it was a QuerySet + # it won't be a database hit per __getitem__. + if not isinstance(self.object_list, list): + self.object_list = list(self.object_list) + return self.object_list[index] + + def has_next(self): + return self.number < self.paginator.num_pages + + def has_previous(self): + return self.number > 1 + + def has_other_pages(self): + return self.has_previous() or self.has_next() + + def next_page_number(self): + return self.paginator.validate_number(self.number + 1) + + def previous_page_number(self): + return self.paginator.validate_number(self.number - 1) + + def start_index(self): + """ + Return the 1-based index of the first object on this page, + relative to total objects in the paginator. + """ + # Special case, return zero if no items. + if self.paginator.count == 0: + return 0 + return (self.paginator.per_page * (self.number - 1)) + 1 + + def end_index(self): + """ + Return the 1-based index of the last object on this page, + relative to total objects found (hits). + """ + # Special case for the last page because there can be orphans. + if self.number == self.paginator.num_pages: + return self.paginator.count + return self.number * self.paginator.per_page diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/serializers/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/serializers/__init__.py new file mode 100644 index 0000000..480c54b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/serializers/__init__.py @@ -0,0 +1,254 @@ +""" +Interfaces for serializing Django objects. + +Usage:: + + from django.core import serializers + json = serializers.serialize("json", some_queryset) + objects = list(serializers.deserialize("json", json)) + +To add your own serializers, use the SERIALIZATION_MODULES setting:: + + SERIALIZATION_MODULES = { + "csv": "path.to.csv.serializer", + "txt": "path.to.txt.serializer", + } + +""" + +import importlib + +from django.apps import apps +from django.conf import settings +from django.core.serializers.base import SerializerDoesNotExist + +# Built-in serializers +BUILTIN_SERIALIZERS = { + "xml": "django.core.serializers.xml_serializer", + "python": "django.core.serializers.python", + "json": "django.core.serializers.json", + "yaml": "django.core.serializers.pyyaml", + "jsonl": "django.core.serializers.jsonl", +} + +_serializers = {} + + +class BadSerializer: + """ + Stub serializer to hold exception raised during registration + + This allows the serializer registration to cache serializers and if there + is an error raised in the process of creating a serializer it will be + raised and passed along to the caller when the serializer is used. + """ + + internal_use_only = False + + def __init__(self, exception): + self.exception = exception + + def __call__(self, *args, **kwargs): + raise self.exception + + +def register_serializer(format, serializer_module, serializers=None): + """Register a new serializer. + + ``serializer_module`` should be the fully qualified module name + for the serializer. + + If ``serializers`` is provided, the registration will be added + to the provided dictionary. + + If ``serializers`` is not provided, the registration will be made + directly into the global register of serializers. Adding serializers + directly is not a thread-safe operation. + """ + if serializers is None and not _serializers: + _load_serializers() + + try: + module = importlib.import_module(serializer_module) + except ImportError as exc: + bad_serializer = BadSerializer(exc) + + module = type( + "BadSerializerModule", + (), + { + "Deserializer": bad_serializer, + "Serializer": bad_serializer, + }, + ) + + if serializers is None: + _serializers[format] = module + else: + serializers[format] = module + + +def unregister_serializer(format): + "Unregister a given serializer. This is not a thread-safe operation." + if not _serializers: + _load_serializers() + if format not in _serializers: + raise SerializerDoesNotExist(format) + del _serializers[format] + + +def get_serializer(format): + if not _serializers: + _load_serializers() + if format not in _serializers: + raise SerializerDoesNotExist(format) + return _serializers[format].Serializer + + +def get_serializer_formats(): + if not _serializers: + _load_serializers() + return list(_serializers) + + +def get_public_serializer_formats(): + if not _serializers: + _load_serializers() + return [k for k, v in _serializers.items() if not v.Serializer.internal_use_only] + + +def get_deserializer(format): + if not _serializers: + _load_serializers() + if format not in _serializers: + raise SerializerDoesNotExist(format) + return _serializers[format].Deserializer + + +def serialize(format, queryset, **options): + """ + Serialize a queryset (or any iterator that returns database objects) using + a certain serializer. + """ + s = get_serializer(format)() + s.serialize(queryset, **options) + return s.getvalue() + + +def deserialize(format, stream_or_string, **options): + """ + Deserialize a stream or a string. Return an iterator that yields ``(obj, + m2m_relation_dict)``, where ``obj`` is an instantiated -- but *unsaved* -- + object, and ``m2m_relation_dict`` is a dictionary of ``{m2m_field_name : + list_of_related_objects}``. + """ + d = get_deserializer(format) + return d(stream_or_string, **options) + + +def _load_serializers(): + """ + Register built-in and settings-defined serializers. This is done lazily so + that user code has a chance to (e.g.) set up custom settings without + needing to be careful of import order. + """ + global _serializers + serializers = {} + for format in BUILTIN_SERIALIZERS: + register_serializer(format, BUILTIN_SERIALIZERS[format], serializers) + if hasattr(settings, "SERIALIZATION_MODULES"): + for format in settings.SERIALIZATION_MODULES: + register_serializer( + format, settings.SERIALIZATION_MODULES[format], serializers + ) + _serializers = serializers + + +def sort_dependencies(app_list, allow_cycles=False): + """Sort a list of (app_config, models) pairs into a single list of models. + + The single list of models is sorted so that any model with a natural key + is serialized before a normal model, and any model with a natural key + dependency has it's dependencies serialized first. + + If allow_cycles is True, return the best-effort ordering that will respect + most of dependencies but ignore some of them to break the cycles. + """ + # Process the list of models, and get the list of dependencies + model_dependencies = [] + models = set() + for app_config, model_list in app_list: + if model_list is None: + model_list = app_config.get_models() + + for model in model_list: + models.add(model) + # Add any explicitly defined dependencies + if hasattr(model, "natural_key"): + deps = getattr(model.natural_key, "dependencies", []) + if deps: + deps = [apps.get_model(dep) for dep in deps] + else: + deps = [] + + # Now add a dependency for any FK relation with a model that + # defines a natural key + for field in model._meta.fields: + if field.remote_field: + rel_model = field.remote_field.model + if hasattr(rel_model, "natural_key") and rel_model != model: + deps.append(rel_model) + # Also add a dependency for any simple M2M relation with a model + # that defines a natural key. M2M relations with explicit through + # models don't count as dependencies. + for field in model._meta.many_to_many: + if field.remote_field.through._meta.auto_created: + rel_model = field.remote_field.model + if hasattr(rel_model, "natural_key") and rel_model != model: + deps.append(rel_model) + model_dependencies.append((model, deps)) + + model_dependencies.reverse() + # Now sort the models to ensure that dependencies are met. This + # is done by repeatedly iterating over the input list of models. + # If all the dependencies of a given model are in the final list, + # that model is promoted to the end of the final list. This process + # continues until the input list is empty, or we do a full iteration + # over the input models without promoting a model to the final list. + # If we do a full iteration without a promotion, that means there are + # circular dependencies in the list. + model_list = [] + while model_dependencies: + skipped = [] + changed = False + while model_dependencies: + model, deps = model_dependencies.pop() + + # If all of the models in the dependency list are either already + # on the final model list, or not on the original serialization list, + # then we've found another model with all it's dependencies satisfied. + if all(d not in models or d in model_list for d in deps): + model_list.append(model) + changed = True + else: + skipped.append((model, deps)) + if not changed: + if allow_cycles: + # If cycles are allowed, add the last skipped model and ignore + # its dependencies. This could be improved by some graph + # analysis to ignore as few dependencies as possible. + model, _ = skipped.pop() + model_list.append(model) + else: + raise RuntimeError( + "Can't resolve dependencies for %s in serialized app list." + % ", ".join( + model._meta.label + for model, deps in sorted( + skipped, key=lambda obj: obj[0].__name__ + ) + ), + ) + model_dependencies = skipped + + return model_list diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/serializers/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/serializers/base.py new file mode 100644 index 0000000..20dffac --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/serializers/base.py @@ -0,0 +1,386 @@ +""" +Module for abstract serializer/unserializer base classes. +""" +from io import StringIO + +from django.core.exceptions import ObjectDoesNotExist +from django.db import models + +DEFER_FIELD = object() + + +class SerializerDoesNotExist(KeyError): + """The requested serializer was not found.""" + + pass + + +class SerializationError(Exception): + """Something bad happened during serialization.""" + + pass + + +class DeserializationError(Exception): + """Something bad happened during deserialization.""" + + @classmethod + def WithData(cls, original_exc, model, fk, field_value): + """ + Factory method for creating a deserialization error which has a more + explanatory message. + """ + return cls( + "%s: (%s:pk=%s) field_value was '%s'" + % (original_exc, model, fk, field_value) + ) + + +class M2MDeserializationError(Exception): + """Something bad happened during deserialization of a ManyToManyField.""" + + def __init__(self, original_exc, pk): + self.original_exc = original_exc + self.pk = pk + + +class ProgressBar: + progress_width = 75 + + def __init__(self, output, total_count): + self.output = output + self.total_count = total_count + self.prev_done = 0 + + def update(self, count): + if not self.output: + return + perc = count * 100 // self.total_count + done = perc * self.progress_width // 100 + if self.prev_done >= done: + return + self.prev_done = done + cr = "" if self.total_count == 1 else "\r" + self.output.write( + cr + "[" + "." * done + " " * (self.progress_width - done) + "]" + ) + if done == self.progress_width: + self.output.write("\n") + self.output.flush() + + +class Serializer: + """ + Abstract serializer base class. + """ + + # Indicates if the implemented serializer is only available for + # internal Django use. + internal_use_only = False + progress_class = ProgressBar + stream_class = StringIO + + def serialize( + self, + queryset, + *, + stream=None, + fields=None, + use_natural_foreign_keys=False, + use_natural_primary_keys=False, + progress_output=None, + object_count=0, + **options, + ): + """ + Serialize a queryset. + """ + self.options = options + + self.stream = stream if stream is not None else self.stream_class() + self.selected_fields = fields + self.use_natural_foreign_keys = use_natural_foreign_keys + self.use_natural_primary_keys = use_natural_primary_keys + progress_bar = self.progress_class(progress_output, object_count) + + self.start_serialization() + self.first = True + for count, obj in enumerate(queryset, start=1): + self.start_object(obj) + # Use the concrete parent class' _meta instead of the object's _meta + # This is to avoid local_fields problems for proxy models. Refs #17717. + concrete_model = obj._meta.concrete_model + # When using natural primary keys, retrieve the pk field of the + # parent for multi-table inheritance child models. That field must + # be serialized, otherwise deserialization isn't possible. + if self.use_natural_primary_keys: + pk = concrete_model._meta.pk + pk_parent = ( + pk if pk.remote_field and pk.remote_field.parent_link else None + ) + else: + pk_parent = None + for field in concrete_model._meta.local_fields: + if field.serialize or field is pk_parent: + if field.remote_field is None: + if ( + self.selected_fields is None + or field.attname in self.selected_fields + ): + self.handle_field(obj, field) + else: + if ( + self.selected_fields is None + or field.attname[:-3] in self.selected_fields + ): + self.handle_fk_field(obj, field) + for field in concrete_model._meta.local_many_to_many: + if field.serialize: + if ( + self.selected_fields is None + or field.attname in self.selected_fields + ): + self.handle_m2m_field(obj, field) + self.end_object(obj) + progress_bar.update(count) + self.first = self.first and False + self.end_serialization() + return self.getvalue() + + def start_serialization(self): + """ + Called when serializing of the queryset starts. + """ + raise NotImplementedError( + "subclasses of Serializer must provide a start_serialization() method" + ) + + def end_serialization(self): + """ + Called when serializing of the queryset ends. + """ + pass + + def start_object(self, obj): + """ + Called when serializing of an object starts. + """ + raise NotImplementedError( + "subclasses of Serializer must provide a start_object() method" + ) + + def end_object(self, obj): + """ + Called when serializing of an object ends. + """ + pass + + def handle_field(self, obj, field): + """ + Called to handle each individual (non-relational) field on an object. + """ + raise NotImplementedError( + "subclasses of Serializer must provide a handle_field() method" + ) + + def handle_fk_field(self, obj, field): + """ + Called to handle a ForeignKey field. + """ + raise NotImplementedError( + "subclasses of Serializer must provide a handle_fk_field() method" + ) + + def handle_m2m_field(self, obj, field): + """ + Called to handle a ManyToManyField. + """ + raise NotImplementedError( + "subclasses of Serializer must provide a handle_m2m_field() method" + ) + + def getvalue(self): + """ + Return the fully serialized queryset (or None if the output stream is + not seekable). + """ + if callable(getattr(self.stream, "getvalue", None)): + return self.stream.getvalue() + + +class Deserializer: + """ + Abstract base deserializer class. + """ + + def __init__(self, stream_or_string, **options): + """ + Init this serializer given a stream or a string + """ + self.options = options + if isinstance(stream_or_string, str): + self.stream = StringIO(stream_or_string) + else: + self.stream = stream_or_string + + def __iter__(self): + return self + + def __next__(self): + """Iteration interface -- return the next item in the stream""" + raise NotImplementedError( + "subclasses of Deserializer must provide a __next__() method" + ) + + +class DeserializedObject: + """ + A deserialized model. + + Basically a container for holding the pre-saved deserialized data along + with the many-to-many data saved with the object. + + Call ``save()`` to save the object (with the many-to-many data) to the + database; call ``save(save_m2m=False)`` to save just the object fields + (and not touch the many-to-many stuff.) + """ + + def __init__(self, obj, m2m_data=None, deferred_fields=None): + self.object = obj + self.m2m_data = m2m_data + self.deferred_fields = deferred_fields + + def __repr__(self): + return "<%s: %s(pk=%s)>" % ( + self.__class__.__name__, + self.object._meta.label, + self.object.pk, + ) + + def save(self, save_m2m=True, using=None, **kwargs): + # Call save on the Model baseclass directly. This bypasses any + # model-defined save. The save is also forced to be raw. + # raw=True is passed to any pre/post_save signals. + models.Model.save_base(self.object, using=using, raw=True, **kwargs) + if self.m2m_data and save_m2m: + for accessor_name, object_list in self.m2m_data.items(): + getattr(self.object, accessor_name).set(object_list) + + # prevent a second (possibly accidental) call to save() from saving + # the m2m data twice. + self.m2m_data = None + + def save_deferred_fields(self, using=None): + self.m2m_data = {} + for field, field_value in self.deferred_fields.items(): + opts = self.object._meta + label = opts.app_label + "." + opts.model_name + if isinstance(field.remote_field, models.ManyToManyRel): + try: + values = deserialize_m2m_values( + field, field_value, using, handle_forward_references=False + ) + except M2MDeserializationError as e: + raise DeserializationError.WithData( + e.original_exc, label, self.object.pk, e.pk + ) + self.m2m_data[field.name] = values + elif isinstance(field.remote_field, models.ManyToOneRel): + try: + value = deserialize_fk_value( + field, field_value, using, handle_forward_references=False + ) + except Exception as e: + raise DeserializationError.WithData( + e, label, self.object.pk, field_value + ) + setattr(self.object, field.attname, value) + self.save() + + +def build_instance(Model, data, db): + """ + Build a model instance. + + If the model instance doesn't have a primary key and the model supports + natural keys, try to retrieve it from the database. + """ + default_manager = Model._meta.default_manager + pk = data.get(Model._meta.pk.attname) + if ( + pk is None + and hasattr(default_manager, "get_by_natural_key") + and hasattr(Model, "natural_key") + ): + obj = Model(**data) + obj._state.db = db + natural_key = obj.natural_key() + try: + data[Model._meta.pk.attname] = Model._meta.pk.to_python( + default_manager.db_manager(db).get_by_natural_key(*natural_key).pk + ) + except Model.DoesNotExist: + pass + return Model(**data) + + +def deserialize_m2m_values(field, field_value, using, handle_forward_references): + model = field.remote_field.model + if hasattr(model._default_manager, "get_by_natural_key"): + + def m2m_convert(value): + if hasattr(value, "__iter__") and not isinstance(value, str): + return ( + model._default_manager.db_manager(using) + .get_by_natural_key(*value) + .pk + ) + else: + return model._meta.pk.to_python(value) + + else: + + def m2m_convert(v): + return model._meta.pk.to_python(v) + + try: + pks_iter = iter(field_value) + except TypeError as e: + raise M2MDeserializationError(e, field_value) + try: + values = [] + for pk in pks_iter: + values.append(m2m_convert(pk)) + return values + except Exception as e: + if isinstance(e, ObjectDoesNotExist) and handle_forward_references: + return DEFER_FIELD + else: + raise M2MDeserializationError(e, pk) + + +def deserialize_fk_value(field, field_value, using, handle_forward_references): + if field_value is None: + return None + model = field.remote_field.model + default_manager = model._default_manager + field_name = field.remote_field.field_name + if ( + hasattr(default_manager, "get_by_natural_key") + and hasattr(field_value, "__iter__") + and not isinstance(field_value, str) + ): + try: + obj = default_manager.db_manager(using).get_by_natural_key(*field_value) + except ObjectDoesNotExist: + if handle_forward_references: + return DEFER_FIELD + else: + raise + value = getattr(obj, field_name) + # If this is a natural foreign key to an object that has a FK/O2O as + # the foreign key, use the FK value. + if model._meta.pk.remote_field: + value = value.pk + return value + return model._meta.get_field(field_name).to_python(field_value) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/serializers/json.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/serializers/json.py new file mode 100644 index 0000000..afac821 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/serializers/json.py @@ -0,0 +1,106 @@ +""" +Serialize data to/from JSON +""" + +import datetime +import decimal +import json +import uuid + +from django.core.serializers.base import DeserializationError +from django.core.serializers.python import Deserializer as PythonDeserializer +from django.core.serializers.python import Serializer as PythonSerializer +from django.utils.duration import duration_iso_string +from django.utils.functional import Promise +from django.utils.timezone import is_aware + + +class Serializer(PythonSerializer): + """Convert a queryset to JSON.""" + + internal_use_only = False + + def _init_options(self): + self._current = None + self.json_kwargs = self.options.copy() + self.json_kwargs.pop("stream", None) + self.json_kwargs.pop("fields", None) + if self.options.get("indent"): + # Prevent trailing spaces + self.json_kwargs["separators"] = (",", ": ") + self.json_kwargs.setdefault("cls", DjangoJSONEncoder) + self.json_kwargs.setdefault("ensure_ascii", False) + + def start_serialization(self): + self._init_options() + self.stream.write("[") + + def end_serialization(self): + if self.options.get("indent"): + self.stream.write("\n") + self.stream.write("]") + if self.options.get("indent"): + self.stream.write("\n") + + def end_object(self, obj): + # self._current has the field data + indent = self.options.get("indent") + if not self.first: + self.stream.write(",") + if not indent: + self.stream.write(" ") + if indent: + self.stream.write("\n") + json.dump(self.get_dump_object(obj), self.stream, **self.json_kwargs) + self._current = None + + def getvalue(self): + # Grandparent super + return super(PythonSerializer, self).getvalue() + + +def Deserializer(stream_or_string, **options): + """Deserialize a stream or string of JSON data.""" + if not isinstance(stream_or_string, (bytes, str)): + stream_or_string = stream_or_string.read() + if isinstance(stream_or_string, bytes): + stream_or_string = stream_or_string.decode() + try: + objects = json.loads(stream_or_string) + yield from PythonDeserializer(objects, **options) + except (GeneratorExit, DeserializationError): + raise + except Exception as exc: + raise DeserializationError() from exc + + +class DjangoJSONEncoder(json.JSONEncoder): + """ + JSONEncoder subclass that knows how to encode date/time, decimal types, and + UUIDs. + """ + + def default(self, o): + # See "Date Time String Format" in the ECMA-262 specification. + if isinstance(o, datetime.datetime): + r = o.isoformat() + if o.microsecond: + r = r[:23] + r[26:] + if r.endswith("+00:00"): + r = r.removesuffix("+00:00") + "Z" + return r + elif isinstance(o, datetime.date): + return o.isoformat() + elif isinstance(o, datetime.time): + if is_aware(o): + raise ValueError("JSON can't represent timezone-aware times.") + r = o.isoformat() + if o.microsecond: + r = r[:12] + return r + elif isinstance(o, datetime.timedelta): + return duration_iso_string(o) + elif isinstance(o, (decimal.Decimal, uuid.UUID, Promise)): + return str(o) + else: + return super().default(o) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/serializers/jsonl.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/serializers/jsonl.py new file mode 100644 index 0000000..c264c2c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/serializers/jsonl.py @@ -0,0 +1,57 @@ +""" +Serialize data to/from JSON Lines +""" + +import json + +from django.core.serializers.base import DeserializationError +from django.core.serializers.json import DjangoJSONEncoder +from django.core.serializers.python import Deserializer as PythonDeserializer +from django.core.serializers.python import Serializer as PythonSerializer + + +class Serializer(PythonSerializer): + """Convert a queryset to JSON Lines.""" + + internal_use_only = False + + def _init_options(self): + self._current = None + self.json_kwargs = self.options.copy() + self.json_kwargs.pop("stream", None) + self.json_kwargs.pop("fields", None) + self.json_kwargs.pop("indent", None) + self.json_kwargs["separators"] = (",", ": ") + self.json_kwargs.setdefault("cls", DjangoJSONEncoder) + self.json_kwargs.setdefault("ensure_ascii", False) + + def start_serialization(self): + self._init_options() + + def end_object(self, obj): + # self._current has the field data + json.dump(self.get_dump_object(obj), self.stream, **self.json_kwargs) + self.stream.write("\n") + self._current = None + + def getvalue(self): + # Grandparent super + return super(PythonSerializer, self).getvalue() + + +def Deserializer(stream_or_string, **options): + """Deserialize a stream or string of JSON data.""" + if isinstance(stream_or_string, bytes): + stream_or_string = stream_or_string.decode() + if isinstance(stream_or_string, (bytes, str)): + stream_or_string = stream_or_string.split("\n") + + for line in stream_or_string: + if not line.strip(): + continue + try: + yield from PythonDeserializer([json.loads(line)], **options) + except (GeneratorExit, DeserializationError): + raise + except Exception as exc: + raise DeserializationError() from exc diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/serializers/python.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/serializers/python.py new file mode 100644 index 0000000..7ec894a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/serializers/python.py @@ -0,0 +1,195 @@ +""" +A Python "serializer". Doesn't do much serializing per se -- just converts to +and from basic Python data types (lists, dicts, strings, etc.). Useful as a basis for +other serializers. +""" + +from django.apps import apps +from django.core.serializers import base +from django.db import DEFAULT_DB_ALIAS, models +from django.utils.encoding import is_protected_type + + +class Serializer(base.Serializer): + """ + Serialize a QuerySet to basic Python objects. + """ + + internal_use_only = True + + def start_serialization(self): + self._current = None + self.objects = [] + + def end_serialization(self): + pass + + def start_object(self, obj): + self._current = {} + + def end_object(self, obj): + self.objects.append(self.get_dump_object(obj)) + self._current = None + + def get_dump_object(self, obj): + data = {"model": str(obj._meta)} + if not self.use_natural_primary_keys or not hasattr(obj, "natural_key"): + data["pk"] = self._value_from_field(obj, obj._meta.pk) + data["fields"] = self._current + return data + + def _value_from_field(self, obj, field): + value = field.value_from_object(obj) + # Protected types (i.e., primitives like None, numbers, dates, + # and Decimals) are passed through as is. All other values are + # converted to string first. + return value if is_protected_type(value) else field.value_to_string(obj) + + def handle_field(self, obj, field): + self._current[field.name] = self._value_from_field(obj, field) + + def handle_fk_field(self, obj, field): + if self.use_natural_foreign_keys and hasattr( + field.remote_field.model, "natural_key" + ): + related = getattr(obj, field.name) + if related: + value = related.natural_key() + else: + value = None + else: + value = self._value_from_field(obj, field) + self._current[field.name] = value + + def handle_m2m_field(self, obj, field): + if field.remote_field.through._meta.auto_created: + if self.use_natural_foreign_keys and hasattr( + field.remote_field.model, "natural_key" + ): + + def m2m_value(value): + return value.natural_key() + + def queryset_iterator(obj, field): + return getattr(obj, field.name).iterator() + + else: + + def m2m_value(value): + return self._value_from_field(value, value._meta.pk) + + def queryset_iterator(obj, field): + return ( + getattr(obj, field.name) + .select_related(None) + .only("pk") + .iterator() + ) + + m2m_iter = getattr(obj, "_prefetched_objects_cache", {}).get( + field.name, + queryset_iterator(obj, field), + ) + self._current[field.name] = [m2m_value(related) for related in m2m_iter] + + def getvalue(self): + return self.objects + + +def Deserializer( + object_list, *, using=DEFAULT_DB_ALIAS, ignorenonexistent=False, **options +): + """ + Deserialize simple Python objects back into Django ORM instances. + + It's expected that you pass the Python objects themselves (instead of a + stream or a string) to the constructor + """ + handle_forward_references = options.pop("handle_forward_references", False) + field_names_cache = {} # Model: + + for d in object_list: + # Look up the model and starting build a dict of data for it. + try: + Model = _get_model(d["model"]) + except base.DeserializationError: + if ignorenonexistent: + continue + else: + raise + data = {} + if "pk" in d: + try: + data[Model._meta.pk.attname] = Model._meta.pk.to_python(d.get("pk")) + except Exception as e: + raise base.DeserializationError.WithData( + e, d["model"], d.get("pk"), None + ) + m2m_data = {} + deferred_fields = {} + + if Model not in field_names_cache: + field_names_cache[Model] = {f.name for f in Model._meta.get_fields()} + field_names = field_names_cache[Model] + + # Handle each field + for field_name, field_value in d["fields"].items(): + if ignorenonexistent and field_name not in field_names: + # skip fields no longer on model + continue + + field = Model._meta.get_field(field_name) + + # Handle M2M relations + if field.remote_field and isinstance( + field.remote_field, models.ManyToManyRel + ): + try: + values = base.deserialize_m2m_values( + field, field_value, using, handle_forward_references + ) + except base.M2MDeserializationError as e: + raise base.DeserializationError.WithData( + e.original_exc, d["model"], d.get("pk"), e.pk + ) + if values == base.DEFER_FIELD: + deferred_fields[field] = field_value + else: + m2m_data[field.name] = values + # Handle FK fields + elif field.remote_field and isinstance( + field.remote_field, models.ManyToOneRel + ): + try: + value = base.deserialize_fk_value( + field, field_value, using, handle_forward_references + ) + except Exception as e: + raise base.DeserializationError.WithData( + e, d["model"], d.get("pk"), field_value + ) + if value == base.DEFER_FIELD: + deferred_fields[field] = field_value + else: + data[field.attname] = value + # Handle all other fields + else: + try: + data[field.name] = field.to_python(field_value) + except Exception as e: + raise base.DeserializationError.WithData( + e, d["model"], d.get("pk"), field_value + ) + + obj = base.build_instance(Model, data, using) + yield base.DeserializedObject(obj, m2m_data, deferred_fields) + + +def _get_model(model_identifier): + """Look up a model from an "app_label.model_name" string.""" + try: + return apps.get_model(model_identifier) + except (LookupError, TypeError): + raise base.DeserializationError( + "Invalid model identifier: '%s'" % model_identifier + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/serializers/pyyaml.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/serializers/pyyaml.py new file mode 100644 index 0000000..9a20b66 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/serializers/pyyaml.py @@ -0,0 +1,82 @@ +""" +YAML serializer. + +Requires PyYaml (https://pyyaml.org/), but that's checked for in __init__. +""" + +import collections +import decimal +from io import StringIO + +import yaml + +from django.core.serializers.base import DeserializationError +from django.core.serializers.python import Deserializer as PythonDeserializer +from django.core.serializers.python import Serializer as PythonSerializer +from django.db import models + +# Use the C (faster) implementation if possible +try: + from yaml import CSafeDumper as SafeDumper + from yaml import CSafeLoader as SafeLoader +except ImportError: + from yaml import SafeDumper, SafeLoader + + +class DjangoSafeDumper(SafeDumper): + def represent_decimal(self, data): + return self.represent_scalar("tag:yaml.org,2002:str", str(data)) + + def represent_ordered_dict(self, data): + return self.represent_mapping("tag:yaml.org,2002:map", data.items()) + + +DjangoSafeDumper.add_representer(decimal.Decimal, DjangoSafeDumper.represent_decimal) +DjangoSafeDumper.add_representer( + collections.OrderedDict, DjangoSafeDumper.represent_ordered_dict +) +# Workaround to represent dictionaries in insertion order. +# See https://github.com/yaml/pyyaml/pull/143. +DjangoSafeDumper.add_representer(dict, DjangoSafeDumper.represent_ordered_dict) + + +class Serializer(PythonSerializer): + """Convert a queryset to YAML.""" + + internal_use_only = False + + def handle_field(self, obj, field): + # A nasty special case: base YAML doesn't support serialization of time + # types (as opposed to dates or datetimes, which it does support). Since + # we want to use the "safe" serializer for better interoperability, we + # need to do something with those pesky times. Converting 'em to strings + # isn't perfect, but it's better than a "!!python/time" type which would + # halt deserialization under any other language. + if isinstance(field, models.TimeField) and getattr(obj, field.name) is not None: + self._current[field.name] = str(getattr(obj, field.name)) + else: + super().handle_field(obj, field) + + def end_serialization(self): + self.options.setdefault("allow_unicode", True) + yaml.dump(self.objects, self.stream, Dumper=DjangoSafeDumper, **self.options) + + def getvalue(self): + # Grandparent super + return super(PythonSerializer, self).getvalue() + + +def Deserializer(stream_or_string, **options): + """Deserialize a stream or string of YAML data.""" + if isinstance(stream_or_string, bytes): + stream_or_string = stream_or_string.decode() + if isinstance(stream_or_string, str): + stream = StringIO(stream_or_string) + else: + stream = stream_or_string + try: + yield from PythonDeserializer(yaml.load(stream, Loader=SafeLoader), **options) + except (GeneratorExit, DeserializationError): + raise + except Exception as exc: + raise DeserializationError() from exc diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/serializers/xml_serializer.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/serializers/xml_serializer.py new file mode 100644 index 0000000..3f9955a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/serializers/xml_serializer.py @@ -0,0 +1,499 @@ +""" +XML serializer. +""" +import json +from xml.dom import pulldom +from xml.sax import handler +from xml.sax.expatreader import ExpatParser as _ExpatParser + +from django.apps import apps +from django.conf import settings +from django.core.exceptions import ObjectDoesNotExist +from django.core.serializers import base +from django.db import DEFAULT_DB_ALIAS, models +from django.utils.xmlutils import SimplerXMLGenerator, UnserializableContentError + + +class Serializer(base.Serializer): + """Serialize a QuerySet to XML.""" + + def indent(self, level): + if self.options.get("indent") is not None: + self.xml.ignorableWhitespace( + "\n" + " " * self.options.get("indent") * level + ) + + def start_serialization(self): + """ + Start serialization -- open the XML document and the root element. + """ + self.xml = SimplerXMLGenerator( + self.stream, self.options.get("encoding", settings.DEFAULT_CHARSET) + ) + self.xml.startDocument() + self.xml.startElement("django-objects", {"version": "1.0"}) + + def end_serialization(self): + """ + End serialization -- end the document. + """ + self.indent(0) + self.xml.endElement("django-objects") + self.xml.endDocument() + + def start_object(self, obj): + """ + Called as each object is handled. + """ + if not hasattr(obj, "_meta"): + raise base.SerializationError( + "Non-model object (%s) encountered during serialization" % type(obj) + ) + + self.indent(1) + attrs = {"model": str(obj._meta)} + if not self.use_natural_primary_keys or not hasattr(obj, "natural_key"): + obj_pk = obj.pk + if obj_pk is not None: + attrs["pk"] = str(obj_pk) + + self.xml.startElement("object", attrs) + + def end_object(self, obj): + """ + Called after handling all fields for an object. + """ + self.indent(1) + self.xml.endElement("object") + + def handle_field(self, obj, field): + """ + Handle each field on an object (except for ForeignKeys and + ManyToManyFields). + """ + self.indent(2) + self.xml.startElement( + "field", + { + "name": field.name, + "type": field.get_internal_type(), + }, + ) + + # Get a "string version" of the object's data. + if getattr(obj, field.name) is not None: + value = field.value_to_string(obj) + if field.get_internal_type() == "JSONField": + # Dump value since JSONField.value_to_string() doesn't output + # strings. + value = json.dumps(value, cls=field.encoder) + try: + self.xml.characters(value) + except UnserializableContentError: + raise ValueError( + "%s.%s (pk:%s) contains unserializable characters" + % (obj.__class__.__name__, field.name, obj.pk) + ) + else: + self.xml.addQuickElement("None") + + self.xml.endElement("field") + + def handle_fk_field(self, obj, field): + """ + Handle a ForeignKey (they need to be treated slightly + differently from regular fields). + """ + self._start_relational_field(field) + related_att = getattr(obj, field.get_attname()) + if related_att is not None: + if self.use_natural_foreign_keys and hasattr( + field.remote_field.model, "natural_key" + ): + related = getattr(obj, field.name) + # If related object has a natural key, use it + related = related.natural_key() + # Iterable natural keys are rolled out as subelements + for key_value in related: + self.xml.startElement("natural", {}) + self.xml.characters(str(key_value)) + self.xml.endElement("natural") + else: + self.xml.characters(str(related_att)) + else: + self.xml.addQuickElement("None") + self.xml.endElement("field") + + def handle_m2m_field(self, obj, field): + """ + Handle a ManyToManyField. Related objects are only serialized as + references to the object's PK (i.e. the related *data* is not dumped, + just the relation). + """ + if field.remote_field.through._meta.auto_created: + self._start_relational_field(field) + if self.use_natural_foreign_keys and hasattr( + field.remote_field.model, "natural_key" + ): + # If the objects in the m2m have a natural key, use it + def handle_m2m(value): + natural = value.natural_key() + # Iterable natural keys are rolled out as subelements + self.xml.startElement("object", {}) + for key_value in natural: + self.xml.startElement("natural", {}) + self.xml.characters(str(key_value)) + self.xml.endElement("natural") + self.xml.endElement("object") + + def queryset_iterator(obj, field): + return getattr(obj, field.name).iterator() + + else: + + def handle_m2m(value): + self.xml.addQuickElement("object", attrs={"pk": str(value.pk)}) + + def queryset_iterator(obj, field): + return ( + getattr(obj, field.name) + .select_related(None) + .only("pk") + .iterator() + ) + + m2m_iter = getattr(obj, "_prefetched_objects_cache", {}).get( + field.name, + queryset_iterator(obj, field), + ) + for relobj in m2m_iter: + handle_m2m(relobj) + + self.xml.endElement("field") + + def _start_relational_field(self, field): + """Output the element for relational fields.""" + self.indent(2) + self.xml.startElement( + "field", + { + "name": field.name, + "rel": field.remote_field.__class__.__name__, + "to": str(field.remote_field.model._meta), + }, + ) + + +class Deserializer(base.Deserializer): + """Deserialize XML.""" + + def __init__( + self, + stream_or_string, + *, + using=DEFAULT_DB_ALIAS, + ignorenonexistent=False, + **options, + ): + super().__init__(stream_or_string, **options) + self.handle_forward_references = options.pop("handle_forward_references", False) + self.event_stream = pulldom.parse(self.stream, self._make_parser()) + self.db = using + self.ignore = ignorenonexistent + + def _make_parser(self): + """Create a hardened XML parser (no custom/external entities).""" + return DefusedExpatParser() + + def __next__(self): + for event, node in self.event_stream: + if event == "START_ELEMENT" and node.nodeName == "object": + self.event_stream.expandNode(node) + return self._handle_object(node) + raise StopIteration + + def _handle_object(self, node): + """Convert an node to a DeserializedObject.""" + # Look up the model using the model loading mechanism. If this fails, + # bail. + Model = self._get_model_from_node(node, "model") + + # Start building a data dictionary from the object. + data = {} + if node.hasAttribute("pk"): + data[Model._meta.pk.attname] = Model._meta.pk.to_python( + node.getAttribute("pk") + ) + + # Also start building a dict of m2m data (this is saved as + # {m2m_accessor_attribute : [list_of_related_objects]}) + m2m_data = {} + deferred_fields = {} + + field_names = {f.name for f in Model._meta.get_fields()} + # Deserialize each field. + for field_node in node.getElementsByTagName("field"): + # If the field is missing the name attribute, bail (are you + # sensing a pattern here?) + field_name = field_node.getAttribute("name") + if not field_name: + raise base.DeserializationError( + " node is missing the 'name' attribute" + ) + + # Get the field from the Model. This will raise a + # FieldDoesNotExist if, well, the field doesn't exist, which will + # be propagated correctly unless ignorenonexistent=True is used. + if self.ignore and field_name not in field_names: + continue + field = Model._meta.get_field(field_name) + + # As is usually the case, relation fields get the special treatment. + if field.remote_field and isinstance( + field.remote_field, models.ManyToManyRel + ): + value = self._handle_m2m_field_node(field_node, field) + if value == base.DEFER_FIELD: + deferred_fields[field] = [ + [ + getInnerText(nat_node).strip() + for nat_node in obj_node.getElementsByTagName("natural") + ] + for obj_node in field_node.getElementsByTagName("object") + ] + else: + m2m_data[field.name] = value + elif field.remote_field and isinstance( + field.remote_field, models.ManyToOneRel + ): + value = self._handle_fk_field_node(field_node, field) + if value == base.DEFER_FIELD: + deferred_fields[field] = [ + getInnerText(k).strip() + for k in field_node.getElementsByTagName("natural") + ] + else: + data[field.attname] = value + else: + if field_node.getElementsByTagName("None"): + value = None + else: + value = field.to_python(getInnerText(field_node).strip()) + # Load value since JSONField.to_python() outputs strings. + if field.get_internal_type() == "JSONField": + value = json.loads(value, cls=field.decoder) + data[field.name] = value + + obj = base.build_instance(Model, data, self.db) + + # Return a DeserializedObject so that the m2m data has a place to live. + return base.DeserializedObject(obj, m2m_data, deferred_fields) + + def _handle_fk_field_node(self, node, field): + """ + Handle a node for a ForeignKey + """ + # Check if there is a child node named 'None', returning None if so. + if node.getElementsByTagName("None"): + return None + else: + model = field.remote_field.model + if hasattr(model._default_manager, "get_by_natural_key"): + keys = node.getElementsByTagName("natural") + if keys: + # If there are 'natural' subelements, it must be a natural key + field_value = [getInnerText(k).strip() for k in keys] + try: + obj = model._default_manager.db_manager( + self.db + ).get_by_natural_key(*field_value) + except ObjectDoesNotExist: + if self.handle_forward_references: + return base.DEFER_FIELD + else: + raise + obj_pk = getattr(obj, field.remote_field.field_name) + # If this is a natural foreign key to an object that + # has a FK/O2O as the foreign key, use the FK value + if field.remote_field.model._meta.pk.remote_field: + obj_pk = obj_pk.pk + else: + # Otherwise, treat like a normal PK + field_value = getInnerText(node).strip() + obj_pk = model._meta.get_field( + field.remote_field.field_name + ).to_python(field_value) + return obj_pk + else: + field_value = getInnerText(node).strip() + return model._meta.get_field(field.remote_field.field_name).to_python( + field_value + ) + + def _handle_m2m_field_node(self, node, field): + """ + Handle a node for a ManyToManyField. + """ + model = field.remote_field.model + default_manager = model._default_manager + if hasattr(default_manager, "get_by_natural_key"): + + def m2m_convert(n): + keys = n.getElementsByTagName("natural") + if keys: + # If there are 'natural' subelements, it must be a natural key + field_value = [getInnerText(k).strip() for k in keys] + obj_pk = ( + default_manager.db_manager(self.db) + .get_by_natural_key(*field_value) + .pk + ) + else: + # Otherwise, treat like a normal PK value. + obj_pk = model._meta.pk.to_python(n.getAttribute("pk")) + return obj_pk + + else: + + def m2m_convert(n): + return model._meta.pk.to_python(n.getAttribute("pk")) + + values = [] + try: + for c in node.getElementsByTagName("object"): + values.append(m2m_convert(c)) + except Exception as e: + if isinstance(e, ObjectDoesNotExist) and self.handle_forward_references: + return base.DEFER_FIELD + else: + raise base.M2MDeserializationError(e, c) + else: + return values + + def _get_model_from_node(self, node, attr): + """ + Look up a model from a or a + node. + """ + model_identifier = node.getAttribute(attr) + if not model_identifier: + raise base.DeserializationError( + "<%s> node is missing the required '%s' attribute" + % (node.nodeName, attr) + ) + try: + return apps.get_model(model_identifier) + except (LookupError, TypeError): + raise base.DeserializationError( + "<%s> node has invalid model identifier: '%s'" + % (node.nodeName, model_identifier) + ) + + +def getInnerText(node): + """Get all the inner text of a DOM node (recursively).""" + # inspired by https://mail.python.org/pipermail/xml-sig/2005-March/011022.html + inner_text = [] + for child in node.childNodes: + if ( + child.nodeType == child.TEXT_NODE + or child.nodeType == child.CDATA_SECTION_NODE + ): + inner_text.append(child.data) + elif child.nodeType == child.ELEMENT_NODE: + inner_text.extend(getInnerText(child)) + else: + pass + return "".join(inner_text) + + +# Below code based on Christian Heimes' defusedxml + + +class DefusedExpatParser(_ExpatParser): + """ + An expat parser hardened against XML bomb attacks. + + Forbid DTDs, external entity references + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.setFeature(handler.feature_external_ges, False) + self.setFeature(handler.feature_external_pes, False) + + def start_doctype_decl(self, name, sysid, pubid, has_internal_subset): + raise DTDForbidden(name, sysid, pubid) + + def entity_decl( + self, name, is_parameter_entity, value, base, sysid, pubid, notation_name + ): + raise EntitiesForbidden(name, value, base, sysid, pubid, notation_name) + + def unparsed_entity_decl(self, name, base, sysid, pubid, notation_name): + # expat 1.2 + raise EntitiesForbidden(name, None, base, sysid, pubid, notation_name) + + def external_entity_ref_handler(self, context, base, sysid, pubid): + raise ExternalReferenceForbidden(context, base, sysid, pubid) + + def reset(self): + _ExpatParser.reset(self) + parser = self._parser + parser.StartDoctypeDeclHandler = self.start_doctype_decl + parser.EntityDeclHandler = self.entity_decl + parser.UnparsedEntityDeclHandler = self.unparsed_entity_decl + parser.ExternalEntityRefHandler = self.external_entity_ref_handler + + +class DefusedXmlException(ValueError): + """Base exception.""" + + def __repr__(self): + return str(self) + + +class DTDForbidden(DefusedXmlException): + """Document type definition is forbidden.""" + + def __init__(self, name, sysid, pubid): + super().__init__() + self.name = name + self.sysid = sysid + self.pubid = pubid + + def __str__(self): + tpl = "DTDForbidden(name='{}', system_id={!r}, public_id={!r})" + return tpl.format(self.name, self.sysid, self.pubid) + + +class EntitiesForbidden(DefusedXmlException): + """Entity definition is forbidden.""" + + def __init__(self, name, value, base, sysid, pubid, notation_name): + super().__init__() + self.name = name + self.value = value + self.base = base + self.sysid = sysid + self.pubid = pubid + self.notation_name = notation_name + + def __str__(self): + tpl = "EntitiesForbidden(name='{}', system_id={!r}, public_id={!r})" + return tpl.format(self.name, self.sysid, self.pubid) + + +class ExternalReferenceForbidden(DefusedXmlException): + """Resolving an external reference is forbidden.""" + + def __init__(self, context, base, sysid, pubid): + super().__init__() + self.context = context + self.base = base + self.sysid = sysid + self.pubid = pubid + + def __str__(self): + tpl = "ExternalReferenceForbidden(system_id='{}', public_id={})" + return tpl.format(self.sysid, self.pubid) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/servers/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/servers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/servers/basehttp.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/servers/basehttp.py new file mode 100644 index 0000000..6afe17c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/servers/basehttp.py @@ -0,0 +1,281 @@ +""" +HTTP server that implements the Python WSGI protocol (PEP 333, rev 1.21). + +Based on wsgiref.simple_server which is part of the standard library since 2.5. + +This is a simple server for use in testing or debugging Django apps. It hasn't +been reviewed for security issues. DON'T USE IT FOR PRODUCTION USE! +""" + +import logging +import socket +import socketserver +import sys +from collections import deque +from wsgiref import simple_server + +from django.core.exceptions import ImproperlyConfigured +from django.core.handlers.wsgi import LimitedStream +from django.core.wsgi import get_wsgi_application +from django.db import connections +from django.utils.module_loading import import_string + +__all__ = ("WSGIServer", "WSGIRequestHandler") + +logger = logging.getLogger("django.server") + + +def get_internal_wsgi_application(): + """ + Load and return the WSGI application as configured by the user in + ``settings.WSGI_APPLICATION``. With the default ``startproject`` layout, + this will be the ``application`` object in ``projectname/wsgi.py``. + + This function, and the ``WSGI_APPLICATION`` setting itself, are only useful + for Django's internal server (runserver); external WSGI servers should just + be configured to point to the correct application object directly. + + If settings.WSGI_APPLICATION is not set (is ``None``), return + whatever ``django.core.wsgi.get_wsgi_application`` returns. + """ + from django.conf import settings + + app_path = getattr(settings, "WSGI_APPLICATION") + if app_path is None: + return get_wsgi_application() + + try: + return import_string(app_path) + except ImportError as err: + raise ImproperlyConfigured( + "WSGI application '%s' could not be loaded; " + "Error importing module." % app_path + ) from err + + +def is_broken_pipe_error(): + exc_type, _, _ = sys.exc_info() + return issubclass( + exc_type, + ( + BrokenPipeError, + ConnectionAbortedError, + ConnectionResetError, + ), + ) + + +class WSGIServer(simple_server.WSGIServer): + """BaseHTTPServer that implements the Python WSGI protocol""" + + request_queue_size = 10 + + def __init__(self, *args, ipv6=False, allow_reuse_address=True, **kwargs): + if ipv6: + self.address_family = socket.AF_INET6 + self.allow_reuse_address = allow_reuse_address + super().__init__(*args, **kwargs) + + def handle_error(self, request, client_address): + if is_broken_pipe_error(): + logger.info("- Broken pipe from %s", client_address) + else: + super().handle_error(request, client_address) + + +class ThreadedWSGIServer(socketserver.ThreadingMixIn, WSGIServer): + """A threaded version of the WSGIServer""" + + daemon_threads = True + + def __init__(self, *args, connections_override=None, **kwargs): + super().__init__(*args, **kwargs) + self.connections_override = connections_override + + # socketserver.ThreadingMixIn.process_request() passes this method as + # the target to a new Thread object. + def process_request_thread(self, request, client_address): + if self.connections_override: + # Override this thread's database connections with the ones + # provided by the parent thread. + for alias, conn in self.connections_override.items(): + connections[alias] = conn + super().process_request_thread(request, client_address) + + def _close_connections(self): + # Used for mocking in tests. + connections.close_all() + + def close_request(self, request): + self._close_connections() + super().close_request(request) + + +class ServerHandler(simple_server.ServerHandler): + http_version = "1.1" + + def __init__(self, stdin, stdout, stderr, environ, **kwargs): + """ + Use a LimitedStream so that unread request data will be ignored at + the end of the request. WSGIRequest uses a LimitedStream but it + shouldn't discard the data since the upstream servers usually do this. + This fix applies only for testserver/runserver. + """ + try: + content_length = int(environ.get("CONTENT_LENGTH")) + except (ValueError, TypeError): + content_length = 0 + super().__init__( + LimitedStream(stdin, content_length), stdout, stderr, environ, **kwargs + ) + + def cleanup_headers(self): + super().cleanup_headers() + if ( + self.environ["REQUEST_METHOD"] == "HEAD" + and "Content-Length" in self.headers + ): + del self.headers["Content-Length"] + # HTTP/1.1 requires support for persistent connections. Send 'close' if + # the content length is unknown to prevent clients from reusing the + # connection. + if ( + self.environ["REQUEST_METHOD"] != "HEAD" + and "Content-Length" not in self.headers + ): + self.headers["Connection"] = "close" + # Persistent connections require threading server. + elif not isinstance(self.request_handler.server, socketserver.ThreadingMixIn): + self.headers["Connection"] = "close" + # Mark the connection for closing if it's set as such above or if the + # application sent the header. + if self.headers.get("Connection") == "close": + self.request_handler.close_connection = True + + def close(self): + self.get_stdin().read() + super().close() + + def finish_response(self): + if self.environ["REQUEST_METHOD"] == "HEAD": + try: + deque(self.result, maxlen=0) # Consume iterator. + # Don't call self.finish_content() as, if the headers have not + # been sent and Content-Length isn't set, it'll default to "0" + # which will prevent omission of the Content-Length header with + # HEAD requests as permitted by RFC 9110 Section 9.3.2. + # Instead, send the headers, if not sent yet. + if not self.headers_sent: + self.send_headers() + finally: + self.close() + else: + super().finish_response() + + +class WSGIRequestHandler(simple_server.WSGIRequestHandler): + protocol_version = "HTTP/1.1" + + def address_string(self): + # Short-circuit parent method to not call socket.getfqdn + return self.client_address[0] + + def log_message(self, format, *args): + extra = { + "request": self.request, + "server_time": self.log_date_time_string(), + } + if args[1][0] == "4": + # 0x16 = Handshake, 0x03 = SSL 3.0 or TLS 1.x + if args[0].startswith("\x16\x03"): + extra["status_code"] = 500 + logger.error( + "You're accessing the development server over HTTPS, but " + "it only supports HTTP.", + extra=extra, + ) + return + + if args[1].isdigit() and len(args[1]) == 3: + status_code = int(args[1]) + extra["status_code"] = status_code + + if status_code >= 500: + level = logger.error + elif status_code >= 400: + level = logger.warning + else: + level = logger.info + else: + level = logger.info + + level(format, *args, extra=extra) + + def get_environ(self): + # Strip all headers with underscores in the name before constructing + # the WSGI environ. This prevents header-spoofing based on ambiguity + # between underscores and dashes both normalized to underscores in WSGI + # env vars. Nginx and Apache 2.4+ both do this as well. + for k in self.headers: + if "_" in k: + del self.headers[k] + + return super().get_environ() + + def handle(self): + self.close_connection = True + self.handle_one_request() + while not self.close_connection: + self.handle_one_request() + try: + self.connection.shutdown(socket.SHUT_WR) + except (AttributeError, OSError): + pass + + def handle_one_request(self): + """Copy of WSGIRequestHandler.handle() but with different ServerHandler""" + self.raw_requestline = self.rfile.readline(65537) + if len(self.raw_requestline) > 65536: + self.requestline = "" + self.request_version = "" + self.command = "" + self.send_error(414) + return + + if not self.parse_request(): # An error code has been sent, just exit + return + + handler = ServerHandler( + self.rfile, self.wfile, self.get_stderr(), self.get_environ() + ) + handler.request_handler = self # backpointer for logging & connection closing + handler.run(self.server.get_app()) + + +def run( + addr, + port, + wsgi_handler, + ipv6=False, + threading=False, + on_bind=None, + server_cls=WSGIServer, +): + server_address = (addr, port) + if threading: + httpd_cls = type("WSGIServer", (socketserver.ThreadingMixIn, server_cls), {}) + else: + httpd_cls = server_cls + httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=ipv6) + if on_bind is not None: + on_bind(getattr(httpd, "server_port", port)) + if threading: + # ThreadingMixIn.daemon_threads indicates how threads will behave on an + # abrupt shutdown; like quitting the server by the user or restarting + # by the auto-reloader. True means the server will not wait for thread + # termination before it quits. This will make auto-reloader faster + # and will prevent the need to kill the server manually if a thread + # isn't terminating correctly. + httpd.daemon_threads = True + httpd.set_app(wsgi_handler) + httpd.serve_forever() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/signals.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/signals.py new file mode 100644 index 0000000..960f5c3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/signals.py @@ -0,0 +1,6 @@ +from django.dispatch import Signal + +request_started = Signal() +request_finished = Signal() +got_request_exception = Signal() +setting_changed = Signal() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/signing.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/signing.py new file mode 100644 index 0000000..5521493 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/signing.py @@ -0,0 +1,302 @@ +""" +Functions for creating and restoring url-safe signed JSON objects. + +The format used looks like this: + +>>> signing.dumps("hello") +'ImhlbGxvIg:1QaUZC:YIye-ze3TTx7gtSv422nZA4sgmk' + +There are two components here, separated by a ':'. The first component is a +URLsafe base64 encoded JSON of the object passed to dumps(). The second +component is a base64 encoded hmac/SHA-256 hash of "$first_component:$secret" + +signing.loads(s) checks the signature and returns the deserialized object. +If the signature fails, a BadSignature exception is raised. + +>>> signing.loads("ImhlbGxvIg:1QaUZC:YIye-ze3TTx7gtSv422nZA4sgmk") +'hello' +>>> signing.loads("ImhlbGxvIg:1QaUZC:YIye-ze3TTx7gtSv42-modified") +... +BadSignature: Signature "ImhlbGxvIg:1QaUZC:YIye-ze3TTx7gtSv42-modified" does not match + +You can optionally compress the JSON prior to base64 encoding it to save +space, using the compress=True argument. This checks if compression actually +helps and only applies compression if the result is a shorter string: + +>>> signing.dumps(list(range(1, 20)), compress=True) +'.eJwFwcERACAIwLCF-rCiILN47r-GyZVJsNgkxaFxoDgxcOHGxMKD_T7vhAml:1QaUaL:BA0thEZrp4FQVXIXuOvYJtLJSrQ' + +The fact that the string is compressed is signalled by the prefixed '.' at the +start of the base64 JSON. + +There are 65 url-safe characters: the 64 used by url-safe base64 and the ':'. +These functions make use of all of them. +""" + +import base64 +import datetime +import json +import time +import warnings +import zlib + +from django.conf import settings +from django.utils.crypto import constant_time_compare, salted_hmac +from django.utils.deprecation import RemovedInDjango51Warning +from django.utils.encoding import force_bytes +from django.utils.module_loading import import_string +from django.utils.regex_helper import _lazy_re_compile + +_SEP_UNSAFE = _lazy_re_compile(r"^[A-z0-9-_=]*$") +BASE62_ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + + +class BadSignature(Exception): + """Signature does not match.""" + + pass + + +class SignatureExpired(BadSignature): + """Signature timestamp is older than required max_age.""" + + pass + + +def b62_encode(s): + if s == 0: + return "0" + sign = "-" if s < 0 else "" + s = abs(s) + encoded = "" + while s > 0: + s, remainder = divmod(s, 62) + encoded = BASE62_ALPHABET[remainder] + encoded + return sign + encoded + + +def b62_decode(s): + if s == "0": + return 0 + sign = 1 + if s[0] == "-": + s = s[1:] + sign = -1 + decoded = 0 + for digit in s: + decoded = decoded * 62 + BASE62_ALPHABET.index(digit) + return sign * decoded + + +def b64_encode(s): + return base64.urlsafe_b64encode(s).strip(b"=") + + +def b64_decode(s): + pad = b"=" * (-len(s) % 4) + return base64.urlsafe_b64decode(s + pad) + + +def base64_hmac(salt, value, key, algorithm="sha1"): + return b64_encode( + salted_hmac(salt, value, key, algorithm=algorithm).digest() + ).decode() + + +def _cookie_signer_key(key): + # SECRET_KEYS items may be str or bytes. + return b"django.http.cookies" + force_bytes(key) + + +def get_cookie_signer(salt="django.core.signing.get_cookie_signer"): + Signer = import_string(settings.SIGNING_BACKEND) + return Signer( + key=_cookie_signer_key(settings.SECRET_KEY), + fallback_keys=map(_cookie_signer_key, settings.SECRET_KEY_FALLBACKS), + salt=salt, + ) + + +class JSONSerializer: + """ + Simple wrapper around json to be used in signing.dumps and + signing.loads. + """ + + def dumps(self, obj): + return json.dumps(obj, separators=(",", ":")).encode("latin-1") + + def loads(self, data): + return json.loads(data.decode("latin-1")) + + +def dumps( + obj, key=None, salt="django.core.signing", serializer=JSONSerializer, compress=False +): + """ + Return URL-safe, hmac signed base64 compressed JSON string. If key is + None, use settings.SECRET_KEY instead. The hmac algorithm is the default + Signer algorithm. + + If compress is True (not the default), check if compressing using zlib can + save some space. Prepend a '.' to signify compression. This is included + in the signature, to protect against zip bombs. + + Salt can be used to namespace the hash, so that a signed string is + only valid for a given namespace. Leaving this at the default + value or re-using a salt value across different parts of your + application without good cause is a security risk. + + The serializer is expected to return a bytestring. + """ + return TimestampSigner(key=key, salt=salt).sign_object( + obj, serializer=serializer, compress=compress + ) + + +def loads( + s, + key=None, + salt="django.core.signing", + serializer=JSONSerializer, + max_age=None, + fallback_keys=None, +): + """ + Reverse of dumps(), raise BadSignature if signature fails. + + The serializer is expected to accept a bytestring. + """ + return TimestampSigner( + key=key, salt=salt, fallback_keys=fallback_keys + ).unsign_object( + s, + serializer=serializer, + max_age=max_age, + ) + + +class Signer: + # RemovedInDjango51Warning: When the deprecation ends, replace with: + # def __init__( + # self, *, key=None, sep=":", salt=None, algorithm=None, fallback_keys=None + # ): + def __init__( + self, + *args, + key=None, + sep=":", + salt=None, + algorithm=None, + fallback_keys=None, + ): + self.key = key or settings.SECRET_KEY + self.fallback_keys = ( + fallback_keys + if fallback_keys is not None + else settings.SECRET_KEY_FALLBACKS + ) + self.sep = sep + self.salt = salt or "%s.%s" % ( + self.__class__.__module__, + self.__class__.__name__, + ) + self.algorithm = algorithm or "sha256" + # RemovedInDjango51Warning. + if args: + warnings.warn( + f"Passing positional arguments to {self.__class__.__name__} is " + f"deprecated.", + RemovedInDjango51Warning, + stacklevel=2, + ) + for arg, attr in zip( + args, ["key", "sep", "salt", "algorithm", "fallback_keys"] + ): + if arg or attr == "sep": + setattr(self, attr, arg) + if _SEP_UNSAFE.match(self.sep): + raise ValueError( + "Unsafe Signer separator: %r (cannot be empty or consist of " + "only A-z0-9-_=)" % sep, + ) + + def signature(self, value, key=None): + key = key or self.key + return base64_hmac(self.salt + "signer", value, key, algorithm=self.algorithm) + + def sign(self, value): + return "%s%s%s" % (value, self.sep, self.signature(value)) + + def unsign(self, signed_value): + if self.sep not in signed_value: + raise BadSignature('No "%s" found in value' % self.sep) + value, sig = signed_value.rsplit(self.sep, 1) + for key in [self.key, *self.fallback_keys]: + if constant_time_compare(sig, self.signature(value, key)): + return value + raise BadSignature('Signature "%s" does not match' % sig) + + def sign_object(self, obj, serializer=JSONSerializer, compress=False): + """ + Return URL-safe, hmac signed base64 compressed JSON string. + + If compress is True (not the default), check if compressing using zlib + can save some space. Prepend a '.' to signify compression. This is + included in the signature, to protect against zip bombs. + + The serializer is expected to return a bytestring. + """ + data = serializer().dumps(obj) + # Flag for if it's been compressed or not. + is_compressed = False + + if compress: + # Avoid zlib dependency unless compress is being used. + compressed = zlib.compress(data) + if len(compressed) < (len(data) - 1): + data = compressed + is_compressed = True + base64d = b64_encode(data).decode() + if is_compressed: + base64d = "." + base64d + return self.sign(base64d) + + def unsign_object(self, signed_obj, serializer=JSONSerializer, **kwargs): + # Signer.unsign() returns str but base64 and zlib compression operate + # on bytes. + base64d = self.unsign(signed_obj, **kwargs).encode() + decompress = base64d[:1] == b"." + if decompress: + # It's compressed; uncompress it first. + base64d = base64d[1:] + data = b64_decode(base64d) + if decompress: + data = zlib.decompress(data) + return serializer().loads(data) + + +class TimestampSigner(Signer): + def timestamp(self): + return b62_encode(int(time.time())) + + def sign(self, value): + value = "%s%s%s" % (value, self.sep, self.timestamp()) + return super().sign(value) + + def unsign(self, value, max_age=None): + """ + Retrieve original value and check it wasn't signed more + than max_age seconds ago. + """ + result = super().unsign(value) + value, timestamp = result.rsplit(self.sep, 1) + timestamp = b62_decode(timestamp) + if max_age is not None: + if isinstance(max_age, datetime.timedelta): + max_age = max_age.total_seconds() + # Check timestamp is not older than max_age + age = time.time() - timestamp + if age > max_age: + raise SignatureExpired("Signature age %s > %s seconds" % (age, max_age)) + return value diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/validators.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/validators.py new file mode 100644 index 0000000..fe8d465 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/validators.py @@ -0,0 +1,642 @@ +import ipaddress +import math +import re +from pathlib import Path +from urllib.parse import urlsplit, urlunsplit + +from django.core.exceptions import ValidationError +from django.utils.deconstruct import deconstructible +from django.utils.encoding import punycode +from django.utils.ipv6 import is_valid_ipv6_address +from django.utils.regex_helper import _lazy_re_compile +from django.utils.translation import gettext_lazy as _ +from django.utils.translation import ngettext_lazy + +# These values, if given to validate(), will trigger the self.required check. +EMPTY_VALUES = (None, "", [], (), {}) + + +@deconstructible +class RegexValidator: + regex = "" + message = _("Enter a valid value.") + code = "invalid" + inverse_match = False + flags = 0 + + def __init__( + self, regex=None, message=None, code=None, inverse_match=None, flags=None + ): + if regex is not None: + self.regex = regex + if message is not None: + self.message = message + if code is not None: + self.code = code + if inverse_match is not None: + self.inverse_match = inverse_match + if flags is not None: + self.flags = flags + if self.flags and not isinstance(self.regex, str): + raise TypeError( + "If the flags are set, regex must be a regular expression string." + ) + + self.regex = _lazy_re_compile(self.regex, self.flags) + + def __call__(self, value): + """ + Validate that the input contains (or does *not* contain, if + inverse_match is True) a match for the regular expression. + """ + regex_matches = self.regex.search(str(value)) + invalid_input = regex_matches if self.inverse_match else not regex_matches + if invalid_input: + raise ValidationError(self.message, code=self.code, params={"value": value}) + + def __eq__(self, other): + return ( + isinstance(other, RegexValidator) + and self.regex.pattern == other.regex.pattern + and self.regex.flags == other.regex.flags + and (self.message == other.message) + and (self.code == other.code) + and (self.inverse_match == other.inverse_match) + ) + + +@deconstructible +class URLValidator(RegexValidator): + ul = "\u00a1-\uffff" # Unicode letters range (must not be a raw string). + + # IP patterns + ipv4_re = ( + r"(?:0|25[0-5]|2[0-4][0-9]|1[0-9]?[0-9]?|[1-9][0-9]?)" + r"(?:\.(?:0|25[0-5]|2[0-4][0-9]|1[0-9]?[0-9]?|[1-9][0-9]?)){3}" + ) + ipv6_re = r"\[[0-9a-f:.]+\]" # (simple regex, validated later) + + # Host patterns + hostname_re = ( + r"[a-z" + ul + r"0-9](?:[a-z" + ul + r"0-9-]{0,61}[a-z" + ul + r"0-9])?" + ) + # Max length for domain name labels is 63 characters per RFC 1034 sec. 3.1 + domain_re = r"(?:\.(?!-)[a-z" + ul + r"0-9-]{1,63}(? self.max_length: + raise ValidationError(self.message, code=self.code, params={"value": value}) + if self.unsafe_chars.intersection(value): + raise ValidationError(self.message, code=self.code, params={"value": value}) + # Check if the scheme is valid. + scheme = value.split("://")[0].lower() + if scheme not in self.schemes: + raise ValidationError(self.message, code=self.code, params={"value": value}) + + # Then check full URL + try: + splitted_url = urlsplit(value) + except ValueError: + raise ValidationError(self.message, code=self.code, params={"value": value}) + try: + super().__call__(value) + except ValidationError as e: + # Trivial case failed. Try for possible IDN domain + if value: + scheme, netloc, path, query, fragment = splitted_url + try: + netloc = punycode(netloc) # IDN -> ACE + except UnicodeError: # invalid domain part + raise e + url = urlunsplit((scheme, netloc, path, query, fragment)) + super().__call__(url) + else: + raise + else: + # Now verify IPv6 in the netloc part + host_match = re.search(r"^\[(.+)\](?::[0-9]{1,5})?$", splitted_url.netloc) + if host_match: + potential_ip = host_match[1] + try: + validate_ipv6_address(potential_ip) + except ValidationError: + raise ValidationError( + self.message, code=self.code, params={"value": value} + ) + + # The maximum length of a full host name is 253 characters per RFC 1034 + # section 3.1. It's defined to be 255 bytes or less, but this includes + # one byte for the length of the name and one byte for the trailing dot + # that's used to indicate absolute names in DNS. + if splitted_url.hostname is None or len(splitted_url.hostname) > 253: + raise ValidationError(self.message, code=self.code, params={"value": value}) + + +integer_validator = RegexValidator( + _lazy_re_compile(r"^-?\d+\Z"), + message=_("Enter a valid integer."), + code="invalid", +) + + +def validate_integer(value): + return integer_validator(value) + + +@deconstructible +class EmailValidator: + message = _("Enter a valid email address.") + code = "invalid" + user_regex = _lazy_re_compile( + # dot-atom + r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*\Z" + # quoted-string + r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])' + r'*"\Z)', + re.IGNORECASE, + ) + domain_regex = _lazy_re_compile( + # max length for domain name labels is 63 characters per RFC 1034 + r"((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+)(?:[A-Z0-9-]{2,63}(? 320: + raise ValidationError(self.message, code=self.code, params={"value": value}) + + user_part, domain_part = value.rsplit("@", 1) + + if not self.user_regex.match(user_part): + raise ValidationError(self.message, code=self.code, params={"value": value}) + + if domain_part not in self.domain_allowlist and not self.validate_domain_part( + domain_part + ): + # Try for possible IDN domain-part + try: + domain_part = punycode(domain_part) + except UnicodeError: + pass + else: + if self.validate_domain_part(domain_part): + return + raise ValidationError(self.message, code=self.code, params={"value": value}) + + def validate_domain_part(self, domain_part): + if self.domain_regex.match(domain_part): + return True + + literal_match = self.literal_regex.match(domain_part) + if literal_match: + ip_address = literal_match[1] + try: + validate_ipv46_address(ip_address) + return True + except ValidationError: + pass + return False + + def __eq__(self, other): + return ( + isinstance(other, EmailValidator) + and (self.domain_allowlist == other.domain_allowlist) + and (self.message == other.message) + and (self.code == other.code) + ) + + +validate_email = EmailValidator() + +slug_re = _lazy_re_compile(r"^[-a-zA-Z0-9_]+\Z") +validate_slug = RegexValidator( + slug_re, + # Translators: "letters" means latin letters: a-z and A-Z. + _("Enter a valid “slug” consisting of letters, numbers, underscores or hyphens."), + "invalid", +) + +slug_unicode_re = _lazy_re_compile(r"^[-\w]+\Z") +validate_unicode_slug = RegexValidator( + slug_unicode_re, + _( + "Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or " + "hyphens." + ), + "invalid", +) + + +def validate_ipv4_address(value): + try: + ipaddress.IPv4Address(value) + except ValueError: + raise ValidationError( + _("Enter a valid IPv4 address."), code="invalid", params={"value": value} + ) + + +def validate_ipv6_address(value): + if not is_valid_ipv6_address(value): + raise ValidationError( + _("Enter a valid IPv6 address."), code="invalid", params={"value": value} + ) + + +def validate_ipv46_address(value): + try: + validate_ipv4_address(value) + except ValidationError: + try: + validate_ipv6_address(value) + except ValidationError: + raise ValidationError( + _("Enter a valid IPv4 or IPv6 address."), + code="invalid", + params={"value": value}, + ) + + +ip_address_validator_map = { + "both": ([validate_ipv46_address], _("Enter a valid IPv4 or IPv6 address.")), + "ipv4": ([validate_ipv4_address], _("Enter a valid IPv4 address.")), + "ipv6": ([validate_ipv6_address], _("Enter a valid IPv6 address.")), +} + + +def ip_address_validators(protocol, unpack_ipv4): + """ + Depending on the given parameters, return the appropriate validators for + the GenericIPAddressField. + """ + if protocol != "both" and unpack_ipv4: + raise ValueError( + "You can only use `unpack_ipv4` if `protocol` is set to 'both'" + ) + try: + return ip_address_validator_map[protocol.lower()] + except KeyError: + raise ValueError( + "The protocol '%s' is unknown. Supported: %s" + % (protocol, list(ip_address_validator_map)) + ) + + +def int_list_validator(sep=",", message=None, code="invalid", allow_negative=False): + regexp = _lazy_re_compile( + r"^%(neg)s\d+(?:%(sep)s%(neg)s\d+)*\Z" + % { + "neg": "(-)?" if allow_negative else "", + "sep": re.escape(sep), + } + ) + return RegexValidator(regexp, message=message, code=code) + + +validate_comma_separated_integer_list = int_list_validator( + message=_("Enter only digits separated by commas."), +) + + +@deconstructible +class BaseValidator: + message = _("Ensure this value is %(limit_value)s (it is %(show_value)s).") + code = "limit_value" + + def __init__(self, limit_value, message=None): + self.limit_value = limit_value + if message: + self.message = message + + def __call__(self, value): + cleaned = self.clean(value) + limit_value = ( + self.limit_value() if callable(self.limit_value) else self.limit_value + ) + params = {"limit_value": limit_value, "show_value": cleaned, "value": value} + if self.compare(cleaned, limit_value): + raise ValidationError(self.message, code=self.code, params=params) + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return ( + self.limit_value == other.limit_value + and self.message == other.message + and self.code == other.code + ) + + def compare(self, a, b): + return a is not b + + def clean(self, x): + return x + + +@deconstructible +class MaxValueValidator(BaseValidator): + message = _("Ensure this value is less than or equal to %(limit_value)s.") + code = "max_value" + + def compare(self, a, b): + return a > b + + +@deconstructible +class MinValueValidator(BaseValidator): + message = _("Ensure this value is greater than or equal to %(limit_value)s.") + code = "min_value" + + def compare(self, a, b): + return a < b + + +@deconstructible +class StepValueValidator(BaseValidator): + message = _("Ensure this value is a multiple of step size %(limit_value)s.") + code = "step_size" + + def __init__(self, limit_value, message=None, offset=None): + super().__init__(limit_value, message) + if offset is not None: + self.message = _( + "Ensure this value is a multiple of step size %(limit_value)s, " + "starting from %(offset)s, e.g. %(offset)s, %(valid_value1)s, " + "%(valid_value2)s, and so on." + ) + self.offset = offset + + def __call__(self, value): + if self.offset is None: + super().__call__(value) + else: + cleaned = self.clean(value) + limit_value = ( + self.limit_value() if callable(self.limit_value) else self.limit_value + ) + if self.compare(cleaned, limit_value): + offset = cleaned.__class__(self.offset) + params = { + "limit_value": limit_value, + "offset": offset, + "valid_value1": offset + limit_value, + "valid_value2": offset + 2 * limit_value, + } + raise ValidationError(self.message, code=self.code, params=params) + + def compare(self, a, b): + offset = 0 if self.offset is None else self.offset + return not math.isclose(math.remainder(a - offset, b), 0, abs_tol=1e-9) + + +@deconstructible +class MinLengthValidator(BaseValidator): + message = ngettext_lazy( + "Ensure this value has at least %(limit_value)d character (it has " + "%(show_value)d).", + "Ensure this value has at least %(limit_value)d characters (it has " + "%(show_value)d).", + "limit_value", + ) + code = "min_length" + + def compare(self, a, b): + return a < b + + def clean(self, x): + return len(x) + + +@deconstructible +class MaxLengthValidator(BaseValidator): + message = ngettext_lazy( + "Ensure this value has at most %(limit_value)d character (it has " + "%(show_value)d).", + "Ensure this value has at most %(limit_value)d characters (it has " + "%(show_value)d).", + "limit_value", + ) + code = "max_length" + + def compare(self, a, b): + return a > b + + def clean(self, x): + return len(x) + + +@deconstructible +class DecimalValidator: + """ + Validate that the input does not exceed the maximum number of digits + expected, otherwise raise ValidationError. + """ + + messages = { + "invalid": _("Enter a number."), + "max_digits": ngettext_lazy( + "Ensure that there are no more than %(max)s digit in total.", + "Ensure that there are no more than %(max)s digits in total.", + "max", + ), + "max_decimal_places": ngettext_lazy( + "Ensure that there are no more than %(max)s decimal place.", + "Ensure that there are no more than %(max)s decimal places.", + "max", + ), + "max_whole_digits": ngettext_lazy( + "Ensure that there are no more than %(max)s digit before the decimal " + "point.", + "Ensure that there are no more than %(max)s digits before the decimal " + "point.", + "max", + ), + } + + def __init__(self, max_digits, decimal_places): + self.max_digits = max_digits + self.decimal_places = decimal_places + + def __call__(self, value): + digit_tuple, exponent = value.as_tuple()[1:] + if exponent in {"F", "n", "N"}: + raise ValidationError( + self.messages["invalid"], code="invalid", params={"value": value} + ) + if exponent >= 0: + digits = len(digit_tuple) + if digit_tuple != (0,): + # A positive exponent adds that many trailing zeros. + digits += exponent + decimals = 0 + else: + # If the absolute value of the negative exponent is larger than the + # number of digits, then it's the same as the number of digits, + # because it'll consume all of the digits in digit_tuple and then + # add abs(exponent) - len(digit_tuple) leading zeros after the + # decimal point. + if abs(exponent) > len(digit_tuple): + digits = decimals = abs(exponent) + else: + digits = len(digit_tuple) + decimals = abs(exponent) + whole_digits = digits - decimals + + if self.max_digits is not None and digits > self.max_digits: + raise ValidationError( + self.messages["max_digits"], + code="max_digits", + params={"max": self.max_digits, "value": value}, + ) + if self.decimal_places is not None and decimals > self.decimal_places: + raise ValidationError( + self.messages["max_decimal_places"], + code="max_decimal_places", + params={"max": self.decimal_places, "value": value}, + ) + if ( + self.max_digits is not None + and self.decimal_places is not None + and whole_digits > (self.max_digits - self.decimal_places) + ): + raise ValidationError( + self.messages["max_whole_digits"], + code="max_whole_digits", + params={"max": (self.max_digits - self.decimal_places), "value": value}, + ) + + def __eq__(self, other): + return ( + isinstance(other, self.__class__) + and self.max_digits == other.max_digits + and self.decimal_places == other.decimal_places + ) + + +@deconstructible +class FileExtensionValidator: + message = _( + "File extension “%(extension)s” is not allowed. " + "Allowed extensions are: %(allowed_extensions)s." + ) + code = "invalid_extension" + + def __init__(self, allowed_extensions=None, message=None, code=None): + if allowed_extensions is not None: + allowed_extensions = [ + allowed_extension.lower() for allowed_extension in allowed_extensions + ] + self.allowed_extensions = allowed_extensions + if message is not None: + self.message = message + if code is not None: + self.code = code + + def __call__(self, value): + extension = Path(value.name).suffix[1:].lower() + if ( + self.allowed_extensions is not None + and extension not in self.allowed_extensions + ): + raise ValidationError( + self.message, + code=self.code, + params={ + "extension": extension, + "allowed_extensions": ", ".join(self.allowed_extensions), + "value": value, + }, + ) + + def __eq__(self, other): + return ( + isinstance(other, self.__class__) + and self.allowed_extensions == other.allowed_extensions + and self.message == other.message + and self.code == other.code + ) + + +def get_available_image_extensions(): + try: + from PIL import Image + except ImportError: + return [] + else: + Image.init() + return [ext.lower()[1:] for ext in Image.EXTENSION] + + +def validate_image_file_extension(value): + return FileExtensionValidator(allowed_extensions=get_available_image_extensions())( + value + ) + + +@deconstructible +class ProhibitNullCharactersValidator: + """Validate that the string doesn't contain the null character.""" + + message = _("Null characters are not allowed.") + code = "null_characters_not_allowed" + + def __init__(self, message=None, code=None): + if message is not None: + self.message = message + if code is not None: + self.code = code + + def __call__(self, value): + if "\x00" in str(value): + raise ValidationError(self.message, code=self.code, params={"value": value}) + + def __eq__(self, other): + return ( + isinstance(other, self.__class__) + and self.message == other.message + and self.code == other.code + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/wsgi.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/wsgi.py new file mode 100644 index 0000000..35e0fa8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/core/wsgi.py @@ -0,0 +1,13 @@ +import django +from django.core.handlers.wsgi import WSGIHandler + + +def get_wsgi_application(): + """ + The public interface to Django's WSGI support. Return a WSGI callable. + + Avoids making django.core.handlers.WSGIHandler a public API, in case the + internal WSGI implementation changes or moves in the future. + """ + django.setup(set_prefix=False) + return WSGIHandler() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/__init__.py new file mode 100644 index 0000000..f3cf457 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/__init__.py @@ -0,0 +1,61 @@ +from django.core import signals +from django.db.utils import ( + DEFAULT_DB_ALIAS, + DJANGO_VERSION_PICKLE_KEY, + ConnectionHandler, + ConnectionRouter, + DatabaseError, + DataError, + Error, + IntegrityError, + InterfaceError, + InternalError, + NotSupportedError, + OperationalError, + ProgrammingError, +) +from django.utils.connection import ConnectionProxy + +__all__ = [ + "connection", + "connections", + "router", + "DatabaseError", + "IntegrityError", + "InternalError", + "ProgrammingError", + "DataError", + "NotSupportedError", + "Error", + "InterfaceError", + "OperationalError", + "DEFAULT_DB_ALIAS", + "DJANGO_VERSION_PICKLE_KEY", +] + +connections = ConnectionHandler() + +router = ConnectionRouter() + +# For backwards compatibility. Prefer connections['default'] instead. +connection = ConnectionProxy(connections, DEFAULT_DB_ALIAS) + + +# Register an event to reset saved queries when a Django request is started. +def reset_queries(**kwargs): + for conn in connections.all(initialized_only=True): + conn.queries_log.clear() + + +signals.request_started.connect(reset_queries) + + +# Register an event to reset transaction state and close connections past +# their lifetime. +def close_old_connections(**kwargs): + for conn in connections.all(initialized_only=True): + conn.close_if_unusable_or_obsolete() + + +signals.request_started.connect(close_old_connections) +signals.request_finished.connect(close_old_connections) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/base.py new file mode 100644 index 0000000..84b9974 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/base.py @@ -0,0 +1,788 @@ +import _thread +import copy +import datetime +import logging +import threading +import time +import warnings +import zoneinfo +from collections import deque +from contextlib import contextmanager + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.db import DEFAULT_DB_ALIAS, DatabaseError, NotSupportedError +from django.db.backends import utils +from django.db.backends.base.validation import BaseDatabaseValidation +from django.db.backends.signals import connection_created +from django.db.backends.utils import debug_transaction +from django.db.transaction import TransactionManagementError +from django.db.utils import DatabaseErrorWrapper +from django.utils.asyncio import async_unsafe +from django.utils.functional import cached_property + +NO_DB_ALIAS = "__no_db__" +RAN_DB_VERSION_CHECK = set() + +logger = logging.getLogger("django.db.backends.base") + + +class BaseDatabaseWrapper: + """Represent a database connection.""" + + # Mapping of Field objects to their column types. + data_types = {} + # Mapping of Field objects to their SQL suffix such as AUTOINCREMENT. + data_types_suffix = {} + # Mapping of Field objects to their SQL for CHECK constraints. + data_type_check_constraints = {} + ops = None + vendor = "unknown" + display_name = "unknown" + SchemaEditorClass = None + # Classes instantiated in __init__(). + client_class = None + creation_class = None + features_class = None + introspection_class = None + ops_class = None + validation_class = BaseDatabaseValidation + + queries_limit = 9000 + + def __init__(self, settings_dict, alias=DEFAULT_DB_ALIAS): + # Connection related attributes. + # The underlying database connection. + self.connection = None + # `settings_dict` should be a dictionary containing keys such as + # NAME, USER, etc. It's called `settings_dict` instead of `settings` + # to disambiguate it from Django settings modules. + self.settings_dict = settings_dict + self.alias = alias + # Query logging in debug mode or when explicitly enabled. + self.queries_log = deque(maxlen=self.queries_limit) + self.force_debug_cursor = False + + # Transaction related attributes. + # Tracks if the connection is in autocommit mode. Per PEP 249, by + # default, it isn't. + self.autocommit = False + # Tracks if the connection is in a transaction managed by 'atomic'. + self.in_atomic_block = False + # Increment to generate unique savepoint ids. + self.savepoint_state = 0 + # List of savepoints created by 'atomic'. + self.savepoint_ids = [] + # Stack of active 'atomic' blocks. + self.atomic_blocks = [] + # Tracks if the outermost 'atomic' block should commit on exit, + # ie. if autocommit was active on entry. + self.commit_on_exit = True + # Tracks if the transaction should be rolled back to the next + # available savepoint because of an exception in an inner block. + self.needs_rollback = False + self.rollback_exc = None + + # Connection termination related attributes. + self.close_at = None + self.closed_in_transaction = False + self.errors_occurred = False + self.health_check_enabled = False + self.health_check_done = False + + # Thread-safety related attributes. + self._thread_sharing_lock = threading.Lock() + self._thread_sharing_count = 0 + self._thread_ident = _thread.get_ident() + + # A list of no-argument functions to run when the transaction commits. + # Each entry is an (sids, func, robust) tuple, where sids is a set of + # the active savepoint IDs when this function was registered and robust + # specifies whether it's allowed for the function to fail. + self.run_on_commit = [] + + # Should we run the on-commit hooks the next time set_autocommit(True) + # is called? + self.run_commit_hooks_on_set_autocommit_on = False + + # A stack of wrappers to be invoked around execute()/executemany() + # calls. Each entry is a function taking five arguments: execute, sql, + # params, many, and context. It's the function's responsibility to + # call execute(sql, params, many, context). + self.execute_wrappers = [] + + self.client = self.client_class(self) + self.creation = self.creation_class(self) + self.features = self.features_class(self) + self.introspection = self.introspection_class(self) + self.ops = self.ops_class(self) + self.validation = self.validation_class(self) + + def __repr__(self): + return ( + f"<{self.__class__.__qualname__} " + f"vendor={self.vendor!r} alias={self.alias!r}>" + ) + + def ensure_timezone(self): + """ + Ensure the connection's timezone is set to `self.timezone_name` and + return whether it changed or not. + """ + return False + + @cached_property + def timezone(self): + """ + Return a tzinfo of the database connection time zone. + + This is only used when time zone support is enabled. When a datetime is + read from the database, it is always returned in this time zone. + + When the database backend supports time zones, it doesn't matter which + time zone Django uses, as long as aware datetimes are used everywhere. + Other users connecting to the database can choose their own time zone. + + When the database backend doesn't support time zones, the time zone + Django uses may be constrained by the requirements of other users of + the database. + """ + if not settings.USE_TZ: + return None + elif self.settings_dict["TIME_ZONE"] is None: + return datetime.timezone.utc + else: + return zoneinfo.ZoneInfo(self.settings_dict["TIME_ZONE"]) + + @cached_property + def timezone_name(self): + """ + Name of the time zone of the database connection. + """ + if not settings.USE_TZ: + return settings.TIME_ZONE + elif self.settings_dict["TIME_ZONE"] is None: + return "UTC" + else: + return self.settings_dict["TIME_ZONE"] + + @property + def queries_logged(self): + return self.force_debug_cursor or settings.DEBUG + + @property + def queries(self): + if len(self.queries_log) == self.queries_log.maxlen: + warnings.warn( + "Limit for query logging exceeded, only the last {} queries " + "will be returned.".format(self.queries_log.maxlen) + ) + return list(self.queries_log) + + def get_database_version(self): + """Return a tuple of the database's version.""" + raise NotImplementedError( + "subclasses of BaseDatabaseWrapper may require a get_database_version() " + "method." + ) + + def check_database_version_supported(self): + """ + Raise an error if the database version isn't supported by this + version of Django. + """ + if ( + self.features.minimum_database_version is not None + and self.get_database_version() < self.features.minimum_database_version + ): + db_version = ".".join(map(str, self.get_database_version())) + min_db_version = ".".join(map(str, self.features.minimum_database_version)) + raise NotSupportedError( + f"{self.display_name} {min_db_version} or later is required " + f"(found {db_version})." + ) + + # ##### Backend-specific methods for creating connections and cursors ##### + + def get_connection_params(self): + """Return a dict of parameters suitable for get_new_connection.""" + raise NotImplementedError( + "subclasses of BaseDatabaseWrapper may require a get_connection_params() " + "method" + ) + + def get_new_connection(self, conn_params): + """Open a connection to the database.""" + raise NotImplementedError( + "subclasses of BaseDatabaseWrapper may require a get_new_connection() " + "method" + ) + + def init_connection_state(self): + """Initialize the database connection settings.""" + global RAN_DB_VERSION_CHECK + if self.alias not in RAN_DB_VERSION_CHECK: + self.check_database_version_supported() + RAN_DB_VERSION_CHECK.add(self.alias) + + def create_cursor(self, name=None): + """Create a cursor. Assume that a connection is established.""" + raise NotImplementedError( + "subclasses of BaseDatabaseWrapper may require a create_cursor() method" + ) + + # ##### Backend-specific methods for creating connections ##### + + @async_unsafe + def connect(self): + """Connect to the database. Assume that the connection is closed.""" + # Check for invalid configurations. + self.check_settings() + # In case the previous connection was closed while in an atomic block + self.in_atomic_block = False + self.savepoint_ids = [] + self.atomic_blocks = [] + self.needs_rollback = False + # Reset parameters defining when to close/health-check the connection. + self.health_check_enabled = self.settings_dict["CONN_HEALTH_CHECKS"] + max_age = self.settings_dict["CONN_MAX_AGE"] + self.close_at = None if max_age is None else time.monotonic() + max_age + self.closed_in_transaction = False + self.errors_occurred = False + # New connections are healthy. + self.health_check_done = True + # Establish the connection + conn_params = self.get_connection_params() + self.connection = self.get_new_connection(conn_params) + self.set_autocommit(self.settings_dict["AUTOCOMMIT"]) + self.init_connection_state() + connection_created.send(sender=self.__class__, connection=self) + + self.run_on_commit = [] + + def check_settings(self): + if self.settings_dict["TIME_ZONE"] is not None and not settings.USE_TZ: + raise ImproperlyConfigured( + "Connection '%s' cannot set TIME_ZONE because USE_TZ is False." + % self.alias + ) + + @async_unsafe + def ensure_connection(self): + """Guarantee that a connection to the database is established.""" + if self.connection is None: + with self.wrap_database_errors: + self.connect() + + # ##### Backend-specific wrappers for PEP-249 connection methods ##### + + def _prepare_cursor(self, cursor): + """ + Validate the connection is usable and perform database cursor wrapping. + """ + self.validate_thread_sharing() + if self.queries_logged: + wrapped_cursor = self.make_debug_cursor(cursor) + else: + wrapped_cursor = self.make_cursor(cursor) + return wrapped_cursor + + def _cursor(self, name=None): + self.close_if_health_check_failed() + self.ensure_connection() + with self.wrap_database_errors: + return self._prepare_cursor(self.create_cursor(name)) + + def _commit(self): + if self.connection is not None: + with debug_transaction(self, "COMMIT"), self.wrap_database_errors: + return self.connection.commit() + + def _rollback(self): + if self.connection is not None: + with debug_transaction(self, "ROLLBACK"), self.wrap_database_errors: + return self.connection.rollback() + + def _close(self): + if self.connection is not None: + with self.wrap_database_errors: + return self.connection.close() + + # ##### Generic wrappers for PEP-249 connection methods ##### + + @async_unsafe + def cursor(self): + """Create a cursor, opening a connection if necessary.""" + return self._cursor() + + @async_unsafe + def commit(self): + """Commit a transaction and reset the dirty flag.""" + self.validate_thread_sharing() + self.validate_no_atomic_block() + self._commit() + # A successful commit means that the database connection works. + self.errors_occurred = False + self.run_commit_hooks_on_set_autocommit_on = True + + @async_unsafe + def rollback(self): + """Roll back a transaction and reset the dirty flag.""" + self.validate_thread_sharing() + self.validate_no_atomic_block() + self._rollback() + # A successful rollback means that the database connection works. + self.errors_occurred = False + self.needs_rollback = False + self.run_on_commit = [] + + @async_unsafe + def close(self): + """Close the connection to the database.""" + self.validate_thread_sharing() + self.run_on_commit = [] + + # Don't call validate_no_atomic_block() to avoid making it difficult + # to get rid of a connection in an invalid state. The next connect() + # will reset the transaction state anyway. + if self.closed_in_transaction or self.connection is None: + return + try: + self._close() + finally: + if self.in_atomic_block: + self.closed_in_transaction = True + self.needs_rollback = True + else: + self.connection = None + + # ##### Backend-specific savepoint management methods ##### + + def _savepoint(self, sid): + with self.cursor() as cursor: + cursor.execute(self.ops.savepoint_create_sql(sid)) + + def _savepoint_rollback(self, sid): + with self.cursor() as cursor: + cursor.execute(self.ops.savepoint_rollback_sql(sid)) + + def _savepoint_commit(self, sid): + with self.cursor() as cursor: + cursor.execute(self.ops.savepoint_commit_sql(sid)) + + def _savepoint_allowed(self): + # Savepoints cannot be created outside a transaction + return self.features.uses_savepoints and not self.get_autocommit() + + # ##### Generic savepoint management methods ##### + + @async_unsafe + def savepoint(self): + """ + Create a savepoint inside the current transaction. Return an + identifier for the savepoint that will be used for the subsequent + rollback or commit. Do nothing if savepoints are not supported. + """ + if not self._savepoint_allowed(): + return + + thread_ident = _thread.get_ident() + tid = str(thread_ident).replace("-", "") + + self.savepoint_state += 1 + sid = "s%s_x%d" % (tid, self.savepoint_state) + + self.validate_thread_sharing() + self._savepoint(sid) + + return sid + + @async_unsafe + def savepoint_rollback(self, sid): + """ + Roll back to a savepoint. Do nothing if savepoints are not supported. + """ + if not self._savepoint_allowed(): + return + + self.validate_thread_sharing() + self._savepoint_rollback(sid) + + # Remove any callbacks registered while this savepoint was active. + self.run_on_commit = [ + (sids, func, robust) + for (sids, func, robust) in self.run_on_commit + if sid not in sids + ] + + @async_unsafe + def savepoint_commit(self, sid): + """ + Release a savepoint. Do nothing if savepoints are not supported. + """ + if not self._savepoint_allowed(): + return + + self.validate_thread_sharing() + self._savepoint_commit(sid) + + @async_unsafe + def clean_savepoints(self): + """ + Reset the counter used to generate unique savepoint ids in this thread. + """ + self.savepoint_state = 0 + + # ##### Backend-specific transaction management methods ##### + + def _set_autocommit(self, autocommit): + """ + Backend-specific implementation to enable or disable autocommit. + """ + raise NotImplementedError( + "subclasses of BaseDatabaseWrapper may require a _set_autocommit() method" + ) + + # ##### Generic transaction management methods ##### + + def get_autocommit(self): + """Get the autocommit state.""" + self.ensure_connection() + return self.autocommit + + def set_autocommit( + self, autocommit, force_begin_transaction_with_broken_autocommit=False + ): + """ + Enable or disable autocommit. + + The usual way to start a transaction is to turn autocommit off. + SQLite does not properly start a transaction when disabling + autocommit. To avoid this buggy behavior and to actually enter a new + transaction, an explicit BEGIN is required. Using + force_begin_transaction_with_broken_autocommit=True will issue an + explicit BEGIN with SQLite. This option will be ignored for other + backends. + """ + self.validate_no_atomic_block() + self.close_if_health_check_failed() + self.ensure_connection() + + start_transaction_under_autocommit = ( + force_begin_transaction_with_broken_autocommit + and not autocommit + and hasattr(self, "_start_transaction_under_autocommit") + ) + + if start_transaction_under_autocommit: + self._start_transaction_under_autocommit() + elif autocommit: + self._set_autocommit(autocommit) + else: + with debug_transaction(self, "BEGIN"): + self._set_autocommit(autocommit) + self.autocommit = autocommit + + if autocommit and self.run_commit_hooks_on_set_autocommit_on: + self.run_and_clear_commit_hooks() + self.run_commit_hooks_on_set_autocommit_on = False + + def get_rollback(self): + """Get the "needs rollback" flag -- for *advanced use* only.""" + if not self.in_atomic_block: + raise TransactionManagementError( + "The rollback flag doesn't work outside of an 'atomic' block." + ) + return self.needs_rollback + + def set_rollback(self, rollback): + """ + Set or unset the "needs rollback" flag -- for *advanced use* only. + """ + if not self.in_atomic_block: + raise TransactionManagementError( + "The rollback flag doesn't work outside of an 'atomic' block." + ) + self.needs_rollback = rollback + + def validate_no_atomic_block(self): + """Raise an error if an atomic block is active.""" + if self.in_atomic_block: + raise TransactionManagementError( + "This is forbidden when an 'atomic' block is active." + ) + + def validate_no_broken_transaction(self): + if self.needs_rollback: + raise TransactionManagementError( + "An error occurred in the current transaction. You can't " + "execute queries until the end of the 'atomic' block." + ) from self.rollback_exc + + # ##### Foreign key constraints checks handling ##### + + @contextmanager + def constraint_checks_disabled(self): + """ + Disable foreign key constraint checking. + """ + disabled = self.disable_constraint_checking() + try: + yield + finally: + if disabled: + self.enable_constraint_checking() + + def disable_constraint_checking(self): + """ + Backends can implement as needed to temporarily disable foreign key + constraint checking. Should return True if the constraints were + disabled and will need to be reenabled. + """ + return False + + def enable_constraint_checking(self): + """ + Backends can implement as needed to re-enable foreign key constraint + checking. + """ + pass + + def check_constraints(self, table_names=None): + """ + Backends can override this method if they can apply constraint + checking (e.g. via "SET CONSTRAINTS ALL IMMEDIATE"). Should raise an + IntegrityError if any invalid foreign key references are encountered. + """ + pass + + # ##### Connection termination handling ##### + + def is_usable(self): + """ + Test if the database connection is usable. + + This method may assume that self.connection is not None. + + Actual implementations should take care not to raise exceptions + as that may prevent Django from recycling unusable connections. + """ + raise NotImplementedError( + "subclasses of BaseDatabaseWrapper may require an is_usable() method" + ) + + def close_if_health_check_failed(self): + """Close existing connection if it fails a health check.""" + if ( + self.connection is None + or not self.health_check_enabled + or self.health_check_done + ): + return + + if not self.is_usable(): + self.close() + self.health_check_done = True + + def close_if_unusable_or_obsolete(self): + """ + Close the current connection if unrecoverable errors have occurred + or if it outlived its maximum age. + """ + if self.connection is not None: + self.health_check_done = False + # If the application didn't restore the original autocommit setting, + # don't take chances, drop the connection. + if self.get_autocommit() != self.settings_dict["AUTOCOMMIT"]: + self.close() + return + + # If an exception other than DataError or IntegrityError occurred + # since the last commit / rollback, check if the connection works. + if self.errors_occurred: + if self.is_usable(): + self.errors_occurred = False + self.health_check_done = True + else: + self.close() + return + + if self.close_at is not None and time.monotonic() >= self.close_at: + self.close() + return + + # ##### Thread safety handling ##### + + @property + def allow_thread_sharing(self): + with self._thread_sharing_lock: + return self._thread_sharing_count > 0 + + def inc_thread_sharing(self): + with self._thread_sharing_lock: + self._thread_sharing_count += 1 + + def dec_thread_sharing(self): + with self._thread_sharing_lock: + if self._thread_sharing_count <= 0: + raise RuntimeError( + "Cannot decrement the thread sharing count below zero." + ) + self._thread_sharing_count -= 1 + + def validate_thread_sharing(self): + """ + Validate that the connection isn't accessed by another thread than the + one which originally created it, unless the connection was explicitly + authorized to be shared between threads (via the `inc_thread_sharing()` + method). Raise an exception if the validation fails. + """ + if not (self.allow_thread_sharing or self._thread_ident == _thread.get_ident()): + raise DatabaseError( + "DatabaseWrapper objects created in a " + "thread can only be used in that same thread. The object " + "with alias '%s' was created in thread id %s and this is " + "thread id %s." % (self.alias, self._thread_ident, _thread.get_ident()) + ) + + # ##### Miscellaneous ##### + + def prepare_database(self): + """ + Hook to do any database check or preparation, generally called before + migrating a project or an app. + """ + pass + + @cached_property + def wrap_database_errors(self): + """ + Context manager and decorator that re-throws backend-specific database + exceptions using Django's common wrappers. + """ + return DatabaseErrorWrapper(self) + + def chunked_cursor(self): + """ + Return a cursor that tries to avoid caching in the database (if + supported by the database), otherwise return a regular cursor. + """ + return self.cursor() + + def make_debug_cursor(self, cursor): + """Create a cursor that logs all queries in self.queries_log.""" + return utils.CursorDebugWrapper(cursor, self) + + def make_cursor(self, cursor): + """Create a cursor without debug logging.""" + return utils.CursorWrapper(cursor, self) + + @contextmanager + def temporary_connection(self): + """ + Context manager that ensures that a connection is established, and + if it opened one, closes it to avoid leaving a dangling connection. + This is useful for operations outside of the request-response cycle. + + Provide a cursor: with self.temporary_connection() as cursor: ... + """ + must_close = self.connection is None + try: + with self.cursor() as cursor: + yield cursor + finally: + if must_close: + self.close() + + @contextmanager + def _nodb_cursor(self): + """ + Return a cursor from an alternative connection to be used when there is + no need to access the main database, specifically for test db + creation/deletion. This also prevents the production database from + being exposed to potential child threads while (or after) the test + database is destroyed. Refs #10868, #17786, #16969. + """ + conn = self.__class__({**self.settings_dict, "NAME": None}, alias=NO_DB_ALIAS) + try: + with conn.cursor() as cursor: + yield cursor + finally: + conn.close() + + def schema_editor(self, *args, **kwargs): + """ + Return a new instance of this backend's SchemaEditor. + """ + if self.SchemaEditorClass is None: + raise NotImplementedError( + "The SchemaEditorClass attribute of this database wrapper is still None" + ) + return self.SchemaEditorClass(self, *args, **kwargs) + + def on_commit(self, func, robust=False): + if not callable(func): + raise TypeError("on_commit()'s callback must be a callable.") + if self.in_atomic_block: + # Transaction in progress; save for execution on commit. + self.run_on_commit.append((set(self.savepoint_ids), func, robust)) + elif not self.get_autocommit(): + raise TransactionManagementError( + "on_commit() cannot be used in manual transaction management" + ) + else: + # No transaction in progress and in autocommit mode; execute + # immediately. + if robust: + try: + func() + except Exception as e: + logger.error( + f"Error calling {func.__qualname__} in on_commit() (%s).", + e, + exc_info=True, + ) + else: + func() + + def run_and_clear_commit_hooks(self): + self.validate_no_atomic_block() + current_run_on_commit = self.run_on_commit + self.run_on_commit = [] + while current_run_on_commit: + _, func, robust = current_run_on_commit.pop(0) + if robust: + try: + func() + except Exception as e: + logger.error( + f"Error calling {func.__qualname__} in on_commit() during " + f"transaction (%s).", + e, + exc_info=True, + ) + else: + func() + + @contextmanager + def execute_wrapper(self, wrapper): + """ + Return a context manager under which the wrapper is applied to suitable + database query executions. + """ + self.execute_wrappers.append(wrapper) + try: + yield + finally: + self.execute_wrappers.pop() + + def copy(self, alias=None): + """ + Return a copy of this connection. + + For tests that require two connections to the same database. + """ + settings_dict = copy.deepcopy(self.settings_dict) + if alias is None: + alias = self.alias + return type(self)(settings_dict, alias) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/client.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/client.py new file mode 100644 index 0000000..0310563 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/client.py @@ -0,0 +1,28 @@ +import os +import subprocess + + +class BaseDatabaseClient: + """Encapsulate backend-specific methods for opening a client shell.""" + + # This should be a string representing the name of the executable + # (e.g., "psql"). Subclasses must override this. + executable_name = None + + def __init__(self, connection): + # connection is an instance of BaseDatabaseWrapper. + self.connection = connection + + @classmethod + def settings_to_cmd_args_env(cls, settings_dict, parameters): + raise NotImplementedError( + "subclasses of BaseDatabaseClient must provide a " + "settings_to_cmd_args_env() method or override a runshell()." + ) + + def runshell(self, parameters): + args, env = self.settings_to_cmd_args_env( + self.connection.settings_dict, parameters + ) + env = {**os.environ, **env} if env else None + subprocess.run(args, env=env, check=True) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/creation.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/creation.py new file mode 100644 index 0000000..cbac8a7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/creation.py @@ -0,0 +1,381 @@ +import os +import sys +from io import StringIO + +from django.apps import apps +from django.conf import settings +from django.core import serializers +from django.db import router +from django.db.transaction import atomic +from django.utils.module_loading import import_string + +# The prefix to put on the default database name when creating +# the test database. +TEST_DATABASE_PREFIX = "test_" + + +class BaseDatabaseCreation: + """ + Encapsulate backend-specific differences pertaining to creation and + destruction of the test database. + """ + + def __init__(self, connection): + self.connection = connection + + def _nodb_cursor(self): + return self.connection._nodb_cursor() + + def log(self, msg): + sys.stderr.write(msg + os.linesep) + + def create_test_db( + self, verbosity=1, autoclobber=False, serialize=True, keepdb=False + ): + """ + Create a test database, prompting the user for confirmation if the + database already exists. Return the name of the test database created. + """ + # Don't import django.core.management if it isn't needed. + from django.core.management import call_command + + test_database_name = self._get_test_db_name() + + if verbosity >= 1: + action = "Creating" + if keepdb: + action = "Using existing" + + self.log( + "%s test database for alias %s..." + % ( + action, + self._get_database_display_str(verbosity, test_database_name), + ) + ) + + # We could skip this call if keepdb is True, but we instead + # give it the keepdb param. This is to handle the case + # where the test DB doesn't exist, in which case we need to + # create it, then just not destroy it. If we instead skip + # this, we will get an exception. + self._create_test_db(verbosity, autoclobber, keepdb) + + self.connection.close() + settings.DATABASES[self.connection.alias]["NAME"] = test_database_name + self.connection.settings_dict["NAME"] = test_database_name + + try: + if self.connection.settings_dict["TEST"]["MIGRATE"] is False: + # Disable migrations for all apps. + old_migration_modules = settings.MIGRATION_MODULES + settings.MIGRATION_MODULES = { + app.label: None for app in apps.get_app_configs() + } + # We report migrate messages at one level lower than that + # requested. This ensures we don't get flooded with messages during + # testing (unless you really ask to be flooded). + call_command( + "migrate", + verbosity=max(verbosity - 1, 0), + interactive=False, + database=self.connection.alias, + run_syncdb=True, + ) + finally: + if self.connection.settings_dict["TEST"]["MIGRATE"] is False: + settings.MIGRATION_MODULES = old_migration_modules + + # We then serialize the current state of the database into a string + # and store it on the connection. This slightly horrific process is so people + # who are testing on databases without transactions or who are using + # a TransactionTestCase still get a clean database on every test run. + if serialize: + self.connection._test_serialized_contents = self.serialize_db_to_string() + + call_command("createcachetable", database=self.connection.alias) + + # Ensure a connection for the side effect of initializing the test database. + self.connection.ensure_connection() + + if os.environ.get("RUNNING_DJANGOS_TEST_SUITE") == "true": + self.mark_expected_failures_and_skips() + + return test_database_name + + def set_as_test_mirror(self, primary_settings_dict): + """ + Set this database up to be used in testing as a mirror of a primary + database whose settings are given. + """ + self.connection.settings_dict["NAME"] = primary_settings_dict["NAME"] + + def serialize_db_to_string(self): + """ + Serialize all data in the database into a JSON string. + Designed only for test runner usage; will not handle large + amounts of data. + """ + + # Iteratively return every object for all models to serialize. + def get_objects(): + from django.db.migrations.loader import MigrationLoader + + loader = MigrationLoader(self.connection) + for app_config in apps.get_app_configs(): + if ( + app_config.models_module is not None + and app_config.label in loader.migrated_apps + and app_config.name not in settings.TEST_NON_SERIALIZED_APPS + ): + for model in app_config.get_models(): + if model._meta.can_migrate( + self.connection + ) and router.allow_migrate_model(self.connection.alias, model): + queryset = model._base_manager.using( + self.connection.alias, + ).order_by(model._meta.pk.name) + yield from queryset.iterator() + + # Serialize to a string + out = StringIO() + serializers.serialize("json", get_objects(), indent=None, stream=out) + return out.getvalue() + + def deserialize_db_from_string(self, data): + """ + Reload the database with data from a string generated by + the serialize_db_to_string() method. + """ + data = StringIO(data) + table_names = set() + # Load data in a transaction to handle forward references and cycles. + with atomic(using=self.connection.alias): + # Disable constraint checks, because some databases (MySQL) doesn't + # support deferred checks. + with self.connection.constraint_checks_disabled(): + for obj in serializers.deserialize( + "json", data, using=self.connection.alias + ): + obj.save() + table_names.add(obj.object.__class__._meta.db_table) + # Manually check for any invalid keys that might have been added, + # because constraint checks were disabled. + self.connection.check_constraints(table_names=table_names) + + def _get_database_display_str(self, verbosity, database_name): + """ + Return display string for a database for use in various actions. + """ + return "'%s'%s" % ( + self.connection.alias, + (" ('%s')" % database_name) if verbosity >= 2 else "", + ) + + def _get_test_db_name(self): + """ + Internal implementation - return the name of the test DB that will be + created. Only useful when called from create_test_db() and + _create_test_db() and when no external munging is done with the 'NAME' + settings. + """ + if self.connection.settings_dict["TEST"]["NAME"]: + return self.connection.settings_dict["TEST"]["NAME"] + return TEST_DATABASE_PREFIX + self.connection.settings_dict["NAME"] + + def _execute_create_test_db(self, cursor, parameters, keepdb=False): + cursor.execute("CREATE DATABASE %(dbname)s %(suffix)s" % parameters) + + def _create_test_db(self, verbosity, autoclobber, keepdb=False): + """ + Internal implementation - create the test db tables. + """ + test_database_name = self._get_test_db_name() + test_db_params = { + "dbname": self.connection.ops.quote_name(test_database_name), + "suffix": self.sql_table_creation_suffix(), + } + # Create the test database and connect to it. + with self._nodb_cursor() as cursor: + try: + self._execute_create_test_db(cursor, test_db_params, keepdb) + except Exception as e: + # if we want to keep the db, then no need to do any of the below, + # just return and skip it all. + if keepdb: + return test_database_name + + self.log("Got an error creating the test database: %s" % e) + if not autoclobber: + confirm = input( + "Type 'yes' if you would like to try deleting the test " + "database '%s', or 'no' to cancel: " % test_database_name + ) + if autoclobber or confirm == "yes": + try: + if verbosity >= 1: + self.log( + "Destroying old test database for alias %s..." + % ( + self._get_database_display_str( + verbosity, test_database_name + ), + ) + ) + cursor.execute("DROP DATABASE %(dbname)s" % test_db_params) + self._execute_create_test_db(cursor, test_db_params, keepdb) + except Exception as e: + self.log("Got an error recreating the test database: %s" % e) + sys.exit(2) + else: + self.log("Tests cancelled.") + sys.exit(1) + + return test_database_name + + def clone_test_db(self, suffix, verbosity=1, autoclobber=False, keepdb=False): + """ + Clone a test database. + """ + source_database_name = self.connection.settings_dict["NAME"] + + if verbosity >= 1: + action = "Cloning test database" + if keepdb: + action = "Using existing clone" + self.log( + "%s for alias %s..." + % ( + action, + self._get_database_display_str(verbosity, source_database_name), + ) + ) + + # We could skip this call if keepdb is True, but we instead + # give it the keepdb param. See create_test_db for details. + self._clone_test_db(suffix, verbosity, keepdb) + + def get_test_db_clone_settings(self, suffix): + """ + Return a modified connection settings dict for the n-th clone of a DB. + """ + # When this function is called, the test database has been created + # already and its name has been copied to settings_dict['NAME'] so + # we don't need to call _get_test_db_name. + orig_settings_dict = self.connection.settings_dict + return { + **orig_settings_dict, + "NAME": "{}_{}".format(orig_settings_dict["NAME"], suffix), + } + + def _clone_test_db(self, suffix, verbosity, keepdb=False): + """ + Internal implementation - duplicate the test db tables. + """ + raise NotImplementedError( + "The database backend doesn't support cloning databases. " + "Disable the option to run tests in parallel processes." + ) + + def destroy_test_db( + self, old_database_name=None, verbosity=1, keepdb=False, suffix=None + ): + """ + Destroy a test database, prompting the user for confirmation if the + database already exists. + """ + self.connection.close() + if suffix is None: + test_database_name = self.connection.settings_dict["NAME"] + else: + test_database_name = self.get_test_db_clone_settings(suffix)["NAME"] + + if verbosity >= 1: + action = "Destroying" + if keepdb: + action = "Preserving" + self.log( + "%s test database for alias %s..." + % ( + action, + self._get_database_display_str(verbosity, test_database_name), + ) + ) + + # if we want to preserve the database + # skip the actual destroying piece. + if not keepdb: + self._destroy_test_db(test_database_name, verbosity) + + # Restore the original database name + if old_database_name is not None: + settings.DATABASES[self.connection.alias]["NAME"] = old_database_name + self.connection.settings_dict["NAME"] = old_database_name + + def _destroy_test_db(self, test_database_name, verbosity): + """ + Internal implementation - remove the test db tables. + """ + # Remove the test database to clean up after + # ourselves. Connect to the previous database (not the test database) + # to do so, because it's not allowed to delete a database while being + # connected to it. + with self._nodb_cursor() as cursor: + cursor.execute( + "DROP DATABASE %s" % self.connection.ops.quote_name(test_database_name) + ) + + def mark_expected_failures_and_skips(self): + """ + Mark tests in Django's test suite which are expected failures on this + database and test which should be skipped on this database. + """ + # Only load unittest if we're actually testing. + from unittest import expectedFailure, skip + + for test_name in self.connection.features.django_test_expected_failures: + test_case_name, _, test_method_name = test_name.rpartition(".") + test_app = test_name.split(".")[0] + # Importing a test app that isn't installed raises RuntimeError. + if test_app in settings.INSTALLED_APPS: + test_case = import_string(test_case_name) + test_method = getattr(test_case, test_method_name) + setattr(test_case, test_method_name, expectedFailure(test_method)) + for reason, tests in self.connection.features.django_test_skips.items(): + for test_name in tests: + test_case_name, _, test_method_name = test_name.rpartition(".") + test_app = test_name.split(".")[0] + # Importing a test app that isn't installed raises RuntimeError. + if test_app in settings.INSTALLED_APPS: + test_case = import_string(test_case_name) + test_method = getattr(test_case, test_method_name) + setattr(test_case, test_method_name, skip(reason)(test_method)) + + def sql_table_creation_suffix(self): + """ + SQL to append to the end of the test table creation statements. + """ + return "" + + def test_db_signature(self): + """ + Return a tuple with elements of self.connection.settings_dict (a + DATABASES setting value) that uniquely identify a database + accordingly to the RDBMS particularities. + """ + settings_dict = self.connection.settings_dict + return ( + settings_dict["HOST"], + settings_dict["PORT"], + settings_dict["ENGINE"], + self._get_test_db_name(), + ) + + def setup_worker_connection(self, _worker_id): + settings_dict = self.get_test_db_clone_settings(str(_worker_id)) + # connection.settings_dict must be updated in place for changes to be + # reflected in django.db.connections. If the following line assigned + # connection.settings_dict = settings_dict, new threads would connect + # to the default database instead of the appropriate clone. + self.connection.settings_dict.update(settings_dict) + self.connection.close() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/features.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/features.py new file mode 100644 index 0000000..4dfe9db --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/features.py @@ -0,0 +1,416 @@ +from django.db import ProgrammingError +from django.utils.functional import cached_property + + +class BaseDatabaseFeatures: + # An optional tuple indicating the minimum supported database version. + minimum_database_version = None + gis_enabled = False + # Oracle can't group by LOB (large object) data types. + allows_group_by_lob = True + allows_group_by_selected_pks = False + allows_group_by_select_index = True + empty_fetchmany_value = [] + update_can_self_select = True + # Does the backend support self-reference subqueries in the DELETE + # statement? + delete_can_self_reference_subquery = True + + # Does the backend distinguish between '' and None? + interprets_empty_strings_as_nulls = False + + # Does the backend allow inserting duplicate NULL rows in a nullable + # unique field? All core backends implement this correctly, but other + # databases such as SQL Server do not. + supports_nullable_unique_constraints = True + + # Does the backend allow inserting duplicate rows when a unique_together + # constraint exists and some fields are nullable but not all of them? + supports_partially_nullable_unique_constraints = True + + # Does the backend supports specifying whether NULL values should be + # considered distinct in unique constraints? + supports_nulls_distinct_unique_constraints = False + + # Does the backend support initially deferrable unique constraints? + supports_deferrable_unique_constraints = False + + can_use_chunked_reads = True + can_return_columns_from_insert = False + can_return_rows_from_bulk_insert = False + has_bulk_insert = True + uses_savepoints = True + can_release_savepoints = False + + # If True, don't use integer foreign keys referring to, e.g., positive + # integer primary keys. + related_fields_match_type = False + allow_sliced_subqueries_with_in = True + has_select_for_update = False + has_select_for_update_nowait = False + has_select_for_update_skip_locked = False + has_select_for_update_of = False + has_select_for_no_key_update = False + # Does the database's SELECT FOR UPDATE OF syntax require a column rather + # than a table? + select_for_update_of_column = False + + # Does the default test database allow multiple connections? + # Usually an indication that the test database is in-memory + test_db_allows_multiple_connections = True + + # Can an object be saved without an explicit primary key? + supports_unspecified_pk = False + + # Can a fixture contain forward references? i.e., are + # FK constraints checked at the end of transaction, or + # at the end of each save operation? + supports_forward_references = True + + # Does the backend truncate names properly when they are too long? + truncates_names = False + + # Is there a REAL datatype in addition to floats/doubles? + has_real_datatype = False + supports_subqueries_in_group_by = True + + # Does the backend ignore unnecessary ORDER BY clauses in subqueries? + ignores_unnecessary_order_by_in_subqueries = True + + # Is there a true datatype for uuid? + has_native_uuid_field = False + + # Is there a true datatype for timedeltas? + has_native_duration_field = False + + # Does the database driver supports same type temporal data subtraction + # by returning the type used to store duration field? + supports_temporal_subtraction = False + + # Does the __regex lookup support backreferencing and grouping? + supports_regex_backreferencing = True + + # Can date/datetime lookups be performed using a string? + supports_date_lookup_using_string = True + + # Can datetimes with timezones be used? + supports_timezones = True + + # Does the database have a copy of the zoneinfo database? + has_zoneinfo_database = True + + # When performing a GROUP BY, is an ORDER BY NULL required + # to remove any ordering? + requires_explicit_null_ordering_when_grouping = False + + # Does the backend order NULL values as largest or smallest? + nulls_order_largest = False + + # Does the backend support NULLS FIRST and NULLS LAST in ORDER BY? + supports_order_by_nulls_modifier = True + + # Does the backend orders NULLS FIRST by default? + order_by_nulls_first = False + + # The database's limit on the number of query parameters. + max_query_params = None + + # Can an object have an autoincrement primary key of 0? + allows_auto_pk_0 = True + + # Do we need to NULL a ForeignKey out, or can the constraint check be + # deferred + can_defer_constraint_checks = False + + # Does the backend support tablespaces? Default to False because it isn't + # in the SQL standard. + supports_tablespaces = False + + # Does the backend reset sequences between tests? + supports_sequence_reset = True + + # Can the backend introspect the default value of a column? + can_introspect_default = True + + # Confirm support for introspected foreign keys + # Every database can do this reliably, except MySQL, + # which can't do it for MyISAM tables + can_introspect_foreign_keys = True + + # Map fields which some backends may not be able to differentiate to the + # field it's introspected as. + introspected_field_types = { + "AutoField": "AutoField", + "BigAutoField": "BigAutoField", + "BigIntegerField": "BigIntegerField", + "BinaryField": "BinaryField", + "BooleanField": "BooleanField", + "CharField": "CharField", + "DurationField": "DurationField", + "GenericIPAddressField": "GenericIPAddressField", + "IntegerField": "IntegerField", + "PositiveBigIntegerField": "PositiveBigIntegerField", + "PositiveIntegerField": "PositiveIntegerField", + "PositiveSmallIntegerField": "PositiveSmallIntegerField", + "SmallAutoField": "SmallAutoField", + "SmallIntegerField": "SmallIntegerField", + "TimeField": "TimeField", + } + + # Can the backend introspect the column order (ASC/DESC) for indexes? + supports_index_column_ordering = True + + # Does the backend support introspection of materialized views? + can_introspect_materialized_views = False + + # Support for the DISTINCT ON clause + can_distinct_on_fields = False + + # Does the backend prevent running SQL queries in broken transactions? + atomic_transactions = True + + # Can we roll back DDL in a transaction? + can_rollback_ddl = False + + schema_editor_uses_clientside_param_binding = False + + # Can we issue more than one ALTER COLUMN clause in an ALTER TABLE? + supports_combined_alters = False + + # Does it support foreign keys? + supports_foreign_keys = True + + # Can it create foreign key constraints inline when adding columns? + can_create_inline_fk = True + + # Can an index be renamed? + can_rename_index = False + + # Does it automatically index foreign keys? + indexes_foreign_keys = True + + # Does it support CHECK constraints? + supports_column_check_constraints = True + supports_table_check_constraints = True + # Does the backend support introspection of CHECK constraints? + can_introspect_check_constraints = True + + # Does the backend support 'pyformat' style ("... %(name)s ...", {'name': value}) + # parameter passing? Note this can be provided by the backend even if not + # supported by the Python driver + supports_paramstyle_pyformat = True + + # Does the backend require literal defaults, rather than parameterized ones? + requires_literal_defaults = False + + # Does the backend support functions in defaults? + supports_expression_defaults = True + + # Does the backend support the DEFAULT keyword in insert queries? + supports_default_keyword_in_insert = True + + # Does the backend support the DEFAULT keyword in bulk insert queries? + supports_default_keyword_in_bulk_insert = True + + # Does the backend require a connection reset after each material schema change? + connection_persists_old_columns = False + + # What kind of error does the backend throw when accessing closed cursor? + closed_cursor_error_class = ProgrammingError + + # Does 'a' LIKE 'A' match? + has_case_insensitive_like = False + + # Suffix for backends that don't support "SELECT xxx;" queries. + bare_select_suffix = "" + + # If NULL is implied on columns without needing to be explicitly specified + implied_column_null = False + + # Does the backend support "select for update" queries with limit (and offset)? + supports_select_for_update_with_limit = True + + # Does the backend ignore null expressions in GREATEST and LEAST queries unless + # every expression is null? + greatest_least_ignores_nulls = False + + # Can the backend clone databases for parallel test execution? + # Defaults to False to allow third-party backends to opt-in. + can_clone_databases = False + + # Does the backend consider table names with different casing to + # be equal? + ignores_table_name_case = False + + # Place FOR UPDATE right after FROM clause. Used on MSSQL. + for_update_after_from = False + + # Combinatorial flags + supports_select_union = True + supports_select_intersection = True + supports_select_difference = True + supports_slicing_ordering_in_compound = False + supports_parentheses_in_compound = True + requires_compound_order_by_subquery = False + + # Does the database support SQL 2003 FILTER (WHERE ...) in aggregate + # expressions? + supports_aggregate_filter_clause = False + + # Does the backend support indexing a TextField? + supports_index_on_text_field = True + + # Does the backend support window expressions (expression OVER (...))? + supports_over_clause = False + supports_frame_range_fixed_distance = False + only_supports_unbounded_with_preceding_and_following = False + + # Does the backend support CAST with precision? + supports_cast_with_precision = True + + # How many second decimals does the database return when casting a value to + # a type with time? + time_cast_precision = 6 + + # SQL to create a procedure for use by the Django test suite. The + # functionality of the procedure isn't important. + create_test_procedure_without_params_sql = None + create_test_procedure_with_int_param_sql = None + + # SQL to create a table with a composite primary key for use by the Django + # test suite. + create_test_table_with_composite_primary_key = None + + # Does the backend support keyword parameters for cursor.callproc()? + supports_callproc_kwargs = False + + # What formats does the backend EXPLAIN syntax support? + supported_explain_formats = set() + + # Does the backend support the default parameter in lead() and lag()? + supports_default_in_lead_lag = True + + # Does the backend support ignoring constraint or uniqueness errors during + # INSERT? + supports_ignore_conflicts = True + # Does the backend support updating rows on constraint or uniqueness errors + # during INSERT? + supports_update_conflicts = False + supports_update_conflicts_with_target = False + + # Does this backend require casting the results of CASE expressions used + # in UPDATE statements to ensure the expression has the correct type? + requires_casted_case_in_updates = False + + # Does the backend support partial indexes (CREATE INDEX ... WHERE ...)? + supports_partial_indexes = True + supports_functions_in_partial_indexes = True + # Does the backend support covering indexes (CREATE INDEX ... INCLUDE ...)? + supports_covering_indexes = False + # Does the backend support indexes on expressions? + supports_expression_indexes = True + # Does the backend treat COLLATE as an indexed expression? + collate_as_index_expression = False + + # Does the database allow more than one constraint or index on the same + # field(s)? + allows_multiple_constraints_on_same_fields = True + + # Does the backend support boolean expressions in SELECT and GROUP BY + # clauses? + supports_boolean_expr_in_select_clause = True + # Does the backend support comparing boolean expressions in WHERE clauses? + # Eg: WHERE (price > 0) IS NOT NULL + supports_comparing_boolean_expr = True + + # Does the backend support JSONField? + supports_json_field = True + # Can the backend introspect a JSONField? + can_introspect_json_field = True + # Does the backend support primitives in JSONField? + supports_primitives_in_json_field = True + # Is there a true datatype for JSON? + has_native_json_field = False + # Does the backend use PostgreSQL-style JSON operators like '->'? + has_json_operators = False + # Does the backend support __contains and __contained_by lookups for + # a JSONField? + supports_json_field_contains = True + # Does value__d__contains={'f': 'g'} (without a list around the dict) match + # {'d': [{'f': 'g'}]}? + json_key_contains_list_matching_requires_list = False + # Does the backend support JSONObject() database function? + has_json_object_function = True + + # Does the backend support column collations? + supports_collation_on_charfield = True + supports_collation_on_textfield = True + # Does the backend support non-deterministic collations? + supports_non_deterministic_collations = True + + # Does the backend support column and table comments? + supports_comments = False + # Does the backend support column comments in ADD COLUMN statements? + supports_comments_inline = False + + # Does the backend support stored generated columns? + supports_stored_generated_columns = False + # Does the backend support virtual generated columns? + supports_virtual_generated_columns = False + + # Does the backend support the logical XOR operator? + supports_logical_xor = False + + # Set to (exception, message) if null characters in text are disallowed. + prohibits_null_characters_in_text_exception = None + + # Does the backend support unlimited character columns? + supports_unlimited_charfield = False + + # Collation names for use by the Django test suite. + test_collations = { + "ci": None, # Case-insensitive. + "cs": None, # Case-sensitive. + "non_default": None, # Non-default. + "swedish_ci": None, # Swedish case-insensitive. + "virtual": None, # A collation that can be used for virtual columns. + } + # SQL template override for tests.aggregation.tests.NowUTC + test_now_utc_template = None + + # SQL to create a model instance using the database defaults. + insert_test_table_with_defaults = None + + # A set of dotted paths to tests in Django's test suite that are expected + # to fail on this database. + django_test_expected_failures = set() + # A map of reasons to sets of dotted paths to tests in Django's test suite + # that should be skipped for this database. + django_test_skips = {} + + def __init__(self, connection): + self.connection = connection + + @cached_property + def supports_explaining_query_execution(self): + """Does this backend support explaining query execution?""" + return self.connection.ops.explain_prefix is not None + + @cached_property + def supports_transactions(self): + """Confirm support for transactions.""" + with self.connection.cursor() as cursor: + cursor.execute("CREATE TABLE ROLLBACK_TEST (X INT)") + self.connection.set_autocommit(False) + cursor.execute("INSERT INTO ROLLBACK_TEST (X) VALUES (8)") + self.connection.rollback() + self.connection.set_autocommit(True) + cursor.execute("SELECT COUNT(X) FROM ROLLBACK_TEST") + (count,) = cursor.fetchone() + cursor.execute("DROP TABLE ROLLBACK_TEST") + return count == 0 + + def allows_group_by_selected_pks_on_model(self, model): + if not self.allows_group_by_selected_pks: + return False + return model._meta.managed diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/introspection.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/introspection.py new file mode 100644 index 0000000..5e4acb3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/introspection.py @@ -0,0 +1,212 @@ +from collections import namedtuple + +# Structure returned by DatabaseIntrospection.get_table_list() +TableInfo = namedtuple("TableInfo", ["name", "type"]) + +# Structure returned by the DB-API cursor.description interface (PEP 249) +FieldInfo = namedtuple( + "FieldInfo", + "name type_code display_size internal_size precision scale null_ok " + "default collation", +) + + +class BaseDatabaseIntrospection: + """Encapsulate backend-specific introspection utilities.""" + + data_types_reverse = {} + + def __init__(self, connection): + self.connection = connection + + def get_field_type(self, data_type, description): + """ + Hook for a database backend to use the cursor description to + match a Django field type to a database column. + + For Oracle, the column data_type on its own is insufficient to + distinguish between a FloatField and IntegerField, for example. + """ + return self.data_types_reverse[data_type] + + def identifier_converter(self, name): + """ + Apply a conversion to the identifier for the purposes of comparison. + + The default identifier converter is for case sensitive comparison. + """ + return name + + def table_names(self, cursor=None, include_views=False): + """ + Return a list of names of all tables that exist in the database. + Sort the returned table list by Python's default sorting. Do NOT use + the database's ORDER BY here to avoid subtle differences in sorting + order between databases. + """ + + def get_names(cursor): + return sorted( + ti.name + for ti in self.get_table_list(cursor) + if include_views or ti.type == "t" + ) + + if cursor is None: + with self.connection.cursor() as cursor: + return get_names(cursor) + return get_names(cursor) + + def get_table_list(self, cursor): + """ + Return an unsorted list of TableInfo named tuples of all tables and + views that exist in the database. + """ + raise NotImplementedError( + "subclasses of BaseDatabaseIntrospection may require a get_table_list() " + "method" + ) + + def get_table_description(self, cursor, table_name): + """ + Return a description of the table with the DB-API cursor.description + interface. + """ + raise NotImplementedError( + "subclasses of BaseDatabaseIntrospection may require a " + "get_table_description() method." + ) + + def get_migratable_models(self): + from django.apps import apps + from django.db import router + + return ( + model + for app_config in apps.get_app_configs() + for model in router.get_migratable_models(app_config, self.connection.alias) + if model._meta.can_migrate(self.connection) + ) + + def django_table_names(self, only_existing=False, include_views=True): + """ + Return a list of all table names that have associated Django models and + are in INSTALLED_APPS. + + If only_existing is True, include only the tables in the database. + """ + tables = set() + for model in self.get_migratable_models(): + if not model._meta.managed: + continue + tables.add(model._meta.db_table) + tables.update( + f.m2m_db_table() + for f in model._meta.local_many_to_many + if f.remote_field.through._meta.managed + ) + tables = list(tables) + if only_existing: + existing_tables = set(self.table_names(include_views=include_views)) + tables = [ + t for t in tables if self.identifier_converter(t) in existing_tables + ] + return tables + + def installed_models(self, tables): + """ + Return a set of all models represented by the provided list of table + names. + """ + tables = set(map(self.identifier_converter, tables)) + return { + m + for m in self.get_migratable_models() + if self.identifier_converter(m._meta.db_table) in tables + } + + def sequence_list(self): + """ + Return a list of information about all DB sequences for all models in + all apps. + """ + sequence_list = [] + with self.connection.cursor() as cursor: + for model in self.get_migratable_models(): + if not model._meta.managed: + continue + if model._meta.swapped: + continue + sequence_list.extend( + self.get_sequences( + cursor, model._meta.db_table, model._meta.local_fields + ) + ) + for f in model._meta.local_many_to_many: + # If this is an m2m using an intermediate table, + # we don't need to reset the sequence. + if f.remote_field.through._meta.auto_created: + sequence = self.get_sequences(cursor, f.m2m_db_table()) + sequence_list.extend( + sequence or [{"table": f.m2m_db_table(), "column": None}] + ) + return sequence_list + + def get_sequences(self, cursor, table_name, table_fields=()): + """ + Return a list of introspected sequences for table_name. Each sequence + is a dict: {'table': , 'column': }. An optional + 'name' key can be added if the backend supports named sequences. + """ + raise NotImplementedError( + "subclasses of BaseDatabaseIntrospection may require a get_sequences() " + "method" + ) + + def get_relations(self, cursor, table_name): + """ + Return a dictionary of {field_name: (field_name_other_table, other_table)} + representing all foreign keys in the given table. + """ + raise NotImplementedError( + "subclasses of BaseDatabaseIntrospection may require a " + "get_relations() method." + ) + + def get_primary_key_column(self, cursor, table_name): + """ + Return the name of the primary key column for the given table. + """ + columns = self.get_primary_key_columns(cursor, table_name) + return columns[0] if columns else None + + def get_primary_key_columns(self, cursor, table_name): + """Return a list of primary key columns for the given table.""" + for constraint in self.get_constraints(cursor, table_name).values(): + if constraint["primary_key"]: + return constraint["columns"] + return None + + def get_constraints(self, cursor, table_name): + """ + Retrieve any constraints or keys (unique, pk, fk, check, index) + across one or more columns. + + Return a dict mapping constraint names to their attributes, + where attributes is a dict with keys: + * columns: List of columns this covers + * primary_key: True if primary key, False otherwise + * unique: True if this is a unique constraint, False otherwise + * foreign_key: (table, column) of target, or None + * check: True if check constraint, False otherwise + * index: True if index, False otherwise. + * orders: The order (ASC/DESC) defined for the columns of indexes + * type: The type of the index (btree, hash, etc.) + + Some backends may return special constraint names that don't exist + if they don't name constraints of a certain type (e.g. SQLite) + """ + raise NotImplementedError( + "subclasses of BaseDatabaseIntrospection may require a get_constraints() " + "method" + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/operations.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/operations.py new file mode 100644 index 0000000..0ee2ffc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/operations.py @@ -0,0 +1,794 @@ +import datetime +import decimal +import json +import warnings +from importlib import import_module + +import sqlparse + +from django.conf import settings +from django.db import NotSupportedError, transaction +from django.db.backends import utils +from django.db.models.expressions import Col +from django.utils import timezone +from django.utils.deprecation import RemovedInDjango60Warning +from django.utils.encoding import force_str + + +class BaseDatabaseOperations: + """ + Encapsulate backend-specific differences, such as the way a backend + performs ordering or calculates the ID of a recently-inserted row. + """ + + compiler_module = "django.db.models.sql.compiler" + + # Integer field safe ranges by `internal_type` as documented + # in docs/ref/models/fields.txt. + integer_field_ranges = { + "SmallIntegerField": (-32768, 32767), + "IntegerField": (-2147483648, 2147483647), + "BigIntegerField": (-9223372036854775808, 9223372036854775807), + "PositiveBigIntegerField": (0, 9223372036854775807), + "PositiveSmallIntegerField": (0, 32767), + "PositiveIntegerField": (0, 2147483647), + "SmallAutoField": (-32768, 32767), + "AutoField": (-2147483648, 2147483647), + "BigAutoField": (-9223372036854775808, 9223372036854775807), + } + set_operators = { + "union": "UNION", + "intersection": "INTERSECT", + "difference": "EXCEPT", + } + # Mapping of Field.get_internal_type() (typically the model field's class + # name) to the data type to use for the Cast() function, if different from + # DatabaseWrapper.data_types. + cast_data_types = {} + # CharField data type if the max_length argument isn't provided. + cast_char_field_without_max_length = None + + # Start and end points for window expressions. + PRECEDING = "PRECEDING" + FOLLOWING = "FOLLOWING" + UNBOUNDED_PRECEDING = "UNBOUNDED " + PRECEDING + UNBOUNDED_FOLLOWING = "UNBOUNDED " + FOLLOWING + CURRENT_ROW = "CURRENT ROW" + + # Prefix for EXPLAIN queries, or None EXPLAIN isn't supported. + explain_prefix = None + + def __init__(self, connection): + self.connection = connection + self._cache = None + + def autoinc_sql(self, table, column): + """ + Return any SQL needed to support auto-incrementing primary keys, or + None if no SQL is necessary. + + This SQL is executed when a table is created. + """ + return None + + def bulk_batch_size(self, fields, objs): + """ + Return the maximum allowed batch size for the backend. The fields + are the fields going to be inserted in the batch, the objs contains + all the objects to be inserted. + """ + return len(objs) + + def format_for_duration_arithmetic(self, sql): + raise NotImplementedError( + "subclasses of BaseDatabaseOperations may require a " + "format_for_duration_arithmetic() method." + ) + + def cache_key_culling_sql(self): + """ + Return an SQL query that retrieves the first cache key greater than the + n smallest. + + This is used by the 'db' cache backend to determine where to start + culling. + """ + cache_key = self.quote_name("cache_key") + return f"SELECT {cache_key} FROM %s ORDER BY {cache_key} LIMIT 1 OFFSET %%s" + + def unification_cast_sql(self, output_field): + """ + Given a field instance, return the SQL that casts the result of a union + to that type. The resulting string should contain a '%s' placeholder + for the expression being cast. + """ + return "%s" + + def date_extract_sql(self, lookup_type, sql, params): + """ + Given a lookup_type of 'year', 'month', or 'day', return the SQL that + extracts a value from the given date field field_name. + """ + raise NotImplementedError( + "subclasses of BaseDatabaseOperations may require a date_extract_sql() " + "method" + ) + + def date_trunc_sql(self, lookup_type, sql, params, tzname=None): + """ + Given a lookup_type of 'year', 'month', or 'day', return the SQL that + truncates the given date or datetime field field_name to a date object + with only the given specificity. + + If `tzname` is provided, the given value is truncated in a specific + timezone. + """ + raise NotImplementedError( + "subclasses of BaseDatabaseOperations may require a date_trunc_sql() " + "method." + ) + + def datetime_cast_date_sql(self, sql, params, tzname): + """ + Return the SQL to cast a datetime value to date value. + """ + raise NotImplementedError( + "subclasses of BaseDatabaseOperations may require a " + "datetime_cast_date_sql() method." + ) + + def datetime_cast_time_sql(self, sql, params, tzname): + """ + Return the SQL to cast a datetime value to time value. + """ + raise NotImplementedError( + "subclasses of BaseDatabaseOperations may require a " + "datetime_cast_time_sql() method" + ) + + def datetime_extract_sql(self, lookup_type, sql, params, tzname): + """ + Given a lookup_type of 'year', 'month', 'day', 'hour', 'minute', or + 'second', return the SQL that extracts a value from the given + datetime field field_name. + """ + raise NotImplementedError( + "subclasses of BaseDatabaseOperations may require a datetime_extract_sql() " + "method" + ) + + def datetime_trunc_sql(self, lookup_type, sql, params, tzname): + """ + Given a lookup_type of 'year', 'month', 'day', 'hour', 'minute', or + 'second', return the SQL that truncates the given datetime field + field_name to a datetime object with only the given specificity. + """ + raise NotImplementedError( + "subclasses of BaseDatabaseOperations may require a datetime_trunc_sql() " + "method" + ) + + def time_trunc_sql(self, lookup_type, sql, params, tzname=None): + """ + Given a lookup_type of 'hour', 'minute' or 'second', return the SQL + that truncates the given time or datetime field field_name to a time + object with only the given specificity. + + If `tzname` is provided, the given value is truncated in a specific + timezone. + """ + raise NotImplementedError( + "subclasses of BaseDatabaseOperations may require a time_trunc_sql() method" + ) + + def time_extract_sql(self, lookup_type, sql, params): + """ + Given a lookup_type of 'hour', 'minute', or 'second', return the SQL + that extracts a value from the given time field field_name. + """ + return self.date_extract_sql(lookup_type, sql, params) + + def deferrable_sql(self): + """ + Return the SQL to make a constraint "initially deferred" during a + CREATE TABLE statement. + """ + return "" + + def distinct_sql(self, fields, params): + """ + Return an SQL DISTINCT clause which removes duplicate rows from the + result set. If any fields are given, only check the given fields for + duplicates. + """ + if fields: + raise NotSupportedError( + "DISTINCT ON fields is not supported by this database backend" + ) + else: + return ["DISTINCT"], [] + + def fetch_returned_insert_columns(self, cursor, returning_params): + """ + Given a cursor object that has just performed an INSERT...RETURNING + statement into a table, return the newly created data. + """ + return cursor.fetchone() + + def field_cast_sql(self, db_type, internal_type): + """ + Given a column type (e.g. 'BLOB', 'VARCHAR') and an internal type + (e.g. 'GenericIPAddressField'), return the SQL to cast it before using + it in a WHERE statement. The resulting string should contain a '%s' + placeholder for the column being searched against. + """ + warnings.warn( + ( + "DatabaseOperations.field_cast_sql() is deprecated use " + "DatabaseOperations.lookup_cast() instead." + ), + RemovedInDjango60Warning, + ) + return "%s" + + def force_no_ordering(self): + """ + Return a list used in the "ORDER BY" clause to force no ordering at + all. Return an empty list to include nothing in the ordering. + """ + return [] + + def for_update_sql(self, nowait=False, skip_locked=False, of=(), no_key=False): + """ + Return the FOR UPDATE SQL clause to lock rows for an update operation. + """ + return "FOR%s UPDATE%s%s%s" % ( + " NO KEY" if no_key else "", + " OF %s" % ", ".join(of) if of else "", + " NOWAIT" if nowait else "", + " SKIP LOCKED" if skip_locked else "", + ) + + def _get_limit_offset_params(self, low_mark, high_mark): + offset = low_mark or 0 + if high_mark is not None: + return (high_mark - offset), offset + elif offset: + return self.connection.ops.no_limit_value(), offset + return None, offset + + def limit_offset_sql(self, low_mark, high_mark): + """Return LIMIT/OFFSET SQL clause.""" + limit, offset = self._get_limit_offset_params(low_mark, high_mark) + return " ".join( + sql + for sql in ( + ("LIMIT %d" % limit) if limit else None, + ("OFFSET %d" % offset) if offset else None, + ) + if sql + ) + + def last_executed_query(self, cursor, sql, params): + """ + Return a string of the query last executed by the given cursor, with + placeholders replaced with actual values. + + `sql` is the raw query containing placeholders and `params` is the + sequence of parameters. These are used by default, but this method + exists for database backends to provide a better implementation + according to their own quoting schemes. + """ + + # Convert params to contain string values. + def to_string(s): + return force_str(s, strings_only=True, errors="replace") + + if isinstance(params, (list, tuple)): + u_params = tuple(to_string(val) for val in params) + elif params is None: + u_params = () + else: + u_params = {to_string(k): to_string(v) for k, v in params.items()} + + return "QUERY = %r - PARAMS = %r" % (sql, u_params) + + def last_insert_id(self, cursor, table_name, pk_name): + """ + Given a cursor object that has just performed an INSERT statement into + a table that has an auto-incrementing ID, return the newly created ID. + + `pk_name` is the name of the primary-key column. + """ + return cursor.lastrowid + + def lookup_cast(self, lookup_type, internal_type=None): + """ + Return the string to use in a query when performing lookups + ("contains", "like", etc.). It should contain a '%s' placeholder for + the column being searched against. + """ + return "%s" + + def max_in_list_size(self): + """ + Return the maximum number of items that can be passed in a single 'IN' + list condition, or None if the backend does not impose a limit. + """ + return None + + def max_name_length(self): + """ + Return the maximum length of table and column names, or None if there + is no limit. + """ + return None + + def no_limit_value(self): + """ + Return the value to use for the LIMIT when we are wanting "LIMIT + infinity". Return None if the limit clause can be omitted in this case. + """ + raise NotImplementedError( + "subclasses of BaseDatabaseOperations may require a no_limit_value() method" + ) + + def pk_default_value(self): + """ + Return the value to use during an INSERT statement to specify that + the field should use its default value. + """ + return "DEFAULT" + + def prepare_sql_script(self, sql): + """ + Take an SQL script that may contain multiple lines and return a list + of statements to feed to successive cursor.execute() calls. + + Since few databases are able to process raw SQL scripts in a single + cursor.execute() call and PEP 249 doesn't talk about this use case, + the default implementation is conservative. + """ + return [ + sqlparse.format(statement, strip_comments=True) + for statement in sqlparse.split(sql) + if statement + ] + + def process_clob(self, value): + """ + Return the value of a CLOB column, for backends that return a locator + object that requires additional processing. + """ + return value + + def return_insert_columns(self, fields): + """ + For backends that support returning columns as part of an insert query, + return the SQL and params to append to the INSERT query. The returned + fragment should contain a format string to hold the appropriate column. + """ + pass + + def compiler(self, compiler_name): + """ + Return the SQLCompiler class corresponding to the given name, + in the namespace corresponding to the `compiler_module` attribute + on this backend. + """ + if self._cache is None: + self._cache = import_module(self.compiler_module) + return getattr(self._cache, compiler_name) + + def quote_name(self, name): + """ + Return a quoted version of the given table, index, or column name. Do + not quote the given name if it's already been quoted. + """ + raise NotImplementedError( + "subclasses of BaseDatabaseOperations may require a quote_name() method" + ) + + def regex_lookup(self, lookup_type): + """ + Return the string to use in a query when performing regular expression + lookups (using "regex" or "iregex"). It should contain a '%s' + placeholder for the column being searched against. + + If the feature is not supported (or part of it is not supported), raise + NotImplementedError. + """ + raise NotImplementedError( + "subclasses of BaseDatabaseOperations may require a regex_lookup() method" + ) + + def savepoint_create_sql(self, sid): + """ + Return the SQL for starting a new savepoint. Only required if the + "uses_savepoints" feature is True. The "sid" parameter is a string + for the savepoint id. + """ + return "SAVEPOINT %s" % self.quote_name(sid) + + def savepoint_commit_sql(self, sid): + """ + Return the SQL for committing the given savepoint. + """ + return "RELEASE SAVEPOINT %s" % self.quote_name(sid) + + def savepoint_rollback_sql(self, sid): + """ + Return the SQL for rolling back the given savepoint. + """ + return "ROLLBACK TO SAVEPOINT %s" % self.quote_name(sid) + + def set_time_zone_sql(self): + """ + Return the SQL that will set the connection's time zone. + + Return '' if the backend doesn't support time zones. + """ + return "" + + def sql_flush(self, style, tables, *, reset_sequences=False, allow_cascade=False): + """ + Return a list of SQL statements required to remove all data from + the given database tables (without actually removing the tables + themselves). + + The `style` argument is a Style object as returned by either + color_style() or no_style() in django.core.management.color. + + If `reset_sequences` is True, the list includes SQL statements required + to reset the sequences. + + The `allow_cascade` argument determines whether truncation may cascade + to tables with foreign keys pointing the tables being truncated. + PostgreSQL requires a cascade even if these tables are empty. + """ + raise NotImplementedError( + "subclasses of BaseDatabaseOperations must provide an sql_flush() method" + ) + + def execute_sql_flush(self, sql_list): + """Execute a list of SQL statements to flush the database.""" + with transaction.atomic( + using=self.connection.alias, + savepoint=self.connection.features.can_rollback_ddl, + ): + with self.connection.cursor() as cursor: + for sql in sql_list: + cursor.execute(sql) + + def sequence_reset_by_name_sql(self, style, sequences): + """ + Return a list of the SQL statements required to reset sequences + passed in `sequences`. + + The `style` argument is a Style object as returned by either + color_style() or no_style() in django.core.management.color. + """ + return [] + + def sequence_reset_sql(self, style, model_list): + """ + Return a list of the SQL statements required to reset sequences for + the given models. + + The `style` argument is a Style object as returned by either + color_style() or no_style() in django.core.management.color. + """ + return [] # No sequence reset required by default. + + def start_transaction_sql(self): + """Return the SQL statement required to start a transaction.""" + return "BEGIN;" + + def end_transaction_sql(self, success=True): + """Return the SQL statement required to end a transaction.""" + if not success: + return "ROLLBACK;" + return "COMMIT;" + + def tablespace_sql(self, tablespace, inline=False): + """ + Return the SQL that will be used in a query to define the tablespace. + + Return '' if the backend doesn't support tablespaces. + + If `inline` is True, append the SQL to a row; otherwise append it to + the entire CREATE TABLE or CREATE INDEX statement. + """ + return "" + + def prep_for_like_query(self, x): + """Prepare a value for use in a LIKE query.""" + return str(x).replace("\\", "\\\\").replace("%", r"\%").replace("_", r"\_") + + # Same as prep_for_like_query(), but called for "iexact" matches, which + # need not necessarily be implemented using "LIKE" in the backend. + prep_for_iexact_query = prep_for_like_query + + def validate_autopk_value(self, value): + """ + Certain backends do not accept some values for "serial" fields + (for example zero in MySQL). Raise a ValueError if the value is + invalid, otherwise return the validated value. + """ + return value + + def adapt_unknown_value(self, value): + """ + Transform a value to something compatible with the backend driver. + + This method only depends on the type of the value. It's designed for + cases where the target type isn't known, such as .raw() SQL queries. + As a consequence it may not work perfectly in all circumstances. + """ + if isinstance(value, datetime.datetime): # must be before date + return self.adapt_datetimefield_value(value) + elif isinstance(value, datetime.date): + return self.adapt_datefield_value(value) + elif isinstance(value, datetime.time): + return self.adapt_timefield_value(value) + elif isinstance(value, decimal.Decimal): + return self.adapt_decimalfield_value(value) + else: + return value + + def adapt_integerfield_value(self, value, internal_type): + return value + + def adapt_datefield_value(self, value): + """ + Transform a date value to an object compatible with what is expected + by the backend driver for date columns. + """ + if value is None: + return None + return str(value) + + def adapt_datetimefield_value(self, value): + """ + Transform a datetime value to an object compatible with what is expected + by the backend driver for datetime columns. + """ + if value is None: + return None + # Expression values are adapted by the database. + if hasattr(value, "resolve_expression"): + return value + + return str(value) + + def adapt_timefield_value(self, value): + """ + Transform a time value to an object compatible with what is expected + by the backend driver for time columns. + """ + if value is None: + return None + # Expression values are adapted by the database. + if hasattr(value, "resolve_expression"): + return value + + if timezone.is_aware(value): + raise ValueError("Django does not support timezone-aware times.") + return str(value) + + def adapt_decimalfield_value(self, value, max_digits=None, decimal_places=None): + """ + Transform a decimal.Decimal value to an object compatible with what is + expected by the backend driver for decimal (numeric) columns. + """ + return utils.format_number(value, max_digits, decimal_places) + + def adapt_ipaddressfield_value(self, value): + """ + Transform a string representation of an IP address into the expected + type for the backend driver. + """ + return value or None + + def adapt_json_value(self, value, encoder): + return json.dumps(value, cls=encoder) + + def year_lookup_bounds_for_date_field(self, value, iso_year=False): + """ + Return a two-elements list with the lower and upper bound to be used + with a BETWEEN operator to query a DateField value using a year + lookup. + + `value` is an int, containing the looked-up year. + If `iso_year` is True, return bounds for ISO-8601 week-numbering years. + """ + if iso_year: + first = datetime.date.fromisocalendar(value, 1, 1) + second = datetime.date.fromisocalendar( + value + 1, 1, 1 + ) - datetime.timedelta(days=1) + else: + first = datetime.date(value, 1, 1) + second = datetime.date(value, 12, 31) + first = self.adapt_datefield_value(first) + second = self.adapt_datefield_value(second) + return [first, second] + + def year_lookup_bounds_for_datetime_field(self, value, iso_year=False): + """ + Return a two-elements list with the lower and upper bound to be used + with a BETWEEN operator to query a DateTimeField value using a year + lookup. + + `value` is an int, containing the looked-up year. + If `iso_year` is True, return bounds for ISO-8601 week-numbering years. + """ + if iso_year: + first = datetime.datetime.fromisocalendar(value, 1, 1) + second = datetime.datetime.fromisocalendar( + value + 1, 1, 1 + ) - datetime.timedelta(microseconds=1) + else: + first = datetime.datetime(value, 1, 1) + second = datetime.datetime(value, 12, 31, 23, 59, 59, 999999) + if settings.USE_TZ: + tz = timezone.get_current_timezone() + first = timezone.make_aware(first, tz) + second = timezone.make_aware(second, tz) + first = self.adapt_datetimefield_value(first) + second = self.adapt_datetimefield_value(second) + return [first, second] + + def get_db_converters(self, expression): + """ + Return a list of functions needed to convert field data. + + Some field types on some backends do not provide data in the correct + format, this is the hook for converter functions. + """ + return [] + + def convert_durationfield_value(self, value, expression, connection): + if value is not None: + return datetime.timedelta(0, 0, value) + + def check_expression_support(self, expression): + """ + Check that the backend supports the provided expression. + + This is used on specific backends to rule out known expressions + that have problematic or nonexistent implementations. If the + expression has a known problem, the backend should raise + NotSupportedError. + """ + pass + + def conditional_expression_supported_in_where_clause(self, expression): + """ + Return True, if the conditional expression is supported in the WHERE + clause. + """ + return True + + def combine_expression(self, connector, sub_expressions): + """ + Combine a list of subexpressions into a single expression, using + the provided connecting operator. This is required because operators + can vary between backends (e.g., Oracle with %% and &) and between + subexpression types (e.g., date expressions). + """ + conn = " %s " % connector + return conn.join(sub_expressions) + + def combine_duration_expression(self, connector, sub_expressions): + return self.combine_expression(connector, sub_expressions) + + def binary_placeholder_sql(self, value): + """ + Some backends require special syntax to insert binary content (MySQL + for example uses '_binary %s'). + """ + return "%s" + + def modify_insert_params(self, placeholder, params): + """ + Allow modification of insert parameters. Needed for Oracle Spatial + backend due to #10888. + """ + return params + + def integer_field_range(self, internal_type): + """ + Given an integer field internal type (e.g. 'PositiveIntegerField'), + return a tuple of the (min_value, max_value) form representing the + range of the column type bound to the field. + """ + return self.integer_field_ranges[internal_type] + + def subtract_temporals(self, internal_type, lhs, rhs): + if self.connection.features.supports_temporal_subtraction: + lhs_sql, lhs_params = lhs + rhs_sql, rhs_params = rhs + return "(%s - %s)" % (lhs_sql, rhs_sql), (*lhs_params, *rhs_params) + raise NotSupportedError( + "This backend does not support %s subtraction." % internal_type + ) + + def window_frame_start(self, start): + if isinstance(start, int): + if start < 0: + return "%d %s" % (abs(start), self.PRECEDING) + elif start == 0: + return self.CURRENT_ROW + elif start is None: + return self.UNBOUNDED_PRECEDING + raise ValueError( + "start argument must be a negative integer, zero, or None, but got '%s'." + % start + ) + + def window_frame_end(self, end): + if isinstance(end, int): + if end == 0: + return self.CURRENT_ROW + elif end > 0: + return "%d %s" % (end, self.FOLLOWING) + elif end is None: + return self.UNBOUNDED_FOLLOWING + raise ValueError( + "end argument must be a positive integer, zero, or None, but got '%s'." + % end + ) + + def window_frame_rows_start_end(self, start=None, end=None): + """ + Return SQL for start and end points in an OVER clause window frame. + """ + if not self.connection.features.supports_over_clause: + raise NotSupportedError("This backend does not support window expressions.") + return self.window_frame_start(start), self.window_frame_end(end) + + def window_frame_range_start_end(self, start=None, end=None): + start_, end_ = self.window_frame_rows_start_end(start, end) + features = self.connection.features + if features.only_supports_unbounded_with_preceding_and_following and ( + (start and start < 0) or (end and end > 0) + ): + raise NotSupportedError( + "%s only supports UNBOUNDED together with PRECEDING and " + "FOLLOWING." % self.connection.display_name + ) + return start_, end_ + + def explain_query_prefix(self, format=None, **options): + if not self.connection.features.supports_explaining_query_execution: + raise NotSupportedError( + "This backend does not support explaining query execution." + ) + if format: + supported_formats = self.connection.features.supported_explain_formats + normalized_format = format.upper() + if normalized_format not in supported_formats: + msg = "%s is not a recognized format." % normalized_format + if supported_formats: + msg += " Allowed formats: %s" % ", ".join(sorted(supported_formats)) + else: + msg += ( + f" {self.connection.display_name} does not support any formats." + ) + raise ValueError(msg) + if options: + raise ValueError("Unknown options: %s" % ", ".join(sorted(options.keys()))) + return self.explain_prefix + + def insert_statement(self, on_conflict=None): + return "INSERT INTO" + + def on_conflict_suffix_sql(self, fields, on_conflict, update_fields, unique_fields): + return "" + + def prepare_join_on_clause(self, lhs_table, lhs_field, rhs_table, rhs_field): + lhs_expr = Col(lhs_table, lhs_field) + rhs_expr = Col(rhs_table, rhs_field) + + return lhs_expr, rhs_expr diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/schema.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/schema.py new file mode 100644 index 0000000..1062e9f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/schema.py @@ -0,0 +1,1994 @@ +import logging +import operator +from datetime import datetime + +from django.conf import settings +from django.db.backends.ddl_references import ( + Columns, + Expressions, + ForeignKeyName, + IndexName, + Statement, + Table, +) +from django.db.backends.utils import names_digest, split_identifier, truncate_name +from django.db.models import NOT_PROVIDED, Deferrable, Index +from django.db.models.sql import Query +from django.db.transaction import TransactionManagementError, atomic +from django.utils import timezone + +logger = logging.getLogger("django.db.backends.schema") + + +def _is_relevant_relation(relation, altered_field): + """ + When altering the given field, must constraints on its model from the given + relation be temporarily dropped? + """ + field = relation.field + if field.many_to_many: + # M2M reverse field + return False + if altered_field.primary_key and field.to_fields == [None]: + # Foreign key constraint on the primary key, which is being altered. + return True + # Is the constraint targeting the field being altered? + return altered_field.name in field.to_fields + + +def _all_related_fields(model): + # Related fields must be returned in a deterministic order. + return sorted( + model._meta._get_fields( + forward=False, + reverse=True, + include_hidden=True, + include_parents=False, + ), + key=operator.attrgetter("name"), + ) + + +def _related_non_m2m_objects(old_field, new_field): + # Filter out m2m objects from reverse relations. + # Return (old_relation, new_relation) tuples. + related_fields = zip( + ( + obj + for obj in _all_related_fields(old_field.model) + if _is_relevant_relation(obj, old_field) + ), + ( + obj + for obj in _all_related_fields(new_field.model) + if _is_relevant_relation(obj, new_field) + ), + ) + for old_rel, new_rel in related_fields: + yield old_rel, new_rel + yield from _related_non_m2m_objects( + old_rel.remote_field, + new_rel.remote_field, + ) + + +class BaseDatabaseSchemaEditor: + """ + This class and its subclasses are responsible for emitting schema-changing + statements to the databases - model creation/removal/alteration, field + renaming, index fiddling, and so on. + """ + + # Overrideable SQL templates + sql_create_table = "CREATE TABLE %(table)s (%(definition)s)" + sql_rename_table = "ALTER TABLE %(old_table)s RENAME TO %(new_table)s" + sql_retablespace_table = "ALTER TABLE %(table)s SET TABLESPACE %(new_tablespace)s" + sql_delete_table = "DROP TABLE %(table)s CASCADE" + + sql_create_column = "ALTER TABLE %(table)s ADD COLUMN %(column)s %(definition)s" + sql_alter_column = "ALTER TABLE %(table)s %(changes)s" + sql_alter_column_type = "ALTER COLUMN %(column)s TYPE %(type)s%(collation)s" + sql_alter_column_null = "ALTER COLUMN %(column)s DROP NOT NULL" + sql_alter_column_not_null = "ALTER COLUMN %(column)s SET NOT NULL" + sql_alter_column_default = "ALTER COLUMN %(column)s SET DEFAULT %(default)s" + sql_alter_column_no_default = "ALTER COLUMN %(column)s DROP DEFAULT" + sql_alter_column_no_default_null = sql_alter_column_no_default + sql_delete_column = "ALTER TABLE %(table)s DROP COLUMN %(column)s CASCADE" + sql_rename_column = ( + "ALTER TABLE %(table)s RENAME COLUMN %(old_column)s TO %(new_column)s" + ) + sql_update_with_default = ( + "UPDATE %(table)s SET %(column)s = %(default)s WHERE %(column)s IS NULL" + ) + + sql_unique_constraint = "UNIQUE (%(columns)s)%(deferrable)s" + sql_check_constraint = "CHECK (%(check)s)" + sql_delete_constraint = "ALTER TABLE %(table)s DROP CONSTRAINT %(name)s" + sql_constraint = "CONSTRAINT %(name)s %(constraint)s" + + sql_create_check = "ALTER TABLE %(table)s ADD CONSTRAINT %(name)s CHECK (%(check)s)" + sql_delete_check = sql_delete_constraint + + sql_create_unique = ( + "ALTER TABLE %(table)s ADD CONSTRAINT %(name)s " + "UNIQUE%(nulls_distinct)s (%(columns)s)%(deferrable)s" + ) + sql_delete_unique = sql_delete_constraint + + sql_create_fk = ( + "ALTER TABLE %(table)s ADD CONSTRAINT %(name)s FOREIGN KEY (%(column)s) " + "REFERENCES %(to_table)s (%(to_column)s)%(deferrable)s" + ) + sql_create_inline_fk = None + sql_create_column_inline_fk = None + sql_delete_fk = sql_delete_constraint + + sql_create_index = ( + "CREATE INDEX %(name)s ON %(table)s " + "(%(columns)s)%(include)s%(extra)s%(condition)s" + ) + sql_create_unique_index = ( + "CREATE UNIQUE INDEX %(name)s ON %(table)s " + "(%(columns)s)%(include)s%(condition)s%(nulls_distinct)s" + ) + sql_rename_index = "ALTER INDEX %(old_name)s RENAME TO %(new_name)s" + sql_delete_index = "DROP INDEX %(name)s" + + sql_create_pk = ( + "ALTER TABLE %(table)s ADD CONSTRAINT %(name)s PRIMARY KEY (%(columns)s)" + ) + sql_delete_pk = sql_delete_constraint + + sql_delete_procedure = "DROP PROCEDURE %(procedure)s" + + sql_alter_table_comment = "COMMENT ON TABLE %(table)s IS %(comment)s" + sql_alter_column_comment = "COMMENT ON COLUMN %(table)s.%(column)s IS %(comment)s" + + def __init__(self, connection, collect_sql=False, atomic=True): + self.connection = connection + self.collect_sql = collect_sql + if self.collect_sql: + self.collected_sql = [] + self.atomic_migration = self.connection.features.can_rollback_ddl and atomic + + # State-managing methods + + def __enter__(self): + self.deferred_sql = [] + if self.atomic_migration: + self.atomic = atomic(self.connection.alias) + self.atomic.__enter__() + return self + + def __exit__(self, exc_type, exc_value, traceback): + if exc_type is None: + for sql in self.deferred_sql: + self.execute(sql) + if self.atomic_migration: + self.atomic.__exit__(exc_type, exc_value, traceback) + + # Core utility functions + + def execute(self, sql, params=()): + """Execute the given SQL statement, with optional parameters.""" + # Don't perform the transactional DDL check if SQL is being collected + # as it's not going to be executed anyway. + if ( + not self.collect_sql + and self.connection.in_atomic_block + and not self.connection.features.can_rollback_ddl + ): + raise TransactionManagementError( + "Executing DDL statements while in a transaction on databases " + "that can't perform a rollback is prohibited." + ) + # Account for non-string statement objects. + sql = str(sql) + # Log the command we're running, then run it + logger.debug( + "%s; (params %r)", sql, params, extra={"params": params, "sql": sql} + ) + if self.collect_sql: + ending = "" if sql.rstrip().endswith(";") else ";" + if params is not None: + self.collected_sql.append( + (sql % tuple(map(self.quote_value, params))) + ending + ) + else: + self.collected_sql.append(sql + ending) + else: + with self.connection.cursor() as cursor: + cursor.execute(sql, params) + + def quote_name(self, name): + return self.connection.ops.quote_name(name) + + def table_sql(self, model): + """Take a model and return its table definition.""" + # Add any unique_togethers (always deferred, as some fields might be + # created afterward, like geometry fields with some backends). + for field_names in model._meta.unique_together: + fields = [model._meta.get_field(field) for field in field_names] + self.deferred_sql.append(self._create_unique_sql(model, fields)) + # Create column SQL, add FK deferreds if needed. + column_sqls = [] + params = [] + for field in model._meta.local_fields: + # SQL. + definition, extra_params = self.column_sql(model, field) + if definition is None: + continue + # Check constraints can go on the column SQL here. + db_params = field.db_parameters(connection=self.connection) + if db_params["check"]: + definition += " " + self.sql_check_constraint % db_params + # Autoincrement SQL (for backends with inline variant). + col_type_suffix = field.db_type_suffix(connection=self.connection) + if col_type_suffix: + definition += " %s" % col_type_suffix + params.extend(extra_params) + # FK. + if field.remote_field and field.db_constraint: + to_table = field.remote_field.model._meta.db_table + to_column = field.remote_field.model._meta.get_field( + field.remote_field.field_name + ).column + if self.sql_create_inline_fk: + definition += " " + self.sql_create_inline_fk % { + "to_table": self.quote_name(to_table), + "to_column": self.quote_name(to_column), + } + elif self.connection.features.supports_foreign_keys: + self.deferred_sql.append( + self._create_fk_sql( + model, field, "_fk_%(to_table)s_%(to_column)s" + ) + ) + # Add the SQL to our big list. + column_sqls.append( + "%s %s" + % ( + self.quote_name(field.column), + definition, + ) + ) + # Autoincrement SQL (for backends with post table definition + # variant). + if field.get_internal_type() in ( + "AutoField", + "BigAutoField", + "SmallAutoField", + ): + autoinc_sql = self.connection.ops.autoinc_sql( + model._meta.db_table, field.column + ) + if autoinc_sql: + self.deferred_sql.extend(autoinc_sql) + constraints = [ + constraint.constraint_sql(model, self) + for constraint in model._meta.constraints + ] + sql = self.sql_create_table % { + "table": self.quote_name(model._meta.db_table), + "definition": ", ".join( + str(constraint) + for constraint in (*column_sqls, *constraints) + if constraint + ), + } + if model._meta.db_tablespace: + tablespace_sql = self.connection.ops.tablespace_sql( + model._meta.db_tablespace + ) + if tablespace_sql: + sql += " " + tablespace_sql + return sql, params + + # Field <-> database mapping functions + + def _iter_column_sql( + self, column_db_type, params, model, field, field_db_params, include_default + ): + yield column_db_type + if collation := field_db_params.get("collation"): + yield self._collate_sql(collation) + if self.connection.features.supports_comments_inline and field.db_comment: + yield self._comment_sql(field.db_comment) + # Work out nullability. + null = field.null + # Add database default. + if field.db_default is not NOT_PROVIDED: + default_sql, default_params = self.db_default_sql(field) + yield f"DEFAULT {default_sql}" + params.extend(default_params) + include_default = False + # Include a default value, if requested. + include_default = ( + include_default + and not self.skip_default(field) + and + # Don't include a default value if it's a nullable field and the + # default cannot be dropped in the ALTER COLUMN statement (e.g. + # MySQL longtext and longblob). + not (null and self.skip_default_on_alter(field)) + ) + if include_default: + default_value = self.effective_default(field) + if default_value is not None: + column_default = "DEFAULT " + self._column_default_sql(field) + if self.connection.features.requires_literal_defaults: + # Some databases can't take defaults as a parameter (Oracle). + # If this is the case, the individual schema backend should + # implement prepare_default(). + yield column_default % self.prepare_default(default_value) + else: + yield column_default + params.append(default_value) + # Oracle treats the empty string ('') as null, so coerce the null + # option whenever '' is a possible value. + if ( + field.empty_strings_allowed + and not field.primary_key + and self.connection.features.interprets_empty_strings_as_nulls + ): + null = True + if field.generated: + yield self._column_generated_sql(field) + elif not null: + yield "NOT NULL" + elif not self.connection.features.implied_column_null: + yield "NULL" + if field.primary_key: + yield "PRIMARY KEY" + elif field.unique: + yield "UNIQUE" + # Optionally add the tablespace if it's an implicitly indexed column. + tablespace = field.db_tablespace or model._meta.db_tablespace + if ( + tablespace + and self.connection.features.supports_tablespaces + and field.unique + ): + yield self.connection.ops.tablespace_sql(tablespace, inline=True) + + def column_sql(self, model, field, include_default=False): + """ + Return the column definition for a field. The field must already have + had set_attributes_from_name() called. + """ + # Get the column's type and use that as the basis of the SQL. + field_db_params = field.db_parameters(connection=self.connection) + column_db_type = field_db_params["type"] + # Check for fields that aren't actually columns (e.g. M2M). + if column_db_type is None: + return None, None + params = [] + return ( + " ".join( + # This appends to the params being returned. + self._iter_column_sql( + column_db_type, + params, + model, + field, + field_db_params, + include_default, + ) + ), + params, + ) + + def skip_default(self, field): + """ + Some backends don't accept default values for certain columns types + (i.e. MySQL longtext and longblob). + """ + return False + + def skip_default_on_alter(self, field): + """ + Some backends don't accept default values for certain columns types + (i.e. MySQL longtext and longblob) in the ALTER COLUMN statement. + """ + return False + + def prepare_default(self, value): + """ + Only used for backends which have requires_literal_defaults feature + """ + raise NotImplementedError( + "subclasses of BaseDatabaseSchemaEditor for backends which have " + "requires_literal_defaults must provide a prepare_default() method" + ) + + def _column_default_sql(self, field): + """ + Return the SQL to use in a DEFAULT clause. The resulting string should + contain a '%s' placeholder for a default value. + """ + return "%s" + + def db_default_sql(self, field): + """Return the sql and params for the field's database default.""" + from django.db.models.expressions import Value + + sql = "%s" if isinstance(field.db_default, Value) else "(%s)" + query = Query(model=field.model) + compiler = query.get_compiler(connection=self.connection) + default_sql, params = compiler.compile(field.db_default) + if self.connection.features.requires_literal_defaults: + # Some databases doesn't support parameterized defaults (Oracle, + # SQLite). If this is the case, the individual schema backend + # should implement prepare_default(). + default_sql %= tuple(self.prepare_default(p) for p in params) + params = [] + return sql % default_sql, params + + def _column_generated_sql(self, field): + """Return the SQL to use in a GENERATED ALWAYS clause.""" + expression_sql, params = field.generated_sql(self.connection) + persistency_sql = "STORED" if field.db_persist else "VIRTUAL" + if params: + expression_sql = expression_sql % tuple(self.quote_value(p) for p in params) + return f"GENERATED ALWAYS AS ({expression_sql}) {persistency_sql}" + + @staticmethod + def _effective_default(field): + # This method allows testing its logic without a connection. + if field.has_default(): + default = field.get_default() + elif field.generated: + default = None + elif not field.null and field.blank and field.empty_strings_allowed: + if field.get_internal_type() == "BinaryField": + default = b"" + else: + default = "" + elif getattr(field, "auto_now", False) or getattr(field, "auto_now_add", False): + internal_type = field.get_internal_type() + if internal_type == "DateTimeField": + default = timezone.now() + else: + default = datetime.now() + if internal_type == "DateField": + default = default.date() + elif internal_type == "TimeField": + default = default.time() + else: + default = None + return default + + def effective_default(self, field): + """Return a field's effective database default value.""" + return field.get_db_prep_save(self._effective_default(field), self.connection) + + def quote_value(self, value): + """ + Return a quoted version of the value so it's safe to use in an SQL + string. This is not safe against injection from user code; it is + intended only for use in making SQL scripts or preparing default values + for particularly tricky backends (defaults are not user-defined, though, + so this is safe). + """ + raise NotImplementedError() + + # Actions + + def create_model(self, model): + """ + Create a table and any accompanying indexes or unique constraints for + the given `model`. + """ + sql, params = self.table_sql(model) + # Prevent using [] as params, in the case a literal '%' is used in the + # definition. + self.execute(sql, params or None) + + if self.connection.features.supports_comments: + # Add table comment. + if model._meta.db_table_comment: + self.alter_db_table_comment(model, None, model._meta.db_table_comment) + # Add column comments. + if not self.connection.features.supports_comments_inline: + for field in model._meta.local_fields: + if field.db_comment: + field_db_params = field.db_parameters( + connection=self.connection + ) + field_type = field_db_params["type"] + self.execute( + *self._alter_column_comment_sql( + model, field, field_type, field.db_comment + ) + ) + # Add any field index and index_together's (deferred as SQLite + # _remake_table needs it). + self.deferred_sql.extend(self._model_indexes_sql(model)) + + # Make M2M tables + for field in model._meta.local_many_to_many: + if field.remote_field.through._meta.auto_created: + self.create_model(field.remote_field.through) + + def delete_model(self, model): + """Delete a model from the database.""" + # Handle auto-created intermediary models + for field in model._meta.local_many_to_many: + if field.remote_field.through._meta.auto_created: + self.delete_model(field.remote_field.through) + + # Delete the table + self.execute( + self.sql_delete_table + % { + "table": self.quote_name(model._meta.db_table), + } + ) + # Remove all deferred statements referencing the deleted table. + for sql in list(self.deferred_sql): + if isinstance(sql, Statement) and sql.references_table( + model._meta.db_table + ): + self.deferred_sql.remove(sql) + + def add_index(self, model, index): + """Add an index on a model.""" + if ( + index.contains_expressions + and not self.connection.features.supports_expression_indexes + ): + return None + # Index.create_sql returns interpolated SQL which makes params=None a + # necessity to avoid escaping attempts on execution. + self.execute(index.create_sql(model, self), params=None) + + def remove_index(self, model, index): + """Remove an index from a model.""" + if ( + index.contains_expressions + and not self.connection.features.supports_expression_indexes + ): + return None + self.execute(index.remove_sql(model, self)) + + def rename_index(self, model, old_index, new_index): + if self.connection.features.can_rename_index: + self.execute( + self._rename_index_sql(model, old_index.name, new_index.name), + params=None, + ) + else: + self.remove_index(model, old_index) + self.add_index(model, new_index) + + def add_constraint(self, model, constraint): + """Add a constraint to a model.""" + sql = constraint.create_sql(model, self) + if sql: + # Constraint.create_sql returns interpolated SQL which makes + # params=None a necessity to avoid escaping attempts on execution. + self.execute(sql, params=None) + + def remove_constraint(self, model, constraint): + """Remove a constraint from a model.""" + sql = constraint.remove_sql(model, self) + if sql: + self.execute(sql) + + def alter_unique_together(self, model, old_unique_together, new_unique_together): + """ + Deal with a model changing its unique_together. The input + unique_togethers must be doubly-nested, not the single-nested + ["foo", "bar"] format. + """ + olds = {tuple(fields) for fields in old_unique_together} + news = {tuple(fields) for fields in new_unique_together} + # Deleted uniques + for fields in olds.difference(news): + self._delete_composed_index( + model, + fields, + {"unique": True, "primary_key": False}, + self.sql_delete_unique, + ) + # Created uniques + for field_names in news.difference(olds): + fields = [model._meta.get_field(field) for field in field_names] + self.execute(self._create_unique_sql(model, fields)) + + def alter_index_together(self, model, old_index_together, new_index_together): + """ + Deal with a model changing its index_together. The input + index_togethers must be doubly-nested, not the single-nested + ["foo", "bar"] format. + """ + olds = {tuple(fields) for fields in old_index_together} + news = {tuple(fields) for fields in new_index_together} + # Deleted indexes + for fields in olds.difference(news): + self._delete_composed_index( + model, + fields, + {"index": True, "unique": False}, + self.sql_delete_index, + ) + # Created indexes + for field_names in news.difference(olds): + fields = [model._meta.get_field(field) for field in field_names] + self.execute(self._create_index_sql(model, fields=fields, suffix="_idx")) + + def _delete_composed_index(self, model, fields, constraint_kwargs, sql): + meta_constraint_names = { + constraint.name for constraint in model._meta.constraints + } + meta_index_names = {constraint.name for constraint in model._meta.indexes} + columns = [model._meta.get_field(field).column for field in fields] + constraint_names = self._constraint_names( + model, + columns, + exclude=meta_constraint_names | meta_index_names, + **constraint_kwargs, + ) + if ( + constraint_kwargs.get("unique") is True + and constraint_names + and self.connection.features.allows_multiple_constraints_on_same_fields + ): + # Constraint matching the unique_together name. + default_name = str( + self._unique_constraint_name(model._meta.db_table, columns, quote=False) + ) + if default_name in constraint_names: + constraint_names = [default_name] + if len(constraint_names) != 1: + raise ValueError( + "Found wrong number (%s) of constraints for %s(%s)" + % ( + len(constraint_names), + model._meta.db_table, + ", ".join(columns), + ) + ) + self.execute(self._delete_constraint_sql(sql, model, constraint_names[0])) + + def alter_db_table(self, model, old_db_table, new_db_table): + """Rename the table a model points to.""" + if old_db_table == new_db_table or ( + self.connection.features.ignores_table_name_case + and old_db_table.lower() == new_db_table.lower() + ): + return + self.execute( + self.sql_rename_table + % { + "old_table": self.quote_name(old_db_table), + "new_table": self.quote_name(new_db_table), + } + ) + # Rename all references to the old table name. + for sql in self.deferred_sql: + if isinstance(sql, Statement): + sql.rename_table_references(old_db_table, new_db_table) + + def alter_db_table_comment(self, model, old_db_table_comment, new_db_table_comment): + if self.sql_alter_table_comment and self.connection.features.supports_comments: + self.execute( + self.sql_alter_table_comment + % { + "table": self.quote_name(model._meta.db_table), + "comment": self.quote_value(new_db_table_comment or ""), + } + ) + + def alter_db_tablespace(self, model, old_db_tablespace, new_db_tablespace): + """Move a model's table between tablespaces.""" + self.execute( + self.sql_retablespace_table + % { + "table": self.quote_name(model._meta.db_table), + "old_tablespace": self.quote_name(old_db_tablespace), + "new_tablespace": self.quote_name(new_db_tablespace), + } + ) + + def add_field(self, model, field): + """ + Create a field on a model. Usually involves adding a column, but may + involve adding a table instead (for M2M fields). + """ + # Special-case implicit M2M tables + if field.many_to_many and field.remote_field.through._meta.auto_created: + return self.create_model(field.remote_field.through) + # Get the column's definition + definition, params = self.column_sql(model, field, include_default=True) + # It might not actually have a column behind it + if definition is None: + return + if col_type_suffix := field.db_type_suffix(connection=self.connection): + definition += f" {col_type_suffix}" + # Check constraints can go on the column SQL here + db_params = field.db_parameters(connection=self.connection) + if db_params["check"]: + definition += " " + self.sql_check_constraint % db_params + if ( + field.remote_field + and self.connection.features.supports_foreign_keys + and field.db_constraint + ): + constraint_suffix = "_fk_%(to_table)s_%(to_column)s" + # Add FK constraint inline, if supported. + if self.sql_create_column_inline_fk: + to_table = field.remote_field.model._meta.db_table + to_column = field.remote_field.model._meta.get_field( + field.remote_field.field_name + ).column + namespace, _ = split_identifier(model._meta.db_table) + definition += " " + self.sql_create_column_inline_fk % { + "name": self._fk_constraint_name(model, field, constraint_suffix), + "namespace": "%s." % self.quote_name(namespace) + if namespace + else "", + "column": self.quote_name(field.column), + "to_table": self.quote_name(to_table), + "to_column": self.quote_name(to_column), + "deferrable": self.connection.ops.deferrable_sql(), + } + # Otherwise, add FK constraints later. + else: + self.deferred_sql.append( + self._create_fk_sql(model, field, constraint_suffix) + ) + # Build the SQL and run it + sql = self.sql_create_column % { + "table": self.quote_name(model._meta.db_table), + "column": self.quote_name(field.column), + "definition": definition, + } + self.execute(sql, params) + # Drop the default if we need to + if ( + field.db_default is NOT_PROVIDED + and not self.skip_default_on_alter(field) + and self.effective_default(field) is not None + ): + changes_sql, params = self._alter_column_default_sql( + model, None, field, drop=True + ) + sql = self.sql_alter_column % { + "table": self.quote_name(model._meta.db_table), + "changes": changes_sql, + } + self.execute(sql, params) + # Add field comment, if required. + if ( + field.db_comment + and self.connection.features.supports_comments + and not self.connection.features.supports_comments_inline + ): + field_type = db_params["type"] + self.execute( + *self._alter_column_comment_sql( + model, field, field_type, field.db_comment + ) + ) + # Add an index, if required + self.deferred_sql.extend(self._field_indexes_sql(model, field)) + # Reset connection if required + if self.connection.features.connection_persists_old_columns: + self.connection.close() + + def remove_field(self, model, field): + """ + Remove a field from a model. Usually involves deleting a column, + but for M2Ms may involve deleting a table. + """ + # Special-case implicit M2M tables + if field.many_to_many and field.remote_field.through._meta.auto_created: + return self.delete_model(field.remote_field.through) + # It might not actually have a column behind it + if field.db_parameters(connection=self.connection)["type"] is None: + return + # Drop any FK constraints, MySQL requires explicit deletion + if field.remote_field: + fk_names = self._constraint_names(model, [field.column], foreign_key=True) + for fk_name in fk_names: + self.execute(self._delete_fk_sql(model, fk_name)) + # Delete the column + sql = self.sql_delete_column % { + "table": self.quote_name(model._meta.db_table), + "column": self.quote_name(field.column), + } + self.execute(sql) + # Reset connection if required + if self.connection.features.connection_persists_old_columns: + self.connection.close() + # Remove all deferred statements referencing the deleted column. + for sql in list(self.deferred_sql): + if isinstance(sql, Statement) and sql.references_column( + model._meta.db_table, field.column + ): + self.deferred_sql.remove(sql) + + def alter_field(self, model, old_field, new_field, strict=False): + """ + Allow a field's type, uniqueness, nullability, default, column, + constraints, etc. to be modified. + `old_field` is required to compute the necessary changes. + If `strict` is True, raise errors if the old column does not match + `old_field` precisely. + """ + if not self._field_should_be_altered(old_field, new_field): + return + # Ensure this field is even column-based + old_db_params = old_field.db_parameters(connection=self.connection) + old_type = old_db_params["type"] + new_db_params = new_field.db_parameters(connection=self.connection) + new_type = new_db_params["type"] + if (old_type is None and old_field.remote_field is None) or ( + new_type is None and new_field.remote_field is None + ): + raise ValueError( + "Cannot alter field %s into %s - they do not properly define " + "db_type (are you using a badly-written custom field?)" + % (old_field, new_field), + ) + elif ( + old_type is None + and new_type is None + and ( + old_field.remote_field.through + and new_field.remote_field.through + and old_field.remote_field.through._meta.auto_created + and new_field.remote_field.through._meta.auto_created + ) + ): + return self._alter_many_to_many(model, old_field, new_field, strict) + elif ( + old_type is None + and new_type is None + and ( + old_field.remote_field.through + and new_field.remote_field.through + and not old_field.remote_field.through._meta.auto_created + and not new_field.remote_field.through._meta.auto_created + ) + ): + # Both sides have through models; this is a no-op. + return + elif old_type is None or new_type is None: + raise ValueError( + "Cannot alter field %s into %s - they are not compatible types " + "(you cannot alter to or from M2M fields, or add or remove " + "through= on M2M fields)" % (old_field, new_field) + ) + elif old_field.generated != new_field.generated or ( + new_field.generated + and ( + old_field.db_persist != new_field.db_persist + or old_field.generated_sql(self.connection) + != new_field.generated_sql(self.connection) + ) + ): + raise ValueError( + f"Modifying GeneratedFields is not supported - the field {new_field} " + "must be removed and re-added with the new definition." + ) + + self._alter_field( + model, + old_field, + new_field, + old_type, + new_type, + old_db_params, + new_db_params, + strict, + ) + + def _field_db_check(self, field, field_db_params): + # Always check constraints with the same mocked column name to avoid + # recreating constrains when the column is renamed. + check_constraints = self.connection.data_type_check_constraints + data = field.db_type_parameters(self.connection) + data["column"] = "__column_name__" + try: + return check_constraints[field.get_internal_type()] % data + except KeyError: + return None + + def _alter_field( + self, + model, + old_field, + new_field, + old_type, + new_type, + old_db_params, + new_db_params, + strict=False, + ): + """Perform a "physical" (non-ManyToMany) field update.""" + # Drop any FK constraints, we'll remake them later + fks_dropped = set() + if ( + self.connection.features.supports_foreign_keys + and old_field.remote_field + and old_field.db_constraint + and self._field_should_be_altered( + old_field, + new_field, + ignore={"db_comment"}, + ) + ): + fk_names = self._constraint_names( + model, [old_field.column], foreign_key=True + ) + if strict and len(fk_names) != 1: + raise ValueError( + "Found wrong number (%s) of foreign key constraints for %s.%s" + % ( + len(fk_names), + model._meta.db_table, + old_field.column, + ) + ) + for fk_name in fk_names: + fks_dropped.add((old_field.column,)) + self.execute(self._delete_fk_sql(model, fk_name)) + # Has unique been removed? + if old_field.unique and ( + not new_field.unique or self._field_became_primary_key(old_field, new_field) + ): + # Find the unique constraint for this field + meta_constraint_names = { + constraint.name for constraint in model._meta.constraints + } + constraint_names = self._constraint_names( + model, + [old_field.column], + unique=True, + primary_key=False, + exclude=meta_constraint_names, + ) + if strict and len(constraint_names) != 1: + raise ValueError( + "Found wrong number (%s) of unique constraints for %s.%s" + % ( + len(constraint_names), + model._meta.db_table, + old_field.column, + ) + ) + for constraint_name in constraint_names: + self.execute(self._delete_unique_sql(model, constraint_name)) + # Drop incoming FK constraints if the field is a primary key or unique, + # which might be a to_field target, and things are going to change. + old_collation = old_db_params.get("collation") + new_collation = new_db_params.get("collation") + drop_foreign_keys = ( + self.connection.features.supports_foreign_keys + and ( + (old_field.primary_key and new_field.primary_key) + or (old_field.unique and new_field.unique) + ) + and ((old_type != new_type) or (old_collation != new_collation)) + ) + if drop_foreign_keys: + # '_meta.related_field' also contains M2M reverse fields, these + # will be filtered out + for _old_rel, new_rel in _related_non_m2m_objects(old_field, new_field): + rel_fk_names = self._constraint_names( + new_rel.related_model, [new_rel.field.column], foreign_key=True + ) + for fk_name in rel_fk_names: + self.execute(self._delete_fk_sql(new_rel.related_model, fk_name)) + # Removed an index? (no strict check, as multiple indexes are possible) + # Remove indexes if db_index switched to False or a unique constraint + # will now be used in lieu of an index. The following lines from the + # truth table show all True cases; the rest are False: + # + # old_field.db_index | old_field.unique | new_field.db_index | new_field.unique + # ------------------------------------------------------------------------------ + # True | False | False | False + # True | False | False | True + # True | False | True | True + if ( + old_field.db_index + and not old_field.unique + and (not new_field.db_index or new_field.unique) + ): + # Find the index for this field + meta_index_names = {index.name for index in model._meta.indexes} + # Retrieve only BTREE indexes since this is what's created with + # db_index=True. + index_names = self._constraint_names( + model, + [old_field.column], + index=True, + type_=Index.suffix, + exclude=meta_index_names, + ) + for index_name in index_names: + # The only way to check if an index was created with + # db_index=True or with Index(['field'], name='foo') + # is to look at its name (refs #28053). + self.execute(self._delete_index_sql(model, index_name)) + # Change check constraints? + old_db_check = self._field_db_check(old_field, old_db_params) + new_db_check = self._field_db_check(new_field, new_db_params) + if old_db_check != new_db_check and old_db_check: + meta_constraint_names = { + constraint.name for constraint in model._meta.constraints + } + constraint_names = self._constraint_names( + model, + [old_field.column], + check=True, + exclude=meta_constraint_names, + ) + if strict and len(constraint_names) != 1: + raise ValueError( + "Found wrong number (%s) of check constraints for %s.%s" + % ( + len(constraint_names), + model._meta.db_table, + old_field.column, + ) + ) + for constraint_name in constraint_names: + self.execute(self._delete_check_sql(model, constraint_name)) + # Have they renamed the column? + if old_field.column != new_field.column: + self.execute( + self._rename_field_sql( + model._meta.db_table, old_field, new_field, new_type + ) + ) + # Rename all references to the renamed column. + for sql in self.deferred_sql: + if isinstance(sql, Statement): + sql.rename_column_references( + model._meta.db_table, old_field.column, new_field.column + ) + # Next, start accumulating actions to do + actions = [] + null_actions = [] + post_actions = [] + # Type suffix change? (e.g. auto increment). + old_type_suffix = old_field.db_type_suffix(connection=self.connection) + new_type_suffix = new_field.db_type_suffix(connection=self.connection) + # Type, collation, or comment change? + if ( + old_type != new_type + or old_type_suffix != new_type_suffix + or old_collation != new_collation + or ( + self.connection.features.supports_comments + and old_field.db_comment != new_field.db_comment + ) + ): + fragment, other_actions = self._alter_column_type_sql( + model, old_field, new_field, new_type, old_collation, new_collation + ) + actions.append(fragment) + post_actions.extend(other_actions) + + if new_field.db_default is not NOT_PROVIDED: + if ( + old_field.db_default is NOT_PROVIDED + or new_field.db_default != old_field.db_default + ): + actions.append( + self._alter_column_database_default_sql(model, old_field, new_field) + ) + elif old_field.db_default is not NOT_PROVIDED: + actions.append( + self._alter_column_database_default_sql( + model, old_field, new_field, drop=True + ) + ) + # When changing a column NULL constraint to NOT NULL with a given + # default value, we need to perform 4 steps: + # 1. Add a default for new incoming writes + # 2. Update existing NULL rows with new default + # 3. Replace NULL constraint with NOT NULL + # 4. Drop the default again. + # Default change? + needs_database_default = False + if ( + old_field.null + and not new_field.null + and new_field.db_default is NOT_PROVIDED + ): + old_default = self.effective_default(old_field) + new_default = self.effective_default(new_field) + if ( + not self.skip_default_on_alter(new_field) + and old_default != new_default + and new_default is not None + ): + needs_database_default = True + actions.append( + self._alter_column_default_sql(model, old_field, new_field) + ) + # Nullability change? + if old_field.null != new_field.null: + fragment = self._alter_column_null_sql(model, old_field, new_field) + if fragment: + null_actions.append(fragment) + # Only if we have a default and there is a change from NULL to NOT NULL + four_way_default_alteration = ( + new_field.has_default() or new_field.db_default is not NOT_PROVIDED + ) and (old_field.null and not new_field.null) + if actions or null_actions: + if not four_way_default_alteration: + # If we don't have to do a 4-way default alteration we can + # directly run a (NOT) NULL alteration + actions += null_actions + # Combine actions together if we can (e.g. postgres) + if self.connection.features.supports_combined_alters and actions: + sql, params = tuple(zip(*actions)) + actions = [(", ".join(sql), sum(params, []))] + # Apply those actions + for sql, params in actions: + self.execute( + self.sql_alter_column + % { + "table": self.quote_name(model._meta.db_table), + "changes": sql, + }, + params, + ) + if four_way_default_alteration: + if new_field.db_default is NOT_PROVIDED: + default_sql = "%s" + params = [new_default] + else: + default_sql, params = self.db_default_sql(new_field) + # Update existing rows with default value + self.execute( + self.sql_update_with_default + % { + "table": self.quote_name(model._meta.db_table), + "column": self.quote_name(new_field.column), + "default": default_sql, + }, + params, + ) + # Since we didn't run a NOT NULL change before we need to do it + # now + for sql, params in null_actions: + self.execute( + self.sql_alter_column + % { + "table": self.quote_name(model._meta.db_table), + "changes": sql, + }, + params, + ) + if post_actions: + for sql, params in post_actions: + self.execute(sql, params) + # If primary_key changed to False, delete the primary key constraint. + if old_field.primary_key and not new_field.primary_key: + self._delete_primary_key(model, strict) + # Added a unique? + if self._unique_should_be_added(old_field, new_field): + self.execute(self._create_unique_sql(model, [new_field])) + # Added an index? Add an index if db_index switched to True or a unique + # constraint will no longer be used in lieu of an index. The following + # lines from the truth table show all True cases; the rest are False: + # + # old_field.db_index | old_field.unique | new_field.db_index | new_field.unique + # ------------------------------------------------------------------------------ + # False | False | True | False + # False | True | True | False + # True | True | True | False + if ( + (not old_field.db_index or old_field.unique) + and new_field.db_index + and not new_field.unique + ): + self.execute(self._create_index_sql(model, fields=[new_field])) + # Type alteration on primary key? Then we need to alter the column + # referring to us. + rels_to_update = [] + if drop_foreign_keys: + rels_to_update.extend(_related_non_m2m_objects(old_field, new_field)) + # Changed to become primary key? + if self._field_became_primary_key(old_field, new_field): + # Make the new one + self.execute(self._create_primary_key_sql(model, new_field)) + # Update all referencing columns + rels_to_update.extend(_related_non_m2m_objects(old_field, new_field)) + # Handle our type alters on the other end of rels from the PK stuff above + for old_rel, new_rel in rels_to_update: + rel_db_params = new_rel.field.db_parameters(connection=self.connection) + rel_type = rel_db_params["type"] + rel_collation = rel_db_params.get("collation") + old_rel_db_params = old_rel.field.db_parameters(connection=self.connection) + old_rel_collation = old_rel_db_params.get("collation") + fragment, other_actions = self._alter_column_type_sql( + new_rel.related_model, + old_rel.field, + new_rel.field, + rel_type, + old_rel_collation, + rel_collation, + ) + self.execute( + self.sql_alter_column + % { + "table": self.quote_name(new_rel.related_model._meta.db_table), + "changes": fragment[0], + }, + fragment[1], + ) + for sql, params in other_actions: + self.execute(sql, params) + # Does it have a foreign key? + if ( + self.connection.features.supports_foreign_keys + and new_field.remote_field + and ( + fks_dropped or not old_field.remote_field or not old_field.db_constraint + ) + and new_field.db_constraint + ): + self.execute( + self._create_fk_sql(model, new_field, "_fk_%(to_table)s_%(to_column)s") + ) + # Rebuild FKs that pointed to us if we previously had to drop them + if drop_foreign_keys: + for _, rel in rels_to_update: + if rel.field.db_constraint: + self.execute( + self._create_fk_sql(rel.related_model, rel.field, "_fk") + ) + # Does it have check constraints we need to add? + if old_db_check != new_db_check and new_db_check: + constraint_name = self._create_index_name( + model._meta.db_table, [new_field.column], suffix="_check" + ) + self.execute( + self._create_check_sql(model, constraint_name, new_db_params["check"]) + ) + # Drop the default if we need to + # (Django usually does not use in-database defaults) + if needs_database_default: + changes_sql, params = self._alter_column_default_sql( + model, old_field, new_field, drop=True + ) + sql = self.sql_alter_column % { + "table": self.quote_name(model._meta.db_table), + "changes": changes_sql, + } + self.execute(sql, params) + # Reset connection if required + if self.connection.features.connection_persists_old_columns: + self.connection.close() + + def _alter_column_null_sql(self, model, old_field, new_field): + """ + Hook to specialize column null alteration. + + Return a (sql, params) fragment to set a column to null or non-null + as required by new_field, or None if no changes are required. + """ + if ( + self.connection.features.interprets_empty_strings_as_nulls + and new_field.empty_strings_allowed + ): + # The field is nullable in the database anyway, leave it alone. + return + else: + new_db_params = new_field.db_parameters(connection=self.connection) + sql = ( + self.sql_alter_column_null + if new_field.null + else self.sql_alter_column_not_null + ) + return ( + sql + % { + "column": self.quote_name(new_field.column), + "type": new_db_params["type"], + }, + [], + ) + + def _alter_column_default_sql(self, model, old_field, new_field, drop=False): + """ + Hook to specialize column default alteration. + + Return a (sql, params) fragment to add or drop (depending on the drop + argument) a default to new_field's column. + """ + new_default = self.effective_default(new_field) + default = self._column_default_sql(new_field) + params = [new_default] + + if drop: + params = [] + elif self.connection.features.requires_literal_defaults: + # Some databases (Oracle) can't take defaults as a parameter + # If this is the case, the SchemaEditor for that database should + # implement prepare_default(). + default = self.prepare_default(new_default) + params = [] + + new_db_params = new_field.db_parameters(connection=self.connection) + if drop: + if new_field.null: + sql = self.sql_alter_column_no_default_null + else: + sql = self.sql_alter_column_no_default + else: + sql = self.sql_alter_column_default + return ( + sql + % { + "column": self.quote_name(new_field.column), + "type": new_db_params["type"], + "default": default, + }, + params, + ) + + def _alter_column_database_default_sql( + self, model, old_field, new_field, drop=False + ): + """ + Hook to specialize column database default alteration. + + Return a (sql, params) fragment to add or drop (depending on the drop + argument) a default to new_field's column. + """ + if drop: + sql = self.sql_alter_column_no_default + default_sql = "" + params = [] + else: + sql = self.sql_alter_column_default + default_sql, params = self.db_default_sql(new_field) + + new_db_params = new_field.db_parameters(connection=self.connection) + return ( + sql + % { + "column": self.quote_name(new_field.column), + "type": new_db_params["type"], + "default": default_sql, + }, + params, + ) + + def _alter_column_type_sql( + self, model, old_field, new_field, new_type, old_collation, new_collation + ): + """ + Hook to specialize column type alteration for different backends, + for cases when a creation type is different to an alteration type + (e.g. SERIAL in PostgreSQL, PostGIS fields). + + Return a 2-tuple of: an SQL fragment of (sql, params) to insert into + an ALTER TABLE statement and a list of extra (sql, params) tuples to + run once the field is altered. + """ + other_actions = [] + if collate_sql := self._collate_sql( + new_collation, old_collation, model._meta.db_table + ): + collate_sql = f" {collate_sql}" + else: + collate_sql = "" + # Comment change? + comment_sql = "" + if self.connection.features.supports_comments and not new_field.many_to_many: + if old_field.db_comment != new_field.db_comment: + # PostgreSQL and Oracle can't execute 'ALTER COLUMN ...' and + # 'COMMENT ON ...' at the same time. + sql, params = self._alter_column_comment_sql( + model, new_field, new_type, new_field.db_comment + ) + if sql: + other_actions.append((sql, params)) + if new_field.db_comment: + comment_sql = self._comment_sql(new_field.db_comment) + return ( + ( + self.sql_alter_column_type + % { + "column": self.quote_name(new_field.column), + "type": new_type, + "collation": collate_sql, + "comment": comment_sql, + }, + [], + ), + other_actions, + ) + + def _alter_column_comment_sql(self, model, new_field, new_type, new_db_comment): + return ( + self.sql_alter_column_comment + % { + "table": self.quote_name(model._meta.db_table), + "column": self.quote_name(new_field.column), + "comment": self._comment_sql(new_db_comment), + }, + [], + ) + + def _comment_sql(self, comment): + return self.quote_value(comment or "") + + def _alter_many_to_many(self, model, old_field, new_field, strict): + """Alter M2Ms to repoint their to= endpoints.""" + # Rename the through table + if ( + old_field.remote_field.through._meta.db_table + != new_field.remote_field.through._meta.db_table + ): + self.alter_db_table( + old_field.remote_field.through, + old_field.remote_field.through._meta.db_table, + new_field.remote_field.through._meta.db_table, + ) + # Repoint the FK to the other side + self.alter_field( + new_field.remote_field.through, + # The field that points to the target model is needed, so we can + # tell alter_field to change it - this is m2m_reverse_field_name() + # (as opposed to m2m_field_name(), which points to our model). + old_field.remote_field.through._meta.get_field( + old_field.m2m_reverse_field_name() + ), + new_field.remote_field.through._meta.get_field( + new_field.m2m_reverse_field_name() + ), + ) + self.alter_field( + new_field.remote_field.through, + # for self-referential models we need to alter field from the other end too + old_field.remote_field.through._meta.get_field(old_field.m2m_field_name()), + new_field.remote_field.through._meta.get_field(new_field.m2m_field_name()), + ) + + def _create_index_name(self, table_name, column_names, suffix=""): + """ + Generate a unique name for an index/unique constraint. + + The name is divided into 3 parts: the table name, the column names, + and a unique digest and suffix. + """ + _, table_name = split_identifier(table_name) + hash_suffix_part = "%s%s" % ( + names_digest(table_name, *column_names, length=8), + suffix, + ) + max_length = self.connection.ops.max_name_length() or 200 + # If everything fits into max_length, use that name. + index_name = "%s_%s_%s" % (table_name, "_".join(column_names), hash_suffix_part) + if len(index_name) <= max_length: + return index_name + # Shorten a long suffix. + if len(hash_suffix_part) > max_length / 3: + hash_suffix_part = hash_suffix_part[: max_length // 3] + other_length = (max_length - len(hash_suffix_part)) // 2 - 1 + index_name = "%s_%s_%s" % ( + table_name[:other_length], + "_".join(column_names)[:other_length], + hash_suffix_part, + ) + # Prepend D if needed to prevent the name from starting with an + # underscore or a number (not permitted on Oracle). + if index_name[0] == "_" or index_name[0].isdigit(): + index_name = "D%s" % index_name[:-1] + return index_name + + def _get_index_tablespace_sql(self, model, fields, db_tablespace=None): + if db_tablespace is None: + if len(fields) == 1 and fields[0].db_tablespace: + db_tablespace = fields[0].db_tablespace + elif settings.DEFAULT_INDEX_TABLESPACE: + db_tablespace = settings.DEFAULT_INDEX_TABLESPACE + elif model._meta.db_tablespace: + db_tablespace = model._meta.db_tablespace + if db_tablespace is not None: + return " " + self.connection.ops.tablespace_sql(db_tablespace) + return "" + + def _index_condition_sql(self, condition): + if condition: + return " WHERE " + condition + return "" + + def _index_include_sql(self, model, columns): + if not columns or not self.connection.features.supports_covering_indexes: + return "" + return Statement( + " INCLUDE (%(columns)s)", + columns=Columns(model._meta.db_table, columns, self.quote_name), + ) + + def _create_index_sql( + self, + model, + *, + fields=None, + name=None, + suffix="", + using="", + db_tablespace=None, + col_suffixes=(), + sql=None, + opclasses=(), + condition=None, + include=None, + expressions=None, + ): + """ + Return the SQL statement to create the index for one or several fields + or expressions. `sql` can be specified if the syntax differs from the + standard (GIS indexes, ...). + """ + fields = fields or [] + expressions = expressions or [] + compiler = Query(model, alias_cols=False).get_compiler( + connection=self.connection, + ) + tablespace_sql = self._get_index_tablespace_sql( + model, fields, db_tablespace=db_tablespace + ) + columns = [field.column for field in fields] + sql_create_index = sql or self.sql_create_index + table = model._meta.db_table + + def create_index_name(*args, **kwargs): + nonlocal name + if name is None: + name = self._create_index_name(*args, **kwargs) + return self.quote_name(name) + + return Statement( + sql_create_index, + table=Table(table, self.quote_name), + name=IndexName(table, columns, suffix, create_index_name), + using=using, + columns=( + self._index_columns(table, columns, col_suffixes, opclasses) + if columns + else Expressions(table, expressions, compiler, self.quote_value) + ), + extra=tablespace_sql, + condition=self._index_condition_sql(condition), + include=self._index_include_sql(model, include), + ) + + def _delete_index_sql(self, model, name, sql=None): + return Statement( + sql or self.sql_delete_index, + table=Table(model._meta.db_table, self.quote_name), + name=self.quote_name(name), + ) + + def _rename_index_sql(self, model, old_name, new_name): + return Statement( + self.sql_rename_index, + table=Table(model._meta.db_table, self.quote_name), + old_name=self.quote_name(old_name), + new_name=self.quote_name(new_name), + ) + + def _index_columns(self, table, columns, col_suffixes, opclasses): + return Columns(table, columns, self.quote_name, col_suffixes=col_suffixes) + + def _model_indexes_sql(self, model): + """ + Return a list of all index SQL statements (field indexes, + index_together, Meta.indexes) for the specified model. + """ + if not model._meta.managed or model._meta.proxy or model._meta.swapped: + return [] + output = [] + for field in model._meta.local_fields: + output.extend(self._field_indexes_sql(model, field)) + + # RemovedInDjango51Warning. + for field_names in model._meta.index_together: + fields = [model._meta.get_field(field) for field in field_names] + output.append(self._create_index_sql(model, fields=fields, suffix="_idx")) + + for index in model._meta.indexes: + if ( + not index.contains_expressions + or self.connection.features.supports_expression_indexes + ): + output.append(index.create_sql(model, self)) + return output + + def _field_indexes_sql(self, model, field): + """ + Return a list of all index SQL statements for the specified field. + """ + output = [] + if self._field_should_be_indexed(model, field): + output.append(self._create_index_sql(model, fields=[field])) + return output + + def _field_should_be_altered(self, old_field, new_field, ignore=None): + if not old_field.concrete and not new_field.concrete: + return False + ignore = ignore or set() + _, old_path, old_args, old_kwargs = old_field.deconstruct() + _, new_path, new_args, new_kwargs = new_field.deconstruct() + # Don't alter when: + # - changing only a field name + # - changing an attribute that doesn't affect the schema + # - changing an attribute in the provided set of ignored attributes + # - adding only a db_column and the column name is not changed + # - db_table does not change for model referenced by foreign keys + for attr in ignore.union(old_field.non_db_attrs): + old_kwargs.pop(attr, None) + for attr in ignore.union(new_field.non_db_attrs): + new_kwargs.pop(attr, None) + if ( + not new_field.many_to_many + and old_field.remote_field + and new_field.remote_field + and old_field.remote_field.model._meta.db_table + == new_field.remote_field.model._meta.db_table + ): + old_kwargs.pop("to", None) + new_kwargs.pop("to", None) + return self.quote_name(old_field.column) != self.quote_name( + new_field.column + ) or (old_path, old_args, old_kwargs) != (new_path, new_args, new_kwargs) + + def _field_should_be_indexed(self, model, field): + return field.db_index and not field.unique + + def _field_became_primary_key(self, old_field, new_field): + return not old_field.primary_key and new_field.primary_key + + def _unique_should_be_added(self, old_field, new_field): + return ( + not new_field.primary_key + and new_field.unique + and (not old_field.unique or old_field.primary_key) + ) + + def _rename_field_sql(self, table, old_field, new_field, new_type): + return self.sql_rename_column % { + "table": self.quote_name(table), + "old_column": self.quote_name(old_field.column), + "new_column": self.quote_name(new_field.column), + "type": new_type, + } + + def _create_fk_sql(self, model, field, suffix): + table = Table(model._meta.db_table, self.quote_name) + name = self._fk_constraint_name(model, field, suffix) + column = Columns(model._meta.db_table, [field.column], self.quote_name) + to_table = Table(field.target_field.model._meta.db_table, self.quote_name) + to_column = Columns( + field.target_field.model._meta.db_table, + [field.target_field.column], + self.quote_name, + ) + deferrable = self.connection.ops.deferrable_sql() + return Statement( + self.sql_create_fk, + table=table, + name=name, + column=column, + to_table=to_table, + to_column=to_column, + deferrable=deferrable, + ) + + def _fk_constraint_name(self, model, field, suffix): + def create_fk_name(*args, **kwargs): + return self.quote_name(self._create_index_name(*args, **kwargs)) + + return ForeignKeyName( + model._meta.db_table, + [field.column], + split_identifier(field.target_field.model._meta.db_table)[1], + [field.target_field.column], + suffix, + create_fk_name, + ) + + def _delete_fk_sql(self, model, name): + return self._delete_constraint_sql(self.sql_delete_fk, model, name) + + def _deferrable_constraint_sql(self, deferrable): + if deferrable is None: + return "" + if deferrable == Deferrable.DEFERRED: + return " DEFERRABLE INITIALLY DEFERRED" + if deferrable == Deferrable.IMMEDIATE: + return " DEFERRABLE INITIALLY IMMEDIATE" + + def _unique_index_nulls_distinct_sql(self, nulls_distinct): + if nulls_distinct is False: + return " NULLS NOT DISTINCT" + elif nulls_distinct is True: + return " NULLS DISTINCT" + return "" + + def _unique_supported( + self, + condition=None, + deferrable=None, + include=None, + expressions=None, + nulls_distinct=None, + ): + return ( + (not condition or self.connection.features.supports_partial_indexes) + and ( + not deferrable + or self.connection.features.supports_deferrable_unique_constraints + ) + and (not include or self.connection.features.supports_covering_indexes) + and ( + not expressions or self.connection.features.supports_expression_indexes + ) + and ( + nulls_distinct is None + or self.connection.features.supports_nulls_distinct_unique_constraints + ) + ) + + def _unique_sql( + self, + model, + fields, + name, + condition=None, + deferrable=None, + include=None, + opclasses=None, + expressions=None, + nulls_distinct=None, + ): + if not self._unique_supported( + condition=condition, + deferrable=deferrable, + include=include, + expressions=expressions, + nulls_distinct=nulls_distinct, + ): + return None + + if ( + condition + or include + or opclasses + or expressions + or nulls_distinct is not None + ): + # Databases support conditional, covering, functional unique, + # and nulls distinct constraints via a unique index. + sql = self._create_unique_sql( + model, + fields, + name=name, + condition=condition, + include=include, + opclasses=opclasses, + expressions=expressions, + nulls_distinct=nulls_distinct, + ) + if sql: + self.deferred_sql.append(sql) + return None + constraint = self.sql_unique_constraint % { + "columns": ", ".join([self.quote_name(field.column) for field in fields]), + "deferrable": self._deferrable_constraint_sql(deferrable), + } + return self.sql_constraint % { + "name": self.quote_name(name), + "constraint": constraint, + } + + def _create_unique_sql( + self, + model, + fields, + name=None, + condition=None, + deferrable=None, + include=None, + opclasses=None, + expressions=None, + nulls_distinct=None, + ): + if not self._unique_supported( + condition=condition, + deferrable=deferrable, + include=include, + expressions=expressions, + nulls_distinct=nulls_distinct, + ): + return None + + compiler = Query(model, alias_cols=False).get_compiler( + connection=self.connection + ) + table = model._meta.db_table + columns = [field.column for field in fields] + if name is None: + name = self._unique_constraint_name(table, columns, quote=True) + else: + name = self.quote_name(name) + if condition or include or opclasses or expressions: + sql = self.sql_create_unique_index + else: + sql = self.sql_create_unique + if columns: + columns = self._index_columns( + table, columns, col_suffixes=(), opclasses=opclasses + ) + else: + columns = Expressions(table, expressions, compiler, self.quote_value) + return Statement( + sql, + table=Table(table, self.quote_name), + name=name, + columns=columns, + condition=self._index_condition_sql(condition), + deferrable=self._deferrable_constraint_sql(deferrable), + include=self._index_include_sql(model, include), + nulls_distinct=self._unique_index_nulls_distinct_sql(nulls_distinct), + ) + + def _unique_constraint_name(self, table, columns, quote=True): + if quote: + + def create_unique_name(*args, **kwargs): + return self.quote_name(self._create_index_name(*args, **kwargs)) + + else: + create_unique_name = self._create_index_name + + return IndexName(table, columns, "_uniq", create_unique_name) + + def _delete_unique_sql( + self, + model, + name, + condition=None, + deferrable=None, + include=None, + opclasses=None, + expressions=None, + nulls_distinct=None, + ): + if not self._unique_supported( + condition=condition, + deferrable=deferrable, + include=include, + expressions=expressions, + nulls_distinct=nulls_distinct, + ): + return None + if condition or include or opclasses or expressions: + sql = self.sql_delete_index + else: + sql = self.sql_delete_unique + return self._delete_constraint_sql(sql, model, name) + + def _check_sql(self, name, check): + return self.sql_constraint % { + "name": self.quote_name(name), + "constraint": self.sql_check_constraint % {"check": check}, + } + + def _create_check_sql(self, model, name, check): + if not self.connection.features.supports_table_check_constraints: + return None + return Statement( + self.sql_create_check, + table=Table(model._meta.db_table, self.quote_name), + name=self.quote_name(name), + check=check, + ) + + def _delete_check_sql(self, model, name): + if not self.connection.features.supports_table_check_constraints: + return None + return self._delete_constraint_sql(self.sql_delete_check, model, name) + + def _delete_constraint_sql(self, template, model, name): + return Statement( + template, + table=Table(model._meta.db_table, self.quote_name), + name=self.quote_name(name), + ) + + def _constraint_names( + self, + model, + column_names=None, + unique=None, + primary_key=None, + index=None, + foreign_key=None, + check=None, + type_=None, + exclude=None, + ): + """Return all constraint names matching the columns and conditions.""" + if column_names is not None: + column_names = [ + self.connection.introspection.identifier_converter( + truncate_name(name, self.connection.ops.max_name_length()) + ) + if self.connection.features.truncates_names + else self.connection.introspection.identifier_converter(name) + for name in column_names + ] + with self.connection.cursor() as cursor: + constraints = self.connection.introspection.get_constraints( + cursor, model._meta.db_table + ) + result = [] + for name, infodict in constraints.items(): + if column_names is None or column_names == infodict["columns"]: + if unique is not None and infodict["unique"] != unique: + continue + if primary_key is not None and infodict["primary_key"] != primary_key: + continue + if index is not None and infodict["index"] != index: + continue + if check is not None and infodict["check"] != check: + continue + if foreign_key is not None and not infodict["foreign_key"]: + continue + if type_ is not None and infodict["type"] != type_: + continue + if not exclude or name not in exclude: + result.append(name) + return result + + def _delete_primary_key(self, model, strict=False): + constraint_names = self._constraint_names(model, primary_key=True) + if strict and len(constraint_names) != 1: + raise ValueError( + "Found wrong number (%s) of PK constraints for %s" + % ( + len(constraint_names), + model._meta.db_table, + ) + ) + for constraint_name in constraint_names: + self.execute(self._delete_primary_key_sql(model, constraint_name)) + + def _create_primary_key_sql(self, model, field): + return Statement( + self.sql_create_pk, + table=Table(model._meta.db_table, self.quote_name), + name=self.quote_name( + self._create_index_name( + model._meta.db_table, [field.column], suffix="_pk" + ) + ), + columns=Columns(model._meta.db_table, [field.column], self.quote_name), + ) + + def _delete_primary_key_sql(self, model, name): + return self._delete_constraint_sql(self.sql_delete_pk, model, name) + + def _collate_sql(self, collation, old_collation=None, table_name=None): + return "COLLATE " + self.quote_name(collation) if collation else "" + + def remove_procedure(self, procedure_name, param_types=()): + sql = self.sql_delete_procedure % { + "procedure": self.quote_name(procedure_name), + "param_types": ",".join(param_types), + } + self.execute(sql) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/validation.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/validation.py new file mode 100644 index 0000000..d0e3e21 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/base/validation.py @@ -0,0 +1,29 @@ +class BaseDatabaseValidation: + """Encapsulate backend-specific validation.""" + + def __init__(self, connection): + self.connection = connection + + def check(self, **kwargs): + return [] + + def check_field(self, field, **kwargs): + errors = [] + # Backends may implement a check_field_type() method. + if ( + hasattr(self, "check_field_type") + and + # Ignore any related fields. + not getattr(field, "remote_field", None) + ): + # Ignore fields with unsupported features. + db_supports_all_required_features = all( + getattr(self.connection.features, feature, False) + for feature in field.model._meta.required_db_features + ) + if db_supports_all_required_features: + field_type = field.db_type(self.connection) + # Ignore non-concrete fields. + if field_type is not None: + errors.extend(self.check_field_type(field, field_type)) + return errors diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/ddl_references.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/ddl_references.py new file mode 100644 index 0000000..412d07a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/ddl_references.py @@ -0,0 +1,254 @@ +""" +Helpers to manipulate deferred DDL statements that might need to be adjusted or +discarded within when executing a migration. +""" +from copy import deepcopy + + +class Reference: + """Base class that defines the reference interface.""" + + def references_table(self, table): + """ + Return whether or not this instance references the specified table. + """ + return False + + def references_column(self, table, column): + """ + Return whether or not this instance references the specified column. + """ + return False + + def rename_table_references(self, old_table, new_table): + """ + Rename all references to the old_name to the new_table. + """ + pass + + def rename_column_references(self, table, old_column, new_column): + """ + Rename all references to the old_column to the new_column. + """ + pass + + def __repr__(self): + return "<%s %r>" % (self.__class__.__name__, str(self)) + + def __str__(self): + raise NotImplementedError( + "Subclasses must define how they should be converted to string." + ) + + +class Table(Reference): + """Hold a reference to a table.""" + + def __init__(self, table, quote_name): + self.table = table + self.quote_name = quote_name + + def references_table(self, table): + return self.table == table + + def rename_table_references(self, old_table, new_table): + if self.table == old_table: + self.table = new_table + + def __str__(self): + return self.quote_name(self.table) + + +class TableColumns(Table): + """Base class for references to multiple columns of a table.""" + + def __init__(self, table, columns): + self.table = table + self.columns = columns + + def references_column(self, table, column): + return self.table == table and column in self.columns + + def rename_column_references(self, table, old_column, new_column): + if self.table == table: + for index, column in enumerate(self.columns): + if column == old_column: + self.columns[index] = new_column + + +class Columns(TableColumns): + """Hold a reference to one or many columns.""" + + def __init__(self, table, columns, quote_name, col_suffixes=()): + self.quote_name = quote_name + self.col_suffixes = col_suffixes + super().__init__(table, columns) + + def __str__(self): + def col_str(column, idx): + col = self.quote_name(column) + try: + suffix = self.col_suffixes[idx] + if suffix: + col = "{} {}".format(col, suffix) + except IndexError: + pass + return col + + return ", ".join( + col_str(column, idx) for idx, column in enumerate(self.columns) + ) + + +class IndexName(TableColumns): + """Hold a reference to an index name.""" + + def __init__(self, table, columns, suffix, create_index_name): + self.suffix = suffix + self.create_index_name = create_index_name + super().__init__(table, columns) + + def __str__(self): + return self.create_index_name(self.table, self.columns, self.suffix) + + +class IndexColumns(Columns): + def __init__(self, table, columns, quote_name, col_suffixes=(), opclasses=()): + self.opclasses = opclasses + super().__init__(table, columns, quote_name, col_suffixes) + + def __str__(self): + def col_str(column, idx): + # Index.__init__() guarantees that self.opclasses is the same + # length as self.columns. + col = "{} {}".format(self.quote_name(column), self.opclasses[idx]) + try: + suffix = self.col_suffixes[idx] + if suffix: + col = "{} {}".format(col, suffix) + except IndexError: + pass + return col + + return ", ".join( + col_str(column, idx) for idx, column in enumerate(self.columns) + ) + + +class ForeignKeyName(TableColumns): + """Hold a reference to a foreign key name.""" + + def __init__( + self, + from_table, + from_columns, + to_table, + to_columns, + suffix_template, + create_fk_name, + ): + self.to_reference = TableColumns(to_table, to_columns) + self.suffix_template = suffix_template + self.create_fk_name = create_fk_name + super().__init__( + from_table, + from_columns, + ) + + def references_table(self, table): + return super().references_table(table) or self.to_reference.references_table( + table + ) + + def references_column(self, table, column): + return super().references_column( + table, column + ) or self.to_reference.references_column(table, column) + + def rename_table_references(self, old_table, new_table): + super().rename_table_references(old_table, new_table) + self.to_reference.rename_table_references(old_table, new_table) + + def rename_column_references(self, table, old_column, new_column): + super().rename_column_references(table, old_column, new_column) + self.to_reference.rename_column_references(table, old_column, new_column) + + def __str__(self): + suffix = self.suffix_template % { + "to_table": self.to_reference.table, + "to_column": self.to_reference.columns[0], + } + return self.create_fk_name(self.table, self.columns, suffix) + + +class Statement(Reference): + """ + Statement template and formatting parameters container. + + Allows keeping a reference to a statement without interpolating identifiers + that might have to be adjusted if they're referencing a table or column + that is removed + """ + + def __init__(self, template, **parts): + self.template = template + self.parts = parts + + def references_table(self, table): + return any( + hasattr(part, "references_table") and part.references_table(table) + for part in self.parts.values() + ) + + def references_column(self, table, column): + return any( + hasattr(part, "references_column") and part.references_column(table, column) + for part in self.parts.values() + ) + + def rename_table_references(self, old_table, new_table): + for part in self.parts.values(): + if hasattr(part, "rename_table_references"): + part.rename_table_references(old_table, new_table) + + def rename_column_references(self, table, old_column, new_column): + for part in self.parts.values(): + if hasattr(part, "rename_column_references"): + part.rename_column_references(table, old_column, new_column) + + def __str__(self): + return self.template % self.parts + + +class Expressions(TableColumns): + def __init__(self, table, expressions, compiler, quote_value): + self.compiler = compiler + self.expressions = expressions + self.quote_value = quote_value + columns = [ + col.target.column + for col in self.compiler.query._gen_cols([self.expressions]) + ] + super().__init__(table, columns) + + def rename_table_references(self, old_table, new_table): + if self.table != old_table: + return + self.expressions = self.expressions.relabeled_clone({old_table: new_table}) + super().rename_table_references(old_table, new_table) + + def rename_column_references(self, table, old_column, new_column): + if self.table != table: + return + expressions = deepcopy(self.expressions) + self.columns = [] + for col in self.compiler.query._gen_cols([expressions]): + if col.target.column == old_column: + col.target.column = new_column + self.columns.append(col.target.column) + self.expressions = expressions + + def __str__(self): + sql, params = self.compiler.compile(self.expressions) + params = map(self.quote_value, params) + return sql % tuple(params) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/dummy/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/dummy/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/dummy/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/dummy/base.py new file mode 100644 index 0000000..36c6480 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/dummy/base.py @@ -0,0 +1,74 @@ +""" +Dummy database backend for Django. + +Django uses this if the database ENGINE setting is empty (None or empty string). + +Each of these API functions, except connection.close(), raise +ImproperlyConfigured. +""" + +from django.core.exceptions import ImproperlyConfigured +from django.db.backends.base.base import BaseDatabaseWrapper +from django.db.backends.base.client import BaseDatabaseClient +from django.db.backends.base.creation import BaseDatabaseCreation +from django.db.backends.base.introspection import BaseDatabaseIntrospection +from django.db.backends.base.operations import BaseDatabaseOperations +from django.db.backends.dummy.features import DummyDatabaseFeatures + + +def complain(*args, **kwargs): + raise ImproperlyConfigured( + "settings.DATABASES is improperly configured. " + "Please supply the ENGINE value. Check " + "settings documentation for more details." + ) + + +def ignore(*args, **kwargs): + pass + + +class DatabaseOperations(BaseDatabaseOperations): + quote_name = complain + + +class DatabaseClient(BaseDatabaseClient): + runshell = complain + + +class DatabaseCreation(BaseDatabaseCreation): + create_test_db = ignore + destroy_test_db = ignore + + +class DatabaseIntrospection(BaseDatabaseIntrospection): + get_table_list = complain + get_table_description = complain + get_relations = complain + get_indexes = complain + + +class DatabaseWrapper(BaseDatabaseWrapper): + operators = {} + # Override the base class implementations with null + # implementations. Anything that tries to actually + # do something raises complain; anything that tries + # to rollback or undo something raises ignore. + _cursor = complain + ensure_connection = complain + _commit = complain + _rollback = ignore + _close = ignore + _savepoint = ignore + _savepoint_commit = complain + _savepoint_rollback = ignore + _set_autocommit = complain + # Classes instantiated in __init__(). + client_class = DatabaseClient + creation_class = DatabaseCreation + features_class = DummyDatabaseFeatures + introspection_class = DatabaseIntrospection + ops_class = DatabaseOperations + + def is_usable(self): + return True diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/dummy/features.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/dummy/features.py new file mode 100644 index 0000000..ac91731 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/dummy/features.py @@ -0,0 +1,6 @@ +from django.db.backends.base.features import BaseDatabaseFeatures + + +class DummyDatabaseFeatures(BaseDatabaseFeatures): + supports_transactions = False + uses_savepoints = False diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/base.py new file mode 100644 index 0000000..e2707a9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/base.py @@ -0,0 +1,452 @@ +""" +MySQL database backend for Django. + +Requires mysqlclient: https://pypi.org/project/mysqlclient/ +""" +from django.core.exceptions import ImproperlyConfigured +from django.db import IntegrityError +from django.db.backends import utils as backend_utils +from django.db.backends.base.base import BaseDatabaseWrapper +from django.utils.asyncio import async_unsafe +from django.utils.functional import cached_property +from django.utils.regex_helper import _lazy_re_compile + +try: + import MySQLdb as Database +except ImportError as err: + raise ImproperlyConfigured( + "Error loading MySQLdb module.\nDid you install mysqlclient?" + ) from err + +from MySQLdb.constants import CLIENT, FIELD_TYPE +from MySQLdb.converters import conversions + +# Some of these import MySQLdb, so import them after checking if it's installed. +from .client import DatabaseClient +from .creation import DatabaseCreation +from .features import DatabaseFeatures +from .introspection import DatabaseIntrospection +from .operations import DatabaseOperations +from .schema import DatabaseSchemaEditor +from .validation import DatabaseValidation + +version = Database.version_info +if version < (1, 4, 3): + raise ImproperlyConfigured( + "mysqlclient 1.4.3 or newer is required; you have %s." % Database.__version__ + ) + + +# MySQLdb returns TIME columns as timedelta -- they are more like timedelta in +# terms of actual behavior as they are signed and include days -- and Django +# expects time. +django_conversions = { + **conversions, + **{FIELD_TYPE.TIME: backend_utils.typecast_time}, +} + +# This should match the numerical portion of the version numbers (we can treat +# versions like 5.0.24 and 5.0.24a as the same). +server_version_re = _lazy_re_compile(r"(\d{1,2})\.(\d{1,2})\.(\d{1,2})") + + +class CursorWrapper: + """ + A thin wrapper around MySQLdb's normal cursor class that catches particular + exception instances and reraises them with the correct types. + + Implemented as a wrapper, rather than a subclass, so that it isn't stuck + to the particular underlying representation returned by Connection.cursor(). + """ + + codes_for_integrityerror = ( + 1048, # Column cannot be null + 1690, # BIGINT UNSIGNED value is out of range + 3819, # CHECK constraint is violated + 4025, # CHECK constraint failed + ) + + def __init__(self, cursor): + self.cursor = cursor + + def execute(self, query, args=None): + try: + # args is None means no string interpolation + return self.cursor.execute(query, args) + except Database.OperationalError as e: + # Map some error codes to IntegrityError, since they seem to be + # misclassified and Django would prefer the more logical place. + if e.args[0] in self.codes_for_integrityerror: + raise IntegrityError(*tuple(e.args)) + raise + + def executemany(self, query, args): + try: + return self.cursor.executemany(query, args) + except Database.OperationalError as e: + # Map some error codes to IntegrityError, since they seem to be + # misclassified and Django would prefer the more logical place. + if e.args[0] in self.codes_for_integrityerror: + raise IntegrityError(*tuple(e.args)) + raise + + def __getattr__(self, attr): + return getattr(self.cursor, attr) + + def __iter__(self): + return iter(self.cursor) + + +class DatabaseWrapper(BaseDatabaseWrapper): + vendor = "mysql" + # This dictionary maps Field objects to their associated MySQL column + # types, as strings. Column-type strings can contain format strings; they'll + # be interpolated against the values of Field.__dict__ before being output. + # If a column type is set to None, it won't be included in the output. + + _data_types = { + "AutoField": "integer AUTO_INCREMENT", + "BigAutoField": "bigint AUTO_INCREMENT", + "BinaryField": "longblob", + "BooleanField": "bool", + "CharField": "varchar(%(max_length)s)", + "DateField": "date", + "DateTimeField": "datetime(6)", + "DecimalField": "numeric(%(max_digits)s, %(decimal_places)s)", + "DurationField": "bigint", + "FileField": "varchar(%(max_length)s)", + "FilePathField": "varchar(%(max_length)s)", + "FloatField": "double precision", + "IntegerField": "integer", + "BigIntegerField": "bigint", + "IPAddressField": "char(15)", + "GenericIPAddressField": "char(39)", + "JSONField": "json", + "OneToOneField": "integer", + "PositiveBigIntegerField": "bigint UNSIGNED", + "PositiveIntegerField": "integer UNSIGNED", + "PositiveSmallIntegerField": "smallint UNSIGNED", + "SlugField": "varchar(%(max_length)s)", + "SmallAutoField": "smallint AUTO_INCREMENT", + "SmallIntegerField": "smallint", + "TextField": "longtext", + "TimeField": "time(6)", + "UUIDField": "char(32)", + } + + @cached_property + def data_types(self): + _data_types = self._data_types.copy() + if self.features.has_native_uuid_field: + _data_types["UUIDField"] = "uuid" + return _data_types + + # For these data types: + # - MySQL < 8.0.13 doesn't accept default values and implicitly treats them + # as nullable + # - all versions of MySQL and MariaDB don't support full width database + # indexes + _limited_data_types = ( + "tinyblob", + "blob", + "mediumblob", + "longblob", + "tinytext", + "text", + "mediumtext", + "longtext", + "json", + ) + + operators = { + "exact": "= %s", + "iexact": "LIKE %s", + "contains": "LIKE BINARY %s", + "icontains": "LIKE %s", + "gt": "> %s", + "gte": ">= %s", + "lt": "< %s", + "lte": "<= %s", + "startswith": "LIKE BINARY %s", + "endswith": "LIKE BINARY %s", + "istartswith": "LIKE %s", + "iendswith": "LIKE %s", + } + + # The patterns below are used to generate SQL pattern lookup clauses when + # the right-hand side of the lookup isn't a raw string (it might be an expression + # or the result of a bilateral transformation). + # In those cases, special characters for LIKE operators (e.g. \, *, _) should be + # escaped on database side. + # + # Note: we use str.format() here for readability as '%' is used as a wildcard for + # the LIKE operator. + pattern_esc = r"REPLACE(REPLACE(REPLACE({}, '\\', '\\\\'), '%%', '\%%'), '_', '\_')" + pattern_ops = { + "contains": "LIKE BINARY CONCAT('%%', {}, '%%')", + "icontains": "LIKE CONCAT('%%', {}, '%%')", + "startswith": "LIKE BINARY CONCAT({}, '%%')", + "istartswith": "LIKE CONCAT({}, '%%')", + "endswith": "LIKE BINARY CONCAT('%%', {})", + "iendswith": "LIKE CONCAT('%%', {})", + } + + isolation_levels = { + "read uncommitted", + "read committed", + "repeatable read", + "serializable", + } + + Database = Database + SchemaEditorClass = DatabaseSchemaEditor + # Classes instantiated in __init__(). + client_class = DatabaseClient + creation_class = DatabaseCreation + features_class = DatabaseFeatures + introspection_class = DatabaseIntrospection + ops_class = DatabaseOperations + validation_class = DatabaseValidation + + def get_database_version(self): + return self.mysql_version + + def get_connection_params(self): + kwargs = { + "conv": django_conversions, + "charset": "utf8", + } + settings_dict = self.settings_dict + if settings_dict["USER"]: + kwargs["user"] = settings_dict["USER"] + if settings_dict["NAME"]: + kwargs["database"] = settings_dict["NAME"] + if settings_dict["PASSWORD"]: + kwargs["password"] = settings_dict["PASSWORD"] + if settings_dict["HOST"].startswith("/"): + kwargs["unix_socket"] = settings_dict["HOST"] + elif settings_dict["HOST"]: + kwargs["host"] = settings_dict["HOST"] + if settings_dict["PORT"]: + kwargs["port"] = int(settings_dict["PORT"]) + # We need the number of potentially affected rows after an + # "UPDATE", not the number of changed rows. + kwargs["client_flag"] = CLIENT.FOUND_ROWS + # Validate the transaction isolation level, if specified. + options = settings_dict["OPTIONS"].copy() + isolation_level = options.pop("isolation_level", "read committed") + if isolation_level: + isolation_level = isolation_level.lower() + if isolation_level not in self.isolation_levels: + raise ImproperlyConfigured( + "Invalid transaction isolation level '%s' specified.\n" + "Use one of %s, or None." + % ( + isolation_level, + ", ".join("'%s'" % s for s in sorted(self.isolation_levels)), + ) + ) + self.isolation_level = isolation_level + kwargs.update(options) + return kwargs + + @async_unsafe + def get_new_connection(self, conn_params): + connection = Database.connect(**conn_params) + # bytes encoder in mysqlclient doesn't work and was added only to + # prevent KeyErrors in Django < 2.0. We can remove this workaround when + # mysqlclient 2.1 becomes the minimal mysqlclient supported by Django. + # See https://github.com/PyMySQL/mysqlclient/issues/489 + if connection.encoders.get(bytes) is bytes: + connection.encoders.pop(bytes) + return connection + + def init_connection_state(self): + super().init_connection_state() + assignments = [] + if self.features.is_sql_auto_is_null_enabled: + # SQL_AUTO_IS_NULL controls whether an AUTO_INCREMENT column on + # a recently inserted row will return when the field is tested + # for NULL. Disabling this brings this aspect of MySQL in line + # with SQL standards. + assignments.append("SET SQL_AUTO_IS_NULL = 0") + + if self.isolation_level: + assignments.append( + "SET SESSION TRANSACTION ISOLATION LEVEL %s" + % self.isolation_level.upper() + ) + + if assignments: + with self.cursor() as cursor: + cursor.execute("; ".join(assignments)) + + @async_unsafe + def create_cursor(self, name=None): + cursor = self.connection.cursor() + return CursorWrapper(cursor) + + def _rollback(self): + try: + BaseDatabaseWrapper._rollback(self) + except Database.NotSupportedError: + pass + + def _set_autocommit(self, autocommit): + with self.wrap_database_errors: + self.connection.autocommit(autocommit) + + def disable_constraint_checking(self): + """ + Disable foreign key checks, primarily for use in adding rows with + forward references. Always return True to indicate constraint checks + need to be re-enabled. + """ + with self.cursor() as cursor: + cursor.execute("SET foreign_key_checks=0") + return True + + def enable_constraint_checking(self): + """ + Re-enable foreign key checks after they have been disabled. + """ + # Override needs_rollback in case constraint_checks_disabled is + # nested inside transaction.atomic. + self.needs_rollback, needs_rollback = False, self.needs_rollback + try: + with self.cursor() as cursor: + cursor.execute("SET foreign_key_checks=1") + finally: + self.needs_rollback = needs_rollback + + def check_constraints(self, table_names=None): + """ + Check each table name in `table_names` for rows with invalid foreign + key references. This method is intended to be used in conjunction with + `disable_constraint_checking()` and `enable_constraint_checking()`, to + determine if rows with invalid references were entered while constraint + checks were off. + """ + with self.cursor() as cursor: + if table_names is None: + table_names = self.introspection.table_names(cursor) + for table_name in table_names: + primary_key_column_name = self.introspection.get_primary_key_column( + cursor, table_name + ) + if not primary_key_column_name: + continue + relations = self.introspection.get_relations(cursor, table_name) + for column_name, ( + referenced_column_name, + referenced_table_name, + ) in relations.items(): + cursor.execute( + """ + SELECT REFERRING.`%s`, REFERRING.`%s` FROM `%s` as REFERRING + LEFT JOIN `%s` as REFERRED + ON (REFERRING.`%s` = REFERRED.`%s`) + WHERE REFERRING.`%s` IS NOT NULL AND REFERRED.`%s` IS NULL + """ + % ( + primary_key_column_name, + column_name, + table_name, + referenced_table_name, + column_name, + referenced_column_name, + column_name, + referenced_column_name, + ) + ) + for bad_row in cursor.fetchall(): + raise IntegrityError( + "The row in table '%s' with primary key '%s' has an " + "invalid foreign key: %s.%s contains a value '%s' that " + "does not have a corresponding value in %s.%s." + % ( + table_name, + bad_row[0], + table_name, + column_name, + bad_row[1], + referenced_table_name, + referenced_column_name, + ) + ) + + def is_usable(self): + try: + self.connection.ping() + except Database.Error: + return False + else: + return True + + @cached_property + def display_name(self): + return "MariaDB" if self.mysql_is_mariadb else "MySQL" + + @cached_property + def data_type_check_constraints(self): + if self.features.supports_column_check_constraints: + check_constraints = { + "PositiveBigIntegerField": "`%(column)s` >= 0", + "PositiveIntegerField": "`%(column)s` >= 0", + "PositiveSmallIntegerField": "`%(column)s` >= 0", + } + if self.mysql_is_mariadb and self.mysql_version < (10, 4, 3): + # MariaDB < 10.4.3 doesn't automatically use the JSON_VALID as + # a check constraint. + check_constraints["JSONField"] = "JSON_VALID(`%(column)s`)" + return check_constraints + return {} + + @cached_property + def mysql_server_data(self): + with self.temporary_connection() as cursor: + # Select some server variables and test if the time zone + # definitions are installed. CONVERT_TZ returns NULL if 'UTC' + # timezone isn't loaded into the mysql.time_zone table. + cursor.execute( + """ + SELECT VERSION(), + @@sql_mode, + @@default_storage_engine, + @@sql_auto_is_null, + @@lower_case_table_names, + CONVERT_TZ('2001-01-01 01:00:00', 'UTC', 'UTC') IS NOT NULL + """ + ) + row = cursor.fetchone() + return { + "version": row[0], + "sql_mode": row[1], + "default_storage_engine": row[2], + "sql_auto_is_null": bool(row[3]), + "lower_case_table_names": bool(row[4]), + "has_zoneinfo_database": bool(row[5]), + } + + @cached_property + def mysql_server_info(self): + return self.mysql_server_data["version"] + + @cached_property + def mysql_version(self): + match = server_version_re.match(self.mysql_server_info) + if not match: + raise Exception( + "Unable to determine MySQL version from version string %r" + % self.mysql_server_info + ) + return tuple(int(x) for x in match.groups()) + + @cached_property + def mysql_is_mariadb(self): + return "mariadb" in self.mysql_server_info.lower() + + @cached_property + def sql_mode(self): + sql_mode = self.mysql_server_data["sql_mode"] + return set(sql_mode.split(",") if sql_mode else ()) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/client.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/client.py new file mode 100644 index 0000000..6aa11b2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/client.py @@ -0,0 +1,72 @@ +import signal + +from django.db.backends.base.client import BaseDatabaseClient + + +class DatabaseClient(BaseDatabaseClient): + executable_name = "mysql" + + @classmethod + def settings_to_cmd_args_env(cls, settings_dict, parameters): + args = [cls.executable_name] + env = None + database = settings_dict["OPTIONS"].get( + "database", + settings_dict["OPTIONS"].get("db", settings_dict["NAME"]), + ) + user = settings_dict["OPTIONS"].get("user", settings_dict["USER"]) + password = settings_dict["OPTIONS"].get( + "password", + settings_dict["OPTIONS"].get("passwd", settings_dict["PASSWORD"]), + ) + host = settings_dict["OPTIONS"].get("host", settings_dict["HOST"]) + port = settings_dict["OPTIONS"].get("port", settings_dict["PORT"]) + server_ca = settings_dict["OPTIONS"].get("ssl", {}).get("ca") + client_cert = settings_dict["OPTIONS"].get("ssl", {}).get("cert") + client_key = settings_dict["OPTIONS"].get("ssl", {}).get("key") + defaults_file = settings_dict["OPTIONS"].get("read_default_file") + charset = settings_dict["OPTIONS"].get("charset") + # Seems to be no good way to set sql_mode with CLI. + + if defaults_file: + args += ["--defaults-file=%s" % defaults_file] + if user: + args += ["--user=%s" % user] + if password: + # The MYSQL_PWD environment variable usage is discouraged per + # MySQL's documentation due to the possibility of exposure through + # `ps` on old Unix flavors but --password suffers from the same + # flaw on even more systems. Usage of an environment variable also + # prevents password exposure if the subprocess.run(check=True) call + # raises a CalledProcessError since the string representation of + # the latter includes all of the provided `args`. + env = {"MYSQL_PWD": password} + if host: + if "/" in host: + args += ["--socket=%s" % host] + else: + args += ["--host=%s" % host] + if port: + args += ["--port=%s" % port] + if server_ca: + args += ["--ssl-ca=%s" % server_ca] + if client_cert: + args += ["--ssl-cert=%s" % client_cert] + if client_key: + args += ["--ssl-key=%s" % client_key] + if charset: + args += ["--default-character-set=%s" % charset] + if database: + args += [database] + args.extend(parameters) + return args, env + + def runshell(self, parameters): + sigint_handler = signal.getsignal(signal.SIGINT) + try: + # Allow SIGINT to pass to mysql to abort queries. + signal.signal(signal.SIGINT, signal.SIG_IGN) + super().runshell(parameters) + finally: + # Restore the original SIGINT handler. + signal.signal(signal.SIGINT, sigint_handler) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/compiler.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/compiler.py new file mode 100644 index 0000000..2ec6bea --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/compiler.py @@ -0,0 +1,84 @@ +from django.core.exceptions import FieldError, FullResultSet +from django.db.models.expressions import Col +from django.db.models.sql import compiler + + +class SQLCompiler(compiler.SQLCompiler): + def as_subquery_condition(self, alias, columns, compiler): + qn = compiler.quote_name_unless_alias + qn2 = self.connection.ops.quote_name + sql, params = self.as_sql() + return ( + "(%s) IN (%s)" + % ( + ", ".join("%s.%s" % (qn(alias), qn2(column)) for column in columns), + sql, + ), + params, + ) + + +class SQLInsertCompiler(compiler.SQLInsertCompiler, SQLCompiler): + pass + + +class SQLDeleteCompiler(compiler.SQLDeleteCompiler, SQLCompiler): + def as_sql(self): + # Prefer the non-standard DELETE FROM syntax over the SQL generated by + # the SQLDeleteCompiler's default implementation when multiple tables + # are involved since MySQL/MariaDB will generate a more efficient query + # plan than when using a subquery. + where, having, qualify = self.query.where.split_having_qualify( + must_group_by=self.query.group_by is not None + ) + if self.single_alias or having or qualify: + # DELETE FROM cannot be used when filtering against aggregates or + # window functions as it doesn't allow for GROUP BY/HAVING clauses + # and the subquery wrapping (necessary to emulate QUALIFY). + return super().as_sql() + result = [ + "DELETE %s FROM" + % self.quote_name_unless_alias(self.query.get_initial_alias()) + ] + from_sql, params = self.get_from_clause() + result.extend(from_sql) + try: + where_sql, where_params = self.compile(where) + except FullResultSet: + pass + else: + result.append("WHERE %s" % where_sql) + params.extend(where_params) + return " ".join(result), tuple(params) + + +class SQLUpdateCompiler(compiler.SQLUpdateCompiler, SQLCompiler): + def as_sql(self): + update_query, update_params = super().as_sql() + # MySQL and MariaDB support UPDATE ... ORDER BY syntax. + if self.query.order_by: + order_by_sql = [] + order_by_params = [] + db_table = self.query.get_meta().db_table + try: + for resolved, (sql, params, _) in self.get_order_by(): + if ( + isinstance(resolved.expression, Col) + and resolved.expression.alias != db_table + ): + # Ignore ordering if it contains joined fields, because + # they cannot be used in the ORDER BY clause. + raise FieldError + order_by_sql.append(sql) + order_by_params.extend(params) + update_query += " ORDER BY " + ", ".join(order_by_sql) + update_params += tuple(order_by_params) + except FieldError: + # Ignore ordering if it contains annotations, because they're + # removed in .update() and cannot be resolved. + pass + return update_query, update_params + + +class SQLAggregateCompiler(compiler.SQLAggregateCompiler, SQLCompiler): + pass diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/creation.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/creation.py new file mode 100644 index 0000000..a060f41 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/creation.py @@ -0,0 +1,87 @@ +import os +import subprocess +import sys + +from django.db.backends.base.creation import BaseDatabaseCreation + +from .client import DatabaseClient + + +class DatabaseCreation(BaseDatabaseCreation): + def sql_table_creation_suffix(self): + suffix = [] + test_settings = self.connection.settings_dict["TEST"] + if test_settings["CHARSET"]: + suffix.append("CHARACTER SET %s" % test_settings["CHARSET"]) + if test_settings["COLLATION"]: + suffix.append("COLLATE %s" % test_settings["COLLATION"]) + return " ".join(suffix) + + def _execute_create_test_db(self, cursor, parameters, keepdb=False): + try: + super()._execute_create_test_db(cursor, parameters, keepdb) + except Exception as e: + if len(e.args) < 1 or e.args[0] != 1007: + # All errors except "database exists" (1007) cancel tests. + self.log("Got an error creating the test database: %s" % e) + sys.exit(2) + else: + raise + + def _clone_test_db(self, suffix, verbosity, keepdb=False): + source_database_name = self.connection.settings_dict["NAME"] + target_database_name = self.get_test_db_clone_settings(suffix)["NAME"] + test_db_params = { + "dbname": self.connection.ops.quote_name(target_database_name), + "suffix": self.sql_table_creation_suffix(), + } + with self._nodb_cursor() as cursor: + try: + self._execute_create_test_db(cursor, test_db_params, keepdb) + except Exception: + if keepdb: + # If the database should be kept, skip everything else. + return + try: + if verbosity >= 1: + self.log( + "Destroying old test database for alias %s..." + % ( + self._get_database_display_str( + verbosity, target_database_name + ), + ) + ) + cursor.execute("DROP DATABASE %(dbname)s" % test_db_params) + self._execute_create_test_db(cursor, test_db_params, keepdb) + except Exception as e: + self.log("Got an error recreating the test database: %s" % e) + sys.exit(2) + self._clone_db(source_database_name, target_database_name) + + def _clone_db(self, source_database_name, target_database_name): + cmd_args, cmd_env = DatabaseClient.settings_to_cmd_args_env( + self.connection.settings_dict, [] + ) + dump_cmd = [ + "mysqldump", + *cmd_args[1:-1], + "--routines", + "--events", + source_database_name, + ] + dump_env = load_env = {**os.environ, **cmd_env} if cmd_env else None + load_cmd = cmd_args + load_cmd[-1] = target_database_name + + with subprocess.Popen( + dump_cmd, stdout=subprocess.PIPE, env=dump_env + ) as dump_proc: + with subprocess.Popen( + load_cmd, + stdin=dump_proc.stdout, + stdout=subprocess.DEVNULL, + env=load_env, + ): + # Allow dump_proc to receive a SIGPIPE if the load process exits. + dump_proc.stdout.close() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/features.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/features.py new file mode 100644 index 0000000..56faefc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/features.py @@ -0,0 +1,345 @@ +import operator + +from django.db.backends.base.features import BaseDatabaseFeatures +from django.utils.functional import cached_property + + +class DatabaseFeatures(BaseDatabaseFeatures): + empty_fetchmany_value = () + related_fields_match_type = True + # MySQL doesn't support sliced subqueries with IN/ALL/ANY/SOME. + allow_sliced_subqueries_with_in = False + has_select_for_update = True + has_select_for_update_nowait = True + supports_forward_references = False + supports_regex_backreferencing = False + supports_date_lookup_using_string = False + supports_timezones = False + requires_explicit_null_ordering_when_grouping = True + atomic_transactions = False + can_clone_databases = True + supports_comments = True + supports_comments_inline = True + supports_temporal_subtraction = True + supports_slicing_ordering_in_compound = True + supports_index_on_text_field = False + supports_over_clause = True + supports_frame_range_fixed_distance = True + supports_update_conflicts = True + delete_can_self_reference_subquery = False + create_test_procedure_without_params_sql = """ + CREATE PROCEDURE test_procedure () + BEGIN + DECLARE V_I INTEGER; + SET V_I = 1; + END; + """ + create_test_procedure_with_int_param_sql = """ + CREATE PROCEDURE test_procedure (P_I INTEGER) + BEGIN + DECLARE V_I INTEGER; + SET V_I = P_I; + END; + """ + create_test_table_with_composite_primary_key = """ + CREATE TABLE test_table_composite_pk ( + column_1 INTEGER NOT NULL, + column_2 INTEGER NOT NULL, + PRIMARY KEY(column_1, column_2) + ) + """ + # Neither MySQL nor MariaDB support partial indexes. + supports_partial_indexes = False + # COLLATE must be wrapped in parentheses because MySQL treats COLLATE as an + # indexed expression. + collate_as_index_expression = True + insert_test_table_with_defaults = "INSERT INTO {} () VALUES ()" + + supports_order_by_nulls_modifier = False + order_by_nulls_first = True + supports_logical_xor = True + + supports_stored_generated_columns = True + supports_virtual_generated_columns = True + + @cached_property + def minimum_database_version(self): + if self.connection.mysql_is_mariadb: + return (10, 4) + else: + return (8, 0, 11) + + @cached_property + def test_collations(self): + charset = "utf8" + if ( + self.connection.mysql_is_mariadb + and self.connection.mysql_version >= (10, 6) + ) or ( + not self.connection.mysql_is_mariadb + and self.connection.mysql_version >= (8, 0, 30) + ): + # utf8 is an alias for utf8mb3 in MariaDB 10.6+ and MySQL 8.0.30+. + charset = "utf8mb3" + return { + "ci": f"{charset}_general_ci", + "non_default": f"{charset}_esperanto_ci", + "swedish_ci": f"{charset}_swedish_ci", + "virtual": f"{charset}_esperanto_ci", + } + + test_now_utc_template = "UTC_TIMESTAMP(6)" + + @cached_property + def django_test_skips(self): + skips = { + "This doesn't work on MySQL.": { + "db_functions.comparison.test_greatest.GreatestTests." + "test_coalesce_workaround", + "db_functions.comparison.test_least.LeastTests." + "test_coalesce_workaround", + }, + "Running on MySQL requires utf8mb4 encoding (#18392).": { + "model_fields.test_textfield.TextFieldTests.test_emoji", + "model_fields.test_charfield.TestCharField.test_emoji", + }, + "MySQL doesn't support functional indexes on a function that " + "returns JSON": { + "schema.tests.SchemaTests.test_func_index_json_key_transform", + }, + "MySQL supports multiplying and dividing DurationFields by a " + "scalar value but it's not implemented (#25287).": { + "expressions.tests.FTimeDeltaTests.test_durationfield_multiply_divide", + }, + "UPDATE ... ORDER BY syntax on MySQL/MariaDB does not support ordering by" + "related fields.": { + "update.tests.AdvancedTests." + "test_update_ordered_by_inline_m2m_annotation", + "update.tests.AdvancedTests.test_update_ordered_by_m2m_annotation", + "update.tests.AdvancedTests.test_update_ordered_by_m2m_annotation_desc", + }, + } + if self.connection.mysql_is_mariadb and ( + 10, + 4, + 3, + ) < self.connection.mysql_version < (10, 5, 2): + skips.update( + { + "https://jira.mariadb.org/browse/MDEV-19598": { + "schema.tests.SchemaTests." + "test_alter_not_unique_field_to_primary_key", + }, + } + ) + if self.connection.mysql_is_mariadb and ( + 10, + 4, + 12, + ) < self.connection.mysql_version < (10, 5): + skips.update( + { + "https://jira.mariadb.org/browse/MDEV-22775": { + "schema.tests.SchemaTests." + "test_alter_pk_with_self_referential_field", + }, + } + ) + if not self.supports_explain_analyze: + skips.update( + { + "MariaDB and MySQL >= 8.0.18 specific.": { + "queries.test_explain.ExplainTests.test_mysql_analyze", + }, + } + ) + if "ONLY_FULL_GROUP_BY" in self.connection.sql_mode: + skips.update( + { + "GROUP BY cannot contain nonaggregated column when " + "ONLY_FULL_GROUP_BY mode is enabled on MySQL, see #34262.": { + "aggregation.tests.AggregateTestCase." + "test_group_by_nested_expression_with_params", + }, + } + ) + if self.connection.mysql_version < (8, 0, 31): + skips.update( + { + "Nesting of UNIONs at the right-hand side is not supported on " + "MySQL < 8.0.31": { + "queries.test_qs_combinators.QuerySetSetOperationTests." + "test_union_nested" + }, + } + ) + return skips + + @cached_property + def _mysql_storage_engine(self): + "Internal method used in Django tests. Don't rely on this from your code" + return self.connection.mysql_server_data["default_storage_engine"] + + @cached_property + def allows_auto_pk_0(self): + """ + Autoincrement primary key can be set to 0 if it doesn't generate new + autoincrement values. + """ + return "NO_AUTO_VALUE_ON_ZERO" in self.connection.sql_mode + + @cached_property + def update_can_self_select(self): + return self.connection.mysql_is_mariadb + + @cached_property + def can_introspect_foreign_keys(self): + "Confirm support for introspected foreign keys" + return self._mysql_storage_engine != "MyISAM" + + @cached_property + def introspected_field_types(self): + return { + **super().introspected_field_types, + "BinaryField": "TextField", + "BooleanField": "IntegerField", + "DurationField": "BigIntegerField", + "GenericIPAddressField": "CharField", + } + + @cached_property + def can_return_columns_from_insert(self): + return self.connection.mysql_is_mariadb and self.connection.mysql_version >= ( + 10, + 5, + 0, + ) + + can_return_rows_from_bulk_insert = property( + operator.attrgetter("can_return_columns_from_insert") + ) + + @cached_property + def has_zoneinfo_database(self): + return self.connection.mysql_server_data["has_zoneinfo_database"] + + @cached_property + def is_sql_auto_is_null_enabled(self): + return self.connection.mysql_server_data["sql_auto_is_null"] + + @cached_property + def supports_column_check_constraints(self): + if self.connection.mysql_is_mariadb: + return True + return self.connection.mysql_version >= (8, 0, 16) + + supports_table_check_constraints = property( + operator.attrgetter("supports_column_check_constraints") + ) + + @cached_property + def can_introspect_check_constraints(self): + if self.connection.mysql_is_mariadb: + return True + return self.connection.mysql_version >= (8, 0, 16) + + @cached_property + def has_select_for_update_skip_locked(self): + if self.connection.mysql_is_mariadb: + return self.connection.mysql_version >= (10, 6) + return True + + @cached_property + def has_select_for_update_of(self): + return not self.connection.mysql_is_mariadb + + @cached_property + def supports_explain_analyze(self): + return self.connection.mysql_is_mariadb or self.connection.mysql_version >= ( + 8, + 0, + 18, + ) + + @cached_property + def supported_explain_formats(self): + # Alias MySQL's TRADITIONAL to TEXT for consistency with other + # backends. + formats = {"JSON", "TEXT", "TRADITIONAL"} + if not self.connection.mysql_is_mariadb and self.connection.mysql_version >= ( + 8, + 0, + 16, + ): + formats.add("TREE") + return formats + + @cached_property + def supports_transactions(self): + """ + All storage engines except MyISAM support transactions. + """ + return self._mysql_storage_engine != "MyISAM" + + @cached_property + def ignores_table_name_case(self): + return self.connection.mysql_server_data["lower_case_table_names"] + + @cached_property + def supports_default_in_lead_lag(self): + # To be added in https://jira.mariadb.org/browse/MDEV-12981. + return not self.connection.mysql_is_mariadb + + @cached_property + def can_introspect_json_field(self): + if self.connection.mysql_is_mariadb: + return self.can_introspect_check_constraints + return True + + @cached_property + def supports_index_column_ordering(self): + if self._mysql_storage_engine != "InnoDB": + return False + if self.connection.mysql_is_mariadb: + return self.connection.mysql_version >= (10, 8) + return True + + @cached_property + def supports_expression_indexes(self): + return ( + not self.connection.mysql_is_mariadb + and self._mysql_storage_engine != "MyISAM" + and self.connection.mysql_version >= (8, 0, 13) + ) + + @cached_property + def supports_select_intersection(self): + is_mariadb = self.connection.mysql_is_mariadb + return is_mariadb or self.connection.mysql_version >= (8, 0, 31) + + supports_select_difference = property( + operator.attrgetter("supports_select_intersection") + ) + + @cached_property + def can_rename_index(self): + if self.connection.mysql_is_mariadb: + return self.connection.mysql_version >= (10, 5, 2) + return True + + @cached_property + def supports_expression_defaults(self): + if self.connection.mysql_is_mariadb: + return True + return self.connection.mysql_version >= (8, 0, 13) + + @cached_property + def has_native_uuid_field(self): + is_mariadb = self.connection.mysql_is_mariadb + return is_mariadb and self.connection.mysql_version >= (10, 7) + + @cached_property + def allows_group_by_selected_pks(self): + if self.connection.mysql_is_mariadb: + return "ONLY_FULL_GROUP_BY" not in self.connection.sql_mode + return True diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/introspection.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/introspection.py new file mode 100644 index 0000000..ea1d0aa --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/introspection.py @@ -0,0 +1,358 @@ +from collections import namedtuple + +import sqlparse +from MySQLdb.constants import FIELD_TYPE + +from django.db.backends.base.introspection import BaseDatabaseIntrospection +from django.db.backends.base.introspection import FieldInfo as BaseFieldInfo +from django.db.backends.base.introspection import TableInfo as BaseTableInfo +from django.db.models import Index +from django.utils.datastructures import OrderedSet + +FieldInfo = namedtuple( + "FieldInfo", + BaseFieldInfo._fields + + ("extra", "is_unsigned", "has_json_constraint", "comment", "data_type"), +) +InfoLine = namedtuple( + "InfoLine", + "col_name data_type max_len num_prec num_scale extra column_default " + "collation is_unsigned comment", +) +TableInfo = namedtuple("TableInfo", BaseTableInfo._fields + ("comment",)) + + +class DatabaseIntrospection(BaseDatabaseIntrospection): + data_types_reverse = { + FIELD_TYPE.BLOB: "TextField", + FIELD_TYPE.CHAR: "CharField", + FIELD_TYPE.DECIMAL: "DecimalField", + FIELD_TYPE.NEWDECIMAL: "DecimalField", + FIELD_TYPE.DATE: "DateField", + FIELD_TYPE.DATETIME: "DateTimeField", + FIELD_TYPE.DOUBLE: "FloatField", + FIELD_TYPE.FLOAT: "FloatField", + FIELD_TYPE.INT24: "IntegerField", + FIELD_TYPE.JSON: "JSONField", + FIELD_TYPE.LONG: "IntegerField", + FIELD_TYPE.LONGLONG: "BigIntegerField", + FIELD_TYPE.SHORT: "SmallIntegerField", + FIELD_TYPE.STRING: "CharField", + FIELD_TYPE.TIME: "TimeField", + FIELD_TYPE.TIMESTAMP: "DateTimeField", + FIELD_TYPE.TINY: "IntegerField", + FIELD_TYPE.TINY_BLOB: "TextField", + FIELD_TYPE.MEDIUM_BLOB: "TextField", + FIELD_TYPE.LONG_BLOB: "TextField", + FIELD_TYPE.VAR_STRING: "CharField", + } + + def get_field_type(self, data_type, description): + field_type = super().get_field_type(data_type, description) + if "auto_increment" in description.extra: + if field_type == "IntegerField": + return "AutoField" + elif field_type == "BigIntegerField": + return "BigAutoField" + elif field_type == "SmallIntegerField": + return "SmallAutoField" + if description.is_unsigned: + if field_type == "BigIntegerField": + return "PositiveBigIntegerField" + elif field_type == "IntegerField": + return "PositiveIntegerField" + elif field_type == "SmallIntegerField": + return "PositiveSmallIntegerField" + if description.data_type.upper() == "UUID": + return "UUIDField" + # JSON data type is an alias for LONGTEXT in MariaDB, use check + # constraints clauses to introspect JSONField. + if description.has_json_constraint: + return "JSONField" + return field_type + + def get_table_list(self, cursor): + """Return a list of table and view names in the current database.""" + cursor.execute( + """ + SELECT + table_name, + table_type, + table_comment + FROM information_schema.tables + WHERE table_schema = DATABASE() + """ + ) + return [ + TableInfo(row[0], {"BASE TABLE": "t", "VIEW": "v"}.get(row[1]), row[2]) + for row in cursor.fetchall() + ] + + def get_table_description(self, cursor, table_name): + """ + Return a description of the table with the DB-API cursor.description + interface." + """ + json_constraints = {} + if ( + self.connection.mysql_is_mariadb + and self.connection.features.can_introspect_json_field + ): + # JSON data type is an alias for LONGTEXT in MariaDB, select + # JSON_VALID() constraints to introspect JSONField. + cursor.execute( + """ + SELECT c.constraint_name AS column_name + FROM information_schema.check_constraints AS c + WHERE + c.table_name = %s AND + LOWER(c.check_clause) = + 'json_valid(`' + LOWER(c.constraint_name) + '`)' AND + c.constraint_schema = DATABASE() + """, + [table_name], + ) + json_constraints = {row[0] for row in cursor.fetchall()} + # A default collation for the given table. + cursor.execute( + """ + SELECT table_collation + FROM information_schema.tables + WHERE table_schema = DATABASE() + AND table_name = %s + """, + [table_name], + ) + row = cursor.fetchone() + default_column_collation = row[0] if row else "" + # information_schema database gives more accurate results for some figures: + # - varchar length returned by cursor.description is an internal length, + # not visible length (#5725) + # - precision and scale (for decimal fields) (#5014) + # - auto_increment is not available in cursor.description + cursor.execute( + """ + SELECT + column_name, data_type, character_maximum_length, + numeric_precision, numeric_scale, extra, column_default, + CASE + WHEN collation_name = %s THEN NULL + ELSE collation_name + END AS collation_name, + CASE + WHEN column_type LIKE '%% unsigned' THEN 1 + ELSE 0 + END AS is_unsigned, + column_comment + FROM information_schema.columns + WHERE table_name = %s AND table_schema = DATABASE() + """, + [default_column_collation, table_name], + ) + field_info = {line[0]: InfoLine(*line) for line in cursor.fetchall()} + + cursor.execute( + "SELECT * FROM %s LIMIT 1" % self.connection.ops.quote_name(table_name) + ) + + def to_int(i): + return int(i) if i is not None else i + + fields = [] + for line in cursor.description: + info = field_info[line[0]] + fields.append( + FieldInfo( + *line[:2], + to_int(info.max_len) or line[2], + to_int(info.max_len) or line[3], + to_int(info.num_prec) or line[4], + to_int(info.num_scale) or line[5], + line[6], + info.column_default, + info.collation, + info.extra, + info.is_unsigned, + line[0] in json_constraints, + info.comment, + info.data_type, + ) + ) + return fields + + def get_sequences(self, cursor, table_name, table_fields=()): + for field_info in self.get_table_description(cursor, table_name): + if "auto_increment" in field_info.extra: + # MySQL allows only one auto-increment column per table. + return [{"table": table_name, "column": field_info.name}] + return [] + + def get_relations(self, cursor, table_name): + """ + Return a dictionary of {field_name: (field_name_other_table, other_table)} + representing all foreign keys in the given table. + """ + cursor.execute( + """ + SELECT column_name, referenced_column_name, referenced_table_name + FROM information_schema.key_column_usage + WHERE table_name = %s + AND table_schema = DATABASE() + AND referenced_table_schema = DATABASE() + AND referenced_table_name IS NOT NULL + AND referenced_column_name IS NOT NULL + """, + [table_name], + ) + return { + field_name: (other_field, other_table) + for field_name, other_field, other_table in cursor.fetchall() + } + + def get_storage_engine(self, cursor, table_name): + """ + Retrieve the storage engine for a given table. Return the default + storage engine if the table doesn't exist. + """ + cursor.execute( + """ + SELECT engine + FROM information_schema.tables + WHERE + table_name = %s AND + table_schema = DATABASE() + """, + [table_name], + ) + result = cursor.fetchone() + if not result: + return self.connection.features._mysql_storage_engine + return result[0] + + def _parse_constraint_columns(self, check_clause, columns): + check_columns = OrderedSet() + statement = sqlparse.parse(check_clause)[0] + tokens = (token for token in statement.flatten() if not token.is_whitespace) + for token in tokens: + if ( + token.ttype == sqlparse.tokens.Name + and self.connection.ops.quote_name(token.value) == token.value + and token.value[1:-1] in columns + ): + check_columns.add(token.value[1:-1]) + return check_columns + + def get_constraints(self, cursor, table_name): + """ + Retrieve any constraints or keys (unique, pk, fk, check, index) across + one or more columns. + """ + constraints = {} + # Get the actual constraint names and columns + name_query = """ + SELECT kc.`constraint_name`, kc.`column_name`, + kc.`referenced_table_name`, kc.`referenced_column_name`, + c.`constraint_type` + FROM + information_schema.key_column_usage AS kc, + information_schema.table_constraints AS c + WHERE + kc.table_schema = DATABASE() AND + ( + kc.referenced_table_schema = DATABASE() OR + kc.referenced_table_schema IS NULL + ) AND + c.table_schema = kc.table_schema AND + c.constraint_name = kc.constraint_name AND + c.constraint_type != 'CHECK' AND + kc.table_name = %s + ORDER BY kc.`ordinal_position` + """ + cursor.execute(name_query, [table_name]) + for constraint, column, ref_table, ref_column, kind in cursor.fetchall(): + if constraint not in constraints: + constraints[constraint] = { + "columns": OrderedSet(), + "primary_key": kind == "PRIMARY KEY", + "unique": kind in {"PRIMARY KEY", "UNIQUE"}, + "index": False, + "check": False, + "foreign_key": (ref_table, ref_column) if ref_column else None, + } + if self.connection.features.supports_index_column_ordering: + constraints[constraint]["orders"] = [] + constraints[constraint]["columns"].add(column) + # Add check constraints. + if self.connection.features.can_introspect_check_constraints: + unnamed_constraints_index = 0 + columns = { + info.name for info in self.get_table_description(cursor, table_name) + } + if self.connection.mysql_is_mariadb: + type_query = """ + SELECT c.constraint_name, c.check_clause + FROM information_schema.check_constraints AS c + WHERE + c.constraint_schema = DATABASE() AND + c.table_name = %s + """ + else: + type_query = """ + SELECT cc.constraint_name, cc.check_clause + FROM + information_schema.check_constraints AS cc, + information_schema.table_constraints AS tc + WHERE + cc.constraint_schema = DATABASE() AND + tc.table_schema = cc.constraint_schema AND + cc.constraint_name = tc.constraint_name AND + tc.constraint_type = 'CHECK' AND + tc.table_name = %s + """ + cursor.execute(type_query, [table_name]) + for constraint, check_clause in cursor.fetchall(): + constraint_columns = self._parse_constraint_columns( + check_clause, columns + ) + # Ensure uniqueness of unnamed constraints. Unnamed unique + # and check columns constraints have the same name as + # a column. + if set(constraint_columns) == {constraint}: + unnamed_constraints_index += 1 + constraint = "__unnamed_constraint_%s__" % unnamed_constraints_index + constraints[constraint] = { + "columns": constraint_columns, + "primary_key": False, + "unique": False, + "index": False, + "check": True, + "foreign_key": None, + } + # Now add in the indexes + cursor.execute( + "SHOW INDEX FROM %s" % self.connection.ops.quote_name(table_name) + ) + for table, non_unique, index, colseq, column, order, type_ in [ + x[:6] + (x[10],) for x in cursor.fetchall() + ]: + if index not in constraints: + constraints[index] = { + "columns": OrderedSet(), + "primary_key": False, + "unique": not non_unique, + "check": False, + "foreign_key": None, + } + if self.connection.features.supports_index_column_ordering: + constraints[index]["orders"] = [] + constraints[index]["index"] = True + constraints[index]["type"] = ( + Index.suffix if type_ == "BTREE" else type_.lower() + ) + constraints[index]["columns"].add(column) + if self.connection.features.supports_index_column_ordering: + constraints[index]["orders"].append("DESC" if order == "D" else "ASC") + # Convert the sorted sets to lists + for constraint in constraints.values(): + constraint["columns"] = list(constraint["columns"]) + return constraints diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/operations.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/operations.py new file mode 100644 index 0000000..76ca815 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/operations.py @@ -0,0 +1,464 @@ +import uuid + +from django.conf import settings +from django.db.backends.base.operations import BaseDatabaseOperations +from django.db.backends.utils import split_tzname_delta +from django.db.models import Exists, ExpressionWrapper, Lookup +from django.db.models.constants import OnConflict +from django.utils import timezone +from django.utils.encoding import force_str +from django.utils.regex_helper import _lazy_re_compile + + +class DatabaseOperations(BaseDatabaseOperations): + compiler_module = "django.db.backends.mysql.compiler" + + # MySQL stores positive fields as UNSIGNED ints. + integer_field_ranges = { + **BaseDatabaseOperations.integer_field_ranges, + "PositiveSmallIntegerField": (0, 65535), + "PositiveIntegerField": (0, 4294967295), + "PositiveBigIntegerField": (0, 18446744073709551615), + } + cast_data_types = { + "AutoField": "signed integer", + "BigAutoField": "signed integer", + "SmallAutoField": "signed integer", + "CharField": "char(%(max_length)s)", + "DecimalField": "decimal(%(max_digits)s, %(decimal_places)s)", + "TextField": "char", + "IntegerField": "signed integer", + "BigIntegerField": "signed integer", + "SmallIntegerField": "signed integer", + "PositiveBigIntegerField": "unsigned integer", + "PositiveIntegerField": "unsigned integer", + "PositiveSmallIntegerField": "unsigned integer", + "DurationField": "signed integer", + } + cast_char_field_without_max_length = "char" + explain_prefix = "EXPLAIN" + + # EXTRACT format cannot be passed in parameters. + _extract_format_re = _lazy_re_compile(r"[A-Z_]+") + + def date_extract_sql(self, lookup_type, sql, params): + # https://dev.mysql.com/doc/mysql/en/date-and-time-functions.html + if lookup_type == "week_day": + # DAYOFWEEK() returns an integer, 1-7, Sunday=1. + return f"DAYOFWEEK({sql})", params + elif lookup_type == "iso_week_day": + # WEEKDAY() returns an integer, 0-6, Monday=0. + return f"WEEKDAY({sql}) + 1", params + elif lookup_type == "week": + # Override the value of default_week_format for consistency with + # other database backends. + # Mode 3: Monday, 1-53, with 4 or more days this year. + return f"WEEK({sql}, 3)", params + elif lookup_type == "iso_year": + # Get the year part from the YEARWEEK function, which returns a + # number as year * 100 + week. + return f"TRUNCATE(YEARWEEK({sql}, 3), -2) / 100", params + else: + # EXTRACT returns 1-53 based on ISO-8601 for the week number. + lookup_type = lookup_type.upper() + if not self._extract_format_re.fullmatch(lookup_type): + raise ValueError(f"Invalid loookup type: {lookup_type!r}") + return f"EXTRACT({lookup_type} FROM {sql})", params + + def date_trunc_sql(self, lookup_type, sql, params, tzname=None): + sql, params = self._convert_sql_to_tz(sql, params, tzname) + fields = { + "year": "%Y-01-01", + "month": "%Y-%m-01", + } + if lookup_type in fields: + format_str = fields[lookup_type] + return f"CAST(DATE_FORMAT({sql}, %s) AS DATE)", (*params, format_str) + elif lookup_type == "quarter": + return ( + f"MAKEDATE(YEAR({sql}), 1) + " + f"INTERVAL QUARTER({sql}) QUARTER - INTERVAL 1 QUARTER", + (*params, *params), + ) + elif lookup_type == "week": + return f"DATE_SUB({sql}, INTERVAL WEEKDAY({sql}) DAY)", (*params, *params) + else: + return f"DATE({sql})", params + + def _prepare_tzname_delta(self, tzname): + tzname, sign, offset = split_tzname_delta(tzname) + return f"{sign}{offset}" if offset else tzname + + def _convert_sql_to_tz(self, sql, params, tzname): + if tzname and settings.USE_TZ and self.connection.timezone_name != tzname: + return f"CONVERT_TZ({sql}, %s, %s)", ( + *params, + self.connection.timezone_name, + self._prepare_tzname_delta(tzname), + ) + return sql, params + + def datetime_cast_date_sql(self, sql, params, tzname): + sql, params = self._convert_sql_to_tz(sql, params, tzname) + return f"DATE({sql})", params + + def datetime_cast_time_sql(self, sql, params, tzname): + sql, params = self._convert_sql_to_tz(sql, params, tzname) + return f"TIME({sql})", params + + def datetime_extract_sql(self, lookup_type, sql, params, tzname): + sql, params = self._convert_sql_to_tz(sql, params, tzname) + return self.date_extract_sql(lookup_type, sql, params) + + def datetime_trunc_sql(self, lookup_type, sql, params, tzname): + sql, params = self._convert_sql_to_tz(sql, params, tzname) + fields = ["year", "month", "day", "hour", "minute", "second"] + format = ("%Y-", "%m", "-%d", " %H:", "%i", ":%s") + format_def = ("0000-", "01", "-01", " 00:", "00", ":00") + if lookup_type == "quarter": + return ( + f"CAST(DATE_FORMAT(MAKEDATE(YEAR({sql}), 1) + " + f"INTERVAL QUARTER({sql}) QUARTER - " + f"INTERVAL 1 QUARTER, %s) AS DATETIME)" + ), (*params, *params, "%Y-%m-01 00:00:00") + if lookup_type == "week": + return ( + f"CAST(DATE_FORMAT(" + f"DATE_SUB({sql}, INTERVAL WEEKDAY({sql}) DAY), %s) AS DATETIME)" + ), (*params, *params, "%Y-%m-%d 00:00:00") + try: + i = fields.index(lookup_type) + 1 + except ValueError: + pass + else: + format_str = "".join(format[:i] + format_def[i:]) + return f"CAST(DATE_FORMAT({sql}, %s) AS DATETIME)", (*params, format_str) + return sql, params + + def time_trunc_sql(self, lookup_type, sql, params, tzname=None): + sql, params = self._convert_sql_to_tz(sql, params, tzname) + fields = { + "hour": "%H:00:00", + "minute": "%H:%i:00", + "second": "%H:%i:%s", + } + if lookup_type in fields: + format_str = fields[lookup_type] + return f"CAST(DATE_FORMAT({sql}, %s) AS TIME)", (*params, format_str) + else: + return f"TIME({sql})", params + + def fetch_returned_insert_rows(self, cursor): + """ + Given a cursor object that has just performed an INSERT...RETURNING + statement into a table, return the tuple of returned data. + """ + return cursor.fetchall() + + def format_for_duration_arithmetic(self, sql): + return "INTERVAL %s MICROSECOND" % sql + + def force_no_ordering(self): + """ + "ORDER BY NULL" prevents MySQL from implicitly ordering by grouped + columns. If no ordering would otherwise be applied, we don't want any + implicit sorting going on. + """ + return [(None, ("NULL", [], False))] + + def adapt_decimalfield_value(self, value, max_digits=None, decimal_places=None): + return value + + def last_executed_query(self, cursor, sql, params): + # With MySQLdb, cursor objects have an (undocumented) "_executed" + # attribute where the exact query sent to the database is saved. + # See MySQLdb/cursors.py in the source distribution. + # MySQLdb returns string, PyMySQL bytes. + return force_str(getattr(cursor, "_executed", None), errors="replace") + + def no_limit_value(self): + # 2**64 - 1, as recommended by the MySQL documentation + return 18446744073709551615 + + def quote_name(self, name): + if name.startswith("`") and name.endswith("`"): + return name # Quoting once is enough. + return "`%s`" % name + + def return_insert_columns(self, fields): + # MySQL and MariaDB < 10.5.0 don't support an INSERT...RETURNING + # statement. + if not fields: + return "", () + columns = [ + "%s.%s" + % ( + self.quote_name(field.model._meta.db_table), + self.quote_name(field.column), + ) + for field in fields + ] + return "RETURNING %s" % ", ".join(columns), () + + def sql_flush(self, style, tables, *, reset_sequences=False, allow_cascade=False): + if not tables: + return [] + + sql = ["SET FOREIGN_KEY_CHECKS = 0;"] + if reset_sequences: + # It's faster to TRUNCATE tables that require a sequence reset + # since ALTER TABLE AUTO_INCREMENT is slower than TRUNCATE. + sql.extend( + "%s %s;" + % ( + style.SQL_KEYWORD("TRUNCATE"), + style.SQL_FIELD(self.quote_name(table_name)), + ) + for table_name in tables + ) + else: + # Otherwise issue a simple DELETE since it's faster than TRUNCATE + # and preserves sequences. + sql.extend( + "%s %s %s;" + % ( + style.SQL_KEYWORD("DELETE"), + style.SQL_KEYWORD("FROM"), + style.SQL_FIELD(self.quote_name(table_name)), + ) + for table_name in tables + ) + sql.append("SET FOREIGN_KEY_CHECKS = 1;") + return sql + + def sequence_reset_by_name_sql(self, style, sequences): + return [ + "%s %s %s %s = 1;" + % ( + style.SQL_KEYWORD("ALTER"), + style.SQL_KEYWORD("TABLE"), + style.SQL_FIELD(self.quote_name(sequence_info["table"])), + style.SQL_FIELD("AUTO_INCREMENT"), + ) + for sequence_info in sequences + ] + + def validate_autopk_value(self, value): + # Zero in AUTO_INCREMENT field does not work without the + # NO_AUTO_VALUE_ON_ZERO SQL mode. + if value == 0 and not self.connection.features.allows_auto_pk_0: + raise ValueError( + "The database backend does not accept 0 as a value for AutoField." + ) + return value + + def adapt_datetimefield_value(self, value): + if value is None: + return None + + # Expression values are adapted by the database. + if hasattr(value, "resolve_expression"): + return value + + # MySQL doesn't support tz-aware datetimes + if timezone.is_aware(value): + if settings.USE_TZ: + value = timezone.make_naive(value, self.connection.timezone) + else: + raise ValueError( + "MySQL backend does not support timezone-aware datetimes when " + "USE_TZ is False." + ) + return str(value) + + def adapt_timefield_value(self, value): + if value is None: + return None + + # Expression values are adapted by the database. + if hasattr(value, "resolve_expression"): + return value + + # MySQL doesn't support tz-aware times + if timezone.is_aware(value): + raise ValueError("MySQL backend does not support timezone-aware times.") + + return value.isoformat(timespec="microseconds") + + def max_name_length(self): + return 64 + + def pk_default_value(self): + return "NULL" + + def bulk_insert_sql(self, fields, placeholder_rows): + placeholder_rows_sql = (", ".join(row) for row in placeholder_rows) + values_sql = ", ".join("(%s)" % sql for sql in placeholder_rows_sql) + return "VALUES " + values_sql + + def combine_expression(self, connector, sub_expressions): + if connector == "^": + return "POW(%s)" % ",".join(sub_expressions) + # Convert the result to a signed integer since MySQL's binary operators + # return an unsigned integer. + elif connector in ("&", "|", "<<", "#"): + connector = "^" if connector == "#" else connector + return "CONVERT(%s, SIGNED)" % connector.join(sub_expressions) + elif connector == ">>": + lhs, rhs = sub_expressions + return "FLOOR(%(lhs)s / POW(2, %(rhs)s))" % {"lhs": lhs, "rhs": rhs} + return super().combine_expression(connector, sub_expressions) + + def get_db_converters(self, expression): + converters = super().get_db_converters(expression) + internal_type = expression.output_field.get_internal_type() + if internal_type == "BooleanField": + converters.append(self.convert_booleanfield_value) + elif internal_type == "DateTimeField": + if settings.USE_TZ: + converters.append(self.convert_datetimefield_value) + elif internal_type == "UUIDField": + converters.append(self.convert_uuidfield_value) + return converters + + def convert_booleanfield_value(self, value, expression, connection): + if value in (0, 1): + value = bool(value) + return value + + def convert_datetimefield_value(self, value, expression, connection): + if value is not None: + value = timezone.make_aware(value, self.connection.timezone) + return value + + def convert_uuidfield_value(self, value, expression, connection): + if value is not None: + value = uuid.UUID(value) + return value + + def binary_placeholder_sql(self, value): + return ( + "_binary %s" if value is not None and not hasattr(value, "as_sql") else "%s" + ) + + def subtract_temporals(self, internal_type, lhs, rhs): + lhs_sql, lhs_params = lhs + rhs_sql, rhs_params = rhs + if internal_type == "TimeField": + if self.connection.mysql_is_mariadb: + # MariaDB includes the microsecond component in TIME_TO_SEC as + # a decimal. MySQL returns an integer without microseconds. + return ( + "CAST((TIME_TO_SEC(%(lhs)s) - TIME_TO_SEC(%(rhs)s)) " + "* 1000000 AS SIGNED)" + ) % { + "lhs": lhs_sql, + "rhs": rhs_sql, + }, ( + *lhs_params, + *rhs_params, + ) + return ( + "((TIME_TO_SEC(%(lhs)s) * 1000000 + MICROSECOND(%(lhs)s)) -" + " (TIME_TO_SEC(%(rhs)s) * 1000000 + MICROSECOND(%(rhs)s)))" + ) % {"lhs": lhs_sql, "rhs": rhs_sql}, tuple(lhs_params) * 2 + tuple( + rhs_params + ) * 2 + params = (*rhs_params, *lhs_params) + return "TIMESTAMPDIFF(MICROSECOND, %s, %s)" % (rhs_sql, lhs_sql), params + + def explain_query_prefix(self, format=None, **options): + # Alias MySQL's TRADITIONAL to TEXT for consistency with other backends. + if format and format.upper() == "TEXT": + format = "TRADITIONAL" + elif ( + not format and "TREE" in self.connection.features.supported_explain_formats + ): + # Use TREE by default (if supported) as it's more informative. + format = "TREE" + analyze = options.pop("analyze", False) + prefix = super().explain_query_prefix(format, **options) + if analyze and self.connection.features.supports_explain_analyze: + # MariaDB uses ANALYZE instead of EXPLAIN ANALYZE. + prefix = ( + "ANALYZE" if self.connection.mysql_is_mariadb else prefix + " ANALYZE" + ) + if format and not (analyze and not self.connection.mysql_is_mariadb): + # Only MariaDB supports the analyze option with formats. + prefix += " FORMAT=%s" % format + return prefix + + def regex_lookup(self, lookup_type): + # REGEXP_LIKE doesn't exist in MariaDB. + if self.connection.mysql_is_mariadb: + if lookup_type == "regex": + return "%s REGEXP BINARY %s" + return "%s REGEXP %s" + + match_option = "c" if lookup_type == "regex" else "i" + return "REGEXP_LIKE(%%s, %%s, '%s')" % match_option + + def insert_statement(self, on_conflict=None): + if on_conflict == OnConflict.IGNORE: + return "INSERT IGNORE INTO" + return super().insert_statement(on_conflict=on_conflict) + + def lookup_cast(self, lookup_type, internal_type=None): + lookup = "%s" + if internal_type == "JSONField": + if self.connection.mysql_is_mariadb or lookup_type in ( + "iexact", + "contains", + "icontains", + "startswith", + "istartswith", + "endswith", + "iendswith", + "regex", + "iregex", + ): + lookup = "JSON_UNQUOTE(%s)" + return lookup + + def conditional_expression_supported_in_where_clause(self, expression): + # MySQL ignores indexes with boolean fields unless they're compared + # directly to a boolean value. + if isinstance(expression, (Exists, Lookup)): + return True + if isinstance(expression, ExpressionWrapper) and expression.conditional: + return self.conditional_expression_supported_in_where_clause( + expression.expression + ) + if getattr(expression, "conditional", False): + return False + return super().conditional_expression_supported_in_where_clause(expression) + + def on_conflict_suffix_sql(self, fields, on_conflict, update_fields, unique_fields): + if on_conflict == OnConflict.UPDATE: + conflict_suffix_sql = "ON DUPLICATE KEY UPDATE %(fields)s" + # The use of VALUES() is deprecated in MySQL 8.0.20+. Instead, use + # aliases for the new row and its columns available in MySQL + # 8.0.19+. + if not self.connection.mysql_is_mariadb: + if self.connection.mysql_version >= (8, 0, 19): + conflict_suffix_sql = f"AS new {conflict_suffix_sql}" + field_sql = "%(field)s = new.%(field)s" + else: + field_sql = "%(field)s = VALUES(%(field)s)" + # Use VALUE() on MariaDB. + else: + field_sql = "%(field)s = VALUE(%(field)s)" + + fields = ", ".join( + [ + field_sql % {"field": field} + for field in map(self.quote_name, update_fields) + ] + ) + return conflict_suffix_sql % {"fields": fields} + return super().on_conflict_suffix_sql( + fields, + on_conflict, + update_fields, + unique_fields, + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/schema.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/schema.py new file mode 100644 index 0000000..905a26b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/schema.py @@ -0,0 +1,271 @@ +from django.db.backends.base.schema import BaseDatabaseSchemaEditor +from django.db.models import NOT_PROVIDED, F, UniqueConstraint +from django.db.models.constants import LOOKUP_SEP + + +class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): + sql_rename_table = "RENAME TABLE %(old_table)s TO %(new_table)s" + + sql_alter_column_null = "MODIFY %(column)s %(type)s NULL" + sql_alter_column_not_null = "MODIFY %(column)s %(type)s NOT NULL" + sql_alter_column_type = "MODIFY %(column)s %(type)s%(collation)s%(comment)s" + sql_alter_column_no_default_null = "ALTER COLUMN %(column)s SET DEFAULT NULL" + + # No 'CASCADE' which works as a no-op in MySQL but is undocumented + sql_delete_column = "ALTER TABLE %(table)s DROP COLUMN %(column)s" + + sql_delete_unique = "ALTER TABLE %(table)s DROP INDEX %(name)s" + sql_create_column_inline_fk = ( + ", ADD CONSTRAINT %(name)s FOREIGN KEY (%(column)s) " + "REFERENCES %(to_table)s(%(to_column)s)" + ) + sql_delete_fk = "ALTER TABLE %(table)s DROP FOREIGN KEY %(name)s" + + sql_delete_index = "DROP INDEX %(name)s ON %(table)s" + sql_rename_index = "ALTER TABLE %(table)s RENAME INDEX %(old_name)s TO %(new_name)s" + + sql_create_pk = ( + "ALTER TABLE %(table)s ADD CONSTRAINT %(name)s PRIMARY KEY (%(columns)s)" + ) + sql_delete_pk = "ALTER TABLE %(table)s DROP PRIMARY KEY" + + sql_create_index = "CREATE INDEX %(name)s ON %(table)s (%(columns)s)%(extra)s" + + sql_alter_table_comment = "ALTER TABLE %(table)s COMMENT = %(comment)s" + sql_alter_column_comment = None + + @property + def sql_delete_check(self): + if self.connection.mysql_is_mariadb: + # The name of the column check constraint is the same as the field + # name on MariaDB. Adding IF EXISTS clause prevents migrations + # crash. Constraint is removed during a "MODIFY" column statement. + return "ALTER TABLE %(table)s DROP CONSTRAINT IF EXISTS %(name)s" + return "ALTER TABLE %(table)s DROP CHECK %(name)s" + + @property + def sql_rename_column(self): + is_mariadb = self.connection.mysql_is_mariadb + if is_mariadb and self.connection.mysql_version < (10, 5, 2): + # MariaDB < 10.5.2 doesn't support an + # "ALTER TABLE ... RENAME COLUMN" statement. + return "ALTER TABLE %(table)s CHANGE %(old_column)s %(new_column)s %(type)s" + return super().sql_rename_column + + def quote_value(self, value): + self.connection.ensure_connection() + # MySQLdb escapes to string, PyMySQL to bytes. + quoted = self.connection.connection.escape( + value, self.connection.connection.encoders + ) + if isinstance(value, str) and isinstance(quoted, bytes): + quoted = quoted.decode() + return quoted + + def _is_limited_data_type(self, field): + db_type = field.db_type(self.connection) + return ( + db_type is not None + and db_type.lower() in self.connection._limited_data_types + ) + + def skip_default(self, field): + if not self._supports_limited_data_type_defaults: + return self._is_limited_data_type(field) + return False + + def skip_default_on_alter(self, field): + if self._is_limited_data_type(field) and not self.connection.mysql_is_mariadb: + # MySQL doesn't support defaults for BLOB and TEXT in the + # ALTER COLUMN statement. + return True + return False + + @property + def _supports_limited_data_type_defaults(self): + # MariaDB and MySQL >= 8.0.13 support defaults for BLOB and TEXT. + if self.connection.mysql_is_mariadb: + return True + return self.connection.mysql_version >= (8, 0, 13) + + def _column_default_sql(self, field): + if ( + not self.connection.mysql_is_mariadb + and self._supports_limited_data_type_defaults + and self._is_limited_data_type(field) + ): + # MySQL supports defaults for BLOB and TEXT columns only if the + # default value is written as an expression i.e. in parentheses. + return "(%s)" + return super()._column_default_sql(field) + + def add_field(self, model, field): + super().add_field(model, field) + + # Simulate the effect of a one-off default. + # field.default may be unhashable, so a set isn't used for "in" check. + if self.skip_default(field) and field.default not in (None, NOT_PROVIDED): + effective_default = self.effective_default(field) + self.execute( + "UPDATE %(table)s SET %(column)s = %%s" + % { + "table": self.quote_name(model._meta.db_table), + "column": self.quote_name(field.column), + }, + [effective_default], + ) + + def remove_constraint(self, model, constraint): + if ( + isinstance(constraint, UniqueConstraint) + and constraint.create_sql(model, self) is not None + ): + self._create_missing_fk_index( + model, + fields=constraint.fields, + expressions=constraint.expressions, + ) + super().remove_constraint(model, constraint) + + def remove_index(self, model, index): + self._create_missing_fk_index( + model, + fields=[field_name for field_name, _ in index.fields_orders], + expressions=index.expressions, + ) + super().remove_index(model, index) + + def _field_should_be_indexed(self, model, field): + if not super()._field_should_be_indexed(model, field): + return False + + storage = self.connection.introspection.get_storage_engine( + self.connection.cursor(), model._meta.db_table + ) + # No need to create an index for ForeignKey fields except if + # db_constraint=False because the index from that constraint won't be + # created. + if ( + storage == "InnoDB" + and field.get_internal_type() == "ForeignKey" + and field.db_constraint + ): + return False + return not self._is_limited_data_type(field) + + def _create_missing_fk_index( + self, + model, + *, + fields, + expressions=None, + ): + """ + MySQL can remove an implicit FK index on a field when that field is + covered by another index like a unique_together. "covered" here means + that the more complex index has the FK field as its first field (see + https://bugs.mysql.com/bug.php?id=37910). + + Manually create an implicit FK index to make it possible to remove the + composed index. + """ + first_field_name = None + if fields: + first_field_name = fields[0] + elif ( + expressions + and self.connection.features.supports_expression_indexes + and isinstance(expressions[0], F) + and LOOKUP_SEP not in expressions[0].name + ): + first_field_name = expressions[0].name + + if not first_field_name: + return + + first_field = model._meta.get_field(first_field_name) + if first_field.get_internal_type() == "ForeignKey": + column = self.connection.introspection.identifier_converter( + first_field.column + ) + with self.connection.cursor() as cursor: + constraint_names = [ + name + for name, infodict in self.connection.introspection.get_constraints( + cursor, model._meta.db_table + ).items() + if infodict["index"] and infodict["columns"][0] == column + ] + # There are no other indexes that starts with the FK field, only + # the index that is expected to be deleted. + if len(constraint_names) == 1: + self.execute( + self._create_index_sql(model, fields=[first_field], suffix="") + ) + + def _delete_composed_index(self, model, fields, *args): + self._create_missing_fk_index(model, fields=fields) + return super()._delete_composed_index(model, fields, *args) + + def _set_field_new_type(self, field, new_type): + """ + Keep the NULL and DEFAULT properties of the old field. If it has + changed, it will be handled separately. + """ + if field.db_default is not NOT_PROVIDED: + default_sql, params = self.db_default_sql(field) + default_sql %= tuple(self.quote_value(p) for p in params) + new_type += f" DEFAULT {default_sql}" + if field.null: + new_type += " NULL" + else: + new_type += " NOT NULL" + return new_type + + def _alter_column_type_sql( + self, model, old_field, new_field, new_type, old_collation, new_collation + ): + new_type = self._set_field_new_type(old_field, new_type) + return super()._alter_column_type_sql( + model, old_field, new_field, new_type, old_collation, new_collation + ) + + def _field_db_check(self, field, field_db_params): + if self.connection.mysql_is_mariadb and self.connection.mysql_version >= ( + 10, + 5, + 2, + ): + return super()._field_db_check(field, field_db_params) + # On MySQL and MariaDB < 10.5.2 (no support for + # "ALTER TABLE ... RENAME COLUMN" statements), check constraints with + # the column name as it requires explicit recreation when the column is + # renamed. + return field_db_params["check"] + + def _rename_field_sql(self, table, old_field, new_field, new_type): + new_type = self._set_field_new_type(old_field, new_type) + return super()._rename_field_sql(table, old_field, new_field, new_type) + + def _alter_column_comment_sql(self, model, new_field, new_type, new_db_comment): + # Comment is alter when altering the column type. + return "", [] + + def _comment_sql(self, comment): + comment_sql = super()._comment_sql(comment) + return f" COMMENT {comment_sql}" + + def _alter_column_null_sql(self, model, old_field, new_field): + if new_field.db_default is NOT_PROVIDED: + return super()._alter_column_null_sql(model, old_field, new_field) + + new_db_params = new_field.db_parameters(connection=self.connection) + type_sql = self._set_field_new_type(new_field, new_db_params["type"]) + return ( + "MODIFY %(column)s %(type)s" + % { + "column": self.quote_name(new_field.column), + "type": type_sql, + }, + [], + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/validation.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/validation.py new file mode 100644 index 0000000..fdc3809 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/mysql/validation.py @@ -0,0 +1,77 @@ +from django.core import checks +from django.db.backends.base.validation import BaseDatabaseValidation +from django.utils.version import get_docs_version + + +class DatabaseValidation(BaseDatabaseValidation): + def check(self, **kwargs): + issues = super().check(**kwargs) + issues.extend(self._check_sql_mode(**kwargs)) + return issues + + def _check_sql_mode(self, **kwargs): + if not ( + self.connection.sql_mode & {"STRICT_TRANS_TABLES", "STRICT_ALL_TABLES"} + ): + return [ + checks.Warning( + "%s Strict Mode is not set for database connection '%s'" + % (self.connection.display_name, self.connection.alias), + hint=( + "%s's Strict Mode fixes many data integrity problems in " + "%s, such as data truncation upon insertion, by " + "escalating warnings into errors. It is strongly " + "recommended you activate it. See: " + "https://docs.djangoproject.com/en/%s/ref/databases/" + "#mysql-sql-mode" + % ( + self.connection.display_name, + self.connection.display_name, + get_docs_version(), + ), + ), + id="mysql.W002", + ) + ] + return [] + + def check_field_type(self, field, field_type): + """ + MySQL has the following field length restriction: + No character (varchar) fields can have a length exceeding 255 + characters if they have a unique index on them. + MySQL doesn't support a database index on some data types. + """ + errors = [] + if ( + field_type.startswith("varchar") + and field.unique + and (field.max_length is None or int(field.max_length) > 255) + ): + errors.append( + checks.Warning( + "%s may not allow unique CharFields to have a max_length " + "> 255." % self.connection.display_name, + obj=field, + hint=( + "See: https://docs.djangoproject.com/en/%s/ref/" + "databases/#mysql-character-fields" % get_docs_version() + ), + id="mysql.W003", + ) + ) + + if field.db_index and field_type.lower() in self.connection._limited_data_types: + errors.append( + checks.Warning( + "%s does not support a database index on %s columns." + % (self.connection.display_name, field_type), + hint=( + "An index won't be created. Silence this warning if " + "you don't care about it." + ), + obj=field, + id="fields.W162", + ) + ) + return errors diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/base.py new file mode 100644 index 0000000..803c3a5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/base.py @@ -0,0 +1,585 @@ +""" +Oracle database backend for Django. + +Requires oracledb: https://oracle.github.io/python-oracledb/ +""" +import datetime +import decimal +import os +import platform +from contextlib import contextmanager + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.db import IntegrityError +from django.db.backends.base.base import BaseDatabaseWrapper +from django.db.backends.oracle.oracledb_any import oracledb as Database +from django.db.backends.utils import debug_transaction +from django.utils.asyncio import async_unsafe +from django.utils.encoding import force_bytes, force_str +from django.utils.functional import cached_property + + +def _setup_environment(environ): + # Cygwin requires some special voodoo to set the environment variables + # properly so that Oracle will see them. + if platform.system().upper().startswith("CYGWIN"): + try: + import ctypes + except ImportError as e: + raise ImproperlyConfigured( + "Error loading ctypes: %s; " + "the Oracle backend requires ctypes to " + "operate correctly under Cygwin." % e + ) + kernel32 = ctypes.CDLL("kernel32") + for name, value in environ: + kernel32.SetEnvironmentVariableA(name, value) + else: + os.environ.update(environ) + + +_setup_environment( + [ + # Oracle takes client-side character set encoding from the environment. + ("NLS_LANG", ".AL32UTF8"), + # This prevents Unicode from getting mangled by getting encoded into the + # potentially non-Unicode database character set. + ("ORA_NCHAR_LITERAL_REPLACE", "TRUE"), + ] +) + + +# Some of these import oracledb, so import them after checking if it's +# installed. +from .client import DatabaseClient # NOQA +from .creation import DatabaseCreation # NOQA +from .features import DatabaseFeatures # NOQA +from .introspection import DatabaseIntrospection # NOQA +from .operations import DatabaseOperations # NOQA +from .schema import DatabaseSchemaEditor # NOQA +from .utils import Oracle_datetime, dsn # NOQA +from .validation import DatabaseValidation # NOQA + + +@contextmanager +def wrap_oracle_errors(): + try: + yield + except Database.DatabaseError as e: + # oracledb raises a oracledb.DatabaseError exception with the + # following attributes and values: + # code = 2091 + # message = 'ORA-02091: transaction rolled back + # 'ORA-02291: integrity constraint (TEST_DJANGOTEST.SYS + # _C00102056) violated - parent key not found' + # or: + # 'ORA-00001: unique constraint (DJANGOTEST.DEFERRABLE_ + # PINK_CONSTRAINT) violated + # Convert that case to Django's IntegrityError exception. + x = e.args[0] + if ( + hasattr(x, "code") + and hasattr(x, "message") + and x.code == 2091 + and ("ORA-02291" in x.message or "ORA-00001" in x.message) + ): + raise IntegrityError(*tuple(e.args)) + raise + + +class _UninitializedOperatorsDescriptor: + def __get__(self, instance, cls=None): + # If connection.operators is looked up before a connection has been + # created, transparently initialize connection.operators to avert an + # AttributeError. + if instance is None: + raise AttributeError("operators not available as class attribute") + # Creating a cursor will initialize the operators. + instance.cursor().close() + return instance.__dict__["operators"] + + +class DatabaseWrapper(BaseDatabaseWrapper): + vendor = "oracle" + display_name = "Oracle" + # This dictionary maps Field objects to their associated Oracle column + # types, as strings. Column-type strings can contain format strings; they'll + # be interpolated against the values of Field.__dict__ before being output. + # If a column type is set to None, it won't be included in the output. + # + # Any format strings starting with "qn_" are quoted before being used in the + # output (the "qn_" prefix is stripped before the lookup is performed. + data_types = { + "AutoField": "NUMBER(11) GENERATED BY DEFAULT ON NULL AS IDENTITY", + "BigAutoField": "NUMBER(19) GENERATED BY DEFAULT ON NULL AS IDENTITY", + "BinaryField": "BLOB", + "BooleanField": "NUMBER(1)", + "CharField": "NVARCHAR2(%(max_length)s)", + "DateField": "DATE", + "DateTimeField": "TIMESTAMP", + "DecimalField": "NUMBER(%(max_digits)s, %(decimal_places)s)", + "DurationField": "INTERVAL DAY(9) TO SECOND(6)", + "FileField": "NVARCHAR2(%(max_length)s)", + "FilePathField": "NVARCHAR2(%(max_length)s)", + "FloatField": "DOUBLE PRECISION", + "IntegerField": "NUMBER(11)", + "JSONField": "NCLOB", + "BigIntegerField": "NUMBER(19)", + "IPAddressField": "VARCHAR2(15)", + "GenericIPAddressField": "VARCHAR2(39)", + "OneToOneField": "NUMBER(11)", + "PositiveBigIntegerField": "NUMBER(19)", + "PositiveIntegerField": "NUMBER(11)", + "PositiveSmallIntegerField": "NUMBER(11)", + "SlugField": "NVARCHAR2(%(max_length)s)", + "SmallAutoField": "NUMBER(5) GENERATED BY DEFAULT ON NULL AS IDENTITY", + "SmallIntegerField": "NUMBER(11)", + "TextField": "NCLOB", + "TimeField": "TIMESTAMP", + "URLField": "VARCHAR2(%(max_length)s)", + "UUIDField": "VARCHAR2(32)", + } + data_type_check_constraints = { + "BooleanField": "%(qn_column)s IN (0,1)", + "JSONField": "%(qn_column)s IS JSON", + "PositiveBigIntegerField": "%(qn_column)s >= 0", + "PositiveIntegerField": "%(qn_column)s >= 0", + "PositiveSmallIntegerField": "%(qn_column)s >= 0", + } + + # Oracle doesn't support a database index on these columns. + _limited_data_types = ("clob", "nclob", "blob") + + operators = _UninitializedOperatorsDescriptor() + + _standard_operators = { + "exact": "= %s", + "iexact": "= UPPER(%s)", + "contains": ( + "LIKE TRANSLATE(%s USING NCHAR_CS) ESCAPE TRANSLATE('\\' USING NCHAR_CS)" + ), + "icontains": ( + "LIKE UPPER(TRANSLATE(%s USING NCHAR_CS)) " + "ESCAPE TRANSLATE('\\' USING NCHAR_CS)" + ), + "gt": "> %s", + "gte": ">= %s", + "lt": "< %s", + "lte": "<= %s", + "startswith": ( + "LIKE TRANSLATE(%s USING NCHAR_CS) ESCAPE TRANSLATE('\\' USING NCHAR_CS)" + ), + "endswith": ( + "LIKE TRANSLATE(%s USING NCHAR_CS) ESCAPE TRANSLATE('\\' USING NCHAR_CS)" + ), + "istartswith": ( + "LIKE UPPER(TRANSLATE(%s USING NCHAR_CS)) " + "ESCAPE TRANSLATE('\\' USING NCHAR_CS)" + ), + "iendswith": ( + "LIKE UPPER(TRANSLATE(%s USING NCHAR_CS)) " + "ESCAPE TRANSLATE('\\' USING NCHAR_CS)" + ), + } + + _likec_operators = { + **_standard_operators, + "contains": "LIKEC %s ESCAPE '\\'", + "icontains": "LIKEC UPPER(%s) ESCAPE '\\'", + "startswith": "LIKEC %s ESCAPE '\\'", + "endswith": "LIKEC %s ESCAPE '\\'", + "istartswith": "LIKEC UPPER(%s) ESCAPE '\\'", + "iendswith": "LIKEC UPPER(%s) ESCAPE '\\'", + } + + # The patterns below are used to generate SQL pattern lookup clauses when + # the right-hand side of the lookup isn't a raw string (it might be an expression + # or the result of a bilateral transformation). + # In those cases, special characters for LIKE operators (e.g. \, %, _) + # should be escaped on the database side. + # + # Note: we use str.format() here for readability as '%' is used as a wildcard for + # the LIKE operator. + pattern_esc = r"REPLACE(REPLACE(REPLACE({}, '\', '\\'), '%%', '\%%'), '_', '\_')" + _pattern_ops = { + "contains": "'%%' || {} || '%%'", + "icontains": "'%%' || UPPER({}) || '%%'", + "startswith": "{} || '%%'", + "istartswith": "UPPER({}) || '%%'", + "endswith": "'%%' || {}", + "iendswith": "'%%' || UPPER({})", + } + + _standard_pattern_ops = { + k: "LIKE TRANSLATE( " + v + " USING NCHAR_CS)" + " ESCAPE TRANSLATE('\\' USING NCHAR_CS)" + for k, v in _pattern_ops.items() + } + _likec_pattern_ops = { + k: "LIKEC " + v + " ESCAPE '\\'" for k, v in _pattern_ops.items() + } + + Database = Database + SchemaEditorClass = DatabaseSchemaEditor + # Classes instantiated in __init__(). + client_class = DatabaseClient + creation_class = DatabaseCreation + features_class = DatabaseFeatures + introspection_class = DatabaseIntrospection + ops_class = DatabaseOperations + validation_class = DatabaseValidation + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + use_returning_into = self.settings_dict["OPTIONS"].get( + "use_returning_into", True + ) + self.features.can_return_columns_from_insert = use_returning_into + + def get_database_version(self): + return self.oracle_version + + def get_connection_params(self): + conn_params = self.settings_dict["OPTIONS"].copy() + if "use_returning_into" in conn_params: + del conn_params["use_returning_into"] + return conn_params + + @async_unsafe + def get_new_connection(self, conn_params): + return Database.connect( + user=self.settings_dict["USER"], + password=self.settings_dict["PASSWORD"], + dsn=dsn(self.settings_dict), + **conn_params, + ) + + def init_connection_state(self): + super().init_connection_state() + cursor = self.create_cursor() + # Set the territory first. The territory overrides NLS_DATE_FORMAT + # and NLS_TIMESTAMP_FORMAT to the territory default. When all of + # these are set in single statement it isn't clear what is supposed + # to happen. + cursor.execute("ALTER SESSION SET NLS_TERRITORY = 'AMERICA'") + # Set Oracle date to ANSI date format. This only needs to execute + # once when we create a new connection. We also set the Territory + # to 'AMERICA' which forces Sunday to evaluate to a '1' in + # TO_CHAR(). + cursor.execute( + "ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'" + " NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF'" + + (" TIME_ZONE = 'UTC'" if settings.USE_TZ else "") + ) + cursor.close() + if "operators" not in self.__dict__: + # Ticket #14149: Check whether our LIKE implementation will + # work for this connection or we need to fall back on LIKEC. + # This check is performed only once per DatabaseWrapper + # instance per thread, since subsequent connections will use + # the same settings. + cursor = self.create_cursor() + try: + cursor.execute( + "SELECT 1 FROM DUAL WHERE DUMMY %s" + % self._standard_operators["contains"], + ["X"], + ) + except Database.DatabaseError: + self.operators = self._likec_operators + self.pattern_ops = self._likec_pattern_ops + else: + self.operators = self._standard_operators + self.pattern_ops = self._standard_pattern_ops + cursor.close() + self.connection.stmtcachesize = 20 + # Ensure all changes are preserved even when AUTOCOMMIT is False. + if not self.get_autocommit(): + self.commit() + + @async_unsafe + def create_cursor(self, name=None): + return FormatStylePlaceholderCursor(self.connection) + + def _commit(self): + if self.connection is not None: + with debug_transaction(self, "COMMIT"), wrap_oracle_errors(): + return self.connection.commit() + + # Oracle doesn't support releasing savepoints. But we fake them when query + # logging is enabled to keep query counts consistent with other backends. + def _savepoint_commit(self, sid): + if self.queries_logged: + self.queries_log.append( + { + "sql": "-- RELEASE SAVEPOINT %s (faked)" % self.ops.quote_name(sid), + "time": "0.000", + } + ) + + def _set_autocommit(self, autocommit): + with self.wrap_database_errors: + self.connection.autocommit = autocommit + + def check_constraints(self, table_names=None): + """ + Check constraints by setting them to immediate. Return them to deferred + afterward. + """ + with self.cursor() as cursor: + cursor.execute("SET CONSTRAINTS ALL IMMEDIATE") + cursor.execute("SET CONSTRAINTS ALL DEFERRED") + + def is_usable(self): + try: + self.connection.ping() + except Database.Error: + return False + else: + return True + + @cached_property + def oracle_version(self): + with self.temporary_connection(): + return tuple(int(x) for x in self.connection.version.split(".")) + + +class OracleParam: + """ + Wrapper object for formatting parameters for Oracle. If the string + representation of the value is large enough (greater than 4000 characters) + the input size needs to be set as CLOB. Alternatively, if the parameter + has an `input_size` attribute, then the value of the `input_size` attribute + will be used instead. Otherwise, no input size will be set for the + parameter when executing the query. + """ + + def __init__(self, param, cursor, strings_only=False): + # With raw SQL queries, datetimes can reach this function + # without being converted by DateTimeField.get_db_prep_value. + if settings.USE_TZ and ( + isinstance(param, datetime.datetime) + and not isinstance(param, Oracle_datetime) + ): + param = Oracle_datetime.from_datetime(param) + + string_size = 0 + # Oracle doesn't recognize True and False correctly. + if param is True: + param = 1 + elif param is False: + param = 0 + if hasattr(param, "bind_parameter"): + self.force_bytes = param.bind_parameter(cursor) + elif isinstance(param, (Database.Binary, datetime.timedelta)): + self.force_bytes = param + else: + # To transmit to the database, we need Unicode if supported + # To get size right, we must consider bytes. + self.force_bytes = force_str(param, cursor.charset, strings_only) + if isinstance(self.force_bytes, str): + # We could optimize by only converting up to 4000 bytes here + string_size = len(force_bytes(param, cursor.charset, strings_only)) + if hasattr(param, "input_size"): + # If parameter has `input_size` attribute, use that. + self.input_size = param.input_size + elif string_size > 4000: + # Mark any string param greater than 4000 characters as a CLOB. + self.input_size = Database.CLOB + elif isinstance(param, datetime.datetime): + self.input_size = Database.TIMESTAMP + else: + self.input_size = None + + +class VariableWrapper: + """ + An adapter class for cursor variables that prevents the wrapped object + from being converted into a string when used to instantiate an OracleParam. + This can be used generally for any other object that should be passed into + Cursor.execute as-is. + """ + + def __init__(self, var): + self.var = var + + def bind_parameter(self, cursor): + return self.var + + def __getattr__(self, key): + return getattr(self.var, key) + + def __setattr__(self, key, value): + if key == "var": + self.__dict__[key] = value + else: + setattr(self.var, key, value) + + +class FormatStylePlaceholderCursor: + """ + Django uses "format" (e.g. '%s') style placeholders, but Oracle uses ":var" + style. This fixes it -- but note that if you want to use a literal "%s" in + a query, you'll need to use "%%s". + """ + + charset = "utf-8" + + def __init__(self, connection): + self.cursor = connection.cursor() + self.cursor.outputtypehandler = self._output_type_handler + + @staticmethod + def _output_number_converter(value): + return decimal.Decimal(value) if "." in value else int(value) + + @staticmethod + def _get_decimal_converter(precision, scale): + if scale == 0: + return int + context = decimal.Context(prec=precision) + quantize_value = decimal.Decimal(1).scaleb(-scale) + return lambda v: decimal.Decimal(v).quantize(quantize_value, context=context) + + @staticmethod + def _output_type_handler(cursor, name, defaultType, length, precision, scale): + """ + Called for each db column fetched from cursors. Return numbers as the + appropriate Python type. + """ + if defaultType == Database.NUMBER: + if scale == -127: + if precision == 0: + # NUMBER column: decimal-precision floating point. + # This will normally be an integer from a sequence, + # but it could be a decimal value. + outconverter = FormatStylePlaceholderCursor._output_number_converter + else: + # FLOAT column: binary-precision floating point. + # This comes from FloatField columns. + outconverter = float + elif precision > 0: + # NUMBER(p,s) column: decimal-precision fixed point. + # This comes from IntegerField and DecimalField columns. + outconverter = FormatStylePlaceholderCursor._get_decimal_converter( + precision, scale + ) + else: + # No type information. This normally comes from a + # mathematical expression in the SELECT list. Guess int + # or Decimal based on whether it has a decimal point. + outconverter = FormatStylePlaceholderCursor._output_number_converter + return cursor.var( + Database.STRING, + size=255, + arraysize=cursor.arraysize, + outconverter=outconverter, + ) + + def _format_params(self, params): + try: + return {k: OracleParam(v, self, True) for k, v in params.items()} + except AttributeError: + return tuple(OracleParam(p, self, True) for p in params) + + def _guess_input_sizes(self, params_list): + # Try dict handling; if that fails, treat as sequence + if hasattr(params_list[0], "keys"): + sizes = {} + for params in params_list: + for k, value in params.items(): + if value.input_size: + sizes[k] = value.input_size + if sizes: + self.setinputsizes(**sizes) + else: + # It's not a list of dicts; it's a list of sequences + sizes = [None] * len(params_list[0]) + for params in params_list: + for i, value in enumerate(params): + if value.input_size: + sizes[i] = value.input_size + if sizes: + self.setinputsizes(*sizes) + + def _param_generator(self, params): + # Try dict handling; if that fails, treat as sequence + if hasattr(params, "items"): + return {k: v.force_bytes for k, v in params.items()} + else: + return [p.force_bytes for p in params] + + def _fix_for_params(self, query, params, unify_by_values=False): + # oracledb wants no trailing ';' for SQL statements. For PL/SQL, it + # it does want a trailing ';' but not a trailing '/'. However, these + # characters must be included in the original query in case the query + # is being passed to SQL*Plus. + if query.endswith(";") or query.endswith("/"): + query = query[:-1] + if params is None: + params = [] + elif hasattr(params, "keys"): + # Handle params as dict + args = {k: ":%s" % k for k in params} + query %= args + elif unify_by_values and params: + # Handle params as a dict with unified query parameters by their + # values. It can be used only in single query execute() because + # executemany() shares the formatted query with each of the params + # list. e.g. for input params = [0.75, 2, 0.75, 'sth', 0.75] + # params_dict = {0.75: ':arg0', 2: ':arg1', 'sth': ':arg2'} + # args = [':arg0', ':arg1', ':arg0', ':arg2', ':arg0'] + # params = {':arg0': 0.75, ':arg1': 2, ':arg2': 'sth'} + params_dict = { + param: ":arg%d" % i for i, param in enumerate(dict.fromkeys(params)) + } + args = [params_dict[param] for param in params] + params = {value: key for key, value in params_dict.items()} + query %= tuple(args) + else: + # Handle params as sequence + args = [(":arg%d" % i) for i in range(len(params))] + query %= tuple(args) + return query, self._format_params(params) + + def execute(self, query, params=None): + query, params = self._fix_for_params(query, params, unify_by_values=True) + self._guess_input_sizes([params]) + with wrap_oracle_errors(): + return self.cursor.execute(query, self._param_generator(params)) + + def executemany(self, query, params=None): + if not params: + # No params given, nothing to do + return None + # uniform treatment for sequences and iterables + params_iter = iter(params) + query, firstparams = self._fix_for_params(query, next(params_iter)) + # we build a list of formatted params; as we're going to traverse it + # more than once, we can't make it lazy by using a generator + formatted = [firstparams] + [self._format_params(p) for p in params_iter] + self._guess_input_sizes(formatted) + with wrap_oracle_errors(): + return self.cursor.executemany( + query, [self._param_generator(p) for p in formatted] + ) + + def close(self): + try: + self.cursor.close() + except Database.InterfaceError: + # already closed + pass + + def var(self, *args): + return VariableWrapper(self.cursor.var(*args)) + + def arrayvar(self, *args): + return VariableWrapper(self.cursor.arrayvar(*args)) + + def __getattr__(self, attr): + return getattr(self.cursor, attr) + + def __iter__(self): + return iter(self.cursor) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/client.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/client.py new file mode 100644 index 0000000..365b116 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/client.py @@ -0,0 +1,27 @@ +import shutil + +from django.db.backends.base.client import BaseDatabaseClient + + +class DatabaseClient(BaseDatabaseClient): + executable_name = "sqlplus" + wrapper_name = "rlwrap" + + @staticmethod + def connect_string(settings_dict): + from django.db.backends.oracle.utils import dsn + + return '%s/"%s"@%s' % ( + settings_dict["USER"], + settings_dict["PASSWORD"], + dsn(settings_dict), + ) + + @classmethod + def settings_to_cmd_args_env(cls, settings_dict, parameters): + args = [cls.executable_name, "-L", cls.connect_string(settings_dict)] + wrapper_path = shutil.which(cls.wrapper_name) + if wrapper_path: + args = [wrapper_path, *args] + args.extend(parameters) + return args, None diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/creation.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/creation.py new file mode 100644 index 0000000..df773bf --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/creation.py @@ -0,0 +1,464 @@ +import sys + +from django.conf import settings +from django.db import DatabaseError +from django.db.backends.base.creation import BaseDatabaseCreation +from django.utils.crypto import get_random_string +from django.utils.functional import cached_property + +TEST_DATABASE_PREFIX = "test_" + + +class DatabaseCreation(BaseDatabaseCreation): + @cached_property + def _maindb_connection(self): + """ + This is analogous to other backends' `_nodb_connection` property, + which allows access to an "administrative" connection which can + be used to manage the test databases. + For Oracle, the only connection that can be used for that purpose + is the main (non-test) connection. + """ + settings_dict = settings.DATABASES[self.connection.alias] + user = settings_dict.get("SAVED_USER") or settings_dict["USER"] + password = settings_dict.get("SAVED_PASSWORD") or settings_dict["PASSWORD"] + settings_dict = {**settings_dict, "USER": user, "PASSWORD": password} + DatabaseWrapper = type(self.connection) + return DatabaseWrapper(settings_dict, alias=self.connection.alias) + + def _create_test_db(self, verbosity=1, autoclobber=False, keepdb=False): + parameters = self._get_test_db_params() + with self._maindb_connection.cursor() as cursor: + if self._test_database_create(): + try: + self._execute_test_db_creation( + cursor, parameters, verbosity, keepdb + ) + except Exception as e: + if "ORA-01543" not in str(e): + # All errors except "tablespace already exists" cancel tests + self.log("Got an error creating the test database: %s" % e) + sys.exit(2) + if not autoclobber: + confirm = input( + "It appears the test database, %s, already exists. " + "Type 'yes' to delete it, or 'no' to cancel: " + % parameters["user"] + ) + if autoclobber or confirm == "yes": + if verbosity >= 1: + self.log( + "Destroying old test database for alias '%s'..." + % self.connection.alias + ) + try: + self._execute_test_db_destruction( + cursor, parameters, verbosity + ) + except DatabaseError as e: + if "ORA-29857" in str(e): + self._handle_objects_preventing_db_destruction( + cursor, parameters, verbosity, autoclobber + ) + else: + # Ran into a database error that isn't about + # leftover objects in the tablespace. + self.log( + "Got an error destroying the old test database: %s" + % e + ) + sys.exit(2) + except Exception as e: + self.log( + "Got an error destroying the old test database: %s" % e + ) + sys.exit(2) + try: + self._execute_test_db_creation( + cursor, parameters, verbosity, keepdb + ) + except Exception as e: + self.log( + "Got an error recreating the test database: %s" % e + ) + sys.exit(2) + else: + self.log("Tests cancelled.") + sys.exit(1) + + if self._test_user_create(): + if verbosity >= 1: + self.log("Creating test user...") + try: + self._create_test_user(cursor, parameters, verbosity, keepdb) + except Exception as e: + if "ORA-01920" not in str(e): + # All errors except "user already exists" cancel tests + self.log("Got an error creating the test user: %s" % e) + sys.exit(2) + if not autoclobber: + confirm = input( + "It appears the test user, %s, already exists. Type " + "'yes' to delete it, or 'no' to cancel: " + % parameters["user"] + ) + if autoclobber or confirm == "yes": + try: + if verbosity >= 1: + self.log("Destroying old test user...") + self._destroy_test_user(cursor, parameters, verbosity) + if verbosity >= 1: + self.log("Creating test user...") + self._create_test_user( + cursor, parameters, verbosity, keepdb + ) + except Exception as e: + self.log("Got an error recreating the test user: %s" % e) + sys.exit(2) + else: + self.log("Tests cancelled.") + sys.exit(1) + # Done with main user -- test user and tablespaces created. + self._maindb_connection.close() + self._switch_to_test_user(parameters) + return self.connection.settings_dict["NAME"] + + def _switch_to_test_user(self, parameters): + """ + Switch to the user that's used for creating the test database. + + Oracle doesn't have the concept of separate databases under the same + user, so a separate user is used; see _create_test_db(). The main user + is also needed for cleanup when testing is completed, so save its + credentials in the SAVED_USER/SAVED_PASSWORD key in the settings dict. + """ + real_settings = settings.DATABASES[self.connection.alias] + real_settings["SAVED_USER"] = self.connection.settings_dict[ + "SAVED_USER" + ] = self.connection.settings_dict["USER"] + real_settings["SAVED_PASSWORD"] = self.connection.settings_dict[ + "SAVED_PASSWORD" + ] = self.connection.settings_dict["PASSWORD"] + real_test_settings = real_settings["TEST"] + test_settings = self.connection.settings_dict["TEST"] + real_test_settings["USER"] = real_settings["USER"] = test_settings[ + "USER" + ] = self.connection.settings_dict["USER"] = parameters["user"] + real_settings["PASSWORD"] = self.connection.settings_dict[ + "PASSWORD" + ] = parameters["password"] + + def set_as_test_mirror(self, primary_settings_dict): + """ + Set this database up to be used in testing as a mirror of a primary + database whose settings are given. + """ + self.connection.settings_dict["USER"] = primary_settings_dict["USER"] + self.connection.settings_dict["PASSWORD"] = primary_settings_dict["PASSWORD"] + + def _handle_objects_preventing_db_destruction( + self, cursor, parameters, verbosity, autoclobber + ): + # There are objects in the test tablespace which prevent dropping it + # The easy fix is to drop the test user -- but are we allowed to do so? + self.log( + "There are objects in the old test database which prevent its destruction." + "\nIf they belong to the test user, deleting the user will allow the test " + "database to be recreated.\n" + "Otherwise, you will need to find and remove each of these objects, " + "or use a different tablespace.\n" + ) + if self._test_user_create(): + if not autoclobber: + confirm = input("Type 'yes' to delete user %s: " % parameters["user"]) + if autoclobber or confirm == "yes": + try: + if verbosity >= 1: + self.log("Destroying old test user...") + self._destroy_test_user(cursor, parameters, verbosity) + except Exception as e: + self.log("Got an error destroying the test user: %s" % e) + sys.exit(2) + try: + if verbosity >= 1: + self.log( + "Destroying old test database for alias '%s'..." + % self.connection.alias + ) + self._execute_test_db_destruction(cursor, parameters, verbosity) + except Exception as e: + self.log("Got an error destroying the test database: %s" % e) + sys.exit(2) + else: + self.log("Tests cancelled -- test database cannot be recreated.") + sys.exit(1) + else: + self.log( + "Django is configured to use pre-existing test user '%s'," + " and will not attempt to delete it." % parameters["user"] + ) + self.log("Tests cancelled -- test database cannot be recreated.") + sys.exit(1) + + def _destroy_test_db(self, test_database_name, verbosity=1): + """ + Destroy a test database, prompting the user for confirmation if the + database already exists. Return the name of the test database created. + """ + self.connection.settings_dict["USER"] = self.connection.settings_dict[ + "SAVED_USER" + ] + self.connection.settings_dict["PASSWORD"] = self.connection.settings_dict[ + "SAVED_PASSWORD" + ] + self.connection.close() + parameters = self._get_test_db_params() + with self._maindb_connection.cursor() as cursor: + if self._test_user_create(): + if verbosity >= 1: + self.log("Destroying test user...") + self._destroy_test_user(cursor, parameters, verbosity) + if self._test_database_create(): + if verbosity >= 1: + self.log("Destroying test database tables...") + self._execute_test_db_destruction(cursor, parameters, verbosity) + self._maindb_connection.close() + + def _execute_test_db_creation(self, cursor, parameters, verbosity, keepdb=False): + if verbosity >= 2: + self.log("_create_test_db(): dbname = %s" % parameters["user"]) + if self._test_database_oracle_managed_files(): + statements = [ + """ + CREATE TABLESPACE %(tblspace)s + DATAFILE SIZE %(size)s + AUTOEXTEND ON NEXT %(extsize)s MAXSIZE %(maxsize)s + """, + """ + CREATE TEMPORARY TABLESPACE %(tblspace_temp)s + TEMPFILE SIZE %(size_tmp)s + AUTOEXTEND ON NEXT %(extsize_tmp)s MAXSIZE %(maxsize_tmp)s + """, + ] + else: + statements = [ + """ + CREATE TABLESPACE %(tblspace)s + DATAFILE '%(datafile)s' SIZE %(size)s REUSE + AUTOEXTEND ON NEXT %(extsize)s MAXSIZE %(maxsize)s + """, + """ + CREATE TEMPORARY TABLESPACE %(tblspace_temp)s + TEMPFILE '%(datafile_tmp)s' SIZE %(size_tmp)s REUSE + AUTOEXTEND ON NEXT %(extsize_tmp)s MAXSIZE %(maxsize_tmp)s + """, + ] + # Ignore "tablespace already exists" error when keepdb is on. + acceptable_ora_err = "ORA-01543" if keepdb else None + self._execute_allow_fail_statements( + cursor, statements, parameters, verbosity, acceptable_ora_err + ) + + def _create_test_user(self, cursor, parameters, verbosity, keepdb=False): + if verbosity >= 2: + self.log("_create_test_user(): username = %s" % parameters["user"]) + statements = [ + """CREATE USER %(user)s + IDENTIFIED BY "%(password)s" + DEFAULT TABLESPACE %(tblspace)s + TEMPORARY TABLESPACE %(tblspace_temp)s + QUOTA UNLIMITED ON %(tblspace)s + """, + """GRANT CREATE SESSION, + CREATE TABLE, + CREATE SEQUENCE, + CREATE PROCEDURE, + CREATE TRIGGER + TO %(user)s""", + ] + # Ignore "user already exists" error when keepdb is on + acceptable_ora_err = "ORA-01920" if keepdb else None + success = self._execute_allow_fail_statements( + cursor, statements, parameters, verbosity, acceptable_ora_err + ) + # If the password was randomly generated, change the user accordingly. + if not success and self._test_settings_get("PASSWORD") is None: + set_password = 'ALTER USER %(user)s IDENTIFIED BY "%(password)s"' + self._execute_statements(cursor, [set_password], parameters, verbosity) + # Most test suites can be run without "create view" and + # "create materialized view" privileges. But some need it. + for object_type in ("VIEW", "MATERIALIZED VIEW"): + extra = "GRANT CREATE %(object_type)s TO %(user)s" + parameters["object_type"] = object_type + success = self._execute_allow_fail_statements( + cursor, [extra], parameters, verbosity, "ORA-01031" + ) + if not success and verbosity >= 2: + self.log( + "Failed to grant CREATE %s permission to test user. This may be ok." + % object_type + ) + + def _execute_test_db_destruction(self, cursor, parameters, verbosity): + if verbosity >= 2: + self.log("_execute_test_db_destruction(): dbname=%s" % parameters["user"]) + statements = [ + "DROP TABLESPACE %(tblspace)s " + "INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS", + "DROP TABLESPACE %(tblspace_temp)s " + "INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS", + ] + self._execute_statements(cursor, statements, parameters, verbosity) + + def _destroy_test_user(self, cursor, parameters, verbosity): + if verbosity >= 2: + self.log("_destroy_test_user(): user=%s" % parameters["user"]) + self.log("Be patient. This can take some time...") + statements = [ + "DROP USER %(user)s CASCADE", + ] + self._execute_statements(cursor, statements, parameters, verbosity) + + def _execute_statements( + self, cursor, statements, parameters, verbosity, allow_quiet_fail=False + ): + for template in statements: + stmt = template % parameters + if verbosity >= 2: + print(stmt) + try: + cursor.execute(stmt) + except Exception as err: + if (not allow_quiet_fail) or verbosity >= 2: + self.log("Failed (%s)" % (err)) + raise + + def _execute_allow_fail_statements( + self, cursor, statements, parameters, verbosity, acceptable_ora_err + ): + """ + Execute statements which are allowed to fail silently if the Oracle + error code given by `acceptable_ora_err` is raised. Return True if the + statements execute without an exception, or False otherwise. + """ + try: + # Statement can fail when acceptable_ora_err is not None + allow_quiet_fail = ( + acceptable_ora_err is not None and len(acceptable_ora_err) > 0 + ) + self._execute_statements( + cursor, + statements, + parameters, + verbosity, + allow_quiet_fail=allow_quiet_fail, + ) + return True + except DatabaseError as err: + description = str(err) + if acceptable_ora_err is None or acceptable_ora_err not in description: + raise + return False + + def _get_test_db_params(self): + return { + "dbname": self._test_database_name(), + "user": self._test_database_user(), + "password": self._test_database_passwd(), + "tblspace": self._test_database_tblspace(), + "tblspace_temp": self._test_database_tblspace_tmp(), + "datafile": self._test_database_tblspace_datafile(), + "datafile_tmp": self._test_database_tblspace_tmp_datafile(), + "maxsize": self._test_database_tblspace_maxsize(), + "maxsize_tmp": self._test_database_tblspace_tmp_maxsize(), + "size": self._test_database_tblspace_size(), + "size_tmp": self._test_database_tblspace_tmp_size(), + "extsize": self._test_database_tblspace_extsize(), + "extsize_tmp": self._test_database_tblspace_tmp_extsize(), + } + + def _test_settings_get(self, key, default=None, prefixed=None): + """ + Return a value from the test settings dict, or a given default, or a + prefixed entry from the main settings dict. + """ + settings_dict = self.connection.settings_dict + val = settings_dict["TEST"].get(key, default) + if val is None and prefixed: + val = TEST_DATABASE_PREFIX + settings_dict[prefixed] + return val + + def _test_database_name(self): + return self._test_settings_get("NAME", prefixed="NAME") + + def _test_database_create(self): + return self._test_settings_get("CREATE_DB", default=True) + + def _test_user_create(self): + return self._test_settings_get("CREATE_USER", default=True) + + def _test_database_user(self): + return self._test_settings_get("USER", prefixed="USER") + + def _test_database_passwd(self): + password = self._test_settings_get("PASSWORD") + if password is None and self._test_user_create(): + # Oracle passwords are limited to 30 chars and can't contain symbols. + password = get_random_string(30) + return password + + def _test_database_tblspace(self): + return self._test_settings_get("TBLSPACE", prefixed="USER") + + def _test_database_tblspace_tmp(self): + settings_dict = self.connection.settings_dict + return settings_dict["TEST"].get( + "TBLSPACE_TMP", TEST_DATABASE_PREFIX + settings_dict["USER"] + "_temp" + ) + + def _test_database_tblspace_datafile(self): + tblspace = "%s.dbf" % self._test_database_tblspace() + return self._test_settings_get("DATAFILE", default=tblspace) + + def _test_database_tblspace_tmp_datafile(self): + tblspace = "%s.dbf" % self._test_database_tblspace_tmp() + return self._test_settings_get("DATAFILE_TMP", default=tblspace) + + def _test_database_tblspace_maxsize(self): + return self._test_settings_get("DATAFILE_MAXSIZE", default="500M") + + def _test_database_tblspace_tmp_maxsize(self): + return self._test_settings_get("DATAFILE_TMP_MAXSIZE", default="500M") + + def _test_database_tblspace_size(self): + return self._test_settings_get("DATAFILE_SIZE", default="50M") + + def _test_database_tblspace_tmp_size(self): + return self._test_settings_get("DATAFILE_TMP_SIZE", default="50M") + + def _test_database_tblspace_extsize(self): + return self._test_settings_get("DATAFILE_EXTSIZE", default="25M") + + def _test_database_tblspace_tmp_extsize(self): + return self._test_settings_get("DATAFILE_TMP_EXTSIZE", default="25M") + + def _test_database_oracle_managed_files(self): + return self._test_settings_get("ORACLE_MANAGED_FILES", default=False) + + def _get_test_db_name(self): + """ + Return the 'production' DB name to get the test DB creation machinery + to work. This isn't a great deal in this case because DB names as + handled by Django don't have real counterparts in Oracle. + """ + return self.connection.settings_dict["NAME"] + + def test_db_signature(self): + settings_dict = self.connection.settings_dict + return ( + settings_dict["HOST"], + settings_dict["PORT"], + settings_dict["ENGINE"], + settings_dict["NAME"], + self._test_database_user(), + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/features.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/features.py new file mode 100644 index 0000000..8a02e09 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/features.py @@ -0,0 +1,168 @@ +from django.db import DatabaseError, InterfaceError +from django.db.backends.base.features import BaseDatabaseFeatures +from django.utils.functional import cached_property + + +class DatabaseFeatures(BaseDatabaseFeatures): + minimum_database_version = (19,) + # Oracle crashes with "ORA-00932: inconsistent datatypes: expected - got + # BLOB" when grouping by LOBs (#24096). + allows_group_by_lob = False + allows_group_by_select_index = False + interprets_empty_strings_as_nulls = True + has_select_for_update = True + has_select_for_update_nowait = True + has_select_for_update_skip_locked = True + has_select_for_update_of = True + select_for_update_of_column = True + can_return_columns_from_insert = True + supports_subqueries_in_group_by = False + ignores_unnecessary_order_by_in_subqueries = False + supports_transactions = True + supports_timezones = False + has_native_duration_field = True + can_defer_constraint_checks = True + supports_partially_nullable_unique_constraints = False + supports_deferrable_unique_constraints = True + truncates_names = True + supports_comments = True + supports_tablespaces = True + supports_sequence_reset = False + can_introspect_materialized_views = True + atomic_transactions = False + nulls_order_largest = True + requires_literal_defaults = True + supports_default_keyword_in_bulk_insert = False + closed_cursor_error_class = InterfaceError + bare_select_suffix = " FROM DUAL" + # Select for update with limit can be achieved on Oracle, but not with the + # current backend. + supports_select_for_update_with_limit = False + supports_temporal_subtraction = True + # Oracle doesn't ignore quoted identifiers case but the current backend + # does by uppercasing all identifiers. + ignores_table_name_case = True + supports_index_on_text_field = False + create_test_procedure_without_params_sql = """ + CREATE PROCEDURE "TEST_PROCEDURE" AS + V_I INTEGER; + BEGIN + V_I := 1; + END; + """ + create_test_procedure_with_int_param_sql = """ + CREATE PROCEDURE "TEST_PROCEDURE" (P_I INTEGER) AS + V_I INTEGER; + BEGIN + V_I := P_I; + END; + """ + create_test_table_with_composite_primary_key = """ + CREATE TABLE test_table_composite_pk ( + column_1 NUMBER(11) NOT NULL, + column_2 NUMBER(11) NOT NULL, + PRIMARY KEY (column_1, column_2) + ) + """ + supports_callproc_kwargs = True + supports_over_clause = True + supports_frame_range_fixed_distance = True + supports_ignore_conflicts = False + max_query_params = 2**16 - 1 + supports_partial_indexes = False + supports_stored_generated_columns = False + supports_virtual_generated_columns = True + can_rename_index = True + supports_slicing_ordering_in_compound = True + requires_compound_order_by_subquery = True + allows_multiple_constraints_on_same_fields = False + supports_boolean_expr_in_select_clause = False + supports_comparing_boolean_expr = False + supports_json_field_contains = False + supports_collation_on_textfield = False + test_now_utc_template = "CURRENT_TIMESTAMP AT TIME ZONE 'UTC'" + + django_test_skips = { + "Oracle doesn't support SHA224.": { + "db_functions.text.test_sha224.SHA224Tests.test_basic", + "db_functions.text.test_sha224.SHA224Tests.test_transform", + }, + "Oracle doesn't correctly calculate ISO 8601 week numbering before " + "1583 (the Gregorian calendar was introduced in 1582).": { + "db_functions.datetime.test_extract_trunc.DateFunctionTests." + "test_trunc_week_before_1000", + "db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests." + "test_trunc_week_before_1000", + }, + "Oracle extracts seconds including fractional seconds (#33517).": { + "db_functions.datetime.test_extract_trunc.DateFunctionTests." + "test_extract_second_func_no_fractional", + "db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests." + "test_extract_second_func_no_fractional", + }, + "Oracle doesn't support bitwise XOR.": { + "expressions.tests.ExpressionOperatorTests.test_lefthand_bitwise_xor", + "expressions.tests.ExpressionOperatorTests.test_lefthand_bitwise_xor_null", + "expressions.tests.ExpressionOperatorTests." + "test_lefthand_bitwise_xor_right_null", + }, + "Oracle requires ORDER BY in row_number, ANSI:SQL doesn't.": { + "expressions_window.tests.WindowFunctionTests.test_row_number_no_ordering", + }, + "Raises ORA-00600: internal error code.": { + "model_fields.test_jsonfield.TestQuerying.test_usage_in_subquery", + }, + "Oracle doesn't support changing collations on indexed columns (#33671).": { + "migrations.test_operations.OperationTests." + "test_alter_field_pk_fk_db_collation", + }, + "Oracle doesn't support comparing NCLOB to NUMBER.": { + "generic_relations_regress.tests.GenericRelationTests.test_textlink_filter", + }, + } + django_test_expected_failures = { + # A bug in Django/oracledb with respect to string handling (#23843). + "annotations.tests.NonAggregateAnnotationTestCase.test_custom_functions", + "annotations.tests.NonAggregateAnnotationTestCase." + "test_custom_functions_can_ref_other_functions", + } + insert_test_table_with_defaults = ( + "INSERT INTO {} VALUES (DEFAULT, DEFAULT, DEFAULT)" + ) + + @cached_property + def introspected_field_types(self): + return { + **super().introspected_field_types, + "GenericIPAddressField": "CharField", + "PositiveBigIntegerField": "BigIntegerField", + "PositiveIntegerField": "IntegerField", + "PositiveSmallIntegerField": "IntegerField", + "SmallIntegerField": "IntegerField", + "TimeField": "DateTimeField", + } + + @cached_property + def test_collations(self): + return { + "ci": "BINARY_CI", + "cs": "BINARY", + "non_default": "SWEDISH_CI", + "swedish_ci": "SWEDISH_CI", + "virtual": "SWEDISH_CI" if self.supports_collation_on_charfield else None, + } + + @cached_property + def supports_collation_on_charfield(self): + with self.connection.cursor() as cursor: + try: + cursor.execute("SELECT CAST('a' AS VARCHAR2(4001)) FROM dual") + except DatabaseError as e: + if e.args[0].code == 910: + return False + raise + return True + + @cached_property + def supports_primitives_in_json_field(self): + return self.connection.oracle_version >= (21,) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/functions.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/functions.py new file mode 100644 index 0000000..936cc9e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/functions.py @@ -0,0 +1,26 @@ +from django.db.models import DecimalField, DurationField, Func + + +class IntervalToSeconds(Func): + function = "" + template = """ + EXTRACT(day from %(expressions)s) * 86400 + + EXTRACT(hour from %(expressions)s) * 3600 + + EXTRACT(minute from %(expressions)s) * 60 + + EXTRACT(second from %(expressions)s) + """ + + def __init__(self, expression, *, output_field=None, **extra): + super().__init__( + expression, output_field=output_field or DecimalField(), **extra + ) + + +class SecondsToInterval(Func): + function = "NUMTODSINTERVAL" + template = "%(function)s(%(expressions)s, 'SECOND')" + + def __init__(self, expression, *, output_field=None, **extra): + super().__init__( + expression, output_field=output_field or DurationField(), **extra + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/introspection.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/introspection.py new file mode 100644 index 0000000..07c2d9b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/introspection.py @@ -0,0 +1,414 @@ +from collections import namedtuple + +from django.db import models +from django.db.backends.base.introspection import BaseDatabaseIntrospection +from django.db.backends.base.introspection import FieldInfo as BaseFieldInfo +from django.db.backends.base.introspection import TableInfo as BaseTableInfo +from django.db.backends.oracle.oracledb_any import oracledb + +FieldInfo = namedtuple( + "FieldInfo", BaseFieldInfo._fields + ("is_autofield", "is_json", "comment") +) +TableInfo = namedtuple("TableInfo", BaseTableInfo._fields + ("comment",)) + + +class DatabaseIntrospection(BaseDatabaseIntrospection): + cache_bust_counter = 1 + + # Maps type objects to Django Field types. + data_types_reverse = { + oracledb.DB_TYPE_DATE: "DateField", + oracledb.DB_TYPE_BINARY_DOUBLE: "FloatField", + oracledb.DB_TYPE_BLOB: "BinaryField", + oracledb.DB_TYPE_CHAR: "CharField", + oracledb.DB_TYPE_CLOB: "TextField", + oracledb.DB_TYPE_INTERVAL_DS: "DurationField", + oracledb.DB_TYPE_NCHAR: "CharField", + oracledb.DB_TYPE_NCLOB: "TextField", + oracledb.DB_TYPE_NVARCHAR: "CharField", + oracledb.DB_TYPE_NUMBER: "DecimalField", + oracledb.DB_TYPE_TIMESTAMP: "DateTimeField", + oracledb.DB_TYPE_VARCHAR: "CharField", + } + + def get_field_type(self, data_type, description): + if data_type == oracledb.NUMBER: + precision, scale = description[4:6] + if scale == 0: + if precision > 11: + return ( + "BigAutoField" + if description.is_autofield + else "BigIntegerField" + ) + elif 1 < precision < 6 and description.is_autofield: + return "SmallAutoField" + elif precision == 1: + return "BooleanField" + elif description.is_autofield: + return "AutoField" + else: + return "IntegerField" + elif scale == -127: + return "FloatField" + elif data_type == oracledb.NCLOB and description.is_json: + return "JSONField" + + return super().get_field_type(data_type, description) + + def get_table_list(self, cursor): + """Return a list of table and view names in the current database.""" + cursor.execute( + """ + SELECT + user_tables.table_name, + 't', + user_tab_comments.comments + FROM user_tables + LEFT OUTER JOIN + user_tab_comments + ON user_tab_comments.table_name = user_tables.table_name + WHERE + NOT EXISTS ( + SELECT 1 + FROM user_mviews + WHERE user_mviews.mview_name = user_tables.table_name + ) + UNION ALL + SELECT view_name, 'v', NULL FROM user_views + UNION ALL + SELECT mview_name, 'v', NULL FROM user_mviews + """ + ) + return [ + TableInfo(self.identifier_converter(row[0]), row[1], row[2]) + for row in cursor.fetchall() + ] + + def get_table_description(self, cursor, table_name): + """ + Return a description of the table with the DB-API cursor.description + interface. + """ + # A default collation for the given table/view/materialized view. + cursor.execute( + """ + SELECT user_tables.default_collation + FROM user_tables + WHERE + user_tables.table_name = UPPER(%s) AND + NOT EXISTS ( + SELECT 1 + FROM user_mviews + WHERE user_mviews.mview_name = user_tables.table_name + ) + UNION ALL + SELECT user_views.default_collation + FROM user_views + WHERE user_views.view_name = UPPER(%s) + UNION ALL + SELECT user_mviews.default_collation + FROM user_mviews + WHERE user_mviews.mview_name = UPPER(%s) + """, + [table_name, table_name, table_name], + ) + row = cursor.fetchone() + default_table_collation = row[0] if row else "" + # user_tab_columns gives data default for columns + cursor.execute( + """ + SELECT + user_tab_cols.column_name, + user_tab_cols.data_default, + CASE + WHEN user_tab_cols.collation = %s + THEN NULL + ELSE user_tab_cols.collation + END collation, + CASE + WHEN user_tab_cols.char_used IS NULL + THEN user_tab_cols.data_length + ELSE user_tab_cols.char_length + END as display_size, + CASE + WHEN user_tab_cols.identity_column = 'YES' THEN 1 + ELSE 0 + END as is_autofield, + CASE + WHEN EXISTS ( + SELECT 1 + FROM user_json_columns + WHERE + user_json_columns.table_name = user_tab_cols.table_name AND + user_json_columns.column_name = user_tab_cols.column_name + ) + THEN 1 + ELSE 0 + END as is_json, + user_col_comments.comments as col_comment + FROM user_tab_cols + LEFT OUTER JOIN + user_col_comments ON + user_col_comments.column_name = user_tab_cols.column_name AND + user_col_comments.table_name = user_tab_cols.table_name + WHERE user_tab_cols.table_name = UPPER(%s) + """, + [default_table_collation, table_name], + ) + field_map = { + column: ( + display_size, + default.rstrip() if default and default != "NULL" else None, + collation, + is_autofield, + is_json, + comment, + ) + for ( + column, + default, + collation, + display_size, + is_autofield, + is_json, + comment, + ) in cursor.fetchall() + } + self.cache_bust_counter += 1 + cursor.execute( + "SELECT * FROM {} WHERE ROWNUM < 2 AND {} > 0".format( + self.connection.ops.quote_name(table_name), self.cache_bust_counter + ) + ) + description = [] + for desc in cursor.description: + name = desc[0] + ( + display_size, + default, + collation, + is_autofield, + is_json, + comment, + ) = field_map[name] + name %= {} # oracledb, for some reason, doubles percent signs. + description.append( + FieldInfo( + self.identifier_converter(name), + desc[1], + display_size, + desc[3], + desc[4] or 0, + desc[5] or 0, + *desc[6:], + default, + collation, + is_autofield, + is_json, + comment, + ) + ) + return description + + def identifier_converter(self, name): + """Identifier comparison is case insensitive under Oracle.""" + return name.lower() + + def get_sequences(self, cursor, table_name, table_fields=()): + cursor.execute( + """ + SELECT + user_tab_identity_cols.sequence_name, + user_tab_identity_cols.column_name + FROM + user_tab_identity_cols, + user_constraints, + user_cons_columns cols + WHERE + user_constraints.constraint_name = cols.constraint_name + AND user_constraints.table_name = user_tab_identity_cols.table_name + AND cols.column_name = user_tab_identity_cols.column_name + AND user_constraints.constraint_type = 'P' + AND user_tab_identity_cols.table_name = UPPER(%s) + """, + [table_name], + ) + # Oracle allows only one identity column per table. + row = cursor.fetchone() + if row: + return [ + { + "name": self.identifier_converter(row[0]), + "table": self.identifier_converter(table_name), + "column": self.identifier_converter(row[1]), + } + ] + # To keep backward compatibility for AutoFields that aren't Oracle + # identity columns. + for f in table_fields: + if isinstance(f, models.AutoField): + return [{"table": table_name, "column": f.column}] + return [] + + def get_relations(self, cursor, table_name): + """ + Return a dictionary of {field_name: (field_name_other_table, other_table)} + representing all foreign keys in the given table. + """ + table_name = table_name.upper() + cursor.execute( + """ + SELECT ca.column_name, cb.table_name, cb.column_name + FROM user_constraints, USER_CONS_COLUMNS ca, USER_CONS_COLUMNS cb + WHERE user_constraints.table_name = %s AND + user_constraints.constraint_name = ca.constraint_name AND + user_constraints.r_constraint_name = cb.constraint_name AND + ca.position = cb.position""", + [table_name], + ) + + return { + self.identifier_converter(field_name): ( + self.identifier_converter(rel_field_name), + self.identifier_converter(rel_table_name), + ) + for field_name, rel_table_name, rel_field_name in cursor.fetchall() + } + + def get_primary_key_columns(self, cursor, table_name): + cursor.execute( + """ + SELECT + cols.column_name + FROM + user_constraints, + user_cons_columns cols + WHERE + user_constraints.constraint_name = cols.constraint_name AND + user_constraints.constraint_type = 'P' AND + user_constraints.table_name = UPPER(%s) + ORDER BY + cols.position + """, + [table_name], + ) + return [self.identifier_converter(row[0]) for row in cursor.fetchall()] + + def get_constraints(self, cursor, table_name): + """ + Retrieve any constraints or keys (unique, pk, fk, check, index) across + one or more columns. + """ + constraints = {} + # Loop over the constraints, getting PKs, uniques, and checks + cursor.execute( + """ + SELECT + user_constraints.constraint_name, + LISTAGG(LOWER(cols.column_name), ',') + WITHIN GROUP (ORDER BY cols.position), + CASE user_constraints.constraint_type + WHEN 'P' THEN 1 + ELSE 0 + END AS is_primary_key, + CASE + WHEN user_constraints.constraint_type IN ('P', 'U') THEN 1 + ELSE 0 + END AS is_unique, + CASE user_constraints.constraint_type + WHEN 'C' THEN 1 + ELSE 0 + END AS is_check_constraint + FROM + user_constraints + LEFT OUTER JOIN + user_cons_columns cols + ON user_constraints.constraint_name = cols.constraint_name + WHERE + user_constraints.constraint_type = ANY('P', 'U', 'C') + AND user_constraints.table_name = UPPER(%s) + GROUP BY user_constraints.constraint_name, user_constraints.constraint_type + """, + [table_name], + ) + for constraint, columns, pk, unique, check in cursor.fetchall(): + constraint = self.identifier_converter(constraint) + constraints[constraint] = { + "columns": columns.split(","), + "primary_key": pk, + "unique": unique, + "foreign_key": None, + "check": check, + "index": unique, # All uniques come with an index + } + # Foreign key constraints + cursor.execute( + """ + SELECT + cons.constraint_name, + LISTAGG(LOWER(cols.column_name), ',') + WITHIN GROUP (ORDER BY cols.position), + LOWER(rcols.table_name), + LOWER(rcols.column_name) + FROM + user_constraints cons + INNER JOIN + user_cons_columns rcols + ON rcols.constraint_name = cons.r_constraint_name AND rcols.position = 1 + LEFT OUTER JOIN + user_cons_columns cols + ON cons.constraint_name = cols.constraint_name + WHERE + cons.constraint_type = 'R' AND + cons.table_name = UPPER(%s) + GROUP BY cons.constraint_name, rcols.table_name, rcols.column_name + """, + [table_name], + ) + for constraint, columns, other_table, other_column in cursor.fetchall(): + constraint = self.identifier_converter(constraint) + constraints[constraint] = { + "primary_key": False, + "unique": False, + "foreign_key": (other_table, other_column), + "check": False, + "index": False, + "columns": columns.split(","), + } + # Now get indexes + cursor.execute( + """ + SELECT + ind.index_name, + LOWER(ind.index_type), + LOWER(ind.uniqueness), + LISTAGG(LOWER(cols.column_name), ',') + WITHIN GROUP (ORDER BY cols.column_position), + LISTAGG(cols.descend, ',') WITHIN GROUP (ORDER BY cols.column_position) + FROM + user_ind_columns cols, user_indexes ind + WHERE + cols.table_name = UPPER(%s) AND + NOT EXISTS ( + SELECT 1 + FROM user_constraints cons + WHERE ind.index_name = cons.index_name + ) AND cols.index_name = ind.index_name + GROUP BY ind.index_name, ind.index_type, ind.uniqueness + """, + [table_name], + ) + for constraint, type_, unique, columns, orders in cursor.fetchall(): + constraint = self.identifier_converter(constraint) + constraints[constraint] = { + "primary_key": False, + "unique": unique == "unique", + "foreign_key": None, + "check": False, + "index": True, + "type": "idx" if type_ == "normal" else type_, + "columns": columns.split(","), + "orders": orders.split(","), + } + return constraints diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/operations.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/operations.py new file mode 100644 index 0000000..11043a9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/operations.py @@ -0,0 +1,722 @@ +import datetime +import uuid +from functools import lru_cache + +from django.conf import settings +from django.db import DatabaseError, NotSupportedError +from django.db.backends.base.operations import BaseDatabaseOperations +from django.db.backends.utils import split_tzname_delta, strip_quotes, truncate_name +from django.db.models import AutoField, Exists, ExpressionWrapper, Lookup +from django.db.models.expressions import RawSQL +from django.db.models.sql.where import WhereNode +from django.utils import timezone +from django.utils.encoding import force_bytes, force_str +from django.utils.functional import cached_property +from django.utils.regex_helper import _lazy_re_compile + +from .base import Database +from .utils import BulkInsertMapper, InsertVar, Oracle_datetime + + +class DatabaseOperations(BaseDatabaseOperations): + # Oracle uses NUMBER(5), NUMBER(11), and NUMBER(19) for integer fields. + # SmallIntegerField uses NUMBER(11) instead of NUMBER(5), which is used by + # SmallAutoField, to preserve backward compatibility. + integer_field_ranges = { + "SmallIntegerField": (-99999999999, 99999999999), + "IntegerField": (-99999999999, 99999999999), + "BigIntegerField": (-9999999999999999999, 9999999999999999999), + "PositiveBigIntegerField": (0, 9999999999999999999), + "PositiveSmallIntegerField": (0, 99999999999), + "PositiveIntegerField": (0, 99999999999), + "SmallAutoField": (-99999, 99999), + "AutoField": (-99999999999, 99999999999), + "BigAutoField": (-9999999999999999999, 9999999999999999999), + } + set_operators = {**BaseDatabaseOperations.set_operators, "difference": "MINUS"} + + # TODO: colorize this SQL code with style.SQL_KEYWORD(), etc. + _sequence_reset_sql = """ +DECLARE + table_value integer; + seq_value integer; + seq_name user_tab_identity_cols.sequence_name%%TYPE; +BEGIN + BEGIN + SELECT sequence_name INTO seq_name FROM user_tab_identity_cols + WHERE table_name = '%(table_name)s' AND + column_name = '%(column_name)s'; + EXCEPTION WHEN NO_DATA_FOUND THEN + seq_name := '%(no_autofield_sequence_name)s'; + END; + + SELECT NVL(MAX(%(column)s), 0) INTO table_value FROM %(table)s; + SELECT NVL(last_number - cache_size, 0) INTO seq_value FROM user_sequences + WHERE sequence_name = seq_name; + WHILE table_value > seq_value LOOP + EXECUTE IMMEDIATE 'SELECT "'||seq_name||'".nextval FROM DUAL' + INTO seq_value; + END LOOP; +END; +/""" + + # Oracle doesn't support string without precision; use the max string size. + cast_char_field_without_max_length = "NVARCHAR2(2000)" + cast_data_types = { + "AutoField": "NUMBER(11)", + "BigAutoField": "NUMBER(19)", + "SmallAutoField": "NUMBER(5)", + "TextField": cast_char_field_without_max_length, + } + + def cache_key_culling_sql(self): + cache_key = self.quote_name("cache_key") + return ( + f"SELECT {cache_key} " + f"FROM %s " + f"ORDER BY {cache_key} OFFSET %%s ROWS FETCH FIRST 1 ROWS ONLY" + ) + + # EXTRACT format cannot be passed in parameters. + _extract_format_re = _lazy_re_compile(r"[A-Z_]+") + + def date_extract_sql(self, lookup_type, sql, params): + extract_sql = f"TO_CHAR({sql}, %s)" + extract_param = None + if lookup_type == "week_day": + # TO_CHAR(field, 'D') returns an integer from 1-7, where 1=Sunday. + extract_param = "D" + elif lookup_type == "iso_week_day": + extract_sql = f"TO_CHAR({sql} - 1, %s)" + extract_param = "D" + elif lookup_type == "week": + # IW = ISO week number + extract_param = "IW" + elif lookup_type == "quarter": + extract_param = "Q" + elif lookup_type == "iso_year": + extract_param = "IYYY" + else: + lookup_type = lookup_type.upper() + if not self._extract_format_re.fullmatch(lookup_type): + raise ValueError(f"Invalid loookup type: {lookup_type!r}") + # https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/EXTRACT-datetime.html + return f"EXTRACT({lookup_type} FROM {sql})", params + return extract_sql, (*params, extract_param) + + def date_trunc_sql(self, lookup_type, sql, params, tzname=None): + sql, params = self._convert_sql_to_tz(sql, params, tzname) + # https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/ROUND-and-TRUNC-Date-Functions.html + trunc_param = None + if lookup_type in ("year", "month"): + trunc_param = lookup_type.upper() + elif lookup_type == "quarter": + trunc_param = "Q" + elif lookup_type == "week": + trunc_param = "IW" + else: + return f"TRUNC({sql})", params + return f"TRUNC({sql}, %s)", (*params, trunc_param) + + # Oracle crashes with "ORA-03113: end-of-file on communication channel" + # if the time zone name is passed in parameter. Use interpolation instead. + # https://groups.google.com/forum/#!msg/django-developers/zwQju7hbG78/9l934yelwfsJ + # This regexp matches all time zone names from the zoneinfo database. + _tzname_re = _lazy_re_compile(r"^[\w/:+-]+$") + + def _prepare_tzname_delta(self, tzname): + tzname, sign, offset = split_tzname_delta(tzname) + return f"{sign}{offset}" if offset else tzname + + def _convert_sql_to_tz(self, sql, params, tzname): + if not (settings.USE_TZ and tzname): + return sql, params + if not self._tzname_re.match(tzname): + raise ValueError("Invalid time zone name: %s" % tzname) + # Convert from connection timezone to the local time, returning + # TIMESTAMP WITH TIME ZONE and cast it back to TIMESTAMP to strip the + # TIME ZONE details. + if self.connection.timezone_name != tzname: + from_timezone_name = self.connection.timezone_name + to_timezone_name = self._prepare_tzname_delta(tzname) + return ( + f"CAST((FROM_TZ({sql}, '{from_timezone_name}') AT TIME ZONE " + f"'{to_timezone_name}') AS TIMESTAMP)", + params, + ) + return sql, params + + def datetime_cast_date_sql(self, sql, params, tzname): + sql, params = self._convert_sql_to_tz(sql, params, tzname) + return f"TRUNC({sql})", params + + def datetime_cast_time_sql(self, sql, params, tzname): + # Since `TimeField` values are stored as TIMESTAMP change to the + # default date and convert the field to the specified timezone. + sql, params = self._convert_sql_to_tz(sql, params, tzname) + convert_datetime_sql = ( + f"TO_TIMESTAMP(CONCAT('1900-01-01 ', TO_CHAR({sql}, 'HH24:MI:SS.FF')), " + f"'YYYY-MM-DD HH24:MI:SS.FF')" + ) + return ( + f"CASE WHEN {sql} IS NOT NULL THEN {convert_datetime_sql} ELSE NULL END", + (*params, *params), + ) + + def datetime_extract_sql(self, lookup_type, sql, params, tzname): + sql, params = self._convert_sql_to_tz(sql, params, tzname) + return self.date_extract_sql(lookup_type, sql, params) + + def datetime_trunc_sql(self, lookup_type, sql, params, tzname): + sql, params = self._convert_sql_to_tz(sql, params, tzname) + # https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/ROUND-and-TRUNC-Date-Functions.html + trunc_param = None + if lookup_type in ("year", "month"): + trunc_param = lookup_type.upper() + elif lookup_type == "quarter": + trunc_param = "Q" + elif lookup_type == "week": + trunc_param = "IW" + elif lookup_type == "hour": + trunc_param = "HH24" + elif lookup_type == "minute": + trunc_param = "MI" + elif lookup_type == "day": + return f"TRUNC({sql})", params + else: + # Cast to DATE removes sub-second precision. + return f"CAST({sql} AS DATE)", params + return f"TRUNC({sql}, %s)", (*params, trunc_param) + + def time_trunc_sql(self, lookup_type, sql, params, tzname=None): + # The implementation is similar to `datetime_trunc_sql` as both + # `DateTimeField` and `TimeField` are stored as TIMESTAMP where + # the date part of the later is ignored. + sql, params = self._convert_sql_to_tz(sql, params, tzname) + trunc_param = None + if lookup_type == "hour": + trunc_param = "HH24" + elif lookup_type == "minute": + trunc_param = "MI" + elif lookup_type == "second": + # Cast to DATE removes sub-second precision. + return f"CAST({sql} AS DATE)", params + return f"TRUNC({sql}, %s)", (*params, trunc_param) + + def get_db_converters(self, expression): + converters = super().get_db_converters(expression) + internal_type = expression.output_field.get_internal_type() + if internal_type in ["JSONField", "TextField"]: + converters.append(self.convert_textfield_value) + elif internal_type == "BinaryField": + converters.append(self.convert_binaryfield_value) + elif internal_type == "BooleanField": + converters.append(self.convert_booleanfield_value) + elif internal_type == "DateTimeField": + if settings.USE_TZ: + converters.append(self.convert_datetimefield_value) + elif internal_type == "DateField": + converters.append(self.convert_datefield_value) + elif internal_type == "TimeField": + converters.append(self.convert_timefield_value) + elif internal_type == "UUIDField": + converters.append(self.convert_uuidfield_value) + # Oracle stores empty strings as null. If the field accepts the empty + # string, undo this to adhere to the Django convention of using + # the empty string instead of null. + if expression.output_field.empty_strings_allowed: + converters.append( + self.convert_empty_bytes + if internal_type == "BinaryField" + else self.convert_empty_string + ) + return converters + + def convert_textfield_value(self, value, expression, connection): + if isinstance(value, Database.LOB): + value = value.read() + return value + + def convert_binaryfield_value(self, value, expression, connection): + if isinstance(value, Database.LOB): + value = force_bytes(value.read()) + return value + + def convert_booleanfield_value(self, value, expression, connection): + if value in (0, 1): + value = bool(value) + return value + + # oracledb always returns datetime.datetime objects for + # DATE and TIMESTAMP columns, but Django wants to see a + # python datetime.date, .time, or .datetime. + + def convert_datetimefield_value(self, value, expression, connection): + if value is not None: + value = timezone.make_aware(value, self.connection.timezone) + return value + + def convert_datefield_value(self, value, expression, connection): + if isinstance(value, Database.Timestamp): + value = value.date() + return value + + def convert_timefield_value(self, value, expression, connection): + if isinstance(value, Database.Timestamp): + value = value.time() + return value + + def convert_uuidfield_value(self, value, expression, connection): + if value is not None: + value = uuid.UUID(value) + return value + + @staticmethod + def convert_empty_string(value, expression, connection): + return "" if value is None else value + + @staticmethod + def convert_empty_bytes(value, expression, connection): + return b"" if value is None else value + + def deferrable_sql(self): + return " DEFERRABLE INITIALLY DEFERRED" + + def fetch_returned_insert_columns(self, cursor, returning_params): + columns = [] + for param in returning_params: + value = param.get_value() + if value == []: + raise DatabaseError( + "The database did not return a new row id. Probably " + '"ORA-1403: no data found" was raised internally but was ' + "hidden by the Oracle OCI library (see " + "https://code.djangoproject.com/ticket/28859)." + ) + columns.append(value[0]) + return tuple(columns) + + def no_limit_value(self): + return None + + def limit_offset_sql(self, low_mark, high_mark): + fetch, offset = self._get_limit_offset_params(low_mark, high_mark) + return " ".join( + sql + for sql in ( + ("OFFSET %d ROWS" % offset) if offset else None, + ("FETCH FIRST %d ROWS ONLY" % fetch) if fetch else None, + ) + if sql + ) + + def last_executed_query(self, cursor, sql, params): + # https://python-oracledb.readthedocs.io/en/latest/api_manual/cursor.html#Cursor.statement + # The DB API definition does not define this attribute. + statement = cursor.statement + # Unlike Psycopg's `query` and MySQLdb`'s `_executed`, oracledb's + # `statement` doesn't contain the query parameters. Substitute + # parameters manually. + if params: + if isinstance(params, (tuple, list)): + params = { + f":arg{i}": param for i, param in enumerate(dict.fromkeys(params)) + } + elif isinstance(params, dict): + params = {f":{key}": val for (key, val) in params.items()} + for key in sorted(params, key=len, reverse=True): + statement = statement.replace( + key, force_str(params[key], errors="replace") + ) + return statement + + def last_insert_id(self, cursor, table_name, pk_name): + sq_name = self._get_sequence_name(cursor, strip_quotes(table_name), pk_name) + cursor.execute('"%s".currval' % sq_name) + return cursor.fetchone()[0] + + def lookup_cast(self, lookup_type, internal_type=None): + if lookup_type in ("iexact", "icontains", "istartswith", "iendswith"): + return "UPPER(%s)" + if ( + lookup_type != "isnull" and internal_type in ("BinaryField", "TextField") + ) or (lookup_type == "exact" and internal_type == "JSONField"): + return "DBMS_LOB.SUBSTR(%s)" + return "%s" + + def max_in_list_size(self): + return 1000 + + def max_name_length(self): + return 30 + + def pk_default_value(self): + return "NULL" + + def prep_for_iexact_query(self, x): + return x + + def process_clob(self, value): + if value is None: + return "" + return value.read() + + def quote_name(self, name): + # SQL92 requires delimited (quoted) names to be case-sensitive. When + # not quoted, Oracle has case-insensitive behavior for identifiers, but + # always defaults to uppercase. + # We simplify things by making Oracle identifiers always uppercase. + if not name.startswith('"') and not name.endswith('"'): + name = '"%s"' % truncate_name(name, self.max_name_length()) + # Oracle puts the query text into a (query % args) construct, so % signs + # in names need to be escaped. The '%%' will be collapsed back to '%' at + # that stage so we aren't really making the name longer here. + name = name.replace("%", "%%") + return name.upper() + + def regex_lookup(self, lookup_type): + if lookup_type == "regex": + match_option = "'c'" + else: + match_option = "'i'" + return "REGEXP_LIKE(%%s, %%s, %s)" % match_option + + def return_insert_columns(self, fields): + if not fields: + return "", () + field_names = [] + params = [] + for field in fields: + field_names.append( + "%s.%s" + % ( + self.quote_name(field.model._meta.db_table), + self.quote_name(field.column), + ) + ) + params.append(InsertVar(field)) + return "RETURNING %s INTO %s" % ( + ", ".join(field_names), + ", ".join(["%s"] * len(params)), + ), tuple(params) + + def __foreign_key_constraints(self, table_name, recursive): + with self.connection.cursor() as cursor: + if recursive: + cursor.execute( + """ + SELECT + user_tables.table_name, rcons.constraint_name + FROM + user_tables + JOIN + user_constraints cons + ON (user_tables.table_name = cons.table_name + AND cons.constraint_type = ANY('P', 'U')) + LEFT JOIN + user_constraints rcons + ON (user_tables.table_name = rcons.table_name + AND rcons.constraint_type = 'R') + START WITH user_tables.table_name = UPPER(%s) + CONNECT BY + NOCYCLE PRIOR cons.constraint_name = rcons.r_constraint_name + GROUP BY + user_tables.table_name, rcons.constraint_name + HAVING user_tables.table_name != UPPER(%s) + ORDER BY MAX(level) DESC + """, + (table_name, table_name), + ) + else: + cursor.execute( + """ + SELECT + cons.table_name, cons.constraint_name + FROM + user_constraints cons + WHERE + cons.constraint_type = 'R' + AND cons.table_name = UPPER(%s) + """, + (table_name,), + ) + return cursor.fetchall() + + @cached_property + def _foreign_key_constraints(self): + # 512 is large enough to fit the ~330 tables (as of this writing) in + # Django's test suite. + return lru_cache(maxsize=512)(self.__foreign_key_constraints) + + def sql_flush(self, style, tables, *, reset_sequences=False, allow_cascade=False): + if not tables: + return [] + + truncated_tables = {table.upper() for table in tables} + constraints = set() + # Oracle's TRUNCATE CASCADE only works with ON DELETE CASCADE foreign + # keys which Django doesn't define. Emulate the PostgreSQL behavior + # which truncates all dependent tables by manually retrieving all + # foreign key constraints and resolving dependencies. + for table in tables: + for foreign_table, constraint in self._foreign_key_constraints( + table, recursive=allow_cascade + ): + if allow_cascade: + truncated_tables.add(foreign_table) + constraints.add((foreign_table, constraint)) + sql = ( + [ + "%s %s %s %s %s %s %s %s;" + % ( + style.SQL_KEYWORD("ALTER"), + style.SQL_KEYWORD("TABLE"), + style.SQL_FIELD(self.quote_name(table)), + style.SQL_KEYWORD("DISABLE"), + style.SQL_KEYWORD("CONSTRAINT"), + style.SQL_FIELD(self.quote_name(constraint)), + style.SQL_KEYWORD("KEEP"), + style.SQL_KEYWORD("INDEX"), + ) + for table, constraint in constraints + ] + + [ + "%s %s %s;" + % ( + style.SQL_KEYWORD("TRUNCATE"), + style.SQL_KEYWORD("TABLE"), + style.SQL_FIELD(self.quote_name(table)), + ) + for table in truncated_tables + ] + + [ + "%s %s %s %s %s %s;" + % ( + style.SQL_KEYWORD("ALTER"), + style.SQL_KEYWORD("TABLE"), + style.SQL_FIELD(self.quote_name(table)), + style.SQL_KEYWORD("ENABLE"), + style.SQL_KEYWORD("CONSTRAINT"), + style.SQL_FIELD(self.quote_name(constraint)), + ) + for table, constraint in constraints + ] + ) + if reset_sequences: + sequences = [ + sequence + for sequence in self.connection.introspection.sequence_list() + if sequence["table"].upper() in truncated_tables + ] + # Since we've just deleted all the rows, running our sequence ALTER + # code will reset the sequence to 0. + sql.extend(self.sequence_reset_by_name_sql(style, sequences)) + return sql + + def sequence_reset_by_name_sql(self, style, sequences): + sql = [] + for sequence_info in sequences: + no_autofield_sequence_name = self._get_no_autofield_sequence_name( + sequence_info["table"] + ) + table = self.quote_name(sequence_info["table"]) + column = self.quote_name(sequence_info["column"] or "id") + query = self._sequence_reset_sql % { + "no_autofield_sequence_name": no_autofield_sequence_name, + "table": table, + "column": column, + "table_name": strip_quotes(table), + "column_name": strip_quotes(column), + } + sql.append(query) + return sql + + def sequence_reset_sql(self, style, model_list): + output = [] + query = self._sequence_reset_sql + for model in model_list: + for f in model._meta.local_fields: + if isinstance(f, AutoField): + no_autofield_sequence_name = self._get_no_autofield_sequence_name( + model._meta.db_table + ) + table = self.quote_name(model._meta.db_table) + column = self.quote_name(f.column) + output.append( + query + % { + "no_autofield_sequence_name": no_autofield_sequence_name, + "table": table, + "column": column, + "table_name": strip_quotes(table), + "column_name": strip_quotes(column), + } + ) + # Only one AutoField is allowed per model, so don't + # continue to loop + break + return output + + def start_transaction_sql(self): + return "" + + def tablespace_sql(self, tablespace, inline=False): + if inline: + return "USING INDEX TABLESPACE %s" % self.quote_name(tablespace) + else: + return "TABLESPACE %s" % self.quote_name(tablespace) + + def adapt_datefield_value(self, value): + """ + Transform a date value to an object compatible with what is expected + by the backend driver for date columns. + The default implementation transforms the date to text, but that is not + necessary for Oracle. + """ + return value + + def adapt_datetimefield_value(self, value): + """ + Transform a datetime value to an object compatible with what is expected + by the backend driver for datetime columns. + + If naive datetime is passed assumes that is in UTC. Normally Django + models.DateTimeField makes sure that if USE_TZ is True passed datetime + is timezone aware. + """ + + if value is None: + return None + + # Expression values are adapted by the database. + if hasattr(value, "resolve_expression"): + return value + + # oracledb doesn't support tz-aware datetimes + if timezone.is_aware(value): + if settings.USE_TZ: + value = timezone.make_naive(value, self.connection.timezone) + else: + raise ValueError( + "Oracle backend does not support timezone-aware datetimes when " + "USE_TZ is False." + ) + + return Oracle_datetime.from_datetime(value) + + def adapt_timefield_value(self, value): + if value is None: + return None + + # Expression values are adapted by the database. + if hasattr(value, "resolve_expression"): + return value + + if isinstance(value, str): + return datetime.datetime.strptime(value, "%H:%M:%S") + + # Oracle doesn't support tz-aware times + if timezone.is_aware(value): + raise ValueError("Oracle backend does not support timezone-aware times.") + + return Oracle_datetime( + 1900, 1, 1, value.hour, value.minute, value.second, value.microsecond + ) + + def adapt_decimalfield_value(self, value, max_digits=None, decimal_places=None): + return value + + def combine_expression(self, connector, sub_expressions): + lhs, rhs = sub_expressions + if connector == "%%": + return "MOD(%s)" % ",".join(sub_expressions) + elif connector == "&": + return "BITAND(%s)" % ",".join(sub_expressions) + elif connector == "|": + return "BITAND(-%(lhs)s-1,%(rhs)s)+%(lhs)s" % {"lhs": lhs, "rhs": rhs} + elif connector == "<<": + return "(%(lhs)s * POWER(2, %(rhs)s))" % {"lhs": lhs, "rhs": rhs} + elif connector == ">>": + return "FLOOR(%(lhs)s / POWER(2, %(rhs)s))" % {"lhs": lhs, "rhs": rhs} + elif connector == "^": + return "POWER(%s)" % ",".join(sub_expressions) + elif connector == "#": + raise NotSupportedError("Bitwise XOR is not supported in Oracle.") + return super().combine_expression(connector, sub_expressions) + + def _get_no_autofield_sequence_name(self, table): + """ + Manually created sequence name to keep backward compatibility for + AutoFields that aren't Oracle identity columns. + """ + name_length = self.max_name_length() - 3 + return "%s_SQ" % truncate_name(strip_quotes(table), name_length).upper() + + def _get_sequence_name(self, cursor, table, pk_name): + cursor.execute( + """ + SELECT sequence_name + FROM user_tab_identity_cols + WHERE table_name = UPPER(%s) + AND column_name = UPPER(%s)""", + [table, pk_name], + ) + row = cursor.fetchone() + return self._get_no_autofield_sequence_name(table) if row is None else row[0] + + def bulk_insert_sql(self, fields, placeholder_rows): + query = [] + for row in placeholder_rows: + select = [] + for i, placeholder in enumerate(row): + # A model without any fields has fields=[None]. + if fields[i]: + internal_type = getattr( + fields[i], "target_field", fields[i] + ).get_internal_type() + placeholder = ( + BulkInsertMapper.types.get(internal_type, "%s") % placeholder + ) + # Add columns aliases to the first select to avoid "ORA-00918: + # column ambiguously defined" when two or more columns in the + # first select have the same value. + if not query: + placeholder = "%s col_%s" % (placeholder, i) + select.append(placeholder) + query.append("SELECT %s FROM DUAL" % ", ".join(select)) + # Bulk insert to tables with Oracle identity columns causes Oracle to + # add sequence.nextval to it. Sequence.nextval cannot be used with the + # UNION operator. To prevent incorrect SQL, move UNION to a subquery. + return "SELECT * FROM (%s)" % " UNION ALL ".join(query) + + def subtract_temporals(self, internal_type, lhs, rhs): + if internal_type == "DateField": + lhs_sql, lhs_params = lhs + rhs_sql, rhs_params = rhs + params = (*lhs_params, *rhs_params) + return ( + "NUMTODSINTERVAL(TO_NUMBER(%s - %s), 'DAY')" % (lhs_sql, rhs_sql), + params, + ) + return super().subtract_temporals(internal_type, lhs, rhs) + + def bulk_batch_size(self, fields, objs): + """Oracle restricts the number of parameters in a query.""" + if fields: + return self.connection.features.max_query_params // len(fields) + return len(objs) + + def conditional_expression_supported_in_where_clause(self, expression): + """ + Oracle supports only EXISTS(...) or filters in the WHERE clause, others + must be compared with True. + """ + if isinstance(expression, (Exists, Lookup, WhereNode)): + return True + if isinstance(expression, ExpressionWrapper) and expression.conditional: + return self.conditional_expression_supported_in_where_clause( + expression.expression + ) + if isinstance(expression, RawSQL) and expression.conditional: + return True + return False diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/oracledb_any.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/oracledb_any.py new file mode 100644 index 0000000..65d9f1d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/oracledb_any.py @@ -0,0 +1,21 @@ +import warnings + +from django.core.exceptions import ImproperlyConfigured +from django.utils.deprecation import RemovedInDjango60Warning + +try: + import oracledb + + is_oracledb = True +except ImportError as e: + try: + import cx_Oracle as oracledb # NOQA + + warnings.warn( + "cx_Oracle is deprecated. Use oracledb instead.", + RemovedInDjango60Warning, + stacklevel=2, + ) + is_oracledb = False + except ImportError: + raise ImproperlyConfigured(f"Error loading oracledb module: {e}") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/schema.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/schema.py new file mode 100644 index 0000000..c8dd646 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/schema.py @@ -0,0 +1,252 @@ +import copy +import datetime +import re + +from django.db import DatabaseError +from django.db.backends.base.schema import ( + BaseDatabaseSchemaEditor, + _related_non_m2m_objects, +) +from django.utils.duration import duration_iso_string + + +class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): + sql_create_column = "ALTER TABLE %(table)s ADD %(column)s %(definition)s" + sql_alter_column_type = "MODIFY %(column)s %(type)s%(collation)s" + sql_alter_column_null = "MODIFY %(column)s NULL" + sql_alter_column_not_null = "MODIFY %(column)s NOT NULL" + sql_alter_column_default = "MODIFY %(column)s DEFAULT %(default)s" + sql_alter_column_no_default = "MODIFY %(column)s DEFAULT NULL" + sql_alter_column_no_default_null = sql_alter_column_no_default + + sql_delete_column = "ALTER TABLE %(table)s DROP COLUMN %(column)s" + sql_create_column_inline_fk = ( + "CONSTRAINT %(name)s REFERENCES %(to_table)s(%(to_column)s)%(deferrable)s" + ) + sql_delete_table = "DROP TABLE %(table)s CASCADE CONSTRAINTS" + sql_create_index = "CREATE INDEX %(name)s ON %(table)s (%(columns)s)%(extra)s" + + def quote_value(self, value): + if isinstance(value, (datetime.date, datetime.time, datetime.datetime)): + return "'%s'" % value + elif isinstance(value, datetime.timedelta): + return "'%s'" % duration_iso_string(value) + elif isinstance(value, str): + return "'%s'" % value.replace("'", "''") + elif isinstance(value, (bytes, bytearray, memoryview)): + return "'%s'" % value.hex() + elif isinstance(value, bool): + return "1" if value else "0" + else: + return str(value) + + def remove_field(self, model, field): + # If the column is an identity column, drop the identity before + # removing the field. + if self._is_identity_column(model._meta.db_table, field.column): + self._drop_identity(model._meta.db_table, field.column) + super().remove_field(model, field) + + def delete_model(self, model): + # Run superclass action + super().delete_model(model) + # Clean up manually created sequence. + self.execute( + """ + DECLARE + i INTEGER; + BEGIN + SELECT COUNT(1) INTO i FROM USER_SEQUENCES + WHERE SEQUENCE_NAME = '%(sq_name)s'; + IF i = 1 THEN + EXECUTE IMMEDIATE 'DROP SEQUENCE "%(sq_name)s"'; + END IF; + END; + /""" + % { + "sq_name": self.connection.ops._get_no_autofield_sequence_name( + model._meta.db_table + ) + } + ) + + def alter_field(self, model, old_field, new_field, strict=False): + try: + super().alter_field(model, old_field, new_field, strict) + except DatabaseError as e: + description = str(e) + # If we're changing type to an unsupported type we need a + # SQLite-ish workaround + if "ORA-22858" in description or "ORA-22859" in description: + self._alter_field_type_workaround(model, old_field, new_field) + # If an identity column is changing to a non-numeric type, drop the + # identity first. + elif "ORA-30675" in description: + self._drop_identity(model._meta.db_table, old_field.column) + self.alter_field(model, old_field, new_field, strict) + # If a primary key column is changing to an identity column, drop + # the primary key first. + elif "ORA-30673" in description and old_field.primary_key: + self._delete_primary_key(model, strict=True) + self._alter_field_type_workaround(model, old_field, new_field) + # If a collation is changing on a primary key, drop the primary key + # first. + elif "ORA-43923" in description and old_field.primary_key: + self._delete_primary_key(model, strict=True) + self.alter_field(model, old_field, new_field, strict) + # Restore a primary key, if needed. + if new_field.primary_key: + self.execute(self._create_primary_key_sql(model, new_field)) + else: + raise + + def _alter_field_type_workaround(self, model, old_field, new_field): + """ + Oracle refuses to change from some type to other type. + What we need to do instead is: + - Add a nullable version of the desired field with a temporary name. If + the new column is an auto field, then the temporary column can't be + nullable. + - Update the table to transfer values from old to new + - Drop old column + - Rename the new column and possibly drop the nullable property + """ + # Make a new field that's like the new one but with a temporary + # column name. + new_temp_field = copy.deepcopy(new_field) + new_temp_field.null = new_field.get_internal_type() not in ( + "AutoField", + "BigAutoField", + "SmallAutoField", + ) + new_temp_field.column = self._generate_temp_name(new_field.column) + # Add it + self.add_field(model, new_temp_field) + # Explicit data type conversion + # https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf + # /Data-Type-Comparison-Rules.html#GUID-D0C5A47E-6F93-4C2D-9E49-4F2B86B359DD + new_value = self.quote_name(old_field.column) + old_type = old_field.db_type(self.connection) + if re.match("^N?CLOB", old_type): + new_value = "TO_CHAR(%s)" % new_value + old_type = "VARCHAR2" + if re.match("^N?VARCHAR2", old_type): + new_internal_type = new_field.get_internal_type() + if new_internal_type == "DateField": + new_value = "TO_DATE(%s, 'YYYY-MM-DD')" % new_value + elif new_internal_type == "DateTimeField": + new_value = "TO_TIMESTAMP(%s, 'YYYY-MM-DD HH24:MI:SS.FF')" % new_value + elif new_internal_type == "TimeField": + # TimeField are stored as TIMESTAMP with a 1900-01-01 date part. + new_value = "CONCAT('1900-01-01 ', %s)" % new_value + new_value = "TO_TIMESTAMP(%s, 'YYYY-MM-DD HH24:MI:SS.FF')" % new_value + # Transfer values across + self.execute( + "UPDATE %s set %s=%s" + % ( + self.quote_name(model._meta.db_table), + self.quote_name(new_temp_field.column), + new_value, + ) + ) + # Drop the old field + self.remove_field(model, old_field) + # Rename and possibly make the new field NOT NULL + super().alter_field(model, new_temp_field, new_field) + # Recreate foreign key (if necessary) because the old field is not + # passed to the alter_field() and data types of new_temp_field and + # new_field always match. + new_type = new_field.db_type(self.connection) + if ( + (old_field.primary_key and new_field.primary_key) + or (old_field.unique and new_field.unique) + ) and old_type != new_type: + for _, rel in _related_non_m2m_objects(new_temp_field, new_field): + if rel.field.db_constraint: + self.execute( + self._create_fk_sql(rel.related_model, rel.field, "_fk") + ) + + def _alter_column_type_sql( + self, model, old_field, new_field, new_type, old_collation, new_collation + ): + auto_field_types = {"AutoField", "BigAutoField", "SmallAutoField"} + # Drop the identity if migrating away from AutoField. + if ( + old_field.get_internal_type() in auto_field_types + and new_field.get_internal_type() not in auto_field_types + and self._is_identity_column(model._meta.db_table, new_field.column) + ): + self._drop_identity(model._meta.db_table, new_field.column) + return super()._alter_column_type_sql( + model, old_field, new_field, new_type, old_collation, new_collation + ) + + def normalize_name(self, name): + """ + Get the properly shortened and uppercased identifier as returned by + quote_name() but without the quotes. + """ + nn = self.quote_name(name) + if nn[0] == '"' and nn[-1] == '"': + nn = nn[1:-1] + return nn + + def _generate_temp_name(self, for_name): + """Generate temporary names for workarounds that need temp columns.""" + suffix = hex(hash(for_name)).upper()[1:] + return self.normalize_name(for_name + "_" + suffix) + + def prepare_default(self, value): + # Replace % with %% as %-formatting is applied in + # FormatStylePlaceholderCursor._fix_for_params(). + return self.quote_value(value).replace("%", "%%") + + def _field_should_be_indexed(self, model, field): + create_index = super()._field_should_be_indexed(model, field) + db_type = field.db_type(self.connection) + if ( + db_type is not None + and db_type.lower() in self.connection._limited_data_types + ): + return False + return create_index + + def _is_identity_column(self, table_name, column_name): + with self.connection.cursor() as cursor: + cursor.execute( + """ + SELECT + CASE WHEN identity_column = 'YES' THEN 1 ELSE 0 END + FROM user_tab_cols + WHERE table_name = %s AND + column_name = %s + """, + [self.normalize_name(table_name), self.normalize_name(column_name)], + ) + row = cursor.fetchone() + return row[0] if row else False + + def _drop_identity(self, table_name, column_name): + self.execute( + "ALTER TABLE %(table)s MODIFY %(column)s DROP IDENTITY" + % { + "table": self.quote_name(table_name), + "column": self.quote_name(column_name), + } + ) + + def _get_default_collation(self, table_name): + with self.connection.cursor() as cursor: + cursor.execute( + """ + SELECT default_collation FROM user_tables WHERE table_name = %s + """, + [self.normalize_name(table_name)], + ) + return cursor.fetchone()[0] + + def _collate_sql(self, collation, old_collation=None, table_name=None): + if collation is None and old_collation is not None: + collation = self._get_default_collation(table_name) + return super()._collate_sql(collation, old_collation, table_name) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/utils.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/utils.py new file mode 100644 index 0000000..930b8e0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/utils.py @@ -0,0 +1,98 @@ +import datetime +import decimal + +from .base import Database + + +class InsertVar: + """ + A late-binding cursor variable that can be passed to Cursor.execute + as a parameter, in order to receive the id of the row created by an + insert statement. + """ + + types = { + "AutoField": int, + "BigAutoField": int, + "SmallAutoField": int, + "IntegerField": int, + "BigIntegerField": int, + "SmallIntegerField": int, + "PositiveBigIntegerField": int, + "PositiveSmallIntegerField": int, + "PositiveIntegerField": int, + "FloatField": Database.NATIVE_FLOAT, + "DateTimeField": Database.TIMESTAMP, + "DateField": Database.Date, + "DecimalField": decimal.Decimal, + } + + def __init__(self, field): + internal_type = getattr(field, "target_field", field).get_internal_type() + self.db_type = self.types.get(internal_type, str) + self.bound_param = None + + def bind_parameter(self, cursor): + self.bound_param = cursor.cursor.var(self.db_type) + return self.bound_param + + def get_value(self): + return self.bound_param.getvalue() + + +class Oracle_datetime(datetime.datetime): + """ + A datetime object, with an additional class attribute + to tell oracledb to save the microseconds too. + """ + + input_size = Database.TIMESTAMP + + @classmethod + def from_datetime(cls, dt): + return Oracle_datetime( + dt.year, + dt.month, + dt.day, + dt.hour, + dt.minute, + dt.second, + dt.microsecond, + ) + + +class BulkInsertMapper: + BLOB = "TO_BLOB(%s)" + DATE = "TO_DATE(%s)" + INTERVAL = "CAST(%s as INTERVAL DAY(9) TO SECOND(6))" + NCLOB = "TO_NCLOB(%s)" + NUMBER = "TO_NUMBER(%s)" + TIMESTAMP = "TO_TIMESTAMP(%s)" + + types = { + "AutoField": NUMBER, + "BigAutoField": NUMBER, + "BigIntegerField": NUMBER, + "BinaryField": BLOB, + "BooleanField": NUMBER, + "DateField": DATE, + "DateTimeField": TIMESTAMP, + "DecimalField": NUMBER, + "DurationField": INTERVAL, + "FloatField": NUMBER, + "IntegerField": NUMBER, + "PositiveBigIntegerField": NUMBER, + "PositiveIntegerField": NUMBER, + "PositiveSmallIntegerField": NUMBER, + "SmallAutoField": NUMBER, + "SmallIntegerField": NUMBER, + "TextField": NCLOB, + "TimeField": TIMESTAMP, + } + + +def dsn(settings_dict): + if settings_dict["PORT"]: + host = settings_dict["HOST"].strip() or "localhost" + return Database.makedsn(host, int(settings_dict["PORT"]), settings_dict["NAME"]) + return settings_dict["NAME"] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/validation.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/validation.py new file mode 100644 index 0000000..4035b12 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/oracle/validation.py @@ -0,0 +1,22 @@ +from django.core import checks +from django.db.backends.base.validation import BaseDatabaseValidation + + +class DatabaseValidation(BaseDatabaseValidation): + def check_field_type(self, field, field_type): + """Oracle doesn't support a database index on some data types.""" + errors = [] + if field.db_index and field_type.lower() in self.connection._limited_data_types: + errors.append( + checks.Warning( + "Oracle does not support a database index on %s columns." + % field_type, + hint=( + "An index won't be created. Silence this warning if " + "you don't care about it." + ), + obj=field, + id="fields.W162", + ) + ) + return errors diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/base.py new file mode 100644 index 0000000..d92ad58 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/base.py @@ -0,0 +1,487 @@ +""" +PostgreSQL database backend for Django. + +Requires psycopg2 >= 2.8.4 or psycopg >= 3.1.8 +""" + +import asyncio +import threading +import warnings +from contextlib import contextmanager + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured +from django.db import DatabaseError as WrappedDatabaseError +from django.db import connections +from django.db.backends.base.base import BaseDatabaseWrapper +from django.db.backends.utils import CursorDebugWrapper as BaseCursorDebugWrapper +from django.utils.asyncio import async_unsafe +from django.utils.functional import cached_property +from django.utils.safestring import SafeString +from django.utils.version import get_version_tuple + +try: + try: + import psycopg as Database + except ImportError: + import psycopg2 as Database +except ImportError: + raise ImproperlyConfigured("Error loading psycopg2 or psycopg module") + + +def psycopg_version(): + version = Database.__version__.split(" ", 1)[0] + return get_version_tuple(version) + + +if psycopg_version() < (2, 8, 4): + raise ImproperlyConfigured( + f"psycopg2 version 2.8.4 or newer is required; you have {Database.__version__}" + ) +if (3,) <= psycopg_version() < (3, 1, 8): + raise ImproperlyConfigured( + f"psycopg version 3.1.8 or newer is required; you have {Database.__version__}" + ) + + +from .psycopg_any import IsolationLevel, is_psycopg3 # NOQA isort:skip + +if is_psycopg3: + from psycopg import adapters, sql + from psycopg.pq import Format + + from .psycopg_any import get_adapters_template, register_tzloader + + TIMESTAMPTZ_OID = adapters.types["timestamptz"].oid + +else: + import psycopg2.extensions + import psycopg2.extras + + psycopg2.extensions.register_adapter(SafeString, psycopg2.extensions.QuotedString) + psycopg2.extras.register_uuid() + + # Register support for inet[] manually so we don't have to handle the Inet() + # object on load all the time. + INETARRAY_OID = 1041 + INETARRAY = psycopg2.extensions.new_array_type( + (INETARRAY_OID,), + "INETARRAY", + psycopg2.extensions.UNICODE, + ) + psycopg2.extensions.register_type(INETARRAY) + +# Some of these import psycopg, so import them after checking if it's installed. +from .client import DatabaseClient # NOQA isort:skip +from .creation import DatabaseCreation # NOQA isort:skip +from .features import DatabaseFeatures # NOQA isort:skip +from .introspection import DatabaseIntrospection # NOQA isort:skip +from .operations import DatabaseOperations # NOQA isort:skip +from .schema import DatabaseSchemaEditor # NOQA isort:skip + + +def _get_varchar_column(data): + if data["max_length"] is None: + return "varchar" + return "varchar(%(max_length)s)" % data + + +class DatabaseWrapper(BaseDatabaseWrapper): + vendor = "postgresql" + display_name = "PostgreSQL" + # This dictionary maps Field objects to their associated PostgreSQL column + # types, as strings. Column-type strings can contain format strings; they'll + # be interpolated against the values of Field.__dict__ before being output. + # If a column type is set to None, it won't be included in the output. + data_types = { + "AutoField": "integer", + "BigAutoField": "bigint", + "BinaryField": "bytea", + "BooleanField": "boolean", + "CharField": _get_varchar_column, + "DateField": "date", + "DateTimeField": "timestamp with time zone", + "DecimalField": "numeric(%(max_digits)s, %(decimal_places)s)", + "DurationField": "interval", + "FileField": "varchar(%(max_length)s)", + "FilePathField": "varchar(%(max_length)s)", + "FloatField": "double precision", + "IntegerField": "integer", + "BigIntegerField": "bigint", + "IPAddressField": "inet", + "GenericIPAddressField": "inet", + "JSONField": "jsonb", + "OneToOneField": "integer", + "PositiveBigIntegerField": "bigint", + "PositiveIntegerField": "integer", + "PositiveSmallIntegerField": "smallint", + "SlugField": "varchar(%(max_length)s)", + "SmallAutoField": "smallint", + "SmallIntegerField": "smallint", + "TextField": "text", + "TimeField": "time", + "UUIDField": "uuid", + } + data_type_check_constraints = { + "PositiveBigIntegerField": '"%(column)s" >= 0', + "PositiveIntegerField": '"%(column)s" >= 0', + "PositiveSmallIntegerField": '"%(column)s" >= 0', + } + data_types_suffix = { + "AutoField": "GENERATED BY DEFAULT AS IDENTITY", + "BigAutoField": "GENERATED BY DEFAULT AS IDENTITY", + "SmallAutoField": "GENERATED BY DEFAULT AS IDENTITY", + } + operators = { + "exact": "= %s", + "iexact": "= UPPER(%s)", + "contains": "LIKE %s", + "icontains": "LIKE UPPER(%s)", + "regex": "~ %s", + "iregex": "~* %s", + "gt": "> %s", + "gte": ">= %s", + "lt": "< %s", + "lte": "<= %s", + "startswith": "LIKE %s", + "endswith": "LIKE %s", + "istartswith": "LIKE UPPER(%s)", + "iendswith": "LIKE UPPER(%s)", + } + + # The patterns below are used to generate SQL pattern lookup clauses when + # the right-hand side of the lookup isn't a raw string (it might be an expression + # or the result of a bilateral transformation). + # In those cases, special characters for LIKE operators (e.g. \, *, _) should be + # escaped on database side. + # + # Note: we use str.format() here for readability as '%' is used as a wildcard for + # the LIKE operator. + pattern_esc = ( + r"REPLACE(REPLACE(REPLACE({}, E'\\', E'\\\\'), E'%%', E'\\%%'), E'_', E'\\_')" + ) + pattern_ops = { + "contains": "LIKE '%%' || {} || '%%'", + "icontains": "LIKE '%%' || UPPER({}) || '%%'", + "startswith": "LIKE {} || '%%'", + "istartswith": "LIKE UPPER({}) || '%%'", + "endswith": "LIKE '%%' || {}", + "iendswith": "LIKE '%%' || UPPER({})", + } + + Database = Database + SchemaEditorClass = DatabaseSchemaEditor + # Classes instantiated in __init__(). + client_class = DatabaseClient + creation_class = DatabaseCreation + features_class = DatabaseFeatures + introspection_class = DatabaseIntrospection + ops_class = DatabaseOperations + # PostgreSQL backend-specific attributes. + _named_cursor_idx = 0 + + def get_database_version(self): + """ + Return a tuple of the database's version. + E.g. for pg_version 120004, return (12, 4). + """ + return divmod(self.pg_version, 10000) + + def get_connection_params(self): + settings_dict = self.settings_dict + # None may be used to connect to the default 'postgres' db + if settings_dict["NAME"] == "" and not settings_dict.get("OPTIONS", {}).get( + "service" + ): + raise ImproperlyConfigured( + "settings.DATABASES is improperly configured. " + "Please supply the NAME or OPTIONS['service'] value." + ) + if len(settings_dict["NAME"] or "") > self.ops.max_name_length(): + raise ImproperlyConfigured( + "The database name '%s' (%d characters) is longer than " + "PostgreSQL's limit of %d characters. Supply a shorter NAME " + "in settings.DATABASES." + % ( + settings_dict["NAME"], + len(settings_dict["NAME"]), + self.ops.max_name_length(), + ) + ) + if settings_dict["NAME"]: + conn_params = { + "dbname": settings_dict["NAME"], + **settings_dict["OPTIONS"], + } + elif settings_dict["NAME"] is None: + # Connect to the default 'postgres' db. + settings_dict.get("OPTIONS", {}).pop("service", None) + conn_params = {"dbname": "postgres", **settings_dict["OPTIONS"]} + else: + conn_params = {**settings_dict["OPTIONS"]} + conn_params["client_encoding"] = "UTF8" + + conn_params.pop("assume_role", None) + conn_params.pop("isolation_level", None) + server_side_binding = conn_params.pop("server_side_binding", None) + conn_params.setdefault( + "cursor_factory", + ServerBindingCursor + if is_psycopg3 and server_side_binding is True + else Cursor, + ) + if settings_dict["USER"]: + conn_params["user"] = settings_dict["USER"] + if settings_dict["PASSWORD"]: + conn_params["password"] = settings_dict["PASSWORD"] + if settings_dict["HOST"]: + conn_params["host"] = settings_dict["HOST"] + if settings_dict["PORT"]: + conn_params["port"] = settings_dict["PORT"] + if is_psycopg3: + conn_params["context"] = get_adapters_template( + settings.USE_TZ, self.timezone + ) + # Disable prepared statements by default to keep connection poolers + # working. Can be reenabled via OPTIONS in the settings dict. + conn_params["prepare_threshold"] = conn_params.pop( + "prepare_threshold", None + ) + return conn_params + + @async_unsafe + def get_new_connection(self, conn_params): + # self.isolation_level must be set: + # - after connecting to the database in order to obtain the database's + # default when no value is explicitly specified in options. + # - before calling _set_autocommit() because if autocommit is on, that + # will set connection.isolation_level to ISOLATION_LEVEL_AUTOCOMMIT. + options = self.settings_dict["OPTIONS"] + set_isolation_level = False + try: + isolation_level_value = options["isolation_level"] + except KeyError: + self.isolation_level = IsolationLevel.READ_COMMITTED + else: + # Set the isolation level to the value from OPTIONS. + try: + self.isolation_level = IsolationLevel(isolation_level_value) + set_isolation_level = True + except ValueError: + raise ImproperlyConfigured( + f"Invalid transaction isolation level {isolation_level_value} " + f"specified. Use one of the psycopg.IsolationLevel values." + ) + connection = self.Database.connect(**conn_params) + if set_isolation_level: + connection.isolation_level = self.isolation_level + if not is_psycopg3: + # Register dummy loads() to avoid a round trip from psycopg2's + # decode to json.dumps() to json.loads(), when using a custom + # decoder in JSONField. + psycopg2.extras.register_default_jsonb( + conn_or_curs=connection, loads=lambda x: x + ) + return connection + + def ensure_timezone(self): + if self.connection is None: + return False + conn_timezone_name = self.connection.info.parameter_status("TimeZone") + timezone_name = self.timezone_name + if timezone_name and conn_timezone_name != timezone_name: + with self.connection.cursor() as cursor: + cursor.execute(self.ops.set_time_zone_sql(), [timezone_name]) + return True + return False + + def ensure_role(self): + if self.connection is None: + return False + if new_role := self.settings_dict.get("OPTIONS", {}).get("assume_role"): + with self.connection.cursor() as cursor: + sql = self.ops.compose_sql("SET ROLE %s", [new_role]) + cursor.execute(sql) + return True + return False + + def init_connection_state(self): + super().init_connection_state() + + # Commit after setting the time zone. + commit_tz = self.ensure_timezone() + # Set the role on the connection. This is useful if the credential used + # to login is not the same as the role that owns database resources. As + # can be the case when using temporary or ephemeral credentials. + commit_role = self.ensure_role() + + if (commit_role or commit_tz) and not self.get_autocommit(): + self.connection.commit() + + @async_unsafe + def create_cursor(self, name=None): + if name: + # In autocommit mode, the cursor will be used outside of a + # transaction, hence use a holdable cursor. + cursor = self.connection.cursor( + name, scrollable=False, withhold=self.connection.autocommit + ) + else: + cursor = self.connection.cursor() + + if is_psycopg3: + # Register the cursor timezone only if the connection disagrees, to + # avoid copying the adapter map. + tzloader = self.connection.adapters.get_loader(TIMESTAMPTZ_OID, Format.TEXT) + if self.timezone != tzloader.timezone: + register_tzloader(self.timezone, cursor) + else: + cursor.tzinfo_factory = self.tzinfo_factory if settings.USE_TZ else None + return cursor + + def tzinfo_factory(self, offset): + return self.timezone + + @async_unsafe + def chunked_cursor(self): + self._named_cursor_idx += 1 + # Get the current async task + # Note that right now this is behind @async_unsafe, so this is + # unreachable, but in future we'll start loosening this restriction. + # For now, it's here so that every use of "threading" is + # also async-compatible. + try: + current_task = asyncio.current_task() + except RuntimeError: + current_task = None + # Current task can be none even if the current_task call didn't error + if current_task: + task_ident = str(id(current_task)) + else: + task_ident = "sync" + # Use that and the thread ident to get a unique name + return self._cursor( + name="_django_curs_%d_%s_%d" + % ( + # Avoid reusing name in other threads / tasks + threading.current_thread().ident, + task_ident, + self._named_cursor_idx, + ) + ) + + def _set_autocommit(self, autocommit): + with self.wrap_database_errors: + self.connection.autocommit = autocommit + + def check_constraints(self, table_names=None): + """ + Check constraints by setting them to immediate. Return them to deferred + afterward. + """ + with self.cursor() as cursor: + cursor.execute("SET CONSTRAINTS ALL IMMEDIATE") + cursor.execute("SET CONSTRAINTS ALL DEFERRED") + + def is_usable(self): + try: + # Use a psycopg cursor directly, bypassing Django's utilities. + with self.connection.cursor() as cursor: + cursor.execute("SELECT 1") + except Database.Error: + return False + else: + return True + + @contextmanager + def _nodb_cursor(self): + cursor = None + try: + with super()._nodb_cursor() as cursor: + yield cursor + except (Database.DatabaseError, WrappedDatabaseError): + if cursor is not None: + raise + warnings.warn( + "Normally Django will use a connection to the 'postgres' database " + "to avoid running initialization queries against the production " + "database when it's not needed (for example, when running tests). " + "Django was unable to create a connection to the 'postgres' database " + "and will use the first PostgreSQL database instead.", + RuntimeWarning, + ) + for connection in connections.all(): + if ( + connection.vendor == "postgresql" + and connection.settings_dict["NAME"] != "postgres" + ): + conn = self.__class__( + { + **self.settings_dict, + "NAME": connection.settings_dict["NAME"], + }, + alias=self.alias, + ) + try: + with conn.cursor() as cursor: + yield cursor + finally: + conn.close() + break + else: + raise + + @cached_property + def pg_version(self): + with self.temporary_connection(): + return self.connection.info.server_version + + def make_debug_cursor(self, cursor): + return CursorDebugWrapper(cursor, self) + + +if is_psycopg3: + + class CursorMixin: + """ + A subclass of psycopg cursor implementing callproc. + """ + + def callproc(self, name, args=None): + if not isinstance(name, sql.Identifier): + name = sql.Identifier(name) + + qparts = [sql.SQL("SELECT * FROM "), name, sql.SQL("(")] + if args: + for item in args: + qparts.append(sql.Literal(item)) + qparts.append(sql.SQL(",")) + del qparts[-1] + + qparts.append(sql.SQL(")")) + stmt = sql.Composed(qparts) + self.execute(stmt) + return args + + class ServerBindingCursor(CursorMixin, Database.Cursor): + pass + + class Cursor(CursorMixin, Database.ClientCursor): + pass + + class CursorDebugWrapper(BaseCursorDebugWrapper): + def copy(self, statement): + with self.debug_sql(statement): + return self.cursor.copy(statement) + +else: + Cursor = psycopg2.extensions.cursor + + class CursorDebugWrapper(BaseCursorDebugWrapper): + def copy_expert(self, sql, file, *args): + with self.debug_sql(sql): + return self.cursor.copy_expert(sql, file, *args) + + def copy_to(self, file, table, *args, **kwargs): + with self.debug_sql(sql="COPY %s TO STDOUT" % table): + return self.cursor.copy_to(file, table, *args, **kwargs) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/client.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/client.py new file mode 100644 index 0000000..3b5ddaf --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/client.py @@ -0,0 +1,64 @@ +import signal + +from django.db.backends.base.client import BaseDatabaseClient + + +class DatabaseClient(BaseDatabaseClient): + executable_name = "psql" + + @classmethod + def settings_to_cmd_args_env(cls, settings_dict, parameters): + args = [cls.executable_name] + options = settings_dict.get("OPTIONS", {}) + + host = settings_dict.get("HOST") + port = settings_dict.get("PORT") + dbname = settings_dict.get("NAME") + user = settings_dict.get("USER") + passwd = settings_dict.get("PASSWORD") + passfile = options.get("passfile") + service = options.get("service") + sslmode = options.get("sslmode") + sslrootcert = options.get("sslrootcert") + sslcert = options.get("sslcert") + sslkey = options.get("sslkey") + + if not dbname and not service: + # Connect to the default 'postgres' db. + dbname = "postgres" + if user: + args += ["-U", user] + if host: + args += ["-h", host] + if port: + args += ["-p", str(port)] + args.extend(parameters) + if dbname: + args += [dbname] + + env = {} + if passwd: + env["PGPASSWORD"] = str(passwd) + if service: + env["PGSERVICE"] = str(service) + if sslmode: + env["PGSSLMODE"] = str(sslmode) + if sslrootcert: + env["PGSSLROOTCERT"] = str(sslrootcert) + if sslcert: + env["PGSSLCERT"] = str(sslcert) + if sslkey: + env["PGSSLKEY"] = str(sslkey) + if passfile: + env["PGPASSFILE"] = str(passfile) + return args, (env or None) + + def runshell(self, parameters): + sigint_handler = signal.getsignal(signal.SIGINT) + try: + # Allow SIGINT to pass to psql to abort queries. + signal.signal(signal.SIGINT, signal.SIG_IGN) + super().runshell(parameters) + finally: + # Restore the original SIGINT handler. + signal.signal(signal.SIGINT, sigint_handler) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/creation.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/creation.py new file mode 100644 index 0000000..9b562ce --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/creation.py @@ -0,0 +1,86 @@ +import sys + +from django.core.exceptions import ImproperlyConfigured +from django.db.backends.base.creation import BaseDatabaseCreation +from django.db.backends.postgresql.psycopg_any import errors +from django.db.backends.utils import strip_quotes + + +class DatabaseCreation(BaseDatabaseCreation): + def _quote_name(self, name): + return self.connection.ops.quote_name(name) + + def _get_database_create_suffix(self, encoding=None, template=None): + suffix = "" + if encoding: + suffix += " ENCODING '{}'".format(encoding) + if template: + suffix += " TEMPLATE {}".format(self._quote_name(template)) + return suffix and "WITH" + suffix + + def sql_table_creation_suffix(self): + test_settings = self.connection.settings_dict["TEST"] + if test_settings.get("COLLATION") is not None: + raise ImproperlyConfigured( + "PostgreSQL does not support collation setting at database " + "creation time." + ) + return self._get_database_create_suffix( + encoding=test_settings["CHARSET"], + template=test_settings.get("TEMPLATE"), + ) + + def _database_exists(self, cursor, database_name): + cursor.execute( + "SELECT 1 FROM pg_catalog.pg_database WHERE datname = %s", + [strip_quotes(database_name)], + ) + return cursor.fetchone() is not None + + def _execute_create_test_db(self, cursor, parameters, keepdb=False): + try: + if keepdb and self._database_exists(cursor, parameters["dbname"]): + # If the database should be kept and it already exists, don't + # try to create a new one. + return + super()._execute_create_test_db(cursor, parameters, keepdb) + except Exception as e: + if not isinstance(e.__cause__, errors.DuplicateDatabase): + # All errors except "database already exists" cancel tests. + self.log("Got an error creating the test database: %s" % e) + sys.exit(2) + elif not keepdb: + # If the database should be kept, ignore "database already + # exists". + raise + + def _clone_test_db(self, suffix, verbosity, keepdb=False): + # CREATE DATABASE ... WITH TEMPLATE ... requires closing connections + # to the template database. + self.connection.close() + + source_database_name = self.connection.settings_dict["NAME"] + target_database_name = self.get_test_db_clone_settings(suffix)["NAME"] + test_db_params = { + "dbname": self._quote_name(target_database_name), + "suffix": self._get_database_create_suffix(template=source_database_name), + } + with self._nodb_cursor() as cursor: + try: + self._execute_create_test_db(cursor, test_db_params, keepdb) + except Exception: + try: + if verbosity >= 1: + self.log( + "Destroying old test database for alias %s..." + % ( + self._get_database_display_str( + verbosity, target_database_name + ), + ) + ) + cursor.execute("DROP DATABASE %(dbname)s" % test_db_params) + self._execute_create_test_db(cursor, test_db_params, keepdb) + except Exception as e: + self.log("Got an error cloning the test database: %s" % e) + sys.exit(2) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/features.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/features.py new file mode 100644 index 0000000..941ebb9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/features.py @@ -0,0 +1,148 @@ +import operator + +from django.db import DataError, InterfaceError +from django.db.backends.base.features import BaseDatabaseFeatures +from django.db.backends.postgresql.psycopg_any import is_psycopg3 +from django.utils.functional import cached_property + + +class DatabaseFeatures(BaseDatabaseFeatures): + minimum_database_version = (12,) + allows_group_by_selected_pks = True + can_return_columns_from_insert = True + can_return_rows_from_bulk_insert = True + has_real_datatype = True + has_native_uuid_field = True + has_native_duration_field = True + has_native_json_field = True + can_defer_constraint_checks = True + has_select_for_update = True + has_select_for_update_nowait = True + has_select_for_update_of = True + has_select_for_update_skip_locked = True + has_select_for_no_key_update = True + can_release_savepoints = True + supports_comments = True + supports_tablespaces = True + supports_transactions = True + can_introspect_materialized_views = True + can_distinct_on_fields = True + can_rollback_ddl = True + schema_editor_uses_clientside_param_binding = True + supports_combined_alters = True + nulls_order_largest = True + closed_cursor_error_class = InterfaceError + greatest_least_ignores_nulls = True + can_clone_databases = True + supports_temporal_subtraction = True + supports_slicing_ordering_in_compound = True + create_test_procedure_without_params_sql = """ + CREATE FUNCTION test_procedure () RETURNS void AS $$ + DECLARE + V_I INTEGER; + BEGIN + V_I := 1; + END; + $$ LANGUAGE plpgsql;""" + create_test_procedure_with_int_param_sql = """ + CREATE FUNCTION test_procedure (P_I INTEGER) RETURNS void AS $$ + DECLARE + V_I INTEGER; + BEGIN + V_I := P_I; + END; + $$ LANGUAGE plpgsql;""" + create_test_table_with_composite_primary_key = """ + CREATE TABLE test_table_composite_pk ( + column_1 INTEGER NOT NULL, + column_2 INTEGER NOT NULL, + PRIMARY KEY(column_1, column_2) + ) + """ + requires_casted_case_in_updates = True + supports_over_clause = True + only_supports_unbounded_with_preceding_and_following = True + supports_aggregate_filter_clause = True + supported_explain_formats = {"JSON", "TEXT", "XML", "YAML"} + supports_deferrable_unique_constraints = True + has_json_operators = True + json_key_contains_list_matching_requires_list = True + supports_update_conflicts = True + supports_update_conflicts_with_target = True + supports_covering_indexes = True + supports_stored_generated_columns = True + supports_virtual_generated_columns = False + can_rename_index = True + test_collations = { + "deterministic": "C", + "non_default": "sv-x-icu", + "swedish_ci": "sv-x-icu", + "virtual": "sv-x-icu", + } + test_now_utc_template = "STATEMENT_TIMESTAMP() AT TIME ZONE 'UTC'" + insert_test_table_with_defaults = "INSERT INTO {} DEFAULT VALUES" + + django_test_skips = { + "opclasses are PostgreSQL only.": { + "indexes.tests.SchemaIndexesNotPostgreSQLTests." + "test_create_index_ignores_opclasses", + }, + "PostgreSQL requires casting to text.": { + "lookup.tests.LookupTests.test_textfield_exact_null", + }, + } + + @cached_property + def django_test_expected_failures(self): + expected_failures = set() + if self.uses_server_side_binding: + expected_failures.update( + { + # Parameters passed to expressions in SELECT and GROUP BY + # clauses are not recognized as the same values when using + # server-side binding cursors (#34255). + "aggregation.tests.AggregateTestCase." + "test_group_by_nested_expression_with_params", + } + ) + return expected_failures + + @cached_property + def uses_server_side_binding(self): + options = self.connection.settings_dict["OPTIONS"] + return is_psycopg3 and options.get("server_side_binding") is True + + @cached_property + def prohibits_null_characters_in_text_exception(self): + if is_psycopg3: + return DataError, "PostgreSQL text fields cannot contain NUL (0x00) bytes" + else: + return ValueError, "A string literal cannot contain NUL (0x00) characters." + + @cached_property + def introspected_field_types(self): + return { + **super().introspected_field_types, + "PositiveBigIntegerField": "BigIntegerField", + "PositiveIntegerField": "IntegerField", + "PositiveSmallIntegerField": "SmallIntegerField", + } + + @cached_property + def is_postgresql_13(self): + return self.connection.pg_version >= 130000 + + @cached_property + def is_postgresql_14(self): + return self.connection.pg_version >= 140000 + + @cached_property + def is_postgresql_15(self): + return self.connection.pg_version >= 150000 + + has_bit_xor = property(operator.attrgetter("is_postgresql_14")) + supports_covering_spgist_indexes = property(operator.attrgetter("is_postgresql_14")) + supports_unlimited_charfield = True + supports_nulls_distinct_unique_constraints = property( + operator.attrgetter("is_postgresql_15") + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/introspection.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/introspection.py new file mode 100644 index 0000000..69bc871 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/introspection.py @@ -0,0 +1,299 @@ +from collections import namedtuple + +from django.db.backends.base.introspection import BaseDatabaseIntrospection +from django.db.backends.base.introspection import FieldInfo as BaseFieldInfo +from django.db.backends.base.introspection import TableInfo as BaseTableInfo +from django.db.models import Index + +FieldInfo = namedtuple("FieldInfo", BaseFieldInfo._fields + ("is_autofield", "comment")) +TableInfo = namedtuple("TableInfo", BaseTableInfo._fields + ("comment",)) + + +class DatabaseIntrospection(BaseDatabaseIntrospection): + # Maps type codes to Django Field types. + data_types_reverse = { + 16: "BooleanField", + 17: "BinaryField", + 20: "BigIntegerField", + 21: "SmallIntegerField", + 23: "IntegerField", + 25: "TextField", + 700: "FloatField", + 701: "FloatField", + 869: "GenericIPAddressField", + 1042: "CharField", # blank-padded + 1043: "CharField", + 1082: "DateField", + 1083: "TimeField", + 1114: "DateTimeField", + 1184: "DateTimeField", + 1186: "DurationField", + 1266: "TimeField", + 1700: "DecimalField", + 2950: "UUIDField", + 3802: "JSONField", + } + # A hook for subclasses. + index_default_access_method = "btree" + + ignored_tables = [] + + def get_field_type(self, data_type, description): + field_type = super().get_field_type(data_type, description) + if description.is_autofield or ( + # Required for pre-Django 4.1 serial columns. + description.default + and "nextval" in description.default + ): + if field_type == "IntegerField": + return "AutoField" + elif field_type == "BigIntegerField": + return "BigAutoField" + elif field_type == "SmallIntegerField": + return "SmallAutoField" + return field_type + + def get_table_list(self, cursor): + """Return a list of table and view names in the current database.""" + cursor.execute( + """ + SELECT + c.relname, + CASE + WHEN c.relispartition THEN 'p' + WHEN c.relkind IN ('m', 'v') THEN 'v' + ELSE 't' + END, + obj_description(c.oid, 'pg_class') + FROM pg_catalog.pg_class c + LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace + WHERE c.relkind IN ('f', 'm', 'p', 'r', 'v') + AND n.nspname NOT IN ('pg_catalog', 'pg_toast') + AND pg_catalog.pg_table_is_visible(c.oid) + """ + ) + return [ + TableInfo(*row) + for row in cursor.fetchall() + if row[0] not in self.ignored_tables + ] + + def get_table_description(self, cursor, table_name): + """ + Return a description of the table with the DB-API cursor.description + interface. + """ + # Query the pg_catalog tables as cursor.description does not reliably + # return the nullable property and information_schema.columns does not + # contain details of materialized views. + cursor.execute( + """ + SELECT + a.attname AS column_name, + NOT (a.attnotnull OR (t.typtype = 'd' AND t.typnotnull)) AS is_nullable, + pg_get_expr(ad.adbin, ad.adrelid) AS column_default, + CASE WHEN collname = 'default' THEN NULL ELSE collname END AS collation, + a.attidentity != '' AS is_autofield, + col_description(a.attrelid, a.attnum) AS column_comment + FROM pg_attribute a + LEFT JOIN pg_attrdef ad ON a.attrelid = ad.adrelid AND a.attnum = ad.adnum + LEFT JOIN pg_collation co ON a.attcollation = co.oid + JOIN pg_type t ON a.atttypid = t.oid + JOIN pg_class c ON a.attrelid = c.oid + JOIN pg_namespace n ON c.relnamespace = n.oid + WHERE c.relkind IN ('f', 'm', 'p', 'r', 'v') + AND c.relname = %s + AND n.nspname NOT IN ('pg_catalog', 'pg_toast') + AND pg_catalog.pg_table_is_visible(c.oid) + """, + [table_name], + ) + field_map = {line[0]: line[1:] for line in cursor.fetchall()} + cursor.execute( + "SELECT * FROM %s LIMIT 1" % self.connection.ops.quote_name(table_name) + ) + return [ + FieldInfo( + line.name, + line.type_code, + # display_size is always None on psycopg2. + line.internal_size if line.display_size is None else line.display_size, + line.internal_size, + line.precision, + line.scale, + *field_map[line.name], + ) + for line in cursor.description + ] + + def get_sequences(self, cursor, table_name, table_fields=()): + cursor.execute( + """ + SELECT + s.relname AS sequence_name, + a.attname AS colname + FROM + pg_class s + JOIN pg_depend d ON d.objid = s.oid + AND d.classid = 'pg_class'::regclass + AND d.refclassid = 'pg_class'::regclass + JOIN pg_attribute a ON d.refobjid = a.attrelid + AND d.refobjsubid = a.attnum + JOIN pg_class tbl ON tbl.oid = d.refobjid + AND tbl.relname = %s + AND pg_catalog.pg_table_is_visible(tbl.oid) + WHERE + s.relkind = 'S'; + """, + [table_name], + ) + return [ + {"name": row[0], "table": table_name, "column": row[1]} + for row in cursor.fetchall() + ] + + def get_relations(self, cursor, table_name): + """ + Return a dictionary of {field_name: (field_name_other_table, other_table)} + representing all foreign keys in the given table. + """ + cursor.execute( + """ + SELECT a1.attname, c2.relname, a2.attname + FROM pg_constraint con + LEFT JOIN pg_class c1 ON con.conrelid = c1.oid + LEFT JOIN pg_class c2 ON con.confrelid = c2.oid + LEFT JOIN + pg_attribute a1 ON c1.oid = a1.attrelid AND a1.attnum = con.conkey[1] + LEFT JOIN + pg_attribute a2 ON c2.oid = a2.attrelid AND a2.attnum = con.confkey[1] + WHERE + c1.relname = %s AND + con.contype = 'f' AND + c1.relnamespace = c2.relnamespace AND + pg_catalog.pg_table_is_visible(c1.oid) + """, + [table_name], + ) + return {row[0]: (row[2], row[1]) for row in cursor.fetchall()} + + def get_constraints(self, cursor, table_name): + """ + Retrieve any constraints or keys (unique, pk, fk, check, index) across + one or more columns. Also retrieve the definition of expression-based + indexes. + """ + constraints = {} + # Loop over the key table, collecting things as constraints. The column + # array must return column names in the same order in which they were + # created. + cursor.execute( + """ + SELECT + c.conname, + array( + SELECT attname + FROM unnest(c.conkey) WITH ORDINALITY cols(colid, arridx) + JOIN pg_attribute AS ca ON cols.colid = ca.attnum + WHERE ca.attrelid = c.conrelid + ORDER BY cols.arridx + ), + c.contype, + (SELECT fkc.relname || '.' || fka.attname + FROM pg_attribute AS fka + JOIN pg_class AS fkc ON fka.attrelid = fkc.oid + WHERE fka.attrelid = c.confrelid AND fka.attnum = c.confkey[1]), + cl.reloptions + FROM pg_constraint AS c + JOIN pg_class AS cl ON c.conrelid = cl.oid + WHERE cl.relname = %s AND pg_catalog.pg_table_is_visible(cl.oid) + """, + [table_name], + ) + for constraint, columns, kind, used_cols, options in cursor.fetchall(): + constraints[constraint] = { + "columns": columns, + "primary_key": kind == "p", + "unique": kind in ["p", "u"], + "foreign_key": tuple(used_cols.split(".", 1)) if kind == "f" else None, + "check": kind == "c", + "index": False, + "definition": None, + "options": options, + } + # Now get indexes + cursor.execute( + """ + SELECT + indexname, + array_agg(attname ORDER BY arridx), + indisunique, + indisprimary, + array_agg(ordering ORDER BY arridx), + amname, + exprdef, + s2.attoptions + FROM ( + SELECT + c2.relname as indexname, idx.*, attr.attname, am.amname, + CASE + WHEN idx.indexprs IS NOT NULL THEN + pg_get_indexdef(idx.indexrelid) + END AS exprdef, + CASE am.amname + WHEN %s THEN + CASE (option & 1) + WHEN 1 THEN 'DESC' ELSE 'ASC' + END + END as ordering, + c2.reloptions as attoptions + FROM ( + SELECT * + FROM + pg_index i, + unnest(i.indkey, i.indoption) + WITH ORDINALITY koi(key, option, arridx) + ) idx + LEFT JOIN pg_class c ON idx.indrelid = c.oid + LEFT JOIN pg_class c2 ON idx.indexrelid = c2.oid + LEFT JOIN pg_am am ON c2.relam = am.oid + LEFT JOIN + pg_attribute attr ON attr.attrelid = c.oid AND attr.attnum = idx.key + WHERE c.relname = %s AND pg_catalog.pg_table_is_visible(c.oid) + ) s2 + GROUP BY indexname, indisunique, indisprimary, amname, exprdef, attoptions; + """, + [self.index_default_access_method, table_name], + ) + for ( + index, + columns, + unique, + primary, + orders, + type_, + definition, + options, + ) in cursor.fetchall(): + if index not in constraints: + basic_index = ( + type_ == self.index_default_access_method + and + # '_btree' references + # django.contrib.postgres.indexes.BTreeIndex.suffix. + not index.endswith("_btree") + and options is None + ) + constraints[index] = { + "columns": columns if columns != [None] else [], + "orders": orders if orders != [None] else [], + "primary_key": primary, + "unique": unique, + "foreign_key": None, + "check": False, + "index": True, + "type": Index.suffix if basic_index else type_, + "definition": definition, + "options": options, + } + return constraints diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/operations.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/operations.py new file mode 100644 index 0000000..6eefb6a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/operations.py @@ -0,0 +1,415 @@ +import json +from functools import lru_cache, partial + +from django.conf import settings +from django.db.backends.base.operations import BaseDatabaseOperations +from django.db.backends.postgresql.psycopg_any import ( + Inet, + Jsonb, + errors, + is_psycopg3, + mogrify, +) +from django.db.backends.utils import split_tzname_delta +from django.db.models.constants import OnConflict +from django.db.models.functions import Cast +from django.utils.regex_helper import _lazy_re_compile + + +@lru_cache +def get_json_dumps(encoder): + if encoder is None: + return json.dumps + return partial(json.dumps, cls=encoder) + + +class DatabaseOperations(BaseDatabaseOperations): + cast_char_field_without_max_length = "varchar" + explain_prefix = "EXPLAIN" + explain_options = frozenset( + [ + "ANALYZE", + "BUFFERS", + "COSTS", + "SETTINGS", + "SUMMARY", + "TIMING", + "VERBOSE", + "WAL", + ] + ) + cast_data_types = { + "AutoField": "integer", + "BigAutoField": "bigint", + "SmallAutoField": "smallint", + } + + if is_psycopg3: + from psycopg.types import numeric + + integerfield_type_map = { + "SmallIntegerField": numeric.Int2, + "IntegerField": numeric.Int4, + "BigIntegerField": numeric.Int8, + "PositiveSmallIntegerField": numeric.Int2, + "PositiveIntegerField": numeric.Int4, + "PositiveBigIntegerField": numeric.Int8, + } + + def unification_cast_sql(self, output_field): + internal_type = output_field.get_internal_type() + if internal_type in ( + "GenericIPAddressField", + "IPAddressField", + "TimeField", + "UUIDField", + ): + # PostgreSQL will resolve a union as type 'text' if input types are + # 'unknown'. + # https://www.postgresql.org/docs/current/typeconv-union-case.html + # These fields cannot be implicitly cast back in the default + # PostgreSQL configuration so we need to explicitly cast them. + # We must also remove components of the type within brackets: + # varchar(255) -> varchar. + return ( + "CAST(%%s AS %s)" % output_field.db_type(self.connection).split("(")[0] + ) + return "%s" + + # EXTRACT format cannot be passed in parameters. + _extract_format_re = _lazy_re_compile(r"[A-Z_]+") + + def date_extract_sql(self, lookup_type, sql, params): + # https://www.postgresql.org/docs/current/functions-datetime.html#FUNCTIONS-DATETIME-EXTRACT + if lookup_type == "week_day": + # For consistency across backends, we return Sunday=1, Saturday=7. + return f"EXTRACT(DOW FROM {sql}) + 1", params + elif lookup_type == "iso_week_day": + return f"EXTRACT(ISODOW FROM {sql})", params + elif lookup_type == "iso_year": + return f"EXTRACT(ISOYEAR FROM {sql})", params + + lookup_type = lookup_type.upper() + if not self._extract_format_re.fullmatch(lookup_type): + raise ValueError(f"Invalid lookup type: {lookup_type!r}") + return f"EXTRACT({lookup_type} FROM {sql})", params + + def date_trunc_sql(self, lookup_type, sql, params, tzname=None): + sql, params = self._convert_sql_to_tz(sql, params, tzname) + # https://www.postgresql.org/docs/current/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC + return f"DATE_TRUNC(%s, {sql})", (lookup_type, *params) + + def _prepare_tzname_delta(self, tzname): + tzname, sign, offset = split_tzname_delta(tzname) + if offset: + sign = "-" if sign == "+" else "+" + return f"{tzname}{sign}{offset}" + return tzname + + def _convert_sql_to_tz(self, sql, params, tzname): + if tzname and settings.USE_TZ: + tzname_param = self._prepare_tzname_delta(tzname) + return f"{sql} AT TIME ZONE %s", (*params, tzname_param) + return sql, params + + def datetime_cast_date_sql(self, sql, params, tzname): + sql, params = self._convert_sql_to_tz(sql, params, tzname) + return f"({sql})::date", params + + def datetime_cast_time_sql(self, sql, params, tzname): + sql, params = self._convert_sql_to_tz(sql, params, tzname) + return f"({sql})::time", params + + def datetime_extract_sql(self, lookup_type, sql, params, tzname): + sql, params = self._convert_sql_to_tz(sql, params, tzname) + if lookup_type == "second": + # Truncate fractional seconds. + return f"EXTRACT(SECOND FROM DATE_TRUNC(%s, {sql}))", ("second", *params) + return self.date_extract_sql(lookup_type, sql, params) + + def datetime_trunc_sql(self, lookup_type, sql, params, tzname): + sql, params = self._convert_sql_to_tz(sql, params, tzname) + # https://www.postgresql.org/docs/current/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC + return f"DATE_TRUNC(%s, {sql})", (lookup_type, *params) + + def time_extract_sql(self, lookup_type, sql, params): + if lookup_type == "second": + # Truncate fractional seconds. + return f"EXTRACT(SECOND FROM DATE_TRUNC(%s, {sql}))", ("second", *params) + return self.date_extract_sql(lookup_type, sql, params) + + def time_trunc_sql(self, lookup_type, sql, params, tzname=None): + sql, params = self._convert_sql_to_tz(sql, params, tzname) + return f"DATE_TRUNC(%s, {sql})::time", (lookup_type, *params) + + def deferrable_sql(self): + return " DEFERRABLE INITIALLY DEFERRED" + + def fetch_returned_insert_rows(self, cursor): + """ + Given a cursor object that has just performed an INSERT...RETURNING + statement into a table, return the tuple of returned data. + """ + return cursor.fetchall() + + def lookup_cast(self, lookup_type, internal_type=None): + lookup = "%s" + # Cast text lookups to text to allow things like filter(x__contains=4) + if lookup_type in ( + "iexact", + "contains", + "icontains", + "startswith", + "istartswith", + "endswith", + "iendswith", + "regex", + "iregex", + ): + if internal_type in ("IPAddressField", "GenericIPAddressField"): + lookup = "HOST(%s)" + # RemovedInDjango51Warning. + elif internal_type in ("CICharField", "CIEmailField", "CITextField"): + lookup = "%s::citext" + else: + lookup = "%s::text" + + # Use UPPER(x) for case-insensitive lookups; it's faster. + if lookup_type in ("iexact", "icontains", "istartswith", "iendswith"): + lookup = "UPPER(%s)" % lookup + + return lookup + + def no_limit_value(self): + return None + + def prepare_sql_script(self, sql): + return [sql] + + def quote_name(self, name): + if name.startswith('"') and name.endswith('"'): + return name # Quoting once is enough. + return '"%s"' % name + + def compose_sql(self, sql, params): + return mogrify(sql, params, self.connection) + + def set_time_zone_sql(self): + return "SELECT set_config('TimeZone', %s, false)" + + def sql_flush(self, style, tables, *, reset_sequences=False, allow_cascade=False): + if not tables: + return [] + + # Perform a single SQL 'TRUNCATE x, y, z...;' statement. It allows us + # to truncate tables referenced by a foreign key in any other table. + sql_parts = [ + style.SQL_KEYWORD("TRUNCATE"), + ", ".join(style.SQL_FIELD(self.quote_name(table)) for table in tables), + ] + if reset_sequences: + sql_parts.append(style.SQL_KEYWORD("RESTART IDENTITY")) + if allow_cascade: + sql_parts.append(style.SQL_KEYWORD("CASCADE")) + return ["%s;" % " ".join(sql_parts)] + + def sequence_reset_by_name_sql(self, style, sequences): + # 'ALTER SEQUENCE sequence_name RESTART WITH 1;'... style SQL statements + # to reset sequence indices + sql = [] + for sequence_info in sequences: + table_name = sequence_info["table"] + # 'id' will be the case if it's an m2m using an autogenerated + # intermediate table (see BaseDatabaseIntrospection.sequence_list). + column_name = sequence_info["column"] or "id" + sql.append( + "%s setval(pg_get_serial_sequence('%s','%s'), 1, false);" + % ( + style.SQL_KEYWORD("SELECT"), + style.SQL_TABLE(self.quote_name(table_name)), + style.SQL_FIELD(column_name), + ) + ) + return sql + + def tablespace_sql(self, tablespace, inline=False): + if inline: + return "USING INDEX TABLESPACE %s" % self.quote_name(tablespace) + else: + return "TABLESPACE %s" % self.quote_name(tablespace) + + def sequence_reset_sql(self, style, model_list): + from django.db import models + + output = [] + qn = self.quote_name + for model in model_list: + # Use `coalesce` to set the sequence for each model to the max pk + # value if there are records, or 1 if there are none. Set the + # `is_called` property (the third argument to `setval`) to true if + # there are records (as the max pk value is already in use), + # otherwise set it to false. Use pg_get_serial_sequence to get the + # underlying sequence name from the table name and column name. + + for f in model._meta.local_fields: + if isinstance(f, models.AutoField): + output.append( + "%s setval(pg_get_serial_sequence('%s','%s'), " + "coalesce(max(%s), 1), max(%s) %s null) %s %s;" + % ( + style.SQL_KEYWORD("SELECT"), + style.SQL_TABLE(qn(model._meta.db_table)), + style.SQL_FIELD(f.column), + style.SQL_FIELD(qn(f.column)), + style.SQL_FIELD(qn(f.column)), + style.SQL_KEYWORD("IS NOT"), + style.SQL_KEYWORD("FROM"), + style.SQL_TABLE(qn(model._meta.db_table)), + ) + ) + # Only one AutoField is allowed per model, so don't bother + # continuing. + break + return output + + def prep_for_iexact_query(self, x): + return x + + def max_name_length(self): + """ + Return the maximum length of an identifier. + + The maximum length of an identifier is 63 by default, but can be + changed by recompiling PostgreSQL after editing the NAMEDATALEN + macro in src/include/pg_config_manual.h. + + This implementation returns 63, but can be overridden by a custom + database backend that inherits most of its behavior from this one. + """ + return 63 + + def distinct_sql(self, fields, params): + if fields: + params = [param for param_list in params for param in param_list] + return (["DISTINCT ON (%s)" % ", ".join(fields)], params) + else: + return ["DISTINCT"], [] + + if is_psycopg3: + + def last_executed_query(self, cursor, sql, params): + try: + return self.compose_sql(sql, params) + except errors.DataError: + return None + + else: + + def last_executed_query(self, cursor, sql, params): + # https://www.psycopg.org/docs/cursor.html#cursor.query + # The query attribute is a Psycopg extension to the DB API 2.0. + if cursor.query is not None: + return cursor.query.decode() + return None + + def return_insert_columns(self, fields): + if not fields: + return "", () + columns = [ + "%s.%s" + % ( + self.quote_name(field.model._meta.db_table), + self.quote_name(field.column), + ) + for field in fields + ] + return "RETURNING %s" % ", ".join(columns), () + + def bulk_insert_sql(self, fields, placeholder_rows): + placeholder_rows_sql = (", ".join(row) for row in placeholder_rows) + values_sql = ", ".join("(%s)" % sql for sql in placeholder_rows_sql) + return "VALUES " + values_sql + + if is_psycopg3: + + def adapt_integerfield_value(self, value, internal_type): + if value is None or hasattr(value, "resolve_expression"): + return value + return self.integerfield_type_map[internal_type](value) + + def adapt_datefield_value(self, value): + return value + + def adapt_datetimefield_value(self, value): + return value + + def adapt_timefield_value(self, value): + return value + + def adapt_decimalfield_value(self, value, max_digits=None, decimal_places=None): + return value + + def adapt_ipaddressfield_value(self, value): + if value: + return Inet(value) + return None + + def adapt_json_value(self, value, encoder): + return Jsonb(value, dumps=get_json_dumps(encoder)) + + def subtract_temporals(self, internal_type, lhs, rhs): + if internal_type == "DateField": + lhs_sql, lhs_params = lhs + rhs_sql, rhs_params = rhs + params = (*lhs_params, *rhs_params) + return "(interval '1 day' * (%s - %s))" % (lhs_sql, rhs_sql), params + return super().subtract_temporals(internal_type, lhs, rhs) + + def explain_query_prefix(self, format=None, **options): + extra = {} + # Normalize options. + if options: + options = { + name.upper(): "true" if value else "false" + for name, value in options.items() + } + for valid_option in self.explain_options: + value = options.pop(valid_option, None) + if value is not None: + extra[valid_option] = value + prefix = super().explain_query_prefix(format, **options) + if format: + extra["FORMAT"] = format + if extra: + prefix += " (%s)" % ", ".join("%s %s" % i for i in extra.items()) + return prefix + + def on_conflict_suffix_sql(self, fields, on_conflict, update_fields, unique_fields): + if on_conflict == OnConflict.IGNORE: + return "ON CONFLICT DO NOTHING" + if on_conflict == OnConflict.UPDATE: + return "ON CONFLICT(%s) DO UPDATE SET %s" % ( + ", ".join(map(self.quote_name, unique_fields)), + ", ".join( + [ + f"{field} = EXCLUDED.{field}" + for field in map(self.quote_name, update_fields) + ] + ), + ) + return super().on_conflict_suffix_sql( + fields, + on_conflict, + update_fields, + unique_fields, + ) + + def prepare_join_on_clause(self, lhs_table, lhs_field, rhs_table, rhs_field): + lhs_expr, rhs_expr = super().prepare_join_on_clause( + lhs_table, lhs_field, rhs_table, rhs_field + ) + + if lhs_field.db_type(self.connection) != rhs_field.db_type(self.connection): + rhs_expr = Cast(rhs_expr, lhs_field) + + return lhs_expr, rhs_expr diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/psycopg_any.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/psycopg_any.py new file mode 100644 index 0000000..1fe6b15 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/psycopg_any.py @@ -0,0 +1,103 @@ +import ipaddress +from functools import lru_cache + +try: + from psycopg import ClientCursor, IsolationLevel, adapt, adapters, errors, sql + from psycopg.postgres import types + from psycopg.types.datetime import TimestamptzLoader + from psycopg.types.json import Jsonb + from psycopg.types.range import Range, RangeDumper + from psycopg.types.string import TextLoader + + Inet = ipaddress.ip_address + + DateRange = DateTimeRange = DateTimeTZRange = NumericRange = Range + RANGE_TYPES = (Range,) + + TSRANGE_OID = types["tsrange"].oid + TSTZRANGE_OID = types["tstzrange"].oid + + def mogrify(sql, params, connection): + with connection.cursor() as cursor: + return ClientCursor(cursor.connection).mogrify(sql, params) + + # Adapters. + class BaseTzLoader(TimestamptzLoader): + """ + Load a PostgreSQL timestamptz using the a specific timezone. + The timezone can be None too, in which case it will be chopped. + """ + + timezone = None + + def load(self, data): + res = super().load(data) + return res.replace(tzinfo=self.timezone) + + def register_tzloader(tz, context): + class SpecificTzLoader(BaseTzLoader): + timezone = tz + + context.adapters.register_loader("timestamptz", SpecificTzLoader) + + class DjangoRangeDumper(RangeDumper): + """A Range dumper customized for Django.""" + + def upgrade(self, obj, format): + # Dump ranges containing naive datetimes as tstzrange, because + # Django doesn't use tz-aware ones. + dumper = super().upgrade(obj, format) + if dumper is not self and dumper.oid == TSRANGE_OID: + dumper.oid = TSTZRANGE_OID + return dumper + + @lru_cache + def get_adapters_template(use_tz, timezone): + # Create at adapters map extending the base one. + ctx = adapt.AdaptersMap(adapters) + # Register a no-op dumper to avoid a round trip from psycopg version 3 + # decode to json.dumps() to json.loads(), when using a custom decoder + # in JSONField. + ctx.register_loader("jsonb", TextLoader) + # Don't convert automatically from PostgreSQL network types to Python + # ipaddress. + ctx.register_loader("inet", TextLoader) + ctx.register_loader("cidr", TextLoader) + ctx.register_dumper(Range, DjangoRangeDumper) + # Register a timestamptz loader configured on self.timezone. + # This, however, can be overridden by create_cursor. + register_tzloader(timezone, ctx) + return ctx + + is_psycopg3 = True + +except ImportError: + from enum import IntEnum + + from psycopg2 import errors, extensions, sql # NOQA + from psycopg2.extras import DateRange, DateTimeRange, DateTimeTZRange, Inet # NOQA + from psycopg2.extras import Json as Jsonb # NOQA + from psycopg2.extras import NumericRange, Range # NOQA + + RANGE_TYPES = (DateRange, DateTimeRange, DateTimeTZRange, NumericRange) + + class IsolationLevel(IntEnum): + READ_UNCOMMITTED = extensions.ISOLATION_LEVEL_READ_UNCOMMITTED + READ_COMMITTED = extensions.ISOLATION_LEVEL_READ_COMMITTED + REPEATABLE_READ = extensions.ISOLATION_LEVEL_REPEATABLE_READ + SERIALIZABLE = extensions.ISOLATION_LEVEL_SERIALIZABLE + + def _quote(value, connection=None): + adapted = extensions.adapt(value) + if hasattr(adapted, "encoding"): + adapted.encoding = "utf8" + # getquoted() returns a quoted bytestring of the adapted value. + return adapted.getquoted().decode() + + sql.quote = _quote + + def mogrify(sql, params, connection): + with connection.cursor() as cursor: + return cursor.mogrify(sql, params).decode() + + is_psycopg3 = False diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/schema.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/schema.py new file mode 100644 index 0000000..5dc93a2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/postgresql/schema.py @@ -0,0 +1,388 @@ +from django.db.backends.base.schema import BaseDatabaseSchemaEditor +from django.db.backends.ddl_references import IndexColumns +from django.db.backends.postgresql.psycopg_any import sql +from django.db.backends.utils import strip_quotes + + +class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): + # Setting all constraints to IMMEDIATE to allow changing data in the same + # transaction. + sql_update_with_default = ( + "UPDATE %(table)s SET %(column)s = %(default)s WHERE %(column)s IS NULL" + "; SET CONSTRAINTS ALL IMMEDIATE" + ) + sql_alter_sequence_type = "ALTER SEQUENCE IF EXISTS %(sequence)s AS %(type)s" + sql_delete_sequence = "DROP SEQUENCE IF EXISTS %(sequence)s CASCADE" + + sql_create_index = ( + "CREATE INDEX %(name)s ON %(table)s%(using)s " + "(%(columns)s)%(include)s%(extra)s%(condition)s" + ) + sql_create_index_concurrently = ( + "CREATE INDEX CONCURRENTLY %(name)s ON %(table)s%(using)s " + "(%(columns)s)%(include)s%(extra)s%(condition)s" + ) + sql_delete_index = "DROP INDEX IF EXISTS %(name)s" + sql_delete_index_concurrently = "DROP INDEX CONCURRENTLY IF EXISTS %(name)s" + + # Setting the constraint to IMMEDIATE to allow changing data in the same + # transaction. + sql_create_column_inline_fk = ( + "CONSTRAINT %(name)s REFERENCES %(to_table)s(%(to_column)s)%(deferrable)s" + "; SET CONSTRAINTS %(namespace)s%(name)s IMMEDIATE" + ) + # Setting the constraint to IMMEDIATE runs any deferred checks to allow + # dropping it in the same transaction. + sql_delete_fk = ( + "SET CONSTRAINTS %(name)s IMMEDIATE; " + "ALTER TABLE %(table)s DROP CONSTRAINT %(name)s" + ) + sql_delete_procedure = "DROP FUNCTION %(procedure)s(%(param_types)s)" + + def execute(self, sql, params=()): + # Merge the query client-side, as PostgreSQL won't do it server-side. + if params is None: + return super().execute(sql, params) + sql = self.connection.ops.compose_sql(str(sql), params) + # Don't let the superclass touch anything. + return super().execute(sql, None) + + sql_add_identity = ( + "ALTER TABLE %(table)s ALTER COLUMN %(column)s ADD " + "GENERATED BY DEFAULT AS IDENTITY" + ) + sql_drop_indentity = ( + "ALTER TABLE %(table)s ALTER COLUMN %(column)s DROP IDENTITY IF EXISTS" + ) + + def quote_value(self, value): + return sql.quote(value, self.connection.connection) + + def _field_indexes_sql(self, model, field): + output = super()._field_indexes_sql(model, field) + like_index_statement = self._create_like_index_sql(model, field) + if like_index_statement is not None: + output.append(like_index_statement) + return output + + def _field_data_type(self, field): + if field.is_relation: + return field.rel_db_type(self.connection) + return self.connection.data_types.get( + field.get_internal_type(), + field.db_type(self.connection), + ) + + def _field_base_data_types(self, field): + # Yield base data types for array fields. + if field.base_field.get_internal_type() == "ArrayField": + yield from self._field_base_data_types(field.base_field) + else: + yield self._field_data_type(field.base_field) + + def _create_like_index_sql(self, model, field): + """ + Return the statement to create an index with varchar operator pattern + when the column type is 'varchar' or 'text', otherwise return None. + """ + db_type = field.db_type(connection=self.connection) + if db_type is not None and (field.db_index or field.unique): + # Fields with database column types of `varchar` and `text` need + # a second index that specifies their operator class, which is + # needed when performing correct LIKE queries outside the + # C locale. See #12234. + # + # The same doesn't apply to array fields such as varchar[size] + # and text[size], so skip them. + if "[" in db_type: + return None + # Non-deterministic collations on Postgresql don't support indexes + # for operator classes varchar_pattern_ops/text_pattern_ops. + collation_name = getattr(field, "db_collation", None) + if not collation_name and field.is_relation: + collation_name = getattr(field.target_field, "db_collation", None) + if collation_name and not self._is_collation_deterministic(collation_name): + return None + if db_type.startswith("varchar"): + return self._create_index_sql( + model, + fields=[field], + suffix="_like", + opclasses=["varchar_pattern_ops"], + ) + elif db_type.startswith("text"): + return self._create_index_sql( + model, + fields=[field], + suffix="_like", + opclasses=["text_pattern_ops"], + ) + return None + + def _using_sql(self, new_field, old_field): + using_sql = " USING %(column)s::%(type)s" + new_internal_type = new_field.get_internal_type() + old_internal_type = old_field.get_internal_type() + if new_internal_type == "ArrayField" and new_internal_type == old_internal_type: + # Compare base data types for array fields. + if list(self._field_base_data_types(old_field)) != list( + self._field_base_data_types(new_field) + ): + return using_sql + elif self._field_data_type(old_field) != self._field_data_type(new_field): + return using_sql + return "" + + def _get_sequence_name(self, table, column): + with self.connection.cursor() as cursor: + for sequence in self.connection.introspection.get_sequences(cursor, table): + if sequence["column"] == column: + return sequence["name"] + return None + + def _alter_column_type_sql( + self, model, old_field, new_field, new_type, old_collation, new_collation + ): + # Drop indexes on varchar/text/citext columns that are changing to a + # different type. + old_db_params = old_field.db_parameters(connection=self.connection) + old_type = old_db_params["type"] + if (old_field.db_index or old_field.unique) and ( + (old_type.startswith("varchar") and not new_type.startswith("varchar")) + or (old_type.startswith("text") and not new_type.startswith("text")) + or (old_type.startswith("citext") and not new_type.startswith("citext")) + ): + index_name = self._create_index_name( + model._meta.db_table, [old_field.column], suffix="_like" + ) + self.execute(self._delete_index_sql(model, index_name)) + + self.sql_alter_column_type = ( + "ALTER COLUMN %(column)s TYPE %(type)s%(collation)s" + ) + # Cast when data type changed. + if using_sql := self._using_sql(new_field, old_field): + self.sql_alter_column_type += using_sql + new_internal_type = new_field.get_internal_type() + old_internal_type = old_field.get_internal_type() + # Make ALTER TYPE with IDENTITY make sense. + table = strip_quotes(model._meta.db_table) + auto_field_types = { + "AutoField", + "BigAutoField", + "SmallAutoField", + } + old_is_auto = old_internal_type in auto_field_types + new_is_auto = new_internal_type in auto_field_types + if new_is_auto and not old_is_auto: + column = strip_quotes(new_field.column) + return ( + ( + self.sql_alter_column_type + % { + "column": self.quote_name(column), + "type": new_type, + "collation": "", + }, + [], + ), + [ + ( + self.sql_add_identity + % { + "table": self.quote_name(table), + "column": self.quote_name(column), + }, + [], + ), + ], + ) + elif old_is_auto and not new_is_auto: + # Drop IDENTITY if exists (pre-Django 4.1 serial columns don't have + # it). + self.execute( + self.sql_drop_indentity + % { + "table": self.quote_name(table), + "column": self.quote_name(strip_quotes(new_field.column)), + } + ) + column = strip_quotes(new_field.column) + fragment, _ = super()._alter_column_type_sql( + model, old_field, new_field, new_type, old_collation, new_collation + ) + # Drop the sequence if exists (Django 4.1+ identity columns don't + # have it). + other_actions = [] + if sequence_name := self._get_sequence_name(table, column): + other_actions = [ + ( + self.sql_delete_sequence + % { + "sequence": self.quote_name(sequence_name), + }, + [], + ) + ] + return fragment, other_actions + elif new_is_auto and old_is_auto and old_internal_type != new_internal_type: + fragment, _ = super()._alter_column_type_sql( + model, old_field, new_field, new_type, old_collation, new_collation + ) + column = strip_quotes(new_field.column) + db_types = { + "AutoField": "integer", + "BigAutoField": "bigint", + "SmallAutoField": "smallint", + } + # Alter the sequence type if exists (Django 4.1+ identity columns + # don't have it). + other_actions = [] + if sequence_name := self._get_sequence_name(table, column): + other_actions = [ + ( + self.sql_alter_sequence_type + % { + "sequence": self.quote_name(sequence_name), + "type": db_types[new_internal_type], + }, + [], + ), + ] + return fragment, other_actions + else: + return super()._alter_column_type_sql( + model, old_field, new_field, new_type, old_collation, new_collation + ) + + def _alter_column_collation_sql( + self, model, new_field, new_type, new_collation, old_field + ): + sql = self.sql_alter_column_collate + # Cast when data type changed. + if using_sql := self._using_sql(new_field, old_field): + sql += using_sql + return ( + sql + % { + "column": self.quote_name(new_field.column), + "type": new_type, + "collation": " " + self._collate_sql(new_collation) + if new_collation + else "", + }, + [], + ) + + def _alter_field( + self, + model, + old_field, + new_field, + old_type, + new_type, + old_db_params, + new_db_params, + strict=False, + ): + super()._alter_field( + model, + old_field, + new_field, + old_type, + new_type, + old_db_params, + new_db_params, + strict, + ) + # Added an index? Create any PostgreSQL-specific indexes. + if (not (old_field.db_index or old_field.unique) and new_field.db_index) or ( + not old_field.unique and new_field.unique + ): + like_index_statement = self._create_like_index_sql(model, new_field) + if like_index_statement is not None: + self.execute(like_index_statement) + + # Removed an index? Drop any PostgreSQL-specific indexes. + if old_field.unique and not (new_field.db_index or new_field.unique): + index_to_remove = self._create_index_name( + model._meta.db_table, [old_field.column], suffix="_like" + ) + self.execute(self._delete_index_sql(model, index_to_remove)) + + def _index_columns(self, table, columns, col_suffixes, opclasses): + if opclasses: + return IndexColumns( + table, + columns, + self.quote_name, + col_suffixes=col_suffixes, + opclasses=opclasses, + ) + return super()._index_columns(table, columns, col_suffixes, opclasses) + + def add_index(self, model, index, concurrently=False): + self.execute( + index.create_sql(model, self, concurrently=concurrently), params=None + ) + + def remove_index(self, model, index, concurrently=False): + self.execute(index.remove_sql(model, self, concurrently=concurrently)) + + def _delete_index_sql(self, model, name, sql=None, concurrently=False): + sql = ( + self.sql_delete_index_concurrently + if concurrently + else self.sql_delete_index + ) + return super()._delete_index_sql(model, name, sql) + + def _create_index_sql( + self, + model, + *, + fields=None, + name=None, + suffix="", + using="", + db_tablespace=None, + col_suffixes=(), + sql=None, + opclasses=(), + condition=None, + concurrently=False, + include=None, + expressions=None, + ): + sql = sql or ( + self.sql_create_index + if not concurrently + else self.sql_create_index_concurrently + ) + return super()._create_index_sql( + model, + fields=fields, + name=name, + suffix=suffix, + using=using, + db_tablespace=db_tablespace, + col_suffixes=col_suffixes, + sql=sql, + opclasses=opclasses, + condition=condition, + include=include, + expressions=expressions, + ) + + def _is_collation_deterministic(self, collation_name): + with self.connection.cursor() as cursor: + cursor.execute( + """ + SELECT collisdeterministic + FROM pg_collation + WHERE collname = %s + """, + [collation_name], + ) + row = cursor.fetchone() + return row[0] if row else None diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/signals.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/signals.py new file mode 100644 index 0000000..a8079d0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/signals.py @@ -0,0 +1,3 @@ +from django.dispatch import Signal + +connection_created = Signal() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/sqlite3/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/sqlite3/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/sqlite3/_functions.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/sqlite3/_functions.py new file mode 100644 index 0000000..7e86950 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/sqlite3/_functions.py @@ -0,0 +1,511 @@ +""" +Implementations of SQL functions for SQLite. +""" +import functools +import random +import statistics +import zoneinfo +from datetime import timedelta +from hashlib import md5, sha1, sha224, sha256, sha384, sha512 +from math import ( + acos, + asin, + atan, + atan2, + ceil, + cos, + degrees, + exp, + floor, + fmod, + log, + pi, + radians, + sin, + sqrt, + tan, +) +from re import search as re_search + +from django.db.backends.utils import ( + split_tzname_delta, + typecast_time, + typecast_timestamp, +) +from django.utils import timezone +from django.utils.duration import duration_microseconds + + +def register(connection): + create_deterministic_function = functools.partial( + connection.create_function, + deterministic=True, + ) + create_deterministic_function("django_date_extract", 2, _sqlite_datetime_extract) + create_deterministic_function("django_date_trunc", 4, _sqlite_date_trunc) + create_deterministic_function( + "django_datetime_cast_date", 3, _sqlite_datetime_cast_date + ) + create_deterministic_function( + "django_datetime_cast_time", 3, _sqlite_datetime_cast_time + ) + create_deterministic_function( + "django_datetime_extract", 4, _sqlite_datetime_extract + ) + create_deterministic_function("django_datetime_trunc", 4, _sqlite_datetime_trunc) + create_deterministic_function("django_time_extract", 2, _sqlite_time_extract) + create_deterministic_function("django_time_trunc", 4, _sqlite_time_trunc) + create_deterministic_function("django_time_diff", 2, _sqlite_time_diff) + create_deterministic_function("django_timestamp_diff", 2, _sqlite_timestamp_diff) + create_deterministic_function("django_format_dtdelta", 3, _sqlite_format_dtdelta) + create_deterministic_function("regexp", 2, _sqlite_regexp) + create_deterministic_function("BITXOR", 2, _sqlite_bitxor) + create_deterministic_function("COT", 1, _sqlite_cot) + create_deterministic_function("LPAD", 3, _sqlite_lpad) + create_deterministic_function("MD5", 1, _sqlite_md5) + create_deterministic_function("REPEAT", 2, _sqlite_repeat) + create_deterministic_function("REVERSE", 1, _sqlite_reverse) + create_deterministic_function("RPAD", 3, _sqlite_rpad) + create_deterministic_function("SHA1", 1, _sqlite_sha1) + create_deterministic_function("SHA224", 1, _sqlite_sha224) + create_deterministic_function("SHA256", 1, _sqlite_sha256) + create_deterministic_function("SHA384", 1, _sqlite_sha384) + create_deterministic_function("SHA512", 1, _sqlite_sha512) + create_deterministic_function("SIGN", 1, _sqlite_sign) + # Don't use the built-in RANDOM() function because it returns a value + # in the range [-1 * 2^63, 2^63 - 1] instead of [0, 1). + connection.create_function("RAND", 0, random.random) + connection.create_aggregate("STDDEV_POP", 1, StdDevPop) + connection.create_aggregate("STDDEV_SAMP", 1, StdDevSamp) + connection.create_aggregate("VAR_POP", 1, VarPop) + connection.create_aggregate("VAR_SAMP", 1, VarSamp) + # Some math functions are enabled by default in SQLite 3.35+. + sql = "select sqlite_compileoption_used('ENABLE_MATH_FUNCTIONS')" + if not connection.execute(sql).fetchone()[0]: + create_deterministic_function("ACOS", 1, _sqlite_acos) + create_deterministic_function("ASIN", 1, _sqlite_asin) + create_deterministic_function("ATAN", 1, _sqlite_atan) + create_deterministic_function("ATAN2", 2, _sqlite_atan2) + create_deterministic_function("CEILING", 1, _sqlite_ceiling) + create_deterministic_function("COS", 1, _sqlite_cos) + create_deterministic_function("DEGREES", 1, _sqlite_degrees) + create_deterministic_function("EXP", 1, _sqlite_exp) + create_deterministic_function("FLOOR", 1, _sqlite_floor) + create_deterministic_function("LN", 1, _sqlite_ln) + create_deterministic_function("LOG", 2, _sqlite_log) + create_deterministic_function("MOD", 2, _sqlite_mod) + create_deterministic_function("PI", 0, _sqlite_pi) + create_deterministic_function("POWER", 2, _sqlite_power) + create_deterministic_function("RADIANS", 1, _sqlite_radians) + create_deterministic_function("SIN", 1, _sqlite_sin) + create_deterministic_function("SQRT", 1, _sqlite_sqrt) + create_deterministic_function("TAN", 1, _sqlite_tan) + + +def _sqlite_datetime_parse(dt, tzname=None, conn_tzname=None): + if dt is None: + return None + try: + dt = typecast_timestamp(dt) + except (TypeError, ValueError): + return None + if conn_tzname: + dt = dt.replace(tzinfo=zoneinfo.ZoneInfo(conn_tzname)) + if tzname is not None and tzname != conn_tzname: + tzname, sign, offset = split_tzname_delta(tzname) + if offset: + hours, minutes = offset.split(":") + offset_delta = timedelta(hours=int(hours), minutes=int(minutes)) + dt += offset_delta if sign == "+" else -offset_delta + dt = timezone.localtime(dt, zoneinfo.ZoneInfo(tzname)) + return dt + + +def _sqlite_date_trunc(lookup_type, dt, tzname, conn_tzname): + dt = _sqlite_datetime_parse(dt, tzname, conn_tzname) + if dt is None: + return None + if lookup_type == "year": + return f"{dt.year:04d}-01-01" + elif lookup_type == "quarter": + month_in_quarter = dt.month - (dt.month - 1) % 3 + return f"{dt.year:04d}-{month_in_quarter:02d}-01" + elif lookup_type == "month": + return f"{dt.year:04d}-{dt.month:02d}-01" + elif lookup_type == "week": + dt -= timedelta(days=dt.weekday()) + return f"{dt.year:04d}-{dt.month:02d}-{dt.day:02d}" + elif lookup_type == "day": + return f"{dt.year:04d}-{dt.month:02d}-{dt.day:02d}" + raise ValueError(f"Unsupported lookup type: {lookup_type!r}") + + +def _sqlite_time_trunc(lookup_type, dt, tzname, conn_tzname): + if dt is None: + return None + dt_parsed = _sqlite_datetime_parse(dt, tzname, conn_tzname) + if dt_parsed is None: + try: + dt = typecast_time(dt) + except (ValueError, TypeError): + return None + else: + dt = dt_parsed + if lookup_type == "hour": + return f"{dt.hour:02d}:00:00" + elif lookup_type == "minute": + return f"{dt.hour:02d}:{dt.minute:02d}:00" + elif lookup_type == "second": + return f"{dt.hour:02d}:{dt.minute:02d}:{dt.second:02d}" + raise ValueError(f"Unsupported lookup type: {lookup_type!r}") + + +def _sqlite_datetime_cast_date(dt, tzname, conn_tzname): + dt = _sqlite_datetime_parse(dt, tzname, conn_tzname) + if dt is None: + return None + return dt.date().isoformat() + + +def _sqlite_datetime_cast_time(dt, tzname, conn_tzname): + dt = _sqlite_datetime_parse(dt, tzname, conn_tzname) + if dt is None: + return None + return dt.time().isoformat() + + +def _sqlite_datetime_extract(lookup_type, dt, tzname=None, conn_tzname=None): + dt = _sqlite_datetime_parse(dt, tzname, conn_tzname) + if dt is None: + return None + if lookup_type == "week_day": + return (dt.isoweekday() % 7) + 1 + elif lookup_type == "iso_week_day": + return dt.isoweekday() + elif lookup_type == "week": + return dt.isocalendar().week + elif lookup_type == "quarter": + return ceil(dt.month / 3) + elif lookup_type == "iso_year": + return dt.isocalendar().year + else: + return getattr(dt, lookup_type) + + +def _sqlite_datetime_trunc(lookup_type, dt, tzname, conn_tzname): + dt = _sqlite_datetime_parse(dt, tzname, conn_tzname) + if dt is None: + return None + if lookup_type == "year": + return f"{dt.year:04d}-01-01 00:00:00" + elif lookup_type == "quarter": + month_in_quarter = dt.month - (dt.month - 1) % 3 + return f"{dt.year:04d}-{month_in_quarter:02d}-01 00:00:00" + elif lookup_type == "month": + return f"{dt.year:04d}-{dt.month:02d}-01 00:00:00" + elif lookup_type == "week": + dt -= timedelta(days=dt.weekday()) + return f"{dt.year:04d}-{dt.month:02d}-{dt.day:02d} 00:00:00" + elif lookup_type == "day": + return f"{dt.year:04d}-{dt.month:02d}-{dt.day:02d} 00:00:00" + elif lookup_type == "hour": + return f"{dt.year:04d}-{dt.month:02d}-{dt.day:02d} {dt.hour:02d}:00:00" + elif lookup_type == "minute": + return ( + f"{dt.year:04d}-{dt.month:02d}-{dt.day:02d} " + f"{dt.hour:02d}:{dt.minute:02d}:00" + ) + elif lookup_type == "second": + return ( + f"{dt.year:04d}-{dt.month:02d}-{dt.day:02d} " + f"{dt.hour:02d}:{dt.minute:02d}:{dt.second:02d}" + ) + raise ValueError(f"Unsupported lookup type: {lookup_type!r}") + + +def _sqlite_time_extract(lookup_type, dt): + if dt is None: + return None + try: + dt = typecast_time(dt) + except (ValueError, TypeError): + return None + return getattr(dt, lookup_type) + + +def _sqlite_prepare_dtdelta_param(conn, param): + if conn in ["+", "-"]: + if isinstance(param, int): + return timedelta(0, 0, param) + else: + return typecast_timestamp(param) + return param + + +def _sqlite_format_dtdelta(connector, lhs, rhs): + """ + LHS and RHS can be either: + - An integer number of microseconds + - A string representing a datetime + - A scalar value, e.g. float + """ + if connector is None or lhs is None or rhs is None: + return None + connector = connector.strip() + try: + real_lhs = _sqlite_prepare_dtdelta_param(connector, lhs) + real_rhs = _sqlite_prepare_dtdelta_param(connector, rhs) + except (ValueError, TypeError): + return None + if connector == "+": + # typecast_timestamp() returns a date or a datetime without timezone. + # It will be formatted as "%Y-%m-%d" or "%Y-%m-%d %H:%M:%S[.%f]" + out = str(real_lhs + real_rhs) + elif connector == "-": + out = str(real_lhs - real_rhs) + elif connector == "*": + out = real_lhs * real_rhs + else: + out = real_lhs / real_rhs + return out + + +def _sqlite_time_diff(lhs, rhs): + if lhs is None or rhs is None: + return None + left = typecast_time(lhs) + right = typecast_time(rhs) + return ( + (left.hour * 60 * 60 * 1000000) + + (left.minute * 60 * 1000000) + + (left.second * 1000000) + + (left.microsecond) + - (right.hour * 60 * 60 * 1000000) + - (right.minute * 60 * 1000000) + - (right.second * 1000000) + - (right.microsecond) + ) + + +def _sqlite_timestamp_diff(lhs, rhs): + if lhs is None or rhs is None: + return None + left = typecast_timestamp(lhs) + right = typecast_timestamp(rhs) + return duration_microseconds(left - right) + + +def _sqlite_regexp(pattern, string): + if pattern is None or string is None: + return None + if not isinstance(string, str): + string = str(string) + return bool(re_search(pattern, string)) + + +def _sqlite_acos(x): + if x is None: + return None + return acos(x) + + +def _sqlite_asin(x): + if x is None: + return None + return asin(x) + + +def _sqlite_atan(x): + if x is None: + return None + return atan(x) + + +def _sqlite_atan2(y, x): + if y is None or x is None: + return None + return atan2(y, x) + + +def _sqlite_bitxor(x, y): + if x is None or y is None: + return None + return x ^ y + + +def _sqlite_ceiling(x): + if x is None: + return None + return ceil(x) + + +def _sqlite_cos(x): + if x is None: + return None + return cos(x) + + +def _sqlite_cot(x): + if x is None: + return None + return 1 / tan(x) + + +def _sqlite_degrees(x): + if x is None: + return None + return degrees(x) + + +def _sqlite_exp(x): + if x is None: + return None + return exp(x) + + +def _sqlite_floor(x): + if x is None: + return None + return floor(x) + + +def _sqlite_ln(x): + if x is None: + return None + return log(x) + + +def _sqlite_log(base, x): + if base is None or x is None: + return None + # Arguments reversed to match SQL standard. + return log(x, base) + + +def _sqlite_lpad(text, length, fill_text): + if text is None or length is None or fill_text is None: + return None + delta = length - len(text) + if delta <= 0: + return text[:length] + return (fill_text * length)[:delta] + text + + +def _sqlite_md5(text): + if text is None: + return None + return md5(text.encode()).hexdigest() + + +def _sqlite_mod(x, y): + if x is None or y is None: + return None + return fmod(x, y) + + +def _sqlite_pi(): + return pi + + +def _sqlite_power(x, y): + if x is None or y is None: + return None + return x**y + + +def _sqlite_radians(x): + if x is None: + return None + return radians(x) + + +def _sqlite_repeat(text, count): + if text is None or count is None: + return None + return text * count + + +def _sqlite_reverse(text): + if text is None: + return None + return text[::-1] + + +def _sqlite_rpad(text, length, fill_text): + if text is None or length is None or fill_text is None: + return None + return (text + fill_text * length)[:length] + + +def _sqlite_sha1(text): + if text is None: + return None + return sha1(text.encode()).hexdigest() + + +def _sqlite_sha224(text): + if text is None: + return None + return sha224(text.encode()).hexdigest() + + +def _sqlite_sha256(text): + if text is None: + return None + return sha256(text.encode()).hexdigest() + + +def _sqlite_sha384(text): + if text is None: + return None + return sha384(text.encode()).hexdigest() + + +def _sqlite_sha512(text): + if text is None: + return None + return sha512(text.encode()).hexdigest() + + +def _sqlite_sign(x): + if x is None: + return None + return (x > 0) - (x < 0) + + +def _sqlite_sin(x): + if x is None: + return None + return sin(x) + + +def _sqlite_sqrt(x): + if x is None: + return None + return sqrt(x) + + +def _sqlite_tan(x): + if x is None: + return None + return tan(x) + + +class ListAggregate(list): + step = list.append + + +class StdDevPop(ListAggregate): + finalize = statistics.pstdev + + +class StdDevSamp(ListAggregate): + finalize = statistics.stdev + + +class VarPop(ListAggregate): + finalize = statistics.pvariance + + +class VarSamp(ListAggregate): + finalize = statistics.variance diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/sqlite3/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/sqlite3/base.py new file mode 100644 index 0000000..08de0ba --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/sqlite3/base.py @@ -0,0 +1,347 @@ +""" +SQLite backend for the sqlite3 module in the standard library. +""" +import datetime +import decimal +import warnings +from collections.abc import Mapping +from itertools import chain, tee +from sqlite3 import dbapi2 as Database + +from django.core.exceptions import ImproperlyConfigured +from django.db import IntegrityError +from django.db.backends.base.base import BaseDatabaseWrapper +from django.utils.asyncio import async_unsafe +from django.utils.dateparse import parse_date, parse_datetime, parse_time +from django.utils.regex_helper import _lazy_re_compile + +from ._functions import register as register_functions +from .client import DatabaseClient +from .creation import DatabaseCreation +from .features import DatabaseFeatures +from .introspection import DatabaseIntrospection +from .operations import DatabaseOperations +from .schema import DatabaseSchemaEditor + + +def decoder(conv_func): + """ + Convert bytestrings from Python's sqlite3 interface to a regular string. + """ + return lambda s: conv_func(s.decode()) + + +def adapt_date(val): + return val.isoformat() + + +def adapt_datetime(val): + return val.isoformat(" ") + + +Database.register_converter("bool", b"1".__eq__) +Database.register_converter("date", decoder(parse_date)) +Database.register_converter("time", decoder(parse_time)) +Database.register_converter("datetime", decoder(parse_datetime)) +Database.register_converter("timestamp", decoder(parse_datetime)) + +Database.register_adapter(decimal.Decimal, str) +Database.register_adapter(datetime.date, adapt_date) +Database.register_adapter(datetime.datetime, adapt_datetime) + + +class DatabaseWrapper(BaseDatabaseWrapper): + vendor = "sqlite" + display_name = "SQLite" + # SQLite doesn't actually support most of these types, but it "does the right + # thing" given more verbose field definitions, so leave them as is so that + # schema inspection is more useful. + data_types = { + "AutoField": "integer", + "BigAutoField": "integer", + "BinaryField": "BLOB", + "BooleanField": "bool", + "CharField": "varchar(%(max_length)s)", + "DateField": "date", + "DateTimeField": "datetime", + "DecimalField": "decimal", + "DurationField": "bigint", + "FileField": "varchar(%(max_length)s)", + "FilePathField": "varchar(%(max_length)s)", + "FloatField": "real", + "IntegerField": "integer", + "BigIntegerField": "bigint", + "IPAddressField": "char(15)", + "GenericIPAddressField": "char(39)", + "JSONField": "text", + "OneToOneField": "integer", + "PositiveBigIntegerField": "bigint unsigned", + "PositiveIntegerField": "integer unsigned", + "PositiveSmallIntegerField": "smallint unsigned", + "SlugField": "varchar(%(max_length)s)", + "SmallAutoField": "integer", + "SmallIntegerField": "smallint", + "TextField": "text", + "TimeField": "time", + "UUIDField": "char(32)", + } + data_type_check_constraints = { + "PositiveBigIntegerField": '"%(column)s" >= 0', + "JSONField": '(JSON_VALID("%(column)s") OR "%(column)s" IS NULL)', + "PositiveIntegerField": '"%(column)s" >= 0', + "PositiveSmallIntegerField": '"%(column)s" >= 0', + } + data_types_suffix = { + "AutoField": "AUTOINCREMENT", + "BigAutoField": "AUTOINCREMENT", + "SmallAutoField": "AUTOINCREMENT", + } + # SQLite requires LIKE statements to include an ESCAPE clause if the value + # being escaped has a percent or underscore in it. + # See https://www.sqlite.org/lang_expr.html for an explanation. + operators = { + "exact": "= %s", + "iexact": "LIKE %s ESCAPE '\\'", + "contains": "LIKE %s ESCAPE '\\'", + "icontains": "LIKE %s ESCAPE '\\'", + "regex": "REGEXP %s", + "iregex": "REGEXP '(?i)' || %s", + "gt": "> %s", + "gte": ">= %s", + "lt": "< %s", + "lte": "<= %s", + "startswith": "LIKE %s ESCAPE '\\'", + "endswith": "LIKE %s ESCAPE '\\'", + "istartswith": "LIKE %s ESCAPE '\\'", + "iendswith": "LIKE %s ESCAPE '\\'", + } + + # The patterns below are used to generate SQL pattern lookup clauses when + # the right-hand side of the lookup isn't a raw string (it might be an expression + # or the result of a bilateral transformation). + # In those cases, special characters for LIKE operators (e.g. \, *, _) should be + # escaped on database side. + # + # Note: we use str.format() here for readability as '%' is used as a wildcard for + # the LIKE operator. + pattern_esc = r"REPLACE(REPLACE(REPLACE({}, '\', '\\'), '%%', '\%%'), '_', '\_')" + pattern_ops = { + "contains": r"LIKE '%%' || {} || '%%' ESCAPE '\'", + "icontains": r"LIKE '%%' || UPPER({}) || '%%' ESCAPE '\'", + "startswith": r"LIKE {} || '%%' ESCAPE '\'", + "istartswith": r"LIKE UPPER({}) || '%%' ESCAPE '\'", + "endswith": r"LIKE '%%' || {} ESCAPE '\'", + "iendswith": r"LIKE '%%' || UPPER({}) ESCAPE '\'", + } + + Database = Database + SchemaEditorClass = DatabaseSchemaEditor + # Classes instantiated in __init__(). + client_class = DatabaseClient + creation_class = DatabaseCreation + features_class = DatabaseFeatures + introspection_class = DatabaseIntrospection + ops_class = DatabaseOperations + + def get_connection_params(self): + settings_dict = self.settings_dict + if not settings_dict["NAME"]: + raise ImproperlyConfigured( + "settings.DATABASES is improperly configured. " + "Please supply the NAME value." + ) + kwargs = { + "database": settings_dict["NAME"], + "detect_types": Database.PARSE_DECLTYPES | Database.PARSE_COLNAMES, + **settings_dict["OPTIONS"], + } + # Always allow the underlying SQLite connection to be shareable + # between multiple threads. The safe-guarding will be handled at a + # higher level by the `BaseDatabaseWrapper.allow_thread_sharing` + # property. This is necessary as the shareability is disabled by + # default in sqlite3 and it cannot be changed once a connection is + # opened. + if "check_same_thread" in kwargs and kwargs["check_same_thread"]: + warnings.warn( + "The `check_same_thread` option was provided and set to " + "True. It will be overridden with False. Use the " + "`DatabaseWrapper.allow_thread_sharing` property instead " + "for controlling thread shareability.", + RuntimeWarning, + ) + kwargs.update({"check_same_thread": False, "uri": True}) + return kwargs + + def get_database_version(self): + return self.Database.sqlite_version_info + + @async_unsafe + def get_new_connection(self, conn_params): + conn = Database.connect(**conn_params) + register_functions(conn) + + conn.execute("PRAGMA foreign_keys = ON") + # The macOS bundled SQLite defaults legacy_alter_table ON, which + # prevents atomic table renames. + conn.execute("PRAGMA legacy_alter_table = OFF") + return conn + + def create_cursor(self, name=None): + return self.connection.cursor(factory=SQLiteCursorWrapper) + + @async_unsafe + def close(self): + self.validate_thread_sharing() + # If database is in memory, closing the connection destroys the + # database. To prevent accidental data loss, ignore close requests on + # an in-memory db. + if not self.is_in_memory_db(): + BaseDatabaseWrapper.close(self) + + def _savepoint_allowed(self): + # When 'isolation_level' is not None, sqlite3 commits before each + # savepoint; it's a bug. When it is None, savepoints don't make sense + # because autocommit is enabled. The only exception is inside 'atomic' + # blocks. To work around that bug, on SQLite, 'atomic' starts a + # transaction explicitly rather than simply disable autocommit. + return self.in_atomic_block + + def _set_autocommit(self, autocommit): + if autocommit: + level = None + else: + # sqlite3's internal default is ''. It's different from None. + # See Modules/_sqlite/connection.c. + level = "" + # 'isolation_level' is a misleading API. + # SQLite always runs at the SERIALIZABLE isolation level. + with self.wrap_database_errors: + self.connection.isolation_level = level + + def disable_constraint_checking(self): + with self.cursor() as cursor: + cursor.execute("PRAGMA foreign_keys = OFF") + # Foreign key constraints cannot be turned off while in a multi- + # statement transaction. Fetch the current state of the pragma + # to determine if constraints are effectively disabled. + enabled = cursor.execute("PRAGMA foreign_keys").fetchone()[0] + return not bool(enabled) + + def enable_constraint_checking(self): + with self.cursor() as cursor: + cursor.execute("PRAGMA foreign_keys = ON") + + def check_constraints(self, table_names=None): + """ + Check each table name in `table_names` for rows with invalid foreign + key references. This method is intended to be used in conjunction with + `disable_constraint_checking()` and `enable_constraint_checking()`, to + determine if rows with invalid references were entered while constraint + checks were off. + """ + with self.cursor() as cursor: + if table_names is None: + violations = cursor.execute("PRAGMA foreign_key_check").fetchall() + else: + violations = chain.from_iterable( + cursor.execute( + "PRAGMA foreign_key_check(%s)" % self.ops.quote_name(table_name) + ).fetchall() + for table_name in table_names + ) + # See https://www.sqlite.org/pragma.html#pragma_foreign_key_check + for ( + table_name, + rowid, + referenced_table_name, + foreign_key_index, + ) in violations: + foreign_key = cursor.execute( + "PRAGMA foreign_key_list(%s)" % self.ops.quote_name(table_name) + ).fetchall()[foreign_key_index] + column_name, referenced_column_name = foreign_key[3:5] + primary_key_column_name = self.introspection.get_primary_key_column( + cursor, table_name + ) + primary_key_value, bad_value = cursor.execute( + "SELECT %s, %s FROM %s WHERE rowid = %%s" + % ( + self.ops.quote_name(primary_key_column_name), + self.ops.quote_name(column_name), + self.ops.quote_name(table_name), + ), + (rowid,), + ).fetchone() + raise IntegrityError( + "The row in table '%s' with primary key '%s' has an " + "invalid foreign key: %s.%s contains a value '%s' that " + "does not have a corresponding value in %s.%s." + % ( + table_name, + primary_key_value, + table_name, + column_name, + bad_value, + referenced_table_name, + referenced_column_name, + ) + ) + + def is_usable(self): + return True + + def _start_transaction_under_autocommit(self): + """ + Start a transaction explicitly in autocommit mode. + + Staying in autocommit mode works around a bug of sqlite3 that breaks + savepoints when autocommit is disabled. + """ + self.cursor().execute("BEGIN") + + def is_in_memory_db(self): + return self.creation.is_in_memory_db(self.settings_dict["NAME"]) + + +FORMAT_QMARK_REGEX = _lazy_re_compile(r"(?= 1: + self.log( + "Destroying old test database for alias %s..." + % (self._get_database_display_str(verbosity, test_database_name),) + ) + if os.access(test_database_name, os.F_OK): + if not autoclobber: + confirm = input( + "Type 'yes' if you would like to try deleting the test " + "database '%s', or 'no' to cancel: " % test_database_name + ) + if autoclobber or confirm == "yes": + try: + os.remove(test_database_name) + except Exception as e: + self.log("Got an error deleting the old test database: %s" % e) + sys.exit(2) + else: + self.log("Tests cancelled.") + sys.exit(1) + return test_database_name + + def get_test_db_clone_settings(self, suffix): + orig_settings_dict = self.connection.settings_dict + source_database_name = orig_settings_dict["NAME"] or ":memory:" + + if not self.is_in_memory_db(source_database_name): + root, ext = os.path.splitext(source_database_name) + return {**orig_settings_dict, "NAME": f"{root}_{suffix}{ext}"} + + start_method = multiprocessing.get_start_method() + if start_method == "fork": + return orig_settings_dict + if start_method == "spawn": + return { + **orig_settings_dict, + "NAME": f"{self.connection.alias}_{suffix}.sqlite3", + } + raise NotSupportedError( + f"Cloning with start method {start_method!r} is not supported." + ) + + def _clone_test_db(self, suffix, verbosity, keepdb=False): + source_database_name = self.connection.settings_dict["NAME"] + target_database_name = self.get_test_db_clone_settings(suffix)["NAME"] + if not self.is_in_memory_db(source_database_name): + # Erase the old test database + if os.access(target_database_name, os.F_OK): + if keepdb: + return + if verbosity >= 1: + self.log( + "Destroying old test database for alias %s..." + % ( + self._get_database_display_str( + verbosity, target_database_name + ), + ) + ) + try: + os.remove(target_database_name) + except Exception as e: + self.log("Got an error deleting the old test database: %s" % e) + sys.exit(2) + try: + shutil.copy(source_database_name, target_database_name) + except Exception as e: + self.log("Got an error cloning the test database: %s" % e) + sys.exit(2) + # Forking automatically makes a copy of an in-memory database. + # Spawn requires migrating to disk which will be re-opened in + # setup_worker_connection. + elif multiprocessing.get_start_method() == "spawn": + ondisk_db = sqlite3.connect(target_database_name, uri=True) + self.connection.connection.backup(ondisk_db) + ondisk_db.close() + + def _destroy_test_db(self, test_database_name, verbosity): + if test_database_name and not self.is_in_memory_db(test_database_name): + # Remove the SQLite database file + os.remove(test_database_name) + + def test_db_signature(self): + """ + Return a tuple that uniquely identifies a test database. + + This takes into account the special cases of ":memory:" and "" for + SQLite since the databases will be distinct despite having the same + TEST NAME. See https://www.sqlite.org/inmemorydb.html + """ + test_database_name = self._get_test_db_name() + sig = [self.connection.settings_dict["NAME"]] + if self.is_in_memory_db(test_database_name): + sig.append(self.connection.alias) + else: + sig.append(test_database_name) + return tuple(sig) + + def setup_worker_connection(self, _worker_id): + settings_dict = self.get_test_db_clone_settings(_worker_id) + # connection.settings_dict must be updated in place for changes to be + # reflected in django.db.connections. Otherwise new threads would + # connect to the default database instead of the appropriate clone. + start_method = multiprocessing.get_start_method() + if start_method == "fork": + # Update settings_dict in place. + self.connection.settings_dict.update(settings_dict) + self.connection.close() + elif start_method == "spawn": + alias = self.connection.alias + connection_str = ( + f"file:memorydb_{alias}_{_worker_id}?mode=memory&cache=shared" + ) + source_db = self.connection.Database.connect( + f"file:{alias}_{_worker_id}.sqlite3", uri=True + ) + target_db = sqlite3.connect(connection_str, uri=True) + source_db.backup(target_db) + source_db.close() + # Update settings_dict in place. + self.connection.settings_dict.update(settings_dict) + self.connection.settings_dict["NAME"] = connection_str + # Re-open connection to in-memory database before closing copy + # connection. + self.connection.connect() + target_db.close() + if os.environ.get("RUNNING_DJANGOS_TEST_SUITE") == "true": + self.mark_expected_failures_and_skips() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/sqlite3/features.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/sqlite3/features.py new file mode 100644 index 0000000..32ea770 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/sqlite3/features.py @@ -0,0 +1,155 @@ +import operator + +from django.db import transaction +from django.db.backends.base.features import BaseDatabaseFeatures +from django.db.utils import OperationalError +from django.utils.functional import cached_property + +from .base import Database + + +class DatabaseFeatures(BaseDatabaseFeatures): + minimum_database_version = (3, 27) + test_db_allows_multiple_connections = False + supports_unspecified_pk = True + supports_timezones = False + max_query_params = 999 + supports_transactions = True + atomic_transactions = False + can_rollback_ddl = True + can_create_inline_fk = False + requires_literal_defaults = True + can_clone_databases = True + supports_temporal_subtraction = True + ignores_table_name_case = True + supports_cast_with_precision = False + time_cast_precision = 3 + can_release_savepoints = True + has_case_insensitive_like = True + # Is "ALTER TABLE ... DROP COLUMN" supported? + can_alter_table_drop_column = Database.sqlite_version_info >= (3, 35, 5) + supports_parentheses_in_compound = False + can_defer_constraint_checks = True + supports_over_clause = True + supports_frame_range_fixed_distance = Database.sqlite_version_info >= (3, 28, 0) + supports_aggregate_filter_clause = Database.sqlite_version_info >= (3, 30, 1) + supports_order_by_nulls_modifier = Database.sqlite_version_info >= (3, 30, 0) + # NULLS LAST/FIRST emulation on < 3.30 requires subquery wrapping. + requires_compound_order_by_subquery = Database.sqlite_version_info < (3, 30) + order_by_nulls_first = True + supports_json_field_contains = False + supports_update_conflicts = True + supports_update_conflicts_with_target = True + supports_stored_generated_columns = Database.sqlite_version_info >= (3, 31, 0) + supports_virtual_generated_columns = Database.sqlite_version_info >= (3, 31, 0) + test_collations = { + "ci": "nocase", + "cs": "binary", + "non_default": "nocase", + "virtual": "nocase", + } + django_test_expected_failures = { + # The django_format_dtdelta() function doesn't properly handle mixed + # Date/DateTime fields and timedeltas. + "expressions.tests.FTimeDeltaTests.test_mixed_comparisons1", + } + create_test_table_with_composite_primary_key = """ + CREATE TABLE test_table_composite_pk ( + column_1 INTEGER NOT NULL, + column_2 INTEGER NOT NULL, + PRIMARY KEY(column_1, column_2) + ) + """ + insert_test_table_with_defaults = 'INSERT INTO {} ("null") VALUES (1)' + supports_default_keyword_in_insert = False + + @cached_property + def django_test_skips(self): + skips = { + "SQLite stores values rounded to 15 significant digits.": { + "model_fields.test_decimalfield.DecimalFieldTests." + "test_fetch_from_db_without_float_rounding", + }, + "SQLite naively remakes the table on field alteration.": { + "schema.tests.SchemaTests.test_unique_no_unnecessary_fk_drops", + "schema.tests.SchemaTests.test_unique_and_reverse_m2m", + "schema.tests.SchemaTests." + "test_alter_field_default_doesnt_perform_queries", + "schema.tests.SchemaTests." + "test_rename_column_renames_deferred_sql_references", + }, + "SQLite doesn't support negative precision for ROUND().": { + "db_functions.math.test_round.RoundTests." + "test_null_with_negative_precision", + "db_functions.math.test_round.RoundTests." + "test_decimal_with_negative_precision", + "db_functions.math.test_round.RoundTests." + "test_float_with_negative_precision", + "db_functions.math.test_round.RoundTests." + "test_integer_with_negative_precision", + }, + } + if self.connection.is_in_memory_db(): + skips.update( + { + "the sqlite backend's close() method is a no-op when using an " + "in-memory database": { + "servers.test_liveserverthread.LiveServerThreadTest." + "test_closes_connections", + "servers.tests.LiveServerTestCloseConnectionTest." + "test_closes_connections", + }, + "For SQLite in-memory tests, closing the connection destroys" + "the database.": { + "test_utils.tests.AssertNumQueriesUponConnectionTests." + "test_ignores_connection_configuration_queries", + }, + } + ) + else: + skips.update( + { + "Only connections to in-memory SQLite databases are passed to the " + "server thread.": { + "servers.tests.LiveServerInMemoryDatabaseLockTest." + "test_in_memory_database_lock", + }, + "multiprocessing's start method is checked only for in-memory " + "SQLite databases": { + "backends.sqlite.test_creation.TestDbSignatureTests." + "test_get_test_db_clone_settings_not_supported", + }, + } + ) + return skips + + @cached_property + def introspected_field_types(self): + return { + **super().introspected_field_types, + "BigAutoField": "AutoField", + "DurationField": "BigIntegerField", + "GenericIPAddressField": "CharField", + "SmallAutoField": "AutoField", + } + + @cached_property + def supports_json_field(self): + with self.connection.cursor() as cursor: + try: + with transaction.atomic(self.connection.alias): + cursor.execute('SELECT JSON(\'{"a": "b"}\')') + except OperationalError: + return False + return True + + can_introspect_json_field = property(operator.attrgetter("supports_json_field")) + has_json_object_function = property(operator.attrgetter("supports_json_field")) + + @cached_property + def can_return_columns_from_insert(self): + return Database.sqlite_version_info >= (3, 35) + + can_return_rows_from_bulk_insert = property( + operator.attrgetter("can_return_columns_from_insert") + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/sqlite3/introspection.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/sqlite3/introspection.py new file mode 100644 index 0000000..79aa193 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/sqlite3/introspection.py @@ -0,0 +1,440 @@ +from collections import namedtuple + +import sqlparse + +from django.db import DatabaseError +from django.db.backends.base.introspection import BaseDatabaseIntrospection +from django.db.backends.base.introspection import FieldInfo as BaseFieldInfo +from django.db.backends.base.introspection import TableInfo +from django.db.models import Index +from django.utils.regex_helper import _lazy_re_compile + +FieldInfo = namedtuple( + "FieldInfo", BaseFieldInfo._fields + ("pk", "has_json_constraint") +) + +field_size_re = _lazy_re_compile(r"^\s*(?:var)?char\s*\(\s*(\d+)\s*\)\s*$") + + +def get_field_size(name): + """Extract the size number from a "varchar(11)" type name""" + m = field_size_re.search(name) + return int(m[1]) if m else None + + +# This light wrapper "fakes" a dictionary interface, because some SQLite data +# types include variables in them -- e.g. "varchar(30)" -- and can't be matched +# as a simple dictionary lookup. +class FlexibleFieldLookupDict: + # Maps SQL types to Django Field types. Some of the SQL types have multiple + # entries here because SQLite allows for anything and doesn't normalize the + # field type; it uses whatever was given. + base_data_types_reverse = { + "bool": "BooleanField", + "boolean": "BooleanField", + "smallint": "SmallIntegerField", + "smallint unsigned": "PositiveSmallIntegerField", + "smallinteger": "SmallIntegerField", + "int": "IntegerField", + "integer": "IntegerField", + "bigint": "BigIntegerField", + "integer unsigned": "PositiveIntegerField", + "bigint unsigned": "PositiveBigIntegerField", + "decimal": "DecimalField", + "real": "FloatField", + "text": "TextField", + "char": "CharField", + "varchar": "CharField", + "blob": "BinaryField", + "date": "DateField", + "datetime": "DateTimeField", + "time": "TimeField", + } + + def __getitem__(self, key): + key = key.lower().split("(", 1)[0].strip() + return self.base_data_types_reverse[key] + + +class DatabaseIntrospection(BaseDatabaseIntrospection): + data_types_reverse = FlexibleFieldLookupDict() + + def get_field_type(self, data_type, description): + field_type = super().get_field_type(data_type, description) + if description.pk and field_type in { + "BigIntegerField", + "IntegerField", + "SmallIntegerField", + }: + # No support for BigAutoField or SmallAutoField as SQLite treats + # all integer primary keys as signed 64-bit integers. + return "AutoField" + if description.has_json_constraint: + return "JSONField" + return field_type + + def get_table_list(self, cursor): + """Return a list of table and view names in the current database.""" + # Skip the sqlite_sequence system table used for autoincrement key + # generation. + cursor.execute( + """ + SELECT name, type FROM sqlite_master + WHERE type in ('table', 'view') AND NOT name='sqlite_sequence' + ORDER BY name""" + ) + return [TableInfo(row[0], row[1][0]) for row in cursor.fetchall()] + + def get_table_description(self, cursor, table_name): + """ + Return a description of the table with the DB-API cursor.description + interface. + """ + cursor.execute( + "PRAGMA table_xinfo(%s)" % self.connection.ops.quote_name(table_name) + ) + table_info = cursor.fetchall() + if not table_info: + raise DatabaseError(f"Table {table_name} does not exist (empty pragma).") + collations = self._get_column_collations(cursor, table_name) + json_columns = set() + if self.connection.features.can_introspect_json_field: + for line in table_info: + column = line[1] + json_constraint_sql = '%%json_valid("%s")%%' % column + has_json_constraint = cursor.execute( + """ + SELECT sql + FROM sqlite_master + WHERE + type = 'table' AND + name = %s AND + sql LIKE %s + """, + [table_name, json_constraint_sql], + ).fetchone() + if has_json_constraint: + json_columns.add(column) + return [ + FieldInfo( + name, + data_type, + get_field_size(data_type), + None, + None, + None, + not notnull, + default, + collations.get(name), + pk == 1, + name in json_columns, + ) + for cid, name, data_type, notnull, default, pk, hidden in table_info + if hidden + in [ + 0, # Normal column. + 2, # Virtual generated column. + 3, # Stored generated column. + ] + ] + + def get_sequences(self, cursor, table_name, table_fields=()): + pk_col = self.get_primary_key_column(cursor, table_name) + return [{"table": table_name, "column": pk_col}] + + def get_relations(self, cursor, table_name): + """ + Return a dictionary of {column_name: (ref_column_name, ref_table_name)} + representing all foreign keys in the given table. + """ + cursor.execute( + "PRAGMA foreign_key_list(%s)" % self.connection.ops.quote_name(table_name) + ) + return { + column_name: (ref_column_name, ref_table_name) + for ( + _, + _, + ref_table_name, + column_name, + ref_column_name, + *_, + ) in cursor.fetchall() + } + + def get_primary_key_columns(self, cursor, table_name): + cursor.execute( + "PRAGMA table_info(%s)" % self.connection.ops.quote_name(table_name) + ) + return [name for _, name, *_, pk in cursor.fetchall() if pk] + + def _parse_column_or_constraint_definition(self, tokens, columns): + token = None + is_constraint_definition = None + field_name = None + constraint_name = None + unique = False + unique_columns = [] + check = False + check_columns = [] + braces_deep = 0 + for token in tokens: + if token.match(sqlparse.tokens.Punctuation, "("): + braces_deep += 1 + elif token.match(sqlparse.tokens.Punctuation, ")"): + braces_deep -= 1 + if braces_deep < 0: + # End of columns and constraints for table definition. + break + elif braces_deep == 0 and token.match(sqlparse.tokens.Punctuation, ","): + # End of current column or constraint definition. + break + # Detect column or constraint definition by first token. + if is_constraint_definition is None: + is_constraint_definition = token.match( + sqlparse.tokens.Keyword, "CONSTRAINT" + ) + if is_constraint_definition: + continue + if is_constraint_definition: + # Detect constraint name by second token. + if constraint_name is None: + if token.ttype in (sqlparse.tokens.Name, sqlparse.tokens.Keyword): + constraint_name = token.value + elif token.ttype == sqlparse.tokens.Literal.String.Symbol: + constraint_name = token.value[1:-1] + # Start constraint columns parsing after UNIQUE keyword. + if token.match(sqlparse.tokens.Keyword, "UNIQUE"): + unique = True + unique_braces_deep = braces_deep + elif unique: + if unique_braces_deep == braces_deep: + if unique_columns: + # Stop constraint parsing. + unique = False + continue + if token.ttype in (sqlparse.tokens.Name, sqlparse.tokens.Keyword): + unique_columns.append(token.value) + elif token.ttype == sqlparse.tokens.Literal.String.Symbol: + unique_columns.append(token.value[1:-1]) + else: + # Detect field name by first token. + if field_name is None: + if token.ttype in (sqlparse.tokens.Name, sqlparse.tokens.Keyword): + field_name = token.value + elif token.ttype == sqlparse.tokens.Literal.String.Symbol: + field_name = token.value[1:-1] + if token.match(sqlparse.tokens.Keyword, "UNIQUE"): + unique_columns = [field_name] + # Start constraint columns parsing after CHECK keyword. + if token.match(sqlparse.tokens.Keyword, "CHECK"): + check = True + check_braces_deep = braces_deep + elif check: + if check_braces_deep == braces_deep: + if check_columns: + # Stop constraint parsing. + check = False + continue + if token.ttype in (sqlparse.tokens.Name, sqlparse.tokens.Keyword): + if token.value in columns: + check_columns.append(token.value) + elif token.ttype == sqlparse.tokens.Literal.String.Symbol: + if token.value[1:-1] in columns: + check_columns.append(token.value[1:-1]) + unique_constraint = ( + { + "unique": True, + "columns": unique_columns, + "primary_key": False, + "foreign_key": None, + "check": False, + "index": False, + } + if unique_columns + else None + ) + check_constraint = ( + { + "check": True, + "columns": check_columns, + "primary_key": False, + "unique": False, + "foreign_key": None, + "index": False, + } + if check_columns + else None + ) + return constraint_name, unique_constraint, check_constraint, token + + def _parse_table_constraints(self, sql, columns): + # Check constraint parsing is based of SQLite syntax diagram. + # https://www.sqlite.org/syntaxdiagrams.html#table-constraint + statement = sqlparse.parse(sql)[0] + constraints = {} + unnamed_constrains_index = 0 + tokens = (token for token in statement.flatten() if not token.is_whitespace) + # Go to columns and constraint definition + for token in tokens: + if token.match(sqlparse.tokens.Punctuation, "("): + break + # Parse columns and constraint definition + while True: + ( + constraint_name, + unique, + check, + end_token, + ) = self._parse_column_or_constraint_definition(tokens, columns) + if unique: + if constraint_name: + constraints[constraint_name] = unique + else: + unnamed_constrains_index += 1 + constraints[ + "__unnamed_constraint_%s__" % unnamed_constrains_index + ] = unique + if check: + if constraint_name: + constraints[constraint_name] = check + else: + unnamed_constrains_index += 1 + constraints[ + "__unnamed_constraint_%s__" % unnamed_constrains_index + ] = check + if end_token.match(sqlparse.tokens.Punctuation, ")"): + break + return constraints + + def get_constraints(self, cursor, table_name): + """ + Retrieve any constraints or keys (unique, pk, fk, check, index) across + one or more columns. + """ + constraints = {} + # Find inline check constraints. + try: + table_schema = cursor.execute( + "SELECT sql FROM sqlite_master WHERE type='table' and name=%s" + % (self.connection.ops.quote_name(table_name),) + ).fetchone()[0] + except TypeError: + # table_name is a view. + pass + else: + columns = { + info.name for info in self.get_table_description(cursor, table_name) + } + constraints.update(self._parse_table_constraints(table_schema, columns)) + + # Get the index info + cursor.execute( + "PRAGMA index_list(%s)" % self.connection.ops.quote_name(table_name) + ) + for row in cursor.fetchall(): + # SQLite 3.8.9+ has 5 columns, however older versions only give 3 + # columns. Discard last 2 columns if there. + number, index, unique = row[:3] + cursor.execute( + "SELECT sql FROM sqlite_master " + "WHERE type='index' AND name=%s" % self.connection.ops.quote_name(index) + ) + # There's at most one row. + (sql,) = cursor.fetchone() or (None,) + # Inline constraints are already detected in + # _parse_table_constraints(). The reasons to avoid fetching inline + # constraints from `PRAGMA index_list` are: + # - Inline constraints can have a different name and information + # than what `PRAGMA index_list` gives. + # - Not all inline constraints may appear in `PRAGMA index_list`. + if not sql: + # An inline constraint + continue + # Get the index info for that index + cursor.execute( + "PRAGMA index_info(%s)" % self.connection.ops.quote_name(index) + ) + for index_rank, column_rank, column in cursor.fetchall(): + if index not in constraints: + constraints[index] = { + "columns": [], + "primary_key": False, + "unique": bool(unique), + "foreign_key": None, + "check": False, + "index": True, + } + constraints[index]["columns"].append(column) + # Add type and column orders for indexes + if constraints[index]["index"]: + # SQLite doesn't support any index type other than b-tree + constraints[index]["type"] = Index.suffix + orders = self._get_index_columns_orders(sql) + if orders is not None: + constraints[index]["orders"] = orders + # Get the PK + pk_columns = self.get_primary_key_columns(cursor, table_name) + if pk_columns: + # SQLite doesn't actually give a name to the PK constraint, + # so we invent one. This is fine, as the SQLite backend never + # deletes PK constraints by name, as you can't delete constraints + # in SQLite; we remake the table with a new PK instead. + constraints["__primary__"] = { + "columns": pk_columns, + "primary_key": True, + "unique": False, # It's not actually a unique constraint. + "foreign_key": None, + "check": False, + "index": False, + } + relations = enumerate(self.get_relations(cursor, table_name).items()) + constraints.update( + { + f"fk_{index}": { + "columns": [column_name], + "primary_key": False, + "unique": False, + "foreign_key": (ref_table_name, ref_column_name), + "check": False, + "index": False, + } + for index, (column_name, (ref_column_name, ref_table_name)) in relations + } + ) + return constraints + + def _get_index_columns_orders(self, sql): + tokens = sqlparse.parse(sql)[0] + for token in tokens: + if isinstance(token, sqlparse.sql.Parenthesis): + columns = str(token).strip("()").split(", ") + return ["DESC" if info.endswith("DESC") else "ASC" for info in columns] + return None + + def _get_column_collations(self, cursor, table_name): + row = cursor.execute( + """ + SELECT sql + FROM sqlite_master + WHERE type = 'table' AND name = %s + """, + [table_name], + ).fetchone() + if not row: + return {} + + sql = row[0] + columns = str(sqlparse.parse(sql)[0][-1]).strip("()").split(", ") + collations = {} + for column in columns: + tokens = column[1:].split() + column_name = tokens[0].strip('"') + for index, token in enumerate(tokens): + if token == "COLLATE": + collation = tokens[index + 1] + break + else: + collation = None + collations[column_name] = collation + return collations diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/sqlite3/operations.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/sqlite3/operations.py new file mode 100644 index 0000000..85ad804 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/sqlite3/operations.py @@ -0,0 +1,441 @@ +import datetime +import decimal +import uuid +from functools import lru_cache +from itertools import chain + +from django.conf import settings +from django.core.exceptions import FieldError +from django.db import DatabaseError, NotSupportedError, models +from django.db.backends.base.operations import BaseDatabaseOperations +from django.db.models.constants import OnConflict +from django.db.models.expressions import Col +from django.utils import timezone +from django.utils.dateparse import parse_date, parse_datetime, parse_time +from django.utils.functional import cached_property + + +class DatabaseOperations(BaseDatabaseOperations): + cast_char_field_without_max_length = "text" + cast_data_types = { + "DateField": "TEXT", + "DateTimeField": "TEXT", + } + explain_prefix = "EXPLAIN QUERY PLAN" + # List of datatypes to that cannot be extracted with JSON_EXTRACT() on + # SQLite. Use JSON_TYPE() instead. + jsonfield_datatype_values = frozenset(["null", "false", "true"]) + + def bulk_batch_size(self, fields, objs): + """ + SQLite has a compile-time default (SQLITE_LIMIT_VARIABLE_NUMBER) of + 999 variables per query. + + If there's only a single field to insert, the limit is 500 + (SQLITE_MAX_COMPOUND_SELECT). + """ + if len(fields) == 1: + return 500 + elif len(fields) > 1: + return self.connection.features.max_query_params // len(fields) + else: + return len(objs) + + def check_expression_support(self, expression): + bad_fields = (models.DateField, models.DateTimeField, models.TimeField) + bad_aggregates = (models.Sum, models.Avg, models.Variance, models.StdDev) + if isinstance(expression, bad_aggregates): + for expr in expression.get_source_expressions(): + try: + output_field = expr.output_field + except (AttributeError, FieldError): + # Not every subexpression has an output_field which is fine + # to ignore. + pass + else: + if isinstance(output_field, bad_fields): + raise NotSupportedError( + "You cannot use Sum, Avg, StdDev, and Variance " + "aggregations on date/time fields in sqlite3 " + "since date/time is saved as text." + ) + if ( + isinstance(expression, models.Aggregate) + and expression.distinct + and len(expression.source_expressions) > 1 + ): + raise NotSupportedError( + "SQLite doesn't support DISTINCT on aggregate functions " + "accepting multiple arguments." + ) + + def date_extract_sql(self, lookup_type, sql, params): + """ + Support EXTRACT with a user-defined function django_date_extract() + that's registered in connect(). Use single quotes because this is a + string and could otherwise cause a collision with a field name. + """ + return f"django_date_extract(%s, {sql})", (lookup_type.lower(), *params) + + def fetch_returned_insert_rows(self, cursor): + """ + Given a cursor object that has just performed an INSERT...RETURNING + statement into a table, return the list of returned data. + """ + return cursor.fetchall() + + def format_for_duration_arithmetic(self, sql): + """Do nothing since formatting is handled in the custom function.""" + return sql + + def date_trunc_sql(self, lookup_type, sql, params, tzname=None): + return f"django_date_trunc(%s, {sql}, %s, %s)", ( + lookup_type.lower(), + *params, + *self._convert_tznames_to_sql(tzname), + ) + + def time_trunc_sql(self, lookup_type, sql, params, tzname=None): + return f"django_time_trunc(%s, {sql}, %s, %s)", ( + lookup_type.lower(), + *params, + *self._convert_tznames_to_sql(tzname), + ) + + def _convert_tznames_to_sql(self, tzname): + if tzname and settings.USE_TZ: + return tzname, self.connection.timezone_name + return None, None + + def datetime_cast_date_sql(self, sql, params, tzname): + return f"django_datetime_cast_date({sql}, %s, %s)", ( + *params, + *self._convert_tznames_to_sql(tzname), + ) + + def datetime_cast_time_sql(self, sql, params, tzname): + return f"django_datetime_cast_time({sql}, %s, %s)", ( + *params, + *self._convert_tznames_to_sql(tzname), + ) + + def datetime_extract_sql(self, lookup_type, sql, params, tzname): + return f"django_datetime_extract(%s, {sql}, %s, %s)", ( + lookup_type.lower(), + *params, + *self._convert_tznames_to_sql(tzname), + ) + + def datetime_trunc_sql(self, lookup_type, sql, params, tzname): + return f"django_datetime_trunc(%s, {sql}, %s, %s)", ( + lookup_type.lower(), + *params, + *self._convert_tznames_to_sql(tzname), + ) + + def time_extract_sql(self, lookup_type, sql, params): + return f"django_time_extract(%s, {sql})", (lookup_type.lower(), *params) + + def pk_default_value(self): + return "NULL" + + def _quote_params_for_last_executed_query(self, params): + """ + Only for last_executed_query! Don't use this to execute SQL queries! + """ + # This function is limited both by SQLITE_LIMIT_VARIABLE_NUMBER (the + # number of parameters, default = 999) and SQLITE_MAX_COLUMN (the + # number of return values, default = 2000). Since Python's sqlite3 + # module doesn't expose the get_limit() C API, assume the default + # limits are in effect and split the work in batches if needed. + BATCH_SIZE = 999 + if len(params) > BATCH_SIZE: + results = () + for index in range(0, len(params), BATCH_SIZE): + chunk = params[index : index + BATCH_SIZE] + results += self._quote_params_for_last_executed_query(chunk) + return results + + sql = "SELECT " + ", ".join(["QUOTE(?)"] * len(params)) + # Bypass Django's wrappers and use the underlying sqlite3 connection + # to avoid logging this query - it would trigger infinite recursion. + cursor = self.connection.connection.cursor() + # Native sqlite3 cursors cannot be used as context managers. + try: + return cursor.execute(sql, params).fetchone() + finally: + cursor.close() + + def last_executed_query(self, cursor, sql, params): + # Python substitutes parameters in Modules/_sqlite/cursor.c with: + # bind_parameters(state, self->statement, parameters); + # Unfortunately there is no way to reach self->statement from Python, + # so we quote and substitute parameters manually. + if params: + if isinstance(params, (list, tuple)): + params = self._quote_params_for_last_executed_query(params) + else: + values = tuple(params.values()) + values = self._quote_params_for_last_executed_query(values) + params = dict(zip(params, values)) + return sql % params + # For consistency with SQLiteCursorWrapper.execute(), just return sql + # when there are no parameters. See #13648 and #17158. + else: + return sql + + def quote_name(self, name): + if name.startswith('"') and name.endswith('"'): + return name # Quoting once is enough. + return '"%s"' % name + + def no_limit_value(self): + return -1 + + def __references_graph(self, table_name): + query = """ + WITH tables AS ( + SELECT %s name + UNION + SELECT sqlite_master.name + FROM sqlite_master + JOIN tables ON (sql REGEXP %s || tables.name || %s) + ) SELECT name FROM tables; + """ + params = ( + table_name, + r'(?i)\s+references\s+("|\')?', + r'("|\')?\s*\(', + ) + with self.connection.cursor() as cursor: + results = cursor.execute(query, params) + return [row[0] for row in results.fetchall()] + + @cached_property + def _references_graph(self): + # 512 is large enough to fit the ~330 tables (as of this writing) in + # Django's test suite. + return lru_cache(maxsize=512)(self.__references_graph) + + def sql_flush(self, style, tables, *, reset_sequences=False, allow_cascade=False): + if tables and allow_cascade: + # Simulate TRUNCATE CASCADE by recursively collecting the tables + # referencing the tables to be flushed. + tables = set( + chain.from_iterable(self._references_graph(table) for table in tables) + ) + sql = [ + "%s %s %s;" + % ( + style.SQL_KEYWORD("DELETE"), + style.SQL_KEYWORD("FROM"), + style.SQL_FIELD(self.quote_name(table)), + ) + for table in tables + ] + if reset_sequences: + sequences = [{"table": table} for table in tables] + sql.extend(self.sequence_reset_by_name_sql(style, sequences)) + return sql + + def sequence_reset_by_name_sql(self, style, sequences): + if not sequences: + return [] + return [ + "%s %s %s %s = 0 %s %s %s (%s);" + % ( + style.SQL_KEYWORD("UPDATE"), + style.SQL_TABLE(self.quote_name("sqlite_sequence")), + style.SQL_KEYWORD("SET"), + style.SQL_FIELD(self.quote_name("seq")), + style.SQL_KEYWORD("WHERE"), + style.SQL_FIELD(self.quote_name("name")), + style.SQL_KEYWORD("IN"), + ", ".join( + ["'%s'" % sequence_info["table"] for sequence_info in sequences] + ), + ), + ] + + def adapt_datetimefield_value(self, value): + if value is None: + return None + + # Expression values are adapted by the database. + if hasattr(value, "resolve_expression"): + return value + + # SQLite doesn't support tz-aware datetimes + if timezone.is_aware(value): + if settings.USE_TZ: + value = timezone.make_naive(value, self.connection.timezone) + else: + raise ValueError( + "SQLite backend does not support timezone-aware datetimes when " + "USE_TZ is False." + ) + + return str(value) + + def adapt_timefield_value(self, value): + if value is None: + return None + + # Expression values are adapted by the database. + if hasattr(value, "resolve_expression"): + return value + + # SQLite doesn't support tz-aware datetimes + if timezone.is_aware(value): + raise ValueError("SQLite backend does not support timezone-aware times.") + + return str(value) + + def get_db_converters(self, expression): + converters = super().get_db_converters(expression) + internal_type = expression.output_field.get_internal_type() + if internal_type == "DateTimeField": + converters.append(self.convert_datetimefield_value) + elif internal_type == "DateField": + converters.append(self.convert_datefield_value) + elif internal_type == "TimeField": + converters.append(self.convert_timefield_value) + elif internal_type == "DecimalField": + converters.append(self.get_decimalfield_converter(expression)) + elif internal_type == "UUIDField": + converters.append(self.convert_uuidfield_value) + elif internal_type == "BooleanField": + converters.append(self.convert_booleanfield_value) + return converters + + def convert_datetimefield_value(self, value, expression, connection): + if value is not None: + if not isinstance(value, datetime.datetime): + value = parse_datetime(value) + if settings.USE_TZ and not timezone.is_aware(value): + value = timezone.make_aware(value, self.connection.timezone) + return value + + def convert_datefield_value(self, value, expression, connection): + if value is not None: + if not isinstance(value, datetime.date): + value = parse_date(value) + return value + + def convert_timefield_value(self, value, expression, connection): + if value is not None: + if not isinstance(value, datetime.time): + value = parse_time(value) + return value + + def get_decimalfield_converter(self, expression): + # SQLite stores only 15 significant digits. Digits coming from + # float inaccuracy must be removed. + create_decimal = decimal.Context(prec=15).create_decimal_from_float + if isinstance(expression, Col): + quantize_value = decimal.Decimal(1).scaleb( + -expression.output_field.decimal_places + ) + + def converter(value, expression, connection): + if value is not None: + return create_decimal(value).quantize( + quantize_value, context=expression.output_field.context + ) + + else: + + def converter(value, expression, connection): + if value is not None: + return create_decimal(value) + + return converter + + def convert_uuidfield_value(self, value, expression, connection): + if value is not None: + value = uuid.UUID(value) + return value + + def convert_booleanfield_value(self, value, expression, connection): + return bool(value) if value in (1, 0) else value + + def bulk_insert_sql(self, fields, placeholder_rows): + placeholder_rows_sql = (", ".join(row) for row in placeholder_rows) + values_sql = ", ".join(f"({sql})" for sql in placeholder_rows_sql) + return f"VALUES {values_sql}" + + def combine_expression(self, connector, sub_expressions): + # SQLite doesn't have a ^ operator, so use the user-defined POWER + # function that's registered in connect(). + if connector == "^": + return "POWER(%s)" % ",".join(sub_expressions) + elif connector == "#": + return "BITXOR(%s)" % ",".join(sub_expressions) + return super().combine_expression(connector, sub_expressions) + + def combine_duration_expression(self, connector, sub_expressions): + if connector not in ["+", "-", "*", "/"]: + raise DatabaseError("Invalid connector for timedelta: %s." % connector) + fn_params = ["'%s'" % connector] + sub_expressions + if len(fn_params) > 3: + raise ValueError("Too many params for timedelta operations.") + return "django_format_dtdelta(%s)" % ", ".join(fn_params) + + def integer_field_range(self, internal_type): + # SQLite doesn't enforce any integer constraints, but sqlite3 supports + # integers up to 64 bits. + if internal_type in [ + "PositiveBigIntegerField", + "PositiveIntegerField", + "PositiveSmallIntegerField", + ]: + return (0, 9223372036854775807) + return (-9223372036854775808, 9223372036854775807) + + def subtract_temporals(self, internal_type, lhs, rhs): + lhs_sql, lhs_params = lhs + rhs_sql, rhs_params = rhs + params = (*lhs_params, *rhs_params) + if internal_type == "TimeField": + return "django_time_diff(%s, %s)" % (lhs_sql, rhs_sql), params + return "django_timestamp_diff(%s, %s)" % (lhs_sql, rhs_sql), params + + def insert_statement(self, on_conflict=None): + if on_conflict == OnConflict.IGNORE: + return "INSERT OR IGNORE INTO" + return super().insert_statement(on_conflict=on_conflict) + + def return_insert_columns(self, fields): + # SQLite < 3.35 doesn't support an INSERT...RETURNING statement. + if not fields: + return "", () + columns = [ + "%s.%s" + % ( + self.quote_name(field.model._meta.db_table), + self.quote_name(field.column), + ) + for field in fields + ] + return "RETURNING %s" % ", ".join(columns), () + + def on_conflict_suffix_sql(self, fields, on_conflict, update_fields, unique_fields): + if ( + on_conflict == OnConflict.UPDATE + and self.connection.features.supports_update_conflicts_with_target + ): + return "ON CONFLICT(%s) DO UPDATE SET %s" % ( + ", ".join(map(self.quote_name, unique_fields)), + ", ".join( + [ + f"{field} = EXCLUDED.{field}" + for field in map(self.quote_name, update_fields) + ] + ), + ) + return super().on_conflict_suffix_sql( + fields, + on_conflict, + update_fields, + unique_fields, + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/sqlite3/schema.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/sqlite3/schema.py new file mode 100644 index 0000000..c25c953 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/sqlite3/schema.py @@ -0,0 +1,493 @@ +import copy +from decimal import Decimal + +from django.apps.registry import Apps +from django.db import NotSupportedError +from django.db.backends.base.schema import BaseDatabaseSchemaEditor +from django.db.backends.ddl_references import Statement +from django.db.backends.utils import strip_quotes +from django.db.models import NOT_PROVIDED, UniqueConstraint + + +class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): + sql_delete_table = "DROP TABLE %(table)s" + sql_create_fk = None + sql_create_inline_fk = ( + "REFERENCES %(to_table)s (%(to_column)s) DEFERRABLE INITIALLY DEFERRED" + ) + sql_create_column_inline_fk = sql_create_inline_fk + sql_delete_column = "ALTER TABLE %(table)s DROP COLUMN %(column)s" + sql_create_unique = "CREATE UNIQUE INDEX %(name)s ON %(table)s (%(columns)s)" + sql_delete_unique = "DROP INDEX %(name)s" + sql_alter_table_comment = None + sql_alter_column_comment = None + + def __enter__(self): + # Some SQLite schema alterations need foreign key constraints to be + # disabled. Enforce it here for the duration of the schema edition. + if not self.connection.disable_constraint_checking(): + raise NotSupportedError( + "SQLite schema editor cannot be used while foreign key " + "constraint checks are enabled. Make sure to disable them " + "before entering a transaction.atomic() context because " + "SQLite does not support disabling them in the middle of " + "a multi-statement transaction." + ) + return super().__enter__() + + def __exit__(self, exc_type, exc_value, traceback): + self.connection.check_constraints() + super().__exit__(exc_type, exc_value, traceback) + self.connection.enable_constraint_checking() + + def quote_value(self, value): + # The backend "mostly works" without this function and there are use + # cases for compiling Python without the sqlite3 libraries (e.g. + # security hardening). + try: + import sqlite3 + + value = sqlite3.adapt(value) + except ImportError: + pass + except sqlite3.ProgrammingError: + pass + # Manual emulation of SQLite parameter quoting + if isinstance(value, bool): + return str(int(value)) + elif isinstance(value, (Decimal, float, int)): + return str(value) + elif isinstance(value, str): + return "'%s'" % value.replace("'", "''") + elif value is None: + return "NULL" + elif isinstance(value, (bytes, bytearray, memoryview)): + # Bytes are only allowed for BLOB fields, encoded as string + # literals containing hexadecimal data and preceded by a single "X" + # character. + return "X'%s'" % value.hex() + else: + raise ValueError( + "Cannot quote parameter value %r of type %s" % (value, type(value)) + ) + + def prepare_default(self, value): + return self.quote_value(value) + + def _remake_table( + self, model, create_field=None, delete_field=None, alter_fields=None + ): + """ + Shortcut to transform a model from old_model into new_model + + This follows the correct procedure to perform non-rename or column + addition operations based on SQLite's documentation + + https://www.sqlite.org/lang_altertable.html#caution + + The essential steps are: + 1. Create a table with the updated definition called "new__app_model" + 2. Copy the data from the existing "app_model" table to the new table + 3. Drop the "app_model" table + 4. Rename the "new__app_model" table to "app_model" + 5. Restore any index of the previous "app_model" table. + """ + + # Self-referential fields must be recreated rather than copied from + # the old model to ensure their remote_field.field_name doesn't refer + # to an altered field. + def is_self_referential(f): + return f.is_relation and f.remote_field.model is model + + # Work out the new fields dict / mapping + body = { + f.name: f.clone() if is_self_referential(f) else f + for f in model._meta.local_concrete_fields + } + # Since mapping might mix column names and default values, + # its values must be already quoted. + mapping = { + f.column: self.quote_name(f.column) + for f in model._meta.local_concrete_fields + if f.generated is False + } + # This maps field names (not columns) for things like unique_together + rename_mapping = {} + # If any of the new or altered fields is introducing a new PK, + # remove the old one + restore_pk_field = None + alter_fields = alter_fields or [] + if getattr(create_field, "primary_key", False) or any( + getattr(new_field, "primary_key", False) for _, new_field in alter_fields + ): + for name, field in list(body.items()): + if field.primary_key and not any( + # Do not remove the old primary key when an altered field + # that introduces a primary key is the same field. + name == new_field.name + for _, new_field in alter_fields + ): + field.primary_key = False + restore_pk_field = field + if field.auto_created: + del body[name] + del mapping[field.column] + # Add in any created fields + if create_field: + body[create_field.name] = create_field + # Choose a default and insert it into the copy map + if ( + create_field.db_default is NOT_PROVIDED + and not (create_field.many_to_many or create_field.generated) + and create_field.concrete + ): + mapping[create_field.column] = self.prepare_default( + self.effective_default(create_field) + ) + # Add in any altered fields + for alter_field in alter_fields: + old_field, new_field = alter_field + body.pop(old_field.name, None) + mapping.pop(old_field.column, None) + body[new_field.name] = new_field + if old_field.null and not new_field.null: + if new_field.db_default is NOT_PROVIDED: + default = self.prepare_default(self.effective_default(new_field)) + else: + default, _ = self.db_default_sql(new_field) + case_sql = "coalesce(%(col)s, %(default)s)" % { + "col": self.quote_name(old_field.column), + "default": default, + } + mapping[new_field.column] = case_sql + else: + mapping[new_field.column] = self.quote_name(old_field.column) + rename_mapping[old_field.name] = new_field.name + # Remove any deleted fields + if delete_field: + del body[delete_field.name] + mapping.pop(delete_field.column, None) + # Remove any implicit M2M tables + if ( + delete_field.many_to_many + and delete_field.remote_field.through._meta.auto_created + ): + return self.delete_model(delete_field.remote_field.through) + # Work inside a new app registry + apps = Apps() + + # Work out the new value of unique_together, taking renames into + # account + unique_together = [ + [rename_mapping.get(n, n) for n in unique] + for unique in model._meta.unique_together + ] + + # RemovedInDjango51Warning. + # Work out the new value for index_together, taking renames into + # account + index_together = [ + [rename_mapping.get(n, n) for n in index] + for index in model._meta.index_together + ] + + indexes = model._meta.indexes + if delete_field: + indexes = [ + index for index in indexes if delete_field.name not in index.fields + ] + + constraints = list(model._meta.constraints) + + # Provide isolated instances of the fields to the new model body so + # that the existing model's internals aren't interfered with when + # the dummy model is constructed. + body_copy = copy.deepcopy(body) + + # Construct a new model with the new fields to allow self referential + # primary key to resolve to. This model won't ever be materialized as a + # table and solely exists for foreign key reference resolution purposes. + # This wouldn't be required if the schema editor was operating on model + # states instead of rendered models. + meta_contents = { + "app_label": model._meta.app_label, + "db_table": model._meta.db_table, + "unique_together": unique_together, + "index_together": index_together, # RemovedInDjango51Warning. + "indexes": indexes, + "constraints": constraints, + "apps": apps, + } + meta = type("Meta", (), meta_contents) + body_copy["Meta"] = meta + body_copy["__module__"] = model.__module__ + type(model._meta.object_name, model.__bases__, body_copy) + + # Construct a model with a renamed table name. + body_copy = copy.deepcopy(body) + meta_contents = { + "app_label": model._meta.app_label, + "db_table": "new__%s" % strip_quotes(model._meta.db_table), + "unique_together": unique_together, + "index_together": index_together, # RemovedInDjango51Warning. + "indexes": indexes, + "constraints": constraints, + "apps": apps, + } + meta = type("Meta", (), meta_contents) + body_copy["Meta"] = meta + body_copy["__module__"] = model.__module__ + new_model = type("New%s" % model._meta.object_name, model.__bases__, body_copy) + + # Create a new table with the updated schema. + self.create_model(new_model) + + # Copy data from the old table into the new table + self.execute( + "INSERT INTO %s (%s) SELECT %s FROM %s" + % ( + self.quote_name(new_model._meta.db_table), + ", ".join(self.quote_name(x) for x in mapping), + ", ".join(mapping.values()), + self.quote_name(model._meta.db_table), + ) + ) + + # Delete the old table to make way for the new + self.delete_model(model, handle_autom2m=False) + + # Rename the new table to take way for the old + self.alter_db_table( + new_model, + new_model._meta.db_table, + model._meta.db_table, + ) + + # Run deferred SQL on correct table + for sql in self.deferred_sql: + self.execute(sql) + self.deferred_sql = [] + # Fix any PK-removed field + if restore_pk_field: + restore_pk_field.primary_key = True + + def delete_model(self, model, handle_autom2m=True): + if handle_autom2m: + super().delete_model(model) + else: + # Delete the table (and only that) + self.execute( + self.sql_delete_table + % { + "table": self.quote_name(model._meta.db_table), + } + ) + # Remove all deferred statements referencing the deleted table. + for sql in list(self.deferred_sql): + if isinstance(sql, Statement) and sql.references_table( + model._meta.db_table + ): + self.deferred_sql.remove(sql) + + def add_field(self, model, field): + """Create a field on a model.""" + from django.db.models.expressions import Value + + # Special-case implicit M2M tables. + if field.many_to_many and field.remote_field.through._meta.auto_created: + self.create_model(field.remote_field.through) + elif ( + # Primary keys and unique fields are not supported in ALTER TABLE + # ADD COLUMN. + field.primary_key + or field.unique + or not field.null + # Fields with default values cannot by handled by ALTER TABLE ADD + # COLUMN statement because DROP DEFAULT is not supported in + # ALTER TABLE. + or self.effective_default(field) is not None + # Fields with non-constant defaults cannot by handled by ALTER + # TABLE ADD COLUMN statement. + or ( + field.db_default is not NOT_PROVIDED + and not isinstance(field.db_default, Value) + ) + ): + self._remake_table(model, create_field=field) + else: + super().add_field(model, field) + + def remove_field(self, model, field): + """ + Remove a field from a model. Usually involves deleting a column, + but for M2Ms may involve deleting a table. + """ + # M2M fields are a special case + if field.many_to_many: + # For implicit M2M tables, delete the auto-created table + if field.remote_field.through._meta.auto_created: + self.delete_model(field.remote_field.through) + # For explicit "through" M2M fields, do nothing + elif ( + self.connection.features.can_alter_table_drop_column + # Primary keys, unique fields, indexed fields, and foreign keys are + # not supported in ALTER TABLE DROP COLUMN. + and not field.primary_key + and not field.unique + and not field.db_index + and not (field.remote_field and field.db_constraint) + ): + super().remove_field(model, field) + # For everything else, remake. + else: + # It might not actually have a column behind it + if field.db_parameters(connection=self.connection)["type"] is None: + return + self._remake_table(model, delete_field=field) + + def _alter_field( + self, + model, + old_field, + new_field, + old_type, + new_type, + old_db_params, + new_db_params, + strict=False, + ): + """Perform a "physical" (non-ManyToMany) field update.""" + # Use "ALTER TABLE ... RENAME COLUMN" if only the column name + # changed and there aren't any constraints. + if ( + old_field.column != new_field.column + and self.column_sql(model, old_field) == self.column_sql(model, new_field) + and not ( + old_field.remote_field + and old_field.db_constraint + or new_field.remote_field + and new_field.db_constraint + ) + ): + return self.execute( + self._rename_field_sql( + model._meta.db_table, old_field, new_field, new_type + ) + ) + # Alter by remaking table + self._remake_table(model, alter_fields=[(old_field, new_field)]) + # Rebuild tables with FKs pointing to this field. + old_collation = old_db_params.get("collation") + new_collation = new_db_params.get("collation") + if new_field.unique and ( + old_type != new_type or old_collation != new_collation + ): + related_models = set() + opts = new_field.model._meta + for remote_field in opts.related_objects: + # Ignore self-relationship since the table was already rebuilt. + if remote_field.related_model == model: + continue + if not remote_field.many_to_many: + if remote_field.field_name == new_field.name: + related_models.add(remote_field.related_model) + elif new_field.primary_key and remote_field.through._meta.auto_created: + related_models.add(remote_field.through) + if new_field.primary_key: + for many_to_many in opts.many_to_many: + # Ignore self-relationship since the table was already rebuilt. + if many_to_many.related_model == model: + continue + if many_to_many.remote_field.through._meta.auto_created: + related_models.add(many_to_many.remote_field.through) + for related_model in related_models: + self._remake_table(related_model) + + def _alter_many_to_many(self, model, old_field, new_field, strict): + """Alter M2Ms to repoint their to= endpoints.""" + if ( + old_field.remote_field.through._meta.db_table + == new_field.remote_field.through._meta.db_table + ): + # The field name didn't change, but some options did, so we have to + # propagate this altering. + self._remake_table( + old_field.remote_field.through, + alter_fields=[ + ( + # The field that points to the target model is needed, + # so that table can be remade with the new m2m field - + # this is m2m_reverse_field_name(). + old_field.remote_field.through._meta.get_field( + old_field.m2m_reverse_field_name() + ), + new_field.remote_field.through._meta.get_field( + new_field.m2m_reverse_field_name() + ), + ), + ( + # The field that points to the model itself is needed, + # so that table can be remade with the new self field - + # this is m2m_field_name(). + old_field.remote_field.through._meta.get_field( + old_field.m2m_field_name() + ), + new_field.remote_field.through._meta.get_field( + new_field.m2m_field_name() + ), + ), + ], + ) + return + + # Make a new through table + self.create_model(new_field.remote_field.through) + # Copy the data across + self.execute( + "INSERT INTO %s (%s) SELECT %s FROM %s" + % ( + self.quote_name(new_field.remote_field.through._meta.db_table), + ", ".join( + [ + "id", + new_field.m2m_column_name(), + new_field.m2m_reverse_name(), + ] + ), + ", ".join( + [ + "id", + old_field.m2m_column_name(), + old_field.m2m_reverse_name(), + ] + ), + self.quote_name(old_field.remote_field.through._meta.db_table), + ) + ) + # Delete the old through table + self.delete_model(old_field.remote_field.through) + + def add_constraint(self, model, constraint): + if isinstance(constraint, UniqueConstraint) and ( + constraint.condition + or constraint.contains_expressions + or constraint.include + or constraint.deferrable + ): + super().add_constraint(model, constraint) + else: + self._remake_table(model) + + def remove_constraint(self, model, constraint): + if isinstance(constraint, UniqueConstraint) and ( + constraint.condition + or constraint.contains_expressions + or constraint.include + or constraint.deferrable + ): + super().remove_constraint(model, constraint) + else: + self._remake_table(model) + + def _collate_sql(self, collation): + return "COLLATE " + collation diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/utils.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/utils.py new file mode 100644 index 0000000..f363253 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/backends/utils.py @@ -0,0 +1,340 @@ +import datetime +import decimal +import functools +import logging +import time +import warnings +from contextlib import contextmanager +from hashlib import md5 + +from django.apps import apps +from django.db import NotSupportedError +from django.utils.dateparse import parse_time + +logger = logging.getLogger("django.db.backends") + + +class CursorWrapper: + def __init__(self, cursor, db): + self.cursor = cursor + self.db = db + + WRAP_ERROR_ATTRS = frozenset(["fetchone", "fetchmany", "fetchall", "nextset"]) + + APPS_NOT_READY_WARNING_MSG = ( + "Accessing the database during app initialization is discouraged. To fix this " + "warning, avoid executing queries in AppConfig.ready() or when your app " + "modules are imported." + ) + + def __getattr__(self, attr): + cursor_attr = getattr(self.cursor, attr) + if attr in CursorWrapper.WRAP_ERROR_ATTRS: + return self.db.wrap_database_errors(cursor_attr) + else: + return cursor_attr + + def __iter__(self): + with self.db.wrap_database_errors: + yield from self.cursor + + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + # Close instead of passing through to avoid backend-specific behavior + # (#17671). Catch errors liberally because errors in cleanup code + # aren't useful. + try: + self.close() + except self.db.Database.Error: + pass + + # The following methods cannot be implemented in __getattr__, because the + # code must run when the method is invoked, not just when it is accessed. + + def callproc(self, procname, params=None, kparams=None): + # Keyword parameters for callproc aren't supported in PEP 249, but the + # database driver may support them (e.g. oracledb). + if kparams is not None and not self.db.features.supports_callproc_kwargs: + raise NotSupportedError( + "Keyword parameters for callproc are not supported on this " + "database backend." + ) + # Raise a warning during app initialization (stored_app_configs is only + # ever set during testing). + if not apps.ready and not apps.stored_app_configs: + warnings.warn(self.APPS_NOT_READY_WARNING_MSG, category=RuntimeWarning) + self.db.validate_no_broken_transaction() + with self.db.wrap_database_errors: + if params is None and kparams is None: + return self.cursor.callproc(procname) + elif kparams is None: + return self.cursor.callproc(procname, params) + else: + params = params or () + return self.cursor.callproc(procname, params, kparams) + + def execute(self, sql, params=None): + return self._execute_with_wrappers( + sql, params, many=False, executor=self._execute + ) + + def executemany(self, sql, param_list): + return self._execute_with_wrappers( + sql, param_list, many=True, executor=self._executemany + ) + + def _execute_with_wrappers(self, sql, params, many, executor): + context = {"connection": self.db, "cursor": self} + for wrapper in reversed(self.db.execute_wrappers): + executor = functools.partial(wrapper, executor) + return executor(sql, params, many, context) + + def _execute(self, sql, params, *ignored_wrapper_args): + # Raise a warning during app initialization (stored_app_configs is only + # ever set during testing). + if not apps.ready and not apps.stored_app_configs: + warnings.warn(self.APPS_NOT_READY_WARNING_MSG, category=RuntimeWarning) + self.db.validate_no_broken_transaction() + with self.db.wrap_database_errors: + if params is None: + # params default might be backend specific. + return self.cursor.execute(sql) + else: + return self.cursor.execute(sql, params) + + def _executemany(self, sql, param_list, *ignored_wrapper_args): + # Raise a warning during app initialization (stored_app_configs is only + # ever set during testing). + if not apps.ready and not apps.stored_app_configs: + warnings.warn(self.APPS_NOT_READY_WARNING_MSG, category=RuntimeWarning) + self.db.validate_no_broken_transaction() + with self.db.wrap_database_errors: + return self.cursor.executemany(sql, param_list) + + +class CursorDebugWrapper(CursorWrapper): + # XXX callproc isn't instrumented at this time. + + def execute(self, sql, params=None): + with self.debug_sql(sql, params, use_last_executed_query=True): + return super().execute(sql, params) + + def executemany(self, sql, param_list): + with self.debug_sql(sql, param_list, many=True): + return super().executemany(sql, param_list) + + @contextmanager + def debug_sql( + self, sql=None, params=None, use_last_executed_query=False, many=False + ): + start = time.monotonic() + try: + yield + finally: + stop = time.monotonic() + duration = stop - start + if use_last_executed_query: + sql = self.db.ops.last_executed_query(self.cursor, sql, params) + try: + times = len(params) if many else "" + except TypeError: + # params could be an iterator. + times = "?" + self.db.queries_log.append( + { + "sql": "%s times: %s" % (times, sql) if many else sql, + "time": "%.3f" % duration, + } + ) + logger.debug( + "(%.3f) %s; args=%s; alias=%s", + duration, + sql, + params, + self.db.alias, + extra={ + "duration": duration, + "sql": sql, + "params": params, + "alias": self.db.alias, + }, + ) + + +@contextmanager +def debug_transaction(connection, sql): + start = time.monotonic() + try: + yield + finally: + if connection.queries_logged: + stop = time.monotonic() + duration = stop - start + connection.queries_log.append( + { + "sql": "%s" % sql, + "time": "%.3f" % duration, + } + ) + logger.debug( + "(%.3f) %s; args=%s; alias=%s", + duration, + sql, + None, + connection.alias, + extra={ + "duration": duration, + "sql": sql, + "alias": connection.alias, + }, + ) + + +def split_tzname_delta(tzname): + """ + Split a time zone name into a 3-tuple of (name, sign, offset). + """ + for sign in ["+", "-"]: + if sign in tzname: + name, offset = tzname.rsplit(sign, 1) + if offset and parse_time(offset): + return name, sign, offset + return tzname, None, None + + +############################################### +# Converters from database (string) to Python # +############################################### + + +def typecast_date(s): + return ( + datetime.date(*map(int, s.split("-"))) if s else None + ) # return None if s is null + + +def typecast_time(s): # does NOT store time zone information + if not s: + return None + hour, minutes, seconds = s.split(":") + if "." in seconds: # check whether seconds have a fractional part + seconds, microseconds = seconds.split(".") + else: + microseconds = "0" + return datetime.time( + int(hour), int(minutes), int(seconds), int((microseconds + "000000")[:6]) + ) + + +def typecast_timestamp(s): # does NOT store time zone information + # "2005-07-29 15:48:00.590358-05" + # "2005-07-29 09:56:00-05" + if not s: + return None + if " " not in s: + return typecast_date(s) + d, t = s.split() + # Remove timezone information. + if "-" in t: + t, _ = t.split("-", 1) + elif "+" in t: + t, _ = t.split("+", 1) + dates = d.split("-") + times = t.split(":") + seconds = times[2] + if "." in seconds: # check whether seconds have a fractional part + seconds, microseconds = seconds.split(".") + else: + microseconds = "0" + return datetime.datetime( + int(dates[0]), + int(dates[1]), + int(dates[2]), + int(times[0]), + int(times[1]), + int(seconds), + int((microseconds + "000000")[:6]), + ) + + +############################################### +# Converters from Python to database (string) # +############################################### + + +def split_identifier(identifier): + """ + Split an SQL identifier into a two element tuple of (namespace, name). + + The identifier could be a table, column, or sequence name might be prefixed + by a namespace. + """ + try: + namespace, name = identifier.split('"."') + except ValueError: + namespace, name = "", identifier + return namespace.strip('"'), name.strip('"') + + +def truncate_name(identifier, length=None, hash_len=4): + """ + Shorten an SQL identifier to a repeatable mangled version with the given + length. + + If a quote stripped name contains a namespace, e.g. USERNAME"."TABLE, + truncate the table portion only. + """ + namespace, name = split_identifier(identifier) + + if length is None or len(name) <= length: + return identifier + + digest = names_digest(name, length=hash_len) + return "%s%s%s" % ( + '%s"."' % namespace if namespace else "", + name[: length - hash_len], + digest, + ) + + +def names_digest(*args, length): + """ + Generate a 32-bit digest of a set of arguments that can be used to shorten + identifying names. + """ + h = md5(usedforsecurity=False) + for arg in args: + h.update(arg.encode()) + return h.hexdigest()[:length] + + +def format_number(value, max_digits, decimal_places): + """ + Format a number into a string with the requisite number of digits and + decimal places. + """ + if value is None: + return None + context = decimal.getcontext().copy() + if max_digits is not None: + context.prec = max_digits + if decimal_places is not None: + value = value.quantize( + decimal.Decimal(1).scaleb(-decimal_places), context=context + ) + else: + context.traps[decimal.Rounded] = 1 + value = context.create_decimal(value) + return "{:f}".format(value) + + +def strip_quotes(table_name): + """ + Strip quotes off of quoted table names to make them safe for use in index + names, sequence names, etc. For example '"USER"."TABLE"' (an Oracle naming + scheme) becomes 'USER"."TABLE'. + """ + has_quotes = table_name.startswith('"') and table_name.endswith('"') + return table_name[1:-1] if has_quotes else table_name diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/__init__.py new file mode 100644 index 0000000..e7f3d2d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/__init__.py @@ -0,0 +1,2 @@ +from .migration import Migration, swappable_dependency # NOQA +from .operations import * # NOQA diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/autodetector.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/autodetector.py new file mode 100644 index 0000000..3a0ee51 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/autodetector.py @@ -0,0 +1,1779 @@ +import functools +import re +from collections import defaultdict +from graphlib import TopologicalSorter +from itertools import chain + +from django.conf import settings +from django.db import models +from django.db.migrations import operations +from django.db.migrations.migration import Migration +from django.db.migrations.operations.models import AlterModelOptions +from django.db.migrations.optimizer import MigrationOptimizer +from django.db.migrations.questioner import MigrationQuestioner +from django.db.migrations.utils import ( + COMPILED_REGEX_TYPE, + RegexObject, + resolve_relation, +) + + +class MigrationAutodetector: + """ + Take a pair of ProjectStates and compare them to see what the first would + need doing to make it match the second (the second usually being the + project's current state). + + Note that this naturally operates on entire projects at a time, + as it's likely that changes interact (for example, you can't + add a ForeignKey without having a migration to add the table it + depends on first). A user interface may offer single-app usage + if it wishes, with the caveat that it may not always be possible. + """ + + def __init__(self, from_state, to_state, questioner=None): + self.from_state = from_state + self.to_state = to_state + self.questioner = questioner or MigrationQuestioner() + self.existing_apps = {app for app, model in from_state.models} + + def changes(self, graph, trim_to_apps=None, convert_apps=None, migration_name=None): + """ + Main entry point to produce a list of applicable changes. + Take a graph to base names on and an optional set of apps + to try and restrict to (restriction is not guaranteed) + """ + changes = self._detect_changes(convert_apps, graph) + changes = self.arrange_for_graph(changes, graph, migration_name) + if trim_to_apps: + changes = self._trim_to_apps(changes, trim_to_apps) + return changes + + def deep_deconstruct(self, obj): + """ + Recursive deconstruction for a field and its arguments. + Used for full comparison for rename/alter; sometimes a single-level + deconstruction will not compare correctly. + """ + if isinstance(obj, list): + return [self.deep_deconstruct(value) for value in obj] + elif isinstance(obj, tuple): + return tuple(self.deep_deconstruct(value) for value in obj) + elif isinstance(obj, dict): + return {key: self.deep_deconstruct(value) for key, value in obj.items()} + elif isinstance(obj, functools.partial): + return ( + obj.func, + self.deep_deconstruct(obj.args), + self.deep_deconstruct(obj.keywords), + ) + elif isinstance(obj, COMPILED_REGEX_TYPE): + return RegexObject(obj) + elif isinstance(obj, type): + # If this is a type that implements 'deconstruct' as an instance method, + # avoid treating this as being deconstructible itself - see #22951 + return obj + elif hasattr(obj, "deconstruct"): + deconstructed = obj.deconstruct() + if isinstance(obj, models.Field): + # we have a field which also returns a name + deconstructed = deconstructed[1:] + path, args, kwargs = deconstructed + return ( + path, + [self.deep_deconstruct(value) for value in args], + {key: self.deep_deconstruct(value) for key, value in kwargs.items()}, + ) + else: + return obj + + def only_relation_agnostic_fields(self, fields): + """ + Return a definition of the fields that ignores field names and + what related fields actually relate to. Used for detecting renames (as + the related fields change during renames). + """ + fields_def = [] + for name, field in sorted(fields.items()): + deconstruction = self.deep_deconstruct(field) + if field.remote_field and field.remote_field.model: + deconstruction[2].pop("to", None) + fields_def.append(deconstruction) + return fields_def + + def _detect_changes(self, convert_apps=None, graph=None): + """ + Return a dict of migration plans which will achieve the + change from from_state to to_state. The dict has app labels + as keys and a list of migrations as values. + + The resulting migrations aren't specially named, but the names + do matter for dependencies inside the set. + + convert_apps is the list of apps to convert to use migrations + (i.e. to make initial migrations for, in the usual case) + + graph is an optional argument that, if provided, can help improve + dependency generation and avoid potential circular dependencies. + """ + # The first phase is generating all the operations for each app + # and gathering them into a big per-app list. + # Then go through that list, order it, and split into migrations to + # resolve dependencies caused by M2Ms and FKs. + self.generated_operations = {} + self.altered_indexes = {} + self.altered_constraints = {} + self.renamed_fields = {} + + # Prepare some old/new state and model lists, separating + # proxy models and ignoring unmigrated apps. + self.old_model_keys = set() + self.old_proxy_keys = set() + self.old_unmanaged_keys = set() + self.new_model_keys = set() + self.new_proxy_keys = set() + self.new_unmanaged_keys = set() + for (app_label, model_name), model_state in self.from_state.models.items(): + if not model_state.options.get("managed", True): + self.old_unmanaged_keys.add((app_label, model_name)) + elif app_label not in self.from_state.real_apps: + if model_state.options.get("proxy"): + self.old_proxy_keys.add((app_label, model_name)) + else: + self.old_model_keys.add((app_label, model_name)) + + for (app_label, model_name), model_state in self.to_state.models.items(): + if not model_state.options.get("managed", True): + self.new_unmanaged_keys.add((app_label, model_name)) + elif app_label not in self.from_state.real_apps or ( + convert_apps and app_label in convert_apps + ): + if model_state.options.get("proxy"): + self.new_proxy_keys.add((app_label, model_name)) + else: + self.new_model_keys.add((app_label, model_name)) + + self.from_state.resolve_fields_and_relations() + self.to_state.resolve_fields_and_relations() + + # Renames have to come first + self.generate_renamed_models() + + # Prepare lists of fields and generate through model map + self._prepare_field_lists() + self._generate_through_model_map() + + # Generate non-rename model operations + self.generate_deleted_models() + self.generate_created_models() + self.generate_deleted_proxies() + self.generate_created_proxies() + self.generate_altered_options() + self.generate_altered_managers() + self.generate_altered_db_table_comment() + + # Create the renamed fields and store them in self.renamed_fields. + # They are used by create_altered_indexes(), generate_altered_fields(), + # generate_removed_altered_index/unique_together(), and + # generate_altered_index/unique_together(). + self.create_renamed_fields() + # Create the altered indexes and store them in self.altered_indexes. + # This avoids the same computation in generate_removed_indexes() + # and generate_added_indexes(). + self.create_altered_indexes() + self.create_altered_constraints() + # Generate index removal operations before field is removed + self.generate_removed_constraints() + self.generate_removed_indexes() + # Generate field renaming operations. + self.generate_renamed_fields() + self.generate_renamed_indexes() + # Generate removal of foo together. + self.generate_removed_altered_unique_together() + self.generate_removed_altered_index_together() # RemovedInDjango51Warning. + # Generate field operations. + self.generate_removed_fields() + self.generate_added_fields() + self.generate_altered_fields() + self.generate_altered_order_with_respect_to() + self.generate_altered_unique_together() + self.generate_altered_index_together() # RemovedInDjango51Warning. + self.generate_added_indexes() + self.generate_added_constraints() + self.generate_altered_db_table() + + self._sort_migrations() + self._build_migration_list(graph) + self._optimize_migrations() + + return self.migrations + + def _prepare_field_lists(self): + """ + Prepare field lists and a list of the fields that used through models + in the old state so dependencies can be made from the through model + deletion to the field that uses it. + """ + self.kept_model_keys = self.old_model_keys & self.new_model_keys + self.kept_proxy_keys = self.old_proxy_keys & self.new_proxy_keys + self.kept_unmanaged_keys = self.old_unmanaged_keys & self.new_unmanaged_keys + self.through_users = {} + self.old_field_keys = { + (app_label, model_name, field_name) + for app_label, model_name in self.kept_model_keys + for field_name in self.from_state.models[ + app_label, self.renamed_models.get((app_label, model_name), model_name) + ].fields + } + self.new_field_keys = { + (app_label, model_name, field_name) + for app_label, model_name in self.kept_model_keys + for field_name in self.to_state.models[app_label, model_name].fields + } + + def _generate_through_model_map(self): + """Through model map generation.""" + for app_label, model_name in sorted(self.old_model_keys): + old_model_name = self.renamed_models.get( + (app_label, model_name), model_name + ) + old_model_state = self.from_state.models[app_label, old_model_name] + for field_name, field in old_model_state.fields.items(): + if hasattr(field, "remote_field") and getattr( + field.remote_field, "through", None + ): + through_key = resolve_relation( + field.remote_field.through, app_label, model_name + ) + self.through_users[through_key] = ( + app_label, + old_model_name, + field_name, + ) + + @staticmethod + def _resolve_dependency(dependency): + """ + Return the resolved dependency and a boolean denoting whether or not + it was swappable. + """ + if dependency[0] != "__setting__": + return dependency, False + resolved_app_label, resolved_object_name = getattr( + settings, dependency[1] + ).split(".") + return (resolved_app_label, resolved_object_name.lower()) + dependency[2:], True + + def _build_migration_list(self, graph=None): + """ + Chop the lists of operations up into migrations with dependencies on + each other. Do this by going through an app's list of operations until + one is found that has an outgoing dependency that isn't in another + app's migration yet (hasn't been chopped off its list). Then chop off + the operations before it into a migration and move onto the next app. + If the loops completes without doing anything, there's a circular + dependency (which _should_ be impossible as the operations are + all split at this point so they can't depend and be depended on). + """ + self.migrations = {} + num_ops = sum(len(x) for x in self.generated_operations.values()) + chop_mode = False + while num_ops: + # On every iteration, we step through all the apps and see if there + # is a completed set of operations. + # If we find that a subset of the operations are complete we can + # try to chop it off from the rest and continue, but we only + # do this if we've already been through the list once before + # without any chopping and nothing has changed. + for app_label in sorted(self.generated_operations): + chopped = [] + dependencies = set() + for operation in list(self.generated_operations[app_label]): + deps_satisfied = True + operation_dependencies = set() + for dep in operation._auto_deps: + # Temporarily resolve the swappable dependency to + # prevent circular references. While keeping the + # dependency checks on the resolved model, add the + # swappable dependencies. + original_dep = dep + dep, is_swappable_dep = self._resolve_dependency(dep) + if dep[0] != app_label: + # External app dependency. See if it's not yet + # satisfied. + for other_operation in self.generated_operations.get( + dep[0], [] + ): + if self.check_dependency(other_operation, dep): + deps_satisfied = False + break + if not deps_satisfied: + break + else: + if is_swappable_dep: + operation_dependencies.add( + (original_dep[0], original_dep[1]) + ) + elif dep[0] in self.migrations: + operation_dependencies.add( + (dep[0], self.migrations[dep[0]][-1].name) + ) + else: + # If we can't find the other app, we add a + # first/last dependency, but only if we've + # already been through once and checked + # everything. + if chop_mode: + # If the app already exists, we add a + # dependency on the last migration, as + # we don't know which migration + # contains the target field. If it's + # not yet migrated or has no + # migrations, we use __first__. + if graph and graph.leaf_nodes(dep[0]): + operation_dependencies.add( + graph.leaf_nodes(dep[0])[0] + ) + else: + operation_dependencies.add( + (dep[0], "__first__") + ) + else: + deps_satisfied = False + if deps_satisfied: + chopped.append(operation) + dependencies.update(operation_dependencies) + del self.generated_operations[app_label][0] + else: + break + # Make a migration! Well, only if there's stuff to put in it + if dependencies or chopped: + if not self.generated_operations[app_label] or chop_mode: + subclass = type( + "Migration", + (Migration,), + {"operations": [], "dependencies": []}, + ) + instance = subclass( + "auto_%i" % (len(self.migrations.get(app_label, [])) + 1), + app_label, + ) + instance.dependencies = list(dependencies) + instance.operations = chopped + instance.initial = app_label not in self.existing_apps + self.migrations.setdefault(app_label, []).append(instance) + chop_mode = False + else: + self.generated_operations[app_label] = ( + chopped + self.generated_operations[app_label] + ) + new_num_ops = sum(len(x) for x in self.generated_operations.values()) + if new_num_ops == num_ops: + if not chop_mode: + chop_mode = True + else: + raise ValueError( + "Cannot resolve operation dependencies: %r" + % self.generated_operations + ) + num_ops = new_num_ops + + def _sort_migrations(self): + """ + Reorder to make things possible. Reordering may be needed so FKs work + nicely inside the same app. + """ + for app_label, ops in sorted(self.generated_operations.items()): + ts = TopologicalSorter() + for op in ops: + ts.add(op) + for dep in op._auto_deps: + # Resolve intra-app dependencies to handle circular + # references involving a swappable model. + dep = self._resolve_dependency(dep)[0] + if dep[0] != app_label: + continue + ts.add(op, *(x for x in ops if self.check_dependency(x, dep))) + self.generated_operations[app_label] = list(ts.static_order()) + + def _optimize_migrations(self): + # Add in internal dependencies among the migrations + for app_label, migrations in self.migrations.items(): + for m1, m2 in zip(migrations, migrations[1:]): + m2.dependencies.append((app_label, m1.name)) + + # De-dupe dependencies + for migrations in self.migrations.values(): + for migration in migrations: + migration.dependencies = list(set(migration.dependencies)) + + # Optimize migrations + for app_label, migrations in self.migrations.items(): + for migration in migrations: + migration.operations = MigrationOptimizer().optimize( + migration.operations, app_label + ) + + def check_dependency(self, operation, dependency): + """ + Return True if the given operation depends on the given dependency, + False otherwise. + """ + # Created model + if dependency[2] is None and dependency[3] is True: + return ( + isinstance(operation, operations.CreateModel) + and operation.name_lower == dependency[1].lower() + ) + # Created field + elif dependency[2] is not None and dependency[3] is True: + return ( + isinstance(operation, operations.CreateModel) + and operation.name_lower == dependency[1].lower() + and any(dependency[2] == x for x, y in operation.fields) + ) or ( + isinstance(operation, operations.AddField) + and operation.model_name_lower == dependency[1].lower() + and operation.name_lower == dependency[2].lower() + ) + # Removed field + elif dependency[2] is not None and dependency[3] is False: + return ( + isinstance(operation, operations.RemoveField) + and operation.model_name_lower == dependency[1].lower() + and operation.name_lower == dependency[2].lower() + ) + # Removed model + elif dependency[2] is None and dependency[3] is False: + return ( + isinstance(operation, operations.DeleteModel) + and operation.name_lower == dependency[1].lower() + ) + # Field being altered + elif dependency[2] is not None and dependency[3] == "alter": + return ( + isinstance(operation, operations.AlterField) + and operation.model_name_lower == dependency[1].lower() + and operation.name_lower == dependency[2].lower() + ) + # order_with_respect_to being unset for a field + elif dependency[2] is not None and dependency[3] == "order_wrt_unset": + return ( + isinstance(operation, operations.AlterOrderWithRespectTo) + and operation.name_lower == dependency[1].lower() + and (operation.order_with_respect_to or "").lower() + != dependency[2].lower() + ) + # Field is removed and part of an index/unique_together + elif dependency[2] is not None and dependency[3] == "foo_together_change": + return ( + isinstance( + operation, + (operations.AlterUniqueTogether, operations.AlterIndexTogether), + ) + and operation.name_lower == dependency[1].lower() + ) + # Unknown dependency. Raise an error. + else: + raise ValueError("Can't handle dependency %r" % (dependency,)) + + def add_operation(self, app_label, operation, dependencies=None, beginning=False): + # Dependencies are + # (app_label, model_name, field_name, create/delete as True/False) + operation._auto_deps = dependencies or [] + if beginning: + self.generated_operations.setdefault(app_label, []).insert(0, operation) + else: + self.generated_operations.setdefault(app_label, []).append(operation) + + def swappable_first_key(self, item): + """ + Place potential swappable models first in lists of created models (only + real way to solve #22783). + """ + try: + model_state = self.to_state.models[item] + base_names = { + base if isinstance(base, str) else base.__name__ + for base in model_state.bases + } + string_version = "%s.%s" % (item[0], item[1]) + if ( + model_state.options.get("swappable") + or "AbstractUser" in base_names + or "AbstractBaseUser" in base_names + or settings.AUTH_USER_MODEL.lower() == string_version.lower() + ): + return ("___" + item[0], "___" + item[1]) + except LookupError: + pass + return item + + def generate_renamed_models(self): + """ + Find any renamed models, generate the operations for them, and remove + the old entry from the model lists. Must be run before other + model-level generation. + """ + self.renamed_models = {} + self.renamed_models_rel = {} + added_models = self.new_model_keys - self.old_model_keys + for app_label, model_name in sorted(added_models): + model_state = self.to_state.models[app_label, model_name] + model_fields_def = self.only_relation_agnostic_fields(model_state.fields) + + removed_models = self.old_model_keys - self.new_model_keys + for rem_app_label, rem_model_name in removed_models: + if rem_app_label == app_label: + rem_model_state = self.from_state.models[ + rem_app_label, rem_model_name + ] + rem_model_fields_def = self.only_relation_agnostic_fields( + rem_model_state.fields + ) + if model_fields_def == rem_model_fields_def: + if self.questioner.ask_rename_model( + rem_model_state, model_state + ): + dependencies = [] + fields = list(model_state.fields.values()) + [ + field.remote_field + for relations in self.to_state.relations[ + app_label, model_name + ].values() + for field in relations.values() + ] + for field in fields: + if field.is_relation: + dependencies.extend( + self._get_dependencies_for_foreign_key( + app_label, + model_name, + field, + self.to_state, + ) + ) + self.add_operation( + app_label, + operations.RenameModel( + old_name=rem_model_state.name, + new_name=model_state.name, + ), + dependencies=dependencies, + ) + self.renamed_models[app_label, model_name] = rem_model_name + renamed_models_rel_key = "%s.%s" % ( + rem_model_state.app_label, + rem_model_state.name_lower, + ) + self.renamed_models_rel[ + renamed_models_rel_key + ] = "%s.%s" % ( + model_state.app_label, + model_state.name_lower, + ) + self.old_model_keys.remove((rem_app_label, rem_model_name)) + self.old_model_keys.add((app_label, model_name)) + break + + def generate_created_models(self): + """ + Find all new models (both managed and unmanaged) and make create + operations for them as well as separate operations to create any + foreign key or M2M relationships (these are optimized later, if + possible). + + Defer any model options that refer to collections of fields that might + be deferred (e.g. unique_together, index_together). + """ + old_keys = self.old_model_keys | self.old_unmanaged_keys + added_models = self.new_model_keys - old_keys + added_unmanaged_models = self.new_unmanaged_keys - old_keys + all_added_models = chain( + sorted(added_models, key=self.swappable_first_key, reverse=True), + sorted(added_unmanaged_models, key=self.swappable_first_key, reverse=True), + ) + for app_label, model_name in all_added_models: + model_state = self.to_state.models[app_label, model_name] + # Gather related fields + related_fields = {} + primary_key_rel = None + for field_name, field in model_state.fields.items(): + if field.remote_field: + if field.remote_field.model: + if field.primary_key: + primary_key_rel = field.remote_field.model + elif not field.remote_field.parent_link: + related_fields[field_name] = field + if getattr(field.remote_field, "through", None): + related_fields[field_name] = field + + # Are there indexes/unique|index_together to defer? + indexes = model_state.options.pop("indexes") + constraints = model_state.options.pop("constraints") + unique_together = model_state.options.pop("unique_together", None) + # RemovedInDjango51Warning. + index_together = model_state.options.pop("index_together", None) + order_with_respect_to = model_state.options.pop( + "order_with_respect_to", None + ) + # Depend on the deletion of any possible proxy version of us + dependencies = [ + (app_label, model_name, None, False), + ] + # Depend on all bases + for base in model_state.bases: + if isinstance(base, str) and "." in base: + base_app_label, base_name = base.split(".", 1) + dependencies.append((base_app_label, base_name, None, True)) + # Depend on the removal of base fields if the new model has + # a field with the same name. + old_base_model_state = self.from_state.models.get( + (base_app_label, base_name) + ) + new_base_model_state = self.to_state.models.get( + (base_app_label, base_name) + ) + if old_base_model_state and new_base_model_state: + removed_base_fields = ( + set(old_base_model_state.fields) + .difference( + new_base_model_state.fields, + ) + .intersection(model_state.fields) + ) + for removed_base_field in removed_base_fields: + dependencies.append( + (base_app_label, base_name, removed_base_field, False) + ) + # Depend on the other end of the primary key if it's a relation + if primary_key_rel: + dependencies.append( + resolve_relation( + primary_key_rel, + app_label, + model_name, + ) + + (None, True) + ) + # Generate creation operation + self.add_operation( + app_label, + operations.CreateModel( + name=model_state.name, + fields=[ + d + for d in model_state.fields.items() + if d[0] not in related_fields + ], + options=model_state.options, + bases=model_state.bases, + managers=model_state.managers, + ), + dependencies=dependencies, + beginning=True, + ) + + # Don't add operations which modify the database for unmanaged models + if not model_state.options.get("managed", True): + continue + + # Generate operations for each related field + for name, field in sorted(related_fields.items()): + dependencies = self._get_dependencies_for_foreign_key( + app_label, + model_name, + field, + self.to_state, + ) + # Depend on our own model being created + dependencies.append((app_label, model_name, None, True)) + # Make operation + self.add_operation( + app_label, + operations.AddField( + model_name=model_name, + name=name, + field=field, + ), + dependencies=list(set(dependencies)), + ) + # Generate other opns + if order_with_respect_to: + self.add_operation( + app_label, + operations.AlterOrderWithRespectTo( + name=model_name, + order_with_respect_to=order_with_respect_to, + ), + dependencies=[ + (app_label, model_name, order_with_respect_to, True), + (app_label, model_name, None, True), + ], + ) + related_dependencies = [ + (app_label, model_name, name, True) for name in sorted(related_fields) + ] + related_dependencies.append((app_label, model_name, None, True)) + for index in indexes: + self.add_operation( + app_label, + operations.AddIndex( + model_name=model_name, + index=index, + ), + dependencies=related_dependencies, + ) + for constraint in constraints: + self.add_operation( + app_label, + operations.AddConstraint( + model_name=model_name, + constraint=constraint, + ), + dependencies=related_dependencies, + ) + if unique_together: + self.add_operation( + app_label, + operations.AlterUniqueTogether( + name=model_name, + unique_together=unique_together, + ), + dependencies=related_dependencies, + ) + # RemovedInDjango51Warning. + if index_together: + self.add_operation( + app_label, + operations.AlterIndexTogether( + name=model_name, + index_together=index_together, + ), + dependencies=related_dependencies, + ) + # Fix relationships if the model changed from a proxy model to a + # concrete model. + relations = self.to_state.relations + if (app_label, model_name) in self.old_proxy_keys: + for related_model_key, related_fields in relations[ + app_label, model_name + ].items(): + related_model_state = self.to_state.models[related_model_key] + for related_field_name, related_field in related_fields.items(): + self.add_operation( + related_model_state.app_label, + operations.AlterField( + model_name=related_model_state.name, + name=related_field_name, + field=related_field, + ), + dependencies=[(app_label, model_name, None, True)], + ) + + def generate_created_proxies(self): + """ + Make CreateModel statements for proxy models. Use the same statements + as that way there's less code duplication, but for proxy models it's + safe to skip all the pointless field stuff and chuck out an operation. + """ + added = self.new_proxy_keys - self.old_proxy_keys + for app_label, model_name in sorted(added): + model_state = self.to_state.models[app_label, model_name] + assert model_state.options.get("proxy") + # Depend on the deletion of any possible non-proxy version of us + dependencies = [ + (app_label, model_name, None, False), + ] + # Depend on all bases + for base in model_state.bases: + if isinstance(base, str) and "." in base: + base_app_label, base_name = base.split(".", 1) + dependencies.append((base_app_label, base_name, None, True)) + # Generate creation operation + self.add_operation( + app_label, + operations.CreateModel( + name=model_state.name, + fields=[], + options=model_state.options, + bases=model_state.bases, + managers=model_state.managers, + ), + # Depend on the deletion of any possible non-proxy version of us + dependencies=dependencies, + ) + + def generate_deleted_models(self): + """ + Find all deleted models (managed and unmanaged) and make delete + operations for them as well as separate operations to delete any + foreign key or M2M relationships (these are optimized later, if + possible). + + Also bring forward removal of any model options that refer to + collections of fields - the inverse of generate_created_models(). + """ + new_keys = self.new_model_keys | self.new_unmanaged_keys + deleted_models = self.old_model_keys - new_keys + deleted_unmanaged_models = self.old_unmanaged_keys - new_keys + all_deleted_models = chain( + sorted(deleted_models), sorted(deleted_unmanaged_models) + ) + for app_label, model_name in all_deleted_models: + model_state = self.from_state.models[app_label, model_name] + # Gather related fields + related_fields = {} + for field_name, field in model_state.fields.items(): + if field.remote_field: + if field.remote_field.model: + related_fields[field_name] = field + if getattr(field.remote_field, "through", None): + related_fields[field_name] = field + # Generate option removal first + unique_together = model_state.options.pop("unique_together", None) + # RemovedInDjango51Warning. + index_together = model_state.options.pop("index_together", None) + if unique_together: + self.add_operation( + app_label, + operations.AlterUniqueTogether( + name=model_name, + unique_together=None, + ), + ) + # RemovedInDjango51Warning. + if index_together: + self.add_operation( + app_label, + operations.AlterIndexTogether( + name=model_name, + index_together=None, + ), + ) + # Then remove each related field + for name in sorted(related_fields): + self.add_operation( + app_label, + operations.RemoveField( + model_name=model_name, + name=name, + ), + ) + # Finally, remove the model. + # This depends on both the removal/alteration of all incoming fields + # and the removal of all its own related fields, and if it's + # a through model the field that references it. + dependencies = [] + relations = self.from_state.relations + for ( + related_object_app_label, + object_name, + ), relation_related_fields in relations[app_label, model_name].items(): + for field_name, field in relation_related_fields.items(): + dependencies.append( + (related_object_app_label, object_name, field_name, False), + ) + if not field.many_to_many: + dependencies.append( + ( + related_object_app_label, + object_name, + field_name, + "alter", + ), + ) + + for name in sorted(related_fields): + dependencies.append((app_label, model_name, name, False)) + # We're referenced in another field's through= + through_user = self.through_users.get((app_label, model_state.name_lower)) + if through_user: + dependencies.append( + (through_user[0], through_user[1], through_user[2], False) + ) + # Finally, make the operation, deduping any dependencies + self.add_operation( + app_label, + operations.DeleteModel( + name=model_state.name, + ), + dependencies=list(set(dependencies)), + ) + + def generate_deleted_proxies(self): + """Make DeleteModel options for proxy models.""" + deleted = self.old_proxy_keys - self.new_proxy_keys + for app_label, model_name in sorted(deleted): + model_state = self.from_state.models[app_label, model_name] + assert model_state.options.get("proxy") + self.add_operation( + app_label, + operations.DeleteModel( + name=model_state.name, + ), + ) + + def create_renamed_fields(self): + """Work out renamed fields.""" + self.renamed_operations = [] + old_field_keys = self.old_field_keys.copy() + for app_label, model_name, field_name in sorted( + self.new_field_keys - old_field_keys + ): + old_model_name = self.renamed_models.get( + (app_label, model_name), model_name + ) + old_model_state = self.from_state.models[app_label, old_model_name] + new_model_state = self.to_state.models[app_label, model_name] + field = new_model_state.get_field(field_name) + # Scan to see if this is actually a rename! + field_dec = self.deep_deconstruct(field) + for rem_app_label, rem_model_name, rem_field_name in sorted( + old_field_keys - self.new_field_keys + ): + if rem_app_label == app_label and rem_model_name == model_name: + old_field = old_model_state.get_field(rem_field_name) + old_field_dec = self.deep_deconstruct(old_field) + if ( + field.remote_field + and field.remote_field.model + and "to" in old_field_dec[2] + ): + old_rel_to = old_field_dec[2]["to"] + if old_rel_to in self.renamed_models_rel: + old_field_dec[2]["to"] = self.renamed_models_rel[old_rel_to] + old_field.set_attributes_from_name(rem_field_name) + old_db_column = old_field.get_attname_column()[1] + if old_field_dec == field_dec or ( + # Was the field renamed and db_column equal to the + # old field's column added? + old_field_dec[0:2] == field_dec[0:2] + and dict(old_field_dec[2], db_column=old_db_column) + == field_dec[2] + ): + if self.questioner.ask_rename( + model_name, rem_field_name, field_name, field + ): + self.renamed_operations.append( + ( + rem_app_label, + rem_model_name, + old_field.db_column, + rem_field_name, + app_label, + model_name, + field, + field_name, + ) + ) + old_field_keys.remove( + (rem_app_label, rem_model_name, rem_field_name) + ) + old_field_keys.add((app_label, model_name, field_name)) + self.renamed_fields[ + app_label, model_name, field_name + ] = rem_field_name + break + + def generate_renamed_fields(self): + """Generate RenameField operations.""" + for ( + rem_app_label, + rem_model_name, + rem_db_column, + rem_field_name, + app_label, + model_name, + field, + field_name, + ) in self.renamed_operations: + # A db_column mismatch requires a prior noop AlterField for the + # subsequent RenameField to be a noop on attempts at preserving the + # old name. + if rem_db_column != field.db_column: + altered_field = field.clone() + altered_field.name = rem_field_name + self.add_operation( + app_label, + operations.AlterField( + model_name=model_name, + name=rem_field_name, + field=altered_field, + ), + ) + self.add_operation( + app_label, + operations.RenameField( + model_name=model_name, + old_name=rem_field_name, + new_name=field_name, + ), + ) + self.old_field_keys.remove((rem_app_label, rem_model_name, rem_field_name)) + self.old_field_keys.add((app_label, model_name, field_name)) + + def generate_added_fields(self): + """Make AddField operations.""" + for app_label, model_name, field_name in sorted( + self.new_field_keys - self.old_field_keys + ): + self._generate_added_field(app_label, model_name, field_name) + + def _generate_added_field(self, app_label, model_name, field_name): + field = self.to_state.models[app_label, model_name].get_field(field_name) + # Adding a field always depends at least on its removal. + dependencies = [(app_label, model_name, field_name, False)] + # Fields that are foreignkeys/m2ms depend on stuff. + if field.remote_field and field.remote_field.model: + dependencies.extend( + self._get_dependencies_for_foreign_key( + app_label, + model_name, + field, + self.to_state, + ) + ) + # You can't just add NOT NULL fields with no default or fields + # which don't allow empty strings as default. + time_fields = (models.DateField, models.DateTimeField, models.TimeField) + preserve_default = ( + field.null + or field.has_default() + or field.db_default is not models.NOT_PROVIDED + or field.many_to_many + or (field.blank and field.empty_strings_allowed) + or (isinstance(field, time_fields) and field.auto_now) + ) + if not preserve_default: + field = field.clone() + if isinstance(field, time_fields) and field.auto_now_add: + field.default = self.questioner.ask_auto_now_add_addition( + field_name, model_name + ) + else: + field.default = self.questioner.ask_not_null_addition( + field_name, model_name + ) + if ( + field.unique + and field.default is not models.NOT_PROVIDED + and callable(field.default) + ): + self.questioner.ask_unique_callable_default_addition(field_name, model_name) + self.add_operation( + app_label, + operations.AddField( + model_name=model_name, + name=field_name, + field=field, + preserve_default=preserve_default, + ), + dependencies=dependencies, + ) + + def generate_removed_fields(self): + """Make RemoveField operations.""" + for app_label, model_name, field_name in sorted( + self.old_field_keys - self.new_field_keys + ): + self._generate_removed_field(app_label, model_name, field_name) + + def _generate_removed_field(self, app_label, model_name, field_name): + self.add_operation( + app_label, + operations.RemoveField( + model_name=model_name, + name=field_name, + ), + # We might need to depend on the removal of an + # order_with_respect_to or index/unique_together operation; + # this is safely ignored if there isn't one + dependencies=[ + (app_label, model_name, field_name, "order_wrt_unset"), + (app_label, model_name, field_name, "foo_together_change"), + ], + ) + + def generate_altered_fields(self): + """ + Make AlterField operations, or possibly RemovedField/AddField if alter + isn't possible. + """ + for app_label, model_name, field_name in sorted( + self.old_field_keys & self.new_field_keys + ): + # Did the field change? + old_model_name = self.renamed_models.get( + (app_label, model_name), model_name + ) + old_field_name = self.renamed_fields.get( + (app_label, model_name, field_name), field_name + ) + old_field = self.from_state.models[app_label, old_model_name].get_field( + old_field_name + ) + new_field = self.to_state.models[app_label, model_name].get_field( + field_name + ) + dependencies = [] + # Implement any model renames on relations; these are handled by RenameModel + # so we need to exclude them from the comparison + if hasattr(new_field, "remote_field") and getattr( + new_field.remote_field, "model", None + ): + rename_key = resolve_relation( + new_field.remote_field.model, app_label, model_name + ) + if rename_key in self.renamed_models: + new_field.remote_field.model = old_field.remote_field.model + # Handle ForeignKey which can only have a single to_field. + remote_field_name = getattr(new_field.remote_field, "field_name", None) + if remote_field_name: + to_field_rename_key = rename_key + (remote_field_name,) + if to_field_rename_key in self.renamed_fields: + # Repoint both model and field name because to_field + # inclusion in ForeignKey.deconstruct() is based on + # both. + new_field.remote_field.model = old_field.remote_field.model + new_field.remote_field.field_name = ( + old_field.remote_field.field_name + ) + # Handle ForeignObjects which can have multiple from_fields/to_fields. + from_fields = getattr(new_field, "from_fields", None) + if from_fields: + from_rename_key = (app_label, model_name) + new_field.from_fields = tuple( + [ + self.renamed_fields.get( + from_rename_key + (from_field,), from_field + ) + for from_field in from_fields + ] + ) + new_field.to_fields = tuple( + [ + self.renamed_fields.get(rename_key + (to_field,), to_field) + for to_field in new_field.to_fields + ] + ) + if old_from_fields := getattr(old_field, "from_fields", None): + old_field.from_fields = tuple(old_from_fields) + old_field.to_fields = tuple(old_field.to_fields) + dependencies.extend( + self._get_dependencies_for_foreign_key( + app_label, + model_name, + new_field, + self.to_state, + ) + ) + if hasattr(new_field, "remote_field") and getattr( + new_field.remote_field, "through", None + ): + rename_key = resolve_relation( + new_field.remote_field.through, app_label, model_name + ) + if rename_key in self.renamed_models: + new_field.remote_field.through = old_field.remote_field.through + old_field_dec = self.deep_deconstruct(old_field) + new_field_dec = self.deep_deconstruct(new_field) + # If the field was confirmed to be renamed it means that only + # db_column was allowed to change which generate_renamed_fields() + # already accounts for by adding an AlterField operation. + if old_field_dec != new_field_dec and old_field_name == field_name: + both_m2m = old_field.many_to_many and new_field.many_to_many + neither_m2m = not old_field.many_to_many and not new_field.many_to_many + if both_m2m or neither_m2m: + # Either both fields are m2m or neither is + preserve_default = True + if ( + old_field.null + and not new_field.null + and not new_field.has_default() + and new_field.db_default is models.NOT_PROVIDED + and not new_field.many_to_many + ): + field = new_field.clone() + new_default = self.questioner.ask_not_null_alteration( + field_name, model_name + ) + if new_default is not models.NOT_PROVIDED: + field.default = new_default + preserve_default = False + else: + field = new_field + self.add_operation( + app_label, + operations.AlterField( + model_name=model_name, + name=field_name, + field=field, + preserve_default=preserve_default, + ), + dependencies=dependencies, + ) + else: + # We cannot alter between m2m and concrete fields + self._generate_removed_field(app_label, model_name, field_name) + self._generate_added_field(app_label, model_name, field_name) + + def create_altered_indexes(self): + option_name = operations.AddIndex.option_name + self.renamed_index_together_values = defaultdict(list) + + for app_label, model_name in sorted(self.kept_model_keys): + old_model_name = self.renamed_models.get( + (app_label, model_name), model_name + ) + old_model_state = self.from_state.models[app_label, old_model_name] + new_model_state = self.to_state.models[app_label, model_name] + + old_indexes = old_model_state.options[option_name] + new_indexes = new_model_state.options[option_name] + added_indexes = [idx for idx in new_indexes if idx not in old_indexes] + removed_indexes = [idx for idx in old_indexes if idx not in new_indexes] + renamed_indexes = [] + # Find renamed indexes. + remove_from_added = [] + remove_from_removed = [] + for new_index in added_indexes: + new_index_dec = new_index.deconstruct() + new_index_name = new_index_dec[2].pop("name") + for old_index in removed_indexes: + old_index_dec = old_index.deconstruct() + old_index_name = old_index_dec[2].pop("name") + # Indexes are the same except for the names. + if ( + new_index_dec == old_index_dec + and new_index_name != old_index_name + ): + renamed_indexes.append((old_index_name, new_index_name, None)) + remove_from_added.append(new_index) + remove_from_removed.append(old_index) + # Find index_together changed to indexes. + for ( + old_value, + new_value, + index_together_app_label, + index_together_model_name, + dependencies, + ) in self._get_altered_foo_together_operations( + operations.AlterIndexTogether.option_name + ): + if ( + app_label != index_together_app_label + or model_name != index_together_model_name + ): + continue + removed_values = old_value.difference(new_value) + for removed_index_together in removed_values: + renamed_index_together_indexes = [] + for new_index in added_indexes: + _, args, kwargs = new_index.deconstruct() + # Ensure only 'fields' are defined in the Index. + if ( + not args + and new_index.fields == list(removed_index_together) + and set(kwargs) == {"name", "fields"} + ): + renamed_index_together_indexes.append(new_index) + + if len(renamed_index_together_indexes) == 1: + renamed_index = renamed_index_together_indexes[0] + remove_from_added.append(renamed_index) + renamed_indexes.append( + (None, renamed_index.name, removed_index_together) + ) + self.renamed_index_together_values[ + index_together_app_label, index_together_model_name + ].append(removed_index_together) + # Remove renamed indexes from the lists of added and removed + # indexes. + added_indexes = [ + idx for idx in added_indexes if idx not in remove_from_added + ] + removed_indexes = [ + idx for idx in removed_indexes if idx not in remove_from_removed + ] + + self.altered_indexes.update( + { + (app_label, model_name): { + "added_indexes": added_indexes, + "removed_indexes": removed_indexes, + "renamed_indexes": renamed_indexes, + } + } + ) + + def generate_added_indexes(self): + for (app_label, model_name), alt_indexes in self.altered_indexes.items(): + dependencies = self._get_dependencies_for_model(app_label, model_name) + for index in alt_indexes["added_indexes"]: + self.add_operation( + app_label, + operations.AddIndex( + model_name=model_name, + index=index, + ), + dependencies=dependencies, + ) + + def generate_removed_indexes(self): + for (app_label, model_name), alt_indexes in self.altered_indexes.items(): + for index in alt_indexes["removed_indexes"]: + self.add_operation( + app_label, + operations.RemoveIndex( + model_name=model_name, + name=index.name, + ), + ) + + def generate_renamed_indexes(self): + for (app_label, model_name), alt_indexes in self.altered_indexes.items(): + for old_index_name, new_index_name, old_fields in alt_indexes[ + "renamed_indexes" + ]: + self.add_operation( + app_label, + operations.RenameIndex( + model_name=model_name, + new_name=new_index_name, + old_name=old_index_name, + old_fields=old_fields, + ), + ) + + def create_altered_constraints(self): + option_name = operations.AddConstraint.option_name + for app_label, model_name in sorted(self.kept_model_keys): + old_model_name = self.renamed_models.get( + (app_label, model_name), model_name + ) + old_model_state = self.from_state.models[app_label, old_model_name] + new_model_state = self.to_state.models[app_label, model_name] + + old_constraints = old_model_state.options[option_name] + new_constraints = new_model_state.options[option_name] + add_constraints = [c for c in new_constraints if c not in old_constraints] + rem_constraints = [c for c in old_constraints if c not in new_constraints] + + self.altered_constraints.update( + { + (app_label, model_name): { + "added_constraints": add_constraints, + "removed_constraints": rem_constraints, + } + } + ) + + def generate_added_constraints(self): + for ( + app_label, + model_name, + ), alt_constraints in self.altered_constraints.items(): + dependencies = self._get_dependencies_for_model(app_label, model_name) + for constraint in alt_constraints["added_constraints"]: + self.add_operation( + app_label, + operations.AddConstraint( + model_name=model_name, + constraint=constraint, + ), + dependencies=dependencies, + ) + + def generate_removed_constraints(self): + for ( + app_label, + model_name, + ), alt_constraints in self.altered_constraints.items(): + for constraint in alt_constraints["removed_constraints"]: + self.add_operation( + app_label, + operations.RemoveConstraint( + model_name=model_name, + name=constraint.name, + ), + ) + + @staticmethod + def _get_dependencies_for_foreign_key(app_label, model_name, field, project_state): + remote_field_model = None + if hasattr(field.remote_field, "model"): + remote_field_model = field.remote_field.model + else: + relations = project_state.relations[app_label, model_name] + for (remote_app_label, remote_model_name), fields in relations.items(): + if any( + field == related_field.remote_field + for related_field in fields.values() + ): + remote_field_model = f"{remote_app_label}.{remote_model_name}" + break + # Account for FKs to swappable models + swappable_setting = getattr(field, "swappable_setting", None) + if swappable_setting is not None: + dep_app_label = "__setting__" + dep_object_name = swappable_setting + else: + dep_app_label, dep_object_name = resolve_relation( + remote_field_model, + app_label, + model_name, + ) + dependencies = [(dep_app_label, dep_object_name, None, True)] + if getattr(field.remote_field, "through", None): + through_app_label, through_object_name = resolve_relation( + field.remote_field.through, + app_label, + model_name, + ) + dependencies.append((through_app_label, through_object_name, None, True)) + return dependencies + + def _get_dependencies_for_model(self, app_label, model_name): + """Return foreign key dependencies of the given model.""" + dependencies = [] + model_state = self.to_state.models[app_label, model_name] + for field in model_state.fields.values(): + if field.is_relation: + dependencies.extend( + self._get_dependencies_for_foreign_key( + app_label, + model_name, + field, + self.to_state, + ) + ) + return dependencies + + def _get_altered_foo_together_operations(self, option_name): + for app_label, model_name in sorted(self.kept_model_keys): + old_model_name = self.renamed_models.get( + (app_label, model_name), model_name + ) + old_model_state = self.from_state.models[app_label, old_model_name] + new_model_state = self.to_state.models[app_label, model_name] + + # We run the old version through the field renames to account for those + old_value = old_model_state.options.get(option_name) + old_value = ( + { + tuple( + self.renamed_fields.get((app_label, model_name, n), n) + for n in unique + ) + for unique in old_value + } + if old_value + else set() + ) + + new_value = new_model_state.options.get(option_name) + new_value = set(new_value) if new_value else set() + + if old_value != new_value: + dependencies = [] + for foo_togethers in new_value: + for field_name in foo_togethers: + field = new_model_state.get_field(field_name) + if field.remote_field and field.remote_field.model: + dependencies.extend( + self._get_dependencies_for_foreign_key( + app_label, + model_name, + field, + self.to_state, + ) + ) + yield ( + old_value, + new_value, + app_label, + model_name, + dependencies, + ) + + def _generate_removed_altered_foo_together(self, operation): + for ( + old_value, + new_value, + app_label, + model_name, + dependencies, + ) in self._get_altered_foo_together_operations(operation.option_name): + if operation == operations.AlterIndexTogether: + old_value = { + value + for value in old_value + if value + not in self.renamed_index_together_values[app_label, model_name] + } + removal_value = new_value.intersection(old_value) + if removal_value or old_value: + self.add_operation( + app_label, + operation( + name=model_name, **{operation.option_name: removal_value} + ), + dependencies=dependencies, + ) + + def generate_removed_altered_unique_together(self): + self._generate_removed_altered_foo_together(operations.AlterUniqueTogether) + + # RemovedInDjango51Warning. + def generate_removed_altered_index_together(self): + self._generate_removed_altered_foo_together(operations.AlterIndexTogether) + + def _generate_altered_foo_together(self, operation): + for ( + old_value, + new_value, + app_label, + model_name, + dependencies, + ) in self._get_altered_foo_together_operations(operation.option_name): + removal_value = new_value.intersection(old_value) + if new_value != removal_value: + self.add_operation( + app_label, + operation(name=model_name, **{operation.option_name: new_value}), + dependencies=dependencies, + ) + + def generate_altered_unique_together(self): + self._generate_altered_foo_together(operations.AlterUniqueTogether) + + # RemovedInDjango51Warning. + def generate_altered_index_together(self): + self._generate_altered_foo_together(operations.AlterIndexTogether) + + def generate_altered_db_table(self): + models_to_check = self.kept_model_keys.union( + self.kept_proxy_keys, self.kept_unmanaged_keys + ) + for app_label, model_name in sorted(models_to_check): + old_model_name = self.renamed_models.get( + (app_label, model_name), model_name + ) + old_model_state = self.from_state.models[app_label, old_model_name] + new_model_state = self.to_state.models[app_label, model_name] + old_db_table_name = old_model_state.options.get("db_table") + new_db_table_name = new_model_state.options.get("db_table") + if old_db_table_name != new_db_table_name: + self.add_operation( + app_label, + operations.AlterModelTable( + name=model_name, + table=new_db_table_name, + ), + ) + + def generate_altered_db_table_comment(self): + models_to_check = self.kept_model_keys.union( + self.kept_proxy_keys, self.kept_unmanaged_keys + ) + for app_label, model_name in sorted(models_to_check): + old_model_name = self.renamed_models.get( + (app_label, model_name), model_name + ) + old_model_state = self.from_state.models[app_label, old_model_name] + new_model_state = self.to_state.models[app_label, model_name] + + old_db_table_comment = old_model_state.options.get("db_table_comment") + new_db_table_comment = new_model_state.options.get("db_table_comment") + if old_db_table_comment != new_db_table_comment: + self.add_operation( + app_label, + operations.AlterModelTableComment( + name=model_name, + table_comment=new_db_table_comment, + ), + ) + + def generate_altered_options(self): + """ + Work out if any non-schema-affecting options have changed and make an + operation to represent them in state changes (in case Python code in + migrations needs them). + """ + models_to_check = self.kept_model_keys.union( + self.kept_proxy_keys, + self.kept_unmanaged_keys, + # unmanaged converted to managed + self.old_unmanaged_keys & self.new_model_keys, + # managed converted to unmanaged + self.old_model_keys & self.new_unmanaged_keys, + ) + + for app_label, model_name in sorted(models_to_check): + old_model_name = self.renamed_models.get( + (app_label, model_name), model_name + ) + old_model_state = self.from_state.models[app_label, old_model_name] + new_model_state = self.to_state.models[app_label, model_name] + old_options = { + key: value + for key, value in old_model_state.options.items() + if key in AlterModelOptions.ALTER_OPTION_KEYS + } + new_options = { + key: value + for key, value in new_model_state.options.items() + if key in AlterModelOptions.ALTER_OPTION_KEYS + } + if old_options != new_options: + self.add_operation( + app_label, + operations.AlterModelOptions( + name=model_name, + options=new_options, + ), + ) + + def generate_altered_order_with_respect_to(self): + for app_label, model_name in sorted(self.kept_model_keys): + old_model_name = self.renamed_models.get( + (app_label, model_name), model_name + ) + old_model_state = self.from_state.models[app_label, old_model_name] + new_model_state = self.to_state.models[app_label, model_name] + if old_model_state.options.get( + "order_with_respect_to" + ) != new_model_state.options.get("order_with_respect_to"): + # Make sure it comes second if we're adding + # (removal dependency is part of RemoveField) + dependencies = [] + if new_model_state.options.get("order_with_respect_to"): + dependencies.append( + ( + app_label, + model_name, + new_model_state.options["order_with_respect_to"], + True, + ) + ) + # Actually generate the operation + self.add_operation( + app_label, + operations.AlterOrderWithRespectTo( + name=model_name, + order_with_respect_to=new_model_state.options.get( + "order_with_respect_to" + ), + ), + dependencies=dependencies, + ) + + def generate_altered_managers(self): + for app_label, model_name in sorted(self.kept_model_keys): + old_model_name = self.renamed_models.get( + (app_label, model_name), model_name + ) + old_model_state = self.from_state.models[app_label, old_model_name] + new_model_state = self.to_state.models[app_label, model_name] + if old_model_state.managers != new_model_state.managers: + self.add_operation( + app_label, + operations.AlterModelManagers( + name=model_name, + managers=new_model_state.managers, + ), + ) + + def arrange_for_graph(self, changes, graph, migration_name=None): + """ + Take a result from changes() and a MigrationGraph, and fix the names + and dependencies of the changes so they extend the graph from the leaf + nodes for each app. + """ + leaves = graph.leaf_nodes() + name_map = {} + for app_label, migrations in list(changes.items()): + if not migrations: + continue + # Find the app label's current leaf node + app_leaf = None + for leaf in leaves: + if leaf[0] == app_label: + app_leaf = leaf + break + # Do they want an initial migration for this app? + if app_leaf is None and not self.questioner.ask_initial(app_label): + # They don't. + for migration in migrations: + name_map[(app_label, migration.name)] = (app_label, "__first__") + del changes[app_label] + continue + # Work out the next number in the sequence + if app_leaf is None: + next_number = 1 + else: + next_number = (self.parse_number(app_leaf[1]) or 0) + 1 + # Name each migration + for i, migration in enumerate(migrations): + if i == 0 and app_leaf: + migration.dependencies.append(app_leaf) + new_name_parts = ["%04i" % next_number] + if migration_name: + new_name_parts.append(migration_name) + elif i == 0 and not app_leaf: + new_name_parts.append("initial") + else: + new_name_parts.append(migration.suggest_name()[:100]) + new_name = "_".join(new_name_parts) + name_map[(app_label, migration.name)] = (app_label, new_name) + next_number += 1 + migration.name = new_name + # Now fix dependencies + for migrations in changes.values(): + for migration in migrations: + migration.dependencies = [ + name_map.get(d, d) for d in migration.dependencies + ] + return changes + + def _trim_to_apps(self, changes, app_labels): + """ + Take changes from arrange_for_graph() and set of app labels, and return + a modified set of changes which trims out as many migrations that are + not in app_labels as possible. Note that some other migrations may + still be present as they may be required dependencies. + """ + # Gather other app dependencies in a first pass + app_dependencies = {} + for app_label, migrations in changes.items(): + for migration in migrations: + for dep_app_label, name in migration.dependencies: + app_dependencies.setdefault(app_label, set()).add(dep_app_label) + required_apps = set(app_labels) + # Keep resolving till there's no change + old_required_apps = None + while old_required_apps != required_apps: + old_required_apps = set(required_apps) + required_apps.update( + *[app_dependencies.get(app_label, ()) for app_label in required_apps] + ) + # Remove all migrations that aren't needed + for app_label in list(changes): + if app_label not in required_apps: + del changes[app_label] + return changes + + @classmethod + def parse_number(cls, name): + """ + Given a migration name, try to extract a number from the beginning of + it. For a squashed migration such as '0001_squashed_0004…', return the + second number. If no number is found, return None. + """ + if squashed_match := re.search(r".*_squashed_(\d+)", name): + return int(squashed_match[1]) + match = re.match(r"^\d+", name) + if match: + return int(match[0]) + return None diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/exceptions.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/exceptions.py new file mode 100644 index 0000000..dd556da --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/exceptions.py @@ -0,0 +1,60 @@ +from django.db import DatabaseError + + +class AmbiguityError(Exception): + """More than one migration matches a name prefix.""" + + pass + + +class BadMigrationError(Exception): + """There's a bad migration (unreadable/bad format/etc.).""" + + pass + + +class CircularDependencyError(Exception): + """There's an impossible-to-resolve circular dependency.""" + + pass + + +class InconsistentMigrationHistory(Exception): + """An applied migration has some of its dependencies not applied.""" + + pass + + +class InvalidBasesError(ValueError): + """A model's base classes can't be resolved.""" + + pass + + +class IrreversibleError(RuntimeError): + """An irreversible migration is about to be reversed.""" + + pass + + +class NodeNotFoundError(LookupError): + """An attempt on a node is made that is not available in the graph.""" + + def __init__(self, message, node, origin=None): + self.message = message + self.origin = origin + self.node = node + + def __str__(self): + return self.message + + def __repr__(self): + return "NodeNotFoundError(%r)" % (self.node,) + + +class MigrationSchemaMissing(DatabaseError): + pass + + +class InvalidMigrationPlan(ValueError): + pass diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/executor.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/executor.py new file mode 100644 index 0000000..eb738cf --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/executor.py @@ -0,0 +1,410 @@ +from django.apps.registry import apps as global_apps +from django.db import migrations, router + +from .exceptions import InvalidMigrationPlan +from .loader import MigrationLoader +from .recorder import MigrationRecorder +from .state import ProjectState + + +class MigrationExecutor: + """ + End-to-end migration execution - load migrations and run them up or down + to a specified set of targets. + """ + + def __init__(self, connection, progress_callback=None): + self.connection = connection + self.loader = MigrationLoader(self.connection) + self.recorder = MigrationRecorder(self.connection) + self.progress_callback = progress_callback + + def migration_plan(self, targets, clean_start=False): + """ + Given a set of targets, return a list of (Migration instance, backwards?). + """ + plan = [] + if clean_start: + applied = {} + else: + applied = dict(self.loader.applied_migrations) + for target in targets: + # If the target is (app_label, None), that means unmigrate everything + if target[1] is None: + for root in self.loader.graph.root_nodes(): + if root[0] == target[0]: + for migration in self.loader.graph.backwards_plan(root): + if migration in applied: + plan.append((self.loader.graph.nodes[migration], True)) + applied.pop(migration) + # If the migration is already applied, do backwards mode, + # otherwise do forwards mode. + elif target in applied: + # If the target is missing, it's likely a replaced migration. + # Reload the graph without replacements. + if ( + self.loader.replace_migrations + and target not in self.loader.graph.node_map + ): + self.loader.replace_migrations = False + self.loader.build_graph() + return self.migration_plan(targets, clean_start=clean_start) + # Don't migrate backwards all the way to the target node (that + # may roll back dependencies in other apps that don't need to + # be rolled back); instead roll back through target's immediate + # child(ren) in the same app, and no further. + next_in_app = sorted( + n + for n in self.loader.graph.node_map[target].children + if n[0] == target[0] + ) + for node in next_in_app: + for migration in self.loader.graph.backwards_plan(node): + if migration in applied: + plan.append((self.loader.graph.nodes[migration], True)) + applied.pop(migration) + else: + for migration in self.loader.graph.forwards_plan(target): + if migration not in applied: + plan.append((self.loader.graph.nodes[migration], False)) + applied[migration] = self.loader.graph.nodes[migration] + return plan + + def _create_project_state(self, with_applied_migrations=False): + """ + Create a project state including all the applications without + migrations and applied migrations if with_applied_migrations=True. + """ + state = ProjectState(real_apps=self.loader.unmigrated_apps) + if with_applied_migrations: + # Create the forwards plan Django would follow on an empty database + full_plan = self.migration_plan( + self.loader.graph.leaf_nodes(), clean_start=True + ) + applied_migrations = { + self.loader.graph.nodes[key] + for key in self.loader.applied_migrations + if key in self.loader.graph.nodes + } + for migration, _ in full_plan: + if migration in applied_migrations: + migration.mutate_state(state, preserve=False) + return state + + def migrate(self, targets, plan=None, state=None, fake=False, fake_initial=False): + """ + Migrate the database up to the given targets. + + Django first needs to create all project states before a migration is + (un)applied and in a second step run all the database operations. + """ + # The django_migrations table must be present to record applied + # migrations, but don't create it if there are no migrations to apply. + if plan == []: + if not self.recorder.has_table(): + return self._create_project_state(with_applied_migrations=False) + else: + self.recorder.ensure_schema() + + if plan is None: + plan = self.migration_plan(targets) + # Create the forwards plan Django would follow on an empty database + full_plan = self.migration_plan( + self.loader.graph.leaf_nodes(), clean_start=True + ) + + all_forwards = all(not backwards for mig, backwards in plan) + all_backwards = all(backwards for mig, backwards in plan) + + if not plan: + if state is None: + # The resulting state should include applied migrations. + state = self._create_project_state(with_applied_migrations=True) + elif all_forwards == all_backwards: + # This should only happen if there's a mixed plan + raise InvalidMigrationPlan( + "Migration plans with both forwards and backwards migrations " + "are not supported. Please split your migration process into " + "separate plans of only forwards OR backwards migrations.", + plan, + ) + elif all_forwards: + if state is None: + # The resulting state should still include applied migrations. + state = self._create_project_state(with_applied_migrations=True) + state = self._migrate_all_forwards( + state, plan, full_plan, fake=fake, fake_initial=fake_initial + ) + else: + # No need to check for `elif all_backwards` here, as that condition + # would always evaluate to true. + state = self._migrate_all_backwards(plan, full_plan, fake=fake) + + self.check_replacements() + + return state + + def _migrate_all_forwards(self, state, plan, full_plan, fake, fake_initial): + """ + Take a list of 2-tuples of the form (migration instance, False) and + apply them in the order they occur in the full_plan. + """ + migrations_to_run = {m[0] for m in plan} + for migration, _ in full_plan: + if not migrations_to_run: + # We remove every migration that we applied from these sets so + # that we can bail out once the last migration has been applied + # and don't always run until the very end of the migration + # process. + break + if migration in migrations_to_run: + if "apps" not in state.__dict__: + if self.progress_callback: + self.progress_callback("render_start") + state.apps # Render all -- performance critical + if self.progress_callback: + self.progress_callback("render_success") + state = self.apply_migration( + state, migration, fake=fake, fake_initial=fake_initial + ) + migrations_to_run.remove(migration) + + return state + + def _migrate_all_backwards(self, plan, full_plan, fake): + """ + Take a list of 2-tuples of the form (migration instance, True) and + unapply them in reverse order they occur in the full_plan. + + Since unapplying a migration requires the project state prior to that + migration, Django will compute the migration states before each of them + in a first run over the plan and then unapply them in a second run over + the plan. + """ + migrations_to_run = {m[0] for m in plan} + # Holds all migration states prior to the migrations being unapplied + states = {} + state = self._create_project_state() + applied_migrations = { + self.loader.graph.nodes[key] + for key in self.loader.applied_migrations + if key in self.loader.graph.nodes + } + if self.progress_callback: + self.progress_callback("render_start") + for migration, _ in full_plan: + if not migrations_to_run: + # We remove every migration that we applied from this set so + # that we can bail out once the last migration has been applied + # and don't always run until the very end of the migration + # process. + break + if migration in migrations_to_run: + if "apps" not in state.__dict__: + state.apps # Render all -- performance critical + # The state before this migration + states[migration] = state + # The old state keeps as-is, we continue with the new state + state = migration.mutate_state(state, preserve=True) + migrations_to_run.remove(migration) + elif migration in applied_migrations: + # Only mutate the state if the migration is actually applied + # to make sure the resulting state doesn't include changes + # from unrelated migrations. + migration.mutate_state(state, preserve=False) + if self.progress_callback: + self.progress_callback("render_success") + + for migration, _ in plan: + self.unapply_migration(states[migration], migration, fake=fake) + applied_migrations.remove(migration) + + # Generate the post migration state by starting from the state before + # the last migration is unapplied and mutating it to include all the + # remaining applied migrations. + last_unapplied_migration = plan[-1][0] + state = states[last_unapplied_migration] + for index, (migration, _) in enumerate(full_plan): + if migration == last_unapplied_migration: + for migration, _ in full_plan[index:]: + if migration in applied_migrations: + migration.mutate_state(state, preserve=False) + break + + return state + + def apply_migration(self, state, migration, fake=False, fake_initial=False): + """Run a migration forwards.""" + migration_recorded = False + if self.progress_callback: + self.progress_callback("apply_start", migration, fake) + if not fake: + if fake_initial: + # Test to see if this is an already-applied initial migration + applied, state = self.detect_soft_applied(state, migration) + if applied: + fake = True + if not fake: + # Alright, do it normally + with self.connection.schema_editor( + atomic=migration.atomic + ) as schema_editor: + state = migration.apply(state, schema_editor) + if not schema_editor.deferred_sql: + self.record_migration(migration) + migration_recorded = True + if not migration_recorded: + self.record_migration(migration) + # Report progress + if self.progress_callback: + self.progress_callback("apply_success", migration, fake) + return state + + def record_migration(self, migration): + # For replacement migrations, record individual statuses + if migration.replaces: + for app_label, name in migration.replaces: + self.recorder.record_applied(app_label, name) + else: + self.recorder.record_applied(migration.app_label, migration.name) + + def unapply_migration(self, state, migration, fake=False): + """Run a migration backwards.""" + if self.progress_callback: + self.progress_callback("unapply_start", migration, fake) + if not fake: + with self.connection.schema_editor( + atomic=migration.atomic + ) as schema_editor: + state = migration.unapply(state, schema_editor) + # For replacement migrations, also record individual statuses. + if migration.replaces: + for app_label, name in migration.replaces: + self.recorder.record_unapplied(app_label, name) + self.recorder.record_unapplied(migration.app_label, migration.name) + # Report progress + if self.progress_callback: + self.progress_callback("unapply_success", migration, fake) + return state + + def check_replacements(self): + """ + Mark replacement migrations applied if their replaced set all are. + + Do this unconditionally on every migrate, rather than just when + migrations are applied or unapplied, to correctly handle the case + when a new squash migration is pushed to a deployment that already had + all its replaced migrations applied. In this case no new migration will + be applied, but the applied state of the squashed migration must be + maintained. + """ + applied = self.recorder.applied_migrations() + for key, migration in self.loader.replacements.items(): + all_applied = all(m in applied for m in migration.replaces) + if all_applied and key not in applied: + self.recorder.record_applied(*key) + + def detect_soft_applied(self, project_state, migration): + """ + Test whether a migration has been implicitly applied - that the + tables or columns it would create exist. This is intended only for use + on initial migrations (as it only looks for CreateModel and AddField). + """ + + def should_skip_detecting_model(migration, model): + """ + No need to detect tables for proxy models, unmanaged models, or + models that can't be migrated on the current database. + """ + return ( + model._meta.proxy + or not model._meta.managed + or not router.allow_migrate( + self.connection.alias, + migration.app_label, + model_name=model._meta.model_name, + ) + ) + + if migration.initial is None: + # Bail if the migration isn't the first one in its app + if any(app == migration.app_label for app, name in migration.dependencies): + return False, project_state + elif migration.initial is False: + # Bail if it's NOT an initial migration + return False, project_state + + if project_state is None: + after_state = self.loader.project_state( + (migration.app_label, migration.name), at_end=True + ) + else: + after_state = migration.mutate_state(project_state) + apps = after_state.apps + found_create_model_migration = False + found_add_field_migration = False + fold_identifier_case = self.connection.features.ignores_table_name_case + with self.connection.cursor() as cursor: + existing_table_names = set( + self.connection.introspection.table_names(cursor) + ) + if fold_identifier_case: + existing_table_names = { + name.casefold() for name in existing_table_names + } + # Make sure all create model and add field operations are done + for operation in migration.operations: + if isinstance(operation, migrations.CreateModel): + model = apps.get_model(migration.app_label, operation.name) + if model._meta.swapped: + # We have to fetch the model to test with from the + # main app cache, as it's not a direct dependency. + model = global_apps.get_model(model._meta.swapped) + if should_skip_detecting_model(migration, model): + continue + db_table = model._meta.db_table + if fold_identifier_case: + db_table = db_table.casefold() + if db_table not in existing_table_names: + return False, project_state + found_create_model_migration = True + elif isinstance(operation, migrations.AddField): + model = apps.get_model(migration.app_label, operation.model_name) + if model._meta.swapped: + # We have to fetch the model to test with from the + # main app cache, as it's not a direct dependency. + model = global_apps.get_model(model._meta.swapped) + if should_skip_detecting_model(migration, model): + continue + + table = model._meta.db_table + field = model._meta.get_field(operation.name) + + # Handle implicit many-to-many tables created by AddField. + if field.many_to_many: + through_db_table = field.remote_field.through._meta.db_table + if fold_identifier_case: + through_db_table = through_db_table.casefold() + if through_db_table not in existing_table_names: + return False, project_state + else: + found_add_field_migration = True + continue + with self.connection.cursor() as cursor: + columns = self.connection.introspection.get_table_description( + cursor, table + ) + for column in columns: + field_column = field.column + column_name = column.name + if fold_identifier_case: + column_name = column_name.casefold() + field_column = field_column.casefold() + if column_name == field_column: + found_add_field_migration = True + break + else: + return False, project_state + # If we get this far and we found at least one CreateModel or AddField + # migration, the migration is considered implicitly applied. + return (found_create_model_migration or found_add_field_migration), after_state diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/graph.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/graph.py new file mode 100644 index 0000000..dd845c1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/graph.py @@ -0,0 +1,333 @@ +from functools import total_ordering + +from django.db.migrations.state import ProjectState + +from .exceptions import CircularDependencyError, NodeNotFoundError + + +@total_ordering +class Node: + """ + A single node in the migration graph. Contains direct links to adjacent + nodes in either direction. + """ + + def __init__(self, key): + self.key = key + self.children = set() + self.parents = set() + + def __eq__(self, other): + return self.key == other + + def __lt__(self, other): + return self.key < other + + def __hash__(self): + return hash(self.key) + + def __getitem__(self, item): + return self.key[item] + + def __str__(self): + return str(self.key) + + def __repr__(self): + return "<%s: (%r, %r)>" % (self.__class__.__name__, self.key[0], self.key[1]) + + def add_child(self, child): + self.children.add(child) + + def add_parent(self, parent): + self.parents.add(parent) + + +class DummyNode(Node): + """ + A node that doesn't correspond to a migration file on disk. + (A squashed migration that was removed, for example.) + + After the migration graph is processed, all dummy nodes should be removed. + If there are any left, a nonexistent dependency error is raised. + """ + + def __init__(self, key, origin, error_message): + super().__init__(key) + self.origin = origin + self.error_message = error_message + + def raise_error(self): + raise NodeNotFoundError(self.error_message, self.key, origin=self.origin) + + +class MigrationGraph: + """ + Represent the digraph of all migrations in a project. + + Each migration is a node, and each dependency is an edge. There are + no implicit dependencies between numbered migrations - the numbering is + merely a convention to aid file listing. Every new numbered migration + has a declared dependency to the previous number, meaning that VCS + branch merges can be detected and resolved. + + Migrations files can be marked as replacing another set of migrations - + this is to support the "squash" feature. The graph handler isn't responsible + for these; instead, the code to load them in here should examine the + migration files and if the replaced migrations are all either unapplied + or not present, it should ignore the replaced ones, load in just the + replacing migration, and repoint any dependencies that pointed to the + replaced migrations to point to the replacing one. + + A node should be a tuple: (app_path, migration_name). The tree special-cases + things within an app - namely, root nodes and leaf nodes ignore dependencies + to other apps. + """ + + def __init__(self): + self.node_map = {} + self.nodes = {} + + def add_node(self, key, migration): + assert key not in self.node_map + node = Node(key) + self.node_map[key] = node + self.nodes[key] = migration + + def add_dummy_node(self, key, origin, error_message): + node = DummyNode(key, origin, error_message) + self.node_map[key] = node + self.nodes[key] = None + + def add_dependency(self, migration, child, parent, skip_validation=False): + """ + This may create dummy nodes if they don't yet exist. If + `skip_validation=True`, validate_consistency() should be called + afterward. + """ + if child not in self.nodes: + error_message = ( + "Migration %s dependencies reference nonexistent" + " child node %r" % (migration, child) + ) + self.add_dummy_node(child, migration, error_message) + if parent not in self.nodes: + error_message = ( + "Migration %s dependencies reference nonexistent" + " parent node %r" % (migration, parent) + ) + self.add_dummy_node(parent, migration, error_message) + self.node_map[child].add_parent(self.node_map[parent]) + self.node_map[parent].add_child(self.node_map[child]) + if not skip_validation: + self.validate_consistency() + + def remove_replaced_nodes(self, replacement, replaced): + """ + Remove each of the `replaced` nodes (when they exist). Any + dependencies that were referencing them are changed to reference the + `replacement` node instead. + """ + # Cast list of replaced keys to set to speed up lookup later. + replaced = set(replaced) + try: + replacement_node = self.node_map[replacement] + except KeyError as err: + raise NodeNotFoundError( + "Unable to find replacement node %r. It was either never added" + " to the migration graph, or has been removed." % (replacement,), + replacement, + ) from err + for replaced_key in replaced: + self.nodes.pop(replaced_key, None) + replaced_node = self.node_map.pop(replaced_key, None) + if replaced_node: + for child in replaced_node.children: + child.parents.remove(replaced_node) + # We don't want to create dependencies between the replaced + # node and the replacement node as this would lead to + # self-referencing on the replacement node at a later iteration. + if child.key not in replaced: + replacement_node.add_child(child) + child.add_parent(replacement_node) + for parent in replaced_node.parents: + parent.children.remove(replaced_node) + # Again, to avoid self-referencing. + if parent.key not in replaced: + replacement_node.add_parent(parent) + parent.add_child(replacement_node) + + def remove_replacement_node(self, replacement, replaced): + """ + The inverse operation to `remove_replaced_nodes`. Almost. Remove the + replacement node `replacement` and remap its child nodes to `replaced` + - the list of nodes it would have replaced. Don't remap its parent + nodes as they are expected to be correct already. + """ + self.nodes.pop(replacement, None) + try: + replacement_node = self.node_map.pop(replacement) + except KeyError as err: + raise NodeNotFoundError( + "Unable to remove replacement node %r. It was either never added" + " to the migration graph, or has been removed already." + % (replacement,), + replacement, + ) from err + replaced_nodes = set() + replaced_nodes_parents = set() + for key in replaced: + replaced_node = self.node_map.get(key) + if replaced_node: + replaced_nodes.add(replaced_node) + replaced_nodes_parents |= replaced_node.parents + # We're only interested in the latest replaced node, so filter out + # replaced nodes that are parents of other replaced nodes. + replaced_nodes -= replaced_nodes_parents + for child in replacement_node.children: + child.parents.remove(replacement_node) + for replaced_node in replaced_nodes: + replaced_node.add_child(child) + child.add_parent(replaced_node) + for parent in replacement_node.parents: + parent.children.remove(replacement_node) + # NOTE: There is no need to remap parent dependencies as we can + # assume the replaced nodes already have the correct ancestry. + + def validate_consistency(self): + """Ensure there are no dummy nodes remaining in the graph.""" + [n.raise_error() for n in self.node_map.values() if isinstance(n, DummyNode)] + + def forwards_plan(self, target): + """ + Given a node, return a list of which previous nodes (dependencies) must + be applied, ending with the node itself. This is the list you would + follow if applying the migrations to a database. + """ + if target not in self.nodes: + raise NodeNotFoundError("Node %r not a valid node" % (target,), target) + return self.iterative_dfs(self.node_map[target]) + + def backwards_plan(self, target): + """ + Given a node, return a list of which dependent nodes (dependencies) + must be unapplied, ending with the node itself. This is the list you + would follow if removing the migrations from a database. + """ + if target not in self.nodes: + raise NodeNotFoundError("Node %r not a valid node" % (target,), target) + return self.iterative_dfs(self.node_map[target], forwards=False) + + def iterative_dfs(self, start, forwards=True): + """Iterative depth-first search for finding dependencies.""" + visited = [] + visited_set = set() + stack = [(start, False)] + while stack: + node, processed = stack.pop() + if node in visited_set: + pass + elif processed: + visited_set.add(node) + visited.append(node.key) + else: + stack.append((node, True)) + stack += [ + (n, False) + for n in sorted(node.parents if forwards else node.children) + ] + return visited + + def root_nodes(self, app=None): + """ + Return all root nodes - that is, nodes with no dependencies inside + their app. These are the starting point for an app. + """ + roots = set() + for node in self.nodes: + if all(key[0] != node[0] for key in self.node_map[node].parents) and ( + not app or app == node[0] + ): + roots.add(node) + return sorted(roots) + + def leaf_nodes(self, app=None): + """ + Return all leaf nodes - that is, nodes with no dependents in their app. + These are the "most current" version of an app's schema. + Having more than one per app is technically an error, but one that + gets handled further up, in the interactive command - it's usually the + result of a VCS merge and needs some user input. + """ + leaves = set() + for node in self.nodes: + if all(key[0] != node[0] for key in self.node_map[node].children) and ( + not app or app == node[0] + ): + leaves.add(node) + return sorted(leaves) + + def ensure_not_cyclic(self): + # Algo from GvR: + # https://neopythonic.blogspot.com/2009/01/detecting-cycles-in-directed-graph.html + todo = set(self.nodes) + while todo: + node = todo.pop() + stack = [node] + while stack: + top = stack[-1] + for child in self.node_map[top].children: + # Use child.key instead of child to speed up the frequent + # hashing. + node = child.key + if node in stack: + cycle = stack[stack.index(node) :] + raise CircularDependencyError( + ", ".join("%s.%s" % n for n in cycle) + ) + if node in todo: + stack.append(node) + todo.remove(node) + break + else: + node = stack.pop() + + def __str__(self): + return "Graph: %s nodes, %s edges" % self._nodes_and_edges() + + def __repr__(self): + nodes, edges = self._nodes_and_edges() + return "<%s: nodes=%s, edges=%s>" % (self.__class__.__name__, nodes, edges) + + def _nodes_and_edges(self): + return len(self.nodes), sum( + len(node.parents) for node in self.node_map.values() + ) + + def _generate_plan(self, nodes, at_end): + plan = [] + for node in nodes: + for migration in self.forwards_plan(node): + if migration not in plan and (at_end or migration not in nodes): + plan.append(migration) + return plan + + def make_state(self, nodes=None, at_end=True, real_apps=None): + """ + Given a migration node or nodes, return a complete ProjectState for it. + If at_end is False, return the state before the migration has run. + If nodes is not provided, return the overall most current project state. + """ + if nodes is None: + nodes = list(self.leaf_nodes()) + if not nodes: + return ProjectState() + if not isinstance(nodes[0], tuple): + nodes = [nodes] + plan = self._generate_plan(nodes, at_end) + project_state = ProjectState(real_apps=real_apps) + for node in plan: + project_state = self.nodes[node].mutate_state(project_state, preserve=False) + return project_state + + def __contains__(self, node): + return node in self.nodes diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/loader.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/loader.py new file mode 100644 index 0000000..81dcd06 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/loader.py @@ -0,0 +1,385 @@ +import pkgutil +import sys +from importlib import import_module, reload + +from django.apps import apps +from django.conf import settings +from django.db.migrations.graph import MigrationGraph +from django.db.migrations.recorder import MigrationRecorder + +from .exceptions import ( + AmbiguityError, + BadMigrationError, + InconsistentMigrationHistory, + NodeNotFoundError, +) + +MIGRATIONS_MODULE_NAME = "migrations" + + +class MigrationLoader: + """ + Load migration files from disk and their status from the database. + + Migration files are expected to live in the "migrations" directory of + an app. Their names are entirely unimportant from a code perspective, + but will probably follow the 1234_name.py convention. + + On initialization, this class will scan those directories, and open and + read the Python files, looking for a class called Migration, which should + inherit from django.db.migrations.Migration. See + django.db.migrations.migration for what that looks like. + + Some migrations will be marked as "replacing" another set of migrations. + These are loaded into a separate set of migrations away from the main ones. + If all the migrations they replace are either unapplied or missing from + disk, then they are injected into the main set, replacing the named migrations. + Any dependency pointers to the replaced migrations are re-pointed to the + new migration. + + This does mean that this class MUST also talk to the database as well as + to disk, but this is probably fine. We're already not just operating + in memory. + """ + + def __init__( + self, + connection, + load=True, + ignore_no_migrations=False, + replace_migrations=True, + ): + self.connection = connection + self.disk_migrations = None + self.applied_migrations = None + self.ignore_no_migrations = ignore_no_migrations + self.replace_migrations = replace_migrations + if load: + self.build_graph() + + @classmethod + def migrations_module(cls, app_label): + """ + Return the path to the migrations module for the specified app_label + and a boolean indicating if the module is specified in + settings.MIGRATION_MODULE. + """ + if app_label in settings.MIGRATION_MODULES: + return settings.MIGRATION_MODULES[app_label], True + else: + app_package_name = apps.get_app_config(app_label).name + return "%s.%s" % (app_package_name, MIGRATIONS_MODULE_NAME), False + + def load_disk(self): + """Load the migrations from all INSTALLED_APPS from disk.""" + self.disk_migrations = {} + self.unmigrated_apps = set() + self.migrated_apps = set() + for app_config in apps.get_app_configs(): + # Get the migrations module directory + module_name, explicit = self.migrations_module(app_config.label) + if module_name is None: + self.unmigrated_apps.add(app_config.label) + continue + was_loaded = module_name in sys.modules + try: + module = import_module(module_name) + except ModuleNotFoundError as e: + if (explicit and self.ignore_no_migrations) or ( + not explicit and MIGRATIONS_MODULE_NAME in e.name.split(".") + ): + self.unmigrated_apps.add(app_config.label) + continue + raise + else: + # Module is not a package (e.g. migrations.py). + if not hasattr(module, "__path__"): + self.unmigrated_apps.add(app_config.label) + continue + # Empty directories are namespaces. Namespace packages have no + # __file__ and don't use a list for __path__. See + # https://docs.python.org/3/reference/import.html#namespace-packages + if getattr(module, "__file__", None) is None and not isinstance( + module.__path__, list + ): + self.unmigrated_apps.add(app_config.label) + continue + # Force a reload if it's already loaded (tests need this) + if was_loaded: + reload(module) + self.migrated_apps.add(app_config.label) + migration_names = { + name + for _, name, is_pkg in pkgutil.iter_modules(module.__path__) + if not is_pkg and name[0] not in "_~" + } + # Load migrations + for migration_name in migration_names: + migration_path = "%s.%s" % (module_name, migration_name) + try: + migration_module = import_module(migration_path) + except ImportError as e: + if "bad magic number" in str(e): + raise ImportError( + "Couldn't import %r as it appears to be a stale " + ".pyc file." % migration_path + ) from e + else: + raise + if not hasattr(migration_module, "Migration"): + raise BadMigrationError( + "Migration %s in app %s has no Migration class" + % (migration_name, app_config.label) + ) + self.disk_migrations[ + app_config.label, migration_name + ] = migration_module.Migration( + migration_name, + app_config.label, + ) + + def get_migration(self, app_label, name_prefix): + """Return the named migration or raise NodeNotFoundError.""" + return self.graph.nodes[app_label, name_prefix] + + def get_migration_by_prefix(self, app_label, name_prefix): + """ + Return the migration(s) which match the given app label and name_prefix. + """ + # Do the search + results = [] + for migration_app_label, migration_name in self.disk_migrations: + if migration_app_label == app_label and migration_name.startswith( + name_prefix + ): + results.append((migration_app_label, migration_name)) + if len(results) > 1: + raise AmbiguityError( + "There is more than one migration for '%s' with the prefix '%s'" + % (app_label, name_prefix) + ) + elif not results: + raise KeyError( + f"There is no migration for '{app_label}' with the prefix " + f"'{name_prefix}'" + ) + else: + return self.disk_migrations[results[0]] + + def check_key(self, key, current_app): + if (key[1] != "__first__" and key[1] != "__latest__") or key in self.graph: + return key + # Special-case __first__, which means "the first migration" for + # migrated apps, and is ignored for unmigrated apps. It allows + # makemigrations to declare dependencies on apps before they even have + # migrations. + if key[0] == current_app: + # Ignore __first__ references to the same app (#22325) + return + if key[0] in self.unmigrated_apps: + # This app isn't migrated, but something depends on it. + # The models will get auto-added into the state, though + # so we're fine. + return + if key[0] in self.migrated_apps: + try: + if key[1] == "__first__": + return self.graph.root_nodes(key[0])[0] + else: # "__latest__" + return self.graph.leaf_nodes(key[0])[0] + except IndexError: + if self.ignore_no_migrations: + return None + else: + raise ValueError( + "Dependency on app with no migrations: %s" % key[0] + ) + raise ValueError("Dependency on unknown app: %s" % key[0]) + + def add_internal_dependencies(self, key, migration): + """ + Internal dependencies need to be added first to ensure `__first__` + dependencies find the correct root node. + """ + for parent in migration.dependencies: + # Ignore __first__ references to the same app. + if parent[0] == key[0] and parent[1] != "__first__": + self.graph.add_dependency(migration, key, parent, skip_validation=True) + + def add_external_dependencies(self, key, migration): + for parent in migration.dependencies: + # Skip internal dependencies + if key[0] == parent[0]: + continue + parent = self.check_key(parent, key[0]) + if parent is not None: + self.graph.add_dependency(migration, key, parent, skip_validation=True) + for child in migration.run_before: + child = self.check_key(child, key[0]) + if child is not None: + self.graph.add_dependency(migration, child, key, skip_validation=True) + + def build_graph(self): + """ + Build a migration dependency graph using both the disk and database. + You'll need to rebuild the graph if you apply migrations. This isn't + usually a problem as generally migration stuff runs in a one-shot process. + """ + # Load disk data + self.load_disk() + # Load database data + if self.connection is None: + self.applied_migrations = {} + else: + recorder = MigrationRecorder(self.connection) + self.applied_migrations = recorder.applied_migrations() + # To start, populate the migration graph with nodes for ALL migrations + # and their dependencies. Also make note of replacing migrations at this step. + self.graph = MigrationGraph() + self.replacements = {} + for key, migration in self.disk_migrations.items(): + self.graph.add_node(key, migration) + # Replacing migrations. + if migration.replaces: + self.replacements[key] = migration + for key, migration in self.disk_migrations.items(): + # Internal (same app) dependencies. + self.add_internal_dependencies(key, migration) + # Add external dependencies now that the internal ones have been resolved. + for key, migration in self.disk_migrations.items(): + self.add_external_dependencies(key, migration) + # Carry out replacements where possible and if enabled. + if self.replace_migrations: + for key, migration in self.replacements.items(): + # Get applied status of each of this migration's replacement + # targets. + applied_statuses = [ + (target in self.applied_migrations) for target in migration.replaces + ] + # The replacing migration is only marked as applied if all of + # its replacement targets are. + if all(applied_statuses): + self.applied_migrations[key] = migration + else: + self.applied_migrations.pop(key, None) + # A replacing migration can be used if either all or none of + # its replacement targets have been applied. + if all(applied_statuses) or (not any(applied_statuses)): + self.graph.remove_replaced_nodes(key, migration.replaces) + else: + # This replacing migration cannot be used because it is + # partially applied. Remove it from the graph and remap + # dependencies to it (#25945). + self.graph.remove_replacement_node(key, migration.replaces) + # Ensure the graph is consistent. + try: + self.graph.validate_consistency() + except NodeNotFoundError as exc: + # Check if the missing node could have been replaced by any squash + # migration but wasn't because the squash migration was partially + # applied before. In that case raise a more understandable exception + # (#23556). + # Get reverse replacements. + reverse_replacements = {} + for key, migration in self.replacements.items(): + for replaced in migration.replaces: + reverse_replacements.setdefault(replaced, set()).add(key) + # Try to reraise exception with more detail. + if exc.node in reverse_replacements: + candidates = reverse_replacements.get(exc.node, set()) + is_replaced = any( + candidate in self.graph.nodes for candidate in candidates + ) + if not is_replaced: + tries = ", ".join("%s.%s" % c for c in candidates) + raise NodeNotFoundError( + "Migration {0} depends on nonexistent node ('{1}', '{2}'). " + "Django tried to replace migration {1}.{2} with any of [{3}] " + "but wasn't able to because some of the replaced migrations " + "are already applied.".format( + exc.origin, exc.node[0], exc.node[1], tries + ), + exc.node, + ) from exc + raise + self.graph.ensure_not_cyclic() + + def check_consistent_history(self, connection): + """ + Raise InconsistentMigrationHistory if any applied migrations have + unapplied dependencies. + """ + recorder = MigrationRecorder(connection) + applied = recorder.applied_migrations() + for migration in applied: + # If the migration is unknown, skip it. + if migration not in self.graph.nodes: + continue + for parent in self.graph.node_map[migration].parents: + if parent not in applied: + # Skip unapplied squashed migrations that have all of their + # `replaces` applied. + if parent in self.replacements: + if all( + m in applied for m in self.replacements[parent].replaces + ): + continue + raise InconsistentMigrationHistory( + "Migration {}.{} is applied before its dependency " + "{}.{} on database '{}'.".format( + migration[0], + migration[1], + parent[0], + parent[1], + connection.alias, + ) + ) + + def detect_conflicts(self): + """ + Look through the loaded graph and detect any conflicts - apps + with more than one leaf migration. Return a dict of the app labels + that conflict with the migration names that conflict. + """ + seen_apps = {} + conflicting_apps = set() + for app_label, migration_name in self.graph.leaf_nodes(): + if app_label in seen_apps: + conflicting_apps.add(app_label) + seen_apps.setdefault(app_label, set()).add(migration_name) + return { + app_label: sorted(seen_apps[app_label]) for app_label in conflicting_apps + } + + def project_state(self, nodes=None, at_end=True): + """ + Return a ProjectState object representing the most recent state + that the loaded migrations represent. + + See graph.make_state() for the meaning of "nodes" and "at_end". + """ + return self.graph.make_state( + nodes=nodes, at_end=at_end, real_apps=self.unmigrated_apps + ) + + def collect_sql(self, plan): + """ + Take a migration plan and return a list of collected SQL statements + that represent the best-efforts version of that plan. + """ + statements = [] + state = None + for migration, backwards in plan: + with self.connection.schema_editor( + collect_sql=True, atomic=migration.atomic + ) as schema_editor: + if state is None: + state = self.project_state( + (migration.app_label, migration.name), at_end=False + ) + if not backwards: + state = migration.apply(state, schema_editor, collect_sql=True) + else: + state = migration.unapply(state, schema_editor, collect_sql=True) + statements.extend(schema_editor.collected_sql) + return statements diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/migration.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/migration.py new file mode 100644 index 0000000..3c7713c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/migration.py @@ -0,0 +1,239 @@ +import re + +from django.db.migrations.utils import get_migration_name_timestamp +from django.db.transaction import atomic + +from .exceptions import IrreversibleError + + +class Migration: + """ + The base class for all migrations. + + Migration files will import this from django.db.migrations.Migration + and subclass it as a class called Migration. It will have one or more + of the following attributes: + + - operations: A list of Operation instances, probably from + django.db.migrations.operations + - dependencies: A list of tuples of (app_path, migration_name) + - run_before: A list of tuples of (app_path, migration_name) + - replaces: A list of migration_names + + Note that all migrations come out of migrations and into the Loader or + Graph as instances, having been initialized with their app label and name. + """ + + # Operations to apply during this migration, in order. + operations = [] + + # Other migrations that should be run before this migration. + # Should be a list of (app, migration_name). + dependencies = [] + + # Other migrations that should be run after this one (i.e. have + # this migration added to their dependencies). Useful to make third-party + # apps' migrations run after your AUTH_USER replacement, for example. + run_before = [] + + # Migration names in this app that this migration replaces. If this is + # non-empty, this migration will only be applied if all these migrations + # are not applied. + replaces = [] + + # Is this an initial migration? Initial migrations are skipped on + # --fake-initial if the table or fields already exist. If None, check if + # the migration has any dependencies to determine if there are dependencies + # to tell if db introspection needs to be done. If True, always perform + # introspection. If False, never perform introspection. + initial = None + + # Whether to wrap the whole migration in a transaction. Only has an effect + # on database backends which support transactional DDL. + atomic = True + + def __init__(self, name, app_label): + self.name = name + self.app_label = app_label + # Copy dependencies & other attrs as we might mutate them at runtime + self.operations = list(self.__class__.operations) + self.dependencies = list(self.__class__.dependencies) + self.run_before = list(self.__class__.run_before) + self.replaces = list(self.__class__.replaces) + + def __eq__(self, other): + return ( + isinstance(other, Migration) + and self.name == other.name + and self.app_label == other.app_label + ) + + def __repr__(self): + return "" % (self.app_label, self.name) + + def __str__(self): + return "%s.%s" % (self.app_label, self.name) + + def __hash__(self): + return hash("%s.%s" % (self.app_label, self.name)) + + def mutate_state(self, project_state, preserve=True): + """ + Take a ProjectState and return a new one with the migration's + operations applied to it. Preserve the original object state by + default and return a mutated state from a copy. + """ + new_state = project_state + if preserve: + new_state = project_state.clone() + + for operation in self.operations: + operation.state_forwards(self.app_label, new_state) + return new_state + + def apply(self, project_state, schema_editor, collect_sql=False): + """ + Take a project_state representing all migrations prior to this one + and a schema_editor for a live database and apply the migration + in a forwards order. + + Return the resulting project state for efficient reuse by following + Migrations. + """ + for operation in self.operations: + # If this operation cannot be represented as SQL, place a comment + # there instead + if collect_sql: + schema_editor.collected_sql.append("--") + schema_editor.collected_sql.append("-- %s" % operation.describe()) + schema_editor.collected_sql.append("--") + if not operation.reduces_to_sql: + schema_editor.collected_sql.append( + "-- THIS OPERATION CANNOT BE WRITTEN AS SQL" + ) + continue + collected_sql_before = len(schema_editor.collected_sql) + # Save the state before the operation has run + old_state = project_state.clone() + operation.state_forwards(self.app_label, project_state) + # Run the operation + atomic_operation = operation.atomic or ( + self.atomic and operation.atomic is not False + ) + if not schema_editor.atomic_migration and atomic_operation: + # Force a transaction on a non-transactional-DDL backend or an + # atomic operation inside a non-atomic migration. + with atomic(schema_editor.connection.alias): + operation.database_forwards( + self.app_label, schema_editor, old_state, project_state + ) + else: + # Normal behaviour + operation.database_forwards( + self.app_label, schema_editor, old_state, project_state + ) + if collect_sql and collected_sql_before == len(schema_editor.collected_sql): + schema_editor.collected_sql.append("-- (no-op)") + return project_state + + def unapply(self, project_state, schema_editor, collect_sql=False): + """ + Take a project_state representing all migrations prior to this one + and a schema_editor for a live database and apply the migration + in a reverse order. + + The backwards migration process consists of two phases: + + 1. The intermediate states from right before the first until right + after the last operation inside this migration are preserved. + 2. The operations are applied in reverse order using the states + recorded in step 1. + """ + # Construct all the intermediate states we need for a reverse migration + to_run = [] + new_state = project_state + # Phase 1 + for operation in self.operations: + # If it's irreversible, error out + if not operation.reversible: + raise IrreversibleError( + "Operation %s in %s is not reversible" % (operation, self) + ) + # Preserve new state from previous run to not tamper the same state + # over all operations + new_state = new_state.clone() + old_state = new_state.clone() + operation.state_forwards(self.app_label, new_state) + to_run.insert(0, (operation, old_state, new_state)) + + # Phase 2 + for operation, to_state, from_state in to_run: + if collect_sql: + schema_editor.collected_sql.append("--") + schema_editor.collected_sql.append("-- %s" % operation.describe()) + schema_editor.collected_sql.append("--") + if not operation.reduces_to_sql: + schema_editor.collected_sql.append( + "-- THIS OPERATION CANNOT BE WRITTEN AS SQL" + ) + continue + collected_sql_before = len(schema_editor.collected_sql) + atomic_operation = operation.atomic or ( + self.atomic and operation.atomic is not False + ) + if not schema_editor.atomic_migration and atomic_operation: + # Force a transaction on a non-transactional-DDL backend or an + # atomic operation inside a non-atomic migration. + with atomic(schema_editor.connection.alias): + operation.database_backwards( + self.app_label, schema_editor, from_state, to_state + ) + else: + # Normal behaviour + operation.database_backwards( + self.app_label, schema_editor, from_state, to_state + ) + if collect_sql and collected_sql_before == len(schema_editor.collected_sql): + schema_editor.collected_sql.append("-- (no-op)") + return project_state + + def suggest_name(self): + """ + Suggest a name for the operations this migration might represent. Names + are not guaranteed to be unique, but put some effort into the fallback + name to avoid VCS conflicts if possible. + """ + if self.initial: + return "initial" + + raw_fragments = [op.migration_name_fragment for op in self.operations] + fragments = [re.sub(r"\W+", "_", name) for name in raw_fragments if name] + + if not fragments or len(fragments) != len(self.operations): + return "auto_%s" % get_migration_name_timestamp() + + name = fragments[0] + for fragment in fragments[1:]: + new_name = f"{name}_{fragment}" + if len(new_name) > 52: + name = f"{name}_and_more" + break + name = new_name + return name + + +class SwappableTuple(tuple): + """ + Subclass of tuple so Django can tell this was originally a swappable + dependency when it reads the migration file. + """ + + def __new__(cls, value, setting): + self = tuple.__new__(cls, value) + self.setting = setting + return self + + +def swappable_dependency(value): + """Turn a setting value into a dependency.""" + return SwappableTuple((value.split(".", 1)[0], "__first__"), value) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/operations/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/operations/__init__.py new file mode 100644 index 0000000..90dbdf8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/operations/__init__.py @@ -0,0 +1,44 @@ +from .fields import AddField, AlterField, RemoveField, RenameField +from .models import ( + AddConstraint, + AddIndex, + AlterIndexTogether, + AlterModelManagers, + AlterModelOptions, + AlterModelTable, + AlterModelTableComment, + AlterOrderWithRespectTo, + AlterUniqueTogether, + CreateModel, + DeleteModel, + RemoveConstraint, + RemoveIndex, + RenameIndex, + RenameModel, +) +from .special import RunPython, RunSQL, SeparateDatabaseAndState + +__all__ = [ + "CreateModel", + "DeleteModel", + "AlterModelTable", + "AlterModelTableComment", + "AlterUniqueTogether", + "RenameModel", + "AlterIndexTogether", + "AlterModelOptions", + "AddIndex", + "RemoveIndex", + "RenameIndex", + "AddField", + "RemoveField", + "AlterField", + "RenameField", + "AddConstraint", + "RemoveConstraint", + "SeparateDatabaseAndState", + "RunSQL", + "RunPython", + "AlterOrderWithRespectTo", + "AlterModelManagers", +] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/operations/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/operations/base.py new file mode 100644 index 0000000..7d4dff2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/operations/base.py @@ -0,0 +1,146 @@ +from django.db import router + + +class Operation: + """ + Base class for migration operations. + + It's responsible for both mutating the in-memory model state + (see db/migrations/state.py) to represent what it performs, as well + as actually performing it against a live database. + + Note that some operations won't modify memory state at all (e.g. data + copying operations), and some will need their modifications to be + optionally specified by the user (e.g. custom Python code snippets) + + Due to the way this class deals with deconstruction, it should be + considered immutable. + """ + + # If this migration can be run in reverse. + # Some operations are impossible to reverse, like deleting data. + reversible = True + + # Can this migration be represented as SQL? (things like RunPython cannot) + reduces_to_sql = True + + # Should this operation be forced as atomic even on backends with no + # DDL transaction support (i.e., does it have no DDL, like RunPython) + atomic = False + + # Should this operation be considered safe to elide and optimize across? + elidable = False + + serialization_expand_args = [] + + def __new__(cls, *args, **kwargs): + # We capture the arguments to make returning them trivial + self = object.__new__(cls) + self._constructor_args = (args, kwargs) + return self + + def deconstruct(self): + """ + Return a 3-tuple of class import path (or just name if it lives + under django.db.migrations), positional arguments, and keyword + arguments. + """ + return ( + self.__class__.__name__, + self._constructor_args[0], + self._constructor_args[1], + ) + + def state_forwards(self, app_label, state): + """ + Take the state from the previous migration, and mutate it + so that it matches what this migration would perform. + """ + raise NotImplementedError( + "subclasses of Operation must provide a state_forwards() method" + ) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + """ + Perform the mutation on the database schema in the normal + (forwards) direction. + """ + raise NotImplementedError( + "subclasses of Operation must provide a database_forwards() method" + ) + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + """ + Perform the mutation on the database schema in the reverse + direction - e.g. if this were CreateModel, it would in fact + drop the model's table. + """ + raise NotImplementedError( + "subclasses of Operation must provide a database_backwards() method" + ) + + def describe(self): + """ + Output a brief summary of what the action does. + """ + return "%s: %s" % (self.__class__.__name__, self._constructor_args) + + @property + def migration_name_fragment(self): + """ + A filename part suitable for automatically naming a migration + containing this operation, or None if not applicable. + """ + return None + + def references_model(self, name, app_label): + """ + Return True if there is a chance this operation references the given + model name (as a string), with an app label for accuracy. + + Used for optimization. If in doubt, return True; + returning a false positive will merely make the optimizer a little + less efficient, while returning a false negative may result in an + unusable optimized migration. + """ + return True + + def references_field(self, model_name, name, app_label): + """ + Return True if there is a chance this operation references the given + field name, with an app label for accuracy. + + Used for optimization. If in doubt, return True. + """ + return self.references_model(model_name, app_label) + + def allow_migrate_model(self, connection_alias, model): + """ + Return whether or not a model may be migrated. + + This is a thin wrapper around router.allow_migrate_model() that + preemptively rejects any proxy, swapped out, or unmanaged model. + """ + if not model._meta.can_migrate(connection_alias): + return False + + return router.allow_migrate_model(connection_alias, model) + + def reduce(self, operation, app_label): + """ + Return either a list of operations the actual operation should be + replaced with or a boolean that indicates whether or not the specified + operation can be optimized across. + """ + if self.elidable: + return [operation] + elif operation.elidable: + return [self] + return False + + def __repr__(self): + return "<%s %s%s>" % ( + self.__class__.__name__, + ", ".join(map(repr, self._constructor_args[0])), + ",".join(" %s=%r" % x for x in self._constructor_args[1].items()), + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/operations/fields.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/operations/fields.py new file mode 100644 index 0000000..fc5640b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/operations/fields.py @@ -0,0 +1,357 @@ +from django.db.migrations.utils import field_references +from django.db.models import NOT_PROVIDED +from django.utils.functional import cached_property + +from .base import Operation + + +class FieldOperation(Operation): + def __init__(self, model_name, name, field=None): + self.model_name = model_name + self.name = name + self.field = field + + @cached_property + def model_name_lower(self): + return self.model_name.lower() + + @cached_property + def name_lower(self): + return self.name.lower() + + def is_same_model_operation(self, operation): + return self.model_name_lower == operation.model_name_lower + + def is_same_field_operation(self, operation): + return ( + self.is_same_model_operation(operation) + and self.name_lower == operation.name_lower + ) + + def references_model(self, name, app_label): + name_lower = name.lower() + if name_lower == self.model_name_lower: + return True + if self.field: + return bool( + field_references( + (app_label, self.model_name_lower), + self.field, + (app_label, name_lower), + ) + ) + return False + + def references_field(self, model_name, name, app_label): + model_name_lower = model_name.lower() + # Check if this operation locally references the field. + if model_name_lower == self.model_name_lower: + if name == self.name: + return True + elif ( + self.field + and hasattr(self.field, "from_fields") + and name in self.field.from_fields + ): + return True + # Check if this operation remotely references the field. + if self.field is None: + return False + return bool( + field_references( + (app_label, self.model_name_lower), + self.field, + (app_label, model_name_lower), + name, + ) + ) + + def reduce(self, operation, app_label): + return super().reduce(operation, app_label) or not operation.references_field( + self.model_name, self.name, app_label + ) + + +class AddField(FieldOperation): + """Add a field to a model.""" + + def __init__(self, model_name, name, field, preserve_default=True): + self.preserve_default = preserve_default + super().__init__(model_name, name, field) + + def deconstruct(self): + kwargs = { + "model_name": self.model_name, + "name": self.name, + "field": self.field, + } + if self.preserve_default is not True: + kwargs["preserve_default"] = self.preserve_default + return (self.__class__.__name__, [], kwargs) + + def state_forwards(self, app_label, state): + state.add_field( + app_label, + self.model_name_lower, + self.name, + self.field, + self.preserve_default, + ) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + to_model = to_state.apps.get_model(app_label, self.model_name) + if self.allow_migrate_model(schema_editor.connection.alias, to_model): + from_model = from_state.apps.get_model(app_label, self.model_name) + field = to_model._meta.get_field(self.name) + if not self.preserve_default: + field.default = self.field.default + schema_editor.add_field( + from_model, + field, + ) + if not self.preserve_default: + field.default = NOT_PROVIDED + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + from_model = from_state.apps.get_model(app_label, self.model_name) + if self.allow_migrate_model(schema_editor.connection.alias, from_model): + schema_editor.remove_field( + from_model, from_model._meta.get_field(self.name) + ) + + def describe(self): + return "Add field %s to %s" % (self.name, self.model_name) + + @property + def migration_name_fragment(self): + return "%s_%s" % (self.model_name_lower, self.name_lower) + + def reduce(self, operation, app_label): + if isinstance(operation, FieldOperation) and self.is_same_field_operation( + operation + ): + if isinstance(operation, AlterField): + return [ + AddField( + model_name=self.model_name, + name=operation.name, + field=operation.field, + ), + ] + elif isinstance(operation, RemoveField): + return [] + elif isinstance(operation, RenameField): + return [ + AddField( + model_name=self.model_name, + name=operation.new_name, + field=self.field, + ), + ] + return super().reduce(operation, app_label) + + +class RemoveField(FieldOperation): + """Remove a field from a model.""" + + def deconstruct(self): + kwargs = { + "model_name": self.model_name, + "name": self.name, + } + return (self.__class__.__name__, [], kwargs) + + def state_forwards(self, app_label, state): + state.remove_field(app_label, self.model_name_lower, self.name) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + from_model = from_state.apps.get_model(app_label, self.model_name) + if self.allow_migrate_model(schema_editor.connection.alias, from_model): + schema_editor.remove_field( + from_model, from_model._meta.get_field(self.name) + ) + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + to_model = to_state.apps.get_model(app_label, self.model_name) + if self.allow_migrate_model(schema_editor.connection.alias, to_model): + from_model = from_state.apps.get_model(app_label, self.model_name) + schema_editor.add_field(from_model, to_model._meta.get_field(self.name)) + + def describe(self): + return "Remove field %s from %s" % (self.name, self.model_name) + + @property + def migration_name_fragment(self): + return "remove_%s_%s" % (self.model_name_lower, self.name_lower) + + def reduce(self, operation, app_label): + from .models import DeleteModel + + if ( + isinstance(operation, DeleteModel) + and operation.name_lower == self.model_name_lower + ): + return [operation] + return super().reduce(operation, app_label) + + +class AlterField(FieldOperation): + """ + Alter a field's database column (e.g. null, max_length) to the provided + new field. + """ + + def __init__(self, model_name, name, field, preserve_default=True): + self.preserve_default = preserve_default + super().__init__(model_name, name, field) + + def deconstruct(self): + kwargs = { + "model_name": self.model_name, + "name": self.name, + "field": self.field, + } + if self.preserve_default is not True: + kwargs["preserve_default"] = self.preserve_default + return (self.__class__.__name__, [], kwargs) + + def state_forwards(self, app_label, state): + state.alter_field( + app_label, + self.model_name_lower, + self.name, + self.field, + self.preserve_default, + ) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + to_model = to_state.apps.get_model(app_label, self.model_name) + if self.allow_migrate_model(schema_editor.connection.alias, to_model): + from_model = from_state.apps.get_model(app_label, self.model_name) + from_field = from_model._meta.get_field(self.name) + to_field = to_model._meta.get_field(self.name) + if not self.preserve_default: + to_field.default = self.field.default + schema_editor.alter_field(from_model, from_field, to_field) + if not self.preserve_default: + to_field.default = NOT_PROVIDED + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + self.database_forwards(app_label, schema_editor, from_state, to_state) + + def describe(self): + return "Alter field %s on %s" % (self.name, self.model_name) + + @property + def migration_name_fragment(self): + return "alter_%s_%s" % (self.model_name_lower, self.name_lower) + + def reduce(self, operation, app_label): + if isinstance( + operation, (AlterField, RemoveField) + ) and self.is_same_field_operation(operation): + return [operation] + elif ( + isinstance(operation, RenameField) + and self.is_same_field_operation(operation) + and self.field.db_column is None + ): + return [ + operation, + AlterField( + model_name=self.model_name, + name=operation.new_name, + field=self.field, + ), + ] + return super().reduce(operation, app_label) + + +class RenameField(FieldOperation): + """Rename a field on the model. Might affect db_column too.""" + + def __init__(self, model_name, old_name, new_name): + self.old_name = old_name + self.new_name = new_name + super().__init__(model_name, old_name) + + @cached_property + def old_name_lower(self): + return self.old_name.lower() + + @cached_property + def new_name_lower(self): + return self.new_name.lower() + + def deconstruct(self): + kwargs = { + "model_name": self.model_name, + "old_name": self.old_name, + "new_name": self.new_name, + } + return (self.__class__.__name__, [], kwargs) + + def state_forwards(self, app_label, state): + state.rename_field( + app_label, self.model_name_lower, self.old_name, self.new_name + ) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + to_model = to_state.apps.get_model(app_label, self.model_name) + if self.allow_migrate_model(schema_editor.connection.alias, to_model): + from_model = from_state.apps.get_model(app_label, self.model_name) + schema_editor.alter_field( + from_model, + from_model._meta.get_field(self.old_name), + to_model._meta.get_field(self.new_name), + ) + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + to_model = to_state.apps.get_model(app_label, self.model_name) + if self.allow_migrate_model(schema_editor.connection.alias, to_model): + from_model = from_state.apps.get_model(app_label, self.model_name) + schema_editor.alter_field( + from_model, + from_model._meta.get_field(self.new_name), + to_model._meta.get_field(self.old_name), + ) + + def describe(self): + return "Rename field %s on %s to %s" % ( + self.old_name, + self.model_name, + self.new_name, + ) + + @property + def migration_name_fragment(self): + return "rename_%s_%s_%s" % ( + self.old_name_lower, + self.model_name_lower, + self.new_name_lower, + ) + + def references_field(self, model_name, name, app_label): + return self.references_model(model_name, app_label) and ( + name.lower() == self.old_name_lower or name.lower() == self.new_name_lower + ) + + def reduce(self, operation, app_label): + if ( + isinstance(operation, RenameField) + and self.is_same_model_operation(operation) + and self.new_name_lower == operation.old_name_lower + ): + return [ + RenameField( + self.model_name, + self.old_name, + operation.new_name, + ), + ] + # Skip `FieldOperation.reduce` as we want to run `references_field` + # against self.old_name and self.new_name. + return super(FieldOperation, self).reduce(operation, app_label) or not ( + operation.references_field(self.model_name, self.old_name, app_label) + or operation.references_field(self.model_name, self.new_name, app_label) + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/operations/models.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/operations/models.py new file mode 100644 index 0000000..b18ef55 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/operations/models.py @@ -0,0 +1,1219 @@ +from django.db import models +from django.db.migrations.operations.base import Operation +from django.db.migrations.state import ModelState +from django.db.migrations.utils import field_references, resolve_relation +from django.db.models.options import normalize_together +from django.utils.functional import cached_property + +from .fields import AddField, AlterField, FieldOperation, RemoveField, RenameField + + +def _check_for_duplicates(arg_name, objs): + used_vals = set() + for val in objs: + if val in used_vals: + raise ValueError( + "Found duplicate value %s in CreateModel %s argument." % (val, arg_name) + ) + used_vals.add(val) + + +class ModelOperation(Operation): + def __init__(self, name): + self.name = name + + @cached_property + def name_lower(self): + return self.name.lower() + + def references_model(self, name, app_label): + return name.lower() == self.name_lower + + def reduce(self, operation, app_label): + return super().reduce(operation, app_label) or self.can_reduce_through( + operation, app_label + ) + + def can_reduce_through(self, operation, app_label): + return not operation.references_model(self.name, app_label) + + +class CreateModel(ModelOperation): + """Create a model's table.""" + + serialization_expand_args = ["fields", "options", "managers"] + + def __init__(self, name, fields, options=None, bases=None, managers=None): + self.fields = fields + self.options = options or {} + self.bases = bases or (models.Model,) + self.managers = managers or [] + super().__init__(name) + # Sanity-check that there are no duplicated field names, bases, or + # manager names + _check_for_duplicates("fields", (name for name, _ in self.fields)) + _check_for_duplicates( + "bases", + ( + base._meta.label_lower + if hasattr(base, "_meta") + else base.lower() + if isinstance(base, str) + else base + for base in self.bases + ), + ) + _check_for_duplicates("managers", (name for name, _ in self.managers)) + + def deconstruct(self): + kwargs = { + "name": self.name, + "fields": self.fields, + } + if self.options: + kwargs["options"] = self.options + if self.bases and self.bases != (models.Model,): + kwargs["bases"] = self.bases + if self.managers and self.managers != [("objects", models.Manager())]: + kwargs["managers"] = self.managers + return (self.__class__.__qualname__, [], kwargs) + + def state_forwards(self, app_label, state): + state.add_model( + ModelState( + app_label, + self.name, + list(self.fields), + dict(self.options), + tuple(self.bases), + list(self.managers), + ) + ) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + model = to_state.apps.get_model(app_label, self.name) + if self.allow_migrate_model(schema_editor.connection.alias, model): + schema_editor.create_model(model) + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + model = from_state.apps.get_model(app_label, self.name) + if self.allow_migrate_model(schema_editor.connection.alias, model): + schema_editor.delete_model(model) + + def describe(self): + return "Create %smodel %s" % ( + "proxy " if self.options.get("proxy", False) else "", + self.name, + ) + + @property + def migration_name_fragment(self): + return self.name_lower + + def references_model(self, name, app_label): + name_lower = name.lower() + if name_lower == self.name_lower: + return True + + # Check we didn't inherit from the model + reference_model_tuple = (app_label, name_lower) + for base in self.bases: + if ( + base is not models.Model + and isinstance(base, (models.base.ModelBase, str)) + and resolve_relation(base, app_label) == reference_model_tuple + ): + return True + + # Check we have no FKs/M2Ms with it + for _name, field in self.fields: + if field_references( + (app_label, self.name_lower), field, reference_model_tuple + ): + return True + return False + + def reduce(self, operation, app_label): + if ( + isinstance(operation, DeleteModel) + and self.name_lower == operation.name_lower + and not self.options.get("proxy", False) + ): + return [] + elif ( + isinstance(operation, RenameModel) + and self.name_lower == operation.old_name_lower + ): + return [ + CreateModel( + operation.new_name, + fields=self.fields, + options=self.options, + bases=self.bases, + managers=self.managers, + ), + ] + elif ( + isinstance(operation, AlterModelOptions) + and self.name_lower == operation.name_lower + ): + options = {**self.options, **operation.options} + for key in operation.ALTER_OPTION_KEYS: + if key not in operation.options: + options.pop(key, None) + return [ + CreateModel( + self.name, + fields=self.fields, + options=options, + bases=self.bases, + managers=self.managers, + ), + ] + elif ( + isinstance(operation, AlterModelManagers) + and self.name_lower == operation.name_lower + ): + return [ + CreateModel( + self.name, + fields=self.fields, + options=self.options, + bases=self.bases, + managers=operation.managers, + ), + ] + elif ( + isinstance(operation, AlterTogetherOptionOperation) + and self.name_lower == operation.name_lower + ): + return [ + CreateModel( + self.name, + fields=self.fields, + options={ + **self.options, + **{operation.option_name: operation.option_value}, + }, + bases=self.bases, + managers=self.managers, + ), + ] + elif ( + isinstance(operation, AlterOrderWithRespectTo) + and self.name_lower == operation.name_lower + ): + return [ + CreateModel( + self.name, + fields=self.fields, + options={ + **self.options, + "order_with_respect_to": operation.order_with_respect_to, + }, + bases=self.bases, + managers=self.managers, + ), + ] + elif ( + isinstance(operation, FieldOperation) + and self.name_lower == operation.model_name_lower + ): + if isinstance(operation, AddField): + return [ + CreateModel( + self.name, + fields=self.fields + [(operation.name, operation.field)], + options=self.options, + bases=self.bases, + managers=self.managers, + ), + ] + elif isinstance(operation, AlterField): + return [ + CreateModel( + self.name, + fields=[ + (n, operation.field if n == operation.name else v) + for n, v in self.fields + ], + options=self.options, + bases=self.bases, + managers=self.managers, + ), + ] + elif isinstance(operation, RemoveField): + options = self.options.copy() + for option_name in ("unique_together", "index_together"): + option = options.pop(option_name, None) + if option: + option = set( + filter( + bool, + ( + tuple( + f for f in fields if f != operation.name_lower + ) + for fields in option + ), + ) + ) + if option: + options[option_name] = option + order_with_respect_to = options.get("order_with_respect_to") + if order_with_respect_to == operation.name_lower: + del options["order_with_respect_to"] + return [ + CreateModel( + self.name, + fields=[ + (n, v) + for n, v in self.fields + if n.lower() != operation.name_lower + ], + options=options, + bases=self.bases, + managers=self.managers, + ), + ] + elif isinstance(operation, RenameField): + options = self.options.copy() + for option_name in ("unique_together", "index_together"): + option = options.get(option_name) + if option: + options[option_name] = { + tuple( + operation.new_name if f == operation.old_name else f + for f in fields + ) + for fields in option + } + order_with_respect_to = options.get("order_with_respect_to") + if order_with_respect_to == operation.old_name: + options["order_with_respect_to"] = operation.new_name + return [ + CreateModel( + self.name, + fields=[ + (operation.new_name if n == operation.old_name else n, v) + for n, v in self.fields + ], + options=options, + bases=self.bases, + managers=self.managers, + ), + ] + elif ( + isinstance(operation, IndexOperation) + and self.name_lower == operation.model_name_lower + ): + if isinstance(operation, AddIndex): + return [ + CreateModel( + self.name, + fields=self.fields, + options={ + **self.options, + "indexes": [ + *self.options.get("indexes", []), + operation.index, + ], + }, + bases=self.bases, + managers=self.managers, + ), + ] + elif isinstance(operation, RemoveIndex): + options_indexes = [ + index + for index in self.options.get("indexes", []) + if index.name != operation.name + ] + return [ + CreateModel( + self.name, + fields=self.fields, + options={ + **self.options, + "indexes": options_indexes, + }, + bases=self.bases, + managers=self.managers, + ), + ] + elif isinstance(operation, RenameIndex) and operation.old_fields: + options_index_together = { + fields + for fields in self.options.get("index_together", []) + if fields != operation.old_fields + } + if options_index_together: + self.options["index_together"] = options_index_together + else: + self.options.pop("index_together", None) + return [ + CreateModel( + self.name, + fields=self.fields, + options={ + **self.options, + "indexes": [ + *self.options.get("indexes", []), + models.Index( + fields=operation.old_fields, name=operation.new_name + ), + ], + }, + bases=self.bases, + managers=self.managers, + ), + ] + return super().reduce(operation, app_label) + + +class DeleteModel(ModelOperation): + """Drop a model's table.""" + + def deconstruct(self): + kwargs = { + "name": self.name, + } + return (self.__class__.__qualname__, [], kwargs) + + def state_forwards(self, app_label, state): + state.remove_model(app_label, self.name_lower) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + model = from_state.apps.get_model(app_label, self.name) + if self.allow_migrate_model(schema_editor.connection.alias, model): + schema_editor.delete_model(model) + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + model = to_state.apps.get_model(app_label, self.name) + if self.allow_migrate_model(schema_editor.connection.alias, model): + schema_editor.create_model(model) + + def references_model(self, name, app_label): + # The deleted model could be referencing the specified model through + # related fields. + return True + + def describe(self): + return "Delete model %s" % self.name + + @property + def migration_name_fragment(self): + return "delete_%s" % self.name_lower + + +class RenameModel(ModelOperation): + """Rename a model.""" + + def __init__(self, old_name, new_name): + self.old_name = old_name + self.new_name = new_name + super().__init__(old_name) + + @cached_property + def old_name_lower(self): + return self.old_name.lower() + + @cached_property + def new_name_lower(self): + return self.new_name.lower() + + def deconstruct(self): + kwargs = { + "old_name": self.old_name, + "new_name": self.new_name, + } + return (self.__class__.__qualname__, [], kwargs) + + def state_forwards(self, app_label, state): + state.rename_model(app_label, self.old_name, self.new_name) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + new_model = to_state.apps.get_model(app_label, self.new_name) + if self.allow_migrate_model(schema_editor.connection.alias, new_model): + old_model = from_state.apps.get_model(app_label, self.old_name) + # Move the main table + schema_editor.alter_db_table( + new_model, + old_model._meta.db_table, + new_model._meta.db_table, + ) + # Alter the fields pointing to us + for related_object in old_model._meta.related_objects: + if related_object.related_model == old_model: + model = new_model + related_key = (app_label, self.new_name_lower) + else: + model = related_object.related_model + related_key = ( + related_object.related_model._meta.app_label, + related_object.related_model._meta.model_name, + ) + to_field = to_state.apps.get_model(*related_key)._meta.get_field( + related_object.field.name + ) + schema_editor.alter_field( + model, + related_object.field, + to_field, + ) + # Rename M2M fields whose name is based on this model's name. + fields = zip( + old_model._meta.local_many_to_many, new_model._meta.local_many_to_many + ) + for old_field, new_field in fields: + # Skip self-referential fields as these are renamed above. + if ( + new_field.model == new_field.related_model + or not new_field.remote_field.through._meta.auto_created + ): + continue + # Rename columns and the M2M table. + schema_editor._alter_many_to_many( + new_model, + old_field, + new_field, + strict=False, + ) + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + self.new_name_lower, self.old_name_lower = ( + self.old_name_lower, + self.new_name_lower, + ) + self.new_name, self.old_name = self.old_name, self.new_name + + self.database_forwards(app_label, schema_editor, from_state, to_state) + + self.new_name_lower, self.old_name_lower = ( + self.old_name_lower, + self.new_name_lower, + ) + self.new_name, self.old_name = self.old_name, self.new_name + + def references_model(self, name, app_label): + return ( + name.lower() == self.old_name_lower or name.lower() == self.new_name_lower + ) + + def describe(self): + return "Rename model %s to %s" % (self.old_name, self.new_name) + + @property + def migration_name_fragment(self): + return "rename_%s_%s" % (self.old_name_lower, self.new_name_lower) + + def reduce(self, operation, app_label): + if ( + isinstance(operation, RenameModel) + and self.new_name_lower == operation.old_name_lower + ): + return [ + RenameModel( + self.old_name, + operation.new_name, + ), + ] + # Skip `ModelOperation.reduce` as we want to run `references_model` + # against self.new_name. + return super(ModelOperation, self).reduce( + operation, app_label + ) or not operation.references_model(self.new_name, app_label) + + +class ModelOptionOperation(ModelOperation): + def reduce(self, operation, app_label): + if ( + isinstance(operation, (self.__class__, DeleteModel)) + and self.name_lower == operation.name_lower + ): + return [operation] + return super().reduce(operation, app_label) + + +class AlterModelTable(ModelOptionOperation): + """Rename a model's table.""" + + def __init__(self, name, table): + self.table = table + super().__init__(name) + + def deconstruct(self): + kwargs = { + "name": self.name, + "table": self.table, + } + return (self.__class__.__qualname__, [], kwargs) + + def state_forwards(self, app_label, state): + state.alter_model_options(app_label, self.name_lower, {"db_table": self.table}) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + new_model = to_state.apps.get_model(app_label, self.name) + if self.allow_migrate_model(schema_editor.connection.alias, new_model): + old_model = from_state.apps.get_model(app_label, self.name) + schema_editor.alter_db_table( + new_model, + old_model._meta.db_table, + new_model._meta.db_table, + ) + # Rename M2M fields whose name is based on this model's db_table + for old_field, new_field in zip( + old_model._meta.local_many_to_many, new_model._meta.local_many_to_many + ): + if new_field.remote_field.through._meta.auto_created: + schema_editor.alter_db_table( + new_field.remote_field.through, + old_field.remote_field.through._meta.db_table, + new_field.remote_field.through._meta.db_table, + ) + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + return self.database_forwards(app_label, schema_editor, from_state, to_state) + + def describe(self): + return "Rename table for %s to %s" % ( + self.name, + self.table if self.table is not None else "(default)", + ) + + @property + def migration_name_fragment(self): + return "alter_%s_table" % self.name_lower + + +class AlterModelTableComment(ModelOptionOperation): + def __init__(self, name, table_comment): + self.table_comment = table_comment + super().__init__(name) + + def deconstruct(self): + kwargs = { + "name": self.name, + "table_comment": self.table_comment, + } + return (self.__class__.__qualname__, [], kwargs) + + def state_forwards(self, app_label, state): + state.alter_model_options( + app_label, self.name_lower, {"db_table_comment": self.table_comment} + ) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + new_model = to_state.apps.get_model(app_label, self.name) + if self.allow_migrate_model(schema_editor.connection.alias, new_model): + old_model = from_state.apps.get_model(app_label, self.name) + schema_editor.alter_db_table_comment( + new_model, + old_model._meta.db_table_comment, + new_model._meta.db_table_comment, + ) + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + return self.database_forwards(app_label, schema_editor, from_state, to_state) + + def describe(self): + return f"Alter {self.name} table comment" + + @property + def migration_name_fragment(self): + return f"alter_{self.name_lower}_table_comment" + + +class AlterTogetherOptionOperation(ModelOptionOperation): + option_name = None + + def __init__(self, name, option_value): + if option_value: + option_value = set(normalize_together(option_value)) + setattr(self, self.option_name, option_value) + super().__init__(name) + + @cached_property + def option_value(self): + return getattr(self, self.option_name) + + def deconstruct(self): + kwargs = { + "name": self.name, + self.option_name: self.option_value, + } + return (self.__class__.__qualname__, [], kwargs) + + def state_forwards(self, app_label, state): + state.alter_model_options( + app_label, + self.name_lower, + {self.option_name: self.option_value}, + ) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + new_model = to_state.apps.get_model(app_label, self.name) + if self.allow_migrate_model(schema_editor.connection.alias, new_model): + old_model = from_state.apps.get_model(app_label, self.name) + alter_together = getattr(schema_editor, "alter_%s" % self.option_name) + alter_together( + new_model, + getattr(old_model._meta, self.option_name, set()), + getattr(new_model._meta, self.option_name, set()), + ) + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + return self.database_forwards(app_label, schema_editor, from_state, to_state) + + def references_field(self, model_name, name, app_label): + return self.references_model(model_name, app_label) and ( + not self.option_value + or any((name in fields) for fields in self.option_value) + ) + + def describe(self): + return "Alter %s for %s (%s constraint(s))" % ( + self.option_name, + self.name, + len(self.option_value or ""), + ) + + @property + def migration_name_fragment(self): + return "alter_%s_%s" % (self.name_lower, self.option_name) + + def can_reduce_through(self, operation, app_label): + return super().can_reduce_through(operation, app_label) or ( + isinstance(operation, AlterTogetherOptionOperation) + and type(operation) is not type(self) + ) + + +class AlterUniqueTogether(AlterTogetherOptionOperation): + """ + Change the value of unique_together to the target one. + Input value of unique_together must be a set of tuples. + """ + + option_name = "unique_together" + + def __init__(self, name, unique_together): + super().__init__(name, unique_together) + + +class AlterIndexTogether(AlterTogetherOptionOperation): + """ + Change the value of index_together to the target one. + Input value of index_together must be a set of tuples. + """ + + option_name = "index_together" + + def __init__(self, name, index_together): + super().__init__(name, index_together) + + +class AlterOrderWithRespectTo(ModelOptionOperation): + """Represent a change with the order_with_respect_to option.""" + + option_name = "order_with_respect_to" + + def __init__(self, name, order_with_respect_to): + self.order_with_respect_to = order_with_respect_to + super().__init__(name) + + def deconstruct(self): + kwargs = { + "name": self.name, + "order_with_respect_to": self.order_with_respect_to, + } + return (self.__class__.__qualname__, [], kwargs) + + def state_forwards(self, app_label, state): + state.alter_model_options( + app_label, + self.name_lower, + {self.option_name: self.order_with_respect_to}, + ) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + to_model = to_state.apps.get_model(app_label, self.name) + if self.allow_migrate_model(schema_editor.connection.alias, to_model): + from_model = from_state.apps.get_model(app_label, self.name) + # Remove a field if we need to + if ( + from_model._meta.order_with_respect_to + and not to_model._meta.order_with_respect_to + ): + schema_editor.remove_field( + from_model, from_model._meta.get_field("_order") + ) + # Add a field if we need to (altering the column is untouched as + # it's likely a rename) + elif ( + to_model._meta.order_with_respect_to + and not from_model._meta.order_with_respect_to + ): + field = to_model._meta.get_field("_order") + if not field.has_default(): + field.default = 0 + schema_editor.add_field( + from_model, + field, + ) + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + self.database_forwards(app_label, schema_editor, from_state, to_state) + + def references_field(self, model_name, name, app_label): + return self.references_model(model_name, app_label) and ( + self.order_with_respect_to is None or name == self.order_with_respect_to + ) + + def describe(self): + return "Set order_with_respect_to on %s to %s" % ( + self.name, + self.order_with_respect_to, + ) + + @property + def migration_name_fragment(self): + return "alter_%s_order_with_respect_to" % self.name_lower + + +class AlterModelOptions(ModelOptionOperation): + """ + Set new model options that don't directly affect the database schema + (like verbose_name, permissions, ordering). Python code in migrations + may still need them. + """ + + # Model options we want to compare and preserve in an AlterModelOptions op + ALTER_OPTION_KEYS = [ + "base_manager_name", + "default_manager_name", + "default_related_name", + "get_latest_by", + "managed", + "ordering", + "permissions", + "default_permissions", + "select_on_save", + "verbose_name", + "verbose_name_plural", + ] + + def __init__(self, name, options): + self.options = options + super().__init__(name) + + def deconstruct(self): + kwargs = { + "name": self.name, + "options": self.options, + } + return (self.__class__.__qualname__, [], kwargs) + + def state_forwards(self, app_label, state): + state.alter_model_options( + app_label, + self.name_lower, + self.options, + self.ALTER_OPTION_KEYS, + ) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + pass + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + pass + + def describe(self): + return "Change Meta options on %s" % self.name + + @property + def migration_name_fragment(self): + return "alter_%s_options" % self.name_lower + + +class AlterModelManagers(ModelOptionOperation): + """Alter the model's managers.""" + + serialization_expand_args = ["managers"] + + def __init__(self, name, managers): + self.managers = managers + super().__init__(name) + + def deconstruct(self): + return (self.__class__.__qualname__, [self.name, self.managers], {}) + + def state_forwards(self, app_label, state): + state.alter_model_managers(app_label, self.name_lower, self.managers) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + pass + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + pass + + def describe(self): + return "Change managers on %s" % self.name + + @property + def migration_name_fragment(self): + return "alter_%s_managers" % self.name_lower + + +class IndexOperation(Operation): + option_name = "indexes" + + @cached_property + def model_name_lower(self): + return self.model_name.lower() + + +class AddIndex(IndexOperation): + """Add an index on a model.""" + + def __init__(self, model_name, index): + self.model_name = model_name + if not index.name: + raise ValueError( + "Indexes passed to AddIndex operations require a name " + "argument. %r doesn't have one." % index + ) + self.index = index + + def state_forwards(self, app_label, state): + state.add_index(app_label, self.model_name_lower, self.index) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + model = to_state.apps.get_model(app_label, self.model_name) + if self.allow_migrate_model(schema_editor.connection.alias, model): + schema_editor.add_index(model, self.index) + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + model = from_state.apps.get_model(app_label, self.model_name) + if self.allow_migrate_model(schema_editor.connection.alias, model): + schema_editor.remove_index(model, self.index) + + def deconstruct(self): + kwargs = { + "model_name": self.model_name, + "index": self.index, + } + return ( + self.__class__.__qualname__, + [], + kwargs, + ) + + def describe(self): + if self.index.expressions: + return "Create index %s on %s on model %s" % ( + self.index.name, + ", ".join([str(expression) for expression in self.index.expressions]), + self.model_name, + ) + return "Create index %s on field(s) %s of model %s" % ( + self.index.name, + ", ".join(self.index.fields), + self.model_name, + ) + + @property + def migration_name_fragment(self): + return "%s_%s" % (self.model_name_lower, self.index.name.lower()) + + def reduce(self, operation, app_label): + if isinstance(operation, RemoveIndex) and self.index.name == operation.name: + return [] + if isinstance(operation, RenameIndex) and self.index.name == operation.old_name: + self.index.name = operation.new_name + return [AddIndex(model_name=self.model_name, index=self.index)] + return super().reduce(operation, app_label) + + +class RemoveIndex(IndexOperation): + """Remove an index from a model.""" + + def __init__(self, model_name, name): + self.model_name = model_name + self.name = name + + def state_forwards(self, app_label, state): + state.remove_index(app_label, self.model_name_lower, self.name) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + model = from_state.apps.get_model(app_label, self.model_name) + if self.allow_migrate_model(schema_editor.connection.alias, model): + from_model_state = from_state.models[app_label, self.model_name_lower] + index = from_model_state.get_index_by_name(self.name) + schema_editor.remove_index(model, index) + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + model = to_state.apps.get_model(app_label, self.model_name) + if self.allow_migrate_model(schema_editor.connection.alias, model): + to_model_state = to_state.models[app_label, self.model_name_lower] + index = to_model_state.get_index_by_name(self.name) + schema_editor.add_index(model, index) + + def deconstruct(self): + kwargs = { + "model_name": self.model_name, + "name": self.name, + } + return ( + self.__class__.__qualname__, + [], + kwargs, + ) + + def describe(self): + return "Remove index %s from %s" % (self.name, self.model_name) + + @property + def migration_name_fragment(self): + return "remove_%s_%s" % (self.model_name_lower, self.name.lower()) + + +class RenameIndex(IndexOperation): + """Rename an index.""" + + def __init__(self, model_name, new_name, old_name=None, old_fields=None): + if not old_name and not old_fields: + raise ValueError( + "RenameIndex requires one of old_name and old_fields arguments to be " + "set." + ) + if old_name and old_fields: + raise ValueError( + "RenameIndex.old_name and old_fields are mutually exclusive." + ) + self.model_name = model_name + self.new_name = new_name + self.old_name = old_name + self.old_fields = old_fields + + @cached_property + def old_name_lower(self): + return self.old_name.lower() + + @cached_property + def new_name_lower(self): + return self.new_name.lower() + + def deconstruct(self): + kwargs = { + "model_name": self.model_name, + "new_name": self.new_name, + } + if self.old_name: + kwargs["old_name"] = self.old_name + if self.old_fields: + kwargs["old_fields"] = self.old_fields + return (self.__class__.__qualname__, [], kwargs) + + def state_forwards(self, app_label, state): + if self.old_fields: + state.add_index( + app_label, + self.model_name_lower, + models.Index(fields=self.old_fields, name=self.new_name), + ) + state.remove_model_options( + app_label, + self.model_name_lower, + AlterIndexTogether.option_name, + self.old_fields, + ) + else: + state.rename_index( + app_label, self.model_name_lower, self.old_name, self.new_name + ) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + model = to_state.apps.get_model(app_label, self.model_name) + if not self.allow_migrate_model(schema_editor.connection.alias, model): + return + + if self.old_fields: + from_model = from_state.apps.get_model(app_label, self.model_name) + columns = [ + from_model._meta.get_field(field).column for field in self.old_fields + ] + matching_index_name = schema_editor._constraint_names( + from_model, column_names=columns, index=True + ) + if len(matching_index_name) != 1: + raise ValueError( + "Found wrong number (%s) of indexes for %s(%s)." + % ( + len(matching_index_name), + from_model._meta.db_table, + ", ".join(columns), + ) + ) + old_index = models.Index( + fields=self.old_fields, + name=matching_index_name[0], + ) + else: + from_model_state = from_state.models[app_label, self.model_name_lower] + old_index = from_model_state.get_index_by_name(self.old_name) + # Don't alter when the index name is not changed. + if old_index.name == self.new_name: + return + + to_model_state = to_state.models[app_label, self.model_name_lower] + new_index = to_model_state.get_index_by_name(self.new_name) + schema_editor.rename_index(model, old_index, new_index) + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + if self.old_fields: + # Backward operation with unnamed index is a no-op. + return + + self.new_name_lower, self.old_name_lower = ( + self.old_name_lower, + self.new_name_lower, + ) + self.new_name, self.old_name = self.old_name, self.new_name + + self.database_forwards(app_label, schema_editor, from_state, to_state) + + self.new_name_lower, self.old_name_lower = ( + self.old_name_lower, + self.new_name_lower, + ) + self.new_name, self.old_name = self.old_name, self.new_name + + def describe(self): + if self.old_name: + return ( + f"Rename index {self.old_name} on {self.model_name} to {self.new_name}" + ) + return ( + f"Rename unnamed index for {self.old_fields} on {self.model_name} to " + f"{self.new_name}" + ) + + @property + def migration_name_fragment(self): + if self.old_name: + return "rename_%s_%s" % (self.old_name_lower, self.new_name_lower) + return "rename_%s_%s_%s" % ( + self.model_name_lower, + "_".join(self.old_fields), + self.new_name_lower, + ) + + def reduce(self, operation, app_label): + if ( + isinstance(operation, RenameIndex) + and self.model_name_lower == operation.model_name_lower + and operation.old_name + and self.new_name_lower == operation.old_name_lower + ): + return [ + RenameIndex( + self.model_name, + new_name=operation.new_name, + old_name=self.old_name, + old_fields=self.old_fields, + ) + ] + return super().reduce(operation, app_label) + + +class AddConstraint(IndexOperation): + option_name = "constraints" + + def __init__(self, model_name, constraint): + self.model_name = model_name + self.constraint = constraint + + def state_forwards(self, app_label, state): + state.add_constraint(app_label, self.model_name_lower, self.constraint) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + model = to_state.apps.get_model(app_label, self.model_name) + if self.allow_migrate_model(schema_editor.connection.alias, model): + schema_editor.add_constraint(model, self.constraint) + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + model = to_state.apps.get_model(app_label, self.model_name) + if self.allow_migrate_model(schema_editor.connection.alias, model): + schema_editor.remove_constraint(model, self.constraint) + + def deconstruct(self): + return ( + self.__class__.__name__, + [], + { + "model_name": self.model_name, + "constraint": self.constraint, + }, + ) + + def describe(self): + return "Create constraint %s on model %s" % ( + self.constraint.name, + self.model_name, + ) + + @property + def migration_name_fragment(self): + return "%s_%s" % (self.model_name_lower, self.constraint.name.lower()) + + def reduce(self, operation, app_label): + if ( + isinstance(operation, RemoveConstraint) + and self.model_name_lower == operation.model_name_lower + and self.constraint.name == operation.name + ): + return [] + return super().reduce(operation, app_label) + + +class RemoveConstraint(IndexOperation): + option_name = "constraints" + + def __init__(self, model_name, name): + self.model_name = model_name + self.name = name + + def state_forwards(self, app_label, state): + state.remove_constraint(app_label, self.model_name_lower, self.name) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + model = to_state.apps.get_model(app_label, self.model_name) + if self.allow_migrate_model(schema_editor.connection.alias, model): + from_model_state = from_state.models[app_label, self.model_name_lower] + constraint = from_model_state.get_constraint_by_name(self.name) + schema_editor.remove_constraint(model, constraint) + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + model = to_state.apps.get_model(app_label, self.model_name) + if self.allow_migrate_model(schema_editor.connection.alias, model): + to_model_state = to_state.models[app_label, self.model_name_lower] + constraint = to_model_state.get_constraint_by_name(self.name) + schema_editor.add_constraint(model, constraint) + + def deconstruct(self): + return ( + self.__class__.__name__, + [], + { + "model_name": self.model_name, + "name": self.name, + }, + ) + + def describe(self): + return "Remove constraint %s from model %s" % (self.name, self.model_name) + + @property + def migration_name_fragment(self): + return "remove_%s_%s" % (self.model_name_lower, self.name.lower()) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/operations/special.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/operations/special.py new file mode 100644 index 0000000..94a6ec7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/operations/special.py @@ -0,0 +1,208 @@ +from django.db import router + +from .base import Operation + + +class SeparateDatabaseAndState(Operation): + """ + Take two lists of operations - ones that will be used for the database, + and ones that will be used for the state change. This allows operations + that don't support state change to have it applied, or have operations + that affect the state or not the database, or so on. + """ + + serialization_expand_args = ["database_operations", "state_operations"] + + def __init__(self, database_operations=None, state_operations=None): + self.database_operations = database_operations or [] + self.state_operations = state_operations or [] + + def deconstruct(self): + kwargs = {} + if self.database_operations: + kwargs["database_operations"] = self.database_operations + if self.state_operations: + kwargs["state_operations"] = self.state_operations + return (self.__class__.__qualname__, [], kwargs) + + def state_forwards(self, app_label, state): + for state_operation in self.state_operations: + state_operation.state_forwards(app_label, state) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + # We calculate state separately in here since our state functions aren't useful + for database_operation in self.database_operations: + to_state = from_state.clone() + database_operation.state_forwards(app_label, to_state) + database_operation.database_forwards( + app_label, schema_editor, from_state, to_state + ) + from_state = to_state + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + # We calculate state separately in here since our state functions aren't useful + to_states = {} + for dbop in self.database_operations: + to_states[dbop] = to_state + to_state = to_state.clone() + dbop.state_forwards(app_label, to_state) + # to_state now has the states of all the database_operations applied + # which is the from_state for the backwards migration of the last + # operation. + for database_operation in reversed(self.database_operations): + from_state = to_state + to_state = to_states[database_operation] + database_operation.database_backwards( + app_label, schema_editor, from_state, to_state + ) + + def describe(self): + return "Custom state/database change combination" + + +class RunSQL(Operation): + """ + Run some raw SQL. A reverse SQL statement may be provided. + + Also accept a list of operations that represent the state change effected + by this SQL change, in case it's custom column/table creation/deletion. + """ + + noop = "" + + def __init__( + self, sql, reverse_sql=None, state_operations=None, hints=None, elidable=False + ): + self.sql = sql + self.reverse_sql = reverse_sql + self.state_operations = state_operations or [] + self.hints = hints or {} + self.elidable = elidable + + def deconstruct(self): + kwargs = { + "sql": self.sql, + } + if self.reverse_sql is not None: + kwargs["reverse_sql"] = self.reverse_sql + if self.state_operations: + kwargs["state_operations"] = self.state_operations + if self.hints: + kwargs["hints"] = self.hints + return (self.__class__.__qualname__, [], kwargs) + + @property + def reversible(self): + return self.reverse_sql is not None + + def state_forwards(self, app_label, state): + for state_operation in self.state_operations: + state_operation.state_forwards(app_label, state) + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + if router.allow_migrate( + schema_editor.connection.alias, app_label, **self.hints + ): + self._run_sql(schema_editor, self.sql) + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + if self.reverse_sql is None: + raise NotImplementedError("You cannot reverse this operation") + if router.allow_migrate( + schema_editor.connection.alias, app_label, **self.hints + ): + self._run_sql(schema_editor, self.reverse_sql) + + def describe(self): + return "Raw SQL operation" + + def _run_sql(self, schema_editor, sqls): + if isinstance(sqls, (list, tuple)): + for sql in sqls: + params = None + if isinstance(sql, (list, tuple)): + elements = len(sql) + if elements == 2: + sql, params = sql + else: + raise ValueError("Expected a 2-tuple but got %d" % elements) + schema_editor.execute(sql, params=params) + elif sqls != RunSQL.noop: + statements = schema_editor.connection.ops.prepare_sql_script(sqls) + for statement in statements: + schema_editor.execute(statement, params=None) + + +class RunPython(Operation): + """ + Run Python code in a context suitable for doing versioned ORM operations. + """ + + reduces_to_sql = False + + def __init__( + self, code, reverse_code=None, atomic=None, hints=None, elidable=False + ): + self.atomic = atomic + # Forwards code + if not callable(code): + raise ValueError("RunPython must be supplied with a callable") + self.code = code + # Reverse code + if reverse_code is None: + self.reverse_code = None + else: + if not callable(reverse_code): + raise ValueError("RunPython must be supplied with callable arguments") + self.reverse_code = reverse_code + self.hints = hints or {} + self.elidable = elidable + + def deconstruct(self): + kwargs = { + "code": self.code, + } + if self.reverse_code is not None: + kwargs["reverse_code"] = self.reverse_code + if self.atomic is not None: + kwargs["atomic"] = self.atomic + if self.hints: + kwargs["hints"] = self.hints + return (self.__class__.__qualname__, [], kwargs) + + @property + def reversible(self): + return self.reverse_code is not None + + def state_forwards(self, app_label, state): + # RunPython objects have no state effect. To add some, combine this + # with SeparateDatabaseAndState. + pass + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + # RunPython has access to all models. Ensure that all models are + # reloaded in case any are delayed. + from_state.clear_delayed_apps_cache() + if router.allow_migrate( + schema_editor.connection.alias, app_label, **self.hints + ): + # We now execute the Python code in a context that contains a 'models' + # object, representing the versioned models as an app registry. + # We could try to override the global cache, but then people will still + # use direct imports, so we go with a documentation approach instead. + self.code(from_state.apps, schema_editor) + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + if self.reverse_code is None: + raise NotImplementedError("You cannot reverse this operation") + if router.allow_migrate( + schema_editor.connection.alias, app_label, **self.hints + ): + self.reverse_code(from_state.apps, schema_editor) + + def describe(self): + return "Raw Python operation" + + @staticmethod + def noop(apps, schema_editor): + return None diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/optimizer.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/optimizer.py new file mode 100644 index 0000000..7e5dea2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/optimizer.py @@ -0,0 +1,69 @@ +class MigrationOptimizer: + """ + Power the optimization process, where you provide a list of Operations + and you are returned a list of equal or shorter length - operations + are merged into one if possible. + + For example, a CreateModel and an AddField can be optimized into a + new CreateModel, and CreateModel and DeleteModel can be optimized into + nothing. + """ + + def optimize(self, operations, app_label): + """ + Main optimization entry point. Pass in a list of Operation instances, + get out a new list of Operation instances. + + Unfortunately, due to the scope of the optimization (two combinable + operations might be separated by several hundred others), this can't be + done as a peephole optimization with checks/output implemented on + the Operations themselves; instead, the optimizer looks at each + individual operation and scans forwards in the list to see if there + are any matches, stopping at boundaries - operations which can't + be optimized over (RunSQL, operations on the same field/model, etc.) + + The inner loop is run until the starting list is the same as the result + list, and then the result is returned. This means that operation + optimization must be stable and always return an equal or shorter list. + """ + # Internal tracking variable for test assertions about # of loops + if app_label is None: + raise TypeError("app_label must be a str.") + self._iterations = 0 + while True: + result = self.optimize_inner(operations, app_label) + self._iterations += 1 + if result == operations: + return result + operations = result + + def optimize_inner(self, operations, app_label): + """Inner optimization loop.""" + new_operations = [] + for i, operation in enumerate(operations): + right = True # Should we reduce on the right or on the left. + # Compare it to each operation after it + for j, other in enumerate(operations[i + 1 :]): + result = operation.reduce(other, app_label) + if isinstance(result, list): + in_between = operations[i + 1 : i + j + 1] + if right: + new_operations.extend(in_between) + new_operations.extend(result) + elif all(op.reduce(other, app_label) is True for op in in_between): + # Perform a left reduction if all of the in-between + # operations can optimize through other. + new_operations.extend(result) + new_operations.extend(in_between) + else: + # Otherwise keep trying. + new_operations.append(operation) + break + new_operations.extend(operations[i + j + 2 :]) + return new_operations + elif not result: + # Can't perform a right reduction. + right = False + else: + new_operations.append(operation) + return new_operations diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/questioner.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/questioner.py new file mode 100644 index 0000000..e1081ab --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/questioner.py @@ -0,0 +1,341 @@ +import datetime +import importlib +import os +import sys + +from django.apps import apps +from django.core.management.base import OutputWrapper +from django.db.models import NOT_PROVIDED +from django.utils import timezone +from django.utils.version import get_docs_version + +from .loader import MigrationLoader + + +class MigrationQuestioner: + """ + Give the autodetector responses to questions it might have. + This base class has a built-in noninteractive mode, but the + interactive subclass is what the command-line arguments will use. + """ + + def __init__(self, defaults=None, specified_apps=None, dry_run=None): + self.defaults = defaults or {} + self.specified_apps = specified_apps or set() + self.dry_run = dry_run + + def ask_initial(self, app_label): + """Should we create an initial migration for the app?""" + # If it was specified on the command line, definitely true + if app_label in self.specified_apps: + return True + # Otherwise, we look to see if it has a migrations module + # without any Python files in it, apart from __init__.py. + # Apps from the new app template will have these; the Python + # file check will ensure we skip South ones. + try: + app_config = apps.get_app_config(app_label) + except LookupError: # It's a fake app. + return self.defaults.get("ask_initial", False) + migrations_import_path, _ = MigrationLoader.migrations_module(app_config.label) + if migrations_import_path is None: + # It's an application with migrations disabled. + return self.defaults.get("ask_initial", False) + try: + migrations_module = importlib.import_module(migrations_import_path) + except ImportError: + return self.defaults.get("ask_initial", False) + else: + if getattr(migrations_module, "__file__", None): + filenames = os.listdir(os.path.dirname(migrations_module.__file__)) + elif hasattr(migrations_module, "__path__"): + if len(migrations_module.__path__) > 1: + return False + filenames = os.listdir(list(migrations_module.__path__)[0]) + return not any(x.endswith(".py") for x in filenames if x != "__init__.py") + + def ask_not_null_addition(self, field_name, model_name): + """Adding a NOT NULL field to a model.""" + # None means quit + return None + + def ask_not_null_alteration(self, field_name, model_name): + """Changing a NULL field to NOT NULL.""" + # None means quit + return None + + def ask_rename(self, model_name, old_name, new_name, field_instance): + """Was this field really renamed?""" + return self.defaults.get("ask_rename", False) + + def ask_rename_model(self, old_model_state, new_model_state): + """Was this model really renamed?""" + return self.defaults.get("ask_rename_model", False) + + def ask_merge(self, app_label): + """Should these migrations really be merged?""" + return self.defaults.get("ask_merge", False) + + def ask_auto_now_add_addition(self, field_name, model_name): + """Adding an auto_now_add field to a model.""" + # None means quit + return None + + def ask_unique_callable_default_addition(self, field_name, model_name): + """Adding a unique field with a callable default.""" + # None means continue. + return None + + +class InteractiveMigrationQuestioner(MigrationQuestioner): + def __init__( + self, defaults=None, specified_apps=None, dry_run=None, prompt_output=None + ): + super().__init__( + defaults=defaults, specified_apps=specified_apps, dry_run=dry_run + ) + self.prompt_output = prompt_output or OutputWrapper(sys.stdout) + + def _boolean_input(self, question, default=None): + self.prompt_output.write(f"{question} ", ending="") + result = input() + if not result and default is not None: + return default + while not result or result[0].lower() not in "yn": + self.prompt_output.write("Please answer yes or no: ", ending="") + result = input() + return result[0].lower() == "y" + + def _choice_input(self, question, choices): + self.prompt_output.write(f"{question}") + for i, choice in enumerate(choices): + self.prompt_output.write(" %s) %s" % (i + 1, choice)) + self.prompt_output.write("Select an option: ", ending="") + result = input() + while True: + try: + value = int(result) + except ValueError: + pass + else: + if 0 < value <= len(choices): + return value + self.prompt_output.write("Please select a valid option: ", ending="") + result = input() + + def _ask_default(self, default=""): + """ + Prompt for a default value. + + The ``default`` argument allows providing a custom default value (as a + string) which will be shown to the user and used as the return value + if the user doesn't provide any other input. + """ + self.prompt_output.write("Please enter the default value as valid Python.") + if default: + self.prompt_output.write( + f"Accept the default '{default}' by pressing 'Enter' or " + f"provide another value." + ) + self.prompt_output.write( + "The datetime and django.utils.timezone modules are available, so " + "it is possible to provide e.g. timezone.now as a value." + ) + self.prompt_output.write("Type 'exit' to exit this prompt") + while True: + if default: + prompt = "[default: {}] >>> ".format(default) + else: + prompt = ">>> " + self.prompt_output.write(prompt, ending="") + code = input() + if not code and default: + code = default + if not code: + self.prompt_output.write( + "Please enter some code, or 'exit' (without quotes) to exit." + ) + elif code == "exit": + sys.exit(1) + else: + try: + return eval(code, {}, {"datetime": datetime, "timezone": timezone}) + except (SyntaxError, NameError) as e: + self.prompt_output.write("Invalid input: %s" % e) + + def ask_not_null_addition(self, field_name, model_name): + """Adding a NOT NULL field to a model.""" + if not self.dry_run: + choice = self._choice_input( + f"It is impossible to add a non-nullable field '{field_name}' " + f"to {model_name} without specifying a default. This is " + f"because the database needs something to populate existing " + f"rows.\n" + f"Please select a fix:", + [ + ( + "Provide a one-off default now (will be set on all existing " + "rows with a null value for this column)" + ), + "Quit and manually define a default value in models.py.", + ], + ) + if choice == 2: + sys.exit(3) + else: + return self._ask_default() + return None + + def ask_not_null_alteration(self, field_name, model_name): + """Changing a NULL field to NOT NULL.""" + if not self.dry_run: + choice = self._choice_input( + f"It is impossible to change a nullable field '{field_name}' " + f"on {model_name} to non-nullable without providing a " + f"default. This is because the database needs something to " + f"populate existing rows.\n" + f"Please select a fix:", + [ + ( + "Provide a one-off default now (will be set on all existing " + "rows with a null value for this column)" + ), + "Ignore for now. Existing rows that contain NULL values " + "will have to be handled manually, for example with a " + "RunPython or RunSQL operation.", + "Quit and manually define a default value in models.py.", + ], + ) + if choice == 2: + return NOT_PROVIDED + elif choice == 3: + sys.exit(3) + else: + return self._ask_default() + return None + + def ask_rename(self, model_name, old_name, new_name, field_instance): + """Was this field really renamed?""" + msg = "Was %s.%s renamed to %s.%s (a %s)? [y/N]" + return self._boolean_input( + msg + % ( + model_name, + old_name, + model_name, + new_name, + field_instance.__class__.__name__, + ), + False, + ) + + def ask_rename_model(self, old_model_state, new_model_state): + """Was this model really renamed?""" + msg = "Was the model %s.%s renamed to %s? [y/N]" + return self._boolean_input( + msg + % (old_model_state.app_label, old_model_state.name, new_model_state.name), + False, + ) + + def ask_merge(self, app_label): + return self._boolean_input( + "\nMerging will only work if the operations printed above do not conflict\n" + + "with each other (working on different fields or models)\n" + + "Should these migration branches be merged? [y/N]", + False, + ) + + def ask_auto_now_add_addition(self, field_name, model_name): + """Adding an auto_now_add field to a model.""" + if not self.dry_run: + choice = self._choice_input( + f"It is impossible to add the field '{field_name}' with " + f"'auto_now_add=True' to {model_name} without providing a " + f"default. This is because the database needs something to " + f"populate existing rows.\n", + [ + "Provide a one-off default now which will be set on all " + "existing rows", + "Quit and manually define a default value in models.py.", + ], + ) + if choice == 2: + sys.exit(3) + else: + return self._ask_default(default="timezone.now") + return None + + def ask_unique_callable_default_addition(self, field_name, model_name): + """Adding a unique field with a callable default.""" + if not self.dry_run: + version = get_docs_version() + choice = self._choice_input( + f"Callable default on unique field {model_name}.{field_name} " + f"will not generate unique values upon migrating.\n" + f"Please choose how to proceed:\n", + [ + f"Continue making this migration as the first step in " + f"writing a manual migration to generate unique values " + f"described here: " + f"https://docs.djangoproject.com/en/{version}/howto/" + f"writing-migrations/#migrations-that-add-unique-fields.", + "Quit and edit field options in models.py.", + ], + ) + if choice == 2: + sys.exit(3) + return None + + +class NonInteractiveMigrationQuestioner(MigrationQuestioner): + def __init__( + self, + defaults=None, + specified_apps=None, + dry_run=None, + verbosity=1, + log=None, + ): + self.verbosity = verbosity + self.log = log + super().__init__( + defaults=defaults, + specified_apps=specified_apps, + dry_run=dry_run, + ) + + def log_lack_of_migration(self, field_name, model_name, reason): + if self.verbosity > 0: + self.log( + f"Field '{field_name}' on model '{model_name}' not migrated: " + f"{reason}." + ) + + def ask_not_null_addition(self, field_name, model_name): + # We can't ask the user, so act like the user aborted. + self.log_lack_of_migration( + field_name, + model_name, + "it is impossible to add a non-nullable field without specifying " + "a default", + ) + sys.exit(3) + + def ask_not_null_alteration(self, field_name, model_name): + # We can't ask the user, so set as not provided. + self.log( + f"Field '{field_name}' on model '{model_name}' given a default of " + f"NOT PROVIDED and must be corrected." + ) + return NOT_PROVIDED + + def ask_auto_now_add_addition(self, field_name, model_name): + # We can't ask the user, so act like the user aborted. + self.log_lack_of_migration( + field_name, + model_name, + "it is impossible to add a field with 'auto_now_add=True' without " + "specifying a default", + ) + sys.exit(3) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/recorder.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/recorder.py new file mode 100644 index 0000000..cf0bd4a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/recorder.py @@ -0,0 +1,111 @@ +from django.apps.registry import Apps +from django.db import DatabaseError, models +from django.utils.functional import classproperty +from django.utils.timezone import now + +from .exceptions import MigrationSchemaMissing + + +class MigrationRecorder: + """ + Deal with storing migration records in the database. + + Because this table is actually itself used for dealing with model + creation, it's the one thing we can't do normally via migrations. + We manually handle table creation/schema updating (using schema backend) + and then have a floating model to do queries with. + + If a migration is unapplied its row is removed from the table. Having + a row in the table always means a migration is applied. + """ + + _migration_class = None + + @classproperty + def Migration(cls): + """ + Lazy load to avoid AppRegistryNotReady if installed apps import + MigrationRecorder. + """ + if cls._migration_class is None: + + class Migration(models.Model): + app = models.CharField(max_length=255) + name = models.CharField(max_length=255) + applied = models.DateTimeField(default=now) + + class Meta: + apps = Apps() + app_label = "migrations" + db_table = "django_migrations" + + def __str__(self): + return "Migration %s for %s" % (self.name, self.app) + + cls._migration_class = Migration + return cls._migration_class + + def __init__(self, connection): + self.connection = connection + self._has_table = False + + @property + def migration_qs(self): + return self.Migration.objects.using(self.connection.alias) + + def has_table(self): + """Return True if the django_migrations table exists.""" + # If the migrations table has already been confirmed to exist, don't + # recheck it's existence. + if self._has_table: + return True + # It hasn't been confirmed to exist, recheck. + with self.connection.cursor() as cursor: + tables = self.connection.introspection.table_names(cursor) + + self._has_table = self.Migration._meta.db_table in tables + return self._has_table + + def ensure_schema(self): + """Ensure the table exists and has the correct schema.""" + # If the table's there, that's fine - we've never changed its schema + # in the codebase. + if self.has_table(): + return + # Make the table + try: + with self.connection.schema_editor() as editor: + editor.create_model(self.Migration) + except DatabaseError as exc: + raise MigrationSchemaMissing( + "Unable to create the django_migrations table (%s)" % exc + ) + + def applied_migrations(self): + """ + Return a dict mapping (app_name, migration_name) to Migration instances + for all applied migrations. + """ + if self.has_table(): + return { + (migration.app, migration.name): migration + for migration in self.migration_qs + } + else: + # If the django_migrations table doesn't exist, then no migrations + # are applied. + return {} + + def record_applied(self, app, name): + """Record that a migration was applied.""" + self.ensure_schema() + self.migration_qs.create(app=app, name=name) + + def record_unapplied(self, app, name): + """Record that a migration was unapplied.""" + self.ensure_schema() + self.migration_qs.filter(app=app, name=name).delete() + + def flush(self): + """Delete all migration records. Useful for testing migrations.""" + self.migration_qs.all().delete() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/serializer.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/serializer.py new file mode 100644 index 0000000..69e10fd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/serializer.py @@ -0,0 +1,401 @@ +import builtins +import collections.abc +import datetime +import decimal +import enum +import functools +import math +import os +import pathlib +import re +import types +import uuid + +from django.conf import SettingsReference +from django.db import models +from django.db.migrations.operations.base import Operation +from django.db.migrations.utils import COMPILED_REGEX_TYPE, RegexObject +from django.utils.functional import LazyObject, Promise +from django.utils.version import PY311, get_docs_version + + +class BaseSerializer: + def __init__(self, value): + self.value = value + + def serialize(self): + raise NotImplementedError( + "Subclasses of BaseSerializer must implement the serialize() method." + ) + + +class BaseSequenceSerializer(BaseSerializer): + def _format(self): + raise NotImplementedError( + "Subclasses of BaseSequenceSerializer must implement the _format() method." + ) + + def serialize(self): + imports = set() + strings = [] + for item in self.value: + item_string, item_imports = serializer_factory(item).serialize() + imports.update(item_imports) + strings.append(item_string) + value = self._format() + return value % (", ".join(strings)), imports + + +class BaseUnorderedSequenceSerializer(BaseSequenceSerializer): + def __init__(self, value): + super().__init__(sorted(value, key=repr)) + + +class BaseSimpleSerializer(BaseSerializer): + def serialize(self): + return repr(self.value), set() + + +class ChoicesSerializer(BaseSerializer): + def serialize(self): + return serializer_factory(self.value.value).serialize() + + +class DateTimeSerializer(BaseSerializer): + """For datetime.*, except datetime.datetime.""" + + def serialize(self): + return repr(self.value), {"import datetime"} + + +class DatetimeDatetimeSerializer(BaseSerializer): + """For datetime.datetime.""" + + def serialize(self): + if self.value.tzinfo is not None and self.value.tzinfo != datetime.timezone.utc: + self.value = self.value.astimezone(datetime.timezone.utc) + imports = ["import datetime"] + return repr(self.value), set(imports) + + +class DecimalSerializer(BaseSerializer): + def serialize(self): + return repr(self.value), {"from decimal import Decimal"} + + +class DeconstructableSerializer(BaseSerializer): + @staticmethod + def serialize_deconstructed(path, args, kwargs): + name, imports = DeconstructableSerializer._serialize_path(path) + strings = [] + for arg in args: + arg_string, arg_imports = serializer_factory(arg).serialize() + strings.append(arg_string) + imports.update(arg_imports) + for kw, arg in sorted(kwargs.items()): + arg_string, arg_imports = serializer_factory(arg).serialize() + imports.update(arg_imports) + strings.append("%s=%s" % (kw, arg_string)) + return "%s(%s)" % (name, ", ".join(strings)), imports + + @staticmethod + def _serialize_path(path): + module, name = path.rsplit(".", 1) + if module == "django.db.models": + imports = {"from django.db import models"} + name = "models.%s" % name + else: + imports = {"import %s" % module} + name = path + return name, imports + + def serialize(self): + return self.serialize_deconstructed(*self.value.deconstruct()) + + +class DictionarySerializer(BaseSerializer): + def serialize(self): + imports = set() + strings = [] + for k, v in sorted(self.value.items()): + k_string, k_imports = serializer_factory(k).serialize() + v_string, v_imports = serializer_factory(v).serialize() + imports.update(k_imports) + imports.update(v_imports) + strings.append((k_string, v_string)) + return "{%s}" % (", ".join("%s: %s" % (k, v) for k, v in strings)), imports + + +class EnumSerializer(BaseSerializer): + def serialize(self): + enum_class = self.value.__class__ + module = enum_class.__module__ + if issubclass(enum_class, enum.Flag): + if PY311: + members = list(self.value) + else: + members, _ = enum._decompose(enum_class, self.value) + members = reversed(members) + else: + members = (self.value,) + return ( + " | ".join( + [ + f"{module}.{enum_class.__qualname__}[{item.name!r}]" + for item in members + ] + ), + {"import %s" % module}, + ) + + +class FloatSerializer(BaseSimpleSerializer): + def serialize(self): + if math.isnan(self.value) or math.isinf(self.value): + return 'float("{}")'.format(self.value), set() + return super().serialize() + + +class FrozensetSerializer(BaseUnorderedSequenceSerializer): + def _format(self): + return "frozenset([%s])" + + +class FunctionTypeSerializer(BaseSerializer): + def serialize(self): + if getattr(self.value, "__self__", None) and isinstance( + self.value.__self__, type + ): + klass = self.value.__self__ + module = klass.__module__ + return "%s.%s.%s" % (module, klass.__qualname__, self.value.__name__), { + "import %s" % module + } + # Further error checking + if self.value.__name__ == "": + raise ValueError("Cannot serialize function: lambda") + if self.value.__module__ is None: + raise ValueError("Cannot serialize function %r: No module" % self.value) + + module_name = self.value.__module__ + + if "<" not in self.value.__qualname__: # Qualname can include + return "%s.%s" % (module_name, self.value.__qualname__), { + "import %s" % self.value.__module__ + } + + raise ValueError( + "Could not find function %s in %s.\n" % (self.value.__name__, module_name) + ) + + +class FunctoolsPartialSerializer(BaseSerializer): + def serialize(self): + # Serialize functools.partial() arguments + func_string, func_imports = serializer_factory(self.value.func).serialize() + args_string, args_imports = serializer_factory(self.value.args).serialize() + keywords_string, keywords_imports = serializer_factory( + self.value.keywords + ).serialize() + # Add any imports needed by arguments + imports = {"import functools", *func_imports, *args_imports, *keywords_imports} + return ( + "functools.%s(%s, *%s, **%s)" + % ( + self.value.__class__.__name__, + func_string, + args_string, + keywords_string, + ), + imports, + ) + + +class IterableSerializer(BaseSerializer): + def serialize(self): + imports = set() + strings = [] + for item in self.value: + item_string, item_imports = serializer_factory(item).serialize() + imports.update(item_imports) + strings.append(item_string) + # When len(strings)==0, the empty iterable should be serialized as + # "()", not "(,)" because (,) is invalid Python syntax. + value = "(%s)" if len(strings) != 1 else "(%s,)" + return value % (", ".join(strings)), imports + + +class ModelFieldSerializer(DeconstructableSerializer): + def serialize(self): + attr_name, path, args, kwargs = self.value.deconstruct() + return self.serialize_deconstructed(path, args, kwargs) + + +class ModelManagerSerializer(DeconstructableSerializer): + def serialize(self): + as_manager, manager_path, qs_path, args, kwargs = self.value.deconstruct() + if as_manager: + name, imports = self._serialize_path(qs_path) + return "%s.as_manager()" % name, imports + else: + return self.serialize_deconstructed(manager_path, args, kwargs) + + +class OperationSerializer(BaseSerializer): + def serialize(self): + from django.db.migrations.writer import OperationWriter + + string, imports = OperationWriter(self.value, indentation=0).serialize() + # Nested operation, trailing comma is handled in upper OperationWriter._write() + return string.rstrip(","), imports + + +class PathLikeSerializer(BaseSerializer): + def serialize(self): + return repr(os.fspath(self.value)), {} + + +class PathSerializer(BaseSerializer): + def serialize(self): + # Convert concrete paths to pure paths to avoid issues with migrations + # generated on one platform being used on a different platform. + prefix = "Pure" if isinstance(self.value, pathlib.Path) else "" + return "pathlib.%s%r" % (prefix, self.value), {"import pathlib"} + + +class RegexSerializer(BaseSerializer): + def serialize(self): + regex_pattern, pattern_imports = serializer_factory( + self.value.pattern + ).serialize() + # Turn off default implicit flags (e.g. re.U) because regexes with the + # same implicit and explicit flags aren't equal. + flags = self.value.flags ^ re.compile("").flags + regex_flags, flag_imports = serializer_factory(flags).serialize() + imports = {"import re", *pattern_imports, *flag_imports} + args = [regex_pattern] + if flags: + args.append(regex_flags) + return "re.compile(%s)" % ", ".join(args), imports + + +class SequenceSerializer(BaseSequenceSerializer): + def _format(self): + return "[%s]" + + +class SetSerializer(BaseUnorderedSequenceSerializer): + def _format(self): + # Serialize as a set literal except when value is empty because {} + # is an empty dict. + return "{%s}" if self.value else "set(%s)" + + +class SettingsReferenceSerializer(BaseSerializer): + def serialize(self): + return "settings.%s" % self.value.setting_name, { + "from django.conf import settings" + } + + +class TupleSerializer(BaseSequenceSerializer): + def _format(self): + # When len(value)==0, the empty tuple should be serialized as "()", + # not "(,)" because (,) is invalid Python syntax. + return "(%s)" if len(self.value) != 1 else "(%s,)" + + +class TypeSerializer(BaseSerializer): + def serialize(self): + special_cases = [ + (models.Model, "models.Model", ["from django.db import models"]), + (types.NoneType, "types.NoneType", ["import types"]), + ] + for case, string, imports in special_cases: + if case is self.value: + return string, set(imports) + if hasattr(self.value, "__module__"): + module = self.value.__module__ + if module == builtins.__name__: + return self.value.__name__, set() + else: + return "%s.%s" % (module, self.value.__qualname__), { + "import %s" % module + } + + +class UUIDSerializer(BaseSerializer): + def serialize(self): + return "uuid.%s" % repr(self.value), {"import uuid"} + + +class Serializer: + _registry = { + # Some of these are order-dependent. + frozenset: FrozensetSerializer, + list: SequenceSerializer, + set: SetSerializer, + tuple: TupleSerializer, + dict: DictionarySerializer, + models.Choices: ChoicesSerializer, + enum.Enum: EnumSerializer, + datetime.datetime: DatetimeDatetimeSerializer, + (datetime.date, datetime.timedelta, datetime.time): DateTimeSerializer, + SettingsReference: SettingsReferenceSerializer, + float: FloatSerializer, + (bool, int, types.NoneType, bytes, str, range): BaseSimpleSerializer, + decimal.Decimal: DecimalSerializer, + (functools.partial, functools.partialmethod): FunctoolsPartialSerializer, + ( + types.FunctionType, + types.BuiltinFunctionType, + types.MethodType, + functools._lru_cache_wrapper, + ): FunctionTypeSerializer, + collections.abc.Iterable: IterableSerializer, + (COMPILED_REGEX_TYPE, RegexObject): RegexSerializer, + uuid.UUID: UUIDSerializer, + pathlib.PurePath: PathSerializer, + os.PathLike: PathLikeSerializer, + } + + @classmethod + def register(cls, type_, serializer): + if not issubclass(serializer, BaseSerializer): + raise ValueError( + "'%s' must inherit from 'BaseSerializer'." % serializer.__name__ + ) + cls._registry[type_] = serializer + + @classmethod + def unregister(cls, type_): + cls._registry.pop(type_) + + +def serializer_factory(value): + if isinstance(value, Promise): + value = str(value) + elif isinstance(value, LazyObject): + # The unwrapped value is returned as the first item of the arguments + # tuple. + value = value.__reduce__()[1][0] + + if isinstance(value, models.Field): + return ModelFieldSerializer(value) + if isinstance(value, models.manager.BaseManager): + return ModelManagerSerializer(value) + if isinstance(value, Operation): + return OperationSerializer(value) + if isinstance(value, type): + return TypeSerializer(value) + # Anything that knows how to deconstruct itself. + if hasattr(value, "deconstruct"): + return DeconstructableSerializer(value) + for type_, serializer_cls in Serializer._registry.items(): + if isinstance(value, type_): + return serializer_cls(value) + raise ValueError( + "Cannot serialize: %r\nThere are some values Django cannot serialize into " + "migration files.\nFor more, see https://docs.djangoproject.com/en/%s/" + "topics/migrations/#migration-serializing" % (value, get_docs_version()) + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/state.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/state.py new file mode 100644 index 0000000..ae55967 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/state.py @@ -0,0 +1,988 @@ +import copy +from collections import defaultdict +from contextlib import contextmanager +from functools import partial + +from django.apps import AppConfig +from django.apps.registry import Apps +from django.apps.registry import apps as global_apps +from django.conf import settings +from django.core.exceptions import FieldDoesNotExist +from django.db import models +from django.db.migrations.utils import field_is_referenced, get_references +from django.db.models import NOT_PROVIDED +from django.db.models.fields.related import RECURSIVE_RELATIONSHIP_CONSTANT +from django.db.models.options import DEFAULT_NAMES, normalize_together +from django.db.models.utils import make_model_tuple +from django.utils.functional import cached_property +from django.utils.module_loading import import_string +from django.utils.version import get_docs_version + +from .exceptions import InvalidBasesError +from .utils import resolve_relation + + +def _get_app_label_and_model_name(model, app_label=""): + if isinstance(model, str): + split = model.split(".", 1) + return tuple(split) if len(split) == 2 else (app_label, split[0]) + else: + return model._meta.app_label, model._meta.model_name + + +def _get_related_models(m): + """Return all models that have a direct relationship to the given model.""" + related_models = [ + subclass + for subclass in m.__subclasses__() + if issubclass(subclass, models.Model) + ] + related_fields_models = set() + for f in m._meta.get_fields(include_parents=True, include_hidden=True): + if ( + f.is_relation + and f.related_model is not None + and not isinstance(f.related_model, str) + ): + related_fields_models.add(f.model) + related_models.append(f.related_model) + # Reverse accessors of foreign keys to proxy models are attached to their + # concrete proxied model. + opts = m._meta + if opts.proxy and m in related_fields_models: + related_models.append(opts.concrete_model) + return related_models + + +def get_related_models_tuples(model): + """ + Return a list of typical (app_label, model_name) tuples for all related + models for the given model. + """ + return { + (rel_mod._meta.app_label, rel_mod._meta.model_name) + for rel_mod in _get_related_models(model) + } + + +def get_related_models_recursive(model): + """ + Return all models that have a direct or indirect relationship + to the given model. + + Relationships are either defined by explicit relational fields, like + ForeignKey, ManyToManyField or OneToOneField, or by inheriting from another + model (a superclass is related to its subclasses, but not vice versa). Note, + however, that a model inheriting from a concrete model is also related to + its superclass through the implicit *_ptr OneToOneField on the subclass. + """ + seen = set() + queue = _get_related_models(model) + for rel_mod in queue: + rel_app_label, rel_model_name = ( + rel_mod._meta.app_label, + rel_mod._meta.model_name, + ) + if (rel_app_label, rel_model_name) in seen: + continue + seen.add((rel_app_label, rel_model_name)) + queue.extend(_get_related_models(rel_mod)) + return seen - {(model._meta.app_label, model._meta.model_name)} + + +class ProjectState: + """ + Represent the entire project's overall state. This is the item that is + passed around - do it here rather than at the app level so that cross-app + FKs/etc. resolve properly. + """ + + def __init__(self, models=None, real_apps=None): + self.models = models or {} + # Apps to include from main registry, usually unmigrated ones + if real_apps is None: + real_apps = set() + else: + assert isinstance(real_apps, set) + self.real_apps = real_apps + self.is_delayed = False + # {remote_model_key: {model_key: {field_name: field}}} + self._relations = None + + @property + def relations(self): + if self._relations is None: + self.resolve_fields_and_relations() + return self._relations + + def add_model(self, model_state): + model_key = model_state.app_label, model_state.name_lower + self.models[model_key] = model_state + if self._relations is not None: + self.resolve_model_relations(model_key) + if "apps" in self.__dict__: # hasattr would cache the property + self.reload_model(*model_key) + + def remove_model(self, app_label, model_name): + model_key = app_label, model_name + del self.models[model_key] + if self._relations is not None: + self._relations.pop(model_key, None) + # Call list() since _relations can change size during iteration. + for related_model_key, model_relations in list(self._relations.items()): + model_relations.pop(model_key, None) + if not model_relations: + del self._relations[related_model_key] + if "apps" in self.__dict__: # hasattr would cache the property + self.apps.unregister_model(*model_key) + # Need to do this explicitly since unregister_model() doesn't clear + # the cache automatically (#24513) + self.apps.clear_cache() + + def rename_model(self, app_label, old_name, new_name): + # Add a new model. + old_name_lower = old_name.lower() + new_name_lower = new_name.lower() + renamed_model = self.models[app_label, old_name_lower].clone() + renamed_model.name = new_name + self.models[app_label, new_name_lower] = renamed_model + # Repoint all fields pointing to the old model to the new one. + old_model_tuple = (app_label, old_name_lower) + new_remote_model = f"{app_label}.{new_name}" + to_reload = set() + for model_state, name, field, reference in get_references( + self, old_model_tuple + ): + changed_field = None + if reference.to: + changed_field = field.clone() + changed_field.remote_field.model = new_remote_model + if reference.through: + if changed_field is None: + changed_field = field.clone() + changed_field.remote_field.through = new_remote_model + if changed_field: + model_state.fields[name] = changed_field + to_reload.add((model_state.app_label, model_state.name_lower)) + if self._relations is not None: + old_name_key = app_label, old_name_lower + new_name_key = app_label, new_name_lower + if old_name_key in self._relations: + self._relations[new_name_key] = self._relations.pop(old_name_key) + for model_relations in self._relations.values(): + if old_name_key in model_relations: + model_relations[new_name_key] = model_relations.pop(old_name_key) + # Reload models related to old model before removing the old model. + self.reload_models(to_reload, delay=True) + # Remove the old model. + self.remove_model(app_label, old_name_lower) + self.reload_model(app_label, new_name_lower, delay=True) + + def alter_model_options(self, app_label, model_name, options, option_keys=None): + model_state = self.models[app_label, model_name] + model_state.options = {**model_state.options, **options} + if option_keys: + for key in option_keys: + if key not in options: + model_state.options.pop(key, False) + self.reload_model(app_label, model_name, delay=True) + + def remove_model_options(self, app_label, model_name, option_name, value_to_remove): + model_state = self.models[app_label, model_name] + if objs := model_state.options.get(option_name): + model_state.options[option_name] = [ + obj for obj in objs if tuple(obj) != tuple(value_to_remove) + ] + self.reload_model(app_label, model_name, delay=True) + + def alter_model_managers(self, app_label, model_name, managers): + model_state = self.models[app_label, model_name] + model_state.managers = list(managers) + self.reload_model(app_label, model_name, delay=True) + + def _append_option(self, app_label, model_name, option_name, obj): + model_state = self.models[app_label, model_name] + model_state.options[option_name] = [*model_state.options[option_name], obj] + self.reload_model(app_label, model_name, delay=True) + + def _remove_option(self, app_label, model_name, option_name, obj_name): + model_state = self.models[app_label, model_name] + objs = model_state.options[option_name] + model_state.options[option_name] = [obj for obj in objs if obj.name != obj_name] + self.reload_model(app_label, model_name, delay=True) + + def add_index(self, app_label, model_name, index): + self._append_option(app_label, model_name, "indexes", index) + + def remove_index(self, app_label, model_name, index_name): + self._remove_option(app_label, model_name, "indexes", index_name) + + def rename_index(self, app_label, model_name, old_index_name, new_index_name): + model_state = self.models[app_label, model_name] + objs = model_state.options["indexes"] + + new_indexes = [] + for obj in objs: + if obj.name == old_index_name: + obj = obj.clone() + obj.name = new_index_name + new_indexes.append(obj) + + model_state.options["indexes"] = new_indexes + self.reload_model(app_label, model_name, delay=True) + + def add_constraint(self, app_label, model_name, constraint): + self._append_option(app_label, model_name, "constraints", constraint) + + def remove_constraint(self, app_label, model_name, constraint_name): + self._remove_option(app_label, model_name, "constraints", constraint_name) + + def add_field(self, app_label, model_name, name, field, preserve_default): + # If preserve default is off, don't use the default for future state. + if not preserve_default: + field = field.clone() + field.default = NOT_PROVIDED + else: + field = field + model_key = app_label, model_name + self.models[model_key].fields[name] = field + if self._relations is not None: + self.resolve_model_field_relations(model_key, name, field) + # Delay rendering of relationships if it's not a relational field. + delay = not field.is_relation + self.reload_model(*model_key, delay=delay) + + def remove_field(self, app_label, model_name, name): + model_key = app_label, model_name + model_state = self.models[model_key] + old_field = model_state.fields.pop(name) + if self._relations is not None: + self.resolve_model_field_relations(model_key, name, old_field) + # Delay rendering of relationships if it's not a relational field. + delay = not old_field.is_relation + self.reload_model(*model_key, delay=delay) + + def alter_field(self, app_label, model_name, name, field, preserve_default): + if not preserve_default: + field = field.clone() + field.default = NOT_PROVIDED + else: + field = field + model_key = app_label, model_name + fields = self.models[model_key].fields + if self._relations is not None: + old_field = fields.pop(name) + if old_field.is_relation: + self.resolve_model_field_relations(model_key, name, old_field) + fields[name] = field + if field.is_relation: + self.resolve_model_field_relations(model_key, name, field) + else: + fields[name] = field + # TODO: investigate if old relational fields must be reloaded or if + # it's sufficient if the new field is (#27737). + # Delay rendering of relationships if it's not a relational field and + # not referenced by a foreign key. + delay = not field.is_relation and not field_is_referenced( + self, model_key, (name, field) + ) + self.reload_model(*model_key, delay=delay) + + def rename_field(self, app_label, model_name, old_name, new_name): + model_key = app_label, model_name + model_state = self.models[model_key] + # Rename the field. + fields = model_state.fields + try: + found = fields.pop(old_name) + except KeyError: + raise FieldDoesNotExist( + f"{app_label}.{model_name} has no field named '{old_name}'" + ) + fields[new_name] = found + for field in fields.values(): + # Fix from_fields to refer to the new field. + from_fields = getattr(field, "from_fields", None) + if from_fields: + field.from_fields = tuple( + [ + new_name if from_field_name == old_name else from_field_name + for from_field_name in from_fields + ] + ) + # Fix index/unique_together to refer to the new field. + options = model_state.options + for option in ("index_together", "unique_together"): + if option in options: + options[option] = [ + [new_name if n == old_name else n for n in together] + for together in options[option] + ] + # Fix to_fields to refer to the new field. + delay = True + references = get_references(self, model_key, (old_name, found)) + for *_, field, reference in references: + delay = False + if reference.to: + remote_field, to_fields = reference.to + if getattr(remote_field, "field_name", None) == old_name: + remote_field.field_name = new_name + if to_fields: + field.to_fields = tuple( + [ + new_name if to_field_name == old_name else to_field_name + for to_field_name in to_fields + ] + ) + if self._relations is not None: + old_name_lower = old_name.lower() + new_name_lower = new_name.lower() + for to_model in self._relations.values(): + if old_name_lower in to_model[model_key]: + field = to_model[model_key].pop(old_name_lower) + field.name = new_name_lower + to_model[model_key][new_name_lower] = field + self.reload_model(*model_key, delay=delay) + + def _find_reload_model(self, app_label, model_name, delay=False): + if delay: + self.is_delayed = True + + related_models = set() + + try: + old_model = self.apps.get_model(app_label, model_name) + except LookupError: + pass + else: + # Get all relations to and from the old model before reloading, + # as _meta.apps may change + if delay: + related_models = get_related_models_tuples(old_model) + else: + related_models = get_related_models_recursive(old_model) + + # Get all outgoing references from the model to be rendered + model_state = self.models[(app_label, model_name)] + # Directly related models are the models pointed to by ForeignKeys, + # OneToOneFields, and ManyToManyFields. + direct_related_models = set() + for field in model_state.fields.values(): + if field.is_relation: + if field.remote_field.model == RECURSIVE_RELATIONSHIP_CONSTANT: + continue + rel_app_label, rel_model_name = _get_app_label_and_model_name( + field.related_model, app_label + ) + direct_related_models.add((rel_app_label, rel_model_name.lower())) + + # For all direct related models recursively get all related models. + related_models.update(direct_related_models) + for rel_app_label, rel_model_name in direct_related_models: + try: + rel_model = self.apps.get_model(rel_app_label, rel_model_name) + except LookupError: + pass + else: + if delay: + related_models.update(get_related_models_tuples(rel_model)) + else: + related_models.update(get_related_models_recursive(rel_model)) + + # Include the model itself + related_models.add((app_label, model_name)) + + return related_models + + def reload_model(self, app_label, model_name, delay=False): + if "apps" in self.__dict__: # hasattr would cache the property + related_models = self._find_reload_model(app_label, model_name, delay) + self._reload(related_models) + + def reload_models(self, models, delay=True): + if "apps" in self.__dict__: # hasattr would cache the property + related_models = set() + for app_label, model_name in models: + related_models.update( + self._find_reload_model(app_label, model_name, delay) + ) + self._reload(related_models) + + def _reload(self, related_models): + # Unregister all related models + with self.apps.bulk_update(): + for rel_app_label, rel_model_name in related_models: + self.apps.unregister_model(rel_app_label, rel_model_name) + + states_to_be_rendered = [] + # Gather all models states of those models that will be rerendered. + # This includes: + # 1. All related models of unmigrated apps + for model_state in self.apps.real_models: + if (model_state.app_label, model_state.name_lower) in related_models: + states_to_be_rendered.append(model_state) + + # 2. All related models of migrated apps + for rel_app_label, rel_model_name in related_models: + try: + model_state = self.models[rel_app_label, rel_model_name] + except KeyError: + pass + else: + states_to_be_rendered.append(model_state) + + # Render all models + self.apps.render_multiple(states_to_be_rendered) + + def update_model_field_relation( + self, + model, + model_key, + field_name, + field, + concretes, + ): + remote_model_key = resolve_relation(model, *model_key) + if remote_model_key[0] not in self.real_apps and remote_model_key in concretes: + remote_model_key = concretes[remote_model_key] + relations_to_remote_model = self._relations[remote_model_key] + if field_name in self.models[model_key].fields: + # The assert holds because it's a new relation, or an altered + # relation, in which case references have been removed by + # alter_field(). + assert field_name not in relations_to_remote_model[model_key] + relations_to_remote_model[model_key][field_name] = field + else: + del relations_to_remote_model[model_key][field_name] + if not relations_to_remote_model[model_key]: + del relations_to_remote_model[model_key] + + def resolve_model_field_relations( + self, + model_key, + field_name, + field, + concretes=None, + ): + remote_field = field.remote_field + if not remote_field: + return + if concretes is None: + concretes, _ = self._get_concrete_models_mapping_and_proxy_models() + + self.update_model_field_relation( + remote_field.model, + model_key, + field_name, + field, + concretes, + ) + + through = getattr(remote_field, "through", None) + if not through: + return + self.update_model_field_relation( + through, model_key, field_name, field, concretes + ) + + def resolve_model_relations(self, model_key, concretes=None): + if concretes is None: + concretes, _ = self._get_concrete_models_mapping_and_proxy_models() + + model_state = self.models[model_key] + for field_name, field in model_state.fields.items(): + self.resolve_model_field_relations(model_key, field_name, field, concretes) + + def resolve_fields_and_relations(self): + # Resolve fields. + for model_state in self.models.values(): + for field_name, field in model_state.fields.items(): + field.name = field_name + # Resolve relations. + # {remote_model_key: {model_key: {field_name: field}}} + self._relations = defaultdict(partial(defaultdict, dict)) + concretes, proxies = self._get_concrete_models_mapping_and_proxy_models() + + for model_key in concretes: + self.resolve_model_relations(model_key, concretes) + + for model_key in proxies: + self._relations[model_key] = self._relations[concretes[model_key]] + + def get_concrete_model_key(self, model): + ( + concrete_models_mapping, + _, + ) = self._get_concrete_models_mapping_and_proxy_models() + model_key = make_model_tuple(model) + return concrete_models_mapping[model_key] + + def _get_concrete_models_mapping_and_proxy_models(self): + concrete_models_mapping = {} + proxy_models = {} + # Split models to proxy and concrete models. + for model_key, model_state in self.models.items(): + if model_state.options.get("proxy"): + proxy_models[model_key] = model_state + # Find a concrete model for the proxy. + concrete_models_mapping[ + model_key + ] = self._find_concrete_model_from_proxy( + proxy_models, + model_state, + ) + else: + concrete_models_mapping[model_key] = model_key + return concrete_models_mapping, proxy_models + + def _find_concrete_model_from_proxy(self, proxy_models, model_state): + for base in model_state.bases: + if not (isinstance(base, str) or issubclass(base, models.Model)): + continue + base_key = make_model_tuple(base) + base_state = proxy_models.get(base_key) + if not base_state: + # Concrete model found, stop looking at bases. + return base_key + return self._find_concrete_model_from_proxy(proxy_models, base_state) + + def clone(self): + """Return an exact copy of this ProjectState.""" + new_state = ProjectState( + models={k: v.clone() for k, v in self.models.items()}, + real_apps=self.real_apps, + ) + if "apps" in self.__dict__: + new_state.apps = self.apps.clone() + new_state.is_delayed = self.is_delayed + return new_state + + def clear_delayed_apps_cache(self): + if self.is_delayed and "apps" in self.__dict__: + del self.__dict__["apps"] + + @cached_property + def apps(self): + return StateApps(self.real_apps, self.models) + + @classmethod + def from_apps(cls, apps): + """Take an Apps and return a ProjectState matching it.""" + app_models = {} + for model in apps.get_models(include_swapped=True): + model_state = ModelState.from_model(model) + app_models[(model_state.app_label, model_state.name_lower)] = model_state + return cls(app_models) + + def __eq__(self, other): + return self.models == other.models and self.real_apps == other.real_apps + + +class AppConfigStub(AppConfig): + """Stub of an AppConfig. Only provides a label and a dict of models.""" + + def __init__(self, label): + self.apps = None + self.models = {} + # App-label and app-name are not the same thing, so technically passing + # in the label here is wrong. In practice, migrations don't care about + # the app name, but we need something unique, and the label works fine. + self.label = label + self.name = label + + def import_models(self): + self.models = self.apps.all_models[self.label] + + +class StateApps(Apps): + """ + Subclass of the global Apps registry class to better handle dynamic model + additions and removals. + """ + + def __init__(self, real_apps, models, ignore_swappable=False): + # Any apps in self.real_apps should have all their models included + # in the render. We don't use the original model instances as there + # are some variables that refer to the Apps object. + # FKs/M2Ms from real apps are also not included as they just + # mess things up with partial states (due to lack of dependencies) + self.real_models = [] + for app_label in real_apps: + app = global_apps.get_app_config(app_label) + for model in app.get_models(): + self.real_models.append(ModelState.from_model(model, exclude_rels=True)) + # Populate the app registry with a stub for each application. + app_labels = {model_state.app_label for model_state in models.values()} + app_configs = [ + AppConfigStub(label) for label in sorted([*real_apps, *app_labels]) + ] + super().__init__(app_configs) + + # These locks get in the way of copying as implemented in clone(), + # which is called whenever Django duplicates a StateApps before + # updating it. + self._lock = None + self.ready_event = None + + self.render_multiple([*models.values(), *self.real_models]) + + # There shouldn't be any operations pending at this point. + from django.core.checks.model_checks import _check_lazy_references + + ignore = ( + {make_model_tuple(settings.AUTH_USER_MODEL)} if ignore_swappable else set() + ) + errors = _check_lazy_references(self, ignore=ignore) + if errors: + raise ValueError("\n".join(error.msg for error in errors)) + + @contextmanager + def bulk_update(self): + # Avoid clearing each model's cache for each change. Instead, clear + # all caches when we're finished updating the model instances. + ready = self.ready + self.ready = False + try: + yield + finally: + self.ready = ready + self.clear_cache() + + def render_multiple(self, model_states): + # We keep trying to render the models in a loop, ignoring invalid + # base errors, until the size of the unrendered models doesn't + # decrease by at least one, meaning there's a base dependency loop/ + # missing base. + if not model_states: + return + # Prevent that all model caches are expired for each render. + with self.bulk_update(): + unrendered_models = model_states + while unrendered_models: + new_unrendered_models = [] + for model in unrendered_models: + try: + model.render(self) + except InvalidBasesError: + new_unrendered_models.append(model) + if len(new_unrendered_models) == len(unrendered_models): + raise InvalidBasesError( + "Cannot resolve bases for %r\nThis can happen if you are " + "inheriting models from an app with migrations (e.g. " + "contrib.auth)\n in an app with no migrations; see " + "https://docs.djangoproject.com/en/%s/topics/migrations/" + "#dependencies for more" + % (new_unrendered_models, get_docs_version()) + ) + unrendered_models = new_unrendered_models + + def clone(self): + """Return a clone of this registry.""" + clone = StateApps([], {}) + clone.all_models = copy.deepcopy(self.all_models) + + for app_label in self.app_configs: + app_config = AppConfigStub(app_label) + app_config.apps = clone + app_config.import_models() + clone.app_configs[app_label] = app_config + + # No need to actually clone them, they'll never change + clone.real_models = self.real_models + return clone + + def register_model(self, app_label, model): + self.all_models[app_label][model._meta.model_name] = model + if app_label not in self.app_configs: + self.app_configs[app_label] = AppConfigStub(app_label) + self.app_configs[app_label].apps = self + self.app_configs[app_label].models[model._meta.model_name] = model + self.do_pending_operations(model) + self.clear_cache() + + def unregister_model(self, app_label, model_name): + try: + del self.all_models[app_label][model_name] + del self.app_configs[app_label].models[model_name] + except KeyError: + pass + + +class ModelState: + """ + Represent a Django Model. Don't use the actual Model class as it's not + designed to have its options changed - instead, mutate this one and then + render it into a Model as required. + + Note that while you are allowed to mutate .fields, you are not allowed + to mutate the Field instances inside there themselves - you must instead + assign new ones, as these are not detached during a clone. + """ + + def __init__( + self, app_label, name, fields, options=None, bases=None, managers=None + ): + self.app_label = app_label + self.name = name + self.fields = dict(fields) + self.options = options or {} + self.options.setdefault("indexes", []) + self.options.setdefault("constraints", []) + self.bases = bases or (models.Model,) + self.managers = managers or [] + for name, field in self.fields.items(): + # Sanity-check that fields are NOT already bound to a model. + if hasattr(field, "model"): + raise ValueError( + 'ModelState.fields cannot be bound to a model - "%s" is.' % name + ) + # Sanity-check that relation fields are NOT referring to a model class. + if field.is_relation and hasattr(field.related_model, "_meta"): + raise ValueError( + 'ModelState.fields cannot refer to a model class - "%s.to" does. ' + "Use a string reference instead." % name + ) + if field.many_to_many and hasattr(field.remote_field.through, "_meta"): + raise ValueError( + 'ModelState.fields cannot refer to a model class - "%s.through" ' + "does. Use a string reference instead." % name + ) + # Sanity-check that indexes have their name set. + for index in self.options["indexes"]: + if not index.name: + raise ValueError( + "Indexes passed to ModelState require a name attribute. " + "%r doesn't have one." % index + ) + + @cached_property + def name_lower(self): + return self.name.lower() + + def get_field(self, field_name): + if field_name == "_order": + field_name = self.options.get("order_with_respect_to", field_name) + return self.fields[field_name] + + @classmethod + def from_model(cls, model, exclude_rels=False): + """Given a model, return a ModelState representing it.""" + # Deconstruct the fields + fields = [] + for field in model._meta.local_fields: + if getattr(field, "remote_field", None) and exclude_rels: + continue + if isinstance(field, models.OrderWrt): + continue + name = field.name + try: + fields.append((name, field.clone())) + except TypeError as e: + raise TypeError( + "Couldn't reconstruct field %s on %s: %s" + % ( + name, + model._meta.label, + e, + ) + ) + if not exclude_rels: + for field in model._meta.local_many_to_many: + name = field.name + try: + fields.append((name, field.clone())) + except TypeError as e: + raise TypeError( + "Couldn't reconstruct m2m field %s on %s: %s" + % ( + name, + model._meta.object_name, + e, + ) + ) + # Extract the options + options = {} + for name in DEFAULT_NAMES: + # Ignore some special options + if name in ["apps", "app_label"]: + continue + elif name in model._meta.original_attrs: + if name == "unique_together": + ut = model._meta.original_attrs["unique_together"] + options[name] = set(normalize_together(ut)) + elif name == "index_together": + it = model._meta.original_attrs["index_together"] + options[name] = set(normalize_together(it)) + elif name == "indexes": + indexes = [idx.clone() for idx in model._meta.indexes] + for index in indexes: + if not index.name: + index.set_name_with_model(model) + options["indexes"] = indexes + elif name == "constraints": + options["constraints"] = [ + con.clone() for con in model._meta.constraints + ] + else: + options[name] = model._meta.original_attrs[name] + # If we're ignoring relationships, remove all field-listing model + # options (that option basically just means "make a stub model") + if exclude_rels: + for key in ["unique_together", "index_together", "order_with_respect_to"]: + if key in options: + del options[key] + # Private fields are ignored, so remove options that refer to them. + elif options.get("order_with_respect_to") in { + field.name for field in model._meta.private_fields + }: + del options["order_with_respect_to"] + + def flatten_bases(model): + bases = [] + for base in model.__bases__: + if hasattr(base, "_meta") and base._meta.abstract: + bases.extend(flatten_bases(base)) + else: + bases.append(base) + return bases + + # We can't rely on __mro__ directly because we only want to flatten + # abstract models and not the whole tree. However by recursing on + # __bases__ we may end up with duplicates and ordering issues, we + # therefore discard any duplicates and reorder the bases according + # to their index in the MRO. + flattened_bases = sorted( + set(flatten_bases(model)), key=lambda x: model.__mro__.index(x) + ) + + # Make our record + bases = tuple( + (base._meta.label_lower if hasattr(base, "_meta") else base) + for base in flattened_bases + ) + # Ensure at least one base inherits from models.Model + if not any( + (isinstance(base, str) or issubclass(base, models.Model)) for base in bases + ): + bases = (models.Model,) + + managers = [] + manager_names = set() + default_manager_shim = None + for manager in model._meta.managers: + if manager.name in manager_names: + # Skip overridden managers. + continue + elif manager.use_in_migrations: + # Copy managers usable in migrations. + new_manager = copy.copy(manager) + new_manager._set_creation_counter() + elif manager is model._base_manager or manager is model._default_manager: + # Shim custom managers used as default and base managers. + new_manager = models.Manager() + new_manager.model = manager.model + new_manager.name = manager.name + if manager is model._default_manager: + default_manager_shim = new_manager + else: + continue + manager_names.add(manager.name) + managers.append((manager.name, new_manager)) + + # Ignore a shimmed default manager called objects if it's the only one. + if managers == [("objects", default_manager_shim)]: + managers = [] + + # Construct the new ModelState + return cls( + model._meta.app_label, + model._meta.object_name, + fields, + options, + bases, + managers, + ) + + def construct_managers(self): + """Deep-clone the managers using deconstruction.""" + # Sort all managers by their creation counter + sorted_managers = sorted(self.managers, key=lambda v: v[1].creation_counter) + for mgr_name, manager in sorted_managers: + as_manager, manager_path, qs_path, args, kwargs = manager.deconstruct() + if as_manager: + qs_class = import_string(qs_path) + yield mgr_name, qs_class.as_manager() + else: + manager_class = import_string(manager_path) + yield mgr_name, manager_class(*args, **kwargs) + + def clone(self): + """Return an exact copy of this ModelState.""" + return self.__class__( + app_label=self.app_label, + name=self.name, + fields=dict(self.fields), + # Since options are shallow-copied here, operations such as + # AddIndex must replace their option (e.g 'indexes') rather + # than mutating it. + options=dict(self.options), + bases=self.bases, + managers=list(self.managers), + ) + + def render(self, apps): + """Create a Model object from our current state into the given apps.""" + # First, make a Meta object + meta_contents = {"app_label": self.app_label, "apps": apps, **self.options} + meta = type("Meta", (), meta_contents) + # Then, work out our bases + try: + bases = tuple( + (apps.get_model(base) if isinstance(base, str) else base) + for base in self.bases + ) + except LookupError: + raise InvalidBasesError( + "Cannot resolve one or more bases from %r" % (self.bases,) + ) + # Clone fields for the body, add other bits. + body = {name: field.clone() for name, field in self.fields.items()} + body["Meta"] = meta + body["__module__"] = "__fake__" + + # Restore managers + body.update(self.construct_managers()) + # Then, make a Model object (apps.register_model is called in __new__) + return type(self.name, bases, body) + + def get_index_by_name(self, name): + for index in self.options["indexes"]: + if index.name == name: + return index + raise ValueError("No index named %s on model %s" % (name, self.name)) + + def get_constraint_by_name(self, name): + for constraint in self.options["constraints"]: + if constraint.name == name: + return constraint + raise ValueError("No constraint named %s on model %s" % (name, self.name)) + + def __repr__(self): + return "<%s: '%s.%s'>" % (self.__class__.__name__, self.app_label, self.name) + + def __eq__(self, other): + return ( + (self.app_label == other.app_label) + and (self.name == other.name) + and (len(self.fields) == len(other.fields)) + and all( + k1 == k2 and f1.deconstruct()[1:] == f2.deconstruct()[1:] + for (k1, f1), (k2, f2) in zip( + sorted(self.fields.items()), + sorted(other.fields.items()), + ) + ) + and (self.options == other.options) + and (self.bases == other.bases) + and (self.managers == other.managers) + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/utils.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/utils.py new file mode 100644 index 0000000..6eb5a4c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/utils.py @@ -0,0 +1,129 @@ +import datetime +import re +from collections import namedtuple + +from django.db.models.fields.related import RECURSIVE_RELATIONSHIP_CONSTANT + +FieldReference = namedtuple("FieldReference", "to through") + +COMPILED_REGEX_TYPE = type(re.compile("")) + + +class RegexObject: + def __init__(self, obj): + self.pattern = obj.pattern + self.flags = obj.flags + + def __eq__(self, other): + if not isinstance(other, RegexObject): + return NotImplemented + return self.pattern == other.pattern and self.flags == other.flags + + +def get_migration_name_timestamp(): + return datetime.datetime.now().strftime("%Y%m%d_%H%M") + + +def resolve_relation(model, app_label=None, model_name=None): + """ + Turn a model class or model reference string and return a model tuple. + + app_label and model_name are used to resolve the scope of recursive and + unscoped model relationship. + """ + if isinstance(model, str): + if model == RECURSIVE_RELATIONSHIP_CONSTANT: + if app_label is None or model_name is None: + raise TypeError( + "app_label and model_name must be provided to resolve " + "recursive relationships." + ) + return app_label, model_name + if "." in model: + app_label, model_name = model.split(".", 1) + return app_label, model_name.lower() + if app_label is None: + raise TypeError( + "app_label must be provided to resolve unscoped model relationships." + ) + return app_label, model.lower() + return model._meta.app_label, model._meta.model_name + + +def field_references( + model_tuple, + field, + reference_model_tuple, + reference_field_name=None, + reference_field=None, +): + """ + Return either False or a FieldReference if `field` references provided + context. + + False positives can be returned if `reference_field_name` is provided + without `reference_field` because of the introspection limitation it + incurs. This should not be an issue when this function is used to determine + whether or not an optimization can take place. + """ + remote_field = field.remote_field + if not remote_field: + return False + references_to = None + references_through = None + if resolve_relation(remote_field.model, *model_tuple) == reference_model_tuple: + to_fields = getattr(field, "to_fields", None) + if ( + reference_field_name is None + or + # Unspecified to_field(s). + to_fields is None + or + # Reference to primary key. + ( + None in to_fields + and (reference_field is None or reference_field.primary_key) + ) + or + # Reference to field. + reference_field_name in to_fields + ): + references_to = (remote_field, to_fields) + through = getattr(remote_field, "through", None) + if through and resolve_relation(through, *model_tuple) == reference_model_tuple: + through_fields = remote_field.through_fields + if ( + reference_field_name is None + or + # Unspecified through_fields. + through_fields is None + or + # Reference to field. + reference_field_name in through_fields + ): + references_through = (remote_field, through_fields) + if not (references_to or references_through): + return False + return FieldReference(references_to, references_through) + + +def get_references(state, model_tuple, field_tuple=()): + """ + Generator of (model_state, name, field, reference) referencing + provided context. + + If field_tuple is provided only references to this particular field of + model_tuple will be generated. + """ + for state_model_tuple, model_state in state.models.items(): + for name, field in model_state.fields.items(): + reference = field_references( + state_model_tuple, field, model_tuple, *field_tuple + ) + if reference: + yield model_state, name, field, reference + + +def field_is_referenced(state, model_tuple, field_tuple): + """Return whether `field_tuple` is referenced by any state models.""" + return next(get_references(state, model_tuple, field_tuple), None) is not None diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/writer.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/writer.py new file mode 100644 index 0000000..3dd3014 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/migrations/writer.py @@ -0,0 +1,316 @@ +import os +import re +from importlib import import_module + +from django import get_version +from django.apps import apps + +# SettingsReference imported for backwards compatibility in Django 2.2. +from django.conf import SettingsReference # NOQA +from django.db import migrations +from django.db.migrations.loader import MigrationLoader +from django.db.migrations.serializer import Serializer, serializer_factory +from django.utils.inspect import get_func_args +from django.utils.module_loading import module_dir +from django.utils.timezone import now + + +class OperationWriter: + def __init__(self, operation, indentation=2): + self.operation = operation + self.buff = [] + self.indentation = indentation + + def serialize(self): + def _write(_arg_name, _arg_value): + if _arg_name in self.operation.serialization_expand_args and isinstance( + _arg_value, (list, tuple, dict) + ): + if isinstance(_arg_value, dict): + self.feed("%s={" % _arg_name) + self.indent() + for key, value in _arg_value.items(): + key_string, key_imports = MigrationWriter.serialize(key) + arg_string, arg_imports = MigrationWriter.serialize(value) + args = arg_string.splitlines() + if len(args) > 1: + self.feed("%s: %s" % (key_string, args[0])) + for arg in args[1:-1]: + self.feed(arg) + self.feed("%s," % args[-1]) + else: + self.feed("%s: %s," % (key_string, arg_string)) + imports.update(key_imports) + imports.update(arg_imports) + self.unindent() + self.feed("},") + else: + self.feed("%s=[" % _arg_name) + self.indent() + for item in _arg_value: + arg_string, arg_imports = MigrationWriter.serialize(item) + args = arg_string.splitlines() + if len(args) > 1: + for arg in args[:-1]: + self.feed(arg) + self.feed("%s," % args[-1]) + else: + self.feed("%s," % arg_string) + imports.update(arg_imports) + self.unindent() + self.feed("],") + else: + arg_string, arg_imports = MigrationWriter.serialize(_arg_value) + args = arg_string.splitlines() + if len(args) > 1: + self.feed("%s=%s" % (_arg_name, args[0])) + for arg in args[1:-1]: + self.feed(arg) + self.feed("%s," % args[-1]) + else: + self.feed("%s=%s," % (_arg_name, arg_string)) + imports.update(arg_imports) + + imports = set() + name, args, kwargs = self.operation.deconstruct() + operation_args = get_func_args(self.operation.__init__) + + # See if this operation is in django.db.migrations. If it is, + # We can just use the fact we already have that imported, + # otherwise, we need to add an import for the operation class. + if getattr(migrations, name, None) == self.operation.__class__: + self.feed("migrations.%s(" % name) + else: + imports.add("import %s" % (self.operation.__class__.__module__)) + self.feed("%s.%s(" % (self.operation.__class__.__module__, name)) + + self.indent() + + for i, arg in enumerate(args): + arg_value = arg + arg_name = operation_args[i] + _write(arg_name, arg_value) + + i = len(args) + # Only iterate over remaining arguments + for arg_name in operation_args[i:]: + if arg_name in kwargs: # Don't sort to maintain signature order + arg_value = kwargs[arg_name] + _write(arg_name, arg_value) + + self.unindent() + self.feed("),") + return self.render(), imports + + def indent(self): + self.indentation += 1 + + def unindent(self): + self.indentation -= 1 + + def feed(self, line): + self.buff.append(" " * (self.indentation * 4) + line) + + def render(self): + return "\n".join(self.buff) + + +class MigrationWriter: + """ + Take a Migration instance and is able to produce the contents + of the migration file from it. + """ + + def __init__(self, migration, include_header=True): + self.migration = migration + self.include_header = include_header + self.needs_manual_porting = False + + def as_string(self): + """Return a string of the file contents.""" + items = { + "replaces_str": "", + "initial_str": "", + } + + imports = set() + + # Deconstruct operations + operations = [] + for operation in self.migration.operations: + operation_string, operation_imports = OperationWriter(operation).serialize() + imports.update(operation_imports) + operations.append(operation_string) + items["operations"] = "\n".join(operations) + "\n" if operations else "" + + # Format dependencies and write out swappable dependencies right + dependencies = [] + for dependency in self.migration.dependencies: + if dependency[0] == "__setting__": + dependencies.append( + " migrations.swappable_dependency(settings.%s)," + % dependency[1] + ) + imports.add("from django.conf import settings") + else: + dependencies.append(" %s," % self.serialize(dependency)[0]) + items["dependencies"] = ( + "\n".join(sorted(dependencies)) + "\n" if dependencies else "" + ) + + # Format imports nicely, swapping imports of functions from migration files + # for comments + migration_imports = set() + for line in list(imports): + if re.match(r"^import (.*)\.\d+[^\s]*$", line): + migration_imports.add(line.split("import")[1].strip()) + imports.remove(line) + self.needs_manual_porting = True + + # django.db.migrations is always used, but models import may not be. + # If models import exists, merge it with migrations import. + if "from django.db import models" in imports: + imports.discard("from django.db import models") + imports.add("from django.db import migrations, models") + else: + imports.add("from django.db import migrations") + + # Sort imports by the package / module to be imported (the part after + # "from" in "from ... import ..." or after "import" in "import ..."). + # First group the "import" statements, then "from ... import ...". + sorted_imports = sorted( + imports, key=lambda i: (i.split()[0] == "from", i.split()[1]) + ) + items["imports"] = "\n".join(sorted_imports) + "\n" if imports else "" + if migration_imports: + items["imports"] += ( + "\n\n# Functions from the following migrations need manual " + "copying.\n# Move them and any dependencies into this file, " + "then update the\n# RunPython operations to refer to the local " + "versions:\n# %s" + ) % "\n# ".join(sorted(migration_imports)) + # If there's a replaces, make a string for it + if self.migration.replaces: + items["replaces_str"] = ( + "\n replaces = %s\n" % self.serialize(self.migration.replaces)[0] + ) + # Hinting that goes into comment + if self.include_header: + items["migration_header"] = MIGRATION_HEADER_TEMPLATE % { + "version": get_version(), + "timestamp": now().strftime("%Y-%m-%d %H:%M"), + } + else: + items["migration_header"] = "" + + if self.migration.initial: + items["initial_str"] = "\n initial = True\n" + + return MIGRATION_TEMPLATE % items + + @property + def basedir(self): + migrations_package_name, _ = MigrationLoader.migrations_module( + self.migration.app_label + ) + + if migrations_package_name is None: + raise ValueError( + "Django can't create migrations for app '%s' because " + "migrations have been disabled via the MIGRATION_MODULES " + "setting." % self.migration.app_label + ) + + # See if we can import the migrations module directly + try: + migrations_module = import_module(migrations_package_name) + except ImportError: + pass + else: + try: + return module_dir(migrations_module) + except ValueError: + pass + + # Alright, see if it's a direct submodule of the app + app_config = apps.get_app_config(self.migration.app_label) + ( + maybe_app_name, + _, + migrations_package_basename, + ) = migrations_package_name.rpartition(".") + if app_config.name == maybe_app_name: + return os.path.join(app_config.path, migrations_package_basename) + + # In case of using MIGRATION_MODULES setting and the custom package + # doesn't exist, create one, starting from an existing package + existing_dirs, missing_dirs = migrations_package_name.split("."), [] + while existing_dirs: + missing_dirs.insert(0, existing_dirs.pop(-1)) + try: + base_module = import_module(".".join(existing_dirs)) + except (ImportError, ValueError): + continue + else: + try: + base_dir = module_dir(base_module) + except ValueError: + continue + else: + break + else: + raise ValueError( + "Could not locate an appropriate location to create " + "migrations package %s. Make sure the toplevel " + "package exists and can be imported." % migrations_package_name + ) + + final_dir = os.path.join(base_dir, *missing_dirs) + os.makedirs(final_dir, exist_ok=True) + for missing_dir in missing_dirs: + base_dir = os.path.join(base_dir, missing_dir) + with open(os.path.join(base_dir, "__init__.py"), "w"): + pass + + return final_dir + + @property + def filename(self): + return "%s.py" % self.migration.name + + @property + def path(self): + return os.path.join(self.basedir, self.filename) + + @classmethod + def serialize(cls, value): + return serializer_factory(value).serialize() + + @classmethod + def register_serializer(cls, type_, serializer): + Serializer.register(type_, serializer) + + @classmethod + def unregister_serializer(cls, type_): + Serializer.unregister(type_) + + +MIGRATION_HEADER_TEMPLATE = """\ +# Generated by Django %(version)s on %(timestamp)s + +""" + + +MIGRATION_TEMPLATE = """\ +%(migration_header)s%(imports)s + +class Migration(migrations.Migration): +%(replaces_str)s%(initial_str)s + dependencies = [ +%(dependencies)s\ + ] + + operations = [ +%(operations)s\ + ] +""" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/__init__.py new file mode 100644 index 0000000..9426280 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/__init__.py @@ -0,0 +1,117 @@ +from django.core.exceptions import ObjectDoesNotExist +from django.db.models import signals +from django.db.models.aggregates import * # NOQA +from django.db.models.aggregates import __all__ as aggregates_all +from django.db.models.constraints import * # NOQA +from django.db.models.constraints import __all__ as constraints_all +from django.db.models.deletion import ( + CASCADE, + DO_NOTHING, + PROTECT, + RESTRICT, + SET, + SET_DEFAULT, + SET_NULL, + ProtectedError, + RestrictedError, +) +from django.db.models.enums import * # NOQA +from django.db.models.enums import __all__ as enums_all +from django.db.models.expressions import ( + Case, + Exists, + Expression, + ExpressionList, + ExpressionWrapper, + F, + Func, + OrderBy, + OuterRef, + RowRange, + Subquery, + Value, + ValueRange, + When, + Window, + WindowFrame, +) +from django.db.models.fields import * # NOQA +from django.db.models.fields import __all__ as fields_all +from django.db.models.fields.files import FileField, ImageField +from django.db.models.fields.generated import GeneratedField +from django.db.models.fields.json import JSONField +from django.db.models.fields.proxy import OrderWrt +from django.db.models.indexes import * # NOQA +from django.db.models.indexes import __all__ as indexes_all +from django.db.models.lookups import Lookup, Transform +from django.db.models.manager import Manager +from django.db.models.query import Prefetch, QuerySet, prefetch_related_objects +from django.db.models.query_utils import FilteredRelation, Q + +# Imports that would create circular imports if sorted +from django.db.models.base import DEFERRED, Model # isort:skip +from django.db.models.fields.related import ( # isort:skip + ForeignKey, + ForeignObject, + OneToOneField, + ManyToManyField, + ForeignObjectRel, + ManyToOneRel, + ManyToManyRel, + OneToOneRel, +) + + +__all__ = aggregates_all + constraints_all + enums_all + fields_all + indexes_all +__all__ += [ + "ObjectDoesNotExist", + "signals", + "CASCADE", + "DO_NOTHING", + "PROTECT", + "RESTRICT", + "SET", + "SET_DEFAULT", + "SET_NULL", + "ProtectedError", + "RestrictedError", + "Case", + "Exists", + "Expression", + "ExpressionList", + "ExpressionWrapper", + "F", + "Func", + "OrderBy", + "OuterRef", + "RowRange", + "Subquery", + "Value", + "ValueRange", + "When", + "Window", + "WindowFrame", + "FileField", + "ImageField", + "GeneratedField", + "JSONField", + "OrderWrt", + "Lookup", + "Transform", + "Manager", + "Prefetch", + "Q", + "QuerySet", + "prefetch_related_objects", + "DEFERRED", + "Model", + "FilteredRelation", + "ForeignKey", + "ForeignObject", + "OneToOneField", + "ManyToManyField", + "ForeignObjectRel", + "ManyToOneRel", + "ManyToManyRel", + "OneToOneRel", +] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/aggregates.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/aggregates.py new file mode 100644 index 0000000..a778cd4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/aggregates.py @@ -0,0 +1,210 @@ +""" +Classes to represent the definitions of aggregate functions. +""" +from django.core.exceptions import FieldError, FullResultSet +from django.db.models.expressions import Case, Func, Star, Value, When +from django.db.models.fields import IntegerField +from django.db.models.functions.comparison import Coalesce +from django.db.models.functions.mixins import ( + FixDurationInputMixin, + NumericOutputFieldMixin, +) + +__all__ = [ + "Aggregate", + "Avg", + "Count", + "Max", + "Min", + "StdDev", + "Sum", + "Variance", +] + + +class Aggregate(Func): + template = "%(function)s(%(distinct)s%(expressions)s)" + contains_aggregate = True + name = None + filter_template = "%s FILTER (WHERE %%(filter)s)" + window_compatible = True + allow_distinct = False + empty_result_set_value = None + + def __init__( + self, *expressions, distinct=False, filter=None, default=None, **extra + ): + if distinct and not self.allow_distinct: + raise TypeError("%s does not allow distinct." % self.__class__.__name__) + if default is not None and self.empty_result_set_value is not None: + raise TypeError(f"{self.__class__.__name__} does not allow default.") + self.distinct = distinct + self.filter = filter + self.default = default + super().__init__(*expressions, **extra) + + def get_source_fields(self): + # Don't return the filter expression since it's not a source field. + return [e._output_field_or_none for e in super().get_source_expressions()] + + def get_source_expressions(self): + source_expressions = super().get_source_expressions() + if self.filter: + return source_expressions + [self.filter] + return source_expressions + + def set_source_expressions(self, exprs): + self.filter = self.filter and exprs.pop() + return super().set_source_expressions(exprs) + + def resolve_expression( + self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False + ): + # Aggregates are not allowed in UPDATE queries, so ignore for_save + c = super().resolve_expression(query, allow_joins, reuse, summarize) + c.filter = c.filter and c.filter.resolve_expression( + query, allow_joins, reuse, summarize + ) + if summarize: + # Summarized aggregates cannot refer to summarized aggregates. + for ref in c.get_refs(): + if query.annotations[ref].is_summary: + raise FieldError( + f"Cannot compute {c.name}('{ref}'): '{ref}' is an aggregate" + ) + elif not self.is_summary: + # Call Aggregate.get_source_expressions() to avoid + # returning self.filter and including that in this loop. + expressions = super(Aggregate, c).get_source_expressions() + for index, expr in enumerate(expressions): + if expr.contains_aggregate: + before_resolved = self.get_source_expressions()[index] + name = ( + before_resolved.name + if hasattr(before_resolved, "name") + else repr(before_resolved) + ) + raise FieldError( + "Cannot compute %s('%s'): '%s' is an aggregate" + % (c.name, name, name) + ) + if (default := c.default) is None: + return c + if hasattr(default, "resolve_expression"): + default = default.resolve_expression(query, allow_joins, reuse, summarize) + if default._output_field_or_none is None: + default.output_field = c._output_field_or_none + else: + default = Value(default, c._output_field_or_none) + c.default = None # Reset the default argument before wrapping. + coalesce = Coalesce(c, default, output_field=c._output_field_or_none) + coalesce.is_summary = c.is_summary + return coalesce + + @property + def default_alias(self): + expressions = self.get_source_expressions() + if len(expressions) == 1 and hasattr(expressions[0], "name"): + return "%s__%s" % (expressions[0].name, self.name.lower()) + raise TypeError("Complex expressions require an alias") + + def get_group_by_cols(self): + return [] + + def as_sql(self, compiler, connection, **extra_context): + extra_context["distinct"] = "DISTINCT " if self.distinct else "" + if self.filter: + if connection.features.supports_aggregate_filter_clause: + try: + filter_sql, filter_params = self.filter.as_sql(compiler, connection) + except FullResultSet: + pass + else: + template = self.filter_template % extra_context.get( + "template", self.template + ) + sql, params = super().as_sql( + compiler, + connection, + template=template, + filter=filter_sql, + **extra_context, + ) + return sql, (*params, *filter_params) + else: + copy = self.copy() + copy.filter = None + source_expressions = copy.get_source_expressions() + condition = When(self.filter, then=source_expressions[0]) + copy.set_source_expressions([Case(condition)] + source_expressions[1:]) + return super(Aggregate, copy).as_sql( + compiler, connection, **extra_context + ) + return super().as_sql(compiler, connection, **extra_context) + + def _get_repr_options(self): + options = super()._get_repr_options() + if self.distinct: + options["distinct"] = self.distinct + if self.filter: + options["filter"] = self.filter + return options + + +class Avg(FixDurationInputMixin, NumericOutputFieldMixin, Aggregate): + function = "AVG" + name = "Avg" + allow_distinct = True + + +class Count(Aggregate): + function = "COUNT" + name = "Count" + output_field = IntegerField() + allow_distinct = True + empty_result_set_value = 0 + + def __init__(self, expression, filter=None, **extra): + if expression == "*": + expression = Star() + if isinstance(expression, Star) and filter is not None: + raise ValueError("Star cannot be used with filter. Please specify a field.") + super().__init__(expression, filter=filter, **extra) + + +class Max(Aggregate): + function = "MAX" + name = "Max" + + +class Min(Aggregate): + function = "MIN" + name = "Min" + + +class StdDev(NumericOutputFieldMixin, Aggregate): + name = "StdDev" + + def __init__(self, expression, sample=False, **extra): + self.function = "STDDEV_SAMP" if sample else "STDDEV_POP" + super().__init__(expression, **extra) + + def _get_repr_options(self): + return {**super()._get_repr_options(), "sample": self.function == "STDDEV_SAMP"} + + +class Sum(FixDurationInputMixin, Aggregate): + function = "SUM" + name = "Sum" + allow_distinct = True + + +class Variance(NumericOutputFieldMixin, Aggregate): + name = "Variance" + + def __init__(self, expression, sample=False, **extra): + self.function = "VAR_SAMP" if sample else "VAR_POP" + super().__init__(expression, **extra) + + def _get_repr_options(self): + return {**super()._get_repr_options(), "sample": self.function == "VAR_SAMP"} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/base.py new file mode 100644 index 0000000..80503d1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/base.py @@ -0,0 +1,2611 @@ +import copy +import inspect +import warnings +from functools import partialmethod +from itertools import chain + +from asgiref.sync import sync_to_async + +import django +from django.apps import apps +from django.conf import settings +from django.core import checks +from django.core.exceptions import ( + NON_FIELD_ERRORS, + FieldDoesNotExist, + FieldError, + MultipleObjectsReturned, + ObjectDoesNotExist, + ValidationError, +) +from django.db import ( + DJANGO_VERSION_PICKLE_KEY, + DatabaseError, + connection, + connections, + router, + transaction, +) +from django.db.models import NOT_PROVIDED, ExpressionWrapper, IntegerField, Max, Value +from django.db.models.constants import LOOKUP_SEP +from django.db.models.constraints import CheckConstraint, UniqueConstraint +from django.db.models.deletion import CASCADE, Collector +from django.db.models.expressions import RawSQL +from django.db.models.fields.related import ( + ForeignObjectRel, + OneToOneField, + lazy_related_operation, + resolve_relation, +) +from django.db.models.functions import Coalesce +from django.db.models.manager import Manager +from django.db.models.options import Options +from django.db.models.query import F, Q +from django.db.models.signals import ( + class_prepared, + post_init, + post_save, + pre_init, + pre_save, +) +from django.db.models.utils import AltersData, make_model_tuple +from django.utils.encoding import force_str +from django.utils.hashable import make_hashable +from django.utils.text import capfirst, get_text_list +from django.utils.translation import gettext_lazy as _ + + +class Deferred: + def __repr__(self): + return "" + + def __str__(self): + return "" + + +DEFERRED = Deferred() + + +def subclass_exception(name, bases, module, attached_to): + """ + Create exception subclass. Used by ModelBase below. + + The exception is created in a way that allows it to be pickled, assuming + that the returned exception class will be added as an attribute to the + 'attached_to' class. + """ + return type( + name, + bases, + { + "__module__": module, + "__qualname__": "%s.%s" % (attached_to.__qualname__, name), + }, + ) + + +def _has_contribute_to_class(value): + # Only call contribute_to_class() if it's bound. + return not inspect.isclass(value) and hasattr(value, "contribute_to_class") + + +class ModelBase(type): + """Metaclass for all models.""" + + def __new__(cls, name, bases, attrs, **kwargs): + super_new = super().__new__ + + # Also ensure initialization is only performed for subclasses of Model + # (excluding Model class itself). + parents = [b for b in bases if isinstance(b, ModelBase)] + if not parents: + return super_new(cls, name, bases, attrs) + + # Create the class. + module = attrs.pop("__module__") + new_attrs = {"__module__": module} + classcell = attrs.pop("__classcell__", None) + if classcell is not None: + new_attrs["__classcell__"] = classcell + attr_meta = attrs.pop("Meta", None) + # Pass all attrs without a (Django-specific) contribute_to_class() + # method to type.__new__() so that they're properly initialized + # (i.e. __set_name__()). + contributable_attrs = {} + for obj_name, obj in attrs.items(): + if _has_contribute_to_class(obj): + contributable_attrs[obj_name] = obj + else: + new_attrs[obj_name] = obj + new_class = super_new(cls, name, bases, new_attrs, **kwargs) + + abstract = getattr(attr_meta, "abstract", False) + meta = attr_meta or getattr(new_class, "Meta", None) + base_meta = getattr(new_class, "_meta", None) + + app_label = None + + # Look for an application configuration to attach the model to. + app_config = apps.get_containing_app_config(module) + + if getattr(meta, "app_label", None) is None: + if app_config is None: + if not abstract: + raise RuntimeError( + "Model class %s.%s doesn't declare an explicit " + "app_label and isn't in an application in " + "INSTALLED_APPS." % (module, name) + ) + + else: + app_label = app_config.label + + new_class.add_to_class("_meta", Options(meta, app_label)) + if not abstract: + new_class.add_to_class( + "DoesNotExist", + subclass_exception( + "DoesNotExist", + tuple( + x.DoesNotExist + for x in parents + if hasattr(x, "_meta") and not x._meta.abstract + ) + or (ObjectDoesNotExist,), + module, + attached_to=new_class, + ), + ) + new_class.add_to_class( + "MultipleObjectsReturned", + subclass_exception( + "MultipleObjectsReturned", + tuple( + x.MultipleObjectsReturned + for x in parents + if hasattr(x, "_meta") and not x._meta.abstract + ) + or (MultipleObjectsReturned,), + module, + attached_to=new_class, + ), + ) + if base_meta and not base_meta.abstract: + # Non-abstract child classes inherit some attributes from their + # non-abstract parent (unless an ABC comes before it in the + # method resolution order). + if not hasattr(meta, "ordering"): + new_class._meta.ordering = base_meta.ordering + if not hasattr(meta, "get_latest_by"): + new_class._meta.get_latest_by = base_meta.get_latest_by + + is_proxy = new_class._meta.proxy + + # If the model is a proxy, ensure that the base class + # hasn't been swapped out. + if is_proxy and base_meta and base_meta.swapped: + raise TypeError( + "%s cannot proxy the swapped model '%s'." % (name, base_meta.swapped) + ) + + # Add remaining attributes (those with a contribute_to_class() method) + # to the class. + for obj_name, obj in contributable_attrs.items(): + new_class.add_to_class(obj_name, obj) + + # All the fields of any type declared on this model + new_fields = chain( + new_class._meta.local_fields, + new_class._meta.local_many_to_many, + new_class._meta.private_fields, + ) + field_names = {f.name for f in new_fields} + + # Basic setup for proxy models. + if is_proxy: + base = None + for parent in [kls for kls in parents if hasattr(kls, "_meta")]: + if parent._meta.abstract: + if parent._meta.fields: + raise TypeError( + "Abstract base class containing model fields not " + "permitted for proxy model '%s'." % name + ) + else: + continue + if base is None: + base = parent + elif parent._meta.concrete_model is not base._meta.concrete_model: + raise TypeError( + "Proxy model '%s' has more than one non-abstract model base " + "class." % name + ) + if base is None: + raise TypeError( + "Proxy model '%s' has no non-abstract model base class." % name + ) + new_class._meta.setup_proxy(base) + new_class._meta.concrete_model = base._meta.concrete_model + else: + new_class._meta.concrete_model = new_class + + # Collect the parent links for multi-table inheritance. + parent_links = {} + for base in reversed([new_class] + parents): + # Conceptually equivalent to `if base is Model`. + if not hasattr(base, "_meta"): + continue + # Skip concrete parent classes. + if base != new_class and not base._meta.abstract: + continue + # Locate OneToOneField instances. + for field in base._meta.local_fields: + if isinstance(field, OneToOneField) and field.remote_field.parent_link: + related = resolve_relation(new_class, field.remote_field.model) + parent_links[make_model_tuple(related)] = field + + # Track fields inherited from base models. + inherited_attributes = set() + # Do the appropriate setup for any model parents. + for base in new_class.mro(): + if base not in parents or not hasattr(base, "_meta"): + # Things without _meta aren't functional models, so they're + # uninteresting parents. + inherited_attributes.update(base.__dict__) + continue + + parent_fields = base._meta.local_fields + base._meta.local_many_to_many + if not base._meta.abstract: + # Check for clashes between locally declared fields and those + # on the base classes. + for field in parent_fields: + if field.name in field_names: + raise FieldError( + "Local field %r in class %r clashes with field of " + "the same name from base class %r." + % ( + field.name, + name, + base.__name__, + ) + ) + else: + inherited_attributes.add(field.name) + + # Concrete classes... + base = base._meta.concrete_model + base_key = make_model_tuple(base) + if base_key in parent_links: + field = parent_links[base_key] + elif not is_proxy: + attr_name = "%s_ptr" % base._meta.model_name + field = OneToOneField( + base, + on_delete=CASCADE, + name=attr_name, + auto_created=True, + parent_link=True, + ) + + if attr_name in field_names: + raise FieldError( + "Auto-generated field '%s' in class %r for " + "parent_link to base class %r clashes with " + "declared field of the same name." + % ( + attr_name, + name, + base.__name__, + ) + ) + + # Only add the ptr field if it's not already present; + # e.g. migrations will already have it specified + if not hasattr(new_class, attr_name): + new_class.add_to_class(attr_name, field) + else: + field = None + new_class._meta.parents[base] = field + else: + base_parents = base._meta.parents.copy() + + # Add fields from abstract base class if it wasn't overridden. + for field in parent_fields: + if ( + field.name not in field_names + and field.name not in new_class.__dict__ + and field.name not in inherited_attributes + ): + new_field = copy.deepcopy(field) + new_class.add_to_class(field.name, new_field) + # Replace parent links defined on this base by the new + # field. It will be appropriately resolved if required. + if field.one_to_one: + for parent, parent_link in base_parents.items(): + if field == parent_link: + base_parents[parent] = new_field + + # Pass any non-abstract parent classes onto child. + new_class._meta.parents.update(base_parents) + + # Inherit private fields (like GenericForeignKey) from the parent + # class + for field in base._meta.private_fields: + if field.name in field_names: + if not base._meta.abstract: + raise FieldError( + "Local field %r in class %r clashes with field of " + "the same name from base class %r." + % ( + field.name, + name, + base.__name__, + ) + ) + else: + field = copy.deepcopy(field) + if not base._meta.abstract: + field.mti_inherited = True + new_class.add_to_class(field.name, field) + + # Copy indexes so that index names are unique when models extend an + # abstract model. + new_class._meta.indexes = [ + copy.deepcopy(idx) for idx in new_class._meta.indexes + ] + + if abstract: + # Abstract base models can't be instantiated and don't appear in + # the list of models for an app. We do the final setup for them a + # little differently from normal models. + attr_meta.abstract = False + new_class.Meta = attr_meta + return new_class + + new_class._prepare() + new_class._meta.apps.register_model(new_class._meta.app_label, new_class) + return new_class + + def add_to_class(cls, name, value): + if _has_contribute_to_class(value): + value.contribute_to_class(cls, name) + else: + setattr(cls, name, value) + + def _prepare(cls): + """Create some methods once self._meta has been populated.""" + opts = cls._meta + opts._prepare(cls) + + if opts.order_with_respect_to: + cls.get_next_in_order = partialmethod( + cls._get_next_or_previous_in_order, is_next=True + ) + cls.get_previous_in_order = partialmethod( + cls._get_next_or_previous_in_order, is_next=False + ) + + # Defer creating accessors on the foreign class until it has been + # created and registered. If remote_field is None, we're ordering + # with respect to a GenericForeignKey and don't know what the + # foreign class is - we'll add those accessors later in + # contribute_to_class(). + if opts.order_with_respect_to.remote_field: + wrt = opts.order_with_respect_to + remote = wrt.remote_field.model + lazy_related_operation(make_foreign_order_accessors, cls, remote) + + # Give the class a docstring -- its definition. + if cls.__doc__ is None: + cls.__doc__ = "%s(%s)" % ( + cls.__name__, + ", ".join(f.name for f in opts.fields), + ) + + get_absolute_url_override = settings.ABSOLUTE_URL_OVERRIDES.get( + opts.label_lower + ) + if get_absolute_url_override: + setattr(cls, "get_absolute_url", get_absolute_url_override) + + if not opts.managers: + if any(f.name == "objects" for f in opts.fields): + raise ValueError( + "Model %s must specify a custom Manager, because it has a " + "field named 'objects'." % cls.__name__ + ) + manager = Manager() + manager.auto_created = True + cls.add_to_class("objects", manager) + + # Set the name of _meta.indexes. This can't be done in + # Options.contribute_to_class() because fields haven't been added to + # the model at that point. + for index in cls._meta.indexes: + if not index.name: + index.set_name_with_model(cls) + + class_prepared.send(sender=cls) + + @property + def _base_manager(cls): + return cls._meta.base_manager + + @property + def _default_manager(cls): + return cls._meta.default_manager + + +class ModelStateFieldsCacheDescriptor: + def __get__(self, instance, cls=None): + if instance is None: + return self + res = instance.fields_cache = {} + return res + + +class ModelState: + """Store model instance state.""" + + db = None + # If true, uniqueness validation checks will consider this a new, unsaved + # object. Necessary for correct validation of new instances of objects with + # explicit (non-auto) PKs. This impacts validation only; it has no effect + # on the actual save. + adding = True + fields_cache = ModelStateFieldsCacheDescriptor() + + +class Model(AltersData, metaclass=ModelBase): + def __init__(self, *args, **kwargs): + # Alias some things as locals to avoid repeat global lookups + cls = self.__class__ + opts = self._meta + _setattr = setattr + _DEFERRED = DEFERRED + if opts.abstract: + raise TypeError("Abstract models cannot be instantiated.") + + pre_init.send(sender=cls, args=args, kwargs=kwargs) + + # Set up the storage for instance state + self._state = ModelState() + + # There is a rather weird disparity here; if kwargs, it's set, then args + # overrides it. It should be one or the other; don't duplicate the work + # The reason for the kwargs check is that standard iterator passes in by + # args, and instantiation for iteration is 33% faster. + if len(args) > len(opts.concrete_fields): + # Daft, but matches old exception sans the err msg. + raise IndexError("Number of args exceeds number of fields") + + if not kwargs: + fields_iter = iter(opts.concrete_fields) + # The ordering of the zip calls matter - zip throws StopIteration + # when an iter throws it. So if the first iter throws it, the second + # is *not* consumed. We rely on this, so don't change the order + # without changing the logic. + for val, field in zip(args, fields_iter): + if val is _DEFERRED: + continue + _setattr(self, field.attname, val) + else: + # Slower, kwargs-ready version. + fields_iter = iter(opts.fields) + for val, field in zip(args, fields_iter): + if val is _DEFERRED: + continue + _setattr(self, field.attname, val) + if kwargs.pop(field.name, NOT_PROVIDED) is not NOT_PROVIDED: + raise TypeError( + f"{cls.__qualname__}() got both positional and " + f"keyword arguments for field '{field.name}'." + ) + + # Now we're left with the unprocessed fields that *must* come from + # keywords, or default. + + for field in fields_iter: + is_related_object = False + # Virtual field + if field.attname not in kwargs and field.column is None or field.generated: + continue + if kwargs: + if isinstance(field.remote_field, ForeignObjectRel): + try: + # Assume object instance was passed in. + rel_obj = kwargs.pop(field.name) + is_related_object = True + except KeyError: + try: + # Object instance wasn't passed in -- must be an ID. + val = kwargs.pop(field.attname) + except KeyError: + val = field.get_default() + else: + try: + val = kwargs.pop(field.attname) + except KeyError: + # This is done with an exception rather than the + # default argument on pop because we don't want + # get_default() to be evaluated, and then not used. + # Refs #12057. + val = field.get_default() + else: + val = field.get_default() + + if is_related_object: + # If we are passed a related instance, set it using the + # field.name instead of field.attname (e.g. "user" instead of + # "user_id") so that the object gets properly cached (and type + # checked) by the RelatedObjectDescriptor. + if rel_obj is not _DEFERRED: + _setattr(self, field.name, rel_obj) + else: + if val is not _DEFERRED: + _setattr(self, field.attname, val) + + if kwargs: + property_names = opts._property_names + unexpected = () + for prop, value in kwargs.items(): + # Any remaining kwargs must correspond to properties or virtual + # fields. + if prop in property_names: + if value is not _DEFERRED: + _setattr(self, prop, value) + else: + try: + opts.get_field(prop) + except FieldDoesNotExist: + unexpected += (prop,) + else: + if value is not _DEFERRED: + _setattr(self, prop, value) + if unexpected: + unexpected_names = ", ".join(repr(n) for n in unexpected) + raise TypeError( + f"{cls.__name__}() got unexpected keyword arguments: " + f"{unexpected_names}" + ) + super().__init__() + post_init.send(sender=cls, instance=self) + + @classmethod + def from_db(cls, db, field_names, values): + if len(values) != len(cls._meta.concrete_fields): + values_iter = iter(values) + values = [ + next(values_iter) if f.attname in field_names else DEFERRED + for f in cls._meta.concrete_fields + ] + new = cls(*values) + new._state.adding = False + new._state.db = db + return new + + def __repr__(self): + return "<%s: %s>" % (self.__class__.__name__, self) + + def __str__(self): + return "%s object (%s)" % (self.__class__.__name__, self.pk) + + def __eq__(self, other): + if not isinstance(other, Model): + return NotImplemented + if self._meta.concrete_model != other._meta.concrete_model: + return False + my_pk = self.pk + if my_pk is None: + return self is other + return my_pk == other.pk + + def __hash__(self): + if self.pk is None: + raise TypeError("Model instances without primary key value are unhashable") + return hash(self.pk) + + def __reduce__(self): + data = self.__getstate__() + data[DJANGO_VERSION_PICKLE_KEY] = django.__version__ + class_id = self._meta.app_label, self._meta.object_name + return model_unpickle, (class_id,), data + + def __getstate__(self): + """Hook to allow choosing the attributes to pickle.""" + state = self.__dict__.copy() + state["_state"] = copy.copy(state["_state"]) + state["_state"].fields_cache = state["_state"].fields_cache.copy() + # memoryview cannot be pickled, so cast it to bytes and store + # separately. + _memoryview_attrs = [] + for attr, value in state.items(): + if isinstance(value, memoryview): + _memoryview_attrs.append((attr, bytes(value))) + if _memoryview_attrs: + state["_memoryview_attrs"] = _memoryview_attrs + for attr, value in _memoryview_attrs: + state.pop(attr) + return state + + def __setstate__(self, state): + pickled_version = state.get(DJANGO_VERSION_PICKLE_KEY) + if pickled_version: + if pickled_version != django.__version__: + warnings.warn( + "Pickled model instance's Django version %s does not " + "match the current version %s." + % (pickled_version, django.__version__), + RuntimeWarning, + stacklevel=2, + ) + else: + warnings.warn( + "Pickled model instance's Django version is not specified.", + RuntimeWarning, + stacklevel=2, + ) + if "_memoryview_attrs" in state: + for attr, value in state.pop("_memoryview_attrs"): + state[attr] = memoryview(value) + self.__dict__.update(state) + + def _get_pk_val(self, meta=None): + meta = meta or self._meta + return getattr(self, meta.pk.attname) + + def _set_pk_val(self, value): + for parent_link in self._meta.parents.values(): + if parent_link and parent_link != self._meta.pk: + setattr(self, parent_link.target_field.attname, value) + return setattr(self, self._meta.pk.attname, value) + + pk = property(_get_pk_val, _set_pk_val) + + def get_deferred_fields(self): + """ + Return a set containing names of deferred fields for this instance. + """ + return { + f.attname + for f in self._meta.concrete_fields + if f.attname not in self.__dict__ + } + + def refresh_from_db(self, using=None, fields=None): + """ + Reload field values from the database. + + By default, the reloading happens from the database this instance was + loaded from, or by the read router if this instance wasn't loaded from + any database. The using parameter will override the default. + + Fields can be used to specify which fields to reload. The fields + should be an iterable of field attnames. If fields is None, then + all non-deferred fields are reloaded. + + When accessing deferred fields of an instance, the deferred loading + of the field will call this method. + """ + if fields is None: + self._prefetched_objects_cache = {} + else: + prefetched_objects_cache = getattr(self, "_prefetched_objects_cache", ()) + for field in fields: + if field in prefetched_objects_cache: + del prefetched_objects_cache[field] + fields.remove(field) + if not fields: + return + if any(LOOKUP_SEP in f for f in fields): + raise ValueError( + 'Found "%s" in fields argument. Relations and transforms ' + "are not allowed in fields." % LOOKUP_SEP + ) + + hints = {"instance": self} + db_instance_qs = self.__class__._base_manager.db_manager( + using, hints=hints + ).filter(pk=self.pk) + + # Use provided fields, if not set then reload all non-deferred fields. + deferred_fields = self.get_deferred_fields() + if fields is not None: + fields = list(fields) + db_instance_qs = db_instance_qs.only(*fields) + elif deferred_fields: + fields = [ + f.attname + for f in self._meta.concrete_fields + if f.attname not in deferred_fields + ] + db_instance_qs = db_instance_qs.only(*fields) + + db_instance = db_instance_qs.get() + non_loaded_fields = db_instance.get_deferred_fields() + for field in self._meta.concrete_fields: + if field.attname in non_loaded_fields: + # This field wasn't refreshed - skip ahead. + continue + setattr(self, field.attname, getattr(db_instance, field.attname)) + # Clear cached foreign keys. + if field.is_relation and field.is_cached(self): + field.delete_cached_value(self) + + # Clear cached relations. + for field in self._meta.related_objects: + if field.is_cached(self): + field.delete_cached_value(self) + + # Clear cached private relations. + for field in self._meta.private_fields: + if field.is_relation and field.is_cached(self): + field.delete_cached_value(self) + + self._state.db = db_instance._state.db + + async def arefresh_from_db(self, using=None, fields=None): + return await sync_to_async(self.refresh_from_db)(using=using, fields=fields) + + def serializable_value(self, field_name): + """ + Return the value of the field name for this instance. If the field is + a foreign key, return the id value instead of the object. If there's + no Field object with this name on the model, return the model + attribute's value. + + Used to serialize a field's value (in the serializer, or form output, + for example). Normally, you would just access the attribute directly + and not use this method. + """ + try: + field = self._meta.get_field(field_name) + except FieldDoesNotExist: + return getattr(self, field_name) + return getattr(self, field.attname) + + def save( + self, force_insert=False, force_update=False, using=None, update_fields=None + ): + """ + Save the current instance. Override this in a subclass if you want to + control the saving process. + + The 'force_insert' and 'force_update' parameters can be used to insist + that the "save" must be an SQL insert or update (or equivalent for + non-SQL backends), respectively. Normally, they should not be set. + """ + self._prepare_related_fields_for_save(operation_name="save") + + using = using or router.db_for_write(self.__class__, instance=self) + if force_insert and (force_update or update_fields): + raise ValueError("Cannot force both insert and updating in model saving.") + + deferred_fields = self.get_deferred_fields() + if update_fields is not None: + # If update_fields is empty, skip the save. We do also check for + # no-op saves later on for inheritance cases. This bailout is + # still needed for skipping signal sending. + if not update_fields: + return + + update_fields = frozenset(update_fields) + field_names = self._meta._non_pk_concrete_field_names + non_model_fields = update_fields.difference(field_names) + + if non_model_fields: + raise ValueError( + "The following fields do not exist in this model, are m2m " + "fields, or are non-concrete fields: %s" + % ", ".join(non_model_fields) + ) + + # If saving to the same database, and this model is deferred, then + # automatically do an "update_fields" save on the loaded fields. + elif not force_insert and deferred_fields and using == self._state.db: + field_names = set() + for field in self._meta.concrete_fields: + if not field.primary_key and not hasattr(field, "through"): + field_names.add(field.attname) + loaded_fields = field_names.difference(deferred_fields) + if loaded_fields: + update_fields = frozenset(loaded_fields) + + self.save_base( + using=using, + force_insert=force_insert, + force_update=force_update, + update_fields=update_fields, + ) + + save.alters_data = True + + async def asave( + self, force_insert=False, force_update=False, using=None, update_fields=None + ): + return await sync_to_async(self.save)( + force_insert=force_insert, + force_update=force_update, + using=using, + update_fields=update_fields, + ) + + asave.alters_data = True + + @classmethod + def _validate_force_insert(cls, force_insert): + if force_insert is False: + return () + if force_insert is True: + return (cls,) + if not isinstance(force_insert, tuple): + raise TypeError("force_insert must be a bool or tuple.") + for member in force_insert: + if not isinstance(member, ModelBase): + raise TypeError( + f"Invalid force_insert member. {member!r} must be a model subclass." + ) + if not issubclass(cls, member): + raise TypeError( + f"Invalid force_insert member. {member.__qualname__} must be a " + f"base of {cls.__qualname__}." + ) + return force_insert + + def save_base( + self, + raw=False, + force_insert=False, + force_update=False, + using=None, + update_fields=None, + ): + """ + Handle the parts of saving which should be done only once per save, + yet need to be done in raw saves, too. This includes some sanity + checks and signal sending. + + The 'raw' argument is telling save_base not to save any parent + models and not to do any changes to the values before save. This + is used by fixture loading. + """ + using = using or router.db_for_write(self.__class__, instance=self) + assert not (force_insert and (force_update or update_fields)) + assert update_fields is None or update_fields + cls = origin = self.__class__ + # Skip proxies, but keep the origin as the proxy model. + if cls._meta.proxy: + cls = cls._meta.concrete_model + meta = cls._meta + if not meta.auto_created: + pre_save.send( + sender=origin, + instance=self, + raw=raw, + using=using, + update_fields=update_fields, + ) + # A transaction isn't needed if one query is issued. + if meta.parents: + context_manager = transaction.atomic(using=using, savepoint=False) + else: + context_manager = transaction.mark_for_rollback_on_error(using=using) + with context_manager: + parent_inserted = False + if not raw: + # Validate force insert only when parents are inserted. + force_insert = self._validate_force_insert(force_insert) + parent_inserted = self._save_parents( + cls, using, update_fields, force_insert + ) + updated = self._save_table( + raw, + cls, + force_insert or parent_inserted, + force_update, + using, + update_fields, + ) + # Store the database on which the object was saved + self._state.db = using + # Once saved, this is no longer a to-be-added instance. + self._state.adding = False + + # Signal that the save is complete + if not meta.auto_created: + post_save.send( + sender=origin, + instance=self, + created=(not updated), + update_fields=update_fields, + raw=raw, + using=using, + ) + + save_base.alters_data = True + + def _save_parents( + self, cls, using, update_fields, force_insert, updated_parents=None + ): + """Save all the parents of cls using values from self.""" + meta = cls._meta + inserted = False + if updated_parents is None: + updated_parents = {} + for parent, field in meta.parents.items(): + # Make sure the link fields are synced between parent and self. + if ( + field + and getattr(self, parent._meta.pk.attname) is None + and getattr(self, field.attname) is not None + ): + setattr(self, parent._meta.pk.attname, getattr(self, field.attname)) + if (parent_updated := updated_parents.get(parent)) is None: + parent_inserted = self._save_parents( + cls=parent, + using=using, + update_fields=update_fields, + force_insert=force_insert, + updated_parents=updated_parents, + ) + updated = self._save_table( + cls=parent, + using=using, + update_fields=update_fields, + force_insert=parent_inserted or issubclass(parent, force_insert), + ) + if not updated: + inserted = True + updated_parents[parent] = updated + elif not parent_updated: + inserted = True + # Set the parent's PK value to self. + if field: + setattr(self, field.attname, self._get_pk_val(parent._meta)) + # Since we didn't have an instance of the parent handy set + # attname directly, bypassing the descriptor. Invalidate + # the related object cache, in case it's been accidentally + # populated. A fresh instance will be re-built from the + # database if necessary. + if field.is_cached(self): + field.delete_cached_value(self) + return inserted + + def _save_table( + self, + raw=False, + cls=None, + force_insert=False, + force_update=False, + using=None, + update_fields=None, + ): + """ + Do the heavy-lifting involved in saving. Update or insert the data + for a single table. + """ + meta = cls._meta + non_pks = [f for f in meta.local_concrete_fields if not f.primary_key] + + if update_fields: + non_pks = [ + f + for f in non_pks + if f.name in update_fields or f.attname in update_fields + ] + + pk_val = self._get_pk_val(meta) + if pk_val is None: + pk_val = meta.pk.get_pk_value_on_save(self) + setattr(self, meta.pk.attname, pk_val) + pk_set = pk_val is not None + if not pk_set and (force_update or update_fields): + raise ValueError("Cannot force an update in save() with no primary key.") + updated = False + # Skip an UPDATE when adding an instance and primary key has a default. + if ( + not raw + and not force_insert + and self._state.adding + and ( + (meta.pk.default and meta.pk.default is not NOT_PROVIDED) + or (meta.pk.db_default and meta.pk.db_default is not NOT_PROVIDED) + ) + ): + force_insert = True + # If possible, try an UPDATE. If that doesn't update anything, do an INSERT. + if pk_set and not force_insert: + base_qs = cls._base_manager.using(using) + values = [ + ( + f, + None, + (getattr(self, f.attname) if raw else f.pre_save(self, False)), + ) + for f in non_pks + ] + forced_update = update_fields or force_update + updated = self._do_update( + base_qs, using, pk_val, values, update_fields, forced_update + ) + if force_update and not updated: + raise DatabaseError("Forced update did not affect any rows.") + if update_fields and not updated: + raise DatabaseError("Save with update_fields did not affect any rows.") + if not updated: + if meta.order_with_respect_to: + # If this is a model with an order_with_respect_to + # autopopulate the _order field + field = meta.order_with_respect_to + filter_args = field.get_filter_kwargs_for_object(self) + self._order = ( + cls._base_manager.using(using) + .filter(**filter_args) + .aggregate( + _order__max=Coalesce( + ExpressionWrapper( + Max("_order") + Value(1), output_field=IntegerField() + ), + Value(0), + ), + )["_order__max"] + ) + fields = [ + f + for f in meta.local_concrete_fields + if not f.generated and (pk_set or f is not meta.auto_field) + ] + returning_fields = meta.db_returning_fields + results = self._do_insert( + cls._base_manager, using, fields, returning_fields, raw + ) + if results: + for value, field in zip(results[0], returning_fields): + setattr(self, field.attname, value) + return updated + + def _do_update(self, base_qs, using, pk_val, values, update_fields, forced_update): + """ + Try to update the model. Return True if the model was updated (if an + update query was done and a matching row was found in the DB). + """ + filtered = base_qs.filter(pk=pk_val) + if not values: + # We can end up here when saving a model in inheritance chain where + # update_fields doesn't target any field in current model. In that + # case we just say the update succeeded. Another case ending up here + # is a model with just PK - in that case check that the PK still + # exists. + return update_fields is not None or filtered.exists() + if self._meta.select_on_save and not forced_update: + return ( + filtered.exists() + and + # It may happen that the object is deleted from the DB right after + # this check, causing the subsequent UPDATE to return zero matching + # rows. The same result can occur in some rare cases when the + # database returns zero despite the UPDATE being executed + # successfully (a row is matched and updated). In order to + # distinguish these two cases, the object's existence in the + # database is again checked for if the UPDATE query returns 0. + (filtered._update(values) > 0 or filtered.exists()) + ) + return filtered._update(values) > 0 + + def _do_insert(self, manager, using, fields, returning_fields, raw): + """ + Do an INSERT. If returning_fields is defined then this method should + return the newly created data for the model. + """ + return manager._insert( + [self], + fields=fields, + returning_fields=returning_fields, + using=using, + raw=raw, + ) + + def _prepare_related_fields_for_save(self, operation_name, fields=None): + # Ensure that a model instance without a PK hasn't been assigned to + # a ForeignKey, GenericForeignKey or OneToOneField on this model. If + # the field is nullable, allowing the save would result in silent data + # loss. + for field in self._meta.concrete_fields: + if fields and field not in fields: + continue + # If the related field isn't cached, then an instance hasn't been + # assigned and there's no need to worry about this check. + if field.is_relation and field.is_cached(self): + obj = getattr(self, field.name, None) + if not obj: + continue + # A pk may have been assigned manually to a model instance not + # saved to the database (or auto-generated in a case like + # UUIDField), but we allow the save to proceed and rely on the + # database to raise an IntegrityError if applicable. If + # constraints aren't supported by the database, there's the + # unavoidable risk of data corruption. + if obj.pk is None: + # Remove the object from a related instance cache. + if not field.remote_field.multiple: + field.remote_field.delete_cached_value(obj) + raise ValueError( + "%s() prohibited to prevent data loss due to unsaved " + "related object '%s'." % (operation_name, field.name) + ) + elif getattr(self, field.attname) in field.empty_values: + # Set related object if it has been saved after an + # assignment. + setattr(self, field.name, obj) + # If the relationship's pk/to_field was changed, clear the + # cached relationship. + if getattr(obj, field.target_field.attname) != getattr( + self, field.attname + ): + field.delete_cached_value(self) + # GenericForeignKeys are private. + for field in self._meta.private_fields: + if fields and field not in fields: + continue + if ( + field.is_relation + and field.is_cached(self) + and hasattr(field, "fk_field") + ): + obj = field.get_cached_value(self, default=None) + if obj and obj.pk is None: + raise ValueError( + f"{operation_name}() prohibited to prevent data loss due to " + f"unsaved related object '{field.name}'." + ) + + def delete(self, using=None, keep_parents=False): + if self.pk is None: + raise ValueError( + "%s object can't be deleted because its %s attribute is set " + "to None." % (self._meta.object_name, self._meta.pk.attname) + ) + using = using or router.db_for_write(self.__class__, instance=self) + collector = Collector(using=using, origin=self) + collector.collect([self], keep_parents=keep_parents) + return collector.delete() + + delete.alters_data = True + + async def adelete(self, using=None, keep_parents=False): + return await sync_to_async(self.delete)( + using=using, + keep_parents=keep_parents, + ) + + adelete.alters_data = True + + def _get_FIELD_display(self, field): + value = getattr(self, field.attname) + choices_dict = dict(make_hashable(field.flatchoices)) + # force_str() to coerce lazy strings. + return force_str( + choices_dict.get(make_hashable(value), value), strings_only=True + ) + + def _get_next_or_previous_by_FIELD(self, field, is_next, **kwargs): + if not self.pk: + raise ValueError("get_next/get_previous cannot be used on unsaved objects.") + op = "gt" if is_next else "lt" + order = "" if is_next else "-" + param = getattr(self, field.attname) + q = Q.create([(field.name, param), (f"pk__{op}", self.pk)], connector=Q.AND) + q = Q.create([q, (f"{field.name}__{op}", param)], connector=Q.OR) + qs = ( + self.__class__._default_manager.using(self._state.db) + .filter(**kwargs) + .filter(q) + .order_by("%s%s" % (order, field.name), "%spk" % order) + ) + try: + return qs[0] + except IndexError: + raise self.DoesNotExist( + "%s matching query does not exist." % self.__class__._meta.object_name + ) + + def _get_next_or_previous_in_order(self, is_next): + cachename = "__%s_order_cache" % is_next + if not hasattr(self, cachename): + op = "gt" if is_next else "lt" + order = "_order" if is_next else "-_order" + order_field = self._meta.order_with_respect_to + filter_args = order_field.get_filter_kwargs_for_object(self) + obj = ( + self.__class__._default_manager.filter(**filter_args) + .filter( + **{ + "_order__%s" + % op: self.__class__._default_manager.values("_order").filter( + **{self._meta.pk.name: self.pk} + ) + } + ) + .order_by(order)[:1] + .get() + ) + setattr(self, cachename, obj) + return getattr(self, cachename) + + def _get_field_value_map(self, meta, exclude=None): + if exclude is None: + exclude = set() + meta = meta or self._meta + field_map = { + field.name: Value(getattr(self, field.attname), field) + for field in meta.local_concrete_fields + if field.name not in exclude + } + if "pk" not in exclude: + field_map["pk"] = Value(self.pk, meta.pk) + return field_map + + def prepare_database_save(self, field): + if self.pk is None: + raise ValueError( + "Unsaved model instance %r cannot be used in an ORM query." % self + ) + return getattr(self, field.remote_field.get_related_field().attname) + + def clean(self): + """ + Hook for doing any extra model-wide validation after clean() has been + called on every field by self.clean_fields. Any ValidationError raised + by this method will not be associated with a particular field; it will + have a special-case association with the field defined by NON_FIELD_ERRORS. + """ + pass + + def validate_unique(self, exclude=None): + """ + Check unique constraints on the model and raise ValidationError if any + failed. + """ + unique_checks, date_checks = self._get_unique_checks(exclude=exclude) + + errors = self._perform_unique_checks(unique_checks) + date_errors = self._perform_date_checks(date_checks) + + for k, v in date_errors.items(): + errors.setdefault(k, []).extend(v) + + if errors: + raise ValidationError(errors) + + def _get_unique_checks(self, exclude=None, include_meta_constraints=False): + """ + Return a list of checks to perform. Since validate_unique() could be + called from a ModelForm, some fields may have been excluded; we can't + perform a unique check on a model that is missing fields involved + in that check. Fields that did not validate should also be excluded, + but they need to be passed in via the exclude argument. + """ + if exclude is None: + exclude = set() + unique_checks = [] + + unique_togethers = [(self.__class__, self._meta.unique_together)] + constraints = [] + if include_meta_constraints: + constraints = [(self.__class__, self._meta.total_unique_constraints)] + for parent_class in self._meta.get_parent_list(): + if parent_class._meta.unique_together: + unique_togethers.append( + (parent_class, parent_class._meta.unique_together) + ) + if include_meta_constraints and parent_class._meta.total_unique_constraints: + constraints.append( + (parent_class, parent_class._meta.total_unique_constraints) + ) + + for model_class, unique_together in unique_togethers: + for check in unique_together: + if not any(name in exclude for name in check): + # Add the check if the field isn't excluded. + unique_checks.append((model_class, tuple(check))) + + if include_meta_constraints: + for model_class, model_constraints in constraints: + for constraint in model_constraints: + if not any(name in exclude for name in constraint.fields): + unique_checks.append((model_class, constraint.fields)) + + # These are checks for the unique_for_. + date_checks = [] + + # Gather a list of checks for fields declared as unique and add them to + # the list of checks. + + fields_with_class = [(self.__class__, self._meta.local_fields)] + for parent_class in self._meta.get_parent_list(): + fields_with_class.append((parent_class, parent_class._meta.local_fields)) + + for model_class, fields in fields_with_class: + for f in fields: + name = f.name + if name in exclude: + continue + if f.unique: + unique_checks.append((model_class, (name,))) + if f.unique_for_date and f.unique_for_date not in exclude: + date_checks.append((model_class, "date", name, f.unique_for_date)) + if f.unique_for_year and f.unique_for_year not in exclude: + date_checks.append((model_class, "year", name, f.unique_for_year)) + if f.unique_for_month and f.unique_for_month not in exclude: + date_checks.append((model_class, "month", name, f.unique_for_month)) + return unique_checks, date_checks + + def _perform_unique_checks(self, unique_checks): + errors = {} + + for model_class, unique_check in unique_checks: + # Try to look up an existing object with the same values as this + # object's values for all the unique field. + + lookup_kwargs = {} + for field_name in unique_check: + f = self._meta.get_field(field_name) + lookup_value = getattr(self, f.attname) + # TODO: Handle multiple backends with different feature flags. + if lookup_value is None or ( + lookup_value == "" + and connection.features.interprets_empty_strings_as_nulls + ): + # no value, skip the lookup + continue + if f.primary_key and not self._state.adding: + # no need to check for unique primary key when editing + continue + lookup_kwargs[str(field_name)] = lookup_value + + # some fields were skipped, no reason to do the check + if len(unique_check) != len(lookup_kwargs): + continue + + qs = model_class._default_manager.filter(**lookup_kwargs) + + # Exclude the current object from the query if we are editing an + # instance (as opposed to creating a new one) + # Note that we need to use the pk as defined by model_class, not + # self.pk. These can be different fields because model inheritance + # allows single model to have effectively multiple primary keys. + # Refs #17615. + model_class_pk = self._get_pk_val(model_class._meta) + if not self._state.adding and model_class_pk is not None: + qs = qs.exclude(pk=model_class_pk) + if qs.exists(): + if len(unique_check) == 1: + key = unique_check[0] + else: + key = NON_FIELD_ERRORS + errors.setdefault(key, []).append( + self.unique_error_message(model_class, unique_check) + ) + + return errors + + def _perform_date_checks(self, date_checks): + errors = {} + for model_class, lookup_type, field, unique_for in date_checks: + lookup_kwargs = {} + # there's a ticket to add a date lookup, we can remove this special + # case if that makes it's way in + date = getattr(self, unique_for) + if date is None: + continue + if lookup_type == "date": + lookup_kwargs["%s__day" % unique_for] = date.day + lookup_kwargs["%s__month" % unique_for] = date.month + lookup_kwargs["%s__year" % unique_for] = date.year + else: + lookup_kwargs["%s__%s" % (unique_for, lookup_type)] = getattr( + date, lookup_type + ) + lookup_kwargs[field] = getattr(self, field) + + qs = model_class._default_manager.filter(**lookup_kwargs) + # Exclude the current object from the query if we are editing an + # instance (as opposed to creating a new one) + if not self._state.adding and self.pk is not None: + qs = qs.exclude(pk=self.pk) + + if qs.exists(): + errors.setdefault(field, []).append( + self.date_error_message(lookup_type, field, unique_for) + ) + return errors + + def date_error_message(self, lookup_type, field_name, unique_for): + opts = self._meta + field = opts.get_field(field_name) + return ValidationError( + message=field.error_messages["unique_for_date"], + code="unique_for_date", + params={ + "model": self, + "model_name": capfirst(opts.verbose_name), + "lookup_type": lookup_type, + "field": field_name, + "field_label": capfirst(field.verbose_name), + "date_field": unique_for, + "date_field_label": capfirst(opts.get_field(unique_for).verbose_name), + }, + ) + + def unique_error_message(self, model_class, unique_check): + opts = model_class._meta + + params = { + "model": self, + "model_class": model_class, + "model_name": capfirst(opts.verbose_name), + "unique_check": unique_check, + } + + # A unique field + if len(unique_check) == 1: + field = opts.get_field(unique_check[0]) + params["field_label"] = capfirst(field.verbose_name) + return ValidationError( + message=field.error_messages["unique"], + code="unique", + params=params, + ) + + # unique_together + else: + field_labels = [ + capfirst(opts.get_field(f).verbose_name) for f in unique_check + ] + params["field_labels"] = get_text_list(field_labels, _("and")) + return ValidationError( + message=_("%(model_name)s with this %(field_labels)s already exists."), + code="unique_together", + params=params, + ) + + def get_constraints(self): + constraints = [(self.__class__, self._meta.constraints)] + for parent_class in self._meta.get_parent_list(): + if parent_class._meta.constraints: + constraints.append((parent_class, parent_class._meta.constraints)) + return constraints + + def validate_constraints(self, exclude=None): + constraints = self.get_constraints() + using = router.db_for_write(self.__class__, instance=self) + + errors = {} + for model_class, model_constraints in constraints: + for constraint in model_constraints: + try: + constraint.validate(model_class, self, exclude=exclude, using=using) + except ValidationError as e: + if ( + getattr(e, "code", None) == "unique" + and len(constraint.fields) == 1 + ): + errors.setdefault(constraint.fields[0], []).append(e) + else: + errors = e.update_error_dict(errors) + if errors: + raise ValidationError(errors) + + def full_clean(self, exclude=None, validate_unique=True, validate_constraints=True): + """ + Call clean_fields(), clean(), validate_unique(), and + validate_constraints() on the model. Raise a ValidationError for any + errors that occur. + """ + errors = {} + if exclude is None: + exclude = set() + else: + exclude = set(exclude) + + try: + self.clean_fields(exclude=exclude) + except ValidationError as e: + errors = e.update_error_dict(errors) + + # Form.clean() is run even if other validation fails, so do the + # same with Model.clean() for consistency. + try: + self.clean() + except ValidationError as e: + errors = e.update_error_dict(errors) + + # Run unique checks, but only for fields that passed validation. + if validate_unique: + for name in errors: + if name != NON_FIELD_ERRORS and name not in exclude: + exclude.add(name) + try: + self.validate_unique(exclude=exclude) + except ValidationError as e: + errors = e.update_error_dict(errors) + + # Run constraints checks, but only for fields that passed validation. + if validate_constraints: + for name in errors: + if name != NON_FIELD_ERRORS and name not in exclude: + exclude.add(name) + try: + self.validate_constraints(exclude=exclude) + except ValidationError as e: + errors = e.update_error_dict(errors) + + if errors: + raise ValidationError(errors) + + def clean_fields(self, exclude=None): + """ + Clean all fields and raise a ValidationError containing a dict + of all validation errors if any occur. + """ + if exclude is None: + exclude = set() + + errors = {} + for f in self._meta.fields: + if f.name in exclude: + continue + # Skip validation for empty fields with blank=True. The developer + # is responsible for making sure they have a valid value. + raw_value = getattr(self, f.attname) + if f.blank and raw_value in f.empty_values: + continue + try: + setattr(self, f.attname, f.clean(raw_value, self)) + except ValidationError as e: + errors[f.name] = e.error_list + + if errors: + raise ValidationError(errors) + + @classmethod + def check(cls, **kwargs): + errors = [ + *cls._check_swappable(), + *cls._check_model(), + *cls._check_managers(**kwargs), + ] + if not cls._meta.swapped: + databases = kwargs.get("databases") or [] + errors += [ + *cls._check_fields(**kwargs), + *cls._check_m2m_through_same_relationship(), + *cls._check_long_column_names(databases), + ] + clash_errors = ( + *cls._check_id_field(), + *cls._check_field_name_clashes(), + *cls._check_model_name_db_lookup_clashes(), + *cls._check_property_name_related_field_accessor_clashes(), + *cls._check_single_primary_key(), + ) + errors.extend(clash_errors) + # If there are field name clashes, hide consequent column name + # clashes. + if not clash_errors: + errors.extend(cls._check_column_name_clashes()) + errors += [ + *cls._check_index_together(), + *cls._check_unique_together(), + *cls._check_indexes(databases), + *cls._check_ordering(), + *cls._check_constraints(databases), + *cls._check_default_pk(), + *cls._check_db_table_comment(databases), + ] + + return errors + + @classmethod + def _check_default_pk(cls): + if ( + not cls._meta.abstract + and cls._meta.pk.auto_created + and + # Inherited PKs are checked in parents models. + not ( + isinstance(cls._meta.pk, OneToOneField) + and cls._meta.pk.remote_field.parent_link + ) + and not settings.is_overridden("DEFAULT_AUTO_FIELD") + and cls._meta.app_config + and not cls._meta.app_config._is_default_auto_field_overridden + ): + return [ + checks.Warning( + f"Auto-created primary key used when not defining a " + f"primary key type, by default " + f"'{settings.DEFAULT_AUTO_FIELD}'.", + hint=( + f"Configure the DEFAULT_AUTO_FIELD setting or the " + f"{cls._meta.app_config.__class__.__qualname__}." + f"default_auto_field attribute to point to a subclass " + f"of AutoField, e.g. 'django.db.models.BigAutoField'." + ), + obj=cls, + id="models.W042", + ), + ] + return [] + + @classmethod + def _check_db_table_comment(cls, databases): + if not cls._meta.db_table_comment: + return [] + errors = [] + for db in databases: + if not router.allow_migrate_model(db, cls): + continue + connection = connections[db] + if not ( + connection.features.supports_comments + or "supports_comments" in cls._meta.required_db_features + ): + errors.append( + checks.Warning( + f"{connection.display_name} does not support comments on " + f"tables (db_table_comment).", + obj=cls, + id="models.W046", + ) + ) + return errors + + @classmethod + def _check_swappable(cls): + """Check if the swapped model exists.""" + errors = [] + if cls._meta.swapped: + try: + apps.get_model(cls._meta.swapped) + except ValueError: + errors.append( + checks.Error( + "'%s' is not of the form 'app_label.app_name'." + % cls._meta.swappable, + id="models.E001", + ) + ) + except LookupError: + app_label, model_name = cls._meta.swapped.split(".") + errors.append( + checks.Error( + "'%s' references '%s.%s', which has not been " + "installed, or is abstract." + % (cls._meta.swappable, app_label, model_name), + id="models.E002", + ) + ) + return errors + + @classmethod + def _check_model(cls): + errors = [] + if cls._meta.proxy: + if cls._meta.local_fields or cls._meta.local_many_to_many: + errors.append( + checks.Error( + "Proxy model '%s' contains model fields." % cls.__name__, + id="models.E017", + ) + ) + return errors + + @classmethod + def _check_managers(cls, **kwargs): + """Perform all manager checks.""" + errors = [] + for manager in cls._meta.managers: + errors.extend(manager.check(**kwargs)) + return errors + + @classmethod + def _check_fields(cls, **kwargs): + """Perform all field checks.""" + errors = [] + for field in cls._meta.local_fields: + errors.extend(field.check(**kwargs)) + for field in cls._meta.local_many_to_many: + errors.extend(field.check(from_model=cls, **kwargs)) + return errors + + @classmethod + def _check_m2m_through_same_relationship(cls): + """Check if no relationship model is used by more than one m2m field.""" + + errors = [] + seen_intermediary_signatures = [] + + fields = cls._meta.local_many_to_many + + # Skip when the target model wasn't found. + fields = (f for f in fields if isinstance(f.remote_field.model, ModelBase)) + + # Skip when the relationship model wasn't found. + fields = (f for f in fields if isinstance(f.remote_field.through, ModelBase)) + + for f in fields: + signature = ( + f.remote_field.model, + cls, + f.remote_field.through, + f.remote_field.through_fields, + ) + if signature in seen_intermediary_signatures: + errors.append( + checks.Error( + "The model has two identical many-to-many relations " + "through the intermediate model '%s'." + % f.remote_field.through._meta.label, + obj=cls, + id="models.E003", + ) + ) + else: + seen_intermediary_signatures.append(signature) + return errors + + @classmethod + def _check_id_field(cls): + """Check if `id` field is a primary key.""" + fields = [ + f for f in cls._meta.local_fields if f.name == "id" and f != cls._meta.pk + ] + # fields is empty or consists of the invalid "id" field + if fields and not fields[0].primary_key and cls._meta.pk.name == "id": + return [ + checks.Error( + "'id' can only be used as a field name if the field also " + "sets 'primary_key=True'.", + obj=cls, + id="models.E004", + ) + ] + else: + return [] + + @classmethod + def _check_field_name_clashes(cls): + """Forbid field shadowing in multi-table inheritance.""" + errors = [] + used_fields = {} # name or attname -> field + + # Check that multi-inheritance doesn't cause field name shadowing. + for parent in cls._meta.get_parent_list(): + for f in parent._meta.local_fields: + clash = used_fields.get(f.name) or used_fields.get(f.attname) or None + if clash: + errors.append( + checks.Error( + "The field '%s' from parent model " + "'%s' clashes with the field '%s' " + "from parent model '%s'." + % (clash.name, clash.model._meta, f.name, f.model._meta), + obj=cls, + id="models.E005", + ) + ) + used_fields[f.name] = f + used_fields[f.attname] = f + + # Check that fields defined in the model don't clash with fields from + # parents, including auto-generated fields like multi-table inheritance + # child accessors. + for parent in cls._meta.get_parent_list(): + for f in parent._meta.get_fields(): + if f not in used_fields: + used_fields[f.name] = f + + # Check that parent links in diamond-shaped MTI models don't clash. + for parent_link in cls._meta.parents.values(): + if not parent_link: + continue + clash = used_fields.get(parent_link.name) or None + if clash: + errors.append( + checks.Error( + f"The field '{parent_link.name}' clashes with the field " + f"'{clash.name}' from model '{clash.model._meta}'.", + obj=cls, + id="models.E006", + ) + ) + + for f in cls._meta.local_fields: + clash = used_fields.get(f.name) or used_fields.get(f.attname) or None + # Note that we may detect clash between user-defined non-unique + # field "id" and automatically added unique field "id", both + # defined at the same model. This special case is considered in + # _check_id_field and here we ignore it. + id_conflict = ( + f.name == "id" and clash and clash.name == "id" and clash.model == cls + ) + if clash and not id_conflict: + errors.append( + checks.Error( + "The field '%s' clashes with the field '%s' " + "from model '%s'." % (f.name, clash.name, clash.model._meta), + obj=f, + id="models.E006", + ) + ) + used_fields[f.name] = f + used_fields[f.attname] = f + + return errors + + @classmethod + def _check_column_name_clashes(cls): + # Store a list of column names which have already been used by other fields. + used_column_names = [] + errors = [] + + for f in cls._meta.local_fields: + _, column_name = f.get_attname_column() + + # Ensure the column name is not already in use. + if column_name and column_name in used_column_names: + errors.append( + checks.Error( + "Field '%s' has column name '%s' that is used by " + "another field." % (f.name, column_name), + hint="Specify a 'db_column' for the field.", + obj=cls, + id="models.E007", + ) + ) + else: + used_column_names.append(column_name) + + return errors + + @classmethod + def _check_model_name_db_lookup_clashes(cls): + errors = [] + model_name = cls.__name__ + if model_name.startswith("_") or model_name.endswith("_"): + errors.append( + checks.Error( + "The model name '%s' cannot start or end with an underscore " + "as it collides with the query lookup syntax." % model_name, + obj=cls, + id="models.E023", + ) + ) + elif LOOKUP_SEP in model_name: + errors.append( + checks.Error( + "The model name '%s' cannot contain double underscores as " + "it collides with the query lookup syntax." % model_name, + obj=cls, + id="models.E024", + ) + ) + return errors + + @classmethod + def _check_property_name_related_field_accessor_clashes(cls): + errors = [] + property_names = cls._meta._property_names + related_field_accessors = ( + f.get_attname() + for f in cls._meta._get_fields(reverse=False) + if f.is_relation and f.related_model is not None + ) + for accessor in related_field_accessors: + if accessor in property_names: + errors.append( + checks.Error( + "The property '%s' clashes with a related field " + "accessor." % accessor, + obj=cls, + id="models.E025", + ) + ) + return errors + + @classmethod + def _check_single_primary_key(cls): + errors = [] + if sum(1 for f in cls._meta.local_fields if f.primary_key) > 1: + errors.append( + checks.Error( + "The model cannot have more than one field with " + "'primary_key=True'.", + obj=cls, + id="models.E026", + ) + ) + return errors + + # RemovedInDjango51Warning. + @classmethod + def _check_index_together(cls): + """Check the value of "index_together" option.""" + if not isinstance(cls._meta.index_together, (tuple, list)): + return [ + checks.Error( + "'index_together' must be a list or tuple.", + obj=cls, + id="models.E008", + ) + ] + + elif any( + not isinstance(fields, (tuple, list)) for fields in cls._meta.index_together + ): + return [ + checks.Error( + "All 'index_together' elements must be lists or tuples.", + obj=cls, + id="models.E009", + ) + ] + + else: + errors = [] + for fields in cls._meta.index_together: + errors.extend(cls._check_local_fields(fields, "index_together")) + return errors + + @classmethod + def _check_unique_together(cls): + """Check the value of "unique_together" option.""" + if not isinstance(cls._meta.unique_together, (tuple, list)): + return [ + checks.Error( + "'unique_together' must be a list or tuple.", + obj=cls, + id="models.E010", + ) + ] + + elif any( + not isinstance(fields, (tuple, list)) + for fields in cls._meta.unique_together + ): + return [ + checks.Error( + "All 'unique_together' elements must be lists or tuples.", + obj=cls, + id="models.E011", + ) + ] + + else: + errors = [] + for fields in cls._meta.unique_together: + errors.extend(cls._check_local_fields(fields, "unique_together")) + return errors + + @classmethod + def _check_indexes(cls, databases): + """Check fields, names, and conditions of indexes.""" + errors = [] + references = set() + for index in cls._meta.indexes: + # Index name can't start with an underscore or a number, restricted + # for cross-database compatibility with Oracle. + if index.name[0] == "_" or index.name[0].isdigit(): + errors.append( + checks.Error( + "The index name '%s' cannot start with an underscore " + "or a number." % index.name, + obj=cls, + id="models.E033", + ), + ) + if len(index.name) > index.max_name_length: + errors.append( + checks.Error( + "The index name '%s' cannot be longer than %d " + "characters." % (index.name, index.max_name_length), + obj=cls, + id="models.E034", + ), + ) + if index.contains_expressions: + for expression in index.expressions: + references.update( + ref[0] for ref in cls._get_expr_references(expression) + ) + for db in databases: + if not router.allow_migrate_model(db, cls): + continue + connection = connections[db] + if not ( + connection.features.supports_partial_indexes + or "supports_partial_indexes" in cls._meta.required_db_features + ) and any(index.condition is not None for index in cls._meta.indexes): + errors.append( + checks.Warning( + "%s does not support indexes with conditions." + % connection.display_name, + hint=( + "Conditions will be ignored. Silence this warning " + "if you don't care about it." + ), + obj=cls, + id="models.W037", + ) + ) + if not ( + connection.features.supports_covering_indexes + or "supports_covering_indexes" in cls._meta.required_db_features + ) and any(index.include for index in cls._meta.indexes): + errors.append( + checks.Warning( + "%s does not support indexes with non-key columns." + % connection.display_name, + hint=( + "Non-key columns will be ignored. Silence this " + "warning if you don't care about it." + ), + obj=cls, + id="models.W040", + ) + ) + if not ( + connection.features.supports_expression_indexes + or "supports_expression_indexes" in cls._meta.required_db_features + ) and any(index.contains_expressions for index in cls._meta.indexes): + errors.append( + checks.Warning( + "%s does not support indexes on expressions." + % connection.display_name, + hint=( + "An index won't be created. Silence this warning " + "if you don't care about it." + ), + obj=cls, + id="models.W043", + ) + ) + fields = [ + field for index in cls._meta.indexes for field, _ in index.fields_orders + ] + fields += [include for index in cls._meta.indexes for include in index.include] + fields += references + errors.extend(cls._check_local_fields(fields, "indexes")) + return errors + + @classmethod + def _check_local_fields(cls, fields, option): + from django.db import models + + # In order to avoid hitting the relation tree prematurely, we use our + # own fields_map instead of using get_field() + forward_fields_map = {} + for field in cls._meta._get_fields(reverse=False): + forward_fields_map[field.name] = field + if hasattr(field, "attname"): + forward_fields_map[field.attname] = field + + errors = [] + for field_name in fields: + try: + field = forward_fields_map[field_name] + except KeyError: + errors.append( + checks.Error( + "'%s' refers to the nonexistent field '%s'." + % ( + option, + field_name, + ), + obj=cls, + id="models.E012", + ) + ) + else: + if isinstance(field.remote_field, models.ManyToManyRel): + errors.append( + checks.Error( + "'%s' refers to a ManyToManyField '%s', but " + "ManyToManyFields are not permitted in '%s'." + % ( + option, + field_name, + option, + ), + obj=cls, + id="models.E013", + ) + ) + elif field not in cls._meta.local_fields: + errors.append( + checks.Error( + "'%s' refers to field '%s' which is not local to model " + "'%s'." % (option, field_name, cls._meta.object_name), + hint="This issue may be caused by multi-table inheritance.", + obj=cls, + id="models.E016", + ) + ) + return errors + + @classmethod + def _check_ordering(cls): + """ + Check "ordering" option -- is it a list of strings and do all fields + exist? + """ + if cls._meta._ordering_clash: + return [ + checks.Error( + "'ordering' and 'order_with_respect_to' cannot be used together.", + obj=cls, + id="models.E021", + ), + ] + + if cls._meta.order_with_respect_to or not cls._meta.ordering: + return [] + + if not isinstance(cls._meta.ordering, (list, tuple)): + return [ + checks.Error( + "'ordering' must be a tuple or list (even if you want to order by " + "only one field).", + obj=cls, + id="models.E014", + ) + ] + + errors = [] + fields = cls._meta.ordering + + # Skip expressions and '?' fields. + fields = (f for f in fields if isinstance(f, str) and f != "?") + + # Convert "-field" to "field". + fields = (f.removeprefix("-") for f in fields) + + # Separate related fields and non-related fields. + _fields = [] + related_fields = [] + for f in fields: + if LOOKUP_SEP in f: + related_fields.append(f) + else: + _fields.append(f) + fields = _fields + + # Check related fields. + for field in related_fields: + _cls = cls + fld = None + for part in field.split(LOOKUP_SEP): + try: + # pk is an alias that won't be found by opts.get_field. + if part == "pk": + fld = _cls._meta.pk + else: + fld = _cls._meta.get_field(part) + if fld.is_relation: + _cls = fld.path_infos[-1].to_opts.model + else: + _cls = None + except (FieldDoesNotExist, AttributeError): + if fld is None or ( + fld.get_transform(part) is None and fld.get_lookup(part) is None + ): + errors.append( + checks.Error( + "'ordering' refers to the nonexistent field, " + "related field, or lookup '%s'." % field, + obj=cls, + id="models.E015", + ) + ) + + # Skip ordering on pk. This is always a valid order_by field + # but is an alias and therefore won't be found by opts.get_field. + fields = {f for f in fields if f != "pk"} + + # Check for invalid or nonexistent fields in ordering. + invalid_fields = [] + + # Any field name that is not present in field_names does not exist. + # Also, ordering by m2m fields is not allowed. + opts = cls._meta + valid_fields = set( + chain.from_iterable( + (f.name, f.attname) + if not (f.auto_created and not f.concrete) + else (f.field.related_query_name(),) + for f in chain(opts.fields, opts.related_objects) + ) + ) + + invalid_fields.extend(fields - valid_fields) + + for invalid_field in invalid_fields: + errors.append( + checks.Error( + "'ordering' refers to the nonexistent field, related " + "field, or lookup '%s'." % invalid_field, + obj=cls, + id="models.E015", + ) + ) + return errors + + @classmethod + def _check_long_column_names(cls, databases): + """ + Check that any auto-generated column names are shorter than the limits + for each database in which the model will be created. + """ + if not databases: + return [] + errors = [] + allowed_len = None + db_alias = None + + # Find the minimum max allowed length among all specified db_aliases. + for db in databases: + # skip databases where the model won't be created + if not router.allow_migrate_model(db, cls): + continue + connection = connections[db] + max_name_length = connection.ops.max_name_length() + if max_name_length is None or connection.features.truncates_names: + continue + else: + if allowed_len is None: + allowed_len = max_name_length + db_alias = db + elif max_name_length < allowed_len: + allowed_len = max_name_length + db_alias = db + + if allowed_len is None: + return errors + + for f in cls._meta.local_fields: + _, column_name = f.get_attname_column() + + # Check if auto-generated name for the field is too long + # for the database. + if ( + f.db_column is None + and column_name is not None + and len(column_name) > allowed_len + ): + errors.append( + checks.Error( + 'Autogenerated column name too long for field "%s". ' + 'Maximum length is "%s" for database "%s".' + % (column_name, allowed_len, db_alias), + hint="Set the column name manually using 'db_column'.", + obj=cls, + id="models.E018", + ) + ) + + for f in cls._meta.local_many_to_many: + # Skip nonexistent models. + if isinstance(f.remote_field.through, str): + continue + + # Check if auto-generated name for the M2M field is too long + # for the database. + for m2m in f.remote_field.through._meta.local_fields: + _, rel_name = m2m.get_attname_column() + if ( + m2m.db_column is None + and rel_name is not None + and len(rel_name) > allowed_len + ): + errors.append( + checks.Error( + "Autogenerated column name too long for M2M field " + '"%s". Maximum length is "%s" for database "%s".' + % (rel_name, allowed_len, db_alias), + hint=( + "Use 'through' to create a separate model for " + "M2M and then set column_name using 'db_column'." + ), + obj=cls, + id="models.E019", + ) + ) + + return errors + + @classmethod + def _get_expr_references(cls, expr): + if isinstance(expr, Q): + for child in expr.children: + if isinstance(child, tuple): + lookup, value = child + yield tuple(lookup.split(LOOKUP_SEP)) + yield from cls._get_expr_references(value) + else: + yield from cls._get_expr_references(child) + elif isinstance(expr, F): + yield tuple(expr.name.split(LOOKUP_SEP)) + elif hasattr(expr, "get_source_expressions"): + for src_expr in expr.get_source_expressions(): + yield from cls._get_expr_references(src_expr) + + @classmethod + def _check_constraints(cls, databases): + errors = [] + for db in databases: + if not router.allow_migrate_model(db, cls): + continue + connection = connections[db] + if not ( + connection.features.supports_table_check_constraints + or "supports_table_check_constraints" in cls._meta.required_db_features + ) and any( + isinstance(constraint, CheckConstraint) + for constraint in cls._meta.constraints + ): + errors.append( + checks.Warning( + "%s does not support check constraints." + % connection.display_name, + hint=( + "A constraint won't be created. Silence this " + "warning if you don't care about it." + ), + obj=cls, + id="models.W027", + ) + ) + if not ( + connection.features.supports_partial_indexes + or "supports_partial_indexes" in cls._meta.required_db_features + ) and any( + isinstance(constraint, UniqueConstraint) + and constraint.condition is not None + for constraint in cls._meta.constraints + ): + errors.append( + checks.Warning( + "%s does not support unique constraints with " + "conditions." % connection.display_name, + hint=( + "A constraint won't be created. Silence this " + "warning if you don't care about it." + ), + obj=cls, + id="models.W036", + ) + ) + if not ( + connection.features.supports_deferrable_unique_constraints + or "supports_deferrable_unique_constraints" + in cls._meta.required_db_features + ) and any( + isinstance(constraint, UniqueConstraint) + and constraint.deferrable is not None + for constraint in cls._meta.constraints + ): + errors.append( + checks.Warning( + "%s does not support deferrable unique constraints." + % connection.display_name, + hint=( + "A constraint won't be created. Silence this " + "warning if you don't care about it." + ), + obj=cls, + id="models.W038", + ) + ) + if not ( + connection.features.supports_covering_indexes + or "supports_covering_indexes" in cls._meta.required_db_features + ) and any( + isinstance(constraint, UniqueConstraint) and constraint.include + for constraint in cls._meta.constraints + ): + errors.append( + checks.Warning( + "%s does not support unique constraints with non-key " + "columns." % connection.display_name, + hint=( + "A constraint won't be created. Silence this " + "warning if you don't care about it." + ), + obj=cls, + id="models.W039", + ) + ) + if not ( + connection.features.supports_expression_indexes + or "supports_expression_indexes" in cls._meta.required_db_features + ) and any( + isinstance(constraint, UniqueConstraint) + and constraint.contains_expressions + for constraint in cls._meta.constraints + ): + errors.append( + checks.Warning( + "%s does not support unique constraints on " + "expressions." % connection.display_name, + hint=( + "A constraint won't be created. Silence this " + "warning if you don't care about it." + ), + obj=cls, + id="models.W044", + ) + ) + if not ( + connection.features.supports_nulls_distinct_unique_constraints + or ( + "supports_nulls_distinct_unique_constraints" + in cls._meta.required_db_features + ) + ) and any( + isinstance(constraint, UniqueConstraint) + and constraint.nulls_distinct is not None + for constraint in cls._meta.constraints + ): + errors.append( + checks.Warning( + "%s does not support unique constraints with " + "nulls distinct." % connection.display_name, + hint=( + "A constraint won't be created. Silence this " + "warning if you don't care about it." + ), + obj=cls, + id="models.W047", + ) + ) + fields = set( + chain.from_iterable( + (*constraint.fields, *constraint.include) + for constraint in cls._meta.constraints + if isinstance(constraint, UniqueConstraint) + ) + ) + references = set() + for constraint in cls._meta.constraints: + if isinstance(constraint, UniqueConstraint): + if ( + connection.features.supports_partial_indexes + or "supports_partial_indexes" + not in cls._meta.required_db_features + ) and isinstance(constraint.condition, Q): + references.update( + cls._get_expr_references(constraint.condition) + ) + if ( + connection.features.supports_expression_indexes + or "supports_expression_indexes" + not in cls._meta.required_db_features + ) and constraint.contains_expressions: + for expression in constraint.expressions: + references.update(cls._get_expr_references(expression)) + elif isinstance(constraint, CheckConstraint): + if ( + connection.features.supports_table_check_constraints + or "supports_table_check_constraints" + not in cls._meta.required_db_features + ): + if isinstance(constraint.check, Q): + references.update( + cls._get_expr_references(constraint.check) + ) + if any( + isinstance(expr, RawSQL) + for expr in constraint.check.flatten() + ): + errors.append( + checks.Warning( + f"Check constraint {constraint.name!r} contains " + f"RawSQL() expression and won't be validated " + f"during the model full_clean().", + hint=( + "Silence this warning if you don't care about " + "it." + ), + obj=cls, + id="models.W045", + ), + ) + for field_name, *lookups in references: + # pk is an alias that won't be found by opts.get_field. + if field_name != "pk": + fields.add(field_name) + if not lookups: + # If it has no lookups it cannot result in a JOIN. + continue + try: + if field_name == "pk": + field = cls._meta.pk + else: + field = cls._meta.get_field(field_name) + if not field.is_relation or field.many_to_many or field.one_to_many: + continue + except FieldDoesNotExist: + continue + # JOIN must happen at the first lookup. + first_lookup = lookups[0] + if ( + hasattr(field, "get_transform") + and hasattr(field, "get_lookup") + and field.get_transform(first_lookup) is None + and field.get_lookup(first_lookup) is None + ): + errors.append( + checks.Error( + "'constraints' refers to the joined field '%s'." + % LOOKUP_SEP.join([field_name] + lookups), + obj=cls, + id="models.E041", + ) + ) + errors.extend(cls._check_local_fields(fields, "constraints")) + return errors + + +############################################ +# HELPER FUNCTIONS (CURRIED MODEL METHODS) # +############################################ + +# ORDERING METHODS ######################### + + +def method_set_order(self, ordered_obj, id_list, using=None): + order_wrt = ordered_obj._meta.order_with_respect_to + filter_args = order_wrt.get_forward_related_filter(self) + ordered_obj.objects.db_manager(using).filter(**filter_args).bulk_update( + [ordered_obj(pk=pk, _order=order) for order, pk in enumerate(id_list)], + ["_order"], + ) + + +def method_get_order(self, ordered_obj): + order_wrt = ordered_obj._meta.order_with_respect_to + filter_args = order_wrt.get_forward_related_filter(self) + pk_name = ordered_obj._meta.pk.name + return ordered_obj.objects.filter(**filter_args).values_list(pk_name, flat=True) + + +def make_foreign_order_accessors(model, related_model): + setattr( + related_model, + "get_%s_order" % model.__name__.lower(), + partialmethod(method_get_order, model), + ) + setattr( + related_model, + "set_%s_order" % model.__name__.lower(), + partialmethod(method_set_order, model), + ) + + +######## +# MISC # +######## + + +def model_unpickle(model_id): + """Used to unpickle Model subclasses with deferred fields.""" + if isinstance(model_id, tuple): + model = apps.get_model(*model_id) + else: + # Backwards compat - the model was cached directly in earlier versions. + model = model_id + return model.__new__(model) + + +model_unpickle.__safe_for_unpickle__ = True diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/constants.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/constants.py new file mode 100644 index 0000000..a0c99c9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/constants.py @@ -0,0 +1,12 @@ +""" +Constants used across the ORM in general. +""" +from enum import Enum + +# Separator used to split filter strings apart. +LOOKUP_SEP = "__" + + +class OnConflict(Enum): + IGNORE = "ignore" + UPDATE = "update" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/constraints.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/constraints.py new file mode 100644 index 0000000..56d547e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/constraints.py @@ -0,0 +1,466 @@ +import warnings +from enum import Enum +from types import NoneType + +from django.core.exceptions import FieldError, ValidationError +from django.db import connections +from django.db.models.expressions import Exists, ExpressionList, F, OrderBy +from django.db.models.indexes import IndexExpression +from django.db.models.lookups import Exact +from django.db.models.query_utils import Q +from django.db.models.sql.query import Query +from django.db.utils import DEFAULT_DB_ALIAS +from django.utils.deprecation import RemovedInDjango60Warning +from django.utils.translation import gettext_lazy as _ + +__all__ = ["BaseConstraint", "CheckConstraint", "Deferrable", "UniqueConstraint"] + + +class BaseConstraint: + default_violation_error_message = _("Constraint “%(name)s” is violated.") + violation_error_code = None + violation_error_message = None + + # RemovedInDjango60Warning: When the deprecation ends, replace with: + # def __init__( + # self, *, name, violation_error_code=None, violation_error_message=None + # ): + def __init__( + self, *args, name=None, violation_error_code=None, violation_error_message=None + ): + # RemovedInDjango60Warning. + if name is None and not args: + raise TypeError( + f"{self.__class__.__name__}.__init__() missing 1 required keyword-only " + f"argument: 'name'" + ) + self.name = name + if violation_error_code is not None: + self.violation_error_code = violation_error_code + if violation_error_message is not None: + self.violation_error_message = violation_error_message + else: + self.violation_error_message = self.default_violation_error_message + # RemovedInDjango60Warning. + if args: + warnings.warn( + f"Passing positional arguments to {self.__class__.__name__} is " + f"deprecated.", + RemovedInDjango60Warning, + stacklevel=2, + ) + for arg, attr in zip(args, ["name", "violation_error_message"]): + if arg: + setattr(self, attr, arg) + + @property + def contains_expressions(self): + return False + + def constraint_sql(self, model, schema_editor): + raise NotImplementedError("This method must be implemented by a subclass.") + + def create_sql(self, model, schema_editor): + raise NotImplementedError("This method must be implemented by a subclass.") + + def remove_sql(self, model, schema_editor): + raise NotImplementedError("This method must be implemented by a subclass.") + + def validate(self, model, instance, exclude=None, using=DEFAULT_DB_ALIAS): + raise NotImplementedError("This method must be implemented by a subclass.") + + def get_violation_error_message(self): + return self.violation_error_message % {"name": self.name} + + def deconstruct(self): + path = "%s.%s" % (self.__class__.__module__, self.__class__.__name__) + path = path.replace("django.db.models.constraints", "django.db.models") + kwargs = {"name": self.name} + if ( + self.violation_error_message is not None + and self.violation_error_message != self.default_violation_error_message + ): + kwargs["violation_error_message"] = self.violation_error_message + if self.violation_error_code is not None: + kwargs["violation_error_code"] = self.violation_error_code + return (path, (), kwargs) + + def clone(self): + _, args, kwargs = self.deconstruct() + return self.__class__(*args, **kwargs) + + +class CheckConstraint(BaseConstraint): + def __init__( + self, *, check, name, violation_error_code=None, violation_error_message=None + ): + self.check = check + if not getattr(check, "conditional", False): + raise TypeError( + "CheckConstraint.check must be a Q instance or boolean expression." + ) + super().__init__( + name=name, + violation_error_code=violation_error_code, + violation_error_message=violation_error_message, + ) + + def _get_check_sql(self, model, schema_editor): + query = Query(model=model, alias_cols=False) + where = query.build_where(self.check) + compiler = query.get_compiler(connection=schema_editor.connection) + sql, params = where.as_sql(compiler, schema_editor.connection) + return sql % tuple(schema_editor.quote_value(p) for p in params) + + def constraint_sql(self, model, schema_editor): + check = self._get_check_sql(model, schema_editor) + return schema_editor._check_sql(self.name, check) + + def create_sql(self, model, schema_editor): + check = self._get_check_sql(model, schema_editor) + return schema_editor._create_check_sql(model, self.name, check) + + def remove_sql(self, model, schema_editor): + return schema_editor._delete_check_sql(model, self.name) + + def validate(self, model, instance, exclude=None, using=DEFAULT_DB_ALIAS): + against = instance._get_field_value_map(meta=model._meta, exclude=exclude) + try: + if not Q(self.check).check(against, using=using): + raise ValidationError( + self.get_violation_error_message(), code=self.violation_error_code + ) + except FieldError: + pass + + def __repr__(self): + return "<%s: check=%s name=%s%s%s>" % ( + self.__class__.__qualname__, + self.check, + repr(self.name), + ( + "" + if self.violation_error_code is None + else " violation_error_code=%r" % self.violation_error_code + ), + ( + "" + if self.violation_error_message is None + or self.violation_error_message == self.default_violation_error_message + else " violation_error_message=%r" % self.violation_error_message + ), + ) + + def __eq__(self, other): + if isinstance(other, CheckConstraint): + return ( + self.name == other.name + and self.check == other.check + and self.violation_error_code == other.violation_error_code + and self.violation_error_message == other.violation_error_message + ) + return super().__eq__(other) + + def deconstruct(self): + path, args, kwargs = super().deconstruct() + kwargs["check"] = self.check + return path, args, kwargs + + +class Deferrable(Enum): + DEFERRED = "deferred" + IMMEDIATE = "immediate" + + # A similar format was proposed for Python 3.10. + def __repr__(self): + return f"{self.__class__.__qualname__}.{self._name_}" + + +class UniqueConstraint(BaseConstraint): + def __init__( + self, + *expressions, + fields=(), + name=None, + condition=None, + deferrable=None, + include=None, + opclasses=(), + nulls_distinct=None, + violation_error_code=None, + violation_error_message=None, + ): + if not name: + raise ValueError("A unique constraint must be named.") + if not expressions and not fields: + raise ValueError( + "At least one field or expression is required to define a " + "unique constraint." + ) + if expressions and fields: + raise ValueError( + "UniqueConstraint.fields and expressions are mutually exclusive." + ) + if not isinstance(condition, (NoneType, Q)): + raise ValueError("UniqueConstraint.condition must be a Q instance.") + if condition and deferrable: + raise ValueError("UniqueConstraint with conditions cannot be deferred.") + if include and deferrable: + raise ValueError("UniqueConstraint with include fields cannot be deferred.") + if opclasses and deferrable: + raise ValueError("UniqueConstraint with opclasses cannot be deferred.") + if expressions and deferrable: + raise ValueError("UniqueConstraint with expressions cannot be deferred.") + if expressions and opclasses: + raise ValueError( + "UniqueConstraint.opclasses cannot be used with expressions. " + "Use django.contrib.postgres.indexes.OpClass() instead." + ) + if not isinstance(deferrable, (NoneType, Deferrable)): + raise TypeError( + "UniqueConstraint.deferrable must be a Deferrable instance." + ) + if not isinstance(include, (NoneType, list, tuple)): + raise TypeError("UniqueConstraint.include must be a list or tuple.") + if not isinstance(opclasses, (list, tuple)): + raise TypeError("UniqueConstraint.opclasses must be a list or tuple.") + if not isinstance(nulls_distinct, (NoneType, bool)): + raise TypeError("UniqueConstraint.nulls_distinct must be a bool.") + if opclasses and len(fields) != len(opclasses): + raise ValueError( + "UniqueConstraint.fields and UniqueConstraint.opclasses must " + "have the same number of elements." + ) + self.fields = tuple(fields) + self.condition = condition + self.deferrable = deferrable + self.include = tuple(include) if include else () + self.opclasses = opclasses + self.nulls_distinct = nulls_distinct + self.expressions = tuple( + F(expression) if isinstance(expression, str) else expression + for expression in expressions + ) + super().__init__( + name=name, + violation_error_code=violation_error_code, + violation_error_message=violation_error_message, + ) + + @property + def contains_expressions(self): + return bool(self.expressions) + + def _get_condition_sql(self, model, schema_editor): + if self.condition is None: + return None + query = Query(model=model, alias_cols=False) + where = query.build_where(self.condition) + compiler = query.get_compiler(connection=schema_editor.connection) + sql, params = where.as_sql(compiler, schema_editor.connection) + return sql % tuple(schema_editor.quote_value(p) for p in params) + + def _get_index_expressions(self, model, schema_editor): + if not self.expressions: + return None + index_expressions = [] + for expression in self.expressions: + index_expression = IndexExpression(expression) + index_expression.set_wrapper_classes(schema_editor.connection) + index_expressions.append(index_expression) + return ExpressionList(*index_expressions).resolve_expression( + Query(model, alias_cols=False), + ) + + def constraint_sql(self, model, schema_editor): + fields = [model._meta.get_field(field_name) for field_name in self.fields] + include = [ + model._meta.get_field(field_name).column for field_name in self.include + ] + condition = self._get_condition_sql(model, schema_editor) + expressions = self._get_index_expressions(model, schema_editor) + return schema_editor._unique_sql( + model, + fields, + self.name, + condition=condition, + deferrable=self.deferrable, + include=include, + opclasses=self.opclasses, + expressions=expressions, + nulls_distinct=self.nulls_distinct, + ) + + def create_sql(self, model, schema_editor): + fields = [model._meta.get_field(field_name) for field_name in self.fields] + include = [ + model._meta.get_field(field_name).column for field_name in self.include + ] + condition = self._get_condition_sql(model, schema_editor) + expressions = self._get_index_expressions(model, schema_editor) + return schema_editor._create_unique_sql( + model, + fields, + self.name, + condition=condition, + deferrable=self.deferrable, + include=include, + opclasses=self.opclasses, + expressions=expressions, + nulls_distinct=self.nulls_distinct, + ) + + def remove_sql(self, model, schema_editor): + condition = self._get_condition_sql(model, schema_editor) + include = [ + model._meta.get_field(field_name).column for field_name in self.include + ] + expressions = self._get_index_expressions(model, schema_editor) + return schema_editor._delete_unique_sql( + model, + self.name, + condition=condition, + deferrable=self.deferrable, + include=include, + opclasses=self.opclasses, + expressions=expressions, + nulls_distinct=self.nulls_distinct, + ) + + def __repr__(self): + return "<%s:%s%s%s%s%s%s%s%s%s%s>" % ( + self.__class__.__qualname__, + "" if not self.fields else " fields=%s" % repr(self.fields), + "" if not self.expressions else " expressions=%s" % repr(self.expressions), + " name=%s" % repr(self.name), + "" if self.condition is None else " condition=%s" % self.condition, + "" if self.deferrable is None else " deferrable=%r" % self.deferrable, + "" if not self.include else " include=%s" % repr(self.include), + "" if not self.opclasses else " opclasses=%s" % repr(self.opclasses), + ( + "" + if self.nulls_distinct is None + else " nulls_distinct=%r" % self.nulls_distinct + ), + ( + "" + if self.violation_error_code is None + else " violation_error_code=%r" % self.violation_error_code + ), + ( + "" + if self.violation_error_message is None + or self.violation_error_message == self.default_violation_error_message + else " violation_error_message=%r" % self.violation_error_message + ), + ) + + def __eq__(self, other): + if isinstance(other, UniqueConstraint): + return ( + self.name == other.name + and self.fields == other.fields + and self.condition == other.condition + and self.deferrable == other.deferrable + and self.include == other.include + and self.opclasses == other.opclasses + and self.expressions == other.expressions + and self.nulls_distinct is other.nulls_distinct + and self.violation_error_code == other.violation_error_code + and self.violation_error_message == other.violation_error_message + ) + return super().__eq__(other) + + def deconstruct(self): + path, args, kwargs = super().deconstruct() + if self.fields: + kwargs["fields"] = self.fields + if self.condition: + kwargs["condition"] = self.condition + if self.deferrable: + kwargs["deferrable"] = self.deferrable + if self.include: + kwargs["include"] = self.include + if self.opclasses: + kwargs["opclasses"] = self.opclasses + if self.nulls_distinct is not None: + kwargs["nulls_distinct"] = self.nulls_distinct + return path, self.expressions, kwargs + + def validate(self, model, instance, exclude=None, using=DEFAULT_DB_ALIAS): + queryset = model._default_manager.using(using) + if self.fields: + lookup_kwargs = {} + for field_name in self.fields: + if exclude and field_name in exclude: + return + field = model._meta.get_field(field_name) + lookup_value = getattr(instance, field.attname) + if ( + self.nulls_distinct is not False + and lookup_value is None + or ( + lookup_value == "" + and connections[ + using + ].features.interprets_empty_strings_as_nulls + ) + ): + # A composite constraint containing NULL value cannot cause + # a violation since NULL != NULL in SQL. + return + lookup_kwargs[field.name] = lookup_value + queryset = queryset.filter(**lookup_kwargs) + else: + # Ignore constraints with excluded fields. + if exclude: + for expression in self.expressions: + if hasattr(expression, "flatten"): + for expr in expression.flatten(): + if isinstance(expr, F) and expr.name in exclude: + return + elif isinstance(expression, F) and expression.name in exclude: + return + replacements = { + F(field): value + for field, value in instance._get_field_value_map( + meta=model._meta, exclude=exclude + ).items() + } + expressions = [] + for expr in self.expressions: + # Ignore ordering. + if isinstance(expr, OrderBy): + expr = expr.expression + expressions.append(Exact(expr, expr.replace_expressions(replacements))) + queryset = queryset.filter(*expressions) + model_class_pk = instance._get_pk_val(model._meta) + if not instance._state.adding and model_class_pk is not None: + queryset = queryset.exclude(pk=model_class_pk) + if not self.condition: + if queryset.exists(): + if self.expressions: + raise ValidationError( + self.get_violation_error_message(), + code=self.violation_error_code, + ) + # When fields are defined, use the unique_error_message() for + # backward compatibility. + for model, constraints in instance.get_constraints(): + for constraint in constraints: + if constraint is self: + raise ValidationError( + instance.unique_error_message(model, self.fields), + ) + else: + against = instance._get_field_value_map(meta=model._meta, exclude=exclude) + try: + if (self.condition & Exists(queryset.filter(self.condition))).check( + against, using=using + ): + raise ValidationError( + self.get_violation_error_message(), + code=self.violation_error_code, + ) + except FieldError: + pass diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/deletion.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/deletion.py new file mode 100644 index 0000000..bc26d82 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/deletion.py @@ -0,0 +1,522 @@ +from collections import Counter, defaultdict +from functools import partial, reduce +from itertools import chain +from operator import attrgetter, or_ + +from django.db import IntegrityError, connections, models, transaction +from django.db.models import query_utils, signals, sql + + +class ProtectedError(IntegrityError): + def __init__(self, msg, protected_objects): + self.protected_objects = protected_objects + super().__init__(msg, protected_objects) + + +class RestrictedError(IntegrityError): + def __init__(self, msg, restricted_objects): + self.restricted_objects = restricted_objects + super().__init__(msg, restricted_objects) + + +def CASCADE(collector, field, sub_objs, using): + collector.collect( + sub_objs, + source=field.remote_field.model, + source_attr=field.name, + nullable=field.null, + fail_on_restricted=False, + ) + if field.null and not connections[using].features.can_defer_constraint_checks: + collector.add_field_update(field, None, sub_objs) + + +def PROTECT(collector, field, sub_objs, using): + raise ProtectedError( + "Cannot delete some instances of model '%s' because they are " + "referenced through a protected foreign key: '%s.%s'" + % ( + field.remote_field.model.__name__, + sub_objs[0].__class__.__name__, + field.name, + ), + sub_objs, + ) + + +def RESTRICT(collector, field, sub_objs, using): + collector.add_restricted_objects(field, sub_objs) + collector.add_dependency(field.remote_field.model, field.model) + + +def SET(value): + if callable(value): + + def set_on_delete(collector, field, sub_objs, using): + collector.add_field_update(field, value(), sub_objs) + + else: + + def set_on_delete(collector, field, sub_objs, using): + collector.add_field_update(field, value, sub_objs) + + set_on_delete.deconstruct = lambda: ("django.db.models.SET", (value,), {}) + set_on_delete.lazy_sub_objs = True + return set_on_delete + + +def SET_NULL(collector, field, sub_objs, using): + collector.add_field_update(field, None, sub_objs) + + +SET_NULL.lazy_sub_objs = True + + +def SET_DEFAULT(collector, field, sub_objs, using): + collector.add_field_update(field, field.get_default(), sub_objs) + + +SET_DEFAULT.lazy_sub_objs = True + + +def DO_NOTHING(collector, field, sub_objs, using): + pass + + +def get_candidate_relations_to_delete(opts): + # The candidate relations are the ones that come from N-1 and 1-1 relations. + # N-N (i.e., many-to-many) relations aren't candidates for deletion. + return ( + f + for f in opts.get_fields(include_hidden=True) + if f.auto_created and not f.concrete and (f.one_to_one or f.one_to_many) + ) + + +class Collector: + def __init__(self, using, origin=None): + self.using = using + # A Model or QuerySet object. + self.origin = origin + # Initially, {model: {instances}}, later values become lists. + self.data = defaultdict(set) + # {(field, value): [instances, …]} + self.field_updates = defaultdict(list) + # {model: {field: {instances}}} + self.restricted_objects = defaultdict(partial(defaultdict, set)) + # fast_deletes is a list of queryset-likes that can be deleted without + # fetching the objects into memory. + self.fast_deletes = [] + + # Tracks deletion-order dependency for databases without transactions + # or ability to defer constraint checks. Only concrete model classes + # should be included, as the dependencies exist only between actual + # database tables; proxy models are represented here by their concrete + # parent. + self.dependencies = defaultdict(set) # {model: {models}} + + def add(self, objs, source=None, nullable=False, reverse_dependency=False): + """ + Add 'objs' to the collection of objects to be deleted. If the call is + the result of a cascade, 'source' should be the model that caused it, + and 'nullable' should be set to True if the relation can be null. + + Return a list of all objects that were not already collected. + """ + if not objs: + return [] + new_objs = [] + model = objs[0].__class__ + instances = self.data[model] + for obj in objs: + if obj not in instances: + new_objs.append(obj) + instances.update(new_objs) + # Nullable relationships can be ignored -- they are nulled out before + # deleting, and therefore do not affect the order in which objects have + # to be deleted. + if source is not None and not nullable: + self.add_dependency(source, model, reverse_dependency=reverse_dependency) + return new_objs + + def add_dependency(self, model, dependency, reverse_dependency=False): + if reverse_dependency: + model, dependency = dependency, model + self.dependencies[model._meta.concrete_model].add( + dependency._meta.concrete_model + ) + self.data.setdefault(dependency, self.data.default_factory()) + + def add_field_update(self, field, value, objs): + """ + Schedule a field update. 'objs' must be a homogeneous iterable + collection of model instances (e.g. a QuerySet). + """ + self.field_updates[field, value].append(objs) + + def add_restricted_objects(self, field, objs): + if objs: + model = objs[0].__class__ + self.restricted_objects[model][field].update(objs) + + def clear_restricted_objects_from_set(self, model, objs): + if model in self.restricted_objects: + self.restricted_objects[model] = { + field: items - objs + for field, items in self.restricted_objects[model].items() + } + + def clear_restricted_objects_from_queryset(self, model, qs): + if model in self.restricted_objects: + objs = set( + qs.filter( + pk__in=[ + obj.pk + for objs in self.restricted_objects[model].values() + for obj in objs + ] + ) + ) + self.clear_restricted_objects_from_set(model, objs) + + def _has_signal_listeners(self, model): + return signals.pre_delete.has_listeners( + model + ) or signals.post_delete.has_listeners(model) + + def can_fast_delete(self, objs, from_field=None): + """ + Determine if the objects in the given queryset-like or single object + can be fast-deleted. This can be done if there are no cascades, no + parents and no signal listeners for the object class. + + The 'from_field' tells where we are coming from - we need this to + determine if the objects are in fact to be deleted. Allow also + skipping parent -> child -> parent chain preventing fast delete of + the child. + """ + if from_field and from_field.remote_field.on_delete is not CASCADE: + return False + if hasattr(objs, "_meta"): + model = objs._meta.model + elif hasattr(objs, "model") and hasattr(objs, "_raw_delete"): + model = objs.model + else: + return False + if self._has_signal_listeners(model): + return False + # The use of from_field comes from the need to avoid cascade back to + # parent when parent delete is cascading to child. + opts = model._meta + return ( + all( + link == from_field + for link in opts.concrete_model._meta.parents.values() + ) + and + # Foreign keys pointing to this model. + all( + related.field.remote_field.on_delete is DO_NOTHING + for related in get_candidate_relations_to_delete(opts) + ) + and ( + # Something like generic foreign key. + not any( + hasattr(field, "bulk_related_objects") + for field in opts.private_fields + ) + ) + ) + + def get_del_batches(self, objs, fields): + """ + Return the objs in suitably sized batches for the used connection. + """ + field_names = [field.name for field in fields] + conn_batch_size = max( + connections[self.using].ops.bulk_batch_size(field_names, objs), 1 + ) + if len(objs) > conn_batch_size: + return [ + objs[i : i + conn_batch_size] + for i in range(0, len(objs), conn_batch_size) + ] + else: + return [objs] + + def collect( + self, + objs, + source=None, + nullable=False, + collect_related=True, + source_attr=None, + reverse_dependency=False, + keep_parents=False, + fail_on_restricted=True, + ): + """ + Add 'objs' to the collection of objects to be deleted as well as all + parent instances. 'objs' must be a homogeneous iterable collection of + model instances (e.g. a QuerySet). If 'collect_related' is True, + related objects will be handled by their respective on_delete handler. + + If the call is the result of a cascade, 'source' should be the model + that caused it and 'nullable' should be set to True, if the relation + can be null. + + If 'reverse_dependency' is True, 'source' will be deleted before the + current model, rather than after. (Needed for cascading to parent + models, the one case in which the cascade follows the forwards + direction of an FK rather than the reverse direction.) + + If 'keep_parents' is True, data of parent model's will be not deleted. + + If 'fail_on_restricted' is False, error won't be raised even if it's + prohibited to delete such objects due to RESTRICT, that defers + restricted object checking in recursive calls where the top-level call + may need to collect more objects to determine whether restricted ones + can be deleted. + """ + if self.can_fast_delete(objs): + self.fast_deletes.append(objs) + return + new_objs = self.add( + objs, source, nullable, reverse_dependency=reverse_dependency + ) + if not new_objs: + return + + model = new_objs[0].__class__ + + if not keep_parents: + # Recursively collect concrete model's parent models, but not their + # related objects. These will be found by meta.get_fields() + concrete_model = model._meta.concrete_model + for ptr in concrete_model._meta.parents.values(): + if ptr: + parent_objs = [getattr(obj, ptr.name) for obj in new_objs] + self.collect( + parent_objs, + source=model, + source_attr=ptr.remote_field.related_name, + collect_related=False, + reverse_dependency=True, + fail_on_restricted=False, + ) + if not collect_related: + return + + if keep_parents: + parents = set(model._meta.get_parent_list()) + model_fast_deletes = defaultdict(list) + protected_objects = defaultdict(list) + for related in get_candidate_relations_to_delete(model._meta): + # Preserve parent reverse relationships if keep_parents=True. + if keep_parents and related.model in parents: + continue + field = related.field + on_delete = field.remote_field.on_delete + if on_delete == DO_NOTHING: + continue + related_model = related.related_model + if self.can_fast_delete(related_model, from_field=field): + model_fast_deletes[related_model].append(field) + continue + batches = self.get_del_batches(new_objs, [field]) + for batch in batches: + sub_objs = self.related_objects(related_model, [field], batch) + # Non-referenced fields can be deferred if no signal receivers + # are connected for the related model as they'll never be + # exposed to the user. Skip field deferring when some + # relationships are select_related as interactions between both + # features are hard to get right. This should only happen in + # the rare cases where .related_objects is overridden anyway. + if not ( + sub_objs.query.select_related + or self._has_signal_listeners(related_model) + ): + referenced_fields = set( + chain.from_iterable( + (rf.attname for rf in rel.field.foreign_related_fields) + for rel in get_candidate_relations_to_delete( + related_model._meta + ) + ) + ) + sub_objs = sub_objs.only(*tuple(referenced_fields)) + if getattr(on_delete, "lazy_sub_objs", False) or sub_objs: + try: + on_delete(self, field, sub_objs, self.using) + except ProtectedError as error: + key = "'%s.%s'" % (field.model.__name__, field.name) + protected_objects[key] += error.protected_objects + if protected_objects: + raise ProtectedError( + "Cannot delete some instances of model %r because they are " + "referenced through protected foreign keys: %s." + % ( + model.__name__, + ", ".join(protected_objects), + ), + set(chain.from_iterable(protected_objects.values())), + ) + for related_model, related_fields in model_fast_deletes.items(): + batches = self.get_del_batches(new_objs, related_fields) + for batch in batches: + sub_objs = self.related_objects(related_model, related_fields, batch) + self.fast_deletes.append(sub_objs) + for field in model._meta.private_fields: + if hasattr(field, "bulk_related_objects"): + # It's something like generic foreign key. + sub_objs = field.bulk_related_objects(new_objs, self.using) + self.collect( + sub_objs, source=model, nullable=True, fail_on_restricted=False + ) + + if fail_on_restricted: + # Raise an error if collected restricted objects (RESTRICT) aren't + # candidates for deletion also collected via CASCADE. + for related_model, instances in self.data.items(): + self.clear_restricted_objects_from_set(related_model, instances) + for qs in self.fast_deletes: + self.clear_restricted_objects_from_queryset(qs.model, qs) + if self.restricted_objects.values(): + restricted_objects = defaultdict(list) + for related_model, fields in self.restricted_objects.items(): + for field, objs in fields.items(): + if objs: + key = "'%s.%s'" % (related_model.__name__, field.name) + restricted_objects[key] += objs + if restricted_objects: + raise RestrictedError( + "Cannot delete some instances of model %r because " + "they are referenced through restricted foreign keys: " + "%s." + % ( + model.__name__, + ", ".join(restricted_objects), + ), + set(chain.from_iterable(restricted_objects.values())), + ) + + def related_objects(self, related_model, related_fields, objs): + """ + Get a QuerySet of the related model to objs via related fields. + """ + predicate = query_utils.Q.create( + [(f"{related_field.name}__in", objs) for related_field in related_fields], + connector=query_utils.Q.OR, + ) + return related_model._base_manager.using(self.using).filter(predicate) + + def instances_with_model(self): + for model, instances in self.data.items(): + for obj in instances: + yield model, obj + + def sort(self): + sorted_models = [] + concrete_models = set() + models = list(self.data) + while len(sorted_models) < len(models): + found = False + for model in models: + if model in sorted_models: + continue + dependencies = self.dependencies.get(model._meta.concrete_model) + if not (dependencies and dependencies.difference(concrete_models)): + sorted_models.append(model) + concrete_models.add(model._meta.concrete_model) + found = True + if not found: + return + self.data = {model: self.data[model] for model in sorted_models} + + def delete(self): + # sort instance collections + for model, instances in self.data.items(): + self.data[model] = sorted(instances, key=attrgetter("pk")) + + # if possible, bring the models in an order suitable for databases that + # don't support transactions or cannot defer constraint checks until the + # end of a transaction. + self.sort() + # number of objects deleted for each model label + deleted_counter = Counter() + + # Optimize for the case with a single obj and no dependencies + if len(self.data) == 1 and len(instances) == 1: + instance = list(instances)[0] + if self.can_fast_delete(instance): + with transaction.mark_for_rollback_on_error(self.using): + count = sql.DeleteQuery(model).delete_batch( + [instance.pk], self.using + ) + setattr(instance, model._meta.pk.attname, None) + return count, {model._meta.label: count} + + with transaction.atomic(using=self.using, savepoint=False): + # send pre_delete signals + for model, obj in self.instances_with_model(): + if not model._meta.auto_created: + signals.pre_delete.send( + sender=model, + instance=obj, + using=self.using, + origin=self.origin, + ) + + # fast deletes + for qs in self.fast_deletes: + count = qs._raw_delete(using=self.using) + if count: + deleted_counter[qs.model._meta.label] += count + + # update fields + for (field, value), instances_list in self.field_updates.items(): + updates = [] + objs = [] + for instances in instances_list: + if ( + isinstance(instances, models.QuerySet) + and instances._result_cache is None + ): + updates.append(instances) + else: + objs.extend(instances) + if updates: + combined_updates = reduce(or_, updates) + combined_updates.update(**{field.name: value}) + if objs: + model = objs[0].__class__ + query = sql.UpdateQuery(model) + query.update_batch( + list({obj.pk for obj in objs}), {field.name: value}, self.using + ) + + # reverse instance collections + for instances in self.data.values(): + instances.reverse() + + # delete instances + for model, instances in self.data.items(): + query = sql.DeleteQuery(model) + pk_list = [obj.pk for obj in instances] + count = query.delete_batch(pk_list, self.using) + if count: + deleted_counter[model._meta.label] += count + + if not model._meta.auto_created: + for obj in instances: + signals.post_delete.send( + sender=model, + instance=obj, + using=self.using, + origin=self.origin, + ) + + for model, instances in self.data.items(): + for instance in instances: + setattr(instance, model._meta.pk.attname, None) + return sum(deleted_counter.values()), dict(deleted_counter) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/enums.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/enums.py new file mode 100644 index 0000000..bdc669b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/enums.py @@ -0,0 +1,123 @@ +import enum +import warnings + +from django.utils.deprecation import RemovedInDjango60Warning +from django.utils.functional import Promise +from django.utils.version import PY311, PY312 + +if PY311: + from enum import EnumType, IntEnum, StrEnum + from enum import property as enum_property +else: + from enum import EnumMeta as EnumType + from types import DynamicClassAttribute as enum_property + + class ReprEnum(enum.Enum): + def __str__(self): + return str(self.value) + + class IntEnum(int, ReprEnum): + pass + + class StrEnum(str, ReprEnum): + pass + + +__all__ = ["Choices", "IntegerChoices", "TextChoices"] + + +class ChoicesType(EnumType): + """A metaclass for creating a enum choices.""" + + def __new__(metacls, classname, bases, classdict, **kwds): + labels = [] + for key in classdict._member_names: + value = classdict[key] + if ( + isinstance(value, (list, tuple)) + and len(value) > 1 + and isinstance(value[-1], (Promise, str)) + ): + *value, label = value + value = tuple(value) + else: + label = key.replace("_", " ").title() + labels.append(label) + # Use dict.__setitem__() to suppress defenses against double + # assignment in enum's classdict. + dict.__setitem__(classdict, key, value) + cls = super().__new__(metacls, classname, bases, classdict, **kwds) + for member, label in zip(cls.__members__.values(), labels): + member._label_ = label + return enum.unique(cls) + + if not PY312: + + def __contains__(cls, member): + if not isinstance(member, enum.Enum): + # Allow non-enums to match against member values. + return any(x.value == member for x in cls) + return super().__contains__(member) + + @property + def names(cls): + empty = ["__empty__"] if hasattr(cls, "__empty__") else [] + return empty + [member.name for member in cls] + + @property + def choices(cls): + empty = [(None, cls.__empty__)] if hasattr(cls, "__empty__") else [] + return empty + [(member.value, member.label) for member in cls] + + @property + def labels(cls): + return [label for _, label in cls.choices] + + @property + def values(cls): + return [value for value, _ in cls.choices] + + +class Choices(enum.Enum, metaclass=ChoicesType): + """Class for creating enumerated choices.""" + + if PY311: + do_not_call_in_templates = enum.nonmember(True) + else: + + @property + def do_not_call_in_templates(self): + return True + + @enum_property + def label(self): + return self._label_ + + # A similar format was proposed for Python 3.10. + def __repr__(self): + return f"{self.__class__.__qualname__}.{self._name_}" + + +class IntegerChoices(Choices, IntEnum): + """Class for creating enumerated integer choices.""" + + pass + + +class TextChoices(Choices, StrEnum): + """Class for creating enumerated string choices.""" + + @staticmethod + def _generate_next_value_(name, start, count, last_values): + return name + + +def __getattr__(name): + if name == "ChoicesMeta": + warnings.warn( + "ChoicesMeta is deprecated in favor of ChoicesType.", + RemovedInDjango60Warning, + stacklevel=2, + ) + return ChoicesType + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/expressions.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/expressions.py new file mode 100644 index 0000000..b162da5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/expressions.py @@ -0,0 +1,1934 @@ +import copy +import datetime +import functools +import inspect +from collections import defaultdict +from decimal import Decimal +from types import NoneType +from uuid import UUID + +from django.core.exceptions import EmptyResultSet, FieldError, FullResultSet +from django.db import DatabaseError, NotSupportedError, connection +from django.db.models import fields +from django.db.models.constants import LOOKUP_SEP +from django.db.models.query_utils import Q +from django.utils.deconstruct import deconstructible +from django.utils.functional import cached_property +from django.utils.hashable import make_hashable + + +class SQLiteNumericMixin: + """ + Some expressions with output_field=DecimalField() must be cast to + numeric to be properly filtered. + """ + + def as_sqlite(self, compiler, connection, **extra_context): + sql, params = self.as_sql(compiler, connection, **extra_context) + try: + if self.output_field.get_internal_type() == "DecimalField": + sql = "(CAST(%s AS NUMERIC))" % sql + except FieldError: + pass + return sql, params + + +class Combinable: + """ + Provide the ability to combine one or two objects with + some connector. For example F('foo') + F('bar'). + """ + + # Arithmetic connectors + ADD = "+" + SUB = "-" + MUL = "*" + DIV = "/" + POW = "^" + # The following is a quoted % operator - it is quoted because it can be + # used in strings that also have parameter substitution. + MOD = "%%" + + # Bitwise operators - note that these are generated by .bitand() + # and .bitor(), the '&' and '|' are reserved for boolean operator + # usage. + BITAND = "&" + BITOR = "|" + BITLEFTSHIFT = "<<" + BITRIGHTSHIFT = ">>" + BITXOR = "#" + + def _combine(self, other, connector, reversed): + if not hasattr(other, "resolve_expression"): + # everything must be resolvable to an expression + other = Value(other) + + if reversed: + return CombinedExpression(other, connector, self) + return CombinedExpression(self, connector, other) + + ############# + # OPERATORS # + ############# + + def __neg__(self): + return self._combine(-1, self.MUL, False) + + def __add__(self, other): + return self._combine(other, self.ADD, False) + + def __sub__(self, other): + return self._combine(other, self.SUB, False) + + def __mul__(self, other): + return self._combine(other, self.MUL, False) + + def __truediv__(self, other): + return self._combine(other, self.DIV, False) + + def __mod__(self, other): + return self._combine(other, self.MOD, False) + + def __pow__(self, other): + return self._combine(other, self.POW, False) + + def __and__(self, other): + if getattr(self, "conditional", False) and getattr(other, "conditional", False): + return Q(self) & Q(other) + raise NotImplementedError( + "Use .bitand(), .bitor(), and .bitxor() for bitwise logical operations." + ) + + def bitand(self, other): + return self._combine(other, self.BITAND, False) + + def bitleftshift(self, other): + return self._combine(other, self.BITLEFTSHIFT, False) + + def bitrightshift(self, other): + return self._combine(other, self.BITRIGHTSHIFT, False) + + def __xor__(self, other): + if getattr(self, "conditional", False) and getattr(other, "conditional", False): + return Q(self) ^ Q(other) + raise NotImplementedError( + "Use .bitand(), .bitor(), and .bitxor() for bitwise logical operations." + ) + + def bitxor(self, other): + return self._combine(other, self.BITXOR, False) + + def __or__(self, other): + if getattr(self, "conditional", False) and getattr(other, "conditional", False): + return Q(self) | Q(other) + raise NotImplementedError( + "Use .bitand(), .bitor(), and .bitxor() for bitwise logical operations." + ) + + def bitor(self, other): + return self._combine(other, self.BITOR, False) + + def __radd__(self, other): + return self._combine(other, self.ADD, True) + + def __rsub__(self, other): + return self._combine(other, self.SUB, True) + + def __rmul__(self, other): + return self._combine(other, self.MUL, True) + + def __rtruediv__(self, other): + return self._combine(other, self.DIV, True) + + def __rmod__(self, other): + return self._combine(other, self.MOD, True) + + def __rpow__(self, other): + return self._combine(other, self.POW, True) + + def __rand__(self, other): + raise NotImplementedError( + "Use .bitand(), .bitor(), and .bitxor() for bitwise logical operations." + ) + + def __ror__(self, other): + raise NotImplementedError( + "Use .bitand(), .bitor(), and .bitxor() for bitwise logical operations." + ) + + def __rxor__(self, other): + raise NotImplementedError( + "Use .bitand(), .bitor(), and .bitxor() for bitwise logical operations." + ) + + def __invert__(self): + return NegatedExpression(self) + + +class BaseExpression: + """Base class for all query expressions.""" + + empty_result_set_value = NotImplemented + # aggregate specific fields + is_summary = False + _output_field_resolved_to_none = False + # Can the expression be used in a WHERE clause? + filterable = True + # Can the expression can be used as a source expression in Window? + window_compatible = False + # Can the expression be used as a database default value? + allowed_default = False + + def __init__(self, output_field=None): + if output_field is not None: + self.output_field = output_field + + def __getstate__(self): + state = self.__dict__.copy() + state.pop("convert_value", None) + return state + + def get_db_converters(self, connection): + return ( + [] + if self.convert_value is self._convert_value_noop + else [self.convert_value] + ) + self.output_field.get_db_converters(connection) + + def get_source_expressions(self): + return [] + + def set_source_expressions(self, exprs): + assert not exprs + + def _parse_expressions(self, *expressions): + return [ + arg + if hasattr(arg, "resolve_expression") + else (F(arg) if isinstance(arg, str) else Value(arg)) + for arg in expressions + ] + + def as_sql(self, compiler, connection): + """ + Responsible for returning a (sql, [params]) tuple to be included + in the current query. + + Different backends can provide their own implementation, by + providing an `as_{vendor}` method and patching the Expression: + + ``` + def override_as_sql(self, compiler, connection): + # custom logic + return super().as_sql(compiler, connection) + setattr(Expression, 'as_' + connection.vendor, override_as_sql) + ``` + + Arguments: + * compiler: the query compiler responsible for generating the query. + Must have a compile method, returning a (sql, [params]) tuple. + Calling compiler(value) will return a quoted `value`. + + * connection: the database connection used for the current query. + + Return: (sql, params) + Where `sql` is a string containing ordered sql parameters to be + replaced with the elements of the list `params`. + """ + raise NotImplementedError("Subclasses must implement as_sql()") + + @cached_property + def contains_aggregate(self): + return any( + expr and expr.contains_aggregate for expr in self.get_source_expressions() + ) + + @cached_property + def contains_over_clause(self): + return any( + expr and expr.contains_over_clause for expr in self.get_source_expressions() + ) + + @cached_property + def contains_column_references(self): + return any( + expr and expr.contains_column_references + for expr in self.get_source_expressions() + ) + + @cached_property + def contains_subquery(self): + return any( + expr and (getattr(expr, "subquery", False) or expr.contains_subquery) + for expr in self.get_source_expressions() + ) + + def resolve_expression( + self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False + ): + """ + Provide the chance to do any preprocessing or validation before being + added to the query. + + Arguments: + * query: the backend query implementation + * allow_joins: boolean allowing or denying use of joins + in this query + * reuse: a set of reusable joins for multijoins + * summarize: a terminal aggregate clause + * for_save: whether this expression about to be used in a save or update + + Return: an Expression to be added to the query. + """ + c = self.copy() + c.is_summary = summarize + c.set_source_expressions( + [ + expr.resolve_expression(query, allow_joins, reuse, summarize) + if expr + else None + for expr in c.get_source_expressions() + ] + ) + return c + + @property + def conditional(self): + return isinstance(self.output_field, fields.BooleanField) + + @property + def field(self): + return self.output_field + + @cached_property + def output_field(self): + """Return the output type of this expressions.""" + output_field = self._resolve_output_field() + if output_field is None: + self._output_field_resolved_to_none = True + raise FieldError("Cannot resolve expression type, unknown output_field") + return output_field + + @cached_property + def _output_field_or_none(self): + """ + Return the output field of this expression, or None if + _resolve_output_field() didn't return an output type. + """ + try: + return self.output_field + except FieldError: + if not self._output_field_resolved_to_none: + raise + + def _resolve_output_field(self): + """ + Attempt to infer the output type of the expression. + + As a guess, if the output fields of all source fields match then simply + infer the same type here. + + If a source's output field resolves to None, exclude it from this check. + If all sources are None, then an error is raised higher up the stack in + the output_field property. + """ + # This guess is mostly a bad idea, but there is quite a lot of code + # (especially 3rd party Func subclasses) that depend on it, we'd need a + # deprecation path to fix it. + sources_iter = ( + source for source in self.get_source_fields() if source is not None + ) + for output_field in sources_iter: + for source in sources_iter: + if not isinstance(output_field, source.__class__): + raise FieldError( + "Expression contains mixed types: %s, %s. You must " + "set output_field." + % ( + output_field.__class__.__name__, + source.__class__.__name__, + ) + ) + return output_field + + @staticmethod + def _convert_value_noop(value, expression, connection): + return value + + @cached_property + def convert_value(self): + """ + Expressions provide their own converters because users have the option + of manually specifying the output_field which may be a different type + from the one the database returns. + """ + field = self.output_field + internal_type = field.get_internal_type() + if internal_type == "FloatField": + return ( + lambda value, expression, connection: None + if value is None + else float(value) + ) + elif internal_type.endswith("IntegerField"): + return ( + lambda value, expression, connection: None + if value is None + else int(value) + ) + elif internal_type == "DecimalField": + return ( + lambda value, expression, connection: None + if value is None + else Decimal(value) + ) + return self._convert_value_noop + + def get_lookup(self, lookup): + return self.output_field.get_lookup(lookup) + + def get_transform(self, name): + return self.output_field.get_transform(name) + + def relabeled_clone(self, change_map): + clone = self.copy() + clone.set_source_expressions( + [ + e.relabeled_clone(change_map) if e is not None else None + for e in self.get_source_expressions() + ] + ) + return clone + + def replace_expressions(self, replacements): + if replacement := replacements.get(self): + return replacement + clone = self.copy() + source_expressions = clone.get_source_expressions() + clone.set_source_expressions( + [ + expr.replace_expressions(replacements) if expr else None + for expr in source_expressions + ] + ) + return clone + + def get_refs(self): + refs = set() + for expr in self.get_source_expressions(): + refs |= expr.get_refs() + return refs + + def copy(self): + return copy.copy(self) + + def prefix_references(self, prefix): + clone = self.copy() + clone.set_source_expressions( + [ + F(f"{prefix}{expr.name}") + if isinstance(expr, F) + else expr.prefix_references(prefix) + for expr in self.get_source_expressions() + ] + ) + return clone + + def get_group_by_cols(self): + if not self.contains_aggregate: + return [self] + cols = [] + for source in self.get_source_expressions(): + cols.extend(source.get_group_by_cols()) + return cols + + def get_source_fields(self): + """Return the underlying field types used by this aggregate.""" + return [e._output_field_or_none for e in self.get_source_expressions()] + + def asc(self, **kwargs): + return OrderBy(self, **kwargs) + + def desc(self, **kwargs): + return OrderBy(self, descending=True, **kwargs) + + def reverse_ordering(self): + return self + + def flatten(self): + """ + Recursively yield this expression and all subexpressions, in + depth-first order. + """ + yield self + for expr in self.get_source_expressions(): + if expr: + if hasattr(expr, "flatten"): + yield from expr.flatten() + else: + yield expr + + def select_format(self, compiler, sql, params): + """ + Custom format for select clauses. For example, EXISTS expressions need + to be wrapped in CASE WHEN on Oracle. + """ + if hasattr(self.output_field, "select_format"): + return self.output_field.select_format(compiler, sql, params) + return sql, params + + +@deconstructible +class Expression(BaseExpression, Combinable): + """An expression that can be combined with other expressions.""" + + @cached_property + def identity(self): + constructor_signature = inspect.signature(self.__init__) + args, kwargs = self._constructor_args + signature = constructor_signature.bind_partial(*args, **kwargs) + signature.apply_defaults() + arguments = signature.arguments.items() + identity = [self.__class__] + for arg, value in arguments: + if isinstance(value, fields.Field): + if value.name and value.model: + value = (value.model._meta.label, value.name) + else: + value = type(value) + else: + value = make_hashable(value) + identity.append((arg, value)) + return tuple(identity) + + def __eq__(self, other): + if not isinstance(other, Expression): + return NotImplemented + return other.identity == self.identity + + def __hash__(self): + return hash(self.identity) + + +# Type inference for CombinedExpression.output_field. +# Missing items will result in FieldError, by design. +# +# The current approach for NULL is based on lowest common denominator behavior +# i.e. if one of the supported databases is raising an error (rather than +# return NULL) for `val NULL`, then Django raises FieldError. + +_connector_combinations = [ + # Numeric operations - operands of same type. + # PositiveIntegerField should take precedence over IntegerField (except + # subtraction). + { + connector: [ + ( + fields.PositiveIntegerField, + fields.PositiveIntegerField, + fields.PositiveIntegerField, + ), + ] + for connector in ( + Combinable.ADD, + Combinable.MUL, + Combinable.DIV, + Combinable.MOD, + Combinable.POW, + ) + }, + # Other numeric operands. + { + connector: [ + (fields.IntegerField, fields.IntegerField, fields.IntegerField), + (fields.FloatField, fields.FloatField, fields.FloatField), + (fields.DecimalField, fields.DecimalField, fields.DecimalField), + ] + for connector in ( + Combinable.ADD, + Combinable.SUB, + Combinable.MUL, + # Behavior for DIV with integer arguments follows Postgres/SQLite, + # not MySQL/Oracle. + Combinable.DIV, + Combinable.MOD, + Combinable.POW, + ) + }, + # Numeric operations - operands of different type. + { + connector: [ + (fields.IntegerField, fields.DecimalField, fields.DecimalField), + (fields.DecimalField, fields.IntegerField, fields.DecimalField), + (fields.IntegerField, fields.FloatField, fields.FloatField), + (fields.FloatField, fields.IntegerField, fields.FloatField), + ] + for connector in ( + Combinable.ADD, + Combinable.SUB, + Combinable.MUL, + Combinable.DIV, + Combinable.MOD, + ) + }, + # Bitwise operators. + { + connector: [ + (fields.IntegerField, fields.IntegerField, fields.IntegerField), + ] + for connector in ( + Combinable.BITAND, + Combinable.BITOR, + Combinable.BITLEFTSHIFT, + Combinable.BITRIGHTSHIFT, + Combinable.BITXOR, + ) + }, + # Numeric with NULL. + { + connector: [ + (field_type, NoneType, field_type), + (NoneType, field_type, field_type), + ] + for connector in ( + Combinable.ADD, + Combinable.SUB, + Combinable.MUL, + Combinable.DIV, + Combinable.MOD, + Combinable.POW, + ) + for field_type in (fields.IntegerField, fields.DecimalField, fields.FloatField) + }, + # Date/DateTimeField/DurationField/TimeField. + { + Combinable.ADD: [ + # Date/DateTimeField. + (fields.DateField, fields.DurationField, fields.DateTimeField), + (fields.DateTimeField, fields.DurationField, fields.DateTimeField), + (fields.DurationField, fields.DateField, fields.DateTimeField), + (fields.DurationField, fields.DateTimeField, fields.DateTimeField), + # DurationField. + (fields.DurationField, fields.DurationField, fields.DurationField), + # TimeField. + (fields.TimeField, fields.DurationField, fields.TimeField), + (fields.DurationField, fields.TimeField, fields.TimeField), + ], + }, + { + Combinable.SUB: [ + # Date/DateTimeField. + (fields.DateField, fields.DurationField, fields.DateTimeField), + (fields.DateTimeField, fields.DurationField, fields.DateTimeField), + (fields.DateField, fields.DateField, fields.DurationField), + (fields.DateField, fields.DateTimeField, fields.DurationField), + (fields.DateTimeField, fields.DateField, fields.DurationField), + (fields.DateTimeField, fields.DateTimeField, fields.DurationField), + # DurationField. + (fields.DurationField, fields.DurationField, fields.DurationField), + # TimeField. + (fields.TimeField, fields.DurationField, fields.TimeField), + (fields.TimeField, fields.TimeField, fields.DurationField), + ], + }, +] + +_connector_combinators = defaultdict(list) + + +def register_combinable_fields(lhs, connector, rhs, result): + """ + Register combinable types: + lhs rhs -> result + e.g. + register_combinable_fields( + IntegerField, Combinable.ADD, FloatField, FloatField + ) + """ + _connector_combinators[connector].append((lhs, rhs, result)) + + +for d in _connector_combinations: + for connector, field_types in d.items(): + for lhs, rhs, result in field_types: + register_combinable_fields(lhs, connector, rhs, result) + + +@functools.lru_cache(maxsize=128) +def _resolve_combined_type(connector, lhs_type, rhs_type): + combinators = _connector_combinators.get(connector, ()) + for combinator_lhs_type, combinator_rhs_type, combined_type in combinators: + if issubclass(lhs_type, combinator_lhs_type) and issubclass( + rhs_type, combinator_rhs_type + ): + return combined_type + + +class CombinedExpression(SQLiteNumericMixin, Expression): + def __init__(self, lhs, connector, rhs, output_field=None): + super().__init__(output_field=output_field) + self.connector = connector + self.lhs = lhs + self.rhs = rhs + + def __repr__(self): + return "<{}: {}>".format(self.__class__.__name__, self) + + def __str__(self): + return "{} {} {}".format(self.lhs, self.connector, self.rhs) + + def get_source_expressions(self): + return [self.lhs, self.rhs] + + def set_source_expressions(self, exprs): + self.lhs, self.rhs = exprs + + def _resolve_output_field(self): + # We avoid using super() here for reasons given in + # Expression._resolve_output_field() + combined_type = _resolve_combined_type( + self.connector, + type(self.lhs._output_field_or_none), + type(self.rhs._output_field_or_none), + ) + if combined_type is None: + raise FieldError( + f"Cannot infer type of {self.connector!r} expression involving these " + f"types: {self.lhs.output_field.__class__.__name__}, " + f"{self.rhs.output_field.__class__.__name__}. You must set " + f"output_field." + ) + return combined_type() + + def as_sql(self, compiler, connection): + expressions = [] + expression_params = [] + sql, params = compiler.compile(self.lhs) + expressions.append(sql) + expression_params.extend(params) + sql, params = compiler.compile(self.rhs) + expressions.append(sql) + expression_params.extend(params) + # order of precedence + expression_wrapper = "(%s)" + sql = connection.ops.combine_expression(self.connector, expressions) + return expression_wrapper % sql, expression_params + + def resolve_expression( + self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False + ): + lhs = self.lhs.resolve_expression( + query, allow_joins, reuse, summarize, for_save + ) + rhs = self.rhs.resolve_expression( + query, allow_joins, reuse, summarize, for_save + ) + if not isinstance(self, (DurationExpression, TemporalSubtraction)): + try: + lhs_type = lhs.output_field.get_internal_type() + except (AttributeError, FieldError): + lhs_type = None + try: + rhs_type = rhs.output_field.get_internal_type() + except (AttributeError, FieldError): + rhs_type = None + if "DurationField" in {lhs_type, rhs_type} and lhs_type != rhs_type: + return DurationExpression( + self.lhs, self.connector, self.rhs + ).resolve_expression( + query, + allow_joins, + reuse, + summarize, + for_save, + ) + datetime_fields = {"DateField", "DateTimeField", "TimeField"} + if ( + self.connector == self.SUB + and lhs_type in datetime_fields + and lhs_type == rhs_type + ): + return TemporalSubtraction(self.lhs, self.rhs).resolve_expression( + query, + allow_joins, + reuse, + summarize, + for_save, + ) + c = self.copy() + c.is_summary = summarize + c.lhs = lhs + c.rhs = rhs + return c + + @cached_property + def allowed_default(self): + return self.lhs.allowed_default and self.rhs.allowed_default + + +class DurationExpression(CombinedExpression): + def compile(self, side, compiler, connection): + try: + output = side.output_field + except FieldError: + pass + else: + if output.get_internal_type() == "DurationField": + sql, params = compiler.compile(side) + return connection.ops.format_for_duration_arithmetic(sql), params + return compiler.compile(side) + + def as_sql(self, compiler, connection): + if connection.features.has_native_duration_field: + return super().as_sql(compiler, connection) + connection.ops.check_expression_support(self) + expressions = [] + expression_params = [] + sql, params = self.compile(self.lhs, compiler, connection) + expressions.append(sql) + expression_params.extend(params) + sql, params = self.compile(self.rhs, compiler, connection) + expressions.append(sql) + expression_params.extend(params) + # order of precedence + expression_wrapper = "(%s)" + sql = connection.ops.combine_duration_expression(self.connector, expressions) + return expression_wrapper % sql, expression_params + + def as_sqlite(self, compiler, connection, **extra_context): + sql, params = self.as_sql(compiler, connection, **extra_context) + if self.connector in {Combinable.MUL, Combinable.DIV}: + try: + lhs_type = self.lhs.output_field.get_internal_type() + rhs_type = self.rhs.output_field.get_internal_type() + except (AttributeError, FieldError): + pass + else: + allowed_fields = { + "DecimalField", + "DurationField", + "FloatField", + "IntegerField", + } + if lhs_type not in allowed_fields or rhs_type not in allowed_fields: + raise DatabaseError( + f"Invalid arguments for operator {self.connector}." + ) + return sql, params + + +class TemporalSubtraction(CombinedExpression): + output_field = fields.DurationField() + + def __init__(self, lhs, rhs): + super().__init__(lhs, self.SUB, rhs) + + def as_sql(self, compiler, connection): + connection.ops.check_expression_support(self) + lhs = compiler.compile(self.lhs) + rhs = compiler.compile(self.rhs) + return connection.ops.subtract_temporals( + self.lhs.output_field.get_internal_type(), lhs, rhs + ) + + +@deconstructible(path="django.db.models.F") +class F(Combinable): + """An object capable of resolving references to existing query objects.""" + + allowed_default = False + + def __init__(self, name): + """ + Arguments: + * name: the name of the field this expression references + """ + self.name = name + + def __repr__(self): + return "{}({})".format(self.__class__.__name__, self.name) + + def resolve_expression( + self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False + ): + return query.resolve_ref(self.name, allow_joins, reuse, summarize) + + def replace_expressions(self, replacements): + return replacements.get(self, self) + + def asc(self, **kwargs): + return OrderBy(self, **kwargs) + + def desc(self, **kwargs): + return OrderBy(self, descending=True, **kwargs) + + def __eq__(self, other): + return self.__class__ == other.__class__ and self.name == other.name + + def __hash__(self): + return hash(self.name) + + def copy(self): + return copy.copy(self) + + +class ResolvedOuterRef(F): + """ + An object that contains a reference to an outer query. + + In this case, the reference to the outer query has been resolved because + the inner query has been used as a subquery. + """ + + contains_aggregate = False + contains_over_clause = False + + def as_sql(self, *args, **kwargs): + raise ValueError( + "This queryset contains a reference to an outer query and may " + "only be used in a subquery." + ) + + def resolve_expression(self, *args, **kwargs): + col = super().resolve_expression(*args, **kwargs) + if col.contains_over_clause: + raise NotSupportedError( + f"Referencing outer query window expression is not supported: " + f"{self.name}." + ) + # FIXME: Rename possibly_multivalued to multivalued and fix detection + # for non-multivalued JOINs (e.g. foreign key fields). This should take + # into account only many-to-many and one-to-many relationships. + col.possibly_multivalued = LOOKUP_SEP in self.name + return col + + def relabeled_clone(self, relabels): + return self + + def get_group_by_cols(self): + return [] + + +class OuterRef(F): + contains_aggregate = False + contains_over_clause = False + + def resolve_expression(self, *args, **kwargs): + if isinstance(self.name, self.__class__): + return self.name + return ResolvedOuterRef(self.name) + + def relabeled_clone(self, relabels): + return self + + +@deconstructible(path="django.db.models.Func") +class Func(SQLiteNumericMixin, Expression): + """An SQL function call.""" + + function = None + template = "%(function)s(%(expressions)s)" + arg_joiner = ", " + arity = None # The number of arguments the function accepts. + + def __init__(self, *expressions, output_field=None, **extra): + if self.arity is not None and len(expressions) != self.arity: + raise TypeError( + "'%s' takes exactly %s %s (%s given)" + % ( + self.__class__.__name__, + self.arity, + "argument" if self.arity == 1 else "arguments", + len(expressions), + ) + ) + super().__init__(output_field=output_field) + self.source_expressions = self._parse_expressions(*expressions) + self.extra = extra + + def __repr__(self): + args = self.arg_joiner.join(str(arg) for arg in self.source_expressions) + extra = {**self.extra, **self._get_repr_options()} + if extra: + extra = ", ".join( + str(key) + "=" + str(val) for key, val in sorted(extra.items()) + ) + return "{}({}, {})".format(self.__class__.__name__, args, extra) + return "{}({})".format(self.__class__.__name__, args) + + def _get_repr_options(self): + """Return a dict of extra __init__() options to include in the repr.""" + return {} + + def get_source_expressions(self): + return self.source_expressions + + def set_source_expressions(self, exprs): + self.source_expressions = exprs + + def resolve_expression( + self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False + ): + c = self.copy() + c.is_summary = summarize + for pos, arg in enumerate(c.source_expressions): + c.source_expressions[pos] = arg.resolve_expression( + query, allow_joins, reuse, summarize, for_save + ) + return c + + def as_sql( + self, + compiler, + connection, + function=None, + template=None, + arg_joiner=None, + **extra_context, + ): + connection.ops.check_expression_support(self) + sql_parts = [] + params = [] + for arg in self.source_expressions: + try: + arg_sql, arg_params = compiler.compile(arg) + except EmptyResultSet: + empty_result_set_value = getattr( + arg, "empty_result_set_value", NotImplemented + ) + if empty_result_set_value is NotImplemented: + raise + arg_sql, arg_params = compiler.compile(Value(empty_result_set_value)) + except FullResultSet: + arg_sql, arg_params = compiler.compile(Value(True)) + sql_parts.append(arg_sql) + params.extend(arg_params) + data = {**self.extra, **extra_context} + # Use the first supplied value in this order: the parameter to this + # method, a value supplied in __init__()'s **extra (the value in + # `data`), or the value defined on the class. + if function is not None: + data["function"] = function + else: + data.setdefault("function", self.function) + template = template or data.get("template", self.template) + arg_joiner = arg_joiner or data.get("arg_joiner", self.arg_joiner) + data["expressions"] = data["field"] = arg_joiner.join(sql_parts) + return template % data, params + + def copy(self): + copy = super().copy() + copy.source_expressions = self.source_expressions[:] + copy.extra = self.extra.copy() + return copy + + @cached_property + def allowed_default(self): + return all(expression.allowed_default for expression in self.source_expressions) + + +@deconstructible(path="django.db.models.Value") +class Value(SQLiteNumericMixin, Expression): + """Represent a wrapped value as a node within an expression.""" + + # Provide a default value for `for_save` in order to allow unresolved + # instances to be compiled until a decision is taken in #25425. + for_save = False + allowed_default = True + + def __init__(self, value, output_field=None): + """ + Arguments: + * value: the value this expression represents. The value will be + added into the sql parameter list and properly quoted. + + * output_field: an instance of the model field type that this + expression will return, such as IntegerField() or CharField(). + """ + super().__init__(output_field=output_field) + self.value = value + + def __repr__(self): + return f"{self.__class__.__name__}({self.value!r})" + + def as_sql(self, compiler, connection): + connection.ops.check_expression_support(self) + val = self.value + output_field = self._output_field_or_none + if output_field is not None: + if self.for_save: + val = output_field.get_db_prep_save(val, connection=connection) + else: + val = output_field.get_db_prep_value(val, connection=connection) + if hasattr(output_field, "get_placeholder"): + return output_field.get_placeholder(val, compiler, connection), [val] + if val is None: + # oracledb does not always convert None to the appropriate + # NULL type (like in case expressions using numbers), so we + # use a literal SQL NULL + return "NULL", [] + return "%s", [val] + + def resolve_expression( + self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False + ): + c = super().resolve_expression(query, allow_joins, reuse, summarize, for_save) + c.for_save = for_save + return c + + def get_group_by_cols(self): + return [] + + def _resolve_output_field(self): + if isinstance(self.value, str): + return fields.CharField() + if isinstance(self.value, bool): + return fields.BooleanField() + if isinstance(self.value, int): + return fields.IntegerField() + if isinstance(self.value, float): + return fields.FloatField() + if isinstance(self.value, datetime.datetime): + return fields.DateTimeField() + if isinstance(self.value, datetime.date): + return fields.DateField() + if isinstance(self.value, datetime.time): + return fields.TimeField() + if isinstance(self.value, datetime.timedelta): + return fields.DurationField() + if isinstance(self.value, Decimal): + return fields.DecimalField() + if isinstance(self.value, bytes): + return fields.BinaryField() + if isinstance(self.value, UUID): + return fields.UUIDField() + + @property + def empty_result_set_value(self): + return self.value + + +class RawSQL(Expression): + allowed_default = True + + def __init__(self, sql, params, output_field=None): + if output_field is None: + output_field = fields.Field() + self.sql, self.params = sql, params + super().__init__(output_field=output_field) + + def __repr__(self): + return "{}({}, {})".format(self.__class__.__name__, self.sql, self.params) + + def as_sql(self, compiler, connection): + return "(%s)" % self.sql, self.params + + def get_group_by_cols(self): + return [self] + + def resolve_expression( + self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False + ): + # Resolve parents fields used in raw SQL. + if query.model: + for parent in query.model._meta.get_parent_list(): + for parent_field in parent._meta.local_fields: + _, column_name = parent_field.get_attname_column() + if column_name.lower() in self.sql.lower(): + query.resolve_ref( + parent_field.name, allow_joins, reuse, summarize + ) + break + return super().resolve_expression( + query, allow_joins, reuse, summarize, for_save + ) + + +class Star(Expression): + def __repr__(self): + return "'*'" + + def as_sql(self, compiler, connection): + return "*", [] + + +class DatabaseDefault(Expression): + """Placeholder expression for the database default in an insert query.""" + + def as_sql(self, compiler, connection): + return "DEFAULT", [] + + +class Col(Expression): + contains_column_references = True + possibly_multivalued = False + + def __init__(self, alias, target, output_field=None): + if output_field is None: + output_field = target + super().__init__(output_field=output_field) + self.alias, self.target = alias, target + + def __repr__(self): + alias, target = self.alias, self.target + identifiers = (alias, str(target)) if alias else (str(target),) + return "{}({})".format(self.__class__.__name__, ", ".join(identifiers)) + + def as_sql(self, compiler, connection): + alias, column = self.alias, self.target.column + identifiers = (alias, column) if alias else (column,) + sql = ".".join(map(compiler.quote_name_unless_alias, identifiers)) + return sql, [] + + def relabeled_clone(self, relabels): + if self.alias is None: + return self + return self.__class__( + relabels.get(self.alias, self.alias), self.target, self.output_field + ) + + def get_group_by_cols(self): + return [self] + + def get_db_converters(self, connection): + if self.target == self.output_field: + return self.output_field.get_db_converters(connection) + return self.output_field.get_db_converters( + connection + ) + self.target.get_db_converters(connection) + + +class Ref(Expression): + """ + Reference to column alias of the query. For example, Ref('sum_cost') in + qs.annotate(sum_cost=Sum('cost')) query. + """ + + def __init__(self, refs, source): + super().__init__() + self.refs, self.source = refs, source + + def __repr__(self): + return "{}({}, {})".format(self.__class__.__name__, self.refs, self.source) + + def get_source_expressions(self): + return [self.source] + + def set_source_expressions(self, exprs): + (self.source,) = exprs + + def resolve_expression( + self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False + ): + # The sub-expression `source` has already been resolved, as this is + # just a reference to the name of `source`. + return self + + def get_refs(self): + return {self.refs} + + def relabeled_clone(self, relabels): + clone = self.copy() + clone.source = self.source.relabeled_clone(relabels) + return clone + + def as_sql(self, compiler, connection): + return connection.ops.quote_name(self.refs), [] + + def get_group_by_cols(self): + return [self] + + +class ExpressionList(Func): + """ + An expression containing multiple expressions. Can be used to provide a + list of expressions as an argument to another expression, like a partition + clause. + """ + + template = "%(expressions)s" + + def __init__(self, *expressions, **extra): + if not expressions: + raise ValueError( + "%s requires at least one expression." % self.__class__.__name__ + ) + super().__init__(*expressions, **extra) + + def __str__(self): + return self.arg_joiner.join(str(arg) for arg in self.source_expressions) + + def as_sqlite(self, compiler, connection, **extra_context): + # Casting to numeric is unnecessary. + return self.as_sql(compiler, connection, **extra_context) + + def get_group_by_cols(self): + group_by_cols = [] + for partition in self.get_source_expressions(): + group_by_cols.extend(partition.get_group_by_cols()) + return group_by_cols + + +class OrderByList(Func): + allowed_default = False + template = "ORDER BY %(expressions)s" + + def __init__(self, *expressions, **extra): + expressions = ( + ( + OrderBy(F(expr[1:]), descending=True) + if isinstance(expr, str) and expr[0] == "-" + else expr + ) + for expr in expressions + ) + super().__init__(*expressions, **extra) + + def as_sql(self, *args, **kwargs): + if not self.source_expressions: + return "", () + return super().as_sql(*args, **kwargs) + + def get_group_by_cols(self): + group_by_cols = [] + for order_by in self.get_source_expressions(): + group_by_cols.extend(order_by.get_group_by_cols()) + return group_by_cols + + +@deconstructible(path="django.db.models.ExpressionWrapper") +class ExpressionWrapper(SQLiteNumericMixin, Expression): + """ + An expression that can wrap another expression so that it can provide + extra context to the inner expression, such as the output_field. + """ + + def __init__(self, expression, output_field): + super().__init__(output_field=output_field) + self.expression = expression + + def set_source_expressions(self, exprs): + self.expression = exprs[0] + + def get_source_expressions(self): + return [self.expression] + + def get_group_by_cols(self): + if isinstance(self.expression, Expression): + expression = self.expression.copy() + expression.output_field = self.output_field + return expression.get_group_by_cols() + # For non-expressions e.g. an SQL WHERE clause, the entire + # `expression` must be included in the GROUP BY clause. + return super().get_group_by_cols() + + def as_sql(self, compiler, connection): + return compiler.compile(self.expression) + + def __repr__(self): + return "{}({})".format(self.__class__.__name__, self.expression) + + @property + def allowed_default(self): + return self.expression.allowed_default + + +class NegatedExpression(ExpressionWrapper): + """The logical negation of a conditional expression.""" + + def __init__(self, expression): + super().__init__(expression, output_field=fields.BooleanField()) + + def __invert__(self): + return self.expression.copy() + + def as_sql(self, compiler, connection): + try: + sql, params = super().as_sql(compiler, connection) + except EmptyResultSet: + features = compiler.connection.features + if not features.supports_boolean_expr_in_select_clause: + return "1=1", () + return compiler.compile(Value(True)) + ops = compiler.connection.ops + # Some database backends (e.g. Oracle) don't allow EXISTS() and filters + # to be compared to another expression unless they're wrapped in a CASE + # WHEN. + if not ops.conditional_expression_supported_in_where_clause(self.expression): + return f"CASE WHEN {sql} = 0 THEN 1 ELSE 0 END", params + return f"NOT {sql}", params + + def resolve_expression( + self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False + ): + resolved = super().resolve_expression( + query, allow_joins, reuse, summarize, for_save + ) + if not getattr(resolved.expression, "conditional", False): + raise TypeError("Cannot negate non-conditional expressions.") + return resolved + + def select_format(self, compiler, sql, params): + # Wrap boolean expressions with a CASE WHEN expression if a database + # backend (e.g. Oracle) doesn't support boolean expression in SELECT or + # GROUP BY list. + expression_supported_in_where_clause = ( + compiler.connection.ops.conditional_expression_supported_in_where_clause + ) + if ( + not compiler.connection.features.supports_boolean_expr_in_select_clause + # Avoid double wrapping. + and expression_supported_in_where_clause(self.expression) + ): + sql = "CASE WHEN {} THEN 1 ELSE 0 END".format(sql) + return sql, params + + +@deconstructible(path="django.db.models.When") +class When(Expression): + template = "WHEN %(condition)s THEN %(result)s" + # This isn't a complete conditional expression, must be used in Case(). + conditional = False + + def __init__(self, condition=None, then=None, **lookups): + if lookups: + if condition is None: + condition, lookups = Q(**lookups), None + elif getattr(condition, "conditional", False): + condition, lookups = Q(condition, **lookups), None + if condition is None or not getattr(condition, "conditional", False) or lookups: + raise TypeError( + "When() supports a Q object, a boolean expression, or lookups " + "as a condition." + ) + if isinstance(condition, Q) and not condition: + raise ValueError("An empty Q() can't be used as a When() condition.") + super().__init__(output_field=None) + self.condition = condition + self.result = self._parse_expressions(then)[0] + + def __str__(self): + return "WHEN %r THEN %r" % (self.condition, self.result) + + def __repr__(self): + return "<%s: %s>" % (self.__class__.__name__, self) + + def get_source_expressions(self): + return [self.condition, self.result] + + def set_source_expressions(self, exprs): + self.condition, self.result = exprs + + def get_source_fields(self): + # We're only interested in the fields of the result expressions. + return [self.result._output_field_or_none] + + def resolve_expression( + self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False + ): + c = self.copy() + c.is_summary = summarize + if hasattr(c.condition, "resolve_expression"): + c.condition = c.condition.resolve_expression( + query, allow_joins, reuse, summarize, False + ) + c.result = c.result.resolve_expression( + query, allow_joins, reuse, summarize, for_save + ) + return c + + def as_sql(self, compiler, connection, template=None, **extra_context): + connection.ops.check_expression_support(self) + template_params = extra_context + sql_params = [] + condition_sql, condition_params = compiler.compile(self.condition) + template_params["condition"] = condition_sql + result_sql, result_params = compiler.compile(self.result) + template_params["result"] = result_sql + template = template or self.template + return template % template_params, ( + *sql_params, + *condition_params, + *result_params, + ) + + def get_group_by_cols(self): + # This is not a complete expression and cannot be used in GROUP BY. + cols = [] + for source in self.get_source_expressions(): + cols.extend(source.get_group_by_cols()) + return cols + + @cached_property + def allowed_default(self): + return self.condition.allowed_default and self.result.allowed_default + + +@deconstructible(path="django.db.models.Case") +class Case(SQLiteNumericMixin, Expression): + """ + An SQL searched CASE expression: + + CASE + WHEN n > 0 + THEN 'positive' + WHEN n < 0 + THEN 'negative' + ELSE 'zero' + END + """ + + template = "CASE %(cases)s ELSE %(default)s END" + case_joiner = " " + + def __init__(self, *cases, default=None, output_field=None, **extra): + if not all(isinstance(case, When) for case in cases): + raise TypeError("Positional arguments must all be When objects.") + super().__init__(output_field) + self.cases = list(cases) + self.default = self._parse_expressions(default)[0] + self.extra = extra + + def __str__(self): + return "CASE %s, ELSE %r" % ( + ", ".join(str(c) for c in self.cases), + self.default, + ) + + def __repr__(self): + return "<%s: %s>" % (self.__class__.__name__, self) + + def get_source_expressions(self): + return self.cases + [self.default] + + def set_source_expressions(self, exprs): + *self.cases, self.default = exprs + + def resolve_expression( + self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False + ): + c = self.copy() + c.is_summary = summarize + for pos, case in enumerate(c.cases): + c.cases[pos] = case.resolve_expression( + query, allow_joins, reuse, summarize, for_save + ) + c.default = c.default.resolve_expression( + query, allow_joins, reuse, summarize, for_save + ) + return c + + def copy(self): + c = super().copy() + c.cases = c.cases[:] + return c + + def as_sql( + self, compiler, connection, template=None, case_joiner=None, **extra_context + ): + connection.ops.check_expression_support(self) + if not self.cases: + return compiler.compile(self.default) + template_params = {**self.extra, **extra_context} + case_parts = [] + sql_params = [] + default_sql, default_params = compiler.compile(self.default) + for case in self.cases: + try: + case_sql, case_params = compiler.compile(case) + except EmptyResultSet: + continue + except FullResultSet: + default_sql, default_params = compiler.compile(case.result) + break + case_parts.append(case_sql) + sql_params.extend(case_params) + if not case_parts: + return default_sql, default_params + case_joiner = case_joiner or self.case_joiner + template_params["cases"] = case_joiner.join(case_parts) + template_params["default"] = default_sql + sql_params.extend(default_params) + template = template or template_params.get("template", self.template) + sql = template % template_params + if self._output_field_or_none is not None: + sql = connection.ops.unification_cast_sql(self.output_field) % sql + return sql, sql_params + + def get_group_by_cols(self): + if not self.cases: + return self.default.get_group_by_cols() + return super().get_group_by_cols() + + @cached_property + def allowed_default(self): + return self.default.allowed_default and all( + case_.allowed_default for case_ in self.cases + ) + + +class Subquery(BaseExpression, Combinable): + """ + An explicit subquery. It may contain OuterRef() references to the outer + query which will be resolved when it is applied to that query. + """ + + template = "(%(subquery)s)" + contains_aggregate = False + empty_result_set_value = None + subquery = True + + def __init__(self, queryset, output_field=None, **extra): + # Allow the usage of both QuerySet and sql.Query objects. + self.query = getattr(queryset, "query", queryset).clone() + self.query.subquery = True + self.extra = extra + super().__init__(output_field) + + def get_source_expressions(self): + return [self.query] + + def set_source_expressions(self, exprs): + self.query = exprs[0] + + def _resolve_output_field(self): + return self.query.output_field + + def copy(self): + clone = super().copy() + clone.query = clone.query.clone() + return clone + + @property + def external_aliases(self): + return self.query.external_aliases + + def get_external_cols(self): + return self.query.get_external_cols() + + def as_sql(self, compiler, connection, template=None, **extra_context): + connection.ops.check_expression_support(self) + template_params = {**self.extra, **extra_context} + subquery_sql, sql_params = self.query.as_sql(compiler, connection) + template_params["subquery"] = subquery_sql[1:-1] + + template = template or template_params.get("template", self.template) + sql = template % template_params + return sql, sql_params + + def get_group_by_cols(self): + return self.query.get_group_by_cols(wrapper=self) + + +class Exists(Subquery): + template = "EXISTS(%(subquery)s)" + output_field = fields.BooleanField() + empty_result_set_value = False + + def __init__(self, queryset, **kwargs): + super().__init__(queryset, **kwargs) + self.query = self.query.exists() + + def select_format(self, compiler, sql, params): + # Wrap EXISTS() with a CASE WHEN expression if a database backend + # (e.g. Oracle) doesn't support boolean expression in SELECT or GROUP + # BY list. + if not compiler.connection.features.supports_boolean_expr_in_select_clause: + sql = "CASE WHEN {} THEN 1 ELSE 0 END".format(sql) + return sql, params + + def as_sql(self, compiler, *args, **kwargs): + try: + return super().as_sql(compiler, *args, **kwargs) + except EmptyResultSet: + features = compiler.connection.features + if not features.supports_boolean_expr_in_select_clause: + return "1=0", () + return compiler.compile(Value(False)) + + +@deconstructible(path="django.db.models.OrderBy") +class OrderBy(Expression): + template = "%(expression)s %(ordering)s" + conditional = False + + def __init__(self, expression, descending=False, nulls_first=None, nulls_last=None): + if nulls_first and nulls_last: + raise ValueError("nulls_first and nulls_last are mutually exclusive") + if nulls_first is False or nulls_last is False: + raise ValueError("nulls_first and nulls_last values must be True or None.") + self.nulls_first = nulls_first + self.nulls_last = nulls_last + self.descending = descending + if not hasattr(expression, "resolve_expression"): + raise ValueError("expression must be an expression type") + self.expression = expression + + def __repr__(self): + return "{}({}, descending={})".format( + self.__class__.__name__, self.expression, self.descending + ) + + def set_source_expressions(self, exprs): + self.expression = exprs[0] + + def get_source_expressions(self): + return [self.expression] + + def as_sql(self, compiler, connection, template=None, **extra_context): + template = template or self.template + if connection.features.supports_order_by_nulls_modifier: + if self.nulls_last: + template = "%s NULLS LAST" % template + elif self.nulls_first: + template = "%s NULLS FIRST" % template + else: + if self.nulls_last and not ( + self.descending and connection.features.order_by_nulls_first + ): + template = "%%(expression)s IS NULL, %s" % template + elif self.nulls_first and not ( + not self.descending and connection.features.order_by_nulls_first + ): + template = "%%(expression)s IS NOT NULL, %s" % template + connection.ops.check_expression_support(self) + expression_sql, params = compiler.compile(self.expression) + placeholders = { + "expression": expression_sql, + "ordering": "DESC" if self.descending else "ASC", + **extra_context, + } + params *= template.count("%(expression)s") + return (template % placeholders).rstrip(), params + + def as_oracle(self, compiler, connection): + # Oracle doesn't allow ORDER BY EXISTS() or filters unless it's wrapped + # in a CASE WHEN. + if connection.ops.conditional_expression_supported_in_where_clause( + self.expression + ): + copy = self.copy() + copy.expression = Case( + When(self.expression, then=True), + default=False, + ) + return copy.as_sql(compiler, connection) + return self.as_sql(compiler, connection) + + def get_group_by_cols(self): + cols = [] + for source in self.get_source_expressions(): + cols.extend(source.get_group_by_cols()) + return cols + + def reverse_ordering(self): + self.descending = not self.descending + if self.nulls_first: + self.nulls_last = True + self.nulls_first = None + elif self.nulls_last: + self.nulls_first = True + self.nulls_last = None + return self + + def asc(self): + self.descending = False + + def desc(self): + self.descending = True + + +class Window(SQLiteNumericMixin, Expression): + template = "%(expression)s OVER (%(window)s)" + # Although the main expression may either be an aggregate or an + # expression with an aggregate function, the GROUP BY that will + # be introduced in the query as a result is not desired. + contains_aggregate = False + contains_over_clause = True + + def __init__( + self, + expression, + partition_by=None, + order_by=None, + frame=None, + output_field=None, + ): + self.partition_by = partition_by + self.order_by = order_by + self.frame = frame + + if not getattr(expression, "window_compatible", False): + raise ValueError( + "Expression '%s' isn't compatible with OVER clauses." + % expression.__class__.__name__ + ) + + if self.partition_by is not None: + if not isinstance(self.partition_by, (tuple, list)): + self.partition_by = (self.partition_by,) + self.partition_by = ExpressionList(*self.partition_by) + + if self.order_by is not None: + if isinstance(self.order_by, (list, tuple)): + self.order_by = OrderByList(*self.order_by) + elif isinstance(self.order_by, (BaseExpression, str)): + self.order_by = OrderByList(self.order_by) + else: + raise ValueError( + "Window.order_by must be either a string reference to a " + "field, an expression, or a list or tuple of them." + ) + super().__init__(output_field=output_field) + self.source_expression = self._parse_expressions(expression)[0] + + def _resolve_output_field(self): + return self.source_expression.output_field + + def get_source_expressions(self): + return [self.source_expression, self.partition_by, self.order_by, self.frame] + + def set_source_expressions(self, exprs): + self.source_expression, self.partition_by, self.order_by, self.frame = exprs + + def as_sql(self, compiler, connection, template=None): + connection.ops.check_expression_support(self) + if not connection.features.supports_over_clause: + raise NotSupportedError("This backend does not support window expressions.") + expr_sql, params = compiler.compile(self.source_expression) + window_sql, window_params = [], () + + if self.partition_by is not None: + sql_expr, sql_params = self.partition_by.as_sql( + compiler=compiler, + connection=connection, + template="PARTITION BY %(expressions)s", + ) + window_sql.append(sql_expr) + window_params += tuple(sql_params) + + if self.order_by is not None: + order_sql, order_params = compiler.compile(self.order_by) + window_sql.append(order_sql) + window_params += tuple(order_params) + + if self.frame: + frame_sql, frame_params = compiler.compile(self.frame) + window_sql.append(frame_sql) + window_params += tuple(frame_params) + + template = template or self.template + + return ( + template % {"expression": expr_sql, "window": " ".join(window_sql).strip()}, + (*params, *window_params), + ) + + def as_sqlite(self, compiler, connection): + if isinstance(self.output_field, fields.DecimalField): + # Casting to numeric must be outside of the window expression. + copy = self.copy() + source_expressions = copy.get_source_expressions() + source_expressions[0].output_field = fields.FloatField() + copy.set_source_expressions(source_expressions) + return super(Window, copy).as_sqlite(compiler, connection) + return self.as_sql(compiler, connection) + + def __str__(self): + return "{} OVER ({}{}{})".format( + str(self.source_expression), + "PARTITION BY " + str(self.partition_by) if self.partition_by else "", + str(self.order_by or ""), + str(self.frame or ""), + ) + + def __repr__(self): + return "<%s: %s>" % (self.__class__.__name__, self) + + def get_group_by_cols(self): + group_by_cols = [] + if self.partition_by: + group_by_cols.extend(self.partition_by.get_group_by_cols()) + if self.order_by is not None: + group_by_cols.extend(self.order_by.get_group_by_cols()) + return group_by_cols + + +class WindowFrame(Expression): + """ + Model the frame clause in window expressions. There are two types of frame + clauses which are subclasses, however, all processing and validation (by no + means intended to be complete) is done here. Thus, providing an end for a + frame is optional (the default is UNBOUNDED FOLLOWING, which is the last + row in the frame). + """ + + template = "%(frame_type)s BETWEEN %(start)s AND %(end)s" + + def __init__(self, start=None, end=None): + self.start = Value(start) + self.end = Value(end) + + def set_source_expressions(self, exprs): + self.start, self.end = exprs + + def get_source_expressions(self): + return [self.start, self.end] + + def as_sql(self, compiler, connection): + connection.ops.check_expression_support(self) + start, end = self.window_frame_start_end( + connection, self.start.value, self.end.value + ) + return ( + self.template + % { + "frame_type": self.frame_type, + "start": start, + "end": end, + }, + [], + ) + + def __repr__(self): + return "<%s: %s>" % (self.__class__.__name__, self) + + def get_group_by_cols(self): + return [] + + def __str__(self): + if self.start.value is not None and self.start.value < 0: + start = "%d %s" % (abs(self.start.value), connection.ops.PRECEDING) + elif self.start.value is not None and self.start.value == 0: + start = connection.ops.CURRENT_ROW + else: + start = connection.ops.UNBOUNDED_PRECEDING + + if self.end.value is not None and self.end.value > 0: + end = "%d %s" % (self.end.value, connection.ops.FOLLOWING) + elif self.end.value is not None and self.end.value == 0: + end = connection.ops.CURRENT_ROW + else: + end = connection.ops.UNBOUNDED_FOLLOWING + return self.template % { + "frame_type": self.frame_type, + "start": start, + "end": end, + } + + def window_frame_start_end(self, connection, start, end): + raise NotImplementedError("Subclasses must implement window_frame_start_end().") + + +class RowRange(WindowFrame): + frame_type = "ROWS" + + def window_frame_start_end(self, connection, start, end): + return connection.ops.window_frame_rows_start_end(start, end) + + +class ValueRange(WindowFrame): + frame_type = "RANGE" + + def window_frame_start_end(self, connection, start, end): + return connection.ops.window_frame_range_start_end(start, end) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/fields/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/fields/__init__.py new file mode 100644 index 0000000..ce3bebb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/fields/__init__.py @@ -0,0 +1,2871 @@ +import copy +import datetime +import decimal +import operator +import uuid +import warnings +from base64 import b64decode, b64encode +from functools import partialmethod, total_ordering + +from django import forms +from django.apps import apps +from django.conf import settings +from django.core import checks, exceptions, validators +from django.db import connection, connections, router +from django.db.models.constants import LOOKUP_SEP +from django.db.models.query_utils import DeferredAttribute, RegisterLookupMixin +from django.utils import timezone +from django.utils.choices import ( + BlankChoiceIterator, + CallableChoiceIterator, + flatten_choices, + normalize_choices, +) +from django.utils.datastructures import DictWrapper +from django.utils.dateparse import ( + parse_date, + parse_datetime, + parse_duration, + parse_time, +) +from django.utils.duration import duration_microseconds, duration_string +from django.utils.functional import Promise, cached_property +from django.utils.ipv6 import clean_ipv6_address +from django.utils.itercompat import is_iterable +from django.utils.text import capfirst +from django.utils.translation import gettext_lazy as _ + +__all__ = [ + "AutoField", + "BLANK_CHOICE_DASH", + "BigAutoField", + "BigIntegerField", + "BinaryField", + "BooleanField", + "CharField", + "CommaSeparatedIntegerField", + "DateField", + "DateTimeField", + "DecimalField", + "DurationField", + "EmailField", + "Empty", + "Field", + "FilePathField", + "FloatField", + "GenericIPAddressField", + "IPAddressField", + "IntegerField", + "NOT_PROVIDED", + "NullBooleanField", + "PositiveBigIntegerField", + "PositiveIntegerField", + "PositiveSmallIntegerField", + "SlugField", + "SmallAutoField", + "SmallIntegerField", + "TextField", + "TimeField", + "URLField", + "UUIDField", +] + + +class Empty: + pass + + +class NOT_PROVIDED: + pass + + +# The values to use for "blank" in SelectFields. Will be appended to the start +# of most "choices" lists. +BLANK_CHOICE_DASH = [("", "---------")] + + +def _load_field(app_label, model_name, field_name): + return apps.get_model(app_label, model_name)._meta.get_field(field_name) + + +# A guide to Field parameters: +# +# * name: The name of the field specified in the model. +# * attname: The attribute to use on the model object. This is the same as +# "name", except in the case of ForeignKeys, where "_id" is +# appended. +# * db_column: The db_column specified in the model (or None). +# * column: The database column for this field. This is the same as +# "attname", except if db_column is specified. +# +# Code that introspects values, or does other dynamic things, should use +# attname. For example, this gets the primary key value of object "obj": +# +# getattr(obj, opts.pk.attname) + + +def _empty(of_cls): + new = Empty() + new.__class__ = of_cls + return new + + +def return_None(): + return None + + +@total_ordering +class Field(RegisterLookupMixin): + """Base class for all field types""" + + # Designates whether empty strings fundamentally are allowed at the + # database level. + empty_strings_allowed = True + empty_values = list(validators.EMPTY_VALUES) + + # These track each time a Field instance is created. Used to retain order. + # The auto_creation_counter is used for fields that Django implicitly + # creates, creation_counter is used for all user-specified fields. + creation_counter = 0 + auto_creation_counter = -1 + default_validators = [] # Default set of validators + default_error_messages = { + "invalid_choice": _("Value %(value)r is not a valid choice."), + "null": _("This field cannot be null."), + "blank": _("This field cannot be blank."), + "unique": _("%(model_name)s with this %(field_label)s already exists."), + "unique_for_date": _( + # Translators: The 'lookup_type' is one of 'date', 'year' or + # 'month'. Eg: "Title must be unique for pub_date year" + "%(field_label)s must be unique for " + "%(date_field_label)s %(lookup_type)s." + ), + } + system_check_deprecated_details = None + system_check_removed_details = None + + # Attributes that don't affect a column definition. + # These attributes are ignored when altering the field. + non_db_attrs = ( + "blank", + "choices", + "db_column", + "editable", + "error_messages", + "help_text", + "limit_choices_to", + # Database-level options are not supported, see #21961. + "on_delete", + "related_name", + "related_query_name", + "validators", + "verbose_name", + ) + + # Field flags + hidden = False + + many_to_many = None + many_to_one = None + one_to_many = None + one_to_one = None + related_model = None + generated = False + + descriptor_class = DeferredAttribute + + # Generic field type description, usually overridden by subclasses + def _description(self): + return _("Field of type: %(field_type)s") % { + "field_type": self.__class__.__name__ + } + + description = property(_description) + + def __init__( + self, + verbose_name=None, + name=None, + primary_key=False, + max_length=None, + unique=False, + blank=False, + null=False, + db_index=False, + rel=None, + default=NOT_PROVIDED, + editable=True, + serialize=True, + unique_for_date=None, + unique_for_month=None, + unique_for_year=None, + choices=None, + help_text="", + db_column=None, + db_tablespace=None, + auto_created=False, + validators=(), + error_messages=None, + db_comment=None, + db_default=NOT_PROVIDED, + ): + self.name = name + self.verbose_name = verbose_name # May be set by set_attributes_from_name + self._verbose_name = verbose_name # Store original for deconstruction + self.primary_key = primary_key + self.max_length, self._unique = max_length, unique + self.blank, self.null = blank, null + self.remote_field = rel + self.is_relation = self.remote_field is not None + self.default = default + if db_default is not NOT_PROVIDED and not hasattr( + db_default, "resolve_expression" + ): + from django.db.models.expressions import Value + + db_default = Value(db_default) + self.db_default = db_default + self.editable = editable + self.serialize = serialize + self.unique_for_date = unique_for_date + self.unique_for_month = unique_for_month + self.unique_for_year = unique_for_year + self.choices = choices + self.help_text = help_text + self.db_index = db_index + self.db_column = db_column + self.db_comment = db_comment + self._db_tablespace = db_tablespace + self.auto_created = auto_created + + # Adjust the appropriate creation counter, and save our local copy. + if auto_created: + self.creation_counter = Field.auto_creation_counter + Field.auto_creation_counter -= 1 + else: + self.creation_counter = Field.creation_counter + Field.creation_counter += 1 + + self._validators = list(validators) # Store for deconstruction later + + self._error_messages = error_messages # Store for deconstruction later + + def __str__(self): + """ + Return "app_label.model_label.field_name" for fields attached to + models. + """ + if not hasattr(self, "model"): + return super().__str__() + model = self.model + return "%s.%s" % (model._meta.label, self.name) + + def __repr__(self): + """Display the module, class, and name of the field.""" + path = "%s.%s" % (self.__class__.__module__, self.__class__.__qualname__) + name = getattr(self, "name", None) + if name is not None: + return "<%s: %s>" % (path, name) + return "<%s>" % path + + def check(self, **kwargs): + return [ + *self._check_field_name(), + *self._check_choices(), + *self._check_db_default(**kwargs), + *self._check_db_index(), + *self._check_db_comment(**kwargs), + *self._check_null_allowed_for_primary_keys(), + *self._check_backend_specific_checks(**kwargs), + *self._check_validators(), + *self._check_deprecation_details(), + ] + + def _check_field_name(self): + """ + Check if field name is valid, i.e. 1) does not end with an + underscore, 2) does not contain "__" and 3) is not "pk". + """ + if self.name is None: + return [] + if self.name.endswith("_"): + return [ + checks.Error( + "Field names must not end with an underscore.", + obj=self, + id="fields.E001", + ) + ] + elif LOOKUP_SEP in self.name: + return [ + checks.Error( + 'Field names must not contain "%s".' % LOOKUP_SEP, + obj=self, + id="fields.E002", + ) + ] + elif self.name == "pk": + return [ + checks.Error( + "'pk' is a reserved word that cannot be used as a field name.", + obj=self, + id="fields.E003", + ) + ] + else: + return [] + + @classmethod + def _choices_is_value(cls, value): + return isinstance(value, (str, Promise)) or not is_iterable(value) + + def _check_choices(self): + if not self.choices: + return [] + + if not is_iterable(self.choices) or isinstance(self.choices, str): + return [ + checks.Error( + "'choices' must be a mapping (e.g. a dictionary) or an iterable " + "(e.g. a list or tuple).", + obj=self, + id="fields.E004", + ) + ] + + choice_max_length = 0 + # Expect [group_name, [value, display]] + for choices_group in self.choices: + try: + group_name, group_choices = choices_group + except (TypeError, ValueError): + # Containing non-pairs + break + try: + if not all( + self._choices_is_value(value) and self._choices_is_value(human_name) + for value, human_name in group_choices + ): + break + if self.max_length is not None and group_choices: + choice_max_length = max( + [ + choice_max_length, + *( + len(value) + for value, _ in group_choices + if isinstance(value, str) + ), + ] + ) + except (TypeError, ValueError): + # No groups, choices in the form [value, display] + value, human_name = group_name, group_choices + if not self._choices_is_value(value) or not self._choices_is_value( + human_name + ): + break + if self.max_length is not None and isinstance(value, str): + choice_max_length = max(choice_max_length, len(value)) + + # Special case: choices=['ab'] + if isinstance(choices_group, str): + break + else: + if self.max_length is not None and choice_max_length > self.max_length: + return [ + checks.Error( + "'max_length' is too small to fit the longest value " + "in 'choices' (%d characters)." % choice_max_length, + obj=self, + id="fields.E009", + ), + ] + return [] + + return [ + checks.Error( + "'choices' must be a mapping of actual values to human readable names " + "or an iterable containing (actual value, human readable name) tuples.", + obj=self, + id="fields.E005", + ) + ] + + def _check_db_default(self, databases=None, **kwargs): + from django.db.models.expressions import Value + + if ( + self.db_default is NOT_PROVIDED + or isinstance(self.db_default, Value) + or databases is None + ): + return [] + errors = [] + for db in databases: + if not router.allow_migrate_model(db, self.model): + continue + connection = connections[db] + + if not getattr(self.db_default, "allowed_default", False) and ( + connection.features.supports_expression_defaults + ): + msg = f"{self.db_default} cannot be used in db_default." + errors.append(checks.Error(msg, obj=self, id="fields.E012")) + + if not ( + connection.features.supports_expression_defaults + or "supports_expression_defaults" + in self.model._meta.required_db_features + ): + msg = ( + f"{connection.display_name} does not support default database " + "values with expressions (db_default)." + ) + errors.append(checks.Error(msg, obj=self, id="fields.E011")) + return errors + + def _check_db_index(self): + if self.db_index not in (None, True, False): + return [ + checks.Error( + "'db_index' must be None, True or False.", + obj=self, + id="fields.E006", + ) + ] + else: + return [] + + def _check_db_comment(self, databases=None, **kwargs): + if not self.db_comment or not databases: + return [] + errors = [] + for db in databases: + if not router.allow_migrate_model(db, self.model): + continue + connection = connections[db] + if not ( + connection.features.supports_comments + or "supports_comments" in self.model._meta.required_db_features + ): + errors.append( + checks.Warning( + f"{connection.display_name} does not support comments on " + f"columns (db_comment).", + obj=self, + id="fields.W163", + ) + ) + return errors + + def _check_null_allowed_for_primary_keys(self): + if ( + self.primary_key + and self.null + and not connection.features.interprets_empty_strings_as_nulls + ): + # We cannot reliably check this for backends like Oracle which + # consider NULL and '' to be equal (and thus set up + # character-based fields a little differently). + return [ + checks.Error( + "Primary keys must not have null=True.", + hint=( + "Set null=False on the field, or " + "remove primary_key=True argument." + ), + obj=self, + id="fields.E007", + ) + ] + else: + return [] + + def _check_backend_specific_checks(self, databases=None, **kwargs): + if databases is None: + return [] + errors = [] + for alias in databases: + if router.allow_migrate_model(alias, self.model): + errors.extend(connections[alias].validation.check_field(self, **kwargs)) + return errors + + def _check_validators(self): + errors = [] + for i, validator in enumerate(self.validators): + if not callable(validator): + errors.append( + checks.Error( + "All 'validators' must be callable.", + hint=( + "validators[{i}] ({repr}) isn't a function or " + "instance of a validator class.".format( + i=i, + repr=repr(validator), + ) + ), + obj=self, + id="fields.E008", + ) + ) + return errors + + def _check_deprecation_details(self): + if self.system_check_removed_details is not None: + return [ + checks.Error( + self.system_check_removed_details.get( + "msg", + "%s has been removed except for support in historical " + "migrations." % self.__class__.__name__, + ), + hint=self.system_check_removed_details.get("hint"), + obj=self, + id=self.system_check_removed_details.get("id", "fields.EXXX"), + ) + ] + elif self.system_check_deprecated_details is not None: + return [ + checks.Warning( + self.system_check_deprecated_details.get( + "msg", "%s has been deprecated." % self.__class__.__name__ + ), + hint=self.system_check_deprecated_details.get("hint"), + obj=self, + id=self.system_check_deprecated_details.get("id", "fields.WXXX"), + ) + ] + return [] + + def get_col(self, alias, output_field=None): + if alias == self.model._meta.db_table and ( + output_field is None or output_field == self + ): + return self.cached_col + from django.db.models.expressions import Col + + return Col(alias, self, output_field) + + @property + def choices(self): + return self._choices + + @choices.setter + def choices(self, value): + self._choices = normalize_choices(value) + + @cached_property + def cached_col(self): + from django.db.models.expressions import Col + + return Col(self.model._meta.db_table, self) + + def select_format(self, compiler, sql, params): + """ + Custom format for select clauses. For example, GIS columns need to be + selected as AsText(table.col) on MySQL as the table.col data can't be + used by Django. + """ + return sql, params + + def deconstruct(self): + """ + Return enough information to recreate the field as a 4-tuple: + + * The name of the field on the model, if contribute_to_class() has + been run. + * The import path of the field, including the class, e.g. + django.db.models.IntegerField. This should be the most portable + version, so less specific may be better. + * A list of positional arguments. + * A dict of keyword arguments. + + Note that the positional or keyword arguments must contain values of + the following types (including inner values of collection types): + + * None, bool, str, int, float, complex, set, frozenset, list, tuple, + dict + * UUID + * datetime.datetime (naive), datetime.date + * top-level classes, top-level functions - will be referenced by their + full import path + * Storage instances - these have their own deconstruct() method + + This is because the values here must be serialized into a text format + (possibly new Python code, possibly JSON) and these are the only types + with encoding handlers defined. + + There's no need to return the exact way the field was instantiated this + time, just ensure that the resulting field is the same - prefer keyword + arguments over positional ones, and omit parameters with their default + values. + """ + # Short-form way of fetching all the default parameters + keywords = {} + possibles = { + "verbose_name": None, + "primary_key": False, + "max_length": None, + "unique": False, + "blank": False, + "null": False, + "db_index": False, + "default": NOT_PROVIDED, + "db_default": NOT_PROVIDED, + "editable": True, + "serialize": True, + "unique_for_date": None, + "unique_for_month": None, + "unique_for_year": None, + "choices": None, + "help_text": "", + "db_column": None, + "db_comment": None, + "db_tablespace": None, + "auto_created": False, + "validators": [], + "error_messages": None, + } + attr_overrides = { + "unique": "_unique", + "error_messages": "_error_messages", + "validators": "_validators", + "verbose_name": "_verbose_name", + "db_tablespace": "_db_tablespace", + } + equals_comparison = {"choices", "validators"} + for name, default in possibles.items(): + value = getattr(self, attr_overrides.get(name, name)) + if isinstance(value, CallableChoiceIterator): + value = value.func + # Do correct kind of comparison + if name in equals_comparison: + if value != default: + keywords[name] = value + else: + if value is not default: + keywords[name] = value + # Work out path - we shorten it for known Django core fields + path = "%s.%s" % (self.__class__.__module__, self.__class__.__qualname__) + if path.startswith("django.db.models.fields.related"): + path = path.replace("django.db.models.fields.related", "django.db.models") + elif path.startswith("django.db.models.fields.files"): + path = path.replace("django.db.models.fields.files", "django.db.models") + elif path.startswith("django.db.models.fields.generated"): + path = path.replace("django.db.models.fields.generated", "django.db.models") + elif path.startswith("django.db.models.fields.json"): + path = path.replace("django.db.models.fields.json", "django.db.models") + elif path.startswith("django.db.models.fields.proxy"): + path = path.replace("django.db.models.fields.proxy", "django.db.models") + elif path.startswith("django.db.models.fields"): + path = path.replace("django.db.models.fields", "django.db.models") + # Return basic info - other fields should override this. + return (self.name, path, [], keywords) + + def clone(self): + """ + Uses deconstruct() to clone a new copy of this Field. + Will not preserve any class attachments/attribute names. + """ + name, path, args, kwargs = self.deconstruct() + return self.__class__(*args, **kwargs) + + def __eq__(self, other): + # Needed for @total_ordering + if isinstance(other, Field): + return self.creation_counter == other.creation_counter and getattr( + self, "model", None + ) == getattr(other, "model", None) + return NotImplemented + + def __lt__(self, other): + # This is needed because bisect does not take a comparison function. + # Order by creation_counter first for backward compatibility. + if isinstance(other, Field): + if ( + self.creation_counter != other.creation_counter + or not hasattr(self, "model") + and not hasattr(other, "model") + ): + return self.creation_counter < other.creation_counter + elif hasattr(self, "model") != hasattr(other, "model"): + return not hasattr(self, "model") # Order no-model fields first + else: + # creation_counter's are equal, compare only models. + return (self.model._meta.app_label, self.model._meta.model_name) < ( + other.model._meta.app_label, + other.model._meta.model_name, + ) + return NotImplemented + + def __hash__(self): + return hash(self.creation_counter) + + def __deepcopy__(self, memodict): + # We don't have to deepcopy very much here, since most things are not + # intended to be altered after initial creation. + obj = copy.copy(self) + if self.remote_field: + obj.remote_field = copy.copy(self.remote_field) + if hasattr(self.remote_field, "field") and self.remote_field.field is self: + obj.remote_field.field = obj + memodict[id(self)] = obj + return obj + + def __copy__(self): + # We need to avoid hitting __reduce__, so define this + # slightly weird copy construct. + obj = Empty() + obj.__class__ = self.__class__ + obj.__dict__ = self.__dict__.copy() + return obj + + def __reduce__(self): + """ + Pickling should return the model._meta.fields instance of the field, + not a new copy of that field. So, use the app registry to load the + model and then the field back. + """ + if not hasattr(self, "model"): + # Fields are sometimes used without attaching them to models (for + # example in aggregation). In this case give back a plain field + # instance. The code below will create a new empty instance of + # class self.__class__, then update its dict with self.__dict__ + # values - so, this is very close to normal pickle. + state = self.__dict__.copy() + # The _get_default cached_property can't be pickled due to lambda + # usage. + state.pop("_get_default", None) + return _empty, (self.__class__,), state + return _load_field, ( + self.model._meta.app_label, + self.model._meta.object_name, + self.name, + ) + + def get_pk_value_on_save(self, instance): + """ + Hook to generate new PK values on save. This method is called when + saving instances with no primary key value set. If this method returns + something else than None, then the returned value is used when saving + the new instance. + """ + if self.default: + return self.get_default() + return None + + def to_python(self, value): + """ + Convert the input value into the expected Python data type, raising + django.core.exceptions.ValidationError if the data can't be converted. + Return the converted value. Subclasses should override this. + """ + return value + + @cached_property + def error_messages(self): + messages = {} + for c in reversed(self.__class__.__mro__): + messages.update(getattr(c, "default_error_messages", {})) + messages.update(self._error_messages or {}) + return messages + + @cached_property + def validators(self): + """ + Some validators can't be created at field initialization time. + This method provides a way to delay their creation until required. + """ + return [*self.default_validators, *self._validators] + + def run_validators(self, value): + if value in self.empty_values: + return + + errors = [] + for v in self.validators: + try: + v(value) + except exceptions.ValidationError as e: + if hasattr(e, "code") and e.code in self.error_messages: + e.message = self.error_messages[e.code] + errors.extend(e.error_list) + + if errors: + raise exceptions.ValidationError(errors) + + def validate(self, value, model_instance): + """ + Validate value and raise ValidationError if necessary. Subclasses + should override this to provide validation logic. + """ + if not self.editable: + # Skip validation for non-editable fields. + return + + if self.choices is not None and value not in self.empty_values: + for option_key, option_value in self.choices: + if isinstance(option_value, (list, tuple)): + # This is an optgroup, so look inside the group for + # options. + for optgroup_key, optgroup_value in option_value: + if value == optgroup_key: + return + elif value == option_key: + return + raise exceptions.ValidationError( + self.error_messages["invalid_choice"], + code="invalid_choice", + params={"value": value}, + ) + + if value is None and not self.null: + raise exceptions.ValidationError(self.error_messages["null"], code="null") + + if not self.blank and value in self.empty_values: + raise exceptions.ValidationError(self.error_messages["blank"], code="blank") + + def clean(self, value, model_instance): + """ + Convert the value's type and run validation. Validation errors + from to_python() and validate() are propagated. Return the correct + value if no error is raised. + """ + value = self.to_python(value) + self.validate(value, model_instance) + self.run_validators(value) + return value + + def db_type_parameters(self, connection): + return DictWrapper(self.__dict__, connection.ops.quote_name, "qn_") + + def db_check(self, connection): + """ + Return the database column check constraint for this field, for the + provided connection. Works the same way as db_type() for the case that + get_internal_type() does not map to a preexisting model field. + """ + data = self.db_type_parameters(connection) + try: + return ( + connection.data_type_check_constraints[self.get_internal_type()] % data + ) + except KeyError: + return None + + def db_type(self, connection): + """ + Return the database column data type for this field, for the provided + connection. + """ + # The default implementation of this method looks at the + # backend-specific data_types dictionary, looking up the field by its + # "internal type". + # + # A Field class can implement the get_internal_type() method to specify + # which *preexisting* Django Field class it's most similar to -- i.e., + # a custom field might be represented by a TEXT column type, which is + # the same as the TextField Django field type, which means the custom + # field's get_internal_type() returns 'TextField'. + # + # But the limitation of the get_internal_type() / data_types approach + # is that it cannot handle database column types that aren't already + # mapped to one of the built-in Django field types. In this case, you + # can implement db_type() instead of get_internal_type() to specify + # exactly which wacky database column type you want to use. + data = self.db_type_parameters(connection) + try: + column_type = connection.data_types[self.get_internal_type()] + except KeyError: + return None + else: + # column_type is either a single-parameter function or a string. + if callable(column_type): + return column_type(data) + return column_type % data + + def rel_db_type(self, connection): + """ + Return the data type that a related field pointing to this field should + use. For example, this method is called by ForeignKey and OneToOneField + to determine its data type. + """ + return self.db_type(connection) + + def cast_db_type(self, connection): + """Return the data type to use in the Cast() function.""" + db_type = connection.ops.cast_data_types.get(self.get_internal_type()) + if db_type: + return db_type % self.db_type_parameters(connection) + return self.db_type(connection) + + def db_parameters(self, connection): + """ + Extension of db_type(), providing a range of different return values + (type, checks). This will look at db_type(), allowing custom model + fields to override it. + """ + type_string = self.db_type(connection) + check_string = self.db_check(connection) + return { + "type": type_string, + "check": check_string, + } + + def db_type_suffix(self, connection): + return connection.data_types_suffix.get(self.get_internal_type()) + + def get_db_converters(self, connection): + if hasattr(self, "from_db_value"): + return [self.from_db_value] + return [] + + @property + def unique(self): + return self._unique or self.primary_key + + @property + def db_tablespace(self): + return self._db_tablespace or settings.DEFAULT_INDEX_TABLESPACE + + @property + def db_returning(self): + """Private API intended only to be used by Django itself.""" + return ( + self.db_default is not NOT_PROVIDED + and connection.features.can_return_columns_from_insert + ) + + def set_attributes_from_name(self, name): + self.name = self.name or name + self.attname, self.column = self.get_attname_column() + self.concrete = self.column is not None + if self.verbose_name is None and self.name: + self.verbose_name = self.name.replace("_", " ") + + def contribute_to_class(self, cls, name, private_only=False): + """ + Register the field with the model class it belongs to. + + If private_only is True, create a separate instance of this field + for every subclass of cls, even if cls is not an abstract model. + """ + self.set_attributes_from_name(name) + self.model = cls + cls._meta.add_field(self, private=private_only) + if self.column: + setattr(cls, self.attname, self.descriptor_class(self)) + if self.choices is not None: + # Don't override a get_FOO_display() method defined explicitly on + # this class, but don't check methods derived from inheritance, to + # allow overriding inherited choices. For more complex inheritance + # structures users should override contribute_to_class(). + if "get_%s_display" % self.name not in cls.__dict__: + setattr( + cls, + "get_%s_display" % self.name, + partialmethod(cls._get_FIELD_display, field=self), + ) + + def get_filter_kwargs_for_object(self, obj): + """ + Return a dict that when passed as kwargs to self.model.filter(), would + yield all instances having the same value for this field as obj has. + """ + return {self.name: getattr(obj, self.attname)} + + def get_attname(self): + return self.name + + def get_attname_column(self): + attname = self.get_attname() + column = self.db_column or attname + return attname, column + + def get_internal_type(self): + return self.__class__.__name__ + + def pre_save(self, model_instance, add): + """Return field's value just before saving.""" + value = getattr(model_instance, self.attname) + if not connection.features.supports_default_keyword_in_insert: + from django.db.models.expressions import DatabaseDefault + + if isinstance(value, DatabaseDefault): + return self.db_default + return value + + def get_prep_value(self, value): + """Perform preliminary non-db specific value checks and conversions.""" + if isinstance(value, Promise): + value = value._proxy____cast() + return value + + def get_db_prep_value(self, value, connection, prepared=False): + """ + Return field's value prepared for interacting with the database backend. + + Used by the default implementations of get_db_prep_save(). + """ + if not prepared: + value = self.get_prep_value(value) + return value + + def get_db_prep_save(self, value, connection): + """Return field's value prepared for saving into a database.""" + if hasattr(value, "as_sql"): + return value + return self.get_db_prep_value(value, connection=connection, prepared=False) + + def has_default(self): + """Return a boolean of whether this field has a default value.""" + return self.default is not NOT_PROVIDED + + def get_default(self): + """Return the default value for this field.""" + return self._get_default() + + @cached_property + def _get_default(self): + if self.has_default(): + if callable(self.default): + return self.default + return lambda: self.default + + if self.db_default is not NOT_PROVIDED: + from django.db.models.expressions import DatabaseDefault + + return DatabaseDefault + + if ( + not self.empty_strings_allowed + or self.null + and not connection.features.interprets_empty_strings_as_nulls + ): + return return_None + return str # return empty string + + def get_choices( + self, + include_blank=True, + blank_choice=BLANK_CHOICE_DASH, + limit_choices_to=None, + ordering=(), + ): + """ + Return choices with a default blank choices included, for use + as choices for this field. + + Analog of django.db.models.fields.Field.get_choices(), provided + initially for utilization by RelatedFieldListFilter. + """ + limit_choices_to = limit_choices_to or self.limit_choices_to + qs = self.related_model._default_manager.complex_filter(limit_choices_to) + if ordering: + qs = qs.order_by(*ordering) + return (blank_choice if include_blank else []) + [(x.pk, str(x)) for x in qs] + + def is_hidden(self): + """Should the related object be hidden?""" + return bool(self.related_name) and self.related_name[-1] == "+" + + def get_joining_columns(self): + warnings.warn( + "ForeignObjectRel.get_joining_columns() is deprecated. Use " + "get_joining_fields() instead.", + RemovedInDjango60Warning, + ) + return self.field.get_reverse_joining_columns() + + def get_joining_fields(self): + return self.field.get_reverse_joining_fields() + + def get_extra_restriction(self, alias, related_alias): + return self.field.get_extra_restriction(related_alias, alias) + + def set_field_name(self): + """ + Set the related field's name, this is not available until later stages + of app loading, so set_field_name is called from + set_attributes_from_rel() + """ + # By default foreign object doesn't relate to any remote field (for + # example custom multicolumn joins currently have no remote field). + self.field_name = None + + def get_accessor_name(self, model=None): + # This method encapsulates the logic that decides what name to give an + # accessor descriptor that retrieves related many-to-one or + # many-to-many objects. It uses the lowercased object_name + "_set", + # but this can be overridden with the "related_name" option. Due to + # backwards compatibility ModelForms need to be able to provide an + # alternate model. See BaseInlineFormSet.get_default_prefix(). + opts = model._meta if model else self.related_model._meta + model = model or self.related_model + if self.multiple: + # If this is a symmetrical m2m relation on self, there is no + # reverse accessor. + if self.symmetrical and model == self.model: + return None + if self.related_name: + return self.related_name + return opts.model_name + ("_set" if self.multiple else "") + + def get_path_info(self, filtered_relation=None): + if filtered_relation: + return self.field.get_reverse_path_info(filtered_relation) + else: + return self.field.reverse_path_infos + + @cached_property + def path_infos(self): + return self.get_path_info() + + def get_cache_name(self): + """ + Return the name of the cache key to use for storing an instance of the + forward model on the reverse model. + """ + return self.get_accessor_name() + + +class ManyToOneRel(ForeignObjectRel): + """ + Used by the ForeignKey field to store information about the relation. + + ``_meta.get_fields()`` returns this class to provide access to the field + flags for the reverse relation. + + Note: Because we somewhat abuse the Rel objects by using them as reverse + fields we get the funny situation where + ``ManyToOneRel.many_to_one == False`` and + ``ManyToOneRel.one_to_many == True``. This is unfortunate but the actual + ManyToOneRel class is a private API and there is work underway to turn + reverse relations into actual fields. + """ + + def __init__( + self, + field, + to, + field_name, + related_name=None, + related_query_name=None, + limit_choices_to=None, + parent_link=False, + on_delete=None, + ): + super().__init__( + field, + to, + related_name=related_name, + related_query_name=related_query_name, + limit_choices_to=limit_choices_to, + parent_link=parent_link, + on_delete=on_delete, + ) + + self.field_name = field_name + + def __getstate__(self): + state = super().__getstate__() + state.pop("related_model", None) + return state + + @property + def identity(self): + return super().identity + (self.field_name,) + + def get_related_field(self): + """ + Return the Field in the 'to' object to which this relationship is tied. + """ + field = self.model._meta.get_field(self.field_name) + if not field.concrete: + raise exceptions.FieldDoesNotExist( + "No related field named '%s'" % self.field_name + ) + return field + + def set_field_name(self): + self.field_name = self.field_name or self.model._meta.pk.name + + +class OneToOneRel(ManyToOneRel): + """ + Used by OneToOneField to store information about the relation. + + ``_meta.get_fields()`` returns this class to provide access to the field + flags for the reverse relation. + """ + + def __init__( + self, + field, + to, + field_name, + related_name=None, + related_query_name=None, + limit_choices_to=None, + parent_link=False, + on_delete=None, + ): + super().__init__( + field, + to, + field_name, + related_name=related_name, + related_query_name=related_query_name, + limit_choices_to=limit_choices_to, + parent_link=parent_link, + on_delete=on_delete, + ) + + self.multiple = False + + +class ManyToManyRel(ForeignObjectRel): + """ + Used by ManyToManyField to store information about the relation. + + ``_meta.get_fields()`` returns this class to provide access to the field + flags for the reverse relation. + """ + + def __init__( + self, + field, + to, + related_name=None, + related_query_name=None, + limit_choices_to=None, + symmetrical=True, + through=None, + through_fields=None, + db_constraint=True, + ): + super().__init__( + field, + to, + related_name=related_name, + related_query_name=related_query_name, + limit_choices_to=limit_choices_to, + ) + + if through and not db_constraint: + raise ValueError("Can't supply a through model and db_constraint=False") + self.through = through + + if through_fields and not through: + raise ValueError("Cannot specify through_fields without a through model") + self.through_fields = through_fields + + self.symmetrical = symmetrical + self.db_constraint = db_constraint + + @property + def identity(self): + return super().identity + ( + self.through, + make_hashable(self.through_fields), + self.db_constraint, + ) + + def get_related_field(self): + """ + Return the field in the 'to' object to which this relationship is tied. + Provided for symmetry with ManyToOneRel. + """ + opts = self.through._meta + if self.through_fields: + field = opts.get_field(self.through_fields[0]) + else: + for field in opts.fields: + rel = getattr(field, "remote_field", None) + if rel and rel.model == self.model: + break + return field.foreign_related_fields[0] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/functions/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/functions/__init__.py new file mode 100644 index 0000000..cd7c801 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/functions/__init__.py @@ -0,0 +1,190 @@ +from .comparison import Cast, Coalesce, Collate, Greatest, JSONObject, Least, NullIf +from .datetime import ( + Extract, + ExtractDay, + ExtractHour, + ExtractIsoWeekDay, + ExtractIsoYear, + ExtractMinute, + ExtractMonth, + ExtractQuarter, + ExtractSecond, + ExtractWeek, + ExtractWeekDay, + ExtractYear, + Now, + Trunc, + TruncDate, + TruncDay, + TruncHour, + TruncMinute, + TruncMonth, + TruncQuarter, + TruncSecond, + TruncTime, + TruncWeek, + TruncYear, +) +from .math import ( + Abs, + ACos, + ASin, + ATan, + ATan2, + Ceil, + Cos, + Cot, + Degrees, + Exp, + Floor, + Ln, + Log, + Mod, + Pi, + Power, + Radians, + Random, + Round, + Sign, + Sin, + Sqrt, + Tan, +) +from .text import ( + MD5, + SHA1, + SHA224, + SHA256, + SHA384, + SHA512, + Chr, + Concat, + ConcatPair, + Left, + Length, + Lower, + LPad, + LTrim, + Ord, + Repeat, + Replace, + Reverse, + Right, + RPad, + RTrim, + StrIndex, + Substr, + Trim, + Upper, +) +from .window import ( + CumeDist, + DenseRank, + FirstValue, + Lag, + LastValue, + Lead, + NthValue, + Ntile, + PercentRank, + Rank, + RowNumber, +) + +__all__ = [ + # comparison and conversion + "Cast", + "Coalesce", + "Collate", + "Greatest", + "JSONObject", + "Least", + "NullIf", + # datetime + "Extract", + "ExtractDay", + "ExtractHour", + "ExtractMinute", + "ExtractMonth", + "ExtractQuarter", + "ExtractSecond", + "ExtractWeek", + "ExtractIsoWeekDay", + "ExtractWeekDay", + "ExtractIsoYear", + "ExtractYear", + "Now", + "Trunc", + "TruncDate", + "TruncDay", + "TruncHour", + "TruncMinute", + "TruncMonth", + "TruncQuarter", + "TruncSecond", + "TruncTime", + "TruncWeek", + "TruncYear", + # math + "Abs", + "ACos", + "ASin", + "ATan", + "ATan2", + "Ceil", + "Cos", + "Cot", + "Degrees", + "Exp", + "Floor", + "Ln", + "Log", + "Mod", + "Pi", + "Power", + "Radians", + "Random", + "Round", + "Sign", + "Sin", + "Sqrt", + "Tan", + # text + "MD5", + "SHA1", + "SHA224", + "SHA256", + "SHA384", + "SHA512", + "Chr", + "Concat", + "ConcatPair", + "Left", + "Length", + "Lower", + "LPad", + "LTrim", + "Ord", + "Repeat", + "Replace", + "Reverse", + "Right", + "RPad", + "RTrim", + "StrIndex", + "Substr", + "Trim", + "Upper", + # window + "CumeDist", + "DenseRank", + "FirstValue", + "Lag", + "LastValue", + "Lead", + "NthValue", + "Ntile", + "PercentRank", + "Rank", + "RowNumber", +] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/functions/comparison.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/functions/comparison.py new file mode 100644 index 0000000..eec2ab7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/functions/comparison.py @@ -0,0 +1,221 @@ +"""Database functions that do comparisons or type conversions.""" +from django.db import NotSupportedError +from django.db.models.expressions import Func, Value +from django.db.models.fields import TextField +from django.db.models.fields.json import JSONField +from django.utils.regex_helper import _lazy_re_compile + + +class Cast(Func): + """Coerce an expression to a new field type.""" + + function = "CAST" + template = "%(function)s(%(expressions)s AS %(db_type)s)" + + def __init__(self, expression, output_field): + super().__init__(expression, output_field=output_field) + + def as_sql(self, compiler, connection, **extra_context): + extra_context["db_type"] = self.output_field.cast_db_type(connection) + return super().as_sql(compiler, connection, **extra_context) + + def as_sqlite(self, compiler, connection, **extra_context): + db_type = self.output_field.db_type(connection) + if db_type in {"datetime", "time"}: + # Use strftime as datetime/time don't keep fractional seconds. + template = "strftime(%%s, %(expressions)s)" + sql, params = super().as_sql( + compiler, connection, template=template, **extra_context + ) + format_string = "%H:%M:%f" if db_type == "time" else "%Y-%m-%d %H:%M:%f" + params.insert(0, format_string) + return sql, params + elif db_type == "date": + template = "date(%(expressions)s)" + return super().as_sql( + compiler, connection, template=template, **extra_context + ) + return self.as_sql(compiler, connection, **extra_context) + + def as_mysql(self, compiler, connection, **extra_context): + template = None + output_type = self.output_field.get_internal_type() + # MySQL doesn't support explicit cast to float. + if output_type == "FloatField": + template = "(%(expressions)s + 0.0)" + # MariaDB doesn't support explicit cast to JSON. + elif output_type == "JSONField" and connection.mysql_is_mariadb: + template = "JSON_EXTRACT(%(expressions)s, '$')" + return self.as_sql(compiler, connection, template=template, **extra_context) + + def as_postgresql(self, compiler, connection, **extra_context): + # CAST would be valid too, but the :: shortcut syntax is more readable. + # 'expressions' is wrapped in parentheses in case it's a complex + # expression. + return self.as_sql( + compiler, + connection, + template="(%(expressions)s)::%(db_type)s", + **extra_context, + ) + + def as_oracle(self, compiler, connection, **extra_context): + if self.output_field.get_internal_type() == "JSONField": + # Oracle doesn't support explicit cast to JSON. + template = "JSON_QUERY(%(expressions)s, '$')" + return super().as_sql( + compiler, connection, template=template, **extra_context + ) + return self.as_sql(compiler, connection, **extra_context) + + +class Coalesce(Func): + """Return, from left to right, the first non-null expression.""" + + function = "COALESCE" + + def __init__(self, *expressions, **extra): + if len(expressions) < 2: + raise ValueError("Coalesce must take at least two expressions") + super().__init__(*expressions, **extra) + + @property + def empty_result_set_value(self): + for expression in self.get_source_expressions(): + result = expression.empty_result_set_value + if result is NotImplemented or result is not None: + return result + return None + + def as_oracle(self, compiler, connection, **extra_context): + # Oracle prohibits mixing TextField (NCLOB) and CharField (NVARCHAR2), + # so convert all fields to NCLOB when that type is expected. + if self.output_field.get_internal_type() == "TextField": + clone = self.copy() + clone.set_source_expressions( + [ + Func(expression, function="TO_NCLOB") + for expression in self.get_source_expressions() + ] + ) + return super(Coalesce, clone).as_sql(compiler, connection, **extra_context) + return self.as_sql(compiler, connection, **extra_context) + + +class Collate(Func): + function = "COLLATE" + template = "%(expressions)s %(function)s %(collation)s" + allowed_default = False + # Inspired from + # https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS + collation_re = _lazy_re_compile(r"^[\w-]+$") + + def __init__(self, expression, collation): + if not (collation and self.collation_re.match(collation)): + raise ValueError("Invalid collation name: %r." % collation) + self.collation = collation + super().__init__(expression) + + def as_sql(self, compiler, connection, **extra_context): + extra_context.setdefault("collation", connection.ops.quote_name(self.collation)) + return super().as_sql(compiler, connection, **extra_context) + + +class Greatest(Func): + """ + Return the maximum expression. + + If any expression is null the return value is database-specific: + On PostgreSQL, the maximum not-null expression is returned. + On MySQL, Oracle, and SQLite, if any expression is null, null is returned. + """ + + function = "GREATEST" + + def __init__(self, *expressions, **extra): + if len(expressions) < 2: + raise ValueError("Greatest must take at least two expressions") + super().__init__(*expressions, **extra) + + def as_sqlite(self, compiler, connection, **extra_context): + """Use the MAX function on SQLite.""" + return super().as_sqlite(compiler, connection, function="MAX", **extra_context) + + +class JSONObject(Func): + function = "JSON_OBJECT" + output_field = JSONField() + + def __init__(self, **fields): + expressions = [] + for key, value in fields.items(): + expressions.extend((Value(key), value)) + super().__init__(*expressions) + + def as_sql(self, compiler, connection, **extra_context): + if not connection.features.has_json_object_function: + raise NotSupportedError( + "JSONObject() is not supported on this database backend." + ) + return super().as_sql(compiler, connection, **extra_context) + + def as_postgresql(self, compiler, connection, **extra_context): + copy = self.copy() + copy.set_source_expressions( + [ + Cast(expression, TextField()) if index % 2 == 0 else expression + for index, expression in enumerate(copy.get_source_expressions()) + ] + ) + return super(JSONObject, copy).as_sql( + compiler, + connection, + function="JSONB_BUILD_OBJECT", + **extra_context, + ) + + def as_oracle(self, compiler, connection, **extra_context): + class ArgJoiner: + def join(self, args): + args = [" VALUE ".join(arg) for arg in zip(args[::2], args[1::2])] + return ", ".join(args) + + return self.as_sql( + compiler, + connection, + arg_joiner=ArgJoiner(), + template="%(function)s(%(expressions)s RETURNING CLOB)", + **extra_context, + ) + + +class Least(Func): + """ + Return the minimum expression. + + If any expression is null the return value is database-specific: + On PostgreSQL, return the minimum not-null expression. + On MySQL, Oracle, and SQLite, if any expression is null, return null. + """ + + function = "LEAST" + + def __init__(self, *expressions, **extra): + if len(expressions) < 2: + raise ValueError("Least must take at least two expressions") + super().__init__(*expressions, **extra) + + def as_sqlite(self, compiler, connection, **extra_context): + """Use the MIN function on SQLite.""" + return super().as_sqlite(compiler, connection, function="MIN", **extra_context) + + +class NullIf(Func): + function = "NULLIF" + arity = 2 + + def as_oracle(self, compiler, connection, **extra_context): + expression1 = self.get_source_expressions()[0] + if isinstance(expression1, Value) and expression1.value is None: + raise ValueError("Oracle does not allow Value(None) for expression1.") + return super().as_sql(compiler, connection, **extra_context) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/functions/datetime.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/functions/datetime.py new file mode 100644 index 0000000..fca211e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/functions/datetime.py @@ -0,0 +1,435 @@ +from datetime import datetime + +from django.conf import settings +from django.db.models.expressions import Func +from django.db.models.fields import ( + DateField, + DateTimeField, + DurationField, + Field, + IntegerField, + TimeField, +) +from django.db.models.lookups import ( + Transform, + YearExact, + YearGt, + YearGte, + YearLt, + YearLte, +) +from django.utils import timezone + + +class TimezoneMixin: + tzinfo = None + + def get_tzname(self): + # Timezone conversions must happen to the input datetime *before* + # applying a function. 2015-12-31 23:00:00 -02:00 is stored in the + # database as 2016-01-01 01:00:00 +00:00. Any results should be + # based on the input datetime not the stored datetime. + tzname = None + if settings.USE_TZ: + if self.tzinfo is None: + tzname = timezone.get_current_timezone_name() + else: + tzname = timezone._get_timezone_name(self.tzinfo) + return tzname + + +class Extract(TimezoneMixin, Transform): + lookup_name = None + output_field = IntegerField() + + def __init__(self, expression, lookup_name=None, tzinfo=None, **extra): + if self.lookup_name is None: + self.lookup_name = lookup_name + if self.lookup_name is None: + raise ValueError("lookup_name must be provided") + self.tzinfo = tzinfo + super().__init__(expression, **extra) + + def as_sql(self, compiler, connection): + sql, params = compiler.compile(self.lhs) + lhs_output_field = self.lhs.output_field + if isinstance(lhs_output_field, DateTimeField): + tzname = self.get_tzname() + sql, params = connection.ops.datetime_extract_sql( + self.lookup_name, sql, tuple(params), tzname + ) + elif self.tzinfo is not None: + raise ValueError("tzinfo can only be used with DateTimeField.") + elif isinstance(lhs_output_field, DateField): + sql, params = connection.ops.date_extract_sql( + self.lookup_name, sql, tuple(params) + ) + elif isinstance(lhs_output_field, TimeField): + sql, params = connection.ops.time_extract_sql( + self.lookup_name, sql, tuple(params) + ) + elif isinstance(lhs_output_field, DurationField): + if not connection.features.has_native_duration_field: + raise ValueError( + "Extract requires native DurationField database support." + ) + sql, params = connection.ops.time_extract_sql( + self.lookup_name, sql, tuple(params) + ) + else: + # resolve_expression has already validated the output_field so this + # assert should never be hit. + assert False, "Tried to Extract from an invalid type." + return sql, params + + def resolve_expression( + self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False + ): + copy = super().resolve_expression( + query, allow_joins, reuse, summarize, for_save + ) + field = getattr(copy.lhs, "output_field", None) + if field is None: + return copy + if not isinstance(field, (DateField, DateTimeField, TimeField, DurationField)): + raise ValueError( + "Extract input expression must be DateField, DateTimeField, " + "TimeField, or DurationField." + ) + # Passing dates to functions expecting datetimes is most likely a mistake. + if type(field) is DateField and copy.lookup_name in ( + "hour", + "minute", + "second", + ): + raise ValueError( + "Cannot extract time component '%s' from DateField '%s'." + % (copy.lookup_name, field.name) + ) + if isinstance(field, DurationField) and copy.lookup_name in ( + "year", + "iso_year", + "month", + "week", + "week_day", + "iso_week_day", + "quarter", + ): + raise ValueError( + "Cannot extract component '%s' from DurationField '%s'." + % (copy.lookup_name, field.name) + ) + return copy + + +class ExtractYear(Extract): + lookup_name = "year" + + +class ExtractIsoYear(Extract): + """Return the ISO-8601 week-numbering year.""" + + lookup_name = "iso_year" + + +class ExtractMonth(Extract): + lookup_name = "month" + + +class ExtractDay(Extract): + lookup_name = "day" + + +class ExtractWeek(Extract): + """ + Return 1-52 or 53, based on ISO-8601, i.e., Monday is the first of the + week. + """ + + lookup_name = "week" + + +class ExtractWeekDay(Extract): + """ + Return Sunday=1 through Saturday=7. + + To replicate this in Python: (mydatetime.isoweekday() % 7) + 1 + """ + + lookup_name = "week_day" + + +class ExtractIsoWeekDay(Extract): + """Return Monday=1 through Sunday=7, based on ISO-8601.""" + + lookup_name = "iso_week_day" + + +class ExtractQuarter(Extract): + lookup_name = "quarter" + + +class ExtractHour(Extract): + lookup_name = "hour" + + +class ExtractMinute(Extract): + lookup_name = "minute" + + +class ExtractSecond(Extract): + lookup_name = "second" + + +DateField.register_lookup(ExtractYear) +DateField.register_lookup(ExtractMonth) +DateField.register_lookup(ExtractDay) +DateField.register_lookup(ExtractWeekDay) +DateField.register_lookup(ExtractIsoWeekDay) +DateField.register_lookup(ExtractWeek) +DateField.register_lookup(ExtractIsoYear) +DateField.register_lookup(ExtractQuarter) + +TimeField.register_lookup(ExtractHour) +TimeField.register_lookup(ExtractMinute) +TimeField.register_lookup(ExtractSecond) + +DateTimeField.register_lookup(ExtractHour) +DateTimeField.register_lookup(ExtractMinute) +DateTimeField.register_lookup(ExtractSecond) + +ExtractYear.register_lookup(YearExact) +ExtractYear.register_lookup(YearGt) +ExtractYear.register_lookup(YearGte) +ExtractYear.register_lookup(YearLt) +ExtractYear.register_lookup(YearLte) + +ExtractIsoYear.register_lookup(YearExact) +ExtractIsoYear.register_lookup(YearGt) +ExtractIsoYear.register_lookup(YearGte) +ExtractIsoYear.register_lookup(YearLt) +ExtractIsoYear.register_lookup(YearLte) + + +class Now(Func): + template = "CURRENT_TIMESTAMP" + output_field = DateTimeField() + + def as_postgresql(self, compiler, connection, **extra_context): + # PostgreSQL's CURRENT_TIMESTAMP means "the time at the start of the + # transaction". Use STATEMENT_TIMESTAMP to be cross-compatible with + # other databases. + return self.as_sql( + compiler, connection, template="STATEMENT_TIMESTAMP()", **extra_context + ) + + def as_mysql(self, compiler, connection, **extra_context): + return self.as_sql( + compiler, connection, template="CURRENT_TIMESTAMP(6)", **extra_context + ) + + def as_sqlite(self, compiler, connection, **extra_context): + return self.as_sql( + compiler, + connection, + template="STRFTIME('%%%%Y-%%%%m-%%%%d %%%%H:%%%%M:%%%%f', 'NOW')", + **extra_context, + ) + + def as_oracle(self, compiler, connection, **extra_context): + return self.as_sql( + compiler, connection, template="LOCALTIMESTAMP", **extra_context + ) + + +class TruncBase(TimezoneMixin, Transform): + kind = None + tzinfo = None + + def __init__( + self, + expression, + output_field=None, + tzinfo=None, + **extra, + ): + self.tzinfo = tzinfo + super().__init__(expression, output_field=output_field, **extra) + + def as_sql(self, compiler, connection): + sql, params = compiler.compile(self.lhs) + tzname = None + if isinstance(self.lhs.output_field, DateTimeField): + tzname = self.get_tzname() + elif self.tzinfo is not None: + raise ValueError("tzinfo can only be used with DateTimeField.") + if isinstance(self.output_field, DateTimeField): + sql, params = connection.ops.datetime_trunc_sql( + self.kind, sql, tuple(params), tzname + ) + elif isinstance(self.output_field, DateField): + sql, params = connection.ops.date_trunc_sql( + self.kind, sql, tuple(params), tzname + ) + elif isinstance(self.output_field, TimeField): + sql, params = connection.ops.time_trunc_sql( + self.kind, sql, tuple(params), tzname + ) + else: + raise ValueError( + "Trunc only valid on DateField, TimeField, or DateTimeField." + ) + return sql, params + + def resolve_expression( + self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False + ): + copy = super().resolve_expression( + query, allow_joins, reuse, summarize, for_save + ) + field = copy.lhs.output_field + # DateTimeField is a subclass of DateField so this works for both. + if not isinstance(field, (DateField, TimeField)): + raise TypeError( + "%r isn't a DateField, TimeField, or DateTimeField." % field.name + ) + # If self.output_field was None, then accessing the field will trigger + # the resolver to assign it to self.lhs.output_field. + if not isinstance(copy.output_field, (DateField, DateTimeField, TimeField)): + raise ValueError( + "output_field must be either DateField, TimeField, or DateTimeField" + ) + # Passing dates or times to functions expecting datetimes is most + # likely a mistake. + class_output_field = ( + self.__class__.output_field + if isinstance(self.__class__.output_field, Field) + else None + ) + output_field = class_output_field or copy.output_field + has_explicit_output_field = ( + class_output_field or field.__class__ is not copy.output_field.__class__ + ) + if type(field) is DateField and ( + isinstance(output_field, DateTimeField) + or copy.kind in ("hour", "minute", "second", "time") + ): + raise ValueError( + "Cannot truncate DateField '%s' to %s." + % ( + field.name, + output_field.__class__.__name__ + if has_explicit_output_field + else "DateTimeField", + ) + ) + elif isinstance(field, TimeField) and ( + isinstance(output_field, DateTimeField) + or copy.kind in ("year", "quarter", "month", "week", "day", "date") + ): + raise ValueError( + "Cannot truncate TimeField '%s' to %s." + % ( + field.name, + output_field.__class__.__name__ + if has_explicit_output_field + else "DateTimeField", + ) + ) + return copy + + def convert_value(self, value, expression, connection): + if isinstance(self.output_field, DateTimeField): + if not settings.USE_TZ: + pass + elif value is not None: + value = value.replace(tzinfo=None) + value = timezone.make_aware(value, self.tzinfo) + elif not connection.features.has_zoneinfo_database: + raise ValueError( + "Database returned an invalid datetime value. Are time " + "zone definitions for your database installed?" + ) + elif isinstance(value, datetime): + if value is None: + pass + elif isinstance(self.output_field, DateField): + value = value.date() + elif isinstance(self.output_field, TimeField): + value = value.time() + return value + + +class Trunc(TruncBase): + def __init__( + self, + expression, + kind, + output_field=None, + tzinfo=None, + **extra, + ): + self.kind = kind + super().__init__(expression, output_field=output_field, tzinfo=tzinfo, **extra) + + +class TruncYear(TruncBase): + kind = "year" + + +class TruncQuarter(TruncBase): + kind = "quarter" + + +class TruncMonth(TruncBase): + kind = "month" + + +class TruncWeek(TruncBase): + """Truncate to midnight on the Monday of the week.""" + + kind = "week" + + +class TruncDay(TruncBase): + kind = "day" + + +class TruncDate(TruncBase): + kind = "date" + lookup_name = "date" + output_field = DateField() + + def as_sql(self, compiler, connection): + # Cast to date rather than truncate to date. + sql, params = compiler.compile(self.lhs) + tzname = self.get_tzname() + return connection.ops.datetime_cast_date_sql(sql, tuple(params), tzname) + + +class TruncTime(TruncBase): + kind = "time" + lookup_name = "time" + output_field = TimeField() + + def as_sql(self, compiler, connection): + # Cast to time rather than truncate to time. + sql, params = compiler.compile(self.lhs) + tzname = self.get_tzname() + return connection.ops.datetime_cast_time_sql(sql, tuple(params), tzname) + + +class TruncHour(TruncBase): + kind = "hour" + + +class TruncMinute(TruncBase): + kind = "minute" + + +class TruncSecond(TruncBase): + kind = "second" + + +DateTimeField.register_lookup(TruncDate) +DateTimeField.register_lookup(TruncTime) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/functions/math.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/functions/math.py new file mode 100644 index 0000000..460143b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/functions/math.py @@ -0,0 +1,212 @@ +import math + +from django.db.models.expressions import Func, Value +from django.db.models.fields import FloatField, IntegerField +from django.db.models.functions import Cast +from django.db.models.functions.mixins import ( + FixDecimalInputMixin, + NumericOutputFieldMixin, +) +from django.db.models.lookups import Transform + + +class Abs(Transform): + function = "ABS" + lookup_name = "abs" + + +class ACos(NumericOutputFieldMixin, Transform): + function = "ACOS" + lookup_name = "acos" + + +class ASin(NumericOutputFieldMixin, Transform): + function = "ASIN" + lookup_name = "asin" + + +class ATan(NumericOutputFieldMixin, Transform): + function = "ATAN" + lookup_name = "atan" + + +class ATan2(NumericOutputFieldMixin, Func): + function = "ATAN2" + arity = 2 + + def as_sqlite(self, compiler, connection, **extra_context): + if not getattr( + connection.ops, "spatialite", False + ) or connection.ops.spatial_version >= (5, 0, 0): + return self.as_sql(compiler, connection) + # This function is usually ATan2(y, x), returning the inverse tangent + # of y / x, but it's ATan2(x, y) on SpatiaLite < 5.0.0. + # Cast integers to float to avoid inconsistent/buggy behavior if the + # arguments are mixed between integer and float or decimal. + # https://www.gaia-gis.it/fossil/libspatialite/tktview?name=0f72cca3a2 + clone = self.copy() + clone.set_source_expressions( + [ + Cast(expression, FloatField()) + if isinstance(expression.output_field, IntegerField) + else expression + for expression in self.get_source_expressions()[::-1] + ] + ) + return clone.as_sql(compiler, connection, **extra_context) + + +class Ceil(Transform): + function = "CEILING" + lookup_name = "ceil" + + def as_oracle(self, compiler, connection, **extra_context): + return super().as_sql(compiler, connection, function="CEIL", **extra_context) + + +class Cos(NumericOutputFieldMixin, Transform): + function = "COS" + lookup_name = "cos" + + +class Cot(NumericOutputFieldMixin, Transform): + function = "COT" + lookup_name = "cot" + + def as_oracle(self, compiler, connection, **extra_context): + return super().as_sql( + compiler, connection, template="(1 / TAN(%(expressions)s))", **extra_context + ) + + +class Degrees(NumericOutputFieldMixin, Transform): + function = "DEGREES" + lookup_name = "degrees" + + def as_oracle(self, compiler, connection, **extra_context): + return super().as_sql( + compiler, + connection, + template="((%%(expressions)s) * 180 / %s)" % math.pi, + **extra_context, + ) + + +class Exp(NumericOutputFieldMixin, Transform): + function = "EXP" + lookup_name = "exp" + + +class Floor(Transform): + function = "FLOOR" + lookup_name = "floor" + + +class Ln(NumericOutputFieldMixin, Transform): + function = "LN" + lookup_name = "ln" + + +class Log(FixDecimalInputMixin, NumericOutputFieldMixin, Func): + function = "LOG" + arity = 2 + + def as_sqlite(self, compiler, connection, **extra_context): + if not getattr(connection.ops, "spatialite", False): + return self.as_sql(compiler, connection) + # This function is usually Log(b, x) returning the logarithm of x to + # the base b, but on SpatiaLite it's Log(x, b). + clone = self.copy() + clone.set_source_expressions(self.get_source_expressions()[::-1]) + return clone.as_sql(compiler, connection, **extra_context) + + +class Mod(FixDecimalInputMixin, NumericOutputFieldMixin, Func): + function = "MOD" + arity = 2 + + +class Pi(NumericOutputFieldMixin, Func): + function = "PI" + arity = 0 + + def as_oracle(self, compiler, connection, **extra_context): + return super().as_sql( + compiler, connection, template=str(math.pi), **extra_context + ) + + +class Power(NumericOutputFieldMixin, Func): + function = "POWER" + arity = 2 + + +class Radians(NumericOutputFieldMixin, Transform): + function = "RADIANS" + lookup_name = "radians" + + def as_oracle(self, compiler, connection, **extra_context): + return super().as_sql( + compiler, + connection, + template="((%%(expressions)s) * %s / 180)" % math.pi, + **extra_context, + ) + + +class Random(NumericOutputFieldMixin, Func): + function = "RANDOM" + arity = 0 + + def as_mysql(self, compiler, connection, **extra_context): + return super().as_sql(compiler, connection, function="RAND", **extra_context) + + def as_oracle(self, compiler, connection, **extra_context): + return super().as_sql( + compiler, connection, function="DBMS_RANDOM.VALUE", **extra_context + ) + + def as_sqlite(self, compiler, connection, **extra_context): + return super().as_sql(compiler, connection, function="RAND", **extra_context) + + def get_group_by_cols(self): + return [] + + +class Round(FixDecimalInputMixin, Transform): + function = "ROUND" + lookup_name = "round" + arity = None # Override Transform's arity=1 to enable passing precision. + + def __init__(self, expression, precision=0, **extra): + super().__init__(expression, precision, **extra) + + def as_sqlite(self, compiler, connection, **extra_context): + precision = self.get_source_expressions()[1] + if isinstance(precision, Value) and precision.value < 0: + raise ValueError("SQLite does not support negative precision.") + return super().as_sqlite(compiler, connection, **extra_context) + + def _resolve_output_field(self): + source = self.get_source_expressions()[0] + return source.output_field + + +class Sign(Transform): + function = "SIGN" + lookup_name = "sign" + + +class Sin(NumericOutputFieldMixin, Transform): + function = "SIN" + lookup_name = "sin" + + +class Sqrt(NumericOutputFieldMixin, Transform): + function = "SQRT" + lookup_name = "sqrt" + + +class Tan(NumericOutputFieldMixin, Transform): + function = "TAN" + lookup_name = "tan" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/functions/mixins.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/functions/mixins.py new file mode 100644 index 0000000..caf20e1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/functions/mixins.py @@ -0,0 +1,57 @@ +import sys + +from django.db.models.fields import DecimalField, FloatField, IntegerField +from django.db.models.functions import Cast + + +class FixDecimalInputMixin: + def as_postgresql(self, compiler, connection, **extra_context): + # Cast FloatField to DecimalField as PostgreSQL doesn't support the + # following function signatures: + # - LOG(double, double) + # - MOD(double, double) + output_field = DecimalField(decimal_places=sys.float_info.dig, max_digits=1000) + clone = self.copy() + clone.set_source_expressions( + [ + Cast(expression, output_field) + if isinstance(expression.output_field, FloatField) + else expression + for expression in self.get_source_expressions() + ] + ) + return clone.as_sql(compiler, connection, **extra_context) + + +class FixDurationInputMixin: + def as_mysql(self, compiler, connection, **extra_context): + sql, params = super().as_sql(compiler, connection, **extra_context) + if self.output_field.get_internal_type() == "DurationField": + sql = "CAST(%s AS SIGNED)" % sql + return sql, params + + def as_oracle(self, compiler, connection, **extra_context): + if self.output_field.get_internal_type() == "DurationField": + expression = self.get_source_expressions()[0] + options = self._get_repr_options() + from django.db.backends.oracle.functions import ( + IntervalToSeconds, + SecondsToInterval, + ) + + return compiler.compile( + SecondsToInterval( + self.__class__(IntervalToSeconds(expression), **options) + ) + ) + return super().as_sql(compiler, connection, **extra_context) + + +class NumericOutputFieldMixin: + def _resolve_output_field(self): + source_fields = self.get_source_fields() + if any(isinstance(s, DecimalField) for s in source_fields): + return DecimalField() + if any(isinstance(s, IntegerField) for s in source_fields): + return FloatField() + return super()._resolve_output_field() if source_fields else FloatField() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/functions/text.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/functions/text.py new file mode 100644 index 0000000..2b49f54 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/functions/text.py @@ -0,0 +1,369 @@ +from django.db import NotSupportedError +from django.db.models.expressions import Func, Value +from django.db.models.fields import CharField, IntegerField, TextField +from django.db.models.functions import Cast, Coalesce +from django.db.models.lookups import Transform + + +class MySQLSHA2Mixin: + def as_mysql(self, compiler, connection, **extra_context): + return super().as_sql( + compiler, + connection, + template="SHA2(%%(expressions)s, %s)" % self.function[3:], + **extra_context, + ) + + +class OracleHashMixin: + def as_oracle(self, compiler, connection, **extra_context): + return super().as_sql( + compiler, + connection, + template=( + "LOWER(RAWTOHEX(STANDARD_HASH(UTL_I18N.STRING_TO_RAW(" + "%(expressions)s, 'AL32UTF8'), '%(function)s')))" + ), + **extra_context, + ) + + +class PostgreSQLSHAMixin: + def as_postgresql(self, compiler, connection, **extra_context): + return super().as_sql( + compiler, + connection, + template="ENCODE(DIGEST(%(expressions)s, '%(function)s'), 'hex')", + function=self.function.lower(), + **extra_context, + ) + + +class Chr(Transform): + function = "CHR" + lookup_name = "chr" + output_field = CharField() + + def as_mysql(self, compiler, connection, **extra_context): + return super().as_sql( + compiler, + connection, + function="CHAR", + template="%(function)s(%(expressions)s USING utf16)", + **extra_context, + ) + + def as_oracle(self, compiler, connection, **extra_context): + return super().as_sql( + compiler, + connection, + template="%(function)s(%(expressions)s USING NCHAR_CS)", + **extra_context, + ) + + def as_sqlite(self, compiler, connection, **extra_context): + return super().as_sql(compiler, connection, function="CHAR", **extra_context) + + +class ConcatPair(Func): + """ + Concatenate two arguments together. This is used by `Concat` because not + all backend databases support more than two arguments. + """ + + function = "CONCAT" + + def as_sqlite(self, compiler, connection, **extra_context): + coalesced = self.coalesce() + return super(ConcatPair, coalesced).as_sql( + compiler, + connection, + template="%(expressions)s", + arg_joiner=" || ", + **extra_context, + ) + + def as_postgresql(self, compiler, connection, **extra_context): + copy = self.copy() + copy.set_source_expressions( + [ + Cast(expression, TextField()) + for expression in copy.get_source_expressions() + ] + ) + return super(ConcatPair, copy).as_sql( + compiler, + connection, + **extra_context, + ) + + def as_mysql(self, compiler, connection, **extra_context): + # Use CONCAT_WS with an empty separator so that NULLs are ignored. + return super().as_sql( + compiler, + connection, + function="CONCAT_WS", + template="%(function)s('', %(expressions)s)", + **extra_context, + ) + + def coalesce(self): + # null on either side results in null for expression, wrap with coalesce + c = self.copy() + c.set_source_expressions( + [ + Coalesce(expression, Value("")) + for expression in c.get_source_expressions() + ] + ) + return c + + +class Concat(Func): + """ + Concatenate text fields together. Backends that result in an entire + null expression when any arguments are null will wrap each argument in + coalesce functions to ensure a non-null result. + """ + + function = None + template = "%(expressions)s" + + def __init__(self, *expressions, **extra): + if len(expressions) < 2: + raise ValueError("Concat must take at least two expressions") + paired = self._paired(expressions) + super().__init__(paired, **extra) + + def _paired(self, expressions): + # wrap pairs of expressions in successive concat functions + # exp = [a, b, c, d] + # -> ConcatPair(a, ConcatPair(b, ConcatPair(c, d)))) + if len(expressions) == 2: + return ConcatPair(*expressions) + return ConcatPair(expressions[0], self._paired(expressions[1:])) + + +class Left(Func): + function = "LEFT" + arity = 2 + output_field = CharField() + + def __init__(self, expression, length, **extra): + """ + expression: the name of a field, or an expression returning a string + length: the number of characters to return from the start of the string + """ + if not hasattr(length, "resolve_expression"): + if length < 1: + raise ValueError("'length' must be greater than 0.") + super().__init__(expression, length, **extra) + + def get_substr(self): + return Substr(self.source_expressions[0], Value(1), self.source_expressions[1]) + + def as_oracle(self, compiler, connection, **extra_context): + return self.get_substr().as_oracle(compiler, connection, **extra_context) + + def as_sqlite(self, compiler, connection, **extra_context): + return self.get_substr().as_sqlite(compiler, connection, **extra_context) + + +class Length(Transform): + """Return the number of characters in the expression.""" + + function = "LENGTH" + lookup_name = "length" + output_field = IntegerField() + + def as_mysql(self, compiler, connection, **extra_context): + return super().as_sql( + compiler, connection, function="CHAR_LENGTH", **extra_context + ) + + +class Lower(Transform): + function = "LOWER" + lookup_name = "lower" + + +class LPad(Func): + function = "LPAD" + output_field = CharField() + + def __init__(self, expression, length, fill_text=Value(" "), **extra): + if ( + not hasattr(length, "resolve_expression") + and length is not None + and length < 0 + ): + raise ValueError("'length' must be greater or equal to 0.") + super().__init__(expression, length, fill_text, **extra) + + +class LTrim(Transform): + function = "LTRIM" + lookup_name = "ltrim" + + +class MD5(OracleHashMixin, Transform): + function = "MD5" + lookup_name = "md5" + + +class Ord(Transform): + function = "ASCII" + lookup_name = "ord" + output_field = IntegerField() + + def as_mysql(self, compiler, connection, **extra_context): + return super().as_sql(compiler, connection, function="ORD", **extra_context) + + def as_sqlite(self, compiler, connection, **extra_context): + return super().as_sql(compiler, connection, function="UNICODE", **extra_context) + + +class Repeat(Func): + function = "REPEAT" + output_field = CharField() + + def __init__(self, expression, number, **extra): + if ( + not hasattr(number, "resolve_expression") + and number is not None + and number < 0 + ): + raise ValueError("'number' must be greater or equal to 0.") + super().__init__(expression, number, **extra) + + def as_oracle(self, compiler, connection, **extra_context): + expression, number = self.source_expressions + length = None if number is None else Length(expression) * number + rpad = RPad(expression, length, expression) + return rpad.as_sql(compiler, connection, **extra_context) + + +class Replace(Func): + function = "REPLACE" + + def __init__(self, expression, text, replacement=Value(""), **extra): + super().__init__(expression, text, replacement, **extra) + + +class Reverse(Transform): + function = "REVERSE" + lookup_name = "reverse" + + def as_oracle(self, compiler, connection, **extra_context): + # REVERSE in Oracle is undocumented and doesn't support multi-byte + # strings. Use a special subquery instead. + sql, params = super().as_sql( + compiler, + connection, + template=( + "(SELECT LISTAGG(s) WITHIN GROUP (ORDER BY n DESC) FROM " + "(SELECT LEVEL n, SUBSTR(%(expressions)s, LEVEL, 1) s " + "FROM DUAL CONNECT BY LEVEL <= LENGTH(%(expressions)s)) " + "GROUP BY %(expressions)s)" + ), + **extra_context, + ) + return sql, params * 3 + + +class Right(Left): + function = "RIGHT" + + def get_substr(self): + return Substr( + self.source_expressions[0], + self.source_expressions[1] * Value(-1), + self.source_expressions[1], + ) + + +class RPad(LPad): + function = "RPAD" + + +class RTrim(Transform): + function = "RTRIM" + lookup_name = "rtrim" + + +class SHA1(OracleHashMixin, PostgreSQLSHAMixin, Transform): + function = "SHA1" + lookup_name = "sha1" + + +class SHA224(MySQLSHA2Mixin, PostgreSQLSHAMixin, Transform): + function = "SHA224" + lookup_name = "sha224" + + def as_oracle(self, compiler, connection, **extra_context): + raise NotSupportedError("SHA224 is not supported on Oracle.") + + +class SHA256(MySQLSHA2Mixin, OracleHashMixin, PostgreSQLSHAMixin, Transform): + function = "SHA256" + lookup_name = "sha256" + + +class SHA384(MySQLSHA2Mixin, OracleHashMixin, PostgreSQLSHAMixin, Transform): + function = "SHA384" + lookup_name = "sha384" + + +class SHA512(MySQLSHA2Mixin, OracleHashMixin, PostgreSQLSHAMixin, Transform): + function = "SHA512" + lookup_name = "sha512" + + +class StrIndex(Func): + """ + Return a positive integer corresponding to the 1-indexed position of the + first occurrence of a substring inside another string, or 0 if the + substring is not found. + """ + + function = "INSTR" + arity = 2 + output_field = IntegerField() + + def as_postgresql(self, compiler, connection, **extra_context): + return super().as_sql(compiler, connection, function="STRPOS", **extra_context) + + +class Substr(Func): + function = "SUBSTRING" + output_field = CharField() + + def __init__(self, expression, pos, length=None, **extra): + """ + expression: the name of a field, or an expression returning a string + pos: an integer > 0, or an expression returning an integer + length: an optional number of characters to return + """ + if not hasattr(pos, "resolve_expression"): + if pos < 1: + raise ValueError("'pos' must be greater than 0") + expressions = [expression, pos] + if length is not None: + expressions.append(length) + super().__init__(*expressions, **extra) + + def as_sqlite(self, compiler, connection, **extra_context): + return super().as_sql(compiler, connection, function="SUBSTR", **extra_context) + + def as_oracle(self, compiler, connection, **extra_context): + return super().as_sql(compiler, connection, function="SUBSTR", **extra_context) + + +class Trim(Transform): + function = "TRIM" + lookup_name = "trim" + + +class Upper(Transform): + function = "UPPER" + lookup_name = "upper" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/functions/window.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/functions/window.py new file mode 100644 index 0000000..671017a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/functions/window.py @@ -0,0 +1,120 @@ +from django.db.models.expressions import Func +from django.db.models.fields import FloatField, IntegerField + +__all__ = [ + "CumeDist", + "DenseRank", + "FirstValue", + "Lag", + "LastValue", + "Lead", + "NthValue", + "Ntile", + "PercentRank", + "Rank", + "RowNumber", +] + + +class CumeDist(Func): + function = "CUME_DIST" + output_field = FloatField() + window_compatible = True + + +class DenseRank(Func): + function = "DENSE_RANK" + output_field = IntegerField() + window_compatible = True + + +class FirstValue(Func): + arity = 1 + function = "FIRST_VALUE" + window_compatible = True + + +class LagLeadFunction(Func): + window_compatible = True + + def __init__(self, expression, offset=1, default=None, **extra): + if expression is None: + raise ValueError( + "%s requires a non-null source expression." % self.__class__.__name__ + ) + if offset is None or offset <= 0: + raise ValueError( + "%s requires a positive integer for the offset." + % self.__class__.__name__ + ) + args = (expression, offset) + if default is not None: + args += (default,) + super().__init__(*args, **extra) + + def _resolve_output_field(self): + sources = self.get_source_expressions() + return sources[0].output_field + + +class Lag(LagLeadFunction): + function = "LAG" + + +class LastValue(Func): + arity = 1 + function = "LAST_VALUE" + window_compatible = True + + +class Lead(LagLeadFunction): + function = "LEAD" + + +class NthValue(Func): + function = "NTH_VALUE" + window_compatible = True + + def __init__(self, expression, nth=1, **extra): + if expression is None: + raise ValueError( + "%s requires a non-null source expression." % self.__class__.__name__ + ) + if nth is None or nth <= 0: + raise ValueError( + "%s requires a positive integer as for nth." % self.__class__.__name__ + ) + super().__init__(expression, nth, **extra) + + def _resolve_output_field(self): + sources = self.get_source_expressions() + return sources[0].output_field + + +class Ntile(Func): + function = "NTILE" + output_field = IntegerField() + window_compatible = True + + def __init__(self, num_buckets=1, **extra): + if num_buckets <= 0: + raise ValueError("num_buckets must be greater than 0.") + super().__init__(num_buckets, **extra) + + +class PercentRank(Func): + function = "PERCENT_RANK" + output_field = FloatField() + window_compatible = True + + +class Rank(Func): + function = "RANK" + output_field = IntegerField() + window_compatible = True + + +class RowNumber(Func): + function = "ROW_NUMBER" + output_field = IntegerField() + window_compatible = True diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/indexes.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/indexes.py new file mode 100644 index 0000000..b5451f9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/indexes.py @@ -0,0 +1,297 @@ +from types import NoneType + +from django.db.backends.utils import names_digest, split_identifier +from django.db.models.expressions import Col, ExpressionList, F, Func, OrderBy +from django.db.models.functions import Collate +from django.db.models.query_utils import Q +from django.db.models.sql import Query +from django.utils.functional import partition + +__all__ = ["Index"] + + +class Index: + suffix = "idx" + # The max length of the name of the index (restricted to 30 for + # cross-database compatibility with Oracle) + max_name_length = 30 + + def __init__( + self, + *expressions, + fields=(), + name=None, + db_tablespace=None, + opclasses=(), + condition=None, + include=None, + ): + if opclasses and not name: + raise ValueError("An index must be named to use opclasses.") + if not isinstance(condition, (NoneType, Q)): + raise ValueError("Index.condition must be a Q instance.") + if condition and not name: + raise ValueError("An index must be named to use condition.") + if not isinstance(fields, (list, tuple)): + raise ValueError("Index.fields must be a list or tuple.") + if not isinstance(opclasses, (list, tuple)): + raise ValueError("Index.opclasses must be a list or tuple.") + if not expressions and not fields: + raise ValueError( + "At least one field or expression is required to define an index." + ) + if expressions and fields: + raise ValueError( + "Index.fields and expressions are mutually exclusive.", + ) + if expressions and not name: + raise ValueError("An index must be named to use expressions.") + if expressions and opclasses: + raise ValueError( + "Index.opclasses cannot be used with expressions. Use " + "django.contrib.postgres.indexes.OpClass() instead." + ) + if opclasses and len(fields) != len(opclasses): + raise ValueError( + "Index.fields and Index.opclasses must have the same number of " + "elements." + ) + if fields and not all(isinstance(field, str) for field in fields): + raise ValueError("Index.fields must contain only strings with field names.") + if include and not name: + raise ValueError("A covering index must be named.") + if not isinstance(include, (NoneType, list, tuple)): + raise ValueError("Index.include must be a list or tuple.") + self.fields = list(fields) + # A list of 2-tuple with the field name and ordering ('' or 'DESC'). + self.fields_orders = [ + (field_name.removeprefix("-"), "DESC" if field_name.startswith("-") else "") + for field_name in self.fields + ] + self.name = name or "" + self.db_tablespace = db_tablespace + self.opclasses = opclasses + self.condition = condition + self.include = tuple(include) if include else () + self.expressions = tuple( + F(expression) if isinstance(expression, str) else expression + for expression in expressions + ) + + @property + def contains_expressions(self): + return bool(self.expressions) + + def _get_condition_sql(self, model, schema_editor): + if self.condition is None: + return None + query = Query(model=model, alias_cols=False) + where = query.build_where(self.condition) + compiler = query.get_compiler(connection=schema_editor.connection) + sql, params = where.as_sql(compiler, schema_editor.connection) + return sql % tuple(schema_editor.quote_value(p) for p in params) + + def create_sql(self, model, schema_editor, using="", **kwargs): + include = [ + model._meta.get_field(field_name).column for field_name in self.include + ] + condition = self._get_condition_sql(model, schema_editor) + if self.expressions: + index_expressions = [] + for expression in self.expressions: + index_expression = IndexExpression(expression) + index_expression.set_wrapper_classes(schema_editor.connection) + index_expressions.append(index_expression) + expressions = ExpressionList(*index_expressions).resolve_expression( + Query(model, alias_cols=False), + ) + fields = None + col_suffixes = None + else: + fields = [ + model._meta.get_field(field_name) + for field_name, _ in self.fields_orders + ] + if schema_editor.connection.features.supports_index_column_ordering: + col_suffixes = [order[1] for order in self.fields_orders] + else: + col_suffixes = [""] * len(self.fields_orders) + expressions = None + return schema_editor._create_index_sql( + model, + fields=fields, + name=self.name, + using=using, + db_tablespace=self.db_tablespace, + col_suffixes=col_suffixes, + opclasses=self.opclasses, + condition=condition, + include=include, + expressions=expressions, + **kwargs, + ) + + def remove_sql(self, model, schema_editor, **kwargs): + return schema_editor._delete_index_sql(model, self.name, **kwargs) + + def deconstruct(self): + path = "%s.%s" % (self.__class__.__module__, self.__class__.__name__) + path = path.replace("django.db.models.indexes", "django.db.models") + kwargs = {"name": self.name} + if self.fields: + kwargs["fields"] = self.fields + if self.db_tablespace is not None: + kwargs["db_tablespace"] = self.db_tablespace + if self.opclasses: + kwargs["opclasses"] = self.opclasses + if self.condition: + kwargs["condition"] = self.condition + if self.include: + kwargs["include"] = self.include + return (path, self.expressions, kwargs) + + def clone(self): + """Create a copy of this Index.""" + _, args, kwargs = self.deconstruct() + return self.__class__(*args, **kwargs) + + def set_name_with_model(self, model): + """ + Generate a unique name for the index. + + The name is divided into 3 parts - table name (12 chars), field name + (8 chars) and unique hash + suffix (10 chars). Each part is made to + fit its size by truncating the excess length. + """ + _, table_name = split_identifier(model._meta.db_table) + column_names = [ + model._meta.get_field(field_name).column + for field_name, order in self.fields_orders + ] + column_names_with_order = [ + (("-%s" if order else "%s") % column_name) + for column_name, (field_name, order) in zip( + column_names, self.fields_orders + ) + ] + # The length of the parts of the name is based on the default max + # length of 30 characters. + hash_data = [table_name] + column_names_with_order + [self.suffix] + self.name = "%s_%s_%s" % ( + table_name[:11], + column_names[0][:7], + "%s_%s" % (names_digest(*hash_data, length=6), self.suffix), + ) + if len(self.name) > self.max_name_length: + raise ValueError( + "Index too long for multiple database support. Is self.suffix " + "longer than 3 characters?" + ) + if self.name[0] == "_" or self.name[0].isdigit(): + self.name = "D%s" % self.name[1:] + + def __repr__(self): + return "<%s:%s%s%s%s%s%s%s>" % ( + self.__class__.__qualname__, + "" if not self.fields else " fields=%s" % repr(self.fields), + "" if not self.expressions else " expressions=%s" % repr(self.expressions), + "" if not self.name else " name=%s" % repr(self.name), + "" + if self.db_tablespace is None + else " db_tablespace=%s" % repr(self.db_tablespace), + "" if self.condition is None else " condition=%s" % self.condition, + "" if not self.include else " include=%s" % repr(self.include), + "" if not self.opclasses else " opclasses=%s" % repr(self.opclasses), + ) + + def __eq__(self, other): + if self.__class__ == other.__class__: + return self.deconstruct() == other.deconstruct() + return NotImplemented + + +class IndexExpression(Func): + """Order and wrap expressions for CREATE INDEX statements.""" + + template = "%(expressions)s" + wrapper_classes = (OrderBy, Collate) + + def set_wrapper_classes(self, connection=None): + # Some databases (e.g. MySQL) treats COLLATE as an indexed expression. + if connection and connection.features.collate_as_index_expression: + self.wrapper_classes = tuple( + [ + wrapper_cls + for wrapper_cls in self.wrapper_classes + if wrapper_cls is not Collate + ] + ) + + @classmethod + def register_wrappers(cls, *wrapper_classes): + cls.wrapper_classes = wrapper_classes + + def resolve_expression( + self, + query=None, + allow_joins=True, + reuse=None, + summarize=False, + for_save=False, + ): + expressions = list(self.flatten()) + # Split expressions and wrappers. + index_expressions, wrappers = partition( + lambda e: isinstance(e, self.wrapper_classes), + expressions, + ) + wrapper_types = [type(wrapper) for wrapper in wrappers] + if len(wrapper_types) != len(set(wrapper_types)): + raise ValueError( + "Multiple references to %s can't be used in an indexed " + "expression." + % ", ".join( + [wrapper_cls.__qualname__ for wrapper_cls in self.wrapper_classes] + ) + ) + if expressions[1 : len(wrappers) + 1] != wrappers: + raise ValueError( + "%s must be topmost expressions in an indexed expression." + % ", ".join( + [wrapper_cls.__qualname__ for wrapper_cls in self.wrapper_classes] + ) + ) + # Wrap expressions in parentheses if they are not column references. + root_expression = index_expressions[1] + resolve_root_expression = root_expression.resolve_expression( + query, + allow_joins, + reuse, + summarize, + for_save, + ) + if not isinstance(resolve_root_expression, Col): + root_expression = Func(root_expression, template="(%(expressions)s)") + + if wrappers: + # Order wrappers and set their expressions. + wrappers = sorted( + wrappers, + key=lambda w: self.wrapper_classes.index(type(w)), + ) + wrappers = [wrapper.copy() for wrapper in wrappers] + for i, wrapper in enumerate(wrappers[:-1]): + wrapper.set_source_expressions([wrappers[i + 1]]) + # Set the root expression on the deepest wrapper. + wrappers[-1].set_source_expressions([root_expression]) + self.set_source_expressions([wrappers[0]]) + else: + # Use the root expression, if there are no wrappers. + self.set_source_expressions([root_expression]) + return super().resolve_expression( + query, allow_joins, reuse, summarize, for_save + ) + + def as_sqlite(self, compiler, connection, **extra_context): + # Casting to numeric is unnecessary. + return self.as_sql(compiler, connection, **extra_context) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/lookups.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/lookups.py new file mode 100644 index 0000000..a562a3d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/lookups.py @@ -0,0 +1,783 @@ +import itertools +import math +import warnings + +from django.core.exceptions import EmptyResultSet, FullResultSet +from django.db.backends.base.operations import BaseDatabaseOperations +from django.db.models.expressions import Case, Expression, Func, Value, When +from django.db.models.fields import ( + BooleanField, + CharField, + DateTimeField, + Field, + IntegerField, + UUIDField, +) +from django.db.models.query_utils import RegisterLookupMixin +from django.utils.datastructures import OrderedSet +from django.utils.deprecation import RemovedInDjango60Warning +from django.utils.functional import cached_property +from django.utils.hashable import make_hashable + + +class Lookup(Expression): + lookup_name = None + prepare_rhs = True + can_use_none_as_rhs = False + + def __init__(self, lhs, rhs): + self.lhs, self.rhs = lhs, rhs + self.rhs = self.get_prep_lookup() + self.lhs = self.get_prep_lhs() + if hasattr(self.lhs, "get_bilateral_transforms"): + bilateral_transforms = self.lhs.get_bilateral_transforms() + else: + bilateral_transforms = [] + if bilateral_transforms: + # Warn the user as soon as possible if they are trying to apply + # a bilateral transformation on a nested QuerySet: that won't work. + from django.db.models.sql.query import Query # avoid circular import + + if isinstance(rhs, Query): + raise NotImplementedError( + "Bilateral transformations on nested querysets are not implemented." + ) + self.bilateral_transforms = bilateral_transforms + + def apply_bilateral_transforms(self, value): + for transform in self.bilateral_transforms: + value = transform(value) + return value + + def __repr__(self): + return f"{self.__class__.__name__}({self.lhs!r}, {self.rhs!r})" + + def batch_process_rhs(self, compiler, connection, rhs=None): + if rhs is None: + rhs = self.rhs + if self.bilateral_transforms: + sqls, sqls_params = [], [] + for p in rhs: + value = Value(p, output_field=self.lhs.output_field) + value = self.apply_bilateral_transforms(value) + value = value.resolve_expression(compiler.query) + sql, sql_params = compiler.compile(value) + sqls.append(sql) + sqls_params.extend(sql_params) + else: + _, params = self.get_db_prep_lookup(rhs, connection) + sqls, sqls_params = ["%s"] * len(params), params + return sqls, sqls_params + + def get_source_expressions(self): + if self.rhs_is_direct_value(): + return [self.lhs] + return [self.lhs, self.rhs] + + def set_source_expressions(self, new_exprs): + if len(new_exprs) == 1: + self.lhs = new_exprs[0] + else: + self.lhs, self.rhs = new_exprs + + def get_prep_lookup(self): + if not self.prepare_rhs or hasattr(self.rhs, "resolve_expression"): + return self.rhs + if hasattr(self.lhs, "output_field"): + if hasattr(self.lhs.output_field, "get_prep_value"): + return self.lhs.output_field.get_prep_value(self.rhs) + elif self.rhs_is_direct_value(): + return Value(self.rhs) + return self.rhs + + def get_prep_lhs(self): + if hasattr(self.lhs, "resolve_expression"): + return self.lhs + return Value(self.lhs) + + def get_db_prep_lookup(self, value, connection): + return ("%s", [value]) + + def process_lhs(self, compiler, connection, lhs=None): + lhs = lhs or self.lhs + if hasattr(lhs, "resolve_expression"): + lhs = lhs.resolve_expression(compiler.query) + sql, params = compiler.compile(lhs) + if isinstance(lhs, Lookup): + # Wrapped in parentheses to respect operator precedence. + sql = f"({sql})" + return sql, params + + def process_rhs(self, compiler, connection): + value = self.rhs + if self.bilateral_transforms: + if self.rhs_is_direct_value(): + # Do not call get_db_prep_lookup here as the value will be + # transformed before being used for lookup + value = Value(value, output_field=self.lhs.output_field) + value = self.apply_bilateral_transforms(value) + value = value.resolve_expression(compiler.query) + if hasattr(value, "as_sql"): + sql, params = compiler.compile(value) + # Ensure expression is wrapped in parentheses to respect operator + # precedence but avoid double wrapping as it can be misinterpreted + # on some backends (e.g. subqueries on SQLite). + if sql and sql[0] != "(": + sql = "(%s)" % sql + return sql, params + else: + return self.get_db_prep_lookup(value, connection) + + def rhs_is_direct_value(self): + return not hasattr(self.rhs, "as_sql") + + def get_group_by_cols(self): + cols = [] + for source in self.get_source_expressions(): + cols.extend(source.get_group_by_cols()) + return cols + + def as_oracle(self, compiler, connection): + # Oracle doesn't allow EXISTS() and filters to be compared to another + # expression unless they're wrapped in a CASE WHEN. + wrapped = False + exprs = [] + for expr in (self.lhs, self.rhs): + if connection.ops.conditional_expression_supported_in_where_clause(expr): + expr = Case(When(expr, then=True), default=False) + wrapped = True + exprs.append(expr) + lookup = type(self)(*exprs) if wrapped else self + return lookup.as_sql(compiler, connection) + + @cached_property + def output_field(self): + return BooleanField() + + @property + def identity(self): + return self.__class__, self.lhs, self.rhs + + def __eq__(self, other): + if not isinstance(other, Lookup): + return NotImplemented + return self.identity == other.identity + + def __hash__(self): + return hash(make_hashable(self.identity)) + + def resolve_expression( + self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False + ): + c = self.copy() + c.is_summary = summarize + c.lhs = self.lhs.resolve_expression( + query, allow_joins, reuse, summarize, for_save + ) + if hasattr(self.rhs, "resolve_expression"): + c.rhs = self.rhs.resolve_expression( + query, allow_joins, reuse, summarize, for_save + ) + return c + + def select_format(self, compiler, sql, params): + # Wrap filters with a CASE WHEN expression if a database backend + # (e.g. Oracle) doesn't support boolean expression in SELECT or GROUP + # BY list. + if not compiler.connection.features.supports_boolean_expr_in_select_clause: + sql = f"CASE WHEN {sql} THEN 1 ELSE 0 END" + return sql, params + + @cached_property + def allowed_default(self): + return self.lhs.allowed_default and self.rhs.allowed_default + + +class Transform(RegisterLookupMixin, Func): + """ + RegisterLookupMixin() is first so that get_lookup() and get_transform() + first examine self and then check output_field. + """ + + bilateral = False + arity = 1 + + @property + def lhs(self): + return self.get_source_expressions()[0] + + def get_bilateral_transforms(self): + if hasattr(self.lhs, "get_bilateral_transforms"): + bilateral_transforms = self.lhs.get_bilateral_transforms() + else: + bilateral_transforms = [] + if self.bilateral: + bilateral_transforms.append(self.__class__) + return bilateral_transforms + + +class BuiltinLookup(Lookup): + def process_lhs(self, compiler, connection, lhs=None): + lhs_sql, params = super().process_lhs(compiler, connection, lhs) + field_internal_type = self.lhs.output_field.get_internal_type() + if ( + hasattr(connection.ops.__class__, "field_cast_sql") + and connection.ops.__class__.field_cast_sql + is not BaseDatabaseOperations.field_cast_sql + ): + warnings.warn( + ( + "The usage of DatabaseOperations.field_cast_sql() is deprecated. " + "Implement DatabaseOperations.lookup_cast() instead." + ), + RemovedInDjango60Warning, + ) + db_type = self.lhs.output_field.db_type(connection=connection) + lhs_sql = ( + connection.ops.field_cast_sql(db_type, field_internal_type) % lhs_sql + ) + lhs_sql = ( + connection.ops.lookup_cast(self.lookup_name, field_internal_type) % lhs_sql + ) + return lhs_sql, list(params) + + def as_sql(self, compiler, connection): + lhs_sql, params = self.process_lhs(compiler, connection) + rhs_sql, rhs_params = self.process_rhs(compiler, connection) + params.extend(rhs_params) + rhs_sql = self.get_rhs_op(connection, rhs_sql) + return "%s %s" % (lhs_sql, rhs_sql), params + + def get_rhs_op(self, connection, rhs): + return connection.operators[self.lookup_name] % rhs + + +class FieldGetDbPrepValueMixin: + """ + Some lookups require Field.get_db_prep_value() to be called on their + inputs. + """ + + get_db_prep_lookup_value_is_iterable = False + + def get_db_prep_lookup(self, value, connection): + # For relational fields, use the 'target_field' attribute of the + # output_field. + field = getattr(self.lhs.output_field, "target_field", None) + get_db_prep_value = ( + getattr(field, "get_db_prep_value", None) + or self.lhs.output_field.get_db_prep_value + ) + return ( + "%s", + [get_db_prep_value(v, connection, prepared=True) for v in value] + if self.get_db_prep_lookup_value_is_iterable + else [get_db_prep_value(value, connection, prepared=True)], + ) + + +class FieldGetDbPrepValueIterableMixin(FieldGetDbPrepValueMixin): + """ + Some lookups require Field.get_db_prep_value() to be called on each value + in an iterable. + """ + + get_db_prep_lookup_value_is_iterable = True + + def get_prep_lookup(self): + if hasattr(self.rhs, "resolve_expression"): + return self.rhs + prepared_values = [] + for rhs_value in self.rhs: + if hasattr(rhs_value, "resolve_expression"): + # An expression will be handled by the database but can coexist + # alongside real values. + pass + elif self.prepare_rhs and hasattr(self.lhs.output_field, "get_prep_value"): + rhs_value = self.lhs.output_field.get_prep_value(rhs_value) + prepared_values.append(rhs_value) + return prepared_values + + def process_rhs(self, compiler, connection): + if self.rhs_is_direct_value(): + # rhs should be an iterable of values. Use batch_process_rhs() + # to prepare/transform those values. + return self.batch_process_rhs(compiler, connection) + else: + return super().process_rhs(compiler, connection) + + def resolve_expression_parameter(self, compiler, connection, sql, param): + params = [param] + if hasattr(param, "resolve_expression"): + param = param.resolve_expression(compiler.query) + if hasattr(param, "as_sql"): + sql, params = compiler.compile(param) + return sql, params + + def batch_process_rhs(self, compiler, connection, rhs=None): + pre_processed = super().batch_process_rhs(compiler, connection, rhs) + # The params list may contain expressions which compile to a + # sql/param pair. Zip them to get sql and param pairs that refer to the + # same argument and attempt to replace them with the result of + # compiling the param step. + sql, params = zip( + *( + self.resolve_expression_parameter(compiler, connection, sql, param) + for sql, param in zip(*pre_processed) + ) + ) + params = itertools.chain.from_iterable(params) + return sql, tuple(params) + + +class PostgresOperatorLookup(Lookup): + """Lookup defined by operators on PostgreSQL.""" + + postgres_operator = None + + def as_postgresql(self, compiler, connection): + lhs, lhs_params = self.process_lhs(compiler, connection) + rhs, rhs_params = self.process_rhs(compiler, connection) + params = tuple(lhs_params) + tuple(rhs_params) + return "%s %s %s" % (lhs, self.postgres_operator, rhs), params + + +@Field.register_lookup +class Exact(FieldGetDbPrepValueMixin, BuiltinLookup): + lookup_name = "exact" + + def get_prep_lookup(self): + from django.db.models.sql.query import Query # avoid circular import + + if isinstance(self.rhs, Query): + if self.rhs.has_limit_one(): + if not self.rhs.has_select_fields: + self.rhs.clear_select_clause() + self.rhs.add_fields(["pk"]) + else: + raise ValueError( + "The QuerySet value for an exact lookup must be limited to " + "one result using slicing." + ) + return super().get_prep_lookup() + + def as_sql(self, compiler, connection): + # Avoid comparison against direct rhs if lhs is a boolean value. That + # turns "boolfield__exact=True" into "WHERE boolean_field" instead of + # "WHERE boolean_field = True" when allowed. + if ( + isinstance(self.rhs, bool) + and getattr(self.lhs, "conditional", False) + and connection.ops.conditional_expression_supported_in_where_clause( + self.lhs + ) + ): + lhs_sql, params = self.process_lhs(compiler, connection) + template = "%s" if self.rhs else "NOT %s" + return template % lhs_sql, params + return super().as_sql(compiler, connection) + + +@Field.register_lookup +class IExact(BuiltinLookup): + lookup_name = "iexact" + prepare_rhs = False + + def process_rhs(self, qn, connection): + rhs, params = super().process_rhs(qn, connection) + if params: + params[0] = connection.ops.prep_for_iexact_query(params[0]) + return rhs, params + + +@Field.register_lookup +class GreaterThan(FieldGetDbPrepValueMixin, BuiltinLookup): + lookup_name = "gt" + + +@Field.register_lookup +class GreaterThanOrEqual(FieldGetDbPrepValueMixin, BuiltinLookup): + lookup_name = "gte" + + +@Field.register_lookup +class LessThan(FieldGetDbPrepValueMixin, BuiltinLookup): + lookup_name = "lt" + + +@Field.register_lookup +class LessThanOrEqual(FieldGetDbPrepValueMixin, BuiltinLookup): + lookup_name = "lte" + + +class IntegerFieldOverflow: + underflow_exception = EmptyResultSet + overflow_exception = EmptyResultSet + + def process_rhs(self, compiler, connection): + rhs = self.rhs + if isinstance(rhs, int): + field_internal_type = self.lhs.output_field.get_internal_type() + min_value, max_value = connection.ops.integer_field_range( + field_internal_type + ) + if min_value is not None and rhs < min_value: + raise self.underflow_exception + if max_value is not None and rhs > max_value: + raise self.overflow_exception + return super().process_rhs(compiler, connection) + + +class IntegerFieldFloatRounding: + """ + Allow floats to work as query values for IntegerField. Without this, the + decimal portion of the float would always be discarded. + """ + + def get_prep_lookup(self): + if isinstance(self.rhs, float): + self.rhs = math.ceil(self.rhs) + return super().get_prep_lookup() + + +@IntegerField.register_lookup +class IntegerFieldExact(IntegerFieldOverflow, Exact): + pass + + +@IntegerField.register_lookup +class IntegerGreaterThan(IntegerFieldOverflow, GreaterThan): + underflow_exception = FullResultSet + + +@IntegerField.register_lookup +class IntegerGreaterThanOrEqual( + IntegerFieldOverflow, IntegerFieldFloatRounding, GreaterThanOrEqual +): + underflow_exception = FullResultSet + + +@IntegerField.register_lookup +class IntegerLessThan(IntegerFieldOverflow, IntegerFieldFloatRounding, LessThan): + overflow_exception = FullResultSet + + +@IntegerField.register_lookup +class IntegerLessThanOrEqual(IntegerFieldOverflow, LessThanOrEqual): + overflow_exception = FullResultSet + + +@Field.register_lookup +class In(FieldGetDbPrepValueIterableMixin, BuiltinLookup): + lookup_name = "in" + + def get_prep_lookup(self): + from django.db.models.sql.query import Query # avoid circular import + + if isinstance(self.rhs, Query): + self.rhs.clear_ordering(clear_default=True) + if not self.rhs.has_select_fields: + self.rhs.clear_select_clause() + self.rhs.add_fields(["pk"]) + return super().get_prep_lookup() + + def process_rhs(self, compiler, connection): + db_rhs = getattr(self.rhs, "_db", None) + if db_rhs is not None and db_rhs != connection.alias: + raise ValueError( + "Subqueries aren't allowed across different databases. Force " + "the inner query to be evaluated using `list(inner_query)`." + ) + + if self.rhs_is_direct_value(): + # Remove None from the list as NULL is never equal to anything. + try: + rhs = OrderedSet(self.rhs) + rhs.discard(None) + except TypeError: # Unhashable items in self.rhs + rhs = [r for r in self.rhs if r is not None] + + if not rhs: + raise EmptyResultSet + + # rhs should be an iterable; use batch_process_rhs() to + # prepare/transform those values. + sqls, sqls_params = self.batch_process_rhs(compiler, connection, rhs) + placeholder = "(" + ", ".join(sqls) + ")" + return (placeholder, sqls_params) + return super().process_rhs(compiler, connection) + + def get_rhs_op(self, connection, rhs): + return "IN %s" % rhs + + def as_sql(self, compiler, connection): + max_in_list_size = connection.ops.max_in_list_size() + if ( + self.rhs_is_direct_value() + and max_in_list_size + and len(self.rhs) > max_in_list_size + ): + return self.split_parameter_list_as_sql(compiler, connection) + return super().as_sql(compiler, connection) + + def split_parameter_list_as_sql(self, compiler, connection): + # This is a special case for databases which limit the number of + # elements which can appear in an 'IN' clause. + max_in_list_size = connection.ops.max_in_list_size() + lhs, lhs_params = self.process_lhs(compiler, connection) + rhs, rhs_params = self.batch_process_rhs(compiler, connection) + in_clause_elements = ["("] + params = [] + for offset in range(0, len(rhs_params), max_in_list_size): + if offset > 0: + in_clause_elements.append(" OR ") + in_clause_elements.append("%s IN (" % lhs) + params.extend(lhs_params) + sqls = rhs[offset : offset + max_in_list_size] + sqls_params = rhs_params[offset : offset + max_in_list_size] + param_group = ", ".join(sqls) + in_clause_elements.append(param_group) + in_clause_elements.append(")") + params.extend(sqls_params) + in_clause_elements.append(")") + return "".join(in_clause_elements), params + + +class PatternLookup(BuiltinLookup): + param_pattern = "%%%s%%" + prepare_rhs = False + + def get_rhs_op(self, connection, rhs): + # Assume we are in startswith. We need to produce SQL like: + # col LIKE %s, ['thevalue%'] + # For python values we can (and should) do that directly in Python, + # but if the value is for example reference to other column, then + # we need to add the % pattern match to the lookup by something like + # col LIKE othercol || '%%' + # So, for Python values we don't need any special pattern, but for + # SQL reference values or SQL transformations we need the correct + # pattern added. + if hasattr(self.rhs, "as_sql") or self.bilateral_transforms: + pattern = connection.pattern_ops[self.lookup_name].format( + connection.pattern_esc + ) + return pattern.format(rhs) + else: + return super().get_rhs_op(connection, rhs) + + def process_rhs(self, qn, connection): + rhs, params = super().process_rhs(qn, connection) + if self.rhs_is_direct_value() and params and not self.bilateral_transforms: + params[0] = self.param_pattern % connection.ops.prep_for_like_query( + params[0] + ) + return rhs, params + + +@Field.register_lookup +class Contains(PatternLookup): + lookup_name = "contains" + + +@Field.register_lookup +class IContains(Contains): + lookup_name = "icontains" + + +@Field.register_lookup +class StartsWith(PatternLookup): + lookup_name = "startswith" + param_pattern = "%s%%" + + +@Field.register_lookup +class IStartsWith(StartsWith): + lookup_name = "istartswith" + + +@Field.register_lookup +class EndsWith(PatternLookup): + lookup_name = "endswith" + param_pattern = "%%%s" + + +@Field.register_lookup +class IEndsWith(EndsWith): + lookup_name = "iendswith" + + +@Field.register_lookup +class Range(FieldGetDbPrepValueIterableMixin, BuiltinLookup): + lookup_name = "range" + + def get_rhs_op(self, connection, rhs): + return "BETWEEN %s AND %s" % (rhs[0], rhs[1]) + + +@Field.register_lookup +class IsNull(BuiltinLookup): + lookup_name = "isnull" + prepare_rhs = False + + def as_sql(self, compiler, connection): + if not isinstance(self.rhs, bool): + raise ValueError( + "The QuerySet value for an isnull lookup must be True or False." + ) + if isinstance(self.lhs, Value): + if self.lhs.value is None or ( + self.lhs.value == "" + and connection.features.interprets_empty_strings_as_nulls + ): + result_exception = FullResultSet if self.rhs else EmptyResultSet + else: + result_exception = EmptyResultSet if self.rhs else FullResultSet + raise result_exception + sql, params = self.process_lhs(compiler, connection) + if self.rhs: + return "%s IS NULL" % sql, params + else: + return "%s IS NOT NULL" % sql, params + + +@Field.register_lookup +class Regex(BuiltinLookup): + lookup_name = "regex" + prepare_rhs = False + + def as_sql(self, compiler, connection): + if self.lookup_name in connection.operators: + return super().as_sql(compiler, connection) + else: + lhs, lhs_params = self.process_lhs(compiler, connection) + rhs, rhs_params = self.process_rhs(compiler, connection) + sql_template = connection.ops.regex_lookup(self.lookup_name) + return sql_template % (lhs, rhs), lhs_params + rhs_params + + +@Field.register_lookup +class IRegex(Regex): + lookup_name = "iregex" + + +class YearLookup(Lookup): + def year_lookup_bounds(self, connection, year): + from django.db.models.functions import ExtractIsoYear + + iso_year = isinstance(self.lhs, ExtractIsoYear) + output_field = self.lhs.lhs.output_field + if isinstance(output_field, DateTimeField): + bounds = connection.ops.year_lookup_bounds_for_datetime_field( + year, + iso_year=iso_year, + ) + else: + bounds = connection.ops.year_lookup_bounds_for_date_field( + year, + iso_year=iso_year, + ) + return bounds + + def as_sql(self, compiler, connection): + # Avoid the extract operation if the rhs is a direct value to allow + # indexes to be used. + if self.rhs_is_direct_value(): + # Skip the extract part by directly using the originating field, + # that is self.lhs.lhs. + lhs_sql, params = self.process_lhs(compiler, connection, self.lhs.lhs) + rhs_sql, _ = self.process_rhs(compiler, connection) + rhs_sql = self.get_direct_rhs_sql(connection, rhs_sql) + start, finish = self.year_lookup_bounds(connection, self.rhs) + params.extend(self.get_bound_params(start, finish)) + return "%s %s" % (lhs_sql, rhs_sql), params + return super().as_sql(compiler, connection) + + def get_direct_rhs_sql(self, connection, rhs): + return connection.operators[self.lookup_name] % rhs + + def get_bound_params(self, start, finish): + raise NotImplementedError( + "subclasses of YearLookup must provide a get_bound_params() method" + ) + + +class YearExact(YearLookup, Exact): + def get_direct_rhs_sql(self, connection, rhs): + return "BETWEEN %s AND %s" + + def get_bound_params(self, start, finish): + return (start, finish) + + +class YearGt(YearLookup, GreaterThan): + def get_bound_params(self, start, finish): + return (finish,) + + +class YearGte(YearLookup, GreaterThanOrEqual): + def get_bound_params(self, start, finish): + return (start,) + + +class YearLt(YearLookup, LessThan): + def get_bound_params(self, start, finish): + return (start,) + + +class YearLte(YearLookup, LessThanOrEqual): + def get_bound_params(self, start, finish): + return (finish,) + + +class UUIDTextMixin: + """ + Strip hyphens from a value when filtering a UUIDField on backends without + a native datatype for UUID. + """ + + def process_rhs(self, qn, connection): + if not connection.features.has_native_uuid_field: + from django.db.models.functions import Replace + + if self.rhs_is_direct_value(): + self.rhs = Value(self.rhs) + self.rhs = Replace( + self.rhs, Value("-"), Value(""), output_field=CharField() + ) + rhs, params = super().process_rhs(qn, connection) + return rhs, params + + +@UUIDField.register_lookup +class UUIDIExact(UUIDTextMixin, IExact): + pass + + +@UUIDField.register_lookup +class UUIDContains(UUIDTextMixin, Contains): + pass + + +@UUIDField.register_lookup +class UUIDIContains(UUIDTextMixin, IContains): + pass + + +@UUIDField.register_lookup +class UUIDStartsWith(UUIDTextMixin, StartsWith): + pass + + +@UUIDField.register_lookup +class UUIDIStartsWith(UUIDTextMixin, IStartsWith): + pass + + +@UUIDField.register_lookup +class UUIDEndsWith(UUIDTextMixin, EndsWith): + pass + + +@UUIDField.register_lookup +class UUIDIEndsWith(UUIDTextMixin, IEndsWith): + pass diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/manager.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/manager.py new file mode 100644 index 0000000..467e79f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/manager.py @@ -0,0 +1,213 @@ +import copy +import inspect +from functools import wraps +from importlib import import_module + +from django.db import router +from django.db.models.query import QuerySet + + +class BaseManager: + # To retain order, track each time a Manager instance is created. + creation_counter = 0 + + # Set to True for the 'objects' managers that are automatically created. + auto_created = False + + #: If set to True the manager will be serialized into migrations and will + #: thus be available in e.g. RunPython operations. + use_in_migrations = False + + def __new__(cls, *args, **kwargs): + # Capture the arguments to make returning them trivial. + obj = super().__new__(cls) + obj._constructor_args = (args, kwargs) + return obj + + def __init__(self): + super().__init__() + self._set_creation_counter() + self.model = None + self.name = None + self._db = None + self._hints = {} + + def __str__(self): + """Return "app_label.model_label.manager_name".""" + return "%s.%s" % (self.model._meta.label, self.name) + + def __class_getitem__(cls, *args, **kwargs): + return cls + + def deconstruct(self): + """ + Return a 5-tuple of the form (as_manager (True), manager_class, + queryset_class, args, kwargs). + + Raise a ValueError if the manager is dynamically generated. + """ + qs_class = self._queryset_class + if getattr(self, "_built_with_as_manager", False): + # using MyQuerySet.as_manager() + return ( + True, # as_manager + None, # manager_class + "%s.%s" % (qs_class.__module__, qs_class.__name__), # qs_class + None, # args + None, # kwargs + ) + else: + module_name = self.__module__ + name = self.__class__.__name__ + # Make sure it's actually there and not an inner class + module = import_module(module_name) + if not hasattr(module, name): + raise ValueError( + "Could not find manager %s in %s.\n" + "Please note that you need to inherit from managers you " + "dynamically generated with 'from_queryset()'." + % (name, module_name) + ) + return ( + False, # as_manager + "%s.%s" % (module_name, name), # manager_class + None, # qs_class + self._constructor_args[0], # args + self._constructor_args[1], # kwargs + ) + + def check(self, **kwargs): + return [] + + @classmethod + def _get_queryset_methods(cls, queryset_class): + def create_method(name, method): + @wraps(method) + def manager_method(self, *args, **kwargs): + return getattr(self.get_queryset(), name)(*args, **kwargs) + + return manager_method + + new_methods = {} + for name, method in inspect.getmembers( + queryset_class, predicate=inspect.isfunction + ): + # Only copy missing methods. + if hasattr(cls, name): + continue + # Only copy public methods or methods with the attribute + # queryset_only=False. + queryset_only = getattr(method, "queryset_only", None) + if queryset_only or (queryset_only is None and name.startswith("_")): + continue + # Copy the method onto the manager. + new_methods[name] = create_method(name, method) + return new_methods + + @classmethod + def from_queryset(cls, queryset_class, class_name=None): + if class_name is None: + class_name = "%sFrom%s" % (cls.__name__, queryset_class.__name__) + return type( + class_name, + (cls,), + { + "_queryset_class": queryset_class, + **cls._get_queryset_methods(queryset_class), + }, + ) + + def contribute_to_class(self, cls, name): + self.name = self.name or name + self.model = cls + + setattr(cls, name, ManagerDescriptor(self)) + + cls._meta.add_manager(self) + + def _set_creation_counter(self): + """ + Set the creation counter value for this instance and increment the + class-level copy. + """ + self.creation_counter = BaseManager.creation_counter + BaseManager.creation_counter += 1 + + def db_manager(self, using=None, hints=None): + obj = copy.copy(self) + obj._db = using or self._db + obj._hints = hints or self._hints + return obj + + @property + def db(self): + return self._db or router.db_for_read(self.model, **self._hints) + + ####################### + # PROXIES TO QUERYSET # + ####################### + + def get_queryset(self): + """ + Return a new QuerySet object. Subclasses can override this method to + customize the behavior of the Manager. + """ + return self._queryset_class(model=self.model, using=self._db, hints=self._hints) + + def all(self): + # We can't proxy this method through the `QuerySet` like we do for the + # rest of the `QuerySet` methods. This is because `QuerySet.all()` + # works by creating a "copy" of the current queryset and in making said + # copy, all the cached `prefetch_related` lookups are lost. See the + # implementation of `RelatedManager.get_queryset()` for a better + # understanding of how this comes into play. + return self.get_queryset() + + def __eq__(self, other): + return ( + isinstance(other, self.__class__) + and self._constructor_args == other._constructor_args + ) + + def __hash__(self): + return id(self) + + +class Manager(BaseManager.from_queryset(QuerySet)): + pass + + +class ManagerDescriptor: + def __init__(self, manager): + self.manager = manager + + def __get__(self, instance, cls=None): + if instance is not None: + raise AttributeError( + "Manager isn't accessible via %s instances" % cls.__name__ + ) + + if cls._meta.abstract: + raise AttributeError( + "Manager isn't available; %s is abstract" % (cls._meta.object_name,) + ) + + if cls._meta.swapped: + raise AttributeError( + "Manager isn't available; '%s' has been swapped for '%s'" + % ( + cls._meta.label, + cls._meta.swapped, + ) + ) + + return cls._meta.managers_map[self.manager.name] + + +class EmptyManager(Manager): + def __init__(self, model): + super().__init__() + self.model = model + + def get_queryset(self): + return super().get_queryset().none() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/options.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/options.py new file mode 100644 index 0000000..76017fc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/options.py @@ -0,0 +1,1018 @@ +import bisect +import copy +import inspect +import warnings +from collections import defaultdict + +from django.apps import apps +from django.conf import settings +from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured +from django.db import connections +from django.db.models import AutoField, Manager, OrderWrt, UniqueConstraint +from django.db.models.query_utils import PathInfo +from django.utils.datastructures import ImmutableList, OrderedSet +from django.utils.deprecation import RemovedInDjango51Warning +from django.utils.functional import cached_property +from django.utils.module_loading import import_string +from django.utils.text import camel_case_to_spaces, format_lazy +from django.utils.translation import override + +PROXY_PARENTS = object() + +EMPTY_RELATION_TREE = () + +IMMUTABLE_WARNING = ( + "The return type of '%s' should never be mutated. If you want to manipulate this " + "list for your own use, make a copy first." +) + +DEFAULT_NAMES = ( + "verbose_name", + "verbose_name_plural", + "db_table", + "db_table_comment", + "ordering", + "unique_together", + "permissions", + "get_latest_by", + "order_with_respect_to", + "app_label", + "db_tablespace", + "abstract", + "managed", + "proxy", + "swappable", + "auto_created", + "index_together", # RemovedInDjango51Warning. + "apps", + "default_permissions", + "select_on_save", + "default_related_name", + "required_db_features", + "required_db_vendor", + "base_manager_name", + "default_manager_name", + "indexes", + "constraints", +) + + +def normalize_together(option_together): + """ + option_together can be either a tuple of tuples, or a single + tuple of two strings. Normalize it to a tuple of tuples, so that + calling code can uniformly expect that. + """ + try: + if not option_together: + return () + if not isinstance(option_together, (tuple, list)): + raise TypeError + first_element = option_together[0] + if not isinstance(first_element, (tuple, list)): + option_together = (option_together,) + # Normalize everything to tuples + return tuple(tuple(ot) for ot in option_together) + except TypeError: + # If the value of option_together isn't valid, return it + # verbatim; this will be picked up by the check framework later. + return option_together + + +def make_immutable_fields_list(name, data): + return ImmutableList(data, warning=IMMUTABLE_WARNING % name) + + +class Options: + FORWARD_PROPERTIES = { + "fields", + "many_to_many", + "concrete_fields", + "local_concrete_fields", + "_non_pk_concrete_field_names", + "_reverse_one_to_one_field_names", + "_forward_fields_map", + "managers", + "managers_map", + "base_manager", + "default_manager", + } + REVERSE_PROPERTIES = {"related_objects", "fields_map", "_relation_tree"} + + default_apps = apps + + def __init__(self, meta, app_label=None): + self._get_fields_cache = {} + self.local_fields = [] + self.local_many_to_many = [] + self.private_fields = [] + self.local_managers = [] + self.base_manager_name = None + self.default_manager_name = None + self.model_name = None + self.verbose_name = None + self.verbose_name_plural = None + self.db_table = "" + self.db_table_comment = "" + self.ordering = [] + self._ordering_clash = False + self.indexes = [] + self.constraints = [] + self.unique_together = [] + self.index_together = [] # RemovedInDjango51Warning. + self.select_on_save = False + self.default_permissions = ("add", "change", "delete", "view") + self.permissions = [] + self.object_name = None + self.app_label = app_label + self.get_latest_by = None + self.order_with_respect_to = None + self.db_tablespace = settings.DEFAULT_TABLESPACE + self.required_db_features = [] + self.required_db_vendor = None + self.meta = meta + self.pk = None + self.auto_field = None + self.abstract = False + self.managed = True + self.proxy = False + # For any class that is a proxy (including automatically created + # classes for deferred object loading), proxy_for_model tells us + # which class this model is proxying. Note that proxy_for_model + # can create a chain of proxy models. For non-proxy models, the + # variable is always None. + self.proxy_for_model = None + # For any non-abstract class, the concrete class is the model + # in the end of the proxy_for_model chain. In particular, for + # concrete models, the concrete_model is always the class itself. + self.concrete_model = None + self.swappable = None + self.parents = {} + self.auto_created = False + + # List of all lookups defined in ForeignKey 'limit_choices_to' options + # from *other* models. Needed for some admin checks. Internal use only. + self.related_fkey_lookups = [] + + # A custom app registry to use, if you're making a separate model set. + self.apps = self.default_apps + + self.default_related_name = None + + @property + def label(self): + return "%s.%s" % (self.app_label, self.object_name) + + @property + def label_lower(self): + return "%s.%s" % (self.app_label, self.model_name) + + @property + def app_config(self): + # Don't go through get_app_config to avoid triggering imports. + return self.apps.app_configs.get(self.app_label) + + def contribute_to_class(self, cls, name): + from django.db import connection + from django.db.backends.utils import truncate_name + + cls._meta = self + self.model = cls + # First, construct the default values for these options. + self.object_name = cls.__name__ + self.model_name = self.object_name.lower() + self.verbose_name = camel_case_to_spaces(self.object_name) + + # Store the original user-defined values for each option, + # for use when serializing the model definition + self.original_attrs = {} + + # Next, apply any overridden values from 'class Meta'. + if self.meta: + meta_attrs = self.meta.__dict__.copy() + for name in self.meta.__dict__: + # Ignore any private attributes that Django doesn't care about. + # NOTE: We can't modify a dictionary's contents while looping + # over it, so we loop over the *original* dictionary instead. + if name.startswith("_"): + del meta_attrs[name] + for attr_name in DEFAULT_NAMES: + if attr_name in meta_attrs: + setattr(self, attr_name, meta_attrs.pop(attr_name)) + self.original_attrs[attr_name] = getattr(self, attr_name) + elif hasattr(self.meta, attr_name): + setattr(self, attr_name, getattr(self.meta, attr_name)) + self.original_attrs[attr_name] = getattr(self, attr_name) + + self.unique_together = normalize_together(self.unique_together) + self.index_together = normalize_together(self.index_together) + if self.index_together: + warnings.warn( + f"'index_together' is deprecated. Use 'Meta.indexes' in " + f"{self.label!r} instead.", + RemovedInDjango51Warning, + ) + # App label/class name interpolation for names of constraints and + # indexes. + if not getattr(cls._meta, "abstract", False): + for attr_name in {"constraints", "indexes"}: + objs = getattr(self, attr_name, []) + setattr(self, attr_name, self._format_names_with_class(cls, objs)) + + # verbose_name_plural is a special case because it uses a 's' + # by default. + if self.verbose_name_plural is None: + self.verbose_name_plural = format_lazy("{}s", self.verbose_name) + + # order_with_respect_and ordering are mutually exclusive. + self._ordering_clash = bool(self.ordering and self.order_with_respect_to) + + # Any leftover attributes must be invalid. + if meta_attrs != {}: + raise TypeError( + "'class Meta' got invalid attribute(s): %s" % ",".join(meta_attrs) + ) + else: + self.verbose_name_plural = format_lazy("{}s", self.verbose_name) + del self.meta + + # If the db_table wasn't provided, use the app_label + model_name. + if not self.db_table: + self.db_table = "%s_%s" % (self.app_label, self.model_name) + self.db_table = truncate_name( + self.db_table, connection.ops.max_name_length() + ) + + def _format_names_with_class(self, cls, objs): + """App label/class name interpolation for object names.""" + new_objs = [] + for obj in objs: + obj = obj.clone() + obj.name = obj.name % { + "app_label": cls._meta.app_label.lower(), + "class": cls.__name__.lower(), + } + new_objs.append(obj) + return new_objs + + def _get_default_pk_class(self): + pk_class_path = getattr( + self.app_config, + "default_auto_field", + settings.DEFAULT_AUTO_FIELD, + ) + if self.app_config and self.app_config._is_default_auto_field_overridden: + app_config_class = type(self.app_config) + source = ( + f"{app_config_class.__module__}." + f"{app_config_class.__qualname__}.default_auto_field" + ) + else: + source = "DEFAULT_AUTO_FIELD" + if not pk_class_path: + raise ImproperlyConfigured(f"{source} must not be empty.") + try: + pk_class = import_string(pk_class_path) + except ImportError as e: + msg = ( + f"{source} refers to the module '{pk_class_path}' that could " + f"not be imported." + ) + raise ImproperlyConfigured(msg) from e + if not issubclass(pk_class, AutoField): + raise ValueError( + f"Primary key '{pk_class_path}' referred by {source} must " + f"subclass AutoField." + ) + return pk_class + + def _prepare(self, model): + if self.order_with_respect_to: + # The app registry will not be ready at this point, so we cannot + # use get_field(). + query = self.order_with_respect_to + try: + self.order_with_respect_to = next( + f + for f in self._get_fields(reverse=False) + if f.name == query or f.attname == query + ) + except StopIteration: + raise FieldDoesNotExist( + "%s has no field named '%s'" % (self.object_name, query) + ) + + self.ordering = ("_order",) + if not any( + isinstance(field, OrderWrt) for field in model._meta.local_fields + ): + model.add_to_class("_order", OrderWrt()) + else: + self.order_with_respect_to = None + + if self.pk is None: + if self.parents: + # Promote the first parent link in lieu of adding yet another + # field. + field = next(iter(self.parents.values())) + # Look for a local field with the same name as the + # first parent link. If a local field has already been + # created, use it instead of promoting the parent + already_created = [ + fld for fld in self.local_fields if fld.name == field.name + ] + if already_created: + field = already_created[0] + field.primary_key = True + self.setup_pk(field) + else: + pk_class = self._get_default_pk_class() + auto = pk_class(verbose_name="ID", primary_key=True, auto_created=True) + model.add_to_class("id", auto) + + def add_manager(self, manager): + self.local_managers.append(manager) + self._expire_cache() + + def add_field(self, field, private=False): + # Insert the given field in the order in which it was created, using + # the "creation_counter" attribute of the field. + # Move many-to-many related fields from self.fields into + # self.many_to_many. + if private: + self.private_fields.append(field) + elif field.is_relation and field.many_to_many: + bisect.insort(self.local_many_to_many, field) + else: + bisect.insort(self.local_fields, field) + self.setup_pk(field) + + # If the field being added is a relation to another known field, + # expire the cache on this field and the forward cache on the field + # being referenced, because there will be new relationships in the + # cache. Otherwise, expire the cache of references *to* this field. + # The mechanism for getting at the related model is slightly odd - + # ideally, we'd just ask for field.related_model. However, related_model + # is a cached property, and all the models haven't been loaded yet, so + # we need to make sure we don't cache a string reference. + if ( + field.is_relation + and hasattr(field.remote_field, "model") + and field.remote_field.model + ): + try: + field.remote_field.model._meta._expire_cache(forward=False) + except AttributeError: + pass + self._expire_cache() + else: + self._expire_cache(reverse=False) + + def setup_pk(self, field): + if not self.pk and field.primary_key: + self.pk = field + field.serialize = False + + def setup_proxy(self, target): + """ + Do the internal setup so that the current model is a proxy for + "target". + """ + self.pk = target._meta.pk + self.proxy_for_model = target + self.db_table = target._meta.db_table + + def __repr__(self): + return "" % self.object_name + + def __str__(self): + return self.label_lower + + def can_migrate(self, connection): + """ + Return True if the model can/should be migrated on the `connection`. + `connection` can be either a real connection or a connection alias. + """ + if self.proxy or self.swapped or not self.managed: + return False + if isinstance(connection, str): + connection = connections[connection] + if self.required_db_vendor: + return self.required_db_vendor == connection.vendor + if self.required_db_features: + return all( + getattr(connection.features, feat, False) + for feat in self.required_db_features + ) + return True + + @property + def verbose_name_raw(self): + """Return the untranslated verbose name.""" + with override(None): + return str(self.verbose_name) + + @property + def swapped(self): + """ + Has this model been swapped out for another? If so, return the model + name of the replacement; otherwise, return None. + + For historical reasons, model name lookups using get_model() are + case insensitive, so we make sure we are case insensitive here. + """ + if self.swappable: + swapped_for = getattr(settings, self.swappable, None) + if swapped_for: + try: + swapped_label, swapped_object = swapped_for.split(".") + except ValueError: + # setting not in the format app_label.model_name + # raising ImproperlyConfigured here causes problems with + # test cleanup code - instead it is raised in get_user_model + # or as part of validation. + return swapped_for + + if ( + "%s.%s" % (swapped_label, swapped_object.lower()) + != self.label_lower + ): + return swapped_for + return None + + @cached_property + def managers(self): + managers = [] + seen_managers = set() + bases = (b for b in self.model.mro() if hasattr(b, "_meta")) + for depth, base in enumerate(bases): + for manager in base._meta.local_managers: + if manager.name in seen_managers: + continue + + manager = copy.copy(manager) + manager.model = self.model + seen_managers.add(manager.name) + managers.append((depth, manager.creation_counter, manager)) + + return make_immutable_fields_list( + "managers", + (m[2] for m in sorted(managers)), + ) + + @cached_property + def managers_map(self): + return {manager.name: manager for manager in self.managers} + + @cached_property + def base_manager(self): + base_manager_name = self.base_manager_name + if not base_manager_name: + # Get the first parent's base_manager_name if there's one. + for parent in self.model.mro()[1:]: + if hasattr(parent, "_meta"): + if parent._base_manager.name != "_base_manager": + base_manager_name = parent._base_manager.name + break + + if base_manager_name: + try: + return self.managers_map[base_manager_name] + except KeyError: + raise ValueError( + "%s has no manager named %r" + % ( + self.object_name, + base_manager_name, + ) + ) + + manager = Manager() + manager.name = "_base_manager" + manager.model = self.model + manager.auto_created = True + return manager + + @cached_property + def default_manager(self): + default_manager_name = self.default_manager_name + if not default_manager_name and not self.local_managers: + # Get the first parent's default_manager_name if there's one. + for parent in self.model.mro()[1:]: + if hasattr(parent, "_meta"): + default_manager_name = parent._meta.default_manager_name + break + + if default_manager_name: + try: + return self.managers_map[default_manager_name] + except KeyError: + raise ValueError( + "%s has no manager named %r" + % ( + self.object_name, + default_manager_name, + ) + ) + + if self.managers: + return self.managers[0] + + @cached_property + def fields(self): + """ + Return a list of all forward fields on the model and its parents, + excluding ManyToManyFields. + + Private API intended only to be used by Django itself; get_fields() + combined with filtering of field properties is the public API for + obtaining this field list. + """ + + # For legacy reasons, the fields property should only contain forward + # fields that are not private or with a m2m cardinality. Therefore we + # pass these three filters as filters to the generator. + # The third lambda is a longwinded way of checking f.related_model - we don't + # use that property directly because related_model is a cached property, + # and all the models may not have been loaded yet; we don't want to cache + # the string reference to the related_model. + def is_not_an_m2m_field(f): + return not (f.is_relation and f.many_to_many) + + def is_not_a_generic_relation(f): + return not (f.is_relation and f.one_to_many) + + def is_not_a_generic_foreign_key(f): + return not ( + f.is_relation + and f.many_to_one + and not (hasattr(f.remote_field, "model") and f.remote_field.model) + ) + + return make_immutable_fields_list( + "fields", + ( + f + for f in self._get_fields(reverse=False) + if is_not_an_m2m_field(f) + and is_not_a_generic_relation(f) + and is_not_a_generic_foreign_key(f) + ), + ) + + @cached_property + def concrete_fields(self): + """ + Return a list of all concrete fields on the model and its parents. + + Private API intended only to be used by Django itself; get_fields() + combined with filtering of field properties is the public API for + obtaining this field list. + """ + return make_immutable_fields_list( + "concrete_fields", (f for f in self.fields if f.concrete) + ) + + @cached_property + def local_concrete_fields(self): + """ + Return a list of all concrete fields on the model. + + Private API intended only to be used by Django itself; get_fields() + combined with filtering of field properties is the public API for + obtaining this field list. + """ + return make_immutable_fields_list( + "local_concrete_fields", (f for f in self.local_fields if f.concrete) + ) + + @cached_property + def many_to_many(self): + """ + Return a list of all many to many fields on the model and its parents. + + Private API intended only to be used by Django itself; get_fields() + combined with filtering of field properties is the public API for + obtaining this list. + """ + return make_immutable_fields_list( + "many_to_many", + ( + f + for f in self._get_fields(reverse=False) + if f.is_relation and f.many_to_many + ), + ) + + @cached_property + def related_objects(self): + """ + Return all related objects pointing to the current model. The related + objects can come from a one-to-one, one-to-many, or many-to-many field + relation type. + + Private API intended only to be used by Django itself; get_fields() + combined with filtering of field properties is the public API for + obtaining this field list. + """ + all_related_fields = self._get_fields( + forward=False, reverse=True, include_hidden=True + ) + return make_immutable_fields_list( + "related_objects", + ( + obj + for obj in all_related_fields + if not obj.hidden or obj.field.many_to_many + ), + ) + + @cached_property + def _forward_fields_map(self): + res = {} + fields = self._get_fields(reverse=False) + for field in fields: + res[field.name] = field + # Due to the way Django's internals work, get_field() should also + # be able to fetch a field by attname. In the case of a concrete + # field with relation, includes the *_id name too + try: + res[field.attname] = field + except AttributeError: + pass + return res + + @cached_property + def fields_map(self): + res = {} + fields = self._get_fields(forward=False, include_hidden=True) + for field in fields: + res[field.name] = field + # Due to the way Django's internals work, get_field() should also + # be able to fetch a field by attname. In the case of a concrete + # field with relation, includes the *_id name too + try: + res[field.attname] = field + except AttributeError: + pass + return res + + def get_field(self, field_name): + """ + Return a field instance given the name of a forward or reverse field. + """ + try: + # In order to avoid premature loading of the relation tree + # (expensive) we prefer checking if the field is a forward field. + return self._forward_fields_map[field_name] + except KeyError: + # If the app registry is not ready, reverse fields are + # unavailable, therefore we throw a FieldDoesNotExist exception. + if not self.apps.models_ready: + raise FieldDoesNotExist( + "%s has no field named '%s'. The app cache isn't ready yet, " + "so if this is an auto-created related field, it won't " + "be available yet." % (self.object_name, field_name) + ) + + try: + # Retrieve field instance by name from cached or just-computed + # field map. + return self.fields_map[field_name] + except KeyError: + raise FieldDoesNotExist( + "%s has no field named '%s'" % (self.object_name, field_name) + ) + + def get_base_chain(self, model): + """ + Return a list of parent classes leading to `model` (ordered from + closest to most distant ancestor). This has to handle the case where + `model` is a grandparent or even more distant relation. + """ + if not self.parents: + return [] + if model in self.parents: + return [model] + for parent in self.parents: + res = parent._meta.get_base_chain(model) + if res: + res.insert(0, parent) + return res + return [] + + def get_parent_list(self): + """ + Return all the ancestors of this model as a list ordered by MRO. + Useful for determining if something is an ancestor, regardless of lineage. + """ + result = OrderedSet(self.parents) + for parent in self.parents: + for ancestor in parent._meta.get_parent_list(): + result.add(ancestor) + return list(result) + + def get_ancestor_link(self, ancestor): + """ + Return the field on the current model which points to the given + "ancestor". This is possible an indirect link (a pointer to a parent + model, which points, eventually, to the ancestor). Used when + constructing table joins for model inheritance. + + Return None if the model isn't an ancestor of this one. + """ + if ancestor in self.parents: + return self.parents[ancestor] + for parent in self.parents: + # Tries to get a link field from the immediate parent + parent_link = parent._meta.get_ancestor_link(ancestor) + if parent_link: + # In case of a proxied model, the first link + # of the chain to the ancestor is that parent + # links + return self.parents[parent] or parent_link + + def get_path_to_parent(self, parent): + """ + Return a list of PathInfos containing the path from the current + model to the parent model, or an empty list if parent is not a + parent of the current model. + """ + if self.model is parent: + return [] + # Skip the chain of proxy to the concrete proxied model. + proxied_model = self.concrete_model + path = [] + opts = self + for int_model in self.get_base_chain(parent): + if int_model is proxied_model: + opts = int_model._meta + else: + final_field = opts.parents[int_model] + targets = (final_field.remote_field.get_related_field(),) + opts = int_model._meta + path.append( + PathInfo( + from_opts=final_field.model._meta, + to_opts=opts, + target_fields=targets, + join_field=final_field, + m2m=False, + direct=True, + filtered_relation=None, + ) + ) + return path + + def get_path_from_parent(self, parent): + """ + Return a list of PathInfos containing the path from the parent + model to the current model, or an empty list if parent is not a + parent of the current model. + """ + if self.model is parent: + return [] + model = self.concrete_model + # Get a reversed base chain including both the current and parent + # models. + chain = model._meta.get_base_chain(parent) + chain.reverse() + chain.append(model) + # Construct a list of the PathInfos between models in chain. + path = [] + for i, ancestor in enumerate(chain[:-1]): + child = chain[i + 1] + link = child._meta.get_ancestor_link(ancestor) + path.extend(link.reverse_path_infos) + return path + + def _populate_directed_relation_graph(self): + """ + This method is used by each model to find its reverse objects. As this + method is very expensive and is accessed frequently (it looks up every + field in a model, in every app), it is computed on first access and then + is set as a property on every model. + """ + related_objects_graph = defaultdict(list) + + all_models = self.apps.get_models(include_auto_created=True) + for model in all_models: + opts = model._meta + # Abstract model's fields are copied to child models, hence we will + # see the fields from the child models. + if opts.abstract: + continue + fields_with_relations = ( + f + for f in opts._get_fields(reverse=False, include_parents=False) + if f.is_relation and f.related_model is not None + ) + for f in fields_with_relations: + if not isinstance(f.remote_field.model, str): + remote_label = f.remote_field.model._meta.concrete_model._meta.label + related_objects_graph[remote_label].append(f) + + for model in all_models: + # Set the relation_tree using the internal __dict__. In this way + # we avoid calling the cached property. In attribute lookup, + # __dict__ takes precedence over a data descriptor (such as + # @cached_property). This means that the _meta._relation_tree is + # only called if related_objects is not in __dict__. + related_objects = related_objects_graph[ + model._meta.concrete_model._meta.label + ] + model._meta.__dict__["_relation_tree"] = related_objects + # It seems it is possible that self is not in all_models, so guard + # against that with default for get(). + return self.__dict__.get("_relation_tree", EMPTY_RELATION_TREE) + + @cached_property + def _relation_tree(self): + return self._populate_directed_relation_graph() + + def _expire_cache(self, forward=True, reverse=True): + # This method is usually called by apps.cache_clear(), when the + # registry is finalized, or when a new field is added. + if forward: + for cache_key in self.FORWARD_PROPERTIES: + if cache_key in self.__dict__: + delattr(self, cache_key) + if reverse and not self.abstract: + for cache_key in self.REVERSE_PROPERTIES: + if cache_key in self.__dict__: + delattr(self, cache_key) + self._get_fields_cache = {} + + def get_fields(self, include_parents=True, include_hidden=False): + """ + Return a list of fields associated to the model. By default, include + forward and reverse fields, fields derived from inheritance, but not + hidden fields. The returned fields can be changed using the parameters: + + - include_parents: include fields derived from inheritance + - include_hidden: include fields that have a related_name that + starts with a "+" + """ + if include_parents is False: + include_parents = PROXY_PARENTS + return self._get_fields( + include_parents=include_parents, include_hidden=include_hidden + ) + + def _get_fields( + self, + forward=True, + reverse=True, + include_parents=True, + include_hidden=False, + topmost_call=True, + ): + """ + Internal helper function to return fields of the model. + * If forward=True, then fields defined on this model are returned. + * If reverse=True, then relations pointing to this model are returned. + * If include_hidden=True, then fields with is_hidden=True are returned. + * The include_parents argument toggles if fields from parent models + should be included. It has three values: True, False, and + PROXY_PARENTS. When set to PROXY_PARENTS, the call will return all + fields defined for the current model or any of its parents in the + parent chain to the model's concrete model. + """ + if include_parents not in (True, False, PROXY_PARENTS): + raise TypeError( + "Invalid argument for include_parents: %s" % (include_parents,) + ) + # This helper function is used to allow recursion in ``get_fields()`` + # implementation and to provide a fast way for Django's internals to + # access specific subsets of fields. + + # Creates a cache key composed of all arguments + cache_key = (forward, reverse, include_parents, include_hidden, topmost_call) + + try: + # In order to avoid list manipulation. Always return a shallow copy + # of the results. + return self._get_fields_cache[cache_key] + except KeyError: + pass + + fields = [] + # Recursively call _get_fields() on each parent, with the same + # options provided in this call. + if include_parents is not False: + # In diamond inheritance it is possible that we see the same model + # from two different routes. In that case, avoid adding fields from + # the same parent again. + parent_fields = set() + for parent in self.parents: + if ( + parent._meta.concrete_model != self.concrete_model + and include_parents == PROXY_PARENTS + ): + continue + for obj in parent._meta._get_fields( + forward=forward, + reverse=reverse, + include_parents=include_parents, + include_hidden=include_hidden, + topmost_call=False, + ): + if ( + not getattr(obj, "parent_link", False) + or obj.model == self.concrete_model + ) and obj not in parent_fields: + fields.append(obj) + parent_fields.add(obj) + + if reverse and not self.proxy: + # Tree is computed once and cached until the app cache is expired. + # It is composed of a list of fields pointing to the current model + # from other models. + all_fields = self._relation_tree + for field in all_fields: + # If hidden fields should be included or the relation is not + # intentionally hidden, add to the fields dict. + if include_hidden or not field.remote_field.hidden: + fields.append(field.remote_field) + + if forward: + fields += self.local_fields + fields += self.local_many_to_many + # Private fields are recopied to each child model, and they get a + # different model as field.model in each child. Hence we have to + # add the private fields separately from the topmost call. If we + # did this recursively similar to local_fields, we would get field + # instances with field.model != self.model. + if topmost_call: + fields += self.private_fields + + # In order to avoid list manipulation. Always + # return a shallow copy of the results + fields = make_immutable_fields_list("get_fields()", fields) + + # Store result into cache for later access + self._get_fields_cache[cache_key] = fields + return fields + + @cached_property + def total_unique_constraints(self): + """ + Return a list of total unique constraints. Useful for determining set + of fields guaranteed to be unique for all rows. + """ + return [ + constraint + for constraint in self.constraints + if ( + isinstance(constraint, UniqueConstraint) + and constraint.condition is None + and not constraint.contains_expressions + ) + ] + + @cached_property + def _property_names(self): + """Return a set of the names of the properties defined on the model.""" + names = [] + for name in dir(self.model): + attr = inspect.getattr_static(self.model, name) + if isinstance(attr, property): + names.append(name) + return frozenset(names) + + @cached_property + def _non_pk_concrete_field_names(self): + """ + Return a set of the non-pk concrete field names defined on the model. + """ + names = [] + for field in self.concrete_fields: + if not field.primary_key: + names.append(field.name) + if field.name != field.attname: + names.append(field.attname) + return frozenset(names) + + @cached_property + def _reverse_one_to_one_field_names(self): + """ + Return a set of reverse one to one field names pointing to the current + model. + """ + return frozenset( + field.name for field in self.related_objects if field.one_to_one + ) + + @cached_property + def db_returning_fields(self): + """ + Private API intended only to be used by Django itself. + Fields to be returned after a database insert. + """ + return [ + field + for field in self._get_fields( + forward=True, reverse=False, include_parents=PROXY_PARENTS + ) + if getattr(field, "db_returning", False) + ] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/query.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/query.py new file mode 100644 index 0000000..de00bba --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/query.py @@ -0,0 +1,2731 @@ +""" +The main QuerySet implementation. This provides the public API for the ORM. +""" + +import copy +import operator +import warnings +from itertools import chain, islice + +from asgiref.sync import sync_to_async + +import django +from django.conf import settings +from django.core import exceptions +from django.db import ( + DJANGO_VERSION_PICKLE_KEY, + IntegrityError, + NotSupportedError, + connections, + router, + transaction, +) +from django.db.models import AutoField, DateField, DateTimeField, Field, sql +from django.db.models.constants import LOOKUP_SEP, OnConflict +from django.db.models.deletion import Collector +from django.db.models.expressions import Case, F, Value, When +from django.db.models.functions import Cast, Trunc +from django.db.models.query_utils import FilteredRelation, Q +from django.db.models.sql.constants import CURSOR, GET_ITERATOR_CHUNK_SIZE +from django.db.models.utils import ( + AltersData, + create_namedtuple_class, + resolve_callables, +) +from django.utils import timezone +from django.utils.deprecation import RemovedInDjango60Warning +from django.utils.functional import cached_property, partition + +# The maximum number of results to fetch in a get() query. +MAX_GET_RESULTS = 21 + +# The maximum number of items to display in a QuerySet.__repr__ +REPR_OUTPUT_SIZE = 20 + + +class BaseIterable: + def __init__( + self, queryset, chunked_fetch=False, chunk_size=GET_ITERATOR_CHUNK_SIZE + ): + self.queryset = queryset + self.chunked_fetch = chunked_fetch + self.chunk_size = chunk_size + + async def _async_generator(self): + # Generators don't actually start running until the first time you call + # next() on them, so make the generator object in the async thread and + # then repeatedly dispatch to it in a sync thread. + sync_generator = self.__iter__() + + def next_slice(gen): + return list(islice(gen, self.chunk_size)) + + while True: + chunk = await sync_to_async(next_slice)(sync_generator) + for item in chunk: + yield item + if len(chunk) < self.chunk_size: + break + + # __aiter__() is a *synchronous* method that has to then return an + # *asynchronous* iterator/generator. Thus, nest an async generator inside + # it. + # This is a generic iterable converter for now, and is going to suffer a + # performance penalty on large sets of items due to the cost of crossing + # over the sync barrier for each chunk. Custom __aiter__() methods should + # be added to each Iterable subclass, but that needs some work in the + # Compiler first. + def __aiter__(self): + return self._async_generator() + + +class ModelIterable(BaseIterable): + """Iterable that yields a model instance for each row.""" + + def __iter__(self): + queryset = self.queryset + db = queryset.db + compiler = queryset.query.get_compiler(using=db) + # Execute the query. This will also fill compiler.select, klass_info, + # and annotations. + results = compiler.execute_sql( + chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size + ) + select, klass_info, annotation_col_map = ( + compiler.select, + compiler.klass_info, + compiler.annotation_col_map, + ) + model_cls = klass_info["model"] + select_fields = klass_info["select_fields"] + model_fields_start, model_fields_end = select_fields[0], select_fields[-1] + 1 + init_list = [ + f[0].target.attname for f in select[model_fields_start:model_fields_end] + ] + related_populators = get_related_populators(klass_info, select, db) + known_related_objects = [ + ( + field, + related_objs, + operator.attrgetter( + *[ + field.attname + if from_field == "self" + else queryset.model._meta.get_field(from_field).attname + for from_field in field.from_fields + ] + ), + ) + for field, related_objs in queryset._known_related_objects.items() + ] + for row in compiler.results_iter(results): + obj = model_cls.from_db( + db, init_list, row[model_fields_start:model_fields_end] + ) + for rel_populator in related_populators: + rel_populator.populate(row, obj) + if annotation_col_map: + for attr_name, col_pos in annotation_col_map.items(): + setattr(obj, attr_name, row[col_pos]) + + # Add the known related objects to the model. + for field, rel_objs, rel_getter in known_related_objects: + # Avoid overwriting objects loaded by, e.g., select_related(). + if field.is_cached(obj): + continue + rel_obj_id = rel_getter(obj) + try: + rel_obj = rel_objs[rel_obj_id] + except KeyError: + pass # May happen in qs1 | qs2 scenarios. + else: + setattr(obj, field.name, rel_obj) + + yield obj + + +class RawModelIterable(BaseIterable): + """ + Iterable that yields a model instance for each row from a raw queryset. + """ + + def __iter__(self): + # Cache some things for performance reasons outside the loop. + db = self.queryset.db + query = self.queryset.query + connection = connections[db] + compiler = connection.ops.compiler("SQLCompiler")(query, connection, db) + query_iterator = iter(query) + + try: + ( + model_init_names, + model_init_pos, + annotation_fields, + ) = self.queryset.resolve_model_init_order() + model_cls = self.queryset.model + if model_cls._meta.pk.attname not in model_init_names: + raise exceptions.FieldDoesNotExist( + "Raw query must include the primary key" + ) + fields = [self.queryset.model_fields.get(c) for c in self.queryset.columns] + converters = compiler.get_converters( + [f.get_col(f.model._meta.db_table) if f else None for f in fields] + ) + if converters: + query_iterator = compiler.apply_converters(query_iterator, converters) + for values in query_iterator: + # Associate fields to values + model_init_values = [values[pos] for pos in model_init_pos] + instance = model_cls.from_db(db, model_init_names, model_init_values) + if annotation_fields: + for column, pos in annotation_fields: + setattr(instance, column, values[pos]) + yield instance + finally: + # Done iterating the Query. If it has its own cursor, close it. + if hasattr(query, "cursor") and query.cursor: + query.cursor.close() + + +class ValuesIterable(BaseIterable): + """ + Iterable returned by QuerySet.values() that yields a dict for each row. + """ + + def __iter__(self): + queryset = self.queryset + query = queryset.query + compiler = query.get_compiler(queryset.db) + + # extra(select=...) cols are always at the start of the row. + names = [ + *query.extra_select, + *query.values_select, + *query.annotation_select, + ] + indexes = range(len(names)) + for row in compiler.results_iter( + chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size + ): + yield {names[i]: row[i] for i in indexes} + + +class ValuesListIterable(BaseIterable): + """ + Iterable returned by QuerySet.values_list(flat=False) that yields a tuple + for each row. + """ + + def __iter__(self): + queryset = self.queryset + query = queryset.query + compiler = query.get_compiler(queryset.db) + + if queryset._fields: + # extra(select=...) cols are always at the start of the row. + names = [ + *query.extra_select, + *query.values_select, + *query.annotation_select, + ] + fields = [ + *queryset._fields, + *(f for f in query.annotation_select if f not in queryset._fields), + ] + if fields != names: + # Reorder according to fields. + index_map = {name: idx for idx, name in enumerate(names)} + rowfactory = operator.itemgetter(*[index_map[f] for f in fields]) + return map( + rowfactory, + compiler.results_iter( + chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size + ), + ) + return compiler.results_iter( + tuple_expected=True, + chunked_fetch=self.chunked_fetch, + chunk_size=self.chunk_size, + ) + + +class NamedValuesListIterable(ValuesListIterable): + """ + Iterable returned by QuerySet.values_list(named=True) that yields a + namedtuple for each row. + """ + + def __iter__(self): + queryset = self.queryset + if queryset._fields: + names = queryset._fields + else: + query = queryset.query + names = [ + *query.extra_select, + *query.values_select, + *query.annotation_select, + ] + tuple_class = create_namedtuple_class(*names) + new = tuple.__new__ + for row in super().__iter__(): + yield new(tuple_class, row) + + +class FlatValuesListIterable(BaseIterable): + """ + Iterable returned by QuerySet.values_list(flat=True) that yields single + values. + """ + + def __iter__(self): + queryset = self.queryset + compiler = queryset.query.get_compiler(queryset.db) + for row in compiler.results_iter( + chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size + ): + yield row[0] + + +class QuerySet(AltersData): + """Represent a lazy database lookup for a set of objects.""" + + def __init__(self, model=None, query=None, using=None, hints=None): + self.model = model + self._db = using + self._hints = hints or {} + self._query = query or sql.Query(self.model) + self._result_cache = None + self._sticky_filter = False + self._for_write = False + self._prefetch_related_lookups = () + self._prefetch_done = False + self._known_related_objects = {} # {rel_field: {pk: rel_obj}} + self._iterable_class = ModelIterable + self._fields = None + self._defer_next_filter = False + self._deferred_filter = None + + @property + def query(self): + if self._deferred_filter: + negate, args, kwargs = self._deferred_filter + self._filter_or_exclude_inplace(negate, args, kwargs) + self._deferred_filter = None + return self._query + + @query.setter + def query(self, value): + if value.values_select: + self._iterable_class = ValuesIterable + self._query = value + + def as_manager(cls): + # Address the circular dependency between `Queryset` and `Manager`. + from django.db.models.manager import Manager + + manager = Manager.from_queryset(cls)() + manager._built_with_as_manager = True + return manager + + as_manager.queryset_only = True + as_manager = classmethod(as_manager) + + ######################## + # PYTHON MAGIC METHODS # + ######################## + + def __deepcopy__(self, memo): + """Don't populate the QuerySet's cache.""" + obj = self.__class__() + for k, v in self.__dict__.items(): + if k == "_result_cache": + obj.__dict__[k] = None + else: + obj.__dict__[k] = copy.deepcopy(v, memo) + return obj + + def __getstate__(self): + # Force the cache to be fully populated. + self._fetch_all() + return {**self.__dict__, DJANGO_VERSION_PICKLE_KEY: django.__version__} + + def __setstate__(self, state): + pickled_version = state.get(DJANGO_VERSION_PICKLE_KEY) + if pickled_version: + if pickled_version != django.__version__: + warnings.warn( + "Pickled queryset instance's Django version %s does not " + "match the current version %s." + % (pickled_version, django.__version__), + RuntimeWarning, + stacklevel=2, + ) + else: + warnings.warn( + "Pickled queryset instance's Django version is not specified.", + RuntimeWarning, + stacklevel=2, + ) + self.__dict__.update(state) + + def __repr__(self): + data = list(self[: REPR_OUTPUT_SIZE + 1]) + if len(data) > REPR_OUTPUT_SIZE: + data[-1] = "...(remaining elements truncated)..." + return "<%s %r>" % (self.__class__.__name__, data) + + def __len__(self): + self._fetch_all() + return len(self._result_cache) + + def __iter__(self): + """ + The queryset iterator protocol uses three nested iterators in the + default case: + 1. sql.compiler.execute_sql() + - Returns 100 rows at time (constants.GET_ITERATOR_CHUNK_SIZE) + using cursor.fetchmany(). This part is responsible for + doing some column masking, and returning the rows in chunks. + 2. sql.compiler.results_iter() + - Returns one row at time. At this point the rows are still just + tuples. In some cases the return values are converted to + Python values at this location. + 3. self.iterator() + - Responsible for turning the rows into model objects. + """ + self._fetch_all() + return iter(self._result_cache) + + def __aiter__(self): + # Remember, __aiter__ itself is synchronous, it's the thing it returns + # that is async! + async def generator(): + await sync_to_async(self._fetch_all)() + for item in self._result_cache: + yield item + + return generator() + + def __bool__(self): + self._fetch_all() + return bool(self._result_cache) + + def __getitem__(self, k): + """Retrieve an item or slice from the set of results.""" + if not isinstance(k, (int, slice)): + raise TypeError( + "QuerySet indices must be integers or slices, not %s." + % type(k).__name__ + ) + if (isinstance(k, int) and k < 0) or ( + isinstance(k, slice) + and ( + (k.start is not None and k.start < 0) + or (k.stop is not None and k.stop < 0) + ) + ): + raise ValueError("Negative indexing is not supported.") + + if self._result_cache is not None: + return self._result_cache[k] + + if isinstance(k, slice): + qs = self._chain() + if k.start is not None: + start = int(k.start) + else: + start = None + if k.stop is not None: + stop = int(k.stop) + else: + stop = None + qs.query.set_limits(start, stop) + return list(qs)[:: k.step] if k.step else qs + + qs = self._chain() + qs.query.set_limits(k, k + 1) + qs._fetch_all() + return qs._result_cache[0] + + def __class_getitem__(cls, *args, **kwargs): + return cls + + def __and__(self, other): + self._check_operator_queryset(other, "&") + self._merge_sanity_check(other) + if isinstance(other, EmptyQuerySet): + return other + if isinstance(self, EmptyQuerySet): + return self + combined = self._chain() + combined._merge_known_related_objects(other) + combined.query.combine(other.query, sql.AND) + return combined + + def __or__(self, other): + self._check_operator_queryset(other, "|") + self._merge_sanity_check(other) + if isinstance(self, EmptyQuerySet): + return other + if isinstance(other, EmptyQuerySet): + return self + query = ( + self + if self.query.can_filter() + else self.model._base_manager.filter(pk__in=self.values("pk")) + ) + combined = query._chain() + combined._merge_known_related_objects(other) + if not other.query.can_filter(): + other = other.model._base_manager.filter(pk__in=other.values("pk")) + combined.query.combine(other.query, sql.OR) + return combined + + def __xor__(self, other): + self._check_operator_queryset(other, "^") + self._merge_sanity_check(other) + if isinstance(self, EmptyQuerySet): + return other + if isinstance(other, EmptyQuerySet): + return self + query = ( + self + if self.query.can_filter() + else self.model._base_manager.filter(pk__in=self.values("pk")) + ) + combined = query._chain() + combined._merge_known_related_objects(other) + if not other.query.can_filter(): + other = other.model._base_manager.filter(pk__in=other.values("pk")) + combined.query.combine(other.query, sql.XOR) + return combined + + #################################### + # METHODS THAT DO DATABASE QUERIES # + #################################### + + def _iterator(self, use_chunked_fetch, chunk_size): + iterable = self._iterable_class( + self, + chunked_fetch=use_chunked_fetch, + chunk_size=chunk_size or 2000, + ) + if not self._prefetch_related_lookups or chunk_size is None: + yield from iterable + return + + iterator = iter(iterable) + while results := list(islice(iterator, chunk_size)): + prefetch_related_objects(results, *self._prefetch_related_lookups) + yield from results + + def iterator(self, chunk_size=None): + """ + An iterator over the results from applying this QuerySet to the + database. chunk_size must be provided for QuerySets that prefetch + related objects. Otherwise, a default chunk_size of 2000 is supplied. + """ + if chunk_size is None: + if self._prefetch_related_lookups: + raise ValueError( + "chunk_size must be provided when using QuerySet.iterator() after " + "prefetch_related()." + ) + elif chunk_size <= 0: + raise ValueError("Chunk size must be strictly positive.") + use_chunked_fetch = not connections[self.db].settings_dict.get( + "DISABLE_SERVER_SIDE_CURSORS" + ) + return self._iterator(use_chunked_fetch, chunk_size) + + async def aiterator(self, chunk_size=2000): + """ + An asynchronous iterator over the results from applying this QuerySet + to the database. + """ + if chunk_size <= 0: + raise ValueError("Chunk size must be strictly positive.") + use_chunked_fetch = not connections[self.db].settings_dict.get( + "DISABLE_SERVER_SIDE_CURSORS" + ) + iterable = self._iterable_class( + self, chunked_fetch=use_chunked_fetch, chunk_size=chunk_size + ) + if self._prefetch_related_lookups: + results = [] + + async for item in iterable: + results.append(item) + if len(results) >= chunk_size: + await aprefetch_related_objects( + results, *self._prefetch_related_lookups + ) + for result in results: + yield result + results.clear() + + if results: + await aprefetch_related_objects( + results, *self._prefetch_related_lookups + ) + for result in results: + yield result + else: + async for item in iterable: + yield item + + def aggregate(self, *args, **kwargs): + """ + Return a dictionary containing the calculations (aggregation) + over the current queryset. + + If args is present the expression is passed as a kwarg using + the Aggregate object's default alias. + """ + if self.query.distinct_fields: + raise NotImplementedError("aggregate() + distinct(fields) not implemented.") + self._validate_values_are_expressions( + (*args, *kwargs.values()), method_name="aggregate" + ) + for arg in args: + # The default_alias property raises TypeError if default_alias + # can't be set automatically or AttributeError if it isn't an + # attribute. + try: + arg.default_alias + except (AttributeError, TypeError): + raise TypeError("Complex aggregates require an alias") + kwargs[arg.default_alias] = arg + + return self.query.chain().get_aggregation(self.db, kwargs) + + async def aaggregate(self, *args, **kwargs): + return await sync_to_async(self.aggregate)(*args, **kwargs) + + def count(self): + """ + Perform a SELECT COUNT() and return the number of records as an + integer. + + If the QuerySet is already fully cached, return the length of the + cached results set to avoid multiple SELECT COUNT(*) calls. + """ + if self._result_cache is not None: + return len(self._result_cache) + + return self.query.get_count(using=self.db) + + async def acount(self): + return await sync_to_async(self.count)() + + def get(self, *args, **kwargs): + """ + Perform the query and return a single object matching the given + keyword arguments. + """ + if self.query.combinator and (args or kwargs): + raise NotSupportedError( + "Calling QuerySet.get(...) with filters after %s() is not " + "supported." % self.query.combinator + ) + clone = self._chain() if self.query.combinator else self.filter(*args, **kwargs) + if self.query.can_filter() and not self.query.distinct_fields: + clone = clone.order_by() + limit = None + if ( + not clone.query.select_for_update + or connections[clone.db].features.supports_select_for_update_with_limit + ): + limit = MAX_GET_RESULTS + clone.query.set_limits(high=limit) + num = len(clone) + if num == 1: + return clone._result_cache[0] + if not num: + raise self.model.DoesNotExist( + "%s matching query does not exist." % self.model._meta.object_name + ) + raise self.model.MultipleObjectsReturned( + "get() returned more than one %s -- it returned %s!" + % ( + self.model._meta.object_name, + num if not limit or num < limit else "more than %s" % (limit - 1), + ) + ) + + async def aget(self, *args, **kwargs): + return await sync_to_async(self.get)(*args, **kwargs) + + def create(self, **kwargs): + """ + Create a new object with the given kwargs, saving it to the database + and returning the created object. + """ + reverse_one_to_one_fields = frozenset(kwargs).intersection( + self.model._meta._reverse_one_to_one_field_names + ) + if reverse_one_to_one_fields: + raise ValueError( + "The following fields do not exist in this model: %s" + % ", ".join(reverse_one_to_one_fields) + ) + + obj = self.model(**kwargs) + self._for_write = True + obj.save(force_insert=True, using=self.db) + return obj + + async def acreate(self, **kwargs): + return await sync_to_async(self.create)(**kwargs) + + def _prepare_for_bulk_create(self, objs): + from django.db.models.expressions import DatabaseDefault + + connection = connections[self.db] + for obj in objs: + if obj.pk is None: + # Populate new PK values. + obj.pk = obj._meta.pk.get_pk_value_on_save(obj) + if not connection.features.supports_default_keyword_in_bulk_insert: + for field in obj._meta.fields: + if field.generated: + continue + value = getattr(obj, field.attname) + if isinstance(value, DatabaseDefault): + setattr(obj, field.attname, field.db_default) + + obj._prepare_related_fields_for_save(operation_name="bulk_create") + + def _check_bulk_create_options( + self, ignore_conflicts, update_conflicts, update_fields, unique_fields + ): + if ignore_conflicts and update_conflicts: + raise ValueError( + "ignore_conflicts and update_conflicts are mutually exclusive." + ) + db_features = connections[self.db].features + if ignore_conflicts: + if not db_features.supports_ignore_conflicts: + raise NotSupportedError( + "This database backend does not support ignoring conflicts." + ) + return OnConflict.IGNORE + elif update_conflicts: + if not db_features.supports_update_conflicts: + raise NotSupportedError( + "This database backend does not support updating conflicts." + ) + if not update_fields: + raise ValueError( + "Fields that will be updated when a row insertion fails " + "on conflicts must be provided." + ) + if unique_fields and not db_features.supports_update_conflicts_with_target: + raise NotSupportedError( + "This database backend does not support updating " + "conflicts with specifying unique fields that can trigger " + "the upsert." + ) + if not unique_fields and db_features.supports_update_conflicts_with_target: + raise ValueError( + "Unique fields that can trigger the upsert must be provided." + ) + # Updating primary keys and non-concrete fields is forbidden. + if any(not f.concrete or f.many_to_many for f in update_fields): + raise ValueError( + "bulk_create() can only be used with concrete fields in " + "update_fields." + ) + if any(f.primary_key for f in update_fields): + raise ValueError( + "bulk_create() cannot be used with primary keys in " + "update_fields." + ) + if unique_fields: + if any(not f.concrete or f.many_to_many for f in unique_fields): + raise ValueError( + "bulk_create() can only be used with concrete fields " + "in unique_fields." + ) + return OnConflict.UPDATE + return None + + def bulk_create( + self, + objs, + batch_size=None, + ignore_conflicts=False, + update_conflicts=False, + update_fields=None, + unique_fields=None, + ): + """ + Insert each of the instances into the database. Do *not* call + save() on each of the instances, do not send any pre/post_save + signals, and do not set the primary key attribute if it is an + autoincrement field (except if features.can_return_rows_from_bulk_insert=True). + Multi-table models are not supported. + """ + # When you bulk insert you don't get the primary keys back (if it's an + # autoincrement, except if can_return_rows_from_bulk_insert=True), so + # you can't insert into the child tables which references this. There + # are two workarounds: + # 1) This could be implemented if you didn't have an autoincrement pk + # 2) You could do it by doing O(n) normal inserts into the parent + # tables to get the primary keys back and then doing a single bulk + # insert into the childmost table. + # We currently set the primary keys on the objects when using + # PostgreSQL via the RETURNING ID clause. It should be possible for + # Oracle as well, but the semantics for extracting the primary keys is + # trickier so it's not done yet. + if batch_size is not None and batch_size <= 0: + raise ValueError("Batch size must be a positive integer.") + # Check that the parents share the same concrete model with the our + # model to detect the inheritance pattern ConcreteGrandParent -> + # MultiTableParent -> ProxyChild. Simply checking self.model._meta.proxy + # would not identify that case as involving multiple tables. + for parent in self.model._meta.get_parent_list(): + if parent._meta.concrete_model is not self.model._meta.concrete_model: + raise ValueError("Can't bulk create a multi-table inherited model") + if not objs: + return objs + opts = self.model._meta + if unique_fields: + # Primary key is allowed in unique_fields. + unique_fields = [ + self.model._meta.get_field(opts.pk.name if name == "pk" else name) + for name in unique_fields + ] + if update_fields: + update_fields = [self.model._meta.get_field(name) for name in update_fields] + on_conflict = self._check_bulk_create_options( + ignore_conflicts, + update_conflicts, + update_fields, + unique_fields, + ) + self._for_write = True + fields = [f for f in opts.concrete_fields if not f.generated] + objs = list(objs) + self._prepare_for_bulk_create(objs) + with transaction.atomic(using=self.db, savepoint=False): + objs_with_pk, objs_without_pk = partition(lambda o: o.pk is None, objs) + if objs_with_pk: + returned_columns = self._batched_insert( + objs_with_pk, + fields, + batch_size, + on_conflict=on_conflict, + update_fields=update_fields, + unique_fields=unique_fields, + ) + for obj_with_pk, results in zip(objs_with_pk, returned_columns): + for result, field in zip(results, opts.db_returning_fields): + if field != opts.pk: + setattr(obj_with_pk, field.attname, result) + for obj_with_pk in objs_with_pk: + obj_with_pk._state.adding = False + obj_with_pk._state.db = self.db + if objs_without_pk: + fields = [f for f in fields if not isinstance(f, AutoField)] + returned_columns = self._batched_insert( + objs_without_pk, + fields, + batch_size, + on_conflict=on_conflict, + update_fields=update_fields, + unique_fields=unique_fields, + ) + connection = connections[self.db] + if ( + connection.features.can_return_rows_from_bulk_insert + and on_conflict is None + ): + assert len(returned_columns) == len(objs_without_pk) + for obj_without_pk, results in zip(objs_without_pk, returned_columns): + for result, field in zip(results, opts.db_returning_fields): + setattr(obj_without_pk, field.attname, result) + obj_without_pk._state.adding = False + obj_without_pk._state.db = self.db + + return objs + + async def abulk_create( + self, + objs, + batch_size=None, + ignore_conflicts=False, + update_conflicts=False, + update_fields=None, + unique_fields=None, + ): + return await sync_to_async(self.bulk_create)( + objs=objs, + batch_size=batch_size, + ignore_conflicts=ignore_conflicts, + update_conflicts=update_conflicts, + update_fields=update_fields, + unique_fields=unique_fields, + ) + + def bulk_update(self, objs, fields, batch_size=None): + """ + Update the given fields in each of the given objects in the database. + """ + if batch_size is not None and batch_size <= 0: + raise ValueError("Batch size must be a positive integer.") + if not fields: + raise ValueError("Field names must be given to bulk_update().") + objs = tuple(objs) + if any(obj.pk is None for obj in objs): + raise ValueError("All bulk_update() objects must have a primary key set.") + fields = [self.model._meta.get_field(name) for name in fields] + if any(not f.concrete or f.many_to_many for f in fields): + raise ValueError("bulk_update() can only be used with concrete fields.") + if any(f.primary_key for f in fields): + raise ValueError("bulk_update() cannot be used with primary key fields.") + if not objs: + return 0 + for obj in objs: + obj._prepare_related_fields_for_save( + operation_name="bulk_update", fields=fields + ) + # PK is used twice in the resulting update query, once in the filter + # and once in the WHEN. Each field will also have one CAST. + self._for_write = True + connection = connections[self.db] + max_batch_size = connection.ops.bulk_batch_size(["pk", "pk"] + fields, objs) + batch_size = min(batch_size, max_batch_size) if batch_size else max_batch_size + requires_casting = connection.features.requires_casted_case_in_updates + batches = (objs[i : i + batch_size] for i in range(0, len(objs), batch_size)) + updates = [] + for batch_objs in batches: + update_kwargs = {} + for field in fields: + when_statements = [] + for obj in batch_objs: + attr = getattr(obj, field.attname) + if not hasattr(attr, "resolve_expression"): + attr = Value(attr, output_field=field) + when_statements.append(When(pk=obj.pk, then=attr)) + case_statement = Case(*when_statements, output_field=field) + if requires_casting: + case_statement = Cast(case_statement, output_field=field) + update_kwargs[field.attname] = case_statement + updates.append(([obj.pk for obj in batch_objs], update_kwargs)) + rows_updated = 0 + queryset = self.using(self.db) + with transaction.atomic(using=self.db, savepoint=False): + for pks, update_kwargs in updates: + rows_updated += queryset.filter(pk__in=pks).update(**update_kwargs) + return rows_updated + + bulk_update.alters_data = True + + async def abulk_update(self, objs, fields, batch_size=None): + return await sync_to_async(self.bulk_update)( + objs=objs, + fields=fields, + batch_size=batch_size, + ) + + abulk_update.alters_data = True + + def get_or_create(self, defaults=None, **kwargs): + """ + Look up an object with the given kwargs, creating one if necessary. + Return a tuple of (object, created), where created is a boolean + specifying whether an object was created. + """ + # The get() needs to be targeted at the write database in order + # to avoid potential transaction consistency problems. + self._for_write = True + try: + return self.get(**kwargs), False + except self.model.DoesNotExist: + params = self._extract_model_params(defaults, **kwargs) + # Try to create an object using passed params. + try: + with transaction.atomic(using=self.db): + params = dict(resolve_callables(params)) + return self.create(**params), True + except IntegrityError: + try: + return self.get(**kwargs), False + except self.model.DoesNotExist: + pass + raise + + async def aget_or_create(self, defaults=None, **kwargs): + return await sync_to_async(self.get_or_create)( + defaults=defaults, + **kwargs, + ) + + def update_or_create(self, defaults=None, create_defaults=None, **kwargs): + """ + Look up an object with the given kwargs, updating one with defaults + if it exists, otherwise create a new one. Optionally, an object can + be created with different values than defaults by using + create_defaults. + Return a tuple (object, created), where created is a boolean + specifying whether an object was created. + """ + update_defaults = defaults or {} + if create_defaults is None: + create_defaults = update_defaults + + self._for_write = True + with transaction.atomic(using=self.db): + # Lock the row so that a concurrent update is blocked until + # update_or_create() has performed its save. + obj, created = self.select_for_update().get_or_create( + create_defaults, **kwargs + ) + if created: + return obj, created + for k, v in resolve_callables(update_defaults): + setattr(obj, k, v) + + update_fields = set(update_defaults) + concrete_field_names = self.model._meta._non_pk_concrete_field_names + # update_fields does not support non-concrete fields. + if concrete_field_names.issuperset(update_fields): + # Add fields which are set on pre_save(), e.g. auto_now fields. + # This is to maintain backward compatibility as these fields + # are not updated unless explicitly specified in the + # update_fields list. + for field in self.model._meta.local_concrete_fields: + if not ( + field.primary_key or field.__class__.pre_save is Field.pre_save + ): + update_fields.add(field.name) + if field.name != field.attname: + update_fields.add(field.attname) + obj.save(using=self.db, update_fields=update_fields) + else: + obj.save(using=self.db) + return obj, False + + async def aupdate_or_create(self, defaults=None, create_defaults=None, **kwargs): + return await sync_to_async(self.update_or_create)( + defaults=defaults, + create_defaults=create_defaults, + **kwargs, + ) + + def _extract_model_params(self, defaults, **kwargs): + """ + Prepare `params` for creating a model instance based on the given + kwargs; for use by get_or_create(). + """ + defaults = defaults or {} + params = {k: v for k, v in kwargs.items() if LOOKUP_SEP not in k} + params.update(defaults) + property_names = self.model._meta._property_names + invalid_params = [] + for param in params: + try: + self.model._meta.get_field(param) + except exceptions.FieldDoesNotExist: + # It's okay to use a model's property if it has a setter. + if not (param in property_names and getattr(self.model, param).fset): + invalid_params.append(param) + if invalid_params: + raise exceptions.FieldError( + "Invalid field name(s) for model %s: '%s'." + % ( + self.model._meta.object_name, + "', '".join(sorted(invalid_params)), + ) + ) + return params + + def _earliest(self, *fields): + """ + Return the earliest object according to fields (if given) or by the + model's Meta.get_latest_by. + """ + if fields: + order_by = fields + else: + order_by = getattr(self.model._meta, "get_latest_by") + if order_by and not isinstance(order_by, (tuple, list)): + order_by = (order_by,) + if order_by is None: + raise ValueError( + "earliest() and latest() require either fields as positional " + "arguments or 'get_latest_by' in the model's Meta." + ) + obj = self._chain() + obj.query.set_limits(high=1) + obj.query.clear_ordering(force=True) + obj.query.add_ordering(*order_by) + return obj.get() + + def earliest(self, *fields): + if self.query.is_sliced: + raise TypeError("Cannot change a query once a slice has been taken.") + return self._earliest(*fields) + + async def aearliest(self, *fields): + return await sync_to_async(self.earliest)(*fields) + + def latest(self, *fields): + """ + Return the latest object according to fields (if given) or by the + model's Meta.get_latest_by. + """ + if self.query.is_sliced: + raise TypeError("Cannot change a query once a slice has been taken.") + return self.reverse()._earliest(*fields) + + async def alatest(self, *fields): + return await sync_to_async(self.latest)(*fields) + + def first(self): + """Return the first object of a query or None if no match is found.""" + if self.ordered: + queryset = self + else: + self._check_ordering_first_last_queryset_aggregation(method="first") + queryset = self.order_by("pk") + for obj in queryset[:1]: + return obj + + async def afirst(self): + return await sync_to_async(self.first)() + + def last(self): + """Return the last object of a query or None if no match is found.""" + if self.ordered: + queryset = self.reverse() + else: + self._check_ordering_first_last_queryset_aggregation(method="last") + queryset = self.order_by("-pk") + for obj in queryset[:1]: + return obj + + async def alast(self): + return await sync_to_async(self.last)() + + def in_bulk(self, id_list=None, *, field_name="pk"): + """ + Return a dictionary mapping each of the given IDs to the object with + that ID. If `id_list` isn't provided, evaluate the entire QuerySet. + """ + if self.query.is_sliced: + raise TypeError("Cannot use 'limit' or 'offset' with in_bulk().") + opts = self.model._meta + unique_fields = [ + constraint.fields[0] + for constraint in opts.total_unique_constraints + if len(constraint.fields) == 1 + ] + if ( + field_name != "pk" + and not opts.get_field(field_name).unique + and field_name not in unique_fields + and self.query.distinct_fields != (field_name,) + ): + raise ValueError( + "in_bulk()'s field_name must be a unique field but %r isn't." + % field_name + ) + if id_list is not None: + if not id_list: + return {} + filter_key = "{}__in".format(field_name) + batch_size = connections[self.db].features.max_query_params + id_list = tuple(id_list) + # If the database has a limit on the number of query parameters + # (e.g. SQLite), retrieve objects in batches if necessary. + if batch_size and batch_size < len(id_list): + qs = () + for offset in range(0, len(id_list), batch_size): + batch = id_list[offset : offset + batch_size] + qs += tuple(self.filter(**{filter_key: batch})) + else: + qs = self.filter(**{filter_key: id_list}) + else: + qs = self._chain() + return {getattr(obj, field_name): obj for obj in qs} + + async def ain_bulk(self, id_list=None, *, field_name="pk"): + return await sync_to_async(self.in_bulk)( + id_list=id_list, + field_name=field_name, + ) + + def delete(self): + """Delete the records in the current QuerySet.""" + self._not_support_combined_queries("delete") + if self.query.is_sliced: + raise TypeError("Cannot use 'limit' or 'offset' with delete().") + if self.query.distinct_fields: + raise TypeError("Cannot call delete() after .distinct(*fields).") + if self._fields is not None: + raise TypeError("Cannot call delete() after .values() or .values_list()") + + del_query = self._chain() + + # The delete is actually 2 queries - one to find related objects, + # and one to delete. Make sure that the discovery of related + # objects is performed on the same database as the deletion. + del_query._for_write = True + + # Disable non-supported fields. + del_query.query.select_for_update = False + del_query.query.select_related = False + del_query.query.clear_ordering(force=True) + + collector = Collector(using=del_query.db, origin=self) + collector.collect(del_query) + deleted, _rows_count = collector.delete() + + # Clear the result cache, in case this QuerySet gets reused. + self._result_cache = None + return deleted, _rows_count + + delete.alters_data = True + delete.queryset_only = True + + async def adelete(self): + return await sync_to_async(self.delete)() + + adelete.alters_data = True + adelete.queryset_only = True + + def _raw_delete(self, using): + """ + Delete objects found from the given queryset in single direct SQL + query. No signals are sent and there is no protection for cascades. + """ + query = self.query.clone() + query.__class__ = sql.DeleteQuery + cursor = query.get_compiler(using).execute_sql(CURSOR) + if cursor: + with cursor: + return cursor.rowcount + return 0 + + _raw_delete.alters_data = True + + def update(self, **kwargs): + """ + Update all elements in the current QuerySet, setting all the given + fields to the appropriate values. + """ + self._not_support_combined_queries("update") + if self.query.is_sliced: + raise TypeError("Cannot update a query once a slice has been taken.") + self._for_write = True + query = self.query.chain(sql.UpdateQuery) + query.add_update_values(kwargs) + + # Inline annotations in order_by(), if possible. + new_order_by = [] + for col in query.order_by: + alias = col + descending = False + if isinstance(alias, str) and alias.startswith("-"): + alias = alias.removeprefix("-") + descending = True + if annotation := query.annotations.get(alias): + if getattr(annotation, "contains_aggregate", False): + raise exceptions.FieldError( + f"Cannot update when ordering by an aggregate: {annotation}" + ) + if descending: + annotation = annotation.desc() + new_order_by.append(annotation) + else: + new_order_by.append(col) + query.order_by = tuple(new_order_by) + + # Clear any annotations so that they won't be present in subqueries. + query.annotations = {} + with transaction.mark_for_rollback_on_error(using=self.db): + rows = query.get_compiler(self.db).execute_sql(CURSOR) + self._result_cache = None + return rows + + update.alters_data = True + + async def aupdate(self, **kwargs): + return await sync_to_async(self.update)(**kwargs) + + aupdate.alters_data = True + + def _update(self, values): + """ + A version of update() that accepts field objects instead of field names. + Used primarily for model saving and not intended for use by general + code (it requires too much poking around at model internals to be + useful at that level). + """ + if self.query.is_sliced: + raise TypeError("Cannot update a query once a slice has been taken.") + query = self.query.chain(sql.UpdateQuery) + query.add_update_fields(values) + # Clear any annotations so that they won't be present in subqueries. + query.annotations = {} + self._result_cache = None + return query.get_compiler(self.db).execute_sql(CURSOR) + + _update.alters_data = True + _update.queryset_only = False + + def exists(self): + """ + Return True if the QuerySet would have any results, False otherwise. + """ + if self._result_cache is None: + return self.query.has_results(using=self.db) + return bool(self._result_cache) + + async def aexists(self): + return await sync_to_async(self.exists)() + + def contains(self, obj): + """ + Return True if the QuerySet contains the provided obj, + False otherwise. + """ + self._not_support_combined_queries("contains") + if self._fields is not None: + raise TypeError( + "Cannot call QuerySet.contains() after .values() or .values_list()." + ) + try: + if obj._meta.concrete_model != self.model._meta.concrete_model: + return False + except AttributeError: + raise TypeError("'obj' must be a model instance.") + if obj.pk is None: + raise ValueError("QuerySet.contains() cannot be used on unsaved objects.") + if self._result_cache is not None: + return obj in self._result_cache + return self.filter(pk=obj.pk).exists() + + async def acontains(self, obj): + return await sync_to_async(self.contains)(obj=obj) + + def _prefetch_related_objects(self): + # This method can only be called once the result cache has been filled. + prefetch_related_objects(self._result_cache, *self._prefetch_related_lookups) + self._prefetch_done = True + + def explain(self, *, format=None, **options): + """ + Runs an EXPLAIN on the SQL query this QuerySet would perform, and + returns the results. + """ + return self.query.explain(using=self.db, format=format, **options) + + async def aexplain(self, *, format=None, **options): + return await sync_to_async(self.explain)(format=format, **options) + + ################################################## + # PUBLIC METHODS THAT RETURN A QUERYSET SUBCLASS # + ################################################## + + def raw(self, raw_query, params=(), translations=None, using=None): + if using is None: + using = self.db + qs = RawQuerySet( + raw_query, + model=self.model, + params=params, + translations=translations, + using=using, + ) + qs._prefetch_related_lookups = self._prefetch_related_lookups[:] + return qs + + def _values(self, *fields, **expressions): + clone = self._chain() + if expressions: + clone = clone.annotate(**expressions) + clone._fields = fields + clone.query.set_values(fields) + return clone + + def values(self, *fields, **expressions): + fields += tuple(expressions) + clone = self._values(*fields, **expressions) + clone._iterable_class = ValuesIterable + return clone + + def values_list(self, *fields, flat=False, named=False): + if flat and named: + raise TypeError("'flat' and 'named' can't be used together.") + if flat and len(fields) > 1: + raise TypeError( + "'flat' is not valid when values_list is called with more than one " + "field." + ) + + field_names = {f for f in fields if not hasattr(f, "resolve_expression")} + _fields = [] + expressions = {} + counter = 1 + for field in fields: + if hasattr(field, "resolve_expression"): + field_id_prefix = getattr( + field, "default_alias", field.__class__.__name__.lower() + ) + while True: + field_id = field_id_prefix + str(counter) + counter += 1 + if field_id not in field_names: + break + expressions[field_id] = field + _fields.append(field_id) + else: + _fields.append(field) + + clone = self._values(*_fields, **expressions) + clone._iterable_class = ( + NamedValuesListIterable + if named + else FlatValuesListIterable + if flat + else ValuesListIterable + ) + return clone + + def dates(self, field_name, kind, order="ASC"): + """ + Return a list of date objects representing all available dates for + the given field_name, scoped to 'kind'. + """ + if kind not in ("year", "month", "week", "day"): + raise ValueError("'kind' must be one of 'year', 'month', 'week', or 'day'.") + if order not in ("ASC", "DESC"): + raise ValueError("'order' must be either 'ASC' or 'DESC'.") + return ( + self.annotate( + datefield=Trunc(field_name, kind, output_field=DateField()), + plain_field=F(field_name), + ) + .values_list("datefield", flat=True) + .distinct() + .filter(plain_field__isnull=False) + .order_by(("-" if order == "DESC" else "") + "datefield") + ) + + def datetimes(self, field_name, kind, order="ASC", tzinfo=None): + """ + Return a list of datetime objects representing all available + datetimes for the given field_name, scoped to 'kind'. + """ + if kind not in ("year", "month", "week", "day", "hour", "minute", "second"): + raise ValueError( + "'kind' must be one of 'year', 'month', 'week', 'day', " + "'hour', 'minute', or 'second'." + ) + if order not in ("ASC", "DESC"): + raise ValueError("'order' must be either 'ASC' or 'DESC'.") + if settings.USE_TZ: + if tzinfo is None: + tzinfo = timezone.get_current_timezone() + else: + tzinfo = None + return ( + self.annotate( + datetimefield=Trunc( + field_name, + kind, + output_field=DateTimeField(), + tzinfo=tzinfo, + ), + plain_field=F(field_name), + ) + .values_list("datetimefield", flat=True) + .distinct() + .filter(plain_field__isnull=False) + .order_by(("-" if order == "DESC" else "") + "datetimefield") + ) + + def none(self): + """Return an empty QuerySet.""" + clone = self._chain() + clone.query.set_empty() + return clone + + ################################################################## + # PUBLIC METHODS THAT ALTER ATTRIBUTES AND RETURN A NEW QUERYSET # + ################################################################## + + def all(self): + """ + Return a new QuerySet that is a copy of the current one. This allows a + QuerySet to proxy for a model manager in some cases. + """ + return self._chain() + + def filter(self, *args, **kwargs): + """ + Return a new QuerySet instance with the args ANDed to the existing + set. + """ + self._not_support_combined_queries("filter") + return self._filter_or_exclude(False, args, kwargs) + + def exclude(self, *args, **kwargs): + """ + Return a new QuerySet instance with NOT (args) ANDed to the existing + set. + """ + self._not_support_combined_queries("exclude") + return self._filter_or_exclude(True, args, kwargs) + + def _filter_or_exclude(self, negate, args, kwargs): + if (args or kwargs) and self.query.is_sliced: + raise TypeError("Cannot filter a query once a slice has been taken.") + clone = self._chain() + if self._defer_next_filter: + self._defer_next_filter = False + clone._deferred_filter = negate, args, kwargs + else: + clone._filter_or_exclude_inplace(negate, args, kwargs) + return clone + + def _filter_or_exclude_inplace(self, negate, args, kwargs): + if negate: + self._query.add_q(~Q(*args, **kwargs)) + else: + self._query.add_q(Q(*args, **kwargs)) + + def complex_filter(self, filter_obj): + """ + Return a new QuerySet instance with filter_obj added to the filters. + + filter_obj can be a Q object or a dictionary of keyword lookup + arguments. + + This exists to support framework features such as 'limit_choices_to', + and usually it will be more natural to use other methods. + """ + if isinstance(filter_obj, Q): + clone = self._chain() + clone.query.add_q(filter_obj) + return clone + else: + return self._filter_or_exclude(False, args=(), kwargs=filter_obj) + + def _combinator_query(self, combinator, *other_qs, all=False): + # Clone the query to inherit the select list and everything + clone = self._chain() + # Clear limits and ordering so they can be reapplied + clone.query.clear_ordering(force=True) + clone.query.clear_limits() + clone.query.combined_queries = (self.query,) + tuple( + qs.query for qs in other_qs + ) + clone.query.combinator = combinator + clone.query.combinator_all = all + return clone + + def union(self, *other_qs, all=False): + # If the query is an EmptyQuerySet, combine all nonempty querysets. + if isinstance(self, EmptyQuerySet): + qs = [q for q in other_qs if not isinstance(q, EmptyQuerySet)] + if not qs: + return self + if len(qs) == 1: + return qs[0] + return qs[0]._combinator_query("union", *qs[1:], all=all) + return self._combinator_query("union", *other_qs, all=all) + + def intersection(self, *other_qs): + # If any query is an EmptyQuerySet, return it. + if isinstance(self, EmptyQuerySet): + return self + for other in other_qs: + if isinstance(other, EmptyQuerySet): + return other + return self._combinator_query("intersection", *other_qs) + + def difference(self, *other_qs): + # If the query is an EmptyQuerySet, return it. + if isinstance(self, EmptyQuerySet): + return self + return self._combinator_query("difference", *other_qs) + + def select_for_update(self, nowait=False, skip_locked=False, of=(), no_key=False): + """ + Return a new QuerySet instance that will select objects with a + FOR UPDATE lock. + """ + if nowait and skip_locked: + raise ValueError("The nowait option cannot be used with skip_locked.") + obj = self._chain() + obj._for_write = True + obj.query.select_for_update = True + obj.query.select_for_update_nowait = nowait + obj.query.select_for_update_skip_locked = skip_locked + obj.query.select_for_update_of = of + obj.query.select_for_no_key_update = no_key + return obj + + def select_related(self, *fields): + """ + Return a new QuerySet instance that will select related objects. + + If fields are specified, they must be ForeignKey fields and only those + related objects are included in the selection. + + If select_related(None) is called, clear the list. + """ + self._not_support_combined_queries("select_related") + if self._fields is not None: + raise TypeError( + "Cannot call select_related() after .values() or .values_list()" + ) + + obj = self._chain() + if fields == (None,): + obj.query.select_related = False + elif fields: + obj.query.add_select_related(fields) + else: + obj.query.select_related = True + return obj + + def prefetch_related(self, *lookups): + """ + Return a new QuerySet instance that will prefetch the specified + Many-To-One and Many-To-Many related objects when the QuerySet is + evaluated. + + When prefetch_related() is called more than once, append to the list of + prefetch lookups. If prefetch_related(None) is called, clear the list. + """ + self._not_support_combined_queries("prefetch_related") + clone = self._chain() + if lookups == (None,): + clone._prefetch_related_lookups = () + else: + for lookup in lookups: + if isinstance(lookup, Prefetch): + lookup = lookup.prefetch_to + lookup = lookup.split(LOOKUP_SEP, 1)[0] + if lookup in self.query._filtered_relations: + raise ValueError( + "prefetch_related() is not supported with FilteredRelation." + ) + clone._prefetch_related_lookups = clone._prefetch_related_lookups + lookups + return clone + + def annotate(self, *args, **kwargs): + """ + Return a query set in which the returned objects have been annotated + with extra data or aggregations. + """ + self._not_support_combined_queries("annotate") + return self._annotate(args, kwargs, select=True) + + def alias(self, *args, **kwargs): + """ + Return a query set with added aliases for extra data or aggregations. + """ + self._not_support_combined_queries("alias") + return self._annotate(args, kwargs, select=False) + + def _annotate(self, args, kwargs, select=True): + self._validate_values_are_expressions( + args + tuple(kwargs.values()), method_name="annotate" + ) + annotations = {} + for arg in args: + # The default_alias property may raise a TypeError. + try: + if arg.default_alias in kwargs: + raise ValueError( + "The named annotation '%s' conflicts with the " + "default name for another annotation." % arg.default_alias + ) + except TypeError: + raise TypeError("Complex annotations require an alias") + annotations[arg.default_alias] = arg + annotations.update(kwargs) + + clone = self._chain() + names = self._fields + if names is None: + names = set( + chain.from_iterable( + (field.name, field.attname) + if hasattr(field, "attname") + else (field.name,) + for field in self.model._meta.get_fields() + ) + ) + + for alias, annotation in annotations.items(): + if alias in names: + raise ValueError( + "The annotation '%s' conflicts with a field on " + "the model." % alias + ) + if isinstance(annotation, FilteredRelation): + clone.query.add_filtered_relation(annotation, alias) + else: + clone.query.add_annotation( + annotation, + alias, + select=select, + ) + for alias, annotation in clone.query.annotations.items(): + if alias in annotations and annotation.contains_aggregate: + if clone._fields is None: + clone.query.group_by = True + else: + clone.query.set_group_by() + break + + return clone + + def order_by(self, *field_names): + """Return a new QuerySet instance with the ordering changed.""" + if self.query.is_sliced: + raise TypeError("Cannot reorder a query once a slice has been taken.") + obj = self._chain() + obj.query.clear_ordering(force=True, clear_default=False) + obj.query.add_ordering(*field_names) + return obj + + def distinct(self, *field_names): + """ + Return a new QuerySet instance that will select only distinct results. + """ + self._not_support_combined_queries("distinct") + if self.query.is_sliced: + raise TypeError( + "Cannot create distinct fields once a slice has been taken." + ) + obj = self._chain() + obj.query.add_distinct_fields(*field_names) + return obj + + def extra( + self, + select=None, + where=None, + params=None, + tables=None, + order_by=None, + select_params=None, + ): + """Add extra SQL fragments to the query.""" + self._not_support_combined_queries("extra") + if self.query.is_sliced: + raise TypeError("Cannot change a query once a slice has been taken.") + clone = self._chain() + clone.query.add_extra(select, select_params, where, params, tables, order_by) + return clone + + def reverse(self): + """Reverse the ordering of the QuerySet.""" + if self.query.is_sliced: + raise TypeError("Cannot reverse a query once a slice has been taken.") + clone = self._chain() + clone.query.standard_ordering = not clone.query.standard_ordering + return clone + + def defer(self, *fields): + """ + Defer the loading of data for certain fields until they are accessed. + Add the set of deferred fields to any existing set of deferred fields. + The only exception to this is if None is passed in as the only + parameter, in which case removal all deferrals. + """ + self._not_support_combined_queries("defer") + if self._fields is not None: + raise TypeError("Cannot call defer() after .values() or .values_list()") + clone = self._chain() + if fields == (None,): + clone.query.clear_deferred_loading() + else: + clone.query.add_deferred_loading(fields) + return clone + + def only(self, *fields): + """ + Essentially, the opposite of defer(). Only the fields passed into this + method and that are not already specified as deferred are loaded + immediately when the queryset is evaluated. + """ + self._not_support_combined_queries("only") + if self._fields is not None: + raise TypeError("Cannot call only() after .values() or .values_list()") + if fields == (None,): + # Can only pass None to defer(), not only(), as the rest option. + # That won't stop people trying to do this, so let's be explicit. + raise TypeError("Cannot pass None as an argument to only().") + for field in fields: + field = field.split(LOOKUP_SEP, 1)[0] + if field in self.query._filtered_relations: + raise ValueError("only() is not supported with FilteredRelation.") + clone = self._chain() + clone.query.add_immediate_loading(fields) + return clone + + def using(self, alias): + """Select which database this QuerySet should execute against.""" + clone = self._chain() + clone._db = alias + return clone + + ################################### + # PUBLIC INTROSPECTION ATTRIBUTES # + ################################### + + @property + def ordered(self): + """ + Return True if the QuerySet is ordered -- i.e. has an order_by() + clause or a default ordering on the model (or is empty). + """ + if isinstance(self, EmptyQuerySet): + return True + if self.query.extra_order_by or self.query.order_by: + return True + elif ( + self.query.default_ordering + and self.query.get_meta().ordering + and + # A default ordering doesn't affect GROUP BY queries. + not self.query.group_by + ): + return True + else: + return False + + @property + def db(self): + """Return the database used if this query is executed now.""" + if self._for_write: + return self._db or router.db_for_write(self.model, **self._hints) + return self._db or router.db_for_read(self.model, **self._hints) + + ################### + # PRIVATE METHODS # + ################### + + def _insert( + self, + objs, + fields, + returning_fields=None, + raw=False, + using=None, + on_conflict=None, + update_fields=None, + unique_fields=None, + ): + """ + Insert a new record for the given model. This provides an interface to + the InsertQuery class and is how Model.save() is implemented. + """ + self._for_write = True + if using is None: + using = self.db + query = sql.InsertQuery( + self.model, + on_conflict=on_conflict, + update_fields=update_fields, + unique_fields=unique_fields, + ) + query.insert_values(fields, objs, raw=raw) + return query.get_compiler(using=using).execute_sql(returning_fields) + + _insert.alters_data = True + _insert.queryset_only = False + + def _batched_insert( + self, + objs, + fields, + batch_size, + on_conflict=None, + update_fields=None, + unique_fields=None, + ): + """ + Helper method for bulk_create() to insert objs one batch at a time. + """ + connection = connections[self.db] + ops = connection.ops + max_batch_size = max(ops.bulk_batch_size(fields, objs), 1) + batch_size = min(batch_size, max_batch_size) if batch_size else max_batch_size + inserted_rows = [] + bulk_return = connection.features.can_return_rows_from_bulk_insert + for item in [objs[i : i + batch_size] for i in range(0, len(objs), batch_size)]: + if bulk_return and ( + on_conflict is None or on_conflict == OnConflict.UPDATE + ): + inserted_rows.extend( + self._insert( + item, + fields=fields, + using=self.db, + on_conflict=on_conflict, + update_fields=update_fields, + unique_fields=unique_fields, + returning_fields=self.model._meta.db_returning_fields, + ) + ) + else: + self._insert( + item, + fields=fields, + using=self.db, + on_conflict=on_conflict, + update_fields=update_fields, + unique_fields=unique_fields, + ) + return inserted_rows + + def _chain(self): + """ + Return a copy of the current QuerySet that's ready for another + operation. + """ + obj = self._clone() + if obj._sticky_filter: + obj.query.filter_is_sticky = True + obj._sticky_filter = False + return obj + + def _clone(self): + """ + Return a copy of the current QuerySet. A lightweight alternative + to deepcopy(). + """ + c = self.__class__( + model=self.model, + query=self.query.chain(), + using=self._db, + hints=self._hints, + ) + c._sticky_filter = self._sticky_filter + c._for_write = self._for_write + c._prefetch_related_lookups = self._prefetch_related_lookups[:] + c._known_related_objects = self._known_related_objects + c._iterable_class = self._iterable_class + c._fields = self._fields + return c + + def _fetch_all(self): + if self._result_cache is None: + self._result_cache = list(self._iterable_class(self)) + if self._prefetch_related_lookups and not self._prefetch_done: + self._prefetch_related_objects() + + def _next_is_sticky(self): + """ + Indicate that the next filter call and the one following that should + be treated as a single filter. This is only important when it comes to + determining when to reuse tables for many-to-many filters. Required so + that we can filter naturally on the results of related managers. + + This doesn't return a clone of the current QuerySet (it returns + "self"). The method is only used internally and should be immediately + followed by a filter() that does create a clone. + """ + self._sticky_filter = True + return self + + def _merge_sanity_check(self, other): + """Check that two QuerySet classes may be merged.""" + if self._fields is not None and ( + set(self.query.values_select) != set(other.query.values_select) + or set(self.query.extra_select) != set(other.query.extra_select) + or set(self.query.annotation_select) != set(other.query.annotation_select) + ): + raise TypeError( + "Merging '%s' classes must involve the same values in each case." + % self.__class__.__name__ + ) + + def _merge_known_related_objects(self, other): + """ + Keep track of all known related objects from either QuerySet instance. + """ + for field, objects in other._known_related_objects.items(): + self._known_related_objects.setdefault(field, {}).update(objects) + + def resolve_expression(self, *args, **kwargs): + if self._fields and len(self._fields) > 1: + # values() queryset can only be used as nested queries + # if they are set up to select only a single field. + raise TypeError("Cannot use multi-field values as a filter value.") + query = self.query.resolve_expression(*args, **kwargs) + query._db = self._db + return query + + resolve_expression.queryset_only = True + + def _add_hints(self, **hints): + """ + Update hinting information for use by routers. Add new key/values or + overwrite existing key/values. + """ + self._hints.update(hints) + + def _has_filters(self): + """ + Check if this QuerySet has any filtering going on. This isn't + equivalent with checking if all objects are present in results, for + example, qs[1:]._has_filters() -> False. + """ + return self.query.has_filters() + + @staticmethod + def _validate_values_are_expressions(values, method_name): + invalid_args = sorted( + str(arg) for arg in values if not hasattr(arg, "resolve_expression") + ) + if invalid_args: + raise TypeError( + "QuerySet.%s() received non-expression(s): %s." + % ( + method_name, + ", ".join(invalid_args), + ) + ) + + def _not_support_combined_queries(self, operation_name): + if self.query.combinator: + raise NotSupportedError( + "Calling QuerySet.%s() after %s() is not supported." + % (operation_name, self.query.combinator) + ) + + def _check_operator_queryset(self, other, operator_): + if self.query.combinator or other.query.combinator: + raise TypeError(f"Cannot use {operator_} operator with combined queryset.") + + def _check_ordering_first_last_queryset_aggregation(self, method): + if isinstance(self.query.group_by, tuple) and not any( + col.output_field is self.model._meta.pk for col in self.query.group_by + ): + raise TypeError( + f"Cannot use QuerySet.{method}() on an unordered queryset performing " + f"aggregation. Add an ordering with order_by()." + ) + + +class InstanceCheckMeta(type): + def __instancecheck__(self, instance): + return isinstance(instance, QuerySet) and instance.query.is_empty() + + +class EmptyQuerySet(metaclass=InstanceCheckMeta): + """ + Marker class to checking if a queryset is empty by .none(): + isinstance(qs.none(), EmptyQuerySet) -> True + """ + + def __init__(self, *args, **kwargs): + raise TypeError("EmptyQuerySet can't be instantiated") + + +class RawQuerySet: + """ + Provide an iterator which converts the results of raw SQL queries into + annotated model instances. + """ + + def __init__( + self, + raw_query, + model=None, + query=None, + params=(), + translations=None, + using=None, + hints=None, + ): + self.raw_query = raw_query + self.model = model + self._db = using + self._hints = hints or {} + self.query = query or sql.RawQuery(sql=raw_query, using=self.db, params=params) + self.params = params + self.translations = translations or {} + self._result_cache = None + self._prefetch_related_lookups = () + self._prefetch_done = False + + def resolve_model_init_order(self): + """Resolve the init field names and value positions.""" + converter = connections[self.db].introspection.identifier_converter + model_init_fields = [ + f for f in self.model._meta.fields if converter(f.column) in self.columns + ] + annotation_fields = [ + (column, pos) + for pos, column in enumerate(self.columns) + if column not in self.model_fields + ] + model_init_order = [ + self.columns.index(converter(f.column)) for f in model_init_fields + ] + model_init_names = [f.attname for f in model_init_fields] + return model_init_names, model_init_order, annotation_fields + + def prefetch_related(self, *lookups): + """Same as QuerySet.prefetch_related()""" + clone = self._clone() + if lookups == (None,): + clone._prefetch_related_lookups = () + else: + clone._prefetch_related_lookups = clone._prefetch_related_lookups + lookups + return clone + + def _prefetch_related_objects(self): + prefetch_related_objects(self._result_cache, *self._prefetch_related_lookups) + self._prefetch_done = True + + def _clone(self): + """Same as QuerySet._clone()""" + c = self.__class__( + self.raw_query, + model=self.model, + query=self.query, + params=self.params, + translations=self.translations, + using=self._db, + hints=self._hints, + ) + c._prefetch_related_lookups = self._prefetch_related_lookups[:] + return c + + def _fetch_all(self): + if self._result_cache is None: + self._result_cache = list(self.iterator()) + if self._prefetch_related_lookups and not self._prefetch_done: + self._prefetch_related_objects() + + def __len__(self): + self._fetch_all() + return len(self._result_cache) + + def __bool__(self): + self._fetch_all() + return bool(self._result_cache) + + def __iter__(self): + self._fetch_all() + return iter(self._result_cache) + + def __aiter__(self): + # Remember, __aiter__ itself is synchronous, it's the thing it returns + # that is async! + async def generator(): + await sync_to_async(self._fetch_all)() + for item in self._result_cache: + yield item + + return generator() + + def iterator(self): + yield from RawModelIterable(self) + + def __repr__(self): + return "<%s: %s>" % (self.__class__.__name__, self.query) + + def __getitem__(self, k): + return list(self)[k] + + @property + def db(self): + """Return the database used if this query is executed now.""" + return self._db or router.db_for_read(self.model, **self._hints) + + def using(self, alias): + """Select the database this RawQuerySet should execute against.""" + return RawQuerySet( + self.raw_query, + model=self.model, + query=self.query.chain(using=alias), + params=self.params, + translations=self.translations, + using=alias, + ) + + @cached_property + def columns(self): + """ + A list of model field names in the order they'll appear in the + query results. + """ + columns = self.query.get_columns() + # Adjust any column names which don't match field names + for query_name, model_name in self.translations.items(): + # Ignore translations for nonexistent column names + try: + index = columns.index(query_name) + except ValueError: + pass + else: + columns[index] = model_name + return columns + + @cached_property + def model_fields(self): + """A dict mapping column names to model field names.""" + converter = connections[self.db].introspection.identifier_converter + model_fields = {} + for field in self.model._meta.fields: + name, column = field.get_attname_column() + model_fields[converter(column)] = field + return model_fields + + +class Prefetch: + def __init__(self, lookup, queryset=None, to_attr=None): + # `prefetch_through` is the path we traverse to perform the prefetch. + self.prefetch_through = lookup + # `prefetch_to` is the path to the attribute that stores the result. + self.prefetch_to = lookup + if queryset is not None and ( + isinstance(queryset, RawQuerySet) + or ( + hasattr(queryset, "_iterable_class") + and not issubclass(queryset._iterable_class, ModelIterable) + ) + ): + raise ValueError( + "Prefetch querysets cannot use raw(), values(), and values_list()." + ) + if to_attr: + self.prefetch_to = LOOKUP_SEP.join( + lookup.split(LOOKUP_SEP)[:-1] + [to_attr] + ) + + self.queryset = queryset + self.to_attr = to_attr + + def __getstate__(self): + obj_dict = self.__dict__.copy() + if self.queryset is not None: + queryset = self.queryset._chain() + # Prevent the QuerySet from being evaluated + queryset._result_cache = [] + queryset._prefetch_done = True + obj_dict["queryset"] = queryset + return obj_dict + + def add_prefix(self, prefix): + self.prefetch_through = prefix + LOOKUP_SEP + self.prefetch_through + self.prefetch_to = prefix + LOOKUP_SEP + self.prefetch_to + + def get_current_prefetch_to(self, level): + return LOOKUP_SEP.join(self.prefetch_to.split(LOOKUP_SEP)[: level + 1]) + + def get_current_to_attr(self, level): + parts = self.prefetch_to.split(LOOKUP_SEP) + to_attr = parts[level] + as_attr = self.to_attr and level == len(parts) - 1 + return to_attr, as_attr + + def get_current_queryset(self, level): + warnings.warn( + "Prefetch.get_current_queryset() is deprecated. Use " + "get_current_querysets() instead.", + RemovedInDjango60Warning, + stacklevel=2, + ) + querysets = self.get_current_querysets(level) + return querysets[0] if querysets is not None else None + + def get_current_querysets(self, level): + if ( + self.get_current_prefetch_to(level) == self.prefetch_to + and self.queryset is not None + ): + return [self.queryset] + return None + + def __eq__(self, other): + if not isinstance(other, Prefetch): + return NotImplemented + return self.prefetch_to == other.prefetch_to + + def __hash__(self): + return hash((self.__class__, self.prefetch_to)) + + +def normalize_prefetch_lookups(lookups, prefix=None): + """Normalize lookups into Prefetch objects.""" + ret = [] + for lookup in lookups: + if not isinstance(lookup, Prefetch): + lookup = Prefetch(lookup) + if prefix: + lookup.add_prefix(prefix) + ret.append(lookup) + return ret + + +def prefetch_related_objects(model_instances, *related_lookups): + """ + Populate prefetched object caches for a list of model instances based on + the lookups/Prefetch instances given. + """ + if not model_instances: + return # nothing to do + + # We need to be able to dynamically add to the list of prefetch_related + # lookups that we look up (see below). So we need some book keeping to + # ensure we don't do duplicate work. + done_queries = {} # dictionary of things like 'foo__bar': [results] + + auto_lookups = set() # we add to this as we go through. + followed_descriptors = set() # recursion protection + + all_lookups = normalize_prefetch_lookups(reversed(related_lookups)) + while all_lookups: + lookup = all_lookups.pop() + if lookup.prefetch_to in done_queries: + if lookup.queryset is not None: + raise ValueError( + "'%s' lookup was already seen with a different queryset. " + "You may need to adjust the ordering of your lookups." + % lookup.prefetch_to + ) + + continue + + # Top level, the list of objects to decorate is the result cache + # from the primary QuerySet. It won't be for deeper levels. + obj_list = model_instances + + through_attrs = lookup.prefetch_through.split(LOOKUP_SEP) + for level, through_attr in enumerate(through_attrs): + # Prepare main instances + if not obj_list: + break + + prefetch_to = lookup.get_current_prefetch_to(level) + if prefetch_to in done_queries: + # Skip any prefetching, and any object preparation + obj_list = done_queries[prefetch_to] + continue + + # Prepare objects: + good_objects = True + for obj in obj_list: + # Since prefetching can re-use instances, it is possible to have + # the same instance multiple times in obj_list, so obj might + # already be prepared. + if not hasattr(obj, "_prefetched_objects_cache"): + try: + obj._prefetched_objects_cache = {} + except (AttributeError, TypeError): + # Must be an immutable object from + # values_list(flat=True), for example (TypeError) or + # a QuerySet subclass that isn't returning Model + # instances (AttributeError), either in Django or a 3rd + # party. prefetch_related() doesn't make sense, so quit. + good_objects = False + break + if not good_objects: + break + + # Descend down tree + + # We assume that objects retrieved are homogeneous (which is the premise + # of prefetch_related), so what applies to first object applies to all. + first_obj = obj_list[0] + to_attr = lookup.get_current_to_attr(level)[0] + prefetcher, descriptor, attr_found, is_fetched = get_prefetcher( + first_obj, through_attr, to_attr + ) + + if not attr_found: + raise AttributeError( + "Cannot find '%s' on %s object, '%s' is an invalid " + "parameter to prefetch_related()" + % ( + through_attr, + first_obj.__class__.__name__, + lookup.prefetch_through, + ) + ) + + if level == len(through_attrs) - 1 and prefetcher is None: + # Last one, this *must* resolve to something that supports + # prefetching, otherwise there is no point adding it and the + # developer asking for it has made a mistake. + raise ValueError( + "'%s' does not resolve to an item that supports " + "prefetching - this is an invalid parameter to " + "prefetch_related()." % lookup.prefetch_through + ) + + obj_to_fetch = None + if prefetcher is not None: + obj_to_fetch = [obj for obj in obj_list if not is_fetched(obj)] + + if obj_to_fetch: + obj_list, additional_lookups = prefetch_one_level( + obj_to_fetch, + prefetcher, + lookup, + level, + ) + # We need to ensure we don't keep adding lookups from the + # same relationships to stop infinite recursion. So, if we + # are already on an automatically added lookup, don't add + # the new lookups from relationships we've seen already. + if not ( + prefetch_to in done_queries + and lookup in auto_lookups + and descriptor in followed_descriptors + ): + done_queries[prefetch_to] = obj_list + new_lookups = normalize_prefetch_lookups( + reversed(additional_lookups), prefetch_to + ) + auto_lookups.update(new_lookups) + all_lookups.extend(new_lookups) + followed_descriptors.add(descriptor) + else: + # Either a singly related object that has already been fetched + # (e.g. via select_related), or hopefully some other property + # that doesn't support prefetching but needs to be traversed. + + # We replace the current list of parent objects with the list + # of related objects, filtering out empty or missing values so + # that we can continue with nullable or reverse relations. + new_obj_list = [] + for obj in obj_list: + if through_attr in getattr(obj, "_prefetched_objects_cache", ()): + # If related objects have been prefetched, use the + # cache rather than the object's through_attr. + new_obj = list(obj._prefetched_objects_cache.get(through_attr)) + else: + try: + new_obj = getattr(obj, through_attr) + except exceptions.ObjectDoesNotExist: + continue + if new_obj is None: + continue + # We special-case `list` rather than something more generic + # like `Iterable` because we don't want to accidentally match + # user models that define __iter__. + if isinstance(new_obj, list): + new_obj_list.extend(new_obj) + else: + new_obj_list.append(new_obj) + obj_list = new_obj_list + + +async def aprefetch_related_objects(model_instances, *related_lookups): + """See prefetch_related_objects().""" + return await sync_to_async(prefetch_related_objects)( + model_instances, *related_lookups + ) + + +def get_prefetcher(instance, through_attr, to_attr): + """ + For the attribute 'through_attr' on the given instance, find + an object that has a get_prefetch_querysets(). + Return a 4 tuple containing: + (the object with get_prefetch_querysets (or None), + the descriptor object representing this relationship (or None), + a boolean that is False if the attribute was not found at all, + a function that takes an instance and returns a boolean that is True if + the attribute has already been fetched for that instance) + """ + + def is_to_attr_fetched(model, to_attr): + # Special case cached_property instances because hasattr() triggers + # attribute computation and assignment. + if isinstance(getattr(model, to_attr, None), cached_property): + + def has_cached_property(instance): + return to_attr in instance.__dict__ + + return has_cached_property + + def has_to_attr_attribute(instance): + return hasattr(instance, to_attr) + + return has_to_attr_attribute + + prefetcher = None + is_fetched = is_to_attr_fetched(instance.__class__, to_attr) + + # For singly related objects, we have to avoid getting the attribute + # from the object, as this will trigger the query. So we first try + # on the class, in order to get the descriptor object. + rel_obj_descriptor = getattr(instance.__class__, through_attr, None) + if rel_obj_descriptor is None: + attr_found = hasattr(instance, through_attr) + else: + attr_found = True + if rel_obj_descriptor: + # singly related object, descriptor object has the + # get_prefetch_querysets() method. + if ( + hasattr(rel_obj_descriptor, "get_prefetch_querysets") + # RemovedInDjango60Warning. + or hasattr(rel_obj_descriptor, "get_prefetch_queryset") + ): + prefetcher = rel_obj_descriptor + # If to_attr is set, check if the value has already been set, + # which is done with has_to_attr_attribute(). Do not use the + # method from the descriptor, as the cache_name it defines + # checks the field name, not the to_attr value. + if through_attr == to_attr: + is_fetched = rel_obj_descriptor.is_cached + else: + # descriptor doesn't support prefetching, so we go ahead and get + # the attribute on the instance rather than the class to + # support many related managers + rel_obj = getattr(instance, through_attr) + if ( + hasattr(rel_obj, "get_prefetch_querysets") + # RemovedInDjango60Warning. + or hasattr(rel_obj, "get_prefetch_queryset") + ): + prefetcher = rel_obj + if through_attr == to_attr: + + def in_prefetched_cache(instance): + return through_attr in instance._prefetched_objects_cache + + is_fetched = in_prefetched_cache + return prefetcher, rel_obj_descriptor, attr_found, is_fetched + + +def prefetch_one_level(instances, prefetcher, lookup, level): + """ + Helper function for prefetch_related_objects(). + + Run prefetches on all instances using the prefetcher object, + assigning results to relevant caches in instance. + + Return the prefetched objects along with any additional prefetches that + must be done due to prefetch_related lookups found from default managers. + """ + # prefetcher must have a method get_prefetch_querysets() which takes a list + # of instances, and returns a tuple: + + # (queryset of instances of self.model that are related to passed in instances, + # callable that gets value to be matched for returned instances, + # callable that gets value to be matched for passed in instances, + # boolean that is True for singly related objects, + # cache or field name to assign to, + # boolean that is True when the previous argument is a cache name vs a field name). + + # The 'values to be matched' must be hashable as they will be used + # in a dictionary. + + if hasattr(prefetcher, "get_prefetch_querysets"): + ( + rel_qs, + rel_obj_attr, + instance_attr, + single, + cache_name, + is_descriptor, + ) = prefetcher.get_prefetch_querysets( + instances, lookup.get_current_querysets(level) + ) + else: + warnings.warn( + "The usage of get_prefetch_queryset() in prefetch_related_objects() is " + "deprecated. Implement get_prefetch_querysets() instead.", + RemovedInDjango60Warning, + stacklevel=2, + ) + queryset = None + if querysets := lookup.get_current_querysets(level): + queryset = querysets[0] + ( + rel_qs, + rel_obj_attr, + instance_attr, + single, + cache_name, + is_descriptor, + ) = prefetcher.get_prefetch_queryset(instances, queryset) + # We have to handle the possibility that the QuerySet we just got back + # contains some prefetch_related lookups. We don't want to trigger the + # prefetch_related functionality by evaluating the query. Rather, we need + # to merge in the prefetch_related lookups. + # Copy the lookups in case it is a Prefetch object which could be reused + # later (happens in nested prefetch_related). + additional_lookups = [ + copy.copy(additional_lookup) + for additional_lookup in getattr(rel_qs, "_prefetch_related_lookups", ()) + ] + if additional_lookups: + # Don't need to clone because the manager should have given us a fresh + # instance, so we access an internal instead of using public interface + # for performance reasons. + rel_qs._prefetch_related_lookups = () + + all_related_objects = list(rel_qs) + + rel_obj_cache = {} + for rel_obj in all_related_objects: + rel_attr_val = rel_obj_attr(rel_obj) + rel_obj_cache.setdefault(rel_attr_val, []).append(rel_obj) + + to_attr, as_attr = lookup.get_current_to_attr(level) + # Make sure `to_attr` does not conflict with a field. + if as_attr and instances: + # We assume that objects retrieved are homogeneous (which is the premise + # of prefetch_related), so what applies to first object applies to all. + model = instances[0].__class__ + try: + model._meta.get_field(to_attr) + except exceptions.FieldDoesNotExist: + pass + else: + msg = "to_attr={} conflicts with a field on the {} model." + raise ValueError(msg.format(to_attr, model.__name__)) + + # Whether or not we're prefetching the last part of the lookup. + leaf = len(lookup.prefetch_through.split(LOOKUP_SEP)) - 1 == level + + for obj in instances: + instance_attr_val = instance_attr(obj) + vals = rel_obj_cache.get(instance_attr_val, []) + + if single: + val = vals[0] if vals else None + if as_attr: + # A to_attr has been given for the prefetch. + setattr(obj, to_attr, val) + elif is_descriptor: + # cache_name points to a field name in obj. + # This field is a descriptor for a related object. + setattr(obj, cache_name, val) + else: + # No to_attr has been given for this prefetch operation and the + # cache_name does not point to a descriptor. Store the value of + # the field in the object's field cache. + obj._state.fields_cache[cache_name] = val + else: + if as_attr: + setattr(obj, to_attr, vals) + else: + manager = getattr(obj, to_attr) + if leaf and lookup.queryset is not None: + qs = manager._apply_rel_filters(lookup.queryset) + else: + qs = manager.get_queryset() + qs._result_cache = vals + # We don't want the individual qs doing prefetch_related now, + # since we have merged this into the current work. + qs._prefetch_done = True + obj._prefetched_objects_cache[cache_name] = qs + return all_related_objects, additional_lookups + + +class RelatedPopulator: + """ + RelatedPopulator is used for select_related() object instantiation. + + The idea is that each select_related() model will be populated by a + different RelatedPopulator instance. The RelatedPopulator instances get + klass_info and select (computed in SQLCompiler) plus the used db as + input for initialization. That data is used to compute which columns + to use, how to instantiate the model, and how to populate the links + between the objects. + + The actual creation of the objects is done in populate() method. This + method gets row and from_obj as input and populates the select_related() + model instance. + """ + + def __init__(self, klass_info, select, db): + self.db = db + # Pre-compute needed attributes. The attributes are: + # - model_cls: the possibly deferred model class to instantiate + # - either: + # - cols_start, cols_end: usually the columns in the row are + # in the same order model_cls.__init__ expects them, so we + # can instantiate by model_cls(*row[cols_start:cols_end]) + # - reorder_for_init: When select_related descends to a child + # class, then we want to reuse the already selected parent + # data. However, in this case the parent data isn't necessarily + # in the same order that Model.__init__ expects it to be, so + # we have to reorder the parent data. The reorder_for_init + # attribute contains a function used to reorder the field data + # in the order __init__ expects it. + # - pk_idx: the index of the primary key field in the reordered + # model data. Used to check if a related object exists at all. + # - init_list: the field attnames fetched from the database. For + # deferred models this isn't the same as all attnames of the + # model's fields. + # - related_populators: a list of RelatedPopulator instances if + # select_related() descends to related models from this model. + # - local_setter, remote_setter: Methods to set cached values on + # the object being populated and on the remote object. Usually + # these are Field.set_cached_value() methods. + select_fields = klass_info["select_fields"] + from_parent = klass_info["from_parent"] + if not from_parent: + self.cols_start = select_fields[0] + self.cols_end = select_fields[-1] + 1 + self.init_list = [ + f[0].target.attname for f in select[self.cols_start : self.cols_end] + ] + self.reorder_for_init = None + else: + attname_indexes = { + select[idx][0].target.attname: idx for idx in select_fields + } + model_init_attnames = ( + f.attname for f in klass_info["model"]._meta.concrete_fields + ) + self.init_list = [ + attname for attname in model_init_attnames if attname in attname_indexes + ] + self.reorder_for_init = operator.itemgetter( + *[attname_indexes[attname] for attname in self.init_list] + ) + + self.model_cls = klass_info["model"] + self.pk_idx = self.init_list.index(self.model_cls._meta.pk.attname) + self.related_populators = get_related_populators(klass_info, select, self.db) + self.local_setter = klass_info["local_setter"] + self.remote_setter = klass_info["remote_setter"] + + def populate(self, row, from_obj): + if self.reorder_for_init: + obj_data = self.reorder_for_init(row) + else: + obj_data = row[self.cols_start : self.cols_end] + if obj_data[self.pk_idx] is None: + obj = None + else: + obj = self.model_cls.from_db(self.db, self.init_list, obj_data) + for rel_iter in self.related_populators: + rel_iter.populate(row, obj) + self.local_setter(from_obj, obj) + if obj is not None: + self.remote_setter(obj, from_obj) + + +def get_related_populators(klass_info, select, db): + iterators = [] + related_klass_infos = klass_info.get("related_klass_infos", []) + for rel_klass_info in related_klass_infos: + rel_cls = RelatedPopulator(rel_klass_info, select, db) + iterators.append(rel_cls) + return iterators diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/query_utils.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/query_utils.py new file mode 100644 index 0000000..4f3358e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/query_utils.py @@ -0,0 +1,473 @@ +""" +Various data structures used in query construction. + +Factored out from django.db.models.query to avoid making the main module very +large and/or so that they can be used by other modules without getting into +circular import difficulties. +""" +import functools +import inspect +import logging +from collections import namedtuple + +from django.core.exceptions import FieldError +from django.db import DEFAULT_DB_ALIAS, DatabaseError, connections +from django.db.models.constants import LOOKUP_SEP +from django.utils import tree +from django.utils.functional import cached_property +from django.utils.hashable import make_hashable + +logger = logging.getLogger("django.db.models") + +# PathInfo is used when converting lookups (fk__somecol). The contents +# describe the relation in Model terms (model Options and Fields for both +# sides of the relation. The join_field is the field backing the relation. +PathInfo = namedtuple( + "PathInfo", + "from_opts to_opts target_fields join_field m2m direct filtered_relation", +) + + +def subclasses(cls): + yield cls + for subclass in cls.__subclasses__(): + yield from subclasses(subclass) + + +class Q(tree.Node): + """ + Encapsulate filters as objects that can then be combined logically (using + `&` and `|`). + """ + + # Connection types + AND = "AND" + OR = "OR" + XOR = "XOR" + default = AND + conditional = True + + def __init__(self, *args, _connector=None, _negated=False, **kwargs): + super().__init__( + children=[*args, *sorted(kwargs.items())], + connector=_connector, + negated=_negated, + ) + + def _combine(self, other, conn): + if getattr(other, "conditional", False) is False: + raise TypeError(other) + if not self: + return other.copy() + if not other and isinstance(other, Q): + return self.copy() + + obj = self.create(connector=conn) + obj.add(self, conn) + obj.add(other, conn) + return obj + + def __or__(self, other): + return self._combine(other, self.OR) + + def __and__(self, other): + return self._combine(other, self.AND) + + def __xor__(self, other): + return self._combine(other, self.XOR) + + def __invert__(self): + obj = self.copy() + obj.negate() + return obj + + def resolve_expression( + self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False + ): + # We must promote any new joins to left outer joins so that when Q is + # used as an expression, rows aren't filtered due to joins. + clause, joins = query._add_q( + self, + reuse, + allow_joins=allow_joins, + split_subq=False, + check_filterable=False, + summarize=summarize, + ) + query.promote_joins(joins) + return clause + + def flatten(self): + """ + Recursively yield this Q object and all subexpressions, in depth-first + order. + """ + yield self + for child in self.children: + if isinstance(child, tuple): + # Use the lookup. + child = child[1] + if hasattr(child, "flatten"): + yield from child.flatten() + else: + yield child + + def check(self, against, using=DEFAULT_DB_ALIAS): + """ + Do a database query to check if the expressions of the Q instance + matches against the expressions. + """ + # Avoid circular imports. + from django.db.models import BooleanField, Value + from django.db.models.functions import Coalesce + from django.db.models.sql import Query + from django.db.models.sql.constants import SINGLE + + query = Query(None) + for name, value in against.items(): + if not hasattr(value, "resolve_expression"): + value = Value(value) + query.add_annotation(value, name, select=False) + query.add_annotation(Value(1), "_check") + # This will raise a FieldError if a field is missing in "against". + if connections[using].features.supports_comparing_boolean_expr: + query.add_q(Q(Coalesce(self, True, output_field=BooleanField()))) + else: + query.add_q(self) + compiler = query.get_compiler(using=using) + try: + return compiler.execute_sql(SINGLE) is not None + except DatabaseError as e: + logger.warning("Got a database error calling check() on %r: %s", self, e) + return True + + def deconstruct(self): + path = "%s.%s" % (self.__class__.__module__, self.__class__.__name__) + if path.startswith("django.db.models.query_utils"): + path = path.replace("django.db.models.query_utils", "django.db.models") + args = tuple(self.children) + kwargs = {} + if self.connector != self.default: + kwargs["_connector"] = self.connector + if self.negated: + kwargs["_negated"] = True + return path, args, kwargs + + @cached_property + def identity(self): + path, args, kwargs = self.deconstruct() + identity = [path, *kwargs.items()] + for child in args: + if isinstance(child, tuple): + arg, value = child + value = make_hashable(value) + identity.append((arg, value)) + else: + identity.append(child) + return tuple(identity) + + def __eq__(self, other): + if not isinstance(other, Q): + return NotImplemented + return other.identity == self.identity + + def __hash__(self): + return hash(self.identity) + + +class DeferredAttribute: + """ + A wrapper for a deferred-loading field. When the value is read from this + object the first time, the query is executed. + """ + + def __init__(self, field): + self.field = field + + def __get__(self, instance, cls=None): + """ + Retrieve and caches the value from the datastore on the first lookup. + Return the cached value. + """ + if instance is None: + return self + data = instance.__dict__ + field_name = self.field.attname + if field_name not in data: + # Let's see if the field is part of the parent chain. If so we + # might be able to reuse the already loaded value. Refs #18343. + val = self._check_parent_chain(instance) + if val is None: + if instance.pk is None and self.field.generated: + raise AttributeError( + "Cannot read a generated field from an unsaved model." + ) + instance.refresh_from_db(fields=[field_name]) + else: + data[field_name] = val + return data[field_name] + + def _check_parent_chain(self, instance): + """ + Check if the field value can be fetched from a parent field already + loaded in the instance. This can be done if the to-be fetched + field is a primary key field. + """ + opts = instance._meta + link_field = opts.get_ancestor_link(self.field.model) + if self.field.primary_key and self.field != link_field: + return getattr(instance, link_field.attname) + return None + + +class class_or_instance_method: + """ + Hook used in RegisterLookupMixin to return partial functions depending on + the caller type (instance or class of models.Field). + """ + + def __init__(self, class_method, instance_method): + self.class_method = class_method + self.instance_method = instance_method + + def __get__(self, instance, owner): + if instance is None: + return functools.partial(self.class_method, owner) + return functools.partial(self.instance_method, instance) + + +class RegisterLookupMixin: + def _get_lookup(self, lookup_name): + return self.get_lookups().get(lookup_name, None) + + @functools.cache + def get_class_lookups(cls): + class_lookups = [ + parent.__dict__.get("class_lookups", {}) for parent in inspect.getmro(cls) + ] + return cls.merge_dicts(class_lookups) + + def get_instance_lookups(self): + class_lookups = self.get_class_lookups() + if instance_lookups := getattr(self, "instance_lookups", None): + return {**class_lookups, **instance_lookups} + return class_lookups + + get_lookups = class_or_instance_method(get_class_lookups, get_instance_lookups) + get_class_lookups = classmethod(get_class_lookups) + + def get_lookup(self, lookup_name): + from django.db.models.lookups import Lookup + + found = self._get_lookup(lookup_name) + if found is None and hasattr(self, "output_field"): + return self.output_field.get_lookup(lookup_name) + if found is not None and not issubclass(found, Lookup): + return None + return found + + def get_transform(self, lookup_name): + from django.db.models.lookups import Transform + + found = self._get_lookup(lookup_name) + if found is None and hasattr(self, "output_field"): + return self.output_field.get_transform(lookup_name) + if found is not None and not issubclass(found, Transform): + return None + return found + + @staticmethod + def merge_dicts(dicts): + """ + Merge dicts in reverse to preference the order of the original list. e.g., + merge_dicts([a, b]) will preference the keys in 'a' over those in 'b'. + """ + merged = {} + for d in reversed(dicts): + merged.update(d) + return merged + + @classmethod + def _clear_cached_class_lookups(cls): + for subclass in subclasses(cls): + subclass.get_class_lookups.cache_clear() + + def register_class_lookup(cls, lookup, lookup_name=None): + if lookup_name is None: + lookup_name = lookup.lookup_name + if "class_lookups" not in cls.__dict__: + cls.class_lookups = {} + cls.class_lookups[lookup_name] = lookup + cls._clear_cached_class_lookups() + return lookup + + def register_instance_lookup(self, lookup, lookup_name=None): + if lookup_name is None: + lookup_name = lookup.lookup_name + if "instance_lookups" not in self.__dict__: + self.instance_lookups = {} + self.instance_lookups[lookup_name] = lookup + return lookup + + register_lookup = class_or_instance_method( + register_class_lookup, register_instance_lookup + ) + register_class_lookup = classmethod(register_class_lookup) + + def _unregister_class_lookup(cls, lookup, lookup_name=None): + """ + Remove given lookup from cls lookups. For use in tests only as it's + not thread-safe. + """ + if lookup_name is None: + lookup_name = lookup.lookup_name + del cls.class_lookups[lookup_name] + cls._clear_cached_class_lookups() + + def _unregister_instance_lookup(self, lookup, lookup_name=None): + """ + Remove given lookup from instance lookups. For use in tests only as + it's not thread-safe. + """ + if lookup_name is None: + lookup_name = lookup.lookup_name + del self.instance_lookups[lookup_name] + + _unregister_lookup = class_or_instance_method( + _unregister_class_lookup, _unregister_instance_lookup + ) + _unregister_class_lookup = classmethod(_unregister_class_lookup) + + +def select_related_descend(field, restricted, requested, select_mask, reverse=False): + """ + Return True if this field should be used to descend deeper for + select_related() purposes. Used by both the query construction code + (compiler.get_related_selections()) and the model instance creation code + (compiler.klass_info). + + Arguments: + * field - the field to be checked + * restricted - a boolean field, indicating if the field list has been + manually restricted using a requested clause) + * requested - The select_related() dictionary. + * select_mask - the dictionary of selected fields. + * reverse - boolean, True if we are checking a reverse select related + """ + if not field.remote_field: + return False + if field.remote_field.parent_link and not reverse: + return False + if restricted: + if reverse and field.related_query_name() not in requested: + return False + if not reverse and field.name not in requested: + return False + if not restricted and field.null: + return False + if ( + restricted + and select_mask + and field.name in requested + and field not in select_mask + ): + raise FieldError( + f"Field {field.model._meta.object_name}.{field.name} cannot be both " + "deferred and traversed using select_related at the same time." + ) + return True + + +def refs_expression(lookup_parts, annotations): + """ + Check if the lookup_parts contains references to the given annotations set. + Because the LOOKUP_SEP is contained in the default annotation names, check + each prefix of the lookup_parts for a match. + """ + for n in range(1, len(lookup_parts) + 1): + level_n_lookup = LOOKUP_SEP.join(lookup_parts[0:n]) + if annotations.get(level_n_lookup): + return level_n_lookup, lookup_parts[n:] + return None, () + + +def check_rel_lookup_compatibility(model, target_opts, field): + """ + Check that self.model is compatible with target_opts. Compatibility + is OK if: + 1) model and opts match (where proxy inheritance is removed) + 2) model is parent of opts' model or the other way around + """ + + def check(opts): + return ( + model._meta.concrete_model == opts.concrete_model + or opts.concrete_model in model._meta.get_parent_list() + or model in opts.get_parent_list() + ) + + # If the field is a primary key, then doing a query against the field's + # model is ok, too. Consider the case: + # class Restaurant(models.Model): + # place = OneToOneField(Place, primary_key=True): + # Restaurant.objects.filter(pk__in=Restaurant.objects.all()). + # If we didn't have the primary key check, then pk__in (== place__in) would + # give Place's opts as the target opts, but Restaurant isn't compatible + # with that. This logic applies only to primary keys, as when doing __in=qs, + # we are going to turn this into __in=qs.values('pk') later on. + return check(target_opts) or ( + getattr(field, "primary_key", False) and check(field.model._meta) + ) + + +class FilteredRelation: + """Specify custom filtering in the ON clause of SQL joins.""" + + def __init__(self, relation_name, *, condition=Q()): + if not relation_name: + raise ValueError("relation_name cannot be empty.") + self.relation_name = relation_name + self.alias = None + if not isinstance(condition, Q): + raise ValueError("condition argument must be a Q() instance.") + # .condition and .resolved_condition have to be stored independently + # as the former must remain unchanged for Join.__eq__ to remain stable + # and reusable even once their .filtered_relation are resolved. + self.condition = condition + self.resolved_condition = None + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return ( + self.relation_name == other.relation_name + and self.alias == other.alias + and self.condition == other.condition + ) + + def clone(self): + clone = FilteredRelation(self.relation_name, condition=self.condition) + clone.alias = self.alias + if (resolved_condition := self.resolved_condition) is not None: + clone.resolved_condition = resolved_condition.clone() + return clone + + def relabeled_clone(self, change_map): + clone = self.clone() + if resolved_condition := clone.resolved_condition: + clone.resolved_condition = resolved_condition.relabeled_clone(change_map) + return clone + + def resolve_expression(self, query, reuse, *args, **kwargs): + clone = self.clone() + clone.resolved_condition = query.build_filter( + self.condition, + can_reuse=reuse, + allow_joins=True, + split_subq=False, + update_join_types=False, + )[0] + return clone + + def as_sql(self, compiler, connection): + return compiler.compile(self.resolved_condition) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/signals.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/signals.py new file mode 100644 index 0000000..a072093 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/signals.py @@ -0,0 +1,54 @@ +from functools import partial + +from django.db.models.utils import make_model_tuple +from django.dispatch import Signal + +class_prepared = Signal() + + +class ModelSignal(Signal): + """ + Signal subclass that allows the sender to be lazily specified as a string + of the `app_label.ModelName` form. + """ + + def _lazy_method(self, method, apps, receiver, sender, **kwargs): + from django.db.models.options import Options + + # This partial takes a single optional argument named "sender". + partial_method = partial(method, receiver, **kwargs) + if isinstance(sender, str): + apps = apps or Options.default_apps + apps.lazy_model_operation(partial_method, make_model_tuple(sender)) + else: + return partial_method(sender) + + def connect(self, receiver, sender=None, weak=True, dispatch_uid=None, apps=None): + self._lazy_method( + super().connect, + apps, + receiver, + sender, + weak=weak, + dispatch_uid=dispatch_uid, + ) + + def disconnect(self, receiver=None, sender=None, dispatch_uid=None, apps=None): + return self._lazy_method( + super().disconnect, apps, receiver, sender, dispatch_uid=dispatch_uid + ) + + +pre_init = ModelSignal(use_caching=True) +post_init = ModelSignal(use_caching=True) + +pre_save = ModelSignal(use_caching=True) +post_save = ModelSignal(use_caching=True) + +pre_delete = ModelSignal(use_caching=True) +post_delete = ModelSignal(use_caching=True) + +m2m_changed = ModelSignal(use_caching=True) + +pre_migrate = Signal() +post_migrate = Signal() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/sql/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/sql/__init__.py new file mode 100644 index 0000000..dd31a6e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/sql/__init__.py @@ -0,0 +1,6 @@ +from django.db.models.sql.query import * # NOQA +from django.db.models.sql.query import Query +from django.db.models.sql.subqueries import * # NOQA +from django.db.models.sql.where import AND, OR, XOR + +__all__ = ["Query", "AND", "OR", "XOR"] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/sql/compiler.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/sql/compiler.py new file mode 100644 index 0000000..b28dc92 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/sql/compiler.py @@ -0,0 +1,2099 @@ +import collections +import json +import re +from functools import partial +from itertools import chain + +from django.core.exceptions import EmptyResultSet, FieldError, FullResultSet +from django.db import DatabaseError, NotSupportedError +from django.db.models.constants import LOOKUP_SEP +from django.db.models.expressions import F, OrderBy, RawSQL, Ref, Value +from django.db.models.functions import Cast, Random +from django.db.models.lookups import Lookup +from django.db.models.query_utils import select_related_descend +from django.db.models.sql.constants import ( + CURSOR, + GET_ITERATOR_CHUNK_SIZE, + MULTI, + NO_RESULTS, + ORDER_DIR, + SINGLE, +) +from django.db.models.sql.query import Query, get_order_dir +from django.db.models.sql.where import AND +from django.db.transaction import TransactionManagementError +from django.utils.functional import cached_property +from django.utils.hashable import make_hashable +from django.utils.regex_helper import _lazy_re_compile + + +class PositionRef(Ref): + def __init__(self, ordinal, refs, source): + self.ordinal = ordinal + super().__init__(refs, source) + + def as_sql(self, compiler, connection): + return str(self.ordinal), () + + +class SQLCompiler: + # Multiline ordering SQL clause may appear from RawSQL. + ordering_parts = _lazy_re_compile( + r"^(.*)\s(?:ASC|DESC).*", + re.MULTILINE | re.DOTALL, + ) + + def __init__(self, query, connection, using, elide_empty=True): + self.query = query + self.connection = connection + self.using = using + # Some queries, e.g. coalesced aggregation, need to be executed even if + # they would return an empty result set. + self.elide_empty = elide_empty + self.quote_cache = {"*": "*"} + # The select, klass_info, and annotations are needed by QuerySet.iterator() + # these are set as a side-effect of executing the query. Note that we calculate + # separately a list of extra select columns needed for grammatical correctness + # of the query, but these columns are not included in self.select. + self.select = None + self.annotation_col_map = None + self.klass_info = None + self._meta_ordering = None + + def __repr__(self): + return ( + f"<{self.__class__.__qualname__} " + f"model={self.query.model.__qualname__} " + f"connection={self.connection!r} using={self.using!r}>" + ) + + def setup_query(self, with_col_aliases=False): + if all(self.query.alias_refcount[a] == 0 for a in self.query.alias_map): + self.query.get_initial_alias() + self.select, self.klass_info, self.annotation_col_map = self.get_select( + with_col_aliases=with_col_aliases, + ) + self.col_count = len(self.select) + + def pre_sql_setup(self, with_col_aliases=False): + """ + Do any necessary class setup immediately prior to producing SQL. This + is for things that can't necessarily be done in __init__ because we + might not have all the pieces in place at that time. + """ + self.setup_query(with_col_aliases=with_col_aliases) + order_by = self.get_order_by() + self.where, self.having, self.qualify = self.query.where.split_having_qualify( + must_group_by=self.query.group_by is not None + ) + extra_select = self.get_extra_select(order_by, self.select) + self.has_extra_select = bool(extra_select) + group_by = self.get_group_by(self.select + extra_select, order_by) + return extra_select, order_by, group_by + + def get_group_by(self, select, order_by): + """ + Return a list of 2-tuples of form (sql, params). + + The logic of what exactly the GROUP BY clause contains is hard + to describe in other words than "if it passes the test suite, + then it is correct". + """ + # Some examples: + # SomeModel.objects.annotate(Count('somecol')) + # GROUP BY: all fields of the model + # + # SomeModel.objects.values('name').annotate(Count('somecol')) + # GROUP BY: name + # + # SomeModel.objects.annotate(Count('somecol')).values('name') + # GROUP BY: all cols of the model + # + # SomeModel.objects.values('name', 'pk') + # .annotate(Count('somecol')).values('pk') + # GROUP BY: name, pk + # + # SomeModel.objects.values('name').annotate(Count('somecol')).values('pk') + # GROUP BY: name, pk + # + # In fact, the self.query.group_by is the minimal set to GROUP BY. It + # can't be ever restricted to a smaller set, but additional columns in + # HAVING, ORDER BY, and SELECT clauses are added to it. Unfortunately + # the end result is that it is impossible to force the query to have + # a chosen GROUP BY clause - you can almost do this by using the form: + # .values(*wanted_cols).annotate(AnAggregate()) + # but any later annotations, extra selects, values calls that + # refer some column outside of the wanted_cols, order_by, or even + # filter calls can alter the GROUP BY clause. + + # The query.group_by is either None (no GROUP BY at all), True + # (group by select fields), or a list of expressions to be added + # to the group by. + if self.query.group_by is None: + return [] + expressions = [] + group_by_refs = set() + if self.query.group_by is not True: + # If the group by is set to a list (by .values() call most likely), + # then we need to add everything in it to the GROUP BY clause. + # Backwards compatibility hack for setting query.group_by. Remove + # when we have public API way of forcing the GROUP BY clause. + # Converts string references to expressions. + for expr in self.query.group_by: + if not hasattr(expr, "as_sql"): + expr = self.query.resolve_ref(expr) + if isinstance(expr, Ref): + if expr.refs not in group_by_refs: + group_by_refs.add(expr.refs) + expressions.append(expr.source) + else: + expressions.append(expr) + # Note that even if the group_by is set, it is only the minimal + # set to group by. So, we need to add cols in select, order_by, and + # having into the select in any case. + selected_expr_positions = {} + for ordinal, (expr, _, alias) in enumerate(select, start=1): + if alias: + selected_expr_positions[expr] = ordinal + # Skip members of the select clause that are already explicitly + # grouped against. + if alias in group_by_refs: + continue + expressions.extend(expr.get_group_by_cols()) + if not self._meta_ordering: + for expr, (sql, params, is_ref) in order_by: + # Skip references to the SELECT clause, as all expressions in + # the SELECT clause are already part of the GROUP BY. + if not is_ref: + expressions.extend(expr.get_group_by_cols()) + having_group_by = self.having.get_group_by_cols() if self.having else () + for expr in having_group_by: + expressions.append(expr) + result = [] + seen = set() + expressions = self.collapse_group_by(expressions, having_group_by) + + allows_group_by_select_index = ( + self.connection.features.allows_group_by_select_index + ) + for expr in expressions: + try: + sql, params = self.compile(expr) + except (EmptyResultSet, FullResultSet): + continue + if ( + allows_group_by_select_index + and (position := selected_expr_positions.get(expr)) is not None + ): + sql, params = str(position), () + else: + sql, params = expr.select_format(self, sql, params) + params_hash = make_hashable(params) + if (sql, params_hash) not in seen: + result.append((sql, params)) + seen.add((sql, params_hash)) + return result + + def collapse_group_by(self, expressions, having): + # If the database supports group by functional dependence reduction, + # then the expressions can be reduced to the set of selected table + # primary keys as all other columns are functionally dependent on them. + if self.connection.features.allows_group_by_selected_pks: + # Filter out all expressions associated with a table's primary key + # present in the grouped columns. This is done by identifying all + # tables that have their primary key included in the grouped + # columns and removing non-primary key columns referring to them. + # Unmanaged models are excluded because they could be representing + # database views on which the optimization might not be allowed. + pks = { + expr + for expr in expressions + if ( + hasattr(expr, "target") + and expr.target.primary_key + and self.connection.features.allows_group_by_selected_pks_on_model( + expr.target.model + ) + ) + } + aliases = {expr.alias for expr in pks} + expressions = [ + expr + for expr in expressions + if expr in pks + or expr in having + or getattr(expr, "alias", None) not in aliases + ] + return expressions + + def get_select(self, with_col_aliases=False): + """ + Return three values: + - a list of 3-tuples of (expression, (sql, params), alias) + - a klass_info structure, + - a dictionary of annotations + + The (sql, params) is what the expression will produce, and alias is the + "AS alias" for the column (possibly None). + + The klass_info structure contains the following information: + - The base model of the query. + - Which columns for that model are present in the query (by + position of the select clause). + - related_klass_infos: [f, klass_info] to descent into + + The annotations is a dictionary of {'attname': column position} values. + """ + select = [] + klass_info = None + annotations = {} + select_idx = 0 + for alias, (sql, params) in self.query.extra_select.items(): + annotations[alias] = select_idx + select.append((RawSQL(sql, params), alias)) + select_idx += 1 + assert not (self.query.select and self.query.default_cols) + select_mask = self.query.get_select_mask() + if self.query.default_cols: + cols = self.get_default_columns(select_mask) + else: + # self.query.select is a special case. These columns never go to + # any model. + cols = self.query.select + if cols: + select_list = [] + for col in cols: + select_list.append(select_idx) + select.append((col, None)) + select_idx += 1 + klass_info = { + "model": self.query.model, + "select_fields": select_list, + } + for alias, annotation in self.query.annotation_select.items(): + annotations[alias] = select_idx + select.append((annotation, alias)) + select_idx += 1 + + if self.query.select_related: + related_klass_infos = self.get_related_selections(select, select_mask) + klass_info["related_klass_infos"] = related_klass_infos + + def get_select_from_parent(klass_info): + for ki in klass_info["related_klass_infos"]: + if ki["from_parent"]: + ki["select_fields"] = ( + klass_info["select_fields"] + ki["select_fields"] + ) + get_select_from_parent(ki) + + get_select_from_parent(klass_info) + + ret = [] + col_idx = 1 + for col, alias in select: + try: + sql, params = self.compile(col) + except EmptyResultSet: + empty_result_set_value = getattr( + col, "empty_result_set_value", NotImplemented + ) + if empty_result_set_value is NotImplemented: + # Select a predicate that's always False. + sql, params = "0", () + else: + sql, params = self.compile(Value(empty_result_set_value)) + except FullResultSet: + sql, params = self.compile(Value(True)) + else: + sql, params = col.select_format(self, sql, params) + if alias is None and with_col_aliases: + alias = f"col{col_idx}" + col_idx += 1 + ret.append((col, (sql, params), alias)) + return ret, klass_info, annotations + + def _order_by_pairs(self): + if self.query.extra_order_by: + ordering = self.query.extra_order_by + elif not self.query.default_ordering: + ordering = self.query.order_by + elif self.query.order_by: + ordering = self.query.order_by + elif (meta := self.query.get_meta()) and meta.ordering: + ordering = meta.ordering + self._meta_ordering = ordering + else: + ordering = [] + if self.query.standard_ordering: + default_order, _ = ORDER_DIR["ASC"] + else: + default_order, _ = ORDER_DIR["DESC"] + + selected_exprs = {} + # Avoid computing `selected_exprs` if there is no `ordering` as it's + # relatively expensive. + if ordering and (select := self.select): + for ordinal, (expr, _, alias) in enumerate(select, start=1): + pos_expr = PositionRef(ordinal, alias, expr) + if alias: + selected_exprs[alias] = pos_expr + selected_exprs[expr] = pos_expr + + for field in ordering: + if hasattr(field, "resolve_expression"): + if isinstance(field, Value): + # output_field must be resolved for constants. + field = Cast(field, field.output_field) + if not isinstance(field, OrderBy): + field = field.asc() + if not self.query.standard_ordering: + field = field.copy() + field.reverse_ordering() + select_ref = selected_exprs.get(field.expression) + if select_ref or ( + isinstance(field.expression, F) + and (select_ref := selected_exprs.get(field.expression.name)) + ): + # Emulation of NULLS (FIRST|LAST) cannot be combined with + # the usage of ordering by position. + if ( + field.nulls_first is None and field.nulls_last is None + ) or self.connection.features.supports_order_by_nulls_modifier: + field = field.copy() + field.expression = select_ref + # Alias collisions are not possible when dealing with + # combined queries so fallback to it if emulation of NULLS + # handling is required. + elif self.query.combinator: + field = field.copy() + field.expression = Ref(select_ref.refs, select_ref.source) + yield field, select_ref is not None + continue + if field == "?": # random + yield OrderBy(Random()), False + continue + + col, order = get_order_dir(field, default_order) + descending = order == "DESC" + + if select_ref := selected_exprs.get(col): + # Reference to expression in SELECT clause + yield ( + OrderBy( + select_ref, + descending=descending, + ), + True, + ) + continue + if col in self.query.annotations: + # References to an expression which is masked out of the SELECT + # clause. + if self.query.combinator and self.select: + # Don't use the resolved annotation because other + # combinated queries might define it differently. + expr = F(col) + else: + expr = self.query.annotations[col] + if isinstance(expr, Value): + # output_field must be resolved for constants. + expr = Cast(expr, expr.output_field) + yield OrderBy(expr, descending=descending), False + continue + + if "." in field: + # This came in through an extra(order_by=...) addition. Pass it + # on verbatim. + table, col = col.split(".", 1) + yield ( + OrderBy( + RawSQL( + "%s.%s" % (self.quote_name_unless_alias(table), col), [] + ), + descending=descending, + ), + False, + ) + continue + + if self.query.extra and col in self.query.extra: + if col in self.query.extra_select: + yield ( + OrderBy( + Ref(col, RawSQL(*self.query.extra[col])), + descending=descending, + ), + True, + ) + else: + yield ( + OrderBy(RawSQL(*self.query.extra[col]), descending=descending), + False, + ) + else: + if self.query.combinator and self.select: + # Don't use the first model's field because other + # combinated queries might define it differently. + yield OrderBy(F(col), descending=descending), False + else: + # 'col' is of the form 'field' or 'field1__field2' or + # '-field1__field2__field', etc. + yield from self.find_ordering_name( + field, + self.query.get_meta(), + default_order=default_order, + ) + + def get_order_by(self): + """ + Return a list of 2-tuples of the form (expr, (sql, params, is_ref)) for + the ORDER BY clause. + + The order_by clause can alter the select clause (for example it can add + aliases to clauses that do not yet have one, or it can add totally new + select clauses). + """ + result = [] + seen = set() + for expr, is_ref in self._order_by_pairs(): + resolved = expr.resolve_expression(self.query, allow_joins=True, reuse=None) + if not is_ref and self.query.combinator and self.select: + src = resolved.expression + expr_src = expr.expression + for sel_expr, _, col_alias in self.select: + if src == sel_expr: + # When values() is used the exact alias must be used to + # reference annotations. + if ( + self.query.has_select_fields + and col_alias in self.query.annotation_select + and not ( + isinstance(expr_src, F) and col_alias == expr_src.name + ) + ): + continue + resolved.set_source_expressions( + [Ref(col_alias if col_alias else src.target.column, src)] + ) + break + else: + # Add column used in ORDER BY clause to the selected + # columns and to each combined query. + order_by_idx = len(self.query.select) + 1 + col_alias = f"__orderbycol{order_by_idx}" + for q in self.query.combined_queries: + # If fields were explicitly selected through values() + # combined queries cannot be augmented. + if q.has_select_fields: + raise DatabaseError( + "ORDER BY term does not match any column in " + "the result set." + ) + q.add_annotation(expr_src, col_alias) + self.query.add_select_col(resolved, col_alias) + resolved.set_source_expressions([Ref(col_alias, src)]) + sql, params = self.compile(resolved) + # Don't add the same column twice, but the order direction is + # not taken into account so we strip it. When this entire method + # is refactored into expressions, then we can check each part as we + # generate it. + without_ordering = self.ordering_parts.search(sql)[1] + params_hash = make_hashable(params) + if (without_ordering, params_hash) in seen: + continue + seen.add((without_ordering, params_hash)) + result.append((resolved, (sql, params, is_ref))) + return result + + def get_extra_select(self, order_by, select): + extra_select = [] + if self.query.distinct and not self.query.distinct_fields: + select_sql = [t[1] for t in select] + for expr, (sql, params, is_ref) in order_by: + without_ordering = self.ordering_parts.search(sql)[1] + if not is_ref and (without_ordering, params) not in select_sql: + extra_select.append((expr, (without_ordering, params), None)) + return extra_select + + def quote_name_unless_alias(self, name): + """ + A wrapper around connection.ops.quote_name that doesn't quote aliases + for table names. This avoids problems with some SQL dialects that treat + quoted strings specially (e.g. PostgreSQL). + """ + if name in self.quote_cache: + return self.quote_cache[name] + if ( + (name in self.query.alias_map and name not in self.query.table_map) + or name in self.query.extra_select + or ( + self.query.external_aliases.get(name) + and name not in self.query.table_map + ) + ): + self.quote_cache[name] = name + return name + r = self.connection.ops.quote_name(name) + self.quote_cache[name] = r + return r + + def compile(self, node): + vendor_impl = getattr(node, "as_" + self.connection.vendor, None) + if vendor_impl: + sql, params = vendor_impl(self, self.connection) + else: + sql, params = node.as_sql(self, self.connection) + return sql, params + + def get_combinator_sql(self, combinator, all): + features = self.connection.features + compilers = [ + query.get_compiler(self.using, self.connection, self.elide_empty) + for query in self.query.combined_queries + ] + if not features.supports_slicing_ordering_in_compound: + for compiler in compilers: + if compiler.query.is_sliced: + raise DatabaseError( + "LIMIT/OFFSET not allowed in subqueries of compound statements." + ) + if compiler.get_order_by(): + raise DatabaseError( + "ORDER BY not allowed in subqueries of compound statements." + ) + elif self.query.is_sliced and combinator == "union": + for compiler in compilers: + # A sliced union cannot have its parts elided as some of them + # might be sliced as well and in the event where only a single + # part produces a non-empty resultset it might be impossible to + # generate valid SQL. + compiler.elide_empty = False + parts = () + for compiler in compilers: + try: + # If the columns list is limited, then all combined queries + # must have the same columns list. Set the selects defined on + # the query on all combined queries, if not already set. + if not compiler.query.values_select and self.query.values_select: + compiler.query = compiler.query.clone() + compiler.query.set_values( + ( + *self.query.extra_select, + *self.query.values_select, + *self.query.annotation_select, + ) + ) + part_sql, part_args = compiler.as_sql(with_col_aliases=True) + if compiler.query.combinator: + # Wrap in a subquery if wrapping in parentheses isn't + # supported. + if not features.supports_parentheses_in_compound: + part_sql = "SELECT * FROM ({})".format(part_sql) + # Add parentheses when combining with compound query if not + # already added for all compound queries. + elif ( + self.query.subquery + or not features.supports_slicing_ordering_in_compound + ): + part_sql = "({})".format(part_sql) + elif ( + self.query.subquery + and features.supports_slicing_ordering_in_compound + ): + part_sql = "({})".format(part_sql) + parts += ((part_sql, part_args),) + except EmptyResultSet: + # Omit the empty queryset with UNION and with DIFFERENCE if the + # first queryset is nonempty. + if combinator == "union" or (combinator == "difference" and parts): + continue + raise + if not parts: + raise EmptyResultSet + combinator_sql = self.connection.ops.set_operators[combinator] + if all and combinator == "union": + combinator_sql += " ALL" + braces = "{}" + if not self.query.subquery and features.supports_slicing_ordering_in_compound: + braces = "({})" + sql_parts, args_parts = zip( + *((braces.format(sql), args) for sql, args in parts) + ) + result = [" {} ".format(combinator_sql).join(sql_parts)] + params = [] + for part in args_parts: + params.extend(part) + return result, params + + def get_qualify_sql(self): + where_parts = [] + if self.where: + where_parts.append(self.where) + if self.having: + where_parts.append(self.having) + inner_query = self.query.clone() + inner_query.subquery = True + inner_query.where = inner_query.where.__class__(where_parts) + # Augment the inner query with any window function references that + # might have been masked via values() and alias(). If any masked + # aliases are added they'll be masked again to avoid fetching + # the data in the `if qual_aliases` branch below. + select = { + expr: alias for expr, _, alias in self.get_select(with_col_aliases=True)[0] + } + select_aliases = set(select.values()) + qual_aliases = set() + replacements = {} + + def collect_replacements(expressions): + while expressions: + expr = expressions.pop() + if expr in replacements: + continue + elif select_alias := select.get(expr): + replacements[expr] = select_alias + elif isinstance(expr, Lookup): + expressions.extend(expr.get_source_expressions()) + elif isinstance(expr, Ref): + if expr.refs not in select_aliases: + expressions.extend(expr.get_source_expressions()) + else: + num_qual_alias = len(qual_aliases) + select_alias = f"qual{num_qual_alias}" + qual_aliases.add(select_alias) + inner_query.add_annotation(expr, select_alias) + replacements[expr] = select_alias + + collect_replacements(list(self.qualify.leaves())) + self.qualify = self.qualify.replace_expressions( + {expr: Ref(alias, expr) for expr, alias in replacements.items()} + ) + order_by = [] + for order_by_expr, *_ in self.get_order_by(): + collect_replacements(order_by_expr.get_source_expressions()) + order_by.append( + order_by_expr.replace_expressions( + {expr: Ref(alias, expr) for expr, alias in replacements.items()} + ) + ) + inner_query_compiler = inner_query.get_compiler( + self.using, connection=self.connection, elide_empty=self.elide_empty + ) + inner_sql, inner_params = inner_query_compiler.as_sql( + # The limits must be applied to the outer query to avoid pruning + # results too eagerly. + with_limits=False, + # Force unique aliasing of selected columns to avoid collisions + # and make rhs predicates referencing easier. + with_col_aliases=True, + ) + qualify_sql, qualify_params = self.compile(self.qualify) + result = [ + "SELECT * FROM (", + inner_sql, + ")", + self.connection.ops.quote_name("qualify"), + "WHERE", + qualify_sql, + ] + if qual_aliases: + # If some select aliases were unmasked for filtering purposes they + # must be masked back. + cols = [self.connection.ops.quote_name(alias) for alias in select.values()] + result = [ + "SELECT", + ", ".join(cols), + "FROM (", + *result, + ")", + self.connection.ops.quote_name("qualify_mask"), + ] + params = list(inner_params) + qualify_params + # As the SQL spec is unclear on whether or not derived tables + # ordering must propagate it has to be explicitly repeated on the + # outer-most query to ensure it's preserved. + if order_by: + ordering_sqls = [] + for ordering in order_by: + ordering_sql, ordering_params = self.compile(ordering) + ordering_sqls.append(ordering_sql) + params.extend(ordering_params) + result.extend(["ORDER BY", ", ".join(ordering_sqls)]) + return result, params + + def as_sql(self, with_limits=True, with_col_aliases=False): + """ + Create the SQL for this query. Return the SQL string and list of + parameters. + + If 'with_limits' is False, any limit/offset information is not included + in the query. + """ + refcounts_before = self.query.alias_refcount.copy() + try: + combinator = self.query.combinator + extra_select, order_by, group_by = self.pre_sql_setup( + with_col_aliases=with_col_aliases or bool(combinator), + ) + for_update_part = None + # Is a LIMIT/OFFSET clause needed? + with_limit_offset = with_limits and self.query.is_sliced + combinator = self.query.combinator + features = self.connection.features + if combinator: + if not getattr(features, "supports_select_{}".format(combinator)): + raise NotSupportedError( + "{} is not supported on this database backend.".format( + combinator + ) + ) + result, params = self.get_combinator_sql( + combinator, self.query.combinator_all + ) + elif self.qualify: + result, params = self.get_qualify_sql() + order_by = None + else: + distinct_fields, distinct_params = self.get_distinct() + # This must come after 'select', 'ordering', and 'distinct' + # (see docstring of get_from_clause() for details). + from_, f_params = self.get_from_clause() + try: + where, w_params = ( + self.compile(self.where) if self.where is not None else ("", []) + ) + except EmptyResultSet: + if self.elide_empty: + raise + # Use a predicate that's always False. + where, w_params = "0 = 1", [] + except FullResultSet: + where, w_params = "", [] + try: + having, h_params = ( + self.compile(self.having) + if self.having is not None + else ("", []) + ) + except FullResultSet: + having, h_params = "", [] + result = ["SELECT"] + params = [] + + if self.query.distinct: + distinct_result, distinct_params = self.connection.ops.distinct_sql( + distinct_fields, + distinct_params, + ) + result += distinct_result + params += distinct_params + + out_cols = [] + for _, (s_sql, s_params), alias in self.select + extra_select: + if alias: + s_sql = "%s AS %s" % ( + s_sql, + self.connection.ops.quote_name(alias), + ) + params.extend(s_params) + out_cols.append(s_sql) + + result += [", ".join(out_cols)] + if from_: + result += ["FROM", *from_] + elif self.connection.features.bare_select_suffix: + result += [self.connection.features.bare_select_suffix] + params.extend(f_params) + + if self.query.select_for_update and features.has_select_for_update: + if ( + self.connection.get_autocommit() + # Don't raise an exception when database doesn't + # support transactions, as it's a noop. + and features.supports_transactions + ): + raise TransactionManagementError( + "select_for_update cannot be used outside of a transaction." + ) + + if ( + with_limit_offset + and not features.supports_select_for_update_with_limit + ): + raise NotSupportedError( + "LIMIT/OFFSET is not supported with " + "select_for_update on this database backend." + ) + nowait = self.query.select_for_update_nowait + skip_locked = self.query.select_for_update_skip_locked + of = self.query.select_for_update_of + no_key = self.query.select_for_no_key_update + # If it's a NOWAIT/SKIP LOCKED/OF/NO KEY query but the + # backend doesn't support it, raise NotSupportedError to + # prevent a possible deadlock. + if nowait and not features.has_select_for_update_nowait: + raise NotSupportedError( + "NOWAIT is not supported on this database backend." + ) + elif skip_locked and not features.has_select_for_update_skip_locked: + raise NotSupportedError( + "SKIP LOCKED is not supported on this database backend." + ) + elif of and not features.has_select_for_update_of: + raise NotSupportedError( + "FOR UPDATE OF is not supported on this database backend." + ) + elif no_key and not features.has_select_for_no_key_update: + raise NotSupportedError( + "FOR NO KEY UPDATE is not supported on this " + "database backend." + ) + for_update_part = self.connection.ops.for_update_sql( + nowait=nowait, + skip_locked=skip_locked, + of=self.get_select_for_update_of_arguments(), + no_key=no_key, + ) + + if for_update_part and features.for_update_after_from: + result.append(for_update_part) + + if where: + result.append("WHERE %s" % where) + params.extend(w_params) + + grouping = [] + for g_sql, g_params in group_by: + grouping.append(g_sql) + params.extend(g_params) + if grouping: + if distinct_fields: + raise NotImplementedError( + "annotate() + distinct(fields) is not implemented." + ) + order_by = order_by or self.connection.ops.force_no_ordering() + result.append("GROUP BY %s" % ", ".join(grouping)) + if self._meta_ordering: + order_by = None + if having: + result.append("HAVING %s" % having) + params.extend(h_params) + + if self.query.explain_info: + result.insert( + 0, + self.connection.ops.explain_query_prefix( + self.query.explain_info.format, + **self.query.explain_info.options, + ), + ) + + if order_by: + ordering = [] + for _, (o_sql, o_params, _) in order_by: + ordering.append(o_sql) + params.extend(o_params) + order_by_sql = "ORDER BY %s" % ", ".join(ordering) + if combinator and features.requires_compound_order_by_subquery: + result = ["SELECT * FROM (", *result, ")", order_by_sql] + else: + result.append(order_by_sql) + + if with_limit_offset: + result.append( + self.connection.ops.limit_offset_sql( + self.query.low_mark, self.query.high_mark + ) + ) + + if for_update_part and not features.for_update_after_from: + result.append(for_update_part) + + if self.query.subquery and extra_select: + # If the query is used as a subquery, the extra selects would + # result in more columns than the left-hand side expression is + # expecting. This can happen when a subquery uses a combination + # of order_by() and distinct(), forcing the ordering expressions + # to be selected as well. Wrap the query in another subquery + # to exclude extraneous selects. + sub_selects = [] + sub_params = [] + for index, (select, _, alias) in enumerate(self.select, start=1): + if alias: + sub_selects.append( + "%s.%s" + % ( + self.connection.ops.quote_name("subquery"), + self.connection.ops.quote_name(alias), + ) + ) + else: + select_clone = select.relabeled_clone( + {select.alias: "subquery"} + ) + subselect, subparams = select_clone.as_sql( + self, self.connection + ) + sub_selects.append(subselect) + sub_params.extend(subparams) + return "SELECT %s FROM (%s) subquery" % ( + ", ".join(sub_selects), + " ".join(result), + ), tuple(sub_params + params) + + return " ".join(result), tuple(params) + finally: + # Finally do cleanup - get rid of the joins we created above. + self.query.reset_refcounts(refcounts_before) + + def get_default_columns( + self, select_mask, start_alias=None, opts=None, from_parent=None + ): + """ + Compute the default columns for selecting every field in the base + model. Will sometimes be called to pull in related models (e.g. via + select_related), in which case "opts" and "start_alias" will be given + to provide a starting point for the traversal. + + Return a list of strings, quoted appropriately for use in SQL + directly, as well as a set of aliases used in the select statement (if + 'as_pairs' is True, return a list of (alias, col_name) pairs instead + of strings as the first component and None as the second component). + """ + result = [] + if opts is None: + if (opts := self.query.get_meta()) is None: + return result + start_alias = start_alias or self.query.get_initial_alias() + # The 'seen_models' is used to optimize checking the needed parent + # alias for a given field. This also includes None -> start_alias to + # be used by local fields. + seen_models = {None: start_alias} + + for field in opts.concrete_fields: + model = field.model._meta.concrete_model + # A proxy model will have a different model and concrete_model. We + # will assign None if the field belongs to this model. + if model == opts.model: + model = None + if ( + from_parent + and model is not None + and issubclass( + from_parent._meta.concrete_model, model._meta.concrete_model + ) + ): + # Avoid loading data for already loaded parents. + # We end up here in the case select_related() resolution + # proceeds from parent model to child model. In that case the + # parent model data is already present in the SELECT clause, + # and we want to avoid reloading the same data again. + continue + if select_mask and field not in select_mask: + continue + alias = self.query.join_parent_model(opts, model, start_alias, seen_models) + column = field.get_col(alias) + result.append(column) + return result + + def get_distinct(self): + """ + Return a quoted list of fields to use in DISTINCT ON part of the query. + + This method can alter the tables in the query, and thus it must be + called before get_from_clause(). + """ + result = [] + params = [] + opts = self.query.get_meta() + + for name in self.query.distinct_fields: + parts = name.split(LOOKUP_SEP) + _, targets, alias, joins, path, _, transform_function = self._setup_joins( + parts, opts, None + ) + targets, alias, _ = self.query.trim_joins(targets, joins, path) + for target in targets: + if name in self.query.annotation_select: + result.append(self.connection.ops.quote_name(name)) + else: + r, p = self.compile(transform_function(target, alias)) + result.append(r) + params.append(p) + return result, params + + def find_ordering_name( + self, name, opts, alias=None, default_order="ASC", already_seen=None + ): + """ + Return the table alias (the name might be ambiguous, the alias will + not be) and column name for ordering by the given 'name' parameter. + The 'name' is of the form 'field1__field2__...__fieldN'. + """ + name, order = get_order_dir(name, default_order) + descending = order == "DESC" + pieces = name.split(LOOKUP_SEP) + ( + field, + targets, + alias, + joins, + path, + opts, + transform_function, + ) = self._setup_joins(pieces, opts, alias) + + # If we get to this point and the field is a relation to another model, + # append the default ordering for that model unless it is the pk + # shortcut or the attribute name of the field that is specified or + # there are transforms to process. + if ( + field.is_relation + and opts.ordering + and getattr(field, "attname", None) != pieces[-1] + and name != "pk" + and not getattr(transform_function, "has_transforms", False) + ): + # Firstly, avoid infinite loops. + already_seen = already_seen or set() + join_tuple = tuple( + getattr(self.query.alias_map[j], "join_cols", None) for j in joins + ) + if join_tuple in already_seen: + raise FieldError("Infinite loop caused by ordering.") + already_seen.add(join_tuple) + + results = [] + for item in opts.ordering: + if hasattr(item, "resolve_expression") and not isinstance( + item, OrderBy + ): + item = item.desc() if descending else item.asc() + if isinstance(item, OrderBy): + results.append( + (item.prefix_references(f"{name}{LOOKUP_SEP}"), False) + ) + continue + results.extend( + (expr.prefix_references(f"{name}{LOOKUP_SEP}"), is_ref) + for expr, is_ref in self.find_ordering_name( + item, opts, alias, order, already_seen + ) + ) + return results + targets, alias, _ = self.query.trim_joins(targets, joins, path) + return [ + (OrderBy(transform_function(t, alias), descending=descending), False) + for t in targets + ] + + def _setup_joins(self, pieces, opts, alias): + """ + Helper method for get_order_by() and get_distinct(). + + get_ordering() and get_distinct() must produce same target columns on + same input, as the prefixes of get_ordering() and get_distinct() must + match. Executing SQL where this is not true is an error. + """ + alias = alias or self.query.get_initial_alias() + field, targets, opts, joins, path, transform_function = self.query.setup_joins( + pieces, opts, alias + ) + alias = joins[-1] + return field, targets, alias, joins, path, opts, transform_function + + def get_from_clause(self): + """ + Return a list of strings that are joined together to go after the + "FROM" part of the query, as well as a list any extra parameters that + need to be included. Subclasses, can override this to create a + from-clause via a "select". + + This should only be called after any SQL construction methods that + might change the tables that are needed. This means the select columns, + ordering, and distinct must be done first. + """ + result = [] + params = [] + for alias in tuple(self.query.alias_map): + if not self.query.alias_refcount[alias]: + continue + try: + from_clause = self.query.alias_map[alias] + except KeyError: + # Extra tables can end up in self.tables, but not in the + # alias_map if they aren't in a join. That's OK. We skip them. + continue + clause_sql, clause_params = self.compile(from_clause) + result.append(clause_sql) + params.extend(clause_params) + for t in self.query.extra_tables: + alias, _ = self.query.table_alias(t) + # Only add the alias if it's not already present (the table_alias() + # call increments the refcount, so an alias refcount of one means + # this is the only reference). + if ( + alias not in self.query.alias_map + or self.query.alias_refcount[alias] == 1 + ): + result.append(", %s" % self.quote_name_unless_alias(alias)) + return result, params + + def get_related_selections( + self, + select, + select_mask, + opts=None, + root_alias=None, + cur_depth=1, + requested=None, + restricted=None, + ): + """ + Fill in the information needed for a select_related query. The current + depth is measured as the number of connections away from the root model + (for example, cur_depth=1 means we are looking at models with direct + connections to the root model). + """ + + def _get_field_choices(): + direct_choices = (f.name for f in opts.fields if f.is_relation) + reverse_choices = ( + f.field.related_query_name() + for f in opts.related_objects + if f.field.unique + ) + return chain( + direct_choices, reverse_choices, self.query._filtered_relations + ) + + related_klass_infos = [] + if not restricted and cur_depth > self.query.max_depth: + # We've recursed far enough; bail out. + return related_klass_infos + + if not opts: + opts = self.query.get_meta() + root_alias = self.query.get_initial_alias() + + # Setup for the case when only particular related fields should be + # included in the related selection. + fields_found = set() + if requested is None: + restricted = isinstance(self.query.select_related, dict) + if restricted: + requested = self.query.select_related + + def get_related_klass_infos(klass_info, related_klass_infos): + klass_info["related_klass_infos"] = related_klass_infos + + for f in opts.fields: + fields_found.add(f.name) + + if restricted: + next = requested.get(f.name, {}) + if not f.is_relation: + # If a non-related field is used like a relation, + # or if a single non-relational field is given. + if next or f.name in requested: + raise FieldError( + "Non-relational field given in select_related: '%s'. " + "Choices are: %s" + % ( + f.name, + ", ".join(_get_field_choices()) or "(none)", + ) + ) + else: + next = False + + if not select_related_descend(f, restricted, requested, select_mask): + continue + related_select_mask = select_mask.get(f) or {} + klass_info = { + "model": f.remote_field.model, + "field": f, + "reverse": False, + "local_setter": f.set_cached_value, + "remote_setter": f.remote_field.set_cached_value + if f.unique + else lambda x, y: None, + "from_parent": False, + } + related_klass_infos.append(klass_info) + select_fields = [] + _, _, _, joins, _, _ = self.query.setup_joins([f.name], opts, root_alias) + alias = joins[-1] + columns = self.get_default_columns( + related_select_mask, start_alias=alias, opts=f.remote_field.model._meta + ) + for col in columns: + select_fields.append(len(select)) + select.append((col, None)) + klass_info["select_fields"] = select_fields + next_klass_infos = self.get_related_selections( + select, + related_select_mask, + f.remote_field.model._meta, + alias, + cur_depth + 1, + next, + restricted, + ) + get_related_klass_infos(klass_info, next_klass_infos) + + if restricted: + related_fields = [ + (o.field, o.related_model) + for o in opts.related_objects + if o.field.unique and not o.many_to_many + ] + for related_field, model in related_fields: + related_select_mask = select_mask.get(related_field) or {} + if not select_related_descend( + related_field, + restricted, + requested, + related_select_mask, + reverse=True, + ): + continue + + related_field_name = related_field.related_query_name() + fields_found.add(related_field_name) + + join_info = self.query.setup_joins( + [related_field_name], opts, root_alias + ) + alias = join_info.joins[-1] + from_parent = issubclass(model, opts.model) and model is not opts.model + klass_info = { + "model": model, + "field": related_field, + "reverse": True, + "local_setter": related_field.remote_field.set_cached_value, + "remote_setter": related_field.set_cached_value, + "from_parent": from_parent, + } + related_klass_infos.append(klass_info) + select_fields = [] + columns = self.get_default_columns( + related_select_mask, + start_alias=alias, + opts=model._meta, + from_parent=opts.model, + ) + for col in columns: + select_fields.append(len(select)) + select.append((col, None)) + klass_info["select_fields"] = select_fields + next = requested.get(related_field.related_query_name(), {}) + next_klass_infos = self.get_related_selections( + select, + related_select_mask, + model._meta, + alias, + cur_depth + 1, + next, + restricted, + ) + get_related_klass_infos(klass_info, next_klass_infos) + + def local_setter(final_field, obj, from_obj): + # Set a reverse fk object when relation is non-empty. + if from_obj: + final_field.remote_field.set_cached_value(from_obj, obj) + + def local_setter_noop(obj, from_obj): + pass + + def remote_setter(name, obj, from_obj): + setattr(from_obj, name, obj) + + for name in list(requested): + # Filtered relations work only on the topmost level. + if cur_depth > 1: + break + if name in self.query._filtered_relations: + fields_found.add(name) + final_field, _, join_opts, joins, _, _ = self.query.setup_joins( + [name], opts, root_alias + ) + model = join_opts.model + alias = joins[-1] + from_parent = ( + issubclass(model, opts.model) and model is not opts.model + ) + klass_info = { + "model": model, + "field": final_field, + "reverse": True, + "local_setter": ( + partial(local_setter, final_field) + if len(joins) <= 2 + else local_setter_noop + ), + "remote_setter": partial(remote_setter, name), + "from_parent": from_parent, + } + related_klass_infos.append(klass_info) + select_fields = [] + field_select_mask = select_mask.get((name, final_field)) or {} + columns = self.get_default_columns( + field_select_mask, + start_alias=alias, + opts=model._meta, + from_parent=opts.model, + ) + for col in columns: + select_fields.append(len(select)) + select.append((col, None)) + klass_info["select_fields"] = select_fields + next_requested = requested.get(name, {}) + next_klass_infos = self.get_related_selections( + select, + field_select_mask, + opts=model._meta, + root_alias=alias, + cur_depth=cur_depth + 1, + requested=next_requested, + restricted=restricted, + ) + get_related_klass_infos(klass_info, next_klass_infos) + fields_not_found = set(requested).difference(fields_found) + if fields_not_found: + invalid_fields = ("'%s'" % s for s in fields_not_found) + raise FieldError( + "Invalid field name(s) given in select_related: %s. " + "Choices are: %s" + % ( + ", ".join(invalid_fields), + ", ".join(_get_field_choices()) or "(none)", + ) + ) + return related_klass_infos + + def get_select_for_update_of_arguments(self): + """ + Return a quoted list of arguments for the SELECT FOR UPDATE OF part of + the query. + """ + + def _get_parent_klass_info(klass_info): + concrete_model = klass_info["model"]._meta.concrete_model + for parent_model, parent_link in concrete_model._meta.parents.items(): + parent_list = parent_model._meta.get_parent_list() + yield { + "model": parent_model, + "field": parent_link, + "reverse": False, + "select_fields": [ + select_index + for select_index in klass_info["select_fields"] + # Selected columns from a model or its parents. + if ( + self.select[select_index][0].target.model == parent_model + or self.select[select_index][0].target.model in parent_list + ) + ], + } + + def _get_first_selected_col_from_model(klass_info): + """ + Find the first selected column from a model. If it doesn't exist, + don't lock a model. + + select_fields is filled recursively, so it also contains fields + from the parent models. + """ + concrete_model = klass_info["model"]._meta.concrete_model + for select_index in klass_info["select_fields"]: + if self.select[select_index][0].target.model == concrete_model: + return self.select[select_index][0] + + def _get_field_choices(): + """Yield all allowed field paths in breadth-first search order.""" + queue = collections.deque([(None, self.klass_info)]) + while queue: + parent_path, klass_info = queue.popleft() + if parent_path is None: + path = [] + yield "self" + else: + field = klass_info["field"] + if klass_info["reverse"]: + field = field.remote_field + path = parent_path + [field.name] + yield LOOKUP_SEP.join(path) + queue.extend( + (path, klass_info) + for klass_info in _get_parent_klass_info(klass_info) + ) + queue.extend( + (path, klass_info) + for klass_info in klass_info.get("related_klass_infos", []) + ) + + if not self.klass_info: + return [] + result = [] + invalid_names = [] + for name in self.query.select_for_update_of: + klass_info = self.klass_info + if name == "self": + col = _get_first_selected_col_from_model(klass_info) + else: + for part in name.split(LOOKUP_SEP): + klass_infos = ( + *klass_info.get("related_klass_infos", []), + *_get_parent_klass_info(klass_info), + ) + for related_klass_info in klass_infos: + field = related_klass_info["field"] + if related_klass_info["reverse"]: + field = field.remote_field + if field.name == part: + klass_info = related_klass_info + break + else: + klass_info = None + break + if klass_info is None: + invalid_names.append(name) + continue + col = _get_first_selected_col_from_model(klass_info) + if col is not None: + if self.connection.features.select_for_update_of_column: + result.append(self.compile(col)[0]) + else: + result.append(self.quote_name_unless_alias(col.alias)) + if invalid_names: + raise FieldError( + "Invalid field name(s) given in select_for_update(of=(...)): %s. " + "Only relational fields followed in the query are allowed. " + "Choices are: %s." + % ( + ", ".join(invalid_names), + ", ".join(_get_field_choices()), + ) + ) + return result + + def get_converters(self, expressions): + converters = {} + for i, expression in enumerate(expressions): + if expression: + backend_converters = self.connection.ops.get_db_converters(expression) + field_converters = expression.get_db_converters(self.connection) + if backend_converters or field_converters: + converters[i] = (backend_converters + field_converters, expression) + return converters + + def apply_converters(self, rows, converters): + connection = self.connection + converters = list(converters.items()) + for row in map(list, rows): + for pos, (convs, expression) in converters: + value = row[pos] + for converter in convs: + value = converter(value, expression, connection) + row[pos] = value + yield row + + def results_iter( + self, + results=None, + tuple_expected=False, + chunked_fetch=False, + chunk_size=GET_ITERATOR_CHUNK_SIZE, + ): + """Return an iterator over the results from executing this query.""" + if results is None: + results = self.execute_sql( + MULTI, chunked_fetch=chunked_fetch, chunk_size=chunk_size + ) + fields = [s[0] for s in self.select[0 : self.col_count]] + converters = self.get_converters(fields) + rows = chain.from_iterable(results) + if converters: + rows = self.apply_converters(rows, converters) + if tuple_expected: + rows = map(tuple, rows) + return rows + + def has_results(self): + """ + Backends (e.g. NoSQL) can override this in order to use optimized + versions of "query has any results." + """ + return bool(self.execute_sql(SINGLE)) + + def execute_sql( + self, result_type=MULTI, chunked_fetch=False, chunk_size=GET_ITERATOR_CHUNK_SIZE + ): + """ + Run the query against the database and return the result(s). The + return value is a single data item if result_type is SINGLE, or an + iterator over the results if the result_type is MULTI. + + result_type is either MULTI (use fetchmany() to retrieve all rows), + SINGLE (only retrieve a single row), or None. In this last case, the + cursor is returned if any query is executed, since it's used by + subclasses such as InsertQuery). It's possible, however, that no query + is needed, as the filters describe an empty set. In that case, None is + returned, to avoid any unnecessary database interaction. + """ + result_type = result_type or NO_RESULTS + try: + sql, params = self.as_sql() + if not sql: + raise EmptyResultSet + except EmptyResultSet: + if result_type == MULTI: + return iter([]) + else: + return + if chunked_fetch: + cursor = self.connection.chunked_cursor() + else: + cursor = self.connection.cursor() + try: + cursor.execute(sql, params) + except Exception: + # Might fail for server-side cursors (e.g. connection closed) + cursor.close() + raise + + if result_type == CURSOR: + # Give the caller the cursor to process and close. + return cursor + if result_type == SINGLE: + try: + val = cursor.fetchone() + if val: + return val[0 : self.col_count] + return val + finally: + # done with the cursor + cursor.close() + if result_type == NO_RESULTS: + cursor.close() + return + + result = cursor_iter( + cursor, + self.connection.features.empty_fetchmany_value, + self.col_count if self.has_extra_select else None, + chunk_size, + ) + if not chunked_fetch or not self.connection.features.can_use_chunked_reads: + # If we are using non-chunked reads, we return the same data + # structure as normally, but ensure it is all read into memory + # before going any further. Use chunked_fetch if requested, + # unless the database doesn't support it. + return list(result) + return result + + def as_subquery_condition(self, alias, columns, compiler): + qn = compiler.quote_name_unless_alias + qn2 = self.connection.ops.quote_name + + for index, select_col in enumerate(self.query.select): + lhs_sql, lhs_params = self.compile(select_col) + rhs = "%s.%s" % (qn(alias), qn2(columns[index])) + self.query.where.add(RawSQL("%s = %s" % (lhs_sql, rhs), lhs_params), AND) + + sql, params = self.as_sql() + return "EXISTS (%s)" % sql, params + + def explain_query(self): + result = list(self.execute_sql()) + # Some backends return 1 item tuples with strings, and others return + # tuples with integers and strings. Flatten them out into strings. + format_ = self.query.explain_info.format + output_formatter = json.dumps if format_ and format_.lower() == "json" else str + for row in result[0]: + if not isinstance(row, str): + yield " ".join(output_formatter(c) for c in row) + else: + yield row + + +class SQLInsertCompiler(SQLCompiler): + returning_fields = None + returning_params = () + + def field_as_sql(self, field, val): + """ + Take a field and a value intended to be saved on that field, and + return placeholder SQL and accompanying params. Check for raw values, + expressions, and fields with get_placeholder() defined in that order. + + When field is None, consider the value raw and use it as the + placeholder, with no corresponding parameters returned. + """ + if field is None: + # A field value of None means the value is raw. + sql, params = val, [] + elif hasattr(val, "as_sql"): + # This is an expression, let's compile it. + sql, params = self.compile(val) + elif hasattr(field, "get_placeholder"): + # Some fields (e.g. geo fields) need special munging before + # they can be inserted. + sql, params = field.get_placeholder(val, self, self.connection), [val] + else: + # Return the common case for the placeholder + sql, params = "%s", [val] + + # The following hook is only used by Oracle Spatial, which sometimes + # needs to yield 'NULL' and [] as its placeholder and params instead + # of '%s' and [None]. The 'NULL' placeholder is produced earlier by + # OracleOperations.get_geom_placeholder(). The following line removes + # the corresponding None parameter. See ticket #10888. + params = self.connection.ops.modify_insert_params(sql, params) + + return sql, params + + def prepare_value(self, field, value): + """ + Prepare a value to be used in a query by resolving it if it is an + expression and otherwise calling the field's get_db_prep_save(). + """ + if hasattr(value, "resolve_expression"): + value = value.resolve_expression( + self.query, allow_joins=False, for_save=True + ) + # Don't allow values containing Col expressions. They refer to + # existing columns on a row, but in the case of insert the row + # doesn't exist yet. + if value.contains_column_references: + raise ValueError( + 'Failed to insert expression "%s" on %s. F() expressions ' + "can only be used to update, not to insert." % (value, field) + ) + if value.contains_aggregate: + raise FieldError( + "Aggregate functions are not allowed in this query " + "(%s=%r)." % (field.name, value) + ) + if value.contains_over_clause: + raise FieldError( + "Window expressions are not allowed in this query (%s=%r)." + % (field.name, value) + ) + return field.get_db_prep_save(value, connection=self.connection) + + def pre_save_val(self, field, obj): + """ + Get the given field's value off the given obj. pre_save() is used for + things like auto_now on DateTimeField. Skip it if this is a raw query. + """ + if self.query.raw: + return getattr(obj, field.attname) + return field.pre_save(obj, add=True) + + def assemble_as_sql(self, fields, value_rows): + """ + Take a sequence of N fields and a sequence of M rows of values, and + generate placeholder SQL and parameters for each field and value. + Return a pair containing: + * a sequence of M rows of N SQL placeholder strings, and + * a sequence of M rows of corresponding parameter values. + + Each placeholder string may contain any number of '%s' interpolation + strings, and each parameter row will contain exactly as many params + as the total number of '%s's in the corresponding placeholder row. + """ + if not value_rows: + return [], [] + + # list of (sql, [params]) tuples for each object to be saved + # Shape: [n_objs][n_fields][2] + rows_of_fields_as_sql = ( + (self.field_as_sql(field, v) for field, v in zip(fields, row)) + for row in value_rows + ) + + # tuple like ([sqls], [[params]s]) for each object to be saved + # Shape: [n_objs][2][n_fields] + sql_and_param_pair_rows = (zip(*row) for row in rows_of_fields_as_sql) + + # Extract separate lists for placeholders and params. + # Each of these has shape [n_objs][n_fields] + placeholder_rows, param_rows = zip(*sql_and_param_pair_rows) + + # Params for each field are still lists, and need to be flattened. + param_rows = [[p for ps in row for p in ps] for row in param_rows] + + return placeholder_rows, param_rows + + def as_sql(self): + # We don't need quote_name_unless_alias() here, since these are all + # going to be column names (so we can avoid the extra overhead). + qn = self.connection.ops.quote_name + opts = self.query.get_meta() + insert_statement = self.connection.ops.insert_statement( + on_conflict=self.query.on_conflict, + ) + result = ["%s %s" % (insert_statement, qn(opts.db_table))] + fields = self.query.fields or [opts.pk] + result.append("(%s)" % ", ".join(qn(f.column) for f in fields)) + + if self.query.fields: + value_rows = [ + [ + self.prepare_value(field, self.pre_save_val(field, obj)) + for field in fields + ] + for obj in self.query.objs + ] + else: + # An empty object. + value_rows = [ + [self.connection.ops.pk_default_value()] for _ in self.query.objs + ] + fields = [None] + + # Currently the backends just accept values when generating bulk + # queries and generate their own placeholders. Doing that isn't + # necessary and it should be possible to use placeholders and + # expressions in bulk inserts too. + can_bulk = ( + not self.returning_fields and self.connection.features.has_bulk_insert + ) + + placeholder_rows, param_rows = self.assemble_as_sql(fields, value_rows) + + on_conflict_suffix_sql = self.connection.ops.on_conflict_suffix_sql( + fields, + self.query.on_conflict, + (f.column for f in self.query.update_fields), + (f.column for f in self.query.unique_fields), + ) + if ( + self.returning_fields + and self.connection.features.can_return_columns_from_insert + ): + if self.connection.features.can_return_rows_from_bulk_insert: + result.append( + self.connection.ops.bulk_insert_sql(fields, placeholder_rows) + ) + params = param_rows + else: + result.append("VALUES (%s)" % ", ".join(placeholder_rows[0])) + params = [param_rows[0]] + if on_conflict_suffix_sql: + result.append(on_conflict_suffix_sql) + # Skip empty r_sql to allow subclasses to customize behavior for + # 3rd party backends. Refs #19096. + r_sql, self.returning_params = self.connection.ops.return_insert_columns( + self.returning_fields + ) + if r_sql: + result.append(r_sql) + params += [self.returning_params] + return [(" ".join(result), tuple(chain.from_iterable(params)))] + + if can_bulk: + result.append(self.connection.ops.bulk_insert_sql(fields, placeholder_rows)) + if on_conflict_suffix_sql: + result.append(on_conflict_suffix_sql) + return [(" ".join(result), tuple(p for ps in param_rows for p in ps))] + else: + if on_conflict_suffix_sql: + result.append(on_conflict_suffix_sql) + return [ + (" ".join(result + ["VALUES (%s)" % ", ".join(p)]), vals) + for p, vals in zip(placeholder_rows, param_rows) + ] + + def execute_sql(self, returning_fields=None): + assert not ( + returning_fields + and len(self.query.objs) != 1 + and not self.connection.features.can_return_rows_from_bulk_insert + ) + opts = self.query.get_meta() + self.returning_fields = returning_fields + with self.connection.cursor() as cursor: + for sql, params in self.as_sql(): + cursor.execute(sql, params) + if not self.returning_fields: + return [] + if ( + self.connection.features.can_return_rows_from_bulk_insert + and len(self.query.objs) > 1 + ): + rows = self.connection.ops.fetch_returned_insert_rows(cursor) + elif self.connection.features.can_return_columns_from_insert: + assert len(self.query.objs) == 1 + rows = [ + self.connection.ops.fetch_returned_insert_columns( + cursor, + self.returning_params, + ) + ] + else: + rows = [ + ( + self.connection.ops.last_insert_id( + cursor, + opts.db_table, + opts.pk.column, + ), + ) + ] + cols = [field.get_col(opts.db_table) for field in self.returning_fields] + converters = self.get_converters(cols) + if converters: + rows = list(self.apply_converters(rows, converters)) + return rows + + +class SQLDeleteCompiler(SQLCompiler): + @cached_property + def single_alias(self): + # Ensure base table is in aliases. + self.query.get_initial_alias() + return sum(self.query.alias_refcount[t] > 0 for t in self.query.alias_map) == 1 + + @classmethod + def _expr_refs_base_model(cls, expr, base_model): + if isinstance(expr, Query): + return expr.model == base_model + if not hasattr(expr, "get_source_expressions"): + return False + return any( + cls._expr_refs_base_model(source_expr, base_model) + for source_expr in expr.get_source_expressions() + ) + + @cached_property + def contains_self_reference_subquery(self): + return any( + self._expr_refs_base_model(expr, self.query.model) + for expr in chain( + self.query.annotations.values(), self.query.where.children + ) + ) + + def _as_sql(self, query): + delete = "DELETE FROM %s" % self.quote_name_unless_alias(query.base_table) + try: + where, params = self.compile(query.where) + except FullResultSet: + return delete, () + return f"{delete} WHERE {where}", tuple(params) + + def as_sql(self): + """ + Create the SQL for this query. Return the SQL string and list of + parameters. + """ + if self.single_alias and ( + self.connection.features.delete_can_self_reference_subquery + or not self.contains_self_reference_subquery + ): + return self._as_sql(self.query) + innerq = self.query.clone() + innerq.__class__ = Query + innerq.clear_select_clause() + pk = self.query.model._meta.pk + innerq.select = [pk.get_col(self.query.get_initial_alias())] + outerq = Query(self.query.model) + if not self.connection.features.update_can_self_select: + # Force the materialization of the inner query to allow reference + # to the target table on MySQL. + sql, params = innerq.get_compiler(connection=self.connection).as_sql() + innerq = RawSQL("SELECT * FROM (%s) subquery" % sql, params) + outerq.add_filter("pk__in", innerq) + return self._as_sql(outerq) + + +class SQLUpdateCompiler(SQLCompiler): + def as_sql(self): + """ + Create the SQL for this query. Return the SQL string and list of + parameters. + """ + self.pre_sql_setup() + if not self.query.values: + return "", () + qn = self.quote_name_unless_alias + values, update_params = [], [] + for field, model, val in self.query.values: + if hasattr(val, "resolve_expression"): + val = val.resolve_expression( + self.query, allow_joins=False, for_save=True + ) + if val.contains_aggregate: + raise FieldError( + "Aggregate functions are not allowed in this query " + "(%s=%r)." % (field.name, val) + ) + if val.contains_over_clause: + raise FieldError( + "Window expressions are not allowed in this query " + "(%s=%r)." % (field.name, val) + ) + elif hasattr(val, "prepare_database_save"): + if field.remote_field: + val = val.prepare_database_save(field) + else: + raise TypeError( + "Tried to update field %s with a model instance, %r. " + "Use a value compatible with %s." + % (field, val, field.__class__.__name__) + ) + val = field.get_db_prep_save(val, connection=self.connection) + + # Getting the placeholder for the field. + if hasattr(field, "get_placeholder"): + placeholder = field.get_placeholder(val, self, self.connection) + else: + placeholder = "%s" + name = field.column + if hasattr(val, "as_sql"): + sql, params = self.compile(val) + values.append("%s = %s" % (qn(name), placeholder % sql)) + update_params.extend(params) + elif val is not None: + values.append("%s = %s" % (qn(name), placeholder)) + update_params.append(val) + else: + values.append("%s = NULL" % qn(name)) + table = self.query.base_table + result = [ + "UPDATE %s SET" % qn(table), + ", ".join(values), + ] + try: + where, params = self.compile(self.query.where) + except FullResultSet: + params = [] + else: + result.append("WHERE %s" % where) + return " ".join(result), tuple(update_params + params) + + def execute_sql(self, result_type): + """ + Execute the specified update. Return the number of rows affected by + the primary update query. The "primary update query" is the first + non-empty query that is executed. Row counts for any subsequent, + related queries are not available. + """ + cursor = super().execute_sql(result_type) + try: + rows = cursor.rowcount if cursor else 0 + is_empty = cursor is None + finally: + if cursor: + cursor.close() + for query in self.query.get_related_updates(): + aux_rows = query.get_compiler(self.using).execute_sql(result_type) + if is_empty and aux_rows: + rows = aux_rows + is_empty = False + return rows + + def pre_sql_setup(self): + """ + If the update depends on results from other tables, munge the "where" + conditions to match the format required for (portable) SQL updates. + + If multiple updates are required, pull out the id values to update at + this point so that they don't change as a result of the progressive + updates. + """ + refcounts_before = self.query.alias_refcount.copy() + # Ensure base table is in the query + self.query.get_initial_alias() + count = self.query.count_active_tables() + if not self.query.related_updates and count == 1: + return + query = self.query.chain(klass=Query) + query.select_related = False + query.clear_ordering(force=True) + query.extra = {} + query.select = [] + meta = query.get_meta() + fields = [meta.pk.name] + related_ids_index = [] + for related in self.query.related_updates: + if all( + path.join_field.primary_key for path in meta.get_path_to_parent(related) + ): + # If a primary key chain exists to the targeted related update, + # then the meta.pk value can be used for it. + related_ids_index.append((related, 0)) + else: + # This branch will only be reached when updating a field of an + # ancestor that is not part of the primary key chain of a MTI + # tree. + related_ids_index.append((related, len(fields))) + fields.append(related._meta.pk.name) + query.add_fields(fields) + super().pre_sql_setup() + + must_pre_select = ( + count > 1 and not self.connection.features.update_can_self_select + ) + + # Now we adjust the current query: reset the where clause and get rid + # of all the tables we don't need (since they're in the sub-select). + self.query.clear_where() + if self.query.related_updates or must_pre_select: + # Either we're using the idents in multiple update queries (so + # don't want them to change), or the db backend doesn't support + # selecting from the updating table (e.g. MySQL). + idents = [] + related_ids = collections.defaultdict(list) + for rows in query.get_compiler(self.using).execute_sql(MULTI): + idents.extend(r[0] for r in rows) + for parent, index in related_ids_index: + related_ids[parent].extend(r[index] for r in rows) + self.query.add_filter("pk__in", idents) + self.query.related_ids = related_ids + else: + # The fast path. Filters and updates in one query. + self.query.add_filter("pk__in", query) + self.query.reset_refcounts(refcounts_before) + + +class SQLAggregateCompiler(SQLCompiler): + def as_sql(self): + """ + Create the SQL for this query. Return the SQL string and list of + parameters. + """ + sql, params = [], [] + for annotation in self.query.annotation_select.values(): + ann_sql, ann_params = self.compile(annotation) + ann_sql, ann_params = annotation.select_format(self, ann_sql, ann_params) + sql.append(ann_sql) + params.extend(ann_params) + self.col_count = len(self.query.annotation_select) + sql = ", ".join(sql) + params = tuple(params) + + inner_query_sql, inner_query_params = self.query.inner_query.get_compiler( + self.using, + elide_empty=self.elide_empty, + ).as_sql(with_col_aliases=True) + sql = "SELECT %s FROM (%s) subquery" % (sql, inner_query_sql) + params += inner_query_params + return sql, params + + +def cursor_iter(cursor, sentinel, col_count, itersize): + """ + Yield blocks of rows from a cursor and ensure the cursor is closed when + done. + """ + try: + for rows in iter((lambda: cursor.fetchmany(itersize)), sentinel): + yield rows if col_count is None else [r[:col_count] for r in rows] + finally: + cursor.close() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/sql/constants.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/sql/constants.py new file mode 100644 index 0000000..fdfb2ea --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/sql/constants.py @@ -0,0 +1,24 @@ +""" +Constants specific to the SQL storage portion of the ORM. +""" + +# Size of each "chunk" for get_iterator calls. +# Larger values are slightly faster at the expense of more storage space. +GET_ITERATOR_CHUNK_SIZE = 100 + +# Namedtuples for sql.* internal use. + +# How many results to expect from a cursor.execute call +MULTI = "multi" +SINGLE = "single" +CURSOR = "cursor" +NO_RESULTS = "no results" + +ORDER_DIR = { + "ASC": ("ASC", "DESC"), + "DESC": ("DESC", "ASC"), +} + +# SQL join types. +INNER = "INNER JOIN" +LOUTER = "LEFT OUTER JOIN" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/sql/datastructures.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/sql/datastructures.py new file mode 100644 index 0000000..5eaa8c2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/sql/datastructures.py @@ -0,0 +1,237 @@ +""" +Useful auxiliary data structures for query construction. Not useful outside +the SQL domain. +""" +import warnings + +from django.core.exceptions import FullResultSet +from django.db.models.sql.constants import INNER, LOUTER +from django.utils.deprecation import RemovedInDjango60Warning + + +class MultiJoin(Exception): + """ + Used by join construction code to indicate the point at which a + multi-valued join was attempted (if the caller wants to treat that + exceptionally). + """ + + def __init__(self, names_pos, path_with_names): + self.level = names_pos + # The path travelled, this includes the path to the multijoin. + self.names_with_path = path_with_names + + +class Empty: + pass + + +class Join: + """ + Used by sql.Query and sql.SQLCompiler to generate JOIN clauses into the + FROM entry. For example, the SQL generated could be + LEFT OUTER JOIN "sometable" T1 + ON ("othertable"."sometable_id" = "sometable"."id") + + This class is primarily used in Query.alias_map. All entries in alias_map + must be Join compatible by providing the following attributes and methods: + - table_name (string) + - table_alias (possible alias for the table, can be None) + - join_type (can be None for those entries that aren't joined from + anything) + - parent_alias (which table is this join's parent, can be None similarly + to join_type) + - as_sql() + - relabeled_clone() + """ + + def __init__( + self, + table_name, + parent_alias, + table_alias, + join_type, + join_field, + nullable, + filtered_relation=None, + ): + # Join table + self.table_name = table_name + self.parent_alias = parent_alias + # Note: table_alias is not necessarily known at instantiation time. + self.table_alias = table_alias + # LOUTER or INNER + self.join_type = join_type + # A list of 2-tuples to use in the ON clause of the JOIN. + # Each 2-tuple will create one join condition in the ON clause. + if hasattr(join_field, "get_joining_fields"): + self.join_fields = join_field.get_joining_fields() + self.join_cols = tuple( + (lhs_field.column, rhs_field.column) + for lhs_field, rhs_field in self.join_fields + ) + else: + warnings.warn( + "The usage of get_joining_columns() in Join is deprecated. Implement " + "get_joining_fields() instead.", + RemovedInDjango60Warning, + ) + self.join_fields = None + self.join_cols = join_field.get_joining_columns() + # Along which field (or ForeignObjectRel in the reverse join case) + self.join_field = join_field + # Is this join nullabled? + self.nullable = nullable + self.filtered_relation = filtered_relation + + def as_sql(self, compiler, connection): + """ + Generate the full + LEFT OUTER JOIN sometable ON sometable.somecol = othertable.othercol, params + clause for this join. + """ + join_conditions = [] + params = [] + qn = compiler.quote_name_unless_alias + qn2 = connection.ops.quote_name + # Add a join condition for each pair of joining columns. + # RemovedInDjango60Warning: when the depraction ends, replace with: + # for lhs, rhs in self.join_field: + join_fields = self.join_fields or self.join_cols + for lhs, rhs in join_fields: + if isinstance(lhs, str): + # RemovedInDjango60Warning: when the depraction ends, remove + # the branch for strings. + lhs_full_name = "%s.%s" % (qn(self.parent_alias), qn2(lhs)) + rhs_full_name = "%s.%s" % (qn(self.table_alias), qn2(rhs)) + else: + lhs, rhs = connection.ops.prepare_join_on_clause( + self.parent_alias, lhs, self.table_alias, rhs + ) + lhs_sql, lhs_params = compiler.compile(lhs) + lhs_full_name = lhs_sql % lhs_params + rhs_sql, rhs_params = compiler.compile(rhs) + rhs_full_name = rhs_sql % rhs_params + join_conditions.append(f"{lhs_full_name} = {rhs_full_name}") + + # Add a single condition inside parentheses for whatever + # get_extra_restriction() returns. + extra_cond = self.join_field.get_extra_restriction( + self.table_alias, self.parent_alias + ) + if extra_cond: + extra_sql, extra_params = compiler.compile(extra_cond) + join_conditions.append("(%s)" % extra_sql) + params.extend(extra_params) + if self.filtered_relation: + try: + extra_sql, extra_params = compiler.compile(self.filtered_relation) + except FullResultSet: + pass + else: + join_conditions.append("(%s)" % extra_sql) + params.extend(extra_params) + if not join_conditions: + # This might be a rel on the other end of an actual declared field. + declared_field = getattr(self.join_field, "field", self.join_field) + raise ValueError( + "Join generated an empty ON clause. %s did not yield either " + "joining columns or extra restrictions." % declared_field.__class__ + ) + on_clause_sql = " AND ".join(join_conditions) + alias_str = ( + "" if self.table_alias == self.table_name else (" %s" % self.table_alias) + ) + sql = "%s %s%s ON (%s)" % ( + self.join_type, + qn(self.table_name), + alias_str, + on_clause_sql, + ) + return sql, params + + def relabeled_clone(self, change_map): + new_parent_alias = change_map.get(self.parent_alias, self.parent_alias) + new_table_alias = change_map.get(self.table_alias, self.table_alias) + if self.filtered_relation is not None: + filtered_relation = self.filtered_relation.relabeled_clone(change_map) + else: + filtered_relation = None + return self.__class__( + self.table_name, + new_parent_alias, + new_table_alias, + self.join_type, + self.join_field, + self.nullable, + filtered_relation=filtered_relation, + ) + + @property + def identity(self): + return ( + self.__class__, + self.table_name, + self.parent_alias, + self.join_field, + self.filtered_relation, + ) + + def __eq__(self, other): + if not isinstance(other, Join): + return NotImplemented + return self.identity == other.identity + + def __hash__(self): + return hash(self.identity) + + def demote(self): + new = self.relabeled_clone({}) + new.join_type = INNER + return new + + def promote(self): + new = self.relabeled_clone({}) + new.join_type = LOUTER + return new + + +class BaseTable: + """ + The BaseTable class is used for base table references in FROM clause. For + example, the SQL "foo" in + SELECT * FROM "foo" WHERE somecond + could be generated by this class. + """ + + join_type = None + parent_alias = None + filtered_relation = None + + def __init__(self, table_name, alias): + self.table_name = table_name + self.table_alias = alias + + def as_sql(self, compiler, connection): + alias_str = ( + "" if self.table_alias == self.table_name else (" %s" % self.table_alias) + ) + base_sql = compiler.quote_name_unless_alias(self.table_name) + return base_sql + alias_str, [] + + def relabeled_clone(self, change_map): + return self.__class__( + self.table_name, change_map.get(self.table_alias, self.table_alias) + ) + + @property + def identity(self): + return self.__class__, self.table_name, self.table_alias + + def __eq__(self, other): + if not isinstance(other, BaseTable): + return NotImplemented + return self.identity == other.identity + + def __hash__(self): + return hash(self.identity) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/sql/query.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/sql/query.py new file mode 100644 index 0000000..f04b1c4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/sql/query.py @@ -0,0 +1,2724 @@ +""" +Create SQL statements for QuerySets. + +The code in here encapsulates all of the SQL construction so that QuerySets +themselves do not have to (and could be backed by things other than SQL +databases). The abstraction barrier only works one way: this module has to know +all about the internals of models in order to get the information it needs. +""" +import copy +import difflib +import functools +import sys +from collections import Counter, namedtuple +from collections.abc import Iterator, Mapping +from itertools import chain, count, product +from string import ascii_uppercase + +from django.core.exceptions import FieldDoesNotExist, FieldError +from django.db import DEFAULT_DB_ALIAS, NotSupportedError, connections +from django.db.models.aggregates import Count +from django.db.models.constants import LOOKUP_SEP +from django.db.models.expressions import ( + BaseExpression, + Col, + Exists, + F, + OuterRef, + Ref, + ResolvedOuterRef, + Value, +) +from django.db.models.fields import Field +from django.db.models.fields.related_lookups import MultiColSource +from django.db.models.lookups import Lookup +from django.db.models.query_utils import ( + Q, + check_rel_lookup_compatibility, + refs_expression, +) +from django.db.models.sql.constants import INNER, LOUTER, ORDER_DIR, SINGLE +from django.db.models.sql.datastructures import BaseTable, Empty, Join, MultiJoin +from django.db.models.sql.where import AND, OR, ExtraWhere, NothingNode, WhereNode +from django.utils.functional import cached_property +from django.utils.regex_helper import _lazy_re_compile +from django.utils.tree import Node + +__all__ = ["Query", "RawQuery"] + +# Quotation marks ('"`[]), whitespace characters, semicolons, or inline +# SQL comments are forbidden in column aliases. +FORBIDDEN_ALIAS_PATTERN = _lazy_re_compile(r"['`\"\]\[;\s]|--|/\*|\*/") + +# Inspired from +# https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS +EXPLAIN_OPTIONS_PATTERN = _lazy_re_compile(r"[\w-]+") + + +def get_field_names_from_opts(opts): + if opts is None: + return set() + return set( + chain.from_iterable( + (f.name, f.attname) if f.concrete else (f.name,) for f in opts.get_fields() + ) + ) + + +def get_paths_from_expression(expr): + if isinstance(expr, F): + yield expr.name + elif hasattr(expr, "flatten"): + for child in expr.flatten(): + if isinstance(child, F): + yield child.name + elif isinstance(child, Q): + yield from get_children_from_q(child) + + +def get_children_from_q(q): + for child in q.children: + if isinstance(child, Node): + yield from get_children_from_q(child) + elif isinstance(child, tuple): + lhs, rhs = child + yield lhs + if hasattr(rhs, "resolve_expression"): + yield from get_paths_from_expression(rhs) + elif hasattr(child, "resolve_expression"): + yield from get_paths_from_expression(child) + + +def get_child_with_renamed_prefix(prefix, replacement, child): + if isinstance(child, Node): + return rename_prefix_from_q(prefix, replacement, child) + if isinstance(child, tuple): + lhs, rhs = child + lhs = lhs.replace(prefix, replacement, 1) + if not isinstance(rhs, F) and hasattr(rhs, "resolve_expression"): + rhs = get_child_with_renamed_prefix(prefix, replacement, rhs) + return lhs, rhs + + if isinstance(child, F): + child = child.copy() + child.name = child.name.replace(prefix, replacement, 1) + elif hasattr(child, "resolve_expression"): + child = child.copy() + child.set_source_expressions( + [ + get_child_with_renamed_prefix(prefix, replacement, grand_child) + for grand_child in child.get_source_expressions() + ] + ) + return child + + +def rename_prefix_from_q(prefix, replacement, q): + return Q.create( + [get_child_with_renamed_prefix(prefix, replacement, c) for c in q.children], + q.connector, + q.negated, + ) + + +JoinInfo = namedtuple( + "JoinInfo", + ("final_field", "targets", "opts", "joins", "path", "transform_function"), +) + + +class RawQuery: + """A single raw SQL query.""" + + def __init__(self, sql, using, params=()): + self.params = params + self.sql = sql + self.using = using + self.cursor = None + + # Mirror some properties of a normal query so that + # the compiler can be used to process results. + self.low_mark, self.high_mark = 0, None # Used for offset/limit + self.extra_select = {} + self.annotation_select = {} + + def chain(self, using): + return self.clone(using) + + def clone(self, using): + return RawQuery(self.sql, using, params=self.params) + + def get_columns(self): + if self.cursor is None: + self._execute_query() + converter = connections[self.using].introspection.identifier_converter + return [converter(column_meta[0]) for column_meta in self.cursor.description] + + def __iter__(self): + # Always execute a new query for a new iterator. + # This could be optimized with a cache at the expense of RAM. + self._execute_query() + if not connections[self.using].features.can_use_chunked_reads: + # If the database can't use chunked reads we need to make sure we + # evaluate the entire query up front. + result = list(self.cursor) + else: + result = self.cursor + return iter(result) + + def __repr__(self): + return "<%s: %s>" % (self.__class__.__name__, self) + + @property + def params_type(self): + if self.params is None: + return None + return dict if isinstance(self.params, Mapping) else tuple + + def __str__(self): + if self.params_type is None: + return self.sql + return self.sql % self.params_type(self.params) + + def _execute_query(self): + connection = connections[self.using] + + # Adapt parameters to the database, as much as possible considering + # that the target type isn't known. See #17755. + params_type = self.params_type + adapter = connection.ops.adapt_unknown_value + if params_type is tuple: + params = tuple(adapter(val) for val in self.params) + elif params_type is dict: + params = {key: adapter(val) for key, val in self.params.items()} + elif params_type is None: + params = None + else: + raise RuntimeError("Unexpected params type: %s" % params_type) + + self.cursor = connection.cursor() + self.cursor.execute(self.sql, params) + + +ExplainInfo = namedtuple("ExplainInfo", ("format", "options")) + + +class Query(BaseExpression): + """A single SQL query.""" + + alias_prefix = "T" + empty_result_set_value = None + subq_aliases = frozenset([alias_prefix]) + + compiler = "SQLCompiler" + + base_table_class = BaseTable + join_class = Join + + default_cols = True + default_ordering = True + standard_ordering = True + + filter_is_sticky = False + subquery = False + + # SQL-related attributes. + # Select and related select clauses are expressions to use in the SELECT + # clause of the query. The select is used for cases where we want to set up + # the select clause to contain other than default fields (values(), + # subqueries...). Note that annotations go to annotations dictionary. + select = () + # The group_by attribute can have one of the following forms: + # - None: no group by at all in the query + # - A tuple of expressions: group by (at least) those expressions. + # String refs are also allowed for now. + # - True: group by all select fields of the model + # See compiler.get_group_by() for details. + group_by = None + order_by = () + low_mark = 0 # Used for offset/limit. + high_mark = None # Used for offset/limit. + distinct = False + distinct_fields = () + select_for_update = False + select_for_update_nowait = False + select_for_update_skip_locked = False + select_for_update_of = () + select_for_no_key_update = False + select_related = False + has_select_fields = False + # Arbitrary limit for select_related to prevents infinite recursion. + max_depth = 5 + # Holds the selects defined by a call to values() or values_list() + # excluding annotation_select and extra_select. + values_select = () + + # SQL annotation-related attributes. + annotation_select_mask = None + _annotation_select_cache = None + + # Set combination attributes. + combinator = None + combinator_all = False + combined_queries = () + + # These are for extensions. The contents are more or less appended verbatim + # to the appropriate clause. + extra_select_mask = None + _extra_select_cache = None + + extra_tables = () + extra_order_by = () + + # A tuple that is a set of model field names and either True, if these are + # the fields to defer, or False if these are the only fields to load. + deferred_loading = (frozenset(), True) + + explain_info = None + + def __init__(self, model, alias_cols=True): + self.model = model + self.alias_refcount = {} + # alias_map is the most important data structure regarding joins. + # It's used for recording which joins exist in the query and what + # types they are. The key is the alias of the joined table (possibly + # the table name) and the value is a Join-like object (see + # sql.datastructures.Join for more information). + self.alias_map = {} + # Whether to provide alias to columns during reference resolving. + self.alias_cols = alias_cols + # Sometimes the query contains references to aliases in outer queries (as + # a result of split_exclude). Correct alias quoting needs to know these + # aliases too. + # Map external tables to whether they are aliased. + self.external_aliases = {} + self.table_map = {} # Maps table names to list of aliases. + self.used_aliases = set() + + self.where = WhereNode() + # Maps alias -> Annotation Expression. + self.annotations = {} + # These are for extensions. The contents are more or less appended + # verbatim to the appropriate clause. + self.extra = {} # Maps col_alias -> (col_sql, params). + + self._filtered_relations = {} + + @property + def output_field(self): + if len(self.select) == 1: + select = self.select[0] + return getattr(select, "target", None) or select.field + elif len(self.annotation_select) == 1: + return next(iter(self.annotation_select.values())).output_field + + @cached_property + def base_table(self): + for alias in self.alias_map: + return alias + + def __str__(self): + """ + Return the query as a string of SQL with the parameter values + substituted in (use sql_with_params() to see the unsubstituted string). + + Parameter values won't necessarily be quoted correctly, since that is + done by the database interface at execution time. + """ + sql, params = self.sql_with_params() + return sql % params + + def sql_with_params(self): + """ + Return the query as an SQL string and the parameters that will be + substituted into the query. + """ + return self.get_compiler(DEFAULT_DB_ALIAS).as_sql() + + def __deepcopy__(self, memo): + """Limit the amount of work when a Query is deepcopied.""" + result = self.clone() + memo[id(self)] = result + return result + + def get_compiler(self, using=None, connection=None, elide_empty=True): + if using is None and connection is None: + raise ValueError("Need either using or connection") + if using: + connection = connections[using] + return connection.ops.compiler(self.compiler)( + self, connection, using, elide_empty + ) + + def get_meta(self): + """ + Return the Options instance (the model._meta) from which to start + processing. Normally, this is self.model._meta, but it can be changed + by subclasses. + """ + if self.model: + return self.model._meta + + def clone(self): + """ + Return a copy of the current Query. A lightweight alternative to + deepcopy(). + """ + obj = Empty() + obj.__class__ = self.__class__ + # Copy references to everything. + obj.__dict__ = self.__dict__.copy() + # Clone attributes that can't use shallow copy. + obj.alias_refcount = self.alias_refcount.copy() + obj.alias_map = self.alias_map.copy() + obj.external_aliases = self.external_aliases.copy() + obj.table_map = self.table_map.copy() + obj.where = self.where.clone() + obj.annotations = self.annotations.copy() + if self.annotation_select_mask is not None: + obj.annotation_select_mask = self.annotation_select_mask.copy() + if self.combined_queries: + obj.combined_queries = tuple( + [query.clone() for query in self.combined_queries] + ) + # _annotation_select_cache cannot be copied, as doing so breaks the + # (necessary) state in which both annotations and + # _annotation_select_cache point to the same underlying objects. + # It will get re-populated in the cloned queryset the next time it's + # used. + obj._annotation_select_cache = None + obj.extra = self.extra.copy() + if self.extra_select_mask is not None: + obj.extra_select_mask = self.extra_select_mask.copy() + if self._extra_select_cache is not None: + obj._extra_select_cache = self._extra_select_cache.copy() + if self.select_related is not False: + # Use deepcopy because select_related stores fields in nested + # dicts. + obj.select_related = copy.deepcopy(obj.select_related) + if "subq_aliases" in self.__dict__: + obj.subq_aliases = self.subq_aliases.copy() + obj.used_aliases = self.used_aliases.copy() + obj._filtered_relations = self._filtered_relations.copy() + # Clear the cached_property, if it exists. + obj.__dict__.pop("base_table", None) + return obj + + def chain(self, klass=None): + """ + Return a copy of the current Query that's ready for another operation. + The klass argument changes the type of the Query, e.g. UpdateQuery. + """ + obj = self.clone() + if klass and obj.__class__ != klass: + obj.__class__ = klass + if not obj.filter_is_sticky: + obj.used_aliases = set() + obj.filter_is_sticky = False + if hasattr(obj, "_setup_query"): + obj._setup_query() + return obj + + def relabeled_clone(self, change_map): + clone = self.clone() + clone.change_aliases(change_map) + return clone + + def _get_col(self, target, field, alias): + if not self.alias_cols: + alias = None + return target.get_col(alias, field) + + def get_aggregation(self, using, aggregate_exprs): + """ + Return the dictionary with the values of the existing aggregations. + """ + if not aggregate_exprs: + return {} + # Store annotation mask prior to temporarily adding aggregations for + # resolving purpose to facilitate their subsequent removal. + refs_subquery = False + refs_window = False + replacements = {} + annotation_select_mask = self.annotation_select_mask + for alias, aggregate_expr in aggregate_exprs.items(): + self.check_alias(alias) + aggregate = aggregate_expr.resolve_expression( + self, allow_joins=True, reuse=None, summarize=True + ) + if not aggregate.contains_aggregate: + raise TypeError("%s is not an aggregate expression" % alias) + # Temporarily add aggregate to annotations to allow remaining + # members of `aggregates` to resolve against each others. + self.append_annotation_mask([alias]) + refs_subquery |= any( + getattr(self.annotations[ref], "contains_subquery", False) + for ref in aggregate.get_refs() + ) + refs_window |= any( + getattr(self.annotations[ref], "contains_over_clause", True) + for ref in aggregate.get_refs() + ) + aggregate = aggregate.replace_expressions(replacements) + self.annotations[alias] = aggregate + replacements[Ref(alias, aggregate)] = aggregate + # Stash resolved aggregates now that they have been allowed to resolve + # against each other. + aggregates = {alias: self.annotations.pop(alias) for alias in aggregate_exprs} + self.set_annotation_mask(annotation_select_mask) + # Existing usage of aggregation can be determined by the presence of + # selected aggregates but also by filters against aliased aggregates. + _, having, qualify = self.where.split_having_qualify() + has_existing_aggregation = ( + any( + getattr(annotation, "contains_aggregate", True) + for annotation in self.annotations.values() + ) + or having + ) + # Decide if we need to use a subquery. + # + # Existing aggregations would cause incorrect results as + # get_aggregation() must produce just one result and thus must not use + # GROUP BY. + # + # If the query has limit or distinct, or uses set operations, then + # those operations must be done in a subquery so that the query + # aggregates on the limit and/or distinct results instead of applying + # the distinct and limit after the aggregation. + if ( + isinstance(self.group_by, tuple) + or self.is_sliced + or has_existing_aggregation + or refs_subquery + or refs_window + or qualify + or self.distinct + or self.combinator + ): + from django.db.models.sql.subqueries import AggregateQuery + + inner_query = self.clone() + inner_query.subquery = True + outer_query = AggregateQuery(self.model, inner_query) + inner_query.select_for_update = False + inner_query.select_related = False + inner_query.set_annotation_mask(self.annotation_select) + # Queries with distinct_fields need ordering and when a limit is + # applied we must take the slice from the ordered query. Otherwise + # no need for ordering. + inner_query.clear_ordering(force=False) + if not inner_query.distinct: + # If the inner query uses default select and it has some + # aggregate annotations, then we must make sure the inner + # query is grouped by the main model's primary key. However, + # clearing the select clause can alter results if distinct is + # used. + if inner_query.default_cols and has_existing_aggregation: + inner_query.group_by = ( + self.model._meta.pk.get_col(inner_query.get_initial_alias()), + ) + inner_query.default_cols = False + if not qualify: + # Mask existing annotations that are not referenced by + # aggregates to be pushed to the outer query unless + # filtering against window functions is involved as it + # requires complex realising. + annotation_mask = set() + if isinstance(self.group_by, tuple): + for expr in self.group_by: + annotation_mask |= expr.get_refs() + for aggregate in aggregates.values(): + annotation_mask |= aggregate.get_refs() + # Avoid eliding expressions that might have an incidence on + # the implicit grouping logic. + for annotation_alias, annotation in self.annotation_select.items(): + if annotation.get_group_by_cols(): + annotation_mask.add(annotation_alias) + inner_query.set_annotation_mask(annotation_mask) + + # Add aggregates to the outer AggregateQuery. This requires making + # sure all columns referenced by the aggregates are selected in the + # inner query. It is achieved by retrieving all column references + # by the aggregates, explicitly selecting them in the inner query, + # and making sure the aggregates are repointed to them. + col_refs = {} + for alias, aggregate in aggregates.items(): + replacements = {} + for col in self._gen_cols([aggregate], resolve_refs=False): + if not (col_ref := col_refs.get(col)): + index = len(col_refs) + 1 + col_alias = f"__col{index}" + col_ref = Ref(col_alias, col) + col_refs[col] = col_ref + inner_query.annotations[col_alias] = col + inner_query.append_annotation_mask([col_alias]) + replacements[col] = col_ref + outer_query.annotations[alias] = aggregate.replace_expressions( + replacements + ) + if ( + inner_query.select == () + and not inner_query.default_cols + and not inner_query.annotation_select_mask + ): + # In case of Model.objects[0:3].count(), there would be no + # field selected in the inner query, yet we must use a subquery. + # So, make sure at least one field is selected. + inner_query.select = ( + self.model._meta.pk.get_col(inner_query.get_initial_alias()), + ) + else: + outer_query = self + self.select = () + self.default_cols = False + self.extra = {} + if self.annotations: + # Inline reference to existing annotations and mask them as + # they are unnecessary given only the summarized aggregations + # are requested. + replacements = { + Ref(alias, annotation): annotation + for alias, annotation in self.annotations.items() + } + self.annotations = { + alias: aggregate.replace_expressions(replacements) + for alias, aggregate in aggregates.items() + } + else: + self.annotations = aggregates + self.set_annotation_mask(aggregates) + + empty_set_result = [ + expression.empty_result_set_value + for expression in outer_query.annotation_select.values() + ] + elide_empty = not any(result is NotImplemented for result in empty_set_result) + outer_query.clear_ordering(force=True) + outer_query.clear_limits() + outer_query.select_for_update = False + outer_query.select_related = False + compiler = outer_query.get_compiler(using, elide_empty=elide_empty) + result = compiler.execute_sql(SINGLE) + if result is None: + result = empty_set_result + else: + converters = compiler.get_converters(outer_query.annotation_select.values()) + result = next(compiler.apply_converters((result,), converters)) + + return dict(zip(outer_query.annotation_select, result)) + + def get_count(self, using): + """ + Perform a COUNT() query using the current filter constraints. + """ + obj = self.clone() + return obj.get_aggregation(using, {"__count": Count("*")})["__count"] + + def has_filters(self): + return self.where + + def exists(self, limit=True): + q = self.clone() + if not (q.distinct and q.is_sliced): + if q.group_by is True: + q.add_fields( + (f.attname for f in self.model._meta.concrete_fields), False + ) + # Disable GROUP BY aliases to avoid orphaning references to the + # SELECT clause which is about to be cleared. + q.set_group_by(allow_aliases=False) + q.clear_select_clause() + if q.combined_queries and q.combinator == "union": + q.combined_queries = tuple( + combined_query.exists(limit=False) + for combined_query in q.combined_queries + ) + q.clear_ordering(force=True) + if limit: + q.set_limits(high=1) + q.add_annotation(Value(1), "a") + return q + + def has_results(self, using): + q = self.exists(using) + compiler = q.get_compiler(using=using) + return compiler.has_results() + + def explain(self, using, format=None, **options): + q = self.clone() + for option_name in options: + if ( + not EXPLAIN_OPTIONS_PATTERN.fullmatch(option_name) + or "--" in option_name + ): + raise ValueError(f"Invalid option name: {option_name!r}.") + q.explain_info = ExplainInfo(format, options) + compiler = q.get_compiler(using=using) + return "\n".join(compiler.explain_query()) + + def combine(self, rhs, connector): + """ + Merge the 'rhs' query into the current one (with any 'rhs' effects + being applied *after* (that is, "to the right of") anything in the + current query. 'rhs' is not modified during a call to this function. + + The 'connector' parameter describes how to connect filters from the + 'rhs' query. + """ + if self.model != rhs.model: + raise TypeError("Cannot combine queries on two different base models.") + if self.is_sliced: + raise TypeError("Cannot combine queries once a slice has been taken.") + if self.distinct != rhs.distinct: + raise TypeError("Cannot combine a unique query with a non-unique query.") + if self.distinct_fields != rhs.distinct_fields: + raise TypeError("Cannot combine queries with different distinct fields.") + + # If lhs and rhs shares the same alias prefix, it is possible to have + # conflicting alias changes like T4 -> T5, T5 -> T6, which might end up + # as T4 -> T6 while combining two querysets. To prevent this, change an + # alias prefix of the rhs and update current aliases accordingly, + # except if the alias is the base table since it must be present in the + # query on both sides. + initial_alias = self.get_initial_alias() + rhs.bump_prefix(self, exclude={initial_alias}) + + # Work out how to relabel the rhs aliases, if necessary. + change_map = {} + conjunction = connector == AND + + # Determine which existing joins can be reused. When combining the + # query with AND we must recreate all joins for m2m filters. When + # combining with OR we can reuse joins. The reason is that in AND + # case a single row can't fulfill a condition like: + # revrel__col=1 & revrel__col=2 + # But, there might be two different related rows matching this + # condition. In OR case a single True is enough, so single row is + # enough, too. + # + # Note that we will be creating duplicate joins for non-m2m joins in + # the AND case. The results will be correct but this creates too many + # joins. This is something that could be fixed later on. + reuse = set() if conjunction else set(self.alias_map) + joinpromoter = JoinPromoter(connector, 2, False) + joinpromoter.add_votes( + j for j in self.alias_map if self.alias_map[j].join_type == INNER + ) + rhs_votes = set() + # Now, add the joins from rhs query into the new query (skipping base + # table). + rhs_tables = list(rhs.alias_map)[1:] + for alias in rhs_tables: + join = rhs.alias_map[alias] + # If the left side of the join was already relabeled, use the + # updated alias. + join = join.relabeled_clone(change_map) + new_alias = self.join(join, reuse=reuse) + if join.join_type == INNER: + rhs_votes.add(new_alias) + # We can't reuse the same join again in the query. If we have two + # distinct joins for the same connection in rhs query, then the + # combined query must have two joins, too. + reuse.discard(new_alias) + if alias != new_alias: + change_map[alias] = new_alias + if not rhs.alias_refcount[alias]: + # The alias was unused in the rhs query. Unref it so that it + # will be unused in the new query, too. We have to add and + # unref the alias so that join promotion has information of + # the join type for the unused alias. + self.unref_alias(new_alias) + joinpromoter.add_votes(rhs_votes) + joinpromoter.update_join_types(self) + + # Combine subqueries aliases to ensure aliases relabelling properly + # handle subqueries when combining where and select clauses. + self.subq_aliases |= rhs.subq_aliases + + # Now relabel a copy of the rhs where-clause and add it to the current + # one. + w = rhs.where.clone() + w.relabel_aliases(change_map) + self.where.add(w, connector) + + # Selection columns and extra extensions are those provided by 'rhs'. + if rhs.select: + self.set_select([col.relabeled_clone(change_map) for col in rhs.select]) + else: + self.select = () + + if connector == OR: + # It would be nice to be able to handle this, but the queries don't + # really make sense (or return consistent value sets). Not worth + # the extra complexity when you can write a real query instead. + if self.extra and rhs.extra: + raise ValueError( + "When merging querysets using 'or', you cannot have " + "extra(select=...) on both sides." + ) + self.extra.update(rhs.extra) + extra_select_mask = set() + if self.extra_select_mask is not None: + extra_select_mask.update(self.extra_select_mask) + if rhs.extra_select_mask is not None: + extra_select_mask.update(rhs.extra_select_mask) + if extra_select_mask: + self.set_extra_mask(extra_select_mask) + self.extra_tables += rhs.extra_tables + + # Ordering uses the 'rhs' ordering, unless it has none, in which case + # the current ordering is used. + self.order_by = rhs.order_by or self.order_by + self.extra_order_by = rhs.extra_order_by or self.extra_order_by + + def _get_defer_select_mask(self, opts, mask, select_mask=None): + if select_mask is None: + select_mask = {} + select_mask[opts.pk] = {} + # All concrete fields that are not part of the defer mask must be + # loaded. If a relational field is encountered it gets added to the + # mask for it be considered if `select_related` and the cycle continues + # by recursively calling this function. + for field in opts.concrete_fields: + field_mask = mask.pop(field.name, None) + field_att_mask = mask.pop(field.attname, None) + if field_mask is None and field_att_mask is None: + select_mask.setdefault(field, {}) + elif field_mask: + if not field.is_relation: + raise FieldError(next(iter(field_mask))) + field_select_mask = select_mask.setdefault(field, {}) + related_model = field.remote_field.model._meta.concrete_model + self._get_defer_select_mask( + related_model._meta, field_mask, field_select_mask + ) + # Remaining defer entries must be references to reverse relationships. + # The following code is expected to raise FieldError if it encounters + # a malformed defer entry. + for field_name, field_mask in mask.items(): + if filtered_relation := self._filtered_relations.get(field_name): + relation = opts.get_field(filtered_relation.relation_name) + field_select_mask = select_mask.setdefault((field_name, relation), {}) + field = relation.field + else: + reverse_rel = opts.get_field(field_name) + # While virtual fields such as many-to-many and generic foreign + # keys cannot be effectively deferred we've historically + # allowed them to be passed to QuerySet.defer(). Ignore such + # field references until a layer of validation at mask + # alteration time will be implemented eventually. + if not hasattr(reverse_rel, "field"): + continue + field = reverse_rel.field + field_select_mask = select_mask.setdefault(field, {}) + related_model = field.model._meta.concrete_model + self._get_defer_select_mask( + related_model._meta, field_mask, field_select_mask + ) + return select_mask + + def _get_only_select_mask(self, opts, mask, select_mask=None): + if select_mask is None: + select_mask = {} + select_mask[opts.pk] = {} + # Only include fields mentioned in the mask. + for field_name, field_mask in mask.items(): + field = opts.get_field(field_name) + # Retrieve the actual field associated with reverse relationships + # as that's what is expected in the select mask. + if field in opts.related_objects: + field_key = field.field + else: + field_key = field + field_select_mask = select_mask.setdefault(field_key, {}) + if field_mask: + if not field.is_relation: + raise FieldError(next(iter(field_mask))) + related_model = field.remote_field.model._meta.concrete_model + self._get_only_select_mask( + related_model._meta, field_mask, field_select_mask + ) + return select_mask + + def get_select_mask(self): + """ + Convert the self.deferred_loading data structure to an alternate data + structure, describing the field that *will* be loaded. This is used to + compute the columns to select from the database and also by the + QuerySet class to work out which fields are being initialized on each + model. Models that have all their fields included aren't mentioned in + the result, only those that have field restrictions in place. + """ + field_names, defer = self.deferred_loading + if not field_names: + return {} + mask = {} + for field_name in field_names: + part_mask = mask + for part in field_name.split(LOOKUP_SEP): + part_mask = part_mask.setdefault(part, {}) + opts = self.get_meta() + if defer: + return self._get_defer_select_mask(opts, mask) + return self._get_only_select_mask(opts, mask) + + def table_alias(self, table_name, create=False, filtered_relation=None): + """ + Return a table alias for the given table_name and whether this is a + new alias or not. + + If 'create' is true, a new alias is always created. Otherwise, the + most recently created alias for the table (if one exists) is reused. + """ + alias_list = self.table_map.get(table_name) + if not create and alias_list: + alias = alias_list[0] + self.alias_refcount[alias] += 1 + return alias, False + + # Create a new alias for this table. + if alias_list: + alias = "%s%d" % (self.alias_prefix, len(self.alias_map) + 1) + alias_list.append(alias) + else: + # The first occurrence of a table uses the table name directly. + alias = ( + filtered_relation.alias if filtered_relation is not None else table_name + ) + self.table_map[table_name] = [alias] + self.alias_refcount[alias] = 1 + return alias, True + + def ref_alias(self, alias): + """Increases the reference count for this alias.""" + self.alias_refcount[alias] += 1 + + def unref_alias(self, alias, amount=1): + """Decreases the reference count for this alias.""" + self.alias_refcount[alias] -= amount + + def promote_joins(self, aliases): + """ + Promote recursively the join type of given aliases and its children to + an outer join. If 'unconditional' is False, only promote the join if + it is nullable or the parent join is an outer join. + + The children promotion is done to avoid join chains that contain a LOUTER + b INNER c. So, if we have currently a INNER b INNER c and a->b is promoted, + then we must also promote b->c automatically, or otherwise the promotion + of a->b doesn't actually change anything in the query results. + """ + aliases = list(aliases) + while aliases: + alias = aliases.pop(0) + if self.alias_map[alias].join_type is None: + # This is the base table (first FROM entry) - this table + # isn't really joined at all in the query, so we should not + # alter its join type. + continue + # Only the first alias (skipped above) should have None join_type + assert self.alias_map[alias].join_type is not None + parent_alias = self.alias_map[alias].parent_alias + parent_louter = ( + parent_alias and self.alias_map[parent_alias].join_type == LOUTER + ) + already_louter = self.alias_map[alias].join_type == LOUTER + if (self.alias_map[alias].nullable or parent_louter) and not already_louter: + self.alias_map[alias] = self.alias_map[alias].promote() + # Join type of 'alias' changed, so re-examine all aliases that + # refer to this one. + aliases.extend( + join + for join in self.alias_map + if self.alias_map[join].parent_alias == alias + and join not in aliases + ) + + def demote_joins(self, aliases): + """ + Change join type from LOUTER to INNER for all joins in aliases. + + Similarly to promote_joins(), this method must ensure no join chains + containing first an outer, then an inner join are generated. If we + are demoting b->c join in chain a LOUTER b LOUTER c then we must + demote a->b automatically, or otherwise the demotion of b->c doesn't + actually change anything in the query results. . + """ + aliases = list(aliases) + while aliases: + alias = aliases.pop(0) + if self.alias_map[alias].join_type == LOUTER: + self.alias_map[alias] = self.alias_map[alias].demote() + parent_alias = self.alias_map[alias].parent_alias + if self.alias_map[parent_alias].join_type == INNER: + aliases.append(parent_alias) + + def reset_refcounts(self, to_counts): + """ + Reset reference counts for aliases so that they match the value passed + in `to_counts`. + """ + for alias, cur_refcount in self.alias_refcount.copy().items(): + unref_amount = cur_refcount - to_counts.get(alias, 0) + self.unref_alias(alias, unref_amount) + + def change_aliases(self, change_map): + """ + Change the aliases in change_map (which maps old-alias -> new-alias), + relabelling any references to them in select columns and the where + clause. + """ + # If keys and values of change_map were to intersect, an alias might be + # updated twice (e.g. T4 -> T5, T5 -> T6, so also T4 -> T6) depending + # on their order in change_map. + assert set(change_map).isdisjoint(change_map.values()) + + # 1. Update references in "select" (normal columns plus aliases), + # "group by" and "where". + self.where.relabel_aliases(change_map) + if isinstance(self.group_by, tuple): + self.group_by = tuple( + [col.relabeled_clone(change_map) for col in self.group_by] + ) + self.select = tuple([col.relabeled_clone(change_map) for col in self.select]) + self.annotations = self.annotations and { + key: col.relabeled_clone(change_map) + for key, col in self.annotations.items() + } + + # 2. Rename the alias in the internal table/alias datastructures. + for old_alias, new_alias in change_map.items(): + if old_alias not in self.alias_map: + continue + alias_data = self.alias_map[old_alias].relabeled_clone(change_map) + self.alias_map[new_alias] = alias_data + self.alias_refcount[new_alias] = self.alias_refcount[old_alias] + del self.alias_refcount[old_alias] + del self.alias_map[old_alias] + + table_aliases = self.table_map[alias_data.table_name] + for pos, alias in enumerate(table_aliases): + if alias == old_alias: + table_aliases[pos] = new_alias + break + self.external_aliases = { + # Table is aliased or it's being changed and thus is aliased. + change_map.get(alias, alias): (aliased or alias in change_map) + for alias, aliased in self.external_aliases.items() + } + + def bump_prefix(self, other_query, exclude=None): + """ + Change the alias prefix to the next letter in the alphabet in a way + that the other query's aliases and this query's aliases will not + conflict. Even tables that previously had no alias will get an alias + after this call. To prevent changing aliases use the exclude parameter. + """ + + def prefix_gen(): + """ + Generate a sequence of characters in alphabetical order: + -> 'A', 'B', 'C', ... + + When the alphabet is finished, the sequence will continue with the + Cartesian product: + -> 'AA', 'AB', 'AC', ... + """ + alphabet = ascii_uppercase + prefix = chr(ord(self.alias_prefix) + 1) + yield prefix + for n in count(1): + seq = alphabet[alphabet.index(prefix) :] if prefix else alphabet + for s in product(seq, repeat=n): + yield "".join(s) + prefix = None + + if self.alias_prefix != other_query.alias_prefix: + # No clashes between self and outer query should be possible. + return + + # Explicitly avoid infinite loop. The constant divider is based on how + # much depth recursive subquery references add to the stack. This value + # might need to be adjusted when adding or removing function calls from + # the code path in charge of performing these operations. + local_recursion_limit = sys.getrecursionlimit() // 16 + for pos, prefix in enumerate(prefix_gen()): + if prefix not in self.subq_aliases: + self.alias_prefix = prefix + break + if pos > local_recursion_limit: + raise RecursionError( + "Maximum recursion depth exceeded: too many subqueries." + ) + self.subq_aliases = self.subq_aliases.union([self.alias_prefix]) + other_query.subq_aliases = other_query.subq_aliases.union(self.subq_aliases) + if exclude is None: + exclude = {} + self.change_aliases( + { + alias: "%s%d" % (self.alias_prefix, pos) + for pos, alias in enumerate(self.alias_map) + if alias not in exclude + } + ) + + def get_initial_alias(self): + """ + Return the first alias for this query, after increasing its reference + count. + """ + if self.alias_map: + alias = self.base_table + self.ref_alias(alias) + elif self.model: + alias = self.join(self.base_table_class(self.get_meta().db_table, None)) + else: + alias = None + return alias + + def count_active_tables(self): + """ + Return the number of tables in this query with a non-zero reference + count. After execution, the reference counts are zeroed, so tables + added in compiler will not be seen by this method. + """ + return len([1 for count in self.alias_refcount.values() if count]) + + def join(self, join, reuse=None): + """ + Return an alias for the 'join', either reusing an existing alias for + that join or creating a new one. 'join' is either a base_table_class or + join_class. + + The 'reuse' parameter can be either None which means all joins are + reusable, or it can be a set containing the aliases that can be reused. + + A join is always created as LOUTER if the lhs alias is LOUTER to make + sure chains like t1 LOUTER t2 INNER t3 aren't generated. All new + joins are created as LOUTER if the join is nullable. + """ + reuse_aliases = [ + a + for a, j in self.alias_map.items() + if (reuse is None or a in reuse) and j == join + ] + if reuse_aliases: + if join.table_alias in reuse_aliases: + reuse_alias = join.table_alias + else: + # Reuse the most recent alias of the joined table + # (a many-to-many relation may be joined multiple times). + reuse_alias = reuse_aliases[-1] + self.ref_alias(reuse_alias) + return reuse_alias + + # No reuse is possible, so we need a new alias. + alias, _ = self.table_alias( + join.table_name, create=True, filtered_relation=join.filtered_relation + ) + if join.join_type: + if self.alias_map[join.parent_alias].join_type == LOUTER or join.nullable: + join_type = LOUTER + else: + join_type = INNER + join.join_type = join_type + join.table_alias = alias + self.alias_map[alias] = join + if filtered_relation := join.filtered_relation: + resolve_reuse = reuse + if resolve_reuse is not None: + resolve_reuse = set(reuse) | {alias} + joins_len = len(self.alias_map) + join.filtered_relation = filtered_relation.resolve_expression( + self, reuse=resolve_reuse + ) + # Some joins were during expression resolving, they must be present + # before the one we just added. + if joins_len < len(self.alias_map): + self.alias_map[alias] = self.alias_map.pop(alias) + return alias + + def join_parent_model(self, opts, model, alias, seen): + """ + Make sure the given 'model' is joined in the query. If 'model' isn't + a parent of 'opts' or if it is None this method is a no-op. + + The 'alias' is the root alias for starting the join, 'seen' is a dict + of model -> alias of existing joins. It must also contain a mapping + of None -> some alias. This will be returned in the no-op case. + """ + if model in seen: + return seen[model] + chain = opts.get_base_chain(model) + if not chain: + return alias + curr_opts = opts + for int_model in chain: + if int_model in seen: + curr_opts = int_model._meta + alias = seen[int_model] + continue + # Proxy model have elements in base chain + # with no parents, assign the new options + # object and skip to the next base in that + # case + if not curr_opts.parents[int_model]: + curr_opts = int_model._meta + continue + link_field = curr_opts.get_ancestor_link(int_model) + join_info = self.setup_joins([link_field.name], curr_opts, alias) + curr_opts = int_model._meta + alias = seen[int_model] = join_info.joins[-1] + return alias or seen[None] + + def check_alias(self, alias): + if FORBIDDEN_ALIAS_PATTERN.search(alias): + raise ValueError( + "Column aliases cannot contain whitespace characters, quotation marks, " + "semicolons, or SQL comments." + ) + + def add_annotation(self, annotation, alias, select=True): + """Add a single annotation expression to the Query.""" + self.check_alias(alias) + annotation = annotation.resolve_expression(self, allow_joins=True, reuse=None) + if select: + self.append_annotation_mask([alias]) + else: + annotation_mask = ( + value + for value in dict.fromkeys(self.annotation_select) + if value != alias + ) + self.set_annotation_mask(annotation_mask) + self.annotations[alias] = annotation + + def resolve_expression(self, query, *args, **kwargs): + clone = self.clone() + # Subqueries need to use a different set of aliases than the outer query. + clone.bump_prefix(query) + clone.subquery = True + clone.where.resolve_expression(query, *args, **kwargs) + # Resolve combined queries. + if clone.combinator: + clone.combined_queries = tuple( + [ + combined_query.resolve_expression(query, *args, **kwargs) + for combined_query in clone.combined_queries + ] + ) + for key, value in clone.annotations.items(): + resolved = value.resolve_expression(query, *args, **kwargs) + if hasattr(resolved, "external_aliases"): + resolved.external_aliases.update(clone.external_aliases) + clone.annotations[key] = resolved + # Outer query's aliases are considered external. + for alias, table in query.alias_map.items(): + clone.external_aliases[alias] = ( + isinstance(table, Join) + and table.join_field.related_model._meta.db_table != alias + ) or ( + isinstance(table, BaseTable) and table.table_name != table.table_alias + ) + return clone + + def get_external_cols(self): + exprs = chain(self.annotations.values(), self.where.children) + return [ + col + for col in self._gen_cols(exprs, include_external=True) + if col.alias in self.external_aliases + ] + + def get_group_by_cols(self, wrapper=None): + # If wrapper is referenced by an alias for an explicit GROUP BY through + # values() a reference to this expression and not the self must be + # returned to ensure external column references are not grouped against + # as well. + external_cols = self.get_external_cols() + if any(col.possibly_multivalued for col in external_cols): + return [wrapper or self] + return external_cols + + def as_sql(self, compiler, connection): + # Some backends (e.g. Oracle) raise an error when a subquery contains + # unnecessary ORDER BY clause. + if ( + self.subquery + and not connection.features.ignores_unnecessary_order_by_in_subqueries + ): + self.clear_ordering(force=False) + for query in self.combined_queries: + query.clear_ordering(force=False) + sql, params = self.get_compiler(connection=connection).as_sql() + if self.subquery: + sql = "(%s)" % sql + return sql, params + + def resolve_lookup_value(self, value, can_reuse, allow_joins, summarize=False): + if hasattr(value, "resolve_expression"): + value = value.resolve_expression( + self, + reuse=can_reuse, + allow_joins=allow_joins, + summarize=summarize, + ) + elif isinstance(value, (list, tuple)): + # The items of the iterable may be expressions and therefore need + # to be resolved independently. + values = ( + self.resolve_lookup_value(sub_value, can_reuse, allow_joins) + for sub_value in value + ) + type_ = type(value) + if hasattr(type_, "_make"): # namedtuple + return type_(*values) + return type_(values) + return value + + def solve_lookup_type(self, lookup, summarize=False): + """ + Solve the lookup type from the lookup (e.g.: 'foobar__id__icontains'). + """ + lookup_splitted = lookup.split(LOOKUP_SEP) + if self.annotations: + annotation, expression_lookups = refs_expression( + lookup_splitted, self.annotations + ) + if annotation: + expression = self.annotations[annotation] + if summarize: + expression = Ref(annotation, expression) + return expression_lookups, (), expression + _, field, _, lookup_parts = self.names_to_path(lookup_splitted, self.get_meta()) + field_parts = lookup_splitted[0 : len(lookup_splitted) - len(lookup_parts)] + if len(lookup_parts) > 1 and not field_parts: + raise FieldError( + 'Invalid lookup "%s" for model %s".' + % (lookup, self.get_meta().model.__name__) + ) + return lookup_parts, field_parts, False + + def check_query_object_type(self, value, opts, field): + """ + Check whether the object passed while querying is of the correct type. + If not, raise a ValueError specifying the wrong object. + """ + if hasattr(value, "_meta"): + if not check_rel_lookup_compatibility(value._meta.model, opts, field): + raise ValueError( + 'Cannot query "%s": Must be "%s" instance.' + % (value, opts.object_name) + ) + + def check_related_objects(self, field, value, opts): + """Check the type of object passed to query relations.""" + if field.is_relation: + # Check that the field and the queryset use the same model in a + # query like .filter(author=Author.objects.all()). For example, the + # opts would be Author's (from the author field) and value.model + # would be Author.objects.all() queryset's .model (Author also). + # The field is the related field on the lhs side. + if ( + isinstance(value, Query) + and not value.has_select_fields + and not check_rel_lookup_compatibility(value.model, opts, field) + ): + raise ValueError( + 'Cannot use QuerySet for "%s": Use a QuerySet for "%s".' + % (value.model._meta.object_name, opts.object_name) + ) + elif hasattr(value, "_meta"): + self.check_query_object_type(value, opts, field) + elif hasattr(value, "__iter__"): + for v in value: + self.check_query_object_type(v, opts, field) + + def check_filterable(self, expression): + """Raise an error if expression cannot be used in a WHERE clause.""" + if hasattr(expression, "resolve_expression") and not getattr( + expression, "filterable", True + ): + raise NotSupportedError( + expression.__class__.__name__ + " is disallowed in the filter " + "clause." + ) + if hasattr(expression, "get_source_expressions"): + for expr in expression.get_source_expressions(): + self.check_filterable(expr) + + def build_lookup(self, lookups, lhs, rhs): + """ + Try to extract transforms and lookup from given lhs. + + The lhs value is something that works like SQLExpression. + The rhs value is what the lookup is going to compare against. + The lookups is a list of names to extract using get_lookup() + and get_transform(). + """ + # __exact is the default lookup if one isn't given. + *transforms, lookup_name = lookups or ["exact"] + for name in transforms: + lhs = self.try_transform(lhs, name) + # First try get_lookup() so that the lookup takes precedence if the lhs + # supports both transform and lookup for the name. + lookup_class = lhs.get_lookup(lookup_name) + if not lookup_class: + # A lookup wasn't found. Try to interpret the name as a transform + # and do an Exact lookup against it. + lhs = self.try_transform(lhs, lookup_name) + lookup_name = "exact" + lookup_class = lhs.get_lookup(lookup_name) + if not lookup_class: + return + + lookup = lookup_class(lhs, rhs) + # Interpret '__exact=None' as the sql 'is NULL'; otherwise, reject all + # uses of None as a query value unless the lookup supports it. + if lookup.rhs is None and not lookup.can_use_none_as_rhs: + if lookup_name not in ("exact", "iexact"): + raise ValueError("Cannot use None as a query value") + return lhs.get_lookup("isnull")(lhs, True) + + # For Oracle '' is equivalent to null. The check must be done at this + # stage because join promotion can't be done in the compiler. Using + # DEFAULT_DB_ALIAS isn't nice but it's the best that can be done here. + # A similar thing is done in is_nullable(), too. + if ( + lookup_name == "exact" + and lookup.rhs == "" + and connections[DEFAULT_DB_ALIAS].features.interprets_empty_strings_as_nulls + ): + return lhs.get_lookup("isnull")(lhs, True) + + return lookup + + def try_transform(self, lhs, name): + """ + Helper method for build_lookup(). Try to fetch and initialize + a transform for name parameter from lhs. + """ + transform_class = lhs.get_transform(name) + if transform_class: + return transform_class(lhs) + else: + output_field = lhs.output_field.__class__ + suggested_lookups = difflib.get_close_matches( + name, lhs.output_field.get_lookups() + ) + if suggested_lookups: + suggestion = ", perhaps you meant %s?" % " or ".join(suggested_lookups) + else: + suggestion = "." + raise FieldError( + "Unsupported lookup '%s' for %s or join on the field not " + "permitted%s" % (name, output_field.__name__, suggestion) + ) + + def build_filter( + self, + filter_expr, + branch_negated=False, + current_negated=False, + can_reuse=None, + allow_joins=True, + split_subq=True, + check_filterable=True, + summarize=False, + update_join_types=True, + ): + """ + Build a WhereNode for a single filter clause but don't add it + to this Query. Query.add_q() will then add this filter to the where + Node. + + The 'branch_negated' tells us if the current branch contains any + negations. This will be used to determine if subqueries are needed. + + The 'current_negated' is used to determine if the current filter is + negated or not and this will be used to determine if IS NULL filtering + is needed. + + The difference between current_negated and branch_negated is that + branch_negated is set on first negation, but current_negated is + flipped for each negation. + + Note that add_filter will not do any negating itself, that is done + upper in the code by add_q(). + + The 'can_reuse' is a set of reusable joins for multijoins. + + The method will create a filter clause that can be added to the current + query. However, if the filter isn't added to the query then the caller + is responsible for unreffing the joins used. + """ + if isinstance(filter_expr, dict): + raise FieldError("Cannot parse keyword query as dict") + if isinstance(filter_expr, Q): + return self._add_q( + filter_expr, + branch_negated=branch_negated, + current_negated=current_negated, + used_aliases=can_reuse, + allow_joins=allow_joins, + split_subq=split_subq, + check_filterable=check_filterable, + summarize=summarize, + update_join_types=update_join_types, + ) + if hasattr(filter_expr, "resolve_expression"): + if not getattr(filter_expr, "conditional", False): + raise TypeError("Cannot filter against a non-conditional expression.") + condition = filter_expr.resolve_expression( + self, allow_joins=allow_joins, reuse=can_reuse, summarize=summarize + ) + if not isinstance(condition, Lookup): + condition = self.build_lookup(["exact"], condition, True) + return WhereNode([condition], connector=AND), [] + arg, value = filter_expr + if not arg: + raise FieldError("Cannot parse keyword query %r" % arg) + lookups, parts, reffed_expression = self.solve_lookup_type(arg, summarize) + + if check_filterable: + self.check_filterable(reffed_expression) + + if not allow_joins and len(parts) > 1: + raise FieldError("Joined field references are not permitted in this query") + + pre_joins = self.alias_refcount.copy() + value = self.resolve_lookup_value(value, can_reuse, allow_joins, summarize) + used_joins = { + k for k, v in self.alias_refcount.items() if v > pre_joins.get(k, 0) + } + + if check_filterable: + self.check_filterable(value) + + if reffed_expression: + condition = self.build_lookup(lookups, reffed_expression, value) + return WhereNode([condition], connector=AND), [] + + opts = self.get_meta() + alias = self.get_initial_alias() + allow_many = not branch_negated or not split_subq + + try: + join_info = self.setup_joins( + parts, + opts, + alias, + can_reuse=can_reuse, + allow_many=allow_many, + ) + + # Prevent iterator from being consumed by check_related_objects() + if isinstance(value, Iterator): + value = list(value) + self.check_related_objects(join_info.final_field, value, join_info.opts) + + # split_exclude() needs to know which joins were generated for the + # lookup parts + self._lookup_joins = join_info.joins + except MultiJoin as e: + return self.split_exclude(filter_expr, can_reuse, e.names_with_path) + + # Update used_joins before trimming since they are reused to determine + # which joins could be later promoted to INNER. + used_joins.update(join_info.joins) + targets, alias, join_list = self.trim_joins( + join_info.targets, join_info.joins, join_info.path + ) + if can_reuse is not None: + can_reuse.update(join_list) + + if join_info.final_field.is_relation: + if len(targets) == 1: + col = self._get_col(targets[0], join_info.final_field, alias) + else: + col = MultiColSource( + alias, targets, join_info.targets, join_info.final_field + ) + else: + col = self._get_col(targets[0], join_info.final_field, alias) + + condition = self.build_lookup(lookups, col, value) + lookup_type = condition.lookup_name + clause = WhereNode([condition], connector=AND) + + require_outer = ( + lookup_type == "isnull" and condition.rhs is True and not current_negated + ) + if ( + current_negated + and (lookup_type != "isnull" or condition.rhs is False) + and condition.rhs is not None + ): + require_outer = True + if lookup_type != "isnull": + # The condition added here will be SQL like this: + # NOT (col IS NOT NULL), where the first NOT is added in + # upper layers of code. The reason for addition is that if col + # is null, then col != someval will result in SQL "unknown" + # which isn't the same as in Python. The Python None handling + # is wanted, and it can be gotten by + # (col IS NULL OR col != someval) + # <=> + # NOT (col IS NOT NULL AND col = someval). + if ( + self.is_nullable(targets[0]) + or self.alias_map[join_list[-1]].join_type == LOUTER + ): + lookup_class = targets[0].get_lookup("isnull") + col = self._get_col(targets[0], join_info.targets[0], alias) + clause.add(lookup_class(col, False), AND) + # If someval is a nullable column, someval IS NOT NULL is + # added. + if isinstance(value, Col) and self.is_nullable(value.target): + lookup_class = value.target.get_lookup("isnull") + clause.add(lookup_class(value, False), AND) + return clause, used_joins if not require_outer else () + + def add_filter(self, filter_lhs, filter_rhs): + self.add_q(Q((filter_lhs, filter_rhs))) + + def add_q(self, q_object): + """ + A preprocessor for the internal _add_q(). Responsible for doing final + join promotion. + """ + # For join promotion this case is doing an AND for the added q_object + # and existing conditions. So, any existing inner join forces the join + # type to remain inner. Existing outer joins can however be demoted. + # (Consider case where rel_a is LOUTER and rel_a__col=1 is added - if + # rel_a doesn't produce any rows, then the whole condition must fail. + # So, demotion is OK. + existing_inner = { + a for a in self.alias_map if self.alias_map[a].join_type == INNER + } + clause, _ = self._add_q(q_object, self.used_aliases) + if clause: + self.where.add(clause, AND) + self.demote_joins(existing_inner) + + def build_where(self, filter_expr): + return self.build_filter(filter_expr, allow_joins=False)[0] + + def clear_where(self): + self.where = WhereNode() + + def _add_q( + self, + q_object, + used_aliases, + branch_negated=False, + current_negated=False, + allow_joins=True, + split_subq=True, + check_filterable=True, + summarize=False, + update_join_types=True, + ): + """Add a Q-object to the current filter.""" + connector = q_object.connector + current_negated ^= q_object.negated + branch_negated = branch_negated or q_object.negated + target_clause = WhereNode(connector=connector, negated=q_object.negated) + joinpromoter = JoinPromoter( + q_object.connector, len(q_object.children), current_negated + ) + for child in q_object.children: + child_clause, needed_inner = self.build_filter( + child, + can_reuse=used_aliases, + branch_negated=branch_negated, + current_negated=current_negated, + allow_joins=allow_joins, + split_subq=split_subq, + check_filterable=check_filterable, + summarize=summarize, + update_join_types=update_join_types, + ) + joinpromoter.add_votes(needed_inner) + if child_clause: + target_clause.add(child_clause, connector) + if update_join_types: + needed_inner = joinpromoter.update_join_types(self) + else: + needed_inner = [] + return target_clause, needed_inner + + def add_filtered_relation(self, filtered_relation, alias): + filtered_relation.alias = alias + relation_lookup_parts, relation_field_parts, _ = self.solve_lookup_type( + filtered_relation.relation_name + ) + if relation_lookup_parts: + raise ValueError( + "FilteredRelation's relation_name cannot contain lookups " + "(got %r)." % filtered_relation.relation_name + ) + for lookup in get_children_from_q(filtered_relation.condition): + lookup_parts, lookup_field_parts, _ = self.solve_lookup_type(lookup) + shift = 2 if not lookup_parts else 1 + lookup_field_path = lookup_field_parts[:-shift] + for idx, lookup_field_part in enumerate(lookup_field_path): + if len(relation_field_parts) > idx: + if relation_field_parts[idx] != lookup_field_part: + raise ValueError( + "FilteredRelation's condition doesn't support " + "relations outside the %r (got %r)." + % (filtered_relation.relation_name, lookup) + ) + else: + raise ValueError( + "FilteredRelation's condition doesn't support nested " + "relations deeper than the relation_name (got %r for " + "%r)." % (lookup, filtered_relation.relation_name) + ) + filtered_relation.condition = rename_prefix_from_q( + filtered_relation.relation_name, + alias, + filtered_relation.condition, + ) + self._filtered_relations[filtered_relation.alias] = filtered_relation + + def names_to_path(self, names, opts, allow_many=True, fail_on_missing=False): + """ + Walk the list of names and turns them into PathInfo tuples. A single + name in 'names' can generate multiple PathInfos (m2m, for example). + + 'names' is the path of names to travel, 'opts' is the model Options we + start the name resolving from, 'allow_many' is as for setup_joins(). + If fail_on_missing is set to True, then a name that can't be resolved + will generate a FieldError. + + Return a list of PathInfo tuples. In addition return the final field + (the last used join field) and target (which is a field guaranteed to + contain the same value as the final field). Finally, return those names + that weren't found (which are likely transforms and the final lookup). + """ + path, names_with_path = [], [] + for pos, name in enumerate(names): + cur_names_with_path = (name, []) + if name == "pk" and opts is not None: + name = opts.pk.name + + field = None + filtered_relation = None + try: + if opts is None: + raise FieldDoesNotExist + field = opts.get_field(name) + except FieldDoesNotExist: + if name in self.annotation_select: + field = self.annotation_select[name].output_field + elif name in self._filtered_relations and pos == 0: + filtered_relation = self._filtered_relations[name] + if LOOKUP_SEP in filtered_relation.relation_name: + parts = filtered_relation.relation_name.split(LOOKUP_SEP) + filtered_relation_path, field, _, _ = self.names_to_path( + parts, + opts, + allow_many, + fail_on_missing, + ) + path.extend(filtered_relation_path[:-1]) + else: + field = opts.get_field(filtered_relation.relation_name) + if field is not None: + # Fields that contain one-to-many relations with a generic + # model (like a GenericForeignKey) cannot generate reverse + # relations and therefore cannot be used for reverse querying. + if field.is_relation and not field.related_model: + raise FieldError( + "Field %r does not generate an automatic reverse " + "relation and therefore cannot be used for reverse " + "querying. If it is a GenericForeignKey, consider " + "adding a GenericRelation." % name + ) + try: + model = field.model._meta.concrete_model + except AttributeError: + # QuerySet.annotate() may introduce fields that aren't + # attached to a model. + model = None + else: + # We didn't find the current field, so move position back + # one step. + pos -= 1 + if pos == -1 or fail_on_missing: + available = sorted( + [ + *get_field_names_from_opts(opts), + *self.annotation_select, + *self._filtered_relations, + ] + ) + raise FieldError( + "Cannot resolve keyword '%s' into field. " + "Choices are: %s" % (name, ", ".join(available)) + ) + break + # Check if we need any joins for concrete inheritance cases (the + # field lives in parent, but we are currently in one of its + # children) + if opts is not None and model is not opts.model: + path_to_parent = opts.get_path_to_parent(model) + if path_to_parent: + path.extend(path_to_parent) + cur_names_with_path[1].extend(path_to_parent) + opts = path_to_parent[-1].to_opts + if hasattr(field, "path_infos"): + if filtered_relation: + pathinfos = field.get_path_info(filtered_relation) + else: + pathinfos = field.path_infos + if not allow_many: + for inner_pos, p in enumerate(pathinfos): + if p.m2m: + cur_names_with_path[1].extend(pathinfos[0 : inner_pos + 1]) + names_with_path.append(cur_names_with_path) + raise MultiJoin(pos + 1, names_with_path) + last = pathinfos[-1] + path.extend(pathinfos) + final_field = last.join_field + opts = last.to_opts + targets = last.target_fields + cur_names_with_path[1].extend(pathinfos) + names_with_path.append(cur_names_with_path) + else: + # Local non-relational field. + final_field = field + targets = (field,) + if fail_on_missing and pos + 1 != len(names): + raise FieldError( + "Cannot resolve keyword %r into field. Join on '%s'" + " not permitted." % (names[pos + 1], name) + ) + break + return path, final_field, targets, names[pos + 1 :] + + def setup_joins( + self, + names, + opts, + alias, + can_reuse=None, + allow_many=True, + ): + """ + Compute the necessary table joins for the passage through the fields + given in 'names'. 'opts' is the Options class for the current model + (which gives the table we are starting from), 'alias' is the alias for + the table to start the joining from. + + The 'can_reuse' defines the reverse foreign key joins we can reuse. It + can be None in which case all joins are reusable or a set of aliases + that can be reused. Note that non-reverse foreign keys are always + reusable when using setup_joins(). + + If 'allow_many' is False, then any reverse foreign key seen will + generate a MultiJoin exception. + + Return the final field involved in the joins, the target field (used + for any 'where' constraint), the final 'opts' value, the joins, the + field path traveled to generate the joins, and a transform function + that takes a field and alias and is equivalent to `field.get_col(alias)` + in the simple case but wraps field transforms if they were included in + names. + + The target field is the field containing the concrete value. Final + field can be something different, for example foreign key pointing to + that value. Final field is needed for example in some value + conversions (convert 'obj' in fk__id=obj to pk val using the foreign + key field for example). + """ + joins = [alias] + # The transform can't be applied yet, as joins must be trimmed later. + # To avoid making every caller of this method look up transforms + # directly, compute transforms here and create a partial that converts + # fields to the appropriate wrapped version. + + def final_transformer(field, alias): + if not self.alias_cols: + alias = None + return field.get_col(alias) + + # Try resolving all the names as fields first. If there's an error, + # treat trailing names as lookups until a field can be resolved. + last_field_exception = None + for pivot in range(len(names), 0, -1): + try: + path, final_field, targets, rest = self.names_to_path( + names[:pivot], + opts, + allow_many, + fail_on_missing=True, + ) + except FieldError as exc: + if pivot == 1: + # The first item cannot be a lookup, so it's safe + # to raise the field error here. + raise + else: + last_field_exception = exc + else: + # The transforms are the remaining items that couldn't be + # resolved into fields. + transforms = names[pivot:] + break + for name in transforms: + + def transform(field, alias, *, name, previous): + try: + wrapped = previous(field, alias) + return self.try_transform(wrapped, name) + except FieldError: + # FieldError is raised if the transform doesn't exist. + if isinstance(final_field, Field) and last_field_exception: + raise last_field_exception + else: + raise + + final_transformer = functools.partial( + transform, name=name, previous=final_transformer + ) + final_transformer.has_transforms = True + # Then, add the path to the query's joins. Note that we can't trim + # joins at this stage - we will need the information about join type + # of the trimmed joins. + for join in path: + if join.filtered_relation: + filtered_relation = join.filtered_relation.clone() + table_alias = filtered_relation.alias + else: + filtered_relation = None + table_alias = None + opts = join.to_opts + if join.direct: + nullable = self.is_nullable(join.join_field) + else: + nullable = True + connection = self.join_class( + opts.db_table, + alias, + table_alias, + INNER, + join.join_field, + nullable, + filtered_relation=filtered_relation, + ) + reuse = can_reuse if join.m2m else None + alias = self.join(connection, reuse=reuse) + joins.append(alias) + return JoinInfo(final_field, targets, opts, joins, path, final_transformer) + + def trim_joins(self, targets, joins, path): + """ + The 'target' parameter is the final field being joined to, 'joins' + is the full list of join aliases. The 'path' contain the PathInfos + used to create the joins. + + Return the final target field and table alias and the new active + joins. + + Always trim any direct join if the target column is already in the + previous table. Can't trim reverse joins as it's unknown if there's + anything on the other side of the join. + """ + joins = joins[:] + for pos, info in enumerate(reversed(path)): + if len(joins) == 1 or not info.direct: + break + if info.filtered_relation: + break + join_targets = {t.column for t in info.join_field.foreign_related_fields} + cur_targets = {t.column for t in targets} + if not cur_targets.issubset(join_targets): + break + targets_dict = { + r[1].column: r[0] + for r in info.join_field.related_fields + if r[1].column in cur_targets + } + targets = tuple(targets_dict[t.column] for t in targets) + self.unref_alias(joins.pop()) + return targets, joins[-1], joins + + @classmethod + def _gen_cols(cls, exprs, include_external=False, resolve_refs=True): + for expr in exprs: + if isinstance(expr, Col): + yield expr + elif include_external and callable( + getattr(expr, "get_external_cols", None) + ): + yield from expr.get_external_cols() + elif hasattr(expr, "get_source_expressions"): + if not resolve_refs and isinstance(expr, Ref): + continue + yield from cls._gen_cols( + expr.get_source_expressions(), + include_external=include_external, + resolve_refs=resolve_refs, + ) + + @classmethod + def _gen_col_aliases(cls, exprs): + yield from (expr.alias for expr in cls._gen_cols(exprs)) + + def resolve_ref(self, name, allow_joins=True, reuse=None, summarize=False): + annotation = self.annotations.get(name) + if annotation is not None: + if not allow_joins: + for alias in self._gen_col_aliases([annotation]): + if isinstance(self.alias_map[alias], Join): + raise FieldError( + "Joined field references are not permitted in this query" + ) + if summarize: + # Summarize currently means we are doing an aggregate() query + # which is executed as a wrapped subquery if any of the + # aggregate() elements reference an existing annotation. In + # that case we need to return a Ref to the subquery's annotation. + if name not in self.annotation_select: + raise FieldError( + "Cannot aggregate over the '%s' alias. Use annotate() " + "to promote it." % name + ) + return Ref(name, self.annotation_select[name]) + else: + return annotation + else: + field_list = name.split(LOOKUP_SEP) + annotation = self.annotations.get(field_list[0]) + if annotation is not None: + for transform in field_list[1:]: + annotation = self.try_transform(annotation, transform) + return annotation + join_info = self.setup_joins( + field_list, self.get_meta(), self.get_initial_alias(), can_reuse=reuse + ) + targets, final_alias, join_list = self.trim_joins( + join_info.targets, join_info.joins, join_info.path + ) + if not allow_joins and len(join_list) > 1: + raise FieldError( + "Joined field references are not permitted in this query" + ) + if len(targets) > 1: + raise FieldError( + "Referencing multicolumn fields with F() objects isn't supported" + ) + # Verify that the last lookup in name is a field or a transform: + # transform_function() raises FieldError if not. + transform = join_info.transform_function(targets[0], final_alias) + if reuse is not None: + reuse.update(join_list) + return transform + + def split_exclude(self, filter_expr, can_reuse, names_with_path): + """ + When doing an exclude against any kind of N-to-many relation, we need + to use a subquery. This method constructs the nested query, given the + original exclude filter (filter_expr) and the portion up to the first + N-to-many relation field. + + For example, if the origin filter is ~Q(child__name='foo'), filter_expr + is ('child__name', 'foo') and can_reuse is a set of joins usable for + filters in the original query. + + We will turn this into equivalent of: + WHERE NOT EXISTS( + SELECT 1 + FROM child + WHERE name = 'foo' AND child.parent_id = parent.id + LIMIT 1 + ) + """ + # Generate the inner query. + query = self.__class__(self.model) + query._filtered_relations = self._filtered_relations + filter_lhs, filter_rhs = filter_expr + if isinstance(filter_rhs, OuterRef): + filter_rhs = OuterRef(filter_rhs) + elif isinstance(filter_rhs, F): + filter_rhs = OuterRef(filter_rhs.name) + query.add_filter(filter_lhs, filter_rhs) + query.clear_ordering(force=True) + # Try to have as simple as possible subquery -> trim leading joins from + # the subquery. + trimmed_prefix, contains_louter = query.trim_start(names_with_path) + + col = query.select[0] + select_field = col.target + alias = col.alias + if alias in can_reuse: + pk = select_field.model._meta.pk + # Need to add a restriction so that outer query's filters are in effect for + # the subquery, too. + query.bump_prefix(self) + lookup_class = select_field.get_lookup("exact") + # Note that the query.select[0].alias is different from alias + # due to bump_prefix above. + lookup = lookup_class(pk.get_col(query.select[0].alias), pk.get_col(alias)) + query.where.add(lookup, AND) + query.external_aliases[alias] = True + else: + lookup_class = select_field.get_lookup("exact") + lookup = lookup_class(col, ResolvedOuterRef(trimmed_prefix)) + query.where.add(lookup, AND) + + condition, needed_inner = self.build_filter(Exists(query)) + + if contains_louter: + or_null_condition, _ = self.build_filter( + ("%s__isnull" % trimmed_prefix, True), + current_negated=True, + branch_negated=True, + can_reuse=can_reuse, + ) + condition.add(or_null_condition, OR) + # Note that the end result will be: + # NOT EXISTS (inner_q) OR outercol IS NULL + # this might look crazy but due to how NULL works, this seems to be + # correct. If the IS NULL check is removed, then if outercol + # IS NULL we will not match the row. + return condition, needed_inner + + def set_empty(self): + self.where.add(NothingNode(), AND) + for query in self.combined_queries: + query.set_empty() + + def is_empty(self): + return any(isinstance(c, NothingNode) for c in self.where.children) + + def set_limits(self, low=None, high=None): + """ + Adjust the limits on the rows retrieved. Use low/high to set these, + as it makes it more Pythonic to read and write. When the SQL query is + created, convert them to the appropriate offset and limit values. + + Apply any limits passed in here to the existing constraints. Add low + to the current low value and clamp both to any existing high value. + """ + if high is not None: + if self.high_mark is not None: + self.high_mark = min(self.high_mark, self.low_mark + high) + else: + self.high_mark = self.low_mark + high + if low is not None: + if self.high_mark is not None: + self.low_mark = min(self.high_mark, self.low_mark + low) + else: + self.low_mark = self.low_mark + low + + if self.low_mark == self.high_mark: + self.set_empty() + + def clear_limits(self): + """Clear any existing limits.""" + self.low_mark, self.high_mark = 0, None + + @property + def is_sliced(self): + return self.low_mark != 0 or self.high_mark is not None + + def has_limit_one(self): + return self.high_mark is not None and (self.high_mark - self.low_mark) == 1 + + def can_filter(self): + """ + Return True if adding filters to this instance is still possible. + + Typically, this means no limits or offsets have been put on the results. + """ + return not self.is_sliced + + def clear_select_clause(self): + """Remove all fields from SELECT clause.""" + self.select = () + self.default_cols = False + self.select_related = False + self.set_extra_mask(()) + self.set_annotation_mask(()) + + def clear_select_fields(self): + """ + Clear the list of fields to select (but not extra_select columns). + Some queryset types completely replace any existing list of select + columns. + """ + self.select = () + self.values_select = () + + def add_select_col(self, col, name): + self.select += (col,) + self.values_select += (name,) + + def set_select(self, cols): + self.default_cols = False + self.select = tuple(cols) + + def add_distinct_fields(self, *field_names): + """ + Add and resolve the given fields to the query's "distinct on" clause. + """ + self.distinct_fields = field_names + self.distinct = True + + def add_fields(self, field_names, allow_m2m=True): + """ + Add the given (model) fields to the select set. Add the field names in + the order specified. + """ + alias = self.get_initial_alias() + opts = self.get_meta() + + try: + cols = [] + for name in field_names: + # Join promotion note - we must not remove any rows here, so + # if there is no existing joins, use outer join. + join_info = self.setup_joins( + name.split(LOOKUP_SEP), opts, alias, allow_many=allow_m2m + ) + targets, final_alias, joins = self.trim_joins( + join_info.targets, + join_info.joins, + join_info.path, + ) + for target in targets: + cols.append(join_info.transform_function(target, final_alias)) + if cols: + self.set_select(cols) + except MultiJoin: + raise FieldError("Invalid field name: '%s'" % name) + except FieldError: + if LOOKUP_SEP in name: + # For lookups spanning over relationships, show the error + # from the model on which the lookup failed. + raise + else: + names = sorted( + [ + *get_field_names_from_opts(opts), + *self.extra, + *self.annotation_select, + *self._filtered_relations, + ] + ) + raise FieldError( + "Cannot resolve keyword %r into field. " + "Choices are: %s" % (name, ", ".join(names)) + ) + + def add_ordering(self, *ordering): + """ + Add items from the 'ordering' sequence to the query's "order by" + clause. These items are either field names (not column names) -- + possibly with a direction prefix ('-' or '?') -- or OrderBy + expressions. + + If 'ordering' is empty, clear all ordering from the query. + """ + errors = [] + for item in ordering: + if isinstance(item, str): + if item == "?": + continue + item = item.removeprefix("-") + if item in self.annotations: + continue + if self.extra and item in self.extra: + continue + # names_to_path() validates the lookup. A descriptive + # FieldError will be raise if it's not. + self.names_to_path(item.split(LOOKUP_SEP), self.model._meta) + elif not hasattr(item, "resolve_expression"): + errors.append(item) + if getattr(item, "contains_aggregate", False): + raise FieldError( + "Using an aggregate in order_by() without also including " + "it in annotate() is not allowed: %s" % item + ) + if errors: + raise FieldError("Invalid order_by arguments: %s" % errors) + if ordering: + self.order_by += ordering + else: + self.default_ordering = False + + def clear_ordering(self, force=False, clear_default=True): + """ + Remove any ordering settings if the current query allows it without + side effects, set 'force' to True to clear the ordering regardless. + If 'clear_default' is True, there will be no ordering in the resulting + query (not even the model's default). + """ + if not force and ( + self.is_sliced or self.distinct_fields or self.select_for_update + ): + return + self.order_by = () + self.extra_order_by = () + if clear_default: + self.default_ordering = False + + def set_group_by(self, allow_aliases=True): + """ + Expand the GROUP BY clause required by the query. + + This will usually be the set of all non-aggregate fields in the + return data. If the database backend supports grouping by the + primary key, and the query would be equivalent, the optimization + will be made automatically. + """ + if allow_aliases and self.values_select: + # If grouping by aliases is allowed assign selected value aliases + # by moving them to annotations. + group_by_annotations = {} + values_select = {} + for alias, expr in zip(self.values_select, self.select): + if isinstance(expr, Col): + values_select[alias] = expr + else: + group_by_annotations[alias] = expr + self.annotations = {**group_by_annotations, **self.annotations} + self.append_annotation_mask(group_by_annotations) + self.select = tuple(values_select.values()) + self.values_select = tuple(values_select) + group_by = list(self.select) + for alias, annotation in self.annotation_select.items(): + if not (group_by_cols := annotation.get_group_by_cols()): + continue + if allow_aliases and not annotation.contains_aggregate: + group_by.append(Ref(alias, annotation)) + else: + group_by.extend(group_by_cols) + self.group_by = tuple(group_by) + + def add_select_related(self, fields): + """ + Set up the select_related data structure so that we only select + certain related models (as opposed to all models, when + self.select_related=True). + """ + if isinstance(self.select_related, bool): + field_dict = {} + else: + field_dict = self.select_related + for field in fields: + d = field_dict + for part in field.split(LOOKUP_SEP): + d = d.setdefault(part, {}) + self.select_related = field_dict + + def add_extra(self, select, select_params, where, params, tables, order_by): + """ + Add data to the various extra_* attributes for user-created additions + to the query. + """ + if select: + # We need to pair any placeholder markers in the 'select' + # dictionary with their parameters in 'select_params' so that + # subsequent updates to the select dictionary also adjust the + # parameters appropriately. + select_pairs = {} + if select_params: + param_iter = iter(select_params) + else: + param_iter = iter([]) + for name, entry in select.items(): + self.check_alias(name) + entry = str(entry) + entry_params = [] + pos = entry.find("%s") + while pos != -1: + if pos == 0 or entry[pos - 1] != "%": + entry_params.append(next(param_iter)) + pos = entry.find("%s", pos + 2) + select_pairs[name] = (entry, entry_params) + self.extra.update(select_pairs) + if where or params: + self.where.add(ExtraWhere(where, params), AND) + if tables: + self.extra_tables += tuple(tables) + if order_by: + self.extra_order_by = order_by + + def clear_deferred_loading(self): + """Remove any fields from the deferred loading set.""" + self.deferred_loading = (frozenset(), True) + + def add_deferred_loading(self, field_names): + """ + Add the given list of model field names to the set of fields to + exclude from loading from the database when automatic column selection + is done. Add the new field names to any existing field names that + are deferred (or removed from any existing field names that are marked + as the only ones for immediate loading). + """ + # Fields on related models are stored in the literal double-underscore + # format, so that we can use a set datastructure. We do the foo__bar + # splitting and handling when computing the SQL column names (as part of + # get_columns()). + existing, defer = self.deferred_loading + if defer: + # Add to existing deferred names. + self.deferred_loading = existing.union(field_names), True + else: + # Remove names from the set of any existing "immediate load" names. + if new_existing := existing.difference(field_names): + self.deferred_loading = new_existing, False + else: + self.clear_deferred_loading() + if new_only := set(field_names).difference(existing): + self.deferred_loading = new_only, True + + def add_immediate_loading(self, field_names): + """ + Add the given list of model field names to the set of fields to + retrieve when the SQL is executed ("immediate loading" fields). The + field names replace any existing immediate loading field names. If + there are field names already specified for deferred loading, remove + those names from the new field_names before storing the new names + for immediate loading. (That is, immediate loading overrides any + existing immediate values, but respects existing deferrals.) + """ + existing, defer = self.deferred_loading + field_names = set(field_names) + if "pk" in field_names: + field_names.remove("pk") + field_names.add(self.get_meta().pk.name) + + if defer: + # Remove any existing deferred names from the current set before + # setting the new names. + self.deferred_loading = field_names.difference(existing), False + else: + # Replace any existing "immediate load" field names. + self.deferred_loading = frozenset(field_names), False + + def set_annotation_mask(self, names): + """Set the mask of annotations that will be returned by the SELECT.""" + if names is None: + self.annotation_select_mask = None + else: + self.annotation_select_mask = list(dict.fromkeys(names)) + self._annotation_select_cache = None + + def append_annotation_mask(self, names): + if self.annotation_select_mask is not None: + self.set_annotation_mask((*self.annotation_select_mask, *names)) + + def set_extra_mask(self, names): + """ + Set the mask of extra select items that will be returned by SELECT. + Don't remove them from the Query since they might be used later. + """ + if names is None: + self.extra_select_mask = None + else: + self.extra_select_mask = set(names) + self._extra_select_cache = None + + def set_values(self, fields): + self.select_related = False + self.clear_deferred_loading() + self.clear_select_fields() + self.has_select_fields = True + + if fields: + field_names = [] + extra_names = [] + annotation_names = [] + if not self.extra and not self.annotations: + # Shortcut - if there are no extra or annotations, then + # the values() clause must be just field names. + field_names = list(fields) + else: + self.default_cols = False + for f in fields: + if f in self.extra_select: + extra_names.append(f) + elif f in self.annotation_select: + annotation_names.append(f) + elif f in self.annotations: + raise FieldError( + f"Cannot select the '{f}' alias. Use annotate() to " + "promote it." + ) + else: + # Call `names_to_path` to ensure a FieldError including + # annotations about to be masked as valid choices if + # `f` is not resolvable. + if self.annotation_select: + self.names_to_path(f.split(LOOKUP_SEP), self.model._meta) + field_names.append(f) + self.set_extra_mask(extra_names) + self.set_annotation_mask(annotation_names) + selected = frozenset(field_names + extra_names + annotation_names) + else: + field_names = [f.attname for f in self.model._meta.concrete_fields] + selected = frozenset(field_names) + # Selected annotations must be known before setting the GROUP BY + # clause. + if self.group_by is True: + self.add_fields( + (f.attname for f in self.model._meta.concrete_fields), False + ) + # Disable GROUP BY aliases to avoid orphaning references to the + # SELECT clause which is about to be cleared. + self.set_group_by(allow_aliases=False) + self.clear_select_fields() + elif self.group_by: + # Resolve GROUP BY annotation references if they are not part of + # the selected fields anymore. + group_by = [] + for expr in self.group_by: + if isinstance(expr, Ref) and expr.refs not in selected: + expr = self.annotations[expr.refs] + group_by.append(expr) + self.group_by = tuple(group_by) + + self.values_select = tuple(field_names) + self.add_fields(field_names, True) + + @property + def annotation_select(self): + """ + Return the dictionary of aggregate columns that are not masked and + should be used in the SELECT clause. Cache this result for performance. + """ + if self._annotation_select_cache is not None: + return self._annotation_select_cache + elif not self.annotations: + return {} + elif self.annotation_select_mask is not None: + self._annotation_select_cache = { + k: self.annotations[k] + for k in self.annotation_select_mask + if k in self.annotations + } + return self._annotation_select_cache + else: + return self.annotations + + @property + def extra_select(self): + if self._extra_select_cache is not None: + return self._extra_select_cache + if not self.extra: + return {} + elif self.extra_select_mask is not None: + self._extra_select_cache = { + k: v for k, v in self.extra.items() if k in self.extra_select_mask + } + return self._extra_select_cache + else: + return self.extra + + def trim_start(self, names_with_path): + """ + Trim joins from the start of the join path. The candidates for trim + are the PathInfos in names_with_path structure that are m2m joins. + + Also set the select column so the start matches the join. + + This method is meant to be used for generating the subquery joins & + cols in split_exclude(). + + Return a lookup usable for doing outerq.filter(lookup=self) and a + boolean indicating if the joins in the prefix contain a LEFT OUTER join. + _""" + all_paths = [] + for _, paths in names_with_path: + all_paths.extend(paths) + contains_louter = False + # Trim and operate only on tables that were generated for + # the lookup part of the query. That is, avoid trimming + # joins generated for F() expressions. + lookup_tables = [ + t for t in self.alias_map if t in self._lookup_joins or t == self.base_table + ] + for trimmed_paths, path in enumerate(all_paths): + if path.m2m: + break + if self.alias_map[lookup_tables[trimmed_paths + 1]].join_type == LOUTER: + contains_louter = True + alias = lookup_tables[trimmed_paths] + self.unref_alias(alias) + # The path.join_field is a Rel, lets get the other side's field + join_field = path.join_field.field + # Build the filter prefix. + paths_in_prefix = trimmed_paths + trimmed_prefix = [] + for name, path in names_with_path: + if paths_in_prefix - len(path) < 0: + break + trimmed_prefix.append(name) + paths_in_prefix -= len(path) + trimmed_prefix.append(join_field.foreign_related_fields[0].name) + trimmed_prefix = LOOKUP_SEP.join(trimmed_prefix) + # Lets still see if we can trim the first join from the inner query + # (that is, self). We can't do this for: + # - LEFT JOINs because we would miss those rows that have nothing on + # the outer side, + # - INNER JOINs from filtered relations because we would miss their + # filters. + first_join = self.alias_map[lookup_tables[trimmed_paths + 1]] + if first_join.join_type != LOUTER and not first_join.filtered_relation: + select_fields = [r[0] for r in join_field.related_fields] + select_alias = lookup_tables[trimmed_paths + 1] + self.unref_alias(lookup_tables[trimmed_paths]) + extra_restriction = join_field.get_extra_restriction( + None, lookup_tables[trimmed_paths + 1] + ) + if extra_restriction: + self.where.add(extra_restriction, AND) + else: + # TODO: It might be possible to trim more joins from the start of the + # inner query if it happens to have a longer join chain containing the + # values in select_fields. Lets punt this one for now. + select_fields = [r[1] for r in join_field.related_fields] + select_alias = lookup_tables[trimmed_paths] + # The found starting point is likely a join_class instead of a + # base_table_class reference. But the first entry in the query's FROM + # clause must not be a JOIN. + for table in self.alias_map: + if self.alias_refcount[table] > 0: + self.alias_map[table] = self.base_table_class( + self.alias_map[table].table_name, + table, + ) + break + self.set_select([f.get_col(select_alias) for f in select_fields]) + return trimmed_prefix, contains_louter + + def is_nullable(self, field): + """ + Check if the given field should be treated as nullable. + + Some backends treat '' as null and Django treats such fields as + nullable for those backends. In such situations field.null can be + False even if we should treat the field as nullable. + """ + # We need to use DEFAULT_DB_ALIAS here, as QuerySet does not have + # (nor should it have) knowledge of which connection is going to be + # used. The proper fix would be to defer all decisions where + # is_nullable() is needed to the compiler stage, but that is not easy + # to do currently. + return field.null or ( + field.empty_strings_allowed + and connections[DEFAULT_DB_ALIAS].features.interprets_empty_strings_as_nulls + ) + + +def get_order_dir(field, default="ASC"): + """ + Return the field name and direction for an order specification. For + example, '-foo' is returned as ('foo', 'DESC'). + + The 'default' param is used to indicate which way no prefix (or a '+' + prefix) should sort. The '-' prefix always sorts the opposite way. + """ + dirn = ORDER_DIR[default] + if field[0] == "-": + return field[1:], dirn[1] + return field, dirn[0] + + +class JoinPromoter: + """ + A class to abstract away join promotion problems for complex filter + conditions. + """ + + def __init__(self, connector, num_children, negated): + self.connector = connector + self.negated = negated + if self.negated: + if connector == AND: + self.effective_connector = OR + else: + self.effective_connector = AND + else: + self.effective_connector = self.connector + self.num_children = num_children + # Maps of table alias to how many times it is seen as required for + # inner and/or outer joins. + self.votes = Counter() + + def __repr__(self): + return ( + f"{self.__class__.__qualname__}(connector={self.connector!r}, " + f"num_children={self.num_children!r}, negated={self.negated!r})" + ) + + def add_votes(self, votes): + """ + Add single vote per item to self.votes. Parameter can be any + iterable. + """ + self.votes.update(votes) + + def update_join_types(self, query): + """ + Change join types so that the generated query is as efficient as + possible, but still correct. So, change as many joins as possible + to INNER, but don't make OUTER joins INNER if that could remove + results from the query. + """ + to_promote = set() + to_demote = set() + # The effective_connector is used so that NOT (a AND b) is treated + # similarly to (a OR b) for join promotion. + for table, votes in self.votes.items(): + # We must use outer joins in OR case when the join isn't contained + # in all of the joins. Otherwise the INNER JOIN itself could remove + # valid results. Consider the case where a model with rel_a and + # rel_b relations is queried with rel_a__col=1 | rel_b__col=2. Now, + # if rel_a join doesn't produce any results is null (for example + # reverse foreign key or null value in direct foreign key), and + # there is a matching row in rel_b with col=2, then an INNER join + # to rel_a would remove a valid match from the query. So, we need + # to promote any existing INNER to LOUTER (it is possible this + # promotion in turn will be demoted later on). + if self.effective_connector == OR and votes < self.num_children: + to_promote.add(table) + # If connector is AND and there is a filter that can match only + # when there is a joinable row, then use INNER. For example, in + # rel_a__col=1 & rel_b__col=2, if either of the rels produce NULL + # as join output, then the col=1 or col=2 can't match (as + # NULL=anything is always false). + # For the OR case, if all children voted for a join to be inner, + # then we can use INNER for the join. For example: + # (rel_a__col__icontains=Alex | rel_a__col__icontains=Russell) + # then if rel_a doesn't produce any rows, the whole condition + # can't match. Hence we can safely use INNER join. + if self.effective_connector == AND or ( + self.effective_connector == OR and votes == self.num_children + ): + to_demote.add(table) + # Finally, what happens in cases where we have: + # (rel_a__col=1|rel_b__col=2) & rel_a__col__gte=0 + # Now, we first generate the OR clause, and promote joins for it + # in the first if branch above. Both rel_a and rel_b are promoted + # to LOUTER joins. After that we do the AND case. The OR case + # voted no inner joins but the rel_a__col__gte=0 votes inner join + # for rel_a. We demote it back to INNER join (in AND case a single + # vote is enough). The demotion is OK, if rel_a doesn't produce + # rows, then the rel_a__col__gte=0 clause can't be true, and thus + # the whole clause must be false. So, it is safe to use INNER + # join. + # Note that in this example we could just as well have the __gte + # clause and the OR clause swapped. Or we could replace the __gte + # clause with an OR clause containing rel_a__col=1|rel_a__col=2, + # and again we could safely demote to INNER. + query.promote_joins(to_promote) + query.demote_joins(to_demote) + return to_demote diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/sql/subqueries.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/sql/subqueries.py new file mode 100644 index 0000000..f639eb8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/sql/subqueries.py @@ -0,0 +1,174 @@ +""" +Query subclasses which provide extra functionality beyond simple data retrieval. +""" + +from django.core.exceptions import FieldError +from django.db.models.sql.constants import CURSOR, GET_ITERATOR_CHUNK_SIZE, NO_RESULTS +from django.db.models.sql.query import Query + +__all__ = ["DeleteQuery", "UpdateQuery", "InsertQuery", "AggregateQuery"] + + +class DeleteQuery(Query): + """A DELETE SQL query.""" + + compiler = "SQLDeleteCompiler" + + def do_query(self, table, where, using): + self.alias_map = {table: self.alias_map[table]} + self.where = where + cursor = self.get_compiler(using).execute_sql(CURSOR) + if cursor: + with cursor: + return cursor.rowcount + return 0 + + def delete_batch(self, pk_list, using): + """ + Set up and execute delete queries for all the objects in pk_list. + + More than one physical query may be executed if there are a + lot of values in pk_list. + """ + # number of objects deleted + num_deleted = 0 + field = self.get_meta().pk + for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE): + self.clear_where() + self.add_filter( + f"{field.attname}__in", + pk_list[offset : offset + GET_ITERATOR_CHUNK_SIZE], + ) + num_deleted += self.do_query( + self.get_meta().db_table, self.where, using=using + ) + return num_deleted + + +class UpdateQuery(Query): + """An UPDATE SQL query.""" + + compiler = "SQLUpdateCompiler" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._setup_query() + + def _setup_query(self): + """ + Run on initialization and at the end of chaining. Any attributes that + would normally be set in __init__() should go here instead. + """ + self.values = [] + self.related_ids = None + self.related_updates = {} + + def clone(self): + obj = super().clone() + obj.related_updates = self.related_updates.copy() + return obj + + def update_batch(self, pk_list, values, using): + self.add_update_values(values) + for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE): + self.clear_where() + self.add_filter( + "pk__in", pk_list[offset : offset + GET_ITERATOR_CHUNK_SIZE] + ) + self.get_compiler(using).execute_sql(NO_RESULTS) + + def add_update_values(self, values): + """ + Convert a dictionary of field name to value mappings into an update + query. This is the entry point for the public update() method on + querysets. + """ + values_seq = [] + for name, val in values.items(): + field = self.get_meta().get_field(name) + direct = ( + not (field.auto_created and not field.concrete) or not field.concrete + ) + model = field.model._meta.concrete_model + if not direct or (field.is_relation and field.many_to_many): + raise FieldError( + "Cannot update model field %r (only non-relations and " + "foreign keys permitted)." % field + ) + if model is not self.get_meta().concrete_model: + self.add_related_update(model, field, val) + continue + values_seq.append((field, model, val)) + return self.add_update_fields(values_seq) + + def add_update_fields(self, values_seq): + """ + Append a sequence of (field, model, value) triples to the internal list + that will be used to generate the UPDATE query. Might be more usefully + called add_update_targets() to hint at the extra information here. + """ + for field, model, val in values_seq: + # Omit generated fields. + if field.generated: + continue + if hasattr(val, "resolve_expression"): + # Resolve expressions here so that annotations are no longer needed + val = val.resolve_expression(self, allow_joins=False, for_save=True) + self.values.append((field, model, val)) + + def add_related_update(self, model, field, value): + """ + Add (name, value) to an update query for an ancestor model. + + Update are coalesced so that only one update query per ancestor is run. + """ + self.related_updates.setdefault(model, []).append((field, None, value)) + + def get_related_updates(self): + """ + Return a list of query objects: one for each update required to an + ancestor model. Each query will have the same filtering conditions as + the current query but will only update a single table. + """ + if not self.related_updates: + return [] + result = [] + for model, values in self.related_updates.items(): + query = UpdateQuery(model) + query.values = values + if self.related_ids is not None: + query.add_filter("pk__in", self.related_ids[model]) + result.append(query) + return result + + +class InsertQuery(Query): + compiler = "SQLInsertCompiler" + + def __init__( + self, *args, on_conflict=None, update_fields=None, unique_fields=None, **kwargs + ): + super().__init__(*args, **kwargs) + self.fields = [] + self.objs = [] + self.on_conflict = on_conflict + self.update_fields = update_fields or [] + self.unique_fields = unique_fields or [] + + def insert_values(self, fields, objs, raw=False): + self.fields = fields + self.objs = objs + self.raw = raw + + +class AggregateQuery(Query): + """ + Take another query as a parameter to the FROM clause and only select the + elements in the provided list. + """ + + compiler = "SQLAggregateCompiler" + + def __init__(self, model, inner_query): + self.inner_query = inner_query + super().__init__(model) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/sql/where.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/sql/where.py new file mode 100644 index 0000000..2f23a29 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/sql/where.py @@ -0,0 +1,360 @@ +""" +Code to manage the creation and SQL rendering of 'where' constraints. +""" +import operator +from functools import reduce + +from django.core.exceptions import EmptyResultSet, FullResultSet +from django.db.models.expressions import Case, When +from django.db.models.functions import Mod +from django.db.models.lookups import Exact +from django.utils import tree +from django.utils.functional import cached_property + +# Connection types +AND = "AND" +OR = "OR" +XOR = "XOR" + + +class WhereNode(tree.Node): + """ + An SQL WHERE clause. + + The class is tied to the Query class that created it (in order to create + the correct SQL). + + A child is usually an expression producing boolean values. Most likely the + expression is a Lookup instance. + + However, a child could also be any class with as_sql() and either + relabeled_clone() method or relabel_aliases() and clone() methods and + contains_aggregate attribute. + """ + + default = AND + resolved = False + conditional = True + + def split_having_qualify(self, negated=False, must_group_by=False): + """ + Return three possibly None nodes: one for those parts of self that + should be included in the WHERE clause, one for those parts of self + that must be included in the HAVING clause, and one for those parts + that refer to window functions. + """ + if not self.contains_aggregate and not self.contains_over_clause: + return self, None, None + in_negated = negated ^ self.negated + # Whether or not children must be connected in the same filtering + # clause (WHERE > HAVING > QUALIFY) to maintain logical semantic. + must_remain_connected = ( + (in_negated and self.connector == AND) + or (not in_negated and self.connector == OR) + or self.connector == XOR + ) + if ( + must_remain_connected + and self.contains_aggregate + and not self.contains_over_clause + ): + # It's must cheaper to short-circuit and stash everything in the + # HAVING clause than split children if possible. + return None, self, None + where_parts = [] + having_parts = [] + qualify_parts = [] + for c in self.children: + if hasattr(c, "split_having_qualify"): + where_part, having_part, qualify_part = c.split_having_qualify( + in_negated, must_group_by + ) + if where_part is not None: + where_parts.append(where_part) + if having_part is not None: + having_parts.append(having_part) + if qualify_part is not None: + qualify_parts.append(qualify_part) + elif c.contains_over_clause: + qualify_parts.append(c) + elif c.contains_aggregate: + having_parts.append(c) + else: + where_parts.append(c) + if must_remain_connected and qualify_parts: + # Disjunctive heterogeneous predicates can be pushed down to + # qualify as long as no conditional aggregation is involved. + if not where_parts or (where_parts and not must_group_by): + return None, None, self + elif where_parts: + # In theory this should only be enforced when dealing with + # where_parts containing predicates against multi-valued + # relationships that could affect aggregation results but this + # is complex to infer properly. + raise NotImplementedError( + "Heterogeneous disjunctive predicates against window functions are " + "not implemented when performing conditional aggregation." + ) + where_node = ( + self.create(where_parts, self.connector, self.negated) + if where_parts + else None + ) + having_node = ( + self.create(having_parts, self.connector, self.negated) + if having_parts + else None + ) + qualify_node = ( + self.create(qualify_parts, self.connector, self.negated) + if qualify_parts + else None + ) + return where_node, having_node, qualify_node + + def as_sql(self, compiler, connection): + """ + Return the SQL version of the where clause and the value to be + substituted in. Return '', [] if this node matches everything, + None, [] if this node is empty, and raise EmptyResultSet if this + node can't match anything. + """ + result = [] + result_params = [] + if self.connector == AND: + full_needed, empty_needed = len(self.children), 1 + else: + full_needed, empty_needed = 1, len(self.children) + + if self.connector == XOR and not connection.features.supports_logical_xor: + # Convert if the database doesn't support XOR: + # a XOR b XOR c XOR ... + # to: + # (a OR b OR c OR ...) AND MOD(a + b + c + ..., 2) == 1 + # The result of an n-ary XOR is true when an odd number of operands + # are true. + lhs = self.__class__(self.children, OR) + rhs_sum = reduce( + operator.add, + (Case(When(c, then=1), default=0) for c in self.children), + ) + if len(self.children) > 2: + rhs_sum = Mod(rhs_sum, 2) + rhs = Exact(1, rhs_sum) + return self.__class__([lhs, rhs], AND, self.negated).as_sql( + compiler, connection + ) + + for child in self.children: + try: + sql, params = compiler.compile(child) + except EmptyResultSet: + empty_needed -= 1 + except FullResultSet: + full_needed -= 1 + else: + if sql: + result.append(sql) + result_params.extend(params) + else: + full_needed -= 1 + # Check if this node matches nothing or everything. + # First check the amount of full nodes and empty nodes + # to make this node empty/full. + # Now, check if this node is full/empty using the + # counts. + if empty_needed == 0: + if self.negated: + raise FullResultSet + else: + raise EmptyResultSet + if full_needed == 0: + if self.negated: + raise EmptyResultSet + else: + raise FullResultSet + conn = " %s " % self.connector + sql_string = conn.join(result) + if not sql_string: + raise FullResultSet + if self.negated: + # Some backends (Oracle at least) need parentheses around the inner + # SQL in the negated case, even if the inner SQL contains just a + # single expression. + sql_string = "NOT (%s)" % sql_string + elif len(result) > 1 or self.resolved: + sql_string = "(%s)" % sql_string + return sql_string, result_params + + def get_group_by_cols(self): + cols = [] + for child in self.children: + cols.extend(child.get_group_by_cols()) + return cols + + def get_source_expressions(self): + return self.children[:] + + def set_source_expressions(self, children): + assert len(children) == len(self.children) + self.children = children + + def relabel_aliases(self, change_map): + """ + Relabel the alias values of any children. 'change_map' is a dictionary + mapping old (current) alias values to the new values. + """ + for pos, child in enumerate(self.children): + if hasattr(child, "relabel_aliases"): + # For example another WhereNode + child.relabel_aliases(change_map) + elif hasattr(child, "relabeled_clone"): + self.children[pos] = child.relabeled_clone(change_map) + + def clone(self): + clone = self.create(connector=self.connector, negated=self.negated) + for child in self.children: + if hasattr(child, "clone"): + child = child.clone() + clone.children.append(child) + return clone + + def relabeled_clone(self, change_map): + clone = self.clone() + clone.relabel_aliases(change_map) + return clone + + def replace_expressions(self, replacements): + if replacement := replacements.get(self): + return replacement + clone = self.create(connector=self.connector, negated=self.negated) + for child in self.children: + clone.children.append(child.replace_expressions(replacements)) + return clone + + def get_refs(self): + refs = set() + for child in self.children: + refs |= child.get_refs() + return refs + + @classmethod + def _contains_aggregate(cls, obj): + if isinstance(obj, tree.Node): + return any(cls._contains_aggregate(c) for c in obj.children) + return obj.contains_aggregate + + @cached_property + def contains_aggregate(self): + return self._contains_aggregate(self) + + @classmethod + def _contains_over_clause(cls, obj): + if isinstance(obj, tree.Node): + return any(cls._contains_over_clause(c) for c in obj.children) + return obj.contains_over_clause + + @cached_property + def contains_over_clause(self): + return self._contains_over_clause(self) + + @property + def is_summary(self): + return any(child.is_summary for child in self.children) + + @staticmethod + def _resolve_leaf(expr, query, *args, **kwargs): + if hasattr(expr, "resolve_expression"): + expr = expr.resolve_expression(query, *args, **kwargs) + return expr + + @classmethod + def _resolve_node(cls, node, query, *args, **kwargs): + if hasattr(node, "children"): + for child in node.children: + cls._resolve_node(child, query, *args, **kwargs) + if hasattr(node, "lhs"): + node.lhs = cls._resolve_leaf(node.lhs, query, *args, **kwargs) + if hasattr(node, "rhs"): + node.rhs = cls._resolve_leaf(node.rhs, query, *args, **kwargs) + + def resolve_expression(self, *args, **kwargs): + clone = self.clone() + clone._resolve_node(clone, *args, **kwargs) + clone.resolved = True + return clone + + @cached_property + def output_field(self): + from django.db.models import BooleanField + + return BooleanField() + + @property + def _output_field_or_none(self): + return self.output_field + + def select_format(self, compiler, sql, params): + # Wrap filters with a CASE WHEN expression if a database backend + # (e.g. Oracle) doesn't support boolean expression in SELECT or GROUP + # BY list. + if not compiler.connection.features.supports_boolean_expr_in_select_clause: + sql = f"CASE WHEN {sql} THEN 1 ELSE 0 END" + return sql, params + + def get_db_converters(self, connection): + return self.output_field.get_db_converters(connection) + + def get_lookup(self, lookup): + return self.output_field.get_lookup(lookup) + + def leaves(self): + for child in self.children: + if isinstance(child, WhereNode): + yield from child.leaves() + else: + yield child + + +class NothingNode: + """A node that matches nothing.""" + + contains_aggregate = False + contains_over_clause = False + + def as_sql(self, compiler=None, connection=None): + raise EmptyResultSet + + +class ExtraWhere: + # The contents are a black box - assume no aggregates or windows are used. + contains_aggregate = False + contains_over_clause = False + + def __init__(self, sqls, params): + self.sqls = sqls + self.params = params + + def as_sql(self, compiler=None, connection=None): + sqls = ["(%s)" % sql for sql in self.sqls] + return " AND ".join(sqls), list(self.params or ()) + + +class SubqueryConstraint: + # Even if aggregates or windows would be used in a subquery, + # the outer query isn't interested about those. + contains_aggregate = False + contains_over_clause = False + + def __init__(self, alias, columns, targets, query_object): + self.alias = alias + self.columns = columns + self.targets = targets + query_object.clear_ordering(clear_default=True) + self.query_object = query_object + + def as_sql(self, compiler, connection): + query = self.query_object + query.set_values(self.targets) + query_compiler = query.get_compiler(connection=connection) + return query_compiler.as_subquery_condition(self.alias, self.columns, compiler) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/utils.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/utils.py new file mode 100644 index 0000000..c6cb5ef --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/models/utils.py @@ -0,0 +1,69 @@ +import functools +from collections import namedtuple + + +def make_model_tuple(model): + """ + Take a model or a string of the form "app_label.ModelName" and return a + corresponding ("app_label", "modelname") tuple. If a tuple is passed in, + assume it's a valid model tuple already and return it unchanged. + """ + try: + if isinstance(model, tuple): + model_tuple = model + elif isinstance(model, str): + app_label, model_name = model.split(".") + model_tuple = app_label, model_name.lower() + else: + model_tuple = model._meta.app_label, model._meta.model_name + assert len(model_tuple) == 2 + return model_tuple + except (ValueError, AssertionError): + raise ValueError( + "Invalid model reference '%s'. String model references " + "must be of the form 'app_label.ModelName'." % model + ) + + +def resolve_callables(mapping): + """ + Generate key/value pairs for the given mapping where the values are + evaluated if they're callable. + """ + for k, v in mapping.items(): + yield k, v() if callable(v) else v + + +def unpickle_named_row(names, values): + return create_namedtuple_class(*names)(*values) + + +@functools.lru_cache +def create_namedtuple_class(*names): + # Cache type() with @lru_cache since it's too slow to be called for every + # QuerySet evaluation. + def __reduce__(self): + return unpickle_named_row, (names, tuple(self)) + + return type( + "Row", + (namedtuple("Row", names),), + {"__reduce__": __reduce__, "__slots__": ()}, + ) + + +class AltersData: + """ + Make subclasses preserve the alters_data attribute on overridden methods. + """ + + def __init_subclass__(cls, **kwargs): + for fn_name, fn in vars(cls).items(): + if callable(fn) and not hasattr(fn, "alters_data"): + for base in cls.__bases__: + if base_fn := getattr(base, fn_name, None): + if hasattr(base_fn, "alters_data"): + fn.alters_data = base_fn.alters_data + break + + super().__init_subclass__(**kwargs) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/transaction.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/transaction.py new file mode 100644 index 0000000..4150cbc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/transaction.py @@ -0,0 +1,340 @@ +from contextlib import ContextDecorator, contextmanager + +from django.db import ( + DEFAULT_DB_ALIAS, + DatabaseError, + Error, + ProgrammingError, + connections, +) + + +class TransactionManagementError(ProgrammingError): + """Transaction management is used improperly.""" + + pass + + +def get_connection(using=None): + """ + Get a database connection by name, or the default database connection + if no name is provided. This is a private API. + """ + if using is None: + using = DEFAULT_DB_ALIAS + return connections[using] + + +def get_autocommit(using=None): + """Get the autocommit status of the connection.""" + return get_connection(using).get_autocommit() + + +def set_autocommit(autocommit, using=None): + """Set the autocommit status of the connection.""" + return get_connection(using).set_autocommit(autocommit) + + +def commit(using=None): + """Commit a transaction.""" + get_connection(using).commit() + + +def rollback(using=None): + """Roll back a transaction.""" + get_connection(using).rollback() + + +def savepoint(using=None): + """ + Create a savepoint (if supported and required by the backend) inside the + current transaction. Return an identifier for the savepoint that will be + used for the subsequent rollback or commit. + """ + return get_connection(using).savepoint() + + +def savepoint_rollback(sid, using=None): + """ + Roll back the most recent savepoint (if one exists). Do nothing if + savepoints are not supported. + """ + get_connection(using).savepoint_rollback(sid) + + +def savepoint_commit(sid, using=None): + """ + Commit the most recent savepoint (if one exists). Do nothing if + savepoints are not supported. + """ + get_connection(using).savepoint_commit(sid) + + +def clean_savepoints(using=None): + """ + Reset the counter used to generate unique savepoint ids in this thread. + """ + get_connection(using).clean_savepoints() + + +def get_rollback(using=None): + """Get the "needs rollback" flag -- for *advanced use* only.""" + return get_connection(using).get_rollback() + + +def set_rollback(rollback, using=None): + """ + Set or unset the "needs rollback" flag -- for *advanced use* only. + + When `rollback` is `True`, trigger a rollback when exiting the innermost + enclosing atomic block that has `savepoint=True` (that's the default). Use + this to force a rollback without raising an exception. + + When `rollback` is `False`, prevent such a rollback. Use this only after + rolling back to a known-good state! Otherwise, you break the atomic block + and data corruption may occur. + """ + return get_connection(using).set_rollback(rollback) + + +@contextmanager +def mark_for_rollback_on_error(using=None): + """ + Internal low-level utility to mark a transaction as "needs rollback" when + an exception is raised while not enforcing the enclosed block to be in a + transaction. This is needed by Model.save() and friends to avoid starting a + transaction when in autocommit mode and a single query is executed. + + It's equivalent to: + + connection = get_connection(using) + if connection.get_autocommit(): + yield + else: + with transaction.atomic(using=using, savepoint=False): + yield + + but it uses low-level utilities to avoid performance overhead. + """ + try: + yield + except Exception as exc: + connection = get_connection(using) + if connection.in_atomic_block: + connection.needs_rollback = True + connection.rollback_exc = exc + raise + + +def on_commit(func, using=None, robust=False): + """ + Register `func` to be called when the current transaction is committed. + If the current transaction is rolled back, `func` will not be called. + """ + get_connection(using).on_commit(func, robust) + + +################################# +# Decorators / context managers # +################################# + + +class Atomic(ContextDecorator): + """ + Guarantee the atomic execution of a given block. + + An instance can be used either as a decorator or as a context manager. + + When it's used as a decorator, __call__ wraps the execution of the + decorated function in the instance itself, used as a context manager. + + When it's used as a context manager, __enter__ creates a transaction or a + savepoint, depending on whether a transaction is already in progress, and + __exit__ commits the transaction or releases the savepoint on normal exit, + and rolls back the transaction or to the savepoint on exceptions. + + It's possible to disable the creation of savepoints if the goal is to + ensure that some code runs within a transaction without creating overhead. + + A stack of savepoints identifiers is maintained as an attribute of the + connection. None denotes the absence of a savepoint. + + This allows reentrancy even if the same AtomicWrapper is reused. For + example, it's possible to define `oa = atomic('other')` and use `@oa` or + `with oa:` multiple times. + + Since database connections are thread-local, this is thread-safe. + + An atomic block can be tagged as durable. In this case, raise a + RuntimeError if it's nested within another atomic block. This guarantees + that database changes in a durable block are committed to the database when + the block exists without error. + + This is a private API. + """ + + def __init__(self, using, savepoint, durable): + self.using = using + self.savepoint = savepoint + self.durable = durable + self._from_testcase = False + + def __enter__(self): + connection = get_connection(self.using) + + if ( + self.durable + and connection.atomic_blocks + and not connection.atomic_blocks[-1]._from_testcase + ): + raise RuntimeError( + "A durable atomic block cannot be nested within another " + "atomic block." + ) + if not connection.in_atomic_block: + # Reset state when entering an outermost atomic block. + connection.commit_on_exit = True + connection.needs_rollback = False + if not connection.get_autocommit(): + # Pretend we're already in an atomic block to bypass the code + # that disables autocommit to enter a transaction, and make a + # note to deal with this case in __exit__. + connection.in_atomic_block = True + connection.commit_on_exit = False + + if connection.in_atomic_block: + # We're already in a transaction; create a savepoint, unless we + # were told not to or we're already waiting for a rollback. The + # second condition avoids creating useless savepoints and prevents + # overwriting needs_rollback until the rollback is performed. + if self.savepoint and not connection.needs_rollback: + sid = connection.savepoint() + connection.savepoint_ids.append(sid) + else: + connection.savepoint_ids.append(None) + else: + connection.set_autocommit( + False, force_begin_transaction_with_broken_autocommit=True + ) + connection.in_atomic_block = True + + if connection.in_atomic_block: + connection.atomic_blocks.append(self) + + def __exit__(self, exc_type, exc_value, traceback): + connection = get_connection(self.using) + + if connection.in_atomic_block: + connection.atomic_blocks.pop() + + if connection.savepoint_ids: + sid = connection.savepoint_ids.pop() + else: + # Prematurely unset this flag to allow using commit or rollback. + connection.in_atomic_block = False + + try: + if connection.closed_in_transaction: + # The database will perform a rollback by itself. + # Wait until we exit the outermost block. + pass + + elif exc_type is None and not connection.needs_rollback: + if connection.in_atomic_block: + # Release savepoint if there is one + if sid is not None: + try: + connection.savepoint_commit(sid) + except DatabaseError: + try: + connection.savepoint_rollback(sid) + # The savepoint won't be reused. Release it to + # minimize overhead for the database server. + connection.savepoint_commit(sid) + except Error: + # If rolling back to a savepoint fails, mark for + # rollback at a higher level and avoid shadowing + # the original exception. + connection.needs_rollback = True + raise + else: + # Commit transaction + try: + connection.commit() + except DatabaseError: + try: + connection.rollback() + except Error: + # An error during rollback means that something + # went wrong with the connection. Drop it. + connection.close() + raise + else: + # This flag will be set to True again if there isn't a savepoint + # allowing to perform the rollback at this level. + connection.needs_rollback = False + if connection.in_atomic_block: + # Roll back to savepoint if there is one, mark for rollback + # otherwise. + if sid is None: + connection.needs_rollback = True + else: + try: + connection.savepoint_rollback(sid) + # The savepoint won't be reused. Release it to + # minimize overhead for the database server. + connection.savepoint_commit(sid) + except Error: + # If rolling back to a savepoint fails, mark for + # rollback at a higher level and avoid shadowing + # the original exception. + connection.needs_rollback = True + else: + # Roll back transaction + try: + connection.rollback() + except Error: + # An error during rollback means that something + # went wrong with the connection. Drop it. + connection.close() + + finally: + # Outermost block exit when autocommit was enabled. + if not connection.in_atomic_block: + if connection.closed_in_transaction: + connection.connection = None + else: + connection.set_autocommit(True) + # Outermost block exit when autocommit was disabled. + elif not connection.savepoint_ids and not connection.commit_on_exit: + if connection.closed_in_transaction: + connection.connection = None + else: + connection.in_atomic_block = False + + +def atomic(using=None, savepoint=True, durable=False): + # Bare decorator: @atomic -- although the first argument is called + # `using`, it's actually the function being decorated. + if callable(using): + return Atomic(DEFAULT_DB_ALIAS, savepoint, durable)(using) + # Decorator: @atomic(...) or context manager: with atomic(...): ... + else: + return Atomic(using, savepoint, durable) + + +def _non_atomic_requests(view, using): + try: + view._non_atomic_requests.add(using) + except AttributeError: + view._non_atomic_requests = {using} + return view + + +def non_atomic_requests(using=None): + if callable(using): + return _non_atomic_requests(using, DEFAULT_DB_ALIAS) + else: + if using is None: + using = DEFAULT_DB_ALIAS + return lambda view: _non_atomic_requests(view, using) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/utils.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/utils.py new file mode 100644 index 0000000..e45f1db --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/db/utils.py @@ -0,0 +1,278 @@ +import pkgutil +from importlib import import_module + +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured + +# For backwards compatibility with Django < 3.2 +from django.utils.connection import ConnectionDoesNotExist # NOQA: F401 +from django.utils.connection import BaseConnectionHandler +from django.utils.functional import cached_property +from django.utils.module_loading import import_string + +DEFAULT_DB_ALIAS = "default" +DJANGO_VERSION_PICKLE_KEY = "_django_version" + + +class Error(Exception): + pass + + +class InterfaceError(Error): + pass + + +class DatabaseError(Error): + pass + + +class DataError(DatabaseError): + pass + + +class OperationalError(DatabaseError): + pass + + +class IntegrityError(DatabaseError): + pass + + +class InternalError(DatabaseError): + pass + + +class ProgrammingError(DatabaseError): + pass + + +class NotSupportedError(DatabaseError): + pass + + +class DatabaseErrorWrapper: + """ + Context manager and decorator that reraises backend-specific database + exceptions using Django's common wrappers. + """ + + def __init__(self, wrapper): + """ + wrapper is a database wrapper. + + It must have a Database attribute defining PEP-249 exceptions. + """ + self.wrapper = wrapper + + def __enter__(self): + pass + + def __exit__(self, exc_type, exc_value, traceback): + if exc_type is None: + return + for dj_exc_type in ( + DataError, + OperationalError, + IntegrityError, + InternalError, + ProgrammingError, + NotSupportedError, + DatabaseError, + InterfaceError, + Error, + ): + db_exc_type = getattr(self.wrapper.Database, dj_exc_type.__name__) + if issubclass(exc_type, db_exc_type): + dj_exc_value = dj_exc_type(*exc_value.args) + # Only set the 'errors_occurred' flag for errors that may make + # the connection unusable. + if dj_exc_type not in (DataError, IntegrityError): + self.wrapper.errors_occurred = True + raise dj_exc_value.with_traceback(traceback) from exc_value + + def __call__(self, func): + # Note that we are intentionally not using @wraps here for performance + # reasons. Refs #21109. + def inner(*args, **kwargs): + with self: + return func(*args, **kwargs) + + return inner + + +def load_backend(backend_name): + """ + Return a database backend's "base" module given a fully qualified database + backend name, or raise an error if it doesn't exist. + """ + # This backend was renamed in Django 1.9. + if backend_name == "django.db.backends.postgresql_psycopg2": + backend_name = "django.db.backends.postgresql" + + try: + return import_module("%s.base" % backend_name) + except ImportError as e_user: + # The database backend wasn't found. Display a helpful error message + # listing all built-in database backends. + import django.db.backends + + builtin_backends = [ + name + for _, name, ispkg in pkgutil.iter_modules(django.db.backends.__path__) + if ispkg and name not in {"base", "dummy"} + ] + if backend_name not in ["django.db.backends.%s" % b for b in builtin_backends]: + backend_reprs = map(repr, sorted(builtin_backends)) + raise ImproperlyConfigured( + "%r isn't an available database backend or couldn't be " + "imported. Check the above exception. To use one of the " + "built-in backends, use 'django.db.backends.XXX', where XXX " + "is one of:\n" + " %s" % (backend_name, ", ".join(backend_reprs)) + ) from e_user + else: + # If there's some other error, this must be an error in Django + raise + + +class ConnectionHandler(BaseConnectionHandler): + settings_name = "DATABASES" + # Connections needs to still be an actual thread local, as it's truly + # thread-critical. Database backends should use @async_unsafe to protect + # their code from async contexts, but this will give those contexts + # separate connections in case it's needed as well. There's no cleanup + # after async contexts, though, so we don't allow that if we can help it. + thread_critical = True + + def configure_settings(self, databases): + databases = super().configure_settings(databases) + if databases == {}: + databases[DEFAULT_DB_ALIAS] = {"ENGINE": "django.db.backends.dummy"} + elif DEFAULT_DB_ALIAS not in databases: + raise ImproperlyConfigured( + f"You must define a '{DEFAULT_DB_ALIAS}' database." + ) + elif databases[DEFAULT_DB_ALIAS] == {}: + databases[DEFAULT_DB_ALIAS]["ENGINE"] = "django.db.backends.dummy" + + # Configure default settings. + for conn in databases.values(): + conn.setdefault("ATOMIC_REQUESTS", False) + conn.setdefault("AUTOCOMMIT", True) + conn.setdefault("ENGINE", "django.db.backends.dummy") + if conn["ENGINE"] == "django.db.backends." or not conn["ENGINE"]: + conn["ENGINE"] = "django.db.backends.dummy" + conn.setdefault("CONN_MAX_AGE", 0) + conn.setdefault("CONN_HEALTH_CHECKS", False) + conn.setdefault("OPTIONS", {}) + conn.setdefault("TIME_ZONE", None) + for setting in ["NAME", "USER", "PASSWORD", "HOST", "PORT"]: + conn.setdefault(setting, "") + + test_settings = conn.setdefault("TEST", {}) + default_test_settings = [ + ("CHARSET", None), + ("COLLATION", None), + ("MIGRATE", True), + ("MIRROR", None), + ("NAME", None), + ] + for key, value in default_test_settings: + test_settings.setdefault(key, value) + return databases + + @property + def databases(self): + # Maintained for backward compatibility as some 3rd party packages have + # made use of this private API in the past. It is no longer used within + # Django itself. + return self.settings + + def create_connection(self, alias): + db = self.settings[alias] + backend = load_backend(db["ENGINE"]) + return backend.DatabaseWrapper(db, alias) + + +class ConnectionRouter: + def __init__(self, routers=None): + """ + If routers is not specified, default to settings.DATABASE_ROUTERS. + """ + self._routers = routers + + @cached_property + def routers(self): + if self._routers is None: + self._routers = settings.DATABASE_ROUTERS + routers = [] + for r in self._routers: + if isinstance(r, str): + router = import_string(r)() + else: + router = r + routers.append(router) + return routers + + def _router_func(action): + def _route_db(self, model, **hints): + chosen_db = None + for router in self.routers: + try: + method = getattr(router, action) + except AttributeError: + # If the router doesn't have a method, skip to the next one. + pass + else: + chosen_db = method(model, **hints) + if chosen_db: + return chosen_db + instance = hints.get("instance") + if instance is not None and instance._state.db: + return instance._state.db + return DEFAULT_DB_ALIAS + + return _route_db + + db_for_read = _router_func("db_for_read") + db_for_write = _router_func("db_for_write") + + def allow_relation(self, obj1, obj2, **hints): + for router in self.routers: + try: + method = router.allow_relation + except AttributeError: + # If the router doesn't have a method, skip to the next one. + pass + else: + allow = method(obj1, obj2, **hints) + if allow is not None: + return allow + return obj1._state.db == obj2._state.db + + def allow_migrate(self, db, app_label, **hints): + for router in self.routers: + try: + method = router.allow_migrate + except AttributeError: + # If the router doesn't have a method, skip to the next one. + continue + + allow = method(db, app_label, **hints) + + if allow is not None: + return allow + return True + + def allow_migrate_model(self, db, model): + return self.allow_migrate( + db, + model._meta.app_label, + model_name=model._meta.model_name, + model=model, + ) + + def get_migratable_models(self, app_config, db, include_auto_created=False): + """Return app models allowed to be migrated on provided db.""" + models = app_config.get_models(include_auto_created=include_auto_created) + return [model for model in models if self.allow_migrate_model(db, model)] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/dispatch/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/dispatch/__init__.py new file mode 100644 index 0000000..a615f99 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/dispatch/__init__.py @@ -0,0 +1,9 @@ +"""Multi-consumer multi-producer dispatching mechanism + +Originally based on pydispatch (BSD) https://pypi.org/project/PyDispatcher/2.0.1/ +See license.txt for original license. + +Heavily modified for Django's purposes. +""" + +from django.dispatch.dispatcher import Signal, receiver # NOQA diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/dispatch/dispatcher.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/dispatch/dispatcher.py new file mode 100644 index 0000000..26ef09c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/dispatch/dispatcher.py @@ -0,0 +1,490 @@ +import asyncio +import logging +import threading +import weakref + +from asgiref.sync import async_to_sync, iscoroutinefunction, sync_to_async + +from django.utils.inspect import func_accepts_kwargs + +logger = logging.getLogger("django.dispatch") + + +def _make_id(target): + if hasattr(target, "__func__"): + return (id(target.__self__), id(target.__func__)) + return id(target) + + +NONE_ID = _make_id(None) + +# A marker for caching +NO_RECEIVERS = object() + + +class Signal: + """ + Base class for all signals + + Internal attributes: + + receivers + { receiverkey (id) : weakref(receiver) } + """ + + def __init__(self, use_caching=False): + """ + Create a new signal. + """ + self.receivers = [] + self.lock = threading.Lock() + self.use_caching = use_caching + # For convenience we create empty caches even if they are not used. + # A note about caching: if use_caching is defined, then for each + # distinct sender we cache the receivers that sender has in + # 'sender_receivers_cache'. The cache is cleaned when .connect() or + # .disconnect() is called and populated on send(). + self.sender_receivers_cache = weakref.WeakKeyDictionary() if use_caching else {} + self._dead_receivers = False + + def connect(self, receiver, sender=None, weak=True, dispatch_uid=None): + """ + Connect receiver to sender for signal. + + Arguments: + + receiver + A function or an instance method which is to receive signals. + Receivers must be hashable objects. Receivers can be + asynchronous. + + If weak is True, then receiver must be weak referenceable. + + Receivers must be able to accept keyword arguments. + + If a receiver is connected with a dispatch_uid argument, it + will not be added if another receiver was already connected + with that dispatch_uid. + + sender + The sender to which the receiver should respond. Must either be + a Python object, or None to receive events from any sender. + + weak + Whether to use weak references to the receiver. By default, the + module will attempt to use weak references to the receiver + objects. If this parameter is false, then strong references will + be used. + + dispatch_uid + An identifier used to uniquely identify a particular instance of + a receiver. This will usually be a string, though it may be + anything hashable. + """ + from django.conf import settings + + # If DEBUG is on, check that we got a good receiver + if settings.configured and settings.DEBUG: + if not callable(receiver): + raise TypeError("Signal receivers must be callable.") + # Check for **kwargs + if not func_accepts_kwargs(receiver): + raise ValueError( + "Signal receivers must accept keyword arguments (**kwargs)." + ) + + if dispatch_uid: + lookup_key = (dispatch_uid, _make_id(sender)) + else: + lookup_key = (_make_id(receiver), _make_id(sender)) + + is_async = iscoroutinefunction(receiver) + + if weak: + ref = weakref.ref + receiver_object = receiver + # Check for bound methods + if hasattr(receiver, "__self__") and hasattr(receiver, "__func__"): + ref = weakref.WeakMethod + receiver_object = receiver.__self__ + receiver = ref(receiver) + weakref.finalize(receiver_object, self._remove_receiver) + + with self.lock: + self._clear_dead_receivers() + if not any(r_key == lookup_key for r_key, _, _ in self.receivers): + self.receivers.append((lookup_key, receiver, is_async)) + self.sender_receivers_cache.clear() + + def disconnect(self, receiver=None, sender=None, dispatch_uid=None): + """ + Disconnect receiver from sender for signal. + + If weak references are used, disconnect need not be called. The receiver + will be removed from dispatch automatically. + + Arguments: + + receiver + The registered receiver to disconnect. May be none if + dispatch_uid is specified. + + sender + The registered sender to disconnect + + dispatch_uid + the unique identifier of the receiver to disconnect + """ + if dispatch_uid: + lookup_key = (dispatch_uid, _make_id(sender)) + else: + lookup_key = (_make_id(receiver), _make_id(sender)) + + disconnected = False + with self.lock: + self._clear_dead_receivers() + for index in range(len(self.receivers)): + r_key, *_ = self.receivers[index] + if r_key == lookup_key: + disconnected = True + del self.receivers[index] + break + self.sender_receivers_cache.clear() + return disconnected + + def has_listeners(self, sender=None): + sync_receivers, async_receivers = self._live_receivers(sender) + return bool(sync_receivers) or bool(async_receivers) + + def send(self, sender, **named): + """ + Send signal from sender to all connected receivers. + + If any receiver raises an error, the error propagates back through send, + terminating the dispatch loop. So it's possible that all receivers + won't be called if an error is raised. + + If any receivers are asynchronous, they are called after all the + synchronous receivers via a single call to async_to_sync(). They are + also executed concurrently with asyncio.gather(). + + Arguments: + + sender + The sender of the signal. Either a specific object or None. + + named + Named arguments which will be passed to receivers. + + Return a list of tuple pairs [(receiver, response), ... ]. + """ + if ( + not self.receivers + or self.sender_receivers_cache.get(sender) is NO_RECEIVERS + ): + return [] + responses = [] + sync_receivers, async_receivers = self._live_receivers(sender) + for receiver in sync_receivers: + response = receiver(signal=self, sender=sender, **named) + responses.append((receiver, response)) + if async_receivers: + + async def asend(): + async_responses = await asyncio.gather( + *( + receiver(signal=self, sender=sender, **named) + for receiver in async_receivers + ) + ) + return zip(async_receivers, async_responses) + + responses.extend(async_to_sync(asend)()) + return responses + + async def asend(self, sender, **named): + """ + Send signal from sender to all connected receivers in async mode. + + All sync receivers will be wrapped by sync_to_async() + If any receiver raises an error, the error propagates back through + send, terminating the dispatch loop. So it's possible that all + receivers won't be called if an error is raised. + + If any receivers are synchronous, they are grouped and called behind a + sync_to_async() adaption before executing any asynchronous receivers. + + If any receivers are asynchronous, they are grouped and executed + concurrently with asyncio.gather(). + + Arguments: + + sender + The sender of the signal. Either a specific object or None. + + named + Named arguments which will be passed to receivers. + + Return a list of tuple pairs [(receiver, response), ...]. + """ + if ( + not self.receivers + or self.sender_receivers_cache.get(sender) is NO_RECEIVERS + ): + return [] + sync_receivers, async_receivers = self._live_receivers(sender) + if sync_receivers: + + @sync_to_async + def sync_send(): + responses = [] + for receiver in sync_receivers: + response = receiver(signal=self, sender=sender, **named) + responses.append((receiver, response)) + return responses + + else: + sync_send = list + + responses, async_responses = await asyncio.gather( + sync_send(), + asyncio.gather( + *( + receiver(signal=self, sender=sender, **named) + for receiver in async_receivers + ) + ), + ) + responses.extend(zip(async_receivers, async_responses)) + return responses + + def _log_robust_failure(self, receiver, err): + logger.error( + "Error calling %s in Signal.send_robust() (%s)", + receiver.__qualname__, + err, + exc_info=err, + ) + + def send_robust(self, sender, **named): + """ + Send signal from sender to all connected receivers catching errors. + + If any receivers are asynchronous, they are called after all the + synchronous receivers via a single call to async_to_sync(). They are + also executed concurrently with asyncio.gather(). + + Arguments: + + sender + The sender of the signal. Can be any Python object (normally one + registered with a connect if you actually want something to + occur). + + named + Named arguments which will be passed to receivers. + + Return a list of tuple pairs [(receiver, response), ... ]. + + If any receiver raises an error (specifically any subclass of + Exception), return the error instance as the result for that receiver. + """ + if ( + not self.receivers + or self.sender_receivers_cache.get(sender) is NO_RECEIVERS + ): + return [] + + # Call each receiver with whatever arguments it can accept. + # Return a list of tuple pairs [(receiver, response), ... ]. + responses = [] + sync_receivers, async_receivers = self._live_receivers(sender) + for receiver in sync_receivers: + try: + response = receiver(signal=self, sender=sender, **named) + except Exception as err: + self._log_robust_failure(receiver, err) + responses.append((receiver, err)) + else: + responses.append((receiver, response)) + if async_receivers: + + async def asend_and_wrap_exception(receiver): + try: + response = await receiver(signal=self, sender=sender, **named) + except Exception as err: + self._log_robust_failure(receiver, err) + return err + return response + + async def asend(): + async_responses = await asyncio.gather( + *( + asend_and_wrap_exception(receiver) + for receiver in async_receivers + ) + ) + return zip(async_receivers, async_responses) + + responses.extend(async_to_sync(asend)()) + return responses + + async def asend_robust(self, sender, **named): + """ + Send signal from sender to all connected receivers catching errors. + + If any receivers are synchronous, they are grouped and called behind a + sync_to_async() adaption before executing any asynchronous receivers. + + If any receivers are asynchronous, they are grouped and executed + concurrently with asyncio.gather. + + Arguments: + + sender + The sender of the signal. Can be any Python object (normally one + registered with a connect if you actually want something to + occur). + + named + Named arguments which will be passed to receivers. + + Return a list of tuple pairs [(receiver, response), ... ]. + + If any receiver raises an error (specifically any subclass of + Exception), return the error instance as the result for that receiver. + """ + if ( + not self.receivers + or self.sender_receivers_cache.get(sender) is NO_RECEIVERS + ): + return [] + + # Call each receiver with whatever arguments it can accept. + # Return a list of tuple pairs [(receiver, response), ... ]. + sync_receivers, async_receivers = self._live_receivers(sender) + + if sync_receivers: + + @sync_to_async + def sync_send(): + responses = [] + for receiver in sync_receivers: + try: + response = receiver(signal=self, sender=sender, **named) + except Exception as err: + self._log_robust_failure(receiver, err) + responses.append((receiver, err)) + else: + responses.append((receiver, response)) + return responses + + else: + sync_send = list + + async def asend_and_wrap_exception(receiver): + try: + response = await receiver(signal=self, sender=sender, **named) + except Exception as err: + self._log_robust_failure(receiver, err) + return err + return response + + responses, async_responses = await asyncio.gather( + sync_send(), + asyncio.gather( + *(asend_and_wrap_exception(receiver) for receiver in async_receivers), + ), + ) + responses.extend(zip(async_receivers, async_responses)) + return responses + + def _clear_dead_receivers(self): + # Note: caller is assumed to hold self.lock. + if self._dead_receivers: + self._dead_receivers = False + self.receivers = [ + r + for r in self.receivers + if not (isinstance(r[1], weakref.ReferenceType) and r[1]() is None) + ] + + def _live_receivers(self, sender): + """ + Filter sequence of receivers to get resolved, live receivers. + + This checks for weak references and resolves them, then returning only + live receivers. + """ + receivers = None + if self.use_caching and not self._dead_receivers: + receivers = self.sender_receivers_cache.get(sender) + # We could end up here with NO_RECEIVERS even if we do check this case in + # .send() prior to calling _live_receivers() due to concurrent .send() call. + if receivers is NO_RECEIVERS: + return [], [] + if receivers is None: + with self.lock: + self._clear_dead_receivers() + senderkey = _make_id(sender) + receivers = [] + for (_receiverkey, r_senderkey), receiver, is_async in self.receivers: + if r_senderkey == NONE_ID or r_senderkey == senderkey: + receivers.append((receiver, is_async)) + if self.use_caching: + if not receivers: + self.sender_receivers_cache[sender] = NO_RECEIVERS + else: + # Note, we must cache the weakref versions. + self.sender_receivers_cache[sender] = receivers + non_weak_sync_receivers = [] + non_weak_async_receivers = [] + for receiver, is_async in receivers: + if isinstance(receiver, weakref.ReferenceType): + # Dereference the weak reference. + receiver = receiver() + if receiver is not None: + if is_async: + non_weak_async_receivers.append(receiver) + else: + non_weak_sync_receivers.append(receiver) + else: + if is_async: + non_weak_async_receivers.append(receiver) + else: + non_weak_sync_receivers.append(receiver) + return non_weak_sync_receivers, non_weak_async_receivers + + def _remove_receiver(self, receiver=None): + # Mark that the self.receivers list has dead weakrefs. If so, we will + # clean those up in connect, disconnect and _live_receivers while + # holding self.lock. Note that doing the cleanup here isn't a good + # idea, _remove_receiver() will be called as side effect of garbage + # collection, and so the call can happen while we are already holding + # self.lock. + self._dead_receivers = True + + +def receiver(signal, **kwargs): + """ + A decorator for connecting receivers to signals. Used by passing in the + signal (or list of signals) and keyword arguments to connect:: + + @receiver(post_save, sender=MyModel) + def signal_receiver(sender, **kwargs): + ... + + @receiver([post_save, post_delete], sender=MyModel) + def signals_receiver(sender, **kwargs): + ... + """ + + def _decorator(func): + if isinstance(signal, (list, tuple)): + for s in signal: + s.connect(func, **kwargs) + else: + signal.connect(func, **kwargs) + return func + + return _decorator diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/dispatch/license.txt b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/dispatch/license.txt new file mode 100644 index 0000000..505090d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/dispatch/license.txt @@ -0,0 +1,36 @@ +django.dispatch was originally forked from PyDispatcher. + +PyDispatcher License: + + Copyright (c) 2001-2003, Patrick K. O'Brien and Contributors + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + The name of Patrick K. O'Brien, or the name of any Contributor, + may not be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/__init__.py new file mode 100644 index 0000000..1c31921 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/__init__.py @@ -0,0 +1,11 @@ +""" +Django validation and HTML form handling. +""" + +from django.core.exceptions import ValidationError # NOQA +from django.forms.boundfield import * # NOQA +from django.forms.fields import * # NOQA +from django.forms.forms import * # NOQA +from django.forms.formsets import * # NOQA +from django.forms.models import * # NOQA +from django.forms.widgets import * # NOQA diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/boundfield.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/boundfield.py new file mode 100644 index 0000000..d56fa0e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/boundfield.py @@ -0,0 +1,358 @@ +import re + +from django.core.exceptions import ValidationError +from django.forms.utils import RenderableFieldMixin, pretty_name +from django.forms.widgets import MultiWidget, Textarea, TextInput +from django.utils.functional import cached_property +from django.utils.html import format_html, html_safe +from django.utils.translation import gettext_lazy as _ + +__all__ = ("BoundField",) + + +class BoundField(RenderableFieldMixin): + "A Field plus data" + + def __init__(self, form, field, name): + self.form = form + self.field = field + self.name = name + self.html_name = form.add_prefix(name) + self.html_initial_name = form.add_initial_prefix(name) + self.html_initial_id = form.add_initial_prefix(self.auto_id) + if self.field.label is None: + self.label = pretty_name(name) + else: + self.label = self.field.label + self.help_text = field.help_text or "" + self.renderer = form.renderer + + @cached_property + def subwidgets(self): + """ + Most widgets yield a single subwidget, but others like RadioSelect and + CheckboxSelectMultiple produce one subwidget for each choice. + + This property is cached so that only one database query occurs when + rendering ModelChoiceFields. + """ + id_ = self.field.widget.attrs.get("id") or self.auto_id + attrs = {"id": id_} if id_ else {} + attrs = self.build_widget_attrs(attrs) + return [ + BoundWidget(self.field.widget, widget, self.form.renderer) + for widget in self.field.widget.subwidgets( + self.html_name, self.value(), attrs=attrs + ) + ] + + def __bool__(self): + # BoundField evaluates to True even if it doesn't have subwidgets. + return True + + def __iter__(self): + return iter(self.subwidgets) + + def __len__(self): + return len(self.subwidgets) + + def __getitem__(self, idx): + # Prevent unnecessary reevaluation when accessing BoundField's attrs + # from templates. + if not isinstance(idx, (int, slice)): + raise TypeError( + "BoundField indices must be integers or slices, not %s." + % type(idx).__name__ + ) + return self.subwidgets[idx] + + @property + def errors(self): + """ + Return an ErrorList (empty if there are no errors) for this field. + """ + return self.form.errors.get( + self.name, self.form.error_class(renderer=self.form.renderer) + ) + + @property + def template_name(self): + return self.field.template_name or self.form.renderer.field_template_name + + def get_context(self): + return {"field": self} + + def as_widget(self, widget=None, attrs=None, only_initial=False): + """ + Render the field by rendering the passed widget, adding any HTML + attributes passed as attrs. If a widget isn't specified, use the + field's default widget. + """ + widget = widget or self.field.widget + if self.field.localize: + widget.is_localized = True + attrs = attrs or {} + attrs = self.build_widget_attrs(attrs, widget) + if self.auto_id and "id" not in widget.attrs: + attrs.setdefault( + "id", self.html_initial_id if only_initial else self.auto_id + ) + if only_initial and self.html_initial_name in self.form.data: + # Propagate the hidden initial value. + value = self.form._widget_data_value( + self.field.hidden_widget(), + self.html_initial_name, + ) + else: + value = self.value() + return widget.render( + name=self.html_initial_name if only_initial else self.html_name, + value=value, + attrs=attrs, + renderer=self.form.renderer, + ) + + def as_text(self, attrs=None, **kwargs): + """ + Return a string of HTML for representing this as an . + """ + return self.as_widget(TextInput(), attrs, **kwargs) + + def as_textarea(self, attrs=None, **kwargs): + """Return a string of HTML for representing this as a diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/jinja2/django/forms/widgets/time.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/jinja2/django/forms/widgets/time.html new file mode 100644 index 0000000..08b1e61 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/jinja2/django/forms/widgets/time.html @@ -0,0 +1 @@ +{% include "django/forms/widgets/input.html" %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/jinja2/django/forms/widgets/url.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/jinja2/django/forms/widgets/url.html new file mode 100644 index 0000000..08b1e61 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/jinja2/django/forms/widgets/url.html @@ -0,0 +1 @@ +{% include "django/forms/widgets/input.html" %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/models.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/models.py new file mode 100644 index 0000000..ff4b83f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/models.py @@ -0,0 +1,1675 @@ +""" +Helper functions for creating Form classes from Django models +and database field objects. +""" +from itertools import chain + +from django.core.exceptions import ( + NON_FIELD_ERRORS, + FieldError, + ImproperlyConfigured, + ValidationError, +) +from django.db.models.utils import AltersData +from django.forms.fields import ChoiceField, Field +from django.forms.forms import BaseForm, DeclarativeFieldsMetaclass +from django.forms.formsets import BaseFormSet, formset_factory +from django.forms.utils import ErrorList +from django.forms.widgets import ( + HiddenInput, + MultipleHiddenInput, + RadioSelect, + SelectMultiple, +) +from django.utils.choices import BaseChoiceIterator +from django.utils.text import capfirst, get_text_list +from django.utils.translation import gettext +from django.utils.translation import gettext_lazy as _ + +__all__ = ( + "ModelForm", + "BaseModelForm", + "model_to_dict", + "fields_for_model", + "ModelChoiceField", + "ModelMultipleChoiceField", + "ALL_FIELDS", + "BaseModelFormSet", + "modelformset_factory", + "BaseInlineFormSet", + "inlineformset_factory", + "modelform_factory", +) + +ALL_FIELDS = "__all__" + + +def construct_instance(form, instance, fields=None, exclude=None): + """ + Construct and return a model instance from the bound ``form``'s + ``cleaned_data``, but do not save the returned instance to the database. + """ + from django.db import models + + opts = instance._meta + + cleaned_data = form.cleaned_data + file_field_list = [] + for f in opts.fields: + if ( + not f.editable + or isinstance(f, models.AutoField) + or f.name not in cleaned_data + ): + continue + if fields is not None and f.name not in fields: + continue + if exclude and f.name in exclude: + continue + # Leave defaults for fields that aren't in POST data, except for + # checkbox inputs because they don't appear in POST data if not checked. + if ( + f.has_default() + and form[f.name].field.widget.value_omitted_from_data( + form.data, form.files, form.add_prefix(f.name) + ) + and cleaned_data.get(f.name) in form[f.name].field.empty_values + ): + continue + # Defer saving file-type fields until after the other fields, so a + # callable upload_to can use the values from other fields. + if isinstance(f, models.FileField): + file_field_list.append(f) + else: + f.save_form_data(instance, cleaned_data[f.name]) + + for f in file_field_list: + f.save_form_data(instance, cleaned_data[f.name]) + + return instance + + +# ModelForms ################################################################# + + +def model_to_dict(instance, fields=None, exclude=None): + """ + Return a dict containing the data in ``instance`` suitable for passing as + a Form's ``initial`` keyword argument. + + ``fields`` is an optional list of field names. If provided, return only the + named. + + ``exclude`` is an optional list of field names. If provided, exclude the + named from the returned dict, even if they are listed in the ``fields`` + argument. + """ + opts = instance._meta + data = {} + for f in chain(opts.concrete_fields, opts.private_fields, opts.many_to_many): + if not getattr(f, "editable", False): + continue + if fields is not None and f.name not in fields: + continue + if exclude and f.name in exclude: + continue + data[f.name] = f.value_from_object(instance) + return data + + +def apply_limit_choices_to_to_formfield(formfield): + """Apply limit_choices_to to the formfield's queryset if needed.""" + from django.db.models import Exists, OuterRef, Q + + if hasattr(formfield, "queryset") and hasattr(formfield, "get_limit_choices_to"): + limit_choices_to = formfield.get_limit_choices_to() + if limit_choices_to: + complex_filter = limit_choices_to + if not isinstance(complex_filter, Q): + complex_filter = Q(**limit_choices_to) + complex_filter &= Q(pk=OuterRef("pk")) + # Use Exists() to avoid potential duplicates. + formfield.queryset = formfield.queryset.filter( + Exists(formfield.queryset.model._base_manager.filter(complex_filter)), + ) + + +def fields_for_model( + model, + fields=None, + exclude=None, + widgets=None, + formfield_callback=None, + localized_fields=None, + labels=None, + help_texts=None, + error_messages=None, + field_classes=None, + *, + apply_limit_choices_to=True, + form_declared_fields=None, +): + """ + Return a dictionary containing form fields for the given model. + + ``fields`` is an optional list of field names. If provided, return only the + named fields. + + ``exclude`` is an optional list of field names. If provided, exclude the + named fields from the returned fields, even if they are listed in the + ``fields`` argument. + + ``widgets`` is a dictionary of model field names mapped to a widget. + + ``formfield_callback`` is a callable that takes a model field and returns + a form field. + + ``localized_fields`` is a list of names of fields which should be localized. + + ``labels`` is a dictionary of model field names mapped to a label. + + ``help_texts`` is a dictionary of model field names mapped to a help text. + + ``error_messages`` is a dictionary of model field names mapped to a + dictionary of error messages. + + ``field_classes`` is a dictionary of model field names mapped to a form + field class. + + ``apply_limit_choices_to`` is a boolean indicating if limit_choices_to + should be applied to a field's queryset. + + ``form_declared_fields`` is a dictionary of form fields created directly on + a form. + """ + form_declared_fields = form_declared_fields or {} + field_dict = {} + ignored = [] + opts = model._meta + # Avoid circular import + from django.db.models import Field as ModelField + + sortable_private_fields = [ + f for f in opts.private_fields if isinstance(f, ModelField) + ] + for f in sorted( + chain(opts.concrete_fields, sortable_private_fields, opts.many_to_many) + ): + if not getattr(f, "editable", False): + if ( + fields is not None + and f.name in fields + and (exclude is None or f.name not in exclude) + ): + raise FieldError( + "'%s' cannot be specified for %s model form as it is a " + "non-editable field" % (f.name, model.__name__) + ) + continue + if fields is not None and f.name not in fields: + continue + if exclude and f.name in exclude: + continue + if f.name in form_declared_fields: + field_dict[f.name] = form_declared_fields[f.name] + continue + + kwargs = {} + if widgets and f.name in widgets: + kwargs["widget"] = widgets[f.name] + if localized_fields == ALL_FIELDS or ( + localized_fields and f.name in localized_fields + ): + kwargs["localize"] = True + if labels and f.name in labels: + kwargs["label"] = labels[f.name] + if help_texts and f.name in help_texts: + kwargs["help_text"] = help_texts[f.name] + if error_messages and f.name in error_messages: + kwargs["error_messages"] = error_messages[f.name] + if field_classes and f.name in field_classes: + kwargs["form_class"] = field_classes[f.name] + + if formfield_callback is None: + formfield = f.formfield(**kwargs) + elif not callable(formfield_callback): + raise TypeError("formfield_callback must be a function or callable") + else: + formfield = formfield_callback(f, **kwargs) + + if formfield: + if apply_limit_choices_to: + apply_limit_choices_to_to_formfield(formfield) + field_dict[f.name] = formfield + else: + ignored.append(f.name) + if fields: + field_dict = { + f: field_dict.get(f) + for f in fields + if (not exclude or f not in exclude) and f not in ignored + } + return field_dict + + +class ModelFormOptions: + def __init__(self, options=None): + self.model = getattr(options, "model", None) + self.fields = getattr(options, "fields", None) + self.exclude = getattr(options, "exclude", None) + self.widgets = getattr(options, "widgets", None) + self.localized_fields = getattr(options, "localized_fields", None) + self.labels = getattr(options, "labels", None) + self.help_texts = getattr(options, "help_texts", None) + self.error_messages = getattr(options, "error_messages", None) + self.field_classes = getattr(options, "field_classes", None) + self.formfield_callback = getattr(options, "formfield_callback", None) + + +class ModelFormMetaclass(DeclarativeFieldsMetaclass): + def __new__(mcs, name, bases, attrs): + new_class = super().__new__(mcs, name, bases, attrs) + + if bases == (BaseModelForm,): + return new_class + + opts = new_class._meta = ModelFormOptions(getattr(new_class, "Meta", None)) + + # We check if a string was passed to `fields` or `exclude`, + # which is likely to be a mistake where the user typed ('foo') instead + # of ('foo',) + for opt in ["fields", "exclude", "localized_fields"]: + value = getattr(opts, opt) + if isinstance(value, str) and value != ALL_FIELDS: + msg = ( + "%(model)s.Meta.%(opt)s cannot be a string. " + "Did you mean to type: ('%(value)s',)?" + % { + "model": new_class.__name__, + "opt": opt, + "value": value, + } + ) + raise TypeError(msg) + + if opts.model: + # If a model is defined, extract form fields from it. + if opts.fields is None and opts.exclude is None: + raise ImproperlyConfigured( + "Creating a ModelForm without either the 'fields' attribute " + "or the 'exclude' attribute is prohibited; form %s " + "needs updating." % name + ) + + if opts.fields == ALL_FIELDS: + # Sentinel for fields_for_model to indicate "get the list of + # fields from the model" + opts.fields = None + + fields = fields_for_model( + opts.model, + opts.fields, + opts.exclude, + opts.widgets, + opts.formfield_callback, + opts.localized_fields, + opts.labels, + opts.help_texts, + opts.error_messages, + opts.field_classes, + # limit_choices_to will be applied during ModelForm.__init__(). + apply_limit_choices_to=False, + form_declared_fields=new_class.declared_fields, + ) + + # make sure opts.fields doesn't specify an invalid field + none_model_fields = {k for k, v in fields.items() if not v} + missing_fields = none_model_fields.difference(new_class.declared_fields) + if missing_fields: + message = "Unknown field(s) (%s) specified for %s" + message %= (", ".join(missing_fields), opts.model.__name__) + raise FieldError(message) + # Include all the other declared fields. + fields.update(new_class.declared_fields) + else: + fields = new_class.declared_fields + + new_class.base_fields = fields + + return new_class + + +class BaseModelForm(BaseForm, AltersData): + def __init__( + self, + data=None, + files=None, + auto_id="id_%s", + prefix=None, + initial=None, + error_class=ErrorList, + label_suffix=None, + empty_permitted=False, + instance=None, + use_required_attribute=None, + renderer=None, + ): + opts = self._meta + if opts.model is None: + raise ValueError("ModelForm has no model class specified.") + if instance is None: + # if we didn't get an instance, instantiate a new one + self.instance = opts.model() + object_data = {} + else: + self.instance = instance + object_data = model_to_dict(instance, opts.fields, opts.exclude) + # if initial was provided, it should override the values from instance + if initial is not None: + object_data.update(initial) + # self._validate_unique will be set to True by BaseModelForm.clean(). + # It is False by default so overriding self.clean() and failing to call + # super will stop validate_unique from being called. + self._validate_unique = False + super().__init__( + data, + files, + auto_id, + prefix, + object_data, + error_class, + label_suffix, + empty_permitted, + use_required_attribute=use_required_attribute, + renderer=renderer, + ) + for formfield in self.fields.values(): + apply_limit_choices_to_to_formfield(formfield) + + def _get_validation_exclusions(self): + """ + For backwards-compatibility, exclude several types of fields from model + validation. See tickets #12507, #12521, #12553. + """ + exclude = set() + # Build up a list of fields that should be excluded from model field + # validation and unique checks. + for f in self.instance._meta.fields: + field = f.name + # Exclude fields that aren't on the form. The developer may be + # adding these values to the model after form validation. + if field not in self.fields: + exclude.add(f.name) + + # Don't perform model validation on fields that were defined + # manually on the form and excluded via the ModelForm's Meta + # class. See #12901. + elif self._meta.fields and field not in self._meta.fields: + exclude.add(f.name) + elif self._meta.exclude and field in self._meta.exclude: + exclude.add(f.name) + + # Exclude fields that failed form validation. There's no need for + # the model fields to validate them as well. + elif field in self._errors: + exclude.add(f.name) + + # Exclude empty fields that are not required by the form, if the + # underlying model field is required. This keeps the model field + # from raising a required error. Note: don't exclude the field from + # validation if the model field allows blanks. If it does, the blank + # value may be included in a unique check, so cannot be excluded + # from validation. + else: + form_field = self.fields[field] + field_value = self.cleaned_data.get(field) + if ( + not f.blank + and not form_field.required + and field_value in form_field.empty_values + ): + exclude.add(f.name) + return exclude + + def clean(self): + self._validate_unique = True + return self.cleaned_data + + def _update_errors(self, errors): + # Override any validation error messages defined at the model level + # with those defined at the form level. + opts = self._meta + + # Allow the model generated by construct_instance() to raise + # ValidationError and have them handled in the same way as others. + if hasattr(errors, "error_dict"): + error_dict = errors.error_dict + else: + error_dict = {NON_FIELD_ERRORS: errors} + + for field, messages in error_dict.items(): + if ( + field == NON_FIELD_ERRORS + and opts.error_messages + and NON_FIELD_ERRORS in opts.error_messages + ): + error_messages = opts.error_messages[NON_FIELD_ERRORS] + elif field in self.fields: + error_messages = self.fields[field].error_messages + else: + continue + + for message in messages: + if ( + isinstance(message, ValidationError) + and message.code in error_messages + ): + message.message = error_messages[message.code] + + self.add_error(None, errors) + + def _post_clean(self): + opts = self._meta + + exclude = self._get_validation_exclusions() + + # Foreign Keys being used to represent inline relationships + # are excluded from basic field value validation. This is for two + # reasons: firstly, the value may not be supplied (#12507; the + # case of providing new values to the admin); secondly the + # object being referred to may not yet fully exist (#12749). + # However, these fields *must* be included in uniqueness checks, + # so this can't be part of _get_validation_exclusions(). + for name, field in self.fields.items(): + if isinstance(field, InlineForeignKeyField): + exclude.add(name) + + try: + self.instance = construct_instance( + self, self.instance, opts.fields, opts.exclude + ) + except ValidationError as e: + self._update_errors(e) + + try: + self.instance.full_clean(exclude=exclude, validate_unique=False) + except ValidationError as e: + self._update_errors(e) + + # Validate uniqueness if needed. + if self._validate_unique: + self.validate_unique() + + def validate_unique(self): + """ + Call the instance's validate_unique() method and update the form's + validation errors if any were raised. + """ + exclude = self._get_validation_exclusions() + try: + self.instance.validate_unique(exclude=exclude) + except ValidationError as e: + self._update_errors(e) + + def _save_m2m(self): + """ + Save the many-to-many fields and generic relations for this form. + """ + cleaned_data = self.cleaned_data + exclude = self._meta.exclude + fields = self._meta.fields + opts = self.instance._meta + # Note that for historical reasons we want to include also + # private_fields here. (GenericRelation was previously a fake + # m2m field). + for f in chain(opts.many_to_many, opts.private_fields): + if not hasattr(f, "save_form_data"): + continue + if fields and f.name not in fields: + continue + if exclude and f.name in exclude: + continue + if f.name in cleaned_data: + f.save_form_data(self.instance, cleaned_data[f.name]) + + def save(self, commit=True): + """ + Save this form's self.instance object if commit=True. Otherwise, add + a save_m2m() method to the form which can be called after the instance + is saved manually at a later time. Return the model instance. + """ + if self.errors: + raise ValueError( + "The %s could not be %s because the data didn't validate." + % ( + self.instance._meta.object_name, + "created" if self.instance._state.adding else "changed", + ) + ) + if commit: + # If committing, save the instance and the m2m data immediately. + self.instance.save() + self._save_m2m() + else: + # If not committing, add a method to the form to allow deferred + # saving of m2m data. + self.save_m2m = self._save_m2m + return self.instance + + save.alters_data = True + + +class ModelForm(BaseModelForm, metaclass=ModelFormMetaclass): + pass + + +def modelform_factory( + model, + form=ModelForm, + fields=None, + exclude=None, + formfield_callback=None, + widgets=None, + localized_fields=None, + labels=None, + help_texts=None, + error_messages=None, + field_classes=None, +): + """ + Return a ModelForm containing form fields for the given model. You can + optionally pass a `form` argument to use as a starting point for + constructing the ModelForm. + + ``fields`` is an optional list of field names. If provided, include only + the named fields in the returned fields. If omitted or '__all__', use all + fields. + + ``exclude`` is an optional list of field names. If provided, exclude the + named fields from the returned fields, even if they are listed in the + ``fields`` argument. + + ``widgets`` is a dictionary of model field names mapped to a widget. + + ``localized_fields`` is a list of names of fields which should be localized. + + ``formfield_callback`` is a callable that takes a model field and returns + a form field. + + ``labels`` is a dictionary of model field names mapped to a label. + + ``help_texts`` is a dictionary of model field names mapped to a help text. + + ``error_messages`` is a dictionary of model field names mapped to a + dictionary of error messages. + + ``field_classes`` is a dictionary of model field names mapped to a form + field class. + """ + # Create the inner Meta class. FIXME: ideally, we should be able to + # construct a ModelForm without creating and passing in a temporary + # inner class. + + # Build up a list of attributes that the Meta object will have. + attrs = {"model": model} + if fields is not None: + attrs["fields"] = fields + if exclude is not None: + attrs["exclude"] = exclude + if widgets is not None: + attrs["widgets"] = widgets + if localized_fields is not None: + attrs["localized_fields"] = localized_fields + if labels is not None: + attrs["labels"] = labels + if help_texts is not None: + attrs["help_texts"] = help_texts + if error_messages is not None: + attrs["error_messages"] = error_messages + if field_classes is not None: + attrs["field_classes"] = field_classes + + # If parent form class already has an inner Meta, the Meta we're + # creating needs to inherit from the parent's inner meta. + bases = (form.Meta,) if hasattr(form, "Meta") else () + Meta = type("Meta", bases, attrs) + if formfield_callback: + Meta.formfield_callback = staticmethod(formfield_callback) + # Give this new form class a reasonable name. + class_name = model.__name__ + "Form" + + # Class attributes for the new form class. + form_class_attrs = {"Meta": Meta} + + if getattr(Meta, "fields", None) is None and getattr(Meta, "exclude", None) is None: + raise ImproperlyConfigured( + "Calling modelform_factory without defining 'fields' or " + "'exclude' explicitly is prohibited." + ) + + # Instantiate type(form) in order to use the same metaclass as form. + return type(form)(class_name, (form,), form_class_attrs) + + +# ModelFormSets ############################################################## + + +class BaseModelFormSet(BaseFormSet, AltersData): + """ + A ``FormSet`` for editing a queryset and/or adding new objects to it. + """ + + model = None + edit_only = False + + # Set of fields that must be unique among forms of this set. + unique_fields = set() + + def __init__( + self, + data=None, + files=None, + auto_id="id_%s", + prefix=None, + queryset=None, + *, + initial=None, + **kwargs, + ): + self.queryset = queryset + self.initial_extra = initial + super().__init__( + **{ + "data": data, + "files": files, + "auto_id": auto_id, + "prefix": prefix, + **kwargs, + } + ) + + def initial_form_count(self): + """Return the number of forms that are required in this FormSet.""" + if not self.is_bound: + return len(self.get_queryset()) + return super().initial_form_count() + + def _existing_object(self, pk): + if not hasattr(self, "_object_dict"): + self._object_dict = {o.pk: o for o in self.get_queryset()} + return self._object_dict.get(pk) + + def _get_to_python(self, field): + """ + If the field is a related field, fetch the concrete field's (that + is, the ultimate pointed-to field's) to_python. + """ + while field.remote_field is not None: + field = field.remote_field.get_related_field() + return field.to_python + + def _construct_form(self, i, **kwargs): + pk_required = i < self.initial_form_count() + if pk_required: + if self.is_bound: + pk_key = "%s-%s" % (self.add_prefix(i), self.model._meta.pk.name) + try: + pk = self.data[pk_key] + except KeyError: + # The primary key is missing. The user may have tampered + # with POST data. + pass + else: + to_python = self._get_to_python(self.model._meta.pk) + try: + pk = to_python(pk) + except ValidationError: + # The primary key exists but is an invalid value. The + # user may have tampered with POST data. + pass + else: + kwargs["instance"] = self._existing_object(pk) + else: + kwargs["instance"] = self.get_queryset()[i] + elif self.initial_extra: + # Set initial values for extra forms + try: + kwargs["initial"] = self.initial_extra[i - self.initial_form_count()] + except IndexError: + pass + form = super()._construct_form(i, **kwargs) + if pk_required: + form.fields[self.model._meta.pk.name].required = True + return form + + def get_queryset(self): + if not hasattr(self, "_queryset"): + if self.queryset is not None: + qs = self.queryset + else: + qs = self.model._default_manager.get_queryset() + + # If the queryset isn't already ordered we need to add an + # artificial ordering here to make sure that all formsets + # constructed from this queryset have the same form order. + if not qs.ordered: + qs = qs.order_by(self.model._meta.pk.name) + + # Removed queryset limiting here. As per discussion re: #13023 + # on django-dev, max_num should not prevent existing + # related objects/inlines from being displayed. + self._queryset = qs + return self._queryset + + def save_new(self, form, commit=True): + """Save and return a new model instance for the given form.""" + return form.save(commit=commit) + + def save_existing(self, form, obj, commit=True): + """Save and return an existing model instance for the given form.""" + return form.save(commit=commit) + + def delete_existing(self, obj, commit=True): + """Deletes an existing model instance.""" + if commit: + obj.delete() + + def save(self, commit=True): + """ + Save model instances for every form, adding and changing instances + as necessary, and return the list of instances. + """ + if not commit: + self.saved_forms = [] + + def save_m2m(): + for form in self.saved_forms: + form.save_m2m() + + self.save_m2m = save_m2m + if self.edit_only: + return self.save_existing_objects(commit) + else: + return self.save_existing_objects(commit) + self.save_new_objects(commit) + + save.alters_data = True + + def clean(self): + self.validate_unique() + + def validate_unique(self): + # Collect unique_checks and date_checks to run from all the forms. + all_unique_checks = set() + all_date_checks = set() + forms_to_delete = self.deleted_forms + valid_forms = [ + form + for form in self.forms + if form.is_valid() and form not in forms_to_delete + ] + for form in valid_forms: + exclude = form._get_validation_exclusions() + unique_checks, date_checks = form.instance._get_unique_checks( + exclude=exclude, + include_meta_constraints=True, + ) + all_unique_checks.update(unique_checks) + all_date_checks.update(date_checks) + + errors = [] + # Do each of the unique checks (unique and unique_together) + for uclass, unique_check in all_unique_checks: + seen_data = set() + for form in valid_forms: + # Get the data for the set of fields that must be unique among + # the forms. + row_data = ( + field if field in self.unique_fields else form.cleaned_data[field] + for field in unique_check + if field in form.cleaned_data + ) + # Reduce Model instances to their primary key values + row_data = tuple( + d._get_pk_val() if hasattr(d, "_get_pk_val") + # Prevent "unhashable type: list" errors later on. + else tuple(d) if isinstance(d, list) else d + for d in row_data + ) + if row_data and None not in row_data: + # if we've already seen it then we have a uniqueness failure + if row_data in seen_data: + # poke error messages into the right places and mark + # the form as invalid + errors.append(self.get_unique_error_message(unique_check)) + form._errors[NON_FIELD_ERRORS] = self.error_class( + [self.get_form_error()], + renderer=self.renderer, + ) + # Remove the data from the cleaned_data dict since it + # was invalid. + for field in unique_check: + if field in form.cleaned_data: + del form.cleaned_data[field] + # mark the data as seen + seen_data.add(row_data) + # iterate over each of the date checks now + for date_check in all_date_checks: + seen_data = set() + uclass, lookup, field, unique_for = date_check + for form in valid_forms: + # see if we have data for both fields + if ( + form.cleaned_data + and form.cleaned_data[field] is not None + and form.cleaned_data[unique_for] is not None + ): + # if it's a date lookup we need to get the data for all the fields + if lookup == "date": + date = form.cleaned_data[unique_for] + date_data = (date.year, date.month, date.day) + # otherwise it's just the attribute on the date/datetime + # object + else: + date_data = (getattr(form.cleaned_data[unique_for], lookup),) + data = (form.cleaned_data[field],) + date_data + # if we've already seen it then we have a uniqueness failure + if data in seen_data: + # poke error messages into the right places and mark + # the form as invalid + errors.append(self.get_date_error_message(date_check)) + form._errors[NON_FIELD_ERRORS] = self.error_class( + [self.get_form_error()], + renderer=self.renderer, + ) + # Remove the data from the cleaned_data dict since it + # was invalid. + del form.cleaned_data[field] + # mark the data as seen + seen_data.add(data) + + if errors: + raise ValidationError(errors) + + def get_unique_error_message(self, unique_check): + if len(unique_check) == 1: + return gettext("Please correct the duplicate data for %(field)s.") % { + "field": unique_check[0], + } + else: + return gettext( + "Please correct the duplicate data for %(field)s, which must be unique." + ) % { + "field": get_text_list(unique_check, _("and")), + } + + def get_date_error_message(self, date_check): + return gettext( + "Please correct the duplicate data for %(field_name)s " + "which must be unique for the %(lookup)s in %(date_field)s." + ) % { + "field_name": date_check[2], + "date_field": date_check[3], + "lookup": str(date_check[1]), + } + + def get_form_error(self): + return gettext("Please correct the duplicate values below.") + + def save_existing_objects(self, commit=True): + self.changed_objects = [] + self.deleted_objects = [] + if not self.initial_forms: + return [] + + saved_instances = [] + forms_to_delete = self.deleted_forms + for form in self.initial_forms: + obj = form.instance + # If the pk is None, it means either: + # 1. The object is an unexpected empty model, created by invalid + # POST data such as an object outside the formset's queryset. + # 2. The object was already deleted from the database. + if obj.pk is None: + continue + if form in forms_to_delete: + self.deleted_objects.append(obj) + self.delete_existing(obj, commit=commit) + elif form.has_changed(): + self.changed_objects.append((obj, form.changed_data)) + saved_instances.append(self.save_existing(form, obj, commit=commit)) + if not commit: + self.saved_forms.append(form) + return saved_instances + + def save_new_objects(self, commit=True): + self.new_objects = [] + for form in self.extra_forms: + if not form.has_changed(): + continue + # If someone has marked an add form for deletion, don't save the + # object. + if self.can_delete and self._should_delete_form(form): + continue + self.new_objects.append(self.save_new(form, commit=commit)) + if not commit: + self.saved_forms.append(form) + return self.new_objects + + def add_fields(self, form, index): + """Add a hidden field for the object's primary key.""" + from django.db.models import AutoField, ForeignKey, OneToOneField + + self._pk_field = pk = self.model._meta.pk + # If a pk isn't editable, then it won't be on the form, so we need to + # add it here so we can tell which object is which when we get the + # data back. Generally, pk.editable should be false, but for some + # reason, auto_created pk fields and AutoField's editable attribute is + # True, so check for that as well. + + def pk_is_not_editable(pk): + return ( + (not pk.editable) + or (pk.auto_created or isinstance(pk, AutoField)) + or ( + pk.remote_field + and pk.remote_field.parent_link + and pk_is_not_editable(pk.remote_field.model._meta.pk) + ) + ) + + if pk_is_not_editable(pk) or pk.name not in form.fields: + if form.is_bound: + # If we're adding the related instance, ignore its primary key + # as it could be an auto-generated default which isn't actually + # in the database. + pk_value = None if form.instance._state.adding else form.instance.pk + else: + try: + if index is not None: + pk_value = self.get_queryset()[index].pk + else: + pk_value = None + except IndexError: + pk_value = None + if isinstance(pk, (ForeignKey, OneToOneField)): + qs = pk.remote_field.model._default_manager.get_queryset() + else: + qs = self.model._default_manager.get_queryset() + qs = qs.using(form.instance._state.db) + if form._meta.widgets: + widget = form._meta.widgets.get(self._pk_field.name, HiddenInput) + else: + widget = HiddenInput + form.fields[self._pk_field.name] = ModelChoiceField( + qs, initial=pk_value, required=False, widget=widget + ) + super().add_fields(form, index) + + +def modelformset_factory( + model, + form=ModelForm, + formfield_callback=None, + formset=BaseModelFormSet, + extra=1, + can_delete=False, + can_order=False, + max_num=None, + fields=None, + exclude=None, + widgets=None, + validate_max=False, + localized_fields=None, + labels=None, + help_texts=None, + error_messages=None, + min_num=None, + validate_min=False, + field_classes=None, + absolute_max=None, + can_delete_extra=True, + renderer=None, + edit_only=False, +): + """Return a FormSet class for the given Django model class.""" + meta = getattr(form, "Meta", None) + if ( + getattr(meta, "fields", fields) is None + and getattr(meta, "exclude", exclude) is None + ): + raise ImproperlyConfigured( + "Calling modelformset_factory without defining 'fields' or " + "'exclude' explicitly is prohibited." + ) + + form = modelform_factory( + model, + form=form, + fields=fields, + exclude=exclude, + formfield_callback=formfield_callback, + widgets=widgets, + localized_fields=localized_fields, + labels=labels, + help_texts=help_texts, + error_messages=error_messages, + field_classes=field_classes, + ) + FormSet = formset_factory( + form, + formset, + extra=extra, + min_num=min_num, + max_num=max_num, + can_order=can_order, + can_delete=can_delete, + validate_min=validate_min, + validate_max=validate_max, + absolute_max=absolute_max, + can_delete_extra=can_delete_extra, + renderer=renderer, + ) + FormSet.model = model + FormSet.edit_only = edit_only + return FormSet + + +# InlineFormSets ############################################################# + + +class BaseInlineFormSet(BaseModelFormSet): + """A formset for child objects related to a parent.""" + + def __init__( + self, + data=None, + files=None, + instance=None, + save_as_new=False, + prefix=None, + queryset=None, + **kwargs, + ): + if instance is None: + self.instance = self.fk.remote_field.model() + else: + self.instance = instance + self.save_as_new = save_as_new + if queryset is None: + queryset = self.model._default_manager + if self.instance.pk is not None: + qs = queryset.filter(**{self.fk.name: self.instance}) + else: + qs = queryset.none() + self.unique_fields = {self.fk.name} + super().__init__(data, files, prefix=prefix, queryset=qs, **kwargs) + + # Add the generated field to form._meta.fields if it's defined to make + # sure validation isn't skipped on that field. + if self.form._meta.fields and self.fk.name not in self.form._meta.fields: + if isinstance(self.form._meta.fields, tuple): + self.form._meta.fields = list(self.form._meta.fields) + self.form._meta.fields.append(self.fk.name) + + def initial_form_count(self): + if self.save_as_new: + return 0 + return super().initial_form_count() + + def _construct_form(self, i, **kwargs): + form = super()._construct_form(i, **kwargs) + if self.save_as_new: + mutable = getattr(form.data, "_mutable", None) + # Allow modifying an immutable QueryDict. + if mutable is not None: + form.data._mutable = True + # Remove the primary key from the form's data, we are only + # creating new instances + form.data[form.add_prefix(self._pk_field.name)] = None + # Remove the foreign key from the form's data + form.data[form.add_prefix(self.fk.name)] = None + if mutable is not None: + form.data._mutable = mutable + + # Set the fk value here so that the form can do its validation. + fk_value = self.instance.pk + if self.fk.remote_field.field_name != self.fk.remote_field.model._meta.pk.name: + fk_value = getattr(self.instance, self.fk.remote_field.field_name) + fk_value = getattr(fk_value, "pk", fk_value) + setattr(form.instance, self.fk.get_attname(), fk_value) + return form + + @classmethod + def get_default_prefix(cls): + return cls.fk.remote_field.get_accessor_name(model=cls.model).replace("+", "") + + def save_new(self, form, commit=True): + # Ensure the latest copy of the related instance is present on each + # form (it may have been saved after the formset was originally + # instantiated). + setattr(form.instance, self.fk.name, self.instance) + return super().save_new(form, commit=commit) + + def add_fields(self, form, index): + super().add_fields(form, index) + if self._pk_field == self.fk: + name = self._pk_field.name + kwargs = {"pk_field": True} + else: + # The foreign key field might not be on the form, so we poke at the + # Model field to get the label, since we need that for error messages. + name = self.fk.name + kwargs = { + "label": getattr( + form.fields.get(name), "label", capfirst(self.fk.verbose_name) + ) + } + + # The InlineForeignKeyField assumes that the foreign key relation is + # based on the parent model's pk. If this isn't the case, set to_field + # to correctly resolve the initial form value. + if self.fk.remote_field.field_name != self.fk.remote_field.model._meta.pk.name: + kwargs["to_field"] = self.fk.remote_field.field_name + + # If we're adding a new object, ignore a parent's auto-generated key + # as it will be regenerated on the save request. + if self.instance._state.adding: + if kwargs.get("to_field") is not None: + to_field = self.instance._meta.get_field(kwargs["to_field"]) + else: + to_field = self.instance._meta.pk + + if to_field.has_default() and ( + # Don't ignore a parent's auto-generated key if it's not the + # parent model's pk and form data is provided. + to_field.attname == self.fk.remote_field.model._meta.pk.name + or not form.data + ): + setattr(self.instance, to_field.attname, None) + + form.fields[name] = InlineForeignKeyField(self.instance, **kwargs) + + def get_unique_error_message(self, unique_check): + unique_check = [field for field in unique_check if field != self.fk.name] + return super().get_unique_error_message(unique_check) + + +def _get_foreign_key(parent_model, model, fk_name=None, can_fail=False): + """ + Find and return the ForeignKey from model to parent if there is one + (return None if can_fail is True and no such field exists). If fk_name is + provided, assume it is the name of the ForeignKey field. Unless can_fail is + True, raise an exception if there isn't a ForeignKey from model to + parent_model. + """ + # avoid circular import + from django.db.models import ForeignKey + + opts = model._meta + if fk_name: + fks_to_parent = [f for f in opts.fields if f.name == fk_name] + if len(fks_to_parent) == 1: + fk = fks_to_parent[0] + parent_list = parent_model._meta.get_parent_list() + if ( + not isinstance(fk, ForeignKey) + or ( + # ForeignKey to proxy models. + fk.remote_field.model._meta.proxy + and fk.remote_field.model._meta.proxy_for_model not in parent_list + ) + or ( + # ForeignKey to concrete models. + not fk.remote_field.model._meta.proxy + and fk.remote_field.model != parent_model + and fk.remote_field.model not in parent_list + ) + ): + raise ValueError( + "fk_name '%s' is not a ForeignKey to '%s'." + % (fk_name, parent_model._meta.label) + ) + elif not fks_to_parent: + raise ValueError( + "'%s' has no field named '%s'." % (model._meta.label, fk_name) + ) + else: + # Try to discover what the ForeignKey from model to parent_model is + parent_list = parent_model._meta.get_parent_list() + fks_to_parent = [ + f + for f in opts.fields + if isinstance(f, ForeignKey) + and ( + f.remote_field.model == parent_model + or f.remote_field.model in parent_list + or ( + f.remote_field.model._meta.proxy + and f.remote_field.model._meta.proxy_for_model in parent_list + ) + ) + ] + if len(fks_to_parent) == 1: + fk = fks_to_parent[0] + elif not fks_to_parent: + if can_fail: + return + raise ValueError( + "'%s' has no ForeignKey to '%s'." + % ( + model._meta.label, + parent_model._meta.label, + ) + ) + else: + raise ValueError( + "'%s' has more than one ForeignKey to '%s'. You must specify " + "a 'fk_name' attribute." + % ( + model._meta.label, + parent_model._meta.label, + ) + ) + return fk + + +def inlineformset_factory( + parent_model, + model, + form=ModelForm, + formset=BaseInlineFormSet, + fk_name=None, + fields=None, + exclude=None, + extra=3, + can_order=False, + can_delete=True, + max_num=None, + formfield_callback=None, + widgets=None, + validate_max=False, + localized_fields=None, + labels=None, + help_texts=None, + error_messages=None, + min_num=None, + validate_min=False, + field_classes=None, + absolute_max=None, + can_delete_extra=True, + renderer=None, + edit_only=False, +): + """ + Return an ``InlineFormSet`` for the given kwargs. + + ``fk_name`` must be provided if ``model`` has more than one ``ForeignKey`` + to ``parent_model``. + """ + fk = _get_foreign_key(parent_model, model, fk_name=fk_name) + # enforce a max_num=1 when the foreign key to the parent model is unique. + if fk.unique: + max_num = 1 + kwargs = { + "form": form, + "formfield_callback": formfield_callback, + "formset": formset, + "extra": extra, + "can_delete": can_delete, + "can_order": can_order, + "fields": fields, + "exclude": exclude, + "min_num": min_num, + "max_num": max_num, + "widgets": widgets, + "validate_min": validate_min, + "validate_max": validate_max, + "localized_fields": localized_fields, + "labels": labels, + "help_texts": help_texts, + "error_messages": error_messages, + "field_classes": field_classes, + "absolute_max": absolute_max, + "can_delete_extra": can_delete_extra, + "renderer": renderer, + "edit_only": edit_only, + } + FormSet = modelformset_factory(model, **kwargs) + FormSet.fk = fk + return FormSet + + +# Fields ##################################################################### + + +class InlineForeignKeyField(Field): + """ + A basic integer field that deals with validating the given value to a + given parent instance in an inline. + """ + + widget = HiddenInput + default_error_messages = { + "invalid_choice": _("The inline value did not match the parent instance."), + } + + def __init__(self, parent_instance, *args, pk_field=False, to_field=None, **kwargs): + self.parent_instance = parent_instance + self.pk_field = pk_field + self.to_field = to_field + if self.parent_instance is not None: + if self.to_field: + kwargs["initial"] = getattr(self.parent_instance, self.to_field) + else: + kwargs["initial"] = self.parent_instance.pk + kwargs["required"] = False + super().__init__(*args, **kwargs) + + def clean(self, value): + if value in self.empty_values: + if self.pk_field: + return None + # if there is no value act as we did before. + return self.parent_instance + # ensure the we compare the values as equal types. + if self.to_field: + orig = getattr(self.parent_instance, self.to_field) + else: + orig = self.parent_instance.pk + if str(value) != str(orig): + raise ValidationError( + self.error_messages["invalid_choice"], code="invalid_choice" + ) + return self.parent_instance + + def has_changed(self, initial, data): + return False + + +class ModelChoiceIteratorValue: + def __init__(self, value, instance): + self.value = value + self.instance = instance + + def __str__(self): + return str(self.value) + + def __hash__(self): + return hash(self.value) + + def __eq__(self, other): + if isinstance(other, ModelChoiceIteratorValue): + other = other.value + return self.value == other + + +class ModelChoiceIterator(BaseChoiceIterator): + def __init__(self, field): + self.field = field + self.queryset = field.queryset + + def __iter__(self): + if self.field.empty_label is not None: + yield ("", self.field.empty_label) + queryset = self.queryset + # Can't use iterator() when queryset uses prefetch_related() + if not queryset._prefetch_related_lookups: + queryset = queryset.iterator() + for obj in queryset: + yield self.choice(obj) + + def __len__(self): + # count() adds a query but uses less memory since the QuerySet results + # won't be cached. In most cases, the choices will only be iterated on, + # and __len__() won't be called. + return self.queryset.count() + (1 if self.field.empty_label is not None else 0) + + def __bool__(self): + return self.field.empty_label is not None or self.queryset.exists() + + def choice(self, obj): + return ( + ModelChoiceIteratorValue(self.field.prepare_value(obj), obj), + self.field.label_from_instance(obj), + ) + + +class ModelChoiceField(ChoiceField): + """A ChoiceField whose choices are a model QuerySet.""" + + # This class is a subclass of ChoiceField for purity, but it doesn't + # actually use any of ChoiceField's implementation. + default_error_messages = { + "invalid_choice": _( + "Select a valid choice. That choice is not one of the available choices." + ), + } + iterator = ModelChoiceIterator + + def __init__( + self, + queryset, + *, + empty_label="---------", + required=True, + widget=None, + label=None, + initial=None, + help_text="", + to_field_name=None, + limit_choices_to=None, + blank=False, + **kwargs, + ): + # Call Field instead of ChoiceField __init__() because we don't need + # ChoiceField.__init__(). + Field.__init__( + self, + required=required, + widget=widget, + label=label, + initial=initial, + help_text=help_text, + **kwargs, + ) + if (required and initial is not None) or ( + isinstance(self.widget, RadioSelect) and not blank + ): + self.empty_label = None + else: + self.empty_label = empty_label + self.queryset = queryset + self.limit_choices_to = limit_choices_to # limit the queryset later. + self.to_field_name = to_field_name + + def get_limit_choices_to(self): + """ + Return ``limit_choices_to`` for this form field. + + If it is a callable, invoke it and return the result. + """ + if callable(self.limit_choices_to): + return self.limit_choices_to() + return self.limit_choices_to + + def __deepcopy__(self, memo): + result = super(ChoiceField, self).__deepcopy__(memo) + # Need to force a new ModelChoiceIterator to be created, bug #11183 + if self.queryset is not None: + result.queryset = self.queryset.all() + return result + + def _get_queryset(self): + return self._queryset + + def _set_queryset(self, queryset): + self._queryset = None if queryset is None else queryset.all() + self.widget.choices = self.choices + + queryset = property(_get_queryset, _set_queryset) + + # this method will be used to create object labels by the QuerySetIterator. + # Override it to customize the label. + def label_from_instance(self, obj): + """ + Convert objects into strings and generate the labels for the choices + presented by this object. Subclasses can override this method to + customize the display of the choices. + """ + return str(obj) + + def _get_choices(self): + # If self._choices is set, then somebody must have manually set + # the property self.choices. In this case, just return self._choices. + if hasattr(self, "_choices"): + return self._choices + + # Otherwise, execute the QuerySet in self.queryset to determine the + # choices dynamically. Return a fresh ModelChoiceIterator that has not been + # consumed. Note that we're instantiating a new ModelChoiceIterator *each* + # time _get_choices() is called (and, thus, each time self.choices is + # accessed) so that we can ensure the QuerySet has not been consumed. This + # construct might look complicated but it allows for lazy evaluation of + # the queryset. + return self.iterator(self) + + choices = property(_get_choices, ChoiceField.choices.fset) + + def prepare_value(self, value): + if hasattr(value, "_meta"): + if self.to_field_name: + return value.serializable_value(self.to_field_name) + else: + return value.pk + return super().prepare_value(value) + + def to_python(self, value): + if value in self.empty_values: + return None + try: + key = self.to_field_name or "pk" + if isinstance(value, self.queryset.model): + value = getattr(value, key) + value = self.queryset.get(**{key: value}) + except (ValueError, TypeError, self.queryset.model.DoesNotExist): + raise ValidationError( + self.error_messages["invalid_choice"], + code="invalid_choice", + params={"value": value}, + ) + return value + + def validate(self, value): + return Field.validate(self, value) + + def has_changed(self, initial, data): + if self.disabled: + return False + initial_value = initial if initial is not None else "" + data_value = data if data is not None else "" + return str(self.prepare_value(initial_value)) != str(data_value) + + +class ModelMultipleChoiceField(ModelChoiceField): + """A MultipleChoiceField whose choices are a model QuerySet.""" + + widget = SelectMultiple + hidden_widget = MultipleHiddenInput + default_error_messages = { + "invalid_list": _("Enter a list of values."), + "invalid_choice": _( + "Select a valid choice. %(value)s is not one of the available choices." + ), + "invalid_pk_value": _("“%(pk)s” is not a valid value."), + } + + def __init__(self, queryset, **kwargs): + super().__init__(queryset, empty_label=None, **kwargs) + + def to_python(self, value): + if not value: + return [] + return list(self._check_values(value)) + + def clean(self, value): + value = self.prepare_value(value) + if self.required and not value: + raise ValidationError(self.error_messages["required"], code="required") + elif not self.required and not value: + return self.queryset.none() + if not isinstance(value, (list, tuple)): + raise ValidationError( + self.error_messages["invalid_list"], + code="invalid_list", + ) + qs = self._check_values(value) + # Since this overrides the inherited ModelChoiceField.clean + # we run custom validators here + self.run_validators(value) + return qs + + def _check_values(self, value): + """ + Given a list of possible PK values, return a QuerySet of the + corresponding objects. Raise a ValidationError if a given value is + invalid (not a valid PK, not in the queryset, etc.) + """ + key = self.to_field_name or "pk" + # deduplicate given values to avoid creating many querysets or + # requiring the database backend deduplicate efficiently. + try: + value = frozenset(value) + except TypeError: + # list of lists isn't hashable, for example + raise ValidationError( + self.error_messages["invalid_list"], + code="invalid_list", + ) + for pk in value: + try: + self.queryset.filter(**{key: pk}) + except (ValueError, TypeError): + raise ValidationError( + self.error_messages["invalid_pk_value"], + code="invalid_pk_value", + params={"pk": pk}, + ) + qs = self.queryset.filter(**{"%s__in" % key: value}) + pks = {str(getattr(o, key)) for o in qs} + for val in value: + if str(val) not in pks: + raise ValidationError( + self.error_messages["invalid_choice"], + code="invalid_choice", + params={"value": val}, + ) + return qs + + def prepare_value(self, value): + if ( + hasattr(value, "__iter__") + and not isinstance(value, str) + and not hasattr(value, "_meta") + ): + prepare_value = super().prepare_value + return [prepare_value(v) for v in value] + return super().prepare_value(value) + + def has_changed(self, initial, data): + if self.disabled: + return False + if initial is None: + initial = [] + if data is None: + data = [] + if len(initial) != len(data): + return True + initial_set = {str(value) for value in self.prepare_value(initial)} + data_set = {str(value) for value in data} + return data_set != initial_set + + +def modelform_defines_fields(form_class): + return hasattr(form_class, "_meta") and ( + form_class._meta.fields is not None or form_class._meta.exclude is not None + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/renderers.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/renderers.py new file mode 100644 index 0000000..970d058 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/renderers.py @@ -0,0 +1,110 @@ +import functools +import warnings +from pathlib import Path + +from django.conf import settings +from django.template.backends.django import DjangoTemplates +from django.template.loader import get_template +from django.utils.deprecation import RemovedInDjango60Warning +from django.utils.functional import cached_property +from django.utils.module_loading import import_string + + +@functools.lru_cache +def get_default_renderer(): + renderer_class = import_string(settings.FORM_RENDERER) + return renderer_class() + + +class BaseRenderer: + form_template_name = "django/forms/div.html" + formset_template_name = "django/forms/formsets/div.html" + field_template_name = "django/forms/field.html" + + def get_template(self, template_name): + raise NotImplementedError("subclasses must implement get_template()") + + def render(self, template_name, context, request=None): + template = self.get_template(template_name) + return template.render(context, request=request).strip() + + +class EngineMixin: + def get_template(self, template_name): + return self.engine.get_template(template_name) + + @cached_property + def engine(self): + return self.backend( + { + "APP_DIRS": True, + "DIRS": [Path(__file__).parent / self.backend.app_dirname], + "NAME": "djangoforms", + "OPTIONS": {}, + } + ) + + +class DjangoTemplates(EngineMixin, BaseRenderer): + """ + Load Django templates from the built-in widget templates in + django/forms/templates and from apps' 'templates' directory. + """ + + backend = DjangoTemplates + + +class Jinja2(EngineMixin, BaseRenderer): + """ + Load Jinja2 templates from the built-in widget templates in + django/forms/jinja2 and from apps' 'jinja2' directory. + """ + + @cached_property + def backend(self): + from django.template.backends.jinja2 import Jinja2 + + return Jinja2 + + +# RemovedInDjango60Warning. +class DjangoDivFormRenderer(DjangoTemplates): + """ + Load Django templates from django/forms/templates and from apps' + 'templates' directory and use the 'div.html' template to render forms and + formsets. + """ + + def __init__(self, *args, **kwargs): + warnings.warn( + "The DjangoDivFormRenderer transitional form renderer is deprecated. Use " + "DjangoTemplates instead.", + RemovedInDjango60Warning, + ) + super().__init__(*args, **kwargs) + + +# RemovedInDjango60Warning. +class Jinja2DivFormRenderer(Jinja2): + """ + Load Jinja2 templates from the built-in widget templates in + django/forms/jinja2 and from apps' 'jinja2' directory. + """ + + def __init__(self, *args, **kwargs): + warnings.warn( + "The Jinja2DivFormRenderer transitional form renderer is deprecated. Use " + "Jinja2 instead.", + RemovedInDjango60Warning, + ) + super().__init__(*args, **kwargs) + + +class TemplatesSetting(BaseRenderer): + """ + Load templates using template.loader.get_template() which is configured + based on settings.TEMPLATES. + """ + + def get_template(self, template_name): + return get_template(template_name) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/attrs.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/attrs.html new file mode 100644 index 0000000..50de36b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/attrs.html @@ -0,0 +1 @@ +{% for name, value in attrs.items %}{% if value is not False %} {{ name }}{% if value is not True %}="{{ value|stringformat:'s' }}"{% endif %}{% endif %}{% endfor %} \ No newline at end of file diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/div.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/div.html new file mode 100644 index 0000000..c20eead --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/div.html @@ -0,0 +1,15 @@ +{{ errors }} +{% if errors and not fields %} +
    {% for field in hidden_fields %}{{ field }}{% endfor %}
    +{% endif %} +{% for field, errors in fields %} + + {{ field.as_field_group }} + {% if forloop.last %} + {% for field in hidden_fields %}{{ field }}{% endfor %} + {% endif %} + +{% endfor %} +{% if not fields and not errors %} + {% for field in hidden_fields %}{{ field }}{% endfor %} +{% endif %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/errors/dict/default.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/errors/dict/default.html new file mode 100644 index 0000000..8a833c6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/errors/dict/default.html @@ -0,0 +1 @@ +{% include "django/forms/errors/dict/ul.html" %} \ No newline at end of file diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/errors/dict/text.txt b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/errors/dict/text.txt new file mode 100644 index 0000000..dc9fd80 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/errors/dict/text.txt @@ -0,0 +1,3 @@ +{% for field, errors in errors %}* {{ field }} +{% for error in errors %} * {{ error }} +{% endfor %}{% endfor %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/errors/dict/ul.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/errors/dict/ul.html new file mode 100644 index 0000000..c16fd65 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/errors/dict/ul.html @@ -0,0 +1 @@ +{% if errors %}
      {% for field, error in errors %}
    • {{ field }}{{ error }}
    • {% endfor %}
    {% endif %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/errors/list/default.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/errors/list/default.html new file mode 100644 index 0000000..b174f26 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/errors/list/default.html @@ -0,0 +1 @@ +{% include "django/forms/errors/list/ul.html" %} \ No newline at end of file diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/errors/list/text.txt b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/errors/list/text.txt new file mode 100644 index 0000000..aa7f870 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/errors/list/text.txt @@ -0,0 +1,2 @@ +{% for error in errors %}* {{ error }} +{% endfor %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/errors/list/ul.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/errors/list/ul.html new file mode 100644 index 0000000..57b34cc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/errors/list/ul.html @@ -0,0 +1 @@ +{% if errors %}
      {% for error in errors %}
    • {{ error }}
    • {% endfor %}
    {% endif %} \ No newline at end of file diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/field.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/field.html new file mode 100644 index 0000000..f8b0cde --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/field.html @@ -0,0 +1,10 @@ +{% if field.use_fieldset %} +
    + {% if field.label %}{{ field.legend_tag }}{% endif %} +{% else %} + {% if field.label %}{{ field.label_tag }}{% endif %} +{% endif %} +{% if field.help_text %}
    {{ field.help_text|safe }}
    {% endif %} +{{ field.errors }} +{{ field }} +{% if field.use_fieldset %}
    {% endif %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/formsets/div.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/formsets/div.html new file mode 100644 index 0000000..9349989 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/formsets/div.html @@ -0,0 +1 @@ +{{ formset.management_form }}{% for form in formset %}{{ form.as_div }}{% endfor %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/formsets/p.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/formsets/p.html new file mode 100644 index 0000000..00c2df6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/formsets/p.html @@ -0,0 +1 @@ +{{ formset.management_form }}{% for form in formset %}{{ form.as_p }}{% endfor %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/formsets/table.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/formsets/table.html new file mode 100644 index 0000000..4fa5e42 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/formsets/table.html @@ -0,0 +1 @@ +{{ formset.management_form }}{% for form in formset %}{{ form.as_table }}{% endfor %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/formsets/ul.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/formsets/ul.html new file mode 100644 index 0000000..272e129 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/formsets/ul.html @@ -0,0 +1 @@ +{{ formset.management_form }}{% for form in formset %}{{ form.as_ul }}{% endfor %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/label.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/label.html new file mode 100644 index 0000000..0eba630 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/label.html @@ -0,0 +1 @@ +{% if use_tag %}<{{ tag }}{% include 'django/forms/attrs.html' %}>{{ label }}{% else %}{{ label }}{% endif %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/p.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/p.html new file mode 100644 index 0000000..89f0a2b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/p.html @@ -0,0 +1,20 @@ +{{ errors }} +{% if errors and not fields %} +

    {% for field in hidden_fields %}{{ field }}{% endfor %}

    +{% endif %} +{% for field, errors in fields %} + {{ errors }} + + {% if field.label %}{{ field.label_tag }}{% endif %} + {{ field }} + {% if field.help_text %} + {{ field.help_text|safe }} + {% endif %} + {% if forloop.last %} + {% for field in hidden_fields %}{{ field }}{% endfor %} + {% endif %} +

    +{% endfor %} +{% if not fields and not errors %} + {% for field in hidden_fields %}{{ field }}{% endfor %} +{% endif %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/table.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/table.html new file mode 100644 index 0000000..4fbd3b9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/table.html @@ -0,0 +1,29 @@ +{% if errors %} + + + {{ errors }} + {% if not fields %} + {% for field in hidden_fields %}{{ field }}{% endfor %} + {% endif %} + + +{% endif %} +{% for field, errors in fields %} + + {% if field.label %}{{ field.label_tag }}{% endif %} + + {{ errors }} + {{ field }} + {% if field.help_text %} +
    + {{ field.help_text|safe }} + {% endif %} + {% if forloop.last %} + {% for field in hidden_fields %}{{ field }}{% endfor %} + {% endif %} + + +{% endfor %} +{% if not fields and not errors %} + {% for field in hidden_fields %}{{ field }}{% endfor %} +{% endif %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/ul.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/ul.html new file mode 100644 index 0000000..d78a79a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/ul.html @@ -0,0 +1,24 @@ +{% if errors %} +
  • + {{ errors }} + {% if not fields %} + {% for field in hidden_fields %}{{ field }}{% endfor %} + {% endif %} +
  • +{% endif %} +{% for field, errors in fields %} + + {{ errors }} + {% if field.label %}{{ field.label_tag }}{% endif %} + {{ field }} + {% if field.help_text %} + {{ field.help_text|safe }} + {% endif %} + {% if forloop.last %} + {% for field in hidden_fields %}{{ field }}{% endfor %} + {% endif %} + +{% endfor %} +{% if not fields and not errors %} + {% for field in hidden_fields %}{{ field }}{% endfor %} +{% endif %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/attrs.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/attrs.html new file mode 100644 index 0000000..7a5592a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/attrs.html @@ -0,0 +1 @@ +{% for name, value in widget.attrs.items %}{% if value is not False %} {{ name }}{% if value is not True %}="{{ value|stringformat:'s' }}"{% endif %}{% endif %}{% endfor %} \ No newline at end of file diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/checkbox.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/checkbox.html new file mode 100644 index 0000000..08b1e61 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/checkbox.html @@ -0,0 +1 @@ +{% include "django/forms/widgets/input.html" %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/checkbox_option.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/checkbox_option.html new file mode 100644 index 0000000..bb9acba --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/checkbox_option.html @@ -0,0 +1 @@ +{% include "django/forms/widgets/input_option.html" %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/checkbox_select.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/checkbox_select.html new file mode 100644 index 0000000..780899a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/checkbox_select.html @@ -0,0 +1 @@ +{% include "django/forms/widgets/multiple_input.html" %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/clearable_file_input.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/clearable_file_input.html new file mode 100644 index 0000000..9381283 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/clearable_file_input.html @@ -0,0 +1,5 @@ +{% if widget.is_initial %}{{ widget.initial_text }}: {{ widget.value }}{% if not widget.required %} + +{% endif %}
    +{{ widget.input_text }}:{% endif %} + diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/date.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/date.html new file mode 100644 index 0000000..08b1e61 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/date.html @@ -0,0 +1 @@ +{% include "django/forms/widgets/input.html" %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/datetime.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/datetime.html new file mode 100644 index 0000000..08b1e61 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/datetime.html @@ -0,0 +1 @@ +{% include "django/forms/widgets/input.html" %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/email.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/email.html new file mode 100644 index 0000000..08b1e61 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/email.html @@ -0,0 +1 @@ +{% include "django/forms/widgets/input.html" %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/file.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/file.html new file mode 100644 index 0000000..08b1e61 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/file.html @@ -0,0 +1 @@ +{% include "django/forms/widgets/input.html" %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/hidden.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/hidden.html new file mode 100644 index 0000000..08b1e61 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/hidden.html @@ -0,0 +1 @@ +{% include "django/forms/widgets/input.html" %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/input.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/input.html new file mode 100644 index 0000000..9010a92 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/input.html @@ -0,0 +1 @@ + diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/input_option.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/input_option.html new file mode 100644 index 0000000..48cd65b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/input_option.html @@ -0,0 +1 @@ +{% if widget.wrap_label %}{% endif %}{% include "django/forms/widgets/input.html" %}{% if widget.wrap_label %} {{ widget.label }}{% endif %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/multiple_hidden.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/multiple_hidden.html new file mode 100644 index 0000000..b9695de --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/multiple_hidden.html @@ -0,0 +1 @@ +{% include "django/forms/widgets/multiwidget.html" %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/multiple_input.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/multiple_input.html new file mode 100644 index 0000000..2a0fec6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/multiple_input.html @@ -0,0 +1,5 @@ +{% with id=widget.attrs.id %}{% for group, options, index in widget.optgroups %}{% if group %} +
    {% endif %}{% for option in options %}
    + {% include option.template_name with widget=option %}
    {% endfor %}{% if group %} +
    {% endif %}{% endfor %} +{% endwith %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/multiwidget.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/multiwidget.html new file mode 100644 index 0000000..7e687a1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/multiwidget.html @@ -0,0 +1 @@ +{% spaceless %}{% for widget in widget.subwidgets %}{% include widget.template_name %}{% endfor %}{% endspaceless %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/number.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/number.html new file mode 100644 index 0000000..08b1e61 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/number.html @@ -0,0 +1 @@ +{% include "django/forms/widgets/input.html" %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/password.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/password.html new file mode 100644 index 0000000..08b1e61 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/password.html @@ -0,0 +1 @@ +{% include "django/forms/widgets/input.html" %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/radio.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/radio.html new file mode 100644 index 0000000..780899a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/radio.html @@ -0,0 +1 @@ +{% include "django/forms/widgets/multiple_input.html" %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/radio_option.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/radio_option.html new file mode 100644 index 0000000..bb9acba --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/radio_option.html @@ -0,0 +1 @@ +{% include "django/forms/widgets/input_option.html" %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/select.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/select.html new file mode 100644 index 0000000..4d1f6b0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/select.html @@ -0,0 +1,5 @@ + diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/select_date.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/select_date.html new file mode 100644 index 0000000..32fda82 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/select_date.html @@ -0,0 +1 @@ +{% include 'django/forms/widgets/multiwidget.html' %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/select_option.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/select_option.html new file mode 100644 index 0000000..8d31961 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/select_option.html @@ -0,0 +1 @@ + diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/splitdatetime.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/splitdatetime.html new file mode 100644 index 0000000..32fda82 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/splitdatetime.html @@ -0,0 +1 @@ +{% include 'django/forms/widgets/multiwidget.html' %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/splithiddendatetime.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/splithiddendatetime.html new file mode 100644 index 0000000..32fda82 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/splithiddendatetime.html @@ -0,0 +1 @@ +{% include 'django/forms/widgets/multiwidget.html' %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/text.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/text.html new file mode 100644 index 0000000..08b1e61 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/text.html @@ -0,0 +1 @@ +{% include "django/forms/widgets/input.html" %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/textarea.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/textarea.html new file mode 100644 index 0000000..b86766c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/textarea.html @@ -0,0 +1,2 @@ + diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/time.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/time.html new file mode 100644 index 0000000..08b1e61 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/time.html @@ -0,0 +1 @@ +{% include "django/forms/widgets/input.html" %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/url.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/url.html new file mode 100644 index 0000000..08b1e61 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/templates/django/forms/widgets/url.html @@ -0,0 +1 @@ +{% include "django/forms/widgets/input.html" %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/utils.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/utils.py new file mode 100644 index 0000000..f4fbf3e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/utils.py @@ -0,0 +1,244 @@ +import json +from collections import UserList + +from django.conf import settings +from django.core.exceptions import ValidationError +from django.forms.renderers import get_default_renderer +from django.utils import timezone +from django.utils.html import escape, format_html_join +from django.utils.safestring import mark_safe +from django.utils.translation import gettext_lazy as _ + + +def pretty_name(name): + """Convert 'first_name' to 'First name'.""" + if not name: + return "" + return name.replace("_", " ").capitalize() + + +def flatatt(attrs): + """ + Convert a dictionary of attributes to a single string. + The returned string will contain a leading space followed by key="value", + XML-style pairs. In the case of a boolean value, the key will appear + without a value. It is assumed that the keys do not need to be + XML-escaped. If the passed dictionary is empty, then return an empty + string. + + The result is passed through 'mark_safe' (by way of 'format_html_join'). + """ + key_value_attrs = [] + boolean_attrs = [] + for attr, value in attrs.items(): + if isinstance(value, bool): + if value: + boolean_attrs.append((attr,)) + elif value is not None: + key_value_attrs.append((attr, value)) + + return format_html_join("", ' {}="{}"', sorted(key_value_attrs)) + format_html_join( + "", " {}", sorted(boolean_attrs) + ) + + +class RenderableMixin: + def get_context(self): + raise NotImplementedError( + "Subclasses of RenderableMixin must provide a get_context() method." + ) + + def render(self, template_name=None, context=None, renderer=None): + renderer = renderer or self.renderer + template = template_name or self.template_name + context = context or self.get_context() + return mark_safe(renderer.render(template, context)) + + __str__ = render + __html__ = render + + +class RenderableFieldMixin(RenderableMixin): + def as_field_group(self): + return self.render() + + def as_hidden(self): + raise NotImplementedError( + "Subclasses of RenderableFieldMixin must provide an as_hidden() method." + ) + + def as_widget(self): + raise NotImplementedError( + "Subclasses of RenderableFieldMixin must provide an as_widget() method." + ) + + def __str__(self): + """Render this field as an HTML widget.""" + if self.field.show_hidden_initial: + return self.as_widget() + self.as_hidden(only_initial=True) + return self.as_widget() + + __html__ = __str__ + + +class RenderableFormMixin(RenderableMixin): + def as_p(self): + """Render as

    elements.""" + return self.render(self.template_name_p) + + def as_table(self): + """Render as elements excluding the surrounding tag.""" + return self.render(self.template_name_table) + + def as_ul(self): + """Render as
  • elements excluding the surrounding
      tag.""" + return self.render(self.template_name_ul) + + def as_div(self): + """Render as
      elements.""" + return self.render(self.template_name_div) + + +class RenderableErrorMixin(RenderableMixin): + def as_json(self, escape_html=False): + return json.dumps(self.get_json_data(escape_html)) + + def as_text(self): + return self.render(self.template_name_text) + + def as_ul(self): + return self.render(self.template_name_ul) + + +class ErrorDict(dict, RenderableErrorMixin): + """ + A collection of errors that knows how to display itself in various formats. + + The dictionary keys are the field names, and the values are the errors. + """ + + template_name = "django/forms/errors/dict/default.html" + template_name_text = "django/forms/errors/dict/text.txt" + template_name_ul = "django/forms/errors/dict/ul.html" + + def __init__(self, *args, renderer=None, **kwargs): + super().__init__(*args, **kwargs) + self.renderer = renderer or get_default_renderer() + + def as_data(self): + return {f: e.as_data() for f, e in self.items()} + + def get_json_data(self, escape_html=False): + return {f: e.get_json_data(escape_html) for f, e in self.items()} + + def get_context(self): + return { + "errors": self.items(), + "error_class": "errorlist", + } + + +class ErrorList(UserList, list, RenderableErrorMixin): + """ + A collection of errors that knows how to display itself in various formats. + """ + + template_name = "django/forms/errors/list/default.html" + template_name_text = "django/forms/errors/list/text.txt" + template_name_ul = "django/forms/errors/list/ul.html" + + def __init__(self, initlist=None, error_class=None, renderer=None): + super().__init__(initlist) + + if error_class is None: + self.error_class = "errorlist" + else: + self.error_class = "errorlist {}".format(error_class) + self.renderer = renderer or get_default_renderer() + + def as_data(self): + return ValidationError(self.data).error_list + + def copy(self): + copy = super().copy() + copy.error_class = self.error_class + return copy + + def get_json_data(self, escape_html=False): + errors = [] + for error in self.as_data(): + message = next(iter(error)) + errors.append( + { + "message": escape(message) if escape_html else message, + "code": error.code or "", + } + ) + return errors + + def get_context(self): + return { + "errors": self, + "error_class": self.error_class, + } + + def __repr__(self): + return repr(list(self)) + + def __contains__(self, item): + return item in list(self) + + def __eq__(self, other): + return list(self) == other + + def __getitem__(self, i): + error = self.data[i] + if isinstance(error, ValidationError): + return next(iter(error)) + return error + + def __reduce_ex__(self, *args, **kwargs): + # The `list` reduce function returns an iterator as the fourth element + # that is normally used for repopulating. Since we only inherit from + # `list` for `isinstance` backward compatibility (Refs #17413) we + # nullify this iterator as it would otherwise result in duplicate + # entries. (Refs #23594) + info = super(UserList, self).__reduce_ex__(*args, **kwargs) + return info[:3] + (None, None) + + +# Utilities for time zone support in DateTimeField et al. + + +def from_current_timezone(value): + """ + When time zone support is enabled, convert naive datetimes + entered in the current time zone to aware datetimes. + """ + if settings.USE_TZ and value is not None and timezone.is_naive(value): + current_timezone = timezone.get_current_timezone() + try: + if timezone._datetime_ambiguous_or_imaginary(value, current_timezone): + raise ValueError("Ambiguous or non-existent time.") + return timezone.make_aware(value, current_timezone) + except Exception as exc: + raise ValidationError( + _( + "%(datetime)s couldn’t be interpreted " + "in time zone %(current_timezone)s; it " + "may be ambiguous or it may not exist." + ), + code="ambiguous_timezone", + params={"datetime": value, "current_timezone": current_timezone}, + ) from exc + return value + + +def to_current_timezone(value): + """ + When time zone support is enabled, convert aware datetimes + to naive datetimes in the current time zone for display. + """ + if settings.USE_TZ and value is not None and timezone.is_aware(value): + return timezone.make_naive(value) + return value diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/widgets.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/widgets.py new file mode 100644 index 0000000..2c73405 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/forms/widgets.py @@ -0,0 +1,1206 @@ +""" +HTML Widget classes +""" + +import copy +import datetime +import warnings +from collections import defaultdict +from graphlib import CycleError, TopologicalSorter +from itertools import chain + +from django.forms.utils import to_current_timezone +from django.templatetags.static import static +from django.utils import formats +from django.utils.choices import normalize_choices +from django.utils.dates import MONTHS +from django.utils.formats import get_format +from django.utils.html import format_html, html_safe +from django.utils.regex_helper import _lazy_re_compile +from django.utils.safestring import mark_safe +from django.utils.translation import gettext_lazy as _ + +from .renderers import get_default_renderer + +__all__ = ( + "Media", + "MediaDefiningClass", + "Widget", + "TextInput", + "NumberInput", + "EmailInput", + "URLInput", + "PasswordInput", + "HiddenInput", + "MultipleHiddenInput", + "FileInput", + "ClearableFileInput", + "Textarea", + "DateInput", + "DateTimeInput", + "TimeInput", + "CheckboxInput", + "Select", + "NullBooleanSelect", + "SelectMultiple", + "RadioSelect", + "CheckboxSelectMultiple", + "MultiWidget", + "SplitDateTimeWidget", + "SplitHiddenDateTimeWidget", + "SelectDateWidget", +) + +MEDIA_TYPES = ("css", "js") + + +class MediaOrderConflictWarning(RuntimeWarning): + pass + + +@html_safe +class Media: + def __init__(self, media=None, css=None, js=None): + if media is not None: + css = getattr(media, "css", {}) + js = getattr(media, "js", []) + else: + if css is None: + css = {} + if js is None: + js = [] + self._css_lists = [css] + self._js_lists = [js] + + def __repr__(self): + return "Media(css=%r, js=%r)" % (self._css, self._js) + + def __str__(self): + return self.render() + + @property + def _css(self): + css = defaultdict(list) + for css_list in self._css_lists: + for medium, sublist in css_list.items(): + css[medium].append(sublist) + return {medium: self.merge(*lists) for medium, lists in css.items()} + + @property + def _js(self): + return self.merge(*self._js_lists) + + def render(self): + return mark_safe( + "\n".join( + chain.from_iterable( + getattr(self, "render_" + name)() for name in MEDIA_TYPES + ) + ) + ) + + def render_js(self): + return [ + path.__html__() + if hasattr(path, "__html__") + else format_html('', self.absolute_path(path)) + for path in self._js + ] + + def render_css(self): + # To keep rendering order consistent, we can't just iterate over items(). + # We need to sort the keys, and iterate over the sorted list. + media = sorted(self._css) + return chain.from_iterable( + [ + path.__html__() + if hasattr(path, "__html__") + else format_html( + '', + self.absolute_path(path), + medium, + ) + for path in self._css[medium] + ] + for medium in media + ) + + def absolute_path(self, path): + """ + Given a relative or absolute path to a static asset, return an absolute + path. An absolute path will be returned unchanged while a relative path + will be passed to django.templatetags.static.static(). + """ + if path.startswith(("http://", "https://", "/")): + return path + return static(path) + + def __getitem__(self, name): + """Return a Media object that only contains media of the given type.""" + if name in MEDIA_TYPES: + return Media(**{str(name): getattr(self, "_" + name)}) + raise KeyError('Unknown media type "%s"' % name) + + @staticmethod + def merge(*lists): + """ + Merge lists while trying to keep the relative order of the elements. + Warn if the lists have the same elements in a different relative order. + + For static assets it can be important to have them included in the DOM + in a certain order. In JavaScript you may not be able to reference a + global or in CSS you might want to override a style. + """ + ts = TopologicalSorter() + for head, *tail in filter(None, lists): + ts.add(head) # Ensure that the first items are included. + for item in tail: + if head != item: # Avoid circular dependency to self. + ts.add(item, head) + head = item + try: + return list(ts.static_order()) + except CycleError: + warnings.warn( + "Detected duplicate Media files in an opposite order: {}".format( + ", ".join(repr(list_) for list_ in lists) + ), + MediaOrderConflictWarning, + ) + return list(dict.fromkeys(chain.from_iterable(filter(None, lists)))) + + def __add__(self, other): + combined = Media() + combined._css_lists = self._css_lists[:] + combined._js_lists = self._js_lists[:] + for item in other._css_lists: + if item and item not in self._css_lists: + combined._css_lists.append(item) + for item in other._js_lists: + if item and item not in self._js_lists: + combined._js_lists.append(item) + return combined + + +def media_property(cls): + def _media(self): + # Get the media property of the superclass, if it exists + sup_cls = super(cls, self) + try: + base = sup_cls.media + except AttributeError: + base = Media() + + # Get the media definition for this class + definition = getattr(cls, "Media", None) + if definition: + extend = getattr(definition, "extend", True) + if extend: + if extend is True: + m = base + else: + m = Media() + for medium in extend: + m += base[medium] + return m + Media(definition) + return Media(definition) + return base + + return property(_media) + + +class MediaDefiningClass(type): + """ + Metaclass for classes that can have media definitions. + """ + + def __new__(mcs, name, bases, attrs): + new_class = super().__new__(mcs, name, bases, attrs) + + if "media" not in attrs: + new_class.media = media_property(new_class) + + return new_class + + +class Widget(metaclass=MediaDefiningClass): + needs_multipart_form = False # Determines does this widget need multipart form + is_localized = False + is_required = False + supports_microseconds = True + use_fieldset = False + + def __init__(self, attrs=None): + self.attrs = {} if attrs is None else attrs.copy() + + def __deepcopy__(self, memo): + obj = copy.copy(self) + obj.attrs = self.attrs.copy() + memo[id(self)] = obj + return obj + + @property + def is_hidden(self): + return self.input_type == "hidden" if hasattr(self, "input_type") else False + + def subwidgets(self, name, value, attrs=None): + context = self.get_context(name, value, attrs) + yield context["widget"] + + def format_value(self, value): + """ + Return a value as it should appear when rendered in a template. + """ + if value == "" or value is None: + return None + if self.is_localized: + return formats.localize_input(value) + return str(value) + + def get_context(self, name, value, attrs): + return { + "widget": { + "name": name, + "is_hidden": self.is_hidden, + "required": self.is_required, + "value": self.format_value(value), + "attrs": self.build_attrs(self.attrs, attrs), + "template_name": self.template_name, + }, + } + + def render(self, name, value, attrs=None, renderer=None): + """Render the widget as an HTML string.""" + context = self.get_context(name, value, attrs) + return self._render(self.template_name, context, renderer) + + def _render(self, template_name, context, renderer=None): + if renderer is None: + renderer = get_default_renderer() + return mark_safe(renderer.render(template_name, context)) + + def build_attrs(self, base_attrs, extra_attrs=None): + """Build an attribute dictionary.""" + return {**base_attrs, **(extra_attrs or {})} + + def value_from_datadict(self, data, files, name): + """ + Given a dictionary of data and this widget's name, return the value + of this widget or None if it's not provided. + """ + return data.get(name) + + def value_omitted_from_data(self, data, files, name): + return name not in data + + def id_for_label(self, id_): + """ + Return the HTML ID attribute of this Widget for use by a
  • + + + + + + + + + {% if raising_view_name %} + + + + + {% endif %} +
    Request Method:{{ request.META.REQUEST_METHOD }}
    Request URL:{{ request.build_absolute_uri }}
    Raised by:{{ raising_view_name }}
    + +

    + {% if urlpatterns %} +

    + Using the URLconf defined in {{ urlconf }}, + Django tried these URL patterns, in this order: +

    +
      + {% for pattern in urlpatterns %} +
    1. + {% for pat in pattern %} + {{ pat.pattern }} + {% if forloop.last and pat.name %}[name='{{ pat.name }}']{% endif %} + {% endfor %} +
    2. + {% endfor %} +
    +

    + {% if request_path %} + The current path, {{ request_path }}, + {% else %} + The empty path + {% endif %} + {% if resolved %}matched the last one.{% else %}didn’t match any of these.{% endif %} +

    + {% endif %} +
    + +
    +

    + You’re seeing this error because you have DEBUG = True in + your Django settings file. Change that to False, and Django + will display a standard 404 page. +

    +
    + + diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/views/templates/technical_500.html b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/views/templates/technical_500.html new file mode 100644 index 0000000..a5c1871 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/views/templates/technical_500.html @@ -0,0 +1,491 @@ + + + + + + {% if exception_type %}{{ exception_type }}{% else %}Report{% endif %} + {% if request %} at {{ request.path_info }}{% endif %} + + {% if not is_email %} + + {% endif %} + + +
    +

    {% if exception_type %}{{ exception_type }}{% else %}Report{% endif %} + {% if request %} at {{ request.path_info }}{% endif %}

    +
    {% if exception_value %}{{ exception_value|force_escape }}{% if exception_notes %}{{ exception_notes }}{% endif %}{% else %}No exception message supplied{% endif %}
    + +{% if request %} + + + + + + + + +{% endif %} + + + + +{% if exception_type %} + + + + +{% endif %} +{% if exception_type and exception_value %} + + + + +{% endif %} +{% if lastframe %} + + + + +{% endif %} +{% if raising_view_name %} + + + + +{% endif %} + + + + + + + + + + + + + + + + +
    Request Method:{{ request.META.REQUEST_METHOD }}
    Request URL:{{ request_insecure_uri }}
    Django Version:{{ django_version_info }}
    Exception Type:{{ exception_type }}
    Exception Value:
    {{ exception_value|force_escape }}
    Exception Location:{{ lastframe.filename }}, line {{ lastframe.lineno }}, in {{ lastframe.function }}
    Raised during:{{ raising_view_name }}
    Python Executable:{{ sys_executable }}
    Python Version:{{ sys_version_info }}
    Python Path:
    {{ sys_path|pprint }}
    Server time:{{server_time|date:"r"}}
    +
    +{% if unicode_hint %} +
    +

    Unicode error hint

    +

    The string that could not be encoded/decoded was: {{ unicode_hint }}

    +
    +{% endif %} +{% if template_does_not_exist %} +
    +

    Template-loader postmortem

    + {% if postmortem %} +

    Django tried loading these templates, in this order:

    + {% for entry in postmortem %} +

    Using engine {{ entry.backend.name }}:

    +
      + {% if entry.tried %} + {% for attempt in entry.tried %} +
    • {{ attempt.0.loader_name }}: {{ attempt.0.name }} ({{ attempt.1 }})
    • + {% endfor %} + {% else %} +
    • This engine did not provide a list of tried templates.
    • + {% endif %} +
    + {% endfor %} + {% else %} +

    No templates were found because your 'TEMPLATES' setting is not configured.

    + {% endif %} +
    +{% endif %} +{% if template_info %} +
    +

    Error during template rendering

    +

    In template {{ template_info.name }}, error at line {{ template_info.line }}

    +

    {{ template_info.message|force_escape }}

    + + {% for source_line in template_info.source_lines %} + {% if source_line.0 == template_info.line %} + + + + {% else %} + + + {% endif %} + {% endfor %} +
    {{ source_line.0 }}{{ template_info.before }}{{ template_info.during }}{{ template_info.after }}
    {{ source_line.0 }}{{ source_line.1 }}
    +
    +{% endif %} +{% if frames %} +
    +

    Traceback{% if not is_email %} + Switch to copy-and-paste view{% endif %} +

    +
    +
      + {% for frame in frames %} + {% ifchanged frame.exc_cause %}{% if frame.exc_cause %} +
    • + {% if frame.exc_cause_explicit %} + The above exception ({{ frame.exc_cause|force_escape }}) was the direct cause of the following exception: + {% else %} + During handling of the above exception ({{ frame.exc_cause|force_escape }}), another exception occurred: + {% endif %} +

    • + {% endif %}{% endifchanged %} +
    • + {% if frame.tb %} + {{ frame.filename }}, line {{ frame.lineno }}, in {{ frame.function }} + {% elif forloop.first %} + None + {% else %} + Traceback: None + {% endif %} + + {% if frame.context_line %} +
      + {% if frame.pre_context and not is_email %} +
        + {% for line in frame.pre_context %} +
      1. {{ line }}
      2. + {% endfor %} +
      + {% endif %} +
        +
      1. {{ frame.context_line }}{{ frame.colno }}
        {% if not is_email %} …{% endif %}
      2. +
      + {% if frame.post_context and not is_email %} +
        + {% for line in frame.post_context %} +
      1. {{ line }}
      2. + {% endfor %} +
      + {% endif %} +
      + {% endif %} + + {% if frame.vars %} + {% if is_email %} +
      +

      Local Vars

      +
      + {% else %} +
      + Local vars + {% endif %} + + + + + + + + + {% for var in frame.vars|dictsort:0 %} + + + + + {% endfor %} + +
      VariableValue
      {{ var.0 }}
      {{ var.1 }}
      + {% if not is_email %}
      {% endif %} + {% endif %} +
    • + {% endfor %} +
    +
    +{% if not is_email %} +
    +
    + + + + + +

    + +
    +
    +{% endif %} +
    +{% endif %} + +
    +

    Request information

    + +{% if request %} + {% if user_str %} +

    USER

    +

    {{ user_str }}

    + {% endif %} + +

    GET

    + {% if request.GET %} + + + + + + + + + {% for k, v in request_GET_items %} + + + + + {% endfor %} + +
    VariableValue
    {{ k }}
    {{ v|pprint }}
    + {% else %} +

    No GET data

    + {% endif %} + +

    POST

    + {% if filtered_POST_items %} + + + + + + + + + {% for k, v in filtered_POST_items %} + + + + + {% endfor %} + +
    VariableValue
    {{ k }}
    {{ v|pprint }}
    + {% else %} +

    No POST data

    + {% endif %} + +

    FILES

    + {% if request.FILES %} + + + + + + + + + {% for k, v in request_FILES_items %} + + + + + {% endfor %} + +
    VariableValue
    {{ k }}
    {{ v|pprint }}
    + {% else %} +

    No FILES data

    + {% endif %} + + + {% if request.COOKIES %} + + + + + + + + + {% for k, v in request_COOKIES_items %} + + + + + {% endfor %} + +
    VariableValue
    {{ k }}
    {{ v|pprint }}
    + {% else %} +

    No cookie data

    + {% endif %} + +

    META

    + + + + + + + + + {% for k, v in request_meta.items|dictsort:0 %} + + + + + {% endfor %} + +
    VariableValue
    {{ k }}
    {{ v|pprint }}
    +{% else %} +

    Request data not supplied

    +{% endif %} + +

    Settings

    +

    Using settings module {{ settings.SETTINGS_MODULE }}

    + + + + + + + + + {% for k, v in settings.items|dictsort:0 %} + + + + + {% endfor %} + +
    SettingValue
    {{ k }}
    {{ v|pprint }}
    + +
    +{% if not is_email %} +
    +

    + You’re seeing this error because you have DEBUG = True in your + Django settings file. Change that to False, and Django will + display a standard page generated by the handler for this status code. +

    +
    +{% endif %} + + diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/views/templates/technical_500.txt b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/views/templates/technical_500.txt new file mode 100644 index 0000000..5a75324 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/django/views/templates/technical_500.txt @@ -0,0 +1,66 @@ +{% firstof exception_type 'Report' %}{% if request %} at {{ request.path_info }}{% endif %} +{% firstof exception_value 'No exception message supplied' %} +{% if request %} +Request Method: {{ request.META.REQUEST_METHOD }} +Request URL: {{ request_insecure_uri }}{% endif %} +Django Version: {{ django_version_info }} +Python Executable: {{ sys_executable }} +Python Version: {{ sys_version_info }} +Python Path: {{ sys_path }} +Server time: {{server_time|date:"r"}} +Installed Applications: +{{ settings.INSTALLED_APPS|pprint }} +Installed Middleware: +{{ settings.MIDDLEWARE|pprint }} +{% if template_does_not_exist %}Template loader postmortem +{% if postmortem %}Django tried loading these templates, in this order: +{% for entry in postmortem %} +Using engine {{ entry.backend.name }}: +{% if entry.tried %}{% for attempt in entry.tried %} * {{ attempt.0.loader_name }}: {{ attempt.0.name }} ({{ attempt.1 }}) +{% endfor %}{% else %} This engine did not provide a list of tried templates. +{% endif %}{% endfor %} +{% else %}No templates were found because your 'TEMPLATES' setting is not configured. +{% endif %} +{% endif %}{% if template_info %} +Template error: +In template {{ template_info.name }}, error at line {{ template_info.line }} + {{ template_info.message }} +{% for source_line in template_info.source_lines %}{% if source_line.0 == template_info.line %} {{ source_line.0 }} : {{ template_info.before }} {{ template_info.during }} {{ template_info.after }}{% else %} {{ source_line.0 }} : {{ source_line.1 }}{% endif %}{% endfor %}{% endif %}{% if frames %} + +Traceback (most recent call last): +{% for frame in frames %}{% ifchanged frame.exc_cause %}{% if frame.exc_cause %} +{% if frame.exc_cause_explicit %}The above exception ({{ frame.exc_cause }}) was the direct cause of the following exception:{% else %}During handling of the above exception ({{ frame.exc_cause }}), another exception occurred:{% endif %} +{% endif %}{% endifchanged %} {% if frame.tb %}File "{{ frame.filename }}"{% if frame.context_line %}, line {{ frame.lineno }}{% endif %}, in {{ frame.function }} +{% if frame.context_line %} {% spaceless %}{{ frame.context_line }}{% endspaceless %}{{ frame.tb_area_colno }}{% endif %}{% elif forloop.first %}None{% else %}Traceback: None{% endif %} +{% endfor %} +{% if exception_type %}Exception Type: {{ exception_type }}{% if request %} at {{ request.path_info }}{% endif %} +{% if exception_value %}Exception Value: {{ exception_value }}{% endif %}{% if exception_notes %}{{ exception_notes }}{% endif %}{% endif %}{% endif %} +{% if raising_view_name %}Raised during: {{ raising_view_name }}{% endif %} +{% if request %}Request information: +{% if user_str %}USER: {{ user_str }}{% endif %} + +GET:{% for k, v in request_GET_items %} +{{ k }} = {{ v|stringformat:"r" }}{% empty %} No GET data{% endfor %} + +POST:{% for k, v in filtered_POST_items %} +{{ k }} = {{ v|stringformat:"r" }}{% empty %} No POST data{% endfor %} + +FILES:{% for k, v in request_FILES_items %} +{{ k }} = {{ v|stringformat:"r" }}{% empty %} No FILES data{% endfor %} + +COOKIES:{% for k, v in request_COOKIES_items %} +{{ k }} = {{ v|stringformat:"r" }}{% empty %} No cookie data{% endfor %} + +META:{% for k, v in request_meta.items|dictsort:0 %} +{{ k }} = {{ v|stringformat:"r" }}{% endfor %} +{% else %}Request data not supplied +{% endif %} +Settings: +Using settings module {{ settings.SETTINGS_MODULE }}{% for k, v in settings.items|dictsort:0 %} +{{ k }} = {{ v|stringformat:"r" }}{% endfor %} + +{% if not is_email %} +You’re seeing this error because you have DEBUG = True in your +Django settings file. Change that to False, and Django will +display a standard page generated by the handler for this status code. +{% endif %} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn-21.2.0.dist-info/INSTALLER b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn-21.2.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn-21.2.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn-21.2.0.dist-info/METADATA b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn-21.2.0.dist-info/METADATA new file mode 100644 index 0000000..ad966b9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn-21.2.0.dist-info/METADATA @@ -0,0 +1,124 @@ +Metadata-Version: 2.1 +Name: gunicorn +Version: 21.2.0 +Summary: WSGI HTTP Server for UNIX +Home-page: https://gunicorn.org +Author: Benoit Chesneau +Author-email: benoitc@gunicorn.org +License: MIT +Project-URL: Documentation, https://docs.gunicorn.org +Project-URL: Homepage, https://gunicorn.org +Project-URL: Issue tracker, https://github.com/benoitc/gunicorn/issues +Project-URL: Source code, https://github.com/benoitc/gunicorn +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Other Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Operating System :: POSIX +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Internet +Classifier: Topic :: Utilities +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Internet :: WWW/HTTP +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Server +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Requires-Python: >=3.5 +Requires-Dist: packaging +Requires-Dist: importlib-metadata ; python_version < "3.8" +Provides-Extra: eventlet +Requires-Dist: eventlet (>=0.24.1) ; extra == 'eventlet' +Provides-Extra: gevent +Requires-Dist: gevent (>=1.4.0) ; extra == 'gevent' +Provides-Extra: gthread +Provides-Extra: setproctitle +Requires-Dist: setproctitle ; extra == 'setproctitle' +Provides-Extra: tornado +Requires-Dist: tornado (>=0.2) ; extra == 'tornado' + +Gunicorn +-------- + +.. image:: https://img.shields.io/pypi/v/gunicorn.svg?style=flat + :alt: PyPI version + :target: https://pypi.python.org/pypi/gunicorn + +.. image:: https://img.shields.io/pypi/pyversions/gunicorn.svg + :alt: Supported Python versions + :target: https://pypi.python.org/pypi/gunicorn + +.. image:: https://github.com/benoitc/gunicorn/actions/workflows/tox.yml/badge.svg + :alt: Build Status + :target: https://github.com/benoitc/gunicorn/actions/workflows/tox.yml + +.. image:: https://github.com/benoitc/gunicorn/actions/workflows/lint.yml/badge.svg + :alt: Lint Status + :target: https://github.com/benoitc/gunicorn/actions/workflows/lint.yml + +Gunicorn 'Green Unicorn' is a Python WSGI HTTP Server for UNIX. It's a pre-fork +worker model ported from Ruby's Unicorn_ project. The Gunicorn server is broadly +compatible with various web frameworks, simply implemented, light on server +resource usage, and fairly speedy. + +Feel free to join us in `#gunicorn`_ on `Libera.chat`_. + +Documentation +------------- + +The documentation is hosted at https://docs.gunicorn.org. + +Installation +------------ + +Gunicorn requires **Python 3.x >= 3.5**. + +Install from PyPI:: + + $ pip install gunicorn + + +Usage +----- + +Basic usage:: + + $ gunicorn [OPTIONS] APP_MODULE + +Where ``APP_MODULE`` is of the pattern ``$(MODULE_NAME):$(VARIABLE_NAME)``. The +module name can be a full dotted path. The variable name refers to a WSGI +callable that should be found in the specified module. + +Example with test app:: + + $ cd examples + $ gunicorn --workers=2 test:app + + +Contributing +------------ + +See `our complete contributor's guide `_ for more details. + + +License +------- + +Gunicorn is released under the MIT License. See the LICENSE_ file for more +details. + +.. _Unicorn: https://bogomips.org/unicorn/ +.. _`#gunicorn`: https://web.libera.chat/?channels=#gunicorn +.. _`Libera.chat`: https://libera.chat/ +.. _LICENSE: https://github.com/benoitc/gunicorn/blob/master/LICENSE diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn-21.2.0.dist-info/RECORD b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn-21.2.0.dist-info/RECORD new file mode 100644 index 0000000..727804e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn-21.2.0.dist-info/RECORD @@ -0,0 +1,42 @@ +../../bin/gunicorn,sha256=mcireadw5vvf0QQwUfN28DJA9FwmrS-iqOV7xBI0nTI,193 +gunicorn-21.2.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +gunicorn-21.2.0.dist-info/METADATA,sha256=5D3VZHwuMtS6iruVsiafVSSiuCpM_vfR3f9_o274SyU,4129 +gunicorn-21.2.0.dist-info/RECORD,, +gunicorn-21.2.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +gunicorn-21.2.0.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92 +gunicorn-21.2.0.dist-info/entry_points.txt,sha256=bF8VNiG4H8W83JfEBcqcPMydv9hl04CS4kwh1KOYrFY,113 +gunicorn-21.2.0.dist-info/top_level.txt,sha256=cdMaa2yhxb8do-WioY9qRHUCfwf55YztjwQCncaInoE,9 +gunicorn/__init__.py,sha256=cp8ijnQcq-iYGac8T6m8hahC9rvVAf8JoV7pyTQj6aI,279 +gunicorn/__main__.py,sha256=kv-LQeOm8rXRw_NQTj8Tg3l3jv9eKMAm6jyKzYY0Hs8,171 +gunicorn/app/__init__.py,sha256=GuqstqdkizeV4HRbd8aGMBn0Q8IDOyRU1wMMNqNe5GY,127 +gunicorn/app/base.py,sha256=CWl34bhgOEAGeW_esL4dylax_7mdx-Kbfde_YdC9Pa0,7400 +gunicorn/app/pasterapp.py,sha256=Bb0JwQNqZxmZ-gvvZUGWAEc9RX2BdhdhfhJ2a12Xafo,2038 +gunicorn/app/wsgiapp.py,sha256=Ktb5z0GPkCpDqQ0zS8zccYCvqJi8Su4zOekwKJulwBA,1926 +gunicorn/arbiter.py,sha256=oPx6GAV8pbFVW9q_5REnXb-RuCslWlchj29gE03fwu8,21509 +gunicorn/config.py,sha256=PEvdKwnlZDKb74gUIwWeJ-ZQCc6dXsQtBfNZDsBvoUA,63419 +gunicorn/debug.py,sha256=lxrs_952G7RHeKqpooLHV_szSpvh-b_dO4YEcfT7LUc,2293 +gunicorn/errors.py,sha256=JlDBjag90gMiRwLHG3xzEJzDOntSl1iM32R277-U6j0,919 +gunicorn/glogging.py,sha256=uP8_tdLRRxmW4t9klPB9uNeKNE0_QvEFIuvNAoqZErA,15303 +gunicorn/http/__init__.py,sha256=b4TF3x5F0VYOPTOeNYwRGR1EYHBaPMhZRMoNeuD5-n0,277 +gunicorn/http/body.py,sha256=F925FyTotfQ2iQ-LTBQmjTsWh9NI_IJSFdEFp1qWUEo,7296 +gunicorn/http/errors.py,sha256=sNjF2lm4m2qyZ9l95_U33FRxPXpxXzjnZyYqWS-hxd4,2850 +gunicorn/http/message.py,sha256=zQxlleTpIBvC6rKWkHiySaUr02zuO3BpX2Dy3YQbmwg,11958 +gunicorn/http/parser.py,sha256=6eNGDUMEURYqzCXsftv3a4hYuD_fBvttZxOJuRbdKNg,1364 +gunicorn/http/unreader.py,sha256=pXVde3fNCUIO2FLOSJ0iNtEEpA0m8GH6_R2Sl-cB-J8,1943 +gunicorn/http/wsgi.py,sha256=bzt62ykG1BdxbnKOzGyyGT_V14Y_OLfmvWP7Z4PsqWs,12366 +gunicorn/instrument/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +gunicorn/instrument/statsd.py,sha256=Qikvsbn9aGFzmeN1efK9u29tCFsVXLS4zWd1WMdiTEs,4690 +gunicorn/pidfile.py,sha256=U3TpoE5_05wQxonGS4pV-aLkq8BMSvql142XJnE2olw,2367 +gunicorn/reloader.py,sha256=wgP05Ou1ysQoVa-xpvSGkG_DLcmd1KRdGPPpvhIjao4,3791 +gunicorn/sock.py,sha256=a_FQgrf_leQFpdjNQtiRPrMLy2Tpoy--kNVIwoARzSk,6887 +gunicorn/systemd.py,sha256=iBnPrn0LcdL_skwjQFPkWV_33HQzGiBMkqHr4gXCeZA,2520 +gunicorn/util.py,sha256=KL4KpZiMtP2dleVpXS_wr2wiyQkDHZeSDx0DVGAvRGw,19127 +gunicorn/workers/__init__.py,sha256=Gv_JJXKofikyiPbRAUQ0IXIchKxgt0Gu-8y-nYRN9vY,594 +gunicorn/workers/base.py,sha256=6aTkFWuu7ou6LiwkBlCZdXJgwnOnRYcoBW5oCr-b1Ac,9197 +gunicorn/workers/base_async.py,sha256=U4rnAY_PGtFe_33eUoOIptilh-Lir8t_6XZAvLQyTYA,5681 +gunicorn/workers/geventlet.py,sha256=SC7uAaoIoMhHNMdE75i_Kw-b4rwHokef8J-5bC5Eghk,6091 +gunicorn/workers/ggevent.py,sha256=OUJAxJMrMP7QR2LzK0H3Hbu0C5cvr3bn4PIGKG_cwP0,5800 +gunicorn/workers/gthread.py,sha256=2e4fhNwTmgn1dkw7aAsO8zaF-NKjDg_2EShutCgPaPY,12575 +gunicorn/workers/gtornado.py,sha256=4ms0vyMr7h1GgUOfq40CVaSjCWB8brelnRLCQdLyONI,5854 +gunicorn/workers/sync.py,sha256=ECdaeyb_29IF1Nb-7EbvZwXBUCIkrSg3849PVSAhGis,7272 +gunicorn/workers/workertmp.py,sha256=yN6GQ9_Z2958BbsHTV-sYenDU-gvTJGFprRD3J-Kp2U,1651 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn-21.2.0.dist-info/REQUESTED b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn-21.2.0.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn-21.2.0.dist-info/WHEEL b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn-21.2.0.dist-info/WHEEL new file mode 100644 index 0000000..1f37c02 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn-21.2.0.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.40.0) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn-21.2.0.dist-info/entry_points.txt b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn-21.2.0.dist-info/entry_points.txt new file mode 100644 index 0000000..fd14749 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn-21.2.0.dist-info/entry_points.txt @@ -0,0 +1,5 @@ +[console_scripts] +gunicorn = gunicorn.app.wsgiapp:run + +[paste.server_runner] +main = gunicorn.app.pasterapp:serve diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn-21.2.0.dist-info/top_level.txt b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn-21.2.0.dist-info/top_level.txt new file mode 100644 index 0000000..8f22dcc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn-21.2.0.dist-info/top_level.txt @@ -0,0 +1 @@ +gunicorn diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/__init__.py new file mode 100644 index 0000000..adf5e89 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/__init__.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +version_info = (21, 2, 0) +__version__ = ".".join([str(v) for v in version_info]) +SERVER = "gunicorn" +SERVER_SOFTWARE = "%s/%s" % (SERVER, __version__) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/__main__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/__main__.py new file mode 100644 index 0000000..49ba696 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/__main__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +from gunicorn.app.wsgiapp import run +run() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/app/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/app/__init__.py new file mode 100644 index 0000000..87f0611 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/app/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/app/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/app/base.py new file mode 100644 index 0000000..dbd05bc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/app/base.py @@ -0,0 +1,236 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. +import importlib.util +import importlib.machinery +import os +import sys +import traceback + +from gunicorn import util +from gunicorn.arbiter import Arbiter +from gunicorn.config import Config, get_default_config_file +from gunicorn import debug + + +class BaseApplication(object): + """ + An application interface for configuring and loading + the various necessities for any given web framework. + """ + def __init__(self, usage=None, prog=None): + self.usage = usage + self.cfg = None + self.callable = None + self.prog = prog + self.logger = None + self.do_load_config() + + def do_load_config(self): + """ + Loads the configuration + """ + try: + self.load_default_config() + self.load_config() + except Exception as e: + print("\nError: %s" % str(e), file=sys.stderr) + sys.stderr.flush() + sys.exit(1) + + def load_default_config(self): + # init configuration + self.cfg = Config(self.usage, prog=self.prog) + + def init(self, parser, opts, args): + raise NotImplementedError + + def load(self): + raise NotImplementedError + + def load_config(self): + """ + This method is used to load the configuration from one or several input(s). + Custom Command line, configuration file. + You have to override this method in your class. + """ + raise NotImplementedError + + def reload(self): + self.do_load_config() + if self.cfg.spew: + debug.spew() + + def wsgi(self): + if self.callable is None: + self.callable = self.load() + return self.callable + + def run(self): + try: + Arbiter(self).run() + except RuntimeError as e: + print("\nError: %s\n" % e, file=sys.stderr) + sys.stderr.flush() + sys.exit(1) + + +class Application(BaseApplication): + + # 'init' and 'load' methods are implemented by WSGIApplication. + # pylint: disable=abstract-method + + def chdir(self): + # chdir to the configured path before loading, + # default is the current dir + os.chdir(self.cfg.chdir) + + # add the path to sys.path + if self.cfg.chdir not in sys.path: + sys.path.insert(0, self.cfg.chdir) + + def get_config_from_filename(self, filename): + + if not os.path.exists(filename): + raise RuntimeError("%r doesn't exist" % filename) + + ext = os.path.splitext(filename)[1] + + try: + module_name = '__config__' + if ext in [".py", ".pyc"]: + spec = importlib.util.spec_from_file_location(module_name, filename) + else: + msg = "configuration file should have a valid Python extension.\n" + util.warn(msg) + loader_ = importlib.machinery.SourceFileLoader(module_name, filename) + spec = importlib.util.spec_from_file_location(module_name, filename, loader=loader_) + mod = importlib.util.module_from_spec(spec) + sys.modules[module_name] = mod + spec.loader.exec_module(mod) + except Exception: + print("Failed to read config file: %s" % filename, file=sys.stderr) + traceback.print_exc() + sys.stderr.flush() + sys.exit(1) + + return vars(mod) + + def get_config_from_module_name(self, module_name): + return vars(importlib.import_module(module_name)) + + def load_config_from_module_name_or_filename(self, location): + """ + Loads the configuration file: the file is a python file, otherwise raise an RuntimeError + Exception or stop the process if the configuration file contains a syntax error. + """ + + if location.startswith("python:"): + module_name = location[len("python:"):] + cfg = self.get_config_from_module_name(module_name) + else: + if location.startswith("file:"): + filename = location[len("file:"):] + else: + filename = location + cfg = self.get_config_from_filename(filename) + + for k, v in cfg.items(): + # Ignore unknown names + if k not in self.cfg.settings: + continue + try: + self.cfg.set(k.lower(), v) + except Exception: + print("Invalid value for %s: %s\n" % (k, v), file=sys.stderr) + sys.stderr.flush() + raise + + return cfg + + def load_config_from_file(self, filename): + return self.load_config_from_module_name_or_filename(location=filename) + + def load_config(self): + # parse console args + parser = self.cfg.parser() + args = parser.parse_args() + + # optional settings from apps + cfg = self.init(parser, args, args.args) + + # set up import paths and follow symlinks + self.chdir() + + # Load up the any app specific configuration + if cfg: + for k, v in cfg.items(): + self.cfg.set(k.lower(), v) + + env_args = parser.parse_args(self.cfg.get_cmd_args_from_env()) + + if args.config: + self.load_config_from_file(args.config) + elif env_args.config: + self.load_config_from_file(env_args.config) + else: + default_config = get_default_config_file() + if default_config is not None: + self.load_config_from_file(default_config) + + # Load up environment configuration + for k, v in vars(env_args).items(): + if v is None: + continue + if k == "args": + continue + self.cfg.set(k.lower(), v) + + # Lastly, update the configuration with any command line settings. + for k, v in vars(args).items(): + if v is None: + continue + if k == "args": + continue + self.cfg.set(k.lower(), v) + + # current directory might be changed by the config now + # set up import paths and follow symlinks + self.chdir() + + def run(self): + if self.cfg.print_config: + print(self.cfg) + + if self.cfg.print_config or self.cfg.check_config: + try: + self.load() + except Exception: + msg = "\nError while loading the application:\n" + print(msg, file=sys.stderr) + traceback.print_exc() + sys.stderr.flush() + sys.exit(1) + sys.exit(0) + + if self.cfg.spew: + debug.spew() + + if self.cfg.daemon: + if os.environ.get('NOTIFY_SOCKET'): + msg = "Warning: you shouldn't specify `daemon = True`" \ + " when launching by systemd with `Type = notify`" + print(msg, file=sys.stderr, flush=True) + + util.daemonize(self.cfg.enable_stdio_inheritance) + + # set python paths + if self.cfg.pythonpath: + paths = self.cfg.pythonpath.split(",") + for path in paths: + pythonpath = os.path.abspath(path) + if pythonpath not in sys.path: + sys.path.insert(0, pythonpath) + + super().run() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/app/pasterapp.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/app/pasterapp.py new file mode 100644 index 0000000..4c9fc7d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/app/pasterapp.py @@ -0,0 +1,75 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +import configparser +import os + +from paste.deploy import loadapp + +from gunicorn.app.wsgiapp import WSGIApplication +from gunicorn.config import get_default_config_file + + +def get_wsgi_app(config_uri, name=None, defaults=None): + if ':' not in config_uri: + config_uri = "config:%s" % config_uri + + return loadapp( + config_uri, + name=name, + relative_to=os.getcwd(), + global_conf=defaults, + ) + + +def has_logging_config(config_file): + parser = configparser.ConfigParser() + parser.read([config_file]) + return parser.has_section('loggers') + + +def serve(app, global_conf, **local_conf): + """\ + A Paste Deployment server runner. + + Example configuration: + + [server:main] + use = egg:gunicorn#main + host = 127.0.0.1 + port = 5000 + """ + config_file = global_conf['__file__'] + gunicorn_config_file = local_conf.pop('config', None) + + host = local_conf.pop('host', '') + port = local_conf.pop('port', '') + if host and port: + local_conf['bind'] = '%s:%s' % (host, port) + elif host: + local_conf['bind'] = host.split(',') + + class PasterServerApplication(WSGIApplication): + def load_config(self): + self.cfg.set("default_proc_name", config_file) + + if has_logging_config(config_file): + self.cfg.set("logconfig", config_file) + + if gunicorn_config_file: + self.load_config_from_file(gunicorn_config_file) + else: + default_gunicorn_config_file = get_default_config_file() + if default_gunicorn_config_file is not None: + self.load_config_from_file(default_gunicorn_config_file) + + for k, v in local_conf.items(): + if v is not None: + self.cfg.set(k.lower(), v) + + def load(self): + return app + + PasterServerApplication().run() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/app/wsgiapp.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/app/wsgiapp.py new file mode 100644 index 0000000..36cfba9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/app/wsgiapp.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +import os + +from gunicorn.errors import ConfigError +from gunicorn.app.base import Application +from gunicorn import util + + +class WSGIApplication(Application): + def init(self, parser, opts, args): + self.app_uri = None + + if opts.paste: + from .pasterapp import has_logging_config + + config_uri = os.path.abspath(opts.paste) + config_file = config_uri.split('#')[0] + + if not os.path.exists(config_file): + raise ConfigError("%r not found" % config_file) + + self.cfg.set("default_proc_name", config_file) + self.app_uri = config_uri + + if has_logging_config(config_file): + self.cfg.set("logconfig", config_file) + + return + + if len(args) > 0: + self.cfg.set("default_proc_name", args[0]) + self.app_uri = args[0] + + def load_config(self): + super().load_config() + + if self.app_uri is None: + if self.cfg.wsgi_app is not None: + self.app_uri = self.cfg.wsgi_app + else: + raise ConfigError("No application module specified.") + + def load_wsgiapp(self): + return util.import_app(self.app_uri) + + def load_pasteapp(self): + from .pasterapp import get_wsgi_app + return get_wsgi_app(self.app_uri, defaults=self.cfg.paste_global_conf) + + def load(self): + if self.cfg.paste is not None: + return self.load_pasteapp() + else: + return self.load_wsgiapp() + + +def run(): + """\ + The ``gunicorn`` command line runner for launching Gunicorn with + generic WSGI applications. + """ + from gunicorn.app.wsgiapp import WSGIApplication + WSGIApplication("%(prog)s [OPTIONS] [APP_MODULE]").run() + + +if __name__ == '__main__': + run() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/arbiter.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/arbiter.py new file mode 100644 index 0000000..08523d4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/arbiter.py @@ -0,0 +1,672 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. +import errno +import os +import random +import select +import signal +import sys +import time +import traceback + +from gunicorn.errors import HaltServer, AppImportError +from gunicorn.pidfile import Pidfile +from gunicorn import sock, systemd, util + +from gunicorn import __version__, SERVER_SOFTWARE + + +class Arbiter(object): + """ + Arbiter maintain the workers processes alive. It launches or + kills them if needed. It also manages application reloading + via SIGHUP/USR2. + """ + + # A flag indicating if a worker failed to + # to boot. If a worker process exist with + # this error code, the arbiter will terminate. + WORKER_BOOT_ERROR = 3 + + # A flag indicating if an application failed to be loaded + APP_LOAD_ERROR = 4 + + START_CTX = {} + + LISTENERS = [] + WORKERS = {} + PIPE = [] + + # I love dynamic languages + SIG_QUEUE = [] + SIGNALS = [getattr(signal, "SIG%s" % x) + for x in "HUP QUIT INT TERM TTIN TTOU USR1 USR2 WINCH".split()] + SIG_NAMES = dict( + (getattr(signal, name), name[3:].lower()) for name in dir(signal) + if name[:3] == "SIG" and name[3] != "_" + ) + + def __init__(self, app): + os.environ["SERVER_SOFTWARE"] = SERVER_SOFTWARE + + self._num_workers = None + self._last_logged_active_worker_count = None + self.log = None + + self.setup(app) + + self.pidfile = None + self.systemd = False + self.worker_age = 0 + self.reexec_pid = 0 + self.master_pid = 0 + self.master_name = "Master" + + cwd = util.getcwd() + + args = sys.argv[:] + args.insert(0, sys.executable) + + # init start context + self.START_CTX = { + "args": args, + "cwd": cwd, + 0: sys.executable + } + + def _get_num_workers(self): + return self._num_workers + + def _set_num_workers(self, value): + old_value = self._num_workers + self._num_workers = value + self.cfg.nworkers_changed(self, value, old_value) + num_workers = property(_get_num_workers, _set_num_workers) + + def setup(self, app): + self.app = app + self.cfg = app.cfg + + if self.log is None: + self.log = self.cfg.logger_class(app.cfg) + + # reopen files + if 'GUNICORN_FD' in os.environ: + self.log.reopen_files() + + self.worker_class = self.cfg.worker_class + self.address = self.cfg.address + self.num_workers = self.cfg.workers + self.timeout = self.cfg.timeout + self.proc_name = self.cfg.proc_name + + self.log.debug('Current configuration:\n{0}'.format( + '\n'.join( + ' {0}: {1}'.format(config, value.value) + for config, value + in sorted(self.cfg.settings.items(), + key=lambda setting: setting[1])))) + + # set enviroment' variables + if self.cfg.env: + for k, v in self.cfg.env.items(): + os.environ[k] = v + + if self.cfg.preload_app: + self.app.wsgi() + + def start(self): + """\ + Initialize the arbiter. Start listening and set pidfile if needed. + """ + self.log.info("Starting gunicorn %s", __version__) + + if 'GUNICORN_PID' in os.environ: + self.master_pid = int(os.environ.get('GUNICORN_PID')) + self.proc_name = self.proc_name + ".2" + self.master_name = "Master.2" + + self.pid = os.getpid() + if self.cfg.pidfile is not None: + pidname = self.cfg.pidfile + if self.master_pid != 0: + pidname += ".2" + self.pidfile = Pidfile(pidname) + self.pidfile.create(self.pid) + self.cfg.on_starting(self) + + self.init_signals() + + if not self.LISTENERS: + fds = None + listen_fds = systemd.listen_fds() + if listen_fds: + self.systemd = True + fds = range(systemd.SD_LISTEN_FDS_START, + systemd.SD_LISTEN_FDS_START + listen_fds) + + elif self.master_pid: + fds = [] + for fd in os.environ.pop('GUNICORN_FD').split(','): + fds.append(int(fd)) + + self.LISTENERS = sock.create_sockets(self.cfg, self.log, fds) + + listeners_str = ",".join([str(lnr) for lnr in self.LISTENERS]) + self.log.debug("Arbiter booted") + self.log.info("Listening at: %s (%s)", listeners_str, self.pid) + self.log.info("Using worker: %s", self.cfg.worker_class_str) + systemd.sd_notify("READY=1\nSTATUS=Gunicorn arbiter booted", self.log) + + # check worker class requirements + if hasattr(self.worker_class, "check_config"): + self.worker_class.check_config(self.cfg, self.log) + + self.cfg.when_ready(self) + + def init_signals(self): + """\ + Initialize master signal handling. Most of the signals + are queued. Child signals only wake up the master. + """ + # close old PIPE + for p in self.PIPE: + os.close(p) + + # initialize the pipe + self.PIPE = pair = os.pipe() + for p in pair: + util.set_non_blocking(p) + util.close_on_exec(p) + + self.log.close_on_exec() + + # initialize all signals + for s in self.SIGNALS: + signal.signal(s, self.signal) + signal.signal(signal.SIGCHLD, self.handle_chld) + + def signal(self, sig, frame): + if len(self.SIG_QUEUE) < 5: + self.SIG_QUEUE.append(sig) + self.wakeup() + + def run(self): + "Main master loop." + self.start() + util._setproctitle("master [%s]" % self.proc_name) + + try: + self.manage_workers() + + while True: + self.maybe_promote_master() + + sig = self.SIG_QUEUE.pop(0) if self.SIG_QUEUE else None + if sig is None: + self.sleep() + self.murder_workers() + self.manage_workers() + continue + + if sig not in self.SIG_NAMES: + self.log.info("Ignoring unknown signal: %s", sig) + continue + + signame = self.SIG_NAMES.get(sig) + handler = getattr(self, "handle_%s" % signame, None) + if not handler: + self.log.error("Unhandled signal: %s", signame) + continue + self.log.info("Handling signal: %s", signame) + handler() + self.wakeup() + except (StopIteration, KeyboardInterrupt): + self.halt() + except HaltServer as inst: + self.halt(reason=inst.reason, exit_status=inst.exit_status) + except SystemExit: + raise + except Exception: + self.log.error("Unhandled exception in main loop", + exc_info=True) + self.stop(False) + if self.pidfile is not None: + self.pidfile.unlink() + sys.exit(-1) + + def handle_chld(self, sig, frame): + "SIGCHLD handling" + self.reap_workers() + self.wakeup() + + def handle_hup(self): + """\ + HUP handling. + - Reload configuration + - Start the new worker processes with a new configuration + - Gracefully shutdown the old worker processes + """ + self.log.info("Hang up: %s", self.master_name) + self.reload() + + def handle_term(self): + "SIGTERM handling" + raise StopIteration + + def handle_int(self): + "SIGINT handling" + self.stop(False) + raise StopIteration + + def handle_quit(self): + "SIGQUIT handling" + self.stop(False) + raise StopIteration + + def handle_ttin(self): + """\ + SIGTTIN handling. + Increases the number of workers by one. + """ + self.num_workers += 1 + self.manage_workers() + + def handle_ttou(self): + """\ + SIGTTOU handling. + Decreases the number of workers by one. + """ + if self.num_workers <= 1: + return + self.num_workers -= 1 + self.manage_workers() + + def handle_usr1(self): + """\ + SIGUSR1 handling. + Kill all workers by sending them a SIGUSR1 + """ + self.log.reopen_files() + self.kill_workers(signal.SIGUSR1) + + def handle_usr2(self): + """\ + SIGUSR2 handling. + Creates a new arbiter/worker set as a fork of the current + arbiter without affecting old workers. Use this to do live + deployment with the ability to backout a change. + """ + self.reexec() + + def handle_winch(self): + """SIGWINCH handling""" + if self.cfg.daemon: + self.log.info("graceful stop of workers") + self.num_workers = 0 + self.kill_workers(signal.SIGTERM) + else: + self.log.debug("SIGWINCH ignored. Not daemonized") + + def maybe_promote_master(self): + if self.master_pid == 0: + return + + if self.master_pid != os.getppid(): + self.log.info("Master has been promoted.") + # reset master infos + self.master_name = "Master" + self.master_pid = 0 + self.proc_name = self.cfg.proc_name + del os.environ['GUNICORN_PID'] + # rename the pidfile + if self.pidfile is not None: + self.pidfile.rename(self.cfg.pidfile) + # reset proctitle + util._setproctitle("master [%s]" % self.proc_name) + + def wakeup(self): + """\ + Wake up the arbiter by writing to the PIPE + """ + try: + os.write(self.PIPE[1], b'.') + except IOError as e: + if e.errno not in [errno.EAGAIN, errno.EINTR]: + raise + + def halt(self, reason=None, exit_status=0): + """ halt arbiter """ + self.stop() + + log_func = self.log.info if exit_status == 0 else self.log.error + log_func("Shutting down: %s", self.master_name) + if reason is not None: + log_func("Reason: %s", reason) + + if self.pidfile is not None: + self.pidfile.unlink() + self.cfg.on_exit(self) + sys.exit(exit_status) + + def sleep(self): + """\ + Sleep until PIPE is readable or we timeout. + A readable PIPE means a signal occurred. + """ + try: + ready = select.select([self.PIPE[0]], [], [], 1.0) + if not ready[0]: + return + while os.read(self.PIPE[0], 1): + pass + except (select.error, OSError) as e: + # TODO: select.error is a subclass of OSError since Python 3.3. + error_number = getattr(e, 'errno', e.args[0]) + if error_number not in [errno.EAGAIN, errno.EINTR]: + raise + except KeyboardInterrupt: + sys.exit() + + def stop(self, graceful=True): + """\ + Stop workers + + :attr graceful: boolean, If True (the default) workers will be + killed gracefully (ie. trying to wait for the current connection) + """ + unlink = ( + self.reexec_pid == self.master_pid == 0 + and not self.systemd + and not self.cfg.reuse_port + ) + sock.close_sockets(self.LISTENERS, unlink) + + self.LISTENERS = [] + sig = signal.SIGTERM + if not graceful: + sig = signal.SIGQUIT + limit = time.time() + self.cfg.graceful_timeout + # instruct the workers to exit + self.kill_workers(sig) + # wait until the graceful timeout + while self.WORKERS and time.time() < limit: + time.sleep(0.1) + + self.kill_workers(signal.SIGKILL) + + def reexec(self): + """\ + Relaunch the master and workers. + """ + if self.reexec_pid != 0: + self.log.warning("USR2 signal ignored. Child exists.") + return + + if self.master_pid != 0: + self.log.warning("USR2 signal ignored. Parent exists.") + return + + master_pid = os.getpid() + self.reexec_pid = os.fork() + if self.reexec_pid != 0: + return + + self.cfg.pre_exec(self) + + environ = self.cfg.env_orig.copy() + environ['GUNICORN_PID'] = str(master_pid) + + if self.systemd: + environ['LISTEN_PID'] = str(os.getpid()) + environ['LISTEN_FDS'] = str(len(self.LISTENERS)) + else: + environ['GUNICORN_FD'] = ','.join( + str(lnr.fileno()) for lnr in self.LISTENERS) + + os.chdir(self.START_CTX['cwd']) + + # exec the process using the original environment + os.execvpe(self.START_CTX[0], self.START_CTX['args'], environ) + + def reload(self): + old_address = self.cfg.address + + # reset old environment + for k in self.cfg.env: + if k in self.cfg.env_orig: + # reset the key to the value it had before + # we launched gunicorn + os.environ[k] = self.cfg.env_orig[k] + else: + # delete the value set by gunicorn + try: + del os.environ[k] + except KeyError: + pass + + # reload conf + self.app.reload() + self.setup(self.app) + + # reopen log files + self.log.reopen_files() + + # do we need to change listener ? + if old_address != self.cfg.address: + # close all listeners + for lnr in self.LISTENERS: + lnr.close() + # init new listeners + self.LISTENERS = sock.create_sockets(self.cfg, self.log) + listeners_str = ",".join([str(lnr) for lnr in self.LISTENERS]) + self.log.info("Listening at: %s", listeners_str) + + # do some actions on reload + self.cfg.on_reload(self) + + # unlink pidfile + if self.pidfile is not None: + self.pidfile.unlink() + + # create new pidfile + if self.cfg.pidfile is not None: + self.pidfile = Pidfile(self.cfg.pidfile) + self.pidfile.create(self.pid) + + # set new proc_name + util._setproctitle("master [%s]" % self.proc_name) + + # spawn new workers + for _ in range(self.cfg.workers): + self.spawn_worker() + + # manage workers + self.manage_workers() + + def murder_workers(self): + """\ + Kill unused/idle workers + """ + if not self.timeout: + return + workers = list(self.WORKERS.items()) + for (pid, worker) in workers: + try: + if time.time() - worker.tmp.last_update() <= self.timeout: + continue + except (OSError, ValueError): + continue + + if not worker.aborted: + self.log.critical("WORKER TIMEOUT (pid:%s)", pid) + worker.aborted = True + self.kill_worker(pid, signal.SIGABRT) + else: + self.kill_worker(pid, signal.SIGKILL) + + def reap_workers(self): + """\ + Reap workers to avoid zombie processes + """ + try: + while True: + wpid, status = os.waitpid(-1, os.WNOHANG) + if not wpid: + break + if self.reexec_pid == wpid: + self.reexec_pid = 0 + else: + # A worker was terminated. If the termination reason was + # that it could not boot, we'll shut it down to avoid + # infinite start/stop cycles. + exitcode = status >> 8 + if exitcode != 0: + self.log.error('Worker (pid:%s) exited with code %s', wpid, exitcode) + if exitcode == self.WORKER_BOOT_ERROR: + reason = "Worker failed to boot." + raise HaltServer(reason, self.WORKER_BOOT_ERROR) + if exitcode == self.APP_LOAD_ERROR: + reason = "App failed to load." + raise HaltServer(reason, self.APP_LOAD_ERROR) + + if exitcode > 0: + # If the exit code of the worker is greater than 0, + # let the user know. + self.log.error("Worker (pid:%s) exited with code %s.", + wpid, exitcode) + elif status > 0: + # If the exit code of the worker is 0 and the status + # is greater than 0, then it was most likely killed + # via a signal. + try: + sig_name = signal.Signals(status).name + except ValueError: + sig_name = "code {}".format(status) + msg = "Worker (pid:{}) was sent {}!".format( + wpid, sig_name) + + # Additional hint for SIGKILL + if status == signal.SIGKILL: + msg += " Perhaps out of memory?" + self.log.error(msg) + + worker = self.WORKERS.pop(wpid, None) + if not worker: + continue + worker.tmp.close() + self.cfg.child_exit(self, worker) + except OSError as e: + if e.errno != errno.ECHILD: + raise + + def manage_workers(self): + """\ + Maintain the number of workers by spawning or killing + as required. + """ + if len(self.WORKERS) < self.num_workers: + self.spawn_workers() + + workers = self.WORKERS.items() + workers = sorted(workers, key=lambda w: w[1].age) + while len(workers) > self.num_workers: + (pid, _) = workers.pop(0) + self.kill_worker(pid, signal.SIGTERM) + + active_worker_count = len(workers) + if self._last_logged_active_worker_count != active_worker_count: + self._last_logged_active_worker_count = active_worker_count + self.log.debug("{0} workers".format(active_worker_count), + extra={"metric": "gunicorn.workers", + "value": active_worker_count, + "mtype": "gauge"}) + + def spawn_worker(self): + self.worker_age += 1 + worker = self.worker_class(self.worker_age, self.pid, self.LISTENERS, + self.app, self.timeout / 2.0, + self.cfg, self.log) + self.cfg.pre_fork(self, worker) + pid = os.fork() + if pid != 0: + worker.pid = pid + self.WORKERS[pid] = worker + return pid + + # Do not inherit the temporary files of other workers + for sibling in self.WORKERS.values(): + sibling.tmp.close() + + # Process Child + worker.pid = os.getpid() + try: + util._setproctitle("worker [%s]" % self.proc_name) + self.log.info("Booting worker with pid: %s", worker.pid) + self.cfg.post_fork(self, worker) + worker.init_process() + sys.exit(0) + except SystemExit: + raise + except AppImportError as e: + self.log.debug("Exception while loading the application", + exc_info=True) + print("%s" % e, file=sys.stderr) + sys.stderr.flush() + sys.exit(self.APP_LOAD_ERROR) + except Exception: + self.log.exception("Exception in worker process") + if not worker.booted: + sys.exit(self.WORKER_BOOT_ERROR) + sys.exit(-1) + finally: + self.log.info("Worker exiting (pid: %s)", worker.pid) + try: + worker.tmp.close() + self.cfg.worker_exit(self, worker) + except Exception: + self.log.warning("Exception during worker exit:\n%s", + traceback.format_exc()) + + def spawn_workers(self): + """\ + Spawn new workers as needed. + + This is where a worker process leaves the main loop + of the master process. + """ + + for _ in range(self.num_workers - len(self.WORKERS)): + self.spawn_worker() + time.sleep(0.1 * random.random()) + + def kill_workers(self, sig): + """\ + Kill all workers with the signal `sig` + :attr sig: `signal.SIG*` value + """ + worker_pids = list(self.WORKERS.keys()) + for pid in worker_pids: + self.kill_worker(pid, sig) + + def kill_worker(self, pid, sig): + """\ + Kill a worker + + :attr pid: int, worker pid + :attr sig: `signal.SIG*` value + """ + try: + os.kill(pid, sig) + except OSError as e: + if e.errno == errno.ESRCH: + try: + worker = self.WORKERS.pop(pid) + worker.tmp.close() + self.cfg.worker_exit(self, worker) + return + except (KeyError, OSError): + return + raise diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/config.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/config.py new file mode 100644 index 0000000..84e7619 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/config.py @@ -0,0 +1,2258 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +# Please remember to run "make -C docs html" after update "desc" attributes. + +import argparse +import copy +import grp +import inspect +import os +import pwd +import re +import shlex +import ssl +import sys +import textwrap + +from gunicorn import __version__, util +from gunicorn.errors import ConfigError +from gunicorn.reloader import reloader_engines + +KNOWN_SETTINGS = [] +PLATFORM = sys.platform + + +def make_settings(ignore=None): + settings = {} + ignore = ignore or () + for s in KNOWN_SETTINGS: + setting = s() + if setting.name in ignore: + continue + settings[setting.name] = setting.copy() + return settings + + +def auto_int(_, x): + # for compatible with octal numbers in python3 + if re.match(r'0(\d)', x, re.IGNORECASE): + x = x.replace('0', '0o', 1) + return int(x, 0) + + +class Config(object): + + def __init__(self, usage=None, prog=None): + self.settings = make_settings() + self.usage = usage + self.prog = prog or os.path.basename(sys.argv[0]) + self.env_orig = os.environ.copy() + + def __str__(self): + lines = [] + kmax = max(len(k) for k in self.settings) + for k in sorted(self.settings): + v = self.settings[k].value + if callable(v): + v = "<{}()>".format(v.__qualname__) + lines.append("{k:{kmax}} = {v}".format(k=k, v=v, kmax=kmax)) + return "\n".join(lines) + + def __getattr__(self, name): + if name not in self.settings: + raise AttributeError("No configuration setting for: %s" % name) + return self.settings[name].get() + + def __setattr__(self, name, value): + if name != "settings" and name in self.settings: + raise AttributeError("Invalid access!") + super().__setattr__(name, value) + + def set(self, name, value): + if name not in self.settings: + raise AttributeError("No configuration setting for: %s" % name) + self.settings[name].set(value) + + def get_cmd_args_from_env(self): + if 'GUNICORN_CMD_ARGS' in self.env_orig: + return shlex.split(self.env_orig['GUNICORN_CMD_ARGS']) + return [] + + def parser(self): + kwargs = { + "usage": self.usage, + "prog": self.prog + } + parser = argparse.ArgumentParser(**kwargs) + parser.add_argument("-v", "--version", + action="version", default=argparse.SUPPRESS, + version="%(prog)s (version " + __version__ + ")\n", + help="show program's version number and exit") + parser.add_argument("args", nargs="*", help=argparse.SUPPRESS) + + keys = sorted(self.settings, key=self.settings.__getitem__) + for k in keys: + self.settings[k].add_option(parser) + + return parser + + @property + def worker_class_str(self): + uri = self.settings['worker_class'].get() + + # are we using a threaded worker? + is_sync = uri.endswith('SyncWorker') or uri == 'sync' + if is_sync and self.threads > 1: + return "gthread" + return uri + + @property + def worker_class(self): + uri = self.settings['worker_class'].get() + + # are we using a threaded worker? + is_sync = uri.endswith('SyncWorker') or uri == 'sync' + if is_sync and self.threads > 1: + uri = "gunicorn.workers.gthread.ThreadWorker" + + worker_class = util.load_class(uri) + if hasattr(worker_class, "setup"): + worker_class.setup() + return worker_class + + @property + def address(self): + s = self.settings['bind'].get() + return [util.parse_address(util.bytes_to_str(bind)) for bind in s] + + @property + def uid(self): + return self.settings['user'].get() + + @property + def gid(self): + return self.settings['group'].get() + + @property + def proc_name(self): + pn = self.settings['proc_name'].get() + if pn is not None: + return pn + else: + return self.settings['default_proc_name'].get() + + @property + def logger_class(self): + uri = self.settings['logger_class'].get() + if uri == "simple": + # support the default + uri = LoggerClass.default + + # if default logger is in use, and statsd is on, automagically switch + # to the statsd logger + if uri == LoggerClass.default: + if 'statsd_host' in self.settings and self.settings['statsd_host'].value is not None: + uri = "gunicorn.instrument.statsd.Statsd" + + logger_class = util.load_class( + uri, + default="gunicorn.glogging.Logger", + section="gunicorn.loggers") + + if hasattr(logger_class, "install"): + logger_class.install() + return logger_class + + @property + def is_ssl(self): + return self.certfile or self.keyfile + + @property + def ssl_options(self): + opts = {} + for name, value in self.settings.items(): + if value.section == 'SSL': + opts[name] = value.get() + return opts + + @property + def env(self): + raw_env = self.settings['raw_env'].get() + env = {} + + if not raw_env: + return env + + for e in raw_env: + s = util.bytes_to_str(e) + try: + k, v = s.split('=', 1) + except ValueError: + raise RuntimeError("environment setting %r invalid" % s) + + env[k] = v + + return env + + @property + def sendfile(self): + if self.settings['sendfile'].get() is not None: + return False + + if 'SENDFILE' in os.environ: + sendfile = os.environ['SENDFILE'].lower() + return sendfile in ['y', '1', 'yes', 'true'] + + return True + + @property + def reuse_port(self): + return self.settings['reuse_port'].get() + + @property + def paste_global_conf(self): + raw_global_conf = self.settings['raw_paste_global_conf'].get() + if raw_global_conf is None: + return None + + global_conf = {} + for e in raw_global_conf: + s = util.bytes_to_str(e) + try: + k, v = re.split(r'(?" % ( + self.__class__.__module__, + self.__class__.__name__, + id(self), + self.value, + ) + + +Setting = SettingMeta('Setting', (Setting,), {}) + + +def validate_bool(val): + if val is None: + return + + if isinstance(val, bool): + return val + if not isinstance(val, str): + raise TypeError("Invalid type for casting: %s" % val) + if val.lower().strip() == "true": + return True + elif val.lower().strip() == "false": + return False + else: + raise ValueError("Invalid boolean: %s" % val) + + +def validate_dict(val): + if not isinstance(val, dict): + raise TypeError("Value is not a dictionary: %s " % val) + return val + + +def validate_pos_int(val): + if not isinstance(val, int): + val = int(val, 0) + else: + # Booleans are ints! + val = int(val) + if val < 0: + raise ValueError("Value must be positive: %s" % val) + return val + + +def validate_ssl_version(val): + if val != SSLVersion.default: + sys.stderr.write("Warning: option `ssl_version` is deprecated and it is ignored. Use ssl_context instead.\n") + return val + + +def validate_string(val): + if val is None: + return None + if not isinstance(val, str): + raise TypeError("Not a string: %s" % val) + return val.strip() + + +def validate_file_exists(val): + if val is None: + return None + if not os.path.exists(val): + raise ValueError("File %s does not exists." % val) + return val + + +def validate_list_string(val): + if not val: + return [] + + # legacy syntax + if isinstance(val, str): + val = [val] + + return [validate_string(v) for v in val] + + +def validate_list_of_existing_files(val): + return [validate_file_exists(v) for v in validate_list_string(val)] + + +def validate_string_to_list(val): + val = validate_string(val) + + if not val: + return [] + + return [v.strip() for v in val.split(",") if v] + + +def validate_class(val): + if inspect.isfunction(val) or inspect.ismethod(val): + val = val() + if inspect.isclass(val): + return val + return validate_string(val) + + +def validate_callable(arity): + def _validate_callable(val): + if isinstance(val, str): + try: + mod_name, obj_name = val.rsplit(".", 1) + except ValueError: + raise TypeError("Value '%s' is not import string. " + "Format: module[.submodules...].object" % val) + try: + mod = __import__(mod_name, fromlist=[obj_name]) + val = getattr(mod, obj_name) + except ImportError as e: + raise TypeError(str(e)) + except AttributeError: + raise TypeError("Can not load '%s' from '%s'" + "" % (obj_name, mod_name)) + if not callable(val): + raise TypeError("Value is not callable: %s" % val) + if arity != -1 and arity != util.get_arity(val): + raise TypeError("Value must have an arity of: %s" % arity) + return val + return _validate_callable + + +def validate_user(val): + if val is None: + return os.geteuid() + if isinstance(val, int): + return val + elif val.isdigit(): + return int(val) + else: + try: + return pwd.getpwnam(val).pw_uid + except KeyError: + raise ConfigError("No such user: '%s'" % val) + + +def validate_group(val): + if val is None: + return os.getegid() + + if isinstance(val, int): + return val + elif val.isdigit(): + return int(val) + else: + try: + return grp.getgrnam(val).gr_gid + except KeyError: + raise ConfigError("No such group: '%s'" % val) + + +def validate_post_request(val): + val = validate_callable(-1)(val) + + largs = util.get_arity(val) + if largs == 4: + return val + elif largs == 3: + return lambda worker, req, env, _r: val(worker, req, env) + elif largs == 2: + return lambda worker, req, _e, _r: val(worker, req) + else: + raise TypeError("Value must have an arity of: 4") + + +def validate_chdir(val): + # valid if the value is a string + val = validate_string(val) + + # transform relative paths + path = os.path.abspath(os.path.normpath(os.path.join(util.getcwd(), val))) + + # test if the path exists + if not os.path.exists(path): + raise ConfigError("can't chdir to %r" % val) + + return path + + +def validate_statsd_address(val): + val = validate_string(val) + if val is None: + return None + + # As of major release 20, util.parse_address would recognize unix:PORT + # as a UDS address, breaking backwards compatibility. We defend against + # that regression here (this is also unit-tested). + # Feel free to remove in the next major release. + unix_hostname_regression = re.match(r'^unix:(\d+)$', val) + if unix_hostname_regression: + return ('unix', int(unix_hostname_regression.group(1))) + + try: + address = util.parse_address(val, default_port='8125') + except RuntimeError: + raise TypeError("Value must be one of ('host:port', 'unix://PATH')") + + return address + + +def validate_reload_engine(val): + if val not in reloader_engines: + raise ConfigError("Invalid reload_engine: %r" % val) + + return val + + +def get_default_config_file(): + config_path = os.path.join(os.path.abspath(os.getcwd()), + 'gunicorn.conf.py') + if os.path.exists(config_path): + return config_path + return None + + +class ConfigFile(Setting): + name = "config" + section = "Config File" + cli = ["-c", "--config"] + meta = "CONFIG" + validator = validate_string + default = "./gunicorn.conf.py" + desc = """\ + :ref:`The Gunicorn config file`. + + A string of the form ``PATH``, ``file:PATH``, or ``python:MODULE_NAME``. + + Only has an effect when specified on the command line or as part of an + application specific configuration. + + By default, a file named ``gunicorn.conf.py`` will be read from the same + directory where gunicorn is being run. + + .. versionchanged:: 19.4 + Loading the config from a Python module requires the ``python:`` + prefix. + """ + + +class WSGIApp(Setting): + name = "wsgi_app" + section = "Config File" + meta = "STRING" + validator = validate_string + default = None + desc = """\ + A WSGI application path in pattern ``$(MODULE_NAME):$(VARIABLE_NAME)``. + + .. versionadded:: 20.1.0 + """ + + +class Bind(Setting): + name = "bind" + action = "append" + section = "Server Socket" + cli = ["-b", "--bind"] + meta = "ADDRESS" + validator = validate_list_string + + if 'PORT' in os.environ: + default = ['0.0.0.0:{0}'.format(os.environ.get('PORT'))] + else: + default = ['127.0.0.1:8000'] + + desc = """\ + The socket to bind. + + A string of the form: ``HOST``, ``HOST:PORT``, ``unix:PATH``, + ``fd://FD``. An IP is a valid ``HOST``. + + .. versionchanged:: 20.0 + Support for ``fd://FD`` got added. + + Multiple addresses can be bound. ex.:: + + $ gunicorn -b 127.0.0.1:8000 -b [::1]:8000 test:app + + will bind the `test:app` application on localhost both on ipv6 + and ipv4 interfaces. + + If the ``PORT`` environment variable is defined, the default + is ``['0.0.0.0:$PORT']``. If it is not defined, the default + is ``['127.0.0.1:8000']``. + """ + + +class Backlog(Setting): + name = "backlog" + section = "Server Socket" + cli = ["--backlog"] + meta = "INT" + validator = validate_pos_int + type = int + default = 2048 + desc = """\ + The maximum number of pending connections. + + This refers to the number of clients that can be waiting to be served. + Exceeding this number results in the client getting an error when + attempting to connect. It should only affect servers under significant + load. + + Must be a positive integer. Generally set in the 64-2048 range. + """ + + +class Workers(Setting): + name = "workers" + section = "Worker Processes" + cli = ["-w", "--workers"] + meta = "INT" + validator = validate_pos_int + type = int + default = int(os.environ.get("WEB_CONCURRENCY", 1)) + desc = """\ + The number of worker processes for handling requests. + + A positive integer generally in the ``2-4 x $(NUM_CORES)`` range. + You'll want to vary this a bit to find the best for your particular + application's work load. + + By default, the value of the ``WEB_CONCURRENCY`` environment variable, + which is set by some Platform-as-a-Service providers such as Heroku. If + it is not defined, the default is ``1``. + """ + + +class WorkerClass(Setting): + name = "worker_class" + section = "Worker Processes" + cli = ["-k", "--worker-class"] + meta = "STRING" + validator = validate_class + default = "sync" + desc = """\ + The type of workers to use. + + The default class (``sync``) should handle most "normal" types of + workloads. You'll want to read :doc:`design` for information on when + you might want to choose one of the other worker classes. Required + libraries may be installed using setuptools' ``extras_require`` feature. + + A string referring to one of the following bundled classes: + + * ``sync`` + * ``eventlet`` - Requires eventlet >= 0.24.1 (or install it via + ``pip install gunicorn[eventlet]``) + * ``gevent`` - Requires gevent >= 1.4 (or install it via + ``pip install gunicorn[gevent]``) + * ``tornado`` - Requires tornado >= 0.2 (or install it via + ``pip install gunicorn[tornado]``) + * ``gthread`` - Python 2 requires the futures package to be installed + (or install it via ``pip install gunicorn[gthread]``) + + Optionally, you can provide your own worker by giving Gunicorn a + Python path to a subclass of ``gunicorn.workers.base.Worker``. + This alternative syntax will load the gevent class: + ``gunicorn.workers.ggevent.GeventWorker``. + """ + + +class WorkerThreads(Setting): + name = "threads" + section = "Worker Processes" + cli = ["--threads"] + meta = "INT" + validator = validate_pos_int + type = int + default = 1 + desc = """\ + The number of worker threads for handling requests. + + Run each worker with the specified number of threads. + + A positive integer generally in the ``2-4 x $(NUM_CORES)`` range. + You'll want to vary this a bit to find the best for your particular + application's work load. + + If it is not defined, the default is ``1``. + + This setting only affects the Gthread worker type. + + .. note:: + If you try to use the ``sync`` worker type and set the ``threads`` + setting to more than 1, the ``gthread`` worker type will be used + instead. + """ + + +class WorkerConnections(Setting): + name = "worker_connections" + section = "Worker Processes" + cli = ["--worker-connections"] + meta = "INT" + validator = validate_pos_int + type = int + default = 1000 + desc = """\ + The maximum number of simultaneous clients. + + This setting only affects the ``gthread``, ``eventlet`` and ``gevent`` worker types. + """ + + +class MaxRequests(Setting): + name = "max_requests" + section = "Worker Processes" + cli = ["--max-requests"] + meta = "INT" + validator = validate_pos_int + type = int + default = 0 + desc = """\ + The maximum number of requests a worker will process before restarting. + + Any value greater than zero will limit the number of requests a worker + will process before automatically restarting. This is a simple method + to help limit the damage of memory leaks. + + If this is set to zero (the default) then the automatic worker + restarts are disabled. + """ + + +class MaxRequestsJitter(Setting): + name = "max_requests_jitter" + section = "Worker Processes" + cli = ["--max-requests-jitter"] + meta = "INT" + validator = validate_pos_int + type = int + default = 0 + desc = """\ + The maximum jitter to add to the *max_requests* setting. + + The jitter causes the restart per worker to be randomized by + ``randint(0, max_requests_jitter)``. This is intended to stagger worker + restarts to avoid all workers restarting at the same time. + + .. versionadded:: 19.2 + """ + + +class Timeout(Setting): + name = "timeout" + section = "Worker Processes" + cli = ["-t", "--timeout"] + meta = "INT" + validator = validate_pos_int + type = int + default = 30 + desc = """\ + Workers silent for more than this many seconds are killed and restarted. + + Value is a positive number or 0. Setting it to 0 has the effect of + infinite timeouts by disabling timeouts for all workers entirely. + + Generally, the default of thirty seconds should suffice. Only set this + noticeably higher if you're sure of the repercussions for sync workers. + For the non sync workers it just means that the worker process is still + communicating and is not tied to the length of time required to handle a + single request. + """ + + +class GracefulTimeout(Setting): + name = "graceful_timeout" + section = "Worker Processes" + cli = ["--graceful-timeout"] + meta = "INT" + validator = validate_pos_int + type = int + default = 30 + desc = """\ + Timeout for graceful workers restart. + + After receiving a restart signal, workers have this much time to finish + serving requests. Workers still alive after the timeout (starting from + the receipt of the restart signal) are force killed. + """ + + +class Keepalive(Setting): + name = "keepalive" + section = "Worker Processes" + cli = ["--keep-alive"] + meta = "INT" + validator = validate_pos_int + type = int + default = 2 + desc = """\ + The number of seconds to wait for requests on a Keep-Alive connection. + + Generally set in the 1-5 seconds range for servers with direct connection + to the client (e.g. when you don't have separate load balancer). When + Gunicorn is deployed behind a load balancer, it often makes sense to + set this to a higher value. + + .. note:: + ``sync`` worker does not support persistent connections and will + ignore this option. + """ + + +class LimitRequestLine(Setting): + name = "limit_request_line" + section = "Security" + cli = ["--limit-request-line"] + meta = "INT" + validator = validate_pos_int + type = int + default = 4094 + desc = """\ + The maximum size of HTTP request line in bytes. + + This parameter is used to limit the allowed size of a client's + HTTP request-line. Since the request-line consists of the HTTP + method, URI, and protocol version, this directive places a + restriction on the length of a request-URI allowed for a request + on the server. A server needs this value to be large enough to + hold any of its resource names, including any information that + might be passed in the query part of a GET request. Value is a number + from 0 (unlimited) to 8190. + + This parameter can be used to prevent any DDOS attack. + """ + + +class LimitRequestFields(Setting): + name = "limit_request_fields" + section = "Security" + cli = ["--limit-request-fields"] + meta = "INT" + validator = validate_pos_int + type = int + default = 100 + desc = """\ + Limit the number of HTTP headers fields in a request. + + This parameter is used to limit the number of headers in a request to + prevent DDOS attack. Used with the *limit_request_field_size* it allows + more safety. By default this value is 100 and can't be larger than + 32768. + """ + + +class LimitRequestFieldSize(Setting): + name = "limit_request_field_size" + section = "Security" + cli = ["--limit-request-field_size"] + meta = "INT" + validator = validate_pos_int + type = int + default = 8190 + desc = """\ + Limit the allowed size of an HTTP request header field. + + Value is a positive number or 0. Setting it to 0 will allow unlimited + header field sizes. + + .. warning:: + Setting this parameter to a very high or unlimited value can open + up for DDOS attacks. + """ + + +class Reload(Setting): + name = "reload" + section = 'Debugging' + cli = ['--reload'] + validator = validate_bool + action = 'store_true' + default = False + + desc = '''\ + Restart workers when code changes. + + This setting is intended for development. It will cause workers to be + restarted whenever application code changes. + + The reloader is incompatible with application preloading. When using a + paste configuration be sure that the server block does not import any + application code or the reload will not work as designed. + + The default behavior is to attempt inotify with a fallback to file + system polling. Generally, inotify should be preferred if available + because it consumes less system resources. + + .. note:: + In order to use the inotify reloader, you must have the ``inotify`` + package installed. + ''' + + +class ReloadEngine(Setting): + name = "reload_engine" + section = "Debugging" + cli = ["--reload-engine"] + meta = "STRING" + validator = validate_reload_engine + default = "auto" + desc = """\ + The implementation that should be used to power :ref:`reload`. + + Valid engines are: + + * ``'auto'`` + * ``'poll'`` + * ``'inotify'`` (requires inotify) + + .. versionadded:: 19.7 + """ + + +class ReloadExtraFiles(Setting): + name = "reload_extra_files" + action = "append" + section = "Debugging" + cli = ["--reload-extra-file"] + meta = "FILES" + validator = validate_list_of_existing_files + default = [] + desc = """\ + Extends :ref:`reload` option to also watch and reload on additional files + (e.g., templates, configurations, specifications, etc.). + + .. versionadded:: 19.8 + """ + + +class Spew(Setting): + name = "spew" + section = "Debugging" + cli = ["--spew"] + validator = validate_bool + action = "store_true" + default = False + desc = """\ + Install a trace function that spews every line executed by the server. + + This is the nuclear option. + """ + + +class ConfigCheck(Setting): + name = "check_config" + section = "Debugging" + cli = ["--check-config"] + validator = validate_bool + action = "store_true" + default = False + desc = """\ + Check the configuration and exit. The exit status is 0 if the + configuration is correct, and 1 if the configuration is incorrect. + """ + + +class PrintConfig(Setting): + name = "print_config" + section = "Debugging" + cli = ["--print-config"] + validator = validate_bool + action = "store_true" + default = False + desc = """\ + Print the configuration settings as fully resolved. Implies :ref:`check-config`. + """ + + +class PreloadApp(Setting): + name = "preload_app" + section = "Server Mechanics" + cli = ["--preload"] + validator = validate_bool + action = "store_true" + default = False + desc = """\ + Load application code before the worker processes are forked. + + By preloading an application you can save some RAM resources as well as + speed up server boot times. Although, if you defer application loading + to each worker process, you can reload your application code easily by + restarting workers. + """ + + +class Sendfile(Setting): + name = "sendfile" + section = "Server Mechanics" + cli = ["--no-sendfile"] + validator = validate_bool + action = "store_const" + const = False + + desc = """\ + Disables the use of ``sendfile()``. + + If not set, the value of the ``SENDFILE`` environment variable is used + to enable or disable its usage. + + .. versionadded:: 19.2 + .. versionchanged:: 19.4 + Swapped ``--sendfile`` with ``--no-sendfile`` to actually allow + disabling. + .. versionchanged:: 19.6 + added support for the ``SENDFILE`` environment variable + """ + + +class ReusePort(Setting): + name = "reuse_port" + section = "Server Mechanics" + cli = ["--reuse-port"] + validator = validate_bool + action = "store_true" + default = False + + desc = """\ + Set the ``SO_REUSEPORT`` flag on the listening socket. + + .. versionadded:: 19.8 + """ + + +class Chdir(Setting): + name = "chdir" + section = "Server Mechanics" + cli = ["--chdir"] + validator = validate_chdir + default = util.getcwd() + default_doc = "``'.'``" + desc = """\ + Change directory to specified directory before loading apps. + """ + + +class Daemon(Setting): + name = "daemon" + section = "Server Mechanics" + cli = ["-D", "--daemon"] + validator = validate_bool + action = "store_true" + default = False + desc = """\ + Daemonize the Gunicorn process. + + Detaches the server from the controlling terminal and enters the + background. + """ + + +class Env(Setting): + name = "raw_env" + action = "append" + section = "Server Mechanics" + cli = ["-e", "--env"] + meta = "ENV" + validator = validate_list_string + default = [] + + desc = """\ + Set environment variables in the execution environment. + + Should be a list of strings in the ``key=value`` format. + + For example on the command line: + + .. code-block:: console + + $ gunicorn -b 127.0.0.1:8000 --env FOO=1 test:app + + Or in the configuration file: + + .. code-block:: python + + raw_env = ["FOO=1"] + """ + + +class Pidfile(Setting): + name = "pidfile" + section = "Server Mechanics" + cli = ["-p", "--pid"] + meta = "FILE" + validator = validate_string + default = None + desc = """\ + A filename to use for the PID file. + + If not set, no PID file will be written. + """ + + +class WorkerTmpDir(Setting): + name = "worker_tmp_dir" + section = "Server Mechanics" + cli = ["--worker-tmp-dir"] + meta = "DIR" + validator = validate_string + default = None + desc = """\ + A directory to use for the worker heartbeat temporary file. + + If not set, the default temporary directory will be used. + + .. note:: + The current heartbeat system involves calling ``os.fchmod`` on + temporary file handlers and may block a worker for arbitrary time + if the directory is on a disk-backed filesystem. + + See :ref:`blocking-os-fchmod` for more detailed information + and a solution for avoiding this problem. + """ + + +class User(Setting): + name = "user" + section = "Server Mechanics" + cli = ["-u", "--user"] + meta = "USER" + validator = validate_user + default = os.geteuid() + default_doc = "``os.geteuid()``" + desc = """\ + Switch worker processes to run as this user. + + A valid user id (as an integer) or the name of a user that can be + retrieved with a call to ``pwd.getpwnam(value)`` or ``None`` to not + change the worker process user. + """ + + +class Group(Setting): + name = "group" + section = "Server Mechanics" + cli = ["-g", "--group"] + meta = "GROUP" + validator = validate_group + default = os.getegid() + default_doc = "``os.getegid()``" + desc = """\ + Switch worker process to run as this group. + + A valid group id (as an integer) or the name of a user that can be + retrieved with a call to ``pwd.getgrnam(value)`` or ``None`` to not + change the worker processes group. + """ + + +class Umask(Setting): + name = "umask" + section = "Server Mechanics" + cli = ["-m", "--umask"] + meta = "INT" + validator = validate_pos_int + type = auto_int + default = 0 + desc = """\ + A bit mask for the file mode on files written by Gunicorn. + + Note that this affects unix socket permissions. + + A valid value for the ``os.umask(mode)`` call or a string compatible + with ``int(value, 0)`` (``0`` means Python guesses the base, so values + like ``0``, ``0xFF``, ``0022`` are valid for decimal, hex, and octal + representations) + """ + + +class Initgroups(Setting): + name = "initgroups" + section = "Server Mechanics" + cli = ["--initgroups"] + validator = validate_bool + action = 'store_true' + default = False + + desc = """\ + If true, set the worker process's group access list with all of the + groups of which the specified username is a member, plus the specified + group id. + + .. versionadded:: 19.7 + """ + + +class TmpUploadDir(Setting): + name = "tmp_upload_dir" + section = "Server Mechanics" + meta = "DIR" + validator = validate_string + default = None + desc = """\ + Directory to store temporary request data as they are read. + + This may disappear in the near future. + + This path should be writable by the process permissions set for Gunicorn + workers. If not specified, Gunicorn will choose a system generated + temporary directory. + """ + + +class SecureSchemeHeader(Setting): + name = "secure_scheme_headers" + section = "Server Mechanics" + validator = validate_dict + default = { + "X-FORWARDED-PROTOCOL": "ssl", + "X-FORWARDED-PROTO": "https", + "X-FORWARDED-SSL": "on" + } + desc = """\ + + A dictionary containing headers and values that the front-end proxy + uses to indicate HTTPS requests. If the source IP is permitted by + ``forwarded-allow-ips`` (below), *and* at least one request header matches + a key-value pair listed in this dictionary, then Gunicorn will set + ``wsgi.url_scheme`` to ``https``, so your application can tell that the + request is secure. + + If the other headers listed in this dictionary are not present in the request, they will be ignored, + but if the other headers are present and do not match the provided values, then + the request will fail to parse. See the note below for more detailed examples of this behaviour. + + The dictionary should map upper-case header names to exact string + values. The value comparisons are case-sensitive, unlike the header + names, so make sure they're exactly what your front-end proxy sends + when handling HTTPS requests. + + It is important that your front-end proxy configuration ensures that + the headers defined here can not be passed directly from the client. + """ + + +class ForwardedAllowIPS(Setting): + name = "forwarded_allow_ips" + section = "Server Mechanics" + cli = ["--forwarded-allow-ips"] + meta = "STRING" + validator = validate_string_to_list + default = os.environ.get("FORWARDED_ALLOW_IPS", "127.0.0.1") + desc = """\ + Front-end's IPs from which allowed to handle set secure headers. + (comma separate). + + Set to ``*`` to disable checking of Front-end IPs (useful for setups + where you don't know in advance the IP address of Front-end, but + you still trust the environment). + + By default, the value of the ``FORWARDED_ALLOW_IPS`` environment + variable. If it is not defined, the default is ``"127.0.0.1"``. + + .. note:: + + The interplay between the request headers, the value of ``forwarded_allow_ips``, and the value of + ``secure_scheme_headers`` is complex. Various scenarios are documented below to further elaborate. + In each case, we have a request from the remote address 134.213.44.18, and the default value of + ``secure_scheme_headers``: + + .. code:: + + secure_scheme_headers = { + 'X-FORWARDED-PROTOCOL': 'ssl', + 'X-FORWARDED-PROTO': 'https', + 'X-FORWARDED-SSL': 'on' + } + + + .. list-table:: + :header-rows: 1 + :align: center + :widths: auto + + * - ``forwarded-allow-ips`` + - Secure Request Headers + - Result + - Explanation + * - .. code:: + + ["127.0.0.1"] + - .. code:: + + X-Forwarded-Proto: https + - .. code:: + + wsgi.url_scheme = "http" + - IP address was not allowed + * - .. code:: + + "*" + - + - .. code:: + + wsgi.url_scheme = "http" + - IP address allowed, but no secure headers provided + * - .. code:: + + "*" + - .. code:: + + X-Forwarded-Proto: https + - .. code:: + + wsgi.url_scheme = "https" + - IP address allowed, one request header matched + * - .. code:: + + ["134.213.44.18"] + - .. code:: + + X-Forwarded-Ssl: on + X-Forwarded-Proto: http + - ``InvalidSchemeHeaders()`` raised + - IP address allowed, but the two secure headers disagreed on if HTTPS was used + + + """ + + +class AccessLog(Setting): + name = "accesslog" + section = "Logging" + cli = ["--access-logfile"] + meta = "FILE" + validator = validate_string + default = None + desc = """\ + The Access log file to write to. + + ``'-'`` means log to stdout. + """ + + +class DisableRedirectAccessToSyslog(Setting): + name = "disable_redirect_access_to_syslog" + section = "Logging" + cli = ["--disable-redirect-access-to-syslog"] + validator = validate_bool + action = 'store_true' + default = False + desc = """\ + Disable redirect access logs to syslog. + + .. versionadded:: 19.8 + """ + + +class AccessLogFormat(Setting): + name = "access_log_format" + section = "Logging" + cli = ["--access-logformat"] + meta = "STRING" + validator = validate_string + default = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"' + desc = """\ + The access log format. + + =========== =========== + Identifier Description + =========== =========== + h remote address + l ``'-'`` + u user name + t date of the request + r status line (e.g. ``GET / HTTP/1.1``) + m request method + U URL path without query string + q query string + H protocol + s status + B response length + b response length or ``'-'`` (CLF format) + f referer + a user agent + T request time in seconds + M request time in milliseconds + D request time in microseconds + L request time in decimal seconds + p process ID + {header}i request header + {header}o response header + {variable}e environment variable + =========== =========== + + Use lowercase for header and environment variable names, and put + ``{...}x`` names inside ``%(...)s``. For example:: + + %({x-forwarded-for}i)s + """ + + +class ErrorLog(Setting): + name = "errorlog" + section = "Logging" + cli = ["--error-logfile", "--log-file"] + meta = "FILE" + validator = validate_string + default = '-' + desc = """\ + The Error log file to write to. + + Using ``'-'`` for FILE makes gunicorn log to stderr. + + .. versionchanged:: 19.2 + Log to stderr by default. + + """ + + +class Loglevel(Setting): + name = "loglevel" + section = "Logging" + cli = ["--log-level"] + meta = "LEVEL" + validator = validate_string + default = "info" + desc = """\ + The granularity of Error log outputs. + + Valid level names are: + + * ``'debug'`` + * ``'info'`` + * ``'warning'`` + * ``'error'`` + * ``'critical'`` + """ + + +class CaptureOutput(Setting): + name = "capture_output" + section = "Logging" + cli = ["--capture-output"] + validator = validate_bool + action = 'store_true' + default = False + desc = """\ + Redirect stdout/stderr to specified file in :ref:`errorlog`. + + .. versionadded:: 19.6 + """ + + +class LoggerClass(Setting): + name = "logger_class" + section = "Logging" + cli = ["--logger-class"] + meta = "STRING" + validator = validate_class + default = "gunicorn.glogging.Logger" + desc = """\ + The logger you want to use to log events in Gunicorn. + + The default class (``gunicorn.glogging.Logger``) handles most + normal usages in logging. It provides error and access logging. + + You can provide your own logger by giving Gunicorn a Python path to a + class that quacks like ``gunicorn.glogging.Logger``. + """ + + +class LogConfig(Setting): + name = "logconfig" + section = "Logging" + cli = ["--log-config"] + meta = "FILE" + validator = validate_string + default = None + desc = """\ + The log config file to use. + Gunicorn uses the standard Python logging module's Configuration + file format. + """ + + +class LogConfigDict(Setting): + name = "logconfig_dict" + section = "Logging" + validator = validate_dict + default = {} + desc = """\ + The log config dictionary to use, using the standard Python + logging module's dictionary configuration format. This option + takes precedence over the :ref:`logconfig` and :ref:`logConfigJson` options, + which uses the older file configuration format and JSON + respectively. + + Format: https://docs.python.org/3/library/logging.config.html#logging.config.dictConfig + + For more context you can look at the default configuration dictionary for logging, + which can be found at ``gunicorn.glogging.CONFIG_DEFAULTS``. + + .. versionadded:: 19.8 + """ + + +class LogConfigJson(Setting): + name = "logconfig_json" + section = "Logging" + cli = ["--log-config-json"] + meta = "FILE" + validator = validate_string + default = None + desc = """\ + The log config to read config from a JSON file + + Format: https://docs.python.org/3/library/logging.config.html#logging.config.jsonConfig + + .. versionadded:: 20.0 + """ + + +class SyslogTo(Setting): + name = "syslog_addr" + section = "Logging" + cli = ["--log-syslog-to"] + meta = "SYSLOG_ADDR" + validator = validate_string + + if PLATFORM == "darwin": + default = "unix:///var/run/syslog" + elif PLATFORM in ('freebsd', 'dragonfly', ): + default = "unix:///var/run/log" + elif PLATFORM == "openbsd": + default = "unix:///dev/log" + else: + default = "udp://localhost:514" + + desc = """\ + Address to send syslog messages. + + Address is a string of the form: + + * ``unix://PATH#TYPE`` : for unix domain socket. ``TYPE`` can be ``stream`` + for the stream driver or ``dgram`` for the dgram driver. + ``stream`` is the default. + * ``udp://HOST:PORT`` : for UDP sockets + * ``tcp://HOST:PORT`` : for TCP sockets + + """ + + +class Syslog(Setting): + name = "syslog" + section = "Logging" + cli = ["--log-syslog"] + validator = validate_bool + action = 'store_true' + default = False + desc = """\ + Send *Gunicorn* logs to syslog. + + .. versionchanged:: 19.8 + You can now disable sending access logs by using the + :ref:`disable-redirect-access-to-syslog` setting. + """ + + +class SyslogPrefix(Setting): + name = "syslog_prefix" + section = "Logging" + cli = ["--log-syslog-prefix"] + meta = "SYSLOG_PREFIX" + validator = validate_string + default = None + desc = """\ + Makes Gunicorn use the parameter as program-name in the syslog entries. + + All entries will be prefixed by ``gunicorn.``. By default the + program name is the name of the process. + """ + + +class SyslogFacility(Setting): + name = "syslog_facility" + section = "Logging" + cli = ["--log-syslog-facility"] + meta = "SYSLOG_FACILITY" + validator = validate_string + default = "user" + desc = """\ + Syslog facility name + """ + + +class EnableStdioInheritance(Setting): + name = "enable_stdio_inheritance" + section = "Logging" + cli = ["-R", "--enable-stdio-inheritance"] + validator = validate_bool + default = False + action = "store_true" + desc = """\ + Enable stdio inheritance. + + Enable inheritance for stdio file descriptors in daemon mode. + + Note: To disable the Python stdout buffering, you can to set the user + environment variable ``PYTHONUNBUFFERED`` . + """ + + +# statsD monitoring +class StatsdHost(Setting): + name = "statsd_host" + section = "Logging" + cli = ["--statsd-host"] + meta = "STATSD_ADDR" + default = None + validator = validate_statsd_address + desc = """\ + The address of the StatsD server to log to. + + Address is a string of the form: + + * ``unix://PATH`` : for a unix domain socket. + * ``HOST:PORT`` : for a network address + + .. versionadded:: 19.1 + """ + + +# Datadog Statsd (dogstatsd) tags. https://docs.datadoghq.com/developers/dogstatsd/ +class DogstatsdTags(Setting): + name = "dogstatsd_tags" + section = "Logging" + cli = ["--dogstatsd-tags"] + meta = "DOGSTATSD_TAGS" + default = "" + validator = validate_string + desc = """\ + A comma-delimited list of datadog statsd (dogstatsd) tags to append to + statsd metrics. + + .. versionadded:: 20 + """ + + +class StatsdPrefix(Setting): + name = "statsd_prefix" + section = "Logging" + cli = ["--statsd-prefix"] + meta = "STATSD_PREFIX" + default = "" + validator = validate_string + desc = """\ + Prefix to use when emitting statsd metrics (a trailing ``.`` is added, + if not provided). + + .. versionadded:: 19.2 + """ + + +class Procname(Setting): + name = "proc_name" + section = "Process Naming" + cli = ["-n", "--name"] + meta = "STRING" + validator = validate_string + default = None + desc = """\ + A base to use with setproctitle for process naming. + + This affects things like ``ps`` and ``top``. If you're going to be + running more than one instance of Gunicorn you'll probably want to set a + name to tell them apart. This requires that you install the setproctitle + module. + + If not set, the *default_proc_name* setting will be used. + """ + + +class DefaultProcName(Setting): + name = "default_proc_name" + section = "Process Naming" + validator = validate_string + default = "gunicorn" + desc = """\ + Internal setting that is adjusted for each type of application. + """ + + +class PythonPath(Setting): + name = "pythonpath" + section = "Server Mechanics" + cli = ["--pythonpath"] + meta = "STRING" + validator = validate_string + default = None + desc = """\ + A comma-separated list of directories to add to the Python path. + + e.g. + ``'/home/djangoprojects/myproject,/home/python/mylibrary'``. + """ + + +class Paste(Setting): + name = "paste" + section = "Server Mechanics" + cli = ["--paste", "--paster"] + meta = "STRING" + validator = validate_string + default = None + desc = """\ + Load a PasteDeploy config file. The argument may contain a ``#`` + symbol followed by the name of an app section from the config file, + e.g. ``production.ini#admin``. + + At this time, using alternate server blocks is not supported. Use the + command line arguments to control server configuration instead. + """ + + +class OnStarting(Setting): + name = "on_starting" + section = "Server Hooks" + validator = validate_callable(1) + type = callable + + def on_starting(server): + pass + default = staticmethod(on_starting) + desc = """\ + Called just before the master process is initialized. + + The callable needs to accept a single instance variable for the Arbiter. + """ + + +class OnReload(Setting): + name = "on_reload" + section = "Server Hooks" + validator = validate_callable(1) + type = callable + + def on_reload(server): + pass + default = staticmethod(on_reload) + desc = """\ + Called to recycle workers during a reload via SIGHUP. + + The callable needs to accept a single instance variable for the Arbiter. + """ + + +class WhenReady(Setting): + name = "when_ready" + section = "Server Hooks" + validator = validate_callable(1) + type = callable + + def when_ready(server): + pass + default = staticmethod(when_ready) + desc = """\ + Called just after the server is started. + + The callable needs to accept a single instance variable for the Arbiter. + """ + + +class Prefork(Setting): + name = "pre_fork" + section = "Server Hooks" + validator = validate_callable(2) + type = callable + + def pre_fork(server, worker): + pass + default = staticmethod(pre_fork) + desc = """\ + Called just before a worker is forked. + + The callable needs to accept two instance variables for the Arbiter and + new Worker. + """ + + +class Postfork(Setting): + name = "post_fork" + section = "Server Hooks" + validator = validate_callable(2) + type = callable + + def post_fork(server, worker): + pass + default = staticmethod(post_fork) + desc = """\ + Called just after a worker has been forked. + + The callable needs to accept two instance variables for the Arbiter and + new Worker. + """ + + +class PostWorkerInit(Setting): + name = "post_worker_init" + section = "Server Hooks" + validator = validate_callable(1) + type = callable + + def post_worker_init(worker): + pass + + default = staticmethod(post_worker_init) + desc = """\ + Called just after a worker has initialized the application. + + The callable needs to accept one instance variable for the initialized + Worker. + """ + + +class WorkerInt(Setting): + name = "worker_int" + section = "Server Hooks" + validator = validate_callable(1) + type = callable + + def worker_int(worker): + pass + + default = staticmethod(worker_int) + desc = """\ + Called just after a worker exited on SIGINT or SIGQUIT. + + The callable needs to accept one instance variable for the initialized + Worker. + """ + + +class WorkerAbort(Setting): + name = "worker_abort" + section = "Server Hooks" + validator = validate_callable(1) + type = callable + + def worker_abort(worker): + pass + + default = staticmethod(worker_abort) + desc = """\ + Called when a worker received the SIGABRT signal. + + This call generally happens on timeout. + + The callable needs to accept one instance variable for the initialized + Worker. + """ + + +class PreExec(Setting): + name = "pre_exec" + section = "Server Hooks" + validator = validate_callable(1) + type = callable + + def pre_exec(server): + pass + default = staticmethod(pre_exec) + desc = """\ + Called just before a new master process is forked. + + The callable needs to accept a single instance variable for the Arbiter. + """ + + +class PreRequest(Setting): + name = "pre_request" + section = "Server Hooks" + validator = validate_callable(2) + type = callable + + def pre_request(worker, req): + worker.log.debug("%s %s", req.method, req.path) + default = staticmethod(pre_request) + desc = """\ + Called just before a worker processes the request. + + The callable needs to accept two instance variables for the Worker and + the Request. + """ + + +class PostRequest(Setting): + name = "post_request" + section = "Server Hooks" + validator = validate_post_request + type = callable + + def post_request(worker, req, environ, resp): + pass + default = staticmethod(post_request) + desc = """\ + Called after a worker processes the request. + + The callable needs to accept two instance variables for the Worker and + the Request. + """ + + +class ChildExit(Setting): + name = "child_exit" + section = "Server Hooks" + validator = validate_callable(2) + type = callable + + def child_exit(server, worker): + pass + default = staticmethod(child_exit) + desc = """\ + Called just after a worker has been exited, in the master process. + + The callable needs to accept two instance variables for the Arbiter and + the just-exited Worker. + + .. versionadded:: 19.7 + """ + + +class WorkerExit(Setting): + name = "worker_exit" + section = "Server Hooks" + validator = validate_callable(2) + type = callable + + def worker_exit(server, worker): + pass + default = staticmethod(worker_exit) + desc = """\ + Called just after a worker has been exited, in the worker process. + + The callable needs to accept two instance variables for the Arbiter and + the just-exited Worker. + """ + + +class NumWorkersChanged(Setting): + name = "nworkers_changed" + section = "Server Hooks" + validator = validate_callable(3) + type = callable + + def nworkers_changed(server, new_value, old_value): + pass + default = staticmethod(nworkers_changed) + desc = """\ + Called just after *num_workers* has been changed. + + The callable needs to accept an instance variable of the Arbiter and + two integers of number of workers after and before change. + + If the number of workers is set for the first time, *old_value* would + be ``None``. + """ + + +class OnExit(Setting): + name = "on_exit" + section = "Server Hooks" + validator = validate_callable(1) + + def on_exit(server): + pass + + default = staticmethod(on_exit) + desc = """\ + Called just before exiting Gunicorn. + + The callable needs to accept a single instance variable for the Arbiter. + """ + + +class NewSSLContext(Setting): + name = "ssl_context" + section = "Server Hooks" + validator = validate_callable(2) + type = callable + + def ssl_context(config, default_ssl_context_factory): + return default_ssl_context_factory() + + default = staticmethod(ssl_context) + desc = """\ + Called when SSLContext is needed. + + Allows customizing SSL context. + + The callable needs to accept an instance variable for the Config and + a factory function that returns default SSLContext which is initialized + with certificates, private key, cert_reqs, and ciphers according to + config and can be further customized by the callable. + The callable needs to return SSLContext object. + + Following example shows a configuration file that sets the minimum TLS version to 1.3: + + .. code-block:: python + + def ssl_context(conf, default_ssl_context_factory): + import ssl + context = default_ssl_context_factory() + context.minimum_version = ssl.TLSVersion.TLSv1_3 + return context + + .. versionadded:: 20.2 + """ + + +class ProxyProtocol(Setting): + name = "proxy_protocol" + section = "Server Mechanics" + cli = ["--proxy-protocol"] + validator = validate_bool + default = False + action = "store_true" + desc = """\ + Enable detect PROXY protocol (PROXY mode). + + Allow using HTTP and Proxy together. It may be useful for work with + stunnel as HTTPS frontend and Gunicorn as HTTP server. + + PROXY protocol: http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt + + Example for stunnel config:: + + [https] + protocol = proxy + accept = 443 + connect = 80 + cert = /etc/ssl/certs/stunnel.pem + key = /etc/ssl/certs/stunnel.key + """ + + +class ProxyAllowFrom(Setting): + name = "proxy_allow_ips" + section = "Server Mechanics" + cli = ["--proxy-allow-from"] + validator = validate_string_to_list + default = "127.0.0.1" + desc = """\ + Front-end's IPs from which allowed accept proxy requests (comma separate). + + Set to ``*`` to disable checking of Front-end IPs (useful for setups + where you don't know in advance the IP address of Front-end, but + you still trust the environment) + """ + + +class KeyFile(Setting): + name = "keyfile" + section = "SSL" + cli = ["--keyfile"] + meta = "FILE" + validator = validate_string + default = None + desc = """\ + SSL key file + """ + + +class CertFile(Setting): + name = "certfile" + section = "SSL" + cli = ["--certfile"] + meta = "FILE" + validator = validate_string + default = None + desc = """\ + SSL certificate file + """ + + +class SSLVersion(Setting): + name = "ssl_version" + section = "SSL" + cli = ["--ssl-version"] + validator = validate_ssl_version + + if hasattr(ssl, "PROTOCOL_TLS"): + default = ssl.PROTOCOL_TLS + else: + default = ssl.PROTOCOL_SSLv23 + + default = ssl.PROTOCOL_SSLv23 + desc = """\ + SSL version to use (see stdlib ssl module's). + + .. deprecated:: 20.2 + The option is deprecated and it is currently ignored. Use :ref:`ssl-context` instead. + + ============= ============ + --ssl-version Description + ============= ============ + SSLv3 SSLv3 is not-secure and is strongly discouraged. + SSLv23 Alias for TLS. Deprecated in Python 3.6, use TLS. + TLS Negotiate highest possible version between client/server. + Can yield SSL. (Python 3.6+) + TLSv1 TLS 1.0 + TLSv1_1 TLS 1.1 (Python 3.4+) + TLSv1_2 TLS 1.2 (Python 3.4+) + TLS_SERVER Auto-negotiate the highest protocol version like TLS, + but only support server-side SSLSocket connections. + (Python 3.6+) + ============= ============ + + .. versionchanged:: 19.7 + The default value has been changed from ``ssl.PROTOCOL_TLSv1`` to + ``ssl.PROTOCOL_SSLv23``. + .. versionchanged:: 20.0 + This setting now accepts string names based on ``ssl.PROTOCOL_`` + constants. + .. versionchanged:: 20.0.1 + The default value has been changed from ``ssl.PROTOCOL_SSLv23`` to + ``ssl.PROTOCOL_TLS`` when Python >= 3.6 . + """ + + +class CertReqs(Setting): + name = "cert_reqs" + section = "SSL" + cli = ["--cert-reqs"] + validator = validate_pos_int + default = ssl.CERT_NONE + desc = """\ + Whether client certificate is required (see stdlib ssl module's) + + =========== =========================== + --cert-reqs Description + =========== =========================== + `0` no client veirifcation + `1` ssl.CERT_OPTIONAL + `2` ssl.CERT_REQUIRED + =========== =========================== + """ + + +class CACerts(Setting): + name = "ca_certs" + section = "SSL" + cli = ["--ca-certs"] + meta = "FILE" + validator = validate_string + default = None + desc = """\ + CA certificates file + """ + + +class SuppressRaggedEOFs(Setting): + name = "suppress_ragged_eofs" + section = "SSL" + cli = ["--suppress-ragged-eofs"] + action = "store_true" + default = True + validator = validate_bool + desc = """\ + Suppress ragged EOFs (see stdlib ssl module's) + """ + + +class DoHandshakeOnConnect(Setting): + name = "do_handshake_on_connect" + section = "SSL" + cli = ["--do-handshake-on-connect"] + validator = validate_bool + action = "store_true" + default = False + desc = """\ + Whether to perform SSL handshake on socket connect (see stdlib ssl module's) + """ + + +class Ciphers(Setting): + name = "ciphers" + section = "SSL" + cli = ["--ciphers"] + validator = validate_string + default = None + desc = """\ + SSL Cipher suite to use, in the format of an OpenSSL cipher list. + + By default we use the default cipher list from Python's ``ssl`` module, + which contains ciphers considered strong at the time of each Python + release. + + As a recommended alternative, the Open Web App Security Project (OWASP) + offers `a vetted set of strong cipher strings rated A+ to C- + `_. + OWASP provides details on user-agent compatibility at each security level. + + See the `OpenSSL Cipher List Format Documentation + `_ + for details on the format of an OpenSSL cipher list. + """ + + +class PasteGlobalConf(Setting): + name = "raw_paste_global_conf" + action = "append" + section = "Server Mechanics" + cli = ["--paste-global"] + meta = "CONF" + validator = validate_list_string + default = [] + + desc = """\ + Set a PasteDeploy global config variable in ``key=value`` form. + + The option can be specified multiple times. + + The variables are passed to the the PasteDeploy entrypoint. Example:: + + $ gunicorn -b 127.0.0.1:8000 --paste development.ini --paste-global FOO=1 --paste-global BAR=2 + + .. versionadded:: 19.7 + """ + + +class StripHeaderSpaces(Setting): + name = "strip_header_spaces" + section = "Server Mechanics" + cli = ["--strip-header-spaces"] + validator = validate_bool + action = "store_true" + default = False + desc = """\ + Strip spaces present between the header name and the the ``:``. + + This is known to induce vulnerabilities and is not compliant with the HTTP/1.1 standard. + See https://portswigger.net/research/http-desync-attacks-request-smuggling-reborn. + + Use with care and only if necessary. + """ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/debug.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/debug.py new file mode 100644 index 0000000..a492df9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/debug.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +"""The debug module contains utilities and functions for better +debugging Gunicorn.""" + +import sys +import linecache +import re +import inspect + +__all__ = ['spew', 'unspew'] + +_token_spliter = re.compile(r'\W+') + + +class Spew(object): + + def __init__(self, trace_names=None, show_values=True): + self.trace_names = trace_names + self.show_values = show_values + + def __call__(self, frame, event, arg): + if event == 'line': + lineno = frame.f_lineno + if '__file__' in frame.f_globals: + filename = frame.f_globals['__file__'] + if (filename.endswith('.pyc') or + filename.endswith('.pyo')): + filename = filename[:-1] + name = frame.f_globals['__name__'] + line = linecache.getline(filename, lineno) + else: + name = '[unknown]' + try: + src = inspect.getsourcelines(frame) + line = src[lineno] + except IOError: + line = 'Unknown code named [%s]. VM instruction #%d' % ( + frame.f_code.co_name, frame.f_lasti) + if self.trace_names is None or name in self.trace_names: + print('%s:%s: %s' % (name, lineno, line.rstrip())) + if not self.show_values: + return self + details = [] + tokens = _token_spliter.split(line) + for tok in tokens: + if tok in frame.f_globals: + details.append('%s=%r' % (tok, frame.f_globals[tok])) + if tok in frame.f_locals: + details.append('%s=%r' % (tok, frame.f_locals[tok])) + if details: + print("\t%s" % ' '.join(details)) + return self + + +def spew(trace_names=None, show_values=False): + """Install a trace hook which writes incredibly detailed logs + about what code is being executed to stdout. + """ + sys.settrace(Spew(trace_names, show_values)) + + +def unspew(): + """Remove the trace hook installed by spew. + """ + sys.settrace(None) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/errors.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/errors.py new file mode 100644 index 0000000..727d336 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/errors.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +# We don't need to call super() in __init__ methods of our +# BaseException and Exception classes because we also define +# our own __str__ methods so there is no need to pass 'message' +# to the base class to get a meaningful output from 'str(exc)'. +# pylint: disable=super-init-not-called + + +# we inherit from BaseException here to make sure to not be caught +# at application level +class HaltServer(BaseException): + def __init__(self, reason, exit_status=1): + self.reason = reason + self.exit_status = exit_status + + def __str__(self): + return "" % (self.reason, self.exit_status) + + +class ConfigError(Exception): + """ Exception raised on config error """ + + +class AppImportError(Exception): + """ Exception raised when loading an application """ diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/glogging.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/glogging.py new file mode 100644 index 0000000..b552e26 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/glogging.py @@ -0,0 +1,474 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +import base64 +import binascii +import json +import time +import logging +logging.Logger.manager.emittedNoHandlerWarning = 1 # noqa +from logging.config import dictConfig +from logging.config import fileConfig +import os +import socket +import sys +import threading +import traceback + +from gunicorn import util + + +# syslog facility codes +SYSLOG_FACILITIES = { + "auth": 4, + "authpriv": 10, + "cron": 9, + "daemon": 3, + "ftp": 11, + "kern": 0, + "lpr": 6, + "mail": 2, + "news": 7, + "security": 4, # DEPRECATED + "syslog": 5, + "user": 1, + "uucp": 8, + "local0": 16, + "local1": 17, + "local2": 18, + "local3": 19, + "local4": 20, + "local5": 21, + "local6": 22, + "local7": 23 +} + +CONFIG_DEFAULTS = { + "version": 1, + "disable_existing_loggers": False, + "root": {"level": "INFO", "handlers": ["console"]}, + "loggers": { + "gunicorn.error": { + "level": "INFO", + "handlers": ["error_console"], + "propagate": True, + "qualname": "gunicorn.error" + }, + + "gunicorn.access": { + "level": "INFO", + "handlers": ["console"], + "propagate": True, + "qualname": "gunicorn.access" + } + }, + "handlers": { + "console": { + "class": "logging.StreamHandler", + "formatter": "generic", + "stream": "ext://sys.stdout" + }, + "error_console": { + "class": "logging.StreamHandler", + "formatter": "generic", + "stream": "ext://sys.stderr" + }, + }, + "formatters": { + "generic": { + "format": "%(asctime)s [%(process)d] [%(levelname)s] %(message)s", + "datefmt": "[%Y-%m-%d %H:%M:%S %z]", + "class": "logging.Formatter" + } + } +} + + +def loggers(): + """ get list of all loggers """ + root = logging.root + existing = list(root.manager.loggerDict.keys()) + return [logging.getLogger(name) for name in existing] + + +class SafeAtoms(dict): + + def __init__(self, atoms): + dict.__init__(self) + for key, value in atoms.items(): + if isinstance(value, str): + self[key] = value.replace('"', '\\"') + else: + self[key] = value + + def __getitem__(self, k): + if k.startswith("{"): + kl = k.lower() + if kl in self: + return super().__getitem__(kl) + else: + return "-" + if k in self: + return super().__getitem__(k) + else: + return '-' + + +def parse_syslog_address(addr): + + # unix domain socket type depends on backend + # SysLogHandler will try both when given None + if addr.startswith("unix://"): + sock_type = None + + # set socket type only if explicitly requested + parts = addr.split("#", 1) + if len(parts) == 2: + addr = parts[0] + if parts[1] == "dgram": + sock_type = socket.SOCK_DGRAM + + return (sock_type, addr.split("unix://")[1]) + + if addr.startswith("udp://"): + addr = addr.split("udp://")[1] + socktype = socket.SOCK_DGRAM + elif addr.startswith("tcp://"): + addr = addr.split("tcp://")[1] + socktype = socket.SOCK_STREAM + else: + raise RuntimeError("invalid syslog address") + + if '[' in addr and ']' in addr: + host = addr.split(']')[0][1:].lower() + elif ':' in addr: + host = addr.split(':')[0].lower() + elif addr == "": + host = "localhost" + else: + host = addr.lower() + + addr = addr.split(']')[-1] + if ":" in addr: + port = addr.split(':', 1)[1] + if not port.isdigit(): + raise RuntimeError("%r is not a valid port number." % port) + port = int(port) + else: + port = 514 + + return (socktype, (host, port)) + + +class Logger(object): + + LOG_LEVELS = { + "critical": logging.CRITICAL, + "error": logging.ERROR, + "warning": logging.WARNING, + "info": logging.INFO, + "debug": logging.DEBUG + } + loglevel = logging.INFO + + error_fmt = r"%(asctime)s [%(process)d] [%(levelname)s] %(message)s" + datefmt = r"[%Y-%m-%d %H:%M:%S %z]" + + access_fmt = "%(message)s" + syslog_fmt = "[%(process)d] %(message)s" + + atoms_wrapper_class = SafeAtoms + + def __init__(self, cfg): + self.error_log = logging.getLogger("gunicorn.error") + self.error_log.propagate = False + self.access_log = logging.getLogger("gunicorn.access") + self.access_log.propagate = False + self.error_handlers = [] + self.access_handlers = [] + self.logfile = None + self.lock = threading.Lock() + self.cfg = cfg + self.setup(cfg) + + def setup(self, cfg): + self.loglevel = self.LOG_LEVELS.get(cfg.loglevel.lower(), logging.INFO) + self.error_log.setLevel(self.loglevel) + self.access_log.setLevel(logging.INFO) + + # set gunicorn.error handler + if self.cfg.capture_output and cfg.errorlog != "-": + for stream in sys.stdout, sys.stderr: + stream.flush() + + self.logfile = open(cfg.errorlog, 'a+') + os.dup2(self.logfile.fileno(), sys.stdout.fileno()) + os.dup2(self.logfile.fileno(), sys.stderr.fileno()) + + self._set_handler(self.error_log, cfg.errorlog, + logging.Formatter(self.error_fmt, self.datefmt)) + + # set gunicorn.access handler + if cfg.accesslog is not None: + self._set_handler( + self.access_log, cfg.accesslog, + fmt=logging.Formatter(self.access_fmt), stream=sys.stdout + ) + + # set syslog handler + if cfg.syslog: + self._set_syslog_handler( + self.error_log, cfg, self.syslog_fmt, "error" + ) + if not cfg.disable_redirect_access_to_syslog: + self._set_syslog_handler( + self.access_log, cfg, self.syslog_fmt, "access" + ) + + if cfg.logconfig_dict: + config = CONFIG_DEFAULTS.copy() + config.update(cfg.logconfig_dict) + try: + dictConfig(config) + except ( + AttributeError, + ImportError, + ValueError, + TypeError + ) as exc: + raise RuntimeError(str(exc)) + elif cfg.logconfig_json: + config = CONFIG_DEFAULTS.copy() + if os.path.exists(cfg.logconfig_json): + try: + config_json = json.load(open(cfg.logconfig_json)) + config.update(config_json) + dictConfig(config) + except ( + json.JSONDecodeError, + AttributeError, + ImportError, + ValueError, + TypeError + ) as exc: + raise RuntimeError(str(exc)) + elif cfg.logconfig: + if os.path.exists(cfg.logconfig): + defaults = CONFIG_DEFAULTS.copy() + defaults['__file__'] = cfg.logconfig + defaults['here'] = os.path.dirname(cfg.logconfig) + fileConfig(cfg.logconfig, defaults=defaults, + disable_existing_loggers=False) + else: + msg = "Error: log config '%s' not found" + raise RuntimeError(msg % cfg.logconfig) + + def critical(self, msg, *args, **kwargs): + self.error_log.critical(msg, *args, **kwargs) + + def error(self, msg, *args, **kwargs): + self.error_log.error(msg, *args, **kwargs) + + def warning(self, msg, *args, **kwargs): + self.error_log.warning(msg, *args, **kwargs) + + def info(self, msg, *args, **kwargs): + self.error_log.info(msg, *args, **kwargs) + + def debug(self, msg, *args, **kwargs): + self.error_log.debug(msg, *args, **kwargs) + + def exception(self, msg, *args, **kwargs): + self.error_log.exception(msg, *args, **kwargs) + + def log(self, lvl, msg, *args, **kwargs): + if isinstance(lvl, str): + lvl = self.LOG_LEVELS.get(lvl.lower(), logging.INFO) + self.error_log.log(lvl, msg, *args, **kwargs) + + def atoms(self, resp, req, environ, request_time): + """ Gets atoms for log formatting. + """ + status = resp.status + if isinstance(status, str): + status = status.split(None, 1)[0] + atoms = { + 'h': environ.get('REMOTE_ADDR', '-'), + 'l': '-', + 'u': self._get_user(environ) or '-', + 't': self.now(), + 'r': "%s %s %s" % (environ['REQUEST_METHOD'], + environ['RAW_URI'], + environ["SERVER_PROTOCOL"]), + 's': status, + 'm': environ.get('REQUEST_METHOD'), + 'U': environ.get('PATH_INFO'), + 'q': environ.get('QUERY_STRING'), + 'H': environ.get('SERVER_PROTOCOL'), + 'b': getattr(resp, 'sent', None) is not None and str(resp.sent) or '-', + 'B': getattr(resp, 'sent', None), + 'f': environ.get('HTTP_REFERER', '-'), + 'a': environ.get('HTTP_USER_AGENT', '-'), + 'T': request_time.seconds, + 'D': (request_time.seconds * 1000000) + request_time.microseconds, + 'M': (request_time.seconds * 1000) + int(request_time.microseconds / 1000), + 'L': "%d.%06d" % (request_time.seconds, request_time.microseconds), + 'p': "<%s>" % os.getpid() + } + + # add request headers + if hasattr(req, 'headers'): + req_headers = req.headers + else: + req_headers = req + + if hasattr(req_headers, "items"): + req_headers = req_headers.items() + + atoms.update({"{%s}i" % k.lower(): v for k, v in req_headers}) + + resp_headers = resp.headers + if hasattr(resp_headers, "items"): + resp_headers = resp_headers.items() + + # add response headers + atoms.update({"{%s}o" % k.lower(): v for k, v in resp_headers}) + + # add environ variables + environ_variables = environ.items() + atoms.update({"{%s}e" % k.lower(): v for k, v in environ_variables}) + + return atoms + + def access(self, resp, req, environ, request_time): + """ See http://httpd.apache.org/docs/2.0/logs.html#combined + for format details + """ + + if not (self.cfg.accesslog or self.cfg.logconfig or + self.cfg.logconfig_dict or self.cfg.logconfig_json or + (self.cfg.syslog and not self.cfg.disable_redirect_access_to_syslog)): + return + + # wrap atoms: + # - make sure atoms will be test case insensitively + # - if atom doesn't exist replace it by '-' + safe_atoms = self.atoms_wrapper_class( + self.atoms(resp, req, environ, request_time) + ) + + try: + self.access_log.info(self.cfg.access_log_format, safe_atoms) + except Exception: + self.error(traceback.format_exc()) + + def now(self): + """ return date in Apache Common Log Format """ + return time.strftime('[%d/%b/%Y:%H:%M:%S %z]') + + def reopen_files(self): + if self.cfg.capture_output and self.cfg.errorlog != "-": + for stream in sys.stdout, sys.stderr: + stream.flush() + + with self.lock: + if self.logfile is not None: + self.logfile.close() + self.logfile = open(self.cfg.errorlog, 'a+') + os.dup2(self.logfile.fileno(), sys.stdout.fileno()) + os.dup2(self.logfile.fileno(), sys.stderr.fileno()) + + for log in loggers(): + for handler in log.handlers: + if isinstance(handler, logging.FileHandler): + handler.acquire() + try: + if handler.stream: + handler.close() + handler.stream = handler._open() + finally: + handler.release() + + def close_on_exec(self): + for log in loggers(): + for handler in log.handlers: + if isinstance(handler, logging.FileHandler): + handler.acquire() + try: + if handler.stream: + util.close_on_exec(handler.stream.fileno()) + finally: + handler.release() + + def _get_gunicorn_handler(self, log): + for h in log.handlers: + if getattr(h, "_gunicorn", False): + return h + + def _set_handler(self, log, output, fmt, stream=None): + # remove previous gunicorn log handler + h = self._get_gunicorn_handler(log) + if h: + log.handlers.remove(h) + + if output is not None: + if output == "-": + h = logging.StreamHandler(stream) + else: + util.check_is_writable(output) + h = logging.FileHandler(output) + # make sure the user can reopen the file + try: + os.chown(h.baseFilename, self.cfg.user, self.cfg.group) + except OSError: + # it's probably OK there, we assume the user has given + # /dev/null as a parameter. + pass + + h.setFormatter(fmt) + h._gunicorn = True + log.addHandler(h) + + def _set_syslog_handler(self, log, cfg, fmt, name): + # setup format + prefix = cfg.syslog_prefix or cfg.proc_name.replace(":", ".") + + prefix = "gunicorn.%s.%s" % (prefix, name) + + # set format + fmt = logging.Formatter(r"%s: %s" % (prefix, fmt)) + + # syslog facility + try: + facility = SYSLOG_FACILITIES[cfg.syslog_facility.lower()] + except KeyError: + raise RuntimeError("unknown facility name") + + # parse syslog address + socktype, addr = parse_syslog_address(cfg.syslog_addr) + + # finally setup the syslog handler + h = logging.handlers.SysLogHandler(address=addr, + facility=facility, socktype=socktype) + + h.setFormatter(fmt) + h._gunicorn = True + log.addHandler(h) + + def _get_user(self, environ): + user = None + http_auth = environ.get("HTTP_AUTHORIZATION") + if http_auth and http_auth.lower().startswith('basic'): + auth = http_auth.split(" ", 1) + if len(auth) == 2: + try: + # b64decode doesn't accept unicode in Python < 3.3 + # so we need to convert it to a byte string + auth = base64.b64decode(auth[1].strip().encode('utf-8')) + # b64decode returns a byte string + user = auth.split(b":", 1)[0].decode("UTF-8") + except (TypeError, binascii.Error, UnicodeDecodeError) as exc: + self.debug("Couldn't get username: %s", exc) + return user diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/http/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/http/__init__.py new file mode 100644 index 0000000..1da6f3e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/http/__init__.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +from gunicorn.http.message import Message, Request +from gunicorn.http.parser import RequestParser + +__all__ = ['Message', 'Request', 'RequestParser'] diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/http/body.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/http/body.py new file mode 100644 index 0000000..aa1af2c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/http/body.py @@ -0,0 +1,262 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +import io +import sys + +from gunicorn.http.errors import (NoMoreData, ChunkMissingTerminator, + InvalidChunkSize) + + +class ChunkedReader(object): + def __init__(self, req, unreader): + self.req = req + self.parser = self.parse_chunked(unreader) + self.buf = io.BytesIO() + + def read(self, size): + if not isinstance(size, int): + raise TypeError("size must be an integer type") + if size < 0: + raise ValueError("Size must be positive.") + if size == 0: + return b"" + + if self.parser: + while self.buf.tell() < size: + try: + self.buf.write(next(self.parser)) + except StopIteration: + self.parser = None + break + + data = self.buf.getvalue() + ret, rest = data[:size], data[size:] + self.buf = io.BytesIO() + self.buf.write(rest) + return ret + + def parse_trailers(self, unreader, data): + buf = io.BytesIO() + buf.write(data) + + idx = buf.getvalue().find(b"\r\n\r\n") + done = buf.getvalue()[:2] == b"\r\n" + while idx < 0 and not done: + self.get_data(unreader, buf) + idx = buf.getvalue().find(b"\r\n\r\n") + done = buf.getvalue()[:2] == b"\r\n" + if done: + unreader.unread(buf.getvalue()[2:]) + return b"" + self.req.trailers = self.req.parse_headers(buf.getvalue()[:idx]) + unreader.unread(buf.getvalue()[idx + 4:]) + + def parse_chunked(self, unreader): + (size, rest) = self.parse_chunk_size(unreader) + while size > 0: + while size > len(rest): + size -= len(rest) + yield rest + rest = unreader.read() + if not rest: + raise NoMoreData() + yield rest[:size] + # Remove \r\n after chunk + rest = rest[size:] + while len(rest) < 2: + rest += unreader.read() + if rest[:2] != b'\r\n': + raise ChunkMissingTerminator(rest[:2]) + (size, rest) = self.parse_chunk_size(unreader, data=rest[2:]) + + def parse_chunk_size(self, unreader, data=None): + buf = io.BytesIO() + if data is not None: + buf.write(data) + + idx = buf.getvalue().find(b"\r\n") + while idx < 0: + self.get_data(unreader, buf) + idx = buf.getvalue().find(b"\r\n") + + data = buf.getvalue() + line, rest_chunk = data[:idx], data[idx + 2:] + + chunk_size = line.split(b";", 1)[0].strip() + try: + chunk_size = int(chunk_size, 16) + except ValueError: + raise InvalidChunkSize(chunk_size) + + if chunk_size == 0: + try: + self.parse_trailers(unreader, rest_chunk) + except NoMoreData: + pass + return (0, None) + return (chunk_size, rest_chunk) + + def get_data(self, unreader, buf): + data = unreader.read() + if not data: + raise NoMoreData() + buf.write(data) + + +class LengthReader(object): + def __init__(self, unreader, length): + self.unreader = unreader + self.length = length + + def read(self, size): + if not isinstance(size, int): + raise TypeError("size must be an integral type") + + size = min(self.length, size) + if size < 0: + raise ValueError("Size must be positive.") + if size == 0: + return b"" + + buf = io.BytesIO() + data = self.unreader.read() + while data: + buf.write(data) + if buf.tell() >= size: + break + data = self.unreader.read() + + buf = buf.getvalue() + ret, rest = buf[:size], buf[size:] + self.unreader.unread(rest) + self.length -= size + return ret + + +class EOFReader(object): + def __init__(self, unreader): + self.unreader = unreader + self.buf = io.BytesIO() + self.finished = False + + def read(self, size): + if not isinstance(size, int): + raise TypeError("size must be an integral type") + if size < 0: + raise ValueError("Size must be positive.") + if size == 0: + return b"" + + if self.finished: + data = self.buf.getvalue() + ret, rest = data[:size], data[size:] + self.buf = io.BytesIO() + self.buf.write(rest) + return ret + + data = self.unreader.read() + while data: + self.buf.write(data) + if self.buf.tell() > size: + break + data = self.unreader.read() + + if not data: + self.finished = True + + data = self.buf.getvalue() + ret, rest = data[:size], data[size:] + self.buf = io.BytesIO() + self.buf.write(rest) + return ret + + +class Body(object): + def __init__(self, reader): + self.reader = reader + self.buf = io.BytesIO() + + def __iter__(self): + return self + + def __next__(self): + ret = self.readline() + if not ret: + raise StopIteration() + return ret + + next = __next__ + + def getsize(self, size): + if size is None: + return sys.maxsize + elif not isinstance(size, int): + raise TypeError("size must be an integral type") + elif size < 0: + return sys.maxsize + return size + + def read(self, size=None): + size = self.getsize(size) + if size == 0: + return b"" + + if size < self.buf.tell(): + data = self.buf.getvalue() + ret, rest = data[:size], data[size:] + self.buf = io.BytesIO() + self.buf.write(rest) + return ret + + while size > self.buf.tell(): + data = self.reader.read(1024) + if not data: + break + self.buf.write(data) + + data = self.buf.getvalue() + ret, rest = data[:size], data[size:] + self.buf = io.BytesIO() + self.buf.write(rest) + return ret + + def readline(self, size=None): + size = self.getsize(size) + if size == 0: + return b"" + + data = self.buf.getvalue() + self.buf = io.BytesIO() + + ret = [] + while 1: + idx = data.find(b"\n", 0, size) + idx = idx + 1 if idx >= 0 else size if len(data) >= size else 0 + if idx: + ret.append(data[:idx]) + self.buf.write(data[idx:]) + break + + ret.append(data) + size -= len(data) + data = self.reader.read(min(1024, size)) + if not data: + break + + return b"".join(ret) + + def readlines(self, size=None): + ret = [] + data = self.read() + while data: + pos = data.find(b"\n") + if pos < 0: + ret.append(data) + data = b"" + else: + line, data = data[:pos + 1], data[pos + 1:] + ret.append(line) + return ret diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/http/errors.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/http/errors.py new file mode 100644 index 0000000..7839ef0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/http/errors.py @@ -0,0 +1,120 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +# We don't need to call super() in __init__ methods of our +# BaseException and Exception classes because we also define +# our own __str__ methods so there is no need to pass 'message' +# to the base class to get a meaningful output from 'str(exc)'. +# pylint: disable=super-init-not-called + + +class ParseException(Exception): + pass + + +class NoMoreData(IOError): + def __init__(self, buf=None): + self.buf = buf + + def __str__(self): + return "No more data after: %r" % self.buf + + +class InvalidRequestLine(ParseException): + def __init__(self, req): + self.req = req + self.code = 400 + + def __str__(self): + return "Invalid HTTP request line: %r" % self.req + + +class InvalidRequestMethod(ParseException): + def __init__(self, method): + self.method = method + + def __str__(self): + return "Invalid HTTP method: %r" % self.method + + +class InvalidHTTPVersion(ParseException): + def __init__(self, version): + self.version = version + + def __str__(self): + return "Invalid HTTP Version: %r" % self.version + + +class InvalidHeader(ParseException): + def __init__(self, hdr, req=None): + self.hdr = hdr + self.req = req + + def __str__(self): + return "Invalid HTTP Header: %r" % self.hdr + + +class InvalidHeaderName(ParseException): + def __init__(self, hdr): + self.hdr = hdr + + def __str__(self): + return "Invalid HTTP header name: %r" % self.hdr + + +class InvalidChunkSize(IOError): + def __init__(self, data): + self.data = data + + def __str__(self): + return "Invalid chunk size: %r" % self.data + + +class ChunkMissingTerminator(IOError): + def __init__(self, term): + self.term = term + + def __str__(self): + return "Invalid chunk terminator is not '\\r\\n': %r" % self.term + + +class LimitRequestLine(ParseException): + def __init__(self, size, max_size): + self.size = size + self.max_size = max_size + + def __str__(self): + return "Request Line is too large (%s > %s)" % (self.size, self.max_size) + + +class LimitRequestHeaders(ParseException): + def __init__(self, msg): + self.msg = msg + + def __str__(self): + return self.msg + + +class InvalidProxyLine(ParseException): + def __init__(self, line): + self.line = line + self.code = 400 + + def __str__(self): + return "Invalid PROXY line: %r" % self.line + + +class ForbiddenProxyRequest(ParseException): + def __init__(self, host): + self.host = host + self.code = 403 + + def __str__(self): + return "Proxy request from %r not allowed" % self.host + + +class InvalidSchemeHeaders(ParseException): + def __str__(self): + return "Contradictory scheme headers" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/http/message.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/http/message.py new file mode 100644 index 0000000..1f93c71 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/http/message.py @@ -0,0 +1,360 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +import io +import re +import socket + +from gunicorn.http.body import ChunkedReader, LengthReader, EOFReader, Body +from gunicorn.http.errors import ( + InvalidHeader, InvalidHeaderName, NoMoreData, + InvalidRequestLine, InvalidRequestMethod, InvalidHTTPVersion, + LimitRequestLine, LimitRequestHeaders, +) +from gunicorn.http.errors import InvalidProxyLine, ForbiddenProxyRequest +from gunicorn.http.errors import InvalidSchemeHeaders +from gunicorn.util import bytes_to_str, split_request_uri + +MAX_REQUEST_LINE = 8190 +MAX_HEADERS = 32768 +DEFAULT_MAX_HEADERFIELD_SIZE = 8190 + +HEADER_RE = re.compile(r"[\x00-\x1F\x7F()<>@,;:\[\]={} \t\\\"]") +METH_RE = re.compile(r"[A-Z0-9$-_.]{3,20}") +VERSION_RE = re.compile(r"HTTP/(\d+)\.(\d+)") + + +class Message(object): + def __init__(self, cfg, unreader, peer_addr): + self.cfg = cfg + self.unreader = unreader + self.peer_addr = peer_addr + self.remote_addr = peer_addr + self.version = None + self.headers = [] + self.trailers = [] + self.body = None + self.scheme = "https" if cfg.is_ssl else "http" + + # set headers limits + self.limit_request_fields = cfg.limit_request_fields + if (self.limit_request_fields <= 0 + or self.limit_request_fields > MAX_HEADERS): + self.limit_request_fields = MAX_HEADERS + self.limit_request_field_size = cfg.limit_request_field_size + if self.limit_request_field_size < 0: + self.limit_request_field_size = DEFAULT_MAX_HEADERFIELD_SIZE + + # set max header buffer size + max_header_field_size = self.limit_request_field_size or DEFAULT_MAX_HEADERFIELD_SIZE + self.max_buffer_headers = self.limit_request_fields * \ + (max_header_field_size + 2) + 4 + + unused = self.parse(self.unreader) + self.unreader.unread(unused) + self.set_body_reader() + + def parse(self, unreader): + raise NotImplementedError() + + def parse_headers(self, data): + cfg = self.cfg + headers = [] + + # Split lines on \r\n keeping the \r\n on each line + lines = [bytes_to_str(line) + "\r\n" for line in data.split(b"\r\n")] + + # handle scheme headers + scheme_header = False + secure_scheme_headers = {} + if ('*' in cfg.forwarded_allow_ips or + not isinstance(self.peer_addr, tuple) + or self.peer_addr[0] in cfg.forwarded_allow_ips): + secure_scheme_headers = cfg.secure_scheme_headers + + # Parse headers into key/value pairs paying attention + # to continuation lines. + while lines: + if len(headers) >= self.limit_request_fields: + raise LimitRequestHeaders("limit request headers fields") + + # Parse initial header name : value pair. + curr = lines.pop(0) + header_length = len(curr) + if curr.find(":") < 0: + raise InvalidHeader(curr.strip()) + name, value = curr.split(":", 1) + if self.cfg.strip_header_spaces: + name = name.rstrip(" \t").upper() + else: + name = name.upper() + if HEADER_RE.search(name): + raise InvalidHeaderName(name) + + name, value = name.strip(), [value.lstrip()] + + # Consume value continuation lines + while lines and lines[0].startswith((" ", "\t")): + curr = lines.pop(0) + header_length += len(curr) + if header_length > self.limit_request_field_size > 0: + raise LimitRequestHeaders("limit request headers " + "fields size") + value.append(curr) + value = ''.join(value).rstrip() + + if header_length > self.limit_request_field_size > 0: + raise LimitRequestHeaders("limit request headers fields size") + + if name in secure_scheme_headers: + secure = value == secure_scheme_headers[name] + scheme = "https" if secure else "http" + if scheme_header: + if scheme != self.scheme: + raise InvalidSchemeHeaders() + else: + scheme_header = True + self.scheme = scheme + + headers.append((name, value)) + + return headers + + def set_body_reader(self): + chunked = False + content_length = None + + for (name, value) in self.headers: + if name == "CONTENT-LENGTH": + if content_length is not None: + raise InvalidHeader("CONTENT-LENGTH", req=self) + content_length = value + elif name == "TRANSFER-ENCODING": + if value.lower() == "chunked": + chunked = True + + if chunked: + self.body = Body(ChunkedReader(self, self.unreader)) + elif content_length is not None: + try: + if str(content_length).isnumeric(): + content_length = int(content_length) + else: + raise InvalidHeader("CONTENT-LENGTH", req=self) + except ValueError: + raise InvalidHeader("CONTENT-LENGTH", req=self) + + if content_length < 0: + raise InvalidHeader("CONTENT-LENGTH", req=self) + + self.body = Body(LengthReader(self.unreader, content_length)) + else: + self.body = Body(EOFReader(self.unreader)) + + def should_close(self): + for (h, v) in self.headers: + if h == "CONNECTION": + v = v.lower().strip() + if v == "close": + return True + elif v == "keep-alive": + return False + break + return self.version <= (1, 0) + + +class Request(Message): + def __init__(self, cfg, unreader, peer_addr, req_number=1): + self.method = None + self.uri = None + self.path = None + self.query = None + self.fragment = None + + # get max request line size + self.limit_request_line = cfg.limit_request_line + if (self.limit_request_line < 0 + or self.limit_request_line >= MAX_REQUEST_LINE): + self.limit_request_line = MAX_REQUEST_LINE + + self.req_number = req_number + self.proxy_protocol_info = None + super().__init__(cfg, unreader, peer_addr) + + def get_data(self, unreader, buf, stop=False): + data = unreader.read() + if not data: + if stop: + raise StopIteration() + raise NoMoreData(buf.getvalue()) + buf.write(data) + + def parse(self, unreader): + buf = io.BytesIO() + self.get_data(unreader, buf, stop=True) + + # get request line + line, rbuf = self.read_line(unreader, buf, self.limit_request_line) + + # proxy protocol + if self.proxy_protocol(bytes_to_str(line)): + # get next request line + buf = io.BytesIO() + buf.write(rbuf) + line, rbuf = self.read_line(unreader, buf, self.limit_request_line) + + self.parse_request_line(line) + buf = io.BytesIO() + buf.write(rbuf) + + # Headers + data = buf.getvalue() + idx = data.find(b"\r\n\r\n") + + done = data[:2] == b"\r\n" + while True: + idx = data.find(b"\r\n\r\n") + done = data[:2] == b"\r\n" + + if idx < 0 and not done: + self.get_data(unreader, buf) + data = buf.getvalue() + if len(data) > self.max_buffer_headers: + raise LimitRequestHeaders("max buffer headers") + else: + break + + if done: + self.unreader.unread(data[2:]) + return b"" + + self.headers = self.parse_headers(data[:idx]) + + ret = data[idx + 4:] + buf = None + return ret + + def read_line(self, unreader, buf, limit=0): + data = buf.getvalue() + + while True: + idx = data.find(b"\r\n") + if idx >= 0: + # check if the request line is too large + if idx > limit > 0: + raise LimitRequestLine(idx, limit) + break + if len(data) - 2 > limit > 0: + raise LimitRequestLine(len(data), limit) + self.get_data(unreader, buf) + data = buf.getvalue() + + return (data[:idx], # request line, + data[idx + 2:]) # residue in the buffer, skip \r\n + + def proxy_protocol(self, line): + """\ + Detect, check and parse proxy protocol. + + :raises: ForbiddenProxyRequest, InvalidProxyLine. + :return: True for proxy protocol line else False + """ + if not self.cfg.proxy_protocol: + return False + + if self.req_number != 1: + return False + + if not line.startswith("PROXY"): + return False + + self.proxy_protocol_access_check() + self.parse_proxy_protocol(line) + + return True + + def proxy_protocol_access_check(self): + # check in allow list + if ("*" not in self.cfg.proxy_allow_ips and + isinstance(self.peer_addr, tuple) and + self.peer_addr[0] not in self.cfg.proxy_allow_ips): + raise ForbiddenProxyRequest(self.peer_addr[0]) + + def parse_proxy_protocol(self, line): + bits = line.split() + + if len(bits) != 6: + raise InvalidProxyLine(line) + + # Extract data + proto = bits[1] + s_addr = bits[2] + d_addr = bits[3] + + # Validation + if proto not in ["TCP4", "TCP6"]: + raise InvalidProxyLine("protocol '%s' not supported" % proto) + if proto == "TCP4": + try: + socket.inet_pton(socket.AF_INET, s_addr) + socket.inet_pton(socket.AF_INET, d_addr) + except socket.error: + raise InvalidProxyLine(line) + elif proto == "TCP6": + try: + socket.inet_pton(socket.AF_INET6, s_addr) + socket.inet_pton(socket.AF_INET6, d_addr) + except socket.error: + raise InvalidProxyLine(line) + + try: + s_port = int(bits[4]) + d_port = int(bits[5]) + except ValueError: + raise InvalidProxyLine("invalid port %s" % line) + + if not ((0 <= s_port <= 65535) and (0 <= d_port <= 65535)): + raise InvalidProxyLine("invalid port %s" % line) + + # Set data + self.proxy_protocol_info = { + "proxy_protocol": proto, + "client_addr": s_addr, + "client_port": s_port, + "proxy_addr": d_addr, + "proxy_port": d_port + } + + def parse_request_line(self, line_bytes): + bits = [bytes_to_str(bit) for bit in line_bytes.split(None, 2)] + if len(bits) != 3: + raise InvalidRequestLine(bytes_to_str(line_bytes)) + + # Method + if not METH_RE.match(bits[0]): + raise InvalidRequestMethod(bits[0]) + self.method = bits[0].upper() + + # URI + self.uri = bits[1] + + try: + parts = split_request_uri(self.uri) + except ValueError: + raise InvalidRequestLine(bytes_to_str(line_bytes)) + self.path = parts.path or "" + self.query = parts.query or "" + self.fragment = parts.fragment or "" + + # Version + match = VERSION_RE.match(bits[2]) + if match is None: + raise InvalidHTTPVersion(bits[2]) + self.version = (int(match.group(1)), int(match.group(2))) + + def set_body_reader(self): + super().set_body_reader() + if isinstance(self.body.reader, EOFReader): + self.body = Body(LengthReader(self.unreader, 0)) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/http/parser.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/http/parser.py new file mode 100644 index 0000000..5d689f0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/http/parser.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +from gunicorn.http.message import Request +from gunicorn.http.unreader import SocketUnreader, IterUnreader + + +class Parser(object): + + mesg_class = None + + def __init__(self, cfg, source, source_addr): + self.cfg = cfg + if hasattr(source, "recv"): + self.unreader = SocketUnreader(source) + else: + self.unreader = IterUnreader(source) + self.mesg = None + self.source_addr = source_addr + + # request counter (for keepalive connetions) + self.req_count = 0 + + def __iter__(self): + return self + + def __next__(self): + # Stop if HTTP dictates a stop. + if self.mesg and self.mesg.should_close(): + raise StopIteration() + + # Discard any unread body of the previous message + if self.mesg: + data = self.mesg.body.read(8192) + while data: + data = self.mesg.body.read(8192) + + # Parse the next request + self.req_count += 1 + self.mesg = self.mesg_class(self.cfg, self.unreader, self.source_addr, self.req_count) + if not self.mesg: + raise StopIteration() + return self.mesg + + next = __next__ + + +class RequestParser(Parser): + + mesg_class = Request diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/http/unreader.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/http/unreader.py new file mode 100644 index 0000000..273bfc3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/http/unreader.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +import io +import os + +# Classes that can undo reading data from +# a given type of data source. + + +class Unreader(object): + def __init__(self): + self.buf = io.BytesIO() + + def chunk(self): + raise NotImplementedError() + + def read(self, size=None): + if size is not None and not isinstance(size, int): + raise TypeError("size parameter must be an int or long.") + + if size is not None: + if size == 0: + return b"" + if size < 0: + size = None + + self.buf.seek(0, os.SEEK_END) + + if size is None and self.buf.tell(): + ret = self.buf.getvalue() + self.buf = io.BytesIO() + return ret + if size is None: + d = self.chunk() + return d + + while self.buf.tell() < size: + chunk = self.chunk() + if not chunk: + ret = self.buf.getvalue() + self.buf = io.BytesIO() + return ret + self.buf.write(chunk) + data = self.buf.getvalue() + self.buf = io.BytesIO() + self.buf.write(data[size:]) + return data[:size] + + def unread(self, data): + self.buf.seek(0, os.SEEK_END) + self.buf.write(data) + + +class SocketUnreader(Unreader): + def __init__(self, sock, max_chunk=8192): + super().__init__() + self.sock = sock + self.mxchunk = max_chunk + + def chunk(self): + return self.sock.recv(self.mxchunk) + + +class IterUnreader(Unreader): + def __init__(self, iterable): + super().__init__() + self.iter = iter(iterable) + + def chunk(self): + if not self.iter: + return b"" + try: + return next(self.iter) + except StopIteration: + self.iter = None + return b"" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/http/wsgi.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/http/wsgi.py new file mode 100644 index 0000000..25715ea --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/http/wsgi.py @@ -0,0 +1,393 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +import io +import logging +import os +import re +import sys + +from gunicorn.http.message import HEADER_RE +from gunicorn.http.errors import InvalidHeader, InvalidHeaderName +from gunicorn import SERVER_SOFTWARE, SERVER +from gunicorn import util + +# Send files in at most 1GB blocks as some operating systems can have problems +# with sending files in blocks over 2GB. +BLKSIZE = 0x3FFFFFFF + +HEADER_VALUE_RE = re.compile(r'[\x00-\x1F\x7F]') + +log = logging.getLogger(__name__) + + +class FileWrapper(object): + + def __init__(self, filelike, blksize=8192): + self.filelike = filelike + self.blksize = blksize + if hasattr(filelike, 'close'): + self.close = filelike.close + + def __getitem__(self, key): + data = self.filelike.read(self.blksize) + if data: + return data + raise IndexError + + +class WSGIErrorsWrapper(io.RawIOBase): + + def __init__(self, cfg): + # There is no public __init__ method for RawIOBase so + # we don't need to call super() in the __init__ method. + # pylint: disable=super-init-not-called + errorlog = logging.getLogger("gunicorn.error") + handlers = errorlog.handlers + self.streams = [] + + if cfg.errorlog == "-": + self.streams.append(sys.stderr) + handlers = handlers[1:] + + for h in handlers: + if hasattr(h, "stream"): + self.streams.append(h.stream) + + def write(self, data): + for stream in self.streams: + try: + stream.write(data) + except UnicodeError: + stream.write(data.encode("UTF-8")) + stream.flush() + + +def base_environ(cfg): + return { + "wsgi.errors": WSGIErrorsWrapper(cfg), + "wsgi.version": (1, 0), + "wsgi.multithread": False, + "wsgi.multiprocess": (cfg.workers > 1), + "wsgi.run_once": False, + "wsgi.file_wrapper": FileWrapper, + "wsgi.input_terminated": True, + "SERVER_SOFTWARE": SERVER_SOFTWARE, + } + + +def default_environ(req, sock, cfg): + env = base_environ(cfg) + env.update({ + "wsgi.input": req.body, + "gunicorn.socket": sock, + "REQUEST_METHOD": req.method, + "QUERY_STRING": req.query, + "RAW_URI": req.uri, + "SERVER_PROTOCOL": "HTTP/%s" % ".".join([str(v) for v in req.version]) + }) + return env + + +def proxy_environ(req): + info = req.proxy_protocol_info + + if not info: + return {} + + return { + "PROXY_PROTOCOL": info["proxy_protocol"], + "REMOTE_ADDR": info["client_addr"], + "REMOTE_PORT": str(info["client_port"]), + "PROXY_ADDR": info["proxy_addr"], + "PROXY_PORT": str(info["proxy_port"]), + } + + +def create(req, sock, client, server, cfg): + resp = Response(req, sock, cfg) + + # set initial environ + environ = default_environ(req, sock, cfg) + + # default variables + host = None + script_name = os.environ.get("SCRIPT_NAME", "") + + # add the headers to the environ + for hdr_name, hdr_value in req.headers: + if hdr_name == "EXPECT": + # handle expect + if hdr_value.lower() == "100-continue": + sock.send(b"HTTP/1.1 100 Continue\r\n\r\n") + elif hdr_name == 'HOST': + host = hdr_value + elif hdr_name == "SCRIPT_NAME": + script_name = hdr_value + elif hdr_name == "CONTENT-TYPE": + environ['CONTENT_TYPE'] = hdr_value + continue + elif hdr_name == "CONTENT-LENGTH": + environ['CONTENT_LENGTH'] = hdr_value + continue + + key = 'HTTP_' + hdr_name.replace('-', '_') + if key in environ: + hdr_value = "%s,%s" % (environ[key], hdr_value) + environ[key] = hdr_value + + # set the url scheme + environ['wsgi.url_scheme'] = req.scheme + + # set the REMOTE_* keys in environ + # authors should be aware that REMOTE_HOST and REMOTE_ADDR + # may not qualify the remote addr: + # http://www.ietf.org/rfc/rfc3875 + if isinstance(client, str): + environ['REMOTE_ADDR'] = client + elif isinstance(client, bytes): + environ['REMOTE_ADDR'] = client.decode() + else: + environ['REMOTE_ADDR'] = client[0] + environ['REMOTE_PORT'] = str(client[1]) + + # handle the SERVER_* + # Normally only the application should use the Host header but since the + # WSGI spec doesn't support unix sockets, we are using it to create + # viable SERVER_* if possible. + if isinstance(server, str): + server = server.split(":") + if len(server) == 1: + # unix socket + if host: + server = host.split(':') + if len(server) == 1: + if req.scheme == "http": + server.append(80) + elif req.scheme == "https": + server.append(443) + else: + server.append('') + else: + # no host header given which means that we are not behind a + # proxy, so append an empty port. + server.append('') + environ['SERVER_NAME'] = server[0] + environ['SERVER_PORT'] = str(server[1]) + + # set the path and script name + path_info = req.path + if script_name: + path_info = path_info.split(script_name, 1)[1] + environ['PATH_INFO'] = util.unquote_to_wsgi_str(path_info) + environ['SCRIPT_NAME'] = script_name + + # override the environ with the correct remote and server address if + # we are behind a proxy using the proxy protocol. + environ.update(proxy_environ(req)) + return resp, environ + + +class Response(object): + + def __init__(self, req, sock, cfg): + self.req = req + self.sock = sock + self.version = SERVER + self.status = None + self.chunked = False + self.must_close = False + self.headers = [] + self.headers_sent = False + self.response_length = None + self.sent = 0 + self.upgrade = False + self.cfg = cfg + + def force_close(self): + self.must_close = True + + def should_close(self): + if self.must_close or self.req.should_close(): + return True + if self.response_length is not None or self.chunked: + return False + if self.req.method == 'HEAD': + return False + if self.status_code < 200 or self.status_code in (204, 304): + return False + return True + + def start_response(self, status, headers, exc_info=None): + if exc_info: + try: + if self.status and self.headers_sent: + util.reraise(exc_info[0], exc_info[1], exc_info[2]) + finally: + exc_info = None + elif self.status is not None: + raise AssertionError("Response headers already set!") + + self.status = status + + # get the status code from the response here so we can use it to check + # the need for the connection header later without parsing the string + # each time. + try: + self.status_code = int(self.status.split()[0]) + except ValueError: + self.status_code = None + + self.process_headers(headers) + self.chunked = self.is_chunked() + return self.write + + def process_headers(self, headers): + for name, value in headers: + if not isinstance(name, str): + raise TypeError('%r is not a string' % name) + + if HEADER_RE.search(name): + raise InvalidHeaderName('%r' % name) + + if not isinstance(value, str): + raise TypeError('%r is not a string' % value) + + if HEADER_VALUE_RE.search(value): + raise InvalidHeader('%r' % value) + + value = value.strip() + lname = name.lower().strip() + if lname == "content-length": + self.response_length = int(value) + elif util.is_hoppish(name): + if lname == "connection": + # handle websocket + if value.lower().strip() == "upgrade": + self.upgrade = True + elif lname == "upgrade": + if value.lower().strip() == "websocket": + self.headers.append((name.strip(), value)) + + # ignore hopbyhop headers + continue + self.headers.append((name.strip(), value)) + + def is_chunked(self): + # Only use chunked responses when the client is + # speaking HTTP/1.1 or newer and there was + # no Content-Length header set. + if self.response_length is not None: + return False + elif self.req.version <= (1, 0): + return False + elif self.req.method == 'HEAD': + # Responses to a HEAD request MUST NOT contain a response body. + return False + elif self.status_code in (204, 304): + # Do not use chunked responses when the response is guaranteed to + # not have a response body. + return False + return True + + def default_headers(self): + # set the connection header + if self.upgrade: + connection = "upgrade" + elif self.should_close(): + connection = "close" + else: + connection = "keep-alive" + + headers = [ + "HTTP/%s.%s %s\r\n" % (self.req.version[0], + self.req.version[1], self.status), + "Server: %s\r\n" % self.version, + "Date: %s\r\n" % util.http_date(), + "Connection: %s\r\n" % connection + ] + if self.chunked: + headers.append("Transfer-Encoding: chunked\r\n") + return headers + + def send_headers(self): + if self.headers_sent: + return + tosend = self.default_headers() + tosend.extend(["%s: %s\r\n" % (k, v) for k, v in self.headers]) + + header_str = "%s\r\n" % "".join(tosend) + util.write(self.sock, util.to_bytestring(header_str, "latin-1")) + self.headers_sent = True + + def write(self, arg): + self.send_headers() + if not isinstance(arg, bytes): + raise TypeError('%r is not a byte' % arg) + arglen = len(arg) + tosend = arglen + if self.response_length is not None: + if self.sent >= self.response_length: + # Never write more than self.response_length bytes + return + + tosend = min(self.response_length - self.sent, tosend) + if tosend < arglen: + arg = arg[:tosend] + + # Sending an empty chunk signals the end of the + # response and prematurely closes the response + if self.chunked and tosend == 0: + return + + self.sent += tosend + util.write(self.sock, arg, self.chunked) + + def can_sendfile(self): + return self.cfg.sendfile is not False + + def sendfile(self, respiter): + if self.cfg.is_ssl or not self.can_sendfile(): + return False + + if not util.has_fileno(respiter.filelike): + return False + + fileno = respiter.filelike.fileno() + try: + offset = os.lseek(fileno, 0, os.SEEK_CUR) + if self.response_length is None: + filesize = os.fstat(fileno).st_size + nbytes = filesize - offset + else: + nbytes = self.response_length + except (OSError, io.UnsupportedOperation): + return False + + self.send_headers() + + if self.is_chunked(): + chunk_size = "%X\r\n" % nbytes + self.sock.sendall(chunk_size.encode('utf-8')) + if nbytes > 0: + self.sock.sendfile(respiter.filelike, offset=offset, count=nbytes) + + if self.is_chunked(): + self.sock.sendall(b"\r\n") + + os.lseek(fileno, offset, os.SEEK_SET) + + return True + + def write_file(self, respiter): + if not self.sendfile(respiter): + for item in respiter: + self.write(item) + + def close(self): + if not self.headers_sent: + self.send_headers() + if self.chunked: + util.write_chunk(self.sock, b"") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/instrument/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/instrument/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/instrument/statsd.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/instrument/statsd.py new file mode 100644 index 0000000..2c54b2e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/instrument/statsd.py @@ -0,0 +1,133 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +"Bare-bones implementation of statsD's protocol, client-side" + +import logging +import socket +from re import sub + +from gunicorn.glogging import Logger + +# Instrumentation constants +METRIC_VAR = "metric" +VALUE_VAR = "value" +MTYPE_VAR = "mtype" +GAUGE_TYPE = "gauge" +COUNTER_TYPE = "counter" +HISTOGRAM_TYPE = "histogram" + + +class Statsd(Logger): + """statsD-based instrumentation, that passes as a logger + """ + def __init__(self, cfg): + Logger.__init__(self, cfg) + self.prefix = sub(r"^(.+[^.]+)\.*$", "\\g<1>.", cfg.statsd_prefix) + + if isinstance(cfg.statsd_host, str): + address_family = socket.AF_UNIX + else: + address_family = socket.AF_INET + + try: + self.sock = socket.socket(address_family, socket.SOCK_DGRAM) + self.sock.connect(cfg.statsd_host) + except Exception: + self.sock = None + + self.dogstatsd_tags = cfg.dogstatsd_tags + + # Log errors and warnings + def critical(self, msg, *args, **kwargs): + Logger.critical(self, msg, *args, **kwargs) + self.increment("gunicorn.log.critical", 1) + + def error(self, msg, *args, **kwargs): + Logger.error(self, msg, *args, **kwargs) + self.increment("gunicorn.log.error", 1) + + def warning(self, msg, *args, **kwargs): + Logger.warning(self, msg, *args, **kwargs) + self.increment("gunicorn.log.warning", 1) + + def exception(self, msg, *args, **kwargs): + Logger.exception(self, msg, *args, **kwargs) + self.increment("gunicorn.log.exception", 1) + + # Special treatment for info, the most common log level + def info(self, msg, *args, **kwargs): + self.log(logging.INFO, msg, *args, **kwargs) + + # skip the run-of-the-mill logs + def debug(self, msg, *args, **kwargs): + self.log(logging.DEBUG, msg, *args, **kwargs) + + def log(self, lvl, msg, *args, **kwargs): + """Log a given statistic if metric, value and type are present + """ + try: + extra = kwargs.get("extra", None) + if extra is not None: + metric = extra.get(METRIC_VAR, None) + value = extra.get(VALUE_VAR, None) + typ = extra.get(MTYPE_VAR, None) + if metric and value and typ: + if typ == GAUGE_TYPE: + self.gauge(metric, value) + elif typ == COUNTER_TYPE: + self.increment(metric, value) + elif typ == HISTOGRAM_TYPE: + self.histogram(metric, value) + else: + pass + + # Log to parent logger only if there is something to say + if msg: + Logger.log(self, lvl, msg, *args, **kwargs) + except Exception: + Logger.warning(self, "Failed to log to statsd", exc_info=True) + + # access logging + def access(self, resp, req, environ, request_time): + """Measure request duration + request_time is a datetime.timedelta + """ + Logger.access(self, resp, req, environ, request_time) + duration_in_ms = request_time.seconds * 1000 + float(request_time.microseconds) / 10 ** 3 + status = resp.status + if isinstance(status, str): + status = int(status.split(None, 1)[0]) + self.histogram("gunicorn.request.duration", duration_in_ms) + self.increment("gunicorn.requests", 1) + self.increment("gunicorn.request.status.%d" % status, 1) + + # statsD methods + # you can use those directly if you want + def gauge(self, name, value): + self._sock_send("{0}{1}:{2}|g".format(self.prefix, name, value)) + + def increment(self, name, value, sampling_rate=1.0): + self._sock_send("{0}{1}:{2}|c|@{3}".format(self.prefix, name, value, sampling_rate)) + + def decrement(self, name, value, sampling_rate=1.0): + self._sock_send("{0}{1}:-{2}|c|@{3}".format(self.prefix, name, value, sampling_rate)) + + def histogram(self, name, value): + self._sock_send("{0}{1}:{2}|ms".format(self.prefix, name, value)) + + def _sock_send(self, msg): + try: + if isinstance(msg, str): + msg = msg.encode("ascii") + + # http://docs.datadoghq.com/guides/dogstatsd/#datagram-format + if self.dogstatsd_tags: + msg = msg + b"|#" + self.dogstatsd_tags.encode('ascii') + + if self.sock: + self.sock.send(msg) + except Exception: + Logger.warning(self, "Error sending message to statsd", exc_info=True) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/pidfile.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/pidfile.py new file mode 100644 index 0000000..585b02a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/pidfile.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +import errno +import os +import tempfile + + +class Pidfile(object): + """\ + Manage a PID file. If a specific name is provided + it and '"%s.oldpid" % name' will be used. Otherwise + we create a temp file using os.mkstemp. + """ + + def __init__(self, fname): + self.fname = fname + self.pid = None + + def create(self, pid): + oldpid = self.validate() + if oldpid: + if oldpid == os.getpid(): + return + msg = "Already running on PID %s (or pid file '%s' is stale)" + raise RuntimeError(msg % (oldpid, self.fname)) + + self.pid = pid + + # Write pidfile + fdir = os.path.dirname(self.fname) + if fdir and not os.path.isdir(fdir): + raise RuntimeError("%s doesn't exist. Can't create pidfile." % fdir) + fd, fname = tempfile.mkstemp(dir=fdir) + os.write(fd, ("%s\n" % self.pid).encode('utf-8')) + if self.fname: + os.rename(fname, self.fname) + else: + self.fname = fname + os.close(fd) + + # set permissions to -rw-r--r-- + os.chmod(self.fname, 420) + + def rename(self, path): + self.unlink() + self.fname = path + self.create(self.pid) + + def unlink(self): + """ delete pidfile""" + try: + with open(self.fname, "r") as f: + pid1 = int(f.read() or 0) + + if pid1 == self.pid: + os.unlink(self.fname) + except Exception: + pass + + def validate(self): + """ Validate pidfile and make it stale if needed""" + if not self.fname: + return + try: + with open(self.fname, "r") as f: + try: + wpid = int(f.read()) + except ValueError: + return + + try: + os.kill(wpid, 0) + return wpid + except OSError as e: + if e.args[0] == errno.EPERM: + return wpid + if e.args[0] == errno.ESRCH: + return + raise + except IOError as e: + if e.args[0] == errno.ENOENT: + return + raise diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/reloader.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/reloader.py new file mode 100644 index 0000000..88b540b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/reloader.py @@ -0,0 +1,132 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. +# pylint: disable=no-else-continue + +import os +import os.path +import re +import sys +import time +import threading + +COMPILED_EXT_RE = re.compile(r'py[co]$') + + +class Reloader(threading.Thread): + def __init__(self, extra_files=None, interval=1, callback=None): + super().__init__() + self.daemon = True + self._extra_files = set(extra_files or ()) + self._interval = interval + self._callback = callback + + def add_extra_file(self, filename): + self._extra_files.add(filename) + + def get_files(self): + fnames = [ + COMPILED_EXT_RE.sub('py', module.__file__) + for module in tuple(sys.modules.values()) + if getattr(module, '__file__', None) + ] + + fnames.extend(self._extra_files) + + return fnames + + def run(self): + mtimes = {} + while True: + for filename in self.get_files(): + try: + mtime = os.stat(filename).st_mtime + except OSError: + continue + old_time = mtimes.get(filename) + if old_time is None: + mtimes[filename] = mtime + continue + elif mtime > old_time: + if self._callback: + self._callback(filename) + time.sleep(self._interval) + + +has_inotify = False +if sys.platform.startswith('linux'): + try: + from inotify.adapters import Inotify + import inotify.constants + has_inotify = True + except ImportError: + pass + + +if has_inotify: + + class InotifyReloader(threading.Thread): + event_mask = (inotify.constants.IN_CREATE | inotify.constants.IN_DELETE + | inotify.constants.IN_DELETE_SELF | inotify.constants.IN_MODIFY + | inotify.constants.IN_MOVE_SELF | inotify.constants.IN_MOVED_FROM + | inotify.constants.IN_MOVED_TO) + + def __init__(self, extra_files=None, callback=None): + super().__init__() + self.daemon = True + self._callback = callback + self._dirs = set() + self._watcher = Inotify() + + for extra_file in extra_files: + self.add_extra_file(extra_file) + + def add_extra_file(self, filename): + dirname = os.path.dirname(filename) + + if dirname in self._dirs: + return + + self._watcher.add_watch(dirname, mask=self.event_mask) + self._dirs.add(dirname) + + def get_dirs(self): + fnames = [ + os.path.dirname(os.path.abspath(COMPILED_EXT_RE.sub('py', module.__file__))) + for module in tuple(sys.modules.values()) + if getattr(module, '__file__', None) + ] + + return set(fnames) + + def run(self): + self._dirs = self.get_dirs() + + for dirname in self._dirs: + if os.path.isdir(dirname): + self._watcher.add_watch(dirname, mask=self.event_mask) + + for event in self._watcher.event_gen(): + if event is None: + continue + + filename = event[3] + + self._callback(filename) + +else: + + class InotifyReloader(object): + def __init__(self, extra_files=None, callback=None): + raise ImportError('You must have the inotify module installed to ' + 'use the inotify reloader') + + +preferred_reloader = InotifyReloader if has_inotify else Reloader + +reloader_engines = { + 'auto': preferred_reloader, + 'poll': Reloader, + 'inotify': InotifyReloader, +} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/sock.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/sock.py new file mode 100644 index 0000000..7700146 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/sock.py @@ -0,0 +1,232 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +import errno +import os +import socket +import ssl +import stat +import sys +import time + +from gunicorn import util + + +class BaseSocket(object): + + def __init__(self, address, conf, log, fd=None): + self.log = log + self.conf = conf + + self.cfg_addr = address + if fd is None: + sock = socket.socket(self.FAMILY, socket.SOCK_STREAM) + bound = False + else: + sock = socket.fromfd(fd, self.FAMILY, socket.SOCK_STREAM) + os.close(fd) + bound = True + + self.sock = self.set_options(sock, bound=bound) + + def __str__(self): + return "" % self.sock.fileno() + + def __getattr__(self, name): + return getattr(self.sock, name) + + def set_options(self, sock, bound=False): + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + if (self.conf.reuse_port + and hasattr(socket, 'SO_REUSEPORT')): # pragma: no cover + try: + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) + except socket.error as err: + if err.errno not in (errno.ENOPROTOOPT, errno.EINVAL): + raise + if not bound: + self.bind(sock) + sock.setblocking(0) + + # make sure that the socket can be inherited + if hasattr(sock, "set_inheritable"): + sock.set_inheritable(True) + + sock.listen(self.conf.backlog) + return sock + + def bind(self, sock): + sock.bind(self.cfg_addr) + + def close(self): + if self.sock is None: + return + + try: + self.sock.close() + except socket.error as e: + self.log.info("Error while closing socket %s", str(e)) + + self.sock = None + + +class TCPSocket(BaseSocket): + + FAMILY = socket.AF_INET + + def __str__(self): + if self.conf.is_ssl: + scheme = "https" + else: + scheme = "http" + + addr = self.sock.getsockname() + return "%s://%s:%d" % (scheme, addr[0], addr[1]) + + def set_options(self, sock, bound=False): + sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + return super().set_options(sock, bound=bound) + + +class TCP6Socket(TCPSocket): + + FAMILY = socket.AF_INET6 + + def __str__(self): + (host, port, _, _) = self.sock.getsockname() + return "http://[%s]:%d" % (host, port) + + +class UnixSocket(BaseSocket): + + FAMILY = socket.AF_UNIX + + def __init__(self, addr, conf, log, fd=None): + if fd is None: + try: + st = os.stat(addr) + except OSError as e: + if e.args[0] != errno.ENOENT: + raise + else: + if stat.S_ISSOCK(st.st_mode): + os.remove(addr) + else: + raise ValueError("%r is not a socket" % addr) + super().__init__(addr, conf, log, fd=fd) + + def __str__(self): + return "unix:%s" % self.cfg_addr + + def bind(self, sock): + old_umask = os.umask(self.conf.umask) + sock.bind(self.cfg_addr) + util.chown(self.cfg_addr, self.conf.uid, self.conf.gid) + os.umask(old_umask) + + +def _sock_type(addr): + if isinstance(addr, tuple): + if util.is_ipv6(addr[0]): + sock_type = TCP6Socket + else: + sock_type = TCPSocket + elif isinstance(addr, (str, bytes)): + sock_type = UnixSocket + else: + raise TypeError("Unable to create socket from: %r" % addr) + return sock_type + + +def create_sockets(conf, log, fds=None): + """ + Create a new socket for the configured addresses or file descriptors. + + If a configured address is a tuple then a TCP socket is created. + If it is a string, a Unix socket is created. Otherwise, a TypeError is + raised. + """ + listeners = [] + + # get it only once + addr = conf.address + fdaddr = [bind for bind in addr if isinstance(bind, int)] + if fds: + fdaddr += list(fds) + laddr = [bind for bind in addr if not isinstance(bind, int)] + + # check ssl config early to raise the error on startup + # only the certfile is needed since it can contains the keyfile + if conf.certfile and not os.path.exists(conf.certfile): + raise ValueError('certfile "%s" does not exist' % conf.certfile) + + if conf.keyfile and not os.path.exists(conf.keyfile): + raise ValueError('keyfile "%s" does not exist' % conf.keyfile) + + # sockets are already bound + if fdaddr: + for fd in fdaddr: + sock = socket.fromfd(fd, socket.AF_UNIX, socket.SOCK_STREAM) + sock_name = sock.getsockname() + sock_type = _sock_type(sock_name) + listener = sock_type(sock_name, conf, log, fd=fd) + listeners.append(listener) + + return listeners + + # no sockets is bound, first initialization of gunicorn in this env. + for addr in laddr: + sock_type = _sock_type(addr) + sock = None + for i in range(5): + try: + sock = sock_type(addr, conf, log) + except socket.error as e: + if e.args[0] == errno.EADDRINUSE: + log.error("Connection in use: %s", str(addr)) + if e.args[0] == errno.EADDRNOTAVAIL: + log.error("Invalid address: %s", str(addr)) + if i < 5: + msg = "connection to {addr} failed: {error}" + log.debug(msg.format(addr=str(addr), error=str(e))) + log.error("Retrying in 1 second.") + time.sleep(1) + else: + break + + if sock is None: + log.error("Can't connect to %s", str(addr)) + sys.exit(1) + + listeners.append(sock) + + return listeners + + +def close_sockets(listeners, unlink=True): + for sock in listeners: + sock_name = sock.getsockname() + sock.close() + if unlink and _sock_type(sock_name) is UnixSocket: + os.unlink(sock_name) + + +def ssl_context(conf): + def default_ssl_context_factory(): + context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH, cafile=conf.ca_certs) + context.load_cert_chain(certfile=conf.certfile, keyfile=conf.keyfile) + context.verify_mode = conf.cert_reqs + if conf.ciphers: + context.set_ciphers(conf.ciphers) + return context + + return conf.ssl_context(conf, default_ssl_context_factory) + + +def ssl_wrap_socket(sock, conf): + return ssl_context(conf).wrap_socket(sock, + server_side=True, + suppress_ragged_eofs=conf.suppress_ragged_eofs, + do_handshake_on_connect=conf.do_handshake_on_connect) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/systemd.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/systemd.py new file mode 100644 index 0000000..5bc1a74 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/systemd.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +import os +import socket + +SD_LISTEN_FDS_START = 3 + + +def listen_fds(unset_environment=True): + """ + Get the number of sockets inherited from systemd socket activation. + + :param unset_environment: clear systemd environment variables unless False + :type unset_environment: bool + :return: the number of sockets to inherit from systemd socket activation + :rtype: int + + Returns zero immediately if $LISTEN_PID is not set to the current pid. + Otherwise, returns the number of systemd activation sockets specified by + $LISTEN_FDS. + + When $LISTEN_PID matches the current pid, unsets the environment variables + unless the ``unset_environment`` flag is ``False``. + + .. note:: + Unlike the sd_listen_fds C function, this implementation does not set + the FD_CLOEXEC flag because the gunicorn arbiter never needs to do this. + + .. seealso:: + ``_ + + """ + fds = int(os.environ.get('LISTEN_FDS', 0)) + listen_pid = int(os.environ.get('LISTEN_PID', 0)) + + if listen_pid != os.getpid(): + return 0 + + if unset_environment: + os.environ.pop('LISTEN_PID', None) + os.environ.pop('LISTEN_FDS', None) + + return fds + + +def sd_notify(state, logger, unset_environment=False): + """Send a notification to systemd. state is a string; see + the man page of sd_notify (http://www.freedesktop.org/software/systemd/man/sd_notify.html) + for a description of the allowable values. + + If the unset_environment parameter is True, sd_notify() will unset + the $NOTIFY_SOCKET environment variable before returning (regardless of + whether the function call itself succeeded or not). Further calls to + sd_notify() will then fail, but the variable is no longer inherited by + child processes. + """ + + addr = os.environ.get('NOTIFY_SOCKET') + if addr is None: + # not run in a service, just a noop + return + try: + sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM | socket.SOCK_CLOEXEC) + if addr[0] == '@': + addr = '\0' + addr[1:] + sock.connect(addr) + sock.sendall(state.encode('utf-8')) + except Exception: + logger.debug("Exception while invoking sd_notify()", exc_info=True) + finally: + if unset_environment: + os.environ.pop('NOTIFY_SOCKET') + sock.close() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/util.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/util.py new file mode 100644 index 0000000..751deea --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/util.py @@ -0,0 +1,654 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. +import ast +import email.utils +import errno +import fcntl +import html +import importlib +import inspect +import io +import logging +import os +import pwd +import random +import re +import socket +import sys +import textwrap +import time +import traceback +import warnings + +try: + import importlib.metadata as importlib_metadata +except (ModuleNotFoundError, ImportError): + import importlib_metadata + +from gunicorn.errors import AppImportError +from gunicorn.workers import SUPPORTED_WORKERS +import urllib.parse + +REDIRECT_TO = getattr(os, 'devnull', '/dev/null') + +# Server and Date aren't technically hop-by-hop +# headers, but they are in the purview of the +# origin server which the WSGI spec says we should +# act like. So we drop them and add our own. +# +# In the future, concatenation server header values +# might be better, but nothing else does it and +# dropping them is easier. +hop_headers = set(""" + connection keep-alive proxy-authenticate proxy-authorization + te trailers transfer-encoding upgrade + server date + """.split()) + +try: + from setproctitle import setproctitle + + def _setproctitle(title): + setproctitle("gunicorn: %s" % title) +except ImportError: + def _setproctitle(title): + pass + + +def load_entry_point(distribution, group, name): + dist_obj = importlib_metadata.distribution(distribution) + eps = [ep for ep in dist_obj.entry_points + if ep.group == group and ep.name == name] + if not eps: + raise ImportError("Entry point %r not found" % ((group, name),)) + return eps[0].load() + + +def load_class(uri, default="gunicorn.workers.sync.SyncWorker", + section="gunicorn.workers"): + if inspect.isclass(uri): + return uri + if uri.startswith("egg:"): + # uses entry points + entry_str = uri.split("egg:")[1] + try: + dist, name = entry_str.rsplit("#", 1) + except ValueError: + dist = entry_str + name = default + + try: + return load_entry_point(dist, section, name) + except Exception: + exc = traceback.format_exc() + msg = "class uri %r invalid or not found: \n\n[%s]" + raise RuntimeError(msg % (uri, exc)) + else: + components = uri.split('.') + if len(components) == 1: + while True: + if uri.startswith("#"): + uri = uri[1:] + + if uri in SUPPORTED_WORKERS: + components = SUPPORTED_WORKERS[uri].split(".") + break + + try: + return load_entry_point( + "gunicorn", section, uri + ) + except Exception: + exc = traceback.format_exc() + msg = "class uri %r invalid or not found: \n\n[%s]" + raise RuntimeError(msg % (uri, exc)) + + klass = components.pop(-1) + + try: + mod = importlib.import_module('.'.join(components)) + except Exception: + exc = traceback.format_exc() + msg = "class uri %r invalid or not found: \n\n[%s]" + raise RuntimeError(msg % (uri, exc)) + return getattr(mod, klass) + + +positionals = ( + inspect.Parameter.POSITIONAL_ONLY, + inspect.Parameter.POSITIONAL_OR_KEYWORD, +) + + +def get_arity(f): + sig = inspect.signature(f) + arity = 0 + + for param in sig.parameters.values(): + if param.kind in positionals: + arity += 1 + + return arity + + +def get_username(uid): + """ get the username for a user id""" + return pwd.getpwuid(uid).pw_name + + +def set_owner_process(uid, gid, initgroups=False): + """ set user and group of workers processes """ + + if gid: + if uid: + try: + username = get_username(uid) + except KeyError: + initgroups = False + + # versions of python < 2.6.2 don't manage unsigned int for + # groups like on osx or fedora + gid = abs(gid) & 0x7FFFFFFF + + if initgroups: + os.initgroups(username, gid) + elif gid != os.getgid(): + os.setgid(gid) + + if uid and uid != os.getuid(): + os.setuid(uid) + + +def chown(path, uid, gid): + os.chown(path, uid, gid) + + +if sys.platform.startswith("win"): + def _waitfor(func, pathname, waitall=False): + # Perform the operation + func(pathname) + # Now setup the wait loop + if waitall: + dirname = pathname + else: + dirname, name = os.path.split(pathname) + dirname = dirname or '.' + # Check for `pathname` to be removed from the filesystem. + # The exponential backoff of the timeout amounts to a total + # of ~1 second after which the deletion is probably an error + # anyway. + # Testing on a i7@4.3GHz shows that usually only 1 iteration is + # required when contention occurs. + timeout = 0.001 + while timeout < 1.0: + # Note we are only testing for the existence of the file(s) in + # the contents of the directory regardless of any security or + # access rights. If we have made it this far, we have sufficient + # permissions to do that much using Python's equivalent of the + # Windows API FindFirstFile. + # Other Windows APIs can fail or give incorrect results when + # dealing with files that are pending deletion. + L = os.listdir(dirname) + if not L if waitall else name in L: + return + # Increase the timeout and try again + time.sleep(timeout) + timeout *= 2 + warnings.warn('tests may fail, delete still pending for ' + pathname, + RuntimeWarning, stacklevel=4) + + def _unlink(filename): + _waitfor(os.unlink, filename) +else: + _unlink = os.unlink + + +def unlink(filename): + try: + _unlink(filename) + except OSError as error: + # The filename need not exist. + if error.errno not in (errno.ENOENT, errno.ENOTDIR): + raise + + +def is_ipv6(addr): + try: + socket.inet_pton(socket.AF_INET6, addr) + except socket.error: # not a valid address + return False + except ValueError: # ipv6 not supported on this platform + return False + return True + + +def parse_address(netloc, default_port='8000'): + if re.match(r'unix:(//)?', netloc): + return re.split(r'unix:(//)?', netloc)[-1] + + if netloc.startswith("fd://"): + fd = netloc[5:] + try: + return int(fd) + except ValueError: + raise RuntimeError("%r is not a valid file descriptor." % fd) from None + + if netloc.startswith("tcp://"): + netloc = netloc.split("tcp://")[1] + host, port = netloc, default_port + + if '[' in netloc and ']' in netloc: + host = netloc.split(']')[0][1:] + port = (netloc.split(']:') + [default_port])[1] + elif ':' in netloc: + host, port = (netloc.split(':') + [default_port])[:2] + elif netloc == "": + host, port = "0.0.0.0", default_port + + try: + port = int(port) + except ValueError: + raise RuntimeError("%r is not a valid port number." % port) + + return host.lower(), port + + +def close_on_exec(fd): + flags = fcntl.fcntl(fd, fcntl.F_GETFD) + flags |= fcntl.FD_CLOEXEC + fcntl.fcntl(fd, fcntl.F_SETFD, flags) + + +def set_non_blocking(fd): + flags = fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK + fcntl.fcntl(fd, fcntl.F_SETFL, flags) + + +def close(sock): + try: + sock.close() + except socket.error: + pass + + +try: + from os import closerange +except ImportError: + def closerange(fd_low, fd_high): + # Iterate through and close all file descriptors. + for fd in range(fd_low, fd_high): + try: + os.close(fd) + except OSError: # ERROR, fd wasn't open to begin with (ignored) + pass + + +def write_chunk(sock, data): + if isinstance(data, str): + data = data.encode('utf-8') + chunk_size = "%X\r\n" % len(data) + chunk = b"".join([chunk_size.encode('utf-8'), data, b"\r\n"]) + sock.sendall(chunk) + + +def write(sock, data, chunked=False): + if chunked: + return write_chunk(sock, data) + sock.sendall(data) + + +def write_nonblock(sock, data, chunked=False): + timeout = sock.gettimeout() + if timeout != 0.0: + try: + sock.setblocking(0) + return write(sock, data, chunked) + finally: + sock.setblocking(1) + else: + return write(sock, data, chunked) + + +def write_error(sock, status_int, reason, mesg): + html_error = textwrap.dedent("""\ + + + %(reason)s + + +

    %(reason)s

    + %(mesg)s + + + """) % {"reason": reason, "mesg": html.escape(mesg)} + + http = textwrap.dedent("""\ + HTTP/1.1 %s %s\r + Connection: close\r + Content-Type: text/html\r + Content-Length: %d\r + \r + %s""") % (str(status_int), reason, len(html_error), html_error) + write_nonblock(sock, http.encode('latin1')) + + +def _called_with_wrong_args(f): + """Check whether calling a function raised a ``TypeError`` because + the call failed or because something in the function raised the + error. + + :param f: The function that was called. + :return: ``True`` if the call failed. + """ + tb = sys.exc_info()[2] + + try: + while tb is not None: + if tb.tb_frame.f_code is f.__code__: + # In the function, it was called successfully. + return False + + tb = tb.tb_next + + # Didn't reach the function. + return True + finally: + # Delete tb to break a circular reference in Python 2. + # https://docs.python.org/2/library/sys.html#sys.exc_info + del tb + + +def import_app(module): + parts = module.split(":", 1) + if len(parts) == 1: + obj = "application" + else: + module, obj = parts[0], parts[1] + + try: + mod = importlib.import_module(module) + except ImportError: + if module.endswith(".py") and os.path.exists(module): + msg = "Failed to find application, did you mean '%s:%s'?" + raise ImportError(msg % (module.rsplit(".", 1)[0], obj)) + raise + + # Parse obj as a single expression to determine if it's a valid + # attribute name or function call. + try: + expression = ast.parse(obj, mode="eval").body + except SyntaxError: + raise AppImportError( + "Failed to parse %r as an attribute name or function call." % obj + ) + + if isinstance(expression, ast.Name): + name = expression.id + args = kwargs = None + elif isinstance(expression, ast.Call): + # Ensure the function name is an attribute name only. + if not isinstance(expression.func, ast.Name): + raise AppImportError("Function reference must be a simple name: %r" % obj) + + name = expression.func.id + + # Parse the positional and keyword arguments as literals. + try: + args = [ast.literal_eval(arg) for arg in expression.args] + kwargs = {kw.arg: ast.literal_eval(kw.value) for kw in expression.keywords} + except ValueError: + # literal_eval gives cryptic error messages, show a generic + # message with the full expression instead. + raise AppImportError( + "Failed to parse arguments as literal values: %r" % obj + ) + else: + raise AppImportError( + "Failed to parse %r as an attribute name or function call." % obj + ) + + is_debug = logging.root.level == logging.DEBUG + try: + app = getattr(mod, name) + except AttributeError: + if is_debug: + traceback.print_exception(*sys.exc_info()) + raise AppImportError("Failed to find attribute %r in %r." % (name, module)) + + # If the expression was a function call, call the retrieved object + # to get the real application. + if args is not None: + try: + app = app(*args, **kwargs) + except TypeError as e: + # If the TypeError was due to bad arguments to the factory + # function, show Python's nice error message without a + # traceback. + if _called_with_wrong_args(app): + raise AppImportError( + "".join(traceback.format_exception_only(TypeError, e)).strip() + ) + + # Otherwise it was raised from within the function, show the + # full traceback. + raise + + if app is None: + raise AppImportError("Failed to find application object: %r" % obj) + + if not callable(app): + raise AppImportError("Application object must be callable.") + return app + + +def getcwd(): + # get current path, try to use PWD env first + try: + a = os.stat(os.environ['PWD']) + b = os.stat(os.getcwd()) + if a.st_ino == b.st_ino and a.st_dev == b.st_dev: + cwd = os.environ['PWD'] + else: + cwd = os.getcwd() + except Exception: + cwd = os.getcwd() + return cwd + + +def http_date(timestamp=None): + """Return the current date and time formatted for a message header.""" + if timestamp is None: + timestamp = time.time() + s = email.utils.formatdate(timestamp, localtime=False, usegmt=True) + return s + + +def is_hoppish(header): + return header.lower().strip() in hop_headers + + +def daemonize(enable_stdio_inheritance=False): + """\ + Standard daemonization of a process. + http://www.faqs.org/faqs/unix-faq/programmer/faq/ section 1.7 + """ + if 'GUNICORN_FD' not in os.environ: + if os.fork(): + os._exit(0) + os.setsid() + + if os.fork(): + os._exit(0) + + os.umask(0o22) + + # In both the following any file descriptors above stdin + # stdout and stderr are left untouched. The inheritance + # option simply allows one to have output go to a file + # specified by way of shell redirection when not wanting + # to use --error-log option. + + if not enable_stdio_inheritance: + # Remap all of stdin, stdout and stderr on to + # /dev/null. The expectation is that users have + # specified the --error-log option. + + closerange(0, 3) + + fd_null = os.open(REDIRECT_TO, os.O_RDWR) + # PEP 446, make fd for /dev/null inheritable + os.set_inheritable(fd_null, True) + + # expect fd_null to be always 0 here, but in-case not ... + if fd_null != 0: + os.dup2(fd_null, 0) + + os.dup2(fd_null, 1) + os.dup2(fd_null, 2) + + else: + fd_null = os.open(REDIRECT_TO, os.O_RDWR) + + # Always redirect stdin to /dev/null as we would + # never expect to need to read interactive input. + + if fd_null != 0: + os.close(0) + os.dup2(fd_null, 0) + + # If stdout and stderr are still connected to + # their original file descriptors we check to see + # if they are associated with terminal devices. + # When they are we map them to /dev/null so that + # are still detached from any controlling terminal + # properly. If not we preserve them as they are. + # + # If stdin and stdout were not hooked up to the + # original file descriptors, then all bets are + # off and all we can really do is leave them as + # they were. + # + # This will allow 'gunicorn ... > output.log 2>&1' + # to work with stdout/stderr going to the file + # as expected. + # + # Note that if using --error-log option, the log + # file specified through shell redirection will + # only be used up until the log file specified + # by the option takes over. As it replaces stdout + # and stderr at the file descriptor level, then + # anything using stdout or stderr, including having + # cached a reference to them, will still work. + + def redirect(stream, fd_expect): + try: + fd = stream.fileno() + if fd == fd_expect and stream.isatty(): + os.close(fd) + os.dup2(fd_null, fd) + except AttributeError: + pass + + redirect(sys.stdout, 1) + redirect(sys.stderr, 2) + + +def seed(): + try: + random.seed(os.urandom(64)) + except NotImplementedError: + random.seed('%s.%s' % (time.time(), os.getpid())) + + +def check_is_writable(path): + try: + with open(path, 'a') as f: + f.close() + except IOError as e: + raise RuntimeError("Error: '%s' isn't writable [%r]" % (path, e)) + + +def to_bytestring(value, encoding="utf8"): + """Converts a string argument to a byte string""" + if isinstance(value, bytes): + return value + if not isinstance(value, str): + raise TypeError('%r is not a string' % value) + + return value.encode(encoding) + + +def has_fileno(obj): + if not hasattr(obj, "fileno"): + return False + + # check BytesIO case and maybe others + try: + obj.fileno() + except (AttributeError, IOError, io.UnsupportedOperation): + return False + + return True + + +def warn(msg): + print("!!!", file=sys.stderr) + + lines = msg.splitlines() + for i, line in enumerate(lines): + if i == 0: + line = "WARNING: %s" % line + print("!!! %s" % line, file=sys.stderr) + + print("!!!\n", file=sys.stderr) + sys.stderr.flush() + + +def make_fail_app(msg): + msg = to_bytestring(msg) + + def app(environ, start_response): + start_response("500 Internal Server Error", [ + ("Content-Type", "text/plain"), + ("Content-Length", str(len(msg))) + ]) + return [msg] + + return app + + +def split_request_uri(uri): + if uri.startswith("//"): + # When the path starts with //, urlsplit considers it as a + # relative uri while the RFC says we should consider it as abs_path + # http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2 + # We use temporary dot prefix to workaround this behaviour + parts = urllib.parse.urlsplit("." + uri) + return parts._replace(path=parts.path[1:]) + + return urllib.parse.urlsplit(uri) + + +# From six.reraise +def reraise(tp, value, tb=None): + try: + if value is None: + value = tp() + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + finally: + value = None + tb = None + + +def bytes_to_str(b): + if isinstance(b, str): + return b + return str(b, 'latin1') + + +def unquote_to_wsgi_str(string): + return urllib.parse.unquote_to_bytes(string).decode('latin-1') diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/__init__.py new file mode 100644 index 0000000..ae753e1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +# supported gunicorn workers. +SUPPORTED_WORKERS = { + "sync": "gunicorn.workers.sync.SyncWorker", + "eventlet": "gunicorn.workers.geventlet.EventletWorker", + "gevent": "gunicorn.workers.ggevent.GeventWorker", + "gevent_wsgi": "gunicorn.workers.ggevent.GeventPyWSGIWorker", + "gevent_pywsgi": "gunicorn.workers.ggevent.GeventPyWSGIWorker", + "tornado": "gunicorn.workers.gtornado.TornadoWorker", + "gthread": "gunicorn.workers.gthread.ThreadWorker", +} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/base.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/base.py new file mode 100644 index 0000000..f321dd2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/base.py @@ -0,0 +1,275 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +import io +import os +import signal +import sys +import time +import traceback +from datetime import datetime +from random import randint +from ssl import SSLError + +from gunicorn import util +from gunicorn.http.errors import ( + ForbiddenProxyRequest, InvalidHeader, + InvalidHeaderName, InvalidHTTPVersion, + InvalidProxyLine, InvalidRequestLine, + InvalidRequestMethod, InvalidSchemeHeaders, + LimitRequestHeaders, LimitRequestLine, +) +from gunicorn.http.wsgi import Response, default_environ +from gunicorn.reloader import reloader_engines +from gunicorn.workers.workertmp import WorkerTmp + + +class Worker(object): + + SIGNALS = [getattr(signal, "SIG%s" % x) for x in ( + "ABRT HUP QUIT INT TERM USR1 USR2 WINCH CHLD".split() + )] + + PIPE = [] + + def __init__(self, age, ppid, sockets, app, timeout, cfg, log): + """\ + This is called pre-fork so it shouldn't do anything to the + current process. If there's a need to make process wide + changes you'll want to do that in ``self.init_process()``. + """ + self.age = age + self.pid = "[booting]" + self.ppid = ppid + self.sockets = sockets + self.app = app + self.timeout = timeout + self.cfg = cfg + self.booted = False + self.aborted = False + self.reloader = None + + self.nr = 0 + + if cfg.max_requests > 0: + jitter = randint(0, cfg.max_requests_jitter) + self.max_requests = cfg.max_requests + jitter + else: + self.max_requests = sys.maxsize + + self.alive = True + self.log = log + self.tmp = WorkerTmp(cfg) + + def __str__(self): + return "" % self.pid + + def notify(self): + """\ + Your worker subclass must arrange to have this method called + once every ``self.timeout`` seconds. If you fail in accomplishing + this task, the master process will murder your workers. + """ + self.tmp.notify() + + def run(self): + """\ + This is the mainloop of a worker process. You should override + this method in a subclass to provide the intended behaviour + for your particular evil schemes. + """ + raise NotImplementedError() + + def init_process(self): + """\ + If you override this method in a subclass, the last statement + in the function should be to call this method with + super().init_process() so that the ``run()`` loop is initiated. + """ + + # set environment' variables + if self.cfg.env: + for k, v in self.cfg.env.items(): + os.environ[k] = v + + util.set_owner_process(self.cfg.uid, self.cfg.gid, + initgroups=self.cfg.initgroups) + + # Reseed the random number generator + util.seed() + + # For waking ourselves up + self.PIPE = os.pipe() + for p in self.PIPE: + util.set_non_blocking(p) + util.close_on_exec(p) + + # Prevent fd inheritance + for s in self.sockets: + util.close_on_exec(s) + util.close_on_exec(self.tmp.fileno()) + + self.wait_fds = self.sockets + [self.PIPE[0]] + + self.log.close_on_exec() + + self.init_signals() + + # start the reloader + if self.cfg.reload: + def changed(fname): + self.log.info("Worker reloading: %s modified", fname) + self.alive = False + os.write(self.PIPE[1], b"1") + self.cfg.worker_int(self) + time.sleep(0.1) + sys.exit(0) + + reloader_cls = reloader_engines[self.cfg.reload_engine] + self.reloader = reloader_cls(extra_files=self.cfg.reload_extra_files, + callback=changed) + + self.load_wsgi() + if self.reloader: + self.reloader.start() + + self.cfg.post_worker_init(self) + + # Enter main run loop + self.booted = True + self.run() + + def load_wsgi(self): + try: + self.wsgi = self.app.wsgi() + except SyntaxError as e: + if not self.cfg.reload: + raise + + self.log.exception(e) + + # fix from PR #1228 + # storing the traceback into exc_tb will create a circular reference. + # per https://docs.python.org/2/library/sys.html#sys.exc_info warning, + # delete the traceback after use. + try: + _, exc_val, exc_tb = sys.exc_info() + self.reloader.add_extra_file(exc_val.filename) + + tb_string = io.StringIO() + traceback.print_tb(exc_tb, file=tb_string) + self.wsgi = util.make_fail_app(tb_string.getvalue()) + finally: + del exc_tb + + def init_signals(self): + # reset signaling + for s in self.SIGNALS: + signal.signal(s, signal.SIG_DFL) + # init new signaling + signal.signal(signal.SIGQUIT, self.handle_quit) + signal.signal(signal.SIGTERM, self.handle_exit) + signal.signal(signal.SIGINT, self.handle_quit) + signal.signal(signal.SIGWINCH, self.handle_winch) + signal.signal(signal.SIGUSR1, self.handle_usr1) + signal.signal(signal.SIGABRT, self.handle_abort) + + # Don't let SIGTERM and SIGUSR1 disturb active requests + # by interrupting system calls + signal.siginterrupt(signal.SIGTERM, False) + signal.siginterrupt(signal.SIGUSR1, False) + + if hasattr(signal, 'set_wakeup_fd'): + signal.set_wakeup_fd(self.PIPE[1]) + + def handle_usr1(self, sig, frame): + self.log.reopen_files() + + def handle_exit(self, sig, frame): + self.alive = False + + def handle_quit(self, sig, frame): + self.alive = False + # worker_int callback + self.cfg.worker_int(self) + time.sleep(0.1) + sys.exit(0) + + def handle_abort(self, sig, frame): + self.alive = False + self.cfg.worker_abort(self) + sys.exit(1) + + def handle_error(self, req, client, addr, exc): + request_start = datetime.now() + addr = addr or ('', -1) # unix socket case + if isinstance(exc, ( + InvalidRequestLine, InvalidRequestMethod, + InvalidHTTPVersion, InvalidHeader, InvalidHeaderName, + LimitRequestLine, LimitRequestHeaders, + InvalidProxyLine, ForbiddenProxyRequest, + InvalidSchemeHeaders, + SSLError, + )): + + status_int = 400 + reason = "Bad Request" + + if isinstance(exc, InvalidRequestLine): + mesg = "Invalid Request Line '%s'" % str(exc) + elif isinstance(exc, InvalidRequestMethod): + mesg = "Invalid Method '%s'" % str(exc) + elif isinstance(exc, InvalidHTTPVersion): + mesg = "Invalid HTTP Version '%s'" % str(exc) + elif isinstance(exc, (InvalidHeaderName, InvalidHeader,)): + mesg = "%s" % str(exc) + if not req and hasattr(exc, "req"): + req = exc.req # for access log + elif isinstance(exc, LimitRequestLine): + mesg = "%s" % str(exc) + elif isinstance(exc, LimitRequestHeaders): + reason = "Request Header Fields Too Large" + mesg = "Error parsing headers: '%s'" % str(exc) + status_int = 431 + elif isinstance(exc, InvalidProxyLine): + mesg = "'%s'" % str(exc) + elif isinstance(exc, ForbiddenProxyRequest): + reason = "Forbidden" + mesg = "Request forbidden" + status_int = 403 + elif isinstance(exc, InvalidSchemeHeaders): + mesg = "%s" % str(exc) + elif isinstance(exc, SSLError): + reason = "Forbidden" + mesg = "'%s'" % str(exc) + status_int = 403 + + msg = "Invalid request from ip={ip}: {error}" + self.log.warning(msg.format(ip=addr[0], error=str(exc))) + else: + if hasattr(req, "uri"): + self.log.exception("Error handling request %s", req.uri) + status_int = 500 + reason = "Internal Server Error" + mesg = "" + + if req is not None: + request_time = datetime.now() - request_start + environ = default_environ(req, client, self.cfg) + environ['REMOTE_ADDR'] = addr[0] + environ['REMOTE_PORT'] = str(addr[1]) + resp = Response(req, client, self.cfg) + resp.status = "%s %s" % (status_int, reason) + resp.response_length = len(mesg) + self.log.access(resp, req, environ, request_time) + + try: + util.write_error(client, status_int, reason, mesg) + except Exception: + self.log.debug("Failed to send error message.") + + def handle_winch(self, sig, fname): + # Ignore SIGWINCH in worker. Fixes a crash on OpenBSD. + self.log.debug("worker: SIGWINCH ignored.") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/base_async.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/base_async.py new file mode 100644 index 0000000..b059a7c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/base_async.py @@ -0,0 +1,148 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +from datetime import datetime +import errno +import socket +import ssl +import sys + +from gunicorn import http +from gunicorn.http import wsgi +from gunicorn import util +from gunicorn.workers import base + +ALREADY_HANDLED = object() + + +class AsyncWorker(base.Worker): + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.worker_connections = self.cfg.worker_connections + + def timeout_ctx(self): + raise NotImplementedError() + + def is_already_handled(self, respiter): + # some workers will need to overload this function to raise a StopIteration + return respiter == ALREADY_HANDLED + + def handle(self, listener, client, addr): + req = None + try: + parser = http.RequestParser(self.cfg, client, addr) + try: + listener_name = listener.getsockname() + if not self.cfg.keepalive: + req = next(parser) + self.handle_request(listener_name, req, client, addr) + else: + # keepalive loop + proxy_protocol_info = {} + while True: + req = None + with self.timeout_ctx(): + req = next(parser) + if not req: + break + if req.proxy_protocol_info: + proxy_protocol_info = req.proxy_protocol_info + else: + req.proxy_protocol_info = proxy_protocol_info + self.handle_request(listener_name, req, client, addr) + except http.errors.NoMoreData as e: + self.log.debug("Ignored premature client disconnection. %s", e) + except StopIteration as e: + self.log.debug("Closing connection. %s", e) + except ssl.SSLError: + # pass to next try-except level + util.reraise(*sys.exc_info()) + except EnvironmentError: + # pass to next try-except level + util.reraise(*sys.exc_info()) + except Exception as e: + self.handle_error(req, client, addr, e) + except ssl.SSLError as e: + if e.args[0] == ssl.SSL_ERROR_EOF: + self.log.debug("ssl connection closed") + client.close() + else: + self.log.debug("Error processing SSL request.") + self.handle_error(req, client, addr, e) + except EnvironmentError as e: + if e.errno not in (errno.EPIPE, errno.ECONNRESET, errno.ENOTCONN): + self.log.exception("Socket error processing request.") + else: + if e.errno == errno.ECONNRESET: + self.log.debug("Ignoring connection reset") + elif e.errno == errno.ENOTCONN: + self.log.debug("Ignoring socket not connected") + else: + self.log.debug("Ignoring EPIPE") + except Exception as e: + self.handle_error(req, client, addr, e) + finally: + util.close(client) + + def handle_request(self, listener_name, req, sock, addr): + request_start = datetime.now() + environ = {} + resp = None + try: + self.cfg.pre_request(self, req) + resp, environ = wsgi.create(req, sock, addr, + listener_name, self.cfg) + environ["wsgi.multithread"] = True + self.nr += 1 + if self.nr >= self.max_requests: + if self.alive: + self.log.info("Autorestarting worker after current request.") + self.alive = False + + if not self.alive or not self.cfg.keepalive: + resp.force_close() + + respiter = self.wsgi(environ, resp.start_response) + if self.is_already_handled(respiter): + return False + try: + if isinstance(respiter, environ['wsgi.file_wrapper']): + resp.write_file(respiter) + else: + for item in respiter: + resp.write(item) + resp.close() + finally: + request_time = datetime.now() - request_start + self.log.access(resp, req, environ, request_time) + if hasattr(respiter, "close"): + respiter.close() + if resp.should_close(): + raise StopIteration() + except StopIteration: + raise + except EnvironmentError: + # If the original exception was a socket.error we delegate + # handling it to the caller (where handle() might ignore it) + util.reraise(*sys.exc_info()) + except Exception: + if resp and resp.headers_sent: + # If the requests have already been sent, we should close the + # connection to indicate the error. + self.log.exception("Error handling request") + try: + sock.shutdown(socket.SHUT_RDWR) + sock.close() + except EnvironmentError: + pass + raise StopIteration() + raise + finally: + try: + self.cfg.post_request(self, req, environ, resp) + except Exception: + self.log.exception("Exception in post_request hook") + return True diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/geventlet.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/geventlet.py new file mode 100644 index 0000000..c42ed11 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/geventlet.py @@ -0,0 +1,187 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +from functools import partial +import sys + +try: + import eventlet +except ImportError: + raise RuntimeError("eventlet worker requires eventlet 0.24.1 or higher") +else: + from packaging.version import parse as parse_version + if parse_version(eventlet.__version__) < parse_version('0.24.1'): + raise RuntimeError("eventlet worker requires eventlet 0.24.1 or higher") + +from eventlet import hubs, greenthread +from eventlet.greenio import GreenSocket +import eventlet.wsgi +import greenlet + +from gunicorn.workers.base_async import AsyncWorker +from gunicorn.sock import ssl_wrap_socket + +# ALREADY_HANDLED is removed in 0.30.3+ now it's `WSGI_LOCAL.already_handled: bool` +# https://github.com/eventlet/eventlet/pull/544 +EVENTLET_WSGI_LOCAL = getattr(eventlet.wsgi, "WSGI_LOCAL", None) +EVENTLET_ALREADY_HANDLED = getattr(eventlet.wsgi, "ALREADY_HANDLED", None) + + +def _eventlet_socket_sendfile(self, file, offset=0, count=None): + # Based on the implementation in gevent which in turn is slightly + # modified from the standard library implementation. + if self.gettimeout() == 0: + raise ValueError("non-blocking sockets are not supported") + if offset: + file.seek(offset) + blocksize = min(count, 8192) if count else 8192 + total_sent = 0 + # localize variable access to minimize overhead + file_read = file.read + sock_send = self.send + try: + while True: + if count: + blocksize = min(count - total_sent, blocksize) + if blocksize <= 0: + break + data = memoryview(file_read(blocksize)) + if not data: + break # EOF + while True: + try: + sent = sock_send(data) + except BlockingIOError: + continue + else: + total_sent += sent + if sent < len(data): + data = data[sent:] + else: + break + return total_sent + finally: + if total_sent > 0 and hasattr(file, 'seek'): + file.seek(offset + total_sent) + + +def _eventlet_serve(sock, handle, concurrency): + """ + Serve requests forever. + + This code is nearly identical to ``eventlet.convenience.serve`` except + that it attempts to join the pool at the end, which allows for gunicorn + graceful shutdowns. + """ + pool = eventlet.greenpool.GreenPool(concurrency) + server_gt = eventlet.greenthread.getcurrent() + + while True: + try: + conn, addr = sock.accept() + gt = pool.spawn(handle, conn, addr) + gt.link(_eventlet_stop, server_gt, conn) + conn, addr, gt = None, None, None + except eventlet.StopServe: + sock.close() + pool.waitall() + return + + +def _eventlet_stop(client, server, conn): + """ + Stop a greenlet handling a request and close its connection. + + This code is lifted from eventlet so as not to depend on undocumented + functions in the library. + """ + try: + try: + client.wait() + finally: + conn.close() + except greenlet.GreenletExit: + pass + except Exception: + greenthread.kill(server, *sys.exc_info()) + + +def patch_sendfile(): + # As of eventlet 0.25.1, GreenSocket.sendfile doesn't exist, + # meaning the native implementations of socket.sendfile will be used. + # If os.sendfile exists, it will attempt to use that, failing explicitly + # if the socket is in non-blocking mode, which the underlying + # socket object /is/. Even the regular _sendfile_use_send will + # fail in that way; plus, it would use the underlying socket.send which isn't + # properly cooperative. So we have to monkey-patch a working socket.sendfile() + # into GreenSocket; in this method, `self.send` will be the GreenSocket's + # send method which is properly cooperative. + if not hasattr(GreenSocket, 'sendfile'): + GreenSocket.sendfile = _eventlet_socket_sendfile + + +class EventletWorker(AsyncWorker): + + def patch(self): + hubs.use_hub() + eventlet.monkey_patch() + patch_sendfile() + + def is_already_handled(self, respiter): + # eventlet >= 0.30.3 + if getattr(EVENTLET_WSGI_LOCAL, "already_handled", None): + raise StopIteration() + # eventlet < 0.30.3 + if respiter == EVENTLET_ALREADY_HANDLED: + raise StopIteration() + return super().is_already_handled(respiter) + + def init_process(self): + self.patch() + super().init_process() + + def handle_quit(self, sig, frame): + eventlet.spawn(super().handle_quit, sig, frame) + + def handle_usr1(self, sig, frame): + eventlet.spawn(super().handle_usr1, sig, frame) + + def timeout_ctx(self): + return eventlet.Timeout(self.cfg.keepalive or None, False) + + def handle(self, listener, client, addr): + if self.cfg.is_ssl: + client = ssl_wrap_socket(client, self.cfg) + super().handle(listener, client, addr) + + def run(self): + acceptors = [] + for sock in self.sockets: + gsock = GreenSocket(sock) + gsock.setblocking(1) + hfun = partial(self.handle, gsock) + acceptor = eventlet.spawn(_eventlet_serve, gsock, hfun, + self.worker_connections) + + acceptors.append(acceptor) + eventlet.sleep(0.0) + + while self.alive: + self.notify() + eventlet.sleep(1.0) + + self.notify() + t = None + try: + with eventlet.Timeout(self.cfg.graceful_timeout) as t: + for a in acceptors: + a.kill(eventlet.StopServe()) + for a in acceptors: + a.wait() + except eventlet.Timeout as te: + if te != t: + raise + for a in acceptors: + a.kill() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/ggevent.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/ggevent.py new file mode 100644 index 0000000..2125a32 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/ggevent.py @@ -0,0 +1,190 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +import os +import sys +from datetime import datetime +from functools import partial +import time + +try: + import gevent +except ImportError: + raise RuntimeError("gevent worker requires gevent 1.4 or higher") +else: + from packaging.version import parse as parse_version + if parse_version(gevent.__version__) < parse_version('1.4'): + raise RuntimeError("gevent worker requires gevent 1.4 or higher") + +from gevent.pool import Pool +from gevent.server import StreamServer +from gevent import hub, monkey, socket, pywsgi + +import gunicorn +from gunicorn.http.wsgi import base_environ +from gunicorn.sock import ssl_context +from gunicorn.workers.base_async import AsyncWorker + +VERSION = "gevent/%s gunicorn/%s" % (gevent.__version__, gunicorn.__version__) + + +class GeventWorker(AsyncWorker): + + server_class = None + wsgi_handler = None + + def patch(self): + monkey.patch_all() + + # patch sockets + sockets = [] + for s in self.sockets: + sockets.append(socket.socket(s.FAMILY, socket.SOCK_STREAM, + fileno=s.sock.fileno())) + self.sockets = sockets + + def notify(self): + super().notify() + if self.ppid != os.getppid(): + self.log.info("Parent changed, shutting down: %s", self) + sys.exit(0) + + def timeout_ctx(self): + return gevent.Timeout(self.cfg.keepalive, False) + + def run(self): + servers = [] + ssl_args = {} + + if self.cfg.is_ssl: + ssl_args = {"ssl_context": ssl_context(self.cfg)} + + for s in self.sockets: + s.setblocking(1) + pool = Pool(self.worker_connections) + if self.server_class is not None: + environ = base_environ(self.cfg) + environ.update({ + "wsgi.multithread": True, + "SERVER_SOFTWARE": VERSION, + }) + server = self.server_class( + s, application=self.wsgi, spawn=pool, log=self.log, + handler_class=self.wsgi_handler, environ=environ, + **ssl_args) + else: + hfun = partial(self.handle, s) + server = StreamServer(s, handle=hfun, spawn=pool, **ssl_args) + if self.cfg.workers > 1: + server.max_accept = 1 + + server.start() + servers.append(server) + + while self.alive: + self.notify() + gevent.sleep(1.0) + + try: + # Stop accepting requests + for server in servers: + if hasattr(server, 'close'): # gevent 1.0 + server.close() + if hasattr(server, 'kill'): # gevent < 1.0 + server.kill() + + # Handle current requests until graceful_timeout + ts = time.time() + while time.time() - ts <= self.cfg.graceful_timeout: + accepting = 0 + for server in servers: + if server.pool.free_count() != server.pool.size: + accepting += 1 + + # if no server is accepting a connection, we can exit + if not accepting: + return + + self.notify() + gevent.sleep(1.0) + + # Force kill all active the handlers + self.log.warning("Worker graceful timeout (pid:%s)", self.pid) + for server in servers: + server.stop(timeout=1) + except Exception: + pass + + def handle(self, listener, client, addr): + # Connected socket timeout defaults to socket.getdefaulttimeout(). + # This forces to blocking mode. + client.setblocking(1) + super().handle(listener, client, addr) + + def handle_request(self, listener_name, req, sock, addr): + try: + super().handle_request(listener_name, req, sock, addr) + except gevent.GreenletExit: + pass + except SystemExit: + pass + + def handle_quit(self, sig, frame): + # Move this out of the signal handler so we can use + # blocking calls. See #1126 + gevent.spawn(super().handle_quit, sig, frame) + + def handle_usr1(self, sig, frame): + # Make the gevent workers handle the usr1 signal + # by deferring to a new greenlet. See #1645 + gevent.spawn(super().handle_usr1, sig, frame) + + def init_process(self): + self.patch() + hub.reinit() + super().init_process() + + +class GeventResponse(object): + + status = None + headers = None + sent = None + + def __init__(self, status, headers, clength): + self.status = status + self.headers = headers + self.sent = clength + + +class PyWSGIHandler(pywsgi.WSGIHandler): + + def log_request(self): + start = datetime.fromtimestamp(self.time_start) + finish = datetime.fromtimestamp(self.time_finish) + response_time = finish - start + resp_headers = getattr(self, 'response_headers', {}) + resp = GeventResponse(self.status, resp_headers, self.response_length) + if hasattr(self, 'headers'): + req_headers = self.headers.items() + else: + req_headers = [] + self.server.log.access(resp, req_headers, self.environ, response_time) + + def get_environ(self): + env = super().get_environ() + env['gunicorn.sock'] = self.socket + env['RAW_URI'] = self.path + return env + + +class PyWSGIServer(pywsgi.WSGIServer): + pass + + +class GeventPyWSGIWorker(GeventWorker): + "The Gevent StreamServer based workers." + server_class = PyWSGIServer + wsgi_handler = PyWSGIHandler diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/gthread.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/gthread.py new file mode 100644 index 0000000..c9c4234 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/gthread.py @@ -0,0 +1,373 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +# design: +# A threaded worker accepts connections in the main loop, accepted +# connections are added to the thread pool as a connection job. +# Keepalive connections are put back in the loop waiting for an event. +# If no event happen after the keep alive timeout, the connection is +# closed. +# pylint: disable=no-else-break + +from concurrent import futures +import errno +import os +import selectors +import socket +import ssl +import sys +import time +from collections import deque +from datetime import datetime +from functools import partial +from threading import RLock + +from . import base +from .. import http +from .. import util +from .. import sock +from ..http import wsgi + + +class TConn(object): + + def __init__(self, cfg, sock, client, server): + self.cfg = cfg + self.sock = sock + self.client = client + self.server = server + + self.timeout = None + self.parser = None + self.initialized = False + + # set the socket to non blocking + self.sock.setblocking(False) + + def init(self): + self.initialized = True + self.sock.setblocking(True) + + if self.parser is None: + # wrap the socket if needed + if self.cfg.is_ssl: + self.sock = sock.ssl_wrap_socket(self.sock, self.cfg) + + # initialize the parser + self.parser = http.RequestParser(self.cfg, self.sock, self.client) + + def set_timeout(self): + # set the timeout + self.timeout = time.time() + self.cfg.keepalive + + def close(self): + util.close(self.sock) + + +class ThreadWorker(base.Worker): + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.worker_connections = self.cfg.worker_connections + self.max_keepalived = self.cfg.worker_connections - self.cfg.threads + # initialise the pool + self.tpool = None + self.poller = None + self._lock = None + self.futures = deque() + self._keep = deque() + self.nr_conns = 0 + + @classmethod + def check_config(cls, cfg, log): + max_keepalived = cfg.worker_connections - cfg.threads + + if max_keepalived <= 0 and cfg.keepalive: + log.warning("No keepalived connections can be handled. " + + "Check the number of worker connections and threads.") + + def init_process(self): + self.tpool = self.get_thread_pool() + self.poller = selectors.DefaultSelector() + self._lock = RLock() + super().init_process() + + def get_thread_pool(self): + """Override this method to customize how the thread pool is created""" + return futures.ThreadPoolExecutor(max_workers=self.cfg.threads) + + def handle_quit(self, sig, frame): + self.alive = False + # worker_int callback + self.cfg.worker_int(self) + self.tpool.shutdown(False) + time.sleep(0.1) + sys.exit(0) + + def _wrap_future(self, fs, conn): + fs.conn = conn + self.futures.append(fs) + fs.add_done_callback(self.finish_request) + + def enqueue_req(self, conn): + conn.init() + # submit the connection to a worker + fs = self.tpool.submit(self.handle, conn) + self._wrap_future(fs, conn) + + def accept(self, server, listener): + try: + sock, client = listener.accept() + # initialize the connection object + conn = TConn(self.cfg, sock, client, server) + + self.nr_conns += 1 + # wait until socket is readable + with self._lock: + self.poller.register(conn.sock, selectors.EVENT_READ, + partial(self.on_client_socket_readable, conn)) + except EnvironmentError as e: + if e.errno not in (errno.EAGAIN, errno.ECONNABORTED, + errno.EWOULDBLOCK): + raise + + def on_client_socket_readable(self, conn, client): + with self._lock: + # unregister the client from the poller + self.poller.unregister(client) + + if conn.initialized: + # remove the connection from keepalive + try: + self._keep.remove(conn) + except ValueError: + # race condition + return + + # submit the connection to a worker + self.enqueue_req(conn) + + def murder_keepalived(self): + now = time.time() + while True: + with self._lock: + try: + # remove the connection from the queue + conn = self._keep.popleft() + except IndexError: + break + + delta = conn.timeout - now + if delta > 0: + # add the connection back to the queue + with self._lock: + self._keep.appendleft(conn) + break + else: + self.nr_conns -= 1 + # remove the socket from the poller + with self._lock: + try: + self.poller.unregister(conn.sock) + except EnvironmentError as e: + if e.errno != errno.EBADF: + raise + except KeyError: + # already removed by the system, continue + pass + except ValueError: + # already removed by the system continue + pass + + # close the socket + conn.close() + + def is_parent_alive(self): + # If our parent changed then we shut down. + if self.ppid != os.getppid(): + self.log.info("Parent changed, shutting down: %s", self) + return False + return True + + def run(self): + # init listeners, add them to the event loop + for sock in self.sockets: + sock.setblocking(False) + # a race condition during graceful shutdown may make the listener + # name unavailable in the request handler so capture it once here + server = sock.getsockname() + acceptor = partial(self.accept, server) + self.poller.register(sock, selectors.EVENT_READ, acceptor) + + while self.alive: + # notify the arbiter we are alive + self.notify() + + # can we accept more connections? + if self.nr_conns < self.worker_connections: + # wait for an event + events = self.poller.select(1.0) + for key, _ in events: + callback = key.data + callback(key.fileobj) + + # check (but do not wait) for finished requests + result = futures.wait(self.futures, timeout=0, + return_when=futures.FIRST_COMPLETED) + else: + # wait for a request to finish + result = futures.wait(self.futures, timeout=1.0, + return_when=futures.FIRST_COMPLETED) + + # clean up finished requests + for fut in result.done: + self.futures.remove(fut) + + if not self.is_parent_alive(): + break + + # handle keepalive timeouts + self.murder_keepalived() + + self.tpool.shutdown(False) + self.poller.close() + + for s in self.sockets: + s.close() + + futures.wait(self.futures, timeout=self.cfg.graceful_timeout) + + def finish_request(self, fs): + if fs.cancelled(): + self.nr_conns -= 1 + fs.conn.close() + return + + try: + (keepalive, conn) = fs.result() + # if the connection should be kept alived add it + # to the eventloop and record it + if keepalive and self.alive: + # flag the socket as non blocked + conn.sock.setblocking(False) + + # register the connection + conn.set_timeout() + with self._lock: + self._keep.append(conn) + + # add the socket to the event loop + self.poller.register(conn.sock, selectors.EVENT_READ, + partial(self.on_client_socket_readable, conn)) + else: + self.nr_conns -= 1 + conn.close() + except Exception: + # an exception happened, make sure to close the + # socket. + self.nr_conns -= 1 + fs.conn.close() + + def handle(self, conn): + keepalive = False + req = None + try: + req = next(conn.parser) + if not req: + return (False, conn) + + # handle the request + keepalive = self.handle_request(req, conn) + if keepalive: + return (keepalive, conn) + except http.errors.NoMoreData as e: + self.log.debug("Ignored premature client disconnection. %s", e) + + except StopIteration as e: + self.log.debug("Closing connection. %s", e) + except ssl.SSLError as e: + if e.args[0] == ssl.SSL_ERROR_EOF: + self.log.debug("ssl connection closed") + conn.sock.close() + else: + self.log.debug("Error processing SSL request.") + self.handle_error(req, conn.sock, conn.client, e) + + except EnvironmentError as e: + if e.errno not in (errno.EPIPE, errno.ECONNRESET, errno.ENOTCONN): + self.log.exception("Socket error processing request.") + else: + if e.errno == errno.ECONNRESET: + self.log.debug("Ignoring connection reset") + elif e.errno == errno.ENOTCONN: + self.log.debug("Ignoring socket not connected") + else: + self.log.debug("Ignoring connection epipe") + except Exception as e: + self.handle_error(req, conn.sock, conn.client, e) + + return (False, conn) + + def handle_request(self, req, conn): + environ = {} + resp = None + try: + self.cfg.pre_request(self, req) + request_start = datetime.now() + resp, environ = wsgi.create(req, conn.sock, conn.client, + conn.server, self.cfg) + environ["wsgi.multithread"] = True + self.nr += 1 + if self.nr >= self.max_requests: + if self.alive: + self.log.info("Autorestarting worker after current request.") + self.alive = False + resp.force_close() + + if not self.alive or not self.cfg.keepalive: + resp.force_close() + elif len(self._keep) >= self.max_keepalived: + resp.force_close() + + respiter = self.wsgi(environ, resp.start_response) + try: + if isinstance(respiter, environ['wsgi.file_wrapper']): + resp.write_file(respiter) + else: + for item in respiter: + resp.write(item) + + resp.close() + finally: + request_time = datetime.now() - request_start + self.log.access(resp, req, environ, request_time) + if hasattr(respiter, "close"): + respiter.close() + + if resp.should_close(): + self.log.debug("Closing connection.") + return False + except EnvironmentError: + # pass to next try-except level + util.reraise(*sys.exc_info()) + except Exception: + if resp and resp.headers_sent: + # If the requests have already been sent, we should close the + # connection to indicate the error. + self.log.exception("Error handling request") + try: + conn.sock.shutdown(socket.SHUT_RDWR) + conn.sock.close() + except EnvironmentError: + pass + raise StopIteration() + raise + finally: + try: + self.cfg.post_request(self, req, environ, resp) + except Exception: + self.log.exception("Exception in post_request hook") + + return True diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/gtornado.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/gtornado.py new file mode 100644 index 0000000..2850611 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/gtornado.py @@ -0,0 +1,167 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +import os +import sys + +try: + import tornado +except ImportError: + raise RuntimeError("You need tornado installed to use this worker.") +import tornado.web +import tornado.httpserver +from tornado.ioloop import IOLoop, PeriodicCallback +from tornado.wsgi import WSGIContainer +from gunicorn.workers.base import Worker +from gunicorn import __version__ as gversion +from gunicorn.sock import ssl_context + + +# Tornado 5.0 updated its IOLoop, and the `io_loop` arguments to many +# Tornado functions have been removed in Tornado 5.0. Also, they no +# longer store PeriodCallbacks in ioloop._callbacks. Instead we store +# them on our side, and use stop() on them when stopping the worker. +# See https://www.tornadoweb.org/en/stable/releases/v5.0.0.html#backwards-compatibility-notes +# for more details. +TORNADO5 = tornado.version_info >= (5, 0, 0) + + +class TornadoWorker(Worker): + + @classmethod + def setup(cls): + web = sys.modules.pop("tornado.web") + old_clear = web.RequestHandler.clear + + def clear(self): + old_clear(self) + if "Gunicorn" not in self._headers["Server"]: + self._headers["Server"] += " (Gunicorn/%s)" % gversion + web.RequestHandler.clear = clear + sys.modules["tornado.web"] = web + + def handle_exit(self, sig, frame): + if self.alive: + super().handle_exit(sig, frame) + + def handle_request(self): + self.nr += 1 + if self.alive and self.nr >= self.max_requests: + self.log.info("Autorestarting worker after current request.") + self.alive = False + + def watchdog(self): + if self.alive: + self.notify() + + if self.ppid != os.getppid(): + self.log.info("Parent changed, shutting down: %s", self) + self.alive = False + + def heartbeat(self): + if not self.alive: + if self.server_alive: + if hasattr(self, 'server'): + try: + self.server.stop() + except Exception: + pass + self.server_alive = False + else: + if TORNADO5: + for callback in self.callbacks: + callback.stop() + self.ioloop.stop() + else: + if not self.ioloop._callbacks: + self.ioloop.stop() + + def init_process(self): + # IOLoop cannot survive a fork or be shared across processes + # in any way. When multiple processes are being used, each process + # should create its own IOLoop. We should clear current IOLoop + # if exists before os.fork. + IOLoop.clear_current() + super().init_process() + + def run(self): + self.ioloop = IOLoop.instance() + self.alive = True + self.server_alive = False + + if TORNADO5: + self.callbacks = [] + self.callbacks.append(PeriodicCallback(self.watchdog, 1000)) + self.callbacks.append(PeriodicCallback(self.heartbeat, 1000)) + for callback in self.callbacks: + callback.start() + else: + PeriodicCallback(self.watchdog, 1000, io_loop=self.ioloop).start() + PeriodicCallback(self.heartbeat, 1000, io_loop=self.ioloop).start() + + # Assume the app is a WSGI callable if its not an + # instance of tornado.web.Application or is an + # instance of tornado.wsgi.WSGIApplication + app = self.wsgi + + if tornado.version_info[0] < 6: + if not isinstance(app, tornado.web.Application) or \ + isinstance(app, tornado.wsgi.WSGIApplication): + app = WSGIContainer(app) + elif not isinstance(app, WSGIContainer) and \ + not isinstance(app, tornado.web.Application): + app = WSGIContainer(app) + + # Monkey-patching HTTPConnection.finish to count the + # number of requests being handled by Tornado. This + # will help gunicorn shutdown the worker if max_requests + # is exceeded. + httpserver = sys.modules["tornado.httpserver"] + if hasattr(httpserver, 'HTTPConnection'): + old_connection_finish = httpserver.HTTPConnection.finish + + def finish(other): + self.handle_request() + old_connection_finish(other) + httpserver.HTTPConnection.finish = finish + sys.modules["tornado.httpserver"] = httpserver + + server_class = tornado.httpserver.HTTPServer + else: + + class _HTTPServer(tornado.httpserver.HTTPServer): + + def on_close(instance, server_conn): + self.handle_request() + super(_HTTPServer, instance).on_close(server_conn) + + server_class = _HTTPServer + + if self.cfg.is_ssl: + if TORNADO5: + server = server_class(app, ssl_options=ssl_context(self.cfg)) + else: + server = server_class(app, io_loop=self.ioloop, + ssl_options=ssl_context(self.cfg)) + else: + if TORNADO5: + server = server_class(app) + else: + server = server_class(app, io_loop=self.ioloop) + + self.server = server + self.server_alive = True + + for s in self.sockets: + s.setblocking(0) + if hasattr(server, "add_socket"): # tornado > 2.0 + server.add_socket(s) + elif hasattr(server, "_sockets"): # tornado 2.0 + server._sockets[s.fileno()] = s + + server.no_keep_alive = self.cfg.keepalive <= 0 + server.start(num_processes=1) + + self.ioloop.start() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/sync.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/sync.py new file mode 100644 index 0000000..39a209f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/sync.py @@ -0,0 +1,210 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. +# + +from datetime import datetime +import errno +import os +import select +import socket +import ssl +import sys + +from gunicorn import http +from gunicorn.http import wsgi +from gunicorn import sock +from gunicorn import util +from gunicorn.workers import base + + +class StopWaiting(Exception): + """ exception raised to stop waiting for a connection """ + + +class SyncWorker(base.Worker): + + def accept(self, listener): + client, addr = listener.accept() + client.setblocking(1) + util.close_on_exec(client) + self.handle(listener, client, addr) + + def wait(self, timeout): + try: + self.notify() + ret = select.select(self.wait_fds, [], [], timeout) + if ret[0]: + if self.PIPE[0] in ret[0]: + os.read(self.PIPE[0], 1) + return ret[0] + + except select.error as e: + if e.args[0] == errno.EINTR: + return self.sockets + if e.args[0] == errno.EBADF: + if self.nr < 0: + return self.sockets + else: + raise StopWaiting + raise + + def is_parent_alive(self): + # If our parent changed then we shut down. + if self.ppid != os.getppid(): + self.log.info("Parent changed, shutting down: %s", self) + return False + return True + + def run_for_one(self, timeout): + listener = self.sockets[0] + while self.alive: + self.notify() + + # Accept a connection. If we get an error telling us + # that no connection is waiting we fall down to the + # select which is where we'll wait for a bit for new + # workers to come give us some love. + try: + self.accept(listener) + # Keep processing clients until no one is waiting. This + # prevents the need to select() for every client that we + # process. + continue + + except EnvironmentError as e: + if e.errno not in (errno.EAGAIN, errno.ECONNABORTED, + errno.EWOULDBLOCK): + raise + + if not self.is_parent_alive(): + return + + try: + self.wait(timeout) + except StopWaiting: + return + + def run_for_multiple(self, timeout): + while self.alive: + self.notify() + + try: + ready = self.wait(timeout) + except StopWaiting: + return + + if ready is not None: + for listener in ready: + if listener == self.PIPE[0]: + continue + + try: + self.accept(listener) + except EnvironmentError as e: + if e.errno not in (errno.EAGAIN, errno.ECONNABORTED, + errno.EWOULDBLOCK): + raise + + if not self.is_parent_alive(): + return + + def run(self): + # if no timeout is given the worker will never wait and will + # use the CPU for nothing. This minimal timeout prevent it. + timeout = self.timeout or 0.5 + + # self.socket appears to lose its blocking status after + # we fork in the arbiter. Reset it here. + for s in self.sockets: + s.setblocking(0) + + if len(self.sockets) > 1: + self.run_for_multiple(timeout) + else: + self.run_for_one(timeout) + + def handle(self, listener, client, addr): + req = None + try: + if self.cfg.is_ssl: + client = sock.ssl_wrap_socket(client, self.cfg) + parser = http.RequestParser(self.cfg, client, addr) + req = next(parser) + self.handle_request(listener, req, client, addr) + except http.errors.NoMoreData as e: + self.log.debug("Ignored premature client disconnection. %s", e) + except StopIteration as e: + self.log.debug("Closing connection. %s", e) + except ssl.SSLError as e: + if e.args[0] == ssl.SSL_ERROR_EOF: + self.log.debug("ssl connection closed") + client.close() + else: + self.log.debug("Error processing SSL request.") + self.handle_error(req, client, addr, e) + except EnvironmentError as e: + if e.errno not in (errno.EPIPE, errno.ECONNRESET, errno.ENOTCONN): + self.log.exception("Socket error processing request.") + else: + if e.errno == errno.ECONNRESET: + self.log.debug("Ignoring connection reset") + elif e.errno == errno.ENOTCONN: + self.log.debug("Ignoring socket not connected") + else: + self.log.debug("Ignoring EPIPE") + except Exception as e: + self.handle_error(req, client, addr, e) + finally: + util.close(client) + + def handle_request(self, listener, req, client, addr): + environ = {} + resp = None + try: + self.cfg.pre_request(self, req) + request_start = datetime.now() + resp, environ = wsgi.create(req, client, addr, + listener.getsockname(), self.cfg) + # Force the connection closed until someone shows + # a buffering proxy that supports Keep-Alive to + # the backend. + resp.force_close() + self.nr += 1 + if self.nr >= self.max_requests: + self.log.info("Autorestarting worker after current request.") + self.alive = False + respiter = self.wsgi(environ, resp.start_response) + try: + if isinstance(respiter, environ['wsgi.file_wrapper']): + resp.write_file(respiter) + else: + for item in respiter: + resp.write(item) + resp.close() + finally: + request_time = datetime.now() - request_start + self.log.access(resp, req, environ, request_time) + if hasattr(respiter, "close"): + respiter.close() + except EnvironmentError: + # pass to next try-except level + util.reraise(*sys.exc_info()) + except Exception: + if resp and resp.headers_sent: + # If the requests have already been sent, we should close the + # connection to indicate the error. + self.log.exception("Error handling request") + try: + client.shutdown(socket.SHUT_RDWR) + client.close() + except EnvironmentError: + pass + raise StopIteration() + raise + finally: + try: + self.cfg.post_request(self, req, environ, resp) + except Exception: + self.log.exception("Exception in post_request hook") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/workertmp.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/workertmp.py new file mode 100644 index 0000000..cc79ecd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/gunicorn/workers/workertmp.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 - +# +# This file is part of gunicorn released under the MIT license. +# See the NOTICE for more information. + +import os +import platform +import tempfile + +from gunicorn import util + +PLATFORM = platform.system() +IS_CYGWIN = PLATFORM.startswith('CYGWIN') + + +class WorkerTmp(object): + + def __init__(self, cfg): + old_umask = os.umask(cfg.umask) + fdir = cfg.worker_tmp_dir + if fdir and not os.path.isdir(fdir): + raise RuntimeError("%s doesn't exist. Can't create workertmp." % fdir) + fd, name = tempfile.mkstemp(prefix="wgunicorn-", dir=fdir) + os.umask(old_umask) + + # change the owner and group of the file if the worker will run as + # a different user or group, so that the worker can modify the file + if cfg.uid != os.geteuid() or cfg.gid != os.getegid(): + util.chown(name, cfg.uid, cfg.gid) + + # unlink the file so we don't leak temporary files + try: + if not IS_CYGWIN: + util.unlink(name) + # In Python 3.8, open() emits RuntimeWarning if buffering=1 for binary mode. + # Because we never write to this file, pass 0 to switch buffering off. + self._tmp = os.fdopen(fd, 'w+b', 0) + except Exception: + os.close(fd) + raise + + self.spinner = 0 + + def notify(self): + self.spinner = (self.spinner + 1) % 2 + os.fchmod(self._tmp.fileno(), self.spinner) + + def last_update(self): + return os.fstat(self._tmp.fileno()).st_ctime + + def fileno(self): + return self._tmp.fileno() + + def close(self): + return self._tmp.close() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging-26.2.dist-info/INSTALLER b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging-26.2.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging-26.2.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging-26.2.dist-info/METADATA b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging-26.2.dist-info/METADATA new file mode 100644 index 0000000..d7ca456 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging-26.2.dist-info/METADATA @@ -0,0 +1,112 @@ +Metadata-Version: 2.4 +Name: packaging +Version: 26.2 +Summary: Core utilities for Python packages +Author-email: Donald Stufft +Requires-Python: >=3.8 +Description-Content-Type: text/x-rst +License-Expression: Apache-2.0 OR BSD-2-Clause +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 +Classifier: Programming Language :: Python :: 3.14 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Programming Language :: Python :: Free Threading :: 4 - Resilient +Classifier: Typing :: Typed +License-File: LICENSE +License-File: LICENSE.APACHE +License-File: LICENSE.BSD +Project-URL: Documentation, https://packaging.pypa.io/ +Project-URL: Source, https://github.com/pypa/packaging + +packaging +========= + +.. start-intro + +Reusable core utilities for various Python Packaging +`interoperability specifications `_. + +This library provides utilities that implement the interoperability +specifications which have clearly one correct behaviour (eg: :pep:`440`) +or benefit greatly from having a single shared implementation (eg: :pep:`425`). + +.. end-intro + +The ``packaging`` project includes the following: version handling, specifiers, +markers, requirements, tags, metadata, lockfiles, utilities. + +Documentation +------------- + +The `documentation`_ provides information and the API for the following: + +- Version Handling +- Specifiers +- Markers +- Licenses +- Requirements +- Metadata +- Tags +- Lockfiles (pylock) +- Direct URL helpers +- Dependency groups +- Errors +- Utilities + +Installation +------------ + +Use ``pip`` to install these utilities:: + + pip install packaging + +The ``packaging`` library uses calendar-based versioning (``YY.N``). + +Discussion +---------- + +If you run into bugs, you can file them in our `issue tracker`_. + +You can also join discussions on `GitHub Discussions`_ to ask questions or get involved. + +.. _`documentation`: https://packaging.pypa.io/ +.. _`issue tracker`: https://github.com/pypa/packaging/issues +.. _`GitHub Discussions`: https://github.com/pypa/packaging/discussions + + +Code of Conduct +--------------- + +Everyone interacting in the packaging project's codebases, issue trackers, chat +rooms, and mailing lists is expected to follow the `PSF Code of Conduct`_. + +.. _PSF Code of Conduct: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md + +Contributing +------------ + +The ``CONTRIBUTING.rst`` file outlines how to contribute to this project as +well as how to report a potential security issue. The documentation for this +project also covers information about `project development`_ and `security`_. + +.. _`project development`: https://packaging.pypa.io/en/latest/development/ +.. _`security`: https://packaging.pypa.io/en/latest/security/ + +Project History +--------------- + +Please review the ``CHANGELOG.rst`` file or the `Changelog documentation`_ for +recent changes and project history. + +.. _`Changelog documentation`: https://packaging.pypa.io/en/latest/changelog/ + diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging-26.2.dist-info/RECORD b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging-26.2.dist-info/RECORD new file mode 100644 index 0000000..96be826 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging-26.2.dist-info/RECORD @@ -0,0 +1,28 @@ +packaging-26.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +packaging-26.2.dist-info/METADATA,sha256=T5y815M0FaR5P3dnyYoralEsgj_IHIczeBVwXyMOyr8,3543 +packaging-26.2.dist-info/RECORD,, +packaging-26.2.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82 +packaging-26.2.dist-info/licenses/LICENSE,sha256=ytHvW9NA1z4HS6YU0m996spceUDD2MNIUuZcSQlobEg,197 +packaging-26.2.dist-info/licenses/LICENSE.APACHE,sha256=DVQuDIgE45qn836wDaWnYhSdxoLXgpRRKH4RuTjpRZQ,10174 +packaging-26.2.dist-info/licenses/LICENSE.BSD,sha256=tw5-m3QvHMb5SLNMFqo5_-zpQZY2S8iP8NIYDwAo-sU,1344 +packaging/__init__.py,sha256=QhMEdPu2XogrJzV3S0KWS6t7l0I9k8EeDRJl4fnw87s,494 +packaging/_elffile.py,sha256=-sKkptYqzYw2-x3QByJa5mB4rfPWu1pxkZHRx1WAFCY,3211 +packaging/_manylinux.py,sha256=Hf6nB0cOrayEs96-p3oIXAgGnFquv20DO5l-o2_Xnv0,9559 +packaging/_musllinux.py,sha256=Z6swjH3MA7XS3qXnmMN7QPhqP3fnoYI0eQ18e9-HgAE,2707 +packaging/_parser.py,sha256=Kf2nsDw4c54X82pY8ba4F02Bve6OygGMAjL-Begqcew,11698 +packaging/_structures.py,sha256=60jRbF78p8z5MKnNd6cAprgOadCJHV0DlmUmRBqFZcs,1109 +packaging/_tokenizer.py,sha256=tFU2Wr-ZZJdAbkXLEJo7qUQDJaIkfft9DqaifiEND7A,5391 +packaging/dependency_groups.py,sha256=XZIAVFK9uHG4RCGprmJn3VInUWMesxha_kytJuMO9eY,10218 +packaging/direct_url.py,sha256=eKmbDiPP1sLV4Mj_kCSZqqknrIyVO9Sr7JpF8KCjp4U,10917 +packaging/errors.py,sha256=6hfEYXAf8v_IF65-lFadJOMIieBP2xIKtyEXjG1nGIs,2680 +packaging/licenses/__init__.py,sha256=_Jx0XRiD_58palsWnyLrLuh59ZpGCPIPXLKdZo9OJvQ,7293 +packaging/licenses/_spdx.py,sha256=WW7DXiyg68up_YND_wpRYlr1SHhiV4FfJLQffghhMxQ,51122 +packaging/markers.py,sha256=8fDIUhAF6YMnCNB5FSiwh9pEIusiFzAF73J-0OB8bTk,17055 +packaging/metadata.py,sha256=crAh0E3GVGVqPlu6EdRFsaG-Y6UYznTUqjuGKRGPv6c,38770 +packaging/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +packaging/pylock.py,sha256=G_1gncTmDbRLY1jo4VDI9Uw-b5IErh_Q9V_BbVJTmD8,33890 +packaging/requirements.py,sha256=dd1c9aa1gp5NI6btF6UFRQjPn1nxQXnE_T34yDDTEpc,4383 +packaging/specifiers.py,sha256=Mfp8avQg0lVot17to9lVKBtZD1FsWBTItoGwFUZ3wtg,71514 +packaging/tags.py,sha256=NQ1weo69_Sjte3xBZ1I_G63CIgCmaN0C24mz-z3hGYo,34224 +packaging/utils.py,sha256=M7-JMKic2sP1YtV_8aW7eVGB-x3ADuKCiSrsVeCd2Uo,9848 +packaging/version.py,sha256=Y1aTtxe3sn2xOMa5BdI85-AcHuybbanOVkEvvSRRC8I,38369 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging-26.2.dist-info/WHEEL b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging-26.2.dist-info/WHEEL new file mode 100644 index 0000000..d8b9936 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging-26.2.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.12.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging-26.2.dist-info/licenses/LICENSE b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging-26.2.dist-info/licenses/LICENSE new file mode 100644 index 0000000..6f62d44 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging-26.2.dist-info/licenses/LICENSE @@ -0,0 +1,3 @@ +This software is made available under the terms of *either* of the licenses +found in LICENSE.APACHE or LICENSE.BSD. Contributions to this software is made +under the terms of *both* these licenses. diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging-26.2.dist-info/licenses/LICENSE.APACHE b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging-26.2.dist-info/licenses/LICENSE.APACHE new file mode 100644 index 0000000..f433b1a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging-26.2.dist-info/licenses/LICENSE.APACHE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging-26.2.dist-info/licenses/LICENSE.BSD b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging-26.2.dist-info/licenses/LICENSE.BSD new file mode 100644 index 0000000..42ce7b7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging-26.2.dist-info/licenses/LICENSE.BSD @@ -0,0 +1,23 @@ +Copyright (c) Donald Stufft and individual contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/__init__.py new file mode 100644 index 0000000..a6bdf59 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/__init__.py @@ -0,0 +1,15 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +__title__ = "packaging" +__summary__ = "Core utilities for Python packages" +__uri__ = "https://github.com/pypa/packaging" + +__version__ = "26.2" + +__author__ = "Donald Stufft and individual contributors" +__email__ = "donald@stufft.io" + +__license__ = "BSD-2-Clause or Apache-2.0" +__copyright__ = f"2014 {__author__}" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/_elffile.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/_elffile.py new file mode 100644 index 0000000..497b064 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/_elffile.py @@ -0,0 +1,108 @@ +""" +ELF file parser. + +This provides a class ``ELFFile`` that parses an ELF executable in a similar +interface to ``ZipFile``. Only the read interface is implemented. + +ELF header: https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.eheader.html +""" + +from __future__ import annotations + +import enum +import os +import struct +from typing import IO + + +class ELFInvalid(ValueError): + pass + + +class EIClass(enum.IntEnum): + C32 = 1 + C64 = 2 + + +class EIData(enum.IntEnum): + Lsb = 1 + Msb = 2 + + +class EMachine(enum.IntEnum): + I386 = 3 + S390 = 22 + Arm = 40 + X8664 = 62 + AArc64 = 183 + + +class ELFFile: + """ + Representation of an ELF executable. + """ + + def __init__(self, f: IO[bytes]) -> None: + self._f = f + + try: + ident = self._read("16B") + except struct.error as e: + raise ELFInvalid("unable to parse identification") from e + magic = bytes(ident[:4]) + if magic != b"\x7fELF": + raise ELFInvalid(f"invalid magic: {magic!r}") + + self.capacity = ident[4] # Format for program header (bitness). + self.encoding = ident[5] # Data structure encoding (endianness). + + try: + # e_fmt: Format for program header. + # p_fmt: Format for section header. + # p_idx: Indexes to find p_type, p_offset, and p_filesz. + e_fmt, self._p_fmt, self._p_idx = { + (1, 1): ("HHIIIIIHHH", ">IIIIIIII", (0, 1, 4)), # 32-bit MSB. + (2, 1): ("HHIQQQIHHH", ">IIQQQQQQ", (0, 2, 5)), # 64-bit MSB. + }[(self.capacity, self.encoding)] + except KeyError as e: + raise ELFInvalid( + f"unrecognized capacity ({self.capacity}) or encoding ({self.encoding})" + ) from e + + try: + ( + _, + self.machine, # Architecture type. + _, + _, + self._e_phoff, # Offset of program header. + _, + self.flags, # Processor-specific flags. + _, + self._e_phentsize, # Size of section. + self._e_phnum, # Number of sections. + ) = self._read(e_fmt) + except struct.error as e: + raise ELFInvalid("unable to parse machine and section information") from e + + def _read(self, fmt: str) -> tuple[int, ...]: + return struct.unpack(fmt, self._f.read(struct.calcsize(fmt))) + + @property + def interpreter(self) -> str | None: + """ + The path recorded in the ``PT_INTERP`` section header. + """ + for index in range(self._e_phnum): + self._f.seek(self._e_phoff + self._e_phentsize * index) + try: + data = self._read(self._p_fmt) + except struct.error: + continue + if data[self._p_idx[0]] != 3: # Not PT_INTERP. + continue + self._f.seek(data[self._p_idx[1]]) + return os.fsdecode(self._f.read(data[self._p_idx[2]])).strip("\0") + return None diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/_manylinux.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/_manylinux.py new file mode 100644 index 0000000..0e79e8a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/_manylinux.py @@ -0,0 +1,262 @@ +from __future__ import annotations + +import collections +import contextlib +import functools +import os +import re +import sys +import warnings +from typing import Generator, Iterator, NamedTuple, Sequence + +from ._elffile import EIClass, EIData, ELFFile, EMachine + +EF_ARM_ABIMASK = 0xFF000000 +EF_ARM_ABI_VER5 = 0x05000000 +EF_ARM_ABI_FLOAT_HARD = 0x00000400 + +_ALLOWED_ARCHS = { + "x86_64", + "aarch64", + "ppc64", + "ppc64le", + "s390x", + "loongarch64", + "riscv64", +} + + +# `os.PathLike` not a generic type until Python 3.9, so sticking with `str` +# as the type for `path` until then. +@contextlib.contextmanager +def _parse_elf(path: str) -> Generator[ELFFile | None, None, None]: + try: + with open(path, "rb") as f: + yield ELFFile(f) + except (OSError, TypeError, ValueError): + yield None + + +def _is_linux_armhf(executable: str) -> bool: + # hard-float ABI can be detected from the ELF header of the running + # process + # https://static.docs.arm.com/ihi0044/g/aaelf32.pdf + with _parse_elf(executable) as f: + return ( + f is not None + and f.capacity == EIClass.C32 + and f.encoding == EIData.Lsb + and f.machine == EMachine.Arm + and f.flags & EF_ARM_ABIMASK == EF_ARM_ABI_VER5 + and f.flags & EF_ARM_ABI_FLOAT_HARD == EF_ARM_ABI_FLOAT_HARD + ) + + +def _is_linux_i686(executable: str) -> bool: + with _parse_elf(executable) as f: + return ( + f is not None + and f.capacity == EIClass.C32 + and f.encoding == EIData.Lsb + and f.machine == EMachine.I386 + ) + + +def _have_compatible_abi(executable: str, archs: Sequence[str]) -> bool: + if "armv7l" in archs: + return _is_linux_armhf(executable) + if "i686" in archs: + return _is_linux_i686(executable) + return any(arch in _ALLOWED_ARCHS for arch in archs) + + +# If glibc ever changes its major version, we need to know what the last +# minor version was, so we can build the complete list of all versions. +# For now, guess what the highest minor version might be, assume it will +# be 50 for testing. Once this actually happens, update the dictionary +# with the actual value. +_LAST_GLIBC_MINOR: dict[int, int] = collections.defaultdict(lambda: 50) + + +class _GLibCVersion(NamedTuple): + major: int + minor: int + + +def _glibc_version_string_confstr() -> str | None: + """ + Primary implementation of glibc_version_string using os.confstr. + """ + # os.confstr is quite a bit faster than ctypes.DLL. It's also less likely + # to be broken or missing. This strategy is used in the standard library + # platform module. + # https://github.com/python/cpython/blob/fcf1d003bf4f0100c/Lib/platform.py#L175-L183 + try: + # Should be a string like "glibc 2.17". + version_string: str | None = os.confstr("CS_GNU_LIBC_VERSION") + assert version_string is not None + _, version = version_string.rsplit() + except (AssertionError, AttributeError, OSError, ValueError): + # os.confstr() or CS_GNU_LIBC_VERSION not available (or a bad value)... + return None + return version + + +def _glibc_version_string_ctypes() -> str | None: + """ + Fallback implementation of glibc_version_string using ctypes. + """ + try: + import ctypes # noqa: PLC0415 + except ImportError: + return None + + # ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen + # manpage says, "If filename is NULL, then the returned handle is for the + # main program". This way we can let the linker do the work to figure out + # which libc our process is actually using. + # + # We must also handle the special case where the executable is not a + # dynamically linked executable. This can occur when using musl libc, + # for example. In this situation, dlopen() will error, leading to an + # OSError. Interestingly, at least in the case of musl, there is no + # errno set on the OSError. The single string argument used to construct + # OSError comes from libc itself and is therefore not portable to + # hard code here. In any case, failure to call dlopen() means we + # can proceed, so we bail on our attempt. + try: + process_namespace = ctypes.CDLL(None) + except OSError: + return None + + try: + gnu_get_libc_version = process_namespace.gnu_get_libc_version + except AttributeError: + # Symbol doesn't exist -> therefore, we are not linked to + # glibc. + return None + + # Call gnu_get_libc_version, which returns a string like "2.5" + gnu_get_libc_version.restype = ctypes.c_char_p + version_str: str = gnu_get_libc_version() + # py2 / py3 compatibility: + if not isinstance(version_str, str): + version_str = version_str.decode("ascii") + + return version_str + + +def _glibc_version_string() -> str | None: + """Returns glibc version string, or None if not using glibc.""" + return _glibc_version_string_confstr() or _glibc_version_string_ctypes() + + +def _parse_glibc_version(version_str: str) -> _GLibCVersion: + """Parse glibc version. + + We use a regexp instead of str.split because we want to discard any + random junk that might come after the minor version -- this might happen + in patched/forked versions of glibc (e.g. Linaro's version of glibc + uses version strings like "2.20-2014.11"). See gh-3588. + """ + m = re.match(r"(?P[0-9]+)\.(?P[0-9]+)", version_str) + if not m: + warnings.warn( + f"Expected glibc version with 2 components major.minor, got: {version_str}", + RuntimeWarning, + stacklevel=2, + ) + return _GLibCVersion(-1, -1) + return _GLibCVersion(int(m.group("major")), int(m.group("minor"))) + + +@functools.lru_cache +def _get_glibc_version() -> _GLibCVersion: + version_str = _glibc_version_string() + if version_str is None: + return _GLibCVersion(-1, -1) + return _parse_glibc_version(version_str) + + +# From PEP 513, PEP 600 +def _is_compatible(arch: str, version: _GLibCVersion) -> bool: + sys_glibc = _get_glibc_version() + if sys_glibc < version: + return False + # Check for presence of _manylinux module. + try: + import _manylinux # noqa: PLC0415 + except ImportError: + return True + if hasattr(_manylinux, "manylinux_compatible"): + result = _manylinux.manylinux_compatible(version[0], version[1], arch) + if result is not None: + return bool(result) + return True + if version == _GLibCVersion(2, 5) and hasattr(_manylinux, "manylinux1_compatible"): + return bool(_manylinux.manylinux1_compatible) + if version == _GLibCVersion(2, 12) and hasattr( + _manylinux, "manylinux2010_compatible" + ): + return bool(_manylinux.manylinux2010_compatible) + if version == _GLibCVersion(2, 17) and hasattr( + _manylinux, "manylinux2014_compatible" + ): + return bool(_manylinux.manylinux2014_compatible) + return True + + +_LEGACY_MANYLINUX_MAP: dict[_GLibCVersion, str] = { + # CentOS 7 w/ glibc 2.17 (PEP 599) + _GLibCVersion(2, 17): "manylinux2014", + # CentOS 6 w/ glibc 2.12 (PEP 571) + _GLibCVersion(2, 12): "manylinux2010", + # CentOS 5 w/ glibc 2.5 (PEP 513) + _GLibCVersion(2, 5): "manylinux1", +} + + +def platform_tags(archs: Sequence[str]) -> Iterator[str]: + """Generate manylinux tags compatible to the current platform. + + :param archs: Sequence of compatible architectures. + The first one shall be the closest to the actual architecture and be the part of + platform tag after the ``linux_`` prefix, e.g. ``x86_64``. + The ``linux_`` prefix is assumed as a prerequisite for the current platform to + be manylinux-compatible. + + :returns: An iterator of compatible manylinux tags. + """ + if not _have_compatible_abi(sys.executable, archs): + return + # Oldest glibc to be supported regardless of architecture is (2, 17). + too_old_glibc2 = _GLibCVersion(2, 16) + if set(archs) & {"x86_64", "i686"}: + # On x86/i686 also oldest glibc to be supported is (2, 5). + too_old_glibc2 = _GLibCVersion(2, 4) + current_glibc = _GLibCVersion(*_get_glibc_version()) + glibc_max_list = [current_glibc] + # We can assume compatibility across glibc major versions. + # https://sourceware.org/bugzilla/show_bug.cgi?id=24636 + # + # Build a list of maximum glibc versions so that we can + # output the canonical list of all glibc from current_glibc + # down to too_old_glibc2, including all intermediary versions. + for glibc_major in range(current_glibc.major - 1, 1, -1): + glibc_minor = _LAST_GLIBC_MINOR[glibc_major] + glibc_max_list.append(_GLibCVersion(glibc_major, glibc_minor)) + for arch in archs: + for glibc_max in glibc_max_list: + if glibc_max.major == too_old_glibc2.major: + min_minor = too_old_glibc2.minor + else: + # For other glibc major versions oldest supported is (x, 0). + min_minor = -1 + for glibc_minor in range(glibc_max.minor, min_minor, -1): + glibc_version = _GLibCVersion(glibc_max.major, glibc_minor) + if _is_compatible(arch, glibc_version): + yield "manylinux_{}_{}_{}".format(*glibc_version, arch) + + # Handle the legacy manylinux1, manylinux2010, manylinux2014 tags. + if legacy_tag := _LEGACY_MANYLINUX_MAP.get(glibc_version): + yield f"{legacy_tag}_{arch}" diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/_musllinux.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/_musllinux.py new file mode 100644 index 0000000..4e8116a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/_musllinux.py @@ -0,0 +1,85 @@ +"""PEP 656 support. + +This module implements logic to detect if the currently running Python is +linked against musl, and what musl version is used. +""" + +from __future__ import annotations + +import functools +import re +import subprocess +import sys +from typing import Iterator, NamedTuple, Sequence + +from ._elffile import ELFFile + + +class _MuslVersion(NamedTuple): + major: int + minor: int + + +def _parse_musl_version(output: str) -> _MuslVersion | None: + lines = [n for n in (n.strip() for n in output.splitlines()) if n] + if len(lines) < 2 or lines[0][:4] != "musl": + return None + m = re.match(r"Version (\d+)\.(\d+)", lines[1]) + if not m: + return None + return _MuslVersion(major=int(m.group(1)), minor=int(m.group(2))) + + +@functools.lru_cache +def _get_musl_version(executable: str) -> _MuslVersion | None: + """Detect currently-running musl runtime version. + + This is done by checking the specified executable's dynamic linking + information, and invoking the loader to parse its output for a version + string. If the loader is musl, the output would be something like:: + + musl libc (x86_64) + Version 1.2.2 + Dynamic Program Loader + """ + try: + with open(executable, "rb") as f: + ld = ELFFile(f).interpreter + except (OSError, TypeError, ValueError): + return None + if ld is None or "musl" not in ld: + return None + proc = subprocess.run([ld], check=False, stderr=subprocess.PIPE, text=True) + return _parse_musl_version(proc.stderr) + + +def platform_tags(archs: Sequence[str]) -> Iterator[str]: + """Generate musllinux tags compatible to the current platform. + + :param archs: Sequence of compatible architectures. + The first one shall be the closest to the actual architecture and be the part of + platform tag after the ``linux_`` prefix, e.g. ``x86_64``. + The ``linux_`` prefix is assumed as a prerequisite for the current platform to + be musllinux-compatible. + + :returns: An iterator of compatible musllinux tags. + """ + sys_musl = _get_musl_version(sys.executable) + if sys_musl is None: # Python not dynamically linked against musl. + return + for arch in archs: + for minor in range(sys_musl.minor, -1, -1): + yield f"musllinux_{sys_musl.major}_{minor}_{arch}" + + +if __name__ == "__main__": # pragma: no cover + import sysconfig + + plat = sysconfig.get_platform() + assert plat.startswith("linux-"), "not linux" + + print("plat:", plat) + print("musl:", _get_musl_version(sys.executable)) + print("tags:", end=" ") + for t in platform_tags(re.sub(r"[.-]", "_", plat.split("-", 1)[-1])): + print(t, end="\n ") diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/_parser.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/_parser.py new file mode 100644 index 0000000..d320269 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/_parser.py @@ -0,0 +1,393 @@ +"""Handwritten parser of dependency specifiers. + +The docstring for each __parse_* function contains EBNF-inspired grammar representing +the implementation. +""" + +from __future__ import annotations + +import ast +from typing import List, Literal, NamedTuple, Sequence, Tuple, Union + +from ._tokenizer import DEFAULT_RULES, Tokenizer + + +class Node: + __slots__ = ("value",) + + def __init__(self, value: str) -> None: + self.value = value + + def __str__(self) -> str: + return self.value + + def __repr__(self) -> str: + return f"<{self.__class__.__name__}({self.value!r})>" + + def serialize(self) -> str: + raise NotImplementedError + + def __getstate__(self) -> str: + # Return just the value string for compactness and stability. + return self.value + + def _restore_value(self, value: object) -> None: + if not isinstance(value, str): + raise TypeError( + f"Cannot restore {self.__class__.__name__} value from {value!r}" + ) + self.value = value + + def __setstate__(self, state: object) -> None: + if isinstance(state, str): + # New format (26.2+): just the value string. + self._restore_value(state) + return + if isinstance(state, tuple) and len(state) == 2: + # Old format (packaging <= 26.0, __slots__): (None, {slot: value}). + _, slot_dict = state + if isinstance(slot_dict, dict) and "value" in slot_dict: + self._restore_value(slot_dict["value"]) + return + if isinstance(state, dict) and "value" in state: + # Old format (packaging <= 25.0, no __slots__): plain __dict__. + self._restore_value(state["value"]) + return + raise TypeError(f"Cannot restore {self.__class__.__name__} from {state!r}") + + +class Variable(Node): + __slots__ = () + + def serialize(self) -> str: + return str(self) + + +class Value(Node): + __slots__ = () + + def serialize(self) -> str: + return f'"{self}"' + + +class Op(Node): + __slots__ = () + + def serialize(self) -> str: + return str(self) + + +MarkerLogical = Literal["and", "or"] +MarkerVar = Union[Variable, Value] +MarkerItem = Tuple[MarkerVar, Op, MarkerVar] +MarkerAtom = Union[MarkerItem, Sequence["MarkerAtom"]] +MarkerList = List[Union["MarkerList", MarkerAtom, MarkerLogical]] + + +class ParsedRequirement(NamedTuple): + name: str + url: str + extras: list[str] + specifier: str + marker: MarkerList | None + + +# -------------------------------------------------------------------------------------- +# Recursive descent parser for dependency specifier +# -------------------------------------------------------------------------------------- +def parse_requirement(source: str) -> ParsedRequirement: + return _parse_requirement(Tokenizer(source, rules=DEFAULT_RULES)) + + +def _parse_requirement(tokenizer: Tokenizer) -> ParsedRequirement: + """ + requirement = WS? IDENTIFIER WS? extras WS? requirement_details + """ + tokenizer.consume("WS") + + name_token = tokenizer.expect( + "IDENTIFIER", expected="package name at the start of dependency specifier" + ) + name = name_token.text + tokenizer.consume("WS") + + extras = _parse_extras(tokenizer) + tokenizer.consume("WS") + + url, specifier, marker = _parse_requirement_details(tokenizer) + tokenizer.expect("END", expected="end of dependency specifier") + + return ParsedRequirement(name, url, extras, specifier, marker) + + +def _parse_requirement_details( + tokenizer: Tokenizer, +) -> tuple[str, str, MarkerList | None]: + """ + requirement_details = AT URL (WS requirement_marker?)? + | specifier WS? (requirement_marker)? + """ + + specifier = "" + url = "" + marker = None + + if tokenizer.check("AT"): + tokenizer.read() + tokenizer.consume("WS") + + url_start = tokenizer.position + url = tokenizer.expect("URL", expected="URL after @").text + if tokenizer.check("END", peek=True): + return (url, specifier, marker) + + tokenizer.expect("WS", expected="whitespace after URL") + + # The input might end after whitespace. + if tokenizer.check("END", peek=True): + return (url, specifier, marker) + + marker = _parse_requirement_marker( + tokenizer, + span_start=url_start, + expected="semicolon (after URL and whitespace)", + ) + else: + specifier_start = tokenizer.position + specifier = _parse_specifier(tokenizer) + tokenizer.consume("WS") + + if tokenizer.check("END", peek=True): + return (url, specifier, marker) + + marker = _parse_requirement_marker( + tokenizer, + span_start=specifier_start, + expected=( + "comma (within version specifier), semicolon (after version specifier)" + if specifier + else "semicolon (after name with no version specifier)" + ), + ) + + return (url, specifier, marker) + + +def _parse_requirement_marker( + tokenizer: Tokenizer, *, span_start: int, expected: str +) -> MarkerList: + """ + requirement_marker = SEMICOLON marker WS? + """ + + if not tokenizer.check("SEMICOLON"): + tokenizer.raise_syntax_error( + f"Expected {expected} or end", + span_start=span_start, + span_end=None, + ) + tokenizer.read() + + marker = _parse_marker(tokenizer) + tokenizer.consume("WS") + + return marker + + +def _parse_extras(tokenizer: Tokenizer) -> list[str]: + """ + extras = (LEFT_BRACKET wsp* extras_list? wsp* RIGHT_BRACKET)? + """ + if not tokenizer.check("LEFT_BRACKET", peek=True): + return [] + + with tokenizer.enclosing_tokens( + "LEFT_BRACKET", + "RIGHT_BRACKET", + around="extras", + ): + tokenizer.consume("WS") + extras = _parse_extras_list(tokenizer) + tokenizer.consume("WS") + + return extras + + +def _parse_extras_list(tokenizer: Tokenizer) -> list[str]: + """ + extras_list = identifier (wsp* ',' wsp* identifier)* + """ + extras: list[str] = [] + + if not tokenizer.check("IDENTIFIER"): + return extras + + extras.append(tokenizer.read().text) + + while True: + tokenizer.consume("WS") + if tokenizer.check("IDENTIFIER", peek=True): + tokenizer.raise_syntax_error("Expected comma between extra names") + elif not tokenizer.check("COMMA"): + break + + tokenizer.read() + tokenizer.consume("WS") + + extra_token = tokenizer.expect("IDENTIFIER", expected="extra name after comma") + extras.append(extra_token.text) + + return extras + + +def _parse_specifier(tokenizer: Tokenizer) -> str: + """ + specifier = LEFT_PARENTHESIS WS? version_many WS? RIGHT_PARENTHESIS + | WS? version_many WS? + """ + with tokenizer.enclosing_tokens( + "LEFT_PARENTHESIS", + "RIGHT_PARENTHESIS", + around="version specifier", + ): + tokenizer.consume("WS") + parsed_specifiers = _parse_version_many(tokenizer) + tokenizer.consume("WS") + + return parsed_specifiers + + +def _parse_version_many(tokenizer: Tokenizer) -> str: + """ + version_many = (SPECIFIER (WS? COMMA WS? SPECIFIER)*)? + """ + parsed_specifiers = "" + while tokenizer.check("SPECIFIER"): + span_start = tokenizer.position + parsed_specifiers += tokenizer.read().text + if tokenizer.check("VERSION_PREFIX_TRAIL", peek=True): + tokenizer.raise_syntax_error( + ".* suffix can only be used with `==` or `!=` operators", + span_start=span_start, + span_end=tokenizer.position + 1, + ) + if tokenizer.check("VERSION_LOCAL_LABEL_TRAIL", peek=True): + tokenizer.raise_syntax_error( + "Local version label can only be used with `==` or `!=` operators", + span_start=span_start, + span_end=tokenizer.position, + ) + tokenizer.consume("WS") + if not tokenizer.check("COMMA"): + break + parsed_specifiers += tokenizer.read().text + tokenizer.consume("WS") + + return parsed_specifiers + + +# -------------------------------------------------------------------------------------- +# Recursive descent parser for marker expression +# -------------------------------------------------------------------------------------- +def parse_marker(source: str) -> MarkerList: + return _parse_full_marker(Tokenizer(source, rules=DEFAULT_RULES)) + + +def _parse_full_marker(tokenizer: Tokenizer) -> MarkerList: + retval = _parse_marker(tokenizer) + tokenizer.expect("END", expected="end of marker expression") + return retval + + +def _parse_marker(tokenizer: Tokenizer) -> MarkerList: + """ + marker = marker_atom (BOOLOP marker_atom)+ + """ + expression = [_parse_marker_atom(tokenizer)] + while tokenizer.check("BOOLOP"): + token = tokenizer.read() + expr_right = _parse_marker_atom(tokenizer) + expression.extend((token.text, expr_right)) + return expression + + +def _parse_marker_atom(tokenizer: Tokenizer) -> MarkerAtom: + """ + marker_atom = WS? LEFT_PARENTHESIS WS? marker WS? RIGHT_PARENTHESIS WS? + | WS? marker_item WS? + """ + + tokenizer.consume("WS") + if tokenizer.check("LEFT_PARENTHESIS", peek=True): + with tokenizer.enclosing_tokens( + "LEFT_PARENTHESIS", + "RIGHT_PARENTHESIS", + around="marker expression", + ): + tokenizer.consume("WS") + marker: MarkerAtom = _parse_marker(tokenizer) + tokenizer.consume("WS") + else: + marker = _parse_marker_item(tokenizer) + tokenizer.consume("WS") + return marker + + +def _parse_marker_item(tokenizer: Tokenizer) -> MarkerItem: + """ + marker_item = WS? marker_var WS? marker_op WS? marker_var WS? + """ + tokenizer.consume("WS") + marker_var_left = _parse_marker_var(tokenizer) + tokenizer.consume("WS") + marker_op = _parse_marker_op(tokenizer) + tokenizer.consume("WS") + marker_var_right = _parse_marker_var(tokenizer) + tokenizer.consume("WS") + return (marker_var_left, marker_op, marker_var_right) + + +def _parse_marker_var(tokenizer: Tokenizer) -> MarkerVar: # noqa: RET503 + """ + marker_var = VARIABLE | QUOTED_STRING + """ + if tokenizer.check("VARIABLE"): + return process_env_var(tokenizer.read().text.replace(".", "_")) + elif tokenizer.check("QUOTED_STRING"): + return process_python_str(tokenizer.read().text) + else: + tokenizer.raise_syntax_error( + message="Expected a marker variable or quoted string" + ) + + +def process_env_var(env_var: str) -> Variable: + if env_var in ("platform_python_implementation", "python_implementation"): + return Variable("platform_python_implementation") + else: + return Variable(env_var) + + +def process_python_str(python_str: str) -> Value: + value = ast.literal_eval(python_str) + return Value(str(value)) + + +def _parse_marker_op(tokenizer: Tokenizer) -> Op: + """ + marker_op = IN | NOT IN | OP + """ + if tokenizer.check("IN"): + tokenizer.read() + return Op("in") + elif tokenizer.check("NOT"): + tokenizer.read() + tokenizer.expect("WS", expected="whitespace after 'not'") + tokenizer.expect("IN", expected="'in' after 'not'") + return Op("not in") + elif tokenizer.check("OP"): + return Op(tokenizer.read().text) + else: + return tokenizer.raise_syntax_error( + "Expected marker operator, one of <=, <, !=, ==, >=, >, ~=, ===, in, not in" + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/_structures.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/_structures.py new file mode 100644 index 0000000..4306784 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/_structures.py @@ -0,0 +1,33 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +"""Backward-compatibility shim for unpickling Version objects serialized before +packaging 26.1. + +Old pickles reference ``packaging._structures.InfinityType`` and +``packaging._structures.NegativeInfinityType``. This module provides minimal +stand-in classes so that ``pickle.loads()`` can resolve those references. +The deserialized objects are not used for comparisons — ``Version.__setstate__`` +discards the stale ``_key`` cache and recomputes it from the core version fields. +""" + +from __future__ import annotations + + +class InfinityType: + """Stand-in for the removed ``InfinityType`` used in old comparison keys.""" + + def __repr__(self) -> str: + return "Infinity" + + +class NegativeInfinityType: + """Stand-in for the removed ``NegativeInfinityType`` used in old comparison keys.""" + + def __repr__(self) -> str: + return "-Infinity" + + +Infinity = InfinityType() +NegativeInfinity = NegativeInfinityType() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/_tokenizer.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/_tokenizer.py new file mode 100644 index 0000000..5ab891c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/_tokenizer.py @@ -0,0 +1,193 @@ +from __future__ import annotations + +import contextlib +import re +from dataclasses import dataclass +from typing import Generator, Mapping, NoReturn + +from .specifiers import Specifier + + +@dataclass +class Token: + name: str + text: str + position: int + + +class ParserSyntaxError(Exception): + """The provided source text could not be parsed correctly.""" + + def __init__( + self, + message: str, + *, + source: str, + span: tuple[int, int], + ) -> None: + self.span = span + self.message = message + self.source = source + + super().__init__() + + def __str__(self) -> str: + marker = " " * self.span[0] + "~" * (self.span[1] - self.span[0]) + "^" + return f"{self.message}\n {self.source}\n {marker}" + + +DEFAULT_RULES: dict[str, re.Pattern[str]] = { + "LEFT_PARENTHESIS": re.compile(r"\("), + "RIGHT_PARENTHESIS": re.compile(r"\)"), + "LEFT_BRACKET": re.compile(r"\["), + "RIGHT_BRACKET": re.compile(r"\]"), + "SEMICOLON": re.compile(r";"), + "COMMA": re.compile(r","), + "QUOTED_STRING": re.compile( + r""" + ( + ('[^']*') + | + ("[^"]*") + ) + """, + re.VERBOSE, + ), + "OP": re.compile(r"(===|==|~=|!=|<=|>=|<|>)"), + "BOOLOP": re.compile(r"\b(or|and)\b"), + "IN": re.compile(r"\bin\b"), + "NOT": re.compile(r"\bnot\b"), + "VARIABLE": re.compile( + r""" + \b( + python_version + |python_full_version + |os[._]name + |sys[._]platform + |platform_(release|system) + |platform[._](version|machine|python_implementation) + |python_implementation + |implementation_(name|version) + |extras? + |dependency_groups + )\b + """, + re.VERBOSE, + ), + "SPECIFIER": re.compile( + Specifier._specifier_regex_str, + re.VERBOSE | re.IGNORECASE, + ), + "AT": re.compile(r"\@"), + "URL": re.compile(r"[^ \t]+"), + "IDENTIFIER": re.compile(r"\b[a-zA-Z0-9][a-zA-Z0-9._-]*\b"), + "VERSION_PREFIX_TRAIL": re.compile(r"\.\*"), + "VERSION_LOCAL_LABEL_TRAIL": re.compile(r"\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*"), + "WS": re.compile(r"[ \t]+"), + "END": re.compile(r"$"), +} + + +class Tokenizer: + """Context-sensitive token parsing. + + Provides methods to examine the input stream to check whether the next token + matches. + """ + + def __init__( + self, + source: str, + *, + rules: Mapping[str, re.Pattern[str]], + ) -> None: + self.source = source + self.rules = rules + self.next_token: Token | None = None + self.position = 0 + + def consume(self, name: str) -> None: + """Move beyond provided token name, if at current position.""" + if self.check(name): + self.read() + + def check(self, name: str, *, peek: bool = False) -> bool: + """Check whether the next token has the provided name. + + By default, if the check succeeds, the token *must* be read before + another check. If `peek` is set to `True`, the token is not loaded and + would need to be checked again. + """ + assert self.next_token is None, ( + f"Cannot check for {name!r}, already have {self.next_token!r}" + ) + assert name in self.rules, f"Unknown token name: {name!r}" + + expression = self.rules[name] + + match = expression.match(self.source, self.position) + if match is None: + return False + if not peek: + self.next_token = Token(name, match[0], self.position) + return True + + def expect(self, name: str, *, expected: str) -> Token: + """Expect a certain token name next, failing with a syntax error otherwise. + + The token is *not* read. + """ + if not self.check(name): + raise self.raise_syntax_error(f"Expected {expected}") + return self.read() + + def read(self) -> Token: + """Consume the next token and return it.""" + token = self.next_token + assert token is not None + + self.position += len(token.text) + self.next_token = None + + return token + + def raise_syntax_error( + self, + message: str, + *, + span_start: int | None = None, + span_end: int | None = None, + ) -> NoReturn: + """Raise ParserSyntaxError at the given position.""" + span = ( + self.position if span_start is None else span_start, + self.position if span_end is None else span_end, + ) + raise ParserSyntaxError( + message, + source=self.source, + span=span, + ) + + @contextlib.contextmanager + def enclosing_tokens( + self, open_token: str, close_token: str, *, around: str + ) -> Generator[None, None, None]: + if self.check(open_token): + open_position = self.position + self.read() + else: + open_position = None + + yield + + if open_position is None: + return + + if not self.check(close_token): + self.raise_syntax_error( + f"Expected matching {close_token} for {open_token}, after {around}", + span_start=open_position, + ) + + self.read() diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/dependency_groups.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/dependency_groups.py new file mode 100644 index 0000000..413e5cb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/dependency_groups.py @@ -0,0 +1,302 @@ +from __future__ import annotations + +import re +from collections.abc import Mapping, Sequence + +from .errors import _ErrorCollector +from .requirements import Requirement + +__all__ = [ + "CyclicDependencyGroup", + "DependencyGroupInclude", + "DependencyGroupResolver", + "DuplicateGroupNames", + "InvalidDependencyGroupObject", + "resolve_dependency_groups", +] + + +def __dir__() -> list[str]: + return __all__ + + +# ----------- +# Error Types +# ----------- + + +class DuplicateGroupNames(ValueError): + """ + The same dependency groups were defined twice, with different non-normalized names. + """ + + +class CyclicDependencyGroup(ValueError): + """ + The dependency group includes form a cycle. + """ + + def __init__(self, requested_group: str, group: str, include_group: str) -> None: + self.requested_group = requested_group + self.group = group + self.include_group = include_group + + if include_group == group: + reason = f"{group} includes itself" + else: + reason = f"{include_group} -> {group}, {group} -> {include_group}" + super().__init__( + "Cyclic dependency group include while resolving " + f"{requested_group}: {reason}" + ) + + +# in the PEP 735 spec, the tables in dependency group lists were described as +# "Dependency Object Specifiers", but the only defined type of object was a +# "Dependency Group Include" -- hence the naming of this error as "Object" +class InvalidDependencyGroupObject(ValueError): + """ + A member of a dependency group was identified as a dict, but was not in a valid + format. + """ + + +# ------------------------ +# Object Model & Interface +# ------------------------ + + +class DependencyGroupInclude: + __slots__ = ("include_group",) + + def __init__(self, include_group: str) -> None: + """ + Initialize a DependencyGroupInclude. + + :param include_group: The name of the group referred to by this include. + """ + self.include_group = include_group + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self.include_group!r})" + + +class DependencyGroupResolver: + """ + A resolver for Dependency Group data. + + This class handles caching, name normalization, cycle detection, and other + parsing requirements. There are only two public methods for exploring the data: + ``lookup()`` and ``resolve()``. + + :param dependency_groups: A mapping, as provided via pyproject + ``[dependency-groups]``. + """ + + def __init__( + self, + dependency_groups: Mapping[str, Sequence[str | Mapping[str, str]]], + ) -> None: + errors = _ErrorCollector() + + self.dependency_groups = _normalize_group_names(dependency_groups, errors) + + # a map of group names to parsed data + self._parsed_groups: dict[ + str, tuple[Requirement | DependencyGroupInclude, ...] + ] = {} + # a map of group names to their ancestors, used for cycle detection + self._include_graph_ancestors: dict[str, tuple[str, ...]] = {} + # a cache of completed resolutions to Requirement lists + self._resolve_cache: dict[str, tuple[Requirement, ...]] = {} + + errors.finalize("[dependency-groups] data was invalid") + + def lookup(self, group: str) -> tuple[Requirement | DependencyGroupInclude, ...]: + """ + Lookup a group name, returning the parsed dependency data for that group. + This will not resolve includes. + + :param group: the name of the group to lookup + """ + group = _normalize_name(group) + + with _ErrorCollector().on_exit( + f"[dependency-groups] data for {group!r} was malformed" + ) as errors: + return self._parse_group(group, errors) + + def resolve(self, group: str) -> tuple[Requirement, ...]: + """ + Resolve a dependency group to a list of requirements. + + :param group: the name of the group to resolve + """ + group = _normalize_name(group) + + with _ErrorCollector().on_exit( + f"[dependency-groups] data for {group!r} was malformed" + ) as errors: + return self._resolve(group, group, errors) + + def _resolve( + self, group: str, requested_group: str, errors: _ErrorCollector + ) -> tuple[Requirement, ...]: + """ + This is a helper for cached resolution to strings. It preserves the name of the + group which the user initially requested in order to present a clearer error in + the event that a cycle is detected. + + :param group: The normalized name of the group to resolve. + :param requested_group: The group which was used in the original, user-facing + request. + """ + if group in self._resolve_cache: + return self._resolve_cache[group] + + parsed = self._parse_group(group, errors) + + resolved_group = [] + + for item in parsed: + if isinstance(item, Requirement): + resolved_group.append(item) + elif isinstance(item, DependencyGroupInclude): + include_group = _normalize_name(item.include_group) + + # if a group is cyclic, record the error + # otherwise, follow the include_group reference + # + # this allows us to examine all includes in a group, even in the + # presence of errors + if include_group in self._include_graph_ancestors.get(group, ()): + errors.error( + CyclicDependencyGroup( + requested_group, group, item.include_group + ) + ) + else: + self._include_graph_ancestors[include_group] = ( + *self._include_graph_ancestors.get(group, ()), + group, + ) + resolved_group.extend( + self._resolve(include_group, requested_group, errors) + ) + else: # pragma: no cover + raise NotImplementedError( + f"Invalid dependency group item after parse: {item}" + ) + + # in the event that errors were detected, present the group as empty and do not + # cache the result + # this ensures that repeated access to a cyclic group will raise multiple errors + if errors.errors: + return () + + self._resolve_cache[group] = tuple(resolved_group) + return self._resolve_cache[group] + + def _parse_group( + self, group: str, errors: _ErrorCollector + ) -> tuple[Requirement | DependencyGroupInclude, ...]: + # short circuit -- never do the work twice + if group in self._parsed_groups: + return self._parsed_groups[group] + + if group not in self.dependency_groups: + errors.error(LookupError(f"Dependency group '{group}' not found")) + return () + + raw_group = self.dependency_groups[group] + if isinstance(raw_group, str): + errors.error( + TypeError( + f"Dependency group {group!r} contained a string rather than a list." + ) + ) + return () + + if not isinstance(raw_group, Sequence): + errors.error( + TypeError(f"Dependency group {group!r} is not a sequence type.") + ) + return () + + elements: list[Requirement | DependencyGroupInclude] = [] + for item in raw_group: + if isinstance(item, str): + # packaging.requirements.Requirement parsing ensures that this is a + # valid PEP 508 Dependency Specifier + # raises InvalidRequirement on failure + elements.append(Requirement(item)) + elif isinstance(item, Mapping): + if tuple(item.keys()) != ("include-group",): + errors.error( + InvalidDependencyGroupObject( + f"Invalid dependency group item: {item!r}" + ) + ) + else: + include_group = item["include-group"] + elements.append(DependencyGroupInclude(include_group=include_group)) + else: + errors.error(TypeError(f"Invalid dependency group item: {item!r}")) + + self._parsed_groups[group] = tuple(elements) + return self._parsed_groups[group] + + +# -------------------- +# Functional Interface +# -------------------- + + +def resolve_dependency_groups( + dependency_groups: Mapping[str, Sequence[str | Mapping[str, str]]], /, *groups: str +) -> tuple[str, ...]: + """ + Resolve a dependency group to a tuple of requirements, as strings. + + :param dependency_groups: the parsed contents of the ``[dependency-groups]`` table + from ``pyproject.toml`` + :param groups: the name of the group(s) to resolve + """ + resolver = DependencyGroupResolver(dependency_groups) + return tuple(str(r) for group in groups for r in resolver.resolve(group)) + + +# ---------------- +# internal helpers +# ---------------- + + +_NORMALIZE_PATTERN = re.compile(r"[-_.]+") + + +def _normalize_name(name: str) -> str: + return _NORMALIZE_PATTERN.sub("-", name).lower() + + +def _normalize_group_names( + dependency_groups: Mapping[str, Sequence[str | Mapping[str, str]]], + errors: _ErrorCollector, +) -> dict[str, Sequence[str | Mapping[str, str]]]: + original_names: dict[str, list[str]] = {} + normalized_groups: dict[str, Sequence[str | Mapping[str, str]]] = {} + + for group_name, value in dependency_groups.items(): + normed_group_name = _normalize_name(group_name) + original_names.setdefault(normed_group_name, []).append(group_name) + normalized_groups[normed_group_name] = value + + for normed_name, names in original_names.items(): + if len(names) > 1: + errors.error( + DuplicateGroupNames( + "Duplicate dependency group names: " + f"{normed_name} ({', '.join(names)})" + ) + ) + + return normalized_groups diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/direct_url.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/direct_url.py new file mode 100644 index 0000000..5d1c56c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/direct_url.py @@ -0,0 +1,325 @@ +from __future__ import annotations + +import dataclasses +import re +import urllib.parse +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, Protocol, TypeVar + +if TYPE_CHECKING: # pragma: no cover + import sys + from collections.abc import Collection + + if sys.version_info >= (3, 11): + from typing import Self + else: + from typing_extensions import Self + +__all__ = [ + "ArchiveInfo", + "DirInfo", + "DirectUrl", + "DirectUrlValidationError", + "VcsInfo", +] + + +def __dir__() -> list[str]: + return __all__ + + +_T = TypeVar("_T") + + +class _FromMappingProtocol(Protocol): # pragma: no cover + @classmethod + def _from_dict(cls, d: Mapping[str, Any]) -> Self: ... + + +_FromMappingProtocolT = TypeVar("_FromMappingProtocolT", bound=_FromMappingProtocol) + + +def _json_dict_factory(data: list[tuple[str, Any]]) -> dict[str, Any]: + return {key: value for key, value in data if value is not None} + + +def _get(d: Mapping[str, Any], expected_type: type[_T], key: str) -> _T | None: + """Get a value from the dictionary and verify it's the expected type.""" + if (value := d.get(key)) is None: + return None + if not isinstance(value, expected_type): + raise DirectUrlValidationError( + f"Unexpected type {type(value).__name__} " + f"(expected {expected_type.__name__})", + context=key, + ) + return value + + +def _get_required(d: Mapping[str, Any], expected_type: type[_T], key: str) -> _T: + """Get a required value from the dictionary and verify it's the expected type.""" + if (value := _get(d, expected_type, key)) is None: + raise _DirectUrlRequiredKeyError(key) + return value + + +def _get_object( + d: Mapping[str, Any], target_type: type[_FromMappingProtocolT], key: str +) -> _FromMappingProtocolT | None: + """Get a dictionary value from the dictionary and convert it to a dataclass.""" + if (value := _get(d, Mapping, key)) is None: # type: ignore[type-abstract] + return None + try: + return target_type._from_dict(value) + except Exception as e: + raise DirectUrlValidationError(e, context=key) from e + + +_PEP610_USER_PASS_ENV_VARS_REGEX = re.compile( + r"^\$\{[A-Za-z0-9-_]+\}(:\$\{[A-Za-z0-9-_]+\})?$" +) + + +def _strip_auth_from_netloc(netloc: str, safe_user_passwords: Collection[str]) -> str: + if "@" not in netloc: + return netloc + user_pass, netloc_no_user_pass = netloc.split("@", 1) + if user_pass in safe_user_passwords: + return netloc + if _PEP610_USER_PASS_ENV_VARS_REGEX.match(user_pass): + return netloc + return netloc_no_user_pass + + +def _strip_url(url: str, safe_user_passwords: Collection[str]) -> str: + """url with user:password part removed unless it is formed with + environment variables as specified in PEP 610, or it is a safe user:password + such as `git`. + """ + parsed_url = urllib.parse.urlsplit(url) + netloc = _strip_auth_from_netloc(parsed_url.netloc, safe_user_passwords) + return urllib.parse.urlunsplit( + ( + parsed_url.scheme, + netloc, + parsed_url.path, + parsed_url.query, + parsed_url.fragment, + ) + ) + + +class DirectUrlValidationError(Exception): + """Raised when when input data is not spec-compliant.""" + + context: str | None = None + message: str + + def __init__( + self, + cause: str | Exception, + *, + context: str | None = None, + ) -> None: + if isinstance(cause, DirectUrlValidationError): + if cause.context: + self.context = ( + f"{context}.{cause.context}" if context else cause.context + ) + else: + self.context = context # pragma: no cover + self.message = cause.message + else: + self.context = context + self.message = str(cause) + + def __str__(self) -> str: + if self.context: + return f"{self.message} in {self.context!r}" + return self.message + + +class _DirectUrlRequiredKeyError(DirectUrlValidationError): + def __init__(self, key: str) -> None: + super().__init__("Missing required value", context=key) + + +@dataclasses.dataclass(frozen=True, init=False) +class VcsInfo: + vcs: str + commit_id: str + requested_revision: str | None = None + + def __init__( + self, + *, + vcs: str, + commit_id: str, + requested_revision: str | None = None, + ) -> None: + object.__setattr__(self, "vcs", vcs) + object.__setattr__(self, "commit_id", commit_id) + object.__setattr__(self, "requested_revision", requested_revision) + + @classmethod + def _from_dict(cls, d: Mapping[str, Any]) -> Self: + # We can't validate vcs value because is not closed. + return cls( + vcs=_get_required(d, str, "vcs"), + requested_revision=_get(d, str, "requested_revision"), + commit_id=_get_required(d, str, "commit_id"), + ) + + +@dataclasses.dataclass(frozen=True, init=False) +class ArchiveInfo: + hashes: Mapping[str, str] | None = None + + def __init__( + self, + *, + hashes: Mapping[str, str] | None = None, + ) -> None: + object.__setattr__(self, "hashes", hashes) + + @classmethod + def _from_dict(cls, d: Mapping[str, Any]) -> Self: + hashes = _get(d, Mapping, "hashes") # type: ignore[type-abstract] + if hashes is not None and not all(isinstance(h, str) for h in hashes.values()): + raise DirectUrlValidationError( + "Hash values must be strings", context="hashes" + ) + legacy_hash = _get(d, str, "hash") + if legacy_hash is not None: + if "=" not in legacy_hash: + raise DirectUrlValidationError( + "Invalid hash format (expected '=')", + context="hash", + ) + hash_algorithm, hash_value = legacy_hash.split("=", 1) + if hashes is None: + # if `hashes` are not present, we can derive it from the legacy `hash` + hashes = {hash_algorithm: hash_value} + else: + # if `hashes` are present, the legacy `hash` must match one of them + if hash_algorithm not in hashes: + raise DirectUrlValidationError( + f"Algorithm {hash_algorithm!r} used in hash field " + f"is not present in hashes field", + context="hashes", + ) + if hashes[hash_algorithm] != hash_value: + raise DirectUrlValidationError( + f"Algorithm {hash_algorithm!r} used in hash field " + f"has different value in hashes field", + context="hash", + ) + return cls(hashes=hashes) + + +@dataclasses.dataclass(frozen=True, init=False) +class DirInfo: + editable: bool | None = None + + def __init__( + self, + *, + editable: bool | None = None, + ) -> None: + object.__setattr__(self, "editable", editable) + + @classmethod + def _from_dict(cls, d: Mapping[str, Any]) -> Self: + return cls( + editable=_get(d, bool, "editable"), + ) + + +@dataclasses.dataclass(frozen=True, init=False) +class DirectUrl: + """A class representing a direct URL.""" + + url: str + archive_info: ArchiveInfo | None = None + vcs_info: VcsInfo | None = None + dir_info: DirInfo | None = None + subdirectory: str | None = None # XXX Path or str? + + def __init__( + self, + *, + url: str, + archive_info: ArchiveInfo | None = None, + vcs_info: VcsInfo | None = None, + dir_info: DirInfo | None = None, + subdirectory: str | None = None, + ) -> None: + object.__setattr__(self, "url", url) + object.__setattr__(self, "archive_info", archive_info) + object.__setattr__(self, "vcs_info", vcs_info) + object.__setattr__(self, "dir_info", dir_info) + object.__setattr__(self, "subdirectory", subdirectory) + + @classmethod + def _from_dict(cls, d: Mapping[str, Any]) -> Self: + direct_url = cls( + url=_get_required(d, str, "url"), + archive_info=_get_object(d, ArchiveInfo, "archive_info"), + vcs_info=_get_object(d, VcsInfo, "vcs_info"), + dir_info=_get_object(d, DirInfo, "dir_info"), + subdirectory=_get(d, str, "subdirectory"), + ) + if ( + bool(direct_url.vcs_info) + + bool(direct_url.archive_info) + + bool(direct_url.dir_info) + ) != 1: + raise DirectUrlValidationError( + "Exactly one of vcs_info, archive_info, dir_info must be present" + ) + if direct_url.dir_info is not None and not direct_url.url.startswith("file://"): + raise DirectUrlValidationError( + "URL scheme must be file:// when dir_info is present", + context="url", + ) + # XXX subdirectory must be relative, can we, should we validate that here? + return direct_url + + @classmethod + def from_dict(cls, d: Mapping[str, Any], /) -> Self: + """Create and validate a DirectUrl instance from a JSON dictionary.""" + return cls._from_dict(d) + + def to_dict( + self, + *, + generate_legacy_hash: bool = False, + strip_user_password: bool = True, + safe_user_passwords: Collection[str] = ("git",), + ) -> Mapping[str, Any]: + """Convert the DirectUrl instance to a JSON dictionary. + + :param generate_legacy_hash: If True, include a legacy `hash` field in + `archive_info` for backward compatibility with tools that don't + support the `hashes` field. + :param strip_user_password: If True, strip user:password from the URL + unless it is formed with environment variables as specified in PEP + 610, or it is a safe user:password such as `git`. + :param safe_user_passwords: A collection of user:password strings that + should not be stripped from the URL even if `strip_user_password` is + True. + """ + res = dataclasses.asdict(self, dict_factory=_json_dict_factory) + if generate_legacy_hash and self.archive_info and self.archive_info.hashes: + hash_algorithm, hash_value = next(iter(self.archive_info.hashes.items())) + res["archive_info"]["hash"] = f"{hash_algorithm}={hash_value}" + if strip_user_password: + res["url"] = _strip_url(self.url, safe_user_passwords) + return res + + def validate(self) -> None: + """Validate the DirectUrl instance against the specification. + + Raises :class:`DirectUrlValidationError` if invalid. + """ + self.from_dict(self.to_dict()) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/errors.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/errors.py new file mode 100644 index 0000000..d1d47cf --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/errors.py @@ -0,0 +1,94 @@ +from __future__ import annotations + +import contextlib +import dataclasses +import sys +import typing + +__all__ = ["ExceptionGroup"] + + +def __dir__() -> list[str]: + return __all__ + + +if sys.version_info >= (3, 11): # pragma: no cover + from builtins import ExceptionGroup +else: # pragma: no cover + + class ExceptionGroup(Exception): + """A minimal implementation of :external:exc:`ExceptionGroup` from Python 3.11. + + If :external:exc:`ExceptionGroup` is already defined by Python itself, + that version is used instead. + """ + + message: str + exceptions: list[Exception] + + def __init__(self, message: str, exceptions: list[Exception]) -> None: + self.message = message + self.exceptions = exceptions + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self.message!r}, {self.exceptions!r})" + + +@dataclasses.dataclass +class _ErrorCollector: + """ + Collect errors into ExceptionGroups. + + Used like this: + + collector = _ErrorCollector() + # Add a single exception + collector.error(ValueError("one")) + + # Supports nesting, including combining ExceptionGroups + with collector.collect(): + raise ValueError("two") + collector.finalize("Found some errors") + + Since making a collector and then calling finalize later is a common pattern, + a convenience method ``on_exit`` is provided. + """ + + errors: list[Exception] = dataclasses.field(default_factory=list, init=False) + + def finalize(self, msg: str) -> None: + """Raise a group exception if there are any errors.""" + if self.errors: + raise ExceptionGroup(msg, self.errors) + + @contextlib.contextmanager + def on_exit(self, msg: str) -> typing.Generator[_ErrorCollector, None, None]: + """ + Calls finalize if no uncollected errors were present. + + Uncollected errors are raised normally. + """ + yield self + self.finalize(msg) + + @contextlib.contextmanager + def collect(self, *err_cls: type[Exception]) -> typing.Generator[None, None, None]: + """ + Context manager to collect errors into the error list. + + Must be inside loops, as only one error can be collected at a time. + """ + error_classes = err_cls or (Exception,) + try: + yield + except ExceptionGroup as error: + self.errors.extend(error.exceptions) + except error_classes as error: + self.errors.append(error) + + def error( + self, + error: Exception, + ) -> None: + """Add an error to the list.""" + self.errors.append(error) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/licenses/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/licenses/__init__.py new file mode 100644 index 0000000..36e46ed --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/licenses/__init__.py @@ -0,0 +1,186 @@ +####################################################################################### +# +# Adapted from: +# https://github.com/pypa/hatch/blob/5352e44/backend/src/hatchling/licenses/parse.py +# +# MIT License +# +# Copyright (c) 2017-present Ofek Lev +# +# 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. +# +# +# With additional allowance of arbitrary `LicenseRef-` identifiers, not just +# `LicenseRef-Public-Domain` and `LicenseRef-Proprietary`. +# +####################################################################################### +from __future__ import annotations + +import re +from typing import NewType, cast + +from ._spdx import EXCEPTIONS, LICENSES + +__all__ = [ + "InvalidLicenseExpression", + "NormalizedLicenseExpression", + "canonicalize_license_expression", +] + + +# Simple __dir__ implementation since there are no public submodules +def __dir__() -> list[str]: + return __all__ + + +license_ref_allowed = re.compile("^[A-Za-z0-9.-]*$") + +NormalizedLicenseExpression = NewType("NormalizedLicenseExpression", str) +""" +A :class:`typing.NewType` of :class:`str`, representing a normalized +License-Expression. +""" + + +class InvalidLicenseExpression(ValueError): + """Raised when a license-expression string is invalid + + >>> from packaging.licenses import canonicalize_license_expression + >>> canonicalize_license_expression("invalid") + Traceback (most recent call last): + ... + packaging.licenses.InvalidLicenseExpression: Invalid license expression: 'invalid' + """ + + +def canonicalize_license_expression( + raw_license_expression: str, +) -> NormalizedLicenseExpression: + """ + This function takes a valid License-Expression, and returns the normalized + form of it. + + The return type is typed as :class:`NormalizedLicenseExpression`. This + allows type checkers to help require that a string has passed through this + function before use. + + :param str raw_license_expression: The License-Expression to canonicalize. + :raises InvalidLicenseExpression: If the License-Expression is invalid due to an + invalid/unknown license identifier or invalid syntax. + + .. doctest:: + + >>> from packaging.licenses import canonicalize_license_expression + >>> canonicalize_license_expression("mit") + 'MIT' + >>> canonicalize_license_expression("mit and (apache-2.0 or bsd-2-clause)") + 'MIT AND (Apache-2.0 OR BSD-2-Clause)' + >>> canonicalize_license_expression("(mit") + Traceback (most recent call last): + ... + InvalidLicenseExpression: Invalid license expression: '(mit' + >>> canonicalize_license_expression("Use-it-after-midnight") + Traceback (most recent call last): + ... + InvalidLicenseExpression: Unknown license: 'Use-it-after-midnight' + """ + if not raw_license_expression: + message = f"Invalid license expression: {raw_license_expression!r}" + raise InvalidLicenseExpression(message) + + # Pad any parentheses so tokenization can be achieved by merely splitting on + # whitespace. + license_expression = raw_license_expression.replace("(", " ( ").replace(")", " ) ") + licenseref_prefix = "LicenseRef-" + license_refs = { + ref.lower(): "LicenseRef-" + ref[len(licenseref_prefix) :] + for ref in license_expression.split() + if ref.lower().startswith(licenseref_prefix.lower()) + } + + # Normalize to lower case so we can look up licenses/exceptions + # and so boolean operators are Python-compatible. + license_expression = license_expression.lower() + + tokens = license_expression.split() + + # Rather than implementing a parenthesis/boolean logic parser, create an + # expression that Python can parse. Everything that is not involved with the + # grammar itself is replaced with the placeholder `False` and the resultant + # expression should become a valid Python expression. + python_tokens = [] + for token in tokens: + if token not in {"or", "and", "with", "(", ")"}: + python_tokens.append("False") + elif token == "with": + python_tokens.append("or") + elif ( + token == "(" + and python_tokens + and python_tokens[-1] not in {"or", "and", "("} + ) or (token == ")" and python_tokens and python_tokens[-1] == "("): + message = f"Invalid license expression: {raw_license_expression!r}" + raise InvalidLicenseExpression(message) + else: + python_tokens.append(token) + + python_expression = " ".join(python_tokens) + try: + compile(python_expression, "", "eval") + except SyntaxError: + message = f"Invalid license expression: {raw_license_expression!r}" + raise InvalidLicenseExpression(message) from None + + # Take a final pass to check for unknown licenses/exceptions. + normalized_tokens = [] + for token in tokens: + if token in {"or", "and", "with", "(", ")"}: + normalized_tokens.append(token.upper()) + continue + + if normalized_tokens and normalized_tokens[-1] == "WITH": + if token not in EXCEPTIONS: + message = f"Unknown license exception: {token!r}" + raise InvalidLicenseExpression(message) + + normalized_tokens.append(EXCEPTIONS[token]["id"]) + else: + if token.endswith("+"): + final_token = token[:-1] + suffix = "+" + else: + final_token = token + suffix = "" + + if final_token.startswith("licenseref-"): + if not license_ref_allowed.match(final_token): + message = f"Invalid licenseref: {final_token!r}" + raise InvalidLicenseExpression(message) + normalized_tokens.append(license_refs[final_token] + suffix) + else: + if final_token not in LICENSES: + message = f"Unknown license: {final_token!r}" + raise InvalidLicenseExpression(message) + normalized_tokens.append(LICENSES[final_token]["id"] + suffix) + + normalized_expression = " ".join(normalized_tokens) + + return cast( + "NormalizedLicenseExpression", + normalized_expression.replace("( ", "(").replace(" )", ")"), + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/licenses/_spdx.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/licenses/_spdx.py new file mode 100644 index 0000000..a277af2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/licenses/_spdx.py @@ -0,0 +1,799 @@ + +from __future__ import annotations + +from typing import TypedDict + +class SPDXLicense(TypedDict): + id: str + deprecated: bool + +class SPDXException(TypedDict): + id: str + deprecated: bool + + +VERSION = '3.27.0' + +LICENSES: dict[str, SPDXLicense] = { + '0bsd': {'id': '0BSD', 'deprecated': False}, + '3d-slicer-1.0': {'id': '3D-Slicer-1.0', 'deprecated': False}, + 'aal': {'id': 'AAL', 'deprecated': False}, + 'abstyles': {'id': 'Abstyles', 'deprecated': False}, + 'adacore-doc': {'id': 'AdaCore-doc', 'deprecated': False}, + 'adobe-2006': {'id': 'Adobe-2006', 'deprecated': False}, + 'adobe-display-postscript': {'id': 'Adobe-Display-PostScript', 'deprecated': False}, + 'adobe-glyph': {'id': 'Adobe-Glyph', 'deprecated': False}, + 'adobe-utopia': {'id': 'Adobe-Utopia', 'deprecated': False}, + 'adsl': {'id': 'ADSL', 'deprecated': False}, + 'afl-1.1': {'id': 'AFL-1.1', 'deprecated': False}, + 'afl-1.2': {'id': 'AFL-1.2', 'deprecated': False}, + 'afl-2.0': {'id': 'AFL-2.0', 'deprecated': False}, + 'afl-2.1': {'id': 'AFL-2.1', 'deprecated': False}, + 'afl-3.0': {'id': 'AFL-3.0', 'deprecated': False}, + 'afmparse': {'id': 'Afmparse', 'deprecated': False}, + 'agpl-1.0': {'id': 'AGPL-1.0', 'deprecated': True}, + 'agpl-1.0-only': {'id': 'AGPL-1.0-only', 'deprecated': False}, + 'agpl-1.0-or-later': {'id': 'AGPL-1.0-or-later', 'deprecated': False}, + 'agpl-3.0': {'id': 'AGPL-3.0', 'deprecated': True}, + 'agpl-3.0-only': {'id': 'AGPL-3.0-only', 'deprecated': False}, + 'agpl-3.0-or-later': {'id': 'AGPL-3.0-or-later', 'deprecated': False}, + 'aladdin': {'id': 'Aladdin', 'deprecated': False}, + 'amd-newlib': {'id': 'AMD-newlib', 'deprecated': False}, + 'amdplpa': {'id': 'AMDPLPA', 'deprecated': False}, + 'aml': {'id': 'AML', 'deprecated': False}, + 'aml-glslang': {'id': 'AML-glslang', 'deprecated': False}, + 'ampas': {'id': 'AMPAS', 'deprecated': False}, + 'antlr-pd': {'id': 'ANTLR-PD', 'deprecated': False}, + 'antlr-pd-fallback': {'id': 'ANTLR-PD-fallback', 'deprecated': False}, + 'any-osi': {'id': 'any-OSI', 'deprecated': False}, + 'any-osi-perl-modules': {'id': 'any-OSI-perl-modules', 'deprecated': False}, + 'apache-1.0': {'id': 'Apache-1.0', 'deprecated': False}, + 'apache-1.1': {'id': 'Apache-1.1', 'deprecated': False}, + 'apache-2.0': {'id': 'Apache-2.0', 'deprecated': False}, + 'apafml': {'id': 'APAFML', 'deprecated': False}, + 'apl-1.0': {'id': 'APL-1.0', 'deprecated': False}, + 'app-s2p': {'id': 'App-s2p', 'deprecated': False}, + 'apsl-1.0': {'id': 'APSL-1.0', 'deprecated': False}, + 'apsl-1.1': {'id': 'APSL-1.1', 'deprecated': False}, + 'apsl-1.2': {'id': 'APSL-1.2', 'deprecated': False}, + 'apsl-2.0': {'id': 'APSL-2.0', 'deprecated': False}, + 'arphic-1999': {'id': 'Arphic-1999', 'deprecated': False}, + 'artistic-1.0': {'id': 'Artistic-1.0', 'deprecated': False}, + 'artistic-1.0-cl8': {'id': 'Artistic-1.0-cl8', 'deprecated': False}, + 'artistic-1.0-perl': {'id': 'Artistic-1.0-Perl', 'deprecated': False}, + 'artistic-2.0': {'id': 'Artistic-2.0', 'deprecated': False}, + 'artistic-dist': {'id': 'Artistic-dist', 'deprecated': False}, + 'aspell-ru': {'id': 'Aspell-RU', 'deprecated': False}, + 'aswf-digital-assets-1.0': {'id': 'ASWF-Digital-Assets-1.0', 'deprecated': False}, + 'aswf-digital-assets-1.1': {'id': 'ASWF-Digital-Assets-1.1', 'deprecated': False}, + 'baekmuk': {'id': 'Baekmuk', 'deprecated': False}, + 'bahyph': {'id': 'Bahyph', 'deprecated': False}, + 'barr': {'id': 'Barr', 'deprecated': False}, + 'bcrypt-solar-designer': {'id': 'bcrypt-Solar-Designer', 'deprecated': False}, + 'beerware': {'id': 'Beerware', 'deprecated': False}, + 'bitstream-charter': {'id': 'Bitstream-Charter', 'deprecated': False}, + 'bitstream-vera': {'id': 'Bitstream-Vera', 'deprecated': False}, + 'bittorrent-1.0': {'id': 'BitTorrent-1.0', 'deprecated': False}, + 'bittorrent-1.1': {'id': 'BitTorrent-1.1', 'deprecated': False}, + 'blessing': {'id': 'blessing', 'deprecated': False}, + 'blueoak-1.0.0': {'id': 'BlueOak-1.0.0', 'deprecated': False}, + 'boehm-gc': {'id': 'Boehm-GC', 'deprecated': False}, + 'boehm-gc-without-fee': {'id': 'Boehm-GC-without-fee', 'deprecated': False}, + 'borceux': {'id': 'Borceux', 'deprecated': False}, + 'brian-gladman-2-clause': {'id': 'Brian-Gladman-2-Clause', 'deprecated': False}, + 'brian-gladman-3-clause': {'id': 'Brian-Gladman-3-Clause', 'deprecated': False}, + 'bsd-1-clause': {'id': 'BSD-1-Clause', 'deprecated': False}, + 'bsd-2-clause': {'id': 'BSD-2-Clause', 'deprecated': False}, + 'bsd-2-clause-darwin': {'id': 'BSD-2-Clause-Darwin', 'deprecated': False}, + 'bsd-2-clause-first-lines': {'id': 'BSD-2-Clause-first-lines', 'deprecated': False}, + 'bsd-2-clause-freebsd': {'id': 'BSD-2-Clause-FreeBSD', 'deprecated': True}, + 'bsd-2-clause-netbsd': {'id': 'BSD-2-Clause-NetBSD', 'deprecated': True}, + 'bsd-2-clause-patent': {'id': 'BSD-2-Clause-Patent', 'deprecated': False}, + 'bsd-2-clause-pkgconf-disclaimer': {'id': 'BSD-2-Clause-pkgconf-disclaimer', 'deprecated': False}, + 'bsd-2-clause-views': {'id': 'BSD-2-Clause-Views', 'deprecated': False}, + 'bsd-3-clause': {'id': 'BSD-3-Clause', 'deprecated': False}, + 'bsd-3-clause-acpica': {'id': 'BSD-3-Clause-acpica', 'deprecated': False}, + 'bsd-3-clause-attribution': {'id': 'BSD-3-Clause-Attribution', 'deprecated': False}, + 'bsd-3-clause-clear': {'id': 'BSD-3-Clause-Clear', 'deprecated': False}, + 'bsd-3-clause-flex': {'id': 'BSD-3-Clause-flex', 'deprecated': False}, + 'bsd-3-clause-hp': {'id': 'BSD-3-Clause-HP', 'deprecated': False}, + 'bsd-3-clause-lbnl': {'id': 'BSD-3-Clause-LBNL', 'deprecated': False}, + 'bsd-3-clause-modification': {'id': 'BSD-3-Clause-Modification', 'deprecated': False}, + 'bsd-3-clause-no-military-license': {'id': 'BSD-3-Clause-No-Military-License', 'deprecated': False}, + 'bsd-3-clause-no-nuclear-license': {'id': 'BSD-3-Clause-No-Nuclear-License', 'deprecated': False}, + 'bsd-3-clause-no-nuclear-license-2014': {'id': 'BSD-3-Clause-No-Nuclear-License-2014', 'deprecated': False}, + 'bsd-3-clause-no-nuclear-warranty': {'id': 'BSD-3-Clause-No-Nuclear-Warranty', 'deprecated': False}, + 'bsd-3-clause-open-mpi': {'id': 'BSD-3-Clause-Open-MPI', 'deprecated': False}, + 'bsd-3-clause-sun': {'id': 'BSD-3-Clause-Sun', 'deprecated': False}, + 'bsd-4-clause': {'id': 'BSD-4-Clause', 'deprecated': False}, + 'bsd-4-clause-shortened': {'id': 'BSD-4-Clause-Shortened', 'deprecated': False}, + 'bsd-4-clause-uc': {'id': 'BSD-4-Clause-UC', 'deprecated': False}, + 'bsd-4.3reno': {'id': 'BSD-4.3RENO', 'deprecated': False}, + 'bsd-4.3tahoe': {'id': 'BSD-4.3TAHOE', 'deprecated': False}, + 'bsd-advertising-acknowledgement': {'id': 'BSD-Advertising-Acknowledgement', 'deprecated': False}, + 'bsd-attribution-hpnd-disclaimer': {'id': 'BSD-Attribution-HPND-disclaimer', 'deprecated': False}, + 'bsd-inferno-nettverk': {'id': 'BSD-Inferno-Nettverk', 'deprecated': False}, + 'bsd-protection': {'id': 'BSD-Protection', 'deprecated': False}, + 'bsd-source-beginning-file': {'id': 'BSD-Source-beginning-file', 'deprecated': False}, + 'bsd-source-code': {'id': 'BSD-Source-Code', 'deprecated': False}, + 'bsd-systemics': {'id': 'BSD-Systemics', 'deprecated': False}, + 'bsd-systemics-w3works': {'id': 'BSD-Systemics-W3Works', 'deprecated': False}, + 'bsl-1.0': {'id': 'BSL-1.0', 'deprecated': False}, + 'busl-1.1': {'id': 'BUSL-1.1', 'deprecated': False}, + 'bzip2-1.0.5': {'id': 'bzip2-1.0.5', 'deprecated': True}, + 'bzip2-1.0.6': {'id': 'bzip2-1.0.6', 'deprecated': False}, + 'c-uda-1.0': {'id': 'C-UDA-1.0', 'deprecated': False}, + 'cal-1.0': {'id': 'CAL-1.0', 'deprecated': False}, + 'cal-1.0-combined-work-exception': {'id': 'CAL-1.0-Combined-Work-Exception', 'deprecated': False}, + 'caldera': {'id': 'Caldera', 'deprecated': False}, + 'caldera-no-preamble': {'id': 'Caldera-no-preamble', 'deprecated': False}, + 'catharon': {'id': 'Catharon', 'deprecated': False}, + 'catosl-1.1': {'id': 'CATOSL-1.1', 'deprecated': False}, + 'cc-by-1.0': {'id': 'CC-BY-1.0', 'deprecated': False}, + 'cc-by-2.0': {'id': 'CC-BY-2.0', 'deprecated': False}, + 'cc-by-2.5': {'id': 'CC-BY-2.5', 'deprecated': False}, + 'cc-by-2.5-au': {'id': 'CC-BY-2.5-AU', 'deprecated': False}, + 'cc-by-3.0': {'id': 'CC-BY-3.0', 'deprecated': False}, + 'cc-by-3.0-at': {'id': 'CC-BY-3.0-AT', 'deprecated': False}, + 'cc-by-3.0-au': {'id': 'CC-BY-3.0-AU', 'deprecated': False}, + 'cc-by-3.0-de': {'id': 'CC-BY-3.0-DE', 'deprecated': False}, + 'cc-by-3.0-igo': {'id': 'CC-BY-3.0-IGO', 'deprecated': False}, + 'cc-by-3.0-nl': {'id': 'CC-BY-3.0-NL', 'deprecated': False}, + 'cc-by-3.0-us': {'id': 'CC-BY-3.0-US', 'deprecated': False}, + 'cc-by-4.0': {'id': 'CC-BY-4.0', 'deprecated': False}, + 'cc-by-nc-1.0': {'id': 'CC-BY-NC-1.0', 'deprecated': False}, + 'cc-by-nc-2.0': {'id': 'CC-BY-NC-2.0', 'deprecated': False}, + 'cc-by-nc-2.5': {'id': 'CC-BY-NC-2.5', 'deprecated': False}, + 'cc-by-nc-3.0': {'id': 'CC-BY-NC-3.0', 'deprecated': False}, + 'cc-by-nc-3.0-de': {'id': 'CC-BY-NC-3.0-DE', 'deprecated': False}, + 'cc-by-nc-4.0': {'id': 'CC-BY-NC-4.0', 'deprecated': False}, + 'cc-by-nc-nd-1.0': {'id': 'CC-BY-NC-ND-1.0', 'deprecated': False}, + 'cc-by-nc-nd-2.0': {'id': 'CC-BY-NC-ND-2.0', 'deprecated': False}, + 'cc-by-nc-nd-2.5': {'id': 'CC-BY-NC-ND-2.5', 'deprecated': False}, + 'cc-by-nc-nd-3.0': {'id': 'CC-BY-NC-ND-3.0', 'deprecated': False}, + 'cc-by-nc-nd-3.0-de': {'id': 'CC-BY-NC-ND-3.0-DE', 'deprecated': False}, + 'cc-by-nc-nd-3.0-igo': {'id': 'CC-BY-NC-ND-3.0-IGO', 'deprecated': False}, + 'cc-by-nc-nd-4.0': {'id': 'CC-BY-NC-ND-4.0', 'deprecated': False}, + 'cc-by-nc-sa-1.0': {'id': 'CC-BY-NC-SA-1.0', 'deprecated': False}, + 'cc-by-nc-sa-2.0': {'id': 'CC-BY-NC-SA-2.0', 'deprecated': False}, + 'cc-by-nc-sa-2.0-de': {'id': 'CC-BY-NC-SA-2.0-DE', 'deprecated': False}, + 'cc-by-nc-sa-2.0-fr': {'id': 'CC-BY-NC-SA-2.0-FR', 'deprecated': False}, + 'cc-by-nc-sa-2.0-uk': {'id': 'CC-BY-NC-SA-2.0-UK', 'deprecated': False}, + 'cc-by-nc-sa-2.5': {'id': 'CC-BY-NC-SA-2.5', 'deprecated': False}, + 'cc-by-nc-sa-3.0': {'id': 'CC-BY-NC-SA-3.0', 'deprecated': False}, + 'cc-by-nc-sa-3.0-de': {'id': 'CC-BY-NC-SA-3.0-DE', 'deprecated': False}, + 'cc-by-nc-sa-3.0-igo': {'id': 'CC-BY-NC-SA-3.0-IGO', 'deprecated': False}, + 'cc-by-nc-sa-4.0': {'id': 'CC-BY-NC-SA-4.0', 'deprecated': False}, + 'cc-by-nd-1.0': {'id': 'CC-BY-ND-1.0', 'deprecated': False}, + 'cc-by-nd-2.0': {'id': 'CC-BY-ND-2.0', 'deprecated': False}, + 'cc-by-nd-2.5': {'id': 'CC-BY-ND-2.5', 'deprecated': False}, + 'cc-by-nd-3.0': {'id': 'CC-BY-ND-3.0', 'deprecated': False}, + 'cc-by-nd-3.0-de': {'id': 'CC-BY-ND-3.0-DE', 'deprecated': False}, + 'cc-by-nd-4.0': {'id': 'CC-BY-ND-4.0', 'deprecated': False}, + 'cc-by-sa-1.0': {'id': 'CC-BY-SA-1.0', 'deprecated': False}, + 'cc-by-sa-2.0': {'id': 'CC-BY-SA-2.0', 'deprecated': False}, + 'cc-by-sa-2.0-uk': {'id': 'CC-BY-SA-2.0-UK', 'deprecated': False}, + 'cc-by-sa-2.1-jp': {'id': 'CC-BY-SA-2.1-JP', 'deprecated': False}, + 'cc-by-sa-2.5': {'id': 'CC-BY-SA-2.5', 'deprecated': False}, + 'cc-by-sa-3.0': {'id': 'CC-BY-SA-3.0', 'deprecated': False}, + 'cc-by-sa-3.0-at': {'id': 'CC-BY-SA-3.0-AT', 'deprecated': False}, + 'cc-by-sa-3.0-de': {'id': 'CC-BY-SA-3.0-DE', 'deprecated': False}, + 'cc-by-sa-3.0-igo': {'id': 'CC-BY-SA-3.0-IGO', 'deprecated': False}, + 'cc-by-sa-4.0': {'id': 'CC-BY-SA-4.0', 'deprecated': False}, + 'cc-pddc': {'id': 'CC-PDDC', 'deprecated': False}, + 'cc-pdm-1.0': {'id': 'CC-PDM-1.0', 'deprecated': False}, + 'cc-sa-1.0': {'id': 'CC-SA-1.0', 'deprecated': False}, + 'cc0-1.0': {'id': 'CC0-1.0', 'deprecated': False}, + 'cddl-1.0': {'id': 'CDDL-1.0', 'deprecated': False}, + 'cddl-1.1': {'id': 'CDDL-1.1', 'deprecated': False}, + 'cdl-1.0': {'id': 'CDL-1.0', 'deprecated': False}, + 'cdla-permissive-1.0': {'id': 'CDLA-Permissive-1.0', 'deprecated': False}, + 'cdla-permissive-2.0': {'id': 'CDLA-Permissive-2.0', 'deprecated': False}, + 'cdla-sharing-1.0': {'id': 'CDLA-Sharing-1.0', 'deprecated': False}, + 'cecill-1.0': {'id': 'CECILL-1.0', 'deprecated': False}, + 'cecill-1.1': {'id': 'CECILL-1.1', 'deprecated': False}, + 'cecill-2.0': {'id': 'CECILL-2.0', 'deprecated': False}, + 'cecill-2.1': {'id': 'CECILL-2.1', 'deprecated': False}, + 'cecill-b': {'id': 'CECILL-B', 'deprecated': False}, + 'cecill-c': {'id': 'CECILL-C', 'deprecated': False}, + 'cern-ohl-1.1': {'id': 'CERN-OHL-1.1', 'deprecated': False}, + 'cern-ohl-1.2': {'id': 'CERN-OHL-1.2', 'deprecated': False}, + 'cern-ohl-p-2.0': {'id': 'CERN-OHL-P-2.0', 'deprecated': False}, + 'cern-ohl-s-2.0': {'id': 'CERN-OHL-S-2.0', 'deprecated': False}, + 'cern-ohl-w-2.0': {'id': 'CERN-OHL-W-2.0', 'deprecated': False}, + 'cfitsio': {'id': 'CFITSIO', 'deprecated': False}, + 'check-cvs': {'id': 'check-cvs', 'deprecated': False}, + 'checkmk': {'id': 'checkmk', 'deprecated': False}, + 'clartistic': {'id': 'ClArtistic', 'deprecated': False}, + 'clips': {'id': 'Clips', 'deprecated': False}, + 'cmu-mach': {'id': 'CMU-Mach', 'deprecated': False}, + 'cmu-mach-nodoc': {'id': 'CMU-Mach-nodoc', 'deprecated': False}, + 'cnri-jython': {'id': 'CNRI-Jython', 'deprecated': False}, + 'cnri-python': {'id': 'CNRI-Python', 'deprecated': False}, + 'cnri-python-gpl-compatible': {'id': 'CNRI-Python-GPL-Compatible', 'deprecated': False}, + 'coil-1.0': {'id': 'COIL-1.0', 'deprecated': False}, + 'community-spec-1.0': {'id': 'Community-Spec-1.0', 'deprecated': False}, + 'condor-1.1': {'id': 'Condor-1.1', 'deprecated': False}, + 'copyleft-next-0.3.0': {'id': 'copyleft-next-0.3.0', 'deprecated': False}, + 'copyleft-next-0.3.1': {'id': 'copyleft-next-0.3.1', 'deprecated': False}, + 'cornell-lossless-jpeg': {'id': 'Cornell-Lossless-JPEG', 'deprecated': False}, + 'cpal-1.0': {'id': 'CPAL-1.0', 'deprecated': False}, + 'cpl-1.0': {'id': 'CPL-1.0', 'deprecated': False}, + 'cpol-1.02': {'id': 'CPOL-1.02', 'deprecated': False}, + 'cronyx': {'id': 'Cronyx', 'deprecated': False}, + 'crossword': {'id': 'Crossword', 'deprecated': False}, + 'cryptoswift': {'id': 'CryptoSwift', 'deprecated': False}, + 'crystalstacker': {'id': 'CrystalStacker', 'deprecated': False}, + 'cua-opl-1.0': {'id': 'CUA-OPL-1.0', 'deprecated': False}, + 'cube': {'id': 'Cube', 'deprecated': False}, + 'curl': {'id': 'curl', 'deprecated': False}, + 'cve-tou': {'id': 'cve-tou', 'deprecated': False}, + 'd-fsl-1.0': {'id': 'D-FSL-1.0', 'deprecated': False}, + 'dec-3-clause': {'id': 'DEC-3-Clause', 'deprecated': False}, + 'diffmark': {'id': 'diffmark', 'deprecated': False}, + 'dl-de-by-2.0': {'id': 'DL-DE-BY-2.0', 'deprecated': False}, + 'dl-de-zero-2.0': {'id': 'DL-DE-ZERO-2.0', 'deprecated': False}, + 'doc': {'id': 'DOC', 'deprecated': False}, + 'docbook-dtd': {'id': 'DocBook-DTD', 'deprecated': False}, + 'docbook-schema': {'id': 'DocBook-Schema', 'deprecated': False}, + 'docbook-stylesheet': {'id': 'DocBook-Stylesheet', 'deprecated': False}, + 'docbook-xml': {'id': 'DocBook-XML', 'deprecated': False}, + 'dotseqn': {'id': 'Dotseqn', 'deprecated': False}, + 'drl-1.0': {'id': 'DRL-1.0', 'deprecated': False}, + 'drl-1.1': {'id': 'DRL-1.1', 'deprecated': False}, + 'dsdp': {'id': 'DSDP', 'deprecated': False}, + 'dtoa': {'id': 'dtoa', 'deprecated': False}, + 'dvipdfm': {'id': 'dvipdfm', 'deprecated': False}, + 'ecl-1.0': {'id': 'ECL-1.0', 'deprecated': False}, + 'ecl-2.0': {'id': 'ECL-2.0', 'deprecated': False}, + 'ecos-2.0': {'id': 'eCos-2.0', 'deprecated': True}, + 'efl-1.0': {'id': 'EFL-1.0', 'deprecated': False}, + 'efl-2.0': {'id': 'EFL-2.0', 'deprecated': False}, + 'egenix': {'id': 'eGenix', 'deprecated': False}, + 'elastic-2.0': {'id': 'Elastic-2.0', 'deprecated': False}, + 'entessa': {'id': 'Entessa', 'deprecated': False}, + 'epics': {'id': 'EPICS', 'deprecated': False}, + 'epl-1.0': {'id': 'EPL-1.0', 'deprecated': False}, + 'epl-2.0': {'id': 'EPL-2.0', 'deprecated': False}, + 'erlpl-1.1': {'id': 'ErlPL-1.1', 'deprecated': False}, + 'etalab-2.0': {'id': 'etalab-2.0', 'deprecated': False}, + 'eudatagrid': {'id': 'EUDatagrid', 'deprecated': False}, + 'eupl-1.0': {'id': 'EUPL-1.0', 'deprecated': False}, + 'eupl-1.1': {'id': 'EUPL-1.1', 'deprecated': False}, + 'eupl-1.2': {'id': 'EUPL-1.2', 'deprecated': False}, + 'eurosym': {'id': 'Eurosym', 'deprecated': False}, + 'fair': {'id': 'Fair', 'deprecated': False}, + 'fbm': {'id': 'FBM', 'deprecated': False}, + 'fdk-aac': {'id': 'FDK-AAC', 'deprecated': False}, + 'ferguson-twofish': {'id': 'Ferguson-Twofish', 'deprecated': False}, + 'frameworx-1.0': {'id': 'Frameworx-1.0', 'deprecated': False}, + 'freebsd-doc': {'id': 'FreeBSD-DOC', 'deprecated': False}, + 'freeimage': {'id': 'FreeImage', 'deprecated': False}, + 'fsfap': {'id': 'FSFAP', 'deprecated': False}, + 'fsfap-no-warranty-disclaimer': {'id': 'FSFAP-no-warranty-disclaimer', 'deprecated': False}, + 'fsful': {'id': 'FSFUL', 'deprecated': False}, + 'fsfullr': {'id': 'FSFULLR', 'deprecated': False}, + 'fsfullrsd': {'id': 'FSFULLRSD', 'deprecated': False}, + 'fsfullrwd': {'id': 'FSFULLRWD', 'deprecated': False}, + 'fsl-1.1-alv2': {'id': 'FSL-1.1-ALv2', 'deprecated': False}, + 'fsl-1.1-mit': {'id': 'FSL-1.1-MIT', 'deprecated': False}, + 'ftl': {'id': 'FTL', 'deprecated': False}, + 'furuseth': {'id': 'Furuseth', 'deprecated': False}, + 'fwlw': {'id': 'fwlw', 'deprecated': False}, + 'game-programming-gems': {'id': 'Game-Programming-Gems', 'deprecated': False}, + 'gcr-docs': {'id': 'GCR-docs', 'deprecated': False}, + 'gd': {'id': 'GD', 'deprecated': False}, + 'generic-xts': {'id': 'generic-xts', 'deprecated': False}, + 'gfdl-1.1': {'id': 'GFDL-1.1', 'deprecated': True}, + 'gfdl-1.1-invariants-only': {'id': 'GFDL-1.1-invariants-only', 'deprecated': False}, + 'gfdl-1.1-invariants-or-later': {'id': 'GFDL-1.1-invariants-or-later', 'deprecated': False}, + 'gfdl-1.1-no-invariants-only': {'id': 'GFDL-1.1-no-invariants-only', 'deprecated': False}, + 'gfdl-1.1-no-invariants-or-later': {'id': 'GFDL-1.1-no-invariants-or-later', 'deprecated': False}, + 'gfdl-1.1-only': {'id': 'GFDL-1.1-only', 'deprecated': False}, + 'gfdl-1.1-or-later': {'id': 'GFDL-1.1-or-later', 'deprecated': False}, + 'gfdl-1.2': {'id': 'GFDL-1.2', 'deprecated': True}, + 'gfdl-1.2-invariants-only': {'id': 'GFDL-1.2-invariants-only', 'deprecated': False}, + 'gfdl-1.2-invariants-or-later': {'id': 'GFDL-1.2-invariants-or-later', 'deprecated': False}, + 'gfdl-1.2-no-invariants-only': {'id': 'GFDL-1.2-no-invariants-only', 'deprecated': False}, + 'gfdl-1.2-no-invariants-or-later': {'id': 'GFDL-1.2-no-invariants-or-later', 'deprecated': False}, + 'gfdl-1.2-only': {'id': 'GFDL-1.2-only', 'deprecated': False}, + 'gfdl-1.2-or-later': {'id': 'GFDL-1.2-or-later', 'deprecated': False}, + 'gfdl-1.3': {'id': 'GFDL-1.3', 'deprecated': True}, + 'gfdl-1.3-invariants-only': {'id': 'GFDL-1.3-invariants-only', 'deprecated': False}, + 'gfdl-1.3-invariants-or-later': {'id': 'GFDL-1.3-invariants-or-later', 'deprecated': False}, + 'gfdl-1.3-no-invariants-only': {'id': 'GFDL-1.3-no-invariants-only', 'deprecated': False}, + 'gfdl-1.3-no-invariants-or-later': {'id': 'GFDL-1.3-no-invariants-or-later', 'deprecated': False}, + 'gfdl-1.3-only': {'id': 'GFDL-1.3-only', 'deprecated': False}, + 'gfdl-1.3-or-later': {'id': 'GFDL-1.3-or-later', 'deprecated': False}, + 'giftware': {'id': 'Giftware', 'deprecated': False}, + 'gl2ps': {'id': 'GL2PS', 'deprecated': False}, + 'glide': {'id': 'Glide', 'deprecated': False}, + 'glulxe': {'id': 'Glulxe', 'deprecated': False}, + 'glwtpl': {'id': 'GLWTPL', 'deprecated': False}, + 'gnuplot': {'id': 'gnuplot', 'deprecated': False}, + 'gpl-1.0': {'id': 'GPL-1.0', 'deprecated': True}, + 'gpl-1.0+': {'id': 'GPL-1.0+', 'deprecated': True}, + 'gpl-1.0-only': {'id': 'GPL-1.0-only', 'deprecated': False}, + 'gpl-1.0-or-later': {'id': 'GPL-1.0-or-later', 'deprecated': False}, + 'gpl-2.0': {'id': 'GPL-2.0', 'deprecated': True}, + 'gpl-2.0+': {'id': 'GPL-2.0+', 'deprecated': True}, + 'gpl-2.0-only': {'id': 'GPL-2.0-only', 'deprecated': False}, + 'gpl-2.0-or-later': {'id': 'GPL-2.0-or-later', 'deprecated': False}, + 'gpl-2.0-with-autoconf-exception': {'id': 'GPL-2.0-with-autoconf-exception', 'deprecated': True}, + 'gpl-2.0-with-bison-exception': {'id': 'GPL-2.0-with-bison-exception', 'deprecated': True}, + 'gpl-2.0-with-classpath-exception': {'id': 'GPL-2.0-with-classpath-exception', 'deprecated': True}, + 'gpl-2.0-with-font-exception': {'id': 'GPL-2.0-with-font-exception', 'deprecated': True}, + 'gpl-2.0-with-gcc-exception': {'id': 'GPL-2.0-with-GCC-exception', 'deprecated': True}, + 'gpl-3.0': {'id': 'GPL-3.0', 'deprecated': True}, + 'gpl-3.0+': {'id': 'GPL-3.0+', 'deprecated': True}, + 'gpl-3.0-only': {'id': 'GPL-3.0-only', 'deprecated': False}, + 'gpl-3.0-or-later': {'id': 'GPL-3.0-or-later', 'deprecated': False}, + 'gpl-3.0-with-autoconf-exception': {'id': 'GPL-3.0-with-autoconf-exception', 'deprecated': True}, + 'gpl-3.0-with-gcc-exception': {'id': 'GPL-3.0-with-GCC-exception', 'deprecated': True}, + 'graphics-gems': {'id': 'Graphics-Gems', 'deprecated': False}, + 'gsoap-1.3b': {'id': 'gSOAP-1.3b', 'deprecated': False}, + 'gtkbook': {'id': 'gtkbook', 'deprecated': False}, + 'gutmann': {'id': 'Gutmann', 'deprecated': False}, + 'haskellreport': {'id': 'HaskellReport', 'deprecated': False}, + 'hdf5': {'id': 'HDF5', 'deprecated': False}, + 'hdparm': {'id': 'hdparm', 'deprecated': False}, + 'hidapi': {'id': 'HIDAPI', 'deprecated': False}, + 'hippocratic-2.1': {'id': 'Hippocratic-2.1', 'deprecated': False}, + 'hp-1986': {'id': 'HP-1986', 'deprecated': False}, + 'hp-1989': {'id': 'HP-1989', 'deprecated': False}, + 'hpnd': {'id': 'HPND', 'deprecated': False}, + 'hpnd-dec': {'id': 'HPND-DEC', 'deprecated': False}, + 'hpnd-doc': {'id': 'HPND-doc', 'deprecated': False}, + 'hpnd-doc-sell': {'id': 'HPND-doc-sell', 'deprecated': False}, + 'hpnd-export-us': {'id': 'HPND-export-US', 'deprecated': False}, + 'hpnd-export-us-acknowledgement': {'id': 'HPND-export-US-acknowledgement', 'deprecated': False}, + 'hpnd-export-us-modify': {'id': 'HPND-export-US-modify', 'deprecated': False}, + 'hpnd-export2-us': {'id': 'HPND-export2-US', 'deprecated': False}, + 'hpnd-fenneberg-livingston': {'id': 'HPND-Fenneberg-Livingston', 'deprecated': False}, + 'hpnd-inria-imag': {'id': 'HPND-INRIA-IMAG', 'deprecated': False}, + 'hpnd-intel': {'id': 'HPND-Intel', 'deprecated': False}, + 'hpnd-kevlin-henney': {'id': 'HPND-Kevlin-Henney', 'deprecated': False}, + 'hpnd-markus-kuhn': {'id': 'HPND-Markus-Kuhn', 'deprecated': False}, + 'hpnd-merchantability-variant': {'id': 'HPND-merchantability-variant', 'deprecated': False}, + 'hpnd-mit-disclaimer': {'id': 'HPND-MIT-disclaimer', 'deprecated': False}, + 'hpnd-netrek': {'id': 'HPND-Netrek', 'deprecated': False}, + 'hpnd-pbmplus': {'id': 'HPND-Pbmplus', 'deprecated': False}, + 'hpnd-sell-mit-disclaimer-xserver': {'id': 'HPND-sell-MIT-disclaimer-xserver', 'deprecated': False}, + 'hpnd-sell-regexpr': {'id': 'HPND-sell-regexpr', 'deprecated': False}, + 'hpnd-sell-variant': {'id': 'HPND-sell-variant', 'deprecated': False}, + 'hpnd-sell-variant-mit-disclaimer': {'id': 'HPND-sell-variant-MIT-disclaimer', 'deprecated': False}, + 'hpnd-sell-variant-mit-disclaimer-rev': {'id': 'HPND-sell-variant-MIT-disclaimer-rev', 'deprecated': False}, + 'hpnd-uc': {'id': 'HPND-UC', 'deprecated': False}, + 'hpnd-uc-export-us': {'id': 'HPND-UC-export-US', 'deprecated': False}, + 'htmltidy': {'id': 'HTMLTIDY', 'deprecated': False}, + 'ibm-pibs': {'id': 'IBM-pibs', 'deprecated': False}, + 'icu': {'id': 'ICU', 'deprecated': False}, + 'iec-code-components-eula': {'id': 'IEC-Code-Components-EULA', 'deprecated': False}, + 'ijg': {'id': 'IJG', 'deprecated': False}, + 'ijg-short': {'id': 'IJG-short', 'deprecated': False}, + 'imagemagick': {'id': 'ImageMagick', 'deprecated': False}, + 'imatix': {'id': 'iMatix', 'deprecated': False}, + 'imlib2': {'id': 'Imlib2', 'deprecated': False}, + 'info-zip': {'id': 'Info-ZIP', 'deprecated': False}, + 'inner-net-2.0': {'id': 'Inner-Net-2.0', 'deprecated': False}, + 'innosetup': {'id': 'InnoSetup', 'deprecated': False}, + 'intel': {'id': 'Intel', 'deprecated': False}, + 'intel-acpi': {'id': 'Intel-ACPI', 'deprecated': False}, + 'interbase-1.0': {'id': 'Interbase-1.0', 'deprecated': False}, + 'ipa': {'id': 'IPA', 'deprecated': False}, + 'ipl-1.0': {'id': 'IPL-1.0', 'deprecated': False}, + 'isc': {'id': 'ISC', 'deprecated': False}, + 'isc-veillard': {'id': 'ISC-Veillard', 'deprecated': False}, + 'jam': {'id': 'Jam', 'deprecated': False}, + 'jasper-2.0': {'id': 'JasPer-2.0', 'deprecated': False}, + 'jove': {'id': 'jove', 'deprecated': False}, + 'jpl-image': {'id': 'JPL-image', 'deprecated': False}, + 'jpnic': {'id': 'JPNIC', 'deprecated': False}, + 'json': {'id': 'JSON', 'deprecated': False}, + 'kastrup': {'id': 'Kastrup', 'deprecated': False}, + 'kazlib': {'id': 'Kazlib', 'deprecated': False}, + 'knuth-ctan': {'id': 'Knuth-CTAN', 'deprecated': False}, + 'lal-1.2': {'id': 'LAL-1.2', 'deprecated': False}, + 'lal-1.3': {'id': 'LAL-1.3', 'deprecated': False}, + 'latex2e': {'id': 'Latex2e', 'deprecated': False}, + 'latex2e-translated-notice': {'id': 'Latex2e-translated-notice', 'deprecated': False}, + 'leptonica': {'id': 'Leptonica', 'deprecated': False}, + 'lgpl-2.0': {'id': 'LGPL-2.0', 'deprecated': True}, + 'lgpl-2.0+': {'id': 'LGPL-2.0+', 'deprecated': True}, + 'lgpl-2.0-only': {'id': 'LGPL-2.0-only', 'deprecated': False}, + 'lgpl-2.0-or-later': {'id': 'LGPL-2.0-or-later', 'deprecated': False}, + 'lgpl-2.1': {'id': 'LGPL-2.1', 'deprecated': True}, + 'lgpl-2.1+': {'id': 'LGPL-2.1+', 'deprecated': True}, + 'lgpl-2.1-only': {'id': 'LGPL-2.1-only', 'deprecated': False}, + 'lgpl-2.1-or-later': {'id': 'LGPL-2.1-or-later', 'deprecated': False}, + 'lgpl-3.0': {'id': 'LGPL-3.0', 'deprecated': True}, + 'lgpl-3.0+': {'id': 'LGPL-3.0+', 'deprecated': True}, + 'lgpl-3.0-only': {'id': 'LGPL-3.0-only', 'deprecated': False}, + 'lgpl-3.0-or-later': {'id': 'LGPL-3.0-or-later', 'deprecated': False}, + 'lgpllr': {'id': 'LGPLLR', 'deprecated': False}, + 'libpng': {'id': 'Libpng', 'deprecated': False}, + 'libpng-1.6.35': {'id': 'libpng-1.6.35', 'deprecated': False}, + 'libpng-2.0': {'id': 'libpng-2.0', 'deprecated': False}, + 'libselinux-1.0': {'id': 'libselinux-1.0', 'deprecated': False}, + 'libtiff': {'id': 'libtiff', 'deprecated': False}, + 'libutil-david-nugent': {'id': 'libutil-David-Nugent', 'deprecated': False}, + 'liliq-p-1.1': {'id': 'LiLiQ-P-1.1', 'deprecated': False}, + 'liliq-r-1.1': {'id': 'LiLiQ-R-1.1', 'deprecated': False}, + 'liliq-rplus-1.1': {'id': 'LiLiQ-Rplus-1.1', 'deprecated': False}, + 'linux-man-pages-1-para': {'id': 'Linux-man-pages-1-para', 'deprecated': False}, + 'linux-man-pages-copyleft': {'id': 'Linux-man-pages-copyleft', 'deprecated': False}, + 'linux-man-pages-copyleft-2-para': {'id': 'Linux-man-pages-copyleft-2-para', 'deprecated': False}, + 'linux-man-pages-copyleft-var': {'id': 'Linux-man-pages-copyleft-var', 'deprecated': False}, + 'linux-openib': {'id': 'Linux-OpenIB', 'deprecated': False}, + 'loop': {'id': 'LOOP', 'deprecated': False}, + 'lpd-document': {'id': 'LPD-document', 'deprecated': False}, + 'lpl-1.0': {'id': 'LPL-1.0', 'deprecated': False}, + 'lpl-1.02': {'id': 'LPL-1.02', 'deprecated': False}, + 'lppl-1.0': {'id': 'LPPL-1.0', 'deprecated': False}, + 'lppl-1.1': {'id': 'LPPL-1.1', 'deprecated': False}, + 'lppl-1.2': {'id': 'LPPL-1.2', 'deprecated': False}, + 'lppl-1.3a': {'id': 'LPPL-1.3a', 'deprecated': False}, + 'lppl-1.3c': {'id': 'LPPL-1.3c', 'deprecated': False}, + 'lsof': {'id': 'lsof', 'deprecated': False}, + 'lucida-bitmap-fonts': {'id': 'Lucida-Bitmap-Fonts', 'deprecated': False}, + 'lzma-sdk-9.11-to-9.20': {'id': 'LZMA-SDK-9.11-to-9.20', 'deprecated': False}, + 'lzma-sdk-9.22': {'id': 'LZMA-SDK-9.22', 'deprecated': False}, + 'mackerras-3-clause': {'id': 'Mackerras-3-Clause', 'deprecated': False}, + 'mackerras-3-clause-acknowledgment': {'id': 'Mackerras-3-Clause-acknowledgment', 'deprecated': False}, + 'magaz': {'id': 'magaz', 'deprecated': False}, + 'mailprio': {'id': 'mailprio', 'deprecated': False}, + 'makeindex': {'id': 'MakeIndex', 'deprecated': False}, + 'man2html': {'id': 'man2html', 'deprecated': False}, + 'martin-birgmeier': {'id': 'Martin-Birgmeier', 'deprecated': False}, + 'mcphee-slideshow': {'id': 'McPhee-slideshow', 'deprecated': False}, + 'metamail': {'id': 'metamail', 'deprecated': False}, + 'minpack': {'id': 'Minpack', 'deprecated': False}, + 'mips': {'id': 'MIPS', 'deprecated': False}, + 'miros': {'id': 'MirOS', 'deprecated': False}, + 'mit': {'id': 'MIT', 'deprecated': False}, + 'mit-0': {'id': 'MIT-0', 'deprecated': False}, + 'mit-advertising': {'id': 'MIT-advertising', 'deprecated': False}, + 'mit-click': {'id': 'MIT-Click', 'deprecated': False}, + 'mit-cmu': {'id': 'MIT-CMU', 'deprecated': False}, + 'mit-enna': {'id': 'MIT-enna', 'deprecated': False}, + 'mit-feh': {'id': 'MIT-feh', 'deprecated': False}, + 'mit-festival': {'id': 'MIT-Festival', 'deprecated': False}, + 'mit-khronos-old': {'id': 'MIT-Khronos-old', 'deprecated': False}, + 'mit-modern-variant': {'id': 'MIT-Modern-Variant', 'deprecated': False}, + 'mit-open-group': {'id': 'MIT-open-group', 'deprecated': False}, + 'mit-testregex': {'id': 'MIT-testregex', 'deprecated': False}, + 'mit-wu': {'id': 'MIT-Wu', 'deprecated': False}, + 'mitnfa': {'id': 'MITNFA', 'deprecated': False}, + 'mmixware': {'id': 'MMIXware', 'deprecated': False}, + 'motosoto': {'id': 'Motosoto', 'deprecated': False}, + 'mpeg-ssg': {'id': 'MPEG-SSG', 'deprecated': False}, + 'mpi-permissive': {'id': 'mpi-permissive', 'deprecated': False}, + 'mpich2': {'id': 'mpich2', 'deprecated': False}, + 'mpl-1.0': {'id': 'MPL-1.0', 'deprecated': False}, + 'mpl-1.1': {'id': 'MPL-1.1', 'deprecated': False}, + 'mpl-2.0': {'id': 'MPL-2.0', 'deprecated': False}, + 'mpl-2.0-no-copyleft-exception': {'id': 'MPL-2.0-no-copyleft-exception', 'deprecated': False}, + 'mplus': {'id': 'mplus', 'deprecated': False}, + 'ms-lpl': {'id': 'MS-LPL', 'deprecated': False}, + 'ms-pl': {'id': 'MS-PL', 'deprecated': False}, + 'ms-rl': {'id': 'MS-RL', 'deprecated': False}, + 'mtll': {'id': 'MTLL', 'deprecated': False}, + 'mulanpsl-1.0': {'id': 'MulanPSL-1.0', 'deprecated': False}, + 'mulanpsl-2.0': {'id': 'MulanPSL-2.0', 'deprecated': False}, + 'multics': {'id': 'Multics', 'deprecated': False}, + 'mup': {'id': 'Mup', 'deprecated': False}, + 'naist-2003': {'id': 'NAIST-2003', 'deprecated': False}, + 'nasa-1.3': {'id': 'NASA-1.3', 'deprecated': False}, + 'naumen': {'id': 'Naumen', 'deprecated': False}, + 'nbpl-1.0': {'id': 'NBPL-1.0', 'deprecated': False}, + 'ncbi-pd': {'id': 'NCBI-PD', 'deprecated': False}, + 'ncgl-uk-2.0': {'id': 'NCGL-UK-2.0', 'deprecated': False}, + 'ncl': {'id': 'NCL', 'deprecated': False}, + 'ncsa': {'id': 'NCSA', 'deprecated': False}, + 'net-snmp': {'id': 'Net-SNMP', 'deprecated': True}, + 'netcdf': {'id': 'NetCDF', 'deprecated': False}, + 'newsletr': {'id': 'Newsletr', 'deprecated': False}, + 'ngpl': {'id': 'NGPL', 'deprecated': False}, + 'ngrep': {'id': 'ngrep', 'deprecated': False}, + 'nicta-1.0': {'id': 'NICTA-1.0', 'deprecated': False}, + 'nist-pd': {'id': 'NIST-PD', 'deprecated': False}, + 'nist-pd-fallback': {'id': 'NIST-PD-fallback', 'deprecated': False}, + 'nist-software': {'id': 'NIST-Software', 'deprecated': False}, + 'nlod-1.0': {'id': 'NLOD-1.0', 'deprecated': False}, + 'nlod-2.0': {'id': 'NLOD-2.0', 'deprecated': False}, + 'nlpl': {'id': 'NLPL', 'deprecated': False}, + 'nokia': {'id': 'Nokia', 'deprecated': False}, + 'nosl': {'id': 'NOSL', 'deprecated': False}, + 'noweb': {'id': 'Noweb', 'deprecated': False}, + 'npl-1.0': {'id': 'NPL-1.0', 'deprecated': False}, + 'npl-1.1': {'id': 'NPL-1.1', 'deprecated': False}, + 'nposl-3.0': {'id': 'NPOSL-3.0', 'deprecated': False}, + 'nrl': {'id': 'NRL', 'deprecated': False}, + 'ntia-pd': {'id': 'NTIA-PD', 'deprecated': False}, + 'ntp': {'id': 'NTP', 'deprecated': False}, + 'ntp-0': {'id': 'NTP-0', 'deprecated': False}, + 'nunit': {'id': 'Nunit', 'deprecated': True}, + 'o-uda-1.0': {'id': 'O-UDA-1.0', 'deprecated': False}, + 'oar': {'id': 'OAR', 'deprecated': False}, + 'occt-pl': {'id': 'OCCT-PL', 'deprecated': False}, + 'oclc-2.0': {'id': 'OCLC-2.0', 'deprecated': False}, + 'odbl-1.0': {'id': 'ODbL-1.0', 'deprecated': False}, + 'odc-by-1.0': {'id': 'ODC-By-1.0', 'deprecated': False}, + 'offis': {'id': 'OFFIS', 'deprecated': False}, + 'ofl-1.0': {'id': 'OFL-1.0', 'deprecated': False}, + 'ofl-1.0-no-rfn': {'id': 'OFL-1.0-no-RFN', 'deprecated': False}, + 'ofl-1.0-rfn': {'id': 'OFL-1.0-RFN', 'deprecated': False}, + 'ofl-1.1': {'id': 'OFL-1.1', 'deprecated': False}, + 'ofl-1.1-no-rfn': {'id': 'OFL-1.1-no-RFN', 'deprecated': False}, + 'ofl-1.1-rfn': {'id': 'OFL-1.1-RFN', 'deprecated': False}, + 'ogc-1.0': {'id': 'OGC-1.0', 'deprecated': False}, + 'ogdl-taiwan-1.0': {'id': 'OGDL-Taiwan-1.0', 'deprecated': False}, + 'ogl-canada-2.0': {'id': 'OGL-Canada-2.0', 'deprecated': False}, + 'ogl-uk-1.0': {'id': 'OGL-UK-1.0', 'deprecated': False}, + 'ogl-uk-2.0': {'id': 'OGL-UK-2.0', 'deprecated': False}, + 'ogl-uk-3.0': {'id': 'OGL-UK-3.0', 'deprecated': False}, + 'ogtsl': {'id': 'OGTSL', 'deprecated': False}, + 'oldap-1.1': {'id': 'OLDAP-1.1', 'deprecated': False}, + 'oldap-1.2': {'id': 'OLDAP-1.2', 'deprecated': False}, + 'oldap-1.3': {'id': 'OLDAP-1.3', 'deprecated': False}, + 'oldap-1.4': {'id': 'OLDAP-1.4', 'deprecated': False}, + 'oldap-2.0': {'id': 'OLDAP-2.0', 'deprecated': False}, + 'oldap-2.0.1': {'id': 'OLDAP-2.0.1', 'deprecated': False}, + 'oldap-2.1': {'id': 'OLDAP-2.1', 'deprecated': False}, + 'oldap-2.2': {'id': 'OLDAP-2.2', 'deprecated': False}, + 'oldap-2.2.1': {'id': 'OLDAP-2.2.1', 'deprecated': False}, + 'oldap-2.2.2': {'id': 'OLDAP-2.2.2', 'deprecated': False}, + 'oldap-2.3': {'id': 'OLDAP-2.3', 'deprecated': False}, + 'oldap-2.4': {'id': 'OLDAP-2.4', 'deprecated': False}, + 'oldap-2.5': {'id': 'OLDAP-2.5', 'deprecated': False}, + 'oldap-2.6': {'id': 'OLDAP-2.6', 'deprecated': False}, + 'oldap-2.7': {'id': 'OLDAP-2.7', 'deprecated': False}, + 'oldap-2.8': {'id': 'OLDAP-2.8', 'deprecated': False}, + 'olfl-1.3': {'id': 'OLFL-1.3', 'deprecated': False}, + 'oml': {'id': 'OML', 'deprecated': False}, + 'openpbs-2.3': {'id': 'OpenPBS-2.3', 'deprecated': False}, + 'openssl': {'id': 'OpenSSL', 'deprecated': False}, + 'openssl-standalone': {'id': 'OpenSSL-standalone', 'deprecated': False}, + 'openvision': {'id': 'OpenVision', 'deprecated': False}, + 'opl-1.0': {'id': 'OPL-1.0', 'deprecated': False}, + 'opl-uk-3.0': {'id': 'OPL-UK-3.0', 'deprecated': False}, + 'opubl-1.0': {'id': 'OPUBL-1.0', 'deprecated': False}, + 'oset-pl-2.1': {'id': 'OSET-PL-2.1', 'deprecated': False}, + 'osl-1.0': {'id': 'OSL-1.0', 'deprecated': False}, + 'osl-1.1': {'id': 'OSL-1.1', 'deprecated': False}, + 'osl-2.0': {'id': 'OSL-2.0', 'deprecated': False}, + 'osl-2.1': {'id': 'OSL-2.1', 'deprecated': False}, + 'osl-3.0': {'id': 'OSL-3.0', 'deprecated': False}, + 'padl': {'id': 'PADL', 'deprecated': False}, + 'parity-6.0.0': {'id': 'Parity-6.0.0', 'deprecated': False}, + 'parity-7.0.0': {'id': 'Parity-7.0.0', 'deprecated': False}, + 'pddl-1.0': {'id': 'PDDL-1.0', 'deprecated': False}, + 'php-3.0': {'id': 'PHP-3.0', 'deprecated': False}, + 'php-3.01': {'id': 'PHP-3.01', 'deprecated': False}, + 'pixar': {'id': 'Pixar', 'deprecated': False}, + 'pkgconf': {'id': 'pkgconf', 'deprecated': False}, + 'plexus': {'id': 'Plexus', 'deprecated': False}, + 'pnmstitch': {'id': 'pnmstitch', 'deprecated': False}, + 'polyform-noncommercial-1.0.0': {'id': 'PolyForm-Noncommercial-1.0.0', 'deprecated': False}, + 'polyform-small-business-1.0.0': {'id': 'PolyForm-Small-Business-1.0.0', 'deprecated': False}, + 'postgresql': {'id': 'PostgreSQL', 'deprecated': False}, + 'ppl': {'id': 'PPL', 'deprecated': False}, + 'psf-2.0': {'id': 'PSF-2.0', 'deprecated': False}, + 'psfrag': {'id': 'psfrag', 'deprecated': False}, + 'psutils': {'id': 'psutils', 'deprecated': False}, + 'python-2.0': {'id': 'Python-2.0', 'deprecated': False}, + 'python-2.0.1': {'id': 'Python-2.0.1', 'deprecated': False}, + 'python-ldap': {'id': 'python-ldap', 'deprecated': False}, + 'qhull': {'id': 'Qhull', 'deprecated': False}, + 'qpl-1.0': {'id': 'QPL-1.0', 'deprecated': False}, + 'qpl-1.0-inria-2004': {'id': 'QPL-1.0-INRIA-2004', 'deprecated': False}, + 'radvd': {'id': 'radvd', 'deprecated': False}, + 'rdisc': {'id': 'Rdisc', 'deprecated': False}, + 'rhecos-1.1': {'id': 'RHeCos-1.1', 'deprecated': False}, + 'rpl-1.1': {'id': 'RPL-1.1', 'deprecated': False}, + 'rpl-1.5': {'id': 'RPL-1.5', 'deprecated': False}, + 'rpsl-1.0': {'id': 'RPSL-1.0', 'deprecated': False}, + 'rsa-md': {'id': 'RSA-MD', 'deprecated': False}, + 'rscpl': {'id': 'RSCPL', 'deprecated': False}, + 'ruby': {'id': 'Ruby', 'deprecated': False}, + 'ruby-pty': {'id': 'Ruby-pty', 'deprecated': False}, + 'sax-pd': {'id': 'SAX-PD', 'deprecated': False}, + 'sax-pd-2.0': {'id': 'SAX-PD-2.0', 'deprecated': False}, + 'saxpath': {'id': 'Saxpath', 'deprecated': False}, + 'scea': {'id': 'SCEA', 'deprecated': False}, + 'schemereport': {'id': 'SchemeReport', 'deprecated': False}, + 'sendmail': {'id': 'Sendmail', 'deprecated': False}, + 'sendmail-8.23': {'id': 'Sendmail-8.23', 'deprecated': False}, + 'sendmail-open-source-1.1': {'id': 'Sendmail-Open-Source-1.1', 'deprecated': False}, + 'sgi-b-1.0': {'id': 'SGI-B-1.0', 'deprecated': False}, + 'sgi-b-1.1': {'id': 'SGI-B-1.1', 'deprecated': False}, + 'sgi-b-2.0': {'id': 'SGI-B-2.0', 'deprecated': False}, + 'sgi-opengl': {'id': 'SGI-OpenGL', 'deprecated': False}, + 'sgp4': {'id': 'SGP4', 'deprecated': False}, + 'shl-0.5': {'id': 'SHL-0.5', 'deprecated': False}, + 'shl-0.51': {'id': 'SHL-0.51', 'deprecated': False}, + 'simpl-2.0': {'id': 'SimPL-2.0', 'deprecated': False}, + 'sissl': {'id': 'SISSL', 'deprecated': False}, + 'sissl-1.2': {'id': 'SISSL-1.2', 'deprecated': False}, + 'sl': {'id': 'SL', 'deprecated': False}, + 'sleepycat': {'id': 'Sleepycat', 'deprecated': False}, + 'smail-gpl': {'id': 'SMAIL-GPL', 'deprecated': False}, + 'smlnj': {'id': 'SMLNJ', 'deprecated': False}, + 'smppl': {'id': 'SMPPL', 'deprecated': False}, + 'snia': {'id': 'SNIA', 'deprecated': False}, + 'snprintf': {'id': 'snprintf', 'deprecated': False}, + 'sofa': {'id': 'SOFA', 'deprecated': False}, + 'softsurfer': {'id': 'softSurfer', 'deprecated': False}, + 'soundex': {'id': 'Soundex', 'deprecated': False}, + 'spencer-86': {'id': 'Spencer-86', 'deprecated': False}, + 'spencer-94': {'id': 'Spencer-94', 'deprecated': False}, + 'spencer-99': {'id': 'Spencer-99', 'deprecated': False}, + 'spl-1.0': {'id': 'SPL-1.0', 'deprecated': False}, + 'ssh-keyscan': {'id': 'ssh-keyscan', 'deprecated': False}, + 'ssh-openssh': {'id': 'SSH-OpenSSH', 'deprecated': False}, + 'ssh-short': {'id': 'SSH-short', 'deprecated': False}, + 'ssleay-standalone': {'id': 'SSLeay-standalone', 'deprecated': False}, + 'sspl-1.0': {'id': 'SSPL-1.0', 'deprecated': False}, + 'standardml-nj': {'id': 'StandardML-NJ', 'deprecated': True}, + 'sugarcrm-1.1.3': {'id': 'SugarCRM-1.1.3', 'deprecated': False}, + 'sul-1.0': {'id': 'SUL-1.0', 'deprecated': False}, + 'sun-ppp': {'id': 'Sun-PPP', 'deprecated': False}, + 'sun-ppp-2000': {'id': 'Sun-PPP-2000', 'deprecated': False}, + 'sunpro': {'id': 'SunPro', 'deprecated': False}, + 'swl': {'id': 'SWL', 'deprecated': False}, + 'swrule': {'id': 'swrule', 'deprecated': False}, + 'symlinks': {'id': 'Symlinks', 'deprecated': False}, + 'tapr-ohl-1.0': {'id': 'TAPR-OHL-1.0', 'deprecated': False}, + 'tcl': {'id': 'TCL', 'deprecated': False}, + 'tcp-wrappers': {'id': 'TCP-wrappers', 'deprecated': False}, + 'termreadkey': {'id': 'TermReadKey', 'deprecated': False}, + 'tgppl-1.0': {'id': 'TGPPL-1.0', 'deprecated': False}, + 'thirdeye': {'id': 'ThirdEye', 'deprecated': False}, + 'threeparttable': {'id': 'threeparttable', 'deprecated': False}, + 'tmate': {'id': 'TMate', 'deprecated': False}, + 'torque-1.1': {'id': 'TORQUE-1.1', 'deprecated': False}, + 'tosl': {'id': 'TOSL', 'deprecated': False}, + 'tpdl': {'id': 'TPDL', 'deprecated': False}, + 'tpl-1.0': {'id': 'TPL-1.0', 'deprecated': False}, + 'trustedqsl': {'id': 'TrustedQSL', 'deprecated': False}, + 'ttwl': {'id': 'TTWL', 'deprecated': False}, + 'ttyp0': {'id': 'TTYP0', 'deprecated': False}, + 'tu-berlin-1.0': {'id': 'TU-Berlin-1.0', 'deprecated': False}, + 'tu-berlin-2.0': {'id': 'TU-Berlin-2.0', 'deprecated': False}, + 'ubuntu-font-1.0': {'id': 'Ubuntu-font-1.0', 'deprecated': False}, + 'ucar': {'id': 'UCAR', 'deprecated': False}, + 'ucl-1.0': {'id': 'UCL-1.0', 'deprecated': False}, + 'ulem': {'id': 'ulem', 'deprecated': False}, + 'umich-merit': {'id': 'UMich-Merit', 'deprecated': False}, + 'unicode-3.0': {'id': 'Unicode-3.0', 'deprecated': False}, + 'unicode-dfs-2015': {'id': 'Unicode-DFS-2015', 'deprecated': False}, + 'unicode-dfs-2016': {'id': 'Unicode-DFS-2016', 'deprecated': False}, + 'unicode-tou': {'id': 'Unicode-TOU', 'deprecated': False}, + 'unixcrypt': {'id': 'UnixCrypt', 'deprecated': False}, + 'unlicense': {'id': 'Unlicense', 'deprecated': False}, + 'unlicense-libtelnet': {'id': 'Unlicense-libtelnet', 'deprecated': False}, + 'unlicense-libwhirlpool': {'id': 'Unlicense-libwhirlpool', 'deprecated': False}, + 'upl-1.0': {'id': 'UPL-1.0', 'deprecated': False}, + 'urt-rle': {'id': 'URT-RLE', 'deprecated': False}, + 'vim': {'id': 'Vim', 'deprecated': False}, + 'vostrom': {'id': 'VOSTROM', 'deprecated': False}, + 'vsl-1.0': {'id': 'VSL-1.0', 'deprecated': False}, + 'w3c': {'id': 'W3C', 'deprecated': False}, + 'w3c-19980720': {'id': 'W3C-19980720', 'deprecated': False}, + 'w3c-20150513': {'id': 'W3C-20150513', 'deprecated': False}, + 'w3m': {'id': 'w3m', 'deprecated': False}, + 'watcom-1.0': {'id': 'Watcom-1.0', 'deprecated': False}, + 'widget-workshop': {'id': 'Widget-Workshop', 'deprecated': False}, + 'wsuipa': {'id': 'Wsuipa', 'deprecated': False}, + 'wtfpl': {'id': 'WTFPL', 'deprecated': False}, + 'wwl': {'id': 'wwl', 'deprecated': False}, + 'wxwindows': {'id': 'wxWindows', 'deprecated': True}, + 'x11': {'id': 'X11', 'deprecated': False}, + 'x11-distribute-modifications-variant': {'id': 'X11-distribute-modifications-variant', 'deprecated': False}, + 'x11-swapped': {'id': 'X11-swapped', 'deprecated': False}, + 'xdebug-1.03': {'id': 'Xdebug-1.03', 'deprecated': False}, + 'xerox': {'id': 'Xerox', 'deprecated': False}, + 'xfig': {'id': 'Xfig', 'deprecated': False}, + 'xfree86-1.1': {'id': 'XFree86-1.1', 'deprecated': False}, + 'xinetd': {'id': 'xinetd', 'deprecated': False}, + 'xkeyboard-config-zinoviev': {'id': 'xkeyboard-config-Zinoviev', 'deprecated': False}, + 'xlock': {'id': 'xlock', 'deprecated': False}, + 'xnet': {'id': 'Xnet', 'deprecated': False}, + 'xpp': {'id': 'xpp', 'deprecated': False}, + 'xskat': {'id': 'XSkat', 'deprecated': False}, + 'xzoom': {'id': 'xzoom', 'deprecated': False}, + 'ypl-1.0': {'id': 'YPL-1.0', 'deprecated': False}, + 'ypl-1.1': {'id': 'YPL-1.1', 'deprecated': False}, + 'zed': {'id': 'Zed', 'deprecated': False}, + 'zeeff': {'id': 'Zeeff', 'deprecated': False}, + 'zend-2.0': {'id': 'Zend-2.0', 'deprecated': False}, + 'zimbra-1.3': {'id': 'Zimbra-1.3', 'deprecated': False}, + 'zimbra-1.4': {'id': 'Zimbra-1.4', 'deprecated': False}, + 'zlib': {'id': 'Zlib', 'deprecated': False}, + 'zlib-acknowledgement': {'id': 'zlib-acknowledgement', 'deprecated': False}, + 'zpl-1.1': {'id': 'ZPL-1.1', 'deprecated': False}, + 'zpl-2.0': {'id': 'ZPL-2.0', 'deprecated': False}, + 'zpl-2.1': {'id': 'ZPL-2.1', 'deprecated': False}, +} + +EXCEPTIONS: dict[str, SPDXException] = { + '389-exception': {'id': '389-exception', 'deprecated': False}, + 'asterisk-exception': {'id': 'Asterisk-exception', 'deprecated': False}, + 'asterisk-linking-protocols-exception': {'id': 'Asterisk-linking-protocols-exception', 'deprecated': False}, + 'autoconf-exception-2.0': {'id': 'Autoconf-exception-2.0', 'deprecated': False}, + 'autoconf-exception-3.0': {'id': 'Autoconf-exception-3.0', 'deprecated': False}, + 'autoconf-exception-generic': {'id': 'Autoconf-exception-generic', 'deprecated': False}, + 'autoconf-exception-generic-3.0': {'id': 'Autoconf-exception-generic-3.0', 'deprecated': False}, + 'autoconf-exception-macro': {'id': 'Autoconf-exception-macro', 'deprecated': False}, + 'bison-exception-1.24': {'id': 'Bison-exception-1.24', 'deprecated': False}, + 'bison-exception-2.2': {'id': 'Bison-exception-2.2', 'deprecated': False}, + 'bootloader-exception': {'id': 'Bootloader-exception', 'deprecated': False}, + 'cgal-linking-exception': {'id': 'CGAL-linking-exception', 'deprecated': False}, + 'classpath-exception-2.0': {'id': 'Classpath-exception-2.0', 'deprecated': False}, + 'clisp-exception-2.0': {'id': 'CLISP-exception-2.0', 'deprecated': False}, + 'cryptsetup-openssl-exception': {'id': 'cryptsetup-OpenSSL-exception', 'deprecated': False}, + 'digia-qt-lgpl-exception-1.1': {'id': 'Digia-Qt-LGPL-exception-1.1', 'deprecated': False}, + 'digirule-foss-exception': {'id': 'DigiRule-FOSS-exception', 'deprecated': False}, + 'ecos-exception-2.0': {'id': 'eCos-exception-2.0', 'deprecated': False}, + 'erlang-otp-linking-exception': {'id': 'erlang-otp-linking-exception', 'deprecated': False}, + 'fawkes-runtime-exception': {'id': 'Fawkes-Runtime-exception', 'deprecated': False}, + 'fltk-exception': {'id': 'FLTK-exception', 'deprecated': False}, + 'fmt-exception': {'id': 'fmt-exception', 'deprecated': False}, + 'font-exception-2.0': {'id': 'Font-exception-2.0', 'deprecated': False}, + 'freertos-exception-2.0': {'id': 'freertos-exception-2.0', 'deprecated': False}, + 'gcc-exception-2.0': {'id': 'GCC-exception-2.0', 'deprecated': False}, + 'gcc-exception-2.0-note': {'id': 'GCC-exception-2.0-note', 'deprecated': False}, + 'gcc-exception-3.1': {'id': 'GCC-exception-3.1', 'deprecated': False}, + 'gmsh-exception': {'id': 'Gmsh-exception', 'deprecated': False}, + 'gnat-exception': {'id': 'GNAT-exception', 'deprecated': False}, + 'gnome-examples-exception': {'id': 'GNOME-examples-exception', 'deprecated': False}, + 'gnu-compiler-exception': {'id': 'GNU-compiler-exception', 'deprecated': False}, + 'gnu-javamail-exception': {'id': 'gnu-javamail-exception', 'deprecated': False}, + 'gpl-3.0-389-ds-base-exception': {'id': 'GPL-3.0-389-ds-base-exception', 'deprecated': False}, + 'gpl-3.0-interface-exception': {'id': 'GPL-3.0-interface-exception', 'deprecated': False}, + 'gpl-3.0-linking-exception': {'id': 'GPL-3.0-linking-exception', 'deprecated': False}, + 'gpl-3.0-linking-source-exception': {'id': 'GPL-3.0-linking-source-exception', 'deprecated': False}, + 'gpl-cc-1.0': {'id': 'GPL-CC-1.0', 'deprecated': False}, + 'gstreamer-exception-2005': {'id': 'GStreamer-exception-2005', 'deprecated': False}, + 'gstreamer-exception-2008': {'id': 'GStreamer-exception-2008', 'deprecated': False}, + 'harbour-exception': {'id': 'harbour-exception', 'deprecated': False}, + 'i2p-gpl-java-exception': {'id': 'i2p-gpl-java-exception', 'deprecated': False}, + 'independent-modules-exception': {'id': 'Independent-modules-exception', 'deprecated': False}, + 'kicad-libraries-exception': {'id': 'KiCad-libraries-exception', 'deprecated': False}, + 'lgpl-3.0-linking-exception': {'id': 'LGPL-3.0-linking-exception', 'deprecated': False}, + 'libpri-openh323-exception': {'id': 'libpri-OpenH323-exception', 'deprecated': False}, + 'libtool-exception': {'id': 'Libtool-exception', 'deprecated': False}, + 'linux-syscall-note': {'id': 'Linux-syscall-note', 'deprecated': False}, + 'llgpl': {'id': 'LLGPL', 'deprecated': False}, + 'llvm-exception': {'id': 'LLVM-exception', 'deprecated': False}, + 'lzma-exception': {'id': 'LZMA-exception', 'deprecated': False}, + 'mif-exception': {'id': 'mif-exception', 'deprecated': False}, + 'mxml-exception': {'id': 'mxml-exception', 'deprecated': False}, + 'nokia-qt-exception-1.1': {'id': 'Nokia-Qt-exception-1.1', 'deprecated': True}, + 'ocaml-lgpl-linking-exception': {'id': 'OCaml-LGPL-linking-exception', 'deprecated': False}, + 'occt-exception-1.0': {'id': 'OCCT-exception-1.0', 'deprecated': False}, + 'openjdk-assembly-exception-1.0': {'id': 'OpenJDK-assembly-exception-1.0', 'deprecated': False}, + 'openvpn-openssl-exception': {'id': 'openvpn-openssl-exception', 'deprecated': False}, + 'pcre2-exception': {'id': 'PCRE2-exception', 'deprecated': False}, + 'polyparse-exception': {'id': 'polyparse-exception', 'deprecated': False}, + 'ps-or-pdf-font-exception-20170817': {'id': 'PS-or-PDF-font-exception-20170817', 'deprecated': False}, + 'qpl-1.0-inria-2004-exception': {'id': 'QPL-1.0-INRIA-2004-exception', 'deprecated': False}, + 'qt-gpl-exception-1.0': {'id': 'Qt-GPL-exception-1.0', 'deprecated': False}, + 'qt-lgpl-exception-1.1': {'id': 'Qt-LGPL-exception-1.1', 'deprecated': False}, + 'qwt-exception-1.0': {'id': 'Qwt-exception-1.0', 'deprecated': False}, + 'romic-exception': {'id': 'romic-exception', 'deprecated': False}, + 'rrdtool-floss-exception-2.0': {'id': 'RRDtool-FLOSS-exception-2.0', 'deprecated': False}, + 'sane-exception': {'id': 'SANE-exception', 'deprecated': False}, + 'shl-2.0': {'id': 'SHL-2.0', 'deprecated': False}, + 'shl-2.1': {'id': 'SHL-2.1', 'deprecated': False}, + 'stunnel-exception': {'id': 'stunnel-exception', 'deprecated': False}, + 'swi-exception': {'id': 'SWI-exception', 'deprecated': False}, + 'swift-exception': {'id': 'Swift-exception', 'deprecated': False}, + 'texinfo-exception': {'id': 'Texinfo-exception', 'deprecated': False}, + 'u-boot-exception-2.0': {'id': 'u-boot-exception-2.0', 'deprecated': False}, + 'ubdl-exception': {'id': 'UBDL-exception', 'deprecated': False}, + 'universal-foss-exception-1.0': {'id': 'Universal-FOSS-exception-1.0', 'deprecated': False}, + 'vsftpd-openssl-exception': {'id': 'vsftpd-openssl-exception', 'deprecated': False}, + 'wxwindows-exception-3.1': {'id': 'WxWindows-exception-3.1', 'deprecated': False}, + 'x11vnc-openssl-exception': {'id': 'x11vnc-openssl-exception', 'deprecated': False}, +} diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/markers.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/markers.py new file mode 100644 index 0000000..564451f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/markers.py @@ -0,0 +1,492 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import operator +import os +import platform +import sys +from typing import AbstractSet, Callable, Literal, Mapping, TypedDict, Union, cast + +from ._parser import MarkerAtom, MarkerList, Op, Value, Variable +from ._parser import parse_marker as _parse_marker +from ._tokenizer import ParserSyntaxError +from .specifiers import InvalidSpecifier, Specifier +from .utils import canonicalize_name + +__all__ = [ + "Environment", + "EvaluateContext", + "InvalidMarker", + "Marker", + "UndefinedComparison", + "UndefinedEnvironmentName", + "default_environment", +] + + +def __dir__() -> list[str]: + return __all__ + + +Operator = Callable[[str, Union[str, AbstractSet[str]]], bool] +EvaluateContext = Literal["metadata", "lock_file", "requirement"] +"""A ``typing.Literal`` enumerating valid marker evaluation contexts. + +Valid values for the ``context`` passed to :meth:`Marker.evaluate` are: + +* ``"metadata"`` (for core metadata; default) +* ``"lock_file"`` (for lock files) +* ``"requirement"`` (i.e. all other situations) +""" + +MARKERS_ALLOWING_SET = {"extras", "dependency_groups"} +MARKERS_REQUIRING_VERSION = { + "implementation_version", + "platform_release", + "python_full_version", + "python_version", +} + + +class InvalidMarker(ValueError): + """Raised when attempting to create a :class:`Marker` from invalid input. + + This error indicates that the given marker string does not conform to the + :ref:`specification of dependency specifiers `. + """ + + +class UndefinedComparison(ValueError): + """Raised when evaluating an unsupported marker comparison. + + This can happen when marker values are compared as versions but do not + conform to the :ref:`specification of version specifiers + `. + """ + + +class UndefinedEnvironmentName(ValueError): + """Raised when evaluating a marker that references a missing environment key.""" + + +class Environment(TypedDict): + """ + A dictionary that represents a Python environment as captured by + :func:`default_environment`. All fields are required. + """ + + implementation_name: str + """The implementation's identifier, e.g. ``'cpython'``.""" + + implementation_version: str + """ + The implementation's version, e.g. ``'3.13.0a2'`` for CPython 3.13.0a2, or + ``'7.3.13'`` for PyPy3.10 v7.3.13. + """ + + os_name: str + """ + The value of :py:data:`os.name`. The name of the operating system dependent module + imported, e.g. ``'posix'``. + """ + + platform_machine: str + """ + Returns the machine type, e.g. ``'i386'``. + + An empty string if the value cannot be determined. + """ + + platform_release: str + """ + The system's release, e.g. ``'2.2.0'`` or ``'NT'``. + + An empty string if the value cannot be determined. + """ + + platform_system: str + """ + The system/OS name, e.g. ``'Linux'``, ``'Windows'`` or ``'Java'``. + + An empty string if the value cannot be determined. + """ + + platform_version: str + """ + The system's release version, e.g. ``'#3 on degas'``. + + An empty string if the value cannot be determined. + """ + + python_full_version: str + """ + The Python version as string ``'major.minor.patchlevel'``. + + Note that unlike the Python :py:data:`sys.version`, this value will always include + the patchlevel (it defaults to 0). + """ + + platform_python_implementation: str + """ + A string identifying the Python implementation, e.g. ``'CPython'``. + """ + + python_version: str + """The Python version as string ``'major.minor'``.""" + + sys_platform: str + """ + This string contains a platform identifier that can be used to append + platform-specific components to :py:data:`sys.path`, for instance. + + For Unix systems, except on Linux and AIX, this is the lowercased OS name as + returned by ``uname -s`` with the first part of the version as returned by + ``uname -r`` appended, e.g. ``'sunos5'`` or ``'freebsd8'``, at the time when Python + was built. + """ + + +def _normalize_extras( + result: MarkerList | MarkerAtom | str, +) -> MarkerList | MarkerAtom | str: + if not isinstance(result, tuple): + return result + + lhs, op, rhs = result + if isinstance(lhs, Variable) and lhs.value == "extra": + normalized_extra = canonicalize_name(rhs.value) + rhs = Value(normalized_extra) + elif isinstance(rhs, Variable) and rhs.value == "extra": + normalized_extra = canonicalize_name(lhs.value) + lhs = Value(normalized_extra) + return lhs, op, rhs + + +def _normalize_extra_values(results: MarkerList) -> MarkerList: + """ + Normalize extra values. + """ + + return [_normalize_extras(r) for r in results] + + +def _format_marker( + marker: list[str] | MarkerAtom | str, first: bool | None = True +) -> str: + assert isinstance(marker, (list, tuple, str)) + + # Sometimes we have a structure like [[...]] which is a single item list + # where the single item is itself it's own list. In that case we want skip + # the rest of this function so that we don't get extraneous () on the + # outside. + if ( + isinstance(marker, list) + and len(marker) == 1 + and isinstance(marker[0], (list, tuple)) + ): + return _format_marker(marker[0]) + + if isinstance(marker, list): + inner = (_format_marker(m, first=False) for m in marker) + if first: + return " ".join(inner) + else: + return "(" + " ".join(inner) + ")" + elif isinstance(marker, tuple): + return " ".join([m.serialize() for m in marker]) + else: + return marker + + +_operators: dict[str, Operator] = { + "in": lambda lhs, rhs: lhs in rhs, + "not in": lambda lhs, rhs: lhs not in rhs, + "<": lambda _lhs, _rhs: False, + "<=": operator.eq, + "==": operator.eq, + "!=": operator.ne, + ">=": operator.eq, + ">": lambda _lhs, _rhs: False, +} + + +def _eval_op(lhs: str, op: Op, rhs: str | AbstractSet[str], *, key: str) -> bool: + op_str = op.serialize() + if key in MARKERS_REQUIRING_VERSION: + try: + spec = Specifier(f"{op_str}{rhs}") + except InvalidSpecifier: + pass + else: + return spec.contains(lhs, prereleases=True) + + oper: Operator | None = _operators.get(op_str) + if oper is None: + raise UndefinedComparison(f"Undefined {op!r} on {lhs!r} and {rhs!r}.") + + return oper(lhs, rhs) + + +def _normalize( + lhs: str, rhs: str | AbstractSet[str], key: str +) -> tuple[str, str | AbstractSet[str]]: + # PEP 685 - Comparison of extra names for optional distribution dependencies + # https://peps.python.org/pep-0685/ + # > When comparing extra names, tools MUST normalize the names being + # > compared using the semantics outlined in PEP 503 for names + if key == "extra": + assert isinstance(rhs, str), "extra value must be a string" + # Both sides are normalized at this point already + return (lhs, rhs) + if key in MARKERS_ALLOWING_SET: + if isinstance(rhs, str): # pragma: no cover + return (canonicalize_name(lhs), canonicalize_name(rhs)) + else: + return (canonicalize_name(lhs), {canonicalize_name(v) for v in rhs}) + + # other environment markers don't have such standards + return lhs, rhs + + +def _evaluate_markers( + markers: MarkerList, environment: dict[str, str | AbstractSet[str]] +) -> bool: + groups: list[list[bool]] = [[]] + + for marker in markers: + if isinstance(marker, list): + groups[-1].append(_evaluate_markers(marker, environment)) + elif isinstance(marker, tuple): + lhs, op, rhs = marker + + if isinstance(lhs, Variable): + environment_key = lhs.value + lhs_value = environment[environment_key] + rhs_value = rhs.value + else: + lhs_value = lhs.value + environment_key = rhs.value + rhs_value = environment[environment_key] + + assert isinstance(lhs_value, str), "lhs must be a string" + lhs_value, rhs_value = _normalize(lhs_value, rhs_value, key=environment_key) + groups[-1].append(_eval_op(lhs_value, op, rhs_value, key=environment_key)) + elif marker == "or": + groups.append([]) + elif marker == "and": + pass + else: # pragma: nocover + raise TypeError(f"Unexpected marker {marker!r}") + + return any(all(item) for item in groups) + + +def _format_full_version(info: sys._version_info) -> str: + version = f"{info.major}.{info.minor}.{info.micro}" + kind = info.releaselevel + if kind != "final": + version += kind[0] + str(info.serial) + return version + + +def default_environment() -> Environment: + """Return the default marker environment for the current Python process. + + This is the base environment used by :meth:`Marker.evaluate`. + """ + iver = _format_full_version(sys.implementation.version) + implementation_name = sys.implementation.name + return { + "implementation_name": implementation_name, + "implementation_version": iver, + "os_name": os.name, + "platform_machine": platform.machine(), + "platform_release": platform.release(), + "platform_system": platform.system(), + "platform_version": platform.version(), + "python_full_version": platform.python_version(), + "platform_python_implementation": platform.python_implementation(), + "python_version": ".".join(platform.python_version_tuple()[:2]), + "sys_platform": sys.platform, + } + + +class Marker: + """Represents a parsed dependency marker expression. + + Marker expressions are parsed according to the + :ref:`specification of dependency specifiers `. + + :param marker: The string representation of a marker expression. + :raises InvalidMarker: If ``marker`` cannot be parsed. + + Instances are safe to serialize with :mod:`pickle`. They use a stable + format so the same pickle can be loaded in future packaging releases. + + .. versionchanged:: 26.2 + + Added a stable pickle format. Pickles created with packaging 26.2+ can + be unpickled with future releases. Backward compatibility with pickles + from packaging < 26.2 is supported but may be removed in a future + release. + """ + + __slots__ = ("_markers",) + + def __init__(self, marker: str) -> None: + # Note: We create a Marker object without calling this constructor in + # packaging.requirements.Requirement. If any additional logic is + # added here, make sure to mirror/adapt Requirement. + + # If this fails and throws an error, the repr still expects _markers to + # be defined. + self._markers: MarkerList = [] + + try: + self._markers = _normalize_extra_values(_parse_marker(marker)) + # The attribute `_markers` can be described in terms of a recursive type: + # MarkerList = List[Union[Tuple[Node, ...], str, MarkerList]] + # + # For example, the following expression: + # python_version > "3.6" or (python_version == "3.6" and os_name == "unix") + # + # is parsed into: + # [ + # (, ')>, ), + # 'and', + # [ + # (, , ), + # 'or', + # (, , ) + # ] + # ] + except ParserSyntaxError as e: + raise InvalidMarker(str(e)) from e + + @classmethod + def _from_markers(cls, markers: MarkerList) -> Marker: + """Create a Marker instance from a pre-parsed marker tree. + + This avoids re-parsing serialised marker strings when combining markers. + """ + new = cls.__new__(cls) + new._markers = markers + return new + + def __str__(self) -> str: + return _format_marker(self._markers) + + def __repr__(self) -> str: + return f"<{self.__class__.__name__}({str(self)!r})>" + + def __hash__(self) -> int: + return hash(str(self)) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, Marker): + return NotImplemented + + return str(self) == str(other) + + def __getstate__(self) -> str: + # Return the marker expression string for compactness and stability. + # Internal Node objects are excluded; the string is re-parsed on load. + return str(self) + + def __setstate__(self, state: object) -> None: + if isinstance(state, str): + # New format (26.2+): just the marker expression string. + try: + self._markers = _normalize_extra_values(_parse_marker(state)) + except ParserSyntaxError as exc: + raise TypeError(f"Cannot restore Marker from {state!r}") from exc + return + if isinstance(state, dict) and "_markers" in state: + # Old format (packaging <= 26.1, no __slots__): plain __dict__. + markers = state["_markers"] + if isinstance(markers, list): + self._markers = markers + return + if isinstance(state, tuple) and len(state) == 2: + # Old format (packaging <= 26.1, __slots__): (None, {slot: value}). + _, slot_dict = state + if isinstance(slot_dict, dict) and "_markers" in slot_dict: + markers = slot_dict["_markers"] + if isinstance(markers, list): + self._markers = markers + return + raise TypeError(f"Cannot restore Marker from {state!r}") + + def __and__(self, other: Marker) -> Marker: + if not isinstance(other, Marker): + return NotImplemented + return self._from_markers([self._markers, "and", other._markers]) + + def __or__(self, other: Marker) -> Marker: + if not isinstance(other, Marker): + return NotImplemented + return self._from_markers([self._markers, "or", other._markers]) + + def evaluate( + self, + environment: Mapping[str, str | AbstractSet[str]] | None = None, + context: EvaluateContext = "metadata", + ) -> bool: + """Evaluate a marker. + + Return the boolean from evaluating this marker against the environment. + The environment is determined from the current Python process unless + passed in explicitly. + + :param environment: Mapping containing keys and values to override the + detected environment. + :param EvaluateContext context: The context in which the marker is + evaluated, which influences what marker names are considered valid. + Accepted values are ``"metadata"`` (for core metadata; default), + ``"lock_file"``, and ``"requirement"`` (i.e. all other situations). + :raises UndefinedComparison: If the marker uses a comparison on values + that are not valid versions per the :ref:`specification of version + specifiers `. + :raises UndefinedEnvironmentName: If the marker references a value that + is missing from the evaluation environment. + :returns: ``True`` if the marker matches, otherwise ``False``. + + """ + current_environment = cast( + "dict[str, str | AbstractSet[str]]", default_environment() + ) + if context == "lock_file": + current_environment.update( + extras=frozenset(), dependency_groups=frozenset() + ) + elif context == "metadata": + current_environment["extra"] = "" + + if environment is not None: + current_environment.update(environment) + if "extra" in current_environment: + # The API used to allow setting extra to None. We need to handle + # this case for backwards compatibility. Also skip running + # normalize name if extra is empty. + extra = cast("str | None", current_environment["extra"]) + current_environment["extra"] = canonicalize_name(extra) if extra else "" + + return _evaluate_markers( + self._markers, _repair_python_full_version(current_environment) + ) + + +def _repair_python_full_version( + env: dict[str, str | AbstractSet[str]], +) -> dict[str, str | AbstractSet[str]]: + """ + Work around platform.python_version() returning something that is not PEP 440 + compliant for non-tagged Python builds. + """ + python_full_version = cast("str", env["python_full_version"]) + if python_full_version.endswith("+"): + env["python_full_version"] = f"{python_full_version}local" + return env diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/metadata.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/metadata.py new file mode 100644 index 0000000..dccb627 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/metadata.py @@ -0,0 +1,964 @@ +from __future__ import annotations + +import email.header +import email.message +import email.parser +import email.policy +import keyword +import pathlib +import typing +from typing import ( + Any, + Callable, + Generic, + Literal, + TypedDict, + cast, +) + +from . import licenses, requirements, specifiers, utils +from . import version as version_module +from .errors import ExceptionGroup, _ErrorCollector + +if typing.TYPE_CHECKING: + from .licenses import NormalizedLicenseExpression + +T = typing.TypeVar("T") + + +__all__ = [ + "ExceptionGroup", # Keep this for a bit (makes mypy happy w/ 26.0 compat) + "InvalidMetadata", + "Metadata", + "RFC822Message", + "RFC822Policy", + "RawMetadata", + "parse_email", +] + + +def __dir__() -> list[str]: + return __all__ + + +class InvalidMetadata(ValueError): + """A metadata field contains invalid data.""" + + field: str + """The name of the field that contains invalid data.""" + + def __init__(self, field: str, message: str) -> None: + self.field = field + super().__init__(message) + + +# The RawMetadata class attempts to make as few assumptions about the underlying +# serialization formats as possible. The idea is that as long as a serialization +# formats offer some very basic primitives in *some* way then we can support +# serializing to and from that format. +class RawMetadata(TypedDict, total=False): + """A dictionary of raw core metadata. + + Each field in core metadata maps to a key of this dictionary (when data is + provided). The key is lower-case and underscores are used instead of dashes + compared to the equivalent core metadata field. Any core metadata field that + can be specified multiple times or can hold multiple values in a single + field have a key with a plural name. See :class:`Metadata` whose attributes + match the keys of this dictionary. + + Core metadata fields that can be specified multiple times are stored as a + list or dict depending on which is appropriate for the field. Any fields + which hold multiple values in a single field are stored as a list. All fields + are considered optional. + """ + + # Metadata 1.0 - PEP 241 + metadata_version: str + name: str + version: str + platforms: list[str] + summary: str + description: str + keywords: list[str] + home_page: str + author: str + author_email: str + license: str + + # Metadata 1.1 - PEP 314 + supported_platforms: list[str] + download_url: str + classifiers: list[str] + requires: list[str] + provides: list[str] + obsoletes: list[str] + + # Metadata 1.2 - PEP 345 + maintainer: str + maintainer_email: str + requires_dist: list[str] + provides_dist: list[str] + obsoletes_dist: list[str] + requires_python: str + requires_external: list[str] + project_urls: dict[str, str] + + # Metadata 2.0 + # PEP 426 attempted to completely revamp the metadata format + # but got stuck without ever being able to build consensus on + # it and ultimately ended up withdrawn. + # + # However, a number of tools had started emitting METADATA with + # `2.0` Metadata-Version, so for historical reasons, this version + # was skipped. + + # Metadata 2.1 - PEP 566 + description_content_type: str + provides_extra: list[str] + + # Metadata 2.2 - PEP 643 + dynamic: list[str] + + # Metadata 2.3 - PEP 685 + # No new fields were added in PEP 685, just some edge case were + # tightened up to provide better interoperability. + + # Metadata 2.4 - PEP 639 + license_expression: str + license_files: list[str] + + # Metadata 2.5 - PEP 794 + import_names: list[str] + import_namespaces: list[str] + + +# 'keywords' is special as it's a string in the core metadata spec, but we +# represent it as a list. +_STRING_FIELDS = { + "author", + "author_email", + "description", + "description_content_type", + "download_url", + "home_page", + "license", + "license_expression", + "maintainer", + "maintainer_email", + "metadata_version", + "name", + "requires_python", + "summary", + "version", +} + +_LIST_FIELDS = { + "classifiers", + "dynamic", + "license_files", + "obsoletes", + "obsoletes_dist", + "platforms", + "provides", + "provides_dist", + "provides_extra", + "requires", + "requires_dist", + "requires_external", + "supported_platforms", + "import_names", + "import_namespaces", +} + +_DICT_FIELDS = { + "project_urls", +} + + +def _parse_keywords(data: str) -> list[str]: + """Split a string of comma-separated keywords into a list of keywords.""" + return [k.strip() for k in data.split(",")] + + +def _parse_project_urls(data: list[str]) -> dict[str, str]: + """Parse a list of label/URL string pairings separated by a comma.""" + urls = {} + for pair in data: + # Our logic is slightly tricky here as we want to try and do + # *something* reasonable with malformed data. + # + # The main thing that we have to worry about, is data that does + # not have a ',' at all to split the label from the Value. There + # isn't a singular right answer here, and we will fail validation + # later on (if the caller is validating) so it doesn't *really* + # matter, but since the missing value has to be an empty str + # and our return value is dict[str, str], if we let the key + # be the missing value, then they'd have multiple '' values that + # overwrite each other in a accumulating dict. + # + # The other potential issue is that it's possible to have the + # same label multiple times in the metadata, with no solid "right" + # answer with what to do in that case. As such, we'll do the only + # thing we can, which is treat the field as unparsable and add it + # to our list of unparsed fields. + # + # TODO: The spec doesn't say anything about if the keys should be + # considered case sensitive or not... logically they should + # be case-preserving and case-insensitive, but doing that + # would open up more cases where we might have duplicate + # entries. + label, _, url = (s.strip() for s in pair.partition(",")) + + if label in urls: + # The label already exists in our set of urls, so this field + # is unparsable, and we can just add the whole thing to our + # unparsable data and stop processing it. + raise KeyError("duplicate labels in project urls") + urls[label] = url + + return urls + + +def _get_payload(msg: email.message.Message, source: bytes | str) -> str: + """Get the body of the message.""" + # If our source is a str, then our caller has managed encodings for us, + # and we don't need to deal with it. + if isinstance(source, str): + payload = msg.get_payload() + assert isinstance(payload, str) + return payload + # If our source is a bytes, then we're managing the encoding and we need + # to deal with it. + else: + bpayload = msg.get_payload(decode=True) + assert isinstance(bpayload, bytes) + try: + return bpayload.decode("utf8", "strict") + except UnicodeDecodeError as exc: + raise ValueError("payload in an invalid encoding") from exc + + +# The various parse_FORMAT functions here are intended to be as lenient as +# possible in their parsing, while still returning a correctly typed +# RawMetadata. +# +# To aid in this, we also generally want to do as little touching of the +# data as possible, except where there are possibly some historic holdovers +# that make valid data awkward to work with. +# +# While this is a lower level, intermediate format than our ``Metadata`` +# class, some light touch ups can make a massive difference in usability. + +# Map METADATA fields to RawMetadata. +_EMAIL_TO_RAW_MAPPING = { + "author": "author", + "author-email": "author_email", + "classifier": "classifiers", + "description": "description", + "description-content-type": "description_content_type", + "download-url": "download_url", + "dynamic": "dynamic", + "home-page": "home_page", + "import-name": "import_names", + "import-namespace": "import_namespaces", + "keywords": "keywords", + "license": "license", + "license-expression": "license_expression", + "license-file": "license_files", + "maintainer": "maintainer", + "maintainer-email": "maintainer_email", + "metadata-version": "metadata_version", + "name": "name", + "obsoletes": "obsoletes", + "obsoletes-dist": "obsoletes_dist", + "platform": "platforms", + "project-url": "project_urls", + "provides": "provides", + "provides-dist": "provides_dist", + "provides-extra": "provides_extra", + "requires": "requires", + "requires-dist": "requires_dist", + "requires-external": "requires_external", + "requires-python": "requires_python", + "summary": "summary", + "supported-platform": "supported_platforms", + "version": "version", +} +_RAW_TO_EMAIL_MAPPING = {raw: email for email, raw in _EMAIL_TO_RAW_MAPPING.items()} + + +# This class is for writing RFC822 messages +class RFC822Policy(email.policy.EmailPolicy): + """ + This is :class:`email.policy.EmailPolicy`, but with a simple ``header_store_parse`` + implementation that handles multi-line values, and some nice defaults. + """ + + utf8 = True + mangle_from_ = False + max_line_length = 0 + + def header_store_parse(self, name: str, value: str) -> tuple[str, str]: + size = len(name) + 2 + value = value.replace("\n", "\n" + " " * size) + return (name, value) + + +# This class is for writing RFC822 messages +class RFC822Message(email.message.EmailMessage): + """ + This is :class:`email.message.EmailMessage` with two small changes: it defaults to + our `RFC822Policy`, and it correctly writes unicode when being called + with `bytes()`. + """ + + def __init__(self) -> None: + super().__init__(policy=RFC822Policy()) + + def as_bytes( + self, unixfrom: bool = False, policy: email.policy.Policy | None = None + ) -> bytes: + """ + Return the bytes representation of the message. + + This handles unicode encoding. + """ + return self.as_string(unixfrom, policy=policy).encode("utf-8") + + +def parse_email(data: bytes | str) -> tuple[RawMetadata, dict[str, list[str]]]: + """Parse a distribution's metadata stored as email headers (e.g. from ``METADATA``). + + This function returns a two-item tuple of dicts. The first dict is of + recognized fields from the core metadata specification. Fields that can be + parsed and translated into Python's built-in types are converted + appropriately. All other fields are left as-is. Fields that are allowed to + appear multiple times are stored as lists. + + The second dict contains all other fields from the metadata. This includes + any unrecognized fields. It also includes any fields which are expected to + be parsed into a built-in type but were not formatted appropriately. Finally, + any fields that are expected to appear only once but are repeated are + included in this dict. + + """ + raw: dict[str, str | list[str] | dict[str, str]] = {} + unparsed: dict[str, list[str]] = {} + + if isinstance(data, str): + parsed = email.parser.Parser(policy=email.policy.compat32).parsestr(data) + else: + parsed = email.parser.BytesParser(policy=email.policy.compat32).parsebytes(data) + + # We have to wrap parsed.keys() in a set, because in the case of multiple + # values for a key (a list), the key will appear multiple times in the + # list of keys, but we're avoiding that by using get_all(). + for name_with_case in frozenset(parsed.keys()): + # Header names in RFC are case insensitive, so we'll normalize to all + # lower case to make comparisons easier. + name = name_with_case.lower() + + # We use get_all() here, even for fields that aren't multiple use, + # because otherwise someone could have e.g. two Name fields, and we + # would just silently ignore it rather than doing something about it. + headers = parsed.get_all(name) or [] + + # The way the email module works when parsing bytes is that it + # unconditionally decodes the bytes as ascii using the surrogateescape + # handler. When you pull that data back out (such as with get_all() ), + # it looks to see if the str has any surrogate escapes, and if it does + # it wraps it in a Header object instead of returning the string. + # + # As such, we'll look for those Header objects, and fix up the encoding. + value = [] + # Flag if we have run into any issues processing the headers, thus + # signalling that the data belongs in 'unparsed'. + valid_encoding = True + for h in headers: + # It's unclear if this can return more types than just a Header or + # a str, so we'll just assert here to make sure. + assert isinstance(h, (email.header.Header, str)) + + # If it's a header object, we need to do our little dance to get + # the real data out of it. In cases where there is invalid data + # we're going to end up with mojibake, but there's no obvious, good + # way around that without reimplementing parts of the Header object + # ourselves. + # + # That should be fine since, if mojibacked happens, this key is + # going into the unparsed dict anyways. + if isinstance(h, email.header.Header): + # The Header object stores it's data as chunks, and each chunk + # can be independently encoded, so we'll need to check each + # of them. + chunks: list[tuple[bytes, str | None]] = [] + for binary, _encoding in email.header.decode_header(h): + try: + binary.decode("utf8", "strict") + except UnicodeDecodeError: + # Enable mojibake. + encoding = "latin1" + valid_encoding = False + else: + encoding = "utf8" + chunks.append((binary, encoding)) + + # Turn our chunks back into a Header object, then let that + # Header object do the right thing to turn them into a + # string for us. + value.append(str(email.header.make_header(chunks))) + # This is already a string, so just add it. + else: + value.append(h) + + # We've processed all of our values to get them into a list of str, + # but we may have mojibake data, in which case this is an unparsed + # field. + if not valid_encoding: + unparsed[name] = value + continue + + raw_name = _EMAIL_TO_RAW_MAPPING.get(name) + if raw_name is None: + # This is a bit of a weird situation, we've encountered a key that + # we don't know what it means, so we don't know whether it's meant + # to be a list or not. + # + # Since we can't really tell one way or another, we'll just leave it + # as a list, even though it may be a single item list, because that's + # what makes the most sense for email headers. + unparsed[name] = value + continue + + # If this is one of our string fields, then we'll check to see if our + # value is a list of a single item. If it is then we'll assume that + # it was emitted as a single string, and unwrap the str from inside + # the list. + # + # If it's any other kind of data, then we haven't the faintest clue + # what we should parse it as, and we have to just add it to our list + # of unparsed stuff. + if raw_name in _STRING_FIELDS and len(value) == 1: + raw[raw_name] = value[0] + # If this is import_names, we need to special case the empty field + # case, which converts to an empty list instead of None. We can't let + # the empty case slip through, as it will fail validation. + elif raw_name == "import_names" and value == [""]: + raw[raw_name] = [] + # If this is one of our list of string fields, then we can just assign + # the value, since email *only* has strings, and our get_all() call + # above ensures that this is a list. + elif raw_name in _LIST_FIELDS: + raw[raw_name] = value + # Special Case: Keywords + # The keywords field is implemented in the metadata spec as a str, + # but it conceptually is a list of strings, and is serialized using + # ", ".join(keywords), so we'll do some light data massaging to turn + # this into what it logically is. + elif raw_name == "keywords" and len(value) == 1: + raw[raw_name] = _parse_keywords(value[0]) + # Special Case: Project-URL + # The project urls is implemented in the metadata spec as a list of + # specially-formatted strings that represent a key and a value, which + # is fundamentally a mapping, however the email format doesn't support + # mappings in a sane way, so it was crammed into a list of strings + # instead. + # + # We will do a little light data massaging to turn this into a map as + # it logically should be. + elif raw_name == "project_urls": + try: + raw[raw_name] = _parse_project_urls(value) + except KeyError: + unparsed[name] = value + # Nothing that we've done has managed to parse this, so it'll just + # throw it in our unparsable data and move on. + else: + unparsed[name] = value + + # We need to support getting the Description from the message payload in + # addition to getting it from the the headers. This does mean, though, there + # is the possibility of it being set both ways, in which case we put both + # in 'unparsed' since we don't know which is right. + try: + payload = _get_payload(parsed, data) + except ValueError: + unparsed.setdefault("description", []).append( + parsed.get_payload(decode=isinstance(data, bytes)) # type: ignore[call-overload] + ) + else: + if payload: + # Check to see if we've already got a description, if so then both + # it, and this body move to unparsable. + if "description" in raw: + description_header = cast("str", raw.pop("description")) + unparsed.setdefault("description", []).extend( + [description_header, payload] + ) + elif "description" in unparsed: + unparsed["description"].append(payload) + else: + raw["description"] = payload + + # We need to cast our `raw` to a metadata, because a TypedDict only support + # literal key names, but we're computing our key names on purpose, but the + # way this function is implemented, our `TypedDict` can only have valid key + # names. + return cast("RawMetadata", raw), unparsed + + +_NOT_FOUND = object() + + +# Keep the two values in sync. +_VALID_METADATA_VERSIONS = ["1.0", "1.1", "1.2", "2.1", "2.2", "2.3", "2.4", "2.5"] +_MetadataVersion = Literal["1.0", "1.1", "1.2", "2.1", "2.2", "2.3", "2.4", "2.5"] + +_REQUIRED_ATTRS = frozenset(["metadata_version", "name", "version"]) + + +class _Validator(Generic[T]): + """Validate a metadata field. + + All _process_*() methods correspond to a core metadata field. The method is + called with the field's raw value. If the raw value is valid it is returned + in its "enriched" form (e.g. ``version.Version`` for the ``Version`` field). + If the raw value is invalid, :exc:`InvalidMetadata` is raised (with a cause + as appropriate). + """ + + name: str + raw_name: str + added: _MetadataVersion + + def __init__( + self, + *, + added: _MetadataVersion = "1.0", + ) -> None: + self.added = added + + def __set_name__(self, _owner: Metadata, name: str) -> None: + self.name = name + self.raw_name = _RAW_TO_EMAIL_MAPPING[name] + + def __get__(self, instance: Metadata, _owner: type[Metadata]) -> T: + # With Python 3.8, the caching can be replaced with functools.cached_property(). + # No need to check the cache as attribute lookup will resolve into the + # instance's __dict__ before __get__ is called. + cache = instance.__dict__ + value = instance._raw.get(self.name) + + # To make the _process_* methods easier, we'll check if the value is None + # and if this field is NOT a required attribute, and if both of those + # things are true, we'll skip the the converter. This will mean that the + # converters never have to deal with the None union. + if self.name in _REQUIRED_ATTRS or value is not None: + try: + converter: Callable[[Any], T] = getattr(self, f"_process_{self.name}") + except AttributeError: + pass + else: + value = converter(value) + + cache[self.name] = value + try: + del instance._raw[self.name] # type: ignore[misc] + except KeyError: + pass + + return cast("T", value) + + def _invalid_metadata( + self, msg: str, cause: Exception | None = None + ) -> InvalidMetadata: + exc = InvalidMetadata( + self.raw_name, msg.format_map({"field": repr(self.raw_name)}) + ) + exc.__cause__ = cause + return exc + + def _process_metadata_version(self, value: str) -> _MetadataVersion: + # Implicitly makes Metadata-Version required. + if value not in _VALID_METADATA_VERSIONS: + raise self._invalid_metadata(f"{value!r} is not a valid metadata version") + return cast("_MetadataVersion", value) + + def _process_name(self, value: str) -> str: + if not value: + raise self._invalid_metadata("{field} is a required field") + # Validate the name as a side-effect. + try: + utils.canonicalize_name(value, validate=True) + except utils.InvalidName as exc: + raise self._invalid_metadata( + f"{value!r} is invalid for {{field}}", cause=exc + ) from exc + else: + return value + + def _process_version(self, value: str) -> version_module.Version: + if not value: + raise self._invalid_metadata("{field} is a required field") + try: + return version_module.parse(value) + except version_module.InvalidVersion as exc: + raise self._invalid_metadata( + f"{value!r} is invalid for {{field}}", cause=exc + ) from exc + + def _process_summary(self, value: str) -> str: + """Check the field contains no newlines.""" + if "\n" in value: + raise self._invalid_metadata("{field} must be a single line") + return value + + def _process_description_content_type(self, value: str) -> str: + content_types = {"text/plain", "text/x-rst", "text/markdown"} + message = email.message.EmailMessage() + message["content-type"] = value + + content_type, parameters = ( + # Defaults to `text/plain` if parsing failed. + message.get_content_type().lower(), + message["content-type"].params, + ) + # Check if content-type is valid or defaulted to `text/plain` and thus was + # not parseable. + if content_type not in content_types or content_type not in value.lower(): + raise self._invalid_metadata( + f"{{field}} must be one of {list(content_types)}, not {value!r}" + ) + + charset = parameters.get("charset", "UTF-8") + if charset != "UTF-8": + raise self._invalid_metadata( + f"{{field}} can only specify the UTF-8 charset, not {charset!r}" + ) + + markdown_variants = {"GFM", "CommonMark"} + variant = parameters.get("variant", "GFM") # Use an acceptable default. + if content_type == "text/markdown" and variant not in markdown_variants: + raise self._invalid_metadata( + f"valid Markdown variants for {{field}} are {list(markdown_variants)}, " + f"not {variant!r}", + ) + return value + + def _process_dynamic(self, value: list[str]) -> list[str]: + for dynamic_field in map(str.lower, value): + if dynamic_field in {"name", "version", "metadata-version"}: + raise self._invalid_metadata( + f"{dynamic_field!r} is not allowed as a dynamic field" + ) + elif dynamic_field not in _EMAIL_TO_RAW_MAPPING: + raise self._invalid_metadata( + f"{dynamic_field!r} is not a valid dynamic field" + ) + return list(map(str.lower, value)) + + def _process_provides_extra( + self, + value: list[str], + ) -> list[utils.NormalizedName]: + normalized_names = [] + try: + for name in value: + normalized_names.append(utils.canonicalize_name(name, validate=True)) + except utils.InvalidName as exc: + raise self._invalid_metadata( + f"{name!r} is invalid for {{field}}", cause=exc + ) from exc + else: + return normalized_names + + def _process_requires_python(self, value: str) -> specifiers.SpecifierSet: + try: + return specifiers.SpecifierSet(value) + except specifiers.InvalidSpecifier as exc: + raise self._invalid_metadata( + f"{value!r} is invalid for {{field}}", cause=exc + ) from exc + + def _process_requires_dist( + self, + value: list[str], + ) -> list[requirements.Requirement]: + reqs = [] + try: + for req in value: + reqs.append(requirements.Requirement(req)) + except requirements.InvalidRequirement as exc: + raise self._invalid_metadata( + f"{req!r} is invalid for {{field}}", cause=exc + ) from exc + else: + return reqs + + def _process_license_expression(self, value: str) -> NormalizedLicenseExpression: + try: + return licenses.canonicalize_license_expression(value) + except ValueError as exc: + raise self._invalid_metadata( + f"{value!r} is invalid for {{field}}", cause=exc + ) from exc + + def _process_license_files(self, value: list[str]) -> list[str]: + paths = [] + for path in value: + if ".." in path: + raise self._invalid_metadata( + f"{path!r} is invalid for {{field}}, " + "parent directory indicators are not allowed" + ) + if "*" in path: + raise self._invalid_metadata( + f"{path!r} is invalid for {{field}}, paths must be resolved" + ) + if ( + pathlib.PurePosixPath(path).is_absolute() + or pathlib.PureWindowsPath(path).is_absolute() + ): + raise self._invalid_metadata( + f"{path!r} is invalid for {{field}}, paths must be relative" + ) + if pathlib.PureWindowsPath(path).as_posix() != path: + raise self._invalid_metadata( + f"{path!r} is invalid for {{field}}, paths must use '/' delimiter" + ) + paths.append(path) + return paths + + def _process_import_names(self, value: list[str]) -> list[str]: + for import_name in value: + name, semicolon, private = import_name.partition(";") + name = name.rstrip() + for identifier in name.split("."): + if not identifier.isidentifier(): + raise self._invalid_metadata( + f"{name!r} is invalid for {{field}}; " + f"{identifier!r} is not a valid identifier" + ) + elif keyword.iskeyword(identifier): + raise self._invalid_metadata( + f"{name!r} is invalid for {{field}}; " + f"{identifier!r} is a keyword" + ) + if semicolon and private.lstrip() != "private": + raise self._invalid_metadata( + f"{import_name!r} is invalid for {{field}}; " + "the only valid option is 'private'" + ) + return value + + _process_import_namespaces = _process_import_names + + +class Metadata: + """Representation of distribution metadata. + + Compared to :class:`RawMetadata`, this class provides objects representing + metadata fields instead of only using built-in types. Any invalid metadata + will cause :exc:`InvalidMetadata` to be raised (with a + :py:attr:`~BaseException.__cause__` attribute as appropriate). + """ + + _raw: RawMetadata + + @classmethod + def from_raw(cls, data: RawMetadata, *, validate: bool = True) -> Metadata: + """Create an instance from :class:`RawMetadata`. + + If *validate* is true, all metadata will be validated. All exceptions + related to validation will be gathered and raised as an :class:`ExceptionGroup`. + """ + ins = cls() + ins._raw = data.copy() # Mutations occur due to caching enriched values. + + if validate: + collector = _ErrorCollector() + metadata_version = None + with collector.collect(InvalidMetadata): + metadata_version = ins.metadata_version + metadata_age = _VALID_METADATA_VERSIONS.index(metadata_version) + + # Make sure to check for the fields that are present, the required + # fields (so their absence can be reported). + fields_to_check = frozenset(ins._raw) | _REQUIRED_ATTRS + # Remove fields that have already been checked. + fields_to_check -= {"metadata_version"} + + for key in fields_to_check: + try: + if metadata_version: + # Can't use getattr() as that triggers descriptor protocol which + # will fail due to no value for the instance argument. + try: + field_metadata_version = cls.__dict__[key].added + except KeyError: + exc = InvalidMetadata(key, f"unrecognized field: {key!r}") + collector.error(exc) + continue + field_age = _VALID_METADATA_VERSIONS.index( + field_metadata_version + ) + if field_age > metadata_age: + field = _RAW_TO_EMAIL_MAPPING[key] + exc = InvalidMetadata( + field, + f"{field} introduced in metadata version " + f"{field_metadata_version}, not {metadata_version}", + ) + collector.error(exc) + continue + getattr(ins, key) + except InvalidMetadata as exc: + collector.error(exc) + + collector.finalize("invalid metadata") + + return ins + + @classmethod + def from_email(cls, data: bytes | str, *, validate: bool = True) -> Metadata: + """Parse metadata from email headers. + + If *validate* is true, the metadata will be validated. All exceptions + related to validation will be gathered and raised as an :class:`ExceptionGroup`. + """ + raw, unparsed = parse_email(data) + + if validate: + with _ErrorCollector().on_exit("unparsed") as collector: + for unparsed_key in unparsed: + if unparsed_key in _EMAIL_TO_RAW_MAPPING: + message = f"{unparsed_key!r} has invalid data" + else: + message = f"unrecognized field: {unparsed_key!r}" + collector.error(InvalidMetadata(unparsed_key, message)) + + try: + return cls.from_raw(raw, validate=validate) + except ExceptionGroup as exc_group: + raise ExceptionGroup( + "invalid or unparsed metadata", exc_group.exceptions + ) from None + + metadata_version: _Validator[_MetadataVersion] = _Validator() + """:external:ref:`core-metadata-metadata-version` + (required; validated to be a valid metadata version)""" + # `name` is not normalized/typed to NormalizedName so as to provide access to + # the original/raw name. + name: _Validator[str] = _Validator() + """:external:ref:`core-metadata-name` + (required; validated using :func:`~packaging.utils.canonicalize_name` and its + *validate* parameter)""" + version: _Validator[version_module.Version] = _Validator() + """:external:ref:`core-metadata-version` (required)""" + dynamic: _Validator[list[str] | None] = _Validator( + added="2.2", + ) + """:external:ref:`core-metadata-dynamic` + (validated against core metadata field names and lowercased)""" + platforms: _Validator[list[str] | None] = _Validator() + """:external:ref:`core-metadata-platform`""" + supported_platforms: _Validator[list[str] | None] = _Validator(added="1.1") + """:external:ref:`core-metadata-supported-platform`""" + summary: _Validator[str | None] = _Validator() + """:external:ref:`core-metadata-summary` (validated to contain no newlines)""" + description: _Validator[str | None] = _Validator() # TODO 2.1: can be in body + """:external:ref:`core-metadata-description`""" + description_content_type: _Validator[str | None] = _Validator(added="2.1") + """:external:ref:`core-metadata-description-content-type` (validated)""" + keywords: _Validator[list[str] | None] = _Validator() + """:external:ref:`core-metadata-keywords`""" + home_page: _Validator[str | None] = _Validator() + """:external:ref:`core-metadata-home-page`""" + download_url: _Validator[str | None] = _Validator(added="1.1") + """:external:ref:`core-metadata-download-url`""" + author: _Validator[str | None] = _Validator() + """:external:ref:`core-metadata-author`""" + author_email: _Validator[str | None] = _Validator() + """:external:ref:`core-metadata-author-email`""" + maintainer: _Validator[str | None] = _Validator(added="1.2") + """:external:ref:`core-metadata-maintainer`""" + maintainer_email: _Validator[str | None] = _Validator(added="1.2") + """:external:ref:`core-metadata-maintainer-email`""" + license: _Validator[str | None] = _Validator() + """:external:ref:`core-metadata-license`""" + license_expression: _Validator[NormalizedLicenseExpression | None] = _Validator( + added="2.4" + ) + """:external:ref:`core-metadata-license-expression`""" + license_files: _Validator[list[str] | None] = _Validator(added="2.4") + """:external:ref:`core-metadata-license-file`""" + classifiers: _Validator[list[str] | None] = _Validator(added="1.1") + """:external:ref:`core-metadata-classifier`""" + requires_dist: _Validator[list[requirements.Requirement] | None] = _Validator( + added="1.2" + ) + """:external:ref:`core-metadata-requires-dist`""" + requires_python: _Validator[specifiers.SpecifierSet | None] = _Validator( + added="1.2" + ) + """:external:ref:`core-metadata-requires-python`""" + # Because `Requires-External` allows for non-PEP 440 version specifiers, we + # don't do any processing on the values. + requires_external: _Validator[list[str] | None] = _Validator(added="1.2") + """:external:ref:`core-metadata-requires-external`""" + project_urls: _Validator[dict[str, str] | None] = _Validator(added="1.2") + """:external:ref:`core-metadata-project-url`""" + # PEP 685 lets us raise an error if an extra doesn't pass `Name` validation + # regardless of metadata version. + provides_extra: _Validator[list[utils.NormalizedName] | None] = _Validator( + added="2.1", + ) + """:external:ref:`core-metadata-provides-extra`""" + provides_dist: _Validator[list[str] | None] = _Validator(added="1.2") + """:external:ref:`core-metadata-provides-dist`""" + obsoletes_dist: _Validator[list[str] | None] = _Validator(added="1.2") + """:external:ref:`core-metadata-obsoletes-dist`""" + import_names: _Validator[list[str] | None] = _Validator(added="2.5") + """:external:ref:`core-metadata-import-name`""" + import_namespaces: _Validator[list[str] | None] = _Validator(added="2.5") + """:external:ref:`core-metadata-import-namespace`""" + requires: _Validator[list[str] | None] = _Validator(added="1.1") + """``Requires`` (deprecated)""" + provides: _Validator[list[str] | None] = _Validator(added="1.1") + """``Provides`` (deprecated)""" + obsoletes: _Validator[list[str] | None] = _Validator(added="1.1") + """``Obsoletes`` (deprecated)""" + + def as_rfc822(self) -> RFC822Message: + """ + Return an RFC822 message with the metadata. + """ + message = RFC822Message() + self._write_metadata(message) + return message + + def _write_metadata(self, message: RFC822Message) -> None: + """ + Return an RFC822 message with the metadata. + """ + for name, validator in self.__class__.__dict__.items(): + if isinstance(validator, _Validator) and name != "description": + value = getattr(self, name) + email_name = _RAW_TO_EMAIL_MAPPING[name] + if value is not None: + if email_name == "project-url": + for label, url in value.items(): + message[email_name] = f"{label}, {url}" + elif email_name == "keywords": + message[email_name] = ",".join(value) + elif email_name == "import-name" and value == []: + message[email_name] = "" + elif isinstance(value, list): + for item in value: + message[email_name] = str(item) + else: + message[email_name] = str(value) + + # The description is a special case because it is in the body of the message. + if self.description is not None: + message.set_payload(self.description) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/py.typed b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/pylock.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/pylock.py new file mode 100644 index 0000000..84e2537 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/pylock.py @@ -0,0 +1,905 @@ +from __future__ import annotations + +import dataclasses +import logging +import re +from collections.abc import Mapping, Sequence +from dataclasses import dataclass +from datetime import datetime +from typing import ( + TYPE_CHECKING, + Any, + Callable, + Protocol, + TypeVar, + cast, +) +from urllib.parse import urlparse + +from .markers import Environment, Marker, default_environment +from .specifiers import SpecifierSet +from .tags import create_compatible_tags_selector, sys_tags +from .utils import ( + NormalizedName, + is_normalized_name, + parse_sdist_filename, + parse_wheel_filename, +) +from .version import Version + +if TYPE_CHECKING: # pragma: no cover + from collections.abc import Collection, Iterator + from pathlib import Path + + from typing_extensions import Self + + from .tags import Tag + +_logger = logging.getLogger(__name__) + +__all__ = [ + "Package", + "PackageArchive", + "PackageDirectory", + "PackageSdist", + "PackageVcs", + "PackageWheel", + "Pylock", + "PylockUnsupportedVersionError", + "PylockValidationError", + "is_valid_pylock_path", +] + + +def __dir__() -> list[str]: + return __all__ + + +_T = TypeVar("_T") +_T2 = TypeVar("_T2") + + +class _FromMappingProtocol(Protocol): # pragma: no cover + @classmethod + def _from_dict(cls, d: Mapping[str, Any]) -> Self: ... + + +_FromMappingProtocolT = TypeVar("_FromMappingProtocolT", bound=_FromMappingProtocol) + + +_PYLOCK_FILE_NAME_RE = re.compile(r"^pylock\.([^.]+)\.toml$") + + +def is_valid_pylock_path(path: Path) -> bool: + """Check if the given path is a valid pylock file path.""" + return path.name == "pylock.toml" or bool(_PYLOCK_FILE_NAME_RE.match(path.name)) + + +def _toml_key(key: str) -> str: + return key.replace("_", "-") + + +def _toml_value(key: str, value: Any) -> Any: # noqa: ANN401 + if isinstance(value, (Version, Marker, SpecifierSet)): + return str(value) + if isinstance(value, Sequence) and key == "environments": + return [str(v) for v in value] + return value + + +def _toml_dict_factory(data: list[tuple[str, Any]]) -> dict[str, Any]: + return { + _toml_key(key): _toml_value(key, value) + for key, value in data + if value is not None + } + + +def _get(d: Mapping[str, Any], expected_type: type[_T], key: str) -> _T | None: + """Get a value from the dictionary and verify it's the expected type.""" + if (value := d.get(key)) is None: + return None + if not isinstance(value, expected_type): + raise PylockValidationError( + f"Unexpected type {type(value).__name__} " + f"(expected {expected_type.__name__})", + context=key, + ) + return value + + +def _get_required(d: Mapping[str, Any], expected_type: type[_T], key: str) -> _T: + """Get a required value from the dictionary and verify it's the expected type.""" + if (value := _get(d, expected_type, key)) is None: + raise _PylockRequiredKeyError(key) + return value + + +def _get_sequence( + d: Mapping[str, Any], expected_item_type: type[_T], key: str +) -> Sequence[_T] | None: + """Get a list value from the dictionary and verify it's the expected items type.""" + if (value := _get(d, Sequence, key)) is None: # type: ignore[type-abstract] + return None + if isinstance(value, (str, bytes)): + # special case: str and bytes are Sequences, but we want to reject it + raise PylockValidationError( + f"Unexpected type {type(value).__name__} (expected Sequence)", + context=key, + ) + for i, item in enumerate(value): + if not isinstance(item, expected_item_type): + raise PylockValidationError( + f"Unexpected type {type(item).__name__} " + f"(expected {expected_item_type.__name__})", + context=f"{key}[{i}]", + ) + return value + + +def _get_as( + d: Mapping[str, Any], + expected_type: type[_T], + target_type: Callable[[_T], _T2], + key: str, +) -> _T2 | None: + """Get a value from the dictionary, verify it's the expected type, + and convert to the target type. + + This assumes the target_type constructor accepts the value. + """ + if (value := _get(d, expected_type, key)) is None: + return None + try: + return target_type(value) + except Exception as e: + raise PylockValidationError(e, context=key) from e + + +def _get_required_as( + d: Mapping[str, Any], + expected_type: type[_T], + target_type: Callable[[_T], _T2], + key: str, +) -> _T2: + """Get a required value from the dict, verify it's the expected type, + and convert to the target type.""" + if (value := _get_as(d, expected_type, target_type, key)) is None: + raise _PylockRequiredKeyError(key) + return value + + +def _get_sequence_as( + d: Mapping[str, Any], + expected_item_type: type[_T], + target_item_type: Callable[[_T], _T2], + key: str, +) -> list[_T2] | None: + """Get list value from dictionary and verify expected items type.""" + if (value := _get_sequence(d, expected_item_type, key)) is None: + return None + result = [] + try: + for item in value: + typed_item = target_item_type(item) + result.append(typed_item) + except Exception as e: + raise PylockValidationError(e, context=f"{key}[{len(result)}]") from e + return result + + +def _get_object( + d: Mapping[str, Any], target_type: type[_FromMappingProtocolT], key: str +) -> _FromMappingProtocolT | None: + """Get a dictionary value from the dictionary and convert it to a dataclass.""" + if (value := _get(d, Mapping, key)) is None: # type: ignore[type-abstract] + return None + try: + return target_type._from_dict(value) + except Exception as e: + raise PylockValidationError(e, context=key) from e + + +def _get_sequence_of_objects( + d: Mapping[str, Any], target_item_type: type[_FromMappingProtocolT], key: str +) -> list[_FromMappingProtocolT] | None: + """Get a list value from the dictionary and convert its items to a dataclass.""" + if (value := _get_sequence(d, Mapping, key)) is None: # type: ignore[type-abstract] + return None + result: list[_FromMappingProtocolT] = [] + try: + for item in value: + typed_item = target_item_type._from_dict(item) + result.append(typed_item) + except Exception as e: + raise PylockValidationError(e, context=f"{key}[{len(result)}]") from e + return result + + +def _get_required_sequence_of_objects( + d: Mapping[str, Any], target_item_type: type[_FromMappingProtocolT], key: str +) -> Sequence[_FromMappingProtocolT]: + """Get a required list value from the dictionary and convert its items to a + dataclass.""" + if (result := _get_sequence_of_objects(d, target_item_type, key)) is None: + raise _PylockRequiredKeyError(key) + return result + + +def _validate_normalized_name(name: str) -> NormalizedName: + """Validate that a string is a NormalizedName.""" + if not is_normalized_name(name): + raise PylockValidationError(f"Name {name!r} is not normalized") + return NormalizedName(name) + + +def _validate_path_url(path: str | None, url: str | None) -> None: + if not path and not url: + raise PylockValidationError("path or url must be provided") + + +def _path_name(path: str | None) -> str | None: + if not path: + return None + # If the path is relative it MAY use POSIX-style path separators explicitly + # for portability + if "/" in path: + return path.rsplit("/", 1)[-1] + elif "\\" in path: + return path.rsplit("\\", 1)[-1] + else: + return path + + +def _url_name(url: str | None) -> str | None: + if not url: + return None + url_path = urlparse(url).path + return url_path.rsplit("/", 1)[-1] + + +def _validate_hashes(hashes: Mapping[str, Any]) -> Mapping[str, Any]: + if not hashes: + raise PylockValidationError("At least one hash must be provided") + if not all(isinstance(hash_val, str) for hash_val in hashes.values()): + raise PylockValidationError("Hash values must be strings") + return hashes + + +class PylockValidationError(Exception): + """Raised when when input data is not spec-compliant.""" + + context: str | None = None + message: str + + def __init__( + self, + cause: str | Exception, + *, + context: str | None = None, + ) -> None: + if isinstance(cause, PylockValidationError): + if cause.context: + self.context = ( + f"{context}.{cause.context}" if context else cause.context + ) + else: + self.context = context + self.message = cause.message + else: + self.context = context + self.message = str(cause) + + def __str__(self) -> str: + if self.context: + return f"{self.message} in {self.context!r}" + return self.message + + +class _PylockRequiredKeyError(PylockValidationError): + def __init__(self, key: str) -> None: + super().__init__("Missing required value", context=key) + + +class PylockUnsupportedVersionError(PylockValidationError): + """Raised when encountering an unsupported `lock_version`.""" + + +class PylockSelectError(Exception): + """Base exception for errors raised by :meth:`Pylock.select`.""" + + +@dataclass(frozen=True, init=False) +class PackageVcs: + type: str + url: str | None = None + path: str | None = None + requested_revision: str | None = None + commit_id: str # type: ignore[misc] + subdirectory: str | None = None + + def __init__( + self, + *, + type: str, + url: str | None = None, + path: str | None = None, + requested_revision: str | None = None, + commit_id: str, + subdirectory: str | None = None, + ) -> None: + # In Python 3.10+ make dataclass kw_only=True and remove __init__ + object.__setattr__(self, "type", type) + object.__setattr__(self, "url", url) + object.__setattr__(self, "path", path) + object.__setattr__(self, "requested_revision", requested_revision) + object.__setattr__(self, "commit_id", commit_id) + object.__setattr__(self, "subdirectory", subdirectory) + + @classmethod + def _from_dict(cls, d: Mapping[str, Any]) -> Self: + package_vcs = cls( + type=_get_required(d, str, "type"), + url=_get(d, str, "url"), + path=_get(d, str, "path"), + requested_revision=_get(d, str, "requested-revision"), + commit_id=_get_required(d, str, "commit-id"), + subdirectory=_get(d, str, "subdirectory"), + ) + _validate_path_url(package_vcs.path, package_vcs.url) + return package_vcs + + +@dataclass(frozen=True, init=False) +class PackageDirectory: + path: str + editable: bool | None = None + subdirectory: str | None = None + + def __init__( + self, + *, + path: str, + editable: bool | None = None, + subdirectory: str | None = None, + ) -> None: + # In Python 3.10+ make dataclass kw_only=True and remove __init__ + object.__setattr__(self, "path", path) + object.__setattr__(self, "editable", editable) + object.__setattr__(self, "subdirectory", subdirectory) + + @classmethod + def _from_dict(cls, d: Mapping[str, Any]) -> Self: + return cls( + path=_get_required(d, str, "path"), + editable=_get(d, bool, "editable"), + subdirectory=_get(d, str, "subdirectory"), + ) + + +@dataclass(frozen=True, init=False) +class PackageArchive: + url: str | None = None + path: str | None = None + size: int | None = None + upload_time: datetime | None = None + hashes: Mapping[str, str] # type: ignore[misc] + subdirectory: str | None = None + + def __init__( + self, + *, + url: str | None = None, + path: str | None = None, + size: int | None = None, + upload_time: datetime | None = None, + hashes: Mapping[str, str], + subdirectory: str | None = None, + ) -> None: + # In Python 3.10+ make dataclass kw_only=True and remove __init__ + object.__setattr__(self, "url", url) + object.__setattr__(self, "path", path) + object.__setattr__(self, "size", size) + object.__setattr__(self, "upload_time", upload_time) + object.__setattr__(self, "hashes", hashes) + object.__setattr__(self, "subdirectory", subdirectory) + + @classmethod + def _from_dict(cls, d: Mapping[str, Any]) -> Self: + package_archive = cls( + url=_get(d, str, "url"), + path=_get(d, str, "path"), + size=_get(d, int, "size"), + upload_time=_get(d, datetime, "upload-time"), + hashes=_get_required_as(d, Mapping, _validate_hashes, "hashes"), # type: ignore[type-abstract] + subdirectory=_get(d, str, "subdirectory"), + ) + _validate_path_url(package_archive.path, package_archive.url) + return package_archive + + +@dataclass(frozen=True, init=False) +class PackageSdist: + name: str | None = None + upload_time: datetime | None = None + url: str | None = None + path: str | None = None + size: int | None = None + hashes: Mapping[str, str] # type: ignore[misc] + + def __init__( + self, + *, + name: str | None = None, + upload_time: datetime | None = None, + url: str | None = None, + path: str | None = None, + size: int | None = None, + hashes: Mapping[str, str], + ) -> None: + # In Python 3.10+ make dataclass kw_only=True and remove __init__ + object.__setattr__(self, "name", name) + object.__setattr__(self, "upload_time", upload_time) + object.__setattr__(self, "url", url) + object.__setattr__(self, "path", path) + object.__setattr__(self, "size", size) + object.__setattr__(self, "hashes", hashes) + + @classmethod + def _from_dict(cls, d: Mapping[str, Any]) -> Self: + package_sdist = cls( + name=_get(d, str, "name"), + upload_time=_get(d, datetime, "upload-time"), + url=_get(d, str, "url"), + path=_get(d, str, "path"), + size=_get(d, int, "size"), + hashes=_get_required_as(d, Mapping, _validate_hashes, "hashes"), # type: ignore[type-abstract] + ) + _validate_path_url(package_sdist.path, package_sdist.url) + return package_sdist + + @property + def filename(self) -> str: + """Get the filename of the sdist.""" + filename = self.name or _path_name(self.path) or _url_name(self.url) + if not filename: + raise PylockValidationError("Cannot determine sdist filename") + return filename + + +@dataclass(frozen=True, init=False) +class PackageWheel: + name: str | None = None + upload_time: datetime | None = None + url: str | None = None + path: str | None = None + size: int | None = None + hashes: Mapping[str, str] # type: ignore[misc] + + def __init__( + self, + *, + name: str | None = None, + upload_time: datetime | None = None, + url: str | None = None, + path: str | None = None, + size: int | None = None, + hashes: Mapping[str, str], + ) -> None: + # In Python 3.10+ make dataclass kw_only=True and remove __init__ + object.__setattr__(self, "name", name) + object.__setattr__(self, "upload_time", upload_time) + object.__setattr__(self, "url", url) + object.__setattr__(self, "path", path) + object.__setattr__(self, "size", size) + object.__setattr__(self, "hashes", hashes) + + @classmethod + def _from_dict(cls, d: Mapping[str, Any]) -> Self: + package_wheel = cls( + name=_get(d, str, "name"), + upload_time=_get(d, datetime, "upload-time"), + url=_get(d, str, "url"), + path=_get(d, str, "path"), + size=_get(d, int, "size"), + hashes=_get_required_as(d, Mapping, _validate_hashes, "hashes"), # type: ignore[type-abstract] + ) + _validate_path_url(package_wheel.path, package_wheel.url) + return package_wheel + + @property + def filename(self) -> str: + """Get the filename of the wheel.""" + filename = self.name or _path_name(self.path) or _url_name(self.url) + if not filename: + raise PylockValidationError("Cannot determine wheel filename") + return filename + + +@dataclass(frozen=True, init=False) +class Package: + name: NormalizedName + version: Version | None = None + marker: Marker | None = None + requires_python: SpecifierSet | None = None + dependencies: Sequence[Mapping[str, Any]] | None = None + vcs: PackageVcs | None = None + directory: PackageDirectory | None = None + archive: PackageArchive | None = None + index: str | None = None + sdist: PackageSdist | None = None + wheels: Sequence[PackageWheel] | None = None + attestation_identities: Sequence[Mapping[str, Any]] | None = None + tool: Mapping[str, Any] | None = None + + def __init__( + self, + *, + name: NormalizedName, + version: Version | None = None, + marker: Marker | None = None, + requires_python: SpecifierSet | None = None, + dependencies: Sequence[Mapping[str, Any]] | None = None, + vcs: PackageVcs | None = None, + directory: PackageDirectory | None = None, + archive: PackageArchive | None = None, + index: str | None = None, + sdist: PackageSdist | None = None, + wheels: Sequence[PackageWheel] | None = None, + attestation_identities: Sequence[Mapping[str, Any]] | None = None, + tool: Mapping[str, Any] | None = None, + ) -> None: + # In Python 3.10+ make dataclass kw_only=True and remove __init__ + object.__setattr__(self, "name", name) + object.__setattr__(self, "version", version) + object.__setattr__(self, "marker", marker) + object.__setattr__(self, "requires_python", requires_python) + object.__setattr__(self, "dependencies", dependencies) + object.__setattr__(self, "vcs", vcs) + object.__setattr__(self, "directory", directory) + object.__setattr__(self, "archive", archive) + object.__setattr__(self, "index", index) + object.__setattr__(self, "sdist", sdist) + object.__setattr__(self, "wheels", wheels) + object.__setattr__(self, "attestation_identities", attestation_identities) + object.__setattr__(self, "tool", tool) + + @classmethod + def _from_dict(cls, d: Mapping[str, Any]) -> Self: + package = cls( + name=_get_required_as(d, str, _validate_normalized_name, "name"), + version=_get_as(d, str, Version, "version"), + requires_python=_get_as(d, str, SpecifierSet, "requires-python"), + dependencies=_get_sequence(d, Mapping, "dependencies"), # type: ignore[type-abstract] + marker=_get_as(d, str, Marker, "marker"), + vcs=_get_object(d, PackageVcs, "vcs"), + directory=_get_object(d, PackageDirectory, "directory"), + archive=_get_object(d, PackageArchive, "archive"), + index=_get(d, str, "index"), + sdist=_get_object(d, PackageSdist, "sdist"), + wheels=_get_sequence_of_objects(d, PackageWheel, "wheels"), + attestation_identities=_get_sequence(d, Mapping, "attestation-identities"), # type: ignore[type-abstract] + tool=_get(d, Mapping, "tool"), # type: ignore[type-abstract] + ) + distributions = bool(package.sdist) + len(package.wheels or []) + direct_urls = ( + bool(package.vcs) + bool(package.directory) + bool(package.archive) + ) + if distributions > 0 and direct_urls > 0: + raise PylockValidationError( + "None of vcs, directory, archive must be set if sdist or wheels are set" + ) + if distributions == 0 and direct_urls != 1: + raise PylockValidationError( + "Exactly one of vcs, directory, archive must be set " + "if sdist and wheels are not set" + ) + for i, wheel in enumerate(package.wheels or []): + try: + (name, version, _, _) = parse_wheel_filename(wheel.filename) + except Exception as e: + raise PylockValidationError( + f"Invalid wheel filename {wheel.filename!r}", + context=f"wheels[{i}]", + ) from e + if name != package.name: + raise PylockValidationError( + f"Name in {wheel.filename!r} is not consistent with " + f"package name {package.name!r}", + context=f"wheels[{i}]", + ) + if package.version and version != package.version: + raise PylockValidationError( + f"Version in {wheel.filename!r} is not consistent with " + f"package version {str(package.version)!r}", + context=f"wheels[{i}]", + ) + if package.sdist: + try: + name, version = parse_sdist_filename(package.sdist.filename) + except Exception as e: + raise PylockValidationError( + f"Invalid sdist filename {package.sdist.filename!r}", + context="sdist", + ) from e + if name != package.name: + raise PylockValidationError( + f"Name in {package.sdist.filename!r} is not consistent with " + f"package name {package.name!r}", + context="sdist", + ) + if package.version and version != package.version: + raise PylockValidationError( + f"Version in {package.sdist.filename!r} is not consistent with " + f"package version {str(package.version)!r}", + context="sdist", + ) + try: + for i, attestation_identity in enumerate( # noqa: B007 + package.attestation_identities or [] + ): + _get_required(attestation_identity, str, "kind") + except Exception as e: + raise PylockValidationError( + e, context=f"attestation-identities[{i}]" + ) from e + return package + + @property + def is_direct(self) -> bool: + return not (self.sdist or self.wheels) + + +@dataclass(frozen=True, init=False) +class Pylock: + """A class representing a pylock file.""" + + lock_version: Version + environments: Sequence[Marker] | None = None + requires_python: SpecifierSet | None = None + extras: Sequence[NormalizedName] | None = None + dependency_groups: Sequence[str] | None = None + default_groups: Sequence[str] | None = None + created_by: str # type: ignore[misc] + packages: Sequence[Package] # type: ignore[misc] + tool: Mapping[str, Any] | None = None + + def __init__( + self, + *, + lock_version: Version, + environments: Sequence[Marker] | None = None, + requires_python: SpecifierSet | None = None, + extras: Sequence[NormalizedName] | None = None, + dependency_groups: Sequence[str] | None = None, + default_groups: Sequence[str] | None = None, + created_by: str, + packages: Sequence[Package], + tool: Mapping[str, Any] | None = None, + ) -> None: + # In Python 3.10+ make dataclass kw_only=True and remove __init__ + object.__setattr__(self, "lock_version", lock_version) + object.__setattr__(self, "environments", environments) + object.__setattr__(self, "requires_python", requires_python) + object.__setattr__(self, "extras", extras) + object.__setattr__(self, "dependency_groups", dependency_groups) + object.__setattr__(self, "default_groups", default_groups) + object.__setattr__(self, "created_by", created_by) + object.__setattr__(self, "packages", packages) + object.__setattr__(self, "tool", tool) + + @classmethod + def _from_dict(cls, d: Mapping[str, Any]) -> Self: + pylock = cls( + lock_version=_get_required_as(d, str, Version, "lock-version"), + environments=_get_sequence_as(d, str, Marker, "environments"), + extras=_get_sequence_as(d, str, _validate_normalized_name, "extras"), + dependency_groups=_get_sequence(d, str, "dependency-groups"), + default_groups=_get_sequence(d, str, "default-groups"), + created_by=_get_required(d, str, "created-by"), + requires_python=_get_as(d, str, SpecifierSet, "requires-python"), + packages=_get_required_sequence_of_objects(d, Package, "packages"), + tool=_get(d, Mapping, "tool"), # type: ignore[type-abstract] + ) + if not Version("1") <= pylock.lock_version < Version("2"): + raise PylockUnsupportedVersionError( + f"pylock version {pylock.lock_version} is not supported" + ) + if pylock.lock_version > Version("1.0"): + _logger.warning( + "pylock minor version %s is not supported", pylock.lock_version + ) + return pylock + + @classmethod + def from_dict(cls, d: Mapping[str, Any], /) -> Self: + """Create and validate a Pylock instance from a TOML dictionary. + + Raises :class:`PylockValidationError` if the input data is not + spec-compliant. + """ + return cls._from_dict(d) + + def to_dict(self) -> Mapping[str, Any]: + """Convert the Pylock instance to a TOML dictionary.""" + return dataclasses.asdict(self, dict_factory=_toml_dict_factory) + + def validate(self) -> None: + """Validate the Pylock instance against the specification. + + Raises :class:`PylockValidationError` otherwise.""" + self.from_dict(self.to_dict()) + + def select( + self, + *, + environment: Environment | None = None, + tags: Sequence[Tag] | None = None, + extras: Collection[str] | None = None, + dependency_groups: Collection[str] | None = None, + ) -> Iterator[ + tuple[ + Package, + PackageVcs + | PackageDirectory + | PackageArchive + | PackageWheel + | PackageSdist, + ] + ]: + """Select what to install from the lock file. + + The *environment* and *tags* parameters represent the environment being + selected for. If unspecified, ``packaging.markers.default_environment()`` and + ``packaging.tags.sys_tags()`` are used. + + The *extras* parameter represents the extras to install. + + The *dependency_groups* parameter represents the groups to install. If + unspecified, the default groups are used. + + This method must be used on valid Pylock instances (i.e. one obtained + from :meth:`Pylock.from_dict` or if constructed manually, after calling + :meth:`Pylock.validate`). + """ + compatible_tags_selector = create_compatible_tags_selector(tags or sys_tags()) + + # #. Gather the extras and dependency groups to install and set ``extras`` and + # ``dependency_groups`` for marker evaluation, respectively. + # + # #. ``extras`` SHOULD be set to the empty set by default. + # #. ``dependency_groups`` SHOULD be the set created from + # :ref:`pylock-default-groups` by default. + env = cast( + "dict[str, str | frozenset[str]]", + dict( + environment or {}, # Marker.evaluate will fill-up + extras=frozenset(extras or []), + dependency_groups=frozenset( + (self.default_groups or []) + if dependency_groups is None # to allow selecting no group + else dependency_groups + ), + ), + ) + env_python_full_version = ( + environment["python_full_version"] + if environment + else default_environment()["python_full_version"] + ) + + # #. Check if the metadata version specified by :ref:`pylock-lock-version` is + # supported; an error or warning MUST be raised as appropriate. + # Covered by lock.validate() which is a precondition for this method. + + # #. If :ref:`pylock-requires-python` is specified, check that the environment + # being installed for meets the requirement; an error MUST be raised if it is + # not met. + if self.requires_python and not self.requires_python.contains( + env_python_full_version, + ): + raise PylockSelectError( + f"python_full_version {env_python_full_version!r} " + f"in provided environment does not satisfy the Python version " + f"requirement {str(self.requires_python)!r}" + ) + + # #. If :ref:`pylock-environments` is specified, check that at least one of the + # environment marker expressions is satisfied; an error MUST be raised if no + # expression is satisfied. + if self.environments: + for env_marker in self.environments: + if env_marker.evaluate( + cast("dict[str, str]", environment or {}), context="requirement" + ): + break + else: + raise PylockSelectError( + "Provided environment does not satisfy any of the " + "environments specified in the lock file" + ) + + # #. For each package listed in :ref:`pylock-packages`: + selected_packages_by_name: dict[str, tuple[int, Package]] = {} + for package_index, package in enumerate(self.packages): + # #. If :ref:`pylock-packages-marker` is specified, check if it is + # satisfied;if it isn't, skip to the next package. + if package.marker and not package.marker.evaluate(env, context="lock_file"): + continue + + # #. If :ref:`pylock-packages-requires-python` is specified, check if it is + # satisfied; an error MUST be raised if it isn't. + if package.requires_python and not package.requires_python.contains( + env_python_full_version, + ): + raise PylockSelectError( + f"python_full_version {env_python_full_version!r} " + f"in provided environment does not satisfy the Python version " + f"requirement {str(package.requires_python)!r} for package " + f"{package.name!r} at packages[{package_index}]" + ) + + # #. Check that no other conflicting instance of the package has been slated + # to be installed; an error about the ambiguity MUST be raised otherwise. + if package.name in selected_packages_by_name: + raise PylockSelectError( + f"Multiple packages with the name {package.name!r} are " + f"selected at packages[{package_index}] and " + f"packages[{selected_packages_by_name[package.name][0]}]" + ) + + # #. Check that the source of the package is specified appropriately (i.e. + # there are no conflicting sources in the package entry); + # an error MUST be raised if any issues are found. + # Covered by lock.validate() which is a precondition for this method. + + # #. Add the package to the set of packages to install. + selected_packages_by_name[package.name] = (package_index, package) + + # #. For each package to be installed: + for package_index, package in selected_packages_by_name.values(): + # - If :ref:`pylock-packages-vcs` is set: + if package.vcs is not None: + yield package, package.vcs + + # - Else if :ref:`pylock-packages-directory` is set: + elif package.directory is not None: + yield package, package.directory + + # - Else if :ref:`pylock-packages-archive` is set: + elif package.archive is not None: + yield package, package.archive + + # - Else if there are entries for :ref:`pylock-packages-wheels`: + elif package.wheels: + # #. Look for the appropriate wheel file based on + # :ref:`pylock-packages-wheels-name`; if one is not found then move + # on to :ref:`pylock-packages-sdist` or an error MUST be raised about + # a lack of source for the project. + best_wheel = next( + compatible_tags_selector( + (wheel, parse_wheel_filename(wheel.filename)[-1]) + for wheel in package.wheels + ), + None, + ) + if best_wheel: + yield package, best_wheel + elif package.sdist is not None: + yield package, package.sdist + else: + raise PylockSelectError( + f"No wheel found matching the provided tags " + f"for package {package.name!r} " + f"at packages[{package_index}], " + f"and no sdist available as a fallback" + ) + + # - Else if no :ref:`pylock-packages-wheels` file is found or + # :ref:`pylock-packages-sdist` is solely set: + elif package.sdist is not None: + yield package, package.sdist + + else: + # Covered by lock.validate() which is a precondition for this method. + raise NotImplementedError # pragma: no cover diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/requirements.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/requirements.py new file mode 100644 index 0000000..5892aee --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/requirements.py @@ -0,0 +1,129 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import annotations + +from typing import Iterator + +from ._parser import parse_requirement as _parse_requirement +from ._tokenizer import ParserSyntaxError +from .markers import Marker, _normalize_extra_values +from .specifiers import SpecifierSet +from .utils import canonicalize_name + +__all__ = [ + "InvalidRequirement", + "Requirement", +] + + +def __dir__() -> list[str]: + return __all__ + + +class InvalidRequirement(ValueError): + """ + An invalid requirement was found, users should refer to PEP 508. + """ + + +class Requirement: + """Parse a requirement. + + Parse a given requirement string into its parts, such as name, specifier, + URL, and extras. Raises InvalidRequirement on a badly-formed requirement + string. + + Instances are safe to serialize with :mod:`pickle`. They use a stable + format so the same pickle can be loaded in future packaging releases. + + .. versionchanged:: 26.2 + + Added a stable pickle format. Pickles created with packaging 26.2+ can + be unpickled with future releases. Backward compatibility with pickles + from packaging < 26.2 is supported but may be removed in a future + release. + """ + + # TODO: Can we test whether something is contained within a requirement? + # If so how do we do that? Do we need to test against the _name_ of + # the thing as well as the version? What about the markers? + # TODO: Can we normalize the name and extra name? + + def __init__(self, requirement_string: str) -> None: + try: + parsed = _parse_requirement(requirement_string) + except ParserSyntaxError as e: + raise InvalidRequirement(str(e)) from e + + self.name: str = parsed.name + self.url: str | None = parsed.url or None + self.extras: set[str] = set(parsed.extras or []) + self.specifier: SpecifierSet = SpecifierSet(parsed.specifier) + self.marker: Marker | None = None + if parsed.marker is not None: + self.marker = Marker.__new__(Marker) + self.marker._markers = _normalize_extra_values(parsed.marker) + + def _iter_parts(self, name: str) -> Iterator[str]: + yield name + + if self.extras: + formatted_extras = ",".join(sorted(self.extras)) + yield f"[{formatted_extras}]" + + if self.specifier: + yield str(self.specifier) + + if self.url: + yield f" @ {self.url}" + if self.marker: + yield " " + + if self.marker: + yield f"; {self.marker}" + + def __getstate__(self) -> str: + # Return the requirement string for compactness and stability. + # Re-parsed on load to reconstruct all fields. + return str(self) + + def __setstate__(self, state: object) -> None: + if isinstance(state, str): + # New format (26.2+): just the requirement string. + try: + tmp = Requirement(state) + except InvalidRequirement as exc: + raise TypeError(f"Cannot restore Requirement from {state!r}") from exc + self.name = tmp.name + self.url = tmp.url + self.extras = tmp.extras + self.specifier = tmp.specifier + self.marker = tmp.marker + return + if isinstance(state, dict): + # Old format (packaging <= 26.1, no __slots__): plain __dict__. + self.__dict__.update(state) + return + raise TypeError(f"Cannot restore Requirement from {state!r}") + + def __str__(self) -> str: + return "".join(self._iter_parts(self.name)) + + def __repr__(self) -> str: + return f"<{self.__class__.__name__}({str(self)!r})>" + + def __hash__(self) -> int: + return hash(tuple(self._iter_parts(canonicalize_name(self.name)))) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, Requirement): + return NotImplemented + + return ( + canonicalize_name(self.name) == canonicalize_name(other.name) + and self.extras == other.extras + and self.specifier == other.specifier + and self.url == other.url + and self.marker == other.marker + ) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/specifiers.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/specifiers.py new file mode 100644 index 0000000..b165dc0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/specifiers.py @@ -0,0 +1,1943 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +""" +.. testsetup:: + + from packaging.specifiers import Specifier, SpecifierSet, InvalidSpecifier + from packaging.version import Version +""" + +from __future__ import annotations + +import abc +import enum +import functools +import itertools +import re +import sys +import typing +from typing import ( + TYPE_CHECKING, + Any, + Callable, + Final, + Iterable, + Iterator, + Sequence, + TypeVar, + Union, +) + +from .utils import canonicalize_version +from .version import InvalidVersion, Version + +if sys.version_info >= (3, 10): + from typing import TypeGuard # pragma: no cover +elif TYPE_CHECKING: + from typing_extensions import TypeGuard + +__all__ = [ + "BaseSpecifier", + "InvalidSpecifier", + "Specifier", + "SpecifierSet", +] + + +def __dir__() -> list[str]: + return __all__ + + +def _validate_spec(spec: object, /) -> TypeGuard[tuple[str, str]]: + return ( + isinstance(spec, tuple) + and len(spec) == 2 + and isinstance(spec[0], str) + and isinstance(spec[1], str) + ) + + +def _validate_pre(pre: object, /) -> TypeGuard[bool | None]: + return pre is None or isinstance(pre, bool) + + +T = TypeVar("T") +UnparsedVersion = Union[Version, str] +UnparsedVersionVar = TypeVar("UnparsedVersionVar", bound=UnparsedVersion) +CallableOperator = Callable[[Version, str], bool] + +# The smallest possible PEP 440 version. No valid version is less than this. +_MIN_VERSION: Final[Version] = Version("0.dev0") + + +def _trim_release(release: tuple[int, ...]) -> tuple[int, ...]: + """Strip trailing zeros from a release tuple for normalized comparison.""" + end = len(release) + while end > 1 and release[end - 1] == 0: + end -= 1 + return release if end == len(release) else release[:end] + + +class _BoundaryKind(enum.Enum): + """Where a boundary marker sits in the version ordering.""" + + AFTER_LOCALS = enum.auto() # after V+local, before V.post0 + AFTER_POSTS = enum.auto() # after V.postN, before next release + + +@functools.total_ordering +class _BoundaryVersion: + """A point on the version line between two real PEP 440 versions. + + Some specifier semantics imply boundaries between real versions: + ``<=1.0`` includes ``1.0+local`` and ``>1.0`` excludes + ``1.0.post0``. No real :class:`Version` falls on those boundaries, + so this class creates values that sort between the real versions + on either side. + + Two kinds exist, shown relative to a base version V:: + + V < V+local < AFTER_LOCALS(V) < V.post0 < AFTER_POSTS(V) + + ``AFTER_LOCALS`` sits after V and every V+local, but before + V.post0. Upper bound of ``<=V``, ``==V``, ``!=V``. + + ``AFTER_POSTS`` sits after every V.postN, but before the next + release segment. Lower bound of ``>V`` (final or pre-release V) + to exclude post-releases per PEP 440. + """ + + __slots__ = ("_kind", "_trimmed_release", "version") + + def __init__(self, version: Version, kind: _BoundaryKind) -> None: + self.version = version + self._kind = kind + self._trimmed_release = _trim_release(version.release) + + def _is_family(self, other: Version) -> bool: + """Is ``other`` a version that this boundary sorts above?""" + v = self.version + if not ( + other.epoch == v.epoch + and _trim_release(other.release) == self._trimmed_release + and other.pre == v.pre + ): + return False + if self._kind == _BoundaryKind.AFTER_LOCALS: + # Local family: exact same public version (any local label). + return other.post == v.post and other.dev == v.dev + # Post family: same base + any post-release (or identical). + return other.dev == v.dev or other.post is not None + + def __eq__(self, other: object) -> bool: + if isinstance(other, _BoundaryVersion): + return self.version == other.version and self._kind == other._kind + return NotImplemented + + def __lt__(self, other: _BoundaryVersion | Version) -> bool: + if isinstance(other, _BoundaryVersion): + if self.version != other.version: + return self.version < other.version + return self._kind.value < other._kind.value + return not self._is_family(other) and self.version < other + + def __hash__(self) -> int: + return hash((self.version, self._kind)) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self.version!r}, {self._kind.name})" + + +@functools.total_ordering +class _LowerBound: + """Lower bound of a version range. + + A version *v* of ``None`` means unbounded below (-inf). + At equal versions, ``[v`` sorts before ``(v`` because an inclusive + bound starts earlier. + """ + + __slots__ = ("inclusive", "version") + + def __init__(self, version: _VersionOrBoundary, inclusive: bool) -> None: + self.version = version + self.inclusive = inclusive + + def __eq__(self, other: object) -> bool: + if not isinstance(other, _LowerBound): + return NotImplemented # pragma: no cover + return self.version == other.version and self.inclusive == other.inclusive + + def __lt__(self, other: _LowerBound) -> bool: + if not isinstance(other, _LowerBound): # pragma: no cover + return NotImplemented + # -inf < anything (except -inf). + if self.version is None: + return other.version is not None + if other.version is None: + return False + if self.version != other.version: + return self.version < other.version + # [v < (v: inclusive starts earlier. + return self.inclusive and not other.inclusive + + def __hash__(self) -> int: + return hash((self.version, self.inclusive)) + + def __repr__(self) -> str: + bracket = "[" if self.inclusive else "(" + return f"<{self.__class__.__name__} {bracket}{self.version!r}>" + + +@functools.total_ordering +class _UpperBound: + """Upper bound of a version range. + + A version *v* of ``None`` means unbounded above (+inf). + At equal versions, ``v)`` sorts before ``v]`` because an exclusive + bound ends earlier. + """ + + __slots__ = ("inclusive", "version") + + def __init__(self, version: _VersionOrBoundary, inclusive: bool) -> None: + self.version = version + self.inclusive = inclusive + + def __eq__(self, other: object) -> bool: + if not isinstance(other, _UpperBound): + return NotImplemented # pragma: no cover + return self.version == other.version and self.inclusive == other.inclusive + + def __lt__(self, other: _UpperBound) -> bool: + if not isinstance(other, _UpperBound): # pragma: no cover + return NotImplemented + # Nothing < +inf (except +inf itself). + if self.version is None: + return False + if other.version is None: + return True + if self.version != other.version: + return self.version < other.version + # v) < v]: exclusive ends earlier. + return not self.inclusive and other.inclusive + + def __hash__(self) -> int: + return hash((self.version, self.inclusive)) + + def __repr__(self) -> str: + bracket = "]" if self.inclusive else ")" + return f"<{self.__class__.__name__} {self.version!r}{bracket}>" + + +if typing.TYPE_CHECKING: + _VersionOrBoundary = Union[Version, _BoundaryVersion, None] + + #: A single contiguous version range, represented as a + #: (lower bound, upper bound) pair. + _VersionRange = tuple[_LowerBound, _UpperBound] + +_NEG_INF = _LowerBound(None, False) +_POS_INF = _UpperBound(None, False) +_FULL_RANGE: tuple[_VersionRange] = ((_NEG_INF, _POS_INF),) + + +def _range_is_empty(lower: _LowerBound, upper: _UpperBound) -> bool: + """True when the range defined by *lower* and *upper* contains no versions.""" + if lower.version is None or upper.version is None: + return False + if lower.version == upper.version: + return not (lower.inclusive and upper.inclusive) + return lower.version > upper.version + + +def _intersect_ranges( + left: Sequence[_VersionRange], + right: Sequence[_VersionRange], +) -> list[_VersionRange]: + """Intersect two sorted, non-overlapping range lists (two-pointer merge).""" + result: list[_VersionRange] = [] + left_index = right_index = 0 + while left_index < len(left) and right_index < len(right): + left_lower, left_upper = left[left_index] + right_lower, right_upper = right[right_index] + + lower = max(left_lower, right_lower) + upper = min(left_upper, right_upper) + + if not _range_is_empty(lower, upper): + result.append((lower, upper)) + + # Advance whichever side has the smaller upper bound. + if left_upper < right_upper: + left_index += 1 + else: + right_index += 1 + + return result + + +def _next_prefix_dev0(version: Version) -> Version: + """Smallest version in the next prefix: 1.2 -> 1.3.dev0.""" + release = (*version.release[:-1], version.release[-1] + 1) + return Version.from_parts(epoch=version.epoch, release=release, dev=0) + + +def _base_dev0(version: Version) -> Version: + """The .dev0 of a version's base release: 1.2 -> 1.2.dev0.""" + return Version.from_parts(epoch=version.epoch, release=version.release, dev=0) + + +def _coerce_version(version: UnparsedVersion) -> Version | None: + if not isinstance(version, Version): + try: + version = Version(version) + except InvalidVersion: + return None + return version + + +def _public_version(version: Version) -> Version: + if version.local is None: + return version + return version.__replace__(local=None) + + +def _post_base(version: Version) -> Version: + """The version that *version* is a post-release of. + + 1.0.post1 -> 1.0, 1.0a1.post0 -> 1.0a1, 1.0.post0.dev1 -> 1.0. + """ + return version.__replace__(post=None, dev=None, local=None) + + +def _earliest_prerelease(version: Version) -> Version: + """Earliest pre-release of *version*. + + 1.2 -> 1.2.dev0, 1.2.post1 -> 1.2.post1.dev0. + """ + return version.__replace__(dev=0, local=None) + + +def _nearest_non_prerelease( + v: _VersionOrBoundary, +) -> Version | None: + """Smallest non-pre-release version at or above *v*, or None.""" + if v is None: + return None + if isinstance(v, _BoundaryVersion): + inner = v.version + if inner.is_prerelease: + # AFTER_LOCALS(1.0a1) -> nearest non-pre is 1.0 + return inner.__replace__(pre=None, dev=None, local=None) + # AFTER_LOCALS(1.0) -> nearest non-pre is 1.0.post0 + # AFTER_LOCALS(1.0.post0) -> nearest non-pre is 1.0.post1 + k = (inner.post + 1) if inner.post is not None else 0 + return inner.__replace__(post=k, local=None) + if not v.is_prerelease: + return v + # Strip pre/dev to get the final or post-release form. + return v.__replace__(pre=None, dev=None, local=None) + + +class InvalidSpecifier(ValueError): + """ + Raised when attempting to create a :class:`Specifier` with a specifier + string that is invalid. + + >>> Specifier("lolwat") + Traceback (most recent call last): + ... + packaging.specifiers.InvalidSpecifier: Invalid specifier: 'lolwat' + """ + + +class BaseSpecifier(metaclass=abc.ABCMeta): + __slots__ = () + __match_args__ = ("_str",) + + @property + def _str(self) -> str: + """Internal property for match_args""" + return str(self) + + @abc.abstractmethod + def __str__(self) -> str: + """ + Returns the str representation of this Specifier-like object. This + should be representative of the Specifier itself. + """ + + @abc.abstractmethod + def __hash__(self) -> int: + """ + Returns a hash value for this Specifier-like object. + """ + + @abc.abstractmethod + def __eq__(self, other: object) -> bool: + """ + Returns a boolean representing whether or not the two Specifier-like + objects are equal. + + :param other: The other object to check against. + """ + + @property + @abc.abstractmethod + def prereleases(self) -> bool | None: + """Whether or not pre-releases as a whole are allowed. + + This can be set to either ``True`` or ``False`` to explicitly enable or disable + prereleases or it can be set to ``None`` (the default) to use default semantics. + """ + + @prereleases.setter # noqa: B027 + def prereleases(self, value: bool) -> None: + """Setter for :attr:`prereleases`. + + :param value: The value to set. + """ + + @abc.abstractmethod + def contains(self, item: str, prereleases: bool | None = None) -> bool: + """ + Determines if the given item is contained within this specifier. + """ + + @typing.overload + def filter( + self, + iterable: Iterable[UnparsedVersionVar], + prereleases: bool | None = None, + key: None = ..., + ) -> Iterator[UnparsedVersionVar]: ... + + @typing.overload + def filter( + self, + iterable: Iterable[T], + prereleases: bool | None = None, + key: Callable[[T], UnparsedVersion] = ..., + ) -> Iterator[T]: ... + + @abc.abstractmethod + def filter( + self, + iterable: Iterable[Any], + prereleases: bool | None = None, + key: Callable[[Any], UnparsedVersion] | None = None, + ) -> Iterator[Any]: + """ + Takes an iterable of items and filters them so that only items which + are contained within this specifier are allowed in it. + """ + + +class Specifier(BaseSpecifier): + """This class abstracts handling of version specifiers. + + .. tip:: + + It is generally not required to instantiate this manually. You should instead + prefer to work with :class:`SpecifierSet` instead, which can parse + comma-separated version specifiers (which is what package metadata contains). + + Instances are safe to serialize with :mod:`pickle`. They use a stable + format so the same pickle can be loaded in future packaging releases. + + .. versionchanged:: 26.2 + + Added a stable pickle format. Pickles created with packaging 26.2+ can + be unpickled with future releases. Backward compatibility with pickles + from packaging < 26.2 is supported but may be removed in a future + release. + """ + + __slots__ = ( + "_prereleases", + "_ranges", + "_spec", + "_spec_version", + "_wildcard_split", + ) + + _specifier_regex_str = r""" + (?: + (?: + # The identity operators allow for an escape hatch that will + # do an exact string match of the version you wish to install. + # This will not be parsed by PEP 440 and we cannot determine + # any semantic meaning from it. This operator is discouraged + # but included entirely as an escape hatch. + === # Only match for the identity operator + \s* + [^\s;)]* # The arbitrary version can be just about anything, + # we match everything except for whitespace, a + # semi-colon for marker support, and a closing paren + # since versions can be enclosed in them. + ) + | + (?: + # The (non)equality operators allow for wild card and local + # versions to be specified so we have to define these two + # operators separately to enable that. + (?:==|!=) # Only match for equals and not equals + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)* # release + + # You cannot use a wild card and a pre-release, post-release, a dev or + # local version together so group them with a | and make them optional. + (?: + \.\* # Wild card syntax of .* + | + (?a: # pre release + [-_\.]? + (alpha|beta|preview|pre|a|b|c|rc) + [-_\.]? + [0-9]* + )? + (?a: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + (?a:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + (?a:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local + )? + ) + | + (?: + # The compatible operator requires at least two digits in the + # release segment. + (?:~=) # Only match for the compatible operator + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *) + (?: # pre release + [-_\.]? + (alpha|beta|preview|pre|a|b|c|rc) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + ) + | + (?: + # All other operators only allow a sub set of what the + # (non)equality operators do. Specifically they do not allow + # local versions to be specified nor do they allow the prefix + # matching wild cards. + (?:<=|>=|<|>) + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)* # release + (?a: # pre release + [-_\.]? + (alpha|beta|preview|pre|a|b|c|rc) + [-_\.]? + [0-9]* + )? + (?a: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + (?a:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + ) + ) + """ + + _regex = re.compile( + r"\s*" + _specifier_regex_str + r"\s*", re.VERBOSE | re.IGNORECASE + ) + + _operators: Final = { + "~=": "compatible", + "==": "equal", + "!=": "not_equal", + "<=": "less_than_equal", + ">=": "greater_than_equal", + "<": "less_than", + ">": "greater_than", + "===": "arbitrary", + } + + def __init__(self, spec: str = "", prereleases: bool | None = None) -> None: + """Initialize a Specifier instance. + + :param spec: + The string representation of a specifier which will be parsed and + normalized before use. + :param prereleases: + This tells the specifier if it should accept prerelease versions if + applicable or not. The default of ``None`` will autodetect it from the + given specifiers. + :raises InvalidSpecifier: + If the given specifier is invalid (i.e. bad syntax). + """ + if not self._regex.fullmatch(spec): + raise InvalidSpecifier(f"Invalid specifier: {spec!r}") + + spec = spec.strip() + if spec.startswith("==="): + operator, version = spec[:3], spec[3:].strip() + elif spec.startswith(("~=", "==", "!=", "<=", ">=")): + operator, version = spec[:2], spec[2:].strip() + else: + operator, version = spec[:1], spec[1:].strip() + + self._spec: tuple[str, str] = (operator, version) + + # Store whether or not this Specifier should accept prereleases + self._prereleases = prereleases + + # Specifier version cache + self._spec_version: tuple[str, Version] | None = None + + # Populated on first wildcard (==X.*) comparison + self._wildcard_split: tuple[list[str], int] | None = None + + # Version range cache (populated by _to_ranges) + self._ranges: Sequence[_VersionRange] | None = None + + def _get_spec_version(self, version: str) -> Version | None: + """One element cache, as only one spec Version is needed per Specifier.""" + if self._spec_version is not None and self._spec_version[0] == version: + return self._spec_version[1] + + version_specifier = _coerce_version(version) + if version_specifier is None: + return None + + self._spec_version = (version, version_specifier) + return version_specifier + + def _require_spec_version(self, version: str) -> Version: + """Get spec version, asserting it's valid (not for === operator). + + This method should only be called for operators where version + strings are guaranteed to be valid PEP 440 versions (not ===). + """ + spec_version = self._get_spec_version(version) + assert spec_version is not None + return spec_version + + def _to_ranges(self) -> Sequence[_VersionRange]: + """Convert this specifier to sorted, non-overlapping version ranges. + + Each standard operator maps to one or two ranges. ``===`` is + modeled as full range (actual check done separately). Cached. + """ + if self._ranges is not None: + return self._ranges + + op = self.operator + ver_str = self.version + + if op == "===": + self._ranges = _FULL_RANGE + return _FULL_RANGE + + if ver_str.endswith(".*"): + result = self._wildcard_ranges(op, ver_str) + else: + result = self._standard_ranges(op, ver_str) + + self._ranges = result + return result + + def _wildcard_ranges(self, op: str, ver_str: str) -> list[_VersionRange]: + # ==1.2.* -> [1.2.dev0, 1.3.dev0); !=1.2.* -> complement. + base = self._require_spec_version(ver_str[:-2]) + lower = _base_dev0(base) + upper = _next_prefix_dev0(base) + if op == "==": + return [(_LowerBound(lower, True), _UpperBound(upper, False))] + # != + return [ + (_NEG_INF, _UpperBound(lower, False)), + (_LowerBound(upper, True), _POS_INF), + ] + + def _standard_ranges(self, op: str, ver_str: str) -> list[_VersionRange]: + v = self._require_spec_version(ver_str) + + if op == ">=": + return [(_LowerBound(v, True), _POS_INF)] + + if op == "<=": + return [ + ( + _NEG_INF, + _UpperBound(_BoundaryVersion(v, _BoundaryKind.AFTER_LOCALS), True), + ) + ] + + if op == ">": + if v.dev is not None: + # >V.devN: dev versions have no post-releases, so the + # next real version is V.dev(N+1). + lower_ver = v.__replace__(dev=v.dev + 1, local=None) + return [(_LowerBound(lower_ver, True), _POS_INF)] + if v.post is not None: + # >V.postN: next real version is V.post(N+1).dev0. + lower_ver = v.__replace__(post=v.post + 1, dev=0, local=None) + return [(_LowerBound(lower_ver, True), _POS_INF)] + # >V (final or pre-release): skip V+local and all V.postN. + return [ + ( + _LowerBound(_BoundaryVersion(v, _BoundaryKind.AFTER_POSTS), False), + _POS_INF, + ) + ] + + if op == "<": + # bool | None: + # If there is an explicit prereleases set for this, then we'll just + # blindly use that. + if self._prereleases is not None: + return self._prereleases + + # Only the "!=" operator does not imply prereleases when + # the version in the specifier is a prerelease. + operator, version_str = self._spec + if operator == "!=": + return False + + # The == specifier with trailing .* cannot include prereleases + # e.g. "==1.0a1.*" is not valid. + if operator == "==" and version_str.endswith(".*"): + return False + + # "===" can have arbitrary string versions, so we cannot parse + # those, we take prereleases as unknown (None) for those. + version = self._get_spec_version(version_str) + if version is None: + return None + + # For all other operators, use the check if spec Version + # object implies pre-releases. + return version.is_prerelease + + @prereleases.setter + def prereleases(self, value: bool | None) -> None: + self._prereleases = value + + def __getstate__(self) -> tuple[tuple[str, str], bool | None]: + # Return state as a 2-item tuple for compactness: + # ((operator, version), prereleases) + # Cache members are excluded and will be recomputed on demand. + return (self._spec, self._prereleases) + + def __setstate__(self, state: object) -> None: + # Always discard cached values - they will be recomputed on demand. + self._spec_version = None + self._wildcard_split = None + self._ranges = None + + if isinstance(state, tuple): + if len(state) == 2: + # New format (26.2+): ((operator, version), prereleases) + spec, prereleases = state + if _validate_spec(spec) and _validate_pre(prereleases): + self._spec = spec + self._prereleases = prereleases + return + if len(state) == 2 and isinstance(state[1], dict): + # Format (packaging 26.0-26.1): (None, {slot: value}). + _, slot_dict = state + spec = slot_dict.get("_spec") + prereleases = slot_dict.get("_prereleases", "invalid") + if _validate_spec(spec) and _validate_pre(prereleases): + self._spec = spec + self._prereleases = prereleases + return + if isinstance(state, dict): + # Old format (packaging <= 25.x, no __slots__): state is a plain dict. + spec = state.get("_spec") + prereleases = state.get("_prereleases", "invalid") + if _validate_spec(spec) and _validate_pre(prereleases): + self._spec = spec + self._prereleases = prereleases + return + + raise TypeError(f"Cannot restore Specifier from {state!r}") + + @property + def operator(self) -> str: + """The operator of this specifier. + + >>> Specifier("==1.2.3").operator + '==' + """ + return self._spec[0] + + @property + def version(self) -> str: + """The version of this specifier. + + >>> Specifier("==1.2.3").version + '1.2.3' + """ + return self._spec[1] + + def __repr__(self) -> str: + """A representation of the Specifier that shows all internal state. + + >>> Specifier('>=1.0.0') + =1.0.0')> + >>> Specifier('>=1.0.0', prereleases=False) + =1.0.0', prereleases=False)> + >>> Specifier('>=1.0.0', prereleases=True) + =1.0.0', prereleases=True)> + """ + pre = ( + f", prereleases={self.prereleases!r}" + if self._prereleases is not None + else "" + ) + + return f"<{self.__class__.__name__}({str(self)!r}{pre})>" + + def __str__(self) -> str: + """A string representation of the Specifier that can be round-tripped. + + >>> str(Specifier('>=1.0.0')) + '>=1.0.0' + >>> str(Specifier('>=1.0.0', prereleases=False)) + '>=1.0.0' + """ + return "{}{}".format(*self._spec) + + @property + def _canonical_spec(self) -> tuple[str, str]: + operator, version = self._spec + if operator == "===" or version.endswith(".*"): + return operator, version + + spec_version = self._require_spec_version(version) + + canonical_version = canonicalize_version( + spec_version, strip_trailing_zero=(operator != "~=") + ) + + return operator, canonical_version + + def __hash__(self) -> int: + return hash(self._canonical_spec) + + def __eq__(self, other: object) -> bool: + """Whether or not the two Specifier-like objects are equal. + + :param other: The other object to check against. + + The value of :attr:`prereleases` is ignored. + + >>> Specifier("==1.2.3") == Specifier("== 1.2.3.0") + True + >>> (Specifier("==1.2.3", prereleases=False) == + ... Specifier("==1.2.3", prereleases=True)) + True + >>> Specifier("==1.2.3") == "==1.2.3" + True + >>> Specifier("==1.2.3") == Specifier("==1.2.4") + False + >>> Specifier("==1.2.3") == Specifier("~=1.2.3") + False + """ + if isinstance(other, str): + try: + other = self.__class__(str(other)) + except InvalidSpecifier: + return NotImplemented + elif not isinstance(other, self.__class__): + return NotImplemented + + return self._canonical_spec == other._canonical_spec + + def _get_operator(self, op: str) -> CallableOperator: + operator_callable: CallableOperator = getattr( + self, f"_compare_{self._operators[op]}" + ) + return operator_callable + + def _compare_compatible(self, prospective: Version, spec: str) -> bool: + # Compatible releases have an equivalent combination of >= and ==. That + # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to + # implement this in terms of the other specifiers instead of + # implementing it ourselves. The only thing we need to do is construct + # the other specifiers. + + # We want everything but the last item in the version, but we want to + # ignore suffix segments. + prefix = _version_join( + list(itertools.takewhile(_is_not_suffix, _version_split(spec)))[:-1] + ) + + # Add the prefix notation to the end of our string + prefix += ".*" + + return (self._compare_greater_than_equal(prospective, spec)) and ( + self._compare_equal(prospective, prefix) + ) + + def _get_wildcard_split(self, spec: str) -> tuple[list[str], int]: + """Cached split of a wildcard spec into components and numeric length. + + >>> Specifier("==1.*")._get_wildcard_split("1.*") + (['0', '1'], 2) + >>> Specifier("==3.10.*")._get_wildcard_split("3.10.*") + (['0', '3', '10'], 3) + """ + wildcard_split = self._wildcard_split + if wildcard_split is None: + normalized = canonicalize_version(spec[:-2], strip_trailing_zero=False) + split_spec = _version_split(normalized) + wildcard_split = (split_spec, _numeric_prefix_len(split_spec)) + self._wildcard_split = wildcard_split + return wildcard_split + + def _compare_equal(self, prospective: Version, spec: str) -> bool: + # We need special logic to handle prefix matching + if spec.endswith(".*"): + split_spec, spec_numeric_len = self._get_wildcard_split(spec) + + # In the case of prefix matching we want to ignore local segment. + normalized_prospective = canonicalize_version( + _public_version(prospective), strip_trailing_zero=False + ) + # Split the prospective version out by bangs and dots, and pretend + # that there is an implicit dot in between a release segment and + # a pre-release segment. + split_prospective = _version_split(normalized_prospective) + + # 0-pad the prospective version before shortening it to get the correct + # shortened version. + padded_prospective = _left_pad(split_prospective, spec_numeric_len) + + # Shorten the prospective version to be the same length as the spec + # so that we can determine if the specifier is a prefix of the + # prospective version or not. + shortened_prospective = padded_prospective[: len(split_spec)] + + return shortened_prospective == split_spec + else: + # Convert our spec string into a Version + spec_version = self._require_spec_version(spec) + + # If the specifier does not have a local segment, then we want to + # act as if the prospective version also does not have a local + # segment. + if not spec_version.local: + prospective = _public_version(prospective) + + return prospective == spec_version + + def _compare_not_equal(self, prospective: Version, spec: str) -> bool: + return not self._compare_equal(prospective, spec) + + def _compare_less_than_equal(self, prospective: Version, spec: str) -> bool: + # NB: Local version identifiers are NOT permitted in the version + # specifier, so local version labels can be universally removed from + # the prospective version. + return _public_version(prospective) <= self._require_spec_version(spec) + + def _compare_greater_than_equal(self, prospective: Version, spec: str) -> bool: + # NB: Local version identifiers are NOT permitted in the version + # specifier, so local version labels can be universally removed from + # the prospective version. + return _public_version(prospective) >= self._require_spec_version(spec) + + def _compare_less_than(self, prospective: Version, spec_str: str) -> bool: + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = self._require_spec_version(spec_str) + + # Check to see if the prospective version is less than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective < spec: + return False + + # The spec says: "= _earliest_prerelease(spec) + ): + return False + + # If we've gotten to here, it means that prospective version is both + # less than the spec version *and* it's not a pre-release of the same + # version in the spec. + return True + + def _compare_greater_than(self, prospective: Version, spec_str: str) -> bool: + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = self._require_spec_version(spec_str) + + # Check to see if the prospective version is greater than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective > spec: + return False + + # The spec says: ">V MUST NOT allow a post-release of the specified + # version unless the specified version is itself a post-release." + if ( + not spec.is_postrelease + and prospective.is_postrelease + and _post_base(prospective) == spec + ): + return False + + # Per the spec: ">V MUST NOT match a local version of the specified + # version". A "local version of V" is any version whose public part + # equals V. So >1.0a1 must not match 1.0a1+local, but must still + # match 1.0a2+local. + if prospective.local is not None and _public_version(prospective) == spec: + return False + + # If we've gotten to here, it means that prospective version is both + # greater than the spec version *and* it's not a pre-release of the + # same version in the spec. + return True + + def _compare_arbitrary(self, prospective: Version | str, spec: str) -> bool: + return str(prospective).lower() == str(spec).lower() + + def __contains__(self, item: str | Version) -> bool: + """Return whether or not the item is contained in this specifier. + + :param item: The item to check for. + + This is used for the ``in`` operator and behaves the same as + :meth:`contains` with no ``prereleases`` argument passed. + + >>> "1.2.3" in Specifier(">=1.2.3") + True + >>> Version("1.2.3") in Specifier(">=1.2.3") + True + >>> "1.0.0" in Specifier(">=1.2.3") + False + >>> "1.3.0a1" in Specifier(">=1.2.3") + True + >>> "1.3.0a1" in Specifier(">=1.2.3", prereleases=True) + True + """ + return self.contains(item) + + def contains(self, item: UnparsedVersion, prereleases: bool | None = None) -> bool: + """Return whether or not the item is contained in this specifier. + + :param item: + The item to check for, which can be a version string or a + :class:`Version` instance. + :param prereleases: + Whether or not to match prereleases with this Specifier. If set to + ``None`` (the default), it will follow the recommendation from + :pep:`440` and match prereleases, as there are no other versions. + + >>> Specifier(">=1.2.3").contains("1.2.3") + True + >>> Specifier(">=1.2.3").contains(Version("1.2.3")) + True + >>> Specifier(">=1.2.3").contains("1.0.0") + False + >>> Specifier(">=1.2.3").contains("1.3.0a1") + True + >>> Specifier(">=1.2.3", prereleases=False).contains("1.3.0a1") + False + >>> Specifier(">=1.2.3").contains("1.3.0a1") + True + """ + + return bool(list(self.filter([item], prereleases=prereleases))) + + @typing.overload + def filter( + self, + iterable: Iterable[UnparsedVersionVar], + prereleases: bool | None = None, + key: None = ..., + ) -> Iterator[UnparsedVersionVar]: ... + + @typing.overload + def filter( + self, + iterable: Iterable[T], + prereleases: bool | None = None, + key: Callable[[T], UnparsedVersion] = ..., + ) -> Iterator[T]: ... + + def filter( + self, + iterable: Iterable[Any], + prereleases: bool | None = None, + key: Callable[[Any], UnparsedVersion] | None = None, + ) -> Iterator[Any]: + """Filter items in the given iterable, that match the specifier. + + :param iterable: + An iterable that can contain version strings and :class:`Version` instances. + The items in the iterable will be filtered according to the specifier. + :param prereleases: + Whether or not to allow prereleases in the returned iterator. If set to + ``None`` (the default), it will follow the recommendation from :pep:`440` + and match prereleases if there are no other versions. + :param key: + A callable that takes a single argument (an item from the iterable) and + returns a version string or :class:`Version` instance to be used for + filtering. + + >>> list(Specifier(">=1.2.3").filter(["1.2", "1.3", "1.5a1"])) + ['1.3'] + >>> list(Specifier(">=1.2.3").filter(["1.2", "1.2.3", "1.3", Version("1.4")])) + ['1.2.3', '1.3', ] + >>> list(Specifier(">=1.2.3").filter(["1.2", "1.5a1"])) + ['1.5a1'] + >>> list(Specifier(">=1.2.3").filter(["1.3", "1.5a1"], prereleases=True)) + ['1.3', '1.5a1'] + >>> list(Specifier(">=1.2.3", prereleases=True).filter(["1.3", "1.5a1"])) + ['1.3', '1.5a1'] + >>> list(Specifier(">=1.2.3").filter( + ... [{"ver": "1.2"}, {"ver": "1.3"}], + ... key=lambda x: x["ver"])) + [{'ver': '1.3'}] + """ + prereleases_versions = [] + found_non_prereleases = False + + # Determine if to include prereleases by default + include_prereleases = ( + prereleases if prereleases is not None else self.prereleases + ) + + # Get the matching operator + operator_callable = self._get_operator(self.operator) + + # Filter versions + for version in iterable: + parsed_version = _coerce_version(version if key is None else key(version)) + match = False + if parsed_version is None: + # === operator can match arbitrary (non-version) strings + if self.operator == "===" and self._compare_arbitrary( + version, self.version + ): + yield version + elif self.operator == "===": + match = self._compare_arbitrary( + version if key is None else key(version), self.version + ) + else: + match = operator_callable(parsed_version, self.version) + + if match and parsed_version is not None: + # If it's not a prerelease or prereleases are allowed, yield it directly + if not parsed_version.is_prerelease or include_prereleases: + found_non_prereleases = True + yield version + # Otherwise collect prereleases for potential later use + elif prereleases is None and self._prereleases is not False: + prereleases_versions.append(version) + + # If no non-prereleases were found and prereleases weren't + # explicitly forbidden, yield the collected prereleases + if ( + not found_non_prereleases + and prereleases is None + and self._prereleases is not False + ): + yield from prereleases_versions + + +_prefix_regex = re.compile(r"([0-9]+)((?:a|b|c|rc)[0-9]+)") + + +def _pep440_filter_prereleases( + iterable: Iterable[Any], key: Callable[[Any], UnparsedVersion] | None +) -> Iterator[Any]: + """Filter per PEP 440: exclude prereleases unless no finals exist.""" + # Two lists used: + # * all_nonfinal to preserve order if no finals exist + # * arbitrary_strings for streaming when first final found + all_nonfinal: list[Any] = [] + arbitrary_strings: list[Any] = [] + + found_final = False + for item in iterable: + parsed = _coerce_version(item if key is None else key(item)) + + if parsed is None: + # Arbitrary strings are always included as it is not + # possible to determine if they are prereleases, + # and they have already passed all specifiers. + if found_final: + yield item + else: + arbitrary_strings.append(item) + all_nonfinal.append(item) + continue + + if not parsed.is_prerelease: + # Final release found - flush arbitrary strings, then yield + if not found_final: + yield from arbitrary_strings + found_final = True + yield item + continue + + # Prerelease - buffer if no finals yet, otherwise skip + if not found_final: + all_nonfinal.append(item) + + # No finals found - yield all buffered items + if not found_final: + yield from all_nonfinal + + +def _version_split(version: str) -> list[str]: + """Split version into components. + + The split components are intended for version comparison. The logic does + not attempt to retain the original version string, so joining the + components back with :func:`_version_join` may not produce the original + version string. + """ + result: list[str] = [] + + epoch, _, rest = version.rpartition("!") + result.append(epoch or "0") + + for item in rest.split("."): + match = _prefix_regex.fullmatch(item) + if match: + result.extend(match.groups()) + else: + result.append(item) + return result + + +def _version_join(components: list[str]) -> str: + """Join split version components into a version string. + + This function assumes the input came from :func:`_version_split`, where the + first component must be the epoch (either empty or numeric), and all other + components numeric. + """ + epoch, *rest = components + return f"{epoch}!{'.'.join(rest)}" + + +def _is_not_suffix(segment: str) -> bool: + return not any( + segment.startswith(prefix) for prefix in ("dev", "a", "b", "rc", "post") + ) + + +def _numeric_prefix_len(split: list[str]) -> int: + """Count leading numeric components in a :func:`_version_split` result. + + >>> _numeric_prefix_len(["0", "1", "2", "a1"]) + 3 + """ + count = 0 + for segment in split: + if not segment.isdigit(): + break + count += 1 + return count + + +def _left_pad(split: list[str], target_numeric_len: int) -> list[str]: + """Pad a :func:`_version_split` result with ``"0"`` segments to reach + ``target_numeric_len`` numeric components. Suffix segments are preserved. + + >>> _left_pad(["0", "1", "a1"], 4) + ['0', '1', '0', '0', 'a1'] + """ + numeric_len = _numeric_prefix_len(split) + pad_needed = target_numeric_len - numeric_len + if pad_needed <= 0: + return split + return [*split[:numeric_len], *(["0"] * pad_needed), *split[numeric_len:]] + + +def _operator_cost(op_entry: tuple[CallableOperator, str, str]) -> int: + """Sort key for Cost Based Ordering of specifier operators in _filter_versions. + + Operators run sequentially on a shrinking candidate set, so operators that + reject the most versions should run first to minimize work for later ones. + + Tier 0: Exact equality (==, ===), likely to narrow candidates to one version + Tier 1: Range checks (>=, <=, >, <), cheap and usually reject a large portion + Tier 2: Wildcard equality (==.*) and compatible release (~=), more expensive + Tier 3: Exact !=, cheap but rarely rejects + Tier 4: Wildcard !=.*, expensive and rarely rejects + """ + _, ver, op = op_entry + if op == "==": + return 0 if not ver.endswith(".*") else 2 + if op in (">=", "<=", ">", "<"): + return 1 + if op == "~=": + return 2 + if op == "!=": + return 3 if not ver.endswith(".*") else 4 + if op == "===": + return 0 + + raise ValueError(f"Unknown operator: {op!r}") # pragma: no cover + + +class SpecifierSet(BaseSpecifier): + """This class abstracts handling of a set of version specifiers. + + It can be passed a single specifier (``>=3.0``), a comma-separated list of + specifiers (``>=3.0,!=3.1``), or no specifier at all. + + Instances are safe to serialize with :mod:`pickle`. They use a stable + format so the same pickle can be loaded in future packaging + releases. + + .. versionchanged:: 26.2 + + Added a stable pickle format. Pickles created with + packaging 26.2+ can be unpickled with future releases. + Backward compatibility with pickles from + packaging < 26.2 is supported but may be removed in a future + release. + """ + + __slots__ = ( + "_canonicalized", + "_has_arbitrary", + "_is_unsatisfiable", + "_prereleases", + "_resolved_ops", + "_specs", + ) + + def __init__( + self, + specifiers: str | Iterable[Specifier] = "", + prereleases: bool | None = None, + ) -> None: + """Initialize a SpecifierSet instance. + + :param specifiers: + The string representation of a specifier or a comma-separated list of + specifiers which will be parsed and normalized before use. + May also be an iterable of ``Specifier`` instances, which will be used + as is. + :param prereleases: + This tells the SpecifierSet if it should accept prerelease versions if + applicable or not. The default of ``None`` will autodetect it from the + given specifiers. + + :raises InvalidSpecifier: + If the given ``specifiers`` are not parseable than this exception will be + raised. + """ + + if isinstance(specifiers, str): + # Split on `,` to break each individual specifier into its own item, and + # strip each item to remove leading/trailing whitespace. + split_specifiers = [s.strip() for s in specifiers.split(",") if s.strip()] + + self._specs: tuple[Specifier, ...] = tuple(map(Specifier, split_specifiers)) + # Fast substring check; avoids iterating parsed specs. + self._has_arbitrary = "===" in specifiers + else: + self._specs = tuple(specifiers) + # Substring check works for both Specifier objects and plain + # strings (setuptools passes lists of strings). + self._has_arbitrary = any("===" in str(s) for s in self._specs) + + self._canonicalized = len(self._specs) <= 1 + self._resolved_ops: list[tuple[CallableOperator, str, str]] | None = None + + # Store our prereleases value so we can use it later to determine if + # we accept prereleases or not. + self._prereleases = prereleases + + self._is_unsatisfiable: bool | None = None + + def _canonical_specs(self) -> tuple[Specifier, ...]: + """Deduplicate, sort, and cache specs for order-sensitive operations.""" + if not self._canonicalized: + self._specs = tuple(dict.fromkeys(sorted(self._specs, key=str))) + self._canonicalized = True + self._resolved_ops = None + self._is_unsatisfiable = None + return self._specs + + @property + def prereleases(self) -> bool | None: + # If we have been given an explicit prerelease modifier, then we'll + # pass that through here. + if self._prereleases is not None: + return self._prereleases + + # If we don't have any specifiers, and we don't have a forced value, + # then we'll just return None since we don't know if this should have + # pre-releases or not. + if not self._specs: + return None + + # Otherwise we'll see if any of the given specifiers accept + # prereleases, if any of them do we'll return True, otherwise False. + if any(s.prereleases for s in self._specs): + return True + + return None + + @prereleases.setter + def prereleases(self, value: bool | None) -> None: + self._prereleases = value + self._is_unsatisfiable = None + + def __getstate__(self) -> tuple[tuple[Specifier, ...], bool | None]: + # Return state as a 2-item tuple for compactness: + # (specs, prereleases) + # Cache members are excluded and will be recomputed on demand. + return (self._specs, self._prereleases) + + def __setstate__(self, state: object) -> None: + # Always discard cached values - they will be recomputed on demand. + self._resolved_ops = None + self._is_unsatisfiable = None + + if isinstance(state, tuple): + if len(state) == 2: + # New format (26.2+): (specs, prereleases) + specs, prereleases = state + if ( + isinstance(specs, tuple) + and all(isinstance(s, Specifier) for s in specs) + and _validate_pre(prereleases) + ): + self._specs = specs + self._prereleases = prereleases + self._canonicalized = len(specs) <= 1 + self._has_arbitrary = any("===" in str(s) for s in specs) + return + if len(state) == 2 and isinstance(state[1], dict): + # Format (packaging 26.0-26.1): (None, {slot: value}). + _, slot_dict = state + specs = slot_dict.get("_specs", ()) + prereleases = slot_dict.get("_prereleases") + # Convert frozenset to tuple (26.0 stored as frozenset) + if isinstance(specs, frozenset): + specs = tuple(sorted(specs, key=str)) + if ( + isinstance(specs, tuple) + and all(isinstance(s, Specifier) for s in specs) + and _validate_pre(prereleases) + ): + self._specs = specs + self._prereleases = prereleases + self._canonicalized = len(self._specs) <= 1 + self._has_arbitrary = any("===" in str(s) for s in self._specs) + return + if isinstance(state, dict): + # Old format (packaging <= 25.x, no __slots__): state is a plain dict. + specs = state.get("_specs", ()) + prereleases = state.get("_prereleases") + # Convert frozenset to tuple (26.0 stored as frozenset) + if isinstance(specs, frozenset): + specs = tuple(sorted(specs, key=str)) + if ( + isinstance(specs, tuple) + and all(isinstance(s, Specifier) for s in specs) + and _validate_pre(prereleases) + ): + self._specs = specs + self._prereleases = prereleases + self._canonicalized = len(self._specs) <= 1 + self._has_arbitrary = any("===" in str(s) for s in self._specs) + return + + raise TypeError(f"Cannot restore SpecifierSet from {state!r}") + + def __repr__(self) -> str: + """A representation of the specifier set that shows all internal state. + + Note that the ordering of the individual specifiers within the set may not + match the input string. + + >>> SpecifierSet('>=1.0.0,!=2.0.0') + =1.0.0')> + >>> SpecifierSet('>=1.0.0,!=2.0.0', prereleases=False) + =1.0.0', prereleases=False)> + >>> SpecifierSet('>=1.0.0,!=2.0.0', prereleases=True) + =1.0.0', prereleases=True)> + """ + pre = ( + f", prereleases={self.prereleases!r}" + if self._prereleases is not None + else "" + ) + + return f"<{self.__class__.__name__}({str(self)!r}{pre})>" + + def __str__(self) -> str: + """A string representation of the specifier set that can be round-tripped. + + Note that the ordering of the individual specifiers within the set may not + match the input string. + + >>> str(SpecifierSet(">=1.0.0,!=1.0.1")) + '!=1.0.1,>=1.0.0' + >>> str(SpecifierSet(">=1.0.0,!=1.0.1", prereleases=False)) + '!=1.0.1,>=1.0.0' + """ + return ",".join(str(s) for s in self._canonical_specs()) + + def __hash__(self) -> int: + return hash(self._canonical_specs()) + + def __and__(self, other: SpecifierSet | str) -> SpecifierSet: + """Return a SpecifierSet which is a combination of the two sets. + + :param other: The other object to combine with. + + >>> SpecifierSet(">=1.0.0,!=1.0.1") & '<=2.0.0,!=2.0.1' + =1.0.0')> + >>> SpecifierSet(">=1.0.0,!=1.0.1") & SpecifierSet('<=2.0.0,!=2.0.1') + =1.0.0')> + """ + if isinstance(other, str): + other = SpecifierSet(other) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + specifier = SpecifierSet() + specifier._specs = self._specs + other._specs + specifier._canonicalized = len(specifier._specs) <= 1 + specifier._has_arbitrary = self._has_arbitrary or other._has_arbitrary + specifier._resolved_ops = None + + # Combine prerelease settings: use common or non-None value + if self._prereleases is None or self._prereleases == other._prereleases: + specifier._prereleases = other._prereleases + elif other._prereleases is None: + specifier._prereleases = self._prereleases + else: + raise ValueError( + "Cannot combine SpecifierSets with True and False prerelease overrides." + ) + + return specifier + + def __eq__(self, other: object) -> bool: + """Whether or not the two SpecifierSet-like objects are equal. + + :param other: The other object to check against. + + The value of :attr:`prereleases` is ignored. + + >>> SpecifierSet(">=1.0.0,!=1.0.1") == SpecifierSet(">=1.0.0,!=1.0.1") + True + >>> (SpecifierSet(">=1.0.0,!=1.0.1", prereleases=False) == + ... SpecifierSet(">=1.0.0,!=1.0.1", prereleases=True)) + True + >>> SpecifierSet(">=1.0.0,!=1.0.1") == ">=1.0.0,!=1.0.1" + True + >>> SpecifierSet(">=1.0.0,!=1.0.1") == SpecifierSet(">=1.0.0") + False + >>> SpecifierSet(">=1.0.0,!=1.0.1") == SpecifierSet(">=1.0.0,!=1.0.2") + False + """ + if isinstance(other, (str, Specifier)): + other = SpecifierSet(str(other)) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + return self._canonical_specs() == other._canonical_specs() + + def __len__(self) -> int: + """Returns the number of specifiers in this specifier set.""" + return len(self._specs) + + def __iter__(self) -> Iterator[Specifier]: + """ + Returns an iterator over all the underlying :class:`Specifier` instances + in this specifier set. + + >>> sorted(SpecifierSet(">=1.0.0,!=1.0.1"), key=str) + [, =1.0.0')>] + """ + return iter(self._specs) + + def _get_ranges(self) -> Sequence[_VersionRange]: + """Intersect all specifiers into a single list of version ranges. + + Returns an empty list when unsatisfiable. ``===`` specs are + modeled as full range; string matching is checked separately + by :meth:`_check_arbitrary_unsatisfiable`. + """ + specs = self._specs + + result: Sequence[_VersionRange] | None = None + for s in specs: + if result is None: + result = s._to_ranges() + else: + result = _intersect_ranges(result, s._to_ranges()) + if not result: + break + + if result is None: # pragma: no cover + raise RuntimeError("_get_ranges called with no specs") + return result + + def is_unsatisfiable(self) -> bool: + """Check whether this specifier set can never be satisfied. + + Returns True if no version can satisfy all specifiers simultaneously. + + >>> SpecifierSet(">=2.0,<1.0").is_unsatisfiable() + True + >>> SpecifierSet(">=1.0,<2.0").is_unsatisfiable() + False + >>> SpecifierSet("").is_unsatisfiable() + False + >>> SpecifierSet("==1.0,!=1.0").is_unsatisfiable() + True + """ + cached = self._is_unsatisfiable + if cached is not None: + return cached + + if not self._specs: + self._is_unsatisfiable = False + return False + + result = not self._get_ranges() + + if not result: + result = self._check_arbitrary_unsatisfiable() + + if not result and self.prereleases is False: + result = self._check_prerelease_only_ranges() + + self._is_unsatisfiable = result + return result + + def _check_prerelease_only_ranges(self) -> bool: + """With prereleases=False, check if every range contains only + pre-release versions (which would be excluded from matching).""" + for lower, upper in self._get_ranges(): + nearest = _nearest_non_prerelease(lower.version) + if nearest is None: + return False + if upper.version is None or nearest < upper.version: + return False + if nearest == upper.version and upper.inclusive: + return False + return True + + def _check_arbitrary_unsatisfiable(self) -> bool: + """Check === (arbitrary equality) specs for unsatisfiability. + + === uses case-insensitive string comparison, so the only candidate + that can match ``===V`` is the literal string V. This method + checks whether that candidate is excluded by other specifiers. + """ + arbitrary = [s for s in self._specs if s.operator == "==="] + if not arbitrary: + return False + + # Multiple === must agree on the same string (case-insensitive). + first = arbitrary[0].version.lower() + if any(s.version.lower() != first for s in arbitrary[1:]): + return True + + # The sole candidate is the === version string. Check whether + # it can satisfy every standard spec. + candidate = _coerce_version(arbitrary[0].version) + + # With prereleases=False, a prerelease candidate is excluded + # by contains() before the === string check even runs. + if ( + self.prereleases is False + and candidate is not None + and candidate.is_prerelease + ): + return True + + standard = [s for s in self._specs if s.operator != "==="] + if not standard: + return False + + if candidate is None: + # Unparsable string cannot satisfy any standard spec. + return True + + return not all(s.contains(candidate) for s in standard) + + def __contains__(self, item: UnparsedVersion) -> bool: + """Return whether or not the item is contained in this specifier. + + :param item: The item to check for. + + This is used for the ``in`` operator and behaves the same as + :meth:`contains` with no ``prereleases`` argument passed. + + >>> "1.2.3" in SpecifierSet(">=1.0.0,!=1.0.1") + True + >>> Version("1.2.3") in SpecifierSet(">=1.0.0,!=1.0.1") + True + >>> "1.0.1" in SpecifierSet(">=1.0.0,!=1.0.1") + False + >>> "1.3.0a1" in SpecifierSet(">=1.0.0,!=1.0.1") + True + >>> "1.3.0a1" in SpecifierSet(">=1.0.0,!=1.0.1", prereleases=True) + True + """ + return self.contains(item) + + def contains( + self, + item: UnparsedVersion, + prereleases: bool | None = None, + installed: bool | None = None, + ) -> bool: + """Return whether or not the item is contained in this SpecifierSet. + + :param item: + The item to check for, which can be a version string or a + :class:`Version` instance. + :param prereleases: + Whether or not to match prereleases with this SpecifierSet. If set to + ``None`` (the default), it will follow the recommendation from :pep:`440` + and match prereleases, as there are no other versions. + :param installed: + Whether or not the item is installed. If set to ``True``, it will + accept prerelease versions even if the specifier does not allow them. + + >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.2.3") + True + >>> SpecifierSet(">=1.0.0,!=1.0.1").contains(Version("1.2.3")) + True + >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.0.1") + False + >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.3.0a1") + True + >>> SpecifierSet(">=1.0.0,!=1.0.1", prereleases=False).contains("1.3.0a1") + False + >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.3.0a1", prereleases=True) + True + """ + version = _coerce_version(item) + + if version is not None and installed and version.is_prerelease: + prereleases = True + + # When item is a string and === is involved, keep it as-is + # so the comparison isn't done against the normalized form. + if version is None or (self._has_arbitrary and not isinstance(item, Version)): + check_item = item + else: + check_item = version + return bool(list(self.filter([check_item], prereleases=prereleases))) + + @typing.overload + def filter( + self, + iterable: Iterable[UnparsedVersionVar], + prereleases: bool | None = None, + key: None = ..., + ) -> Iterator[UnparsedVersionVar]: ... + + @typing.overload + def filter( + self, + iterable: Iterable[T], + prereleases: bool | None = None, + key: Callable[[T], UnparsedVersion] = ..., + ) -> Iterator[T]: ... + + def filter( + self, + iterable: Iterable[Any], + prereleases: bool | None = None, + key: Callable[[Any], UnparsedVersion] | None = None, + ) -> Iterator[Any]: + """Filter items in the given iterable, that match the specifiers in this set. + + :param iterable: + An iterable that can contain version strings and :class:`Version` instances. + The items in the iterable will be filtered according to the specifier. + :param prereleases: + Whether or not to allow prereleases in the returned iterator. If set to + ``None`` (the default), it will follow the recommendation from :pep:`440` + and match prereleases if there are no other versions. + :param key: + A callable that takes a single argument (an item from the iterable) and + returns a version string or :class:`Version` instance to be used for + filtering. + + >>> list(SpecifierSet(">=1.2.3").filter(["1.2", "1.3", "1.5a1"])) + ['1.3'] + >>> list(SpecifierSet(">=1.2.3").filter(["1.2", "1.3", Version("1.4")])) + ['1.3', ] + >>> list(SpecifierSet(">=1.2.3").filter(["1.2", "1.5a1"])) + ['1.5a1'] + >>> list(SpecifierSet(">=1.2.3").filter(["1.3", "1.5a1"], prereleases=True)) + ['1.3', '1.5a1'] + >>> list(SpecifierSet(">=1.2.3", prereleases=True).filter(["1.3", "1.5a1"])) + ['1.3', '1.5a1'] + >>> list(SpecifierSet(">=1.2.3").filter( + ... [{"ver": "1.2"}, {"ver": "1.3"}], + ... key=lambda x: x["ver"])) + [{'ver': '1.3'}] + + An "empty" SpecifierSet will filter items based on the presence of prerelease + versions in the set. + + >>> list(SpecifierSet("").filter(["1.3", "1.5a1"])) + ['1.3'] + >>> list(SpecifierSet("").filter(["1.5a1"])) + ['1.5a1'] + >>> list(SpecifierSet("", prereleases=True).filter(["1.3", "1.5a1"])) + ['1.3', '1.5a1'] + >>> list(SpecifierSet("").filter(["1.3", "1.5a1"], prereleases=True)) + ['1.3', '1.5a1'] + """ + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None and self.prereleases is not None: + prereleases = self.prereleases + + # Filter versions that match all specifiers using Cost Based Ordering. + if self._specs: + # When prereleases is None, we need to let all versions through + # the individual filters, then decide about prereleases at the end + # based on whether any non-prereleases matched ALL specs. + + # Fast path: single specifier, delegate directly. + if len(self._specs) == 1: + filtered = self._specs[0].filter( + iterable, + prereleases=True if prereleases is None else prereleases, + key=key, + ) + else: + filtered = self._filter_versions( + iterable, + key, + prereleases=True if prereleases is None else prereleases, + ) + + if prereleases is not None: + return filtered + + return _pep440_filter_prereleases(filtered, key) + + # Handle Empty SpecifierSet. + if prereleases is True: + return iter(iterable) + + if prereleases is False: + return ( + item + for item in iterable + if ( + (version := _coerce_version(item if key is None else key(item))) + is None + or not version.is_prerelease + ) + ) + + # PEP 440: exclude prereleases unless no final releases matched + return _pep440_filter_prereleases(iterable, key) + + def _filter_versions( + self, + iterable: Iterable[Any], + key: Callable[[Any], UnparsedVersion] | None, + prereleases: bool | None = None, + ) -> Iterator[Any]: + """Filter versions against all specifiers in a single pass. + + Uses Cost Based Ordering: specifiers are sorted by _operator_cost so + that cheap range operators reject versions early, avoiding expensive + wildcard or compatible operators on versions that would have been + rejected anyway. + """ + # Pre-resolve operators and sort (cached after first call). + if self._resolved_ops is None: + self._resolved_ops = sorted( + ( + (spec._get_operator(spec.operator), spec.version, spec.operator) + for spec in self._specs + ), + key=_operator_cost, + ) + ops = self._resolved_ops + exclude_prereleases = prereleases is False + + for item in iterable: + parsed = _coerce_version(item if key is None else key(item)) + + if parsed is None: + # Only === can match non-parseable versions. + if all( + op == "===" and str(item).lower() == ver.lower() + for _, ver, op in ops + ): + yield item + elif exclude_prereleases and parsed.is_prerelease: + pass + elif all( + str(item if key is None else key(item)).lower() == ver.lower() + if op == "===" + else op_fn(parsed, ver) + for op_fn, ver, op in ops + ): + # Short-circuits on the first failing operator. + yield item diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/tags.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/tags.py new file mode 100644 index 0000000..9980ab3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/tags.py @@ -0,0 +1,932 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import logging +import operator +import platform +import re +import struct +import subprocess +import sys +import sysconfig +from importlib.machinery import EXTENSION_SUFFIXES +from typing import ( + TYPE_CHECKING, + Iterable, + Iterator, + Sequence, + Tuple, + TypeVar, + cast, +) + +from . import _manylinux, _musllinux + +if TYPE_CHECKING: + from collections.abc import Callable, Iterable + from typing import AbstractSet + + +__all__ = [ + "INTERPRETER_SHORT_NAMES", + "AppleVersion", + "PythonVersion", + "Tag", + "UnsortedTagsError", + "android_platforms", + "compatible_tags", + "cpython_tags", + "create_compatible_tags_selector", + "generic_tags", + "interpreter_name", + "interpreter_version", + "ios_platforms", + "mac_platforms", + "parse_tag", + "platform_tags", + "sys_tags", +] + + +def __dir__() -> list[str]: + return __all__ + + +logger = logging.getLogger(__name__) + +PythonVersion = Sequence[int] +AppleVersion = Tuple[int, int] +_T = TypeVar("_T") + +INTERPRETER_SHORT_NAMES: dict[str, str] = { + "python": "py", # Generic. + "cpython": "cp", + "pypy": "pp", + "ironpython": "ip", + "jython": "jy", +} + + +# This function can be unit tested without reloading the module +# (Unlike _32_BIT_INTERPRETER) +def _compute_32_bit_interpreter() -> bool: + return struct.calcsize("P") == 4 + + +_32_BIT_INTERPRETER = _compute_32_bit_interpreter() + + +class UnsortedTagsError(ValueError): + """ + Raised when a tag component is not in sorted order per PEP 425. + """ + + +class Tag: + """ + A representation of the tag triple for a wheel. + + Instances are considered immutable and thus are hashable. Equality checking + is also supported. + + Instances are safe to serialize with :mod:`pickle`. They use a stable + format so the same pickle can be loaded in future packaging releases. + + .. versionchanged:: 26.2 + + Added a stable pickle format. Pickles created with packaging 26.2+ can + be unpickled with future releases. Backward compatibility with pickles + from packaging < 26.2 is supported but may be removed in a future + release. + """ + + __slots__ = ["_abi", "_hash", "_interpreter", "_platform"] + + def __init__(self, interpreter: str, abi: str, platform: str) -> None: + """ + :param str interpreter: The interpreter name, e.g. ``"py"`` + (see :attr:`INTERPRETER_SHORT_NAMES` for mapping + well-known interpreter names to their short names). + :param str abi: The ABI that a wheel supports, e.g. ``"cp37m"``. + :param str platform: The OS/platform the wheel supports, + e.g. ``"win_amd64"``. + """ + self._interpreter = interpreter.lower() + self._abi = abi.lower() + self._platform = platform.lower() + # The __hash__ of every single element in a Set[Tag] will be evaluated each time + # that a set calls its `.disjoint()` method, which may be called hundreds of + # times when scanning a page of links for packages with tags matching that + # Set[Tag]. Pre-computing the value here produces significant speedups for + # downstream consumers. + self._hash = hash((self._interpreter, self._abi, self._platform)) + + @property + def interpreter(self) -> str: + """ + The interpreter name, e.g. ``"py"`` (see + :attr:`INTERPRETER_SHORT_NAMES` for mapping well-known interpreter + names to their short names). + """ + return self._interpreter + + @property + def abi(self) -> str: + """ + The supported ABI. + """ + return self._abi + + @property + def platform(self) -> str: + """ + The OS/platform. + """ + return self._platform + + def __eq__(self, other: object) -> bool: + if not isinstance(other, Tag): + return NotImplemented + + return ( + (self._hash == other._hash) # Short-circuit ASAP for perf reasons. + and (self._platform == other._platform) + and (self._abi == other._abi) + and (self._interpreter == other._interpreter) + ) + + def __hash__(self) -> int: + return self._hash + + def __str__(self) -> str: + return f"{self._interpreter}-{self._abi}-{self._platform}" + + def __repr__(self) -> str: + return f"<{self} @ {id(self)}>" + + def __getstate__(self) -> tuple[str, str, str]: + # Return state as a 3-item tuple: (interpreter, abi, platform). + # Cache member _hash is excluded and will be recomputed. + return (self._interpreter, self._abi, self._platform) + + def __setstate__(self, state: object) -> None: + if isinstance(state, tuple): + if len(state) == 3 and all(isinstance(s, str) for s in state): + # New format (26.2+): (interpreter, abi, platform) + self._interpreter, self._abi, self._platform = state + self._hash = hash((self._interpreter, self._abi, self._platform)) + return + if len(state) == 2 and isinstance(state[1], dict): + # Old format (packaging <= 26.1, __slots__): (None, {slot: value}). + _, slots = state + try: + interpreter = slots["_interpreter"] + abi = slots["_abi"] + platform = slots["_platform"] + except KeyError: + raise TypeError(f"Cannot restore Tag from {state!r}") from None + if not all( + isinstance(value, str) for value in (interpreter, abi, platform) + ): + raise TypeError(f"Cannot restore Tag from {state!r}") + self._interpreter = interpreter.lower() + self._abi = abi.lower() + self._platform = platform.lower() + self._hash = hash((self._interpreter, self._abi, self._platform)) + return + raise TypeError(f"Cannot restore Tag from {state!r}") + + +def parse_tag(tag: str, *, validate_order: bool = False) -> frozenset[Tag]: + """ + Parses the provided tag (e.g. `py3-none-any`) into a frozenset of + :class:`Tag` instances. + + Returning a set is required due to the possibility that the tag is a + `compressed tag set`_, e.g. ``"py2.py3-none-any"`` which supports both + Python 2 and Python 3. + + If **validate_order** is true, compressed tag set components are checked + to be in sorted order as required by PEP 425. + + :param str tag: The tag to parse, e.g. ``"py3-none-any"``. + :param bool validate_order: Check whether compressed tag set components + are in sorted order. + :raises UnsortedTagsError: If **validate_order** is true and any compressed tag + set component is not in sorted order. + + .. versionadded:: 26.1 + The *validate_order* parameter. + """ + tags = set() + interpreters, abis, platforms = tag.split("-") + if validate_order: + for component in (interpreters, abis, platforms): + parts = component.split(".") + if parts != sorted(parts): + raise UnsortedTagsError( + f"Tag component {component!r} is not in sorted order per PEP 425" + ) + for interpreter in interpreters.split("."): + for abi in abis.split("."): + for platform_ in platforms.split("."): + tags.add(Tag(interpreter, abi, platform_)) + return frozenset(tags) + + +def _get_config_var(name: str, warn: bool = False) -> int | str | None: + value: int | str | None = sysconfig.get_config_var(name) + if value is None and warn: + logger.debug( + "Config variable '%s' is unset, Python ABI tag may be incorrect", name + ) + return value + + +def _normalize_string(string: str) -> str: + return string.replace(".", "_").replace("-", "_").replace(" ", "_") + + +def _is_threaded_cpython(abis: list[str]) -> bool: + """ + Determine if the ABI corresponds to a threaded (`--disable-gil`) build. + + The threaded builds are indicated by a "t" in the abiflags. + """ + if len(abis) == 0: + return False + # expect e.g., cp313 + m = re.match(r"cp\d+(.*)", abis[0]) + if not m: + return False + abiflags = m.group(1) + return "t" in abiflags + + +def _abi3_applies(python_version: PythonVersion, threading: bool) -> bool: + """ + Determine if the Python version supports abi3. + + PEP 384 was first implemented in Python 3.2. The free-threaded + builds do not support abi3. + """ + return len(python_version) > 1 and tuple(python_version) >= (3, 2) and not threading + + +def _abi3t_applies(python_version: PythonVersion, threading: bool) -> bool: + """ + Determine if the Python version supports abi3t. + + PEP 803 was first implemented in Python 3.15 but, per PEP 803, this + returns tags going back to Python 3.2 to mirror the abi3 + implementation and leave open the possibility of abi3t wheels + supporting older Python versions. + + """ + return len(python_version) > 1 and tuple(python_version) >= (3, 2) and threading + + +def _cpython_abis(py_version: PythonVersion, warn: bool = False) -> list[str]: + py_version = tuple(py_version) # To allow for version comparison. + abis = [] + version = _version_nodot(py_version[:2]) + threading = debug = pymalloc = ucs4 = "" + with_debug = _get_config_var("Py_DEBUG", warn) + has_refcount = hasattr(sys, "gettotalrefcount") + # Windows doesn't set Py_DEBUG, so checking for support of debug-compiled + # extension modules is the best option. + # https://github.com/pypa/pip/issues/3383#issuecomment-173267692 + has_ext = "_d.pyd" in EXTENSION_SUFFIXES + if with_debug or (with_debug is None and (has_refcount or has_ext)): + debug = "d" + if py_version >= (3, 13) and _get_config_var("Py_GIL_DISABLED", warn): + threading = "t" + if py_version < (3, 8): + with_pymalloc = _get_config_var("WITH_PYMALLOC", warn) + if with_pymalloc or with_pymalloc is None: + pymalloc = "m" + if py_version < (3, 3): + unicode_size = _get_config_var("Py_UNICODE_SIZE", warn) + if unicode_size == 4 or ( + unicode_size is None and sys.maxunicode == 0x10FFFF + ): + ucs4 = "u" + elif debug: + # Debug builds can also load "normal" extension modules. + # We can also assume no UCS-4 or pymalloc requirement. + abis.append(f"cp{version}{threading}") + abis.insert(0, f"cp{version}{threading}{debug}{pymalloc}{ucs4}") + return abis + + +def cpython_tags( + python_version: PythonVersion | None = None, + abis: Iterable[str] | None = None, + platforms: Iterable[str] | None = None, + *, + warn: bool = False, +) -> Iterator[Tag]: + """ + Yields the tags for the CPython interpreter. + + The specific tags generated are: + + - ``cp--`` + - ``cp--`` + - ``cp-none-`` + - ``cp--`` where "older version" is all older + minor versions down to Python 3.2 (when ``abi3`` was introduced) + + If ``python_version`` only provides a major-only version then only + user-provided ABIs via ``abis`` and the ``none`` ABI will be used. + + The ``stable_abi`` will be either ``abi3`` or ``abi3t`` if `abi` is a + GIL-enabled ABI like `"cp315"` or a free-threaded ABI like `"cp315t"`, + respectively. + + :param Sequence python_version: A one- or two-item sequence representing the + targeted Python version. Defaults to + ``sys.version_info[:2]``. + :param Iterable abis: Iterable of compatible ABIs. Defaults to the ABIs + compatible with the current system. + :param Iterable platforms: Iterable of compatible platforms. Defaults to the + platforms compatible with the current system. + :param bool warn: Whether warnings should be logged. Defaults to ``False``. + """ + if not python_version: + python_version = sys.version_info[:2] + + interpreter = f"cp{_version_nodot(python_version[:2])}" + + if abis is None: + abis = _cpython_abis(python_version, warn) if len(python_version) > 1 else [] + abis = list(abis) + # 'abi3' and 'none' are explicitly handled later. + for explicit_abi in ("abi3", "none"): + try: + abis.remove(explicit_abi) + except ValueError: # noqa: PERF203 + pass + + platforms = list(platforms or platform_tags()) + for abi in abis: + for platform_ in platforms: + yield Tag(interpreter, abi, platform_) + + threading = _is_threaded_cpython(abis) + use_abi3 = _abi3_applies(python_version, threading) + use_abi3t = _abi3t_applies(python_version, threading) + + if use_abi3: + yield from (Tag(interpreter, "abi3", platform_) for platform_ in platforms) + if use_abi3t: + yield from (Tag(interpreter, "abi3t", platform_) for platform_ in platforms) + + yield from (Tag(interpreter, "none", platform_) for platform_ in platforms) + + if use_abi3 or use_abi3t: + for minor_version in range(python_version[1] - 1, 1, -1): + for platform_ in platforms: + version = _version_nodot((python_version[0], minor_version)) + interpreter = f"cp{version}" + if use_abi3: + yield Tag(interpreter, "abi3", platform_) + if use_abi3t: + # Support for abi3t was introduced in Python 3.15, but in + # principle abi3t wheels are possible for older limited API + # versions, so allow things like ("cp37", "abi3t", "platform") + yield Tag(interpreter, "abi3t", platform_) + + +def _generic_abi() -> list[str]: + """ + Return the ABI tag based on EXT_SUFFIX. + """ + # The following are examples of `EXT_SUFFIX`. + # We want to keep the parts which are related to the ABI and remove the + # parts which are related to the platform: + # - linux: '.cpython-310-x86_64-linux-gnu.so' => cp310 + # - mac: '.cpython-310-darwin.so' => cp310 + # - win: '.cp310-win_amd64.pyd' => cp310 + # - win: '.pyd' => cp37 (uses _cpython_abis()) + # - pypy: '.pypy38-pp73-x86_64-linux-gnu.so' => pypy38_pp73 + # - graalpy: '.graalpy-38-native-x86_64-darwin.dylib' + # => graalpy_38_native + + ext_suffix = _get_config_var("EXT_SUFFIX", warn=True) + if not isinstance(ext_suffix, str) or ext_suffix[0] != ".": + raise SystemError("invalid sysconfig.get_config_var('EXT_SUFFIX')") + parts = ext_suffix.split(".") + if len(parts) < 3: + # CPython3.7 and earlier uses ".pyd" on Windows. + return _cpython_abis(sys.version_info[:2]) + soabi = parts[1] + if soabi.startswith("cpython"): + # non-windows + abi = "cp" + soabi.split("-")[1] + elif soabi.startswith("cp"): + # windows + abi = soabi.split("-")[0] + elif soabi.startswith("pypy"): + abi = "-".join(soabi.split("-")[:2]) + elif soabi.startswith("graalpy"): + abi = "-".join(soabi.split("-")[:3]) + elif soabi: + # pyston, ironpython, others? + abi = soabi + else: + return [] + return [_normalize_string(abi)] + + +def generic_tags( + interpreter: str | None = None, + abis: Iterable[str] | None = None, + platforms: Iterable[str] | None = None, + *, + warn: bool = False, +) -> Iterator[Tag]: + """ + Yields the tags for an interpreter which requires no specialization. + + This function should be used if one of the other interpreter-specific + functions provided by this module is not appropriate (i.e. not calculating + tags for a CPython interpreter). + + The specific tags generated are: + + - ``--`` + + The ``"none"`` ABI will be added if it was not explicitly provided. + + :param str interpreter: The name of the interpreter. Defaults to being + calculated. + :param Iterable abis: Iterable of compatible ABIs. Defaults to the ABIs + compatible with the current system. + :param Iterable platforms: Iterable of compatible platforms. Defaults to the + platforms compatible with the current system. + :param bool warn: Whether warnings should be logged. Defaults to ``False``. + """ + if not interpreter: + interp_name = interpreter_name() + interp_version = interpreter_version(warn=warn) + interpreter = f"{interp_name}{interp_version}" + abis = _generic_abi() if abis is None else list(abis) + platforms = list(platforms or platform_tags()) + if "none" not in abis: + abis.append("none") + for abi in abis: + for platform_ in platforms: + yield Tag(interpreter, abi, platform_) + + +def _py_interpreter_range(py_version: PythonVersion) -> Iterator[str]: + """ + Yields Python versions in descending order. + + After the latest version, the major-only version will be yielded, and then + all previous versions of that major version. + """ + if len(py_version) > 1: + yield f"py{_version_nodot(py_version[:2])}" + yield f"py{py_version[0]}" + if len(py_version) > 1: + for minor in range(py_version[1] - 1, -1, -1): + yield f"py{_version_nodot((py_version[0], minor))}" + + +def compatible_tags( + python_version: PythonVersion | None = None, + interpreter: str | None = None, + platforms: Iterable[str] | None = None, +) -> Iterator[Tag]: + """ + Yields the tags for an interpreter compatible with the Python version + specified by ``python_version``. + + The specific tags generated are: + + - ``py*-none-`` + - ``-none-any`` if ``interpreter`` is provided + - ``py*-none-any`` + + :param Sequence python_version: A one- or two-item sequence representing the + compatible version of Python. Defaults to + ``sys.version_info[:2]``. + :param str interpreter: The name of the interpreter (if known), e.g. + ``"cp38"``. Defaults to the current interpreter. + :param Iterable platforms: Iterable of compatible platforms. Defaults to the + platforms compatible with the current system. + """ + if not python_version: + python_version = sys.version_info[:2] + platforms = list(platforms or platform_tags()) + for version in _py_interpreter_range(python_version): + for platform_ in platforms: + yield Tag(version, "none", platform_) + if interpreter: + yield Tag(interpreter, "none", "any") + for version in _py_interpreter_range(python_version): + yield Tag(version, "none", "any") + + +def _mac_arch(arch: str, is_32bit: bool = _32_BIT_INTERPRETER) -> str: + if not is_32bit: + return arch + + if arch.startswith("ppc"): + return "ppc" + + return "i386" + + +def _mac_binary_formats(version: AppleVersion, cpu_arch: str) -> list[str]: + formats = [cpu_arch] + if cpu_arch == "x86_64": + if version < (10, 4): + return [] + formats.extend(["intel", "fat64", "fat32"]) + + elif cpu_arch == "i386": + if version < (10, 4): + return [] + formats.extend(["intel", "fat32", "fat"]) + + elif cpu_arch == "ppc64": + # TODO: Need to care about 32-bit PPC for ppc64 through 10.2? + if version > (10, 5) or version < (10, 4): + return [] + formats.append("fat64") + + elif cpu_arch == "ppc": + if version > (10, 6): + return [] + formats.extend(["fat32", "fat"]) + + if cpu_arch in {"arm64", "x86_64"}: + formats.append("universal2") + + if cpu_arch in {"x86_64", "i386", "ppc64", "ppc", "intel"}: + formats.append("universal") + + return formats + + +def mac_platforms( + version: AppleVersion | None = None, arch: str | None = None +) -> Iterator[str]: + """ + Yields the :attr:`~Tag.platform` tags for macOS. + + The `version` parameter is a two-item tuple specifying the macOS version to + generate platform tags for. The `arch` parameter is the CPU architecture to + generate platform tags for. Both parameters default to the appropriate value + for the current system. + + :param tuple version: A two-item tuple representing the version of macOS. + Defaults to the current system's version. + :param str arch: The CPU architecture. Defaults to the architecture of the + current system, e.g. ``"x86_64"``. + + .. note:: + Equivalent support for the other major platforms is purposefully not + provided: + + - On Windows, platform compatibility is statically specified + - On Linux, code must be run on the system itself to determine + compatibility + """ + version_str, _, cpu_arch = platform.mac_ver() + if version is None: + version = cast("AppleVersion", tuple(map(int, version_str.split(".")[:2]))) + if version == (10, 16): + # When built against an older macOS SDK, Python will report macOS 10.16 + # instead of the real version. + version_str = subprocess.run( + [ + sys.executable, + "-sS", + "-c", + "import platform; print(platform.mac_ver()[0])", + ], + check=True, + env={"SYSTEM_VERSION_COMPAT": "0"}, + stdout=subprocess.PIPE, + text=True, + ).stdout + version = cast("AppleVersion", tuple(map(int, version_str.split(".")[:2]))) + + if arch is None: + arch = _mac_arch(cpu_arch) + + if (10, 0) <= version < (11, 0): + # Prior to Mac OS 11, each yearly release of Mac OS bumped the + # "minor" version number. The major version was always 10. + major_version = 10 + for minor_version in range(version[1], -1, -1): + compat_version = major_version, minor_version + binary_formats = _mac_binary_formats(compat_version, arch) + for binary_format in binary_formats: + yield f"macosx_{major_version}_{minor_version}_{binary_format}" + + if version >= (11, 0): + # Starting with Mac OS 11, each yearly release bumps the major version + # number. The minor versions are now the midyear updates. + minor_version = 0 + for major_version in range(version[0], 10, -1): + compat_version = major_version, minor_version + binary_formats = _mac_binary_formats(compat_version, arch) + for binary_format in binary_formats: + yield f"macosx_{major_version}_{minor_version}_{binary_format}" + + if version >= (11, 0): + # Mac OS 11 on x86_64 is compatible with binaries from previous releases. + # Arm64 support was introduced in 11.0, so no Arm binaries from previous + # releases exist. + # + # However, the "universal2" binary format can have a + # macOS version earlier than 11.0 when the x86_64 part of the binary supports + # that version of macOS. + major_version = 10 + if arch == "x86_64": + for minor_version in range(16, 3, -1): + compat_version = major_version, minor_version + binary_formats = _mac_binary_formats(compat_version, arch) + for binary_format in binary_formats: + yield f"macosx_{major_version}_{minor_version}_{binary_format}" + else: + for minor_version in range(16, 3, -1): + compat_version = major_version, minor_version + binary_format = "universal2" + yield f"macosx_{major_version}_{minor_version}_{binary_format}" + + +def ios_platforms( + version: AppleVersion | None = None, multiarch: str | None = None +) -> Iterator[str]: + """ + + Yields the :attr:`~Tag.platform` tags for iOS. + + :param tuple version: A two-item tuple representing the version of iOS. + Defaults to the current system's version. + :param str multiarch: The CPU architecture+ABI to be used. This should be in + the format by ``sys.implementation._multiarch`` (e.g., + ``arm64_iphoneos`` or ``x86_64_iphonesimulator``). + Defaults to the current system's multiarch value. + + .. note:: + Behavior of this method is undefined if invoked on non-iOS platforms + without providing explicit version and multiarch arguments. + """ + if version is None: + # if iOS is the current platform, ios_ver *must* be defined. However, + # it won't exist for CPython versions before 3.13, which causes a mypy + # error. + _, release, _, _ = platform.ios_ver() # type: ignore[attr-defined, unused-ignore] + version = cast("AppleVersion", tuple(map(int, release.split(".")[:2]))) + + if multiarch is None: + multiarch = sys.implementation._multiarch + multiarch = multiarch.replace("-", "_") + + ios_platform_template = "ios_{major}_{minor}_{multiarch}" + + # Consider any iOS major.minor version from the version requested, down to + # 12.0. 12.0 is the first iOS version that is known to have enough features + # to support CPython. Consider every possible minor release up to X.9. There + # highest the minor has ever gone is 8 (14.8 and 15.8) but having some extra + # candidates that won't ever match doesn't really hurt, and it saves us from + # having to keep an explicit list of known iOS versions in the code. Return + # the results descending order of version number. + + # If the requested major version is less than 12, there won't be any matches. + if version[0] < 12: + return + + # Consider the actual X.Y version that was requested. + yield ios_platform_template.format( + major=version[0], minor=version[1], multiarch=multiarch + ) + + # Consider every minor version from X.0 to the minor version prior to the + # version requested by the platform. + for minor in range(version[1] - 1, -1, -1): + yield ios_platform_template.format( + major=version[0], minor=minor, multiarch=multiarch + ) + + for major in range(version[0] - 1, 11, -1): + for minor in range(9, -1, -1): + yield ios_platform_template.format( + major=major, minor=minor, multiarch=multiarch + ) + + +def android_platforms( + api_level: int | None = None, abi: str | None = None +) -> Iterator[str]: + """ + Yields the :attr:`~Tag.platform` tags for Android. If this function is invoked on + non-Android platforms, the ``api_level`` and ``abi`` arguments are required. + + :param int api_level: The maximum `API level + `__ to return. Defaults + to the current system's version, as returned by ``platform.android_ver``. + :param str abi: The `Android ABI `__, + e.g. ``arm64_v8a``. Defaults to the current system's ABI , as returned by + ``sysconfig.get_platform``. Hyphens and periods will be replaced with + underscores. + """ + if platform.system() != "Android" and (api_level is None or abi is None): + raise TypeError( + "on non-Android platforms, the api_level and abi arguments are required" + ) + + if api_level is None: + # Python 3.13 was the first version to return platform.system() == "Android", + # and also the first version to define platform.android_ver(). + api_level = platform.android_ver().api_level # type: ignore[attr-defined] + + if abi is None: + abi = sysconfig.get_platform().split("-")[-1] + abi = _normalize_string(abi) + + # 16 is the minimum API level known to have enough features to support CPython + # without major patching. Yield every API level from the maximum down to the + # minimum, inclusive. + min_api_level = 16 + for ver in range(api_level, min_api_level - 1, -1): + yield f"android_{ver}_{abi}" + + +def _linux_platforms(is_32bit: bool = _32_BIT_INTERPRETER) -> Iterator[str]: + linux = _normalize_string(sysconfig.get_platform()) + if not linux.startswith("linux_"): + # we should never be here, just yield the sysconfig one and return + yield linux + return + if is_32bit: + if linux == "linux_x86_64": + linux = "linux_i686" + elif linux == "linux_aarch64": + linux = "linux_armv8l" + _, arch = linux.split("_", 1) + archs = {"armv8l": ["armv8l", "armv7l"]}.get(arch, [arch]) + yield from _manylinux.platform_tags(archs) + yield from _musllinux.platform_tags(archs) + for arch in archs: + yield f"linux_{arch}" + + +def _emscripten_platforms() -> Iterator[str]: + pyemscripten_platform_version = sysconfig.get_config_var( + "PYEMSCRIPTEN_PLATFORM_VERSION" + ) + if pyemscripten_platform_version: + yield f"pyemscripten_{pyemscripten_platform_version}_wasm32" + yield from _generic_platforms() + + +def _generic_platforms() -> Iterator[str]: + yield _normalize_string(sysconfig.get_platform()) + + +def platform_tags() -> Iterator[str]: + """ + Yields the :attr:`~Tag.platform` tags for the running interpreter. + """ + if platform.system() == "Darwin": + return mac_platforms() + elif platform.system() == "iOS": + return ios_platforms() + elif platform.system() == "Android": + return android_platforms() + elif platform.system() == "Linux": + return _linux_platforms() + elif platform.system() == "Emscripten": + return _emscripten_platforms() + else: + return _generic_platforms() + + +def interpreter_name() -> str: + """ + Returns the name of the running interpreter. + + Some implementations have a reserved, two-letter abbreviation which will + be returned when appropriate. + + This typically acts as the prefix to the :attr:`~Tag.interpreter` tag. + """ + name = sys.implementation.name + return INTERPRETER_SHORT_NAMES.get(name) or name + + +def interpreter_version(*, warn: bool = False) -> str: + """ + Returns the running interpreter's version. + + This typically acts as the suffix to the :attr:`~Tag.interpreter` tag. + + :param bool warn: Whether warnings should be logged. Defaults to ``False``. + """ + version = _get_config_var("py_version_nodot", warn=warn) + return str(version) if version else _version_nodot(sys.version_info[:2]) + + +def _version_nodot(version: PythonVersion) -> str: + return "".join(map(str, version)) + + +def sys_tags(*, warn: bool = False) -> Iterator[Tag]: + """ + Yields the sequence of tag triples that the running interpreter supports. + + The iterable is ordered so that the best-matching tag is first in the + sequence. The exact preferential order to tags is interpreter-specific, but + in general the tag importance is in the order of: + + 1. Interpreter + 2. Platform + 3. ABI + + This order is due to the fact that an ABI is inherently tied to the + platform, but platform-specific code is not necessarily tied to the ABI. The + interpreter is the most important tag as it dictates basic support for any + wheel. + + The function returns an iterable in order to allow for the possible + short-circuiting of tag generation if the entire sequence is not necessary + and tag calculation happens to be expensive. + + :param bool warn: Whether warnings should be logged. Defaults to ``False``. + + .. versionchanged:: 21.3 + Added the `pp3-none-any` tag (:issue:`311`). + .. versionchanged:: 27.0 + Added the `abi3t` tag (:issue:`1099`). + """ + + interp_name = interpreter_name() + if interp_name == "cp": + yield from cpython_tags(warn=warn) + else: + yield from generic_tags() + + if interp_name == "pp": + interp = "pp3" + elif interp_name == "cp": + interp = "cp" + interpreter_version(warn=warn) + else: + interp = None + yield from compatible_tags(interpreter=interp) + + +def create_compatible_tags_selector( + tags: Iterable[Tag], +) -> Callable[[Iterable[tuple[_T, AbstractSet[Tag]]]], Iterator[_T]]: + """Create a callable to select things compatible with supported tags. + + This function accepts an ordered sequence of tags, with the preferred + tags first. + + The returned callable accepts an iterable of tuples (thing, set[Tag]), + and returns an iterator of things, with the things with the best + matching tags first. + + Example to select compatible wheel filenames: + + >>> from packaging import tags + >>> from packaging.utils import parse_wheel_filename + >>> selector = tags.create_compatible_tags_selector(tags.sys_tags()) + >>> filenames = ["foo-1.0-py3-none-any.whl", "foo-1.0-py2-none-any.whl"] + >>> list(selector([ + ... (filename, parse_wheel_filename(filename)[-1]) for filename in filenames + ... ])) + ['foo-1.0-py3-none-any.whl'] + + .. versionadded:: 26.1 + """ + tag_ranks: dict[Tag, int] = {} + for rank, tag in enumerate(tags): + tag_ranks.setdefault(tag, rank) # ignore duplicate tags, keep first + supported_tags = tag_ranks.keys() + + def selector( + tagged_things: Iterable[tuple[_T, AbstractSet[Tag]]], + ) -> Iterator[_T]: + ranked_things: list[tuple[_T, int]] = [] + for thing, thing_tags in tagged_things: + supported_thing_tags = thing_tags & supported_tags + if supported_thing_tags: + thing_rank = min(tag_ranks[t] for t in supported_thing_tags) + ranked_things.append((thing, thing_rank)) + return iter( + thing for thing, _ in sorted(ranked_things, key=operator.itemgetter(1)) + ) + + return selector diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/utils.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/utils.py new file mode 100644 index 0000000..cbd3be2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/utils.py @@ -0,0 +1,296 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import re +from typing import NewType, Tuple, Union, cast + +from .tags import Tag, UnsortedTagsError, parse_tag +from .version import InvalidVersion, Version, _TrimmedRelease + +__all__ = [ + "BuildTag", + "InvalidName", + "InvalidSdistFilename", + "InvalidWheelFilename", + "NormalizedName", + "canonicalize_name", + "canonicalize_version", + "is_normalized_name", + "parse_sdist_filename", + "parse_wheel_filename", +] + + +def __dir__() -> list[str]: + return __all__ + + +BuildTag = Union[Tuple[()], Tuple[int, str]] + +NormalizedName = NewType("NormalizedName", str) +""" +A :class:`typing.NewType` of :class:`str`, representing a normalized name. +""" + + +class InvalidName(ValueError): + """ + An invalid distribution name; users should refer to the packaging user guide. + """ + + +class InvalidWheelFilename(ValueError): + """ + An invalid wheel filename was found, users should refer to PEP 427. + """ + + +class InvalidSdistFilename(ValueError): + """ + An invalid sdist filename was found, users should refer to the packaging user guide. + """ + + +# Core metadata spec for `Name` +_validate_regex = re.compile( + r"[a-z0-9]|[a-z0-9][a-z0-9._-]*[a-z0-9]", re.IGNORECASE | re.ASCII +) +_normalized_regex = re.compile(r"[a-z0-9]|[a-z0-9]([a-z0-9-](?!--))*[a-z0-9]", re.ASCII) +# PEP 427: The build number must start with a digit. +_build_tag_regex = re.compile(r"(\d+)(.*)", re.ASCII) + + +def canonicalize_name(name: str, *, validate: bool = False) -> NormalizedName: + """ + This function takes a valid Python package or extra name, and returns the + normalized form of it. + + The return type is typed as :class:`NormalizedName`. This allows type + checkers to help require that a string has passed through this function + before use. + + If **validate** is true, then the function will check if **name** is a valid + distribution name before normalizing. + + :param str name: The name to normalize. + :param bool validate: Check whether the name is a valid distribution name. + :raises InvalidName: If **validate** is true and the name is not an + acceptable distribution name. + + >>> from packaging.utils import canonicalize_name + >>> canonicalize_name("Django") + 'django' + >>> canonicalize_name("oslo.concurrency") + 'oslo-concurrency' + >>> canonicalize_name("requests") + 'requests' + """ + if validate and not _validate_regex.fullmatch(name): + raise InvalidName(f"name is invalid: {name!r}") + # Ensure all ``.`` and ``_`` are ``-`` + # Emulates ``re.sub(r"[-_.]+", "-", name).lower()`` from PEP 503 + # Much faster than re, and even faster than str.translate + value = name.lower().replace("_", "-").replace(".", "-") + # Condense repeats (faster than regex) + while "--" in value: + value = value.replace("--", "-") + return cast("NormalizedName", value) + + +def is_normalized_name(name: str) -> bool: + """ + Check if a name is already normalized (i.e. :func:`canonicalize_name` would + roundtrip to the same value). + + :param str name: The name to check. + + >>> from packaging.utils import is_normalized_name + >>> is_normalized_name("requests") + True + >>> is_normalized_name("Django") + False + """ + return _normalized_regex.fullmatch(name) is not None + + +def canonicalize_version( + version: Version | str, *, strip_trailing_zero: bool = True +) -> str: + """Return a canonical form of a version as a string. + + This function takes a string representing a package version (or a + :class:`~packaging.version.Version` instance), and returns the + normalized form of it. By default, it strips trailing zeros from + the release segment. + + >>> from packaging.utils import canonicalize_version + >>> canonicalize_version('1.0.1') + '1.0.1' + + Per PEP 625, versions may have multiple canonical forms, differing + only by trailing zeros. + + >>> canonicalize_version('1.0.0') + '1' + >>> canonicalize_version('1.0.0', strip_trailing_zero=False) + '1.0.0' + + Invalid versions are returned unaltered. + + >>> canonicalize_version('foo bar baz') + 'foo bar baz' + + >>> canonicalize_version('1.4.0.0.0') + '1.4' + """ + if isinstance(version, str): + try: + version = Version(version) + except InvalidVersion: + return str(version) + return str(_TrimmedRelease(version) if strip_trailing_zero else version) + + +def parse_wheel_filename( + filename: str, + *, + validate_order: bool = False, +) -> tuple[NormalizedName, Version, BuildTag, frozenset[Tag]]: + """ + This function takes the filename of a wheel file, and parses it, + returning a tuple of name, version, build number, and tags. + + The name part of the tuple is normalized and typed as + :class:`NormalizedName`. The version portion is an instance of + :class:`~packaging.version.Version`. The build number is ``()`` if + there is no build number in the wheel filename, otherwise a + two-item tuple of an integer for the leading digits and + a string for the rest of the build number. The tags portion is a + frozen set of :class:`~packaging.tags.Tag` instances (as the tag + string format allows multiple tags to be combined into a single + string). + + If **validate_order** is true, compressed tag set components are + checked to be in sorted order as required by PEP 425. + + :param str filename: The name of the wheel file. + :param bool validate_order: Check whether compressed tag set components + are in sorted order. + :raises InvalidWheelFilename: If the filename in question + does not follow the :ref:`wheel specification + `. + + >>> from packaging.utils import parse_wheel_filename + >>> from packaging.tags import Tag + >>> from packaging.version import Version + >>> name, ver, build, tags = parse_wheel_filename("foo-1.0-py3-none-any.whl") + >>> name + 'foo' + >>> ver == Version('1.0') + True + >>> tags == {Tag("py3", "none", "any")} + True + >>> not build + True + + .. versionadded:: 26.1 + The *validate_order* parameter. + """ + if not filename.endswith(".whl"): + raise InvalidWheelFilename( + f"Invalid wheel filename (extension must be '.whl'): {filename!r}" + ) + + filename = filename[:-4] + dashes = filename.count("-") + if dashes not in (4, 5): + raise InvalidWheelFilename( + f"Invalid wheel filename (wrong number of parts): {filename!r}" + ) + + parts = filename.split("-", dashes - 2) + name_part = parts[0] + # See PEP 427 for the rules on escaping the project name. + if "__" in name_part or re.match(r"^[\w\d._]*$", name_part, re.UNICODE) is None: + raise InvalidWheelFilename(f"Invalid project name: {filename!r}") + name = canonicalize_name(name_part) + + try: + version = Version(parts[1]) + except InvalidVersion as e: + raise InvalidWheelFilename( + f"Invalid wheel filename (invalid version): {filename!r}" + ) from e + + if dashes == 5: + build_part = parts[2] + build_match = _build_tag_regex.match(build_part) + if build_match is None: + raise InvalidWheelFilename( + f"Invalid build number: {build_part} in {filename!r}" + ) + build = cast("BuildTag", (int(build_match.group(1)), build_match.group(2))) + else: + build = () + tag_str = parts[-1] + try: + tags = parse_tag(tag_str, validate_order=validate_order) + except UnsortedTagsError: + raise InvalidWheelFilename( + f"Invalid wheel filename (compressed tag set components must be in " + f"sorted order per PEP 425): {filename!r}" + ) from None + return (name, version, build, tags) + + +def parse_sdist_filename(filename: str) -> tuple[NormalizedName, Version]: + """ + This function takes the filename of a sdist file (as specified + in the `Source distribution format`_ documentation), and parses + it, returning a tuple of the normalized name and version as + represented by an instance of :class:`~packaging.version.Version`. + + :param str filename: The name of the sdist file. + :raises InvalidSdistFilename: If the filename does not end + with an sdist extension (``.zip`` or ``.tar.gz``), or if it does not + contain a dash separating the name and the version of the distribution. + + >>> from packaging.utils import parse_sdist_filename + >>> from packaging.version import Version + >>> name, ver = parse_sdist_filename("foo-1.0.tar.gz") + >>> name + 'foo' + >>> ver == Version('1.0') + True + + .. _Source distribution format: https://packaging.python.org/specifications/source-distribution-format/#source-distribution-file-name + """ + if filename.endswith(".tar.gz"): + file_stem = filename[: -len(".tar.gz")] + elif filename.endswith(".zip"): + file_stem = filename[: -len(".zip")] + else: + raise InvalidSdistFilename( + f"Invalid sdist filename (extension must be '.tar.gz' or '.zip'):" + f" {filename!r}" + ) + + # We are requiring a PEP 440 version, which cannot contain dashes, + # so we split on the last dash. + name_part, sep, version_part = file_stem.rpartition("-") + if not sep: + raise InvalidSdistFilename(f"Invalid sdist filename: {filename!r}") + + name = canonicalize_name(name_part) + + try: + version = Version(version_part) + except InvalidVersion as e: + raise InvalidSdistFilename( + f"Invalid sdist filename (invalid version): {filename!r}" + ) from e + + return (name, version) diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/version.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/version.py new file mode 100644 index 0000000..97f23fd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/packaging/version.py @@ -0,0 +1,1231 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +""" +.. testsetup:: + + from packaging.version import parse, normalize_pre, Version, _cmpkey +""" + +from __future__ import annotations + +import re +import sys +import typing +from typing import ( + Any, + Callable, + Literal, + NamedTuple, + SupportsInt, + Tuple, + TypedDict, + Union, +) + +if typing.TYPE_CHECKING: + from typing_extensions import Self, Unpack + +if sys.version_info >= (3, 13): # pragma: no cover + from warnings import deprecated as _deprecated +elif typing.TYPE_CHECKING: + from typing_extensions import deprecated as _deprecated +else: # pragma: no cover + import functools + import warnings + + def _deprecated(message: str) -> object: + def decorator(func: Callable[[...], object]) -> object: + @functools.wraps(func) + def wrapper(*args: object, **kwargs: object) -> object: + warnings.warn( + message, + category=DeprecationWarning, + stacklevel=2, + ) + return func(*args, **kwargs) + + return wrapper + + return decorator + + +_LETTER_NORMALIZATION = { + "alpha": "a", + "beta": "b", + "c": "rc", + "pre": "rc", + "preview": "rc", + "rev": "post", + "r": "post", +} + +__all__ = ["VERSION_PATTERN", "InvalidVersion", "Version", "normalize_pre", "parse"] + + +def __dir__() -> list[str]: + return __all__ + + +LocalType = Tuple[Union[int, str], ...] + +CmpLocalType = Tuple[Tuple[int, str], ...] +CmpSuffix = Tuple[int, int, int, int, int, int] +CmpKey = Union[ + Tuple[int, Tuple[int, ...], CmpSuffix], + Tuple[int, Tuple[int, ...], CmpSuffix, CmpLocalType], +] +VersionComparisonMethod = Callable[[CmpKey, CmpKey], bool] + + +class _VersionReplace(TypedDict, total=False): + epoch: int | None + release: tuple[int, ...] | None + pre: tuple[str, int] | None + post: int | None + dev: int | None + local: str | None + + +def normalize_pre(letter: str, /) -> str: + """Normalize the pre-release segment of a version string. + + Returns a lowercase version of the string if not a known pre-release + identifier. + + >>> normalize_pre('alpha') + 'a' + >>> normalize_pre('BETA') + 'b' + >>> normalize_pre('rc') + 'rc' + + :param letter: + + .. versionadded:: 26.1 + """ + letter = letter.lower() + return _LETTER_NORMALIZATION.get(letter, letter) + + +def parse(version: str) -> Version: + """Parse the given version string. + + This is identical to the :class:`Version` constructor. + + >>> parse('1.0.dev1') + + + :param version: The version string to parse. + :raises InvalidVersion: When the version string is not a valid version. + """ + return Version(version) + + +class InvalidVersion(ValueError): + """Raised when a version string is not a valid version. + + >>> Version("invalid") + Traceback (most recent call last): + ... + packaging.version.InvalidVersion: Invalid version: 'invalid' + """ + + +class _BaseVersion: + __slots__ = () + + # This can also be a normal member (see the packaging_legacy package); + # we are just requiring it to be readable. Actually defining a property + # has runtime effect on subclasses, so it's typing only. + if typing.TYPE_CHECKING: + + @property + def _key(self) -> tuple[Any, ...]: ... + + def __hash__(self) -> int: + return hash(self._key) + + # Please keep the duplicated `isinstance` check + # in the six comparisons hereunder + # unless you find a way to avoid adding overhead function calls. + def __lt__(self, other: _BaseVersion) -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key < other._key + + def __le__(self, other: _BaseVersion) -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key <= other._key + + def __eq__(self, other: object) -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key == other._key + + def __ge__(self, other: _BaseVersion) -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key >= other._key + + def __gt__(self, other: _BaseVersion) -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key > other._key + + def __ne__(self, other: object) -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key != other._key + + +# Deliberately not anchored to the start and end of the string, to make it +# easier for 3rd party code to reuse + +# Note that ++ doesn't behave identically on CPython and PyPy, so not using it here +_VERSION_PATTERN = r""" + v?+ # optional leading v + (?a: + (?:(?P[0-9]+)!)?+ # epoch + (?P[0-9]+(?:\.[0-9]+)*+) # release segment + (?P
                                              # pre-release
    +            [._-]?+
    +            (?Palpha|a|beta|b|preview|pre|c|rc)
    +            [._-]?+
    +            (?P[0-9]+)?
    +        )?+
    +        (?P                                         # post release
    +            (?:-(?P[0-9]+))
    +            |
    +            (?:
    +                [._-]?
    +                (?Ppost|rev|r)
    +                [._-]?
    +                (?P[0-9]+)?
    +            )
    +        )?+
    +        (?P                                          # dev release
    +            [._-]?+
    +            (?Pdev)
    +            [._-]?+
    +            (?P[0-9]+)?
    +        )?+
    +    )
    +    (?a:\+
    +        (?P                                        # local version
    +            [a-z0-9]+
    +            (?:[._-][a-z0-9]+)*+
    +        )
    +    )?+
    +"""
    +
    +_VERSION_PATTERN_OLD = _VERSION_PATTERN.replace("*+", "*").replace("?+", "?")
    +
    +# Possessive qualifiers were added in Python 3.11.
    +# CPython 3.11.0-3.11.4 had a bug: https://github.com/python/cpython/pull/107795
    +# Older PyPy also had a bug.
    +VERSION_PATTERN = (
    +    _VERSION_PATTERN_OLD
    +    if (sys.implementation.name == "cpython" and sys.version_info < (3, 11, 5))
    +    or (sys.implementation.name == "pypy" and sys.version_info < (3, 11, 13))
    +    or sys.version_info < (3, 11)
    +    else _VERSION_PATTERN
    +)
    +"""
    +A string containing the regular expression used to match a valid version.
    +
    +The pattern is not anchored at either end, and is intended for embedding in larger
    +expressions (for example, matching a version number as part of a file name). The
    +regular expression should be compiled with the ``re.VERBOSE`` and ``re.IGNORECASE``
    +flags set.
    +
    +.. versionchanged:: 26.0
    +
    +   The regex now uses possessive qualifiers on Python 3.11 if they are
    +   supported (CPython 3.11.5+, PyPy 3.11.13+).
    +
    +:meta hide-value:
    +"""
    +
    +
    +# Validation pattern for local version in replace()
    +_LOCAL_PATTERN = re.compile(r"[a-z0-9]+(?:[._-][a-z0-9]+)*", re.IGNORECASE | re.ASCII)
    +
    +# Fast path: If a version has only digits and dots then we
    +# can skip the regex and parse it as a release segment
    +_SIMPLE_VERSION_INDICATORS = frozenset(".0123456789")
    +
    +
    +def _validate_epoch(value: object, /) -> int:
    +    epoch = value or 0
    +    if isinstance(epoch, int) and epoch >= 0:
    +        return epoch
    +    msg = f"epoch must be non-negative integer, got {epoch}"
    +    raise InvalidVersion(msg)
    +
    +
    +def _validate_release(value: object, /) -> tuple[int, ...]:
    +    release = (0,) if value is None else value
    +    if (
    +        isinstance(release, tuple)
    +        and len(release) > 0
    +        and all(isinstance(i, int) and i >= 0 for i in release)
    +    ):
    +        return release
    +    msg = f"release must be a non-empty tuple of non-negative integers, got {release}"
    +    raise InvalidVersion(msg)
    +
    +
    +def _validate_pre(value: object, /) -> tuple[Literal["a", "b", "rc"], int] | None:
    +    if value is None:
    +        return value
    +    if isinstance(value, tuple) and len(value) == 2:
    +        letter, number = value
    +        letter = normalize_pre(letter)
    +        if letter in {"a", "b", "rc"} and isinstance(number, int) and number >= 0:
    +            # type checkers can't infer the Literal type here on letter
    +            return (letter, number)  # type: ignore[return-value]
    +    msg = f"pre must be a tuple of ('a'|'b'|'rc', non-negative int), got {value}"
    +    raise InvalidVersion(msg)
    +
    +
    +def _validate_post(value: object, /) -> tuple[Literal["post"], int] | None:
    +    if value is None:
    +        return value
    +    if isinstance(value, int) and value >= 0:
    +        return ("post", value)
    +    msg = f"post must be non-negative integer, got {value}"
    +    raise InvalidVersion(msg)
    +
    +
    +def _validate_dev(value: object, /) -> tuple[Literal["dev"], int] | None:
    +    if value is None:
    +        return value
    +    if isinstance(value, int) and value >= 0:
    +        return ("dev", value)
    +    msg = f"dev must be non-negative integer, got {value}"
    +    raise InvalidVersion(msg)
    +
    +
    +def _validate_local(value: object, /) -> LocalType | None:
    +    if value is None:
    +        return value
    +    if isinstance(value, str) and _LOCAL_PATTERN.fullmatch(value):
    +        return _parse_local_version(value)
    +    msg = f"local must be a valid version string, got {value!r}"
    +    raise InvalidVersion(msg)
    +
    +
    +# Backward compatibility for internals before 26.0. Do not use.
    +class _Version(NamedTuple):
    +    epoch: int
    +    release: tuple[int, ...]
    +    dev: tuple[Literal["dev"], int] | None
    +    pre: tuple[Literal["a", "b", "rc"], int] | None
    +    post: tuple[Literal["post"], int] | None
    +    local: LocalType | None
    +
    +
    +class Version(_BaseVersion):
    +    """This class abstracts handling of a project's versions.
    +
    +    A :class:`Version` instance is comparison aware and can be compared and
    +    sorted using the standard Python interfaces.
    +
    +    >>> v1 = Version("1.0a5")
    +    >>> v2 = Version("1.0")
    +    >>> v1
    +    
    +    >>> v2
    +    
    +    >>> v1 < v2
    +    True
    +    >>> v1 == v2
    +    False
    +    >>> v1 > v2
    +    False
    +    >>> v1 >= v2
    +    False
    +    >>> v1 <= v2
    +    True
    +
    +    :class:`Version` is immutable; use :meth:`__replace__` to change
    +    part of a version.
    +
    +    Instances are safe to serialize with :mod:`pickle`. They use a stable
    +    format so the same pickle can be loaded in future packaging releases.
    +
    +    .. versionchanged:: 26.2
    +
    +        Added a stable pickle format. Pickles created with packaging 26.2+ can
    +        be unpickled with future releases.  Backward compatibility with pickles
    +        from packaging < 26.2 is supported but may be removed in a future
    +        release.
    +    """
    +
    +    __slots__ = (
    +        "_dev",
    +        "_epoch",
    +        "_hash_cache",
    +        "_key_cache",
    +        "_local",
    +        "_post",
    +        "_pre",
    +        "_release",
    +    )
    +    __match_args__ = ("_str",)
    +    """
    +    Pattern matching is supported on Python 3.10+.
    +
    +    .. versionadded:: 26.0
    +
    +    :meta hide-value:
    +    """
    +
    +    _regex = re.compile(r"\s*" + VERSION_PATTERN + r"\s*", re.VERBOSE | re.IGNORECASE)
    +
    +    _epoch: int
    +    _release: tuple[int, ...]
    +    _dev: tuple[Literal["dev"], int] | None
    +    _pre: tuple[Literal["a", "b", "rc"], int] | None
    +    _post: tuple[Literal["post"], int] | None
    +    _local: LocalType | None
    +
    +    _hash_cache: int | None
    +    _key_cache: CmpKey | None
    +
    +    def __init__(self, version: str) -> None:
    +        """Initialize a Version object.
    +
    +        :param version:
    +            The string representation of a version which will be parsed and normalized
    +            before use.
    +        :raises InvalidVersion:
    +            If the ``version`` does not conform to PEP 440 in any way then this
    +            exception will be raised.
    +        """
    +        if _SIMPLE_VERSION_INDICATORS.issuperset(version):
    +            try:
    +                self._release = tuple(map(int, version.split(".")))
    +            except ValueError:
    +                # Empty parts (from "1..2", ".1", etc.) are invalid versions.
    +                # Any other ValueError (e.g. int str-digits limit) should
    +                # propagate to the caller.
    +                if "" in version.split("."):
    +                    raise InvalidVersion(f"Invalid version: {version!r}") from None
    +                # TODO: remove "no cover" when Python 3.9 is dropped.
    +                raise  # pragma: no cover
    +
    +            self._epoch = 0
    +            self._pre = None
    +            self._post = None
    +            self._dev = None
    +            self._local = None
    +            self._key_cache = None
    +            self._hash_cache = None
    +            return
    +
    +        # Validate the version and parse it into pieces
    +        match = self._regex.fullmatch(version)
    +        if not match:
    +            raise InvalidVersion(f"Invalid version: {version!r}")
    +        self._epoch = int(match.group("epoch")) if match.group("epoch") else 0
    +        self._release = tuple(map(int, match.group("release").split(".")))
    +        # We can type ignore the assignments below because the regex guarantees
    +        # the correct strings
    +        self._pre = _parse_letter_version(match.group("pre_l"), match.group("pre_n"))  # type: ignore[assignment]
    +        self._post = _parse_letter_version(  # type: ignore[assignment]
    +            match.group("post_l"), match.group("post_n1") or match.group("post_n2")
    +        )
    +        self._dev = _parse_letter_version(match.group("dev_l"), match.group("dev_n"))  # type: ignore[assignment]
    +        self._local = _parse_local_version(match.group("local"))
    +
    +        # Key which will be used for sorting
    +        self._key_cache = None
    +        self._hash_cache = None
    +
    +    @classmethod
    +    def from_parts(
    +        cls,
    +        *,
    +        epoch: int = 0,
    +        release: tuple[int, ...],
    +        pre: tuple[str, int] | None = None,
    +        post: int | None = None,
    +        dev: int | None = None,
    +        local: str | None = None,
    +    ) -> Self:
    +        """
    +        Return a new version composed of the various parts.
    +
    +        This allows you to build a version without going though a string and
    +        running a regular expression. It normalizes pre-release strings. The
    +        ``release=`` keyword argument is required.
    +
    +        >>> Version.from_parts(release=(1,2,3))
    +        
    +        >>> Version.from_parts(release=(0,1,0), pre=("b", 1))
    +        
    +
    +        :param epoch:
    +        :param release: This version tuple is required
    +
    +        .. versionadded:: 26.1
    +        """
    +        _epoch = _validate_epoch(epoch)
    +        _release = _validate_release(release)
    +        _pre = _validate_pre(pre) if pre is not None else None
    +        _post = _validate_post(post) if post is not None else None
    +        _dev = _validate_dev(dev) if dev is not None else None
    +        _local = _validate_local(local) if local is not None else None
    +
    +        new_version = cls.__new__(cls)
    +        new_version._key_cache = None
    +        new_version._hash_cache = None
    +        new_version._epoch = _epoch
    +        new_version._release = _release
    +        new_version._pre = _pre
    +        new_version._post = _post
    +        new_version._dev = _dev
    +        new_version._local = _local
    +
    +        return new_version
    +
    +    def __replace__(self, **kwargs: Unpack[_VersionReplace]) -> Self:
    +        """
    +        __replace__(*, epoch=..., release=..., pre=..., post=..., dev=..., local=...)
    +
    +        Return a new version with parts replaced.
    +
    +        This returns a new version (unless no parts were changed). The
    +        pre-release is normalized. Setting a value to ``None`` clears it.
    +
    +        >>> v = Version("1.2.3")
    +        >>> v.__replace__(pre=("a", 1))
    +        
    +
    +        :param int | None epoch:
    +        :param tuple[int, ...] | None release:
    +        :param tuple[str, int] | None pre:
    +        :param int | None post:
    +        :param int | None dev:
    +        :param str | None local:
    +
    +        .. versionadded:: 26.0
    +        .. versionchanged:: 26.1
    +
    +           The pre-release portion is now normalized.
    +        """
    +        epoch = _validate_epoch(kwargs["epoch"]) if "epoch" in kwargs else self._epoch
    +        release = (
    +            _validate_release(kwargs["release"])
    +            if "release" in kwargs
    +            else self._release
    +        )
    +        pre = _validate_pre(kwargs["pre"]) if "pre" in kwargs else self._pre
    +        post = _validate_post(kwargs["post"]) if "post" in kwargs else self._post
    +        dev = _validate_dev(kwargs["dev"]) if "dev" in kwargs else self._dev
    +        local = _validate_local(kwargs["local"]) if "local" in kwargs else self._local
    +
    +        if (
    +            epoch == self._epoch
    +            and release == self._release
    +            and pre == self._pre
    +            and post == self._post
    +            and dev == self._dev
    +            and local == self._local
    +        ):
    +            return self
    +
    +        new_version = self.__class__.__new__(self.__class__)
    +        new_version._key_cache = None
    +        new_version._hash_cache = None
    +        new_version._epoch = epoch
    +        new_version._release = release
    +        new_version._pre = pre
    +        new_version._post = post
    +        new_version._dev = dev
    +        new_version._local = local
    +
    +        return new_version
    +
    +    @property
    +    def _key(self) -> CmpKey:
    +        if self._key_cache is None:
    +            self._key_cache = _cmpkey(
    +                self._epoch,
    +                self._release,
    +                self._pre,
    +                self._post,
    +                self._dev,
    +                self._local,
    +            )
    +        return self._key_cache
    +
    +    # __hash__ must be defined when __eq__ is overridden,
    +    # otherwise Python sets __hash__ to None.
    +    def __hash__(self) -> int:
    +        if (cached_hash := self._hash_cache) is not None:
    +            return cached_hash
    +
    +        if (key := self._key_cache) is None:
    +            self._key_cache = key = _cmpkey(
    +                self._epoch,
    +                self._release,
    +                self._pre,
    +                self._post,
    +                self._dev,
    +                self._local,
    +            )
    +        self._hash_cache = cached_hash = hash(key)
    +        return cached_hash
    +
    +    # Override comparison methods to use direct _key_cache access
    +    # This is faster than property access, especially before Python 3.12
    +    def __lt__(self, other: _BaseVersion) -> bool:
    +        if isinstance(other, Version):
    +            if self._key_cache is None:
    +                self._key_cache = _cmpkey(
    +                    self._epoch,
    +                    self._release,
    +                    self._pre,
    +                    self._post,
    +                    self._dev,
    +                    self._local,
    +                )
    +            if other._key_cache is None:
    +                other._key_cache = _cmpkey(
    +                    other._epoch,
    +                    other._release,
    +                    other._pre,
    +                    other._post,
    +                    other._dev,
    +                    other._local,
    +                )
    +            return self._key_cache < other._key_cache
    +
    +        if not isinstance(other, _BaseVersion):
    +            return NotImplemented
    +
    +        return super().__lt__(other)
    +
    +    def __le__(self, other: _BaseVersion) -> bool:
    +        if isinstance(other, Version):
    +            if self._key_cache is None:
    +                self._key_cache = _cmpkey(
    +                    self._epoch,
    +                    self._release,
    +                    self._pre,
    +                    self._post,
    +                    self._dev,
    +                    self._local,
    +                )
    +            if other._key_cache is None:
    +                other._key_cache = _cmpkey(
    +                    other._epoch,
    +                    other._release,
    +                    other._pre,
    +                    other._post,
    +                    other._dev,
    +                    other._local,
    +                )
    +            return self._key_cache <= other._key_cache
    +
    +        if not isinstance(other, _BaseVersion):
    +            return NotImplemented
    +
    +        return super().__le__(other)
    +
    +    def __eq__(self, other: object) -> bool:
    +        if isinstance(other, Version):
    +            if self._key_cache is None:
    +                self._key_cache = _cmpkey(
    +                    self._epoch,
    +                    self._release,
    +                    self._pre,
    +                    self._post,
    +                    self._dev,
    +                    self._local,
    +                )
    +            if other._key_cache is None:
    +                other._key_cache = _cmpkey(
    +                    other._epoch,
    +                    other._release,
    +                    other._pre,
    +                    other._post,
    +                    other._dev,
    +                    other._local,
    +                )
    +            return self._key_cache == other._key_cache
    +
    +        if not isinstance(other, _BaseVersion):
    +            return NotImplemented
    +
    +        return super().__eq__(other)
    +
    +    def __ge__(self, other: _BaseVersion) -> bool:
    +        if isinstance(other, Version):
    +            if self._key_cache is None:
    +                self._key_cache = _cmpkey(
    +                    self._epoch,
    +                    self._release,
    +                    self._pre,
    +                    self._post,
    +                    self._dev,
    +                    self._local,
    +                )
    +            if other._key_cache is None:
    +                other._key_cache = _cmpkey(
    +                    other._epoch,
    +                    other._release,
    +                    other._pre,
    +                    other._post,
    +                    other._dev,
    +                    other._local,
    +                )
    +            return self._key_cache >= other._key_cache
    +
    +        if not isinstance(other, _BaseVersion):
    +            return NotImplemented
    +
    +        return super().__ge__(other)
    +
    +    def __gt__(self, other: _BaseVersion) -> bool:
    +        if isinstance(other, Version):
    +            if self._key_cache is None:
    +                self._key_cache = _cmpkey(
    +                    self._epoch,
    +                    self._release,
    +                    self._pre,
    +                    self._post,
    +                    self._dev,
    +                    self._local,
    +                )
    +            if other._key_cache is None:
    +                other._key_cache = _cmpkey(
    +                    other._epoch,
    +                    other._release,
    +                    other._pre,
    +                    other._post,
    +                    other._dev,
    +                    other._local,
    +                )
    +            return self._key_cache > other._key_cache
    +
    +        if not isinstance(other, _BaseVersion):
    +            return NotImplemented
    +
    +        return super().__gt__(other)
    +
    +    def __ne__(self, other: object) -> bool:
    +        if isinstance(other, Version):
    +            if self._key_cache is None:
    +                self._key_cache = _cmpkey(
    +                    self._epoch,
    +                    self._release,
    +                    self._pre,
    +                    self._post,
    +                    self._dev,
    +                    self._local,
    +                )
    +            if other._key_cache is None:
    +                other._key_cache = _cmpkey(
    +                    other._epoch,
    +                    other._release,
    +                    other._pre,
    +                    other._post,
    +                    other._dev,
    +                    other._local,
    +                )
    +            return self._key_cache != other._key_cache
    +
    +        if not isinstance(other, _BaseVersion):
    +            return NotImplemented
    +
    +        return super().__ne__(other)
    +
    +    def __getstate__(
    +        self,
    +    ) -> tuple[
    +        int,
    +        tuple[int, ...],
    +        tuple[str, int] | None,
    +        tuple[str, int] | None,
    +        tuple[str, int] | None,
    +        LocalType | None,
    +    ]:
    +        # Return state as a 6-item tuple for compactness:
    +        #   (epoch, release, pre, post, dev, local)
    +        # Cache members are excluded and will be recomputed on demand
    +        return (
    +            self._epoch,
    +            self._release,
    +            self._pre,
    +            self._post,
    +            self._dev,
    +            self._local,
    +        )
    +
    +    def __setstate__(self, state: object) -> None:
    +        # Always discard cached values — they may contain stale references
    +        # (e.g. packaging._structures.InfinityType from pre-26.1 pickles)
    +        # and will be recomputed on demand from the core fields above.
    +        self._key_cache = None
    +        self._hash_cache = None
    +
    +        if isinstance(state, tuple):
    +            if len(state) == 6:
    +                # New format (26.2+): (epoch, release, pre, post, dev, local)
    +                (
    +                    self._epoch,
    +                    self._release,
    +                    self._pre,
    +                    self._post,
    +                    self._dev,
    +                    self._local,
    +                ) = state
    +                return
    +            if len(state) == 2:
    +                # Format (packaging 26.0-26.1): (None, {slot: value}).
    +                _, slot_dict = state
    +                if isinstance(slot_dict, dict):
    +                    self._epoch = slot_dict["_epoch"]
    +                    self._release = slot_dict["_release"]
    +                    self._pre = slot_dict.get("_pre")
    +                    self._post = slot_dict.get("_post")
    +                    self._dev = slot_dict.get("_dev")
    +                    self._local = slot_dict.get("_local")
    +                    return
    +        if isinstance(state, dict):
    +            # Old format (packaging <= 25.x, no __slots__): state is a plain
    +            # dict with "_version" (_Version NamedTuple) and "_key" entries.
    +            version_nt = state.get("_version")
    +            if version_nt is not None:
    +                self._epoch = version_nt.epoch
    +                self._release = version_nt.release
    +                self._pre = version_nt.pre
    +                self._post = version_nt.post
    +                self._dev = version_nt.dev
    +                self._local = version_nt.local
    +                return
    +
    +        raise TypeError(f"Cannot restore Version from {state!r}")
    +
    +    @property
    +    @_deprecated("Version._version is private and will be removed soon")
    +    def _version(self) -> _Version:
    +        return _Version(
    +            self._epoch, self._release, self._dev, self._pre, self._post, self._local
    +        )
    +
    +    @_version.setter
    +    @_deprecated("Version._version is private and will be removed soon")
    +    def _version(self, value: _Version) -> None:
    +        self._epoch = value.epoch
    +        self._release = value.release
    +        self._dev = value.dev
    +        self._pre = value.pre
    +        self._post = value.post
    +        self._local = value.local
    +        self._key_cache = None
    +        self._hash_cache = None
    +
    +    def __repr__(self) -> str:
    +        """A representation of the Version that shows all internal state.
    +
    +        >>> Version('1.0.0')
    +        
    +        """
    +        return f"<{self.__class__.__name__}({str(self)!r})>"
    +
    +    def __str__(self) -> str:
    +        """A string representation of the version that can be round-tripped.
    +
    +        >>> str(Version("1.0a5"))
    +        '1.0a5'
    +        """
    +        # This is a hot function, so not calling self.base_version
    +        version = ".".join(map(str, self.release))
    +
    +        # Epoch
    +        if self.epoch:
    +            version = f"{self.epoch}!{version}"
    +
    +        # Pre-release
    +        if self.pre is not None:
    +            version += "".join(map(str, self.pre))
    +
    +        # Post-release
    +        if self.post is not None:
    +            version += f".post{self.post}"
    +
    +        # Development release
    +        if self.dev is not None:
    +            version += f".dev{self.dev}"
    +
    +        # Local version segment
    +        if self.local is not None:
    +            version += f"+{self.local}"
    +
    +        return version
    +
    +    @property
    +    def _str(self) -> str:
    +        """Internal property for match_args"""
    +        return str(self)
    +
    +    @property
    +    def epoch(self) -> int:
    +        """The epoch of the version.
    +
    +        >>> Version("2.0.0").epoch
    +        0
    +        >>> Version("1!2.0.0").epoch
    +        1
    +        """
    +        return self._epoch
    +
    +    @property
    +    def release(self) -> tuple[int, ...]:
    +        """The components of the "release" segment of the version.
    +
    +        >>> Version("1.2.3").release
    +        (1, 2, 3)
    +        >>> Version("2.0.0").release
    +        (2, 0, 0)
    +        >>> Version("1!2.0.0.post0").release
    +        (2, 0, 0)
    +
    +        Includes trailing zeroes but not the epoch or any pre-release / development /
    +        post-release suffixes.
    +        """
    +        return self._release
    +
    +    @property
    +    def pre(self) -> tuple[Literal["a", "b", "rc"], int] | None:
    +        """The pre-release segment of the version.
    +
    +        >>> print(Version("1.2.3").pre)
    +        None
    +        >>> Version("1.2.3a1").pre
    +        ('a', 1)
    +        >>> Version("1.2.3b1").pre
    +        ('b', 1)
    +        >>> Version("1.2.3rc1").pre
    +        ('rc', 1)
    +        """
    +        return self._pre
    +
    +    @property
    +    def post(self) -> int | None:
    +        """The post-release number of the version.
    +
    +        >>> print(Version("1.2.3").post)
    +        None
    +        >>> Version("1.2.3.post1").post
    +        1
    +        """
    +        return self._post[1] if self._post else None
    +
    +    @property
    +    def dev(self) -> int | None:
    +        """The development number of the version.
    +
    +        >>> print(Version("1.2.3").dev)
    +        None
    +        >>> Version("1.2.3.dev1").dev
    +        1
    +        """
    +        return self._dev[1] if self._dev else None
    +
    +    @property
    +    def local(self) -> str | None:
    +        """The local version segment of the version.
    +
    +        >>> print(Version("1.2.3").local)
    +        None
    +        >>> Version("1.2.3+abc").local
    +        'abc'
    +        """
    +        if self._local:
    +            return ".".join(str(x) for x in self._local)
    +        else:
    +            return None
    +
    +    @property
    +    def public(self) -> str:
    +        """The public portion of the version.
    +
    +        This returns a string. If you want a :class:`Version` again and care
    +        about performance, use ``v.__replace__(local=None)`` instead.
    +
    +        >>> Version("1.2.3").public
    +        '1.2.3'
    +        >>> Version("1.2.3+abc").public
    +        '1.2.3'
    +        >>> Version("1!1.2.3dev1+abc").public
    +        '1!1.2.3.dev1'
    +        """
    +        return str(self).split("+", 1)[0]
    +
    +    @property
    +    def base_version(self) -> str:
    +        """The "base version" of the version.
    +
    +        This returns a string. If you want a :class:`Version` again and care
    +        about performance, use
    +        ``v.__replace__(pre=None, post=None, dev=None, local=None)`` instead.
    +
    +        >>> Version("1.2.3").base_version
    +        '1.2.3'
    +        >>> Version("1.2.3+abc").base_version
    +        '1.2.3'
    +        >>> Version("1!1.2.3dev1+abc").base_version
    +        '1!1.2.3'
    +
    +        The "base version" is the public version of the project without any pre or post
    +        release markers.
    +        """
    +        release_segment = ".".join(map(str, self.release))
    +        return f"{self.epoch}!{release_segment}" if self.epoch else release_segment
    +
    +    @property
    +    def is_prerelease(self) -> bool:
    +        """Whether this version is a pre-release.
    +
    +        >>> Version("1.2.3").is_prerelease
    +        False
    +        >>> Version("1.2.3a1").is_prerelease
    +        True
    +        >>> Version("1.2.3b1").is_prerelease
    +        True
    +        >>> Version("1.2.3rc1").is_prerelease
    +        True
    +        >>> Version("1.2.3dev1").is_prerelease
    +        True
    +        """
    +        return self.dev is not None or self.pre is not None
    +
    +    @property
    +    def is_postrelease(self) -> bool:
    +        """Whether this version is a post-release.
    +
    +        >>> Version("1.2.3").is_postrelease
    +        False
    +        >>> Version("1.2.3.post1").is_postrelease
    +        True
    +        """
    +        return self.post is not None
    +
    +    @property
    +    def is_devrelease(self) -> bool:
    +        """Whether this version is a development release.
    +
    +        >>> Version("1.2.3").is_devrelease
    +        False
    +        >>> Version("1.2.3.dev1").is_devrelease
    +        True
    +        """
    +        return self.dev is not None
    +
    +    @property
    +    def major(self) -> int:
    +        """The first item of :attr:`release` or ``0`` if unavailable.
    +
    +        >>> Version("1.2.3").major
    +        1
    +        """
    +        return self.release[0] if len(self.release) >= 1 else 0
    +
    +    @property
    +    def minor(self) -> int:
    +        """The second item of :attr:`release` or ``0`` if unavailable.
    +
    +        >>> Version("1.2.3").minor
    +        2
    +        >>> Version("1").minor
    +        0
    +        """
    +        return self.release[1] if len(self.release) >= 2 else 0
    +
    +    @property
    +    def micro(self) -> int:
    +        """The third item of :attr:`release` or ``0`` if unavailable.
    +
    +        >>> Version("1.2.3").micro
    +        3
    +        >>> Version("1").micro
    +        0
    +        """
    +        return self.release[2] if len(self.release) >= 3 else 0
    +
    +
    +class _TrimmedRelease(Version):
    +    __slots__ = ()
    +
    +    def __init__(self, version: str | Version) -> None:
    +        if isinstance(version, Version):
    +            self._epoch = version._epoch
    +            self._release = version._release
    +            self._dev = version._dev
    +            self._pre = version._pre
    +            self._post = version._post
    +            self._local = version._local
    +            self._key_cache = version._key_cache
    +            return
    +        super().__init__(version)  # pragma: no cover
    +
    +    @property
    +    def release(self) -> tuple[int, ...]:
    +        """
    +        Release segment without any trailing zeros.
    +
    +        >>> _TrimmedRelease('1.0.0').release
    +        (1,)
    +        >>> _TrimmedRelease('0.0').release
    +        (0,)
    +        """
    +        # This leaves one 0.
    +        rel = super().release
    +        len_release = len(rel)
    +        i = len_release
    +        while i > 1 and rel[i - 1] == 0:
    +            i -= 1
    +        return rel if i == len_release else rel[:i]
    +
    +
    +def _parse_letter_version(
    +    letter: str | None, number: str | bytes | SupportsInt | None
    +) -> tuple[str, int] | None:
    +    if letter:
    +        # We normalize any letters to their lower case form
    +        letter = letter.lower()
    +
    +        # We consider some words to be alternate spellings of other words and
    +        # in those cases we want to normalize the spellings to our preferred
    +        # spelling.
    +        letter = _LETTER_NORMALIZATION.get(letter, letter)
    +
    +        # We consider there to be an implicit 0 in a pre-release if there is
    +        # not a numeral associated with it.
    +        return letter, int(number or 0)
    +
    +    if number:
    +        # We assume if we are given a number, but we are not given a letter
    +        # then this is using the implicit post release syntax (e.g. 1.0-1)
    +        return "post", int(number)
    +
    +    return None
    +
    +
    +_local_version_separators = re.compile(r"[\._-]")
    +
    +
    +def _parse_local_version(local: str | None) -> LocalType | None:
    +    """
    +    Takes a string like ``"abc.1.twelve"`` and turns it into
    +    ``("abc", 1, "twelve")``.
    +    """
    +    if local is not None:
    +        return tuple(
    +            part.lower() if not part.isdigit() else int(part)
    +            for part in _local_version_separators.split(local)
    +        )
    +    return None
    +
    +
    +# Sort ranks for pre-release: dev-only < a < b < rc < stable (no pre-release).
    +_PRE_RANK = {"a": 0, "b": 1, "rc": 2}
    +_PRE_RANK_DEV_ONLY = -1  # sorts before a(0)
    +_PRE_RANK_STABLE = 3  # sorts after rc(2)
    +
    +# In local version segments, strings sort before ints per PEP 440.
    +_LOCAL_STR_RANK = -1  # sorts before all non-negative ints
    +
    +# Pre-computed suffix for stable releases (no pre, post, or dev segments).
    +# See _cmpkey() for the suffix layout.
    +_STABLE_SUFFIX = (_PRE_RANK_STABLE, 0, 0, 0, 1, 0)
    +
    +
    +def _cmpkey(
    +    epoch: int,
    +    release: tuple[int, ...],
    +    pre: tuple[str, int] | None,
    +    post: tuple[str, int] | None,
    +    dev: tuple[str, int] | None,
    +    local: LocalType | None,
    +) -> CmpKey:
    +    """Build a comparison key for PEP 440 ordering.
    +
    +    Returns ``(epoch, release, suffix)`` or
    +    ``(epoch, release, suffix, local)`` so that plain tuple
    +    comparison gives the correct order.
    +
    +    Trailing zeros are stripped from the release so that ``1.0.0 == 1``.
    +
    +    The suffix is a flat 6-int tuple that encodes pre/post/dev:
    +    ``(pre_rank, pre_n, post_rank, post_n, dev_rank, dev_n)``
    +
    +    pre_rank: dev-only=-1, a=0, b=1, rc=2, no-pre=3
    +        Dev-only releases (no pre or post) get -1 so they sort before
    +        any alpha/beta/rc.  Releases without a pre-release tag get 3
    +        so they sort after rc.
    +    post_rank: no-post=0, post=1
    +        Releases without a post segment sort before those with one.
    +    dev_rank: dev=0, no-dev=1
    +        Releases without a dev segment sort after those with one.
    +
    +    Local segments use ``(n, "")`` for ints and ``(-1, s)`` for strings,
    +    following PEP 440: strings sort before ints, strings compare
    +    lexicographically, ints compare numerically, and shorter segments
    +    sort before longer when prefixes match.  Versions without a local
    +    segment sort before those with one (3-tuple < 4-tuple).
    +
    +    >>> _cmpkey(0, (1, 0, 0), None, None, None, None)
    +    (0, (1,), (3, 0, 0, 0, 1, 0))
    +    >>> _cmpkey(0, (1,), ("a", 1), None, None, None)
    +    (0, (1,), (0, 1, 0, 0, 1, 0))
    +    >>> _cmpkey(0, (1,), None, None, None, ("ubuntu", 1))
    +    (0, (1,), (3, 0, 0, 0, 1, 0), ((-1, 'ubuntu'), (1, '')))
    +    """
    +    # Strip trailing zeros: 1.0.0 compares equal to 1.
    +    len_release = len(release)
    +    i = len_release
    +    while i and release[i - 1] == 0:
    +        i -= 1
    +    trimmed = release if i == len_release else release[:i]
    +
    +    # Fast path: stable release with no local segment.
    +    if pre is None and post is None and dev is None and local is None:
    +        return epoch, trimmed, _STABLE_SUFFIX
    +
    +    if pre is None and post is None and dev is not None:
    +        # dev-only (e.g. 1.0.dev1) sorts before all pre-releases.
    +        pre_rank, pre_n = _PRE_RANK_DEV_ONLY, 0
    +    elif pre is None:
    +        pre_rank, pre_n = _PRE_RANK_STABLE, 0
    +    else:
    +        pre_rank, pre_n = _PRE_RANK[pre[0]], pre[1]
    +
    +    post_rank = 0 if post is None else 1
    +    post_n = 0 if post is None else post[1]
    +
    +    dev_rank = 1 if dev is None else 0
    +    dev_n = 0 if dev is None else dev[1]
    +
    +    suffix = (pre_rank, pre_n, post_rank, post_n, dev_rank, dev_n)
    +
    +    if local is None:
    +        return epoch, trimmed, suffix
    +
    +    cmp_local: CmpLocalType = tuple(
    +        (seg, "") if isinstance(seg, int) else (_LOCAL_STR_RANK, seg) for seg in local
    +    )
    +    return epoch, trimmed, suffix, cmp_local
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse-0.5.5.dist-info/INSTALLER b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse-0.5.5.dist-info/INSTALLER
    new file mode 100644
    index 0000000..a1b589e
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse-0.5.5.dist-info/INSTALLER
    @@ -0,0 +1 @@
    +pip
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse-0.5.5.dist-info/METADATA b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse-0.5.5.dist-info/METADATA
    new file mode 100644
    index 0000000..8423225
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse-0.5.5.dist-info/METADATA
    @@ -0,0 +1,143 @@
    +Metadata-Version: 2.4
    +Name: sqlparse
    +Version: 0.5.5
    +Summary: A non-validating SQL parser.
    +Project-URL: Home, https://github.com/andialbrecht/sqlparse
    +Project-URL: Documentation, https://sqlparse.readthedocs.io/
    +Project-URL: Release Notes, https://sqlparse.readthedocs.io/en/latest/changes.html
    +Project-URL: Source, https://github.com/andialbrecht/sqlparse
    +Project-URL: Tracker, https://github.com/andialbrecht/sqlparse/issues
    +Author-email: Andi Albrecht 
    +License-File: AUTHORS
    +License-File: LICENSE
    +Classifier: Development Status :: 5 - Production/Stable
    +Classifier: Intended Audience :: Developers
    +Classifier: License :: OSI Approved :: BSD License
    +Classifier: Operating System :: OS Independent
    +Classifier: Programming Language :: Python
    +Classifier: Programming Language :: Python :: 3
    +Classifier: Programming Language :: Python :: 3 :: Only
    +Classifier: Programming Language :: Python :: 3.8
    +Classifier: Programming Language :: Python :: 3.9
    +Classifier: Programming Language :: Python :: 3.10
    +Classifier: Programming Language :: Python :: 3.11
    +Classifier: Programming Language :: Python :: 3.12
    +Classifier: Programming Language :: Python :: 3.13
    +Classifier: Programming Language :: Python :: 3.14
    +Classifier: Programming Language :: Python :: Implementation :: CPython
    +Classifier: Programming Language :: Python :: Implementation :: PyPy
    +Classifier: Topic :: Database
    +Classifier: Topic :: Software Development
    +Requires-Python: >=3.8
    +Provides-Extra: dev
    +Requires-Dist: build; extra == 'dev'
    +Provides-Extra: doc
    +Requires-Dist: sphinx; extra == 'doc'
    +Description-Content-Type: text/x-rst
    +
    +python-sqlparse - Parse SQL statements
    +======================================
    +
    +|buildstatus|_
    +|coverage|_
    +|docs|_
    +|packageversion|_
    +
    +.. docincludebegin
    +
    +sqlparse is a non-validating SQL parser for Python.
    +It provides support for parsing, splitting and formatting SQL statements.
    +
    +The module is compatible with Python 3.8+ and released under the terms of the
    +`New BSD license `_.
    +
    +Visit the project page at https://github.com/andialbrecht/sqlparse for
    +further information about this project.
    +
    +
    +Quick Start
    +-----------
    +
    +.. code-block:: sh
    +
    +   $ pip install sqlparse
    +
    +.. code-block:: python
    +
    +   >>> import sqlparse
    +
    +   >>> # Split a string containing two SQL statements:
    +   >>> raw = 'select * from foo; select * from bar;'
    +   >>> statements = sqlparse.split(raw)
    +   >>> statements
    +   ['select * from foo;', 'select * from bar;']
    +
    +   >>> # Format the first statement and print it out:
    +   >>> first = statements[0]
    +   >>> print(sqlparse.format(first, reindent=True, keyword_case='upper'))
    +   SELECT *
    +   FROM foo;
    +
    +   >>> # Parsing a SQL statement:
    +   >>> parsed = sqlparse.parse('select * from foo')[0]
    +   >>> parsed.tokens
    +   [, , >>
    +
    +Pre-commit Hook
    +---------------
    +
    +sqlparse can be used as a `pre-commit `_ hook
    +to automatically format SQL files before committing:
    +
    +.. code-block:: yaml
    +
    +   repos:
    +     - repo: https://github.com/andialbrecht/sqlparse
    +       rev: 0.5.4  # Use the latest version
    +       hooks:
    +         - id: sqlformat
    +           # Optional: Add more formatting options
    +           # IMPORTANT: --in-place is required, already included by default
    +           args: [--in-place, --reindent, --keywords, upper]
    +
    +Then install the hook:
    +
    +.. code-block:: sh
    +
    +   $ pre-commit install
    +
    +Your SQL files will now be automatically formatted on each commit.
    +
    +**Note**: The hook uses ``--in-place --reindent`` by default. If you override
    +the ``args``, you **must** include ``--in-place`` for the hook to work.
    +
    +Links
    +-----
    +
    +Project page
    +   https://github.com/andialbrecht/sqlparse
    +
    +Bug tracker
    +   https://github.com/andialbrecht/sqlparse/issues
    +
    +Documentation
    +   https://sqlparse.readthedocs.io/
    +
    +Online Demo
    +   https://sqlformat.org/
    +
    +
    +sqlparse is licensed under the BSD license.
    +
    +Parts of the code are based on pygments written by Georg Brandl and others.
    +pygments-Homepage: http://pygments.org/
    +
    +.. |buildstatus| image:: https://github.com/andialbrecht/sqlparse/actions/workflows/python-app.yml/badge.svg
    +.. _buildstatus: https://github.com/andialbrecht/sqlparse/actions/workflows/python-app.yml
    +.. |coverage| image:: https://codecov.io/gh/andialbrecht/sqlparse/branch/master/graph/badge.svg
    +.. _coverage: https://codecov.io/gh/andialbrecht/sqlparse
    +.. |docs| image:: https://readthedocs.org/projects/sqlparse/badge/?version=latest
    +.. _docs: https://sqlparse.readthedocs.io/en/latest/?badge=latest
    +.. |packageversion| image:: https://img.shields.io/pypi/v/sqlparse?color=%2334D058&label=pypi%20package
    +.. _packageversion: https://pypi.org/project/sqlparse
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse-0.5.5.dist-info/RECORD b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse-0.5.5.dist-info/RECORD
    new file mode 100644
    index 0000000..878a3cb
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse-0.5.5.dist-info/RECORD
    @@ -0,0 +1,30 @@
    +../../bin/sqlformat,sha256=VIvsMQtda4_vgi7kzFrPSZuR2ZRWW_ncFj8swmP32qs,192
    +sqlparse-0.5.5.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
    +sqlparse-0.5.5.dist-info/METADATA,sha256=ZGCM4WMxMzRoUdjs-mg5MdChtwwWIHINiiGViRc1NiE,4734
    +sqlparse-0.5.5.dist-info/RECORD,,
    +sqlparse-0.5.5.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
    +sqlparse-0.5.5.dist-info/entry_points.txt,sha256=caB1VVIDXYzEjsQD0qpaPl2CfDFIKnRSPpsK88ne_4M,53
    +sqlparse-0.5.5.dist-info/licenses/AUTHORS,sha256=Ze1CH8AyJS6yO3pLZO1pFcEsO_ZN7G891Ne1tCH4_Tw,3462
    +sqlparse-0.5.5.dist-info/licenses/LICENSE,sha256=wZOCNbgNOekxOOrontw69n4Y7LxA0mZSn6V7Lc5CYxA,1537
    +sqlparse/__init__.py,sha256=gAH0j0P2NmU_AKH1VtjL7UjyVYjczGPmqiDXLtq7WyU,2617
    +sqlparse/__main__.py,sha256=1jhVFLHlZs4NUJoAuHvQQKWgykPVTdgeE8V4XB5WQzw,610
    +sqlparse/cli.py,sha256=LM_AymzzVAtLEeTCaR-nj4-8uTZyxaN7z1gy1KqldNc,7191
    +sqlparse/engine/__init__.py,sha256=i9kh0USMjk1bwKPFTn6K0PKC55HOqvnkoxHi1t7YccE,447
    +sqlparse/engine/filter_stack.py,sha256=qA0MlaTSN3rDa3aUTsW-G5yXbZt6xnCZlEsKTGMO-Uk,1600
    +sqlparse/engine/grouping.py,sha256=oKzutz1ku93vDIzMmYx5BRpyxiaZe-2CA1yrwqHN7QI,16025
    +sqlparse/engine/statement_splitter.py,sha256=CcSrt0zcrAgVpLhvd_9hAgcprebD5p_jLQkO2-Kr79A,5634
    +sqlparse/exceptions.py,sha256=QyZ9TKTvzgcmuQ1cJkxAj9SoAw4M02-Bf0CSUNWNDKM,342
    +sqlparse/filters/__init__.py,sha256=HSlZIjmJBUwjwQf00KDpok1azKOzFVUWXBNpsVLKZ3Y,1343
    +sqlparse/filters/aligned_indent.py,sha256=1HsTHX7NtFpqnoxpxMvKdAPJND2qbl-4AOFzlk4rC3U,5095
    +sqlparse/filters/others.py,sha256=3LrfMOr5zirF6qop2K4G_AAzSd33cebBqh9aPwgIEK8,6669
    +sqlparse/filters/output.py,sha256=OMSalSPvq3s3-r268Tjv-AmtjTNCfhLayWtQFO5oyVE,4001
    +sqlparse/filters/reindent.py,sha256=opoNmKCY4MleKG9HnCYVB8o5TtbyDgnoz37pwKPCAqU,9891
    +sqlparse/filters/right_margin.py,sha256=NhpkVfgPfd9T62I_9M4nsGY_rtFmAnh5mRMlako0KoA,1535
    +sqlparse/filters/tokens.py,sha256=CZwDwMzzOdq0qvTRIIic7w59g54QhwFgM2Op9932Zvk,1553
    +sqlparse/formatter.py,sha256=Cf_vAKmcSN-Wq_6Hz1NBtFjxJl8dyYwcZf772Ecy4MU,7804
    +sqlparse/keywords.py,sha256=jSN_9hro4Kf2SeZlHjSD3DbUPXRL0QJvs3oqd4Ext38,30627
    +sqlparse/lexer.py,sha256=IOfwZTxvw0hSfACRA72sbWbwKTkaVSNCzKjR83PTonA,5991
    +sqlparse/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
    +sqlparse/sql.py,sha256=TT1j4WEwjpmO7hkirRlyEt0KblARJJqns41uUd1rw8k,20885
    +sqlparse/tokens.py,sha256=g9iwZMLGboSuRQUHfVLSddC5dv43PkxJOu4-tkhMs0o,1779
    +sqlparse/utils.py,sha256=bKFkat1Ko5wfEIPhD_FvZRMBGG9OJtv9dQLBoZKnboc,3475
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse-0.5.5.dist-info/WHEEL b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse-0.5.5.dist-info/WHEEL
    new file mode 100644
    index 0000000..ae8ec1b
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse-0.5.5.dist-info/WHEEL
    @@ -0,0 +1,4 @@
    +Wheel-Version: 1.0
    +Generator: hatchling 1.28.0
    +Root-Is-Purelib: true
    +Tag: py3-none-any
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse-0.5.5.dist-info/entry_points.txt b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse-0.5.5.dist-info/entry_points.txt
    new file mode 100644
    index 0000000..dcba058
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse-0.5.5.dist-info/entry_points.txt
    @@ -0,0 +1,2 @@
    +[console_scripts]
    +sqlformat = sqlparse.__main__:main
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse-0.5.5.dist-info/licenses/AUTHORS b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse-0.5.5.dist-info/licenses/AUTHORS
    new file mode 100644
    index 0000000..24ca667
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse-0.5.5.dist-info/licenses/AUTHORS
    @@ -0,0 +1,88 @@
    +python-sqlparse is written and maintained by Andi Albrecht .
    +
    +This module contains code (namely the lexer and filter mechanism) from
    +the pygments project that was written by Georg Brandl.
    +
    +This module contains code (Python 2/3 compatibility) from the six
    +project: https://bitbucket.org/gutworth/six.
    +
    +Alphabetical list of contributors:
    +* Adam Greenhall 
    +* Adam Johnson 
    +* Aki Ariga 
    +* Alexander Beedie 
    +* Alexey Malyshev 
    +* ali-tny 
    +* andrew deryabin 
    +* Andrew Tipton 
    +* atronah 
    +* casey 
    +* Cauê Beloni 
    +* Christian Clauss 
    +* circld 
    +* Corey Zumar 
    +* Cristian Orellana 
    +* Dag Wieers 
    +* Daniel Harding 
    +* Darik Gamble 
    +* Demetrio92 
    +* Dennis Taylor 
    +* Dvořák Václav 
    +* Erik Cederstrand 
    +* Florian Bauer 
    +* Fredy Wijaya 
    +* Gavin Wahl 
    +* Georg Traar 
    +* griff <70294474+griffatrasgo@users.noreply.github.com>
    +* Hugo van Kemenade 
    +* hurcy 
    +* Ian Robertson 
    +* Igor Khrol 
    +* JacekPliszka 
    +* JavierPan 
    +* Jean-Martin Archer 
    +* Jesús Leganés Combarro "Piranna" 
    +* Johannes Hoff 
    +* John Bodley 
    +* Jon Dufresne 
    +* Josh Soref 
    +* Kevin Jing Qiu 
    +* koljonen 
    +* Likai Liu 
    +* Long Le Xich 
    +* mathilde.oustlant 
    +* Michael Schuller 
    +* Mike Amy 
    +* mulos 
    +* Oleg Broytman 
    +* osmnv <80402144+osmnv@users.noreply.github.com>
    +* Patrick Schemitz 
    +* Pi Delport 
    +* Prudhvi Vatala 
    +* quest 
    +* Robert Nix 
    +* Rocky Meza 
    +* Romain Rigaux 
    +* Rowan Seymour 
    +* Ryan Wooden 
    +* saaj 
    +* Sergei Stropysh 
    +* Shen Longxing 
    +* Simon Heisterkamp 
    +* Sjoerd Job Postmus
    +* skryzh 
    +* Soloman Weng 
    +* spigwitmer 
    +* Stefan Warnat 
    +* Tao Wang 
    +* Tenghuan 
    +* Tim Graham 
    +* Victor Hahn 
    +* Victor Uriarte 
    +* Ville Skyttä 
    +* vthriller 
    +* wayne.wuw 
    +* Will Jones 
    +* William Ivanski 
    +* Yago Riveiro 
    +* Zi-Xuan Fu 
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse-0.5.5.dist-info/licenses/LICENSE b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse-0.5.5.dist-info/licenses/LICENSE
    new file mode 100644
    index 0000000..de414c5
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse-0.5.5.dist-info/licenses/LICENSE
    @@ -0,0 +1,25 @@
    +Copyright (c) 2016, Andi Albrecht 
    +All rights reserved.
    +
    +Redistribution and use in source and binary forms, with or without modification,
    +are permitted provided that the following conditions are met:
    +
    +    * Redistributions of source code must retain the above copyright notice,
    +      this list of conditions and the following disclaimer.
    +    * Redistributions in binary form must reproduce the above copyright notice,
    +      this list of conditions and the following disclaimer in the documentation
    +      and/or other materials provided with the distribution.
    +    * Neither the name of the authors nor the names of its contributors may be
    +      used to endorse or promote products derived from this software without
    +      specific prior written permission.
    +
    +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
    +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/__init__.py
    new file mode 100644
    index 0000000..b900af1
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/__init__.py
    @@ -0,0 +1,80 @@
    +#
    +# Copyright (C) 2009-2020 the sqlparse authors and contributors
    +# 
    +#
    +# This module is part of python-sqlparse and is released under
    +# the BSD License: https://opensource.org/licenses/BSD-3-Clause
    +
    +"""Parse SQL statements."""
    +
    +# Setup namespace
    +from typing import Any, Generator, IO, List, Optional, Tuple, Union
    +
    +from sqlparse import sql
    +from sqlparse import cli
    +from sqlparse import engine
    +from sqlparse import tokens
    +from sqlparse import filters
    +from sqlparse import formatter
    +
    +
    +__version__ = "0.5.5"
    +__all__ = ["engine", "filters", "formatter", "sql", "tokens", "cli"]
    +
    +
    +def parse(
    +    sql: str, encoding: Optional[str] = None
    +) -> Tuple[sql.Statement, ...]:
    +    """Parse sql and return a list of statements.
    +
    +    :param sql: A string containing one or more SQL statements.
    +    :param encoding: The encoding of the statement (optional).
    +    :returns: A tuple of :class:`~sqlparse.sql.Statement` instances.
    +    """
    +    return tuple(parsestream(sql, encoding))
    +
    +
    +def parsestream(
    +    stream: Union[str, IO[str]], encoding: Optional[str] = None
    +) -> Generator[sql.Statement, None, None]:
    +    """Parses sql statements from file-like object.
    +
    +    :param stream: A file-like object.
    +    :param encoding: The encoding of the stream contents (optional).
    +    :returns: A generator of :class:`~sqlparse.sql.Statement` instances.
    +    """
    +    stack = engine.FilterStack()
    +    stack.enable_grouping()
    +    return stack.run(stream, encoding)
    +
    +
    +def format(sql: str, encoding: Optional[str] = None, **options: Any) -> str:
    +    """Format *sql* according to *options*.
    +
    +    Available options are documented in :ref:`formatting`.
    +
    +    In addition to the formatting options this function accepts the
    +    keyword "encoding" which determines the encoding of the statement.
    +
    +    :returns: The formatted SQL statement as string.
    +    """
    +    stack = engine.FilterStack()
    +    options = formatter.validate_options(options)
    +    stack = formatter.build_filter_stack(stack, options)
    +    stack.postprocess.append(filters.SerializerUnicode())
    +    return "".join(stack.run(sql, encoding))
    +
    +
    +def split(
    +    sql: str, encoding: Optional[str] = None, strip_semicolon: bool = False
    +) -> List[str]:
    +    """Split *sql* into single statements.
    +
    +    :param sql: A string containing one or more SQL statements.
    +    :param encoding: The encoding of the statement (optional).
    +    :param strip_semicolon: If True, remove trailing semicolons
    +        (default: False).
    +    :returns: A list of strings.
    +    """
    +    stack = engine.FilterStack(strip_semicolon=strip_semicolon)
    +    return [str(stmt).strip() for stmt in stack.run(sql, encoding)]
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/__main__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/__main__.py
    new file mode 100644
    index 0000000..2bf2513
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/__main__.py
    @@ -0,0 +1,22 @@
    +#!/usr/bin/env python
    +#
    +# Copyright (C) 2009-2020 the sqlparse authors and contributors
    +# 
    +#
    +# This module is part of python-sqlparse and is released under
    +# the BSD License: https://opensource.org/licenses/BSD-3-Clause
    +
    +"""Entrypoint module for `python -m sqlparse`.
    +
    +Why does this file exist, and why __main__? For more info, read:
    +- https://www.python.org/dev/peps/pep-0338/
    +- https://docs.python.org/2/using/cmdline.html#cmdoption-m
    +- https://docs.python.org/3/using/cmdline.html#cmdoption-m
    +"""
    +
    +import sys
    +
    +from sqlparse.cli import main
    +
    +if __name__ == '__main__':
    +    sys.exit(main())
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/cli.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/cli.py
    new file mode 100644
    index 0000000..03ee86e
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/cli.py
    @@ -0,0 +1,246 @@
    +# Copyright (C) 2009-2020 the sqlparse authors and contributors
    +# 
    +#
    +# This module is part of python-sqlparse and is released under
    +# the BSD License: https://opensource.org/licenses/BSD-3-Clause
    +
    +"""Module that contains the command line app.
    +
    +Why does this file exist, and why not put this in __main__?
    +  You might be tempted to import things from __main__ later, but that will
    +  cause problems: the code will get executed twice:
    +  - When you run `python -m sqlparse` python will execute
    +    ``__main__.py`` as a script. That means there won't be any
    +    ``sqlparse.__main__`` in ``sys.modules``.
    +  - When you import __main__ it will get executed again (as a module) because
    +    there's no ``sqlparse.__main__`` in ``sys.modules``.
    +  Also see (1) from http://click.pocoo.org/5/setuptools/#setuptools-integration
    +"""
    +
    +import argparse
    +import sys
    +from io import TextIOWrapper
    +
    +import sqlparse
    +from sqlparse.exceptions import SQLParseError
    +
    +
    +# TODO: Add CLI Tests
    +# TODO: Simplify formatter by using argparse `type` arguments
    +def create_parser():
    +    _CASE_CHOICES = ['upper', 'lower', 'capitalize']
    +
    +    parser = argparse.ArgumentParser(
    +        prog='sqlformat',
    +        description='Format FILE according to OPTIONS. Use "-" as FILE '
    +                    'to read from stdin.',
    +        usage='%(prog)s [OPTIONS] FILE [FILE ...]',
    +    )
    +
    +    parser.add_argument(
    +        'filename',
    +        nargs='+',
    +        help='file(s) to format (use "-" for stdin)')
    +
    +    parser.add_argument(
    +        '-o', '--outfile',
    +        dest='outfile',
    +        metavar='FILE',
    +        help='write output to FILE (defaults to stdout)')
    +
    +    parser.add_argument(
    +        '--in-place',
    +        dest='inplace',
    +        action='store_true',
    +        default=False,
    +        help='format files in-place (overwrite existing files)')
    +
    +    parser.add_argument(
    +        '--version',
    +        action='version',
    +        version=sqlparse.__version__)
    +
    +    group = parser.add_argument_group('Formatting Options')
    +
    +    group.add_argument(
    +        '-k', '--keywords',
    +        metavar='CHOICE',
    +        dest='keyword_case',
    +        choices=_CASE_CHOICES,
    +        help='change case of keywords, CHOICE is one of {}'.format(
    +            ', '.join(f'"{x}"' for x in _CASE_CHOICES)))
    +
    +    group.add_argument(
    +        '-i', '--identifiers',
    +        metavar='CHOICE',
    +        dest='identifier_case',
    +        choices=_CASE_CHOICES,
    +        help='change case of identifiers, CHOICE is one of {}'.format(
    +            ', '.join(f'"{x}"' for x in _CASE_CHOICES)))
    +
    +    group.add_argument(
    +        '-l', '--language',
    +        metavar='LANG',
    +        dest='output_format',
    +        choices=['python', 'php'],
    +        help='output a snippet in programming language LANG, '
    +             'choices are "python", "php"')
    +
    +    group.add_argument(
    +        '--strip-comments',
    +        dest='strip_comments',
    +        action='store_true',
    +        default=False,
    +        help='remove comments')
    +
    +    group.add_argument(
    +        '-r', '--reindent',
    +        dest='reindent',
    +        action='store_true',
    +        default=False,
    +        help='reindent statements')
    +
    +    group.add_argument(
    +        '--indent_width',
    +        dest='indent_width',
    +        default=2,
    +        type=int,
    +        help='indentation width (defaults to 2 spaces)')
    +
    +    group.add_argument(
    +        '--indent_after_first',
    +        dest='indent_after_first',
    +        action='store_true',
    +        default=False,
    +        help='indent after first line of statement (e.g. SELECT)')
    +
    +    group.add_argument(
    +        '--indent_columns',
    +        dest='indent_columns',
    +        action='store_true',
    +        default=False,
    +        help='indent all columns by indent_width instead of keyword length')
    +
    +    group.add_argument(
    +        '-a', '--reindent_aligned',
    +        action='store_true',
    +        default=False,
    +        help='reindent statements to aligned format')
    +
    +    group.add_argument(
    +        '-s', '--use_space_around_operators',
    +        action='store_true',
    +        default=False,
    +        help='place spaces around mathematical operators')
    +
    +    group.add_argument(
    +        '--wrap_after',
    +        dest='wrap_after',
    +        default=0,
    +        type=int,
    +        help='Column after which lists should be wrapped')
    +
    +    group.add_argument(
    +        '--comma_first',
    +        dest='comma_first',
    +        default=False,
    +        type=bool,
    +        help='Insert linebreak before comma (default False)')
    +
    +    group.add_argument(
    +        '--compact',
    +        dest='compact',
    +        default=False,
    +        type=bool,
    +        help='Try to produce more compact output (default False)')
    +
    +    group.add_argument(
    +        '--encoding',
    +        dest='encoding',
    +        default='utf-8',
    +        help='Specify the input encoding (default utf-8)')
    +
    +    return parser
    +
    +
    +def _error(msg):
    +    """Print msg and optionally exit with return code exit_."""
    +    sys.stderr.write(f'[ERROR] {msg}\n')
    +    return 1
    +
    +
    +def _process_file(filename, args):
    +    """Process a single file with the given formatting options.
    +
    +    Returns 0 on success, 1 on error.
    +    """
    +    # Check for incompatible option combinations first
    +    if filename == '-' and args.inplace:
    +        return _error('Cannot use --in-place with stdin')
    +
    +    # Read input
    +    if filename == '-':  # read from stdin
    +        wrapper = TextIOWrapper(sys.stdin.buffer, encoding=args.encoding)
    +        try:
    +            data = wrapper.read()
    +        finally:
    +            wrapper.detach()
    +    else:
    +        try:
    +            with open(filename, encoding=args.encoding) as f:
    +                data = ''.join(f.readlines())
    +        except OSError as e:
    +            return _error(f'Failed to read {filename}: {e}')
    +
    +    # Determine output destination
    +    close_stream = False
    +    if args.inplace:
    +        try:
    +            stream = open(filename, 'w', encoding=args.encoding)
    +            close_stream = True
    +        except OSError as e:
    +            return _error(f'Failed to open {filename}: {e}')
    +    elif args.outfile:
    +        try:
    +            stream = open(args.outfile, 'w', encoding=args.encoding)
    +            close_stream = True
    +        except OSError as e:
    +            return _error(f'Failed to open {args.outfile}: {e}')
    +    else:
    +        stream = sys.stdout
    +
    +    # Format the SQL
    +    formatter_opts = vars(args)
    +    try:
    +        formatter_opts = sqlparse.formatter.validate_options(formatter_opts)
    +    except SQLParseError as e:
    +        return _error(f'Invalid options: {e}')
    +
    +    s = sqlparse.format(data, **formatter_opts)
    +    stream.write(s)
    +    stream.flush()
    +    if close_stream:
    +        stream.close()
    +    return 0
    +
    +
    +def main(args=None):
    +    parser = create_parser()
    +    args = parser.parse_args(args)
    +
    +    # Validate argument combinations
    +    if len(args.filename) > 1:
    +        if args.outfile:
    +            return _error('Cannot use -o/--outfile with multiple files')
    +        if not args.inplace:
    +            return _error('Multiple files require --in-place flag')
    +
    +    # Process all files
    +    exit_code = 0
    +    for filename in args.filename:
    +        result = _process_file(filename, args)
    +        if result != 0:
    +            exit_code = result
    +            # Continue processing remaining files even if one fails
    +
    +    return exit_code
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/engine/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/engine/__init__.py
    new file mode 100644
    index 0000000..6d54d51
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/engine/__init__.py
    @@ -0,0 +1,16 @@
    +#
    +# Copyright (C) 2009-2020 the sqlparse authors and contributors
    +# 
    +#
    +# This module is part of python-sqlparse and is released under
    +# the BSD License: https://opensource.org/licenses/BSD-3-Clause
    +
    +from sqlparse.engine import grouping
    +from sqlparse.engine.filter_stack import FilterStack
    +from sqlparse.engine.statement_splitter import StatementSplitter
    +
    +__all__ = [
    +    'grouping',
    +    'FilterStack',
    +    'StatementSplitter',
    +]
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/engine/filter_stack.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/engine/filter_stack.py
    new file mode 100644
    index 0000000..415d3fc
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/engine/filter_stack.py
    @@ -0,0 +1,51 @@
    +#
    +# Copyright (C) 2009-2020 the sqlparse authors and contributors
    +# 
    +#
    +# This module is part of python-sqlparse and is released under
    +# the BSD License: https://opensource.org/licenses/BSD-3-Clause
    +
    +"""filter"""
    +
    +from sqlparse import lexer
    +from sqlparse.engine import grouping
    +from sqlparse.engine.statement_splitter import StatementSplitter
    +from sqlparse.exceptions import SQLParseError
    +from sqlparse.filters import StripTrailingSemicolonFilter
    +
    +
    +class FilterStack:
    +    def __init__(self, strip_semicolon=False):
    +        self.preprocess = []
    +        self.stmtprocess = []
    +        self.postprocess = []
    +        self._grouping = False
    +        if strip_semicolon:
    +            self.stmtprocess.append(StripTrailingSemicolonFilter())
    +
    +    def enable_grouping(self):
    +        self._grouping = True
    +
    +    def run(self, sql, encoding=None):
    +        try:
    +            stream = lexer.tokenize(sql, encoding)
    +            # Process token stream
    +            for filter_ in self.preprocess:
    +                stream = filter_.process(stream)
    +
    +            stream = StatementSplitter().process(stream)
    +
    +            # Output: Stream processed Statements
    +            for stmt in stream:
    +                if self._grouping:
    +                    stmt = grouping.group(stmt)
    +
    +                for filter_ in self.stmtprocess:
    +                    filter_.process(stmt)
    +
    +                for filter_ in self.postprocess:
    +                    stmt = filter_.process(stmt)
    +
    +                yield stmt
    +        except RecursionError as err:
    +            raise SQLParseError('Maximum recursion depth exceeded') from err
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/engine/grouping.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/engine/grouping.py
    new file mode 100644
    index 0000000..43ca5b5
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/engine/grouping.py
    @@ -0,0 +1,525 @@
    +#
    +# Copyright (C) 2009-2020 the sqlparse authors and contributors
    +# 
    +#
    +# This module is part of python-sqlparse and is released under
    +# the BSD License: https://opensource.org/licenses/BSD-3-Clause
    +
    +from sqlparse import sql
    +from sqlparse import tokens as T
    +from sqlparse.exceptions import SQLParseError
    +from sqlparse.utils import recurse, imt
    +
    +# Maximum recursion depth for grouping operations to prevent DoS attacks
    +# Set to None to disable limit (not recommended for untrusted input)
    +MAX_GROUPING_DEPTH = 100
    +
    +# Maximum number of tokens to process in one grouping operation to prevent
    +# DoS attacks.
    +# Set to None to disable limit (not recommended for untrusted input)
    +MAX_GROUPING_TOKENS = 10000
    +
    +T_NUMERICAL = (T.Number, T.Number.Integer, T.Number.Float)
    +T_STRING = (T.String, T.String.Single, T.String.Symbol)
    +T_NAME = (T.Name, T.Name.Placeholder)
    +
    +
    +def _group_matching(tlist, cls, depth=0):
    +    """Groups Tokens that have beginning and end."""
    +    if MAX_GROUPING_DEPTH is not None and depth > MAX_GROUPING_DEPTH:
    +        raise SQLParseError(
    +            f"Maximum grouping depth exceeded ({MAX_GROUPING_DEPTH})."
    +        )
    +
    +    # Limit the number of tokens to prevent DoS attacks
    +    if MAX_GROUPING_TOKENS is not None \
    +       and len(tlist.tokens) > MAX_GROUPING_TOKENS:
    +        raise SQLParseError(
    +            f"Maximum number of tokens exceeded ({MAX_GROUPING_TOKENS})."
    +        )
    +
    +    opens = []
    +    tidx_offset = 0
    +    token_list = list(tlist)
    +
    +    for idx, token in enumerate(token_list):
    +        tidx = idx - tidx_offset
    +
    +        if token.is_whitespace:
    +            # ~50% of tokens will be whitespace. Will checking early
    +            # for them avoid 3 comparisons, but then add 1 more comparison
    +            # for the other ~50% of tokens...
    +            continue
    +
    +        if token.is_group and not isinstance(token, cls):
    +            # Check inside previously grouped (i.e. parenthesis) if group
    +            # of different type is inside (i.e., case). though ideally  should
    +            # should check for all open/close tokens at once to avoid recursion
    +            _group_matching(token, cls, depth + 1)
    +            continue
    +
    +        if token.match(*cls.M_OPEN):
    +            opens.append(tidx)
    +
    +        elif token.match(*cls.M_CLOSE):
    +            try:
    +                open_idx = opens.pop()
    +            except IndexError:
    +                # this indicates invalid sql and unbalanced tokens.
    +                # instead of break, continue in case other "valid" groups exist
    +                continue
    +            close_idx = tidx
    +            tlist.group_tokens(cls, open_idx, close_idx)
    +            tidx_offset += close_idx - open_idx
    +
    +
    +def group_brackets(tlist):
    +    _group_matching(tlist, sql.SquareBrackets)
    +
    +
    +def group_parenthesis(tlist):
    +    _group_matching(tlist, sql.Parenthesis)
    +
    +
    +def group_case(tlist):
    +    _group_matching(tlist, sql.Case)
    +
    +
    +def group_if(tlist):
    +    _group_matching(tlist, sql.If)
    +
    +
    +def group_for(tlist):
    +    _group_matching(tlist, sql.For)
    +
    +
    +def group_begin(tlist):
    +    _group_matching(tlist, sql.Begin)
    +
    +
    +def group_typecasts(tlist):
    +    def match(token):
    +        return token.match(T.Punctuation, '::')
    +
    +    def valid(token):
    +        return token is not None
    +
    +    def post(tlist, pidx, tidx, nidx):
    +        return pidx, nidx
    +
    +    valid_prev = valid_next = valid
    +    _group(tlist, sql.Identifier, match, valid_prev, valid_next, post)
    +
    +
    +def group_tzcasts(tlist):
    +    def match(token):
    +        return token.ttype == T.Keyword.TZCast
    +
    +    def valid_prev(token):
    +        return token is not None
    +
    +    def valid_next(token):
    +        return token is not None and (
    +            token.is_whitespace
    +            or token.match(T.Keyword, 'AS')
    +            or token.match(*sql.TypedLiteral.M_CLOSE)
    +        )
    +
    +    def post(tlist, pidx, tidx, nidx):
    +        return pidx, nidx
    +
    +    _group(tlist, sql.Identifier, match, valid_prev, valid_next, post)
    +
    +
    +def group_typed_literal(tlist):
    +    # definitely not complete, see e.g.:
    +    # https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/interval-literal-syntax
    +    # https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/interval-literals
    +    # https://www.postgresql.org/docs/9.1/datatype-datetime.html
    +    # https://www.postgresql.org/docs/9.1/functions-datetime.html
    +    def match(token):
    +        return imt(token, m=sql.TypedLiteral.M_OPEN)
    +
    +    def match_to_extend(token):
    +        return isinstance(token, sql.TypedLiteral)
    +
    +    def valid_prev(token):
    +        return token is not None
    +
    +    def valid_next(token):
    +        return token is not None and token.match(*sql.TypedLiteral.M_CLOSE)
    +
    +    def valid_final(token):
    +        return token is not None and token.match(*sql.TypedLiteral.M_EXTEND)
    +
    +    def post(tlist, pidx, tidx, nidx):
    +        return tidx, nidx
    +
    +    _group(tlist, sql.TypedLiteral, match, valid_prev, valid_next,
    +           post, extend=False)
    +    _group(tlist, sql.TypedLiteral, match_to_extend, valid_prev, valid_final,
    +           post, extend=True)
    +
    +
    +def group_period(tlist):
    +    def match(token):
    +        for ttype, value in ((T.Punctuation, '.'),
    +                             (T.Operator, '->'),
    +                             (T.Operator, '->>')):
    +            if token.match(ttype, value):
    +                return True
    +        return False
    +
    +    def valid_prev(token):
    +        sqlcls = sql.SquareBrackets, sql.Identifier
    +        ttypes = T.Name, T.String.Symbol
    +        return imt(token, i=sqlcls, t=ttypes)
    +
    +    def valid_next(token):
    +        # issue261, allow invalid next token
    +        return True
    +
    +    def post(tlist, pidx, tidx, nidx):
    +        # next_ validation is being performed here. issue261
    +        sqlcls = sql.SquareBrackets, sql.Function
    +        ttypes = T.Name, T.String.Symbol, T.Wildcard, T.String.Single
    +        next_ = tlist[nidx] if nidx is not None else None
    +        valid_next = imt(next_, i=sqlcls, t=ttypes)
    +
    +        return (pidx, nidx) if valid_next else (pidx, tidx)
    +
    +    _group(tlist, sql.Identifier, match, valid_prev, valid_next, post)
    +
    +
    +def group_as(tlist):
    +    def match(token):
    +        return token.is_keyword and token.normalized == 'AS'
    +
    +    def valid_prev(token):
    +        return token.normalized == 'NULL' or not token.is_keyword
    +
    +    def valid_next(token):
    +        ttypes = T.DML, T.DDL, T.CTE
    +        return not imt(token, t=ttypes) and token is not None
    +
    +    def post(tlist, pidx, tidx, nidx):
    +        return pidx, nidx
    +
    +    _group(tlist, sql.Identifier, match, valid_prev, valid_next, post)
    +
    +
    +def group_assignment(tlist):
    +    def match(token):
    +        return token.match(T.Assignment, ':=')
    +
    +    def valid(token):
    +        return token is not None and token.ttype not in (T.Keyword,)
    +
    +    def post(tlist, pidx, tidx, nidx):
    +        m_semicolon = T.Punctuation, ';'
    +        snidx, _ = tlist.token_next_by(m=m_semicolon, idx=nidx)
    +        nidx = snidx or nidx
    +        return pidx, nidx
    +
    +    valid_prev = valid_next = valid
    +    _group(tlist, sql.Assignment, match, valid_prev, valid_next, post)
    +
    +
    +def group_comparison(tlist):
    +    sqlcls = (sql.Parenthesis, sql.Function, sql.Identifier,
    +              sql.Operation, sql.TypedLiteral)
    +    ttypes = T_NUMERICAL + T_STRING + T_NAME
    +
    +    def match(token):
    +        return token.ttype == T.Operator.Comparison
    +
    +    def valid(token):
    +        if imt(token, t=ttypes, i=sqlcls):
    +            return True
    +        elif token and token.is_keyword and token.normalized == 'NULL':
    +            return True
    +        else:
    +            return False
    +
    +    def post(tlist, pidx, tidx, nidx):
    +        return pidx, nidx
    +
    +    valid_prev = valid_next = valid
    +    _group(tlist, sql.Comparison, match,
    +           valid_prev, valid_next, post, extend=False)
    +
    +
    +@recurse(sql.Identifier)
    +def group_identifier(tlist):
    +    ttypes = (T.String.Symbol, T.Name)
    +
    +    tidx, token = tlist.token_next_by(t=ttypes)
    +    while token:
    +        tlist.group_tokens(sql.Identifier, tidx, tidx)
    +        tidx, token = tlist.token_next_by(t=ttypes, idx=tidx)
    +
    +
    +@recurse(sql.Over)
    +def group_over(tlist):
    +    tidx, token = tlist.token_next_by(m=sql.Over.M_OPEN)
    +    while token:
    +        nidx, next_ = tlist.token_next(tidx)
    +        if imt(next_, i=sql.Parenthesis, t=T.Name):
    +            tlist.group_tokens(sql.Over, tidx, nidx)
    +        tidx, token = tlist.token_next_by(m=sql.Over.M_OPEN, idx=tidx)
    +
    +
    +def group_arrays(tlist):
    +    sqlcls = sql.SquareBrackets, sql.Identifier, sql.Function
    +    ttypes = T.Name, T.String.Symbol
    +
    +    def match(token):
    +        return isinstance(token, sql.SquareBrackets)
    +
    +    def valid_prev(token):
    +        return imt(token, i=sqlcls, t=ttypes)
    +
    +    def valid_next(token):
    +        return True
    +
    +    def post(tlist, pidx, tidx, nidx):
    +        return pidx, tidx
    +
    +    _group(tlist, sql.Identifier, match,
    +           valid_prev, valid_next, post, extend=True, recurse=False)
    +
    +
    +def group_operator(tlist):
    +    ttypes = T_NUMERICAL + T_STRING + T_NAME
    +    sqlcls = (sql.SquareBrackets, sql.Parenthesis, sql.Function,
    +              sql.Identifier, sql.Operation, sql.TypedLiteral)
    +
    +    def match(token):
    +        return imt(token, t=(T.Operator, T.Wildcard))
    +
    +    def valid(token):
    +        return imt(token, i=sqlcls, t=ttypes) \
    +            or (token and token.match(
    +                T.Keyword,
    +                ('CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP')))
    +
    +    def post(tlist, pidx, tidx, nidx):
    +        tlist[tidx].ttype = T.Operator
    +        return pidx, nidx
    +
    +    valid_prev = valid_next = valid
    +    _group(tlist, sql.Operation, match,
    +           valid_prev, valid_next, post, extend=False)
    +
    +
    +def group_identifier_list(tlist):
    +    m_role = T.Keyword, ('null', 'role')
    +    sqlcls = (sql.Function, sql.Case, sql.Identifier, sql.Comparison,
    +              sql.IdentifierList, sql.Operation)
    +    ttypes = (T_NUMERICAL + T_STRING + T_NAME
    +              + (T.Keyword, T.Comment, T.Wildcard))
    +
    +    def match(token):
    +        return token.match(T.Punctuation, ',')
    +
    +    def valid(token):
    +        return imt(token, i=sqlcls, m=m_role, t=ttypes)
    +
    +    def post(tlist, pidx, tidx, nidx):
    +        return pidx, nidx
    +
    +    valid_prev = valid_next = valid
    +    _group(tlist, sql.IdentifierList, match,
    +           valid_prev, valid_next, post, extend=True)
    +
    +
    +@recurse(sql.Comment)
    +def group_comments(tlist):
    +    tidx, token = tlist.token_next_by(t=T.Comment)
    +    while token:
    +        eidx, end = tlist.token_not_matching(
    +            lambda tk: imt(tk, t=T.Comment) or tk.is_newline, idx=tidx)
    +        if end is not None:
    +            eidx, end = tlist.token_prev(eidx, skip_ws=False)
    +            tlist.group_tokens(sql.Comment, tidx, eidx)
    +
    +        tidx, token = tlist.token_next_by(t=T.Comment, idx=tidx)
    +
    +
    +@recurse(sql.Where)
    +def group_where(tlist):
    +    tidx, token = tlist.token_next_by(m=sql.Where.M_OPEN)
    +    while token:
    +        eidx, end = tlist.token_next_by(m=sql.Where.M_CLOSE, idx=tidx)
    +
    +        if end is None:
    +            end = tlist._groupable_tokens[-1]
    +        else:
    +            end = tlist.tokens[eidx - 1]
    +        # TODO: convert this to eidx instead of end token.
    +        # i think above values are len(tlist) and eidx-1
    +        eidx = tlist.token_index(end)
    +        tlist.group_tokens(sql.Where, tidx, eidx)
    +        tidx, token = tlist.token_next_by(m=sql.Where.M_OPEN, idx=tidx)
    +
    +
    +@recurse()
    +def group_aliased(tlist):
    +    I_ALIAS = (sql.Parenthesis, sql.Function, sql.Case, sql.Identifier,
    +               sql.Operation, sql.Comparison)
    +
    +    tidx, token = tlist.token_next_by(i=I_ALIAS, t=T.Number)
    +    while token:
    +        nidx, next_ = tlist.token_next(tidx)
    +        if isinstance(next_, sql.Identifier):
    +            tlist.group_tokens(sql.Identifier, tidx, nidx, extend=True)
    +        tidx, token = tlist.token_next_by(i=I_ALIAS, t=T.Number, idx=tidx)
    +
    +
    +@recurse(sql.Function)
    +def group_functions(tlist):
    +    has_create = False
    +    has_table = False
    +    has_as = False
    +    for tmp_token in tlist.tokens:
    +        if tmp_token.value.upper() == 'CREATE':
    +            has_create = True
    +        if tmp_token.value.upper() == 'TABLE':
    +            has_table = True
    +        if tmp_token.value == 'AS':
    +            has_as = True
    +    if has_create and has_table and not has_as:
    +        return
    +
    +    tidx, token = tlist.token_next_by(t=T.Name)
    +    while token:
    +        nidx, next_ = tlist.token_next(tidx)
    +        if isinstance(next_, sql.Parenthesis):
    +            over_idx, over = tlist.token_next(nidx)
    +            if over and isinstance(over, sql.Over):
    +                eidx = over_idx
    +            else:
    +                eidx = nidx
    +            tlist.group_tokens(sql.Function, tidx, eidx)
    +        tidx, token = tlist.token_next_by(t=T.Name, idx=tidx)
    +
    +
    +@recurse(sql.Identifier)
    +def group_order(tlist):
    +    """Group together Identifier and Asc/Desc token"""
    +    tidx, token = tlist.token_next_by(t=T.Keyword.Order)
    +    while token:
    +        pidx, prev_ = tlist.token_prev(tidx)
    +        if imt(prev_, i=sql.Identifier, t=T.Number):
    +            tlist.group_tokens(sql.Identifier, pidx, tidx)
    +            tidx = pidx
    +        tidx, token = tlist.token_next_by(t=T.Keyword.Order, idx=tidx)
    +
    +
    +@recurse()
    +def align_comments(tlist):
    +    tidx, token = tlist.token_next_by(i=sql.Comment)
    +    while token:
    +        pidx, prev_ = tlist.token_prev(tidx)
    +        if isinstance(prev_, sql.TokenList):
    +            tlist.group_tokens(sql.TokenList, pidx, tidx, extend=True)
    +            tidx = pidx
    +        tidx, token = tlist.token_next_by(i=sql.Comment, idx=tidx)
    +
    +
    +def group_values(tlist):
    +    tidx, token = tlist.token_next_by(m=(T.Keyword, 'VALUES'))
    +    start_idx = tidx
    +    end_idx = -1
    +    while token:
    +        if isinstance(token, sql.Parenthesis):
    +            end_idx = tidx
    +        tidx, token = tlist.token_next(tidx)
    +    if end_idx != -1:
    +        tlist.group_tokens(sql.Values, start_idx, end_idx, extend=True)
    +
    +
    +def group(stmt):
    +    for func in [
    +        group_comments,
    +
    +        # _group_matching
    +        group_brackets,
    +        group_parenthesis,
    +        group_case,
    +        group_if,
    +        group_for,
    +        group_begin,
    +
    +        group_over,
    +        group_functions,
    +        group_where,
    +        group_period,
    +        group_arrays,
    +        group_identifier,
    +        group_order,
    +        group_typecasts,
    +        group_tzcasts,
    +        group_typed_literal,
    +        group_operator,
    +        group_comparison,
    +        group_as,
    +        group_aliased,
    +        group_assignment,
    +
    +        align_comments,
    +        group_identifier_list,
    +        group_values,
    +    ]:
    +        func(stmt)
    +    return stmt
    +
    +
    +def _group(tlist, cls, match,
    +           valid_prev=lambda t: True,
    +           valid_next=lambda t: True,
    +           post=None,
    +           extend=True,
    +           recurse=True,
    +           depth=0
    +           ):
    +    """Groups together tokens that are joined by a middle token. i.e. x < y"""
    +    if MAX_GROUPING_DEPTH is not None and depth > MAX_GROUPING_DEPTH:
    +        raise SQLParseError(
    +            f"Maximum grouping depth exceeded ({MAX_GROUPING_DEPTH})."
    +        )
    +
    +    # Limit the number of tokens to prevent DoS attacks
    +    if MAX_GROUPING_TOKENS is not None \
    +       and len(tlist.tokens) > MAX_GROUPING_TOKENS:
    +        raise SQLParseError(
    +            f"Maximum number of tokens exceeded ({MAX_GROUPING_TOKENS})."
    +        )
    +
    +    tidx_offset = 0
    +    pidx, prev_ = None, None
    +    token_list = list(tlist)
    +
    +    for idx, token in enumerate(token_list):
    +        tidx = idx - tidx_offset
    +        if tidx < 0:  # tidx shouldn't get negative
    +            continue
    +
    +        if token.is_whitespace:
    +            continue
    +
    +        if recurse and token.is_group and not isinstance(token, cls):
    +            _group(token, cls, match, valid_prev, valid_next,
    +                   post, extend, True, depth + 1)
    +
    +        if match(token):
    +            nidx, next_ = tlist.token_next(tidx)
    +            if prev_ and valid_prev(prev_) and valid_next(next_):
    +                from_idx, to_idx = post(tlist, pidx, tidx, nidx)
    +                grp = tlist.group_tokens(cls, from_idx, to_idx, extend=extend)
    +
    +                tidx_offset += to_idx - from_idx
    +                pidx, prev_ = from_idx, grp
    +                continue
    +
    +        pidx, prev_ = tidx, token
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/engine/statement_splitter.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/engine/statement_splitter.py
    new file mode 100644
    index 0000000..62aa9d9
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/engine/statement_splitter.py
    @@ -0,0 +1,144 @@
    +#
    +# Copyright (C) 2009-2020 the sqlparse authors and contributors
    +# 
    +#
    +# This module is part of python-sqlparse and is released under
    +# the BSD License: https://opensource.org/licenses/BSD-3-Clause
    +
    +from sqlparse import sql, tokens as T
    +
    +
    +class StatementSplitter:
    +    """Filter that split stream at individual statements"""
    +
    +    def __init__(self):
    +        self._reset()
    +
    +    def _reset(self):
    +        """Set the filter attributes to its default values"""
    +        self._in_declare = False
    +        self._in_case = False
    +        self._is_create = False
    +        self._begin_depth = 0
    +        self._seen_begin = False
    +
    +        self.consume_ws = False
    +        self.tokens = []
    +        self.level = 0
    +
    +    def _change_splitlevel(self, ttype, value):
    +        """Get the new split level (increase, decrease or remain equal)"""
    +
    +        # parenthesis increase/decrease a level
    +        if ttype is T.Punctuation and value == '(':
    +            return 1
    +        elif ttype is T.Punctuation and value == ')':
    +            return -1
    +        elif ttype not in T.Keyword:  # if normal token return
    +            return 0
    +
    +        # Everything after here is ttype = T.Keyword
    +        # Also to note, once entered an If statement you are done and basically
    +        # returning
    +        unified = value.upper()
    +
    +        # three keywords begin with CREATE, but only one of them is DDL
    +        # DDL Create though can contain more words such as "or replace"
    +        if ttype is T.Keyword.DDL and unified.startswith('CREATE'):
    +            self._is_create = True
    +            return 0
    +
    +        # can have nested declare inside of being...
    +        if unified == 'DECLARE' and self._is_create and self._begin_depth == 0:
    +            self._in_declare = True
    +            return 1
    +
    +        if unified == 'BEGIN':
    +            self._begin_depth += 1
    +            self._seen_begin = True
    +            if self._is_create:
    +                # FIXME(andi): This makes no sense.  ## this comment neither
    +                return 1
    +            return 0
    +
    +        # Issue826: If we see a transaction keyword after BEGIN,
    +        # it's a transaction statement, not a block.
    +        if self._seen_begin and \
    +                (ttype is T.Keyword or ttype is T.Name) and \
    +                unified in ('TRANSACTION', 'WORK', 'TRAN',
    +                            'DISTRIBUTED', 'DEFERRED',
    +                            'IMMEDIATE', 'EXCLUSIVE'):
    +            self._begin_depth = max(0, self._begin_depth - 1)
    +            self._seen_begin = False
    +            return 0
    +
    +        # BEGIN and CASE/WHEN both end with END
    +        if unified == 'END':
    +            if not self._in_case:
    +                self._begin_depth = max(0, self._begin_depth - 1)
    +            else:
    +                self._in_case = False
    +            return -1
    +
    +        if (unified in ('IF', 'FOR', 'WHILE', 'CASE')
    +                and self._is_create and self._begin_depth > 0):
    +            if unified == 'CASE':
    +                self._in_case = True
    +            return 1
    +
    +        if unified in ('END IF', 'END FOR', 'END WHILE'):
    +            return -1
    +
    +        # Default
    +        return 0
    +
    +    def process(self, stream):
    +        """Process the stream"""
    +        EOS_TTYPE = T.Whitespace, T.Comment.Single
    +
    +        # Run over all stream tokens
    +        for ttype, value in stream:
    +            # Yield token if we finished a statement and there's no whitespaces
    +            # It will count newline token as a non whitespace. In this context
    +            # whitespace ignores newlines.
    +            # why don't multi line comments also count?
    +            if self.consume_ws and ttype not in EOS_TTYPE:
    +                yield sql.Statement(self.tokens)
    +
    +                # Reset filter and prepare to process next statement
    +                self._reset()
    +
    +            # Change current split level (increase, decrease or remain equal)
    +            self.level += self._change_splitlevel(ttype, value)
    +
    +            # Append the token to the current statement
    +            self.tokens.append(sql.Token(ttype, value))
    +
    +            # Check if we get the end of a statement
    +            # Issue762: Allow GO (or "GO 2") as statement splitter.
    +            # When implementing a language toggle, it's not only to add
    +            # keywords it's also to change some rules, like this splitting
    +            # rule.
    +            # Issue809: Ignore semicolons inside BEGIN...END blocks, but handle
    +            # standalone BEGIN; as a transaction statement
    +            if ttype is T.Punctuation and value == ';':
    +                # If we just saw BEGIN; then this is a transaction BEGIN,
    +                # not a BEGIN...END block, so decrement depth
    +                if self._seen_begin:
    +                    self._begin_depth = max(0, self._begin_depth - 1)
    +                self._seen_begin = False
    +                # Split on semicolon if not inside a BEGIN...END block
    +                if self.level <= 0 and self._begin_depth == 0:
    +                    self.consume_ws = True
    +            elif ttype is T.Keyword and value.split()[0] == 'GO':
    +                self.consume_ws = True
    +            elif (ttype not in (T.Whitespace, T.Newline, T.Comment.Single,
    +                                T.Comment.Multiline)
    +                  and not (ttype is T.Keyword and value.upper() == 'BEGIN')):
    +                # Reset _seen_begin if we see a non-whitespace, non-comment
    +                # token but not for BEGIN itself (which just set the flag)
    +                self._seen_begin = False
    +
    +        # Yield pending statement (if any)
    +        if self.tokens and not all(t.is_whitespace for t in self.tokens):
    +            yield sql.Statement(self.tokens)
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/exceptions.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/exceptions.py
    new file mode 100644
    index 0000000..11285da
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/exceptions.py
    @@ -0,0 +1,12 @@
    +#
    +# Copyright (C) 2009-2020 the sqlparse authors and contributors
    +# 
    +#
    +# This module is part of python-sqlparse and is released under
    +# the BSD License: https://opensource.org/licenses/BSD-3-Clause
    +
    +"""Exceptions used in this package."""
    +
    +
    +class SQLParseError(Exception):
    +    """Base class for exceptions in this module."""
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/filters/__init__.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/filters/__init__.py
    new file mode 100644
    index 0000000..0616946
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/filters/__init__.py
    @@ -0,0 +1,42 @@
    +#
    +# Copyright (C) 2009-2020 the sqlparse authors and contributors
    +# 
    +#
    +# This module is part of python-sqlparse and is released under
    +# the BSD License: https://opensource.org/licenses/BSD-3-Clause
    +
    +from sqlparse.filters.others import SerializerUnicode
    +from sqlparse.filters.others import StripCommentsFilter
    +from sqlparse.filters.others import StripWhitespaceFilter
    +from sqlparse.filters.others import StripTrailingSemicolonFilter
    +from sqlparse.filters.others import SpacesAroundOperatorsFilter
    +
    +from sqlparse.filters.output import OutputPHPFilter
    +from sqlparse.filters.output import OutputPythonFilter
    +
    +from sqlparse.filters.tokens import KeywordCaseFilter
    +from sqlparse.filters.tokens import IdentifierCaseFilter
    +from sqlparse.filters.tokens import TruncateStringFilter
    +
    +from sqlparse.filters.reindent import ReindentFilter
    +from sqlparse.filters.right_margin import RightMarginFilter
    +from sqlparse.filters.aligned_indent import AlignedIndentFilter
    +
    +__all__ = [
    +    'SerializerUnicode',
    +    'StripCommentsFilter',
    +    'StripWhitespaceFilter',
    +    'StripTrailingSemicolonFilter',
    +    'SpacesAroundOperatorsFilter',
    +
    +    'OutputPHPFilter',
    +    'OutputPythonFilter',
    +
    +    'KeywordCaseFilter',
    +    'IdentifierCaseFilter',
    +    'TruncateStringFilter',
    +
    +    'ReindentFilter',
    +    'RightMarginFilter',
    +    'AlignedIndentFilter',
    +]
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/filters/aligned_indent.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/filters/aligned_indent.py
    new file mode 100644
    index 0000000..553483b
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/filters/aligned_indent.py
    @@ -0,0 +1,135 @@
    +#
    +# Copyright (C) 2009-2020 the sqlparse authors and contributors
    +# 
    +#
    +# This module is part of python-sqlparse and is released under
    +# the BSD License: https://opensource.org/licenses/BSD-3-Clause
    +
    +from sqlparse import sql, tokens as T
    +from sqlparse.utils import offset, indent
    +
    +
    +class AlignedIndentFilter:
    +    join_words = (r'((LEFT\s+|RIGHT\s+|FULL\s+)?'
    +                  r'(INNER\s+|OUTER\s+|STRAIGHT\s+)?|'
    +                  r'(CROSS\s+|NATURAL\s+)?)?JOIN\b')
    +    by_words = r'(GROUP|ORDER)\s+BY\b'
    +    split_words = ('FROM',
    +                   join_words, 'ON', by_words,
    +                   'WHERE', 'AND', 'OR',
    +                   'HAVING', 'LIMIT',
    +                   'UNION', 'VALUES',
    +                   'SET', 'BETWEEN', 'EXCEPT')
    +
    +    def __init__(self, char=' ', n='\n'):
    +        self.n = n
    +        self.offset = 0
    +        self.indent = 0
    +        self.char = char
    +        self._max_kwd_len = len('select')
    +
    +    def nl(self, offset=1):
    +        # offset = 1 represent a single space after SELECT
    +        offset = -len(offset) if not isinstance(offset, int) else offset
    +        # add two for the space and parenthesis
    +        indent = self.indent * (2 + self._max_kwd_len)
    +
    +        return sql.Token(T.Whitespace, self.n + self.char * (
    +            self._max_kwd_len + offset + indent + self.offset))
    +
    +    def _process_statement(self, tlist):
    +        if len(tlist.tokens) > 0 and tlist.tokens[0].is_whitespace \
    +                and self.indent == 0:
    +            tlist.tokens.pop(0)
    +
    +        # process the main query body
    +        self._process(sql.TokenList(tlist.tokens))
    +
    +    def _process_parenthesis(self, tlist):
    +        # if this isn't a subquery, don't re-indent
    +        _, token = tlist.token_next_by(m=(T.DML, 'SELECT'))
    +        if token is not None:
    +            with indent(self):
    +                tlist.insert_after(tlist[0], self.nl('SELECT'))
    +                # process the inside of the parenthesis
    +                self._process_default(tlist)
    +
    +            # de-indent last parenthesis
    +            tlist.insert_before(tlist[-1], self.nl())
    +
    +    def _process_identifierlist(self, tlist):
    +        # columns being selected
    +        identifiers = list(tlist.get_identifiers())
    +        identifiers.pop(0)
    +        [tlist.insert_before(token, self.nl()) for token in identifiers]
    +        self._process_default(tlist)
    +
    +    def _process_case(self, tlist):
    +        offset_ = len('case ') + len('when ')
    +        cases = tlist.get_cases(skip_ws=True)
    +        # align the end as well
    +        end_token = tlist.token_next_by(m=(T.Keyword, 'END'))[1]
    +        cases.append((None, [end_token]))
    +
    +        condition_width = [len(' '.join(map(str, cond))) if cond else 0
    +                           for cond, _ in cases]
    +        max_cond_width = max(condition_width)
    +
    +        for i, (cond, value) in enumerate(cases):
    +            # cond is None when 'else or end'
    +            stmt = cond[0] if cond else value[0]
    +
    +            if i > 0:
    +                tlist.insert_before(stmt, self.nl(offset_ - len(str(stmt))))
    +            if cond:
    +                ws = sql.Token(T.Whitespace, self.char * (
    +                    max_cond_width - condition_width[i]))
    +                tlist.insert_after(cond[-1], ws)
    +
    +    def _next_token(self, tlist, idx=-1):
    +        split_words = T.Keyword, self.split_words, True
    +        tidx, token = tlist.token_next_by(m=split_words, idx=idx)
    +        # treat "BETWEEN x and y" as a single statement
    +        if token and token.normalized == 'BETWEEN':
    +            tidx, token = self._next_token(tlist, tidx)
    +            if token and token.normalized == 'AND':
    +                tidx, token = self._next_token(tlist, tidx)
    +        return tidx, token
    +
    +    def _split_kwds(self, tlist):
    +        tidx, token = self._next_token(tlist)
    +        while token:
    +            # joins, group/order by are special case. only consider the first
    +            # word as aligner
    +            if (
    +                token.match(T.Keyword, self.join_words, regex=True)
    +                or token.match(T.Keyword, self.by_words, regex=True)
    +            ):
    +                token_indent = token.value.split()[0]
    +            else:
    +                token_indent = str(token)
    +            tlist.insert_before(token, self.nl(token_indent))
    +            tidx += 1
    +            tidx, token = self._next_token(tlist, tidx)
    +
    +    def _process_default(self, tlist):
    +        self._split_kwds(tlist)
    +        # process any sub-sub statements
    +        for sgroup in tlist.get_sublists():
    +            idx = tlist.token_index(sgroup)
    +            pidx, prev_ = tlist.token_prev(idx)
    +            # HACK: make "group/order by" work. Longer than max_len.
    +            offset_ = 3 if (
    +                prev_ and prev_.match(T.Keyword, self.by_words, regex=True)
    +            ) else 0
    +            with offset(self, offset_):
    +                self._process(sgroup)
    +
    +    def _process(self, tlist):
    +        func_name = f'_process_{type(tlist).__name__}'
    +        func = getattr(self, func_name.lower(), self._process_default)
    +        func(tlist)
    +
    +    def process(self, stmt):
    +        self._process(stmt)
    +        return stmt
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/filters/others.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/filters/others.py
    new file mode 100644
    index 0000000..cdb63f0
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/filters/others.py
    @@ -0,0 +1,173 @@
    +#
    +# Copyright (C) 2009-2020 the sqlparse authors and contributors
    +# 
    +#
    +# This module is part of python-sqlparse and is released under
    +# the BSD License: https://opensource.org/licenses/BSD-3-Clause
    +
    +import re
    +
    +from sqlparse import sql, tokens as T
    +from sqlparse.utils import split_unquoted_newlines
    +
    +
    +class StripCommentsFilter:
    +
    +    @staticmethod
    +    def _process(tlist):
    +        def get_next_comment(idx=-1):
    +            # TODO(andi) Comment types should be unified, see related issue38
    +            return tlist.token_next_by(i=sql.Comment, t=T.Comment, idx=idx)
    +
    +        def _get_insert_token(token):
    +            """Returns either a whitespace or the line breaks from token."""
    +            # See issue484 why line breaks should be preserved.
    +            # Note: The actual value for a line break is replaced by \n
    +            # in SerializerUnicode which will be executed in the
    +            # postprocessing state.
    +            m = re.search(r'([\r\n]+) *$', token.value)
    +            if m is not None:
    +                return sql.Token(T.Whitespace.Newline, m.groups()[0])
    +            else:
    +                return sql.Token(T.Whitespace, ' ')
    +
    +        sql_hints = (T.Comment.Multiline.Hint, T.Comment.Single.Hint)
    +        tidx, token = get_next_comment()
    +        while token:
    +            # skipping token remove if token is a SQL-Hint. issue262
    +            is_sql_hint = False
    +            if token.ttype in sql_hints:
    +                is_sql_hint = True
    +            elif isinstance(token, sql.Comment):
    +                comment_tokens = token.tokens
    +                if len(comment_tokens) > 0:
    +                    if comment_tokens[0].ttype in sql_hints:
    +                        is_sql_hint = True
    +
    +            if is_sql_hint:
    +                # using current index as start index to search next token for
    +                # preventing infinite loop in cases when token type is a
    +                # "SQL-Hint" and has to be skipped
    +                tidx, token = get_next_comment(idx=tidx)
    +                continue
    +
    +            pidx, prev_ = tlist.token_prev(tidx, skip_ws=False)
    +            nidx, next_ = tlist.token_next(tidx, skip_ws=False)
    +            # Replace by whitespace if prev and next exist and if they're not
    +            # whitespaces. This doesn't apply if prev or next is a parenthesis.
    +            if (
    +                prev_ is None or next_ is None
    +                or prev_.is_whitespace or prev_.match(T.Punctuation, '(')
    +                or next_.is_whitespace or next_.match(T.Punctuation, ')')
    +            ):
    +                # Insert a whitespace to ensure the following SQL produces
    +                # a valid SQL (see #425).
    +                if prev_ is not None and not prev_.match(T.Punctuation, '('):
    +                    tlist.tokens.insert(tidx, _get_insert_token(token))
    +                tlist.tokens.remove(token)
    +                tidx -= 1
    +            else:
    +                tlist.tokens[tidx] = _get_insert_token(token)
    +
    +            # using current index as start index to search next token for
    +            # preventing infinite loop in cases when token type is a
    +            # "SQL-Hint" and has to be skipped
    +            tidx, token = get_next_comment(idx=tidx)
    +
    +    def process(self, stmt):
    +        [self.process(sgroup) for sgroup in stmt.get_sublists()]
    +        StripCommentsFilter._process(stmt)
    +        return stmt
    +
    +
    +class StripWhitespaceFilter:
    +    def _stripws(self, tlist):
    +        func_name = f'_stripws_{type(tlist).__name__}'
    +        func = getattr(self, func_name.lower(), self._stripws_default)
    +        func(tlist)
    +
    +    @staticmethod
    +    def _stripws_default(tlist):
    +        last_was_ws = False
    +        is_first_char = True
    +        for token in tlist.tokens:
    +            if token.is_whitespace:
    +                token.value = '' if last_was_ws or is_first_char else ' '
    +            last_was_ws = token.is_whitespace
    +            is_first_char = False
    +
    +    def _stripws_identifierlist(self, tlist):
    +        # Removes newlines before commas, see issue140
    +        last_nl = None
    +        for token in list(tlist.tokens):
    +            if last_nl and token.ttype is T.Punctuation and token.value == ',':
    +                tlist.tokens.remove(last_nl)
    +            last_nl = token if token.is_whitespace else None
    +
    +            # next_ = tlist.token_next(token, skip_ws=False)
    +            # if (next_ and not next_.is_whitespace and
    +            #             token.ttype is T.Punctuation and token.value == ','):
    +            #     tlist.insert_after(token, sql.Token(T.Whitespace, ' '))
    +        return self._stripws_default(tlist)
    +
    +    def _stripws_parenthesis(self, tlist):
    +        while tlist.tokens[1].is_whitespace:
    +            tlist.tokens.pop(1)
    +        while tlist.tokens[-2].is_whitespace:
    +            tlist.tokens.pop(-2)
    +        if tlist.tokens[-2].is_group:
    +            # save to remove the last whitespace
    +            while tlist.tokens[-2].tokens[-1].is_whitespace:
    +                tlist.tokens[-2].tokens.pop(-1)
    +        self._stripws_default(tlist)
    +
    +    def process(self, stmt, depth=0):
    +        [self.process(sgroup, depth + 1) for sgroup in stmt.get_sublists()]
    +        self._stripws(stmt)
    +        if depth == 0 and stmt.tokens and stmt.tokens[-1].is_whitespace:
    +            stmt.tokens.pop(-1)
    +        return stmt
    +
    +
    +class SpacesAroundOperatorsFilter:
    +    @staticmethod
    +    def _process(tlist):
    +
    +        ttypes = (T.Operator, T.Comparison)
    +        tidx, token = tlist.token_next_by(t=ttypes)
    +        while token:
    +            nidx, next_ = tlist.token_next(tidx, skip_ws=False)
    +            if next_ and next_.ttype != T.Whitespace:
    +                tlist.insert_after(tidx, sql.Token(T.Whitespace, ' '))
    +
    +            pidx, prev_ = tlist.token_prev(tidx, skip_ws=False)
    +            if prev_ and prev_.ttype != T.Whitespace:
    +                tlist.insert_before(tidx, sql.Token(T.Whitespace, ' '))
    +                tidx += 1  # has to shift since token inserted before it
    +
    +            # assert tlist.token_index(token) == tidx
    +            tidx, token = tlist.token_next_by(t=ttypes, idx=tidx)
    +
    +    def process(self, stmt):
    +        [self.process(sgroup) for sgroup in stmt.get_sublists()]
    +        SpacesAroundOperatorsFilter._process(stmt)
    +        return stmt
    +
    +
    +class StripTrailingSemicolonFilter:
    +
    +    def process(self, stmt):
    +        while stmt.tokens and (stmt.tokens[-1].is_whitespace
    +                               or stmt.tokens[-1].value == ';'):
    +            stmt.tokens.pop()
    +        return stmt
    +
    +
    +# ---------------------------
    +# postprocess
    +
    +class SerializerUnicode:
    +    @staticmethod
    +    def process(stmt):
    +        lines = split_unquoted_newlines(stmt)
    +        return '\n'.join(line.rstrip() for line in lines)
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/filters/output.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/filters/output.py
    new file mode 100644
    index 0000000..253537e
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/filters/output.py
    @@ -0,0 +1,122 @@
    +#
    +# Copyright (C) 2009-2020 the sqlparse authors and contributors
    +# 
    +#
    +# This module is part of python-sqlparse and is released under
    +# the BSD License: https://opensource.org/licenses/BSD-3-Clause
    +
    +from sqlparse import sql, tokens as T
    +
    +
    +class OutputFilter:
    +    varname_prefix = ''
    +
    +    def __init__(self, varname='sql'):
    +        self.varname = self.varname_prefix + varname
    +        self.count = 0
    +
    +    def _process(self, stream, varname, has_nl):
    +        raise NotImplementedError
    +
    +    def process(self, stmt):
    +        self.count += 1
    +        if self.count > 1:
    +            varname = '{f.varname}{f.count}'.format(f=self)
    +        else:
    +            varname = self.varname
    +
    +        has_nl = len(str(stmt).strip().splitlines()) > 1
    +        stmt.tokens = self._process(stmt.tokens, varname, has_nl)
    +        return stmt
    +
    +
    +class OutputPythonFilter(OutputFilter):
    +    def _process(self, stream, varname, has_nl):
    +        # SQL query assignation to varname
    +        if self.count > 1:
    +            yield sql.Token(T.Whitespace, '\n')
    +        yield sql.Token(T.Name, varname)
    +        yield sql.Token(T.Whitespace, ' ')
    +        yield sql.Token(T.Operator, '=')
    +        yield sql.Token(T.Whitespace, ' ')
    +        if has_nl:
    +            yield sql.Token(T.Operator, '(')
    +        yield sql.Token(T.Text, "'")
    +
    +        # Print the tokens on the quote
    +        for token in stream:
    +            # Token is a new line separator
    +            if token.is_whitespace and '\n' in token.value:
    +                # Close quote and add a new line
    +                yield sql.Token(T.Text, " '")
    +                yield sql.Token(T.Whitespace, '\n')
    +
    +                # Quote header on secondary lines
    +                yield sql.Token(T.Whitespace, ' ' * (len(varname) + 4))
    +                yield sql.Token(T.Text, "'")
    +
    +                # Indentation
    +                after_lb = token.value.split('\n', 1)[1]
    +                if after_lb:
    +                    yield sql.Token(T.Whitespace, after_lb)
    +                continue
    +
    +            # Token has escape chars
    +            elif "'" in token.value:
    +                token.value = token.value.replace("'", "\\'")
    +
    +            # Put the token
    +            yield sql.Token(T.Text, token.value)
    +
    +        # Close quote
    +        yield sql.Token(T.Text, "'")
    +        if has_nl:
    +            yield sql.Token(T.Operator, ')')
    +
    +
    +class OutputPHPFilter(OutputFilter):
    +    varname_prefix = '$'
    +
    +    def _process(self, stream, varname, has_nl):
    +        # SQL query assignation to varname (quote header)
    +        if self.count > 1:
    +            yield sql.Token(T.Whitespace, '\n')
    +        yield sql.Token(T.Name, varname)
    +        yield sql.Token(T.Whitespace, ' ')
    +        if has_nl:
    +            yield sql.Token(T.Whitespace, ' ')
    +        yield sql.Token(T.Operator, '=')
    +        yield sql.Token(T.Whitespace, ' ')
    +        yield sql.Token(T.Text, '"')
    +
    +        # Print the tokens on the quote
    +        for token in stream:
    +            # Token is a new line separator
    +            if token.is_whitespace and '\n' in token.value:
    +                # Close quote and add a new line
    +                yield sql.Token(T.Text, ' ";')
    +                yield sql.Token(T.Whitespace, '\n')
    +
    +                # Quote header on secondary lines
    +                yield sql.Token(T.Name, varname)
    +                yield sql.Token(T.Whitespace, ' ')
    +                yield sql.Token(T.Operator, '.=')
    +                yield sql.Token(T.Whitespace, ' ')
    +                yield sql.Token(T.Text, '"')
    +
    +                # Indentation
    +                after_lb = token.value.split('\n', 1)[1]
    +                if after_lb:
    +                    yield sql.Token(T.Whitespace, after_lb)
    +                continue
    +
    +            # Token has escape chars
    +            elif '"' in token.value:
    +                token.value = token.value.replace('"', '\\"')
    +
    +            # Put the token
    +            yield sql.Token(T.Text, token.value)
    +
    +        # Close quote
    +        yield sql.Token(T.Text, '"')
    +        yield sql.Token(T.Punctuation, ';')
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/filters/reindent.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/filters/reindent.py
    new file mode 100644
    index 0000000..e8cc3b5
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/filters/reindent.py
    @@ -0,0 +1,247 @@
    +#
    +# Copyright (C) 2009-2020 the sqlparse authors and contributors
    +# 
    +#
    +# This module is part of python-sqlparse and is released under
    +# the BSD License: https://opensource.org/licenses/BSD-3-Clause
    +
    +from sqlparse import sql, tokens as T
    +from sqlparse.utils import offset, indent
    +
    +
    +class ReindentFilter:
    +    def __init__(self, width=2, char=' ', wrap_after=0, n='\n',
    +                 comma_first=False, indent_after_first=False,
    +                 indent_columns=False, compact=False):
    +        self.n = n
    +        self.width = width
    +        self.char = char
    +        self.indent = 1 if indent_after_first else 0
    +        self.offset = 0
    +        self.wrap_after = wrap_after
    +        self.comma_first = comma_first
    +        self.indent_columns = indent_columns
    +        self.compact = compact
    +        self._curr_stmt = None
    +        self._last_stmt = None
    +        self._last_func = None
    +
    +    def _flatten_up_to_token(self, token):
    +        """Yields all tokens up to token but excluding current."""
    +        if token.is_group:
    +            token = next(token.flatten())
    +
    +        for t in self._curr_stmt.flatten():
    +            if t == token:
    +                break
    +            yield t
    +
    +    @property
    +    def leading_ws(self):
    +        return self.offset + self.indent * self.width
    +
    +    def _get_offset(self, token):
    +        raw = ''.join(map(str, self._flatten_up_to_token(token)))
    +        line = (raw or '\n').splitlines()[-1]
    +        # Now take current offset into account and return relative offset.
    +        return len(line) - len(self.char * self.leading_ws)
    +
    +    def nl(self, offset=0):
    +        return sql.Token(
    +            T.Whitespace,
    +            self.n + self.char * max(0, self.leading_ws + offset))
    +
    +    def _next_token(self, tlist, idx=-1):
    +        split_words = ('FROM', 'STRAIGHT_JOIN$', 'JOIN$', 'AND', 'OR',
    +                       'GROUP BY', 'ORDER BY', 'UNION', 'VALUES',
    +                       'SET', 'BETWEEN', 'EXCEPT', 'HAVING', 'LIMIT')
    +        m_split = T.Keyword, split_words, True
    +        tidx, token = tlist.token_next_by(m=m_split, idx=idx)
    +
    +        if token and token.normalized == 'BETWEEN':
    +            tidx, token = self._next_token(tlist, tidx)
    +
    +            if token and token.normalized == 'AND':
    +                tidx, token = self._next_token(tlist, tidx)
    +
    +        return tidx, token
    +
    +    def _split_kwds(self, tlist):
    +        tidx, token = self._next_token(tlist)
    +        while token:
    +            pidx, prev_ = tlist.token_prev(tidx, skip_ws=False)
    +            uprev = str(prev_)
    +
    +            if prev_ and prev_.is_whitespace:
    +                del tlist.tokens[pidx]
    +                tidx -= 1
    +
    +            if not (uprev.endswith('\n') or uprev.endswith('\r')):
    +                tlist.insert_before(tidx, self.nl())
    +                tidx += 1
    +
    +            tidx, token = self._next_token(tlist, tidx)
    +
    +    def _split_statements(self, tlist):
    +        ttypes = T.Keyword.DML, T.Keyword.DDL
    +        tidx, token = tlist.token_next_by(t=ttypes)
    +        while token:
    +            pidx, prev_ = tlist.token_prev(tidx, skip_ws=False)
    +            if prev_ and prev_.is_whitespace:
    +                del tlist.tokens[pidx]
    +                tidx -= 1
    +            # only break if it's not the first token
    +            if prev_:
    +                tlist.insert_before(tidx, self.nl())
    +                tidx += 1
    +            tidx, token = tlist.token_next_by(t=ttypes, idx=tidx)
    +
    +    def _process(self, tlist):
    +        func_name = f'_process_{type(tlist).__name__}'
    +        func = getattr(self, func_name.lower(), self._process_default)
    +        func(tlist)
    +
    +    def _process_where(self, tlist):
    +        tidx, token = tlist.token_next_by(m=(T.Keyword, 'WHERE'))
    +        if not token:
    +            return
    +        # issue121, errors in statement fixed??
    +        tlist.insert_before(tidx, self.nl())
    +        with indent(self):
    +            self._process_default(tlist)
    +
    +    def _process_parenthesis(self, tlist):
    +        ttypes = T.Keyword.DML, T.Keyword.DDL
    +        _, is_dml_dll = tlist.token_next_by(t=ttypes)
    +        fidx, first = tlist.token_next_by(m=sql.Parenthesis.M_OPEN)
    +        if first is None:
    +            return
    +
    +        with indent(self, 1 if is_dml_dll else 0):
    +            tlist.tokens.insert(0, self.nl()) if is_dml_dll else None
    +            with offset(self, self._get_offset(first) + 1):
    +                self._process_default(tlist, not is_dml_dll)
    +
    +    def _process_function(self, tlist):
    +        self._last_func = tlist[0]
    +        self._process_default(tlist)
    +
    +    def _process_identifierlist(self, tlist):
    +        identifiers = list(tlist.get_identifiers())
    +        if self.indent_columns:
    +            first = next(identifiers[0].flatten())
    +            num_offset = 1 if self.char == '\t' else self.width
    +        else:
    +            first = next(identifiers.pop(0).flatten())
    +            num_offset = 1 if self.char == '\t' else self._get_offset(first)
    +
    +        if not tlist.within(sql.Function) and not tlist.within(sql.Values):
    +            with offset(self, num_offset):
    +                position = 0
    +                for token in identifiers:
    +                    # Add 1 for the "," separator
    +                    position += len(token.value) + 1
    +                    if position > (self.wrap_after - self.offset):
    +                        adjust = 0
    +                        if self.comma_first:
    +                            adjust = -2
    +                            _, comma = tlist.token_prev(
    +                                tlist.token_index(token))
    +                            if comma is None:
    +                                continue
    +                            token = comma
    +                        tlist.insert_before(token, self.nl(offset=adjust))
    +                        if self.comma_first:
    +                            _, ws = tlist.token_next(
    +                                tlist.token_index(token), skip_ws=False)
    +                            if (ws is not None
    +                                    and ws.ttype is not T.Text.Whitespace):
    +                                tlist.insert_after(
    +                                    token, sql.Token(T.Whitespace, ' '))
    +                        position = 0
    +        else:
    +            # ensure whitespace
    +            for token in tlist:
    +                _, next_ws = tlist.token_next(
    +                    tlist.token_index(token), skip_ws=False)
    +                if token.value == ',' and not next_ws.is_whitespace:
    +                    tlist.insert_after(
    +                        token, sql.Token(T.Whitespace, ' '))
    +
    +            end_at = self.offset + sum(len(i.value) + 1 for i in identifiers)
    +            adjusted_offset = 0
    +            if (self.wrap_after > 0
    +                    and end_at > (self.wrap_after - self.offset)
    +                    and self._last_func):
    +                adjusted_offset = -len(self._last_func.value) - 1
    +
    +            with offset(self, adjusted_offset), indent(self):
    +                if adjusted_offset < 0:
    +                    tlist.insert_before(identifiers[0], self.nl())
    +                position = 0
    +                for token in identifiers:
    +                    # Add 1 for the "," separator
    +                    position += len(token.value) + 1
    +                    if (self.wrap_after > 0
    +                            and position > (self.wrap_after - self.offset)):
    +                        adjust = 0
    +                        tlist.insert_before(token, self.nl(offset=adjust))
    +                        position = 0
    +        self._process_default(tlist)
    +
    +    def _process_case(self, tlist):
    +        iterable = iter(tlist.get_cases())
    +        cond, _ = next(iterable)
    +        first = next(cond[0].flatten())
    +
    +        with offset(self, self._get_offset(tlist[0])):
    +            with offset(self, self._get_offset(first)):
    +                for cond, value in iterable:
    +                    str_cond = ''.join(str(x) for x in cond or [])
    +                    str_value = ''.join(str(x) for x in value)
    +                    end_pos = self.offset + 1 + len(str_cond) + len(str_value)
    +                    if (not self.compact and end_pos > self.wrap_after):
    +                        token = value[0] if cond is None else cond[0]
    +                        tlist.insert_before(token, self.nl())
    +
    +                # Line breaks on group level are done. let's add an offset of
    +                # len "when ", "then ", "else "
    +                with offset(self, len("WHEN ")):
    +                    self._process_default(tlist)
    +            end_idx, end = tlist.token_next_by(m=sql.Case.M_CLOSE)
    +            if end_idx is not None and not self.compact:
    +                tlist.insert_before(end_idx, self.nl())
    +
    +    def _process_values(self, tlist):
    +        tlist.insert_before(0, self.nl())
    +        tidx, token = tlist.token_next_by(i=sql.Parenthesis)
    +        first_token = token
    +        while token:
    +            ptidx, ptoken = tlist.token_next_by(m=(T.Punctuation, ','),
    +                                                idx=tidx)
    +            if ptoken:
    +                if self.comma_first:
    +                    adjust = -2
    +                    offset = self._get_offset(first_token) + adjust
    +                    tlist.insert_before(ptoken, self.nl(offset))
    +                else:
    +                    tlist.insert_after(ptoken,
    +                                       self.nl(self._get_offset(token)))
    +            tidx, token = tlist.token_next_by(i=sql.Parenthesis, idx=tidx)
    +
    +    def _process_default(self, tlist, stmts=True):
    +        self._split_statements(tlist) if stmts else None
    +        self._split_kwds(tlist)
    +        for sgroup in tlist.get_sublists():
    +            self._process(sgroup)
    +
    +    def process(self, stmt):
    +        self._curr_stmt = stmt
    +        self._process(stmt)
    +
    +        if self._last_stmt is not None:
    +            nl = '\n' if str(self._last_stmt).endswith('\n') else '\n\n'
    +            stmt.tokens.insert(0, sql.Token(T.Whitespace, nl))
    +
    +        self._last_stmt = stmt
    +        return stmt
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/filters/right_margin.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/filters/right_margin.py
    new file mode 100644
    index 0000000..5a8e6f8
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/filters/right_margin.py
    @@ -0,0 +1,48 @@
    +#
    +# Copyright (C) 2009-2020 the sqlparse authors and contributors
    +# 
    +#
    +# This module is part of python-sqlparse and is released under
    +# the BSD License: https://opensource.org/licenses/BSD-3-Clause
    +
    +import re
    +
    +from sqlparse import sql, tokens as T
    +
    +
    +# FIXME: Doesn't work
    +class RightMarginFilter:
    +    keep_together = (
    +        # sql.TypeCast, sql.Identifier, sql.Alias,
    +    )
    +
    +    def __init__(self, width=79):
    +        self.width = width
    +        self.line = ''
    +
    +    def _process(self, group, stream):
    +        for token in stream:
    +            if token.is_whitespace and '\n' in token.value:
    +                if token.value.endswith('\n'):
    +                    self.line = ''
    +                else:
    +                    self.line = token.value.splitlines()[-1]
    +            elif token.is_group and type(token) not in self.keep_together:
    +                token.tokens = self._process(token, token.tokens)
    +            else:
    +                val = str(token)
    +                if len(self.line) + len(val) > self.width:
    +                    match = re.search(r'^ +', self.line)
    +                    if match is not None:
    +                        indent = match.group()
    +                    else:
    +                        indent = ''
    +                    yield sql.Token(T.Whitespace, f'\n{indent}')
    +                    self.line = indent
    +                self.line += val
    +            yield token
    +
    +    def process(self, group):
    +        # return
    +        # group.tokens = self._process(group, group.tokens)
    +        raise NotImplementedError
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/filters/tokens.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/filters/tokens.py
    new file mode 100644
    index 0000000..cc00a84
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/filters/tokens.py
    @@ -0,0 +1,59 @@
    +#
    +# Copyright (C) 2009-2020 the sqlparse authors and contributors
    +# 
    +#
    +# This module is part of python-sqlparse and is released under
    +# the BSD License: https://opensource.org/licenses/BSD-3-Clause
    +
    +from sqlparse import tokens as T
    +
    +
    +class _CaseFilter:
    +    ttype = None
    +
    +    def __init__(self, case=None):
    +        case = case or 'upper'
    +        self.convert = getattr(str, case)
    +
    +    def process(self, stream):
    +        for ttype, value in stream:
    +            if ttype in self.ttype:
    +                value = self.convert(value)
    +            yield ttype, value
    +
    +
    +class KeywordCaseFilter(_CaseFilter):
    +    ttype = T.Keyword
    +
    +
    +class IdentifierCaseFilter(_CaseFilter):
    +    ttype = T.Name, T.String.Symbol
    +
    +    def process(self, stream):
    +        for ttype, value in stream:
    +            if ttype in self.ttype and value.strip()[0] != '"':
    +                value = self.convert(value)
    +            yield ttype, value
    +
    +
    +class TruncateStringFilter:
    +    def __init__(self, width, char):
    +        self.width = width
    +        self.char = char
    +
    +    def process(self, stream):
    +        for ttype, value in stream:
    +            if ttype != T.Literal.String.Single:
    +                yield ttype, value
    +                continue
    +
    +            if value[:2] == "''":
    +                inner = value[2:-2]
    +                quote = "''"
    +            else:
    +                inner = value[1:-1]
    +                quote = "'"
    +
    +            if len(inner) > self.width:
    +                value = ''.join((quote, inner[:self.width], self.char, quote))
    +            yield ttype, value
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/formatter.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/formatter.py
    new file mode 100644
    index 0000000..72f2c19
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/formatter.py
    @@ -0,0 +1,204 @@
    +#
    +# Copyright (C) 2009-2020 the sqlparse authors and contributors
    +# 
    +#
    +# This module is part of python-sqlparse and is released under
    +# the BSD License: https://opensource.org/licenses/BSD-3-Clause
    +
    +"""SQL formatter"""
    +
    +from sqlparse import filters
    +from sqlparse.exceptions import SQLParseError
    +
    +
    +def validate_options(options):  # noqa: C901
    +    """Validates options."""
    +    kwcase = options.get('keyword_case')
    +    if kwcase not in [None, 'upper', 'lower', 'capitalize']:
    +        raise SQLParseError('Invalid value for keyword_case: '
    +                            '{!r}'.format(kwcase))
    +
    +    idcase = options.get('identifier_case')
    +    if idcase not in [None, 'upper', 'lower', 'capitalize']:
    +        raise SQLParseError('Invalid value for identifier_case: '
    +                            '{!r}'.format(idcase))
    +
    +    ofrmt = options.get('output_format')
    +    if ofrmt not in [None, 'sql', 'python', 'php']:
    +        raise SQLParseError('Unknown output format: '
    +                            '{!r}'.format(ofrmt))
    +
    +    strip_comments = options.get('strip_comments', False)
    +    if strip_comments not in [True, False]:
    +        raise SQLParseError('Invalid value for strip_comments: '
    +                            '{!r}'.format(strip_comments))
    +
    +    space_around_operators = options.get('use_space_around_operators', False)
    +    if space_around_operators not in [True, False]:
    +        raise SQLParseError('Invalid value for use_space_around_operators: '
    +                            '{!r}'.format(space_around_operators))
    +
    +    strip_ws = options.get('strip_whitespace', False)
    +    if strip_ws not in [True, False]:
    +        raise SQLParseError('Invalid value for strip_whitespace: '
    +                            '{!r}'.format(strip_ws))
    +
    +    truncate_strings = options.get('truncate_strings')
    +    if truncate_strings is not None:
    +        try:
    +            truncate_strings = int(truncate_strings)
    +        except (ValueError, TypeError):
    +            raise SQLParseError('Invalid value for truncate_strings: '
    +                                '{!r}'.format(truncate_strings))
    +        if truncate_strings <= 1:
    +            raise SQLParseError('Invalid value for truncate_strings: '
    +                                '{!r}'.format(truncate_strings))
    +        options['truncate_strings'] = truncate_strings
    +        options['truncate_char'] = options.get('truncate_char', '[...]')
    +
    +    indent_columns = options.get('indent_columns', False)
    +    if indent_columns not in [True, False]:
    +        raise SQLParseError('Invalid value for indent_columns: '
    +                            '{!r}'.format(indent_columns))
    +    elif indent_columns:
    +        options['reindent'] = True  # enforce reindent
    +    options['indent_columns'] = indent_columns
    +
    +    reindent = options.get('reindent', False)
    +    if reindent not in [True, False]:
    +        raise SQLParseError('Invalid value for reindent: '
    +                            '{!r}'.format(reindent))
    +    elif reindent:
    +        options['strip_whitespace'] = True
    +
    +    reindent_aligned = options.get('reindent_aligned', False)
    +    if reindent_aligned not in [True, False]:
    +        raise SQLParseError('Invalid value for reindent_aligned: '
    +                            '{!r}'.format(reindent))
    +    elif reindent_aligned:
    +        options['strip_whitespace'] = True
    +
    +    indent_after_first = options.get('indent_after_first', False)
    +    if indent_after_first not in [True, False]:
    +        raise SQLParseError('Invalid value for indent_after_first: '
    +                            '{!r}'.format(indent_after_first))
    +    options['indent_after_first'] = indent_after_first
    +
    +    indent_tabs = options.get('indent_tabs', False)
    +    if indent_tabs not in [True, False]:
    +        raise SQLParseError('Invalid value for indent_tabs: '
    +                            '{!r}'.format(indent_tabs))
    +    elif indent_tabs:
    +        options['indent_char'] = '\t'
    +    else:
    +        options['indent_char'] = ' '
    +
    +    indent_width = options.get('indent_width', 2)
    +    try:
    +        indent_width = int(indent_width)
    +    except (TypeError, ValueError):
    +        raise SQLParseError('indent_width requires an integer')
    +    if indent_width < 1:
    +        raise SQLParseError('indent_width requires a positive integer')
    +    options['indent_width'] = indent_width
    +
    +    wrap_after = options.get('wrap_after', 0)
    +    try:
    +        wrap_after = int(wrap_after)
    +    except (TypeError, ValueError):
    +        raise SQLParseError('wrap_after requires an integer')
    +    if wrap_after < 0:
    +        raise SQLParseError('wrap_after requires a positive integer')
    +    options['wrap_after'] = wrap_after
    +
    +    comma_first = options.get('comma_first', False)
    +    if comma_first not in [True, False]:
    +        raise SQLParseError('comma_first requires a boolean value')
    +    options['comma_first'] = comma_first
    +
    +    compact = options.get('compact', False)
    +    if compact not in [True, False]:
    +        raise SQLParseError('compact requires a boolean value')
    +    options['compact'] = compact
    +
    +    right_margin = options.get('right_margin')
    +    if right_margin is not None:
    +        try:
    +            right_margin = int(right_margin)
    +        except (TypeError, ValueError):
    +            raise SQLParseError('right_margin requires an integer')
    +        if right_margin < 10:
    +            raise SQLParseError('right_margin requires an integer > 10')
    +    options['right_margin'] = right_margin
    +
    +    return options
    +
    +
    +def build_filter_stack(stack, options):
    +    """Setup and return a filter stack.
    +
    +    Args:
    +      stack: :class:`~sqlparse.filters.FilterStack` instance
    +      options: Dictionary with options validated by validate_options.
    +    """
    +    # Token filter
    +    if options.get('keyword_case'):
    +        stack.preprocess.append(
    +            filters.KeywordCaseFilter(options['keyword_case']))
    +
    +    if options.get('identifier_case'):
    +        stack.preprocess.append(
    +            filters.IdentifierCaseFilter(options['identifier_case']))
    +
    +    if options.get('truncate_strings'):
    +        stack.preprocess.append(filters.TruncateStringFilter(
    +            width=options['truncate_strings'], char=options['truncate_char']))
    +
    +    if options.get('use_space_around_operators', False):
    +        stack.enable_grouping()
    +        stack.stmtprocess.append(filters.SpacesAroundOperatorsFilter())
    +
    +    # After grouping
    +    if options.get('strip_comments'):
    +        stack.enable_grouping()
    +        stack.stmtprocess.append(filters.StripCommentsFilter())
    +
    +    if options.get('strip_whitespace') or options.get('reindent'):
    +        stack.enable_grouping()
    +        stack.stmtprocess.append(filters.StripWhitespaceFilter())
    +
    +    if options.get('reindent'):
    +        stack.enable_grouping()
    +        stack.stmtprocess.append(
    +            filters.ReindentFilter(
    +                char=options['indent_char'],
    +                width=options['indent_width'],
    +                indent_after_first=options['indent_after_first'],
    +                indent_columns=options['indent_columns'],
    +                wrap_after=options['wrap_after'],
    +                comma_first=options['comma_first'],
    +                compact=options['compact'],))
    +
    +    if options.get('reindent_aligned', False):
    +        stack.enable_grouping()
    +        stack.stmtprocess.append(
    +            filters.AlignedIndentFilter(char=options['indent_char']))
    +
    +    if options.get('right_margin'):
    +        stack.enable_grouping()
    +        stack.stmtprocess.append(
    +            filters.RightMarginFilter(width=options['right_margin']))
    +
    +    # Serializer
    +    if options.get('output_format'):
    +        frmt = options['output_format']
    +        if frmt.lower() == 'php':
    +            fltr = filters.OutputPHPFilter()
    +        elif frmt.lower() == 'python':
    +            fltr = filters.OutputPythonFilter()
    +        else:
    +            fltr = None
    +        if fltr is not None:
    +            stack.postprocess.append(fltr)
    +
    +    return stack
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/keywords.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/keywords.py
    new file mode 100644
    index 0000000..874431f
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/keywords.py
    @@ -0,0 +1,1005 @@
    +#
    +# Copyright (C) 2009-2020 the sqlparse authors and contributors
    +# 
    +#
    +# This module is part of python-sqlparse and is released under
    +# the BSD License: https://opensource.org/licenses/BSD-3-Clause
    +
    +from sqlparse import tokens
    +
    +# object() only supports "is" and is useful as a marker
    +# use this marker to specify that the given regex in SQL_REGEX
    +# shall be processed further through a lookup in the KEYWORDS dictionaries
    +PROCESS_AS_KEYWORD = object()
    +
    +
    +SQL_REGEX = [
    +    (r'(--|# )\+.*?(\r\n|\r|\n|$)', tokens.Comment.Single.Hint),
    +    (r'/\*\+[\s\S]*?\*/', tokens.Comment.Multiline.Hint),
    +
    +    (r'(--|# ).*?(\r\n|\r|\n|$)', tokens.Comment.Single),
    +    (r'/\*[\s\S]*?\*/', tokens.Comment.Multiline),
    +
    +    (r'(\r\n|\r|\n)', tokens.Newline),
    +    (r'\s+?', tokens.Whitespace),
    +
    +    (r':=', tokens.Assignment),
    +    (r'::', tokens.Punctuation),
    +
    +    (r'\*', tokens.Wildcard),
    +
    +    (r"`(``|[^`])*`", tokens.Name),
    +    (r"´(´´|[^´])*´", tokens.Name),
    +    (r'((?>?|#>>?|@>|<@|\?\|?|\?&|\-|#\-)', tokens.Operator),
    +    (r'[<>=~!]+', tokens.Operator.Comparison),
    +    (r'[+/@#%^&|^-]+', tokens.Operator),
    +]
    +
    +KEYWORDS = {
    +    'ABORT': tokens.Keyword,
    +    'ABS': tokens.Keyword,
    +    'ABSOLUTE': tokens.Keyword,
    +    'ACCESS': tokens.Keyword,
    +    'ADA': tokens.Keyword,
    +    'ADD': tokens.Keyword,
    +    'ADMIN': tokens.Keyword,
    +    'AFTER': tokens.Keyword,
    +    'AGGREGATE': tokens.Keyword,
    +    'ALIAS': tokens.Keyword,
    +    'ALL': tokens.Keyword,
    +    'ALLOCATE': tokens.Keyword,
    +    'ANALYSE': tokens.Keyword,
    +    'ANALYZE': tokens.Keyword,
    +    'ANY': tokens.Keyword,
    +    'ARRAYLEN': tokens.Keyword,
    +    'ARE': tokens.Keyword,
    +    'ASENSITIVE': tokens.Keyword,
    +    'ASSERTION': tokens.Keyword,
    +    'ASSIGNMENT': tokens.Keyword,
    +    'ASYMMETRIC': tokens.Keyword,
    +    'AT': tokens.Keyword,
    +    'ATOMIC': tokens.Keyword,
    +    'AUDIT': tokens.Keyword,
    +    'AUTHORIZATION': tokens.Keyword,
    +    'AUTO_INCREMENT': tokens.Keyword,
    +    'AVG': tokens.Keyword,
    +
    +    'BACKWARD': tokens.Keyword,
    +    'BEFORE': tokens.Keyword,
    +    'BEGIN': tokens.Keyword,
    +    'BETWEEN': tokens.Keyword,
    +    'BITVAR': tokens.Keyword,
    +    'BIT_LENGTH': tokens.Keyword,
    +    'BOTH': tokens.Keyword,
    +    'BREADTH': tokens.Keyword,
    +
    +    # 'C': tokens.Keyword,  # most likely this is an alias
    +    'CACHE': tokens.Keyword,
    +    'CALL': tokens.Keyword,
    +    'CALLED': tokens.Keyword,
    +    'CARDINALITY': tokens.Keyword,
    +    'CASCADE': tokens.Keyword,
    +    'CASCADED': tokens.Keyword,
    +    'CAST': tokens.Keyword,
    +    'CATALOG': tokens.Keyword,
    +    'CATALOG_NAME': tokens.Keyword,
    +    'CHAIN': tokens.Keyword,
    +    'CHARACTERISTICS': tokens.Keyword,
    +    'CHARACTER_LENGTH': tokens.Keyword,
    +    'CHARACTER_SET_CATALOG': tokens.Keyword,
    +    'CHARACTER_SET_NAME': tokens.Keyword,
    +    'CHARACTER_SET_SCHEMA': tokens.Keyword,
    +    'CHAR_LENGTH': tokens.Keyword,
    +    'CHARSET': tokens.Keyword,
    +    'CHECK': tokens.Keyword,
    +    'CHECKED': tokens.Keyword,
    +    'CHECKPOINT': tokens.Keyword,
    +    'CLASS': tokens.Keyword,
    +    'CLASS_ORIGIN': tokens.Keyword,
    +    'CLOB': tokens.Keyword,
    +    'CLOSE': tokens.Keyword,
    +    'CLUSTER': tokens.Keyword,
    +    'COALESCE': tokens.Keyword,
    +    'COBOL': tokens.Keyword,
    +    'COLLATE': tokens.Keyword,
    +    'COLLATION': tokens.Keyword,
    +    'COLLATION_CATALOG': tokens.Keyword,
    +    'COLLATION_NAME': tokens.Keyword,
    +    'COLLATION_SCHEMA': tokens.Keyword,
    +    'COLLECT': tokens.Keyword,
    +    'COLUMN': tokens.Keyword,
    +    'COLUMN_NAME': tokens.Keyword,
    +    'COMPRESS': tokens.Keyword,
    +    'COMMAND_FUNCTION': tokens.Keyword,
    +    'COMMAND_FUNCTION_CODE': tokens.Keyword,
    +    'COMMENT': tokens.Keyword,
    +    'COMMIT': tokens.Keyword.DML,
    +    'COMMITTED': tokens.Keyword,
    +    'COMPLETION': tokens.Keyword,
    +    'CONCURRENTLY': tokens.Keyword,
    +    'CONDITION_NUMBER': tokens.Keyword,
    +    'CONNECT': tokens.Keyword,
    +    'CONNECTION': tokens.Keyword,
    +    'CONNECTION_NAME': tokens.Keyword,
    +    'CONSTRAINT': tokens.Keyword,
    +    'CONSTRAINTS': tokens.Keyword,
    +    'CONSTRAINT_CATALOG': tokens.Keyword,
    +    'CONSTRAINT_NAME': tokens.Keyword,
    +    'CONSTRAINT_SCHEMA': tokens.Keyword,
    +    'CONSTRUCTOR': tokens.Keyword,
    +    'CONTAINS': tokens.Keyword,
    +    'CONTINUE': tokens.Keyword,
    +    'CONVERSION': tokens.Keyword,
    +    'CONVERT': tokens.Keyword,
    +    'COPY': tokens.Keyword,
    +    'CORRESPONDING': tokens.Keyword,
    +    'COUNT': tokens.Keyword,
    +    'CREATEDB': tokens.Keyword,
    +    'CREATEUSER': tokens.Keyword,
    +    'CROSS': tokens.Keyword,
    +    'CUBE': tokens.Keyword,
    +    'CURRENT': tokens.Keyword,
    +    'CURRENT_DATE': tokens.Keyword,
    +    'CURRENT_PATH': tokens.Keyword,
    +    'CURRENT_ROLE': tokens.Keyword,
    +    'CURRENT_TIME': tokens.Keyword,
    +    'CURRENT_TIMESTAMP': tokens.Keyword,
    +    'CURRENT_USER': tokens.Keyword,
    +    'CURSOR': tokens.Keyword,
    +    'CURSOR_NAME': tokens.Keyword,
    +    'CYCLE': tokens.Keyword,
    +
    +    'DATA': tokens.Keyword,
    +    'DATABASE': tokens.Keyword,
    +    'DATETIME_INTERVAL_CODE': tokens.Keyword,
    +    'DATETIME_INTERVAL_PRECISION': tokens.Keyword,
    +    'DAY': tokens.Keyword,
    +    'DEALLOCATE': tokens.Keyword,
    +    'DECLARE': tokens.Keyword,
    +    'DEFAULT': tokens.Keyword,
    +    'DEFAULTS': tokens.Keyword,
    +    'DEFERRABLE': tokens.Keyword,
    +    'DEFERRED': tokens.Keyword,
    +    'DEFINED': tokens.Keyword,
    +    'DEFINER': tokens.Keyword,
    +    'DELIMITER': tokens.Keyword,
    +    'DELIMITERS': tokens.Keyword,
    +    'DEREF': tokens.Keyword,
    +    'DESCRIBE': tokens.Keyword,
    +    'DESCRIPTOR': tokens.Keyword,
    +    'DESTROY': tokens.Keyword,
    +    'DESTRUCTOR': tokens.Keyword,
    +    'DETERMINISTIC': tokens.Keyword,
    +    'DIAGNOSTICS': tokens.Keyword,
    +    'DICTIONARY': tokens.Keyword,
    +    'DISABLE': tokens.Keyword,
    +    'DISCONNECT': tokens.Keyword,
    +    'DISPATCH': tokens.Keyword,
    +    'DIV': tokens.Operator,
    +    'DO': tokens.Keyword,
    +    'DOMAIN': tokens.Keyword,
    +    'DYNAMIC': tokens.Keyword,
    +    'DYNAMIC_FUNCTION': tokens.Keyword,
    +    'DYNAMIC_FUNCTION_CODE': tokens.Keyword,
    +
    +    'EACH': tokens.Keyword,
    +    'ENABLE': tokens.Keyword,
    +    'ENCODING': tokens.Keyword,
    +    'ENCRYPTED': tokens.Keyword,
    +    'END-EXEC': tokens.Keyword,
    +    'ENGINE': tokens.Keyword,
    +    'EQUALS': tokens.Keyword,
    +    'ESCAPE': tokens.Keyword,
    +    'EVERY': tokens.Keyword,
    +    'EXCEPT': tokens.Keyword,
    +    'EXCEPTION': tokens.Keyword,
    +    'EXCLUDING': tokens.Keyword,
    +    'EXCLUSIVE': tokens.Keyword,
    +    'EXEC': tokens.Keyword,
    +    'EXECUTE': tokens.Keyword,
    +    'EXISTING': tokens.Keyword,
    +    'EXISTS': tokens.Keyword,
    +    'EXPLAIN': tokens.Keyword,
    +    'EXTERNAL': tokens.Keyword,
    +    'EXTRACT': tokens.Keyword,
    +
    +    'FALSE': tokens.Keyword,
    +    'FETCH': tokens.Keyword,
    +    'FILE': tokens.Keyword,
    +    'FINAL': tokens.Keyword,
    +    'FIRST': tokens.Keyword,
    +    'FORCE': tokens.Keyword,
    +    'FOREACH': tokens.Keyword,
    +    'FOREIGN': tokens.Keyword,
    +    'FORTRAN': tokens.Keyword,
    +    'FORWARD': tokens.Keyword,
    +    'FOUND': tokens.Keyword,
    +    'FREE': tokens.Keyword,
    +    'FREEZE': tokens.Keyword,
    +    'FULL': tokens.Keyword,
    +    'FUNCTION': tokens.Keyword,
    +
    +    # 'G': tokens.Keyword,
    +    'GENERAL': tokens.Keyword,
    +    'GENERATED': tokens.Keyword,
    +    'GET': tokens.Keyword,
    +    'GLOBAL': tokens.Keyword,
    +    'GO': tokens.Keyword,
    +    'GOTO': tokens.Keyword,
    +    'GRANTED': tokens.Keyword,
    +    'GROUPING': tokens.Keyword,
    +
    +    'HAVING': tokens.Keyword,
    +    'HIERARCHY': tokens.Keyword,
    +    'HOLD': tokens.Keyword,
    +    'HOUR': tokens.Keyword,
    +    'HOST': tokens.Keyword,
    +
    +    'IDENTIFIED': tokens.Keyword,
    +    'IDENTITY': tokens.Keyword,
    +    'IGNORE': tokens.Keyword,
    +    'ILIKE': tokens.Keyword,
    +    'IMMEDIATE': tokens.Keyword,
    +    'IMMUTABLE': tokens.Keyword,
    +
    +    'IMPLEMENTATION': tokens.Keyword,
    +    'IMPLICIT': tokens.Keyword,
    +    'INCLUDING': tokens.Keyword,
    +    'INCREMENT': tokens.Keyword,
    +    'INDEX': tokens.Keyword,
    +
    +    'INDICATOR': tokens.Keyword,
    +    'INFIX': tokens.Keyword,
    +    'INHERITS': tokens.Keyword,
    +    'INITIAL': tokens.Keyword,
    +    'INITIALIZE': tokens.Keyword,
    +    'INITIALLY': tokens.Keyword,
    +    'INOUT': tokens.Keyword,
    +    'INPUT': tokens.Keyword,
    +    'INSENSITIVE': tokens.Keyword,
    +    'INSTANTIABLE': tokens.Keyword,
    +    'INSTEAD': tokens.Keyword,
    +    'INTERSECT': tokens.Keyword,
    +    'INTO': tokens.Keyword,
    +    'INVOKER': tokens.Keyword,
    +    'IS': tokens.Keyword,
    +    'ISNULL': tokens.Keyword,
    +    'ISOLATION': tokens.Keyword,
    +    'ITERATE': tokens.Keyword,
    +
    +    # 'K': tokens.Keyword,
    +    'KEY': tokens.Keyword,
    +    'KEY_MEMBER': tokens.Keyword,
    +    'KEY_TYPE': tokens.Keyword,
    +
    +    'LANCOMPILER': tokens.Keyword,
    +    'LANGUAGE': tokens.Keyword,
    +    'LARGE': tokens.Keyword,
    +    'LAST': tokens.Keyword,
    +    'LATERAL': tokens.Keyword,
    +    'LEADING': tokens.Keyword,
    +    'LENGTH': tokens.Keyword,
    +    'LESS': tokens.Keyword,
    +    'LEVEL': tokens.Keyword,
    +    'LIMIT': tokens.Keyword,
    +    'LISTEN': tokens.Keyword,
    +    'LOAD': tokens.Keyword,
    +    'LOCAL': tokens.Keyword,
    +    'LOCALTIME': tokens.Keyword,
    +    'LOCALTIMESTAMP': tokens.Keyword,
    +    'LOCATION': tokens.Keyword,
    +    'LOCATOR': tokens.Keyword,
    +    'LOCK': tokens.Keyword,
    +    'LOWER': tokens.Keyword,
    +
    +    # 'M': tokens.Keyword,
    +    'MAP': tokens.Keyword,
    +    'MATCH': tokens.Keyword,
    +    'MAXEXTENTS': tokens.Keyword,
    +    'MAXVALUE': tokens.Keyword,
    +    'MESSAGE_LENGTH': tokens.Keyword,
    +    'MESSAGE_OCTET_LENGTH': tokens.Keyword,
    +    'MESSAGE_TEXT': tokens.Keyword,
    +    'METHOD': tokens.Keyword,
    +    'MINUTE': tokens.Keyword,
    +    'MINUS': tokens.Keyword,
    +    'MINVALUE': tokens.Keyword,
    +    'MOD': tokens.Keyword,
    +    'MODE': tokens.Keyword,
    +    'MODIFIES': tokens.Keyword,
    +    'MODIFY': tokens.Keyword,
    +    'MONTH': tokens.Keyword,
    +    'MORE': tokens.Keyword,
    +    'MOVE': tokens.Keyword,
    +    'MUMPS': tokens.Keyword,
    +
    +    'NAMES': tokens.Keyword,
    +    'NATIONAL': tokens.Keyword,
    +    'NATURAL': tokens.Keyword,
    +    'NCHAR': tokens.Keyword,
    +    'NCLOB': tokens.Keyword,
    +    'NEW': tokens.Keyword,
    +    'NEXT': tokens.Keyword,
    +    'NO': tokens.Keyword,
    +    'NOAUDIT': tokens.Keyword,
    +    'NOCOMPRESS': tokens.Keyword,
    +    'NOCREATEDB': tokens.Keyword,
    +    'NOCREATEUSER': tokens.Keyword,
    +    'NONE': tokens.Keyword,
    +    'NOT': tokens.Keyword,
    +    'NOTFOUND': tokens.Keyword,
    +    'NOTHING': tokens.Keyword,
    +    'NOTIFY': tokens.Keyword,
    +    'NOTNULL': tokens.Keyword,
    +    'NOWAIT': tokens.Keyword,
    +    'NULL': tokens.Keyword,
    +    'NULLABLE': tokens.Keyword,
    +    'NULLIF': tokens.Keyword,
    +
    +    'OBJECT': tokens.Keyword,
    +    'OCTET_LENGTH': tokens.Keyword,
    +    'OF': tokens.Keyword,
    +    'OFF': tokens.Keyword,
    +    'OFFLINE': tokens.Keyword,
    +    'OFFSET': tokens.Keyword,
    +    'OIDS': tokens.Keyword,
    +    'OLD': tokens.Keyword,
    +    'ONLINE': tokens.Keyword,
    +    'ONLY': tokens.Keyword,
    +    'OPEN': tokens.Keyword,
    +    'OPERATION': tokens.Keyword,
    +    'OPERATOR': tokens.Keyword,
    +    'OPTION': tokens.Keyword,
    +    'OPTIONS': tokens.Keyword,
    +    'ORDINALITY': tokens.Keyword,
    +    'OUT': tokens.Keyword,
    +    'OUTPUT': tokens.Keyword,
    +    'OVERLAPS': tokens.Keyword,
    +    'OVERLAY': tokens.Keyword,
    +    'OVERRIDING': tokens.Keyword,
    +    'OWNER': tokens.Keyword,
    +
    +    'QUARTER': tokens.Keyword,
    +
    +    'PAD': tokens.Keyword,
    +    'PARAMETER': tokens.Keyword,
    +    'PARAMETERS': tokens.Keyword,
    +    'PARAMETER_MODE': tokens.Keyword,
    +    'PARAMETER_NAME': tokens.Keyword,
    +    'PARAMETER_ORDINAL_POSITION': tokens.Keyword,
    +    'PARAMETER_SPECIFIC_CATALOG': tokens.Keyword,
    +    'PARAMETER_SPECIFIC_NAME': tokens.Keyword,
    +    'PARAMETER_SPECIFIC_SCHEMA': tokens.Keyword,
    +    'PARTIAL': tokens.Keyword,
    +    'PASCAL': tokens.Keyword,
    +    'PCTFREE': tokens.Keyword,
    +    'PENDANT': tokens.Keyword,
    +    'PLACING': tokens.Keyword,
    +    'PLI': tokens.Keyword,
    +    'POSITION': tokens.Keyword,
    +    'POSTFIX': tokens.Keyword,
    +    'PRECISION': tokens.Keyword,
    +    'PREFIX': tokens.Keyword,
    +    'PREORDER': tokens.Keyword,
    +    'PREPARE': tokens.Keyword,
    +    'PRESERVE': tokens.Keyword,
    +    'PRIMARY': tokens.Keyword,
    +    'PRIOR': tokens.Keyword,
    +    'PRIVILEGES': tokens.Keyword,
    +    'PROCEDURAL': tokens.Keyword,
    +    'PROCEDURE': tokens.Keyword,
    +    'PUBLIC': tokens.Keyword,
    +
    +    'RAISE': tokens.Keyword,
    +    'RAW': tokens.Keyword,
    +    'READ': tokens.Keyword,
    +    'READS': tokens.Keyword,
    +    'RECHECK': tokens.Keyword,
    +    'RECURSIVE': tokens.Keyword,
    +    'REF': tokens.Keyword,
    +    'REFERENCES': tokens.Keyword,
    +    'REFERENCING': tokens.Keyword,
    +    'REINDEX': tokens.Keyword,
    +    'RELATIVE': tokens.Keyword,
    +    'RENAME': tokens.Keyword,
    +    'REPEATABLE': tokens.Keyword,
    +    'RESET': tokens.Keyword,
    +    'RESOURCE': tokens.Keyword,
    +    'RESTART': tokens.Keyword,
    +    'RESTRICT': tokens.Keyword,
    +    'RESULT': tokens.Keyword,
    +    'RETURN': tokens.Keyword,
    +    'RETURNED_LENGTH': tokens.Keyword,
    +    'RETURNED_OCTET_LENGTH': tokens.Keyword,
    +    'RETURNED_SQLSTATE': tokens.Keyword,
    +    'RETURNING': tokens.Keyword,
    +    'RETURNS': tokens.Keyword,
    +    'RIGHT': tokens.Keyword,
    +    'ROLE': tokens.Keyword,
    +    'ROLLBACK': tokens.Keyword.DML,
    +    'ROLLUP': tokens.Keyword,
    +    'ROUTINE': tokens.Keyword,
    +    'ROUTINE_CATALOG': tokens.Keyword,
    +    'ROUTINE_NAME': tokens.Keyword,
    +    'ROUTINE_SCHEMA': tokens.Keyword,
    +    'ROWS': tokens.Keyword,
    +    'ROW_COUNT': tokens.Keyword,
    +    'RULE': tokens.Keyword,
    +
    +    'SAVE_POINT': tokens.Keyword,
    +    'SCALE': tokens.Keyword,
    +    'SCHEMA': tokens.Keyword,
    +    'SCHEMA_NAME': tokens.Keyword,
    +    'SCOPE': tokens.Keyword,
    +    'SCROLL': tokens.Keyword,
    +    'SEARCH': tokens.Keyword,
    +    'SECOND': tokens.Keyword,
    +    'SECURITY': tokens.Keyword,
    +    'SELF': tokens.Keyword,
    +    'SENSITIVE': tokens.Keyword,
    +    'SEQUENCE': tokens.Keyword,
    +    'SERIALIZABLE': tokens.Keyword,
    +    'SERVER_NAME': tokens.Keyword,
    +    'SESSION': tokens.Keyword,
    +    'SESSION_USER': tokens.Keyword,
    +    'SETOF': tokens.Keyword,
    +    'SETS': tokens.Keyword,
    +    'SHARE': tokens.Keyword,
    +    'SHOW': tokens.Keyword,
    +    'SIMILAR': tokens.Keyword,
    +    'SIMPLE': tokens.Keyword,
    +    'SIZE': tokens.Keyword,
    +    'SOME': tokens.Keyword,
    +    'SOURCE': tokens.Keyword,
    +    'SPACE': tokens.Keyword,
    +    'SPECIFIC': tokens.Keyword,
    +    'SPECIFICTYPE': tokens.Keyword,
    +    'SPECIFIC_NAME': tokens.Keyword,
    +    'SQL': tokens.Keyword,
    +    'SQLBUF': tokens.Keyword,
    +    'SQLCODE': tokens.Keyword,
    +    'SQLERROR': tokens.Keyword,
    +    'SQLEXCEPTION': tokens.Keyword,
    +    'SQLSTATE': tokens.Keyword,
    +    'SQLWARNING': tokens.Keyword,
    +    'STABLE': tokens.Keyword,
    +    'START': tokens.Keyword.DML,
    +    # 'STATE': tokens.Keyword,
    +    'STATEMENT': tokens.Keyword,
    +    'STATIC': tokens.Keyword,
    +    'STATISTICS': tokens.Keyword,
    +    'STDIN': tokens.Keyword,
    +    'STDOUT': tokens.Keyword,
    +    'STORAGE': tokens.Keyword,
    +    'STRICT': tokens.Keyword,
    +    'STRUCTURE': tokens.Keyword,
    +    'STYPE': tokens.Keyword,
    +    'SUBCLASS_ORIGIN': tokens.Keyword,
    +    'SUBLIST': tokens.Keyword,
    +    'SUBSTRING': tokens.Keyword,
    +    'SUCCESSFUL': tokens.Keyword,
    +    'SUM': tokens.Keyword,
    +    'SYMMETRIC': tokens.Keyword,
    +    'SYNONYM': tokens.Keyword,
    +    'SYSID': tokens.Keyword,
    +    'SYSTEM': tokens.Keyword,
    +    'SYSTEM_USER': tokens.Keyword,
    +
    +    'TABLE': tokens.Keyword,
    +    'TABLE_NAME': tokens.Keyword,
    +    'TEMP': tokens.Keyword,
    +    'TEMPLATE': tokens.Keyword,
    +    'TEMPORARY': tokens.Keyword,
    +    'TERMINATE': tokens.Keyword,
    +    'THAN': tokens.Keyword,
    +    'TIMESTAMP': tokens.Keyword,
    +    'TIMEZONE_HOUR': tokens.Keyword,
    +    'TIMEZONE_MINUTE': tokens.Keyword,
    +    'TO': tokens.Keyword,
    +    'TOAST': tokens.Keyword,
    +    'TRAILING': tokens.Keyword,
    +    'TRANSATION': tokens.Keyword,
    +    'TRANSACTIONS_COMMITTED': tokens.Keyword,
    +    'TRANSACTIONS_ROLLED_BACK': tokens.Keyword,
    +    'TRANSATION_ACTIVE': tokens.Keyword,
    +    'TRANSFORM': tokens.Keyword,
    +    'TRANSFORMS': tokens.Keyword,
    +    'TRANSLATE': tokens.Keyword,
    +    'TRANSLATION': tokens.Keyword,
    +    'TREAT': tokens.Keyword,
    +    'TRIGGER': tokens.Keyword,
    +    'TRIGGER_CATALOG': tokens.Keyword,
    +    'TRIGGER_NAME': tokens.Keyword,
    +    'TRIGGER_SCHEMA': tokens.Keyword,
    +    'TRIM': tokens.Keyword,
    +    'TRUE': tokens.Keyword,
    +    'TRUSTED': tokens.Keyword,
    +    'TYPE': tokens.Keyword,
    +
    +    'UID': tokens.Keyword,
    +    'UNCOMMITTED': tokens.Keyword,
    +    'UNDER': tokens.Keyword,
    +    'UNENCRYPTED': tokens.Keyword,
    +    'UNION': tokens.Keyword,
    +    'UNIQUE': tokens.Keyword,
    +    'UNKNOWN': tokens.Keyword,
    +    'UNLISTEN': tokens.Keyword,
    +    'UNNAMED': tokens.Keyword,
    +    'UNNEST': tokens.Keyword,
    +    'UNTIL': tokens.Keyword,
    +    'UPPER': tokens.Keyword,
    +    'USAGE': tokens.Keyword,
    +    'USE': tokens.Keyword,
    +    'USER': tokens.Keyword,
    +    'USER_DEFINED_TYPE_CATALOG': tokens.Keyword,
    +    'USER_DEFINED_TYPE_NAME': tokens.Keyword,
    +    'USER_DEFINED_TYPE_SCHEMA': tokens.Keyword,
    +    'USING': tokens.Keyword,
    +
    +    'VACUUM': tokens.Keyword,
    +    'VALID': tokens.Keyword,
    +    'VALIDATE': tokens.Keyword,
    +    'VALIDATOR': tokens.Keyword,
    +    'VALUES': tokens.Keyword,
    +    'VARIABLE': tokens.Keyword,
    +    'VERBOSE': tokens.Keyword,
    +    'VERSION': tokens.Keyword,
    +    'VIEW': tokens.Keyword,
    +    'VOLATILE': tokens.Keyword,
    +
    +    'WEEK': tokens.Keyword,
    +    'WHENEVER': tokens.Keyword,
    +    'WITH': tokens.Keyword.CTE,
    +    'WITHOUT': tokens.Keyword,
    +    'WORK': tokens.Keyword,
    +    'WRITE': tokens.Keyword,
    +
    +    'YEAR': tokens.Keyword,
    +
    +    'ZONE': tokens.Keyword,
    +
    +    # Name.Builtin
    +    'ARRAY': tokens.Name.Builtin,
    +    'BIGINT': tokens.Name.Builtin,
    +    'BINARY': tokens.Name.Builtin,
    +    'BIT': tokens.Name.Builtin,
    +    'BLOB': tokens.Name.Builtin,
    +    'BOOLEAN': tokens.Name.Builtin,
    +    'CHAR': tokens.Name.Builtin,
    +    'CHARACTER': tokens.Name.Builtin,
    +    'DATE': tokens.Name.Builtin,
    +    'DEC': tokens.Name.Builtin,
    +    'DECIMAL': tokens.Name.Builtin,
    +    'FILE_TYPE': tokens.Name.Builtin,
    +    'FLOAT': tokens.Name.Builtin,
    +    'INT': tokens.Name.Builtin,
    +    'INT8': tokens.Name.Builtin,
    +    'INTEGER': tokens.Name.Builtin,
    +    'INTERVAL': tokens.Name.Builtin,
    +    'LONG': tokens.Name.Builtin,
    +    'NATURALN': tokens.Name.Builtin,
    +    'NVARCHAR': tokens.Name.Builtin,
    +    'NUMBER': tokens.Name.Builtin,
    +    'NUMERIC': tokens.Name.Builtin,
    +    'PLS_INTEGER': tokens.Name.Builtin,
    +    'POSITIVE': tokens.Name.Builtin,
    +    'POSITIVEN': tokens.Name.Builtin,
    +    'REAL': tokens.Name.Builtin,
    +    'ROWID': tokens.Name.Builtin,
    +    'ROWLABEL': tokens.Name.Builtin,
    +    'ROWNUM': tokens.Name.Builtin,
    +    'SERIAL': tokens.Name.Builtin,
    +    'SERIAL8': tokens.Name.Builtin,
    +    'SIGNED': tokens.Name.Builtin,
    +    'SIGNTYPE': tokens.Name.Builtin,
    +    'SIMPLE_DOUBLE': tokens.Name.Builtin,
    +    'SIMPLE_FLOAT': tokens.Name.Builtin,
    +    'SIMPLE_INTEGER': tokens.Name.Builtin,
    +    'SMALLINT': tokens.Name.Builtin,
    +    'SYS_REFCURSOR': tokens.Name.Builtin,
    +    'SYSDATE': tokens.Name,
    +    'TEXT': tokens.Name.Builtin,
    +    'TINYINT': tokens.Name.Builtin,
    +    'UNSIGNED': tokens.Name.Builtin,
    +    'UROWID': tokens.Name.Builtin,
    +    'UTL_FILE': tokens.Name.Builtin,
    +    'VARCHAR': tokens.Name.Builtin,
    +    'VARCHAR2': tokens.Name.Builtin,
    +    'VARYING': tokens.Name.Builtin,
    +}
    +
    +KEYWORDS_COMMON = {
    +    'SELECT': tokens.Keyword.DML,
    +    'INSERT': tokens.Keyword.DML,
    +    'DELETE': tokens.Keyword.DML,
    +    'UPDATE': tokens.Keyword.DML,
    +    'UPSERT': tokens.Keyword.DML,
    +    'REPLACE': tokens.Keyword.DML,
    +    'MERGE': tokens.Keyword.DML,
    +    'DROP': tokens.Keyword.DDL,
    +    'CREATE': tokens.Keyword.DDL,
    +    'ALTER': tokens.Keyword.DDL,
    +    'TRUNCATE': tokens.Keyword.DDL,
    +    'GRANT': tokens.Keyword.DCL,
    +    'REVOKE': tokens.Keyword.DCL,
    +
    +    'WHERE': tokens.Keyword,
    +    'FROM': tokens.Keyword,
    +    'INNER': tokens.Keyword,
    +    'JOIN': tokens.Keyword,
    +    'STRAIGHT_JOIN': tokens.Keyword,
    +    'AND': tokens.Keyword,
    +    'OR': tokens.Keyword,
    +    'LIKE': tokens.Keyword,
    +    'ON': tokens.Keyword,
    +    'IN': tokens.Keyword,
    +    'SET': tokens.Keyword,
    +
    +    'BY': tokens.Keyword,
    +    'GROUP': tokens.Keyword,
    +    'ORDER': tokens.Keyword,
    +    'LEFT': tokens.Keyword,
    +    'OUTER': tokens.Keyword,
    +    'FULL': tokens.Keyword,
    +
    +    'IF': tokens.Keyword,
    +    'END': tokens.Keyword,
    +    'THEN': tokens.Keyword,
    +    'LOOP': tokens.Keyword,
    +    'AS': tokens.Keyword,
    +    'ELSE': tokens.Keyword,
    +    'FOR': tokens.Keyword,
    +    'WHILE': tokens.Keyword,
    +
    +    'CASE': tokens.Keyword,
    +    'WHEN': tokens.Keyword,
    +    'MIN': tokens.Keyword,
    +    'MAX': tokens.Keyword,
    +    'DISTINCT': tokens.Keyword,
    +}
    +
    +KEYWORDS_ORACLE = {
    +    'ARCHIVE': tokens.Keyword,
    +    'ARCHIVELOG': tokens.Keyword,
    +
    +    'BACKUP': tokens.Keyword,
    +    'BECOME': tokens.Keyword,
    +    'BLOCK': tokens.Keyword,
    +    'BODY': tokens.Keyword,
    +
    +    'CANCEL': tokens.Keyword,
    +    'CHANGE': tokens.Keyword,
    +    'COMPILE': tokens.Keyword,
    +    'CONTENTS': tokens.Keyword,
    +    'CONTROLFILE': tokens.Keyword,
    +
    +    'DATAFILE': tokens.Keyword,
    +    'DBA': tokens.Keyword,
    +    'DISMOUNT': tokens.Keyword,
    +    'DOUBLE': tokens.Keyword,
    +    'DUMP': tokens.Keyword,
    +
    +    'ELSIF': tokens.Keyword,
    +    'EVENTS': tokens.Keyword,
    +    'EXCEPTIONS': tokens.Keyword,
    +    'EXPLAIN': tokens.Keyword,
    +    'EXTENT': tokens.Keyword,
    +    'EXTERNALLY': tokens.Keyword,
    +
    +    'FLUSH': tokens.Keyword,
    +    'FREELIST': tokens.Keyword,
    +    'FREELISTS': tokens.Keyword,
    +
    +    # groups seems too common as table name
    +    # 'GROUPS': tokens.Keyword,
    +
    +    'INDICATOR': tokens.Keyword,
    +    'INITRANS': tokens.Keyword,
    +    'INSTANCE': tokens.Keyword,
    +
    +    'LAYER': tokens.Keyword,
    +    'LINK': tokens.Keyword,
    +    'LISTS': tokens.Keyword,
    +    'LOGFILE': tokens.Keyword,
    +
    +    'MANAGE': tokens.Keyword,
    +    'MANUAL': tokens.Keyword,
    +    'MAXDATAFILES': tokens.Keyword,
    +    'MAXINSTANCES': tokens.Keyword,
    +    'MAXLOGFILES': tokens.Keyword,
    +    'MAXLOGHISTORY': tokens.Keyword,
    +    'MAXLOGMEMBERS': tokens.Keyword,
    +    'MAXTRANS': tokens.Keyword,
    +    'MINEXTENTS': tokens.Keyword,
    +    'MODULE': tokens.Keyword,
    +    'MOUNT': tokens.Keyword,
    +
    +    'NOARCHIVELOG': tokens.Keyword,
    +    'NOCACHE': tokens.Keyword,
    +    'NOCYCLE': tokens.Keyword,
    +    'NOMAXVALUE': tokens.Keyword,
    +    'NOMINVALUE': tokens.Keyword,
    +    'NOORDER': tokens.Keyword,
    +    'NORESETLOGS': tokens.Keyword,
    +    'NORMAL': tokens.Keyword,
    +    'NOSORT': tokens.Keyword,
    +
    +    'OPTIMAL': tokens.Keyword,
    +    'OWN': tokens.Keyword,
    +
    +    'PACKAGE': tokens.Keyword,
    +    'PARALLEL': tokens.Keyword,
    +    'PCTINCREASE': tokens.Keyword,
    +    'PCTUSED': tokens.Keyword,
    +    'PLAN': tokens.Keyword,
    +    'PRIVATE': tokens.Keyword,
    +    'PROFILE': tokens.Keyword,
    +
    +    'QUOTA': tokens.Keyword,
    +
    +    'RECOVER': tokens.Keyword,
    +    'RESETLOGS': tokens.Keyword,
    +    'RESTRICTED': tokens.Keyword,
    +    'REUSE': tokens.Keyword,
    +    'ROLES': tokens.Keyword,
    +
    +    'SAVEPOINT': tokens.Keyword,
    +    'SCN': tokens.Keyword,
    +    'SECTION': tokens.Keyword,
    +    'SEGMENT': tokens.Keyword,
    +    'SHARED': tokens.Keyword,
    +    'SNAPSHOT': tokens.Keyword,
    +    'SORT': tokens.Keyword,
    +    'STATEMENT_ID': tokens.Keyword,
    +    'STOP': tokens.Keyword,
    +    'SWITCH': tokens.Keyword,
    +
    +    'TABLES': tokens.Keyword,
    +    'TABLESPACE': tokens.Keyword,
    +    'THREAD': tokens.Keyword,
    +    'TIME': tokens.Keyword,
    +    'TRACING': tokens.Keyword,
    +    'TRANSACTION': tokens.Keyword,
    +    'TRIGGERS': tokens.Keyword,
    +
    +    'UNLIMITED': tokens.Keyword,
    +    'UNLOCK': tokens.Keyword,
    +}
    +
    +# MySQL
    +KEYWORDS_MYSQL = {
    +    'ROW': tokens.Keyword,
    +}
    +
    +# PostgreSQL Syntax
    +KEYWORDS_PLPGSQL = {
    +    'CONFLICT': tokens.Keyword,
    +    'WINDOW': tokens.Keyword,
    +    'PARTITION': tokens.Keyword,
    +    'ATTACH': tokens.Keyword,
    +    'DETACH': tokens.Keyword,
    +    'OVER': tokens.Keyword,
    +    'PERFORM': tokens.Keyword,
    +    'NOTICE': tokens.Keyword,
    +    'PLPGSQL': tokens.Keyword,
    +    'INHERIT': tokens.Keyword,
    +    'INDEXES': tokens.Keyword,
    +    'ON_ERROR_STOP': tokens.Keyword,
    +    'EXTENSION': tokens.Keyword,
    +
    +    'BYTEA': tokens.Keyword,
    +    'BIGSERIAL': tokens.Keyword,
    +    'BIT VARYING': tokens.Keyword,
    +    'BOX': tokens.Keyword,
    +    'CHARACTER': tokens.Keyword,
    +    'CHARACTER VARYING': tokens.Keyword,
    +    'CIDR': tokens.Keyword,
    +    'CIRCLE': tokens.Keyword,
    +    'DOUBLE PRECISION': tokens.Keyword,
    +    'INET': tokens.Keyword,
    +    'JSON': tokens.Keyword,
    +    'JSONB': tokens.Keyword,
    +    'LINE': tokens.Keyword,
    +    'LSEG': tokens.Keyword,
    +    'MACADDR': tokens.Keyword,
    +    'MONEY': tokens.Keyword,
    +    'PATH': tokens.Keyword,
    +    'PG_LSN': tokens.Keyword,
    +    'POINT': tokens.Keyword,
    +    'POLYGON': tokens.Keyword,
    +    'SMALLSERIAL': tokens.Keyword,
    +    'TSQUERY': tokens.Keyword,
    +    'TSVECTOR': tokens.Keyword,
    +    'TXID_SNAPSHOT': tokens.Keyword,
    +    'UUID': tokens.Keyword,
    +    'XML': tokens.Keyword,
    +
    +    'FOR': tokens.Keyword,
    +    'IN': tokens.Keyword,
    +    'LOOP': tokens.Keyword,
    +}
    +
    +# Hive Syntax
    +KEYWORDS_HQL = {
    +    'EXPLODE': tokens.Keyword,
    +    'DIRECTORY': tokens.Keyword,
    +    'DISTRIBUTE': tokens.Keyword,
    +    'INCLUDE': tokens.Keyword,
    +    'LOCATE': tokens.Keyword,
    +    'OVERWRITE': tokens.Keyword,
    +    'POSEXPLODE': tokens.Keyword,
    +
    +    'ARRAY_CONTAINS': tokens.Keyword,
    +    'CMP': tokens.Keyword,
    +    'COLLECT_LIST': tokens.Keyword,
    +    'CONCAT': tokens.Keyword,
    +    'CONDITION': tokens.Keyword,
    +    'DATE_ADD': tokens.Keyword,
    +    'DATE_SUB': tokens.Keyword,
    +    'DECODE': tokens.Keyword,
    +    'DBMS_OUTPUT': tokens.Keyword,
    +    'ELEMENTS': tokens.Keyword,
    +    'EXCHANGE': tokens.Keyword,
    +    'EXTENDED': tokens.Keyword,
    +    'FLOOR': tokens.Keyword,
    +    'FOLLOWING': tokens.Keyword,
    +    'FROM_UNIXTIME': tokens.Keyword,
    +    'FTP': tokens.Keyword,
    +    'HOUR': tokens.Keyword,
    +    'INLINE': tokens.Keyword,
    +    'INSTR': tokens.Keyword,
    +    'LEN': tokens.Keyword,
    +    'MAP': tokens.Name.Builtin,
    +    'MAXELEMENT': tokens.Keyword,
    +    'MAXINDEX': tokens.Keyword,
    +    'MAX_PART_DATE': tokens.Keyword,
    +    'MAX_PART_INT': tokens.Keyword,
    +    'MAX_PART_STRING': tokens.Keyword,
    +    'MINELEMENT': tokens.Keyword,
    +    'MININDEX': tokens.Keyword,
    +    'MIN_PART_DATE': tokens.Keyword,
    +    'MIN_PART_INT': tokens.Keyword,
    +    'MIN_PART_STRING': tokens.Keyword,
    +    'NOW': tokens.Keyword,
    +    'NVL': tokens.Keyword,
    +    'NVL2': tokens.Keyword,
    +    'PARSE_URL_TUPLE': tokens.Keyword,
    +    'PART_LOC': tokens.Keyword,
    +    'PART_COUNT': tokens.Keyword,
    +    'PART_COUNT_BY': tokens.Keyword,
    +    'PRINT': tokens.Keyword,
    +    'PUT_LINE': tokens.Keyword,
    +    'RANGE': tokens.Keyword,
    +    'REDUCE': tokens.Keyword,
    +    'REGEXP_REPLACE': tokens.Keyword,
    +    'RESIGNAL': tokens.Keyword,
    +    'RTRIM': tokens.Keyword,
    +    'SIGN': tokens.Keyword,
    +    'SIGNAL': tokens.Keyword,
    +    'SIN': tokens.Keyword,
    +    'SPLIT': tokens.Keyword,
    +    'SQRT': tokens.Keyword,
    +    'STACK': tokens.Keyword,
    +    'STR': tokens.Keyword,
    +    'STRING': tokens.Name.Builtin,
    +    'STRUCT': tokens.Name.Builtin,
    +    'SUBSTR': tokens.Keyword,
    +    'SUMMARY': tokens.Keyword,
    +    'TBLPROPERTIES': tokens.Keyword,
    +    'TIMESTAMP': tokens.Name.Builtin,
    +    'TIMESTAMP_ISO': tokens.Keyword,
    +    'TO_CHAR': tokens.Keyword,
    +    'TO_DATE': tokens.Keyword,
    +    'TO_TIMESTAMP': tokens.Keyword,
    +    'TRUNC': tokens.Keyword,
    +    'UNBOUNDED': tokens.Keyword,
    +    'UNIQUEJOIN': tokens.Keyword,
    +    'UNIX_TIMESTAMP': tokens.Keyword,
    +    'UTC_TIMESTAMP': tokens.Keyword,
    +    'VIEWS': tokens.Keyword,
    +
    +    'EXIT': tokens.Keyword,
    +    'BREAK': tokens.Keyword,
    +    'LEAVE': tokens.Keyword,
    +}
    +
    +
    +KEYWORDS_MSACCESS = {
    +    'DISTINCTROW': tokens.Keyword,
    +}
    +
    +
    +KEYWORDS_SNOWFLAKE = {
    +    'ACCOUNT': tokens.Keyword,
    +    'GSCLUSTER': tokens.Keyword,
    +    'ISSUE': tokens.Keyword,
    +    'ORGANIZATION': tokens.Keyword,
    +    'PIVOT': tokens.Keyword,
    +    'QUALIFY': tokens.Keyword,
    +    'REGEXP': tokens.Keyword,
    +    'RLIKE': tokens.Keyword,
    +    'SAMPLE': tokens.Keyword,
    +    'TRY_CAST': tokens.Keyword,
    +    'UNPIVOT': tokens.Keyword,
    +
    +    'VARIANT': tokens.Name.Builtin,
    +}
    +
    +
    +KEYWORDS_BIGQUERY = {
    +    'ASSERT_ROWS_MODIFIED': tokens.Keyword,
    +    'DEFINE': tokens.Keyword,
    +    'ENUM': tokens.Keyword,
    +    'HASH': tokens.Keyword,
    +    'LOOKUP': tokens.Keyword,
    +    'PRECEDING': tokens.Keyword,
    +    'PROTO': tokens.Keyword,
    +    'RESPECT': tokens.Keyword,
    +    'TABLESAMPLE': tokens.Keyword,
    +
    +    'BIGNUMERIC': tokens.Name.Builtin,
    +}
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/lexer.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/lexer.py
    new file mode 100644
    index 0000000..8f88d17
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/lexer.py
    @@ -0,0 +1,161 @@
    +#
    +# Copyright (C) 2009-2020 the sqlparse authors and contributors
    +# 
    +#
    +# This module is part of python-sqlparse and is released under
    +# the BSD License: https://opensource.org/licenses/BSD-3-Clause
    +
    +"""SQL Lexer"""
    +import re
    +from threading import Lock
    +
    +# This code is based on the SqlLexer in pygments.
    +# http://pygments.org/
    +# It's separated from the rest of pygments to increase performance
    +# and to allow some customizations.
    +
    +from io import TextIOBase
    +
    +from sqlparse import tokens, keywords
    +from sqlparse.utils import consume
    +
    +
    +class Lexer:
    +    """The Lexer supports configurable syntax.
    +    To add support for additional keywords, use the `add_keywords` method."""
    +
    +    _default_instance = None
    +    _lock = Lock()
    +
    +    # Development notes:
    +    # - This class is prepared to be able to support additional SQL dialects
    +    #   in the future by adding additional functions that take the place of
    +    #   the function default_initialization().
    +    # - The lexer class uses an explicit singleton behavior with the
    +    #   instance-getter method get_default_instance(). This mechanism has
    +    #   the advantage that the call signature of the entry-points to the
    +    #   sqlparse library are not affected. Also, usage of sqlparse in third
    +    #   party code does not need to be adapted. On the other hand, the current
    +    #   implementation does not easily allow for multiple SQL dialects to be
    +    #   parsed in the same process.
    +    #   Such behavior can be supported in the future by passing a
    +    #   suitably initialized lexer object as an additional parameter to the
    +    #   entry-point functions (such as `parse`). Code will need to be written
    +    #   to pass down and utilize such an object. The current implementation
    +    #   is prepared to support this thread safe approach without the
    +    #   default_instance part needing to change interface.
    +
    +    @classmethod
    +    def get_default_instance(cls):
    +        """Returns the lexer instance used internally
    +        by the sqlparse core functions."""
    +        with cls._lock:
    +            if cls._default_instance is None:
    +                cls._default_instance = cls()
    +                cls._default_instance.default_initialization()
    +        return cls._default_instance
    +
    +    def default_initialization(self):
    +        """Initialize the lexer with default dictionaries.
    +        Useful if you need to revert custom syntax settings."""
    +        self.clear()
    +        self.set_SQL_REGEX(keywords.SQL_REGEX)
    +        self.add_keywords(keywords.KEYWORDS_COMMON)
    +        self.add_keywords(keywords.KEYWORDS_ORACLE)
    +        self.add_keywords(keywords.KEYWORDS_MYSQL)
    +        self.add_keywords(keywords.KEYWORDS_PLPGSQL)
    +        self.add_keywords(keywords.KEYWORDS_HQL)
    +        self.add_keywords(keywords.KEYWORDS_MSACCESS)
    +        self.add_keywords(keywords.KEYWORDS_SNOWFLAKE)
    +        self.add_keywords(keywords.KEYWORDS_BIGQUERY)
    +        self.add_keywords(keywords.KEYWORDS)
    +
    +    def clear(self):
    +        """Clear all syntax configurations.
    +        Useful if you want to load a reduced set of syntax configurations.
    +        After this call, regexps and keyword dictionaries need to be loaded
    +        to make the lexer functional again."""
    +        self._SQL_REGEX = []
    +        self._keywords = []
    +
    +    def set_SQL_REGEX(self, SQL_REGEX):
    +        """Set the list of regex that will parse the SQL."""
    +        FLAGS = re.IGNORECASE | re.UNICODE
    +        self._SQL_REGEX = [
    +            (re.compile(rx, FLAGS).match, tt)
    +            for rx, tt in SQL_REGEX
    +        ]
    +
    +    def add_keywords(self, keywords):
    +        """Add keyword dictionaries. Keywords are looked up in the same order
    +        that dictionaries were added."""
    +        self._keywords.append(keywords)
    +
    +    def is_keyword(self, value):
    +        """Checks for a keyword.
    +
    +        If the given value is in one of the KEYWORDS_* dictionary
    +        it's considered a keyword. Otherwise, tokens.Name is returned.
    +        """
    +        val = value.upper()
    +        for kwdict in self._keywords:
    +            if val in kwdict:
    +                return kwdict[val], value
    +        else:
    +            return tokens.Name, value
    +
    +    def get_tokens(self, text, encoding=None):
    +        """
    +        Return an iterable of (tokentype, value) pairs generated from
    +        `text`. If `unfiltered` is set to `True`, the filtering mechanism
    +        is bypassed even if filters are defined.
    +
    +        Also preprocess the text, i.e. expand tabs and strip it if
    +        wanted and applies registered filters.
    +
    +        Split ``text`` into (tokentype, text) pairs.
    +
    +        ``stack`` is the initial stack (default: ``['root']``)
    +        """
    +        if isinstance(text, TextIOBase):
    +            text = text.read()
    +
    +        if isinstance(text, str):
    +            pass
    +        elif isinstance(text, bytes):
    +            if encoding:
    +                text = text.decode(encoding)
    +            else:
    +                try:
    +                    text = text.decode('utf-8')
    +                except UnicodeDecodeError:
    +                    text = text.decode('unicode-escape')
    +        else:
    +            raise TypeError("Expected text or file-like object, got {!r}".
    +                            format(type(text)))
    +
    +        iterable = enumerate(text)
    +        for pos, char in iterable:
    +            for rexmatch, action in self._SQL_REGEX:
    +                m = rexmatch(text, pos)
    +
    +                if not m:
    +                    continue
    +                elif isinstance(action, tokens._TokenType):
    +                    yield action, m.group()
    +                elif action is keywords.PROCESS_AS_KEYWORD:
    +                    yield self.is_keyword(m.group())
    +
    +                consume(iterable, m.end() - pos - 1)
    +                break
    +            else:
    +                yield tokens.Error, char
    +
    +
    +def tokenize(sql, encoding=None):
    +    """Tokenize sql.
    +
    +    Tokenize *sql* using the :class:`Lexer` and return a 2-tuple stream
    +    of ``(token type, value)`` items.
    +    """
    +    return Lexer.get_default_instance().get_tokens(sql, encoding)
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/py.typed b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/py.typed
    new file mode 100644
    index 0000000..e69de29
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/sql.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/sql.py
    new file mode 100644
    index 0000000..831dfb9
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/sql.py
    @@ -0,0 +1,659 @@
    +#
    +# Copyright (C) 2009-2020 the sqlparse authors and contributors
    +# 
    +#
    +# This module is part of python-sqlparse and is released under
    +# the BSD License: https://opensource.org/licenses/BSD-3-Clause
    +
    +"""This module contains classes representing syntactical elements of SQL."""
    +
    +import re
    +
    +from sqlparse import tokens as T
    +from sqlparse.utils import imt, remove_quotes
    +
    +
    +class NameAliasMixin:
    +    """Implements get_real_name and get_alias."""
    +
    +    def get_real_name(self):
    +        """Returns the real name (object name) of this identifier."""
    +        # a.b
    +        dot_idx, _ = self.token_next_by(m=(T.Punctuation, '.'))
    +        return self._get_first_name(dot_idx, real_name=True)
    +
    +    def get_alias(self):
    +        """Returns the alias for this identifier or ``None``."""
    +
    +        # "name AS alias"
    +        kw_idx, kw = self.token_next_by(m=(T.Keyword, 'AS'))
    +        if kw is not None:
    +            return self._get_first_name(kw_idx + 1, keywords=True)
    +
    +        # "name alias" or "complicated column expression alias"
    +        _, ws = self.token_next_by(t=T.Whitespace)
    +        if len(self.tokens) > 2 and ws is not None:
    +            return self._get_first_name(reverse=True)
    +
    +
    +class Token:
    +    """Base class for all other classes in this module.
    +
    +    It represents a single token and has two instance attributes:
    +    ``value`` is the unchanged value of the token and ``ttype`` is
    +    the type of the token.
    +    """
    +
    +    __slots__ = ('value', 'ttype', 'parent', 'normalized', 'is_keyword',
    +                 'is_group', 'is_whitespace', 'is_newline')
    +
    +    def __init__(self, ttype, value):
    +        value = str(value)
    +        self.value = value
    +        self.ttype = ttype
    +        self.parent = None
    +        self.is_group = False
    +        self.is_keyword = ttype in T.Keyword
    +        self.is_whitespace = self.ttype in T.Whitespace
    +        self.is_newline = self.ttype in T.Newline
    +        self.normalized = value.upper() if self.is_keyword else value
    +
    +    def __str__(self):
    +        return self.value
    +
    +    # Pending tokenlist __len__ bug fix
    +    # def __len__(self):
    +    #     return len(self.value)
    +
    +    def __repr__(self):
    +        cls = self._get_repr_name()
    +        value = self._get_repr_value()
    +
    +        q = '"' if value.startswith("'") and value.endswith("'") else "'"
    +        return "<{cls} {q}{value}{q} at 0x{id:2X}>".format(
    +            id=id(self), **locals())
    +
    +    def _get_repr_name(self):
    +        return str(self.ttype).split('.')[-1]
    +
    +    def _get_repr_value(self):
    +        raw = str(self)
    +        if len(raw) > 7:
    +            raw = raw[:6] + '...'
    +        return re.sub(r'\s+', ' ', raw)
    +
    +    def flatten(self):
    +        """Resolve subgroups."""
    +        yield self
    +
    +    def match(self, ttype, values, regex=False):
    +        """Checks whether the token matches the given arguments.
    +
    +        *ttype* is a token type as defined in `sqlparse.tokens`. If it does
    +        not match, ``False`` is returned.
    +        *values* is a list of possible values for this token. For match to be
    +        considered valid, the token value needs to be in this list. For tokens
    +        of type ``Keyword`` the comparison is case-insensitive. For
    +        convenience, a single value can be given passed as a string.
    +        If *regex* is ``True``, the given values are treated as regular
    +        expressions. Partial matches are allowed. Defaults to ``False``.
    +        """
    +        type_matched = self.ttype is ttype
    +        if not type_matched or values is None:
    +            return type_matched
    +
    +        if isinstance(values, str):
    +            values = (values,)
    +
    +        if regex:
    +            # TODO: Add test for regex with is_keyword = false
    +            flag = re.IGNORECASE if self.is_keyword else 0
    +            values = (re.compile(v, flag) for v in values)
    +
    +            for pattern in values:
    +                if pattern.search(self.normalized):
    +                    return True
    +            return False
    +
    +        if self.is_keyword:
    +            values = (v.upper() for v in values)
    +
    +        return self.normalized in values
    +
    +    def within(self, group_cls):
    +        """Returns ``True`` if this token is within *group_cls*.
    +
    +        Use this method for example to check if an identifier is within
    +        a function: ``t.within(sql.Function)``.
    +        """
    +        parent = self.parent
    +        while parent:
    +            if isinstance(parent, group_cls):
    +                return True
    +            parent = parent.parent
    +        return False
    +
    +    def is_child_of(self, other):
    +        """Returns ``True`` if this token is a direct child of *other*."""
    +        return self.parent == other
    +
    +    def has_ancestor(self, other):
    +        """Returns ``True`` if *other* is in this tokens ancestry."""
    +        parent = self.parent
    +        while parent:
    +            if parent == other:
    +                return True
    +            parent = parent.parent
    +        return False
    +
    +
    +class TokenList(Token):
    +    """A group of tokens.
    +
    +    It has an additional instance attribute ``tokens`` which holds a
    +    list of child-tokens.
    +    """
    +
    +    __slots__ = 'tokens'
    +
    +    def __init__(self, tokens=None):
    +        self.tokens = tokens or []
    +        [setattr(token, 'parent', self) for token in self.tokens]
    +        super().__init__(None, str(self))
    +        self.is_group = True
    +
    +    def __str__(self):
    +        return ''.join(token.value for token in self.flatten())
    +
    +    # weird bug
    +    # def __len__(self):
    +    #     return len(self.tokens)
    +
    +    def __iter__(self):
    +        return iter(self.tokens)
    +
    +    def __getitem__(self, item):
    +        return self.tokens[item]
    +
    +    def _get_repr_name(self):
    +        return type(self).__name__
    +
    +    def _pprint_tree(self, max_depth=None, depth=0, f=None, _pre=''):
    +        """Pretty-print the object tree."""
    +        token_count = len(self.tokens)
    +        for idx, token in enumerate(self.tokens):
    +            cls = token._get_repr_name()
    +            value = token._get_repr_value()
    +
    +            last = idx == (token_count - 1)
    +            pre = '`- ' if last else '|- '
    +
    +            q = '"' if value.startswith("'") and value.endswith("'") else "'"
    +            print(f"{_pre}{pre}{idx} {cls} {q}{value}{q}", file=f)
    +
    +            if token.is_group and (max_depth is None or depth < max_depth):
    +                parent_pre = '   ' if last else '|  '
    +                token._pprint_tree(max_depth, depth + 1, f, _pre + parent_pre)
    +
    +    def get_token_at_offset(self, offset):
    +        """Returns the token that is on position offset."""
    +        idx = 0
    +        for token in self.flatten():
    +            end = idx + len(token.value)
    +            if idx <= offset < end:
    +                return token
    +            idx = end
    +
    +    def flatten(self):
    +        """Generator yielding ungrouped tokens.
    +
    +        This method is recursively called for all child tokens.
    +        """
    +        for token in self.tokens:
    +            if token.is_group:
    +                yield from token.flatten()
    +            else:
    +                yield token
    +
    +    def get_sublists(self):
    +        for token in self.tokens:
    +            if token.is_group:
    +                yield token
    +
    +    @property
    +    def _groupable_tokens(self):
    +        return self.tokens
    +
    +    def _token_matching(self, funcs, start=0, end=None, reverse=False):
    +        """next token that match functions"""
    +        if start is None:
    +            return None
    +
    +        if not isinstance(funcs, (list, tuple)):
    +            funcs = (funcs,)
    +
    +        if reverse:
    +            assert end is None
    +            indexes = range(start - 2, -1, -1)
    +        else:
    +            if end is None:
    +                end = len(self.tokens)
    +            indexes = range(start, end)
    +        for idx in indexes:
    +            token = self.tokens[idx]
    +            for func in funcs:
    +                if func(token):
    +                    return idx, token
    +        return None, None
    +
    +    def token_first(self, skip_ws=True, skip_cm=False):
    +        """Returns the first child token.
    +
    +        If *skip_ws* is ``True`` (the default), whitespace
    +        tokens are ignored.
    +
    +        if *skip_cm* is ``True`` (default: ``False``), comments are
    +        ignored too.
    +        """
    +        # this on is inconsistent, using Comment instead of T.Comment...
    +        def matcher(tk):
    +            return not ((skip_ws and tk.is_whitespace)
    +                        or (skip_cm and imt(tk, t=T.Comment, i=Comment)))
    +        return self._token_matching(matcher)[1]
    +
    +    def token_next_by(self, i=None, m=None, t=None, idx=-1, end=None):
    +        idx += 1
    +        return self._token_matching(lambda tk: imt(tk, i, m, t), idx, end)
    +
    +    def token_not_matching(self, funcs, idx):
    +        funcs = (funcs,) if not isinstance(funcs, (list, tuple)) else funcs
    +        funcs = [lambda tk: not func(tk) for func in funcs]
    +        return self._token_matching(funcs, idx)
    +
    +    def token_matching(self, funcs, idx):
    +        return self._token_matching(funcs, idx)[1]
    +
    +    def token_prev(self, idx, skip_ws=True, skip_cm=False):
    +        """Returns the previous token relative to *idx*.
    +
    +        If *skip_ws* is ``True`` (the default) whitespace tokens are ignored.
    +        If *skip_cm* is ``True`` comments are ignored.
    +        ``None`` is returned if there's no previous token.
    +        """
    +        return self.token_next(idx, skip_ws, skip_cm, _reverse=True)
    +
    +    # TODO: May need to re-add default value to idx
    +    def token_next(self, idx, skip_ws=True, skip_cm=False, _reverse=False):
    +        """Returns the next token relative to *idx*.
    +
    +        If *skip_ws* is ``True`` (the default) whitespace tokens are ignored.
    +        If *skip_cm* is ``True`` comments are ignored.
    +        ``None`` is returned if there's no next token.
    +        """
    +        if idx is None:
    +            return None, None
    +        idx += 1  # alot of code usage current pre-compensates for this
    +
    +        def matcher(tk):
    +            return not ((skip_ws and tk.is_whitespace)
    +                        or (skip_cm and imt(tk, t=T.Comment, i=Comment)))
    +        return self._token_matching(matcher, idx, reverse=_reverse)
    +
    +    def token_index(self, token, start=0):
    +        """Return list index of token."""
    +        start = start if isinstance(start, int) else self.token_index(start)
    +        return start + self.tokens[start:].index(token)
    +
    +    def group_tokens(self, grp_cls, start, end, include_end=True,
    +                     extend=False):
    +        """Replace tokens by an instance of *grp_cls*."""
    +        start_idx = start
    +        start = self.tokens[start_idx]
    +
    +        end_idx = end + include_end
    +
    +        # will be needed later for new group_clauses
    +        # while skip_ws and tokens and tokens[-1].is_whitespace:
    +        #     tokens = tokens[:-1]
    +
    +        if extend and isinstance(start, grp_cls):
    +            subtokens = self.tokens[start_idx + 1:end_idx]
    +
    +            grp = start
    +            grp.tokens.extend(subtokens)
    +            del self.tokens[start_idx + 1:end_idx]
    +            grp.value = str(start)
    +        else:
    +            subtokens = self.tokens[start_idx:end_idx]
    +            grp = grp_cls(subtokens)
    +            self.tokens[start_idx:end_idx] = [grp]
    +            grp.parent = self
    +
    +        for token in subtokens:
    +            token.parent = grp
    +
    +        return grp
    +
    +    def insert_before(self, where, token):
    +        """Inserts *token* before *where*."""
    +        if not isinstance(where, int):
    +            where = self.token_index(where)
    +        token.parent = self
    +        self.tokens.insert(where, token)
    +
    +    def insert_after(self, where, token, skip_ws=True):
    +        """Inserts *token* after *where*."""
    +        if not isinstance(where, int):
    +            where = self.token_index(where)
    +        nidx, next_ = self.token_next(where, skip_ws=skip_ws)
    +        token.parent = self
    +        if next_ is None:
    +            self.tokens.append(token)
    +        else:
    +            self.tokens.insert(nidx, token)
    +
    +    def has_alias(self):
    +        """Returns ``True`` if an alias is present."""
    +        return self.get_alias() is not None
    +
    +    def get_alias(self):
    +        """Returns the alias for this identifier or ``None``."""
    +        return None
    +
    +    def get_name(self):
    +        """Returns the name of this identifier.
    +
    +        This is either it's alias or it's real name. The returned valued can
    +        be considered as the name under which the object corresponding to
    +        this identifier is known within the current statement.
    +        """
    +        return self.get_alias() or self.get_real_name()
    +
    +    def get_real_name(self):
    +        """Returns the real name (object name) of this identifier."""
    +        return None
    +
    +    def get_parent_name(self):
    +        """Return name of the parent object if any.
    +
    +        A parent object is identified by the first occurring dot.
    +        """
    +        dot_idx, _ = self.token_next_by(m=(T.Punctuation, '.'))
    +        _, prev_ = self.token_prev(dot_idx)
    +        return remove_quotes(prev_.value) if prev_ is not None else None
    +
    +    def _get_first_name(self, idx=None, reverse=False, keywords=False,
    +                        real_name=False):
    +        """Returns the name of the first token with a name"""
    +
    +        tokens = self.tokens[idx:] if idx else self.tokens
    +        tokens = reversed(tokens) if reverse else tokens
    +        types = [T.Name, T.Wildcard, T.String.Symbol]
    +
    +        if keywords:
    +            types.append(T.Keyword)
    +
    +        for token in tokens:
    +            if token.ttype in types:
    +                return remove_quotes(token.value)
    +            elif isinstance(token, (Identifier, Function)):
    +                return token.get_real_name() if real_name else token.get_name()
    +
    +
    +class Statement(TokenList):
    +    """Represents a SQL statement."""
    +
    +    def get_type(self):
    +        """Returns the type of a statement.
    +
    +        The returned value is a string holding an upper-cased reprint of
    +        the first DML or DDL keyword. If the first token in this group
    +        isn't a DML or DDL keyword "UNKNOWN" is returned.
    +
    +        Whitespaces and comments at the beginning of the statement
    +        are ignored.
    +        """
    +        token = self.token_first(skip_cm=True)
    +        if token is None:
    +            # An "empty" statement that either has not tokens at all
    +            # or only whitespace tokens.
    +            return 'UNKNOWN'
    +
    +        elif token.ttype in (T.Keyword.DML, T.Keyword.DDL):
    +            return token.normalized
    +
    +        elif token.ttype == T.Keyword.CTE:
    +            # The WITH keyword should be followed by either an Identifier or
    +            # an IdentifierList containing the CTE definitions;  the actual
    +            # DML keyword (e.g. SELECT, INSERT) will follow next.
    +            tidx = self.token_index(token)
    +            while tidx is not None:
    +                tidx, token = self.token_next(tidx, skip_ws=True)
    +                if isinstance(token, (Identifier, IdentifierList)):
    +                    tidx, token = self.token_next(tidx, skip_ws=True)
    +
    +                    if token is not None \
    +                            and token.ttype == T.Keyword.DML:
    +                        return token.normalized
    +
    +        # Hmm, probably invalid syntax, so return unknown.
    +        return 'UNKNOWN'
    +
    +
    +class Identifier(NameAliasMixin, TokenList):
    +    """Represents an identifier.
    +
    +    Identifiers may have aliases or typecasts.
    +    """
    +
    +    def is_wildcard(self):
    +        """Return ``True`` if this identifier contains a wildcard."""
    +        _, token = self.token_next_by(t=T.Wildcard)
    +        return token is not None
    +
    +    def get_typecast(self):
    +        """Returns the typecast or ``None`` of this object as a string."""
    +        midx, marker = self.token_next_by(m=(T.Punctuation, '::'))
    +        nidx, next_ = self.token_next(midx, skip_ws=False)
    +        return next_.value if next_ else None
    +
    +    def get_ordering(self):
    +        """Returns the ordering or ``None`` as uppercase string."""
    +        _, ordering = self.token_next_by(t=T.Keyword.Order)
    +        return ordering.normalized if ordering else None
    +
    +    def get_array_indices(self):
    +        """Returns an iterator of index token lists"""
    +
    +        for token in self.tokens:
    +            if isinstance(token, SquareBrackets):
    +                # Use [1:-1] index to discard the square brackets
    +                yield token.tokens[1:-1]
    +
    +
    +class IdentifierList(TokenList):
    +    """A list of :class:`~sqlparse.sql.Identifier`\'s."""
    +
    +    def get_identifiers(self):
    +        """Returns the identifiers.
    +
    +        Whitespaces and punctuations are not included in this generator.
    +        """
    +        for token in self.tokens:
    +            if not (token.is_whitespace or token.match(T.Punctuation, ',')):
    +                yield token
    +
    +
    +class TypedLiteral(TokenList):
    +    """A typed literal, such as "date '2001-09-28'" or "interval '2 hours'"."""
    +    M_OPEN = [(T.Name.Builtin, None), (T.Keyword, "TIMESTAMP")]
    +    M_CLOSE = T.String.Single, None
    +    M_EXTEND = T.Keyword, ("DAY", "HOUR", "MINUTE", "MONTH", "SECOND", "YEAR")
    +
    +
    +class Parenthesis(TokenList):
    +    """Tokens between parenthesis."""
    +    M_OPEN = T.Punctuation, '('
    +    M_CLOSE = T.Punctuation, ')'
    +
    +    @property
    +    def _groupable_tokens(self):
    +        return self.tokens[1:-1]
    +
    +
    +class SquareBrackets(TokenList):
    +    """Tokens between square brackets"""
    +    M_OPEN = T.Punctuation, '['
    +    M_CLOSE = T.Punctuation, ']'
    +
    +    @property
    +    def _groupable_tokens(self):
    +        return self.tokens[1:-1]
    +
    +
    +class Assignment(TokenList):
    +    """An assignment like 'var := val;'"""
    +
    +
    +class If(TokenList):
    +    """An 'if' clause with possible 'else if' or 'else' parts."""
    +    M_OPEN = T.Keyword, 'IF'
    +    M_CLOSE = T.Keyword, 'END IF'
    +
    +
    +class For(TokenList):
    +    """A 'FOR' loop."""
    +    M_OPEN = T.Keyword, ('FOR', 'FOREACH')
    +    M_CLOSE = T.Keyword, 'END LOOP'
    +
    +
    +class Comparison(TokenList):
    +    """A comparison used for example in WHERE clauses."""
    +
    +    @property
    +    def left(self):
    +        return self.tokens[0]
    +
    +    @property
    +    def right(self):
    +        return self.tokens[-1]
    +
    +
    +class Comment(TokenList):
    +    """A comment."""
    +
    +    def is_multiline(self):
    +        return self.tokens and self.tokens[0].ttype == T.Comment.Multiline
    +
    +
    +class Where(TokenList):
    +    """A WHERE clause."""
    +    M_OPEN = T.Keyword, 'WHERE'
    +    M_CLOSE = T.Keyword, (
    +        'ORDER BY', 'GROUP BY', 'LIMIT', 'UNION', 'UNION ALL', 'EXCEPT',
    +        'INTERSECT', 'HAVING', 'RETURNING', 'INTO')
    +
    +
    +class Over(TokenList):
    +    """An OVER clause."""
    +    M_OPEN = T.Keyword, 'OVER'
    +
    +
    +class Having(TokenList):
    +    """A HAVING clause."""
    +    M_OPEN = T.Keyword, 'HAVING'
    +    M_CLOSE = T.Keyword, ('ORDER BY', 'LIMIT')
    +
    +
    +class Case(TokenList):
    +    """A CASE statement with one or more WHEN and possibly an ELSE part."""
    +    M_OPEN = T.Keyword, 'CASE'
    +    M_CLOSE = T.Keyword, 'END'
    +
    +    def get_cases(self, skip_ws=False):
    +        """Returns a list of 2-tuples (condition, value).
    +
    +        If an ELSE exists condition is None.
    +        """
    +        CONDITION = 1
    +        VALUE = 2
    +
    +        ret = []
    +        mode = CONDITION
    +
    +        for token in self.tokens:
    +            # Set mode from the current statement
    +            if token.match(T.Keyword, 'CASE'):
    +                continue
    +
    +            elif skip_ws and token.ttype in T.Whitespace:
    +                continue
    +
    +            elif token.match(T.Keyword, 'WHEN'):
    +                ret.append(([], []))
    +                mode = CONDITION
    +
    +            elif token.match(T.Keyword, 'THEN'):
    +                mode = VALUE
    +
    +            elif token.match(T.Keyword, 'ELSE'):
    +                ret.append((None, []))
    +                mode = VALUE
    +
    +            elif token.match(T.Keyword, 'END'):
    +                mode = None
    +
    +            # First condition without preceding WHEN
    +            if mode and not ret:
    +                ret.append(([], []))
    +
    +            # Append token depending of the current mode
    +            if mode == CONDITION:
    +                ret[-1][0].append(token)
    +
    +            elif mode == VALUE:
    +                ret[-1][1].append(token)
    +
    +        # Return cases list
    +        return ret
    +
    +
    +class Function(NameAliasMixin, TokenList):
    +    """A function or procedure call."""
    +
    +    def get_parameters(self):
    +        """Return a list of parameters."""
    +        parenthesis = self.token_next_by(i=Parenthesis)[1]
    +        result = []
    +        for token in parenthesis.tokens:
    +            if isinstance(token, IdentifierList):
    +                return token.get_identifiers()
    +            elif imt(token, i=(Function, Identifier, TypedLiteral),
    +                     t=T.Literal):
    +                result.append(token)
    +        return result
    +
    +    def get_window(self):
    +        """Return the window if it exists."""
    +        over_clause = self.token_next_by(i=Over)
    +        if not over_clause:
    +            return None
    +        return over_clause[1].tokens[-1]
    +
    +
    +class Begin(TokenList):
    +    """A BEGIN/END block."""
    +    M_OPEN = T.Keyword, 'BEGIN'
    +    M_CLOSE = T.Keyword, 'END'
    +
    +
    +class Operation(TokenList):
    +    """Grouping of operations"""
    +
    +
    +class Values(TokenList):
    +    """Grouping of values"""
    +
    +
    +class Command(TokenList):
    +    """Grouping of CLI commands."""
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/tokens.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/tokens.py
    new file mode 100644
    index 0000000..143f66b
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/tokens.py
    @@ -0,0 +1,71 @@
    +#
    +# Copyright (C) 2009-2020 the sqlparse authors and contributors
    +# 
    +#
    +# This module is part of python-sqlparse and is released under
    +# the BSD License: https://opensource.org/licenses/BSD-3-Clause
    +#
    +# The Token implementation is based on pygment's token system written
    +# by Georg Brandl.
    +# http://pygments.org/
    +
    +"""Tokens"""
    +
    +
    +class _TokenType(tuple):
    +    parent = None
    +
    +    def __contains__(self, item):
    +        return item is not None and (self is item or item[:len(self)] == self)
    +
    +    def __getattr__(self, name):
    +        # don't mess with dunder
    +        if name.startswith('__'):
    +            return super().__getattr__(self, name)
    +        new = _TokenType(self + (name,))
    +        setattr(self, name, new)
    +        new.parent = self
    +        return new
    +
    +    def __repr__(self):
    +        # self can be False only if its the `root` i.e. Token itself
    +        return 'Token' + ('.' if self else '') + '.'.join(self)
    +
    +
    +Token = _TokenType()
    +
    +# Special token types
    +Text = Token.Text
    +Whitespace = Text.Whitespace
    +Newline = Whitespace.Newline
    +Error = Token.Error
    +# Text that doesn't belong to this lexer (e.g. HTML in PHP)
    +Other = Token.Other
    +
    +# Common token types for source code
    +Keyword = Token.Keyword
    +Name = Token.Name
    +Literal = Token.Literal
    +String = Literal.String
    +Number = Literal.Number
    +Punctuation = Token.Punctuation
    +Operator = Token.Operator
    +Comparison = Operator.Comparison
    +Wildcard = Token.Wildcard
    +Comment = Token.Comment
    +Assignment = Token.Assignment
    +
    +# Generic types for non-source code
    +Generic = Token.Generic
    +Command = Generic.Command
    +
    +# String and some others are not direct children of Token.
    +# alias them:
    +Token.Token = Token
    +Token.String = String
    +Token.Number = Number
    +
    +# SQL specific tokens
    +DML = Keyword.DML
    +DDL = Keyword.DDL
    +CTE = Keyword.CTE
    diff --git a/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/utils.py b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/utils.py
    new file mode 100644
    index 0000000..58c0245
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django-shared/.pypackages/sqlparse/utils.py
    @@ -0,0 +1,124 @@
    +#
    +# Copyright (C) 2009-2020 the sqlparse authors and contributors
    +# 
    +#
    +# This module is part of python-sqlparse and is released under
    +# the BSD License: https://opensource.org/licenses/BSD-3-Clause
    +
    +import itertools
    +import re
    +from collections import deque
    +from contextlib import contextmanager
    +
    +# This regular expression replaces the home-cooked parser that was here before.
    +# It is much faster, but requires an extra post-processing step to get the
    +# desired results (that are compatible with what you would expect from the
    +# str.splitlines() method).
    +#
    +# It matches groups of characters: newlines, quoted strings, or unquoted text,
    +# and splits on that basis. The post-processing step puts those back together
    +# into the actual lines of SQL.
    +SPLIT_REGEX = re.compile(r"""
    +(
    + (?:                     # Start of non-capturing group
    +  (?:\r\n|\r|\n)      |  # Match any single newline, or
    +  [^\r\n'"]+          |  # Match any character series without quotes or
    +                         # newlines, or
    +  "(?:[^"\\]|\\.)*"   |  # Match double-quoted strings, or
    +  '(?:[^'\\]|\\.)*'      # Match single quoted strings
    + )
    +)
    +""", re.VERBOSE)
    +
    +LINE_MATCH = re.compile(r'(\r\n|\r|\n)')
    +
    +
    +def split_unquoted_newlines(stmt):
    +    """Split a string on all unquoted newlines.
    +
    +    Unlike str.splitlines(), this will ignore CR/LF/CR+LF if the requisite
    +    character is inside of a string."""
    +    text = str(stmt)
    +    lines = SPLIT_REGEX.split(text)
    +    outputlines = ['']
    +    for line in lines:
    +        if not line:
    +            continue
    +        elif LINE_MATCH.match(line):
    +            outputlines.append('')
    +        else:
    +            outputlines[-1] += line
    +    return outputlines
    +
    +
    +def remove_quotes(val):
    +    """Helper that removes surrounding quotes from strings."""
    +    if val is None:
    +        return
    +    if val[0] in ('"', "'", '`') and val[0] == val[-1]:
    +        val = val[1:-1]
    +    return val
    +
    +
    +def recurse(*cls):
    +    """Function decorator to help with recursion
    +
    +    :param cls: Classes to not recurse over
    +    :return: function
    +    """
    +    def wrap(f):
    +        def wrapped_f(tlist):
    +            for sgroup in tlist.get_sublists():
    +                if not isinstance(sgroup, cls):
    +                    wrapped_f(sgroup)
    +            f(tlist)
    +
    +        return wrapped_f
    +
    +    return wrap
    +
    +
    +def imt(token, i=None, m=None, t=None):
    +    """Helper function to simplify comparisons Instance, Match and TokenType
    +    :param token:
    +    :param i: Class or Tuple/List of Classes
    +    :param m: Tuple of TokenType & Value. Can be list of Tuple for multiple
    +    :param t: TokenType or Tuple/List of TokenTypes
    +    :return:  bool
    +    """
    +    if token is None:
    +        return False
    +    if i and isinstance(token, i):
    +        return True
    +    if m:
    +        if isinstance(m, list):
    +            if any(token.match(*pattern) for pattern in m):
    +                return True
    +        elif token.match(*m):
    +            return True
    +    if t:
    +        if isinstance(t, list):
    +            if any(token.ttype in ttype for ttype in t):
    +                return True
    +        elif token.ttype in t:
    +            return True
    +    return False
    +
    +
    +def consume(iterator, n):
    +    """Advance the iterator n-steps ahead. If n is none, consume entirely."""
    +    deque(itertools.islice(iterator, n), maxlen=0)
    +
    +
    +@contextmanager
    +def offset(filter_, n=0):
    +    filter_.offset += n
    +    yield
    +    filter_.offset -= n
    +
    +
    +@contextmanager
    +def indent(filter_, n=1):
    +    filter_.indent += n
    +    yield
    +    filter_.indent -= n
    diff --git a/app/src/main/assets/sample_projects/python-django/manage.py b/app/src/main/assets/sample_projects/python-django/manage.py
    new file mode 100644
    index 0000000..2b37e9c
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django/manage.py
    @@ -0,0 +1,9 @@
    +
    +
    +import os, sys
    +def main():
    +    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
    +    from django.core.management import execute_from_command_line
    +    execute_from_command_line(sys.argv)
    +if __name__ == '__main__':
    +    main()
    diff --git a/app/src/main/assets/sample_projects/python-django/mysite/__init__.py b/app/src/main/assets/sample_projects/python-django/mysite/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/app/src/main/assets/sample_projects/python-django/mysite/settings.py b/app/src/main/assets/sample_projects/python-django/mysite/settings.py
    new file mode 100644
    index 0000000..5ababf7
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django/mysite/settings.py
    @@ -0,0 +1,9 @@
    +SECRET_KEY = 'demo-secret-key'
    +DEBUG = True
    +ALLOWED_HOSTS = ['*']
    +INSTALLED_APPS = ['django.contrib.auth', 'django.contrib.contenttypes']
    +MIDDLEWARE = []
    +ROOT_URLCONF = 'mysite.urls'
    +WSGI_APPLICATION = 'mysite.wsgi.application'
    +DATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': 'db.sqlite3'}}
    +STATIC_URL = 'static/'
    diff --git a/app/src/main/assets/sample_projects/python-django/mysite/urls.py b/app/src/main/assets/sample_projects/python-django/mysite/urls.py
    new file mode 100644
    index 0000000..9aca924
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django/mysite/urls.py
    @@ -0,0 +1,7 @@
    +from django.urls import path
    +from mysite import views
    +
    +urlpatterns = [
    +    path('', views.dashboard),
    +    path('api/stats', views.api_stats),
    +]
    diff --git a/app/src/main/assets/sample_projects/python-django/mysite/views.py b/app/src/main/assets/sample_projects/python-django/mysite/views.py
    new file mode 100644
    index 0000000..551a206
    --- /dev/null
    +++ b/app/src/main/assets/sample_projects/python-django/mysite/views.py
    @@ -0,0 +1,139 @@
    +"""
    +Django Admin Dashboard — 精美的管理后台仪表盘
    +展示 Django 的 MTV 架构和模板渲染能力
    +"""
    +import os
    +import random
    +from datetime import datetime
    +from django.http import HttpResponse, JsonResponse
    +
    +def dashboard(request):
    +    """主仪表盘视图"""
    +    stats = {
    +        'users': f'{random.randint(8000,15000):,}',
    +        'posts': f'{random.randint(2000,5000):,}',
    +        'comments': f'{random.randint(10000,30000):,}',
    +        'pageviews': f'{random.randint(80,200)}K',
    +    }
    +    models = [
    +        {'name': 'User', 'count': random.randint(800, 1500), 'icon': '👤', 'color': '#7c3aed'},
    +        {'name': 'Post', 'count': random.randint(200, 500), 'icon': '📝', 'color': '#3b82f6'},
    +        {'name': 'Comment', 'count': random.randint(1000, 3000), 'icon': '💬', 'color': '#10b981'},
    +        {'name': 'Category', 'count': random.randint(10, 30), 'icon': '📂', 'color': '#f59e0b'},
    +        {'name': 'Tag', 'count': random.randint(50, 150), 'icon': '🏷️', 'color': '#ec4899'},
    +        {'name': 'Media', 'count': random.randint(100, 400), 'icon': '🖼️', 'color': '#06b6d4'},
    +    ]
    +    logs = [
    +        {'action': '创建了新文章', 'user': '管理员', 'time': f'{random.randint(2,30)}分钟前', 'icon': '📝', 'color': '#3b82f6'},
    +        {'action': '更新了用户权限', 'user': '系统', 'time': f'{random.randint(1,5)}小时前', 'icon': '🔐', 'color': '#7c3aed'},
    +        {'action': '发布了 3 条评论', 'user': '张伟', 'time': f'{random.randint(1,3)}小时前', 'icon': '💬', 'color': '#10b981'},
    +        {'action': '上传了 5 张图片', 'user': '李娜', 'time': f'{random.randint(2,6)}小时前', 'icon': '🖼️', 'color': '#06b6d4'},
    +        {'action': '备份了数据库', 'user': '系统', 'time': '今天 08:00', 'icon': '💾', 'color': '#f59e0b'},
    +    ]
    +    weekly = [random.randint(40, 100) for _ in range(7)]
    +    max_w = max(weekly) or 1
    +    week_pct = [int(v / max_w * 85) + 15 for v in weekly]
    +    days = ['一', '二', '三', '四', '五', '六', '日']
    +    import django
    +    html = f"""
    +
    +
    +
    +
    +Django Admin
    +
    +
    +
    +
    +
    +

    🦄 Django Admin

    管理后台仪表盘

    +
    运行中
    +
    +
    +
    用户👥
    {stats['users']}
    ↑ 12.3%
    +
    文章📝
    {stats['posts']}
    ↑ 8.7%
    +
    评论💬
    {stats['comments']}
    ↑ 15.1%
    +
    浏览👁️
    {stats['pageviews']}
    ↑ 22.4%
    +
    +
    +
    本周活跃📊 趋势
    +
    + {''.join(f'
    周{days[i]}
    ' for i in range(7))} +
    +
    +
    +
    数据模型📦 {len(models)} 个
    + {''.join(f'
    {m["icon"]}
    {m["name"]}
    {m["count"]} 条记录
    ' for m in models)} +
    +
    +
    操作日志🔔 最近
    + {''.join(f'
    {l["icon"]}
    {l["action"]}
    {l["user"]}
    {l["time"]}
    ' for l in logs)} +
    +
    Django {django.get_version()} · Python · {datetime.now().strftime('%Y-%m-%d')}
    +
    + +""" + return HttpResponse(html) + +def api_stats(request): + return JsonResponse({ + 'status': 'ok', + 'data': { + 'users': random.randint(8000, 15000), + 'posts': random.randint(2000, 5000), + 'comments': random.randint(10000, 30000), + }, + 'framework': 'Django', + 'timestamp': datetime.now().isoformat() + }) diff --git a/app/src/main/assets/sample_projects/python-django/mysite/wsgi.py b/app/src/main/assets/sample_projects/python-django/mysite/wsgi.py new file mode 100644 index 0000000..b1fc26c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django/mysite/wsgi.py @@ -0,0 +1,4 @@ +import os +from django.core.wsgi import get_wsgi_application +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') +application = get_wsgi_application() diff --git a/app/src/main/assets/sample_projects/python-django/requirements.txt b/app/src/main/assets/sample_projects/python-django/requirements.txt new file mode 100644 index 0000000..9516b92 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-django/requirements.txt @@ -0,0 +1,2 @@ +django==5.0 +gunicorn==21.2.0 diff --git a/app/src/main/assets/sample_projects/python-fastapi-ar/main.py b/app/src/main/assets/sample_projects/python-fastapi-ar/main.py new file mode 100644 index 0000000..076a863 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-ar/main.py @@ -0,0 +1,181 @@ + +""" +FastAPI API Monitor — 精美的 API 监控仪表盘 +展示 FastAPI 的高性能异步能力,包含交互式 API 文档 +""" +import os +import random +import time +from datetime import datetime +from fastapi import FastAPI +from fastapi.responses import HTMLResponse, JSONResponse +from pydantic import BaseModel +from typing import List, Optional + +app = FastAPI(title="API Monitor", version="2.0.0") + +class Book(BaseModel): + id: int + title: str + author: str + price: float + +books_db: List[Book] = [ + Book(id=1, title="Python Crash Course", author="Eric Matthes", price=29.99), + Book(id=2, title="Clean Code", author="Robert C. Martin", price=35.50), + Book(id=3, title="Design Patterns", author="Gang of Four", price=42.00), +] + +start_time = time.time() + +DASHBOARD = """ + + + + +FastAPI Monitor + + + +
    +
    +

    ⚡ FastAPI Monitor

    مراقب API عالي الأداء

    +
    متصل
    +
    +
    +
    0s
    وقت التشغيل
    +
    0
    الطلبات
    +
    <1ms
    متوسط التأخير
    +
    +
    +
    نقاط API6 مسارات
    +
    GET
    /
    الصفحة الرئيسية
    <1ms
    +
    GET
    /api/books
    قائمة الكتب
    ~2ms
    +
    GET
    /api/books/{id}
    كتاب محدد
    ~1ms
    +
    POST
    /api/books
    إضافة كتاب
    ~3ms
    +
    GET
    /api/health
    فحص الصحة
    <1ms
    +
    GET
    /docs
    مستندات Swagger
    تلقائي
    +
    +
    +
    اختبار مباشر🧪 تفاعلي
    +
    + + + +
    +
    +
    +
    +
    المقاييس📊 مباشر
    +
    CPU
    0%
    +
    الذاكرة
    0%
    +
    القرص
    0%
    +
    + +
    + + +""" + +@app.get("/", response_class=HTMLResponse) +async def dashboard(): + return DASHBOARD + +@app.get("/api/books", response_model=List[Book]) +async def list_books(): + return books_db + +@app.get("/api/books/{book_id}") +async def get_book(book_id: int): + for b in books_db: + if b.id == book_id: + return b + return JSONResponse({"error": "Book not found"}, status_code=404) + +@app.post("/api/books", response_model=Book) +async def create_book(book: Book): + books_db.append(book) + return book + +@app.get("/api/health") +async def health(): + return { + "status": "healthy", + "uptime_seconds": round(time.time() - start_time, 1), + "framework": "FastAPI", + "books_count": len(books_db), + "timestamp": datetime.now().isoformat() + } diff --git a/app/src/main/assets/sample_projects/python-fastapi-ar/requirements.txt b/app/src/main/assets/sample_projects/python-fastapi-ar/requirements.txt new file mode 100644 index 0000000..244b15d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-ar/requirements.txt @@ -0,0 +1,3 @@ +fastapi==0.99.1 +uvicorn==0.23.2 +pydantic==1.10.16 diff --git a/app/src/main/assets/sample_projects/python-fastapi-en/main.py b/app/src/main/assets/sample_projects/python-fastapi-en/main.py new file mode 100644 index 0000000..4337ec1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-en/main.py @@ -0,0 +1,181 @@ + +""" +FastAPI API Monitor — 精美的 API 监控仪表盘 +展示 FastAPI 的高性能异步能力,包含交互式 API 文档 +""" +import os +import random +import time +from datetime import datetime +from fastapi import FastAPI +from fastapi.responses import HTMLResponse, JSONResponse +from pydantic import BaseModel +from typing import List, Optional + +app = FastAPI(title="API Monitor", version="2.0.0") + +class Book(BaseModel): + id: int + title: str + author: str + price: float + +books_db: List[Book] = [ + Book(id=1, title="Python Crash Course", author="Eric Matthes", price=29.99), + Book(id=2, title="Clean Code", author="Robert C. Martin", price=35.50), + Book(id=3, title="Design Patterns", author="Gang of Four", price=42.00), +] + +start_time = time.time() + +DASHBOARD = """ + + + + +FastAPI Monitor + + + +
    +
    +

    ⚡ FastAPI Monitor

    High-Performance API Monitor

    +
    Online
    +
    +
    +
    0s
    Uptime
    +
    0
    Requests
    +
    <1ms
    Avg Latency
    +
    +
    +
    API Endpoints6 Routes
    +
    GET
    /
    Dashboard Home
    <1ms
    +
    GET
    /api/books
    List all books
    ~2ms
    +
    GET
    /api/books/{id}
    Get book by ID
    ~1ms
    +
    POST
    /api/books
    Add new book
    ~3ms
    +
    GET
    /api/health
    Health Check
    <1ms
    +
    GET
    /docs
    Swagger Docs
    Auto-generated
    +
    +
    +
    Live Testing🧪 Interactive
    +
    + + + +
    +
    +
    +
    +
    Metrics📊 Live
    +
    CPU
    0%
    +
    Memory
    0%
    +
    Disk
    0%
    +
    + +
    + + +""" + +@app.get("/", response_class=HTMLResponse) +async def dashboard(): + return DASHBOARD + +@app.get("/api/books", response_model=List[Book]) +async def list_books(): + return books_db + +@app.get("/api/books/{book_id}") +async def get_book(book_id: int): + for b in books_db: + if b.id == book_id: + return b + return JSONResponse({"error": "Book not found"}, status_code=404) + +@app.post("/api/books", response_model=Book) +async def create_book(book: Book): + books_db.append(book) + return book + +@app.get("/api/health") +async def health(): + return { + "status": "healthy", + "uptime_seconds": round(time.time() - start_time, 1), + "framework": "FastAPI", + "books_count": len(books_db), + "timestamp": datetime.now().isoformat() + } diff --git a/app/src/main/assets/sample_projects/python-fastapi-en/requirements.txt b/app/src/main/assets/sample_projects/python-fastapi-en/requirements.txt new file mode 100644 index 0000000..244b15d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-en/requirements.txt @@ -0,0 +1,3 @@ +fastapi==0.99.1 +uvicorn==0.23.2 +pydantic==1.10.16 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio-4.12.1.dist-info/INSTALLER b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio-4.12.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio-4.12.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio-4.12.1.dist-info/METADATA b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio-4.12.1.dist-info/METADATA new file mode 100644 index 0000000..dbeb198 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio-4.12.1.dist-info/METADATA @@ -0,0 +1,96 @@ +Metadata-Version: 2.4 +Name: anyio +Version: 4.12.1 +Summary: High-level concurrency and networking framework on top of asyncio or Trio +Author-email: Alex Grönholm +License-Expression: MIT +Project-URL: Documentation, https://anyio.readthedocs.io/en/latest/ +Project-URL: Changelog, https://anyio.readthedocs.io/en/stable/versionhistory.html +Project-URL: Source code, https://github.com/agronholm/anyio +Project-URL: Issue tracker, https://github.com/agronholm/anyio/issues +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: Framework :: AnyIO +Classifier: Typing :: Typed +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 +Classifier: Programming Language :: Python :: 3.14 +Requires-Python: >=3.9 +Description-Content-Type: text/x-rst +License-File: LICENSE +Requires-Dist: exceptiongroup>=1.0.2; python_version < "3.11" +Requires-Dist: idna>=2.8 +Requires-Dist: typing_extensions>=4.5; python_version < "3.13" +Provides-Extra: trio +Requires-Dist: trio>=0.32.0; python_version >= "3.10" and extra == "trio" +Requires-Dist: trio>=0.31.0; python_version < "3.10" and extra == "trio" +Dynamic: license-file + +.. image:: https://github.com/agronholm/anyio/actions/workflows/test.yml/badge.svg + :target: https://github.com/agronholm/anyio/actions/workflows/test.yml + :alt: Build Status +.. image:: https://coveralls.io/repos/github/agronholm/anyio/badge.svg?branch=master + :target: https://coveralls.io/github/agronholm/anyio?branch=master + :alt: Code Coverage +.. image:: https://readthedocs.org/projects/anyio/badge/?version=latest + :target: https://anyio.readthedocs.io/en/latest/?badge=latest + :alt: Documentation +.. image:: https://badges.gitter.im/gitterHQ/gitter.svg + :target: https://gitter.im/python-trio/AnyIO + :alt: Gitter chat + +AnyIO is an asynchronous networking and concurrency library that works on top of either asyncio_ or +Trio_. It implements Trio-like `structured concurrency`_ (SC) on top of asyncio and works in harmony +with the native SC of Trio itself. + +Applications and libraries written against AnyIO's API will run unmodified on either asyncio_ or +Trio_. AnyIO can also be adopted into a library or application incrementally – bit by bit, no full +refactoring necessary. It will blend in with the native libraries of your chosen backend. + +To find out why you might want to use AnyIO's APIs instead of asyncio's, you can read about it +`here `_. + +Documentation +------------- + +View full documentation at: https://anyio.readthedocs.io/ + +Features +-------- + +AnyIO offers the following functionality: + +* Task groups (nurseries_ in trio terminology) +* High-level networking (TCP, UDP and UNIX sockets) + + * `Happy eyeballs`_ algorithm for TCP connections (more robust than that of asyncio on Python + 3.8) + * async/await style UDP sockets (unlike asyncio where you still have to use Transports and + Protocols) + +* A versatile API for byte streams and object streams +* Inter-task synchronization and communication (locks, conditions, events, semaphores, object + streams) +* Worker threads +* Subprocesses +* Subinterpreter support for code parallelization (on Python 3.13 and later) +* Asynchronous file I/O (using worker threads) +* Signal handling +* Asynchronous version of the functools_ module + +AnyIO also comes with its own pytest_ plugin which also supports asynchronous fixtures. +It even works with the popular Hypothesis_ library. + +.. _asyncio: https://docs.python.org/3/library/asyncio.html +.. _Trio: https://github.com/python-trio/trio +.. _structured concurrency: https://en.wikipedia.org/wiki/Structured_concurrency +.. _nurseries: https://trio.readthedocs.io/en/stable/reference-core.html#nurseries-and-spawning +.. _Happy eyeballs: https://en.wikipedia.org/wiki/Happy_Eyeballs +.. _pytest: https://docs.pytest.org/en/latest/ +.. _functools: https://docs.python.org/3/library/functools.html +.. _Hypothesis: https://hypothesis.works/ diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio-4.12.1.dist-info/RECORD b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio-4.12.1.dist-info/RECORD new file mode 100644 index 0000000..9b3de70 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio-4.12.1.dist-info/RECORD @@ -0,0 +1,50 @@ +anyio-4.12.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +anyio-4.12.1.dist-info/METADATA,sha256=DfiDab9Tmmcfy802lOLTMEHJQShkOSbopCwqCYbLuJk,4277 +anyio-4.12.1.dist-info/RECORD,, +anyio-4.12.1.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91 +anyio-4.12.1.dist-info/entry_points.txt,sha256=_d6Yu6uiaZmNe0CydowirE9Cmg7zUL2g08tQpoS3Qvc,39 +anyio-4.12.1.dist-info/licenses/LICENSE,sha256=U2GsncWPLvX9LpsJxoKXwX8ElQkJu8gCO9uC6s8iwrA,1081 +anyio-4.12.1.dist-info/top_level.txt,sha256=QglSMiWX8_5dpoVAEIHdEYzvqFMdSYWmCj6tYw2ITkQ,6 +anyio/__init__.py,sha256=7iDVqMUprUuKNY91FuoKqayAhR-OY136YDPI6P78HHk,6170 +anyio/_backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +anyio/_backends/_asyncio.py,sha256=xG6qv60mgGnL0mK82dxjH2b8hlkMlJ-x2BqIq3qv70Y,98863 +anyio/_backends/_trio.py,sha256=30Rctb7lm8g63ZHljVPVnj5aH-uK6oQvphjwUBoAzuI,41456 +anyio/_core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +anyio/_core/_asyncio_selector_thread.py,sha256=2PdxFM3cs02Kp6BSppbvmRT7q7asreTW5FgBxEsflBo,5626 +anyio/_core/_contextmanagers.py,sha256=YInBCabiEeS-UaP_Jdxa1CaFC71ETPW8HZTHIM8Rsc8,7215 +anyio/_core/_eventloop.py,sha256=c2EdcBX-xnKwxPcC4Pjn3_qG9I-x4IWFO2R9RqCGjM4,6448 +anyio/_core/_exceptions.py,sha256=Y3aq-Wxd7Q2HqwSg7nZPvRsHEuGazv_qeet6gqEBdPk,4407 +anyio/_core/_fileio.py,sha256=uc7t10Vb-If7GbdWM_zFf-ajUe6uek63fSt7IBLlZW0,25731 +anyio/_core/_resources.py,sha256=NbmU5O5UX3xEyACnkmYX28Fmwdl-f-ny0tHym26e0w0,435 +anyio/_core/_signals.py,sha256=mjTBB2hTKNPRlU0IhnijeQedpWOGERDiMjSlJQsFrug,1016 +anyio/_core/_sockets.py,sha256=RBXHcUqZt5gg_-OOfgHVv8uq2FSKk1uVUzTdpjBoI1o,34977 +anyio/_core/_streams.py,sha256=FczFwIgDpnkK0bODWJXMpsUJYdvAD04kaUaGzJU8DK0,1806 +anyio/_core/_subprocesses.py,sha256=EXm5igL7dj55iYkPlbYVAqtbqxJxjU-6OndSTIx9SRg,8047 +anyio/_core/_synchronization.py,sha256=MgVVqFzvt580tHC31LiOcq1G6aryut--xRG4Ff8KwxQ,20869 +anyio/_core/_tasks.py,sha256=pVB7K6AAulzUM8YgXAeqNZG44nSyZ1bYJjH8GznC00I,5435 +anyio/_core/_tempfile.py,sha256=lHb7CW4FyIlpkf5ADAf4VmLHCKwEHF9nxqNyBCFFUiA,19697 +anyio/_core/_testing.py,sha256=u7MPqGXwpTxqI7hclSdNA30z2GH1Nw258uwKvy_RfBg,2340 +anyio/_core/_typedattr.py,sha256=P4ozZikn3-DbpoYcvyghS_FOYAgbmUxeoU8-L_07pZM,2508 +anyio/abc/__init__.py,sha256=6mWhcl_pGXhrgZVHP_TCfMvIXIOp9mroEFM90fYCU_U,2869 +anyio/abc/_eventloop.py,sha256=GlzgB3UJGgG6Kr7olpjOZ-o00PghecXuofVDQ_5611Q,10749 +anyio/abc/_resources.py,sha256=DrYvkNN1hH6Uvv5_5uKySvDsnknGVDe8FCKfko0VtN8,783 +anyio/abc/_sockets.py,sha256=ECTY0jLEF18gryANHR3vFzXzGdZ-xPwELq1QdgOb0Jo,13258 +anyio/abc/_streams.py,sha256=005GKSCXGprxnhucILboSqc2JFovECZk9m3p-qqxXVc,7640 +anyio/abc/_subprocesses.py,sha256=cumAPJTktOQtw63IqG0lDpyZqu_l1EElvQHMiwJgL08,2067 +anyio/abc/_tasks.py,sha256=KC7wrciE48AINOI-AhPutnFhe1ewfP7QnamFlDzqesQ,3721 +anyio/abc/_testing.py,sha256=tBJUzkSfOXJw23fe8qSJ03kJlShOYjjaEyFB6k6MYT8,1821 +anyio/from_thread.py,sha256=L-0w1HxJ6BSb-KuVi57k5Tkc3yzQrx3QK5tAxMPcY-0,19141 +anyio/functools.py,sha256=HWj7GBEmc0Z-mZg3uok7Z7ZJn0rEC_0Pzbt0nYUDaTQ,10973 +anyio/lowlevel.py,sha256=AyKLVK3LaWSoK39LkCKxE4_GDMLKZBNqTrLUgk63y80,5158 +anyio/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +anyio/pytest_plugin.py,sha256=3jAFQn0jv_pyoWE2GBBlHaj9sqXj4e8vob0_hgrsXE8,10244 +anyio/streams/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +anyio/streams/buffered.py,sha256=2R3PeJhe4EXrdYqz44Y6-Eg9R6DrmlsYrP36Ir43-po,6263 +anyio/streams/file.py,sha256=4WZ7XGz5WNu39FQHvqbe__TQ0HDP9OOhgO1mk9iVpVU,4470 +anyio/streams/memory.py,sha256=F0zwzvFJKAhX_LRZGoKzzqDC2oMM-f-yyTBrEYEGOaU,10740 +anyio/streams/stapled.py,sha256=T8Xqwf8K6EgURPxbt1N4i7A8BAk-gScv-GRhjLXIf_o,4390 +anyio/streams/text.py,sha256=BcVAGJw1VRvtIqnv-o0Rb0pwH7p8vwlvl21xHq522ag,5765 +anyio/streams/tls.py,sha256=Jpxy0Mfbcp1BxHCwE-YjSSFaLnIBbnnwur-excYThs4,15368 +anyio/to_interpreter.py,sha256=_mLngrMy97TMR6VbW4Y6YzDUk9ZuPcQMPlkuyRh3C9k,7100 +anyio/to_process.py,sha256=J7gAA_YOuoHqnpDAf5fm1Qu6kOmTzdFbiDNvnV755vk,9798 +anyio/to_thread.py,sha256=menEgXYmUV7Fjg_9WqCV95P9MAtQS8BzPGGcWB_QnfQ,2687 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio-4.12.1.dist-info/WHEEL b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio-4.12.1.dist-info/WHEEL new file mode 100644 index 0000000..14a883f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio-4.12.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: setuptools (82.0.1) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio-4.12.1.dist-info/entry_points.txt b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio-4.12.1.dist-info/entry_points.txt new file mode 100644 index 0000000..44dd9bd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio-4.12.1.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[pytest11] +anyio = anyio.pytest_plugin diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio-4.12.1.dist-info/licenses/LICENSE b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio-4.12.1.dist-info/licenses/LICENSE new file mode 100644 index 0000000..104eebf --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio-4.12.1.dist-info/licenses/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2018 Alex Grönholm + +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. diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio-4.12.1.dist-info/top_level.txt b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio-4.12.1.dist-info/top_level.txt new file mode 100644 index 0000000..c77c069 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio-4.12.1.dist-info/top_level.txt @@ -0,0 +1 @@ +anyio diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/__init__.py new file mode 100644 index 0000000..d23c5a5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/__init__.py @@ -0,0 +1,111 @@ +from __future__ import annotations + +from ._core._contextmanagers import AsyncContextManagerMixin as AsyncContextManagerMixin +from ._core._contextmanagers import ContextManagerMixin as ContextManagerMixin +from ._core._eventloop import current_time as current_time +from ._core._eventloop import get_all_backends as get_all_backends +from ._core._eventloop import get_available_backends as get_available_backends +from ._core._eventloop import get_cancelled_exc_class as get_cancelled_exc_class +from ._core._eventloop import run as run +from ._core._eventloop import sleep as sleep +from ._core._eventloop import sleep_forever as sleep_forever +from ._core._eventloop import sleep_until as sleep_until +from ._core._exceptions import BrokenResourceError as BrokenResourceError +from ._core._exceptions import BrokenWorkerInterpreter as BrokenWorkerInterpreter +from ._core._exceptions import BrokenWorkerProcess as BrokenWorkerProcess +from ._core._exceptions import BusyResourceError as BusyResourceError +from ._core._exceptions import ClosedResourceError as ClosedResourceError +from ._core._exceptions import ConnectionFailed as ConnectionFailed +from ._core._exceptions import DelimiterNotFound as DelimiterNotFound +from ._core._exceptions import EndOfStream as EndOfStream +from ._core._exceptions import IncompleteRead as IncompleteRead +from ._core._exceptions import NoEventLoopError as NoEventLoopError +from ._core._exceptions import RunFinishedError as RunFinishedError +from ._core._exceptions import TypedAttributeLookupError as TypedAttributeLookupError +from ._core._exceptions import WouldBlock as WouldBlock +from ._core._fileio import AsyncFile as AsyncFile +from ._core._fileio import Path as Path +from ._core._fileio import open_file as open_file +from ._core._fileio import wrap_file as wrap_file +from ._core._resources import aclose_forcefully as aclose_forcefully +from ._core._signals import open_signal_receiver as open_signal_receiver +from ._core._sockets import TCPConnectable as TCPConnectable +from ._core._sockets import UNIXConnectable as UNIXConnectable +from ._core._sockets import as_connectable as as_connectable +from ._core._sockets import connect_tcp as connect_tcp +from ._core._sockets import connect_unix as connect_unix +from ._core._sockets import create_connected_udp_socket as create_connected_udp_socket +from ._core._sockets import ( + create_connected_unix_datagram_socket as create_connected_unix_datagram_socket, +) +from ._core._sockets import create_tcp_listener as create_tcp_listener +from ._core._sockets import create_udp_socket as create_udp_socket +from ._core._sockets import create_unix_datagram_socket as create_unix_datagram_socket +from ._core._sockets import create_unix_listener as create_unix_listener +from ._core._sockets import getaddrinfo as getaddrinfo +from ._core._sockets import getnameinfo as getnameinfo +from ._core._sockets import notify_closing as notify_closing +from ._core._sockets import wait_readable as wait_readable +from ._core._sockets import wait_socket_readable as wait_socket_readable +from ._core._sockets import wait_socket_writable as wait_socket_writable +from ._core._sockets import wait_writable as wait_writable +from ._core._streams import create_memory_object_stream as create_memory_object_stream +from ._core._subprocesses import open_process as open_process +from ._core._subprocesses import run_process as run_process +from ._core._synchronization import CapacityLimiter as CapacityLimiter +from ._core._synchronization import ( + CapacityLimiterStatistics as CapacityLimiterStatistics, +) +from ._core._synchronization import Condition as Condition +from ._core._synchronization import ConditionStatistics as ConditionStatistics +from ._core._synchronization import Event as Event +from ._core._synchronization import EventStatistics as EventStatistics +from ._core._synchronization import Lock as Lock +from ._core._synchronization import LockStatistics as LockStatistics +from ._core._synchronization import ResourceGuard as ResourceGuard +from ._core._synchronization import Semaphore as Semaphore +from ._core._synchronization import SemaphoreStatistics as SemaphoreStatistics +from ._core._tasks import TASK_STATUS_IGNORED as TASK_STATUS_IGNORED +from ._core._tasks import CancelScope as CancelScope +from ._core._tasks import create_task_group as create_task_group +from ._core._tasks import current_effective_deadline as current_effective_deadline +from ._core._tasks import fail_after as fail_after +from ._core._tasks import move_on_after as move_on_after +from ._core._tempfile import NamedTemporaryFile as NamedTemporaryFile +from ._core._tempfile import SpooledTemporaryFile as SpooledTemporaryFile +from ._core._tempfile import TemporaryDirectory as TemporaryDirectory +from ._core._tempfile import TemporaryFile as TemporaryFile +from ._core._tempfile import gettempdir as gettempdir +from ._core._tempfile import gettempdirb as gettempdirb +from ._core._tempfile import mkdtemp as mkdtemp +from ._core._tempfile import mkstemp as mkstemp +from ._core._testing import TaskInfo as TaskInfo +from ._core._testing import get_current_task as get_current_task +from ._core._testing import get_running_tasks as get_running_tasks +from ._core._testing import wait_all_tasks_blocked as wait_all_tasks_blocked +from ._core._typedattr import TypedAttributeProvider as TypedAttributeProvider +from ._core._typedattr import TypedAttributeSet as TypedAttributeSet +from ._core._typedattr import typed_attribute as typed_attribute + +# Re-export imports so they look like they live directly in this package +for __value in list(locals().values()): + if getattr(__value, "__module__", "").startswith("anyio."): + __value.__module__ = __name__ + + +del __value + + +def __getattr__(attr: str) -> type[BrokenWorkerInterpreter]: + """Support deprecated aliases.""" + if attr == "BrokenWorkerIntepreter": + import warnings + + warnings.warn( + "The 'BrokenWorkerIntepreter' alias is deprecated, use 'BrokenWorkerInterpreter' instead.", + DeprecationWarning, + stacklevel=2, + ) + return BrokenWorkerInterpreter + + raise AttributeError(f"module {__name__!r} has no attribute {attr!r}") diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_backends/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_backends/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_backends/_asyncio.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_backends/_asyncio.py new file mode 100644 index 0000000..8ff009e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_backends/_asyncio.py @@ -0,0 +1,2980 @@ +from __future__ import annotations + +import array +import asyncio +import concurrent.futures +import contextvars +import math +import os +import socket +import sys +import threading +import weakref +from asyncio import ( + AbstractEventLoop, + CancelledError, + all_tasks, + create_task, + current_task, + get_running_loop, + sleep, +) +from asyncio.base_events import _run_until_complete_cb # type: ignore[attr-defined] +from collections import OrderedDict, deque +from collections.abc import ( + AsyncGenerator, + AsyncIterator, + Awaitable, + Callable, + Collection, + Coroutine, + Iterable, + Sequence, +) +from concurrent.futures import Future +from contextlib import AbstractContextManager, suppress +from contextvars import Context, copy_context +from dataclasses import dataclass, field +from functools import partial, wraps +from inspect import ( + CORO_RUNNING, + CORO_SUSPENDED, + getcoroutinestate, + iscoroutine, +) +from io import IOBase +from os import PathLike +from queue import Queue +from signal import Signals +from socket import AddressFamily, SocketKind +from threading import Thread +from types import CodeType, TracebackType +from typing import ( + IO, + TYPE_CHECKING, + Any, + Optional, + TypeVar, + cast, +) +from weakref import WeakKeyDictionary + +from .. import ( + CapacityLimiterStatistics, + EventStatistics, + LockStatistics, + TaskInfo, + abc, +) +from .._core._eventloop import ( + claim_worker_thread, + set_current_async_library, + threadlocals, +) +from .._core._exceptions import ( + BrokenResourceError, + BusyResourceError, + ClosedResourceError, + EndOfStream, + RunFinishedError, + WouldBlock, + iterate_exceptions, +) +from .._core._sockets import convert_ipv6_sockaddr +from .._core._streams import create_memory_object_stream +from .._core._synchronization import ( + CapacityLimiter as BaseCapacityLimiter, +) +from .._core._synchronization import Event as BaseEvent +from .._core._synchronization import Lock as BaseLock +from .._core._synchronization import ( + ResourceGuard, + SemaphoreStatistics, +) +from .._core._synchronization import Semaphore as BaseSemaphore +from .._core._tasks import CancelScope as BaseCancelScope +from ..abc import ( + AsyncBackend, + IPSockAddrType, + SocketListener, + UDPPacketType, + UNIXDatagramPacketType, +) +from ..abc._eventloop import StrOrBytesPath +from ..lowlevel import RunVar +from ..streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream + +if TYPE_CHECKING: + from _typeshed import FileDescriptorLike +else: + FileDescriptorLike = object + +if sys.version_info >= (3, 10): + from typing import ParamSpec +else: + from typing_extensions import ParamSpec + +if sys.version_info >= (3, 11): + from asyncio import Runner + from typing import TypeVarTuple, Unpack +else: + import contextvars + import enum + import signal + from asyncio import coroutines, events, exceptions, tasks + + from exceptiongroup import BaseExceptionGroup + from typing_extensions import TypeVarTuple, Unpack + + class _State(enum.Enum): + CREATED = "created" + INITIALIZED = "initialized" + CLOSED = "closed" + + class Runner: + # Copied from CPython 3.11 + def __init__( + self, + *, + debug: bool | None = None, + loop_factory: Callable[[], AbstractEventLoop] | None = None, + ): + self._state = _State.CREATED + self._debug = debug + self._loop_factory = loop_factory + self._loop: AbstractEventLoop | None = None + self._context = None + self._interrupt_count = 0 + self._set_event_loop = False + + def __enter__(self) -> Runner: + self._lazy_init() + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + self.close() + + def close(self) -> None: + """Shutdown and close event loop.""" + loop = self._loop + if self._state is not _State.INITIALIZED or loop is None: + return + try: + _cancel_all_tasks(loop) + loop.run_until_complete(loop.shutdown_asyncgens()) + if hasattr(loop, "shutdown_default_executor"): + loop.run_until_complete(loop.shutdown_default_executor()) + else: + loop.run_until_complete(_shutdown_default_executor(loop)) + finally: + if self._set_event_loop: + events.set_event_loop(None) + loop.close() + self._loop = None + self._state = _State.CLOSED + + def get_loop(self) -> AbstractEventLoop: + """Return embedded event loop.""" + self._lazy_init() + return self._loop + + def run(self, coro: Coroutine[T_Retval], *, context=None) -> T_Retval: + """Run a coroutine inside the embedded event loop.""" + if not coroutines.iscoroutine(coro): + raise ValueError(f"a coroutine was expected, got {coro!r}") + + if events._get_running_loop() is not None: + # fail fast with short traceback + raise RuntimeError( + "Runner.run() cannot be called from a running event loop" + ) + + self._lazy_init() + + if context is None: + context = self._context + task = context.run(self._loop.create_task, coro) + + if ( + threading.current_thread() is threading.main_thread() + and signal.getsignal(signal.SIGINT) is signal.default_int_handler + ): + sigint_handler = partial(self._on_sigint, main_task=task) + try: + signal.signal(signal.SIGINT, sigint_handler) + except ValueError: + # `signal.signal` may throw if `threading.main_thread` does + # not support signals (e.g. embedded interpreter with signals + # not registered - see gh-91880) + sigint_handler = None + else: + sigint_handler = None + + self._interrupt_count = 0 + try: + return self._loop.run_until_complete(task) + except exceptions.CancelledError: + if self._interrupt_count > 0: + uncancel = getattr(task, "uncancel", None) + if uncancel is not None and uncancel() == 0: + raise KeyboardInterrupt # noqa: B904 + raise # CancelledError + finally: + if ( + sigint_handler is not None + and signal.getsignal(signal.SIGINT) is sigint_handler + ): + signal.signal(signal.SIGINT, signal.default_int_handler) + + def _lazy_init(self) -> None: + if self._state is _State.CLOSED: + raise RuntimeError("Runner is closed") + if self._state is _State.INITIALIZED: + return + if self._loop_factory is None: + self._loop = events.new_event_loop() + if not self._set_event_loop: + # Call set_event_loop only once to avoid calling + # attach_loop multiple times on child watchers + events.set_event_loop(self._loop) + self._set_event_loop = True + else: + self._loop = self._loop_factory() + if self._debug is not None: + self._loop.set_debug(self._debug) + self._context = contextvars.copy_context() + self._state = _State.INITIALIZED + + def _on_sigint(self, signum, frame, main_task: asyncio.Task) -> None: + self._interrupt_count += 1 + if self._interrupt_count == 1 and not main_task.done(): + main_task.cancel() + # wakeup loop if it is blocked by select() with long timeout + self._loop.call_soon_threadsafe(lambda: None) + return + raise KeyboardInterrupt() + + def _cancel_all_tasks(loop: AbstractEventLoop) -> None: + to_cancel = tasks.all_tasks(loop) + if not to_cancel: + return + + for task in to_cancel: + task.cancel() + + loop.run_until_complete(tasks.gather(*to_cancel, return_exceptions=True)) + + for task in to_cancel: + if task.cancelled(): + continue + if task.exception() is not None: + loop.call_exception_handler( + { + "message": "unhandled exception during asyncio.run() shutdown", + "exception": task.exception(), + "task": task, + } + ) + + async def _shutdown_default_executor(loop: AbstractEventLoop) -> None: + """Schedule the shutdown of the default executor.""" + + def _do_shutdown(future: asyncio.futures.Future) -> None: + try: + loop._default_executor.shutdown(wait=True) # type: ignore[attr-defined] + loop.call_soon_threadsafe(future.set_result, None) + except Exception as ex: + loop.call_soon_threadsafe(future.set_exception, ex) + + loop._executor_shutdown_called = True + if loop._default_executor is None: + return + future = loop.create_future() + thread = threading.Thread(target=_do_shutdown, args=(future,)) + thread.start() + try: + await future + finally: + thread.join() + + +T_Retval = TypeVar("T_Retval") +T_contra = TypeVar("T_contra", contravariant=True) +PosArgsT = TypeVarTuple("PosArgsT") +P = ParamSpec("P") + +_root_task: RunVar[asyncio.Task | None] = RunVar("_root_task") + + +def find_root_task() -> asyncio.Task: + root_task = _root_task.get(None) + if root_task is not None and not root_task.done(): + return root_task + + # Look for a task that has been started via run_until_complete() + for task in all_tasks(): + if task._callbacks and not task.done(): + callbacks = [cb for cb, context in task._callbacks] + for cb in callbacks: + if ( + cb is _run_until_complete_cb + or getattr(cb, "__module__", None) == "uvloop.loop" + ): + _root_task.set(task) + return task + + # Look up the topmost task in the AnyIO task tree, if possible + task = cast(asyncio.Task, current_task()) + state = _task_states.get(task) + if state: + cancel_scope = state.cancel_scope + while cancel_scope and cancel_scope._parent_scope is not None: + cancel_scope = cancel_scope._parent_scope + + if cancel_scope is not None: + return cast(asyncio.Task, cancel_scope._host_task) + + return task + + +def get_callable_name(func: Callable) -> str: + module = getattr(func, "__module__", None) + qualname = getattr(func, "__qualname__", None) + return ".".join([x for x in (module, qualname) if x]) + + +# +# Event loop +# + +_run_vars: WeakKeyDictionary[asyncio.AbstractEventLoop, Any] = WeakKeyDictionary() + + +def _task_started(task: asyncio.Task) -> bool: + """Return ``True`` if the task has been started and has not finished.""" + # The task coro should never be None here, as we never add finished tasks to the + # task list + coro = task.get_coro() + assert coro is not None + try: + return getcoroutinestate(coro) in (CORO_RUNNING, CORO_SUSPENDED) + except AttributeError: + # task coro is async_genenerator_asend https://bugs.python.org/issue37771 + raise Exception(f"Cannot determine if task {task} has started or not") from None + + +# +# Timeouts and cancellation +# + + +def is_anyio_cancellation(exc: CancelledError) -> bool: + # Sometimes third party frameworks catch a CancelledError and raise a new one, so as + # a workaround we have to look at the previous ones in __context__ too for a + # matching cancel message + while True: + if ( + exc.args + and isinstance(exc.args[0], str) + and exc.args[0].startswith("Cancelled via cancel scope ") + ): + return True + + if isinstance(exc.__context__, CancelledError): + exc = exc.__context__ + continue + + return False + + +class CancelScope(BaseCancelScope): + def __new__( + cls, *, deadline: float = math.inf, shield: bool = False + ) -> CancelScope: + return object.__new__(cls) + + def __init__(self, deadline: float = math.inf, shield: bool = False): + self._deadline = deadline + self._shield = shield + self._parent_scope: CancelScope | None = None + self._child_scopes: set[CancelScope] = set() + self._cancel_called = False + self._cancel_reason: str | None = None + self._cancelled_caught = False + self._active = False + self._timeout_handle: asyncio.TimerHandle | None = None + self._cancel_handle: asyncio.Handle | None = None + self._tasks: set[asyncio.Task] = set() + self._host_task: asyncio.Task | None = None + if sys.version_info >= (3, 11): + self._pending_uncancellations: int | None = 0 + else: + self._pending_uncancellations = None + + def __enter__(self) -> CancelScope: + if self._active: + raise RuntimeError( + "Each CancelScope may only be used for a single 'with' block" + ) + + self._host_task = host_task = cast(asyncio.Task, current_task()) + self._tasks.add(host_task) + try: + task_state = _task_states[host_task] + except KeyError: + task_state = TaskState(None, self) + _task_states[host_task] = task_state + else: + self._parent_scope = task_state.cancel_scope + task_state.cancel_scope = self + if self._parent_scope is not None: + # If using an eager task factory, the parent scope may not even contain + # the host task + self._parent_scope._child_scopes.add(self) + self._parent_scope._tasks.discard(host_task) + + self._timeout() + self._active = True + + # Start cancelling the host task if the scope was cancelled before entering + if self._cancel_called: + self._deliver_cancellation(self) + + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> bool: + del exc_tb + + if not self._active: + raise RuntimeError("This cancel scope is not active") + if current_task() is not self._host_task: + raise RuntimeError( + "Attempted to exit cancel scope in a different task than it was " + "entered in" + ) + + assert self._host_task is not None + host_task_state = _task_states.get(self._host_task) + if host_task_state is None or host_task_state.cancel_scope is not self: + raise RuntimeError( + "Attempted to exit a cancel scope that isn't the current tasks's " + "current cancel scope" + ) + + try: + self._active = False + if self._timeout_handle: + self._timeout_handle.cancel() + self._timeout_handle = None + + self._tasks.remove(self._host_task) + if self._parent_scope is not None: + self._parent_scope._child_scopes.remove(self) + self._parent_scope._tasks.add(self._host_task) + + host_task_state.cancel_scope = self._parent_scope + + # Restart the cancellation effort in the closest visible, cancelled parent + # scope if necessary + self._restart_cancellation_in_parent() + + # We only swallow the exception iff it was an AnyIO CancelledError, either + # directly as exc_val or inside an exception group and there are no cancelled + # parent cancel scopes visible to us here + if self._cancel_called and not self._parent_cancellation_is_visible_to_us: + # For each level-cancel() call made on the host task, call uncancel() + while self._pending_uncancellations: + self._host_task.uncancel() + self._pending_uncancellations -= 1 + + # Update cancelled_caught and check for exceptions we must not swallow + cannot_swallow_exc_val = False + if exc_val is not None: + for exc in iterate_exceptions(exc_val): + if isinstance(exc, CancelledError) and is_anyio_cancellation( + exc + ): + self._cancelled_caught = True + else: + cannot_swallow_exc_val = True + + return self._cancelled_caught and not cannot_swallow_exc_val + else: + if self._pending_uncancellations: + assert self._parent_scope is not None + assert self._parent_scope._pending_uncancellations is not None + self._parent_scope._pending_uncancellations += ( + self._pending_uncancellations + ) + self._pending_uncancellations = 0 + + return False + finally: + self._host_task = None + del exc_val + + @property + def _effectively_cancelled(self) -> bool: + cancel_scope: CancelScope | None = self + while cancel_scope is not None: + if cancel_scope._cancel_called: + return True + + if cancel_scope.shield: + return False + + cancel_scope = cancel_scope._parent_scope + + return False + + @property + def _parent_cancellation_is_visible_to_us(self) -> bool: + return ( + self._parent_scope is not None + and not self.shield + and self._parent_scope._effectively_cancelled + ) + + def _timeout(self) -> None: + if self._deadline != math.inf: + loop = get_running_loop() + if loop.time() >= self._deadline: + self.cancel("deadline exceeded") + else: + self._timeout_handle = loop.call_at(self._deadline, self._timeout) + + def _deliver_cancellation(self, origin: CancelScope) -> bool: + """ + Deliver cancellation to directly contained tasks and nested cancel scopes. + + Schedule another run at the end if we still have tasks eligible for + cancellation. + + :param origin: the cancel scope that originated the cancellation + :return: ``True`` if the delivery needs to be retried on the next cycle + + """ + should_retry = False + current = current_task() + for task in self._tasks: + should_retry = True + if task._must_cancel: # type: ignore[attr-defined] + continue + + # The task is eligible for cancellation if it has started + if task is not current and (task is self._host_task or _task_started(task)): + waiter = task._fut_waiter # type: ignore[attr-defined] + if not isinstance(waiter, asyncio.Future) or not waiter.done(): + task.cancel(origin._cancel_reason) + if ( + task is origin._host_task + and origin._pending_uncancellations is not None + ): + origin._pending_uncancellations += 1 + + # Deliver cancellation to child scopes that aren't shielded or running their own + # cancellation callbacks + for scope in self._child_scopes: + if not scope._shield and not scope.cancel_called: + should_retry = scope._deliver_cancellation(origin) or should_retry + + # Schedule another callback if there are still tasks left + if origin is self: + if should_retry: + self._cancel_handle = get_running_loop().call_soon( + self._deliver_cancellation, origin + ) + else: + self._cancel_handle = None + + return should_retry + + def _restart_cancellation_in_parent(self) -> None: + """ + Restart the cancellation effort in the closest directly cancelled parent scope. + + """ + scope = self._parent_scope + while scope is not None: + if scope._cancel_called: + if scope._cancel_handle is None: + scope._deliver_cancellation(scope) + + break + + # No point in looking beyond any shielded scope + if scope._shield: + break + + scope = scope._parent_scope + + def cancel(self, reason: str | None = None) -> None: + if not self._cancel_called: + if self._timeout_handle: + self._timeout_handle.cancel() + self._timeout_handle = None + + self._cancel_called = True + self._cancel_reason = f"Cancelled via cancel scope {id(self):x}" + if task := current_task(): + self._cancel_reason += f" by {task}" + + if reason: + self._cancel_reason += f"; reason: {reason}" + + if self._host_task is not None: + self._deliver_cancellation(self) + + @property + def deadline(self) -> float: + return self._deadline + + @deadline.setter + def deadline(self, value: float) -> None: + self._deadline = float(value) + if self._timeout_handle is not None: + self._timeout_handle.cancel() + self._timeout_handle = None + + if self._active and not self._cancel_called: + self._timeout() + + @property + def cancel_called(self) -> bool: + return self._cancel_called + + @property + def cancelled_caught(self) -> bool: + return self._cancelled_caught + + @property + def shield(self) -> bool: + return self._shield + + @shield.setter + def shield(self, value: bool) -> None: + if self._shield != value: + self._shield = value + if not value: + self._restart_cancellation_in_parent() + + +# +# Task states +# + + +class TaskState: + """ + Encapsulates auxiliary task information that cannot be added to the Task instance + itself because there are no guarantees about its implementation. + """ + + __slots__ = "parent_id", "cancel_scope", "__weakref__" + + def __init__(self, parent_id: int | None, cancel_scope: CancelScope | None): + self.parent_id = parent_id + self.cancel_scope = cancel_scope + + +_task_states: WeakKeyDictionary[asyncio.Task, TaskState] = WeakKeyDictionary() + + +# +# Task groups +# + + +class _AsyncioTaskStatus(abc.TaskStatus): + def __init__(self, future: asyncio.Future, parent_id: int): + self._future = future + self._parent_id = parent_id + + def started(self, value: T_contra | None = None) -> None: + try: + self._future.set_result(value) + except asyncio.InvalidStateError: + if not self._future.cancelled(): + raise RuntimeError( + "called 'started' twice on the same task status" + ) from None + + task = cast(asyncio.Task, current_task()) + _task_states[task].parent_id = self._parent_id + + +if sys.version_info >= (3, 12): + _eager_task_factory_code: CodeType | None = asyncio.eager_task_factory.__code__ +else: + _eager_task_factory_code = None + + +class TaskGroup(abc.TaskGroup): + def __init__(self) -> None: + self.cancel_scope: CancelScope = CancelScope() + self._active = False + self._exceptions: list[BaseException] = [] + self._tasks: set[asyncio.Task] = set() + self._on_completed_fut: asyncio.Future[None] | None = None + + async def __aenter__(self) -> TaskGroup: + self.cancel_scope.__enter__() + self._active = True + return self + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> bool: + try: + if exc_val is not None: + self.cancel_scope.cancel() + if not isinstance(exc_val, CancelledError): + self._exceptions.append(exc_val) + + loop = get_running_loop() + try: + if self._tasks: + with CancelScope() as wait_scope: + while self._tasks: + self._on_completed_fut = loop.create_future() + + try: + await self._on_completed_fut + except CancelledError as exc: + # Shield the scope against further cancellation attempts, + # as they're not productive (#695) + wait_scope.shield = True + self.cancel_scope.cancel() + + # Set exc_val from the cancellation exception if it was + # previously unset. However, we should not replace a native + # cancellation exception with one raise by a cancel scope. + if exc_val is None or ( + isinstance(exc_val, CancelledError) + and not is_anyio_cancellation(exc) + ): + exc_val = exc + + self._on_completed_fut = None + else: + # If there are no child tasks to wait on, run at least one checkpoint + # anyway + await AsyncIOBackend.cancel_shielded_checkpoint() + + self._active = False + if self._exceptions: + # The exception that got us here should already have been + # added to self._exceptions so it's ok to break exception + # chaining and avoid adding a "During handling of above..." + # for each nesting level. + raise BaseExceptionGroup( + "unhandled errors in a TaskGroup", self._exceptions + ) from None + elif exc_val: + raise exc_val + except BaseException as exc: + if self.cancel_scope.__exit__(type(exc), exc, exc.__traceback__): + return True + + raise + + return self.cancel_scope.__exit__(exc_type, exc_val, exc_tb) + finally: + del exc_val, exc_tb, self._exceptions + + def _spawn( + self, + func: Callable[[Unpack[PosArgsT]], Awaitable[Any]], + args: tuple[Unpack[PosArgsT]], + name: object, + task_status_future: asyncio.Future | None = None, + ) -> asyncio.Task: + def task_done(_task: asyncio.Task) -> None: + if sys.version_info >= (3, 14) and self.cancel_scope._host_task is not None: + asyncio.future_discard_from_awaited_by( + _task, self.cancel_scope._host_task + ) + + task_state = _task_states[_task] + assert task_state.cancel_scope is not None + assert _task in task_state.cancel_scope._tasks + task_state.cancel_scope._tasks.remove(_task) + self._tasks.remove(task) + del _task_states[_task] + + if self._on_completed_fut is not None and not self._tasks: + try: + self._on_completed_fut.set_result(None) + except asyncio.InvalidStateError: + pass + + try: + exc = _task.exception() + except CancelledError as e: + while isinstance(e.__context__, CancelledError): + e = e.__context__ + + exc = e + + if exc is not None: + # The future can only be in the cancelled state if the host task was + # cancelled, so return immediately instead of adding one more + # CancelledError to the exceptions list + if task_status_future is not None and task_status_future.cancelled(): + return + + if task_status_future is None or task_status_future.done(): + if not isinstance(exc, CancelledError): + self._exceptions.append(exc) + + if not self.cancel_scope._effectively_cancelled: + self.cancel_scope.cancel() + else: + task_status_future.set_exception(exc) + elif task_status_future is not None and not task_status_future.done(): + task_status_future.set_exception( + RuntimeError("Child exited without calling task_status.started()") + ) + + if not self._active: + raise RuntimeError( + "This task group is not active; no new tasks can be started." + ) + + kwargs = {} + if task_status_future: + parent_id = id(current_task()) + kwargs["task_status"] = _AsyncioTaskStatus( + task_status_future, id(self.cancel_scope._host_task) + ) + else: + parent_id = id(self.cancel_scope._host_task) + + coro = func(*args, **kwargs) + if not iscoroutine(coro): + prefix = f"{func.__module__}." if hasattr(func, "__module__") else "" + raise TypeError( + f"Expected {prefix}{func.__qualname__}() to return a coroutine, but " + f"the return value ({coro!r}) is not a coroutine object" + ) + + name = get_callable_name(func) if name is None else str(name) + loop = asyncio.get_running_loop() + if ( + (factory := loop.get_task_factory()) + and getattr(factory, "__code__", None) is _eager_task_factory_code + and (closure := getattr(factory, "__closure__", None)) + ): + custom_task_constructor = closure[0].cell_contents + task = custom_task_constructor(coro, loop=loop, name=name) + else: + task = create_task(coro, name=name) + + # Make the spawned task inherit the task group's cancel scope + _task_states[task] = TaskState( + parent_id=parent_id, cancel_scope=self.cancel_scope + ) + self.cancel_scope._tasks.add(task) + self._tasks.add(task) + if sys.version_info >= (3, 14) and self.cancel_scope._host_task is not None: + asyncio.future_add_to_awaited_by(task, self.cancel_scope._host_task) + + task.add_done_callback(task_done) + return task + + def start_soon( + self, + func: Callable[[Unpack[PosArgsT]], Awaitable[Any]], + *args: Unpack[PosArgsT], + name: object = None, + ) -> None: + self._spawn(func, args, name) + + async def start( + self, func: Callable[..., Awaitable[Any]], *args: object, name: object = None + ) -> Any: + future: asyncio.Future = asyncio.Future() + task = self._spawn(func, args, name, future) + + # If the task raises an exception after sending a start value without a switch + # point between, the task group is cancelled and this method never proceeds to + # process the completed future. That's why we have to have a shielded cancel + # scope here. + try: + return await future + except CancelledError: + # Cancel the task and wait for it to exit before returning + task.cancel() + with CancelScope(shield=True), suppress(CancelledError): + await task + + raise + + +# +# Threads +# + +_Retval_Queue_Type = tuple[Optional[T_Retval], Optional[BaseException]] + + +class WorkerThread(Thread): + MAX_IDLE_TIME = 10 # seconds + + def __init__( + self, + root_task: asyncio.Task, + workers: set[WorkerThread], + idle_workers: deque[WorkerThread], + ): + super().__init__(name="AnyIO worker thread") + self.root_task = root_task + self.workers = workers + self.idle_workers = idle_workers + self.loop = root_task._loop + self.queue: Queue[ + tuple[Context, Callable, tuple, asyncio.Future, CancelScope] | None + ] = Queue(2) + self.idle_since = AsyncIOBackend.current_time() + self.stopping = False + + def _report_result( + self, future: asyncio.Future, result: Any, exc: BaseException | None + ) -> None: + self.idle_since = AsyncIOBackend.current_time() + if not self.stopping: + self.idle_workers.append(self) + + if not future.cancelled(): + if exc is not None: + if isinstance(exc, StopIteration): + new_exc = RuntimeError("coroutine raised StopIteration") + new_exc.__cause__ = exc + exc = new_exc + + future.set_exception(exc) + else: + future.set_result(result) + + def run(self) -> None: + with claim_worker_thread(AsyncIOBackend, self.loop): + while True: + item = self.queue.get() + if item is None: + # Shutdown command received + return + + context, func, args, future, cancel_scope = item + if not future.cancelled(): + result = None + exception: BaseException | None = None + threadlocals.current_cancel_scope = cancel_scope + try: + result = context.run(func, *args) + except BaseException as exc: + exception = exc + finally: + del threadlocals.current_cancel_scope + + if not self.loop.is_closed(): + self.loop.call_soon_threadsafe( + self._report_result, future, result, exception + ) + + del result, exception + + self.queue.task_done() + del item, context, func, args, future, cancel_scope + + def stop(self, f: asyncio.Task | None = None) -> None: + self.stopping = True + self.queue.put_nowait(None) + self.workers.discard(self) + try: + self.idle_workers.remove(self) + except ValueError: + pass + + +_threadpool_idle_workers: RunVar[deque[WorkerThread]] = RunVar( + "_threadpool_idle_workers" +) +_threadpool_workers: RunVar[set[WorkerThread]] = RunVar("_threadpool_workers") + + +# +# Subprocesses +# + + +@dataclass(eq=False) +class StreamReaderWrapper(abc.ByteReceiveStream): + _stream: asyncio.StreamReader + + async def receive(self, max_bytes: int = 65536) -> bytes: + data = await self._stream.read(max_bytes) + if data: + return data + else: + raise EndOfStream + + async def aclose(self) -> None: + self._stream.set_exception(ClosedResourceError()) + await AsyncIOBackend.checkpoint() + + +@dataclass(eq=False) +class StreamWriterWrapper(abc.ByteSendStream): + _stream: asyncio.StreamWriter + _closed: bool = field(init=False, default=False) + + async def send(self, item: bytes) -> None: + await AsyncIOBackend.checkpoint_if_cancelled() + stream_paused = self._stream._protocol._paused # type: ignore[attr-defined] + try: + self._stream.write(item) + await self._stream.drain() + except (ConnectionResetError, BrokenPipeError, RuntimeError) as exc: + # If closed by us and/or the peer: + # * on stdlib, drain() raises ConnectionResetError or BrokenPipeError + # * on uvloop and Winloop, write() eventually starts raising RuntimeError + if self._closed: + raise ClosedResourceError from exc + elif self._stream.is_closing(): + raise BrokenResourceError from exc + + raise + + if not stream_paused: + await AsyncIOBackend.cancel_shielded_checkpoint() + + async def aclose(self) -> None: + self._closed = True + self._stream.close() + await AsyncIOBackend.checkpoint() + + +@dataclass(eq=False) +class Process(abc.Process): + _process: asyncio.subprocess.Process + _stdin: StreamWriterWrapper | None + _stdout: StreamReaderWrapper | None + _stderr: StreamReaderWrapper | None + + async def aclose(self) -> None: + with CancelScope(shield=True) as scope: + if self._stdin: + await self._stdin.aclose() + if self._stdout: + await self._stdout.aclose() + if self._stderr: + await self._stderr.aclose() + + scope.shield = False + try: + await self.wait() + except BaseException: + scope.shield = True + self.kill() + await self.wait() + raise + + async def wait(self) -> int: + return await self._process.wait() + + def terminate(self) -> None: + self._process.terminate() + + def kill(self) -> None: + self._process.kill() + + def send_signal(self, signal: int) -> None: + self._process.send_signal(signal) + + @property + def pid(self) -> int: + return self._process.pid + + @property + def returncode(self) -> int | None: + return self._process.returncode + + @property + def stdin(self) -> abc.ByteSendStream | None: + return self._stdin + + @property + def stdout(self) -> abc.ByteReceiveStream | None: + return self._stdout + + @property + def stderr(self) -> abc.ByteReceiveStream | None: + return self._stderr + + +def _forcibly_shutdown_process_pool_on_exit( + workers: set[Process], _task: object +) -> None: + """ + Forcibly shuts down worker processes belonging to this event loop.""" + child_watcher: asyncio.AbstractChildWatcher | None = None # type: ignore[name-defined] + if sys.version_info < (3, 12): + try: + child_watcher = asyncio.get_event_loop_policy().get_child_watcher() + except NotImplementedError: + pass + + # Close as much as possible (w/o async/await) to avoid warnings + for process in workers.copy(): + if process.returncode is None: + continue + + process._stdin._stream._transport.close() # type: ignore[union-attr] + process._stdout._stream._transport.close() # type: ignore[union-attr] + process._stderr._stream._transport.close() # type: ignore[union-attr] + process.kill() + if child_watcher: + child_watcher.remove_child_handler(process.pid) + + +async def _shutdown_process_pool_on_exit(workers: set[abc.Process]) -> None: + """ + Shuts down worker processes belonging to this event loop. + + NOTE: this only works when the event loop was started using asyncio.run() or + anyio.run(). + + """ + process: abc.Process + try: + await sleep(math.inf) + except asyncio.CancelledError: + workers = workers.copy() + for process in workers: + if process.returncode is None: + process.kill() + + for process in workers: + await process.aclose() + + +# +# Sockets and networking +# + + +class StreamProtocol(asyncio.Protocol): + read_queue: deque[bytes] + read_event: asyncio.Event + write_event: asyncio.Event + exception: Exception | None = None + is_at_eof: bool = False + + def connection_made(self, transport: asyncio.BaseTransport) -> None: + self.read_queue = deque() + self.read_event = asyncio.Event() + self.write_event = asyncio.Event() + self.write_event.set() + cast(asyncio.Transport, transport).set_write_buffer_limits(0) + + def connection_lost(self, exc: Exception | None) -> None: + if exc: + self.exception = BrokenResourceError() + self.exception.__cause__ = exc + + self.read_event.set() + self.write_event.set() + + def data_received(self, data: bytes) -> None: + # ProactorEventloop sometimes sends bytearray instead of bytes + self.read_queue.append(bytes(data)) + self.read_event.set() + + def eof_received(self) -> bool | None: + self.is_at_eof = True + self.read_event.set() + return True + + def pause_writing(self) -> None: + self.write_event = asyncio.Event() + + def resume_writing(self) -> None: + self.write_event.set() + + +class DatagramProtocol(asyncio.DatagramProtocol): + read_queue: deque[tuple[bytes, IPSockAddrType]] + read_event: asyncio.Event + write_event: asyncio.Event + exception: Exception | None = None + + def connection_made(self, transport: asyncio.BaseTransport) -> None: + self.read_queue = deque(maxlen=100) # arbitrary value + self.read_event = asyncio.Event() + self.write_event = asyncio.Event() + self.write_event.set() + + def connection_lost(self, exc: Exception | None) -> None: + self.read_event.set() + self.write_event.set() + + def datagram_received(self, data: bytes, addr: IPSockAddrType) -> None: + addr = convert_ipv6_sockaddr(addr) + self.read_queue.append((data, addr)) + self.read_event.set() + + def error_received(self, exc: Exception) -> None: + self.exception = exc + + def pause_writing(self) -> None: + self.write_event.clear() + + def resume_writing(self) -> None: + self.write_event.set() + + +class SocketStream(abc.SocketStream): + def __init__(self, transport: asyncio.Transport, protocol: StreamProtocol): + self._transport = transport + self._protocol = protocol + self._receive_guard = ResourceGuard("reading from") + self._send_guard = ResourceGuard("writing to") + self._closed = False + + @property + def _raw_socket(self) -> socket.socket: + return self._transport.get_extra_info("socket") + + async def receive(self, max_bytes: int = 65536) -> bytes: + with self._receive_guard: + if ( + not self._protocol.read_event.is_set() + and not self._transport.is_closing() + and not self._protocol.is_at_eof + ): + self._transport.resume_reading() + await self._protocol.read_event.wait() + self._transport.pause_reading() + else: + await AsyncIOBackend.checkpoint() + + try: + chunk = self._protocol.read_queue.popleft() + except IndexError: + if self._closed: + raise ClosedResourceError from None + elif self._protocol.exception: + raise self._protocol.exception from None + else: + raise EndOfStream from None + + if len(chunk) > max_bytes: + # Split the oversized chunk + chunk, leftover = chunk[:max_bytes], chunk[max_bytes:] + self._protocol.read_queue.appendleft(leftover) + + # If the read queue is empty, clear the flag so that the next call will + # block until data is available + if not self._protocol.read_queue: + self._protocol.read_event.clear() + + return chunk + + async def send(self, item: bytes) -> None: + with self._send_guard: + await AsyncIOBackend.checkpoint() + + if self._closed: + raise ClosedResourceError + elif self._protocol.exception is not None: + raise self._protocol.exception + + try: + self._transport.write(item) + except RuntimeError as exc: + if self._transport.is_closing(): + raise BrokenResourceError from exc + else: + raise + + await self._protocol.write_event.wait() + + async def send_eof(self) -> None: + try: + self._transport.write_eof() + except OSError: + pass + + async def aclose(self) -> None: + self._closed = True + if not self._transport.is_closing(): + try: + self._transport.write_eof() + except OSError: + pass + + self._transport.close() + await sleep(0) + self._transport.abort() + + +class _RawSocketMixin: + _receive_future: asyncio.Future | None = None + _send_future: asyncio.Future | None = None + _closing = False + + def __init__(self, raw_socket: socket.socket): + self.__raw_socket = raw_socket + self._receive_guard = ResourceGuard("reading from") + self._send_guard = ResourceGuard("writing to") + + @property + def _raw_socket(self) -> socket.socket: + return self.__raw_socket + + def _wait_until_readable(self, loop: asyncio.AbstractEventLoop) -> asyncio.Future: + def callback(f: object) -> None: + del self._receive_future + loop.remove_reader(self.__raw_socket) + + f = self._receive_future = asyncio.Future() + loop.add_reader(self.__raw_socket, f.set_result, None) + f.add_done_callback(callback) + return f + + def _wait_until_writable(self, loop: asyncio.AbstractEventLoop) -> asyncio.Future: + def callback(f: object) -> None: + del self._send_future + loop.remove_writer(self.__raw_socket) + + f = self._send_future = asyncio.Future() + loop.add_writer(self.__raw_socket, f.set_result, None) + f.add_done_callback(callback) + return f + + async def aclose(self) -> None: + if not self._closing: + self._closing = True + if self.__raw_socket.fileno() != -1: + self.__raw_socket.close() + + if self._receive_future: + self._receive_future.set_result(None) + if self._send_future: + self._send_future.set_result(None) + + +class UNIXSocketStream(_RawSocketMixin, abc.UNIXSocketStream): + async def send_eof(self) -> None: + with self._send_guard: + self._raw_socket.shutdown(socket.SHUT_WR) + + async def receive(self, max_bytes: int = 65536) -> bytes: + loop = get_running_loop() + await AsyncIOBackend.checkpoint() + with self._receive_guard: + while True: + try: + data = self._raw_socket.recv(max_bytes) + except BlockingIOError: + await self._wait_until_readable(loop) + except OSError as exc: + if self._closing: + raise ClosedResourceError from None + else: + raise BrokenResourceError from exc + else: + if not data: + raise EndOfStream + + return data + + async def send(self, item: bytes) -> None: + loop = get_running_loop() + await AsyncIOBackend.checkpoint() + with self._send_guard: + view = memoryview(item) + while view: + try: + bytes_sent = self._raw_socket.send(view) + except BlockingIOError: + await self._wait_until_writable(loop) + except OSError as exc: + if self._closing: + raise ClosedResourceError from None + else: + raise BrokenResourceError from exc + else: + view = view[bytes_sent:] + + async def receive_fds(self, msglen: int, maxfds: int) -> tuple[bytes, list[int]]: + if not isinstance(msglen, int) or msglen < 0: + raise ValueError("msglen must be a non-negative integer") + if not isinstance(maxfds, int) or maxfds < 1: + raise ValueError("maxfds must be a positive integer") + + loop = get_running_loop() + fds = array.array("i") + await AsyncIOBackend.checkpoint() + with self._receive_guard: + while True: + try: + message, ancdata, flags, addr = self._raw_socket.recvmsg( + msglen, socket.CMSG_LEN(maxfds * fds.itemsize) + ) + except BlockingIOError: + await self._wait_until_readable(loop) + except OSError as exc: + if self._closing: + raise ClosedResourceError from None + else: + raise BrokenResourceError from exc + else: + if not message and not ancdata: + raise EndOfStream + + break + + for cmsg_level, cmsg_type, cmsg_data in ancdata: + if cmsg_level != socket.SOL_SOCKET or cmsg_type != socket.SCM_RIGHTS: + raise RuntimeError( + f"Received unexpected ancillary data; message = {message!r}, " + f"cmsg_level = {cmsg_level}, cmsg_type = {cmsg_type}" + ) + + fds.frombytes(cmsg_data[: len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) + + return message, list(fds) + + async def send_fds(self, message: bytes, fds: Collection[int | IOBase]) -> None: + if not message: + raise ValueError("message must not be empty") + if not fds: + raise ValueError("fds must not be empty") + + loop = get_running_loop() + filenos: list[int] = [] + for fd in fds: + if isinstance(fd, int): + filenos.append(fd) + elif isinstance(fd, IOBase): + filenos.append(fd.fileno()) + + fdarray = array.array("i", filenos) + await AsyncIOBackend.checkpoint() + with self._send_guard: + while True: + try: + # The ignore can be removed after mypy picks up + # https://github.com/python/typeshed/pull/5545 + self._raw_socket.sendmsg( + [message], [(socket.SOL_SOCKET, socket.SCM_RIGHTS, fdarray)] + ) + break + except BlockingIOError: + await self._wait_until_writable(loop) + except OSError as exc: + if self._closing: + raise ClosedResourceError from None + else: + raise BrokenResourceError from exc + + +class TCPSocketListener(abc.SocketListener): + _accept_scope: CancelScope | None = None + _closed = False + + def __init__(self, raw_socket: socket.socket): + self.__raw_socket = raw_socket + self._loop = cast(asyncio.BaseEventLoop, get_running_loop()) + self._accept_guard = ResourceGuard("accepting connections from") + + @property + def _raw_socket(self) -> socket.socket: + return self.__raw_socket + + async def accept(self) -> abc.SocketStream: + if self._closed: + raise ClosedResourceError + + with self._accept_guard: + await AsyncIOBackend.checkpoint() + with CancelScope() as self._accept_scope: + try: + client_sock, _addr = await self._loop.sock_accept(self._raw_socket) + except asyncio.CancelledError: + # Workaround for https://bugs.python.org/issue41317 + try: + self._loop.remove_reader(self._raw_socket) + except (ValueError, NotImplementedError): + pass + + if self._closed: + raise ClosedResourceError from None + + raise + finally: + self._accept_scope = None + + client_sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + transport, protocol = await self._loop.connect_accepted_socket( + StreamProtocol, client_sock + ) + return SocketStream(transport, protocol) + + async def aclose(self) -> None: + if self._closed: + return + + self._closed = True + if self._accept_scope: + # Workaround for https://bugs.python.org/issue41317 + try: + self._loop.remove_reader(self._raw_socket) + except (ValueError, NotImplementedError): + pass + + self._accept_scope.cancel() + await sleep(0) + + self._raw_socket.close() + + +class UNIXSocketListener(abc.SocketListener): + def __init__(self, raw_socket: socket.socket): + self.__raw_socket = raw_socket + self._loop = get_running_loop() + self._accept_guard = ResourceGuard("accepting connections from") + self._closed = False + + async def accept(self) -> abc.SocketStream: + await AsyncIOBackend.checkpoint() + with self._accept_guard: + while True: + try: + client_sock, _ = self.__raw_socket.accept() + client_sock.setblocking(False) + return UNIXSocketStream(client_sock) + except BlockingIOError: + f: asyncio.Future = asyncio.Future() + self._loop.add_reader(self.__raw_socket, f.set_result, None) + f.add_done_callback( + lambda _: self._loop.remove_reader(self.__raw_socket) + ) + await f + except OSError as exc: + if self._closed: + raise ClosedResourceError from None + else: + raise BrokenResourceError from exc + + async def aclose(self) -> None: + self._closed = True + self.__raw_socket.close() + + @property + def _raw_socket(self) -> socket.socket: + return self.__raw_socket + + +class UDPSocket(abc.UDPSocket): + def __init__( + self, transport: asyncio.DatagramTransport, protocol: DatagramProtocol + ): + self._transport = transport + self._protocol = protocol + self._receive_guard = ResourceGuard("reading from") + self._send_guard = ResourceGuard("writing to") + self._closed = False + + @property + def _raw_socket(self) -> socket.socket: + return self._transport.get_extra_info("socket") + + async def aclose(self) -> None: + self._closed = True + if not self._transport.is_closing(): + self._transport.close() + + async def receive(self) -> tuple[bytes, IPSockAddrType]: + with self._receive_guard: + await AsyncIOBackend.checkpoint() + + # If the buffer is empty, ask for more data + if not self._protocol.read_queue and not self._transport.is_closing(): + self._protocol.read_event.clear() + await self._protocol.read_event.wait() + + try: + return self._protocol.read_queue.popleft() + except IndexError: + if self._closed: + raise ClosedResourceError from None + else: + raise BrokenResourceError from None + + async def send(self, item: UDPPacketType) -> None: + with self._send_guard: + await AsyncIOBackend.checkpoint() + await self._protocol.write_event.wait() + if self._closed: + raise ClosedResourceError + elif self._transport.is_closing(): + raise BrokenResourceError + else: + self._transport.sendto(*item) + + +class ConnectedUDPSocket(abc.ConnectedUDPSocket): + def __init__( + self, transport: asyncio.DatagramTransport, protocol: DatagramProtocol + ): + self._transport = transport + self._protocol = protocol + self._receive_guard = ResourceGuard("reading from") + self._send_guard = ResourceGuard("writing to") + self._closed = False + + @property + def _raw_socket(self) -> socket.socket: + return self._transport.get_extra_info("socket") + + async def aclose(self) -> None: + self._closed = True + if not self._transport.is_closing(): + self._transport.close() + + async def receive(self) -> bytes: + with self._receive_guard: + await AsyncIOBackend.checkpoint() + + # If the buffer is empty, ask for more data + if not self._protocol.read_queue and not self._transport.is_closing(): + self._protocol.read_event.clear() + await self._protocol.read_event.wait() + + try: + packet = self._protocol.read_queue.popleft() + except IndexError: + if self._closed: + raise ClosedResourceError from None + else: + raise BrokenResourceError from None + + return packet[0] + + async def send(self, item: bytes) -> None: + with self._send_guard: + await AsyncIOBackend.checkpoint() + await self._protocol.write_event.wait() + if self._closed: + raise ClosedResourceError + elif self._transport.is_closing(): + raise BrokenResourceError + else: + self._transport.sendto(item) + + +class UNIXDatagramSocket(_RawSocketMixin, abc.UNIXDatagramSocket): + async def receive(self) -> UNIXDatagramPacketType: + loop = get_running_loop() + await AsyncIOBackend.checkpoint() + with self._receive_guard: + while True: + try: + data = self._raw_socket.recvfrom(65536) + except BlockingIOError: + await self._wait_until_readable(loop) + except OSError as exc: + if self._closing: + raise ClosedResourceError from None + else: + raise BrokenResourceError from exc + else: + return data + + async def send(self, item: UNIXDatagramPacketType) -> None: + loop = get_running_loop() + await AsyncIOBackend.checkpoint() + with self._send_guard: + while True: + try: + self._raw_socket.sendto(*item) + except BlockingIOError: + await self._wait_until_writable(loop) + except OSError as exc: + if self._closing: + raise ClosedResourceError from None + else: + raise BrokenResourceError from exc + else: + return + + +class ConnectedUNIXDatagramSocket(_RawSocketMixin, abc.ConnectedUNIXDatagramSocket): + async def receive(self) -> bytes: + loop = get_running_loop() + await AsyncIOBackend.checkpoint() + with self._receive_guard: + while True: + try: + data = self._raw_socket.recv(65536) + except BlockingIOError: + await self._wait_until_readable(loop) + except OSError as exc: + if self._closing: + raise ClosedResourceError from None + else: + raise BrokenResourceError from exc + else: + return data + + async def send(self, item: bytes) -> None: + loop = get_running_loop() + await AsyncIOBackend.checkpoint() + with self._send_guard: + while True: + try: + self._raw_socket.send(item) + except BlockingIOError: + await self._wait_until_writable(loop) + except OSError as exc: + if self._closing: + raise ClosedResourceError from None + else: + raise BrokenResourceError from exc + else: + return + + +_read_events: RunVar[dict[int, asyncio.Future[bool]]] = RunVar("read_events") +_write_events: RunVar[dict[int, asyncio.Future[bool]]] = RunVar("write_events") + + +# +# Synchronization +# + + +class Event(BaseEvent): + def __new__(cls) -> Event: + return object.__new__(cls) + + def __init__(self) -> None: + self._event = asyncio.Event() + + def set(self) -> None: + self._event.set() + + def is_set(self) -> bool: + return self._event.is_set() + + async def wait(self) -> None: + if self.is_set(): + await AsyncIOBackend.checkpoint() + else: + await self._event.wait() + + def statistics(self) -> EventStatistics: + return EventStatistics(len(self._event._waiters)) + + +class Lock(BaseLock): + def __new__(cls, *, fast_acquire: bool = False) -> Lock: + return object.__new__(cls) + + def __init__(self, *, fast_acquire: bool = False) -> None: + self._fast_acquire = fast_acquire + self._owner_task: asyncio.Task | None = None + self._waiters: deque[tuple[asyncio.Task, asyncio.Future]] = deque() + + async def acquire(self) -> None: + task = cast(asyncio.Task, current_task()) + if self._owner_task is None and not self._waiters: + await AsyncIOBackend.checkpoint_if_cancelled() + self._owner_task = task + + # Unless on the "fast path", yield control of the event loop so that other + # tasks can run too + if not self._fast_acquire: + try: + await AsyncIOBackend.cancel_shielded_checkpoint() + except CancelledError: + self.release() + raise + + return + + if self._owner_task == task: + raise RuntimeError("Attempted to acquire an already held Lock") + + fut: asyncio.Future[None] = asyncio.Future() + item = task, fut + self._waiters.append(item) + try: + await fut + except CancelledError: + self._waiters.remove(item) + if self._owner_task is task: + self.release() + + raise + + self._waiters.remove(item) + + def acquire_nowait(self) -> None: + task = cast(asyncio.Task, current_task()) + if self._owner_task is None and not self._waiters: + self._owner_task = task + return + + if self._owner_task is task: + raise RuntimeError("Attempted to acquire an already held Lock") + + raise WouldBlock + + def locked(self) -> bool: + return self._owner_task is not None + + def release(self) -> None: + if self._owner_task != current_task(): + raise RuntimeError("The current task is not holding this lock") + + for task, fut in self._waiters: + if not fut.cancelled(): + self._owner_task = task + fut.set_result(None) + return + + self._owner_task = None + + def statistics(self) -> LockStatistics: + task_info = AsyncIOTaskInfo(self._owner_task) if self._owner_task else None + return LockStatistics(self.locked(), task_info, len(self._waiters)) + + +class Semaphore(BaseSemaphore): + def __new__( + cls, + initial_value: int, + *, + max_value: int | None = None, + fast_acquire: bool = False, + ) -> Semaphore: + return object.__new__(cls) + + def __init__( + self, + initial_value: int, + *, + max_value: int | None = None, + fast_acquire: bool = False, + ): + super().__init__(initial_value, max_value=max_value) + self._value = initial_value + self._max_value = max_value + self._fast_acquire = fast_acquire + self._waiters: deque[asyncio.Future[None]] = deque() + + async def acquire(self) -> None: + if self._value > 0 and not self._waiters: + await AsyncIOBackend.checkpoint_if_cancelled() + self._value -= 1 + + # Unless on the "fast path", yield control of the event loop so that other + # tasks can run too + if not self._fast_acquire: + try: + await AsyncIOBackend.cancel_shielded_checkpoint() + except CancelledError: + self.release() + raise + + return + + fut: asyncio.Future[None] = asyncio.Future() + self._waiters.append(fut) + try: + await fut + except CancelledError: + try: + self._waiters.remove(fut) + except ValueError: + self.release() + + raise + + def acquire_nowait(self) -> None: + if self._value == 0: + raise WouldBlock + + self._value -= 1 + + def release(self) -> None: + if self._max_value is not None and self._value == self._max_value: + raise ValueError("semaphore released too many times") + + for fut in self._waiters: + if not fut.cancelled(): + fut.set_result(None) + self._waiters.remove(fut) + return + + self._value += 1 + + @property + def value(self) -> int: + return self._value + + @property + def max_value(self) -> int | None: + return self._max_value + + def statistics(self) -> SemaphoreStatistics: + return SemaphoreStatistics(len(self._waiters)) + + +class CapacityLimiter(BaseCapacityLimiter): + _total_tokens: float = 0 + + def __new__(cls, total_tokens: float) -> CapacityLimiter: + return object.__new__(cls) + + def __init__(self, total_tokens: float): + self._borrowers: set[Any] = set() + self._wait_queue: OrderedDict[Any, asyncio.Event] = OrderedDict() + self.total_tokens = total_tokens + + async def __aenter__(self) -> None: + await self.acquire() + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + self.release() + + @property + def total_tokens(self) -> float: + return self._total_tokens + + @total_tokens.setter + def total_tokens(self, value: float) -> None: + if not isinstance(value, int) and not math.isinf(value): + raise TypeError("total_tokens must be an int or math.inf") + + if value < 0: + raise ValueError("total_tokens must be >= 0") + + waiters_to_notify = max(value - self._total_tokens, 0) + self._total_tokens = value + + # Notify waiting tasks that they have acquired the limiter + while self._wait_queue and waiters_to_notify: + event = self._wait_queue.popitem(last=False)[1] + event.set() + waiters_to_notify -= 1 + + @property + def borrowed_tokens(self) -> int: + return len(self._borrowers) + + @property + def available_tokens(self) -> float: + return self._total_tokens - len(self._borrowers) + + def _notify_next_waiter(self) -> None: + """Notify the next task in line if this limiter has free capacity now.""" + if self._wait_queue and len(self._borrowers) < self._total_tokens: + event = self._wait_queue.popitem(last=False)[1] + event.set() + + def acquire_nowait(self) -> None: + self.acquire_on_behalf_of_nowait(current_task()) + + def acquire_on_behalf_of_nowait(self, borrower: object) -> None: + if borrower in self._borrowers: + raise RuntimeError( + "this borrower is already holding one of this CapacityLimiter's tokens" + ) + + if self._wait_queue or len(self._borrowers) >= self._total_tokens: + raise WouldBlock + + self._borrowers.add(borrower) + + async def acquire(self) -> None: + return await self.acquire_on_behalf_of(current_task()) + + async def acquire_on_behalf_of(self, borrower: object) -> None: + await AsyncIOBackend.checkpoint_if_cancelled() + try: + self.acquire_on_behalf_of_nowait(borrower) + except WouldBlock: + event = asyncio.Event() + self._wait_queue[borrower] = event + try: + await event.wait() + except BaseException: + self._wait_queue.pop(borrower, None) + if event.is_set(): + self._notify_next_waiter() + + raise + + self._borrowers.add(borrower) + else: + try: + await AsyncIOBackend.cancel_shielded_checkpoint() + except BaseException: + self.release() + raise + + def release(self) -> None: + self.release_on_behalf_of(current_task()) + + def release_on_behalf_of(self, borrower: object) -> None: + try: + self._borrowers.remove(borrower) + except KeyError: + raise RuntimeError( + "this borrower isn't holding any of this CapacityLimiter's tokens" + ) from None + + self._notify_next_waiter() + + def statistics(self) -> CapacityLimiterStatistics: + return CapacityLimiterStatistics( + self.borrowed_tokens, + self.total_tokens, + tuple(self._borrowers), + len(self._wait_queue), + ) + + +_default_thread_limiter: RunVar[CapacityLimiter] = RunVar("_default_thread_limiter") + + +# +# Operating system signals +# + + +class _SignalReceiver: + def __init__(self, signals: tuple[Signals, ...]): + self._signals = signals + self._loop = get_running_loop() + self._signal_queue: deque[Signals] = deque() + self._future: asyncio.Future = asyncio.Future() + self._handled_signals: set[Signals] = set() + + def _deliver(self, signum: Signals) -> None: + self._signal_queue.append(signum) + if not self._future.done(): + self._future.set_result(None) + + def __enter__(self) -> _SignalReceiver: + for sig in set(self._signals): + self._loop.add_signal_handler(sig, self._deliver, sig) + self._handled_signals.add(sig) + + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + for sig in self._handled_signals: + self._loop.remove_signal_handler(sig) + + def __aiter__(self) -> _SignalReceiver: + return self + + async def __anext__(self) -> Signals: + await AsyncIOBackend.checkpoint() + if not self._signal_queue: + self._future = asyncio.Future() + await self._future + + return self._signal_queue.popleft() + + +# +# Testing and debugging +# + + +class AsyncIOTaskInfo(TaskInfo): + def __init__(self, task: asyncio.Task): + task_state = _task_states.get(task) + if task_state is None: + parent_id = None + else: + parent_id = task_state.parent_id + + coro = task.get_coro() + assert coro is not None, "created TaskInfo from a completed Task" + super().__init__(id(task), parent_id, task.get_name(), coro) + self._task = weakref.ref(task) + + def has_pending_cancellation(self) -> bool: + if not (task := self._task()): + # If the task isn't around anymore, it won't have a pending cancellation + return False + + if task._must_cancel: # type: ignore[attr-defined] + return True + elif ( + isinstance(task._fut_waiter, asyncio.Future) # type: ignore[attr-defined] + and task._fut_waiter.cancelled() # type: ignore[attr-defined] + ): + return True + + if task_state := _task_states.get(task): + if cancel_scope := task_state.cancel_scope: + return cancel_scope._effectively_cancelled + + return False + + +class TestRunner(abc.TestRunner): + _send_stream: MemoryObjectSendStream[tuple[Awaitable[Any], asyncio.Future[Any]]] + + def __init__( + self, + *, + debug: bool | None = None, + use_uvloop: bool = False, + loop_factory: Callable[[], AbstractEventLoop] | None = None, + ) -> None: + if use_uvloop and loop_factory is None: + if sys.platform != "win32": + import uvloop + + loop_factory = uvloop.new_event_loop + else: + import winloop + + loop_factory = winloop.new_event_loop + + self._runner = Runner(debug=debug, loop_factory=loop_factory) + self._exceptions: list[BaseException] = [] + self._runner_task: asyncio.Task | None = None + + def __enter__(self) -> TestRunner: + self._runner.__enter__() + self.get_loop().set_exception_handler(self._exception_handler) + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + self._runner.__exit__(exc_type, exc_val, exc_tb) + + def get_loop(self) -> AbstractEventLoop: + return self._runner.get_loop() + + def _exception_handler( + self, loop: asyncio.AbstractEventLoop, context: dict[str, Any] + ) -> None: + if isinstance(context.get("exception"), Exception): + self._exceptions.append(context["exception"]) + else: + loop.default_exception_handler(context) + + def _raise_async_exceptions(self) -> None: + # Re-raise any exceptions raised in asynchronous callbacks + if self._exceptions: + exceptions, self._exceptions = self._exceptions, [] + if len(exceptions) == 1: + raise exceptions[0] + elif exceptions: + raise BaseExceptionGroup( + "Multiple exceptions occurred in asynchronous callbacks", exceptions + ) + + async def _run_tests_and_fixtures( + self, + receive_stream: MemoryObjectReceiveStream[ + tuple[Awaitable[T_Retval], asyncio.Future[T_Retval]] + ], + ) -> None: + from _pytest.outcomes import OutcomeException + + with receive_stream, self._send_stream: + async for coro, future in receive_stream: + try: + retval = await coro + except CancelledError as exc: + if not future.cancelled(): + future.cancel(*exc.args) + + raise + except BaseException as exc: + if not future.cancelled(): + future.set_exception(exc) + + if not isinstance(exc, (Exception, OutcomeException)): + raise + else: + if not future.cancelled(): + future.set_result(retval) + + async def _call_in_runner_task( + self, + func: Callable[P, Awaitable[T_Retval]], + *args: P.args, + **kwargs: P.kwargs, + ) -> T_Retval: + if not self._runner_task: + self._send_stream, receive_stream = create_memory_object_stream[ + tuple[Awaitable[Any], asyncio.Future] + ](1) + self._runner_task = self.get_loop().create_task( + self._run_tests_and_fixtures(receive_stream) + ) + + coro = func(*args, **kwargs) + future: asyncio.Future[T_Retval] = self.get_loop().create_future() + self._send_stream.send_nowait((coro, future)) + return await future + + def run_asyncgen_fixture( + self, + fixture_func: Callable[..., AsyncGenerator[T_Retval, Any]], + kwargs: dict[str, Any], + ) -> Iterable[T_Retval]: + asyncgen = fixture_func(**kwargs) + fixturevalue: T_Retval = self.get_loop().run_until_complete( + self._call_in_runner_task(asyncgen.asend, None) + ) + self._raise_async_exceptions() + + yield fixturevalue + + try: + self.get_loop().run_until_complete( + self._call_in_runner_task(asyncgen.asend, None) + ) + except StopAsyncIteration: + self._raise_async_exceptions() + else: + self.get_loop().run_until_complete(asyncgen.aclose()) + raise RuntimeError("Async generator fixture did not stop") + + def run_fixture( + self, + fixture_func: Callable[..., Coroutine[Any, Any, T_Retval]], + kwargs: dict[str, Any], + ) -> T_Retval: + retval = self.get_loop().run_until_complete( + self._call_in_runner_task(fixture_func, **kwargs) + ) + self._raise_async_exceptions() + return retval + + def run_test( + self, test_func: Callable[..., Coroutine[Any, Any, Any]], kwargs: dict[str, Any] + ) -> None: + try: + self.get_loop().run_until_complete( + self._call_in_runner_task(test_func, **kwargs) + ) + except Exception as exc: + self._exceptions.append(exc) + + self._raise_async_exceptions() + + +class AsyncIOBackend(AsyncBackend): + @classmethod + def run( + cls, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], + args: tuple[Unpack[PosArgsT]], + kwargs: dict[str, Any], + options: dict[str, Any], + ) -> T_Retval: + @wraps(func) + async def wrapper() -> T_Retval: + task = cast(asyncio.Task, current_task()) + task.set_name(get_callable_name(func)) + _task_states[task] = TaskState(None, None) + + try: + return await func(*args) + finally: + del _task_states[task] + + debug = options.get("debug", None) + loop_factory = options.get("loop_factory", None) + if loop_factory is None and options.get("use_uvloop", False): + if sys.platform != "win32": + import uvloop + + loop_factory = uvloop.new_event_loop + else: + import winloop + + loop_factory = winloop.new_event_loop + + with Runner(debug=debug, loop_factory=loop_factory) as runner: + return runner.run(wrapper()) + + @classmethod + def current_token(cls) -> object: + return get_running_loop() + + @classmethod + def current_time(cls) -> float: + return get_running_loop().time() + + @classmethod + def cancelled_exception_class(cls) -> type[BaseException]: + return CancelledError + + @classmethod + async def checkpoint(cls) -> None: + await sleep(0) + + @classmethod + async def checkpoint_if_cancelled(cls) -> None: + task = current_task() + if task is None: + return + + try: + cancel_scope = _task_states[task].cancel_scope + except KeyError: + return + + while cancel_scope: + if cancel_scope.cancel_called: + await sleep(0) + elif cancel_scope.shield: + break + else: + cancel_scope = cancel_scope._parent_scope + + @classmethod + async def cancel_shielded_checkpoint(cls) -> None: + with CancelScope(shield=True): + await sleep(0) + + @classmethod + async def sleep(cls, delay: float) -> None: + await sleep(delay) + + @classmethod + def create_cancel_scope( + cls, *, deadline: float = math.inf, shield: bool = False + ) -> CancelScope: + return CancelScope(deadline=deadline, shield=shield) + + @classmethod + def current_effective_deadline(cls) -> float: + if (task := current_task()) is None: + return math.inf + + try: + cancel_scope = _task_states[task].cancel_scope + except KeyError: + return math.inf + + deadline = math.inf + while cancel_scope: + deadline = min(deadline, cancel_scope.deadline) + if cancel_scope._cancel_called: + deadline = -math.inf + break + elif cancel_scope.shield: + break + else: + cancel_scope = cancel_scope._parent_scope + + return deadline + + @classmethod + def create_task_group(cls) -> abc.TaskGroup: + return TaskGroup() + + @classmethod + def create_event(cls) -> abc.Event: + return Event() + + @classmethod + def create_lock(cls, *, fast_acquire: bool) -> abc.Lock: + return Lock(fast_acquire=fast_acquire) + + @classmethod + def create_semaphore( + cls, + initial_value: int, + *, + max_value: int | None = None, + fast_acquire: bool = False, + ) -> abc.Semaphore: + return Semaphore(initial_value, max_value=max_value, fast_acquire=fast_acquire) + + @classmethod + def create_capacity_limiter(cls, total_tokens: float) -> abc.CapacityLimiter: + return CapacityLimiter(total_tokens) + + @classmethod + async def run_sync_in_worker_thread( # type: ignore[return] + cls, + func: Callable[[Unpack[PosArgsT]], T_Retval], + args: tuple[Unpack[PosArgsT]], + abandon_on_cancel: bool = False, + limiter: abc.CapacityLimiter | None = None, + ) -> T_Retval: + await cls.checkpoint() + + # If this is the first run in this event loop thread, set up the necessary + # variables + try: + idle_workers = _threadpool_idle_workers.get() + workers = _threadpool_workers.get() + except LookupError: + idle_workers = deque() + workers = set() + _threadpool_idle_workers.set(idle_workers) + _threadpool_workers.set(workers) + + async with limiter or cls.current_default_thread_limiter(): + with CancelScope(shield=not abandon_on_cancel) as scope: + future = asyncio.Future[T_Retval]() + root_task = find_root_task() + if not idle_workers: + worker = WorkerThread(root_task, workers, idle_workers) + worker.start() + workers.add(worker) + root_task.add_done_callback( + worker.stop, context=contextvars.Context() + ) + else: + worker = idle_workers.pop() + + # Prune any other workers that have been idle for MAX_IDLE_TIME + # seconds or longer + now = cls.current_time() + while idle_workers: + if ( + now - idle_workers[0].idle_since + < WorkerThread.MAX_IDLE_TIME + ): + break + + expired_worker = idle_workers.popleft() + expired_worker.root_task.remove_done_callback( + expired_worker.stop + ) + expired_worker.stop() + + context = copy_context() + context.run(set_current_async_library, None) + if abandon_on_cancel or scope._parent_scope is None: + worker_scope = scope + else: + worker_scope = scope._parent_scope + + worker.queue.put_nowait((context, func, args, future, worker_scope)) + return await future + + @classmethod + def check_cancelled(cls) -> None: + scope: CancelScope | None = threadlocals.current_cancel_scope + while scope is not None: + if scope.cancel_called: + raise CancelledError(f"Cancelled by cancel scope {id(scope):x}") + + if scope.shield: + return + + scope = scope._parent_scope + + @classmethod + def run_async_from_thread( + cls, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], + args: tuple[Unpack[PosArgsT]], + token: object, + ) -> T_Retval: + async def task_wrapper() -> T_Retval: + __tracebackhide__ = True + if scope is not None: + task = cast(asyncio.Task, current_task()) + _task_states[task] = TaskState(None, scope) + scope._tasks.add(task) + try: + return await func(*args) + except CancelledError as exc: + raise concurrent.futures.CancelledError(str(exc)) from None + finally: + if scope is not None: + scope._tasks.discard(task) + + loop = cast( + "AbstractEventLoop", token or threadlocals.current_token.native_token + ) + if loop.is_closed(): + raise RunFinishedError + + context = copy_context() + context.run(set_current_async_library, "asyncio") + scope = getattr(threadlocals, "current_cancel_scope", None) + f: concurrent.futures.Future[T_Retval] = context.run( + asyncio.run_coroutine_threadsafe, task_wrapper(), loop=loop + ) + return f.result() + + @classmethod + def run_sync_from_thread( + cls, + func: Callable[[Unpack[PosArgsT]], T_Retval], + args: tuple[Unpack[PosArgsT]], + token: object, + ) -> T_Retval: + @wraps(func) + def wrapper() -> None: + try: + set_current_async_library("asyncio") + f.set_result(func(*args)) + except BaseException as exc: + f.set_exception(exc) + if not isinstance(exc, Exception): + raise + + loop = cast( + "AbstractEventLoop", token or threadlocals.current_token.native_token + ) + if loop.is_closed(): + raise RunFinishedError + + f: concurrent.futures.Future[T_Retval] = Future() + loop.call_soon_threadsafe(wrapper) + return f.result() + + @classmethod + async def open_process( + cls, + command: StrOrBytesPath | Sequence[StrOrBytesPath], + *, + stdin: int | IO[Any] | None, + stdout: int | IO[Any] | None, + stderr: int | IO[Any] | None, + **kwargs: Any, + ) -> Process: + await cls.checkpoint() + if isinstance(command, PathLike): + command = os.fspath(command) + + if isinstance(command, (str, bytes)): + process = await asyncio.create_subprocess_shell( + command, + stdin=stdin, + stdout=stdout, + stderr=stderr, + **kwargs, + ) + else: + process = await asyncio.create_subprocess_exec( + *command, + stdin=stdin, + stdout=stdout, + stderr=stderr, + **kwargs, + ) + + stdin_stream = StreamWriterWrapper(process.stdin) if process.stdin else None + stdout_stream = StreamReaderWrapper(process.stdout) if process.stdout else None + stderr_stream = StreamReaderWrapper(process.stderr) if process.stderr else None + return Process(process, stdin_stream, stdout_stream, stderr_stream) + + @classmethod + def setup_process_pool_exit_at_shutdown(cls, workers: set[abc.Process]) -> None: + create_task( + _shutdown_process_pool_on_exit(workers), + name="AnyIO process pool shutdown task", + ) + find_root_task().add_done_callback( + partial(_forcibly_shutdown_process_pool_on_exit, workers) # type:ignore[arg-type] + ) + + @classmethod + async def connect_tcp( + cls, host: str, port: int, local_address: IPSockAddrType | None = None + ) -> abc.SocketStream: + transport, protocol = cast( + tuple[asyncio.Transport, StreamProtocol], + await get_running_loop().create_connection( + StreamProtocol, host, port, local_addr=local_address + ), + ) + transport.pause_reading() + return SocketStream(transport, protocol) + + @classmethod + async def connect_unix(cls, path: str | bytes) -> abc.UNIXSocketStream: + await cls.checkpoint() + loop = get_running_loop() + raw_socket = socket.socket(socket.AF_UNIX) + raw_socket.setblocking(False) + while True: + try: + raw_socket.connect(path) + except BlockingIOError: + f: asyncio.Future = asyncio.Future() + loop.add_writer(raw_socket, f.set_result, None) + f.add_done_callback(lambda _: loop.remove_writer(raw_socket)) + await f + except BaseException: + raw_socket.close() + raise + else: + return UNIXSocketStream(raw_socket) + + @classmethod + def create_tcp_listener(cls, sock: socket.socket) -> SocketListener: + return TCPSocketListener(sock) + + @classmethod + def create_unix_listener(cls, sock: socket.socket) -> SocketListener: + return UNIXSocketListener(sock) + + @classmethod + async def create_udp_socket( + cls, + family: AddressFamily, + local_address: IPSockAddrType | None, + remote_address: IPSockAddrType | None, + reuse_port: bool, + ) -> UDPSocket | ConnectedUDPSocket: + transport, protocol = await get_running_loop().create_datagram_endpoint( + DatagramProtocol, + local_addr=local_address, + remote_addr=remote_address, + family=family, + reuse_port=reuse_port, + ) + if protocol.exception: + transport.close() + raise protocol.exception + + if not remote_address: + return UDPSocket(transport, protocol) + else: + return ConnectedUDPSocket(transport, protocol) + + @classmethod + async def create_unix_datagram_socket( # type: ignore[override] + cls, raw_socket: socket.socket, remote_path: str | bytes | None + ) -> abc.UNIXDatagramSocket | abc.ConnectedUNIXDatagramSocket: + await cls.checkpoint() + loop = get_running_loop() + + if remote_path: + while True: + try: + raw_socket.connect(remote_path) + except BlockingIOError: + f: asyncio.Future = asyncio.Future() + loop.add_writer(raw_socket, f.set_result, None) + f.add_done_callback(lambda _: loop.remove_writer(raw_socket)) + await f + except BaseException: + raw_socket.close() + raise + else: + return ConnectedUNIXDatagramSocket(raw_socket) + else: + return UNIXDatagramSocket(raw_socket) + + @classmethod + async def getaddrinfo( + cls, + host: bytes | str | None, + port: str | int | None, + *, + family: int | AddressFamily = 0, + type: int | SocketKind = 0, + proto: int = 0, + flags: int = 0, + ) -> Sequence[ + tuple[ + AddressFamily, + SocketKind, + int, + str, + tuple[str, int] | tuple[str, int, int, int] | tuple[int, bytes], + ] + ]: + return await get_running_loop().getaddrinfo( + host, port, family=family, type=type, proto=proto, flags=flags + ) + + @classmethod + async def getnameinfo( + cls, sockaddr: IPSockAddrType, flags: int = 0 + ) -> tuple[str, str]: + return await get_running_loop().getnameinfo(sockaddr, flags) + + @classmethod + async def wait_readable(cls, obj: FileDescriptorLike) -> None: + try: + read_events = _read_events.get() + except LookupError: + read_events = {} + _read_events.set(read_events) + + fd = obj if isinstance(obj, int) else obj.fileno() + if read_events.get(fd): + raise BusyResourceError("reading from") + + loop = get_running_loop() + fut: asyncio.Future[bool] = loop.create_future() + + def cb() -> None: + try: + del read_events[fd] + except KeyError: + pass + else: + remove_reader(fd) + + try: + fut.set_result(True) + except asyncio.InvalidStateError: + pass + + try: + loop.add_reader(fd, cb) + except NotImplementedError: + from anyio._core._asyncio_selector_thread import get_selector + + selector = get_selector() + selector.add_reader(fd, cb) + remove_reader = selector.remove_reader + else: + remove_reader = loop.remove_reader + + read_events[fd] = fut + try: + success = await fut + finally: + try: + del read_events[fd] + except KeyError: + pass + else: + remove_reader(fd) + + if not success: + raise ClosedResourceError + + @classmethod + async def wait_writable(cls, obj: FileDescriptorLike) -> None: + try: + write_events = _write_events.get() + except LookupError: + write_events = {} + _write_events.set(write_events) + + fd = obj if isinstance(obj, int) else obj.fileno() + if write_events.get(fd): + raise BusyResourceError("writing to") + + loop = get_running_loop() + fut: asyncio.Future[bool] = loop.create_future() + + def cb() -> None: + try: + del write_events[fd] + except KeyError: + pass + else: + remove_writer(fd) + + try: + fut.set_result(True) + except asyncio.InvalidStateError: + pass + + try: + loop.add_writer(fd, cb) + except NotImplementedError: + from anyio._core._asyncio_selector_thread import get_selector + + selector = get_selector() + selector.add_writer(fd, cb) + remove_writer = selector.remove_writer + else: + remove_writer = loop.remove_writer + + write_events[fd] = fut + try: + success = await fut + finally: + try: + del write_events[fd] + except KeyError: + pass + else: + remove_writer(fd) + + if not success: + raise ClosedResourceError + + @classmethod + def notify_closing(cls, obj: FileDescriptorLike) -> None: + fd = obj if isinstance(obj, int) else obj.fileno() + loop = get_running_loop() + + try: + write_events = _write_events.get() + except LookupError: + pass + else: + try: + fut = write_events.pop(fd) + except KeyError: + pass + else: + try: + fut.set_result(False) + except asyncio.InvalidStateError: + pass + + try: + loop.remove_writer(fd) + except NotImplementedError: + from anyio._core._asyncio_selector_thread import get_selector + + get_selector().remove_writer(fd) + + try: + read_events = _read_events.get() + except LookupError: + pass + else: + try: + fut = read_events.pop(fd) + except KeyError: + pass + else: + try: + fut.set_result(False) + except asyncio.InvalidStateError: + pass + + try: + loop.remove_reader(fd) + except NotImplementedError: + from anyio._core._asyncio_selector_thread import get_selector + + get_selector().remove_reader(fd) + + @classmethod + async def wrap_listener_socket(cls, sock: socket.socket) -> SocketListener: + return TCPSocketListener(sock) + + @classmethod + async def wrap_stream_socket(cls, sock: socket.socket) -> SocketStream: + transport, protocol = await get_running_loop().create_connection( + StreamProtocol, sock=sock + ) + return SocketStream(transport, protocol) + + @classmethod + async def wrap_unix_stream_socket(cls, sock: socket.socket) -> UNIXSocketStream: + return UNIXSocketStream(sock) + + @classmethod + async def wrap_udp_socket(cls, sock: socket.socket) -> UDPSocket: + transport, protocol = await get_running_loop().create_datagram_endpoint( + DatagramProtocol, sock=sock + ) + return UDPSocket(transport, protocol) + + @classmethod + async def wrap_connected_udp_socket(cls, sock: socket.socket) -> ConnectedUDPSocket: + transport, protocol = await get_running_loop().create_datagram_endpoint( + DatagramProtocol, sock=sock + ) + return ConnectedUDPSocket(transport, protocol) + + @classmethod + async def wrap_unix_datagram_socket(cls, sock: socket.socket) -> UNIXDatagramSocket: + return UNIXDatagramSocket(sock) + + @classmethod + async def wrap_connected_unix_datagram_socket( + cls, sock: socket.socket + ) -> ConnectedUNIXDatagramSocket: + return ConnectedUNIXDatagramSocket(sock) + + @classmethod + def current_default_thread_limiter(cls) -> CapacityLimiter: + try: + return _default_thread_limiter.get() + except LookupError: + limiter = CapacityLimiter(40) + _default_thread_limiter.set(limiter) + return limiter + + @classmethod + def open_signal_receiver( + cls, *signals: Signals + ) -> AbstractContextManager[AsyncIterator[Signals]]: + return _SignalReceiver(signals) + + @classmethod + def get_current_task(cls) -> TaskInfo: + return AsyncIOTaskInfo(current_task()) # type: ignore[arg-type] + + @classmethod + def get_running_tasks(cls) -> Sequence[TaskInfo]: + return [AsyncIOTaskInfo(task) for task in all_tasks() if not task.done()] + + @classmethod + async def wait_all_tasks_blocked(cls) -> None: + await cls.checkpoint() + this_task = current_task() + while True: + for task in all_tasks(): + if task is this_task: + continue + + waiter = task._fut_waiter # type: ignore[attr-defined] + if waiter is None or waiter.done(): + await sleep(0.1) + break + else: + return + + @classmethod + def create_test_runner(cls, options: dict[str, Any]) -> TestRunner: + return TestRunner(**options) + + +backend_class = AsyncIOBackend diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_backends/_trio.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_backends/_trio.py new file mode 100644 index 0000000..f460a7f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_backends/_trio.py @@ -0,0 +1,1346 @@ +from __future__ import annotations + +import array +import math +import os +import socket +import sys +import types +import weakref +from collections.abc import ( + AsyncGenerator, + AsyncIterator, + Awaitable, + Callable, + Collection, + Coroutine, + Iterable, + Sequence, +) +from contextlib import AbstractContextManager +from dataclasses import dataclass +from io import IOBase +from os import PathLike +from signal import Signals +from socket import AddressFamily, SocketKind +from types import TracebackType +from typing import ( + IO, + TYPE_CHECKING, + Any, + Generic, + NoReturn, + TypeVar, + cast, + overload, +) + +import trio.from_thread +import trio.lowlevel +from outcome import Error, Outcome, Value +from trio.lowlevel import ( + current_root_task, + current_task, + notify_closing, + wait_readable, + wait_writable, +) +from trio.socket import SocketType as TrioSocketType +from trio.to_thread import run_sync + +from .. import ( + CapacityLimiterStatistics, + EventStatistics, + LockStatistics, + RunFinishedError, + TaskInfo, + WouldBlock, + abc, +) +from .._core._eventloop import claim_worker_thread +from .._core._exceptions import ( + BrokenResourceError, + BusyResourceError, + ClosedResourceError, + EndOfStream, +) +from .._core._sockets import convert_ipv6_sockaddr +from .._core._streams import create_memory_object_stream +from .._core._synchronization import ( + CapacityLimiter as BaseCapacityLimiter, +) +from .._core._synchronization import Event as BaseEvent +from .._core._synchronization import Lock as BaseLock +from .._core._synchronization import ( + ResourceGuard, + SemaphoreStatistics, +) +from .._core._synchronization import Semaphore as BaseSemaphore +from .._core._tasks import CancelScope as BaseCancelScope +from ..abc import IPSockAddrType, UDPPacketType, UNIXDatagramPacketType +from ..abc._eventloop import AsyncBackend, StrOrBytesPath +from ..streams.memory import MemoryObjectSendStream + +if TYPE_CHECKING: + from _typeshed import FileDescriptorLike + +if sys.version_info >= (3, 10): + from typing import ParamSpec +else: + from typing_extensions import ParamSpec + +if sys.version_info >= (3, 11): + from typing import TypeVarTuple, Unpack +else: + from exceptiongroup import BaseExceptionGroup + from typing_extensions import TypeVarTuple, Unpack + +T = TypeVar("T") +T_Retval = TypeVar("T_Retval") +T_SockAddr = TypeVar("T_SockAddr", str, IPSockAddrType) +PosArgsT = TypeVarTuple("PosArgsT") +P = ParamSpec("P") + + +# +# Event loop +# + +RunVar = trio.lowlevel.RunVar + + +# +# Timeouts and cancellation +# + + +class CancelScope(BaseCancelScope): + def __new__( + cls, original: trio.CancelScope | None = None, **kwargs: object + ) -> CancelScope: + return object.__new__(cls) + + def __init__(self, original: trio.CancelScope | None = None, **kwargs: Any) -> None: + self.__original = original or trio.CancelScope(**kwargs) + + def __enter__(self) -> CancelScope: + self.__original.__enter__() + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> bool: + return self.__original.__exit__(exc_type, exc_val, exc_tb) + + def cancel(self, reason: str | None = None) -> None: + self.__original.cancel(reason) + + @property + def deadline(self) -> float: + return self.__original.deadline + + @deadline.setter + def deadline(self, value: float) -> None: + self.__original.deadline = value + + @property + def cancel_called(self) -> bool: + return self.__original.cancel_called + + @property + def cancelled_caught(self) -> bool: + return self.__original.cancelled_caught + + @property + def shield(self) -> bool: + return self.__original.shield + + @shield.setter + def shield(self, value: bool) -> None: + self.__original.shield = value + + +# +# Task groups +# + + +class TaskGroup(abc.TaskGroup): + def __init__(self) -> None: + self._active = False + self._nursery_manager = trio.open_nursery(strict_exception_groups=True) + self.cancel_scope = None # type: ignore[assignment] + + async def __aenter__(self) -> TaskGroup: + self._active = True + self._nursery = await self._nursery_manager.__aenter__() + self.cancel_scope = CancelScope(self._nursery.cancel_scope) + return self + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> bool: + try: + # trio.Nursery.__exit__ returns bool; .open_nursery has wrong type + return await self._nursery_manager.__aexit__(exc_type, exc_val, exc_tb) # type: ignore[return-value] + except BaseExceptionGroup as exc: + if not exc.split(trio.Cancelled)[1]: + raise trio.Cancelled._create() from exc + + raise + finally: + del exc_val, exc_tb + self._active = False + + def start_soon( + self, + func: Callable[[Unpack[PosArgsT]], Awaitable[Any]], + *args: Unpack[PosArgsT], + name: object = None, + ) -> None: + if not self._active: + raise RuntimeError( + "This task group is not active; no new tasks can be started." + ) + + self._nursery.start_soon(func, *args, name=name) + + async def start( + self, func: Callable[..., Awaitable[Any]], *args: object, name: object = None + ) -> Any: + if not self._active: + raise RuntimeError( + "This task group is not active; no new tasks can be started." + ) + + return await self._nursery.start(func, *args, name=name) + + +# +# Subprocesses +# + + +@dataclass(eq=False) +class ReceiveStreamWrapper(abc.ByteReceiveStream): + _stream: trio.abc.ReceiveStream + + async def receive(self, max_bytes: int | None = None) -> bytes: + try: + data = await self._stream.receive_some(max_bytes) + except trio.ClosedResourceError as exc: + raise ClosedResourceError from exc.__cause__ + except trio.BrokenResourceError as exc: + raise BrokenResourceError from exc.__cause__ + + if data: + return bytes(data) + else: + raise EndOfStream + + async def aclose(self) -> None: + await self._stream.aclose() + + +@dataclass(eq=False) +class SendStreamWrapper(abc.ByteSendStream): + _stream: trio.abc.SendStream + + async def send(self, item: bytes) -> None: + try: + await self._stream.send_all(item) + except trio.ClosedResourceError as exc: + raise ClosedResourceError from exc.__cause__ + except trio.BrokenResourceError as exc: + raise BrokenResourceError from exc.__cause__ + + async def aclose(self) -> None: + await self._stream.aclose() + + +@dataclass(eq=False) +class Process(abc.Process): + _process: trio.Process + _stdin: abc.ByteSendStream | None + _stdout: abc.ByteReceiveStream | None + _stderr: abc.ByteReceiveStream | None + + async def aclose(self) -> None: + with CancelScope(shield=True): + if self._stdin: + await self._stdin.aclose() + if self._stdout: + await self._stdout.aclose() + if self._stderr: + await self._stderr.aclose() + + try: + await self.wait() + except BaseException: + self.kill() + with CancelScope(shield=True): + await self.wait() + raise + + async def wait(self) -> int: + return await self._process.wait() + + def terminate(self) -> None: + self._process.terminate() + + def kill(self) -> None: + self._process.kill() + + def send_signal(self, signal: Signals) -> None: + self._process.send_signal(signal) + + @property + def pid(self) -> int: + return self._process.pid + + @property + def returncode(self) -> int | None: + return self._process.returncode + + @property + def stdin(self) -> abc.ByteSendStream | None: + return self._stdin + + @property + def stdout(self) -> abc.ByteReceiveStream | None: + return self._stdout + + @property + def stderr(self) -> abc.ByteReceiveStream | None: + return self._stderr + + +class _ProcessPoolShutdownInstrument(trio.abc.Instrument): + def after_run(self) -> None: + super().after_run() + + +current_default_worker_process_limiter: trio.lowlevel.RunVar = RunVar( + "current_default_worker_process_limiter" +) + + +async def _shutdown_process_pool(workers: set[abc.Process]) -> None: + try: + await trio.sleep(math.inf) + except trio.Cancelled: + for process in workers: + if process.returncode is None: + process.kill() + + with CancelScope(shield=True): + for process in workers: + await process.aclose() + + +# +# Sockets and networking +# + + +class _TrioSocketMixin(Generic[T_SockAddr]): + def __init__(self, trio_socket: TrioSocketType) -> None: + self._trio_socket = trio_socket + self._closed = False + + def _check_closed(self) -> None: + if self._closed: + raise ClosedResourceError + if self._trio_socket.fileno() < 0: + raise BrokenResourceError + + @property + def _raw_socket(self) -> socket.socket: + return self._trio_socket._sock # type: ignore[attr-defined] + + async def aclose(self) -> None: + if self._trio_socket.fileno() >= 0: + self._closed = True + self._trio_socket.close() + + def _convert_socket_error(self, exc: BaseException) -> NoReturn: + if isinstance(exc, trio.ClosedResourceError): + raise ClosedResourceError from exc + elif self._trio_socket.fileno() < 0 and self._closed: + raise ClosedResourceError from None + elif isinstance(exc, OSError): + raise BrokenResourceError from exc + else: + raise exc + + +class SocketStream(_TrioSocketMixin, abc.SocketStream): + def __init__(self, trio_socket: TrioSocketType) -> None: + super().__init__(trio_socket) + self._receive_guard = ResourceGuard("reading from") + self._send_guard = ResourceGuard("writing to") + + async def receive(self, max_bytes: int = 65536) -> bytes: + with self._receive_guard: + try: + data = await self._trio_socket.recv(max_bytes) + except BaseException as exc: + self._convert_socket_error(exc) + + if data: + return data + else: + raise EndOfStream + + async def send(self, item: bytes) -> None: + with self._send_guard: + view = memoryview(item) + while view: + try: + bytes_sent = await self._trio_socket.send(view) + except BaseException as exc: + self._convert_socket_error(exc) + + view = view[bytes_sent:] + + async def send_eof(self) -> None: + self._trio_socket.shutdown(socket.SHUT_WR) + + +class UNIXSocketStream(SocketStream, abc.UNIXSocketStream): + async def receive_fds(self, msglen: int, maxfds: int) -> tuple[bytes, list[int]]: + if not isinstance(msglen, int) or msglen < 0: + raise ValueError("msglen must be a non-negative integer") + if not isinstance(maxfds, int) or maxfds < 1: + raise ValueError("maxfds must be a positive integer") + + fds = array.array("i") + await trio.lowlevel.checkpoint() + with self._receive_guard: + while True: + try: + message, ancdata, flags, addr = await self._trio_socket.recvmsg( + msglen, socket.CMSG_LEN(maxfds * fds.itemsize) + ) + except BaseException as exc: + self._convert_socket_error(exc) + else: + if not message and not ancdata: + raise EndOfStream + + break + + for cmsg_level, cmsg_type, cmsg_data in ancdata: + if cmsg_level != socket.SOL_SOCKET or cmsg_type != socket.SCM_RIGHTS: + raise RuntimeError( + f"Received unexpected ancillary data; message = {message!r}, " + f"cmsg_level = {cmsg_level}, cmsg_type = {cmsg_type}" + ) + + fds.frombytes(cmsg_data[: len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) + + return message, list(fds) + + async def send_fds(self, message: bytes, fds: Collection[int | IOBase]) -> None: + if not message: + raise ValueError("message must not be empty") + if not fds: + raise ValueError("fds must not be empty") + + filenos: list[int] = [] + for fd in fds: + if isinstance(fd, int): + filenos.append(fd) + elif isinstance(fd, IOBase): + filenos.append(fd.fileno()) + + fdarray = array.array("i", filenos) + await trio.lowlevel.checkpoint() + with self._send_guard: + while True: + try: + await self._trio_socket.sendmsg( + [message], + [ + ( + socket.SOL_SOCKET, + socket.SCM_RIGHTS, + fdarray, + ) + ], + ) + break + except BaseException as exc: + self._convert_socket_error(exc) + + +class TCPSocketListener(_TrioSocketMixin, abc.SocketListener): + def __init__(self, raw_socket: socket.socket): + super().__init__(trio.socket.from_stdlib_socket(raw_socket)) + self._accept_guard = ResourceGuard("accepting connections from") + + async def accept(self) -> SocketStream: + with self._accept_guard: + try: + trio_socket, _addr = await self._trio_socket.accept() + except BaseException as exc: + self._convert_socket_error(exc) + + trio_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + return SocketStream(trio_socket) + + +class UNIXSocketListener(_TrioSocketMixin, abc.SocketListener): + def __init__(self, raw_socket: socket.socket): + super().__init__(trio.socket.from_stdlib_socket(raw_socket)) + self._accept_guard = ResourceGuard("accepting connections from") + + async def accept(self) -> UNIXSocketStream: + with self._accept_guard: + try: + trio_socket, _addr = await self._trio_socket.accept() + except BaseException as exc: + self._convert_socket_error(exc) + + return UNIXSocketStream(trio_socket) + + +class UDPSocket(_TrioSocketMixin[IPSockAddrType], abc.UDPSocket): + def __init__(self, trio_socket: TrioSocketType) -> None: + super().__init__(trio_socket) + self._receive_guard = ResourceGuard("reading from") + self._send_guard = ResourceGuard("writing to") + + async def receive(self) -> tuple[bytes, IPSockAddrType]: + with self._receive_guard: + try: + data, addr = await self._trio_socket.recvfrom(65536) + return data, convert_ipv6_sockaddr(addr) + except BaseException as exc: + self._convert_socket_error(exc) + + async def send(self, item: UDPPacketType) -> None: + with self._send_guard: + try: + await self._trio_socket.sendto(*item) + except BaseException as exc: + self._convert_socket_error(exc) + + +class ConnectedUDPSocket(_TrioSocketMixin[IPSockAddrType], abc.ConnectedUDPSocket): + def __init__(self, trio_socket: TrioSocketType) -> None: + super().__init__(trio_socket) + self._receive_guard = ResourceGuard("reading from") + self._send_guard = ResourceGuard("writing to") + + async def receive(self) -> bytes: + with self._receive_guard: + try: + return await self._trio_socket.recv(65536) + except BaseException as exc: + self._convert_socket_error(exc) + + async def send(self, item: bytes) -> None: + with self._send_guard: + try: + await self._trio_socket.send(item) + except BaseException as exc: + self._convert_socket_error(exc) + + +class UNIXDatagramSocket(_TrioSocketMixin[str], abc.UNIXDatagramSocket): + def __init__(self, trio_socket: TrioSocketType) -> None: + super().__init__(trio_socket) + self._receive_guard = ResourceGuard("reading from") + self._send_guard = ResourceGuard("writing to") + + async def receive(self) -> UNIXDatagramPacketType: + with self._receive_guard: + try: + data, addr = await self._trio_socket.recvfrom(65536) + return data, addr + except BaseException as exc: + self._convert_socket_error(exc) + + async def send(self, item: UNIXDatagramPacketType) -> None: + with self._send_guard: + try: + await self._trio_socket.sendto(*item) + except BaseException as exc: + self._convert_socket_error(exc) + + +class ConnectedUNIXDatagramSocket( + _TrioSocketMixin[str], abc.ConnectedUNIXDatagramSocket +): + def __init__(self, trio_socket: TrioSocketType) -> None: + super().__init__(trio_socket) + self._receive_guard = ResourceGuard("reading from") + self._send_guard = ResourceGuard("writing to") + + async def receive(self) -> bytes: + with self._receive_guard: + try: + return await self._trio_socket.recv(65536) + except BaseException as exc: + self._convert_socket_error(exc) + + async def send(self, item: bytes) -> None: + with self._send_guard: + try: + await self._trio_socket.send(item) + except BaseException as exc: + self._convert_socket_error(exc) + + +# +# Synchronization +# + + +class Event(BaseEvent): + def __new__(cls) -> Event: + return object.__new__(cls) + + def __init__(self) -> None: + self.__original = trio.Event() + + def is_set(self) -> bool: + return self.__original.is_set() + + async def wait(self) -> None: + return await self.__original.wait() + + def statistics(self) -> EventStatistics: + orig_statistics = self.__original.statistics() + return EventStatistics(tasks_waiting=orig_statistics.tasks_waiting) + + def set(self) -> None: + self.__original.set() + + +class Lock(BaseLock): + def __new__(cls, *, fast_acquire: bool = False) -> Lock: + return object.__new__(cls) + + def __init__(self, *, fast_acquire: bool = False) -> None: + self._fast_acquire = fast_acquire + self.__original = trio.Lock() + + @staticmethod + def _convert_runtime_error_msg(exc: RuntimeError) -> None: + if exc.args == ("attempt to re-acquire an already held Lock",): + exc.args = ("Attempted to acquire an already held Lock",) + + async def acquire(self) -> None: + if not self._fast_acquire: + try: + await self.__original.acquire() + except RuntimeError as exc: + self._convert_runtime_error_msg(exc) + raise + + return + + # This is the "fast path" where we don't let other tasks run + await trio.lowlevel.checkpoint_if_cancelled() + try: + self.__original.acquire_nowait() + except trio.WouldBlock: + await self.__original._lot.park() + except RuntimeError as exc: + self._convert_runtime_error_msg(exc) + raise + + def acquire_nowait(self) -> None: + try: + self.__original.acquire_nowait() + except trio.WouldBlock: + raise WouldBlock from None + except RuntimeError as exc: + self._convert_runtime_error_msg(exc) + raise + + def locked(self) -> bool: + return self.__original.locked() + + def release(self) -> None: + self.__original.release() + + def statistics(self) -> LockStatistics: + orig_statistics = self.__original.statistics() + owner = TrioTaskInfo(orig_statistics.owner) if orig_statistics.owner else None + return LockStatistics( + orig_statistics.locked, owner, orig_statistics.tasks_waiting + ) + + +class Semaphore(BaseSemaphore): + def __new__( + cls, + initial_value: int, + *, + max_value: int | None = None, + fast_acquire: bool = False, + ) -> Semaphore: + return object.__new__(cls) + + def __init__( + self, + initial_value: int, + *, + max_value: int | None = None, + fast_acquire: bool = False, + ) -> None: + super().__init__(initial_value, max_value=max_value, fast_acquire=fast_acquire) + self.__original = trio.Semaphore(initial_value, max_value=max_value) + + async def acquire(self) -> None: + if not self._fast_acquire: + await self.__original.acquire() + return + + # This is the "fast path" where we don't let other tasks run + await trio.lowlevel.checkpoint_if_cancelled() + try: + self.__original.acquire_nowait() + except trio.WouldBlock: + await self.__original._lot.park() + + def acquire_nowait(self) -> None: + try: + self.__original.acquire_nowait() + except trio.WouldBlock: + raise WouldBlock from None + + @property + def max_value(self) -> int | None: + return self.__original.max_value + + @property + def value(self) -> int: + return self.__original.value + + def release(self) -> None: + self.__original.release() + + def statistics(self) -> SemaphoreStatistics: + orig_statistics = self.__original.statistics() + return SemaphoreStatistics(orig_statistics.tasks_waiting) + + +class CapacityLimiter(BaseCapacityLimiter): + def __new__( + cls, + total_tokens: float | None = None, + *, + original: trio.CapacityLimiter | None = None, + ) -> CapacityLimiter: + return object.__new__(cls) + + def __init__( + self, + total_tokens: float | None = None, + *, + original: trio.CapacityLimiter | None = None, + ) -> None: + if original is not None: + self.__original = original + else: + assert total_tokens is not None + self.__original = trio.CapacityLimiter(total_tokens) + + async def __aenter__(self) -> None: + return await self.__original.__aenter__() + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + await self.__original.__aexit__(exc_type, exc_val, exc_tb) + + @property + def total_tokens(self) -> float: + return self.__original.total_tokens + + @total_tokens.setter + def total_tokens(self, value: float) -> None: + self.__original.total_tokens = value + + @property + def borrowed_tokens(self) -> int: + return self.__original.borrowed_tokens + + @property + def available_tokens(self) -> float: + return self.__original.available_tokens + + def acquire_nowait(self) -> None: + self.__original.acquire_nowait() + + def acquire_on_behalf_of_nowait(self, borrower: object) -> None: + self.__original.acquire_on_behalf_of_nowait(borrower) + + async def acquire(self) -> None: + await self.__original.acquire() + + async def acquire_on_behalf_of(self, borrower: object) -> None: + await self.__original.acquire_on_behalf_of(borrower) + + def release(self) -> None: + return self.__original.release() + + def release_on_behalf_of(self, borrower: object) -> None: + return self.__original.release_on_behalf_of(borrower) + + def statistics(self) -> CapacityLimiterStatistics: + orig = self.__original.statistics() + return CapacityLimiterStatistics( + borrowed_tokens=orig.borrowed_tokens, + total_tokens=orig.total_tokens, + borrowers=tuple(orig.borrowers), + tasks_waiting=orig.tasks_waiting, + ) + + +_capacity_limiter_wrapper: trio.lowlevel.RunVar = RunVar("_capacity_limiter_wrapper") + + +# +# Signal handling +# + + +class _SignalReceiver: + _iterator: AsyncIterator[int] + + def __init__(self, signals: tuple[Signals, ...]): + self._signals = signals + + def __enter__(self) -> _SignalReceiver: + self._cm = trio.open_signal_receiver(*self._signals) + self._iterator = self._cm.__enter__() + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> bool | None: + return self._cm.__exit__(exc_type, exc_val, exc_tb) + + def __aiter__(self) -> _SignalReceiver: + return self + + async def __anext__(self) -> Signals: + signum = await self._iterator.__anext__() + return Signals(signum) + + +# +# Testing and debugging +# + + +class TestRunner(abc.TestRunner): + def __init__(self, **options: Any) -> None: + from queue import Queue + + self._call_queue: Queue[Callable[[], object]] = Queue() + self._send_stream: MemoryObjectSendStream | None = None + self._options = options + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: types.TracebackType | None, + ) -> None: + if self._send_stream: + self._send_stream.close() + while self._send_stream is not None: + self._call_queue.get()() + + async def _run_tests_and_fixtures(self) -> None: + self._send_stream, receive_stream = create_memory_object_stream(1) + with receive_stream: + async for coro, outcome_holder in receive_stream: + try: + retval = await coro + except BaseException as exc: + outcome_holder.append(Error(exc)) + else: + outcome_holder.append(Value(retval)) + + def _main_task_finished(self, outcome: object) -> None: + self._send_stream = None + + def _call_in_runner_task( + self, + func: Callable[P, Awaitable[T_Retval]], + *args: P.args, + **kwargs: P.kwargs, + ) -> T_Retval: + if self._send_stream is None: + trio.lowlevel.start_guest_run( + self._run_tests_and_fixtures, + run_sync_soon_threadsafe=self._call_queue.put, + done_callback=self._main_task_finished, + **self._options, + ) + while self._send_stream is None: + self._call_queue.get()() + + outcome_holder: list[Outcome] = [] + self._send_stream.send_nowait((func(*args, **kwargs), outcome_holder)) + while not outcome_holder: + self._call_queue.get()() + + return outcome_holder[0].unwrap() + + def run_asyncgen_fixture( + self, + fixture_func: Callable[..., AsyncGenerator[T_Retval, Any]], + kwargs: dict[str, Any], + ) -> Iterable[T_Retval]: + asyncgen = fixture_func(**kwargs) + fixturevalue: T_Retval = self._call_in_runner_task(asyncgen.asend, None) + + yield fixturevalue + + try: + self._call_in_runner_task(asyncgen.asend, None) + except StopAsyncIteration: + pass + else: + self._call_in_runner_task(asyncgen.aclose) + raise RuntimeError("Async generator fixture did not stop") + + def run_fixture( + self, + fixture_func: Callable[..., Coroutine[Any, Any, T_Retval]], + kwargs: dict[str, Any], + ) -> T_Retval: + return self._call_in_runner_task(fixture_func, **kwargs) + + def run_test( + self, test_func: Callable[..., Coroutine[Any, Any, Any]], kwargs: dict[str, Any] + ) -> None: + self._call_in_runner_task(test_func, **kwargs) + + +class TrioTaskInfo(TaskInfo): + def __init__(self, task: trio.lowlevel.Task): + parent_id = None + if task.parent_nursery and task.parent_nursery.parent_task: + parent_id = id(task.parent_nursery.parent_task) + + super().__init__(id(task), parent_id, task.name, task.coro) + self._task = weakref.proxy(task) + + def has_pending_cancellation(self) -> bool: + try: + return self._task._cancel_status.effectively_cancelled + except ReferenceError: + # If the task is no longer around, it surely doesn't have a cancellation + # pending + return False + + +class TrioBackend(AsyncBackend): + @classmethod + def run( + cls, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], + args: tuple[Unpack[PosArgsT]], + kwargs: dict[str, Any], + options: dict[str, Any], + ) -> T_Retval: + return trio.run(func, *args) + + @classmethod + def current_token(cls) -> object: + return trio.lowlevel.current_trio_token() + + @classmethod + def current_time(cls) -> float: + return trio.current_time() + + @classmethod + def cancelled_exception_class(cls) -> type[BaseException]: + return trio.Cancelled + + @classmethod + async def checkpoint(cls) -> None: + await trio.lowlevel.checkpoint() + + @classmethod + async def checkpoint_if_cancelled(cls) -> None: + await trio.lowlevel.checkpoint_if_cancelled() + + @classmethod + async def cancel_shielded_checkpoint(cls) -> None: + await trio.lowlevel.cancel_shielded_checkpoint() + + @classmethod + async def sleep(cls, delay: float) -> None: + await trio.sleep(delay) + + @classmethod + def create_cancel_scope( + cls, *, deadline: float = math.inf, shield: bool = False + ) -> abc.CancelScope: + return CancelScope(deadline=deadline, shield=shield) + + @classmethod + def current_effective_deadline(cls) -> float: + return trio.current_effective_deadline() + + @classmethod + def create_task_group(cls) -> abc.TaskGroup: + return TaskGroup() + + @classmethod + def create_event(cls) -> abc.Event: + return Event() + + @classmethod + def create_lock(cls, *, fast_acquire: bool) -> Lock: + return Lock(fast_acquire=fast_acquire) + + @classmethod + def create_semaphore( + cls, + initial_value: int, + *, + max_value: int | None = None, + fast_acquire: bool = False, + ) -> abc.Semaphore: + return Semaphore(initial_value, max_value=max_value, fast_acquire=fast_acquire) + + @classmethod + def create_capacity_limiter(cls, total_tokens: float) -> CapacityLimiter: + return CapacityLimiter(total_tokens) + + @classmethod + async def run_sync_in_worker_thread( + cls, + func: Callable[[Unpack[PosArgsT]], T_Retval], + args: tuple[Unpack[PosArgsT]], + abandon_on_cancel: bool = False, + limiter: abc.CapacityLimiter | None = None, + ) -> T_Retval: + def wrapper() -> T_Retval: + with claim_worker_thread(TrioBackend, token): + return func(*args) + + token = TrioBackend.current_token() + return await run_sync( + wrapper, + abandon_on_cancel=abandon_on_cancel, + limiter=cast(trio.CapacityLimiter, limiter), + ) + + @classmethod + def check_cancelled(cls) -> None: + trio.from_thread.check_cancelled() + + @classmethod + def run_async_from_thread( + cls, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], + args: tuple[Unpack[PosArgsT]], + token: object, + ) -> T_Retval: + trio_token = cast("trio.lowlevel.TrioToken | None", token) + try: + return trio.from_thread.run(func, *args, trio_token=trio_token) + except trio.RunFinishedError: + raise RunFinishedError from None + + @classmethod + def run_sync_from_thread( + cls, + func: Callable[[Unpack[PosArgsT]], T_Retval], + args: tuple[Unpack[PosArgsT]], + token: object, + ) -> T_Retval: + trio_token = cast("trio.lowlevel.TrioToken | None", token) + try: + return trio.from_thread.run_sync(func, *args, trio_token=trio_token) + except trio.RunFinishedError: + raise RunFinishedError from None + + @classmethod + async def open_process( + cls, + command: StrOrBytesPath | Sequence[StrOrBytesPath], + *, + stdin: int | IO[Any] | None, + stdout: int | IO[Any] | None, + stderr: int | IO[Any] | None, + **kwargs: Any, + ) -> Process: + def convert_item(item: StrOrBytesPath) -> str: + str_or_bytes = os.fspath(item) + if isinstance(str_or_bytes, str): + return str_or_bytes + else: + return os.fsdecode(str_or_bytes) + + if isinstance(command, (str, bytes, PathLike)): + process = await trio.lowlevel.open_process( + convert_item(command), + stdin=stdin, + stdout=stdout, + stderr=stderr, + shell=True, + **kwargs, + ) + else: + process = await trio.lowlevel.open_process( + [convert_item(item) for item in command], + stdin=stdin, + stdout=stdout, + stderr=stderr, + shell=False, + **kwargs, + ) + + stdin_stream = SendStreamWrapper(process.stdin) if process.stdin else None + stdout_stream = ReceiveStreamWrapper(process.stdout) if process.stdout else None + stderr_stream = ReceiveStreamWrapper(process.stderr) if process.stderr else None + return Process(process, stdin_stream, stdout_stream, stderr_stream) + + @classmethod + def setup_process_pool_exit_at_shutdown(cls, workers: set[abc.Process]) -> None: + trio.lowlevel.spawn_system_task(_shutdown_process_pool, workers) + + @classmethod + async def connect_tcp( + cls, host: str, port: int, local_address: IPSockAddrType | None = None + ) -> SocketStream: + family = socket.AF_INET6 if ":" in host else socket.AF_INET + trio_socket = trio.socket.socket(family) + trio_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + if local_address: + await trio_socket.bind(local_address) + + try: + await trio_socket.connect((host, port)) + except BaseException: + trio_socket.close() + raise + + return SocketStream(trio_socket) + + @classmethod + async def connect_unix(cls, path: str | bytes) -> abc.UNIXSocketStream: + trio_socket = trio.socket.socket(socket.AF_UNIX) + try: + await trio_socket.connect(path) + except BaseException: + trio_socket.close() + raise + + return UNIXSocketStream(trio_socket) + + @classmethod + def create_tcp_listener(cls, sock: socket.socket) -> abc.SocketListener: + return TCPSocketListener(sock) + + @classmethod + def create_unix_listener(cls, sock: socket.socket) -> abc.SocketListener: + return UNIXSocketListener(sock) + + @classmethod + async def create_udp_socket( + cls, + family: socket.AddressFamily, + local_address: IPSockAddrType | None, + remote_address: IPSockAddrType | None, + reuse_port: bool, + ) -> UDPSocket | ConnectedUDPSocket: + trio_socket = trio.socket.socket(family=family, type=socket.SOCK_DGRAM) + + if reuse_port: + trio_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) + + if local_address: + await trio_socket.bind(local_address) + + if remote_address: + await trio_socket.connect(remote_address) + return ConnectedUDPSocket(trio_socket) + else: + return UDPSocket(trio_socket) + + @classmethod + @overload + async def create_unix_datagram_socket( + cls, raw_socket: socket.socket, remote_path: None + ) -> abc.UNIXDatagramSocket: ... + + @classmethod + @overload + async def create_unix_datagram_socket( + cls, raw_socket: socket.socket, remote_path: str | bytes + ) -> abc.ConnectedUNIXDatagramSocket: ... + + @classmethod + async def create_unix_datagram_socket( + cls, raw_socket: socket.socket, remote_path: str | bytes | None + ) -> abc.UNIXDatagramSocket | abc.ConnectedUNIXDatagramSocket: + trio_socket = trio.socket.from_stdlib_socket(raw_socket) + + if remote_path: + await trio_socket.connect(remote_path) + return ConnectedUNIXDatagramSocket(trio_socket) + else: + return UNIXDatagramSocket(trio_socket) + + @classmethod + async def getaddrinfo( + cls, + host: bytes | str | None, + port: str | int | None, + *, + family: int | AddressFamily = 0, + type: int | SocketKind = 0, + proto: int = 0, + flags: int = 0, + ) -> Sequence[ + tuple[ + AddressFamily, + SocketKind, + int, + str, + tuple[str, int] | tuple[str, int, int, int] | tuple[int, bytes], + ] + ]: + return await trio.socket.getaddrinfo(host, port, family, type, proto, flags) + + @classmethod + async def getnameinfo( + cls, sockaddr: IPSockAddrType, flags: int = 0 + ) -> tuple[str, str]: + return await trio.socket.getnameinfo(sockaddr, flags) + + @classmethod + async def wait_readable(cls, obj: FileDescriptorLike) -> None: + try: + await wait_readable(obj) + except trio.ClosedResourceError as exc: + raise ClosedResourceError().with_traceback(exc.__traceback__) from None + except trio.BusyResourceError: + raise BusyResourceError("reading from") from None + + @classmethod + async def wait_writable(cls, obj: FileDescriptorLike) -> None: + try: + await wait_writable(obj) + except trio.ClosedResourceError as exc: + raise ClosedResourceError().with_traceback(exc.__traceback__) from None + except trio.BusyResourceError: + raise BusyResourceError("writing to") from None + + @classmethod + def notify_closing(cls, obj: FileDescriptorLike) -> None: + notify_closing(obj) + + @classmethod + async def wrap_listener_socket(cls, sock: socket.socket) -> abc.SocketListener: + return TCPSocketListener(sock) + + @classmethod + async def wrap_stream_socket(cls, sock: socket.socket) -> SocketStream: + trio_sock = trio.socket.from_stdlib_socket(sock) + return SocketStream(trio_sock) + + @classmethod + async def wrap_unix_stream_socket(cls, sock: socket.socket) -> UNIXSocketStream: + trio_sock = trio.socket.from_stdlib_socket(sock) + return UNIXSocketStream(trio_sock) + + @classmethod + async def wrap_udp_socket(cls, sock: socket.socket) -> UDPSocket: + trio_sock = trio.socket.from_stdlib_socket(sock) + return UDPSocket(trio_sock) + + @classmethod + async def wrap_connected_udp_socket(cls, sock: socket.socket) -> ConnectedUDPSocket: + trio_sock = trio.socket.from_stdlib_socket(sock) + return ConnectedUDPSocket(trio_sock) + + @classmethod + async def wrap_unix_datagram_socket(cls, sock: socket.socket) -> UNIXDatagramSocket: + trio_sock = trio.socket.from_stdlib_socket(sock) + return UNIXDatagramSocket(trio_sock) + + @classmethod + async def wrap_connected_unix_datagram_socket( + cls, sock: socket.socket + ) -> ConnectedUNIXDatagramSocket: + trio_sock = trio.socket.from_stdlib_socket(sock) + return ConnectedUNIXDatagramSocket(trio_sock) + + @classmethod + def current_default_thread_limiter(cls) -> CapacityLimiter: + try: + return _capacity_limiter_wrapper.get() + except LookupError: + limiter = CapacityLimiter( + original=trio.to_thread.current_default_thread_limiter() + ) + _capacity_limiter_wrapper.set(limiter) + return limiter + + @classmethod + def open_signal_receiver( + cls, *signals: Signals + ) -> AbstractContextManager[AsyncIterator[Signals]]: + return _SignalReceiver(signals) + + @classmethod + def get_current_task(cls) -> TaskInfo: + task = current_task() + return TrioTaskInfo(task) + + @classmethod + def get_running_tasks(cls) -> Sequence[TaskInfo]: + root_task = current_root_task() + assert root_task + task_infos = [TrioTaskInfo(root_task)] + nurseries = root_task.child_nurseries + while nurseries: + new_nurseries: list[trio.Nursery] = [] + for nursery in nurseries: + for task in nursery.child_tasks: + task_infos.append(TrioTaskInfo(task)) + new_nurseries.extend(task.child_nurseries) + + nurseries = new_nurseries + + return task_infos + + @classmethod + async def wait_all_tasks_blocked(cls) -> None: + from trio.testing import wait_all_tasks_blocked + + await wait_all_tasks_blocked() + + @classmethod + def create_test_runner(cls, options: dict[str, Any]) -> TestRunner: + return TestRunner(**options) + + +backend_class = TrioBackend diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_asyncio_selector_thread.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_asyncio_selector_thread.py new file mode 100644 index 0000000..9f35bae --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_asyncio_selector_thread.py @@ -0,0 +1,167 @@ +from __future__ import annotations + +import asyncio +import socket +import threading +from collections.abc import Callable +from selectors import EVENT_READ, EVENT_WRITE, DefaultSelector +from typing import TYPE_CHECKING, Any + +if TYPE_CHECKING: + from _typeshed import FileDescriptorLike + +_selector_lock = threading.Lock() +_selector: Selector | None = None + + +class Selector: + def __init__(self) -> None: + self._thread = threading.Thread(target=self.run, name="AnyIO socket selector") + self._selector = DefaultSelector() + self._send, self._receive = socket.socketpair() + self._send.setblocking(False) + self._receive.setblocking(False) + # This somewhat reduces the amount of memory wasted queueing up data + # for wakeups. With these settings, maximum number of 1-byte sends + # before getting BlockingIOError: + # Linux 4.8: 6 + # macOS (darwin 15.5): 1 + # Windows 10: 525347 + # Windows you're weird. (And on Windows setting SNDBUF to 0 makes send + # blocking, even on non-blocking sockets, so don't do that.) + self._receive.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1) + self._send.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1) + # On Windows this is a TCP socket so this might matter. On other + # platforms this fails b/c AF_UNIX sockets aren't actually TCP. + try: + self._send.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + except OSError: + pass + + self._selector.register(self._receive, EVENT_READ) + self._closed = False + + def start(self) -> None: + self._thread.start() + threading._register_atexit(self._stop) # type: ignore[attr-defined] + + def _stop(self) -> None: + global _selector + self._closed = True + self._notify_self() + self._send.close() + self._thread.join() + self._selector.unregister(self._receive) + self._receive.close() + self._selector.close() + _selector = None + assert not self._selector.get_map(), ( + "selector still has registered file descriptors after shutdown" + ) + + def _notify_self(self) -> None: + try: + self._send.send(b"\x00") + except BlockingIOError: + pass + + def add_reader(self, fd: FileDescriptorLike, callback: Callable[[], Any]) -> None: + loop = asyncio.get_running_loop() + try: + key = self._selector.get_key(fd) + except KeyError: + self._selector.register(fd, EVENT_READ, {EVENT_READ: (loop, callback)}) + else: + if EVENT_READ in key.data: + raise ValueError( + "this file descriptor is already registered for reading" + ) + + key.data[EVENT_READ] = loop, callback + self._selector.modify(fd, key.events | EVENT_READ, key.data) + + self._notify_self() + + def add_writer(self, fd: FileDescriptorLike, callback: Callable[[], Any]) -> None: + loop = asyncio.get_running_loop() + try: + key = self._selector.get_key(fd) + except KeyError: + self._selector.register(fd, EVENT_WRITE, {EVENT_WRITE: (loop, callback)}) + else: + if EVENT_WRITE in key.data: + raise ValueError( + "this file descriptor is already registered for writing" + ) + + key.data[EVENT_WRITE] = loop, callback + self._selector.modify(fd, key.events | EVENT_WRITE, key.data) + + self._notify_self() + + def remove_reader(self, fd: FileDescriptorLike) -> bool: + try: + key = self._selector.get_key(fd) + except KeyError: + return False + + if new_events := key.events ^ EVENT_READ: + del key.data[EVENT_READ] + self._selector.modify(fd, new_events, key.data) + else: + self._selector.unregister(fd) + + return True + + def remove_writer(self, fd: FileDescriptorLike) -> bool: + try: + key = self._selector.get_key(fd) + except KeyError: + return False + + if new_events := key.events ^ EVENT_WRITE: + del key.data[EVENT_WRITE] + self._selector.modify(fd, new_events, key.data) + else: + self._selector.unregister(fd) + + return True + + def run(self) -> None: + while not self._closed: + for key, events in self._selector.select(): + if key.fileobj is self._receive: + try: + while self._receive.recv(4096): + pass + except BlockingIOError: + pass + + continue + + if events & EVENT_READ: + loop, callback = key.data[EVENT_READ] + self.remove_reader(key.fd) + try: + loop.call_soon_threadsafe(callback) + except RuntimeError: + pass # the loop was already closed + + if events & EVENT_WRITE: + loop, callback = key.data[EVENT_WRITE] + self.remove_writer(key.fd) + try: + loop.call_soon_threadsafe(callback) + except RuntimeError: + pass # the loop was already closed + + +def get_selector() -> Selector: + global _selector + + with _selector_lock: + if _selector is None: + _selector = Selector() + _selector.start() + + return _selector diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_contextmanagers.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_contextmanagers.py new file mode 100644 index 0000000..302f32b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_contextmanagers.py @@ -0,0 +1,200 @@ +from __future__ import annotations + +from abc import abstractmethod +from contextlib import AbstractAsyncContextManager, AbstractContextManager +from inspect import isasyncgen, iscoroutine, isgenerator +from types import TracebackType +from typing import Protocol, TypeVar, cast, final + +_T_co = TypeVar("_T_co", covariant=True) +_ExitT_co = TypeVar("_ExitT_co", covariant=True, bound="bool | None") + + +class _SupportsCtxMgr(Protocol[_T_co, _ExitT_co]): + def __contextmanager__(self) -> AbstractContextManager[_T_co, _ExitT_co]: ... + + +class _SupportsAsyncCtxMgr(Protocol[_T_co, _ExitT_co]): + def __asynccontextmanager__( + self, + ) -> AbstractAsyncContextManager[_T_co, _ExitT_co]: ... + + +class ContextManagerMixin: + """ + Mixin class providing context manager functionality via a generator-based + implementation. + + This class allows you to implement a context manager via :meth:`__contextmanager__` + which should return a generator. The mechanics are meant to mirror those of + :func:`@contextmanager `. + + .. note:: Classes using this mix-in are not reentrant as context managers, meaning + that once you enter it, you can't re-enter before first exiting it. + + .. seealso:: :doc:`contextmanagers` + """ + + __cm: AbstractContextManager[object, bool | None] | None = None + + @final + def __enter__(self: _SupportsCtxMgr[_T_co, bool | None]) -> _T_co: + # Needed for mypy to assume self still has the __cm member + assert isinstance(self, ContextManagerMixin) + if self.__cm is not None: + raise RuntimeError( + f"this {self.__class__.__qualname__} has already been entered" + ) + + cm = self.__contextmanager__() + if not isinstance(cm, AbstractContextManager): + if isgenerator(cm): + raise TypeError( + "__contextmanager__() returned a generator object instead of " + "a context manager. Did you forget to add the @contextmanager " + "decorator?" + ) + + raise TypeError( + f"__contextmanager__() did not return a context manager object, " + f"but {cm.__class__!r}" + ) + + if cm is self: + raise TypeError( + f"{self.__class__.__qualname__}.__contextmanager__() returned " + f"self. Did you forget to add the @contextmanager decorator and a " + f"'yield' statement?" + ) + + value = cm.__enter__() + self.__cm = cm + return value + + @final + def __exit__( + self: _SupportsCtxMgr[object, _ExitT_co], + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> _ExitT_co: + # Needed for mypy to assume self still has the __cm member + assert isinstance(self, ContextManagerMixin) + if self.__cm is None: + raise RuntimeError( + f"this {self.__class__.__qualname__} has not been entered yet" + ) + + # Prevent circular references + cm = self.__cm + del self.__cm + + return cast(_ExitT_co, cm.__exit__(exc_type, exc_val, exc_tb)) + + @abstractmethod + def __contextmanager__(self) -> AbstractContextManager[object, bool | None]: + """ + Implement your context manager logic here. + + This method **must** be decorated with + :func:`@contextmanager `. + + .. note:: Remember that the ``yield`` will raise any exception raised in the + enclosed context block, so use a ``finally:`` block to clean up resources! + + :return: a context manager object + """ + + +class AsyncContextManagerMixin: + """ + Mixin class providing async context manager functionality via a generator-based + implementation. + + This class allows you to implement a context manager via + :meth:`__asynccontextmanager__`. The mechanics are meant to mirror those of + :func:`@asynccontextmanager `. + + .. note:: Classes using this mix-in are not reentrant as context managers, meaning + that once you enter it, you can't re-enter before first exiting it. + + .. seealso:: :doc:`contextmanagers` + """ + + __cm: AbstractAsyncContextManager[object, bool | None] | None = None + + @final + async def __aenter__(self: _SupportsAsyncCtxMgr[_T_co, bool | None]) -> _T_co: + # Needed for mypy to assume self still has the __cm member + assert isinstance(self, AsyncContextManagerMixin) + if self.__cm is not None: + raise RuntimeError( + f"this {self.__class__.__qualname__} has already been entered" + ) + + cm = self.__asynccontextmanager__() + if not isinstance(cm, AbstractAsyncContextManager): + if isasyncgen(cm): + raise TypeError( + "__asynccontextmanager__() returned an async generator instead of " + "an async context manager. Did you forget to add the " + "@asynccontextmanager decorator?" + ) + elif iscoroutine(cm): + cm.close() + raise TypeError( + "__asynccontextmanager__() returned a coroutine object instead of " + "an async context manager. Did you forget to add the " + "@asynccontextmanager decorator and a 'yield' statement?" + ) + + raise TypeError( + f"__asynccontextmanager__() did not return an async context manager, " + f"but {cm.__class__!r}" + ) + + if cm is self: + raise TypeError( + f"{self.__class__.__qualname__}.__asynccontextmanager__() returned " + f"self. Did you forget to add the @asynccontextmanager decorator and a " + f"'yield' statement?" + ) + + value = await cm.__aenter__() + self.__cm = cm + return value + + @final + async def __aexit__( + self: _SupportsAsyncCtxMgr[object, _ExitT_co], + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> _ExitT_co: + assert isinstance(self, AsyncContextManagerMixin) + if self.__cm is None: + raise RuntimeError( + f"this {self.__class__.__qualname__} has not been entered yet" + ) + + # Prevent circular references + cm = self.__cm + del self.__cm + + return cast(_ExitT_co, await cm.__aexit__(exc_type, exc_val, exc_tb)) + + @abstractmethod + def __asynccontextmanager__( + self, + ) -> AbstractAsyncContextManager[object, bool | None]: + """ + Implement your async context manager logic here. + + This method **must** be decorated with + :func:`@asynccontextmanager `. + + .. note:: Remember that the ``yield`` will raise any exception raised in the + enclosed context block, so use a ``finally:`` block to clean up resources! + + :return: an async context manager object + """ diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_eventloop.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_eventloop.py new file mode 100644 index 0000000..59a69cc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_eventloop.py @@ -0,0 +1,234 @@ +from __future__ import annotations + +import math +import sys +import threading +from collections.abc import Awaitable, Callable, Generator +from contextlib import contextmanager +from contextvars import Token +from importlib import import_module +from typing import TYPE_CHECKING, Any, TypeVar + +from ._exceptions import NoEventLoopError + +if sys.version_info >= (3, 11): + from typing import TypeVarTuple, Unpack +else: + from typing_extensions import TypeVarTuple, Unpack + +sniffio: Any +try: + import sniffio +except ModuleNotFoundError: + sniffio = None + +if TYPE_CHECKING: + from ..abc import AsyncBackend + +# This must be updated when new backends are introduced +BACKENDS = "asyncio", "trio" + +T_Retval = TypeVar("T_Retval") +PosArgsT = TypeVarTuple("PosArgsT") + +threadlocals = threading.local() +loaded_backends: dict[str, type[AsyncBackend]] = {} + + +def run( + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], + *args: Unpack[PosArgsT], + backend: str = "asyncio", + backend_options: dict[str, Any] | None = None, +) -> T_Retval: + """ + Run the given coroutine function in an asynchronous event loop. + + The current thread must not be already running an event loop. + + :param func: a coroutine function + :param args: positional arguments to ``func`` + :param backend: name of the asynchronous event loop implementation – currently + either ``asyncio`` or ``trio`` + :param backend_options: keyword arguments to call the backend ``run()`` + implementation with (documented :ref:`here `) + :return: the return value of the coroutine function + :raises RuntimeError: if an asynchronous event loop is already running in this + thread + :raises LookupError: if the named backend is not found + + """ + if asynclib_name := current_async_library(): + raise RuntimeError(f"Already running {asynclib_name} in this thread") + + try: + async_backend = get_async_backend(backend) + except ImportError as exc: + raise LookupError(f"No such backend: {backend}") from exc + + token = None + if asynclib_name is None: + # Since we're in control of the event loop, we can cache the name of the async + # library + token = set_current_async_library(backend) + + try: + backend_options = backend_options or {} + return async_backend.run(func, args, {}, backend_options) + finally: + reset_current_async_library(token) + + +async def sleep(delay: float) -> None: + """ + Pause the current task for the specified duration. + + :param delay: the duration, in seconds + + """ + return await get_async_backend().sleep(delay) + + +async def sleep_forever() -> None: + """ + Pause the current task until it's cancelled. + + This is a shortcut for ``sleep(math.inf)``. + + .. versionadded:: 3.1 + + """ + await sleep(math.inf) + + +async def sleep_until(deadline: float) -> None: + """ + Pause the current task until the given time. + + :param deadline: the absolute time to wake up at (according to the internal + monotonic clock of the event loop) + + .. versionadded:: 3.1 + + """ + now = current_time() + await sleep(max(deadline - now, 0)) + + +def current_time() -> float: + """ + Return the current value of the event loop's internal clock. + + :return: the clock value (seconds) + :raises NoEventLoopError: if no supported asynchronous event loop is running in the + current thread + + """ + return get_async_backend().current_time() + + +def get_all_backends() -> tuple[str, ...]: + """Return a tuple of the names of all built-in backends.""" + return BACKENDS + + +def get_available_backends() -> tuple[str, ...]: + """ + Test for the availability of built-in backends. + + :return a tuple of the built-in backend names that were successfully imported + + .. versionadded:: 4.12 + + """ + available_backends: list[str] = [] + for backend_name in get_all_backends(): + try: + get_async_backend(backend_name) + except ImportError: + continue + + available_backends.append(backend_name) + + return tuple(available_backends) + + +def get_cancelled_exc_class() -> type[BaseException]: + """ + Return the current async library's cancellation exception class. + + :raises NoEventLoopError: if no supported asynchronous event loop is running in the + current thread + + """ + return get_async_backend().cancelled_exception_class() + + +# +# Private API +# + + +@contextmanager +def claim_worker_thread( + backend_class: type[AsyncBackend], token: object +) -> Generator[Any, None, None]: + from ..lowlevel import EventLoopToken + + threadlocals.current_token = EventLoopToken(backend_class, token) + try: + yield + finally: + del threadlocals.current_token + + +def get_async_backend(asynclib_name: str | None = None) -> type[AsyncBackend]: + if asynclib_name is None: + asynclib_name = current_async_library() + if not asynclib_name: + raise NoEventLoopError( + f"Not currently running on any asynchronous event loop. " + f"Available async backends: {', '.join(get_all_backends())}" + ) + + # We use our own dict instead of sys.modules to get the already imported back-end + # class because the appropriate modules in sys.modules could potentially be only + # partially initialized + try: + return loaded_backends[asynclib_name] + except KeyError: + module = import_module(f"anyio._backends._{asynclib_name}") + loaded_backends[asynclib_name] = module.backend_class + return module.backend_class + + +def current_async_library() -> str | None: + if sniffio is None: + # If sniffio is not installed, we assume we're either running asyncio or nothing + import asyncio + + try: + asyncio.get_running_loop() + return "asyncio" + except RuntimeError: + pass + else: + try: + return sniffio.current_async_library() + except sniffio.AsyncLibraryNotFoundError: + pass + + return None + + +def set_current_async_library(asynclib_name: str | None) -> Token | None: + # no-op if sniffio is not installed + if sniffio is None: + return None + + return sniffio.current_async_library_cvar.set(asynclib_name) + + +def reset_current_async_library(token: Token | None) -> None: + if token is not None: + sniffio.current_async_library_cvar.reset(token) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_exceptions.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_exceptions.py new file mode 100644 index 0000000..3776bed --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_exceptions.py @@ -0,0 +1,156 @@ +from __future__ import annotations + +import sys +from collections.abc import Generator +from textwrap import dedent +from typing import Any + +if sys.version_info < (3, 11): + from exceptiongroup import BaseExceptionGroup + + +class BrokenResourceError(Exception): + """ + Raised when trying to use a resource that has been rendered unusable due to external + causes (e.g. a send stream whose peer has disconnected). + """ + + +class BrokenWorkerProcess(Exception): + """ + Raised by :meth:`~anyio.to_process.run_sync` if the worker process terminates abruptly or + otherwise misbehaves. + """ + + +class BrokenWorkerInterpreter(Exception): + """ + Raised by :meth:`~anyio.to_interpreter.run_sync` if an unexpected exception is + raised in the subinterpreter. + """ + + def __init__(self, excinfo: Any): + # This was adapted from concurrent.futures.interpreter.ExecutionFailed + msg = excinfo.formatted + if not msg: + if excinfo.type and excinfo.msg: + msg = f"{excinfo.type.__name__}: {excinfo.msg}" + else: + msg = excinfo.type.__name__ or excinfo.msg + + super().__init__(msg) + self.excinfo = excinfo + + def __str__(self) -> str: + try: + formatted = self.excinfo.errdisplay + except Exception: + return super().__str__() + else: + return dedent( + f""" + {super().__str__()} + + Uncaught in the interpreter: + + {formatted} + """.strip() + ) + + +class BusyResourceError(Exception): + """ + Raised when two tasks are trying to read from or write to the same resource + concurrently. + """ + + def __init__(self, action: str): + super().__init__(f"Another task is already {action} this resource") + + +class ClosedResourceError(Exception): + """Raised when trying to use a resource that has been closed.""" + + +class ConnectionFailed(OSError): + """ + Raised when a connection attempt fails. + + .. note:: This class inherits from :exc:`OSError` for backwards compatibility. + """ + + +def iterate_exceptions( + exception: BaseException, +) -> Generator[BaseException, None, None]: + if isinstance(exception, BaseExceptionGroup): + for exc in exception.exceptions: + yield from iterate_exceptions(exc) + else: + yield exception + + +class DelimiterNotFound(Exception): + """ + Raised during + :meth:`~anyio.streams.buffered.BufferedByteReceiveStream.receive_until` if the + maximum number of bytes has been read without the delimiter being found. + """ + + def __init__(self, max_bytes: int) -> None: + super().__init__( + f"The delimiter was not found among the first {max_bytes} bytes" + ) + + +class EndOfStream(Exception): + """ + Raised when trying to read from a stream that has been closed from the other end. + """ + + +class IncompleteRead(Exception): + """ + Raised during + :meth:`~anyio.streams.buffered.BufferedByteReceiveStream.receive_exactly` or + :meth:`~anyio.streams.buffered.BufferedByteReceiveStream.receive_until` if the + connection is closed before the requested amount of bytes has been read. + """ + + def __init__(self) -> None: + super().__init__( + "The stream was closed before the read operation could be completed" + ) + + +class TypedAttributeLookupError(LookupError): + """ + Raised by :meth:`~anyio.TypedAttributeProvider.extra` when the given typed attribute + is not found and no default value has been given. + """ + + +class WouldBlock(Exception): + """Raised by ``X_nowait`` functions if ``X()`` would block.""" + + +class NoEventLoopError(RuntimeError): + """ + Raised by several functions that require an event loop to be running in the current + thread when there is no running event loop. + + This is also raised by :func:`.from_thread.run` and :func:`.from_thread.run_sync` + if not calling from an AnyIO worker thread, and no ``token`` was passed. + """ + + +class RunFinishedError(RuntimeError): + """ + Raised by :func:`.from_thread.run` and :func:`.from_thread.run_sync` if the event + loop associated with the explicitly passed token has already finished. + """ + + def __init__(self) -> None: + super().__init__( + "The event loop associated with the given token has already finished" + ) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_fileio.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_fileio.py new file mode 100644 index 0000000..061f0d7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_fileio.py @@ -0,0 +1,797 @@ +from __future__ import annotations + +import os +import pathlib +import sys +from collections.abc import ( + AsyncIterator, + Callable, + Iterable, + Iterator, + Sequence, +) +from dataclasses import dataclass +from functools import partial +from os import PathLike +from typing import ( + IO, + TYPE_CHECKING, + Any, + AnyStr, + ClassVar, + Final, + Generic, + overload, +) + +from .. import to_thread +from ..abc import AsyncResource + +if TYPE_CHECKING: + from types import ModuleType + + from _typeshed import OpenBinaryMode, OpenTextMode, ReadableBuffer, WriteableBuffer +else: + ReadableBuffer = OpenBinaryMode = OpenTextMode = WriteableBuffer = object + + +class AsyncFile(AsyncResource, Generic[AnyStr]): + """ + An asynchronous file object. + + This class wraps a standard file object and provides async friendly versions of the + following blocking methods (where available on the original file object): + + * read + * read1 + * readline + * readlines + * readinto + * readinto1 + * write + * writelines + * truncate + * seek + * tell + * flush + + All other methods are directly passed through. + + This class supports the asynchronous context manager protocol which closes the + underlying file at the end of the context block. + + This class also supports asynchronous iteration:: + + async with await open_file(...) as f: + async for line in f: + print(line) + """ + + def __init__(self, fp: IO[AnyStr]) -> None: + self._fp: Any = fp + + def __getattr__(self, name: str) -> object: + return getattr(self._fp, name) + + @property + def wrapped(self) -> IO[AnyStr]: + """The wrapped file object.""" + return self._fp + + async def __aiter__(self) -> AsyncIterator[AnyStr]: + while True: + line = await self.readline() + if line: + yield line + else: + break + + async def aclose(self) -> None: + return await to_thread.run_sync(self._fp.close) + + async def read(self, size: int = -1) -> AnyStr: + return await to_thread.run_sync(self._fp.read, size) + + async def read1(self: AsyncFile[bytes], size: int = -1) -> bytes: + return await to_thread.run_sync(self._fp.read1, size) + + async def readline(self) -> AnyStr: + return await to_thread.run_sync(self._fp.readline) + + async def readlines(self) -> list[AnyStr]: + return await to_thread.run_sync(self._fp.readlines) + + async def readinto(self: AsyncFile[bytes], b: WriteableBuffer) -> int: + return await to_thread.run_sync(self._fp.readinto, b) + + async def readinto1(self: AsyncFile[bytes], b: WriteableBuffer) -> int: + return await to_thread.run_sync(self._fp.readinto1, b) + + @overload + async def write(self: AsyncFile[bytes], b: ReadableBuffer) -> int: ... + + @overload + async def write(self: AsyncFile[str], b: str) -> int: ... + + async def write(self, b: ReadableBuffer | str) -> int: + return await to_thread.run_sync(self._fp.write, b) + + @overload + async def writelines( + self: AsyncFile[bytes], lines: Iterable[ReadableBuffer] + ) -> None: ... + + @overload + async def writelines(self: AsyncFile[str], lines: Iterable[str]) -> None: ... + + async def writelines(self, lines: Iterable[ReadableBuffer] | Iterable[str]) -> None: + return await to_thread.run_sync(self._fp.writelines, lines) + + async def truncate(self, size: int | None = None) -> int: + return await to_thread.run_sync(self._fp.truncate, size) + + async def seek(self, offset: int, whence: int | None = os.SEEK_SET) -> int: + return await to_thread.run_sync(self._fp.seek, offset, whence) + + async def tell(self) -> int: + return await to_thread.run_sync(self._fp.tell) + + async def flush(self) -> None: + return await to_thread.run_sync(self._fp.flush) + + +@overload +async def open_file( + file: str | PathLike[str] | int, + mode: OpenBinaryMode, + buffering: int = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., + closefd: bool = ..., + opener: Callable[[str, int], int] | None = ..., +) -> AsyncFile[bytes]: ... + + +@overload +async def open_file( + file: str | PathLike[str] | int, + mode: OpenTextMode = ..., + buffering: int = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., + closefd: bool = ..., + opener: Callable[[str, int], int] | None = ..., +) -> AsyncFile[str]: ... + + +async def open_file( + file: str | PathLike[str] | int, + mode: str = "r", + buffering: int = -1, + encoding: str | None = None, + errors: str | None = None, + newline: str | None = None, + closefd: bool = True, + opener: Callable[[str, int], int] | None = None, +) -> AsyncFile[Any]: + """ + Open a file asynchronously. + + The arguments are exactly the same as for the builtin :func:`open`. + + :return: an asynchronous file object + + """ + fp = await to_thread.run_sync( + open, file, mode, buffering, encoding, errors, newline, closefd, opener + ) + return AsyncFile(fp) + + +def wrap_file(file: IO[AnyStr]) -> AsyncFile[AnyStr]: + """ + Wrap an existing file as an asynchronous file. + + :param file: an existing file-like object + :return: an asynchronous file object + + """ + return AsyncFile(file) + + +@dataclass(eq=False) +class _PathIterator(AsyncIterator["Path"]): + iterator: Iterator[PathLike[str]] + + async def __anext__(self) -> Path: + nextval = await to_thread.run_sync( + next, self.iterator, None, abandon_on_cancel=True + ) + if nextval is None: + raise StopAsyncIteration from None + + return Path(nextval) + + +class Path: + """ + An asynchronous version of :class:`pathlib.Path`. + + This class cannot be substituted for :class:`pathlib.Path` or + :class:`pathlib.PurePath`, but it is compatible with the :class:`os.PathLike` + interface. + + It implements the Python 3.10 version of :class:`pathlib.Path` interface, except for + the deprecated :meth:`~pathlib.Path.link_to` method. + + Some methods may be unavailable or have limited functionality, based on the Python + version: + + * :meth:`~pathlib.Path.copy` (available on Python 3.14 or later) + * :meth:`~pathlib.Path.copy_into` (available on Python 3.14 or later) + * :meth:`~pathlib.Path.from_uri` (available on Python 3.13 or later) + * :meth:`~pathlib.PurePath.full_match` (available on Python 3.13 or later) + * :attr:`~pathlib.Path.info` (available on Python 3.14 or later) + * :meth:`~pathlib.Path.is_junction` (available on Python 3.12 or later) + * :meth:`~pathlib.PurePath.match` (the ``case_sensitive`` parameter is only + available on Python 3.13 or later) + * :meth:`~pathlib.Path.move` (available on Python 3.14 or later) + * :meth:`~pathlib.Path.move_into` (available on Python 3.14 or later) + * :meth:`~pathlib.PurePath.relative_to` (the ``walk_up`` parameter is only available + on Python 3.12 or later) + * :meth:`~pathlib.Path.walk` (available on Python 3.12 or later) + + Any methods that do disk I/O need to be awaited on. These methods are: + + * :meth:`~pathlib.Path.absolute` + * :meth:`~pathlib.Path.chmod` + * :meth:`~pathlib.Path.cwd` + * :meth:`~pathlib.Path.exists` + * :meth:`~pathlib.Path.expanduser` + * :meth:`~pathlib.Path.group` + * :meth:`~pathlib.Path.hardlink_to` + * :meth:`~pathlib.Path.home` + * :meth:`~pathlib.Path.is_block_device` + * :meth:`~pathlib.Path.is_char_device` + * :meth:`~pathlib.Path.is_dir` + * :meth:`~pathlib.Path.is_fifo` + * :meth:`~pathlib.Path.is_file` + * :meth:`~pathlib.Path.is_junction` + * :meth:`~pathlib.Path.is_mount` + * :meth:`~pathlib.Path.is_socket` + * :meth:`~pathlib.Path.is_symlink` + * :meth:`~pathlib.Path.lchmod` + * :meth:`~pathlib.Path.lstat` + * :meth:`~pathlib.Path.mkdir` + * :meth:`~pathlib.Path.open` + * :meth:`~pathlib.Path.owner` + * :meth:`~pathlib.Path.read_bytes` + * :meth:`~pathlib.Path.read_text` + * :meth:`~pathlib.Path.readlink` + * :meth:`~pathlib.Path.rename` + * :meth:`~pathlib.Path.replace` + * :meth:`~pathlib.Path.resolve` + * :meth:`~pathlib.Path.rmdir` + * :meth:`~pathlib.Path.samefile` + * :meth:`~pathlib.Path.stat` + * :meth:`~pathlib.Path.symlink_to` + * :meth:`~pathlib.Path.touch` + * :meth:`~pathlib.Path.unlink` + * :meth:`~pathlib.Path.walk` + * :meth:`~pathlib.Path.write_bytes` + * :meth:`~pathlib.Path.write_text` + + Additionally, the following methods return an async iterator yielding + :class:`~.Path` objects: + + * :meth:`~pathlib.Path.glob` + * :meth:`~pathlib.Path.iterdir` + * :meth:`~pathlib.Path.rglob` + """ + + __slots__ = "_path", "__weakref__" + + __weakref__: Any + + def __init__(self, *args: str | PathLike[str]) -> None: + self._path: Final[pathlib.Path] = pathlib.Path(*args) + + def __fspath__(self) -> str: + return self._path.__fspath__() + + def __str__(self) -> str: + return self._path.__str__() + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self.as_posix()!r})" + + def __bytes__(self) -> bytes: + return self._path.__bytes__() + + def __hash__(self) -> int: + return self._path.__hash__() + + def __eq__(self, other: object) -> bool: + target = other._path if isinstance(other, Path) else other + return self._path.__eq__(target) + + def __lt__(self, other: pathlib.PurePath | Path) -> bool: + target = other._path if isinstance(other, Path) else other + return self._path.__lt__(target) + + def __le__(self, other: pathlib.PurePath | Path) -> bool: + target = other._path if isinstance(other, Path) else other + return self._path.__le__(target) + + def __gt__(self, other: pathlib.PurePath | Path) -> bool: + target = other._path if isinstance(other, Path) else other + return self._path.__gt__(target) + + def __ge__(self, other: pathlib.PurePath | Path) -> bool: + target = other._path if isinstance(other, Path) else other + return self._path.__ge__(target) + + def __truediv__(self, other: str | PathLike[str]) -> Path: + return Path(self._path / other) + + def __rtruediv__(self, other: str | PathLike[str]) -> Path: + return Path(other) / self + + @property + def parts(self) -> tuple[str, ...]: + return self._path.parts + + @property + def drive(self) -> str: + return self._path.drive + + @property + def root(self) -> str: + return self._path.root + + @property + def anchor(self) -> str: + return self._path.anchor + + @property + def parents(self) -> Sequence[Path]: + return tuple(Path(p) for p in self._path.parents) + + @property + def parent(self) -> Path: + return Path(self._path.parent) + + @property + def name(self) -> str: + return self._path.name + + @property + def suffix(self) -> str: + return self._path.suffix + + @property + def suffixes(self) -> list[str]: + return self._path.suffixes + + @property + def stem(self) -> str: + return self._path.stem + + async def absolute(self) -> Path: + path = await to_thread.run_sync(self._path.absolute) + return Path(path) + + def as_posix(self) -> str: + return self._path.as_posix() + + def as_uri(self) -> str: + return self._path.as_uri() + + if sys.version_info >= (3, 13): + parser: ClassVar[ModuleType] = pathlib.Path.parser + + @classmethod + def from_uri(cls, uri: str) -> Path: + return Path(pathlib.Path.from_uri(uri)) + + def full_match( + self, path_pattern: str, *, case_sensitive: bool | None = None + ) -> bool: + return self._path.full_match(path_pattern, case_sensitive=case_sensitive) + + def match( + self, path_pattern: str, *, case_sensitive: bool | None = None + ) -> bool: + return self._path.match(path_pattern, case_sensitive=case_sensitive) + else: + + def match(self, path_pattern: str) -> bool: + return self._path.match(path_pattern) + + if sys.version_info >= (3, 14): + + @property + def info(self) -> Any: # TODO: add return type annotation when Typeshed gets it + return self._path.info + + async def copy( + self, + target: str | os.PathLike[str], + *, + follow_symlinks: bool = True, + preserve_metadata: bool = False, + ) -> Path: + func = partial( + self._path.copy, + follow_symlinks=follow_symlinks, + preserve_metadata=preserve_metadata, + ) + return Path(await to_thread.run_sync(func, pathlib.Path(target))) + + async def copy_into( + self, + target_dir: str | os.PathLike[str], + *, + follow_symlinks: bool = True, + preserve_metadata: bool = False, + ) -> Path: + func = partial( + self._path.copy_into, + follow_symlinks=follow_symlinks, + preserve_metadata=preserve_metadata, + ) + return Path(await to_thread.run_sync(func, pathlib.Path(target_dir))) + + async def move(self, target: str | os.PathLike[str]) -> Path: + # Upstream does not handle anyio.Path properly as a PathLike + target = pathlib.Path(target) + return Path(await to_thread.run_sync(self._path.move, target)) + + async def move_into( + self, + target_dir: str | os.PathLike[str], + ) -> Path: + return Path(await to_thread.run_sync(self._path.move_into, target_dir)) + + def is_relative_to(self, other: str | PathLike[str]) -> bool: + try: + self.relative_to(other) + return True + except ValueError: + return False + + async def chmod(self, mode: int, *, follow_symlinks: bool = True) -> None: + func = partial(os.chmod, follow_symlinks=follow_symlinks) + return await to_thread.run_sync(func, self._path, mode) + + @classmethod + async def cwd(cls) -> Path: + path = await to_thread.run_sync(pathlib.Path.cwd) + return cls(path) + + async def exists(self) -> bool: + return await to_thread.run_sync(self._path.exists, abandon_on_cancel=True) + + async def expanduser(self) -> Path: + return Path( + await to_thread.run_sync(self._path.expanduser, abandon_on_cancel=True) + ) + + if sys.version_info < (3, 12): + # Python 3.11 and earlier + def glob(self, pattern: str) -> AsyncIterator[Path]: + gen = self._path.glob(pattern) + return _PathIterator(gen) + elif (3, 12) <= sys.version_info < (3, 13): + # changed in Python 3.12: + # - The case_sensitive parameter was added. + def glob( + self, + pattern: str, + *, + case_sensitive: bool | None = None, + ) -> AsyncIterator[Path]: + gen = self._path.glob(pattern, case_sensitive=case_sensitive) + return _PathIterator(gen) + elif sys.version_info >= (3, 13): + # Changed in Python 3.13: + # - The recurse_symlinks parameter was added. + # - The pattern parameter accepts a path-like object. + def glob( # type: ignore[misc] # mypy doesn't allow for differing signatures in a conditional block + self, + pattern: str | PathLike[str], + *, + case_sensitive: bool | None = None, + recurse_symlinks: bool = False, + ) -> AsyncIterator[Path]: + gen = self._path.glob( + pattern, # type: ignore[arg-type] + case_sensitive=case_sensitive, + recurse_symlinks=recurse_symlinks, + ) + return _PathIterator(gen) + + async def group(self) -> str: + return await to_thread.run_sync(self._path.group, abandon_on_cancel=True) + + async def hardlink_to( + self, target: str | bytes | PathLike[str] | PathLike[bytes] + ) -> None: + if isinstance(target, Path): + target = target._path + + await to_thread.run_sync(os.link, target, self) + + @classmethod + async def home(cls) -> Path: + home_path = await to_thread.run_sync(pathlib.Path.home) + return cls(home_path) + + def is_absolute(self) -> bool: + return self._path.is_absolute() + + async def is_block_device(self) -> bool: + return await to_thread.run_sync( + self._path.is_block_device, abandon_on_cancel=True + ) + + async def is_char_device(self) -> bool: + return await to_thread.run_sync( + self._path.is_char_device, abandon_on_cancel=True + ) + + async def is_dir(self) -> bool: + return await to_thread.run_sync(self._path.is_dir, abandon_on_cancel=True) + + async def is_fifo(self) -> bool: + return await to_thread.run_sync(self._path.is_fifo, abandon_on_cancel=True) + + async def is_file(self) -> bool: + return await to_thread.run_sync(self._path.is_file, abandon_on_cancel=True) + + if sys.version_info >= (3, 12): + + async def is_junction(self) -> bool: + return await to_thread.run_sync(self._path.is_junction) + + async def is_mount(self) -> bool: + return await to_thread.run_sync( + os.path.ismount, self._path, abandon_on_cancel=True + ) + + def is_reserved(self) -> bool: + return self._path.is_reserved() + + async def is_socket(self) -> bool: + return await to_thread.run_sync(self._path.is_socket, abandon_on_cancel=True) + + async def is_symlink(self) -> bool: + return await to_thread.run_sync(self._path.is_symlink, abandon_on_cancel=True) + + async def iterdir(self) -> AsyncIterator[Path]: + gen = ( + self._path.iterdir() + if sys.version_info < (3, 13) + else await to_thread.run_sync(self._path.iterdir, abandon_on_cancel=True) + ) + async for path in _PathIterator(gen): + yield path + + def joinpath(self, *args: str | PathLike[str]) -> Path: + return Path(self._path.joinpath(*args)) + + async def lchmod(self, mode: int) -> None: + await to_thread.run_sync(self._path.lchmod, mode) + + async def lstat(self) -> os.stat_result: + return await to_thread.run_sync(self._path.lstat, abandon_on_cancel=True) + + async def mkdir( + self, mode: int = 0o777, parents: bool = False, exist_ok: bool = False + ) -> None: + await to_thread.run_sync(self._path.mkdir, mode, parents, exist_ok) + + @overload + async def open( + self, + mode: OpenBinaryMode, + buffering: int = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., + ) -> AsyncFile[bytes]: ... + + @overload + async def open( + self, + mode: OpenTextMode = ..., + buffering: int = ..., + encoding: str | None = ..., + errors: str | None = ..., + newline: str | None = ..., + ) -> AsyncFile[str]: ... + + async def open( + self, + mode: str = "r", + buffering: int = -1, + encoding: str | None = None, + errors: str | None = None, + newline: str | None = None, + ) -> AsyncFile[Any]: + fp = await to_thread.run_sync( + self._path.open, mode, buffering, encoding, errors, newline + ) + return AsyncFile(fp) + + async def owner(self) -> str: + return await to_thread.run_sync(self._path.owner, abandon_on_cancel=True) + + async def read_bytes(self) -> bytes: + return await to_thread.run_sync(self._path.read_bytes) + + async def read_text( + self, encoding: str | None = None, errors: str | None = None + ) -> str: + return await to_thread.run_sync(self._path.read_text, encoding, errors) + + if sys.version_info >= (3, 12): + + def relative_to( + self, *other: str | PathLike[str], walk_up: bool = False + ) -> Path: + # relative_to() should work with any PathLike but it doesn't + others = [pathlib.Path(other) for other in other] + return Path(self._path.relative_to(*others, walk_up=walk_up)) + + else: + + def relative_to(self, *other: str | PathLike[str]) -> Path: + return Path(self._path.relative_to(*other)) + + async def readlink(self) -> Path: + target = await to_thread.run_sync(os.readlink, self._path) + return Path(target) + + async def rename(self, target: str | pathlib.PurePath | Path) -> Path: + if isinstance(target, Path): + target = target._path + + await to_thread.run_sync(self._path.rename, target) + return Path(target) + + async def replace(self, target: str | pathlib.PurePath | Path) -> Path: + if isinstance(target, Path): + target = target._path + + await to_thread.run_sync(self._path.replace, target) + return Path(target) + + async def resolve(self, strict: bool = False) -> Path: + func = partial(self._path.resolve, strict=strict) + return Path(await to_thread.run_sync(func, abandon_on_cancel=True)) + + if sys.version_info < (3, 12): + # Pre Python 3.12 + def rglob(self, pattern: str) -> AsyncIterator[Path]: + gen = self._path.rglob(pattern) + return _PathIterator(gen) + elif (3, 12) <= sys.version_info < (3, 13): + # Changed in Python 3.12: + # - The case_sensitive parameter was added. + def rglob( + self, pattern: str, *, case_sensitive: bool | None = None + ) -> AsyncIterator[Path]: + gen = self._path.rglob(pattern, case_sensitive=case_sensitive) + return _PathIterator(gen) + elif sys.version_info >= (3, 13): + # Changed in Python 3.13: + # - The recurse_symlinks parameter was added. + # - The pattern parameter accepts a path-like object. + def rglob( # type: ignore[misc] # mypy doesn't allow for differing signatures in a conditional block + self, + pattern: str | PathLike[str], + *, + case_sensitive: bool | None = None, + recurse_symlinks: bool = False, + ) -> AsyncIterator[Path]: + gen = self._path.rglob( + pattern, # type: ignore[arg-type] + case_sensitive=case_sensitive, + recurse_symlinks=recurse_symlinks, + ) + return _PathIterator(gen) + + async def rmdir(self) -> None: + await to_thread.run_sync(self._path.rmdir) + + async def samefile(self, other_path: str | PathLike[str]) -> bool: + if isinstance(other_path, Path): + other_path = other_path._path + + return await to_thread.run_sync( + self._path.samefile, other_path, abandon_on_cancel=True + ) + + async def stat(self, *, follow_symlinks: bool = True) -> os.stat_result: + func = partial(os.stat, follow_symlinks=follow_symlinks) + return await to_thread.run_sync(func, self._path, abandon_on_cancel=True) + + async def symlink_to( + self, + target: str | bytes | PathLike[str] | PathLike[bytes], + target_is_directory: bool = False, + ) -> None: + if isinstance(target, Path): + target = target._path + + await to_thread.run_sync(self._path.symlink_to, target, target_is_directory) + + async def touch(self, mode: int = 0o666, exist_ok: bool = True) -> None: + await to_thread.run_sync(self._path.touch, mode, exist_ok) + + async def unlink(self, missing_ok: bool = False) -> None: + try: + await to_thread.run_sync(self._path.unlink) + except FileNotFoundError: + if not missing_ok: + raise + + if sys.version_info >= (3, 12): + + async def walk( + self, + top_down: bool = True, + on_error: Callable[[OSError], object] | None = None, + follow_symlinks: bool = False, + ) -> AsyncIterator[tuple[Path, list[str], list[str]]]: + def get_next_value() -> tuple[pathlib.Path, list[str], list[str]] | None: + try: + return next(gen) + except StopIteration: + return None + + gen = self._path.walk(top_down, on_error, follow_symlinks) + while True: + value = await to_thread.run_sync(get_next_value) + if value is None: + return + + root, dirs, paths = value + yield Path(root), dirs, paths + + def with_name(self, name: str) -> Path: + return Path(self._path.with_name(name)) + + def with_stem(self, stem: str) -> Path: + return Path(self._path.with_name(stem + self._path.suffix)) + + def with_suffix(self, suffix: str) -> Path: + return Path(self._path.with_suffix(suffix)) + + def with_segments(self, *pathsegments: str | PathLike[str]) -> Path: + return Path(*pathsegments) + + async def write_bytes(self, data: bytes) -> int: + return await to_thread.run_sync(self._path.write_bytes, data) + + async def write_text( + self, + data: str, + encoding: str | None = None, + errors: str | None = None, + newline: str | None = None, + ) -> int: + # Path.write_text() does not support the "newline" parameter before Python 3.10 + def sync_write_text() -> int: + with self._path.open( + "w", encoding=encoding, errors=errors, newline=newline + ) as fp: + return fp.write(data) + + return await to_thread.run_sync(sync_write_text) + + +PathLike.register(Path) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_resources.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_resources.py new file mode 100644 index 0000000..b9a5344 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_resources.py @@ -0,0 +1,18 @@ +from __future__ import annotations + +from ..abc import AsyncResource +from ._tasks import CancelScope + + +async def aclose_forcefully(resource: AsyncResource) -> None: + """ + Close an asynchronous resource in a cancelled scope. + + Doing this closes the resource without waiting on anything. + + :param resource: the resource to close + + """ + with CancelScope() as scope: + scope.cancel() + await resource.aclose() diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_signals.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_signals.py new file mode 100644 index 0000000..e24c79e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_signals.py @@ -0,0 +1,29 @@ +from __future__ import annotations + +from collections.abc import AsyncIterator +from contextlib import AbstractContextManager +from signal import Signals + +from ._eventloop import get_async_backend + + +def open_signal_receiver( + *signals: Signals, +) -> AbstractContextManager[AsyncIterator[Signals]]: + """ + Start receiving operating system signals. + + :param signals: signals to receive (e.g. ``signal.SIGINT``) + :return: an asynchronous context manager for an asynchronous iterator which yields + signal numbers + :raises NoEventLoopError: if no supported asynchronous event loop is running in the + current thread + + .. warning:: Windows does not support signals natively so it is best to avoid + relying on this in cross-platform applications. + + .. warning:: On asyncio, this permanently replaces any previous signal handler for + the given signals, as set via :meth:`~asyncio.loop.add_signal_handler`. + + """ + return get_async_backend().open_signal_receiver(*signals) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_sockets.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_sockets.py new file mode 100644 index 0000000..6c99b3a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_sockets.py @@ -0,0 +1,1003 @@ +from __future__ import annotations + +import errno +import os +import socket +import ssl +import stat +import sys +from collections.abc import Awaitable +from dataclasses import dataclass +from ipaddress import IPv4Address, IPv6Address, ip_address +from os import PathLike, chmod +from socket import AddressFamily, SocketKind +from typing import TYPE_CHECKING, Any, Literal, cast, overload + +from .. import ConnectionFailed, to_thread +from ..abc import ( + ByteStreamConnectable, + ConnectedUDPSocket, + ConnectedUNIXDatagramSocket, + IPAddressType, + IPSockAddrType, + SocketListener, + SocketStream, + UDPSocket, + UNIXDatagramSocket, + UNIXSocketStream, +) +from ..streams.stapled import MultiListener +from ..streams.tls import TLSConnectable, TLSStream +from ._eventloop import get_async_backend +from ._resources import aclose_forcefully +from ._synchronization import Event +from ._tasks import create_task_group, move_on_after + +if TYPE_CHECKING: + from _typeshed import FileDescriptorLike +else: + FileDescriptorLike = object + +if sys.version_info < (3, 11): + from exceptiongroup import ExceptionGroup + +if sys.version_info >= (3, 12): + from typing import override +else: + from typing_extensions import override + +if sys.version_info < (3, 13): + from typing_extensions import deprecated +else: + from warnings import deprecated + +IPPROTO_IPV6 = getattr(socket, "IPPROTO_IPV6", 41) # https://bugs.python.org/issue29515 + +AnyIPAddressFamily = Literal[ + AddressFamily.AF_UNSPEC, AddressFamily.AF_INET, AddressFamily.AF_INET6 +] +IPAddressFamily = Literal[AddressFamily.AF_INET, AddressFamily.AF_INET6] + + +# tls_hostname given +@overload +async def connect_tcp( + remote_host: IPAddressType, + remote_port: int, + *, + local_host: IPAddressType | None = ..., + ssl_context: ssl.SSLContext | None = ..., + tls_standard_compatible: bool = ..., + tls_hostname: str, + happy_eyeballs_delay: float = ..., +) -> TLSStream: ... + + +# ssl_context given +@overload +async def connect_tcp( + remote_host: IPAddressType, + remote_port: int, + *, + local_host: IPAddressType | None = ..., + ssl_context: ssl.SSLContext, + tls_standard_compatible: bool = ..., + tls_hostname: str | None = ..., + happy_eyeballs_delay: float = ..., +) -> TLSStream: ... + + +# tls=True +@overload +async def connect_tcp( + remote_host: IPAddressType, + remote_port: int, + *, + local_host: IPAddressType | None = ..., + tls: Literal[True], + ssl_context: ssl.SSLContext | None = ..., + tls_standard_compatible: bool = ..., + tls_hostname: str | None = ..., + happy_eyeballs_delay: float = ..., +) -> TLSStream: ... + + +# tls=False +@overload +async def connect_tcp( + remote_host: IPAddressType, + remote_port: int, + *, + local_host: IPAddressType | None = ..., + tls: Literal[False], + ssl_context: ssl.SSLContext | None = ..., + tls_standard_compatible: bool = ..., + tls_hostname: str | None = ..., + happy_eyeballs_delay: float = ..., +) -> SocketStream: ... + + +# No TLS arguments +@overload +async def connect_tcp( + remote_host: IPAddressType, + remote_port: int, + *, + local_host: IPAddressType | None = ..., + happy_eyeballs_delay: float = ..., +) -> SocketStream: ... + + +async def connect_tcp( + remote_host: IPAddressType, + remote_port: int, + *, + local_host: IPAddressType | None = None, + tls: bool = False, + ssl_context: ssl.SSLContext | None = None, + tls_standard_compatible: bool = True, + tls_hostname: str | None = None, + happy_eyeballs_delay: float = 0.25, +) -> SocketStream | TLSStream: + """ + Connect to a host using the TCP protocol. + + This function implements the stateless version of the Happy Eyeballs algorithm (RFC + 6555). If ``remote_host`` is a host name that resolves to multiple IP addresses, + each one is tried until one connection attempt succeeds. If the first attempt does + not connected within 250 milliseconds, a second attempt is started using the next + address in the list, and so on. On IPv6 enabled systems, an IPv6 address (if + available) is tried first. + + When the connection has been established, a TLS handshake will be done if either + ``ssl_context`` or ``tls_hostname`` is not ``None``, or if ``tls`` is ``True``. + + :param remote_host: the IP address or host name to connect to + :param remote_port: port on the target host to connect to + :param local_host: the interface address or name to bind the socket to before + connecting + :param tls: ``True`` to do a TLS handshake with the connected stream and return a + :class:`~anyio.streams.tls.TLSStream` instead + :param ssl_context: the SSL context object to use (if omitted, a default context is + created) + :param tls_standard_compatible: If ``True``, performs the TLS shutdown handshake + before closing the stream and requires that the server does this as well. + Otherwise, :exc:`~ssl.SSLEOFError` may be raised during reads from the stream. + Some protocols, such as HTTP, require this option to be ``False``. + See :meth:`~ssl.SSLContext.wrap_socket` for details. + :param tls_hostname: host name to check the server certificate against (defaults to + the value of ``remote_host``) + :param happy_eyeballs_delay: delay (in seconds) before starting the next connection + attempt + :return: a socket stream object if no TLS handshake was done, otherwise a TLS stream + :raises ConnectionFailed: if the connection fails + + """ + # Placed here due to https://github.com/python/mypy/issues/7057 + connected_stream: SocketStream | None = None + + async def try_connect(remote_host: str, event: Event) -> None: + nonlocal connected_stream + try: + stream = await asynclib.connect_tcp(remote_host, remote_port, local_address) + except OSError as exc: + oserrors.append(exc) + return + else: + if connected_stream is None: + connected_stream = stream + tg.cancel_scope.cancel() + else: + await stream.aclose() + finally: + event.set() + + asynclib = get_async_backend() + local_address: IPSockAddrType | None = None + family = socket.AF_UNSPEC + if local_host: + gai_res = await getaddrinfo(str(local_host), None) + family, *_, local_address = gai_res[0] + + target_host = str(remote_host) + try: + addr_obj = ip_address(remote_host) + except ValueError: + addr_obj = None + + if addr_obj is not None: + if isinstance(addr_obj, IPv6Address): + target_addrs = [(socket.AF_INET6, addr_obj.compressed)] + else: + target_addrs = [(socket.AF_INET, addr_obj.compressed)] + else: + # getaddrinfo() will raise an exception if name resolution fails + gai_res = await getaddrinfo( + target_host, remote_port, family=family, type=socket.SOCK_STREAM + ) + + # Organize the list so that the first address is an IPv6 address (if available) + # and the second one is an IPv4 addresses. The rest can be in whatever order. + v6_found = v4_found = False + target_addrs = [] + for af, *_, sa in gai_res: + if af == socket.AF_INET6 and not v6_found: + v6_found = True + target_addrs.insert(0, (af, sa[0])) + elif af == socket.AF_INET and not v4_found and v6_found: + v4_found = True + target_addrs.insert(1, (af, sa[0])) + else: + target_addrs.append((af, sa[0])) + + oserrors: list[OSError] = [] + try: + async with create_task_group() as tg: + for _af, addr in target_addrs: + event = Event() + tg.start_soon(try_connect, addr, event) + with move_on_after(happy_eyeballs_delay): + await event.wait() + + if connected_stream is None: + cause = ( + oserrors[0] + if len(oserrors) == 1 + else ExceptionGroup("multiple connection attempts failed", oserrors) + ) + raise OSError("All connection attempts failed") from cause + finally: + oserrors.clear() + + if tls or tls_hostname or ssl_context: + try: + return await TLSStream.wrap( + connected_stream, + server_side=False, + hostname=tls_hostname or str(remote_host), + ssl_context=ssl_context, + standard_compatible=tls_standard_compatible, + ) + except BaseException: + await aclose_forcefully(connected_stream) + raise + + return connected_stream + + +async def connect_unix(path: str | bytes | PathLike[Any]) -> UNIXSocketStream: + """ + Connect to the given UNIX socket. + + Not available on Windows. + + :param path: path to the socket + :return: a socket stream object + :raises ConnectionFailed: if the connection fails + + """ + path = os.fspath(path) + return await get_async_backend().connect_unix(path) + + +async def create_tcp_listener( + *, + local_host: IPAddressType | None = None, + local_port: int = 0, + family: AnyIPAddressFamily = socket.AddressFamily.AF_UNSPEC, + backlog: int = 65536, + reuse_port: bool = False, +) -> MultiListener[SocketStream]: + """ + Create a TCP socket listener. + + :param local_port: port number to listen on + :param local_host: IP address of the interface to listen on. If omitted, listen on + all IPv4 and IPv6 interfaces. To listen on all interfaces on a specific address + family, use ``0.0.0.0`` for IPv4 or ``::`` for IPv6. + :param family: address family (used if ``local_host`` was omitted) + :param backlog: maximum number of queued incoming connections (up to a maximum of + 2**16, or 65536) + :param reuse_port: ``True`` to allow multiple sockets to bind to the same + address/port (not supported on Windows) + :return: a multi-listener object containing one or more socket listeners + :raises OSError: if there's an error creating a socket, or binding to one or more + interfaces failed + + """ + asynclib = get_async_backend() + backlog = min(backlog, 65536) + local_host = str(local_host) if local_host is not None else None + + def setup_raw_socket( + fam: AddressFamily, + bind_addr: tuple[str, int] | tuple[str, int, int, int], + *, + v6only: bool = True, + ) -> socket.socket: + sock = socket.socket(fam) + try: + sock.setblocking(False) + + if fam == AddressFamily.AF_INET6: + sock.setsockopt(IPPROTO_IPV6, socket.IPV6_V6ONLY, v6only) + + # For Windows, enable exclusive address use. For others, enable address + # reuse. + if sys.platform == "win32": + sock.setsockopt(socket.SOL_SOCKET, socket.SO_EXCLUSIVEADDRUSE, 1) + else: + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + + if reuse_port: + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) + + # Workaround for #554 + if fam == socket.AF_INET6 and "%" in bind_addr[0]: + addr, scope_id = bind_addr[0].split("%", 1) + bind_addr = (addr, bind_addr[1], 0, int(scope_id)) + + sock.bind(bind_addr) + sock.listen(backlog) + except BaseException: + sock.close() + raise + + return sock + + # We passing type=0 on non-Windows platforms as a workaround for a uvloop bug + # where we don't get the correct scope ID for IPv6 link-local addresses when passing + # type=socket.SOCK_STREAM to getaddrinfo(): + # https://github.com/MagicStack/uvloop/issues/539 + gai_res = await getaddrinfo( + local_host, + local_port, + family=family, + type=socket.SOCK_STREAM if sys.platform == "win32" else 0, + flags=socket.AI_PASSIVE | socket.AI_ADDRCONFIG, + ) + + # The set comprehension is here to work around a glibc bug: + # https://sourceware.org/bugzilla/show_bug.cgi?id=14969 + sockaddrs = sorted({res for res in gai_res if res[1] == SocketKind.SOCK_STREAM}) + + # Special case for dual-stack binding on the "any" interface + if ( + local_host is None + and family == AddressFamily.AF_UNSPEC + and socket.has_dualstack_ipv6() + and any(fam == AddressFamily.AF_INET6 for fam, *_ in gai_res) + ): + raw_socket = setup_raw_socket( + AddressFamily.AF_INET6, ("::", local_port), v6only=False + ) + listener = asynclib.create_tcp_listener(raw_socket) + return MultiListener([listener]) + + errors: list[OSError] = [] + try: + for _ in range(len(sockaddrs)): + listeners: list[SocketListener] = [] + bound_ephemeral_port = local_port + try: + for fam, *_, sockaddr in sockaddrs: + sockaddr = sockaddr[0], bound_ephemeral_port, *sockaddr[2:] + raw_socket = setup_raw_socket(fam, sockaddr) + + # Store the assigned port if an ephemeral port was requested, so + # we'll bind to the same port on all interfaces + if local_port == 0 and len(gai_res) > 1: + bound_ephemeral_port = raw_socket.getsockname()[1] + + listeners.append(asynclib.create_tcp_listener(raw_socket)) + except BaseException as exc: + for listener in listeners: + await listener.aclose() + + # If an ephemeral port was requested but binding the assigned port + # failed for another interface, rotate the address list and try again + if ( + isinstance(exc, OSError) + and exc.errno == errno.EADDRINUSE + and local_port == 0 + and bound_ephemeral_port + ): + errors.append(exc) + sockaddrs.append(sockaddrs.pop(0)) + continue + + raise + + return MultiListener(listeners) + + raise OSError( + f"Could not create {len(sockaddrs)} listeners with a consistent port" + ) from ExceptionGroup("Several bind attempts failed", errors) + finally: + del errors # Prevent reference cycles + + +async def create_unix_listener( + path: str | bytes | PathLike[Any], + *, + mode: int | None = None, + backlog: int = 65536, +) -> SocketListener: + """ + Create a UNIX socket listener. + + Not available on Windows. + + :param path: path of the socket + :param mode: permissions to set on the socket + :param backlog: maximum number of queued incoming connections (up to a maximum of + 2**16, or 65536) + :return: a listener object + + .. versionchanged:: 3.0 + If a socket already exists on the file system in the given path, it will be + removed first. + + """ + backlog = min(backlog, 65536) + raw_socket = await setup_unix_local_socket(path, mode, socket.SOCK_STREAM) + try: + raw_socket.listen(backlog) + return get_async_backend().create_unix_listener(raw_socket) + except BaseException: + raw_socket.close() + raise + + +async def create_udp_socket( + family: AnyIPAddressFamily = AddressFamily.AF_UNSPEC, + *, + local_host: IPAddressType | None = None, + local_port: int = 0, + reuse_port: bool = False, +) -> UDPSocket: + """ + Create a UDP socket. + + If ``port`` has been given, the socket will be bound to this port on the local + machine, making this socket suitable for providing UDP based services. + + :param family: address family (``AF_INET`` or ``AF_INET6``) – automatically + determined from ``local_host`` if omitted + :param local_host: IP address or host name of the local interface to bind to + :param local_port: local port to bind to + :param reuse_port: ``True`` to allow multiple sockets to bind to the same + address/port (not supported on Windows) + :return: a UDP socket + + """ + if family is AddressFamily.AF_UNSPEC and not local_host: + raise ValueError('Either "family" or "local_host" must be given') + + if local_host: + gai_res = await getaddrinfo( + str(local_host), + local_port, + family=family, + type=socket.SOCK_DGRAM, + flags=socket.AI_PASSIVE | socket.AI_ADDRCONFIG, + ) + family = cast(AnyIPAddressFamily, gai_res[0][0]) + local_address = gai_res[0][-1] + elif family is AddressFamily.AF_INET6: + local_address = ("::", 0) + else: + local_address = ("0.0.0.0", 0) + + sock = await get_async_backend().create_udp_socket( + family, local_address, None, reuse_port + ) + return cast(UDPSocket, sock) + + +async def create_connected_udp_socket( + remote_host: IPAddressType, + remote_port: int, + *, + family: AnyIPAddressFamily = AddressFamily.AF_UNSPEC, + local_host: IPAddressType | None = None, + local_port: int = 0, + reuse_port: bool = False, +) -> ConnectedUDPSocket: + """ + Create a connected UDP socket. + + Connected UDP sockets can only communicate with the specified remote host/port, an + any packets sent from other sources are dropped. + + :param remote_host: remote host to set as the default target + :param remote_port: port on the remote host to set as the default target + :param family: address family (``AF_INET`` or ``AF_INET6``) – automatically + determined from ``local_host`` or ``remote_host`` if omitted + :param local_host: IP address or host name of the local interface to bind to + :param local_port: local port to bind to + :param reuse_port: ``True`` to allow multiple sockets to bind to the same + address/port (not supported on Windows) + :return: a connected UDP socket + + """ + local_address = None + if local_host: + gai_res = await getaddrinfo( + str(local_host), + local_port, + family=family, + type=socket.SOCK_DGRAM, + flags=socket.AI_PASSIVE | socket.AI_ADDRCONFIG, + ) + family = cast(AnyIPAddressFamily, gai_res[0][0]) + local_address = gai_res[0][-1] + + gai_res = await getaddrinfo( + str(remote_host), remote_port, family=family, type=socket.SOCK_DGRAM + ) + family = cast(AnyIPAddressFamily, gai_res[0][0]) + remote_address = gai_res[0][-1] + + sock = await get_async_backend().create_udp_socket( + family, local_address, remote_address, reuse_port + ) + return cast(ConnectedUDPSocket, sock) + + +async def create_unix_datagram_socket( + *, + local_path: None | str | bytes | PathLike[Any] = None, + local_mode: int | None = None, +) -> UNIXDatagramSocket: + """ + Create a UNIX datagram socket. + + Not available on Windows. + + If ``local_path`` has been given, the socket will be bound to this path, making this + socket suitable for receiving datagrams from other processes. Other processes can + send datagrams to this socket only if ``local_path`` is set. + + If a socket already exists on the file system in the ``local_path``, it will be + removed first. + + :param local_path: the path on which to bind to + :param local_mode: permissions to set on the local socket + :return: a UNIX datagram socket + + """ + raw_socket = await setup_unix_local_socket( + local_path, local_mode, socket.SOCK_DGRAM + ) + return await get_async_backend().create_unix_datagram_socket(raw_socket, None) + + +async def create_connected_unix_datagram_socket( + remote_path: str | bytes | PathLike[Any], + *, + local_path: None | str | bytes | PathLike[Any] = None, + local_mode: int | None = None, +) -> ConnectedUNIXDatagramSocket: + """ + Create a connected UNIX datagram socket. + + Connected datagram sockets can only communicate with the specified remote path. + + If ``local_path`` has been given, the socket will be bound to this path, making + this socket suitable for receiving datagrams from other processes. Other processes + can send datagrams to this socket only if ``local_path`` is set. + + If a socket already exists on the file system in the ``local_path``, it will be + removed first. + + :param remote_path: the path to set as the default target + :param local_path: the path on which to bind to + :param local_mode: permissions to set on the local socket + :return: a connected UNIX datagram socket + + """ + remote_path = os.fspath(remote_path) + raw_socket = await setup_unix_local_socket( + local_path, local_mode, socket.SOCK_DGRAM + ) + return await get_async_backend().create_unix_datagram_socket( + raw_socket, remote_path + ) + + +async def getaddrinfo( + host: bytes | str | None, + port: str | int | None, + *, + family: int | AddressFamily = 0, + type: int | SocketKind = 0, + proto: int = 0, + flags: int = 0, +) -> list[tuple[AddressFamily, SocketKind, int, str, tuple[str, int]]]: + """ + Look up a numeric IP address given a host name. + + Internationalized domain names are translated according to the (non-transitional) + IDNA 2008 standard. + + .. note:: 4-tuple IPv6 socket addresses are automatically converted to 2-tuples of + (host, port), unlike what :func:`socket.getaddrinfo` does. + + :param host: host name + :param port: port number + :param family: socket family (`'AF_INET``, ...) + :param type: socket type (``SOCK_STREAM``, ...) + :param proto: protocol number + :param flags: flags to pass to upstream ``getaddrinfo()`` + :return: list of tuples containing (family, type, proto, canonname, sockaddr) + + .. seealso:: :func:`socket.getaddrinfo` + + """ + # Handle unicode hostnames + if isinstance(host, str): + try: + encoded_host: bytes | None = host.encode("ascii") + except UnicodeEncodeError: + import idna + + encoded_host = idna.encode(host, uts46=True) + else: + encoded_host = host + + gai_res = await get_async_backend().getaddrinfo( + encoded_host, port, family=family, type=type, proto=proto, flags=flags + ) + return [ + (family, type, proto, canonname, convert_ipv6_sockaddr(sockaddr)) + for family, type, proto, canonname, sockaddr in gai_res + # filter out IPv6 results when IPv6 is disabled + if not isinstance(sockaddr[0], int) + ] + + +def getnameinfo(sockaddr: IPSockAddrType, flags: int = 0) -> Awaitable[tuple[str, str]]: + """ + Look up the host name of an IP address. + + :param sockaddr: socket address (e.g. (ipaddress, port) for IPv4) + :param flags: flags to pass to upstream ``getnameinfo()`` + :return: a tuple of (host name, service name) + :raises NoEventLoopError: if no supported asynchronous event loop is running in the + current thread + + .. seealso:: :func:`socket.getnameinfo` + + """ + return get_async_backend().getnameinfo(sockaddr, flags) + + +@deprecated("This function is deprecated; use `wait_readable` instead") +def wait_socket_readable(sock: socket.socket) -> Awaitable[None]: + """ + .. deprecated:: 4.7.0 + Use :func:`wait_readable` instead. + + Wait until the given socket has data to be read. + + .. warning:: Only use this on raw sockets that have not been wrapped by any higher + level constructs like socket streams! + + :param sock: a socket object + :raises ~anyio.ClosedResourceError: if the socket was closed while waiting for the + socket to become readable + :raises ~anyio.BusyResourceError: if another task is already waiting for the socket + to become readable + :raises NoEventLoopError: if no supported asynchronous event loop is running in the + current thread + + """ + return get_async_backend().wait_readable(sock.fileno()) + + +@deprecated("This function is deprecated; use `wait_writable` instead") +def wait_socket_writable(sock: socket.socket) -> Awaitable[None]: + """ + .. deprecated:: 4.7.0 + Use :func:`wait_writable` instead. + + Wait until the given socket can be written to. + + This does **NOT** work on Windows when using the asyncio backend with a proactor + event loop (default on py3.8+). + + .. warning:: Only use this on raw sockets that have not been wrapped by any higher + level constructs like socket streams! + + :param sock: a socket object + :raises ~anyio.ClosedResourceError: if the socket was closed while waiting for the + socket to become writable + :raises ~anyio.BusyResourceError: if another task is already waiting for the socket + to become writable + :raises NoEventLoopError: if no supported asynchronous event loop is running in the + current thread + + """ + return get_async_backend().wait_writable(sock.fileno()) + + +def wait_readable(obj: FileDescriptorLike) -> Awaitable[None]: + """ + Wait until the given object has data to be read. + + On Unix systems, ``obj`` must either be an integer file descriptor, or else an + object with a ``.fileno()`` method which returns an integer file descriptor. Any + kind of file descriptor can be passed, though the exact semantics will depend on + your kernel. For example, this probably won't do anything useful for on-disk files. + + On Windows systems, ``obj`` must either be an integer ``SOCKET`` handle, or else an + object with a ``.fileno()`` method which returns an integer ``SOCKET`` handle. File + descriptors aren't supported, and neither are handles that refer to anything besides + a ``SOCKET``. + + On backends where this functionality is not natively provided (asyncio + ``ProactorEventLoop`` on Windows), it is provided using a separate selector thread + which is set to shut down when the interpreter shuts down. + + .. warning:: Don't use this on raw sockets that have been wrapped by any higher + level constructs like socket streams! + + :param obj: an object with a ``.fileno()`` method or an integer handle + :raises ~anyio.ClosedResourceError: if the object was closed while waiting for the + object to become readable + :raises ~anyio.BusyResourceError: if another task is already waiting for the object + to become readable + :raises NoEventLoopError: if no supported asynchronous event loop is running in the + current thread + + """ + return get_async_backend().wait_readable(obj) + + +def wait_writable(obj: FileDescriptorLike) -> Awaitable[None]: + """ + Wait until the given object can be written to. + + :param obj: an object with a ``.fileno()`` method or an integer handle + :raises ~anyio.ClosedResourceError: if the object was closed while waiting for the + object to become writable + :raises ~anyio.BusyResourceError: if another task is already waiting for the object + to become writable + :raises NoEventLoopError: if no supported asynchronous event loop is running in the + current thread + + .. seealso:: See the documentation of :func:`wait_readable` for the definition of + ``obj`` and notes on backend compatibility. + + .. warning:: Don't use this on raw sockets that have been wrapped by any higher + level constructs like socket streams! + + """ + return get_async_backend().wait_writable(obj) + + +def notify_closing(obj: FileDescriptorLike) -> None: + """ + Call this before closing a file descriptor (on Unix) or socket (on + Windows). This will cause any `wait_readable` or `wait_writable` + calls on the given object to immediately wake up and raise + `~anyio.ClosedResourceError`. + + This doesn't actually close the object – you still have to do that + yourself afterwards. Also, you want to be careful to make sure no + new tasks start waiting on the object in between when you call this + and when it's actually closed. So to close something properly, you + usually want to do these steps in order: + + 1. Explicitly mark the object as closed, so that any new attempts + to use it will abort before they start. + 2. Call `notify_closing` to wake up any already-existing users. + 3. Actually close the object. + + It's also possible to do them in a different order if that's more + convenient, *but only if* you make sure not to have any checkpoints in + between the steps. This way they all happen in a single atomic + step, so other tasks won't be able to tell what order they happened + in anyway. + + :param obj: an object with a ``.fileno()`` method or an integer handle + :raises NoEventLoopError: if no supported asynchronous event loop is running in the + current thread + + """ + get_async_backend().notify_closing(obj) + + +# +# Private API +# + + +def convert_ipv6_sockaddr( + sockaddr: tuple[str, int, int, int] | tuple[str, int], +) -> tuple[str, int]: + """ + Convert a 4-tuple IPv6 socket address to a 2-tuple (address, port) format. + + If the scope ID is nonzero, it is added to the address, separated with ``%``. + Otherwise the flow id and scope id are simply cut off from the tuple. + Any other kinds of socket addresses are returned as-is. + + :param sockaddr: the result of :meth:`~socket.socket.getsockname` + :return: the converted socket address + + """ + # This is more complicated than it should be because of MyPy + if isinstance(sockaddr, tuple) and len(sockaddr) == 4: + host, port, flowinfo, scope_id = sockaddr + if scope_id: + # PyPy (as of v7.3.11) leaves the interface name in the result, so + # we discard it and only get the scope ID from the end + # (https://foss.heptapod.net/pypy/pypy/-/issues/3938) + host = host.split("%")[0] + + # Add scope_id to the address + return f"{host}%{scope_id}", port + else: + return host, port + else: + return sockaddr + + +async def setup_unix_local_socket( + path: None | str | bytes | PathLike[Any], + mode: int | None, + socktype: int, +) -> socket.socket: + """ + Create a UNIX local socket object, deleting the socket at the given path if it + exists. + + Not available on Windows. + + :param path: path of the socket + :param mode: permissions to set on the socket + :param socktype: socket.SOCK_STREAM or socket.SOCK_DGRAM + + """ + path_str: str | None + if path is not None: + path_str = os.fsdecode(path) + + # Linux abstract namespace sockets aren't backed by a concrete file so skip stat call + if not path_str.startswith("\0"): + # Copied from pathlib... + try: + stat_result = os.stat(path) + except OSError as e: + if e.errno not in ( + errno.ENOENT, + errno.ENOTDIR, + errno.EBADF, + errno.ELOOP, + ): + raise + else: + if stat.S_ISSOCK(stat_result.st_mode): + os.unlink(path) + else: + path_str = None + + raw_socket = socket.socket(socket.AF_UNIX, socktype) + raw_socket.setblocking(False) + + if path_str is not None: + try: + await to_thread.run_sync(raw_socket.bind, path_str, abandon_on_cancel=True) + if mode is not None: + await to_thread.run_sync(chmod, path_str, mode, abandon_on_cancel=True) + except BaseException: + raw_socket.close() + raise + + return raw_socket + + +@dataclass +class TCPConnectable(ByteStreamConnectable): + """ + Connects to a TCP server at the given host and port. + + :param host: host name or IP address of the server + :param port: TCP port number of the server + """ + + host: str | IPv4Address | IPv6Address + port: int + + def __post_init__(self) -> None: + if self.port < 1 or self.port > 65535: + raise ValueError("TCP port number out of range") + + @override + async def connect(self) -> SocketStream: + try: + return await connect_tcp(self.host, self.port) + except OSError as exc: + raise ConnectionFailed( + f"error connecting to {self.host}:{self.port}: {exc}" + ) from exc + + +@dataclass +class UNIXConnectable(ByteStreamConnectable): + """ + Connects to a UNIX domain socket at the given path. + + :param path: the file system path of the socket + """ + + path: str | bytes | PathLike[str] | PathLike[bytes] + + @override + async def connect(self) -> UNIXSocketStream: + try: + return await connect_unix(self.path) + except OSError as exc: + raise ConnectionFailed(f"error connecting to {self.path!r}: {exc}") from exc + + +def as_connectable( + remote: ByteStreamConnectable + | tuple[str | IPv4Address | IPv6Address, int] + | str + | bytes + | PathLike[str], + /, + *, + tls: bool = False, + ssl_context: ssl.SSLContext | None = None, + tls_hostname: str | None = None, + tls_standard_compatible: bool = True, +) -> ByteStreamConnectable: + """ + Return a byte stream connectable from the given object. + + If a bytestream connectable is given, it is returned unchanged. + If a tuple of (host, port) is given, a TCP connectable is returned. + If a string or bytes path is given, a UNIX connectable is returned. + + If ``tls=True``, the connectable will be wrapped in a + :class:`~.streams.tls.TLSConnectable`. + + :param remote: a connectable, a tuple of (host, port) or a path to a UNIX socket + :param tls: if ``True``, wrap the plaintext connectable in a + :class:`~.streams.tls.TLSConnectable`, using the provided TLS settings) + :param ssl_context: if ``tls=True``, the SSLContext object to use (if not provided, + a secure default will be created) + :param tls_hostname: if ``tls=True``, host name of the server to use for checking + the server certificate (defaults to the host portion of the address for TCP + connectables) + :param tls_standard_compatible: if ``False`` and ``tls=True``, makes the TLS stream + skip the closing handshake when closing the connection, so it won't raise an + exception if the server does the same + + """ + connectable: TCPConnectable | UNIXConnectable | TLSConnectable + if isinstance(remote, ByteStreamConnectable): + return remote + elif isinstance(remote, tuple) and len(remote) == 2: + connectable = TCPConnectable(*remote) + elif isinstance(remote, (str, bytes, PathLike)): + connectable = UNIXConnectable(remote) + else: + raise TypeError(f"cannot convert {remote!r} to a connectable") + + if tls: + if not tls_hostname and isinstance(connectable, TCPConnectable): + tls_hostname = str(connectable.host) + + connectable = TLSConnectable( + connectable, + ssl_context=ssl_context, + hostname=tls_hostname, + standard_compatible=tls_standard_compatible, + ) + + return connectable diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_streams.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_streams.py new file mode 100644 index 0000000..2b9c7df --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_streams.py @@ -0,0 +1,52 @@ +from __future__ import annotations + +import math +from typing import TypeVar +from warnings import warn + +from ..streams.memory import ( + MemoryObjectReceiveStream, + MemoryObjectSendStream, + _MemoryObjectStreamState, +) + +T_Item = TypeVar("T_Item") + + +class create_memory_object_stream( + tuple[MemoryObjectSendStream[T_Item], MemoryObjectReceiveStream[T_Item]], +): + """ + Create a memory object stream. + + The stream's item type can be annotated like + :func:`create_memory_object_stream[T_Item]`. + + :param max_buffer_size: number of items held in the buffer until ``send()`` starts + blocking + :param item_type: old way of marking the streams with the right generic type for + static typing (does nothing on AnyIO 4) + + .. deprecated:: 4.0 + Use ``create_memory_object_stream[YourItemType](...)`` instead. + :return: a tuple of (send stream, receive stream) + + """ + + def __new__( # type: ignore[misc] + cls, max_buffer_size: float = 0, item_type: object = None + ) -> tuple[MemoryObjectSendStream[T_Item], MemoryObjectReceiveStream[T_Item]]: + if max_buffer_size != math.inf and not isinstance(max_buffer_size, int): + raise ValueError("max_buffer_size must be either an integer or math.inf") + if max_buffer_size < 0: + raise ValueError("max_buffer_size cannot be negative") + if item_type is not None: + warn( + "The item_type argument has been deprecated in AnyIO 4.0. " + "Use create_memory_object_stream[YourItemType](...) instead.", + DeprecationWarning, + stacklevel=2, + ) + + state = _MemoryObjectStreamState[T_Item](max_buffer_size) + return (MemoryObjectSendStream(state), MemoryObjectReceiveStream(state)) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_subprocesses.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_subprocesses.py new file mode 100644 index 0000000..36d9b30 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_subprocesses.py @@ -0,0 +1,202 @@ +from __future__ import annotations + +import sys +from collections.abc import AsyncIterable, Iterable, Mapping, Sequence +from io import BytesIO +from os import PathLike +from subprocess import PIPE, CalledProcessError, CompletedProcess +from typing import IO, Any, Union, cast + +from ..abc import Process +from ._eventloop import get_async_backend +from ._tasks import create_task_group + +if sys.version_info >= (3, 10): + from typing import TypeAlias +else: + from typing_extensions import TypeAlias + +StrOrBytesPath: TypeAlias = Union[str, bytes, "PathLike[str]", "PathLike[bytes]"] + + +async def run_process( + command: StrOrBytesPath | Sequence[StrOrBytesPath], + *, + input: bytes | None = None, + stdin: int | IO[Any] | None = None, + stdout: int | IO[Any] | None = PIPE, + stderr: int | IO[Any] | None = PIPE, + check: bool = True, + cwd: StrOrBytesPath | None = None, + env: Mapping[str, str] | None = None, + startupinfo: Any = None, + creationflags: int = 0, + start_new_session: bool = False, + pass_fds: Sequence[int] = (), + user: str | int | None = None, + group: str | int | None = None, + extra_groups: Iterable[str | int] | None = None, + umask: int = -1, +) -> CompletedProcess[bytes]: + """ + Run an external command in a subprocess and wait until it completes. + + .. seealso:: :func:`subprocess.run` + + :param command: either a string to pass to the shell, or an iterable of strings + containing the executable name or path and its arguments + :param input: bytes passed to the standard input of the subprocess + :param stdin: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, + a file-like object, or `None`; ``input`` overrides this + :param stdout: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, + a file-like object, or `None` + :param stderr: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, + :data:`subprocess.STDOUT`, a file-like object, or `None` + :param check: if ``True``, raise :exc:`~subprocess.CalledProcessError` if the + process terminates with a return code other than 0 + :param cwd: If not ``None``, change the working directory to this before running the + command + :param env: if not ``None``, this mapping replaces the inherited environment + variables from the parent process + :param startupinfo: an instance of :class:`subprocess.STARTUPINFO` that can be used + to specify process startup parameters (Windows only) + :param creationflags: flags that can be used to control the creation of the + subprocess (see :class:`subprocess.Popen` for the specifics) + :param start_new_session: if ``true`` the setsid() system call will be made in the + child process prior to the execution of the subprocess. (POSIX only) + :param pass_fds: sequence of file descriptors to keep open between the parent and + child processes. (POSIX only) + :param user: effective user to run the process as (Python >= 3.9, POSIX only) + :param group: effective group to run the process as (Python >= 3.9, POSIX only) + :param extra_groups: supplementary groups to set in the subprocess (Python >= 3.9, + POSIX only) + :param umask: if not negative, this umask is applied in the child process before + running the given command (Python >= 3.9, POSIX only) + :return: an object representing the completed process + :raises ~subprocess.CalledProcessError: if ``check`` is ``True`` and the process + exits with a nonzero return code + + """ + + async def drain_stream(stream: AsyncIterable[bytes], index: int) -> None: + buffer = BytesIO() + async for chunk in stream: + buffer.write(chunk) + + stream_contents[index] = buffer.getvalue() + + if stdin is not None and input is not None: + raise ValueError("only one of stdin and input is allowed") + + async with await open_process( + command, + stdin=PIPE if input else stdin, + stdout=stdout, + stderr=stderr, + cwd=cwd, + env=env, + startupinfo=startupinfo, + creationflags=creationflags, + start_new_session=start_new_session, + pass_fds=pass_fds, + user=user, + group=group, + extra_groups=extra_groups, + umask=umask, + ) as process: + stream_contents: list[bytes | None] = [None, None] + async with create_task_group() as tg: + if process.stdout: + tg.start_soon(drain_stream, process.stdout, 0) + + if process.stderr: + tg.start_soon(drain_stream, process.stderr, 1) + + if process.stdin and input: + await process.stdin.send(input) + await process.stdin.aclose() + + await process.wait() + + output, errors = stream_contents + if check and process.returncode != 0: + raise CalledProcessError(cast(int, process.returncode), command, output, errors) + + return CompletedProcess(command, cast(int, process.returncode), output, errors) + + +async def open_process( + command: StrOrBytesPath | Sequence[StrOrBytesPath], + *, + stdin: int | IO[Any] | None = PIPE, + stdout: int | IO[Any] | None = PIPE, + stderr: int | IO[Any] | None = PIPE, + cwd: StrOrBytesPath | None = None, + env: Mapping[str, str] | None = None, + startupinfo: Any = None, + creationflags: int = 0, + start_new_session: bool = False, + pass_fds: Sequence[int] = (), + user: str | int | None = None, + group: str | int | None = None, + extra_groups: Iterable[str | int] | None = None, + umask: int = -1, +) -> Process: + """ + Start an external command in a subprocess. + + .. seealso:: :class:`subprocess.Popen` + + :param command: either a string to pass to the shell, or an iterable of strings + containing the executable name or path and its arguments + :param stdin: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, a + file-like object, or ``None`` + :param stdout: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, + a file-like object, or ``None`` + :param stderr: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, + :data:`subprocess.STDOUT`, a file-like object, or ``None`` + :param cwd: If not ``None``, the working directory is changed before executing + :param env: If env is not ``None``, it must be a mapping that defines the + environment variables for the new process + :param creationflags: flags that can be used to control the creation of the + subprocess (see :class:`subprocess.Popen` for the specifics) + :param startupinfo: an instance of :class:`subprocess.STARTUPINFO` that can be used + to specify process startup parameters (Windows only) + :param start_new_session: if ``true`` the setsid() system call will be made in the + child process prior to the execution of the subprocess. (POSIX only) + :param pass_fds: sequence of file descriptors to keep open between the parent and + child processes. (POSIX only) + :param user: effective user to run the process as (POSIX only) + :param group: effective group to run the process as (POSIX only) + :param extra_groups: supplementary groups to set in the subprocess (POSIX only) + :param umask: if not negative, this umask is applied in the child process before + running the given command (POSIX only) + :return: an asynchronous process object + + """ + kwargs: dict[str, Any] = {} + if user is not None: + kwargs["user"] = user + + if group is not None: + kwargs["group"] = group + + if extra_groups is not None: + kwargs["extra_groups"] = group + + if umask >= 0: + kwargs["umask"] = umask + + return await get_async_backend().open_process( + command, + stdin=stdin, + stdout=stdout, + stderr=stderr, + cwd=cwd, + env=env, + startupinfo=startupinfo, + creationflags=creationflags, + start_new_session=start_new_session, + pass_fds=pass_fds, + **kwargs, + ) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_synchronization.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_synchronization.py new file mode 100644 index 0000000..c0ef27a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_synchronization.py @@ -0,0 +1,753 @@ +from __future__ import annotations + +import math +from collections import deque +from collections.abc import Callable +from dataclasses import dataclass +from types import TracebackType +from typing import TypeVar + +from ..lowlevel import checkpoint_if_cancelled +from ._eventloop import get_async_backend +from ._exceptions import BusyResourceError, NoEventLoopError +from ._tasks import CancelScope +from ._testing import TaskInfo, get_current_task + +T = TypeVar("T") + + +@dataclass(frozen=True) +class EventStatistics: + """ + :ivar int tasks_waiting: number of tasks waiting on :meth:`~.Event.wait` + """ + + tasks_waiting: int + + +@dataclass(frozen=True) +class CapacityLimiterStatistics: + """ + :ivar int borrowed_tokens: number of tokens currently borrowed by tasks + :ivar float total_tokens: total number of available tokens + :ivar tuple borrowers: tasks or other objects currently holding tokens borrowed from + this limiter + :ivar int tasks_waiting: number of tasks waiting on + :meth:`~.CapacityLimiter.acquire` or + :meth:`~.CapacityLimiter.acquire_on_behalf_of` + """ + + borrowed_tokens: int + total_tokens: float + borrowers: tuple[object, ...] + tasks_waiting: int + + +@dataclass(frozen=True) +class LockStatistics: + """ + :ivar bool locked: flag indicating if this lock is locked or not + :ivar ~anyio.TaskInfo owner: task currently holding the lock (or ``None`` if the + lock is not held by any task) + :ivar int tasks_waiting: number of tasks waiting on :meth:`~.Lock.acquire` + """ + + locked: bool + owner: TaskInfo | None + tasks_waiting: int + + +@dataclass(frozen=True) +class ConditionStatistics: + """ + :ivar int tasks_waiting: number of tasks blocked on :meth:`~.Condition.wait` + :ivar ~anyio.LockStatistics lock_statistics: statistics of the underlying + :class:`~.Lock` + """ + + tasks_waiting: int + lock_statistics: LockStatistics + + +@dataclass(frozen=True) +class SemaphoreStatistics: + """ + :ivar int tasks_waiting: number of tasks waiting on :meth:`~.Semaphore.acquire` + + """ + + tasks_waiting: int + + +class Event: + def __new__(cls) -> Event: + try: + return get_async_backend().create_event() + except NoEventLoopError: + return EventAdapter() + + def set(self) -> None: + """Set the flag, notifying all listeners.""" + raise NotImplementedError + + def is_set(self) -> bool: + """Return ``True`` if the flag is set, ``False`` if not.""" + raise NotImplementedError + + async def wait(self) -> None: + """ + Wait until the flag has been set. + + If the flag has already been set when this method is called, it returns + immediately. + + """ + raise NotImplementedError + + def statistics(self) -> EventStatistics: + """Return statistics about the current state of this event.""" + raise NotImplementedError + + +class EventAdapter(Event): + _internal_event: Event | None = None + _is_set: bool = False + + def __new__(cls) -> EventAdapter: + return object.__new__(cls) + + @property + def _event(self) -> Event: + if self._internal_event is None: + self._internal_event = get_async_backend().create_event() + if self._is_set: + self._internal_event.set() + + return self._internal_event + + def set(self) -> None: + if self._internal_event is None: + self._is_set = True + else: + self._event.set() + + def is_set(self) -> bool: + if self._internal_event is None: + return self._is_set + + return self._internal_event.is_set() + + async def wait(self) -> None: + await self._event.wait() + + def statistics(self) -> EventStatistics: + if self._internal_event is None: + return EventStatistics(tasks_waiting=0) + + return self._internal_event.statistics() + + +class Lock: + def __new__(cls, *, fast_acquire: bool = False) -> Lock: + try: + return get_async_backend().create_lock(fast_acquire=fast_acquire) + except NoEventLoopError: + return LockAdapter(fast_acquire=fast_acquire) + + async def __aenter__(self) -> None: + await self.acquire() + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + self.release() + + async def acquire(self) -> None: + """Acquire the lock.""" + raise NotImplementedError + + def acquire_nowait(self) -> None: + """ + Acquire the lock, without blocking. + + :raises ~anyio.WouldBlock: if the operation would block + + """ + raise NotImplementedError + + def release(self) -> None: + """Release the lock.""" + raise NotImplementedError + + def locked(self) -> bool: + """Return True if the lock is currently held.""" + raise NotImplementedError + + def statistics(self) -> LockStatistics: + """ + Return statistics about the current state of this lock. + + .. versionadded:: 3.0 + """ + raise NotImplementedError + + +class LockAdapter(Lock): + _internal_lock: Lock | None = None + + def __new__(cls, *, fast_acquire: bool = False) -> LockAdapter: + return object.__new__(cls) + + def __init__(self, *, fast_acquire: bool = False): + self._fast_acquire = fast_acquire + + @property + def _lock(self) -> Lock: + if self._internal_lock is None: + self._internal_lock = get_async_backend().create_lock( + fast_acquire=self._fast_acquire + ) + + return self._internal_lock + + async def __aenter__(self) -> None: + await self._lock.acquire() + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + if self._internal_lock is not None: + self._internal_lock.release() + + async def acquire(self) -> None: + """Acquire the lock.""" + await self._lock.acquire() + + def acquire_nowait(self) -> None: + """ + Acquire the lock, without blocking. + + :raises ~anyio.WouldBlock: if the operation would block + + """ + self._lock.acquire_nowait() + + def release(self) -> None: + """Release the lock.""" + self._lock.release() + + def locked(self) -> bool: + """Return True if the lock is currently held.""" + return self._lock.locked() + + def statistics(self) -> LockStatistics: + """ + Return statistics about the current state of this lock. + + .. versionadded:: 3.0 + + """ + if self._internal_lock is None: + return LockStatistics(False, None, 0) + + return self._internal_lock.statistics() + + +class Condition: + _owner_task: TaskInfo | None = None + + def __init__(self, lock: Lock | None = None): + self._lock = lock or Lock() + self._waiters: deque[Event] = deque() + + async def __aenter__(self) -> None: + await self.acquire() + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + self.release() + + def _check_acquired(self) -> None: + if self._owner_task != get_current_task(): + raise RuntimeError("The current task is not holding the underlying lock") + + async def acquire(self) -> None: + """Acquire the underlying lock.""" + await self._lock.acquire() + self._owner_task = get_current_task() + + def acquire_nowait(self) -> None: + """ + Acquire the underlying lock, without blocking. + + :raises ~anyio.WouldBlock: if the operation would block + + """ + self._lock.acquire_nowait() + self._owner_task = get_current_task() + + def release(self) -> None: + """Release the underlying lock.""" + self._lock.release() + + def locked(self) -> bool: + """Return True if the lock is set.""" + return self._lock.locked() + + def notify(self, n: int = 1) -> None: + """Notify exactly n listeners.""" + self._check_acquired() + for _ in range(n): + try: + event = self._waiters.popleft() + except IndexError: + break + + event.set() + + def notify_all(self) -> None: + """Notify all the listeners.""" + self._check_acquired() + for event in self._waiters: + event.set() + + self._waiters.clear() + + async def wait(self) -> None: + """Wait for a notification.""" + await checkpoint_if_cancelled() + self._check_acquired() + event = Event() + self._waiters.append(event) + self.release() + try: + await event.wait() + except BaseException: + if not event.is_set(): + self._waiters.remove(event) + + raise + finally: + with CancelScope(shield=True): + await self.acquire() + + async def wait_for(self, predicate: Callable[[], T]) -> T: + """ + Wait until a predicate becomes true. + + :param predicate: a callable that returns a truthy value when the condition is + met + :return: the result of the predicate + + .. versionadded:: 4.11.0 + + """ + while not (result := predicate()): + await self.wait() + + return result + + def statistics(self) -> ConditionStatistics: + """ + Return statistics about the current state of this condition. + + .. versionadded:: 3.0 + """ + return ConditionStatistics(len(self._waiters), self._lock.statistics()) + + +class Semaphore: + def __new__( + cls, + initial_value: int, + *, + max_value: int | None = None, + fast_acquire: bool = False, + ) -> Semaphore: + try: + return get_async_backend().create_semaphore( + initial_value, max_value=max_value, fast_acquire=fast_acquire + ) + except NoEventLoopError: + return SemaphoreAdapter(initial_value, max_value=max_value) + + def __init__( + self, + initial_value: int, + *, + max_value: int | None = None, + fast_acquire: bool = False, + ): + if not isinstance(initial_value, int): + raise TypeError("initial_value must be an integer") + if initial_value < 0: + raise ValueError("initial_value must be >= 0") + if max_value is not None: + if not isinstance(max_value, int): + raise TypeError("max_value must be an integer or None") + if max_value < initial_value: + raise ValueError( + "max_value must be equal to or higher than initial_value" + ) + + self._fast_acquire = fast_acquire + + async def __aenter__(self) -> Semaphore: + await self.acquire() + return self + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + self.release() + + async def acquire(self) -> None: + """Decrement the semaphore value, blocking if necessary.""" + raise NotImplementedError + + def acquire_nowait(self) -> None: + """ + Acquire the underlying lock, without blocking. + + :raises ~anyio.WouldBlock: if the operation would block + + """ + raise NotImplementedError + + def release(self) -> None: + """Increment the semaphore value.""" + raise NotImplementedError + + @property + def value(self) -> int: + """The current value of the semaphore.""" + raise NotImplementedError + + @property + def max_value(self) -> int | None: + """The maximum value of the semaphore.""" + raise NotImplementedError + + def statistics(self) -> SemaphoreStatistics: + """ + Return statistics about the current state of this semaphore. + + .. versionadded:: 3.0 + """ + raise NotImplementedError + + +class SemaphoreAdapter(Semaphore): + _internal_semaphore: Semaphore | None = None + + def __new__( + cls, + initial_value: int, + *, + max_value: int | None = None, + fast_acquire: bool = False, + ) -> SemaphoreAdapter: + return object.__new__(cls) + + def __init__( + self, + initial_value: int, + *, + max_value: int | None = None, + fast_acquire: bool = False, + ) -> None: + super().__init__(initial_value, max_value=max_value, fast_acquire=fast_acquire) + self._initial_value = initial_value + self._max_value = max_value + + @property + def _semaphore(self) -> Semaphore: + if self._internal_semaphore is None: + self._internal_semaphore = get_async_backend().create_semaphore( + self._initial_value, max_value=self._max_value + ) + + return self._internal_semaphore + + async def acquire(self) -> None: + await self._semaphore.acquire() + + def acquire_nowait(self) -> None: + self._semaphore.acquire_nowait() + + def release(self) -> None: + self._semaphore.release() + + @property + def value(self) -> int: + if self._internal_semaphore is None: + return self._initial_value + + return self._semaphore.value + + @property + def max_value(self) -> int | None: + return self._max_value + + def statistics(self) -> SemaphoreStatistics: + if self._internal_semaphore is None: + return SemaphoreStatistics(tasks_waiting=0) + + return self._semaphore.statistics() + + +class CapacityLimiter: + def __new__(cls, total_tokens: float) -> CapacityLimiter: + try: + return get_async_backend().create_capacity_limiter(total_tokens) + except NoEventLoopError: + return CapacityLimiterAdapter(total_tokens) + + async def __aenter__(self) -> None: + raise NotImplementedError + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + raise NotImplementedError + + @property + def total_tokens(self) -> float: + """ + The total number of tokens available for borrowing. + + This is a read-write property. If the total number of tokens is increased, the + proportionate number of tasks waiting on this limiter will be granted their + tokens. + + .. versionchanged:: 3.0 + The property is now writable. + .. versionchanged:: 4.12 + The value can now be set to 0. + + """ + raise NotImplementedError + + @total_tokens.setter + def total_tokens(self, value: float) -> None: + raise NotImplementedError + + @property + def borrowed_tokens(self) -> int: + """The number of tokens that have currently been borrowed.""" + raise NotImplementedError + + @property + def available_tokens(self) -> float: + """The number of tokens currently available to be borrowed""" + raise NotImplementedError + + def acquire_nowait(self) -> None: + """ + Acquire a token for the current task without waiting for one to become + available. + + :raises ~anyio.WouldBlock: if there are no tokens available for borrowing + + """ + raise NotImplementedError + + def acquire_on_behalf_of_nowait(self, borrower: object) -> None: + """ + Acquire a token without waiting for one to become available. + + :param borrower: the entity borrowing a token + :raises ~anyio.WouldBlock: if there are no tokens available for borrowing + + """ + raise NotImplementedError + + async def acquire(self) -> None: + """ + Acquire a token for the current task, waiting if necessary for one to become + available. + + """ + raise NotImplementedError + + async def acquire_on_behalf_of(self, borrower: object) -> None: + """ + Acquire a token, waiting if necessary for one to become available. + + :param borrower: the entity borrowing a token + + """ + raise NotImplementedError + + def release(self) -> None: + """ + Release the token held by the current task. + + :raises RuntimeError: if the current task has not borrowed a token from this + limiter. + + """ + raise NotImplementedError + + def release_on_behalf_of(self, borrower: object) -> None: + """ + Release the token held by the given borrower. + + :raises RuntimeError: if the borrower has not borrowed a token from this + limiter. + + """ + raise NotImplementedError + + def statistics(self) -> CapacityLimiterStatistics: + """ + Return statistics about the current state of this limiter. + + .. versionadded:: 3.0 + + """ + raise NotImplementedError + + +class CapacityLimiterAdapter(CapacityLimiter): + _internal_limiter: CapacityLimiter | None = None + + def __new__(cls, total_tokens: float) -> CapacityLimiterAdapter: + return object.__new__(cls) + + def __init__(self, total_tokens: float) -> None: + self.total_tokens = total_tokens + + @property + def _limiter(self) -> CapacityLimiter: + if self._internal_limiter is None: + self._internal_limiter = get_async_backend().create_capacity_limiter( + self._total_tokens + ) + + return self._internal_limiter + + async def __aenter__(self) -> None: + await self._limiter.__aenter__() + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + return await self._limiter.__aexit__(exc_type, exc_val, exc_tb) + + @property + def total_tokens(self) -> float: + if self._internal_limiter is None: + return self._total_tokens + + return self._internal_limiter.total_tokens + + @total_tokens.setter + def total_tokens(self, value: float) -> None: + if not isinstance(value, int) and value is not math.inf: + raise TypeError("total_tokens must be an int or math.inf") + elif value < 1: + raise ValueError("total_tokens must be >= 1") + + if self._internal_limiter is None: + self._total_tokens = value + return + + self._limiter.total_tokens = value + + @property + def borrowed_tokens(self) -> int: + if self._internal_limiter is None: + return 0 + + return self._internal_limiter.borrowed_tokens + + @property + def available_tokens(self) -> float: + if self._internal_limiter is None: + return self._total_tokens + + return self._internal_limiter.available_tokens + + def acquire_nowait(self) -> None: + self._limiter.acquire_nowait() + + def acquire_on_behalf_of_nowait(self, borrower: object) -> None: + self._limiter.acquire_on_behalf_of_nowait(borrower) + + async def acquire(self) -> None: + await self._limiter.acquire() + + async def acquire_on_behalf_of(self, borrower: object) -> None: + await self._limiter.acquire_on_behalf_of(borrower) + + def release(self) -> None: + self._limiter.release() + + def release_on_behalf_of(self, borrower: object) -> None: + self._limiter.release_on_behalf_of(borrower) + + def statistics(self) -> CapacityLimiterStatistics: + if self._internal_limiter is None: + return CapacityLimiterStatistics( + borrowed_tokens=0, + total_tokens=self.total_tokens, + borrowers=(), + tasks_waiting=0, + ) + + return self._internal_limiter.statistics() + + +class ResourceGuard: + """ + A context manager for ensuring that a resource is only used by a single task at a + time. + + Entering this context manager while the previous has not exited it yet will trigger + :exc:`BusyResourceError`. + + :param action: the action to guard against (visible in the :exc:`BusyResourceError` + when triggered, e.g. "Another task is already {action} this resource") + + .. versionadded:: 4.1 + """ + + __slots__ = "action", "_guarded" + + def __init__(self, action: str = "using"): + self.action: str = action + self._guarded = False + + def __enter__(self) -> None: + if self._guarded: + raise BusyResourceError(self.action) + + self._guarded = True + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + self._guarded = False diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_tasks.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_tasks.py new file mode 100644 index 0000000..0688bfe --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_tasks.py @@ -0,0 +1,173 @@ +from __future__ import annotations + +import math +from collections.abc import Generator +from contextlib import contextmanager +from types import TracebackType + +from ..abc._tasks import TaskGroup, TaskStatus +from ._eventloop import get_async_backend + + +class _IgnoredTaskStatus(TaskStatus[object]): + def started(self, value: object = None) -> None: + pass + + +TASK_STATUS_IGNORED = _IgnoredTaskStatus() + + +class CancelScope: + """ + Wraps a unit of work that can be made separately cancellable. + + :param deadline: The time (clock value) when this scope is cancelled automatically + :param shield: ``True`` to shield the cancel scope from external cancellation + :raises NoEventLoopError: if no supported asynchronous event loop is running in the + current thread + """ + + def __new__( + cls, *, deadline: float = math.inf, shield: bool = False + ) -> CancelScope: + return get_async_backend().create_cancel_scope(shield=shield, deadline=deadline) + + def cancel(self, reason: str | None = None) -> None: + """ + Cancel this scope immediately. + + :param reason: a message describing the reason for the cancellation + + """ + raise NotImplementedError + + @property + def deadline(self) -> float: + """ + The time (clock value) when this scope is cancelled automatically. + + Will be ``float('inf')`` if no timeout has been set. + + """ + raise NotImplementedError + + @deadline.setter + def deadline(self, value: float) -> None: + raise NotImplementedError + + @property + def cancel_called(self) -> bool: + """``True`` if :meth:`cancel` has been called.""" + raise NotImplementedError + + @property + def cancelled_caught(self) -> bool: + """ + ``True`` if this scope suppressed a cancellation exception it itself raised. + + This is typically used to check if any work was interrupted, or to see if the + scope was cancelled due to its deadline being reached. The value will, however, + only be ``True`` if the cancellation was triggered by the scope itself (and not + an outer scope). + + """ + raise NotImplementedError + + @property + def shield(self) -> bool: + """ + ``True`` if this scope is shielded from external cancellation. + + While a scope is shielded, it will not receive cancellations from outside. + + """ + raise NotImplementedError + + @shield.setter + def shield(self, value: bool) -> None: + raise NotImplementedError + + def __enter__(self) -> CancelScope: + raise NotImplementedError + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> bool: + raise NotImplementedError + + +@contextmanager +def fail_after( + delay: float | None, shield: bool = False +) -> Generator[CancelScope, None, None]: + """ + Create a context manager which raises a :class:`TimeoutError` if does not finish in + time. + + :param delay: maximum allowed time (in seconds) before raising the exception, or + ``None`` to disable the timeout + :param shield: ``True`` to shield the cancel scope from external cancellation + :return: a context manager that yields a cancel scope + :rtype: :class:`~typing.ContextManager`\\[:class:`~anyio.CancelScope`\\] + :raises NoEventLoopError: if no supported asynchronous event loop is running in the + current thread + + """ + current_time = get_async_backend().current_time + deadline = (current_time() + delay) if delay is not None else math.inf + with get_async_backend().create_cancel_scope( + deadline=deadline, shield=shield + ) as cancel_scope: + yield cancel_scope + + if cancel_scope.cancelled_caught and current_time() >= cancel_scope.deadline: + raise TimeoutError + + +def move_on_after(delay: float | None, shield: bool = False) -> CancelScope: + """ + Create a cancel scope with a deadline that expires after the given delay. + + :param delay: maximum allowed time (in seconds) before exiting the context block, or + ``None`` to disable the timeout + :param shield: ``True`` to shield the cancel scope from external cancellation + :return: a cancel scope + :raises NoEventLoopError: if no supported asynchronous event loop is running in the + current thread + + """ + deadline = ( + (get_async_backend().current_time() + delay) if delay is not None else math.inf + ) + return get_async_backend().create_cancel_scope(deadline=deadline, shield=shield) + + +def current_effective_deadline() -> float: + """ + Return the nearest deadline among all the cancel scopes effective for the current + task. + + :return: a clock value from the event loop's internal clock (or ``float('inf')`` if + there is no deadline in effect, or ``float('-inf')`` if the current scope has + been cancelled) + :rtype: float + :raises NoEventLoopError: if no supported asynchronous event loop is running in the + current thread + + """ + return get_async_backend().current_effective_deadline() + + +def create_task_group() -> TaskGroup: + """ + Create a task group. + + :return: a task group + :raises NoEventLoopError: if no supported asynchronous event loop is running in the + current thread + + """ + return get_async_backend().create_task_group() diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_tempfile.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_tempfile.py new file mode 100644 index 0000000..fbb6b14 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_tempfile.py @@ -0,0 +1,616 @@ +from __future__ import annotations + +import os +import sys +import tempfile +from collections.abc import Iterable +from io import BytesIO, TextIOWrapper +from types import TracebackType +from typing import ( + TYPE_CHECKING, + Any, + AnyStr, + Generic, + overload, +) + +from .. import to_thread +from .._core._fileio import AsyncFile +from ..lowlevel import checkpoint_if_cancelled + +if TYPE_CHECKING: + from _typeshed import OpenBinaryMode, OpenTextMode, ReadableBuffer, WriteableBuffer + + +class TemporaryFile(Generic[AnyStr]): + """ + An asynchronous temporary file that is automatically created and cleaned up. + + This class provides an asynchronous context manager interface to a temporary file. + The file is created using Python's standard `tempfile.TemporaryFile` function in a + background thread, and is wrapped as an asynchronous file using `AsyncFile`. + + :param mode: The mode in which the file is opened. Defaults to "w+b". + :param buffering: The buffering policy (-1 means the default buffering). + :param encoding: The encoding used to decode or encode the file. Only applicable in + text mode. + :param newline: Controls how universal newlines mode works (only applicable in text + mode). + :param suffix: The suffix for the temporary file name. + :param prefix: The prefix for the temporary file name. + :param dir: The directory in which the temporary file is created. + :param errors: The error handling scheme used for encoding/decoding errors. + """ + + _async_file: AsyncFile[AnyStr] + + @overload + def __init__( + self: TemporaryFile[bytes], + mode: OpenBinaryMode = ..., + buffering: int = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: str | None = ..., + prefix: str | None = ..., + dir: str | None = ..., + *, + errors: str | None = ..., + ): ... + @overload + def __init__( + self: TemporaryFile[str], + mode: OpenTextMode, + buffering: int = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: str | None = ..., + prefix: str | None = ..., + dir: str | None = ..., + *, + errors: str | None = ..., + ): ... + + def __init__( + self, + mode: OpenTextMode | OpenBinaryMode = "w+b", + buffering: int = -1, + encoding: str | None = None, + newline: str | None = None, + suffix: str | None = None, + prefix: str | None = None, + dir: str | None = None, + *, + errors: str | None = None, + ) -> None: + self.mode = mode + self.buffering = buffering + self.encoding = encoding + self.newline = newline + self.suffix: str | None = suffix + self.prefix: str | None = prefix + self.dir: str | None = dir + self.errors = errors + + async def __aenter__(self) -> AsyncFile[AnyStr]: + fp = await to_thread.run_sync( + lambda: tempfile.TemporaryFile( + self.mode, + self.buffering, + self.encoding, + self.newline, + self.suffix, + self.prefix, + self.dir, + errors=self.errors, + ) + ) + self._async_file = AsyncFile(fp) + return self._async_file + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + traceback: TracebackType | None, + ) -> None: + await self._async_file.aclose() + + +class NamedTemporaryFile(Generic[AnyStr]): + """ + An asynchronous named temporary file that is automatically created and cleaned up. + + This class provides an asynchronous context manager for a temporary file with a + visible name in the file system. It uses Python's standard + :func:`~tempfile.NamedTemporaryFile` function and wraps the file object with + :class:`AsyncFile` for asynchronous operations. + + :param mode: The mode in which the file is opened. Defaults to "w+b". + :param buffering: The buffering policy (-1 means the default buffering). + :param encoding: The encoding used to decode or encode the file. Only applicable in + text mode. + :param newline: Controls how universal newlines mode works (only applicable in text + mode). + :param suffix: The suffix for the temporary file name. + :param prefix: The prefix for the temporary file name. + :param dir: The directory in which the temporary file is created. + :param delete: Whether to delete the file when it is closed. + :param errors: The error handling scheme used for encoding/decoding errors. + :param delete_on_close: (Python 3.12+) Whether to delete the file on close. + """ + + _async_file: AsyncFile[AnyStr] + + @overload + def __init__( + self: NamedTemporaryFile[bytes], + mode: OpenBinaryMode = ..., + buffering: int = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: str | None = ..., + prefix: str | None = ..., + dir: str | None = ..., + delete: bool = ..., + *, + errors: str | None = ..., + delete_on_close: bool = ..., + ): ... + @overload + def __init__( + self: NamedTemporaryFile[str], + mode: OpenTextMode, + buffering: int = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: str | None = ..., + prefix: str | None = ..., + dir: str | None = ..., + delete: bool = ..., + *, + errors: str | None = ..., + delete_on_close: bool = ..., + ): ... + + def __init__( + self, + mode: OpenBinaryMode | OpenTextMode = "w+b", + buffering: int = -1, + encoding: str | None = None, + newline: str | None = None, + suffix: str | None = None, + prefix: str | None = None, + dir: str | None = None, + delete: bool = True, + *, + errors: str | None = None, + delete_on_close: bool = True, + ) -> None: + self._params: dict[str, Any] = { + "mode": mode, + "buffering": buffering, + "encoding": encoding, + "newline": newline, + "suffix": suffix, + "prefix": prefix, + "dir": dir, + "delete": delete, + "errors": errors, + } + if sys.version_info >= (3, 12): + self._params["delete_on_close"] = delete_on_close + + async def __aenter__(self) -> AsyncFile[AnyStr]: + fp = await to_thread.run_sync( + lambda: tempfile.NamedTemporaryFile(**self._params) + ) + self._async_file = AsyncFile(fp) + return self._async_file + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + traceback: TracebackType | None, + ) -> None: + await self._async_file.aclose() + + +class SpooledTemporaryFile(AsyncFile[AnyStr]): + """ + An asynchronous spooled temporary file that starts in memory and is spooled to disk. + + This class provides an asynchronous interface to a spooled temporary file, much like + Python's standard :class:`~tempfile.SpooledTemporaryFile`. It supports asynchronous + write operations and provides a method to force a rollover to disk. + + :param max_size: Maximum size in bytes before the file is rolled over to disk. + :param mode: The mode in which the file is opened. Defaults to "w+b". + :param buffering: The buffering policy (-1 means the default buffering). + :param encoding: The encoding used to decode or encode the file (text mode only). + :param newline: Controls how universal newlines mode works (text mode only). + :param suffix: The suffix for the temporary file name. + :param prefix: The prefix for the temporary file name. + :param dir: The directory in which the temporary file is created. + :param errors: The error handling scheme used for encoding/decoding errors. + """ + + _rolled: bool = False + + @overload + def __init__( + self: SpooledTemporaryFile[bytes], + max_size: int = ..., + mode: OpenBinaryMode = ..., + buffering: int = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: str | None = ..., + prefix: str | None = ..., + dir: str | None = ..., + *, + errors: str | None = ..., + ): ... + @overload + def __init__( + self: SpooledTemporaryFile[str], + max_size: int = ..., + mode: OpenTextMode = ..., + buffering: int = ..., + encoding: str | None = ..., + newline: str | None = ..., + suffix: str | None = ..., + prefix: str | None = ..., + dir: str | None = ..., + *, + errors: str | None = ..., + ): ... + + def __init__( + self, + max_size: int = 0, + mode: OpenBinaryMode | OpenTextMode = "w+b", + buffering: int = -1, + encoding: str | None = None, + newline: str | None = None, + suffix: str | None = None, + prefix: str | None = None, + dir: str | None = None, + *, + errors: str | None = None, + ) -> None: + self._tempfile_params: dict[str, Any] = { + "mode": mode, + "buffering": buffering, + "encoding": encoding, + "newline": newline, + "suffix": suffix, + "prefix": prefix, + "dir": dir, + "errors": errors, + } + self._max_size = max_size + if "b" in mode: + super().__init__(BytesIO()) # type: ignore[arg-type] + else: + super().__init__( + TextIOWrapper( # type: ignore[arg-type] + BytesIO(), + encoding=encoding, + errors=errors, + newline=newline, + write_through=True, + ) + ) + + async def aclose(self) -> None: + if not self._rolled: + self._fp.close() + return + + await super().aclose() + + async def _check(self) -> None: + if self._rolled or self._fp.tell() <= self._max_size: + return + + await self.rollover() + + async def rollover(self) -> None: + if self._rolled: + return + + self._rolled = True + buffer = self._fp + buffer.seek(0) + self._fp = await to_thread.run_sync( + lambda: tempfile.TemporaryFile(**self._tempfile_params) + ) + await self.write(buffer.read()) + buffer.close() + + @property + def closed(self) -> bool: + return self._fp.closed + + async def read(self, size: int = -1) -> AnyStr: + if not self._rolled: + await checkpoint_if_cancelled() + return self._fp.read(size) + + return await super().read(size) # type: ignore[return-value] + + async def read1(self: SpooledTemporaryFile[bytes], size: int = -1) -> bytes: + if not self._rolled: + await checkpoint_if_cancelled() + return self._fp.read1(size) + + return await super().read1(size) + + async def readline(self) -> AnyStr: + if not self._rolled: + await checkpoint_if_cancelled() + return self._fp.readline() + + return await super().readline() # type: ignore[return-value] + + async def readlines(self) -> list[AnyStr]: + if not self._rolled: + await checkpoint_if_cancelled() + return self._fp.readlines() + + return await super().readlines() # type: ignore[return-value] + + async def readinto(self: SpooledTemporaryFile[bytes], b: WriteableBuffer) -> int: + if not self._rolled: + await checkpoint_if_cancelled() + self._fp.readinto(b) + + return await super().readinto(b) + + async def readinto1(self: SpooledTemporaryFile[bytes], b: WriteableBuffer) -> int: + if not self._rolled: + await checkpoint_if_cancelled() + self._fp.readinto(b) + + return await super().readinto1(b) + + async def seek(self, offset: int, whence: int | None = os.SEEK_SET) -> int: + if not self._rolled: + await checkpoint_if_cancelled() + return self._fp.seek(offset, whence) + + return await super().seek(offset, whence) + + async def tell(self) -> int: + if not self._rolled: + await checkpoint_if_cancelled() + return self._fp.tell() + + return await super().tell() + + async def truncate(self, size: int | None = None) -> int: + if not self._rolled: + await checkpoint_if_cancelled() + return self._fp.truncate(size) + + return await super().truncate(size) + + @overload + async def write(self: SpooledTemporaryFile[bytes], b: ReadableBuffer) -> int: ... + @overload + async def write(self: SpooledTemporaryFile[str], b: str) -> int: ... + + async def write(self, b: ReadableBuffer | str) -> int: + """ + Asynchronously write data to the spooled temporary file. + + If the file has not yet been rolled over, the data is written synchronously, + and a rollover is triggered if the size exceeds the maximum size. + + :param s: The data to write. + :return: The number of bytes written. + :raises RuntimeError: If the underlying file is not initialized. + + """ + if not self._rolled: + await checkpoint_if_cancelled() + result = self._fp.write(b) + await self._check() + return result + + return await super().write(b) # type: ignore[misc] + + @overload + async def writelines( + self: SpooledTemporaryFile[bytes], lines: Iterable[ReadableBuffer] + ) -> None: ... + @overload + async def writelines( + self: SpooledTemporaryFile[str], lines: Iterable[str] + ) -> None: ... + + async def writelines(self, lines: Iterable[str] | Iterable[ReadableBuffer]) -> None: + """ + Asynchronously write a list of lines to the spooled temporary file. + + If the file has not yet been rolled over, the lines are written synchronously, + and a rollover is triggered if the size exceeds the maximum size. + + :param lines: An iterable of lines to write. + :raises RuntimeError: If the underlying file is not initialized. + + """ + if not self._rolled: + await checkpoint_if_cancelled() + result = self._fp.writelines(lines) + await self._check() + return result + + return await super().writelines(lines) # type: ignore[misc] + + +class TemporaryDirectory(Generic[AnyStr]): + """ + An asynchronous temporary directory that is created and cleaned up automatically. + + This class provides an asynchronous context manager for creating a temporary + directory. It wraps Python's standard :class:`~tempfile.TemporaryDirectory` to + perform directory creation and cleanup operations in a background thread. + + :param suffix: Suffix to be added to the temporary directory name. + :param prefix: Prefix to be added to the temporary directory name. + :param dir: The parent directory where the temporary directory is created. + :param ignore_cleanup_errors: Whether to ignore errors during cleanup + (Python 3.10+). + :param delete: Whether to delete the directory upon closing (Python 3.12+). + """ + + def __init__( + self, + suffix: AnyStr | None = None, + prefix: AnyStr | None = None, + dir: AnyStr | None = None, + *, + ignore_cleanup_errors: bool = False, + delete: bool = True, + ) -> None: + self.suffix: AnyStr | None = suffix + self.prefix: AnyStr | None = prefix + self.dir: AnyStr | None = dir + self.ignore_cleanup_errors = ignore_cleanup_errors + self.delete = delete + + self._tempdir: tempfile.TemporaryDirectory | None = None + + async def __aenter__(self) -> str: + params: dict[str, Any] = { + "suffix": self.suffix, + "prefix": self.prefix, + "dir": self.dir, + } + if sys.version_info >= (3, 10): + params["ignore_cleanup_errors"] = self.ignore_cleanup_errors + + if sys.version_info >= (3, 12): + params["delete"] = self.delete + + self._tempdir = await to_thread.run_sync( + lambda: tempfile.TemporaryDirectory(**params) + ) + return await to_thread.run_sync(self._tempdir.__enter__) + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + traceback: TracebackType | None, + ) -> None: + if self._tempdir is not None: + await to_thread.run_sync( + self._tempdir.__exit__, exc_type, exc_value, traceback + ) + + async def cleanup(self) -> None: + if self._tempdir is not None: + await to_thread.run_sync(self._tempdir.cleanup) + + +@overload +async def mkstemp( + suffix: str | None = None, + prefix: str | None = None, + dir: str | None = None, + text: bool = False, +) -> tuple[int, str]: ... + + +@overload +async def mkstemp( + suffix: bytes | None = None, + prefix: bytes | None = None, + dir: bytes | None = None, + text: bool = False, +) -> tuple[int, bytes]: ... + + +async def mkstemp( + suffix: AnyStr | None = None, + prefix: AnyStr | None = None, + dir: AnyStr | None = None, + text: bool = False, +) -> tuple[int, str | bytes]: + """ + Asynchronously create a temporary file and return an OS-level handle and the file + name. + + This function wraps `tempfile.mkstemp` and executes it in a background thread. + + :param suffix: Suffix to be added to the file name. + :param prefix: Prefix to be added to the file name. + :param dir: Directory in which the temporary file is created. + :param text: Whether the file is opened in text mode. + :return: A tuple containing the file descriptor and the file name. + + """ + return await to_thread.run_sync(tempfile.mkstemp, suffix, prefix, dir, text) + + +@overload +async def mkdtemp( + suffix: str | None = None, + prefix: str | None = None, + dir: str | None = None, +) -> str: ... + + +@overload +async def mkdtemp( + suffix: bytes | None = None, + prefix: bytes | None = None, + dir: bytes | None = None, +) -> bytes: ... + + +async def mkdtemp( + suffix: AnyStr | None = None, + prefix: AnyStr | None = None, + dir: AnyStr | None = None, +) -> str | bytes: + """ + Asynchronously create a temporary directory and return its path. + + This function wraps `tempfile.mkdtemp` and executes it in a background thread. + + :param suffix: Suffix to be added to the directory name. + :param prefix: Prefix to be added to the directory name. + :param dir: Parent directory where the temporary directory is created. + :return: The path of the created temporary directory. + + """ + return await to_thread.run_sync(tempfile.mkdtemp, suffix, prefix, dir) + + +async def gettempdir() -> str: + """ + Asynchronously return the name of the directory used for temporary files. + + This function wraps `tempfile.gettempdir` and executes it in a background thread. + + :return: The path of the temporary directory as a string. + + """ + return await to_thread.run_sync(tempfile.gettempdir) + + +async def gettempdirb() -> bytes: + """ + Asynchronously return the name of the directory used for temporary files in bytes. + + This function wraps `tempfile.gettempdirb` and executes it in a background thread. + + :return: The path of the temporary directory as bytes. + + """ + return await to_thread.run_sync(tempfile.gettempdirb) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_testing.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_testing.py new file mode 100644 index 0000000..369e65c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_testing.py @@ -0,0 +1,82 @@ +from __future__ import annotations + +from collections.abc import Awaitable, Generator +from typing import Any, cast + +from ._eventloop import get_async_backend + + +class TaskInfo: + """ + Represents an asynchronous task. + + :ivar int id: the unique identifier of the task + :ivar parent_id: the identifier of the parent task, if any + :vartype parent_id: Optional[int] + :ivar str name: the description of the task (if any) + :ivar ~collections.abc.Coroutine coro: the coroutine object of the task + """ + + __slots__ = "_name", "id", "parent_id", "name", "coro" + + def __init__( + self, + id: int, + parent_id: int | None, + name: str | None, + coro: Generator[Any, Any, Any] | Awaitable[Any], + ): + func = get_current_task + self._name = f"{func.__module__}.{func.__qualname__}" + self.id: int = id + self.parent_id: int | None = parent_id + self.name: str | None = name + self.coro: Generator[Any, Any, Any] | Awaitable[Any] = coro + + def __eq__(self, other: object) -> bool: + if isinstance(other, TaskInfo): + return self.id == other.id + + return NotImplemented + + def __hash__(self) -> int: + return hash(self.id) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}(id={self.id!r}, name={self.name!r})" + + def has_pending_cancellation(self) -> bool: + """ + Return ``True`` if the task has a cancellation pending, ``False`` otherwise. + + """ + return False + + +def get_current_task() -> TaskInfo: + """ + Return the current task. + + :return: a representation of the current task + :raises NoEventLoopError: if no supported asynchronous event loop is running in the + current thread + + """ + return get_async_backend().get_current_task() + + +def get_running_tasks() -> list[TaskInfo]: + """ + Return a list of running tasks in the current event loop. + + :return: a list of task info objects + :raises NoEventLoopError: if no supported asynchronous event loop is running in the + current thread + + """ + return cast("list[TaskInfo]", get_async_backend().get_running_tasks()) + + +async def wait_all_tasks_blocked() -> None: + """Wait until all other tasks are waiting for something.""" + await get_async_backend().wait_all_tasks_blocked() diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_typedattr.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_typedattr.py new file mode 100644 index 0000000..f358a44 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/_core/_typedattr.py @@ -0,0 +1,81 @@ +from __future__ import annotations + +from collections.abc import Callable, Mapping +from typing import Any, TypeVar, final, overload + +from ._exceptions import TypedAttributeLookupError + +T_Attr = TypeVar("T_Attr") +T_Default = TypeVar("T_Default") +undefined = object() + + +def typed_attribute() -> Any: + """Return a unique object, used to mark typed attributes.""" + return object() + + +class TypedAttributeSet: + """ + Superclass for typed attribute collections. + + Checks that every public attribute of every subclass has a type annotation. + """ + + def __init_subclass__(cls) -> None: + annotations: dict[str, Any] = getattr(cls, "__annotations__", {}) + for attrname in dir(cls): + if not attrname.startswith("_") and attrname not in annotations: + raise TypeError( + f"Attribute {attrname!r} is missing its type annotation" + ) + + super().__init_subclass__() + + +class TypedAttributeProvider: + """Base class for classes that wish to provide typed extra attributes.""" + + @property + def extra_attributes(self) -> Mapping[T_Attr, Callable[[], T_Attr]]: + """ + A mapping of the extra attributes to callables that return the corresponding + values. + + If the provider wraps another provider, the attributes from that wrapper should + also be included in the returned mapping (but the wrapper may override the + callables from the wrapped instance). + + """ + return {} + + @overload + def extra(self, attribute: T_Attr) -> T_Attr: ... + + @overload + def extra(self, attribute: T_Attr, default: T_Default) -> T_Attr | T_Default: ... + + @final + def extra(self, attribute: Any, default: object = undefined) -> object: + """ + extra(attribute, default=undefined) + + Return the value of the given typed extra attribute. + + :param attribute: the attribute (member of a :class:`~TypedAttributeSet`) to + look for + :param default: the value that should be returned if no value is found for the + attribute + :raises ~anyio.TypedAttributeLookupError: if the search failed and no default + value was given + + """ + try: + getter = self.extra_attributes[attribute] + except KeyError: + if default is undefined: + raise TypedAttributeLookupError("Attribute not found") from None + else: + return default + + return getter() diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/abc/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/abc/__init__.py new file mode 100644 index 0000000..d560ce3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/abc/__init__.py @@ -0,0 +1,58 @@ +from __future__ import annotations + +from ._eventloop import AsyncBackend as AsyncBackend +from ._resources import AsyncResource as AsyncResource +from ._sockets import ConnectedUDPSocket as ConnectedUDPSocket +from ._sockets import ConnectedUNIXDatagramSocket as ConnectedUNIXDatagramSocket +from ._sockets import IPAddressType as IPAddressType +from ._sockets import IPSockAddrType as IPSockAddrType +from ._sockets import SocketAttribute as SocketAttribute +from ._sockets import SocketListener as SocketListener +from ._sockets import SocketStream as SocketStream +from ._sockets import UDPPacketType as UDPPacketType +from ._sockets import UDPSocket as UDPSocket +from ._sockets import UNIXDatagramPacketType as UNIXDatagramPacketType +from ._sockets import UNIXDatagramSocket as UNIXDatagramSocket +from ._sockets import UNIXSocketStream as UNIXSocketStream +from ._streams import AnyByteReceiveStream as AnyByteReceiveStream +from ._streams import AnyByteSendStream as AnyByteSendStream +from ._streams import AnyByteStream as AnyByteStream +from ._streams import AnyByteStreamConnectable as AnyByteStreamConnectable +from ._streams import AnyUnreliableByteReceiveStream as AnyUnreliableByteReceiveStream +from ._streams import AnyUnreliableByteSendStream as AnyUnreliableByteSendStream +from ._streams import AnyUnreliableByteStream as AnyUnreliableByteStream +from ._streams import ByteReceiveStream as ByteReceiveStream +from ._streams import ByteSendStream as ByteSendStream +from ._streams import ByteStream as ByteStream +from ._streams import ByteStreamConnectable as ByteStreamConnectable +from ._streams import Listener as Listener +from ._streams import ObjectReceiveStream as ObjectReceiveStream +from ._streams import ObjectSendStream as ObjectSendStream +from ._streams import ObjectStream as ObjectStream +from ._streams import ObjectStreamConnectable as ObjectStreamConnectable +from ._streams import UnreliableObjectReceiveStream as UnreliableObjectReceiveStream +from ._streams import UnreliableObjectSendStream as UnreliableObjectSendStream +from ._streams import UnreliableObjectStream as UnreliableObjectStream +from ._subprocesses import Process as Process +from ._tasks import TaskGroup as TaskGroup +from ._tasks import TaskStatus as TaskStatus +from ._testing import TestRunner as TestRunner + +# Re-exported here, for backwards compatibility +# isort: off +from .._core._synchronization import ( + CapacityLimiter as CapacityLimiter, + Condition as Condition, + Event as Event, + Lock as Lock, + Semaphore as Semaphore, +) +from .._core._tasks import CancelScope as CancelScope +from ..from_thread import BlockingPortal as BlockingPortal + +# Re-export imports so they look like they live directly in this package +for __value in list(locals().values()): + if getattr(__value, "__module__", "").startswith("anyio.abc."): + __value.__module__ = __name__ + +del __value diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/abc/_eventloop.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/abc/_eventloop.py new file mode 100644 index 0000000..b1bd085 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/abc/_eventloop.py @@ -0,0 +1,414 @@ +from __future__ import annotations + +import math +import sys +from abc import ABCMeta, abstractmethod +from collections.abc import AsyncIterator, Awaitable, Callable, Sequence +from contextlib import AbstractContextManager +from os import PathLike +from signal import Signals +from socket import AddressFamily, SocketKind, socket +from typing import ( + IO, + TYPE_CHECKING, + Any, + TypeVar, + Union, + overload, +) + +if sys.version_info >= (3, 11): + from typing import TypeVarTuple, Unpack +else: + from typing_extensions import TypeVarTuple, Unpack + +if sys.version_info >= (3, 10): + from typing import TypeAlias +else: + from typing_extensions import TypeAlias + +if TYPE_CHECKING: + from _typeshed import FileDescriptorLike + + from .._core._synchronization import CapacityLimiter, Event, Lock, Semaphore + from .._core._tasks import CancelScope + from .._core._testing import TaskInfo + from ._sockets import ( + ConnectedUDPSocket, + ConnectedUNIXDatagramSocket, + IPSockAddrType, + SocketListener, + SocketStream, + UDPSocket, + UNIXDatagramSocket, + UNIXSocketStream, + ) + from ._subprocesses import Process + from ._tasks import TaskGroup + from ._testing import TestRunner + +T_Retval = TypeVar("T_Retval") +PosArgsT = TypeVarTuple("PosArgsT") +StrOrBytesPath: TypeAlias = Union[str, bytes, "PathLike[str]", "PathLike[bytes]"] + + +class AsyncBackend(metaclass=ABCMeta): + @classmethod + @abstractmethod + def run( + cls, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], + args: tuple[Unpack[PosArgsT]], + kwargs: dict[str, Any], + options: dict[str, Any], + ) -> T_Retval: + """ + Run the given coroutine function in an asynchronous event loop. + + The current thread must not be already running an event loop. + + :param func: a coroutine function + :param args: positional arguments to ``func`` + :param kwargs: positional arguments to ``func`` + :param options: keyword arguments to call the backend ``run()`` implementation + with + :return: the return value of the coroutine function + """ + + @classmethod + @abstractmethod + def current_token(cls) -> object: + """ + Return an object that allows other threads to run code inside the event loop. + + :return: a token object, specific to the event loop running in the current + thread + """ + + @classmethod + @abstractmethod + def current_time(cls) -> float: + """ + Return the current value of the event loop's internal clock. + + :return: the clock value (seconds) + """ + + @classmethod + @abstractmethod + def cancelled_exception_class(cls) -> type[BaseException]: + """Return the exception class that is raised in a task if it's cancelled.""" + + @classmethod + @abstractmethod + async def checkpoint(cls) -> None: + """ + Check if the task has been cancelled, and allow rescheduling of other tasks. + + This is effectively the same as running :meth:`checkpoint_if_cancelled` and then + :meth:`cancel_shielded_checkpoint`. + """ + + @classmethod + async def checkpoint_if_cancelled(cls) -> None: + """ + Check if the current task group has been cancelled. + + This will check if the task has been cancelled, but will not allow other tasks + to be scheduled if not. + + """ + if cls.current_effective_deadline() == -math.inf: + await cls.checkpoint() + + @classmethod + async def cancel_shielded_checkpoint(cls) -> None: + """ + Allow the rescheduling of other tasks. + + This will give other tasks the opportunity to run, but without checking if the + current task group has been cancelled, unlike with :meth:`checkpoint`. + + """ + with cls.create_cancel_scope(shield=True): + await cls.sleep(0) + + @classmethod + @abstractmethod + async def sleep(cls, delay: float) -> None: + """ + Pause the current task for the specified duration. + + :param delay: the duration, in seconds + """ + + @classmethod + @abstractmethod + def create_cancel_scope( + cls, *, deadline: float = math.inf, shield: bool = False + ) -> CancelScope: + pass + + @classmethod + @abstractmethod + def current_effective_deadline(cls) -> float: + """ + Return the nearest deadline among all the cancel scopes effective for the + current task. + + :return: + - a clock value from the event loop's internal clock + - ``inf`` if there is no deadline in effect + - ``-inf`` if the current scope has been cancelled + :rtype: float + """ + + @classmethod + @abstractmethod + def create_task_group(cls) -> TaskGroup: + pass + + @classmethod + @abstractmethod + def create_event(cls) -> Event: + pass + + @classmethod + @abstractmethod + def create_lock(cls, *, fast_acquire: bool) -> Lock: + pass + + @classmethod + @abstractmethod + def create_semaphore( + cls, + initial_value: int, + *, + max_value: int | None = None, + fast_acquire: bool = False, + ) -> Semaphore: + pass + + @classmethod + @abstractmethod + def create_capacity_limiter(cls, total_tokens: float) -> CapacityLimiter: + pass + + @classmethod + @abstractmethod + async def run_sync_in_worker_thread( + cls, + func: Callable[[Unpack[PosArgsT]], T_Retval], + args: tuple[Unpack[PosArgsT]], + abandon_on_cancel: bool = False, + limiter: CapacityLimiter | None = None, + ) -> T_Retval: + pass + + @classmethod + @abstractmethod + def check_cancelled(cls) -> None: + pass + + @classmethod + @abstractmethod + def run_async_from_thread( + cls, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], + args: tuple[Unpack[PosArgsT]], + token: object, + ) -> T_Retval: + pass + + @classmethod + @abstractmethod + def run_sync_from_thread( + cls, + func: Callable[[Unpack[PosArgsT]], T_Retval], + args: tuple[Unpack[PosArgsT]], + token: object, + ) -> T_Retval: + pass + + @classmethod + @abstractmethod + async def open_process( + cls, + command: StrOrBytesPath | Sequence[StrOrBytesPath], + *, + stdin: int | IO[Any] | None, + stdout: int | IO[Any] | None, + stderr: int | IO[Any] | None, + **kwargs: Any, + ) -> Process: + pass + + @classmethod + @abstractmethod + def setup_process_pool_exit_at_shutdown(cls, workers: set[Process]) -> None: + pass + + @classmethod + @abstractmethod + async def connect_tcp( + cls, host: str, port: int, local_address: IPSockAddrType | None = None + ) -> SocketStream: + pass + + @classmethod + @abstractmethod + async def connect_unix(cls, path: str | bytes) -> UNIXSocketStream: + pass + + @classmethod + @abstractmethod + def create_tcp_listener(cls, sock: socket) -> SocketListener: + pass + + @classmethod + @abstractmethod + def create_unix_listener(cls, sock: socket) -> SocketListener: + pass + + @classmethod + @abstractmethod + async def create_udp_socket( + cls, + family: AddressFamily, + local_address: IPSockAddrType | None, + remote_address: IPSockAddrType | None, + reuse_port: bool, + ) -> UDPSocket | ConnectedUDPSocket: + pass + + @classmethod + @overload + async def create_unix_datagram_socket( + cls, raw_socket: socket, remote_path: None + ) -> UNIXDatagramSocket: ... + + @classmethod + @overload + async def create_unix_datagram_socket( + cls, raw_socket: socket, remote_path: str | bytes + ) -> ConnectedUNIXDatagramSocket: ... + + @classmethod + @abstractmethod + async def create_unix_datagram_socket( + cls, raw_socket: socket, remote_path: str | bytes | None + ) -> UNIXDatagramSocket | ConnectedUNIXDatagramSocket: + pass + + @classmethod + @abstractmethod + async def getaddrinfo( + cls, + host: bytes | str | None, + port: str | int | None, + *, + family: int | AddressFamily = 0, + type: int | SocketKind = 0, + proto: int = 0, + flags: int = 0, + ) -> Sequence[ + tuple[ + AddressFamily, + SocketKind, + int, + str, + tuple[str, int] | tuple[str, int, int, int] | tuple[int, bytes], + ] + ]: + pass + + @classmethod + @abstractmethod + async def getnameinfo( + cls, sockaddr: IPSockAddrType, flags: int = 0 + ) -> tuple[str, str]: + pass + + @classmethod + @abstractmethod + async def wait_readable(cls, obj: FileDescriptorLike) -> None: + pass + + @classmethod + @abstractmethod + async def wait_writable(cls, obj: FileDescriptorLike) -> None: + pass + + @classmethod + @abstractmethod + def notify_closing(cls, obj: FileDescriptorLike) -> None: + pass + + @classmethod + @abstractmethod + async def wrap_listener_socket(cls, sock: socket) -> SocketListener: + pass + + @classmethod + @abstractmethod + async def wrap_stream_socket(cls, sock: socket) -> SocketStream: + pass + + @classmethod + @abstractmethod + async def wrap_unix_stream_socket(cls, sock: socket) -> UNIXSocketStream: + pass + + @classmethod + @abstractmethod + async def wrap_udp_socket(cls, sock: socket) -> UDPSocket: + pass + + @classmethod + @abstractmethod + async def wrap_connected_udp_socket(cls, sock: socket) -> ConnectedUDPSocket: + pass + + @classmethod + @abstractmethod + async def wrap_unix_datagram_socket(cls, sock: socket) -> UNIXDatagramSocket: + pass + + @classmethod + @abstractmethod + async def wrap_connected_unix_datagram_socket( + cls, sock: socket + ) -> ConnectedUNIXDatagramSocket: + pass + + @classmethod + @abstractmethod + def current_default_thread_limiter(cls) -> CapacityLimiter: + pass + + @classmethod + @abstractmethod + def open_signal_receiver( + cls, *signals: Signals + ) -> AbstractContextManager[AsyncIterator[Signals]]: + pass + + @classmethod + @abstractmethod + def get_current_task(cls) -> TaskInfo: + pass + + @classmethod + @abstractmethod + def get_running_tasks(cls) -> Sequence[TaskInfo]: + pass + + @classmethod + @abstractmethod + async def wait_all_tasks_blocked(cls) -> None: + pass + + @classmethod + @abstractmethod + def create_test_runner(cls, options: dict[str, Any]) -> TestRunner: + pass diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/abc/_resources.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/abc/_resources.py new file mode 100644 index 0000000..10df115 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/abc/_resources.py @@ -0,0 +1,33 @@ +from __future__ import annotations + +from abc import ABCMeta, abstractmethod +from types import TracebackType +from typing import TypeVar + +T = TypeVar("T") + + +class AsyncResource(metaclass=ABCMeta): + """ + Abstract base class for all closeable asynchronous resources. + + Works as an asynchronous context manager which returns the instance itself on enter, + and calls :meth:`aclose` on exit. + """ + + __slots__ = () + + async def __aenter__(self: T) -> T: + return self + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + await self.aclose() + + @abstractmethod + async def aclose(self) -> None: + """Close the resource.""" diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/abc/_sockets.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/abc/_sockets.py new file mode 100644 index 0000000..3ff60d4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/abc/_sockets.py @@ -0,0 +1,405 @@ +from __future__ import annotations + +import errno +import socket +import sys +from abc import abstractmethod +from collections.abc import Callable, Collection, Mapping +from contextlib import AsyncExitStack +from io import IOBase +from ipaddress import IPv4Address, IPv6Address +from socket import AddressFamily +from typing import Any, TypeVar, Union + +from .._core._eventloop import get_async_backend +from .._core._typedattr import ( + TypedAttributeProvider, + TypedAttributeSet, + typed_attribute, +) +from ._streams import ByteStream, Listener, UnreliableObjectStream +from ._tasks import TaskGroup + +if sys.version_info >= (3, 10): + from typing import TypeAlias +else: + from typing_extensions import TypeAlias + +IPAddressType: TypeAlias = Union[str, IPv4Address, IPv6Address] +IPSockAddrType: TypeAlias = tuple[str, int] +SockAddrType: TypeAlias = Union[IPSockAddrType, str] +UDPPacketType: TypeAlias = tuple[bytes, IPSockAddrType] +UNIXDatagramPacketType: TypeAlias = tuple[bytes, str] +T_Retval = TypeVar("T_Retval") + + +def _validate_socket( + sock_or_fd: socket.socket | int, + sock_type: socket.SocketKind, + addr_family: socket.AddressFamily = socket.AF_UNSPEC, + *, + require_connected: bool = False, + require_bound: bool = False, +) -> socket.socket: + if isinstance(sock_or_fd, int): + try: + sock = socket.socket(fileno=sock_or_fd) + except OSError as exc: + if exc.errno == errno.ENOTSOCK: + raise ValueError( + "the file descriptor does not refer to a socket" + ) from exc + elif require_connected: + raise ValueError("the socket must be connected") from exc + elif require_bound: + raise ValueError("the socket must be bound to a local address") from exc + else: + raise + elif isinstance(sock_or_fd, socket.socket): + sock = sock_or_fd + else: + raise TypeError( + f"expected an int or socket, got {type(sock_or_fd).__qualname__} instead" + ) + + try: + if require_connected: + try: + sock.getpeername() + except OSError as exc: + raise ValueError("the socket must be connected") from exc + + if require_bound: + try: + if sock.family in (socket.AF_INET, socket.AF_INET6): + bound_addr = sock.getsockname()[1] + else: + bound_addr = sock.getsockname() + except OSError: + bound_addr = None + + if not bound_addr: + raise ValueError("the socket must be bound to a local address") + + if addr_family != socket.AF_UNSPEC and sock.family != addr_family: + raise ValueError( + f"address family mismatch: expected {addr_family.name}, got " + f"{sock.family.name}" + ) + + if sock.type != sock_type: + raise ValueError( + f"socket type mismatch: expected {sock_type.name}, got {sock.type.name}" + ) + except BaseException: + # Avoid ResourceWarning from the locally constructed socket object + if isinstance(sock_or_fd, int): + sock.detach() + + raise + + sock.setblocking(False) + return sock + + +class SocketAttribute(TypedAttributeSet): + """ + .. attribute:: family + :type: socket.AddressFamily + + the address family of the underlying socket + + .. attribute:: local_address + :type: tuple[str, int] | str + + the local address the underlying socket is connected to + + .. attribute:: local_port + :type: int + + for IP based sockets, the local port the underlying socket is bound to + + .. attribute:: raw_socket + :type: socket.socket + + the underlying stdlib socket object + + .. attribute:: remote_address + :type: tuple[str, int] | str + + the remote address the underlying socket is connected to + + .. attribute:: remote_port + :type: int + + for IP based sockets, the remote port the underlying socket is connected to + """ + + family: AddressFamily = typed_attribute() + local_address: SockAddrType = typed_attribute() + local_port: int = typed_attribute() + raw_socket: socket.socket = typed_attribute() + remote_address: SockAddrType = typed_attribute() + remote_port: int = typed_attribute() + + +class _SocketProvider(TypedAttributeProvider): + @property + def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: + from .._core._sockets import convert_ipv6_sockaddr as convert + + attributes: dict[Any, Callable[[], Any]] = { + SocketAttribute.family: lambda: self._raw_socket.family, + SocketAttribute.local_address: lambda: convert( + self._raw_socket.getsockname() + ), + SocketAttribute.raw_socket: lambda: self._raw_socket, + } + try: + peername: tuple[str, int] | None = convert(self._raw_socket.getpeername()) + except OSError: + peername = None + + # Provide the remote address for connected sockets + if peername is not None: + attributes[SocketAttribute.remote_address] = lambda: peername + + # Provide local and remote ports for IP based sockets + if self._raw_socket.family in (AddressFamily.AF_INET, AddressFamily.AF_INET6): + attributes[SocketAttribute.local_port] = ( + lambda: self._raw_socket.getsockname()[1] + ) + if peername is not None: + remote_port = peername[1] + attributes[SocketAttribute.remote_port] = lambda: remote_port + + return attributes + + @property + @abstractmethod + def _raw_socket(self) -> socket.socket: + pass + + +class SocketStream(ByteStream, _SocketProvider): + """ + Transports bytes over a socket. + + Supports all relevant extra attributes from :class:`~SocketAttribute`. + """ + + @classmethod + async def from_socket(cls, sock_or_fd: socket.socket | int) -> SocketStream: + """ + Wrap an existing socket object or file descriptor as a socket stream. + + The newly created socket wrapper takes ownership of the socket being passed in. + The existing socket must already be connected. + + :param sock_or_fd: a socket object or file descriptor + :return: a socket stream + + """ + sock = _validate_socket(sock_or_fd, socket.SOCK_STREAM, require_connected=True) + return await get_async_backend().wrap_stream_socket(sock) + + +class UNIXSocketStream(SocketStream): + @classmethod + async def from_socket(cls, sock_or_fd: socket.socket | int) -> UNIXSocketStream: + """ + Wrap an existing socket object or file descriptor as a UNIX socket stream. + + The newly created socket wrapper takes ownership of the socket being passed in. + The existing socket must already be connected. + + :param sock_or_fd: a socket object or file descriptor + :return: a UNIX socket stream + + """ + sock = _validate_socket( + sock_or_fd, socket.SOCK_STREAM, socket.AF_UNIX, require_connected=True + ) + return await get_async_backend().wrap_unix_stream_socket(sock) + + @abstractmethod + async def send_fds(self, message: bytes, fds: Collection[int | IOBase]) -> None: + """ + Send file descriptors along with a message to the peer. + + :param message: a non-empty bytestring + :param fds: a collection of files (either numeric file descriptors or open file + or socket objects) + """ + + @abstractmethod + async def receive_fds(self, msglen: int, maxfds: int) -> tuple[bytes, list[int]]: + """ + Receive file descriptors along with a message from the peer. + + :param msglen: length of the message to expect from the peer + :param maxfds: maximum number of file descriptors to expect from the peer + :return: a tuple of (message, file descriptors) + """ + + +class SocketListener(Listener[SocketStream], _SocketProvider): + """ + Listens to incoming socket connections. + + Supports all relevant extra attributes from :class:`~SocketAttribute`. + """ + + @classmethod + async def from_socket( + cls, + sock_or_fd: socket.socket | int, + ) -> SocketListener: + """ + Wrap an existing socket object or file descriptor as a socket listener. + + The newly created listener takes ownership of the socket being passed in. + + :param sock_or_fd: a socket object or file descriptor + :return: a socket listener + + """ + sock = _validate_socket(sock_or_fd, socket.SOCK_STREAM, require_bound=True) + return await get_async_backend().wrap_listener_socket(sock) + + @abstractmethod + async def accept(self) -> SocketStream: + """Accept an incoming connection.""" + + async def serve( + self, + handler: Callable[[SocketStream], Any], + task_group: TaskGroup | None = None, + ) -> None: + from .. import create_task_group + + async with AsyncExitStack() as stack: + if task_group is None: + task_group = await stack.enter_async_context(create_task_group()) + + while True: + stream = await self.accept() + task_group.start_soon(handler, stream) + + +class UDPSocket(UnreliableObjectStream[UDPPacketType], _SocketProvider): + """ + Represents an unconnected UDP socket. + + Supports all relevant extra attributes from :class:`~SocketAttribute`. + """ + + @classmethod + async def from_socket(cls, sock_or_fd: socket.socket | int) -> UDPSocket: + """ + Wrap an existing socket object or file descriptor as a UDP socket. + + The newly created socket wrapper takes ownership of the socket being passed in. + The existing socket must be bound to a local address. + + :param sock_or_fd: a socket object or file descriptor + :return: a UDP socket + + """ + sock = _validate_socket(sock_or_fd, socket.SOCK_DGRAM, require_bound=True) + return await get_async_backend().wrap_udp_socket(sock) + + async def sendto(self, data: bytes, host: str, port: int) -> None: + """ + Alias for :meth:`~.UnreliableObjectSendStream.send` ((data, (host, port))). + + """ + return await self.send((data, (host, port))) + + +class ConnectedUDPSocket(UnreliableObjectStream[bytes], _SocketProvider): + """ + Represents an connected UDP socket. + + Supports all relevant extra attributes from :class:`~SocketAttribute`. + """ + + @classmethod + async def from_socket(cls, sock_or_fd: socket.socket | int) -> ConnectedUDPSocket: + """ + Wrap an existing socket object or file descriptor as a connected UDP socket. + + The newly created socket wrapper takes ownership of the socket being passed in. + The existing socket must already be connected. + + :param sock_or_fd: a socket object or file descriptor + :return: a connected UDP socket + + """ + sock = _validate_socket( + sock_or_fd, + socket.SOCK_DGRAM, + require_connected=True, + ) + return await get_async_backend().wrap_connected_udp_socket(sock) + + +class UNIXDatagramSocket( + UnreliableObjectStream[UNIXDatagramPacketType], _SocketProvider +): + """ + Represents an unconnected Unix datagram socket. + + Supports all relevant extra attributes from :class:`~SocketAttribute`. + """ + + @classmethod + async def from_socket( + cls, + sock_or_fd: socket.socket | int, + ) -> UNIXDatagramSocket: + """ + Wrap an existing socket object or file descriptor as a UNIX datagram + socket. + + The newly created socket wrapper takes ownership of the socket being passed in. + + :param sock_or_fd: a socket object or file descriptor + :return: a UNIX datagram socket + + """ + sock = _validate_socket(sock_or_fd, socket.SOCK_DGRAM, socket.AF_UNIX) + return await get_async_backend().wrap_unix_datagram_socket(sock) + + async def sendto(self, data: bytes, path: str) -> None: + """Alias for :meth:`~.UnreliableObjectSendStream.send` ((data, path)).""" + return await self.send((data, path)) + + +class ConnectedUNIXDatagramSocket(UnreliableObjectStream[bytes], _SocketProvider): + """ + Represents a connected Unix datagram socket. + + Supports all relevant extra attributes from :class:`~SocketAttribute`. + """ + + @classmethod + async def from_socket( + cls, + sock_or_fd: socket.socket | int, + ) -> ConnectedUNIXDatagramSocket: + """ + Wrap an existing socket object or file descriptor as a connected UNIX datagram + socket. + + The newly created socket wrapper takes ownership of the socket being passed in. + The existing socket must already be connected. + + :param sock_or_fd: a socket object or file descriptor + :return: a connected UNIX datagram socket + + """ + sock = _validate_socket( + sock_or_fd, socket.SOCK_DGRAM, socket.AF_UNIX, require_connected=True + ) + return await get_async_backend().wrap_connected_unix_datagram_socket(sock) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/abc/_streams.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/abc/_streams.py new file mode 100644 index 0000000..369df3f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/abc/_streams.py @@ -0,0 +1,239 @@ +from __future__ import annotations + +import sys +from abc import ABCMeta, abstractmethod +from collections.abc import Callable +from typing import Any, Generic, TypeVar, Union + +from .._core._exceptions import EndOfStream +from .._core._typedattr import TypedAttributeProvider +from ._resources import AsyncResource +from ._tasks import TaskGroup + +if sys.version_info >= (3, 10): + from typing import TypeAlias +else: + from typing_extensions import TypeAlias + +T_Item = TypeVar("T_Item") +T_co = TypeVar("T_co", covariant=True) +T_contra = TypeVar("T_contra", contravariant=True) + + +class UnreliableObjectReceiveStream( + Generic[T_co], AsyncResource, TypedAttributeProvider +): + """ + An interface for receiving objects. + + This interface makes no guarantees that the received messages arrive in the order in + which they were sent, or that no messages are missed. + + Asynchronously iterating over objects of this type will yield objects matching the + given type parameter. + """ + + def __aiter__(self) -> UnreliableObjectReceiveStream[T_co]: + return self + + async def __anext__(self) -> T_co: + try: + return await self.receive() + except EndOfStream: + raise StopAsyncIteration from None + + @abstractmethod + async def receive(self) -> T_co: + """ + Receive the next item. + + :raises ~anyio.ClosedResourceError: if the receive stream has been explicitly + closed + :raises ~anyio.EndOfStream: if this stream has been closed from the other end + :raises ~anyio.BrokenResourceError: if this stream has been rendered unusable + due to external causes + """ + + +class UnreliableObjectSendStream( + Generic[T_contra], AsyncResource, TypedAttributeProvider +): + """ + An interface for sending objects. + + This interface makes no guarantees that the messages sent will reach the + recipient(s) in the same order in which they were sent, or at all. + """ + + @abstractmethod + async def send(self, item: T_contra) -> None: + """ + Send an item to the peer(s). + + :param item: the item to send + :raises ~anyio.ClosedResourceError: if the send stream has been explicitly + closed + :raises ~anyio.BrokenResourceError: if this stream has been rendered unusable + due to external causes + """ + + +class UnreliableObjectStream( + UnreliableObjectReceiveStream[T_Item], UnreliableObjectSendStream[T_Item] +): + """ + A bidirectional message stream which does not guarantee the order or reliability of + message delivery. + """ + + +class ObjectReceiveStream(UnreliableObjectReceiveStream[T_co]): + """ + A receive message stream which guarantees that messages are received in the same + order in which they were sent, and that no messages are missed. + """ + + +class ObjectSendStream(UnreliableObjectSendStream[T_contra]): + """ + A send message stream which guarantees that messages are delivered in the same order + in which they were sent, without missing any messages in the middle. + """ + + +class ObjectStream( + ObjectReceiveStream[T_Item], + ObjectSendStream[T_Item], + UnreliableObjectStream[T_Item], +): + """ + A bidirectional message stream which guarantees the order and reliability of message + delivery. + """ + + @abstractmethod + async def send_eof(self) -> None: + """ + Send an end-of-file indication to the peer. + + You should not try to send any further data to this stream after calling this + method. This method is idempotent (does nothing on successive calls). + """ + + +class ByteReceiveStream(AsyncResource, TypedAttributeProvider): + """ + An interface for receiving bytes from a single peer. + + Iterating this byte stream will yield a byte string of arbitrary length, but no more + than 65536 bytes. + """ + + def __aiter__(self) -> ByteReceiveStream: + return self + + async def __anext__(self) -> bytes: + try: + return await self.receive() + except EndOfStream: + raise StopAsyncIteration from None + + @abstractmethod + async def receive(self, max_bytes: int = 65536) -> bytes: + """ + Receive at most ``max_bytes`` bytes from the peer. + + .. note:: Implementers of this interface should not return an empty + :class:`bytes` object, and users should ignore them. + + :param max_bytes: maximum number of bytes to receive + :return: the received bytes + :raises ~anyio.EndOfStream: if this stream has been closed from the other end + """ + + +class ByteSendStream(AsyncResource, TypedAttributeProvider): + """An interface for sending bytes to a single peer.""" + + @abstractmethod + async def send(self, item: bytes) -> None: + """ + Send the given bytes to the peer. + + :param item: the bytes to send + """ + + +class ByteStream(ByteReceiveStream, ByteSendStream): + """A bidirectional byte stream.""" + + @abstractmethod + async def send_eof(self) -> None: + """ + Send an end-of-file indication to the peer. + + You should not try to send any further data to this stream after calling this + method. This method is idempotent (does nothing on successive calls). + """ + + +#: Type alias for all unreliable bytes-oriented receive streams. +AnyUnreliableByteReceiveStream: TypeAlias = Union[ + UnreliableObjectReceiveStream[bytes], ByteReceiveStream +] +#: Type alias for all unreliable bytes-oriented send streams. +AnyUnreliableByteSendStream: TypeAlias = Union[ + UnreliableObjectSendStream[bytes], ByteSendStream +] +#: Type alias for all unreliable bytes-oriented streams. +AnyUnreliableByteStream: TypeAlias = Union[UnreliableObjectStream[bytes], ByteStream] +#: Type alias for all bytes-oriented receive streams. +AnyByteReceiveStream: TypeAlias = Union[ObjectReceiveStream[bytes], ByteReceiveStream] +#: Type alias for all bytes-oriented send streams. +AnyByteSendStream: TypeAlias = Union[ObjectSendStream[bytes], ByteSendStream] +#: Type alias for all bytes-oriented streams. +AnyByteStream: TypeAlias = Union[ObjectStream[bytes], ByteStream] + + +class Listener(Generic[T_co], AsyncResource, TypedAttributeProvider): + """An interface for objects that let you accept incoming connections.""" + + @abstractmethod + async def serve( + self, handler: Callable[[T_co], Any], task_group: TaskGroup | None = None + ) -> None: + """ + Accept incoming connections as they come in and start tasks to handle them. + + :param handler: a callable that will be used to handle each accepted connection + :param task_group: the task group that will be used to start tasks for handling + each accepted connection (if omitted, an ad-hoc task group will be created) + """ + + +class ObjectStreamConnectable(Generic[T_co], metaclass=ABCMeta): + @abstractmethod + async def connect(self) -> ObjectStream[T_co]: + """ + Connect to the remote endpoint. + + :return: an object stream connected to the remote end + :raises ConnectionFailed: if the connection fails + """ + + +class ByteStreamConnectable(metaclass=ABCMeta): + @abstractmethod + async def connect(self) -> ByteStream: + """ + Connect to the remote endpoint. + + :return: a bytestream connected to the remote end + :raises ConnectionFailed: if the connection fails + """ + + +#: Type alias for all connectables returning bytestreams or bytes-oriented object streams +AnyByteStreamConnectable: TypeAlias = Union[ + ObjectStreamConnectable[bytes], ByteStreamConnectable +] diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/abc/_subprocesses.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/abc/_subprocesses.py new file mode 100644 index 0000000..ce0564c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/abc/_subprocesses.py @@ -0,0 +1,79 @@ +from __future__ import annotations + +from abc import abstractmethod +from signal import Signals + +from ._resources import AsyncResource +from ._streams import ByteReceiveStream, ByteSendStream + + +class Process(AsyncResource): + """An asynchronous version of :class:`subprocess.Popen`.""" + + @abstractmethod + async def wait(self) -> int: + """ + Wait until the process exits. + + :return: the exit code of the process + """ + + @abstractmethod + def terminate(self) -> None: + """ + Terminates the process, gracefully if possible. + + On Windows, this calls ``TerminateProcess()``. + On POSIX systems, this sends ``SIGTERM`` to the process. + + .. seealso:: :meth:`subprocess.Popen.terminate` + """ + + @abstractmethod + def kill(self) -> None: + """ + Kills the process. + + On Windows, this calls ``TerminateProcess()``. + On POSIX systems, this sends ``SIGKILL`` to the process. + + .. seealso:: :meth:`subprocess.Popen.kill` + """ + + @abstractmethod + def send_signal(self, signal: Signals) -> None: + """ + Send a signal to the subprocess. + + .. seealso:: :meth:`subprocess.Popen.send_signal` + + :param signal: the signal number (e.g. :data:`signal.SIGHUP`) + """ + + @property + @abstractmethod + def pid(self) -> int: + """The process ID of the process.""" + + @property + @abstractmethod + def returncode(self) -> int | None: + """ + The return code of the process. If the process has not yet terminated, this will + be ``None``. + """ + + @property + @abstractmethod + def stdin(self) -> ByteSendStream | None: + """The stream for the standard input of the process.""" + + @property + @abstractmethod + def stdout(self) -> ByteReceiveStream | None: + """The stream for the standard output of the process.""" + + @property + @abstractmethod + def stderr(self) -> ByteReceiveStream | None: + """The stream for the standard error output of the process.""" diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/abc/_tasks.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/abc/_tasks.py new file mode 100644 index 0000000..516b3ec --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/abc/_tasks.py @@ -0,0 +1,117 @@ +from __future__ import annotations + +import sys +from abc import ABCMeta, abstractmethod +from collections.abc import Awaitable, Callable +from types import TracebackType +from typing import TYPE_CHECKING, Any, Protocol, overload + +if sys.version_info >= (3, 13): + from typing import TypeVar +else: + from typing_extensions import TypeVar + +if sys.version_info >= (3, 11): + from typing import TypeVarTuple, Unpack +else: + from typing_extensions import TypeVarTuple, Unpack + +if TYPE_CHECKING: + from .._core._tasks import CancelScope + +T_Retval = TypeVar("T_Retval") +T_contra = TypeVar("T_contra", contravariant=True, default=None) +PosArgsT = TypeVarTuple("PosArgsT") + + +class TaskStatus(Protocol[T_contra]): + @overload + def started(self: TaskStatus[None]) -> None: ... + + @overload + def started(self, value: T_contra) -> None: ... + + def started(self, value: T_contra | None = None) -> None: + """ + Signal that the task has started. + + :param value: object passed back to the starter of the task + """ + + +class TaskGroup(metaclass=ABCMeta): + """ + Groups several asynchronous tasks together. + + :ivar cancel_scope: the cancel scope inherited by all child tasks + :vartype cancel_scope: CancelScope + + .. note:: On asyncio, support for eager task factories is considered to be + **experimental**. In particular, they don't follow the usual semantics of new + tasks being scheduled on the next iteration of the event loop, and may thus + cause unexpected behavior in code that wasn't written with such semantics in + mind. + """ + + cancel_scope: CancelScope + + @abstractmethod + def start_soon( + self, + func: Callable[[Unpack[PosArgsT]], Awaitable[Any]], + *args: Unpack[PosArgsT], + name: object = None, + ) -> None: + """ + Start a new task in this task group. + + :param func: a coroutine function + :param args: positional arguments to call the function with + :param name: name of the task, for the purposes of introspection and debugging + + .. versionadded:: 3.0 + """ + + @abstractmethod + async def start( + self, + func: Callable[..., Awaitable[Any]], + *args: object, + name: object = None, + ) -> Any: + """ + Start a new task and wait until it signals for readiness. + + The target callable must accept a keyword argument ``task_status`` (of type + :class:`TaskStatus`). Awaiting on this method will return whatever was passed to + ``task_status.started()`` (``None`` by default). + + .. note:: The :class:`TaskStatus` class is generic, and the type argument should + indicate the type of the value that will be passed to + ``task_status.started()``. + + :param func: a coroutine function that accepts the ``task_status`` keyword + argument + :param args: positional arguments to call the function with + :param name: an optional name for the task, for introspection and debugging + :return: the value passed to ``task_status.started()`` + :raises RuntimeError: if the task finishes without calling + ``task_status.started()`` + + .. seealso:: :ref:`start_initialize` + + .. versionadded:: 3.0 + """ + + @abstractmethod + async def __aenter__(self) -> TaskGroup: + """Enter the task group context and allow starting new tasks.""" + + @abstractmethod + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> bool: + """Exit the task group context waiting for all tasks to finish.""" diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/abc/_testing.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/abc/_testing.py new file mode 100644 index 0000000..7c50ed7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/abc/_testing.py @@ -0,0 +1,65 @@ +from __future__ import annotations + +import types +from abc import ABCMeta, abstractmethod +from collections.abc import AsyncGenerator, Callable, Coroutine, Iterable +from typing import Any, TypeVar + +_T = TypeVar("_T") + + +class TestRunner(metaclass=ABCMeta): + """ + Encapsulates a running event loop. Every call made through this object will use the + same event loop. + """ + + def __enter__(self) -> TestRunner: + return self + + @abstractmethod + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: types.TracebackType | None, + ) -> bool | None: ... + + @abstractmethod + def run_asyncgen_fixture( + self, + fixture_func: Callable[..., AsyncGenerator[_T, Any]], + kwargs: dict[str, Any], + ) -> Iterable[_T]: + """ + Run an async generator fixture. + + :param fixture_func: the fixture function + :param kwargs: keyword arguments to call the fixture function with + :return: an iterator yielding the value yielded from the async generator + """ + + @abstractmethod + def run_fixture( + self, + fixture_func: Callable[..., Coroutine[Any, Any, _T]], + kwargs: dict[str, Any], + ) -> _T: + """ + Run an async fixture. + + :param fixture_func: the fixture function + :param kwargs: keyword arguments to call the fixture function with + :return: the return value of the fixture function + """ + + @abstractmethod + def run_test( + self, test_func: Callable[..., Coroutine[Any, Any, Any]], kwargs: dict[str, Any] + ) -> None: + """ + Run an async test function. + + :param test_func: the test function + :param kwargs: keyword arguments to call the test function with + """ diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/from_thread.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/from_thread.py new file mode 100644 index 0000000..837de5e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/from_thread.py @@ -0,0 +1,578 @@ +from __future__ import annotations + +__all__ = ( + "BlockingPortal", + "BlockingPortalProvider", + "check_cancelled", + "run", + "run_sync", + "start_blocking_portal", +) + +import sys +from collections.abc import Awaitable, Callable, Generator +from concurrent.futures import Future +from contextlib import ( + AbstractAsyncContextManager, + AbstractContextManager, + contextmanager, +) +from dataclasses import dataclass, field +from functools import partial +from inspect import isawaitable +from threading import Lock, Thread, current_thread, get_ident +from types import TracebackType +from typing import ( + Any, + Generic, + TypeVar, + cast, + overload, +) + +from ._core._eventloop import ( + get_cancelled_exc_class, + threadlocals, +) +from ._core._eventloop import run as run_eventloop +from ._core._exceptions import NoEventLoopError +from ._core._synchronization import Event +from ._core._tasks import CancelScope, create_task_group +from .abc._tasks import TaskStatus +from .lowlevel import EventLoopToken, current_token + +if sys.version_info >= (3, 11): + from typing import TypeVarTuple, Unpack +else: + from typing_extensions import TypeVarTuple, Unpack + +T_Retval = TypeVar("T_Retval") +T_co = TypeVar("T_co", covariant=True) +PosArgsT = TypeVarTuple("PosArgsT") + + +def _token_or_error(token: EventLoopToken | None) -> EventLoopToken: + if token is not None: + return token + + try: + return threadlocals.current_token + except AttributeError: + raise NoEventLoopError( + "Not running inside an AnyIO worker thread, and no event loop token was " + "provided" + ) from None + + +def run( + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], + *args: Unpack[PosArgsT], + token: EventLoopToken | None = None, +) -> T_Retval: + """ + Call a coroutine function from a worker thread. + + :param func: a coroutine function + :param args: positional arguments for the callable + :param token: an event loop token to use to get back to the event loop thread + (required if calling this function from outside an AnyIO worker thread) + :return: the return value of the coroutine function + :raises MissingTokenError: if no token was provided and called from outside an + AnyIO worker thread + :raises RunFinishedError: if the event loop tied to ``token`` is no longer running + + .. versionchanged:: 4.11.0 + Added the ``token`` parameter. + + """ + explicit_token = token is not None + token = _token_or_error(token) + return token.backend_class.run_async_from_thread( + func, args, token=token.native_token if explicit_token else None + ) + + +def run_sync( + func: Callable[[Unpack[PosArgsT]], T_Retval], + *args: Unpack[PosArgsT], + token: EventLoopToken | None = None, +) -> T_Retval: + """ + Call a function in the event loop thread from a worker thread. + + :param func: a callable + :param args: positional arguments for the callable + :param token: an event loop token to use to get back to the event loop thread + (required if calling this function from outside an AnyIO worker thread) + :return: the return value of the callable + :raises MissingTokenError: if no token was provided and called from outside an + AnyIO worker thread + :raises RunFinishedError: if the event loop tied to ``token`` is no longer running + + .. versionchanged:: 4.11.0 + Added the ``token`` parameter. + + """ + explicit_token = token is not None + token = _token_or_error(token) + return token.backend_class.run_sync_from_thread( + func, args, token=token.native_token if explicit_token else None + ) + + +class _BlockingAsyncContextManager(Generic[T_co], AbstractContextManager): + _enter_future: Future[T_co] + _exit_future: Future[bool | None] + _exit_event: Event + _exit_exc_info: tuple[ + type[BaseException] | None, BaseException | None, TracebackType | None + ] = (None, None, None) + + def __init__( + self, async_cm: AbstractAsyncContextManager[T_co], portal: BlockingPortal + ): + self._async_cm = async_cm + self._portal = portal + + async def run_async_cm(self) -> bool | None: + try: + self._exit_event = Event() + value = await self._async_cm.__aenter__() + except BaseException as exc: + self._enter_future.set_exception(exc) + raise + else: + self._enter_future.set_result(value) + + try: + # Wait for the sync context manager to exit. + # This next statement can raise `get_cancelled_exc_class()` if + # something went wrong in a task group in this async context + # manager. + await self._exit_event.wait() + finally: + # In case of cancellation, it could be that we end up here before + # `_BlockingAsyncContextManager.__exit__` is called, and an + # `_exit_exc_info` has been set. + result = await self._async_cm.__aexit__(*self._exit_exc_info) + + return result + + def __enter__(self) -> T_co: + self._enter_future = Future() + self._exit_future = self._portal.start_task_soon(self.run_async_cm) + return self._enter_future.result() + + def __exit__( + self, + __exc_type: type[BaseException] | None, + __exc_value: BaseException | None, + __traceback: TracebackType | None, + ) -> bool | None: + self._exit_exc_info = __exc_type, __exc_value, __traceback + self._portal.call(self._exit_event.set) + return self._exit_future.result() + + +class _BlockingPortalTaskStatus(TaskStatus): + def __init__(self, future: Future): + self._future = future + + def started(self, value: object = None) -> None: + self._future.set_result(value) + + +class BlockingPortal: + """ + An object that lets external threads run code in an asynchronous event loop. + + :raises NoEventLoopError: if no supported asynchronous event loop is running in the + current thread + """ + + def __init__(self) -> None: + self._token = current_token() + self._event_loop_thread_id: int | None = get_ident() + self._stop_event = Event() + self._task_group = create_task_group() + + async def __aenter__(self) -> BlockingPortal: + await self._task_group.__aenter__() + return self + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> bool: + await self.stop() + return await self._task_group.__aexit__(exc_type, exc_val, exc_tb) + + def _check_running(self) -> None: + if self._event_loop_thread_id is None: + raise RuntimeError("This portal is not running") + if self._event_loop_thread_id == get_ident(): + raise RuntimeError( + "This method cannot be called from the event loop thread" + ) + + async def sleep_until_stopped(self) -> None: + """Sleep until :meth:`stop` is called.""" + await self._stop_event.wait() + + async def stop(self, cancel_remaining: bool = False) -> None: + """ + Signal the portal to shut down. + + This marks the portal as no longer accepting new calls and exits from + :meth:`sleep_until_stopped`. + + :param cancel_remaining: ``True`` to cancel all the remaining tasks, ``False`` + to let them finish before returning + + """ + self._event_loop_thread_id = None + self._stop_event.set() + if cancel_remaining: + self._task_group.cancel_scope.cancel("the blocking portal is shutting down") + + async def _call_func( + self, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval], + args: tuple[Unpack[PosArgsT]], + kwargs: dict[str, Any], + future: Future[T_Retval], + ) -> None: + def callback(f: Future[T_Retval]) -> None: + if f.cancelled(): + if self._event_loop_thread_id == get_ident(): + scope.cancel("the future was cancelled") + elif self._event_loop_thread_id is not None: + self.call(scope.cancel, "the future was cancelled") + + try: + retval_or_awaitable = func(*args, **kwargs) + if isawaitable(retval_or_awaitable): + with CancelScope() as scope: + future.add_done_callback(callback) + retval = await retval_or_awaitable + else: + retval = retval_or_awaitable + except get_cancelled_exc_class(): + future.cancel() + future.set_running_or_notify_cancel() + except BaseException as exc: + if not future.cancelled(): + future.set_exception(exc) + + # Let base exceptions fall through + if not isinstance(exc, Exception): + raise + else: + if not future.cancelled(): + future.set_result(retval) + finally: + scope = None # type: ignore[assignment] + + def _spawn_task_from_thread( + self, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval], + args: tuple[Unpack[PosArgsT]], + kwargs: dict[str, Any], + name: object, + future: Future[T_Retval], + ) -> None: + """ + Spawn a new task using the given callable. + + :param func: a callable + :param args: positional arguments to be passed to the callable + :param kwargs: keyword arguments to be passed to the callable + :param name: name of the task (will be coerced to a string if not ``None``) + :param future: a future that will resolve to the return value of the callable, + or the exception raised during its execution + + """ + run_sync( + partial(self._task_group.start_soon, name=name), + self._call_func, + func, + args, + kwargs, + future, + token=self._token, + ) + + @overload + def call( + self, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], + *args: Unpack[PosArgsT], + ) -> T_Retval: ... + + @overload + def call( + self, func: Callable[[Unpack[PosArgsT]], T_Retval], *args: Unpack[PosArgsT] + ) -> T_Retval: ... + + def call( + self, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval], + *args: Unpack[PosArgsT], + ) -> T_Retval: + """ + Call the given function in the event loop thread. + + If the callable returns a coroutine object, it is awaited on. + + :param func: any callable + :raises RuntimeError: if the portal is not running or if this method is called + from within the event loop thread + + """ + return cast(T_Retval, self.start_task_soon(func, *args).result()) + + @overload + def start_task_soon( + self, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], + *args: Unpack[PosArgsT], + name: object = None, + ) -> Future[T_Retval]: ... + + @overload + def start_task_soon( + self, + func: Callable[[Unpack[PosArgsT]], T_Retval], + *args: Unpack[PosArgsT], + name: object = None, + ) -> Future[T_Retval]: ... + + def start_task_soon( + self, + func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval], + *args: Unpack[PosArgsT], + name: object = None, + ) -> Future[T_Retval]: + """ + Start a task in the portal's task group. + + The task will be run inside a cancel scope which can be cancelled by cancelling + the returned future. + + :param func: the target function + :param args: positional arguments passed to ``func`` + :param name: name of the task (will be coerced to a string if not ``None``) + :return: a future that resolves with the return value of the callable if the + task completes successfully, or with the exception raised in the task + :raises RuntimeError: if the portal is not running or if this method is called + from within the event loop thread + :rtype: concurrent.futures.Future[T_Retval] + + .. versionadded:: 3.0 + + """ + self._check_running() + f: Future[T_Retval] = Future() + self._spawn_task_from_thread(func, args, {}, name, f) + return f + + def start_task( + self, + func: Callable[..., Awaitable[T_Retval]], + *args: object, + name: object = None, + ) -> tuple[Future[T_Retval], Any]: + """ + Start a task in the portal's task group and wait until it signals for readiness. + + This method works the same way as :meth:`.abc.TaskGroup.start`. + + :param func: the target function + :param args: positional arguments passed to ``func`` + :param name: name of the task (will be coerced to a string if not ``None``) + :return: a tuple of (future, task_status_value) where the ``task_status_value`` + is the value passed to ``task_status.started()`` from within the target + function + :rtype: tuple[concurrent.futures.Future[T_Retval], Any] + + .. versionadded:: 3.0 + + """ + + def task_done(future: Future[T_Retval]) -> None: + if not task_status_future.done(): + if future.cancelled(): + task_status_future.cancel() + elif future.exception(): + task_status_future.set_exception(future.exception()) + else: + exc = RuntimeError( + "Task exited without calling task_status.started()" + ) + task_status_future.set_exception(exc) + + self._check_running() + task_status_future: Future = Future() + task_status = _BlockingPortalTaskStatus(task_status_future) + f: Future = Future() + f.add_done_callback(task_done) + self._spawn_task_from_thread(func, args, {"task_status": task_status}, name, f) + return f, task_status_future.result() + + def wrap_async_context_manager( + self, cm: AbstractAsyncContextManager[T_co] + ) -> AbstractContextManager[T_co]: + """ + Wrap an async context manager as a synchronous context manager via this portal. + + Spawns a task that will call both ``__aenter__()`` and ``__aexit__()``, stopping + in the middle until the synchronous context manager exits. + + :param cm: an asynchronous context manager + :return: a synchronous context manager + + .. versionadded:: 2.1 + + """ + return _BlockingAsyncContextManager(cm, self) + + +@dataclass +class BlockingPortalProvider: + """ + A manager for a blocking portal. Used as a context manager. The first thread to + enter this context manager causes a blocking portal to be started with the specific + parameters, and the last thread to exit causes the portal to be shut down. Thus, + there will be exactly one blocking portal running in this context as long as at + least one thread has entered this context manager. + + The parameters are the same as for :func:`~anyio.run`. + + :param backend: name of the backend + :param backend_options: backend options + + .. versionadded:: 4.4 + """ + + backend: str = "asyncio" + backend_options: dict[str, Any] | None = None + _lock: Lock = field(init=False, default_factory=Lock) + _leases: int = field(init=False, default=0) + _portal: BlockingPortal = field(init=False) + _portal_cm: AbstractContextManager[BlockingPortal] | None = field( + init=False, default=None + ) + + def __enter__(self) -> BlockingPortal: + with self._lock: + if self._portal_cm is None: + self._portal_cm = start_blocking_portal( + self.backend, self.backend_options + ) + self._portal = self._portal_cm.__enter__() + + self._leases += 1 + return self._portal + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + portal_cm: AbstractContextManager[BlockingPortal] | None = None + with self._lock: + assert self._portal_cm + assert self._leases > 0 + self._leases -= 1 + if not self._leases: + portal_cm = self._portal_cm + self._portal_cm = None + del self._portal + + if portal_cm: + portal_cm.__exit__(None, None, None) + + +@contextmanager +def start_blocking_portal( + backend: str = "asyncio", + backend_options: dict[str, Any] | None = None, + *, + name: str | None = None, +) -> Generator[BlockingPortal, Any, None]: + """ + Start a new event loop in a new thread and run a blocking portal in its main task. + + The parameters are the same as for :func:`~anyio.run`. + + :param backend: name of the backend + :param backend_options: backend options + :param name: name of the thread + :return: a context manager that yields a blocking portal + + .. versionchanged:: 3.0 + Usage as a context manager is now required. + + """ + + async def run_portal() -> None: + async with BlockingPortal() as portal_: + if name is None: + current_thread().name = f"{backend}-portal-{id(portal_):x}" + + future.set_result(portal_) + await portal_.sleep_until_stopped() + + def run_blocking_portal() -> None: + if future.set_running_or_notify_cancel(): + try: + run_eventloop( + run_portal, backend=backend, backend_options=backend_options + ) + except BaseException as exc: + if not future.done(): + future.set_exception(exc) + + future: Future[BlockingPortal] = Future() + thread = Thread(target=run_blocking_portal, daemon=True, name=name) + thread.start() + try: + cancel_remaining_tasks = False + portal = future.result() + try: + yield portal + except BaseException: + cancel_remaining_tasks = True + raise + finally: + try: + portal.call(portal.stop, cancel_remaining_tasks) + except RuntimeError: + pass + finally: + thread.join() + + +def check_cancelled() -> None: + """ + Check if the cancel scope of the host task's running the current worker thread has + been cancelled. + + If the host task's current cancel scope has indeed been cancelled, the + backend-specific cancellation exception will be raised. + + :raises RuntimeError: if the current thread was not spawned by + :func:`.to_thread.run_sync` + + """ + try: + token: EventLoopToken = threadlocals.current_token + except AttributeError: + raise NoEventLoopError( + "This function can only be called inside an AnyIO worker thread" + ) from None + + token.backend_class.check_cancelled() diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/functools.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/functools.py new file mode 100644 index 0000000..b80afe6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/functools.py @@ -0,0 +1,375 @@ +from __future__ import annotations + +__all__ = ( + "AsyncCacheInfo", + "AsyncCacheParameters", + "AsyncLRUCacheWrapper", + "cache", + "lru_cache", + "reduce", +) + +import functools +import sys +from collections import OrderedDict +from collections.abc import ( + AsyncIterable, + Awaitable, + Callable, + Coroutine, + Hashable, + Iterable, +) +from functools import update_wrapper +from inspect import iscoroutinefunction +from typing import ( + Any, + Generic, + NamedTuple, + TypedDict, + TypeVar, + cast, + final, + overload, +) +from weakref import WeakKeyDictionary + +from ._core._synchronization import Lock +from .lowlevel import RunVar, checkpoint + +if sys.version_info >= (3, 11): + from typing import ParamSpec +else: + from typing_extensions import ParamSpec + +T = TypeVar("T") +S = TypeVar("S") +P = ParamSpec("P") +lru_cache_items: RunVar[ + WeakKeyDictionary[ + AsyncLRUCacheWrapper[Any, Any], + OrderedDict[Hashable, tuple[_InitialMissingType, Lock] | tuple[Any, None]], + ] +] = RunVar("lru_cache_items") + + +class _InitialMissingType: + pass + + +initial_missing: _InitialMissingType = _InitialMissingType() + + +class AsyncCacheInfo(NamedTuple): + hits: int + misses: int + maxsize: int | None + currsize: int + + +class AsyncCacheParameters(TypedDict): + maxsize: int | None + typed: bool + always_checkpoint: bool + + +class _LRUMethodWrapper(Generic[T]): + def __init__(self, wrapper: AsyncLRUCacheWrapper[..., T], instance: object): + self.__wrapper = wrapper + self.__instance = instance + + def cache_info(self) -> AsyncCacheInfo: + return self.__wrapper.cache_info() + + def cache_parameters(self) -> AsyncCacheParameters: + return self.__wrapper.cache_parameters() + + def cache_clear(self) -> None: + self.__wrapper.cache_clear() + + async def __call__(self, *args: Any, **kwargs: Any) -> T: + if self.__instance is None: + return await self.__wrapper(*args, **kwargs) + + return await self.__wrapper(self.__instance, *args, **kwargs) + + +@final +class AsyncLRUCacheWrapper(Generic[P, T]): + def __init__( + self, + func: Callable[P, Awaitable[T]], + maxsize: int | None, + typed: bool, + always_checkpoint: bool, + ): + self.__wrapped__ = func + self._hits: int = 0 + self._misses: int = 0 + self._maxsize = max(maxsize, 0) if maxsize is not None else None + self._currsize: int = 0 + self._typed = typed + self._always_checkpoint = always_checkpoint + update_wrapper(self, func) + + def cache_info(self) -> AsyncCacheInfo: + return AsyncCacheInfo(self._hits, self._misses, self._maxsize, self._currsize) + + def cache_parameters(self) -> AsyncCacheParameters: + return { + "maxsize": self._maxsize, + "typed": self._typed, + "always_checkpoint": self._always_checkpoint, + } + + def cache_clear(self) -> None: + if cache := lru_cache_items.get(None): + cache.pop(self, None) + self._hits = self._misses = self._currsize = 0 + + async def __call__(self, *args: P.args, **kwargs: P.kwargs) -> T: + # Easy case first: if maxsize == 0, no caching is done + if self._maxsize == 0: + value = await self.__wrapped__(*args, **kwargs) + self._misses += 1 + return value + + # The key is constructed as a flat tuple to avoid memory overhead + key: tuple[Any, ...] = args + if kwargs: + # initial_missing is used as a separator + key += (initial_missing,) + sum(kwargs.items(), ()) + + if self._typed: + key += tuple(type(arg) for arg in args) + if kwargs: + key += (initial_missing,) + tuple(type(val) for val in kwargs.values()) + + try: + cache = lru_cache_items.get() + except LookupError: + cache = WeakKeyDictionary() + lru_cache_items.set(cache) + + try: + cache_entry = cache[self] + except KeyError: + cache_entry = cache[self] = OrderedDict() + + cached_value: T | _InitialMissingType + try: + cached_value, lock = cache_entry[key] + except KeyError: + # We're the first task to call this function + cached_value, lock = ( + initial_missing, + Lock(fast_acquire=not self._always_checkpoint), + ) + cache_entry[key] = cached_value, lock + + if lock is None: + # The value was already cached + self._hits += 1 + cache_entry.move_to_end(key) + if self._always_checkpoint: + await checkpoint() + + return cast(T, cached_value) + + async with lock: + # Check if another task filled the cache while we acquired the lock + if (cached_value := cache_entry[key][0]) is initial_missing: + self._misses += 1 + if self._maxsize is not None and self._currsize >= self._maxsize: + cache_entry.popitem(last=False) + else: + self._currsize += 1 + + value = await self.__wrapped__(*args, **kwargs) + cache_entry[key] = value, None + else: + # Another task filled the cache while we were waiting for the lock + self._hits += 1 + cache_entry.move_to_end(key) + value = cast(T, cached_value) + + return value + + def __get__( + self, instance: object, owner: type | None = None + ) -> _LRUMethodWrapper[T]: + wrapper = _LRUMethodWrapper(self, instance) + update_wrapper(wrapper, self.__wrapped__) + return wrapper + + +class _LRUCacheWrapper(Generic[T]): + def __init__(self, maxsize: int | None, typed: bool, always_checkpoint: bool): + self._maxsize = maxsize + self._typed = typed + self._always_checkpoint = always_checkpoint + + @overload + def __call__( # type: ignore[overload-overlap] + self, func: Callable[P, Coroutine[Any, Any, T]], / + ) -> AsyncLRUCacheWrapper[P, T]: ... + + @overload + def __call__( + self, func: Callable[..., T], / + ) -> functools._lru_cache_wrapper[T]: ... + + def __call__( + self, f: Callable[P, Coroutine[Any, Any, T]] | Callable[..., T], / + ) -> AsyncLRUCacheWrapper[P, T] | functools._lru_cache_wrapper[T]: + if iscoroutinefunction(f): + return AsyncLRUCacheWrapper( + f, self._maxsize, self._typed, self._always_checkpoint + ) + + return functools.lru_cache(maxsize=self._maxsize, typed=self._typed)(f) # type: ignore[arg-type] + + +@overload +def cache( # type: ignore[overload-overlap] + func: Callable[P, Coroutine[Any, Any, T]], / +) -> AsyncLRUCacheWrapper[P, T]: ... + + +@overload +def cache(func: Callable[..., T], /) -> functools._lru_cache_wrapper[T]: ... + + +def cache( + func: Callable[..., T] | Callable[P, Coroutine[Any, Any, T]], / +) -> AsyncLRUCacheWrapper[P, T] | functools._lru_cache_wrapper[T]: + """ + A convenient shortcut for :func:`lru_cache` with ``maxsize=None``. + + This is the asynchronous equivalent to :func:`functools.cache`. + + """ + return lru_cache(maxsize=None)(func) + + +@overload +def lru_cache( + *, maxsize: int | None = ..., typed: bool = ..., always_checkpoint: bool = ... +) -> _LRUCacheWrapper[Any]: ... + + +@overload +def lru_cache( # type: ignore[overload-overlap] + func: Callable[P, Coroutine[Any, Any, T]], / +) -> AsyncLRUCacheWrapper[P, T]: ... + + +@overload +def lru_cache(func: Callable[..., T], /) -> functools._lru_cache_wrapper[T]: ... + + +def lru_cache( + func: Callable[P, Coroutine[Any, Any, T]] | Callable[..., T] | None = None, + /, + *, + maxsize: int | None = 128, + typed: bool = False, + always_checkpoint: bool = False, +) -> ( + AsyncLRUCacheWrapper[P, T] | functools._lru_cache_wrapper[T] | _LRUCacheWrapper[Any] +): + """ + An asynchronous version of :func:`functools.lru_cache`. + + If a synchronous function is passed, the standard library + :func:`functools.lru_cache` is applied instead. + + :param always_checkpoint: if ``True``, every call to the cached function will be + guaranteed to yield control to the event loop at least once + + .. note:: Caches and locks are managed on a per-event loop basis. + + """ + if func is None: + return _LRUCacheWrapper[Any](maxsize, typed, always_checkpoint) + + if not callable(func): + raise TypeError("the first argument must be callable") + + return _LRUCacheWrapper[T](maxsize, typed, always_checkpoint)(func) + + +@overload +async def reduce( + function: Callable[[T, S], Awaitable[T]], + iterable: Iterable[S] | AsyncIterable[S], + /, + initial: T, +) -> T: ... + + +@overload +async def reduce( + function: Callable[[T, T], Awaitable[T]], + iterable: Iterable[T] | AsyncIterable[T], + /, +) -> T: ... + + +async def reduce( # type: ignore[misc] + function: Callable[[T, T], Awaitable[T]] | Callable[[T, S], Awaitable[T]], + iterable: Iterable[T] | Iterable[S] | AsyncIterable[T] | AsyncIterable[S], + /, + initial: T | _InitialMissingType = initial_missing, +) -> T: + """ + Asynchronous version of :func:`functools.reduce`. + + :param function: a coroutine function that takes two arguments: the accumulated + value and the next element from the iterable + :param iterable: an iterable or async iterable + :param initial: the initial value (if missing, the first element of the iterable is + used as the initial value) + + """ + element: Any + function_called = False + if isinstance(iterable, AsyncIterable): + async_it = iterable.__aiter__() + if initial is initial_missing: + try: + value = cast(T, await async_it.__anext__()) + except StopAsyncIteration: + raise TypeError( + "reduce() of empty sequence with no initial value" + ) from None + else: + value = cast(T, initial) + + async for element in async_it: + value = await function(value, element) + function_called = True + elif isinstance(iterable, Iterable): + it = iter(iterable) + if initial is initial_missing: + try: + value = cast(T, next(it)) + except StopIteration: + raise TypeError( + "reduce() of empty sequence with no initial value" + ) from None + else: + value = cast(T, initial) + + for element in it: + value = await function(value, element) + function_called = True + else: + raise TypeError("reduce() argument 2 must be an iterable or async iterable") + + # Make sure there is at least one checkpoint, even if an empty iterable and an + # initial value were given + if not function_called: + await checkpoint() + + return value diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/lowlevel.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/lowlevel.py new file mode 100644 index 0000000..ffbb75a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/lowlevel.py @@ -0,0 +1,196 @@ +from __future__ import annotations + +__all__ = ( + "EventLoopToken", + "RunvarToken", + "RunVar", + "checkpoint", + "checkpoint_if_cancelled", + "cancel_shielded_checkpoint", + "current_token", +) + +import enum +from dataclasses import dataclass +from types import TracebackType +from typing import Any, Generic, Literal, TypeVar, final, overload +from weakref import WeakKeyDictionary + +from ._core._eventloop import get_async_backend +from .abc import AsyncBackend + +T = TypeVar("T") +D = TypeVar("D") + + +async def checkpoint() -> None: + """ + Check for cancellation and allow the scheduler to switch to another task. + + Equivalent to (but more efficient than):: + + await checkpoint_if_cancelled() + await cancel_shielded_checkpoint() + + .. versionadded:: 3.0 + + """ + await get_async_backend().checkpoint() + + +async def checkpoint_if_cancelled() -> None: + """ + Enter a checkpoint if the enclosing cancel scope has been cancelled. + + This does not allow the scheduler to switch to a different task. + + .. versionadded:: 3.0 + + """ + await get_async_backend().checkpoint_if_cancelled() + + +async def cancel_shielded_checkpoint() -> None: + """ + Allow the scheduler to switch to another task but without checking for cancellation. + + Equivalent to (but potentially more efficient than):: + + with CancelScope(shield=True): + await checkpoint() + + .. versionadded:: 3.0 + + """ + await get_async_backend().cancel_shielded_checkpoint() + + +@final +@dataclass(frozen=True, repr=False) +class EventLoopToken: + """ + An opaque object that holds a reference to an event loop. + + .. versionadded:: 4.11.0 + """ + + backend_class: type[AsyncBackend] + native_token: object + + +def current_token() -> EventLoopToken: + """ + Return a token object that can be used to call code in the current event loop from + another thread. + + :raises NoEventLoopError: if no supported asynchronous event loop is running in the + current thread + + .. versionadded:: 4.11.0 + + """ + backend_class = get_async_backend() + raw_token = backend_class.current_token() + return EventLoopToken(backend_class, raw_token) + + +_run_vars: WeakKeyDictionary[object, dict[RunVar[Any], Any]] = WeakKeyDictionary() + + +class _NoValueSet(enum.Enum): + NO_VALUE_SET = enum.auto() + + +class RunvarToken(Generic[T]): + __slots__ = "_var", "_value", "_redeemed" + + def __init__(self, var: RunVar[T], value: T | Literal[_NoValueSet.NO_VALUE_SET]): + self._var = var + self._value: T | Literal[_NoValueSet.NO_VALUE_SET] = value + self._redeemed = False + + def __enter__(self) -> RunvarToken[T]: + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + self._var.reset(self) + + +class RunVar(Generic[T]): + """ + Like a :class:`~contextvars.ContextVar`, except scoped to the running event loop. + + Can be used as a context manager, Just like :class:`~contextvars.ContextVar`, that + will reset the variable to its previous value when the context block is exited. + """ + + __slots__ = "_name", "_default" + + NO_VALUE_SET: Literal[_NoValueSet.NO_VALUE_SET] = _NoValueSet.NO_VALUE_SET + + def __init__( + self, name: str, default: T | Literal[_NoValueSet.NO_VALUE_SET] = NO_VALUE_SET + ): + self._name = name + self._default = default + + @property + def _current_vars(self) -> dict[RunVar[T], T]: + native_token = current_token().native_token + try: + return _run_vars[native_token] + except KeyError: + run_vars = _run_vars[native_token] = {} + return run_vars + + @overload + def get(self, default: D) -> T | D: ... + + @overload + def get(self) -> T: ... + + def get( + self, default: D | Literal[_NoValueSet.NO_VALUE_SET] = NO_VALUE_SET + ) -> T | D: + try: + return self._current_vars[self] + except KeyError: + if default is not RunVar.NO_VALUE_SET: + return default + elif self._default is not RunVar.NO_VALUE_SET: + return self._default + + raise LookupError( + f'Run variable "{self._name}" has no value and no default set' + ) + + def set(self, value: T) -> RunvarToken[T]: + current_vars = self._current_vars + token = RunvarToken(self, current_vars.get(self, RunVar.NO_VALUE_SET)) + current_vars[self] = value + return token + + def reset(self, token: RunvarToken[T]) -> None: + if token._var is not self: + raise ValueError("This token does not belong to this RunVar") + + if token._redeemed: + raise ValueError("This token has already been used") + + if token._value is _NoValueSet.NO_VALUE_SET: + try: + del self._current_vars[self] + except KeyError: + pass + else: + self._current_vars[self] = token._value + + token._redeemed = True + + def __repr__(self) -> str: + return f"" diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/py.typed b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/pytest_plugin.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/pytest_plugin.py new file mode 100644 index 0000000..4222816 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/pytest_plugin.py @@ -0,0 +1,302 @@ +from __future__ import annotations + +import socket +import sys +from collections.abc import Callable, Generator, Iterator +from contextlib import ExitStack, contextmanager +from inspect import isasyncgenfunction, iscoroutinefunction, ismethod +from typing import Any, cast + +import pytest +from _pytest.fixtures import SubRequest +from _pytest.outcomes import Exit + +from . import get_available_backends +from ._core._eventloop import ( + current_async_library, + get_async_backend, + reset_current_async_library, + set_current_async_library, +) +from ._core._exceptions import iterate_exceptions +from .abc import TestRunner + +if sys.version_info < (3, 11): + from exceptiongroup import ExceptionGroup + +_current_runner: TestRunner | None = None +_runner_stack: ExitStack | None = None +_runner_leases = 0 + + +def extract_backend_and_options(backend: object) -> tuple[str, dict[str, Any]]: + if isinstance(backend, str): + return backend, {} + elif isinstance(backend, tuple) and len(backend) == 2: + if isinstance(backend[0], str) and isinstance(backend[1], dict): + return cast(tuple[str, dict[str, Any]], backend) + + raise TypeError("anyio_backend must be either a string or tuple of (string, dict)") + + +@contextmanager +def get_runner( + backend_name: str, backend_options: dict[str, Any] +) -> Iterator[TestRunner]: + global _current_runner, _runner_leases, _runner_stack + if _current_runner is None: + asynclib = get_async_backend(backend_name) + _runner_stack = ExitStack() + if current_async_library() is None: + # Since we're in control of the event loop, we can cache the name of the + # async library + token = set_current_async_library(backend_name) + _runner_stack.callback(reset_current_async_library, token) + + backend_options = backend_options or {} + _current_runner = _runner_stack.enter_context( + asynclib.create_test_runner(backend_options) + ) + + _runner_leases += 1 + try: + yield _current_runner + finally: + _runner_leases -= 1 + if not _runner_leases: + assert _runner_stack is not None + _runner_stack.close() + _runner_stack = _current_runner = None + + +def pytest_addoption(parser: pytest.Parser) -> None: + parser.addini( + "anyio_mode", + default="strict", + help='AnyIO plugin mode (either "strict" or "auto")', + ) + + +def pytest_configure(config: pytest.Config) -> None: + config.addinivalue_line( + "markers", + "anyio: mark the (coroutine function) test to be run asynchronously via anyio.", + ) + if ( + config.getini("anyio_mode") == "auto" + and config.pluginmanager.has_plugin("asyncio") + and config.getini("asyncio_mode") == "auto" + ): + config.issue_config_time_warning( + pytest.PytestConfigWarning( + "AnyIO auto mode has been enabled together with pytest-asyncio auto " + "mode. This may cause unexpected behavior." + ), + 1, + ) + + +@pytest.hookimpl(hookwrapper=True) +def pytest_fixture_setup(fixturedef: Any, request: Any) -> Generator[Any]: + def wrapper(anyio_backend: Any, request: SubRequest, **kwargs: Any) -> Any: + # Rebind any fixture methods to the request instance + if ( + request.instance + and ismethod(func) + and type(func.__self__) is type(request.instance) + ): + local_func = func.__func__.__get__(request.instance) + else: + local_func = func + + backend_name, backend_options = extract_backend_and_options(anyio_backend) + if has_backend_arg: + kwargs["anyio_backend"] = anyio_backend + + if has_request_arg: + kwargs["request"] = request + + with get_runner(backend_name, backend_options) as runner: + if isasyncgenfunction(local_func): + yield from runner.run_asyncgen_fixture(local_func, kwargs) + else: + yield runner.run_fixture(local_func, kwargs) + + # Only apply this to coroutine functions and async generator functions in requests + # that involve the anyio_backend fixture + func = fixturedef.func + if isasyncgenfunction(func) or iscoroutinefunction(func): + if "anyio_backend" in request.fixturenames: + fixturedef.func = wrapper + original_argname = fixturedef.argnames + + if not (has_backend_arg := "anyio_backend" in fixturedef.argnames): + fixturedef.argnames += ("anyio_backend",) + + if not (has_request_arg := "request" in fixturedef.argnames): + fixturedef.argnames += ("request",) + + try: + return (yield) + finally: + fixturedef.func = func + fixturedef.argnames = original_argname + + return (yield) + + +@pytest.hookimpl(tryfirst=True) +def pytest_pycollect_makeitem( + collector: pytest.Module | pytest.Class, name: str, obj: object +) -> None: + if collector.istestfunction(obj, name): + inner_func = obj.hypothesis.inner_test if hasattr(obj, "hypothesis") else obj + if iscoroutinefunction(inner_func): + anyio_auto_mode = collector.config.getini("anyio_mode") == "auto" + marker = collector.get_closest_marker("anyio") + own_markers = getattr(obj, "pytestmark", ()) + if ( + anyio_auto_mode + or marker + or any(marker.name == "anyio" for marker in own_markers) + ): + pytest.mark.usefixtures("anyio_backend")(obj) + + +@pytest.hookimpl(tryfirst=True) +def pytest_pyfunc_call(pyfuncitem: Any) -> bool | None: + def run_with_hypothesis(**kwargs: Any) -> None: + with get_runner(backend_name, backend_options) as runner: + runner.run_test(original_func, kwargs) + + backend = pyfuncitem.funcargs.get("anyio_backend") + if backend: + backend_name, backend_options = extract_backend_and_options(backend) + + if hasattr(pyfuncitem.obj, "hypothesis"): + # Wrap the inner test function unless it's already wrapped + original_func = pyfuncitem.obj.hypothesis.inner_test + if original_func.__qualname__ != run_with_hypothesis.__qualname__: + if iscoroutinefunction(original_func): + pyfuncitem.obj.hypothesis.inner_test = run_with_hypothesis + + return None + + if iscoroutinefunction(pyfuncitem.obj): + funcargs = pyfuncitem.funcargs + testargs = {arg: funcargs[arg] for arg in pyfuncitem._fixtureinfo.argnames} + with get_runner(backend_name, backend_options) as runner: + try: + runner.run_test(pyfuncitem.obj, testargs) + except ExceptionGroup as excgrp: + for exc in iterate_exceptions(excgrp): + if isinstance(exc, (Exit, KeyboardInterrupt, SystemExit)): + raise exc from excgrp + + raise + + return True + + return None + + +@pytest.fixture(scope="module", params=get_available_backends()) +def anyio_backend(request: Any) -> Any: + return request.param + + +@pytest.fixture +def anyio_backend_name(anyio_backend: Any) -> str: + if isinstance(anyio_backend, str): + return anyio_backend + else: + return anyio_backend[0] + + +@pytest.fixture +def anyio_backend_options(anyio_backend: Any) -> dict[str, Any]: + if isinstance(anyio_backend, str): + return {} + else: + return anyio_backend[1] + + +class FreePortFactory: + """ + Manages port generation based on specified socket kind, ensuring no duplicate + ports are generated. + + This class provides functionality for generating available free ports on the + system. It is initialized with a specific socket kind and can generate ports + for given address families while avoiding reuse of previously generated ports. + + Users should not instantiate this class directly, but use the + ``free_tcp_port_factory`` and ``free_udp_port_factory`` fixtures instead. For simple + uses cases, ``free_tcp_port`` and ``free_udp_port`` can be used instead. + """ + + def __init__(self, kind: socket.SocketKind) -> None: + self._kind = kind + self._generated = set[int]() + + @property + def kind(self) -> socket.SocketKind: + """ + The type of socket connection (e.g., :data:`~socket.SOCK_STREAM` or + :data:`~socket.SOCK_DGRAM`) used to bind for checking port availability + + """ + return self._kind + + def __call__(self, family: socket.AddressFamily | None = None) -> int: + """ + Return an unbound port for the given address family. + + :param family: if omitted, both IPv4 and IPv6 addresses will be tried + :return: a port number + + """ + if family is not None: + families = [family] + else: + families = [socket.AF_INET] + if socket.has_ipv6: + families.append(socket.AF_INET6) + + while True: + port = 0 + with ExitStack() as stack: + for family in families: + sock = stack.enter_context(socket.socket(family, self._kind)) + addr = "::1" if family == socket.AF_INET6 else "127.0.0.1" + try: + sock.bind((addr, port)) + except OSError: + break + + if not port: + port = sock.getsockname()[1] + else: + if port not in self._generated: + self._generated.add(port) + return port + + +@pytest.fixture(scope="session") +def free_tcp_port_factory() -> FreePortFactory: + return FreePortFactory(socket.SOCK_STREAM) + + +@pytest.fixture(scope="session") +def free_udp_port_factory() -> FreePortFactory: + return FreePortFactory(socket.SOCK_DGRAM) + + +@pytest.fixture +def free_tcp_port(free_tcp_port_factory: Callable[[], int]) -> int: + return free_tcp_port_factory() + + +@pytest.fixture +def free_udp_port(free_udp_port_factory: Callable[[], int]) -> int: + return free_udp_port_factory() diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/streams/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/streams/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/streams/buffered.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/streams/buffered.py new file mode 100644 index 0000000..57c7cd7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/streams/buffered.py @@ -0,0 +1,188 @@ +from __future__ import annotations + +__all__ = ( + "BufferedByteReceiveStream", + "BufferedByteStream", + "BufferedConnectable", +) + +import sys +from collections.abc import Callable, Iterable, Mapping +from dataclasses import dataclass, field +from typing import Any, SupportsIndex + +from .. import ClosedResourceError, DelimiterNotFound, EndOfStream, IncompleteRead +from ..abc import ( + AnyByteReceiveStream, + AnyByteStream, + AnyByteStreamConnectable, + ByteReceiveStream, + ByteStream, + ByteStreamConnectable, +) + +if sys.version_info >= (3, 12): + from typing import override +else: + from typing_extensions import override + + +@dataclass(eq=False) +class BufferedByteReceiveStream(ByteReceiveStream): + """ + Wraps any bytes-based receive stream and uses a buffer to provide sophisticated + receiving capabilities in the form of a byte stream. + """ + + receive_stream: AnyByteReceiveStream + _buffer: bytearray = field(init=False, default_factory=bytearray) + _closed: bool = field(init=False, default=False) + + async def aclose(self) -> None: + await self.receive_stream.aclose() + self._closed = True + + @property + def buffer(self) -> bytes: + """The bytes currently in the buffer.""" + return bytes(self._buffer) + + @property + def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: + return self.receive_stream.extra_attributes + + def feed_data(self, data: Iterable[SupportsIndex], /) -> None: + """ + Append data directly into the buffer. + + Any data in the buffer will be consumed by receive operations before receiving + anything from the wrapped stream. + + :param data: the data to append to the buffer (can be bytes or anything else + that supports ``__index__()``) + + """ + self._buffer.extend(data) + + async def receive(self, max_bytes: int = 65536) -> bytes: + if self._closed: + raise ClosedResourceError + + if self._buffer: + chunk = bytes(self._buffer[:max_bytes]) + del self._buffer[:max_bytes] + return chunk + elif isinstance(self.receive_stream, ByteReceiveStream): + return await self.receive_stream.receive(max_bytes) + else: + # With a bytes-oriented object stream, we need to handle any surplus bytes + # we get from the receive() call + chunk = await self.receive_stream.receive() + if len(chunk) > max_bytes: + # Save the surplus bytes in the buffer + self._buffer.extend(chunk[max_bytes:]) + return chunk[:max_bytes] + else: + return chunk + + async def receive_exactly(self, nbytes: int) -> bytes: + """ + Read exactly the given amount of bytes from the stream. + + :param nbytes: the number of bytes to read + :return: the bytes read + :raises ~anyio.IncompleteRead: if the stream was closed before the requested + amount of bytes could be read from the stream + + """ + while True: + remaining = nbytes - len(self._buffer) + if remaining <= 0: + retval = self._buffer[:nbytes] + del self._buffer[:nbytes] + return bytes(retval) + + try: + if isinstance(self.receive_stream, ByteReceiveStream): + chunk = await self.receive_stream.receive(remaining) + else: + chunk = await self.receive_stream.receive() + except EndOfStream as exc: + raise IncompleteRead from exc + + self._buffer.extend(chunk) + + async def receive_until(self, delimiter: bytes, max_bytes: int) -> bytes: + """ + Read from the stream until the delimiter is found or max_bytes have been read. + + :param delimiter: the marker to look for in the stream + :param max_bytes: maximum number of bytes that will be read before raising + :exc:`~anyio.DelimiterNotFound` + :return: the bytes read (not including the delimiter) + :raises ~anyio.IncompleteRead: if the stream was closed before the delimiter + was found + :raises ~anyio.DelimiterNotFound: if the delimiter is not found within the + bytes read up to the maximum allowed + + """ + delimiter_size = len(delimiter) + offset = 0 + while True: + # Check if the delimiter can be found in the current buffer + index = self._buffer.find(delimiter, offset) + if index >= 0: + found = self._buffer[:index] + del self._buffer[: index + len(delimiter) :] + return bytes(found) + + # Check if the buffer is already at or over the limit + if len(self._buffer) >= max_bytes: + raise DelimiterNotFound(max_bytes) + + # Read more data into the buffer from the socket + try: + data = await self.receive_stream.receive() + except EndOfStream as exc: + raise IncompleteRead from exc + + # Move the offset forward and add the new data to the buffer + offset = max(len(self._buffer) - delimiter_size + 1, 0) + self._buffer.extend(data) + + +class BufferedByteStream(BufferedByteReceiveStream, ByteStream): + """ + A full-duplex variant of :class:`BufferedByteReceiveStream`. All writes are passed + through to the wrapped stream as-is. + """ + + def __init__(self, stream: AnyByteStream): + """ + :param stream: the stream to be wrapped + + """ + super().__init__(stream) + self._stream = stream + + @override + async def send_eof(self) -> None: + await self._stream.send_eof() + + @override + async def send(self, item: bytes) -> None: + await self._stream.send(item) + + +class BufferedConnectable(ByteStreamConnectable): + def __init__(self, connectable: AnyByteStreamConnectable): + """ + :param connectable: the connectable to wrap + + """ + self.connectable = connectable + + @override + async def connect(self) -> BufferedByteStream: + stream = await self.connectable.connect() + return BufferedByteStream(stream) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/streams/file.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/streams/file.py new file mode 100644 index 0000000..82d2da8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/streams/file.py @@ -0,0 +1,154 @@ +from __future__ import annotations + +__all__ = ( + "FileReadStream", + "FileStreamAttribute", + "FileWriteStream", +) + +from collections.abc import Callable, Mapping +from io import SEEK_SET, UnsupportedOperation +from os import PathLike +from pathlib import Path +from typing import Any, BinaryIO, cast + +from .. import ( + BrokenResourceError, + ClosedResourceError, + EndOfStream, + TypedAttributeSet, + to_thread, + typed_attribute, +) +from ..abc import ByteReceiveStream, ByteSendStream + + +class FileStreamAttribute(TypedAttributeSet): + #: the open file descriptor + file: BinaryIO = typed_attribute() + #: the path of the file on the file system, if available (file must be a real file) + path: Path = typed_attribute() + #: the file number, if available (file must be a real file or a TTY) + fileno: int = typed_attribute() + + +class _BaseFileStream: + def __init__(self, file: BinaryIO): + self._file = file + + async def aclose(self) -> None: + await to_thread.run_sync(self._file.close) + + @property + def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: + attributes: dict[Any, Callable[[], Any]] = { + FileStreamAttribute.file: lambda: self._file, + } + + if hasattr(self._file, "name"): + attributes[FileStreamAttribute.path] = lambda: Path(self._file.name) + + try: + self._file.fileno() + except UnsupportedOperation: + pass + else: + attributes[FileStreamAttribute.fileno] = lambda: self._file.fileno() + + return attributes + + +class FileReadStream(_BaseFileStream, ByteReceiveStream): + """ + A byte stream that reads from a file in the file system. + + :param file: a file that has been opened for reading in binary mode + + .. versionadded:: 3.0 + """ + + @classmethod + async def from_path(cls, path: str | PathLike[str]) -> FileReadStream: + """ + Create a file read stream by opening the given file. + + :param path: path of the file to read from + + """ + file = await to_thread.run_sync(Path(path).open, "rb") + return cls(cast(BinaryIO, file)) + + async def receive(self, max_bytes: int = 65536) -> bytes: + try: + data = await to_thread.run_sync(self._file.read, max_bytes) + except ValueError: + raise ClosedResourceError from None + except OSError as exc: + raise BrokenResourceError from exc + + if data: + return data + else: + raise EndOfStream + + async def seek(self, position: int, whence: int = SEEK_SET) -> int: + """ + Seek the file to the given position. + + .. seealso:: :meth:`io.IOBase.seek` + + .. note:: Not all file descriptors are seekable. + + :param position: position to seek the file to + :param whence: controls how ``position`` is interpreted + :return: the new absolute position + :raises OSError: if the file is not seekable + + """ + return await to_thread.run_sync(self._file.seek, position, whence) + + async def tell(self) -> int: + """ + Return the current stream position. + + .. note:: Not all file descriptors are seekable. + + :return: the current absolute position + :raises OSError: if the file is not seekable + + """ + return await to_thread.run_sync(self._file.tell) + + +class FileWriteStream(_BaseFileStream, ByteSendStream): + """ + A byte stream that writes to a file in the file system. + + :param file: a file that has been opened for writing in binary mode + + .. versionadded:: 3.0 + """ + + @classmethod + async def from_path( + cls, path: str | PathLike[str], append: bool = False + ) -> FileWriteStream: + """ + Create a file write stream by opening the given file for writing. + + :param path: path of the file to write to + :param append: if ``True``, open the file for appending; if ``False``, any + existing file at the given path will be truncated + + """ + mode = "ab" if append else "wb" + file = await to_thread.run_sync(Path(path).open, mode) + return cls(cast(BinaryIO, file)) + + async def send(self, item: bytes) -> None: + try: + await to_thread.run_sync(self._file.write, item) + except ValueError: + raise ClosedResourceError from None + except OSError as exc: + raise BrokenResourceError from exc diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/streams/memory.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/streams/memory.py new file mode 100644 index 0000000..a3fa0c3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/streams/memory.py @@ -0,0 +1,325 @@ +from __future__ import annotations + +__all__ = ( + "MemoryObjectReceiveStream", + "MemoryObjectSendStream", + "MemoryObjectStreamStatistics", +) + +import warnings +from collections import OrderedDict, deque +from dataclasses import dataclass, field +from types import TracebackType +from typing import Generic, NamedTuple, TypeVar + +from .. import ( + BrokenResourceError, + ClosedResourceError, + EndOfStream, + WouldBlock, +) +from .._core._testing import TaskInfo, get_current_task +from ..abc import Event, ObjectReceiveStream, ObjectSendStream +from ..lowlevel import checkpoint + +T_Item = TypeVar("T_Item") +T_co = TypeVar("T_co", covariant=True) +T_contra = TypeVar("T_contra", contravariant=True) + + +class MemoryObjectStreamStatistics(NamedTuple): + current_buffer_used: int #: number of items stored in the buffer + #: maximum number of items that can be stored on this stream (or :data:`math.inf`) + max_buffer_size: float + open_send_streams: int #: number of unclosed clones of the send stream + open_receive_streams: int #: number of unclosed clones of the receive stream + #: number of tasks blocked on :meth:`MemoryObjectSendStream.send` + tasks_waiting_send: int + #: number of tasks blocked on :meth:`MemoryObjectReceiveStream.receive` + tasks_waiting_receive: int + + +@dataclass(eq=False) +class _MemoryObjectItemReceiver(Generic[T_Item]): + task_info: TaskInfo = field(init=False, default_factory=get_current_task) + item: T_Item = field(init=False) + + def __repr__(self) -> str: + # When item is not defined, we get following error with default __repr__: + # AttributeError: 'MemoryObjectItemReceiver' object has no attribute 'item' + item = getattr(self, "item", None) + return f"{self.__class__.__name__}(task_info={self.task_info}, item={item!r})" + + +@dataclass(eq=False) +class _MemoryObjectStreamState(Generic[T_Item]): + max_buffer_size: float = field() + buffer: deque[T_Item] = field(init=False, default_factory=deque) + open_send_channels: int = field(init=False, default=0) + open_receive_channels: int = field(init=False, default=0) + waiting_receivers: OrderedDict[Event, _MemoryObjectItemReceiver[T_Item]] = field( + init=False, default_factory=OrderedDict + ) + waiting_senders: OrderedDict[Event, T_Item] = field( + init=False, default_factory=OrderedDict + ) + + def statistics(self) -> MemoryObjectStreamStatistics: + return MemoryObjectStreamStatistics( + len(self.buffer), + self.max_buffer_size, + self.open_send_channels, + self.open_receive_channels, + len(self.waiting_senders), + len(self.waiting_receivers), + ) + + +@dataclass(eq=False) +class MemoryObjectReceiveStream(Generic[T_co], ObjectReceiveStream[T_co]): + _state: _MemoryObjectStreamState[T_co] + _closed: bool = field(init=False, default=False) + + def __post_init__(self) -> None: + self._state.open_receive_channels += 1 + + def receive_nowait(self) -> T_co: + """ + Receive the next item if it can be done without waiting. + + :return: the received item + :raises ~anyio.ClosedResourceError: if this send stream has been closed + :raises ~anyio.EndOfStream: if the buffer is empty and this stream has been + closed from the sending end + :raises ~anyio.WouldBlock: if there are no items in the buffer and no tasks + waiting to send + + """ + if self._closed: + raise ClosedResourceError + + if self._state.waiting_senders: + # Get the item from the next sender + send_event, item = self._state.waiting_senders.popitem(last=False) + self._state.buffer.append(item) + send_event.set() + + if self._state.buffer: + return self._state.buffer.popleft() + elif not self._state.open_send_channels: + raise EndOfStream + + raise WouldBlock + + async def receive(self) -> T_co: + await checkpoint() + try: + return self.receive_nowait() + except WouldBlock: + # Add ourselves in the queue + receive_event = Event() + receiver = _MemoryObjectItemReceiver[T_co]() + self._state.waiting_receivers[receive_event] = receiver + + try: + await receive_event.wait() + finally: + self._state.waiting_receivers.pop(receive_event, None) + + try: + return receiver.item + except AttributeError: + raise EndOfStream from None + + def clone(self) -> MemoryObjectReceiveStream[T_co]: + """ + Create a clone of this receive stream. + + Each clone can be closed separately. Only when all clones have been closed will + the receiving end of the memory stream be considered closed by the sending ends. + + :return: the cloned stream + + """ + if self._closed: + raise ClosedResourceError + + return MemoryObjectReceiveStream(_state=self._state) + + def close(self) -> None: + """ + Close the stream. + + This works the exact same way as :meth:`aclose`, but is provided as a special + case for the benefit of synchronous callbacks. + + """ + if not self._closed: + self._closed = True + self._state.open_receive_channels -= 1 + if self._state.open_receive_channels == 0: + send_events = list(self._state.waiting_senders.keys()) + for event in send_events: + event.set() + + async def aclose(self) -> None: + self.close() + + def statistics(self) -> MemoryObjectStreamStatistics: + """ + Return statistics about the current state of this stream. + + .. versionadded:: 3.0 + """ + return self._state.statistics() + + def __enter__(self) -> MemoryObjectReceiveStream[T_co]: + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + self.close() + + def __del__(self) -> None: + if not self._closed: + warnings.warn( + f"Unclosed <{self.__class__.__name__} at {id(self):x}>", + ResourceWarning, + stacklevel=1, + source=self, + ) + + +@dataclass(eq=False) +class MemoryObjectSendStream(Generic[T_contra], ObjectSendStream[T_contra]): + _state: _MemoryObjectStreamState[T_contra] + _closed: bool = field(init=False, default=False) + + def __post_init__(self) -> None: + self._state.open_send_channels += 1 + + def send_nowait(self, item: T_contra) -> None: + """ + Send an item immediately if it can be done without waiting. + + :param item: the item to send + :raises ~anyio.ClosedResourceError: if this send stream has been closed + :raises ~anyio.BrokenResourceError: if the stream has been closed from the + receiving end + :raises ~anyio.WouldBlock: if the buffer is full and there are no tasks waiting + to receive + + """ + if self._closed: + raise ClosedResourceError + if not self._state.open_receive_channels: + raise BrokenResourceError + + while self._state.waiting_receivers: + receive_event, receiver = self._state.waiting_receivers.popitem(last=False) + if not receiver.task_info.has_pending_cancellation(): + receiver.item = item + receive_event.set() + return + + if len(self._state.buffer) < self._state.max_buffer_size: + self._state.buffer.append(item) + else: + raise WouldBlock + + async def send(self, item: T_contra) -> None: + """ + Send an item to the stream. + + If the buffer is full, this method blocks until there is again room in the + buffer or the item can be sent directly to a receiver. + + :param item: the item to send + :raises ~anyio.ClosedResourceError: if this send stream has been closed + :raises ~anyio.BrokenResourceError: if the stream has been closed from the + receiving end + + """ + await checkpoint() + try: + self.send_nowait(item) + except WouldBlock: + # Wait until there's someone on the receiving end + send_event = Event() + self._state.waiting_senders[send_event] = item + try: + await send_event.wait() + except BaseException: + self._state.waiting_senders.pop(send_event, None) + raise + + if send_event in self._state.waiting_senders: + del self._state.waiting_senders[send_event] + raise BrokenResourceError from None + + def clone(self) -> MemoryObjectSendStream[T_contra]: + """ + Create a clone of this send stream. + + Each clone can be closed separately. Only when all clones have been closed will + the sending end of the memory stream be considered closed by the receiving ends. + + :return: the cloned stream + + """ + if self._closed: + raise ClosedResourceError + + return MemoryObjectSendStream(_state=self._state) + + def close(self) -> None: + """ + Close the stream. + + This works the exact same way as :meth:`aclose`, but is provided as a special + case for the benefit of synchronous callbacks. + + """ + if not self._closed: + self._closed = True + self._state.open_send_channels -= 1 + if self._state.open_send_channels == 0: + receive_events = list(self._state.waiting_receivers.keys()) + self._state.waiting_receivers.clear() + for event in receive_events: + event.set() + + async def aclose(self) -> None: + self.close() + + def statistics(self) -> MemoryObjectStreamStatistics: + """ + Return statistics about the current state of this stream. + + .. versionadded:: 3.0 + """ + return self._state.statistics() + + def __enter__(self) -> MemoryObjectSendStream[T_contra]: + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + self.close() + + def __del__(self) -> None: + if not self._closed: + warnings.warn( + f"Unclosed <{self.__class__.__name__} at {id(self):x}>", + ResourceWarning, + stacklevel=1, + source=self, + ) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/streams/stapled.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/streams/stapled.py new file mode 100644 index 0000000..9248b68 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/streams/stapled.py @@ -0,0 +1,147 @@ +from __future__ import annotations + +__all__ = ( + "MultiListener", + "StapledByteStream", + "StapledObjectStream", +) + +from collections.abc import Callable, Mapping, Sequence +from dataclasses import dataclass +from typing import Any, Generic, TypeVar + +from ..abc import ( + ByteReceiveStream, + ByteSendStream, + ByteStream, + Listener, + ObjectReceiveStream, + ObjectSendStream, + ObjectStream, + TaskGroup, +) + +T_Item = TypeVar("T_Item") +T_Stream = TypeVar("T_Stream") + + +@dataclass(eq=False) +class StapledByteStream(ByteStream): + """ + Combines two byte streams into a single, bidirectional byte stream. + + Extra attributes will be provided from both streams, with the receive stream + providing the values in case of a conflict. + + :param ByteSendStream send_stream: the sending byte stream + :param ByteReceiveStream receive_stream: the receiving byte stream + """ + + send_stream: ByteSendStream + receive_stream: ByteReceiveStream + + async def receive(self, max_bytes: int = 65536) -> bytes: + return await self.receive_stream.receive(max_bytes) + + async def send(self, item: bytes) -> None: + await self.send_stream.send(item) + + async def send_eof(self) -> None: + await self.send_stream.aclose() + + async def aclose(self) -> None: + await self.send_stream.aclose() + await self.receive_stream.aclose() + + @property + def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: + return { + **self.send_stream.extra_attributes, + **self.receive_stream.extra_attributes, + } + + +@dataclass(eq=False) +class StapledObjectStream(Generic[T_Item], ObjectStream[T_Item]): + """ + Combines two object streams into a single, bidirectional object stream. + + Extra attributes will be provided from both streams, with the receive stream + providing the values in case of a conflict. + + :param ObjectSendStream send_stream: the sending object stream + :param ObjectReceiveStream receive_stream: the receiving object stream + """ + + send_stream: ObjectSendStream[T_Item] + receive_stream: ObjectReceiveStream[T_Item] + + async def receive(self) -> T_Item: + return await self.receive_stream.receive() + + async def send(self, item: T_Item) -> None: + await self.send_stream.send(item) + + async def send_eof(self) -> None: + await self.send_stream.aclose() + + async def aclose(self) -> None: + await self.send_stream.aclose() + await self.receive_stream.aclose() + + @property + def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: + return { + **self.send_stream.extra_attributes, + **self.receive_stream.extra_attributes, + } + + +@dataclass(eq=False) +class MultiListener(Generic[T_Stream], Listener[T_Stream]): + """ + Combines multiple listeners into one, serving connections from all of them at once. + + Any MultiListeners in the given collection of listeners will have their listeners + moved into this one. + + Extra attributes are provided from each listener, with each successive listener + overriding any conflicting attributes from the previous one. + + :param listeners: listeners to serve + :type listeners: Sequence[Listener[T_Stream]] + """ + + listeners: Sequence[Listener[T_Stream]] + + def __post_init__(self) -> None: + listeners: list[Listener[T_Stream]] = [] + for listener in self.listeners: + if isinstance(listener, MultiListener): + listeners.extend(listener.listeners) + del listener.listeners[:] # type: ignore[attr-defined] + else: + listeners.append(listener) + + self.listeners = listeners + + async def serve( + self, handler: Callable[[T_Stream], Any], task_group: TaskGroup | None = None + ) -> None: + from .. import create_task_group + + async with create_task_group() as tg: + for listener in self.listeners: + tg.start_soon(listener.serve, handler, task_group) + + async def aclose(self) -> None: + for listener in self.listeners: + await listener.aclose() + + @property + def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: + attributes: dict = {} + for listener in self.listeners: + attributes.update(listener.extra_attributes) + + return attributes diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/streams/text.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/streams/text.py new file mode 100644 index 0000000..296cd25 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/streams/text.py @@ -0,0 +1,176 @@ +from __future__ import annotations + +__all__ = ( + "TextConnectable", + "TextReceiveStream", + "TextSendStream", + "TextStream", +) + +import codecs +import sys +from collections.abc import Callable, Mapping +from dataclasses import InitVar, dataclass, field +from typing import Any + +from ..abc import ( + AnyByteReceiveStream, + AnyByteSendStream, + AnyByteStream, + AnyByteStreamConnectable, + ObjectReceiveStream, + ObjectSendStream, + ObjectStream, + ObjectStreamConnectable, +) + +if sys.version_info >= (3, 12): + from typing import override +else: + from typing_extensions import override + + +@dataclass(eq=False) +class TextReceiveStream(ObjectReceiveStream[str]): + """ + Stream wrapper that decodes bytes to strings using the given encoding. + + Decoding is done using :class:`~codecs.IncrementalDecoder` which returns any + completely received unicode characters as soon as they come in. + + :param transport_stream: any bytes-based receive stream + :param encoding: character encoding to use for decoding bytes to strings (defaults + to ``utf-8``) + :param errors: handling scheme for decoding errors (defaults to ``strict``; see the + `codecs module documentation`_ for a comprehensive list of options) + + .. _codecs module documentation: + https://docs.python.org/3/library/codecs.html#codec-objects + """ + + transport_stream: AnyByteReceiveStream + encoding: InitVar[str] = "utf-8" + errors: InitVar[str] = "strict" + _decoder: codecs.IncrementalDecoder = field(init=False) + + def __post_init__(self, encoding: str, errors: str) -> None: + decoder_class = codecs.getincrementaldecoder(encoding) + self._decoder = decoder_class(errors=errors) + + async def receive(self) -> str: + while True: + chunk = await self.transport_stream.receive() + decoded = self._decoder.decode(chunk) + if decoded: + return decoded + + async def aclose(self) -> None: + await self.transport_stream.aclose() + self._decoder.reset() + + @property + def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: + return self.transport_stream.extra_attributes + + +@dataclass(eq=False) +class TextSendStream(ObjectSendStream[str]): + """ + Sends strings to the wrapped stream as bytes using the given encoding. + + :param AnyByteSendStream transport_stream: any bytes-based send stream + :param str encoding: character encoding to use for encoding strings to bytes + (defaults to ``utf-8``) + :param str errors: handling scheme for encoding errors (defaults to ``strict``; see + the `codecs module documentation`_ for a comprehensive list of options) + + .. _codecs module documentation: + https://docs.python.org/3/library/codecs.html#codec-objects + """ + + transport_stream: AnyByteSendStream + encoding: InitVar[str] = "utf-8" + errors: str = "strict" + _encoder: Callable[..., tuple[bytes, int]] = field(init=False) + + def __post_init__(self, encoding: str) -> None: + self._encoder = codecs.getencoder(encoding) + + async def send(self, item: str) -> None: + encoded = self._encoder(item, self.errors)[0] + await self.transport_stream.send(encoded) + + async def aclose(self) -> None: + await self.transport_stream.aclose() + + @property + def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: + return self.transport_stream.extra_attributes + + +@dataclass(eq=False) +class TextStream(ObjectStream[str]): + """ + A bidirectional stream that decodes bytes to strings on receive and encodes strings + to bytes on send. + + Extra attributes will be provided from both streams, with the receive stream + providing the values in case of a conflict. + + :param AnyByteStream transport_stream: any bytes-based stream + :param str encoding: character encoding to use for encoding/decoding strings to/from + bytes (defaults to ``utf-8``) + :param str errors: handling scheme for encoding errors (defaults to ``strict``; see + the `codecs module documentation`_ for a comprehensive list of options) + + .. _codecs module documentation: + https://docs.python.org/3/library/codecs.html#codec-objects + """ + + transport_stream: AnyByteStream + encoding: InitVar[str] = "utf-8" + errors: InitVar[str] = "strict" + _receive_stream: TextReceiveStream = field(init=False) + _send_stream: TextSendStream = field(init=False) + + def __post_init__(self, encoding: str, errors: str) -> None: + self._receive_stream = TextReceiveStream( + self.transport_stream, encoding=encoding, errors=errors + ) + self._send_stream = TextSendStream( + self.transport_stream, encoding=encoding, errors=errors + ) + + async def receive(self) -> str: + return await self._receive_stream.receive() + + async def send(self, item: str) -> None: + await self._send_stream.send(item) + + async def send_eof(self) -> None: + await self.transport_stream.send_eof() + + async def aclose(self) -> None: + await self._send_stream.aclose() + await self._receive_stream.aclose() + + @property + def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: + return { + **self._send_stream.extra_attributes, + **self._receive_stream.extra_attributes, + } + + +class TextConnectable(ObjectStreamConnectable[str]): + def __init__(self, connectable: AnyByteStreamConnectable): + """ + :param connectable: the bytestream endpoint to wrap + + """ + self.connectable = connectable + + @override + async def connect(self) -> TextStream: + stream = await self.connectable.connect() + return TextStream(stream) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/streams/tls.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/streams/tls.py new file mode 100644 index 0000000..b507488 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/streams/tls.py @@ -0,0 +1,424 @@ +from __future__ import annotations + +__all__ = ( + "TLSAttribute", + "TLSConnectable", + "TLSListener", + "TLSStream", +) + +import logging +import re +import ssl +import sys +from collections.abc import Callable, Mapping +from dataclasses import dataclass +from functools import wraps +from ssl import SSLContext +from typing import Any, TypeVar + +from .. import ( + BrokenResourceError, + EndOfStream, + aclose_forcefully, + get_cancelled_exc_class, + to_thread, +) +from .._core._typedattr import TypedAttributeSet, typed_attribute +from ..abc import ( + AnyByteStream, + AnyByteStreamConnectable, + ByteStream, + ByteStreamConnectable, + Listener, + TaskGroup, +) + +if sys.version_info >= (3, 10): + from typing import TypeAlias +else: + from typing_extensions import TypeAlias + +if sys.version_info >= (3, 11): + from typing import TypeVarTuple, Unpack +else: + from typing_extensions import TypeVarTuple, Unpack + +if sys.version_info >= (3, 12): + from typing import override +else: + from typing_extensions import override + +T_Retval = TypeVar("T_Retval") +PosArgsT = TypeVarTuple("PosArgsT") +_PCTRTT: TypeAlias = tuple[tuple[str, str], ...] +_PCTRTTT: TypeAlias = tuple[_PCTRTT, ...] + + +class TLSAttribute(TypedAttributeSet): + """Contains Transport Layer Security related attributes.""" + + #: the selected ALPN protocol + alpn_protocol: str | None = typed_attribute() + #: the channel binding for type ``tls-unique`` + channel_binding_tls_unique: bytes = typed_attribute() + #: the selected cipher + cipher: tuple[str, str, int] = typed_attribute() + #: the peer certificate in dictionary form (see :meth:`ssl.SSLSocket.getpeercert` + # for more information) + peer_certificate: None | (dict[str, str | _PCTRTTT | _PCTRTT]) = typed_attribute() + #: the peer certificate in binary form + peer_certificate_binary: bytes | None = typed_attribute() + #: ``True`` if this is the server side of the connection + server_side: bool = typed_attribute() + #: ciphers shared by the client during the TLS handshake (``None`` if this is the + #: client side) + shared_ciphers: list[tuple[str, str, int]] | None = typed_attribute() + #: the :class:`~ssl.SSLObject` used for encryption + ssl_object: ssl.SSLObject = typed_attribute() + #: ``True`` if this stream does (and expects) a closing TLS handshake when the + #: stream is being closed + standard_compatible: bool = typed_attribute() + #: the TLS protocol version (e.g. ``TLSv1.2``) + tls_version: str = typed_attribute() + + +@dataclass(eq=False) +class TLSStream(ByteStream): + """ + A stream wrapper that encrypts all sent data and decrypts received data. + + This class has no public initializer; use :meth:`wrap` instead. + All extra attributes from :class:`~TLSAttribute` are supported. + + :var AnyByteStream transport_stream: the wrapped stream + + """ + + transport_stream: AnyByteStream + standard_compatible: bool + _ssl_object: ssl.SSLObject + _read_bio: ssl.MemoryBIO + _write_bio: ssl.MemoryBIO + + @classmethod + async def wrap( + cls, + transport_stream: AnyByteStream, + *, + server_side: bool | None = None, + hostname: str | None = None, + ssl_context: ssl.SSLContext | None = None, + standard_compatible: bool = True, + ) -> TLSStream: + """ + Wrap an existing stream with Transport Layer Security. + + This performs a TLS handshake with the peer. + + :param transport_stream: a bytes-transporting stream to wrap + :param server_side: ``True`` if this is the server side of the connection, + ``False`` if this is the client side (if omitted, will be set to ``False`` + if ``hostname`` has been provided, ``False`` otherwise). Used only to create + a default context when an explicit context has not been provided. + :param hostname: host name of the peer (if host name checking is desired) + :param ssl_context: the SSLContext object to use (if not provided, a secure + default will be created) + :param standard_compatible: if ``False``, skip the closing handshake when + closing the connection, and don't raise an exception if the peer does the + same + :raises ~ssl.SSLError: if the TLS handshake fails + + """ + if server_side is None: + server_side = not hostname + + if not ssl_context: + purpose = ( + ssl.Purpose.CLIENT_AUTH if server_side else ssl.Purpose.SERVER_AUTH + ) + ssl_context = ssl.create_default_context(purpose) + + # Re-enable detection of unexpected EOFs if it was disabled by Python + if hasattr(ssl, "OP_IGNORE_UNEXPECTED_EOF"): + ssl_context.options &= ~ssl.OP_IGNORE_UNEXPECTED_EOF + + bio_in = ssl.MemoryBIO() + bio_out = ssl.MemoryBIO() + + # External SSLContext implementations may do blocking I/O in wrap_bio(), + # but the standard library implementation won't + if type(ssl_context) is ssl.SSLContext: + ssl_object = ssl_context.wrap_bio( + bio_in, bio_out, server_side=server_side, server_hostname=hostname + ) + else: + ssl_object = await to_thread.run_sync( + ssl_context.wrap_bio, + bio_in, + bio_out, + server_side, + hostname, + None, + ) + + wrapper = cls( + transport_stream=transport_stream, + standard_compatible=standard_compatible, + _ssl_object=ssl_object, + _read_bio=bio_in, + _write_bio=bio_out, + ) + await wrapper._call_sslobject_method(ssl_object.do_handshake) + return wrapper + + async def _call_sslobject_method( + self, func: Callable[[Unpack[PosArgsT]], T_Retval], *args: Unpack[PosArgsT] + ) -> T_Retval: + while True: + try: + result = func(*args) + except ssl.SSLWantReadError: + try: + # Flush any pending writes first + if self._write_bio.pending: + await self.transport_stream.send(self._write_bio.read()) + + data = await self.transport_stream.receive() + except EndOfStream: + self._read_bio.write_eof() + except OSError as exc: + self._read_bio.write_eof() + self._write_bio.write_eof() + raise BrokenResourceError from exc + else: + self._read_bio.write(data) + except ssl.SSLWantWriteError: + await self.transport_stream.send(self._write_bio.read()) + except ssl.SSLSyscallError as exc: + self._read_bio.write_eof() + self._write_bio.write_eof() + raise BrokenResourceError from exc + except ssl.SSLError as exc: + self._read_bio.write_eof() + self._write_bio.write_eof() + if isinstance(exc, ssl.SSLEOFError) or ( + exc.strerror and "UNEXPECTED_EOF_WHILE_READING" in exc.strerror + ): + if self.standard_compatible: + raise BrokenResourceError from exc + else: + raise EndOfStream from None + + raise + else: + # Flush any pending writes first + if self._write_bio.pending: + await self.transport_stream.send(self._write_bio.read()) + + return result + + async def unwrap(self) -> tuple[AnyByteStream, bytes]: + """ + Does the TLS closing handshake. + + :return: a tuple of (wrapped byte stream, bytes left in the read buffer) + + """ + await self._call_sslobject_method(self._ssl_object.unwrap) + self._read_bio.write_eof() + self._write_bio.write_eof() + return self.transport_stream, self._read_bio.read() + + async def aclose(self) -> None: + if self.standard_compatible: + try: + await self.unwrap() + except BaseException: + await aclose_forcefully(self.transport_stream) + raise + + await self.transport_stream.aclose() + + async def receive(self, max_bytes: int = 65536) -> bytes: + data = await self._call_sslobject_method(self._ssl_object.read, max_bytes) + if not data: + raise EndOfStream + + return data + + async def send(self, item: bytes) -> None: + await self._call_sslobject_method(self._ssl_object.write, item) + + async def send_eof(self) -> None: + tls_version = self.extra(TLSAttribute.tls_version) + match = re.match(r"TLSv(\d+)(?:\.(\d+))?", tls_version) + if match: + major, minor = int(match.group(1)), int(match.group(2) or 0) + if (major, minor) < (1, 3): + raise NotImplementedError( + f"send_eof() requires at least TLSv1.3; current " + f"session uses {tls_version}" + ) + + raise NotImplementedError( + "send_eof() has not yet been implemented for TLS streams" + ) + + @property + def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: + return { + **self.transport_stream.extra_attributes, + TLSAttribute.alpn_protocol: self._ssl_object.selected_alpn_protocol, + TLSAttribute.channel_binding_tls_unique: ( + self._ssl_object.get_channel_binding + ), + TLSAttribute.cipher: self._ssl_object.cipher, + TLSAttribute.peer_certificate: lambda: self._ssl_object.getpeercert(False), + TLSAttribute.peer_certificate_binary: lambda: self._ssl_object.getpeercert( + True + ), + TLSAttribute.server_side: lambda: self._ssl_object.server_side, + TLSAttribute.shared_ciphers: lambda: self._ssl_object.shared_ciphers() + if self._ssl_object.server_side + else None, + TLSAttribute.standard_compatible: lambda: self.standard_compatible, + TLSAttribute.ssl_object: lambda: self._ssl_object, + TLSAttribute.tls_version: self._ssl_object.version, + } + + +@dataclass(eq=False) +class TLSListener(Listener[TLSStream]): + """ + A convenience listener that wraps another listener and auto-negotiates a TLS session + on every accepted connection. + + If the TLS handshake times out or raises an exception, + :meth:`handle_handshake_error` is called to do whatever post-mortem processing is + deemed necessary. + + Supports only the :attr:`~TLSAttribute.standard_compatible` extra attribute. + + :param Listener listener: the listener to wrap + :param ssl_context: the SSL context object + :param standard_compatible: a flag passed through to :meth:`TLSStream.wrap` + :param handshake_timeout: time limit for the TLS handshake + (passed to :func:`~anyio.fail_after`) + """ + + listener: Listener[Any] + ssl_context: ssl.SSLContext + standard_compatible: bool = True + handshake_timeout: float = 30 + + @staticmethod + async def handle_handshake_error(exc: BaseException, stream: AnyByteStream) -> None: + """ + Handle an exception raised during the TLS handshake. + + This method does 3 things: + + #. Forcefully closes the original stream + #. Logs the exception (unless it was a cancellation exception) using the + ``anyio.streams.tls`` logger + #. Reraises the exception if it was a base exception or a cancellation exception + + :param exc: the exception + :param stream: the original stream + + """ + await aclose_forcefully(stream) + + # Log all except cancellation exceptions + if not isinstance(exc, get_cancelled_exc_class()): + # CPython (as of 3.11.5) returns incorrect `sys.exc_info()` here when using + # any asyncio implementation, so we explicitly pass the exception to log + # (https://github.com/python/cpython/issues/108668). Trio does not have this + # issue because it works around the CPython bug. + logging.getLogger(__name__).exception( + "Error during TLS handshake", exc_info=exc + ) + + # Only reraise base exceptions and cancellation exceptions + if not isinstance(exc, Exception) or isinstance(exc, get_cancelled_exc_class()): + raise + + async def serve( + self, + handler: Callable[[TLSStream], Any], + task_group: TaskGroup | None = None, + ) -> None: + @wraps(handler) + async def handler_wrapper(stream: AnyByteStream) -> None: + from .. import fail_after + + try: + with fail_after(self.handshake_timeout): + wrapped_stream = await TLSStream.wrap( + stream, + ssl_context=self.ssl_context, + standard_compatible=self.standard_compatible, + ) + except BaseException as exc: + await self.handle_handshake_error(exc, stream) + else: + await handler(wrapped_stream) + + await self.listener.serve(handler_wrapper, task_group) + + async def aclose(self) -> None: + await self.listener.aclose() + + @property + def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: + return { + TLSAttribute.standard_compatible: lambda: self.standard_compatible, + } + + +class TLSConnectable(ByteStreamConnectable): + """ + Wraps another connectable and does TLS negotiation after a successful connection. + + :param connectable: the connectable to wrap + :param hostname: host name of the server (if host name checking is desired) + :param ssl_context: the SSLContext object to use (if not provided, a secure default + will be created) + :param standard_compatible: if ``False``, skip the closing handshake when closing + the connection, and don't raise an exception if the server does the same + """ + + def __init__( + self, + connectable: AnyByteStreamConnectable, + *, + hostname: str | None = None, + ssl_context: ssl.SSLContext | None = None, + standard_compatible: bool = True, + ) -> None: + self.connectable = connectable + self.ssl_context: SSLContext = ssl_context or ssl.create_default_context( + ssl.Purpose.SERVER_AUTH + ) + if not isinstance(self.ssl_context, ssl.SSLContext): + raise TypeError( + "ssl_context must be an instance of ssl.SSLContext, not " + f"{type(self.ssl_context).__name__}" + ) + self.hostname = hostname + self.standard_compatible = standard_compatible + + @override + async def connect(self) -> TLSStream: + stream = await self.connectable.connect() + try: + return await TLSStream.wrap( + stream, + hostname=self.hostname, + ssl_context=self.ssl_context, + standard_compatible=self.standard_compatible, + ) + except BaseException: + await aclose_forcefully(stream) + raise diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/to_interpreter.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/to_interpreter.py new file mode 100644 index 0000000..694dbe7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/to_interpreter.py @@ -0,0 +1,246 @@ +from __future__ import annotations + +__all__ = ( + "run_sync", + "current_default_interpreter_limiter", +) + +import atexit +import os +import sys +from collections import deque +from collections.abc import Callable +from typing import Any, Final, TypeVar + +from . import current_time, to_thread +from ._core._exceptions import BrokenWorkerInterpreter +from ._core._synchronization import CapacityLimiter +from .lowlevel import RunVar + +if sys.version_info >= (3, 11): + from typing import TypeVarTuple, Unpack +else: + from typing_extensions import TypeVarTuple, Unpack + +if sys.version_info >= (3, 14): + from concurrent.interpreters import ExecutionFailed, create + + def _interp_call( + func: Callable[..., Any], args: tuple[Any, ...] + ) -> tuple[Any, bool]: + try: + retval = func(*args) + except BaseException as exc: + return exc, True + else: + return retval, False + + class _Worker: + last_used: float = 0 + + def __init__(self) -> None: + self._interpreter = create() + + def destroy(self) -> None: + self._interpreter.close() + + def call( + self, + func: Callable[..., T_Retval], + args: tuple[Any, ...], + ) -> T_Retval: + try: + res, is_exception = self._interpreter.call(_interp_call, func, args) + except ExecutionFailed as exc: + raise BrokenWorkerInterpreter(exc.excinfo) from exc + + if is_exception: + raise res + + return res +elif sys.version_info >= (3, 13): + import _interpqueues + import _interpreters + + UNBOUND: Final = 2 # I have no clue how this works, but it was used in the stdlib + FMT_UNPICKLED: Final = 0 + FMT_PICKLED: Final = 1 + QUEUE_PICKLE_ARGS: Final = (FMT_PICKLED, UNBOUND) + QUEUE_UNPICKLE_ARGS: Final = (FMT_UNPICKLED, UNBOUND) + + _run_func = compile( + """ +import _interpqueues +from _interpreters import NotShareableError +from pickle import loads, dumps, HIGHEST_PROTOCOL + +QUEUE_PICKLE_ARGS = (1, 2) +QUEUE_UNPICKLE_ARGS = (0, 2) + +item = _interpqueues.get(queue_id)[0] +try: + func, args = loads(item) + retval = func(*args) +except BaseException as exc: + is_exception = True + retval = exc +else: + is_exception = False + +try: + _interpqueues.put(queue_id, (retval, is_exception), *QUEUE_UNPICKLE_ARGS) +except NotShareableError: + retval = dumps(retval, HIGHEST_PROTOCOL) + _interpqueues.put(queue_id, (retval, is_exception), *QUEUE_PICKLE_ARGS) + """, + "", + "exec", + ) + + class _Worker: + last_used: float = 0 + + def __init__(self) -> None: + self._interpreter_id = _interpreters.create() + self._queue_id = _interpqueues.create(1, *QUEUE_UNPICKLE_ARGS) + _interpreters.set___main___attrs( + self._interpreter_id, {"queue_id": self._queue_id} + ) + + def destroy(self) -> None: + _interpqueues.destroy(self._queue_id) + _interpreters.destroy(self._interpreter_id) + + def call( + self, + func: Callable[..., T_Retval], + args: tuple[Any, ...], + ) -> T_Retval: + import pickle + + item = pickle.dumps((func, args), pickle.HIGHEST_PROTOCOL) + _interpqueues.put(self._queue_id, item, *QUEUE_PICKLE_ARGS) + exc_info = _interpreters.exec(self._interpreter_id, _run_func) + if exc_info: + raise BrokenWorkerInterpreter(exc_info) + + res = _interpqueues.get(self._queue_id) + (res, is_exception), fmt = res[:2] + if fmt == FMT_PICKLED: + res = pickle.loads(res) + + if is_exception: + raise res + + return res +else: + + class _Worker: + last_used: float = 0 + + def __init__(self) -> None: + raise RuntimeError("subinterpreters require at least Python 3.13") + + def call( + self, + func: Callable[..., T_Retval], + args: tuple[Any, ...], + ) -> T_Retval: + raise NotImplementedError + + def destroy(self) -> None: + pass + + +DEFAULT_CPU_COUNT: Final = 8 # this is just an arbitrarily selected value +MAX_WORKER_IDLE_TIME = ( + 30 # seconds a subinterpreter can be idle before becoming eligible for pruning +) + +T_Retval = TypeVar("T_Retval") +PosArgsT = TypeVarTuple("PosArgsT") + +_idle_workers = RunVar[deque[_Worker]]("_available_workers") +_default_interpreter_limiter = RunVar[CapacityLimiter]("_default_interpreter_limiter") + + +def _stop_workers(workers: deque[_Worker]) -> None: + for worker in workers: + worker.destroy() + + workers.clear() + + +async def run_sync( + func: Callable[[Unpack[PosArgsT]], T_Retval], + *args: Unpack[PosArgsT], + limiter: CapacityLimiter | None = None, +) -> T_Retval: + """ + Call the given function with the given arguments in a subinterpreter. + + .. warning:: On Python 3.13, the :mod:`concurrent.interpreters` module was not yet + available, so the code path for that Python version relies on an undocumented, + private API. As such, it is recommended to not rely on this function for anything + mission-critical on Python 3.13. + + :param func: a callable + :param args: the positional arguments for the callable + :param limiter: capacity limiter to use to limit the total number of subinterpreters + running (if omitted, the default limiter is used) + :return: the result of the call + :raises BrokenWorkerInterpreter: if there's an internal error in a subinterpreter + + """ + if limiter is None: + limiter = current_default_interpreter_limiter() + + try: + idle_workers = _idle_workers.get() + except LookupError: + idle_workers = deque() + _idle_workers.set(idle_workers) + atexit.register(_stop_workers, idle_workers) + + async with limiter: + try: + worker = idle_workers.pop() + except IndexError: + worker = _Worker() + + try: + return await to_thread.run_sync( + worker.call, + func, + args, + limiter=limiter, + ) + finally: + # Prune workers that have been idle for too long + now = current_time() + while idle_workers: + if now - idle_workers[0].last_used <= MAX_WORKER_IDLE_TIME: + break + + await to_thread.run_sync(idle_workers.popleft().destroy, limiter=limiter) + + worker.last_used = current_time() + idle_workers.append(worker) + + +def current_default_interpreter_limiter() -> CapacityLimiter: + """ + Return the capacity limiter used by default to limit the number of concurrently + running subinterpreters. + + Defaults to the number of CPU cores. + + :return: a capacity limiter object + + """ + try: + return _default_interpreter_limiter.get() + except LookupError: + limiter = CapacityLimiter(os.cpu_count() or DEFAULT_CPU_COUNT) + _default_interpreter_limiter.set(limiter) + return limiter diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/to_process.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/to_process.py new file mode 100644 index 0000000..b289234 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/to_process.py @@ -0,0 +1,266 @@ +from __future__ import annotations + +__all__ = ( + "current_default_process_limiter", + "process_worker", + "run_sync", +) + +import os +import pickle +import subprocess +import sys +from collections import deque +from collections.abc import Callable +from importlib.util import module_from_spec, spec_from_file_location +from typing import TypeVar, cast + +from ._core._eventloop import current_time, get_async_backend, get_cancelled_exc_class +from ._core._exceptions import BrokenWorkerProcess +from ._core._subprocesses import open_process +from ._core._synchronization import CapacityLimiter +from ._core._tasks import CancelScope, fail_after +from .abc import ByteReceiveStream, ByteSendStream, Process +from .lowlevel import RunVar, checkpoint_if_cancelled +from .streams.buffered import BufferedByteReceiveStream + +if sys.version_info >= (3, 11): + from typing import TypeVarTuple, Unpack +else: + from typing_extensions import TypeVarTuple, Unpack + +WORKER_MAX_IDLE_TIME = 300 # 5 minutes + +T_Retval = TypeVar("T_Retval") +PosArgsT = TypeVarTuple("PosArgsT") + +_process_pool_workers: RunVar[set[Process]] = RunVar("_process_pool_workers") +_process_pool_idle_workers: RunVar[deque[tuple[Process, float]]] = RunVar( + "_process_pool_idle_workers" +) +_default_process_limiter: RunVar[CapacityLimiter] = RunVar("_default_process_limiter") + + +async def run_sync( # type: ignore[return] + func: Callable[[Unpack[PosArgsT]], T_Retval], + *args: Unpack[PosArgsT], + cancellable: bool = False, + limiter: CapacityLimiter | None = None, +) -> T_Retval: + """ + Call the given function with the given arguments in a worker process. + + If the ``cancellable`` option is enabled and the task waiting for its completion is + cancelled, the worker process running it will be abruptly terminated using SIGKILL + (or ``terminateProcess()`` on Windows). + + :param func: a callable + :param args: positional arguments for the callable + :param cancellable: ``True`` to allow cancellation of the operation while it's + running + :param limiter: capacity limiter to use to limit the total amount of processes + running (if omitted, the default limiter is used) + :raises NoEventLoopError: if no supported asynchronous event loop is running in the + current thread + :return: an awaitable that yields the return value of the function. + + """ + + async def send_raw_command(pickled_cmd: bytes) -> object: + try: + await stdin.send(pickled_cmd) + response = await buffered.receive_until(b"\n", 50) + status, length = response.split(b" ") + if status not in (b"RETURN", b"EXCEPTION"): + raise RuntimeError( + f"Worker process returned unexpected response: {response!r}" + ) + + pickled_response = await buffered.receive_exactly(int(length)) + except BaseException as exc: + workers.discard(process) + try: + process.kill() + with CancelScope(shield=True): + await process.aclose() + except ProcessLookupError: + pass + + if isinstance(exc, get_cancelled_exc_class()): + raise + else: + raise BrokenWorkerProcess from exc + + retval = pickle.loads(pickled_response) + if status == b"EXCEPTION": + assert isinstance(retval, BaseException) + raise retval + else: + return retval + + # First pickle the request before trying to reserve a worker process + await checkpoint_if_cancelled() + request = pickle.dumps(("run", func, args), protocol=pickle.HIGHEST_PROTOCOL) + + # If this is the first run in this event loop thread, set up the necessary variables + try: + workers = _process_pool_workers.get() + idle_workers = _process_pool_idle_workers.get() + except LookupError: + workers = set() + idle_workers = deque() + _process_pool_workers.set(workers) + _process_pool_idle_workers.set(idle_workers) + get_async_backend().setup_process_pool_exit_at_shutdown(workers) + + async with limiter or current_default_process_limiter(): + # Pop processes from the pool (starting from the most recently used) until we + # find one that hasn't exited yet + process: Process + while idle_workers: + process, idle_since = idle_workers.pop() + if process.returncode is None: + stdin = cast(ByteSendStream, process.stdin) + buffered = BufferedByteReceiveStream( + cast(ByteReceiveStream, process.stdout) + ) + + # Prune any other workers that have been idle for WORKER_MAX_IDLE_TIME + # seconds or longer + now = current_time() + killed_processes: list[Process] = [] + while idle_workers: + if now - idle_workers[0][1] < WORKER_MAX_IDLE_TIME: + break + + process_to_kill, idle_since = idle_workers.popleft() + process_to_kill.kill() + workers.remove(process_to_kill) + killed_processes.append(process_to_kill) + + with CancelScope(shield=True): + for killed_process in killed_processes: + await killed_process.aclose() + + break + + workers.remove(process) + else: + command = [sys.executable, "-u", "-m", __name__] + process = await open_process( + command, stdin=subprocess.PIPE, stdout=subprocess.PIPE + ) + try: + stdin = cast(ByteSendStream, process.stdin) + buffered = BufferedByteReceiveStream( + cast(ByteReceiveStream, process.stdout) + ) + with fail_after(20): + message = await buffered.receive(6) + + if message != b"READY\n": + raise BrokenWorkerProcess( + f"Worker process returned unexpected response: {message!r}" + ) + + main_module_path = getattr(sys.modules["__main__"], "__file__", None) + pickled = pickle.dumps( + ("init", sys.path, main_module_path), + protocol=pickle.HIGHEST_PROTOCOL, + ) + await send_raw_command(pickled) + except (BrokenWorkerProcess, get_cancelled_exc_class()): + raise + except BaseException as exc: + process.kill() + raise BrokenWorkerProcess( + "Error during worker process initialization" + ) from exc + + workers.add(process) + + with CancelScope(shield=not cancellable): + try: + return cast(T_Retval, await send_raw_command(request)) + finally: + if process in workers: + idle_workers.append((process, current_time())) + + +def current_default_process_limiter() -> CapacityLimiter: + """ + Return the capacity limiter that is used by default to limit the number of worker + processes. + + :return: a capacity limiter object + + """ + try: + return _default_process_limiter.get() + except LookupError: + limiter = CapacityLimiter(os.cpu_count() or 2) + _default_process_limiter.set(limiter) + return limiter + + +def process_worker() -> None: + # Redirect standard streams to os.devnull so that user code won't interfere with the + # parent-worker communication + stdin = sys.stdin + stdout = sys.stdout + sys.stdin = open(os.devnull) + sys.stdout = open(os.devnull, "w") + + stdout.buffer.write(b"READY\n") + while True: + retval = exception = None + try: + command, *args = pickle.load(stdin.buffer) + except EOFError: + return + except BaseException as exc: + exception = exc + else: + if command == "run": + func, args = args + try: + retval = func(*args) + except BaseException as exc: + exception = exc + elif command == "init": + main_module_path: str | None + sys.path, main_module_path = args + del sys.modules["__main__"] + if main_module_path and os.path.isfile(main_module_path): + # Load the parent's main module but as __mp_main__ instead of + # __main__ (like multiprocessing does) to avoid infinite recursion + try: + spec = spec_from_file_location("__mp_main__", main_module_path) + if spec and spec.loader: + main = module_from_spec(spec) + spec.loader.exec_module(main) + sys.modules["__main__"] = main + except BaseException as exc: + exception = exc + try: + if exception is not None: + status = b"EXCEPTION" + pickled = pickle.dumps(exception, pickle.HIGHEST_PROTOCOL) + else: + status = b"RETURN" + pickled = pickle.dumps(retval, pickle.HIGHEST_PROTOCOL) + except BaseException as exc: + exception = exc + status = b"EXCEPTION" + pickled = pickle.dumps(exc, pickle.HIGHEST_PROTOCOL) + + stdout.buffer.write(b"%s %d\n" % (status, len(pickled))) + stdout.buffer.write(pickled) + + # Respect SIGTERM + if isinstance(exception, SystemExit): + raise exception + + +if __name__ == "__main__": + process_worker() diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/to_thread.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/to_thread.py new file mode 100644 index 0000000..4be5b71 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/anyio/to_thread.py @@ -0,0 +1,78 @@ +from __future__ import annotations + +__all__ = ( + "run_sync", + "current_default_thread_limiter", +) + +import sys +from collections.abc import Callable +from typing import TypeVar +from warnings import warn + +from ._core._eventloop import get_async_backend +from .abc import CapacityLimiter + +if sys.version_info >= (3, 11): + from typing import TypeVarTuple, Unpack +else: + from typing_extensions import TypeVarTuple, Unpack + +T_Retval = TypeVar("T_Retval") +PosArgsT = TypeVarTuple("PosArgsT") + + +async def run_sync( + func: Callable[[Unpack[PosArgsT]], T_Retval], + *args: Unpack[PosArgsT], + abandon_on_cancel: bool = False, + cancellable: bool | None = None, + limiter: CapacityLimiter | None = None, +) -> T_Retval: + """ + Call the given function with the given arguments in a worker thread. + + If the ``cancellable`` option is enabled and the task waiting for its completion is + cancelled, the thread will still run its course but its return value (or any raised + exception) will be ignored. + + :param func: a callable + :param args: positional arguments for the callable + :param abandon_on_cancel: ``True`` to abandon the thread (leaving it to run + unchecked on own) if the host task is cancelled, ``False`` to ignore + cancellations in the host task until the operation has completed in the worker + thread + :param cancellable: deprecated alias of ``abandon_on_cancel``; will override + ``abandon_on_cancel`` if both parameters are passed + :param limiter: capacity limiter to use to limit the total amount of threads running + (if omitted, the default limiter is used) + :raises NoEventLoopError: if no supported asynchronous event loop is running in the + current thread + :return: an awaitable that yields the return value of the function. + + """ + if cancellable is not None: + abandon_on_cancel = cancellable + warn( + "The `cancellable=` keyword argument to `anyio.to_thread.run_sync` is " + "deprecated since AnyIO 4.1.0; use `abandon_on_cancel=` instead", + DeprecationWarning, + stacklevel=2, + ) + + return await get_async_backend().run_sync_in_worker_thread( + func, args, abandon_on_cancel=abandon_on_cancel, limiter=limiter + ) + + +def current_default_thread_limiter() -> CapacityLimiter: + """ + Return the capacity limiter that is used by default to limit the number of + concurrent threads. + + :return: a capacity limiter object + :raises NoEventLoopError: if no supported asynchronous event loop is running in the + current thread + + """ + return get_async_backend().current_default_thread_limiter() diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click-8.1.8.dist-info/INSTALLER b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click-8.1.8.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click-8.1.8.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click-8.1.8.dist-info/METADATA b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click-8.1.8.dist-info/METADATA new file mode 100644 index 0000000..82df135 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click-8.1.8.dist-info/METADATA @@ -0,0 +1,75 @@ +Metadata-Version: 2.4 +Name: click +Version: 8.1.8 +Summary: Composable command line interface toolkit +Maintainer-email: Pallets +Requires-Python: >=3.7 +Description-Content-Type: text/markdown +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Typing :: Typed +License-File: LICENSE.txt +Requires-Dist: colorama; platform_system == 'Windows' +Requires-Dist: importlib-metadata; python_version < '3.8' +Project-URL: Changes, https://click.palletsprojects.com/changes/ +Project-URL: Chat, https://discord.gg/pallets +Project-URL: Documentation, https://click.palletsprojects.com/ +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Source, https://github.com/pallets/click/ + +# $ click_ + +Click is a Python package for creating beautiful command line interfaces +in a composable way with as little code as necessary. It's the "Command +Line Interface Creation Kit". It's highly configurable but comes with +sensible defaults out of the box. + +It aims to make the process of writing command line tools quick and fun +while also preventing any frustration caused by the inability to +implement an intended CLI API. + +Click in three points: + +- Arbitrary nesting of commands +- Automatic help page generation +- Supports lazy loading of subcommands at runtime + + +## A Simple Example + +```python +import click + +@click.command() +@click.option("--count", default=1, help="Number of greetings.") +@click.option("--name", prompt="Your name", help="The person to greet.") +def hello(count, name): + """Simple program that greets NAME for a total of COUNT times.""" + for _ in range(count): + click.echo(f"Hello, {name}!") + +if __name__ == '__main__': + hello() +``` + +``` +$ python hello.py --count=3 +Your name: Click +Hello, Click! +Hello, Click! +Hello, Click! +``` + + +## Donate + +The Pallets organization develops and supports Click and other popular +packages. In order to grow the community of contributors and users, and +allow the maintainers to devote more time to the projects, [please +donate today][]. + +[please donate today]: https://palletsprojects.com/donate + diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click-8.1.8.dist-info/RECORD b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click-8.1.8.dist-info/RECORD new file mode 100644 index 0000000..57b3c41 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click-8.1.8.dist-info/RECORD @@ -0,0 +1,22 @@ +click-8.1.8.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +click-8.1.8.dist-info/METADATA,sha256=r3P0YoocobE6xkGO4VqBk5mi_4LacU-YnNfBWCoDDak,2289 +click-8.1.8.dist-info/RECORD,, +click-8.1.8.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82 +click-8.1.8.dist-info/licenses/LICENSE.txt,sha256=morRBqOU6FO_4h9C9OctWSgZoigF2ZG18ydQKSkrZY0,1475 +click/__init__.py,sha256=j1DJeCbga4ribkv5uyvIAzI0oFN13fW9mevDKShFelo,3188 +click/_compat.py,sha256=IGKh_J5QdfKELitnRfTGHneejWxoCw_NX9tfMbdcg3w,18730 +click/_termui_impl.py,sha256=a5z7I9gOFeMmu7Gb6_RPyQ8GPuVP1EeblixcWSPSQPk,24783 +click/_textwrap.py,sha256=10fQ64OcBUMuK7mFvh8363_uoOxPlRItZBmKzRJDgoY,1353 +click/_winconsole.py,sha256=5ju3jQkcZD0W27WEMGqmEP4y_crUVzPCqsX_FYb7BO0,7860 +click/core.py,sha256=Q1nEVdctZwvIPOlt4vfHko0TYnHCeE40UEEul8Wpyvs,114748 +click/decorators.py,sha256=7t6F-QWowtLh6F_6l-4YV4Y4yNTcqFQEu9i37zIz68s,18925 +click/exceptions.py,sha256=V7zDT6emqJ8iNl0kF1P5kpFmLMWQ1T1L7aNNKM4YR0w,9600 +click/formatting.py,sha256=Frf0-5W33-loyY_i9qrwXR8-STnW3m5gvyxLVUdyxyk,9706 +click/globals.py,sha256=cuJ6Bbo073lgEEmhjr394PeM-QFmXM-Ci-wmfsd7H5g,1954 +click/parser.py,sha256=h4sndcpF5OHrZQN8vD8IWb5OByvW7ABbhRToxovrqS8,19067 +click/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +click/shell_completion.py,sha256=TR0dXEGcvWb9Eo3aaQEXGhnvNS3FF4H4QcuLnvAvYo4,18636 +click/termui.py,sha256=dLxiS70UOvIYBda_nEEZaPAFOVDVmRs1sEPMuLDowQo,28310 +click/testing.py,sha256=3RA8anCf7TZ8-5RAF5it2Te-aWXBAL5VLasQnMiC2ZQ,16282 +click/types.py,sha256=BD5Qqq4h-8kawBmOIzJlmq4xzThAf4wCvaOLZSBDNx0,36422 +click/utils.py,sha256=ce-IrO9ilII76LGkU354pOdHbepM8UftfNH7SfMU_28,20330 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click-8.1.8.dist-info/WHEEL b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click-8.1.8.dist-info/WHEEL new file mode 100644 index 0000000..d8b9936 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click-8.1.8.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.12.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click-8.1.8.dist-info/licenses/LICENSE.txt b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click-8.1.8.dist-info/licenses/LICENSE.txt new file mode 100644 index 0000000..d12a849 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click-8.1.8.dist-info/licenses/LICENSE.txt @@ -0,0 +1,28 @@ +Copyright 2014 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/__init__.py new file mode 100644 index 0000000..2610d0e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/__init__.py @@ -0,0 +1,75 @@ +""" +Click is a simple Python module inspired by the stdlib optparse to make +writing command line scripts fun. Unlike other modules, it's based +around a simple API that does not come with too much magic and is +composable. +""" + +from .core import Argument as Argument +from .core import BaseCommand as BaseCommand +from .core import Command as Command +from .core import CommandCollection as CommandCollection +from .core import Context as Context +from .core import Group as Group +from .core import MultiCommand as MultiCommand +from .core import Option as Option +from .core import Parameter as Parameter +from .decorators import argument as argument +from .decorators import command as command +from .decorators import confirmation_option as confirmation_option +from .decorators import group as group +from .decorators import help_option as help_option +from .decorators import HelpOption as HelpOption +from .decorators import make_pass_decorator as make_pass_decorator +from .decorators import option as option +from .decorators import pass_context as pass_context +from .decorators import pass_obj as pass_obj +from .decorators import password_option as password_option +from .decorators import version_option as version_option +from .exceptions import Abort as Abort +from .exceptions import BadArgumentUsage as BadArgumentUsage +from .exceptions import BadOptionUsage as BadOptionUsage +from .exceptions import BadParameter as BadParameter +from .exceptions import ClickException as ClickException +from .exceptions import FileError as FileError +from .exceptions import MissingParameter as MissingParameter +from .exceptions import NoSuchOption as NoSuchOption +from .exceptions import UsageError as UsageError +from .formatting import HelpFormatter as HelpFormatter +from .formatting import wrap_text as wrap_text +from .globals import get_current_context as get_current_context +from .parser import OptionParser as OptionParser +from .termui import clear as clear +from .termui import confirm as confirm +from .termui import echo_via_pager as echo_via_pager +from .termui import edit as edit +from .termui import getchar as getchar +from .termui import launch as launch +from .termui import pause as pause +from .termui import progressbar as progressbar +from .termui import prompt as prompt +from .termui import secho as secho +from .termui import style as style +from .termui import unstyle as unstyle +from .types import BOOL as BOOL +from .types import Choice as Choice +from .types import DateTime as DateTime +from .types import File as File +from .types import FLOAT as FLOAT +from .types import FloatRange as FloatRange +from .types import INT as INT +from .types import IntRange as IntRange +from .types import ParamType as ParamType +from .types import Path as Path +from .types import STRING as STRING +from .types import Tuple as Tuple +from .types import UNPROCESSED as UNPROCESSED +from .types import UUID as UUID +from .utils import echo as echo +from .utils import format_filename as format_filename +from .utils import get_app_dir as get_app_dir +from .utils import get_binary_stream as get_binary_stream +from .utils import get_text_stream as get_text_stream +from .utils import open_file as open_file + +__version__ = "8.1.8" diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/_compat.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/_compat.py new file mode 100644 index 0000000..9153d15 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/_compat.py @@ -0,0 +1,623 @@ +import codecs +import io +import os +import re +import sys +import typing as t +from weakref import WeakKeyDictionary + +CYGWIN = sys.platform.startswith("cygwin") +WIN = sys.platform.startswith("win") +auto_wrap_for_ansi: t.Optional[t.Callable[[t.TextIO], t.TextIO]] = None +_ansi_re = re.compile(r"\033\[[;?0-9]*[a-zA-Z]") + + +def _make_text_stream( + stream: t.BinaryIO, + encoding: t.Optional[str], + errors: t.Optional[str], + force_readable: bool = False, + force_writable: bool = False, +) -> t.TextIO: + if encoding is None: + encoding = get_best_encoding(stream) + if errors is None: + errors = "replace" + return _NonClosingTextIOWrapper( + stream, + encoding, + errors, + line_buffering=True, + force_readable=force_readable, + force_writable=force_writable, + ) + + +def is_ascii_encoding(encoding: str) -> bool: + """Checks if a given encoding is ascii.""" + try: + return codecs.lookup(encoding).name == "ascii" + except LookupError: + return False + + +def get_best_encoding(stream: t.IO[t.Any]) -> str: + """Returns the default stream encoding if not found.""" + rv = getattr(stream, "encoding", None) or sys.getdefaultencoding() + if is_ascii_encoding(rv): + return "utf-8" + return rv + + +class _NonClosingTextIOWrapper(io.TextIOWrapper): + def __init__( + self, + stream: t.BinaryIO, + encoding: t.Optional[str], + errors: t.Optional[str], + force_readable: bool = False, + force_writable: bool = False, + **extra: t.Any, + ) -> None: + self._stream = stream = t.cast( + t.BinaryIO, _FixupStream(stream, force_readable, force_writable) + ) + super().__init__(stream, encoding, errors, **extra) + + def __del__(self) -> None: + try: + self.detach() + except Exception: + pass + + def isatty(self) -> bool: + # https://bitbucket.org/pypy/pypy/issue/1803 + return self._stream.isatty() + + +class _FixupStream: + """The new io interface needs more from streams than streams + traditionally implement. As such, this fix-up code is necessary in + some circumstances. + + The forcing of readable and writable flags are there because some tools + put badly patched objects on sys (one such offender are certain version + of jupyter notebook). + """ + + def __init__( + self, + stream: t.BinaryIO, + force_readable: bool = False, + force_writable: bool = False, + ): + self._stream = stream + self._force_readable = force_readable + self._force_writable = force_writable + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._stream, name) + + def read1(self, size: int) -> bytes: + f = getattr(self._stream, "read1", None) + + if f is not None: + return t.cast(bytes, f(size)) + + return self._stream.read(size) + + def readable(self) -> bool: + if self._force_readable: + return True + x = getattr(self._stream, "readable", None) + if x is not None: + return t.cast(bool, x()) + try: + self._stream.read(0) + except Exception: + return False + return True + + def writable(self) -> bool: + if self._force_writable: + return True + x = getattr(self._stream, "writable", None) + if x is not None: + return t.cast(bool, x()) + try: + self._stream.write("") # type: ignore + except Exception: + try: + self._stream.write(b"") + except Exception: + return False + return True + + def seekable(self) -> bool: + x = getattr(self._stream, "seekable", None) + if x is not None: + return t.cast(bool, x()) + try: + self._stream.seek(self._stream.tell()) + except Exception: + return False + return True + + +def _is_binary_reader(stream: t.IO[t.Any], default: bool = False) -> bool: + try: + return isinstance(stream.read(0), bytes) + except Exception: + return default + # This happens in some cases where the stream was already + # closed. In this case, we assume the default. + + +def _is_binary_writer(stream: t.IO[t.Any], default: bool = False) -> bool: + try: + stream.write(b"") + except Exception: + try: + stream.write("") + return False + except Exception: + pass + return default + return True + + +def _find_binary_reader(stream: t.IO[t.Any]) -> t.Optional[t.BinaryIO]: + # We need to figure out if the given stream is already binary. + # This can happen because the official docs recommend detaching + # the streams to get binary streams. Some code might do this, so + # we need to deal with this case explicitly. + if _is_binary_reader(stream, False): + return t.cast(t.BinaryIO, stream) + + buf = getattr(stream, "buffer", None) + + # Same situation here; this time we assume that the buffer is + # actually binary in case it's closed. + if buf is not None and _is_binary_reader(buf, True): + return t.cast(t.BinaryIO, buf) + + return None + + +def _find_binary_writer(stream: t.IO[t.Any]) -> t.Optional[t.BinaryIO]: + # We need to figure out if the given stream is already binary. + # This can happen because the official docs recommend detaching + # the streams to get binary streams. Some code might do this, so + # we need to deal with this case explicitly. + if _is_binary_writer(stream, False): + return t.cast(t.BinaryIO, stream) + + buf = getattr(stream, "buffer", None) + + # Same situation here; this time we assume that the buffer is + # actually binary in case it's closed. + if buf is not None and _is_binary_writer(buf, True): + return t.cast(t.BinaryIO, buf) + + return None + + +def _stream_is_misconfigured(stream: t.TextIO) -> bool: + """A stream is misconfigured if its encoding is ASCII.""" + # If the stream does not have an encoding set, we assume it's set + # to ASCII. This appears to happen in certain unittest + # environments. It's not quite clear what the correct behavior is + # but this at least will force Click to recover somehow. + return is_ascii_encoding(getattr(stream, "encoding", None) or "ascii") + + +def _is_compat_stream_attr(stream: t.TextIO, attr: str, value: t.Optional[str]) -> bool: + """A stream attribute is compatible if it is equal to the + desired value or the desired value is unset and the attribute + has a value. + """ + stream_value = getattr(stream, attr, None) + return stream_value == value or (value is None and stream_value is not None) + + +def _is_compatible_text_stream( + stream: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str] +) -> bool: + """Check if a stream's encoding and errors attributes are + compatible with the desired values. + """ + return _is_compat_stream_attr( + stream, "encoding", encoding + ) and _is_compat_stream_attr(stream, "errors", errors) + + +def _force_correct_text_stream( + text_stream: t.IO[t.Any], + encoding: t.Optional[str], + errors: t.Optional[str], + is_binary: t.Callable[[t.IO[t.Any], bool], bool], + find_binary: t.Callable[[t.IO[t.Any]], t.Optional[t.BinaryIO]], + force_readable: bool = False, + force_writable: bool = False, +) -> t.TextIO: + if is_binary(text_stream, False): + binary_reader = t.cast(t.BinaryIO, text_stream) + else: + text_stream = t.cast(t.TextIO, text_stream) + # If the stream looks compatible, and won't default to a + # misconfigured ascii encoding, return it as-is. + if _is_compatible_text_stream(text_stream, encoding, errors) and not ( + encoding is None and _stream_is_misconfigured(text_stream) + ): + return text_stream + + # Otherwise, get the underlying binary reader. + possible_binary_reader = find_binary(text_stream) + + # If that's not possible, silently use the original reader + # and get mojibake instead of exceptions. + if possible_binary_reader is None: + return text_stream + + binary_reader = possible_binary_reader + + # Default errors to replace instead of strict in order to get + # something that works. + if errors is None: + errors = "replace" + + # Wrap the binary stream in a text stream with the correct + # encoding parameters. + return _make_text_stream( + binary_reader, + encoding, + errors, + force_readable=force_readable, + force_writable=force_writable, + ) + + +def _force_correct_text_reader( + text_reader: t.IO[t.Any], + encoding: t.Optional[str], + errors: t.Optional[str], + force_readable: bool = False, +) -> t.TextIO: + return _force_correct_text_stream( + text_reader, + encoding, + errors, + _is_binary_reader, + _find_binary_reader, + force_readable=force_readable, + ) + + +def _force_correct_text_writer( + text_writer: t.IO[t.Any], + encoding: t.Optional[str], + errors: t.Optional[str], + force_writable: bool = False, +) -> t.TextIO: + return _force_correct_text_stream( + text_writer, + encoding, + errors, + _is_binary_writer, + _find_binary_writer, + force_writable=force_writable, + ) + + +def get_binary_stdin() -> t.BinaryIO: + reader = _find_binary_reader(sys.stdin) + if reader is None: + raise RuntimeError("Was not able to determine binary stream for sys.stdin.") + return reader + + +def get_binary_stdout() -> t.BinaryIO: + writer = _find_binary_writer(sys.stdout) + if writer is None: + raise RuntimeError("Was not able to determine binary stream for sys.stdout.") + return writer + + +def get_binary_stderr() -> t.BinaryIO: + writer = _find_binary_writer(sys.stderr) + if writer is None: + raise RuntimeError("Was not able to determine binary stream for sys.stderr.") + return writer + + +def get_text_stdin( + encoding: t.Optional[str] = None, errors: t.Optional[str] = None +) -> t.TextIO: + rv = _get_windows_console_stream(sys.stdin, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_reader(sys.stdin, encoding, errors, force_readable=True) + + +def get_text_stdout( + encoding: t.Optional[str] = None, errors: t.Optional[str] = None +) -> t.TextIO: + rv = _get_windows_console_stream(sys.stdout, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_writer(sys.stdout, encoding, errors, force_writable=True) + + +def get_text_stderr( + encoding: t.Optional[str] = None, errors: t.Optional[str] = None +) -> t.TextIO: + rv = _get_windows_console_stream(sys.stderr, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_writer(sys.stderr, encoding, errors, force_writable=True) + + +def _wrap_io_open( + file: t.Union[str, "os.PathLike[str]", int], + mode: str, + encoding: t.Optional[str], + errors: t.Optional[str], +) -> t.IO[t.Any]: + """Handles not passing ``encoding`` and ``errors`` in binary mode.""" + if "b" in mode: + return open(file, mode) + + return open(file, mode, encoding=encoding, errors=errors) + + +def open_stream( + filename: "t.Union[str, os.PathLike[str]]", + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + atomic: bool = False, +) -> t.Tuple[t.IO[t.Any], bool]: + binary = "b" in mode + filename = os.fspath(filename) + + # Standard streams first. These are simple because they ignore the + # atomic flag. Use fsdecode to handle Path("-"). + if os.fsdecode(filename) == "-": + if any(m in mode for m in ["w", "a", "x"]): + if binary: + return get_binary_stdout(), False + return get_text_stdout(encoding=encoding, errors=errors), False + if binary: + return get_binary_stdin(), False + return get_text_stdin(encoding=encoding, errors=errors), False + + # Non-atomic writes directly go out through the regular open functions. + if not atomic: + return _wrap_io_open(filename, mode, encoding, errors), True + + # Some usability stuff for atomic writes + if "a" in mode: + raise ValueError( + "Appending to an existing file is not supported, because that" + " would involve an expensive `copy`-operation to a temporary" + " file. Open the file in normal `w`-mode and copy explicitly" + " if that's what you're after." + ) + if "x" in mode: + raise ValueError("Use the `overwrite`-parameter instead.") + if "w" not in mode: + raise ValueError("Atomic writes only make sense with `w`-mode.") + + # Atomic writes are more complicated. They work by opening a file + # as a proxy in the same folder and then using the fdopen + # functionality to wrap it in a Python file. Then we wrap it in an + # atomic file that moves the file over on close. + import errno + import random + + try: + perm: t.Optional[int] = os.stat(filename).st_mode + except OSError: + perm = None + + flags = os.O_RDWR | os.O_CREAT | os.O_EXCL + + if binary: + flags |= getattr(os, "O_BINARY", 0) + + while True: + tmp_filename = os.path.join( + os.path.dirname(filename), + f".__atomic-write{random.randrange(1 << 32):08x}", + ) + try: + fd = os.open(tmp_filename, flags, 0o666 if perm is None else perm) + break + except OSError as e: + if e.errno == errno.EEXIST or ( + os.name == "nt" + and e.errno == errno.EACCES + and os.path.isdir(e.filename) + and os.access(e.filename, os.W_OK) + ): + continue + raise + + if perm is not None: + os.chmod(tmp_filename, perm) # in case perm includes bits in umask + + f = _wrap_io_open(fd, mode, encoding, errors) + af = _AtomicFile(f, tmp_filename, os.path.realpath(filename)) + return t.cast(t.IO[t.Any], af), True + + +class _AtomicFile: + def __init__(self, f: t.IO[t.Any], tmp_filename: str, real_filename: str) -> None: + self._f = f + self._tmp_filename = tmp_filename + self._real_filename = real_filename + self.closed = False + + @property + def name(self) -> str: + return self._real_filename + + def close(self, delete: bool = False) -> None: + if self.closed: + return + self._f.close() + os.replace(self._tmp_filename, self._real_filename) + self.closed = True + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._f, name) + + def __enter__(self) -> "_AtomicFile": + return self + + def __exit__(self, exc_type: t.Optional[t.Type[BaseException]], *_: t.Any) -> None: + self.close(delete=exc_type is not None) + + def __repr__(self) -> str: + return repr(self._f) + + +def strip_ansi(value: str) -> str: + return _ansi_re.sub("", value) + + +def _is_jupyter_kernel_output(stream: t.IO[t.Any]) -> bool: + while isinstance(stream, (_FixupStream, _NonClosingTextIOWrapper)): + stream = stream._stream + + return stream.__class__.__module__.startswith("ipykernel.") + + +def should_strip_ansi( + stream: t.Optional[t.IO[t.Any]] = None, color: t.Optional[bool] = None +) -> bool: + if color is None: + if stream is None: + stream = sys.stdin + return not isatty(stream) and not _is_jupyter_kernel_output(stream) + return not color + + +# On Windows, wrap the output streams with colorama to support ANSI +# color codes. +# NOTE: double check is needed so mypy does not analyze this on Linux +if sys.platform.startswith("win") and WIN: + from ._winconsole import _get_windows_console_stream + + def _get_argv_encoding() -> str: + import locale + + return locale.getpreferredencoding() + + _ansi_stream_wrappers: t.MutableMapping[t.TextIO, t.TextIO] = WeakKeyDictionary() + + def auto_wrap_for_ansi( + stream: t.TextIO, color: t.Optional[bool] = None + ) -> t.TextIO: + """Support ANSI color and style codes on Windows by wrapping a + stream with colorama. + """ + try: + cached = _ansi_stream_wrappers.get(stream) + except Exception: + cached = None + + if cached is not None: + return cached + + import colorama + + strip = should_strip_ansi(stream, color) + ansi_wrapper = colorama.AnsiToWin32(stream, strip=strip) + rv = t.cast(t.TextIO, ansi_wrapper.stream) + _write = rv.write + + def _safe_write(s): + try: + return _write(s) + except BaseException: + ansi_wrapper.reset_all() + raise + + rv.write = _safe_write + + try: + _ansi_stream_wrappers[stream] = rv + except Exception: + pass + + return rv + +else: + + def _get_argv_encoding() -> str: + return getattr(sys.stdin, "encoding", None) or sys.getfilesystemencoding() + + def _get_windows_console_stream( + f: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str] + ) -> t.Optional[t.TextIO]: + return None + + +def term_len(x: str) -> int: + return len(strip_ansi(x)) + + +def isatty(stream: t.IO[t.Any]) -> bool: + try: + return stream.isatty() + except Exception: + return False + + +def _make_cached_stream_func( + src_func: t.Callable[[], t.Optional[t.TextIO]], + wrapper_func: t.Callable[[], t.TextIO], +) -> t.Callable[[], t.Optional[t.TextIO]]: + cache: t.MutableMapping[t.TextIO, t.TextIO] = WeakKeyDictionary() + + def func() -> t.Optional[t.TextIO]: + stream = src_func() + + if stream is None: + return None + + try: + rv = cache.get(stream) + except Exception: + rv = None + if rv is not None: + return rv + rv = wrapper_func() + try: + cache[stream] = rv + except Exception: + pass + return rv + + return func + + +_default_text_stdin = _make_cached_stream_func(lambda: sys.stdin, get_text_stdin) +_default_text_stdout = _make_cached_stream_func(lambda: sys.stdout, get_text_stdout) +_default_text_stderr = _make_cached_stream_func(lambda: sys.stderr, get_text_stderr) + + +binary_streams: t.Mapping[str, t.Callable[[], t.BinaryIO]] = { + "stdin": get_binary_stdin, + "stdout": get_binary_stdout, + "stderr": get_binary_stderr, +} + +text_streams: t.Mapping[ + str, t.Callable[[t.Optional[str], t.Optional[str]], t.TextIO] +] = { + "stdin": get_text_stdin, + "stdout": get_text_stdout, + "stderr": get_text_stderr, +} diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/_termui_impl.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/_termui_impl.py new file mode 100644 index 0000000..ad9f8f6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/_termui_impl.py @@ -0,0 +1,788 @@ +""" +This module contains implementations for the termui module. To keep the +import time of Click down, some infrequently used functionality is +placed in this module and only imported as needed. +""" + +import contextlib +import math +import os +import sys +import time +import typing as t +from gettext import gettext as _ +from io import StringIO +from shutil import which +from types import TracebackType + +from ._compat import _default_text_stdout +from ._compat import CYGWIN +from ._compat import get_best_encoding +from ._compat import isatty +from ._compat import open_stream +from ._compat import strip_ansi +from ._compat import term_len +from ._compat import WIN +from .exceptions import ClickException +from .utils import echo + +V = t.TypeVar("V") + +if os.name == "nt": + BEFORE_BAR = "\r" + AFTER_BAR = "\n" +else: + BEFORE_BAR = "\r\033[?25l" + AFTER_BAR = "\033[?25h\n" + + +class ProgressBar(t.Generic[V]): + def __init__( + self, + iterable: t.Optional[t.Iterable[V]], + length: t.Optional[int] = None, + fill_char: str = "#", + empty_char: str = " ", + bar_template: str = "%(bar)s", + info_sep: str = " ", + show_eta: bool = True, + show_percent: t.Optional[bool] = None, + show_pos: bool = False, + item_show_func: t.Optional[t.Callable[[t.Optional[V]], t.Optional[str]]] = None, + label: t.Optional[str] = None, + file: t.Optional[t.TextIO] = None, + color: t.Optional[bool] = None, + update_min_steps: int = 1, + width: int = 30, + ) -> None: + self.fill_char = fill_char + self.empty_char = empty_char + self.bar_template = bar_template + self.info_sep = info_sep + self.show_eta = show_eta + self.show_percent = show_percent + self.show_pos = show_pos + self.item_show_func = item_show_func + self.label: str = label or "" + + if file is None: + file = _default_text_stdout() + + # There are no standard streams attached to write to. For example, + # pythonw on Windows. + if file is None: + file = StringIO() + + self.file = file + self.color = color + self.update_min_steps = update_min_steps + self._completed_intervals = 0 + self.width: int = width + self.autowidth: bool = width == 0 + + if length is None: + from operator import length_hint + + length = length_hint(iterable, -1) + + if length == -1: + length = None + if iterable is None: + if length is None: + raise TypeError("iterable or length is required") + iterable = t.cast(t.Iterable[V], range(length)) + self.iter: t.Iterable[V] = iter(iterable) + self.length = length + self.pos = 0 + self.avg: t.List[float] = [] + self.last_eta: float + self.start: float + self.start = self.last_eta = time.time() + self.eta_known: bool = False + self.finished: bool = False + self.max_width: t.Optional[int] = None + self.entered: bool = False + self.current_item: t.Optional[V] = None + self.is_hidden: bool = not isatty(self.file) + self._last_line: t.Optional[str] = None + + def __enter__(self) -> "ProgressBar[V]": + self.entered = True + self.render_progress() + return self + + def __exit__( + self, + exc_type: t.Optional[t.Type[BaseException]], + exc_value: t.Optional[BaseException], + tb: t.Optional[TracebackType], + ) -> None: + self.render_finish() + + def __iter__(self) -> t.Iterator[V]: + if not self.entered: + raise RuntimeError("You need to use progress bars in a with block.") + self.render_progress() + return self.generator() + + def __next__(self) -> V: + # Iteration is defined in terms of a generator function, + # returned by iter(self); use that to define next(). This works + # because `self.iter` is an iterable consumed by that generator, + # so it is re-entry safe. Calling `next(self.generator())` + # twice works and does "what you want". + return next(iter(self)) + + def render_finish(self) -> None: + if self.is_hidden: + return + self.file.write(AFTER_BAR) + self.file.flush() + + @property + def pct(self) -> float: + if self.finished: + return 1.0 + return min(self.pos / (float(self.length or 1) or 1), 1.0) + + @property + def time_per_iteration(self) -> float: + if not self.avg: + return 0.0 + return sum(self.avg) / float(len(self.avg)) + + @property + def eta(self) -> float: + if self.length is not None and not self.finished: + return self.time_per_iteration * (self.length - self.pos) + return 0.0 + + def format_eta(self) -> str: + if self.eta_known: + t = int(self.eta) + seconds = t % 60 + t //= 60 + minutes = t % 60 + t //= 60 + hours = t % 24 + t //= 24 + if t > 0: + return f"{t}d {hours:02}:{minutes:02}:{seconds:02}" + else: + return f"{hours:02}:{minutes:02}:{seconds:02}" + return "" + + def format_pos(self) -> str: + pos = str(self.pos) + if self.length is not None: + pos += f"/{self.length}" + return pos + + def format_pct(self) -> str: + return f"{int(self.pct * 100): 4}%"[1:] + + def format_bar(self) -> str: + if self.length is not None: + bar_length = int(self.pct * self.width) + bar = self.fill_char * bar_length + bar += self.empty_char * (self.width - bar_length) + elif self.finished: + bar = self.fill_char * self.width + else: + chars = list(self.empty_char * (self.width or 1)) + if self.time_per_iteration != 0: + chars[ + int( + (math.cos(self.pos * self.time_per_iteration) / 2.0 + 0.5) + * self.width + ) + ] = self.fill_char + bar = "".join(chars) + return bar + + def format_progress_line(self) -> str: + show_percent = self.show_percent + + info_bits = [] + if self.length is not None and show_percent is None: + show_percent = not self.show_pos + + if self.show_pos: + info_bits.append(self.format_pos()) + if show_percent: + info_bits.append(self.format_pct()) + if self.show_eta and self.eta_known and not self.finished: + info_bits.append(self.format_eta()) + if self.item_show_func is not None: + item_info = self.item_show_func(self.current_item) + if item_info is not None: + info_bits.append(item_info) + + return ( + self.bar_template + % { + "label": self.label, + "bar": self.format_bar(), + "info": self.info_sep.join(info_bits), + } + ).rstrip() + + def render_progress(self) -> None: + import shutil + + if self.is_hidden: + # Only output the label as it changes if the output is not a + # TTY. Use file=stderr if you expect to be piping stdout. + if self._last_line != self.label: + self._last_line = self.label + echo(self.label, file=self.file, color=self.color) + + return + + buf = [] + # Update width in case the terminal has been resized + if self.autowidth: + old_width = self.width + self.width = 0 + clutter_length = term_len(self.format_progress_line()) + new_width = max(0, shutil.get_terminal_size().columns - clutter_length) + if new_width < old_width: + buf.append(BEFORE_BAR) + buf.append(" " * self.max_width) # type: ignore + self.max_width = new_width + self.width = new_width + + clear_width = self.width + if self.max_width is not None: + clear_width = self.max_width + + buf.append(BEFORE_BAR) + line = self.format_progress_line() + line_len = term_len(line) + if self.max_width is None or self.max_width < line_len: + self.max_width = line_len + + buf.append(line) + buf.append(" " * (clear_width - line_len)) + line = "".join(buf) + # Render the line only if it changed. + + if line != self._last_line: + self._last_line = line + echo(line, file=self.file, color=self.color, nl=False) + self.file.flush() + + def make_step(self, n_steps: int) -> None: + self.pos += n_steps + if self.length is not None and self.pos >= self.length: + self.finished = True + + if (time.time() - self.last_eta) < 1.0: + return + + self.last_eta = time.time() + + # self.avg is a rolling list of length <= 7 of steps where steps are + # defined as time elapsed divided by the total progress through + # self.length. + if self.pos: + step = (time.time() - self.start) / self.pos + else: + step = time.time() - self.start + + self.avg = self.avg[-6:] + [step] + + self.eta_known = self.length is not None + + def update(self, n_steps: int, current_item: t.Optional[V] = None) -> None: + """Update the progress bar by advancing a specified number of + steps, and optionally set the ``current_item`` for this new + position. + + :param n_steps: Number of steps to advance. + :param current_item: Optional item to set as ``current_item`` + for the updated position. + + .. versionchanged:: 8.0 + Added the ``current_item`` optional parameter. + + .. versionchanged:: 8.0 + Only render when the number of steps meets the + ``update_min_steps`` threshold. + """ + if current_item is not None: + self.current_item = current_item + + self._completed_intervals += n_steps + + if self._completed_intervals >= self.update_min_steps: + self.make_step(self._completed_intervals) + self.render_progress() + self._completed_intervals = 0 + + def finish(self) -> None: + self.eta_known = False + self.current_item = None + self.finished = True + + def generator(self) -> t.Iterator[V]: + """Return a generator which yields the items added to the bar + during construction, and updates the progress bar *after* the + yielded block returns. + """ + # WARNING: the iterator interface for `ProgressBar` relies on + # this and only works because this is a simple generator which + # doesn't create or manage additional state. If this function + # changes, the impact should be evaluated both against + # `iter(bar)` and `next(bar)`. `next()` in particular may call + # `self.generator()` repeatedly, and this must remain safe in + # order for that interface to work. + if not self.entered: + raise RuntimeError("You need to use progress bars in a with block.") + + if self.is_hidden: + yield from self.iter + else: + for rv in self.iter: + self.current_item = rv + + # This allows show_item_func to be updated before the + # item is processed. Only trigger at the beginning of + # the update interval. + if self._completed_intervals == 0: + self.render_progress() + + yield rv + self.update(1) + + self.finish() + self.render_progress() + + +def pager(generator: t.Iterable[str], color: t.Optional[bool] = None) -> None: + """Decide what method to use for paging through text.""" + stdout = _default_text_stdout() + + # There are no standard streams attached to write to. For example, + # pythonw on Windows. + if stdout is None: + stdout = StringIO() + + if not isatty(sys.stdin) or not isatty(stdout): + return _nullpager(stdout, generator, color) + pager_cmd = (os.environ.get("PAGER", None) or "").strip() + if pager_cmd: + if WIN: + if _tempfilepager(generator, pager_cmd, color): + return + elif _pipepager(generator, pager_cmd, color): + return + if os.environ.get("TERM") in ("dumb", "emacs"): + return _nullpager(stdout, generator, color) + if (WIN or sys.platform.startswith("os2")) and _tempfilepager( + generator, "more", color + ): + return + if _pipepager(generator, "less", color): + return + + import tempfile + + fd, filename = tempfile.mkstemp() + os.close(fd) + try: + if _pipepager(generator, "more", color): + return + return _nullpager(stdout, generator, color) + finally: + os.unlink(filename) + + +def _pipepager(generator: t.Iterable[str], cmd: str, color: t.Optional[bool]) -> bool: + """Page through text by feeding it to another program. Invoking a + pager through this might support colors. + + Returns True if the command was found, False otherwise and thus another + pager should be attempted. + """ + cmd_absolute = which(cmd) + if cmd_absolute is None: + return False + + import subprocess + + env = dict(os.environ) + + # If we're piping to less we might support colors under the + # condition that + cmd_detail = cmd.rsplit("/", 1)[-1].split() + if color is None and cmd_detail[0] == "less": + less_flags = f"{os.environ.get('LESS', '')}{' '.join(cmd_detail[1:])}" + if not less_flags: + env["LESS"] = "-R" + color = True + elif "r" in less_flags or "R" in less_flags: + color = True + + c = subprocess.Popen( + [cmd_absolute], + shell=True, + stdin=subprocess.PIPE, + env=env, + errors="replace", + text=True, + ) + assert c.stdin is not None + try: + for text in generator: + if not color: + text = strip_ansi(text) + + c.stdin.write(text) + except (OSError, KeyboardInterrupt): + pass + else: + c.stdin.close() + + # Less doesn't respect ^C, but catches it for its own UI purposes (aborting + # search or other commands inside less). + # + # That means when the user hits ^C, the parent process (click) terminates, + # but less is still alive, paging the output and messing up the terminal. + # + # If the user wants to make the pager exit on ^C, they should set + # `LESS='-K'`. It's not our decision to make. + while True: + try: + c.wait() + except KeyboardInterrupt: + pass + else: + break + + return True + + +def _tempfilepager( + generator: t.Iterable[str], + cmd: str, + color: t.Optional[bool], +) -> bool: + """Page through text by invoking a program on a temporary file. + + Returns True if the command was found, False otherwise and thus another + pager should be attempted. + """ + # Which is necessary for Windows, it is also recommended in the Popen docs. + cmd_absolute = which(cmd) + if cmd_absolute is None: + return False + + import subprocess + import tempfile + + fd, filename = tempfile.mkstemp() + # TODO: This never terminates if the passed generator never terminates. + text = "".join(generator) + if not color: + text = strip_ansi(text) + encoding = get_best_encoding(sys.stdout) + with open_stream(filename, "wb")[0] as f: + f.write(text.encode(encoding)) + try: + subprocess.call([cmd_absolute, filename]) + except OSError: + # Command not found + pass + finally: + os.close(fd) + os.unlink(filename) + + return True + + +def _nullpager( + stream: t.TextIO, generator: t.Iterable[str], color: t.Optional[bool] +) -> None: + """Simply print unformatted text. This is the ultimate fallback.""" + for text in generator: + if not color: + text = strip_ansi(text) + stream.write(text) + + +class Editor: + def __init__( + self, + editor: t.Optional[str] = None, + env: t.Optional[t.Mapping[str, str]] = None, + require_save: bool = True, + extension: str = ".txt", + ) -> None: + self.editor = editor + self.env = env + self.require_save = require_save + self.extension = extension + + def get_editor(self) -> str: + if self.editor is not None: + return self.editor + for key in "VISUAL", "EDITOR": + rv = os.environ.get(key) + if rv: + return rv + if WIN: + return "notepad" + for editor in "sensible-editor", "vim", "nano": + if which(editor) is not None: + return editor + return "vi" + + def edit_file(self, filename: str) -> None: + import subprocess + + editor = self.get_editor() + environ: t.Optional[t.Dict[str, str]] = None + + if self.env: + environ = os.environ.copy() + environ.update(self.env) + + try: + c = subprocess.Popen(f'{editor} "{filename}"', env=environ, shell=True) + exit_code = c.wait() + if exit_code != 0: + raise ClickException( + _("{editor}: Editing failed").format(editor=editor) + ) + except OSError as e: + raise ClickException( + _("{editor}: Editing failed: {e}").format(editor=editor, e=e) + ) from e + + def edit(self, text: t.Optional[t.AnyStr]) -> t.Optional[t.AnyStr]: + import tempfile + + if not text: + data = b"" + elif isinstance(text, (bytes, bytearray)): + data = text + else: + if text and not text.endswith("\n"): + text += "\n" + + if WIN: + data = text.replace("\n", "\r\n").encode("utf-8-sig") + else: + data = text.encode("utf-8") + + fd, name = tempfile.mkstemp(prefix="editor-", suffix=self.extension) + f: t.BinaryIO + + try: + with os.fdopen(fd, "wb") as f: + f.write(data) + + # If the filesystem resolution is 1 second, like Mac OS + # 10.12 Extended, or 2 seconds, like FAT32, and the editor + # closes very fast, require_save can fail. Set the modified + # time to be 2 seconds in the past to work around this. + os.utime(name, (os.path.getatime(name), os.path.getmtime(name) - 2)) + # Depending on the resolution, the exact value might not be + # recorded, so get the new recorded value. + timestamp = os.path.getmtime(name) + + self.edit_file(name) + + if self.require_save and os.path.getmtime(name) == timestamp: + return None + + with open(name, "rb") as f: + rv = f.read() + + if isinstance(text, (bytes, bytearray)): + return rv + + return rv.decode("utf-8-sig").replace("\r\n", "\n") # type: ignore + finally: + os.unlink(name) + + +def open_url(url: str, wait: bool = False, locate: bool = False) -> int: + import subprocess + + def _unquote_file(url: str) -> str: + from urllib.parse import unquote + + if url.startswith("file://"): + url = unquote(url[7:]) + + return url + + if sys.platform == "darwin": + args = ["open"] + if wait: + args.append("-W") + if locate: + args.append("-R") + args.append(_unquote_file(url)) + null = open("/dev/null", "w") + try: + return subprocess.Popen(args, stderr=null).wait() + finally: + null.close() + elif WIN: + if locate: + url = _unquote_file(url) + args = ["explorer", f"/select,{url}"] + else: + args = ["start"] + if wait: + args.append("/WAIT") + args.append("") + args.append(url) + try: + return subprocess.call(args) + except OSError: + # Command not found + return 127 + elif CYGWIN: + if locate: + url = _unquote_file(url) + args = ["cygstart", os.path.dirname(url)] + else: + args = ["cygstart"] + if wait: + args.append("-w") + args.append(url) + try: + return subprocess.call(args) + except OSError: + # Command not found + return 127 + + try: + if locate: + url = os.path.dirname(_unquote_file(url)) or "." + else: + url = _unquote_file(url) + c = subprocess.Popen(["xdg-open", url]) + if wait: + return c.wait() + return 0 + except OSError: + if url.startswith(("http://", "https://")) and not locate and not wait: + import webbrowser + + webbrowser.open(url) + return 0 + return 1 + + +def _translate_ch_to_exc(ch: str) -> t.Optional[BaseException]: + if ch == "\x03": + raise KeyboardInterrupt() + + if ch == "\x04" and not WIN: # Unix-like, Ctrl+D + raise EOFError() + + if ch == "\x1a" and WIN: # Windows, Ctrl+Z + raise EOFError() + + return None + + +if WIN: + import msvcrt + + @contextlib.contextmanager + def raw_terminal() -> t.Iterator[int]: + yield -1 + + def getchar(echo: bool) -> str: + # The function `getch` will return a bytes object corresponding to + # the pressed character. Since Windows 10 build 1803, it will also + # return \x00 when called a second time after pressing a regular key. + # + # `getwch` does not share this probably-bugged behavior. Moreover, it + # returns a Unicode object by default, which is what we want. + # + # Either of these functions will return \x00 or \xe0 to indicate + # a special key, and you need to call the same function again to get + # the "rest" of the code. The fun part is that \u00e0 is + # "latin small letter a with grave", so if you type that on a French + # keyboard, you _also_ get a \xe0. + # E.g., consider the Up arrow. This returns \xe0 and then \x48. The + # resulting Unicode string reads as "a with grave" + "capital H". + # This is indistinguishable from when the user actually types + # "a with grave" and then "capital H". + # + # When \xe0 is returned, we assume it's part of a special-key sequence + # and call `getwch` again, but that means that when the user types + # the \u00e0 character, `getchar` doesn't return until a second + # character is typed. + # The alternative is returning immediately, but that would mess up + # cross-platform handling of arrow keys and others that start with + # \xe0. Another option is using `getch`, but then we can't reliably + # read non-ASCII characters, because return values of `getch` are + # limited to the current 8-bit codepage. + # + # Anyway, Click doesn't claim to do this Right(tm), and using `getwch` + # is doing the right thing in more situations than with `getch`. + func: t.Callable[[], str] + + if echo: + func = msvcrt.getwche # type: ignore + else: + func = msvcrt.getwch # type: ignore + + rv = func() + + if rv in ("\x00", "\xe0"): + # \x00 and \xe0 are control characters that indicate special key, + # see above. + rv += func() + + _translate_ch_to_exc(rv) + return rv + +else: + import termios + import tty + + @contextlib.contextmanager + def raw_terminal() -> t.Iterator[int]: + f: t.Optional[t.TextIO] + fd: int + + if not isatty(sys.stdin): + f = open("/dev/tty") + fd = f.fileno() + else: + fd = sys.stdin.fileno() + f = None + + try: + old_settings = termios.tcgetattr(fd) + + try: + tty.setraw(fd) + yield fd + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) + sys.stdout.flush() + + if f is not None: + f.close() + except termios.error: + pass + + def getchar(echo: bool) -> str: + with raw_terminal() as fd: + ch = os.read(fd, 32).decode(get_best_encoding(sys.stdin), "replace") + + if echo and isatty(sys.stdout): + sys.stdout.write(ch) + + _translate_ch_to_exc(ch) + return ch diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/_textwrap.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/_textwrap.py new file mode 100644 index 0000000..b47dcbd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/_textwrap.py @@ -0,0 +1,49 @@ +import textwrap +import typing as t +from contextlib import contextmanager + + +class TextWrapper(textwrap.TextWrapper): + def _handle_long_word( + self, + reversed_chunks: t.List[str], + cur_line: t.List[str], + cur_len: int, + width: int, + ) -> None: + space_left = max(width - cur_len, 1) + + if self.break_long_words: + last = reversed_chunks[-1] + cut = last[:space_left] + res = last[space_left:] + cur_line.append(cut) + reversed_chunks[-1] = res + elif not cur_line: + cur_line.append(reversed_chunks.pop()) + + @contextmanager + def extra_indent(self, indent: str) -> t.Iterator[None]: + old_initial_indent = self.initial_indent + old_subsequent_indent = self.subsequent_indent + self.initial_indent += indent + self.subsequent_indent += indent + + try: + yield + finally: + self.initial_indent = old_initial_indent + self.subsequent_indent = old_subsequent_indent + + def indent_only(self, text: str) -> str: + rv = [] + + for idx, line in enumerate(text.splitlines()): + indent = self.initial_indent + + if idx > 0: + indent = self.subsequent_indent + + rv.append(f"{indent}{line}") + + return "\n".join(rv) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/_winconsole.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/_winconsole.py new file mode 100644 index 0000000..6b20df3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/_winconsole.py @@ -0,0 +1,279 @@ +# This module is based on the excellent work by Adam Bartoš who +# provided a lot of what went into the implementation here in +# the discussion to issue1602 in the Python bug tracker. +# +# There are some general differences in regards to how this works +# compared to the original patches as we do not need to patch +# the entire interpreter but just work in our little world of +# echo and prompt. +import io +import sys +import time +import typing as t +from ctypes import byref +from ctypes import c_char +from ctypes import c_char_p +from ctypes import c_int +from ctypes import c_ssize_t +from ctypes import c_ulong +from ctypes import c_void_p +from ctypes import POINTER +from ctypes import py_object +from ctypes import Structure +from ctypes.wintypes import DWORD +from ctypes.wintypes import HANDLE +from ctypes.wintypes import LPCWSTR +from ctypes.wintypes import LPWSTR + +from ._compat import _NonClosingTextIOWrapper + +assert sys.platform == "win32" +import msvcrt # noqa: E402 +from ctypes import windll # noqa: E402 +from ctypes import WINFUNCTYPE # noqa: E402 + +c_ssize_p = POINTER(c_ssize_t) + +kernel32 = windll.kernel32 +GetStdHandle = kernel32.GetStdHandle +ReadConsoleW = kernel32.ReadConsoleW +WriteConsoleW = kernel32.WriteConsoleW +GetConsoleMode = kernel32.GetConsoleMode +GetLastError = kernel32.GetLastError +GetCommandLineW = WINFUNCTYPE(LPWSTR)(("GetCommandLineW", windll.kernel32)) +CommandLineToArgvW = WINFUNCTYPE(POINTER(LPWSTR), LPCWSTR, POINTER(c_int))( + ("CommandLineToArgvW", windll.shell32) +) +LocalFree = WINFUNCTYPE(c_void_p, c_void_p)(("LocalFree", windll.kernel32)) + +STDIN_HANDLE = GetStdHandle(-10) +STDOUT_HANDLE = GetStdHandle(-11) +STDERR_HANDLE = GetStdHandle(-12) + +PyBUF_SIMPLE = 0 +PyBUF_WRITABLE = 1 + +ERROR_SUCCESS = 0 +ERROR_NOT_ENOUGH_MEMORY = 8 +ERROR_OPERATION_ABORTED = 995 + +STDIN_FILENO = 0 +STDOUT_FILENO = 1 +STDERR_FILENO = 2 + +EOF = b"\x1a" +MAX_BYTES_WRITTEN = 32767 + +try: + from ctypes import pythonapi +except ImportError: + # On PyPy we cannot get buffers so our ability to operate here is + # severely limited. + get_buffer = None +else: + + class Py_buffer(Structure): + _fields_ = [ + ("buf", c_void_p), + ("obj", py_object), + ("len", c_ssize_t), + ("itemsize", c_ssize_t), + ("readonly", c_int), + ("ndim", c_int), + ("format", c_char_p), + ("shape", c_ssize_p), + ("strides", c_ssize_p), + ("suboffsets", c_ssize_p), + ("internal", c_void_p), + ] + + PyObject_GetBuffer = pythonapi.PyObject_GetBuffer + PyBuffer_Release = pythonapi.PyBuffer_Release + + def get_buffer(obj, writable=False): + buf = Py_buffer() + flags = PyBUF_WRITABLE if writable else PyBUF_SIMPLE + PyObject_GetBuffer(py_object(obj), byref(buf), flags) + + try: + buffer_type = c_char * buf.len + return buffer_type.from_address(buf.buf) + finally: + PyBuffer_Release(byref(buf)) + + +class _WindowsConsoleRawIOBase(io.RawIOBase): + def __init__(self, handle): + self.handle = handle + + def isatty(self): + super().isatty() + return True + + +class _WindowsConsoleReader(_WindowsConsoleRawIOBase): + def readable(self): + return True + + def readinto(self, b): + bytes_to_be_read = len(b) + if not bytes_to_be_read: + return 0 + elif bytes_to_be_read % 2: + raise ValueError( + "cannot read odd number of bytes from UTF-16-LE encoded console" + ) + + buffer = get_buffer(b, writable=True) + code_units_to_be_read = bytes_to_be_read // 2 + code_units_read = c_ulong() + + rv = ReadConsoleW( + HANDLE(self.handle), + buffer, + code_units_to_be_read, + byref(code_units_read), + None, + ) + if GetLastError() == ERROR_OPERATION_ABORTED: + # wait for KeyboardInterrupt + time.sleep(0.1) + if not rv: + raise OSError(f"Windows error: {GetLastError()}") + + if buffer[0] == EOF: + return 0 + return 2 * code_units_read.value + + +class _WindowsConsoleWriter(_WindowsConsoleRawIOBase): + def writable(self): + return True + + @staticmethod + def _get_error_message(errno): + if errno == ERROR_SUCCESS: + return "ERROR_SUCCESS" + elif errno == ERROR_NOT_ENOUGH_MEMORY: + return "ERROR_NOT_ENOUGH_MEMORY" + return f"Windows error {errno}" + + def write(self, b): + bytes_to_be_written = len(b) + buf = get_buffer(b) + code_units_to_be_written = min(bytes_to_be_written, MAX_BYTES_WRITTEN) // 2 + code_units_written = c_ulong() + + WriteConsoleW( + HANDLE(self.handle), + buf, + code_units_to_be_written, + byref(code_units_written), + None, + ) + bytes_written = 2 * code_units_written.value + + if bytes_written == 0 and bytes_to_be_written > 0: + raise OSError(self._get_error_message(GetLastError())) + return bytes_written + + +class ConsoleStream: + def __init__(self, text_stream: t.TextIO, byte_stream: t.BinaryIO) -> None: + self._text_stream = text_stream + self.buffer = byte_stream + + @property + def name(self) -> str: + return self.buffer.name + + def write(self, x: t.AnyStr) -> int: + if isinstance(x, str): + return self._text_stream.write(x) + try: + self.flush() + except Exception: + pass + return self.buffer.write(x) + + def writelines(self, lines: t.Iterable[t.AnyStr]) -> None: + for line in lines: + self.write(line) + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._text_stream, name) + + def isatty(self) -> bool: + return self.buffer.isatty() + + def __repr__(self): + return f"" + + +def _get_text_stdin(buffer_stream: t.BinaryIO) -> t.TextIO: + text_stream = _NonClosingTextIOWrapper( + io.BufferedReader(_WindowsConsoleReader(STDIN_HANDLE)), + "utf-16-le", + "strict", + line_buffering=True, + ) + return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) + + +def _get_text_stdout(buffer_stream: t.BinaryIO) -> t.TextIO: + text_stream = _NonClosingTextIOWrapper( + io.BufferedWriter(_WindowsConsoleWriter(STDOUT_HANDLE)), + "utf-16-le", + "strict", + line_buffering=True, + ) + return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) + + +def _get_text_stderr(buffer_stream: t.BinaryIO) -> t.TextIO: + text_stream = _NonClosingTextIOWrapper( + io.BufferedWriter(_WindowsConsoleWriter(STDERR_HANDLE)), + "utf-16-le", + "strict", + line_buffering=True, + ) + return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) + + +_stream_factories: t.Mapping[int, t.Callable[[t.BinaryIO], t.TextIO]] = { + 0: _get_text_stdin, + 1: _get_text_stdout, + 2: _get_text_stderr, +} + + +def _is_console(f: t.TextIO) -> bool: + if not hasattr(f, "fileno"): + return False + + try: + fileno = f.fileno() + except (OSError, io.UnsupportedOperation): + return False + + handle = msvcrt.get_osfhandle(fileno) + return bool(GetConsoleMode(handle, byref(DWORD()))) + + +def _get_windows_console_stream( + f: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str] +) -> t.Optional[t.TextIO]: + if ( + get_buffer is not None + and encoding in {"utf-16-le", None} + and errors in {"strict", None} + and _is_console(f) + ): + func = _stream_factories.get(f.fileno()) + if func is not None: + b = getattr(f, "buffer", None) + + if b is None: + return None + + return func(b) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/core.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/core.py new file mode 100644 index 0000000..e630501 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/core.py @@ -0,0 +1,3047 @@ +import enum +import errno +import inspect +import os +import sys +import typing as t +from collections import abc +from contextlib import contextmanager +from contextlib import ExitStack +from functools import update_wrapper +from gettext import gettext as _ +from gettext import ngettext +from itertools import repeat +from types import TracebackType + +from . import types +from .exceptions import Abort +from .exceptions import BadParameter +from .exceptions import ClickException +from .exceptions import Exit +from .exceptions import MissingParameter +from .exceptions import UsageError +from .formatting import HelpFormatter +from .formatting import join_options +from .globals import pop_context +from .globals import push_context +from .parser import _flag_needs_value +from .parser import OptionParser +from .parser import split_opt +from .termui import confirm +from .termui import prompt +from .termui import style +from .utils import _detect_program_name +from .utils import _expand_args +from .utils import echo +from .utils import make_default_short_help +from .utils import make_str +from .utils import PacifyFlushWrapper + +if t.TYPE_CHECKING: + import typing_extensions as te + + from .decorators import HelpOption + from .shell_completion import CompletionItem + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) +V = t.TypeVar("V") + + +def _complete_visible_commands( + ctx: "Context", incomplete: str +) -> t.Iterator[t.Tuple[str, "Command"]]: + """List all the subcommands of a group that start with the + incomplete value and aren't hidden. + + :param ctx: Invocation context for the group. + :param incomplete: Value being completed. May be empty. + """ + multi = t.cast(MultiCommand, ctx.command) + + for name in multi.list_commands(ctx): + if name.startswith(incomplete): + command = multi.get_command(ctx, name) + + if command is not None and not command.hidden: + yield name, command + + +def _check_multicommand( + base_command: "MultiCommand", cmd_name: str, cmd: "Command", register: bool = False +) -> None: + if not base_command.chain or not isinstance(cmd, MultiCommand): + return + if register: + hint = ( + "It is not possible to add multi commands as children to" + " another multi command that is in chain mode." + ) + else: + hint = ( + "Found a multi command as subcommand to a multi command" + " that is in chain mode. This is not supported." + ) + raise RuntimeError( + f"{hint}. Command {base_command.name!r} is set to chain and" + f" {cmd_name!r} was added as a subcommand but it in itself is a" + f" multi command. ({cmd_name!r} is a {type(cmd).__name__}" + f" within a chained {type(base_command).__name__} named" + f" {base_command.name!r})." + ) + + +def batch(iterable: t.Iterable[V], batch_size: int) -> t.List[t.Tuple[V, ...]]: + return list(zip(*repeat(iter(iterable), batch_size))) + + +@contextmanager +def augment_usage_errors( + ctx: "Context", param: t.Optional["Parameter"] = None +) -> t.Iterator[None]: + """Context manager that attaches extra information to exceptions.""" + try: + yield + except BadParameter as e: + if e.ctx is None: + e.ctx = ctx + if param is not None and e.param is None: + e.param = param + raise + except UsageError as e: + if e.ctx is None: + e.ctx = ctx + raise + + +def iter_params_for_processing( + invocation_order: t.Sequence["Parameter"], + declaration_order: t.Sequence["Parameter"], +) -> t.List["Parameter"]: + """Returns all declared parameters in the order they should be processed. + + The declared parameters are re-shuffled depending on the order in which + they were invoked, as well as the eagerness of each parameters. + + The invocation order takes precedence over the declaration order. I.e. the + order in which the user provided them to the CLI is respected. + + This behavior and its effect on callback evaluation is detailed at: + https://click.palletsprojects.com/en/stable/advanced/#callback-evaluation-order + """ + + def sort_key(item: "Parameter") -> t.Tuple[bool, float]: + try: + idx: float = invocation_order.index(item) + except ValueError: + idx = float("inf") + + return not item.is_eager, idx + + return sorted(declaration_order, key=sort_key) + + +class ParameterSource(enum.Enum): + """This is an :class:`~enum.Enum` that indicates the source of a + parameter's value. + + Use :meth:`click.Context.get_parameter_source` to get the + source for a parameter by name. + + .. versionchanged:: 8.0 + Use :class:`~enum.Enum` and drop the ``validate`` method. + + .. versionchanged:: 8.0 + Added the ``PROMPT`` value. + """ + + COMMANDLINE = enum.auto() + """The value was provided by the command line args.""" + ENVIRONMENT = enum.auto() + """The value was provided with an environment variable.""" + DEFAULT = enum.auto() + """Used the default specified by the parameter.""" + DEFAULT_MAP = enum.auto() + """Used a default provided by :attr:`Context.default_map`.""" + PROMPT = enum.auto() + """Used a prompt to confirm a default or provide a value.""" + + +class Context: + """The context is a special internal object that holds state relevant + for the script execution at every single level. It's normally invisible + to commands unless they opt-in to getting access to it. + + The context is useful as it can pass internal objects around and can + control special execution features such as reading data from + environment variables. + + A context can be used as context manager in which case it will call + :meth:`close` on teardown. + + :param command: the command class for this context. + :param parent: the parent context. + :param info_name: the info name for this invocation. Generally this + is the most descriptive name for the script or + command. For the toplevel script it is usually + the name of the script, for commands below it it's + the name of the script. + :param obj: an arbitrary object of user data. + :param auto_envvar_prefix: the prefix to use for automatic environment + variables. If this is `None` then reading + from environment variables is disabled. This + does not affect manually set environment + variables which are always read. + :param default_map: a dictionary (like object) with default values + for parameters. + :param terminal_width: the width of the terminal. The default is + inherit from parent context. If no context + defines the terminal width then auto + detection will be applied. + :param max_content_width: the maximum width for content rendered by + Click (this currently only affects help + pages). This defaults to 80 characters if + not overridden. In other words: even if the + terminal is larger than that, Click will not + format things wider than 80 characters by + default. In addition to that, formatters might + add some safety mapping on the right. + :param resilient_parsing: if this flag is enabled then Click will + parse without any interactivity or callback + invocation. Default values will also be + ignored. This is useful for implementing + things such as completion support. + :param allow_extra_args: if this is set to `True` then extra arguments + at the end will not raise an error and will be + kept on the context. The default is to inherit + from the command. + :param allow_interspersed_args: if this is set to `False` then options + and arguments cannot be mixed. The + default is to inherit from the command. + :param ignore_unknown_options: instructs click to ignore options it does + not know and keeps them for later + processing. + :param help_option_names: optionally a list of strings that define how + the default help parameter is named. The + default is ``['--help']``. + :param token_normalize_func: an optional function that is used to + normalize tokens (options, choices, + etc.). This for instance can be used to + implement case insensitive behavior. + :param color: controls if the terminal supports ANSI colors or not. The + default is autodetection. This is only needed if ANSI + codes are used in texts that Click prints which is by + default not the case. This for instance would affect + help output. + :param show_default: Show the default value for commands. If this + value is not set, it defaults to the value from the parent + context. ``Command.show_default`` overrides this default for the + specific command. + + .. versionchanged:: 8.1 + The ``show_default`` parameter is overridden by + ``Command.show_default``, instead of the other way around. + + .. versionchanged:: 8.0 + The ``show_default`` parameter defaults to the value from the + parent context. + + .. versionchanged:: 7.1 + Added the ``show_default`` parameter. + + .. versionchanged:: 4.0 + Added the ``color``, ``ignore_unknown_options``, and + ``max_content_width`` parameters. + + .. versionchanged:: 3.0 + Added the ``allow_extra_args`` and ``allow_interspersed_args`` + parameters. + + .. versionchanged:: 2.0 + Added the ``resilient_parsing``, ``help_option_names``, and + ``token_normalize_func`` parameters. + """ + + #: The formatter class to create with :meth:`make_formatter`. + #: + #: .. versionadded:: 8.0 + formatter_class: t.Type["HelpFormatter"] = HelpFormatter + + def __init__( + self, + command: "Command", + parent: t.Optional["Context"] = None, + info_name: t.Optional[str] = None, + obj: t.Optional[t.Any] = None, + auto_envvar_prefix: t.Optional[str] = None, + default_map: t.Optional[t.MutableMapping[str, t.Any]] = None, + terminal_width: t.Optional[int] = None, + max_content_width: t.Optional[int] = None, + resilient_parsing: bool = False, + allow_extra_args: t.Optional[bool] = None, + allow_interspersed_args: t.Optional[bool] = None, + ignore_unknown_options: t.Optional[bool] = None, + help_option_names: t.Optional[t.List[str]] = None, + token_normalize_func: t.Optional[t.Callable[[str], str]] = None, + color: t.Optional[bool] = None, + show_default: t.Optional[bool] = None, + ) -> None: + #: the parent context or `None` if none exists. + self.parent = parent + #: the :class:`Command` for this context. + self.command = command + #: the descriptive information name + self.info_name = info_name + #: Map of parameter names to their parsed values. Parameters + #: with ``expose_value=False`` are not stored. + self.params: t.Dict[str, t.Any] = {} + #: the leftover arguments. + self.args: t.List[str] = [] + #: protected arguments. These are arguments that are prepended + #: to `args` when certain parsing scenarios are encountered but + #: must be never propagated to another arguments. This is used + #: to implement nested parsing. + self.protected_args: t.List[str] = [] + #: the collected prefixes of the command's options. + self._opt_prefixes: t.Set[str] = set(parent._opt_prefixes) if parent else set() + + if obj is None and parent is not None: + obj = parent.obj + + #: the user object stored. + self.obj: t.Any = obj + self._meta: t.Dict[str, t.Any] = getattr(parent, "meta", {}) + + #: A dictionary (-like object) with defaults for parameters. + if ( + default_map is None + and info_name is not None + and parent is not None + and parent.default_map is not None + ): + default_map = parent.default_map.get(info_name) + + self.default_map: t.Optional[t.MutableMapping[str, t.Any]] = default_map + + #: This flag indicates if a subcommand is going to be executed. A + #: group callback can use this information to figure out if it's + #: being executed directly or because the execution flow passes + #: onwards to a subcommand. By default it's None, but it can be + #: the name of the subcommand to execute. + #: + #: If chaining is enabled this will be set to ``'*'`` in case + #: any commands are executed. It is however not possible to + #: figure out which ones. If you require this knowledge you + #: should use a :func:`result_callback`. + self.invoked_subcommand: t.Optional[str] = None + + if terminal_width is None and parent is not None: + terminal_width = parent.terminal_width + + #: The width of the terminal (None is autodetection). + self.terminal_width: t.Optional[int] = terminal_width + + if max_content_width is None and parent is not None: + max_content_width = parent.max_content_width + + #: The maximum width of formatted content (None implies a sensible + #: default which is 80 for most things). + self.max_content_width: t.Optional[int] = max_content_width + + if allow_extra_args is None: + allow_extra_args = command.allow_extra_args + + #: Indicates if the context allows extra args or if it should + #: fail on parsing. + #: + #: .. versionadded:: 3.0 + self.allow_extra_args = allow_extra_args + + if allow_interspersed_args is None: + allow_interspersed_args = command.allow_interspersed_args + + #: Indicates if the context allows mixing of arguments and + #: options or not. + #: + #: .. versionadded:: 3.0 + self.allow_interspersed_args: bool = allow_interspersed_args + + if ignore_unknown_options is None: + ignore_unknown_options = command.ignore_unknown_options + + #: Instructs click to ignore options that a command does not + #: understand and will store it on the context for later + #: processing. This is primarily useful for situations where you + #: want to call into external programs. Generally this pattern is + #: strongly discouraged because it's not possibly to losslessly + #: forward all arguments. + #: + #: .. versionadded:: 4.0 + self.ignore_unknown_options: bool = ignore_unknown_options + + if help_option_names is None: + if parent is not None: + help_option_names = parent.help_option_names + else: + help_option_names = ["--help"] + + #: The names for the help options. + self.help_option_names: t.List[str] = help_option_names + + if token_normalize_func is None and parent is not None: + token_normalize_func = parent.token_normalize_func + + #: An optional normalization function for tokens. This is + #: options, choices, commands etc. + self.token_normalize_func: t.Optional[t.Callable[[str], str]] = ( + token_normalize_func + ) + + #: Indicates if resilient parsing is enabled. In that case Click + #: will do its best to not cause any failures and default values + #: will be ignored. Useful for completion. + self.resilient_parsing: bool = resilient_parsing + + # If there is no envvar prefix yet, but the parent has one and + # the command on this level has a name, we can expand the envvar + # prefix automatically. + if auto_envvar_prefix is None: + if ( + parent is not None + and parent.auto_envvar_prefix is not None + and self.info_name is not None + ): + auto_envvar_prefix = ( + f"{parent.auto_envvar_prefix}_{self.info_name.upper()}" + ) + else: + auto_envvar_prefix = auto_envvar_prefix.upper() + + if auto_envvar_prefix is not None: + auto_envvar_prefix = auto_envvar_prefix.replace("-", "_") + + self.auto_envvar_prefix: t.Optional[str] = auto_envvar_prefix + + if color is None and parent is not None: + color = parent.color + + #: Controls if styling output is wanted or not. + self.color: t.Optional[bool] = color + + if show_default is None and parent is not None: + show_default = parent.show_default + + #: Show option default values when formatting help text. + self.show_default: t.Optional[bool] = show_default + + self._close_callbacks: t.List[t.Callable[[], t.Any]] = [] + self._depth = 0 + self._parameter_source: t.Dict[str, ParameterSource] = {} + self._exit_stack = ExitStack() + + def to_info_dict(self) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. This traverses the entire CLI + structure. + + .. code-block:: python + + with Context(cli) as ctx: + info = ctx.to_info_dict() + + .. versionadded:: 8.0 + """ + return { + "command": self.command.to_info_dict(self), + "info_name": self.info_name, + "allow_extra_args": self.allow_extra_args, + "allow_interspersed_args": self.allow_interspersed_args, + "ignore_unknown_options": self.ignore_unknown_options, + "auto_envvar_prefix": self.auto_envvar_prefix, + } + + def __enter__(self) -> "Context": + self._depth += 1 + push_context(self) + return self + + def __exit__( + self, + exc_type: t.Optional[t.Type[BaseException]], + exc_value: t.Optional[BaseException], + tb: t.Optional[TracebackType], + ) -> None: + self._depth -= 1 + if self._depth == 0: + self.close() + pop_context() + + @contextmanager + def scope(self, cleanup: bool = True) -> t.Iterator["Context"]: + """This helper method can be used with the context object to promote + it to the current thread local (see :func:`get_current_context`). + The default behavior of this is to invoke the cleanup functions which + can be disabled by setting `cleanup` to `False`. The cleanup + functions are typically used for things such as closing file handles. + + If the cleanup is intended the context object can also be directly + used as a context manager. + + Example usage:: + + with ctx.scope(): + assert get_current_context() is ctx + + This is equivalent:: + + with ctx: + assert get_current_context() is ctx + + .. versionadded:: 5.0 + + :param cleanup: controls if the cleanup functions should be run or + not. The default is to run these functions. In + some situations the context only wants to be + temporarily pushed in which case this can be disabled. + Nested pushes automatically defer the cleanup. + """ + if not cleanup: + self._depth += 1 + try: + with self as rv: + yield rv + finally: + if not cleanup: + self._depth -= 1 + + @property + def meta(self) -> t.Dict[str, t.Any]: + """This is a dictionary which is shared with all the contexts + that are nested. It exists so that click utilities can store some + state here if they need to. It is however the responsibility of + that code to manage this dictionary well. + + The keys are supposed to be unique dotted strings. For instance + module paths are a good choice for it. What is stored in there is + irrelevant for the operation of click. However what is important is + that code that places data here adheres to the general semantics of + the system. + + Example usage:: + + LANG_KEY = f'{__name__}.lang' + + def set_language(value): + ctx = get_current_context() + ctx.meta[LANG_KEY] = value + + def get_language(): + return get_current_context().meta.get(LANG_KEY, 'en_US') + + .. versionadded:: 5.0 + """ + return self._meta + + def make_formatter(self) -> HelpFormatter: + """Creates the :class:`~click.HelpFormatter` for the help and + usage output. + + To quickly customize the formatter class used without overriding + this method, set the :attr:`formatter_class` attribute. + + .. versionchanged:: 8.0 + Added the :attr:`formatter_class` attribute. + """ + return self.formatter_class( + width=self.terminal_width, max_width=self.max_content_width + ) + + def with_resource(self, context_manager: t.ContextManager[V]) -> V: + """Register a resource as if it were used in a ``with`` + statement. The resource will be cleaned up when the context is + popped. + + Uses :meth:`contextlib.ExitStack.enter_context`. It calls the + resource's ``__enter__()`` method and returns the result. When + the context is popped, it closes the stack, which calls the + resource's ``__exit__()`` method. + + To register a cleanup function for something that isn't a + context manager, use :meth:`call_on_close`. Or use something + from :mod:`contextlib` to turn it into a context manager first. + + .. code-block:: python + + @click.group() + @click.option("--name") + @click.pass_context + def cli(ctx): + ctx.obj = ctx.with_resource(connect_db(name)) + + :param context_manager: The context manager to enter. + :return: Whatever ``context_manager.__enter__()`` returns. + + .. versionadded:: 8.0 + """ + return self._exit_stack.enter_context(context_manager) + + def call_on_close(self, f: t.Callable[..., t.Any]) -> t.Callable[..., t.Any]: + """Register a function to be called when the context tears down. + + This can be used to close resources opened during the script + execution. Resources that support Python's context manager + protocol which would be used in a ``with`` statement should be + registered with :meth:`with_resource` instead. + + :param f: The function to execute on teardown. + """ + return self._exit_stack.callback(f) + + def close(self) -> None: + """Invoke all close callbacks registered with + :meth:`call_on_close`, and exit all context managers entered + with :meth:`with_resource`. + """ + self._exit_stack.close() + # In case the context is reused, create a new exit stack. + self._exit_stack = ExitStack() + + @property + def command_path(self) -> str: + """The computed command path. This is used for the ``usage`` + information on the help page. It's automatically created by + combining the info names of the chain of contexts to the root. + """ + rv = "" + if self.info_name is not None: + rv = self.info_name + if self.parent is not None: + parent_command_path = [self.parent.command_path] + + if isinstance(self.parent.command, Command): + for param in self.parent.command.get_params(self): + parent_command_path.extend(param.get_usage_pieces(self)) + + rv = f"{' '.join(parent_command_path)} {rv}" + return rv.lstrip() + + def find_root(self) -> "Context": + """Finds the outermost context.""" + node = self + while node.parent is not None: + node = node.parent + return node + + def find_object(self, object_type: t.Type[V]) -> t.Optional[V]: + """Finds the closest object of a given type.""" + node: t.Optional[Context] = self + + while node is not None: + if isinstance(node.obj, object_type): + return node.obj + + node = node.parent + + return None + + def ensure_object(self, object_type: t.Type[V]) -> V: + """Like :meth:`find_object` but sets the innermost object to a + new instance of `object_type` if it does not exist. + """ + rv = self.find_object(object_type) + if rv is None: + self.obj = rv = object_type() + return rv + + @t.overload + def lookup_default( + self, name: str, call: "te.Literal[True]" = True + ) -> t.Optional[t.Any]: ... + + @t.overload + def lookup_default( + self, name: str, call: "te.Literal[False]" = ... + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: ... + + def lookup_default(self, name: str, call: bool = True) -> t.Optional[t.Any]: + """Get the default for a parameter from :attr:`default_map`. + + :param name: Name of the parameter. + :param call: If the default is a callable, call it. Disable to + return the callable instead. + + .. versionchanged:: 8.0 + Added the ``call`` parameter. + """ + if self.default_map is not None: + value = self.default_map.get(name) + + if call and callable(value): + return value() + + return value + + return None + + def fail(self, message: str) -> "te.NoReturn": + """Aborts the execution of the program with a specific error + message. + + :param message: the error message to fail with. + """ + raise UsageError(message, self) + + def abort(self) -> "te.NoReturn": + """Aborts the script.""" + raise Abort() + + def exit(self, code: int = 0) -> "te.NoReturn": + """Exits the application with a given exit code.""" + raise Exit(code) + + def get_usage(self) -> str: + """Helper method to get formatted usage string for the current + context and command. + """ + return self.command.get_usage(self) + + def get_help(self) -> str: + """Helper method to get formatted help page for the current + context and command. + """ + return self.command.get_help(self) + + def _make_sub_context(self, command: "Command") -> "Context": + """Create a new context of the same type as this context, but + for a new command. + + :meta private: + """ + return type(self)(command, info_name=command.name, parent=self) + + @t.overload + def invoke( + __self, + __callback: "t.Callable[..., V]", + *args: t.Any, + **kwargs: t.Any, + ) -> V: ... + + @t.overload + def invoke( + __self, + __callback: "Command", + *args: t.Any, + **kwargs: t.Any, + ) -> t.Any: ... + + def invoke( + __self, + __callback: t.Union["Command", "t.Callable[..., V]"], + *args: t.Any, + **kwargs: t.Any, + ) -> t.Union[t.Any, V]: + """Invokes a command callback in exactly the way it expects. There + are two ways to invoke this method: + + 1. the first argument can be a callback and all other arguments and + keyword arguments are forwarded directly to the function. + 2. the first argument is a click command object. In that case all + arguments are forwarded as well but proper click parameters + (options and click arguments) must be keyword arguments and Click + will fill in defaults. + + Note that before Click 3.2 keyword arguments were not properly filled + in against the intention of this code and no context was created. For + more information about this change and why it was done in a bugfix + release see :ref:`upgrade-to-3.2`. + + .. versionchanged:: 8.0 + All ``kwargs`` are tracked in :attr:`params` so they will be + passed if :meth:`forward` is called at multiple levels. + """ + if isinstance(__callback, Command): + other_cmd = __callback + + if other_cmd.callback is None: + raise TypeError( + "The given command does not have a callback that can be invoked." + ) + else: + __callback = t.cast("t.Callable[..., V]", other_cmd.callback) + + ctx = __self._make_sub_context(other_cmd) + + for param in other_cmd.params: + if param.name not in kwargs and param.expose_value: + kwargs[param.name] = param.type_cast_value( # type: ignore + ctx, param.get_default(ctx) + ) + + # Track all kwargs as params, so that forward() will pass + # them on in subsequent calls. + ctx.params.update(kwargs) + else: + ctx = __self + + with augment_usage_errors(__self): + with ctx: + return __callback(*args, **kwargs) + + def forward(__self, __cmd: "Command", *args: t.Any, **kwargs: t.Any) -> t.Any: + """Similar to :meth:`invoke` but fills in default keyword + arguments from the current context if the other command expects + it. This cannot invoke callbacks directly, only other commands. + + .. versionchanged:: 8.0 + All ``kwargs`` are tracked in :attr:`params` so they will be + passed if ``forward`` is called at multiple levels. + """ + # Can only forward to other commands, not direct callbacks. + if not isinstance(__cmd, Command): + raise TypeError("Callback is not a command.") + + for param in __self.params: + if param not in kwargs: + kwargs[param] = __self.params[param] + + return __self.invoke(__cmd, *args, **kwargs) + + def set_parameter_source(self, name: str, source: ParameterSource) -> None: + """Set the source of a parameter. This indicates the location + from which the value of the parameter was obtained. + + :param name: The name of the parameter. + :param source: A member of :class:`~click.core.ParameterSource`. + """ + self._parameter_source[name] = source + + def get_parameter_source(self, name: str) -> t.Optional[ParameterSource]: + """Get the source of a parameter. This indicates the location + from which the value of the parameter was obtained. + + This can be useful for determining when a user specified a value + on the command line that is the same as the default value. It + will be :attr:`~click.core.ParameterSource.DEFAULT` only if the + value was actually taken from the default. + + :param name: The name of the parameter. + :rtype: ParameterSource + + .. versionchanged:: 8.0 + Returns ``None`` if the parameter was not provided from any + source. + """ + return self._parameter_source.get(name) + + +class BaseCommand: + """The base command implements the minimal API contract of commands. + Most code will never use this as it does not implement a lot of useful + functionality but it can act as the direct subclass of alternative + parsing methods that do not depend on the Click parser. + + For instance, this can be used to bridge Click and other systems like + argparse or docopt. + + Because base commands do not implement a lot of the API that other + parts of Click take for granted, they are not supported for all + operations. For instance, they cannot be used with the decorators + usually and they have no built-in callback system. + + .. versionchanged:: 2.0 + Added the `context_settings` parameter. + + :param name: the name of the command to use unless a group overrides it. + :param context_settings: an optional dictionary with defaults that are + passed to the context object. + """ + + #: The context class to create with :meth:`make_context`. + #: + #: .. versionadded:: 8.0 + context_class: t.Type[Context] = Context + #: the default for the :attr:`Context.allow_extra_args` flag. + allow_extra_args = False + #: the default for the :attr:`Context.allow_interspersed_args` flag. + allow_interspersed_args = True + #: the default for the :attr:`Context.ignore_unknown_options` flag. + ignore_unknown_options = False + + def __init__( + self, + name: t.Optional[str], + context_settings: t.Optional[t.MutableMapping[str, t.Any]] = None, + ) -> None: + #: the name the command thinks it has. Upon registering a command + #: on a :class:`Group` the group will default the command name + #: with this information. You should instead use the + #: :class:`Context`\'s :attr:`~Context.info_name` attribute. + self.name = name + + if context_settings is None: + context_settings = {} + + #: an optional dictionary with defaults passed to the context. + self.context_settings: t.MutableMapping[str, t.Any] = context_settings + + def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. This traverses the entire structure + below this command. + + Use :meth:`click.Context.to_info_dict` to traverse the entire + CLI structure. + + :param ctx: A :class:`Context` representing this command. + + .. versionadded:: 8.0 + """ + return {"name": self.name} + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} {self.name}>" + + def get_usage(self, ctx: Context) -> str: + raise NotImplementedError("Base commands cannot get usage") + + def get_help(self, ctx: Context) -> str: + raise NotImplementedError("Base commands cannot get help") + + def make_context( + self, + info_name: t.Optional[str], + args: t.List[str], + parent: t.Optional[Context] = None, + **extra: t.Any, + ) -> Context: + """This function when given an info name and arguments will kick + off the parsing and create a new :class:`Context`. It does not + invoke the actual command callback though. + + To quickly customize the context class used without overriding + this method, set the :attr:`context_class` attribute. + + :param info_name: the info name for this invocation. Generally this + is the most descriptive name for the script or + command. For the toplevel script it's usually + the name of the script, for commands below it's + the name of the command. + :param args: the arguments to parse as list of strings. + :param parent: the parent context if available. + :param extra: extra keyword arguments forwarded to the context + constructor. + + .. versionchanged:: 8.0 + Added the :attr:`context_class` attribute. + """ + for key, value in self.context_settings.items(): + if key not in extra: + extra[key] = value + + ctx = self.context_class( + self, # type: ignore[arg-type] + info_name=info_name, + parent=parent, + **extra, + ) + + with ctx.scope(cleanup=False): + self.parse_args(ctx, args) + return ctx + + def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: + """Given a context and a list of arguments this creates the parser + and parses the arguments, then modifies the context as necessary. + This is automatically invoked by :meth:`make_context`. + """ + raise NotImplementedError("Base commands do not know how to parse arguments.") + + def invoke(self, ctx: Context) -> t.Any: + """Given a context, this invokes the command. The default + implementation is raising a not implemented error. + """ + raise NotImplementedError("Base commands are not invocable by default") + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. Looks + at the names of chained multi-commands. + + Any command could be part of a chained multi-command, so sibling + commands are valid at any point during command completion. Other + command classes will return more completions. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + results: t.List[CompletionItem] = [] + + while ctx.parent is not None: + ctx = ctx.parent + + if isinstance(ctx.command, MultiCommand) and ctx.command.chain: + results.extend( + CompletionItem(name, help=command.get_short_help_str()) + for name, command in _complete_visible_commands(ctx, incomplete) + if name not in ctx.protected_args + ) + + return results + + @t.overload + def main( + self, + args: t.Optional[t.Sequence[str]] = None, + prog_name: t.Optional[str] = None, + complete_var: t.Optional[str] = None, + standalone_mode: "te.Literal[True]" = True, + **extra: t.Any, + ) -> "te.NoReturn": ... + + @t.overload + def main( + self, + args: t.Optional[t.Sequence[str]] = None, + prog_name: t.Optional[str] = None, + complete_var: t.Optional[str] = None, + standalone_mode: bool = ..., + **extra: t.Any, + ) -> t.Any: ... + + def main( + self, + args: t.Optional[t.Sequence[str]] = None, + prog_name: t.Optional[str] = None, + complete_var: t.Optional[str] = None, + standalone_mode: bool = True, + windows_expand_args: bool = True, + **extra: t.Any, + ) -> t.Any: + """This is the way to invoke a script with all the bells and + whistles as a command line application. This will always terminate + the application after a call. If this is not wanted, ``SystemExit`` + needs to be caught. + + This method is also available by directly calling the instance of + a :class:`Command`. + + :param args: the arguments that should be used for parsing. If not + provided, ``sys.argv[1:]`` is used. + :param prog_name: the program name that should be used. By default + the program name is constructed by taking the file + name from ``sys.argv[0]``. + :param complete_var: the environment variable that controls the + bash completion support. The default is + ``"__COMPLETE"`` with prog_name in + uppercase. + :param standalone_mode: the default behavior is to invoke the script + in standalone mode. Click will then + handle exceptions and convert them into + error messages and the function will never + return but shut down the interpreter. If + this is set to `False` they will be + propagated to the caller and the return + value of this function is the return value + of :meth:`invoke`. + :param windows_expand_args: Expand glob patterns, user dir, and + env vars in command line args on Windows. + :param extra: extra keyword arguments are forwarded to the context + constructor. See :class:`Context` for more information. + + .. versionchanged:: 8.0.1 + Added the ``windows_expand_args`` parameter to allow + disabling command line arg expansion on Windows. + + .. versionchanged:: 8.0 + When taking arguments from ``sys.argv`` on Windows, glob + patterns, user dir, and env vars are expanded. + + .. versionchanged:: 3.0 + Added the ``standalone_mode`` parameter. + """ + if args is None: + args = sys.argv[1:] + + if os.name == "nt" and windows_expand_args: + args = _expand_args(args) + else: + args = list(args) + + if prog_name is None: + prog_name = _detect_program_name() + + # Process shell completion requests and exit early. + self._main_shell_completion(extra, prog_name, complete_var) + + try: + try: + with self.make_context(prog_name, args, **extra) as ctx: + rv = self.invoke(ctx) + if not standalone_mode: + return rv + # it's not safe to `ctx.exit(rv)` here! + # note that `rv` may actually contain data like "1" which + # has obvious effects + # more subtle case: `rv=[None, None]` can come out of + # chained commands which all returned `None` -- so it's not + # even always obvious that `rv` indicates success/failure + # by its truthiness/falsiness + ctx.exit() + except (EOFError, KeyboardInterrupt) as e: + echo(file=sys.stderr) + raise Abort() from e + except ClickException as e: + if not standalone_mode: + raise + e.show() + sys.exit(e.exit_code) + except OSError as e: + if e.errno == errno.EPIPE: + sys.stdout = t.cast(t.TextIO, PacifyFlushWrapper(sys.stdout)) + sys.stderr = t.cast(t.TextIO, PacifyFlushWrapper(sys.stderr)) + sys.exit(1) + else: + raise + except Exit as e: + if standalone_mode: + sys.exit(e.exit_code) + else: + # in non-standalone mode, return the exit code + # note that this is only reached if `self.invoke` above raises + # an Exit explicitly -- thus bypassing the check there which + # would return its result + # the results of non-standalone execution may therefore be + # somewhat ambiguous: if there are codepaths which lead to + # `ctx.exit(1)` and to `return 1`, the caller won't be able to + # tell the difference between the two + return e.exit_code + except Abort: + if not standalone_mode: + raise + echo(_("Aborted!"), file=sys.stderr) + sys.exit(1) + + def _main_shell_completion( + self, + ctx_args: t.MutableMapping[str, t.Any], + prog_name: str, + complete_var: t.Optional[str] = None, + ) -> None: + """Check if the shell is asking for tab completion, process + that, then exit early. Called from :meth:`main` before the + program is invoked. + + :param prog_name: Name of the executable in the shell. + :param complete_var: Name of the environment variable that holds + the completion instruction. Defaults to + ``_{PROG_NAME}_COMPLETE``. + + .. versionchanged:: 8.2.0 + Dots (``.``) in ``prog_name`` are replaced with underscores (``_``). + """ + if complete_var is None: + complete_name = prog_name.replace("-", "_").replace(".", "_") + complete_var = f"_{complete_name}_COMPLETE".upper() + + instruction = os.environ.get(complete_var) + + if not instruction: + return + + from .shell_completion import shell_complete + + rv = shell_complete(self, ctx_args, prog_name, complete_var, instruction) + sys.exit(rv) + + def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Any: + """Alias for :meth:`main`.""" + return self.main(*args, **kwargs) + + +class Command(BaseCommand): + """Commands are the basic building block of command line interfaces in + Click. A basic command handles command line parsing and might dispatch + more parsing to commands nested below it. + + :param name: the name of the command to use unless a group overrides it. + :param context_settings: an optional dictionary with defaults that are + passed to the context object. + :param callback: the callback to invoke. This is optional. + :param params: the parameters to register with this command. This can + be either :class:`Option` or :class:`Argument` objects. + :param help: the help string to use for this command. + :param epilog: like the help string but it's printed at the end of the + help page after everything else. + :param short_help: the short help to use for this command. This is + shown on the command listing of the parent command. + :param add_help_option: by default each command registers a ``--help`` + option. This can be disabled by this parameter. + :param no_args_is_help: this controls what happens if no arguments are + provided. This option is disabled by default. + If enabled this will add ``--help`` as argument + if no arguments are passed + :param hidden: hide this command from help outputs. + + :param deprecated: issues a message indicating that + the command is deprecated. + + .. versionchanged:: 8.1 + ``help``, ``epilog``, and ``short_help`` are stored unprocessed, + all formatting is done when outputting help text, not at init, + and is done even if not using the ``@command`` decorator. + + .. versionchanged:: 8.0 + Added a ``repr`` showing the command name. + + .. versionchanged:: 7.1 + Added the ``no_args_is_help`` parameter. + + .. versionchanged:: 2.0 + Added the ``context_settings`` parameter. + """ + + def __init__( + self, + name: t.Optional[str], + context_settings: t.Optional[t.MutableMapping[str, t.Any]] = None, + callback: t.Optional[t.Callable[..., t.Any]] = None, + params: t.Optional[t.List["Parameter"]] = None, + help: t.Optional[str] = None, + epilog: t.Optional[str] = None, + short_help: t.Optional[str] = None, + options_metavar: t.Optional[str] = "[OPTIONS]", + add_help_option: bool = True, + no_args_is_help: bool = False, + hidden: bool = False, + deprecated: bool = False, + ) -> None: + super().__init__(name, context_settings) + #: the callback to execute when the command fires. This might be + #: `None` in which case nothing happens. + self.callback = callback + #: the list of parameters for this command in the order they + #: should show up in the help page and execute. Eager parameters + #: will automatically be handled before non eager ones. + self.params: t.List[Parameter] = params or [] + self.help = help + self.epilog = epilog + self.options_metavar = options_metavar + self.short_help = short_help + self.add_help_option = add_help_option + self._help_option: t.Optional[HelpOption] = None + self.no_args_is_help = no_args_is_help + self.hidden = hidden + self.deprecated = deprecated + + def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict(ctx) + info_dict.update( + params=[param.to_info_dict() for param in self.get_params(ctx)], + help=self.help, + epilog=self.epilog, + short_help=self.short_help, + hidden=self.hidden, + deprecated=self.deprecated, + ) + return info_dict + + def get_usage(self, ctx: Context) -> str: + """Formats the usage line into a string and returns it. + + Calls :meth:`format_usage` internally. + """ + formatter = ctx.make_formatter() + self.format_usage(ctx, formatter) + return formatter.getvalue().rstrip("\n") + + def get_params(self, ctx: Context) -> t.List["Parameter"]: + rv = self.params + help_option = self.get_help_option(ctx) + + if help_option is not None: + rv = [*rv, help_option] + + return rv + + def format_usage(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the usage line into the formatter. + + This is a low-level method called by :meth:`get_usage`. + """ + pieces = self.collect_usage_pieces(ctx) + formatter.write_usage(ctx.command_path, " ".join(pieces)) + + def collect_usage_pieces(self, ctx: Context) -> t.List[str]: + """Returns all the pieces that go into the usage line and returns + it as a list of strings. + """ + rv = [self.options_metavar] if self.options_metavar else [] + + for param in self.get_params(ctx): + rv.extend(param.get_usage_pieces(ctx)) + + return rv + + def get_help_option_names(self, ctx: Context) -> t.List[str]: + """Returns the names for the help option.""" + all_names = set(ctx.help_option_names) + for param in self.params: + all_names.difference_update(param.opts) + all_names.difference_update(param.secondary_opts) + return list(all_names) + + def get_help_option(self, ctx: Context) -> t.Optional["Option"]: + """Returns the help option object. + + Unless ``add_help_option`` is ``False``. + + .. versionchanged:: 8.1.8 + The help option is now cached to avoid creating it multiple times. + """ + help_options = self.get_help_option_names(ctx) + + if not help_options or not self.add_help_option: + return None + + # Cache the help option object in private _help_option attribute to + # avoid creating it multiple times. Not doing this will break the + # callback odering by iter_params_for_processing(), which relies on + # object comparison. + if self._help_option is None: + # Avoid circular import. + from .decorators import HelpOption + + self._help_option = HelpOption(help_options) + + return self._help_option + + def make_parser(self, ctx: Context) -> OptionParser: + """Creates the underlying option parser for this command.""" + parser = OptionParser(ctx) + for param in self.get_params(ctx): + param.add_to_parser(parser, ctx) + return parser + + def get_help(self, ctx: Context) -> str: + """Formats the help into a string and returns it. + + Calls :meth:`format_help` internally. + """ + formatter = ctx.make_formatter() + self.format_help(ctx, formatter) + return formatter.getvalue().rstrip("\n") + + def get_short_help_str(self, limit: int = 45) -> str: + """Gets short help for the command or makes it by shortening the + long help string. + """ + if self.short_help: + text = inspect.cleandoc(self.short_help) + elif self.help: + text = make_default_short_help(self.help, limit) + else: + text = "" + + if self.deprecated: + text = _("(Deprecated) {text}").format(text=text) + + return text.strip() + + def format_help(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the help into the formatter if it exists. + + This is a low-level method called by :meth:`get_help`. + + This calls the following methods: + + - :meth:`format_usage` + - :meth:`format_help_text` + - :meth:`format_options` + - :meth:`format_epilog` + """ + self.format_usage(ctx, formatter) + self.format_help_text(ctx, formatter) + self.format_options(ctx, formatter) + self.format_epilog(ctx, formatter) + + def format_help_text(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the help text to the formatter if it exists.""" + if self.help is not None: + # truncate the help text to the first form feed + text = inspect.cleandoc(self.help).partition("\f")[0] + else: + text = "" + + if self.deprecated: + text = _("(Deprecated) {text}").format(text=text) + + if text: + formatter.write_paragraph() + + with formatter.indentation(): + formatter.write_text(text) + + def format_options(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes all the options into the formatter if they exist.""" + opts = [] + for param in self.get_params(ctx): + rv = param.get_help_record(ctx) + if rv is not None: + opts.append(rv) + + if opts: + with formatter.section(_("Options")): + formatter.write_dl(opts) + + def format_epilog(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the epilog into the formatter if it exists.""" + if self.epilog: + epilog = inspect.cleandoc(self.epilog) + formatter.write_paragraph() + + with formatter.indentation(): + formatter.write_text(epilog) + + def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: + if not args and self.no_args_is_help and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + parser = self.make_parser(ctx) + opts, args, param_order = parser.parse_args(args=args) + + for param in iter_params_for_processing(param_order, self.get_params(ctx)): + value, args = param.handle_parse_result(ctx, opts, args) + + if args and not ctx.allow_extra_args and not ctx.resilient_parsing: + ctx.fail( + ngettext( + "Got unexpected extra argument ({args})", + "Got unexpected extra arguments ({args})", + len(args), + ).format(args=" ".join(map(str, args))) + ) + + ctx.args = args + ctx._opt_prefixes.update(parser._opt_prefixes) + return args + + def invoke(self, ctx: Context) -> t.Any: + """Given a context, this invokes the attached callback (if it exists) + in the right way. + """ + if self.deprecated: + message = _( + "DeprecationWarning: The command {name!r} is deprecated." + ).format(name=self.name) + echo(style(message, fg="red"), err=True) + + if self.callback is not None: + return ctx.invoke(self.callback, **ctx.params) + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. Looks + at the names of options and chained multi-commands. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + results: t.List[CompletionItem] = [] + + if incomplete and not incomplete[0].isalnum(): + for param in self.get_params(ctx): + if ( + not isinstance(param, Option) + or param.hidden + or ( + not param.multiple + and ctx.get_parameter_source(param.name) # type: ignore + is ParameterSource.COMMANDLINE + ) + ): + continue + + results.extend( + CompletionItem(name, help=param.help) + for name in [*param.opts, *param.secondary_opts] + if name.startswith(incomplete) + ) + + results.extend(super().shell_complete(ctx, incomplete)) + return results + + +class MultiCommand(Command): + """A multi command is the basic implementation of a command that + dispatches to subcommands. The most common version is the + :class:`Group`. + + :param invoke_without_command: this controls how the multi command itself + is invoked. By default it's only invoked + if a subcommand is provided. + :param no_args_is_help: this controls what happens if no arguments are + provided. This option is enabled by default if + `invoke_without_command` is disabled or disabled + if it's enabled. If enabled this will add + ``--help`` as argument if no arguments are + passed. + :param subcommand_metavar: the string that is used in the documentation + to indicate the subcommand place. + :param chain: if this is set to `True` chaining of multiple subcommands + is enabled. This restricts the form of commands in that + they cannot have optional arguments but it allows + multiple commands to be chained together. + :param result_callback: The result callback to attach to this multi + command. This can be set or changed later with the + :meth:`result_callback` decorator. + :param attrs: Other command arguments described in :class:`Command`. + """ + + allow_extra_args = True + allow_interspersed_args = False + + def __init__( + self, + name: t.Optional[str] = None, + invoke_without_command: bool = False, + no_args_is_help: t.Optional[bool] = None, + subcommand_metavar: t.Optional[str] = None, + chain: bool = False, + result_callback: t.Optional[t.Callable[..., t.Any]] = None, + **attrs: t.Any, + ) -> None: + super().__init__(name, **attrs) + + if no_args_is_help is None: + no_args_is_help = not invoke_without_command + + self.no_args_is_help = no_args_is_help + self.invoke_without_command = invoke_without_command + + if subcommand_metavar is None: + if chain: + subcommand_metavar = "COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]..." + else: + subcommand_metavar = "COMMAND [ARGS]..." + + self.subcommand_metavar = subcommand_metavar + self.chain = chain + # The result callback that is stored. This can be set or + # overridden with the :func:`result_callback` decorator. + self._result_callback = result_callback + + if self.chain: + for param in self.params: + if isinstance(param, Argument) and not param.required: + raise RuntimeError( + "Multi commands in chain mode cannot have" + " optional arguments." + ) + + def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict(ctx) + commands = {} + + for name in self.list_commands(ctx): + command = self.get_command(ctx, name) + + if command is None: + continue + + sub_ctx = ctx._make_sub_context(command) + + with sub_ctx.scope(cleanup=False): + commands[name] = command.to_info_dict(sub_ctx) + + info_dict.update(commands=commands, chain=self.chain) + return info_dict + + def collect_usage_pieces(self, ctx: Context) -> t.List[str]: + rv = super().collect_usage_pieces(ctx) + rv.append(self.subcommand_metavar) + return rv + + def format_options(self, ctx: Context, formatter: HelpFormatter) -> None: + super().format_options(ctx, formatter) + self.format_commands(ctx, formatter) + + def result_callback(self, replace: bool = False) -> t.Callable[[F], F]: + """Adds a result callback to the command. By default if a + result callback is already registered this will chain them but + this can be disabled with the `replace` parameter. The result + callback is invoked with the return value of the subcommand + (or the list of return values from all subcommands if chaining + is enabled) as well as the parameters as they would be passed + to the main callback. + + Example:: + + @click.group() + @click.option('-i', '--input', default=23) + def cli(input): + return 42 + + @cli.result_callback() + def process_result(result, input): + return result + input + + :param replace: if set to `True` an already existing result + callback will be removed. + + .. versionchanged:: 8.0 + Renamed from ``resultcallback``. + + .. versionadded:: 3.0 + """ + + def decorator(f: F) -> F: + old_callback = self._result_callback + + if old_callback is None or replace: + self._result_callback = f + return f + + def function(__value, *args, **kwargs): # type: ignore + inner = old_callback(__value, *args, **kwargs) + return f(inner, *args, **kwargs) + + self._result_callback = rv = update_wrapper(t.cast(F, function), f) + return rv # type: ignore[return-value] + + return decorator + + def format_commands(self, ctx: Context, formatter: HelpFormatter) -> None: + """Extra format methods for multi methods that adds all the commands + after the options. + """ + commands = [] + for subcommand in self.list_commands(ctx): + cmd = self.get_command(ctx, subcommand) + # What is this, the tool lied about a command. Ignore it + if cmd is None: + continue + if cmd.hidden: + continue + + commands.append((subcommand, cmd)) + + # allow for 3 times the default spacing + if len(commands): + limit = formatter.width - 6 - max(len(cmd[0]) for cmd in commands) + + rows = [] + for subcommand, cmd in commands: + help = cmd.get_short_help_str(limit) + rows.append((subcommand, help)) + + if rows: + with formatter.section(_("Commands")): + formatter.write_dl(rows) + + def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: + if not args and self.no_args_is_help and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + rest = super().parse_args(ctx, args) + + if self.chain: + ctx.protected_args = rest + ctx.args = [] + elif rest: + ctx.protected_args, ctx.args = rest[:1], rest[1:] + + return ctx.args + + def invoke(self, ctx: Context) -> t.Any: + def _process_result(value: t.Any) -> t.Any: + if self._result_callback is not None: + value = ctx.invoke(self._result_callback, value, **ctx.params) + return value + + if not ctx.protected_args: + if self.invoke_without_command: + # No subcommand was invoked, so the result callback is + # invoked with the group return value for regular + # groups, or an empty list for chained groups. + with ctx: + rv = super().invoke(ctx) + return _process_result([] if self.chain else rv) + ctx.fail(_("Missing command.")) + + # Fetch args back out + args = [*ctx.protected_args, *ctx.args] + ctx.args = [] + ctx.protected_args = [] + + # If we're not in chain mode, we only allow the invocation of a + # single command but we also inform the current context about the + # name of the command to invoke. + if not self.chain: + # Make sure the context is entered so we do not clean up + # resources until the result processor has worked. + with ctx: + cmd_name, cmd, args = self.resolve_command(ctx, args) + assert cmd is not None + ctx.invoked_subcommand = cmd_name + super().invoke(ctx) + sub_ctx = cmd.make_context(cmd_name, args, parent=ctx) + with sub_ctx: + return _process_result(sub_ctx.command.invoke(sub_ctx)) + + # In chain mode we create the contexts step by step, but after the + # base command has been invoked. Because at that point we do not + # know the subcommands yet, the invoked subcommand attribute is + # set to ``*`` to inform the command that subcommands are executed + # but nothing else. + with ctx: + ctx.invoked_subcommand = "*" if args else None + super().invoke(ctx) + + # Otherwise we make every single context and invoke them in a + # chain. In that case the return value to the result processor + # is the list of all invoked subcommand's results. + contexts = [] + while args: + cmd_name, cmd, args = self.resolve_command(ctx, args) + assert cmd is not None + sub_ctx = cmd.make_context( + cmd_name, + args, + parent=ctx, + allow_extra_args=True, + allow_interspersed_args=False, + ) + contexts.append(sub_ctx) + args, sub_ctx.args = sub_ctx.args, [] + + rv = [] + for sub_ctx in contexts: + with sub_ctx: + rv.append(sub_ctx.command.invoke(sub_ctx)) + return _process_result(rv) + + def resolve_command( + self, ctx: Context, args: t.List[str] + ) -> t.Tuple[t.Optional[str], t.Optional[Command], t.List[str]]: + cmd_name = make_str(args[0]) + original_cmd_name = cmd_name + + # Get the command + cmd = self.get_command(ctx, cmd_name) + + # If we can't find the command but there is a normalization + # function available, we try with that one. + if cmd is None and ctx.token_normalize_func is not None: + cmd_name = ctx.token_normalize_func(cmd_name) + cmd = self.get_command(ctx, cmd_name) + + # If we don't find the command we want to show an error message + # to the user that it was not provided. However, there is + # something else we should do: if the first argument looks like + # an option we want to kick off parsing again for arguments to + # resolve things like --help which now should go to the main + # place. + if cmd is None and not ctx.resilient_parsing: + if split_opt(cmd_name)[0]: + self.parse_args(ctx, ctx.args) + ctx.fail(_("No such command {name!r}.").format(name=original_cmd_name)) + return cmd_name if cmd else None, cmd, args[1:] + + def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: + """Given a context and a command name, this returns a + :class:`Command` object if it exists or returns `None`. + """ + raise NotImplementedError + + def list_commands(self, ctx: Context) -> t.List[str]: + """Returns a list of subcommand names in the order they should + appear. + """ + return [] + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. Looks + at the names of options, subcommands, and chained + multi-commands. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + results = [ + CompletionItem(name, help=command.get_short_help_str()) + for name, command in _complete_visible_commands(ctx, incomplete) + ] + results.extend(super().shell_complete(ctx, incomplete)) + return results + + +class Group(MultiCommand): + """A group allows a command to have subcommands attached. This is + the most common way to implement nesting in Click. + + :param name: The name of the group command. + :param commands: A dict mapping names to :class:`Command` objects. + Can also be a list of :class:`Command`, which will use + :attr:`Command.name` to create the dict. + :param attrs: Other command arguments described in + :class:`MultiCommand`, :class:`Command`, and + :class:`BaseCommand`. + + .. versionchanged:: 8.0 + The ``commands`` argument can be a list of command objects. + """ + + #: If set, this is used by the group's :meth:`command` decorator + #: as the default :class:`Command` class. This is useful to make all + #: subcommands use a custom command class. + #: + #: .. versionadded:: 8.0 + command_class: t.Optional[t.Type[Command]] = None + + #: If set, this is used by the group's :meth:`group` decorator + #: as the default :class:`Group` class. This is useful to make all + #: subgroups use a custom group class. + #: + #: If set to the special value :class:`type` (literally + #: ``group_class = type``), this group's class will be used as the + #: default class. This makes a custom group class continue to make + #: custom groups. + #: + #: .. versionadded:: 8.0 + group_class: t.Optional[t.Union[t.Type["Group"], t.Type[type]]] = None + # Literal[type] isn't valid, so use Type[type] + + def __init__( + self, + name: t.Optional[str] = None, + commands: t.Optional[ + t.Union[t.MutableMapping[str, Command], t.Sequence[Command]] + ] = None, + **attrs: t.Any, + ) -> None: + super().__init__(name, **attrs) + + if commands is None: + commands = {} + elif isinstance(commands, abc.Sequence): + commands = {c.name: c for c in commands if c.name is not None} + + #: The registered subcommands by their exported names. + self.commands: t.MutableMapping[str, Command] = commands + + def add_command(self, cmd: Command, name: t.Optional[str] = None) -> None: + """Registers another :class:`Command` with this group. If the name + is not provided, the name of the command is used. + """ + name = name or cmd.name + if name is None: + raise TypeError("Command has no name.") + _check_multicommand(self, name, cmd, register=True) + self.commands[name] = cmd + + @t.overload + def command(self, __func: t.Callable[..., t.Any]) -> Command: ... + + @t.overload + def command( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[t.Callable[..., t.Any]], Command]: ... + + def command( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Union[t.Callable[[t.Callable[..., t.Any]], Command], Command]: + """A shortcut decorator for declaring and attaching a command to + the group. This takes the same arguments as :func:`command` and + immediately registers the created command with this group by + calling :meth:`add_command`. + + To customize the command class used, set the + :attr:`command_class` attribute. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + + .. versionchanged:: 8.0 + Added the :attr:`command_class` attribute. + """ + from .decorators import command + + func: t.Optional[t.Callable[..., t.Any]] = None + + if args and callable(args[0]): + assert ( + len(args) == 1 and not kwargs + ), "Use 'command(**kwargs)(callable)' to provide arguments." + (func,) = args + args = () + + if self.command_class and kwargs.get("cls") is None: + kwargs["cls"] = self.command_class + + def decorator(f: t.Callable[..., t.Any]) -> Command: + cmd: Command = command(*args, **kwargs)(f) + self.add_command(cmd) + return cmd + + if func is not None: + return decorator(func) + + return decorator + + @t.overload + def group(self, __func: t.Callable[..., t.Any]) -> "Group": ... + + @t.overload + def group( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[t.Callable[..., t.Any]], "Group"]: ... + + def group( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Union[t.Callable[[t.Callable[..., t.Any]], "Group"], "Group"]: + """A shortcut decorator for declaring and attaching a group to + the group. This takes the same arguments as :func:`group` and + immediately registers the created group with this group by + calling :meth:`add_command`. + + To customize the group class used, set the :attr:`group_class` + attribute. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + + .. versionchanged:: 8.0 + Added the :attr:`group_class` attribute. + """ + from .decorators import group + + func: t.Optional[t.Callable[..., t.Any]] = None + + if args and callable(args[0]): + assert ( + len(args) == 1 and not kwargs + ), "Use 'group(**kwargs)(callable)' to provide arguments." + (func,) = args + args = () + + if self.group_class is not None and kwargs.get("cls") is None: + if self.group_class is type: + kwargs["cls"] = type(self) + else: + kwargs["cls"] = self.group_class + + def decorator(f: t.Callable[..., t.Any]) -> "Group": + cmd: Group = group(*args, **kwargs)(f) + self.add_command(cmd) + return cmd + + if func is not None: + return decorator(func) + + return decorator + + def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: + return self.commands.get(cmd_name) + + def list_commands(self, ctx: Context) -> t.List[str]: + return sorted(self.commands) + + +class CommandCollection(MultiCommand): + """A command collection is a multi command that merges multiple multi + commands together into one. This is a straightforward implementation + that accepts a list of different multi commands as sources and + provides all the commands for each of them. + + See :class:`MultiCommand` and :class:`Command` for the description of + ``name`` and ``attrs``. + """ + + def __init__( + self, + name: t.Optional[str] = None, + sources: t.Optional[t.List[MultiCommand]] = None, + **attrs: t.Any, + ) -> None: + super().__init__(name, **attrs) + #: The list of registered multi commands. + self.sources: t.List[MultiCommand] = sources or [] + + def add_source(self, multi_cmd: MultiCommand) -> None: + """Adds a new multi command to the chain dispatcher.""" + self.sources.append(multi_cmd) + + def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: + for source in self.sources: + rv = source.get_command(ctx, cmd_name) + + if rv is not None: + if self.chain: + _check_multicommand(self, cmd_name, rv) + + return rv + + return None + + def list_commands(self, ctx: Context) -> t.List[str]: + rv: t.Set[str] = set() + + for source in self.sources: + rv.update(source.list_commands(ctx)) + + return sorted(rv) + + +def _check_iter(value: t.Any) -> t.Iterator[t.Any]: + """Check if the value is iterable but not a string. Raises a type + error, or return an iterator over the value. + """ + if isinstance(value, str): + raise TypeError + + return iter(value) + + +class Parameter: + r"""A parameter to a command comes in two versions: they are either + :class:`Option`\s or :class:`Argument`\s. Other subclasses are currently + not supported by design as some of the internals for parsing are + intentionally not finalized. + + Some settings are supported by both options and arguments. + + :param param_decls: the parameter declarations for this option or + argument. This is a list of flags or argument + names. + :param type: the type that should be used. Either a :class:`ParamType` + or a Python type. The latter is converted into the former + automatically if supported. + :param required: controls if this is optional or not. + :param default: the default value if omitted. This can also be a callable, + in which case it's invoked when the default is needed + without any arguments. + :param callback: A function to further process or validate the value + after type conversion. It is called as ``f(ctx, param, value)`` + and must return the value. It is called for all sources, + including prompts. + :param nargs: the number of arguments to match. If not ``1`` the return + value is a tuple instead of single value. The default for + nargs is ``1`` (except if the type is a tuple, then it's + the arity of the tuple). If ``nargs=-1``, all remaining + parameters are collected. + :param metavar: how the value is represented in the help page. + :param expose_value: if this is `True` then the value is passed onwards + to the command callback and stored on the context, + otherwise it's skipped. + :param is_eager: eager values are processed before non eager ones. This + should not be set for arguments or it will inverse the + order of processing. + :param envvar: a string or list of strings that are environment variables + that should be checked. + :param shell_complete: A function that returns custom shell + completions. Used instead of the param's type completion if + given. Takes ``ctx, param, incomplete`` and must return a list + of :class:`~click.shell_completion.CompletionItem` or a list of + strings. + + .. versionchanged:: 8.0 + ``process_value`` validates required parameters and bounded + ``nargs``, and invokes the parameter callback before returning + the value. This allows the callback to validate prompts. + ``full_process_value`` is removed. + + .. versionchanged:: 8.0 + ``autocompletion`` is renamed to ``shell_complete`` and has new + semantics described above. The old name is deprecated and will + be removed in 8.1, until then it will be wrapped to match the + new requirements. + + .. versionchanged:: 8.0 + For ``multiple=True, nargs>1``, the default must be a list of + tuples. + + .. versionchanged:: 8.0 + Setting a default is no longer required for ``nargs>1``, it will + default to ``None``. ``multiple=True`` or ``nargs=-1`` will + default to ``()``. + + .. versionchanged:: 7.1 + Empty environment variables are ignored rather than taking the + empty string value. This makes it possible for scripts to clear + variables if they can't unset them. + + .. versionchanged:: 2.0 + Changed signature for parameter callback to also be passed the + parameter. The old callback format will still work, but it will + raise a warning to give you a chance to migrate the code easier. + """ + + param_type_name = "parameter" + + def __init__( + self, + param_decls: t.Optional[t.Sequence[str]] = None, + type: t.Optional[t.Union[types.ParamType, t.Any]] = None, + required: bool = False, + default: t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]] = None, + callback: t.Optional[t.Callable[[Context, "Parameter", t.Any], t.Any]] = None, + nargs: t.Optional[int] = None, + multiple: bool = False, + metavar: t.Optional[str] = None, + expose_value: bool = True, + is_eager: bool = False, + envvar: t.Optional[t.Union[str, t.Sequence[str]]] = None, + shell_complete: t.Optional[ + t.Callable[ + [Context, "Parameter", str], + t.Union[t.List["CompletionItem"], t.List[str]], + ] + ] = None, + ) -> None: + self.name: t.Optional[str] + self.opts: t.List[str] + self.secondary_opts: t.List[str] + self.name, self.opts, self.secondary_opts = self._parse_decls( + param_decls or (), expose_value + ) + self.type: types.ParamType = types.convert_type(type, default) + + # Default nargs to what the type tells us if we have that + # information available. + if nargs is None: + if self.type.is_composite: + nargs = self.type.arity + else: + nargs = 1 + + self.required = required + self.callback = callback + self.nargs = nargs + self.multiple = multiple + self.expose_value = expose_value + self.default = default + self.is_eager = is_eager + self.metavar = metavar + self.envvar = envvar + self._custom_shell_complete = shell_complete + + if __debug__: + if self.type.is_composite and nargs != self.type.arity: + raise ValueError( + f"'nargs' must be {self.type.arity} (or None) for" + f" type {self.type!r}, but it was {nargs}." + ) + + # Skip no default or callable default. + check_default = default if not callable(default) else None + + if check_default is not None: + if multiple: + try: + # Only check the first value against nargs. + check_default = next(_check_iter(check_default), None) + except TypeError: + raise ValueError( + "'default' must be a list when 'multiple' is true." + ) from None + + # Can be None for multiple with empty default. + if nargs != 1 and check_default is not None: + try: + _check_iter(check_default) + except TypeError: + if multiple: + message = ( + "'default' must be a list of lists when 'multiple' is" + " true and 'nargs' != 1." + ) + else: + message = "'default' must be a list when 'nargs' != 1." + + raise ValueError(message) from None + + if nargs > 1 and len(check_default) != nargs: + subject = "item length" if multiple else "length" + raise ValueError( + f"'default' {subject} must match nargs={nargs}." + ) + + def to_info_dict(self) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. + + Use :meth:`click.Context.to_info_dict` to traverse the entire + CLI structure. + + .. versionadded:: 8.0 + """ + return { + "name": self.name, + "param_type_name": self.param_type_name, + "opts": self.opts, + "secondary_opts": self.secondary_opts, + "type": self.type.to_info_dict(), + "required": self.required, + "nargs": self.nargs, + "multiple": self.multiple, + "default": self.default, + "envvar": self.envvar, + } + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} {self.name}>" + + def _parse_decls( + self, decls: t.Sequence[str], expose_value: bool + ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: + raise NotImplementedError() + + @property + def human_readable_name(self) -> str: + """Returns the human readable name of this parameter. This is the + same as the name for options, but the metavar for arguments. + """ + return self.name # type: ignore + + def make_metavar(self) -> str: + if self.metavar is not None: + return self.metavar + + metavar = self.type.get_metavar(self) + + if metavar is None: + metavar = self.type.name.upper() + + if self.nargs != 1: + metavar += "..." + + return metavar + + @t.overload + def get_default( + self, ctx: Context, call: "te.Literal[True]" = True + ) -> t.Optional[t.Any]: ... + + @t.overload + def get_default( + self, ctx: Context, call: bool = ... + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: ... + + def get_default( + self, ctx: Context, call: bool = True + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + """Get the default for the parameter. Tries + :meth:`Context.lookup_default` first, then the local default. + + :param ctx: Current context. + :param call: If the default is a callable, call it. Disable to + return the callable instead. + + .. versionchanged:: 8.0.2 + Type casting is no longer performed when getting a default. + + .. versionchanged:: 8.0.1 + Type casting can fail in resilient parsing mode. Invalid + defaults will not prevent showing help text. + + .. versionchanged:: 8.0 + Looks at ``ctx.default_map`` first. + + .. versionchanged:: 8.0 + Added the ``call`` parameter. + """ + value = ctx.lookup_default(self.name, call=False) # type: ignore + + if value is None: + value = self.default + + if call and callable(value): + value = value() + + return value + + def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: + raise NotImplementedError() + + def consume_value( + self, ctx: Context, opts: t.Mapping[str, t.Any] + ) -> t.Tuple[t.Any, ParameterSource]: + value = opts.get(self.name) # type: ignore + source = ParameterSource.COMMANDLINE + + if value is None: + value = self.value_from_envvar(ctx) + source = ParameterSource.ENVIRONMENT + + if value is None: + value = ctx.lookup_default(self.name) # type: ignore + source = ParameterSource.DEFAULT_MAP + + if value is None: + value = self.get_default(ctx) + source = ParameterSource.DEFAULT + + return value, source + + def type_cast_value(self, ctx: Context, value: t.Any) -> t.Any: + """Convert and validate a value against the option's + :attr:`type`, :attr:`multiple`, and :attr:`nargs`. + """ + if value is None: + return () if self.multiple or self.nargs == -1 else None + + def check_iter(value: t.Any) -> t.Iterator[t.Any]: + try: + return _check_iter(value) + except TypeError: + # This should only happen when passing in args manually, + # the parser should construct an iterable when parsing + # the command line. + raise BadParameter( + _("Value must be an iterable."), ctx=ctx, param=self + ) from None + + if self.nargs == 1 or self.type.is_composite: + + def convert(value: t.Any) -> t.Any: + return self.type(value, param=self, ctx=ctx) + + elif self.nargs == -1: + + def convert(value: t.Any) -> t.Any: # t.Tuple[t.Any, ...] + return tuple(self.type(x, self, ctx) for x in check_iter(value)) + + else: # nargs > 1 + + def convert(value: t.Any) -> t.Any: # t.Tuple[t.Any, ...] + value = tuple(check_iter(value)) + + if len(value) != self.nargs: + raise BadParameter( + ngettext( + "Takes {nargs} values but 1 was given.", + "Takes {nargs} values but {len} were given.", + len(value), + ).format(nargs=self.nargs, len=len(value)), + ctx=ctx, + param=self, + ) + + return tuple(self.type(x, self, ctx) for x in value) + + if self.multiple: + return tuple(convert(x) for x in check_iter(value)) + + return convert(value) + + def value_is_missing(self, value: t.Any) -> bool: + if value is None: + return True + + if (self.nargs != 1 or self.multiple) and value == (): + return True + + return False + + def process_value(self, ctx: Context, value: t.Any) -> t.Any: + value = self.type_cast_value(ctx, value) + + if self.required and self.value_is_missing(value): + raise MissingParameter(ctx=ctx, param=self) + + if self.callback is not None: + value = self.callback(ctx, self, value) + + return value + + def resolve_envvar_value(self, ctx: Context) -> t.Optional[str]: + if self.envvar is None: + return None + + if isinstance(self.envvar, str): + rv = os.environ.get(self.envvar) + + if rv: + return rv + else: + for envvar in self.envvar: + rv = os.environ.get(envvar) + + if rv: + return rv + + return None + + def value_from_envvar(self, ctx: Context) -> t.Optional[t.Any]: + rv: t.Optional[t.Any] = self.resolve_envvar_value(ctx) + + if rv is not None and self.nargs != 1: + rv = self.type.split_envvar_value(rv) + + return rv + + def handle_parse_result( + self, ctx: Context, opts: t.Mapping[str, t.Any], args: t.List[str] + ) -> t.Tuple[t.Any, t.List[str]]: + with augment_usage_errors(ctx, param=self): + value, source = self.consume_value(ctx, opts) + ctx.set_parameter_source(self.name, source) # type: ignore + + try: + value = self.process_value(ctx, value) + except Exception: + if not ctx.resilient_parsing: + raise + + value = None + + if self.expose_value: + ctx.params[self.name] = value # type: ignore + + return value, args + + def get_help_record(self, ctx: Context) -> t.Optional[t.Tuple[str, str]]: + pass + + def get_usage_pieces(self, ctx: Context) -> t.List[str]: + return [] + + def get_error_hint(self, ctx: Context) -> str: + """Get a stringified version of the param for use in error messages to + indicate which param caused the error. + """ + hint_list = self.opts or [self.human_readable_name] + return " / ".join(f"'{x}'" for x in hint_list) + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. If a + ``shell_complete`` function was given during init, it is used. + Otherwise, the :attr:`type` + :meth:`~click.types.ParamType.shell_complete` function is used. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + if self._custom_shell_complete is not None: + results = self._custom_shell_complete(ctx, self, incomplete) + + if results and isinstance(results[0], str): + from click.shell_completion import CompletionItem + + results = [CompletionItem(c) for c in results] + + return t.cast(t.List["CompletionItem"], results) + + return self.type.shell_complete(ctx, self, incomplete) + + +class Option(Parameter): + """Options are usually optional values on the command line and + have some extra features that arguments don't have. + + All other parameters are passed onwards to the parameter constructor. + + :param show_default: Show the default value for this option in its + help text. Values are not shown by default, unless + :attr:`Context.show_default` is ``True``. If this value is a + string, it shows that string in parentheses instead of the + actual value. This is particularly useful for dynamic options. + For single option boolean flags, the default remains hidden if + its value is ``False``. + :param show_envvar: Controls if an environment variable should be + shown on the help page. Normally, environment variables are not + shown. + :param prompt: If set to ``True`` or a non empty string then the + user will be prompted for input. If set to ``True`` the prompt + will be the option name capitalized. + :param confirmation_prompt: Prompt a second time to confirm the + value if it was prompted for. Can be set to a string instead of + ``True`` to customize the message. + :param prompt_required: If set to ``False``, the user will be + prompted for input only when the option was specified as a flag + without a value. + :param hide_input: If this is ``True`` then the input on the prompt + will be hidden from the user. This is useful for password input. + :param is_flag: forces this option to act as a flag. The default is + auto detection. + :param flag_value: which value should be used for this flag if it's + enabled. This is set to a boolean automatically if + the option string contains a slash to mark two options. + :param multiple: if this is set to `True` then the argument is accepted + multiple times and recorded. This is similar to ``nargs`` + in how it works but supports arbitrary number of + arguments. + :param count: this flag makes an option increment an integer. + :param allow_from_autoenv: if this is enabled then the value of this + parameter will be pulled from an environment + variable in case a prefix is defined on the + context. + :param help: the help string. + :param hidden: hide this option from help outputs. + :param attrs: Other command arguments described in :class:`Parameter`. + + .. versionchanged:: 8.1.0 + Help text indentation is cleaned here instead of only in the + ``@option`` decorator. + + .. versionchanged:: 8.1.0 + The ``show_default`` parameter overrides + ``Context.show_default``. + + .. versionchanged:: 8.1.0 + The default of a single option boolean flag is not shown if the + default value is ``False``. + + .. versionchanged:: 8.0.1 + ``type`` is detected from ``flag_value`` if given. + """ + + param_type_name = "option" + + def __init__( + self, + param_decls: t.Optional[t.Sequence[str]] = None, + show_default: t.Union[bool, str, None] = None, + prompt: t.Union[bool, str] = False, + confirmation_prompt: t.Union[bool, str] = False, + prompt_required: bool = True, + hide_input: bool = False, + is_flag: t.Optional[bool] = None, + flag_value: t.Optional[t.Any] = None, + multiple: bool = False, + count: bool = False, + allow_from_autoenv: bool = True, + type: t.Optional[t.Union[types.ParamType, t.Any]] = None, + help: t.Optional[str] = None, + hidden: bool = False, + show_choices: bool = True, + show_envvar: bool = False, + **attrs: t.Any, + ) -> None: + if help: + help = inspect.cleandoc(help) + + default_is_missing = "default" not in attrs + super().__init__(param_decls, type=type, multiple=multiple, **attrs) + + if prompt is True: + if self.name is None: + raise TypeError("'name' is required with 'prompt=True'.") + + prompt_text: t.Optional[str] = self.name.replace("_", " ").capitalize() + elif prompt is False: + prompt_text = None + else: + prompt_text = prompt + + self.prompt = prompt_text + self.confirmation_prompt = confirmation_prompt + self.prompt_required = prompt_required + self.hide_input = hide_input + self.hidden = hidden + + # If prompt is enabled but not required, then the option can be + # used as a flag to indicate using prompt or flag_value. + self._flag_needs_value = self.prompt is not None and not self.prompt_required + + if is_flag is None: + if flag_value is not None: + # Implicitly a flag because flag_value was set. + is_flag = True + elif self._flag_needs_value: + # Not a flag, but when used as a flag it shows a prompt. + is_flag = False + else: + # Implicitly a flag because flag options were given. + is_flag = bool(self.secondary_opts) + elif is_flag is False and not self._flag_needs_value: + # Not a flag, and prompt is not enabled, can be used as a + # flag if flag_value is set. + self._flag_needs_value = flag_value is not None + + self.default: t.Union[t.Any, t.Callable[[], t.Any]] + + if is_flag and default_is_missing and not self.required: + if multiple: + self.default = () + else: + self.default = False + + if flag_value is None: + flag_value = not self.default + + self.type: types.ParamType + if is_flag and type is None: + # Re-guess the type from the flag value instead of the + # default. + self.type = types.convert_type(None, flag_value) + + self.is_flag: bool = is_flag + self.is_bool_flag: bool = is_flag and isinstance(self.type, types.BoolParamType) + self.flag_value: t.Any = flag_value + + # Counting + self.count = count + if count: + if type is None: + self.type = types.IntRange(min=0) + if default_is_missing: + self.default = 0 + + self.allow_from_autoenv = allow_from_autoenv + self.help = help + self.show_default = show_default + self.show_choices = show_choices + self.show_envvar = show_envvar + + if __debug__: + if self.nargs == -1: + raise TypeError("nargs=-1 is not supported for options.") + + if self.prompt and self.is_flag and not self.is_bool_flag: + raise TypeError("'prompt' is not valid for non-boolean flag.") + + if not self.is_bool_flag and self.secondary_opts: + raise TypeError("Secondary flag is not valid for non-boolean flag.") + + if self.is_bool_flag and self.hide_input and self.prompt is not None: + raise TypeError( + "'prompt' with 'hide_input' is not valid for boolean flag." + ) + + if self.count: + if self.multiple: + raise TypeError("'count' is not valid with 'multiple'.") + + if self.is_flag: + raise TypeError("'count' is not valid with 'is_flag'.") + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update( + help=self.help, + prompt=self.prompt, + is_flag=self.is_flag, + flag_value=self.flag_value, + count=self.count, + hidden=self.hidden, + ) + return info_dict + + def _parse_decls( + self, decls: t.Sequence[str], expose_value: bool + ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: + opts = [] + secondary_opts = [] + name = None + possible_names = [] + + for decl in decls: + if decl.isidentifier(): + if name is not None: + raise TypeError(f"Name '{name}' defined twice") + name = decl + else: + split_char = ";" if decl[:1] == "/" else "/" + if split_char in decl: + first, second = decl.split(split_char, 1) + first = first.rstrip() + if first: + possible_names.append(split_opt(first)) + opts.append(first) + second = second.lstrip() + if second: + secondary_opts.append(second.lstrip()) + if first == second: + raise ValueError( + f"Boolean option {decl!r} cannot use the" + " same flag for true/false." + ) + else: + possible_names.append(split_opt(decl)) + opts.append(decl) + + if name is None and possible_names: + possible_names.sort(key=lambda x: -len(x[0])) # group long options first + name = possible_names[0][1].replace("-", "_").lower() + if not name.isidentifier(): + name = None + + if name is None: + if not expose_value: + return None, opts, secondary_opts + raise TypeError( + f"Could not determine name for option with declarations {decls!r}" + ) + + if not opts and not secondary_opts: + raise TypeError( + f"No options defined but a name was passed ({name})." + " Did you mean to declare an argument instead? Did" + f" you mean to pass '--{name}'?" + ) + + return name, opts, secondary_opts + + def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: + if self.multiple: + action = "append" + elif self.count: + action = "count" + else: + action = "store" + + if self.is_flag: + action = f"{action}_const" + + if self.is_bool_flag and self.secondary_opts: + parser.add_option( + obj=self, opts=self.opts, dest=self.name, action=action, const=True + ) + parser.add_option( + obj=self, + opts=self.secondary_opts, + dest=self.name, + action=action, + const=False, + ) + else: + parser.add_option( + obj=self, + opts=self.opts, + dest=self.name, + action=action, + const=self.flag_value, + ) + else: + parser.add_option( + obj=self, + opts=self.opts, + dest=self.name, + action=action, + nargs=self.nargs, + ) + + def get_help_record(self, ctx: Context) -> t.Optional[t.Tuple[str, str]]: + if self.hidden: + return None + + any_prefix_is_slash = False + + def _write_opts(opts: t.Sequence[str]) -> str: + nonlocal any_prefix_is_slash + + rv, any_slashes = join_options(opts) + + if any_slashes: + any_prefix_is_slash = True + + if not self.is_flag and not self.count: + rv += f" {self.make_metavar()}" + + return rv + + rv = [_write_opts(self.opts)] + + if self.secondary_opts: + rv.append(_write_opts(self.secondary_opts)) + + help = self.help or "" + extra = [] + + if self.show_envvar: + envvar = self.envvar + + if envvar is None: + if ( + self.allow_from_autoenv + and ctx.auto_envvar_prefix is not None + and self.name is not None + ): + envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}" + + if envvar is not None: + var_str = ( + envvar + if isinstance(envvar, str) + else ", ".join(str(d) for d in envvar) + ) + extra.append(_("env var: {var}").format(var=var_str)) + + # Temporarily enable resilient parsing to avoid type casting + # failing for the default. Might be possible to extend this to + # help formatting in general. + resilient = ctx.resilient_parsing + ctx.resilient_parsing = True + + try: + default_value = self.get_default(ctx, call=False) + finally: + ctx.resilient_parsing = resilient + + show_default = False + show_default_is_str = False + + if self.show_default is not None: + if isinstance(self.show_default, str): + show_default_is_str = show_default = True + else: + show_default = self.show_default + elif ctx.show_default is not None: + show_default = ctx.show_default + + if show_default_is_str or (show_default and (default_value is not None)): + if show_default_is_str: + default_string = f"({self.show_default})" + elif isinstance(default_value, (list, tuple)): + default_string = ", ".join(str(d) for d in default_value) + elif inspect.isfunction(default_value): + default_string = _("(dynamic)") + elif self.is_bool_flag and self.secondary_opts: + # For boolean flags that have distinct True/False opts, + # use the opt without prefix instead of the value. + default_string = split_opt( + (self.opts if default_value else self.secondary_opts)[0] + )[1] + elif self.is_bool_flag and not self.secondary_opts and not default_value: + default_string = "" + elif default_value == "": + default_string = '""' + else: + default_string = str(default_value) + + if default_string: + extra.append(_("default: {default}").format(default=default_string)) + + if ( + isinstance(self.type, types._NumberRangeBase) + # skip count with default range type + and not (self.count and self.type.min == 0 and self.type.max is None) + ): + range_str = self.type._describe_range() + + if range_str: + extra.append(range_str) + + if self.required: + extra.append(_("required")) + + if extra: + extra_str = "; ".join(extra) + help = f"{help} [{extra_str}]" if help else f"[{extra_str}]" + + return ("; " if any_prefix_is_slash else " / ").join(rv), help + + @t.overload + def get_default( + self, ctx: Context, call: "te.Literal[True]" = True + ) -> t.Optional[t.Any]: ... + + @t.overload + def get_default( + self, ctx: Context, call: bool = ... + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: ... + + def get_default( + self, ctx: Context, call: bool = True + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + # If we're a non boolean flag our default is more complex because + # we need to look at all flags in the same group to figure out + # if we're the default one in which case we return the flag + # value as default. + if self.is_flag and not self.is_bool_flag: + for param in ctx.command.params: + if param.name == self.name and param.default: + return t.cast(Option, param).flag_value + + return None + + return super().get_default(ctx, call=call) + + def prompt_for_value(self, ctx: Context) -> t.Any: + """This is an alternative flow that can be activated in the full + value processing if a value does not exist. It will prompt the + user until a valid value exists and then returns the processed + value as result. + """ + assert self.prompt is not None + + # Calculate the default before prompting anything to be stable. + default = self.get_default(ctx) + + # If this is a prompt for a flag we need to handle this + # differently. + if self.is_bool_flag: + return confirm(self.prompt, default) + + return prompt( + self.prompt, + default=default, + type=self.type, + hide_input=self.hide_input, + show_choices=self.show_choices, + confirmation_prompt=self.confirmation_prompt, + value_proc=lambda x: self.process_value(ctx, x), + ) + + def resolve_envvar_value(self, ctx: Context) -> t.Optional[str]: + rv = super().resolve_envvar_value(ctx) + + if rv is not None: + return rv + + if ( + self.allow_from_autoenv + and ctx.auto_envvar_prefix is not None + and self.name is not None + ): + envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}" + rv = os.environ.get(envvar) + + if rv: + return rv + + return None + + def value_from_envvar(self, ctx: Context) -> t.Optional[t.Any]: + rv: t.Optional[t.Any] = self.resolve_envvar_value(ctx) + + if rv is None: + return None + + value_depth = (self.nargs != 1) + bool(self.multiple) + + if value_depth > 0: + rv = self.type.split_envvar_value(rv) + + if self.multiple and self.nargs != 1: + rv = batch(rv, self.nargs) + + return rv + + def consume_value( + self, ctx: Context, opts: t.Mapping[str, "Parameter"] + ) -> t.Tuple[t.Any, ParameterSource]: + value, source = super().consume_value(ctx, opts) + + # The parser will emit a sentinel value if the option can be + # given as a flag without a value. This is different from None + # to distinguish from the flag not being given at all. + if value is _flag_needs_value: + if self.prompt is not None and not ctx.resilient_parsing: + value = self.prompt_for_value(ctx) + source = ParameterSource.PROMPT + else: + value = self.flag_value + source = ParameterSource.COMMANDLINE + + elif ( + self.multiple + and value is not None + and any(v is _flag_needs_value for v in value) + ): + value = [self.flag_value if v is _flag_needs_value else v for v in value] + source = ParameterSource.COMMANDLINE + + # The value wasn't set, or used the param's default, prompt if + # prompting is enabled. + elif ( + source in {None, ParameterSource.DEFAULT} + and self.prompt is not None + and (self.required or self.prompt_required) + and not ctx.resilient_parsing + ): + value = self.prompt_for_value(ctx) + source = ParameterSource.PROMPT + + return value, source + + +class Argument(Parameter): + """Arguments are positional parameters to a command. They generally + provide fewer features than options but can have infinite ``nargs`` + and are required by default. + + All parameters are passed onwards to the constructor of :class:`Parameter`. + """ + + param_type_name = "argument" + + def __init__( + self, + param_decls: t.Sequence[str], + required: t.Optional[bool] = None, + **attrs: t.Any, + ) -> None: + if required is None: + if attrs.get("default") is not None: + required = False + else: + required = attrs.get("nargs", 1) > 0 + + if "multiple" in attrs: + raise TypeError("__init__() got an unexpected keyword argument 'multiple'.") + + super().__init__(param_decls, required=required, **attrs) + + if __debug__: + if self.default is not None and self.nargs == -1: + raise TypeError("'default' is not supported for nargs=-1.") + + @property + def human_readable_name(self) -> str: + if self.metavar is not None: + return self.metavar + return self.name.upper() # type: ignore + + def make_metavar(self) -> str: + if self.metavar is not None: + return self.metavar + var = self.type.get_metavar(self) + if not var: + var = self.name.upper() # type: ignore + if not self.required: + var = f"[{var}]" + if self.nargs != 1: + var += "..." + return var + + def _parse_decls( + self, decls: t.Sequence[str], expose_value: bool + ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: + if not decls: + if not expose_value: + return None, [], [] + raise TypeError("Argument is marked as exposed, but does not have a name.") + if len(decls) == 1: + name = arg = decls[0] + name = name.replace("-", "_").lower() + else: + raise TypeError( + "Arguments take exactly one parameter declaration, got" + f" {len(decls)}." + ) + return name, [arg], [] + + def get_usage_pieces(self, ctx: Context) -> t.List[str]: + return [self.make_metavar()] + + def get_error_hint(self, ctx: Context) -> str: + return f"'{self.make_metavar()}'" + + def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: + parser.add_argument(dest=self.name, nargs=self.nargs, obj=self) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/decorators.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/decorators.py new file mode 100644 index 0000000..bcf8906 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/decorators.py @@ -0,0 +1,562 @@ +import inspect +import types +import typing as t +from functools import update_wrapper +from gettext import gettext as _ + +from .core import Argument +from .core import Command +from .core import Context +from .core import Group +from .core import Option +from .core import Parameter +from .globals import get_current_context +from .utils import echo + +if t.TYPE_CHECKING: + import typing_extensions as te + + P = te.ParamSpec("P") + +R = t.TypeVar("R") +T = t.TypeVar("T") +_AnyCallable = t.Callable[..., t.Any] +FC = t.TypeVar("FC", bound=t.Union[_AnyCallable, Command]) + + +def pass_context(f: "t.Callable[te.Concatenate[Context, P], R]") -> "t.Callable[P, R]": + """Marks a callback as wanting to receive the current context + object as first argument. + """ + + def new_func(*args: "P.args", **kwargs: "P.kwargs") -> "R": + return f(get_current_context(), *args, **kwargs) + + return update_wrapper(new_func, f) + + +def pass_obj(f: "t.Callable[te.Concatenate[t.Any, P], R]") -> "t.Callable[P, R]": + """Similar to :func:`pass_context`, but only pass the object on the + context onwards (:attr:`Context.obj`). This is useful if that object + represents the state of a nested system. + """ + + def new_func(*args: "P.args", **kwargs: "P.kwargs") -> "R": + return f(get_current_context().obj, *args, **kwargs) + + return update_wrapper(new_func, f) + + +def make_pass_decorator( + object_type: t.Type[T], ensure: bool = False +) -> t.Callable[["t.Callable[te.Concatenate[T, P], R]"], "t.Callable[P, R]"]: + """Given an object type this creates a decorator that will work + similar to :func:`pass_obj` but instead of passing the object of the + current context, it will find the innermost context of type + :func:`object_type`. + + This generates a decorator that works roughly like this:: + + from functools import update_wrapper + + def decorator(f): + @pass_context + def new_func(ctx, *args, **kwargs): + obj = ctx.find_object(object_type) + return ctx.invoke(f, obj, *args, **kwargs) + return update_wrapper(new_func, f) + return decorator + + :param object_type: the type of the object to pass. + :param ensure: if set to `True`, a new object will be created and + remembered on the context if it's not there yet. + """ + + def decorator(f: "t.Callable[te.Concatenate[T, P], R]") -> "t.Callable[P, R]": + def new_func(*args: "P.args", **kwargs: "P.kwargs") -> "R": + ctx = get_current_context() + + obj: t.Optional[T] + if ensure: + obj = ctx.ensure_object(object_type) + else: + obj = ctx.find_object(object_type) + + if obj is None: + raise RuntimeError( + "Managed to invoke callback without a context" + f" object of type {object_type.__name__!r}" + " existing." + ) + + return ctx.invoke(f, obj, *args, **kwargs) + + return update_wrapper(new_func, f) + + return decorator + + +def pass_meta_key( + key: str, *, doc_description: t.Optional[str] = None +) -> "t.Callable[[t.Callable[te.Concatenate[t.Any, P], R]], t.Callable[P, R]]": + """Create a decorator that passes a key from + :attr:`click.Context.meta` as the first argument to the decorated + function. + + :param key: Key in ``Context.meta`` to pass. + :param doc_description: Description of the object being passed, + inserted into the decorator's docstring. Defaults to "the 'key' + key from Context.meta". + + .. versionadded:: 8.0 + """ + + def decorator(f: "t.Callable[te.Concatenate[t.Any, P], R]") -> "t.Callable[P, R]": + def new_func(*args: "P.args", **kwargs: "P.kwargs") -> R: + ctx = get_current_context() + obj = ctx.meta[key] + return ctx.invoke(f, obj, *args, **kwargs) + + return update_wrapper(new_func, f) + + if doc_description is None: + doc_description = f"the {key!r} key from :attr:`click.Context.meta`" + + decorator.__doc__ = ( + f"Decorator that passes {doc_description} as the first argument" + " to the decorated function." + ) + return decorator + + +CmdType = t.TypeVar("CmdType", bound=Command) + + +# variant: no call, directly as decorator for a function. +@t.overload +def command(name: _AnyCallable) -> Command: ... + + +# variant: with positional name and with positional or keyword cls argument: +# @command(namearg, CommandCls, ...) or @command(namearg, cls=CommandCls, ...) +@t.overload +def command( + name: t.Optional[str], + cls: t.Type[CmdType], + **attrs: t.Any, +) -> t.Callable[[_AnyCallable], CmdType]: ... + + +# variant: name omitted, cls _must_ be a keyword argument, @command(cls=CommandCls, ...) +@t.overload +def command( + name: None = None, + *, + cls: t.Type[CmdType], + **attrs: t.Any, +) -> t.Callable[[_AnyCallable], CmdType]: ... + + +# variant: with optional string name, no cls argument provided. +@t.overload +def command( + name: t.Optional[str] = ..., cls: None = None, **attrs: t.Any +) -> t.Callable[[_AnyCallable], Command]: ... + + +def command( + name: t.Union[t.Optional[str], _AnyCallable] = None, + cls: t.Optional[t.Type[CmdType]] = None, + **attrs: t.Any, +) -> t.Union[Command, t.Callable[[_AnyCallable], t.Union[Command, CmdType]]]: + r"""Creates a new :class:`Command` and uses the decorated function as + callback. This will also automatically attach all decorated + :func:`option`\s and :func:`argument`\s as parameters to the command. + + The name of the command defaults to the name of the function with + underscores replaced by dashes. If you want to change that, you can + pass the intended name as the first argument. + + All keyword arguments are forwarded to the underlying command class. + For the ``params`` argument, any decorated params are appended to + the end of the list. + + Once decorated the function turns into a :class:`Command` instance + that can be invoked as a command line utility or be attached to a + command :class:`Group`. + + :param name: the name of the command. This defaults to the function + name with underscores replaced by dashes. + :param cls: the command class to instantiate. This defaults to + :class:`Command`. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + + .. versionchanged:: 8.1 + The ``params`` argument can be used. Decorated params are + appended to the end of the list. + """ + + func: t.Optional[t.Callable[[_AnyCallable], t.Any]] = None + + if callable(name): + func = name + name = None + assert cls is None, "Use 'command(cls=cls)(callable)' to specify a class." + assert not attrs, "Use 'command(**kwargs)(callable)' to provide arguments." + + if cls is None: + cls = t.cast(t.Type[CmdType], Command) + + def decorator(f: _AnyCallable) -> CmdType: + if isinstance(f, Command): + raise TypeError("Attempted to convert a callback into a command twice.") + + attr_params = attrs.pop("params", None) + params = attr_params if attr_params is not None else [] + + try: + decorator_params = f.__click_params__ # type: ignore + except AttributeError: + pass + else: + del f.__click_params__ # type: ignore + params.extend(reversed(decorator_params)) + + if attrs.get("help") is None: + attrs["help"] = f.__doc__ + + if t.TYPE_CHECKING: + assert cls is not None + assert not callable(name) + + cmd = cls( + name=name or f.__name__.lower().replace("_", "-"), + callback=f, + params=params, + **attrs, + ) + cmd.__doc__ = f.__doc__ + return cmd + + if func is not None: + return decorator(func) + + return decorator + + +GrpType = t.TypeVar("GrpType", bound=Group) + + +# variant: no call, directly as decorator for a function. +@t.overload +def group(name: _AnyCallable) -> Group: ... + + +# variant: with positional name and with positional or keyword cls argument: +# @group(namearg, GroupCls, ...) or @group(namearg, cls=GroupCls, ...) +@t.overload +def group( + name: t.Optional[str], + cls: t.Type[GrpType], + **attrs: t.Any, +) -> t.Callable[[_AnyCallable], GrpType]: ... + + +# variant: name omitted, cls _must_ be a keyword argument, @group(cmd=GroupCls, ...) +@t.overload +def group( + name: None = None, + *, + cls: t.Type[GrpType], + **attrs: t.Any, +) -> t.Callable[[_AnyCallable], GrpType]: ... + + +# variant: with optional string name, no cls argument provided. +@t.overload +def group( + name: t.Optional[str] = ..., cls: None = None, **attrs: t.Any +) -> t.Callable[[_AnyCallable], Group]: ... + + +def group( + name: t.Union[str, _AnyCallable, None] = None, + cls: t.Optional[t.Type[GrpType]] = None, + **attrs: t.Any, +) -> t.Union[Group, t.Callable[[_AnyCallable], t.Union[Group, GrpType]]]: + """Creates a new :class:`Group` with a function as callback. This + works otherwise the same as :func:`command` just that the `cls` + parameter is set to :class:`Group`. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + """ + if cls is None: + cls = t.cast(t.Type[GrpType], Group) + + if callable(name): + return command(cls=cls, **attrs)(name) + + return command(name, cls, **attrs) + + +def _param_memo(f: t.Callable[..., t.Any], param: Parameter) -> None: + if isinstance(f, Command): + f.params.append(param) + else: + if not hasattr(f, "__click_params__"): + f.__click_params__ = [] # type: ignore + + f.__click_params__.append(param) # type: ignore + + +def argument( + *param_decls: str, cls: t.Optional[t.Type[Argument]] = None, **attrs: t.Any +) -> t.Callable[[FC], FC]: + """Attaches an argument to the command. All positional arguments are + passed as parameter declarations to :class:`Argument`; all keyword + arguments are forwarded unchanged (except ``cls``). + This is equivalent to creating an :class:`Argument` instance manually + and attaching it to the :attr:`Command.params` list. + + For the default argument class, refer to :class:`Argument` and + :class:`Parameter` for descriptions of parameters. + + :param cls: the argument class to instantiate. This defaults to + :class:`Argument`. + :param param_decls: Passed as positional arguments to the constructor of + ``cls``. + :param attrs: Passed as keyword arguments to the constructor of ``cls``. + """ + if cls is None: + cls = Argument + + def decorator(f: FC) -> FC: + _param_memo(f, cls(param_decls, **attrs)) + return f + + return decorator + + +def option( + *param_decls: str, cls: t.Optional[t.Type[Option]] = None, **attrs: t.Any +) -> t.Callable[[FC], FC]: + """Attaches an option to the command. All positional arguments are + passed as parameter declarations to :class:`Option`; all keyword + arguments are forwarded unchanged (except ``cls``). + This is equivalent to creating an :class:`Option` instance manually + and attaching it to the :attr:`Command.params` list. + + For the default option class, refer to :class:`Option` and + :class:`Parameter` for descriptions of parameters. + + :param cls: the option class to instantiate. This defaults to + :class:`Option`. + :param param_decls: Passed as positional arguments to the constructor of + ``cls``. + :param attrs: Passed as keyword arguments to the constructor of ``cls``. + """ + if cls is None: + cls = Option + + def decorator(f: FC) -> FC: + _param_memo(f, cls(param_decls, **attrs)) + return f + + return decorator + + +def confirmation_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Add a ``--yes`` option which shows a prompt before continuing if + not passed. If the prompt is declined, the program will exit. + + :param param_decls: One or more option names. Defaults to the single + value ``"--yes"``. + :param kwargs: Extra arguments are passed to :func:`option`. + """ + + def callback(ctx: Context, param: Parameter, value: bool) -> None: + if not value: + ctx.abort() + + if not param_decls: + param_decls = ("--yes",) + + kwargs.setdefault("is_flag", True) + kwargs.setdefault("callback", callback) + kwargs.setdefault("expose_value", False) + kwargs.setdefault("prompt", "Do you want to continue?") + kwargs.setdefault("help", "Confirm the action without prompting.") + return option(*param_decls, **kwargs) + + +def password_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Add a ``--password`` option which prompts for a password, hiding + input and asking to enter the value again for confirmation. + + :param param_decls: One or more option names. Defaults to the single + value ``"--password"``. + :param kwargs: Extra arguments are passed to :func:`option`. + """ + if not param_decls: + param_decls = ("--password",) + + kwargs.setdefault("prompt", True) + kwargs.setdefault("confirmation_prompt", True) + kwargs.setdefault("hide_input", True) + return option(*param_decls, **kwargs) + + +def version_option( + version: t.Optional[str] = None, + *param_decls: str, + package_name: t.Optional[str] = None, + prog_name: t.Optional[str] = None, + message: t.Optional[str] = None, + **kwargs: t.Any, +) -> t.Callable[[FC], FC]: + """Add a ``--version`` option which immediately prints the version + number and exits the program. + + If ``version`` is not provided, Click will try to detect it using + :func:`importlib.metadata.version` to get the version for the + ``package_name``. On Python < 3.8, the ``importlib_metadata`` + backport must be installed. + + If ``package_name`` is not provided, Click will try to detect it by + inspecting the stack frames. This will be used to detect the + version, so it must match the name of the installed package. + + :param version: The version number to show. If not provided, Click + will try to detect it. + :param param_decls: One or more option names. Defaults to the single + value ``"--version"``. + :param package_name: The package name to detect the version from. If + not provided, Click will try to detect it. + :param prog_name: The name of the CLI to show in the message. If not + provided, it will be detected from the command. + :param message: The message to show. The values ``%(prog)s``, + ``%(package)s``, and ``%(version)s`` are available. Defaults to + ``"%(prog)s, version %(version)s"``. + :param kwargs: Extra arguments are passed to :func:`option`. + :raise RuntimeError: ``version`` could not be detected. + + .. versionchanged:: 8.0 + Add the ``package_name`` parameter, and the ``%(package)s`` + value for messages. + + .. versionchanged:: 8.0 + Use :mod:`importlib.metadata` instead of ``pkg_resources``. The + version is detected based on the package name, not the entry + point name. The Python package name must match the installed + package name, or be passed with ``package_name=``. + """ + if message is None: + message = _("%(prog)s, version %(version)s") + + if version is None and package_name is None: + frame = inspect.currentframe() + f_back = frame.f_back if frame is not None else None + f_globals = f_back.f_globals if f_back is not None else None + # break reference cycle + # https://docs.python.org/3/library/inspect.html#the-interpreter-stack + del frame + + if f_globals is not None: + package_name = f_globals.get("__name__") + + if package_name == "__main__": + package_name = f_globals.get("__package__") + + if package_name: + package_name = package_name.partition(".")[0] + + def callback(ctx: Context, param: Parameter, value: bool) -> None: + if not value or ctx.resilient_parsing: + return + + nonlocal prog_name + nonlocal version + + if prog_name is None: + prog_name = ctx.find_root().info_name + + if version is None and package_name is not None: + metadata: t.Optional[types.ModuleType] + + try: + from importlib import metadata + except ImportError: + # Python < 3.8 + import importlib_metadata as metadata # type: ignore + + try: + version = metadata.version(package_name) # type: ignore + except metadata.PackageNotFoundError: # type: ignore + raise RuntimeError( + f"{package_name!r} is not installed. Try passing" + " 'package_name' instead." + ) from None + + if version is None: + raise RuntimeError( + f"Could not determine the version for {package_name!r} automatically." + ) + + echo( + message % {"prog": prog_name, "package": package_name, "version": version}, + color=ctx.color, + ) + ctx.exit() + + if not param_decls: + param_decls = ("--version",) + + kwargs.setdefault("is_flag", True) + kwargs.setdefault("expose_value", False) + kwargs.setdefault("is_eager", True) + kwargs.setdefault("help", _("Show the version and exit.")) + kwargs["callback"] = callback + return option(*param_decls, **kwargs) + + +class HelpOption(Option): + """Pre-configured ``--help`` option which immediately prints the help page + and exits the program. + """ + + def __init__( + self, + param_decls: t.Optional[t.Sequence[str]] = None, + **kwargs: t.Any, + ) -> None: + if not param_decls: + param_decls = ("--help",) + + kwargs.setdefault("is_flag", True) + kwargs.setdefault("expose_value", False) + kwargs.setdefault("is_eager", True) + kwargs.setdefault("help", _("Show this message and exit.")) + kwargs.setdefault("callback", self.show_help) + + super().__init__(param_decls, **kwargs) + + @staticmethod + def show_help(ctx: Context, param: Parameter, value: bool) -> None: + """Callback that print the help page on ```` and exits.""" + if value and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + +def help_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Decorator for the pre-configured ``--help`` option defined above. + + :param param_decls: One or more option names. Defaults to the single + value ``"--help"``. + :param kwargs: Extra arguments are passed to :func:`option`. + """ + kwargs.setdefault("cls", HelpOption) + return option(*param_decls, **kwargs) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/exceptions.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/exceptions.py new file mode 100644 index 0000000..0b83151 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/exceptions.py @@ -0,0 +1,296 @@ +import typing as t +from gettext import gettext as _ +from gettext import ngettext + +from ._compat import get_text_stderr +from .globals import resolve_color_default +from .utils import echo +from .utils import format_filename + +if t.TYPE_CHECKING: + from .core import Command + from .core import Context + from .core import Parameter + + +def _join_param_hints( + param_hint: t.Optional[t.Union[t.Sequence[str], str]], +) -> t.Optional[str]: + if param_hint is not None and not isinstance(param_hint, str): + return " / ".join(repr(x) for x in param_hint) + + return param_hint + + +class ClickException(Exception): + """An exception that Click can handle and show to the user.""" + + #: The exit code for this exception. + exit_code = 1 + + def __init__(self, message: str) -> None: + super().__init__(message) + # The context will be removed by the time we print the message, so cache + # the color settings here to be used later on (in `show`) + self.show_color: t.Optional[bool] = resolve_color_default() + self.message = message + + def format_message(self) -> str: + return self.message + + def __str__(self) -> str: + return self.message + + def show(self, file: t.Optional[t.IO[t.Any]] = None) -> None: + if file is None: + file = get_text_stderr() + + echo( + _("Error: {message}").format(message=self.format_message()), + file=file, + color=self.show_color, + ) + + +class UsageError(ClickException): + """An internal exception that signals a usage error. This typically + aborts any further handling. + + :param message: the error message to display. + :param ctx: optionally the context that caused this error. Click will + fill in the context automatically in some situations. + """ + + exit_code = 2 + + def __init__(self, message: str, ctx: t.Optional["Context"] = None) -> None: + super().__init__(message) + self.ctx = ctx + self.cmd: t.Optional[Command] = self.ctx.command if self.ctx else None + + def show(self, file: t.Optional[t.IO[t.Any]] = None) -> None: + if file is None: + file = get_text_stderr() + color = None + hint = "" + if ( + self.ctx is not None + and self.ctx.command.get_help_option(self.ctx) is not None + ): + hint = _("Try '{command} {option}' for help.").format( + command=self.ctx.command_path, option=self.ctx.help_option_names[0] + ) + hint = f"{hint}\n" + if self.ctx is not None: + color = self.ctx.color + echo(f"{self.ctx.get_usage()}\n{hint}", file=file, color=color) + echo( + _("Error: {message}").format(message=self.format_message()), + file=file, + color=color, + ) + + +class BadParameter(UsageError): + """An exception that formats out a standardized error message for a + bad parameter. This is useful when thrown from a callback or type as + Click will attach contextual information to it (for instance, which + parameter it is). + + .. versionadded:: 2.0 + + :param param: the parameter object that caused this error. This can + be left out, and Click will attach this info itself + if possible. + :param param_hint: a string that shows up as parameter name. This + can be used as alternative to `param` in cases + where custom validation should happen. If it is + a string it's used as such, if it's a list then + each item is quoted and separated. + """ + + def __init__( + self, + message: str, + ctx: t.Optional["Context"] = None, + param: t.Optional["Parameter"] = None, + param_hint: t.Optional[str] = None, + ) -> None: + super().__init__(message, ctx) + self.param = param + self.param_hint = param_hint + + def format_message(self) -> str: + if self.param_hint is not None: + param_hint = self.param_hint + elif self.param is not None: + param_hint = self.param.get_error_hint(self.ctx) # type: ignore + else: + return _("Invalid value: {message}").format(message=self.message) + + return _("Invalid value for {param_hint}: {message}").format( + param_hint=_join_param_hints(param_hint), message=self.message + ) + + +class MissingParameter(BadParameter): + """Raised if click required an option or argument but it was not + provided when invoking the script. + + .. versionadded:: 4.0 + + :param param_type: a string that indicates the type of the parameter. + The default is to inherit the parameter type from + the given `param`. Valid values are ``'parameter'``, + ``'option'`` or ``'argument'``. + """ + + def __init__( + self, + message: t.Optional[str] = None, + ctx: t.Optional["Context"] = None, + param: t.Optional["Parameter"] = None, + param_hint: t.Optional[str] = None, + param_type: t.Optional[str] = None, + ) -> None: + super().__init__(message or "", ctx, param, param_hint) + self.param_type = param_type + + def format_message(self) -> str: + if self.param_hint is not None: + param_hint: t.Optional[str] = self.param_hint + elif self.param is not None: + param_hint = self.param.get_error_hint(self.ctx) # type: ignore + else: + param_hint = None + + param_hint = _join_param_hints(param_hint) + param_hint = f" {param_hint}" if param_hint else "" + + param_type = self.param_type + if param_type is None and self.param is not None: + param_type = self.param.param_type_name + + msg = self.message + if self.param is not None: + msg_extra = self.param.type.get_missing_message(self.param) + if msg_extra: + if msg: + msg += f". {msg_extra}" + else: + msg = msg_extra + + msg = f" {msg}" if msg else "" + + # Translate param_type for known types. + if param_type == "argument": + missing = _("Missing argument") + elif param_type == "option": + missing = _("Missing option") + elif param_type == "parameter": + missing = _("Missing parameter") + else: + missing = _("Missing {param_type}").format(param_type=param_type) + + return f"{missing}{param_hint}.{msg}" + + def __str__(self) -> str: + if not self.message: + param_name = self.param.name if self.param else None + return _("Missing parameter: {param_name}").format(param_name=param_name) + else: + return self.message + + +class NoSuchOption(UsageError): + """Raised if click attempted to handle an option that does not + exist. + + .. versionadded:: 4.0 + """ + + def __init__( + self, + option_name: str, + message: t.Optional[str] = None, + possibilities: t.Optional[t.Sequence[str]] = None, + ctx: t.Optional["Context"] = None, + ) -> None: + if message is None: + message = _("No such option: {name}").format(name=option_name) + + super().__init__(message, ctx) + self.option_name = option_name + self.possibilities = possibilities + + def format_message(self) -> str: + if not self.possibilities: + return self.message + + possibility_str = ", ".join(sorted(self.possibilities)) + suggest = ngettext( + "Did you mean {possibility}?", + "(Possible options: {possibilities})", + len(self.possibilities), + ).format(possibility=possibility_str, possibilities=possibility_str) + return f"{self.message} {suggest}" + + +class BadOptionUsage(UsageError): + """Raised if an option is generally supplied but the use of the option + was incorrect. This is for instance raised if the number of arguments + for an option is not correct. + + .. versionadded:: 4.0 + + :param option_name: the name of the option being used incorrectly. + """ + + def __init__( + self, option_name: str, message: str, ctx: t.Optional["Context"] = None + ) -> None: + super().__init__(message, ctx) + self.option_name = option_name + + +class BadArgumentUsage(UsageError): + """Raised if an argument is generally supplied but the use of the argument + was incorrect. This is for instance raised if the number of values + for an argument is not correct. + + .. versionadded:: 6.0 + """ + + +class FileError(ClickException): + """Raised if a file cannot be opened.""" + + def __init__(self, filename: str, hint: t.Optional[str] = None) -> None: + if hint is None: + hint = _("unknown error") + + super().__init__(hint) + self.ui_filename: str = format_filename(filename) + self.filename = filename + + def format_message(self) -> str: + return _("Could not open file {filename!r}: {message}").format( + filename=self.ui_filename, message=self.message + ) + + +class Abort(RuntimeError): + """An internal signalling exception that signals Click to abort.""" + + +class Exit(RuntimeError): + """An exception that indicates that the application should exit with some + status code. + + :param code: the status code to exit with. + """ + + __slots__ = ("exit_code",) + + def __init__(self, code: int = 0) -> None: + self.exit_code: int = code diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/formatting.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/formatting.py new file mode 100644 index 0000000..ddd2a2f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/formatting.py @@ -0,0 +1,301 @@ +import typing as t +from contextlib import contextmanager +from gettext import gettext as _ + +from ._compat import term_len +from .parser import split_opt + +# Can force a width. This is used by the test system +FORCED_WIDTH: t.Optional[int] = None + + +def measure_table(rows: t.Iterable[t.Tuple[str, str]]) -> t.Tuple[int, ...]: + widths: t.Dict[int, int] = {} + + for row in rows: + for idx, col in enumerate(row): + widths[idx] = max(widths.get(idx, 0), term_len(col)) + + return tuple(y for x, y in sorted(widths.items())) + + +def iter_rows( + rows: t.Iterable[t.Tuple[str, str]], col_count: int +) -> t.Iterator[t.Tuple[str, ...]]: + for row in rows: + yield row + ("",) * (col_count - len(row)) + + +def wrap_text( + text: str, + width: int = 78, + initial_indent: str = "", + subsequent_indent: str = "", + preserve_paragraphs: bool = False, +) -> str: + """A helper function that intelligently wraps text. By default, it + assumes that it operates on a single paragraph of text but if the + `preserve_paragraphs` parameter is provided it will intelligently + handle paragraphs (defined by two empty lines). + + If paragraphs are handled, a paragraph can be prefixed with an empty + line containing the ``\\b`` character (``\\x08``) to indicate that + no rewrapping should happen in that block. + + :param text: the text that should be rewrapped. + :param width: the maximum width for the text. + :param initial_indent: the initial indent that should be placed on the + first line as a string. + :param subsequent_indent: the indent string that should be placed on + each consecutive line. + :param preserve_paragraphs: if this flag is set then the wrapping will + intelligently handle paragraphs. + """ + from ._textwrap import TextWrapper + + text = text.expandtabs() + wrapper = TextWrapper( + width, + initial_indent=initial_indent, + subsequent_indent=subsequent_indent, + replace_whitespace=False, + ) + if not preserve_paragraphs: + return wrapper.fill(text) + + p: t.List[t.Tuple[int, bool, str]] = [] + buf: t.List[str] = [] + indent = None + + def _flush_par() -> None: + if not buf: + return + if buf[0].strip() == "\b": + p.append((indent or 0, True, "\n".join(buf[1:]))) + else: + p.append((indent or 0, False, " ".join(buf))) + del buf[:] + + for line in text.splitlines(): + if not line: + _flush_par() + indent = None + else: + if indent is None: + orig_len = term_len(line) + line = line.lstrip() + indent = orig_len - term_len(line) + buf.append(line) + _flush_par() + + rv = [] + for indent, raw, text in p: + with wrapper.extra_indent(" " * indent): + if raw: + rv.append(wrapper.indent_only(text)) + else: + rv.append(wrapper.fill(text)) + + return "\n\n".join(rv) + + +class HelpFormatter: + """This class helps with formatting text-based help pages. It's + usually just needed for very special internal cases, but it's also + exposed so that developers can write their own fancy outputs. + + At present, it always writes into memory. + + :param indent_increment: the additional increment for each level. + :param width: the width for the text. This defaults to the terminal + width clamped to a maximum of 78. + """ + + def __init__( + self, + indent_increment: int = 2, + width: t.Optional[int] = None, + max_width: t.Optional[int] = None, + ) -> None: + import shutil + + self.indent_increment = indent_increment + if max_width is None: + max_width = 80 + if width is None: + width = FORCED_WIDTH + if width is None: + width = max(min(shutil.get_terminal_size().columns, max_width) - 2, 50) + self.width = width + self.current_indent = 0 + self.buffer: t.List[str] = [] + + def write(self, string: str) -> None: + """Writes a unicode string into the internal buffer.""" + self.buffer.append(string) + + def indent(self) -> None: + """Increases the indentation.""" + self.current_indent += self.indent_increment + + def dedent(self) -> None: + """Decreases the indentation.""" + self.current_indent -= self.indent_increment + + def write_usage( + self, prog: str, args: str = "", prefix: t.Optional[str] = None + ) -> None: + """Writes a usage line into the buffer. + + :param prog: the program name. + :param args: whitespace separated list of arguments. + :param prefix: The prefix for the first line. Defaults to + ``"Usage: "``. + """ + if prefix is None: + prefix = f"{_('Usage:')} " + + usage_prefix = f"{prefix:>{self.current_indent}}{prog} " + text_width = self.width - self.current_indent + + if text_width >= (term_len(usage_prefix) + 20): + # The arguments will fit to the right of the prefix. + indent = " " * term_len(usage_prefix) + self.write( + wrap_text( + args, + text_width, + initial_indent=usage_prefix, + subsequent_indent=indent, + ) + ) + else: + # The prefix is too long, put the arguments on the next line. + self.write(usage_prefix) + self.write("\n") + indent = " " * (max(self.current_indent, term_len(prefix)) + 4) + self.write( + wrap_text( + args, text_width, initial_indent=indent, subsequent_indent=indent + ) + ) + + self.write("\n") + + def write_heading(self, heading: str) -> None: + """Writes a heading into the buffer.""" + self.write(f"{'':>{self.current_indent}}{heading}:\n") + + def write_paragraph(self) -> None: + """Writes a paragraph into the buffer.""" + if self.buffer: + self.write("\n") + + def write_text(self, text: str) -> None: + """Writes re-indented text into the buffer. This rewraps and + preserves paragraphs. + """ + indent = " " * self.current_indent + self.write( + wrap_text( + text, + self.width, + initial_indent=indent, + subsequent_indent=indent, + preserve_paragraphs=True, + ) + ) + self.write("\n") + + def write_dl( + self, + rows: t.Sequence[t.Tuple[str, str]], + col_max: int = 30, + col_spacing: int = 2, + ) -> None: + """Writes a definition list into the buffer. This is how options + and commands are usually formatted. + + :param rows: a list of two item tuples for the terms and values. + :param col_max: the maximum width of the first column. + :param col_spacing: the number of spaces between the first and + second column. + """ + rows = list(rows) + widths = measure_table(rows) + if len(widths) != 2: + raise TypeError("Expected two columns for definition list") + + first_col = min(widths[0], col_max) + col_spacing + + for first, second in iter_rows(rows, len(widths)): + self.write(f"{'':>{self.current_indent}}{first}") + if not second: + self.write("\n") + continue + if term_len(first) <= first_col - col_spacing: + self.write(" " * (first_col - term_len(first))) + else: + self.write("\n") + self.write(" " * (first_col + self.current_indent)) + + text_width = max(self.width - first_col - 2, 10) + wrapped_text = wrap_text(second, text_width, preserve_paragraphs=True) + lines = wrapped_text.splitlines() + + if lines: + self.write(f"{lines[0]}\n") + + for line in lines[1:]: + self.write(f"{'':>{first_col + self.current_indent}}{line}\n") + else: + self.write("\n") + + @contextmanager + def section(self, name: str) -> t.Iterator[None]: + """Helpful context manager that writes a paragraph, a heading, + and the indents. + + :param name: the section name that is written as heading. + """ + self.write_paragraph() + self.write_heading(name) + self.indent() + try: + yield + finally: + self.dedent() + + @contextmanager + def indentation(self) -> t.Iterator[None]: + """A context manager that increases the indentation.""" + self.indent() + try: + yield + finally: + self.dedent() + + def getvalue(self) -> str: + """Returns the buffer contents.""" + return "".join(self.buffer) + + +def join_options(options: t.Sequence[str]) -> t.Tuple[str, bool]: + """Given a list of option strings this joins them in the most appropriate + way and returns them in the form ``(formatted_string, + any_prefix_is_slash)`` where the second item in the tuple is a flag that + indicates if any of the option prefixes was a slash. + """ + rv = [] + any_prefix_is_slash = False + + for opt in options: + prefix = split_opt(opt)[0] + + if prefix == "/": + any_prefix_is_slash = True + + rv.append((len(prefix), opt)) + + rv.sort(key=lambda x: x[0]) + return ", ".join(x[1] for x in rv), any_prefix_is_slash diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/globals.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/globals.py new file mode 100644 index 0000000..191e712 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/globals.py @@ -0,0 +1,67 @@ +import typing as t +from threading import local + +if t.TYPE_CHECKING: + import typing_extensions as te + + from .core import Context + +_local = local() + + +@t.overload +def get_current_context(silent: "te.Literal[False]" = False) -> "Context": ... + + +@t.overload +def get_current_context(silent: bool = ...) -> t.Optional["Context"]: ... + + +def get_current_context(silent: bool = False) -> t.Optional["Context"]: + """Returns the current click context. This can be used as a way to + access the current context object from anywhere. This is a more implicit + alternative to the :func:`pass_context` decorator. This function is + primarily useful for helpers such as :func:`echo` which might be + interested in changing its behavior based on the current context. + + To push the current context, :meth:`Context.scope` can be used. + + .. versionadded:: 5.0 + + :param silent: if set to `True` the return value is `None` if no context + is available. The default behavior is to raise a + :exc:`RuntimeError`. + """ + try: + return t.cast("Context", _local.stack[-1]) + except (AttributeError, IndexError) as e: + if not silent: + raise RuntimeError("There is no active click context.") from e + + return None + + +def push_context(ctx: "Context") -> None: + """Pushes a new context to the current stack.""" + _local.__dict__.setdefault("stack", []).append(ctx) + + +def pop_context() -> None: + """Removes the top level from the stack.""" + _local.stack.pop() + + +def resolve_color_default(color: t.Optional[bool] = None) -> t.Optional[bool]: + """Internal helper to get the default value of the color flag. If a + value is passed it's returned unchanged, otherwise it's looked up from + the current context. + """ + if color is not None: + return color + + ctx = get_current_context(silent=True) + + if ctx is not None: + return ctx.color + + return None diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/parser.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/parser.py new file mode 100644 index 0000000..600b843 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/parser.py @@ -0,0 +1,531 @@ +""" +This module started out as largely a copy paste from the stdlib's +optparse module with the features removed that we do not need from +optparse because we implement them in Click on a higher level (for +instance type handling, help formatting and a lot more). + +The plan is to remove more and more from here over time. + +The reason this is a different module and not optparse from the stdlib +is that there are differences in 2.x and 3.x about the error messages +generated and optparse in the stdlib uses gettext for no good reason +and might cause us issues. + +Click uses parts of optparse written by Gregory P. Ward and maintained +by the Python Software Foundation. This is limited to code in parser.py. + +Copyright 2001-2006 Gregory P. Ward. All rights reserved. +Copyright 2002-2006 Python Software Foundation. All rights reserved. +""" + +# This code uses parts of optparse written by Gregory P. Ward and +# maintained by the Python Software Foundation. +# Copyright 2001-2006 Gregory P. Ward +# Copyright 2002-2006 Python Software Foundation +import typing as t +from collections import deque +from gettext import gettext as _ +from gettext import ngettext + +from .exceptions import BadArgumentUsage +from .exceptions import BadOptionUsage +from .exceptions import NoSuchOption +from .exceptions import UsageError + +if t.TYPE_CHECKING: + import typing_extensions as te + + from .core import Argument as CoreArgument + from .core import Context + from .core import Option as CoreOption + from .core import Parameter as CoreParameter + +V = t.TypeVar("V") + +# Sentinel value that indicates an option was passed as a flag without a +# value but is not a flag option. Option.consume_value uses this to +# prompt or use the flag_value. +_flag_needs_value = object() + + +def _unpack_args( + args: t.Sequence[str], nargs_spec: t.Sequence[int] +) -> t.Tuple[t.Sequence[t.Union[str, t.Sequence[t.Optional[str]], None]], t.List[str]]: + """Given an iterable of arguments and an iterable of nargs specifications, + it returns a tuple with all the unpacked arguments at the first index + and all remaining arguments as the second. + + The nargs specification is the number of arguments that should be consumed + or `-1` to indicate that this position should eat up all the remainders. + + Missing items are filled with `None`. + """ + args = deque(args) + nargs_spec = deque(nargs_spec) + rv: t.List[t.Union[str, t.Tuple[t.Optional[str], ...], None]] = [] + spos: t.Optional[int] = None + + def _fetch(c: "te.Deque[V]") -> t.Optional[V]: + try: + if spos is None: + return c.popleft() + else: + return c.pop() + except IndexError: + return None + + while nargs_spec: + nargs = _fetch(nargs_spec) + + if nargs is None: + continue + + if nargs == 1: + rv.append(_fetch(args)) + elif nargs > 1: + x = [_fetch(args) for _ in range(nargs)] + + # If we're reversed, we're pulling in the arguments in reverse, + # so we need to turn them around. + if spos is not None: + x.reverse() + + rv.append(tuple(x)) + elif nargs < 0: + if spos is not None: + raise TypeError("Cannot have two nargs < 0") + + spos = len(rv) + rv.append(None) + + # spos is the position of the wildcard (star). If it's not `None`, + # we fill it with the remainder. + if spos is not None: + rv[spos] = tuple(args) + args = [] + rv[spos + 1 :] = reversed(rv[spos + 1 :]) + + return tuple(rv), list(args) + + +def split_opt(opt: str) -> t.Tuple[str, str]: + first = opt[:1] + if first.isalnum(): + return "", opt + if opt[1:2] == first: + return opt[:2], opt[2:] + return first, opt[1:] + + +def normalize_opt(opt: str, ctx: t.Optional["Context"]) -> str: + if ctx is None or ctx.token_normalize_func is None: + return opt + prefix, opt = split_opt(opt) + return f"{prefix}{ctx.token_normalize_func(opt)}" + + +def split_arg_string(string: str) -> t.List[str]: + """Split an argument string as with :func:`shlex.split`, but don't + fail if the string is incomplete. Ignores a missing closing quote or + incomplete escape sequence and uses the partial token as-is. + + .. code-block:: python + + split_arg_string("example 'my file") + ["example", "my file"] + + split_arg_string("example my\\") + ["example", "my"] + + :param string: String to split. + """ + import shlex + + lex = shlex.shlex(string, posix=True) + lex.whitespace_split = True + lex.commenters = "" + out = [] + + try: + for token in lex: + out.append(token) + except ValueError: + # Raised when end-of-string is reached in an invalid state. Use + # the partial token as-is. The quote or escape character is in + # lex.state, not lex.token. + out.append(lex.token) + + return out + + +class Option: + def __init__( + self, + obj: "CoreOption", + opts: t.Sequence[str], + dest: t.Optional[str], + action: t.Optional[str] = None, + nargs: int = 1, + const: t.Optional[t.Any] = None, + ): + self._short_opts = [] + self._long_opts = [] + self.prefixes: t.Set[str] = set() + + for opt in opts: + prefix, value = split_opt(opt) + if not prefix: + raise ValueError(f"Invalid start character for option ({opt})") + self.prefixes.add(prefix[0]) + if len(prefix) == 1 and len(value) == 1: + self._short_opts.append(opt) + else: + self._long_opts.append(opt) + self.prefixes.add(prefix) + + if action is None: + action = "store" + + self.dest = dest + self.action = action + self.nargs = nargs + self.const = const + self.obj = obj + + @property + def takes_value(self) -> bool: + return self.action in ("store", "append") + + def process(self, value: t.Any, state: "ParsingState") -> None: + if self.action == "store": + state.opts[self.dest] = value # type: ignore + elif self.action == "store_const": + state.opts[self.dest] = self.const # type: ignore + elif self.action == "append": + state.opts.setdefault(self.dest, []).append(value) # type: ignore + elif self.action == "append_const": + state.opts.setdefault(self.dest, []).append(self.const) # type: ignore + elif self.action == "count": + state.opts[self.dest] = state.opts.get(self.dest, 0) + 1 # type: ignore + else: + raise ValueError(f"unknown action '{self.action}'") + state.order.append(self.obj) + + +class Argument: + def __init__(self, obj: "CoreArgument", dest: t.Optional[str], nargs: int = 1): + self.dest = dest + self.nargs = nargs + self.obj = obj + + def process( + self, + value: t.Union[t.Optional[str], t.Sequence[t.Optional[str]]], + state: "ParsingState", + ) -> None: + if self.nargs > 1: + assert value is not None + holes = sum(1 for x in value if x is None) + if holes == len(value): + value = None + elif holes != 0: + raise BadArgumentUsage( + _("Argument {name!r} takes {nargs} values.").format( + name=self.dest, nargs=self.nargs + ) + ) + + if self.nargs == -1 and self.obj.envvar is not None and value == (): + # Replace empty tuple with None so that a value from the + # environment may be tried. + value = None + + state.opts[self.dest] = value # type: ignore + state.order.append(self.obj) + + +class ParsingState: + def __init__(self, rargs: t.List[str]) -> None: + self.opts: t.Dict[str, t.Any] = {} + self.largs: t.List[str] = [] + self.rargs = rargs + self.order: t.List[CoreParameter] = [] + + +class OptionParser: + """The option parser is an internal class that is ultimately used to + parse options and arguments. It's modelled after optparse and brings + a similar but vastly simplified API. It should generally not be used + directly as the high level Click classes wrap it for you. + + It's not nearly as extensible as optparse or argparse as it does not + implement features that are implemented on a higher level (such as + types or defaults). + + :param ctx: optionally the :class:`~click.Context` where this parser + should go with. + """ + + def __init__(self, ctx: t.Optional["Context"] = None) -> None: + #: The :class:`~click.Context` for this parser. This might be + #: `None` for some advanced use cases. + self.ctx = ctx + #: This controls how the parser deals with interspersed arguments. + #: If this is set to `False`, the parser will stop on the first + #: non-option. Click uses this to implement nested subcommands + #: safely. + self.allow_interspersed_args: bool = True + #: This tells the parser how to deal with unknown options. By + #: default it will error out (which is sensible), but there is a + #: second mode where it will ignore it and continue processing + #: after shifting all the unknown options into the resulting args. + self.ignore_unknown_options: bool = False + + if ctx is not None: + self.allow_interspersed_args = ctx.allow_interspersed_args + self.ignore_unknown_options = ctx.ignore_unknown_options + + self._short_opt: t.Dict[str, Option] = {} + self._long_opt: t.Dict[str, Option] = {} + self._opt_prefixes = {"-", "--"} + self._args: t.List[Argument] = [] + + def add_option( + self, + obj: "CoreOption", + opts: t.Sequence[str], + dest: t.Optional[str], + action: t.Optional[str] = None, + nargs: int = 1, + const: t.Optional[t.Any] = None, + ) -> None: + """Adds a new option named `dest` to the parser. The destination + is not inferred (unlike with optparse) and needs to be explicitly + provided. Action can be any of ``store``, ``store_const``, + ``append``, ``append_const`` or ``count``. + + The `obj` can be used to identify the option in the order list + that is returned from the parser. + """ + opts = [normalize_opt(opt, self.ctx) for opt in opts] + option = Option(obj, opts, dest, action=action, nargs=nargs, const=const) + self._opt_prefixes.update(option.prefixes) + for opt in option._short_opts: + self._short_opt[opt] = option + for opt in option._long_opts: + self._long_opt[opt] = option + + def add_argument( + self, obj: "CoreArgument", dest: t.Optional[str], nargs: int = 1 + ) -> None: + """Adds a positional argument named `dest` to the parser. + + The `obj` can be used to identify the option in the order list + that is returned from the parser. + """ + self._args.append(Argument(obj, dest=dest, nargs=nargs)) + + def parse_args( + self, args: t.List[str] + ) -> t.Tuple[t.Dict[str, t.Any], t.List[str], t.List["CoreParameter"]]: + """Parses positional arguments and returns ``(values, args, order)`` + for the parsed options and arguments as well as the leftover + arguments if there are any. The order is a list of objects as they + appear on the command line. If arguments appear multiple times they + will be memorized multiple times as well. + """ + state = ParsingState(args) + try: + self._process_args_for_options(state) + self._process_args_for_args(state) + except UsageError: + if self.ctx is None or not self.ctx.resilient_parsing: + raise + return state.opts, state.largs, state.order + + def _process_args_for_args(self, state: ParsingState) -> None: + pargs, args = _unpack_args( + state.largs + state.rargs, [x.nargs for x in self._args] + ) + + for idx, arg in enumerate(self._args): + arg.process(pargs[idx], state) + + state.largs = args + state.rargs = [] + + def _process_args_for_options(self, state: ParsingState) -> None: + while state.rargs: + arg = state.rargs.pop(0) + arglen = len(arg) + # Double dashes always handled explicitly regardless of what + # prefixes are valid. + if arg == "--": + return + elif arg[:1] in self._opt_prefixes and arglen > 1: + self._process_opts(arg, state) + elif self.allow_interspersed_args: + state.largs.append(arg) + else: + state.rargs.insert(0, arg) + return + + # Say this is the original argument list: + # [arg0, arg1, ..., arg(i-1), arg(i), arg(i+1), ..., arg(N-1)] + # ^ + # (we are about to process arg(i)). + # + # Then rargs is [arg(i), ..., arg(N-1)] and largs is a *subset* of + # [arg0, ..., arg(i-1)] (any options and their arguments will have + # been removed from largs). + # + # The while loop will usually consume 1 or more arguments per pass. + # If it consumes 1 (eg. arg is an option that takes no arguments), + # then after _process_arg() is done the situation is: + # + # largs = subset of [arg0, ..., arg(i)] + # rargs = [arg(i+1), ..., arg(N-1)] + # + # If allow_interspersed_args is false, largs will always be + # *empty* -- still a subset of [arg0, ..., arg(i-1)], but + # not a very interesting subset! + + def _match_long_opt( + self, opt: str, explicit_value: t.Optional[str], state: ParsingState + ) -> None: + if opt not in self._long_opt: + from difflib import get_close_matches + + possibilities = get_close_matches(opt, self._long_opt) + raise NoSuchOption(opt, possibilities=possibilities, ctx=self.ctx) + + option = self._long_opt[opt] + if option.takes_value: + # At this point it's safe to modify rargs by injecting the + # explicit value, because no exception is raised in this + # branch. This means that the inserted value will be fully + # consumed. + if explicit_value is not None: + state.rargs.insert(0, explicit_value) + + value = self._get_value_from_state(opt, option, state) + + elif explicit_value is not None: + raise BadOptionUsage( + opt, _("Option {name!r} does not take a value.").format(name=opt) + ) + + else: + value = None + + option.process(value, state) + + def _match_short_opt(self, arg: str, state: ParsingState) -> None: + stop = False + i = 1 + prefix = arg[0] + unknown_options = [] + + for ch in arg[1:]: + opt = normalize_opt(f"{prefix}{ch}", self.ctx) + option = self._short_opt.get(opt) + i += 1 + + if not option: + if self.ignore_unknown_options: + unknown_options.append(ch) + continue + raise NoSuchOption(opt, ctx=self.ctx) + if option.takes_value: + # Any characters left in arg? Pretend they're the + # next arg, and stop consuming characters of arg. + if i < len(arg): + state.rargs.insert(0, arg[i:]) + stop = True + + value = self._get_value_from_state(opt, option, state) + + else: + value = None + + option.process(value, state) + + if stop: + break + + # If we got any unknown options we recombine the string of the + # remaining options and re-attach the prefix, then report that + # to the state as new larg. This way there is basic combinatorics + # that can be achieved while still ignoring unknown arguments. + if self.ignore_unknown_options and unknown_options: + state.largs.append(f"{prefix}{''.join(unknown_options)}") + + def _get_value_from_state( + self, option_name: str, option: Option, state: ParsingState + ) -> t.Any: + nargs = option.nargs + + if len(state.rargs) < nargs: + if option.obj._flag_needs_value: + # Option allows omitting the value. + value = _flag_needs_value + else: + raise BadOptionUsage( + option_name, + ngettext( + "Option {name!r} requires an argument.", + "Option {name!r} requires {nargs} arguments.", + nargs, + ).format(name=option_name, nargs=nargs), + ) + elif nargs == 1: + next_rarg = state.rargs[0] + + if ( + option.obj._flag_needs_value + and isinstance(next_rarg, str) + and next_rarg[:1] in self._opt_prefixes + and len(next_rarg) > 1 + ): + # The next arg looks like the start of an option, don't + # use it as the value if omitting the value is allowed. + value = _flag_needs_value + else: + value = state.rargs.pop(0) + else: + value = tuple(state.rargs[:nargs]) + del state.rargs[:nargs] + + return value + + def _process_opts(self, arg: str, state: ParsingState) -> None: + explicit_value = None + # Long option handling happens in two parts. The first part is + # supporting explicitly attached values. In any case, we will try + # to long match the option first. + if "=" in arg: + long_opt, explicit_value = arg.split("=", 1) + else: + long_opt = arg + norm_long_opt = normalize_opt(long_opt, self.ctx) + + # At this point we will match the (assumed) long option through + # the long option matching code. Note that this allows options + # like "-foo" to be matched as long options. + try: + self._match_long_opt(norm_long_opt, explicit_value, state) + except NoSuchOption: + # At this point the long option matching failed, and we need + # to try with short options. However there is a special rule + # which says, that if we have a two character options prefix + # (applies to "--foo" for instance), we do not dispatch to the + # short option code and will instead raise the no option + # error. + if arg[:2] not in self._opt_prefixes: + self._match_short_opt(arg, state) + return + + if not self.ignore_unknown_options: + raise + + state.largs.append(arg) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/py.typed b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/shell_completion.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/shell_completion.py new file mode 100644 index 0000000..07d0f09 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/shell_completion.py @@ -0,0 +1,603 @@ +import os +import re +import typing as t +from gettext import gettext as _ + +from .core import Argument +from .core import BaseCommand +from .core import Context +from .core import MultiCommand +from .core import Option +from .core import Parameter +from .core import ParameterSource +from .parser import split_arg_string +from .utils import echo + + +def shell_complete( + cli: BaseCommand, + ctx_args: t.MutableMapping[str, t.Any], + prog_name: str, + complete_var: str, + instruction: str, +) -> int: + """Perform shell completion for the given CLI program. + + :param cli: Command being called. + :param ctx_args: Extra arguments to pass to + ``cli.make_context``. + :param prog_name: Name of the executable in the shell. + :param complete_var: Name of the environment variable that holds + the completion instruction. + :param instruction: Value of ``complete_var`` with the completion + instruction and shell, in the form ``instruction_shell``. + :return: Status code to exit with. + """ + shell, _, instruction = instruction.partition("_") + comp_cls = get_completion_class(shell) + + if comp_cls is None: + return 1 + + comp = comp_cls(cli, ctx_args, prog_name, complete_var) + + if instruction == "source": + echo(comp.source()) + return 0 + + if instruction == "complete": + echo(comp.complete()) + return 0 + + return 1 + + +class CompletionItem: + """Represents a completion value and metadata about the value. The + default metadata is ``type`` to indicate special shell handling, + and ``help`` if a shell supports showing a help string next to the + value. + + Arbitrary parameters can be passed when creating the object, and + accessed using ``item.attr``. If an attribute wasn't passed, + accessing it returns ``None``. + + :param value: The completion suggestion. + :param type: Tells the shell script to provide special completion + support for the type. Click uses ``"dir"`` and ``"file"``. + :param help: String shown next to the value if supported. + :param kwargs: Arbitrary metadata. The built-in implementations + don't use this, but custom type completions paired with custom + shell support could use it. + """ + + __slots__ = ("value", "type", "help", "_info") + + def __init__( + self, + value: t.Any, + type: str = "plain", + help: t.Optional[str] = None, + **kwargs: t.Any, + ) -> None: + self.value: t.Any = value + self.type: str = type + self.help: t.Optional[str] = help + self._info = kwargs + + def __getattr__(self, name: str) -> t.Any: + return self._info.get(name) + + +# Only Bash >= 4.4 has the nosort option. +_SOURCE_BASH = """\ +%(complete_func)s() { + local IFS=$'\\n' + local response + + response=$(env COMP_WORDS="${COMP_WORDS[*]}" COMP_CWORD=$COMP_CWORD \ +%(complete_var)s=bash_complete $1) + + for completion in $response; do + IFS=',' read type value <<< "$completion" + + if [[ $type == 'dir' ]]; then + COMPREPLY=() + compopt -o dirnames + elif [[ $type == 'file' ]]; then + COMPREPLY=() + compopt -o default + elif [[ $type == 'plain' ]]; then + COMPREPLY+=($value) + fi + done + + return 0 +} + +%(complete_func)s_setup() { + complete -o nosort -F %(complete_func)s %(prog_name)s +} + +%(complete_func)s_setup; +""" + +_SOURCE_ZSH = """\ +#compdef %(prog_name)s + +%(complete_func)s() { + local -a completions + local -a completions_with_descriptions + local -a response + (( ! $+commands[%(prog_name)s] )) && return 1 + + response=("${(@f)$(env COMP_WORDS="${words[*]}" COMP_CWORD=$((CURRENT-1)) \ +%(complete_var)s=zsh_complete %(prog_name)s)}") + + for type key descr in ${response}; do + if [[ "$type" == "plain" ]]; then + if [[ "$descr" == "_" ]]; then + completions+=("$key") + else + completions_with_descriptions+=("$key":"$descr") + fi + elif [[ "$type" == "dir" ]]; then + _path_files -/ + elif [[ "$type" == "file" ]]; then + _path_files -f + fi + done + + if [ -n "$completions_with_descriptions" ]; then + _describe -V unsorted completions_with_descriptions -U + fi + + if [ -n "$completions" ]; then + compadd -U -V unsorted -a completions + fi +} + +if [[ $zsh_eval_context[-1] == loadautofunc ]]; then + # autoload from fpath, call function directly + %(complete_func)s "$@" +else + # eval/source/. command, register function for later + compdef %(complete_func)s %(prog_name)s +fi +""" + +_SOURCE_FISH = """\ +function %(complete_func)s; + set -l response (env %(complete_var)s=fish_complete COMP_WORDS=(commandline -cp) \ +COMP_CWORD=(commandline -t) %(prog_name)s); + + for completion in $response; + set -l metadata (string split "," $completion); + + if test $metadata[1] = "dir"; + __fish_complete_directories $metadata[2]; + else if test $metadata[1] = "file"; + __fish_complete_path $metadata[2]; + else if test $metadata[1] = "plain"; + echo $metadata[2]; + end; + end; +end; + +complete --no-files --command %(prog_name)s --arguments \ +"(%(complete_func)s)"; +""" + + +class ShellComplete: + """Base class for providing shell completion support. A subclass for + a given shell will override attributes and methods to implement the + completion instructions (``source`` and ``complete``). + + :param cli: Command being called. + :param prog_name: Name of the executable in the shell. + :param complete_var: Name of the environment variable that holds + the completion instruction. + + .. versionadded:: 8.0 + """ + + name: t.ClassVar[str] + """Name to register the shell as with :func:`add_completion_class`. + This is used in completion instructions (``{name}_source`` and + ``{name}_complete``). + """ + + source_template: t.ClassVar[str] + """Completion script template formatted by :meth:`source`. This must + be provided by subclasses. + """ + + def __init__( + self, + cli: BaseCommand, + ctx_args: t.MutableMapping[str, t.Any], + prog_name: str, + complete_var: str, + ) -> None: + self.cli = cli + self.ctx_args = ctx_args + self.prog_name = prog_name + self.complete_var = complete_var + + @property + def func_name(self) -> str: + """The name of the shell function defined by the completion + script. + """ + safe_name = re.sub(r"\W*", "", self.prog_name.replace("-", "_"), flags=re.ASCII) + return f"_{safe_name}_completion" + + def source_vars(self) -> t.Dict[str, t.Any]: + """Vars for formatting :attr:`source_template`. + + By default this provides ``complete_func``, ``complete_var``, + and ``prog_name``. + """ + return { + "complete_func": self.func_name, + "complete_var": self.complete_var, + "prog_name": self.prog_name, + } + + def source(self) -> str: + """Produce the shell script that defines the completion + function. By default this ``%``-style formats + :attr:`source_template` with the dict returned by + :meth:`source_vars`. + """ + return self.source_template % self.source_vars() + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + """Use the env vars defined by the shell script to return a + tuple of ``args, incomplete``. This must be implemented by + subclasses. + """ + raise NotImplementedError + + def get_completions( + self, args: t.List[str], incomplete: str + ) -> t.List[CompletionItem]: + """Determine the context and last complete command or parameter + from the complete args. Call that object's ``shell_complete`` + method to get the completions for the incomplete value. + + :param args: List of complete args before the incomplete value. + :param incomplete: Value being completed. May be empty. + """ + ctx = _resolve_context(self.cli, self.ctx_args, self.prog_name, args) + obj, incomplete = _resolve_incomplete(ctx, args, incomplete) + return obj.shell_complete(ctx, incomplete) + + def format_completion(self, item: CompletionItem) -> str: + """Format a completion item into the form recognized by the + shell script. This must be implemented by subclasses. + + :param item: Completion item to format. + """ + raise NotImplementedError + + def complete(self) -> str: + """Produce the completion data to send back to the shell. + + By default this calls :meth:`get_completion_args`, gets the + completions, then calls :meth:`format_completion` for each + completion. + """ + args, incomplete = self.get_completion_args() + completions = self.get_completions(args, incomplete) + out = [self.format_completion(item) for item in completions] + return "\n".join(out) + + +class BashComplete(ShellComplete): + """Shell completion for Bash.""" + + name = "bash" + source_template = _SOURCE_BASH + + @staticmethod + def _check_version() -> None: + import shutil + import subprocess + + bash_exe = shutil.which("bash") + + if bash_exe is None: + match = None + else: + output = subprocess.run( + [bash_exe, "--norc", "-c", 'echo "${BASH_VERSION}"'], + stdout=subprocess.PIPE, + ) + match = re.search(r"^(\d+)\.(\d+)\.\d+", output.stdout.decode()) + + if match is not None: + major, minor = match.groups() + + if major < "4" or major == "4" and minor < "4": + echo( + _( + "Shell completion is not supported for Bash" + " versions older than 4.4." + ), + err=True, + ) + else: + echo( + _("Couldn't detect Bash version, shell completion is not supported."), + err=True, + ) + + def source(self) -> str: + self._check_version() + return super().source() + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + cword = int(os.environ["COMP_CWORD"]) + args = cwords[1:cword] + + try: + incomplete = cwords[cword] + except IndexError: + incomplete = "" + + return args, incomplete + + def format_completion(self, item: CompletionItem) -> str: + return f"{item.type},{item.value}" + + +class ZshComplete(ShellComplete): + """Shell completion for Zsh.""" + + name = "zsh" + source_template = _SOURCE_ZSH + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + cword = int(os.environ["COMP_CWORD"]) + args = cwords[1:cword] + + try: + incomplete = cwords[cword] + except IndexError: + incomplete = "" + + return args, incomplete + + def format_completion(self, item: CompletionItem) -> str: + return f"{item.type}\n{item.value}\n{item.help if item.help else '_'}" + + +class FishComplete(ShellComplete): + """Shell completion for Fish.""" + + name = "fish" + source_template = _SOURCE_FISH + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + incomplete = os.environ["COMP_CWORD"] + args = cwords[1:] + + # Fish stores the partial word in both COMP_WORDS and + # COMP_CWORD, remove it from complete args. + if incomplete and args and args[-1] == incomplete: + args.pop() + + return args, incomplete + + def format_completion(self, item: CompletionItem) -> str: + if item.help: + return f"{item.type},{item.value}\t{item.help}" + + return f"{item.type},{item.value}" + + +ShellCompleteType = t.TypeVar("ShellCompleteType", bound=t.Type[ShellComplete]) + + +_available_shells: t.Dict[str, t.Type[ShellComplete]] = { + "bash": BashComplete, + "fish": FishComplete, + "zsh": ZshComplete, +} + + +def add_completion_class( + cls: ShellCompleteType, name: t.Optional[str] = None +) -> ShellCompleteType: + """Register a :class:`ShellComplete` subclass under the given name. + The name will be provided by the completion instruction environment + variable during completion. + + :param cls: The completion class that will handle completion for the + shell. + :param name: Name to register the class under. Defaults to the + class's ``name`` attribute. + """ + if name is None: + name = cls.name + + _available_shells[name] = cls + + return cls + + +def get_completion_class(shell: str) -> t.Optional[t.Type[ShellComplete]]: + """Look up a registered :class:`ShellComplete` subclass by the name + provided by the completion instruction environment variable. If the + name isn't registered, returns ``None``. + + :param shell: Name the class is registered under. + """ + return _available_shells.get(shell) + + +def _is_incomplete_argument(ctx: Context, param: Parameter) -> bool: + """Determine if the given parameter is an argument that can still + accept values. + + :param ctx: Invocation context for the command represented by the + parsed complete args. + :param param: Argument object being checked. + """ + if not isinstance(param, Argument): + return False + + assert param.name is not None + # Will be None if expose_value is False. + value = ctx.params.get(param.name) + return ( + param.nargs == -1 + or ctx.get_parameter_source(param.name) is not ParameterSource.COMMANDLINE + or ( + param.nargs > 1 + and isinstance(value, (tuple, list)) + and len(value) < param.nargs + ) + ) + + +def _start_of_option(ctx: Context, value: str) -> bool: + """Check if the value looks like the start of an option.""" + if not value: + return False + + c = value[0] + return c in ctx._opt_prefixes + + +def _is_incomplete_option(ctx: Context, args: t.List[str], param: Parameter) -> bool: + """Determine if the given parameter is an option that needs a value. + + :param args: List of complete args before the incomplete value. + :param param: Option object being checked. + """ + if not isinstance(param, Option): + return False + + if param.is_flag or param.count: + return False + + last_option = None + + for index, arg in enumerate(reversed(args)): + if index + 1 > param.nargs: + break + + if _start_of_option(ctx, arg): + last_option = arg + + return last_option is not None and last_option in param.opts + + +def _resolve_context( + cli: BaseCommand, + ctx_args: t.MutableMapping[str, t.Any], + prog_name: str, + args: t.List[str], +) -> Context: + """Produce the context hierarchy starting with the command and + traversing the complete arguments. This only follows the commands, + it doesn't trigger input prompts or callbacks. + + :param cli: Command being called. + :param prog_name: Name of the executable in the shell. + :param args: List of complete args before the incomplete value. + """ + ctx_args["resilient_parsing"] = True + ctx = cli.make_context(prog_name, args.copy(), **ctx_args) + args = ctx.protected_args + ctx.args + + while args: + command = ctx.command + + if isinstance(command, MultiCommand): + if not command.chain: + name, cmd, args = command.resolve_command(ctx, args) + + if cmd is None: + return ctx + + ctx = cmd.make_context(name, args, parent=ctx, resilient_parsing=True) + args = ctx.protected_args + ctx.args + else: + sub_ctx = ctx + + while args: + name, cmd, args = command.resolve_command(ctx, args) + + if cmd is None: + return ctx + + sub_ctx = cmd.make_context( + name, + args, + parent=ctx, + allow_extra_args=True, + allow_interspersed_args=False, + resilient_parsing=True, + ) + args = sub_ctx.args + + ctx = sub_ctx + args = [*sub_ctx.protected_args, *sub_ctx.args] + else: + break + + return ctx + + +def _resolve_incomplete( + ctx: Context, args: t.List[str], incomplete: str +) -> t.Tuple[t.Union[BaseCommand, Parameter], str]: + """Find the Click object that will handle the completion of the + incomplete value. Return the object and the incomplete value. + + :param ctx: Invocation context for the command represented by + the parsed complete args. + :param args: List of complete args before the incomplete value. + :param incomplete: Value being completed. May be empty. + """ + # Different shells treat an "=" between a long option name and + # value differently. Might keep the value joined, return the "=" + # as a separate item, or return the split name and value. Always + # split and discard the "=" to make completion easier. + if incomplete == "=": + incomplete = "" + elif "=" in incomplete and _start_of_option(ctx, incomplete): + name, _, incomplete = incomplete.partition("=") + args.append(name) + + # The "--" marker tells Click to stop treating values as options + # even if they start with the option character. If it hasn't been + # given and the incomplete arg looks like an option, the current + # command will provide option name completions. + if "--" not in args and _start_of_option(ctx, incomplete): + return ctx.command, incomplete + + params = ctx.command.get_params(ctx) + + # If the last complete arg is an option name with an incomplete + # value, the option will provide value completions. + for param in params: + if _is_incomplete_option(ctx, args, param): + return param, incomplete + + # It's not an option name or value. The first argument without a + # parsed value will provide value completions. + for param in params: + if _is_incomplete_argument(ctx, param): + return param, incomplete + + # There were no unparsed arguments, the command may be a group that + # will provide command name completions. + return ctx.command, incomplete diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/termui.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/termui.py new file mode 100644 index 0000000..c084f19 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/termui.py @@ -0,0 +1,784 @@ +import inspect +import io +import itertools +import sys +import typing as t +from gettext import gettext as _ + +from ._compat import isatty +from ._compat import strip_ansi +from .exceptions import Abort +from .exceptions import UsageError +from .globals import resolve_color_default +from .types import Choice +from .types import convert_type +from .types import ParamType +from .utils import echo +from .utils import LazyFile + +if t.TYPE_CHECKING: + from ._termui_impl import ProgressBar + +V = t.TypeVar("V") + +# The prompt functions to use. The doc tools currently override these +# functions to customize how they work. +visible_prompt_func: t.Callable[[str], str] = input + +_ansi_colors = { + "black": 30, + "red": 31, + "green": 32, + "yellow": 33, + "blue": 34, + "magenta": 35, + "cyan": 36, + "white": 37, + "reset": 39, + "bright_black": 90, + "bright_red": 91, + "bright_green": 92, + "bright_yellow": 93, + "bright_blue": 94, + "bright_magenta": 95, + "bright_cyan": 96, + "bright_white": 97, +} +_ansi_reset_all = "\033[0m" + + +def hidden_prompt_func(prompt: str) -> str: + import getpass + + return getpass.getpass(prompt) + + +def _build_prompt( + text: str, + suffix: str, + show_default: bool = False, + default: t.Optional[t.Any] = None, + show_choices: bool = True, + type: t.Optional[ParamType] = None, +) -> str: + prompt = text + if type is not None and show_choices and isinstance(type, Choice): + prompt += f" ({', '.join(map(str, type.choices))})" + if default is not None and show_default: + prompt = f"{prompt} [{_format_default(default)}]" + return f"{prompt}{suffix}" + + +def _format_default(default: t.Any) -> t.Any: + if isinstance(default, (io.IOBase, LazyFile)) and hasattr(default, "name"): + return default.name + + return default + + +def prompt( + text: str, + default: t.Optional[t.Any] = None, + hide_input: bool = False, + confirmation_prompt: t.Union[bool, str] = False, + type: t.Optional[t.Union[ParamType, t.Any]] = None, + value_proc: t.Optional[t.Callable[[str], t.Any]] = None, + prompt_suffix: str = ": ", + show_default: bool = True, + err: bool = False, + show_choices: bool = True, +) -> t.Any: + """Prompts a user for input. This is a convenience function that can + be used to prompt a user for input later. + + If the user aborts the input by sending an interrupt signal, this + function will catch it and raise a :exc:`Abort` exception. + + :param text: the text to show for the prompt. + :param default: the default value to use if no input happens. If this + is not given it will prompt until it's aborted. + :param hide_input: if this is set to true then the input value will + be hidden. + :param confirmation_prompt: Prompt a second time to confirm the + value. Can be set to a string instead of ``True`` to customize + the message. + :param type: the type to use to check the value against. + :param value_proc: if this parameter is provided it's a function that + is invoked instead of the type conversion to + convert a value. + :param prompt_suffix: a suffix that should be added to the prompt. + :param show_default: shows or hides the default value in the prompt. + :param err: if set to true the file defaults to ``stderr`` instead of + ``stdout``, the same as with echo. + :param show_choices: Show or hide choices if the passed type is a Choice. + For example if type is a Choice of either day or week, + show_choices is true and text is "Group by" then the + prompt will be "Group by (day, week): ". + + .. versionadded:: 8.0 + ``confirmation_prompt`` can be a custom string. + + .. versionadded:: 7.0 + Added the ``show_choices`` parameter. + + .. versionadded:: 6.0 + Added unicode support for cmd.exe on Windows. + + .. versionadded:: 4.0 + Added the `err` parameter. + + """ + + def prompt_func(text: str) -> str: + f = hidden_prompt_func if hide_input else visible_prompt_func + try: + # Write the prompt separately so that we get nice + # coloring through colorama on Windows + echo(text.rstrip(" "), nl=False, err=err) + # Echo a space to stdout to work around an issue where + # readline causes backspace to clear the whole line. + return f(" ") + except (KeyboardInterrupt, EOFError): + # getpass doesn't print a newline if the user aborts input with ^C. + # Allegedly this behavior is inherited from getpass(3). + # A doc bug has been filed at https://bugs.python.org/issue24711 + if hide_input: + echo(None, err=err) + raise Abort() from None + + if value_proc is None: + value_proc = convert_type(type, default) + + prompt = _build_prompt( + text, prompt_suffix, show_default, default, show_choices, type + ) + + if confirmation_prompt: + if confirmation_prompt is True: + confirmation_prompt = _("Repeat for confirmation") + + confirmation_prompt = _build_prompt(confirmation_prompt, prompt_suffix) + + while True: + while True: + value = prompt_func(prompt) + if value: + break + elif default is not None: + value = default + break + try: + result = value_proc(value) + except UsageError as e: + if hide_input: + echo(_("Error: The value you entered was invalid."), err=err) + else: + echo(_("Error: {e.message}").format(e=e), err=err) + continue + if not confirmation_prompt: + return result + while True: + value2 = prompt_func(confirmation_prompt) + is_empty = not value and not value2 + if value2 or is_empty: + break + if value == value2: + return result + echo(_("Error: The two entered values do not match."), err=err) + + +def confirm( + text: str, + default: t.Optional[bool] = False, + abort: bool = False, + prompt_suffix: str = ": ", + show_default: bool = True, + err: bool = False, +) -> bool: + """Prompts for confirmation (yes/no question). + + If the user aborts the input by sending a interrupt signal this + function will catch it and raise a :exc:`Abort` exception. + + :param text: the question to ask. + :param default: The default value to use when no input is given. If + ``None``, repeat until input is given. + :param abort: if this is set to `True` a negative answer aborts the + exception by raising :exc:`Abort`. + :param prompt_suffix: a suffix that should be added to the prompt. + :param show_default: shows or hides the default value in the prompt. + :param err: if set to true the file defaults to ``stderr`` instead of + ``stdout``, the same as with echo. + + .. versionchanged:: 8.0 + Repeat until input is given if ``default`` is ``None``. + + .. versionadded:: 4.0 + Added the ``err`` parameter. + """ + prompt = _build_prompt( + text, + prompt_suffix, + show_default, + "y/n" if default is None else ("Y/n" if default else "y/N"), + ) + + while True: + try: + # Write the prompt separately so that we get nice + # coloring through colorama on Windows + echo(prompt.rstrip(" "), nl=False, err=err) + # Echo a space to stdout to work around an issue where + # readline causes backspace to clear the whole line. + value = visible_prompt_func(" ").lower().strip() + except (KeyboardInterrupt, EOFError): + raise Abort() from None + if value in ("y", "yes"): + rv = True + elif value in ("n", "no"): + rv = False + elif default is not None and value == "": + rv = default + else: + echo(_("Error: invalid input"), err=err) + continue + break + if abort and not rv: + raise Abort() + return rv + + +def echo_via_pager( + text_or_generator: t.Union[t.Iterable[str], t.Callable[[], t.Iterable[str]], str], + color: t.Optional[bool] = None, +) -> None: + """This function takes a text and shows it via an environment specific + pager on stdout. + + .. versionchanged:: 3.0 + Added the `color` flag. + + :param text_or_generator: the text to page, or alternatively, a + generator emitting the text to page. + :param color: controls if the pager supports ANSI colors or not. The + default is autodetection. + """ + color = resolve_color_default(color) + + if inspect.isgeneratorfunction(text_or_generator): + i = t.cast(t.Callable[[], t.Iterable[str]], text_or_generator)() + elif isinstance(text_or_generator, str): + i = [text_or_generator] + else: + i = iter(t.cast(t.Iterable[str], text_or_generator)) + + # convert every element of i to a text type if necessary + text_generator = (el if isinstance(el, str) else str(el) for el in i) + + from ._termui_impl import pager + + return pager(itertools.chain(text_generator, "\n"), color) + + +def progressbar( + iterable: t.Optional[t.Iterable[V]] = None, + length: t.Optional[int] = None, + label: t.Optional[str] = None, + show_eta: bool = True, + show_percent: t.Optional[bool] = None, + show_pos: bool = False, + item_show_func: t.Optional[t.Callable[[t.Optional[V]], t.Optional[str]]] = None, + fill_char: str = "#", + empty_char: str = "-", + bar_template: str = "%(label)s [%(bar)s] %(info)s", + info_sep: str = " ", + width: int = 36, + file: t.Optional[t.TextIO] = None, + color: t.Optional[bool] = None, + update_min_steps: int = 1, +) -> "ProgressBar[V]": + """This function creates an iterable context manager that can be used + to iterate over something while showing a progress bar. It will + either iterate over the `iterable` or `length` items (that are counted + up). While iteration happens, this function will print a rendered + progress bar to the given `file` (defaults to stdout) and will attempt + to calculate remaining time and more. By default, this progress bar + will not be rendered if the file is not a terminal. + + The context manager creates the progress bar. When the context + manager is entered the progress bar is already created. With every + iteration over the progress bar, the iterable passed to the bar is + advanced and the bar is updated. When the context manager exits, + a newline is printed and the progress bar is finalized on screen. + + Note: The progress bar is currently designed for use cases where the + total progress can be expected to take at least several seconds. + Because of this, the ProgressBar class object won't display + progress that is considered too fast, and progress where the time + between steps is less than a second. + + No printing must happen or the progress bar will be unintentionally + destroyed. + + Example usage:: + + with progressbar(items) as bar: + for item in bar: + do_something_with(item) + + Alternatively, if no iterable is specified, one can manually update the + progress bar through the `update()` method instead of directly + iterating over the progress bar. The update method accepts the number + of steps to increment the bar with:: + + with progressbar(length=chunks.total_bytes) as bar: + for chunk in chunks: + process_chunk(chunk) + bar.update(chunks.bytes) + + The ``update()`` method also takes an optional value specifying the + ``current_item`` at the new position. This is useful when used + together with ``item_show_func`` to customize the output for each + manual step:: + + with click.progressbar( + length=total_size, + label='Unzipping archive', + item_show_func=lambda a: a.filename + ) as bar: + for archive in zip_file: + archive.extract() + bar.update(archive.size, archive) + + :param iterable: an iterable to iterate over. If not provided the length + is required. + :param length: the number of items to iterate over. By default the + progressbar will attempt to ask the iterator about its + length, which might or might not work. If an iterable is + also provided this parameter can be used to override the + length. If an iterable is not provided the progress bar + will iterate over a range of that length. + :param label: the label to show next to the progress bar. + :param show_eta: enables or disables the estimated time display. This is + automatically disabled if the length cannot be + determined. + :param show_percent: enables or disables the percentage display. The + default is `True` if the iterable has a length or + `False` if not. + :param show_pos: enables or disables the absolute position display. The + default is `False`. + :param item_show_func: A function called with the current item which + can return a string to show next to the progress bar. If the + function returns ``None`` nothing is shown. The current item can + be ``None``, such as when entering and exiting the bar. + :param fill_char: the character to use to show the filled part of the + progress bar. + :param empty_char: the character to use to show the non-filled part of + the progress bar. + :param bar_template: the format string to use as template for the bar. + The parameters in it are ``label`` for the label, + ``bar`` for the progress bar and ``info`` for the + info section. + :param info_sep: the separator between multiple info items (eta etc.) + :param width: the width of the progress bar in characters, 0 means full + terminal width + :param file: The file to write to. If this is not a terminal then + only the label is printed. + :param color: controls if the terminal supports ANSI colors or not. The + default is autodetection. This is only needed if ANSI + codes are included anywhere in the progress bar output + which is not the case by default. + :param update_min_steps: Render only when this many updates have + completed. This allows tuning for very fast iterators. + + .. versionchanged:: 8.0 + Output is shown even if execution time is less than 0.5 seconds. + + .. versionchanged:: 8.0 + ``item_show_func`` shows the current item, not the previous one. + + .. versionchanged:: 8.0 + Labels are echoed if the output is not a TTY. Reverts a change + in 7.0 that removed all output. + + .. versionadded:: 8.0 + Added the ``update_min_steps`` parameter. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. Added the ``update`` method to + the object. + + .. versionadded:: 2.0 + """ + from ._termui_impl import ProgressBar + + color = resolve_color_default(color) + return ProgressBar( + iterable=iterable, + length=length, + show_eta=show_eta, + show_percent=show_percent, + show_pos=show_pos, + item_show_func=item_show_func, + fill_char=fill_char, + empty_char=empty_char, + bar_template=bar_template, + info_sep=info_sep, + file=file, + label=label, + width=width, + color=color, + update_min_steps=update_min_steps, + ) + + +def clear() -> None: + """Clears the terminal screen. This will have the effect of clearing + the whole visible space of the terminal and moving the cursor to the + top left. This does not do anything if not connected to a terminal. + + .. versionadded:: 2.0 + """ + if not isatty(sys.stdout): + return + + # ANSI escape \033[2J clears the screen, \033[1;1H moves the cursor + echo("\033[2J\033[1;1H", nl=False) + + +def _interpret_color( + color: t.Union[int, t.Tuple[int, int, int], str], offset: int = 0 +) -> str: + if isinstance(color, int): + return f"{38 + offset};5;{color:d}" + + if isinstance(color, (tuple, list)): + r, g, b = color + return f"{38 + offset};2;{r:d};{g:d};{b:d}" + + return str(_ansi_colors[color] + offset) + + +def style( + text: t.Any, + fg: t.Optional[t.Union[int, t.Tuple[int, int, int], str]] = None, + bg: t.Optional[t.Union[int, t.Tuple[int, int, int], str]] = None, + bold: t.Optional[bool] = None, + dim: t.Optional[bool] = None, + underline: t.Optional[bool] = None, + overline: t.Optional[bool] = None, + italic: t.Optional[bool] = None, + blink: t.Optional[bool] = None, + reverse: t.Optional[bool] = None, + strikethrough: t.Optional[bool] = None, + reset: bool = True, +) -> str: + """Styles a text with ANSI styles and returns the new string. By + default the styling is self contained which means that at the end + of the string a reset code is issued. This can be prevented by + passing ``reset=False``. + + Examples:: + + click.echo(click.style('Hello World!', fg='green')) + click.echo(click.style('ATTENTION!', blink=True)) + click.echo(click.style('Some things', reverse=True, fg='cyan')) + click.echo(click.style('More colors', fg=(255, 12, 128), bg=117)) + + Supported color names: + + * ``black`` (might be a gray) + * ``red`` + * ``green`` + * ``yellow`` (might be an orange) + * ``blue`` + * ``magenta`` + * ``cyan`` + * ``white`` (might be light gray) + * ``bright_black`` + * ``bright_red`` + * ``bright_green`` + * ``bright_yellow`` + * ``bright_blue`` + * ``bright_magenta`` + * ``bright_cyan`` + * ``bright_white`` + * ``reset`` (reset the color code only) + + If the terminal supports it, color may also be specified as: + + - An integer in the interval [0, 255]. The terminal must support + 8-bit/256-color mode. + - An RGB tuple of three integers in [0, 255]. The terminal must + support 24-bit/true-color mode. + + See https://en.wikipedia.org/wiki/ANSI_color and + https://gist.github.com/XVilka/8346728 for more information. + + :param text: the string to style with ansi codes. + :param fg: if provided this will become the foreground color. + :param bg: if provided this will become the background color. + :param bold: if provided this will enable or disable bold mode. + :param dim: if provided this will enable or disable dim mode. This is + badly supported. + :param underline: if provided this will enable or disable underline. + :param overline: if provided this will enable or disable overline. + :param italic: if provided this will enable or disable italic. + :param blink: if provided this will enable or disable blinking. + :param reverse: if provided this will enable or disable inverse + rendering (foreground becomes background and the + other way round). + :param strikethrough: if provided this will enable or disable + striking through text. + :param reset: by default a reset-all code is added at the end of the + string which means that styles do not carry over. This + can be disabled to compose styles. + + .. versionchanged:: 8.0 + A non-string ``message`` is converted to a string. + + .. versionchanged:: 8.0 + Added support for 256 and RGB color codes. + + .. versionchanged:: 8.0 + Added the ``strikethrough``, ``italic``, and ``overline`` + parameters. + + .. versionchanged:: 7.0 + Added support for bright colors. + + .. versionadded:: 2.0 + """ + if not isinstance(text, str): + text = str(text) + + bits = [] + + if fg: + try: + bits.append(f"\033[{_interpret_color(fg)}m") + except KeyError: + raise TypeError(f"Unknown color {fg!r}") from None + + if bg: + try: + bits.append(f"\033[{_interpret_color(bg, 10)}m") + except KeyError: + raise TypeError(f"Unknown color {bg!r}") from None + + if bold is not None: + bits.append(f"\033[{1 if bold else 22}m") + if dim is not None: + bits.append(f"\033[{2 if dim else 22}m") + if underline is not None: + bits.append(f"\033[{4 if underline else 24}m") + if overline is not None: + bits.append(f"\033[{53 if overline else 55}m") + if italic is not None: + bits.append(f"\033[{3 if italic else 23}m") + if blink is not None: + bits.append(f"\033[{5 if blink else 25}m") + if reverse is not None: + bits.append(f"\033[{7 if reverse else 27}m") + if strikethrough is not None: + bits.append(f"\033[{9 if strikethrough else 29}m") + bits.append(text) + if reset: + bits.append(_ansi_reset_all) + return "".join(bits) + + +def unstyle(text: str) -> str: + """Removes ANSI styling information from a string. Usually it's not + necessary to use this function as Click's echo function will + automatically remove styling if necessary. + + .. versionadded:: 2.0 + + :param text: the text to remove style information from. + """ + return strip_ansi(text) + + +def secho( + message: t.Optional[t.Any] = None, + file: t.Optional[t.IO[t.AnyStr]] = None, + nl: bool = True, + err: bool = False, + color: t.Optional[bool] = None, + **styles: t.Any, +) -> None: + """This function combines :func:`echo` and :func:`style` into one + call. As such the following two calls are the same:: + + click.secho('Hello World!', fg='green') + click.echo(click.style('Hello World!', fg='green')) + + All keyword arguments are forwarded to the underlying functions + depending on which one they go with. + + Non-string types will be converted to :class:`str`. However, + :class:`bytes` are passed directly to :meth:`echo` without applying + style. If you want to style bytes that represent text, call + :meth:`bytes.decode` first. + + .. versionchanged:: 8.0 + A non-string ``message`` is converted to a string. Bytes are + passed through without style applied. + + .. versionadded:: 2.0 + """ + if message is not None and not isinstance(message, (bytes, bytearray)): + message = style(message, **styles) + + return echo(message, file=file, nl=nl, err=err, color=color) + + +def edit( + text: t.Optional[t.AnyStr] = None, + editor: t.Optional[str] = None, + env: t.Optional[t.Mapping[str, str]] = None, + require_save: bool = True, + extension: str = ".txt", + filename: t.Optional[str] = None, +) -> t.Optional[t.AnyStr]: + r"""Edits the given text in the defined editor. If an editor is given + (should be the full path to the executable but the regular operating + system search path is used for finding the executable) it overrides + the detected editor. Optionally, some environment variables can be + used. If the editor is closed without changes, `None` is returned. In + case a file is edited directly the return value is always `None` and + `require_save` and `extension` are ignored. + + If the editor cannot be opened a :exc:`UsageError` is raised. + + Note for Windows: to simplify cross-platform usage, the newlines are + automatically converted from POSIX to Windows and vice versa. As such, + the message here will have ``\n`` as newline markers. + + :param text: the text to edit. + :param editor: optionally the editor to use. Defaults to automatic + detection. + :param env: environment variables to forward to the editor. + :param require_save: if this is true, then not saving in the editor + will make the return value become `None`. + :param extension: the extension to tell the editor about. This defaults + to `.txt` but changing this might change syntax + highlighting. + :param filename: if provided it will edit this file instead of the + provided text contents. It will not use a temporary + file as an indirection in that case. + """ + from ._termui_impl import Editor + + ed = Editor(editor=editor, env=env, require_save=require_save, extension=extension) + + if filename is None: + return ed.edit(text) + + ed.edit_file(filename) + return None + + +def launch(url: str, wait: bool = False, locate: bool = False) -> int: + """This function launches the given URL (or filename) in the default + viewer application for this file type. If this is an executable, it + might launch the executable in a new session. The return value is + the exit code of the launched application. Usually, ``0`` indicates + success. + + Examples:: + + click.launch('https://click.palletsprojects.com/') + click.launch('/my/downloaded/file', locate=True) + + .. versionadded:: 2.0 + + :param url: URL or filename of the thing to launch. + :param wait: Wait for the program to exit before returning. This + only works if the launched program blocks. In particular, + ``xdg-open`` on Linux does not block. + :param locate: if this is set to `True` then instead of launching the + application associated with the URL it will attempt to + launch a file manager with the file located. This + might have weird effects if the URL does not point to + the filesystem. + """ + from ._termui_impl import open_url + + return open_url(url, wait=wait, locate=locate) + + +# If this is provided, getchar() calls into this instead. This is used +# for unittesting purposes. +_getchar: t.Optional[t.Callable[[bool], str]] = None + + +def getchar(echo: bool = False) -> str: + """Fetches a single character from the terminal and returns it. This + will always return a unicode character and under certain rare + circumstances this might return more than one character. The + situations which more than one character is returned is when for + whatever reason multiple characters end up in the terminal buffer or + standard input was not actually a terminal. + + Note that this will always read from the terminal, even if something + is piped into the standard input. + + Note for Windows: in rare cases when typing non-ASCII characters, this + function might wait for a second character and then return both at once. + This is because certain Unicode characters look like special-key markers. + + .. versionadded:: 2.0 + + :param echo: if set to `True`, the character read will also show up on + the terminal. The default is to not show it. + """ + global _getchar + + if _getchar is None: + from ._termui_impl import getchar as f + + _getchar = f + + return _getchar(echo) + + +def raw_terminal() -> t.ContextManager[int]: + from ._termui_impl import raw_terminal as f + + return f() + + +def pause(info: t.Optional[str] = None, err: bool = False) -> None: + """This command stops execution and waits for the user to press any + key to continue. This is similar to the Windows batch "pause" + command. If the program is not run through a terminal, this command + will instead do nothing. + + .. versionadded:: 2.0 + + .. versionadded:: 4.0 + Added the `err` parameter. + + :param info: The message to print before pausing. Defaults to + ``"Press any key to continue..."``. + :param err: if set to message goes to ``stderr`` instead of + ``stdout``, the same as with echo. + """ + if not isatty(sys.stdin) or not isatty(sys.stdout): + return + + if info is None: + info = _("Press any key to continue...") + + try: + if info: + echo(info, nl=False, err=err) + try: + getchar() + except (KeyboardInterrupt, EOFError): + pass + finally: + if info: + echo(err=err) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/testing.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/testing.py new file mode 100644 index 0000000..772b215 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/testing.py @@ -0,0 +1,483 @@ +import contextlib +import io +import os +import shlex +import shutil +import sys +import tempfile +import typing as t +from types import TracebackType + +from . import _compat +from . import formatting +from . import termui +from . import utils +from ._compat import _find_binary_reader + +if t.TYPE_CHECKING: + from .core import BaseCommand + + +class EchoingStdin: + def __init__(self, input: t.BinaryIO, output: t.BinaryIO) -> None: + self._input = input + self._output = output + self._paused = False + + def __getattr__(self, x: str) -> t.Any: + return getattr(self._input, x) + + def _echo(self, rv: bytes) -> bytes: + if not self._paused: + self._output.write(rv) + + return rv + + def read(self, n: int = -1) -> bytes: + return self._echo(self._input.read(n)) + + def read1(self, n: int = -1) -> bytes: + return self._echo(self._input.read1(n)) # type: ignore + + def readline(self, n: int = -1) -> bytes: + return self._echo(self._input.readline(n)) + + def readlines(self) -> t.List[bytes]: + return [self._echo(x) for x in self._input.readlines()] + + def __iter__(self) -> t.Iterator[bytes]: + return iter(self._echo(x) for x in self._input) + + def __repr__(self) -> str: + return repr(self._input) + + +@contextlib.contextmanager +def _pause_echo(stream: t.Optional[EchoingStdin]) -> t.Iterator[None]: + if stream is None: + yield + else: + stream._paused = True + yield + stream._paused = False + + +class _NamedTextIOWrapper(io.TextIOWrapper): + def __init__( + self, buffer: t.BinaryIO, name: str, mode: str, **kwargs: t.Any + ) -> None: + super().__init__(buffer, **kwargs) + self._name = name + self._mode = mode + + @property + def name(self) -> str: + return self._name + + @property + def mode(self) -> str: + return self._mode + + +def make_input_stream( + input: t.Optional[t.Union[str, bytes, t.IO[t.Any]]], charset: str +) -> t.BinaryIO: + # Is already an input stream. + if hasattr(input, "read"): + rv = _find_binary_reader(t.cast(t.IO[t.Any], input)) + + if rv is not None: + return rv + + raise TypeError("Could not find binary reader for input stream.") + + if input is None: + input = b"" + elif isinstance(input, str): + input = input.encode(charset) + + return io.BytesIO(input) + + +class Result: + """Holds the captured result of an invoked CLI script.""" + + def __init__( + self, + runner: "CliRunner", + stdout_bytes: bytes, + stderr_bytes: t.Optional[bytes], + return_value: t.Any, + exit_code: int, + exception: t.Optional[BaseException], + exc_info: t.Optional[ + t.Tuple[t.Type[BaseException], BaseException, TracebackType] + ] = None, + ): + #: The runner that created the result + self.runner = runner + #: The standard output as bytes. + self.stdout_bytes = stdout_bytes + #: The standard error as bytes, or None if not available + self.stderr_bytes = stderr_bytes + #: The value returned from the invoked command. + #: + #: .. versionadded:: 8.0 + self.return_value = return_value + #: The exit code as integer. + self.exit_code = exit_code + #: The exception that happened if one did. + self.exception = exception + #: The traceback + self.exc_info = exc_info + + @property + def output(self) -> str: + """The (standard) output as unicode string.""" + return self.stdout + + @property + def stdout(self) -> str: + """The standard output as unicode string.""" + return self.stdout_bytes.decode(self.runner.charset, "replace").replace( + "\r\n", "\n" + ) + + @property + def stderr(self) -> str: + """The standard error as unicode string.""" + if self.stderr_bytes is None: + raise ValueError("stderr not separately captured") + return self.stderr_bytes.decode(self.runner.charset, "replace").replace( + "\r\n", "\n" + ) + + def __repr__(self) -> str: + exc_str = repr(self.exception) if self.exception else "okay" + return f"<{type(self).__name__} {exc_str}>" + + +class CliRunner: + """The CLI runner provides functionality to invoke a Click command line + script for unittesting purposes in a isolated environment. This only + works in single-threaded systems without any concurrency as it changes the + global interpreter state. + + :param charset: the character set for the input and output data. + :param env: a dictionary with environment variables for overriding. + :param echo_stdin: if this is set to `True`, then reading from stdin writes + to stdout. This is useful for showing examples in + some circumstances. Note that regular prompts + will automatically echo the input. + :param mix_stderr: if this is set to `False`, then stdout and stderr are + preserved as independent streams. This is useful for + Unix-philosophy apps that have predictable stdout and + noisy stderr, such that each may be measured + independently + """ + + def __init__( + self, + charset: str = "utf-8", + env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + echo_stdin: bool = False, + mix_stderr: bool = True, + ) -> None: + self.charset = charset + self.env: t.Mapping[str, t.Optional[str]] = env or {} + self.echo_stdin = echo_stdin + self.mix_stderr = mix_stderr + + def get_default_prog_name(self, cli: "BaseCommand") -> str: + """Given a command object it will return the default program name + for it. The default is the `name` attribute or ``"root"`` if not + set. + """ + return cli.name or "root" + + def make_env( + self, overrides: t.Optional[t.Mapping[str, t.Optional[str]]] = None + ) -> t.Mapping[str, t.Optional[str]]: + """Returns the environment overrides for invoking a script.""" + rv = dict(self.env) + if overrides: + rv.update(overrides) + return rv + + @contextlib.contextmanager + def isolation( + self, + input: t.Optional[t.Union[str, bytes, t.IO[t.Any]]] = None, + env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + color: bool = False, + ) -> t.Iterator[t.Tuple[io.BytesIO, t.Optional[io.BytesIO]]]: + """A context manager that sets up the isolation for invoking of a + command line tool. This sets up stdin with the given input data + and `os.environ` with the overrides from the given dictionary. + This also rebinds some internals in Click to be mocked (like the + prompt functionality). + + This is automatically done in the :meth:`invoke` method. + + :param input: the input stream to put into sys.stdin. + :param env: the environment overrides as dictionary. + :param color: whether the output should contain color codes. The + application can still override this explicitly. + + .. versionchanged:: 8.0 + ``stderr`` is opened with ``errors="backslashreplace"`` + instead of the default ``"strict"``. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. + """ + bytes_input = make_input_stream(input, self.charset) + echo_input = None + + old_stdin = sys.stdin + old_stdout = sys.stdout + old_stderr = sys.stderr + old_forced_width = formatting.FORCED_WIDTH + formatting.FORCED_WIDTH = 80 + + env = self.make_env(env) + + bytes_output = io.BytesIO() + + if self.echo_stdin: + bytes_input = echo_input = t.cast( + t.BinaryIO, EchoingStdin(bytes_input, bytes_output) + ) + + sys.stdin = text_input = _NamedTextIOWrapper( + bytes_input, encoding=self.charset, name="", mode="r" + ) + + if self.echo_stdin: + # Force unbuffered reads, otherwise TextIOWrapper reads a + # large chunk which is echoed early. + text_input._CHUNK_SIZE = 1 # type: ignore + + sys.stdout = _NamedTextIOWrapper( + bytes_output, encoding=self.charset, name="", mode="w" + ) + + bytes_error = None + if self.mix_stderr: + sys.stderr = sys.stdout + else: + bytes_error = io.BytesIO() + sys.stderr = _NamedTextIOWrapper( + bytes_error, + encoding=self.charset, + name="", + mode="w", + errors="backslashreplace", + ) + + @_pause_echo(echo_input) # type: ignore + def visible_input(prompt: t.Optional[str] = None) -> str: + sys.stdout.write(prompt or "") + val = text_input.readline().rstrip("\r\n") + sys.stdout.write(f"{val}\n") + sys.stdout.flush() + return val + + @_pause_echo(echo_input) # type: ignore + def hidden_input(prompt: t.Optional[str] = None) -> str: + sys.stdout.write(f"{prompt or ''}\n") + sys.stdout.flush() + return text_input.readline().rstrip("\r\n") + + @_pause_echo(echo_input) # type: ignore + def _getchar(echo: bool) -> str: + char = sys.stdin.read(1) + + if echo: + sys.stdout.write(char) + + sys.stdout.flush() + return char + + default_color = color + + def should_strip_ansi( + stream: t.Optional[t.IO[t.Any]] = None, color: t.Optional[bool] = None + ) -> bool: + if color is None: + return not default_color + return not color + + old_visible_prompt_func = termui.visible_prompt_func + old_hidden_prompt_func = termui.hidden_prompt_func + old__getchar_func = termui._getchar + old_should_strip_ansi = utils.should_strip_ansi # type: ignore + old__compat_should_strip_ansi = _compat.should_strip_ansi + termui.visible_prompt_func = visible_input + termui.hidden_prompt_func = hidden_input + termui._getchar = _getchar + utils.should_strip_ansi = should_strip_ansi # type: ignore + _compat.should_strip_ansi = should_strip_ansi + + old_env = {} + try: + for key, value in env.items(): + old_env[key] = os.environ.get(key) + if value is None: + try: + del os.environ[key] + except Exception: + pass + else: + os.environ[key] = value + yield (bytes_output, bytes_error) + finally: + for key, value in old_env.items(): + if value is None: + try: + del os.environ[key] + except Exception: + pass + else: + os.environ[key] = value + sys.stdout = old_stdout + sys.stderr = old_stderr + sys.stdin = old_stdin + termui.visible_prompt_func = old_visible_prompt_func + termui.hidden_prompt_func = old_hidden_prompt_func + termui._getchar = old__getchar_func + utils.should_strip_ansi = old_should_strip_ansi # type: ignore + _compat.should_strip_ansi = old__compat_should_strip_ansi + formatting.FORCED_WIDTH = old_forced_width + + def invoke( + self, + cli: "BaseCommand", + args: t.Optional[t.Union[str, t.Sequence[str]]] = None, + input: t.Optional[t.Union[str, bytes, t.IO[t.Any]]] = None, + env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + catch_exceptions: bool = True, + color: bool = False, + **extra: t.Any, + ) -> Result: + """Invokes a command in an isolated environment. The arguments are + forwarded directly to the command line script, the `extra` keyword + arguments are passed to the :meth:`~clickpkg.Command.main` function of + the command. + + This returns a :class:`Result` object. + + :param cli: the command to invoke + :param args: the arguments to invoke. It may be given as an iterable + or a string. When given as string it will be interpreted + as a Unix shell command. More details at + :func:`shlex.split`. + :param input: the input data for `sys.stdin`. + :param env: the environment overrides. + :param catch_exceptions: Whether to catch any other exceptions than + ``SystemExit``. + :param extra: the keyword arguments to pass to :meth:`main`. + :param color: whether the output should contain color codes. The + application can still override this explicitly. + + .. versionchanged:: 8.0 + The result object has the ``return_value`` attribute with + the value returned from the invoked command. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. + + .. versionchanged:: 3.0 + Added the ``catch_exceptions`` parameter. + + .. versionchanged:: 3.0 + The result object has the ``exc_info`` attribute with the + traceback if available. + """ + exc_info = None + with self.isolation(input=input, env=env, color=color) as outstreams: + return_value = None + exception: t.Optional[BaseException] = None + exit_code = 0 + + if isinstance(args, str): + args = shlex.split(args) + + try: + prog_name = extra.pop("prog_name") + except KeyError: + prog_name = self.get_default_prog_name(cli) + + try: + return_value = cli.main(args=args or (), prog_name=prog_name, **extra) + except SystemExit as e: + exc_info = sys.exc_info() + e_code = t.cast(t.Optional[t.Union[int, t.Any]], e.code) + + if e_code is None: + e_code = 0 + + if e_code != 0: + exception = e + + if not isinstance(e_code, int): + sys.stdout.write(str(e_code)) + sys.stdout.write("\n") + e_code = 1 + + exit_code = e_code + + except Exception as e: + if not catch_exceptions: + raise + exception = e + exit_code = 1 + exc_info = sys.exc_info() + finally: + sys.stdout.flush() + stdout = outstreams[0].getvalue() + if self.mix_stderr: + stderr = None + else: + stderr = outstreams[1].getvalue() # type: ignore + + return Result( + runner=self, + stdout_bytes=stdout, + stderr_bytes=stderr, + return_value=return_value, + exit_code=exit_code, + exception=exception, + exc_info=exc_info, # type: ignore + ) + + @contextlib.contextmanager + def isolated_filesystem( + self, temp_dir: t.Optional[t.Union[str, "os.PathLike[str]"]] = None + ) -> t.Iterator[str]: + """A context manager that creates a temporary directory and + changes the current working directory to it. This isolates tests + that affect the contents of the CWD to prevent them from + interfering with each other. + + :param temp_dir: Create the temporary directory under this + directory. If given, the created directory is not removed + when exiting. + + .. versionchanged:: 8.0 + Added the ``temp_dir`` parameter. + """ + cwd = os.getcwd() + dt = tempfile.mkdtemp(dir=temp_dir) + os.chdir(dt) + + try: + yield dt + finally: + os.chdir(cwd) + + if temp_dir is None: + try: + shutil.rmtree(dt) + except OSError: + pass diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/types.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/types.py new file mode 100644 index 0000000..a70fd58 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/types.py @@ -0,0 +1,1093 @@ +import os +import stat +import sys +import typing as t +from datetime import datetime +from gettext import gettext as _ +from gettext import ngettext + +from ._compat import _get_argv_encoding +from ._compat import open_stream +from .exceptions import BadParameter +from .utils import format_filename +from .utils import LazyFile +from .utils import safecall + +if t.TYPE_CHECKING: + import typing_extensions as te + + from .core import Context + from .core import Parameter + from .shell_completion import CompletionItem + + +class ParamType: + """Represents the type of a parameter. Validates and converts values + from the command line or Python into the correct type. + + To implement a custom type, subclass and implement at least the + following: + + - The :attr:`name` class attribute must be set. + - Calling an instance of the type with ``None`` must return + ``None``. This is already implemented by default. + - :meth:`convert` must convert string values to the correct type. + - :meth:`convert` must accept values that are already the correct + type. + - It must be able to convert a value if the ``ctx`` and ``param`` + arguments are ``None``. This can occur when converting prompt + input. + """ + + is_composite: t.ClassVar[bool] = False + arity: t.ClassVar[int] = 1 + + #: the descriptive name of this type + name: str + + #: if a list of this type is expected and the value is pulled from a + #: string environment variable, this is what splits it up. `None` + #: means any whitespace. For all parameters the general rule is that + #: whitespace splits them up. The exception are paths and files which + #: are split by ``os.path.pathsep`` by default (":" on Unix and ";" on + #: Windows). + envvar_list_splitter: t.ClassVar[t.Optional[str]] = None + + def to_info_dict(self) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. + + Use :meth:`click.Context.to_info_dict` to traverse the entire + CLI structure. + + .. versionadded:: 8.0 + """ + # The class name without the "ParamType" suffix. + param_type = type(self).__name__.partition("ParamType")[0] + param_type = param_type.partition("ParameterType")[0] + + # Custom subclasses might not remember to set a name. + if hasattr(self, "name"): + name = self.name + else: + name = param_type + + return {"param_type": param_type, "name": name} + + def __call__( + self, + value: t.Any, + param: t.Optional["Parameter"] = None, + ctx: t.Optional["Context"] = None, + ) -> t.Any: + if value is not None: + return self.convert(value, param, ctx) + + def get_metavar(self, param: "Parameter") -> t.Optional[str]: + """Returns the metavar default for this param if it provides one.""" + + def get_missing_message(self, param: "Parameter") -> t.Optional[str]: + """Optionally might return extra information about a missing + parameter. + + .. versionadded:: 2.0 + """ + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + """Convert the value to the correct type. This is not called if + the value is ``None`` (the missing value). + + This must accept string values from the command line, as well as + values that are already the correct type. It may also convert + other compatible types. + + The ``param`` and ``ctx`` arguments may be ``None`` in certain + situations, such as when converting prompt input. + + If the value cannot be converted, call :meth:`fail` with a + descriptive message. + + :param value: The value to convert. + :param param: The parameter that is using this type to convert + its value. May be ``None``. + :param ctx: The current context that arrived at this value. May + be ``None``. + """ + return value + + def split_envvar_value(self, rv: str) -> t.Sequence[str]: + """Given a value from an environment variable this splits it up + into small chunks depending on the defined envvar list splitter. + + If the splitter is set to `None`, which means that whitespace splits, + then leading and trailing whitespace is ignored. Otherwise, leading + and trailing splitters usually lead to empty items being included. + """ + return (rv or "").split(self.envvar_list_splitter) + + def fail( + self, + message: str, + param: t.Optional["Parameter"] = None, + ctx: t.Optional["Context"] = None, + ) -> "t.NoReturn": + """Helper method to fail with an invalid value message.""" + raise BadParameter(message, ctx=ctx, param=param) + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Return a list of + :class:`~click.shell_completion.CompletionItem` objects for the + incomplete value. Most types do not provide completions, but + some do, and this allows custom types to provide custom + completions as well. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + return [] + + +class CompositeParamType(ParamType): + is_composite = True + + @property + def arity(self) -> int: # type: ignore + raise NotImplementedError() + + +class FuncParamType(ParamType): + def __init__(self, func: t.Callable[[t.Any], t.Any]) -> None: + self.name: str = func.__name__ + self.func = func + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["func"] = self.func + return info_dict + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + try: + return self.func(value) + except ValueError: + try: + value = str(value) + except UnicodeError: + value = value.decode("utf-8", "replace") + + self.fail(value, param, ctx) + + +class UnprocessedParamType(ParamType): + name = "text" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + return value + + def __repr__(self) -> str: + return "UNPROCESSED" + + +class StringParamType(ParamType): + name = "text" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + if isinstance(value, bytes): + enc = _get_argv_encoding() + try: + value = value.decode(enc) + except UnicodeError: + fs_enc = sys.getfilesystemencoding() + if fs_enc != enc: + try: + value = value.decode(fs_enc) + except UnicodeError: + value = value.decode("utf-8", "replace") + else: + value = value.decode("utf-8", "replace") + return value + return str(value) + + def __repr__(self) -> str: + return "STRING" + + +class Choice(ParamType): + """The choice type allows a value to be checked against a fixed set + of supported values. All of these values have to be strings. + + You should only pass a list or tuple of choices. Other iterables + (like generators) may lead to surprising results. + + The resulting value will always be one of the originally passed choices + regardless of ``case_sensitive`` or any ``ctx.token_normalize_func`` + being specified. + + See :ref:`choice-opts` for an example. + + :param case_sensitive: Set to false to make choices case + insensitive. Defaults to true. + """ + + name = "choice" + + def __init__(self, choices: t.Sequence[str], case_sensitive: bool = True) -> None: + self.choices = choices + self.case_sensitive = case_sensitive + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["choices"] = self.choices + info_dict["case_sensitive"] = self.case_sensitive + return info_dict + + def get_metavar(self, param: "Parameter") -> str: + choices_str = "|".join(self.choices) + + # Use curly braces to indicate a required argument. + if param.required and param.param_type_name == "argument": + return f"{{{choices_str}}}" + + # Use square braces to indicate an option or optional argument. + return f"[{choices_str}]" + + def get_missing_message(self, param: "Parameter") -> str: + return _("Choose from:\n\t{choices}").format(choices=",\n\t".join(self.choices)) + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + # Match through normalization and case sensitivity + # first do token_normalize_func, then lowercase + # preserve original `value` to produce an accurate message in + # `self.fail` + normed_value = value + normed_choices = {choice: choice for choice in self.choices} + + if ctx is not None and ctx.token_normalize_func is not None: + normed_value = ctx.token_normalize_func(value) + normed_choices = { + ctx.token_normalize_func(normed_choice): original + for normed_choice, original in normed_choices.items() + } + + if not self.case_sensitive: + normed_value = normed_value.casefold() + normed_choices = { + normed_choice.casefold(): original + for normed_choice, original in normed_choices.items() + } + + if normed_value in normed_choices: + return normed_choices[normed_value] + + choices_str = ", ".join(map(repr, self.choices)) + self.fail( + ngettext( + "{value!r} is not {choice}.", + "{value!r} is not one of {choices}.", + len(self.choices), + ).format(value=value, choice=choices_str, choices=choices_str), + param, + ctx, + ) + + def __repr__(self) -> str: + return f"Choice({list(self.choices)})" + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Complete choices that start with the incomplete value. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + str_choices = map(str, self.choices) + + if self.case_sensitive: + matched = (c for c in str_choices if c.startswith(incomplete)) + else: + incomplete = incomplete.lower() + matched = (c for c in str_choices if c.lower().startswith(incomplete)) + + return [CompletionItem(c) for c in matched] + + +class DateTime(ParamType): + """The DateTime type converts date strings into `datetime` objects. + + The format strings which are checked are configurable, but default to some + common (non-timezone aware) ISO 8601 formats. + + When specifying *DateTime* formats, you should only pass a list or a tuple. + Other iterables, like generators, may lead to surprising results. + + The format strings are processed using ``datetime.strptime``, and this + consequently defines the format strings which are allowed. + + Parsing is tried using each format, in order, and the first format which + parses successfully is used. + + :param formats: A list or tuple of date format strings, in the order in + which they should be tried. Defaults to + ``'%Y-%m-%d'``, ``'%Y-%m-%dT%H:%M:%S'``, + ``'%Y-%m-%d %H:%M:%S'``. + """ + + name = "datetime" + + def __init__(self, formats: t.Optional[t.Sequence[str]] = None): + self.formats: t.Sequence[str] = formats or [ + "%Y-%m-%d", + "%Y-%m-%dT%H:%M:%S", + "%Y-%m-%d %H:%M:%S", + ] + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["formats"] = self.formats + return info_dict + + def get_metavar(self, param: "Parameter") -> str: + return f"[{'|'.join(self.formats)}]" + + def _try_to_convert_date(self, value: t.Any, format: str) -> t.Optional[datetime]: + try: + return datetime.strptime(value, format) + except ValueError: + return None + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + if isinstance(value, datetime): + return value + + for format in self.formats: + converted = self._try_to_convert_date(value, format) + + if converted is not None: + return converted + + formats_str = ", ".join(map(repr, self.formats)) + self.fail( + ngettext( + "{value!r} does not match the format {format}.", + "{value!r} does not match the formats {formats}.", + len(self.formats), + ).format(value=value, format=formats_str, formats=formats_str), + param, + ctx, + ) + + def __repr__(self) -> str: + return "DateTime" + + +class _NumberParamTypeBase(ParamType): + _number_class: t.ClassVar[t.Type[t.Any]] + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + try: + return self._number_class(value) + except ValueError: + self.fail( + _("{value!r} is not a valid {number_type}.").format( + value=value, number_type=self.name + ), + param, + ctx, + ) + + +class _NumberRangeBase(_NumberParamTypeBase): + def __init__( + self, + min: t.Optional[float] = None, + max: t.Optional[float] = None, + min_open: bool = False, + max_open: bool = False, + clamp: bool = False, + ) -> None: + self.min = min + self.max = max + self.min_open = min_open + self.max_open = max_open + self.clamp = clamp + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update( + min=self.min, + max=self.max, + min_open=self.min_open, + max_open=self.max_open, + clamp=self.clamp, + ) + return info_dict + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + import operator + + rv = super().convert(value, param, ctx) + lt_min: bool = self.min is not None and ( + operator.le if self.min_open else operator.lt + )(rv, self.min) + gt_max: bool = self.max is not None and ( + operator.ge if self.max_open else operator.gt + )(rv, self.max) + + if self.clamp: + if lt_min: + return self._clamp(self.min, 1, self.min_open) # type: ignore + + if gt_max: + return self._clamp(self.max, -1, self.max_open) # type: ignore + + if lt_min or gt_max: + self.fail( + _("{value} is not in the range {range}.").format( + value=rv, range=self._describe_range() + ), + param, + ctx, + ) + + return rv + + def _clamp(self, bound: float, dir: "te.Literal[1, -1]", open: bool) -> float: + """Find the valid value to clamp to bound in the given + direction. + + :param bound: The boundary value. + :param dir: 1 or -1 indicating the direction to move. + :param open: If true, the range does not include the bound. + """ + raise NotImplementedError + + def _describe_range(self) -> str: + """Describe the range for use in help text.""" + if self.min is None: + op = "<" if self.max_open else "<=" + return f"x{op}{self.max}" + + if self.max is None: + op = ">" if self.min_open else ">=" + return f"x{op}{self.min}" + + lop = "<" if self.min_open else "<=" + rop = "<" if self.max_open else "<=" + return f"{self.min}{lop}x{rop}{self.max}" + + def __repr__(self) -> str: + clamp = " clamped" if self.clamp else "" + return f"<{type(self).__name__} {self._describe_range()}{clamp}>" + + +class IntParamType(_NumberParamTypeBase): + name = "integer" + _number_class = int + + def __repr__(self) -> str: + return "INT" + + +class IntRange(_NumberRangeBase, IntParamType): + """Restrict an :data:`click.INT` value to a range of accepted + values. See :ref:`ranges`. + + If ``min`` or ``max`` are not passed, any value is accepted in that + direction. If ``min_open`` or ``max_open`` are enabled, the + corresponding boundary is not included in the range. + + If ``clamp`` is enabled, a value outside the range is clamped to the + boundary instead of failing. + + .. versionchanged:: 8.0 + Added the ``min_open`` and ``max_open`` parameters. + """ + + name = "integer range" + + def _clamp( # type: ignore + self, bound: int, dir: "te.Literal[1, -1]", open: bool + ) -> int: + if not open: + return bound + + return bound + dir + + +class FloatParamType(_NumberParamTypeBase): + name = "float" + _number_class = float + + def __repr__(self) -> str: + return "FLOAT" + + +class FloatRange(_NumberRangeBase, FloatParamType): + """Restrict a :data:`click.FLOAT` value to a range of accepted + values. See :ref:`ranges`. + + If ``min`` or ``max`` are not passed, any value is accepted in that + direction. If ``min_open`` or ``max_open`` are enabled, the + corresponding boundary is not included in the range. + + If ``clamp`` is enabled, a value outside the range is clamped to the + boundary instead of failing. This is not supported if either + boundary is marked ``open``. + + .. versionchanged:: 8.0 + Added the ``min_open`` and ``max_open`` parameters. + """ + + name = "float range" + + def __init__( + self, + min: t.Optional[float] = None, + max: t.Optional[float] = None, + min_open: bool = False, + max_open: bool = False, + clamp: bool = False, + ) -> None: + super().__init__( + min=min, max=max, min_open=min_open, max_open=max_open, clamp=clamp + ) + + if (min_open or max_open) and clamp: + raise TypeError("Clamping is not supported for open bounds.") + + def _clamp(self, bound: float, dir: "te.Literal[1, -1]", open: bool) -> float: + if not open: + return bound + + # Could use Python 3.9's math.nextafter here, but clamping an + # open float range doesn't seem to be particularly useful. It's + # left up to the user to write a callback to do it if needed. + raise RuntimeError("Clamping is not supported for open bounds.") + + +class BoolParamType(ParamType): + name = "boolean" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + if value in {False, True}: + return bool(value) + + norm = value.strip().lower() + + if norm in {"1", "true", "t", "yes", "y", "on"}: + return True + + if norm in {"0", "false", "f", "no", "n", "off"}: + return False + + self.fail( + _("{value!r} is not a valid boolean.").format(value=value), param, ctx + ) + + def __repr__(self) -> str: + return "BOOL" + + +class UUIDParameterType(ParamType): + name = "uuid" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + import uuid + + if isinstance(value, uuid.UUID): + return value + + value = value.strip() + + try: + return uuid.UUID(value) + except ValueError: + self.fail( + _("{value!r} is not a valid UUID.").format(value=value), param, ctx + ) + + def __repr__(self) -> str: + return "UUID" + + +class File(ParamType): + """Declares a parameter to be a file for reading or writing. The file + is automatically closed once the context tears down (after the command + finished working). + + Files can be opened for reading or writing. The special value ``-`` + indicates stdin or stdout depending on the mode. + + By default, the file is opened for reading text data, but it can also be + opened in binary mode or for writing. The encoding parameter can be used + to force a specific encoding. + + The `lazy` flag controls if the file should be opened immediately or upon + first IO. The default is to be non-lazy for standard input and output + streams as well as files opened for reading, `lazy` otherwise. When opening a + file lazily for reading, it is still opened temporarily for validation, but + will not be held open until first IO. lazy is mainly useful when opening + for writing to avoid creating the file until it is needed. + + Files can also be opened atomically in which case all writes go into a + separate file in the same folder and upon completion the file will + be moved over to the original location. This is useful if a file + regularly read by other users is modified. + + See :ref:`file-args` for more information. + + .. versionchanged:: 2.0 + Added the ``atomic`` parameter. + """ + + name = "filename" + envvar_list_splitter: t.ClassVar[str] = os.path.pathsep + + def __init__( + self, + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + lazy: t.Optional[bool] = None, + atomic: bool = False, + ) -> None: + self.mode = mode + self.encoding = encoding + self.errors = errors + self.lazy = lazy + self.atomic = atomic + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update(mode=self.mode, encoding=self.encoding) + return info_dict + + def resolve_lazy_flag(self, value: "t.Union[str, os.PathLike[str]]") -> bool: + if self.lazy is not None: + return self.lazy + if os.fspath(value) == "-": + return False + elif "w" in self.mode: + return True + return False + + def convert( + self, + value: t.Union[str, "os.PathLike[str]", t.IO[t.Any]], + param: t.Optional["Parameter"], + ctx: t.Optional["Context"], + ) -> t.IO[t.Any]: + if _is_file_like(value): + return value + + value = t.cast("t.Union[str, os.PathLike[str]]", value) + + try: + lazy = self.resolve_lazy_flag(value) + + if lazy: + lf = LazyFile( + value, self.mode, self.encoding, self.errors, atomic=self.atomic + ) + + if ctx is not None: + ctx.call_on_close(lf.close_intelligently) + + return t.cast(t.IO[t.Any], lf) + + f, should_close = open_stream( + value, self.mode, self.encoding, self.errors, atomic=self.atomic + ) + + # If a context is provided, we automatically close the file + # at the end of the context execution (or flush out). If a + # context does not exist, it's the caller's responsibility to + # properly close the file. This for instance happens when the + # type is used with prompts. + if ctx is not None: + if should_close: + ctx.call_on_close(safecall(f.close)) + else: + ctx.call_on_close(safecall(f.flush)) + + return f + except OSError as e: + self.fail(f"'{format_filename(value)}': {e.strerror}", param, ctx) + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Return a special completion marker that tells the completion + system to use the shell to provide file path completions. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + return [CompletionItem(incomplete, type="file")] + + +def _is_file_like(value: t.Any) -> "te.TypeGuard[t.IO[t.Any]]": + return hasattr(value, "read") or hasattr(value, "write") + + +class Path(ParamType): + """The ``Path`` type is similar to the :class:`File` type, but + returns the filename instead of an open file. Various checks can be + enabled to validate the type of file and permissions. + + :param exists: The file or directory needs to exist for the value to + be valid. If this is not set to ``True``, and the file does not + exist, then all further checks are silently skipped. + :param file_okay: Allow a file as a value. + :param dir_okay: Allow a directory as a value. + :param readable: if true, a readable check is performed. + :param writable: if true, a writable check is performed. + :param executable: if true, an executable check is performed. + :param resolve_path: Make the value absolute and resolve any + symlinks. A ``~`` is not expanded, as this is supposed to be + done by the shell only. + :param allow_dash: Allow a single dash as a value, which indicates + a standard stream (but does not open it). Use + :func:`~click.open_file` to handle opening this value. + :param path_type: Convert the incoming path value to this type. If + ``None``, keep Python's default, which is ``str``. Useful to + convert to :class:`pathlib.Path`. + + .. versionchanged:: 8.1 + Added the ``executable`` parameter. + + .. versionchanged:: 8.0 + Allow passing ``path_type=pathlib.Path``. + + .. versionchanged:: 6.0 + Added the ``allow_dash`` parameter. + """ + + envvar_list_splitter: t.ClassVar[str] = os.path.pathsep + + def __init__( + self, + exists: bool = False, + file_okay: bool = True, + dir_okay: bool = True, + writable: bool = False, + readable: bool = True, + resolve_path: bool = False, + allow_dash: bool = False, + path_type: t.Optional[t.Type[t.Any]] = None, + executable: bool = False, + ): + self.exists = exists + self.file_okay = file_okay + self.dir_okay = dir_okay + self.readable = readable + self.writable = writable + self.executable = executable + self.resolve_path = resolve_path + self.allow_dash = allow_dash + self.type = path_type + + if self.file_okay and not self.dir_okay: + self.name: str = _("file") + elif self.dir_okay and not self.file_okay: + self.name = _("directory") + else: + self.name = _("path") + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update( + exists=self.exists, + file_okay=self.file_okay, + dir_okay=self.dir_okay, + writable=self.writable, + readable=self.readable, + allow_dash=self.allow_dash, + ) + return info_dict + + def coerce_path_result( + self, value: "t.Union[str, os.PathLike[str]]" + ) -> "t.Union[str, bytes, os.PathLike[str]]": + if self.type is not None and not isinstance(value, self.type): + if self.type is str: + return os.fsdecode(value) + elif self.type is bytes: + return os.fsencode(value) + else: + return t.cast("os.PathLike[str]", self.type(value)) + + return value + + def convert( + self, + value: "t.Union[str, os.PathLike[str]]", + param: t.Optional["Parameter"], + ctx: t.Optional["Context"], + ) -> "t.Union[str, bytes, os.PathLike[str]]": + rv = value + + is_dash = self.file_okay and self.allow_dash and rv in (b"-", "-") + + if not is_dash: + if self.resolve_path: + # os.path.realpath doesn't resolve symlinks on Windows + # until Python 3.8. Use pathlib for now. + import pathlib + + rv = os.fsdecode(pathlib.Path(rv).resolve()) + + try: + st = os.stat(rv) + except OSError: + if not self.exists: + return self.coerce_path_result(rv) + self.fail( + _("{name} {filename!r} does not exist.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + if not self.file_okay and stat.S_ISREG(st.st_mode): + self.fail( + _("{name} {filename!r} is a file.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + if not self.dir_okay and stat.S_ISDIR(st.st_mode): + self.fail( + _("{name} {filename!r} is a directory.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + if self.readable and not os.access(rv, os.R_OK): + self.fail( + _("{name} {filename!r} is not readable.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + if self.writable and not os.access(rv, os.W_OK): + self.fail( + _("{name} {filename!r} is not writable.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + if self.executable and not os.access(value, os.X_OK): + self.fail( + _("{name} {filename!r} is not executable.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + return self.coerce_path_result(rv) + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Return a special completion marker that tells the completion + system to use the shell to provide path completions for only + directories or any paths. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + type = "dir" if self.dir_okay and not self.file_okay else "file" + return [CompletionItem(incomplete, type=type)] + + +class Tuple(CompositeParamType): + """The default behavior of Click is to apply a type on a value directly. + This works well in most cases, except for when `nargs` is set to a fixed + count and different types should be used for different items. In this + case the :class:`Tuple` type can be used. This type can only be used + if `nargs` is set to a fixed number. + + For more information see :ref:`tuple-type`. + + This can be selected by using a Python tuple literal as a type. + + :param types: a list of types that should be used for the tuple items. + """ + + def __init__(self, types: t.Sequence[t.Union[t.Type[t.Any], ParamType]]) -> None: + self.types: t.Sequence[ParamType] = [convert_type(ty) for ty in types] + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["types"] = [t.to_info_dict() for t in self.types] + return info_dict + + @property + def name(self) -> str: # type: ignore + return f"<{' '.join(ty.name for ty in self.types)}>" + + @property + def arity(self) -> int: # type: ignore + return len(self.types) + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + len_type = len(self.types) + len_value = len(value) + + if len_value != len_type: + self.fail( + ngettext( + "{len_type} values are required, but {len_value} was given.", + "{len_type} values are required, but {len_value} were given.", + len_value, + ).format(len_type=len_type, len_value=len_value), + param=param, + ctx=ctx, + ) + + return tuple(ty(x, param, ctx) for ty, x in zip(self.types, value)) + + +def convert_type(ty: t.Optional[t.Any], default: t.Optional[t.Any] = None) -> ParamType: + """Find the most appropriate :class:`ParamType` for the given Python + type. If the type isn't provided, it can be inferred from a default + value. + """ + guessed_type = False + + if ty is None and default is not None: + if isinstance(default, (tuple, list)): + # If the default is empty, ty will remain None and will + # return STRING. + if default: + item = default[0] + + # A tuple of tuples needs to detect the inner types. + # Can't call convert recursively because that would + # incorrectly unwind the tuple to a single type. + if isinstance(item, (tuple, list)): + ty = tuple(map(type, item)) + else: + ty = type(item) + else: + ty = type(default) + + guessed_type = True + + if isinstance(ty, tuple): + return Tuple(ty) + + if isinstance(ty, ParamType): + return ty + + if ty is str or ty is None: + return STRING + + if ty is int: + return INT + + if ty is float: + return FLOAT + + if ty is bool: + return BOOL + + if guessed_type: + return STRING + + if __debug__: + try: + if issubclass(ty, ParamType): + raise AssertionError( + f"Attempted to use an uninstantiated parameter type ({ty})." + ) + except TypeError: + # ty is an instance (correct), so issubclass fails. + pass + + return FuncParamType(ty) + + +#: A dummy parameter type that just does nothing. From a user's +#: perspective this appears to just be the same as `STRING` but +#: internally no string conversion takes place if the input was bytes. +#: This is usually useful when working with file paths as they can +#: appear in bytes and unicode. +#: +#: For path related uses the :class:`Path` type is a better choice but +#: there are situations where an unprocessed type is useful which is why +#: it is is provided. +#: +#: .. versionadded:: 4.0 +UNPROCESSED = UnprocessedParamType() + +#: A unicode string parameter type which is the implicit default. This +#: can also be selected by using ``str`` as type. +STRING = StringParamType() + +#: An integer parameter. This can also be selected by using ``int`` as +#: type. +INT = IntParamType() + +#: A floating point value parameter. This can also be selected by using +#: ``float`` as type. +FLOAT = FloatParamType() + +#: A boolean parameter. This is the default for boolean flags. This can +#: also be selected by using ``bool`` as a type. +BOOL = BoolParamType() + +#: A UUID parameter. +UUID = UUIDParameterType() diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/utils.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/utils.py new file mode 100644 index 0000000..836c6f2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/click/utils.py @@ -0,0 +1,624 @@ +import os +import re +import sys +import typing as t +from functools import update_wrapper +from types import ModuleType +from types import TracebackType + +from ._compat import _default_text_stderr +from ._compat import _default_text_stdout +from ._compat import _find_binary_writer +from ._compat import auto_wrap_for_ansi +from ._compat import binary_streams +from ._compat import open_stream +from ._compat import should_strip_ansi +from ._compat import strip_ansi +from ._compat import text_streams +from ._compat import WIN +from .globals import resolve_color_default + +if t.TYPE_CHECKING: + import typing_extensions as te + + P = te.ParamSpec("P") + +R = t.TypeVar("R") + + +def _posixify(name: str) -> str: + return "-".join(name.split()).lower() + + +def safecall(func: "t.Callable[P, R]") -> "t.Callable[P, t.Optional[R]]": + """Wraps a function so that it swallows exceptions.""" + + def wrapper(*args: "P.args", **kwargs: "P.kwargs") -> t.Optional[R]: + try: + return func(*args, **kwargs) + except Exception: + pass + return None + + return update_wrapper(wrapper, func) + + +def make_str(value: t.Any) -> str: + """Converts a value into a valid string.""" + if isinstance(value, bytes): + try: + return value.decode(sys.getfilesystemencoding()) + except UnicodeError: + return value.decode("utf-8", "replace") + return str(value) + + +def make_default_short_help(help: str, max_length: int = 45) -> str: + """Returns a condensed version of help string.""" + # Consider only the first paragraph. + paragraph_end = help.find("\n\n") + + if paragraph_end != -1: + help = help[:paragraph_end] + + # Collapse newlines, tabs, and spaces. + words = help.split() + + if not words: + return "" + + # The first paragraph started with a "no rewrap" marker, ignore it. + if words[0] == "\b": + words = words[1:] + + total_length = 0 + last_index = len(words) - 1 + + for i, word in enumerate(words): + total_length += len(word) + (i > 0) + + if total_length > max_length: # too long, truncate + break + + if word[-1] == ".": # sentence end, truncate without "..." + return " ".join(words[: i + 1]) + + if total_length == max_length and i != last_index: + break # not at sentence end, truncate with "..." + else: + return " ".join(words) # no truncation needed + + # Account for the length of the suffix. + total_length += len("...") + + # remove words until the length is short enough + while i > 0: + total_length -= len(words[i]) + (i > 0) + + if total_length <= max_length: + break + + i -= 1 + + return " ".join(words[:i]) + "..." + + +class LazyFile: + """A lazy file works like a regular file but it does not fully open + the file but it does perform some basic checks early to see if the + filename parameter does make sense. This is useful for safely opening + files for writing. + """ + + def __init__( + self, + filename: t.Union[str, "os.PathLike[str]"], + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + atomic: bool = False, + ): + self.name: str = os.fspath(filename) + self.mode = mode + self.encoding = encoding + self.errors = errors + self.atomic = atomic + self._f: t.Optional[t.IO[t.Any]] + self.should_close: bool + + if self.name == "-": + self._f, self.should_close = open_stream(filename, mode, encoding, errors) + else: + if "r" in mode: + # Open and close the file in case we're opening it for + # reading so that we can catch at least some errors in + # some cases early. + open(filename, mode).close() + self._f = None + self.should_close = True + + def __getattr__(self, name: str) -> t.Any: + return getattr(self.open(), name) + + def __repr__(self) -> str: + if self._f is not None: + return repr(self._f) + return f"" + + def open(self) -> t.IO[t.Any]: + """Opens the file if it's not yet open. This call might fail with + a :exc:`FileError`. Not handling this error will produce an error + that Click shows. + """ + if self._f is not None: + return self._f + try: + rv, self.should_close = open_stream( + self.name, self.mode, self.encoding, self.errors, atomic=self.atomic + ) + except OSError as e: + from .exceptions import FileError + + raise FileError(self.name, hint=e.strerror) from e + self._f = rv + return rv + + def close(self) -> None: + """Closes the underlying file, no matter what.""" + if self._f is not None: + self._f.close() + + def close_intelligently(self) -> None: + """This function only closes the file if it was opened by the lazy + file wrapper. For instance this will never close stdin. + """ + if self.should_close: + self.close() + + def __enter__(self) -> "LazyFile": + return self + + def __exit__( + self, + exc_type: t.Optional[t.Type[BaseException]], + exc_value: t.Optional[BaseException], + tb: t.Optional[TracebackType], + ) -> None: + self.close_intelligently() + + def __iter__(self) -> t.Iterator[t.AnyStr]: + self.open() + return iter(self._f) # type: ignore + + +class KeepOpenFile: + def __init__(self, file: t.IO[t.Any]) -> None: + self._file: t.IO[t.Any] = file + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._file, name) + + def __enter__(self) -> "KeepOpenFile": + return self + + def __exit__( + self, + exc_type: t.Optional[t.Type[BaseException]], + exc_value: t.Optional[BaseException], + tb: t.Optional[TracebackType], + ) -> None: + pass + + def __repr__(self) -> str: + return repr(self._file) + + def __iter__(self) -> t.Iterator[t.AnyStr]: + return iter(self._file) + + +def echo( + message: t.Optional[t.Any] = None, + file: t.Optional[t.IO[t.Any]] = None, + nl: bool = True, + err: bool = False, + color: t.Optional[bool] = None, +) -> None: + """Print a message and newline to stdout or a file. This should be + used instead of :func:`print` because it provides better support + for different data, files, and environments. + + Compared to :func:`print`, this does the following: + + - Ensures that the output encoding is not misconfigured on Linux. + - Supports Unicode in the Windows console. + - Supports writing to binary outputs, and supports writing bytes + to text outputs. + - Supports colors and styles on Windows. + - Removes ANSI color and style codes if the output does not look + like an interactive terminal. + - Always flushes the output. + + :param message: The string or bytes to output. Other objects are + converted to strings. + :param file: The file to write to. Defaults to ``stdout``. + :param err: Write to ``stderr`` instead of ``stdout``. + :param nl: Print a newline after the message. Enabled by default. + :param color: Force showing or hiding colors and other styles. By + default Click will remove color if the output does not look like + an interactive terminal. + + .. versionchanged:: 6.0 + Support Unicode output on the Windows console. Click does not + modify ``sys.stdout``, so ``sys.stdout.write()`` and ``print()`` + will still not support Unicode. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. + + .. versionadded:: 3.0 + Added the ``err`` parameter. + + .. versionchanged:: 2.0 + Support colors on Windows if colorama is installed. + """ + if file is None: + if err: + file = _default_text_stderr() + else: + file = _default_text_stdout() + + # There are no standard streams attached to write to. For example, + # pythonw on Windows. + if file is None: + return + + # Convert non bytes/text into the native string type. + if message is not None and not isinstance(message, (str, bytes, bytearray)): + out: t.Optional[t.Union[str, bytes]] = str(message) + else: + out = message + + if nl: + out = out or "" + if isinstance(out, str): + out += "\n" + else: + out += b"\n" + + if not out: + file.flush() + return + + # If there is a message and the value looks like bytes, we manually + # need to find the binary stream and write the message in there. + # This is done separately so that most stream types will work as you + # would expect. Eg: you can write to StringIO for other cases. + if isinstance(out, (bytes, bytearray)): + binary_file = _find_binary_writer(file) + + if binary_file is not None: + file.flush() + binary_file.write(out) + binary_file.flush() + return + + # ANSI style code support. For no message or bytes, nothing happens. + # When outputting to a file instead of a terminal, strip codes. + else: + color = resolve_color_default(color) + + if should_strip_ansi(file, color): + out = strip_ansi(out) + elif WIN: + if auto_wrap_for_ansi is not None: + file = auto_wrap_for_ansi(file, color) # type: ignore + elif not color: + out = strip_ansi(out) + + file.write(out) # type: ignore + file.flush() + + +def get_binary_stream(name: "te.Literal['stdin', 'stdout', 'stderr']") -> t.BinaryIO: + """Returns a system stream for byte processing. + + :param name: the name of the stream to open. Valid names are ``'stdin'``, + ``'stdout'`` and ``'stderr'`` + """ + opener = binary_streams.get(name) + if opener is None: + raise TypeError(f"Unknown standard stream '{name}'") + return opener() + + +def get_text_stream( + name: "te.Literal['stdin', 'stdout', 'stderr']", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", +) -> t.TextIO: + """Returns a system stream for text processing. This usually returns + a wrapped stream around a binary stream returned from + :func:`get_binary_stream` but it also can take shortcuts for already + correctly configured streams. + + :param name: the name of the stream to open. Valid names are ``'stdin'``, + ``'stdout'`` and ``'stderr'`` + :param encoding: overrides the detected default encoding. + :param errors: overrides the default error mode. + """ + opener = text_streams.get(name) + if opener is None: + raise TypeError(f"Unknown standard stream '{name}'") + return opener(encoding, errors) + + +def open_file( + filename: t.Union[str, "os.PathLike[str]"], + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + lazy: bool = False, + atomic: bool = False, +) -> t.IO[t.Any]: + """Open a file, with extra behavior to handle ``'-'`` to indicate + a standard stream, lazy open on write, and atomic write. Similar to + the behavior of the :class:`~click.File` param type. + + If ``'-'`` is given to open ``stdout`` or ``stdin``, the stream is + wrapped so that using it in a context manager will not close it. + This makes it possible to use the function without accidentally + closing a standard stream: + + .. code-block:: python + + with open_file(filename) as f: + ... + + :param filename: The name or Path of the file to open, or ``'-'`` for + ``stdin``/``stdout``. + :param mode: The mode in which to open the file. + :param encoding: The encoding to decode or encode a file opened in + text mode. + :param errors: The error handling mode. + :param lazy: Wait to open the file until it is accessed. For read + mode, the file is temporarily opened to raise access errors + early, then closed until it is read again. + :param atomic: Write to a temporary file and replace the given file + on close. + + .. versionadded:: 3.0 + """ + if lazy: + return t.cast( + t.IO[t.Any], LazyFile(filename, mode, encoding, errors, atomic=atomic) + ) + + f, should_close = open_stream(filename, mode, encoding, errors, atomic=atomic) + + if not should_close: + f = t.cast(t.IO[t.Any], KeepOpenFile(f)) + + return f + + +def format_filename( + filename: "t.Union[str, bytes, os.PathLike[str], os.PathLike[bytes]]", + shorten: bool = False, +) -> str: + """Format a filename as a string for display. Ensures the filename can be + displayed by replacing any invalid bytes or surrogate escapes in the name + with the replacement character ``�``. + + Invalid bytes or surrogate escapes will raise an error when written to a + stream with ``errors="strict"``. This will typically happen with ``stdout`` + when the locale is something like ``en_GB.UTF-8``. + + Many scenarios *are* safe to write surrogates though, due to PEP 538 and + PEP 540, including: + + - Writing to ``stderr``, which uses ``errors="backslashreplace"``. + - The system has ``LANG=C.UTF-8``, ``C``, or ``POSIX``. Python opens + stdout and stderr with ``errors="surrogateescape"``. + - None of ``LANG/LC_*`` are set. Python assumes ``LANG=C.UTF-8``. + - Python is started in UTF-8 mode with ``PYTHONUTF8=1`` or ``-X utf8``. + Python opens stdout and stderr with ``errors="surrogateescape"``. + + :param filename: formats a filename for UI display. This will also convert + the filename into unicode without failing. + :param shorten: this optionally shortens the filename to strip of the + path that leads up to it. + """ + if shorten: + filename = os.path.basename(filename) + else: + filename = os.fspath(filename) + + if isinstance(filename, bytes): + filename = filename.decode(sys.getfilesystemencoding(), "replace") + else: + filename = filename.encode("utf-8", "surrogateescape").decode( + "utf-8", "replace" + ) + + return filename + + +def get_app_dir(app_name: str, roaming: bool = True, force_posix: bool = False) -> str: + r"""Returns the config folder for the application. The default behavior + is to return whatever is most appropriate for the operating system. + + To give you an idea, for an app called ``"Foo Bar"``, something like + the following folders could be returned: + + Mac OS X: + ``~/Library/Application Support/Foo Bar`` + Mac OS X (POSIX): + ``~/.foo-bar`` + Unix: + ``~/.config/foo-bar`` + Unix (POSIX): + ``~/.foo-bar`` + Windows (roaming): + ``C:\Users\\AppData\Roaming\Foo Bar`` + Windows (not roaming): + ``C:\Users\\AppData\Local\Foo Bar`` + + .. versionadded:: 2.0 + + :param app_name: the application name. This should be properly capitalized + and can contain whitespace. + :param roaming: controls if the folder should be roaming or not on Windows. + Has no effect otherwise. + :param force_posix: if this is set to `True` then on any POSIX system the + folder will be stored in the home folder with a leading + dot instead of the XDG config home or darwin's + application support folder. + """ + if WIN: + key = "APPDATA" if roaming else "LOCALAPPDATA" + folder = os.environ.get(key) + if folder is None: + folder = os.path.expanduser("~") + return os.path.join(folder, app_name) + if force_posix: + return os.path.join(os.path.expanduser(f"~/.{_posixify(app_name)}")) + if sys.platform == "darwin": + return os.path.join( + os.path.expanduser("~/Library/Application Support"), app_name + ) + return os.path.join( + os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config")), + _posixify(app_name), + ) + + +class PacifyFlushWrapper: + """This wrapper is used to catch and suppress BrokenPipeErrors resulting + from ``.flush()`` being called on broken pipe during the shutdown/final-GC + of the Python interpreter. Notably ``.flush()`` is always called on + ``sys.stdout`` and ``sys.stderr``. So as to have minimal impact on any + other cleanup code, and the case where the underlying file is not a broken + pipe, all calls and attributes are proxied. + """ + + def __init__(self, wrapped: t.IO[t.Any]) -> None: + self.wrapped = wrapped + + def flush(self) -> None: + try: + self.wrapped.flush() + except OSError as e: + import errno + + if e.errno != errno.EPIPE: + raise + + def __getattr__(self, attr: str) -> t.Any: + return getattr(self.wrapped, attr) + + +def _detect_program_name( + path: t.Optional[str] = None, _main: t.Optional[ModuleType] = None +) -> str: + """Determine the command used to run the program, for use in help + text. If a file or entry point was executed, the file name is + returned. If ``python -m`` was used to execute a module or package, + ``python -m name`` is returned. + + This doesn't try to be too precise, the goal is to give a concise + name for help text. Files are only shown as their name without the + path. ``python`` is only shown for modules, and the full path to + ``sys.executable`` is not shown. + + :param path: The Python file being executed. Python puts this in + ``sys.argv[0]``, which is used by default. + :param _main: The ``__main__`` module. This should only be passed + during internal testing. + + .. versionadded:: 8.0 + Based on command args detection in the Werkzeug reloader. + + :meta private: + """ + if _main is None: + _main = sys.modules["__main__"] + + if not path: + path = sys.argv[0] + + # The value of __package__ indicates how Python was called. It may + # not exist if a setuptools script is installed as an egg. It may be + # set incorrectly for entry points created with pip on Windows. + # It is set to "" inside a Shiv or PEX zipapp. + if getattr(_main, "__package__", None) in {None, ""} or ( + os.name == "nt" + and _main.__package__ == "" + and not os.path.exists(path) + and os.path.exists(f"{path}.exe") + ): + # Executed a file, like "python app.py". + return os.path.basename(path) + + # Executed a module, like "python -m example". + # Rewritten by Python from "-m script" to "/path/to/script.py". + # Need to look at main module to determine how it was executed. + py_module = t.cast(str, _main.__package__) + name = os.path.splitext(os.path.basename(path))[0] + + # A submodule like "example.cli". + if name != "__main__": + py_module = f"{py_module}.{name}" + + return f"python -m {py_module.lstrip('.')}" + + +def _expand_args( + args: t.Iterable[str], + *, + user: bool = True, + env: bool = True, + glob_recursive: bool = True, +) -> t.List[str]: + """Simulate Unix shell expansion with Python functions. + + See :func:`glob.glob`, :func:`os.path.expanduser`, and + :func:`os.path.expandvars`. + + This is intended for use on Windows, where the shell does not do any + expansion. It may not exactly match what a Unix shell would do. + + :param args: List of command line arguments to expand. + :param user: Expand user home directory. + :param env: Expand environment variables. + :param glob_recursive: ``**`` matches directories recursively. + + .. versionchanged:: 8.1 + Invalid glob patterns are treated as empty expansions rather + than raising an error. + + .. versionadded:: 8.0 + + :meta private: + """ + from glob import glob + + out = [] + + for arg in args: + if user: + arg = os.path.expanduser(arg) + + if env: + arg = os.path.expandvars(arg) + + try: + matches = glob(arg, recursive=glob_recursive) + except re.error: + matches = [] + + if not matches: + out.append(arg) + else: + out.extend(matches) + + return out diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup-1.3.1.dist-info/INSTALLER b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup-1.3.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup-1.3.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup-1.3.1.dist-info/METADATA b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup-1.3.1.dist-info/METADATA new file mode 100644 index 0000000..e1a9a27 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup-1.3.1.dist-info/METADATA @@ -0,0 +1,159 @@ +Metadata-Version: 2.4 +Name: exceptiongroup +Version: 1.3.1 +Summary: Backport of PEP 654 (exception groups) +Author-email: Alex Grönholm +Requires-Python: >=3.7 +Description-Content-Type: text/x-rst +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Typing :: Typed +License-File: LICENSE +Requires-Dist: typing-extensions >= 4.6.0; python_version < '3.13' +Requires-Dist: pytest >= 6 ; extra == "test" +Project-URL: Changelog, https://github.com/agronholm/exceptiongroup/blob/main/CHANGES.rst +Project-URL: Issue Tracker, https://github.com/agronholm/exceptiongroup/issues +Project-URL: Source code, https://github.com/agronholm/exceptiongroup +Provides-Extra: test + +.. image:: https://github.com/agronholm/exceptiongroup/actions/workflows/test.yml/badge.svg + :target: https://github.com/agronholm/exceptiongroup/actions/workflows/test.yml + :alt: Build Status +.. image:: https://coveralls.io/repos/github/agronholm/exceptiongroup/badge.svg?branch=main + :target: https://coveralls.io/github/agronholm/exceptiongroup?branch=main + :alt: Code Coverage + +This is a backport of the ``BaseExceptionGroup`` and ``ExceptionGroup`` classes from +Python 3.11. + +It contains the following: + +* The ``exceptiongroup.BaseExceptionGroup`` and ``exceptiongroup.ExceptionGroup`` + classes +* A utility function (``exceptiongroup.catch()``) for catching exceptions possibly + nested in an exception group +* Patches to the ``TracebackException`` class that properly formats exception groups + (installed on import) +* An exception hook that handles formatting of exception groups through + ``TracebackException`` (installed on import) +* Special versions of some of the functions from the ``traceback`` module, modified to + correctly handle exception groups even when monkey patching is disabled, or blocked by + another custom exception hook: + + * ``traceback.format_exception()`` + * ``traceback.format_exception_only()`` + * ``traceback.print_exception()`` + * ``traceback.print_exc()`` +* A backported version of ``contextlib.suppress()`` from Python 3.12.1 which also + handles suppressing exceptions inside exception groups + +If this package is imported on Python 3.11 or later, the built-in implementations of the +exception group classes are used instead, ``TracebackException`` is not monkey patched +and the exception hook won't be installed. + +See the `standard library documentation`_ for more information on exception groups. + +.. _standard library documentation: https://docs.python.org/3/library/exceptions.html + +Catching exceptions +=================== + +Due to the lack of the ``except*`` syntax introduced by `PEP 654`_ in earlier Python +versions, you need to use ``exceptiongroup.catch()`` to catch exceptions that are +potentially nested inside an exception group. This function returns a context manager +that calls the given handler for any exceptions matching the sole argument. + +The argument to ``catch()`` must be a dict (or any ``Mapping``) where each key is either +an exception class or an iterable of exception classes. Each value must be a callable +that takes a single positional argument. The handler will be called at most once, with +an exception group as an argument which will contain all the exceptions that are any +of the given types, or their subclasses. The exception group may contain nested groups +containing more matching exceptions. + +Thus, the following Python 3.11+ code: + +.. code-block:: python + + try: + ... + except* (ValueError, KeyError) as excgroup: + for exc in excgroup.exceptions: + print('Caught exception:', type(exc)) + except* RuntimeError: + print('Caught runtime error') + +would be written with this backport like this: + +.. code-block:: python + + from exceptiongroup import BaseExceptionGroup, catch + + def value_key_err_handler(excgroup: BaseExceptionGroup) -> None: + for exc in excgroup.exceptions: + print('Caught exception:', type(exc)) + + def runtime_err_handler(exc: BaseExceptionGroup) -> None: + print('Caught runtime error') + + with catch({ + (ValueError, KeyError): value_key_err_handler, + RuntimeError: runtime_err_handler + }): + ... + +**NOTE**: Just like with ``except*``, you cannot handle ``BaseExceptionGroup`` or +``ExceptionGroup`` with ``catch()``. + +Suppressing exceptions +====================== + +This library contains a backport of the ``contextlib.suppress()`` context manager from +Python 3.12.1. It allows you to selectively ignore certain exceptions, even when they're +inside exception groups: + +.. code-block:: python + + from exceptiongroup import suppress + + with suppress(RuntimeError): + raise ExceptionGroup("", [RuntimeError("boo")]) + +Notes on monkey patching +======================== + +To make exception groups render properly when an unhandled exception group is being +printed out, this package does two things when it is imported on any Python version +earlier than 3.11: + +#. The ``traceback.TracebackException`` class is monkey patched to store extra + information about exception groups (in ``__init__()``) and properly format them (in + ``format()``) +#. An exception hook is installed at ``sys.excepthook``, provided that no other hook is + already present. This hook causes the exception to be formatted using + ``traceback.TracebackException`` rather than the built-in rendered. + +If ``sys.exceptionhook`` is found to be set to something else than the default when +``exceptiongroup`` is imported, no monkeypatching is done at all. + +To prevent the exception hook and patches from being installed, set the environment +variable ``EXCEPTIONGROUP_NO_PATCH`` to ``1``. + +Formatting exception groups +--------------------------- + +Normally, the monkey patching applied by this library on import will cause exception +groups to be printed properly in tracebacks. But in cases when the monkey patching is +blocked by a third party exception hook, or monkey patching is explicitly disabled, +you can still manually format exceptions using the special versions of the ``traceback`` +functions, like ``format_exception()``, listed at the top of this page. They work just +like their counterparts in the ``traceback`` module, except that they use a separately +patched subclass of ``TracebackException`` to perform the rendering. + +Particularly in cases where a library installs its own exception hook, it is recommended +to use these special versions to do the actual formatting of exceptions/tracebacks. + +.. _PEP 654: https://www.python.org/dev/peps/pep-0654/ + diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup-1.3.1.dist-info/RECORD b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup-1.3.1.dist-info/RECORD new file mode 100644 index 0000000..9f810d1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup-1.3.1.dist-info/RECORD @@ -0,0 +1,12 @@ +exceptiongroup-1.3.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +exceptiongroup-1.3.1.dist-info/METADATA,sha256=gZhKUjovelIq0SvqeEqLuF7ewIBeu9D7TjUBaaNt2AI,6725 +exceptiongroup-1.3.1.dist-info/RECORD,, +exceptiongroup-1.3.1.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82 +exceptiongroup-1.3.1.dist-info/licenses/LICENSE,sha256=blBw12UDHgrUA6HL-Qrm0ZoCKPgC4yC3rP9GCqcu1Hw,3704 +exceptiongroup/__init__.py,sha256=7DHS0hDk-RIs3IQc3SbZVB0-1MhiSCJ9XgvEyEloL7M,1049 +exceptiongroup/_catch.py,sha256=CaJez3E-Jkr-7B7RT3fzusdLWnuyeekooSFn7KyWt9s,4680 +exceptiongroup/_exceptions.py,sha256=wPwPsZ64SXEptuwb4XrTIa1Mc78uqF5vmCrXTdllLn4,11463 +exceptiongroup/_formatting.py,sha256=OYTuT_T6TzM8G2v3DVt8LRBwMNyNK0tNl0fKMls3chM,21063 +exceptiongroup/_suppress.py,sha256=LX11PRNpchwfNWwEMY92nYN1F_5qFenQcS8EjIONXKE,1772 +exceptiongroup/_version.py,sha256=-4u7pjQ4caDQqa-1Qgms81j5hpkXjmjUYRCVEaLmb88,704 +exceptiongroup/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup-1.3.1.dist-info/WHEEL b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup-1.3.1.dist-info/WHEEL new file mode 100644 index 0000000..d8b9936 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup-1.3.1.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.12.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup-1.3.1.dist-info/licenses/LICENSE b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup-1.3.1.dist-info/licenses/LICENSE new file mode 100644 index 0000000..50d4fa5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup-1.3.1.dist-info/licenses/LICENSE @@ -0,0 +1,73 @@ +The MIT License (MIT) + +Copyright (c) 2022 Alex Grönholm + +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. + + +This project contains code copied from the Python standard library. +The following is the required license notice for those parts. + +PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 +-------------------------------------------- + +1. This LICENSE AGREEMENT is between the Python Software Foundation +("PSF"), and the Individual or Organization ("Licensee") accessing and +otherwise using this software ("Python") in source or binary form and +its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, PSF hereby +grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, +analyze, test, perform and/or display publicly, prepare derivative works, +distribute, and otherwise use Python alone or in any derivative version, +provided, however, that PSF's License Agreement and PSF's notice of copyright, +i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022 Python Software Foundation; +All Rights Reserved" are retained in Python alone or in any derivative version +prepared by Licensee. + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python. + +4. PSF is making Python available to Licensee on an "AS IS" +basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. Nothing in this License Agreement shall be deemed to create any +relationship of agency, partnership, or joint venture between PSF and +Licensee. This License Agreement does not grant permission to use PSF +trademarks or trade name in a trademark sense to endorse or promote +products or services of Licensee, or any third party. + +8. By copying, installing or otherwise using Python, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup/__init__.py new file mode 100644 index 0000000..d8e36b2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup/__init__.py @@ -0,0 +1,46 @@ +__all__ = [ + "BaseExceptionGroup", + "ExceptionGroup", + "catch", + "format_exception", + "format_exception_only", + "print_exception", + "print_exc", + "suppress", +] + +import os +import sys + +from ._catch import catch +from ._version import version as __version__ # noqa: F401 + +if sys.version_info < (3, 11): + from ._exceptions import BaseExceptionGroup, ExceptionGroup + from ._formatting import ( + format_exception, + format_exception_only, + print_exc, + print_exception, + ) + + if os.getenv("EXCEPTIONGROUP_NO_PATCH") != "1": + from . import _formatting # noqa: F401 + + BaseExceptionGroup.__module__ = __name__ + ExceptionGroup.__module__ = __name__ +else: + from traceback import ( + format_exception, + format_exception_only, + print_exc, + print_exception, + ) + + BaseExceptionGroup = BaseExceptionGroup + ExceptionGroup = ExceptionGroup + +if sys.version_info < (3, 12, 1): + from ._suppress import suppress +else: + from contextlib import suppress diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup/_catch.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup/_catch.py new file mode 100644 index 0000000..0246568 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup/_catch.py @@ -0,0 +1,138 @@ +from __future__ import annotations + +import inspect +import sys +from collections.abc import Callable, Iterable, Mapping +from contextlib import AbstractContextManager +from types import TracebackType +from typing import TYPE_CHECKING, Any + +if sys.version_info < (3, 11): + from ._exceptions import BaseExceptionGroup + +if TYPE_CHECKING: + _Handler = Callable[[BaseExceptionGroup[Any]], Any] + + +class _Catcher: + def __init__(self, handler_map: Mapping[tuple[type[BaseException], ...], _Handler]): + self._handler_map = handler_map + + def __enter__(self) -> None: + pass + + def __exit__( + self, + etype: type[BaseException] | None, + exc: BaseException | None, + tb: TracebackType | None, + ) -> bool: + if exc is not None: + unhandled = self.handle_exception(exc) + if unhandled is exc: + return False + elif unhandled is None: + return True + else: + if isinstance(exc, BaseExceptionGroup): + try: + raise unhandled from exc.__cause__ + except BaseExceptionGroup: + # Change __context__ to __cause__ because Python 3.11 does this + # too + unhandled.__context__ = exc.__cause__ + raise + + raise unhandled from exc + + return False + + def handle_exception(self, exc: BaseException) -> BaseException | None: + excgroup: BaseExceptionGroup | None + if isinstance(exc, BaseExceptionGroup): + excgroup = exc + else: + excgroup = BaseExceptionGroup("", [exc]) + + new_exceptions: list[BaseException] = [] + for exc_types, handler in self._handler_map.items(): + matched, excgroup = excgroup.split(exc_types) + if matched: + try: + try: + raise matched + except BaseExceptionGroup: + result = handler(matched) + except BaseExceptionGroup as new_exc: + if new_exc is matched: + new_exceptions.append(new_exc) + else: + new_exceptions.extend(new_exc.exceptions) + except BaseException as new_exc: + new_exceptions.append(new_exc) + else: + if inspect.iscoroutine(result): + raise TypeError( + f"Error trying to handle {matched!r} with {handler!r}. " + "Exception handler must be a sync function." + ) from exc + + if not excgroup: + break + + if new_exceptions: + if len(new_exceptions) == 1: + return new_exceptions[0] + + return BaseExceptionGroup("", new_exceptions) + elif ( + excgroup and len(excgroup.exceptions) == 1 and excgroup.exceptions[0] is exc + ): + return exc + else: + return excgroup + + +def catch( + __handlers: Mapping[type[BaseException] | Iterable[type[BaseException]], _Handler], +) -> AbstractContextManager[None]: + if not isinstance(__handlers, Mapping): + raise TypeError("the argument must be a mapping") + + handler_map: dict[ + tuple[type[BaseException], ...], Callable[[BaseExceptionGroup]] + ] = {} + for type_or_iterable, handler in __handlers.items(): + iterable: tuple[type[BaseException]] + if isinstance(type_or_iterable, type) and issubclass( + type_or_iterable, BaseException + ): + iterable = (type_or_iterable,) + elif isinstance(type_or_iterable, Iterable): + iterable = tuple(type_or_iterable) + else: + raise TypeError( + "each key must be either an exception classes or an iterable thereof" + ) + + if not callable(handler): + raise TypeError("handlers must be callable") + + for exc_type in iterable: + if not isinstance(exc_type, type) or not issubclass( + exc_type, BaseException + ): + raise TypeError( + "each key must be either an exception classes or an iterable " + "thereof" + ) + + if issubclass(exc_type, BaseExceptionGroup): + raise TypeError( + "catching ExceptionGroup with catch() is not allowed. " + "Use except instead." + ) + + handler_map[iterable] = handler + + return _Catcher(handler_map) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup/_exceptions.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup/_exceptions.py new file mode 100644 index 0000000..f42c1ad --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup/_exceptions.py @@ -0,0 +1,336 @@ +from __future__ import annotations + +import sys +from collections.abc import Callable, Sequence +from functools import partial +from inspect import getmro, isclass +from typing import TYPE_CHECKING, Generic, Type, TypeVar, cast, overload + +if sys.version_info < (3, 13): + from typing_extensions import TypeVar + +_BaseExceptionT_co = TypeVar( + "_BaseExceptionT_co", bound=BaseException, covariant=True, default=BaseException +) +_BaseExceptionT = TypeVar("_BaseExceptionT", bound=BaseException) +_ExceptionT_co = TypeVar( + "_ExceptionT_co", bound=Exception, covariant=True, default=Exception +) +_ExceptionT = TypeVar("_ExceptionT", bound=Exception) +# using typing.Self would require a typing_extensions dependency on py<3.11 +_ExceptionGroupSelf = TypeVar("_ExceptionGroupSelf", bound="ExceptionGroup") +_BaseExceptionGroupSelf = TypeVar("_BaseExceptionGroupSelf", bound="BaseExceptionGroup") + + +def check_direct_subclass( + exc: BaseException, parents: tuple[type[BaseException]] +) -> bool: + for cls in getmro(exc.__class__)[:-1]: + if cls in parents: + return True + + return False + + +def get_condition_filter( + condition: type[_BaseExceptionT] + | tuple[type[_BaseExceptionT], ...] + | Callable[[_BaseExceptionT_co], bool], +) -> Callable[[_BaseExceptionT_co], bool]: + if isclass(condition) and issubclass( + cast(Type[BaseException], condition), BaseException + ): + return partial(check_direct_subclass, parents=(condition,)) + elif isinstance(condition, tuple): + if all(isclass(x) and issubclass(x, BaseException) for x in condition): + return partial(check_direct_subclass, parents=condition) + elif callable(condition): + return cast("Callable[[BaseException], bool]", condition) + + raise TypeError("expected a function, exception type or tuple of exception types") + + +def _derive_and_copy_attributes(self, excs): + eg = self.derive(excs) + eg.__cause__ = self.__cause__ + eg.__context__ = self.__context__ + eg.__traceback__ = self.__traceback__ + if hasattr(self, "__notes__"): + # Create a new list so that add_note() only affects one exceptiongroup + eg.__notes__ = list(self.__notes__) + return eg + + +class BaseExceptionGroup(BaseException, Generic[_BaseExceptionT_co]): + """A combination of multiple unrelated exceptions.""" + + def __new__( + cls: type[_BaseExceptionGroupSelf], + __message: str, + __exceptions: Sequence[_BaseExceptionT_co], + ) -> _BaseExceptionGroupSelf: + if not isinstance(__message, str): + raise TypeError(f"argument 1 must be str, not {type(__message)}") + if not isinstance(__exceptions, Sequence): + raise TypeError("second argument (exceptions) must be a sequence") + if not __exceptions: + raise ValueError( + "second argument (exceptions) must be a non-empty sequence" + ) + + for i, exc in enumerate(__exceptions): + if not isinstance(exc, BaseException): + raise ValueError( + f"Item {i} of second argument (exceptions) is not an exception" + ) + + if cls is BaseExceptionGroup: + if all(isinstance(exc, Exception) for exc in __exceptions): + cls = ExceptionGroup + + if issubclass(cls, Exception): + for exc in __exceptions: + if not isinstance(exc, Exception): + if cls is ExceptionGroup: + raise TypeError( + "Cannot nest BaseExceptions in an ExceptionGroup" + ) + else: + raise TypeError( + f"Cannot nest BaseExceptions in {cls.__name__!r}" + ) + + instance = super().__new__(cls, __message, __exceptions) + instance._exceptions = tuple(__exceptions) + return instance + + def __init__( + self, + __message: str, + __exceptions: Sequence[_BaseExceptionT_co], + *args: object, + ) -> None: + BaseException.__init__(self, __message, __exceptions, *args) + + def add_note(self, note: str) -> None: + if not isinstance(note, str): + raise TypeError( + f"Expected a string, got note={note!r} (type {type(note).__name__})" + ) + + if not hasattr(self, "__notes__"): + self.__notes__: list[str] = [] + + self.__notes__.append(note) + + @property + def message(self) -> str: + return self.args[0] + + @property + def exceptions( + self, + ) -> tuple[_BaseExceptionT_co | BaseExceptionGroup[_BaseExceptionT_co], ...]: + return tuple(self._exceptions) + + @overload + def subgroup( + self, __condition: type[_ExceptionT] | tuple[type[_ExceptionT], ...] + ) -> ExceptionGroup[_ExceptionT] | None: ... + + @overload + def subgroup( + self, __condition: type[_BaseExceptionT] | tuple[type[_BaseExceptionT], ...] + ) -> BaseExceptionGroup[_BaseExceptionT] | None: ... + + @overload + def subgroup( + self, + __condition: Callable[[_BaseExceptionT_co | _BaseExceptionGroupSelf], bool], + ) -> BaseExceptionGroup[_BaseExceptionT_co] | None: ... + + def subgroup( + self, + __condition: type[_BaseExceptionT] + | tuple[type[_BaseExceptionT], ...] + | Callable[[_BaseExceptionT_co | _BaseExceptionGroupSelf], bool], + ) -> BaseExceptionGroup[_BaseExceptionT] | None: + condition = get_condition_filter(__condition) + modified = False + if condition(self): + return self + + exceptions: list[BaseException] = [] + for exc in self.exceptions: + if isinstance(exc, BaseExceptionGroup): + subgroup = exc.subgroup(__condition) + if subgroup is not None: + exceptions.append(subgroup) + + if subgroup is not exc: + modified = True + elif condition(exc): + exceptions.append(exc) + else: + modified = True + + if not modified: + return self + elif exceptions: + group = _derive_and_copy_attributes(self, exceptions) + return group + else: + return None + + @overload + def split( + self, __condition: type[_ExceptionT] | tuple[type[_ExceptionT], ...] + ) -> tuple[ + ExceptionGroup[_ExceptionT] | None, + BaseExceptionGroup[_BaseExceptionT_co] | None, + ]: ... + + @overload + def split( + self, __condition: type[_BaseExceptionT] | tuple[type[_BaseExceptionT], ...] + ) -> tuple[ + BaseExceptionGroup[_BaseExceptionT] | None, + BaseExceptionGroup[_BaseExceptionT_co] | None, + ]: ... + + @overload + def split( + self, + __condition: Callable[[_BaseExceptionT_co | _BaseExceptionGroupSelf], bool], + ) -> tuple[ + BaseExceptionGroup[_BaseExceptionT_co] | None, + BaseExceptionGroup[_BaseExceptionT_co] | None, + ]: ... + + def split( + self, + __condition: type[_BaseExceptionT] + | tuple[type[_BaseExceptionT], ...] + | Callable[[_BaseExceptionT_co], bool], + ) -> ( + tuple[ + ExceptionGroup[_ExceptionT] | None, + BaseExceptionGroup[_BaseExceptionT_co] | None, + ] + | tuple[ + BaseExceptionGroup[_BaseExceptionT] | None, + BaseExceptionGroup[_BaseExceptionT_co] | None, + ] + | tuple[ + BaseExceptionGroup[_BaseExceptionT_co] | None, + BaseExceptionGroup[_BaseExceptionT_co] | None, + ] + ): + condition = get_condition_filter(__condition) + if condition(self): + return self, None + + matching_exceptions: list[BaseException] = [] + nonmatching_exceptions: list[BaseException] = [] + for exc in self.exceptions: + if isinstance(exc, BaseExceptionGroup): + matching, nonmatching = exc.split(condition) + if matching is not None: + matching_exceptions.append(matching) + + if nonmatching is not None: + nonmatching_exceptions.append(nonmatching) + elif condition(exc): + matching_exceptions.append(exc) + else: + nonmatching_exceptions.append(exc) + + matching_group: _BaseExceptionGroupSelf | None = None + if matching_exceptions: + matching_group = _derive_and_copy_attributes(self, matching_exceptions) + + nonmatching_group: _BaseExceptionGroupSelf | None = None + if nonmatching_exceptions: + nonmatching_group = _derive_and_copy_attributes( + self, nonmatching_exceptions + ) + + return matching_group, nonmatching_group + + @overload + def derive(self, __excs: Sequence[_ExceptionT]) -> ExceptionGroup[_ExceptionT]: ... + + @overload + def derive( + self, __excs: Sequence[_BaseExceptionT] + ) -> BaseExceptionGroup[_BaseExceptionT]: ... + + def derive( + self, __excs: Sequence[_BaseExceptionT] + ) -> BaseExceptionGroup[_BaseExceptionT]: + return BaseExceptionGroup(self.message, __excs) + + def __str__(self) -> str: + suffix = "" if len(self._exceptions) == 1 else "s" + return f"{self.message} ({len(self._exceptions)} sub-exception{suffix})" + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self.args[0]!r}, {self.args[1]!r})" + + +class ExceptionGroup(BaseExceptionGroup[_ExceptionT_co], Exception): + def __new__( + cls: type[_ExceptionGroupSelf], + __message: str, + __exceptions: Sequence[_ExceptionT_co], + ) -> _ExceptionGroupSelf: + return super().__new__(cls, __message, __exceptions) + + if TYPE_CHECKING: + + @property + def exceptions( + self, + ) -> tuple[_ExceptionT_co | ExceptionGroup[_ExceptionT_co], ...]: ... + + @overload # type: ignore[override] + def subgroup( + self, __condition: type[_ExceptionT] | tuple[type[_ExceptionT], ...] + ) -> ExceptionGroup[_ExceptionT] | None: ... + + @overload + def subgroup( + self, __condition: Callable[[_ExceptionT_co | _ExceptionGroupSelf], bool] + ) -> ExceptionGroup[_ExceptionT_co] | None: ... + + def subgroup( + self, + __condition: type[_ExceptionT] + | tuple[type[_ExceptionT], ...] + | Callable[[_ExceptionT_co], bool], + ) -> ExceptionGroup[_ExceptionT] | None: + return super().subgroup(__condition) + + @overload + def split( + self, __condition: type[_ExceptionT] | tuple[type[_ExceptionT], ...] + ) -> tuple[ + ExceptionGroup[_ExceptionT] | None, ExceptionGroup[_ExceptionT_co] | None + ]: ... + + @overload + def split( + self, __condition: Callable[[_ExceptionT_co | _ExceptionGroupSelf], bool] + ) -> tuple[ + ExceptionGroup[_ExceptionT_co] | None, ExceptionGroup[_ExceptionT_co] | None + ]: ... + + def split( + self: _ExceptionGroupSelf, + __condition: type[_ExceptionT] + | tuple[type[_ExceptionT], ...] + | Callable[[_ExceptionT_co], bool], + ) -> tuple[ + ExceptionGroup[_ExceptionT_co] | None, ExceptionGroup[_ExceptionT_co] | None + ]: + return super().split(__condition) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup/_formatting.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup/_formatting.py new file mode 100644 index 0000000..490e2e0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup/_formatting.py @@ -0,0 +1,602 @@ +# traceback_exception_init() adapted from trio +# +# _ExceptionPrintContext and traceback_exception_format() copied from the standard +# library +from __future__ import annotations + +import collections.abc +import sys +import textwrap +import traceback +from functools import singledispatch +from types import TracebackType +from typing import Any, List, Optional + +from ._exceptions import BaseExceptionGroup + +max_group_width = 15 +max_group_depth = 10 +_cause_message = ( + "\nThe above exception was the direct cause of the following exception:\n\n" +) + +_context_message = ( + "\nDuring handling of the above exception, another exception occurred:\n\n" +) + + +def _format_final_exc_line(etype, value): + valuestr = _safe_string(value, "exception") + if value is None or not valuestr: + line = f"{etype}\n" + else: + line = f"{etype}: {valuestr}\n" + + return line + + +def _safe_string(value, what, func=str): + try: + return func(value) + except BaseException: + return f"<{what} {func.__name__}() failed>" + + +class _ExceptionPrintContext: + def __init__(self): + self.seen = set() + self.exception_group_depth = 0 + self.need_close = False + + def indent(self): + return " " * (2 * self.exception_group_depth) + + def emit(self, text_gen, margin_char=None): + if margin_char is None: + margin_char = "|" + indent_str = self.indent() + if self.exception_group_depth: + indent_str += margin_char + " " + + if isinstance(text_gen, str): + yield textwrap.indent(text_gen, indent_str, lambda line: True) + else: + for text in text_gen: + yield textwrap.indent(text, indent_str, lambda line: True) + + +def exceptiongroup_excepthook( + etype: type[BaseException], value: BaseException, tb: TracebackType | None +) -> None: + sys.stderr.write("".join(traceback.format_exception(etype, value, tb))) + + +class PatchedTracebackException(traceback.TracebackException): + def __init__( + self, + exc_type: type[BaseException], + exc_value: BaseException, + exc_traceback: TracebackType | None, + *, + limit: int | None = None, + lookup_lines: bool = True, + capture_locals: bool = False, + compact: bool = False, + _seen: set[int] | None = None, + ) -> None: + kwargs: dict[str, Any] = {} + if sys.version_info >= (3, 10): + kwargs["compact"] = compact + + is_recursive_call = _seen is not None + if _seen is None: + _seen = set() + _seen.add(id(exc_value)) + + self.stack = traceback.StackSummary.extract( + traceback.walk_tb(exc_traceback), + limit=limit, + lookup_lines=lookup_lines, + capture_locals=capture_locals, + ) + self.exc_type = exc_type + # Capture now to permit freeing resources: only complication is in the + # unofficial API _format_final_exc_line + self._str = _safe_string(exc_value, "exception") + try: + self.__notes__ = getattr(exc_value, "__notes__", None) + except KeyError: + # Workaround for https://github.com/python/cpython/issues/98778 on Python + # <= 3.9, and some 3.10 and 3.11 patch versions. + HTTPError = getattr(sys.modules.get("urllib.error", None), "HTTPError", ()) + if sys.version_info[:2] <= (3, 11) and isinstance(exc_value, HTTPError): + self.__notes__ = None + else: + raise + + if exc_type and issubclass(exc_type, SyntaxError): + # Handle SyntaxError's specially + self.filename = exc_value.filename + lno = exc_value.lineno + self.lineno = str(lno) if lno is not None else None + self.text = exc_value.text + self.offset = exc_value.offset + self.msg = exc_value.msg + if sys.version_info >= (3, 10): + end_lno = exc_value.end_lineno + self.end_lineno = str(end_lno) if end_lno is not None else None + self.end_offset = exc_value.end_offset + elif ( + exc_type + and issubclass(exc_type, (NameError, AttributeError)) + and getattr(exc_value, "name", None) is not None + ): + suggestion = _compute_suggestion_error(exc_value, exc_traceback) + if suggestion: + self._str += f". Did you mean: '{suggestion}'?" + + if lookup_lines: + # Force all lines in the stack to be loaded + for frame in self.stack: + frame.line + + self.__suppress_context__ = ( + exc_value.__suppress_context__ if exc_value is not None else False + ) + + # Convert __cause__ and __context__ to `TracebackExceptions`s, use a + # queue to avoid recursion (only the top-level call gets _seen == None) + if not is_recursive_call: + queue = [(self, exc_value)] + while queue: + te, e = queue.pop() + + if e and e.__cause__ is not None and id(e.__cause__) not in _seen: + cause = PatchedTracebackException( + type(e.__cause__), + e.__cause__, + e.__cause__.__traceback__, + limit=limit, + lookup_lines=lookup_lines, + capture_locals=capture_locals, + _seen=_seen, + ) + else: + cause = None + + if compact: + need_context = ( + cause is None and e is not None and not e.__suppress_context__ + ) + else: + need_context = True + if ( + e + and e.__context__ is not None + and need_context + and id(e.__context__) not in _seen + ): + context = PatchedTracebackException( + type(e.__context__), + e.__context__, + e.__context__.__traceback__, + limit=limit, + lookup_lines=lookup_lines, + capture_locals=capture_locals, + _seen=_seen, + ) + else: + context = None + + # Capture each of the exceptions in the ExceptionGroup along with each + # of their causes and contexts + if e and isinstance(e, BaseExceptionGroup): + exceptions = [] + for exc in e.exceptions: + texc = PatchedTracebackException( + type(exc), + exc, + exc.__traceback__, + lookup_lines=lookup_lines, + capture_locals=capture_locals, + _seen=_seen, + ) + exceptions.append(texc) + else: + exceptions = None + + te.__cause__ = cause + te.__context__ = context + te.exceptions = exceptions + if cause: + queue.append((te.__cause__, e.__cause__)) + if context: + queue.append((te.__context__, e.__context__)) + if exceptions: + queue.extend(zip(te.exceptions, e.exceptions)) + + def format(self, *, chain=True, _ctx=None, **kwargs): + if _ctx is None: + _ctx = _ExceptionPrintContext() + + output = [] + exc = self + if chain: + while exc: + if exc.__cause__ is not None: + chained_msg = _cause_message + chained_exc = exc.__cause__ + elif exc.__context__ is not None and not exc.__suppress_context__: + chained_msg = _context_message + chained_exc = exc.__context__ + else: + chained_msg = None + chained_exc = None + + output.append((chained_msg, exc)) + exc = chained_exc + else: + output.append((None, exc)) + + for msg, exc in reversed(output): + if msg is not None: + yield from _ctx.emit(msg) + if getattr(exc, "exceptions", None) is None: + if exc.stack: + yield from _ctx.emit("Traceback (most recent call last):\n") + yield from _ctx.emit(exc.stack.format()) + yield from _ctx.emit(exc.format_exception_only()) + elif _ctx.exception_group_depth > max_group_depth: + # exception group, but depth exceeds limit + yield from _ctx.emit(f"... (max_group_depth is {max_group_depth})\n") + else: + # format exception group + is_toplevel = _ctx.exception_group_depth == 0 + if is_toplevel: + _ctx.exception_group_depth += 1 + + if exc.stack: + yield from _ctx.emit( + "Exception Group Traceback (most recent call last):\n", + margin_char="+" if is_toplevel else None, + ) + yield from _ctx.emit(exc.stack.format()) + + yield from _ctx.emit(exc.format_exception_only()) + num_excs = len(exc.exceptions) + if num_excs <= max_group_width: + n = num_excs + else: + n = max_group_width + 1 + _ctx.need_close = False + for i in range(n): + last_exc = i == n - 1 + if last_exc: + # The closing frame may be added by a recursive call + _ctx.need_close = True + + if max_group_width is not None: + truncated = i >= max_group_width + else: + truncated = False + title = f"{i + 1}" if not truncated else "..." + yield ( + _ctx.indent() + + ("+-" if i == 0 else " ") + + f"+---------------- {title} ----------------\n" + ) + _ctx.exception_group_depth += 1 + if not truncated: + yield from exc.exceptions[i].format(chain=chain, _ctx=_ctx) + else: + remaining = num_excs - max_group_width + plural = "s" if remaining > 1 else "" + yield from _ctx.emit( + f"and {remaining} more exception{plural}\n" + ) + + if last_exc and _ctx.need_close: + yield _ctx.indent() + "+------------------------------------\n" + _ctx.need_close = False + _ctx.exception_group_depth -= 1 + + if is_toplevel: + assert _ctx.exception_group_depth == 1 + _ctx.exception_group_depth = 0 + + def format_exception_only(self, **kwargs): + """Format the exception part of the traceback. + The return value is a generator of strings, each ending in a newline. + Normally, the generator emits a single string; however, for + SyntaxError exceptions, it emits several lines that (when + printed) display detailed information about where the syntax + error occurred. + The message indicating which exception occurred is always the last + string in the output. + """ + if self.exc_type is None: + yield traceback._format_final_exc_line(None, self._str) + return + + stype = self.exc_type.__qualname__ + smod = self.exc_type.__module__ + if smod not in ("__main__", "builtins"): + if not isinstance(smod, str): + smod = "" + stype = smod + "." + stype + + if not issubclass(self.exc_type, SyntaxError): + yield _format_final_exc_line(stype, self._str) + elif traceback_exception_format_syntax_error is not None: + yield from traceback_exception_format_syntax_error(self, stype) + else: + yield from traceback_exception_original_format_exception_only(self) + + notes = getattr(self, "__notes__", None) + if isinstance(notes, collections.abc.Sequence): + for note in notes: + note = _safe_string(note, "note") + yield from [line + "\n" for line in note.split("\n")] + elif notes is not None: + yield _safe_string(notes, "__notes__", func=repr) + + +traceback_exception_original_format = traceback.TracebackException.format +traceback_exception_original_format_exception_only = ( + traceback.TracebackException.format_exception_only +) +traceback_exception_format_syntax_error = getattr( + traceback.TracebackException, "_format_syntax_error", None +) +if sys.excepthook is sys.__excepthook__: + traceback.TracebackException.__init__ = ( # type: ignore[assignment] + PatchedTracebackException.__init__ + ) + traceback.TracebackException.format = ( # type: ignore[assignment] + PatchedTracebackException.format + ) + traceback.TracebackException.format_exception_only = ( # type: ignore[assignment] + PatchedTracebackException.format_exception_only + ) + sys.excepthook = exceptiongroup_excepthook + +# Ubuntu's system Python has a sitecustomize.py file that imports +# apport_python_hook and replaces sys.excepthook. +# +# The custom hook captures the error for crash reporting, and then calls +# sys.__excepthook__ to actually print the error. +# +# We don't mind it capturing the error for crash reporting, but we want to +# take over printing the error. So we monkeypatch the apport_python_hook +# module so that instead of calling sys.__excepthook__, it calls our custom +# hook. +# +# More details: https://github.com/python-trio/trio/issues/1065 +if getattr(sys.excepthook, "__name__", None) in ( + "apport_excepthook", + # on ubuntu 22.10 the hook was renamed to partial_apport_excepthook + "partial_apport_excepthook", +): + # patch traceback like above + traceback.TracebackException.__init__ = ( # type: ignore[assignment] + PatchedTracebackException.__init__ + ) + traceback.TracebackException.format = ( # type: ignore[assignment] + PatchedTracebackException.format + ) + traceback.TracebackException.format_exception_only = ( # type: ignore[assignment] + PatchedTracebackException.format_exception_only + ) + + from types import ModuleType + + import apport_python_hook + + # monkeypatch the sys module that apport has imported + fake_sys = ModuleType("exceptiongroup_fake_sys") + fake_sys.__dict__.update(sys.__dict__) + fake_sys.__excepthook__ = exceptiongroup_excepthook + apport_python_hook.sys = fake_sys + + +@singledispatch +def format_exception_only(__exc: BaseException, **kwargs: Any) -> List[str]: + return list( + PatchedTracebackException( + type(__exc), __exc, None, compact=True + ).format_exception_only() + ) + + +@format_exception_only.register +def _(__exc: type, value: BaseException, **kwargs: Any) -> List[str]: + return format_exception_only(value) + + +@singledispatch +def format_exception( + __exc: BaseException, limit: Optional[int] = None, chain: bool = True, **kwargs: Any +) -> List[str]: + return list( + PatchedTracebackException( + type(__exc), __exc, __exc.__traceback__, limit=limit, compact=True + ).format(chain=chain) + ) + + +@format_exception.register +def _( + __exc: type, + value: BaseException, + tb: TracebackType, + limit: Optional[int] = None, + chain: bool = True, + **kwargs: Any, +) -> List[str]: + return format_exception(value, limit, chain) + + +@singledispatch +def print_exception( + __exc: BaseException, + limit: Optional[int] = None, + file: Any = None, + chain: bool = True, + **kwargs: Any, +) -> None: + if file is None: + file = sys.stderr + + for line in PatchedTracebackException( + type(__exc), __exc, __exc.__traceback__, limit=limit + ).format(chain=chain): + print(line, file=file, end="") + + +@print_exception.register +def _( + __exc: type, + value: BaseException, + tb: TracebackType, + limit: Optional[int] = None, + file: Any = None, + chain: bool = True, +) -> None: + print_exception(value, limit, file, chain) + + +def print_exc( + limit: Optional[int] = None, + file: Any | None = None, + chain: bool = True, +) -> None: + value = sys.exc_info()[1] + print_exception(value, limit, file, chain) + + +# Python levenshtein edit distance code for NameError/AttributeError +# suggestions, backported from 3.12 + +_MAX_CANDIDATE_ITEMS = 750 +_MAX_STRING_SIZE = 40 +_MOVE_COST = 2 +_CASE_COST = 1 +_SENTINEL = object() + + +def _substitution_cost(ch_a, ch_b): + if ch_a == ch_b: + return 0 + if ch_a.lower() == ch_b.lower(): + return _CASE_COST + return _MOVE_COST + + +def _compute_suggestion_error(exc_value, tb): + wrong_name = getattr(exc_value, "name", None) + if wrong_name is None or not isinstance(wrong_name, str): + return None + if isinstance(exc_value, AttributeError): + obj = getattr(exc_value, "obj", _SENTINEL) + if obj is _SENTINEL: + return None + obj = exc_value.obj + try: + d = dir(obj) + except Exception: + return None + else: + assert isinstance(exc_value, NameError) + # find most recent frame + if tb is None: + return None + while tb.tb_next is not None: + tb = tb.tb_next + frame = tb.tb_frame + + d = list(frame.f_locals) + list(frame.f_globals) + list(frame.f_builtins) + if len(d) > _MAX_CANDIDATE_ITEMS: + return None + wrong_name_len = len(wrong_name) + if wrong_name_len > _MAX_STRING_SIZE: + return None + best_distance = wrong_name_len + suggestion = None + for possible_name in d: + if possible_name == wrong_name: + # A missing attribute is "found". Don't suggest it (see GH-88821). + continue + # No more than 1/3 of the involved characters should need changed. + max_distance = (len(possible_name) + wrong_name_len + 3) * _MOVE_COST // 6 + # Don't take matches we've already beaten. + max_distance = min(max_distance, best_distance - 1) + current_distance = _levenshtein_distance( + wrong_name, possible_name, max_distance + ) + if current_distance > max_distance: + continue + if not suggestion or current_distance < best_distance: + suggestion = possible_name + best_distance = current_distance + return suggestion + + +def _levenshtein_distance(a, b, max_cost): + # A Python implementation of Python/suggestions.c:levenshtein_distance. + + # Both strings are the same + if a == b: + return 0 + + # Trim away common affixes + pre = 0 + while a[pre:] and b[pre:] and a[pre] == b[pre]: + pre += 1 + a = a[pre:] + b = b[pre:] + post = 0 + while a[: post or None] and b[: post or None] and a[post - 1] == b[post - 1]: + post -= 1 + a = a[: post or None] + b = b[: post or None] + if not a or not b: + return _MOVE_COST * (len(a) + len(b)) + if len(a) > _MAX_STRING_SIZE or len(b) > _MAX_STRING_SIZE: + return max_cost + 1 + + # Prefer shorter buffer + if len(b) < len(a): + a, b = b, a + + # Quick fail when a match is impossible + if (len(b) - len(a)) * _MOVE_COST > max_cost: + return max_cost + 1 + + # Instead of producing the whole traditional len(a)-by-len(b) + # matrix, we can update just one row in place. + # Initialize the buffer row + row = list(range(_MOVE_COST, _MOVE_COST * (len(a) + 1), _MOVE_COST)) + + result = 0 + for bindex in range(len(b)): + bchar = b[bindex] + distance = result = bindex * _MOVE_COST + minimum = sys.maxsize + for index in range(len(a)): + # 1) Previous distance in this row is cost(b[:b_index], a[:index]) + substitute = distance + _substitution_cost(bchar, a[index]) + # 2) cost(b[:b_index], a[:index+1]) from previous row + distance = row[index] + # 3) existing result is cost(b[:b_index+1], a[index]) + + insert_delete = min(result, distance) + _MOVE_COST + result = min(insert_delete, substitute) + + # cost(b[:b_index+1], a[:index+1]) + row[index] = result + if result < minimum: + minimum = result + if minimum > max_cost: + # Everything in this row is too big, so bail early. + return max_cost + 1 + return result diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup/_suppress.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup/_suppress.py new file mode 100644 index 0000000..11467ee --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup/_suppress.py @@ -0,0 +1,55 @@ +from __future__ import annotations + +import sys +from contextlib import AbstractContextManager +from types import TracebackType +from typing import TYPE_CHECKING, Optional, Type, cast + +if sys.version_info < (3, 11): + from ._exceptions import BaseExceptionGroup + +if TYPE_CHECKING: + # requires python 3.9 + BaseClass = AbstractContextManager[None] +else: + BaseClass = AbstractContextManager + + +class suppress(BaseClass): + """Backport of :class:`contextlib.suppress` from Python 3.12.1.""" + + def __init__(self, *exceptions: type[BaseException]): + self._exceptions = exceptions + + def __enter__(self) -> None: + pass + + def __exit__( + self, + exctype: Optional[Type[BaseException]], + excinst: Optional[BaseException], + exctb: Optional[TracebackType], + ) -> bool: + # Unlike isinstance and issubclass, CPython exception handling + # currently only looks at the concrete type hierarchy (ignoring + # the instance and subclass checking hooks). While Guido considers + # that a bug rather than a feature, it's a fairly hard one to fix + # due to various internal implementation details. suppress provides + # the simpler issubclass based semantics, rather than trying to + # exactly reproduce the limitations of the CPython interpreter. + # + # See http://bugs.python.org/issue12029 for more details + if exctype is None: + return False + + if issubclass(exctype, self._exceptions): + return True + + if issubclass(exctype, BaseExceptionGroup): + match, rest = cast(BaseExceptionGroup, excinst).split(self._exceptions) + if rest is None: + return True + + raise rest + + return False diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup/_version.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup/_version.py new file mode 100644 index 0000000..ebbbcb2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup/_version.py @@ -0,0 +1,34 @@ +# file generated by setuptools-scm +# don't change, don't track in version control + +__all__ = [ + "__version__", + "__version_tuple__", + "version", + "version_tuple", + "__commit_id__", + "commit_id", +] + +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import Tuple + from typing import Union + + VERSION_TUPLE = Tuple[Union[int, str], ...] + COMMIT_ID = Union[str, None] +else: + VERSION_TUPLE = object + COMMIT_ID = object + +version: str +__version__: str +__version_tuple__: VERSION_TUPLE +version_tuple: VERSION_TUPLE +commit_id: COMMIT_ID +__commit_id__: COMMIT_ID + +__version__ = version = '1.3.1' +__version_tuple__ = version_tuple = (1, 3, 1) + +__commit_id__ = commit_id = None diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup/py.typed b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/exceptiongroup/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi-0.99.1.dist-info/INSTALLER b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi-0.99.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi-0.99.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi-0.99.1.dist-info/METADATA b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi-0.99.1.dist-info/METADATA new file mode 100644 index 0000000..9ca5933 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi-0.99.1.dist-info/METADATA @@ -0,0 +1,522 @@ +Metadata-Version: 2.4 +Name: fastapi +Version: 0.99.1 +Summary: FastAPI framework, high performance, easy to learn, fast to code, ready for production +Project-URL: Homepage, https://github.com/tiangolo/fastapi +Project-URL: Documentation, https://fastapi.tiangolo.com/ +Project-URL: Repository, https://github.com/tiangolo/fastapi +Author-email: Sebastián Ramírez +License-Expression: MIT +License-File: LICENSE +Classifier: Development Status :: 4 - Beta +Classifier: Environment :: Web Environment +Classifier: Framework :: AsyncIO +Classifier: Framework :: FastAPI +Classifier: Framework :: Pydantic +Classifier: Framework :: Pydantic :: 1 +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: Information Technology +Classifier: Intended Audience :: System Administrators +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Topic :: Internet +Classifier: Topic :: Internet :: WWW/HTTP +Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers +Classifier: Topic :: Software Development +Classifier: Topic :: Software Development :: Libraries +Classifier: Topic :: Software Development :: Libraries :: Application Frameworks +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Typing :: Typed +Requires-Python: >=3.7 +Requires-Dist: pydantic!=1.8,!=1.8.1,<2.0.0,>=1.7.4 +Requires-Dist: starlette<0.28.0,>=0.27.0 +Requires-Dist: typing-extensions>=4.5.0 +Provides-Extra: all +Requires-Dist: email-validator>=1.1.1; extra == 'all' +Requires-Dist: httpx>=0.23.0; extra == 'all' +Requires-Dist: itsdangerous>=1.1.0; extra == 'all' +Requires-Dist: jinja2>=2.11.2; extra == 'all' +Requires-Dist: orjson>=3.2.1; extra == 'all' +Requires-Dist: python-multipart>=0.0.5; extra == 'all' +Requires-Dist: pyyaml>=5.3.1; extra == 'all' +Requires-Dist: ujson!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,>=4.0.1; extra == 'all' +Requires-Dist: uvicorn[standard]>=0.12.0; extra == 'all' +Description-Content-Type: text/markdown + +

    + FastAPI +

    +

    + FastAPI framework, high performance, easy to learn, fast to code, ready for production +

    +

    + + Test + + + Coverage + + + Package version + + + Supported Python versions + +

    + +--- + +**Documentation**: https://fastapi.tiangolo.com + +**Source Code**: https://github.com/tiangolo/fastapi + +--- + +FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.7+ based on standard Python type hints. + +The key features are: + +* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance). +* **Fast to code**: Increase the speed to develop features by about 200% to 300%. * +* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. * +* **Intuitive**: Great editor support. Completion everywhere. Less time debugging. +* **Easy**: Designed to be easy to use and learn. Less time reading docs. +* **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs. +* **Robust**: Get production-ready code. With automatic interactive documentation. +* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: OpenAPI (previously known as Swagger) and JSON Schema. + +* estimation based on tests on an internal development team, building production applications. + +## Sponsors + + + + + + + + + + + + + + + +Other sponsors + +## Opinions + +"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._" + +
    Kabir Khan - Microsoft (ref)
    + +--- + +"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_" + +
    Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (ref)
    + +--- + +"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_" + +
    Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
    + +--- + +"_I’m over the moon excited about **FastAPI**. It’s so fun!_" + +
    Brian Okken - Python Bytes podcast host (ref)
    + +--- + +"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._" + +
    Timothy Crosley - Hug creator (ref)
    + +--- + +"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_" + +"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_" + +
    Ines Montani - Matthew Honnibal - Explosion AI founders - spaCy creators (ref) - (ref)
    + +--- + +"_If anyone is looking to build a production Python API, I would highly recommend **FastAPI**. It is **beautifully designed**, **simple to use** and **highly scalable**, it has become a **key component** in our API first development strategy and is driving many automations and services such as our Virtual TAC Engineer._" + +
    Deon Pillsbury - Cisco (ref)
    + +--- + +## **Typer**, the FastAPI of CLIs + + + +If you are building a CLI app to be used in the terminal instead of a web API, check out **Typer**. + +**Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀 + +## Requirements + +Python 3.7+ + +FastAPI stands on the shoulders of giants: + +* Starlette for the web parts. +* Pydantic for the data parts. + +## Installation + +
    + +```console +$ pip install fastapi + +---> 100% +``` + +
    + +You will also need an ASGI server, for production such as Uvicorn or Hypercorn. + +
    + +```console +$ pip install "uvicorn[standard]" + +---> 100% +``` + +
    + +## Example + +### Create it + +* Create a file `main.py` with: + +```Python +from typing import Union + +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: Union[str, None] = None): + return {"item_id": item_id, "q": q} +``` + +
    +Or use async def... + +If your code uses `async` / `await`, use `async def`: + +```Python hl_lines="9 14" +from typing import Union + +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +async def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +async def read_item(item_id: int, q: Union[str, None] = None): + return {"item_id": item_id, "q": q} +``` + +**Note**: + +If you don't know, check the _"In a hurry?"_ section about `async` and `await` in the docs. + +
    + +### Run it + +Run the server with: + +
    + +```console +$ uvicorn main:app --reload + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +INFO: Started reloader process [28720] +INFO: Started server process [28722] +INFO: Waiting for application startup. +INFO: Application startup complete. +``` + +
    + +
    +About the command uvicorn main:app --reload... + +The command `uvicorn main:app` refers to: + +* `main`: the file `main.py` (the Python "module"). +* `app`: the object created inside of `main.py` with the line `app = FastAPI()`. +* `--reload`: make the server restart after code changes. Only do this for development. + +
    + +### Check it + +Open your browser at http://127.0.0.1:8000/items/5?q=somequery. + +You will see the JSON response as: + +```JSON +{"item_id": 5, "q": "somequery"} +``` + +You already created an API that: + +* Receives HTTP requests in the _paths_ `/` and `/items/{item_id}`. +* Both _paths_ take `GET` operations (also known as HTTP _methods_). +* The _path_ `/items/{item_id}` has a _path parameter_ `item_id` that should be an `int`. +* The _path_ `/items/{item_id}` has an optional `str` _query parameter_ `q`. + +### Interactive API docs + +Now go to http://127.0.0.1:8000/docs. + +You will see the automatic interactive API documentation (provided by Swagger UI): + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) + +### Alternative API docs + +And now, go to http://127.0.0.1:8000/redoc. + +You will see the alternative automatic documentation (provided by ReDoc): + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) + +## Example upgrade + +Now modify the file `main.py` to receive a body from a `PUT` request. + +Declare the body using standard Python types, thanks to Pydantic. + +```Python hl_lines="4 9-12 25-27" +from typing import Union + +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + price: float + is_offer: Union[bool, None] = None + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: Union[str, None] = None): + return {"item_id": item_id, "q": q} + + +@app.put("/items/{item_id}") +def update_item(item_id: int, item: Item): + return {"item_name": item.name, "item_id": item_id} +``` + +The server should reload automatically (because you added `--reload` to the `uvicorn` command above). + +### Interactive API docs upgrade + +Now go to http://127.0.0.1:8000/docs. + +* The interactive API documentation will be automatically updated, including the new body: + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) + +* Click on the button "Try it out", it allows you to fill the parameters and directly interact with the API: + +![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png) + +* Then click on the "Execute" button, the user interface will communicate with your API, send the parameters, get the results and show them on the screen: + +![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png) + +### Alternative API docs upgrade + +And now, go to http://127.0.0.1:8000/redoc. + +* The alternative documentation will also reflect the new query parameter and body: + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) + +### Recap + +In summary, you declare **once** the types of parameters, body, etc. as function parameters. + +You do that with standard modern Python types. + +You don't have to learn a new syntax, the methods or classes of a specific library, etc. + +Just standard **Python 3.7+**. + +For example, for an `int`: + +```Python +item_id: int +``` + +or for a more complex `Item` model: + +```Python +item: Item +``` + +...and with that single declaration you get: + +* Editor support, including: + * Completion. + * Type checks. +* Validation of data: + * Automatic and clear errors when the data is invalid. + * Validation even for deeply nested JSON objects. +* Conversion of input data: coming from the network to Python data and types. Reading from: + * JSON. + * Path parameters. + * Query parameters. + * Cookies. + * Headers. + * Forms. + * Files. +* Conversion of output data: converting from Python data and types to network data (as JSON): + * Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc). + * `datetime` objects. + * `UUID` objects. + * Database models. + * ...and many more. +* Automatic interactive API documentation, including 2 alternative user interfaces: + * Swagger UI. + * ReDoc. + +--- + +Coming back to the previous code example, **FastAPI** will: + +* Validate that there is an `item_id` in the path for `GET` and `PUT` requests. +* Validate that the `item_id` is of type `int` for `GET` and `PUT` requests. + * If it is not, the client will see a useful, clear error. +* Check if there is an optional query parameter named `q` (as in `http://127.0.0.1:8000/items/foo?q=somequery`) for `GET` requests. + * As the `q` parameter is declared with `= None`, it is optional. + * Without the `None` it would be required (as is the body in the case with `PUT`). +* For `PUT` requests to `/items/{item_id}`, Read the body as JSON: + * Check that it has a required attribute `name` that should be a `str`. + * Check that it has a required attribute `price` that has to be a `float`. + * Check that it has an optional attribute `is_offer`, that should be a `bool`, if present. + * All this would also work for deeply nested JSON objects. +* Convert from and to JSON automatically. +* Document everything with OpenAPI, that can be used by: + * Interactive documentation systems. + * Automatic client code generation systems, for many languages. +* Provide 2 interactive documentation web interfaces directly. + +--- + +We just scratched the surface, but you already get the idea of how it all works. + +Try changing the line with: + +```Python + return {"item_name": item.name, "item_id": item_id} +``` + +...from: + +```Python + ... "item_name": item.name ... +``` + +...to: + +```Python + ... "item_price": item.price ... +``` + +...and see how your editor will auto-complete the attributes and know their types: + +![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) + +For a more complete example including more features, see the Tutorial - User Guide. + +**Spoiler alert**: the tutorial - user guide includes: + +* Declaration of **parameters** from other different places as: **headers**, **cookies**, **form fields** and **files**. +* How to set **validation constraints** as `maximum_length` or `regex`. +* A very powerful and easy to use **Dependency Injection** system. +* Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth. +* More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic). +* **GraphQL** integration with Strawberry and other libraries. +* Many extra features (thanks to Starlette) as: + * **WebSockets** + * extremely easy tests based on HTTPX and `pytest` + * **CORS** + * **Cookie Sessions** + * ...and more. + +## Performance + +Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as one of the fastest Python frameworks available, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*) + +To understand more about it, see the section Benchmarks. + +## Optional Dependencies + +Used by Pydantic: + +* email_validator - for email validation. + +Used by Starlette: + +* httpx - Required if you want to use the `TestClient`. +* jinja2 - Required if you want to use the default template configuration. +* python-multipart - Required if you want to support form "parsing", with `request.form()`. +* itsdangerous - Required for `SessionMiddleware` support. +* pyyaml - Required for Starlette's `SchemaGenerator` support (you probably don't need it with FastAPI). +* ujson - Required if you want to use `UJSONResponse`. + +Used by FastAPI / Starlette: + +* uvicorn - for the server that loads and serves your application. +* orjson - Required if you want to use `ORJSONResponse`. + +You can install all of these with `pip install "fastapi[all]"`. + +## License + +This project is licensed under the terms of the MIT license. diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi-0.99.1.dist-info/RECORD b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi-0.99.1.dist-info/RECORD new file mode 100644 index 0000000..9a75d27 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi-0.99.1.dist-info/RECORD @@ -0,0 +1,49 @@ +fastapi-0.99.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +fastapi-0.99.1.dist-info/METADATA,sha256=qMya5ltHmFFhB-pIrJNctt85acEde7COzJwpo54w6Ug,23001 +fastapi-0.99.1.dist-info/RECORD,, +fastapi-0.99.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +fastapi-0.99.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87 +fastapi-0.99.1.dist-info/licenses/LICENSE,sha256=Tsif_IFIW5f-xYSy1KlhAy7v_oNEU4lP2cEnSQbMdE4,1086 +fastapi/__init__.py,sha256=V35ESeBEwy1Lt6Cww96Iur2-HGWcKpCxF5CKPjEW2y8,1080 +fastapi/applications.py,sha256=xV95gsMsnOqsezXnBEBpL9Yb7prwd0s9c-be8EmEa4w,40588 +fastapi/background.py,sha256=HtN5_pJJrOdalSbuGSMKJAPNWUU5h7rY_BXXubu7-IQ,76 +fastapi/concurrency.py,sha256=h7ZhZG8cEiVx6an1txcB2RKpjW6_xmHwFo9E3vUiMQA,1468 +fastapi/datastructures.py,sha256=oW6xuU0C-sBwbcyXI-MlBO0tSS4BSPB2lYUa1yCw8-A,1905 +fastapi/dependencies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +fastapi/dependencies/models.py,sha256=zNbioxICuOeb-9ADDVQ45hUHOC0PBtPVEfVU3f1l_nc,2494 +fastapi/dependencies/utils.py,sha256=hDn1Uz6g_CiSrQikwA8WrYs_vH-Og5kG2a1qFFc6ZpA,30908 +fastapi/encoders.py,sha256=VsFE_5xOv9c53-qctpTQf4xsscrJhmZZJdif1-1WTjs,5976 +fastapi/exception_handlers.py,sha256=MBrIOA-ugjJDivIi4rSsUJBdTsjuzN76q4yh0q1COKw,1332 +fastapi/exceptions.py,sha256=rYONIZZhCPYCrA8XTNMQ07GVsGBSN7LipSLsoFB3JMk,1205 +fastapi/logger.py,sha256=I9NNi3ov8AcqbsbC9wl1X-hdItKgYt2XTrx1f99Zpl4,54 +fastapi/middleware/__init__.py,sha256=oQDxiFVcc1fYJUOIFvphnK7pTT5kktmfL32QXpBFvvo,58 +fastapi/middleware/asyncexitstack.py,sha256=LvMyVI1QdmWNWYPZqx295VFavssUfVpUsonPOsMWz1E,1035 +fastapi/middleware/cors.py,sha256=ynwjWQZoc_vbhzZ3_ZXceoaSrslHFHPdoM52rXr0WUU,79 +fastapi/middleware/gzip.py,sha256=xM5PcsH8QlAimZw4VDvcmTnqQamslThsfe3CVN2voa0,79 +fastapi/middleware/httpsredirect.py,sha256=rL8eXMnmLijwVkH7_400zHri1AekfeBd6D6qs8ix950,115 +fastapi/middleware/trustedhost.py,sha256=eE5XGRxGa7c5zPnMJDGp3BxaL25k5iVQlhnv-Pk0Pss,109 +fastapi/middleware/wsgi.py,sha256=Z3Ue-7wni4lUZMvH3G9ek__acgYdJstbnpZX_HQAboY,79 +fastapi/openapi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +fastapi/openapi/constants.py,sha256=mWxYBjED6PU-tQ9X227Qkq2SsW2cv-C1jYFKt63xxEs,107 +fastapi/openapi/docs.py,sha256=HbP76-u4A45BrL4WjLMhA3MBVI9xMx7XiMyDRS_ZO0E,6532 +fastapi/openapi/models.py,sha256=ff5fxNEhhf7Gh5SIOkVuIrLe-gVSDpo9doVi56Byoog,14941 +fastapi/openapi/utils.py,sha256=JWM8ApZ2Ij6m7VSalKrzU2MYfNQY-nrpi2FunaushM8,19576 +fastapi/param_functions.py,sha256=LOzbtY0eqmivGM_-MgzvQoCZim0WMQNO60JDFyQi3Do,8981 +fastapi/params.py,sha256=kmLpzYZ7uYI_jGxZJtgtPPrV1n4nbQQEykeLAyTyG48,13207 +fastapi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +fastapi/requests.py,sha256=zayepKFcienBllv3snmWI20Gk0oHNVLU4DDhqXBb4LU,142 +fastapi/responses.py,sha256=on95e4CfSRyNz7MEjqFuzsP-eW8kHWTxEl_Z-Vzb7lA,1242 +fastapi/routing.py,sha256=ENL3MNsSqlqo5Io7AGj0g7reX59PhfwIRsfQTEsTIhc,56490 +fastapi/security/__init__.py,sha256=bO8pNmxqVRXUjfl2mOKiVZLn0FpBQ61VUYVjmppnbJw,881 +fastapi/security/api_key.py,sha256=92kxZjj9OuIvQCUpLszP9qlILRgx6hCh1x-bZdhmQDU,2939 +fastapi/security/base.py,sha256=dl4pvbC-RxjfbWgPtCWd8MVU-7CB2SZ22rJDXVCXO6c,141 +fastapi/security/http.py,sha256=VbTm1k6t6EjJAnCnYVquSOmSK7fATdKRgq0-TgC7FnQ,5964 +fastapi/security/oauth2.py,sha256=I0DyRHEmfn_Up8vpYl3H8EV0dTdl5T1S3ib8EtRqfMI,8360 +fastapi/security/open_id_connect_url.py,sha256=GKK84g6OZbOFCEZJyd27pGjpaClGxeZrYOemUzyhfbU,1141 +fastapi/security/utils.py,sha256=bd8T0YM7UQD5ATKucr1bNtAvz_Y3__dVNAv5UebiPvc,293 +fastapi/staticfiles.py,sha256=iirGIt3sdY2QZXd36ijs3Cj-T0FuGFda3cd90kM9Ikw,69 +fastapi/templating.py,sha256=4zsuTWgcjcEainMJFAlW6-gnslm6AgOS1SiiDWfmQxk,76 +fastapi/testclient.py,sha256=nBvaAmX66YldReJNZXPOk1sfuo2Q6hs8bOvIaCep6LQ,66 +fastapi/types.py,sha256=r6MngTHzkZOP9lzXgduje9yeZe5EInWAzCLuRJlhIuE,118 +fastapi/utils.py,sha256=ROfkxh6erG_hGkmTNGE4gD36D_dZ33R5jL8GOjzHGPM,7652 +fastapi/websockets.py,sha256=419uncYObEKZG0YcrXscfQQYLSWoE10jqxVMetGdR98,222 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi-0.99.1.dist-info/REQUESTED b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi-0.99.1.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi-0.99.1.dist-info/WHEEL b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi-0.99.1.dist-info/WHEEL new file mode 100644 index 0000000..12228d4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi-0.99.1.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: hatchling 1.27.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi-0.99.1.dist-info/licenses/LICENSE b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi-0.99.1.dist-info/licenses/LICENSE new file mode 100644 index 0000000..3e92463 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi-0.99.1.dist-info/licenses/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2018 Sebastián Ramírez + +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. diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/__init__.py new file mode 100644 index 0000000..2d1bac2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/__init__.py @@ -0,0 +1,25 @@ +"""FastAPI framework, high performance, easy to learn, fast to code, ready for production""" + +__version__ = "0.99.1" + +from starlette import status as status + +from .applications import FastAPI as FastAPI +from .background import BackgroundTasks as BackgroundTasks +from .datastructures import UploadFile as UploadFile +from .exceptions import HTTPException as HTTPException +from .exceptions import WebSocketException as WebSocketException +from .param_functions import Body as Body +from .param_functions import Cookie as Cookie +from .param_functions import Depends as Depends +from .param_functions import File as File +from .param_functions import Form as Form +from .param_functions import Header as Header +from .param_functions import Path as Path +from .param_functions import Query as Query +from .param_functions import Security as Security +from .requests import Request as Request +from .responses import Response as Response +from .routing import APIRouter as APIRouter +from .websockets import WebSocket as WebSocket +from .websockets import WebSocketDisconnect as WebSocketDisconnect diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/applications.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/applications.py new file mode 100644 index 0000000..88f861c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/applications.py @@ -0,0 +1,943 @@ +from enum import Enum +from typing import ( + Any, + Awaitable, + Callable, + Coroutine, + Dict, + List, + Optional, + Sequence, + Type, + TypeVar, + Union, +) + +from fastapi import routing +from fastapi.datastructures import Default, DefaultPlaceholder +from fastapi.encoders import DictIntStrAny, SetIntStr +from fastapi.exception_handlers import ( + http_exception_handler, + request_validation_exception_handler, + websocket_request_validation_exception_handler, +) +from fastapi.exceptions import RequestValidationError, WebSocketRequestValidationError +from fastapi.logger import logger +from fastapi.middleware.asyncexitstack import AsyncExitStackMiddleware +from fastapi.openapi.docs import ( + get_redoc_html, + get_swagger_ui_html, + get_swagger_ui_oauth2_redirect_html, +) +from fastapi.openapi.utils import get_openapi +from fastapi.params import Depends +from fastapi.types import DecoratedCallable +from fastapi.utils import generate_unique_id +from starlette.applications import Starlette +from starlette.datastructures import State +from starlette.exceptions import HTTPException +from starlette.middleware import Middleware +from starlette.middleware.base import BaseHTTPMiddleware +from starlette.middleware.errors import ServerErrorMiddleware +from starlette.middleware.exceptions import ExceptionMiddleware +from starlette.requests import Request +from starlette.responses import HTMLResponse, JSONResponse, Response +from starlette.routing import BaseRoute +from starlette.types import ASGIApp, Lifespan, Receive, Scope, Send + +AppType = TypeVar("AppType", bound="FastAPI") + + +class FastAPI(Starlette): + def __init__( + self: AppType, + *, + debug: bool = False, + routes: Optional[List[BaseRoute]] = None, + title: str = "FastAPI", + summary: Optional[str] = None, + description: str = "", + version: str = "0.1.0", + openapi_url: Optional[str] = "/openapi.json", + openapi_tags: Optional[List[Dict[str, Any]]] = None, + servers: Optional[List[Dict[str, Union[str, Any]]]] = None, + dependencies: Optional[Sequence[Depends]] = None, + default_response_class: Type[Response] = Default(JSONResponse), + redirect_slashes: bool = True, + docs_url: Optional[str] = "/docs", + redoc_url: Optional[str] = "/redoc", + swagger_ui_oauth2_redirect_url: Optional[str] = "/docs/oauth2-redirect", + swagger_ui_init_oauth: Optional[Dict[str, Any]] = None, + middleware: Optional[Sequence[Middleware]] = None, + exception_handlers: Optional[ + Dict[ + Union[int, Type[Exception]], + Callable[[Request, Any], Coroutine[Any, Any, Response]], + ] + ] = None, + on_startup: Optional[Sequence[Callable[[], Any]]] = None, + on_shutdown: Optional[Sequence[Callable[[], Any]]] = None, + lifespan: Optional[Lifespan[AppType]] = None, + terms_of_service: Optional[str] = None, + contact: Optional[Dict[str, Union[str, Any]]] = None, + license_info: Optional[Dict[str, Union[str, Any]]] = None, + openapi_prefix: str = "", + root_path: str = "", + root_path_in_servers: bool = True, + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + callbacks: Optional[List[BaseRoute]] = None, + webhooks: Optional[routing.APIRouter] = None, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + swagger_ui_parameters: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( + generate_unique_id + ), + **extra: Any, + ) -> None: + self.debug = debug + self.title = title + self.summary = summary + self.description = description + self.version = version + self.terms_of_service = terms_of_service + self.contact = contact + self.license_info = license_info + self.openapi_url = openapi_url + self.openapi_tags = openapi_tags + self.root_path_in_servers = root_path_in_servers + self.docs_url = docs_url + self.redoc_url = redoc_url + self.swagger_ui_oauth2_redirect_url = swagger_ui_oauth2_redirect_url + self.swagger_ui_init_oauth = swagger_ui_init_oauth + self.swagger_ui_parameters = swagger_ui_parameters + self.servers = servers or [] + self.extra = extra + self.openapi_version = "3.1.0" + self.openapi_schema: Optional[Dict[str, Any]] = None + if self.openapi_url: + assert self.title, "A title must be provided for OpenAPI, e.g.: 'My API'" + assert self.version, "A version must be provided for OpenAPI, e.g.: '2.1.0'" + # TODO: remove when discarding the openapi_prefix parameter + if openapi_prefix: + logger.warning( + '"openapi_prefix" has been deprecated in favor of "root_path", which ' + "follows more closely the ASGI standard, is simpler, and more " + "automatic. Check the docs at " + "https://fastapi.tiangolo.com/advanced/sub-applications/" + ) + self.webhooks = webhooks or routing.APIRouter() + self.root_path = root_path or openapi_prefix + self.state: State = State() + self.dependency_overrides: Dict[Callable[..., Any], Callable[..., Any]] = {} + self.router: routing.APIRouter = routing.APIRouter( + routes=routes, + redirect_slashes=redirect_slashes, + dependency_overrides_provider=self, + on_startup=on_startup, + on_shutdown=on_shutdown, + lifespan=lifespan, + default_response_class=default_response_class, + dependencies=dependencies, + callbacks=callbacks, + deprecated=deprecated, + include_in_schema=include_in_schema, + responses=responses, + generate_unique_id_function=generate_unique_id_function, + ) + self.exception_handlers: Dict[ + Any, Callable[[Request, Any], Union[Response, Awaitable[Response]]] + ] = ({} if exception_handlers is None else dict(exception_handlers)) + self.exception_handlers.setdefault(HTTPException, http_exception_handler) + self.exception_handlers.setdefault( + RequestValidationError, request_validation_exception_handler + ) + self.exception_handlers.setdefault( + WebSocketRequestValidationError, + # Starlette still has incorrect type specification for the handlers + websocket_request_validation_exception_handler, # type: ignore + ) + + self.user_middleware: List[Middleware] = ( + [] if middleware is None else list(middleware) + ) + self.middleware_stack: Union[ASGIApp, None] = None + self.setup() + + def build_middleware_stack(self) -> ASGIApp: + # Duplicate/override from Starlette to add AsyncExitStackMiddleware + # inside of ExceptionMiddleware, inside of custom user middlewares + debug = self.debug + error_handler = None + exception_handlers = {} + + for key, value in self.exception_handlers.items(): + if key in (500, Exception): + error_handler = value + else: + exception_handlers[key] = value + + middleware = ( + [Middleware(ServerErrorMiddleware, handler=error_handler, debug=debug)] + + self.user_middleware + + [ + Middleware( + ExceptionMiddleware, handlers=exception_handlers, debug=debug + ), + # Add FastAPI-specific AsyncExitStackMiddleware for dependencies with + # contextvars. + # This needs to happen after user middlewares because those create a + # new contextvars context copy by using a new AnyIO task group. + # The initial part of dependencies with yield is executed in the + # FastAPI code, inside all the middlewares, but the teardown part + # (after yield) is executed in the AsyncExitStack in this middleware, + # if the AsyncExitStack lived outside of the custom middlewares and + # contextvars were set in a dependency with yield in that internal + # contextvars context, the values would not be available in the + # outside context of the AsyncExitStack. + # By putting the middleware and the AsyncExitStack here, inside all + # user middlewares, the code before and after yield in dependencies + # with yield is executed in the same contextvars context, so all values + # set in contextvars before yield is still available after yield as + # would be expected. + # Additionally, by having this AsyncExitStack here, after the + # ExceptionMiddleware, now dependencies can catch handled exceptions, + # e.g. HTTPException, to customize the teardown code (e.g. DB session + # rollback). + Middleware(AsyncExitStackMiddleware), + ] + ) + + app = self.router + for cls, options in reversed(middleware): + app = cls(app=app, **options) + return app + + def openapi(self) -> Dict[str, Any]: + if not self.openapi_schema: + self.openapi_schema = get_openapi( + title=self.title, + version=self.version, + openapi_version=self.openapi_version, + summary=self.summary, + description=self.description, + terms_of_service=self.terms_of_service, + contact=self.contact, + license_info=self.license_info, + routes=self.routes, + webhooks=self.webhooks.routes, + tags=self.openapi_tags, + servers=self.servers, + ) + return self.openapi_schema + + def setup(self) -> None: + if self.openapi_url: + urls = (server_data.get("url") for server_data in self.servers) + server_urls = {url for url in urls if url} + + async def openapi(req: Request) -> JSONResponse: + root_path = req.scope.get("root_path", "").rstrip("/") + if root_path not in server_urls: + if root_path and self.root_path_in_servers: + self.servers.insert(0, {"url": root_path}) + server_urls.add(root_path) + return JSONResponse(self.openapi()) + + self.add_route(self.openapi_url, openapi, include_in_schema=False) + if self.openapi_url and self.docs_url: + + async def swagger_ui_html(req: Request) -> HTMLResponse: + root_path = req.scope.get("root_path", "").rstrip("/") + openapi_url = root_path + self.openapi_url + oauth2_redirect_url = self.swagger_ui_oauth2_redirect_url + if oauth2_redirect_url: + oauth2_redirect_url = root_path + oauth2_redirect_url + return get_swagger_ui_html( + openapi_url=openapi_url, + title=self.title + " - Swagger UI", + oauth2_redirect_url=oauth2_redirect_url, + init_oauth=self.swagger_ui_init_oauth, + swagger_ui_parameters=self.swagger_ui_parameters, + ) + + self.add_route(self.docs_url, swagger_ui_html, include_in_schema=False) + + if self.swagger_ui_oauth2_redirect_url: + + async def swagger_ui_redirect(req: Request) -> HTMLResponse: + return get_swagger_ui_oauth2_redirect_html() + + self.add_route( + self.swagger_ui_oauth2_redirect_url, + swagger_ui_redirect, + include_in_schema=False, + ) + if self.openapi_url and self.redoc_url: + + async def redoc_html(req: Request) -> HTMLResponse: + root_path = req.scope.get("root_path", "").rstrip("/") + openapi_url = root_path + self.openapi_url + return get_redoc_html( + openapi_url=openapi_url, title=self.title + " - ReDoc" + ) + + self.add_route(self.redoc_url, redoc_html, include_in_schema=False) + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if self.root_path: + scope["root_path"] = self.root_path + await super().__call__(scope, receive, send) + + def add_api_route( + self, + path: str, + endpoint: Callable[..., Coroutine[Any, Any, Response]], + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + methods: Optional[List[str]] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Union[Type[Response], DefaultPlaceholder] = Default( + JSONResponse + ), + name: Optional[str] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( + generate_unique_id + ), + ) -> None: + self.router.add_api_route( + path, + endpoint=endpoint, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + methods=methods, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def api_route( + self, + path: str, + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + methods: Optional[List[str]] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Type[Response] = Default(JSONResponse), + name: Optional[str] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + def decorator(func: DecoratedCallable) -> DecoratedCallable: + self.router.add_api_route( + path, + func, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + methods=methods, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + return func + + return decorator + + def add_api_websocket_route( + self, + path: str, + endpoint: Callable[..., Any], + name: Optional[str] = None, + *, + dependencies: Optional[Sequence[Depends]] = None, + ) -> None: + self.router.add_api_websocket_route( + path, + endpoint, + name=name, + dependencies=dependencies, + ) + + def websocket( + self, + path: str, + name: Optional[str] = None, + *, + dependencies: Optional[Sequence[Depends]] = None, + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + def decorator(func: DecoratedCallable) -> DecoratedCallable: + self.add_api_websocket_route( + path, + func, + name=name, + dependencies=dependencies, + ) + return func + + return decorator + + def include_router( + self, + router: routing.APIRouter, + *, + prefix: str = "", + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[Depends]] = None, + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + default_response_class: Type[Response] = Default(JSONResponse), + callbacks: Optional[List[BaseRoute]] = None, + generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( + generate_unique_id + ), + ) -> None: + self.router.include_router( + router, + prefix=prefix, + tags=tags, + dependencies=dependencies, + responses=responses, + deprecated=deprecated, + include_in_schema=include_in_schema, + default_response_class=default_response_class, + callbacks=callbacks, + generate_unique_id_function=generate_unique_id_function, + ) + + def get( + self, + path: str, + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Type[Response] = Default(JSONResponse), + name: Optional[str] = None, + callbacks: Optional[List[BaseRoute]] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + return self.router.get( + path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def put( + self, + path: str, + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Type[Response] = Default(JSONResponse), + name: Optional[str] = None, + callbacks: Optional[List[BaseRoute]] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + return self.router.put( + path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def post( + self, + path: str, + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Type[Response] = Default(JSONResponse), + name: Optional[str] = None, + callbacks: Optional[List[BaseRoute]] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + return self.router.post( + path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def delete( + self, + path: str, + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Type[Response] = Default(JSONResponse), + name: Optional[str] = None, + callbacks: Optional[List[BaseRoute]] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + return self.router.delete( + path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def options( + self, + path: str, + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Type[Response] = Default(JSONResponse), + name: Optional[str] = None, + callbacks: Optional[List[BaseRoute]] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + return self.router.options( + path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def head( + self, + path: str, + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Type[Response] = Default(JSONResponse), + name: Optional[str] = None, + callbacks: Optional[List[BaseRoute]] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + return self.router.head( + path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def patch( + self, + path: str, + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Type[Response] = Default(JSONResponse), + name: Optional[str] = None, + callbacks: Optional[List[BaseRoute]] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + return self.router.patch( + path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def trace( + self, + path: str, + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Type[Response] = Default(JSONResponse), + name: Optional[str] = None, + callbacks: Optional[List[BaseRoute]] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Callable[[routing.APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + return self.router.trace( + path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def websocket_route( + self, path: str, name: Union[str, None] = None + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + def decorator(func: DecoratedCallable) -> DecoratedCallable: + self.router.add_websocket_route(path, func, name=name) + return func + + return decorator + + def on_event( + self, event_type: str + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + return self.router.on_event(event_type) + + def middleware( + self, middleware_type: str + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + def decorator(func: DecoratedCallable) -> DecoratedCallable: + self.add_middleware(BaseHTTPMiddleware, dispatch=func) + return func + + return decorator + + def exception_handler( + self, exc_class_or_status_code: Union[int, Type[Exception]] + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + def decorator(func: DecoratedCallable) -> DecoratedCallable: + self.add_exception_handler(exc_class_or_status_code, func) + return func + + return decorator diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/background.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/background.py new file mode 100644 index 0000000..dd3bbe2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/background.py @@ -0,0 +1 @@ +from starlette.background import BackgroundTasks as BackgroundTasks # noqa diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/concurrency.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/concurrency.py new file mode 100644 index 0000000..31b878d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/concurrency.py @@ -0,0 +1,40 @@ +from contextlib import AsyncExitStack as AsyncExitStack # noqa +from contextlib import asynccontextmanager as asynccontextmanager +from typing import AsyncGenerator, ContextManager, TypeVar + +import anyio +from anyio import CapacityLimiter +from starlette.concurrency import iterate_in_threadpool as iterate_in_threadpool # noqa +from starlette.concurrency import run_in_threadpool as run_in_threadpool # noqa +from starlette.concurrency import ( # noqa + run_until_first_complete as run_until_first_complete, +) + +_T = TypeVar("_T") + + +@asynccontextmanager +async def contextmanager_in_threadpool( + cm: ContextManager[_T], +) -> AsyncGenerator[_T, None]: + # blocking __exit__ from running waiting on a free thread + # can create race conditions/deadlocks if the context manager itself + # has it's own internal pool (e.g. a database connection pool) + # to avoid this we let __exit__ run without a capacity limit + # since we're creating a new limiter for each call, any non-zero limit + # works (1 is arbitrary) + exit_limiter = CapacityLimiter(1) + try: + yield await run_in_threadpool(cm.__enter__) + except Exception as e: + ok = bool( + await anyio.to_thread.run_sync( + cm.__exit__, type(e), e, None, limiter=exit_limiter + ) + ) + if not ok: + raise e + else: + await anyio.to_thread.run_sync( + cm.__exit__, None, None, None, limiter=exit_limiter + ) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/datastructures.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/datastructures.py new file mode 100644 index 0000000..b20a25a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/datastructures.py @@ -0,0 +1,56 @@ +from typing import Any, Callable, Dict, Iterable, Type, TypeVar + +from starlette.datastructures import URL as URL # noqa: F401 +from starlette.datastructures import Address as Address # noqa: F401 +from starlette.datastructures import FormData as FormData # noqa: F401 +from starlette.datastructures import Headers as Headers # noqa: F401 +from starlette.datastructures import QueryParams as QueryParams # noqa: F401 +from starlette.datastructures import State as State # noqa: F401 +from starlette.datastructures import UploadFile as StarletteUploadFile + + +class UploadFile(StarletteUploadFile): + @classmethod + def __get_validators__(cls: Type["UploadFile"]) -> Iterable[Callable[..., Any]]: + yield cls.validate + + @classmethod + def validate(cls: Type["UploadFile"], v: Any) -> Any: + if not isinstance(v, StarletteUploadFile): + raise ValueError(f"Expected UploadFile, received: {type(v)}") + return v + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update({"type": "string", "format": "binary"}) + + +class DefaultPlaceholder: + """ + You shouldn't use this class directly. + + It's used internally to recognize when a default value has been overwritten, even + if the overridden default value was truthy. + """ + + def __init__(self, value: Any): + self.value = value + + def __bool__(self) -> bool: + return bool(self.value) + + def __eq__(self, o: object) -> bool: + return isinstance(o, DefaultPlaceholder) and o.value == self.value + + +DefaultType = TypeVar("DefaultType") + + +def Default(value: DefaultType) -> DefaultType: + """ + You shouldn't use this function directly. + + It's used internally to recognize when a default value has been overwritten, even + if the overridden default value was truthy. + """ + return DefaultPlaceholder(value) # type: ignore diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/dependencies/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/dependencies/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/dependencies/models.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/dependencies/models.py new file mode 100644 index 0000000..443590b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/dependencies/models.py @@ -0,0 +1,58 @@ +from typing import Any, Callable, List, Optional, Sequence + +from fastapi.security.base import SecurityBase +from pydantic.fields import ModelField + + +class SecurityRequirement: + def __init__( + self, security_scheme: SecurityBase, scopes: Optional[Sequence[str]] = None + ): + self.security_scheme = security_scheme + self.scopes = scopes + + +class Dependant: + def __init__( + self, + *, + path_params: Optional[List[ModelField]] = None, + query_params: Optional[List[ModelField]] = None, + header_params: Optional[List[ModelField]] = None, + cookie_params: Optional[List[ModelField]] = None, + body_params: Optional[List[ModelField]] = None, + dependencies: Optional[List["Dependant"]] = None, + security_schemes: Optional[List[SecurityRequirement]] = None, + name: Optional[str] = None, + call: Optional[Callable[..., Any]] = None, + request_param_name: Optional[str] = None, + websocket_param_name: Optional[str] = None, + http_connection_param_name: Optional[str] = None, + response_param_name: Optional[str] = None, + background_tasks_param_name: Optional[str] = None, + security_scopes_param_name: Optional[str] = None, + security_scopes: Optional[List[str]] = None, + use_cache: bool = True, + path: Optional[str] = None, + ) -> None: + self.path_params = path_params or [] + self.query_params = query_params or [] + self.header_params = header_params or [] + self.cookie_params = cookie_params or [] + self.body_params = body_params or [] + self.dependencies = dependencies or [] + self.security_requirements = security_schemes or [] + self.request_param_name = request_param_name + self.websocket_param_name = websocket_param_name + self.http_connection_param_name = http_connection_param_name + self.response_param_name = response_param_name + self.background_tasks_param_name = background_tasks_param_name + self.security_scopes = security_scopes + self.security_scopes_param_name = security_scopes_param_name + self.name = name + self.call = call + self.use_cache = use_cache + # Store the path to be able to re-generate a dependable from it in overrides + self.path = path + # Save the cache key at creation to optimize performance + self.cache_key = (self.call, tuple(sorted(set(self.security_scopes or [])))) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/dependencies/utils.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/dependencies/utils.py new file mode 100644 index 0000000..f131001 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/dependencies/utils.py @@ -0,0 +1,846 @@ +import dataclasses +import inspect +from contextlib import contextmanager +from copy import copy, deepcopy +from typing import ( + Any, + Callable, + Coroutine, + Dict, + ForwardRef, + List, + Mapping, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) + +import anyio +from fastapi import params +from fastapi.concurrency import ( + AsyncExitStack, + asynccontextmanager, + contextmanager_in_threadpool, +) +from fastapi.dependencies.models import Dependant, SecurityRequirement +from fastapi.logger import logger +from fastapi.security.base import SecurityBase +from fastapi.security.oauth2 import OAuth2, SecurityScopes +from fastapi.security.open_id_connect_url import OpenIdConnect +from fastapi.utils import create_response_field, get_path_param_names +from pydantic import BaseModel, create_model +from pydantic.error_wrappers import ErrorWrapper +from pydantic.errors import MissingError +from pydantic.fields import ( + SHAPE_FROZENSET, + SHAPE_LIST, + SHAPE_SEQUENCE, + SHAPE_SET, + SHAPE_SINGLETON, + SHAPE_TUPLE, + SHAPE_TUPLE_ELLIPSIS, + FieldInfo, + ModelField, + Required, + Undefined, +) +from pydantic.schema import get_annotation_from_field_info +from pydantic.typing import evaluate_forwardref, get_args, get_origin +from pydantic.utils import lenient_issubclass +from starlette.background import BackgroundTasks +from starlette.concurrency import run_in_threadpool +from starlette.datastructures import FormData, Headers, QueryParams, UploadFile +from starlette.requests import HTTPConnection, Request +from starlette.responses import Response +from starlette.websockets import WebSocket +from typing_extensions import Annotated + +sequence_shapes = { + SHAPE_LIST, + SHAPE_SET, + SHAPE_FROZENSET, + SHAPE_TUPLE, + SHAPE_SEQUENCE, + SHAPE_TUPLE_ELLIPSIS, +} +sequence_types = (list, set, tuple) +sequence_shape_to_type = { + SHAPE_LIST: list, + SHAPE_SET: set, + SHAPE_TUPLE: tuple, + SHAPE_SEQUENCE: list, + SHAPE_TUPLE_ELLIPSIS: list, +} + + +multipart_not_installed_error = ( + 'Form data requires "python-multipart" to be installed. \n' + 'You can install "python-multipart" with: \n\n' + "pip install python-multipart\n" +) +multipart_incorrect_install_error = ( + 'Form data requires "python-multipart" to be installed. ' + 'It seems you installed "multipart" instead. \n' + 'You can remove "multipart" with: \n\n' + "pip uninstall multipart\n\n" + 'And then install "python-multipart" with: \n\n' + "pip install python-multipart\n" +) + + +def check_file_field(field: ModelField) -> None: + field_info = field.field_info + if isinstance(field_info, params.Form): + try: + # __version__ is available in both multiparts, and can be mocked + from multipart import __version__ # type: ignore + + assert __version__ + try: + # parse_options_header is only available in the right multipart + from multipart.multipart import parse_options_header # type: ignore + + assert parse_options_header + except ImportError: + logger.error(multipart_incorrect_install_error) + raise RuntimeError(multipart_incorrect_install_error) from None + except ImportError: + logger.error(multipart_not_installed_error) + raise RuntimeError(multipart_not_installed_error) from None + + +def get_param_sub_dependant( + *, + param_name: str, + depends: params.Depends, + path: str, + security_scopes: Optional[List[str]] = None, +) -> Dependant: + assert depends.dependency + return get_sub_dependant( + depends=depends, + dependency=depends.dependency, + path=path, + name=param_name, + security_scopes=security_scopes, + ) + + +def get_parameterless_sub_dependant(*, depends: params.Depends, path: str) -> Dependant: + assert callable( + depends.dependency + ), "A parameter-less dependency must have a callable dependency" + return get_sub_dependant(depends=depends, dependency=depends.dependency, path=path) + + +def get_sub_dependant( + *, + depends: params.Depends, + dependency: Callable[..., Any], + path: str, + name: Optional[str] = None, + security_scopes: Optional[List[str]] = None, +) -> Dependant: + security_requirement = None + security_scopes = security_scopes or [] + if isinstance(depends, params.Security): + dependency_scopes = depends.scopes + security_scopes.extend(dependency_scopes) + if isinstance(dependency, SecurityBase): + use_scopes: List[str] = [] + if isinstance(dependency, (OAuth2, OpenIdConnect)): + use_scopes = security_scopes + security_requirement = SecurityRequirement( + security_scheme=dependency, scopes=use_scopes + ) + sub_dependant = get_dependant( + path=path, + call=dependency, + name=name, + security_scopes=security_scopes, + use_cache=depends.use_cache, + ) + if security_requirement: + sub_dependant.security_requirements.append(security_requirement) + return sub_dependant + + +CacheKey = Tuple[Optional[Callable[..., Any]], Tuple[str, ...]] + + +def get_flat_dependant( + dependant: Dependant, + *, + skip_repeats: bool = False, + visited: Optional[List[CacheKey]] = None, +) -> Dependant: + if visited is None: + visited = [] + visited.append(dependant.cache_key) + + flat_dependant = Dependant( + path_params=dependant.path_params.copy(), + query_params=dependant.query_params.copy(), + header_params=dependant.header_params.copy(), + cookie_params=dependant.cookie_params.copy(), + body_params=dependant.body_params.copy(), + security_schemes=dependant.security_requirements.copy(), + use_cache=dependant.use_cache, + path=dependant.path, + ) + for sub_dependant in dependant.dependencies: + if skip_repeats and sub_dependant.cache_key in visited: + continue + flat_sub = get_flat_dependant( + sub_dependant, skip_repeats=skip_repeats, visited=visited + ) + flat_dependant.path_params.extend(flat_sub.path_params) + flat_dependant.query_params.extend(flat_sub.query_params) + flat_dependant.header_params.extend(flat_sub.header_params) + flat_dependant.cookie_params.extend(flat_sub.cookie_params) + flat_dependant.body_params.extend(flat_sub.body_params) + flat_dependant.security_requirements.extend(flat_sub.security_requirements) + return flat_dependant + + +def get_flat_params(dependant: Dependant) -> List[ModelField]: + flat_dependant = get_flat_dependant(dependant, skip_repeats=True) + return ( + flat_dependant.path_params + + flat_dependant.query_params + + flat_dependant.header_params + + flat_dependant.cookie_params + ) + + +def is_scalar_field(field: ModelField) -> bool: + field_info = field.field_info + if not ( + field.shape == SHAPE_SINGLETON + and not lenient_issubclass(field.type_, BaseModel) + and not lenient_issubclass(field.type_, sequence_types + (dict,)) + and not dataclasses.is_dataclass(field.type_) + and not isinstance(field_info, params.Body) + ): + return False + if field.sub_fields: + if not all(is_scalar_field(f) for f in field.sub_fields): + return False + return True + + +def is_scalar_sequence_field(field: ModelField) -> bool: + if (field.shape in sequence_shapes) and not lenient_issubclass( + field.type_, BaseModel + ): + if field.sub_fields is not None: + for sub_field in field.sub_fields: + if not is_scalar_field(sub_field): + return False + return True + if lenient_issubclass(field.type_, sequence_types): + return True + return False + + +def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature: + signature = inspect.signature(call) + globalns = getattr(call, "__globals__", {}) + typed_params = [ + inspect.Parameter( + name=param.name, + kind=param.kind, + default=param.default, + annotation=get_typed_annotation(param.annotation, globalns), + ) + for param in signature.parameters.values() + ] + typed_signature = inspect.Signature(typed_params) + return typed_signature + + +def get_typed_annotation(annotation: Any, globalns: Dict[str, Any]) -> Any: + if isinstance(annotation, str): + annotation = ForwardRef(annotation) + annotation = evaluate_forwardref(annotation, globalns, globalns) + return annotation + + +def get_typed_return_annotation(call: Callable[..., Any]) -> Any: + signature = inspect.signature(call) + annotation = signature.return_annotation + + if annotation is inspect.Signature.empty: + return None + + globalns = getattr(call, "__globals__", {}) + return get_typed_annotation(annotation, globalns) + + +def get_dependant( + *, + path: str, + call: Callable[..., Any], + name: Optional[str] = None, + security_scopes: Optional[List[str]] = None, + use_cache: bool = True, +) -> Dependant: + path_param_names = get_path_param_names(path) + endpoint_signature = get_typed_signature(call) + signature_params = endpoint_signature.parameters + dependant = Dependant( + call=call, + name=name, + path=path, + security_scopes=security_scopes, + use_cache=use_cache, + ) + for param_name, param in signature_params.items(): + is_path_param = param_name in path_param_names + type_annotation, depends, param_field = analyze_param( + param_name=param_name, + annotation=param.annotation, + value=param.default, + is_path_param=is_path_param, + ) + if depends is not None: + sub_dependant = get_param_sub_dependant( + param_name=param_name, + depends=depends, + path=path, + security_scopes=security_scopes, + ) + dependant.dependencies.append(sub_dependant) + continue + if add_non_field_param_to_dependency( + param_name=param_name, + type_annotation=type_annotation, + dependant=dependant, + ): + assert ( + param_field is None + ), f"Cannot specify multiple FastAPI annotations for {param_name!r}" + continue + assert param_field is not None + if is_body_param(param_field=param_field, is_path_param=is_path_param): + dependant.body_params.append(param_field) + else: + add_param_to_fields(field=param_field, dependant=dependant) + return dependant + + +def add_non_field_param_to_dependency( + *, param_name: str, type_annotation: Any, dependant: Dependant +) -> Optional[bool]: + if lenient_issubclass(type_annotation, Request): + dependant.request_param_name = param_name + return True + elif lenient_issubclass(type_annotation, WebSocket): + dependant.websocket_param_name = param_name + return True + elif lenient_issubclass(type_annotation, HTTPConnection): + dependant.http_connection_param_name = param_name + return True + elif lenient_issubclass(type_annotation, Response): + dependant.response_param_name = param_name + return True + elif lenient_issubclass(type_annotation, BackgroundTasks): + dependant.background_tasks_param_name = param_name + return True + elif lenient_issubclass(type_annotation, SecurityScopes): + dependant.security_scopes_param_name = param_name + return True + return None + + +def analyze_param( + *, + param_name: str, + annotation: Any, + value: Any, + is_path_param: bool, +) -> Tuple[Any, Optional[params.Depends], Optional[ModelField]]: + field_info = None + used_default_field_info = False + depends = None + type_annotation: Any = Any + if ( + annotation is not inspect.Signature.empty + and get_origin(annotation) is Annotated # type: ignore[comparison-overlap] + ): + annotated_args = get_args(annotation) + type_annotation = annotated_args[0] + fastapi_annotations = [ + arg + for arg in annotated_args[1:] + if isinstance(arg, (FieldInfo, params.Depends)) + ] + assert ( + len(fastapi_annotations) <= 1 + ), f"Cannot specify multiple `Annotated` FastAPI arguments for {param_name!r}" + fastapi_annotation = next(iter(fastapi_annotations), None) + if isinstance(fastapi_annotation, FieldInfo): + # Copy `field_info` because we mutate `field_info.default` below. + field_info = copy(fastapi_annotation) + assert field_info.default is Undefined or field_info.default is Required, ( + f"`{field_info.__class__.__name__}` default value cannot be set in" + f" `Annotated` for {param_name!r}. Set the default value with `=` instead." + ) + if value is not inspect.Signature.empty: + assert not is_path_param, "Path parameters cannot have default values" + field_info.default = value + else: + field_info.default = Required + elif isinstance(fastapi_annotation, params.Depends): + depends = fastapi_annotation + elif annotation is not inspect.Signature.empty: + type_annotation = annotation + + if isinstance(value, params.Depends): + assert depends is None, ( + "Cannot specify `Depends` in `Annotated` and default value" + f" together for {param_name!r}" + ) + assert field_info is None, ( + "Cannot specify a FastAPI annotation in `Annotated` and `Depends` as a" + f" default value together for {param_name!r}" + ) + depends = value + elif isinstance(value, FieldInfo): + assert field_info is None, ( + "Cannot specify FastAPI annotations in `Annotated` and default value" + f" together for {param_name!r}" + ) + field_info = value + + if depends is not None and depends.dependency is None: + depends.dependency = type_annotation + + if lenient_issubclass( + type_annotation, + (Request, WebSocket, HTTPConnection, Response, BackgroundTasks, SecurityScopes), + ): + assert depends is None, f"Cannot specify `Depends` for type {type_annotation!r}" + assert ( + field_info is None + ), f"Cannot specify FastAPI annotation for type {type_annotation!r}" + elif field_info is None and depends is None: + default_value = value if value is not inspect.Signature.empty else Required + if is_path_param: + # We might check here that `default_value is Required`, but the fact is that the same + # parameter might sometimes be a path parameter and sometimes not. See + # `tests/test_infer_param_optionality.py` for an example. + field_info = params.Path() + else: + field_info = params.Query(default=default_value) + used_default_field_info = True + + field = None + if field_info is not None: + if is_path_param: + assert isinstance(field_info, params.Path), ( + f"Cannot use `{field_info.__class__.__name__}` for path param" + f" {param_name!r}" + ) + elif ( + isinstance(field_info, params.Param) + and getattr(field_info, "in_", None) is None + ): + field_info.in_ = params.ParamTypes.query + annotation = get_annotation_from_field_info( + annotation if annotation is not inspect.Signature.empty else Any, + field_info, + param_name, + ) + if not field_info.alias and getattr(field_info, "convert_underscores", None): + alias = param_name.replace("_", "-") + else: + alias = field_info.alias or param_name + field = create_response_field( + name=param_name, + type_=annotation, + default=field_info.default, + alias=alias, + required=field_info.default in (Required, Undefined), + field_info=field_info, + ) + if used_default_field_info: + if lenient_issubclass(field.type_, UploadFile): + field.field_info = params.File(field_info.default) + elif not is_scalar_field(field=field): + field.field_info = params.Body(field_info.default) + + return type_annotation, depends, field + + +def is_body_param(*, param_field: ModelField, is_path_param: bool) -> bool: + if is_path_param: + assert is_scalar_field( + field=param_field + ), "Path params must be of one of the supported types" + return False + elif is_scalar_field(field=param_field): + return False + elif isinstance( + param_field.field_info, (params.Query, params.Header) + ) and is_scalar_sequence_field(param_field): + return False + else: + assert isinstance( + param_field.field_info, params.Body + ), f"Param: {param_field.name} can only be a request body, using Body()" + return True + + +def add_param_to_fields(*, field: ModelField, dependant: Dependant) -> None: + field_info = cast(params.Param, field.field_info) + if field_info.in_ == params.ParamTypes.path: + dependant.path_params.append(field) + elif field_info.in_ == params.ParamTypes.query: + dependant.query_params.append(field) + elif field_info.in_ == params.ParamTypes.header: + dependant.header_params.append(field) + else: + assert ( + field_info.in_ == params.ParamTypes.cookie + ), f"non-body parameters must be in path, query, header or cookie: {field.name}" + dependant.cookie_params.append(field) + + +def is_coroutine_callable(call: Callable[..., Any]) -> bool: + if inspect.isroutine(call): + return inspect.iscoroutinefunction(call) + if inspect.isclass(call): + return False + dunder_call = getattr(call, "__call__", None) # noqa: B004 + return inspect.iscoroutinefunction(dunder_call) + + +def is_async_gen_callable(call: Callable[..., Any]) -> bool: + if inspect.isasyncgenfunction(call): + return True + dunder_call = getattr(call, "__call__", None) # noqa: B004 + return inspect.isasyncgenfunction(dunder_call) + + +def is_gen_callable(call: Callable[..., Any]) -> bool: + if inspect.isgeneratorfunction(call): + return True + dunder_call = getattr(call, "__call__", None) # noqa: B004 + return inspect.isgeneratorfunction(dunder_call) + + +async def solve_generator( + *, call: Callable[..., Any], stack: AsyncExitStack, sub_values: Dict[str, Any] +) -> Any: + if is_gen_callable(call): + cm = contextmanager_in_threadpool(contextmanager(call)(**sub_values)) + elif is_async_gen_callable(call): + cm = asynccontextmanager(call)(**sub_values) + return await stack.enter_async_context(cm) + + +async def solve_dependencies( + *, + request: Union[Request, WebSocket], + dependant: Dependant, + body: Optional[Union[Dict[str, Any], FormData]] = None, + background_tasks: Optional[BackgroundTasks] = None, + response: Optional[Response] = None, + dependency_overrides_provider: Optional[Any] = None, + dependency_cache: Optional[Dict[Tuple[Callable[..., Any], Tuple[str]], Any]] = None, +) -> Tuple[ + Dict[str, Any], + List[ErrorWrapper], + Optional[BackgroundTasks], + Response, + Dict[Tuple[Callable[..., Any], Tuple[str]], Any], +]: + values: Dict[str, Any] = {} + errors: List[ErrorWrapper] = [] + if response is None: + response = Response() + del response.headers["content-length"] + response.status_code = None # type: ignore + dependency_cache = dependency_cache or {} + sub_dependant: Dependant + for sub_dependant in dependant.dependencies: + sub_dependant.call = cast(Callable[..., Any], sub_dependant.call) + sub_dependant.cache_key = cast( + Tuple[Callable[..., Any], Tuple[str]], sub_dependant.cache_key + ) + call = sub_dependant.call + use_sub_dependant = sub_dependant + if ( + dependency_overrides_provider + and dependency_overrides_provider.dependency_overrides + ): + original_call = sub_dependant.call + call = getattr( + dependency_overrides_provider, "dependency_overrides", {} + ).get(original_call, original_call) + use_path: str = sub_dependant.path # type: ignore + use_sub_dependant = get_dependant( + path=use_path, + call=call, + name=sub_dependant.name, + security_scopes=sub_dependant.security_scopes, + ) + + solved_result = await solve_dependencies( + request=request, + dependant=use_sub_dependant, + body=body, + background_tasks=background_tasks, + response=response, + dependency_overrides_provider=dependency_overrides_provider, + dependency_cache=dependency_cache, + ) + ( + sub_values, + sub_errors, + background_tasks, + _, # the subdependency returns the same response we have + sub_dependency_cache, + ) = solved_result + dependency_cache.update(sub_dependency_cache) + if sub_errors: + errors.extend(sub_errors) + continue + if sub_dependant.use_cache and sub_dependant.cache_key in dependency_cache: + solved = dependency_cache[sub_dependant.cache_key] + elif is_gen_callable(call) or is_async_gen_callable(call): + stack = request.scope.get("fastapi_astack") + assert isinstance(stack, AsyncExitStack) + solved = await solve_generator( + call=call, stack=stack, sub_values=sub_values + ) + elif is_coroutine_callable(call): + solved = await call(**sub_values) + else: + solved = await run_in_threadpool(call, **sub_values) + if sub_dependant.name is not None: + values[sub_dependant.name] = solved + if sub_dependant.cache_key not in dependency_cache: + dependency_cache[sub_dependant.cache_key] = solved + path_values, path_errors = request_params_to_args( + dependant.path_params, request.path_params + ) + query_values, query_errors = request_params_to_args( + dependant.query_params, request.query_params + ) + header_values, header_errors = request_params_to_args( + dependant.header_params, request.headers + ) + cookie_values, cookie_errors = request_params_to_args( + dependant.cookie_params, request.cookies + ) + values.update(path_values) + values.update(query_values) + values.update(header_values) + values.update(cookie_values) + errors += path_errors + query_errors + header_errors + cookie_errors + if dependant.body_params: + ( + body_values, + body_errors, + ) = await request_body_to_args( # body_params checked above + required_params=dependant.body_params, received_body=body + ) + values.update(body_values) + errors.extend(body_errors) + if dependant.http_connection_param_name: + values[dependant.http_connection_param_name] = request + if dependant.request_param_name and isinstance(request, Request): + values[dependant.request_param_name] = request + elif dependant.websocket_param_name and isinstance(request, WebSocket): + values[dependant.websocket_param_name] = request + if dependant.background_tasks_param_name: + if background_tasks is None: + background_tasks = BackgroundTasks() + values[dependant.background_tasks_param_name] = background_tasks + if dependant.response_param_name: + values[dependant.response_param_name] = response + if dependant.security_scopes_param_name: + values[dependant.security_scopes_param_name] = SecurityScopes( + scopes=dependant.security_scopes + ) + return values, errors, background_tasks, response, dependency_cache + + +def request_params_to_args( + required_params: Sequence[ModelField], + received_params: Union[Mapping[str, Any], QueryParams, Headers], +) -> Tuple[Dict[str, Any], List[ErrorWrapper]]: + values = {} + errors = [] + for field in required_params: + if is_scalar_sequence_field(field) and isinstance( + received_params, (QueryParams, Headers) + ): + value = received_params.getlist(field.alias) or field.default + else: + value = received_params.get(field.alias) + field_info = field.field_info + assert isinstance( + field_info, params.Param + ), "Params must be subclasses of Param" + if value is None: + if field.required: + errors.append( + ErrorWrapper( + MissingError(), loc=(field_info.in_.value, field.alias) + ) + ) + else: + values[field.name] = deepcopy(field.default) + continue + v_, errors_ = field.validate( + value, values, loc=(field_info.in_.value, field.alias) + ) + if isinstance(errors_, ErrorWrapper): + errors.append(errors_) + elif isinstance(errors_, list): + errors.extend(errors_) + else: + values[field.name] = v_ + return values, errors + + +async def request_body_to_args( + required_params: List[ModelField], + received_body: Optional[Union[Dict[str, Any], FormData]], +) -> Tuple[Dict[str, Any], List[ErrorWrapper]]: + values = {} + errors = [] + if required_params: + field = required_params[0] + field_info = field.field_info + embed = getattr(field_info, "embed", None) + field_alias_omitted = len(required_params) == 1 and not embed + if field_alias_omitted: + received_body = {field.alias: received_body} + + for field in required_params: + loc: Tuple[str, ...] + if field_alias_omitted: + loc = ("body",) + else: + loc = ("body", field.alias) + + value: Optional[Any] = None + if received_body is not None: + if ( + field.shape in sequence_shapes or field.type_ in sequence_types + ) and isinstance(received_body, FormData): + value = received_body.getlist(field.alias) + else: + try: + value = received_body.get(field.alias) + except AttributeError: + errors.append(get_missing_field_error(loc)) + continue + if ( + value is None + or (isinstance(field_info, params.Form) and value == "") + or ( + isinstance(field_info, params.Form) + and field.shape in sequence_shapes + and len(value) == 0 + ) + ): + if field.required: + errors.append(get_missing_field_error(loc)) + else: + values[field.name] = deepcopy(field.default) + continue + if ( + isinstance(field_info, params.File) + and lenient_issubclass(field.type_, bytes) + and isinstance(value, UploadFile) + ): + value = await value.read() + elif ( + field.shape in sequence_shapes + and isinstance(field_info, params.File) + and lenient_issubclass(field.type_, bytes) + and isinstance(value, sequence_types) + ): + results: List[Union[bytes, str]] = [] + + async def process_fn( + fn: Callable[[], Coroutine[Any, Any, Any]] + ) -> None: + result = await fn() + results.append(result) # noqa: B023 + + async with anyio.create_task_group() as tg: + for sub_value in value: + tg.start_soon(process_fn, sub_value.read) + value = sequence_shape_to_type[field.shape](results) + + v_, errors_ = field.validate(value, values, loc=loc) + + if isinstance(errors_, ErrorWrapper): + errors.append(errors_) + elif isinstance(errors_, list): + errors.extend(errors_) + else: + values[field.name] = v_ + return values, errors + + +def get_missing_field_error(loc: Tuple[str, ...]) -> ErrorWrapper: + missing_field_error = ErrorWrapper(MissingError(), loc=loc) + return missing_field_error + + +def get_body_field(*, dependant: Dependant, name: str) -> Optional[ModelField]: + flat_dependant = get_flat_dependant(dependant) + if not flat_dependant.body_params: + return None + first_param = flat_dependant.body_params[0] + field_info = first_param.field_info + embed = getattr(field_info, "embed", None) + body_param_names_set = {param.name for param in flat_dependant.body_params} + if len(body_param_names_set) == 1 and not embed: + check_file_field(first_param) + return first_param + # If one field requires to embed, all have to be embedded + # in case a sub-dependency is evaluated with a single unique body field + # That is combined (embedded) with other body fields + for param in flat_dependant.body_params: + setattr(param.field_info, "embed", True) # noqa: B010 + model_name = "Body_" + name + BodyModel: Type[BaseModel] = create_model(model_name) + for f in flat_dependant.body_params: + BodyModel.__fields__[f.name] = f + required = any(True for f in flat_dependant.body_params if f.required) + + BodyFieldInfo_kwargs: Dict[str, Any] = {"default": None} + if any(isinstance(f.field_info, params.File) for f in flat_dependant.body_params): + BodyFieldInfo: Type[params.Body] = params.File + elif any(isinstance(f.field_info, params.Form) for f in flat_dependant.body_params): + BodyFieldInfo = params.Form + else: + BodyFieldInfo = params.Body + + body_param_media_types = [ + f.field_info.media_type + for f in flat_dependant.body_params + if isinstance(f.field_info, params.Body) + ] + if len(set(body_param_media_types)) == 1: + BodyFieldInfo_kwargs["media_type"] = body_param_media_types[0] + final_field = create_response_field( + name="body", + type_=BodyModel, + required=required, + alias="body", + field_info=BodyFieldInfo(**BodyFieldInfo_kwargs), + ) + check_file_field(final_field) + return final_field diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/encoders.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/encoders.py new file mode 100644 index 0000000..94f41bf --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/encoders.py @@ -0,0 +1,171 @@ +import dataclasses +from collections import defaultdict, deque +from enum import Enum +from pathlib import PurePath +from types import GeneratorType +from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union + +from pydantic import BaseModel +from pydantic.json import ENCODERS_BY_TYPE + +SetIntStr = Set[Union[int, str]] +DictIntStrAny = Dict[Union[int, str], Any] + + +def generate_encoders_by_class_tuples( + type_encoder_map: Dict[Any, Callable[[Any], Any]] +) -> Dict[Callable[[Any], Any], Tuple[Any, ...]]: + encoders_by_class_tuples: Dict[Callable[[Any], Any], Tuple[Any, ...]] = defaultdict( + tuple + ) + for type_, encoder in type_encoder_map.items(): + encoders_by_class_tuples[encoder] += (type_,) + return encoders_by_class_tuples + + +encoders_by_class_tuples = generate_encoders_by_class_tuples(ENCODERS_BY_TYPE) + + +def jsonable_encoder( + obj: Any, + include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + by_alias: bool = True, + exclude_unset: bool = False, + exclude_defaults: bool = False, + exclude_none: bool = False, + custom_encoder: Optional[Dict[Any, Callable[[Any], Any]]] = None, + sqlalchemy_safe: bool = True, +) -> Any: + custom_encoder = custom_encoder or {} + if custom_encoder: + if type(obj) in custom_encoder: + return custom_encoder[type(obj)](obj) + else: + for encoder_type, encoder_instance in custom_encoder.items(): + if isinstance(obj, encoder_type): + return encoder_instance(obj) + if include is not None and not isinstance(include, (set, dict)): + include = set(include) + if exclude is not None and not isinstance(exclude, (set, dict)): + exclude = set(exclude) + if isinstance(obj, BaseModel): + encoder = getattr(obj.__config__, "json_encoders", {}) + if custom_encoder: + encoder.update(custom_encoder) + obj_dict = obj.dict( + include=include, + exclude=exclude, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_none=exclude_none, + exclude_defaults=exclude_defaults, + ) + if "__root__" in obj_dict: + obj_dict = obj_dict["__root__"] + return jsonable_encoder( + obj_dict, + exclude_none=exclude_none, + exclude_defaults=exclude_defaults, + custom_encoder=encoder, + sqlalchemy_safe=sqlalchemy_safe, + ) + if dataclasses.is_dataclass(obj): + obj_dict = dataclasses.asdict(obj) + return jsonable_encoder( + obj_dict, + include=include, + exclude=exclude, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + custom_encoder=custom_encoder, + sqlalchemy_safe=sqlalchemy_safe, + ) + if isinstance(obj, Enum): + return obj.value + if isinstance(obj, PurePath): + return str(obj) + if isinstance(obj, (str, int, float, type(None))): + return obj + if isinstance(obj, dict): + encoded_dict = {} + allowed_keys = set(obj.keys()) + if include is not None: + allowed_keys &= set(include) + if exclude is not None: + allowed_keys -= set(exclude) + for key, value in obj.items(): + if ( + ( + not sqlalchemy_safe + or (not isinstance(key, str)) + or (not key.startswith("_sa")) + ) + and (value is not None or not exclude_none) + and key in allowed_keys + ): + encoded_key = jsonable_encoder( + key, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_none=exclude_none, + custom_encoder=custom_encoder, + sqlalchemy_safe=sqlalchemy_safe, + ) + encoded_value = jsonable_encoder( + value, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_none=exclude_none, + custom_encoder=custom_encoder, + sqlalchemy_safe=sqlalchemy_safe, + ) + encoded_dict[encoded_key] = encoded_value + return encoded_dict + if isinstance(obj, (list, set, frozenset, GeneratorType, tuple, deque)): + encoded_list = [] + for item in obj: + encoded_list.append( + jsonable_encoder( + item, + include=include, + exclude=exclude, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + custom_encoder=custom_encoder, + sqlalchemy_safe=sqlalchemy_safe, + ) + ) + return encoded_list + + if type(obj) in ENCODERS_BY_TYPE: + return ENCODERS_BY_TYPE[type(obj)](obj) + for encoder, classes_tuple in encoders_by_class_tuples.items(): + if isinstance(obj, classes_tuple): + return encoder(obj) + + try: + data = dict(obj) + except Exception as e: + errors: List[Exception] = [] + errors.append(e) + try: + data = vars(obj) + except Exception as e: + errors.append(e) + raise ValueError(errors) from e + return jsonable_encoder( + data, + include=include, + exclude=exclude, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + custom_encoder=custom_encoder, + sqlalchemy_safe=sqlalchemy_safe, + ) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/exception_handlers.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/exception_handlers.py new file mode 100644 index 0000000..6c2ba7f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/exception_handlers.py @@ -0,0 +1,34 @@ +from fastapi.encoders import jsonable_encoder +from fastapi.exceptions import RequestValidationError, WebSocketRequestValidationError +from fastapi.utils import is_body_allowed_for_status_code +from fastapi.websockets import WebSocket +from starlette.exceptions import HTTPException +from starlette.requests import Request +from starlette.responses import JSONResponse, Response +from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY, WS_1008_POLICY_VIOLATION + + +async def http_exception_handler(request: Request, exc: HTTPException) -> Response: + headers = getattr(exc, "headers", None) + if not is_body_allowed_for_status_code(exc.status_code): + return Response(status_code=exc.status_code, headers=headers) + return JSONResponse( + {"detail": exc.detail}, status_code=exc.status_code, headers=headers + ) + + +async def request_validation_exception_handler( + request: Request, exc: RequestValidationError +) -> JSONResponse: + return JSONResponse( + status_code=HTTP_422_UNPROCESSABLE_ENTITY, + content={"detail": jsonable_encoder(exc.errors())}, + ) + + +async def websocket_request_validation_exception_handler( + websocket: WebSocket, exc: WebSocketRequestValidationError +) -> None: + await websocket.close( + code=WS_1008_POLICY_VIOLATION, reason=jsonable_encoder(exc.errors()) + ) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/exceptions.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/exceptions.py new file mode 100644 index 0000000..cac5330 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/exceptions.py @@ -0,0 +1,37 @@ +from typing import Any, Dict, Optional, Sequence, Type + +from pydantic import BaseModel, ValidationError, create_model +from pydantic.error_wrappers import ErrorList +from starlette.exceptions import HTTPException as StarletteHTTPException +from starlette.exceptions import WebSocketException as WebSocketException # noqa: F401 + + +class HTTPException(StarletteHTTPException): + def __init__( + self, + status_code: int, + detail: Any = None, + headers: Optional[Dict[str, str]] = None, + ) -> None: + super().__init__(status_code=status_code, detail=detail, headers=headers) + + +RequestErrorModel: Type[BaseModel] = create_model("Request") +WebSocketErrorModel: Type[BaseModel] = create_model("WebSocket") + + +class FastAPIError(RuntimeError): + """ + A generic, FastAPI-specific error. + """ + + +class RequestValidationError(ValidationError): + def __init__(self, errors: Sequence[ErrorList], *, body: Any = None) -> None: + self.body = body + super().__init__(errors, RequestErrorModel) + + +class WebSocketRequestValidationError(ValidationError): + def __init__(self, errors: Sequence[ErrorList]) -> None: + super().__init__(errors, WebSocketErrorModel) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/logger.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/logger.py new file mode 100644 index 0000000..5b2c4ad --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/logger.py @@ -0,0 +1,3 @@ +import logging + +logger = logging.getLogger("fastapi") diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/middleware/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/middleware/__init__.py new file mode 100644 index 0000000..620296d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/middleware/__init__.py @@ -0,0 +1 @@ +from starlette.middleware import Middleware as Middleware diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/middleware/asyncexitstack.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/middleware/asyncexitstack.py new file mode 100644 index 0000000..30a0ae6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/middleware/asyncexitstack.py @@ -0,0 +1,25 @@ +from typing import Optional + +from fastapi.concurrency import AsyncExitStack +from starlette.types import ASGIApp, Receive, Scope, Send + + +class AsyncExitStackMiddleware: + def __init__(self, app: ASGIApp, context_name: str = "fastapi_astack") -> None: + self.app = app + self.context_name = context_name + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + dependency_exception: Optional[Exception] = None + async with AsyncExitStack() as stack: + scope[self.context_name] = stack + try: + await self.app(scope, receive, send) + except Exception as e: + dependency_exception = e + raise e + if dependency_exception: + # This exception was possibly handled by the dependency but it should + # still bubble up so that the ServerErrorMiddleware can return a 500 + # or the ExceptionMiddleware can catch and handle any other exceptions + raise dependency_exception diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/middleware/cors.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/middleware/cors.py new file mode 100644 index 0000000..8dfaad0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/middleware/cors.py @@ -0,0 +1 @@ +from starlette.middleware.cors import CORSMiddleware as CORSMiddleware # noqa diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/middleware/gzip.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/middleware/gzip.py new file mode 100644 index 0000000..bbeb2cc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/middleware/gzip.py @@ -0,0 +1 @@ +from starlette.middleware.gzip import GZipMiddleware as GZipMiddleware # noqa diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/middleware/httpsredirect.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/middleware/httpsredirect.py new file mode 100644 index 0000000..b7a3d8e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/middleware/httpsredirect.py @@ -0,0 +1,3 @@ +from starlette.middleware.httpsredirect import ( # noqa + HTTPSRedirectMiddleware as HTTPSRedirectMiddleware, +) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/middleware/trustedhost.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/middleware/trustedhost.py new file mode 100644 index 0000000..08d7e03 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/middleware/trustedhost.py @@ -0,0 +1,3 @@ +from starlette.middleware.trustedhost import ( # noqa + TrustedHostMiddleware as TrustedHostMiddleware, +) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/middleware/wsgi.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/middleware/wsgi.py new file mode 100644 index 0000000..c4c6a79 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/middleware/wsgi.py @@ -0,0 +1 @@ +from starlette.middleware.wsgi import WSGIMiddleware as WSGIMiddleware # noqa diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/openapi/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/openapi/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/openapi/constants.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/openapi/constants.py new file mode 100644 index 0000000..1897ad7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/openapi/constants.py @@ -0,0 +1,2 @@ +METHODS_WITH_BODY = {"GET", "HEAD", "POST", "PUT", "DELETE", "PATCH"} +REF_PREFIX = "#/components/schemas/" diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/openapi/docs.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/openapi/docs.py new file mode 100644 index 0000000..81f67dc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/openapi/docs.py @@ -0,0 +1,203 @@ +import json +from typing import Any, Dict, Optional + +from fastapi.encoders import jsonable_encoder +from starlette.responses import HTMLResponse + +swagger_ui_default_parameters = { + "dom_id": "#swagger-ui", + "layout": "BaseLayout", + "deepLinking": True, + "showExtensions": True, + "showCommonExtensions": True, +} + + +def get_swagger_ui_html( + *, + openapi_url: str, + title: str, + swagger_js_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js", + swagger_css_url: str = "https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css", + swagger_favicon_url: str = "https://fastapi.tiangolo.com/img/favicon.png", + oauth2_redirect_url: Optional[str] = None, + init_oauth: Optional[Dict[str, Any]] = None, + swagger_ui_parameters: Optional[Dict[str, Any]] = None, +) -> HTMLResponse: + current_swagger_ui_parameters = swagger_ui_default_parameters.copy() + if swagger_ui_parameters: + current_swagger_ui_parameters.update(swagger_ui_parameters) + + html = f""" + + + + + + {title} + + +
    +
    + + + + + + """ + return HTMLResponse(html) + + +def get_redoc_html( + *, + openapi_url: str, + title: str, + redoc_js_url: str = "https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js", + redoc_favicon_url: str = "https://fastapi.tiangolo.com/img/favicon.png", + with_google_fonts: bool = True, +) -> HTMLResponse: + html = f""" + + + + {title} + + + + """ + if with_google_fonts: + html += """ + + """ + html += f""" + + + + + + + + + + + """ + return HTMLResponse(html) + + +def get_swagger_ui_oauth2_redirect_html() -> HTMLResponse: + # copied from https://github.com/swagger-api/swagger-ui/blob/v4.14.0/dist/oauth2-redirect.html + html = """ + + + + Swagger UI: OAuth2 Redirect + + + + + + """ + return HTMLResponse(content=html) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/openapi/models.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/openapi/models.py new file mode 100644 index 0000000..a2ea536 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/openapi/models.py @@ -0,0 +1,468 @@ +from enum import Enum +from typing import Any, Callable, Dict, Iterable, List, Optional, Set, Union + +from fastapi.logger import logger +from pydantic import AnyUrl, BaseModel, Field +from typing_extensions import Annotated, Literal +from typing_extensions import deprecated as typing_deprecated + +try: + import email_validator # type: ignore + + assert email_validator # make autoflake ignore the unused import + from pydantic import EmailStr +except ImportError: # pragma: no cover + + class EmailStr(str): # type: ignore + @classmethod + def __get_validators__(cls) -> Iterable[Callable[..., Any]]: + yield cls.validate + + @classmethod + def validate(cls, v: Any) -> str: + logger.warning( + "email-validator not installed, email fields will be treated as str.\n" + "To install, run: pip install email-validator" + ) + return str(v) + + +class Contact(BaseModel): + name: Optional[str] = None + url: Optional[AnyUrl] = None + email: Optional[EmailStr] = None + + class Config: + extra = "allow" + + +class License(BaseModel): + name: str + identifier: Optional[str] = None + url: Optional[AnyUrl] = None + + class Config: + extra = "allow" + + +class Info(BaseModel): + title: str + summary: Optional[str] = None + description: Optional[str] = None + termsOfService: Optional[str] = None + contact: Optional[Contact] = None + license: Optional[License] = None + version: str + + class Config: + extra = "allow" + + +class ServerVariable(BaseModel): + enum: Annotated[Optional[List[str]], Field(min_items=1)] = None + default: str + description: Optional[str] = None + + class Config: + extra = "allow" + + +class Server(BaseModel): + url: Union[AnyUrl, str] + description: Optional[str] = None + variables: Optional[Dict[str, ServerVariable]] = None + + class Config: + extra = "allow" + + +class Reference(BaseModel): + ref: str = Field(alias="$ref") + + +class Discriminator(BaseModel): + propertyName: str + mapping: Optional[Dict[str, str]] = None + + +class XML(BaseModel): + name: Optional[str] = None + namespace: Optional[str] = None + prefix: Optional[str] = None + attribute: Optional[bool] = None + wrapped: Optional[bool] = None + + class Config: + extra = "allow" + + +class ExternalDocumentation(BaseModel): + description: Optional[str] = None + url: AnyUrl + + class Config: + extra = "allow" + + +class Schema(BaseModel): + # Ref: JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-core.html#name-the-json-schema-core-vocabu + # Core Vocabulary + schema_: Optional[str] = Field(default=None, alias="$schema") + vocabulary: Optional[str] = Field(default=None, alias="$vocabulary") + id: Optional[str] = Field(default=None, alias="$id") + anchor: Optional[str] = Field(default=None, alias="$anchor") + dynamicAnchor: Optional[str] = Field(default=None, alias="$dynamicAnchor") + ref: Optional[str] = Field(default=None, alias="$ref") + dynamicRef: Optional[str] = Field(default=None, alias="$dynamicRef") + defs: Optional[Dict[str, "SchemaOrBool"]] = Field(default=None, alias="$defs") + comment: Optional[str] = Field(default=None, alias="$comment") + # Ref: JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-core.html#name-a-vocabulary-for-applying-s + # A Vocabulary for Applying Subschemas + allOf: Optional[List["SchemaOrBool"]] = None + anyOf: Optional[List["SchemaOrBool"]] = None + oneOf: Optional[List["SchemaOrBool"]] = None + not_: Optional["SchemaOrBool"] = Field(default=None, alias="not") + if_: Optional["SchemaOrBool"] = Field(default=None, alias="if") + then: Optional["SchemaOrBool"] = None + else_: Optional["SchemaOrBool"] = Field(default=None, alias="else") + dependentSchemas: Optional[Dict[str, "SchemaOrBool"]] = None + prefixItems: Optional[List["SchemaOrBool"]] = None + # TODO: uncomment and remove below when deprecating Pydantic v1 + # It generales a list of schemas for tuples, before prefixItems was available + # items: Optional["SchemaOrBool"] = None + items: Optional[Union["SchemaOrBool", List["SchemaOrBool"]]] = None + contains: Optional["SchemaOrBool"] = None + properties: Optional[Dict[str, "SchemaOrBool"]] = None + patternProperties: Optional[Dict[str, "SchemaOrBool"]] = None + additionalProperties: Optional["SchemaOrBool"] = None + propertyNames: Optional["SchemaOrBool"] = None + unevaluatedItems: Optional["SchemaOrBool"] = None + unevaluatedProperties: Optional["SchemaOrBool"] = None + # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-structural + # A Vocabulary for Structural Validation + type: Optional[str] = None + enum: Optional[List[Any]] = None + const: Optional[Any] = None + multipleOf: Optional[float] = Field(default=None, gt=0) + maximum: Optional[float] = None + exclusiveMaximum: Optional[float] = None + minimum: Optional[float] = None + exclusiveMinimum: Optional[float] = None + maxLength: Optional[int] = Field(default=None, ge=0) + minLength: Optional[int] = Field(default=None, ge=0) + pattern: Optional[str] = None + maxItems: Optional[int] = Field(default=None, ge=0) + minItems: Optional[int] = Field(default=None, ge=0) + uniqueItems: Optional[bool] = None + maxContains: Optional[int] = Field(default=None, ge=0) + minContains: Optional[int] = Field(default=None, ge=0) + maxProperties: Optional[int] = Field(default=None, ge=0) + minProperties: Optional[int] = Field(default=None, ge=0) + required: Optional[List[str]] = None + dependentRequired: Optional[Dict[str, Set[str]]] = None + # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-vocabularies-for-semantic-c + # Vocabularies for Semantic Content With "format" + format: Optional[str] = None + # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-the-conten + # A Vocabulary for the Contents of String-Encoded Data + contentEncoding: Optional[str] = None + contentMediaType: Optional[str] = None + contentSchema: Optional["SchemaOrBool"] = None + # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-basic-meta + # A Vocabulary for Basic Meta-Data Annotations + title: Optional[str] = None + description: Optional[str] = None + default: Optional[Any] = None + deprecated: Optional[bool] = None + readOnly: Optional[bool] = None + writeOnly: Optional[bool] = None + examples: Optional[List[Any]] = None + # Ref: OpenAPI 3.1.0: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#schema-object + # Schema Object + discriminator: Optional[Discriminator] = None + xml: Optional[XML] = None + externalDocs: Optional[ExternalDocumentation] = None + example: Annotated[ + Optional[Any], + typing_deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = None + + class Config: + extra: str = "allow" + + +# Ref: https://json-schema.org/draft/2020-12/json-schema-core.html#name-json-schema-documents +# A JSON Schema MUST be an object or a boolean. +SchemaOrBool = Union[Schema, bool] + + +class Example(BaseModel): + summary: Optional[str] = None + description: Optional[str] = None + value: Optional[Any] = None + externalValue: Optional[AnyUrl] = None + + class Config: + extra = "allow" + + +class ParameterInType(Enum): + query = "query" + header = "header" + path = "path" + cookie = "cookie" + + +class Encoding(BaseModel): + contentType: Optional[str] = None + headers: Optional[Dict[str, Union["Header", Reference]]] = None + style: Optional[str] = None + explode: Optional[bool] = None + allowReserved: Optional[bool] = None + + class Config: + extra = "allow" + + +class MediaType(BaseModel): + schema_: Optional[Union[Schema, Reference]] = Field(default=None, alias="schema") + example: Optional[Any] = None + examples: Optional[Dict[str, Union[Example, Reference]]] = None + encoding: Optional[Dict[str, Encoding]] = None + + class Config: + extra = "allow" + + +class ParameterBase(BaseModel): + description: Optional[str] = None + required: Optional[bool] = None + deprecated: Optional[bool] = None + # Serialization rules for simple scenarios + style: Optional[str] = None + explode: Optional[bool] = None + allowReserved: Optional[bool] = None + schema_: Optional[Union[Schema, Reference]] = Field(default=None, alias="schema") + example: Optional[Any] = None + examples: Optional[Dict[str, Union[Example, Reference]]] = None + # Serialization rules for more complex scenarios + content: Optional[Dict[str, MediaType]] = None + + class Config: + extra = "allow" + + +class Parameter(ParameterBase): + name: str + in_: ParameterInType = Field(alias="in") + + +class Header(ParameterBase): + pass + + +class RequestBody(BaseModel): + description: Optional[str] = None + content: Dict[str, MediaType] + required: Optional[bool] = None + + class Config: + extra = "allow" + + +class Link(BaseModel): + operationRef: Optional[str] = None + operationId: Optional[str] = None + parameters: Optional[Dict[str, Union[Any, str]]] = None + requestBody: Optional[Union[Any, str]] = None + description: Optional[str] = None + server: Optional[Server] = None + + class Config: + extra = "allow" + + +class Response(BaseModel): + description: str + headers: Optional[Dict[str, Union[Header, Reference]]] = None + content: Optional[Dict[str, MediaType]] = None + links: Optional[Dict[str, Union[Link, Reference]]] = None + + class Config: + extra = "allow" + + +class Operation(BaseModel): + tags: Optional[List[str]] = None + summary: Optional[str] = None + description: Optional[str] = None + externalDocs: Optional[ExternalDocumentation] = None + operationId: Optional[str] = None + parameters: Optional[List[Union[Parameter, Reference]]] = None + requestBody: Optional[Union[RequestBody, Reference]] = None + # Using Any for Specification Extensions + responses: Optional[Dict[str, Union[Response, Any]]] = None + callbacks: Optional[Dict[str, Union[Dict[str, "PathItem"], Reference]]] = None + deprecated: Optional[bool] = None + security: Optional[List[Dict[str, List[str]]]] = None + servers: Optional[List[Server]] = None + + class Config: + extra = "allow" + + +class PathItem(BaseModel): + ref: Optional[str] = Field(default=None, alias="$ref") + summary: Optional[str] = None + description: Optional[str] = None + get: Optional[Operation] = None + put: Optional[Operation] = None + post: Optional[Operation] = None + delete: Optional[Operation] = None + options: Optional[Operation] = None + head: Optional[Operation] = None + patch: Optional[Operation] = None + trace: Optional[Operation] = None + servers: Optional[List[Server]] = None + parameters: Optional[List[Union[Parameter, Reference]]] = None + + class Config: + extra = "allow" + + +class SecuritySchemeType(Enum): + apiKey = "apiKey" + http = "http" + oauth2 = "oauth2" + openIdConnect = "openIdConnect" + + +class SecurityBase(BaseModel): + type_: SecuritySchemeType = Field(alias="type") + description: Optional[str] = None + + class Config: + extra = "allow" + + +class APIKeyIn(Enum): + query = "query" + header = "header" + cookie = "cookie" + + +class APIKey(SecurityBase): + type_: SecuritySchemeType = Field(default=SecuritySchemeType.apiKey, alias="type") + in_: APIKeyIn = Field(alias="in") + name: str + + +class HTTPBase(SecurityBase): + type_: SecuritySchemeType = Field(default=SecuritySchemeType.http, alias="type") + scheme: str + + +class HTTPBearer(HTTPBase): + scheme: Literal["bearer"] = "bearer" + bearerFormat: Optional[str] = None + + +class OAuthFlow(BaseModel): + refreshUrl: Optional[str] = None + scopes: Dict[str, str] = {} + + class Config: + extra = "allow" + + +class OAuthFlowImplicit(OAuthFlow): + authorizationUrl: str + + +class OAuthFlowPassword(OAuthFlow): + tokenUrl: str + + +class OAuthFlowClientCredentials(OAuthFlow): + tokenUrl: str + + +class OAuthFlowAuthorizationCode(OAuthFlow): + authorizationUrl: str + tokenUrl: str + + +class OAuthFlows(BaseModel): + implicit: Optional[OAuthFlowImplicit] = None + password: Optional[OAuthFlowPassword] = None + clientCredentials: Optional[OAuthFlowClientCredentials] = None + authorizationCode: Optional[OAuthFlowAuthorizationCode] = None + + class Config: + extra = "allow" + + +class OAuth2(SecurityBase): + type_: SecuritySchemeType = Field(default=SecuritySchemeType.oauth2, alias="type") + flows: OAuthFlows + + +class OpenIdConnect(SecurityBase): + type_: SecuritySchemeType = Field( + default=SecuritySchemeType.openIdConnect, alias="type" + ) + openIdConnectUrl: str + + +SecurityScheme = Union[APIKey, HTTPBase, OAuth2, OpenIdConnect, HTTPBearer] + + +class Components(BaseModel): + schemas: Optional[Dict[str, Union[Schema, Reference]]] = None + responses: Optional[Dict[str, Union[Response, Reference]]] = None + parameters: Optional[Dict[str, Union[Parameter, Reference]]] = None + examples: Optional[Dict[str, Union[Example, Reference]]] = None + requestBodies: Optional[Dict[str, Union[RequestBody, Reference]]] = None + headers: Optional[Dict[str, Union[Header, Reference]]] = None + securitySchemes: Optional[Dict[str, Union[SecurityScheme, Reference]]] = None + links: Optional[Dict[str, Union[Link, Reference]]] = None + # Using Any for Specification Extensions + callbacks: Optional[Dict[str, Union[Dict[str, PathItem], Reference, Any]]] = None + pathItems: Optional[Dict[str, Union[PathItem, Reference]]] = None + + class Config: + extra = "allow" + + +class Tag(BaseModel): + name: str + description: Optional[str] = None + externalDocs: Optional[ExternalDocumentation] = None + + class Config: + extra = "allow" + + +class OpenAPI(BaseModel): + openapi: str + info: Info + jsonSchemaDialect: Optional[str] = None + servers: Optional[List[Server]] = None + # Using Any for Specification Extensions + paths: Optional[Dict[str, Union[PathItem, Any]]] = None + webhooks: Optional[Dict[str, Union[PathItem, Reference]]] = None + components: Optional[Components] = None + security: Optional[List[Dict[str, List[str]]]] = None + tags: Optional[List[Tag]] = None + externalDocs: Optional[ExternalDocumentation] = None + + class Config: + extra = "allow" + + +Schema.update_forward_refs() +Operation.update_forward_refs() +Encoding.update_forward_refs() diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/openapi/utils.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/openapi/utils.py new file mode 100644 index 0000000..609fe43 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/openapi/utils.py @@ -0,0 +1,466 @@ +import http.client +import inspect +import warnings +from enum import Enum +from typing import Any, Dict, List, Optional, Sequence, Set, Tuple, Type, Union, cast + +from fastapi import routing +from fastapi.datastructures import DefaultPlaceholder +from fastapi.dependencies.models import Dependant +from fastapi.dependencies.utils import get_flat_dependant, get_flat_params +from fastapi.encoders import jsonable_encoder +from fastapi.openapi.constants import METHODS_WITH_BODY, REF_PREFIX +from fastapi.openapi.models import OpenAPI +from fastapi.params import Body, Param +from fastapi.responses import Response +from fastapi.utils import ( + deep_dict_update, + generate_operation_id_for_path, + get_model_definitions, + is_body_allowed_for_status_code, +) +from pydantic import BaseModel +from pydantic.fields import ModelField, Undefined +from pydantic.schema import ( + field_schema, + get_flat_models_from_fields, + get_model_name_map, +) +from pydantic.utils import lenient_issubclass +from starlette.responses import JSONResponse +from starlette.routing import BaseRoute +from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY + +validation_error_definition = { + "title": "ValidationError", + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, + }, + "msg": {"title": "Message", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, + }, + "required": ["loc", "msg", "type"], +} + +validation_error_response_definition = { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": {"$ref": REF_PREFIX + "ValidationError"}, + } + }, +} + +status_code_ranges: Dict[str, str] = { + "1XX": "Information", + "2XX": "Success", + "3XX": "Redirection", + "4XX": "Client Error", + "5XX": "Server Error", + "DEFAULT": "Default Response", +} + + +def get_openapi_security_definitions( + flat_dependant: Dependant, +) -> Tuple[Dict[str, Any], List[Dict[str, Any]]]: + security_definitions = {} + operation_security = [] + for security_requirement in flat_dependant.security_requirements: + security_definition = jsonable_encoder( + security_requirement.security_scheme.model, + by_alias=True, + exclude_none=True, + ) + security_name = security_requirement.security_scheme.scheme_name + security_definitions[security_name] = security_definition + operation_security.append({security_name: security_requirement.scopes}) + return security_definitions, operation_security + + +def get_openapi_operation_parameters( + *, + all_route_params: Sequence[ModelField], + model_name_map: Dict[Union[Type[BaseModel], Type[Enum]], str], +) -> List[Dict[str, Any]]: + parameters = [] + for param in all_route_params: + field_info = param.field_info + field_info = cast(Param, field_info) + if not field_info.include_in_schema: + continue + parameter = { + "name": param.alias, + "in": field_info.in_.value, + "required": param.required, + "schema": field_schema( + param, model_name_map=model_name_map, ref_prefix=REF_PREFIX + )[0], + } + if field_info.description: + parameter["description"] = field_info.description + if field_info.example != Undefined: + parameter["example"] = jsonable_encoder(field_info.example) + if field_info.deprecated: + parameter["deprecated"] = field_info.deprecated + parameters.append(parameter) + return parameters + + +def get_openapi_operation_request_body( + *, + body_field: Optional[ModelField], + model_name_map: Dict[Union[Type[BaseModel], Type[Enum]], str], +) -> Optional[Dict[str, Any]]: + if not body_field: + return None + assert isinstance(body_field, ModelField) + body_schema, _, _ = field_schema( + body_field, model_name_map=model_name_map, ref_prefix=REF_PREFIX + ) + field_info = cast(Body, body_field.field_info) + request_media_type = field_info.media_type + required = body_field.required + request_body_oai: Dict[str, Any] = {} + if required: + request_body_oai["required"] = required + request_media_content: Dict[str, Any] = {"schema": body_schema} + if field_info.example != Undefined: + request_media_content["example"] = jsonable_encoder(field_info.example) + request_body_oai["content"] = {request_media_type: request_media_content} + return request_body_oai + + +def generate_operation_id( + *, route: routing.APIRoute, method: str +) -> str: # pragma: nocover + warnings.warn( + "fastapi.openapi.utils.generate_operation_id() was deprecated, " + "it is not used internally, and will be removed soon", + DeprecationWarning, + stacklevel=2, + ) + if route.operation_id: + return route.operation_id + path: str = route.path_format + return generate_operation_id_for_path(name=route.name, path=path, method=method) + + +def generate_operation_summary(*, route: routing.APIRoute, method: str) -> str: + if route.summary: + return route.summary + return route.name.replace("_", " ").title() + + +def get_openapi_operation_metadata( + *, route: routing.APIRoute, method: str, operation_ids: Set[str] +) -> Dict[str, Any]: + operation: Dict[str, Any] = {} + if route.tags: + operation["tags"] = route.tags + operation["summary"] = generate_operation_summary(route=route, method=method) + if route.description: + operation["description"] = route.description + operation_id = route.operation_id or route.unique_id + if operation_id in operation_ids: + message = ( + f"Duplicate Operation ID {operation_id} for function " + + f"{route.endpoint.__name__}" + ) + file_name = getattr(route.endpoint, "__globals__", {}).get("__file__") + if file_name: + message += f" at {file_name}" + warnings.warn(message, stacklevel=1) + operation_ids.add(operation_id) + operation["operationId"] = operation_id + if route.deprecated: + operation["deprecated"] = route.deprecated + return operation + + +def get_openapi_path( + *, route: routing.APIRoute, model_name_map: Dict[type, str], operation_ids: Set[str] +) -> Tuple[Dict[str, Any], Dict[str, Any], Dict[str, Any]]: + path = {} + security_schemes: Dict[str, Any] = {} + definitions: Dict[str, Any] = {} + assert route.methods is not None, "Methods must be a list" + if isinstance(route.response_class, DefaultPlaceholder): + current_response_class: Type[Response] = route.response_class.value + else: + current_response_class = route.response_class + assert current_response_class, "A response class is needed to generate OpenAPI" + route_response_media_type: Optional[str] = current_response_class.media_type + if route.include_in_schema: + for method in route.methods: + operation = get_openapi_operation_metadata( + route=route, method=method, operation_ids=operation_ids + ) + parameters: List[Dict[str, Any]] = [] + flat_dependant = get_flat_dependant(route.dependant, skip_repeats=True) + security_definitions, operation_security = get_openapi_security_definitions( + flat_dependant=flat_dependant + ) + if operation_security: + operation.setdefault("security", []).extend(operation_security) + if security_definitions: + security_schemes.update(security_definitions) + all_route_params = get_flat_params(route.dependant) + operation_parameters = get_openapi_operation_parameters( + all_route_params=all_route_params, model_name_map=model_name_map + ) + parameters.extend(operation_parameters) + if parameters: + all_parameters = { + (param["in"], param["name"]): param for param in parameters + } + required_parameters = { + (param["in"], param["name"]): param + for param in parameters + if param.get("required") + } + # Make sure required definitions of the same parameter take precedence + # over non-required definitions + all_parameters.update(required_parameters) + operation["parameters"] = list(all_parameters.values()) + if method in METHODS_WITH_BODY: + request_body_oai = get_openapi_operation_request_body( + body_field=route.body_field, model_name_map=model_name_map + ) + if request_body_oai: + operation["requestBody"] = request_body_oai + if route.callbacks: + callbacks = {} + for callback in route.callbacks: + if isinstance(callback, routing.APIRoute): + ( + cb_path, + cb_security_schemes, + cb_definitions, + ) = get_openapi_path( + route=callback, + model_name_map=model_name_map, + operation_ids=operation_ids, + ) + callbacks[callback.name] = {callback.path: cb_path} + operation["callbacks"] = callbacks + if route.status_code is not None: + status_code = str(route.status_code) + else: + # It would probably make more sense for all response classes to have an + # explicit default status_code, and to extract it from them, instead of + # doing this inspection tricks, that would probably be in the future + # TODO: probably make status_code a default class attribute for all + # responses in Starlette + response_signature = inspect.signature(current_response_class.__init__) + status_code_param = response_signature.parameters.get("status_code") + if status_code_param is not None: + if isinstance(status_code_param.default, int): + status_code = str(status_code_param.default) + operation.setdefault("responses", {}).setdefault(status_code, {})[ + "description" + ] = route.response_description + if route_response_media_type and is_body_allowed_for_status_code( + route.status_code + ): + response_schema = {"type": "string"} + if lenient_issubclass(current_response_class, JSONResponse): + if route.response_field: + response_schema, _, _ = field_schema( + route.response_field, + model_name_map=model_name_map, + ref_prefix=REF_PREFIX, + ) + else: + response_schema = {} + operation.setdefault("responses", {}).setdefault( + status_code, {} + ).setdefault("content", {}).setdefault(route_response_media_type, {})[ + "schema" + ] = response_schema + if route.responses: + operation_responses = operation.setdefault("responses", {}) + for ( + additional_status_code, + additional_response, + ) in route.responses.items(): + process_response = additional_response.copy() + process_response.pop("model", None) + status_code_key = str(additional_status_code).upper() + if status_code_key == "DEFAULT": + status_code_key = "default" + openapi_response = operation_responses.setdefault( + status_code_key, {} + ) + assert isinstance( + process_response, dict + ), "An additional response must be a dict" + field = route.response_fields.get(additional_status_code) + additional_field_schema: Optional[Dict[str, Any]] = None + if field: + additional_field_schema, _, _ = field_schema( + field, model_name_map=model_name_map, ref_prefix=REF_PREFIX + ) + media_type = route_response_media_type or "application/json" + additional_schema = ( + process_response.setdefault("content", {}) + .setdefault(media_type, {}) + .setdefault("schema", {}) + ) + deep_dict_update(additional_schema, additional_field_schema) + status_text: Optional[str] = status_code_ranges.get( + str(additional_status_code).upper() + ) or http.client.responses.get(int(additional_status_code)) + description = ( + process_response.get("description") + or openapi_response.get("description") + or status_text + or "Additional Response" + ) + deep_dict_update(openapi_response, process_response) + openapi_response["description"] = description + http422 = str(HTTP_422_UNPROCESSABLE_ENTITY) + if (all_route_params or route.body_field) and not any( + status in operation["responses"] + for status in [http422, "4XX", "default"] + ): + operation["responses"][http422] = { + "description": "Validation Error", + "content": { + "application/json": { + "schema": {"$ref": REF_PREFIX + "HTTPValidationError"} + } + }, + } + if "ValidationError" not in definitions: + definitions.update( + { + "ValidationError": validation_error_definition, + "HTTPValidationError": validation_error_response_definition, + } + ) + if route.openapi_extra: + deep_dict_update(operation, route.openapi_extra) + path[method.lower()] = operation + return path, security_schemes, definitions + + +def get_flat_models_from_routes( + routes: Sequence[BaseRoute], +) -> Set[Union[Type[BaseModel], Type[Enum]]]: + body_fields_from_routes: List[ModelField] = [] + responses_from_routes: List[ModelField] = [] + request_fields_from_routes: List[ModelField] = [] + callback_flat_models: Set[Union[Type[BaseModel], Type[Enum]]] = set() + for route in routes: + if getattr(route, "include_in_schema", None) and isinstance( + route, routing.APIRoute + ): + if route.body_field: + assert isinstance( + route.body_field, ModelField + ), "A request body must be a Pydantic Field" + body_fields_from_routes.append(route.body_field) + if route.response_field: + responses_from_routes.append(route.response_field) + if route.response_fields: + responses_from_routes.extend(route.response_fields.values()) + if route.callbacks: + callback_flat_models |= get_flat_models_from_routes(route.callbacks) + params = get_flat_params(route.dependant) + request_fields_from_routes.extend(params) + + flat_models = callback_flat_models | get_flat_models_from_fields( + body_fields_from_routes + responses_from_routes + request_fields_from_routes, + known_models=set(), + ) + return flat_models + + +def get_openapi( + *, + title: str, + version: str, + openapi_version: str = "3.1.0", + summary: Optional[str] = None, + description: Optional[str] = None, + routes: Sequence[BaseRoute], + webhooks: Optional[Sequence[BaseRoute]] = None, + tags: Optional[List[Dict[str, Any]]] = None, + servers: Optional[List[Dict[str, Union[str, Any]]]] = None, + terms_of_service: Optional[str] = None, + contact: Optional[Dict[str, Union[str, Any]]] = None, + license_info: Optional[Dict[str, Union[str, Any]]] = None, +) -> Dict[str, Any]: + info: Dict[str, Any] = {"title": title, "version": version} + if summary: + info["summary"] = summary + if description: + info["description"] = description + if terms_of_service: + info["termsOfService"] = terms_of_service + if contact: + info["contact"] = contact + if license_info: + info["license"] = license_info + output: Dict[str, Any] = {"openapi": openapi_version, "info": info} + if servers: + output["servers"] = servers + components: Dict[str, Dict[str, Any]] = {} + paths: Dict[str, Dict[str, Any]] = {} + webhook_paths: Dict[str, Dict[str, Any]] = {} + operation_ids: Set[str] = set() + flat_models = get_flat_models_from_routes(list(routes or []) + list(webhooks or [])) + model_name_map = get_model_name_map(flat_models) + definitions = get_model_definitions( + flat_models=flat_models, model_name_map=model_name_map + ) + for route in routes or []: + if isinstance(route, routing.APIRoute): + result = get_openapi_path( + route=route, model_name_map=model_name_map, operation_ids=operation_ids + ) + if result: + path, security_schemes, path_definitions = result + if path: + paths.setdefault(route.path_format, {}).update(path) + if security_schemes: + components.setdefault("securitySchemes", {}).update( + security_schemes + ) + if path_definitions: + definitions.update(path_definitions) + for webhook in webhooks or []: + if isinstance(webhook, routing.APIRoute): + result = get_openapi_path( + route=webhook, + model_name_map=model_name_map, + operation_ids=operation_ids, + ) + if result: + path, security_schemes, path_definitions = result + if path: + webhook_paths.setdefault(webhook.path_format, {}).update(path) + if security_schemes: + components.setdefault("securitySchemes", {}).update( + security_schemes + ) + if path_definitions: + definitions.update(path_definitions) + if definitions: + components["schemas"] = {k: definitions[k] for k in sorted(definitions)} + if components: + output["components"] = components + output["paths"] = paths + if webhook_paths: + output["webhooks"] = webhook_paths + if tags: + output["tags"] = tags + return jsonable_encoder(OpenAPI(**output), by_alias=True, exclude_none=True) # type: ignore diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/param_functions.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/param_functions.py new file mode 100644 index 0000000..2f5818c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/param_functions.py @@ -0,0 +1,333 @@ +from typing import Any, Callable, List, Optional, Sequence + +from fastapi import params +from pydantic.fields import Undefined +from typing_extensions import Annotated, deprecated + + +def Path( # noqa: N802 + default: Any = ..., + *, + alias: Optional[str] = None, + title: Optional[str] = None, + description: Optional[str] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + regex: Optional[str] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + **extra: Any, +) -> Any: + return params.Path( + default=default, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + example=example, + examples=examples, + deprecated=deprecated, + include_in_schema=include_in_schema, + **extra, + ) + + +def Query( # noqa: N802 + default: Any = Undefined, + *, + alias: Optional[str] = None, + title: Optional[str] = None, + description: Optional[str] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + regex: Optional[str] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + **extra: Any, +) -> Any: + return params.Query( + default=default, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + example=example, + examples=examples, + deprecated=deprecated, + include_in_schema=include_in_schema, + **extra, + ) + + +def Header( # noqa: N802 + default: Any = Undefined, + *, + alias: Optional[str] = None, + convert_underscores: bool = True, + title: Optional[str] = None, + description: Optional[str] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + regex: Optional[str] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + **extra: Any, +) -> Any: + return params.Header( + default=default, + alias=alias, + convert_underscores=convert_underscores, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + example=example, + examples=examples, + deprecated=deprecated, + include_in_schema=include_in_schema, + **extra, + ) + + +def Cookie( # noqa: N802 + default: Any = Undefined, + *, + alias: Optional[str] = None, + title: Optional[str] = None, + description: Optional[str] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + regex: Optional[str] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + **extra: Any, +) -> Any: + return params.Cookie( + default=default, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + example=example, + examples=examples, + deprecated=deprecated, + include_in_schema=include_in_schema, + **extra, + ) + + +def Body( # noqa: N802 + default: Any = Undefined, + *, + embed: bool = False, + media_type: str = "application/json", + alias: Optional[str] = None, + title: Optional[str] = None, + description: Optional[str] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + regex: Optional[str] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, + **extra: Any, +) -> Any: + return params.Body( + default=default, + embed=embed, + media_type=media_type, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + example=example, + examples=examples, + **extra, + ) + + +def Form( # noqa: N802 + default: Any = Undefined, + *, + media_type: str = "application/x-www-form-urlencoded", + alias: Optional[str] = None, + title: Optional[str] = None, + description: Optional[str] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + regex: Optional[str] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, + **extra: Any, +) -> Any: + return params.Form( + default=default, + media_type=media_type, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + example=example, + examples=examples, + **extra, + ) + + +def File( # noqa: N802 + default: Any = Undefined, + *, + media_type: str = "multipart/form-data", + alias: Optional[str] = None, + title: Optional[str] = None, + description: Optional[str] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + regex: Optional[str] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, + **extra: Any, +) -> Any: + return params.File( + default=default, + media_type=media_type, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + example=example, + examples=examples, + **extra, + ) + + +def Depends( # noqa: N802 + dependency: Optional[Callable[..., Any]] = None, *, use_cache: bool = True +) -> Any: + return params.Depends(dependency=dependency, use_cache=use_cache) + + +def Security( # noqa: N802 + dependency: Optional[Callable[..., Any]] = None, + *, + scopes: Optional[Sequence[str]] = None, + use_cache: bool = True, +) -> Any: + return params.Security(dependency=dependency, scopes=scopes, use_cache=use_cache) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/params.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/params.py new file mode 100644 index 0000000..4069f2c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/params.py @@ -0,0 +1,447 @@ +import warnings +from enum import Enum +from typing import Any, Callable, List, Optional, Sequence + +from pydantic.fields import FieldInfo, Undefined +from typing_extensions import Annotated, deprecated + + +class ParamTypes(Enum): + query = "query" + header = "header" + path = "path" + cookie = "cookie" + + +class Param(FieldInfo): + in_: ParamTypes + + def __init__( + self, + default: Any = Undefined, + *, + alias: Optional[str] = None, + title: Optional[str] = None, + description: Optional[str] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + regex: Optional[str] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + **extra: Any, + ): + self.deprecated = deprecated + if example is not Undefined: + warnings.warn( + "`example` has been depreacated, please use `examples` instead", + category=DeprecationWarning, + stacklevel=1, + ) + self.example = example + self.include_in_schema = include_in_schema + extra_kwargs = {**extra} + if examples: + extra_kwargs["examples"] = examples + super().__init__( + default=default, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + **extra_kwargs, + ) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self.default})" + + +class Path(Param): + in_ = ParamTypes.path + + def __init__( + self, + default: Any = ..., + *, + alias: Optional[str] = None, + title: Optional[str] = None, + description: Optional[str] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + regex: Optional[str] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + **extra: Any, + ): + assert default is ..., "Path parameters cannot have a default value" + self.in_ = self.in_ + super().__init__( + default=default, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + deprecated=deprecated, + example=example, + examples=examples, + include_in_schema=include_in_schema, + **extra, + ) + + +class Query(Param): + in_ = ParamTypes.query + + def __init__( + self, + default: Any = Undefined, + *, + alias: Optional[str] = None, + title: Optional[str] = None, + description: Optional[str] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + regex: Optional[str] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + **extra: Any, + ): + super().__init__( + default=default, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + deprecated=deprecated, + example=example, + examples=examples, + include_in_schema=include_in_schema, + **extra, + ) + + +class Header(Param): + in_ = ParamTypes.header + + def __init__( + self, + default: Any = Undefined, + *, + alias: Optional[str] = None, + convert_underscores: bool = True, + title: Optional[str] = None, + description: Optional[str] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + regex: Optional[str] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + **extra: Any, + ): + self.convert_underscores = convert_underscores + super().__init__( + default=default, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + deprecated=deprecated, + example=example, + examples=examples, + include_in_schema=include_in_schema, + **extra, + ) + + +class Cookie(Param): + in_ = ParamTypes.cookie + + def __init__( + self, + default: Any = Undefined, + *, + alias: Optional[str] = None, + title: Optional[str] = None, + description: Optional[str] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + regex: Optional[str] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + **extra: Any, + ): + super().__init__( + default=default, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + deprecated=deprecated, + example=example, + examples=examples, + include_in_schema=include_in_schema, + **extra, + ) + + +class Body(FieldInfo): + def __init__( + self, + default: Any = Undefined, + *, + embed: bool = False, + media_type: str = "application/json", + alias: Optional[str] = None, + title: Optional[str] = None, + description: Optional[str] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + regex: Optional[str] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, + **extra: Any, + ): + self.embed = embed + self.media_type = media_type + if example is not Undefined: + warnings.warn( + "`example` has been depreacated, please use `examples` instead", + category=DeprecationWarning, + stacklevel=1, + ) + self.example = example + extra_kwargs = {**extra} + if examples is not None: + extra_kwargs["examples"] = examples + super().__init__( + default=default, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + **extra_kwargs, + ) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self.default})" + + +class Form(Body): + def __init__( + self, + default: Any = Undefined, + *, + media_type: str = "application/x-www-form-urlencoded", + alias: Optional[str] = None, + title: Optional[str] = None, + description: Optional[str] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + regex: Optional[str] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, + **extra: Any, + ): + super().__init__( + default=default, + embed=True, + media_type=media_type, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + example=example, + examples=examples, + **extra, + ) + + +class File(Form): + def __init__( + self, + default: Any = Undefined, + *, + media_type: str = "multipart/form-data", + alias: Optional[str] = None, + title: Optional[str] = None, + description: Optional[str] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + regex: Optional[str] = None, + examples: Optional[List[Any]] = None, + example: Annotated[ + Optional[Any], + deprecated( + "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, " + "although still supported. Use examples instead." + ), + ] = Undefined, + **extra: Any, + ): + super().__init__( + default=default, + media_type=media_type, + alias=alias, + title=title, + description=description, + gt=gt, + ge=ge, + lt=lt, + le=le, + min_length=min_length, + max_length=max_length, + regex=regex, + example=example, + examples=examples, + **extra, + ) + + +class Depends: + def __init__( + self, dependency: Optional[Callable[..., Any]] = None, *, use_cache: bool = True + ): + self.dependency = dependency + self.use_cache = use_cache + + def __repr__(self) -> str: + attr = getattr(self.dependency, "__name__", type(self.dependency).__name__) + cache = "" if self.use_cache else ", use_cache=False" + return f"{self.__class__.__name__}({attr}{cache})" + + +class Security(Depends): + def __init__( + self, + dependency: Optional[Callable[..., Any]] = None, + *, + scopes: Optional[Sequence[str]] = None, + use_cache: bool = True, + ): + super().__init__(dependency=dependency, use_cache=use_cache) + self.scopes = scopes or [] diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/py.typed b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/requests.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/requests.py new file mode 100644 index 0000000..d16552c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/requests.py @@ -0,0 +1,2 @@ +from starlette.requests import HTTPConnection as HTTPConnection # noqa: F401 +from starlette.requests import Request as Request # noqa: F401 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/responses.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/responses.py new file mode 100644 index 0000000..c0a13b7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/responses.py @@ -0,0 +1,34 @@ +from typing import Any + +from starlette.responses import FileResponse as FileResponse # noqa +from starlette.responses import HTMLResponse as HTMLResponse # noqa +from starlette.responses import JSONResponse as JSONResponse # noqa +from starlette.responses import PlainTextResponse as PlainTextResponse # noqa +from starlette.responses import RedirectResponse as RedirectResponse # noqa +from starlette.responses import Response as Response # noqa +from starlette.responses import StreamingResponse as StreamingResponse # noqa + +try: + import ujson +except ImportError: # pragma: nocover + ujson = None # type: ignore + + +try: + import orjson +except ImportError: # pragma: nocover + orjson = None # type: ignore + + +class UJSONResponse(JSONResponse): + def render(self, content: Any) -> bytes: + assert ujson is not None, "ujson must be installed to use UJSONResponse" + return ujson.dumps(content, ensure_ascii=False).encode("utf-8") + + +class ORJSONResponse(JSONResponse): + def render(self, content: Any) -> bytes: + assert orjson is not None, "orjson must be installed to use ORJSONResponse" + return orjson.dumps( + content, option=orjson.OPT_NON_STR_KEYS | orjson.OPT_SERIALIZE_NUMPY + ) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/routing.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/routing.py new file mode 100644 index 0000000..ec8af99 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/routing.py @@ -0,0 +1,1321 @@ +import asyncio +import dataclasses +import email.message +import inspect +import json +from contextlib import AsyncExitStack +from enum import Enum, IntEnum +from typing import ( + Any, + Callable, + Coroutine, + Dict, + List, + Optional, + Sequence, + Set, + Tuple, + Type, + Union, +) + +from fastapi import params +from fastapi.datastructures import Default, DefaultPlaceholder +from fastapi.dependencies.models import Dependant +from fastapi.dependencies.utils import ( + get_body_field, + get_dependant, + get_parameterless_sub_dependant, + get_typed_return_annotation, + solve_dependencies, +) +from fastapi.encoders import DictIntStrAny, SetIntStr, jsonable_encoder +from fastapi.exceptions import ( + FastAPIError, + RequestValidationError, + WebSocketRequestValidationError, +) +from fastapi.types import DecoratedCallable +from fastapi.utils import ( + create_cloned_field, + create_response_field, + generate_unique_id, + get_value_or_default, + is_body_allowed_for_status_code, +) +from pydantic import BaseModel +from pydantic.error_wrappers import ErrorWrapper, ValidationError +from pydantic.fields import ModelField, Undefined +from pydantic.utils import lenient_issubclass +from starlette import routing +from starlette.concurrency import run_in_threadpool +from starlette.exceptions import HTTPException +from starlette.requests import Request +from starlette.responses import JSONResponse, Response +from starlette.routing import ( + BaseRoute, + Match, + compile_path, + get_name, + request_response, + websocket_session, +) +from starlette.routing import Mount as Mount # noqa +from starlette.types import ASGIApp, Lifespan, Scope +from starlette.websockets import WebSocket + + +def _prepare_response_content( + res: Any, + *, + exclude_unset: bool, + exclude_defaults: bool = False, + exclude_none: bool = False, +) -> Any: + if isinstance(res, BaseModel): + read_with_orm_mode = getattr(res.__config__, "read_with_orm_mode", None) + if read_with_orm_mode: + # Let from_orm extract the data from this model instead of converting + # it now to a dict. + # Otherwise there's no way to extract lazy data that requires attribute + # access instead of dict iteration, e.g. lazy relationships. + return res + return res.dict( + by_alias=True, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + ) + elif isinstance(res, list): + return [ + _prepare_response_content( + item, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + ) + for item in res + ] + elif isinstance(res, dict): + return { + k: _prepare_response_content( + v, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + ) + for k, v in res.items() + } + elif dataclasses.is_dataclass(res): + return dataclasses.asdict(res) + return res + + +async def serialize_response( + *, + field: Optional[ModelField] = None, + response_content: Any, + include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + by_alias: bool = True, + exclude_unset: bool = False, + exclude_defaults: bool = False, + exclude_none: bool = False, + is_coroutine: bool = True, +) -> Any: + if field: + errors = [] + response_content = _prepare_response_content( + response_content, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + ) + if is_coroutine: + value, errors_ = field.validate(response_content, {}, loc=("response",)) + else: + value, errors_ = await run_in_threadpool( + field.validate, response_content, {}, loc=("response",) + ) + if isinstance(errors_, ErrorWrapper): + errors.append(errors_) + elif isinstance(errors_, list): + errors.extend(errors_) + if errors: + raise ValidationError(errors, field.type_) + return jsonable_encoder( + value, + include=include, + exclude=exclude, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + ) + else: + return jsonable_encoder(response_content) + + +async def run_endpoint_function( + *, dependant: Dependant, values: Dict[str, Any], is_coroutine: bool +) -> Any: + # Only called by get_request_handler. Has been split into its own function to + # facilitate profiling endpoints, since inner functions are harder to profile. + assert dependant.call is not None, "dependant.call must be a function" + + if is_coroutine: + return await dependant.call(**values) + else: + return await run_in_threadpool(dependant.call, **values) + + +def get_request_handler( + dependant: Dependant, + body_field: Optional[ModelField] = None, + status_code: Optional[int] = None, + response_class: Union[Type[Response], DefaultPlaceholder] = Default(JSONResponse), + response_field: Optional[ModelField] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + dependency_overrides_provider: Optional[Any] = None, +) -> Callable[[Request], Coroutine[Any, Any, Response]]: + assert dependant.call is not None, "dependant.call must be a function" + is_coroutine = asyncio.iscoroutinefunction(dependant.call) + is_body_form = body_field and isinstance(body_field.field_info, params.Form) + if isinstance(response_class, DefaultPlaceholder): + actual_response_class: Type[Response] = response_class.value + else: + actual_response_class = response_class + + async def app(request: Request) -> Response: + try: + body: Any = None + if body_field: + if is_body_form: + body = await request.form() + stack = request.scope.get("fastapi_astack") + assert isinstance(stack, AsyncExitStack) + stack.push_async_callback(body.close) + else: + body_bytes = await request.body() + if body_bytes: + json_body: Any = Undefined + content_type_value = request.headers.get("content-type") + if not content_type_value: + json_body = await request.json() + else: + message = email.message.Message() + message["content-type"] = content_type_value + if message.get_content_maintype() == "application": + subtype = message.get_content_subtype() + if subtype == "json" or subtype.endswith("+json"): + json_body = await request.json() + if json_body != Undefined: + body = json_body + else: + body = body_bytes + except json.JSONDecodeError as e: + raise RequestValidationError( + [ErrorWrapper(e, ("body", e.pos))], body=e.doc + ) from e + except HTTPException: + raise + except Exception as e: + raise HTTPException( + status_code=400, detail="There was an error parsing the body" + ) from e + solved_result = await solve_dependencies( + request=request, + dependant=dependant, + body=body, + dependency_overrides_provider=dependency_overrides_provider, + ) + values, errors, background_tasks, sub_response, _ = solved_result + if errors: + raise RequestValidationError(errors, body=body) + else: + raw_response = await run_endpoint_function( + dependant=dependant, values=values, is_coroutine=is_coroutine + ) + + if isinstance(raw_response, Response): + if raw_response.background is None: + raw_response.background = background_tasks + return raw_response + response_args: Dict[str, Any] = {"background": background_tasks} + # If status_code was set, use it, otherwise use the default from the + # response class, in the case of redirect it's 307 + current_status_code = ( + status_code if status_code else sub_response.status_code + ) + if current_status_code is not None: + response_args["status_code"] = current_status_code + if sub_response.status_code: + response_args["status_code"] = sub_response.status_code + content = await serialize_response( + field=response_field, + response_content=raw_response, + include=response_model_include, + exclude=response_model_exclude, + by_alias=response_model_by_alias, + exclude_unset=response_model_exclude_unset, + exclude_defaults=response_model_exclude_defaults, + exclude_none=response_model_exclude_none, + is_coroutine=is_coroutine, + ) + response = actual_response_class(content, **response_args) + if not is_body_allowed_for_status_code(response.status_code): + response.body = b"" + response.headers.raw.extend(sub_response.headers.raw) + return response + + return app + + +def get_websocket_app( + dependant: Dependant, dependency_overrides_provider: Optional[Any] = None +) -> Callable[[WebSocket], Coroutine[Any, Any, Any]]: + async def app(websocket: WebSocket) -> None: + solved_result = await solve_dependencies( + request=websocket, + dependant=dependant, + dependency_overrides_provider=dependency_overrides_provider, + ) + values, errors, _, _2, _3 = solved_result + if errors: + raise WebSocketRequestValidationError(errors) + assert dependant.call is not None, "dependant.call must be a function" + await dependant.call(**values) + + return app + + +class APIWebSocketRoute(routing.WebSocketRoute): + def __init__( + self, + path: str, + endpoint: Callable[..., Any], + *, + name: Optional[str] = None, + dependencies: Optional[Sequence[params.Depends]] = None, + dependency_overrides_provider: Optional[Any] = None, + ) -> None: + self.path = path + self.endpoint = endpoint + self.name = get_name(endpoint) if name is None else name + self.dependencies = list(dependencies or []) + self.path_regex, self.path_format, self.param_convertors = compile_path(path) + self.dependant = get_dependant(path=self.path_format, call=self.endpoint) + for depends in self.dependencies[::-1]: + self.dependant.dependencies.insert( + 0, + get_parameterless_sub_dependant(depends=depends, path=self.path_format), + ) + + self.app = websocket_session( + get_websocket_app( + dependant=self.dependant, + dependency_overrides_provider=dependency_overrides_provider, + ) + ) + + def matches(self, scope: Scope) -> Tuple[Match, Scope]: + match, child_scope = super().matches(scope) + if match != Match.NONE: + child_scope["route"] = self + return match, child_scope + + +class APIRoute(routing.Route): + def __init__( + self, + path: str, + endpoint: Callable[..., Any], + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[params.Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + name: Optional[str] = None, + methods: Optional[Union[Set[str], List[str]]] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Union[Type[Response], DefaultPlaceholder] = Default( + JSONResponse + ), + dependency_overrides_provider: Optional[Any] = None, + callbacks: Optional[List[BaseRoute]] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Union[ + Callable[["APIRoute"], str], DefaultPlaceholder + ] = Default(generate_unique_id), + ) -> None: + self.path = path + self.endpoint = endpoint + if isinstance(response_model, DefaultPlaceholder): + return_annotation = get_typed_return_annotation(endpoint) + if lenient_issubclass(return_annotation, Response): + response_model = None + else: + response_model = return_annotation + self.response_model = response_model + self.summary = summary + self.response_description = response_description + self.deprecated = deprecated + self.operation_id = operation_id + self.response_model_include = response_model_include + self.response_model_exclude = response_model_exclude + self.response_model_by_alias = response_model_by_alias + self.response_model_exclude_unset = response_model_exclude_unset + self.response_model_exclude_defaults = response_model_exclude_defaults + self.response_model_exclude_none = response_model_exclude_none + self.include_in_schema = include_in_schema + self.response_class = response_class + self.dependency_overrides_provider = dependency_overrides_provider + self.callbacks = callbacks + self.openapi_extra = openapi_extra + self.generate_unique_id_function = generate_unique_id_function + self.tags = tags or [] + self.responses = responses or {} + self.name = get_name(endpoint) if name is None else name + self.path_regex, self.path_format, self.param_convertors = compile_path(path) + if methods is None: + methods = ["GET"] + self.methods: Set[str] = {method.upper() for method in methods} + if isinstance(generate_unique_id_function, DefaultPlaceholder): + current_generate_unique_id: Callable[ + ["APIRoute"], str + ] = generate_unique_id_function.value + else: + current_generate_unique_id = generate_unique_id_function + self.unique_id = self.operation_id or current_generate_unique_id(self) + # normalize enums e.g. http.HTTPStatus + if isinstance(status_code, IntEnum): + status_code = int(status_code) + self.status_code = status_code + if self.response_model: + assert is_body_allowed_for_status_code( + status_code + ), f"Status code {status_code} must not have a response body" + response_name = "Response_" + self.unique_id + self.response_field = create_response_field( + name=response_name, type_=self.response_model + ) + # Create a clone of the field, so that a Pydantic submodel is not returned + # as is just because it's an instance of a subclass of a more limited class + # e.g. UserInDB (containing hashed_password) could be a subclass of User + # that doesn't have the hashed_password. But because it's a subclass, it + # would pass the validation and be returned as is. + # By being a new field, no inheritance will be passed as is. A new model + # will be always created. + self.secure_cloned_response_field: Optional[ + ModelField + ] = create_cloned_field(self.response_field) + else: + self.response_field = None # type: ignore + self.secure_cloned_response_field = None + self.dependencies = list(dependencies or []) + self.description = description or inspect.cleandoc(self.endpoint.__doc__ or "") + # if a "form feed" character (page break) is found in the description text, + # truncate description text to the content preceding the first "form feed" + self.description = self.description.split("\f")[0].strip() + response_fields = {} + for additional_status_code, response in self.responses.items(): + assert isinstance(response, dict), "An additional response must be a dict" + model = response.get("model") + if model: + assert is_body_allowed_for_status_code( + additional_status_code + ), f"Status code {additional_status_code} must not have a response body" + response_name = f"Response_{additional_status_code}_{self.unique_id}" + response_field = create_response_field(name=response_name, type_=model) + response_fields[additional_status_code] = response_field + if response_fields: + self.response_fields: Dict[Union[int, str], ModelField] = response_fields + else: + self.response_fields = {} + + assert callable(endpoint), "An endpoint must be a callable" + self.dependant = get_dependant(path=self.path_format, call=self.endpoint) + for depends in self.dependencies[::-1]: + self.dependant.dependencies.insert( + 0, + get_parameterless_sub_dependant(depends=depends, path=self.path_format), + ) + self.body_field = get_body_field(dependant=self.dependant, name=self.unique_id) + self.app = request_response(self.get_route_handler()) + + def get_route_handler(self) -> Callable[[Request], Coroutine[Any, Any, Response]]: + return get_request_handler( + dependant=self.dependant, + body_field=self.body_field, + status_code=self.status_code, + response_class=self.response_class, + response_field=self.secure_cloned_response_field, + response_model_include=self.response_model_include, + response_model_exclude=self.response_model_exclude, + response_model_by_alias=self.response_model_by_alias, + response_model_exclude_unset=self.response_model_exclude_unset, + response_model_exclude_defaults=self.response_model_exclude_defaults, + response_model_exclude_none=self.response_model_exclude_none, + dependency_overrides_provider=self.dependency_overrides_provider, + ) + + def matches(self, scope: Scope) -> Tuple[Match, Scope]: + match, child_scope = super().matches(scope) + if match != Match.NONE: + child_scope["route"] = self + return match, child_scope + + +class APIRouter(routing.Router): + def __init__( + self, + *, + prefix: str = "", + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[params.Depends]] = None, + default_response_class: Type[Response] = Default(JSONResponse), + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + callbacks: Optional[List[BaseRoute]] = None, + routes: Optional[List[routing.BaseRoute]] = None, + redirect_slashes: bool = True, + default: Optional[ASGIApp] = None, + dependency_overrides_provider: Optional[Any] = None, + route_class: Type[APIRoute] = APIRoute, + on_startup: Optional[Sequence[Callable[[], Any]]] = None, + on_shutdown: Optional[Sequence[Callable[[], Any]]] = None, + # the generic to Lifespan[AppType] is the type of the top level application + # which the router cannot know statically, so we use typing.Any + lifespan: Optional[Lifespan[Any]] = None, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + generate_unique_id_function: Callable[[APIRoute], str] = Default( + generate_unique_id + ), + ) -> None: + super().__init__( + routes=routes, + redirect_slashes=redirect_slashes, + default=default, + on_startup=on_startup, + on_shutdown=on_shutdown, + lifespan=lifespan, + ) + if prefix: + assert prefix.startswith("/"), "A path prefix must start with '/'" + assert not prefix.endswith( + "/" + ), "A path prefix must not end with '/', as the routes will start with '/'" + self.prefix = prefix + self.tags: List[Union[str, Enum]] = tags or [] + self.dependencies = list(dependencies or []) + self.deprecated = deprecated + self.include_in_schema = include_in_schema + self.responses = responses or {} + self.callbacks = callbacks or [] + self.dependency_overrides_provider = dependency_overrides_provider + self.route_class = route_class + self.default_response_class = default_response_class + self.generate_unique_id_function = generate_unique_id_function + + def route( + self, + path: str, + methods: Optional[List[str]] = None, + name: Optional[str] = None, + include_in_schema: bool = True, + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + def decorator(func: DecoratedCallable) -> DecoratedCallable: + self.add_route( + path, + func, + methods=methods, + name=name, + include_in_schema=include_in_schema, + ) + return func + + return decorator + + def add_api_route( + self, + path: str, + endpoint: Callable[..., Any], + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[params.Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + methods: Optional[Union[Set[str], List[str]]] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Union[Type[Response], DefaultPlaceholder] = Default( + JSONResponse + ), + name: Optional[str] = None, + route_class_override: Optional[Type[APIRoute]] = None, + callbacks: Optional[List[BaseRoute]] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Union[ + Callable[[APIRoute], str], DefaultPlaceholder + ] = Default(generate_unique_id), + ) -> None: + route_class = route_class_override or self.route_class + responses = responses or {} + combined_responses = {**self.responses, **responses} + current_response_class = get_value_or_default( + response_class, self.default_response_class + ) + current_tags = self.tags.copy() + if tags: + current_tags.extend(tags) + current_dependencies = self.dependencies.copy() + if dependencies: + current_dependencies.extend(dependencies) + current_callbacks = self.callbacks.copy() + if callbacks: + current_callbacks.extend(callbacks) + current_generate_unique_id = get_value_or_default( + generate_unique_id_function, self.generate_unique_id_function + ) + route = route_class( + self.prefix + path, + endpoint=endpoint, + response_model=response_model, + status_code=status_code, + tags=current_tags, + dependencies=current_dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=combined_responses, + deprecated=deprecated or self.deprecated, + methods=methods, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema and self.include_in_schema, + response_class=current_response_class, + name=name, + dependency_overrides_provider=self.dependency_overrides_provider, + callbacks=current_callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=current_generate_unique_id, + ) + self.routes.append(route) + + def api_route( + self, + path: str, + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[params.Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + methods: Optional[List[str]] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Type[Response] = Default(JSONResponse), + name: Optional[str] = None, + callbacks: Optional[List[BaseRoute]] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Callable[[APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + def decorator(func: DecoratedCallable) -> DecoratedCallable: + self.add_api_route( + path, + func, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + methods=methods, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + return func + + return decorator + + def add_api_websocket_route( + self, + path: str, + endpoint: Callable[..., Any], + name: Optional[str] = None, + *, + dependencies: Optional[Sequence[params.Depends]] = None, + ) -> None: + current_dependencies = self.dependencies.copy() + if dependencies: + current_dependencies.extend(dependencies) + + route = APIWebSocketRoute( + self.prefix + path, + endpoint=endpoint, + name=name, + dependencies=current_dependencies, + dependency_overrides_provider=self.dependency_overrides_provider, + ) + self.routes.append(route) + + def websocket( + self, + path: str, + name: Optional[str] = None, + *, + dependencies: Optional[Sequence[params.Depends]] = None, + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + def decorator(func: DecoratedCallable) -> DecoratedCallable: + self.add_api_websocket_route( + path, func, name=name, dependencies=dependencies + ) + return func + + return decorator + + def websocket_route( + self, path: str, name: Union[str, None] = None + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + def decorator(func: DecoratedCallable) -> DecoratedCallable: + self.add_websocket_route(path, func, name=name) + return func + + return decorator + + def include_router( + self, + router: "APIRouter", + *, + prefix: str = "", + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[params.Depends]] = None, + default_response_class: Type[Response] = Default(JSONResponse), + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + callbacks: Optional[List[BaseRoute]] = None, + deprecated: Optional[bool] = None, + include_in_schema: bool = True, + generate_unique_id_function: Callable[[APIRoute], str] = Default( + generate_unique_id + ), + ) -> None: + if prefix: + assert prefix.startswith("/"), "A path prefix must start with '/'" + assert not prefix.endswith( + "/" + ), "A path prefix must not end with '/', as the routes will start with '/'" + else: + for r in router.routes: + path = getattr(r, "path") # noqa: B009 + name = getattr(r, "name", "unknown") + if path is not None and not path: + raise FastAPIError( + f"Prefix and path cannot be both empty (path operation: {name})" + ) + if responses is None: + responses = {} + for route in router.routes: + if isinstance(route, APIRoute): + combined_responses = {**responses, **route.responses} + use_response_class = get_value_or_default( + route.response_class, + router.default_response_class, + default_response_class, + self.default_response_class, + ) + current_tags = [] + if tags: + current_tags.extend(tags) + if route.tags: + current_tags.extend(route.tags) + current_dependencies: List[params.Depends] = [] + if dependencies: + current_dependencies.extend(dependencies) + if route.dependencies: + current_dependencies.extend(route.dependencies) + current_callbacks = [] + if callbacks: + current_callbacks.extend(callbacks) + if route.callbacks: + current_callbacks.extend(route.callbacks) + current_generate_unique_id = get_value_or_default( + route.generate_unique_id_function, + router.generate_unique_id_function, + generate_unique_id_function, + self.generate_unique_id_function, + ) + self.add_api_route( + prefix + route.path, + route.endpoint, + response_model=route.response_model, + status_code=route.status_code, + tags=current_tags, + dependencies=current_dependencies, + summary=route.summary, + description=route.description, + response_description=route.response_description, + responses=combined_responses, + deprecated=route.deprecated or deprecated or self.deprecated, + methods=route.methods, + operation_id=route.operation_id, + response_model_include=route.response_model_include, + response_model_exclude=route.response_model_exclude, + response_model_by_alias=route.response_model_by_alias, + response_model_exclude_unset=route.response_model_exclude_unset, + response_model_exclude_defaults=route.response_model_exclude_defaults, + response_model_exclude_none=route.response_model_exclude_none, + include_in_schema=route.include_in_schema + and self.include_in_schema + and include_in_schema, + response_class=use_response_class, + name=route.name, + route_class_override=type(route), + callbacks=current_callbacks, + openapi_extra=route.openapi_extra, + generate_unique_id_function=current_generate_unique_id, + ) + elif isinstance(route, routing.Route): + methods = list(route.methods or []) + self.add_route( + prefix + route.path, + route.endpoint, + methods=methods, + include_in_schema=route.include_in_schema, + name=route.name, + ) + elif isinstance(route, APIWebSocketRoute): + current_dependencies = [] + if dependencies: + current_dependencies.extend(dependencies) + if route.dependencies: + current_dependencies.extend(route.dependencies) + self.add_api_websocket_route( + prefix + route.path, + route.endpoint, + dependencies=current_dependencies, + name=route.name, + ) + elif isinstance(route, routing.WebSocketRoute): + self.add_websocket_route( + prefix + route.path, route.endpoint, name=route.name + ) + for handler in router.on_startup: + self.add_event_handler("startup", handler) + for handler in router.on_shutdown: + self.add_event_handler("shutdown", handler) + + def get( + self, + path: str, + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[params.Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Type[Response] = Default(JSONResponse), + name: Optional[str] = None, + callbacks: Optional[List[BaseRoute]] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Callable[[APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + return self.api_route( + path=path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + methods=["GET"], + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def put( + self, + path: str, + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[params.Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Type[Response] = Default(JSONResponse), + name: Optional[str] = None, + callbacks: Optional[List[BaseRoute]] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Callable[[APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + return self.api_route( + path=path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + methods=["PUT"], + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def post( + self, + path: str, + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[params.Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Type[Response] = Default(JSONResponse), + name: Optional[str] = None, + callbacks: Optional[List[BaseRoute]] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Callable[[APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + return self.api_route( + path=path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + methods=["POST"], + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def delete( + self, + path: str, + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[params.Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Type[Response] = Default(JSONResponse), + name: Optional[str] = None, + callbacks: Optional[List[BaseRoute]] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Callable[[APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + return self.api_route( + path=path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + methods=["DELETE"], + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def options( + self, + path: str, + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[params.Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Type[Response] = Default(JSONResponse), + name: Optional[str] = None, + callbacks: Optional[List[BaseRoute]] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Callable[[APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + return self.api_route( + path=path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + methods=["OPTIONS"], + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def head( + self, + path: str, + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[params.Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Type[Response] = Default(JSONResponse), + name: Optional[str] = None, + callbacks: Optional[List[BaseRoute]] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Callable[[APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + return self.api_route( + path=path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + methods=["HEAD"], + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def patch( + self, + path: str, + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[params.Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Type[Response] = Default(JSONResponse), + name: Optional[str] = None, + callbacks: Optional[List[BaseRoute]] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Callable[[APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + return self.api_route( + path=path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + methods=["PATCH"], + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def trace( + self, + path: str, + *, + response_model: Any = Default(None), + status_code: Optional[int] = None, + tags: Optional[List[Union[str, Enum]]] = None, + dependencies: Optional[Sequence[params.Depends]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + response_description: str = "Successful Response", + responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None, + deprecated: Optional[bool] = None, + operation_id: Optional[str] = None, + response_model_include: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: Type[Response] = Default(JSONResponse), + name: Optional[str] = None, + callbacks: Optional[List[BaseRoute]] = None, + openapi_extra: Optional[Dict[str, Any]] = None, + generate_unique_id_function: Callable[[APIRoute], str] = Default( + generate_unique_id + ), + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + return self.api_route( + path=path, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + methods=["TRACE"], + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + name=name, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + ) + + def on_event( + self, event_type: str + ) -> Callable[[DecoratedCallable], DecoratedCallable]: + def decorator(func: DecoratedCallable) -> DecoratedCallable: + self.add_event_handler(event_type, func) + return func + + return decorator diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/security/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/security/__init__.py new file mode 100644 index 0000000..3aa6bf2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/security/__init__.py @@ -0,0 +1,15 @@ +from .api_key import APIKeyCookie as APIKeyCookie +from .api_key import APIKeyHeader as APIKeyHeader +from .api_key import APIKeyQuery as APIKeyQuery +from .http import HTTPAuthorizationCredentials as HTTPAuthorizationCredentials +from .http import HTTPBasic as HTTPBasic +from .http import HTTPBasicCredentials as HTTPBasicCredentials +from .http import HTTPBearer as HTTPBearer +from .http import HTTPDigest as HTTPDigest +from .oauth2 import OAuth2 as OAuth2 +from .oauth2 import OAuth2AuthorizationCodeBearer as OAuth2AuthorizationCodeBearer +from .oauth2 import OAuth2PasswordBearer as OAuth2PasswordBearer +from .oauth2 import OAuth2PasswordRequestForm as OAuth2PasswordRequestForm +from .oauth2 import OAuth2PasswordRequestFormStrict as OAuth2PasswordRequestFormStrict +from .oauth2 import SecurityScopes as SecurityScopes +from .open_id_connect_url import OpenIdConnect as OpenIdConnect diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/security/api_key.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/security/api_key.py new file mode 100644 index 0000000..8b2c5c0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/security/api_key.py @@ -0,0 +1,98 @@ +from typing import Optional + +from fastapi.openapi.models import APIKey, APIKeyIn +from fastapi.security.base import SecurityBase +from starlette.exceptions import HTTPException +from starlette.requests import Request +from starlette.status import HTTP_403_FORBIDDEN + + +class APIKeyBase(SecurityBase): + pass + + +class APIKeyQuery(APIKeyBase): + def __init__( + self, + *, + name: str, + scheme_name: Optional[str] = None, + description: Optional[str] = None, + auto_error: bool = True, + ): + self.model: APIKey = APIKey( + **{"in": APIKeyIn.query}, # type: ignore[arg-type] + name=name, + description=description, + ) + self.scheme_name = scheme_name or self.__class__.__name__ + self.auto_error = auto_error + + async def __call__(self, request: Request) -> Optional[str]: + api_key = request.query_params.get(self.model.name) + if not api_key: + if self.auto_error: + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" + ) + else: + return None + return api_key + + +class APIKeyHeader(APIKeyBase): + def __init__( + self, + *, + name: str, + scheme_name: Optional[str] = None, + description: Optional[str] = None, + auto_error: bool = True, + ): + self.model: APIKey = APIKey( + **{"in": APIKeyIn.header}, # type: ignore[arg-type] + name=name, + description=description, + ) + self.scheme_name = scheme_name or self.__class__.__name__ + self.auto_error = auto_error + + async def __call__(self, request: Request) -> Optional[str]: + api_key = request.headers.get(self.model.name) + if not api_key: + if self.auto_error: + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" + ) + else: + return None + return api_key + + +class APIKeyCookie(APIKeyBase): + def __init__( + self, + *, + name: str, + scheme_name: Optional[str] = None, + description: Optional[str] = None, + auto_error: bool = True, + ): + self.model: APIKey = APIKey( + **{"in": APIKeyIn.cookie}, # type: ignore[arg-type] + name=name, + description=description, + ) + self.scheme_name = scheme_name or self.__class__.__name__ + self.auto_error = auto_error + + async def __call__(self, request: Request) -> Optional[str]: + api_key = request.cookies.get(self.model.name) + if not api_key: + if self.auto_error: + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" + ) + else: + return None + return api_key diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/security/base.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/security/base.py new file mode 100644 index 0000000..c43555d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/security/base.py @@ -0,0 +1,6 @@ +from fastapi.openapi.models import SecurityBase as SecurityBaseModel + + +class SecurityBase: + model: SecurityBaseModel + scheme_name: str diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/security/http.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/security/http.py new file mode 100644 index 0000000..8fc0aaf --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/security/http.py @@ -0,0 +1,165 @@ +import binascii +from base64 import b64decode +from typing import Optional + +from fastapi.exceptions import HTTPException +from fastapi.openapi.models import HTTPBase as HTTPBaseModel +from fastapi.openapi.models import HTTPBearer as HTTPBearerModel +from fastapi.security.base import SecurityBase +from fastapi.security.utils import get_authorization_scheme_param +from pydantic import BaseModel +from starlette.requests import Request +from starlette.status import HTTP_401_UNAUTHORIZED, HTTP_403_FORBIDDEN + + +class HTTPBasicCredentials(BaseModel): + username: str + password: str + + +class HTTPAuthorizationCredentials(BaseModel): + scheme: str + credentials: str + + +class HTTPBase(SecurityBase): + def __init__( + self, + *, + scheme: str, + scheme_name: Optional[str] = None, + description: Optional[str] = None, + auto_error: bool = True, + ): + self.model = HTTPBaseModel(scheme=scheme, description=description) + self.scheme_name = scheme_name or self.__class__.__name__ + self.auto_error = auto_error + + async def __call__( + self, request: Request + ) -> Optional[HTTPAuthorizationCredentials]: + authorization = request.headers.get("Authorization") + scheme, credentials = get_authorization_scheme_param(authorization) + if not (authorization and scheme and credentials): + if self.auto_error: + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" + ) + else: + return None + return HTTPAuthorizationCredentials(scheme=scheme, credentials=credentials) + + +class HTTPBasic(HTTPBase): + def __init__( + self, + *, + scheme_name: Optional[str] = None, + realm: Optional[str] = None, + description: Optional[str] = None, + auto_error: bool = True, + ): + self.model = HTTPBaseModel(scheme="basic", description=description) + self.scheme_name = scheme_name or self.__class__.__name__ + self.realm = realm + self.auto_error = auto_error + + async def __call__( # type: ignore + self, request: Request + ) -> Optional[HTTPBasicCredentials]: + authorization = request.headers.get("Authorization") + scheme, param = get_authorization_scheme_param(authorization) + if self.realm: + unauthorized_headers = {"WWW-Authenticate": f'Basic realm="{self.realm}"'} + else: + unauthorized_headers = {"WWW-Authenticate": "Basic"} + if not authorization or scheme.lower() != "basic": + if self.auto_error: + raise HTTPException( + status_code=HTTP_401_UNAUTHORIZED, + detail="Not authenticated", + headers=unauthorized_headers, + ) + else: + return None + invalid_user_credentials_exc = HTTPException( + status_code=HTTP_401_UNAUTHORIZED, + detail="Invalid authentication credentials", + headers=unauthorized_headers, + ) + try: + data = b64decode(param).decode("ascii") + except (ValueError, UnicodeDecodeError, binascii.Error): + raise invalid_user_credentials_exc + username, separator, password = data.partition(":") + if not separator: + raise invalid_user_credentials_exc + return HTTPBasicCredentials(username=username, password=password) + + +class HTTPBearer(HTTPBase): + def __init__( + self, + *, + bearerFormat: Optional[str] = None, + scheme_name: Optional[str] = None, + description: Optional[str] = None, + auto_error: bool = True, + ): + self.model = HTTPBearerModel(bearerFormat=bearerFormat, description=description) + self.scheme_name = scheme_name or self.__class__.__name__ + self.auto_error = auto_error + + async def __call__( + self, request: Request + ) -> Optional[HTTPAuthorizationCredentials]: + authorization = request.headers.get("Authorization") + scheme, credentials = get_authorization_scheme_param(authorization) + if not (authorization and scheme and credentials): + if self.auto_error: + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" + ) + else: + return None + if scheme.lower() != "bearer": + if self.auto_error: + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, + detail="Invalid authentication credentials", + ) + else: + return None + return HTTPAuthorizationCredentials(scheme=scheme, credentials=credentials) + + +class HTTPDigest(HTTPBase): + def __init__( + self, + *, + scheme_name: Optional[str] = None, + description: Optional[str] = None, + auto_error: bool = True, + ): + self.model = HTTPBaseModel(scheme="digest", description=description) + self.scheme_name = scheme_name or self.__class__.__name__ + self.auto_error = auto_error + + async def __call__( + self, request: Request + ) -> Optional[HTTPAuthorizationCredentials]: + authorization = request.headers.get("Authorization") + scheme, credentials = get_authorization_scheme_param(authorization) + if not (authorization and scheme and credentials): + if self.auto_error: + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" + ) + else: + return None + if scheme.lower() != "digest": + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, + detail="Invalid authentication credentials", + ) + return HTTPAuthorizationCredentials(scheme=scheme, credentials=credentials) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/security/oauth2.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/security/oauth2.py new file mode 100644 index 0000000..938dec3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/security/oauth2.py @@ -0,0 +1,227 @@ +from typing import Any, Dict, List, Optional, Union, cast + +from fastapi.exceptions import HTTPException +from fastapi.openapi.models import OAuth2 as OAuth2Model +from fastapi.openapi.models import OAuthFlows as OAuthFlowsModel +from fastapi.param_functions import Form +from fastapi.security.base import SecurityBase +from fastapi.security.utils import get_authorization_scheme_param +from starlette.requests import Request +from starlette.status import HTTP_401_UNAUTHORIZED, HTTP_403_FORBIDDEN + + +class OAuth2PasswordRequestForm: + """ + This is a dependency class, use it like: + + @app.post("/login") + def login(form_data: OAuth2PasswordRequestForm = Depends()): + data = form_data.parse() + print(data.username) + print(data.password) + for scope in data.scopes: + print(scope) + if data.client_id: + print(data.client_id) + if data.client_secret: + print(data.client_secret) + return data + + + It creates the following Form request parameters in your endpoint: + + grant_type: the OAuth2 spec says it is required and MUST be the fixed string "password". + Nevertheless, this dependency class is permissive and allows not passing it. If you want to enforce it, + use instead the OAuth2PasswordRequestFormStrict dependency. + username: username string. The OAuth2 spec requires the exact field name "username". + password: password string. The OAuth2 spec requires the exact field name "password". + scope: Optional string. Several scopes (each one a string) separated by spaces. E.g. + "items:read items:write users:read profile openid" + client_id: optional string. OAuth2 recommends sending the client_id and client_secret (if any) + using HTTP Basic auth, as: client_id:client_secret + client_secret: optional string. OAuth2 recommends sending the client_id and client_secret (if any) + using HTTP Basic auth, as: client_id:client_secret + """ + + def __init__( + self, + grant_type: str = Form(default=None, regex="password"), + username: str = Form(), + password: str = Form(), + scope: str = Form(default=""), + client_id: Optional[str] = Form(default=None), + client_secret: Optional[str] = Form(default=None), + ): + self.grant_type = grant_type + self.username = username + self.password = password + self.scopes = scope.split() + self.client_id = client_id + self.client_secret = client_secret + + +class OAuth2PasswordRequestFormStrict(OAuth2PasswordRequestForm): + """ + This is a dependency class, use it like: + + @app.post("/login") + def login(form_data: OAuth2PasswordRequestFormStrict = Depends()): + data = form_data.parse() + print(data.username) + print(data.password) + for scope in data.scopes: + print(scope) + if data.client_id: + print(data.client_id) + if data.client_secret: + print(data.client_secret) + return data + + + It creates the following Form request parameters in your endpoint: + + grant_type: the OAuth2 spec says it is required and MUST be the fixed string "password". + This dependency is strict about it. If you want to be permissive, use instead the + OAuth2PasswordRequestForm dependency class. + username: username string. The OAuth2 spec requires the exact field name "username". + password: password string. The OAuth2 spec requires the exact field name "password". + scope: Optional string. Several scopes (each one a string) separated by spaces. E.g. + "items:read items:write users:read profile openid" + client_id: optional string. OAuth2 recommends sending the client_id and client_secret (if any) + using HTTP Basic auth, as: client_id:client_secret + client_secret: optional string. OAuth2 recommends sending the client_id and client_secret (if any) + using HTTP Basic auth, as: client_id:client_secret + """ + + def __init__( + self, + grant_type: str = Form(regex="password"), + username: str = Form(), + password: str = Form(), + scope: str = Form(default=""), + client_id: Optional[str] = Form(default=None), + client_secret: Optional[str] = Form(default=None), + ): + super().__init__( + grant_type=grant_type, + username=username, + password=password, + scope=scope, + client_id=client_id, + client_secret=client_secret, + ) + + +class OAuth2(SecurityBase): + def __init__( + self, + *, + flows: Union[OAuthFlowsModel, Dict[str, Dict[str, Any]]] = OAuthFlowsModel(), + scheme_name: Optional[str] = None, + description: Optional[str] = None, + auto_error: bool = True, + ): + self.model = OAuth2Model( + flows=cast(OAuthFlowsModel, flows), description=description + ) + self.scheme_name = scheme_name or self.__class__.__name__ + self.auto_error = auto_error + + async def __call__(self, request: Request) -> Optional[str]: + authorization = request.headers.get("Authorization") + if not authorization: + if self.auto_error: + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" + ) + else: + return None + return authorization + + +class OAuth2PasswordBearer(OAuth2): + def __init__( + self, + tokenUrl: str, + scheme_name: Optional[str] = None, + scopes: Optional[Dict[str, str]] = None, + description: Optional[str] = None, + auto_error: bool = True, + ): + if not scopes: + scopes = {} + flows = OAuthFlowsModel( + password=cast(Any, {"tokenUrl": tokenUrl, "scopes": scopes}) + ) + super().__init__( + flows=flows, + scheme_name=scheme_name, + description=description, + auto_error=auto_error, + ) + + async def __call__(self, request: Request) -> Optional[str]: + authorization = request.headers.get("Authorization") + scheme, param = get_authorization_scheme_param(authorization) + if not authorization or scheme.lower() != "bearer": + if self.auto_error: + raise HTTPException( + status_code=HTTP_401_UNAUTHORIZED, + detail="Not authenticated", + headers={"WWW-Authenticate": "Bearer"}, + ) + else: + return None + return param + + +class OAuth2AuthorizationCodeBearer(OAuth2): + def __init__( + self, + authorizationUrl: str, + tokenUrl: str, + refreshUrl: Optional[str] = None, + scheme_name: Optional[str] = None, + scopes: Optional[Dict[str, str]] = None, + description: Optional[str] = None, + auto_error: bool = True, + ): + if not scopes: + scopes = {} + flows = OAuthFlowsModel( + authorizationCode=cast( + Any, + { + "authorizationUrl": authorizationUrl, + "tokenUrl": tokenUrl, + "refreshUrl": refreshUrl, + "scopes": scopes, + }, + ) + ) + super().__init__( + flows=flows, + scheme_name=scheme_name, + description=description, + auto_error=auto_error, + ) + + async def __call__(self, request: Request) -> Optional[str]: + authorization = request.headers.get("Authorization") + scheme, param = get_authorization_scheme_param(authorization) + if not authorization or scheme.lower() != "bearer": + if self.auto_error: + raise HTTPException( + status_code=HTTP_401_UNAUTHORIZED, + detail="Not authenticated", + headers={"WWW-Authenticate": "Bearer"}, + ) + else: + return None # pragma: nocover + return param + + +class SecurityScopes: + def __init__(self, scopes: Optional[List[str]] = None): + self.scopes = scopes or [] + self.scope_str = " ".join(self.scopes) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/security/open_id_connect_url.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/security/open_id_connect_url.py new file mode 100644 index 0000000..4e65f1f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/security/open_id_connect_url.py @@ -0,0 +1,34 @@ +from typing import Optional + +from fastapi.openapi.models import OpenIdConnect as OpenIdConnectModel +from fastapi.security.base import SecurityBase +from starlette.exceptions import HTTPException +from starlette.requests import Request +from starlette.status import HTTP_403_FORBIDDEN + + +class OpenIdConnect(SecurityBase): + def __init__( + self, + *, + openIdConnectUrl: str, + scheme_name: Optional[str] = None, + description: Optional[str] = None, + auto_error: bool = True, + ): + self.model = OpenIdConnectModel( + openIdConnectUrl=openIdConnectUrl, description=description + ) + self.scheme_name = scheme_name or self.__class__.__name__ + self.auto_error = auto_error + + async def __call__(self, request: Request) -> Optional[str]: + authorization = request.headers.get("Authorization") + if not authorization: + if self.auto_error: + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" + ) + else: + return None + return authorization diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/security/utils.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/security/utils.py new file mode 100644 index 0000000..fa7a450 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/security/utils.py @@ -0,0 +1,10 @@ +from typing import Optional, Tuple + + +def get_authorization_scheme_param( + authorization_header_value: Optional[str], +) -> Tuple[str, str]: + if not authorization_header_value: + return "", "" + scheme, _, param = authorization_header_value.partition(" ") + return scheme, param diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/staticfiles.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/staticfiles.py new file mode 100644 index 0000000..299015d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/staticfiles.py @@ -0,0 +1 @@ +from starlette.staticfiles import StaticFiles as StaticFiles # noqa diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/templating.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/templating.py new file mode 100644 index 0000000..0cb8684 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/templating.py @@ -0,0 +1 @@ +from starlette.templating import Jinja2Templates as Jinja2Templates # noqa diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/testclient.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/testclient.py new file mode 100644 index 0000000..4012406 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/testclient.py @@ -0,0 +1 @@ +from starlette.testclient import TestClient as TestClient # noqa diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/types.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/types.py new file mode 100644 index 0000000..e0bca46 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/types.py @@ -0,0 +1,3 @@ +from typing import Any, Callable, TypeVar + +DecoratedCallable = TypeVar("DecoratedCallable", bound=Callable[..., Any]) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/utils.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/utils.py new file mode 100644 index 0000000..9b9ebcb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/utils.py @@ -0,0 +1,222 @@ +import re +import warnings +from dataclasses import is_dataclass +from enum import Enum +from typing import ( + TYPE_CHECKING, + Any, + Dict, + MutableMapping, + Optional, + Set, + Type, + Union, + cast, +) +from weakref import WeakKeyDictionary + +import fastapi +from fastapi.datastructures import DefaultPlaceholder, DefaultType +from fastapi.openapi.constants import REF_PREFIX +from pydantic import BaseConfig, BaseModel, create_model +from pydantic.class_validators import Validator +from pydantic.fields import FieldInfo, ModelField, UndefinedType +from pydantic.schema import model_process_schema +from pydantic.utils import lenient_issubclass + +if TYPE_CHECKING: # pragma: nocover + from .routing import APIRoute + +# Cache for `create_cloned_field` +_CLONED_TYPES_CACHE: MutableMapping[ + Type[BaseModel], Type[BaseModel] +] = WeakKeyDictionary() + + +def is_body_allowed_for_status_code(status_code: Union[int, str, None]) -> bool: + if status_code is None: + return True + # Ref: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#patterned-fields-1 + if status_code in { + "default", + "1XX", + "2XX", + "3XX", + "4XX", + "5XX", + }: + return True + current_status_code = int(status_code) + return not (current_status_code < 200 or current_status_code in {204, 304}) + + +def get_model_definitions( + *, + flat_models: Set[Union[Type[BaseModel], Type[Enum]]], + model_name_map: Dict[Union[Type[BaseModel], Type[Enum]], str], +) -> Dict[str, Any]: + definitions: Dict[str, Dict[str, Any]] = {} + for model in flat_models: + m_schema, m_definitions, m_nested_models = model_process_schema( + model, model_name_map=model_name_map, ref_prefix=REF_PREFIX + ) + definitions.update(m_definitions) + model_name = model_name_map[model] + if "description" in m_schema: + m_schema["description"] = m_schema["description"].split("\f")[0] + definitions[model_name] = m_schema + return definitions + + +def get_path_param_names(path: str) -> Set[str]: + return set(re.findall("{(.*?)}", path)) + + +def create_response_field( + name: str, + type_: Type[Any], + class_validators: Optional[Dict[str, Validator]] = None, + default: Optional[Any] = None, + required: Union[bool, UndefinedType] = True, + model_config: Type[BaseConfig] = BaseConfig, + field_info: Optional[FieldInfo] = None, + alias: Optional[str] = None, +) -> ModelField: + """ + Create a new response field. Raises if type_ is invalid. + """ + class_validators = class_validators or {} + field_info = field_info or FieldInfo() + + try: + return ModelField( + name=name, + type_=type_, + class_validators=class_validators, + default=default, + required=required, + model_config=model_config, + alias=alias, + field_info=field_info, + ) + except RuntimeError: + raise fastapi.exceptions.FastAPIError( + "Invalid args for response field! Hint: " + f"check that {type_} is a valid Pydantic field type. " + "If you are using a return type annotation that is not a valid Pydantic " + "field (e.g. Union[Response, dict, None]) you can disable generating the " + "response model from the type annotation with the path operation decorator " + "parameter response_model=None. Read more: " + "https://fastapi.tiangolo.com/tutorial/response-model/" + ) from None + + +def create_cloned_field( + field: ModelField, + *, + cloned_types: Optional[MutableMapping[Type[BaseModel], Type[BaseModel]]] = None, +) -> ModelField: + # cloned_types caches already cloned types to support recursive models and improve + # performance by avoiding unecessary cloning + if cloned_types is None: + cloned_types = _CLONED_TYPES_CACHE + + original_type = field.type_ + if is_dataclass(original_type) and hasattr(original_type, "__pydantic_model__"): + original_type = original_type.__pydantic_model__ + use_type = original_type + if lenient_issubclass(original_type, BaseModel): + original_type = cast(Type[BaseModel], original_type) + use_type = cloned_types.get(original_type) + if use_type is None: + use_type = create_model(original_type.__name__, __base__=original_type) + cloned_types[original_type] = use_type + for f in original_type.__fields__.values(): + use_type.__fields__[f.name] = create_cloned_field( + f, cloned_types=cloned_types + ) + new_field = create_response_field(name=field.name, type_=use_type) + new_field.has_alias = field.has_alias + new_field.alias = field.alias + new_field.class_validators = field.class_validators + new_field.default = field.default + new_field.required = field.required + new_field.model_config = field.model_config + new_field.field_info = field.field_info + new_field.allow_none = field.allow_none + new_field.validate_always = field.validate_always + if field.sub_fields: + new_field.sub_fields = [ + create_cloned_field(sub_field, cloned_types=cloned_types) + for sub_field in field.sub_fields + ] + if field.key_field: + new_field.key_field = create_cloned_field( + field.key_field, cloned_types=cloned_types + ) + new_field.validators = field.validators + new_field.pre_validators = field.pre_validators + new_field.post_validators = field.post_validators + new_field.parse_json = field.parse_json + new_field.shape = field.shape + new_field.populate_validators() + return new_field + + +def generate_operation_id_for_path( + *, name: str, path: str, method: str +) -> str: # pragma: nocover + warnings.warn( + "fastapi.utils.generate_operation_id_for_path() was deprecated, " + "it is not used internally, and will be removed soon", + DeprecationWarning, + stacklevel=2, + ) + operation_id = name + path + operation_id = re.sub(r"\W", "_", operation_id) + operation_id = operation_id + "_" + method.lower() + return operation_id + + +def generate_unique_id(route: "APIRoute") -> str: + operation_id = route.name + route.path_format + operation_id = re.sub(r"\W", "_", operation_id) + assert route.methods + operation_id = operation_id + "_" + list(route.methods)[0].lower() + return operation_id + + +def deep_dict_update(main_dict: Dict[Any, Any], update_dict: Dict[Any, Any]) -> None: + for key, value in update_dict.items(): + if ( + key in main_dict + and isinstance(main_dict[key], dict) + and isinstance(value, dict) + ): + deep_dict_update(main_dict[key], value) + elif ( + key in main_dict + and isinstance(main_dict[key], list) + and isinstance(update_dict[key], list) + ): + main_dict[key] = main_dict[key] + update_dict[key] + else: + main_dict[key] = value + + +def get_value_or_default( + first_item: Union[DefaultPlaceholder, DefaultType], + *extra_items: Union[DefaultPlaceholder, DefaultType], +) -> Union[DefaultPlaceholder, DefaultType]: + """ + Pass items or `DefaultPlaceholder`s by descending priority. + + The first one to _not_ be a `DefaultPlaceholder` will be returned. + + Otherwise, the first item (a `DefaultPlaceholder`) will be returned. + """ + items = (first_item,) + extra_items + for item in items: + if not isinstance(item, DefaultPlaceholder): + return item + return first_item diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/websockets.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/websockets.py new file mode 100644 index 0000000..55a4ac4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/fastapi/websockets.py @@ -0,0 +1,3 @@ +from starlette.websockets import WebSocket as WebSocket # noqa +from starlette.websockets import WebSocketDisconnect as WebSocketDisconnect # noqa +from starlette.websockets import WebSocketState as WebSocketState # noqa diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11-0.16.0.dist-info/INSTALLER b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11-0.16.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11-0.16.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11-0.16.0.dist-info/METADATA b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11-0.16.0.dist-info/METADATA new file mode 100644 index 0000000..8a2f639 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11-0.16.0.dist-info/METADATA @@ -0,0 +1,202 @@ +Metadata-Version: 2.4 +Name: h11 +Version: 0.16.0 +Summary: A pure-Python, bring-your-own-I/O implementation of HTTP/1.1 +Home-page: https://github.com/python-hyper/h11 +Author: Nathaniel J. Smith +Author-email: njs@pobox.com +License: MIT +Classifier: Development Status :: 3 - Alpha +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Topic :: Internet :: WWW/HTTP +Classifier: Topic :: System :: Networking +Requires-Python: >=3.8 +License-File: LICENSE.txt +Dynamic: author +Dynamic: author-email +Dynamic: classifier +Dynamic: description +Dynamic: home-page +Dynamic: license +Dynamic: license-file +Dynamic: requires-python +Dynamic: summary + +h11 +=== + +.. image:: https://travis-ci.org/python-hyper/h11.svg?branch=master + :target: https://travis-ci.org/python-hyper/h11 + :alt: Automated test status + +.. image:: https://codecov.io/gh/python-hyper/h11/branch/master/graph/badge.svg + :target: https://codecov.io/gh/python-hyper/h11 + :alt: Test coverage + +.. image:: https://readthedocs.org/projects/h11/badge/?version=latest + :target: http://h11.readthedocs.io/en/latest/?badge=latest + :alt: Documentation Status + +This is a little HTTP/1.1 library written from scratch in Python, +heavily inspired by `hyper-h2 `_. + +It's a "bring-your-own-I/O" library; h11 contains no IO code +whatsoever. This means you can hook h11 up to your favorite network +API, and that could be anything you want: synchronous, threaded, +asynchronous, or your own implementation of `RFC 6214 +`_ -- h11 won't judge you. +(Compare this to the current state of the art, where every time a `new +network API `_ comes along then someone +gets to start over reimplementing the entire HTTP protocol from +scratch.) Cory Benfield made an `excellent blog post describing the +benefits of this approach +`_, or if you like video +then here's his `PyCon 2016 talk on the same theme +`_. + +This also means that h11 is not immediately useful out of the box: +it's a toolkit for building programs that speak HTTP, not something +that could directly replace ``requests`` or ``twisted.web`` or +whatever. But h11 makes it much easier to implement something like +``requests`` or ``twisted.web``. + +At a high level, working with h11 goes like this: + +1) First, create an ``h11.Connection`` object to track the state of a + single HTTP/1.1 connection. + +2) When you read data off the network, pass it to + ``conn.receive_data(...)``; you'll get back a list of objects + representing high-level HTTP "events". + +3) When you want to send a high-level HTTP event, create the + corresponding "event" object and pass it to ``conn.send(...)``; + this will give you back some bytes that you can then push out + through the network. + +For example, a client might instantiate and then send a +``h11.Request`` object, then zero or more ``h11.Data`` objects for the +request body (e.g., if this is a POST), and then a +``h11.EndOfMessage`` to indicate the end of the message. Then the +server would then send back a ``h11.Response``, some ``h11.Data``, and +its own ``h11.EndOfMessage``. If either side violates the protocol, +you'll get a ``h11.ProtocolError`` exception. + +h11 is suitable for implementing both servers and clients, and has a +pleasantly symmetric API: the events you send as a client are exactly +the ones that you receive as a server and vice-versa. + +`Here's an example of a tiny HTTP client +`_ + +It also has `a fine manual `_. + +FAQ +--- + +*Whyyyyy?* + +I wanted to play with HTTP in `Curio +`__ and `Trio +`__, which at the time didn't have any +HTTP libraries. So I thought, no big deal, Python has, like, a dozen +different implementations of HTTP, surely I can find one that's +reusable. I didn't find one, but I did find Cory's call-to-arms +blog-post. So I figured, well, fine, if I have to implement HTTP from +scratch, at least I can make sure no-one *else* has to ever again. + +*Should I use it?* + +Maybe. You should be aware that it's a very young project. But, it's +feature complete and has an exhaustive test-suite and complete docs, +so the next step is for people to try using it and see how it goes +:-). If you do then please let us know -- if nothing else we'll want +to talk to you before making any incompatible changes! + +*What are the features/limitations?* + +Roughly speaking, it's trying to be a robust, complete, and non-hacky +implementation of the first "chapter" of the HTTP/1.1 spec: `RFC 7230: +HTTP/1.1 Message Syntax and Routing +`_. That is, it mostly focuses on +implementing HTTP at the level of taking bytes on and off the wire, +and the headers related to that, and tries to be anal about spec +conformance. It doesn't know about higher-level concerns like URL +routing, conditional GETs, cross-origin cookie policies, or content +negotiation. But it does know how to take care of framing, +cross-version differences in keep-alive handling, and the "obsolete +line folding" rule, so you can focus your energies on the hard / +interesting parts for your application, and it tries to support the +full specification in the sense that any useful HTTP/1.1 conformant +application should be able to use h11. + +It's pure Python, and has no dependencies outside of the standard +library. + +It has a test suite with 100.0% coverage for both statements and +branches. + +Currently it supports Python 3 (testing on 3.8-3.12) and PyPy 3. +The last Python 2-compatible version was h11 0.11.x. +(Originally it had a Cython wrapper for `http-parser +`_ and a beautiful nested state +machine implemented with ``yield from`` to postprocess the output. But +I had to take these out -- the new *parser* needs fewer lines-of-code +than the old *parser wrapper*, is written in pure Python, uses no +exotic language syntax, and has more features. It's sad, really; that +old state machine was really slick. I just need a few sentences here +to mourn that.) + +I don't know how fast it is. I haven't benchmarked or profiled it yet, +so it's probably got a few pointless hot spots, and I've been trying +to err on the side of simplicity and robustness instead of +micro-optimization. But at the architectural level I tried hard to +avoid fundamentally bad decisions, e.g., I believe that all the +parsing algorithms remain linear-time even in the face of pathological +input like slowloris, and there are no byte-by-byte loops. (I also +believe that it maintains bounded memory usage in the face of +arbitrary/pathological input.) + +The whole library is ~800 lines-of-code. You can read and understand +the whole thing in less than an hour. Most of the energy invested in +this so far has been spent on trying to keep things simple by +minimizing special-cases and ad hoc state manipulation; even though it +is now quite small and simple, I'm still annoyed that I haven't +figured out how to make it even smaller and simpler. (Unfortunately, +HTTP does not lend itself to simplicity.) + +The API is ~feature complete and I don't expect the general outlines +to change much, but you can't judge an API's ergonomics until you +actually document and use it, so I'd expect some changes in the +details. + +*How do I try it?* + +.. code-block:: sh + + $ pip install h11 + $ git clone git@github.com:python-hyper/h11 + $ cd h11/examples + $ python basic-client.py + +and go from there. + +*License?* + +MIT + +*Code of conduct?* + +Contributors are requested to follow our `code of conduct +`_ in +all project spaces. diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11-0.16.0.dist-info/RECORD b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11-0.16.0.dist-info/RECORD new file mode 100644 index 0000000..334b8fa --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11-0.16.0.dist-info/RECORD @@ -0,0 +1,18 @@ +h11-0.16.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +h11-0.16.0.dist-info/METADATA,sha256=KPMmCYrAn8unm48YD5YIfIQf4kViFct7hyqcfVzRnWQ,8348 +h11-0.16.0.dist-info/RECORD,, +h11-0.16.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91 +h11-0.16.0.dist-info/licenses/LICENSE.txt,sha256=N9tbuFkm2yikJ6JYZ_ELEjIAOuob5pzLhRE4rbjm82E,1124 +h11-0.16.0.dist-info/top_level.txt,sha256=F7dC4jl3zeh8TGHEPaWJrMbeuoWbS379Gwdi-Yvdcis,4 +h11/__init__.py,sha256=iO1KzkSO42yZ6ffg-VMgbx_ZVTWGUY00nRYEWn-s3kY,1507 +h11/_abnf.py,sha256=ybixr0xsupnkA6GFAyMubuXF6Tc1lb_hF890NgCsfNc,4815 +h11/_connection.py,sha256=k9YRVf6koZqbttBW36xSWaJpWdZwa-xQVU9AHEo9DuI,26863 +h11/_events.py,sha256=I97aXoal1Wu7dkL548BANBUCkOIbe-x5CioYA9IBY14,11792 +h11/_headers.py,sha256=P7D-lBNxHwdLZPLimmYwrPG-9ZkjElvvJZJdZAgSP-4,10412 +h11/_readers.py,sha256=a4RypORUCC3d0q_kxPuBIM7jTD8iLt5X91TH0FsduN4,8590 +h11/_receivebuffer.py,sha256=xrspsdsNgWFxRfQcTXxR8RrdjRXXTK0Io5cQYWpJ1Ws,5252 +h11/_state.py,sha256=_5LG_BGR8FCcFQeBPH-TMHgm_-B-EUcWCnQof_9XjFE,13231 +h11/_util.py,sha256=LWkkjXyJaFlAy6Lt39w73UStklFT5ovcvo0TkY7RYuk,4888 +h11/_version.py,sha256=GVSsbPSPDcOuF6ptfIiXnVJoaEm3ygXbMnqlr_Giahw,686 +h11/_writers.py,sha256=oFKm6PtjeHfbj4RLX7VB7KDc1gIY53gXG3_HR9ltmTA,5081 +h11/py.typed,sha256=sow9soTwP9T_gEAQSVh7Gb8855h04Nwmhs2We-JRgZM,7 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11-0.16.0.dist-info/WHEEL b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11-0.16.0.dist-info/WHEEL new file mode 100644 index 0000000..14a883f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11-0.16.0.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: setuptools (82.0.1) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11-0.16.0.dist-info/licenses/LICENSE.txt b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11-0.16.0.dist-info/licenses/LICENSE.txt new file mode 100644 index 0000000..8f080ea --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11-0.16.0.dist-info/licenses/LICENSE.txt @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2016 Nathaniel J. Smith and other 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. diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11-0.16.0.dist-info/top_level.txt b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11-0.16.0.dist-info/top_level.txt new file mode 100644 index 0000000..0d24def --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11-0.16.0.dist-info/top_level.txt @@ -0,0 +1 @@ +h11 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/__init__.py new file mode 100644 index 0000000..989e92c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/__init__.py @@ -0,0 +1,62 @@ +# A highish-level implementation of the HTTP/1.1 wire protocol (RFC 7230), +# containing no networking code at all, loosely modelled on hyper-h2's generic +# implementation of HTTP/2 (and in particular the h2.connection.H2Connection +# class). There's still a bunch of subtle details you need to get right if you +# want to make this actually useful, because it doesn't implement all the +# semantics to check that what you're asking to write to the wire is sensible, +# but at least it gets you out of dealing with the wire itself. + +from h11._connection import Connection, NEED_DATA, PAUSED +from h11._events import ( + ConnectionClosed, + Data, + EndOfMessage, + Event, + InformationalResponse, + Request, + Response, +) +from h11._state import ( + CLIENT, + CLOSED, + DONE, + ERROR, + IDLE, + MIGHT_SWITCH_PROTOCOL, + MUST_CLOSE, + SEND_BODY, + SEND_RESPONSE, + SERVER, + SWITCHED_PROTOCOL, +) +from h11._util import LocalProtocolError, ProtocolError, RemoteProtocolError +from h11._version import __version__ + +PRODUCT_ID = "python-h11/" + __version__ + + +__all__ = ( + "Connection", + "NEED_DATA", + "PAUSED", + "ConnectionClosed", + "Data", + "EndOfMessage", + "Event", + "InformationalResponse", + "Request", + "Response", + "CLIENT", + "CLOSED", + "DONE", + "ERROR", + "IDLE", + "MUST_CLOSE", + "SEND_BODY", + "SEND_RESPONSE", + "SERVER", + "SWITCHED_PROTOCOL", + "ProtocolError", + "LocalProtocolError", + "RemoteProtocolError", +) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_abnf.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_abnf.py new file mode 100644 index 0000000..933587f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_abnf.py @@ -0,0 +1,132 @@ +# We use native strings for all the re patterns, to take advantage of string +# formatting, and then convert to bytestrings when compiling the final re +# objects. + +# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#whitespace +# OWS = *( SP / HTAB ) +# ; optional whitespace +OWS = r"[ \t]*" + +# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#rule.token.separators +# token = 1*tchar +# +# tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" +# / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" +# / DIGIT / ALPHA +# ; any VCHAR, except delimiters +token = r"[-!#$%&'*+.^_`|~0-9a-zA-Z]+" + +# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#header.fields +# field-name = token +field_name = token + +# The standard says: +# +# field-value = *( field-content / obs-fold ) +# field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] +# field-vchar = VCHAR / obs-text +# obs-fold = CRLF 1*( SP / HTAB ) +# ; obsolete line folding +# ; see Section 3.2.4 +# +# https://tools.ietf.org/html/rfc5234#appendix-B.1 +# +# VCHAR = %x21-7E +# ; visible (printing) characters +# +# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#rule.quoted-string +# obs-text = %x80-FF +# +# However, the standard definition of field-content is WRONG! It disallows +# fields containing a single visible character surrounded by whitespace, +# e.g. "foo a bar". +# +# See: https://www.rfc-editor.org/errata_search.php?rfc=7230&eid=4189 +# +# So our definition of field_content attempts to fix it up... +# +# Also, we allow lots of control characters, because apparently people assume +# that they're legal in practice (e.g., google analytics makes cookies with +# \x01 in them!): +# https://github.com/python-hyper/h11/issues/57 +# We still don't allow NUL or whitespace, because those are often treated as +# meta-characters and letting them through can lead to nasty issues like SSRF. +vchar = r"[\x21-\x7e]" +vchar_or_obs_text = r"[^\x00\s]" +field_vchar = vchar_or_obs_text +field_content = r"{field_vchar}+(?:[ \t]+{field_vchar}+)*".format(**globals()) + +# We handle obs-fold at a different level, and our fixed-up field_content +# already grows to swallow the whole value, so ? instead of * +field_value = r"({field_content})?".format(**globals()) + +# header-field = field-name ":" OWS field-value OWS +header_field = ( + r"(?P{field_name})" + r":" + r"{OWS}" + r"(?P{field_value})" + r"{OWS}".format(**globals()) +) + +# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#request.line +# +# request-line = method SP request-target SP HTTP-version CRLF +# method = token +# HTTP-version = HTTP-name "/" DIGIT "." DIGIT +# HTTP-name = %x48.54.54.50 ; "HTTP", case-sensitive +# +# request-target is complicated (see RFC 7230 sec 5.3) -- could be path, full +# URL, host+port (for connect), or even "*", but in any case we are guaranteed +# that it contists of the visible printing characters. +method = token +request_target = r"{vchar}+".format(**globals()) +http_version = r"HTTP/(?P[0-9]\.[0-9])" +request_line = ( + r"(?P{method})" + r" " + r"(?P{request_target})" + r" " + r"{http_version}".format(**globals()) +) + +# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#status.line +# +# status-line = HTTP-version SP status-code SP reason-phrase CRLF +# status-code = 3DIGIT +# reason-phrase = *( HTAB / SP / VCHAR / obs-text ) +status_code = r"[0-9]{3}" +reason_phrase = r"([ \t]|{vchar_or_obs_text})*".format(**globals()) +status_line = ( + r"{http_version}" + r" " + r"(?P{status_code})" + # However, there are apparently a few too many servers out there that just + # leave out the reason phrase: + # https://github.com/scrapy/scrapy/issues/345#issuecomment-281756036 + # https://github.com/seanmonstar/httparse/issues/29 + # so make it optional. ?: is a non-capturing group. + r"(?: (?P{reason_phrase}))?".format(**globals()) +) + +HEXDIG = r"[0-9A-Fa-f]" +# Actually +# +# chunk-size = 1*HEXDIG +# +# but we impose an upper-limit to avoid ridiculosity. len(str(2**64)) == 20 +chunk_size = r"({HEXDIG}){{1,20}}".format(**globals()) +# Actually +# +# chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-val ] ) +# +# but we aren't parsing the things so we don't really care. +chunk_ext = r";.*" +chunk_header = ( + r"(?P{chunk_size})" + r"(?P{chunk_ext})?" + r"{OWS}\r\n".format( + **globals() + ) # Even though the specification does not allow for extra whitespaces, + # we are lenient with trailing whitespaces because some servers on the wild use it. +) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_connection.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_connection.py new file mode 100644 index 0000000..e37d82a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_connection.py @@ -0,0 +1,659 @@ +# This contains the main Connection class. Everything in h11 revolves around +# this. +from typing import ( + Any, + Callable, + cast, + Dict, + List, + Optional, + overload, + Tuple, + Type, + Union, +) + +from ._events import ( + ConnectionClosed, + Data, + EndOfMessage, + Event, + InformationalResponse, + Request, + Response, +) +from ._headers import get_comma_header, has_expect_100_continue, set_comma_header +from ._readers import READERS, ReadersType +from ._receivebuffer import ReceiveBuffer +from ._state import ( + _SWITCH_CONNECT, + _SWITCH_UPGRADE, + CLIENT, + ConnectionState, + DONE, + ERROR, + MIGHT_SWITCH_PROTOCOL, + SEND_BODY, + SERVER, + SWITCHED_PROTOCOL, +) +from ._util import ( # Import the internal things we need + LocalProtocolError, + RemoteProtocolError, + Sentinel, +) +from ._writers import WRITERS, WritersType + +# Everything in __all__ gets re-exported as part of the h11 public API. +__all__ = ["Connection", "NEED_DATA", "PAUSED"] + + +class NEED_DATA(Sentinel, metaclass=Sentinel): + pass + + +class PAUSED(Sentinel, metaclass=Sentinel): + pass + + +# If we ever have this much buffered without it making a complete parseable +# event, we error out. The only time we really buffer is when reading the +# request/response line + headers together, so this is effectively the limit on +# the size of that. +# +# Some precedents for defaults: +# - node.js: 80 * 1024 +# - tomcat: 8 * 1024 +# - IIS: 16 * 1024 +# - Apache: <8 KiB per line> +DEFAULT_MAX_INCOMPLETE_EVENT_SIZE = 16 * 1024 + + +# RFC 7230's rules for connection lifecycles: +# - If either side says they want to close the connection, then the connection +# must close. +# - HTTP/1.1 defaults to keep-alive unless someone says Connection: close +# - HTTP/1.0 defaults to close unless both sides say Connection: keep-alive +# (and even this is a mess -- e.g. if you're implementing a proxy then +# sending Connection: keep-alive is forbidden). +# +# We simplify life by simply not supporting keep-alive with HTTP/1.0 peers. So +# our rule is: +# - If someone says Connection: close, we will close +# - If someone uses HTTP/1.0, we will close. +def _keep_alive(event: Union[Request, Response]) -> bool: + connection = get_comma_header(event.headers, b"connection") + if b"close" in connection: + return False + if getattr(event, "http_version", b"1.1") < b"1.1": + return False + return True + + +def _body_framing( + request_method: bytes, event: Union[Request, Response] +) -> Tuple[str, Union[Tuple[()], Tuple[int]]]: + # Called when we enter SEND_BODY to figure out framing information for + # this body. + # + # These are the only two events that can trigger a SEND_BODY state: + assert type(event) in (Request, Response) + # Returns one of: + # + # ("content-length", count) + # ("chunked", ()) + # ("http/1.0", ()) + # + # which are (lookup key, *args) for constructing body reader/writer + # objects. + # + # Reference: https://tools.ietf.org/html/rfc7230#section-3.3.3 + # + # Step 1: some responses always have an empty body, regardless of what the + # headers say. + if type(event) is Response: + if ( + event.status_code in (204, 304) + or request_method == b"HEAD" + or (request_method == b"CONNECT" and 200 <= event.status_code < 300) + ): + return ("content-length", (0,)) + # Section 3.3.3 also lists another case -- responses with status_code + # < 200. For us these are InformationalResponses, not Responses, so + # they can't get into this function in the first place. + assert event.status_code >= 200 + + # Step 2: check for Transfer-Encoding (T-E beats C-L): + transfer_encodings = get_comma_header(event.headers, b"transfer-encoding") + if transfer_encodings: + assert transfer_encodings == [b"chunked"] + return ("chunked", ()) + + # Step 3: check for Content-Length + content_lengths = get_comma_header(event.headers, b"content-length") + if content_lengths: + return ("content-length", (int(content_lengths[0]),)) + + # Step 4: no applicable headers; fallback/default depends on type + if type(event) is Request: + return ("content-length", (0,)) + else: + return ("http/1.0", ()) + + +################################################################ +# +# The main Connection class +# +################################################################ + + +class Connection: + """An object encapsulating the state of an HTTP connection. + + Args: + our_role: If you're implementing a client, pass :data:`h11.CLIENT`. If + you're implementing a server, pass :data:`h11.SERVER`. + + max_incomplete_event_size (int): + The maximum number of bytes we're willing to buffer of an + incomplete event. In practice this mostly sets a limit on the + maximum size of the request/response line + headers. If this is + exceeded, then :meth:`next_event` will raise + :exc:`RemoteProtocolError`. + + """ + + def __init__( + self, + our_role: Type[Sentinel], + max_incomplete_event_size: int = DEFAULT_MAX_INCOMPLETE_EVENT_SIZE, + ) -> None: + self._max_incomplete_event_size = max_incomplete_event_size + # State and role tracking + if our_role not in (CLIENT, SERVER): + raise ValueError(f"expected CLIENT or SERVER, not {our_role!r}") + self.our_role = our_role + self.their_role: Type[Sentinel] + if our_role is CLIENT: + self.their_role = SERVER + else: + self.their_role = CLIENT + self._cstate = ConnectionState() + + # Callables for converting data->events or vice-versa given the + # current state + self._writer = self._get_io_object(self.our_role, None, WRITERS) + self._reader = self._get_io_object(self.their_role, None, READERS) + + # Holds any unprocessed received data + self._receive_buffer = ReceiveBuffer() + # If this is true, then it indicates that the incoming connection was + # closed *after* the end of whatever's in self._receive_buffer: + self._receive_buffer_closed = False + + # Extra bits of state that don't fit into the state machine. + # + # These two are only used to interpret framing headers for figuring + # out how to read/write response bodies. their_http_version is also + # made available as a convenient public API. + self.their_http_version: Optional[bytes] = None + self._request_method: Optional[bytes] = None + # This is pure flow-control and doesn't at all affect the set of legal + # transitions, so no need to bother ConnectionState with it: + self.client_is_waiting_for_100_continue = False + + @property + def states(self) -> Dict[Type[Sentinel], Type[Sentinel]]: + """A dictionary like:: + + {CLIENT: , SERVER: } + + See :ref:`state-machine` for details. + + """ + return dict(self._cstate.states) + + @property + def our_state(self) -> Type[Sentinel]: + """The current state of whichever role we are playing. See + :ref:`state-machine` for details. + """ + return self._cstate.states[self.our_role] + + @property + def their_state(self) -> Type[Sentinel]: + """The current state of whichever role we are NOT playing. See + :ref:`state-machine` for details. + """ + return self._cstate.states[self.their_role] + + @property + def they_are_waiting_for_100_continue(self) -> bool: + return self.their_role is CLIENT and self.client_is_waiting_for_100_continue + + def start_next_cycle(self) -> None: + """Attempt to reset our connection state for a new request/response + cycle. + + If both client and server are in :data:`DONE` state, then resets them + both to :data:`IDLE` state in preparation for a new request/response + cycle on this same connection. Otherwise, raises a + :exc:`LocalProtocolError`. + + See :ref:`keepalive-and-pipelining`. + + """ + old_states = dict(self._cstate.states) + self._cstate.start_next_cycle() + self._request_method = None + # self.their_http_version gets left alone, since it presumably lasts + # beyond a single request/response cycle + assert not self.client_is_waiting_for_100_continue + self._respond_to_state_changes(old_states) + + def _process_error(self, role: Type[Sentinel]) -> None: + old_states = dict(self._cstate.states) + self._cstate.process_error(role) + self._respond_to_state_changes(old_states) + + def _server_switch_event(self, event: Event) -> Optional[Type[Sentinel]]: + if type(event) is InformationalResponse and event.status_code == 101: + return _SWITCH_UPGRADE + if type(event) is Response: + if ( + _SWITCH_CONNECT in self._cstate.pending_switch_proposals + and 200 <= event.status_code < 300 + ): + return _SWITCH_CONNECT + return None + + # All events go through here + def _process_event(self, role: Type[Sentinel], event: Event) -> None: + # First, pass the event through the state machine to make sure it + # succeeds. + old_states = dict(self._cstate.states) + if role is CLIENT and type(event) is Request: + if event.method == b"CONNECT": + self._cstate.process_client_switch_proposal(_SWITCH_CONNECT) + if get_comma_header(event.headers, b"upgrade"): + self._cstate.process_client_switch_proposal(_SWITCH_UPGRADE) + server_switch_event = None + if role is SERVER: + server_switch_event = self._server_switch_event(event) + self._cstate.process_event(role, type(event), server_switch_event) + + # Then perform the updates triggered by it. + + if type(event) is Request: + self._request_method = event.method + + if role is self.their_role and type(event) in ( + Request, + Response, + InformationalResponse, + ): + event = cast(Union[Request, Response, InformationalResponse], event) + self.their_http_version = event.http_version + + # Keep alive handling + # + # RFC 7230 doesn't really say what one should do if Connection: close + # shows up on a 1xx InformationalResponse. I think the idea is that + # this is not supposed to happen. In any case, if it does happen, we + # ignore it. + if type(event) in (Request, Response) and not _keep_alive( + cast(Union[Request, Response], event) + ): + self._cstate.process_keep_alive_disabled() + + # 100-continue + if type(event) is Request and has_expect_100_continue(event): + self.client_is_waiting_for_100_continue = True + if type(event) in (InformationalResponse, Response): + self.client_is_waiting_for_100_continue = False + if role is CLIENT and type(event) in (Data, EndOfMessage): + self.client_is_waiting_for_100_continue = False + + self._respond_to_state_changes(old_states, event) + + def _get_io_object( + self, + role: Type[Sentinel], + event: Optional[Event], + io_dict: Union[ReadersType, WritersType], + ) -> Optional[Callable[..., Any]]: + # event may be None; it's only used when entering SEND_BODY + state = self._cstate.states[role] + if state is SEND_BODY: + # Special case: the io_dict has a dict of reader/writer factories + # that depend on the request/response framing. + framing_type, args = _body_framing( + cast(bytes, self._request_method), cast(Union[Request, Response], event) + ) + return io_dict[SEND_BODY][framing_type](*args) # type: ignore[index] + else: + # General case: the io_dict just has the appropriate reader/writer + # for this state + return io_dict.get((role, state)) # type: ignore[return-value] + + # This must be called after any action that might have caused + # self._cstate.states to change. + def _respond_to_state_changes( + self, + old_states: Dict[Type[Sentinel], Type[Sentinel]], + event: Optional[Event] = None, + ) -> None: + # Update reader/writer + if self.our_state != old_states[self.our_role]: + self._writer = self._get_io_object(self.our_role, event, WRITERS) + if self.their_state != old_states[self.their_role]: + self._reader = self._get_io_object(self.their_role, event, READERS) + + @property + def trailing_data(self) -> Tuple[bytes, bool]: + """Data that has been received, but not yet processed, represented as + a tuple with two elements, where the first is a byte-string containing + the unprocessed data itself, and the second is a bool that is True if + the receive connection was closed. + + See :ref:`switching-protocols` for discussion of why you'd want this. + """ + return (bytes(self._receive_buffer), self._receive_buffer_closed) + + def receive_data(self, data: bytes) -> None: + """Add data to our internal receive buffer. + + This does not actually do any processing on the data, just stores + it. To trigger processing, you have to call :meth:`next_event`. + + Args: + data (:term:`bytes-like object`): + The new data that was just received. + + Special case: If *data* is an empty byte-string like ``b""``, + then this indicates that the remote side has closed the + connection (end of file). Normally this is convenient, because + standard Python APIs like :meth:`file.read` or + :meth:`socket.recv` use ``b""`` to indicate end-of-file, while + other failures to read are indicated using other mechanisms + like raising :exc:`TimeoutError`. When using such an API you + can just blindly pass through whatever you get from ``read`` + to :meth:`receive_data`, and everything will work. + + But, if you have an API where reading an empty string is a + valid non-EOF condition, then you need to be aware of this and + make sure to check for such strings and avoid passing them to + :meth:`receive_data`. + + Returns: + Nothing, but after calling this you should call :meth:`next_event` + to parse the newly received data. + + Raises: + RuntimeError: + Raised if you pass an empty *data*, indicating EOF, and then + pass a non-empty *data*, indicating more data that somehow + arrived after the EOF. + + (Calling ``receive_data(b"")`` multiple times is fine, + and equivalent to calling it once.) + + """ + if data: + if self._receive_buffer_closed: + raise RuntimeError("received close, then received more data?") + self._receive_buffer += data + else: + self._receive_buffer_closed = True + + def _extract_next_receive_event( + self, + ) -> Union[Event, Type[NEED_DATA], Type[PAUSED]]: + state = self.their_state + # We don't pause immediately when they enter DONE, because even in + # DONE state we can still process a ConnectionClosed() event. But + # if we have data in our buffer, then we definitely aren't getting + # a ConnectionClosed() immediately and we need to pause. + if state is DONE and self._receive_buffer: + return PAUSED + if state is MIGHT_SWITCH_PROTOCOL or state is SWITCHED_PROTOCOL: + return PAUSED + assert self._reader is not None + event = self._reader(self._receive_buffer) + if event is None: + if not self._receive_buffer and self._receive_buffer_closed: + # In some unusual cases (basically just HTTP/1.0 bodies), EOF + # triggers an actual protocol event; in that case, we want to + # return that event, and then the state will change and we'll + # get called again to generate the actual ConnectionClosed(). + if hasattr(self._reader, "read_eof"): + event = self._reader.read_eof() + else: + event = ConnectionClosed() + if event is None: + event = NEED_DATA + return event # type: ignore[no-any-return] + + def next_event(self) -> Union[Event, Type[NEED_DATA], Type[PAUSED]]: + """Parse the next event out of our receive buffer, update our internal + state, and return it. + + This is a mutating operation -- think of it like calling :func:`next` + on an iterator. + + Returns: + : One of three things: + + 1) An event object -- see :ref:`events`. + + 2) The special constant :data:`NEED_DATA`, which indicates that + you need to read more data from your socket and pass it to + :meth:`receive_data` before this method will be able to return + any more events. + + 3) The special constant :data:`PAUSED`, which indicates that we + are not in a state where we can process incoming data (usually + because the peer has finished their part of the current + request/response cycle, and you have not yet called + :meth:`start_next_cycle`). See :ref:`flow-control` for details. + + Raises: + RemoteProtocolError: + The peer has misbehaved. You should close the connection + (possibly after sending some kind of 4xx response). + + Once this method returns :class:`ConnectionClosed` once, then all + subsequent calls will also return :class:`ConnectionClosed`. + + If this method raises any exception besides :exc:`RemoteProtocolError` + then that's a bug -- if it happens please file a bug report! + + If this method raises any exception then it also sets + :attr:`Connection.their_state` to :data:`ERROR` -- see + :ref:`error-handling` for discussion. + + """ + + if self.their_state is ERROR: + raise RemoteProtocolError("Can't receive data when peer state is ERROR") + try: + event = self._extract_next_receive_event() + if event not in [NEED_DATA, PAUSED]: + self._process_event(self.their_role, cast(Event, event)) + if event is NEED_DATA: + if len(self._receive_buffer) > self._max_incomplete_event_size: + # 431 is "Request header fields too large" which is pretty + # much the only situation where we can get here + raise RemoteProtocolError( + "Receive buffer too long", error_status_hint=431 + ) + if self._receive_buffer_closed: + # We're still trying to complete some event, but that's + # never going to happen because no more data is coming + raise RemoteProtocolError("peer unexpectedly closed connection") + return event + except BaseException as exc: + self._process_error(self.their_role) + if isinstance(exc, LocalProtocolError): + exc._reraise_as_remote_protocol_error() + else: + raise + + @overload + def send(self, event: ConnectionClosed) -> None: + ... + + @overload + def send( + self, event: Union[Request, InformationalResponse, Response, Data, EndOfMessage] + ) -> bytes: + ... + + @overload + def send(self, event: Event) -> Optional[bytes]: + ... + + def send(self, event: Event) -> Optional[bytes]: + """Convert a high-level event into bytes that can be sent to the peer, + while updating our internal state machine. + + Args: + event: The :ref:`event ` to send. + + Returns: + If ``type(event) is ConnectionClosed``, then returns + ``None``. Otherwise, returns a :term:`bytes-like object`. + + Raises: + LocalProtocolError: + Sending this event at this time would violate our + understanding of the HTTP/1.1 protocol. + + If this method raises any exception then it also sets + :attr:`Connection.our_state` to :data:`ERROR` -- see + :ref:`error-handling` for discussion. + + """ + data_list = self.send_with_data_passthrough(event) + if data_list is None: + return None + else: + return b"".join(data_list) + + def send_with_data_passthrough(self, event: Event) -> Optional[List[bytes]]: + """Identical to :meth:`send`, except that in situations where + :meth:`send` returns a single :term:`bytes-like object`, this instead + returns a list of them -- and when sending a :class:`Data` event, this + list is guaranteed to contain the exact object you passed in as + :attr:`Data.data`. See :ref:`sendfile` for discussion. + + """ + if self.our_state is ERROR: + raise LocalProtocolError("Can't send data when our state is ERROR") + try: + if type(event) is Response: + event = self._clean_up_response_headers_for_sending(event) + # We want to call _process_event before calling the writer, + # because if someone tries to do something invalid then this will + # give a sensible error message, while our writers all just assume + # they will only receive valid events. But, _process_event might + # change self._writer. So we have to do a little dance: + writer = self._writer + self._process_event(self.our_role, event) + if type(event) is ConnectionClosed: + return None + else: + # In any situation where writer is None, process_event should + # have raised ProtocolError + assert writer is not None + data_list: List[bytes] = [] + writer(event, data_list.append) + return data_list + except: + self._process_error(self.our_role) + raise + + def send_failed(self) -> None: + """Notify the state machine that we failed to send the data it gave + us. + + This causes :attr:`Connection.our_state` to immediately become + :data:`ERROR` -- see :ref:`error-handling` for discussion. + + """ + self._process_error(self.our_role) + + # When sending a Response, we take responsibility for a few things: + # + # - Sometimes you MUST set Connection: close. We take care of those + # times. (You can also set it yourself if you want, and if you do then + # we'll respect that and close the connection at the right time. But you + # don't have to worry about that unless you want to.) + # + # - The user has to set Content-Length if they want it. Otherwise, for + # responses that have bodies (e.g. not HEAD), then we will automatically + # select the right mechanism for streaming a body of unknown length, + # which depends on depending on the peer's HTTP version. + # + # This function's *only* responsibility is making sure headers are set up + # right -- everything downstream just looks at the headers. There are no + # side channels. + def _clean_up_response_headers_for_sending(self, response: Response) -> Response: + assert type(response) is Response + + headers = response.headers + need_close = False + + # HEAD requests need some special handling: they always act like they + # have Content-Length: 0, and that's how _body_framing treats + # them. But their headers are supposed to match what we would send if + # the request was a GET. (Technically there is one deviation allowed: + # we're allowed to leave out the framing headers -- see + # https://tools.ietf.org/html/rfc7231#section-4.3.2 . But it's just as + # easy to get them right.) + method_for_choosing_headers = cast(bytes, self._request_method) + if method_for_choosing_headers == b"HEAD": + method_for_choosing_headers = b"GET" + framing_type, _ = _body_framing(method_for_choosing_headers, response) + if framing_type in ("chunked", "http/1.0"): + # This response has a body of unknown length. + # If our peer is HTTP/1.1, we use Transfer-Encoding: chunked + # If our peer is HTTP/1.0, we use no framing headers, and close the + # connection afterwards. + # + # Make sure to clear Content-Length (in principle user could have + # set both and then we ignored Content-Length b/c + # Transfer-Encoding overwrote it -- this would be naughty of them, + # but the HTTP spec says that if our peer does this then we have + # to fix it instead of erroring out, so we'll accord the user the + # same respect). + headers = set_comma_header(headers, b"content-length", []) + if self.their_http_version is None or self.their_http_version < b"1.1": + # Either we never got a valid request and are sending back an + # error (their_http_version is None), so we assume the worst; + # or else we did get a valid HTTP/1.0 request, so we know that + # they don't understand chunked encoding. + headers = set_comma_header(headers, b"transfer-encoding", []) + # This is actually redundant ATM, since currently we + # unconditionally disable keep-alive when talking to HTTP/1.0 + # peers. But let's be defensive just in case we add + # Connection: keep-alive support later: + if self._request_method != b"HEAD": + need_close = True + else: + headers = set_comma_header(headers, b"transfer-encoding", [b"chunked"]) + + if not self._cstate.keep_alive or need_close: + # Make sure Connection: close is set + connection = set(get_comma_header(headers, b"connection")) + connection.discard(b"keep-alive") + connection.add(b"close") + headers = set_comma_header(headers, b"connection", sorted(connection)) + + return Response( + headers=headers, + status_code=response.status_code, + http_version=response.http_version, + reason=response.reason, + ) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_events.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_events.py new file mode 100644 index 0000000..ca1c3ad --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_events.py @@ -0,0 +1,369 @@ +# High level events that make up HTTP/1.1 conversations. Loosely inspired by +# the corresponding events in hyper-h2: +# +# http://python-hyper.org/h2/en/stable/api.html#events +# +# Don't subclass these. Stuff will break. + +import re +from abc import ABC +from dataclasses import dataclass +from typing import List, Tuple, Union + +from ._abnf import method, request_target +from ._headers import Headers, normalize_and_validate +from ._util import bytesify, LocalProtocolError, validate + +# Everything in __all__ gets re-exported as part of the h11 public API. +__all__ = [ + "Event", + "Request", + "InformationalResponse", + "Response", + "Data", + "EndOfMessage", + "ConnectionClosed", +] + +method_re = re.compile(method.encode("ascii")) +request_target_re = re.compile(request_target.encode("ascii")) + + +class Event(ABC): + """ + Base class for h11 events. + """ + + __slots__ = () + + +@dataclass(init=False, frozen=True) +class Request(Event): + """The beginning of an HTTP request. + + Fields: + + .. attribute:: method + + An HTTP method, e.g. ``b"GET"`` or ``b"POST"``. Always a byte + string. :term:`Bytes-like objects ` and native + strings containing only ascii characters will be automatically + converted to byte strings. + + .. attribute:: target + + The target of an HTTP request, e.g. ``b"/index.html"``, or one of the + more exotic formats described in `RFC 7320, section 5.3 + `_. Always a byte + string. :term:`Bytes-like objects ` and native + strings containing only ascii characters will be automatically + converted to byte strings. + + .. attribute:: headers + + Request headers, represented as a list of (name, value) pairs. See + :ref:`the header normalization rules ` for details. + + .. attribute:: http_version + + The HTTP protocol version, represented as a byte string like + ``b"1.1"``. See :ref:`the HTTP version normalization rules + ` for details. + + """ + + __slots__ = ("method", "headers", "target", "http_version") + + method: bytes + headers: Headers + target: bytes + http_version: bytes + + def __init__( + self, + *, + method: Union[bytes, str], + headers: Union[Headers, List[Tuple[bytes, bytes]], List[Tuple[str, str]]], + target: Union[bytes, str], + http_version: Union[bytes, str] = b"1.1", + _parsed: bool = False, + ) -> None: + super().__init__() + if isinstance(headers, Headers): + object.__setattr__(self, "headers", headers) + else: + object.__setattr__( + self, "headers", normalize_and_validate(headers, _parsed=_parsed) + ) + if not _parsed: + object.__setattr__(self, "method", bytesify(method)) + object.__setattr__(self, "target", bytesify(target)) + object.__setattr__(self, "http_version", bytesify(http_version)) + else: + object.__setattr__(self, "method", method) + object.__setattr__(self, "target", target) + object.__setattr__(self, "http_version", http_version) + + # "A server MUST respond with a 400 (Bad Request) status code to any + # HTTP/1.1 request message that lacks a Host header field and to any + # request message that contains more than one Host header field or a + # Host header field with an invalid field-value." + # -- https://tools.ietf.org/html/rfc7230#section-5.4 + host_count = 0 + for name, value in self.headers: + if name == b"host": + host_count += 1 + if self.http_version == b"1.1" and host_count == 0: + raise LocalProtocolError("Missing mandatory Host: header") + if host_count > 1: + raise LocalProtocolError("Found multiple Host: headers") + + validate(method_re, self.method, "Illegal method characters") + validate(request_target_re, self.target, "Illegal target characters") + + # This is an unhashable type. + __hash__ = None # type: ignore + + +@dataclass(init=False, frozen=True) +class _ResponseBase(Event): + __slots__ = ("headers", "http_version", "reason", "status_code") + + headers: Headers + http_version: bytes + reason: bytes + status_code: int + + def __init__( + self, + *, + headers: Union[Headers, List[Tuple[bytes, bytes]], List[Tuple[str, str]]], + status_code: int, + http_version: Union[bytes, str] = b"1.1", + reason: Union[bytes, str] = b"", + _parsed: bool = False, + ) -> None: + super().__init__() + if isinstance(headers, Headers): + object.__setattr__(self, "headers", headers) + else: + object.__setattr__( + self, "headers", normalize_and_validate(headers, _parsed=_parsed) + ) + if not _parsed: + object.__setattr__(self, "reason", bytesify(reason)) + object.__setattr__(self, "http_version", bytesify(http_version)) + if not isinstance(status_code, int): + raise LocalProtocolError("status code must be integer") + # Because IntEnum objects are instances of int, but aren't + # duck-compatible (sigh), see gh-72. + object.__setattr__(self, "status_code", int(status_code)) + else: + object.__setattr__(self, "reason", reason) + object.__setattr__(self, "http_version", http_version) + object.__setattr__(self, "status_code", status_code) + + self.__post_init__() + + def __post_init__(self) -> None: + pass + + # This is an unhashable type. + __hash__ = None # type: ignore + + +@dataclass(init=False, frozen=True) +class InformationalResponse(_ResponseBase): + """An HTTP informational response. + + Fields: + + .. attribute:: status_code + + The status code of this response, as an integer. For an + :class:`InformationalResponse`, this is always in the range [100, + 200). + + .. attribute:: headers + + Request headers, represented as a list of (name, value) pairs. See + :ref:`the header normalization rules ` for + details. + + .. attribute:: http_version + + The HTTP protocol version, represented as a byte string like + ``b"1.1"``. See :ref:`the HTTP version normalization rules + ` for details. + + .. attribute:: reason + + The reason phrase of this response, as a byte string. For example: + ``b"OK"``, or ``b"Not Found"``. + + """ + + def __post_init__(self) -> None: + if not (100 <= self.status_code < 200): + raise LocalProtocolError( + "InformationalResponse status_code should be in range " + "[100, 200), not {}".format(self.status_code) + ) + + # This is an unhashable type. + __hash__ = None # type: ignore + + +@dataclass(init=False, frozen=True) +class Response(_ResponseBase): + """The beginning of an HTTP response. + + Fields: + + .. attribute:: status_code + + The status code of this response, as an integer. For an + :class:`Response`, this is always in the range [200, + 1000). + + .. attribute:: headers + + Request headers, represented as a list of (name, value) pairs. See + :ref:`the header normalization rules ` for details. + + .. attribute:: http_version + + The HTTP protocol version, represented as a byte string like + ``b"1.1"``. See :ref:`the HTTP version normalization rules + ` for details. + + .. attribute:: reason + + The reason phrase of this response, as a byte string. For example: + ``b"OK"``, or ``b"Not Found"``. + + """ + + def __post_init__(self) -> None: + if not (200 <= self.status_code < 1000): + raise LocalProtocolError( + "Response status_code should be in range [200, 1000), not {}".format( + self.status_code + ) + ) + + # This is an unhashable type. + __hash__ = None # type: ignore + + +@dataclass(init=False, frozen=True) +class Data(Event): + """Part of an HTTP message body. + + Fields: + + .. attribute:: data + + A :term:`bytes-like object` containing part of a message body. Or, if + using the ``combine=False`` argument to :meth:`Connection.send`, then + any object that your socket writing code knows what to do with, and for + which calling :func:`len` returns the number of bytes that will be + written -- see :ref:`sendfile` for details. + + .. attribute:: chunk_start + + A marker that indicates whether this data object is from the start of a + chunked transfer encoding chunk. This field is ignored when when a Data + event is provided to :meth:`Connection.send`: it is only valid on + events emitted from :meth:`Connection.next_event`. You probably + shouldn't use this attribute at all; see + :ref:`chunk-delimiters-are-bad` for details. + + .. attribute:: chunk_end + + A marker that indicates whether this data object is the last for a + given chunked transfer encoding chunk. This field is ignored when when + a Data event is provided to :meth:`Connection.send`: it is only valid + on events emitted from :meth:`Connection.next_event`. You probably + shouldn't use this attribute at all; see + :ref:`chunk-delimiters-are-bad` for details. + + """ + + __slots__ = ("data", "chunk_start", "chunk_end") + + data: bytes + chunk_start: bool + chunk_end: bool + + def __init__( + self, data: bytes, chunk_start: bool = False, chunk_end: bool = False + ) -> None: + object.__setattr__(self, "data", data) + object.__setattr__(self, "chunk_start", chunk_start) + object.__setattr__(self, "chunk_end", chunk_end) + + # This is an unhashable type. + __hash__ = None # type: ignore + + +# XX FIXME: "A recipient MUST ignore (or consider as an error) any fields that +# are forbidden to be sent in a trailer, since processing them as if they were +# present in the header section might bypass external security filters." +# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#chunked.trailer.part +# Unfortunately, the list of forbidden fields is long and vague :-/ +@dataclass(init=False, frozen=True) +class EndOfMessage(Event): + """The end of an HTTP message. + + Fields: + + .. attribute:: headers + + Default value: ``[]`` + + Any trailing headers attached to this message, represented as a list of + (name, value) pairs. See :ref:`the header normalization rules + ` for details. + + Must be empty unless ``Transfer-Encoding: chunked`` is in use. + + """ + + __slots__ = ("headers",) + + headers: Headers + + def __init__( + self, + *, + headers: Union[ + Headers, List[Tuple[bytes, bytes]], List[Tuple[str, str]], None + ] = None, + _parsed: bool = False, + ) -> None: + super().__init__() + if headers is None: + headers = Headers([]) + elif not isinstance(headers, Headers): + headers = normalize_and_validate(headers, _parsed=_parsed) + + object.__setattr__(self, "headers", headers) + + # This is an unhashable type. + __hash__ = None # type: ignore + + +@dataclass(frozen=True) +class ConnectionClosed(Event): + """This event indicates that the sender has closed their outgoing + connection. + + Note that this does not necessarily mean that they can't *receive* further + data, because TCP connections are composed to two one-way channels which + can be closed independently. See :ref:`closing` for details. + + No fields. + """ + + pass diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_headers.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_headers.py new file mode 100644 index 0000000..31da3e2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_headers.py @@ -0,0 +1,282 @@ +import re +from typing import AnyStr, cast, List, overload, Sequence, Tuple, TYPE_CHECKING, Union + +from ._abnf import field_name, field_value +from ._util import bytesify, LocalProtocolError, validate + +if TYPE_CHECKING: + from ._events import Request + +try: + from typing import Literal +except ImportError: + from typing_extensions import Literal # type: ignore + +CONTENT_LENGTH_MAX_DIGITS = 20 # allow up to 1 billion TB - 1 + + +# Facts +# ----- +# +# Headers are: +# keys: case-insensitive ascii +# values: mixture of ascii and raw bytes +# +# "Historically, HTTP has allowed field content with text in the ISO-8859-1 +# charset [ISO-8859-1], supporting other charsets only through use of +# [RFC2047] encoding. In practice, most HTTP header field values use only a +# subset of the US-ASCII charset [USASCII]. Newly defined header fields SHOULD +# limit their field values to US-ASCII octets. A recipient SHOULD treat other +# octets in field content (obs-text) as opaque data." +# And it deprecates all non-ascii values +# +# Leading/trailing whitespace in header names is forbidden +# +# Values get leading/trailing whitespace stripped +# +# Content-Disposition actually needs to contain unicode semantically; to +# accomplish this it has a terrifically weird way of encoding the filename +# itself as ascii (and even this still has lots of cross-browser +# incompatibilities) +# +# Order is important: +# "a proxy MUST NOT change the order of these field values when forwarding a +# message" +# (and there are several headers where the order indicates a preference) +# +# Multiple occurences of the same header: +# "A sender MUST NOT generate multiple header fields with the same field name +# in a message unless either the entire field value for that header field is +# defined as a comma-separated list [or the header is Set-Cookie which gets a +# special exception]" - RFC 7230. (cookies are in RFC 6265) +# +# So every header aside from Set-Cookie can be merged by b", ".join if it +# occurs repeatedly. But, of course, they can't necessarily be split by +# .split(b","), because quoting. +# +# Given all this mess (case insensitive, duplicates allowed, order is +# important, ...), there doesn't appear to be any standard way to handle +# headers in Python -- they're almost like dicts, but... actually just +# aren't. For now we punt and just use a super simple representation: headers +# are a list of pairs +# +# [(name1, value1), (name2, value2), ...] +# +# where all entries are bytestrings, names are lowercase and have no +# leading/trailing whitespace, and values are bytestrings with no +# leading/trailing whitespace. Searching and updating are done via naive O(n) +# methods. +# +# Maybe a dict-of-lists would be better? + +_content_length_re = re.compile(rb"[0-9]+") +_field_name_re = re.compile(field_name.encode("ascii")) +_field_value_re = re.compile(field_value.encode("ascii")) + + +class Headers(Sequence[Tuple[bytes, bytes]]): + """ + A list-like interface that allows iterating over headers as byte-pairs + of (lowercased-name, value). + + Internally we actually store the representation as three-tuples, + including both the raw original casing, in order to preserve casing + over-the-wire, and the lowercased name, for case-insensitive comparisions. + + r = Request( + method="GET", + target="/", + headers=[("Host", "example.org"), ("Connection", "keep-alive")], + http_version="1.1", + ) + assert r.headers == [ + (b"host", b"example.org"), + (b"connection", b"keep-alive") + ] + assert r.headers.raw_items() == [ + (b"Host", b"example.org"), + (b"Connection", b"keep-alive") + ] + """ + + __slots__ = "_full_items" + + def __init__(self, full_items: List[Tuple[bytes, bytes, bytes]]) -> None: + self._full_items = full_items + + def __bool__(self) -> bool: + return bool(self._full_items) + + def __eq__(self, other: object) -> bool: + return list(self) == list(other) # type: ignore + + def __len__(self) -> int: + return len(self._full_items) + + def __repr__(self) -> str: + return "" % repr(list(self)) + + def __getitem__(self, idx: int) -> Tuple[bytes, bytes]: # type: ignore[override] + _, name, value = self._full_items[idx] + return (name, value) + + def raw_items(self) -> List[Tuple[bytes, bytes]]: + return [(raw_name, value) for raw_name, _, value in self._full_items] + + +HeaderTypes = Union[ + List[Tuple[bytes, bytes]], + List[Tuple[bytes, str]], + List[Tuple[str, bytes]], + List[Tuple[str, str]], +] + + +@overload +def normalize_and_validate(headers: Headers, _parsed: Literal[True]) -> Headers: + ... + + +@overload +def normalize_and_validate(headers: HeaderTypes, _parsed: Literal[False]) -> Headers: + ... + + +@overload +def normalize_and_validate( + headers: Union[Headers, HeaderTypes], _parsed: bool = False +) -> Headers: + ... + + +def normalize_and_validate( + headers: Union[Headers, HeaderTypes], _parsed: bool = False +) -> Headers: + new_headers = [] + seen_content_length = None + saw_transfer_encoding = False + for name, value in headers: + # For headers coming out of the parser, we can safely skip some steps, + # because it always returns bytes and has already run these regexes + # over the data: + if not _parsed: + name = bytesify(name) + value = bytesify(value) + validate(_field_name_re, name, "Illegal header name {!r}", name) + validate(_field_value_re, value, "Illegal header value {!r}", value) + assert isinstance(name, bytes) + assert isinstance(value, bytes) + + raw_name = name + name = name.lower() + if name == b"content-length": + lengths = {length.strip() for length in value.split(b",")} + if len(lengths) != 1: + raise LocalProtocolError("conflicting Content-Length headers") + value = lengths.pop() + validate(_content_length_re, value, "bad Content-Length") + if len(value) > CONTENT_LENGTH_MAX_DIGITS: + raise LocalProtocolError("bad Content-Length") + if seen_content_length is None: + seen_content_length = value + new_headers.append((raw_name, name, value)) + elif seen_content_length != value: + raise LocalProtocolError("conflicting Content-Length headers") + elif name == b"transfer-encoding": + # "A server that receives a request message with a transfer coding + # it does not understand SHOULD respond with 501 (Not + # Implemented)." + # https://tools.ietf.org/html/rfc7230#section-3.3.1 + if saw_transfer_encoding: + raise LocalProtocolError( + "multiple Transfer-Encoding headers", error_status_hint=501 + ) + # "All transfer-coding names are case-insensitive" + # -- https://tools.ietf.org/html/rfc7230#section-4 + value = value.lower() + if value != b"chunked": + raise LocalProtocolError( + "Only Transfer-Encoding: chunked is supported", + error_status_hint=501, + ) + saw_transfer_encoding = True + new_headers.append((raw_name, name, value)) + else: + new_headers.append((raw_name, name, value)) + return Headers(new_headers) + + +def get_comma_header(headers: Headers, name: bytes) -> List[bytes]: + # Should only be used for headers whose value is a list of + # comma-separated, case-insensitive values. + # + # The header name `name` is expected to be lower-case bytes. + # + # Connection: meets these criteria (including cast insensitivity). + # + # Content-Length: technically is just a single value (1*DIGIT), but the + # standard makes reference to implementations that do multiple values, and + # using this doesn't hurt. Ditto, case insensitivity doesn't things either + # way. + # + # Transfer-Encoding: is more complex (allows for quoted strings), so + # splitting on , is actually wrong. For example, this is legal: + # + # Transfer-Encoding: foo; options="1,2", chunked + # + # and should be parsed as + # + # foo; options="1,2" + # chunked + # + # but this naive function will parse it as + # + # foo; options="1 + # 2" + # chunked + # + # However, this is okay because the only thing we are going to do with + # any Transfer-Encoding is reject ones that aren't just "chunked", so + # both of these will be treated the same anyway. + # + # Expect: the only legal value is the literal string + # "100-continue". Splitting on commas is harmless. Case insensitive. + # + out: List[bytes] = [] + for _, found_name, found_raw_value in headers._full_items: + if found_name == name: + found_raw_value = found_raw_value.lower() + for found_split_value in found_raw_value.split(b","): + found_split_value = found_split_value.strip() + if found_split_value: + out.append(found_split_value) + return out + + +def set_comma_header(headers: Headers, name: bytes, new_values: List[bytes]) -> Headers: + # The header name `name` is expected to be lower-case bytes. + # + # Note that when we store the header we use title casing for the header + # names, in order to match the conventional HTTP header style. + # + # Simply calling `.title()` is a blunt approach, but it's correct + # here given the cases where we're using `set_comma_header`... + # + # Connection, Content-Length, Transfer-Encoding. + new_headers: List[Tuple[bytes, bytes]] = [] + for found_raw_name, found_name, found_raw_value in headers._full_items: + if found_name != name: + new_headers.append((found_raw_name, found_raw_value)) + for new_value in new_values: + new_headers.append((name.title(), new_value)) + return normalize_and_validate(new_headers) + + +def has_expect_100_continue(request: "Request") -> bool: + # https://tools.ietf.org/html/rfc7231#section-5.1.1 + # "A server that receives a 100-continue expectation in an HTTP/1.0 request + # MUST ignore that expectation." + if request.http_version < b"1.1": + return False + expect = get_comma_header(request.headers, b"expect") + return b"100-continue" in expect diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_readers.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_readers.py new file mode 100644 index 0000000..576804c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_readers.py @@ -0,0 +1,250 @@ +# Code to read HTTP data +# +# Strategy: each reader is a callable which takes a ReceiveBuffer object, and +# either: +# 1) consumes some of it and returns an Event +# 2) raises a LocalProtocolError (for consistency -- e.g. we call validate() +# and it might raise a LocalProtocolError, so simpler just to always use +# this) +# 3) returns None, meaning "I need more data" +# +# If they have a .read_eof attribute, then this will be called if an EOF is +# received -- but this is optional. Either way, the actual ConnectionClosed +# event will be generated afterwards. +# +# READERS is a dict describing how to pick a reader. It maps states to either: +# - a reader +# - or, for body readers, a dict of per-framing reader factories + +import re +from typing import Any, Callable, Dict, Iterable, NoReturn, Optional, Tuple, Type, Union + +from ._abnf import chunk_header, header_field, request_line, status_line +from ._events import Data, EndOfMessage, InformationalResponse, Request, Response +from ._receivebuffer import ReceiveBuffer +from ._state import ( + CLIENT, + CLOSED, + DONE, + IDLE, + MUST_CLOSE, + SEND_BODY, + SEND_RESPONSE, + SERVER, +) +from ._util import LocalProtocolError, RemoteProtocolError, Sentinel, validate + +__all__ = ["READERS"] + +header_field_re = re.compile(header_field.encode("ascii")) +obs_fold_re = re.compile(rb"[ \t]+") + + +def _obsolete_line_fold(lines: Iterable[bytes]) -> Iterable[bytes]: + it = iter(lines) + last: Optional[bytes] = None + for line in it: + match = obs_fold_re.match(line) + if match: + if last is None: + raise LocalProtocolError("continuation line at start of headers") + if not isinstance(last, bytearray): + # Cast to a mutable type, avoiding copy on append to ensure O(n) time + last = bytearray(last) + last += b" " + last += line[match.end() :] + else: + if last is not None: + yield last + last = line + if last is not None: + yield last + + +def _decode_header_lines( + lines: Iterable[bytes], +) -> Iterable[Tuple[bytes, bytes]]: + for line in _obsolete_line_fold(lines): + matches = validate(header_field_re, line, "illegal header line: {!r}", line) + yield (matches["field_name"], matches["field_value"]) + + +request_line_re = re.compile(request_line.encode("ascii")) + + +def maybe_read_from_IDLE_client(buf: ReceiveBuffer) -> Optional[Request]: + lines = buf.maybe_extract_lines() + if lines is None: + if buf.is_next_line_obviously_invalid_request_line(): + raise LocalProtocolError("illegal request line") + return None + if not lines: + raise LocalProtocolError("no request line received") + matches = validate( + request_line_re, lines[0], "illegal request line: {!r}", lines[0] + ) + return Request( + headers=list(_decode_header_lines(lines[1:])), _parsed=True, **matches + ) + + +status_line_re = re.compile(status_line.encode("ascii")) + + +def maybe_read_from_SEND_RESPONSE_server( + buf: ReceiveBuffer, +) -> Union[InformationalResponse, Response, None]: + lines = buf.maybe_extract_lines() + if lines is None: + if buf.is_next_line_obviously_invalid_request_line(): + raise LocalProtocolError("illegal request line") + return None + if not lines: + raise LocalProtocolError("no response line received") + matches = validate(status_line_re, lines[0], "illegal status line: {!r}", lines[0]) + http_version = ( + b"1.1" if matches["http_version"] is None else matches["http_version"] + ) + reason = b"" if matches["reason"] is None else matches["reason"] + status_code = int(matches["status_code"]) + class_: Union[Type[InformationalResponse], Type[Response]] = ( + InformationalResponse if status_code < 200 else Response + ) + return class_( + headers=list(_decode_header_lines(lines[1:])), + _parsed=True, + status_code=status_code, + reason=reason, + http_version=http_version, + ) + + +class ContentLengthReader: + def __init__(self, length: int) -> None: + self._length = length + self._remaining = length + + def __call__(self, buf: ReceiveBuffer) -> Union[Data, EndOfMessage, None]: + if self._remaining == 0: + return EndOfMessage() + data = buf.maybe_extract_at_most(self._remaining) + if data is None: + return None + self._remaining -= len(data) + return Data(data=data) + + def read_eof(self) -> NoReturn: + raise RemoteProtocolError( + "peer closed connection without sending complete message body " + "(received {} bytes, expected {})".format( + self._length - self._remaining, self._length + ) + ) + + +chunk_header_re = re.compile(chunk_header.encode("ascii")) + + +class ChunkedReader: + def __init__(self) -> None: + self._bytes_in_chunk = 0 + # After reading a chunk, we have to throw away the trailing \r\n. + # This tracks the bytes that we need to match and throw away. + self._bytes_to_discard = b"" + self._reading_trailer = False + + def __call__(self, buf: ReceiveBuffer) -> Union[Data, EndOfMessage, None]: + if self._reading_trailer: + lines = buf.maybe_extract_lines() + if lines is None: + return None + return EndOfMessage(headers=list(_decode_header_lines(lines))) + if self._bytes_to_discard: + data = buf.maybe_extract_at_most(len(self._bytes_to_discard)) + if data is None: + return None + if data != self._bytes_to_discard[: len(data)]: + raise LocalProtocolError( + f"malformed chunk footer: {data!r} (expected {self._bytes_to_discard!r})" + ) + self._bytes_to_discard = self._bytes_to_discard[len(data) :] + if self._bytes_to_discard: + return None + # else, fall through and read some more + assert self._bytes_to_discard == b"" + if self._bytes_in_chunk == 0: + # We need to refill our chunk count + chunk_header = buf.maybe_extract_next_line() + if chunk_header is None: + return None + matches = validate( + chunk_header_re, + chunk_header, + "illegal chunk header: {!r}", + chunk_header, + ) + # XX FIXME: we discard chunk extensions. Does anyone care? + self._bytes_in_chunk = int(matches["chunk_size"], base=16) + if self._bytes_in_chunk == 0: + self._reading_trailer = True + return self(buf) + chunk_start = True + else: + chunk_start = False + assert self._bytes_in_chunk > 0 + data = buf.maybe_extract_at_most(self._bytes_in_chunk) + if data is None: + return None + self._bytes_in_chunk -= len(data) + if self._bytes_in_chunk == 0: + self._bytes_to_discard = b"\r\n" + chunk_end = True + else: + chunk_end = False + return Data(data=data, chunk_start=chunk_start, chunk_end=chunk_end) + + def read_eof(self) -> NoReturn: + raise RemoteProtocolError( + "peer closed connection without sending complete message body " + "(incomplete chunked read)" + ) + + +class Http10Reader: + def __call__(self, buf: ReceiveBuffer) -> Optional[Data]: + data = buf.maybe_extract_at_most(999999999) + if data is None: + return None + return Data(data=data) + + def read_eof(self) -> EndOfMessage: + return EndOfMessage() + + +def expect_nothing(buf: ReceiveBuffer) -> None: + if buf: + raise LocalProtocolError("Got data when expecting EOF") + return None + + +ReadersType = Dict[ + Union[Type[Sentinel], Tuple[Type[Sentinel], Type[Sentinel]]], + Union[Callable[..., Any], Dict[str, Callable[..., Any]]], +] + +READERS: ReadersType = { + (CLIENT, IDLE): maybe_read_from_IDLE_client, + (SERVER, IDLE): maybe_read_from_SEND_RESPONSE_server, + (SERVER, SEND_RESPONSE): maybe_read_from_SEND_RESPONSE_server, + (CLIENT, DONE): expect_nothing, + (CLIENT, MUST_CLOSE): expect_nothing, + (CLIENT, CLOSED): expect_nothing, + (SERVER, DONE): expect_nothing, + (SERVER, MUST_CLOSE): expect_nothing, + (SERVER, CLOSED): expect_nothing, + SEND_BODY: { + "chunked": ChunkedReader, + "content-length": ContentLengthReader, + "http/1.0": Http10Reader, + }, +} diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_receivebuffer.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_receivebuffer.py new file mode 100644 index 0000000..e5c4e08 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_receivebuffer.py @@ -0,0 +1,153 @@ +import re +import sys +from typing import List, Optional, Union + +__all__ = ["ReceiveBuffer"] + + +# Operations we want to support: +# - find next \r\n or \r\n\r\n (\n or \n\n are also acceptable), +# or wait until there is one +# - read at-most-N bytes +# Goals: +# - on average, do this fast +# - worst case, do this in O(n) where n is the number of bytes processed +# Plan: +# - store bytearray, offset, how far we've searched for a separator token +# - use the how-far-we've-searched data to avoid rescanning +# - while doing a stream of uninterrupted processing, advance offset instead +# of constantly copying +# WARNING: +# - I haven't benchmarked or profiled any of this yet. +# +# Note that starting in Python 3.4, deleting the initial n bytes from a +# bytearray is amortized O(n), thanks to some excellent work by Antoine +# Martin: +# +# https://bugs.python.org/issue19087 +# +# This means that if we only supported 3.4+, we could get rid of the code here +# involving self._start and self.compress, because it's doing exactly the same +# thing that bytearray now does internally. +# +# BUT unfortunately, we still support 2.7, and reading short segments out of a +# long buffer MUST be O(bytes read) to avoid DoS issues, so we can't actually +# delete this code. Yet: +# +# https://pythonclock.org/ +# +# (Two things to double-check first though: make sure PyPy also has the +# optimization, and benchmark to make sure it's a win, since we do have a +# slightly clever thing where we delay calling compress() until we've +# processed a whole event, which could in theory be slightly more efficient +# than the internal bytearray support.) +blank_line_regex = re.compile(b"\n\r?\n", re.MULTILINE) + + +class ReceiveBuffer: + def __init__(self) -> None: + self._data = bytearray() + self._next_line_search = 0 + self._multiple_lines_search = 0 + + def __iadd__(self, byteslike: Union[bytes, bytearray]) -> "ReceiveBuffer": + self._data += byteslike + return self + + def __bool__(self) -> bool: + return bool(len(self)) + + def __len__(self) -> int: + return len(self._data) + + # for @property unprocessed_data + def __bytes__(self) -> bytes: + return bytes(self._data) + + def _extract(self, count: int) -> bytearray: + # extracting an initial slice of the data buffer and return it + out = self._data[:count] + del self._data[:count] + + self._next_line_search = 0 + self._multiple_lines_search = 0 + + return out + + def maybe_extract_at_most(self, count: int) -> Optional[bytearray]: + """ + Extract a fixed number of bytes from the buffer. + """ + out = self._data[:count] + if not out: + return None + + return self._extract(count) + + def maybe_extract_next_line(self) -> Optional[bytearray]: + """ + Extract the first line, if it is completed in the buffer. + """ + # Only search in buffer space that we've not already looked at. + search_start_index = max(0, self._next_line_search - 1) + partial_idx = self._data.find(b"\r\n", search_start_index) + + if partial_idx == -1: + self._next_line_search = len(self._data) + return None + + # + 2 is to compensate len(b"\r\n") + idx = partial_idx + 2 + + return self._extract(idx) + + def maybe_extract_lines(self) -> Optional[List[bytearray]]: + """ + Extract everything up to the first blank line, and return a list of lines. + """ + # Handle the case where we have an immediate empty line. + if self._data[:1] == b"\n": + self._extract(1) + return [] + + if self._data[:2] == b"\r\n": + self._extract(2) + return [] + + # Only search in buffer space that we've not already looked at. + match = blank_line_regex.search(self._data, self._multiple_lines_search) + if match is None: + self._multiple_lines_search = max(0, len(self._data) - 2) + return None + + # Truncate the buffer and return it. + idx = match.span(0)[-1] + out = self._extract(idx) + lines = out.split(b"\n") + + for line in lines: + if line.endswith(b"\r"): + del line[-1] + + assert lines[-2] == lines[-1] == b"" + + del lines[-2:] + + return lines + + # In theory we should wait until `\r\n` before starting to validate + # incoming data. However it's interesting to detect (very) invalid data + # early given they might not even contain `\r\n` at all (hence only + # timeout will get rid of them). + # This is not a 100% effective detection but more of a cheap sanity check + # allowing for early abort in some useful cases. + # This is especially interesting when peer is messing up with HTTPS and + # sent us a TLS stream where we were expecting plain HTTP given all + # versions of TLS so far start handshake with a 0x16 message type code. + def is_next_line_obviously_invalid_request_line(self) -> bool: + try: + # HTTP header line must not contain non-printable characters + # and should not start with a space + return self._data[0] < 0x21 + except IndexError: + return False diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_state.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_state.py new file mode 100644 index 0000000..3ad444b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_state.py @@ -0,0 +1,365 @@ +################################################################ +# The core state machine +################################################################ +# +# Rule 1: everything that affects the state machine and state transitions must +# live here in this file. As much as possible goes into the table-based +# representation, but for the bits that don't quite fit, the actual code and +# state must nonetheless live here. +# +# Rule 2: this file does not know about what role we're playing; it only knows +# about HTTP request/response cycles in the abstract. This ensures that we +# don't cheat and apply different rules to local and remote parties. +# +# +# Theory of operation +# =================== +# +# Possibly the simplest way to think about this is that we actually have 5 +# different state machines here. Yes, 5. These are: +# +# 1) The client state, with its complicated automaton (see the docs) +# 2) The server state, with its complicated automaton (see the docs) +# 3) The keep-alive state, with possible states {True, False} +# 4) The SWITCH_CONNECT state, with possible states {False, True} +# 5) The SWITCH_UPGRADE state, with possible states {False, True} +# +# For (3)-(5), the first state listed is the initial state. +# +# (1)-(3) are stored explicitly in member variables. The last +# two are stored implicitly in the pending_switch_proposals set as: +# (state of 4) == (_SWITCH_CONNECT in pending_switch_proposals) +# (state of 5) == (_SWITCH_UPGRADE in pending_switch_proposals) +# +# And each of these machines has two different kinds of transitions: +# +# a) Event-triggered +# b) State-triggered +# +# Event triggered is the obvious thing that you'd think it is: some event +# happens, and if it's the right event at the right time then a transition +# happens. But there are somewhat complicated rules for which machines can +# "see" which events. (As a rule of thumb, if a machine "sees" an event, this +# means two things: the event can affect the machine, and if the machine is +# not in a state where it expects that event then it's an error.) These rules +# are: +# +# 1) The client machine sees all h11.events objects emitted by the client. +# +# 2) The server machine sees all h11.events objects emitted by the server. +# +# It also sees the client's Request event. +# +# And sometimes, server events are annotated with a _SWITCH_* event. For +# example, we can have a (Response, _SWITCH_CONNECT) event, which is +# different from a regular Response event. +# +# 3) The keep-alive machine sees the process_keep_alive_disabled() event +# (which is derived from Request/Response events), and this event +# transitions it from True -> False, or from False -> False. There's no way +# to transition back. +# +# 4&5) The _SWITCH_* machines transition from False->True when we get a +# Request that proposes the relevant type of switch (via +# process_client_switch_proposals), and they go from True->False when we +# get a Response that has no _SWITCH_* annotation. +# +# So that's event-triggered transitions. +# +# State-triggered transitions are less standard. What they do here is couple +# the machines together. The way this works is, when certain *joint* +# configurations of states are achieved, then we automatically transition to a +# new *joint* state. So, for example, if we're ever in a joint state with +# +# client: DONE +# keep-alive: False +# +# then the client state immediately transitions to: +# +# client: MUST_CLOSE +# +# This is fundamentally different from an event-based transition, because it +# doesn't matter how we arrived at the {client: DONE, keep-alive: False} state +# -- maybe the client transitioned SEND_BODY -> DONE, or keep-alive +# transitioned True -> False. Either way, once this precondition is satisfied, +# this transition is immediately triggered. +# +# What if two conflicting state-based transitions get enabled at the same +# time? In practice there's only one case where this arises (client DONE -> +# MIGHT_SWITCH_PROTOCOL versus DONE -> MUST_CLOSE), and we resolve it by +# explicitly prioritizing the DONE -> MIGHT_SWITCH_PROTOCOL transition. +# +# Implementation +# -------------- +# +# The event-triggered transitions for the server and client machines are all +# stored explicitly in a table. Ditto for the state-triggered transitions that +# involve just the server and client state. +# +# The transitions for the other machines, and the state-triggered transitions +# that involve the other machines, are written out as explicit Python code. +# +# It'd be nice if there were some cleaner way to do all this. This isn't +# *too* terrible, but I feel like it could probably be better. +# +# WARNING +# ------- +# +# The script that generates the state machine diagrams for the docs knows how +# to read out the EVENT_TRIGGERED_TRANSITIONS and STATE_TRIGGERED_TRANSITIONS +# tables. But it can't automatically read the transitions that are written +# directly in Python code. So if you touch those, you need to also update the +# script to keep it in sync! +from typing import cast, Dict, Optional, Set, Tuple, Type, Union + +from ._events import * +from ._util import LocalProtocolError, Sentinel + +# Everything in __all__ gets re-exported as part of the h11 public API. +__all__ = [ + "CLIENT", + "SERVER", + "IDLE", + "SEND_RESPONSE", + "SEND_BODY", + "DONE", + "MUST_CLOSE", + "CLOSED", + "MIGHT_SWITCH_PROTOCOL", + "SWITCHED_PROTOCOL", + "ERROR", +] + + +class CLIENT(Sentinel, metaclass=Sentinel): + pass + + +class SERVER(Sentinel, metaclass=Sentinel): + pass + + +# States +class IDLE(Sentinel, metaclass=Sentinel): + pass + + +class SEND_RESPONSE(Sentinel, metaclass=Sentinel): + pass + + +class SEND_BODY(Sentinel, metaclass=Sentinel): + pass + + +class DONE(Sentinel, metaclass=Sentinel): + pass + + +class MUST_CLOSE(Sentinel, metaclass=Sentinel): + pass + + +class CLOSED(Sentinel, metaclass=Sentinel): + pass + + +class ERROR(Sentinel, metaclass=Sentinel): + pass + + +# Switch types +class MIGHT_SWITCH_PROTOCOL(Sentinel, metaclass=Sentinel): + pass + + +class SWITCHED_PROTOCOL(Sentinel, metaclass=Sentinel): + pass + + +class _SWITCH_UPGRADE(Sentinel, metaclass=Sentinel): + pass + + +class _SWITCH_CONNECT(Sentinel, metaclass=Sentinel): + pass + + +EventTransitionType = Dict[ + Type[Sentinel], + Dict[ + Type[Sentinel], + Dict[Union[Type[Event], Tuple[Type[Event], Type[Sentinel]]], Type[Sentinel]], + ], +] + +EVENT_TRIGGERED_TRANSITIONS: EventTransitionType = { + CLIENT: { + IDLE: {Request: SEND_BODY, ConnectionClosed: CLOSED}, + SEND_BODY: {Data: SEND_BODY, EndOfMessage: DONE}, + DONE: {ConnectionClosed: CLOSED}, + MUST_CLOSE: {ConnectionClosed: CLOSED}, + CLOSED: {ConnectionClosed: CLOSED}, + MIGHT_SWITCH_PROTOCOL: {}, + SWITCHED_PROTOCOL: {}, + ERROR: {}, + }, + SERVER: { + IDLE: { + ConnectionClosed: CLOSED, + Response: SEND_BODY, + # Special case: server sees client Request events, in this form + (Request, CLIENT): SEND_RESPONSE, + }, + SEND_RESPONSE: { + InformationalResponse: SEND_RESPONSE, + Response: SEND_BODY, + (InformationalResponse, _SWITCH_UPGRADE): SWITCHED_PROTOCOL, + (Response, _SWITCH_CONNECT): SWITCHED_PROTOCOL, + }, + SEND_BODY: {Data: SEND_BODY, EndOfMessage: DONE}, + DONE: {ConnectionClosed: CLOSED}, + MUST_CLOSE: {ConnectionClosed: CLOSED}, + CLOSED: {ConnectionClosed: CLOSED}, + SWITCHED_PROTOCOL: {}, + ERROR: {}, + }, +} + +StateTransitionType = Dict[ + Tuple[Type[Sentinel], Type[Sentinel]], Dict[Type[Sentinel], Type[Sentinel]] +] + +# NB: there are also some special-case state-triggered transitions hard-coded +# into _fire_state_triggered_transitions below. +STATE_TRIGGERED_TRANSITIONS: StateTransitionType = { + # (Client state, Server state) -> new states + # Protocol negotiation + (MIGHT_SWITCH_PROTOCOL, SWITCHED_PROTOCOL): {CLIENT: SWITCHED_PROTOCOL}, + # Socket shutdown + (CLOSED, DONE): {SERVER: MUST_CLOSE}, + (CLOSED, IDLE): {SERVER: MUST_CLOSE}, + (ERROR, DONE): {SERVER: MUST_CLOSE}, + (DONE, CLOSED): {CLIENT: MUST_CLOSE}, + (IDLE, CLOSED): {CLIENT: MUST_CLOSE}, + (DONE, ERROR): {CLIENT: MUST_CLOSE}, +} + + +class ConnectionState: + def __init__(self) -> None: + # Extra bits of state that don't quite fit into the state model. + + # If this is False then it enables the automatic DONE -> MUST_CLOSE + # transition. Don't set this directly; call .keep_alive_disabled() + self.keep_alive = True + + # This is a subset of {UPGRADE, CONNECT}, containing the proposals + # made by the client for switching protocols. + self.pending_switch_proposals: Set[Type[Sentinel]] = set() + + self.states: Dict[Type[Sentinel], Type[Sentinel]] = {CLIENT: IDLE, SERVER: IDLE} + + def process_error(self, role: Type[Sentinel]) -> None: + self.states[role] = ERROR + self._fire_state_triggered_transitions() + + def process_keep_alive_disabled(self) -> None: + self.keep_alive = False + self._fire_state_triggered_transitions() + + def process_client_switch_proposal(self, switch_event: Type[Sentinel]) -> None: + self.pending_switch_proposals.add(switch_event) + self._fire_state_triggered_transitions() + + def process_event( + self, + role: Type[Sentinel], + event_type: Type[Event], + server_switch_event: Optional[Type[Sentinel]] = None, + ) -> None: + _event_type: Union[Type[Event], Tuple[Type[Event], Type[Sentinel]]] = event_type + if server_switch_event is not None: + assert role is SERVER + if server_switch_event not in self.pending_switch_proposals: + raise LocalProtocolError( + "Received server _SWITCH_UPGRADE event without a pending proposal" + ) + _event_type = (event_type, server_switch_event) + if server_switch_event is None and _event_type is Response: + self.pending_switch_proposals = set() + self._fire_event_triggered_transitions(role, _event_type) + # Special case: the server state does get to see Request + # events. + if _event_type is Request: + assert role is CLIENT + self._fire_event_triggered_transitions(SERVER, (Request, CLIENT)) + self._fire_state_triggered_transitions() + + def _fire_event_triggered_transitions( + self, + role: Type[Sentinel], + event_type: Union[Type[Event], Tuple[Type[Event], Type[Sentinel]]], + ) -> None: + state = self.states[role] + try: + new_state = EVENT_TRIGGERED_TRANSITIONS[role][state][event_type] + except KeyError: + event_type = cast(Type[Event], event_type) + raise LocalProtocolError( + "can't handle event type {} when role={} and state={}".format( + event_type.__name__, role, self.states[role] + ) + ) from None + self.states[role] = new_state + + def _fire_state_triggered_transitions(self) -> None: + # We apply these rules repeatedly until converging on a fixed point + while True: + start_states = dict(self.states) + + # It could happen that both these special-case transitions are + # enabled at the same time: + # + # DONE -> MIGHT_SWITCH_PROTOCOL + # DONE -> MUST_CLOSE + # + # For example, this will always be true of a HTTP/1.0 client + # requesting CONNECT. If this happens, the protocol switch takes + # priority. From there the client will either go to + # SWITCHED_PROTOCOL, in which case it's none of our business when + # they close the connection, or else the server will deny the + # request, in which case the client will go back to DONE and then + # from there to MUST_CLOSE. + if self.pending_switch_proposals: + if self.states[CLIENT] is DONE: + self.states[CLIENT] = MIGHT_SWITCH_PROTOCOL + + if not self.pending_switch_proposals: + if self.states[CLIENT] is MIGHT_SWITCH_PROTOCOL: + self.states[CLIENT] = DONE + + if not self.keep_alive: + for role in (CLIENT, SERVER): + if self.states[role] is DONE: + self.states[role] = MUST_CLOSE + + # Tabular state-triggered transitions + joint_state = (self.states[CLIENT], self.states[SERVER]) + changes = STATE_TRIGGERED_TRANSITIONS.get(joint_state, {}) + self.states.update(changes) + + if self.states == start_states: + # Fixed point reached + return + + def start_next_cycle(self) -> None: + if self.states != {CLIENT: DONE, SERVER: DONE}: + raise LocalProtocolError( + f"not in a reusable state. self.states={self.states}" + ) + # Can't reach DONE/DONE with any of these active, but still, let's be + # sure. + assert self.keep_alive + assert not self.pending_switch_proposals + self.states = {CLIENT: IDLE, SERVER: IDLE} diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_util.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_util.py new file mode 100644 index 0000000..6718445 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_util.py @@ -0,0 +1,135 @@ +from typing import Any, Dict, NoReturn, Pattern, Tuple, Type, TypeVar, Union + +__all__ = [ + "ProtocolError", + "LocalProtocolError", + "RemoteProtocolError", + "validate", + "bytesify", +] + + +class ProtocolError(Exception): + """Exception indicating a violation of the HTTP/1.1 protocol. + + This as an abstract base class, with two concrete base classes: + :exc:`LocalProtocolError`, which indicates that you tried to do something + that HTTP/1.1 says is illegal, and :exc:`RemoteProtocolError`, which + indicates that the remote peer tried to do something that HTTP/1.1 says is + illegal. See :ref:`error-handling` for details. + + In addition to the normal :exc:`Exception` features, it has one attribute: + + .. attribute:: error_status_hint + + This gives a suggestion as to what status code a server might use if + this error occurred as part of a request. + + For a :exc:`RemoteProtocolError`, this is useful as a suggestion for + how you might want to respond to a misbehaving peer, if you're + implementing a server. + + For a :exc:`LocalProtocolError`, this can be taken as a suggestion for + how your peer might have responded to *you* if h11 had allowed you to + continue. + + The default is 400 Bad Request, a generic catch-all for protocol + violations. + + """ + + def __init__(self, msg: str, error_status_hint: int = 400) -> None: + if type(self) is ProtocolError: + raise TypeError("tried to directly instantiate ProtocolError") + Exception.__init__(self, msg) + self.error_status_hint = error_status_hint + + +# Strategy: there are a number of public APIs where a LocalProtocolError can +# be raised (send(), all the different event constructors, ...), and only one +# public API where RemoteProtocolError can be raised +# (receive_data()). Therefore we always raise LocalProtocolError internally, +# and then receive_data will translate this into a RemoteProtocolError. +# +# Internally: +# LocalProtocolError is the generic "ProtocolError". +# Externally: +# LocalProtocolError is for local errors and RemoteProtocolError is for +# remote errors. +class LocalProtocolError(ProtocolError): + def _reraise_as_remote_protocol_error(self) -> NoReturn: + # After catching a LocalProtocolError, use this method to re-raise it + # as a RemoteProtocolError. This method must be called from inside an + # except: block. + # + # An easy way to get an equivalent RemoteProtocolError is just to + # modify 'self' in place. + self.__class__ = RemoteProtocolError # type: ignore + # But the re-raising is somewhat non-trivial -- you might think that + # now that we've modified the in-flight exception object, that just + # doing 'raise' to re-raise it would be enough. But it turns out that + # this doesn't work, because Python tracks the exception type + # (exc_info[0]) separately from the exception object (exc_info[1]), + # and we only modified the latter. So we really do need to re-raise + # the new type explicitly. + # On py3, the traceback is part of the exception object, so our + # in-place modification preserved it and we can just re-raise: + raise self + + +class RemoteProtocolError(ProtocolError): + pass + + +def validate( + regex: Pattern[bytes], data: bytes, msg: str = "malformed data", *format_args: Any +) -> Dict[str, bytes]: + match = regex.fullmatch(data) + if not match: + if format_args: + msg = msg.format(*format_args) + raise LocalProtocolError(msg) + return match.groupdict() + + +# Sentinel values +# +# - Inherit identity-based comparison and hashing from object +# - Have a nice repr +# - Have a *bonus property*: type(sentinel) is sentinel +# +# The bonus property is useful if you want to take the return value from +# next_event() and do some sort of dispatch based on type(event). + +_T_Sentinel = TypeVar("_T_Sentinel", bound="Sentinel") + + +class Sentinel(type): + def __new__( + cls: Type[_T_Sentinel], + name: str, + bases: Tuple[type, ...], + namespace: Dict[str, Any], + **kwds: Any + ) -> _T_Sentinel: + assert bases == (Sentinel,) + v = super().__new__(cls, name, bases, namespace, **kwds) + v.__class__ = v # type: ignore + return v + + def __repr__(self) -> str: + return self.__name__ + + +# Used for methods, request targets, HTTP versions, header names, and header +# values. Accepts ascii-strings, or bytes/bytearray/memoryview/..., and always +# returns bytes. +def bytesify(s: Union[bytes, bytearray, memoryview, int, str]) -> bytes: + # Fast-path: + if type(s) is bytes: + return s + if isinstance(s, str): + s = s.encode("ascii") + if isinstance(s, int): + raise TypeError("expected bytes-like object, not int") + return bytes(s) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_version.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_version.py new file mode 100644 index 0000000..76e7327 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_version.py @@ -0,0 +1,16 @@ +# This file must be kept very simple, because it is consumed from several +# places -- it is imported by h11/__init__.py, execfile'd by setup.py, etc. + +# We use a simple scheme: +# 1.0.0 -> 1.0.0+dev -> 1.1.0 -> 1.1.0+dev +# where the +dev versions are never released into the wild, they're just what +# we stick into the VCS in between releases. +# +# This is compatible with PEP 440: +# http://legacy.python.org/dev/peps/pep-0440/ +# via the use of the "local suffix" "+dev", which is disallowed on index +# servers and causes 1.0.0+dev to sort after plain 1.0.0, which is what we +# want. (Contrast with the special suffix 1.0.0.dev, which sorts *before* +# 1.0.0.) + +__version__ = "0.16.0" diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_writers.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_writers.py new file mode 100644 index 0000000..939cdb9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/_writers.py @@ -0,0 +1,145 @@ +# Code to read HTTP data +# +# Strategy: each writer takes an event + a write-some-bytes function, which is +# calls. +# +# WRITERS is a dict describing how to pick a reader. It maps states to either: +# - a writer +# - or, for body writers, a dict of framin-dependent writer factories + +from typing import Any, Callable, Dict, List, Tuple, Type, Union + +from ._events import Data, EndOfMessage, Event, InformationalResponse, Request, Response +from ._headers import Headers +from ._state import CLIENT, IDLE, SEND_BODY, SEND_RESPONSE, SERVER +from ._util import LocalProtocolError, Sentinel + +__all__ = ["WRITERS"] + +Writer = Callable[[bytes], Any] + + +def write_headers(headers: Headers, write: Writer) -> None: + # "Since the Host field-value is critical information for handling a + # request, a user agent SHOULD generate Host as the first header field + # following the request-line." - RFC 7230 + raw_items = headers._full_items + for raw_name, name, value in raw_items: + if name == b"host": + write(b"%s: %s\r\n" % (raw_name, value)) + for raw_name, name, value in raw_items: + if name != b"host": + write(b"%s: %s\r\n" % (raw_name, value)) + write(b"\r\n") + + +def write_request(request: Request, write: Writer) -> None: + if request.http_version != b"1.1": + raise LocalProtocolError("I only send HTTP/1.1") + write(b"%s %s HTTP/1.1\r\n" % (request.method, request.target)) + write_headers(request.headers, write) + + +# Shared between InformationalResponse and Response +def write_any_response( + response: Union[InformationalResponse, Response], write: Writer +) -> None: + if response.http_version != b"1.1": + raise LocalProtocolError("I only send HTTP/1.1") + status_bytes = str(response.status_code).encode("ascii") + # We don't bother sending ascii status messages like "OK"; they're + # optional and ignored by the protocol. (But the space after the numeric + # status code is mandatory.) + # + # XX FIXME: could at least make an effort to pull out the status message + # from stdlib's http.HTTPStatus table. Or maybe just steal their enums + # (either by import or copy/paste). We already accept them as status codes + # since they're of type IntEnum < int. + write(b"HTTP/1.1 %s %s\r\n" % (status_bytes, response.reason)) + write_headers(response.headers, write) + + +class BodyWriter: + def __call__(self, event: Event, write: Writer) -> None: + if type(event) is Data: + self.send_data(event.data, write) + elif type(event) is EndOfMessage: + self.send_eom(event.headers, write) + else: # pragma: no cover + assert False + + def send_data(self, data: bytes, write: Writer) -> None: + pass + + def send_eom(self, headers: Headers, write: Writer) -> None: + pass + + +# +# These are all careful not to do anything to 'data' except call len(data) and +# write(data). This allows us to transparently pass-through funny objects, +# like placeholder objects referring to files on disk that will be sent via +# sendfile(2). +# +class ContentLengthWriter(BodyWriter): + def __init__(self, length: int) -> None: + self._length = length + + def send_data(self, data: bytes, write: Writer) -> None: + self._length -= len(data) + if self._length < 0: + raise LocalProtocolError("Too much data for declared Content-Length") + write(data) + + def send_eom(self, headers: Headers, write: Writer) -> None: + if self._length != 0: + raise LocalProtocolError("Too little data for declared Content-Length") + if headers: + raise LocalProtocolError("Content-Length and trailers don't mix") + + +class ChunkedWriter(BodyWriter): + def send_data(self, data: bytes, write: Writer) -> None: + # if we encoded 0-length data in the naive way, it would look like an + # end-of-message. + if not data: + return + write(b"%x\r\n" % len(data)) + write(data) + write(b"\r\n") + + def send_eom(self, headers: Headers, write: Writer) -> None: + write(b"0\r\n") + write_headers(headers, write) + + +class Http10Writer(BodyWriter): + def send_data(self, data: bytes, write: Writer) -> None: + write(data) + + def send_eom(self, headers: Headers, write: Writer) -> None: + if headers: + raise LocalProtocolError("can't send trailers to HTTP/1.0 client") + # no need to close the socket ourselves, that will be taken care of by + # Connection: close machinery + + +WritersType = Dict[ + Union[Tuple[Type[Sentinel], Type[Sentinel]], Type[Sentinel]], + Union[ + Dict[str, Type[BodyWriter]], + Callable[[Union[InformationalResponse, Response], Writer], None], + Callable[[Request, Writer], None], + ], +] + +WRITERS: WritersType = { + (CLIENT, IDLE): write_request, + (SERVER, IDLE): write_any_response, + (SERVER, SEND_RESPONSE): write_any_response, + SEND_BODY: { + "chunked": ChunkedWriter, + "content-length": ContentLengthWriter, + "http/1.0": Http10Writer, + }, +} diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/py.typed b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/py.typed new file mode 100644 index 0000000..f5642f7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/h11/py.typed @@ -0,0 +1 @@ +Marker diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna-3.13.dist-info/INSTALLER b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna-3.13.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna-3.13.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna-3.13.dist-info/METADATA b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna-3.13.dist-info/METADATA new file mode 100644 index 0000000..b30fccc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna-3.13.dist-info/METADATA @@ -0,0 +1,204 @@ +Metadata-Version: 2.4 +Name: idna +Version: 3.13 +Summary: Internationalized Domain Names in Applications (IDNA) +Author-email: Kim Davies +Requires-Python: >=3.8 +Description-Content-Type: text/x-rst +License-Expression: BSD-3-Clause +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: System Administrators +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 +Classifier: Programming Language :: Python :: 3.14 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Internet :: Name Service (DNS) +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Utilities +License-File: LICENSE.md +Requires-Dist: ruff >= 0.6.2 ; extra == "all" +Requires-Dist: mypy >= 1.11.2 ; extra == "all" +Requires-Dist: pytest >= 8.3.2 ; extra == "all" +Project-URL: Changelog, https://github.com/kjd/idna/blob/master/HISTORY.rst +Project-URL: Issue tracker, https://github.com/kjd/idna/issues +Project-URL: Source, https://github.com/kjd/idna +Provides-Extra: all + +Internationalized Domain Names in Applications (IDNA) +===================================================== + +Support for `Internationalized Domain Names in +Applications (IDNA) `_ +and `Unicode IDNA Compatibility Processing +`_. + +The latest versions of these standards supplied here provide +more comprehensive language coverage and reduce the potential of +allowing domains with known security vulnerabilities. This library +is a suitable replacement for the “encodings.idna” +module that comes with the Python standard library, but which +only supports an older superseded IDNA specification from 2003. + +Basic functions are simply executed: + +.. code-block:: pycon + + >>> import idna + >>> idna.encode('ドメイン.テスト') + b'xn--eckwd4c7c.xn--zckzah' + >>> print(idna.decode('xn--eckwd4c7c.xn--zckzah')) + ドメイン.テスト + + +Installation +------------ + +This package is available for installation from PyPI via the +typical mechanisms, such as: + +.. code-block:: bash + + $ python3 -m pip install idna + + +Usage +----- + +For typical usage, the ``encode`` and ``decode`` functions will take a +domain name argument and perform a conversion to ASCII-compatible encoding +(known as A-labels), or to Unicode strings (known as U-labels) +respectively. + +.. code-block:: pycon + + >>> import idna + >>> idna.encode('ドメイン.テスト') + b'xn--eckwd4c7c.xn--zckzah' + >>> print(idna.decode('xn--eckwd4c7c.xn--zckzah')) + ドメイン.テスト + +Conversions can be applied at a per-label basis using the ``ulabel`` or +``alabel`` functions if necessary: + +.. code-block:: pycon + + >>> idna.alabel('测试') + b'xn--0zwm56d' + + +Compatibility Mapping (UTS #46) ++++++++++++++++++++++++++++++++ + +This library provides support for `Unicode IDNA Compatibility +Processing `_ which normalizes input from +different potential ways a user may input a domain prior to performing the IDNA +conversion operations. This functionality, known as a +`mapping `_, is considered by the +specification to be a local user-interface issue distinct from IDNA +conversion functionality. + +For example, “Königsgäßchen” is not a permissible label as *LATIN +CAPITAL LETTER K* is not allowed (nor are capital letters in general). +UTS 46 will convert this into lower case prior to applying the IDNA +conversion. + +.. code-block:: pycon + + >>> import idna + >>> idna.encode('Königsgäßchen') + ... + idna.core.InvalidCodepoint: Codepoint U+004B at position 1 of 'Königsgäßchen' not allowed + >>> idna.encode('Königsgäßchen', uts46=True) + b'xn--knigsgchen-b4a3dun' + >>> print(idna.decode('xn--knigsgchen-b4a3dun')) + königsgäßchen + + +Exceptions +---------- + +All errors raised during the conversion following the specification +should raise an exception derived from the ``idna.IDNAError`` base +class. + +More specific exceptions that may be generated as ``idna.IDNABidiError`` +when the error reflects an illegal combination of left-to-right and +right-to-left characters in a label; ``idna.InvalidCodepoint`` when +a specific codepoint is an illegal character in an IDN label (i.e. +INVALID); and ``idna.InvalidCodepointContext`` when the codepoint is +illegal based on its position in the string (i.e. it is CONTEXTO or CONTEXTJ +but the contextual requirements are not satisfied.) + +Building and Diagnostics +------------------------ + +The IDNA and UTS 46 functionality relies upon pre-calculated lookup +tables for performance. These tables are derived from computing against +eligibility criteria in the respective standards using the command-line +script ``tools/idna-data``. + +This tool will fetch relevant codepoint data from the Unicode repository +and perform the required calculations to identify eligibility. There are +three main modes: + +* ``idna-data make-libdata``. Generates ``idnadata.py`` and + ``uts46data.py``, the pre-calculated lookup tables used for IDNA and + UTS 46 conversions. Implementers who wish to track this library against + a different Unicode version may use this tool to manually generate a + different version of the ``idnadata.py`` and ``uts46data.py`` files. + +* ``idna-data make-table``. Generate a table of the IDNA disposition + (e.g. PVALID, CONTEXTJ, CONTEXTO) in the format found in Appendix + B.1 of RFC 5892 and the pre-computed tables published by `IANA + `_. + +* ``idna-data U+0061``. Prints debugging output on the various + properties associated with an individual Unicode codepoint (in this + case, U+0061), that are used to assess the IDNA and UTS 46 status of a + codepoint. This is helpful in debugging or analysis. + +The tool accepts a number of arguments, described using ``idna-data -h``. +Most notably, the ``--version`` argument allows the specification +of the version of Unicode to be used in computing the table data. For +example, ``idna-data --version 9.0.0 make-libdata`` will generate +library data against Unicode 9.0.0. + + +Additional Notes +---------------- + +* **Packages**. The latest tagged release version is published in the + `Python Package Index `_. + +* **Version support**. This library supports Python 3.8 and higher. + As this library serves as a low-level toolkit for a variety of + applications, many of which strive for broad compatibility with older + Python versions, there is no rush to remove older interpreter support. + Support for older versions are likely to be removed from new releases + as automated tests can no longer easily be run, i.e. once the Python + version is officially end-of-life. + +* **Testing**. The library has a test suite based on each rule of the + IDNA specification, as well as tests that are provided as part of the + Unicode Technical Standard 46, `Unicode IDNA Compatibility Processing + `_. + +* **Emoji**. It is an occasional request to support emoji domains in + this library. Encoding of symbols like emoji is expressly prohibited by + the IDNA technical standard, and emoji domains are broadly phased + out across the domain industry due to associated security risks. + +* **Transitional processing**. Unicode 16.0.0 removed transitional + processing so the `transitional` argument for the encode() method + no longer has any effect and will be removed at a later date. + diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna-3.13.dist-info/RECORD b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna-3.13.dist-info/RECORD new file mode 100644 index 0000000..36f72b0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna-3.13.dist-info/RECORD @@ -0,0 +1,14 @@ +idna-3.13.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +idna-3.13.dist-info/METADATA,sha256=aCJPP9iIHtp9NZSENIrzP52rgjQxw0-PWNfHGJ7ffQA,8033 +idna-3.13.dist-info/RECORD,, +idna-3.13.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82 +idna-3.13.dist-info/licenses/LICENSE.md,sha256=GppPDj1HmickDd1ZqRN6ZqtKD539yMphiMwL_YUYfwQ,1541 +idna/__init__.py,sha256=MPqNDLZbXqGaNdXxAFhiqFPKEQXju2jNQhCey6-5eJM,868 +idna/codec.py,sha256=M2SGWN7cs_6B32QmKTyTN6xQGZeYQgQ2wiX3_DR6loE,3438 +idna/compat.py,sha256=RzLy6QQCdl9784aFhb2EX9EKGCJjg0P3PilGdeXXcx8,316 +idna/core.py,sha256=0_28DR8hKT_pJKcmbeIQiiO1rHOpS3kJTtp9pyrk-4k,13374 +idna/idnadata.py,sha256=EYkhqhOze0Whw1pIMum_-qEHM-8utUwc_IBoIUWW8Go,92613 +idna/intranges.py,sha256=amUtkdhYcQG8Zr-CoMM_kVRacxkivC1WgxN1b63KKdU,1898 +idna/package_data.py,sha256=Nc4yldCrxxvai27WL76JL60jhw0ajOoboFGsm5L8FxM,21 +idna/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +idna/uts46data.py,sha256=JAacELsMTouJI-U6jk_UcKuAM4K7ffGCYpbDLux8iVk,202713 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna-3.13.dist-info/WHEEL b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna-3.13.dist-info/WHEEL new file mode 100644 index 0000000..d8b9936 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna-3.13.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.12.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna-3.13.dist-info/licenses/LICENSE.md b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna-3.13.dist-info/licenses/LICENSE.md new file mode 100644 index 0000000..f706835 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna-3.13.dist-info/licenses/LICENSE.md @@ -0,0 +1,31 @@ +BSD 3-Clause License + +Copyright (c) 2013-2026, Kim Davies and contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/__init__.py new file mode 100644 index 0000000..cfdc030 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/__init__.py @@ -0,0 +1,45 @@ +from .core import ( + IDNABidiError, + IDNAError, + InvalidCodepoint, + InvalidCodepointContext, + alabel, + check_bidi, + check_hyphen_ok, + check_initial_combiner, + check_label, + check_nfc, + decode, + encode, + ulabel, + uts46_remap, + valid_contextj, + valid_contexto, + valid_label_length, + valid_string_length, +) +from .intranges import intranges_contain +from .package_data import __version__ + +__all__ = [ + "__version__", + "IDNABidiError", + "IDNAError", + "InvalidCodepoint", + "InvalidCodepointContext", + "alabel", + "check_bidi", + "check_hyphen_ok", + "check_initial_combiner", + "check_label", + "check_nfc", + "decode", + "encode", + "intranges_contain", + "ulabel", + "uts46_remap", + "valid_contextj", + "valid_contexto", + "valid_label_length", + "valid_string_length", +] diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/codec.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/codec.py new file mode 100644 index 0000000..cbc2e4f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/codec.py @@ -0,0 +1,122 @@ +import codecs +import re +from typing import Any, Optional, Tuple + +from .core import IDNAError, alabel, decode, encode, ulabel + +_unicode_dots_re = re.compile("[\u002e\u3002\uff0e\uff61]") + + +class Codec(codecs.Codec): + def encode(self, data: str, errors: str = "strict") -> Tuple[bytes, int]: + if errors != "strict": + raise IDNAError('Unsupported error handling "{}"'.format(errors)) + + if not data: + return b"", 0 + + return encode(data), len(data) + + def decode(self, data: bytes, errors: str = "strict") -> Tuple[str, int]: + if errors != "strict": + raise IDNAError('Unsupported error handling "{}"'.format(errors)) + + if not data: + return "", 0 + + return decode(data), len(data) + + +class IncrementalEncoder(codecs.BufferedIncrementalEncoder): + def _buffer_encode(self, data: str, errors: str, final: bool) -> Tuple[bytes, int]: + if errors != "strict": + raise IDNAError('Unsupported error handling "{}"'.format(errors)) + + if not data: + return b"", 0 + + labels = _unicode_dots_re.split(data) + trailing_dot = b"" + if labels: + if not labels[-1]: + trailing_dot = b"." + del labels[-1] + elif not final: + # Keep potentially unfinished label until the next call + del labels[-1] + if labels: + trailing_dot = b"." + + result = [] + size = 0 + for label in labels: + result.append(alabel(label)) + if size: + size += 1 + size += len(label) + + # Join with U+002E + result_bytes = b".".join(result) + trailing_dot + size += len(trailing_dot) + return result_bytes, size + + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + def _buffer_decode(self, data: Any, errors: str, final: bool) -> Tuple[str, int]: + if errors != "strict": + raise IDNAError('Unsupported error handling "{}"'.format(errors)) + + if not data: + return ("", 0) + + if not isinstance(data, str): + data = str(data, "ascii") + + labels = _unicode_dots_re.split(data) + trailing_dot = "" + if labels: + if not labels[-1]: + trailing_dot = "." + del labels[-1] + elif not final: + # Keep potentially unfinished label until the next call + del labels[-1] + if labels: + trailing_dot = "." + + result = [] + size = 0 + for label in labels: + result.append(ulabel(label)) + if size: + size += 1 + size += len(label) + + result_str = ".".join(result) + trailing_dot + size += len(trailing_dot) + return (result_str, size) + + +class StreamWriter(Codec, codecs.StreamWriter): + pass + + +class StreamReader(Codec, codecs.StreamReader): + pass + + +def search_function(name: str) -> Optional[codecs.CodecInfo]: + if name != "idna2008": + return None + return codecs.CodecInfo( + name=name, + encode=Codec().encode, + decode=Codec().decode, # type: ignore + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) + + +codecs.register(search_function) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/compat.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/compat.py new file mode 100644 index 0000000..1df9f2a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/compat.py @@ -0,0 +1,15 @@ +from typing import Any, Union + +from .core import decode, encode + + +def ToASCII(label: str) -> bytes: + return encode(label) + + +def ToUnicode(label: Union[bytes, bytearray]) -> str: + return decode(label) + + +def nameprep(s: Any) -> None: + raise NotImplementedError("IDNA 2008 does not utilise nameprep protocol") diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/core.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/core.py new file mode 100644 index 0000000..e6ac1f9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/core.py @@ -0,0 +1,440 @@ +import bisect +import re +import unicodedata +import warnings +from typing import Optional, Union + +from . import idnadata +from .intranges import intranges_contain + +_virama_combining_class = 9 +_alabel_prefix = b"xn--" +_unicode_dots_re = re.compile("[\u002e\u3002\uff0e\uff61]") + + +class IDNAError(UnicodeError): + """Base exception for all IDNA-encoding related problems""" + + pass + + +class IDNABidiError(IDNAError): + """Exception when bidirectional requirements are not satisfied""" + + pass + + +class InvalidCodepoint(IDNAError): + """Exception when a disallowed or unallocated codepoint is used""" + + pass + + +class InvalidCodepointContext(IDNAError): + """Exception when the codepoint is not valid in the context it is used""" + + pass + + +def _combining_class(cp: int) -> int: + v = unicodedata.combining(chr(cp)) + if v == 0: + if not unicodedata.name(chr(cp)): + raise ValueError("Unknown character in unicodedata") + return v + + +def _is_script(cp: str, script: str) -> bool: + return intranges_contain(ord(cp), idnadata.scripts[script]) + + +def _punycode(s: str) -> bytes: + return s.encode("punycode") + + +def _unot(s: int) -> str: + return "U+{:04X}".format(s) + + +def valid_label_length(label: Union[bytes, str]) -> bool: + if len(label) > 63: + return False + return True + + +def valid_string_length(label: Union[bytes, str], trailing_dot: bool) -> bool: + if len(label) > (254 if trailing_dot else 253): + return False + return True + + +def check_bidi(label: str, check_ltr: bool = False) -> bool: + # Bidi rules should only be applied if string contains RTL characters + bidi_label = False + for idx, cp in enumerate(label, 1): + direction = unicodedata.bidirectional(cp) + if direction == "": + # String likely comes from a newer version of Unicode + raise IDNABidiError("Unknown directionality in label {} at position {}".format(repr(label), idx)) + if direction in ["R", "AL", "AN"]: + bidi_label = True + if not bidi_label and not check_ltr: + return True + + # Bidi rule 1 + direction = unicodedata.bidirectional(label[0]) + if direction in ["R", "AL"]: + rtl = True + elif direction == "L": + rtl = False + else: + raise IDNABidiError("First codepoint in label {} must be directionality L, R or AL".format(repr(label))) + + valid_ending = False + number_type: Optional[str] = None + for idx, cp in enumerate(label, 1): + direction = unicodedata.bidirectional(cp) + + if rtl: + # Bidi rule 2 + if direction not in [ + "R", + "AL", + "AN", + "EN", + "ES", + "CS", + "ET", + "ON", + "BN", + "NSM", + ]: + raise IDNABidiError("Invalid direction for codepoint at position {} in a right-to-left label".format(idx)) + # Bidi rule 3 + if direction in ["R", "AL", "EN", "AN"]: + valid_ending = True + elif direction != "NSM": + valid_ending = False + # Bidi rule 4 + if direction in ["AN", "EN"]: + if not number_type: + number_type = direction + else: + if number_type != direction: + raise IDNABidiError("Can not mix numeral types in a right-to-left label") + else: + # Bidi rule 5 + if direction not in ["L", "EN", "ES", "CS", "ET", "ON", "BN", "NSM"]: + raise IDNABidiError("Invalid direction for codepoint at position {} in a left-to-right label".format(idx)) + # Bidi rule 6 + if direction in ["L", "EN"]: + valid_ending = True + elif direction != "NSM": + valid_ending = False + + if not valid_ending: + raise IDNABidiError("Label ends with illegal codepoint directionality") + + return True + + +def check_initial_combiner(label: str) -> bool: + if unicodedata.category(label[0])[0] == "M": + raise IDNAError("Label begins with an illegal combining character") + return True + + +def check_hyphen_ok(label: str) -> bool: + if label[2:4] == "--": + raise IDNAError("Label has disallowed hyphens in 3rd and 4th position") + if label[0] == "-" or label[-1] == "-": + raise IDNAError("Label must not start or end with a hyphen") + return True + + +def check_nfc(label: str) -> None: + if unicodedata.normalize("NFC", label) != label: + raise IDNAError("Label must be in Normalization Form C") + + +def valid_contextj(label: str, pos: int) -> bool: + cp_value = ord(label[pos]) + + if cp_value == 0x200C: + if pos > 0: + if _combining_class(ord(label[pos - 1])) == _virama_combining_class: + return True + + ok = False + for i in range(pos - 1, -1, -1): + joining_type = idnadata.joining_types().get(ord(label[i])) + if joining_type == ord("T"): + continue + elif joining_type in [ord("L"), ord("D")]: + ok = True + break + else: + break + + if not ok: + return False + + ok = False + for i in range(pos + 1, len(label)): + joining_type = idnadata.joining_types().get(ord(label[i])) + if joining_type == ord("T"): + continue + elif joining_type in [ord("R"), ord("D")]: + ok = True + break + else: + break + return ok + + if cp_value == 0x200D: + if pos > 0: + if _combining_class(ord(label[pos - 1])) == _virama_combining_class: + return True + return False + + else: + return False + + +def valid_contexto(label: str, pos: int, exception: bool = False) -> bool: + cp_value = ord(label[pos]) + + if cp_value == 0x00B7: + if 0 < pos < len(label) - 1: + if ord(label[pos - 1]) == 0x006C and ord(label[pos + 1]) == 0x006C: + return True + return False + + elif cp_value == 0x0375: + if pos < len(label) - 1 and len(label) > 1: + return _is_script(label[pos + 1], "Greek") + return False + + elif cp_value == 0x05F3 or cp_value == 0x05F4: + if pos > 0: + return _is_script(label[pos - 1], "Hebrew") + return False + + elif cp_value == 0x30FB: + for cp in label: + if cp == "\u30fb": + continue + if _is_script(cp, "Hiragana") or _is_script(cp, "Katakana") or _is_script(cp, "Han"): + return True + return False + + elif 0x660 <= cp_value <= 0x669: + for cp in label: + if 0x6F0 <= ord(cp) <= 0x06F9: + return False + return True + + elif 0x6F0 <= cp_value <= 0x6F9: + for cp in label: + if 0x660 <= ord(cp) <= 0x0669: + return False + return True + + return False + + +def check_label(label: Union[str, bytes, bytearray]) -> None: + if isinstance(label, (bytes, bytearray)): + label = label.decode("utf-8") + if len(label) == 0: + raise IDNAError("Empty Label") + + check_nfc(label) + check_hyphen_ok(label) + check_initial_combiner(label) + + for pos, cp in enumerate(label): + cp_value = ord(cp) + if intranges_contain(cp_value, idnadata.codepoint_classes["PVALID"]): + continue + elif intranges_contain(cp_value, idnadata.codepoint_classes["CONTEXTJ"]): + try: + if not valid_contextj(label, pos): + raise InvalidCodepointContext( + "Joiner {} not allowed at position {} in {}".format(_unot(cp_value), pos + 1, repr(label)) + ) + except ValueError: + raise IDNAError( + "Unknown codepoint adjacent to joiner {} at position {} in {}".format( + _unot(cp_value), pos + 1, repr(label) + ) + ) + elif intranges_contain(cp_value, idnadata.codepoint_classes["CONTEXTO"]): + if not valid_contexto(label, pos): + raise InvalidCodepointContext( + "Codepoint {} not allowed at position {} in {}".format(_unot(cp_value), pos + 1, repr(label)) + ) + else: + raise InvalidCodepoint( + "Codepoint {} at position {} of {} not allowed".format(_unot(cp_value), pos + 1, repr(label)) + ) + + check_bidi(label) + + +def alabel(label: str) -> bytes: + try: + label_bytes = label.encode("ascii") + ulabel(label_bytes) + if not valid_label_length(label_bytes): + raise IDNAError("Label too long") + return label_bytes + except UnicodeEncodeError: + pass + + check_label(label) + label_bytes = _alabel_prefix + _punycode(label) + + if not valid_label_length(label_bytes): + raise IDNAError("Label too long") + + return label_bytes + + +def ulabel(label: Union[str, bytes, bytearray]) -> str: + if not isinstance(label, (bytes, bytearray)): + try: + label_bytes = label.encode("ascii") + except UnicodeEncodeError: + check_label(label) + return label + else: + label_bytes = bytes(label) + + label_bytes = label_bytes.lower() + if label_bytes.startswith(_alabel_prefix): + label_bytes = label_bytes[len(_alabel_prefix) :] + if not label_bytes: + raise IDNAError("Malformed A-label, no Punycode eligible content found") + if label_bytes.decode("ascii")[-1] == "-": + raise IDNAError("A-label must not end with a hyphen") + else: + check_label(label_bytes) + return label_bytes.decode("ascii") + + try: + label = label_bytes.decode("punycode") + except UnicodeError: + raise IDNAError("Invalid A-label") + check_label(label) + return label + + +def uts46_remap(domain: str, std3_rules: bool = True, transitional: bool = False) -> str: + """Re-map the characters in the string according to UTS46 processing.""" + from .uts46data import uts46data + + output = "" + + for pos, char in enumerate(domain): + code_point = ord(char) + uts46row = uts46data[code_point if code_point < 256 else bisect.bisect_left(uts46data, (code_point, "Z")) - 1] + status = uts46row[1] + replacement: Optional[str] = None + if len(uts46row) == 3: + replacement = uts46row[2] + if status == "V" or (status == "D" and not transitional) or (status == "3" and not std3_rules and replacement is None): + output += char + elif replacement is not None and ( + status == "M" or (status == "3" and not std3_rules) or (status == "D" and transitional) + ): + output += replacement + elif status == "I": + continue + else: + raise InvalidCodepoint( + "Codepoint {} not allowed at position {} in {}".format(_unot(code_point), pos + 1, repr(domain)) + ) + + return unicodedata.normalize("NFC", output) + + +def encode( + s: Union[str, bytes, bytearray], + strict: bool = False, + uts46: bool = False, + std3_rules: bool = False, + transitional: bool = False, +) -> bytes: + if transitional: + warnings.warn( + "Transitional processing has been removed from UTS #46. " + "The transitional argument will be removed in a future version.", + DeprecationWarning, + stacklevel=2, + ) + if not isinstance(s, str): + try: + s = str(s, "ascii") + except UnicodeDecodeError: + raise IDNAError("should pass a unicode string to the function rather than a byte string.") + if uts46: + s = uts46_remap(s, std3_rules, transitional) + trailing_dot = False + result = [] + if strict: + labels = s.split(".") + else: + labels = _unicode_dots_re.split(s) + if not labels or labels == [""]: + raise IDNAError("Empty domain") + if labels[-1] == "": + del labels[-1] + trailing_dot = True + for label in labels: + s = alabel(label) + if s: + result.append(s) + else: + raise IDNAError("Empty label") + if trailing_dot: + result.append(b"") + s = b".".join(result) + if not valid_string_length(s, trailing_dot): + raise IDNAError("Domain too long") + return s + + +def decode( + s: Union[str, bytes, bytearray], + strict: bool = False, + uts46: bool = False, + std3_rules: bool = False, +) -> str: + try: + if not isinstance(s, str): + s = str(s, "ascii") + except UnicodeDecodeError: + raise IDNAError("Invalid ASCII in A-label") + if uts46: + s = uts46_remap(s, std3_rules, False) + trailing_dot = False + result = [] + if not strict: + labels = _unicode_dots_re.split(s) + else: + labels = s.split(".") + if not labels or labels == [""]: + raise IDNAError("Empty domain") + if not labels[-1]: + del labels[-1] + trailing_dot = True + for label in labels: + s = ulabel(label) + if s: + result.append(s) + else: + raise IDNAError("Empty label") + if trailing_dot: + result.append("") + return ".".join(result) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/idnadata.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/idnadata.py new file mode 100644 index 0000000..8335f26 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/idnadata.py @@ -0,0 +1,4367 @@ +# This file is automatically generated by tools/idna-data + +from functools import lru_cache +from typing import Dict + +__version__ = "17.0.0" + +scripts = { + "Greek": ( + 0x37000000374, + 0x37500000378, + 0x37A0000037E, + 0x37F00000380, + 0x38400000385, + 0x38600000387, + 0x3880000038B, + 0x38C0000038D, + 0x38E000003A2, + 0x3A3000003E2, + 0x3F000000400, + 0x1D2600001D2B, + 0x1D5D00001D62, + 0x1D6600001D6B, + 0x1DBF00001DC0, + 0x1F0000001F16, + 0x1F1800001F1E, + 0x1F2000001F46, + 0x1F4800001F4E, + 0x1F5000001F58, + 0x1F5900001F5A, + 0x1F5B00001F5C, + 0x1F5D00001F5E, + 0x1F5F00001F7E, + 0x1F8000001FB5, + 0x1FB600001FC5, + 0x1FC600001FD4, + 0x1FD600001FDC, + 0x1FDD00001FF0, + 0x1FF200001FF5, + 0x1FF600001FFF, + 0x212600002127, + 0xAB650000AB66, + 0x101400001018F, + 0x101A0000101A1, + 0x1D2000001D246, + ), + "Han": ( + 0x2E8000002E9A, + 0x2E9B00002EF4, + 0x2F0000002FD6, + 0x300500003006, + 0x300700003008, + 0x30210000302A, + 0x30380000303C, + 0x340000004DC0, + 0x4E000000A000, + 0xF9000000FA6E, + 0xFA700000FADA, + 0x16FE200016FE4, + 0x16FF000016FF7, + 0x200000002A6E0, + 0x2A7000002B81E, + 0x2B8200002CEAE, + 0x2CEB00002EBE1, + 0x2EBF00002EE5E, + 0x2F8000002FA1E, + 0x300000003134B, + 0x313500003347A, + ), + "Hebrew": ( + 0x591000005C8, + 0x5D0000005EB, + 0x5EF000005F5, + 0xFB1D0000FB37, + 0xFB380000FB3D, + 0xFB3E0000FB3F, + 0xFB400000FB42, + 0xFB430000FB45, + 0xFB460000FB50, + ), + "Hiragana": ( + 0x304100003097, + 0x309D000030A0, + 0x1B0010001B120, + 0x1B1320001B133, + 0x1B1500001B153, + 0x1F2000001F201, + ), + "Katakana": ( + 0x30A1000030FB, + 0x30FD00003100, + 0x31F000003200, + 0x32D0000032FF, + 0x330000003358, + 0xFF660000FF70, + 0xFF710000FF9E, + 0x1AFF00001AFF4, + 0x1AFF50001AFFC, + 0x1AFFD0001AFFF, + 0x1B0000001B001, + 0x1B1200001B123, + 0x1B1550001B156, + 0x1B1640001B168, + ), +} + + +@lru_cache(None) +def joining_types() -> Dict[int, int]: + return { + 0xAD: 84, + 0x300: 84, + 0x301: 84, + 0x302: 84, + 0x303: 84, + 0x304: 84, + 0x305: 84, + 0x306: 84, + 0x307: 84, + 0x308: 84, + 0x309: 84, + 0x30A: 84, + 0x30B: 84, + 0x30C: 84, + 0x30D: 84, + 0x30E: 84, + 0x30F: 84, + 0x310: 84, + 0x311: 84, + 0x312: 84, + 0x313: 84, + 0x314: 84, + 0x315: 84, + 0x316: 84, + 0x317: 84, + 0x318: 84, + 0x319: 84, + 0x31A: 84, + 0x31B: 84, + 0x31C: 84, + 0x31D: 84, + 0x31E: 84, + 0x31F: 84, + 0x320: 84, + 0x321: 84, + 0x322: 84, + 0x323: 84, + 0x324: 84, + 0x325: 84, + 0x326: 84, + 0x327: 84, + 0x328: 84, + 0x329: 84, + 0x32A: 84, + 0x32B: 84, + 0x32C: 84, + 0x32D: 84, + 0x32E: 84, + 0x32F: 84, + 0x330: 84, + 0x331: 84, + 0x332: 84, + 0x333: 84, + 0x334: 84, + 0x335: 84, + 0x336: 84, + 0x337: 84, + 0x338: 84, + 0x339: 84, + 0x33A: 84, + 0x33B: 84, + 0x33C: 84, + 0x33D: 84, + 0x33E: 84, + 0x33F: 84, + 0x340: 84, + 0x341: 84, + 0x342: 84, + 0x343: 84, + 0x344: 84, + 0x345: 84, + 0x346: 84, + 0x347: 84, + 0x348: 84, + 0x349: 84, + 0x34A: 84, + 0x34B: 84, + 0x34C: 84, + 0x34D: 84, + 0x34E: 84, + 0x34F: 84, + 0x350: 84, + 0x351: 84, + 0x352: 84, + 0x353: 84, + 0x354: 84, + 0x355: 84, + 0x356: 84, + 0x357: 84, + 0x358: 84, + 0x359: 84, + 0x35A: 84, + 0x35B: 84, + 0x35C: 84, + 0x35D: 84, + 0x35E: 84, + 0x35F: 84, + 0x360: 84, + 0x361: 84, + 0x362: 84, + 0x363: 84, + 0x364: 84, + 0x365: 84, + 0x366: 84, + 0x367: 84, + 0x368: 84, + 0x369: 84, + 0x36A: 84, + 0x36B: 84, + 0x36C: 84, + 0x36D: 84, + 0x36E: 84, + 0x36F: 84, + 0x483: 84, + 0x484: 84, + 0x485: 84, + 0x486: 84, + 0x487: 84, + 0x488: 84, + 0x489: 84, + 0x591: 84, + 0x592: 84, + 0x593: 84, + 0x594: 84, + 0x595: 84, + 0x596: 84, + 0x597: 84, + 0x598: 84, + 0x599: 84, + 0x59A: 84, + 0x59B: 84, + 0x59C: 84, + 0x59D: 84, + 0x59E: 84, + 0x59F: 84, + 0x5A0: 84, + 0x5A1: 84, + 0x5A2: 84, + 0x5A3: 84, + 0x5A4: 84, + 0x5A5: 84, + 0x5A6: 84, + 0x5A7: 84, + 0x5A8: 84, + 0x5A9: 84, + 0x5AA: 84, + 0x5AB: 84, + 0x5AC: 84, + 0x5AD: 84, + 0x5AE: 84, + 0x5AF: 84, + 0x5B0: 84, + 0x5B1: 84, + 0x5B2: 84, + 0x5B3: 84, + 0x5B4: 84, + 0x5B5: 84, + 0x5B6: 84, + 0x5B7: 84, + 0x5B8: 84, + 0x5B9: 84, + 0x5BA: 84, + 0x5BB: 84, + 0x5BC: 84, + 0x5BD: 84, + 0x5BF: 84, + 0x5C1: 84, + 0x5C2: 84, + 0x5C4: 84, + 0x5C5: 84, + 0x5C7: 84, + 0x610: 84, + 0x611: 84, + 0x612: 84, + 0x613: 84, + 0x614: 84, + 0x615: 84, + 0x616: 84, + 0x617: 84, + 0x618: 84, + 0x619: 84, + 0x61A: 84, + 0x61C: 84, + 0x620: 68, + 0x622: 82, + 0x623: 82, + 0x624: 82, + 0x625: 82, + 0x626: 68, + 0x627: 82, + 0x628: 68, + 0x629: 82, + 0x62A: 68, + 0x62B: 68, + 0x62C: 68, + 0x62D: 68, + 0x62E: 68, + 0x62F: 82, + 0x630: 82, + 0x631: 82, + 0x632: 82, + 0x633: 68, + 0x634: 68, + 0x635: 68, + 0x636: 68, + 0x637: 68, + 0x638: 68, + 0x639: 68, + 0x63A: 68, + 0x63B: 68, + 0x63C: 68, + 0x63D: 68, + 0x63E: 68, + 0x63F: 68, + 0x640: 67, + 0x641: 68, + 0x642: 68, + 0x643: 68, + 0x644: 68, + 0x645: 68, + 0x646: 68, + 0x647: 68, + 0x648: 82, + 0x649: 68, + 0x64A: 68, + 0x64B: 84, + 0x64C: 84, + 0x64D: 84, + 0x64E: 84, + 0x64F: 84, + 0x650: 84, + 0x651: 84, + 0x652: 84, + 0x653: 84, + 0x654: 84, + 0x655: 84, + 0x656: 84, + 0x657: 84, + 0x658: 84, + 0x659: 84, + 0x65A: 84, + 0x65B: 84, + 0x65C: 84, + 0x65D: 84, + 0x65E: 84, + 0x65F: 84, + 0x66E: 68, + 0x66F: 68, + 0x670: 84, + 0x671: 82, + 0x672: 82, + 0x673: 82, + 0x675: 82, + 0x676: 82, + 0x677: 82, + 0x678: 68, + 0x679: 68, + 0x67A: 68, + 0x67B: 68, + 0x67C: 68, + 0x67D: 68, + 0x67E: 68, + 0x67F: 68, + 0x680: 68, + 0x681: 68, + 0x682: 68, + 0x683: 68, + 0x684: 68, + 0x685: 68, + 0x686: 68, + 0x687: 68, + 0x688: 82, + 0x689: 82, + 0x68A: 82, + 0x68B: 82, + 0x68C: 82, + 0x68D: 82, + 0x68E: 82, + 0x68F: 82, + 0x690: 82, + 0x691: 82, + 0x692: 82, + 0x693: 82, + 0x694: 82, + 0x695: 82, + 0x696: 82, + 0x697: 82, + 0x698: 82, + 0x699: 82, + 0x69A: 68, + 0x69B: 68, + 0x69C: 68, + 0x69D: 68, + 0x69E: 68, + 0x69F: 68, + 0x6A0: 68, + 0x6A1: 68, + 0x6A2: 68, + 0x6A3: 68, + 0x6A4: 68, + 0x6A5: 68, + 0x6A6: 68, + 0x6A7: 68, + 0x6A8: 68, + 0x6A9: 68, + 0x6AA: 68, + 0x6AB: 68, + 0x6AC: 68, + 0x6AD: 68, + 0x6AE: 68, + 0x6AF: 68, + 0x6B0: 68, + 0x6B1: 68, + 0x6B2: 68, + 0x6B3: 68, + 0x6B4: 68, + 0x6B5: 68, + 0x6B6: 68, + 0x6B7: 68, + 0x6B8: 68, + 0x6B9: 68, + 0x6BA: 68, + 0x6BB: 68, + 0x6BC: 68, + 0x6BD: 68, + 0x6BE: 68, + 0x6BF: 68, + 0x6C0: 82, + 0x6C1: 68, + 0x6C2: 68, + 0x6C3: 82, + 0x6C4: 82, + 0x6C5: 82, + 0x6C6: 82, + 0x6C7: 82, + 0x6C8: 82, + 0x6C9: 82, + 0x6CA: 82, + 0x6CB: 82, + 0x6CC: 68, + 0x6CD: 82, + 0x6CE: 68, + 0x6CF: 82, + 0x6D0: 68, + 0x6D1: 68, + 0x6D2: 82, + 0x6D3: 82, + 0x6D5: 82, + 0x6D6: 84, + 0x6D7: 84, + 0x6D8: 84, + 0x6D9: 84, + 0x6DA: 84, + 0x6DB: 84, + 0x6DC: 84, + 0x6DF: 84, + 0x6E0: 84, + 0x6E1: 84, + 0x6E2: 84, + 0x6E3: 84, + 0x6E4: 84, + 0x6E7: 84, + 0x6E8: 84, + 0x6EA: 84, + 0x6EB: 84, + 0x6EC: 84, + 0x6ED: 84, + 0x6EE: 82, + 0x6EF: 82, + 0x6FA: 68, + 0x6FB: 68, + 0x6FC: 68, + 0x6FF: 68, + 0x70F: 84, + 0x710: 82, + 0x711: 84, + 0x712: 68, + 0x713: 68, + 0x714: 68, + 0x715: 82, + 0x716: 82, + 0x717: 82, + 0x718: 82, + 0x719: 82, + 0x71A: 68, + 0x71B: 68, + 0x71C: 68, + 0x71D: 68, + 0x71E: 82, + 0x71F: 68, + 0x720: 68, + 0x721: 68, + 0x722: 68, + 0x723: 68, + 0x724: 68, + 0x725: 68, + 0x726: 68, + 0x727: 68, + 0x728: 82, + 0x729: 68, + 0x72A: 82, + 0x72B: 68, + 0x72C: 82, + 0x72D: 68, + 0x72E: 68, + 0x72F: 82, + 0x730: 84, + 0x731: 84, + 0x732: 84, + 0x733: 84, + 0x734: 84, + 0x735: 84, + 0x736: 84, + 0x737: 84, + 0x738: 84, + 0x739: 84, + 0x73A: 84, + 0x73B: 84, + 0x73C: 84, + 0x73D: 84, + 0x73E: 84, + 0x73F: 84, + 0x740: 84, + 0x741: 84, + 0x742: 84, + 0x743: 84, + 0x744: 84, + 0x745: 84, + 0x746: 84, + 0x747: 84, + 0x748: 84, + 0x749: 84, + 0x74A: 84, + 0x74D: 82, + 0x74E: 68, + 0x74F: 68, + 0x750: 68, + 0x751: 68, + 0x752: 68, + 0x753: 68, + 0x754: 68, + 0x755: 68, + 0x756: 68, + 0x757: 68, + 0x758: 68, + 0x759: 82, + 0x75A: 82, + 0x75B: 82, + 0x75C: 68, + 0x75D: 68, + 0x75E: 68, + 0x75F: 68, + 0x760: 68, + 0x761: 68, + 0x762: 68, + 0x763: 68, + 0x764: 68, + 0x765: 68, + 0x766: 68, + 0x767: 68, + 0x768: 68, + 0x769: 68, + 0x76A: 68, + 0x76B: 82, + 0x76C: 82, + 0x76D: 68, + 0x76E: 68, + 0x76F: 68, + 0x770: 68, + 0x771: 82, + 0x772: 68, + 0x773: 82, + 0x774: 82, + 0x775: 68, + 0x776: 68, + 0x777: 68, + 0x778: 82, + 0x779: 82, + 0x77A: 68, + 0x77B: 68, + 0x77C: 68, + 0x77D: 68, + 0x77E: 68, + 0x77F: 68, + 0x7A6: 84, + 0x7A7: 84, + 0x7A8: 84, + 0x7A9: 84, + 0x7AA: 84, + 0x7AB: 84, + 0x7AC: 84, + 0x7AD: 84, + 0x7AE: 84, + 0x7AF: 84, + 0x7B0: 84, + 0x7CA: 68, + 0x7CB: 68, + 0x7CC: 68, + 0x7CD: 68, + 0x7CE: 68, + 0x7CF: 68, + 0x7D0: 68, + 0x7D1: 68, + 0x7D2: 68, + 0x7D3: 68, + 0x7D4: 68, + 0x7D5: 68, + 0x7D6: 68, + 0x7D7: 68, + 0x7D8: 68, + 0x7D9: 68, + 0x7DA: 68, + 0x7DB: 68, + 0x7DC: 68, + 0x7DD: 68, + 0x7DE: 68, + 0x7DF: 68, + 0x7E0: 68, + 0x7E1: 68, + 0x7E2: 68, + 0x7E3: 68, + 0x7E4: 68, + 0x7E5: 68, + 0x7E6: 68, + 0x7E7: 68, + 0x7E8: 68, + 0x7E9: 68, + 0x7EA: 68, + 0x7EB: 84, + 0x7EC: 84, + 0x7ED: 84, + 0x7EE: 84, + 0x7EF: 84, + 0x7F0: 84, + 0x7F1: 84, + 0x7F2: 84, + 0x7F3: 84, + 0x7FA: 67, + 0x7FD: 84, + 0x816: 84, + 0x817: 84, + 0x818: 84, + 0x819: 84, + 0x81B: 84, + 0x81C: 84, + 0x81D: 84, + 0x81E: 84, + 0x81F: 84, + 0x820: 84, + 0x821: 84, + 0x822: 84, + 0x823: 84, + 0x825: 84, + 0x826: 84, + 0x827: 84, + 0x829: 84, + 0x82A: 84, + 0x82B: 84, + 0x82C: 84, + 0x82D: 84, + 0x840: 82, + 0x841: 68, + 0x842: 68, + 0x843: 68, + 0x844: 68, + 0x845: 68, + 0x846: 82, + 0x847: 82, + 0x848: 68, + 0x849: 82, + 0x84A: 68, + 0x84B: 68, + 0x84C: 68, + 0x84D: 68, + 0x84E: 68, + 0x84F: 68, + 0x850: 68, + 0x851: 68, + 0x852: 68, + 0x853: 68, + 0x854: 82, + 0x855: 68, + 0x856: 82, + 0x857: 82, + 0x858: 82, + 0x859: 84, + 0x85A: 84, + 0x85B: 84, + 0x860: 68, + 0x862: 68, + 0x863: 68, + 0x864: 68, + 0x865: 68, + 0x867: 82, + 0x868: 68, + 0x869: 82, + 0x86A: 82, + 0x870: 82, + 0x871: 82, + 0x872: 82, + 0x873: 82, + 0x874: 82, + 0x875: 82, + 0x876: 82, + 0x877: 82, + 0x878: 82, + 0x879: 82, + 0x87A: 82, + 0x87B: 82, + 0x87C: 82, + 0x87D: 82, + 0x87E: 82, + 0x87F: 82, + 0x880: 82, + 0x881: 82, + 0x882: 82, + 0x883: 67, + 0x884: 67, + 0x885: 67, + 0x886: 68, + 0x889: 68, + 0x88A: 68, + 0x88B: 68, + 0x88C: 68, + 0x88D: 68, + 0x88E: 82, + 0x88F: 68, + 0x897: 84, + 0x898: 84, + 0x899: 84, + 0x89A: 84, + 0x89B: 84, + 0x89C: 84, + 0x89D: 84, + 0x89E: 84, + 0x89F: 84, + 0x8A0: 68, + 0x8A1: 68, + 0x8A2: 68, + 0x8A3: 68, + 0x8A4: 68, + 0x8A5: 68, + 0x8A6: 68, + 0x8A7: 68, + 0x8A8: 68, + 0x8A9: 68, + 0x8AA: 82, + 0x8AB: 82, + 0x8AC: 82, + 0x8AE: 82, + 0x8AF: 68, + 0x8B0: 68, + 0x8B1: 82, + 0x8B2: 82, + 0x8B3: 68, + 0x8B4: 68, + 0x8B5: 68, + 0x8B6: 68, + 0x8B7: 68, + 0x8B8: 68, + 0x8B9: 82, + 0x8BA: 68, + 0x8BB: 68, + 0x8BC: 68, + 0x8BD: 68, + 0x8BE: 68, + 0x8BF: 68, + 0x8C0: 68, + 0x8C1: 68, + 0x8C2: 68, + 0x8C3: 68, + 0x8C4: 68, + 0x8C5: 68, + 0x8C6: 68, + 0x8C7: 68, + 0x8C8: 68, + 0x8CA: 84, + 0x8CB: 84, + 0x8CC: 84, + 0x8CD: 84, + 0x8CE: 84, + 0x8CF: 84, + 0x8D0: 84, + 0x8D1: 84, + 0x8D2: 84, + 0x8D3: 84, + 0x8D4: 84, + 0x8D5: 84, + 0x8D6: 84, + 0x8D7: 84, + 0x8D8: 84, + 0x8D9: 84, + 0x8DA: 84, + 0x8DB: 84, + 0x8DC: 84, + 0x8DD: 84, + 0x8DE: 84, + 0x8DF: 84, + 0x8E0: 84, + 0x8E1: 84, + 0x8E3: 84, + 0x8E4: 84, + 0x8E5: 84, + 0x8E6: 84, + 0x8E7: 84, + 0x8E8: 84, + 0x8E9: 84, + 0x8EA: 84, + 0x8EB: 84, + 0x8EC: 84, + 0x8ED: 84, + 0x8EE: 84, + 0x8EF: 84, + 0x8F0: 84, + 0x8F1: 84, + 0x8F2: 84, + 0x8F3: 84, + 0x8F4: 84, + 0x8F5: 84, + 0x8F6: 84, + 0x8F7: 84, + 0x8F8: 84, + 0x8F9: 84, + 0x8FA: 84, + 0x8FB: 84, + 0x8FC: 84, + 0x8FD: 84, + 0x8FE: 84, + 0x8FF: 84, + 0x900: 84, + 0x901: 84, + 0x902: 84, + 0x93A: 84, + 0x93C: 84, + 0x941: 84, + 0x942: 84, + 0x943: 84, + 0x944: 84, + 0x945: 84, + 0x946: 84, + 0x947: 84, + 0x948: 84, + 0x94D: 84, + 0x951: 84, + 0x952: 84, + 0x953: 84, + 0x954: 84, + 0x955: 84, + 0x956: 84, + 0x957: 84, + 0x962: 84, + 0x963: 84, + 0x981: 84, + 0x9BC: 84, + 0x9C1: 84, + 0x9C2: 84, + 0x9C3: 84, + 0x9C4: 84, + 0x9CD: 84, + 0x9E2: 84, + 0x9E3: 84, + 0x9FE: 84, + 0xA01: 84, + 0xA02: 84, + 0xA3C: 84, + 0xA41: 84, + 0xA42: 84, + 0xA47: 84, + 0xA48: 84, + 0xA4B: 84, + 0xA4C: 84, + 0xA4D: 84, + 0xA51: 84, + 0xA70: 84, + 0xA71: 84, + 0xA75: 84, + 0xA81: 84, + 0xA82: 84, + 0xABC: 84, + 0xAC1: 84, + 0xAC2: 84, + 0xAC3: 84, + 0xAC4: 84, + 0xAC5: 84, + 0xAC7: 84, + 0xAC8: 84, + 0xACD: 84, + 0xAE2: 84, + 0xAE3: 84, + 0xAFA: 84, + 0xAFB: 84, + 0xAFC: 84, + 0xAFD: 84, + 0xAFE: 84, + 0xAFF: 84, + 0xB01: 84, + 0xB3C: 84, + 0xB3F: 84, + 0xB41: 84, + 0xB42: 84, + 0xB43: 84, + 0xB44: 84, + 0xB4D: 84, + 0xB55: 84, + 0xB56: 84, + 0xB62: 84, + 0xB63: 84, + 0xB82: 84, + 0xBC0: 84, + 0xBCD: 84, + 0xC00: 84, + 0xC04: 84, + 0xC3C: 84, + 0xC3E: 84, + 0xC3F: 84, + 0xC40: 84, + 0xC46: 84, + 0xC47: 84, + 0xC48: 84, + 0xC4A: 84, + 0xC4B: 84, + 0xC4C: 84, + 0xC4D: 84, + 0xC55: 84, + 0xC56: 84, + 0xC62: 84, + 0xC63: 84, + 0xC81: 84, + 0xCBC: 84, + 0xCBF: 84, + 0xCC6: 84, + 0xCCC: 84, + 0xCCD: 84, + 0xCE2: 84, + 0xCE3: 84, + 0xD00: 84, + 0xD01: 84, + 0xD3B: 84, + 0xD3C: 84, + 0xD41: 84, + 0xD42: 84, + 0xD43: 84, + 0xD44: 84, + 0xD4D: 84, + 0xD62: 84, + 0xD63: 84, + 0xD81: 84, + 0xDCA: 84, + 0xDD2: 84, + 0xDD3: 84, + 0xDD4: 84, + 0xDD6: 84, + 0xE31: 84, + 0xE34: 84, + 0xE35: 84, + 0xE36: 84, + 0xE37: 84, + 0xE38: 84, + 0xE39: 84, + 0xE3A: 84, + 0xE47: 84, + 0xE48: 84, + 0xE49: 84, + 0xE4A: 84, + 0xE4B: 84, + 0xE4C: 84, + 0xE4D: 84, + 0xE4E: 84, + 0xEB1: 84, + 0xEB4: 84, + 0xEB5: 84, + 0xEB6: 84, + 0xEB7: 84, + 0xEB8: 84, + 0xEB9: 84, + 0xEBA: 84, + 0xEBB: 84, + 0xEBC: 84, + 0xEC8: 84, + 0xEC9: 84, + 0xECA: 84, + 0xECB: 84, + 0xECC: 84, + 0xECD: 84, + 0xECE: 84, + 0xF18: 84, + 0xF19: 84, + 0xF35: 84, + 0xF37: 84, + 0xF39: 84, + 0xF71: 84, + 0xF72: 84, + 0xF73: 84, + 0xF74: 84, + 0xF75: 84, + 0xF76: 84, + 0xF77: 84, + 0xF78: 84, + 0xF79: 84, + 0xF7A: 84, + 0xF7B: 84, + 0xF7C: 84, + 0xF7D: 84, + 0xF7E: 84, + 0xF80: 84, + 0xF81: 84, + 0xF82: 84, + 0xF83: 84, + 0xF84: 84, + 0xF86: 84, + 0xF87: 84, + 0xF8D: 84, + 0xF8E: 84, + 0xF8F: 84, + 0xF90: 84, + 0xF91: 84, + 0xF92: 84, + 0xF93: 84, + 0xF94: 84, + 0xF95: 84, + 0xF96: 84, + 0xF97: 84, + 0xF99: 84, + 0xF9A: 84, + 0xF9B: 84, + 0xF9C: 84, + 0xF9D: 84, + 0xF9E: 84, + 0xF9F: 84, + 0xFA0: 84, + 0xFA1: 84, + 0xFA2: 84, + 0xFA3: 84, + 0xFA4: 84, + 0xFA5: 84, + 0xFA6: 84, + 0xFA7: 84, + 0xFA8: 84, + 0xFA9: 84, + 0xFAA: 84, + 0xFAB: 84, + 0xFAC: 84, + 0xFAD: 84, + 0xFAE: 84, + 0xFAF: 84, + 0xFB0: 84, + 0xFB1: 84, + 0xFB2: 84, + 0xFB3: 84, + 0xFB4: 84, + 0xFB5: 84, + 0xFB6: 84, + 0xFB7: 84, + 0xFB8: 84, + 0xFB9: 84, + 0xFBA: 84, + 0xFBB: 84, + 0xFBC: 84, + 0xFC6: 84, + 0x102D: 84, + 0x102E: 84, + 0x102F: 84, + 0x1030: 84, + 0x1032: 84, + 0x1033: 84, + 0x1034: 84, + 0x1035: 84, + 0x1036: 84, + 0x1037: 84, + 0x1039: 84, + 0x103A: 84, + 0x103D: 84, + 0x103E: 84, + 0x1058: 84, + 0x1059: 84, + 0x105E: 84, + 0x105F: 84, + 0x1060: 84, + 0x1071: 84, + 0x1072: 84, + 0x1073: 84, + 0x1074: 84, + 0x1082: 84, + 0x1085: 84, + 0x1086: 84, + 0x108D: 84, + 0x109D: 84, + 0x135D: 84, + 0x135E: 84, + 0x135F: 84, + 0x1712: 84, + 0x1713: 84, + 0x1714: 84, + 0x1732: 84, + 0x1733: 84, + 0x1752: 84, + 0x1753: 84, + 0x1772: 84, + 0x1773: 84, + 0x17B4: 84, + 0x17B5: 84, + 0x17B7: 84, + 0x17B8: 84, + 0x17B9: 84, + 0x17BA: 84, + 0x17BB: 84, + 0x17BC: 84, + 0x17BD: 84, + 0x17C6: 84, + 0x17C9: 84, + 0x17CA: 84, + 0x17CB: 84, + 0x17CC: 84, + 0x17CD: 84, + 0x17CE: 84, + 0x17CF: 84, + 0x17D0: 84, + 0x17D1: 84, + 0x17D2: 84, + 0x17D3: 84, + 0x17DD: 84, + 0x1807: 68, + 0x180A: 67, + 0x180B: 84, + 0x180C: 84, + 0x180D: 84, + 0x180F: 84, + 0x1820: 68, + 0x1821: 68, + 0x1822: 68, + 0x1823: 68, + 0x1824: 68, + 0x1825: 68, + 0x1826: 68, + 0x1827: 68, + 0x1828: 68, + 0x1829: 68, + 0x182A: 68, + 0x182B: 68, + 0x182C: 68, + 0x182D: 68, + 0x182E: 68, + 0x182F: 68, + 0x1830: 68, + 0x1831: 68, + 0x1832: 68, + 0x1833: 68, + 0x1834: 68, + 0x1835: 68, + 0x1836: 68, + 0x1837: 68, + 0x1838: 68, + 0x1839: 68, + 0x183A: 68, + 0x183B: 68, + 0x183C: 68, + 0x183D: 68, + 0x183E: 68, + 0x183F: 68, + 0x1840: 68, + 0x1841: 68, + 0x1842: 68, + 0x1843: 68, + 0x1844: 68, + 0x1845: 68, + 0x1846: 68, + 0x1847: 68, + 0x1848: 68, + 0x1849: 68, + 0x184A: 68, + 0x184B: 68, + 0x184C: 68, + 0x184D: 68, + 0x184E: 68, + 0x184F: 68, + 0x1850: 68, + 0x1851: 68, + 0x1852: 68, + 0x1853: 68, + 0x1854: 68, + 0x1855: 68, + 0x1856: 68, + 0x1857: 68, + 0x1858: 68, + 0x1859: 68, + 0x185A: 68, + 0x185B: 68, + 0x185C: 68, + 0x185D: 68, + 0x185E: 68, + 0x185F: 68, + 0x1860: 68, + 0x1861: 68, + 0x1862: 68, + 0x1863: 68, + 0x1864: 68, + 0x1865: 68, + 0x1866: 68, + 0x1867: 68, + 0x1868: 68, + 0x1869: 68, + 0x186A: 68, + 0x186B: 68, + 0x186C: 68, + 0x186D: 68, + 0x186E: 68, + 0x186F: 68, + 0x1870: 68, + 0x1871: 68, + 0x1872: 68, + 0x1873: 68, + 0x1874: 68, + 0x1875: 68, + 0x1876: 68, + 0x1877: 68, + 0x1878: 68, + 0x1885: 84, + 0x1886: 84, + 0x1887: 68, + 0x1888: 68, + 0x1889: 68, + 0x188A: 68, + 0x188B: 68, + 0x188C: 68, + 0x188D: 68, + 0x188E: 68, + 0x188F: 68, + 0x1890: 68, + 0x1891: 68, + 0x1892: 68, + 0x1893: 68, + 0x1894: 68, + 0x1895: 68, + 0x1896: 68, + 0x1897: 68, + 0x1898: 68, + 0x1899: 68, + 0x189A: 68, + 0x189B: 68, + 0x189C: 68, + 0x189D: 68, + 0x189E: 68, + 0x189F: 68, + 0x18A0: 68, + 0x18A1: 68, + 0x18A2: 68, + 0x18A3: 68, + 0x18A4: 68, + 0x18A5: 68, + 0x18A6: 68, + 0x18A7: 68, + 0x18A8: 68, + 0x18A9: 84, + 0x18AA: 68, + 0x1920: 84, + 0x1921: 84, + 0x1922: 84, + 0x1927: 84, + 0x1928: 84, + 0x1932: 84, + 0x1939: 84, + 0x193A: 84, + 0x193B: 84, + 0x1A17: 84, + 0x1A18: 84, + 0x1A1B: 84, + 0x1A56: 84, + 0x1A58: 84, + 0x1A59: 84, + 0x1A5A: 84, + 0x1A5B: 84, + 0x1A5C: 84, + 0x1A5D: 84, + 0x1A5E: 84, + 0x1A60: 84, + 0x1A62: 84, + 0x1A65: 84, + 0x1A66: 84, + 0x1A67: 84, + 0x1A68: 84, + 0x1A69: 84, + 0x1A6A: 84, + 0x1A6B: 84, + 0x1A6C: 84, + 0x1A73: 84, + 0x1A74: 84, + 0x1A75: 84, + 0x1A76: 84, + 0x1A77: 84, + 0x1A78: 84, + 0x1A79: 84, + 0x1A7A: 84, + 0x1A7B: 84, + 0x1A7C: 84, + 0x1A7F: 84, + 0x1AB0: 84, + 0x1AB1: 84, + 0x1AB2: 84, + 0x1AB3: 84, + 0x1AB4: 84, + 0x1AB5: 84, + 0x1AB6: 84, + 0x1AB7: 84, + 0x1AB8: 84, + 0x1AB9: 84, + 0x1ABA: 84, + 0x1ABB: 84, + 0x1ABC: 84, + 0x1ABD: 84, + 0x1ABE: 84, + 0x1ABF: 84, + 0x1AC0: 84, + 0x1AC1: 84, + 0x1AC2: 84, + 0x1AC3: 84, + 0x1AC4: 84, + 0x1AC5: 84, + 0x1AC6: 84, + 0x1AC7: 84, + 0x1AC8: 84, + 0x1AC9: 84, + 0x1ACA: 84, + 0x1ACB: 84, + 0x1ACC: 84, + 0x1ACD: 84, + 0x1ACE: 84, + 0x1ACF: 84, + 0x1AD0: 84, + 0x1AD1: 84, + 0x1AD2: 84, + 0x1AD3: 84, + 0x1AD4: 84, + 0x1AD5: 84, + 0x1AD6: 84, + 0x1AD7: 84, + 0x1AD8: 84, + 0x1AD9: 84, + 0x1ADA: 84, + 0x1ADB: 84, + 0x1ADC: 84, + 0x1ADD: 84, + 0x1AE0: 84, + 0x1AE1: 84, + 0x1AE2: 84, + 0x1AE3: 84, + 0x1AE4: 84, + 0x1AE5: 84, + 0x1AE6: 84, + 0x1AE7: 84, + 0x1AE8: 84, + 0x1AE9: 84, + 0x1AEA: 84, + 0x1AEB: 84, + 0x1B00: 84, + 0x1B01: 84, + 0x1B02: 84, + 0x1B03: 84, + 0x1B34: 84, + 0x1B36: 84, + 0x1B37: 84, + 0x1B38: 84, + 0x1B39: 84, + 0x1B3A: 84, + 0x1B3C: 84, + 0x1B42: 84, + 0x1B6B: 84, + 0x1B6C: 84, + 0x1B6D: 84, + 0x1B6E: 84, + 0x1B6F: 84, + 0x1B70: 84, + 0x1B71: 84, + 0x1B72: 84, + 0x1B73: 84, + 0x1B80: 84, + 0x1B81: 84, + 0x1BA2: 84, + 0x1BA3: 84, + 0x1BA4: 84, + 0x1BA5: 84, + 0x1BA8: 84, + 0x1BA9: 84, + 0x1BAB: 84, + 0x1BAC: 84, + 0x1BAD: 84, + 0x1BE6: 84, + 0x1BE8: 84, + 0x1BE9: 84, + 0x1BED: 84, + 0x1BEF: 84, + 0x1BF0: 84, + 0x1BF1: 84, + 0x1C2C: 84, + 0x1C2D: 84, + 0x1C2E: 84, + 0x1C2F: 84, + 0x1C30: 84, + 0x1C31: 84, + 0x1C32: 84, + 0x1C33: 84, + 0x1C36: 84, + 0x1C37: 84, + 0x1CD0: 84, + 0x1CD1: 84, + 0x1CD2: 84, + 0x1CD4: 84, + 0x1CD5: 84, + 0x1CD6: 84, + 0x1CD7: 84, + 0x1CD8: 84, + 0x1CD9: 84, + 0x1CDA: 84, + 0x1CDB: 84, + 0x1CDC: 84, + 0x1CDD: 84, + 0x1CDE: 84, + 0x1CDF: 84, + 0x1CE0: 84, + 0x1CE2: 84, + 0x1CE3: 84, + 0x1CE4: 84, + 0x1CE5: 84, + 0x1CE6: 84, + 0x1CE7: 84, + 0x1CE8: 84, + 0x1CED: 84, + 0x1CF4: 84, + 0x1CF8: 84, + 0x1CF9: 84, + 0x1DC0: 84, + 0x1DC1: 84, + 0x1DC2: 84, + 0x1DC3: 84, + 0x1DC4: 84, + 0x1DC5: 84, + 0x1DC6: 84, + 0x1DC7: 84, + 0x1DC8: 84, + 0x1DC9: 84, + 0x1DCA: 84, + 0x1DCB: 84, + 0x1DCC: 84, + 0x1DCD: 84, + 0x1DCE: 84, + 0x1DCF: 84, + 0x1DD0: 84, + 0x1DD1: 84, + 0x1DD2: 84, + 0x1DD3: 84, + 0x1DD4: 84, + 0x1DD5: 84, + 0x1DD6: 84, + 0x1DD7: 84, + 0x1DD8: 84, + 0x1DD9: 84, + 0x1DDA: 84, + 0x1DDB: 84, + 0x1DDC: 84, + 0x1DDD: 84, + 0x1DDE: 84, + 0x1DDF: 84, + 0x1DE0: 84, + 0x1DE1: 84, + 0x1DE2: 84, + 0x1DE3: 84, + 0x1DE4: 84, + 0x1DE5: 84, + 0x1DE6: 84, + 0x1DE7: 84, + 0x1DE8: 84, + 0x1DE9: 84, + 0x1DEA: 84, + 0x1DEB: 84, + 0x1DEC: 84, + 0x1DED: 84, + 0x1DEE: 84, + 0x1DEF: 84, + 0x1DF0: 84, + 0x1DF1: 84, + 0x1DF2: 84, + 0x1DF3: 84, + 0x1DF4: 84, + 0x1DF5: 84, + 0x1DF6: 84, + 0x1DF7: 84, + 0x1DF8: 84, + 0x1DF9: 84, + 0x1DFA: 84, + 0x1DFB: 84, + 0x1DFC: 84, + 0x1DFD: 84, + 0x1DFE: 84, + 0x1DFF: 84, + 0x200B: 84, + 0x200D: 67, + 0x200E: 84, + 0x200F: 84, + 0x202A: 84, + 0x202B: 84, + 0x202C: 84, + 0x202D: 84, + 0x202E: 84, + 0x2060: 84, + 0x2061: 84, + 0x2062: 84, + 0x2063: 84, + 0x2064: 84, + 0x206A: 84, + 0x206B: 84, + 0x206C: 84, + 0x206D: 84, + 0x206E: 84, + 0x206F: 84, + 0x20D0: 84, + 0x20D1: 84, + 0x20D2: 84, + 0x20D3: 84, + 0x20D4: 84, + 0x20D5: 84, + 0x20D6: 84, + 0x20D7: 84, + 0x20D8: 84, + 0x20D9: 84, + 0x20DA: 84, + 0x20DB: 84, + 0x20DC: 84, + 0x20DD: 84, + 0x20DE: 84, + 0x20DF: 84, + 0x20E0: 84, + 0x20E1: 84, + 0x20E2: 84, + 0x20E3: 84, + 0x20E4: 84, + 0x20E5: 84, + 0x20E6: 84, + 0x20E7: 84, + 0x20E8: 84, + 0x20E9: 84, + 0x20EA: 84, + 0x20EB: 84, + 0x20EC: 84, + 0x20ED: 84, + 0x20EE: 84, + 0x20EF: 84, + 0x20F0: 84, + 0x2CEF: 84, + 0x2CF0: 84, + 0x2CF1: 84, + 0x2D7F: 84, + 0x2DE0: 84, + 0x2DE1: 84, + 0x2DE2: 84, + 0x2DE3: 84, + 0x2DE4: 84, + 0x2DE5: 84, + 0x2DE6: 84, + 0x2DE7: 84, + 0x2DE8: 84, + 0x2DE9: 84, + 0x2DEA: 84, + 0x2DEB: 84, + 0x2DEC: 84, + 0x2DED: 84, + 0x2DEE: 84, + 0x2DEF: 84, + 0x2DF0: 84, + 0x2DF1: 84, + 0x2DF2: 84, + 0x2DF3: 84, + 0x2DF4: 84, + 0x2DF5: 84, + 0x2DF6: 84, + 0x2DF7: 84, + 0x2DF8: 84, + 0x2DF9: 84, + 0x2DFA: 84, + 0x2DFB: 84, + 0x2DFC: 84, + 0x2DFD: 84, + 0x2DFE: 84, + 0x2DFF: 84, + 0x302A: 84, + 0x302B: 84, + 0x302C: 84, + 0x302D: 84, + 0x3099: 84, + 0x309A: 84, + 0xA66F: 84, + 0xA670: 84, + 0xA671: 84, + 0xA672: 84, + 0xA674: 84, + 0xA675: 84, + 0xA676: 84, + 0xA677: 84, + 0xA678: 84, + 0xA679: 84, + 0xA67A: 84, + 0xA67B: 84, + 0xA67C: 84, + 0xA67D: 84, + 0xA69E: 84, + 0xA69F: 84, + 0xA6F0: 84, + 0xA6F1: 84, + 0xA802: 84, + 0xA806: 84, + 0xA80B: 84, + 0xA825: 84, + 0xA826: 84, + 0xA82C: 84, + 0xA840: 68, + 0xA841: 68, + 0xA842: 68, + 0xA843: 68, + 0xA844: 68, + 0xA845: 68, + 0xA846: 68, + 0xA847: 68, + 0xA848: 68, + 0xA849: 68, + 0xA84A: 68, + 0xA84B: 68, + 0xA84C: 68, + 0xA84D: 68, + 0xA84E: 68, + 0xA84F: 68, + 0xA850: 68, + 0xA851: 68, + 0xA852: 68, + 0xA853: 68, + 0xA854: 68, + 0xA855: 68, + 0xA856: 68, + 0xA857: 68, + 0xA858: 68, + 0xA859: 68, + 0xA85A: 68, + 0xA85B: 68, + 0xA85C: 68, + 0xA85D: 68, + 0xA85E: 68, + 0xA85F: 68, + 0xA860: 68, + 0xA861: 68, + 0xA862: 68, + 0xA863: 68, + 0xA864: 68, + 0xA865: 68, + 0xA866: 68, + 0xA867: 68, + 0xA868: 68, + 0xA869: 68, + 0xA86A: 68, + 0xA86B: 68, + 0xA86C: 68, + 0xA86D: 68, + 0xA86E: 68, + 0xA86F: 68, + 0xA870: 68, + 0xA871: 68, + 0xA872: 76, + 0xA8C4: 84, + 0xA8C5: 84, + 0xA8E0: 84, + 0xA8E1: 84, + 0xA8E2: 84, + 0xA8E3: 84, + 0xA8E4: 84, + 0xA8E5: 84, + 0xA8E6: 84, + 0xA8E7: 84, + 0xA8E8: 84, + 0xA8E9: 84, + 0xA8EA: 84, + 0xA8EB: 84, + 0xA8EC: 84, + 0xA8ED: 84, + 0xA8EE: 84, + 0xA8EF: 84, + 0xA8F0: 84, + 0xA8F1: 84, + 0xA8FF: 84, + 0xA926: 84, + 0xA927: 84, + 0xA928: 84, + 0xA929: 84, + 0xA92A: 84, + 0xA92B: 84, + 0xA92C: 84, + 0xA92D: 84, + 0xA947: 84, + 0xA948: 84, + 0xA949: 84, + 0xA94A: 84, + 0xA94B: 84, + 0xA94C: 84, + 0xA94D: 84, + 0xA94E: 84, + 0xA94F: 84, + 0xA950: 84, + 0xA951: 84, + 0xA980: 84, + 0xA981: 84, + 0xA982: 84, + 0xA9B3: 84, + 0xA9B6: 84, + 0xA9B7: 84, + 0xA9B8: 84, + 0xA9B9: 84, + 0xA9BC: 84, + 0xA9BD: 84, + 0xA9E5: 84, + 0xAA29: 84, + 0xAA2A: 84, + 0xAA2B: 84, + 0xAA2C: 84, + 0xAA2D: 84, + 0xAA2E: 84, + 0xAA31: 84, + 0xAA32: 84, + 0xAA35: 84, + 0xAA36: 84, + 0xAA43: 84, + 0xAA4C: 84, + 0xAA7C: 84, + 0xAAB0: 84, + 0xAAB2: 84, + 0xAAB3: 84, + 0xAAB4: 84, + 0xAAB7: 84, + 0xAAB8: 84, + 0xAABE: 84, + 0xAABF: 84, + 0xAAC1: 84, + 0xAAEC: 84, + 0xAAED: 84, + 0xAAF6: 84, + 0xABE5: 84, + 0xABE8: 84, + 0xABED: 84, + 0xFB1E: 84, + 0xFE00: 84, + 0xFE01: 84, + 0xFE02: 84, + 0xFE03: 84, + 0xFE04: 84, + 0xFE05: 84, + 0xFE06: 84, + 0xFE07: 84, + 0xFE08: 84, + 0xFE09: 84, + 0xFE0A: 84, + 0xFE0B: 84, + 0xFE0C: 84, + 0xFE0D: 84, + 0xFE0E: 84, + 0xFE0F: 84, + 0xFE20: 84, + 0xFE21: 84, + 0xFE22: 84, + 0xFE23: 84, + 0xFE24: 84, + 0xFE25: 84, + 0xFE26: 84, + 0xFE27: 84, + 0xFE28: 84, + 0xFE29: 84, + 0xFE2A: 84, + 0xFE2B: 84, + 0xFE2C: 84, + 0xFE2D: 84, + 0xFE2E: 84, + 0xFE2F: 84, + 0xFEFF: 84, + 0xFFF9: 84, + 0xFFFA: 84, + 0xFFFB: 84, + 0x101FD: 84, + 0x102E0: 84, + 0x10376: 84, + 0x10377: 84, + 0x10378: 84, + 0x10379: 84, + 0x1037A: 84, + 0x10A01: 84, + 0x10A02: 84, + 0x10A03: 84, + 0x10A05: 84, + 0x10A06: 84, + 0x10A0C: 84, + 0x10A0D: 84, + 0x10A0E: 84, + 0x10A0F: 84, + 0x10A38: 84, + 0x10A39: 84, + 0x10A3A: 84, + 0x10A3F: 84, + 0x10AC0: 68, + 0x10AC1: 68, + 0x10AC2: 68, + 0x10AC3: 68, + 0x10AC4: 68, + 0x10AC5: 82, + 0x10AC7: 82, + 0x10AC9: 82, + 0x10ACA: 82, + 0x10ACD: 76, + 0x10ACE: 82, + 0x10ACF: 82, + 0x10AD0: 82, + 0x10AD1: 82, + 0x10AD2: 82, + 0x10AD3: 68, + 0x10AD4: 68, + 0x10AD5: 68, + 0x10AD6: 68, + 0x10AD7: 76, + 0x10AD8: 68, + 0x10AD9: 68, + 0x10ADA: 68, + 0x10ADB: 68, + 0x10ADC: 68, + 0x10ADD: 82, + 0x10ADE: 68, + 0x10ADF: 68, + 0x10AE0: 68, + 0x10AE1: 82, + 0x10AE4: 82, + 0x10AE5: 84, + 0x10AE6: 84, + 0x10AEB: 68, + 0x10AEC: 68, + 0x10AED: 68, + 0x10AEE: 68, + 0x10AEF: 82, + 0x10B80: 68, + 0x10B81: 82, + 0x10B82: 68, + 0x10B83: 82, + 0x10B84: 82, + 0x10B85: 82, + 0x10B86: 68, + 0x10B87: 68, + 0x10B88: 68, + 0x10B89: 82, + 0x10B8A: 68, + 0x10B8B: 68, + 0x10B8C: 82, + 0x10B8D: 68, + 0x10B8E: 82, + 0x10B8F: 82, + 0x10B90: 68, + 0x10B91: 82, + 0x10BA9: 82, + 0x10BAA: 82, + 0x10BAB: 82, + 0x10BAC: 82, + 0x10BAD: 68, + 0x10BAE: 68, + 0x10D00: 76, + 0x10D01: 68, + 0x10D02: 68, + 0x10D03: 68, + 0x10D04: 68, + 0x10D05: 68, + 0x10D06: 68, + 0x10D07: 68, + 0x10D08: 68, + 0x10D09: 68, + 0x10D0A: 68, + 0x10D0B: 68, + 0x10D0C: 68, + 0x10D0D: 68, + 0x10D0E: 68, + 0x10D0F: 68, + 0x10D10: 68, + 0x10D11: 68, + 0x10D12: 68, + 0x10D13: 68, + 0x10D14: 68, + 0x10D15: 68, + 0x10D16: 68, + 0x10D17: 68, + 0x10D18: 68, + 0x10D19: 68, + 0x10D1A: 68, + 0x10D1B: 68, + 0x10D1C: 68, + 0x10D1D: 68, + 0x10D1E: 68, + 0x10D1F: 68, + 0x10D20: 68, + 0x10D21: 68, + 0x10D22: 82, + 0x10D23: 68, + 0x10D24: 84, + 0x10D25: 84, + 0x10D26: 84, + 0x10D27: 84, + 0x10D69: 84, + 0x10D6A: 84, + 0x10D6B: 84, + 0x10D6C: 84, + 0x10D6D: 84, + 0x10EAB: 84, + 0x10EAC: 84, + 0x10EC2: 82, + 0x10EC3: 68, + 0x10EC4: 68, + 0x10EC6: 68, + 0x10EC7: 68, + 0x10EFA: 84, + 0x10EFB: 84, + 0x10EFC: 84, + 0x10EFD: 84, + 0x10EFE: 84, + 0x10EFF: 84, + 0x10F30: 68, + 0x10F31: 68, + 0x10F32: 68, + 0x10F33: 82, + 0x10F34: 68, + 0x10F35: 68, + 0x10F36: 68, + 0x10F37: 68, + 0x10F38: 68, + 0x10F39: 68, + 0x10F3A: 68, + 0x10F3B: 68, + 0x10F3C: 68, + 0x10F3D: 68, + 0x10F3E: 68, + 0x10F3F: 68, + 0x10F40: 68, + 0x10F41: 68, + 0x10F42: 68, + 0x10F43: 68, + 0x10F44: 68, + 0x10F46: 84, + 0x10F47: 84, + 0x10F48: 84, + 0x10F49: 84, + 0x10F4A: 84, + 0x10F4B: 84, + 0x10F4C: 84, + 0x10F4D: 84, + 0x10F4E: 84, + 0x10F4F: 84, + 0x10F50: 84, + 0x10F51: 68, + 0x10F52: 68, + 0x10F53: 68, + 0x10F54: 82, + 0x10F70: 68, + 0x10F71: 68, + 0x10F72: 68, + 0x10F73: 68, + 0x10F74: 82, + 0x10F75: 82, + 0x10F76: 68, + 0x10F77: 68, + 0x10F78: 68, + 0x10F79: 68, + 0x10F7A: 68, + 0x10F7B: 68, + 0x10F7C: 68, + 0x10F7D: 68, + 0x10F7E: 68, + 0x10F7F: 68, + 0x10F80: 68, + 0x10F81: 68, + 0x10F82: 84, + 0x10F83: 84, + 0x10F84: 84, + 0x10F85: 84, + 0x10FB0: 68, + 0x10FB2: 68, + 0x10FB3: 68, + 0x10FB4: 82, + 0x10FB5: 82, + 0x10FB6: 82, + 0x10FB8: 68, + 0x10FB9: 82, + 0x10FBA: 82, + 0x10FBB: 68, + 0x10FBC: 68, + 0x10FBD: 82, + 0x10FBE: 68, + 0x10FBF: 68, + 0x10FC1: 68, + 0x10FC2: 82, + 0x10FC3: 82, + 0x10FC4: 68, + 0x10FC9: 82, + 0x10FCA: 68, + 0x10FCB: 76, + 0x11001: 84, + 0x11038: 84, + 0x11039: 84, + 0x1103A: 84, + 0x1103B: 84, + 0x1103C: 84, + 0x1103D: 84, + 0x1103E: 84, + 0x1103F: 84, + 0x11040: 84, + 0x11041: 84, + 0x11042: 84, + 0x11043: 84, + 0x11044: 84, + 0x11045: 84, + 0x11046: 84, + 0x11070: 84, + 0x11073: 84, + 0x11074: 84, + 0x1107F: 84, + 0x11080: 84, + 0x11081: 84, + 0x110B3: 84, + 0x110B4: 84, + 0x110B5: 84, + 0x110B6: 84, + 0x110B9: 84, + 0x110BA: 84, + 0x110C2: 84, + 0x11100: 84, + 0x11101: 84, + 0x11102: 84, + 0x11127: 84, + 0x11128: 84, + 0x11129: 84, + 0x1112A: 84, + 0x1112B: 84, + 0x1112D: 84, + 0x1112E: 84, + 0x1112F: 84, + 0x11130: 84, + 0x11131: 84, + 0x11132: 84, + 0x11133: 84, + 0x11134: 84, + 0x11173: 84, + 0x11180: 84, + 0x11181: 84, + 0x111B6: 84, + 0x111B7: 84, + 0x111B8: 84, + 0x111B9: 84, + 0x111BA: 84, + 0x111BB: 84, + 0x111BC: 84, + 0x111BD: 84, + 0x111BE: 84, + 0x111C9: 84, + 0x111CA: 84, + 0x111CB: 84, + 0x111CC: 84, + 0x111CF: 84, + 0x1122F: 84, + 0x11230: 84, + 0x11231: 84, + 0x11234: 84, + 0x11236: 84, + 0x11237: 84, + 0x1123E: 84, + 0x11241: 84, + 0x112DF: 84, + 0x112E3: 84, + 0x112E4: 84, + 0x112E5: 84, + 0x112E6: 84, + 0x112E7: 84, + 0x112E8: 84, + 0x112E9: 84, + 0x112EA: 84, + 0x11300: 84, + 0x11301: 84, + 0x1133B: 84, + 0x1133C: 84, + 0x11340: 84, + 0x11366: 84, + 0x11367: 84, + 0x11368: 84, + 0x11369: 84, + 0x1136A: 84, + 0x1136B: 84, + 0x1136C: 84, + 0x11370: 84, + 0x11371: 84, + 0x11372: 84, + 0x11373: 84, + 0x11374: 84, + 0x113BB: 84, + 0x113BC: 84, + 0x113BD: 84, + 0x113BE: 84, + 0x113BF: 84, + 0x113C0: 84, + 0x113CE: 84, + 0x113D0: 84, + 0x113D2: 84, + 0x113E1: 84, + 0x113E2: 84, + 0x11438: 84, + 0x11439: 84, + 0x1143A: 84, + 0x1143B: 84, + 0x1143C: 84, + 0x1143D: 84, + 0x1143E: 84, + 0x1143F: 84, + 0x11442: 84, + 0x11443: 84, + 0x11444: 84, + 0x11446: 84, + 0x1145E: 84, + 0x114B3: 84, + 0x114B4: 84, + 0x114B5: 84, + 0x114B6: 84, + 0x114B7: 84, + 0x114B8: 84, + 0x114BA: 84, + 0x114BF: 84, + 0x114C0: 84, + 0x114C2: 84, + 0x114C3: 84, + 0x115B2: 84, + 0x115B3: 84, + 0x115B4: 84, + 0x115B5: 84, + 0x115BC: 84, + 0x115BD: 84, + 0x115BF: 84, + 0x115C0: 84, + 0x115DC: 84, + 0x115DD: 84, + 0x11633: 84, + 0x11634: 84, + 0x11635: 84, + 0x11636: 84, + 0x11637: 84, + 0x11638: 84, + 0x11639: 84, + 0x1163A: 84, + 0x1163D: 84, + 0x1163F: 84, + 0x11640: 84, + 0x116AB: 84, + 0x116AD: 84, + 0x116B0: 84, + 0x116B1: 84, + 0x116B2: 84, + 0x116B3: 84, + 0x116B4: 84, + 0x116B5: 84, + 0x116B7: 84, + 0x1171D: 84, + 0x1171F: 84, + 0x11722: 84, + 0x11723: 84, + 0x11724: 84, + 0x11725: 84, + 0x11727: 84, + 0x11728: 84, + 0x11729: 84, + 0x1172A: 84, + 0x1172B: 84, + 0x1182F: 84, + 0x11830: 84, + 0x11831: 84, + 0x11832: 84, + 0x11833: 84, + 0x11834: 84, + 0x11835: 84, + 0x11836: 84, + 0x11837: 84, + 0x11839: 84, + 0x1183A: 84, + 0x1193B: 84, + 0x1193C: 84, + 0x1193E: 84, + 0x11943: 84, + 0x119D4: 84, + 0x119D5: 84, + 0x119D6: 84, + 0x119D7: 84, + 0x119DA: 84, + 0x119DB: 84, + 0x119E0: 84, + 0x11A01: 84, + 0x11A02: 84, + 0x11A03: 84, + 0x11A04: 84, + 0x11A05: 84, + 0x11A06: 84, + 0x11A07: 84, + 0x11A08: 84, + 0x11A09: 84, + 0x11A0A: 84, + 0x11A33: 84, + 0x11A34: 84, + 0x11A35: 84, + 0x11A36: 84, + 0x11A37: 84, + 0x11A38: 84, + 0x11A3B: 84, + 0x11A3C: 84, + 0x11A3D: 84, + 0x11A3E: 84, + 0x11A47: 84, + 0x11A51: 84, + 0x11A52: 84, + 0x11A53: 84, + 0x11A54: 84, + 0x11A55: 84, + 0x11A56: 84, + 0x11A59: 84, + 0x11A5A: 84, + 0x11A5B: 84, + 0x11A8A: 84, + 0x11A8B: 84, + 0x11A8C: 84, + 0x11A8D: 84, + 0x11A8E: 84, + 0x11A8F: 84, + 0x11A90: 84, + 0x11A91: 84, + 0x11A92: 84, + 0x11A93: 84, + 0x11A94: 84, + 0x11A95: 84, + 0x11A96: 84, + 0x11A98: 84, + 0x11A99: 84, + 0x11B60: 84, + 0x11B62: 84, + 0x11B63: 84, + 0x11B64: 84, + 0x11B66: 84, + 0x11C30: 84, + 0x11C31: 84, + 0x11C32: 84, + 0x11C33: 84, + 0x11C34: 84, + 0x11C35: 84, + 0x11C36: 84, + 0x11C38: 84, + 0x11C39: 84, + 0x11C3A: 84, + 0x11C3B: 84, + 0x11C3C: 84, + 0x11C3D: 84, + 0x11C3F: 84, + 0x11C92: 84, + 0x11C93: 84, + 0x11C94: 84, + 0x11C95: 84, + 0x11C96: 84, + 0x11C97: 84, + 0x11C98: 84, + 0x11C99: 84, + 0x11C9A: 84, + 0x11C9B: 84, + 0x11C9C: 84, + 0x11C9D: 84, + 0x11C9E: 84, + 0x11C9F: 84, + 0x11CA0: 84, + 0x11CA1: 84, + 0x11CA2: 84, + 0x11CA3: 84, + 0x11CA4: 84, + 0x11CA5: 84, + 0x11CA6: 84, + 0x11CA7: 84, + 0x11CAA: 84, + 0x11CAB: 84, + 0x11CAC: 84, + 0x11CAD: 84, + 0x11CAE: 84, + 0x11CAF: 84, + 0x11CB0: 84, + 0x11CB2: 84, + 0x11CB3: 84, + 0x11CB5: 84, + 0x11CB6: 84, + 0x11D31: 84, + 0x11D32: 84, + 0x11D33: 84, + 0x11D34: 84, + 0x11D35: 84, + 0x11D36: 84, + 0x11D3A: 84, + 0x11D3C: 84, + 0x11D3D: 84, + 0x11D3F: 84, + 0x11D40: 84, + 0x11D41: 84, + 0x11D42: 84, + 0x11D43: 84, + 0x11D44: 84, + 0x11D45: 84, + 0x11D47: 84, + 0x11D90: 84, + 0x11D91: 84, + 0x11D95: 84, + 0x11D97: 84, + 0x11EF3: 84, + 0x11EF4: 84, + 0x11F00: 84, + 0x11F01: 84, + 0x11F36: 84, + 0x11F37: 84, + 0x11F38: 84, + 0x11F39: 84, + 0x11F3A: 84, + 0x11F40: 84, + 0x11F42: 84, + 0x11F5A: 84, + 0x13430: 84, + 0x13431: 84, + 0x13432: 84, + 0x13433: 84, + 0x13434: 84, + 0x13435: 84, + 0x13436: 84, + 0x13437: 84, + 0x13438: 84, + 0x13439: 84, + 0x1343A: 84, + 0x1343B: 84, + 0x1343C: 84, + 0x1343D: 84, + 0x1343E: 84, + 0x1343F: 84, + 0x13440: 84, + 0x13447: 84, + 0x13448: 84, + 0x13449: 84, + 0x1344A: 84, + 0x1344B: 84, + 0x1344C: 84, + 0x1344D: 84, + 0x1344E: 84, + 0x1344F: 84, + 0x13450: 84, + 0x13451: 84, + 0x13452: 84, + 0x13453: 84, + 0x13454: 84, + 0x13455: 84, + 0x1611E: 84, + 0x1611F: 84, + 0x16120: 84, + 0x16121: 84, + 0x16122: 84, + 0x16123: 84, + 0x16124: 84, + 0x16125: 84, + 0x16126: 84, + 0x16127: 84, + 0x16128: 84, + 0x16129: 84, + 0x1612D: 84, + 0x1612E: 84, + 0x1612F: 84, + 0x16AF0: 84, + 0x16AF1: 84, + 0x16AF2: 84, + 0x16AF3: 84, + 0x16AF4: 84, + 0x16B30: 84, + 0x16B31: 84, + 0x16B32: 84, + 0x16B33: 84, + 0x16B34: 84, + 0x16B35: 84, + 0x16B36: 84, + 0x16F4F: 84, + 0x16F8F: 84, + 0x16F90: 84, + 0x16F91: 84, + 0x16F92: 84, + 0x16FE4: 84, + 0x1BC9D: 84, + 0x1BC9E: 84, + 0x1BCA0: 84, + 0x1BCA1: 84, + 0x1BCA2: 84, + 0x1BCA3: 84, + 0x1CF00: 84, + 0x1CF01: 84, + 0x1CF02: 84, + 0x1CF03: 84, + 0x1CF04: 84, + 0x1CF05: 84, + 0x1CF06: 84, + 0x1CF07: 84, + 0x1CF08: 84, + 0x1CF09: 84, + 0x1CF0A: 84, + 0x1CF0B: 84, + 0x1CF0C: 84, + 0x1CF0D: 84, + 0x1CF0E: 84, + 0x1CF0F: 84, + 0x1CF10: 84, + 0x1CF11: 84, + 0x1CF12: 84, + 0x1CF13: 84, + 0x1CF14: 84, + 0x1CF15: 84, + 0x1CF16: 84, + 0x1CF17: 84, + 0x1CF18: 84, + 0x1CF19: 84, + 0x1CF1A: 84, + 0x1CF1B: 84, + 0x1CF1C: 84, + 0x1CF1D: 84, + 0x1CF1E: 84, + 0x1CF1F: 84, + 0x1CF20: 84, + 0x1CF21: 84, + 0x1CF22: 84, + 0x1CF23: 84, + 0x1CF24: 84, + 0x1CF25: 84, + 0x1CF26: 84, + 0x1CF27: 84, + 0x1CF28: 84, + 0x1CF29: 84, + 0x1CF2A: 84, + 0x1CF2B: 84, + 0x1CF2C: 84, + 0x1CF2D: 84, + 0x1CF30: 84, + 0x1CF31: 84, + 0x1CF32: 84, + 0x1CF33: 84, + 0x1CF34: 84, + 0x1CF35: 84, + 0x1CF36: 84, + 0x1CF37: 84, + 0x1CF38: 84, + 0x1CF39: 84, + 0x1CF3A: 84, + 0x1CF3B: 84, + 0x1CF3C: 84, + 0x1CF3D: 84, + 0x1CF3E: 84, + 0x1CF3F: 84, + 0x1CF40: 84, + 0x1CF41: 84, + 0x1CF42: 84, + 0x1CF43: 84, + 0x1CF44: 84, + 0x1CF45: 84, + 0x1CF46: 84, + 0x1D167: 84, + 0x1D168: 84, + 0x1D169: 84, + 0x1D173: 84, + 0x1D174: 84, + 0x1D175: 84, + 0x1D176: 84, + 0x1D177: 84, + 0x1D178: 84, + 0x1D179: 84, + 0x1D17A: 84, + 0x1D17B: 84, + 0x1D17C: 84, + 0x1D17D: 84, + 0x1D17E: 84, + 0x1D17F: 84, + 0x1D180: 84, + 0x1D181: 84, + 0x1D182: 84, + 0x1D185: 84, + 0x1D186: 84, + 0x1D187: 84, + 0x1D188: 84, + 0x1D189: 84, + 0x1D18A: 84, + 0x1D18B: 84, + 0x1D1AA: 84, + 0x1D1AB: 84, + 0x1D1AC: 84, + 0x1D1AD: 84, + 0x1D242: 84, + 0x1D243: 84, + 0x1D244: 84, + 0x1DA00: 84, + 0x1DA01: 84, + 0x1DA02: 84, + 0x1DA03: 84, + 0x1DA04: 84, + 0x1DA05: 84, + 0x1DA06: 84, + 0x1DA07: 84, + 0x1DA08: 84, + 0x1DA09: 84, + 0x1DA0A: 84, + 0x1DA0B: 84, + 0x1DA0C: 84, + 0x1DA0D: 84, + 0x1DA0E: 84, + 0x1DA0F: 84, + 0x1DA10: 84, + 0x1DA11: 84, + 0x1DA12: 84, + 0x1DA13: 84, + 0x1DA14: 84, + 0x1DA15: 84, + 0x1DA16: 84, + 0x1DA17: 84, + 0x1DA18: 84, + 0x1DA19: 84, + 0x1DA1A: 84, + 0x1DA1B: 84, + 0x1DA1C: 84, + 0x1DA1D: 84, + 0x1DA1E: 84, + 0x1DA1F: 84, + 0x1DA20: 84, + 0x1DA21: 84, + 0x1DA22: 84, + 0x1DA23: 84, + 0x1DA24: 84, + 0x1DA25: 84, + 0x1DA26: 84, + 0x1DA27: 84, + 0x1DA28: 84, + 0x1DA29: 84, + 0x1DA2A: 84, + 0x1DA2B: 84, + 0x1DA2C: 84, + 0x1DA2D: 84, + 0x1DA2E: 84, + 0x1DA2F: 84, + 0x1DA30: 84, + 0x1DA31: 84, + 0x1DA32: 84, + 0x1DA33: 84, + 0x1DA34: 84, + 0x1DA35: 84, + 0x1DA36: 84, + 0x1DA3B: 84, + 0x1DA3C: 84, + 0x1DA3D: 84, + 0x1DA3E: 84, + 0x1DA3F: 84, + 0x1DA40: 84, + 0x1DA41: 84, + 0x1DA42: 84, + 0x1DA43: 84, + 0x1DA44: 84, + 0x1DA45: 84, + 0x1DA46: 84, + 0x1DA47: 84, + 0x1DA48: 84, + 0x1DA49: 84, + 0x1DA4A: 84, + 0x1DA4B: 84, + 0x1DA4C: 84, + 0x1DA4D: 84, + 0x1DA4E: 84, + 0x1DA4F: 84, + 0x1DA50: 84, + 0x1DA51: 84, + 0x1DA52: 84, + 0x1DA53: 84, + 0x1DA54: 84, + 0x1DA55: 84, + 0x1DA56: 84, + 0x1DA57: 84, + 0x1DA58: 84, + 0x1DA59: 84, + 0x1DA5A: 84, + 0x1DA5B: 84, + 0x1DA5C: 84, + 0x1DA5D: 84, + 0x1DA5E: 84, + 0x1DA5F: 84, + 0x1DA60: 84, + 0x1DA61: 84, + 0x1DA62: 84, + 0x1DA63: 84, + 0x1DA64: 84, + 0x1DA65: 84, + 0x1DA66: 84, + 0x1DA67: 84, + 0x1DA68: 84, + 0x1DA69: 84, + 0x1DA6A: 84, + 0x1DA6B: 84, + 0x1DA6C: 84, + 0x1DA75: 84, + 0x1DA84: 84, + 0x1DA9B: 84, + 0x1DA9C: 84, + 0x1DA9D: 84, + 0x1DA9E: 84, + 0x1DA9F: 84, + 0x1DAA1: 84, + 0x1DAA2: 84, + 0x1DAA3: 84, + 0x1DAA4: 84, + 0x1DAA5: 84, + 0x1DAA6: 84, + 0x1DAA7: 84, + 0x1DAA8: 84, + 0x1DAA9: 84, + 0x1DAAA: 84, + 0x1DAAB: 84, + 0x1DAAC: 84, + 0x1DAAD: 84, + 0x1DAAE: 84, + 0x1DAAF: 84, + 0x1E000: 84, + 0x1E001: 84, + 0x1E002: 84, + 0x1E003: 84, + 0x1E004: 84, + 0x1E005: 84, + 0x1E006: 84, + 0x1E008: 84, + 0x1E009: 84, + 0x1E00A: 84, + 0x1E00B: 84, + 0x1E00C: 84, + 0x1E00D: 84, + 0x1E00E: 84, + 0x1E00F: 84, + 0x1E010: 84, + 0x1E011: 84, + 0x1E012: 84, + 0x1E013: 84, + 0x1E014: 84, + 0x1E015: 84, + 0x1E016: 84, + 0x1E017: 84, + 0x1E018: 84, + 0x1E01B: 84, + 0x1E01C: 84, + 0x1E01D: 84, + 0x1E01E: 84, + 0x1E01F: 84, + 0x1E020: 84, + 0x1E021: 84, + 0x1E023: 84, + 0x1E024: 84, + 0x1E026: 84, + 0x1E027: 84, + 0x1E028: 84, + 0x1E029: 84, + 0x1E02A: 84, + 0x1E08F: 84, + 0x1E130: 84, + 0x1E131: 84, + 0x1E132: 84, + 0x1E133: 84, + 0x1E134: 84, + 0x1E135: 84, + 0x1E136: 84, + 0x1E2AE: 84, + 0x1E2EC: 84, + 0x1E2ED: 84, + 0x1E2EE: 84, + 0x1E2EF: 84, + 0x1E4EC: 84, + 0x1E4ED: 84, + 0x1E4EE: 84, + 0x1E4EF: 84, + 0x1E5EE: 84, + 0x1E5EF: 84, + 0x1E6E3: 84, + 0x1E6E6: 84, + 0x1E6EE: 84, + 0x1E6EF: 84, + 0x1E6F5: 84, + 0x1E8D0: 84, + 0x1E8D1: 84, + 0x1E8D2: 84, + 0x1E8D3: 84, + 0x1E8D4: 84, + 0x1E8D5: 84, + 0x1E8D6: 84, + 0x1E900: 68, + 0x1E901: 68, + 0x1E902: 68, + 0x1E903: 68, + 0x1E904: 68, + 0x1E905: 68, + 0x1E906: 68, + 0x1E907: 68, + 0x1E908: 68, + 0x1E909: 68, + 0x1E90A: 68, + 0x1E90B: 68, + 0x1E90C: 68, + 0x1E90D: 68, + 0x1E90E: 68, + 0x1E90F: 68, + 0x1E910: 68, + 0x1E911: 68, + 0x1E912: 68, + 0x1E913: 68, + 0x1E914: 68, + 0x1E915: 68, + 0x1E916: 68, + 0x1E917: 68, + 0x1E918: 68, + 0x1E919: 68, + 0x1E91A: 68, + 0x1E91B: 68, + 0x1E91C: 68, + 0x1E91D: 68, + 0x1E91E: 68, + 0x1E91F: 68, + 0x1E920: 68, + 0x1E921: 68, + 0x1E922: 68, + 0x1E923: 68, + 0x1E924: 68, + 0x1E925: 68, + 0x1E926: 68, + 0x1E927: 68, + 0x1E928: 68, + 0x1E929: 68, + 0x1E92A: 68, + 0x1E92B: 68, + 0x1E92C: 68, + 0x1E92D: 68, + 0x1E92E: 68, + 0x1E92F: 68, + 0x1E930: 68, + 0x1E931: 68, + 0x1E932: 68, + 0x1E933: 68, + 0x1E934: 68, + 0x1E935: 68, + 0x1E936: 68, + 0x1E937: 68, + 0x1E938: 68, + 0x1E939: 68, + 0x1E93A: 68, + 0x1E93B: 68, + 0x1E93C: 68, + 0x1E93D: 68, + 0x1E93E: 68, + 0x1E93F: 68, + 0x1E940: 68, + 0x1E941: 68, + 0x1E942: 68, + 0x1E943: 68, + 0x1E944: 84, + 0x1E945: 84, + 0x1E946: 84, + 0x1E947: 84, + 0x1E948: 84, + 0x1E949: 84, + 0x1E94A: 84, + 0x1E94B: 84, + 0xE0001: 84, + 0xE0020: 84, + 0xE0021: 84, + 0xE0022: 84, + 0xE0023: 84, + 0xE0024: 84, + 0xE0025: 84, + 0xE0026: 84, + 0xE0027: 84, + 0xE0028: 84, + 0xE0029: 84, + 0xE002A: 84, + 0xE002B: 84, + 0xE002C: 84, + 0xE002D: 84, + 0xE002E: 84, + 0xE002F: 84, + 0xE0030: 84, + 0xE0031: 84, + 0xE0032: 84, + 0xE0033: 84, + 0xE0034: 84, + 0xE0035: 84, + 0xE0036: 84, + 0xE0037: 84, + 0xE0038: 84, + 0xE0039: 84, + 0xE003A: 84, + 0xE003B: 84, + 0xE003C: 84, + 0xE003D: 84, + 0xE003E: 84, + 0xE003F: 84, + 0xE0040: 84, + 0xE0041: 84, + 0xE0042: 84, + 0xE0043: 84, + 0xE0044: 84, + 0xE0045: 84, + 0xE0046: 84, + 0xE0047: 84, + 0xE0048: 84, + 0xE0049: 84, + 0xE004A: 84, + 0xE004B: 84, + 0xE004C: 84, + 0xE004D: 84, + 0xE004E: 84, + 0xE004F: 84, + 0xE0050: 84, + 0xE0051: 84, + 0xE0052: 84, + 0xE0053: 84, + 0xE0054: 84, + 0xE0055: 84, + 0xE0056: 84, + 0xE0057: 84, + 0xE0058: 84, + 0xE0059: 84, + 0xE005A: 84, + 0xE005B: 84, + 0xE005C: 84, + 0xE005D: 84, + 0xE005E: 84, + 0xE005F: 84, + 0xE0060: 84, + 0xE0061: 84, + 0xE0062: 84, + 0xE0063: 84, + 0xE0064: 84, + 0xE0065: 84, + 0xE0066: 84, + 0xE0067: 84, + 0xE0068: 84, + 0xE0069: 84, + 0xE006A: 84, + 0xE006B: 84, + 0xE006C: 84, + 0xE006D: 84, + 0xE006E: 84, + 0xE006F: 84, + 0xE0070: 84, + 0xE0071: 84, + 0xE0072: 84, + 0xE0073: 84, + 0xE0074: 84, + 0xE0075: 84, + 0xE0076: 84, + 0xE0077: 84, + 0xE0078: 84, + 0xE0079: 84, + 0xE007A: 84, + 0xE007B: 84, + 0xE007C: 84, + 0xE007D: 84, + 0xE007E: 84, + 0xE007F: 84, + 0xE0100: 84, + 0xE0101: 84, + 0xE0102: 84, + 0xE0103: 84, + 0xE0104: 84, + 0xE0105: 84, + 0xE0106: 84, + 0xE0107: 84, + 0xE0108: 84, + 0xE0109: 84, + 0xE010A: 84, + 0xE010B: 84, + 0xE010C: 84, + 0xE010D: 84, + 0xE010E: 84, + 0xE010F: 84, + 0xE0110: 84, + 0xE0111: 84, + 0xE0112: 84, + 0xE0113: 84, + 0xE0114: 84, + 0xE0115: 84, + 0xE0116: 84, + 0xE0117: 84, + 0xE0118: 84, + 0xE0119: 84, + 0xE011A: 84, + 0xE011B: 84, + 0xE011C: 84, + 0xE011D: 84, + 0xE011E: 84, + 0xE011F: 84, + 0xE0120: 84, + 0xE0121: 84, + 0xE0122: 84, + 0xE0123: 84, + 0xE0124: 84, + 0xE0125: 84, + 0xE0126: 84, + 0xE0127: 84, + 0xE0128: 84, + 0xE0129: 84, + 0xE012A: 84, + 0xE012B: 84, + 0xE012C: 84, + 0xE012D: 84, + 0xE012E: 84, + 0xE012F: 84, + 0xE0130: 84, + 0xE0131: 84, + 0xE0132: 84, + 0xE0133: 84, + 0xE0134: 84, + 0xE0135: 84, + 0xE0136: 84, + 0xE0137: 84, + 0xE0138: 84, + 0xE0139: 84, + 0xE013A: 84, + 0xE013B: 84, + 0xE013C: 84, + 0xE013D: 84, + 0xE013E: 84, + 0xE013F: 84, + 0xE0140: 84, + 0xE0141: 84, + 0xE0142: 84, + 0xE0143: 84, + 0xE0144: 84, + 0xE0145: 84, + 0xE0146: 84, + 0xE0147: 84, + 0xE0148: 84, + 0xE0149: 84, + 0xE014A: 84, + 0xE014B: 84, + 0xE014C: 84, + 0xE014D: 84, + 0xE014E: 84, + 0xE014F: 84, + 0xE0150: 84, + 0xE0151: 84, + 0xE0152: 84, + 0xE0153: 84, + 0xE0154: 84, + 0xE0155: 84, + 0xE0156: 84, + 0xE0157: 84, + 0xE0158: 84, + 0xE0159: 84, + 0xE015A: 84, + 0xE015B: 84, + 0xE015C: 84, + 0xE015D: 84, + 0xE015E: 84, + 0xE015F: 84, + 0xE0160: 84, + 0xE0161: 84, + 0xE0162: 84, + 0xE0163: 84, + 0xE0164: 84, + 0xE0165: 84, + 0xE0166: 84, + 0xE0167: 84, + 0xE0168: 84, + 0xE0169: 84, + 0xE016A: 84, + 0xE016B: 84, + 0xE016C: 84, + 0xE016D: 84, + 0xE016E: 84, + 0xE016F: 84, + 0xE0170: 84, + 0xE0171: 84, + 0xE0172: 84, + 0xE0173: 84, + 0xE0174: 84, + 0xE0175: 84, + 0xE0176: 84, + 0xE0177: 84, + 0xE0178: 84, + 0xE0179: 84, + 0xE017A: 84, + 0xE017B: 84, + 0xE017C: 84, + 0xE017D: 84, + 0xE017E: 84, + 0xE017F: 84, + 0xE0180: 84, + 0xE0181: 84, + 0xE0182: 84, + 0xE0183: 84, + 0xE0184: 84, + 0xE0185: 84, + 0xE0186: 84, + 0xE0187: 84, + 0xE0188: 84, + 0xE0189: 84, + 0xE018A: 84, + 0xE018B: 84, + 0xE018C: 84, + 0xE018D: 84, + 0xE018E: 84, + 0xE018F: 84, + 0xE0190: 84, + 0xE0191: 84, + 0xE0192: 84, + 0xE0193: 84, + 0xE0194: 84, + 0xE0195: 84, + 0xE0196: 84, + 0xE0197: 84, + 0xE0198: 84, + 0xE0199: 84, + 0xE019A: 84, + 0xE019B: 84, + 0xE019C: 84, + 0xE019D: 84, + 0xE019E: 84, + 0xE019F: 84, + 0xE01A0: 84, + 0xE01A1: 84, + 0xE01A2: 84, + 0xE01A3: 84, + 0xE01A4: 84, + 0xE01A5: 84, + 0xE01A6: 84, + 0xE01A7: 84, + 0xE01A8: 84, + 0xE01A9: 84, + 0xE01AA: 84, + 0xE01AB: 84, + 0xE01AC: 84, + 0xE01AD: 84, + 0xE01AE: 84, + 0xE01AF: 84, + 0xE01B0: 84, + 0xE01B1: 84, + 0xE01B2: 84, + 0xE01B3: 84, + 0xE01B4: 84, + 0xE01B5: 84, + 0xE01B6: 84, + 0xE01B7: 84, + 0xE01B8: 84, + 0xE01B9: 84, + 0xE01BA: 84, + 0xE01BB: 84, + 0xE01BC: 84, + 0xE01BD: 84, + 0xE01BE: 84, + 0xE01BF: 84, + 0xE01C0: 84, + 0xE01C1: 84, + 0xE01C2: 84, + 0xE01C3: 84, + 0xE01C4: 84, + 0xE01C5: 84, + 0xE01C6: 84, + 0xE01C7: 84, + 0xE01C8: 84, + 0xE01C9: 84, + 0xE01CA: 84, + 0xE01CB: 84, + 0xE01CC: 84, + 0xE01CD: 84, + 0xE01CE: 84, + 0xE01CF: 84, + 0xE01D0: 84, + 0xE01D1: 84, + 0xE01D2: 84, + 0xE01D3: 84, + 0xE01D4: 84, + 0xE01D5: 84, + 0xE01D6: 84, + 0xE01D7: 84, + 0xE01D8: 84, + 0xE01D9: 84, + 0xE01DA: 84, + 0xE01DB: 84, + 0xE01DC: 84, + 0xE01DD: 84, + 0xE01DE: 84, + 0xE01DF: 84, + 0xE01E0: 84, + 0xE01E1: 84, + 0xE01E2: 84, + 0xE01E3: 84, + 0xE01E4: 84, + 0xE01E5: 84, + 0xE01E6: 84, + 0xE01E7: 84, + 0xE01E8: 84, + 0xE01E9: 84, + 0xE01EA: 84, + 0xE01EB: 84, + 0xE01EC: 84, + 0xE01ED: 84, + 0xE01EE: 84, + 0xE01EF: 84, + } + + +codepoint_classes = { + "PVALID": ( + 0x2D0000002E, + 0x300000003A, + 0x610000007B, + 0xDF000000F7, + 0xF800000100, + 0x10100000102, + 0x10300000104, + 0x10500000106, + 0x10700000108, + 0x1090000010A, + 0x10B0000010C, + 0x10D0000010E, + 0x10F00000110, + 0x11100000112, + 0x11300000114, + 0x11500000116, + 0x11700000118, + 0x1190000011A, + 0x11B0000011C, + 0x11D0000011E, + 0x11F00000120, + 0x12100000122, + 0x12300000124, + 0x12500000126, + 0x12700000128, + 0x1290000012A, + 0x12B0000012C, + 0x12D0000012E, + 0x12F00000130, + 0x13100000132, + 0x13500000136, + 0x13700000139, + 0x13A0000013B, + 0x13C0000013D, + 0x13E0000013F, + 0x14200000143, + 0x14400000145, + 0x14600000147, + 0x14800000149, + 0x14B0000014C, + 0x14D0000014E, + 0x14F00000150, + 0x15100000152, + 0x15300000154, + 0x15500000156, + 0x15700000158, + 0x1590000015A, + 0x15B0000015C, + 0x15D0000015E, + 0x15F00000160, + 0x16100000162, + 0x16300000164, + 0x16500000166, + 0x16700000168, + 0x1690000016A, + 0x16B0000016C, + 0x16D0000016E, + 0x16F00000170, + 0x17100000172, + 0x17300000174, + 0x17500000176, + 0x17700000178, + 0x17A0000017B, + 0x17C0000017D, + 0x17E0000017F, + 0x18000000181, + 0x18300000184, + 0x18500000186, + 0x18800000189, + 0x18C0000018E, + 0x19200000193, + 0x19500000196, + 0x1990000019C, + 0x19E0000019F, + 0x1A1000001A2, + 0x1A3000001A4, + 0x1A5000001A6, + 0x1A8000001A9, + 0x1AA000001AC, + 0x1AD000001AE, + 0x1B0000001B1, + 0x1B4000001B5, + 0x1B6000001B7, + 0x1B9000001BC, + 0x1BD000001C4, + 0x1CE000001CF, + 0x1D0000001D1, + 0x1D2000001D3, + 0x1D4000001D5, + 0x1D6000001D7, + 0x1D8000001D9, + 0x1DA000001DB, + 0x1DC000001DE, + 0x1DF000001E0, + 0x1E1000001E2, + 0x1E3000001E4, + 0x1E5000001E6, + 0x1E7000001E8, + 0x1E9000001EA, + 0x1EB000001EC, + 0x1ED000001EE, + 0x1EF000001F1, + 0x1F5000001F6, + 0x1F9000001FA, + 0x1FB000001FC, + 0x1FD000001FE, + 0x1FF00000200, + 0x20100000202, + 0x20300000204, + 0x20500000206, + 0x20700000208, + 0x2090000020A, + 0x20B0000020C, + 0x20D0000020E, + 0x20F00000210, + 0x21100000212, + 0x21300000214, + 0x21500000216, + 0x21700000218, + 0x2190000021A, + 0x21B0000021C, + 0x21D0000021E, + 0x21F00000220, + 0x22100000222, + 0x22300000224, + 0x22500000226, + 0x22700000228, + 0x2290000022A, + 0x22B0000022C, + 0x22D0000022E, + 0x22F00000230, + 0x23100000232, + 0x2330000023A, + 0x23C0000023D, + 0x23F00000241, + 0x24200000243, + 0x24700000248, + 0x2490000024A, + 0x24B0000024C, + 0x24D0000024E, + 0x24F000002B0, + 0x2B9000002C2, + 0x2C6000002D2, + 0x2EC000002ED, + 0x2EE000002EF, + 0x30000000340, + 0x34200000343, + 0x3460000034F, + 0x35000000370, + 0x37100000372, + 0x37300000374, + 0x37700000378, + 0x37B0000037E, + 0x39000000391, + 0x3AC000003CF, + 0x3D7000003D8, + 0x3D9000003DA, + 0x3DB000003DC, + 0x3DD000003DE, + 0x3DF000003E0, + 0x3E1000003E2, + 0x3E3000003E4, + 0x3E5000003E6, + 0x3E7000003E8, + 0x3E9000003EA, + 0x3EB000003EC, + 0x3ED000003EE, + 0x3EF000003F0, + 0x3F3000003F4, + 0x3F8000003F9, + 0x3FB000003FD, + 0x43000000460, + 0x46100000462, + 0x46300000464, + 0x46500000466, + 0x46700000468, + 0x4690000046A, + 0x46B0000046C, + 0x46D0000046E, + 0x46F00000470, + 0x47100000472, + 0x47300000474, + 0x47500000476, + 0x47700000478, + 0x4790000047A, + 0x47B0000047C, + 0x47D0000047E, + 0x47F00000480, + 0x48100000482, + 0x48300000488, + 0x48B0000048C, + 0x48D0000048E, + 0x48F00000490, + 0x49100000492, + 0x49300000494, + 0x49500000496, + 0x49700000498, + 0x4990000049A, + 0x49B0000049C, + 0x49D0000049E, + 0x49F000004A0, + 0x4A1000004A2, + 0x4A3000004A4, + 0x4A5000004A6, + 0x4A7000004A8, + 0x4A9000004AA, + 0x4AB000004AC, + 0x4AD000004AE, + 0x4AF000004B0, + 0x4B1000004B2, + 0x4B3000004B4, + 0x4B5000004B6, + 0x4B7000004B8, + 0x4B9000004BA, + 0x4BB000004BC, + 0x4BD000004BE, + 0x4BF000004C0, + 0x4C2000004C3, + 0x4C4000004C5, + 0x4C6000004C7, + 0x4C8000004C9, + 0x4CA000004CB, + 0x4CC000004CD, + 0x4CE000004D0, + 0x4D1000004D2, + 0x4D3000004D4, + 0x4D5000004D6, + 0x4D7000004D8, + 0x4D9000004DA, + 0x4DB000004DC, + 0x4DD000004DE, + 0x4DF000004E0, + 0x4E1000004E2, + 0x4E3000004E4, + 0x4E5000004E6, + 0x4E7000004E8, + 0x4E9000004EA, + 0x4EB000004EC, + 0x4ED000004EE, + 0x4EF000004F0, + 0x4F1000004F2, + 0x4F3000004F4, + 0x4F5000004F6, + 0x4F7000004F8, + 0x4F9000004FA, + 0x4FB000004FC, + 0x4FD000004FE, + 0x4FF00000500, + 0x50100000502, + 0x50300000504, + 0x50500000506, + 0x50700000508, + 0x5090000050A, + 0x50B0000050C, + 0x50D0000050E, + 0x50F00000510, + 0x51100000512, + 0x51300000514, + 0x51500000516, + 0x51700000518, + 0x5190000051A, + 0x51B0000051C, + 0x51D0000051E, + 0x51F00000520, + 0x52100000522, + 0x52300000524, + 0x52500000526, + 0x52700000528, + 0x5290000052A, + 0x52B0000052C, + 0x52D0000052E, + 0x52F00000530, + 0x5590000055A, + 0x56000000587, + 0x58800000589, + 0x591000005BE, + 0x5BF000005C0, + 0x5C1000005C3, + 0x5C4000005C6, + 0x5C7000005C8, + 0x5D0000005EB, + 0x5EF000005F3, + 0x6100000061B, + 0x62000000640, + 0x64100000660, + 0x66E00000675, + 0x679000006D4, + 0x6D5000006DD, + 0x6DF000006E9, + 0x6EA000006F0, + 0x6FA00000700, + 0x7100000074B, + 0x74D000007B2, + 0x7C0000007F6, + 0x7FD000007FE, + 0x8000000082E, + 0x8400000085C, + 0x8600000086B, + 0x87000000888, + 0x88900000890, + 0x897000008E2, + 0x8E300000958, + 0x96000000964, + 0x96600000970, + 0x97100000984, + 0x9850000098D, + 0x98F00000991, + 0x993000009A9, + 0x9AA000009B1, + 0x9B2000009B3, + 0x9B6000009BA, + 0x9BC000009C5, + 0x9C7000009C9, + 0x9CB000009CF, + 0x9D7000009D8, + 0x9E0000009E4, + 0x9E6000009F2, + 0x9FC000009FD, + 0x9FE000009FF, + 0xA0100000A04, + 0xA0500000A0B, + 0xA0F00000A11, + 0xA1300000A29, + 0xA2A00000A31, + 0xA3200000A33, + 0xA3500000A36, + 0xA3800000A3A, + 0xA3C00000A3D, + 0xA3E00000A43, + 0xA4700000A49, + 0xA4B00000A4E, + 0xA5100000A52, + 0xA5C00000A5D, + 0xA6600000A76, + 0xA8100000A84, + 0xA8500000A8E, + 0xA8F00000A92, + 0xA9300000AA9, + 0xAAA00000AB1, + 0xAB200000AB4, + 0xAB500000ABA, + 0xABC00000AC6, + 0xAC700000ACA, + 0xACB00000ACE, + 0xAD000000AD1, + 0xAE000000AE4, + 0xAE600000AF0, + 0xAF900000B00, + 0xB0100000B04, + 0xB0500000B0D, + 0xB0F00000B11, + 0xB1300000B29, + 0xB2A00000B31, + 0xB3200000B34, + 0xB3500000B3A, + 0xB3C00000B45, + 0xB4700000B49, + 0xB4B00000B4E, + 0xB5500000B58, + 0xB5F00000B64, + 0xB6600000B70, + 0xB7100000B72, + 0xB8200000B84, + 0xB8500000B8B, + 0xB8E00000B91, + 0xB9200000B96, + 0xB9900000B9B, + 0xB9C00000B9D, + 0xB9E00000BA0, + 0xBA300000BA5, + 0xBA800000BAB, + 0xBAE00000BBA, + 0xBBE00000BC3, + 0xBC600000BC9, + 0xBCA00000BCE, + 0xBD000000BD1, + 0xBD700000BD8, + 0xBE600000BF0, + 0xC0000000C0D, + 0xC0E00000C11, + 0xC1200000C29, + 0xC2A00000C3A, + 0xC3C00000C45, + 0xC4600000C49, + 0xC4A00000C4E, + 0xC5500000C57, + 0xC5800000C5B, + 0xC5C00000C5E, + 0xC6000000C64, + 0xC6600000C70, + 0xC8000000C84, + 0xC8500000C8D, + 0xC8E00000C91, + 0xC9200000CA9, + 0xCAA00000CB4, + 0xCB500000CBA, + 0xCBC00000CC5, + 0xCC600000CC9, + 0xCCA00000CCE, + 0xCD500000CD7, + 0xCDC00000CDF, + 0xCE000000CE4, + 0xCE600000CF0, + 0xCF100000CF4, + 0xD0000000D0D, + 0xD0E00000D11, + 0xD1200000D45, + 0xD4600000D49, + 0xD4A00000D4F, + 0xD5400000D58, + 0xD5F00000D64, + 0xD6600000D70, + 0xD7A00000D80, + 0xD8100000D84, + 0xD8500000D97, + 0xD9A00000DB2, + 0xDB300000DBC, + 0xDBD00000DBE, + 0xDC000000DC7, + 0xDCA00000DCB, + 0xDCF00000DD5, + 0xDD600000DD7, + 0xDD800000DE0, + 0xDE600000DF0, + 0xDF200000DF4, + 0xE0100000E33, + 0xE3400000E3B, + 0xE4000000E4F, + 0xE5000000E5A, + 0xE8100000E83, + 0xE8400000E85, + 0xE8600000E8B, + 0xE8C00000EA4, + 0xEA500000EA6, + 0xEA700000EB3, + 0xEB400000EBE, + 0xEC000000EC5, + 0xEC600000EC7, + 0xEC800000ECF, + 0xED000000EDA, + 0xEDE00000EE0, + 0xF0000000F01, + 0xF0B00000F0C, + 0xF1800000F1A, + 0xF2000000F2A, + 0xF3500000F36, + 0xF3700000F38, + 0xF3900000F3A, + 0xF3E00000F43, + 0xF4400000F48, + 0xF4900000F4D, + 0xF4E00000F52, + 0xF5300000F57, + 0xF5800000F5C, + 0xF5D00000F69, + 0xF6A00000F6D, + 0xF7100000F73, + 0xF7400000F75, + 0xF7A00000F81, + 0xF8200000F85, + 0xF8600000F93, + 0xF9400000F98, + 0xF9900000F9D, + 0xF9E00000FA2, + 0xFA300000FA7, + 0xFA800000FAC, + 0xFAD00000FB9, + 0xFBA00000FBD, + 0xFC600000FC7, + 0x10000000104A, + 0x10500000109E, + 0x10D0000010FB, + 0x10FD00001100, + 0x120000001249, + 0x124A0000124E, + 0x125000001257, + 0x125800001259, + 0x125A0000125E, + 0x126000001289, + 0x128A0000128E, + 0x1290000012B1, + 0x12B2000012B6, + 0x12B8000012BF, + 0x12C0000012C1, + 0x12C2000012C6, + 0x12C8000012D7, + 0x12D800001311, + 0x131200001316, + 0x13180000135B, + 0x135D00001360, + 0x138000001390, + 0x13A0000013F6, + 0x14010000166D, + 0x166F00001680, + 0x16810000169B, + 0x16A0000016EB, + 0x16F1000016F9, + 0x170000001716, + 0x171F00001735, + 0x174000001754, + 0x17600000176D, + 0x176E00001771, + 0x177200001774, + 0x1780000017B4, + 0x17B6000017D4, + 0x17D7000017D8, + 0x17DC000017DE, + 0x17E0000017EA, + 0x18100000181A, + 0x182000001879, + 0x1880000018AB, + 0x18B0000018F6, + 0x19000000191F, + 0x19200000192C, + 0x19300000193C, + 0x19460000196E, + 0x197000001975, + 0x1980000019AC, + 0x19B0000019CA, + 0x19D0000019DA, + 0x1A0000001A1C, + 0x1A2000001A5F, + 0x1A6000001A7D, + 0x1A7F00001A8A, + 0x1A9000001A9A, + 0x1AA700001AA8, + 0x1AB000001ABE, + 0x1ABF00001ADE, + 0x1AE000001AEC, + 0x1B0000001B4D, + 0x1B5000001B5A, + 0x1B6B00001B74, + 0x1B8000001BF4, + 0x1C0000001C38, + 0x1C4000001C4A, + 0x1C4D00001C7E, + 0x1C8A00001C8B, + 0x1CD000001CD3, + 0x1CD400001CFB, + 0x1D0000001D2C, + 0x1D2F00001D30, + 0x1D3B00001D3C, + 0x1D4E00001D4F, + 0x1D6B00001D78, + 0x1D7900001D9B, + 0x1DC000001E00, + 0x1E0100001E02, + 0x1E0300001E04, + 0x1E0500001E06, + 0x1E0700001E08, + 0x1E0900001E0A, + 0x1E0B00001E0C, + 0x1E0D00001E0E, + 0x1E0F00001E10, + 0x1E1100001E12, + 0x1E1300001E14, + 0x1E1500001E16, + 0x1E1700001E18, + 0x1E1900001E1A, + 0x1E1B00001E1C, + 0x1E1D00001E1E, + 0x1E1F00001E20, + 0x1E2100001E22, + 0x1E2300001E24, + 0x1E2500001E26, + 0x1E2700001E28, + 0x1E2900001E2A, + 0x1E2B00001E2C, + 0x1E2D00001E2E, + 0x1E2F00001E30, + 0x1E3100001E32, + 0x1E3300001E34, + 0x1E3500001E36, + 0x1E3700001E38, + 0x1E3900001E3A, + 0x1E3B00001E3C, + 0x1E3D00001E3E, + 0x1E3F00001E40, + 0x1E4100001E42, + 0x1E4300001E44, + 0x1E4500001E46, + 0x1E4700001E48, + 0x1E4900001E4A, + 0x1E4B00001E4C, + 0x1E4D00001E4E, + 0x1E4F00001E50, + 0x1E5100001E52, + 0x1E5300001E54, + 0x1E5500001E56, + 0x1E5700001E58, + 0x1E5900001E5A, + 0x1E5B00001E5C, + 0x1E5D00001E5E, + 0x1E5F00001E60, + 0x1E6100001E62, + 0x1E6300001E64, + 0x1E6500001E66, + 0x1E6700001E68, + 0x1E6900001E6A, + 0x1E6B00001E6C, + 0x1E6D00001E6E, + 0x1E6F00001E70, + 0x1E7100001E72, + 0x1E7300001E74, + 0x1E7500001E76, + 0x1E7700001E78, + 0x1E7900001E7A, + 0x1E7B00001E7C, + 0x1E7D00001E7E, + 0x1E7F00001E80, + 0x1E8100001E82, + 0x1E8300001E84, + 0x1E8500001E86, + 0x1E8700001E88, + 0x1E8900001E8A, + 0x1E8B00001E8C, + 0x1E8D00001E8E, + 0x1E8F00001E90, + 0x1E9100001E92, + 0x1E9300001E94, + 0x1E9500001E9A, + 0x1E9C00001E9E, + 0x1E9F00001EA0, + 0x1EA100001EA2, + 0x1EA300001EA4, + 0x1EA500001EA6, + 0x1EA700001EA8, + 0x1EA900001EAA, + 0x1EAB00001EAC, + 0x1EAD00001EAE, + 0x1EAF00001EB0, + 0x1EB100001EB2, + 0x1EB300001EB4, + 0x1EB500001EB6, + 0x1EB700001EB8, + 0x1EB900001EBA, + 0x1EBB00001EBC, + 0x1EBD00001EBE, + 0x1EBF00001EC0, + 0x1EC100001EC2, + 0x1EC300001EC4, + 0x1EC500001EC6, + 0x1EC700001EC8, + 0x1EC900001ECA, + 0x1ECB00001ECC, + 0x1ECD00001ECE, + 0x1ECF00001ED0, + 0x1ED100001ED2, + 0x1ED300001ED4, + 0x1ED500001ED6, + 0x1ED700001ED8, + 0x1ED900001EDA, + 0x1EDB00001EDC, + 0x1EDD00001EDE, + 0x1EDF00001EE0, + 0x1EE100001EE2, + 0x1EE300001EE4, + 0x1EE500001EE6, + 0x1EE700001EE8, + 0x1EE900001EEA, + 0x1EEB00001EEC, + 0x1EED00001EEE, + 0x1EEF00001EF0, + 0x1EF100001EF2, + 0x1EF300001EF4, + 0x1EF500001EF6, + 0x1EF700001EF8, + 0x1EF900001EFA, + 0x1EFB00001EFC, + 0x1EFD00001EFE, + 0x1EFF00001F08, + 0x1F1000001F16, + 0x1F2000001F28, + 0x1F3000001F38, + 0x1F4000001F46, + 0x1F5000001F58, + 0x1F6000001F68, + 0x1F7000001F71, + 0x1F7200001F73, + 0x1F7400001F75, + 0x1F7600001F77, + 0x1F7800001F79, + 0x1F7A00001F7B, + 0x1F7C00001F7D, + 0x1FB000001FB2, + 0x1FB600001FB7, + 0x1FC600001FC7, + 0x1FD000001FD3, + 0x1FD600001FD8, + 0x1FE000001FE3, + 0x1FE400001FE8, + 0x1FF600001FF7, + 0x214E0000214F, + 0x218400002185, + 0x2C3000002C60, + 0x2C6100002C62, + 0x2C6500002C67, + 0x2C6800002C69, + 0x2C6A00002C6B, + 0x2C6C00002C6D, + 0x2C7100002C72, + 0x2C7300002C75, + 0x2C7600002C7C, + 0x2C8100002C82, + 0x2C8300002C84, + 0x2C8500002C86, + 0x2C8700002C88, + 0x2C8900002C8A, + 0x2C8B00002C8C, + 0x2C8D00002C8E, + 0x2C8F00002C90, + 0x2C9100002C92, + 0x2C9300002C94, + 0x2C9500002C96, + 0x2C9700002C98, + 0x2C9900002C9A, + 0x2C9B00002C9C, + 0x2C9D00002C9E, + 0x2C9F00002CA0, + 0x2CA100002CA2, + 0x2CA300002CA4, + 0x2CA500002CA6, + 0x2CA700002CA8, + 0x2CA900002CAA, + 0x2CAB00002CAC, + 0x2CAD00002CAE, + 0x2CAF00002CB0, + 0x2CB100002CB2, + 0x2CB300002CB4, + 0x2CB500002CB6, + 0x2CB700002CB8, + 0x2CB900002CBA, + 0x2CBB00002CBC, + 0x2CBD00002CBE, + 0x2CBF00002CC0, + 0x2CC100002CC2, + 0x2CC300002CC4, + 0x2CC500002CC6, + 0x2CC700002CC8, + 0x2CC900002CCA, + 0x2CCB00002CCC, + 0x2CCD00002CCE, + 0x2CCF00002CD0, + 0x2CD100002CD2, + 0x2CD300002CD4, + 0x2CD500002CD6, + 0x2CD700002CD8, + 0x2CD900002CDA, + 0x2CDB00002CDC, + 0x2CDD00002CDE, + 0x2CDF00002CE0, + 0x2CE100002CE2, + 0x2CE300002CE5, + 0x2CEC00002CED, + 0x2CEE00002CF2, + 0x2CF300002CF4, + 0x2D0000002D26, + 0x2D2700002D28, + 0x2D2D00002D2E, + 0x2D3000002D68, + 0x2D7F00002D97, + 0x2DA000002DA7, + 0x2DA800002DAF, + 0x2DB000002DB7, + 0x2DB800002DBF, + 0x2DC000002DC7, + 0x2DC800002DCF, + 0x2DD000002DD7, + 0x2DD800002DDF, + 0x2DE000002E00, + 0x2E2F00002E30, + 0x300500003008, + 0x302A0000302E, + 0x303C0000303D, + 0x304100003097, + 0x30990000309B, + 0x309D0000309F, + 0x30A1000030FB, + 0x30FC000030FF, + 0x310500003130, + 0x31A0000031C0, + 0x31F000003200, + 0x340000004DC0, + 0x4E000000A48D, + 0xA4D00000A4FE, + 0xA5000000A60D, + 0xA6100000A62C, + 0xA6410000A642, + 0xA6430000A644, + 0xA6450000A646, + 0xA6470000A648, + 0xA6490000A64A, + 0xA64B0000A64C, + 0xA64D0000A64E, + 0xA64F0000A650, + 0xA6510000A652, + 0xA6530000A654, + 0xA6550000A656, + 0xA6570000A658, + 0xA6590000A65A, + 0xA65B0000A65C, + 0xA65D0000A65E, + 0xA65F0000A660, + 0xA6610000A662, + 0xA6630000A664, + 0xA6650000A666, + 0xA6670000A668, + 0xA6690000A66A, + 0xA66B0000A66C, + 0xA66D0000A670, + 0xA6740000A67E, + 0xA67F0000A680, + 0xA6810000A682, + 0xA6830000A684, + 0xA6850000A686, + 0xA6870000A688, + 0xA6890000A68A, + 0xA68B0000A68C, + 0xA68D0000A68E, + 0xA68F0000A690, + 0xA6910000A692, + 0xA6930000A694, + 0xA6950000A696, + 0xA6970000A698, + 0xA6990000A69A, + 0xA69B0000A69C, + 0xA69E0000A6E6, + 0xA6F00000A6F2, + 0xA7170000A720, + 0xA7230000A724, + 0xA7250000A726, + 0xA7270000A728, + 0xA7290000A72A, + 0xA72B0000A72C, + 0xA72D0000A72E, + 0xA72F0000A732, + 0xA7330000A734, + 0xA7350000A736, + 0xA7370000A738, + 0xA7390000A73A, + 0xA73B0000A73C, + 0xA73D0000A73E, + 0xA73F0000A740, + 0xA7410000A742, + 0xA7430000A744, + 0xA7450000A746, + 0xA7470000A748, + 0xA7490000A74A, + 0xA74B0000A74C, + 0xA74D0000A74E, + 0xA74F0000A750, + 0xA7510000A752, + 0xA7530000A754, + 0xA7550000A756, + 0xA7570000A758, + 0xA7590000A75A, + 0xA75B0000A75C, + 0xA75D0000A75E, + 0xA75F0000A760, + 0xA7610000A762, + 0xA7630000A764, + 0xA7650000A766, + 0xA7670000A768, + 0xA7690000A76A, + 0xA76B0000A76C, + 0xA76D0000A76E, + 0xA76F0000A770, + 0xA7710000A779, + 0xA77A0000A77B, + 0xA77C0000A77D, + 0xA77F0000A780, + 0xA7810000A782, + 0xA7830000A784, + 0xA7850000A786, + 0xA7870000A789, + 0xA78C0000A78D, + 0xA78E0000A790, + 0xA7910000A792, + 0xA7930000A796, + 0xA7970000A798, + 0xA7990000A79A, + 0xA79B0000A79C, + 0xA79D0000A79E, + 0xA79F0000A7A0, + 0xA7A10000A7A2, + 0xA7A30000A7A4, + 0xA7A50000A7A6, + 0xA7A70000A7A8, + 0xA7A90000A7AA, + 0xA7AF0000A7B0, + 0xA7B50000A7B6, + 0xA7B70000A7B8, + 0xA7B90000A7BA, + 0xA7BB0000A7BC, + 0xA7BD0000A7BE, + 0xA7BF0000A7C0, + 0xA7C10000A7C2, + 0xA7C30000A7C4, + 0xA7C80000A7C9, + 0xA7CA0000A7CB, + 0xA7CD0000A7CE, + 0xA7CF0000A7D0, + 0xA7D10000A7D2, + 0xA7D30000A7D4, + 0xA7D50000A7D6, + 0xA7D70000A7D8, + 0xA7D90000A7DA, + 0xA7DB0000A7DC, + 0xA7F60000A7F8, + 0xA7FA0000A828, + 0xA82C0000A82D, + 0xA8400000A874, + 0xA8800000A8C6, + 0xA8D00000A8DA, + 0xA8E00000A8F8, + 0xA8FB0000A8FC, + 0xA8FD0000A92E, + 0xA9300000A954, + 0xA9800000A9C1, + 0xA9CF0000A9DA, + 0xA9E00000A9FF, + 0xAA000000AA37, + 0xAA400000AA4E, + 0xAA500000AA5A, + 0xAA600000AA77, + 0xAA7A0000AAC3, + 0xAADB0000AADE, + 0xAAE00000AAF0, + 0xAAF20000AAF7, + 0xAB010000AB07, + 0xAB090000AB0F, + 0xAB110000AB17, + 0xAB200000AB27, + 0xAB280000AB2F, + 0xAB300000AB5B, + 0xAB600000AB69, + 0xABC00000ABEB, + 0xABEC0000ABEE, + 0xABF00000ABFA, + 0xAC000000D7A4, + 0xFA0E0000FA10, + 0xFA110000FA12, + 0xFA130000FA15, + 0xFA1F0000FA20, + 0xFA210000FA22, + 0xFA230000FA25, + 0xFA270000FA2A, + 0xFB1E0000FB1F, + 0xFE200000FE30, + 0xFE730000FE74, + 0x100000001000C, + 0x1000D00010027, + 0x100280001003B, + 0x1003C0001003E, + 0x1003F0001004E, + 0x100500001005E, + 0x10080000100FB, + 0x101FD000101FE, + 0x102800001029D, + 0x102A0000102D1, + 0x102E0000102E1, + 0x1030000010320, + 0x1032D00010341, + 0x103420001034A, + 0x103500001037B, + 0x103800001039E, + 0x103A0000103C4, + 0x103C8000103D0, + 0x104280001049E, + 0x104A0000104AA, + 0x104D8000104FC, + 0x1050000010528, + 0x1053000010564, + 0x10597000105A2, + 0x105A3000105B2, + 0x105B3000105BA, + 0x105BB000105BD, + 0x105C0000105F4, + 0x1060000010737, + 0x1074000010756, + 0x1076000010768, + 0x1078000010781, + 0x1080000010806, + 0x1080800010809, + 0x1080A00010836, + 0x1083700010839, + 0x1083C0001083D, + 0x1083F00010856, + 0x1086000010877, + 0x108800001089F, + 0x108E0000108F3, + 0x108F4000108F6, + 0x1090000010916, + 0x109200001093A, + 0x109400001095A, + 0x10980000109B8, + 0x109BE000109C0, + 0x10A0000010A04, + 0x10A0500010A07, + 0x10A0C00010A14, + 0x10A1500010A18, + 0x10A1900010A36, + 0x10A3800010A3B, + 0x10A3F00010A40, + 0x10A6000010A7D, + 0x10A8000010A9D, + 0x10AC000010AC8, + 0x10AC900010AE7, + 0x10B0000010B36, + 0x10B4000010B56, + 0x10B6000010B73, + 0x10B8000010B92, + 0x10C0000010C49, + 0x10CC000010CF3, + 0x10D0000010D28, + 0x10D3000010D3A, + 0x10D4000010D50, + 0x10D6900010D6E, + 0x10D6F00010D86, + 0x10E8000010EAA, + 0x10EAB00010EAD, + 0x10EB000010EB2, + 0x10EC200010EC8, + 0x10EFA00010F1D, + 0x10F2700010F28, + 0x10F3000010F51, + 0x10F7000010F86, + 0x10FB000010FC5, + 0x10FE000010FF7, + 0x1100000011047, + 0x1106600011076, + 0x1107F000110BB, + 0x110C2000110C3, + 0x110D0000110E9, + 0x110F0000110FA, + 0x1110000011135, + 0x1113600011140, + 0x1114400011148, + 0x1115000011174, + 0x1117600011177, + 0x11180000111C5, + 0x111C9000111CD, + 0x111CE000111DB, + 0x111DC000111DD, + 0x1120000011212, + 0x1121300011238, + 0x1123E00011242, + 0x1128000011287, + 0x1128800011289, + 0x1128A0001128E, + 0x1128F0001129E, + 0x1129F000112A9, + 0x112B0000112EB, + 0x112F0000112FA, + 0x1130000011304, + 0x113050001130D, + 0x1130F00011311, + 0x1131300011329, + 0x1132A00011331, + 0x1133200011334, + 0x113350001133A, + 0x1133B00011345, + 0x1134700011349, + 0x1134B0001134E, + 0x1135000011351, + 0x1135700011358, + 0x1135D00011364, + 0x113660001136D, + 0x1137000011375, + 0x113800001138A, + 0x1138B0001138C, + 0x1138E0001138F, + 0x11390000113B6, + 0x113B7000113C1, + 0x113C2000113C3, + 0x113C5000113C6, + 0x113C7000113CB, + 0x113CC000113D4, + 0x113E1000113E3, + 0x114000001144B, + 0x114500001145A, + 0x1145E00011462, + 0x11480000114C6, + 0x114C7000114C8, + 0x114D0000114DA, + 0x11580000115B6, + 0x115B8000115C1, + 0x115D8000115DE, + 0x1160000011641, + 0x1164400011645, + 0x116500001165A, + 0x11680000116B9, + 0x116C0000116CA, + 0x116D0000116E4, + 0x117000001171B, + 0x1171D0001172C, + 0x117300001173A, + 0x1174000011747, + 0x118000001183B, + 0x118C0000118EA, + 0x118FF00011907, + 0x119090001190A, + 0x1190C00011914, + 0x1191500011917, + 0x1191800011936, + 0x1193700011939, + 0x1193B00011944, + 0x119500001195A, + 0x119A0000119A8, + 0x119AA000119D8, + 0x119DA000119E2, + 0x119E3000119E5, + 0x11A0000011A3F, + 0x11A4700011A48, + 0x11A5000011A9A, + 0x11A9D00011A9E, + 0x11AB000011AF9, + 0x11B6000011B68, + 0x11BC000011BE1, + 0x11BF000011BFA, + 0x11C0000011C09, + 0x11C0A00011C37, + 0x11C3800011C41, + 0x11C5000011C5A, + 0x11C7200011C90, + 0x11C9200011CA8, + 0x11CA900011CB7, + 0x11D0000011D07, + 0x11D0800011D0A, + 0x11D0B00011D37, + 0x11D3A00011D3B, + 0x11D3C00011D3E, + 0x11D3F00011D48, + 0x11D5000011D5A, + 0x11D6000011D66, + 0x11D6700011D69, + 0x11D6A00011D8F, + 0x11D9000011D92, + 0x11D9300011D99, + 0x11DA000011DAA, + 0x11DB000011DDC, + 0x11DE000011DEA, + 0x11EE000011EF7, + 0x11F0000011F11, + 0x11F1200011F3B, + 0x11F3E00011F43, + 0x11F5000011F5B, + 0x11FB000011FB1, + 0x120000001239A, + 0x1248000012544, + 0x12F9000012FF1, + 0x1300000013430, + 0x1344000013456, + 0x13460000143FB, + 0x1440000014647, + 0x161000001613A, + 0x1680000016A39, + 0x16A4000016A5F, + 0x16A6000016A6A, + 0x16A7000016ABF, + 0x16AC000016ACA, + 0x16AD000016AEE, + 0x16AF000016AF5, + 0x16B0000016B37, + 0x16B4000016B44, + 0x16B5000016B5A, + 0x16B6300016B78, + 0x16B7D00016B90, + 0x16D4000016D6D, + 0x16D7000016D7A, + 0x16E6000016E80, + 0x16EBB00016ED4, + 0x16F0000016F4B, + 0x16F4F00016F88, + 0x16F8F00016FA0, + 0x16FE000016FE2, + 0x16FE300016FE5, + 0x16FF000016FF4, + 0x1700000018CD6, + 0x18CFF00018D1F, + 0x18D8000018DF3, + 0x1AFF00001AFF4, + 0x1AFF50001AFFC, + 0x1AFFD0001AFFF, + 0x1B0000001B123, + 0x1B1320001B133, + 0x1B1500001B153, + 0x1B1550001B156, + 0x1B1640001B168, + 0x1B1700001B2FC, + 0x1BC000001BC6B, + 0x1BC700001BC7D, + 0x1BC800001BC89, + 0x1BC900001BC9A, + 0x1BC9D0001BC9F, + 0x1CF000001CF2E, + 0x1CF300001CF47, + 0x1DA000001DA37, + 0x1DA3B0001DA6D, + 0x1DA750001DA76, + 0x1DA840001DA85, + 0x1DA9B0001DAA0, + 0x1DAA10001DAB0, + 0x1DF000001DF1F, + 0x1DF250001DF2B, + 0x1E0000001E007, + 0x1E0080001E019, + 0x1E01B0001E022, + 0x1E0230001E025, + 0x1E0260001E02B, + 0x1E08F0001E090, + 0x1E1000001E12D, + 0x1E1300001E13E, + 0x1E1400001E14A, + 0x1E14E0001E14F, + 0x1E2900001E2AF, + 0x1E2C00001E2FA, + 0x1E4D00001E4FA, + 0x1E5D00001E5FB, + 0x1E6C00001E6DF, + 0x1E6E00001E6F6, + 0x1E6FE0001E700, + 0x1E7E00001E7E7, + 0x1E7E80001E7EC, + 0x1E7ED0001E7EF, + 0x1E7F00001E7FF, + 0x1E8000001E8C5, + 0x1E8D00001E8D7, + 0x1E9220001E94C, + 0x1E9500001E95A, + 0x200000002A6E0, + 0x2A7000002B81E, + 0x2B8200002CEAE, + 0x2CEB00002EBE1, + 0x2EBF00002EE5E, + 0x300000003134B, + 0x313500003347A, + ), + "CONTEXTJ": (0x200C0000200E,), + "CONTEXTO": ( + 0xB7000000B8, + 0x37500000376, + 0x5F3000005F5, + 0x6600000066A, + 0x6F0000006FA, + 0x30FB000030FC, + ), +} diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/intranges.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/intranges.py new file mode 100644 index 0000000..7bfaa8d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/intranges.py @@ -0,0 +1,57 @@ +""" +Given a list of integers, made up of (hopefully) a small number of long runs +of consecutive integers, compute a representation of the form +((start1, end1), (start2, end2) ...). Then answer the question "was x present +in the original list?" in time O(log(# runs)). +""" + +import bisect +from typing import List, Tuple + + +def intranges_from_list(list_: List[int]) -> Tuple[int, ...]: + """Represent a list of integers as a sequence of ranges: + ((start_0, end_0), (start_1, end_1), ...), such that the original + integers are exactly those x such that start_i <= x < end_i for some i. + + Ranges are encoded as single integers (start << 32 | end), not as tuples. + """ + + sorted_list = sorted(list_) + ranges = [] + last_write = -1 + for i in range(len(sorted_list)): + if i + 1 < len(sorted_list): + if sorted_list[i] == sorted_list[i + 1] - 1: + continue + current_range = sorted_list[last_write + 1 : i + 1] + ranges.append(_encode_range(current_range[0], current_range[-1] + 1)) + last_write = i + + return tuple(ranges) + + +def _encode_range(start: int, end: int) -> int: + return (start << 32) | end + + +def _decode_range(r: int) -> Tuple[int, int]: + return (r >> 32), (r & ((1 << 32) - 1)) + + +def intranges_contain(int_: int, ranges: Tuple[int, ...]) -> bool: + """Determine if `int_` falls into one of the ranges in `ranges`.""" + tuple_ = _encode_range(int_, 0) + pos = bisect.bisect_left(ranges, tuple_) + # we could be immediately ahead of a tuple (start, end) + # with start < int_ <= end + if pos > 0: + left, right = _decode_range(ranges[pos - 1]) + if left <= int_ < right: + return True + # or we could be immediately behind a tuple (int_, end) + if pos < len(ranges): + left, _ = _decode_range(ranges[pos]) + if left == int_: + return True + return False diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/package_data.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/package_data.py new file mode 100644 index 0000000..fc1788c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/package_data.py @@ -0,0 +1 @@ +__version__ = "3.13" diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/py.typed b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/uts46data.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/uts46data.py new file mode 100644 index 0000000..cc2453e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/idna/uts46data.py @@ -0,0 +1,8384 @@ +# This file is automatically generated by tools/idna-data +# vim: set fileencoding=utf-8 : + +from typing import Tuple, Union + +"""IDNA Mapping Table from UTS46.""" + + +__version__ = "17.0.0" + +uts46data: Tuple[Union[Tuple[int, str], Tuple[int, str, str]], ...] = ( + (0x0, "V"), + (0x1, "V"), + (0x2, "V"), + (0x3, "V"), + (0x4, "V"), + (0x5, "V"), + (0x6, "V"), + (0x7, "V"), + (0x8, "V"), + (0x9, "V"), + (0xA, "V"), + (0xB, "V"), + (0xC, "V"), + (0xD, "V"), + (0xE, "V"), + (0xF, "V"), + (0x10, "V"), + (0x11, "V"), + (0x12, "V"), + (0x13, "V"), + (0x14, "V"), + (0x15, "V"), + (0x16, "V"), + (0x17, "V"), + (0x18, "V"), + (0x19, "V"), + (0x1A, "V"), + (0x1B, "V"), + (0x1C, "V"), + (0x1D, "V"), + (0x1E, "V"), + (0x1F, "V"), + (0x20, "V"), + (0x21, "V"), + (0x22, "V"), + (0x23, "V"), + (0x24, "V"), + (0x25, "V"), + (0x26, "V"), + (0x27, "V"), + (0x28, "V"), + (0x29, "V"), + (0x2A, "V"), + (0x2B, "V"), + (0x2C, "V"), + (0x2D, "V"), + (0x2E, "V"), + (0x2F, "V"), + (0x30, "V"), + (0x31, "V"), + (0x32, "V"), + (0x33, "V"), + (0x34, "V"), + (0x35, "V"), + (0x36, "V"), + (0x37, "V"), + (0x38, "V"), + (0x39, "V"), + (0x3A, "V"), + (0x3B, "V"), + (0x3C, "V"), + (0x3D, "V"), + (0x3E, "V"), + (0x3F, "V"), + (0x40, "V"), + (0x41, "M", "a"), + (0x42, "M", "b"), + (0x43, "M", "c"), + (0x44, "M", "d"), + (0x45, "M", "e"), + (0x46, "M", "f"), + (0x47, "M", "g"), + (0x48, "M", "h"), + (0x49, "M", "i"), + (0x4A, "M", "j"), + (0x4B, "M", "k"), + (0x4C, "M", "l"), + (0x4D, "M", "m"), + (0x4E, "M", "n"), + (0x4F, "M", "o"), + (0x50, "M", "p"), + (0x51, "M", "q"), + (0x52, "M", "r"), + (0x53, "M", "s"), + (0x54, "M", "t"), + (0x55, "M", "u"), + (0x56, "M", "v"), + (0x57, "M", "w"), + (0x58, "M", "x"), + (0x59, "M", "y"), + (0x5A, "M", "z"), + (0x5B, "V"), + (0x5C, "V"), + (0x5D, "V"), + (0x5E, "V"), + (0x5F, "V"), + (0x60, "V"), + (0x61, "V"), + (0x62, "V"), + (0x63, "V"), + (0x64, "V"), + (0x65, "V"), + (0x66, "V"), + (0x67, "V"), + (0x68, "V"), + (0x69, "V"), + (0x6A, "V"), + (0x6B, "V"), + (0x6C, "V"), + (0x6D, "V"), + (0x6E, "V"), + (0x6F, "V"), + (0x70, "V"), + (0x71, "V"), + (0x72, "V"), + (0x73, "V"), + (0x74, "V"), + (0x75, "V"), + (0x76, "V"), + (0x77, "V"), + (0x78, "V"), + (0x79, "V"), + (0x7A, "V"), + (0x7B, "V"), + (0x7C, "V"), + (0x7D, "V"), + (0x7E, "V"), + (0x7F, "V"), + (0x80, "X"), + (0x81, "X"), + (0x82, "X"), + (0x83, "X"), + (0x84, "X"), + (0x85, "X"), + (0x86, "X"), + (0x87, "X"), + (0x88, "X"), + (0x89, "X"), + (0x8A, "X"), + (0x8B, "X"), + (0x8C, "X"), + (0x8D, "X"), + (0x8E, "X"), + (0x8F, "X"), + (0x90, "X"), + (0x91, "X"), + (0x92, "X"), + (0x93, "X"), + (0x94, "X"), + (0x95, "X"), + (0x96, "X"), + (0x97, "X"), + (0x98, "X"), + (0x99, "X"), + (0x9A, "X"), + (0x9B, "X"), + (0x9C, "X"), + (0x9D, "X"), + (0x9E, "X"), + (0x9F, "X"), + (0xA0, "M", " "), + (0xA1, "V"), + (0xA2, "V"), + (0xA3, "V"), + (0xA4, "V"), + (0xA5, "V"), + (0xA6, "V"), + (0xA7, "V"), + (0xA8, "M", " ̈"), + (0xA9, "V"), + (0xAA, "M", "a"), + (0xAB, "V"), + (0xAC, "V"), + (0xAD, "I"), + (0xAE, "V"), + (0xAF, "M", " ̄"), + (0xB0, "V"), + (0xB1, "V"), + (0xB2, "M", "2"), + (0xB3, "M", "3"), + (0xB4, "M", " ́"), + (0xB5, "M", "μ"), + (0xB6, "V"), + (0xB7, "V"), + (0xB8, "M", " ̧"), + (0xB9, "M", "1"), + (0xBA, "M", "o"), + (0xBB, "V"), + (0xBC, "M", "1⁄4"), + (0xBD, "M", "1⁄2"), + (0xBE, "M", "3⁄4"), + (0xBF, "V"), + (0xC0, "M", "à"), + (0xC1, "M", "á"), + (0xC2, "M", "â"), + (0xC3, "M", "ã"), + (0xC4, "M", "ä"), + (0xC5, "M", "å"), + (0xC6, "M", "æ"), + (0xC7, "M", "ç"), + (0xC8, "M", "è"), + (0xC9, "M", "é"), + (0xCA, "M", "ê"), + (0xCB, "M", "ë"), + (0xCC, "M", "ì"), + (0xCD, "M", "í"), + (0xCE, "M", "î"), + (0xCF, "M", "ï"), + (0xD0, "M", "ð"), + (0xD1, "M", "ñ"), + (0xD2, "M", "ò"), + (0xD3, "M", "ó"), + (0xD4, "M", "ô"), + (0xD5, "M", "õ"), + (0xD6, "M", "ö"), + (0xD7, "V"), + (0xD8, "M", "ø"), + (0xD9, "M", "ù"), + (0xDA, "M", "ú"), + (0xDB, "M", "û"), + (0xDC, "M", "ü"), + (0xDD, "M", "ý"), + (0xDE, "M", "þ"), + (0xDF, "D", "ss"), + (0xE0, "V"), + (0xE1, "V"), + (0xE2, "V"), + (0xE3, "V"), + (0xE4, "V"), + (0xE5, "V"), + (0xE6, "V"), + (0xE7, "V"), + (0xE8, "V"), + (0xE9, "V"), + (0xEA, "V"), + (0xEB, "V"), + (0xEC, "V"), + (0xED, "V"), + (0xEE, "V"), + (0xEF, "V"), + (0xF0, "V"), + (0xF1, "V"), + (0xF2, "V"), + (0xF3, "V"), + (0xF4, "V"), + (0xF5, "V"), + (0xF6, "V"), + (0xF7, "V"), + (0xF8, "V"), + (0xF9, "V"), + (0xFA, "V"), + (0xFB, "V"), + (0xFC, "V"), + (0xFD, "V"), + (0xFE, "V"), + (0xFF, "V"), + (0x100, "M", "ā"), + (0x101, "V"), + (0x102, "M", "ă"), + (0x103, "V"), + (0x104, "M", "ą"), + (0x105, "V"), + (0x106, "M", "ć"), + (0x107, "V"), + (0x108, "M", "ĉ"), + (0x109, "V"), + (0x10A, "M", "ċ"), + (0x10B, "V"), + (0x10C, "M", "č"), + (0x10D, "V"), + (0x10E, "M", "ď"), + (0x10F, "V"), + (0x110, "M", "đ"), + (0x111, "V"), + (0x112, "M", "ē"), + (0x113, "V"), + (0x114, "M", "ĕ"), + (0x115, "V"), + (0x116, "M", "ė"), + (0x117, "V"), + (0x118, "M", "ę"), + (0x119, "V"), + (0x11A, "M", "ě"), + (0x11B, "V"), + (0x11C, "M", "ĝ"), + (0x11D, "V"), + (0x11E, "M", "ğ"), + (0x11F, "V"), + (0x120, "M", "ġ"), + (0x121, "V"), + (0x122, "M", "ģ"), + (0x123, "V"), + (0x124, "M", "ĥ"), + (0x125, "V"), + (0x126, "M", "ħ"), + (0x127, "V"), + (0x128, "M", "ĩ"), + (0x129, "V"), + (0x12A, "M", "ī"), + (0x12B, "V"), + (0x12C, "M", "ĭ"), + (0x12D, "V"), + (0x12E, "M", "į"), + (0x12F, "V"), + (0x130, "M", "i̇"), + (0x131, "V"), + (0x132, "M", "ij"), + (0x134, "M", "ĵ"), + (0x135, "V"), + (0x136, "M", "ķ"), + (0x137, "V"), + (0x139, "M", "ĺ"), + (0x13A, "V"), + (0x13B, "M", "ļ"), + (0x13C, "V"), + (0x13D, "M", "ľ"), + (0x13E, "V"), + (0x13F, "M", "l·"), + (0x141, "M", "ł"), + (0x142, "V"), + (0x143, "M", "ń"), + (0x144, "V"), + (0x145, "M", "ņ"), + (0x146, "V"), + (0x147, "M", "ň"), + (0x148, "V"), + (0x149, "M", "ʼn"), + (0x14A, "M", "ŋ"), + (0x14B, "V"), + (0x14C, "M", "ō"), + (0x14D, "V"), + (0x14E, "M", "ŏ"), + (0x14F, "V"), + (0x150, "M", "ő"), + (0x151, "V"), + (0x152, "M", "œ"), + (0x153, "V"), + (0x154, "M", "ŕ"), + (0x155, "V"), + (0x156, "M", "ŗ"), + (0x157, "V"), + (0x158, "M", "ř"), + (0x159, "V"), + (0x15A, "M", "ś"), + (0x15B, "V"), + (0x15C, "M", "ŝ"), + (0x15D, "V"), + (0x15E, "M", "ş"), + (0x15F, "V"), + (0x160, "M", "š"), + (0x161, "V"), + (0x162, "M", "ţ"), + (0x163, "V"), + (0x164, "M", "ť"), + (0x165, "V"), + (0x166, "M", "ŧ"), + (0x167, "V"), + (0x168, "M", "ũ"), + (0x169, "V"), + (0x16A, "M", "ū"), + (0x16B, "V"), + (0x16C, "M", "ŭ"), + (0x16D, "V"), + (0x16E, "M", "ů"), + (0x16F, "V"), + (0x170, "M", "ű"), + (0x171, "V"), + (0x172, "M", "ų"), + (0x173, "V"), + (0x174, "M", "ŵ"), + (0x175, "V"), + (0x176, "M", "ŷ"), + (0x177, "V"), + (0x178, "M", "ÿ"), + (0x179, "M", "ź"), + (0x17A, "V"), + (0x17B, "M", "ż"), + (0x17C, "V"), + (0x17D, "M", "ž"), + (0x17E, "V"), + (0x17F, "M", "s"), + (0x180, "V"), + (0x181, "M", "ɓ"), + (0x182, "M", "ƃ"), + (0x183, "V"), + (0x184, "M", "ƅ"), + (0x185, "V"), + (0x186, "M", "ɔ"), + (0x187, "M", "ƈ"), + (0x188, "V"), + (0x189, "M", "ɖ"), + (0x18A, "M", "ɗ"), + (0x18B, "M", "ƌ"), + (0x18C, "V"), + (0x18E, "M", "ǝ"), + (0x18F, "M", "ə"), + (0x190, "M", "ɛ"), + (0x191, "M", "ƒ"), + (0x192, "V"), + (0x193, "M", "ɠ"), + (0x194, "M", "ɣ"), + (0x195, "V"), + (0x196, "M", "ɩ"), + (0x197, "M", "ɨ"), + (0x198, "M", "ƙ"), + (0x199, "V"), + (0x19C, "M", "ɯ"), + (0x19D, "M", "ɲ"), + (0x19E, "V"), + (0x19F, "M", "ɵ"), + (0x1A0, "M", "ơ"), + (0x1A1, "V"), + (0x1A2, "M", "ƣ"), + (0x1A3, "V"), + (0x1A4, "M", "ƥ"), + (0x1A5, "V"), + (0x1A6, "M", "ʀ"), + (0x1A7, "M", "ƨ"), + (0x1A8, "V"), + (0x1A9, "M", "ʃ"), + (0x1AA, "V"), + (0x1AC, "M", "ƭ"), + (0x1AD, "V"), + (0x1AE, "M", "ʈ"), + (0x1AF, "M", "ư"), + (0x1B0, "V"), + (0x1B1, "M", "ʊ"), + (0x1B2, "M", "ʋ"), + (0x1B3, "M", "ƴ"), + (0x1B4, "V"), + (0x1B5, "M", "ƶ"), + (0x1B6, "V"), + (0x1B7, "M", "ʒ"), + (0x1B8, "M", "ƹ"), + (0x1B9, "V"), + (0x1BC, "M", "ƽ"), + (0x1BD, "V"), + (0x1C4, "M", "dž"), + (0x1C7, "M", "lj"), + (0x1CA, "M", "nj"), + (0x1CD, "M", "ǎ"), + (0x1CE, "V"), + (0x1CF, "M", "ǐ"), + (0x1D0, "V"), + (0x1D1, "M", "ǒ"), + (0x1D2, "V"), + (0x1D3, "M", "ǔ"), + (0x1D4, "V"), + (0x1D5, "M", "ǖ"), + (0x1D6, "V"), + (0x1D7, "M", "ǘ"), + (0x1D8, "V"), + (0x1D9, "M", "ǚ"), + (0x1DA, "V"), + (0x1DB, "M", "ǜ"), + (0x1DC, "V"), + (0x1DE, "M", "ǟ"), + (0x1DF, "V"), + (0x1E0, "M", "ǡ"), + (0x1E1, "V"), + (0x1E2, "M", "ǣ"), + (0x1E3, "V"), + (0x1E4, "M", "ǥ"), + (0x1E5, "V"), + (0x1E6, "M", "ǧ"), + (0x1E7, "V"), + (0x1E8, "M", "ǩ"), + (0x1E9, "V"), + (0x1EA, "M", "ǫ"), + (0x1EB, "V"), + (0x1EC, "M", "ǭ"), + (0x1ED, "V"), + (0x1EE, "M", "ǯ"), + (0x1EF, "V"), + (0x1F1, "M", "dz"), + (0x1F4, "M", "ǵ"), + (0x1F5, "V"), + (0x1F6, "M", "ƕ"), + (0x1F7, "M", "ƿ"), + (0x1F8, "M", "ǹ"), + (0x1F9, "V"), + (0x1FA, "M", "ǻ"), + (0x1FB, "V"), + (0x1FC, "M", "ǽ"), + (0x1FD, "V"), + (0x1FE, "M", "ǿ"), + (0x1FF, "V"), + (0x200, "M", "ȁ"), + (0x201, "V"), + (0x202, "M", "ȃ"), + (0x203, "V"), + (0x204, "M", "ȅ"), + (0x205, "V"), + (0x206, "M", "ȇ"), + (0x207, "V"), + (0x208, "M", "ȉ"), + (0x209, "V"), + (0x20A, "M", "ȋ"), + (0x20B, "V"), + (0x20C, "M", "ȍ"), + (0x20D, "V"), + (0x20E, "M", "ȏ"), + (0x20F, "V"), + (0x210, "M", "ȑ"), + (0x211, "V"), + (0x212, "M", "ȓ"), + (0x213, "V"), + (0x214, "M", "ȕ"), + (0x215, "V"), + (0x216, "M", "ȗ"), + (0x217, "V"), + (0x218, "M", "ș"), + (0x219, "V"), + (0x21A, "M", "ț"), + (0x21B, "V"), + (0x21C, "M", "ȝ"), + (0x21D, "V"), + (0x21E, "M", "ȟ"), + (0x21F, "V"), + (0x220, "M", "ƞ"), + (0x221, "V"), + (0x222, "M", "ȣ"), + (0x223, "V"), + (0x224, "M", "ȥ"), + (0x225, "V"), + (0x226, "M", "ȧ"), + (0x227, "V"), + (0x228, "M", "ȩ"), + (0x229, "V"), + (0x22A, "M", "ȫ"), + (0x22B, "V"), + (0x22C, "M", "ȭ"), + (0x22D, "V"), + (0x22E, "M", "ȯ"), + (0x22F, "V"), + (0x230, "M", "ȱ"), + (0x231, "V"), + (0x232, "M", "ȳ"), + (0x233, "V"), + (0x23A, "M", "ⱥ"), + (0x23B, "M", "ȼ"), + (0x23C, "V"), + (0x23D, "M", "ƚ"), + (0x23E, "M", "ⱦ"), + (0x23F, "V"), + (0x241, "M", "ɂ"), + (0x242, "V"), + (0x243, "M", "ƀ"), + (0x244, "M", "ʉ"), + (0x245, "M", "ʌ"), + (0x246, "M", "ɇ"), + (0x247, "V"), + (0x248, "M", "ɉ"), + (0x249, "V"), + (0x24A, "M", "ɋ"), + (0x24B, "V"), + (0x24C, "M", "ɍ"), + (0x24D, "V"), + (0x24E, "M", "ɏ"), + (0x24F, "V"), + (0x2B0, "M", "h"), + (0x2B1, "M", "ɦ"), + (0x2B2, "M", "j"), + (0x2B3, "M", "r"), + (0x2B4, "M", "ɹ"), + (0x2B5, "M", "ɻ"), + (0x2B6, "M", "ʁ"), + (0x2B7, "M", "w"), + (0x2B8, "M", "y"), + (0x2B9, "V"), + (0x2D8, "M", " ̆"), + (0x2D9, "M", " ̇"), + (0x2DA, "M", " ̊"), + (0x2DB, "M", " ̨"), + (0x2DC, "M", " ̃"), + (0x2DD, "M", " ̋"), + (0x2DE, "V"), + (0x2E0, "M", "ɣ"), + (0x2E1, "M", "l"), + (0x2E2, "M", "s"), + (0x2E3, "M", "x"), + (0x2E4, "M", "ʕ"), + (0x2E5, "V"), + (0x340, "M", "̀"), + (0x341, "M", "́"), + (0x342, "V"), + (0x343, "M", "̓"), + (0x344, "M", "̈́"), + (0x345, "M", "ι"), + (0x346, "V"), + (0x34F, "I"), + (0x350, "V"), + (0x370, "M", "ͱ"), + (0x371, "V"), + (0x372, "M", "ͳ"), + (0x373, "V"), + (0x374, "M", "ʹ"), + (0x375, "V"), + (0x376, "M", "ͷ"), + (0x377, "V"), + (0x378, "X"), + (0x37A, "M", " ι"), + (0x37B, "V"), + (0x37E, "M", ";"), + (0x37F, "M", "ϳ"), + (0x380, "X"), + (0x384, "M", " ́"), + (0x385, "M", " ̈́"), + (0x386, "M", "ά"), + (0x387, "M", "·"), + (0x388, "M", "έ"), + (0x389, "M", "ή"), + (0x38A, "M", "ί"), + (0x38B, "X"), + (0x38C, "M", "ό"), + (0x38D, "X"), + (0x38E, "M", "ύ"), + (0x38F, "M", "ώ"), + (0x390, "V"), + (0x391, "M", "α"), + (0x392, "M", "β"), + (0x393, "M", "γ"), + (0x394, "M", "δ"), + (0x395, "M", "ε"), + (0x396, "M", "ζ"), + (0x397, "M", "η"), + (0x398, "M", "θ"), + (0x399, "M", "ι"), + (0x39A, "M", "κ"), + (0x39B, "M", "λ"), + (0x39C, "M", "μ"), + (0x39D, "M", "ν"), + (0x39E, "M", "ξ"), + (0x39F, "M", "ο"), + (0x3A0, "M", "π"), + (0x3A1, "M", "ρ"), + (0x3A2, "X"), + (0x3A3, "M", "σ"), + (0x3A4, "M", "τ"), + (0x3A5, "M", "υ"), + (0x3A6, "M", "φ"), + (0x3A7, "M", "χ"), + (0x3A8, "M", "ψ"), + (0x3A9, "M", "ω"), + (0x3AA, "M", "ϊ"), + (0x3AB, "M", "ϋ"), + (0x3AC, "V"), + (0x3C2, "D", "σ"), + (0x3C3, "V"), + (0x3CF, "M", "ϗ"), + (0x3D0, "M", "β"), + (0x3D1, "M", "θ"), + (0x3D2, "M", "υ"), + (0x3D3, "M", "ύ"), + (0x3D4, "M", "ϋ"), + (0x3D5, "M", "φ"), + (0x3D6, "M", "π"), + (0x3D7, "V"), + (0x3D8, "M", "ϙ"), + (0x3D9, "V"), + (0x3DA, "M", "ϛ"), + (0x3DB, "V"), + (0x3DC, "M", "ϝ"), + (0x3DD, "V"), + (0x3DE, "M", "ϟ"), + (0x3DF, "V"), + (0x3E0, "M", "ϡ"), + (0x3E1, "V"), + (0x3E2, "M", "ϣ"), + (0x3E3, "V"), + (0x3E4, "M", "ϥ"), + (0x3E5, "V"), + (0x3E6, "M", "ϧ"), + (0x3E7, "V"), + (0x3E8, "M", "ϩ"), + (0x3E9, "V"), + (0x3EA, "M", "ϫ"), + (0x3EB, "V"), + (0x3EC, "M", "ϭ"), + (0x3ED, "V"), + (0x3EE, "M", "ϯ"), + (0x3EF, "V"), + (0x3F0, "M", "κ"), + (0x3F1, "M", "ρ"), + (0x3F2, "M", "σ"), + (0x3F3, "V"), + (0x3F4, "M", "θ"), + (0x3F5, "M", "ε"), + (0x3F6, "V"), + (0x3F7, "M", "ϸ"), + (0x3F8, "V"), + (0x3F9, "M", "σ"), + (0x3FA, "M", "ϻ"), + (0x3FB, "V"), + (0x3FD, "M", "ͻ"), + (0x3FE, "M", "ͼ"), + (0x3FF, "M", "ͽ"), + (0x400, "M", "ѐ"), + (0x401, "M", "ё"), + (0x402, "M", "ђ"), + (0x403, "M", "ѓ"), + (0x404, "M", "є"), + (0x405, "M", "ѕ"), + (0x406, "M", "і"), + (0x407, "M", "ї"), + (0x408, "M", "ј"), + (0x409, "M", "љ"), + (0x40A, "M", "њ"), + (0x40B, "M", "ћ"), + (0x40C, "M", "ќ"), + (0x40D, "M", "ѝ"), + (0x40E, "M", "ў"), + (0x40F, "M", "џ"), + (0x410, "M", "а"), + (0x411, "M", "б"), + (0x412, "M", "в"), + (0x413, "M", "г"), + (0x414, "M", "д"), + (0x415, "M", "е"), + (0x416, "M", "ж"), + (0x417, "M", "з"), + (0x418, "M", "и"), + (0x419, "M", "й"), + (0x41A, "M", "к"), + (0x41B, "M", "л"), + (0x41C, "M", "м"), + (0x41D, "M", "н"), + (0x41E, "M", "о"), + (0x41F, "M", "п"), + (0x420, "M", "р"), + (0x421, "M", "с"), + (0x422, "M", "т"), + (0x423, "M", "у"), + (0x424, "M", "ф"), + (0x425, "M", "х"), + (0x426, "M", "ц"), + (0x427, "M", "ч"), + (0x428, "M", "ш"), + (0x429, "M", "щ"), + (0x42A, "M", "ъ"), + (0x42B, "M", "ы"), + (0x42C, "M", "ь"), + (0x42D, "M", "э"), + (0x42E, "M", "ю"), + (0x42F, "M", "я"), + (0x430, "V"), + (0x460, "M", "ѡ"), + (0x461, "V"), + (0x462, "M", "ѣ"), + (0x463, "V"), + (0x464, "M", "ѥ"), + (0x465, "V"), + (0x466, "M", "ѧ"), + (0x467, "V"), + (0x468, "M", "ѩ"), + (0x469, "V"), + (0x46A, "M", "ѫ"), + (0x46B, "V"), + (0x46C, "M", "ѭ"), + (0x46D, "V"), + (0x46E, "M", "ѯ"), + (0x46F, "V"), + (0x470, "M", "ѱ"), + (0x471, "V"), + (0x472, "M", "ѳ"), + (0x473, "V"), + (0x474, "M", "ѵ"), + (0x475, "V"), + (0x476, "M", "ѷ"), + (0x477, "V"), + (0x478, "M", "ѹ"), + (0x479, "V"), + (0x47A, "M", "ѻ"), + (0x47B, "V"), + (0x47C, "M", "ѽ"), + (0x47D, "V"), + (0x47E, "M", "ѿ"), + (0x47F, "V"), + (0x480, "M", "ҁ"), + (0x481, "V"), + (0x48A, "M", "ҋ"), + (0x48B, "V"), + (0x48C, "M", "ҍ"), + (0x48D, "V"), + (0x48E, "M", "ҏ"), + (0x48F, "V"), + (0x490, "M", "ґ"), + (0x491, "V"), + (0x492, "M", "ғ"), + (0x493, "V"), + (0x494, "M", "ҕ"), + (0x495, "V"), + (0x496, "M", "җ"), + (0x497, "V"), + (0x498, "M", "ҙ"), + (0x499, "V"), + (0x49A, "M", "қ"), + (0x49B, "V"), + (0x49C, "M", "ҝ"), + (0x49D, "V"), + (0x49E, "M", "ҟ"), + (0x49F, "V"), + (0x4A0, "M", "ҡ"), + (0x4A1, "V"), + (0x4A2, "M", "ң"), + (0x4A3, "V"), + (0x4A4, "M", "ҥ"), + (0x4A5, "V"), + (0x4A6, "M", "ҧ"), + (0x4A7, "V"), + (0x4A8, "M", "ҩ"), + (0x4A9, "V"), + (0x4AA, "M", "ҫ"), + (0x4AB, "V"), + (0x4AC, "M", "ҭ"), + (0x4AD, "V"), + (0x4AE, "M", "ү"), + (0x4AF, "V"), + (0x4B0, "M", "ұ"), + (0x4B1, "V"), + (0x4B2, "M", "ҳ"), + (0x4B3, "V"), + (0x4B4, "M", "ҵ"), + (0x4B5, "V"), + (0x4B6, "M", "ҷ"), + (0x4B7, "V"), + (0x4B8, "M", "ҹ"), + (0x4B9, "V"), + (0x4BA, "M", "һ"), + (0x4BB, "V"), + (0x4BC, "M", "ҽ"), + (0x4BD, "V"), + (0x4BE, "M", "ҿ"), + (0x4BF, "V"), + (0x4C0, "M", "ӏ"), + (0x4C1, "M", "ӂ"), + (0x4C2, "V"), + (0x4C3, "M", "ӄ"), + (0x4C4, "V"), + (0x4C5, "M", "ӆ"), + (0x4C6, "V"), + (0x4C7, "M", "ӈ"), + (0x4C8, "V"), + (0x4C9, "M", "ӊ"), + (0x4CA, "V"), + (0x4CB, "M", "ӌ"), + (0x4CC, "V"), + (0x4CD, "M", "ӎ"), + (0x4CE, "V"), + (0x4D0, "M", "ӑ"), + (0x4D1, "V"), + (0x4D2, "M", "ӓ"), + (0x4D3, "V"), + (0x4D4, "M", "ӕ"), + (0x4D5, "V"), + (0x4D6, "M", "ӗ"), + (0x4D7, "V"), + (0x4D8, "M", "ә"), + (0x4D9, "V"), + (0x4DA, "M", "ӛ"), + (0x4DB, "V"), + (0x4DC, "M", "ӝ"), + (0x4DD, "V"), + (0x4DE, "M", "ӟ"), + (0x4DF, "V"), + (0x4E0, "M", "ӡ"), + (0x4E1, "V"), + (0x4E2, "M", "ӣ"), + (0x4E3, "V"), + (0x4E4, "M", "ӥ"), + (0x4E5, "V"), + (0x4E6, "M", "ӧ"), + (0x4E7, "V"), + (0x4E8, "M", "ө"), + (0x4E9, "V"), + (0x4EA, "M", "ӫ"), + (0x4EB, "V"), + (0x4EC, "M", "ӭ"), + (0x4ED, "V"), + (0x4EE, "M", "ӯ"), + (0x4EF, "V"), + (0x4F0, "M", "ӱ"), + (0x4F1, "V"), + (0x4F2, "M", "ӳ"), + (0x4F3, "V"), + (0x4F4, "M", "ӵ"), + (0x4F5, "V"), + (0x4F6, "M", "ӷ"), + (0x4F7, "V"), + (0x4F8, "M", "ӹ"), + (0x4F9, "V"), + (0x4FA, "M", "ӻ"), + (0x4FB, "V"), + (0x4FC, "M", "ӽ"), + (0x4FD, "V"), + (0x4FE, "M", "ӿ"), + (0x4FF, "V"), + (0x500, "M", "ԁ"), + (0x501, "V"), + (0x502, "M", "ԃ"), + (0x503, "V"), + (0x504, "M", "ԅ"), + (0x505, "V"), + (0x506, "M", "ԇ"), + (0x507, "V"), + (0x508, "M", "ԉ"), + (0x509, "V"), + (0x50A, "M", "ԋ"), + (0x50B, "V"), + (0x50C, "M", "ԍ"), + (0x50D, "V"), + (0x50E, "M", "ԏ"), + (0x50F, "V"), + (0x510, "M", "ԑ"), + (0x511, "V"), + (0x512, "M", "ԓ"), + (0x513, "V"), + (0x514, "M", "ԕ"), + (0x515, "V"), + (0x516, "M", "ԗ"), + (0x517, "V"), + (0x518, "M", "ԙ"), + (0x519, "V"), + (0x51A, "M", "ԛ"), + (0x51B, "V"), + (0x51C, "M", "ԝ"), + (0x51D, "V"), + (0x51E, "M", "ԟ"), + (0x51F, "V"), + (0x520, "M", "ԡ"), + (0x521, "V"), + (0x522, "M", "ԣ"), + (0x523, "V"), + (0x524, "M", "ԥ"), + (0x525, "V"), + (0x526, "M", "ԧ"), + (0x527, "V"), + (0x528, "M", "ԩ"), + (0x529, "V"), + (0x52A, "M", "ԫ"), + (0x52B, "V"), + (0x52C, "M", "ԭ"), + (0x52D, "V"), + (0x52E, "M", "ԯ"), + (0x52F, "V"), + (0x530, "X"), + (0x531, "M", "ա"), + (0x532, "M", "բ"), + (0x533, "M", "գ"), + (0x534, "M", "դ"), + (0x535, "M", "ե"), + (0x536, "M", "զ"), + (0x537, "M", "է"), + (0x538, "M", "ը"), + (0x539, "M", "թ"), + (0x53A, "M", "ժ"), + (0x53B, "M", "ի"), + (0x53C, "M", "լ"), + (0x53D, "M", "խ"), + (0x53E, "M", "ծ"), + (0x53F, "M", "կ"), + (0x540, "M", "հ"), + (0x541, "M", "ձ"), + (0x542, "M", "ղ"), + (0x543, "M", "ճ"), + (0x544, "M", "մ"), + (0x545, "M", "յ"), + (0x546, "M", "ն"), + (0x547, "M", "շ"), + (0x548, "M", "ո"), + (0x549, "M", "չ"), + (0x54A, "M", "պ"), + (0x54B, "M", "ջ"), + (0x54C, "M", "ռ"), + (0x54D, "M", "ս"), + (0x54E, "M", "վ"), + (0x54F, "M", "տ"), + (0x550, "M", "ր"), + (0x551, "M", "ց"), + (0x552, "M", "ւ"), + (0x553, "M", "փ"), + (0x554, "M", "ք"), + (0x555, "M", "օ"), + (0x556, "M", "ֆ"), + (0x557, "X"), + (0x559, "V"), + (0x587, "M", "եւ"), + (0x588, "V"), + (0x58B, "X"), + (0x58D, "V"), + (0x590, "X"), + (0x591, "V"), + (0x5C8, "X"), + (0x5D0, "V"), + (0x5EB, "X"), + (0x5EF, "V"), + (0x5F5, "X"), + (0x606, "V"), + (0x61C, "X"), + (0x61D, "V"), + (0x675, "M", "اٴ"), + (0x676, "M", "وٴ"), + (0x677, "M", "ۇٴ"), + (0x678, "M", "يٴ"), + (0x679, "V"), + (0x6DD, "X"), + (0x6DE, "V"), + (0x70E, "X"), + (0x710, "V"), + (0x74B, "X"), + (0x74D, "V"), + (0x7B2, "X"), + (0x7C0, "V"), + (0x7FB, "X"), + (0x7FD, "V"), + (0x82E, "X"), + (0x830, "V"), + (0x83F, "X"), + (0x840, "V"), + (0x85C, "X"), + (0x85E, "V"), + (0x85F, "X"), + (0x860, "V"), + (0x86B, "X"), + (0x870, "V"), + (0x890, "X"), + (0x897, "V"), + (0x8E2, "X"), + (0x8E3, "V"), + (0x958, "M", "क़"), + (0x959, "M", "ख़"), + (0x95A, "M", "ग़"), + (0x95B, "M", "ज़"), + (0x95C, "M", "ड़"), + (0x95D, "M", "ढ़"), + (0x95E, "M", "फ़"), + (0x95F, "M", "य़"), + (0x960, "V"), + (0x984, "X"), + (0x985, "V"), + (0x98D, "X"), + (0x98F, "V"), + (0x991, "X"), + (0x993, "V"), + (0x9A9, "X"), + (0x9AA, "V"), + (0x9B1, "X"), + (0x9B2, "V"), + (0x9B3, "X"), + (0x9B6, "V"), + (0x9BA, "X"), + (0x9BC, "V"), + (0x9C5, "X"), + (0x9C7, "V"), + (0x9C9, "X"), + (0x9CB, "V"), + (0x9CF, "X"), + (0x9D7, "V"), + (0x9D8, "X"), + (0x9DC, "M", "ড়"), + (0x9DD, "M", "ঢ়"), + (0x9DE, "X"), + (0x9DF, "M", "য়"), + (0x9E0, "V"), + (0x9E4, "X"), + (0x9E6, "V"), + (0x9FF, "X"), + (0xA01, "V"), + (0xA04, "X"), + (0xA05, "V"), + (0xA0B, "X"), + (0xA0F, "V"), + (0xA11, "X"), + (0xA13, "V"), + (0xA29, "X"), + (0xA2A, "V"), + (0xA31, "X"), + (0xA32, "V"), + (0xA33, "M", "ਲ਼"), + (0xA34, "X"), + (0xA35, "V"), + (0xA36, "M", "ਸ਼"), + (0xA37, "X"), + (0xA38, "V"), + (0xA3A, "X"), + (0xA3C, "V"), + (0xA3D, "X"), + (0xA3E, "V"), + (0xA43, "X"), + (0xA47, "V"), + (0xA49, "X"), + (0xA4B, "V"), + (0xA4E, "X"), + (0xA51, "V"), + (0xA52, "X"), + (0xA59, "M", "ਖ਼"), + (0xA5A, "M", "ਗ਼"), + (0xA5B, "M", "ਜ਼"), + (0xA5C, "V"), + (0xA5D, "X"), + (0xA5E, "M", "ਫ਼"), + (0xA5F, "X"), + (0xA66, "V"), + (0xA77, "X"), + (0xA81, "V"), + (0xA84, "X"), + (0xA85, "V"), + (0xA8E, "X"), + (0xA8F, "V"), + (0xA92, "X"), + (0xA93, "V"), + (0xAA9, "X"), + (0xAAA, "V"), + (0xAB1, "X"), + (0xAB2, "V"), + (0xAB4, "X"), + (0xAB5, "V"), + (0xABA, "X"), + (0xABC, "V"), + (0xAC6, "X"), + (0xAC7, "V"), + (0xACA, "X"), + (0xACB, "V"), + (0xACE, "X"), + (0xAD0, "V"), + (0xAD1, "X"), + (0xAE0, "V"), + (0xAE4, "X"), + (0xAE6, "V"), + (0xAF2, "X"), + (0xAF9, "V"), + (0xB00, "X"), + (0xB01, "V"), + (0xB04, "X"), + (0xB05, "V"), + (0xB0D, "X"), + (0xB0F, "V"), + (0xB11, "X"), + (0xB13, "V"), + (0xB29, "X"), + (0xB2A, "V"), + (0xB31, "X"), + (0xB32, "V"), + (0xB34, "X"), + (0xB35, "V"), + (0xB3A, "X"), + (0xB3C, "V"), + (0xB45, "X"), + (0xB47, "V"), + (0xB49, "X"), + (0xB4B, "V"), + (0xB4E, "X"), + (0xB55, "V"), + (0xB58, "X"), + (0xB5C, "M", "ଡ଼"), + (0xB5D, "M", "ଢ଼"), + (0xB5E, "X"), + (0xB5F, "V"), + (0xB64, "X"), + (0xB66, "V"), + (0xB78, "X"), + (0xB82, "V"), + (0xB84, "X"), + (0xB85, "V"), + (0xB8B, "X"), + (0xB8E, "V"), + (0xB91, "X"), + (0xB92, "V"), + (0xB96, "X"), + (0xB99, "V"), + (0xB9B, "X"), + (0xB9C, "V"), + (0xB9D, "X"), + (0xB9E, "V"), + (0xBA0, "X"), + (0xBA3, "V"), + (0xBA5, "X"), + (0xBA8, "V"), + (0xBAB, "X"), + (0xBAE, "V"), + (0xBBA, "X"), + (0xBBE, "V"), + (0xBC3, "X"), + (0xBC6, "V"), + (0xBC9, "X"), + (0xBCA, "V"), + (0xBCE, "X"), + (0xBD0, "V"), + (0xBD1, "X"), + (0xBD7, "V"), + (0xBD8, "X"), + (0xBE6, "V"), + (0xBFB, "X"), + (0xC00, "V"), + (0xC0D, "X"), + (0xC0E, "V"), + (0xC11, "X"), + (0xC12, "V"), + (0xC29, "X"), + (0xC2A, "V"), + (0xC3A, "X"), + (0xC3C, "V"), + (0xC45, "X"), + (0xC46, "V"), + (0xC49, "X"), + (0xC4A, "V"), + (0xC4E, "X"), + (0xC55, "V"), + (0xC57, "X"), + (0xC58, "V"), + (0xC5B, "X"), + (0xC5C, "V"), + (0xC5E, "X"), + (0xC60, "V"), + (0xC64, "X"), + (0xC66, "V"), + (0xC70, "X"), + (0xC77, "V"), + (0xC8D, "X"), + (0xC8E, "V"), + (0xC91, "X"), + (0xC92, "V"), + (0xCA9, "X"), + (0xCAA, "V"), + (0xCB4, "X"), + (0xCB5, "V"), + (0xCBA, "X"), + (0xCBC, "V"), + (0xCC5, "X"), + (0xCC6, "V"), + (0xCC9, "X"), + (0xCCA, "V"), + (0xCCE, "X"), + (0xCD5, "V"), + (0xCD7, "X"), + (0xCDC, "V"), + (0xCDF, "X"), + (0xCE0, "V"), + (0xCE4, "X"), + (0xCE6, "V"), + (0xCF0, "X"), + (0xCF1, "V"), + (0xCF4, "X"), + (0xD00, "V"), + (0xD0D, "X"), + (0xD0E, "V"), + (0xD11, "X"), + (0xD12, "V"), + (0xD45, "X"), + (0xD46, "V"), + (0xD49, "X"), + (0xD4A, "V"), + (0xD50, "X"), + (0xD54, "V"), + (0xD64, "X"), + (0xD66, "V"), + (0xD80, "X"), + (0xD81, "V"), + (0xD84, "X"), + (0xD85, "V"), + (0xD97, "X"), + (0xD9A, "V"), + (0xDB2, "X"), + (0xDB3, "V"), + (0xDBC, "X"), + (0xDBD, "V"), + (0xDBE, "X"), + (0xDC0, "V"), + (0xDC7, "X"), + (0xDCA, "V"), + (0xDCB, "X"), + (0xDCF, "V"), + (0xDD5, "X"), + (0xDD6, "V"), + (0xDD7, "X"), + (0xDD8, "V"), + (0xDE0, "X"), + (0xDE6, "V"), + (0xDF0, "X"), + (0xDF2, "V"), + (0xDF5, "X"), + (0xE01, "V"), + (0xE33, "M", "ํา"), + (0xE34, "V"), + (0xE3B, "X"), + (0xE3F, "V"), + (0xE5C, "X"), + (0xE81, "V"), + (0xE83, "X"), + (0xE84, "V"), + (0xE85, "X"), + (0xE86, "V"), + (0xE8B, "X"), + (0xE8C, "V"), + (0xEA4, "X"), + (0xEA5, "V"), + (0xEA6, "X"), + (0xEA7, "V"), + (0xEB3, "M", "ໍາ"), + (0xEB4, "V"), + (0xEBE, "X"), + (0xEC0, "V"), + (0xEC5, "X"), + (0xEC6, "V"), + (0xEC7, "X"), + (0xEC8, "V"), + (0xECF, "X"), + (0xED0, "V"), + (0xEDA, "X"), + (0xEDC, "M", "ຫນ"), + (0xEDD, "M", "ຫມ"), + (0xEDE, "V"), + (0xEE0, "X"), + (0xF00, "V"), + (0xF0C, "M", "་"), + (0xF0D, "V"), + (0xF43, "M", "གྷ"), + (0xF44, "V"), + (0xF48, "X"), + (0xF49, "V"), + (0xF4D, "M", "ཌྷ"), + (0xF4E, "V"), + (0xF52, "M", "དྷ"), + (0xF53, "V"), + (0xF57, "M", "བྷ"), + (0xF58, "V"), + (0xF5C, "M", "ཛྷ"), + (0xF5D, "V"), + (0xF69, "M", "ཀྵ"), + (0xF6A, "V"), + (0xF6D, "X"), + (0xF71, "V"), + (0xF73, "M", "ཱི"), + (0xF74, "V"), + (0xF75, "M", "ཱུ"), + (0xF76, "M", "ྲྀ"), + (0xF77, "M", "ྲཱྀ"), + (0xF78, "M", "ླྀ"), + (0xF79, "M", "ླཱྀ"), + (0xF7A, "V"), + (0xF81, "M", "ཱྀ"), + (0xF82, "V"), + (0xF93, "M", "ྒྷ"), + (0xF94, "V"), + (0xF98, "X"), + (0xF99, "V"), + (0xF9D, "M", "ྜྷ"), + (0xF9E, "V"), + (0xFA2, "M", "ྡྷ"), + (0xFA3, "V"), + (0xFA7, "M", "ྦྷ"), + (0xFA8, "V"), + (0xFAC, "M", "ྫྷ"), + (0xFAD, "V"), + (0xFB9, "M", "ྐྵ"), + (0xFBA, "V"), + (0xFBD, "X"), + (0xFBE, "V"), + (0xFCD, "X"), + (0xFCE, "V"), + (0xFDB, "X"), + (0x1000, "V"), + (0x10A0, "M", "ⴀ"), + (0x10A1, "M", "ⴁ"), + (0x10A2, "M", "ⴂ"), + (0x10A3, "M", "ⴃ"), + (0x10A4, "M", "ⴄ"), + (0x10A5, "M", "ⴅ"), + (0x10A6, "M", "ⴆ"), + (0x10A7, "M", "ⴇ"), + (0x10A8, "M", "ⴈ"), + (0x10A9, "M", "ⴉ"), + (0x10AA, "M", "ⴊ"), + (0x10AB, "M", "ⴋ"), + (0x10AC, "M", "ⴌ"), + (0x10AD, "M", "ⴍ"), + (0x10AE, "M", "ⴎ"), + (0x10AF, "M", "ⴏ"), + (0x10B0, "M", "ⴐ"), + (0x10B1, "M", "ⴑ"), + (0x10B2, "M", "ⴒ"), + (0x10B3, "M", "ⴓ"), + (0x10B4, "M", "ⴔ"), + (0x10B5, "M", "ⴕ"), + (0x10B6, "M", "ⴖ"), + (0x10B7, "M", "ⴗ"), + (0x10B8, "M", "ⴘ"), + (0x10B9, "M", "ⴙ"), + (0x10BA, "M", "ⴚ"), + (0x10BB, "M", "ⴛ"), + (0x10BC, "M", "ⴜ"), + (0x10BD, "M", "ⴝ"), + (0x10BE, "M", "ⴞ"), + (0x10BF, "M", "ⴟ"), + (0x10C0, "M", "ⴠ"), + (0x10C1, "M", "ⴡ"), + (0x10C2, "M", "ⴢ"), + (0x10C3, "M", "ⴣ"), + (0x10C4, "M", "ⴤ"), + (0x10C5, "M", "ⴥ"), + (0x10C6, "X"), + (0x10C7, "M", "ⴧ"), + (0x10C8, "X"), + (0x10CD, "M", "ⴭ"), + (0x10CE, "X"), + (0x10D0, "V"), + (0x10FC, "M", "ნ"), + (0x10FD, "V"), + (0x115F, "I"), + (0x1161, "V"), + (0x1249, "X"), + (0x124A, "V"), + (0x124E, "X"), + (0x1250, "V"), + (0x1257, "X"), + (0x1258, "V"), + (0x1259, "X"), + (0x125A, "V"), + (0x125E, "X"), + (0x1260, "V"), + (0x1289, "X"), + (0x128A, "V"), + (0x128E, "X"), + (0x1290, "V"), + (0x12B1, "X"), + (0x12B2, "V"), + (0x12B6, "X"), + (0x12B8, "V"), + (0x12BF, "X"), + (0x12C0, "V"), + (0x12C1, "X"), + (0x12C2, "V"), + (0x12C6, "X"), + (0x12C8, "V"), + (0x12D7, "X"), + (0x12D8, "V"), + (0x1311, "X"), + (0x1312, "V"), + (0x1316, "X"), + (0x1318, "V"), + (0x135B, "X"), + (0x135D, "V"), + (0x137D, "X"), + (0x1380, "V"), + (0x139A, "X"), + (0x13A0, "V"), + (0x13F6, "X"), + (0x13F8, "M", "Ᏸ"), + (0x13F9, "M", "Ᏹ"), + (0x13FA, "M", "Ᏺ"), + (0x13FB, "M", "Ᏻ"), + (0x13FC, "M", "Ᏼ"), + (0x13FD, "M", "Ᏽ"), + (0x13FE, "X"), + (0x1400, "V"), + (0x1680, "X"), + (0x1681, "V"), + (0x169D, "X"), + (0x16A0, "V"), + (0x16F9, "X"), + (0x1700, "V"), + (0x1716, "X"), + (0x171F, "V"), + (0x1737, "X"), + (0x1740, "V"), + (0x1754, "X"), + (0x1760, "V"), + (0x176D, "X"), + (0x176E, "V"), + (0x1771, "X"), + (0x1772, "V"), + (0x1774, "X"), + (0x1780, "V"), + (0x17B4, "I"), + (0x17B6, "V"), + (0x17DE, "X"), + (0x17E0, "V"), + (0x17EA, "X"), + (0x17F0, "V"), + (0x17FA, "X"), + (0x1800, "V"), + (0x180B, "I"), + (0x1810, "V"), + (0x181A, "X"), + (0x1820, "V"), + (0x1879, "X"), + (0x1880, "V"), + (0x18AB, "X"), + (0x18B0, "V"), + (0x18F6, "X"), + (0x1900, "V"), + (0x191F, "X"), + (0x1920, "V"), + (0x192C, "X"), + (0x1930, "V"), + (0x193C, "X"), + (0x1940, "V"), + (0x1941, "X"), + (0x1944, "V"), + (0x196E, "X"), + (0x1970, "V"), + (0x1975, "X"), + (0x1980, "V"), + (0x19AC, "X"), + (0x19B0, "V"), + (0x19CA, "X"), + (0x19D0, "V"), + (0x19DB, "X"), + (0x19DE, "V"), + (0x1A1C, "X"), + (0x1A1E, "V"), + (0x1A5F, "X"), + (0x1A60, "V"), + (0x1A7D, "X"), + (0x1A7F, "V"), + (0x1A8A, "X"), + (0x1A90, "V"), + (0x1A9A, "X"), + (0x1AA0, "V"), + (0x1AAE, "X"), + (0x1AB0, "V"), + (0x1ADE, "X"), + (0x1AE0, "V"), + (0x1AEC, "X"), + (0x1B00, "V"), + (0x1B4D, "X"), + (0x1B4E, "V"), + (0x1BF4, "X"), + (0x1BFC, "V"), + (0x1C38, "X"), + (0x1C3B, "V"), + (0x1C4A, "X"), + (0x1C4D, "V"), + (0x1C80, "M", "в"), + (0x1C81, "M", "д"), + (0x1C82, "M", "о"), + (0x1C83, "M", "с"), + (0x1C84, "M", "т"), + (0x1C86, "M", "ъ"), + (0x1C87, "M", "ѣ"), + (0x1C88, "M", "ꙋ"), + (0x1C89, "M", "ᲊ"), + (0x1C8A, "V"), + (0x1C8B, "X"), + (0x1C90, "M", "ა"), + (0x1C91, "M", "ბ"), + (0x1C92, "M", "გ"), + (0x1C93, "M", "დ"), + (0x1C94, "M", "ე"), + (0x1C95, "M", "ვ"), + (0x1C96, "M", "ზ"), + (0x1C97, "M", "თ"), + (0x1C98, "M", "ი"), + (0x1C99, "M", "კ"), + (0x1C9A, "M", "ლ"), + (0x1C9B, "M", "მ"), + (0x1C9C, "M", "ნ"), + (0x1C9D, "M", "ო"), + (0x1C9E, "M", "პ"), + (0x1C9F, "M", "ჟ"), + (0x1CA0, "M", "რ"), + (0x1CA1, "M", "ს"), + (0x1CA2, "M", "ტ"), + (0x1CA3, "M", "უ"), + (0x1CA4, "M", "ფ"), + (0x1CA5, "M", "ქ"), + (0x1CA6, "M", "ღ"), + (0x1CA7, "M", "ყ"), + (0x1CA8, "M", "შ"), + (0x1CA9, "M", "ჩ"), + (0x1CAA, "M", "ც"), + (0x1CAB, "M", "ძ"), + (0x1CAC, "M", "წ"), + (0x1CAD, "M", "ჭ"), + (0x1CAE, "M", "ხ"), + (0x1CAF, "M", "ჯ"), + (0x1CB0, "M", "ჰ"), + (0x1CB1, "M", "ჱ"), + (0x1CB2, "M", "ჲ"), + (0x1CB3, "M", "ჳ"), + (0x1CB4, "M", "ჴ"), + (0x1CB5, "M", "ჵ"), + (0x1CB6, "M", "ჶ"), + (0x1CB7, "M", "ჷ"), + (0x1CB8, "M", "ჸ"), + (0x1CB9, "M", "ჹ"), + (0x1CBA, "M", "ჺ"), + (0x1CBB, "X"), + (0x1CBD, "M", "ჽ"), + (0x1CBE, "M", "ჾ"), + (0x1CBF, "M", "ჿ"), + (0x1CC0, "V"), + (0x1CC8, "X"), + (0x1CD0, "V"), + (0x1CFB, "X"), + (0x1D00, "V"), + (0x1D2C, "M", "a"), + (0x1D2D, "M", "æ"), + (0x1D2E, "M", "b"), + (0x1D2F, "V"), + (0x1D30, "M", "d"), + (0x1D31, "M", "e"), + (0x1D32, "M", "ǝ"), + (0x1D33, "M", "g"), + (0x1D34, "M", "h"), + (0x1D35, "M", "i"), + (0x1D36, "M", "j"), + (0x1D37, "M", "k"), + (0x1D38, "M", "l"), + (0x1D39, "M", "m"), + (0x1D3A, "M", "n"), + (0x1D3B, "V"), + (0x1D3C, "M", "o"), + (0x1D3D, "M", "ȣ"), + (0x1D3E, "M", "p"), + (0x1D3F, "M", "r"), + (0x1D40, "M", "t"), + (0x1D41, "M", "u"), + (0x1D42, "M", "w"), + (0x1D43, "M", "a"), + (0x1D44, "M", "ɐ"), + (0x1D45, "M", "ɑ"), + (0x1D46, "M", "ᴂ"), + (0x1D47, "M", "b"), + (0x1D48, "M", "d"), + (0x1D49, "M", "e"), + (0x1D4A, "M", "ə"), + (0x1D4B, "M", "ɛ"), + (0x1D4C, "M", "ɜ"), + (0x1D4D, "M", "g"), + (0x1D4E, "V"), + (0x1D4F, "M", "k"), + (0x1D50, "M", "m"), + (0x1D51, "M", "ŋ"), + (0x1D52, "M", "o"), + (0x1D53, "M", "ɔ"), + (0x1D54, "M", "ᴖ"), + (0x1D55, "M", "ᴗ"), + (0x1D56, "M", "p"), + (0x1D57, "M", "t"), + (0x1D58, "M", "u"), + (0x1D59, "M", "ᴝ"), + (0x1D5A, "M", "ɯ"), + (0x1D5B, "M", "v"), + (0x1D5C, "M", "ᴥ"), + (0x1D5D, "M", "β"), + (0x1D5E, "M", "γ"), + (0x1D5F, "M", "δ"), + (0x1D60, "M", "φ"), + (0x1D61, "M", "χ"), + (0x1D62, "M", "i"), + (0x1D63, "M", "r"), + (0x1D64, "M", "u"), + (0x1D65, "M", "v"), + (0x1D66, "M", "β"), + (0x1D67, "M", "γ"), + (0x1D68, "M", "ρ"), + (0x1D69, "M", "φ"), + (0x1D6A, "M", "χ"), + (0x1D6B, "V"), + (0x1D78, "M", "н"), + (0x1D79, "V"), + (0x1D9B, "M", "ɒ"), + (0x1D9C, "M", "c"), + (0x1D9D, "M", "ɕ"), + (0x1D9E, "M", "ð"), + (0x1D9F, "M", "ɜ"), + (0x1DA0, "M", "f"), + (0x1DA1, "M", "ɟ"), + (0x1DA2, "M", "ɡ"), + (0x1DA3, "M", "ɥ"), + (0x1DA4, "M", "ɨ"), + (0x1DA5, "M", "ɩ"), + (0x1DA6, "M", "ɪ"), + (0x1DA7, "M", "ᵻ"), + (0x1DA8, "M", "ʝ"), + (0x1DA9, "M", "ɭ"), + (0x1DAA, "M", "ᶅ"), + (0x1DAB, "M", "ʟ"), + (0x1DAC, "M", "ɱ"), + (0x1DAD, "M", "ɰ"), + (0x1DAE, "M", "ɲ"), + (0x1DAF, "M", "ɳ"), + (0x1DB0, "M", "ɴ"), + (0x1DB1, "M", "ɵ"), + (0x1DB2, "M", "ɸ"), + (0x1DB3, "M", "ʂ"), + (0x1DB4, "M", "ʃ"), + (0x1DB5, "M", "ƫ"), + (0x1DB6, "M", "ʉ"), + (0x1DB7, "M", "ʊ"), + (0x1DB8, "M", "ᴜ"), + (0x1DB9, "M", "ʋ"), + (0x1DBA, "M", "ʌ"), + (0x1DBB, "M", "z"), + (0x1DBC, "M", "ʐ"), + (0x1DBD, "M", "ʑ"), + (0x1DBE, "M", "ʒ"), + (0x1DBF, "M", "θ"), + (0x1DC0, "V"), + (0x1E00, "M", "ḁ"), + (0x1E01, "V"), + (0x1E02, "M", "ḃ"), + (0x1E03, "V"), + (0x1E04, "M", "ḅ"), + (0x1E05, "V"), + (0x1E06, "M", "ḇ"), + (0x1E07, "V"), + (0x1E08, "M", "ḉ"), + (0x1E09, "V"), + (0x1E0A, "M", "ḋ"), + (0x1E0B, "V"), + (0x1E0C, "M", "ḍ"), + (0x1E0D, "V"), + (0x1E0E, "M", "ḏ"), + (0x1E0F, "V"), + (0x1E10, "M", "ḑ"), + (0x1E11, "V"), + (0x1E12, "M", "ḓ"), + (0x1E13, "V"), + (0x1E14, "M", "ḕ"), + (0x1E15, "V"), + (0x1E16, "M", "ḗ"), + (0x1E17, "V"), + (0x1E18, "M", "ḙ"), + (0x1E19, "V"), + (0x1E1A, "M", "ḛ"), + (0x1E1B, "V"), + (0x1E1C, "M", "ḝ"), + (0x1E1D, "V"), + (0x1E1E, "M", "ḟ"), + (0x1E1F, "V"), + (0x1E20, "M", "ḡ"), + (0x1E21, "V"), + (0x1E22, "M", "ḣ"), + (0x1E23, "V"), + (0x1E24, "M", "ḥ"), + (0x1E25, "V"), + (0x1E26, "M", "ḧ"), + (0x1E27, "V"), + (0x1E28, "M", "ḩ"), + (0x1E29, "V"), + (0x1E2A, "M", "ḫ"), + (0x1E2B, "V"), + (0x1E2C, "M", "ḭ"), + (0x1E2D, "V"), + (0x1E2E, "M", "ḯ"), + (0x1E2F, "V"), + (0x1E30, "M", "ḱ"), + (0x1E31, "V"), + (0x1E32, "M", "ḳ"), + (0x1E33, "V"), + (0x1E34, "M", "ḵ"), + (0x1E35, "V"), + (0x1E36, "M", "ḷ"), + (0x1E37, "V"), + (0x1E38, "M", "ḹ"), + (0x1E39, "V"), + (0x1E3A, "M", "ḻ"), + (0x1E3B, "V"), + (0x1E3C, "M", "ḽ"), + (0x1E3D, "V"), + (0x1E3E, "M", "ḿ"), + (0x1E3F, "V"), + (0x1E40, "M", "ṁ"), + (0x1E41, "V"), + (0x1E42, "M", "ṃ"), + (0x1E43, "V"), + (0x1E44, "M", "ṅ"), + (0x1E45, "V"), + (0x1E46, "M", "ṇ"), + (0x1E47, "V"), + (0x1E48, "M", "ṉ"), + (0x1E49, "V"), + (0x1E4A, "M", "ṋ"), + (0x1E4B, "V"), + (0x1E4C, "M", "ṍ"), + (0x1E4D, "V"), + (0x1E4E, "M", "ṏ"), + (0x1E4F, "V"), + (0x1E50, "M", "ṑ"), + (0x1E51, "V"), + (0x1E52, "M", "ṓ"), + (0x1E53, "V"), + (0x1E54, "M", "ṕ"), + (0x1E55, "V"), + (0x1E56, "M", "ṗ"), + (0x1E57, "V"), + (0x1E58, "M", "ṙ"), + (0x1E59, "V"), + (0x1E5A, "M", "ṛ"), + (0x1E5B, "V"), + (0x1E5C, "M", "ṝ"), + (0x1E5D, "V"), + (0x1E5E, "M", "ṟ"), + (0x1E5F, "V"), + (0x1E60, "M", "ṡ"), + (0x1E61, "V"), + (0x1E62, "M", "ṣ"), + (0x1E63, "V"), + (0x1E64, "M", "ṥ"), + (0x1E65, "V"), + (0x1E66, "M", "ṧ"), + (0x1E67, "V"), + (0x1E68, "M", "ṩ"), + (0x1E69, "V"), + (0x1E6A, "M", "ṫ"), + (0x1E6B, "V"), + (0x1E6C, "M", "ṭ"), + (0x1E6D, "V"), + (0x1E6E, "M", "ṯ"), + (0x1E6F, "V"), + (0x1E70, "M", "ṱ"), + (0x1E71, "V"), + (0x1E72, "M", "ṳ"), + (0x1E73, "V"), + (0x1E74, "M", "ṵ"), + (0x1E75, "V"), + (0x1E76, "M", "ṷ"), + (0x1E77, "V"), + (0x1E78, "M", "ṹ"), + (0x1E79, "V"), + (0x1E7A, "M", "ṻ"), + (0x1E7B, "V"), + (0x1E7C, "M", "ṽ"), + (0x1E7D, "V"), + (0x1E7E, "M", "ṿ"), + (0x1E7F, "V"), + (0x1E80, "M", "ẁ"), + (0x1E81, "V"), + (0x1E82, "M", "ẃ"), + (0x1E83, "V"), + (0x1E84, "M", "ẅ"), + (0x1E85, "V"), + (0x1E86, "M", "ẇ"), + (0x1E87, "V"), + (0x1E88, "M", "ẉ"), + (0x1E89, "V"), + (0x1E8A, "M", "ẋ"), + (0x1E8B, "V"), + (0x1E8C, "M", "ẍ"), + (0x1E8D, "V"), + (0x1E8E, "M", "ẏ"), + (0x1E8F, "V"), + (0x1E90, "M", "ẑ"), + (0x1E91, "V"), + (0x1E92, "M", "ẓ"), + (0x1E93, "V"), + (0x1E94, "M", "ẕ"), + (0x1E95, "V"), + (0x1E9A, "M", "aʾ"), + (0x1E9B, "M", "ṡ"), + (0x1E9C, "V"), + (0x1E9E, "M", "ß"), + (0x1E9F, "V"), + (0x1EA0, "M", "ạ"), + (0x1EA1, "V"), + (0x1EA2, "M", "ả"), + (0x1EA3, "V"), + (0x1EA4, "M", "ấ"), + (0x1EA5, "V"), + (0x1EA6, "M", "ầ"), + (0x1EA7, "V"), + (0x1EA8, "M", "ẩ"), + (0x1EA9, "V"), + (0x1EAA, "M", "ẫ"), + (0x1EAB, "V"), + (0x1EAC, "M", "ậ"), + (0x1EAD, "V"), + (0x1EAE, "M", "ắ"), + (0x1EAF, "V"), + (0x1EB0, "M", "ằ"), + (0x1EB1, "V"), + (0x1EB2, "M", "ẳ"), + (0x1EB3, "V"), + (0x1EB4, "M", "ẵ"), + (0x1EB5, "V"), + (0x1EB6, "M", "ặ"), + (0x1EB7, "V"), + (0x1EB8, "M", "ẹ"), + (0x1EB9, "V"), + (0x1EBA, "M", "ẻ"), + (0x1EBB, "V"), + (0x1EBC, "M", "ẽ"), + (0x1EBD, "V"), + (0x1EBE, "M", "ế"), + (0x1EBF, "V"), + (0x1EC0, "M", "ề"), + (0x1EC1, "V"), + (0x1EC2, "M", "ể"), + (0x1EC3, "V"), + (0x1EC4, "M", "ễ"), + (0x1EC5, "V"), + (0x1EC6, "M", "ệ"), + (0x1EC7, "V"), + (0x1EC8, "M", "ỉ"), + (0x1EC9, "V"), + (0x1ECA, "M", "ị"), + (0x1ECB, "V"), + (0x1ECC, "M", "ọ"), + (0x1ECD, "V"), + (0x1ECE, "M", "ỏ"), + (0x1ECF, "V"), + (0x1ED0, "M", "ố"), + (0x1ED1, "V"), + (0x1ED2, "M", "ồ"), + (0x1ED3, "V"), + (0x1ED4, "M", "ổ"), + (0x1ED5, "V"), + (0x1ED6, "M", "ỗ"), + (0x1ED7, "V"), + (0x1ED8, "M", "ộ"), + (0x1ED9, "V"), + (0x1EDA, "M", "ớ"), + (0x1EDB, "V"), + (0x1EDC, "M", "ờ"), + (0x1EDD, "V"), + (0x1EDE, "M", "ở"), + (0x1EDF, "V"), + (0x1EE0, "M", "ỡ"), + (0x1EE1, "V"), + (0x1EE2, "M", "ợ"), + (0x1EE3, "V"), + (0x1EE4, "M", "ụ"), + (0x1EE5, "V"), + (0x1EE6, "M", "ủ"), + (0x1EE7, "V"), + (0x1EE8, "M", "ứ"), + (0x1EE9, "V"), + (0x1EEA, "M", "ừ"), + (0x1EEB, "V"), + (0x1EEC, "M", "ử"), + (0x1EED, "V"), + (0x1EEE, "M", "ữ"), + (0x1EEF, "V"), + (0x1EF0, "M", "ự"), + (0x1EF1, "V"), + (0x1EF2, "M", "ỳ"), + (0x1EF3, "V"), + (0x1EF4, "M", "ỵ"), + (0x1EF5, "V"), + (0x1EF6, "M", "ỷ"), + (0x1EF7, "V"), + (0x1EF8, "M", "ỹ"), + (0x1EF9, "V"), + (0x1EFA, "M", "ỻ"), + (0x1EFB, "V"), + (0x1EFC, "M", "ỽ"), + (0x1EFD, "V"), + (0x1EFE, "M", "ỿ"), + (0x1EFF, "V"), + (0x1F08, "M", "ἀ"), + (0x1F09, "M", "ἁ"), + (0x1F0A, "M", "ἂ"), + (0x1F0B, "M", "ἃ"), + (0x1F0C, "M", "ἄ"), + (0x1F0D, "M", "ἅ"), + (0x1F0E, "M", "ἆ"), + (0x1F0F, "M", "ἇ"), + (0x1F10, "V"), + (0x1F16, "X"), + (0x1F18, "M", "ἐ"), + (0x1F19, "M", "ἑ"), + (0x1F1A, "M", "ἒ"), + (0x1F1B, "M", "ἓ"), + (0x1F1C, "M", "ἔ"), + (0x1F1D, "M", "ἕ"), + (0x1F1E, "X"), + (0x1F20, "V"), + (0x1F28, "M", "ἠ"), + (0x1F29, "M", "ἡ"), + (0x1F2A, "M", "ἢ"), + (0x1F2B, "M", "ἣ"), + (0x1F2C, "M", "ἤ"), + (0x1F2D, "M", "ἥ"), + (0x1F2E, "M", "ἦ"), + (0x1F2F, "M", "ἧ"), + (0x1F30, "V"), + (0x1F38, "M", "ἰ"), + (0x1F39, "M", "ἱ"), + (0x1F3A, "M", "ἲ"), + (0x1F3B, "M", "ἳ"), + (0x1F3C, "M", "ἴ"), + (0x1F3D, "M", "ἵ"), + (0x1F3E, "M", "ἶ"), + (0x1F3F, "M", "ἷ"), + (0x1F40, "V"), + (0x1F46, "X"), + (0x1F48, "M", "ὀ"), + (0x1F49, "M", "ὁ"), + (0x1F4A, "M", "ὂ"), + (0x1F4B, "M", "ὃ"), + (0x1F4C, "M", "ὄ"), + (0x1F4D, "M", "ὅ"), + (0x1F4E, "X"), + (0x1F50, "V"), + (0x1F58, "X"), + (0x1F59, "M", "ὑ"), + (0x1F5A, "X"), + (0x1F5B, "M", "ὓ"), + (0x1F5C, "X"), + (0x1F5D, "M", "ὕ"), + (0x1F5E, "X"), + (0x1F5F, "M", "ὗ"), + (0x1F60, "V"), + (0x1F68, "M", "ὠ"), + (0x1F69, "M", "ὡ"), + (0x1F6A, "M", "ὢ"), + (0x1F6B, "M", "ὣ"), + (0x1F6C, "M", "ὤ"), + (0x1F6D, "M", "ὥ"), + (0x1F6E, "M", "ὦ"), + (0x1F6F, "M", "ὧ"), + (0x1F70, "V"), + (0x1F71, "M", "ά"), + (0x1F72, "V"), + (0x1F73, "M", "έ"), + (0x1F74, "V"), + (0x1F75, "M", "ή"), + (0x1F76, "V"), + (0x1F77, "M", "ί"), + (0x1F78, "V"), + (0x1F79, "M", "ό"), + (0x1F7A, "V"), + (0x1F7B, "M", "ύ"), + (0x1F7C, "V"), + (0x1F7D, "M", "ώ"), + (0x1F7E, "X"), + (0x1F80, "M", "ἀι"), + (0x1F81, "M", "ἁι"), + (0x1F82, "M", "ἂι"), + (0x1F83, "M", "ἃι"), + (0x1F84, "M", "ἄι"), + (0x1F85, "M", "ἅι"), + (0x1F86, "M", "ἆι"), + (0x1F87, "M", "ἇι"), + (0x1F88, "M", "ἀι"), + (0x1F89, "M", "ἁι"), + (0x1F8A, "M", "ἂι"), + (0x1F8B, "M", "ἃι"), + (0x1F8C, "M", "ἄι"), + (0x1F8D, "M", "ἅι"), + (0x1F8E, "M", "ἆι"), + (0x1F8F, "M", "ἇι"), + (0x1F90, "M", "ἠι"), + (0x1F91, "M", "ἡι"), + (0x1F92, "M", "ἢι"), + (0x1F93, "M", "ἣι"), + (0x1F94, "M", "ἤι"), + (0x1F95, "M", "ἥι"), + (0x1F96, "M", "ἦι"), + (0x1F97, "M", "ἧι"), + (0x1F98, "M", "ἠι"), + (0x1F99, "M", "ἡι"), + (0x1F9A, "M", "ἢι"), + (0x1F9B, "M", "ἣι"), + (0x1F9C, "M", "ἤι"), + (0x1F9D, "M", "ἥι"), + (0x1F9E, "M", "ἦι"), + (0x1F9F, "M", "ἧι"), + (0x1FA0, "M", "ὠι"), + (0x1FA1, "M", "ὡι"), + (0x1FA2, "M", "ὢι"), + (0x1FA3, "M", "ὣι"), + (0x1FA4, "M", "ὤι"), + (0x1FA5, "M", "ὥι"), + (0x1FA6, "M", "ὦι"), + (0x1FA7, "M", "ὧι"), + (0x1FA8, "M", "ὠι"), + (0x1FA9, "M", "ὡι"), + (0x1FAA, "M", "ὢι"), + (0x1FAB, "M", "ὣι"), + (0x1FAC, "M", "ὤι"), + (0x1FAD, "M", "ὥι"), + (0x1FAE, "M", "ὦι"), + (0x1FAF, "M", "ὧι"), + (0x1FB0, "V"), + (0x1FB2, "M", "ὰι"), + (0x1FB3, "M", "αι"), + (0x1FB4, "M", "άι"), + (0x1FB5, "X"), + (0x1FB6, "V"), + (0x1FB7, "M", "ᾶι"), + (0x1FB8, "M", "ᾰ"), + (0x1FB9, "M", "ᾱ"), + (0x1FBA, "M", "ὰ"), + (0x1FBB, "M", "ά"), + (0x1FBC, "M", "αι"), + (0x1FBD, "M", " ̓"), + (0x1FBE, "M", "ι"), + (0x1FBF, "M", " ̓"), + (0x1FC0, "M", " ͂"), + (0x1FC1, "M", " ̈͂"), + (0x1FC2, "M", "ὴι"), + (0x1FC3, "M", "ηι"), + (0x1FC4, "M", "ήι"), + (0x1FC5, "X"), + (0x1FC6, "V"), + (0x1FC7, "M", "ῆι"), + (0x1FC8, "M", "ὲ"), + (0x1FC9, "M", "έ"), + (0x1FCA, "M", "ὴ"), + (0x1FCB, "M", "ή"), + (0x1FCC, "M", "ηι"), + (0x1FCD, "M", " ̓̀"), + (0x1FCE, "M", " ̓́"), + (0x1FCF, "M", " ̓͂"), + (0x1FD0, "V"), + (0x1FD3, "M", "ΐ"), + (0x1FD4, "X"), + (0x1FD6, "V"), + (0x1FD8, "M", "ῐ"), + (0x1FD9, "M", "ῑ"), + (0x1FDA, "M", "ὶ"), + (0x1FDB, "M", "ί"), + (0x1FDC, "X"), + (0x1FDD, "M", " ̔̀"), + (0x1FDE, "M", " ̔́"), + (0x1FDF, "M", " ̔͂"), + (0x1FE0, "V"), + (0x1FE3, "M", "ΰ"), + (0x1FE4, "V"), + (0x1FE8, "M", "ῠ"), + (0x1FE9, "M", "ῡ"), + (0x1FEA, "M", "ὺ"), + (0x1FEB, "M", "ύ"), + (0x1FEC, "M", "ῥ"), + (0x1FED, "M", " ̈̀"), + (0x1FEE, "M", " ̈́"), + (0x1FEF, "M", "`"), + (0x1FF0, "X"), + (0x1FF2, "M", "ὼι"), + (0x1FF3, "M", "ωι"), + (0x1FF4, "M", "ώι"), + (0x1FF5, "X"), + (0x1FF6, "V"), + (0x1FF7, "M", "ῶι"), + (0x1FF8, "M", "ὸ"), + (0x1FF9, "M", "ό"), + (0x1FFA, "M", "ὼ"), + (0x1FFB, "M", "ώ"), + (0x1FFC, "M", "ωι"), + (0x1FFD, "M", " ́"), + (0x1FFE, "M", " ̔"), + (0x1FFF, "X"), + (0x2000, "M", " "), + (0x200B, "I"), + (0x200C, "D", ""), + (0x200E, "X"), + (0x2010, "V"), + (0x2011, "M", "‐"), + (0x2012, "V"), + (0x2017, "M", " ̳"), + (0x2018, "V"), + (0x2024, "X"), + (0x2027, "V"), + (0x2028, "X"), + (0x202F, "M", " "), + (0x2030, "V"), + (0x2033, "M", "′′"), + (0x2034, "M", "′′′"), + (0x2035, "V"), + (0x2036, "M", "‵‵"), + (0x2037, "M", "‵‵‵"), + (0x2038, "V"), + (0x203C, "M", "!!"), + (0x203D, "V"), + (0x203E, "M", " ̅"), + (0x203F, "V"), + (0x2047, "M", "??"), + (0x2048, "M", "?!"), + (0x2049, "M", "!?"), + (0x204A, "V"), + (0x2057, "M", "′′′′"), + (0x2058, "V"), + (0x205F, "M", " "), + (0x2060, "I"), + (0x2065, "X"), + (0x206A, "I"), + (0x2070, "M", "0"), + (0x2071, "M", "i"), + (0x2072, "X"), + (0x2074, "M", "4"), + (0x2075, "M", "5"), + (0x2076, "M", "6"), + (0x2077, "M", "7"), + (0x2078, "M", "8"), + (0x2079, "M", "9"), + (0x207A, "M", "+"), + (0x207B, "M", "−"), + (0x207C, "M", "="), + (0x207D, "M", "("), + (0x207E, "M", ")"), + (0x207F, "M", "n"), + (0x2080, "M", "0"), + (0x2081, "M", "1"), + (0x2082, "M", "2"), + (0x2083, "M", "3"), + (0x2084, "M", "4"), + (0x2085, "M", "5"), + (0x2086, "M", "6"), + (0x2087, "M", "7"), + (0x2088, "M", "8"), + (0x2089, "M", "9"), + (0x208A, "M", "+"), + (0x208B, "M", "−"), + (0x208C, "M", "="), + (0x208D, "M", "("), + (0x208E, "M", ")"), + (0x208F, "X"), + (0x2090, "M", "a"), + (0x2091, "M", "e"), + (0x2092, "M", "o"), + (0x2093, "M", "x"), + (0x2094, "M", "ə"), + (0x2095, "M", "h"), + (0x2096, "M", "k"), + (0x2097, "M", "l"), + (0x2098, "M", "m"), + (0x2099, "M", "n"), + (0x209A, "M", "p"), + (0x209B, "M", "s"), + (0x209C, "M", "t"), + (0x209D, "X"), + (0x20A0, "V"), + (0x20A8, "M", "rs"), + (0x20A9, "V"), + (0x20C2, "X"), + (0x20D0, "V"), + (0x20F1, "X"), + (0x2100, "M", "a/c"), + (0x2101, "M", "a/s"), + (0x2102, "M", "c"), + (0x2103, "M", "°c"), + (0x2104, "V"), + (0x2105, "M", "c/o"), + (0x2106, "M", "c/u"), + (0x2107, "M", "ɛ"), + (0x2108, "V"), + (0x2109, "M", "°f"), + (0x210A, "M", "g"), + (0x210B, "M", "h"), + (0x210F, "M", "ħ"), + (0x2110, "M", "i"), + (0x2112, "M", "l"), + (0x2114, "V"), + (0x2115, "M", "n"), + (0x2116, "M", "no"), + (0x2117, "V"), + (0x2119, "M", "p"), + (0x211A, "M", "q"), + (0x211B, "M", "r"), + (0x211E, "V"), + (0x2120, "M", "sm"), + (0x2121, "M", "tel"), + (0x2122, "M", "tm"), + (0x2123, "V"), + (0x2124, "M", "z"), + (0x2125, "V"), + (0x2126, "M", "ω"), + (0x2127, "V"), + (0x2128, "M", "z"), + (0x2129, "V"), + (0x212A, "M", "k"), + (0x212B, "M", "å"), + (0x212C, "M", "b"), + (0x212D, "M", "c"), + (0x212E, "V"), + (0x212F, "M", "e"), + (0x2131, "M", "f"), + (0x2132, "M", "ⅎ"), + (0x2133, "M", "m"), + (0x2134, "M", "o"), + (0x2135, "M", "א"), + (0x2136, "M", "ב"), + (0x2137, "M", "ג"), + (0x2138, "M", "ד"), + (0x2139, "M", "i"), + (0x213A, "V"), + (0x213B, "M", "fax"), + (0x213C, "M", "π"), + (0x213D, "M", "γ"), + (0x213F, "M", "π"), + (0x2140, "M", "∑"), + (0x2141, "V"), + (0x2145, "M", "d"), + (0x2147, "M", "e"), + (0x2148, "M", "i"), + (0x2149, "M", "j"), + (0x214A, "V"), + (0x2150, "M", "1⁄7"), + (0x2151, "M", "1⁄9"), + (0x2152, "M", "1⁄10"), + (0x2153, "M", "1⁄3"), + (0x2154, "M", "2⁄3"), + (0x2155, "M", "1⁄5"), + (0x2156, "M", "2⁄5"), + (0x2157, "M", "3⁄5"), + (0x2158, "M", "4⁄5"), + (0x2159, "M", "1⁄6"), + (0x215A, "M", "5⁄6"), + (0x215B, "M", "1⁄8"), + (0x215C, "M", "3⁄8"), + (0x215D, "M", "5⁄8"), + (0x215E, "M", "7⁄8"), + (0x215F, "M", "1⁄"), + (0x2160, "M", "i"), + (0x2161, "M", "ii"), + (0x2162, "M", "iii"), + (0x2163, "M", "iv"), + (0x2164, "M", "v"), + (0x2165, "M", "vi"), + (0x2166, "M", "vii"), + (0x2167, "M", "viii"), + (0x2168, "M", "ix"), + (0x2169, "M", "x"), + (0x216A, "M", "xi"), + (0x216B, "M", "xii"), + (0x216C, "M", "l"), + (0x216D, "M", "c"), + (0x216E, "M", "d"), + (0x216F, "M", "m"), + (0x2170, "M", "i"), + (0x2171, "M", "ii"), + (0x2172, "M", "iii"), + (0x2173, "M", "iv"), + (0x2174, "M", "v"), + (0x2175, "M", "vi"), + (0x2176, "M", "vii"), + (0x2177, "M", "viii"), + (0x2178, "M", "ix"), + (0x2179, "M", "x"), + (0x217A, "M", "xi"), + (0x217B, "M", "xii"), + (0x217C, "M", "l"), + (0x217D, "M", "c"), + (0x217E, "M", "d"), + (0x217F, "M", "m"), + (0x2180, "V"), + (0x2183, "M", "ↄ"), + (0x2184, "V"), + (0x2189, "M", "0⁄3"), + (0x218A, "V"), + (0x218C, "X"), + (0x2190, "V"), + (0x222C, "M", "∫∫"), + (0x222D, "M", "∫∫∫"), + (0x222E, "V"), + (0x222F, "M", "∮∮"), + (0x2230, "M", "∮∮∮"), + (0x2231, "V"), + (0x2329, "M", "〈"), + (0x232A, "M", "〉"), + (0x232B, "V"), + (0x242A, "X"), + (0x2440, "V"), + (0x244B, "X"), + (0x2460, "M", "1"), + (0x2461, "M", "2"), + (0x2462, "M", "3"), + (0x2463, "M", "4"), + (0x2464, "M", "5"), + (0x2465, "M", "6"), + (0x2466, "M", "7"), + (0x2467, "M", "8"), + (0x2468, "M", "9"), + (0x2469, "M", "10"), + (0x246A, "M", "11"), + (0x246B, "M", "12"), + (0x246C, "M", "13"), + (0x246D, "M", "14"), + (0x246E, "M", "15"), + (0x246F, "M", "16"), + (0x2470, "M", "17"), + (0x2471, "M", "18"), + (0x2472, "M", "19"), + (0x2473, "M", "20"), + (0x2474, "M", "(1)"), + (0x2475, "M", "(2)"), + (0x2476, "M", "(3)"), + (0x2477, "M", "(4)"), + (0x2478, "M", "(5)"), + (0x2479, "M", "(6)"), + (0x247A, "M", "(7)"), + (0x247B, "M", "(8)"), + (0x247C, "M", "(9)"), + (0x247D, "M", "(10)"), + (0x247E, "M", "(11)"), + (0x247F, "M", "(12)"), + (0x2480, "M", "(13)"), + (0x2481, "M", "(14)"), + (0x2482, "M", "(15)"), + (0x2483, "M", "(16)"), + (0x2484, "M", "(17)"), + (0x2485, "M", "(18)"), + (0x2486, "M", "(19)"), + (0x2487, "M", "(20)"), + (0x2488, "X"), + (0x249C, "M", "(a)"), + (0x249D, "M", "(b)"), + (0x249E, "M", "(c)"), + (0x249F, "M", "(d)"), + (0x24A0, "M", "(e)"), + (0x24A1, "M", "(f)"), + (0x24A2, "M", "(g)"), + (0x24A3, "M", "(h)"), + (0x24A4, "M", "(i)"), + (0x24A5, "M", "(j)"), + (0x24A6, "M", "(k)"), + (0x24A7, "M", "(l)"), + (0x24A8, "M", "(m)"), + (0x24A9, "M", "(n)"), + (0x24AA, "M", "(o)"), + (0x24AB, "M", "(p)"), + (0x24AC, "M", "(q)"), + (0x24AD, "M", "(r)"), + (0x24AE, "M", "(s)"), + (0x24AF, "M", "(t)"), + (0x24B0, "M", "(u)"), + (0x24B1, "M", "(v)"), + (0x24B2, "M", "(w)"), + (0x24B3, "M", "(x)"), + (0x24B4, "M", "(y)"), + (0x24B5, "M", "(z)"), + (0x24B6, "M", "a"), + (0x24B7, "M", "b"), + (0x24B8, "M", "c"), + (0x24B9, "M", "d"), + (0x24BA, "M", "e"), + (0x24BB, "M", "f"), + (0x24BC, "M", "g"), + (0x24BD, "M", "h"), + (0x24BE, "M", "i"), + (0x24BF, "M", "j"), + (0x24C0, "M", "k"), + (0x24C1, "M", "l"), + (0x24C2, "M", "m"), + (0x24C3, "M", "n"), + (0x24C4, "M", "o"), + (0x24C5, "M", "p"), + (0x24C6, "M", "q"), + (0x24C7, "M", "r"), + (0x24C8, "M", "s"), + (0x24C9, "M", "t"), + (0x24CA, "M", "u"), + (0x24CB, "M", "v"), + (0x24CC, "M", "w"), + (0x24CD, "M", "x"), + (0x24CE, "M", "y"), + (0x24CF, "M", "z"), + (0x24D0, "M", "a"), + (0x24D1, "M", "b"), + (0x24D2, "M", "c"), + (0x24D3, "M", "d"), + (0x24D4, "M", "e"), + (0x24D5, "M", "f"), + (0x24D6, "M", "g"), + (0x24D7, "M", "h"), + (0x24D8, "M", "i"), + (0x24D9, "M", "j"), + (0x24DA, "M", "k"), + (0x24DB, "M", "l"), + (0x24DC, "M", "m"), + (0x24DD, "M", "n"), + (0x24DE, "M", "o"), + (0x24DF, "M", "p"), + (0x24E0, "M", "q"), + (0x24E1, "M", "r"), + (0x24E2, "M", "s"), + (0x24E3, "M", "t"), + (0x24E4, "M", "u"), + (0x24E5, "M", "v"), + (0x24E6, "M", "w"), + (0x24E7, "M", "x"), + (0x24E8, "M", "y"), + (0x24E9, "M", "z"), + (0x24EA, "M", "0"), + (0x24EB, "V"), + (0x2A0C, "M", "∫∫∫∫"), + (0x2A0D, "V"), + (0x2A74, "M", "::="), + (0x2A75, "M", "=="), + (0x2A76, "M", "==="), + (0x2A77, "V"), + (0x2ADC, "M", "⫝̸"), + (0x2ADD, "V"), + (0x2B74, "X"), + (0x2B76, "V"), + (0x2C00, "M", "ⰰ"), + (0x2C01, "M", "ⰱ"), + (0x2C02, "M", "ⰲ"), + (0x2C03, "M", "ⰳ"), + (0x2C04, "M", "ⰴ"), + (0x2C05, "M", "ⰵ"), + (0x2C06, "M", "ⰶ"), + (0x2C07, "M", "ⰷ"), + (0x2C08, "M", "ⰸ"), + (0x2C09, "M", "ⰹ"), + (0x2C0A, "M", "ⰺ"), + (0x2C0B, "M", "ⰻ"), + (0x2C0C, "M", "ⰼ"), + (0x2C0D, "M", "ⰽ"), + (0x2C0E, "M", "ⰾ"), + (0x2C0F, "M", "ⰿ"), + (0x2C10, "M", "ⱀ"), + (0x2C11, "M", "ⱁ"), + (0x2C12, "M", "ⱂ"), + (0x2C13, "M", "ⱃ"), + (0x2C14, "M", "ⱄ"), + (0x2C15, "M", "ⱅ"), + (0x2C16, "M", "ⱆ"), + (0x2C17, "M", "ⱇ"), + (0x2C18, "M", "ⱈ"), + (0x2C19, "M", "ⱉ"), + (0x2C1A, "M", "ⱊ"), + (0x2C1B, "M", "ⱋ"), + (0x2C1C, "M", "ⱌ"), + (0x2C1D, "M", "ⱍ"), + (0x2C1E, "M", "ⱎ"), + (0x2C1F, "M", "ⱏ"), + (0x2C20, "M", "ⱐ"), + (0x2C21, "M", "ⱑ"), + (0x2C22, "M", "ⱒ"), + (0x2C23, "M", "ⱓ"), + (0x2C24, "M", "ⱔ"), + (0x2C25, "M", "ⱕ"), + (0x2C26, "M", "ⱖ"), + (0x2C27, "M", "ⱗ"), + (0x2C28, "M", "ⱘ"), + (0x2C29, "M", "ⱙ"), + (0x2C2A, "M", "ⱚ"), + (0x2C2B, "M", "ⱛ"), + (0x2C2C, "M", "ⱜ"), + (0x2C2D, "M", "ⱝ"), + (0x2C2E, "M", "ⱞ"), + (0x2C2F, "M", "ⱟ"), + (0x2C30, "V"), + (0x2C60, "M", "ⱡ"), + (0x2C61, "V"), + (0x2C62, "M", "ɫ"), + (0x2C63, "M", "ᵽ"), + (0x2C64, "M", "ɽ"), + (0x2C65, "V"), + (0x2C67, "M", "ⱨ"), + (0x2C68, "V"), + (0x2C69, "M", "ⱪ"), + (0x2C6A, "V"), + (0x2C6B, "M", "ⱬ"), + (0x2C6C, "V"), + (0x2C6D, "M", "ɑ"), + (0x2C6E, "M", "ɱ"), + (0x2C6F, "M", "ɐ"), + (0x2C70, "M", "ɒ"), + (0x2C71, "V"), + (0x2C72, "M", "ⱳ"), + (0x2C73, "V"), + (0x2C75, "M", "ⱶ"), + (0x2C76, "V"), + (0x2C7C, "M", "j"), + (0x2C7D, "M", "v"), + (0x2C7E, "M", "ȿ"), + (0x2C7F, "M", "ɀ"), + (0x2C80, "M", "ⲁ"), + (0x2C81, "V"), + (0x2C82, "M", "ⲃ"), + (0x2C83, "V"), + (0x2C84, "M", "ⲅ"), + (0x2C85, "V"), + (0x2C86, "M", "ⲇ"), + (0x2C87, "V"), + (0x2C88, "M", "ⲉ"), + (0x2C89, "V"), + (0x2C8A, "M", "ⲋ"), + (0x2C8B, "V"), + (0x2C8C, "M", "ⲍ"), + (0x2C8D, "V"), + (0x2C8E, "M", "ⲏ"), + (0x2C8F, "V"), + (0x2C90, "M", "ⲑ"), + (0x2C91, "V"), + (0x2C92, "M", "ⲓ"), + (0x2C93, "V"), + (0x2C94, "M", "ⲕ"), + (0x2C95, "V"), + (0x2C96, "M", "ⲗ"), + (0x2C97, "V"), + (0x2C98, "M", "ⲙ"), + (0x2C99, "V"), + (0x2C9A, "M", "ⲛ"), + (0x2C9B, "V"), + (0x2C9C, "M", "ⲝ"), + (0x2C9D, "V"), + (0x2C9E, "M", "ⲟ"), + (0x2C9F, "V"), + (0x2CA0, "M", "ⲡ"), + (0x2CA1, "V"), + (0x2CA2, "M", "ⲣ"), + (0x2CA3, "V"), + (0x2CA4, "M", "ⲥ"), + (0x2CA5, "V"), + (0x2CA6, "M", "ⲧ"), + (0x2CA7, "V"), + (0x2CA8, "M", "ⲩ"), + (0x2CA9, "V"), + (0x2CAA, "M", "ⲫ"), + (0x2CAB, "V"), + (0x2CAC, "M", "ⲭ"), + (0x2CAD, "V"), + (0x2CAE, "M", "ⲯ"), + (0x2CAF, "V"), + (0x2CB0, "M", "ⲱ"), + (0x2CB1, "V"), + (0x2CB2, "M", "ⲳ"), + (0x2CB3, "V"), + (0x2CB4, "M", "ⲵ"), + (0x2CB5, "V"), + (0x2CB6, "M", "ⲷ"), + (0x2CB7, "V"), + (0x2CB8, "M", "ⲹ"), + (0x2CB9, "V"), + (0x2CBA, "M", "ⲻ"), + (0x2CBB, "V"), + (0x2CBC, "M", "ⲽ"), + (0x2CBD, "V"), + (0x2CBE, "M", "ⲿ"), + (0x2CBF, "V"), + (0x2CC0, "M", "ⳁ"), + (0x2CC1, "V"), + (0x2CC2, "M", "ⳃ"), + (0x2CC3, "V"), + (0x2CC4, "M", "ⳅ"), + (0x2CC5, "V"), + (0x2CC6, "M", "ⳇ"), + (0x2CC7, "V"), + (0x2CC8, "M", "ⳉ"), + (0x2CC9, "V"), + (0x2CCA, "M", "ⳋ"), + (0x2CCB, "V"), + (0x2CCC, "M", "ⳍ"), + (0x2CCD, "V"), + (0x2CCE, "M", "ⳏ"), + (0x2CCF, "V"), + (0x2CD0, "M", "ⳑ"), + (0x2CD1, "V"), + (0x2CD2, "M", "ⳓ"), + (0x2CD3, "V"), + (0x2CD4, "M", "ⳕ"), + (0x2CD5, "V"), + (0x2CD6, "M", "ⳗ"), + (0x2CD7, "V"), + (0x2CD8, "M", "ⳙ"), + (0x2CD9, "V"), + (0x2CDA, "M", "ⳛ"), + (0x2CDB, "V"), + (0x2CDC, "M", "ⳝ"), + (0x2CDD, "V"), + (0x2CDE, "M", "ⳟ"), + (0x2CDF, "V"), + (0x2CE0, "M", "ⳡ"), + (0x2CE1, "V"), + (0x2CE2, "M", "ⳣ"), + (0x2CE3, "V"), + (0x2CEB, "M", "ⳬ"), + (0x2CEC, "V"), + (0x2CED, "M", "ⳮ"), + (0x2CEE, "V"), + (0x2CF2, "M", "ⳳ"), + (0x2CF3, "V"), + (0x2CF4, "X"), + (0x2CF9, "V"), + (0x2D26, "X"), + (0x2D27, "V"), + (0x2D28, "X"), + (0x2D2D, "V"), + (0x2D2E, "X"), + (0x2D30, "V"), + (0x2D68, "X"), + (0x2D6F, "M", "ⵡ"), + (0x2D70, "V"), + (0x2D71, "X"), + (0x2D7F, "V"), + (0x2D97, "X"), + (0x2DA0, "V"), + (0x2DA7, "X"), + (0x2DA8, "V"), + (0x2DAF, "X"), + (0x2DB0, "V"), + (0x2DB7, "X"), + (0x2DB8, "V"), + (0x2DBF, "X"), + (0x2DC0, "V"), + (0x2DC7, "X"), + (0x2DC8, "V"), + (0x2DCF, "X"), + (0x2DD0, "V"), + (0x2DD7, "X"), + (0x2DD8, "V"), + (0x2DDF, "X"), + (0x2DE0, "V"), + (0x2E5E, "X"), + (0x2E80, "V"), + (0x2E9A, "X"), + (0x2E9B, "V"), + (0x2E9F, "M", "母"), + (0x2EA0, "V"), + (0x2EF3, "M", "龟"), + (0x2EF4, "X"), + (0x2F00, "M", "一"), + (0x2F01, "M", "丨"), + (0x2F02, "M", "丶"), + (0x2F03, "M", "丿"), + (0x2F04, "M", "乙"), + (0x2F05, "M", "亅"), + (0x2F06, "M", "二"), + (0x2F07, "M", "亠"), + (0x2F08, "M", "人"), + (0x2F09, "M", "儿"), + (0x2F0A, "M", "入"), + (0x2F0B, "M", "八"), + (0x2F0C, "M", "冂"), + (0x2F0D, "M", "冖"), + (0x2F0E, "M", "冫"), + (0x2F0F, "M", "几"), + (0x2F10, "M", "凵"), + (0x2F11, "M", "刀"), + (0x2F12, "M", "力"), + (0x2F13, "M", "勹"), + (0x2F14, "M", "匕"), + (0x2F15, "M", "匚"), + (0x2F16, "M", "匸"), + (0x2F17, "M", "十"), + (0x2F18, "M", "卜"), + (0x2F19, "M", "卩"), + (0x2F1A, "M", "厂"), + (0x2F1B, "M", "厶"), + (0x2F1C, "M", "又"), + (0x2F1D, "M", "口"), + (0x2F1E, "M", "囗"), + (0x2F1F, "M", "土"), + (0x2F20, "M", "士"), + (0x2F21, "M", "夂"), + (0x2F22, "M", "夊"), + (0x2F23, "M", "夕"), + (0x2F24, "M", "大"), + (0x2F25, "M", "女"), + (0x2F26, "M", "子"), + (0x2F27, "M", "宀"), + (0x2F28, "M", "寸"), + (0x2F29, "M", "小"), + (0x2F2A, "M", "尢"), + (0x2F2B, "M", "尸"), + (0x2F2C, "M", "屮"), + (0x2F2D, "M", "山"), + (0x2F2E, "M", "巛"), + (0x2F2F, "M", "工"), + (0x2F30, "M", "己"), + (0x2F31, "M", "巾"), + (0x2F32, "M", "干"), + (0x2F33, "M", "幺"), + (0x2F34, "M", "广"), + (0x2F35, "M", "廴"), + (0x2F36, "M", "廾"), + (0x2F37, "M", "弋"), + (0x2F38, "M", "弓"), + (0x2F39, "M", "彐"), + (0x2F3A, "M", "彡"), + (0x2F3B, "M", "彳"), + (0x2F3C, "M", "心"), + (0x2F3D, "M", "戈"), + (0x2F3E, "M", "戶"), + (0x2F3F, "M", "手"), + (0x2F40, "M", "支"), + (0x2F41, "M", "攴"), + (0x2F42, "M", "文"), + (0x2F43, "M", "斗"), + (0x2F44, "M", "斤"), + (0x2F45, "M", "方"), + (0x2F46, "M", "无"), + (0x2F47, "M", "日"), + (0x2F48, "M", "曰"), + (0x2F49, "M", "月"), + (0x2F4A, "M", "木"), + (0x2F4B, "M", "欠"), + (0x2F4C, "M", "止"), + (0x2F4D, "M", "歹"), + (0x2F4E, "M", "殳"), + (0x2F4F, "M", "毋"), + (0x2F50, "M", "比"), + (0x2F51, "M", "毛"), + (0x2F52, "M", "氏"), + (0x2F53, "M", "气"), + (0x2F54, "M", "水"), + (0x2F55, "M", "火"), + (0x2F56, "M", "爪"), + (0x2F57, "M", "父"), + (0x2F58, "M", "爻"), + (0x2F59, "M", "爿"), + (0x2F5A, "M", "片"), + (0x2F5B, "M", "牙"), + (0x2F5C, "M", "牛"), + (0x2F5D, "M", "犬"), + (0x2F5E, "M", "玄"), + (0x2F5F, "M", "玉"), + (0x2F60, "M", "瓜"), + (0x2F61, "M", "瓦"), + (0x2F62, "M", "甘"), + (0x2F63, "M", "生"), + (0x2F64, "M", "用"), + (0x2F65, "M", "田"), + (0x2F66, "M", "疋"), + (0x2F67, "M", "疒"), + (0x2F68, "M", "癶"), + (0x2F69, "M", "白"), + (0x2F6A, "M", "皮"), + (0x2F6B, "M", "皿"), + (0x2F6C, "M", "目"), + (0x2F6D, "M", "矛"), + (0x2F6E, "M", "矢"), + (0x2F6F, "M", "石"), + (0x2F70, "M", "示"), + (0x2F71, "M", "禸"), + (0x2F72, "M", "禾"), + (0x2F73, "M", "穴"), + (0x2F74, "M", "立"), + (0x2F75, "M", "竹"), + (0x2F76, "M", "米"), + (0x2F77, "M", "糸"), + (0x2F78, "M", "缶"), + (0x2F79, "M", "网"), + (0x2F7A, "M", "羊"), + (0x2F7B, "M", "羽"), + (0x2F7C, "M", "老"), + (0x2F7D, "M", "而"), + (0x2F7E, "M", "耒"), + (0x2F7F, "M", "耳"), + (0x2F80, "M", "聿"), + (0x2F81, "M", "肉"), + (0x2F82, "M", "臣"), + (0x2F83, "M", "自"), + (0x2F84, "M", "至"), + (0x2F85, "M", "臼"), + (0x2F86, "M", "舌"), + (0x2F87, "M", "舛"), + (0x2F88, "M", "舟"), + (0x2F89, "M", "艮"), + (0x2F8A, "M", "色"), + (0x2F8B, "M", "艸"), + (0x2F8C, "M", "虍"), + (0x2F8D, "M", "虫"), + (0x2F8E, "M", "血"), + (0x2F8F, "M", "行"), + (0x2F90, "M", "衣"), + (0x2F91, "M", "襾"), + (0x2F92, "M", "見"), + (0x2F93, "M", "角"), + (0x2F94, "M", "言"), + (0x2F95, "M", "谷"), + (0x2F96, "M", "豆"), + (0x2F97, "M", "豕"), + (0x2F98, "M", "豸"), + (0x2F99, "M", "貝"), + (0x2F9A, "M", "赤"), + (0x2F9B, "M", "走"), + (0x2F9C, "M", "足"), + (0x2F9D, "M", "身"), + (0x2F9E, "M", "車"), + (0x2F9F, "M", "辛"), + (0x2FA0, "M", "辰"), + (0x2FA1, "M", "辵"), + (0x2FA2, "M", "邑"), + (0x2FA3, "M", "酉"), + (0x2FA4, "M", "釆"), + (0x2FA5, "M", "里"), + (0x2FA6, "M", "金"), + (0x2FA7, "M", "長"), + (0x2FA8, "M", "門"), + (0x2FA9, "M", "阜"), + (0x2FAA, "M", "隶"), + (0x2FAB, "M", "隹"), + (0x2FAC, "M", "雨"), + (0x2FAD, "M", "靑"), + (0x2FAE, "M", "非"), + (0x2FAF, "M", "面"), + (0x2FB0, "M", "革"), + (0x2FB1, "M", "韋"), + (0x2FB2, "M", "韭"), + (0x2FB3, "M", "音"), + (0x2FB4, "M", "頁"), + (0x2FB5, "M", "風"), + (0x2FB6, "M", "飛"), + (0x2FB7, "M", "食"), + (0x2FB8, "M", "首"), + (0x2FB9, "M", "香"), + (0x2FBA, "M", "馬"), + (0x2FBB, "M", "骨"), + (0x2FBC, "M", "高"), + (0x2FBD, "M", "髟"), + (0x2FBE, "M", "鬥"), + (0x2FBF, "M", "鬯"), + (0x2FC0, "M", "鬲"), + (0x2FC1, "M", "鬼"), + (0x2FC2, "M", "魚"), + (0x2FC3, "M", "鳥"), + (0x2FC4, "M", "鹵"), + (0x2FC5, "M", "鹿"), + (0x2FC6, "M", "麥"), + (0x2FC7, "M", "麻"), + (0x2FC8, "M", "黃"), + (0x2FC9, "M", "黍"), + (0x2FCA, "M", "黑"), + (0x2FCB, "M", "黹"), + (0x2FCC, "M", "黽"), + (0x2FCD, "M", "鼎"), + (0x2FCE, "M", "鼓"), + (0x2FCF, "M", "鼠"), + (0x2FD0, "M", "鼻"), + (0x2FD1, "M", "齊"), + (0x2FD2, "M", "齒"), + (0x2FD3, "M", "龍"), + (0x2FD4, "M", "龜"), + (0x2FD5, "M", "龠"), + (0x2FD6, "X"), + (0x3000, "M", " "), + (0x3001, "V"), + (0x3002, "M", "."), + (0x3003, "V"), + (0x3036, "M", "〒"), + (0x3037, "V"), + (0x3038, "M", "十"), + (0x3039, "M", "卄"), + (0x303A, "M", "卅"), + (0x303B, "V"), + (0x3040, "X"), + (0x3041, "V"), + (0x3097, "X"), + (0x3099, "V"), + (0x309B, "M", " ゙"), + (0x309C, "M", " ゚"), + (0x309D, "V"), + (0x309F, "M", "より"), + (0x30A0, "V"), + (0x30FF, "M", "コト"), + (0x3100, "X"), + (0x3105, "V"), + (0x3130, "X"), + (0x3131, "M", "ᄀ"), + (0x3132, "M", "ᄁ"), + (0x3133, "M", "ᆪ"), + (0x3134, "M", "ᄂ"), + (0x3135, "M", "ᆬ"), + (0x3136, "M", "ᆭ"), + (0x3137, "M", "ᄃ"), + (0x3138, "M", "ᄄ"), + (0x3139, "M", "ᄅ"), + (0x313A, "M", "ᆰ"), + (0x313B, "M", "ᆱ"), + (0x313C, "M", "ᆲ"), + (0x313D, "M", "ᆳ"), + (0x313E, "M", "ᆴ"), + (0x313F, "M", "ᆵ"), + (0x3140, "M", "ᄚ"), + (0x3141, "M", "ᄆ"), + (0x3142, "M", "ᄇ"), + (0x3143, "M", "ᄈ"), + (0x3144, "M", "ᄡ"), + (0x3145, "M", "ᄉ"), + (0x3146, "M", "ᄊ"), + (0x3147, "M", "ᄋ"), + (0x3148, "M", "ᄌ"), + (0x3149, "M", "ᄍ"), + (0x314A, "M", "ᄎ"), + (0x314B, "M", "ᄏ"), + (0x314C, "M", "ᄐ"), + (0x314D, "M", "ᄑ"), + (0x314E, "M", "ᄒ"), + (0x314F, "M", "ᅡ"), + (0x3150, "M", "ᅢ"), + (0x3151, "M", "ᅣ"), + (0x3152, "M", "ᅤ"), + (0x3153, "M", "ᅥ"), + (0x3154, "M", "ᅦ"), + (0x3155, "M", "ᅧ"), + (0x3156, "M", "ᅨ"), + (0x3157, "M", "ᅩ"), + (0x3158, "M", "ᅪ"), + (0x3159, "M", "ᅫ"), + (0x315A, "M", "ᅬ"), + (0x315B, "M", "ᅭ"), + (0x315C, "M", "ᅮ"), + (0x315D, "M", "ᅯ"), + (0x315E, "M", "ᅰ"), + (0x315F, "M", "ᅱ"), + (0x3160, "M", "ᅲ"), + (0x3161, "M", "ᅳ"), + (0x3162, "M", "ᅴ"), + (0x3163, "M", "ᅵ"), + (0x3164, "I"), + (0x3165, "M", "ᄔ"), + (0x3166, "M", "ᄕ"), + (0x3167, "M", "ᇇ"), + (0x3168, "M", "ᇈ"), + (0x3169, "M", "ᇌ"), + (0x316A, "M", "ᇎ"), + (0x316B, "M", "ᇓ"), + (0x316C, "M", "ᇗ"), + (0x316D, "M", "ᇙ"), + (0x316E, "M", "ᄜ"), + (0x316F, "M", "ᇝ"), + (0x3170, "M", "ᇟ"), + (0x3171, "M", "ᄝ"), + (0x3172, "M", "ᄞ"), + (0x3173, "M", "ᄠ"), + (0x3174, "M", "ᄢ"), + (0x3175, "M", "ᄣ"), + (0x3176, "M", "ᄧ"), + (0x3177, "M", "ᄩ"), + (0x3178, "M", "ᄫ"), + (0x3179, "M", "ᄬ"), + (0x317A, "M", "ᄭ"), + (0x317B, "M", "ᄮ"), + (0x317C, "M", "ᄯ"), + (0x317D, "M", "ᄲ"), + (0x317E, "M", "ᄶ"), + (0x317F, "M", "ᅀ"), + (0x3180, "M", "ᅇ"), + (0x3181, "M", "ᅌ"), + (0x3182, "M", "ᇱ"), + (0x3183, "M", "ᇲ"), + (0x3184, "M", "ᅗ"), + (0x3185, "M", "ᅘ"), + (0x3186, "M", "ᅙ"), + (0x3187, "M", "ᆄ"), + (0x3188, "M", "ᆅ"), + (0x3189, "M", "ᆈ"), + (0x318A, "M", "ᆑ"), + (0x318B, "M", "ᆒ"), + (0x318C, "M", "ᆔ"), + (0x318D, "M", "ᆞ"), + (0x318E, "M", "ᆡ"), + (0x318F, "X"), + (0x3190, "V"), + (0x3192, "M", "一"), + (0x3193, "M", "二"), + (0x3194, "M", "三"), + (0x3195, "M", "四"), + (0x3196, "M", "上"), + (0x3197, "M", "中"), + (0x3198, "M", "下"), + (0x3199, "M", "甲"), + (0x319A, "M", "乙"), + (0x319B, "M", "丙"), + (0x319C, "M", "丁"), + (0x319D, "M", "天"), + (0x319E, "M", "地"), + (0x319F, "M", "人"), + (0x31A0, "V"), + (0x31E6, "X"), + (0x31F0, "V"), + (0x3200, "M", "(ᄀ)"), + (0x3201, "M", "(ᄂ)"), + (0x3202, "M", "(ᄃ)"), + (0x3203, "M", "(ᄅ)"), + (0x3204, "M", "(ᄆ)"), + (0x3205, "M", "(ᄇ)"), + (0x3206, "M", "(ᄉ)"), + (0x3207, "M", "(ᄋ)"), + (0x3208, "M", "(ᄌ)"), + (0x3209, "M", "(ᄎ)"), + (0x320A, "M", "(ᄏ)"), + (0x320B, "M", "(ᄐ)"), + (0x320C, "M", "(ᄑ)"), + (0x320D, "M", "(ᄒ)"), + (0x320E, "M", "(가)"), + (0x320F, "M", "(나)"), + (0x3210, "M", "(다)"), + (0x3211, "M", "(라)"), + (0x3212, "M", "(마)"), + (0x3213, "M", "(바)"), + (0x3214, "M", "(사)"), + (0x3215, "M", "(아)"), + (0x3216, "M", "(자)"), + (0x3217, "M", "(차)"), + (0x3218, "M", "(카)"), + (0x3219, "M", "(타)"), + (0x321A, "M", "(파)"), + (0x321B, "M", "(하)"), + (0x321C, "M", "(주)"), + (0x321D, "M", "(오전)"), + (0x321E, "M", "(오후)"), + (0x321F, "X"), + (0x3220, "M", "(一)"), + (0x3221, "M", "(二)"), + (0x3222, "M", "(三)"), + (0x3223, "M", "(四)"), + (0x3224, "M", "(五)"), + (0x3225, "M", "(六)"), + (0x3226, "M", "(七)"), + (0x3227, "M", "(八)"), + (0x3228, "M", "(九)"), + (0x3229, "M", "(十)"), + (0x322A, "M", "(月)"), + (0x322B, "M", "(火)"), + (0x322C, "M", "(水)"), + (0x322D, "M", "(木)"), + (0x322E, "M", "(金)"), + (0x322F, "M", "(土)"), + (0x3230, "M", "(日)"), + (0x3231, "M", "(株)"), + (0x3232, "M", "(有)"), + (0x3233, "M", "(社)"), + (0x3234, "M", "(名)"), + (0x3235, "M", "(特)"), + (0x3236, "M", "(財)"), + (0x3237, "M", "(祝)"), + (0x3238, "M", "(労)"), + (0x3239, "M", "(代)"), + (0x323A, "M", "(呼)"), + (0x323B, "M", "(学)"), + (0x323C, "M", "(監)"), + (0x323D, "M", "(企)"), + (0x323E, "M", "(資)"), + (0x323F, "M", "(協)"), + (0x3240, "M", "(祭)"), + (0x3241, "M", "(休)"), + (0x3242, "M", "(自)"), + (0x3243, "M", "(至)"), + (0x3244, "M", "問"), + (0x3245, "M", "幼"), + (0x3246, "M", "文"), + (0x3247, "M", "箏"), + (0x3248, "V"), + (0x3250, "M", "pte"), + (0x3251, "M", "21"), + (0x3252, "M", "22"), + (0x3253, "M", "23"), + (0x3254, "M", "24"), + (0x3255, "M", "25"), + (0x3256, "M", "26"), + (0x3257, "M", "27"), + (0x3258, "M", "28"), + (0x3259, "M", "29"), + (0x325A, "M", "30"), + (0x325B, "M", "31"), + (0x325C, "M", "32"), + (0x325D, "M", "33"), + (0x325E, "M", "34"), + (0x325F, "M", "35"), + (0x3260, "M", "ᄀ"), + (0x3261, "M", "ᄂ"), + (0x3262, "M", "ᄃ"), + (0x3263, "M", "ᄅ"), + (0x3264, "M", "ᄆ"), + (0x3265, "M", "ᄇ"), + (0x3266, "M", "ᄉ"), + (0x3267, "M", "ᄋ"), + (0x3268, "M", "ᄌ"), + (0x3269, "M", "ᄎ"), + (0x326A, "M", "ᄏ"), + (0x326B, "M", "ᄐ"), + (0x326C, "M", "ᄑ"), + (0x326D, "M", "ᄒ"), + (0x326E, "M", "가"), + (0x326F, "M", "나"), + (0x3270, "M", "다"), + (0x3271, "M", "라"), + (0x3272, "M", "마"), + (0x3273, "M", "바"), + (0x3274, "M", "사"), + (0x3275, "M", "아"), + (0x3276, "M", "자"), + (0x3277, "M", "차"), + (0x3278, "M", "카"), + (0x3279, "M", "타"), + (0x327A, "M", "파"), + (0x327B, "M", "하"), + (0x327C, "M", "참고"), + (0x327D, "M", "주의"), + (0x327E, "M", "우"), + (0x327F, "V"), + (0x3280, "M", "一"), + (0x3281, "M", "二"), + (0x3282, "M", "三"), + (0x3283, "M", "四"), + (0x3284, "M", "五"), + (0x3285, "M", "六"), + (0x3286, "M", "七"), + (0x3287, "M", "八"), + (0x3288, "M", "九"), + (0x3289, "M", "十"), + (0x328A, "M", "月"), + (0x328B, "M", "火"), + (0x328C, "M", "水"), + (0x328D, "M", "木"), + (0x328E, "M", "金"), + (0x328F, "M", "土"), + (0x3290, "M", "日"), + (0x3291, "M", "株"), + (0x3292, "M", "有"), + (0x3293, "M", "社"), + (0x3294, "M", "名"), + (0x3295, "M", "特"), + (0x3296, "M", "財"), + (0x3297, "M", "祝"), + (0x3298, "M", "労"), + (0x3299, "M", "秘"), + (0x329A, "M", "男"), + (0x329B, "M", "女"), + (0x329C, "M", "適"), + (0x329D, "M", "優"), + (0x329E, "M", "印"), + (0x329F, "M", "注"), + (0x32A0, "M", "項"), + (0x32A1, "M", "休"), + (0x32A2, "M", "写"), + (0x32A3, "M", "正"), + (0x32A4, "M", "上"), + (0x32A5, "M", "中"), + (0x32A6, "M", "下"), + (0x32A7, "M", "左"), + (0x32A8, "M", "右"), + (0x32A9, "M", "医"), + (0x32AA, "M", "宗"), + (0x32AB, "M", "学"), + (0x32AC, "M", "監"), + (0x32AD, "M", "企"), + (0x32AE, "M", "資"), + (0x32AF, "M", "協"), + (0x32B0, "M", "夜"), + (0x32B1, "M", "36"), + (0x32B2, "M", "37"), + (0x32B3, "M", "38"), + (0x32B4, "M", "39"), + (0x32B5, "M", "40"), + (0x32B6, "M", "41"), + (0x32B7, "M", "42"), + (0x32B8, "M", "43"), + (0x32B9, "M", "44"), + (0x32BA, "M", "45"), + (0x32BB, "M", "46"), + (0x32BC, "M", "47"), + (0x32BD, "M", "48"), + (0x32BE, "M", "49"), + (0x32BF, "M", "50"), + (0x32C0, "M", "1月"), + (0x32C1, "M", "2月"), + (0x32C2, "M", "3月"), + (0x32C3, "M", "4月"), + (0x32C4, "M", "5月"), + (0x32C5, "M", "6月"), + (0x32C6, "M", "7月"), + (0x32C7, "M", "8月"), + (0x32C8, "M", "9月"), + (0x32C9, "M", "10月"), + (0x32CA, "M", "11月"), + (0x32CB, "M", "12月"), + (0x32CC, "M", "hg"), + (0x32CD, "M", "erg"), + (0x32CE, "M", "ev"), + (0x32CF, "M", "ltd"), + (0x32D0, "M", "ア"), + (0x32D1, "M", "イ"), + (0x32D2, "M", "ウ"), + (0x32D3, "M", "エ"), + (0x32D4, "M", "オ"), + (0x32D5, "M", "カ"), + (0x32D6, "M", "キ"), + (0x32D7, "M", "ク"), + (0x32D8, "M", "ケ"), + (0x32D9, "M", "コ"), + (0x32DA, "M", "サ"), + (0x32DB, "M", "シ"), + (0x32DC, "M", "ス"), + (0x32DD, "M", "セ"), + (0x32DE, "M", "ソ"), + (0x32DF, "M", "タ"), + (0x32E0, "M", "チ"), + (0x32E1, "M", "ツ"), + (0x32E2, "M", "テ"), + (0x32E3, "M", "ト"), + (0x32E4, "M", "ナ"), + (0x32E5, "M", "ニ"), + (0x32E6, "M", "ヌ"), + (0x32E7, "M", "ネ"), + (0x32E8, "M", "ノ"), + (0x32E9, "M", "ハ"), + (0x32EA, "M", "ヒ"), + (0x32EB, "M", "フ"), + (0x32EC, "M", "ヘ"), + (0x32ED, "M", "ホ"), + (0x32EE, "M", "マ"), + (0x32EF, "M", "ミ"), + (0x32F0, "M", "ム"), + (0x32F1, "M", "メ"), + (0x32F2, "M", "モ"), + (0x32F3, "M", "ヤ"), + (0x32F4, "M", "ユ"), + (0x32F5, "M", "ヨ"), + (0x32F6, "M", "ラ"), + (0x32F7, "M", "リ"), + (0x32F8, "M", "ル"), + (0x32F9, "M", "レ"), + (0x32FA, "M", "ロ"), + (0x32FB, "M", "ワ"), + (0x32FC, "M", "ヰ"), + (0x32FD, "M", "ヱ"), + (0x32FE, "M", "ヲ"), + (0x32FF, "M", "令和"), + (0x3300, "M", "アパート"), + (0x3301, "M", "アルファ"), + (0x3302, "M", "アンペア"), + (0x3303, "M", "アール"), + (0x3304, "M", "イニング"), + (0x3305, "M", "インチ"), + (0x3306, "M", "ウォン"), + (0x3307, "M", "エスクード"), + (0x3308, "M", "エーカー"), + (0x3309, "M", "オンス"), + (0x330A, "M", "オーム"), + (0x330B, "M", "カイリ"), + (0x330C, "M", "カラット"), + (0x330D, "M", "カロリー"), + (0x330E, "M", "ガロン"), + (0x330F, "M", "ガンマ"), + (0x3310, "M", "ギガ"), + (0x3311, "M", "ギニー"), + (0x3312, "M", "キュリー"), + (0x3313, "M", "ギルダー"), + (0x3314, "M", "キロ"), + (0x3315, "M", "キログラム"), + (0x3316, "M", "キロメートル"), + (0x3317, "M", "キロワット"), + (0x3318, "M", "グラム"), + (0x3319, "M", "グラムトン"), + (0x331A, "M", "クルゼイロ"), + (0x331B, "M", "クローネ"), + (0x331C, "M", "ケース"), + (0x331D, "M", "コルナ"), + (0x331E, "M", "コーポ"), + (0x331F, "M", "サイクル"), + (0x3320, "M", "サンチーム"), + (0x3321, "M", "シリング"), + (0x3322, "M", "センチ"), + (0x3323, "M", "セント"), + (0x3324, "M", "ダース"), + (0x3325, "M", "デシ"), + (0x3326, "M", "ドル"), + (0x3327, "M", "トン"), + (0x3328, "M", "ナノ"), + (0x3329, "M", "ノット"), + (0x332A, "M", "ハイツ"), + (0x332B, "M", "パーセント"), + (0x332C, "M", "パーツ"), + (0x332D, "M", "バーレル"), + (0x332E, "M", "ピアストル"), + (0x332F, "M", "ピクル"), + (0x3330, "M", "ピコ"), + (0x3331, "M", "ビル"), + (0x3332, "M", "ファラッド"), + (0x3333, "M", "フィート"), + (0x3334, "M", "ブッシェル"), + (0x3335, "M", "フラン"), + (0x3336, "M", "ヘクタール"), + (0x3337, "M", "ペソ"), + (0x3338, "M", "ペニヒ"), + (0x3339, "M", "ヘルツ"), + (0x333A, "M", "ペンス"), + (0x333B, "M", "ページ"), + (0x333C, "M", "ベータ"), + (0x333D, "M", "ポイント"), + (0x333E, "M", "ボルト"), + (0x333F, "M", "ホン"), + (0x3340, "M", "ポンド"), + (0x3341, "M", "ホール"), + (0x3342, "M", "ホーン"), + (0x3343, "M", "マイクロ"), + (0x3344, "M", "マイル"), + (0x3345, "M", "マッハ"), + (0x3346, "M", "マルク"), + (0x3347, "M", "マンション"), + (0x3348, "M", "ミクロン"), + (0x3349, "M", "ミリ"), + (0x334A, "M", "ミリバール"), + (0x334B, "M", "メガ"), + (0x334C, "M", "メガトン"), + (0x334D, "M", "メートル"), + (0x334E, "M", "ヤード"), + (0x334F, "M", "ヤール"), + (0x3350, "M", "ユアン"), + (0x3351, "M", "リットル"), + (0x3352, "M", "リラ"), + (0x3353, "M", "ルピー"), + (0x3354, "M", "ルーブル"), + (0x3355, "M", "レム"), + (0x3356, "M", "レントゲン"), + (0x3357, "M", "ワット"), + (0x3358, "M", "0点"), + (0x3359, "M", "1点"), + (0x335A, "M", "2点"), + (0x335B, "M", "3点"), + (0x335C, "M", "4点"), + (0x335D, "M", "5点"), + (0x335E, "M", "6点"), + (0x335F, "M", "7点"), + (0x3360, "M", "8点"), + (0x3361, "M", "9点"), + (0x3362, "M", "10点"), + (0x3363, "M", "11点"), + (0x3364, "M", "12点"), + (0x3365, "M", "13点"), + (0x3366, "M", "14点"), + (0x3367, "M", "15点"), + (0x3368, "M", "16点"), + (0x3369, "M", "17点"), + (0x336A, "M", "18点"), + (0x336B, "M", "19点"), + (0x336C, "M", "20点"), + (0x336D, "M", "21点"), + (0x336E, "M", "22点"), + (0x336F, "M", "23点"), + (0x3370, "M", "24点"), + (0x3371, "M", "hpa"), + (0x3372, "M", "da"), + (0x3373, "M", "au"), + (0x3374, "M", "bar"), + (0x3375, "M", "ov"), + (0x3376, "M", "pc"), + (0x3377, "M", "dm"), + (0x3378, "M", "dm2"), + (0x3379, "M", "dm3"), + (0x337A, "M", "iu"), + (0x337B, "M", "平成"), + (0x337C, "M", "昭和"), + (0x337D, "M", "大正"), + (0x337E, "M", "明治"), + (0x337F, "M", "株式会社"), + (0x3380, "M", "pa"), + (0x3381, "M", "na"), + (0x3382, "M", "μa"), + (0x3383, "M", "ma"), + (0x3384, "M", "ka"), + (0x3385, "M", "kb"), + (0x3386, "M", "mb"), + (0x3387, "M", "gb"), + (0x3388, "M", "cal"), + (0x3389, "M", "kcal"), + (0x338A, "M", "pf"), + (0x338B, "M", "nf"), + (0x338C, "M", "μf"), + (0x338D, "M", "μg"), + (0x338E, "M", "mg"), + (0x338F, "M", "kg"), + (0x3390, "M", "hz"), + (0x3391, "M", "khz"), + (0x3392, "M", "mhz"), + (0x3393, "M", "ghz"), + (0x3394, "M", "thz"), + (0x3395, "M", "μl"), + (0x3396, "M", "ml"), + (0x3397, "M", "dl"), + (0x3398, "M", "kl"), + (0x3399, "M", "fm"), + (0x339A, "M", "nm"), + (0x339B, "M", "μm"), + (0x339C, "M", "mm"), + (0x339D, "M", "cm"), + (0x339E, "M", "km"), + (0x339F, "M", "mm2"), + (0x33A0, "M", "cm2"), + (0x33A1, "M", "m2"), + (0x33A2, "M", "km2"), + (0x33A3, "M", "mm3"), + (0x33A4, "M", "cm3"), + (0x33A5, "M", "m3"), + (0x33A6, "M", "km3"), + (0x33A7, "M", "m∕s"), + (0x33A8, "M", "m∕s2"), + (0x33A9, "M", "pa"), + (0x33AA, "M", "kpa"), + (0x33AB, "M", "mpa"), + (0x33AC, "M", "gpa"), + (0x33AD, "M", "rad"), + (0x33AE, "M", "rad∕s"), + (0x33AF, "M", "rad∕s2"), + (0x33B0, "M", "ps"), + (0x33B1, "M", "ns"), + (0x33B2, "M", "μs"), + (0x33B3, "M", "ms"), + (0x33B4, "M", "pv"), + (0x33B5, "M", "nv"), + (0x33B6, "M", "μv"), + (0x33B7, "M", "mv"), + (0x33B8, "M", "kv"), + (0x33B9, "M", "mv"), + (0x33BA, "M", "pw"), + (0x33BB, "M", "nw"), + (0x33BC, "M", "μw"), + (0x33BD, "M", "mw"), + (0x33BE, "M", "kw"), + (0x33BF, "M", "mw"), + (0x33C0, "M", "kω"), + (0x33C1, "M", "mω"), + (0x33C2, "X"), + (0x33C3, "M", "bq"), + (0x33C4, "M", "cc"), + (0x33C5, "M", "cd"), + (0x33C6, "M", "c∕kg"), + (0x33C7, "X"), + (0x33C8, "M", "db"), + (0x33C9, "M", "gy"), + (0x33CA, "M", "ha"), + (0x33CB, "M", "hp"), + (0x33CC, "M", "in"), + (0x33CD, "M", "kk"), + (0x33CE, "M", "km"), + (0x33CF, "M", "kt"), + (0x33D0, "M", "lm"), + (0x33D1, "M", "ln"), + (0x33D2, "M", "log"), + (0x33D3, "M", "lx"), + (0x33D4, "M", "mb"), + (0x33D5, "M", "mil"), + (0x33D6, "M", "mol"), + (0x33D7, "M", "ph"), + (0x33D8, "X"), + (0x33D9, "M", "ppm"), + (0x33DA, "M", "pr"), + (0x33DB, "M", "sr"), + (0x33DC, "M", "sv"), + (0x33DD, "M", "wb"), + (0x33DE, "M", "v∕m"), + (0x33DF, "M", "a∕m"), + (0x33E0, "M", "1日"), + (0x33E1, "M", "2日"), + (0x33E2, "M", "3日"), + (0x33E3, "M", "4日"), + (0x33E4, "M", "5日"), + (0x33E5, "M", "6日"), + (0x33E6, "M", "7日"), + (0x33E7, "M", "8日"), + (0x33E8, "M", "9日"), + (0x33E9, "M", "10日"), + (0x33EA, "M", "11日"), + (0x33EB, "M", "12日"), + (0x33EC, "M", "13日"), + (0x33ED, "M", "14日"), + (0x33EE, "M", "15日"), + (0x33EF, "M", "16日"), + (0x33F0, "M", "17日"), + (0x33F1, "M", "18日"), + (0x33F2, "M", "19日"), + (0x33F3, "M", "20日"), + (0x33F4, "M", "21日"), + (0x33F5, "M", "22日"), + (0x33F6, "M", "23日"), + (0x33F7, "M", "24日"), + (0x33F8, "M", "25日"), + (0x33F9, "M", "26日"), + (0x33FA, "M", "27日"), + (0x33FB, "M", "28日"), + (0x33FC, "M", "29日"), + (0x33FD, "M", "30日"), + (0x33FE, "M", "31日"), + (0x33FF, "M", "gal"), + (0x3400, "V"), + (0xA48D, "X"), + (0xA490, "V"), + (0xA4C7, "X"), + (0xA4D0, "V"), + (0xA62C, "X"), + (0xA640, "M", "ꙁ"), + (0xA641, "V"), + (0xA642, "M", "ꙃ"), + (0xA643, "V"), + (0xA644, "M", "ꙅ"), + (0xA645, "V"), + (0xA646, "M", "ꙇ"), + (0xA647, "V"), + (0xA648, "M", "ꙉ"), + (0xA649, "V"), + (0xA64A, "M", "ꙋ"), + (0xA64B, "V"), + (0xA64C, "M", "ꙍ"), + (0xA64D, "V"), + (0xA64E, "M", "ꙏ"), + (0xA64F, "V"), + (0xA650, "M", "ꙑ"), + (0xA651, "V"), + (0xA652, "M", "ꙓ"), + (0xA653, "V"), + (0xA654, "M", "ꙕ"), + (0xA655, "V"), + (0xA656, "M", "ꙗ"), + (0xA657, "V"), + (0xA658, "M", "ꙙ"), + (0xA659, "V"), + (0xA65A, "M", "ꙛ"), + (0xA65B, "V"), + (0xA65C, "M", "ꙝ"), + (0xA65D, "V"), + (0xA65E, "M", "ꙟ"), + (0xA65F, "V"), + (0xA660, "M", "ꙡ"), + (0xA661, "V"), + (0xA662, "M", "ꙣ"), + (0xA663, "V"), + (0xA664, "M", "ꙥ"), + (0xA665, "V"), + (0xA666, "M", "ꙧ"), + (0xA667, "V"), + (0xA668, "M", "ꙩ"), + (0xA669, "V"), + (0xA66A, "M", "ꙫ"), + (0xA66B, "V"), + (0xA66C, "M", "ꙭ"), + (0xA66D, "V"), + (0xA680, "M", "ꚁ"), + (0xA681, "V"), + (0xA682, "M", "ꚃ"), + (0xA683, "V"), + (0xA684, "M", "ꚅ"), + (0xA685, "V"), + (0xA686, "M", "ꚇ"), + (0xA687, "V"), + (0xA688, "M", "ꚉ"), + (0xA689, "V"), + (0xA68A, "M", "ꚋ"), + (0xA68B, "V"), + (0xA68C, "M", "ꚍ"), + (0xA68D, "V"), + (0xA68E, "M", "ꚏ"), + (0xA68F, "V"), + (0xA690, "M", "ꚑ"), + (0xA691, "V"), + (0xA692, "M", "ꚓ"), + (0xA693, "V"), + (0xA694, "M", "ꚕ"), + (0xA695, "V"), + (0xA696, "M", "ꚗ"), + (0xA697, "V"), + (0xA698, "M", "ꚙ"), + (0xA699, "V"), + (0xA69A, "M", "ꚛ"), + (0xA69B, "V"), + (0xA69C, "M", "ъ"), + (0xA69D, "M", "ь"), + (0xA69E, "V"), + (0xA6F8, "X"), + (0xA700, "V"), + (0xA722, "M", "ꜣ"), + (0xA723, "V"), + (0xA724, "M", "ꜥ"), + (0xA725, "V"), + (0xA726, "M", "ꜧ"), + (0xA727, "V"), + (0xA728, "M", "ꜩ"), + (0xA729, "V"), + (0xA72A, "M", "ꜫ"), + (0xA72B, "V"), + (0xA72C, "M", "ꜭ"), + (0xA72D, "V"), + (0xA72E, "M", "ꜯ"), + (0xA72F, "V"), + (0xA732, "M", "ꜳ"), + (0xA733, "V"), + (0xA734, "M", "ꜵ"), + (0xA735, "V"), + (0xA736, "M", "ꜷ"), + (0xA737, "V"), + (0xA738, "M", "ꜹ"), + (0xA739, "V"), + (0xA73A, "M", "ꜻ"), + (0xA73B, "V"), + (0xA73C, "M", "ꜽ"), + (0xA73D, "V"), + (0xA73E, "M", "ꜿ"), + (0xA73F, "V"), + (0xA740, "M", "ꝁ"), + (0xA741, "V"), + (0xA742, "M", "ꝃ"), + (0xA743, "V"), + (0xA744, "M", "ꝅ"), + (0xA745, "V"), + (0xA746, "M", "ꝇ"), + (0xA747, "V"), + (0xA748, "M", "ꝉ"), + (0xA749, "V"), + (0xA74A, "M", "ꝋ"), + (0xA74B, "V"), + (0xA74C, "M", "ꝍ"), + (0xA74D, "V"), + (0xA74E, "M", "ꝏ"), + (0xA74F, "V"), + (0xA750, "M", "ꝑ"), + (0xA751, "V"), + (0xA752, "M", "ꝓ"), + (0xA753, "V"), + (0xA754, "M", "ꝕ"), + (0xA755, "V"), + (0xA756, "M", "ꝗ"), + (0xA757, "V"), + (0xA758, "M", "ꝙ"), + (0xA759, "V"), + (0xA75A, "M", "ꝛ"), + (0xA75B, "V"), + (0xA75C, "M", "ꝝ"), + (0xA75D, "V"), + (0xA75E, "M", "ꝟ"), + (0xA75F, "V"), + (0xA760, "M", "ꝡ"), + (0xA761, "V"), + (0xA762, "M", "ꝣ"), + (0xA763, "V"), + (0xA764, "M", "ꝥ"), + (0xA765, "V"), + (0xA766, "M", "ꝧ"), + (0xA767, "V"), + (0xA768, "M", "ꝩ"), + (0xA769, "V"), + (0xA76A, "M", "ꝫ"), + (0xA76B, "V"), + (0xA76C, "M", "ꝭ"), + (0xA76D, "V"), + (0xA76E, "M", "ꝯ"), + (0xA76F, "V"), + (0xA770, "M", "ꝯ"), + (0xA771, "V"), + (0xA779, "M", "ꝺ"), + (0xA77A, "V"), + (0xA77B, "M", "ꝼ"), + (0xA77C, "V"), + (0xA77D, "M", "ᵹ"), + (0xA77E, "M", "ꝿ"), + (0xA77F, "V"), + (0xA780, "M", "ꞁ"), + (0xA781, "V"), + (0xA782, "M", "ꞃ"), + (0xA783, "V"), + (0xA784, "M", "ꞅ"), + (0xA785, "V"), + (0xA786, "M", "ꞇ"), + (0xA787, "V"), + (0xA78B, "M", "ꞌ"), + (0xA78C, "V"), + (0xA78D, "M", "ɥ"), + (0xA78E, "V"), + (0xA790, "M", "ꞑ"), + (0xA791, "V"), + (0xA792, "M", "ꞓ"), + (0xA793, "V"), + (0xA796, "M", "ꞗ"), + (0xA797, "V"), + (0xA798, "M", "ꞙ"), + (0xA799, "V"), + (0xA79A, "M", "ꞛ"), + (0xA79B, "V"), + (0xA79C, "M", "ꞝ"), + (0xA79D, "V"), + (0xA79E, "M", "ꞟ"), + (0xA79F, "V"), + (0xA7A0, "M", "ꞡ"), + (0xA7A1, "V"), + (0xA7A2, "M", "ꞣ"), + (0xA7A3, "V"), + (0xA7A4, "M", "ꞥ"), + (0xA7A5, "V"), + (0xA7A6, "M", "ꞧ"), + (0xA7A7, "V"), + (0xA7A8, "M", "ꞩ"), + (0xA7A9, "V"), + (0xA7AA, "M", "ɦ"), + (0xA7AB, "M", "ɜ"), + (0xA7AC, "M", "ɡ"), + (0xA7AD, "M", "ɬ"), + (0xA7AE, "M", "ɪ"), + (0xA7AF, "V"), + (0xA7B0, "M", "ʞ"), + (0xA7B1, "M", "ʇ"), + (0xA7B2, "M", "ʝ"), + (0xA7B3, "M", "ꭓ"), + (0xA7B4, "M", "ꞵ"), + (0xA7B5, "V"), + (0xA7B6, "M", "ꞷ"), + (0xA7B7, "V"), + (0xA7B8, "M", "ꞹ"), + (0xA7B9, "V"), + (0xA7BA, "M", "ꞻ"), + (0xA7BB, "V"), + (0xA7BC, "M", "ꞽ"), + (0xA7BD, "V"), + (0xA7BE, "M", "ꞿ"), + (0xA7BF, "V"), + (0xA7C0, "M", "ꟁ"), + (0xA7C1, "V"), + (0xA7C2, "M", "ꟃ"), + (0xA7C3, "V"), + (0xA7C4, "M", "ꞔ"), + (0xA7C5, "M", "ʂ"), + (0xA7C6, "M", "ᶎ"), + (0xA7C7, "M", "ꟈ"), + (0xA7C8, "V"), + (0xA7C9, "M", "ꟊ"), + (0xA7CA, "V"), + (0xA7CB, "M", "ɤ"), + (0xA7CC, "M", "ꟍ"), + (0xA7CD, "V"), + (0xA7CE, "M", "꟏"), + (0xA7CF, "V"), + (0xA7D0, "M", "ꟑ"), + (0xA7D1, "V"), + (0xA7D2, "M", "ꟓ"), + (0xA7D3, "V"), + (0xA7D4, "M", "ꟕ"), + (0xA7D5, "V"), + (0xA7D6, "M", "ꟗ"), + (0xA7D7, "V"), + (0xA7D8, "M", "ꟙ"), + (0xA7D9, "V"), + (0xA7DA, "M", "ꟛ"), + (0xA7DB, "V"), + (0xA7DC, "M", "ƛ"), + (0xA7DD, "X"), + (0xA7F1, "M", "s"), + (0xA7F2, "M", "c"), + (0xA7F3, "M", "f"), + (0xA7F4, "M", "q"), + (0xA7F5, "M", "ꟶ"), + (0xA7F6, "V"), + (0xA7F8, "M", "ħ"), + (0xA7F9, "M", "œ"), + (0xA7FA, "V"), + (0xA82D, "X"), + (0xA830, "V"), + (0xA83A, "X"), + (0xA840, "V"), + (0xA878, "X"), + (0xA880, "V"), + (0xA8C6, "X"), + (0xA8CE, "V"), + (0xA8DA, "X"), + (0xA8E0, "V"), + (0xA954, "X"), + (0xA95F, "V"), + (0xA97D, "X"), + (0xA980, "V"), + (0xA9CE, "X"), + (0xA9CF, "V"), + (0xA9DA, "X"), + (0xA9DE, "V"), + (0xA9FF, "X"), + (0xAA00, "V"), + (0xAA37, "X"), + (0xAA40, "V"), + (0xAA4E, "X"), + (0xAA50, "V"), + (0xAA5A, "X"), + (0xAA5C, "V"), + (0xAAC3, "X"), + (0xAADB, "V"), + (0xAAF7, "X"), + (0xAB01, "V"), + (0xAB07, "X"), + (0xAB09, "V"), + (0xAB0F, "X"), + (0xAB11, "V"), + (0xAB17, "X"), + (0xAB20, "V"), + (0xAB27, "X"), + (0xAB28, "V"), + (0xAB2F, "X"), + (0xAB30, "V"), + (0xAB5C, "M", "ꜧ"), + (0xAB5D, "M", "ꬷ"), + (0xAB5E, "M", "ɫ"), + (0xAB5F, "M", "ꭒ"), + (0xAB60, "V"), + (0xAB69, "M", "ʍ"), + (0xAB6A, "V"), + (0xAB6C, "X"), + (0xAB70, "M", "Ꭰ"), + (0xAB71, "M", "Ꭱ"), + (0xAB72, "M", "Ꭲ"), + (0xAB73, "M", "Ꭳ"), + (0xAB74, "M", "Ꭴ"), + (0xAB75, "M", "Ꭵ"), + (0xAB76, "M", "Ꭶ"), + (0xAB77, "M", "Ꭷ"), + (0xAB78, "M", "Ꭸ"), + (0xAB79, "M", "Ꭹ"), + (0xAB7A, "M", "Ꭺ"), + (0xAB7B, "M", "Ꭻ"), + (0xAB7C, "M", "Ꭼ"), + (0xAB7D, "M", "Ꭽ"), + (0xAB7E, "M", "Ꭾ"), + (0xAB7F, "M", "Ꭿ"), + (0xAB80, "M", "Ꮀ"), + (0xAB81, "M", "Ꮁ"), + (0xAB82, "M", "Ꮂ"), + (0xAB83, "M", "Ꮃ"), + (0xAB84, "M", "Ꮄ"), + (0xAB85, "M", "Ꮅ"), + (0xAB86, "M", "Ꮆ"), + (0xAB87, "M", "Ꮇ"), + (0xAB88, "M", "Ꮈ"), + (0xAB89, "M", "Ꮉ"), + (0xAB8A, "M", "Ꮊ"), + (0xAB8B, "M", "Ꮋ"), + (0xAB8C, "M", "Ꮌ"), + (0xAB8D, "M", "Ꮍ"), + (0xAB8E, "M", "Ꮎ"), + (0xAB8F, "M", "Ꮏ"), + (0xAB90, "M", "Ꮐ"), + (0xAB91, "M", "Ꮑ"), + (0xAB92, "M", "Ꮒ"), + (0xAB93, "M", "Ꮓ"), + (0xAB94, "M", "Ꮔ"), + (0xAB95, "M", "Ꮕ"), + (0xAB96, "M", "Ꮖ"), + (0xAB97, "M", "Ꮗ"), + (0xAB98, "M", "Ꮘ"), + (0xAB99, "M", "Ꮙ"), + (0xAB9A, "M", "Ꮚ"), + (0xAB9B, "M", "Ꮛ"), + (0xAB9C, "M", "Ꮜ"), + (0xAB9D, "M", "Ꮝ"), + (0xAB9E, "M", "Ꮞ"), + (0xAB9F, "M", "Ꮟ"), + (0xABA0, "M", "Ꮠ"), + (0xABA1, "M", "Ꮡ"), + (0xABA2, "M", "Ꮢ"), + (0xABA3, "M", "Ꮣ"), + (0xABA4, "M", "Ꮤ"), + (0xABA5, "M", "Ꮥ"), + (0xABA6, "M", "Ꮦ"), + (0xABA7, "M", "Ꮧ"), + (0xABA8, "M", "Ꮨ"), + (0xABA9, "M", "Ꮩ"), + (0xABAA, "M", "Ꮪ"), + (0xABAB, "M", "Ꮫ"), + (0xABAC, "M", "Ꮬ"), + (0xABAD, "M", "Ꮭ"), + (0xABAE, "M", "Ꮮ"), + (0xABAF, "M", "Ꮯ"), + (0xABB0, "M", "Ꮰ"), + (0xABB1, "M", "Ꮱ"), + (0xABB2, "M", "Ꮲ"), + (0xABB3, "M", "Ꮳ"), + (0xABB4, "M", "Ꮴ"), + (0xABB5, "M", "Ꮵ"), + (0xABB6, "M", "Ꮶ"), + (0xABB7, "M", "Ꮷ"), + (0xABB8, "M", "Ꮸ"), + (0xABB9, "M", "Ꮹ"), + (0xABBA, "M", "Ꮺ"), + (0xABBB, "M", "Ꮻ"), + (0xABBC, "M", "Ꮼ"), + (0xABBD, "M", "Ꮽ"), + (0xABBE, "M", "Ꮾ"), + (0xABBF, "M", "Ꮿ"), + (0xABC0, "V"), + (0xABEE, "X"), + (0xABF0, "V"), + (0xABFA, "X"), + (0xAC00, "V"), + (0xD7A4, "X"), + (0xD7B0, "V"), + (0xD7C7, "X"), + (0xD7CB, "V"), + (0xD7FC, "X"), + (0xF900, "M", "豈"), + (0xF901, "M", "更"), + (0xF902, "M", "車"), + (0xF903, "M", "賈"), + (0xF904, "M", "滑"), + (0xF905, "M", "串"), + (0xF906, "M", "句"), + (0xF907, "M", "龜"), + (0xF909, "M", "契"), + (0xF90A, "M", "金"), + (0xF90B, "M", "喇"), + (0xF90C, "M", "奈"), + (0xF90D, "M", "懶"), + (0xF90E, "M", "癩"), + (0xF90F, "M", "羅"), + (0xF910, "M", "蘿"), + (0xF911, "M", "螺"), + (0xF912, "M", "裸"), + (0xF913, "M", "邏"), + (0xF914, "M", "樂"), + (0xF915, "M", "洛"), + (0xF916, "M", "烙"), + (0xF917, "M", "珞"), + (0xF918, "M", "落"), + (0xF919, "M", "酪"), + (0xF91A, "M", "駱"), + (0xF91B, "M", "亂"), + (0xF91C, "M", "卵"), + (0xF91D, "M", "欄"), + (0xF91E, "M", "爛"), + (0xF91F, "M", "蘭"), + (0xF920, "M", "鸞"), + (0xF921, "M", "嵐"), + (0xF922, "M", "濫"), + (0xF923, "M", "藍"), + (0xF924, "M", "襤"), + (0xF925, "M", "拉"), + (0xF926, "M", "臘"), + (0xF927, "M", "蠟"), + (0xF928, "M", "廊"), + (0xF929, "M", "朗"), + (0xF92A, "M", "浪"), + (0xF92B, "M", "狼"), + (0xF92C, "M", "郎"), + (0xF92D, "M", "來"), + (0xF92E, "M", "冷"), + (0xF92F, "M", "勞"), + (0xF930, "M", "擄"), + (0xF931, "M", "櫓"), + (0xF932, "M", "爐"), + (0xF933, "M", "盧"), + (0xF934, "M", "老"), + (0xF935, "M", "蘆"), + (0xF936, "M", "虜"), + (0xF937, "M", "路"), + (0xF938, "M", "露"), + (0xF939, "M", "魯"), + (0xF93A, "M", "鷺"), + (0xF93B, "M", "碌"), + (0xF93C, "M", "祿"), + (0xF93D, "M", "綠"), + (0xF93E, "M", "菉"), + (0xF93F, "M", "錄"), + (0xF940, "M", "鹿"), + (0xF941, "M", "論"), + (0xF942, "M", "壟"), + (0xF943, "M", "弄"), + (0xF944, "M", "籠"), + (0xF945, "M", "聾"), + (0xF946, "M", "牢"), + (0xF947, "M", "磊"), + (0xF948, "M", "賂"), + (0xF949, "M", "雷"), + (0xF94A, "M", "壘"), + (0xF94B, "M", "屢"), + (0xF94C, "M", "樓"), + (0xF94D, "M", "淚"), + (0xF94E, "M", "漏"), + (0xF94F, "M", "累"), + (0xF950, "M", "縷"), + (0xF951, "M", "陋"), + (0xF952, "M", "勒"), + (0xF953, "M", "肋"), + (0xF954, "M", "凜"), + (0xF955, "M", "凌"), + (0xF956, "M", "稜"), + (0xF957, "M", "綾"), + (0xF958, "M", "菱"), + (0xF959, "M", "陵"), + (0xF95A, "M", "讀"), + (0xF95B, "M", "拏"), + (0xF95C, "M", "樂"), + (0xF95D, "M", "諾"), + (0xF95E, "M", "丹"), + (0xF95F, "M", "寧"), + (0xF960, "M", "怒"), + (0xF961, "M", "率"), + (0xF962, "M", "異"), + (0xF963, "M", "北"), + (0xF964, "M", "磻"), + (0xF965, "M", "便"), + (0xF966, "M", "復"), + (0xF967, "M", "不"), + (0xF968, "M", "泌"), + (0xF969, "M", "數"), + (0xF96A, "M", "索"), + (0xF96B, "M", "參"), + (0xF96C, "M", "塞"), + (0xF96D, "M", "省"), + (0xF96E, "M", "葉"), + (0xF96F, "M", "說"), + (0xF970, "M", "殺"), + (0xF971, "M", "辰"), + (0xF972, "M", "沈"), + (0xF973, "M", "拾"), + (0xF974, "M", "若"), + (0xF975, "M", "掠"), + (0xF976, "M", "略"), + (0xF977, "M", "亮"), + (0xF978, "M", "兩"), + (0xF979, "M", "凉"), + (0xF97A, "M", "梁"), + (0xF97B, "M", "糧"), + (0xF97C, "M", "良"), + (0xF97D, "M", "諒"), + (0xF97E, "M", "量"), + (0xF97F, "M", "勵"), + (0xF980, "M", "呂"), + (0xF981, "M", "女"), + (0xF982, "M", "廬"), + (0xF983, "M", "旅"), + (0xF984, "M", "濾"), + (0xF985, "M", "礪"), + (0xF986, "M", "閭"), + (0xF987, "M", "驪"), + (0xF988, "M", "麗"), + (0xF989, "M", "黎"), + (0xF98A, "M", "力"), + (0xF98B, "M", "曆"), + (0xF98C, "M", "歷"), + (0xF98D, "M", "轢"), + (0xF98E, "M", "年"), + (0xF98F, "M", "憐"), + (0xF990, "M", "戀"), + (0xF991, "M", "撚"), + (0xF992, "M", "漣"), + (0xF993, "M", "煉"), + (0xF994, "M", "璉"), + (0xF995, "M", "秊"), + (0xF996, "M", "練"), + (0xF997, "M", "聯"), + (0xF998, "M", "輦"), + (0xF999, "M", "蓮"), + (0xF99A, "M", "連"), + (0xF99B, "M", "鍊"), + (0xF99C, "M", "列"), + (0xF99D, "M", "劣"), + (0xF99E, "M", "咽"), + (0xF99F, "M", "烈"), + (0xF9A0, "M", "裂"), + (0xF9A1, "M", "說"), + (0xF9A2, "M", "廉"), + (0xF9A3, "M", "念"), + (0xF9A4, "M", "捻"), + (0xF9A5, "M", "殮"), + (0xF9A6, "M", "簾"), + (0xF9A7, "M", "獵"), + (0xF9A8, "M", "令"), + (0xF9A9, "M", "囹"), + (0xF9AA, "M", "寧"), + (0xF9AB, "M", "嶺"), + (0xF9AC, "M", "怜"), + (0xF9AD, "M", "玲"), + (0xF9AE, "M", "瑩"), + (0xF9AF, "M", "羚"), + (0xF9B0, "M", "聆"), + (0xF9B1, "M", "鈴"), + (0xF9B2, "M", "零"), + (0xF9B3, "M", "靈"), + (0xF9B4, "M", "領"), + (0xF9B5, "M", "例"), + (0xF9B6, "M", "禮"), + (0xF9B7, "M", "醴"), + (0xF9B8, "M", "隸"), + (0xF9B9, "M", "惡"), + (0xF9BA, "M", "了"), + (0xF9BB, "M", "僚"), + (0xF9BC, "M", "寮"), + (0xF9BD, "M", "尿"), + (0xF9BE, "M", "料"), + (0xF9BF, "M", "樂"), + (0xF9C0, "M", "燎"), + (0xF9C1, "M", "療"), + (0xF9C2, "M", "蓼"), + (0xF9C3, "M", "遼"), + (0xF9C4, "M", "龍"), + (0xF9C5, "M", "暈"), + (0xF9C6, "M", "阮"), + (0xF9C7, "M", "劉"), + (0xF9C8, "M", "杻"), + (0xF9C9, "M", "柳"), + (0xF9CA, "M", "流"), + (0xF9CB, "M", "溜"), + (0xF9CC, "M", "琉"), + (0xF9CD, "M", "留"), + (0xF9CE, "M", "硫"), + (0xF9CF, "M", "紐"), + (0xF9D0, "M", "類"), + (0xF9D1, "M", "六"), + (0xF9D2, "M", "戮"), + (0xF9D3, "M", "陸"), + (0xF9D4, "M", "倫"), + (0xF9D5, "M", "崙"), + (0xF9D6, "M", "淪"), + (0xF9D7, "M", "輪"), + (0xF9D8, "M", "律"), + (0xF9D9, "M", "慄"), + (0xF9DA, "M", "栗"), + (0xF9DB, "M", "率"), + (0xF9DC, "M", "隆"), + (0xF9DD, "M", "利"), + (0xF9DE, "M", "吏"), + (0xF9DF, "M", "履"), + (0xF9E0, "M", "易"), + (0xF9E1, "M", "李"), + (0xF9E2, "M", "梨"), + (0xF9E3, "M", "泥"), + (0xF9E4, "M", "理"), + (0xF9E5, "M", "痢"), + (0xF9E6, "M", "罹"), + (0xF9E7, "M", "裏"), + (0xF9E8, "M", "裡"), + (0xF9E9, "M", "里"), + (0xF9EA, "M", "離"), + (0xF9EB, "M", "匿"), + (0xF9EC, "M", "溺"), + (0xF9ED, "M", "吝"), + (0xF9EE, "M", "燐"), + (0xF9EF, "M", "璘"), + (0xF9F0, "M", "藺"), + (0xF9F1, "M", "隣"), + (0xF9F2, "M", "鱗"), + (0xF9F3, "M", "麟"), + (0xF9F4, "M", "林"), + (0xF9F5, "M", "淋"), + (0xF9F6, "M", "臨"), + (0xF9F7, "M", "立"), + (0xF9F8, "M", "笠"), + (0xF9F9, "M", "粒"), + (0xF9FA, "M", "狀"), + (0xF9FB, "M", "炙"), + (0xF9FC, "M", "識"), + (0xF9FD, "M", "什"), + (0xF9FE, "M", "茶"), + (0xF9FF, "M", "刺"), + (0xFA00, "M", "切"), + (0xFA01, "M", "度"), + (0xFA02, "M", "拓"), + (0xFA03, "M", "糖"), + (0xFA04, "M", "宅"), + (0xFA05, "M", "洞"), + (0xFA06, "M", "暴"), + (0xFA07, "M", "輻"), + (0xFA08, "M", "行"), + (0xFA09, "M", "降"), + (0xFA0A, "M", "見"), + (0xFA0B, "M", "廓"), + (0xFA0C, "M", "兀"), + (0xFA0D, "M", "嗀"), + (0xFA0E, "V"), + (0xFA10, "M", "塚"), + (0xFA11, "V"), + (0xFA12, "M", "晴"), + (0xFA13, "V"), + (0xFA15, "M", "凞"), + (0xFA16, "M", "猪"), + (0xFA17, "M", "益"), + (0xFA18, "M", "礼"), + (0xFA19, "M", "神"), + (0xFA1A, "M", "祥"), + (0xFA1B, "M", "福"), + (0xFA1C, "M", "靖"), + (0xFA1D, "M", "精"), + (0xFA1E, "M", "羽"), + (0xFA1F, "V"), + (0xFA20, "M", "蘒"), + (0xFA21, "V"), + (0xFA22, "M", "諸"), + (0xFA23, "V"), + (0xFA25, "M", "逸"), + (0xFA26, "M", "都"), + (0xFA27, "V"), + (0xFA2A, "M", "飯"), + (0xFA2B, "M", "飼"), + (0xFA2C, "M", "館"), + (0xFA2D, "M", "鶴"), + (0xFA2E, "M", "郞"), + (0xFA2F, "M", "隷"), + (0xFA30, "M", "侮"), + (0xFA31, "M", "僧"), + (0xFA32, "M", "免"), + (0xFA33, "M", "勉"), + (0xFA34, "M", "勤"), + (0xFA35, "M", "卑"), + (0xFA36, "M", "喝"), + (0xFA37, "M", "嘆"), + (0xFA38, "M", "器"), + (0xFA39, "M", "塀"), + (0xFA3A, "M", "墨"), + (0xFA3B, "M", "層"), + (0xFA3C, "M", "屮"), + (0xFA3D, "M", "悔"), + (0xFA3E, "M", "慨"), + (0xFA3F, "M", "憎"), + (0xFA40, "M", "懲"), + (0xFA41, "M", "敏"), + (0xFA42, "M", "既"), + (0xFA43, "M", "暑"), + (0xFA44, "M", "梅"), + (0xFA45, "M", "海"), + (0xFA46, "M", "渚"), + (0xFA47, "M", "漢"), + (0xFA48, "M", "煮"), + (0xFA49, "M", "爫"), + (0xFA4A, "M", "琢"), + (0xFA4B, "M", "碑"), + (0xFA4C, "M", "社"), + (0xFA4D, "M", "祉"), + (0xFA4E, "M", "祈"), + (0xFA4F, "M", "祐"), + (0xFA50, "M", "祖"), + (0xFA51, "M", "祝"), + (0xFA52, "M", "禍"), + (0xFA53, "M", "禎"), + (0xFA54, "M", "穀"), + (0xFA55, "M", "突"), + (0xFA56, "M", "節"), + (0xFA57, "M", "練"), + (0xFA58, "M", "縉"), + (0xFA59, "M", "繁"), + (0xFA5A, "M", "署"), + (0xFA5B, "M", "者"), + (0xFA5C, "M", "臭"), + (0xFA5D, "M", "艹"), + (0xFA5F, "M", "著"), + (0xFA60, "M", "褐"), + (0xFA61, "M", "視"), + (0xFA62, "M", "謁"), + (0xFA63, "M", "謹"), + (0xFA64, "M", "賓"), + (0xFA65, "M", "贈"), + (0xFA66, "M", "辶"), + (0xFA67, "M", "逸"), + (0xFA68, "M", "難"), + (0xFA69, "M", "響"), + (0xFA6A, "M", "頻"), + (0xFA6B, "M", "恵"), + (0xFA6C, "M", "𤋮"), + (0xFA6D, "M", "舘"), + (0xFA6E, "X"), + (0xFA70, "M", "並"), + (0xFA71, "M", "况"), + (0xFA72, "M", "全"), + (0xFA73, "M", "侀"), + (0xFA74, "M", "充"), + (0xFA75, "M", "冀"), + (0xFA76, "M", "勇"), + (0xFA77, "M", "勺"), + (0xFA78, "M", "喝"), + (0xFA79, "M", "啕"), + (0xFA7A, "M", "喙"), + (0xFA7B, "M", "嗢"), + (0xFA7C, "M", "塚"), + (0xFA7D, "M", "墳"), + (0xFA7E, "M", "奄"), + (0xFA7F, "M", "奔"), + (0xFA80, "M", "婢"), + (0xFA81, "M", "嬨"), + (0xFA82, "M", "廒"), + (0xFA83, "M", "廙"), + (0xFA84, "M", "彩"), + (0xFA85, "M", "徭"), + (0xFA86, "M", "惘"), + (0xFA87, "M", "慎"), + (0xFA88, "M", "愈"), + (0xFA89, "M", "憎"), + (0xFA8A, "M", "慠"), + (0xFA8B, "M", "懲"), + (0xFA8C, "M", "戴"), + (0xFA8D, "M", "揄"), + (0xFA8E, "M", "搜"), + (0xFA8F, "M", "摒"), + (0xFA90, "M", "敖"), + (0xFA91, "M", "晴"), + (0xFA92, "M", "朗"), + (0xFA93, "M", "望"), + (0xFA94, "M", "杖"), + (0xFA95, "M", "歹"), + (0xFA96, "M", "殺"), + (0xFA97, "M", "流"), + (0xFA98, "M", "滛"), + (0xFA99, "M", "滋"), + (0xFA9A, "M", "漢"), + (0xFA9B, "M", "瀞"), + (0xFA9C, "M", "煮"), + (0xFA9D, "M", "瞧"), + (0xFA9E, "M", "爵"), + (0xFA9F, "M", "犯"), + (0xFAA0, "M", "猪"), + (0xFAA1, "M", "瑱"), + (0xFAA2, "M", "甆"), + (0xFAA3, "M", "画"), + (0xFAA4, "M", "瘝"), + (0xFAA5, "M", "瘟"), + (0xFAA6, "M", "益"), + (0xFAA7, "M", "盛"), + (0xFAA8, "M", "直"), + (0xFAA9, "M", "睊"), + (0xFAAA, "M", "着"), + (0xFAAB, "M", "磌"), + (0xFAAC, "M", "窱"), + (0xFAAD, "M", "節"), + (0xFAAE, "M", "类"), + (0xFAAF, "M", "絛"), + (0xFAB0, "M", "練"), + (0xFAB1, "M", "缾"), + (0xFAB2, "M", "者"), + (0xFAB3, "M", "荒"), + (0xFAB4, "M", "華"), + (0xFAB5, "M", "蝹"), + (0xFAB6, "M", "襁"), + (0xFAB7, "M", "覆"), + (0xFAB8, "M", "視"), + (0xFAB9, "M", "調"), + (0xFABA, "M", "諸"), + (0xFABB, "M", "請"), + (0xFABC, "M", "謁"), + (0xFABD, "M", "諾"), + (0xFABE, "M", "諭"), + (0xFABF, "M", "謹"), + (0xFAC0, "M", "變"), + (0xFAC1, "M", "贈"), + (0xFAC2, "M", "輸"), + (0xFAC3, "M", "遲"), + (0xFAC4, "M", "醙"), + (0xFAC5, "M", "鉶"), + (0xFAC6, "M", "陼"), + (0xFAC7, "M", "難"), + (0xFAC8, "M", "靖"), + (0xFAC9, "M", "韛"), + (0xFACA, "M", "響"), + (0xFACB, "M", "頋"), + (0xFACC, "M", "頻"), + (0xFACD, "M", "鬒"), + (0xFACE, "M", "龜"), + (0xFACF, "M", "𢡊"), + (0xFAD0, "M", "𢡄"), + (0xFAD1, "M", "𣏕"), + (0xFAD2, "M", "㮝"), + (0xFAD3, "M", "䀘"), + (0xFAD4, "M", "䀹"), + (0xFAD5, "M", "𥉉"), + (0xFAD6, "M", "𥳐"), + (0xFAD7, "M", "𧻓"), + (0xFAD8, "M", "齃"), + (0xFAD9, "M", "龎"), + (0xFADA, "X"), + (0xFB00, "M", "ff"), + (0xFB01, "M", "fi"), + (0xFB02, "M", "fl"), + (0xFB03, "M", "ffi"), + (0xFB04, "M", "ffl"), + (0xFB05, "M", "st"), + (0xFB07, "X"), + (0xFB13, "M", "մն"), + (0xFB14, "M", "մե"), + (0xFB15, "M", "մի"), + (0xFB16, "M", "վն"), + (0xFB17, "M", "մխ"), + (0xFB18, "X"), + (0xFB1D, "M", "יִ"), + (0xFB1E, "V"), + (0xFB1F, "M", "ײַ"), + (0xFB20, "M", "ע"), + (0xFB21, "M", "א"), + (0xFB22, "M", "ד"), + (0xFB23, "M", "ה"), + (0xFB24, "M", "כ"), + (0xFB25, "M", "ל"), + (0xFB26, "M", "ם"), + (0xFB27, "M", "ר"), + (0xFB28, "M", "ת"), + (0xFB29, "M", "+"), + (0xFB2A, "M", "שׁ"), + (0xFB2B, "M", "שׂ"), + (0xFB2C, "M", "שּׁ"), + (0xFB2D, "M", "שּׂ"), + (0xFB2E, "M", "אַ"), + (0xFB2F, "M", "אָ"), + (0xFB30, "M", "אּ"), + (0xFB31, "M", "בּ"), + (0xFB32, "M", "גּ"), + (0xFB33, "M", "דּ"), + (0xFB34, "M", "הּ"), + (0xFB35, "M", "וּ"), + (0xFB36, "M", "זּ"), + (0xFB37, "X"), + (0xFB38, "M", "טּ"), + (0xFB39, "M", "יּ"), + (0xFB3A, "M", "ךּ"), + (0xFB3B, "M", "כּ"), + (0xFB3C, "M", "לּ"), + (0xFB3D, "X"), + (0xFB3E, "M", "מּ"), + (0xFB3F, "X"), + (0xFB40, "M", "נּ"), + (0xFB41, "M", "סּ"), + (0xFB42, "X"), + (0xFB43, "M", "ףּ"), + (0xFB44, "M", "פּ"), + (0xFB45, "X"), + (0xFB46, "M", "צּ"), + (0xFB47, "M", "קּ"), + (0xFB48, "M", "רּ"), + (0xFB49, "M", "שּ"), + (0xFB4A, "M", "תּ"), + (0xFB4B, "M", "וֹ"), + (0xFB4C, "M", "בֿ"), + (0xFB4D, "M", "כֿ"), + (0xFB4E, "M", "פֿ"), + (0xFB4F, "M", "אל"), + (0xFB50, "M", "ٱ"), + (0xFB52, "M", "ٻ"), + (0xFB56, "M", "پ"), + (0xFB5A, "M", "ڀ"), + (0xFB5E, "M", "ٺ"), + (0xFB62, "M", "ٿ"), + (0xFB66, "M", "ٹ"), + (0xFB6A, "M", "ڤ"), + (0xFB6E, "M", "ڦ"), + (0xFB72, "M", "ڄ"), + (0xFB76, "M", "ڃ"), + (0xFB7A, "M", "چ"), + (0xFB7E, "M", "ڇ"), + (0xFB82, "M", "ڍ"), + (0xFB84, "M", "ڌ"), + (0xFB86, "M", "ڎ"), + (0xFB88, "M", "ڈ"), + (0xFB8A, "M", "ژ"), + (0xFB8C, "M", "ڑ"), + (0xFB8E, "M", "ک"), + (0xFB92, "M", "گ"), + (0xFB96, "M", "ڳ"), + (0xFB9A, "M", "ڱ"), + (0xFB9E, "M", "ں"), + (0xFBA0, "M", "ڻ"), + (0xFBA4, "M", "ۀ"), + (0xFBA6, "M", "ہ"), + (0xFBAA, "M", "ھ"), + (0xFBAE, "M", "ے"), + (0xFBB0, "M", "ۓ"), + (0xFBB2, "V"), + (0xFBD3, "M", "ڭ"), + (0xFBD7, "M", "ۇ"), + (0xFBD9, "M", "ۆ"), + (0xFBDB, "M", "ۈ"), + (0xFBDD, "M", "ۇٴ"), + (0xFBDE, "M", "ۋ"), + (0xFBE0, "M", "ۅ"), + (0xFBE2, "M", "ۉ"), + (0xFBE4, "M", "ې"), + (0xFBE8, "M", "ى"), + (0xFBEA, "M", "ئا"), + (0xFBEC, "M", "ئە"), + (0xFBEE, "M", "ئو"), + (0xFBF0, "M", "ئۇ"), + (0xFBF2, "M", "ئۆ"), + (0xFBF4, "M", "ئۈ"), + (0xFBF6, "M", "ئې"), + (0xFBF9, "M", "ئى"), + (0xFBFC, "M", "ی"), + (0xFC00, "M", "ئج"), + (0xFC01, "M", "ئح"), + (0xFC02, "M", "ئم"), + (0xFC03, "M", "ئى"), + (0xFC04, "M", "ئي"), + (0xFC05, "M", "بج"), + (0xFC06, "M", "بح"), + (0xFC07, "M", "بخ"), + (0xFC08, "M", "بم"), + (0xFC09, "M", "بى"), + (0xFC0A, "M", "بي"), + (0xFC0B, "M", "تج"), + (0xFC0C, "M", "تح"), + (0xFC0D, "M", "تخ"), + (0xFC0E, "M", "تم"), + (0xFC0F, "M", "تى"), + (0xFC10, "M", "تي"), + (0xFC11, "M", "ثج"), + (0xFC12, "M", "ثم"), + (0xFC13, "M", "ثى"), + (0xFC14, "M", "ثي"), + (0xFC15, "M", "جح"), + (0xFC16, "M", "جم"), + (0xFC17, "M", "حج"), + (0xFC18, "M", "حم"), + (0xFC19, "M", "خج"), + (0xFC1A, "M", "خح"), + (0xFC1B, "M", "خم"), + (0xFC1C, "M", "سج"), + (0xFC1D, "M", "سح"), + (0xFC1E, "M", "سخ"), + (0xFC1F, "M", "سم"), + (0xFC20, "M", "صح"), + (0xFC21, "M", "صم"), + (0xFC22, "M", "ضج"), + (0xFC23, "M", "ضح"), + (0xFC24, "M", "ضخ"), + (0xFC25, "M", "ضم"), + (0xFC26, "M", "طح"), + (0xFC27, "M", "طم"), + (0xFC28, "M", "ظم"), + (0xFC29, "M", "عج"), + (0xFC2A, "M", "عم"), + (0xFC2B, "M", "غج"), + (0xFC2C, "M", "غم"), + (0xFC2D, "M", "فج"), + (0xFC2E, "M", "فح"), + (0xFC2F, "M", "فخ"), + (0xFC30, "M", "فم"), + (0xFC31, "M", "فى"), + (0xFC32, "M", "في"), + (0xFC33, "M", "قح"), + (0xFC34, "M", "قم"), + (0xFC35, "M", "قى"), + (0xFC36, "M", "قي"), + (0xFC37, "M", "كا"), + (0xFC38, "M", "كج"), + (0xFC39, "M", "كح"), + (0xFC3A, "M", "كخ"), + (0xFC3B, "M", "كل"), + (0xFC3C, "M", "كم"), + (0xFC3D, "M", "كى"), + (0xFC3E, "M", "كي"), + (0xFC3F, "M", "لج"), + (0xFC40, "M", "لح"), + (0xFC41, "M", "لخ"), + (0xFC42, "M", "لم"), + (0xFC43, "M", "لى"), + (0xFC44, "M", "لي"), + (0xFC45, "M", "مج"), + (0xFC46, "M", "مح"), + (0xFC47, "M", "مخ"), + (0xFC48, "M", "مم"), + (0xFC49, "M", "مى"), + (0xFC4A, "M", "مي"), + (0xFC4B, "M", "نج"), + (0xFC4C, "M", "نح"), + (0xFC4D, "M", "نخ"), + (0xFC4E, "M", "نم"), + (0xFC4F, "M", "نى"), + (0xFC50, "M", "ني"), + (0xFC51, "M", "هج"), + (0xFC52, "M", "هم"), + (0xFC53, "M", "هى"), + (0xFC54, "M", "هي"), + (0xFC55, "M", "يج"), + (0xFC56, "M", "يح"), + (0xFC57, "M", "يخ"), + (0xFC58, "M", "يم"), + (0xFC59, "M", "يى"), + (0xFC5A, "M", "يي"), + (0xFC5B, "M", "ذٰ"), + (0xFC5C, "M", "رٰ"), + (0xFC5D, "M", "ىٰ"), + (0xFC5E, "M", " ٌّ"), + (0xFC5F, "M", " ٍّ"), + (0xFC60, "M", " َّ"), + (0xFC61, "M", " ُّ"), + (0xFC62, "M", " ِّ"), + (0xFC63, "M", " ّٰ"), + (0xFC64, "M", "ئر"), + (0xFC65, "M", "ئز"), + (0xFC66, "M", "ئم"), + (0xFC67, "M", "ئن"), + (0xFC68, "M", "ئى"), + (0xFC69, "M", "ئي"), + (0xFC6A, "M", "بر"), + (0xFC6B, "M", "بز"), + (0xFC6C, "M", "بم"), + (0xFC6D, "M", "بن"), + (0xFC6E, "M", "بى"), + (0xFC6F, "M", "بي"), + (0xFC70, "M", "تر"), + (0xFC71, "M", "تز"), + (0xFC72, "M", "تم"), + (0xFC73, "M", "تن"), + (0xFC74, "M", "تى"), + (0xFC75, "M", "تي"), + (0xFC76, "M", "ثر"), + (0xFC77, "M", "ثز"), + (0xFC78, "M", "ثم"), + (0xFC79, "M", "ثن"), + (0xFC7A, "M", "ثى"), + (0xFC7B, "M", "ثي"), + (0xFC7C, "M", "فى"), + (0xFC7D, "M", "في"), + (0xFC7E, "M", "قى"), + (0xFC7F, "M", "قي"), + (0xFC80, "M", "كا"), + (0xFC81, "M", "كل"), + (0xFC82, "M", "كم"), + (0xFC83, "M", "كى"), + (0xFC84, "M", "كي"), + (0xFC85, "M", "لم"), + (0xFC86, "M", "لى"), + (0xFC87, "M", "لي"), + (0xFC88, "M", "ما"), + (0xFC89, "M", "مم"), + (0xFC8A, "M", "نر"), + (0xFC8B, "M", "نز"), + (0xFC8C, "M", "نم"), + (0xFC8D, "M", "نن"), + (0xFC8E, "M", "نى"), + (0xFC8F, "M", "ني"), + (0xFC90, "M", "ىٰ"), + (0xFC91, "M", "ير"), + (0xFC92, "M", "يز"), + (0xFC93, "M", "يم"), + (0xFC94, "M", "ين"), + (0xFC95, "M", "يى"), + (0xFC96, "M", "يي"), + (0xFC97, "M", "ئج"), + (0xFC98, "M", "ئح"), + (0xFC99, "M", "ئخ"), + (0xFC9A, "M", "ئم"), + (0xFC9B, "M", "ئه"), + (0xFC9C, "M", "بج"), + (0xFC9D, "M", "بح"), + (0xFC9E, "M", "بخ"), + (0xFC9F, "M", "بم"), + (0xFCA0, "M", "به"), + (0xFCA1, "M", "تج"), + (0xFCA2, "M", "تح"), + (0xFCA3, "M", "تخ"), + (0xFCA4, "M", "تم"), + (0xFCA5, "M", "ته"), + (0xFCA6, "M", "ثم"), + (0xFCA7, "M", "جح"), + (0xFCA8, "M", "جم"), + (0xFCA9, "M", "حج"), + (0xFCAA, "M", "حم"), + (0xFCAB, "M", "خج"), + (0xFCAC, "M", "خم"), + (0xFCAD, "M", "سج"), + (0xFCAE, "M", "سح"), + (0xFCAF, "M", "سخ"), + (0xFCB0, "M", "سم"), + (0xFCB1, "M", "صح"), + (0xFCB2, "M", "صخ"), + (0xFCB3, "M", "صم"), + (0xFCB4, "M", "ضج"), + (0xFCB5, "M", "ضح"), + (0xFCB6, "M", "ضخ"), + (0xFCB7, "M", "ضم"), + (0xFCB8, "M", "طح"), + (0xFCB9, "M", "ظم"), + (0xFCBA, "M", "عج"), + (0xFCBB, "M", "عم"), + (0xFCBC, "M", "غج"), + (0xFCBD, "M", "غم"), + (0xFCBE, "M", "فج"), + (0xFCBF, "M", "فح"), + (0xFCC0, "M", "فخ"), + (0xFCC1, "M", "فم"), + (0xFCC2, "M", "قح"), + (0xFCC3, "M", "قم"), + (0xFCC4, "M", "كج"), + (0xFCC5, "M", "كح"), + (0xFCC6, "M", "كخ"), + (0xFCC7, "M", "كل"), + (0xFCC8, "M", "كم"), + (0xFCC9, "M", "لج"), + (0xFCCA, "M", "لح"), + (0xFCCB, "M", "لخ"), + (0xFCCC, "M", "لم"), + (0xFCCD, "M", "له"), + (0xFCCE, "M", "مج"), + (0xFCCF, "M", "مح"), + (0xFCD0, "M", "مخ"), + (0xFCD1, "M", "مم"), + (0xFCD2, "M", "نج"), + (0xFCD3, "M", "نح"), + (0xFCD4, "M", "نخ"), + (0xFCD5, "M", "نم"), + (0xFCD6, "M", "نه"), + (0xFCD7, "M", "هج"), + (0xFCD8, "M", "هم"), + (0xFCD9, "M", "هٰ"), + (0xFCDA, "M", "يج"), + (0xFCDB, "M", "يح"), + (0xFCDC, "M", "يخ"), + (0xFCDD, "M", "يم"), + (0xFCDE, "M", "يه"), + (0xFCDF, "M", "ئم"), + (0xFCE0, "M", "ئه"), + (0xFCE1, "M", "بم"), + (0xFCE2, "M", "به"), + (0xFCE3, "M", "تم"), + (0xFCE4, "M", "ته"), + (0xFCE5, "M", "ثم"), + (0xFCE6, "M", "ثه"), + (0xFCE7, "M", "سم"), + (0xFCE8, "M", "سه"), + (0xFCE9, "M", "شم"), + (0xFCEA, "M", "شه"), + (0xFCEB, "M", "كل"), + (0xFCEC, "M", "كم"), + (0xFCED, "M", "لم"), + (0xFCEE, "M", "نم"), + (0xFCEF, "M", "نه"), + (0xFCF0, "M", "يم"), + (0xFCF1, "M", "يه"), + (0xFCF2, "M", "ـَّ"), + (0xFCF3, "M", "ـُّ"), + (0xFCF4, "M", "ـِّ"), + (0xFCF5, "M", "طى"), + (0xFCF6, "M", "طي"), + (0xFCF7, "M", "عى"), + (0xFCF8, "M", "عي"), + (0xFCF9, "M", "غى"), + (0xFCFA, "M", "غي"), + (0xFCFB, "M", "سى"), + (0xFCFC, "M", "سي"), + (0xFCFD, "M", "شى"), + (0xFCFE, "M", "شي"), + (0xFCFF, "M", "حى"), + (0xFD00, "M", "حي"), + (0xFD01, "M", "جى"), + (0xFD02, "M", "جي"), + (0xFD03, "M", "خى"), + (0xFD04, "M", "خي"), + (0xFD05, "M", "صى"), + (0xFD06, "M", "صي"), + (0xFD07, "M", "ضى"), + (0xFD08, "M", "ضي"), + (0xFD09, "M", "شج"), + (0xFD0A, "M", "شح"), + (0xFD0B, "M", "شخ"), + (0xFD0C, "M", "شم"), + (0xFD0D, "M", "شر"), + (0xFD0E, "M", "سر"), + (0xFD0F, "M", "صر"), + (0xFD10, "M", "ضر"), + (0xFD11, "M", "طى"), + (0xFD12, "M", "طي"), + (0xFD13, "M", "عى"), + (0xFD14, "M", "عي"), + (0xFD15, "M", "غى"), + (0xFD16, "M", "غي"), + (0xFD17, "M", "سى"), + (0xFD18, "M", "سي"), + (0xFD19, "M", "شى"), + (0xFD1A, "M", "شي"), + (0xFD1B, "M", "حى"), + (0xFD1C, "M", "حي"), + (0xFD1D, "M", "جى"), + (0xFD1E, "M", "جي"), + (0xFD1F, "M", "خى"), + (0xFD20, "M", "خي"), + (0xFD21, "M", "صى"), + (0xFD22, "M", "صي"), + (0xFD23, "M", "ضى"), + (0xFD24, "M", "ضي"), + (0xFD25, "M", "شج"), + (0xFD26, "M", "شح"), + (0xFD27, "M", "شخ"), + (0xFD28, "M", "شم"), + (0xFD29, "M", "شر"), + (0xFD2A, "M", "سر"), + (0xFD2B, "M", "صر"), + (0xFD2C, "M", "ضر"), + (0xFD2D, "M", "شج"), + (0xFD2E, "M", "شح"), + (0xFD2F, "M", "شخ"), + (0xFD30, "M", "شم"), + (0xFD31, "M", "سه"), + (0xFD32, "M", "شه"), + (0xFD33, "M", "طم"), + (0xFD34, "M", "سج"), + (0xFD35, "M", "سح"), + (0xFD36, "M", "سخ"), + (0xFD37, "M", "شج"), + (0xFD38, "M", "شح"), + (0xFD39, "M", "شخ"), + (0xFD3A, "M", "طم"), + (0xFD3B, "M", "ظم"), + (0xFD3C, "M", "اً"), + (0xFD3E, "V"), + (0xFD50, "M", "تجم"), + (0xFD51, "M", "تحج"), + (0xFD53, "M", "تحم"), + (0xFD54, "M", "تخم"), + (0xFD55, "M", "تمج"), + (0xFD56, "M", "تمح"), + (0xFD57, "M", "تمخ"), + (0xFD58, "M", "جمح"), + (0xFD5A, "M", "حمي"), + (0xFD5B, "M", "حمى"), + (0xFD5C, "M", "سحج"), + (0xFD5D, "M", "سجح"), + (0xFD5E, "M", "سجى"), + (0xFD5F, "M", "سمح"), + (0xFD61, "M", "سمج"), + (0xFD62, "M", "سمم"), + (0xFD64, "M", "صحح"), + (0xFD66, "M", "صمم"), + (0xFD67, "M", "شحم"), + (0xFD69, "M", "شجي"), + (0xFD6A, "M", "شمخ"), + (0xFD6C, "M", "شمم"), + (0xFD6E, "M", "ضحى"), + (0xFD6F, "M", "ضخم"), + (0xFD71, "M", "طمح"), + (0xFD73, "M", "طمم"), + (0xFD74, "M", "طمي"), + (0xFD75, "M", "عجم"), + (0xFD76, "M", "عمم"), + (0xFD78, "M", "عمى"), + (0xFD79, "M", "غمم"), + (0xFD7A, "M", "غمي"), + (0xFD7B, "M", "غمى"), + (0xFD7C, "M", "فخم"), + (0xFD7E, "M", "قمح"), + (0xFD7F, "M", "قمم"), + (0xFD80, "M", "لحم"), + (0xFD81, "M", "لحي"), + (0xFD82, "M", "لحى"), + (0xFD83, "M", "لجج"), + (0xFD85, "M", "لخم"), + (0xFD87, "M", "لمح"), + (0xFD89, "M", "محج"), + (0xFD8A, "M", "محم"), + (0xFD8B, "M", "محي"), + (0xFD8C, "M", "مجح"), + (0xFD8D, "M", "مجم"), + (0xFD8E, "M", "مخج"), + (0xFD8F, "M", "مخم"), + (0xFD90, "V"), + (0xFD92, "M", "مجخ"), + (0xFD93, "M", "همج"), + (0xFD94, "M", "همم"), + (0xFD95, "M", "نحم"), + (0xFD96, "M", "نحى"), + (0xFD97, "M", "نجم"), + (0xFD99, "M", "نجى"), + (0xFD9A, "M", "نمي"), + (0xFD9B, "M", "نمى"), + (0xFD9C, "M", "يمم"), + (0xFD9E, "M", "بخي"), + (0xFD9F, "M", "تجي"), + (0xFDA0, "M", "تجى"), + (0xFDA1, "M", "تخي"), + (0xFDA2, "M", "تخى"), + (0xFDA3, "M", "تمي"), + (0xFDA4, "M", "تمى"), + (0xFDA5, "M", "جمي"), + (0xFDA6, "M", "جحى"), + (0xFDA7, "M", "جمى"), + (0xFDA8, "M", "سخى"), + (0xFDA9, "M", "صحي"), + (0xFDAA, "M", "شحي"), + (0xFDAB, "M", "ضحي"), + (0xFDAC, "M", "لجي"), + (0xFDAD, "M", "لمي"), + (0xFDAE, "M", "يحي"), + (0xFDAF, "M", "يجي"), + (0xFDB0, "M", "يمي"), + (0xFDB1, "M", "ممي"), + (0xFDB2, "M", "قمي"), + (0xFDB3, "M", "نحي"), + (0xFDB4, "M", "قمح"), + (0xFDB5, "M", "لحم"), + (0xFDB6, "M", "عمي"), + (0xFDB7, "M", "كمي"), + (0xFDB8, "M", "نجح"), + (0xFDB9, "M", "مخي"), + (0xFDBA, "M", "لجم"), + (0xFDBB, "M", "كمم"), + (0xFDBC, "M", "لجم"), + (0xFDBD, "M", "نجح"), + (0xFDBE, "M", "جحي"), + (0xFDBF, "M", "حجي"), + (0xFDC0, "M", "مجي"), + (0xFDC1, "M", "فمي"), + (0xFDC2, "M", "بحي"), + (0xFDC3, "M", "كمم"), + (0xFDC4, "M", "عجم"), + (0xFDC5, "M", "صمم"), + (0xFDC6, "M", "سخي"), + (0xFDC7, "M", "نجي"), + (0xFDC8, "V"), + (0xFDD0, "X"), + (0xFDF0, "M", "صلے"), + (0xFDF1, "M", "قلے"), + (0xFDF2, "M", "الله"), + (0xFDF3, "M", "اكبر"), + (0xFDF4, "M", "محمد"), + (0xFDF5, "M", "صلعم"), + (0xFDF6, "M", "رسول"), + (0xFDF7, "M", "عليه"), + (0xFDF8, "M", "وسلم"), + (0xFDF9, "M", "صلى"), + (0xFDFA, "M", "صلى الله عليه وسلم"), + (0xFDFB, "M", "جل جلاله"), + (0xFDFC, "M", "ریال"), + (0xFDFD, "V"), + (0xFE00, "I"), + (0xFE10, "M", ","), + (0xFE11, "M", "、"), + (0xFE12, "X"), + (0xFE13, "M", ":"), + (0xFE14, "M", ";"), + (0xFE15, "M", "!"), + (0xFE16, "M", "?"), + (0xFE17, "M", "〖"), + (0xFE18, "M", "〗"), + (0xFE19, "X"), + (0xFE20, "V"), + (0xFE30, "X"), + (0xFE31, "M", "—"), + (0xFE32, "M", "–"), + (0xFE33, "M", "_"), + (0xFE35, "M", "("), + (0xFE36, "M", ")"), + (0xFE37, "M", "{"), + (0xFE38, "M", "}"), + (0xFE39, "M", "〔"), + (0xFE3A, "M", "〕"), + (0xFE3B, "M", "【"), + (0xFE3C, "M", "】"), + (0xFE3D, "M", "《"), + (0xFE3E, "M", "》"), + (0xFE3F, "M", "〈"), + (0xFE40, "M", "〉"), + (0xFE41, "M", "「"), + (0xFE42, "M", "」"), + (0xFE43, "M", "『"), + (0xFE44, "M", "』"), + (0xFE45, "V"), + (0xFE47, "M", "["), + (0xFE48, "M", "]"), + (0xFE49, "M", " ̅"), + (0xFE4D, "M", "_"), + (0xFE50, "M", ","), + (0xFE51, "M", "、"), + (0xFE52, "X"), + (0xFE54, "M", ";"), + (0xFE55, "M", ":"), + (0xFE56, "M", "?"), + (0xFE57, "M", "!"), + (0xFE58, "M", "—"), + (0xFE59, "M", "("), + (0xFE5A, "M", ")"), + (0xFE5B, "M", "{"), + (0xFE5C, "M", "}"), + (0xFE5D, "M", "〔"), + (0xFE5E, "M", "〕"), + (0xFE5F, "M", "#"), + (0xFE60, "M", "&"), + (0xFE61, "M", "*"), + (0xFE62, "M", "+"), + (0xFE63, "M", "-"), + (0xFE64, "M", "<"), + (0xFE65, "M", ">"), + (0xFE66, "M", "="), + (0xFE67, "X"), + (0xFE68, "M", "\\"), + (0xFE69, "M", "$"), + (0xFE6A, "M", "%"), + (0xFE6B, "M", "@"), + (0xFE6C, "X"), + (0xFE70, "M", " ً"), + (0xFE71, "M", "ـً"), + (0xFE72, "M", " ٌ"), + (0xFE73, "V"), + (0xFE74, "M", " ٍ"), + (0xFE75, "X"), + (0xFE76, "M", " َ"), + (0xFE77, "M", "ـَ"), + (0xFE78, "M", " ُ"), + (0xFE79, "M", "ـُ"), + (0xFE7A, "M", " ِ"), + (0xFE7B, "M", "ـِ"), + (0xFE7C, "M", " ّ"), + (0xFE7D, "M", "ـّ"), + (0xFE7E, "M", " ْ"), + (0xFE7F, "M", "ـْ"), + (0xFE80, "M", "ء"), + (0xFE81, "M", "آ"), + (0xFE83, "M", "أ"), + (0xFE85, "M", "ؤ"), + (0xFE87, "M", "إ"), + (0xFE89, "M", "ئ"), + (0xFE8D, "M", "ا"), + (0xFE8F, "M", "ب"), + (0xFE93, "M", "ة"), + (0xFE95, "M", "ت"), + (0xFE99, "M", "ث"), + (0xFE9D, "M", "ج"), + (0xFEA1, "M", "ح"), + (0xFEA5, "M", "خ"), + (0xFEA9, "M", "د"), + (0xFEAB, "M", "ذ"), + (0xFEAD, "M", "ر"), + (0xFEAF, "M", "ز"), + (0xFEB1, "M", "س"), + (0xFEB5, "M", "ش"), + (0xFEB9, "M", "ص"), + (0xFEBD, "M", "ض"), + (0xFEC1, "M", "ط"), + (0xFEC5, "M", "ظ"), + (0xFEC9, "M", "ع"), + (0xFECD, "M", "غ"), + (0xFED1, "M", "ف"), + (0xFED5, "M", "ق"), + (0xFED9, "M", "ك"), + (0xFEDD, "M", "ل"), + (0xFEE1, "M", "م"), + (0xFEE5, "M", "ن"), + (0xFEE9, "M", "ه"), + (0xFEED, "M", "و"), + (0xFEEF, "M", "ى"), + (0xFEF1, "M", "ي"), + (0xFEF5, "M", "لآ"), + (0xFEF7, "M", "لأ"), + (0xFEF9, "M", "لإ"), + (0xFEFB, "M", "لا"), + (0xFEFD, "X"), + (0xFEFF, "I"), + (0xFF00, "X"), + (0xFF01, "M", "!"), + (0xFF02, "M", '"'), + (0xFF03, "M", "#"), + (0xFF04, "M", "$"), + (0xFF05, "M", "%"), + (0xFF06, "M", "&"), + (0xFF07, "M", "'"), + (0xFF08, "M", "("), + (0xFF09, "M", ")"), + (0xFF0A, "M", "*"), + (0xFF0B, "M", "+"), + (0xFF0C, "M", ","), + (0xFF0D, "M", "-"), + (0xFF0E, "M", "."), + (0xFF0F, "M", "/"), + (0xFF10, "M", "0"), + (0xFF11, "M", "1"), + (0xFF12, "M", "2"), + (0xFF13, "M", "3"), + (0xFF14, "M", "4"), + (0xFF15, "M", "5"), + (0xFF16, "M", "6"), + (0xFF17, "M", "7"), + (0xFF18, "M", "8"), + (0xFF19, "M", "9"), + (0xFF1A, "M", ":"), + (0xFF1B, "M", ";"), + (0xFF1C, "M", "<"), + (0xFF1D, "M", "="), + (0xFF1E, "M", ">"), + (0xFF1F, "M", "?"), + (0xFF20, "M", "@"), + (0xFF21, "M", "a"), + (0xFF22, "M", "b"), + (0xFF23, "M", "c"), + (0xFF24, "M", "d"), + (0xFF25, "M", "e"), + (0xFF26, "M", "f"), + (0xFF27, "M", "g"), + (0xFF28, "M", "h"), + (0xFF29, "M", "i"), + (0xFF2A, "M", "j"), + (0xFF2B, "M", "k"), + (0xFF2C, "M", "l"), + (0xFF2D, "M", "m"), + (0xFF2E, "M", "n"), + (0xFF2F, "M", "o"), + (0xFF30, "M", "p"), + (0xFF31, "M", "q"), + (0xFF32, "M", "r"), + (0xFF33, "M", "s"), + (0xFF34, "M", "t"), + (0xFF35, "M", "u"), + (0xFF36, "M", "v"), + (0xFF37, "M", "w"), + (0xFF38, "M", "x"), + (0xFF39, "M", "y"), + (0xFF3A, "M", "z"), + (0xFF3B, "M", "["), + (0xFF3C, "M", "\\"), + (0xFF3D, "M", "]"), + (0xFF3E, "M", "^"), + (0xFF3F, "M", "_"), + (0xFF40, "M", "`"), + (0xFF41, "M", "a"), + (0xFF42, "M", "b"), + (0xFF43, "M", "c"), + (0xFF44, "M", "d"), + (0xFF45, "M", "e"), + (0xFF46, "M", "f"), + (0xFF47, "M", "g"), + (0xFF48, "M", "h"), + (0xFF49, "M", "i"), + (0xFF4A, "M", "j"), + (0xFF4B, "M", "k"), + (0xFF4C, "M", "l"), + (0xFF4D, "M", "m"), + (0xFF4E, "M", "n"), + (0xFF4F, "M", "o"), + (0xFF50, "M", "p"), + (0xFF51, "M", "q"), + (0xFF52, "M", "r"), + (0xFF53, "M", "s"), + (0xFF54, "M", "t"), + (0xFF55, "M", "u"), + (0xFF56, "M", "v"), + (0xFF57, "M", "w"), + (0xFF58, "M", "x"), + (0xFF59, "M", "y"), + (0xFF5A, "M", "z"), + (0xFF5B, "M", "{"), + (0xFF5C, "M", "|"), + (0xFF5D, "M", "}"), + (0xFF5E, "M", "~"), + (0xFF5F, "M", "⦅"), + (0xFF60, "M", "⦆"), + (0xFF61, "M", "."), + (0xFF62, "M", "「"), + (0xFF63, "M", "」"), + (0xFF64, "M", "、"), + (0xFF65, "M", "・"), + (0xFF66, "M", "ヲ"), + (0xFF67, "M", "ァ"), + (0xFF68, "M", "ィ"), + (0xFF69, "M", "ゥ"), + (0xFF6A, "M", "ェ"), + (0xFF6B, "M", "ォ"), + (0xFF6C, "M", "ャ"), + (0xFF6D, "M", "ュ"), + (0xFF6E, "M", "ョ"), + (0xFF6F, "M", "ッ"), + (0xFF70, "M", "ー"), + (0xFF71, "M", "ア"), + (0xFF72, "M", "イ"), + (0xFF73, "M", "ウ"), + (0xFF74, "M", "エ"), + (0xFF75, "M", "オ"), + (0xFF76, "M", "カ"), + (0xFF77, "M", "キ"), + (0xFF78, "M", "ク"), + (0xFF79, "M", "ケ"), + (0xFF7A, "M", "コ"), + (0xFF7B, "M", "サ"), + (0xFF7C, "M", "シ"), + (0xFF7D, "M", "ス"), + (0xFF7E, "M", "セ"), + (0xFF7F, "M", "ソ"), + (0xFF80, "M", "タ"), + (0xFF81, "M", "チ"), + (0xFF82, "M", "ツ"), + (0xFF83, "M", "テ"), + (0xFF84, "M", "ト"), + (0xFF85, "M", "ナ"), + (0xFF86, "M", "ニ"), + (0xFF87, "M", "ヌ"), + (0xFF88, "M", "ネ"), + (0xFF89, "M", "ノ"), + (0xFF8A, "M", "ハ"), + (0xFF8B, "M", "ヒ"), + (0xFF8C, "M", "フ"), + (0xFF8D, "M", "ヘ"), + (0xFF8E, "M", "ホ"), + (0xFF8F, "M", "マ"), + (0xFF90, "M", "ミ"), + (0xFF91, "M", "ム"), + (0xFF92, "M", "メ"), + (0xFF93, "M", "モ"), + (0xFF94, "M", "ヤ"), + (0xFF95, "M", "ユ"), + (0xFF96, "M", "ヨ"), + (0xFF97, "M", "ラ"), + (0xFF98, "M", "リ"), + (0xFF99, "M", "ル"), + (0xFF9A, "M", "レ"), + (0xFF9B, "M", "ロ"), + (0xFF9C, "M", "ワ"), + (0xFF9D, "M", "ン"), + (0xFF9E, "M", "゙"), + (0xFF9F, "M", "゚"), + (0xFFA0, "I"), + (0xFFA1, "M", "ᄀ"), + (0xFFA2, "M", "ᄁ"), + (0xFFA3, "M", "ᆪ"), + (0xFFA4, "M", "ᄂ"), + (0xFFA5, "M", "ᆬ"), + (0xFFA6, "M", "ᆭ"), + (0xFFA7, "M", "ᄃ"), + (0xFFA8, "M", "ᄄ"), + (0xFFA9, "M", "ᄅ"), + (0xFFAA, "M", "ᆰ"), + (0xFFAB, "M", "ᆱ"), + (0xFFAC, "M", "ᆲ"), + (0xFFAD, "M", "ᆳ"), + (0xFFAE, "M", "ᆴ"), + (0xFFAF, "M", "ᆵ"), + (0xFFB0, "M", "ᄚ"), + (0xFFB1, "M", "ᄆ"), + (0xFFB2, "M", "ᄇ"), + (0xFFB3, "M", "ᄈ"), + (0xFFB4, "M", "ᄡ"), + (0xFFB5, "M", "ᄉ"), + (0xFFB6, "M", "ᄊ"), + (0xFFB7, "M", "ᄋ"), + (0xFFB8, "M", "ᄌ"), + (0xFFB9, "M", "ᄍ"), + (0xFFBA, "M", "ᄎ"), + (0xFFBB, "M", "ᄏ"), + (0xFFBC, "M", "ᄐ"), + (0xFFBD, "M", "ᄑ"), + (0xFFBE, "M", "ᄒ"), + (0xFFBF, "X"), + (0xFFC2, "M", "ᅡ"), + (0xFFC3, "M", "ᅢ"), + (0xFFC4, "M", "ᅣ"), + (0xFFC5, "M", "ᅤ"), + (0xFFC6, "M", "ᅥ"), + (0xFFC7, "M", "ᅦ"), + (0xFFC8, "X"), + (0xFFCA, "M", "ᅧ"), + (0xFFCB, "M", "ᅨ"), + (0xFFCC, "M", "ᅩ"), + (0xFFCD, "M", "ᅪ"), + (0xFFCE, "M", "ᅫ"), + (0xFFCF, "M", "ᅬ"), + (0xFFD0, "X"), + (0xFFD2, "M", "ᅭ"), + (0xFFD3, "M", "ᅮ"), + (0xFFD4, "M", "ᅯ"), + (0xFFD5, "M", "ᅰ"), + (0xFFD6, "M", "ᅱ"), + (0xFFD7, "M", "ᅲ"), + (0xFFD8, "X"), + (0xFFDA, "M", "ᅳ"), + (0xFFDB, "M", "ᅴ"), + (0xFFDC, "M", "ᅵ"), + (0xFFDD, "X"), + (0xFFE0, "M", "¢"), + (0xFFE1, "M", "£"), + (0xFFE2, "M", "¬"), + (0xFFE3, "M", " ̄"), + (0xFFE4, "M", "¦"), + (0xFFE5, "M", "¥"), + (0xFFE6, "M", "₩"), + (0xFFE7, "X"), + (0xFFE8, "M", "│"), + (0xFFE9, "M", "←"), + (0xFFEA, "M", "↑"), + (0xFFEB, "M", "→"), + (0xFFEC, "M", "↓"), + (0xFFED, "M", "■"), + (0xFFEE, "M", "○"), + (0xFFEF, "X"), + (0x10000, "V"), + (0x1000C, "X"), + (0x1000D, "V"), + (0x10027, "X"), + (0x10028, "V"), + (0x1003B, "X"), + (0x1003C, "V"), + (0x1003E, "X"), + (0x1003F, "V"), + (0x1004E, "X"), + (0x10050, "V"), + (0x1005E, "X"), + (0x10080, "V"), + (0x100FB, "X"), + (0x10100, "V"), + (0x10103, "X"), + (0x10107, "V"), + (0x10134, "X"), + (0x10137, "V"), + (0x1018F, "X"), + (0x10190, "V"), + (0x1019D, "X"), + (0x101A0, "V"), + (0x101A1, "X"), + (0x101D0, "V"), + (0x101FE, "X"), + (0x10280, "V"), + (0x1029D, "X"), + (0x102A0, "V"), + (0x102D1, "X"), + (0x102E0, "V"), + (0x102FC, "X"), + (0x10300, "V"), + (0x10324, "X"), + (0x1032D, "V"), + (0x1034B, "X"), + (0x10350, "V"), + (0x1037B, "X"), + (0x10380, "V"), + (0x1039E, "X"), + (0x1039F, "V"), + (0x103C4, "X"), + (0x103C8, "V"), + (0x103D6, "X"), + (0x10400, "M", "𐐨"), + (0x10401, "M", "𐐩"), + (0x10402, "M", "𐐪"), + (0x10403, "M", "𐐫"), + (0x10404, "M", "𐐬"), + (0x10405, "M", "𐐭"), + (0x10406, "M", "𐐮"), + (0x10407, "M", "𐐯"), + (0x10408, "M", "𐐰"), + (0x10409, "M", "𐐱"), + (0x1040A, "M", "𐐲"), + (0x1040B, "M", "𐐳"), + (0x1040C, "M", "𐐴"), + (0x1040D, "M", "𐐵"), + (0x1040E, "M", "𐐶"), + (0x1040F, "M", "𐐷"), + (0x10410, "M", "𐐸"), + (0x10411, "M", "𐐹"), + (0x10412, "M", "𐐺"), + (0x10413, "M", "𐐻"), + (0x10414, "M", "𐐼"), + (0x10415, "M", "𐐽"), + (0x10416, "M", "𐐾"), + (0x10417, "M", "𐐿"), + (0x10418, "M", "𐑀"), + (0x10419, "M", "𐑁"), + (0x1041A, "M", "𐑂"), + (0x1041B, "M", "𐑃"), + (0x1041C, "M", "𐑄"), + (0x1041D, "M", "𐑅"), + (0x1041E, "M", "𐑆"), + (0x1041F, "M", "𐑇"), + (0x10420, "M", "𐑈"), + (0x10421, "M", "𐑉"), + (0x10422, "M", "𐑊"), + (0x10423, "M", "𐑋"), + (0x10424, "M", "𐑌"), + (0x10425, "M", "𐑍"), + (0x10426, "M", "𐑎"), + (0x10427, "M", "𐑏"), + (0x10428, "V"), + (0x1049E, "X"), + (0x104A0, "V"), + (0x104AA, "X"), + (0x104B0, "M", "𐓘"), + (0x104B1, "M", "𐓙"), + (0x104B2, "M", "𐓚"), + (0x104B3, "M", "𐓛"), + (0x104B4, "M", "𐓜"), + (0x104B5, "M", "𐓝"), + (0x104B6, "M", "𐓞"), + (0x104B7, "M", "𐓟"), + (0x104B8, "M", "𐓠"), + (0x104B9, "M", "𐓡"), + (0x104BA, "M", "𐓢"), + (0x104BB, "M", "𐓣"), + (0x104BC, "M", "𐓤"), + (0x104BD, "M", "𐓥"), + (0x104BE, "M", "𐓦"), + (0x104BF, "M", "𐓧"), + (0x104C0, "M", "𐓨"), + (0x104C1, "M", "𐓩"), + (0x104C2, "M", "𐓪"), + (0x104C3, "M", "𐓫"), + (0x104C4, "M", "𐓬"), + (0x104C5, "M", "𐓭"), + (0x104C6, "M", "𐓮"), + (0x104C7, "M", "𐓯"), + (0x104C8, "M", "𐓰"), + (0x104C9, "M", "𐓱"), + (0x104CA, "M", "𐓲"), + (0x104CB, "M", "𐓳"), + (0x104CC, "M", "𐓴"), + (0x104CD, "M", "𐓵"), + (0x104CE, "M", "𐓶"), + (0x104CF, "M", "𐓷"), + (0x104D0, "M", "𐓸"), + (0x104D1, "M", "𐓹"), + (0x104D2, "M", "𐓺"), + (0x104D3, "M", "𐓻"), + (0x104D4, "X"), + (0x104D8, "V"), + (0x104FC, "X"), + (0x10500, "V"), + (0x10528, "X"), + (0x10530, "V"), + (0x10564, "X"), + (0x1056F, "V"), + (0x10570, "M", "𐖗"), + (0x10571, "M", "𐖘"), + (0x10572, "M", "𐖙"), + (0x10573, "M", "𐖚"), + (0x10574, "M", "𐖛"), + (0x10575, "M", "𐖜"), + (0x10576, "M", "𐖝"), + (0x10577, "M", "𐖞"), + (0x10578, "M", "𐖟"), + (0x10579, "M", "𐖠"), + (0x1057A, "M", "𐖡"), + (0x1057B, "X"), + (0x1057C, "M", "𐖣"), + (0x1057D, "M", "𐖤"), + (0x1057E, "M", "𐖥"), + (0x1057F, "M", "𐖦"), + (0x10580, "M", "𐖧"), + (0x10581, "M", "𐖨"), + (0x10582, "M", "𐖩"), + (0x10583, "M", "𐖪"), + (0x10584, "M", "𐖫"), + (0x10585, "M", "𐖬"), + (0x10586, "M", "𐖭"), + (0x10587, "M", "𐖮"), + (0x10588, "M", "𐖯"), + (0x10589, "M", "𐖰"), + (0x1058A, "M", "𐖱"), + (0x1058B, "X"), + (0x1058C, "M", "𐖳"), + (0x1058D, "M", "𐖴"), + (0x1058E, "M", "𐖵"), + (0x1058F, "M", "𐖶"), + (0x10590, "M", "𐖷"), + (0x10591, "M", "𐖸"), + (0x10592, "M", "𐖹"), + (0x10593, "X"), + (0x10594, "M", "𐖻"), + (0x10595, "M", "𐖼"), + (0x10596, "X"), + (0x10597, "V"), + (0x105A2, "X"), + (0x105A3, "V"), + (0x105B2, "X"), + (0x105B3, "V"), + (0x105BA, "X"), + (0x105BB, "V"), + (0x105BD, "X"), + (0x105C0, "V"), + (0x105F4, "X"), + (0x10600, "V"), + (0x10737, "X"), + (0x10740, "V"), + (0x10756, "X"), + (0x10760, "V"), + (0x10768, "X"), + (0x10780, "V"), + (0x10781, "M", "ː"), + (0x10782, "M", "ˑ"), + (0x10783, "M", "æ"), + (0x10784, "M", "ʙ"), + (0x10785, "M", "ɓ"), + (0x10786, "X"), + (0x10787, "M", "ʣ"), + (0x10788, "M", "ꭦ"), + (0x10789, "M", "ʥ"), + (0x1078A, "M", "ʤ"), + (0x1078B, "M", "ɖ"), + (0x1078C, "M", "ɗ"), + (0x1078D, "M", "ᶑ"), + (0x1078E, "M", "ɘ"), + (0x1078F, "M", "ɞ"), + (0x10790, "M", "ʩ"), + (0x10791, "M", "ɤ"), + (0x10792, "M", "ɢ"), + (0x10793, "M", "ɠ"), + (0x10794, "M", "ʛ"), + (0x10795, "M", "ħ"), + (0x10796, "M", "ʜ"), + (0x10797, "M", "ɧ"), + (0x10798, "M", "ʄ"), + (0x10799, "M", "ʪ"), + (0x1079A, "M", "ʫ"), + (0x1079B, "M", "ɬ"), + (0x1079C, "M", "𝼄"), + (0x1079D, "M", "ꞎ"), + (0x1079E, "M", "ɮ"), + (0x1079F, "M", "𝼅"), + (0x107A0, "M", "ʎ"), + (0x107A1, "M", "𝼆"), + (0x107A2, "M", "ø"), + (0x107A3, "M", "ɶ"), + (0x107A4, "M", "ɷ"), + (0x107A5, "M", "q"), + (0x107A6, "M", "ɺ"), + (0x107A7, "M", "𝼈"), + (0x107A8, "M", "ɽ"), + (0x107A9, "M", "ɾ"), + (0x107AA, "M", "ʀ"), + (0x107AB, "M", "ʨ"), + (0x107AC, "M", "ʦ"), + (0x107AD, "M", "ꭧ"), + (0x107AE, "M", "ʧ"), + (0x107AF, "M", "ʈ"), + (0x107B0, "M", "ⱱ"), + (0x107B1, "X"), + (0x107B2, "M", "ʏ"), + (0x107B3, "M", "ʡ"), + (0x107B4, "M", "ʢ"), + (0x107B5, "M", "ʘ"), + (0x107B6, "M", "ǀ"), + (0x107B7, "M", "ǁ"), + (0x107B8, "M", "ǂ"), + (0x107B9, "M", "𝼊"), + (0x107BA, "M", "𝼞"), + (0x107BB, "X"), + (0x10800, "V"), + (0x10806, "X"), + (0x10808, "V"), + (0x10809, "X"), + (0x1080A, "V"), + (0x10836, "X"), + (0x10837, "V"), + (0x10839, "X"), + (0x1083C, "V"), + (0x1083D, "X"), + (0x1083F, "V"), + (0x10856, "X"), + (0x10857, "V"), + (0x1089F, "X"), + (0x108A7, "V"), + (0x108B0, "X"), + (0x108E0, "V"), + (0x108F3, "X"), + (0x108F4, "V"), + (0x108F6, "X"), + (0x108FB, "V"), + (0x1091C, "X"), + (0x1091F, "V"), + (0x1093A, "X"), + (0x1093F, "V"), + (0x1095A, "X"), + (0x10980, "V"), + (0x109B8, "X"), + (0x109BC, "V"), + (0x109D0, "X"), + (0x109D2, "V"), + (0x10A04, "X"), + (0x10A05, "V"), + (0x10A07, "X"), + (0x10A0C, "V"), + (0x10A14, "X"), + (0x10A15, "V"), + (0x10A18, "X"), + (0x10A19, "V"), + (0x10A36, "X"), + (0x10A38, "V"), + (0x10A3B, "X"), + (0x10A3F, "V"), + (0x10A49, "X"), + (0x10A50, "V"), + (0x10A59, "X"), + (0x10A60, "V"), + (0x10AA0, "X"), + (0x10AC0, "V"), + (0x10AE7, "X"), + (0x10AEB, "V"), + (0x10AF7, "X"), + (0x10B00, "V"), + (0x10B36, "X"), + (0x10B39, "V"), + (0x10B56, "X"), + (0x10B58, "V"), + (0x10B73, "X"), + (0x10B78, "V"), + (0x10B92, "X"), + (0x10B99, "V"), + (0x10B9D, "X"), + (0x10BA9, "V"), + (0x10BB0, "X"), + (0x10C00, "V"), + (0x10C49, "X"), + (0x10C80, "M", "𐳀"), + (0x10C81, "M", "𐳁"), + (0x10C82, "M", "𐳂"), + (0x10C83, "M", "𐳃"), + (0x10C84, "M", "𐳄"), + (0x10C85, "M", "𐳅"), + (0x10C86, "M", "𐳆"), + (0x10C87, "M", "𐳇"), + (0x10C88, "M", "𐳈"), + (0x10C89, "M", "𐳉"), + (0x10C8A, "M", "𐳊"), + (0x10C8B, "M", "𐳋"), + (0x10C8C, "M", "𐳌"), + (0x10C8D, "M", "𐳍"), + (0x10C8E, "M", "𐳎"), + (0x10C8F, "M", "𐳏"), + (0x10C90, "M", "𐳐"), + (0x10C91, "M", "𐳑"), + (0x10C92, "M", "𐳒"), + (0x10C93, "M", "𐳓"), + (0x10C94, "M", "𐳔"), + (0x10C95, "M", "𐳕"), + (0x10C96, "M", "𐳖"), + (0x10C97, "M", "𐳗"), + (0x10C98, "M", "𐳘"), + (0x10C99, "M", "𐳙"), + (0x10C9A, "M", "𐳚"), + (0x10C9B, "M", "𐳛"), + (0x10C9C, "M", "𐳜"), + (0x10C9D, "M", "𐳝"), + (0x10C9E, "M", "𐳞"), + (0x10C9F, "M", "𐳟"), + (0x10CA0, "M", "𐳠"), + (0x10CA1, "M", "𐳡"), + (0x10CA2, "M", "𐳢"), + (0x10CA3, "M", "𐳣"), + (0x10CA4, "M", "𐳤"), + (0x10CA5, "M", "𐳥"), + (0x10CA6, "M", "𐳦"), + (0x10CA7, "M", "𐳧"), + (0x10CA8, "M", "𐳨"), + (0x10CA9, "M", "𐳩"), + (0x10CAA, "M", "𐳪"), + (0x10CAB, "M", "𐳫"), + (0x10CAC, "M", "𐳬"), + (0x10CAD, "M", "𐳭"), + (0x10CAE, "M", "𐳮"), + (0x10CAF, "M", "𐳯"), + (0x10CB0, "M", "𐳰"), + (0x10CB1, "M", "𐳱"), + (0x10CB2, "M", "𐳲"), + (0x10CB3, "X"), + (0x10CC0, "V"), + (0x10CF3, "X"), + (0x10CFA, "V"), + (0x10D28, "X"), + (0x10D30, "V"), + (0x10D3A, "X"), + (0x10D40, "V"), + (0x10D50, "M", "𐵰"), + (0x10D51, "M", "𐵱"), + (0x10D52, "M", "𐵲"), + (0x10D53, "M", "𐵳"), + (0x10D54, "M", "𐵴"), + (0x10D55, "M", "𐵵"), + (0x10D56, "M", "𐵶"), + (0x10D57, "M", "𐵷"), + (0x10D58, "M", "𐵸"), + (0x10D59, "M", "𐵹"), + (0x10D5A, "M", "𐵺"), + (0x10D5B, "M", "𐵻"), + (0x10D5C, "M", "𐵼"), + (0x10D5D, "M", "𐵽"), + (0x10D5E, "M", "𐵾"), + (0x10D5F, "M", "𐵿"), + (0x10D60, "M", "𐶀"), + (0x10D61, "M", "𐶁"), + (0x10D62, "M", "𐶂"), + (0x10D63, "M", "𐶃"), + (0x10D64, "M", "𐶄"), + (0x10D65, "M", "𐶅"), + (0x10D66, "X"), + (0x10D69, "V"), + (0x10D86, "X"), + (0x10D8E, "V"), + (0x10D90, "X"), + (0x10E60, "V"), + (0x10E7F, "X"), + (0x10E80, "V"), + (0x10EAA, "X"), + (0x10EAB, "V"), + (0x10EAE, "X"), + (0x10EB0, "V"), + (0x10EB2, "X"), + (0x10EC2, "V"), + (0x10EC8, "X"), + (0x10ED0, "V"), + (0x10ED9, "X"), + (0x10EFA, "V"), + (0x10F28, "X"), + (0x10F30, "V"), + (0x10F5A, "X"), + (0x10F70, "V"), + (0x10F8A, "X"), + (0x10FB0, "V"), + (0x10FCC, "X"), + (0x10FE0, "V"), + (0x10FF7, "X"), + (0x11000, "V"), + (0x1104E, "X"), + (0x11052, "V"), + (0x11076, "X"), + (0x1107F, "V"), + (0x110BD, "X"), + (0x110BE, "V"), + (0x110C3, "X"), + (0x110D0, "V"), + (0x110E9, "X"), + (0x110F0, "V"), + (0x110FA, "X"), + (0x11100, "V"), + (0x11135, "X"), + (0x11136, "V"), + (0x11148, "X"), + (0x11150, "V"), + (0x11177, "X"), + (0x11180, "V"), + (0x111E0, "X"), + (0x111E1, "V"), + (0x111F5, "X"), + (0x11200, "V"), + (0x11212, "X"), + (0x11213, "V"), + (0x11242, "X"), + (0x11280, "V"), + (0x11287, "X"), + (0x11288, "V"), + (0x11289, "X"), + (0x1128A, "V"), + (0x1128E, "X"), + (0x1128F, "V"), + (0x1129E, "X"), + (0x1129F, "V"), + (0x112AA, "X"), + (0x112B0, "V"), + (0x112EB, "X"), + (0x112F0, "V"), + (0x112FA, "X"), + (0x11300, "V"), + (0x11304, "X"), + (0x11305, "V"), + (0x1130D, "X"), + (0x1130F, "V"), + (0x11311, "X"), + (0x11313, "V"), + (0x11329, "X"), + (0x1132A, "V"), + (0x11331, "X"), + (0x11332, "V"), + (0x11334, "X"), + (0x11335, "V"), + (0x1133A, "X"), + (0x1133B, "V"), + (0x11345, "X"), + (0x11347, "V"), + (0x11349, "X"), + (0x1134B, "V"), + (0x1134E, "X"), + (0x11350, "V"), + (0x11351, "X"), + (0x11357, "V"), + (0x11358, "X"), + (0x1135D, "V"), + (0x11364, "X"), + (0x11366, "V"), + (0x1136D, "X"), + (0x11370, "V"), + (0x11375, "X"), + (0x11380, "V"), + (0x1138A, "X"), + (0x1138B, "V"), + (0x1138C, "X"), + (0x1138E, "V"), + (0x1138F, "X"), + (0x11390, "V"), + (0x113B6, "X"), + (0x113B7, "V"), + (0x113C1, "X"), + (0x113C2, "V"), + (0x113C3, "X"), + (0x113C5, "V"), + (0x113C6, "X"), + (0x113C7, "V"), + (0x113CB, "X"), + (0x113CC, "V"), + (0x113D6, "X"), + (0x113D7, "V"), + (0x113D9, "X"), + (0x113E1, "V"), + (0x113E3, "X"), + (0x11400, "V"), + (0x1145C, "X"), + (0x1145D, "V"), + (0x11462, "X"), + (0x11480, "V"), + (0x114C8, "X"), + (0x114D0, "V"), + (0x114DA, "X"), + (0x11580, "V"), + (0x115B6, "X"), + (0x115B8, "V"), + (0x115DE, "X"), + (0x11600, "V"), + (0x11645, "X"), + (0x11650, "V"), + (0x1165A, "X"), + (0x11660, "V"), + (0x1166D, "X"), + (0x11680, "V"), + (0x116BA, "X"), + (0x116C0, "V"), + (0x116CA, "X"), + (0x116D0, "V"), + (0x116E4, "X"), + (0x11700, "V"), + (0x1171B, "X"), + (0x1171D, "V"), + (0x1172C, "X"), + (0x11730, "V"), + (0x11747, "X"), + (0x11800, "V"), + (0x1183C, "X"), + (0x118A0, "M", "𑣀"), + (0x118A1, "M", "𑣁"), + (0x118A2, "M", "𑣂"), + (0x118A3, "M", "𑣃"), + (0x118A4, "M", "𑣄"), + (0x118A5, "M", "𑣅"), + (0x118A6, "M", "𑣆"), + (0x118A7, "M", "𑣇"), + (0x118A8, "M", "𑣈"), + (0x118A9, "M", "𑣉"), + (0x118AA, "M", "𑣊"), + (0x118AB, "M", "𑣋"), + (0x118AC, "M", "𑣌"), + (0x118AD, "M", "𑣍"), + (0x118AE, "M", "𑣎"), + (0x118AF, "M", "𑣏"), + (0x118B0, "M", "𑣐"), + (0x118B1, "M", "𑣑"), + (0x118B2, "M", "𑣒"), + (0x118B3, "M", "𑣓"), + (0x118B4, "M", "𑣔"), + (0x118B5, "M", "𑣕"), + (0x118B6, "M", "𑣖"), + (0x118B7, "M", "𑣗"), + (0x118B8, "M", "𑣘"), + (0x118B9, "M", "𑣙"), + (0x118BA, "M", "𑣚"), + (0x118BB, "M", "𑣛"), + (0x118BC, "M", "𑣜"), + (0x118BD, "M", "𑣝"), + (0x118BE, "M", "𑣞"), + (0x118BF, "M", "𑣟"), + (0x118C0, "V"), + (0x118F3, "X"), + (0x118FF, "V"), + (0x11907, "X"), + (0x11909, "V"), + (0x1190A, "X"), + (0x1190C, "V"), + (0x11914, "X"), + (0x11915, "V"), + (0x11917, "X"), + (0x11918, "V"), + (0x11936, "X"), + (0x11937, "V"), + (0x11939, "X"), + (0x1193B, "V"), + (0x11947, "X"), + (0x11950, "V"), + (0x1195A, "X"), + (0x119A0, "V"), + (0x119A8, "X"), + (0x119AA, "V"), + (0x119D8, "X"), + (0x119DA, "V"), + (0x119E5, "X"), + (0x11A00, "V"), + (0x11A48, "X"), + (0x11A50, "V"), + (0x11AA3, "X"), + (0x11AB0, "V"), + (0x11AF9, "X"), + (0x11B00, "V"), + (0x11B0A, "X"), + (0x11B60, "V"), + (0x11B68, "X"), + (0x11BC0, "V"), + (0x11BE2, "X"), + (0x11BF0, "V"), + (0x11BFA, "X"), + (0x11C00, "V"), + (0x11C09, "X"), + (0x11C0A, "V"), + (0x11C37, "X"), + (0x11C38, "V"), + (0x11C46, "X"), + (0x11C50, "V"), + (0x11C6D, "X"), + (0x11C70, "V"), + (0x11C90, "X"), + (0x11C92, "V"), + (0x11CA8, "X"), + (0x11CA9, "V"), + (0x11CB7, "X"), + (0x11D00, "V"), + (0x11D07, "X"), + (0x11D08, "V"), + (0x11D0A, "X"), + (0x11D0B, "V"), + (0x11D37, "X"), + (0x11D3A, "V"), + (0x11D3B, "X"), + (0x11D3C, "V"), + (0x11D3E, "X"), + (0x11D3F, "V"), + (0x11D48, "X"), + (0x11D50, "V"), + (0x11D5A, "X"), + (0x11D60, "V"), + (0x11D66, "X"), + (0x11D67, "V"), + (0x11D69, "X"), + (0x11D6A, "V"), + (0x11D8F, "X"), + (0x11D90, "V"), + (0x11D92, "X"), + (0x11D93, "V"), + (0x11D99, "X"), + (0x11DA0, "V"), + (0x11DAA, "X"), + (0x11DB0, "V"), + (0x11DDC, "X"), + (0x11DE0, "V"), + (0x11DEA, "X"), + (0x11EE0, "V"), + (0x11EF9, "X"), + (0x11F00, "V"), + (0x11F11, "X"), + (0x11F12, "V"), + (0x11F3B, "X"), + (0x11F3E, "V"), + (0x11F5B, "X"), + (0x11FB0, "V"), + (0x11FB1, "X"), + (0x11FC0, "V"), + (0x11FF2, "X"), + (0x11FFF, "V"), + (0x1239A, "X"), + (0x12400, "V"), + (0x1246F, "X"), + (0x12470, "V"), + (0x12475, "X"), + (0x12480, "V"), + (0x12544, "X"), + (0x12F90, "V"), + (0x12FF3, "X"), + (0x13000, "V"), + (0x13430, "X"), + (0x13440, "V"), + (0x13456, "X"), + (0x13460, "V"), + (0x143FB, "X"), + (0x14400, "V"), + (0x14647, "X"), + (0x16100, "V"), + (0x1613A, "X"), + (0x16800, "V"), + (0x16A39, "X"), + (0x16A40, "V"), + (0x16A5F, "X"), + (0x16A60, "V"), + (0x16A6A, "X"), + (0x16A6E, "V"), + (0x16ABF, "X"), + (0x16AC0, "V"), + (0x16ACA, "X"), + (0x16AD0, "V"), + (0x16AEE, "X"), + (0x16AF0, "V"), + (0x16AF6, "X"), + (0x16B00, "V"), + (0x16B46, "X"), + (0x16B50, "V"), + (0x16B5A, "X"), + (0x16B5B, "V"), + (0x16B62, "X"), + (0x16B63, "V"), + (0x16B78, "X"), + (0x16B7D, "V"), + (0x16B90, "X"), + (0x16D40, "V"), + (0x16D7A, "X"), + (0x16E40, "M", "𖹠"), + (0x16E41, "M", "𖹡"), + (0x16E42, "M", "𖹢"), + (0x16E43, "M", "𖹣"), + (0x16E44, "M", "𖹤"), + (0x16E45, "M", "𖹥"), + (0x16E46, "M", "𖹦"), + (0x16E47, "M", "𖹧"), + (0x16E48, "M", "𖹨"), + (0x16E49, "M", "𖹩"), + (0x16E4A, "M", "𖹪"), + (0x16E4B, "M", "𖹫"), + (0x16E4C, "M", "𖹬"), + (0x16E4D, "M", "𖹭"), + (0x16E4E, "M", "𖹮"), + (0x16E4F, "M", "𖹯"), + (0x16E50, "M", "𖹰"), + (0x16E51, "M", "𖹱"), + (0x16E52, "M", "𖹲"), + (0x16E53, "M", "𖹳"), + (0x16E54, "M", "𖹴"), + (0x16E55, "M", "𖹵"), + (0x16E56, "M", "𖹶"), + (0x16E57, "M", "𖹷"), + (0x16E58, "M", "𖹸"), + (0x16E59, "M", "𖹹"), + (0x16E5A, "M", "𖹺"), + (0x16E5B, "M", "𖹻"), + (0x16E5C, "M", "𖹼"), + (0x16E5D, "M", "𖹽"), + (0x16E5E, "M", "𖹾"), + (0x16E5F, "M", "𖹿"), + (0x16E60, "V"), + (0x16E9B, "X"), + (0x16EA0, "M", "𖺻"), + (0x16EA1, "M", "𖺼"), + (0x16EA2, "M", "𖺽"), + (0x16EA3, "M", "𖺾"), + (0x16EA4, "M", "𖺿"), + (0x16EA5, "M", "𖻀"), + (0x16EA6, "M", "𖻁"), + (0x16EA7, "M", "𖻂"), + (0x16EA8, "M", "𖻃"), + (0x16EA9, "M", "𖻄"), + (0x16EAA, "M", "𖻅"), + (0x16EAB, "M", "𖻆"), + (0x16EAC, "M", "𖻇"), + (0x16EAD, "M", "𖻈"), + (0x16EAE, "M", "𖻉"), + (0x16EAF, "M", "𖻊"), + (0x16EB0, "M", "𖻋"), + (0x16EB1, "M", "𖻌"), + (0x16EB2, "M", "𖻍"), + (0x16EB3, "M", "𖻎"), + (0x16EB4, "M", "𖻏"), + (0x16EB5, "M", "𖻐"), + (0x16EB6, "M", "𖻑"), + (0x16EB7, "M", "𖻒"), + (0x16EB8, "M", "𖻓"), + (0x16EB9, "X"), + (0x16EBB, "V"), + (0x16ED4, "X"), + (0x16F00, "V"), + (0x16F4B, "X"), + (0x16F4F, "V"), + (0x16F88, "X"), + (0x16F8F, "V"), + (0x16FA0, "X"), + (0x16FE0, "V"), + (0x16FE5, "X"), + (0x16FF0, "V"), + (0x16FF7, "X"), + (0x17000, "V"), + (0x18CD6, "X"), + (0x18CFF, "V"), + (0x18D1F, "X"), + (0x18D80, "V"), + (0x18DF3, "X"), + (0x1AFF0, "V"), + (0x1AFF4, "X"), + (0x1AFF5, "V"), + (0x1AFFC, "X"), + (0x1AFFD, "V"), + (0x1AFFF, "X"), + (0x1B000, "V"), + (0x1B123, "X"), + (0x1B132, "V"), + (0x1B133, "X"), + (0x1B150, "V"), + (0x1B153, "X"), + (0x1B155, "V"), + (0x1B156, "X"), + (0x1B164, "V"), + (0x1B168, "X"), + (0x1B170, "V"), + (0x1B2FC, "X"), + (0x1BC00, "V"), + (0x1BC6B, "X"), + (0x1BC70, "V"), + (0x1BC7D, "X"), + (0x1BC80, "V"), + (0x1BC89, "X"), + (0x1BC90, "V"), + (0x1BC9A, "X"), + (0x1BC9C, "V"), + (0x1BCA0, "I"), + (0x1BCA4, "X"), + (0x1CC00, "V"), + (0x1CCD6, "M", "a"), + (0x1CCD7, "M", "b"), + (0x1CCD8, "M", "c"), + (0x1CCD9, "M", "d"), + (0x1CCDA, "M", "e"), + (0x1CCDB, "M", "f"), + (0x1CCDC, "M", "g"), + (0x1CCDD, "M", "h"), + (0x1CCDE, "M", "i"), + (0x1CCDF, "M", "j"), + (0x1CCE0, "M", "k"), + (0x1CCE1, "M", "l"), + (0x1CCE2, "M", "m"), + (0x1CCE3, "M", "n"), + (0x1CCE4, "M", "o"), + (0x1CCE5, "M", "p"), + (0x1CCE6, "M", "q"), + (0x1CCE7, "M", "r"), + (0x1CCE8, "M", "s"), + (0x1CCE9, "M", "t"), + (0x1CCEA, "M", "u"), + (0x1CCEB, "M", "v"), + (0x1CCEC, "M", "w"), + (0x1CCED, "M", "x"), + (0x1CCEE, "M", "y"), + (0x1CCEF, "M", "z"), + (0x1CCF0, "M", "0"), + (0x1CCF1, "M", "1"), + (0x1CCF2, "M", "2"), + (0x1CCF3, "M", "3"), + (0x1CCF4, "M", "4"), + (0x1CCF5, "M", "5"), + (0x1CCF6, "M", "6"), + (0x1CCF7, "M", "7"), + (0x1CCF8, "M", "8"), + (0x1CCF9, "M", "9"), + (0x1CCFA, "V"), + (0x1CCFD, "X"), + (0x1CD00, "V"), + (0x1CEB4, "X"), + (0x1CEBA, "V"), + (0x1CED1, "X"), + (0x1CEE0, "V"), + (0x1CEF1, "X"), + (0x1CF00, "V"), + (0x1CF2E, "X"), + (0x1CF30, "V"), + (0x1CF47, "X"), + (0x1CF50, "V"), + (0x1CFC4, "X"), + (0x1D000, "V"), + (0x1D0F6, "X"), + (0x1D100, "V"), + (0x1D127, "X"), + (0x1D129, "V"), + (0x1D15E, "M", "𝅗𝅥"), + (0x1D15F, "M", "𝅘𝅥"), + (0x1D160, "M", "𝅘𝅥𝅮"), + (0x1D161, "M", "𝅘𝅥𝅯"), + (0x1D162, "M", "𝅘𝅥𝅰"), + (0x1D163, "M", "𝅘𝅥𝅱"), + (0x1D164, "M", "𝅘𝅥𝅲"), + (0x1D165, "V"), + (0x1D173, "I"), + (0x1D17B, "V"), + (0x1D1BB, "M", "𝆹𝅥"), + (0x1D1BC, "M", "𝆺𝅥"), + (0x1D1BD, "M", "𝆹𝅥𝅮"), + (0x1D1BE, "M", "𝆺𝅥𝅮"), + (0x1D1BF, "M", "𝆹𝅥𝅯"), + (0x1D1C0, "M", "𝆺𝅥𝅯"), + (0x1D1C1, "V"), + (0x1D1EB, "X"), + (0x1D200, "V"), + (0x1D246, "X"), + (0x1D2C0, "V"), + (0x1D2D4, "X"), + (0x1D2E0, "V"), + (0x1D2F4, "X"), + (0x1D300, "V"), + (0x1D357, "X"), + (0x1D360, "V"), + (0x1D379, "X"), + (0x1D400, "M", "a"), + (0x1D401, "M", "b"), + (0x1D402, "M", "c"), + (0x1D403, "M", "d"), + (0x1D404, "M", "e"), + (0x1D405, "M", "f"), + (0x1D406, "M", "g"), + (0x1D407, "M", "h"), + (0x1D408, "M", "i"), + (0x1D409, "M", "j"), + (0x1D40A, "M", "k"), + (0x1D40B, "M", "l"), + (0x1D40C, "M", "m"), + (0x1D40D, "M", "n"), + (0x1D40E, "M", "o"), + (0x1D40F, "M", "p"), + (0x1D410, "M", "q"), + (0x1D411, "M", "r"), + (0x1D412, "M", "s"), + (0x1D413, "M", "t"), + (0x1D414, "M", "u"), + (0x1D415, "M", "v"), + (0x1D416, "M", "w"), + (0x1D417, "M", "x"), + (0x1D418, "M", "y"), + (0x1D419, "M", "z"), + (0x1D41A, "M", "a"), + (0x1D41B, "M", "b"), + (0x1D41C, "M", "c"), + (0x1D41D, "M", "d"), + (0x1D41E, "M", "e"), + (0x1D41F, "M", "f"), + (0x1D420, "M", "g"), + (0x1D421, "M", "h"), + (0x1D422, "M", "i"), + (0x1D423, "M", "j"), + (0x1D424, "M", "k"), + (0x1D425, "M", "l"), + (0x1D426, "M", "m"), + (0x1D427, "M", "n"), + (0x1D428, "M", "o"), + (0x1D429, "M", "p"), + (0x1D42A, "M", "q"), + (0x1D42B, "M", "r"), + (0x1D42C, "M", "s"), + (0x1D42D, "M", "t"), + (0x1D42E, "M", "u"), + (0x1D42F, "M", "v"), + (0x1D430, "M", "w"), + (0x1D431, "M", "x"), + (0x1D432, "M", "y"), + (0x1D433, "M", "z"), + (0x1D434, "M", "a"), + (0x1D435, "M", "b"), + (0x1D436, "M", "c"), + (0x1D437, "M", "d"), + (0x1D438, "M", "e"), + (0x1D439, "M", "f"), + (0x1D43A, "M", "g"), + (0x1D43B, "M", "h"), + (0x1D43C, "M", "i"), + (0x1D43D, "M", "j"), + (0x1D43E, "M", "k"), + (0x1D43F, "M", "l"), + (0x1D440, "M", "m"), + (0x1D441, "M", "n"), + (0x1D442, "M", "o"), + (0x1D443, "M", "p"), + (0x1D444, "M", "q"), + (0x1D445, "M", "r"), + (0x1D446, "M", "s"), + (0x1D447, "M", "t"), + (0x1D448, "M", "u"), + (0x1D449, "M", "v"), + (0x1D44A, "M", "w"), + (0x1D44B, "M", "x"), + (0x1D44C, "M", "y"), + (0x1D44D, "M", "z"), + (0x1D44E, "M", "a"), + (0x1D44F, "M", "b"), + (0x1D450, "M", "c"), + (0x1D451, "M", "d"), + (0x1D452, "M", "e"), + (0x1D453, "M", "f"), + (0x1D454, "M", "g"), + (0x1D455, "X"), + (0x1D456, "M", "i"), + (0x1D457, "M", "j"), + (0x1D458, "M", "k"), + (0x1D459, "M", "l"), + (0x1D45A, "M", "m"), + (0x1D45B, "M", "n"), + (0x1D45C, "M", "o"), + (0x1D45D, "M", "p"), + (0x1D45E, "M", "q"), + (0x1D45F, "M", "r"), + (0x1D460, "M", "s"), + (0x1D461, "M", "t"), + (0x1D462, "M", "u"), + (0x1D463, "M", "v"), + (0x1D464, "M", "w"), + (0x1D465, "M", "x"), + (0x1D466, "M", "y"), + (0x1D467, "M", "z"), + (0x1D468, "M", "a"), + (0x1D469, "M", "b"), + (0x1D46A, "M", "c"), + (0x1D46B, "M", "d"), + (0x1D46C, "M", "e"), + (0x1D46D, "M", "f"), + (0x1D46E, "M", "g"), + (0x1D46F, "M", "h"), + (0x1D470, "M", "i"), + (0x1D471, "M", "j"), + (0x1D472, "M", "k"), + (0x1D473, "M", "l"), + (0x1D474, "M", "m"), + (0x1D475, "M", "n"), + (0x1D476, "M", "o"), + (0x1D477, "M", "p"), + (0x1D478, "M", "q"), + (0x1D479, "M", "r"), + (0x1D47A, "M", "s"), + (0x1D47B, "M", "t"), + (0x1D47C, "M", "u"), + (0x1D47D, "M", "v"), + (0x1D47E, "M", "w"), + (0x1D47F, "M", "x"), + (0x1D480, "M", "y"), + (0x1D481, "M", "z"), + (0x1D482, "M", "a"), + (0x1D483, "M", "b"), + (0x1D484, "M", "c"), + (0x1D485, "M", "d"), + (0x1D486, "M", "e"), + (0x1D487, "M", "f"), + (0x1D488, "M", "g"), + (0x1D489, "M", "h"), + (0x1D48A, "M", "i"), + (0x1D48B, "M", "j"), + (0x1D48C, "M", "k"), + (0x1D48D, "M", "l"), + (0x1D48E, "M", "m"), + (0x1D48F, "M", "n"), + (0x1D490, "M", "o"), + (0x1D491, "M", "p"), + (0x1D492, "M", "q"), + (0x1D493, "M", "r"), + (0x1D494, "M", "s"), + (0x1D495, "M", "t"), + (0x1D496, "M", "u"), + (0x1D497, "M", "v"), + (0x1D498, "M", "w"), + (0x1D499, "M", "x"), + (0x1D49A, "M", "y"), + (0x1D49B, "M", "z"), + (0x1D49C, "M", "a"), + (0x1D49D, "X"), + (0x1D49E, "M", "c"), + (0x1D49F, "M", "d"), + (0x1D4A0, "X"), + (0x1D4A2, "M", "g"), + (0x1D4A3, "X"), + (0x1D4A5, "M", "j"), + (0x1D4A6, "M", "k"), + (0x1D4A7, "X"), + (0x1D4A9, "M", "n"), + (0x1D4AA, "M", "o"), + (0x1D4AB, "M", "p"), + (0x1D4AC, "M", "q"), + (0x1D4AD, "X"), + (0x1D4AE, "M", "s"), + (0x1D4AF, "M", "t"), + (0x1D4B0, "M", "u"), + (0x1D4B1, "M", "v"), + (0x1D4B2, "M", "w"), + (0x1D4B3, "M", "x"), + (0x1D4B4, "M", "y"), + (0x1D4B5, "M", "z"), + (0x1D4B6, "M", "a"), + (0x1D4B7, "M", "b"), + (0x1D4B8, "M", "c"), + (0x1D4B9, "M", "d"), + (0x1D4BA, "X"), + (0x1D4BB, "M", "f"), + (0x1D4BC, "X"), + (0x1D4BD, "M", "h"), + (0x1D4BE, "M", "i"), + (0x1D4BF, "M", "j"), + (0x1D4C0, "M", "k"), + (0x1D4C1, "M", "l"), + (0x1D4C2, "M", "m"), + (0x1D4C3, "M", "n"), + (0x1D4C4, "X"), + (0x1D4C5, "M", "p"), + (0x1D4C6, "M", "q"), + (0x1D4C7, "M", "r"), + (0x1D4C8, "M", "s"), + (0x1D4C9, "M", "t"), + (0x1D4CA, "M", "u"), + (0x1D4CB, "M", "v"), + (0x1D4CC, "M", "w"), + (0x1D4CD, "M", "x"), + (0x1D4CE, "M", "y"), + (0x1D4CF, "M", "z"), + (0x1D4D0, "M", "a"), + (0x1D4D1, "M", "b"), + (0x1D4D2, "M", "c"), + (0x1D4D3, "M", "d"), + (0x1D4D4, "M", "e"), + (0x1D4D5, "M", "f"), + (0x1D4D6, "M", "g"), + (0x1D4D7, "M", "h"), + (0x1D4D8, "M", "i"), + (0x1D4D9, "M", "j"), + (0x1D4DA, "M", "k"), + (0x1D4DB, "M", "l"), + (0x1D4DC, "M", "m"), + (0x1D4DD, "M", "n"), + (0x1D4DE, "M", "o"), + (0x1D4DF, "M", "p"), + (0x1D4E0, "M", "q"), + (0x1D4E1, "M", "r"), + (0x1D4E2, "M", "s"), + (0x1D4E3, "M", "t"), + (0x1D4E4, "M", "u"), + (0x1D4E5, "M", "v"), + (0x1D4E6, "M", "w"), + (0x1D4E7, "M", "x"), + (0x1D4E8, "M", "y"), + (0x1D4E9, "M", "z"), + (0x1D4EA, "M", "a"), + (0x1D4EB, "M", "b"), + (0x1D4EC, "M", "c"), + (0x1D4ED, "M", "d"), + (0x1D4EE, "M", "e"), + (0x1D4EF, "M", "f"), + (0x1D4F0, "M", "g"), + (0x1D4F1, "M", "h"), + (0x1D4F2, "M", "i"), + (0x1D4F3, "M", "j"), + (0x1D4F4, "M", "k"), + (0x1D4F5, "M", "l"), + (0x1D4F6, "M", "m"), + (0x1D4F7, "M", "n"), + (0x1D4F8, "M", "o"), + (0x1D4F9, "M", "p"), + (0x1D4FA, "M", "q"), + (0x1D4FB, "M", "r"), + (0x1D4FC, "M", "s"), + (0x1D4FD, "M", "t"), + (0x1D4FE, "M", "u"), + (0x1D4FF, "M", "v"), + (0x1D500, "M", "w"), + (0x1D501, "M", "x"), + (0x1D502, "M", "y"), + (0x1D503, "M", "z"), + (0x1D504, "M", "a"), + (0x1D505, "M", "b"), + (0x1D506, "X"), + (0x1D507, "M", "d"), + (0x1D508, "M", "e"), + (0x1D509, "M", "f"), + (0x1D50A, "M", "g"), + (0x1D50B, "X"), + (0x1D50D, "M", "j"), + (0x1D50E, "M", "k"), + (0x1D50F, "M", "l"), + (0x1D510, "M", "m"), + (0x1D511, "M", "n"), + (0x1D512, "M", "o"), + (0x1D513, "M", "p"), + (0x1D514, "M", "q"), + (0x1D515, "X"), + (0x1D516, "M", "s"), + (0x1D517, "M", "t"), + (0x1D518, "M", "u"), + (0x1D519, "M", "v"), + (0x1D51A, "M", "w"), + (0x1D51B, "M", "x"), + (0x1D51C, "M", "y"), + (0x1D51D, "X"), + (0x1D51E, "M", "a"), + (0x1D51F, "M", "b"), + (0x1D520, "M", "c"), + (0x1D521, "M", "d"), + (0x1D522, "M", "e"), + (0x1D523, "M", "f"), + (0x1D524, "M", "g"), + (0x1D525, "M", "h"), + (0x1D526, "M", "i"), + (0x1D527, "M", "j"), + (0x1D528, "M", "k"), + (0x1D529, "M", "l"), + (0x1D52A, "M", "m"), + (0x1D52B, "M", "n"), + (0x1D52C, "M", "o"), + (0x1D52D, "M", "p"), + (0x1D52E, "M", "q"), + (0x1D52F, "M", "r"), + (0x1D530, "M", "s"), + (0x1D531, "M", "t"), + (0x1D532, "M", "u"), + (0x1D533, "M", "v"), + (0x1D534, "M", "w"), + (0x1D535, "M", "x"), + (0x1D536, "M", "y"), + (0x1D537, "M", "z"), + (0x1D538, "M", "a"), + (0x1D539, "M", "b"), + (0x1D53A, "X"), + (0x1D53B, "M", "d"), + (0x1D53C, "M", "e"), + (0x1D53D, "M", "f"), + (0x1D53E, "M", "g"), + (0x1D53F, "X"), + (0x1D540, "M", "i"), + (0x1D541, "M", "j"), + (0x1D542, "M", "k"), + (0x1D543, "M", "l"), + (0x1D544, "M", "m"), + (0x1D545, "X"), + (0x1D546, "M", "o"), + (0x1D547, "X"), + (0x1D54A, "M", "s"), + (0x1D54B, "M", "t"), + (0x1D54C, "M", "u"), + (0x1D54D, "M", "v"), + (0x1D54E, "M", "w"), + (0x1D54F, "M", "x"), + (0x1D550, "M", "y"), + (0x1D551, "X"), + (0x1D552, "M", "a"), + (0x1D553, "M", "b"), + (0x1D554, "M", "c"), + (0x1D555, "M", "d"), + (0x1D556, "M", "e"), + (0x1D557, "M", "f"), + (0x1D558, "M", "g"), + (0x1D559, "M", "h"), + (0x1D55A, "M", "i"), + (0x1D55B, "M", "j"), + (0x1D55C, "M", "k"), + (0x1D55D, "M", "l"), + (0x1D55E, "M", "m"), + (0x1D55F, "M", "n"), + (0x1D560, "M", "o"), + (0x1D561, "M", "p"), + (0x1D562, "M", "q"), + (0x1D563, "M", "r"), + (0x1D564, "M", "s"), + (0x1D565, "M", "t"), + (0x1D566, "M", "u"), + (0x1D567, "M", "v"), + (0x1D568, "M", "w"), + (0x1D569, "M", "x"), + (0x1D56A, "M", "y"), + (0x1D56B, "M", "z"), + (0x1D56C, "M", "a"), + (0x1D56D, "M", "b"), + (0x1D56E, "M", "c"), + (0x1D56F, "M", "d"), + (0x1D570, "M", "e"), + (0x1D571, "M", "f"), + (0x1D572, "M", "g"), + (0x1D573, "M", "h"), + (0x1D574, "M", "i"), + (0x1D575, "M", "j"), + (0x1D576, "M", "k"), + (0x1D577, "M", "l"), + (0x1D578, "M", "m"), + (0x1D579, "M", "n"), + (0x1D57A, "M", "o"), + (0x1D57B, "M", "p"), + (0x1D57C, "M", "q"), + (0x1D57D, "M", "r"), + (0x1D57E, "M", "s"), + (0x1D57F, "M", "t"), + (0x1D580, "M", "u"), + (0x1D581, "M", "v"), + (0x1D582, "M", "w"), + (0x1D583, "M", "x"), + (0x1D584, "M", "y"), + (0x1D585, "M", "z"), + (0x1D586, "M", "a"), + (0x1D587, "M", "b"), + (0x1D588, "M", "c"), + (0x1D589, "M", "d"), + (0x1D58A, "M", "e"), + (0x1D58B, "M", "f"), + (0x1D58C, "M", "g"), + (0x1D58D, "M", "h"), + (0x1D58E, "M", "i"), + (0x1D58F, "M", "j"), + (0x1D590, "M", "k"), + (0x1D591, "M", "l"), + (0x1D592, "M", "m"), + (0x1D593, "M", "n"), + (0x1D594, "M", "o"), + (0x1D595, "M", "p"), + (0x1D596, "M", "q"), + (0x1D597, "M", "r"), + (0x1D598, "M", "s"), + (0x1D599, "M", "t"), + (0x1D59A, "M", "u"), + (0x1D59B, "M", "v"), + (0x1D59C, "M", "w"), + (0x1D59D, "M", "x"), + (0x1D59E, "M", "y"), + (0x1D59F, "M", "z"), + (0x1D5A0, "M", "a"), + (0x1D5A1, "M", "b"), + (0x1D5A2, "M", "c"), + (0x1D5A3, "M", "d"), + (0x1D5A4, "M", "e"), + (0x1D5A5, "M", "f"), + (0x1D5A6, "M", "g"), + (0x1D5A7, "M", "h"), + (0x1D5A8, "M", "i"), + (0x1D5A9, "M", "j"), + (0x1D5AA, "M", "k"), + (0x1D5AB, "M", "l"), + (0x1D5AC, "M", "m"), + (0x1D5AD, "M", "n"), + (0x1D5AE, "M", "o"), + (0x1D5AF, "M", "p"), + (0x1D5B0, "M", "q"), + (0x1D5B1, "M", "r"), + (0x1D5B2, "M", "s"), + (0x1D5B3, "M", "t"), + (0x1D5B4, "M", "u"), + (0x1D5B5, "M", "v"), + (0x1D5B6, "M", "w"), + (0x1D5B7, "M", "x"), + (0x1D5B8, "M", "y"), + (0x1D5B9, "M", "z"), + (0x1D5BA, "M", "a"), + (0x1D5BB, "M", "b"), + (0x1D5BC, "M", "c"), + (0x1D5BD, "M", "d"), + (0x1D5BE, "M", "e"), + (0x1D5BF, "M", "f"), + (0x1D5C0, "M", "g"), + (0x1D5C1, "M", "h"), + (0x1D5C2, "M", "i"), + (0x1D5C3, "M", "j"), + (0x1D5C4, "M", "k"), + (0x1D5C5, "M", "l"), + (0x1D5C6, "M", "m"), + (0x1D5C7, "M", "n"), + (0x1D5C8, "M", "o"), + (0x1D5C9, "M", "p"), + (0x1D5CA, "M", "q"), + (0x1D5CB, "M", "r"), + (0x1D5CC, "M", "s"), + (0x1D5CD, "M", "t"), + (0x1D5CE, "M", "u"), + (0x1D5CF, "M", "v"), + (0x1D5D0, "M", "w"), + (0x1D5D1, "M", "x"), + (0x1D5D2, "M", "y"), + (0x1D5D3, "M", "z"), + (0x1D5D4, "M", "a"), + (0x1D5D5, "M", "b"), + (0x1D5D6, "M", "c"), + (0x1D5D7, "M", "d"), + (0x1D5D8, "M", "e"), + (0x1D5D9, "M", "f"), + (0x1D5DA, "M", "g"), + (0x1D5DB, "M", "h"), + (0x1D5DC, "M", "i"), + (0x1D5DD, "M", "j"), + (0x1D5DE, "M", "k"), + (0x1D5DF, "M", "l"), + (0x1D5E0, "M", "m"), + (0x1D5E1, "M", "n"), + (0x1D5E2, "M", "o"), + (0x1D5E3, "M", "p"), + (0x1D5E4, "M", "q"), + (0x1D5E5, "M", "r"), + (0x1D5E6, "M", "s"), + (0x1D5E7, "M", "t"), + (0x1D5E8, "M", "u"), + (0x1D5E9, "M", "v"), + (0x1D5EA, "M", "w"), + (0x1D5EB, "M", "x"), + (0x1D5EC, "M", "y"), + (0x1D5ED, "M", "z"), + (0x1D5EE, "M", "a"), + (0x1D5EF, "M", "b"), + (0x1D5F0, "M", "c"), + (0x1D5F1, "M", "d"), + (0x1D5F2, "M", "e"), + (0x1D5F3, "M", "f"), + (0x1D5F4, "M", "g"), + (0x1D5F5, "M", "h"), + (0x1D5F6, "M", "i"), + (0x1D5F7, "M", "j"), + (0x1D5F8, "M", "k"), + (0x1D5F9, "M", "l"), + (0x1D5FA, "M", "m"), + (0x1D5FB, "M", "n"), + (0x1D5FC, "M", "o"), + (0x1D5FD, "M", "p"), + (0x1D5FE, "M", "q"), + (0x1D5FF, "M", "r"), + (0x1D600, "M", "s"), + (0x1D601, "M", "t"), + (0x1D602, "M", "u"), + (0x1D603, "M", "v"), + (0x1D604, "M", "w"), + (0x1D605, "M", "x"), + (0x1D606, "M", "y"), + (0x1D607, "M", "z"), + (0x1D608, "M", "a"), + (0x1D609, "M", "b"), + (0x1D60A, "M", "c"), + (0x1D60B, "M", "d"), + (0x1D60C, "M", "e"), + (0x1D60D, "M", "f"), + (0x1D60E, "M", "g"), + (0x1D60F, "M", "h"), + (0x1D610, "M", "i"), + (0x1D611, "M", "j"), + (0x1D612, "M", "k"), + (0x1D613, "M", "l"), + (0x1D614, "M", "m"), + (0x1D615, "M", "n"), + (0x1D616, "M", "o"), + (0x1D617, "M", "p"), + (0x1D618, "M", "q"), + (0x1D619, "M", "r"), + (0x1D61A, "M", "s"), + (0x1D61B, "M", "t"), + (0x1D61C, "M", "u"), + (0x1D61D, "M", "v"), + (0x1D61E, "M", "w"), + (0x1D61F, "M", "x"), + (0x1D620, "M", "y"), + (0x1D621, "M", "z"), + (0x1D622, "M", "a"), + (0x1D623, "M", "b"), + (0x1D624, "M", "c"), + (0x1D625, "M", "d"), + (0x1D626, "M", "e"), + (0x1D627, "M", "f"), + (0x1D628, "M", "g"), + (0x1D629, "M", "h"), + (0x1D62A, "M", "i"), + (0x1D62B, "M", "j"), + (0x1D62C, "M", "k"), + (0x1D62D, "M", "l"), + (0x1D62E, "M", "m"), + (0x1D62F, "M", "n"), + (0x1D630, "M", "o"), + (0x1D631, "M", "p"), + (0x1D632, "M", "q"), + (0x1D633, "M", "r"), + (0x1D634, "M", "s"), + (0x1D635, "M", "t"), + (0x1D636, "M", "u"), + (0x1D637, "M", "v"), + (0x1D638, "M", "w"), + (0x1D639, "M", "x"), + (0x1D63A, "M", "y"), + (0x1D63B, "M", "z"), + (0x1D63C, "M", "a"), + (0x1D63D, "M", "b"), + (0x1D63E, "M", "c"), + (0x1D63F, "M", "d"), + (0x1D640, "M", "e"), + (0x1D641, "M", "f"), + (0x1D642, "M", "g"), + (0x1D643, "M", "h"), + (0x1D644, "M", "i"), + (0x1D645, "M", "j"), + (0x1D646, "M", "k"), + (0x1D647, "M", "l"), + (0x1D648, "M", "m"), + (0x1D649, "M", "n"), + (0x1D64A, "M", "o"), + (0x1D64B, "M", "p"), + (0x1D64C, "M", "q"), + (0x1D64D, "M", "r"), + (0x1D64E, "M", "s"), + (0x1D64F, "M", "t"), + (0x1D650, "M", "u"), + (0x1D651, "M", "v"), + (0x1D652, "M", "w"), + (0x1D653, "M", "x"), + (0x1D654, "M", "y"), + (0x1D655, "M", "z"), + (0x1D656, "M", "a"), + (0x1D657, "M", "b"), + (0x1D658, "M", "c"), + (0x1D659, "M", "d"), + (0x1D65A, "M", "e"), + (0x1D65B, "M", "f"), + (0x1D65C, "M", "g"), + (0x1D65D, "M", "h"), + (0x1D65E, "M", "i"), + (0x1D65F, "M", "j"), + (0x1D660, "M", "k"), + (0x1D661, "M", "l"), + (0x1D662, "M", "m"), + (0x1D663, "M", "n"), + (0x1D664, "M", "o"), + (0x1D665, "M", "p"), + (0x1D666, "M", "q"), + (0x1D667, "M", "r"), + (0x1D668, "M", "s"), + (0x1D669, "M", "t"), + (0x1D66A, "M", "u"), + (0x1D66B, "M", "v"), + (0x1D66C, "M", "w"), + (0x1D66D, "M", "x"), + (0x1D66E, "M", "y"), + (0x1D66F, "M", "z"), + (0x1D670, "M", "a"), + (0x1D671, "M", "b"), + (0x1D672, "M", "c"), + (0x1D673, "M", "d"), + (0x1D674, "M", "e"), + (0x1D675, "M", "f"), + (0x1D676, "M", "g"), + (0x1D677, "M", "h"), + (0x1D678, "M", "i"), + (0x1D679, "M", "j"), + (0x1D67A, "M", "k"), + (0x1D67B, "M", "l"), + (0x1D67C, "M", "m"), + (0x1D67D, "M", "n"), + (0x1D67E, "M", "o"), + (0x1D67F, "M", "p"), + (0x1D680, "M", "q"), + (0x1D681, "M", "r"), + (0x1D682, "M", "s"), + (0x1D683, "M", "t"), + (0x1D684, "M", "u"), + (0x1D685, "M", "v"), + (0x1D686, "M", "w"), + (0x1D687, "M", "x"), + (0x1D688, "M", "y"), + (0x1D689, "M", "z"), + (0x1D68A, "M", "a"), + (0x1D68B, "M", "b"), + (0x1D68C, "M", "c"), + (0x1D68D, "M", "d"), + (0x1D68E, "M", "e"), + (0x1D68F, "M", "f"), + (0x1D690, "M", "g"), + (0x1D691, "M", "h"), + (0x1D692, "M", "i"), + (0x1D693, "M", "j"), + (0x1D694, "M", "k"), + (0x1D695, "M", "l"), + (0x1D696, "M", "m"), + (0x1D697, "M", "n"), + (0x1D698, "M", "o"), + (0x1D699, "M", "p"), + (0x1D69A, "M", "q"), + (0x1D69B, "M", "r"), + (0x1D69C, "M", "s"), + (0x1D69D, "M", "t"), + (0x1D69E, "M", "u"), + (0x1D69F, "M", "v"), + (0x1D6A0, "M", "w"), + (0x1D6A1, "M", "x"), + (0x1D6A2, "M", "y"), + (0x1D6A3, "M", "z"), + (0x1D6A4, "M", "ı"), + (0x1D6A5, "M", "ȷ"), + (0x1D6A6, "X"), + (0x1D6A8, "M", "α"), + (0x1D6A9, "M", "β"), + (0x1D6AA, "M", "γ"), + (0x1D6AB, "M", "δ"), + (0x1D6AC, "M", "ε"), + (0x1D6AD, "M", "ζ"), + (0x1D6AE, "M", "η"), + (0x1D6AF, "M", "θ"), + (0x1D6B0, "M", "ι"), + (0x1D6B1, "M", "κ"), + (0x1D6B2, "M", "λ"), + (0x1D6B3, "M", "μ"), + (0x1D6B4, "M", "ν"), + (0x1D6B5, "M", "ξ"), + (0x1D6B6, "M", "ο"), + (0x1D6B7, "M", "π"), + (0x1D6B8, "M", "ρ"), + (0x1D6B9, "M", "θ"), + (0x1D6BA, "M", "σ"), + (0x1D6BB, "M", "τ"), + (0x1D6BC, "M", "υ"), + (0x1D6BD, "M", "φ"), + (0x1D6BE, "M", "χ"), + (0x1D6BF, "M", "ψ"), + (0x1D6C0, "M", "ω"), + (0x1D6C1, "M", "∇"), + (0x1D6C2, "M", "α"), + (0x1D6C3, "M", "β"), + (0x1D6C4, "M", "γ"), + (0x1D6C5, "M", "δ"), + (0x1D6C6, "M", "ε"), + (0x1D6C7, "M", "ζ"), + (0x1D6C8, "M", "η"), + (0x1D6C9, "M", "θ"), + (0x1D6CA, "M", "ι"), + (0x1D6CB, "M", "κ"), + (0x1D6CC, "M", "λ"), + (0x1D6CD, "M", "μ"), + (0x1D6CE, "M", "ν"), + (0x1D6CF, "M", "ξ"), + (0x1D6D0, "M", "ο"), + (0x1D6D1, "M", "π"), + (0x1D6D2, "M", "ρ"), + (0x1D6D3, "M", "σ"), + (0x1D6D5, "M", "τ"), + (0x1D6D6, "M", "υ"), + (0x1D6D7, "M", "φ"), + (0x1D6D8, "M", "χ"), + (0x1D6D9, "M", "ψ"), + (0x1D6DA, "M", "ω"), + (0x1D6DB, "M", "∂"), + (0x1D6DC, "M", "ε"), + (0x1D6DD, "M", "θ"), + (0x1D6DE, "M", "κ"), + (0x1D6DF, "M", "φ"), + (0x1D6E0, "M", "ρ"), + (0x1D6E1, "M", "π"), + (0x1D6E2, "M", "α"), + (0x1D6E3, "M", "β"), + (0x1D6E4, "M", "γ"), + (0x1D6E5, "M", "δ"), + (0x1D6E6, "M", "ε"), + (0x1D6E7, "M", "ζ"), + (0x1D6E8, "M", "η"), + (0x1D6E9, "M", "θ"), + (0x1D6EA, "M", "ι"), + (0x1D6EB, "M", "κ"), + (0x1D6EC, "M", "λ"), + (0x1D6ED, "M", "μ"), + (0x1D6EE, "M", "ν"), + (0x1D6EF, "M", "ξ"), + (0x1D6F0, "M", "ο"), + (0x1D6F1, "M", "π"), + (0x1D6F2, "M", "ρ"), + (0x1D6F3, "M", "θ"), + (0x1D6F4, "M", "σ"), + (0x1D6F5, "M", "τ"), + (0x1D6F6, "M", "υ"), + (0x1D6F7, "M", "φ"), + (0x1D6F8, "M", "χ"), + (0x1D6F9, "M", "ψ"), + (0x1D6FA, "M", "ω"), + (0x1D6FB, "M", "∇"), + (0x1D6FC, "M", "α"), + (0x1D6FD, "M", "β"), + (0x1D6FE, "M", "γ"), + (0x1D6FF, "M", "δ"), + (0x1D700, "M", "ε"), + (0x1D701, "M", "ζ"), + (0x1D702, "M", "η"), + (0x1D703, "M", "θ"), + (0x1D704, "M", "ι"), + (0x1D705, "M", "κ"), + (0x1D706, "M", "λ"), + (0x1D707, "M", "μ"), + (0x1D708, "M", "ν"), + (0x1D709, "M", "ξ"), + (0x1D70A, "M", "ο"), + (0x1D70B, "M", "π"), + (0x1D70C, "M", "ρ"), + (0x1D70D, "M", "σ"), + (0x1D70F, "M", "τ"), + (0x1D710, "M", "υ"), + (0x1D711, "M", "φ"), + (0x1D712, "M", "χ"), + (0x1D713, "M", "ψ"), + (0x1D714, "M", "ω"), + (0x1D715, "M", "∂"), + (0x1D716, "M", "ε"), + (0x1D717, "M", "θ"), + (0x1D718, "M", "κ"), + (0x1D719, "M", "φ"), + (0x1D71A, "M", "ρ"), + (0x1D71B, "M", "π"), + (0x1D71C, "M", "α"), + (0x1D71D, "M", "β"), + (0x1D71E, "M", "γ"), + (0x1D71F, "M", "δ"), + (0x1D720, "M", "ε"), + (0x1D721, "M", "ζ"), + (0x1D722, "M", "η"), + (0x1D723, "M", "θ"), + (0x1D724, "M", "ι"), + (0x1D725, "M", "κ"), + (0x1D726, "M", "λ"), + (0x1D727, "M", "μ"), + (0x1D728, "M", "ν"), + (0x1D729, "M", "ξ"), + (0x1D72A, "M", "ο"), + (0x1D72B, "M", "π"), + (0x1D72C, "M", "ρ"), + (0x1D72D, "M", "θ"), + (0x1D72E, "M", "σ"), + (0x1D72F, "M", "τ"), + (0x1D730, "M", "υ"), + (0x1D731, "M", "φ"), + (0x1D732, "M", "χ"), + (0x1D733, "M", "ψ"), + (0x1D734, "M", "ω"), + (0x1D735, "M", "∇"), + (0x1D736, "M", "α"), + (0x1D737, "M", "β"), + (0x1D738, "M", "γ"), + (0x1D739, "M", "δ"), + (0x1D73A, "M", "ε"), + (0x1D73B, "M", "ζ"), + (0x1D73C, "M", "η"), + (0x1D73D, "M", "θ"), + (0x1D73E, "M", "ι"), + (0x1D73F, "M", "κ"), + (0x1D740, "M", "λ"), + (0x1D741, "M", "μ"), + (0x1D742, "M", "ν"), + (0x1D743, "M", "ξ"), + (0x1D744, "M", "ο"), + (0x1D745, "M", "π"), + (0x1D746, "M", "ρ"), + (0x1D747, "M", "σ"), + (0x1D749, "M", "τ"), + (0x1D74A, "M", "υ"), + (0x1D74B, "M", "φ"), + (0x1D74C, "M", "χ"), + (0x1D74D, "M", "ψ"), + (0x1D74E, "M", "ω"), + (0x1D74F, "M", "∂"), + (0x1D750, "M", "ε"), + (0x1D751, "M", "θ"), + (0x1D752, "M", "κ"), + (0x1D753, "M", "φ"), + (0x1D754, "M", "ρ"), + (0x1D755, "M", "π"), + (0x1D756, "M", "α"), + (0x1D757, "M", "β"), + (0x1D758, "M", "γ"), + (0x1D759, "M", "δ"), + (0x1D75A, "M", "ε"), + (0x1D75B, "M", "ζ"), + (0x1D75C, "M", "η"), + (0x1D75D, "M", "θ"), + (0x1D75E, "M", "ι"), + (0x1D75F, "M", "κ"), + (0x1D760, "M", "λ"), + (0x1D761, "M", "μ"), + (0x1D762, "M", "ν"), + (0x1D763, "M", "ξ"), + (0x1D764, "M", "ο"), + (0x1D765, "M", "π"), + (0x1D766, "M", "ρ"), + (0x1D767, "M", "θ"), + (0x1D768, "M", "σ"), + (0x1D769, "M", "τ"), + (0x1D76A, "M", "υ"), + (0x1D76B, "M", "φ"), + (0x1D76C, "M", "χ"), + (0x1D76D, "M", "ψ"), + (0x1D76E, "M", "ω"), + (0x1D76F, "M", "∇"), + (0x1D770, "M", "α"), + (0x1D771, "M", "β"), + (0x1D772, "M", "γ"), + (0x1D773, "M", "δ"), + (0x1D774, "M", "ε"), + (0x1D775, "M", "ζ"), + (0x1D776, "M", "η"), + (0x1D777, "M", "θ"), + (0x1D778, "M", "ι"), + (0x1D779, "M", "κ"), + (0x1D77A, "M", "λ"), + (0x1D77B, "M", "μ"), + (0x1D77C, "M", "ν"), + (0x1D77D, "M", "ξ"), + (0x1D77E, "M", "ο"), + (0x1D77F, "M", "π"), + (0x1D780, "M", "ρ"), + (0x1D781, "M", "σ"), + (0x1D783, "M", "τ"), + (0x1D784, "M", "υ"), + (0x1D785, "M", "φ"), + (0x1D786, "M", "χ"), + (0x1D787, "M", "ψ"), + (0x1D788, "M", "ω"), + (0x1D789, "M", "∂"), + (0x1D78A, "M", "ε"), + (0x1D78B, "M", "θ"), + (0x1D78C, "M", "κ"), + (0x1D78D, "M", "φ"), + (0x1D78E, "M", "ρ"), + (0x1D78F, "M", "π"), + (0x1D790, "M", "α"), + (0x1D791, "M", "β"), + (0x1D792, "M", "γ"), + (0x1D793, "M", "δ"), + (0x1D794, "M", "ε"), + (0x1D795, "M", "ζ"), + (0x1D796, "M", "η"), + (0x1D797, "M", "θ"), + (0x1D798, "M", "ι"), + (0x1D799, "M", "κ"), + (0x1D79A, "M", "λ"), + (0x1D79B, "M", "μ"), + (0x1D79C, "M", "ν"), + (0x1D79D, "M", "ξ"), + (0x1D79E, "M", "ο"), + (0x1D79F, "M", "π"), + (0x1D7A0, "M", "ρ"), + (0x1D7A1, "M", "θ"), + (0x1D7A2, "M", "σ"), + (0x1D7A3, "M", "τ"), + (0x1D7A4, "M", "υ"), + (0x1D7A5, "M", "φ"), + (0x1D7A6, "M", "χ"), + (0x1D7A7, "M", "ψ"), + (0x1D7A8, "M", "ω"), + (0x1D7A9, "M", "∇"), + (0x1D7AA, "M", "α"), + (0x1D7AB, "M", "β"), + (0x1D7AC, "M", "γ"), + (0x1D7AD, "M", "δ"), + (0x1D7AE, "M", "ε"), + (0x1D7AF, "M", "ζ"), + (0x1D7B0, "M", "η"), + (0x1D7B1, "M", "θ"), + (0x1D7B2, "M", "ι"), + (0x1D7B3, "M", "κ"), + (0x1D7B4, "M", "λ"), + (0x1D7B5, "M", "μ"), + (0x1D7B6, "M", "ν"), + (0x1D7B7, "M", "ξ"), + (0x1D7B8, "M", "ο"), + (0x1D7B9, "M", "π"), + (0x1D7BA, "M", "ρ"), + (0x1D7BB, "M", "σ"), + (0x1D7BD, "M", "τ"), + (0x1D7BE, "M", "υ"), + (0x1D7BF, "M", "φ"), + (0x1D7C0, "M", "χ"), + (0x1D7C1, "M", "ψ"), + (0x1D7C2, "M", "ω"), + (0x1D7C3, "M", "∂"), + (0x1D7C4, "M", "ε"), + (0x1D7C5, "M", "θ"), + (0x1D7C6, "M", "κ"), + (0x1D7C7, "M", "φ"), + (0x1D7C8, "M", "ρ"), + (0x1D7C9, "M", "π"), + (0x1D7CA, "M", "ϝ"), + (0x1D7CC, "X"), + (0x1D7CE, "M", "0"), + (0x1D7CF, "M", "1"), + (0x1D7D0, "M", "2"), + (0x1D7D1, "M", "3"), + (0x1D7D2, "M", "4"), + (0x1D7D3, "M", "5"), + (0x1D7D4, "M", "6"), + (0x1D7D5, "M", "7"), + (0x1D7D6, "M", "8"), + (0x1D7D7, "M", "9"), + (0x1D7D8, "M", "0"), + (0x1D7D9, "M", "1"), + (0x1D7DA, "M", "2"), + (0x1D7DB, "M", "3"), + (0x1D7DC, "M", "4"), + (0x1D7DD, "M", "5"), + (0x1D7DE, "M", "6"), + (0x1D7DF, "M", "7"), + (0x1D7E0, "M", "8"), + (0x1D7E1, "M", "9"), + (0x1D7E2, "M", "0"), + (0x1D7E3, "M", "1"), + (0x1D7E4, "M", "2"), + (0x1D7E5, "M", "3"), + (0x1D7E6, "M", "4"), + (0x1D7E7, "M", "5"), + (0x1D7E8, "M", "6"), + (0x1D7E9, "M", "7"), + (0x1D7EA, "M", "8"), + (0x1D7EB, "M", "9"), + (0x1D7EC, "M", "0"), + (0x1D7ED, "M", "1"), + (0x1D7EE, "M", "2"), + (0x1D7EF, "M", "3"), + (0x1D7F0, "M", "4"), + (0x1D7F1, "M", "5"), + (0x1D7F2, "M", "6"), + (0x1D7F3, "M", "7"), + (0x1D7F4, "M", "8"), + (0x1D7F5, "M", "9"), + (0x1D7F6, "M", "0"), + (0x1D7F7, "M", "1"), + (0x1D7F8, "M", "2"), + (0x1D7F9, "M", "3"), + (0x1D7FA, "M", "4"), + (0x1D7FB, "M", "5"), + (0x1D7FC, "M", "6"), + (0x1D7FD, "M", "7"), + (0x1D7FE, "M", "8"), + (0x1D7FF, "M", "9"), + (0x1D800, "V"), + (0x1DA8C, "X"), + (0x1DA9B, "V"), + (0x1DAA0, "X"), + (0x1DAA1, "V"), + (0x1DAB0, "X"), + (0x1DF00, "V"), + (0x1DF1F, "X"), + (0x1DF25, "V"), + (0x1DF2B, "X"), + (0x1E000, "V"), + (0x1E007, "X"), + (0x1E008, "V"), + (0x1E019, "X"), + (0x1E01B, "V"), + (0x1E022, "X"), + (0x1E023, "V"), + (0x1E025, "X"), + (0x1E026, "V"), + (0x1E02B, "X"), + (0x1E030, "M", "а"), + (0x1E031, "M", "б"), + (0x1E032, "M", "в"), + (0x1E033, "M", "г"), + (0x1E034, "M", "д"), + (0x1E035, "M", "е"), + (0x1E036, "M", "ж"), + (0x1E037, "M", "з"), + (0x1E038, "M", "и"), + (0x1E039, "M", "к"), + (0x1E03A, "M", "л"), + (0x1E03B, "M", "м"), + (0x1E03C, "M", "о"), + (0x1E03D, "M", "п"), + (0x1E03E, "M", "р"), + (0x1E03F, "M", "с"), + (0x1E040, "M", "т"), + (0x1E041, "M", "у"), + (0x1E042, "M", "ф"), + (0x1E043, "M", "х"), + (0x1E044, "M", "ц"), + (0x1E045, "M", "ч"), + (0x1E046, "M", "ш"), + (0x1E047, "M", "ы"), + (0x1E048, "M", "э"), + (0x1E049, "M", "ю"), + (0x1E04A, "M", "ꚉ"), + (0x1E04B, "M", "ә"), + (0x1E04C, "M", "і"), + (0x1E04D, "M", "ј"), + (0x1E04E, "M", "ө"), + (0x1E04F, "M", "ү"), + (0x1E050, "M", "ӏ"), + (0x1E051, "M", "а"), + (0x1E052, "M", "б"), + (0x1E053, "M", "в"), + (0x1E054, "M", "г"), + (0x1E055, "M", "д"), + (0x1E056, "M", "е"), + (0x1E057, "M", "ж"), + (0x1E058, "M", "з"), + (0x1E059, "M", "и"), + (0x1E05A, "M", "к"), + (0x1E05B, "M", "л"), + (0x1E05C, "M", "о"), + (0x1E05D, "M", "п"), + (0x1E05E, "M", "с"), + (0x1E05F, "M", "у"), + (0x1E060, "M", "ф"), + (0x1E061, "M", "х"), + (0x1E062, "M", "ц"), + (0x1E063, "M", "ч"), + (0x1E064, "M", "ш"), + (0x1E065, "M", "ъ"), + (0x1E066, "M", "ы"), + (0x1E067, "M", "ґ"), + (0x1E068, "M", "і"), + (0x1E069, "M", "ѕ"), + (0x1E06A, "M", "џ"), + (0x1E06B, "M", "ҫ"), + (0x1E06C, "M", "ꙑ"), + (0x1E06D, "M", "ұ"), + (0x1E06E, "X"), + (0x1E08F, "V"), + (0x1E090, "X"), + (0x1E100, "V"), + (0x1E12D, "X"), + (0x1E130, "V"), + (0x1E13E, "X"), + (0x1E140, "V"), + (0x1E14A, "X"), + (0x1E14E, "V"), + (0x1E150, "X"), + (0x1E290, "V"), + (0x1E2AF, "X"), + (0x1E2C0, "V"), + (0x1E2FA, "X"), + (0x1E2FF, "V"), + (0x1E300, "X"), + (0x1E4D0, "V"), + (0x1E4FA, "X"), + (0x1E5D0, "V"), + (0x1E5FB, "X"), + (0x1E5FF, "V"), + (0x1E600, "X"), + (0x1E6C0, "V"), + (0x1E6DF, "X"), + (0x1E6E0, "V"), + (0x1E6F6, "X"), + (0x1E6FE, "V"), + (0x1E700, "X"), + (0x1E7E0, "V"), + (0x1E7E7, "X"), + (0x1E7E8, "V"), + (0x1E7EC, "X"), + (0x1E7ED, "V"), + (0x1E7EF, "X"), + (0x1E7F0, "V"), + (0x1E7FF, "X"), + (0x1E800, "V"), + (0x1E8C5, "X"), + (0x1E8C7, "V"), + (0x1E8D7, "X"), + (0x1E900, "M", "𞤢"), + (0x1E901, "M", "𞤣"), + (0x1E902, "M", "𞤤"), + (0x1E903, "M", "𞤥"), + (0x1E904, "M", "𞤦"), + (0x1E905, "M", "𞤧"), + (0x1E906, "M", "𞤨"), + (0x1E907, "M", "𞤩"), + (0x1E908, "M", "𞤪"), + (0x1E909, "M", "𞤫"), + (0x1E90A, "M", "𞤬"), + (0x1E90B, "M", "𞤭"), + (0x1E90C, "M", "𞤮"), + (0x1E90D, "M", "𞤯"), + (0x1E90E, "M", "𞤰"), + (0x1E90F, "M", "𞤱"), + (0x1E910, "M", "𞤲"), + (0x1E911, "M", "𞤳"), + (0x1E912, "M", "𞤴"), + (0x1E913, "M", "𞤵"), + (0x1E914, "M", "𞤶"), + (0x1E915, "M", "𞤷"), + (0x1E916, "M", "𞤸"), + (0x1E917, "M", "𞤹"), + (0x1E918, "M", "𞤺"), + (0x1E919, "M", "𞤻"), + (0x1E91A, "M", "𞤼"), + (0x1E91B, "M", "𞤽"), + (0x1E91C, "M", "𞤾"), + (0x1E91D, "M", "𞤿"), + (0x1E91E, "M", "𞥀"), + (0x1E91F, "M", "𞥁"), + (0x1E920, "M", "𞥂"), + (0x1E921, "M", "𞥃"), + (0x1E922, "V"), + (0x1E94C, "X"), + (0x1E950, "V"), + (0x1E95A, "X"), + (0x1E95E, "V"), + (0x1E960, "X"), + (0x1EC71, "V"), + (0x1ECB5, "X"), + (0x1ED01, "V"), + (0x1ED3E, "X"), + (0x1EE00, "M", "ا"), + (0x1EE01, "M", "ب"), + (0x1EE02, "M", "ج"), + (0x1EE03, "M", "د"), + (0x1EE04, "X"), + (0x1EE05, "M", "و"), + (0x1EE06, "M", "ز"), + (0x1EE07, "M", "ح"), + (0x1EE08, "M", "ط"), + (0x1EE09, "M", "ي"), + (0x1EE0A, "M", "ك"), + (0x1EE0B, "M", "ل"), + (0x1EE0C, "M", "م"), + (0x1EE0D, "M", "ن"), + (0x1EE0E, "M", "س"), + (0x1EE0F, "M", "ع"), + (0x1EE10, "M", "ف"), + (0x1EE11, "M", "ص"), + (0x1EE12, "M", "ق"), + (0x1EE13, "M", "ر"), + (0x1EE14, "M", "ش"), + (0x1EE15, "M", "ت"), + (0x1EE16, "M", "ث"), + (0x1EE17, "M", "خ"), + (0x1EE18, "M", "ذ"), + (0x1EE19, "M", "ض"), + (0x1EE1A, "M", "ظ"), + (0x1EE1B, "M", "غ"), + (0x1EE1C, "M", "ٮ"), + (0x1EE1D, "M", "ں"), + (0x1EE1E, "M", "ڡ"), + (0x1EE1F, "M", "ٯ"), + (0x1EE20, "X"), + (0x1EE21, "M", "ب"), + (0x1EE22, "M", "ج"), + (0x1EE23, "X"), + (0x1EE24, "M", "ه"), + (0x1EE25, "X"), + (0x1EE27, "M", "ح"), + (0x1EE28, "X"), + (0x1EE29, "M", "ي"), + (0x1EE2A, "M", "ك"), + (0x1EE2B, "M", "ل"), + (0x1EE2C, "M", "م"), + (0x1EE2D, "M", "ن"), + (0x1EE2E, "M", "س"), + (0x1EE2F, "M", "ع"), + (0x1EE30, "M", "ف"), + (0x1EE31, "M", "ص"), + (0x1EE32, "M", "ق"), + (0x1EE33, "X"), + (0x1EE34, "M", "ش"), + (0x1EE35, "M", "ت"), + (0x1EE36, "M", "ث"), + (0x1EE37, "M", "خ"), + (0x1EE38, "X"), + (0x1EE39, "M", "ض"), + (0x1EE3A, "X"), + (0x1EE3B, "M", "غ"), + (0x1EE3C, "X"), + (0x1EE42, "M", "ج"), + (0x1EE43, "X"), + (0x1EE47, "M", "ح"), + (0x1EE48, "X"), + (0x1EE49, "M", "ي"), + (0x1EE4A, "X"), + (0x1EE4B, "M", "ل"), + (0x1EE4C, "X"), + (0x1EE4D, "M", "ن"), + (0x1EE4E, "M", "س"), + (0x1EE4F, "M", "ع"), + (0x1EE50, "X"), + (0x1EE51, "M", "ص"), + (0x1EE52, "M", "ق"), + (0x1EE53, "X"), + (0x1EE54, "M", "ش"), + (0x1EE55, "X"), + (0x1EE57, "M", "خ"), + (0x1EE58, "X"), + (0x1EE59, "M", "ض"), + (0x1EE5A, "X"), + (0x1EE5B, "M", "غ"), + (0x1EE5C, "X"), + (0x1EE5D, "M", "ں"), + (0x1EE5E, "X"), + (0x1EE5F, "M", "ٯ"), + (0x1EE60, "X"), + (0x1EE61, "M", "ب"), + (0x1EE62, "M", "ج"), + (0x1EE63, "X"), + (0x1EE64, "M", "ه"), + (0x1EE65, "X"), + (0x1EE67, "M", "ح"), + (0x1EE68, "M", "ط"), + (0x1EE69, "M", "ي"), + (0x1EE6A, "M", "ك"), + (0x1EE6B, "X"), + (0x1EE6C, "M", "م"), + (0x1EE6D, "M", "ن"), + (0x1EE6E, "M", "س"), + (0x1EE6F, "M", "ع"), + (0x1EE70, "M", "ف"), + (0x1EE71, "M", "ص"), + (0x1EE72, "M", "ق"), + (0x1EE73, "X"), + (0x1EE74, "M", "ش"), + (0x1EE75, "M", "ت"), + (0x1EE76, "M", "ث"), + (0x1EE77, "M", "خ"), + (0x1EE78, "X"), + (0x1EE79, "M", "ض"), + (0x1EE7A, "M", "ظ"), + (0x1EE7B, "M", "غ"), + (0x1EE7C, "M", "ٮ"), + (0x1EE7D, "X"), + (0x1EE7E, "M", "ڡ"), + (0x1EE7F, "X"), + (0x1EE80, "M", "ا"), + (0x1EE81, "M", "ب"), + (0x1EE82, "M", "ج"), + (0x1EE83, "M", "د"), + (0x1EE84, "M", "ه"), + (0x1EE85, "M", "و"), + (0x1EE86, "M", "ز"), + (0x1EE87, "M", "ح"), + (0x1EE88, "M", "ط"), + (0x1EE89, "M", "ي"), + (0x1EE8A, "X"), + (0x1EE8B, "M", "ل"), + (0x1EE8C, "M", "م"), + (0x1EE8D, "M", "ن"), + (0x1EE8E, "M", "س"), + (0x1EE8F, "M", "ع"), + (0x1EE90, "M", "ف"), + (0x1EE91, "M", "ص"), + (0x1EE92, "M", "ق"), + (0x1EE93, "M", "ر"), + (0x1EE94, "M", "ش"), + (0x1EE95, "M", "ت"), + (0x1EE96, "M", "ث"), + (0x1EE97, "M", "خ"), + (0x1EE98, "M", "ذ"), + (0x1EE99, "M", "ض"), + (0x1EE9A, "M", "ظ"), + (0x1EE9B, "M", "غ"), + (0x1EE9C, "X"), + (0x1EEA1, "M", "ب"), + (0x1EEA2, "M", "ج"), + (0x1EEA3, "M", "د"), + (0x1EEA4, "X"), + (0x1EEA5, "M", "و"), + (0x1EEA6, "M", "ز"), + (0x1EEA7, "M", "ح"), + (0x1EEA8, "M", "ط"), + (0x1EEA9, "M", "ي"), + (0x1EEAA, "X"), + (0x1EEAB, "M", "ل"), + (0x1EEAC, "M", "م"), + (0x1EEAD, "M", "ن"), + (0x1EEAE, "M", "س"), + (0x1EEAF, "M", "ع"), + (0x1EEB0, "M", "ف"), + (0x1EEB1, "M", "ص"), + (0x1EEB2, "M", "ق"), + (0x1EEB3, "M", "ر"), + (0x1EEB4, "M", "ش"), + (0x1EEB5, "M", "ت"), + (0x1EEB6, "M", "ث"), + (0x1EEB7, "M", "خ"), + (0x1EEB8, "M", "ذ"), + (0x1EEB9, "M", "ض"), + (0x1EEBA, "M", "ظ"), + (0x1EEBB, "M", "غ"), + (0x1EEBC, "X"), + (0x1EEF0, "V"), + (0x1EEF2, "X"), + (0x1F000, "V"), + (0x1F02C, "X"), + (0x1F030, "V"), + (0x1F094, "X"), + (0x1F0A0, "V"), + (0x1F0AF, "X"), + (0x1F0B1, "V"), + (0x1F0C0, "X"), + (0x1F0C1, "V"), + (0x1F0D0, "X"), + (0x1F0D1, "V"), + (0x1F0F6, "X"), + (0x1F101, "M", "0,"), + (0x1F102, "M", "1,"), + (0x1F103, "M", "2,"), + (0x1F104, "M", "3,"), + (0x1F105, "M", "4,"), + (0x1F106, "M", "5,"), + (0x1F107, "M", "6,"), + (0x1F108, "M", "7,"), + (0x1F109, "M", "8,"), + (0x1F10A, "M", "9,"), + (0x1F10B, "V"), + (0x1F110, "M", "(a)"), + (0x1F111, "M", "(b)"), + (0x1F112, "M", "(c)"), + (0x1F113, "M", "(d)"), + (0x1F114, "M", "(e)"), + (0x1F115, "M", "(f)"), + (0x1F116, "M", "(g)"), + (0x1F117, "M", "(h)"), + (0x1F118, "M", "(i)"), + (0x1F119, "M", "(j)"), + (0x1F11A, "M", "(k)"), + (0x1F11B, "M", "(l)"), + (0x1F11C, "M", "(m)"), + (0x1F11D, "M", "(n)"), + (0x1F11E, "M", "(o)"), + (0x1F11F, "M", "(p)"), + (0x1F120, "M", "(q)"), + (0x1F121, "M", "(r)"), + (0x1F122, "M", "(s)"), + (0x1F123, "M", "(t)"), + (0x1F124, "M", "(u)"), + (0x1F125, "M", "(v)"), + (0x1F126, "M", "(w)"), + (0x1F127, "M", "(x)"), + (0x1F128, "M", "(y)"), + (0x1F129, "M", "(z)"), + (0x1F12A, "M", "〔s〕"), + (0x1F12B, "M", "c"), + (0x1F12C, "M", "r"), + (0x1F12D, "M", "cd"), + (0x1F12E, "M", "wz"), + (0x1F12F, "V"), + (0x1F130, "M", "a"), + (0x1F131, "M", "b"), + (0x1F132, "M", "c"), + (0x1F133, "M", "d"), + (0x1F134, "M", "e"), + (0x1F135, "M", "f"), + (0x1F136, "M", "g"), + (0x1F137, "M", "h"), + (0x1F138, "M", "i"), + (0x1F139, "M", "j"), + (0x1F13A, "M", "k"), + (0x1F13B, "M", "l"), + (0x1F13C, "M", "m"), + (0x1F13D, "M", "n"), + (0x1F13E, "M", "o"), + (0x1F13F, "M", "p"), + (0x1F140, "M", "q"), + (0x1F141, "M", "r"), + (0x1F142, "M", "s"), + (0x1F143, "M", "t"), + (0x1F144, "M", "u"), + (0x1F145, "M", "v"), + (0x1F146, "M", "w"), + (0x1F147, "M", "x"), + (0x1F148, "M", "y"), + (0x1F149, "M", "z"), + (0x1F14A, "M", "hv"), + (0x1F14B, "M", "mv"), + (0x1F14C, "M", "sd"), + (0x1F14D, "M", "ss"), + (0x1F14E, "M", "ppv"), + (0x1F14F, "M", "wc"), + (0x1F150, "V"), + (0x1F16A, "M", "mc"), + (0x1F16B, "M", "md"), + (0x1F16C, "M", "mr"), + (0x1F16D, "V"), + (0x1F190, "M", "dj"), + (0x1F191, "V"), + (0x1F1AE, "X"), + (0x1F1E6, "V"), + (0x1F200, "M", "ほか"), + (0x1F201, "M", "ココ"), + (0x1F202, "M", "サ"), + (0x1F203, "X"), + (0x1F210, "M", "手"), + (0x1F211, "M", "字"), + (0x1F212, "M", "双"), + (0x1F213, "M", "デ"), + (0x1F214, "M", "二"), + (0x1F215, "M", "多"), + (0x1F216, "M", "解"), + (0x1F217, "M", "天"), + (0x1F218, "M", "交"), + (0x1F219, "M", "映"), + (0x1F21A, "M", "無"), + (0x1F21B, "M", "料"), + (0x1F21C, "M", "前"), + (0x1F21D, "M", "後"), + (0x1F21E, "M", "再"), + (0x1F21F, "M", "新"), + (0x1F220, "M", "初"), + (0x1F221, "M", "終"), + (0x1F222, "M", "生"), + (0x1F223, "M", "販"), + (0x1F224, "M", "声"), + (0x1F225, "M", "吹"), + (0x1F226, "M", "演"), + (0x1F227, "M", "投"), + (0x1F228, "M", "捕"), + (0x1F229, "M", "一"), + (0x1F22A, "M", "三"), + (0x1F22B, "M", "遊"), + (0x1F22C, "M", "左"), + (0x1F22D, "M", "中"), + (0x1F22E, "M", "右"), + (0x1F22F, "M", "指"), + (0x1F230, "M", "走"), + (0x1F231, "M", "打"), + (0x1F232, "M", "禁"), + (0x1F233, "M", "空"), + (0x1F234, "M", "合"), + (0x1F235, "M", "満"), + (0x1F236, "M", "有"), + (0x1F237, "M", "月"), + (0x1F238, "M", "申"), + (0x1F239, "M", "割"), + (0x1F23A, "M", "営"), + (0x1F23B, "M", "配"), + (0x1F23C, "X"), + (0x1F240, "M", "〔本〕"), + (0x1F241, "M", "〔三〕"), + (0x1F242, "M", "〔二〕"), + (0x1F243, "M", "〔安〕"), + (0x1F244, "M", "〔点〕"), + (0x1F245, "M", "〔打〕"), + (0x1F246, "M", "〔盗〕"), + (0x1F247, "M", "〔勝〕"), + (0x1F248, "M", "〔敗〕"), + (0x1F249, "X"), + (0x1F250, "M", "得"), + (0x1F251, "M", "可"), + (0x1F252, "X"), + (0x1F260, "V"), + (0x1F266, "X"), + (0x1F300, "V"), + (0x1F6D9, "X"), + (0x1F6DC, "V"), + (0x1F6ED, "X"), + (0x1F6F0, "V"), + (0x1F6FD, "X"), + (0x1F700, "V"), + (0x1F7DA, "X"), + (0x1F7E0, "V"), + (0x1F7EC, "X"), + (0x1F7F0, "V"), + (0x1F7F1, "X"), + (0x1F800, "V"), + (0x1F80C, "X"), + (0x1F810, "V"), + (0x1F848, "X"), + (0x1F850, "V"), + (0x1F85A, "X"), + (0x1F860, "V"), + (0x1F888, "X"), + (0x1F890, "V"), + (0x1F8AE, "X"), + (0x1F8B0, "V"), + (0x1F8BC, "X"), + (0x1F8C0, "V"), + (0x1F8C2, "X"), + (0x1F8D0, "V"), + (0x1F8D9, "X"), + (0x1F900, "V"), + (0x1FA58, "X"), + (0x1FA60, "V"), + (0x1FA6E, "X"), + (0x1FA70, "V"), + (0x1FA7D, "X"), + (0x1FA80, "V"), + (0x1FA8B, "X"), + (0x1FA8E, "V"), + (0x1FAC7, "X"), + (0x1FAC8, "V"), + (0x1FAC9, "X"), + (0x1FACD, "V"), + (0x1FADD, "X"), + (0x1FADF, "V"), + (0x1FAEB, "X"), + (0x1FAEF, "V"), + (0x1FAF9, "X"), + (0x1FB00, "V"), + (0x1FB93, "X"), + (0x1FB94, "V"), + (0x1FBF0, "M", "0"), + (0x1FBF1, "M", "1"), + (0x1FBF2, "M", "2"), + (0x1FBF3, "M", "3"), + (0x1FBF4, "M", "4"), + (0x1FBF5, "M", "5"), + (0x1FBF6, "M", "6"), + (0x1FBF7, "M", "7"), + (0x1FBF8, "M", "8"), + (0x1FBF9, "M", "9"), + (0x1FBFA, "V"), + (0x1FBFB, "X"), + (0x20000, "V"), + (0x2A6E0, "X"), + (0x2A700, "V"), + (0x2B81E, "X"), + (0x2B820, "V"), + (0x2CEAE, "X"), + (0x2CEB0, "V"), + (0x2EBE1, "X"), + (0x2EBF0, "V"), + (0x2EE5E, "X"), + (0x2F800, "M", "丽"), + (0x2F801, "M", "丸"), + (0x2F802, "M", "乁"), + (0x2F803, "M", "𠄢"), + (0x2F804, "M", "你"), + (0x2F805, "M", "侮"), + (0x2F806, "M", "侻"), + (0x2F807, "M", "倂"), + (0x2F808, "M", "偺"), + (0x2F809, "M", "備"), + (0x2F80A, "M", "僧"), + (0x2F80B, "M", "像"), + (0x2F80C, "M", "㒞"), + (0x2F80D, "M", "𠘺"), + (0x2F80E, "M", "免"), + (0x2F80F, "M", "兔"), + (0x2F810, "M", "兤"), + (0x2F811, "M", "具"), + (0x2F812, "M", "𠔜"), + (0x2F813, "M", "㒹"), + (0x2F814, "M", "內"), + (0x2F815, "M", "再"), + (0x2F816, "M", "𠕋"), + (0x2F817, "M", "冗"), + (0x2F818, "M", "冤"), + (0x2F819, "M", "仌"), + (0x2F81A, "M", "冬"), + (0x2F81B, "M", "况"), + (0x2F81C, "M", "𩇟"), + (0x2F81D, "M", "凵"), + (0x2F81E, "M", "刃"), + (0x2F81F, "M", "㓟"), + (0x2F820, "M", "刻"), + (0x2F821, "M", "剆"), + (0x2F822, "M", "割"), + (0x2F823, "M", "剷"), + (0x2F824, "M", "㔕"), + (0x2F825, "M", "勇"), + (0x2F826, "M", "勉"), + (0x2F827, "M", "勤"), + (0x2F828, "M", "勺"), + (0x2F829, "M", "包"), + (0x2F82A, "M", "匆"), + (0x2F82B, "M", "北"), + (0x2F82C, "M", "卉"), + (0x2F82D, "M", "卑"), + (0x2F82E, "M", "博"), + (0x2F82F, "M", "即"), + (0x2F830, "M", "卽"), + (0x2F831, "M", "卿"), + (0x2F834, "M", "𠨬"), + (0x2F835, "M", "灰"), + (0x2F836, "M", "及"), + (0x2F837, "M", "叟"), + (0x2F838, "M", "𠭣"), + (0x2F839, "M", "叫"), + (0x2F83A, "M", "叱"), + (0x2F83B, "M", "吆"), + (0x2F83C, "M", "咞"), + (0x2F83D, "M", "吸"), + (0x2F83E, "M", "呈"), + (0x2F83F, "M", "周"), + (0x2F840, "M", "咢"), + (0x2F841, "M", "哶"), + (0x2F842, "M", "唐"), + (0x2F843, "M", "啓"), + (0x2F844, "M", "啣"), + (0x2F845, "M", "善"), + (0x2F847, "M", "喙"), + (0x2F848, "M", "喫"), + (0x2F849, "M", "喳"), + (0x2F84A, "M", "嗂"), + (0x2F84B, "M", "圖"), + (0x2F84C, "M", "嘆"), + (0x2F84D, "M", "圗"), + (0x2F84E, "M", "噑"), + (0x2F84F, "M", "噴"), + (0x2F850, "M", "切"), + (0x2F851, "M", "壮"), + (0x2F852, "M", "城"), + (0x2F853, "M", "埴"), + (0x2F854, "M", "堍"), + (0x2F855, "M", "型"), + (0x2F856, "M", "堲"), + (0x2F857, "M", "報"), + (0x2F858, "M", "墬"), + (0x2F859, "M", "𡓤"), + (0x2F85A, "M", "売"), + (0x2F85B, "M", "壷"), + (0x2F85C, "M", "夆"), + (0x2F85D, "M", "多"), + (0x2F85E, "M", "夢"), + (0x2F85F, "M", "奢"), + (0x2F860, "M", "𡚨"), + (0x2F861, "M", "𡛪"), + (0x2F862, "M", "姬"), + (0x2F863, "M", "娛"), + (0x2F864, "M", "娧"), + (0x2F865, "M", "姘"), + (0x2F866, "M", "婦"), + (0x2F867, "M", "㛮"), + (0x2F868, "M", "㛼"), + (0x2F869, "M", "嬈"), + (0x2F86A, "M", "嬾"), + (0x2F86C, "M", "𡧈"), + (0x2F86D, "M", "寃"), + (0x2F86E, "M", "寘"), + (0x2F86F, "M", "寧"), + (0x2F870, "M", "寳"), + (0x2F871, "M", "𡬘"), + (0x2F872, "M", "寿"), + (0x2F873, "M", "将"), + (0x2F874, "M", "当"), + (0x2F875, "M", "尢"), + (0x2F876, "M", "㞁"), + (0x2F877, "M", "屠"), + (0x2F878, "M", "屮"), + (0x2F879, "M", "峀"), + (0x2F87A, "M", "岍"), + (0x2F87B, "M", "𡷤"), + (0x2F87C, "M", "嵃"), + (0x2F87D, "M", "𡷦"), + (0x2F87E, "M", "嵮"), + (0x2F87F, "M", "嵫"), + (0x2F880, "M", "嵼"), + (0x2F881, "M", "巡"), + (0x2F882, "M", "巢"), + (0x2F883, "M", "㠯"), + (0x2F884, "M", "巽"), + (0x2F885, "M", "帨"), + (0x2F886, "M", "帽"), + (0x2F887, "M", "幩"), + (0x2F888, "M", "㡢"), + (0x2F889, "M", "𢆃"), + (0x2F88A, "M", "㡼"), + (0x2F88B, "M", "庰"), + (0x2F88C, "M", "庳"), + (0x2F88D, "M", "庶"), + (0x2F88E, "M", "廊"), + (0x2F88F, "M", "𪎒"), + (0x2F890, "M", "廾"), + (0x2F891, "M", "𢌱"), + (0x2F893, "M", "舁"), + (0x2F894, "M", "弢"), + (0x2F896, "M", "㣇"), + (0x2F897, "M", "𣊸"), + (0x2F898, "M", "𦇚"), + (0x2F899, "M", "形"), + (0x2F89A, "M", "彫"), + (0x2F89B, "M", "㣣"), + (0x2F89C, "M", "徚"), + (0x2F89D, "M", "忍"), + (0x2F89E, "M", "志"), + (0x2F89F, "M", "忹"), + (0x2F8A0, "M", "悁"), + (0x2F8A1, "M", "㤺"), + (0x2F8A2, "M", "㤜"), + (0x2F8A3, "M", "悔"), + (0x2F8A4, "M", "𢛔"), + (0x2F8A5, "M", "惇"), + (0x2F8A6, "M", "慈"), + (0x2F8A7, "M", "慌"), + (0x2F8A8, "M", "慎"), + (0x2F8A9, "M", "慌"), + (0x2F8AA, "M", "慺"), + (0x2F8AB, "M", "憎"), + (0x2F8AC, "M", "憲"), + (0x2F8AD, "M", "憤"), + (0x2F8AE, "M", "憯"), + (0x2F8AF, "M", "懞"), + (0x2F8B0, "M", "懲"), + (0x2F8B1, "M", "懶"), + (0x2F8B2, "M", "成"), + (0x2F8B3, "M", "戛"), + (0x2F8B4, "M", "扝"), + (0x2F8B5, "M", "抱"), + (0x2F8B6, "M", "拔"), + (0x2F8B7, "M", "捐"), + (0x2F8B8, "M", "𢬌"), + (0x2F8B9, "M", "挽"), + (0x2F8BA, "M", "拼"), + (0x2F8BB, "M", "捨"), + (0x2F8BC, "M", "掃"), + (0x2F8BD, "M", "揤"), + (0x2F8BE, "M", "𢯱"), + (0x2F8BF, "M", "搢"), + (0x2F8C0, "M", "揅"), + (0x2F8C1, "M", "掩"), + (0x2F8C2, "M", "㨮"), + (0x2F8C3, "M", "摩"), + (0x2F8C4, "M", "摾"), + (0x2F8C5, "M", "撝"), + (0x2F8C6, "M", "摷"), + (0x2F8C7, "M", "㩬"), + (0x2F8C8, "M", "敏"), + (0x2F8C9, "M", "敬"), + (0x2F8CA, "M", "𣀊"), + (0x2F8CB, "M", "旣"), + (0x2F8CC, "M", "書"), + (0x2F8CD, "M", "晉"), + (0x2F8CE, "M", "㬙"), + (0x2F8CF, "M", "暑"), + (0x2F8D0, "M", "㬈"), + (0x2F8D1, "M", "㫤"), + (0x2F8D2, "M", "冒"), + (0x2F8D3, "M", "冕"), + (0x2F8D4, "M", "最"), + (0x2F8D5, "M", "暜"), + (0x2F8D6, "M", "肭"), + (0x2F8D7, "M", "䏙"), + (0x2F8D8, "M", "朗"), + (0x2F8D9, "M", "望"), + (0x2F8DA, "M", "朡"), + (0x2F8DB, "M", "杞"), + (0x2F8DC, "M", "杓"), + (0x2F8DD, "M", "𣏃"), + (0x2F8DE, "M", "㭉"), + (0x2F8DF, "M", "柺"), + (0x2F8E0, "M", "枅"), + (0x2F8E1, "M", "桒"), + (0x2F8E2, "M", "梅"), + (0x2F8E3, "M", "𣑭"), + (0x2F8E4, "M", "梎"), + (0x2F8E5, "M", "栟"), + (0x2F8E6, "M", "椔"), + (0x2F8E7, "M", "㮝"), + (0x2F8E8, "M", "楂"), + (0x2F8E9, "M", "榣"), + (0x2F8EA, "M", "槪"), + (0x2F8EB, "M", "檨"), + (0x2F8EC, "M", "𣚣"), + (0x2F8ED, "M", "櫛"), + (0x2F8EE, "M", "㰘"), + (0x2F8EF, "M", "次"), + (0x2F8F0, "M", "𣢧"), + (0x2F8F1, "M", "歔"), + (0x2F8F2, "M", "㱎"), + (0x2F8F3, "M", "歲"), + (0x2F8F4, "M", "殟"), + (0x2F8F5, "M", "殺"), + (0x2F8F6, "M", "殻"), + (0x2F8F7, "M", "𣪍"), + (0x2F8F8, "M", "𡴋"), + (0x2F8F9, "M", "𣫺"), + (0x2F8FA, "M", "汎"), + (0x2F8FB, "M", "𣲼"), + (0x2F8FC, "M", "沿"), + (0x2F8FD, "M", "泍"), + (0x2F8FE, "M", "汧"), + (0x2F8FF, "M", "洖"), + (0x2F900, "M", "派"), + (0x2F901, "M", "海"), + (0x2F902, "M", "流"), + (0x2F903, "M", "浩"), + (0x2F904, "M", "浸"), + (0x2F905, "M", "涅"), + (0x2F906, "M", "𣴞"), + (0x2F907, "M", "洴"), + (0x2F908, "M", "港"), + (0x2F909, "M", "湮"), + (0x2F90A, "M", "㴳"), + (0x2F90B, "M", "滋"), + (0x2F90C, "M", "滇"), + (0x2F90D, "M", "𣻑"), + (0x2F90E, "M", "淹"), + (0x2F90F, "M", "潮"), + (0x2F910, "M", "𣽞"), + (0x2F911, "M", "𣾎"), + (0x2F912, "M", "濆"), + (0x2F913, "M", "瀹"), + (0x2F914, "M", "瀞"), + (0x2F915, "M", "瀛"), + (0x2F916, "M", "㶖"), + (0x2F917, "M", "灊"), + (0x2F918, "M", "災"), + (0x2F919, "M", "灷"), + (0x2F91A, "M", "炭"), + (0x2F91B, "M", "𠔥"), + (0x2F91C, "M", "煅"), + (0x2F91D, "M", "𤉣"), + (0x2F91E, "M", "熜"), + (0x2F91F, "M", "𤎫"), + (0x2F920, "M", "爨"), + (0x2F921, "M", "爵"), + (0x2F922, "M", "牐"), + (0x2F923, "M", "𤘈"), + (0x2F924, "M", "犀"), + (0x2F925, "M", "犕"), + (0x2F926, "M", "𤜵"), + (0x2F927, "M", "𤠔"), + (0x2F928, "M", "獺"), + (0x2F929, "M", "王"), + (0x2F92A, "M", "㺬"), + (0x2F92B, "M", "玥"), + (0x2F92C, "M", "㺸"), + (0x2F92E, "M", "瑇"), + (0x2F92F, "M", "瑜"), + (0x2F930, "M", "瑱"), + (0x2F931, "M", "璅"), + (0x2F932, "M", "瓊"), + (0x2F933, "M", "㼛"), + (0x2F934, "M", "甤"), + (0x2F935, "M", "𤰶"), + (0x2F936, "M", "甾"), + (0x2F937, "M", "𤲒"), + (0x2F938, "M", "異"), + (0x2F939, "M", "𢆟"), + (0x2F93A, "M", "瘐"), + (0x2F93B, "M", "𤾡"), + (0x2F93C, "M", "𤾸"), + (0x2F93D, "M", "𥁄"), + (0x2F93E, "M", "㿼"), + (0x2F93F, "M", "䀈"), + (0x2F940, "M", "直"), + (0x2F941, "M", "𥃳"), + (0x2F942, "M", "𥃲"), + (0x2F943, "M", "𥄙"), + (0x2F944, "M", "𥄳"), + (0x2F945, "M", "眞"), + (0x2F946, "M", "真"), + (0x2F948, "M", "睊"), + (0x2F949, "M", "䀹"), + (0x2F94A, "M", "瞋"), + (0x2F94B, "M", "䁆"), + (0x2F94C, "M", "䂖"), + (0x2F94D, "M", "𥐝"), + (0x2F94E, "M", "硎"), + (0x2F94F, "M", "碌"), + (0x2F950, "M", "磌"), + (0x2F951, "M", "䃣"), + (0x2F952, "M", "𥘦"), + (0x2F953, "M", "祖"), + (0x2F954, "M", "𥚚"), + (0x2F955, "M", "𥛅"), + (0x2F956, "M", "福"), + (0x2F957, "M", "秫"), + (0x2F958, "M", "䄯"), + (0x2F959, "M", "穀"), + (0x2F95A, "M", "穊"), + (0x2F95B, "M", "穏"), + (0x2F95C, "M", "𥥼"), + (0x2F95D, "M", "𥪧"), + (0x2F95F, "M", "竮"), + (0x2F960, "M", "䈂"), + (0x2F961, "M", "𥮫"), + (0x2F962, "M", "篆"), + (0x2F963, "M", "築"), + (0x2F964, "M", "䈧"), + (0x2F965, "M", "𥲀"), + (0x2F966, "M", "糒"), + (0x2F967, "M", "䊠"), + (0x2F968, "M", "糨"), + (0x2F969, "M", "糣"), + (0x2F96A, "M", "紀"), + (0x2F96B, "M", "𥾆"), + (0x2F96C, "M", "絣"), + (0x2F96D, "M", "䌁"), + (0x2F96E, "M", "緇"), + (0x2F96F, "M", "縂"), + (0x2F970, "M", "繅"), + (0x2F971, "M", "䌴"), + (0x2F972, "M", "𦈨"), + (0x2F973, "M", "𦉇"), + (0x2F974, "M", "䍙"), + (0x2F975, "M", "𦋙"), + (0x2F976, "M", "罺"), + (0x2F977, "M", "𦌾"), + (0x2F978, "M", "羕"), + (0x2F979, "M", "翺"), + (0x2F97A, "M", "者"), + (0x2F97B, "M", "𦓚"), + (0x2F97C, "M", "𦔣"), + (0x2F97D, "M", "聠"), + (0x2F97E, "M", "𦖨"), + (0x2F97F, "M", "聰"), + (0x2F980, "M", "𣍟"), + (0x2F981, "M", "䏕"), + (0x2F982, "M", "育"), + (0x2F983, "M", "脃"), + (0x2F984, "M", "䐋"), + (0x2F985, "M", "脾"), + (0x2F986, "M", "媵"), + (0x2F987, "M", "𦞧"), + (0x2F988, "M", "𦞵"), + (0x2F989, "M", "𣎓"), + (0x2F98A, "M", "𣎜"), + (0x2F98B, "M", "舁"), + (0x2F98C, "M", "舄"), + (0x2F98D, "M", "辞"), + (0x2F98E, "M", "䑫"), + (0x2F98F, "M", "芑"), + (0x2F990, "M", "芋"), + (0x2F991, "M", "芝"), + (0x2F992, "M", "劳"), + (0x2F993, "M", "花"), + (0x2F994, "M", "芳"), + (0x2F995, "M", "芽"), + (0x2F996, "M", "苦"), + (0x2F997, "M", "𦬼"), + (0x2F998, "M", "若"), + (0x2F999, "M", "茝"), + (0x2F99A, "M", "荣"), + (0x2F99B, "M", "莭"), + (0x2F99C, "M", "茣"), + (0x2F99D, "M", "莽"), + (0x2F99E, "M", "菧"), + (0x2F99F, "M", "著"), + (0x2F9A0, "M", "荓"), + (0x2F9A1, "M", "菊"), + (0x2F9A2, "M", "菌"), + (0x2F9A3, "M", "菜"), + (0x2F9A4, "M", "𦰶"), + (0x2F9A5, "M", "𦵫"), + (0x2F9A6, "M", "𦳕"), + (0x2F9A7, "M", "䔫"), + (0x2F9A8, "M", "蓱"), + (0x2F9A9, "M", "蓳"), + (0x2F9AA, "M", "蔖"), + (0x2F9AB, "M", "𧏊"), + (0x2F9AC, "M", "蕤"), + (0x2F9AD, "M", "𦼬"), + (0x2F9AE, "M", "䕝"), + (0x2F9AF, "M", "䕡"), + (0x2F9B0, "M", "𦾱"), + (0x2F9B1, "M", "𧃒"), + (0x2F9B2, "M", "䕫"), + (0x2F9B3, "M", "虐"), + (0x2F9B4, "M", "虜"), + (0x2F9B5, "M", "虧"), + (0x2F9B6, "M", "虩"), + (0x2F9B7, "M", "蚩"), + (0x2F9B8, "M", "蚈"), + (0x2F9B9, "M", "蜎"), + (0x2F9BA, "M", "蛢"), + (0x2F9BB, "M", "蝹"), + (0x2F9BC, "M", "蜨"), + (0x2F9BD, "M", "蝫"), + (0x2F9BE, "M", "螆"), + (0x2F9BF, "M", "䗗"), + (0x2F9C0, "M", "蟡"), + (0x2F9C1, "M", "蠁"), + (0x2F9C2, "M", "䗹"), + (0x2F9C3, "M", "衠"), + (0x2F9C4, "M", "衣"), + (0x2F9C5, "M", "𧙧"), + (0x2F9C6, "M", "裗"), + (0x2F9C7, "M", "裞"), + (0x2F9C8, "M", "䘵"), + (0x2F9C9, "M", "裺"), + (0x2F9CA, "M", "㒻"), + (0x2F9CB, "M", "𧢮"), + (0x2F9CC, "M", "𧥦"), + (0x2F9CD, "M", "䚾"), + (0x2F9CE, "M", "䛇"), + (0x2F9CF, "M", "誠"), + (0x2F9D0, "M", "諭"), + (0x2F9D1, "M", "變"), + (0x2F9D2, "M", "豕"), + (0x2F9D3, "M", "𧲨"), + (0x2F9D4, "M", "貫"), + (0x2F9D5, "M", "賁"), + (0x2F9D6, "M", "贛"), + (0x2F9D7, "M", "起"), + (0x2F9D8, "M", "𧼯"), + (0x2F9D9, "M", "𠠄"), + (0x2F9DA, "M", "跋"), + (0x2F9DB, "M", "趼"), + (0x2F9DC, "M", "跰"), + (0x2F9DD, "M", "𠣞"), + (0x2F9DE, "M", "軔"), + (0x2F9DF, "M", "輸"), + (0x2F9E0, "M", "𨗒"), + (0x2F9E1, "M", "𨗭"), + (0x2F9E2, "M", "邔"), + (0x2F9E3, "M", "郱"), + (0x2F9E4, "M", "鄑"), + (0x2F9E5, "M", "𨜮"), + (0x2F9E6, "M", "鄛"), + (0x2F9E7, "M", "鈸"), + (0x2F9E8, "M", "鋗"), + (0x2F9E9, "M", "鋘"), + (0x2F9EA, "M", "鉼"), + (0x2F9EB, "M", "鏹"), + (0x2F9EC, "M", "鐕"), + (0x2F9ED, "M", "𨯺"), + (0x2F9EE, "M", "開"), + (0x2F9EF, "M", "䦕"), + (0x2F9F0, "M", "閷"), + (0x2F9F1, "M", "𨵷"), + (0x2F9F2, "M", "䧦"), + (0x2F9F3, "M", "雃"), + (0x2F9F4, "M", "嶲"), + (0x2F9F5, "M", "霣"), + (0x2F9F6, "M", "𩅅"), + (0x2F9F7, "M", "𩈚"), + (0x2F9F8, "M", "䩮"), + (0x2F9F9, "M", "䩶"), + (0x2F9FA, "M", "韠"), + (0x2F9FB, "M", "𩐊"), + (0x2F9FC, "M", "䪲"), + (0x2F9FD, "M", "𩒖"), + (0x2F9FE, "M", "頋"), + (0x2FA00, "M", "頩"), + (0x2FA01, "M", "𩖶"), + (0x2FA02, "M", "飢"), + (0x2FA03, "M", "䬳"), + (0x2FA04, "M", "餩"), + (0x2FA05, "M", "馧"), + (0x2FA06, "M", "駂"), + (0x2FA07, "M", "駾"), + (0x2FA08, "M", "䯎"), + (0x2FA09, "M", "𩬰"), + (0x2FA0A, "M", "鬒"), + (0x2FA0B, "M", "鱀"), + (0x2FA0C, "M", "鳽"), + (0x2FA0D, "M", "䳎"), + (0x2FA0E, "M", "䳭"), + (0x2FA0F, "M", "鵧"), + (0x2FA10, "M", "𪃎"), + (0x2FA11, "M", "䳸"), + (0x2FA12, "M", "𪄅"), + (0x2FA13, "M", "𪈎"), + (0x2FA14, "M", "𪊑"), + (0x2FA15, "M", "麻"), + (0x2FA16, "M", "䵖"), + (0x2FA17, "M", "黹"), + (0x2FA18, "M", "黾"), + (0x2FA19, "M", "鼅"), + (0x2FA1A, "M", "鼏"), + (0x2FA1B, "M", "鼖"), + (0x2FA1C, "M", "鼻"), + (0x2FA1D, "M", "𪘀"), + (0x2FA1E, "X"), + (0x30000, "V"), + (0x3134B, "X"), + (0x31350, "V"), + (0x3347A, "X"), + (0xE0100, "I"), + (0xE01F0, "X"), +) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic-1.10.16.dist-info/INSTALLER b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic-1.10.16.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic-1.10.16.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic-1.10.16.dist-info/METADATA b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic-1.10.16.dist-info/METADATA new file mode 100644 index 0000000..0516001 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic-1.10.16.dist-info/METADATA @@ -0,0 +1,1390 @@ +Metadata-Version: 2.4 +Name: pydantic +Version: 1.10.16 +Summary: Data validation and settings management using python type hints +Home-page: https://github.com/pydantic/pydantic +Author: Samuel Colvin +Author-email: s@muelcolvin.com +License: MIT +Classifier: Development Status :: 5 - Production/Stable +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: Information Technology +Classifier: Intended Audience :: System Administrators +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: Unix +Classifier: Operating System :: POSIX :: Linux +Classifier: Environment :: Console +Classifier: Environment :: MacOS X +Classifier: Framework :: Hypothesis +Classifier: Framework :: Pydantic +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Internet +Requires-Python: >=3.7 +Description-Content-Type: text/markdown +License-File: LICENSE +Requires-Dist: typing-extensions>=4.2.0 +Provides-Extra: email +Requires-Dist: email-validator>=1.0.3; extra == "email" +Provides-Extra: dotenv +Requires-Dist: python-dotenv>=0.10.4; extra == "dotenv" +Dynamic: author +Dynamic: author-email +Dynamic: classifier +Dynamic: description +Dynamic: description-content-type +Dynamic: home-page +Dynamic: license +Dynamic: license-file +Dynamic: provides-extra +Dynamic: requires-dist +Dynamic: requires-python +Dynamic: summary + +# pydantic + +[![CI](https://github.com/pydantic/pydantic/workflows/CI/badge.svg?event=push)](https://github.com/pydantic/pydantic/actions?query=event%3Apush+branch%3Amain+workflow%3ACI) +[![Coverage](https://coverage-badge.samuelcolvin.workers.dev/pydantic/pydantic.svg?branch=1.10.X-fixes)](https://coverage-badge.samuelcolvin.workers.dev/redirect/pydantic/pydantic?branch=1.10.X-fixes) +[![pypi](https://img.shields.io/pypi/v/pydantic.svg)](https://pypi.python.org/pypi/pydantic) +[![CondaForge](https://img.shields.io/conda/v/conda-forge/pydantic.svg)](https://anaconda.org/conda-forge/pydantic) +[![downloads](https://pepy.tech/badge/pydantic/month)](https://pepy.tech/project/pydantic) +[![versions](https://img.shields.io/pypi/pyversions/pydantic.svg)](https://github.com/pydantic/pydantic) +[![license](https://img.shields.io/github/license/pydantic/pydantic.svg)](https://github.com/pydantic/pydantic/blob/main/LICENSE) + +Data validation and settings management using Python type hints. + +Fast and extensible, *pydantic* plays nicely with your linters/IDE/brain. +Define how data should be in pure, canonical Python 3.7+; validate it with *pydantic*. + +## Pydantic Company :rocket: + +We've started a company based on the principles that I believe have led to Pydantic's success. +Learning more from the [Company Announcement](https://pydantic.dev/announcement/). + +## Help + +See [documentation](https://docs.pydantic.dev/) for more details. + +## Installation + +Install using `pip install -U pydantic` or `conda install pydantic -c conda-forge`. +For more installation options to make *pydantic* even faster, +see the [Install](https://docs.pydantic.dev/install/) section in the documentation. + +## A Simple Example + +```py +from datetime import datetime +from typing import List, Optional +from pydantic import BaseModel + +class User(BaseModel): + id: int + name = 'John Doe' + signup_ts: Optional[datetime] = None + friends: List[int] = [] + +external_data = {'id': '123', 'signup_ts': '2017-06-01 12:22', 'friends': [1, '2', b'3']} +user = User(**external_data) +print(user) +#> User id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3] +print(user.id) +#> 123 +``` + +## Contributing + +For guidance on setting up a development environment and how to make a +contribution to *pydantic*, see +[Contributing to Pydantic](https://docs.pydantic.dev/contributing/). + +## Reporting a Security Vulnerability + +See our [security policy](https://github.com/pydantic/pydantic/security/policy). + + +## v1.10.16 (2024-06-11) + +* Specify recursive_guard as kwarg in FutureRef._evaluate by [@vfazio](https://github.com/vfazio) in https://github.com/pydantic/pydantic/pull/#961 +* Fix mypy v1 plugin for upcoming mypy release by @ cdce8p in https://github.com/pydantic/pydantic/pull/9586 +* Import modules/objects directly from v1 namespace by [@exs-dwoodward](https://github.com/exs-dwoodward) in https://github.com/pydantic/pydantic/pull/9162 + +## v1.10.15 (2024-04-03) + +* Add pydantic.v1 namespace to Pydantic v1 by [@exs-dmiketa](https://github.com/exs-dmiketa) in https://github.com/pydantic/pydantic/pull/9042 +* Relax version of typing-extensions for V1 by [@SonOfLilit](https://github.com/SonOfLilit) in https://github.com/pydantic/pydantic/pull/8819 +* patch fix for mypy by [@sydney-runkle](https://github.com/sydney-runkle) in https://github.com/pydantic/pydantic/pull/8765 + +## v1.10.14 (2024-01-19) + +* Update install.md by [@dmontagu](https://github.com/dmontagu) in https://github.com/pydantic/pydantic/pull/7690 +* Fixes ci to only deploy docs on release by [@sydney-runkle](https://github.com/sydney-runkle) in https://github.com/pydantic/pydantic/pull/7740 +* Ubuntu fixes for V1 by [@sydney-runkle](https://github.com/sydney-runkle) in https://github.com/pydantic/pydantic/pull/8540 and https://github.com/pydantic/pydantic/pull/8587 +* Fix cached_property handling in dataclasses when copied by [@rdbisme](https://github.com/rdbisme) in https://github.com/pydantic/pydantic/pull/8407 + +## v1.10.13 (2023-09-27) + +* Fix: Add max length check to `pydantic.validate_email`, [#7673](https://github.com/pydantic/pydantic/issues/7673) by [@hramezani](https://github.com/hramezani) +* Docs: Fix pip commands to install v1, [#6930](https://github.com/pydantic/pydantic/issues/6930) by [@chbndrhnns](https://github.com/chbndrhnns) + +## v1.10.12 (2023-07-24) + +* Fixes the `maxlen` property being dropped on `deque` validation. Happened only if the deque item has been typed. Changes the `_validate_sequence_like` func, [#6581](https://github.com/pydantic/pydantic/issues/6581) by [@maciekglowka](https://github.com/maciekglowka) + +## v1.10.11 (2023-07-04) + +* Importing create_model in tools.py through relative path instead of absolute path - so that it doesn't import V2 code when copied over to V2 branch, [#6361](https://github.com/pydantic/pydantic/issues/6361) by [@SharathHuddar](https://github.com/SharathHuddar) + +## v2.0b3 (2023-06-16) + +Third beta pre-release of Pydantic V2 + +See the full changelog [here](https://github.com/pydantic/pydantic/releases/tag/v2.0b3) + +## v2.0b2 (2023-06-03) + +Add `from_attributes` runtime flag to `TypeAdapter.validate_python` and `BaseModel.model_validate`. + +See the full changelog [here](https://github.com/pydantic/pydantic/releases/tag/v2.0b2) + +## v2.0b1 (2023-06-01) + +First beta pre-release of Pydantic V2 + +See the full changelog [here](https://github.com/pydantic/pydantic/releases/tag/v2.0b1) + +## v2.0a4 (2023-05-05) + +Fourth pre-release of Pydantic V2 + +See the full changelog [here](https://github.com/pydantic/pydantic/releases/tag/v2.0a4) + +## v2.0a3 (2023-04-20) + +Third pre-release of Pydantic V2 + +See the full changelog [here](https://github.com/pydantic/pydantic/releases/tag/v2.0a3) + +## v2.0a2 (2023-04-12) + +Second pre-release of Pydantic V2 + +See the full changelog [here](https://github.com/pydantic/pydantic/releases/tag/v2.0a2) + +## v2.0a1 (2023-04-03) + +First pre-release of Pydantic V2! + +See [this post](https://docs.pydantic.dev/blog/pydantic-v2-alpha/) for more details. + +## v1.10.10 (2023-06-30) + +* Add Pydantic `Json` field support to settings management, [#6250](https://github.com/pydantic/pydantic/issues/6250) by [@hramezani](https://github.com/hramezani) +* Fixed literal validator errors for unhashable values, [#6188](https://github.com/pydantic/pydantic/issues/6188) by [@markus1978](https://github.com/markus1978) +* Fixed bug with generics receiving forward refs, [#6130](https://github.com/pydantic/pydantic/issues/6130) by [@mark-todd](https://github.com/mark-todd) +* Update install method of FastAPI for internal tests in CI, [#6117](https://github.com/pydantic/pydantic/issues/6117) by [@Kludex](https://github.com/Kludex) + +## v1.10.9 (2023-06-07) + +* Fix trailing zeros not ignored in Decimal validation, [#5968](https://github.com/pydantic/pydantic/issues/5968) by [@hramezani](https://github.com/hramezani) +* Fix mypy plugin for v1.4.0, [#5928](https://github.com/pydantic/pydantic/issues/5928) by [@cdce8p](https://github.com/cdce8p) +* Add future and past date hypothesis strategies, [#5850](https://github.com/pydantic/pydantic/issues/5850) by [@bschoenmaeckers](https://github.com/bschoenmaeckers) +* Discourage usage of Cython 3 with Pydantic 1.x, [#5845](https://github.com/pydantic/pydantic/issues/5845) by [@lig](https://github.com/lig) + +## v1.10.8 (2023-05-23) + +* Fix a bug in `Literal` usage with `typing-extension==4.6.0`, [#5826](https://github.com/pydantic/pydantic/issues/5826) by [@hramezani](https://github.com/hramezani) +* This solves the (closed) issue [#3849](https://github.com/pydantic/pydantic/issues/3849) where aliased fields that use discriminated union fail to validate when the data contains the non-aliased field name, [#5736](https://github.com/pydantic/pydantic/issues/5736) by [@benwah](https://github.com/benwah) +* Update email-validator dependency to >=2.0.0post2, [#5627](https://github.com/pydantic/pydantic/issues/5627) by [@adriangb](https://github.com/adriangb) +* update `AnyClassMethod` for changes in [python/typeshed#9771](https://github.com/python/typeshed/issues/9771), [#5505](https://github.com/pydantic/pydantic/issues/5505) by [@ITProKyle](https://github.com/ITProKyle) + +## v1.10.7 (2023-03-22) + +* Fix creating schema from model using `ConstrainedStr` with `regex` as dict key, [#5223](https://github.com/pydantic/pydantic/issues/5223) by [@matejetz](https://github.com/matejetz) +* Address bug in mypy plugin caused by explicit_package_bases=True, [#5191](https://github.com/pydantic/pydantic/issues/5191) by [@dmontagu](https://github.com/dmontagu) +* Add implicit defaults in the mypy plugin for Field with no default argument, [#5190](https://github.com/pydantic/pydantic/issues/5190) by [@dmontagu](https://github.com/dmontagu) +* Fix schema generated for Enum values used as Literals in discriminated unions, [#5188](https://github.com/pydantic/pydantic/issues/5188) by [@javibookline](https://github.com/javibookline) +* Fix mypy failures caused by the pydantic mypy plugin when users define `from_orm` in their own classes, [#5187](https://github.com/pydantic/pydantic/issues/5187) by [@dmontagu](https://github.com/dmontagu) +* Fix `InitVar` usage with pydantic dataclasses, mypy version `1.1.1` and the custom mypy plugin, [#5162](https://github.com/pydantic/pydantic/issues/5162) by [@cdce8p](https://github.com/cdce8p) + +## v1.10.6 (2023-03-08) + +* Implement logic to support creating validators from non standard callables by using defaults to identify them and unwrapping `functools.partial` and `functools.partialmethod` when checking the signature, [#5126](https://github.com/pydantic/pydantic/issues/5126) by [@JensHeinrich](https://github.com/JensHeinrich) +* Fix mypy plugin for v1.1.1, and fix `dataclass_transform` decorator for pydantic dataclasses, [#5111](https://github.com/pydantic/pydantic/issues/5111) by [@cdce8p](https://github.com/cdce8p) +* Raise `ValidationError`, not `ConfigError`, when a discriminator value is unhashable, [#4773](https://github.com/pydantic/pydantic/issues/4773) by [@kurtmckee](https://github.com/kurtmckee) + +## v1.10.5 (2023-02-15) + +* Fix broken parametrized bases handling with `GenericModel`s with complex sets of models, [#5052](https://github.com/pydantic/pydantic/issues/5052) by [@MarkusSintonen](https://github.com/MarkusSintonen) +* Invalidate mypy cache if plugin config changes, [#5007](https://github.com/pydantic/pydantic/issues/5007) by [@cdce8p](https://github.com/cdce8p) +* Fix `RecursionError` when deep-copying dataclass types wrapped by pydantic, [#4949](https://github.com/pydantic/pydantic/issues/4949) by [@mbillingr](https://github.com/mbillingr) +* Fix `X | Y` union syntax breaking `GenericModel`, [#4146](https://github.com/pydantic/pydantic/issues/4146) by [@thenx](https://github.com/thenx) +* Switch coverage badge to show coverage for this branch/release, [#5060](https://github.com/pydantic/pydantic/issues/5060) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v1.10.4 (2022-12-30) + +* Change dependency to `typing-extensions>=4.2.0`, [#4885](https://github.com/pydantic/pydantic/issues/4885) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v1.10.3 (2022-12-29) + +**NOTE: v1.10.3 was ["yanked"](https://pypi.org/help/#yanked) from PyPI due to [#4885](https://github.com/pydantic/pydantic/issues/4885) which is fixed in v1.10.4** + +* fix parsing of custom root models, [#4883](https://github.com/pydantic/pydantic/issues/4883) by [@gou177](https://github.com/gou177) +* fix: use dataclass proxy for frozen or empty dataclasses, [#4878](https://github.com/pydantic/pydantic/issues/4878) by [@PrettyWood](https://github.com/PrettyWood) +* Fix `schema` and `schema_json` on models where a model instance is a one of default values, [#4781](https://github.com/pydantic/pydantic/issues/4781) by [@Bobronium](https://github.com/Bobronium) +* Add Jina AI to sponsors on docs index page, [#4767](https://github.com/pydantic/pydantic/issues/4767) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix: support assignment on `DataclassProxy`, [#4695](https://github.com/pydantic/pydantic/issues/4695) by [@PrettyWood](https://github.com/PrettyWood) +* Add `postgresql+psycopg` as allowed scheme for `PostgreDsn` to make it usable with SQLAlchemy 2, [#4689](https://github.com/pydantic/pydantic/issues/4689) by [@morian](https://github.com/morian) +* Allow dict schemas to have both `patternProperties` and `additionalProperties`, [#4641](https://github.com/pydantic/pydantic/issues/4641) by [@jparise](https://github.com/jparise) +* Fixes error passing None for optional lists with `unique_items`, [#4568](https://github.com/pydantic/pydantic/issues/4568) by [@mfulgo](https://github.com/mfulgo) +* Fix `GenericModel` with `Callable` param raising a `TypeError`, [#4551](https://github.com/pydantic/pydantic/issues/4551) by [@mfulgo](https://github.com/mfulgo) +* Fix field regex with `StrictStr` type annotation, [#4538](https://github.com/pydantic/pydantic/issues/4538) by [@sisp](https://github.com/sisp) +* Correct `dataclass_transform` keyword argument name from `field_descriptors` to `field_specifiers`, [#4500](https://github.com/pydantic/pydantic/issues/4500) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix: avoid multiple calls of `__post_init__` when dataclasses are inherited, [#4487](https://github.com/pydantic/pydantic/issues/4487) by [@PrettyWood](https://github.com/PrettyWood) +* Reduce the size of binary wheels, [#2276](https://github.com/pydantic/pydantic/issues/2276) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v1.10.2 (2022-09-05) + +* **Revert Change:** Revert percent encoding of URL parts which was originally added in [#4224](https://github.com/pydantic/pydantic/issues/4224), [#4470](https://github.com/pydantic/pydantic/issues/4470) by [@samuelcolvin](https://github.com/samuelcolvin) +* Prevent long (length > `4_300`) strings/bytes as input to int fields, see + [python/cpython#95778](https://github.com/python/cpython/issues/95778) and + [CVE-2020-10735](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-10735), [#1477](https://github.com/pydantic/pydantic/issues/1477) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix: dataclass wrapper was not always called, [#4477](https://github.com/pydantic/pydantic/issues/4477) by [@PrettyWood](https://github.com/PrettyWood) +* Use `tomllib` on Python 3.11 when parsing `mypy` configuration, [#4476](https://github.com/pydantic/pydantic/issues/4476) by [@hauntsaninja](https://github.com/hauntsaninja) +* Basic fix of `GenericModel` cache to detect order of arguments in `Union` models, [#4474](https://github.com/pydantic/pydantic/issues/4474) by [@sveinugu](https://github.com/sveinugu) +* Fix mypy plugin when using bare types like `list` and `dict` as `default_factory`, [#4457](https://github.com/pydantic/pydantic/issues/4457) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v1.10.1 (2022-08-31) + +* Add `__hash__` method to `pydancic.color.Color` class, [#4454](https://github.com/pydantic/pydantic/issues/4454) by [@czaki](https://github.com/czaki) + +## v1.10.0 (2022-08-30) + +* Refactor the whole _pydantic_ `dataclass` decorator to really act like its standard lib equivalent. + It hence keeps `__eq__`, `__hash__`, ... and makes comparison with its non-validated version possible. + It also fixes usage of `frozen` dataclasses in fields and usage of `default_factory` in nested dataclasses. + The support of `Config.extra` has been added. + Finally, config customization directly via a `dict` is now possible, [#2557](https://github.com/pydantic/pydantic/issues/2557) by [@PrettyWood](https://github.com/PrettyWood) +

    + **BREAKING CHANGES:** + - The `compiled` boolean (whether _pydantic_ is compiled with cython) has been moved from `main.py` to `version.py` + - Now that `Config.extra` is supported, `dataclass` ignores by default extra arguments (like `BaseModel`) +* Fix PEP487 `__set_name__` protocol in `BaseModel` for PrivateAttrs, [#4407](https://github.com/pydantic/pydantic/issues/4407) by [@tlambert03](https://github.com/tlambert03) +* Allow for custom parsing of environment variables via `parse_env_var` in `Config`, [#4406](https://github.com/pydantic/pydantic/issues/4406) by [@acmiyaguchi](https://github.com/acmiyaguchi) +* Rename `master` to `main`, [#4405](https://github.com/pydantic/pydantic/issues/4405) by [@hramezani](https://github.com/hramezani) +* Fix `StrictStr` does not raise `ValidationError` when `max_length` is present in `Field`, [#4388](https://github.com/pydantic/pydantic/issues/4388) by [@hramezani](https://github.com/hramezani) +* Make `SecretStr` and `SecretBytes` hashable, [#4387](https://github.com/pydantic/pydantic/issues/4387) by [@chbndrhnns](https://github.com/chbndrhnns) +* Fix `StrictBytes` does not raise `ValidationError` when `max_length` is present in `Field`, [#4380](https://github.com/pydantic/pydantic/issues/4380) by [@JeanArhancet](https://github.com/JeanArhancet) +* Add support for bare `type`, [#4375](https://github.com/pydantic/pydantic/issues/4375) by [@hramezani](https://github.com/hramezani) +* Support Python 3.11, including binaries for 3.11 in PyPI, [#4374](https://github.com/pydantic/pydantic/issues/4374) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add support for `re.Pattern`, [#4366](https://github.com/pydantic/pydantic/issues/4366) by [@hramezani](https://github.com/hramezani) +* Fix `__post_init_post_parse__` is incorrectly passed keyword arguments when no `__post_init__` is defined, [#4361](https://github.com/pydantic/pydantic/issues/4361) by [@hramezani](https://github.com/hramezani) +* Fix implicitly importing `ForwardRef` and `Callable` from `pydantic.typing` instead of `typing` and also expose `MappingIntStrAny`, [#4358](https://github.com/pydantic/pydantic/issues/4358) by [@aminalaee](https://github.com/aminalaee) +* remove `Any` types from the `dataclass` decorator so it can be used with the `disallow_any_expr` mypy option, [#4356](https://github.com/pydantic/pydantic/issues/4356) by [@DetachHead](https://github.com/DetachHead) +* moved repo to `pydantic/pydantic`, [#4348](https://github.com/pydantic/pydantic/issues/4348) by [@yezz123](https://github.com/yezz123) +* fix "extra fields not permitted" error when dataclass with `Extra.forbid` is validated multiple times, [#4343](https://github.com/pydantic/pydantic/issues/4343) by [@detachhead](https://github.com/detachhead) +* Add Python 3.9 and 3.10 examples to docs, [#4339](https://github.com/pydantic/pydantic/issues/4339) by [@Bobronium](https://github.com/Bobronium) +* Discriminated union models now use `oneOf` instead of `anyOf` when generating OpenAPI schema definitions, [#4335](https://github.com/pydantic/pydantic/issues/4335) by [@MaxwellPayne](https://github.com/MaxwellPayne) +* Allow type checkers to infer inner type of `Json` type. `Json[list[str]]` will be now inferred as `list[str]`, + `Json[Any]` should be used instead of plain `Json`. + Runtime behaviour is not changed, [#4332](https://github.com/pydantic/pydantic/issues/4332) by [@Bobronium](https://github.com/Bobronium) +* Allow empty string aliases by using a `alias is not None` check, rather than `bool(alias)`, [#4253](https://github.com/pydantic/pydantic/issues/4253) by [@sergeytsaplin](https://github.com/sergeytsaplin) +* Update `ForwardRef`s in `Field.outer_type_`, [#4249](https://github.com/pydantic/pydantic/issues/4249) by [@JacobHayes](https://github.com/JacobHayes) +* The use of `__dataclass_transform__` has been replaced by `typing_extensions.dataclass_transform`, which is the preferred way to mark pydantic models as a dataclass under [PEP 681](https://peps.python.org/pep-0681/), [#4241](https://github.com/pydantic/pydantic/issues/4241) by [@multimeric](https://github.com/multimeric) +* Use parent model's `Config` when validating nested `NamedTuple` fields, [#4219](https://github.com/pydantic/pydantic/issues/4219) by [@synek](https://github.com/synek) +* Update `BaseModel.construct` to work with aliased Fields, [#4192](https://github.com/pydantic/pydantic/issues/4192) by [@kylebamos](https://github.com/kylebamos) +* Catch certain raised errors in `smart_deepcopy` and revert to `deepcopy` if so, [#4184](https://github.com/pydantic/pydantic/issues/4184) by [@coneybeare](https://github.com/coneybeare) +* Add `Config.anystr_upper` and `to_upper` kwarg to constr and conbytes, [#4165](https://github.com/pydantic/pydantic/issues/4165) by [@satheler](https://github.com/satheler) +* Fix JSON schema for `set` and `frozenset` when they include default values, [#4155](https://github.com/pydantic/pydantic/issues/4155) by [@aminalaee](https://github.com/aminalaee) +* Teach the mypy plugin that methods decorated by `@validator` are classmethods, [#4102](https://github.com/pydantic/pydantic/issues/4102) by [@DMRobertson](https://github.com/DMRobertson) +* Improve mypy plugin's ability to detect required fields, [#4086](https://github.com/pydantic/pydantic/issues/4086) by [@richardxia](https://github.com/richardxia) +* Support fields of type `Type[]` in schema, [#4051](https://github.com/pydantic/pydantic/issues/4051) by [@aminalaee](https://github.com/aminalaee) +* Add `default` value in JSON Schema when `const=True`, [#4031](https://github.com/pydantic/pydantic/issues/4031) by [@aminalaee](https://github.com/aminalaee) +* Adds reserved word check to signature generation logic, [#4011](https://github.com/pydantic/pydantic/issues/4011) by [@strue36](https://github.com/strue36) +* Fix Json strategy failure for the complex nested field, [#4005](https://github.com/pydantic/pydantic/issues/4005) by [@sergiosim](https://github.com/sergiosim) +* Add JSON-compatible float constraint `allow_inf_nan`, [#3994](https://github.com/pydantic/pydantic/issues/3994) by [@tiangolo](https://github.com/tiangolo) +* Remove undefined behaviour when `env_prefix` had characters in common with `env_nested_delimiter`, [#3975](https://github.com/pydantic/pydantic/issues/3975) by [@arsenron](https://github.com/arsenron) +* Support generics model with `create_model`, [#3945](https://github.com/pydantic/pydantic/issues/3945) by [@hot123s](https://github.com/hot123s) +* allow submodels to overwrite extra field info, [#3934](https://github.com/pydantic/pydantic/issues/3934) by [@PrettyWood](https://github.com/PrettyWood) +* Document and test structural pattern matching ([PEP 636](https://peps.python.org/pep-0636/)) on `BaseModel`, [#3920](https://github.com/pydantic/pydantic/issues/3920) by [@irgolic](https://github.com/irgolic) +* Fix incorrect deserialization of python timedelta object to ISO 8601 for negative time deltas. + Minus was serialized in incorrect place ("P-1DT23H59M59.888735S" instead of correct "-P1DT23H59M59.888735S"), [#3899](https://github.com/pydantic/pydantic/issues/3899) by [@07pepa](https://github.com/07pepa) +* Fix validation of discriminated union fields with an alias when passing a model instance, [#3846](https://github.com/pydantic/pydantic/issues/3846) by [@chornsby](https://github.com/chornsby) +* Add a CockroachDsn type to validate CockroachDB connection strings. The type + supports the following schemes: `cockroachdb`, `cockroachdb+psycopg2` and `cockroachdb+asyncpg`, [#3839](https://github.com/pydantic/pydantic/issues/3839) by [@blubber](https://github.com/blubber) +* Fix MyPy plugin to not override pre-existing `__init__` method in models, [#3824](https://github.com/pydantic/pydantic/issues/3824) by [@patrick91](https://github.com/patrick91) +* Fix mypy version checking, [#3783](https://github.com/pydantic/pydantic/issues/3783) by [@KotlinIsland](https://github.com/KotlinIsland) +* support overwriting dunder attributes of `BaseModel` instances, [#3777](https://github.com/pydantic/pydantic/issues/3777) by [@PrettyWood](https://github.com/PrettyWood) +* Added `ConstrainedDate` and `condate`, [#3740](https://github.com/pydantic/pydantic/issues/3740) by [@hottwaj](https://github.com/hottwaj) +* Support `kw_only` in dataclasses, [#3670](https://github.com/pydantic/pydantic/issues/3670) by [@detachhead](https://github.com/detachhead) +* Add comparison method for `Color` class, [#3646](https://github.com/pydantic/pydantic/issues/3646) by [@aminalaee](https://github.com/aminalaee) +* Drop support for python3.6, associated cleanup, [#3605](https://github.com/pydantic/pydantic/issues/3605) by [@samuelcolvin](https://github.com/samuelcolvin) +* created new function `to_lower_camel()` for "non pascal case" camel case, [#3463](https://github.com/pydantic/pydantic/issues/3463) by [@schlerp](https://github.com/schlerp) +* Add checks to `default` and `default_factory` arguments in Mypy plugin, [#3430](https://github.com/pydantic/pydantic/issues/3430) by [@klaa97](https://github.com/klaa97) +* fix mangling of `inspect.signature` for `BaseModel`, [#3413](https://github.com/pydantic/pydantic/issues/3413) by [@fix-inspect-signature](https://github.com/fix-inspect-signature) +* Adds the `SecretField` abstract class so that all the current and future secret fields like `SecretStr` and `SecretBytes` will derive from it, [#3409](https://github.com/pydantic/pydantic/issues/3409) by [@expobrain](https://github.com/expobrain) +* Support multi hosts validation in `PostgresDsn`, [#3337](https://github.com/pydantic/pydantic/issues/3337) by [@rglsk](https://github.com/rglsk) +* Fix parsing of very small numeric timedelta values, [#3315](https://github.com/pydantic/pydantic/issues/3315) by [@samuelcolvin](https://github.com/samuelcolvin) +* Update `SecretsSettingsSource` to respect `config.case_sensitive`, [#3273](https://github.com/pydantic/pydantic/issues/3273) by [@JeanArhancet](https://github.com/JeanArhancet) +* Add MongoDB network data source name (DSN) schema, [#3229](https://github.com/pydantic/pydantic/issues/3229) by [@snosratiershad](https://github.com/snosratiershad) +* Add support for multiple dotenv files, [#3222](https://github.com/pydantic/pydantic/issues/3222) by [@rekyungmin](https://github.com/rekyungmin) +* Raise an explicit `ConfigError` when multiple fields are incorrectly set for a single validator, [#3215](https://github.com/pydantic/pydantic/issues/3215) by [@SunsetOrange](https://github.com/SunsetOrange) +* Allow ellipsis on `Field`s inside `Annotated` for `TypedDicts` required, [#3133](https://github.com/pydantic/pydantic/issues/3133) by [@ezegomez](https://github.com/ezegomez) +* Catch overflow errors in `int_validator`, [#3112](https://github.com/pydantic/pydantic/issues/3112) by [@ojii](https://github.com/ojii) +* Adds a `__rich_repr__` method to `Representation` class which enables pretty printing with [Rich](https://github.com/willmcgugan/rich), [#3099](https://github.com/pydantic/pydantic/issues/3099) by [@willmcgugan](https://github.com/willmcgugan) +* Add percent encoding in `AnyUrl` and descendent types, [#3061](https://github.com/pydantic/pydantic/issues/3061) by [@FaresAhmedb](https://github.com/FaresAhmedb) +* `validate_arguments` decorator now supports `alias`, [#3019](https://github.com/pydantic/pydantic/issues/3019) by [@MAD-py](https://github.com/MAD-py) +* Avoid `__dict__` and `__weakref__` attributes in `AnyUrl` and IP address fields, [#2890](https://github.com/pydantic/pydantic/issues/2890) by [@nuno-andre](https://github.com/nuno-andre) +* Add ability to use `Final` in a field type annotation, [#2766](https://github.com/pydantic/pydantic/issues/2766) by [@uriyyo](https://github.com/uriyyo) +* Update requirement to `typing_extensions>=4.1.0` to guarantee `dataclass_transform` is available, [#4424](https://github.com/pydantic/pydantic/issues/4424) by [@commonism](https://github.com/commonism) +* Add Explosion and AWS to main sponsors, [#4413](https://github.com/pydantic/pydantic/issues/4413) by [@samuelcolvin](https://github.com/samuelcolvin) +* Update documentation for `copy_on_model_validation` to reflect recent changes, [#4369](https://github.com/pydantic/pydantic/issues/4369) by [@samuelcolvin](https://github.com/samuelcolvin) +* Runtime warning if `__slots__` is passed to `create_model`, `__slots__` is then ignored, [#4432](https://github.com/pydantic/pydantic/issues/4432) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add type hints to `BaseSettings.Config` to avoid mypy errors, also correct mypy version compatibility notice in docs, [#4450](https://github.com/pydantic/pydantic/issues/4450) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v1.10.0b1 (2022-08-24) + +Pre-release, see [the GitHub release](https://github.com/pydantic/pydantic/releases/tag/v1.10.0b1) for details. + +## v1.10.0a2 (2022-08-24) + +Pre-release, see [the GitHub release](https://github.com/pydantic/pydantic/releases/tag/v1.10.0a2) for details. + +## v1.10.0a1 (2022-08-22) + +Pre-release, see [the GitHub release](https://github.com/pydantic/pydantic/releases/tag/v1.10.0a1) for details. + +## v1.9.2 (2022-08-11) + +**Revert Breaking Change**: _v1.9.1_ introduced a breaking change where model fields were +deep copied by default, this release reverts the default behaviour to match _v1.9.0_ and before, +while also allow deep-copy behaviour via `copy_on_model_validation = 'deep'`. See [#4092](https://github.com/pydantic/pydantic/issues/4092) for more information. + +* Allow for shallow copies of model fields, `Config.copy_on_model_validation` is now a str which must be + `'none'`, `'deep'`, or `'shallow'` corresponding to not copying, deep copy & shallow copy; default `'shallow'`, + [#4093](https://github.com/pydantic/pydantic/issues/4093) by [@timkpaine](https://github.com/timkpaine) + +## v1.9.1 (2022-05-19) + +Thank you to pydantic's sponsors: +@tiangolo, [@stellargraph](https://github.com/stellargraph), [@JonasKs](https://github.com/JonasKs), [@grillazz](https://github.com/grillazz), [@Mazyod](https://github.com/Mazyod), [@kevinalh](https://github.com/kevinalh), [@chdsbd](https://github.com/chdsbd), [@povilasb](https://github.com/povilasb), [@povilasb](https://github.com/povilasb), [@jina-ai](https://github.com/jina-ai), +@mainframeindustries, [@robusta-dev](https://github.com/robusta-dev), [@SendCloud](https://github.com/SendCloud), [@rszamszur](https://github.com/rszamszur), [@jodal](https://github.com/jodal), [@hardbyte](https://github.com/hardbyte), [@corleyma](https://github.com/corleyma), [@daddycocoaman](https://github.com/daddycocoaman), +@Rehket, [@jokull](https://github.com/jokull), [@reillysiemens](https://github.com/reillysiemens), [@westonsteimel](https://github.com/westonsteimel), [@primer-io](https://github.com/primer-io), [@koxudaxi](https://github.com/koxudaxi), [@browniebroke](https://github.com/browniebroke), [@stradivari96](https://github.com/stradivari96), +@adriangb, [@kamalgill](https://github.com/kamalgill), [@jqueguiner](https://github.com/jqueguiner), [@dev-zero](https://github.com/dev-zero), [@datarootsio](https://github.com/datarootsio), [@RedCarpetUp](https://github.com/RedCarpetUp) +for their kind support. + +* Limit the size of `generics._generic_types_cache` and `generics._assigned_parameters` + to avoid unlimited increase in memory usage, [#4083](https://github.com/pydantic/pydantic/issues/4083) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add Jupyverse and FPS as Jupyter projects using pydantic, [#4082](https://github.com/pydantic/pydantic/issues/4082) by [@davidbrochart](https://github.com/davidbrochart) +* Speedup `__isinstancecheck__` on pydantic models when the type is not a model, may also avoid memory "leaks", [#4081](https://github.com/pydantic/pydantic/issues/4081) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fix in-place modification of `FieldInfo` that caused problems with PEP 593 type aliases, [#4067](https://github.com/pydantic/pydantic/issues/4067) by [@adriangb](https://github.com/adriangb) +* Add support for autocomplete in VS Code via `__dataclass_transform__` when using `pydantic.dataclasses.dataclass`, [#4006](https://github.com/pydantic/pydantic/issues/4006) by [@giuliano-oliveira](https://github.com/giuliano-oliveira) +* Remove benchmarks from codebase and docs, [#3973](https://github.com/pydantic/pydantic/issues/3973) by [@samuelcolvin](https://github.com/samuelcolvin) +* Typing checking with pyright in CI, improve docs on vscode/pylance/pyright, [#3972](https://github.com/pydantic/pydantic/issues/3972) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fix nested Python dataclass schema regression, [#3819](https://github.com/pydantic/pydantic/issues/3819) by [@himbeles](https://github.com/himbeles) +* Update documentation about lazy evaluation of sources for Settings, [#3806](https://github.com/pydantic/pydantic/issues/3806) by [@garyd203](https://github.com/garyd203) +* Prevent subclasses of bytes being converted to bytes, [#3706](https://github.com/pydantic/pydantic/issues/3706) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fixed "error checking inheritance of" when using PEP585 and PEP604 type hints, [#3681](https://github.com/pydantic/pydantic/issues/3681) by [@aleksul](https://github.com/aleksul) +* Allow self referencing `ClassVar`s in models, [#3679](https://github.com/pydantic/pydantic/issues/3679) by [@samuelcolvin](https://github.com/samuelcolvin) +* **Breaking Change, see [#4106](https://github.com/pydantic/pydantic/issues/4106)**: Fix issue with self-referencing dataclass, [#3675](https://github.com/pydantic/pydantic/issues/3675) by [@uriyyo](https://github.com/uriyyo) +* Include non-standard port numbers in rendered URLs, [#3652](https://github.com/pydantic/pydantic/issues/3652) by [@dolfinus](https://github.com/dolfinus) +* `Config.copy_on_model_validation` does a deep copy and not a shallow one, [#3641](https://github.com/pydantic/pydantic/issues/3641) by [@PrettyWood](https://github.com/PrettyWood) +* fix: clarify that discriminated unions do not support singletons, [#3636](https://github.com/pydantic/pydantic/issues/3636) by [@tommilligan](https://github.com/tommilligan) +* Add `read_text(encoding='utf-8')` for `setup.py`, [#3625](https://github.com/pydantic/pydantic/issues/3625) by [@hswong3i](https://github.com/hswong3i) +* Fix JSON Schema generation for Discriminated Unions within lists, [#3608](https://github.com/pydantic/pydantic/issues/3608) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v1.9.0 (2021-12-31) + +Thank you to pydantic's sponsors: +@sthagen, [@timdrijvers](https://github.com/timdrijvers), [@toinbis](https://github.com/toinbis), [@koxudaxi](https://github.com/koxudaxi), [@ginomempin](https://github.com/ginomempin), [@primer-io](https://github.com/primer-io), [@and-semakin](https://github.com/and-semakin), [@westonsteimel](https://github.com/westonsteimel), [@reillysiemens](https://github.com/reillysiemens), +@es3n1n, [@jokull](https://github.com/jokull), [@JonasKs](https://github.com/JonasKs), [@Rehket](https://github.com/Rehket), [@corleyma](https://github.com/corleyma), [@daddycocoaman](https://github.com/daddycocoaman), [@hardbyte](https://github.com/hardbyte), [@datarootsio](https://github.com/datarootsio), [@jodal](https://github.com/jodal), [@aminalaee](https://github.com/aminalaee), [@rafsaf](https://github.com/rafsaf), +@jqueguiner, [@chdsbd](https://github.com/chdsbd), [@kevinalh](https://github.com/kevinalh), [@Mazyod](https://github.com/Mazyod), [@grillazz](https://github.com/grillazz), [@JonasKs](https://github.com/JonasKs), [@simw](https://github.com/simw), [@leynier](https://github.com/leynier), [@xfenix](https://github.com/xfenix) +for their kind support. + +### Highlights + +* add Python 3.10 support, [#2885](https://github.com/pydantic/pydantic/issues/2885) by [@PrettyWood](https://github.com/PrettyWood) +* [Discriminated unions](https://docs.pydantic.dev/usage/types/#discriminated-unions-aka-tagged-unions), [#619](https://github.com/pydantic/pydantic/issues/619) by [@PrettyWood](https://github.com/PrettyWood) +* [`Config.smart_union` for better union logic](https://docs.pydantic.dev/usage/model_config/#smart-union), [#2092](https://github.com/pydantic/pydantic/issues/2092) by [@PrettyWood](https://github.com/PrettyWood) +* Binaries for Macos M1 CPUs, [#3498](https://github.com/pydantic/pydantic/issues/3498) by [@samuelcolvin](https://github.com/samuelcolvin) +* Complex types can be set via [nested environment variables](https://docs.pydantic.dev/usage/settings/#parsing-environment-variable-values), e.g. `foo___bar`, [#3159](https://github.com/pydantic/pydantic/issues/3159) by [@Air-Mark](https://github.com/Air-Mark) +* add a dark mode to _pydantic_ documentation, [#2913](https://github.com/pydantic/pydantic/issues/2913) by [@gbdlin](https://github.com/gbdlin) +* Add support for autocomplete in VS Code via `__dataclass_transform__`, [#2721](https://github.com/pydantic/pydantic/issues/2721) by [@tiangolo](https://github.com/tiangolo) +* Add "exclude" as a field parameter so that it can be configured using model config, [#660](https://github.com/pydantic/pydantic/issues/660) by [@daviskirk](https://github.com/daviskirk) + +### v1.9.0 (2021-12-31) Changes + +* Apply `update_forward_refs` to `Config.json_encodes` prevent name clashes in types defined via strings, [#3583](https://github.com/pydantic/pydantic/issues/3583) by [@samuelcolvin](https://github.com/samuelcolvin) +* Extend pydantic's mypy plugin to support mypy versions `0.910`, `0.920`, `0.921` & `0.930`, [#3573](https://github.com/pydantic/pydantic/issues/3573) & [#3594](https://github.com/pydantic/pydantic/issues/3594) by [@PrettyWood](https://github.com/PrettyWood), [@christianbundy](https://github.com/christianbundy), [@samuelcolvin](https://github.com/samuelcolvin) + +### v1.9.0a2 (2021-12-24) Changes + +* support generic models with discriminated union, [#3551](https://github.com/pydantic/pydantic/issues/3551) by [@PrettyWood](https://github.com/PrettyWood) +* keep old behaviour of `json()` by default, [#3542](https://github.com/pydantic/pydantic/issues/3542) by [@PrettyWood](https://github.com/PrettyWood) +* Removed typing-only `__root__` attribute from `BaseModel`, [#3540](https://github.com/pydantic/pydantic/issues/3540) by [@layday](https://github.com/layday) +* Build Python 3.10 wheels, [#3539](https://github.com/pydantic/pydantic/issues/3539) by [@mbachry](https://github.com/mbachry) +* Fix display of `extra` fields with model `__repr__`, [#3234](https://github.com/pydantic/pydantic/issues/3234) by [@cocolman](https://github.com/cocolman) +* models copied via `Config.copy_on_model_validation` always have all fields, [#3201](https://github.com/pydantic/pydantic/issues/3201) by [@PrettyWood](https://github.com/PrettyWood) +* nested ORM from nested dictionaries, [#3182](https://github.com/pydantic/pydantic/issues/3182) by [@PrettyWood](https://github.com/PrettyWood) +* fix link to discriminated union section by [@PrettyWood](https://github.com/PrettyWood) + +### v1.9.0a1 (2021-12-18) Changes + +* Add support for `Decimal`-specific validation configurations in `Field()`, additionally to using `condecimal()`, + to allow better support from editors and tooling, [#3507](https://github.com/pydantic/pydantic/issues/3507) by [@tiangolo](https://github.com/tiangolo) +* Add `arm64` binaries suitable for MacOS with an M1 CPU to PyPI, [#3498](https://github.com/pydantic/pydantic/issues/3498) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fix issue where `None` was considered invalid when using a `Union` type containing `Any` or `object`, [#3444](https://github.com/pydantic/pydantic/issues/3444) by [@tharradine](https://github.com/tharradine) +* When generating field schema, pass optional `field` argument (of type + `pydantic.fields.ModelField`) to `__modify_schema__()` if present, [#3434](https://github.com/pydantic/pydantic/issues/3434) by [@jasujm](https://github.com/jasujm) +* Fix issue when pydantic fail to parse `typing.ClassVar` string type annotation, [#3401](https://github.com/pydantic/pydantic/issues/3401) by [@uriyyo](https://github.com/uriyyo) +* Mention Python >= 3.9.2 as an alternative to `typing_extensions.TypedDict`, [#3374](https://github.com/pydantic/pydantic/issues/3374) by [@BvB93](https://github.com/BvB93) +* Changed the validator method name in the [Custom Errors example](https://docs.pydantic.dev/usage/models/#custom-errors) + to more accurately describe what the validator is doing; changed from `name_must_contain_space` to ` value_must_equal_bar`, [#3327](https://github.com/pydantic/pydantic/issues/3327) by [@michaelrios28](https://github.com/michaelrios28) +* Add `AmqpDsn` class, [#3254](https://github.com/pydantic/pydantic/issues/3254) by [@kludex](https://github.com/kludex) +* Always use `Enum` value as default in generated JSON schema, [#3190](https://github.com/pydantic/pydantic/issues/3190) by [@joaommartins](https://github.com/joaommartins) +* Add support for Mypy 0.920, [#3175](https://github.com/pydantic/pydantic/issues/3175) by [@christianbundy](https://github.com/christianbundy) +* `validate_arguments` now supports `extra` customization (used to always be `Extra.forbid`), [#3161](https://github.com/pydantic/pydantic/issues/3161) by [@PrettyWood](https://github.com/PrettyWood) +* Complex types can be set by nested environment variables, [#3159](https://github.com/pydantic/pydantic/issues/3159) by [@Air-Mark](https://github.com/Air-Mark) +* Fix mypy plugin to collect fields based on `pydantic.utils.is_valid_field` so that it ignores untyped private variables, [#3146](https://github.com/pydantic/pydantic/issues/3146) by [@hi-ogawa](https://github.com/hi-ogawa) +* fix `validate_arguments` issue with `Config.validate_all`, [#3135](https://github.com/pydantic/pydantic/issues/3135) by [@PrettyWood](https://github.com/PrettyWood) +* avoid dict coercion when using dict subclasses as field type, [#3122](https://github.com/pydantic/pydantic/issues/3122) by [@PrettyWood](https://github.com/PrettyWood) +* add support for `object` type, [#3062](https://github.com/pydantic/pydantic/issues/3062) by [@PrettyWood](https://github.com/PrettyWood) +* Updates pydantic dataclasses to keep `_special` properties on parent classes, [#3043](https://github.com/pydantic/pydantic/issues/3043) by [@zulrang](https://github.com/zulrang) +* Add a `TypedDict` class for error objects, [#3038](https://github.com/pydantic/pydantic/issues/3038) by [@matthewhughes934](https://github.com/matthewhughes934) +* Fix support for using a subclass of an annotation as a default, [#3018](https://github.com/pydantic/pydantic/issues/3018) by [@JacobHayes](https://github.com/JacobHayes) +* make `create_model_from_typeddict` mypy compliant, [#3008](https://github.com/pydantic/pydantic/issues/3008) by [@PrettyWood](https://github.com/PrettyWood) +* Make multiple inheritance work when using `PrivateAttr`, [#2989](https://github.com/pydantic/pydantic/issues/2989) by [@hmvp](https://github.com/hmvp) +* Parse environment variables as JSON, if they have a `Union` type with a complex subfield, [#2936](https://github.com/pydantic/pydantic/issues/2936) by [@cbartz](https://github.com/cbartz) +* Prevent `StrictStr` permitting `Enum` values where the enum inherits from `str`, [#2929](https://github.com/pydantic/pydantic/issues/2929) by [@samuelcolvin](https://github.com/samuelcolvin) +* Make `SecretsSettingsSource` parse values being assigned to fields of complex types when sourced from a secrets file, + just as when sourced from environment variables, [#2917](https://github.com/pydantic/pydantic/issues/2917) by [@davidmreed](https://github.com/davidmreed) +* add a dark mode to _pydantic_ documentation, [#2913](https://github.com/pydantic/pydantic/issues/2913) by [@gbdlin](https://github.com/gbdlin) +* Make `pydantic-mypy` plugin compatible with `pyproject.toml` configuration, consistent with `mypy` changes. + See the [doc](https://docs.pydantic.dev/mypy_plugin/#configuring-the-plugin) for more information, [#2908](https://github.com/pydantic/pydantic/issues/2908) by [@jrwalk](https://github.com/jrwalk) +* add Python 3.10 support, [#2885](https://github.com/pydantic/pydantic/issues/2885) by [@PrettyWood](https://github.com/PrettyWood) +* Correctly parse generic models with `Json[T]`, [#2860](https://github.com/pydantic/pydantic/issues/2860) by [@geekingfrog](https://github.com/geekingfrog) +* Update contrib docs re: Python version to use for building docs, [#2856](https://github.com/pydantic/pydantic/issues/2856) by [@paxcodes](https://github.com/paxcodes) +* Clarify documentation about _pydantic_'s support for custom validation and strict type checking, + despite _pydantic_ being primarily a parsing library, [#2855](https://github.com/pydantic/pydantic/issues/2855) by [@paxcodes](https://github.com/paxcodes) +* Fix schema generation for `Deque` fields, [#2810](https://github.com/pydantic/pydantic/issues/2810) by [@sergejkozin](https://github.com/sergejkozin) +* fix an edge case when mixing constraints and `Literal`, [#2794](https://github.com/pydantic/pydantic/issues/2794) by [@PrettyWood](https://github.com/PrettyWood) +* Fix postponed annotation resolution for `NamedTuple` and `TypedDict` when they're used directly as the type of fields + within Pydantic models, [#2760](https://github.com/pydantic/pydantic/issues/2760) by [@jameysharp](https://github.com/jameysharp) +* Fix bug when `mypy` plugin fails on `construct` method call for `BaseSettings` derived classes, [#2753](https://github.com/pydantic/pydantic/issues/2753) by [@uriyyo](https://github.com/uriyyo) +* Add function overloading for a `pydantic.create_model` function, [#2748](https://github.com/pydantic/pydantic/issues/2748) by [@uriyyo](https://github.com/uriyyo) +* Fix mypy plugin issue with self field declaration, [#2743](https://github.com/pydantic/pydantic/issues/2743) by [@uriyyo](https://github.com/uriyyo) +* The colon at the end of the line "The fields which were supplied when user was initialised:" suggests that the code following it is related. + Changed it to a period, [#2733](https://github.com/pydantic/pydantic/issues/2733) by [@krisaoe](https://github.com/krisaoe) +* Renamed variable `schema` to `schema_` to avoid shadowing of global variable name, [#2724](https://github.com/pydantic/pydantic/issues/2724) by [@shahriyarr](https://github.com/shahriyarr) +* Add support for autocomplete in VS Code via `__dataclass_transform__`, [#2721](https://github.com/pydantic/pydantic/issues/2721) by [@tiangolo](https://github.com/tiangolo) +* add missing type annotations in `BaseConfig` and handle `max_length = 0`, [#2719](https://github.com/pydantic/pydantic/issues/2719) by [@PrettyWood](https://github.com/PrettyWood) +* Change `orm_mode` checking to allow recursive ORM mode parsing with dicts, [#2718](https://github.com/pydantic/pydantic/issues/2718) by [@nuno-andre](https://github.com/nuno-andre) +* Add episode 313 of the *Talk Python To Me* podcast, where Michael Kennedy and Samuel Colvin discuss *pydantic*, to the docs, [#2712](https://github.com/pydantic/pydantic/issues/2712) by [@RatulMaharaj](https://github.com/RatulMaharaj) +* fix JSON schema generation when a field is of type `NamedTuple` and has a default value, [#2707](https://github.com/pydantic/pydantic/issues/2707) by [@PrettyWood](https://github.com/PrettyWood) +* `Enum` fields now properly support extra kwargs in schema generation, [#2697](https://github.com/pydantic/pydantic/issues/2697) by [@sammchardy](https://github.com/sammchardy) +* **Breaking Change, see [#3780](https://github.com/pydantic/pydantic/issues/3780)**: Make serialization of referenced pydantic models possible, [#2650](https://github.com/pydantic/pydantic/issues/2650) by [@PrettyWood](https://github.com/PrettyWood) +* Add `uniqueItems` option to `ConstrainedList`, [#2618](https://github.com/pydantic/pydantic/issues/2618) by [@nuno-andre](https://github.com/nuno-andre) +* Try to evaluate forward refs automatically at model creation, [#2588](https://github.com/pydantic/pydantic/issues/2588) by [@uriyyo](https://github.com/uriyyo) +* Switch docs preview and coverage display to use [smokeshow](https://smokeshow.helpmanual.io/), [#2580](https://github.com/pydantic/pydantic/issues/2580) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add `__version__` attribute to pydantic module, [#2572](https://github.com/pydantic/pydantic/issues/2572) by [@paxcodes](https://github.com/paxcodes) +* Add `postgresql+asyncpg`, `postgresql+pg8000`, `postgresql+psycopg2`, `postgresql+psycopg2cffi`, `postgresql+py-postgresql` + and `postgresql+pygresql` schemes for `PostgresDsn`, [#2567](https://github.com/pydantic/pydantic/issues/2567) by [@postgres-asyncpg](https://github.com/postgres-asyncpg) +* Enable the Hypothesis plugin to generate a constrained decimal when the `decimal_places` argument is specified, [#2524](https://github.com/pydantic/pydantic/issues/2524) by [@cwe5590](https://github.com/cwe5590) +* Allow `collections.abc.Callable` to be used as type in Python 3.9, [#2519](https://github.com/pydantic/pydantic/issues/2519) by [@daviskirk](https://github.com/daviskirk) +* Documentation update how to custom compile pydantic when using pip install, small change in `setup.py` + to allow for custom CFLAGS when compiling, [#2517](https://github.com/pydantic/pydantic/issues/2517) by [@peterroelants](https://github.com/peterroelants) +* remove side effect of `default_factory` to run it only once even if `Config.validate_all` is set, [#2515](https://github.com/pydantic/pydantic/issues/2515) by [@PrettyWood](https://github.com/PrettyWood) +* Add lookahead to ip regexes for `AnyUrl` hosts. This allows urls with DNS labels + looking like IPs to validate as they are perfectly valid host names, [#2512](https://github.com/pydantic/pydantic/issues/2512) by [@sbv-csis](https://github.com/sbv-csis) +* Set `minItems` and `maxItems` in generated JSON schema for fixed-length tuples, [#2497](https://github.com/pydantic/pydantic/issues/2497) by [@PrettyWood](https://github.com/PrettyWood) +* Add `strict` argument to `conbytes`, [#2489](https://github.com/pydantic/pydantic/issues/2489) by [@koxudaxi](https://github.com/koxudaxi) +* Support user defined generic field types in generic models, [#2465](https://github.com/pydantic/pydantic/issues/2465) by [@daviskirk](https://github.com/daviskirk) +* Add an example and a short explanation of subclassing `GetterDict` to docs, [#2463](https://github.com/pydantic/pydantic/issues/2463) by [@nuno-andre](https://github.com/nuno-andre) +* add `KafkaDsn` type, `HttpUrl` now has default port 80 for http and 443 for https, [#2447](https://github.com/pydantic/pydantic/issues/2447) by [@MihanixA](https://github.com/MihanixA) +* Add `PastDate` and `FutureDate` types, [#2425](https://github.com/pydantic/pydantic/issues/2425) by [@Kludex](https://github.com/Kludex) +* Support generating schema for `Generic` fields with subtypes, [#2375](https://github.com/pydantic/pydantic/issues/2375) by [@maximberg](https://github.com/maximberg) +* fix(encoder): serialize `NameEmail` to str, [#2341](https://github.com/pydantic/pydantic/issues/2341) by [@alecgerona](https://github.com/alecgerona) +* add `Config.smart_union` to prevent coercion in `Union` if possible, see + [the doc](https://docs.pydantic.dev/usage/model_config/#smart-union) for more information, [#2092](https://github.com/pydantic/pydantic/issues/2092) by [@PrettyWood](https://github.com/PrettyWood) +* Add ability to use `typing.Counter` as a model field type, [#2060](https://github.com/pydantic/pydantic/issues/2060) by [@uriyyo](https://github.com/uriyyo) +* Add parameterised subclasses to `__bases__` when constructing new parameterised classes, so that `A <: B => A[int] <: B[int]`, [#2007](https://github.com/pydantic/pydantic/issues/2007) by [@diabolo-dan](https://github.com/diabolo-dan) +* Create `FileUrl` type that allows URLs that conform to [RFC 8089](https://tools.ietf.org/html/rfc8089#section-2). + Add `host_required` parameter, which is `True` by default (`AnyUrl` and subclasses), `False` in `RedisDsn`, `FileUrl`, [#1983](https://github.com/pydantic/pydantic/issues/1983) by [@vgerak](https://github.com/vgerak) +* add `confrozenset()`, analogous to `conset()` and `conlist()`, [#1897](https://github.com/pydantic/pydantic/issues/1897) by [@PrettyWood](https://github.com/PrettyWood) +* stop calling parent class `root_validator` if overridden, [#1895](https://github.com/pydantic/pydantic/issues/1895) by [@PrettyWood](https://github.com/PrettyWood) +* Add `repr` (defaults to `True`) parameter to `Field`, to hide it from the default representation of the `BaseModel`, [#1831](https://github.com/pydantic/pydantic/issues/1831) by [@fnep](https://github.com/fnep) +* Accept empty query/fragment URL parts, [#1807](https://github.com/pydantic/pydantic/issues/1807) by [@xavier](https://github.com/xavier) + +## v1.8.2 (2021-05-11) + +!!! warning + A security vulnerability, level "moderate" is fixed in v1.8.2. Please upgrade **ASAP**. + See security advisory [CVE-2021-29510](https://github.com/pydantic/pydantic/security/advisories/GHSA-5jqp-qgf6-3pvh) + +* **Security fix:** Fix `date` and `datetime` parsing so passing either `'infinity'` or `float('inf')` + (or their negative values) does not cause an infinite loop, + see security advisory [CVE-2021-29510](https://github.com/pydantic/pydantic/security/advisories/GHSA-5jqp-qgf6-3pvh) +* fix schema generation with Enum by generating a valid name, [#2575](https://github.com/pydantic/pydantic/issues/2575) by [@PrettyWood](https://github.com/PrettyWood) +* fix JSON schema generation with a `Literal` of an enum member, [#2536](https://github.com/pydantic/pydantic/issues/2536) by [@PrettyWood](https://github.com/PrettyWood) +* Fix bug with configurations declarations that are passed as + keyword arguments during class creation, [#2532](https://github.com/pydantic/pydantic/issues/2532) by [@uriyyo](https://github.com/uriyyo) +* Allow passing `json_encoders` in class kwargs, [#2521](https://github.com/pydantic/pydantic/issues/2521) by [@layday](https://github.com/layday) +* support arbitrary types with custom `__eq__`, [#2483](https://github.com/pydantic/pydantic/issues/2483) by [@PrettyWood](https://github.com/PrettyWood) +* support `Annotated` in `validate_arguments` and in generic models with Python 3.9, [#2483](https://github.com/pydantic/pydantic/issues/2483) by [@PrettyWood](https://github.com/PrettyWood) + +## v1.8.1 (2021-03-03) + +Bug fixes for regressions and new features from `v1.8` + +* allow elements of `Config.field` to update elements of a `Field`, [#2461](https://github.com/pydantic/pydantic/issues/2461) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix validation with a `BaseModel` field and a custom root type, [#2449](https://github.com/pydantic/pydantic/issues/2449) by [@PrettyWood](https://github.com/PrettyWood) +* expose `Pattern` encoder to `fastapi`, [#2444](https://github.com/pydantic/pydantic/issues/2444) by [@PrettyWood](https://github.com/PrettyWood) +* enable the Hypothesis plugin to generate a constrained float when the `multiple_of` argument is specified, [#2442](https://github.com/pydantic/pydantic/issues/2442) by [@tobi-lipede-oodle](https://github.com/tobi-lipede-oodle) +* Avoid `RecursionError` when using some types like `Enum` or `Literal` with generic models, [#2436](https://github.com/pydantic/pydantic/issues/2436) by [@PrettyWood](https://github.com/PrettyWood) +* do not overwrite declared `__hash__` in subclasses of a model, [#2422](https://github.com/pydantic/pydantic/issues/2422) by [@PrettyWood](https://github.com/PrettyWood) +* fix `mypy` complaints on `Path` and `UUID` related custom types, [#2418](https://github.com/pydantic/pydantic/issues/2418) by [@PrettyWood](https://github.com/PrettyWood) +* Support properly variable length tuples of compound types, [#2416](https://github.com/pydantic/pydantic/issues/2416) by [@PrettyWood](https://github.com/PrettyWood) + +## v1.8 (2021-02-26) + +Thank you to pydantic's sponsors: +@jorgecarleitao, [@BCarley](https://github.com/BCarley), [@chdsbd](https://github.com/chdsbd), [@tiangolo](https://github.com/tiangolo), [@matin](https://github.com/matin), [@linusg](https://github.com/linusg), [@kevinalh](https://github.com/kevinalh), [@koxudaxi](https://github.com/koxudaxi), [@timdrijvers](https://github.com/timdrijvers), [@mkeen](https://github.com/mkeen), [@meadsteve](https://github.com/meadsteve), +@ginomempin, [@primer-io](https://github.com/primer-io), [@and-semakin](https://github.com/and-semakin), [@tomthorogood](https://github.com/tomthorogood), [@AjitZK](https://github.com/AjitZK), [@westonsteimel](https://github.com/westonsteimel), [@Mazyod](https://github.com/Mazyod), [@christippett](https://github.com/christippett), [@CarlosDomingues](https://github.com/CarlosDomingues), +@Kludex, [@r-m-n](https://github.com/r-m-n) +for their kind support. + +### Highlights + +* [Hypothesis plugin](https://docs.pydantic.dev/hypothesis_plugin/) for testing, [#2097](https://github.com/pydantic/pydantic/issues/2097) by [@Zac-HD](https://github.com/Zac-HD) +* support for [`NamedTuple` and `TypedDict`](https://docs.pydantic.dev/usage/types/#annotated-types), [#2216](https://github.com/pydantic/pydantic/issues/2216) by [@PrettyWood](https://github.com/PrettyWood) +* Support [`Annotated` hints on model fields](https://docs.pydantic.dev/usage/schema/#typingannotated-fields), [#2147](https://github.com/pydantic/pydantic/issues/2147) by [@JacobHayes](https://github.com/JacobHayes) +* [`frozen` parameter on `Config`](https://docs.pydantic.dev/usage/model_config/) to allow models to be hashed, [#1880](https://github.com/pydantic/pydantic/issues/1880) by [@rhuille](https://github.com/rhuille) + +### Changes + +* **Breaking Change**, remove old deprecation aliases from v1, [#2415](https://github.com/pydantic/pydantic/issues/2415) by [@samuelcolvin](https://github.com/samuelcolvin): + * remove notes on migrating to v1 in docs + * remove `Schema` which was replaced by `Field` + * remove `Config.case_insensitive` which was replaced by `Config.case_sensitive` (default `False`) + * remove `Config.allow_population_by_alias` which was replaced by `Config.allow_population_by_field_name` + * remove `model.fields` which was replaced by `model.__fields__` + * remove `model.to_string()` which was replaced by `str(model)` + * remove `model.__values__` which was replaced by `model.__dict__` +* **Breaking Change:** always validate only first sublevel items with `each_item`. + There were indeed some edge cases with some compound types where the validated items were the last sublevel ones, [#1933](https://github.com/pydantic/pydantic/issues/1933) by [@PrettyWood](https://github.com/PrettyWood) +* Update docs extensions to fix local syntax highlighting, [#2400](https://github.com/pydantic/pydantic/issues/2400) by [@daviskirk](https://github.com/daviskirk) +* fix: allow `utils.lenient_issubclass` to handle `typing.GenericAlias` objects like `list[str]` in Python >= 3.9, [#2399](https://github.com/pydantic/pydantic/issues/2399) by [@daviskirk](https://github.com/daviskirk) +* Improve field declaration for _pydantic_ `dataclass` by allowing the usage of _pydantic_ `Field` or `'metadata'` kwarg of `dataclasses.field`, [#2384](https://github.com/pydantic/pydantic/issues/2384) by [@PrettyWood](https://github.com/PrettyWood) +* Making `typing-extensions` a required dependency, [#2368](https://github.com/pydantic/pydantic/issues/2368) by [@samuelcolvin](https://github.com/samuelcolvin) +* Make `resolve_annotations` more lenient, allowing for missing modules, [#2363](https://github.com/pydantic/pydantic/issues/2363) by [@samuelcolvin](https://github.com/samuelcolvin) +* Allow configuring models through class kwargs, [#2356](https://github.com/pydantic/pydantic/issues/2356) by [@Bobronium](https://github.com/Bobronium) +* Prevent `Mapping` subclasses from always being coerced to `dict`, [#2325](https://github.com/pydantic/pydantic/issues/2325) by [@ofek](https://github.com/ofek) +* fix: allow `None` for type `Optional[conset / conlist]`, [#2320](https://github.com/pydantic/pydantic/issues/2320) by [@PrettyWood](https://github.com/PrettyWood) +* Support empty tuple type, [#2318](https://github.com/pydantic/pydantic/issues/2318) by [@PrettyWood](https://github.com/PrettyWood) +* fix: `python_requires` metadata to require >=3.6.1, [#2306](https://github.com/pydantic/pydantic/issues/2306) by [@hukkinj1](https://github.com/hukkinj1) +* Properly encode `Decimal` with, or without any decimal places, [#2293](https://github.com/pydantic/pydantic/issues/2293) by [@hultner](https://github.com/hultner) +* fix: update `__fields_set__` in `BaseModel.copy(update=…)`, [#2290](https://github.com/pydantic/pydantic/issues/2290) by [@PrettyWood](https://github.com/PrettyWood) +* fix: keep order of fields with `BaseModel.construct()`, [#2281](https://github.com/pydantic/pydantic/issues/2281) by [@PrettyWood](https://github.com/PrettyWood) +* Support generating schema for Generic fields, [#2262](https://github.com/pydantic/pydantic/issues/2262) by [@maximberg](https://github.com/maximberg) +* Fix `validate_decorator` so `**kwargs` doesn't exclude values when the keyword + has the same name as the `*args` or `**kwargs` names, [#2251](https://github.com/pydantic/pydantic/issues/2251) by [@cybojenix](https://github.com/cybojenix) +* Prevent overriding positional arguments with keyword arguments in + `validate_arguments`, as per behaviour with native functions, [#2249](https://github.com/pydantic/pydantic/issues/2249) by [@cybojenix](https://github.com/cybojenix) +* add documentation for `con*` type functions, [#2242](https://github.com/pydantic/pydantic/issues/2242) by [@tayoogunbiyi](https://github.com/tayoogunbiyi) +* Support custom root type (aka `__root__`) when using `parse_obj()` with nested models, [#2238](https://github.com/pydantic/pydantic/issues/2238) by [@PrettyWood](https://github.com/PrettyWood) +* Support custom root type (aka `__root__`) with `from_orm()`, [#2237](https://github.com/pydantic/pydantic/issues/2237) by [@PrettyWood](https://github.com/PrettyWood) +* ensure cythonized functions are left untouched when creating models, based on [#1944](https://github.com/pydantic/pydantic/issues/1944) by [@kollmats](https://github.com/kollmats), [#2228](https://github.com/pydantic/pydantic/issues/2228) by [@samuelcolvin](https://github.com/samuelcolvin) +* Resolve forward refs for stdlib dataclasses converted into _pydantic_ ones, [#2220](https://github.com/pydantic/pydantic/issues/2220) by [@PrettyWood](https://github.com/PrettyWood) +* Add support for `NamedTuple` and `TypedDict` types. + Those two types are now handled and validated when used inside `BaseModel` or _pydantic_ `dataclass`. + Two utils are also added `create_model_from_namedtuple` and `create_model_from_typeddict`, [#2216](https://github.com/pydantic/pydantic/issues/2216) by [@PrettyWood](https://github.com/PrettyWood) +* Do not ignore annotated fields when type is `Union[Type[...], ...]`, [#2213](https://github.com/pydantic/pydantic/issues/2213) by [@PrettyWood](https://github.com/PrettyWood) +* Raise a user-friendly `TypeError` when a `root_validator` does not return a `dict` (e.g. `None`), [#2209](https://github.com/pydantic/pydantic/issues/2209) by [@masalim2](https://github.com/masalim2) +* Add a `FrozenSet[str]` type annotation to the `allowed_schemes` argument on the `strict_url` field type, [#2198](https://github.com/pydantic/pydantic/issues/2198) by [@Midnighter](https://github.com/Midnighter) +* add `allow_mutation` constraint to `Field`, [#2195](https://github.com/pydantic/pydantic/issues/2195) by [@sblack-usu](https://github.com/sblack-usu) +* Allow `Field` with a `default_factory` to be used as an argument to a function + decorated with `validate_arguments`, [#2176](https://github.com/pydantic/pydantic/issues/2176) by [@thomascobb](https://github.com/thomascobb) +* Allow non-existent secrets directory by only issuing a warning, [#2175](https://github.com/pydantic/pydantic/issues/2175) by [@davidolrik](https://github.com/davidolrik) +* fix URL regex to parse fragment without query string, [#2168](https://github.com/pydantic/pydantic/issues/2168) by [@andrewmwhite](https://github.com/andrewmwhite) +* fix: ensure to always return one of the values in `Literal` field type, [#2166](https://github.com/pydantic/pydantic/issues/2166) by [@PrettyWood](https://github.com/PrettyWood) +* Support `typing.Annotated` hints on model fields. A `Field` may now be set in the type hint with `Annotated[..., Field(...)`; all other annotations are ignored but still visible with `get_type_hints(..., include_extras=True)`, [#2147](https://github.com/pydantic/pydantic/issues/2147) by [@JacobHayes](https://github.com/JacobHayes) +* Added `StrictBytes` type as well as `strict=False` option to `ConstrainedBytes`, [#2136](https://github.com/pydantic/pydantic/issues/2136) by [@rlizzo](https://github.com/rlizzo) +* added `Config.anystr_lower` and `to_lower` kwarg to `constr` and `conbytes`, [#2134](https://github.com/pydantic/pydantic/issues/2134) by [@tayoogunbiyi](https://github.com/tayoogunbiyi) +* Support plain `typing.Tuple` type, [#2132](https://github.com/pydantic/pydantic/issues/2132) by [@PrettyWood](https://github.com/PrettyWood) +* Add a bound method `validate` to functions decorated with `validate_arguments` + to validate parameters without actually calling the function, [#2127](https://github.com/pydantic/pydantic/issues/2127) by [@PrettyWood](https://github.com/PrettyWood) +* Add the ability to customize settings sources (add / disable / change priority order), [#2107](https://github.com/pydantic/pydantic/issues/2107) by [@kozlek](https://github.com/kozlek) +* Fix mypy complaints about most custom _pydantic_ types, [#2098](https://github.com/pydantic/pydantic/issues/2098) by [@PrettyWood](https://github.com/PrettyWood) +* Add a [Hypothesis](https://hypothesis.readthedocs.io/) plugin for easier [property-based testing](https://increment.com/testing/in-praise-of-property-based-testing/) with Pydantic's custom types - [usage details here](https://docs.pydantic.dev/hypothesis_plugin/), [#2097](https://github.com/pydantic/pydantic/issues/2097) by [@Zac-HD](https://github.com/Zac-HD) +* add validator for `None`, `NoneType` or `Literal[None]`, [#2095](https://github.com/pydantic/pydantic/issues/2095) by [@PrettyWood](https://github.com/PrettyWood) +* Handle properly fields of type `Callable` with a default value, [#2094](https://github.com/pydantic/pydantic/issues/2094) by [@PrettyWood](https://github.com/PrettyWood) +* Updated `create_model` return type annotation to return type which inherits from `__base__` argument, [#2071](https://github.com/pydantic/pydantic/issues/2071) by [@uriyyo](https://github.com/uriyyo) +* Add merged `json_encoders` inheritance, [#2064](https://github.com/pydantic/pydantic/issues/2064) by [@art049](https://github.com/art049) +* allow overwriting `ClassVar`s in sub-models without having to re-annotate them, [#2061](https://github.com/pydantic/pydantic/issues/2061) by [@layday](https://github.com/layday) +* add default encoder for `Pattern` type, [#2045](https://github.com/pydantic/pydantic/issues/2045) by [@PrettyWood](https://github.com/PrettyWood) +* Add `NonNegativeInt`, `NonPositiveInt`, `NonNegativeFloat`, `NonPositiveFloat`, [#1975](https://github.com/pydantic/pydantic/issues/1975) by [@mdavis-xyz](https://github.com/mdavis-xyz) +* Use % for percentage in string format of colors, [#1960](https://github.com/pydantic/pydantic/issues/1960) by [@EdwardBetts](https://github.com/EdwardBetts) +* Fixed issue causing `KeyError` to be raised when building schema from multiple `BaseModel` with the same names declared in separate classes, [#1912](https://github.com/pydantic/pydantic/issues/1912) by [@JSextonn](https://github.com/JSextonn) +* Add `rediss` (Redis over SSL) protocol to `RedisDsn` + Allow URLs without `user` part (e.g., `rediss://:pass@localhost`), [#1911](https://github.com/pydantic/pydantic/issues/1911) by [@TrDex](https://github.com/TrDex) +* Add a new `frozen` boolean parameter to `Config` (default: `False`). + Setting `frozen=True` does everything that `allow_mutation=False` does, and also generates a `__hash__()` method for the model. This makes instances of the model potentially hashable if all the attributes are hashable, [#1880](https://github.com/pydantic/pydantic/issues/1880) by [@rhuille](https://github.com/rhuille) +* fix schema generation with multiple Enums having the same name, [#1857](https://github.com/pydantic/pydantic/issues/1857) by [@PrettyWood](https://github.com/PrettyWood) +* Added support for 13/19 digits VISA credit cards in `PaymentCardNumber` type, [#1416](https://github.com/pydantic/pydantic/issues/1416) by [@AlexanderSov](https://github.com/AlexanderSov) +* fix: prevent `RecursionError` while using recursive `GenericModel`s, [#1370](https://github.com/pydantic/pydantic/issues/1370) by [@xppt](https://github.com/xppt) +* use `enum` for `typing.Literal` in JSON schema, [#1350](https://github.com/pydantic/pydantic/issues/1350) by [@PrettyWood](https://github.com/PrettyWood) +* Fix: some recursive models did not require `update_forward_refs` and silently behaved incorrectly, [#1201](https://github.com/pydantic/pydantic/issues/1201) by [@PrettyWood](https://github.com/PrettyWood) +* Fix bug where generic models with fields where the typevar is nested in another type `a: List[T]` are considered to be concrete. This allows these models to be subclassed and composed as expected, [#947](https://github.com/pydantic/pydantic/issues/947) by [@daviskirk](https://github.com/daviskirk) +* Add `Config.copy_on_model_validation` flag. When set to `False`, _pydantic_ will keep models used as fields + untouched on validation instead of reconstructing (copying) them, [#265](https://github.com/pydantic/pydantic/issues/265) by [@PrettyWood](https://github.com/PrettyWood) + +## v1.7.4 (2021-05-11) + +* **Security fix:** Fix `date` and `datetime` parsing so passing either `'infinity'` or `float('inf')` + (or their negative values) does not cause an infinite loop, + See security advisory [CVE-2021-29510](https://github.com/pydantic/pydantic/security/advisories/GHSA-5jqp-qgf6-3pvh) + +## v1.7.3 (2020-11-30) + +Thank you to pydantic's sponsors: +@timdrijvers, [@BCarley](https://github.com/BCarley), [@chdsbd](https://github.com/chdsbd), [@tiangolo](https://github.com/tiangolo), [@matin](https://github.com/matin), [@linusg](https://github.com/linusg), [@kevinalh](https://github.com/kevinalh), [@jorgecarleitao](https://github.com/jorgecarleitao), [@koxudaxi](https://github.com/koxudaxi), [@primer-api](https://github.com/primer-api), +@mkeen, [@meadsteve](https://github.com/meadsteve) for their kind support. + +* fix: set right default value for required (optional) fields, [#2142](https://github.com/pydantic/pydantic/issues/2142) by [@PrettyWood](https://github.com/PrettyWood) +* fix: support `underscore_attrs_are_private` with generic models, [#2138](https://github.com/pydantic/pydantic/issues/2138) by [@PrettyWood](https://github.com/PrettyWood) +* fix: update all modified field values in `root_validator` when `validate_assignment` is on, [#2116](https://github.com/pydantic/pydantic/issues/2116) by [@PrettyWood](https://github.com/PrettyWood) +* Allow pickling of `pydantic.dataclasses.dataclass` dynamically created from a built-in `dataclasses.dataclass`, [#2111](https://github.com/pydantic/pydantic/issues/2111) by [@aimestereo](https://github.com/aimestereo) +* Fix a regression where Enum fields would not propagate keyword arguments to the schema, [#2109](https://github.com/pydantic/pydantic/issues/2109) by [@bm424](https://github.com/bm424) +* Ignore `__doc__` as private attribute when `Config.underscore_attrs_are_private` is set, [#2090](https://github.com/pydantic/pydantic/issues/2090) by [@PrettyWood](https://github.com/PrettyWood) + +## v1.7.2 (2020-11-01) + +* fix slow `GenericModel` concrete model creation, allow `GenericModel` concrete name reusing in module, [#2078](https://github.com/pydantic/pydantic/issues/2078) by [@Bobronium](https://github.com/Bobronium) +* keep the order of the fields when `validate_assignment` is set, [#2073](https://github.com/pydantic/pydantic/issues/2073) by [@PrettyWood](https://github.com/PrettyWood) +* forward all the params of the stdlib `dataclass` when converted into _pydantic_ `dataclass`, [#2065](https://github.com/pydantic/pydantic/issues/2065) by [@PrettyWood](https://github.com/PrettyWood) + +## v1.7.1 (2020-10-28) + +Thank you to pydantic's sponsors: +@timdrijvers, [@BCarley](https://github.com/BCarley), [@chdsbd](https://github.com/chdsbd), [@tiangolo](https://github.com/tiangolo), [@matin](https://github.com/matin), [@linusg](https://github.com/linusg), [@kevinalh](https://github.com/kevinalh), [@jorgecarleitao](https://github.com/jorgecarleitao), [@koxudaxi](https://github.com/koxudaxi), [@primer-api](https://github.com/primer-api), [@mkeen](https://github.com/mkeen) +for their kind support. + +* fix annotation of `validate_arguments` when passing configuration as argument, [#2055](https://github.com/pydantic/pydantic/issues/2055) by [@layday](https://github.com/layday) +* Fix mypy assignment error when using `PrivateAttr`, [#2048](https://github.com/pydantic/pydantic/issues/2048) by [@aphedges](https://github.com/aphedges) +* fix `underscore_attrs_are_private` causing `TypeError` when overriding `__init__`, [#2047](https://github.com/pydantic/pydantic/issues/2047) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fixed regression introduced in v1.7 involving exception handling in field validators when `validate_assignment=True`, [#2044](https://github.com/pydantic/pydantic/issues/2044) by [@johnsabath](https://github.com/johnsabath) +* fix: _pydantic_ `dataclass` can inherit from stdlib `dataclass` + and `Config.arbitrary_types_allowed` is supported, [#2042](https://github.com/pydantic/pydantic/issues/2042) by [@PrettyWood](https://github.com/PrettyWood) + +## v1.7 (2020-10-26) + +Thank you to pydantic's sponsors: +@timdrijvers, [@BCarley](https://github.com/BCarley), [@chdsbd](https://github.com/chdsbd), [@tiangolo](https://github.com/tiangolo), [@matin](https://github.com/matin), [@linusg](https://github.com/linusg), [@kevinalh](https://github.com/kevinalh), [@jorgecarleitao](https://github.com/jorgecarleitao), [@koxudaxi](https://github.com/koxudaxi), [@primer-api](https://github.com/primer-api) +for their kind support. + +### Highlights + +* Python 3.9 support, thanks [@PrettyWood](https://github.com/PrettyWood) +* [Private model attributes](https://docs.pydantic.dev/usage/models/#private-model-attributes), thanks [@Bobronium](https://github.com/Bobronium) +* ["secrets files" support in `BaseSettings`](https://docs.pydantic.dev/usage/settings/#secret-support), thanks [@mdgilene](https://github.com/mdgilene) +* [convert stdlib dataclasses to pydantic dataclasses and use stdlib dataclasses in models](https://docs.pydantic.dev/usage/dataclasses/#stdlib-dataclasses-and-pydantic-dataclasses), thanks [@PrettyWood](https://github.com/PrettyWood) + +### Changes + +* **Breaking Change:** remove `__field_defaults__`, add `default_factory` support with `BaseModel.construct`. + Use `.get_default()` method on fields in `__fields__` attribute instead, [#1732](https://github.com/pydantic/pydantic/issues/1732) by [@PrettyWood](https://github.com/PrettyWood) +* Rearrange CI to run linting as a separate job, split install recipes for different tasks, [#2020](https://github.com/pydantic/pydantic/issues/2020) by [@samuelcolvin](https://github.com/samuelcolvin) +* Allows subclasses of generic models to make some, or all, of the superclass's type parameters concrete, while + also defining new type parameters in the subclass, [#2005](https://github.com/pydantic/pydantic/issues/2005) by [@choogeboom](https://github.com/choogeboom) +* Call validator with the correct `values` parameter type in `BaseModel.__setattr__`, + when `validate_assignment = True` in model config, [#1999](https://github.com/pydantic/pydantic/issues/1999) by [@me-ransh](https://github.com/me-ransh) +* Force `fields.Undefined` to be a singleton object, fixing inherited generic model schemas, [#1981](https://github.com/pydantic/pydantic/issues/1981) by [@daviskirk](https://github.com/daviskirk) +* Include tests in source distributions, [#1976](https://github.com/pydantic/pydantic/issues/1976) by [@sbraz](https://github.com/sbraz) +* Add ability to use `min_length/max_length` constraints with secret types, [#1974](https://github.com/pydantic/pydantic/issues/1974) by [@uriyyo](https://github.com/uriyyo) +* Also check `root_validators` when `validate_assignment` is on, [#1971](https://github.com/pydantic/pydantic/issues/1971) by [@PrettyWood](https://github.com/PrettyWood) +* Fix const validators not running when custom validators are present, [#1957](https://github.com/pydantic/pydantic/issues/1957) by [@hmvp](https://github.com/hmvp) +* add `deque` to field types, [#1935](https://github.com/pydantic/pydantic/issues/1935) by [@wozniakty](https://github.com/wozniakty) +* add basic support for Python 3.9, [#1832](https://github.com/pydantic/pydantic/issues/1832) by [@PrettyWood](https://github.com/PrettyWood) +* Fix typo in the anchor of exporting_models.md#modelcopy and incorrect description, [#1821](https://github.com/pydantic/pydantic/issues/1821) by [@KimMachineGun](https://github.com/KimMachineGun) +* Added ability for `BaseSettings` to read "secret files", [#1820](https://github.com/pydantic/pydantic/issues/1820) by [@mdgilene](https://github.com/mdgilene) +* add `parse_raw_as` utility function, [#1812](https://github.com/pydantic/pydantic/issues/1812) by [@PrettyWood](https://github.com/PrettyWood) +* Support home directory relative paths for `dotenv` files (e.g. `~/.env`), [#1803](https://github.com/pydantic/pydantic/issues/1803) by [@PrettyWood](https://github.com/PrettyWood) +* Clarify documentation for `parse_file` to show that the argument + should be a file *path* not a file-like object, [#1794](https://github.com/pydantic/pydantic/issues/1794) by [@mdavis-xyz](https://github.com/mdavis-xyz) +* Fix false positive from mypy plugin when a class nested within a `BaseModel` is named `Model`, [#1770](https://github.com/pydantic/pydantic/issues/1770) by [@selimb](https://github.com/selimb) +* add basic support of Pattern type in schema generation, [#1767](https://github.com/pydantic/pydantic/issues/1767) by [@PrettyWood](https://github.com/PrettyWood) +* Support custom title, description and default in schema of enums, [#1748](https://github.com/pydantic/pydantic/issues/1748) by [@PrettyWood](https://github.com/PrettyWood) +* Properly represent `Literal` Enums when `use_enum_values` is True, [#1747](https://github.com/pydantic/pydantic/issues/1747) by [@noelevans](https://github.com/noelevans) +* Allows timezone information to be added to strings to be formatted as time objects. Permitted formats are `Z` for UTC + or an offset for absolute positive or negative time shifts. Or the timezone data can be omitted, [#1744](https://github.com/pydantic/pydantic/issues/1744) by [@noelevans](https://github.com/noelevans) +* Add stub `__init__` with Python 3.6 signature for `ForwardRef`, [#1738](https://github.com/pydantic/pydantic/issues/1738) by [@sirtelemak](https://github.com/sirtelemak) +* Fix behaviour with forward refs and optional fields in nested models, [#1736](https://github.com/pydantic/pydantic/issues/1736) by [@PrettyWood](https://github.com/PrettyWood) +* add `Enum` and `IntEnum` as valid types for fields, [#1735](https://github.com/pydantic/pydantic/issues/1735) by [@PrettyWood](https://github.com/PrettyWood) +* Change default value of `__module__` argument of `create_model` from `None` to `'pydantic.main'`. + Set reference of created concrete model to it's module to allow pickling (not applied to models created in + functions), [#1686](https://github.com/pydantic/pydantic/issues/1686) by [@Bobronium](https://github.com/Bobronium) +* Add private attributes support, [#1679](https://github.com/pydantic/pydantic/issues/1679) by [@Bobronium](https://github.com/Bobronium) +* add `config` to `@validate_arguments`, [#1663](https://github.com/pydantic/pydantic/issues/1663) by [@samuelcolvin](https://github.com/samuelcolvin) +* Allow descendant Settings models to override env variable names for the fields defined in parent Settings models with + `env` in their `Config`. Previously only `env_prefix` configuration option was applicable, [#1561](https://github.com/pydantic/pydantic/issues/1561) by [@ojomio](https://github.com/ojomio) +* Support `ref_template` when creating schema `$ref`s, [#1479](https://github.com/pydantic/pydantic/issues/1479) by [@kilo59](https://github.com/kilo59) +* Add a `__call__` stub to `PyObject` so that mypy will know that it is callable, [#1352](https://github.com/pydantic/pydantic/issues/1352) by [@brianmaissy](https://github.com/brianmaissy) +* `pydantic.dataclasses.dataclass` decorator now supports built-in `dataclasses.dataclass`. + It is hence possible to convert an existing `dataclass` easily to add *pydantic* validation. + Moreover nested dataclasses are also supported, [#744](https://github.com/pydantic/pydantic/issues/744) by [@PrettyWood](https://github.com/PrettyWood) + +## v1.6.2 (2021-05-11) + +* **Security fix:** Fix `date` and `datetime` parsing so passing either `'infinity'` or `float('inf')` + (or their negative values) does not cause an infinite loop, + See security advisory [CVE-2021-29510](https://github.com/pydantic/pydantic/security/advisories/GHSA-5jqp-qgf6-3pvh) + +## v1.6.1 (2020-07-15) + +* fix validation and parsing of nested models with `default_factory`, [#1710](https://github.com/pydantic/pydantic/issues/1710) by [@PrettyWood](https://github.com/PrettyWood) + +## v1.6 (2020-07-11) + +Thank you to pydantic's sponsors: [@matin](https://github.com/matin), [@tiangolo](https://github.com/tiangolo), [@chdsbd](https://github.com/chdsbd), [@jorgecarleitao](https://github.com/jorgecarleitao), and 1 anonymous sponsor for their kind support. + +* Modify validators for `conlist` and `conset` to not have `always=True`, [#1682](https://github.com/pydantic/pydantic/issues/1682) by [@samuelcolvin](https://github.com/samuelcolvin) +* add port check to `AnyUrl` (can't exceed 65536) ports are 16 insigned bits: `0 <= port <= 2**16-1` src: [rfc793 header format](https://tools.ietf.org/html/rfc793#section-3.1), [#1654](https://github.com/pydantic/pydantic/issues/1654) by [@flapili](https://github.com/flapili) +* Document default `regex` anchoring semantics, [#1648](https://github.com/pydantic/pydantic/issues/1648) by [@yurikhan](https://github.com/yurikhan) +* Use `chain.from_iterable` in class_validators.py. This is a faster and more idiomatic way of using `itertools.chain`. + Instead of computing all the items in the iterable and storing them in memory, they are computed one-by-one and never + stored as a huge list. This can save on both runtime and memory space, [#1642](https://github.com/pydantic/pydantic/issues/1642) by [@cool-RR](https://github.com/cool-RR) +* Add `conset()`, analogous to `conlist()`, [#1623](https://github.com/pydantic/pydantic/issues/1623) by [@patrickkwang](https://github.com/patrickkwang) +* make *pydantic* errors (un)pickable, [#1616](https://github.com/pydantic/pydantic/issues/1616) by [@PrettyWood](https://github.com/PrettyWood) +* Allow custom encoding for `dotenv` files, [#1615](https://github.com/pydantic/pydantic/issues/1615) by [@PrettyWood](https://github.com/PrettyWood) +* Ensure `SchemaExtraCallable` is always defined to get type hints on BaseConfig, [#1614](https://github.com/pydantic/pydantic/issues/1614) by [@PrettyWood](https://github.com/PrettyWood) +* Update datetime parser to support negative timestamps, [#1600](https://github.com/pydantic/pydantic/issues/1600) by [@mlbiche](https://github.com/mlbiche) +* Update mypy, remove `AnyType` alias for `Type[Any]`, [#1598](https://github.com/pydantic/pydantic/issues/1598) by [@samuelcolvin](https://github.com/samuelcolvin) +* Adjust handling of root validators so that errors are aggregated from _all_ failing root validators, instead of reporting on only the first root validator to fail, [#1586](https://github.com/pydantic/pydantic/issues/1586) by [@beezee](https://github.com/beezee) +* Make `__modify_schema__` on Enums apply to the enum schema rather than fields that use the enum, [#1581](https://github.com/pydantic/pydantic/issues/1581) by [@therefromhere](https://github.com/therefromhere) +* Fix behavior of `__all__` key when used in conjunction with index keys in advanced include/exclude of fields that are sequences, [#1579](https://github.com/pydantic/pydantic/issues/1579) by [@xspirus](https://github.com/xspirus) +* Subclass validators do not run when referencing a `List` field defined in a parent class when `each_item=True`. Added an example to the docs illustrating this, [#1566](https://github.com/pydantic/pydantic/issues/1566) by [@samueldeklund](https://github.com/samueldeklund) +* change `schema.field_class_to_schema` to support `frozenset` in schema, [#1557](https://github.com/pydantic/pydantic/issues/1557) by [@wangpeibao](https://github.com/wangpeibao) +* Call `__modify_schema__` only for the field schema, [#1552](https://github.com/pydantic/pydantic/issues/1552) by [@PrettyWood](https://github.com/PrettyWood) +* Move the assignment of `field.validate_always` in `fields.py` so the `always` parameter of validators work on inheritance, [#1545](https://github.com/pydantic/pydantic/issues/1545) by [@dcHHH](https://github.com/dcHHH) +* Added support for UUID instantiation through 16 byte strings such as `b'\x12\x34\x56\x78' * 4`. This was done to support `BINARY(16)` columns in sqlalchemy, [#1541](https://github.com/pydantic/pydantic/issues/1541) by [@shawnwall](https://github.com/shawnwall) +* Add a test assertion that `default_factory` can return a singleton, [#1523](https://github.com/pydantic/pydantic/issues/1523) by [@therefromhere](https://github.com/therefromhere) +* Add `NameEmail.__eq__` so duplicate `NameEmail` instances are evaluated as equal, [#1514](https://github.com/pydantic/pydantic/issues/1514) by [@stephen-bunn](https://github.com/stephen-bunn) +* Add datamodel-code-generator link in pydantic document site, [#1500](https://github.com/pydantic/pydantic/issues/1500) by [@koxudaxi](https://github.com/koxudaxi) +* Added a "Discussion of Pydantic" section to the documentation, with a link to "Pydantic Introduction" video by Alexander Hultnér, [#1499](https://github.com/pydantic/pydantic/issues/1499) by [@hultner](https://github.com/hultner) +* Avoid some side effects of `default_factory` by calling it only once + if possible and by not setting a default value in the schema, [#1491](https://github.com/pydantic/pydantic/issues/1491) by [@PrettyWood](https://github.com/PrettyWood) +* Added docs about dumping dataclasses to JSON, [#1487](https://github.com/pydantic/pydantic/issues/1487) by [@mikegrima](https://github.com/mikegrima) +* Make `BaseModel.__signature__` class-only, so getting `__signature__` from model instance will raise `AttributeError`, [#1466](https://github.com/pydantic/pydantic/issues/1466) by [@Bobronium](https://github.com/Bobronium) +* include `'format': 'password'` in the schema for secret types, [#1424](https://github.com/pydantic/pydantic/issues/1424) by [@atheuz](https://github.com/atheuz) +* Modify schema constraints on `ConstrainedFloat` so that `exclusiveMinimum` and + minimum are not included in the schema if they are equal to `-math.inf` and + `exclusiveMaximum` and `maximum` are not included if they are equal to `math.inf`, [#1417](https://github.com/pydantic/pydantic/issues/1417) by [@vdwees](https://github.com/vdwees) +* Squash internal `__root__` dicts in `.dict()` (and, by extension, in `.json()`), [#1414](https://github.com/pydantic/pydantic/issues/1414) by [@patrickkwang](https://github.com/patrickkwang) +* Move `const` validator to post-validators so it validates the parsed value, [#1410](https://github.com/pydantic/pydantic/issues/1410) by [@selimb](https://github.com/selimb) +* Fix model validation to handle nested literals, e.g. `Literal['foo', Literal['bar']]`, [#1364](https://github.com/pydantic/pydantic/issues/1364) by [@DBCerigo](https://github.com/DBCerigo) +* Remove `user_required = True` from `RedisDsn`, neither user nor password are required, [#1275](https://github.com/pydantic/pydantic/issues/1275) by [@samuelcolvin](https://github.com/samuelcolvin) +* Remove extra `allOf` from schema for fields with `Union` and custom `Field`, [#1209](https://github.com/pydantic/pydantic/issues/1209) by [@mostaphaRoudsari](https://github.com/mostaphaRoudsari) +* Updates OpenAPI schema generation to output all enums as separate models. + Instead of inlining the enum values in the model schema, models now use a `$ref` + property to point to the enum definition, [#1173](https://github.com/pydantic/pydantic/issues/1173) by [@calvinwyoung](https://github.com/calvinwyoung) + +## v1.5.1 (2020-04-23) + +* Signature generation with `extra: allow` never uses a field name, [#1418](https://github.com/pydantic/pydantic/issues/1418) by [@prettywood](https://github.com/prettywood) +* Avoid mutating `Field` default value, [#1412](https://github.com/pydantic/pydantic/issues/1412) by [@prettywood](https://github.com/prettywood) + +## v1.5 (2020-04-18) + +* Make includes/excludes arguments for `.dict()`, `._iter()`, ..., immutable, [#1404](https://github.com/pydantic/pydantic/issues/1404) by [@AlexECX](https://github.com/AlexECX) +* Always use a field's real name with includes/excludes in `model._iter()`, regardless of `by_alias`, [#1397](https://github.com/pydantic/pydantic/issues/1397) by [@AlexECX](https://github.com/AlexECX) +* Update constr regex example to include start and end lines, [#1396](https://github.com/pydantic/pydantic/issues/1396) by [@lmcnearney](https://github.com/lmcnearney) +* Confirm that shallow `model.copy()` does make a shallow copy of attributes, [#1383](https://github.com/pydantic/pydantic/issues/1383) by [@samuelcolvin](https://github.com/samuelcolvin) +* Renaming `model_name` argument of `main.create_model()` to `__model_name` to allow using `model_name` as a field name, [#1367](https://github.com/pydantic/pydantic/issues/1367) by [@kittipatv](https://github.com/kittipatv) +* Replace raising of exception to silent passing for non-Var attributes in mypy plugin, [#1345](https://github.com/pydantic/pydantic/issues/1345) by [@b0g3r](https://github.com/b0g3r) +* Remove `typing_extensions` dependency for Python 3.8, [#1342](https://github.com/pydantic/pydantic/issues/1342) by [@prettywood](https://github.com/prettywood) +* Make `SecretStr` and `SecretBytes` initialization idempotent, [#1330](https://github.com/pydantic/pydantic/issues/1330) by [@atheuz](https://github.com/atheuz) +* document making secret types dumpable using the json method, [#1328](https://github.com/pydantic/pydantic/issues/1328) by [@atheuz](https://github.com/atheuz) +* Move all testing and build to github actions, add windows and macos binaries, + thank you [@StephenBrown2](https://github.com/StephenBrown2) for much help, [#1326](https://github.com/pydantic/pydantic/issues/1326) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix card number length check in `PaymentCardNumber`, `PaymentCardBrand` now inherits from `str`, [#1317](https://github.com/pydantic/pydantic/issues/1317) by [@samuelcolvin](https://github.com/samuelcolvin) +* Have `BaseModel` inherit from `Representation` to make mypy happy when overriding `__str__`, [#1310](https://github.com/pydantic/pydantic/issues/1310) by [@FuegoFro](https://github.com/FuegoFro) +* Allow `None` as input to all optional list fields, [#1307](https://github.com/pydantic/pydantic/issues/1307) by [@prettywood](https://github.com/prettywood) +* Add `datetime` field to `default_factory` example, [#1301](https://github.com/pydantic/pydantic/issues/1301) by [@StephenBrown2](https://github.com/StephenBrown2) +* Allow subclasses of known types to be encoded with superclass encoder, [#1291](https://github.com/pydantic/pydantic/issues/1291) by [@StephenBrown2](https://github.com/StephenBrown2) +* Exclude exported fields from all elements of a list/tuple of submodels/dicts with `'__all__'`, [#1286](https://github.com/pydantic/pydantic/issues/1286) by [@masalim2](https://github.com/masalim2) +* Add pydantic.color.Color objects as available input for Color fields, [#1258](https://github.com/pydantic/pydantic/issues/1258) by [@leosussan](https://github.com/leosussan) +* In examples, type nullable fields as `Optional`, so that these are valid mypy annotations, [#1248](https://github.com/pydantic/pydantic/issues/1248) by [@kokes](https://github.com/kokes) +* Make `pattern_validator()` accept pre-compiled `Pattern` objects. Fix `str_validator()` return type to `str`, [#1237](https://github.com/pydantic/pydantic/issues/1237) by [@adamgreg](https://github.com/adamgreg) +* Document how to manage Generics and inheritance, [#1229](https://github.com/pydantic/pydantic/issues/1229) by [@esadruhn](https://github.com/esadruhn) +* `update_forward_refs()` method of BaseModel now copies `__dict__` of class module instead of modyfying it, [#1228](https://github.com/pydantic/pydantic/issues/1228) by [@paul-ilyin](https://github.com/paul-ilyin) +* Support instance methods and class methods with `@validate_arguments`, [#1222](https://github.com/pydantic/pydantic/issues/1222) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add `default_factory` argument to `Field` to create a dynamic default value by passing a zero-argument callable, [#1210](https://github.com/pydantic/pydantic/issues/1210) by [@prettywood](https://github.com/prettywood) +* add support for `NewType` of `List`, `Optional`, etc, [#1207](https://github.com/pydantic/pydantic/issues/1207) by [@Kazy](https://github.com/Kazy) +* fix mypy signature for `root_validator`, [#1192](https://github.com/pydantic/pydantic/issues/1192) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fixed parsing of nested 'custom root type' models, [#1190](https://github.com/pydantic/pydantic/issues/1190) by [@Shados](https://github.com/Shados) +* Add `validate_arguments` function decorator which checks the arguments to a function matches type annotations, [#1179](https://github.com/pydantic/pydantic/issues/1179) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add `__signature__` to models, [#1034](https://github.com/pydantic/pydantic/issues/1034) by [@Bobronium](https://github.com/Bobronium) +* Refactor `._iter()` method, 10x speed boost for `dict(model)`, [#1017](https://github.com/pydantic/pydantic/issues/1017) by [@Bobronium](https://github.com/Bobronium) + +## v1.4 (2020-01-24) + +* **Breaking Change:** alias precedence logic changed so aliases on a field always take priority over + an alias from `alias_generator` to avoid buggy/unexpected behaviour, + see [here](https://docs.pydantic.dev/usage/model_config/#alias-precedence) for details, [#1178](https://github.com/pydantic/pydantic/issues/1178) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add support for unicode and punycode in TLDs, [#1182](https://github.com/pydantic/pydantic/issues/1182) by [@jamescurtin](https://github.com/jamescurtin) +* Fix `cls` argument in validators during assignment, [#1172](https://github.com/pydantic/pydantic/issues/1172) by [@samuelcolvin](https://github.com/samuelcolvin) +* completing Luhn algorithm for `PaymentCardNumber`, [#1166](https://github.com/pydantic/pydantic/issues/1166) by [@cuencandres](https://github.com/cuencandres) +* add support for generics that implement `__get_validators__` like a custom data type, [#1159](https://github.com/pydantic/pydantic/issues/1159) by [@tiangolo](https://github.com/tiangolo) +* add support for infinite generators with `Iterable`, [#1152](https://github.com/pydantic/pydantic/issues/1152) by [@tiangolo](https://github.com/tiangolo) +* fix `url_regex` to accept schemas with `+`, `-` and `.` after the first character, [#1142](https://github.com/pydantic/pydantic/issues/1142) by [@samuelcolvin](https://github.com/samuelcolvin) +* move `version_info()` to `version.py`, suggest its use in issues, [#1138](https://github.com/pydantic/pydantic/issues/1138) by [@samuelcolvin](https://github.com/samuelcolvin) +* Improve pydantic import time by roughly 50% by deferring some module loading and regex compilation, [#1127](https://github.com/pydantic/pydantic/issues/1127) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fix `EmailStr` and `NameEmail` to accept instances of themselves in cython, [#1126](https://github.com/pydantic/pydantic/issues/1126) by [@koxudaxi](https://github.com/koxudaxi) +* Pass model class to the `Config.schema_extra` callable, [#1125](https://github.com/pydantic/pydantic/issues/1125) by [@therefromhere](https://github.com/therefromhere) +* Fix regex for username and password in URLs, [#1115](https://github.com/pydantic/pydantic/issues/1115) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add support for nested generic models, [#1104](https://github.com/pydantic/pydantic/issues/1104) by [@dmontagu](https://github.com/dmontagu) +* add `__all__` to `__init__.py` to prevent "implicit reexport" errors from mypy, [#1072](https://github.com/pydantic/pydantic/issues/1072) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add support for using "dotenv" files with `BaseSettings`, [#1011](https://github.com/pydantic/pydantic/issues/1011) by [@acnebs](https://github.com/acnebs) + +## v1.3 (2019-12-21) + +* Change `schema` and `schema_model` to handle dataclasses by using their `__pydantic_model__` feature, [#792](https://github.com/pydantic/pydantic/issues/792) by [@aviramha](https://github.com/aviramha) +* Added option for `root_validator` to be skipped if values validation fails using keyword `skip_on_failure=True`, [#1049](https://github.com/pydantic/pydantic/issues/1049) by [@aviramha](https://github.com/aviramha) +* Allow `Config.schema_extra` to be a callable so that the generated schema can be post-processed, [#1054](https://github.com/pydantic/pydantic/issues/1054) by [@selimb](https://github.com/selimb) +* Update mypy to version 0.750, [#1057](https://github.com/pydantic/pydantic/issues/1057) by [@dmontagu](https://github.com/dmontagu) +* Trick Cython into allowing str subclassing, [#1061](https://github.com/pydantic/pydantic/issues/1061) by [@skewty](https://github.com/skewty) +* Prevent type attributes being added to schema unless the attribute `__schema_attributes__` is `True`, [#1064](https://github.com/pydantic/pydantic/issues/1064) by [@samuelcolvin](https://github.com/samuelcolvin) +* Change `BaseModel.parse_file` to use `Config.json_loads`, [#1067](https://github.com/pydantic/pydantic/issues/1067) by [@kierandarcy](https://github.com/kierandarcy) +* Fix for optional `Json` fields, [#1073](https://github.com/pydantic/pydantic/issues/1073) by [@volker48](https://github.com/volker48) +* Change the default number of threads used when compiling with cython to one, + allow override via the `CYTHON_NTHREADS` environment variable, [#1074](https://github.com/pydantic/pydantic/issues/1074) by [@samuelcolvin](https://github.com/samuelcolvin) +* Run FastAPI tests during Pydantic's CI tests, [#1075](https://github.com/pydantic/pydantic/issues/1075) by [@tiangolo](https://github.com/tiangolo) +* My mypy strictness constraints, and associated tweaks to type annotations, [#1077](https://github.com/pydantic/pydantic/issues/1077) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add `__eq__` to SecretStr and SecretBytes to allow "value equals", [#1079](https://github.com/pydantic/pydantic/issues/1079) by [@sbv-trueenergy](https://github.com/sbv-trueenergy) +* Fix schema generation for nested None case, [#1088](https://github.com/pydantic/pydantic/issues/1088) by [@lutostag](https://github.com/lutostag) +* Consistent checks for sequence like objects, [#1090](https://github.com/pydantic/pydantic/issues/1090) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fix `Config` inheritance on `BaseSettings` when used with `env_prefix`, [#1091](https://github.com/pydantic/pydantic/issues/1091) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fix for `__modify_schema__` when it conflicted with `field_class_to_schema*`, [#1102](https://github.com/pydantic/pydantic/issues/1102) by [@samuelcolvin](https://github.com/samuelcolvin) +* docs: Fix explanation of case sensitive environment variable names when populating `BaseSettings` subclass attributes, [#1105](https://github.com/pydantic/pydantic/issues/1105) by [@tribals](https://github.com/tribals) +* Rename django-rest-framework benchmark in documentation, [#1119](https://github.com/pydantic/pydantic/issues/1119) by [@frankie567](https://github.com/frankie567) + +## v1.2 (2019-11-28) + +* **Possible Breaking Change:** Add support for required `Optional` with `name: Optional[AnyType] = Field(...)` + and refactor `ModelField` creation to preserve `required` parameter value, [#1031](https://github.com/pydantic/pydantic/issues/1031) by [@tiangolo](https://github.com/tiangolo); + see [here](https://docs.pydantic.dev/usage/models/#required-optional-fields) for details +* Add benchmarks for `cattrs`, [#513](https://github.com/pydantic/pydantic/issues/513) by [@sebastianmika](https://github.com/sebastianmika) +* Add `exclude_none` option to `dict()` and friends, [#587](https://github.com/pydantic/pydantic/issues/587) by [@niknetniko](https://github.com/niknetniko) +* Add benchmarks for `valideer`, [#670](https://github.com/pydantic/pydantic/issues/670) by [@gsakkis](https://github.com/gsakkis) +* Add `parse_obj_as` and `parse_file_as` functions for ad-hoc parsing of data into arbitrary pydantic-compatible types, [#934](https://github.com/pydantic/pydantic/issues/934) by [@dmontagu](https://github.com/dmontagu) +* Add `allow_reuse` argument to validators, thus allowing validator reuse, [#940](https://github.com/pydantic/pydantic/issues/940) by [@dmontagu](https://github.com/dmontagu) +* Add support for mapping types for custom root models, [#958](https://github.com/pydantic/pydantic/issues/958) by [@dmontagu](https://github.com/dmontagu) +* Mypy plugin support for dataclasses, [#966](https://github.com/pydantic/pydantic/issues/966) by [@koxudaxi](https://github.com/koxudaxi) +* Add support for dataclasses default factory, [#968](https://github.com/pydantic/pydantic/issues/968) by [@ahirner](https://github.com/ahirner) +* Add a `ByteSize` type for converting byte string (`1GB`) to plain bytes, [#977](https://github.com/pydantic/pydantic/issues/977) by [@dgasmith](https://github.com/dgasmith) +* Fix mypy complaint about `@root_validator(pre=True)`, [#984](https://github.com/pydantic/pydantic/issues/984) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add manylinux binaries for Python 3.8 to pypi, also support manylinux2010, [#994](https://github.com/pydantic/pydantic/issues/994) by [@samuelcolvin](https://github.com/samuelcolvin) +* Adds ByteSize conversion to another unit, [#995](https://github.com/pydantic/pydantic/issues/995) by [@dgasmith](https://github.com/dgasmith) +* Fix `__str__` and `__repr__` inheritance for models, [#1022](https://github.com/pydantic/pydantic/issues/1022) by [@samuelcolvin](https://github.com/samuelcolvin) +* add testimonials section to docs, [#1025](https://github.com/pydantic/pydantic/issues/1025) by [@sullivancolin](https://github.com/sullivancolin) +* Add support for `typing.Literal` for Python 3.8, [#1026](https://github.com/pydantic/pydantic/issues/1026) by [@dmontagu](https://github.com/dmontagu) + +## v1.1.1 (2019-11-20) + +* Fix bug where use of complex fields on sub-models could cause fields to be incorrectly configured, [#1015](https://github.com/pydantic/pydantic/issues/1015) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v1.1 (2019-11-07) + +* Add a mypy plugin for type checking `BaseModel.__init__` and more, [#722](https://github.com/pydantic/pydantic/issues/722) by [@dmontagu](https://github.com/dmontagu) +* Change return type typehint for `GenericModel.__class_getitem__` to prevent PyCharm warnings, [#936](https://github.com/pydantic/pydantic/issues/936) by [@dmontagu](https://github.com/dmontagu) +* Fix usage of `Any` to allow `None`, also support `TypeVar` thus allowing use of un-parameterised collection types + e.g. `Dict` and `List`, [#962](https://github.com/pydantic/pydantic/issues/962) by [@samuelcolvin](https://github.com/samuelcolvin) +* Set `FieldInfo` on subfields to fix schema generation for complex nested types, [#965](https://github.com/pydantic/pydantic/issues/965) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v1.0 (2019-10-23) + +* **Breaking Change:** deprecate the `Model.fields` property, use `Model.__fields__` instead, [#883](https://github.com/pydantic/pydantic/issues/883) by [@samuelcolvin](https://github.com/samuelcolvin) +* **Breaking Change:** Change the precedence of aliases so child model aliases override parent aliases, + including using `alias_generator`, [#904](https://github.com/pydantic/pydantic/issues/904) by [@samuelcolvin](https://github.com/samuelcolvin) +* **Breaking change:** Rename `skip_defaults` to `exclude_unset`, and add ability to exclude actual defaults, [#915](https://github.com/pydantic/pydantic/issues/915) by [@dmontagu](https://github.com/dmontagu) +* Add `**kwargs` to `pydantic.main.ModelMetaclass.__new__` so `__init_subclass__` can take custom parameters on extended + `BaseModel` classes, [#867](https://github.com/pydantic/pydantic/issues/867) by [@retnikt](https://github.com/retnikt) +* Fix field of a type that has a default value, [#880](https://github.com/pydantic/pydantic/issues/880) by [@koxudaxi](https://github.com/koxudaxi) +* Use `FutureWarning` instead of `DeprecationWarning` when `alias` instead of `env` is used for settings models, [#881](https://github.com/pydantic/pydantic/issues/881) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fix issue with `BaseSettings` inheritance and `alias` getting set to `None`, [#882](https://github.com/pydantic/pydantic/issues/882) by [@samuelcolvin](https://github.com/samuelcolvin) +* Modify `__repr__` and `__str__` methods to be consistent across all public classes, add `__pretty__` to support + python-devtools, [#884](https://github.com/pydantic/pydantic/issues/884) by [@samuelcolvin](https://github.com/samuelcolvin) +* deprecation warning for `case_insensitive` on `BaseSettings` config, [#885](https://github.com/pydantic/pydantic/issues/885) by [@samuelcolvin](https://github.com/samuelcolvin) +* For `BaseSettings` merge environment variables and in-code values recursively, as long as they create a valid object + when merged together, to allow splitting init arguments, [#888](https://github.com/pydantic/pydantic/issues/888) by [@idmitrievsky](https://github.com/idmitrievsky) +* change secret types example, [#890](https://github.com/pydantic/pydantic/issues/890) by [@ashears](https://github.com/ashears) +* Change the signature of `Model.construct()` to be more user-friendly, document `construct()` usage, [#898](https://github.com/pydantic/pydantic/issues/898) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add example for the `construct()` method, [#907](https://github.com/pydantic/pydantic/issues/907) by [@ashears](https://github.com/ashears) +* Improve use of `Field` constraints on complex types, raise an error if constraints are not enforceable, + also support tuples with an ellipsis `Tuple[X, ...]`, `Sequence` and `FrozenSet` in schema, [#909](https://github.com/pydantic/pydantic/issues/909) by [@samuelcolvin](https://github.com/samuelcolvin) +* update docs for bool missing valid value, [#911](https://github.com/pydantic/pydantic/issues/911) by [@trim21](https://github.com/trim21) +* Better `str`/`repr` logic for `ModelField`, [#912](https://github.com/pydantic/pydantic/issues/912) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fix `ConstrainedList`, update schema generation to reflect `min_items` and `max_items` `Field()` arguments, [#917](https://github.com/pydantic/pydantic/issues/917) by [@samuelcolvin](https://github.com/samuelcolvin) +* Allow abstracts sets (eg. dict keys) in the `include` and `exclude` arguments of `dict()`, [#921](https://github.com/pydantic/pydantic/issues/921) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fix JSON serialization errors on `ValidationError.json()` by using `pydantic_encoder`, [#922](https://github.com/pydantic/pydantic/issues/922) by [@samuelcolvin](https://github.com/samuelcolvin) +* Clarify usage of `remove_untouched`, improve error message for types with no validators, [#926](https://github.com/pydantic/pydantic/issues/926) by [@retnikt](https://github.com/retnikt) + +## v1.0b2 (2019-10-07) + +* Mark `StrictBool` typecheck as `bool` to allow for default values without mypy errors, [#690](https://github.com/pydantic/pydantic/issues/690) by [@dmontagu](https://github.com/dmontagu) +* Transfer the documentation build from sphinx to mkdocs, re-write much of the documentation, [#856](https://github.com/pydantic/pydantic/issues/856) by [@samuelcolvin](https://github.com/samuelcolvin) +* Add support for custom naming schemes for `GenericModel` subclasses, [#859](https://github.com/pydantic/pydantic/issues/859) by [@dmontagu](https://github.com/dmontagu) +* Add `if TYPE_CHECKING:` to the excluded lines for test coverage, [#874](https://github.com/pydantic/pydantic/issues/874) by [@dmontagu](https://github.com/dmontagu) +* Rename `allow_population_by_alias` to `allow_population_by_field_name`, remove unnecessary warning about it, [#875](https://github.com/pydantic/pydantic/issues/875) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v1.0b1 (2019-10-01) + +* **Breaking Change:** rename `Schema` to `Field`, make it a function to placate mypy, [#577](https://github.com/pydantic/pydantic/issues/577) by [@samuelcolvin](https://github.com/samuelcolvin) +* **Breaking Change:** modify parsing behavior for `bool`, [#617](https://github.com/pydantic/pydantic/issues/617) by [@dmontagu](https://github.com/dmontagu) +* **Breaking Change:** `get_validators` is no longer recognised, use `__get_validators__`. + `Config.ignore_extra` and `Config.allow_extra` are no longer recognised, use `Config.extra`, [#720](https://github.com/pydantic/pydantic/issues/720) by [@samuelcolvin](https://github.com/samuelcolvin) +* **Breaking Change:** modify default config settings for `BaseSettings`; `case_insensitive` renamed to `case_sensitive`, + default changed to `case_sensitive = False`, `env_prefix` default changed to `''` - e.g. no prefix, [#721](https://github.com/pydantic/pydantic/issues/721) by [@dmontagu](https://github.com/dmontagu) +* **Breaking change:** Implement `root_validator` and rename root errors from `__obj__` to `__root__`, [#729](https://github.com/pydantic/pydantic/issues/729) by [@samuelcolvin](https://github.com/samuelcolvin) +* **Breaking Change:** alter the behaviour of `dict(model)` so that sub-models are nolonger + converted to dictionaries, [#733](https://github.com/pydantic/pydantic/issues/733) by [@samuelcolvin](https://github.com/samuelcolvin) +* **Breaking change:** Added `initvars` support to `post_init_post_parse`, [#748](https://github.com/pydantic/pydantic/issues/748) by [@Raphael-C-Almeida](https://github.com/Raphael-C-Almeida) +* **Breaking Change:** Make `BaseModel.json()` only serialize the `__root__` key for models with custom root, [#752](https://github.com/pydantic/pydantic/issues/752) by [@dmontagu](https://github.com/dmontagu) +* **Breaking Change:** complete rewrite of `URL` parsing logic, [#755](https://github.com/pydantic/pydantic/issues/755) by [@samuelcolvin](https://github.com/samuelcolvin) +* **Breaking Change:** preserve superclass annotations for field-determination when not provided in subclass, [#757](https://github.com/pydantic/pydantic/issues/757) by [@dmontagu](https://github.com/dmontagu) +* **Breaking Change:** `BaseSettings` now uses the special `env` settings to define which environment variables to + read, not aliases, [#847](https://github.com/pydantic/pydantic/issues/847) by [@samuelcolvin](https://github.com/samuelcolvin) +* add support for `assert` statements inside validators, [#653](https://github.com/pydantic/pydantic/issues/653) by [@abdusco](https://github.com/abdusco) +* Update documentation to specify the use of `pydantic.dataclasses.dataclass` and subclassing `pydantic.BaseModel`, [#710](https://github.com/pydantic/pydantic/issues/710) by [@maddosaurus](https://github.com/maddosaurus) +* Allow custom JSON decoding and encoding via `json_loads` and `json_dumps` `Config` properties, [#714](https://github.com/pydantic/pydantic/issues/714) by [@samuelcolvin](https://github.com/samuelcolvin) +* make all annotated fields occur in the order declared, [#715](https://github.com/pydantic/pydantic/issues/715) by [@dmontagu](https://github.com/dmontagu) +* use pytest to test `mypy` integration, [#735](https://github.com/pydantic/pydantic/issues/735) by [@dmontagu](https://github.com/dmontagu) +* add `__repr__` method to `ErrorWrapper`, [#738](https://github.com/pydantic/pydantic/issues/738) by [@samuelcolvin](https://github.com/samuelcolvin) +* Added support for `FrozenSet` members in dataclasses, and a better error when attempting to use types from the `typing` module that are not supported by Pydantic, [#745](https://github.com/pydantic/pydantic/issues/745) by [@djpetti](https://github.com/djpetti) +* add documentation for Pycharm Plugin, [#750](https://github.com/pydantic/pydantic/issues/750) by [@koxudaxi](https://github.com/koxudaxi) +* fix broken examples in the docs, [#753](https://github.com/pydantic/pydantic/issues/753) by [@dmontagu](https://github.com/dmontagu) +* moving typing related objects into `pydantic.typing`, [#761](https://github.com/pydantic/pydantic/issues/761) by [@samuelcolvin](https://github.com/samuelcolvin) +* Minor performance improvements to `ErrorWrapper`, `ValidationError` and datetime parsing, [#763](https://github.com/pydantic/pydantic/issues/763) by [@samuelcolvin](https://github.com/samuelcolvin) +* Improvements to `datetime`/`date`/`time`/`timedelta` types: more descriptive errors, + change errors to `value_error` not `type_error`, support bytes, [#766](https://github.com/pydantic/pydantic/issues/766) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix error messages for `Literal` types with multiple allowed values, [#770](https://github.com/pydantic/pydantic/issues/770) by [@dmontagu](https://github.com/dmontagu) +* Improved auto-generated `title` field in JSON schema by converting underscore to space, [#772](https://github.com/pydantic/pydantic/issues/772) by [@skewty](https://github.com/skewty) +* support `mypy --no-implicit-reexport` for dataclasses, also respect `--no-implicit-reexport` in pydantic itself, [#783](https://github.com/pydantic/pydantic/issues/783) by [@samuelcolvin](https://github.com/samuelcolvin) +* add the `PaymentCardNumber` type, [#790](https://github.com/pydantic/pydantic/issues/790) by [@matin](https://github.com/matin) +* Fix const validations for lists, [#794](https://github.com/pydantic/pydantic/issues/794) by [@hmvp](https://github.com/hmvp) +* Set `additionalProperties` to false in schema for models with extra fields disallowed, [#796](https://github.com/pydantic/pydantic/issues/796) by [@Code0x58](https://github.com/Code0x58) +* `EmailStr` validation method now returns local part case-sensitive per RFC 5321, [#798](https://github.com/pydantic/pydantic/issues/798) by [@henriklindgren](https://github.com/henriklindgren) +* Added ability to validate strictness to `ConstrainedFloat`, `ConstrainedInt` and `ConstrainedStr` and added + `StrictFloat` and `StrictInt` classes, [#799](https://github.com/pydantic/pydantic/issues/799) by [@DerRidda](https://github.com/DerRidda) +* Improve handling of `None` and `Optional`, replace `whole` with `each_item` (inverse meaning, default `False`) + on validators, [#803](https://github.com/pydantic/pydantic/issues/803) by [@samuelcolvin](https://github.com/samuelcolvin) +* add support for `Type[T]` type hints, [#807](https://github.com/pydantic/pydantic/issues/807) by [@timonbimon](https://github.com/timonbimon) +* Performance improvements from removing `change_exceptions`, change how pydantic error are constructed, [#819](https://github.com/pydantic/pydantic/issues/819) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fix the error message arising when a `BaseModel`-type model field causes a `ValidationError` during parsing, [#820](https://github.com/pydantic/pydantic/issues/820) by [@dmontagu](https://github.com/dmontagu) +* allow `getter_dict` on `Config`, modify `GetterDict` to be more like a `Mapping` object and thus easier to work with, [#821](https://github.com/pydantic/pydantic/issues/821) by [@samuelcolvin](https://github.com/samuelcolvin) +* Only check `TypeVar` param on base `GenericModel` class, [#842](https://github.com/pydantic/pydantic/issues/842) by [@zpencerq](https://github.com/zpencerq) +* rename `Model._schema_cache` -> `Model.__schema_cache__`, `Model._json_encoder` -> `Model.__json_encoder__`, + `Model._custom_root_type` -> `Model.__custom_root_type__`, [#851](https://github.com/pydantic/pydantic/issues/851) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v0.32.2 (2019-08-17) + +(Docs are available [here](https://5d584fcca7c9b70007d1c997--pydantic-docs.netlify.com)) + +* fix `__post_init__` usage with dataclass inheritance, fix [#739](https://github.com/pydantic/pydantic/issues/739) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix required fields validation on GenericModels classes, [#742](https://github.com/pydantic/pydantic/issues/742) by [@amitbl](https://github.com/amitbl) +* fix defining custom `Schema` on `GenericModel` fields, [#754](https://github.com/pydantic/pydantic/issues/754) by [@amitbl](https://github.com/amitbl) + +## v0.32.1 (2019-08-08) + +* do not validate extra fields when `validate_assignment` is on, [#724](https://github.com/pydantic/pydantic/issues/724) by [@YaraslauZhylko](https://github.com/YaraslauZhylko) + +## v0.32 (2019-08-06) + +* add model name to `ValidationError` error message, [#676](https://github.com/pydantic/pydantic/issues/676) by [@dmontagu](https://github.com/dmontagu) +* **breaking change**: remove `__getattr__` and rename `__values__` to `__dict__` on `BaseModel`, + deprecation warning on use `__values__` attr, attributes access speed increased up to 14 times, [#712](https://github.com/pydantic/pydantic/issues/712) by [@Bobronium](https://github.com/Bobronium) +* support `ForwardRef` (without self-referencing annotations) in Python 3.6, [#706](https://github.com/pydantic/pydantic/issues/706) by [@koxudaxi](https://github.com/koxudaxi) +* implement `schema_extra` in `Config` sub-class, [#663](https://github.com/pydantic/pydantic/issues/663) by [@tiangolo](https://github.com/tiangolo) + +## v0.31.1 (2019-07-31) + +* fix json generation for `EnumError`, [#697](https://github.com/pydantic/pydantic/issues/697) by [@dmontagu](https://github.com/dmontagu) +* update numerous dependencies + +## v0.31 (2019-07-24) + +* better support for floating point `multiple_of` values, [#652](https://github.com/pydantic/pydantic/issues/652) by [@justindujardin](https://github.com/justindujardin) +* fix schema generation for `NewType` and `Literal`, [#649](https://github.com/pydantic/pydantic/issues/649) by [@dmontagu](https://github.com/dmontagu) +* fix `alias_generator` and field config conflict, [#645](https://github.com/pydantic/pydantic/issues/645) by [@gmetzker](https://github.com/gmetzker) and [#658](https://github.com/pydantic/pydantic/issues/658) by [@Bobronium](https://github.com/Bobronium) +* more detailed message for `EnumError`, [#673](https://github.com/pydantic/pydantic/issues/673) by [@dmontagu](https://github.com/dmontagu) +* add advanced exclude support for `dict`, `json` and `copy`, [#648](https://github.com/pydantic/pydantic/issues/648) by [@Bobronium](https://github.com/Bobronium) +* fix bug in `GenericModel` for models with concrete parameterized fields, [#672](https://github.com/pydantic/pydantic/issues/672) by [@dmontagu](https://github.com/dmontagu) +* add documentation for `Literal` type, [#651](https://github.com/pydantic/pydantic/issues/651) by [@dmontagu](https://github.com/dmontagu) +* add `Config.keep_untouched` for custom descriptors support, [#679](https://github.com/pydantic/pydantic/issues/679) by [@Bobronium](https://github.com/Bobronium) +* use `inspect.cleandoc` internally to get model description, [#657](https://github.com/pydantic/pydantic/issues/657) by [@tiangolo](https://github.com/tiangolo) +* add `Color` to schema generation, by [@euri10](https://github.com/euri10) +* add documentation for Literal type, [#651](https://github.com/pydantic/pydantic/issues/651) by [@dmontagu](https://github.com/dmontagu) + +## v0.30.1 (2019-07-15) + +* fix so nested classes which inherit and change `__init__` are correctly processed while still allowing `self` as a + parameter, [#644](https://github.com/pydantic/pydantic/issues/644) by [@lnaden](https://github.com/lnaden) and [@dgasmith](https://github.com/dgasmith) + +## v0.30 (2019-07-07) + +* enforce single quotes in code, [#612](https://github.com/pydantic/pydantic/issues/612) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix infinite recursion with dataclass inheritance and `__post_init__`, [#606](https://github.com/pydantic/pydantic/issues/606) by [@Hanaasagi](https://github.com/Hanaasagi) +* fix default values for `GenericModel`, [#610](https://github.com/pydantic/pydantic/issues/610) by [@dmontagu](https://github.com/dmontagu) +* clarify that self-referencing models require Python 3.7+, [#616](https://github.com/pydantic/pydantic/issues/616) by [@vlcinsky](https://github.com/vlcinsky) +* fix truncate for types, [#611](https://github.com/pydantic/pydantic/issues/611) by [@dmontagu](https://github.com/dmontagu) +* add `alias_generator` support, [#622](https://github.com/pydantic/pydantic/issues/622) by [@Bobronium](https://github.com/Bobronium) +* fix unparameterized generic type schema generation, [#625](https://github.com/pydantic/pydantic/issues/625) by [@dmontagu](https://github.com/dmontagu) +* fix schema generation with multiple/circular references to the same model, [#621](https://github.com/pydantic/pydantic/issues/621) by [@tiangolo](https://github.com/tiangolo) and [@wongpat](https://github.com/wongpat) +* support custom root types, [#628](https://github.com/pydantic/pydantic/issues/628) by [@koxudaxi](https://github.com/koxudaxi) +* support `self` as a field name in `parse_obj`, [#632](https://github.com/pydantic/pydantic/issues/632) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v0.29 (2019-06-19) + +* support dataclasses.InitVar, [#592](https://github.com/pydantic/pydantic/issues/592) by [@pfrederiks](https://github.com/pfrederiks) +* Updated documentation to elucidate the usage of `Union` when defining multiple types under an attribute's + annotation and showcase how the type-order can affect marshalling of provided values, [#594](https://github.com/pydantic/pydantic/issues/594) by [@somada141](https://github.com/somada141) +* add `conlist` type, [#583](https://github.com/pydantic/pydantic/issues/583) by [@hmvp](https://github.com/hmvp) +* add support for generics, [#595](https://github.com/pydantic/pydantic/issues/595) by [@dmontagu](https://github.com/dmontagu) + +## v0.28 (2019-06-06) + +* fix support for JSON Schema generation when using models with circular references in Python 3.7, [#572](https://github.com/pydantic/pydantic/issues/572) by [@tiangolo](https://github.com/tiangolo) +* support `__post_init_post_parse__` on dataclasses, [#567](https://github.com/pydantic/pydantic/issues/567) by [@sevaho](https://github.com/sevaho) +* allow dumping dataclasses to JSON, [#575](https://github.com/pydantic/pydantic/issues/575) by [@samuelcolvin](https://github.com/samuelcolvin) and [@DanielOberg](https://github.com/DanielOberg) +* ORM mode, [#562](https://github.com/pydantic/pydantic/issues/562) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix `pydantic.compiled` on ipython, [#573](https://github.com/pydantic/pydantic/issues/573) by [@dmontagu](https://github.com/dmontagu) and [@samuelcolvin](https://github.com/samuelcolvin) +* add `StrictBool` type, [#579](https://github.com/pydantic/pydantic/issues/579) by [@cazgp](https://github.com/cazgp) + +## v0.27 (2019-05-30) + +* **breaking change** `_pydantic_post_init` to execute dataclass' original `__post_init__` before + validation, [#560](https://github.com/pydantic/pydantic/issues/560) by [@HeavenVolkoff](https://github.com/HeavenVolkoff) +* fix handling of generic types without specified parameters, [#550](https://github.com/pydantic/pydantic/issues/550) by [@dmontagu](https://github.com/dmontagu) +* **breaking change** (maybe): this is the first release compiled with **cython**, see the docs and please + submit an issue if you run into problems + +## v0.27.0a1 (2019-05-26) + +* fix JSON Schema for `list`, `tuple`, and `set`, [#540](https://github.com/pydantic/pydantic/issues/540) by [@tiangolo](https://github.com/tiangolo) +* compiling with cython, `manylinux` binaries, some other performance improvements, [#548](https://github.com/pydantic/pydantic/issues/548) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v0.26 (2019-05-22) + +* fix to schema generation for `IPvAnyAddress`, `IPvAnyInterface`, `IPvAnyNetwork` [#498](https://github.com/pydantic/pydantic/issues/498) by [@pilosus](https://github.com/pilosus) +* fix variable length tuples support, [#495](https://github.com/pydantic/pydantic/issues/495) by [@pilosus](https://github.com/pilosus) +* fix return type hint for `create_model`, [#526](https://github.com/pydantic/pydantic/issues/526) by [@dmontagu](https://github.com/dmontagu) +* **Breaking Change:** fix `.dict(skip_keys=True)` skipping values set via alias (this involves changing + `validate_model()` to always returns `Tuple[Dict[str, Any], Set[str], Optional[ValidationError]]`), [#517](https://github.com/pydantic/pydantic/issues/517) by [@sommd](https://github.com/sommd) +* fix to schema generation for `IPv4Address`, `IPv6Address`, `IPv4Interface`, + `IPv6Interface`, `IPv4Network`, `IPv6Network` [#532](https://github.com/pydantic/pydantic/issues/532) by [@euri10](https://github.com/euri10) +* add `Color` type, [#504](https://github.com/pydantic/pydantic/issues/504) by [@pilosus](https://github.com/pilosus) and [@samuelcolvin](https://github.com/samuelcolvin) + +## v0.25 (2019-05-05) + +* Improve documentation on self-referencing models and annotations, [#487](https://github.com/pydantic/pydantic/issues/487) by [@theenglishway](https://github.com/theenglishway) +* fix `.dict()` with extra keys, [#490](https://github.com/pydantic/pydantic/issues/490) by [@JaewonKim](https://github.com/JaewonKim) +* support `const` keyword in `Schema`, [#434](https://github.com/pydantic/pydantic/issues/434) by [@Sean1708](https://github.com/Sean1708) + +## v0.24 (2019-04-23) + +* fix handling `ForwardRef` in sub-types, like `Union`, [#464](https://github.com/pydantic/pydantic/issues/464) by [@tiangolo](https://github.com/tiangolo) +* fix secret serialization, [#465](https://github.com/pydantic/pydantic/issues/465) by [@atheuz](https://github.com/atheuz) +* Support custom validators for dataclasses, [#454](https://github.com/pydantic/pydantic/issues/454) by [@primal100](https://github.com/primal100) +* fix `parse_obj` to cope with dict-like objects, [#472](https://github.com/pydantic/pydantic/issues/472) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix to schema generation in nested dataclass-based models, [#474](https://github.com/pydantic/pydantic/issues/474) by [@NoAnyLove](https://github.com/NoAnyLove) +* fix `json` for `Path`, `FilePath`, and `DirectoryPath` objects, [#473](https://github.com/pydantic/pydantic/issues/473) by [@mikegoodspeed](https://github.com/mikegoodspeed) + +## v0.23 (2019-04-04) + +* improve documentation for contributing section, [#441](https://github.com/pydantic/pydantic/issues/441) by [@pilosus](https://github.com/pilosus) +* improve README.rst to include essential information about the package, [#446](https://github.com/pydantic/pydantic/issues/446) by [@pilosus](https://github.com/pilosus) +* `IntEnum` support, [#444](https://github.com/pydantic/pydantic/issues/444) by [@potykion](https://github.com/potykion) +* fix PyObject callable value, [#409](https://github.com/pydantic/pydantic/issues/409) by [@pilosus](https://github.com/pilosus) +* fix `black` deprecation warnings after update, [#451](https://github.com/pydantic/pydantic/issues/451) by [@pilosus](https://github.com/pilosus) +* fix `ForwardRef` collection bug, [#450](https://github.com/pydantic/pydantic/issues/450) by [@tigerwings](https://github.com/tigerwings) +* Support specialized `ClassVars`, [#455](https://github.com/pydantic/pydantic/issues/455) by [@tyrylu](https://github.com/tyrylu) +* fix JSON serialization for `ipaddress` types, [#333](https://github.com/pydantic/pydantic/issues/333) by [@pilosus](https://github.com/pilosus) +* add `SecretStr` and `SecretBytes` types, [#452](https://github.com/pydantic/pydantic/issues/452) by [@atheuz](https://github.com/atheuz) + +## v0.22 (2019-03-29) + +* add `IPv{4,6,Any}Network` and `IPv{4,6,Any}Interface` types from `ipaddress` stdlib, [#333](https://github.com/pydantic/pydantic/issues/333) by [@pilosus](https://github.com/pilosus) +* add docs for `datetime` types, [#386](https://github.com/pydantic/pydantic/issues/386) by [@pilosus](https://github.com/pilosus) +* fix to schema generation in dataclass-based models, [#408](https://github.com/pydantic/pydantic/issues/408) by [@pilosus](https://github.com/pilosus) +* fix path in nested models, [#437](https://github.com/pydantic/pydantic/issues/437) by [@kataev](https://github.com/kataev) +* add `Sequence` support, [#304](https://github.com/pydantic/pydantic/issues/304) by [@pilosus](https://github.com/pilosus) + +## v0.21.0 (2019-03-15) + +* fix typo in `NoneIsNotAllowedError` message, [#414](https://github.com/pydantic/pydantic/issues/414) by [@YaraslauZhylko](https://github.com/YaraslauZhylko) +* add `IPvAnyAddress`, `IPv4Address` and `IPv6Address` types, [#333](https://github.com/pydantic/pydantic/issues/333) by [@pilosus](https://github.com/pilosus) + +## v0.20.1 (2019-02-26) + +* fix type hints of `parse_obj` and similar methods, [#405](https://github.com/pydantic/pydantic/issues/405) by [@erosennin](https://github.com/erosennin) +* fix submodel validation, [#403](https://github.com/pydantic/pydantic/issues/403) by [@samuelcolvin](https://github.com/samuelcolvin) +* correct type hints for `ValidationError.json`, [#406](https://github.com/pydantic/pydantic/issues/406) by [@layday](https://github.com/layday) + +## v0.20.0 (2019-02-18) + +* fix tests for Python 3.8, [#396](https://github.com/pydantic/pydantic/issues/396) by [@samuelcolvin](https://github.com/samuelcolvin) +* Adds fields to the `dir` method for autocompletion in interactive sessions, [#398](https://github.com/pydantic/pydantic/issues/398) by [@dgasmith](https://github.com/dgasmith) +* support `ForwardRef` (and therefore `from __future__ import annotations`) with dataclasses, [#397](https://github.com/pydantic/pydantic/issues/397) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v0.20.0a1 (2019-02-13) + +* **breaking change** (maybe): more sophisticated argument parsing for validators, any subset of + `values`, `config` and `field` is now permitted, eg. `(cls, value, field)`, + however the variadic key word argument ("`**kwargs`") **must** be called `kwargs`, [#388](https://github.com/pydantic/pydantic/issues/388) by [@samuelcolvin](https://github.com/samuelcolvin) +* **breaking change**: Adds `skip_defaults` argument to `BaseModel.dict()` to allow skipping of fields that + were not explicitly set, signature of `Model.construct()` changed, [#389](https://github.com/pydantic/pydantic/issues/389) by [@dgasmith](https://github.com/dgasmith) +* add `py.typed` marker file for PEP-561 support, [#391](https://github.com/pydantic/pydantic/issues/391) by [@je-l](https://github.com/je-l) +* Fix `extra` behaviour for multiple inheritance/mix-ins, [#394](https://github.com/pydantic/pydantic/issues/394) by [@YaraslauZhylko](https://github.com/YaraslauZhylko) + +## v0.19.0 (2019-02-04) + +* Support `Callable` type hint, fix [#279](https://github.com/pydantic/pydantic/issues/279) by [@proofit404](https://github.com/proofit404) +* Fix schema for fields with `validator` decorator, fix [#375](https://github.com/pydantic/pydantic/issues/375) by [@tiangolo](https://github.com/tiangolo) +* Add `multiple_of` constraint to `ConstrainedDecimal`, `ConstrainedFloat`, `ConstrainedInt` + and their related types `condecimal`, `confloat`, and `conint` [#371](https://github.com/pydantic/pydantic/issues/371), thanks [@StephenBrown2](https://github.com/StephenBrown2) +* Deprecated `ignore_extra` and `allow_extra` Config fields in favor of `extra`, [#352](https://github.com/pydantic/pydantic/issues/352) by [@liiight](https://github.com/liiight) +* Add type annotations to all functions, test fully with mypy, [#373](https://github.com/pydantic/pydantic/issues/373) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix for 'missing' error with `validate_all` or `validate_always`, [#381](https://github.com/pydantic/pydantic/issues/381) by [@samuelcolvin](https://github.com/samuelcolvin) +* Change the second/millisecond watershed for date/datetime parsing to `2e10`, [#385](https://github.com/pydantic/pydantic/issues/385) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v0.18.2 (2019-01-22) + +* Fix to schema generation with `Optional` fields, fix [#361](https://github.com/pydantic/pydantic/issues/361) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v0.18.1 (2019-01-17) + +* add `ConstrainedBytes` and `conbytes` types, [#315](https://github.com/pydantic/pydantic/issues/315) [@Gr1N](https://github.com/Gr1N) +* adding `MANIFEST.in` to include license in package `.tar.gz`, [#358](https://github.com/pydantic/pydantic/issues/358) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v0.18.0 (2019-01-13) + +* **breaking change**: don't call validators on keys of dictionaries, [#254](https://github.com/pydantic/pydantic/issues/254) by [@samuelcolvin](https://github.com/samuelcolvin) +* Fix validators with `always=True` when the default is `None` or the type is optional, also prevent + `whole` validators being called for sub-fields, fix [#132](https://github.com/pydantic/pydantic/issues/132) by [@samuelcolvin](https://github.com/samuelcolvin) +* improve documentation for settings priority and allow it to be easily changed, [#343](https://github.com/pydantic/pydantic/issues/343) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix `ignore_extra=False` and `allow_population_by_alias=True`, fix [#257](https://github.com/pydantic/pydantic/issues/257) by [@samuelcolvin](https://github.com/samuelcolvin) +* **breaking change**: Set `BaseConfig` attributes `min_anystr_length` and `max_anystr_length` to + `None` by default, fix [#349](https://github.com/pydantic/pydantic/issues/349) in [#350](https://github.com/pydantic/pydantic/issues/350) by [@tiangolo](https://github.com/tiangolo) +* add support for postponed annotations, [#348](https://github.com/pydantic/pydantic/issues/348) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v0.17.0 (2018-12-27) + +* fix schema for `timedelta` as number, [#325](https://github.com/pydantic/pydantic/issues/325) by [@tiangolo](https://github.com/tiangolo) +* prevent validators being called repeatedly after inheritance, [#327](https://github.com/pydantic/pydantic/issues/327) by [@samuelcolvin](https://github.com/samuelcolvin) +* prevent duplicate validator check in ipython, fix [#312](https://github.com/pydantic/pydantic/issues/312) by [@samuelcolvin](https://github.com/samuelcolvin) +* add "Using Pydantic" section to docs, [#323](https://github.com/pydantic/pydantic/issues/323) by [@tiangolo](https://github.com/tiangolo) & [#326](https://github.com/pydantic/pydantic/issues/326) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix schema generation for fields annotated as `: dict`, `: list`, + `: tuple` and `: set`, [#330](https://github.com/pydantic/pydantic/issues/330) & [#335](https://github.com/pydantic/pydantic/issues/335) by [@nkonin](https://github.com/nkonin) +* add support for constrained strings as dict keys in schema, [#332](https://github.com/pydantic/pydantic/issues/332) by [@tiangolo](https://github.com/tiangolo) +* support for passing Config class in dataclasses decorator, [#276](https://github.com/pydantic/pydantic/issues/276) by [@jarekkar](https://github.com/jarekkar) + (**breaking change**: this supersedes the `validate_assignment` argument with `config`) +* support for nested dataclasses, [#334](https://github.com/pydantic/pydantic/issues/334) by [@samuelcolvin](https://github.com/samuelcolvin) +* better errors when getting an `ImportError` with `PyObject`, [#309](https://github.com/pydantic/pydantic/issues/309) by [@samuelcolvin](https://github.com/samuelcolvin) +* rename `get_validators` to `__get_validators__`, deprecation warning on use of old name, [#338](https://github.com/pydantic/pydantic/issues/338) by [@samuelcolvin](https://github.com/samuelcolvin) +* support `ClassVar` by excluding such attributes from fields, [#184](https://github.com/pydantic/pydantic/issues/184) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v0.16.1 (2018-12-10) + +* fix `create_model` to correctly use the passed `__config__`, [#320](https://github.com/pydantic/pydantic/issues/320) by [@hugoduncan](https://github.com/hugoduncan) + +## v0.16.0 (2018-12-03) + +* **breaking change**: refactor schema generation to be compatible with JSON Schema and OpenAPI specs, [#308](https://github.com/pydantic/pydantic/issues/308) by [@tiangolo](https://github.com/tiangolo) +* add `schema` to `schema` module to generate top-level schemas from base models, [#308](https://github.com/pydantic/pydantic/issues/308) by [@tiangolo](https://github.com/tiangolo) +* add additional fields to `Schema` class to declare validation for `str` and numeric values, [#311](https://github.com/pydantic/pydantic/issues/311) by [@tiangolo](https://github.com/tiangolo) +* rename `_schema` to `schema` on fields, [#318](https://github.com/pydantic/pydantic/issues/318) by [@samuelcolvin](https://github.com/samuelcolvin) +* add `case_insensitive` option to `BaseSettings` `Config`, [#277](https://github.com/pydantic/pydantic/issues/277) by [@jasonkuhrt](https://github.com/jasonkuhrt) + +## v0.15.0 (2018-11-18) + +* move codebase to use black, [#287](https://github.com/pydantic/pydantic/issues/287) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix alias use in settings, [#286](https://github.com/pydantic/pydantic/issues/286) by [@jasonkuhrt](https://github.com/jasonkuhrt) and [@samuelcolvin](https://github.com/samuelcolvin) +* fix datetime parsing in `parse_date`, [#298](https://github.com/pydantic/pydantic/issues/298) by [@samuelcolvin](https://github.com/samuelcolvin) +* allow dataclass inheritance, fix [#293](https://github.com/pydantic/pydantic/issues/293) by [@samuelcolvin](https://github.com/samuelcolvin) +* fix `PyObject = None`, fix [#305](https://github.com/pydantic/pydantic/issues/305) by [@samuelcolvin](https://github.com/samuelcolvin) +* allow `Pattern` type, fix [#303](https://github.com/pydantic/pydantic/issues/303) by [@samuelcolvin](https://github.com/samuelcolvin) + +## v0.14.0 (2018-10-02) + +* dataclasses decorator, [#269](https://github.com/pydantic/pydantic/issues/269) by [@Gaunt](https://github.com/Gaunt) and [@samuelcolvin](https://github.com/samuelcolvin) + +## v0.13.1 (2018-09-21) + +* fix issue where int_validator doesn't cast a `bool` to an `int` [#264](https://github.com/pydantic/pydantic/issues/264) by [@nphyatt](https://github.com/nphyatt) +* add deep copy support for `BaseModel.copy()` [#249](https://github.com/pydantic/pydantic/issues/249), [@gangefors](https://github.com/gangefors) + +## v0.13.0 (2018-08-25) + +* raise an exception if a field's name shadows an existing `BaseModel` attribute [#242](https://github.com/pydantic/pydantic/issues/242) +* add `UrlStr` and `urlstr` types [#236](https://github.com/pydantic/pydantic/issues/236) +* timedelta json encoding ISO8601 and total seconds, custom json encoders [#247](https://github.com/pydantic/pydantic/issues/247), by [@cfkanesan](https://github.com/cfkanesan) and [@samuelcolvin](https://github.com/samuelcolvin) +* allow `timedelta` objects as values for properties of type `timedelta` (matches `datetime` etc. behavior) [#247](https://github.com/pydantic/pydantic/issues/247) + +## v0.12.1 (2018-07-31) + +* fix schema generation for fields defined using `typing.Any` [#237](https://github.com/pydantic/pydantic/issues/237) + +## v0.12.0 (2018-07-31) + +* add `by_alias` argument in `.dict()` and `.json()` model methods [#205](https://github.com/pydantic/pydantic/issues/205) +* add Json type support [#214](https://github.com/pydantic/pydantic/issues/214) +* support tuples [#227](https://github.com/pydantic/pydantic/issues/227) +* major improvements and changes to schema [#213](https://github.com/pydantic/pydantic/issues/213) + +## v0.11.2 (2018-07-05) + +* add `NewType` support [#115](https://github.com/pydantic/pydantic/issues/115) +* fix `list`, `set` & `tuple` validation [#225](https://github.com/pydantic/pydantic/issues/225) +* separate out `validate_model` method, allow errors to be returned along with valid values [#221](https://github.com/pydantic/pydantic/issues/221) + +## v0.11.1 (2018-07-02) + +* support Python 3.7 [#216](https://github.com/pydantic/pydantic/issues/216), thanks [@layday](https://github.com/layday) +* Allow arbitrary types in model [#209](https://github.com/pydantic/pydantic/issues/209), thanks [@oldPadavan](https://github.com/oldPadavan) + +## v0.11.0 (2018-06-28) + +* make `list`, `tuple` and `set` types stricter [#86](https://github.com/pydantic/pydantic/issues/86) +* **breaking change**: remove msgpack parsing [#201](https://github.com/pydantic/pydantic/issues/201) +* add `FilePath` and `DirectoryPath` types [#10](https://github.com/pydantic/pydantic/issues/10) +* model schema generation [#190](https://github.com/pydantic/pydantic/issues/190) +* JSON serialisation of models and schemas [#133](https://github.com/pydantic/pydantic/issues/133) + +## v0.10.0 (2018-06-11) + +* add `Config.allow_population_by_alias` [#160](https://github.com/pydantic/pydantic/issues/160), thanks [@bendemaree](https://github.com/bendemaree) +* **breaking change**: new errors format [#179](https://github.com/pydantic/pydantic/issues/179), thanks [@Gr1N](https://github.com/Gr1N) +* **breaking change**: removed `Config.min_number_size` and `Config.max_number_size` [#183](https://github.com/pydantic/pydantic/issues/183), thanks [@Gr1N](https://github.com/Gr1N) +* **breaking change**: correct behaviour of `lt` and `gt` arguments to `conint` etc. [#188](https://github.com/pydantic/pydantic/issues/188) + for the old behaviour use `le` and `ge` [#194](https://github.com/pydantic/pydantic/issues/194), thanks [@jaheba](https://github.com/jaheba) +* added error context and ability to redefine error message templates using `Config.error_msg_templates` [#183](https://github.com/pydantic/pydantic/issues/183), + thanks [@Gr1N](https://github.com/Gr1N) +* fix typo in validator exception [#150](https://github.com/pydantic/pydantic/issues/150) +* copy defaults to model values, so different models don't share objects [#154](https://github.com/pydantic/pydantic/issues/154) + +## v0.9.1 (2018-05-10) + +* allow custom `get_field_config` on config classes [#159](https://github.com/pydantic/pydantic/issues/159) +* add `UUID1`, `UUID3`, `UUID4` and `UUID5` types [#167](https://github.com/pydantic/pydantic/issues/167), thanks [@Gr1N](https://github.com/Gr1N) +* modify some inconsistent docstrings and annotations [#173](https://github.com/pydantic/pydantic/issues/173), thanks [@YannLuo](https://github.com/YannLuo) +* fix type annotations for exotic types [#171](https://github.com/pydantic/pydantic/issues/171), thanks [@Gr1N](https://github.com/Gr1N) +* re-use type validators in exotic types [#171](https://github.com/pydantic/pydantic/issues/171) +* scheduled monthly requirements updates [#168](https://github.com/pydantic/pydantic/issues/168) +* add `Decimal`, `ConstrainedDecimal` and `condecimal` types [#170](https://github.com/pydantic/pydantic/issues/170), thanks [@Gr1N](https://github.com/Gr1N) + +## v0.9.0 (2018-04-28) + +* tweak email-validator import error message [#145](https://github.com/pydantic/pydantic/issues/145) +* fix parse error of `parse_date()` and `parse_datetime()` when input is 0 [#144](https://github.com/pydantic/pydantic/issues/144), thanks [@YannLuo](https://github.com/YannLuo) +* add `Config.anystr_strip_whitespace` and `strip_whitespace` kwarg to `constr`, + by default values is `False` [#163](https://github.com/pydantic/pydantic/issues/163), thanks [@Gr1N](https://github.com/Gr1N) +* add `ConstrainedFloat`, `confloat`, `PositiveFloat` and `NegativeFloat` types [#166](https://github.com/pydantic/pydantic/issues/166), thanks [@Gr1N](https://github.com/Gr1N) + +## v0.8.0 (2018-03-25) + +* fix type annotation for `inherit_config` [#139](https://github.com/pydantic/pydantic/issues/139) +* **breaking change**: check for invalid field names in validators [#140](https://github.com/pydantic/pydantic/issues/140) +* validate attributes of parent models [#141](https://github.com/pydantic/pydantic/issues/141) +* **breaking change**: email validation now uses + [email-validator](https://github.com/JoshData/python-email-validator) [#142](https://github.com/pydantic/pydantic/issues/142) + +## v0.7.1 (2018-02-07) + +* fix bug with `create_model` modifying the base class + +## v0.7.0 (2018-02-06) + +* added compatibility with abstract base classes (ABCs) [#123](https://github.com/pydantic/pydantic/issues/123) +* add `create_model` method [#113](https://github.com/pydantic/pydantic/issues/113) [#125](https://github.com/pydantic/pydantic/issues/125) +* **breaking change**: rename `.config` to `.__config__` on a model +* **breaking change**: remove deprecated `.values()` on a model, use `.dict()` instead +* remove use of `OrderedDict` and use simple dict [#126](https://github.com/pydantic/pydantic/issues/126) +* add `Config.use_enum_values` [#127](https://github.com/pydantic/pydantic/issues/127) +* add wildcard validators of the form `@validate('*')` [#128](https://github.com/pydantic/pydantic/issues/128) + +## v0.6.4 (2018-02-01) + +* allow Python date and times objects [#122](https://github.com/pydantic/pydantic/issues/122) + +## v0.6.3 (2017-11-26) + +* fix direct install without `README.rst` present + +## v0.6.2 (2017-11-13) + +* errors for invalid validator use +* safer check for complex models in `Settings` + +## v0.6.1 (2017-11-08) + +* prevent duplicate validators, [#101](https://github.com/pydantic/pydantic/issues/101) +* add `always` kwarg to validators, [#102](https://github.com/pydantic/pydantic/issues/102) + +## v0.6.0 (2017-11-07) + +* assignment validation [#94](https://github.com/pydantic/pydantic/issues/94), thanks petroswork! +* JSON in environment variables for complex types, [#96](https://github.com/pydantic/pydantic/issues/96) +* add `validator` decorators for complex validation, [#97](https://github.com/pydantic/pydantic/issues/97) +* depreciate `values(...)` and replace with `.dict(...)`, [#99](https://github.com/pydantic/pydantic/issues/99) + +## v0.5.0 (2017-10-23) + +* add `UUID` validation [#89](https://github.com/pydantic/pydantic/issues/89) +* remove `index` and `track` from error object (json) if they're null [#90](https://github.com/pydantic/pydantic/issues/90) +* improve the error text when a list is provided rather than a dict [#90](https://github.com/pydantic/pydantic/issues/90) +* add benchmarks table to docs [#91](https://github.com/pydantic/pydantic/issues/91) + +## v0.4.0 (2017-07-08) + +* show length in string validation error +* fix aliases in config during inheritance [#55](https://github.com/pydantic/pydantic/issues/55) +* simplify error display +* use unicode ellipsis in `truncate` +* add `parse_obj`, `parse_raw` and `parse_file` helper functions [#58](https://github.com/pydantic/pydantic/issues/58) +* switch annotation only fields to come first in fields list not last + +## v0.3.0 (2017-06-21) + +* immutable models via `config.allow_mutation = False`, associated cleanup and performance improvement [#44](https://github.com/pydantic/pydantic/issues/44) +* immutable helper methods `construct()` and `copy()` [#53](https://github.com/pydantic/pydantic/issues/53) +* allow pickling of models [#53](https://github.com/pydantic/pydantic/issues/53) +* `setattr` is removed as `__setattr__` is now intelligent [#44](https://github.com/pydantic/pydantic/issues/44) +* `raise_exception` removed, Models now always raise exceptions [#44](https://github.com/pydantic/pydantic/issues/44) +* instance method validators removed +* django-restful-framework benchmarks added [#47](https://github.com/pydantic/pydantic/issues/47) +* fix inheritance bug [#49](https://github.com/pydantic/pydantic/issues/49) +* make str type stricter so list, dict etc are not coerced to strings. [#52](https://github.com/pydantic/pydantic/issues/52) +* add `StrictStr` which only always strings as input [#52](https://github.com/pydantic/pydantic/issues/52) + +## v0.2.1 (2017-06-07) + +* pypi and travis together messed up the deploy of `v0.2` this should fix it + +## v0.2.0 (2017-06-07) + +* **breaking change**: `values()` on a model is now a method not a property, + takes `include` and `exclude` arguments +* allow annotation only fields to support mypy +* add pretty `to_string(pretty=True)` method for models + +## v0.1.0 (2017-06-03) + +* add docs +* add history diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic-1.10.16.dist-info/RECORD b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic-1.10.16.dist-info/RECORD new file mode 100644 index 0000000..0256ee4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic-1.10.16.dist-info/RECORD @@ -0,0 +1,63 @@ +pydantic-1.10.16.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pydantic-1.10.16.dist-info/METADATA,sha256=Ldh0YKJGR0hkHjBT3ZoV_g-IYq6ZZKXjhXqnDE9xNvE,151326 +pydantic-1.10.16.dist-info/RECORD,, +pydantic-1.10.16.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pydantic-1.10.16.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91 +pydantic-1.10.16.dist-info/entry_points.txt,sha256=EquH5n3pilIXg-LLa1K4evpu5-6dnvxzi6vwvkoAMns,45 +pydantic-1.10.16.dist-info/licenses/LICENSE,sha256=njlGaQrIi2tz6PABoFhq8TVovohS_VFOQ5Pzl2F2Q4c,1127 +pydantic-1.10.16.dist-info/top_level.txt,sha256=cmo_5n0F_YY5td5nPZBfdjBENkmGg_pE5ShWXYbXxTM,9 +pydantic/__init__.py,sha256=TeIqU1PmJdMH0ztvKf781k_e0ziVkpDNMD6Rx1BAPi0,2898 +pydantic/__pycache__/__init__.cpython-312.pyc,, +pydantic/__pycache__/_hypothesis_plugin.cpython-312.pyc,, +pydantic/__pycache__/annotated_types.cpython-312.pyc,, +pydantic/__pycache__/class_validators.cpython-312.pyc,, +pydantic/__pycache__/color.cpython-312.pyc,, +pydantic/__pycache__/config.cpython-312.pyc,, +pydantic/__pycache__/dataclasses.cpython-312.pyc,, +pydantic/__pycache__/datetime_parse.cpython-312.pyc,, +pydantic/__pycache__/decorator.cpython-312.pyc,, +pydantic/__pycache__/env_settings.cpython-312.pyc,, +pydantic/__pycache__/error_wrappers.cpython-312.pyc,, +pydantic/__pycache__/errors.cpython-312.pyc,, +pydantic/__pycache__/fields.cpython-312.pyc,, +pydantic/__pycache__/generics.cpython-312.pyc,, +pydantic/__pycache__/json.cpython-312.pyc,, +pydantic/__pycache__/main.cpython-312.pyc,, +pydantic/__pycache__/mypy.cpython-312.pyc,, +pydantic/__pycache__/networks.cpython-312.pyc,, +pydantic/__pycache__/parse.cpython-312.pyc,, +pydantic/__pycache__/schema.cpython-312.pyc,, +pydantic/__pycache__/tools.cpython-312.pyc,, +pydantic/__pycache__/types.cpython-312.pyc,, +pydantic/__pycache__/typing.cpython-312.pyc,, +pydantic/__pycache__/utils.cpython-312.pyc,, +pydantic/__pycache__/v1.cpython-312.pyc,, +pydantic/__pycache__/validators.cpython-312.pyc,, +pydantic/__pycache__/version.cpython-312.pyc,, +pydantic/_hypothesis_plugin.py,sha256=gILcyAEfZ3u9YfKxtDxkReLpakjMou1VWC3FEcXmJgQ,14844 +pydantic/annotated_types.py,sha256=BfEVx8bdMUFK-AlO-LU-fxt2I_7xQwNA_fl-mbuNrbM,3148 +pydantic/class_validators.py,sha256=JumZvw-ZPc_EQZAK_qqtgTzz1pcWVShBYM8ghDXpIHA,14651 +pydantic/color.py,sha256=AlQ4wBEgeU8-Va-5pV_FObl5lA7r579EF-MHt-nkphI,16835 +pydantic/config.py,sha256=1-fak1i6rfrY7iuFC-JcXuC2BkJ5M8v6u62k8BsmZrM,6517 +pydantic/dataclasses.py,sha256=_zFFUJIx1hlaI0CT151gzKzjbPFi0gd8adb9POFtWvA,18145 +pydantic/datetime_parse.py,sha256=abJc-x71ik-Gz6ofbePDE2zmdgqGTTblStb8U_-s9SU,7721 +pydantic/decorator.py,sha256=OuGBAGeL-HYXis2hXKw9dgcks-ZwuttNRMl7hkt8Pbk,10318 +pydantic/env_settings.py,sha256=_haBeW4mDyciRenUt4L71vcWevkN68bVgzW7HcSDvr8,14087 +pydantic/error_wrappers.py,sha256=HPT2e25KJyMF3qm0nhPUmlso166_OcHxj32NR_rRtII,5181 +pydantic/errors.py,sha256=eCC88uVOeX1TacrjDAcpcZd8nxmpLWaTAK9LImWhx6o,17717 +pydantic/fields.py,sha256=dOeDmaUxRVywbD8_BBLEsJFPP3HN-mNNdOoHwDPECF0,50604 +pydantic/generics.py,sha256=bMBu8urVkYq_MwCjqHA6TPLG1qIe6MoMZZ4zX8FBpFU,17853 +pydantic/json.py,sha256=Ia86XPrskWFxCl6Bp9KvKXY56nl3COOPABUuu9bFLKU,3378 +pydantic/main.py,sha256=PMkIaXPUPNcju_nNRoDutDvEToMwM0L02K5ypp1jTns,44496 +pydantic/mypy.py,sha256=hh_d645pOfcKDeWbuvM10wlEn33aK-wjHcJxRE7sHCs,38771 +pydantic/networks.py,sha256=VZFhVZWDeaC71kufxBYQExSuTVQxjSjXFJAzBMAU1QU,22106 +pydantic/parse.py,sha256=t09djjmx7CLALG8lg83hAonV6qbRwhIP8PSSzxULZKk,1818 +pydantic/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pydantic/schema.py,sha256=YoReTBcnhzEz6fRj4gQOGHPDfdc65c-X_PtCaV2US3k,47710 +pydantic/tools.py,sha256=GNOURtVeWh0RbashriXadzh6G6NQOjvhCKdaoepmV5E,2866 +pydantic/types.py,sha256=9nrl-YFHkW6iE8PtteQFWFSmz2pJvsT38poNLSgwPpM,35434 +pydantic/typing.py,sha256=OmORFCDRBjBxJoHomOSvNZlIo6Mv4CoL8VK58XzJUDM,19234 +pydantic/utils.py,sha256=oXx5P7NRQllgZdoXorFLFh8qij0yKVwiQejUznA5rGI,25889 +pydantic/v1.py,sha256=mUdulX-fZ4Kb1URsHRaQLzSSq0beVkL7NuPutO2wftk,2674 +pydantic/validators.py,sha256=9N-zeBytOIWUcTqT5aJnNZuwCERmab_5QGLYfKnmFAU,21966 +pydantic/version.py,sha256=XJgzOxlJwdKTl32VGaCDtaOBUeG52t2R3Hmqa4bXNkM,1039 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic-1.10.16.dist-info/REQUESTED b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic-1.10.16.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic-1.10.16.dist-info/WHEEL b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic-1.10.16.dist-info/WHEEL new file mode 100644 index 0000000..14a883f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic-1.10.16.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: setuptools (82.0.1) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic-1.10.16.dist-info/entry_points.txt b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic-1.10.16.dist-info/entry_points.txt new file mode 100644 index 0000000..6178b39 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic-1.10.16.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[hypothesis] +_ = pydantic._hypothesis_plugin diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic-1.10.16.dist-info/licenses/LICENSE b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic-1.10.16.dist-info/licenses/LICENSE new file mode 100644 index 0000000..411ce48 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic-1.10.16.dist-info/licenses/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2017, 2018, 2019, 2020, 2021 Samuel Colvin and other 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. diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic-1.10.16.dist-info/top_level.txt b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic-1.10.16.dist-info/top_level.txt new file mode 100644 index 0000000..572b352 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic-1.10.16.dist-info/top_level.txt @@ -0,0 +1 @@ +pydantic diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/__init__.py new file mode 100644 index 0000000..f3262a2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/__init__.py @@ -0,0 +1,131 @@ +# flake8: noqa +from pydantic import dataclasses +from pydantic.annotated_types import create_model_from_namedtuple, create_model_from_typeddict +from pydantic.class_validators import root_validator, validator +from pydantic.config import BaseConfig, ConfigDict, Extra +from pydantic.decorator import validate_arguments +from pydantic.env_settings import BaseSettings +from pydantic.error_wrappers import ValidationError +from pydantic.errors import * +from pydantic.fields import Field, PrivateAttr, Required +from pydantic.main import * +from pydantic.networks import * +from pydantic.parse import Protocol +from pydantic.tools import * +from pydantic.types import * +from pydantic.version import VERSION, compiled + +__version__ = VERSION + +# WARNING __all__ from pydantic.errors is not included here, it will be removed as an export here in v2 +# please use "from pydantic.errors import ..." instead +__all__ = [ + # annotated types utils + 'create_model_from_namedtuple', + 'create_model_from_typeddict', + # dataclasses + 'dataclasses', + # class_validators + 'root_validator', + 'validator', + # config + 'BaseConfig', + 'ConfigDict', + 'Extra', + # decorator + 'validate_arguments', + # env_settings + 'BaseSettings', + # error_wrappers + 'ValidationError', + # fields + 'Field', + 'Required', + # main + 'BaseModel', + 'create_model', + 'validate_model', + # network + 'AnyUrl', + 'AnyHttpUrl', + 'FileUrl', + 'HttpUrl', + 'stricturl', + 'EmailStr', + 'NameEmail', + 'IPvAnyAddress', + 'IPvAnyInterface', + 'IPvAnyNetwork', + 'PostgresDsn', + 'CockroachDsn', + 'AmqpDsn', + 'RedisDsn', + 'MongoDsn', + 'KafkaDsn', + 'validate_email', + # parse + 'Protocol', + # tools + 'parse_file_as', + 'parse_obj_as', + 'parse_raw_as', + 'schema_of', + 'schema_json_of', + # types + 'NoneStr', + 'NoneBytes', + 'StrBytes', + 'NoneStrBytes', + 'StrictStr', + 'ConstrainedBytes', + 'conbytes', + 'ConstrainedList', + 'conlist', + 'ConstrainedSet', + 'conset', + 'ConstrainedFrozenSet', + 'confrozenset', + 'ConstrainedStr', + 'constr', + 'PyObject', + 'ConstrainedInt', + 'conint', + 'PositiveInt', + 'NegativeInt', + 'NonNegativeInt', + 'NonPositiveInt', + 'ConstrainedFloat', + 'confloat', + 'PositiveFloat', + 'NegativeFloat', + 'NonNegativeFloat', + 'NonPositiveFloat', + 'FiniteFloat', + 'ConstrainedDecimal', + 'condecimal', + 'ConstrainedDate', + 'condate', + 'UUID1', + 'UUID3', + 'UUID4', + 'UUID5', + 'FilePath', + 'DirectoryPath', + 'Json', + 'JsonWrapper', + 'SecretField', + 'SecretStr', + 'SecretBytes', + 'StrictBool', + 'StrictBytes', + 'StrictInt', + 'StrictFloat', + 'PaymentCardNumber', + 'PrivateAttr', + 'ByteSize', + 'PastDate', + 'FutureDate', + # version + 'compiled', + 'VERSION', +] diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/_hypothesis_plugin.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/_hypothesis_plugin.py new file mode 100644 index 0000000..0c52962 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/_hypothesis_plugin.py @@ -0,0 +1,391 @@ +""" +Register Hypothesis strategies for Pydantic custom types. + +This enables fully-automatic generation of test data for most Pydantic classes. + +Note that this module has *no* runtime impact on Pydantic itself; instead it +is registered as a setuptools entry point and Hypothesis will import it if +Pydantic is installed. See also: + +https://hypothesis.readthedocs.io/en/latest/strategies.html#registering-strategies-via-setuptools-entry-points +https://hypothesis.readthedocs.io/en/latest/data.html#hypothesis.strategies.register_type_strategy +https://hypothesis.readthedocs.io/en/latest/strategies.html#interaction-with-pytest-cov +https://docs.pydantic.dev/usage/types/#pydantic-types + +Note that because our motivation is to *improve user experience*, the strategies +are always sound (never generate invalid data) but sacrifice completeness for +maintainability (ie may be unable to generate some tricky but valid data). + +Finally, this module makes liberal use of `# type: ignore[]` pragmas. +This is because Hypothesis annotates `register_type_strategy()` with +`(T, SearchStrategy[T])`, but in most cases we register e.g. `ConstrainedInt` +to generate instances of the builtin `int` type which match the constraints. +""" + +import contextlib +import datetime +import ipaddress +import json +import math +from fractions import Fraction +from typing import Callable, Dict, Type, Union, cast, overload + +import hypothesis.strategies as st + +import pydantic +import pydantic.color +import pydantic.types +from pydantic.utils import lenient_issubclass + +# FilePath and DirectoryPath are explicitly unsupported, as we'd have to create +# them on-disk, and that's unsafe in general without being told *where* to do so. +# +# URLs are unsupported because it's easy for users to define their own strategy for +# "normal" URLs, and hard for us to define a general strategy which includes "weird" +# URLs but doesn't also have unpredictable performance problems. +# +# conlist() and conset() are unsupported for now, because the workarounds for +# Cython and Hypothesis to handle parametrized generic types are incompatible. +# We are rethinking Hypothesis compatibility in Pydantic v2. + +# Emails +try: + import email_validator +except ImportError: # pragma: no cover + pass +else: + + def is_valid_email(s: str) -> bool: + # Hypothesis' st.emails() occasionally generates emails like 0@A0--0.ac + # that are invalid according to email-validator, so we filter those out. + try: + email_validator.validate_email(s, check_deliverability=False) + return True + except email_validator.EmailNotValidError: # pragma: no cover + return False + + # Note that these strategies deliberately stay away from any tricky Unicode + # or other encoding issues; we're just trying to generate *something* valid. + st.register_type_strategy(pydantic.EmailStr, st.emails().filter(is_valid_email)) # type: ignore[arg-type] + st.register_type_strategy( + pydantic.NameEmail, + st.builds( + '{} <{}>'.format, # type: ignore[arg-type] + st.from_regex('[A-Za-z0-9_]+( [A-Za-z0-9_]+){0,5}', fullmatch=True), + st.emails().filter(is_valid_email), + ), + ) + +# PyObject - dotted names, in this case taken from the math module. +st.register_type_strategy( + pydantic.PyObject, # type: ignore[arg-type] + st.sampled_from( + [cast(pydantic.PyObject, f'math.{name}') for name in sorted(vars(math)) if not name.startswith('_')] + ), +) + +# CSS3 Colors; as name, hex, rgb(a) tuples or strings, or hsl strings +_color_regexes = ( + '|'.join( + ( + pydantic.color.r_hex_short, + pydantic.color.r_hex_long, + pydantic.color.r_rgb, + pydantic.color.r_rgba, + pydantic.color.r_hsl, + pydantic.color.r_hsla, + ) + ) + # Use more precise regex patterns to avoid value-out-of-range errors + .replace(pydantic.color._r_sl, r'(?:(\d\d?(?:\.\d+)?|100(?:\.0+)?)%)') + .replace(pydantic.color._r_alpha, r'(?:(0(?:\.\d+)?|1(?:\.0+)?|\.\d+|\d{1,2}%))') + .replace(pydantic.color._r_255, r'(?:((?:\d|\d\d|[01]\d\d|2[0-4]\d|25[0-4])(?:\.\d+)?|255(?:\.0+)?))') +) +st.register_type_strategy( + pydantic.color.Color, + st.one_of( + st.sampled_from(sorted(pydantic.color.COLORS_BY_NAME)), + st.tuples( + st.integers(0, 255), + st.integers(0, 255), + st.integers(0, 255), + st.none() | st.floats(0, 1) | st.floats(0, 100).map('{}%'.format), + ), + st.from_regex(_color_regexes, fullmatch=True), + ), +) + + +# Card numbers, valid according to the Luhn algorithm + + +def add_luhn_digit(card_number: str) -> str: + # See https://en.wikipedia.org/wiki/Luhn_algorithm + for digit in '0123456789': + with contextlib.suppress(Exception): + pydantic.PaymentCardNumber.validate_luhn_check_digit(card_number + digit) + return card_number + digit + raise AssertionError('Unreachable') # pragma: no cover + + +card_patterns = ( + # Note that these patterns omit the Luhn check digit; that's added by the function above + '4[0-9]{14}', # Visa + '5[12345][0-9]{13}', # Mastercard + '3[47][0-9]{12}', # American Express + '[0-26-9][0-9]{10,17}', # other (incomplete to avoid overlap) +) +st.register_type_strategy( + pydantic.PaymentCardNumber, + st.from_regex('|'.join(card_patterns), fullmatch=True).map(add_luhn_digit), # type: ignore[arg-type] +) + +# UUIDs +st.register_type_strategy(pydantic.UUID1, st.uuids(version=1)) +st.register_type_strategy(pydantic.UUID3, st.uuids(version=3)) +st.register_type_strategy(pydantic.UUID4, st.uuids(version=4)) +st.register_type_strategy(pydantic.UUID5, st.uuids(version=5)) + +# Secrets +st.register_type_strategy(pydantic.SecretBytes, st.binary().map(pydantic.SecretBytes)) +st.register_type_strategy(pydantic.SecretStr, st.text().map(pydantic.SecretStr)) + +# IP addresses, networks, and interfaces +st.register_type_strategy(pydantic.IPvAnyAddress, st.ip_addresses()) # type: ignore[arg-type] +st.register_type_strategy( + pydantic.IPvAnyInterface, + st.from_type(ipaddress.IPv4Interface) | st.from_type(ipaddress.IPv6Interface), # type: ignore[arg-type] +) +st.register_type_strategy( + pydantic.IPvAnyNetwork, + st.from_type(ipaddress.IPv4Network) | st.from_type(ipaddress.IPv6Network), # type: ignore[arg-type] +) + +# We hook into the con***() functions and the ConstrainedNumberMeta metaclass, +# so here we only have to register subclasses for other constrained types which +# don't go via those mechanisms. Then there are the registration hooks below. +st.register_type_strategy(pydantic.StrictBool, st.booleans()) +st.register_type_strategy(pydantic.StrictStr, st.text()) + + +# FutureDate, PastDate +st.register_type_strategy(pydantic.FutureDate, st.dates(min_value=datetime.date.today() + datetime.timedelta(days=1))) +st.register_type_strategy(pydantic.PastDate, st.dates(max_value=datetime.date.today() - datetime.timedelta(days=1))) + + +# Constrained-type resolver functions +# +# For these ones, we actually want to inspect the type in order to work out a +# satisfying strategy. First up, the machinery for tracking resolver functions: + +RESOLVERS: Dict[type, Callable[[type], st.SearchStrategy]] = {} # type: ignore[type-arg] + + +@overload +def _registered(typ: Type[pydantic.types.T]) -> Type[pydantic.types.T]: + pass + + +@overload +def _registered(typ: pydantic.types.ConstrainedNumberMeta) -> pydantic.types.ConstrainedNumberMeta: + pass + + +def _registered( + typ: Union[Type[pydantic.types.T], pydantic.types.ConstrainedNumberMeta] +) -> Union[Type[pydantic.types.T], pydantic.types.ConstrainedNumberMeta]: + # This function replaces the version in `pydantic.types`, in order to + # effect the registration of new constrained types so that Hypothesis + # can generate valid examples. + pydantic.types._DEFINED_TYPES.add(typ) + for supertype, resolver in RESOLVERS.items(): + if issubclass(typ, supertype): + st.register_type_strategy(typ, resolver(typ)) # type: ignore + return typ + raise NotImplementedError(f'Unknown type {typ!r} has no resolver to register') # pragma: no cover + + +def resolves( + typ: Union[type, pydantic.types.ConstrainedNumberMeta] +) -> Callable[[Callable[..., st.SearchStrategy]], Callable[..., st.SearchStrategy]]: # type: ignore[type-arg] + def inner(f): # type: ignore + assert f not in RESOLVERS + RESOLVERS[typ] = f + return f + + return inner + + +# Type-to-strategy resolver functions + + +@resolves(pydantic.JsonWrapper) +def resolve_json(cls): # type: ignore[no-untyped-def] + try: + inner = st.none() if cls.inner_type is None else st.from_type(cls.inner_type) + except Exception: # pragma: no cover + finite = st.floats(allow_infinity=False, allow_nan=False) + inner = st.recursive( + base=st.one_of(st.none(), st.booleans(), st.integers(), finite, st.text()), + extend=lambda x: st.lists(x) | st.dictionaries(st.text(), x), # type: ignore + ) + inner_type = getattr(cls, 'inner_type', None) + return st.builds( + cls.inner_type.json if lenient_issubclass(inner_type, pydantic.BaseModel) else json.dumps, + inner, + ensure_ascii=st.booleans(), + indent=st.none() | st.integers(0, 16), + sort_keys=st.booleans(), + ) + + +@resolves(pydantic.ConstrainedBytes) +def resolve_conbytes(cls): # type: ignore[no-untyped-def] # pragma: no cover + min_size = cls.min_length or 0 + max_size = cls.max_length + if not cls.strip_whitespace: + return st.binary(min_size=min_size, max_size=max_size) + # Fun with regex to ensure we neither start nor end with whitespace + repeats = '{{{},{}}}'.format( + min_size - 2 if min_size > 2 else 0, + max_size - 2 if (max_size or 0) > 2 else '', + ) + if min_size >= 2: + pattern = rf'\W.{repeats}\W' + elif min_size == 1: + pattern = rf'\W(.{repeats}\W)?' + else: + assert min_size == 0 + pattern = rf'(\W(.{repeats}\W)?)?' + return st.from_regex(pattern.encode(), fullmatch=True) + + +@resolves(pydantic.ConstrainedDecimal) +def resolve_condecimal(cls): # type: ignore[no-untyped-def] + min_value = cls.ge + max_value = cls.le + if cls.gt is not None: + assert min_value is None, 'Set `gt` or `ge`, but not both' + min_value = cls.gt + if cls.lt is not None: + assert max_value is None, 'Set `lt` or `le`, but not both' + max_value = cls.lt + s = st.decimals(min_value, max_value, allow_nan=False, places=cls.decimal_places) + if cls.lt is not None: + s = s.filter(lambda d: d < cls.lt) + if cls.gt is not None: + s = s.filter(lambda d: cls.gt < d) + return s + + +@resolves(pydantic.ConstrainedFloat) +def resolve_confloat(cls): # type: ignore[no-untyped-def] + min_value = cls.ge + max_value = cls.le + exclude_min = False + exclude_max = False + + if cls.gt is not None: + assert min_value is None, 'Set `gt` or `ge`, but not both' + min_value = cls.gt + exclude_min = True + if cls.lt is not None: + assert max_value is None, 'Set `lt` or `le`, but not both' + max_value = cls.lt + exclude_max = True + + if cls.multiple_of is None: + return st.floats(min_value, max_value, exclude_min=exclude_min, exclude_max=exclude_max, allow_nan=False) + + if min_value is not None: + min_value = math.ceil(min_value / cls.multiple_of) + if exclude_min: + min_value = min_value + 1 + if max_value is not None: + assert max_value >= cls.multiple_of, 'Cannot build model with max value smaller than multiple of' + max_value = math.floor(max_value / cls.multiple_of) + if exclude_max: + max_value = max_value - 1 + + return st.integers(min_value, max_value).map(lambda x: x * cls.multiple_of) + + +@resolves(pydantic.ConstrainedInt) +def resolve_conint(cls): # type: ignore[no-untyped-def] + min_value = cls.ge + max_value = cls.le + if cls.gt is not None: + assert min_value is None, 'Set `gt` or `ge`, but not both' + min_value = cls.gt + 1 + if cls.lt is not None: + assert max_value is None, 'Set `lt` or `le`, but not both' + max_value = cls.lt - 1 + + if cls.multiple_of is None or cls.multiple_of == 1: + return st.integers(min_value, max_value) + + # These adjustments and the .map handle integer-valued multiples, while the + # .filter handles trickier cases as for confloat. + if min_value is not None: + min_value = math.ceil(Fraction(min_value) / Fraction(cls.multiple_of)) + if max_value is not None: + max_value = math.floor(Fraction(max_value) / Fraction(cls.multiple_of)) + return st.integers(min_value, max_value).map(lambda x: x * cls.multiple_of) + + +@resolves(pydantic.ConstrainedDate) +def resolve_condate(cls): # type: ignore[no-untyped-def] + if cls.ge is not None: + assert cls.gt is None, 'Set `gt` or `ge`, but not both' + min_value = cls.ge + elif cls.gt is not None: + min_value = cls.gt + datetime.timedelta(days=1) + else: + min_value = datetime.date.min + if cls.le is not None: + assert cls.lt is None, 'Set `lt` or `le`, but not both' + max_value = cls.le + elif cls.lt is not None: + max_value = cls.lt - datetime.timedelta(days=1) + else: + max_value = datetime.date.max + return st.dates(min_value, max_value) + + +@resolves(pydantic.ConstrainedStr) +def resolve_constr(cls): # type: ignore[no-untyped-def] # pragma: no cover + min_size = cls.min_length or 0 + max_size = cls.max_length + + if cls.regex is None and not cls.strip_whitespace: + return st.text(min_size=min_size, max_size=max_size) + + if cls.regex is not None: + strategy = st.from_regex(cls.regex) + if cls.strip_whitespace: + strategy = strategy.filter(lambda s: s == s.strip()) + elif cls.strip_whitespace: + repeats = '{{{},{}}}'.format( + min_size - 2 if min_size > 2 else 0, + max_size - 2 if (max_size or 0) > 2 else '', + ) + if min_size >= 2: + strategy = st.from_regex(rf'\W.{repeats}\W') + elif min_size == 1: + strategy = st.from_regex(rf'\W(.{repeats}\W)?') + else: + assert min_size == 0 + strategy = st.from_regex(rf'(\W(.{repeats}\W)?)?') + + if min_size == 0 and max_size is None: + return strategy + elif max_size is None: + return strategy.filter(lambda s: min_size <= len(s)) + return strategy.filter(lambda s: min_size <= len(s) <= max_size) + + +# Finally, register all previously-defined types, and patch in our new function +for typ in list(pydantic.types._DEFINED_TYPES): + _registered(typ) +pydantic.types._registered = _registered +st.register_type_strategy(pydantic.Json, resolve_json) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/annotated_types.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/annotated_types.py new file mode 100644 index 0000000..27a12a6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/annotated_types.py @@ -0,0 +1,72 @@ +import sys +from typing import TYPE_CHECKING, Any, Dict, FrozenSet, NamedTuple, Type + +from pydantic.fields import Required +from pydantic.main import BaseModel, create_model +from pydantic.typing import is_typeddict, is_typeddict_special + +if TYPE_CHECKING: + from typing_extensions import TypedDict + +if sys.version_info < (3, 11): + + def is_legacy_typeddict(typeddict_cls: Type['TypedDict']) -> bool: # type: ignore[valid-type] + return is_typeddict(typeddict_cls) and type(typeddict_cls).__module__ == 'typing' + +else: + + def is_legacy_typeddict(_: Any) -> Any: + return False + + +def create_model_from_typeddict( + # Mypy bug: `Type[TypedDict]` is resolved as `Any` https://github.com/python/mypy/issues/11030 + typeddict_cls: Type['TypedDict'], # type: ignore[valid-type] + **kwargs: Any, +) -> Type['BaseModel']: + """ + Create a `BaseModel` based on the fields of a `TypedDict`. + Since `typing.TypedDict` in Python 3.8 does not store runtime information about optional keys, + we raise an error if this happens (see https://bugs.python.org/issue38834). + """ + field_definitions: Dict[str, Any] + + # Best case scenario: with python 3.9+ or when `TypedDict` is imported from `typing_extensions` + if not hasattr(typeddict_cls, '__required_keys__'): + raise TypeError( + 'You should use `typing_extensions.TypedDict` instead of `typing.TypedDict` with Python < 3.9.2. ' + 'Without it, there is no way to differentiate required and optional fields when subclassed.' + ) + + if is_legacy_typeddict(typeddict_cls) and any( + is_typeddict_special(t) for t in typeddict_cls.__annotations__.values() + ): + raise TypeError( + 'You should use `typing_extensions.TypedDict` instead of `typing.TypedDict` with Python < 3.11. ' + 'Without it, there is no way to reflect Required/NotRequired keys.' + ) + + required_keys: FrozenSet[str] = typeddict_cls.__required_keys__ # type: ignore[attr-defined] + field_definitions = { + field_name: (field_type, Required if field_name in required_keys else None) + for field_name, field_type in typeddict_cls.__annotations__.items() + } + + return create_model(typeddict_cls.__name__, **kwargs, **field_definitions) + + +def create_model_from_namedtuple(namedtuple_cls: Type['NamedTuple'], **kwargs: Any) -> Type['BaseModel']: + """ + Create a `BaseModel` based on the fields of a named tuple. + A named tuple can be created with `typing.NamedTuple` and declared annotations + but also with `collections.namedtuple`, in this case we consider all fields + to have type `Any`. + """ + # With python 3.10+, `__annotations__` always exists but can be empty hence the `getattr... or...` logic + namedtuple_annotations: Dict[str, Type[Any]] = getattr(namedtuple_cls, '__annotations__', None) or { + k: Any for k in namedtuple_cls._fields + } + field_definitions: Dict[str, Any] = { + field_name: (field_type, Required) for field_name, field_type in namedtuple_annotations.items() + } + return create_model(namedtuple_cls.__name__, **kwargs, **field_definitions) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/class_validators.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/class_validators.py new file mode 100644 index 0000000..3959cde --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/class_validators.py @@ -0,0 +1,361 @@ +import warnings +from collections import ChainMap +from functools import partial, partialmethod, wraps +from itertools import chain +from types import FunctionType +from typing import TYPE_CHECKING, Any, Callable, Dict, Iterable, List, Optional, Set, Tuple, Type, Union, overload + +from pydantic.errors import ConfigError +from pydantic.typing import AnyCallable +from pydantic.utils import ROOT_KEY, in_ipython + +if TYPE_CHECKING: + from pydantic.typing import AnyClassMethod + + +class Validator: + __slots__ = 'func', 'pre', 'each_item', 'always', 'check_fields', 'skip_on_failure' + + def __init__( + self, + func: AnyCallable, + pre: bool = False, + each_item: bool = False, + always: bool = False, + check_fields: bool = False, + skip_on_failure: bool = False, + ): + self.func = func + self.pre = pre + self.each_item = each_item + self.always = always + self.check_fields = check_fields + self.skip_on_failure = skip_on_failure + + +if TYPE_CHECKING: + from inspect import Signature + + from pydantic.config import BaseConfig + from pydantic.fields import ModelField + from pydantic.types import ModelOrDc + + ValidatorCallable = Callable[[Optional[ModelOrDc], Any, Dict[str, Any], ModelField, Type[BaseConfig]], Any] + ValidatorsList = List[ValidatorCallable] + ValidatorListDict = Dict[str, List[Validator]] + +_FUNCS: Set[str] = set() +VALIDATOR_CONFIG_KEY = '__validator_config__' +ROOT_VALIDATOR_CONFIG_KEY = '__root_validator_config__' + + +def validator( + *fields: str, + pre: bool = False, + each_item: bool = False, + always: bool = False, + check_fields: bool = True, + whole: Optional[bool] = None, + allow_reuse: bool = False, +) -> Callable[[AnyCallable], 'AnyClassMethod']: + """ + Decorate methods on the class indicating that they should be used to validate fields + :param fields: which field(s) the method should be called on + :param pre: whether or not this validator should be called before the standard validators (else after) + :param each_item: for complex objects (sets, lists etc.) whether to validate individual elements rather than the + whole object + :param always: whether this method and other validators should be called even if the value is missing + :param check_fields: whether to check that the fields actually exist on the model + :param allow_reuse: whether to track and raise an error if another validator refers to the decorated function + """ + if not fields: + raise ConfigError('validator with no fields specified') + elif isinstance(fields[0], FunctionType): + raise ConfigError( + "validators should be used with fields and keyword arguments, not bare. " # noqa: Q000 + "E.g. usage should be `@validator('', ...)`" + ) + elif not all(isinstance(field, str) for field in fields): + raise ConfigError( + "validator fields should be passed as separate string args. " # noqa: Q000 + "E.g. usage should be `@validator('', '', ...)`" + ) + + if whole is not None: + warnings.warn( + 'The "whole" keyword argument is deprecated, use "each_item" (inverse meaning, default False) instead', + DeprecationWarning, + ) + assert each_item is False, '"each_item" and "whole" conflict, remove "whole"' + each_item = not whole + + def dec(f: AnyCallable) -> 'AnyClassMethod': + f_cls = _prepare_validator(f, allow_reuse) + setattr( + f_cls, + VALIDATOR_CONFIG_KEY, + ( + fields, + Validator(func=f_cls.__func__, pre=pre, each_item=each_item, always=always, check_fields=check_fields), + ), + ) + return f_cls + + return dec + + +@overload +def root_validator(_func: AnyCallable) -> 'AnyClassMethod': + ... + + +@overload +def root_validator( + *, pre: bool = False, allow_reuse: bool = False, skip_on_failure: bool = False +) -> Callable[[AnyCallable], 'AnyClassMethod']: + ... + + +def root_validator( + _func: Optional[AnyCallable] = None, *, pre: bool = False, allow_reuse: bool = False, skip_on_failure: bool = False +) -> Union['AnyClassMethod', Callable[[AnyCallable], 'AnyClassMethod']]: + """ + Decorate methods on a model indicating that they should be used to validate (and perhaps modify) data either + before or after standard model parsing/validation is performed. + """ + if _func: + f_cls = _prepare_validator(_func, allow_reuse) + setattr( + f_cls, ROOT_VALIDATOR_CONFIG_KEY, Validator(func=f_cls.__func__, pre=pre, skip_on_failure=skip_on_failure) + ) + return f_cls + + def dec(f: AnyCallable) -> 'AnyClassMethod': + f_cls = _prepare_validator(f, allow_reuse) + setattr( + f_cls, ROOT_VALIDATOR_CONFIG_KEY, Validator(func=f_cls.__func__, pre=pre, skip_on_failure=skip_on_failure) + ) + return f_cls + + return dec + + +def _prepare_validator(function: AnyCallable, allow_reuse: bool) -> 'AnyClassMethod': + """ + Avoid validators with duplicated names since without this, validators can be overwritten silently + which generally isn't the intended behaviour, don't run in ipython (see #312) or if allow_reuse is False. + """ + f_cls = function if isinstance(function, classmethod) else classmethod(function) + if not in_ipython() and not allow_reuse: + ref = ( + getattr(f_cls.__func__, '__module__', '') + + '.' + + getattr(f_cls.__func__, '__qualname__', f'') + ) + if ref in _FUNCS: + raise ConfigError(f'duplicate validator function "{ref}"; if this is intended, set `allow_reuse=True`') + _FUNCS.add(ref) + return f_cls + + +class ValidatorGroup: + def __init__(self, validators: 'ValidatorListDict') -> None: + self.validators = validators + self.used_validators = {'*'} + + def get_validators(self, name: str) -> Optional[Dict[str, Validator]]: + self.used_validators.add(name) + validators = self.validators.get(name, []) + if name != ROOT_KEY: + validators += self.validators.get('*', []) + if validators: + return {getattr(v.func, '__name__', f''): v for v in validators} + else: + return None + + def check_for_unused(self) -> None: + unused_validators = set( + chain.from_iterable( + ( + getattr(v.func, '__name__', f'') + for v in self.validators[f] + if v.check_fields + ) + for f in (self.validators.keys() - self.used_validators) + ) + ) + if unused_validators: + fn = ', '.join(unused_validators) + raise ConfigError( + f"Validators defined with incorrect fields: {fn} " # noqa: Q000 + f"(use check_fields=False if you're inheriting from the model and intended this)" + ) + + +def extract_validators(namespace: Dict[str, Any]) -> Dict[str, List[Validator]]: + validators: Dict[str, List[Validator]] = {} + for var_name, value in namespace.items(): + validator_config = getattr(value, VALIDATOR_CONFIG_KEY, None) + if validator_config: + fields, v = validator_config + for field in fields: + if field in validators: + validators[field].append(v) + else: + validators[field] = [v] + return validators + + +def extract_root_validators(namespace: Dict[str, Any]) -> Tuple[List[AnyCallable], List[Tuple[bool, AnyCallable]]]: + from inspect import signature + + pre_validators: List[AnyCallable] = [] + post_validators: List[Tuple[bool, AnyCallable]] = [] + for name, value in namespace.items(): + validator_config: Optional[Validator] = getattr(value, ROOT_VALIDATOR_CONFIG_KEY, None) + if validator_config: + sig = signature(validator_config.func) + args = list(sig.parameters.keys()) + if args[0] == 'self': + raise ConfigError( + f'Invalid signature for root validator {name}: {sig}, "self" not permitted as first argument, ' + f'should be: (cls, values).' + ) + if len(args) != 2: + raise ConfigError(f'Invalid signature for root validator {name}: {sig}, should be: (cls, values).') + # check function signature + if validator_config.pre: + pre_validators.append(validator_config.func) + else: + post_validators.append((validator_config.skip_on_failure, validator_config.func)) + return pre_validators, post_validators + + +def inherit_validators(base_validators: 'ValidatorListDict', validators: 'ValidatorListDict') -> 'ValidatorListDict': + for field, field_validators in base_validators.items(): + if field not in validators: + validators[field] = [] + validators[field] += field_validators + return validators + + +def make_generic_validator(validator: AnyCallable) -> 'ValidatorCallable': + """ + Make a generic function which calls a validator with the right arguments. + + Unfortunately other approaches (eg. return a partial of a function that builds the arguments) is slow, + hence this laborious way of doing things. + + It's done like this so validators don't all need **kwargs in their signature, eg. any combination of + the arguments "values", "fields" and/or "config" are permitted. + """ + from inspect import signature + + if not isinstance(validator, (partial, partialmethod)): + # This should be the default case, so overhead is reduced + sig = signature(validator) + args = list(sig.parameters.keys()) + else: + # Fix the generated argument lists of partial methods + sig = signature(validator.func) + args = [ + k + for k in signature(validator.func).parameters.keys() + if k not in validator.args | validator.keywords.keys() + ] + + first_arg = args.pop(0) + if first_arg == 'self': + raise ConfigError( + f'Invalid signature for validator {validator}: {sig}, "self" not permitted as first argument, ' + f'should be: (cls, value, values, config, field), "values", "config" and "field" are all optional.' + ) + elif first_arg == 'cls': + # assume the second argument is value + return wraps(validator)(_generic_validator_cls(validator, sig, set(args[1:]))) + else: + # assume the first argument was value which has already been removed + return wraps(validator)(_generic_validator_basic(validator, sig, set(args))) + + +def prep_validators(v_funcs: Iterable[AnyCallable]) -> 'ValidatorsList': + return [make_generic_validator(f) for f in v_funcs if f] + + +all_kwargs = {'values', 'field', 'config'} + + +def _generic_validator_cls(validator: AnyCallable, sig: 'Signature', args: Set[str]) -> 'ValidatorCallable': + # assume the first argument is value + has_kwargs = False + if 'kwargs' in args: + has_kwargs = True + args -= {'kwargs'} + + if not args.issubset(all_kwargs): + raise ConfigError( + f'Invalid signature for validator {validator}: {sig}, should be: ' + f'(cls, value, values, config, field), "values", "config" and "field" are all optional.' + ) + + if has_kwargs: + return lambda cls, v, values, field, config: validator(cls, v, values=values, field=field, config=config) + elif args == set(): + return lambda cls, v, values, field, config: validator(cls, v) + elif args == {'values'}: + return lambda cls, v, values, field, config: validator(cls, v, values=values) + elif args == {'field'}: + return lambda cls, v, values, field, config: validator(cls, v, field=field) + elif args == {'config'}: + return lambda cls, v, values, field, config: validator(cls, v, config=config) + elif args == {'values', 'field'}: + return lambda cls, v, values, field, config: validator(cls, v, values=values, field=field) + elif args == {'values', 'config'}: + return lambda cls, v, values, field, config: validator(cls, v, values=values, config=config) + elif args == {'field', 'config'}: + return lambda cls, v, values, field, config: validator(cls, v, field=field, config=config) + else: + # args == {'values', 'field', 'config'} + return lambda cls, v, values, field, config: validator(cls, v, values=values, field=field, config=config) + + +def _generic_validator_basic(validator: AnyCallable, sig: 'Signature', args: Set[str]) -> 'ValidatorCallable': + has_kwargs = False + if 'kwargs' in args: + has_kwargs = True + args -= {'kwargs'} + + if not args.issubset(all_kwargs): + raise ConfigError( + f'Invalid signature for validator {validator}: {sig}, should be: ' + f'(value, values, config, field), "values", "config" and "field" are all optional.' + ) + + if has_kwargs: + return lambda cls, v, values, field, config: validator(v, values=values, field=field, config=config) + elif args == set(): + return lambda cls, v, values, field, config: validator(v) + elif args == {'values'}: + return lambda cls, v, values, field, config: validator(v, values=values) + elif args == {'field'}: + return lambda cls, v, values, field, config: validator(v, field=field) + elif args == {'config'}: + return lambda cls, v, values, field, config: validator(v, config=config) + elif args == {'values', 'field'}: + return lambda cls, v, values, field, config: validator(v, values=values, field=field) + elif args == {'values', 'config'}: + return lambda cls, v, values, field, config: validator(v, values=values, config=config) + elif args == {'field', 'config'}: + return lambda cls, v, values, field, config: validator(v, field=field, config=config) + else: + # args == {'values', 'field', 'config'} + return lambda cls, v, values, field, config: validator(v, values=values, field=field, config=config) + + +def gather_all_validators(type_: 'ModelOrDc') -> Dict[str, 'AnyClassMethod']: + all_attributes = ChainMap(*[cls.__dict__ for cls in type_.__mro__]) # type: ignore[arg-type,var-annotated] + return { + k: v + for k, v in all_attributes.items() + if hasattr(v, VALIDATOR_CONFIG_KEY) or hasattr(v, ROOT_VALIDATOR_CONFIG_KEY) + } diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/color.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/color.py new file mode 100644 index 0000000..a61d352 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/color.py @@ -0,0 +1,494 @@ +""" +Color definitions are used as per CSS3 specification: +http://www.w3.org/TR/css3-color/#svg-color + +A few colors have multiple names referring to the sames colors, eg. `grey` and `gray` or `aqua` and `cyan`. + +In these cases the LAST color when sorted alphabetically takes preferences, +eg. Color((0, 255, 255)).as_named() == 'cyan' because "cyan" comes after "aqua". +""" +import math +import re +from colorsys import hls_to_rgb, rgb_to_hls +from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple, Union, cast + +from pydantic.errors import ColorError +from pydantic.utils import Representation, almost_equal_floats + +if TYPE_CHECKING: + from pydantic.typing import CallableGenerator, ReprArgs + +ColorTuple = Union[Tuple[int, int, int], Tuple[int, int, int, float]] +ColorType = Union[ColorTuple, str] +HslColorTuple = Union[Tuple[float, float, float], Tuple[float, float, float, float]] + + +class RGBA: + """ + Internal use only as a representation of a color. + """ + + __slots__ = 'r', 'g', 'b', 'alpha', '_tuple' + + def __init__(self, r: float, g: float, b: float, alpha: Optional[float]): + self.r = r + self.g = g + self.b = b + self.alpha = alpha + + self._tuple: Tuple[float, float, float, Optional[float]] = (r, g, b, alpha) + + def __getitem__(self, item: Any) -> Any: + return self._tuple[item] + + +# these are not compiled here to avoid import slowdown, they'll be compiled the first time they're used, then cached +r_hex_short = r'\s*(?:#|0x)?([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])?\s*' +r_hex_long = r'\s*(?:#|0x)?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})?\s*' +_r_255 = r'(\d{1,3}(?:\.\d+)?)' +_r_comma = r'\s*,\s*' +r_rgb = fr'\s*rgb\(\s*{_r_255}{_r_comma}{_r_255}{_r_comma}{_r_255}\)\s*' +_r_alpha = r'(\d(?:\.\d+)?|\.\d+|\d{1,2}%)' +r_rgba = fr'\s*rgba\(\s*{_r_255}{_r_comma}{_r_255}{_r_comma}{_r_255}{_r_comma}{_r_alpha}\s*\)\s*' +_r_h = r'(-?\d+(?:\.\d+)?|-?\.\d+)(deg|rad|turn)?' +_r_sl = r'(\d{1,3}(?:\.\d+)?)%' +r_hsl = fr'\s*hsl\(\s*{_r_h}{_r_comma}{_r_sl}{_r_comma}{_r_sl}\s*\)\s*' +r_hsla = fr'\s*hsl\(\s*{_r_h}{_r_comma}{_r_sl}{_r_comma}{_r_sl}{_r_comma}{_r_alpha}\s*\)\s*' + +# colors where the two hex characters are the same, if all colors match this the short version of hex colors can be used +repeat_colors = {int(c * 2, 16) for c in '0123456789abcdef'} +rads = 2 * math.pi + + +class Color(Representation): + __slots__ = '_original', '_rgba' + + def __init__(self, value: ColorType) -> None: + self._rgba: RGBA + self._original: ColorType + if isinstance(value, (tuple, list)): + self._rgba = parse_tuple(value) + elif isinstance(value, str): + self._rgba = parse_str(value) + elif isinstance(value, Color): + self._rgba = value._rgba + value = value._original + else: + raise ColorError(reason='value must be a tuple, list or string') + + # if we've got here value must be a valid color + self._original = value + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update(type='string', format='color') + + def original(self) -> ColorType: + """ + Original value passed to Color + """ + return self._original + + def as_named(self, *, fallback: bool = False) -> str: + if self._rgba.alpha is None: + rgb = cast(Tuple[int, int, int], self.as_rgb_tuple()) + try: + return COLORS_BY_VALUE[rgb] + except KeyError as e: + if fallback: + return self.as_hex() + else: + raise ValueError('no named color found, use fallback=True, as_hex() or as_rgb()') from e + else: + return self.as_hex() + + def as_hex(self) -> str: + """ + Hex string representing the color can be 3, 4, 6 or 8 characters depending on whether the string + a "short" representation of the color is possible and whether there's an alpha channel. + """ + values = [float_to_255(c) for c in self._rgba[:3]] + if self._rgba.alpha is not None: + values.append(float_to_255(self._rgba.alpha)) + + as_hex = ''.join(f'{v:02x}' for v in values) + if all(c in repeat_colors for c in values): + as_hex = ''.join(as_hex[c] for c in range(0, len(as_hex), 2)) + return '#' + as_hex + + def as_rgb(self) -> str: + """ + Color as an rgb(, , ) or rgba(, , , ) string. + """ + if self._rgba.alpha is None: + return f'rgb({float_to_255(self._rgba.r)}, {float_to_255(self._rgba.g)}, {float_to_255(self._rgba.b)})' + else: + return ( + f'rgba({float_to_255(self._rgba.r)}, {float_to_255(self._rgba.g)}, {float_to_255(self._rgba.b)}, ' + f'{round(self._alpha_float(), 2)})' + ) + + def as_rgb_tuple(self, *, alpha: Optional[bool] = None) -> ColorTuple: + """ + Color as an RGB or RGBA tuple; red, green and blue are in the range 0 to 255, alpha if included is + in the range 0 to 1. + + :param alpha: whether to include the alpha channel, options are + None - (default) include alpha only if it's set (e.g. not None) + True - always include alpha, + False - always omit alpha, + """ + r, g, b = (float_to_255(c) for c in self._rgba[:3]) + if alpha is None: + if self._rgba.alpha is None: + return r, g, b + else: + return r, g, b, self._alpha_float() + elif alpha: + return r, g, b, self._alpha_float() + else: + # alpha is False + return r, g, b + + def as_hsl(self) -> str: + """ + Color as an hsl(, , ) or hsl(, , , ) string. + """ + if self._rgba.alpha is None: + h, s, li = self.as_hsl_tuple(alpha=False) # type: ignore + return f'hsl({h * 360:0.0f}, {s:0.0%}, {li:0.0%})' + else: + h, s, li, a = self.as_hsl_tuple(alpha=True) # type: ignore + return f'hsl({h * 360:0.0f}, {s:0.0%}, {li:0.0%}, {round(a, 2)})' + + def as_hsl_tuple(self, *, alpha: Optional[bool] = None) -> HslColorTuple: + """ + Color as an HSL or HSLA tuple, e.g. hue, saturation, lightness and optionally alpha; all elements are in + the range 0 to 1. + + NOTE: this is HSL as used in HTML and most other places, not HLS as used in python's colorsys. + + :param alpha: whether to include the alpha channel, options are + None - (default) include alpha only if it's set (e.g. not None) + True - always include alpha, + False - always omit alpha, + """ + h, l, s = rgb_to_hls(self._rgba.r, self._rgba.g, self._rgba.b) + if alpha is None: + if self._rgba.alpha is None: + return h, s, l + else: + return h, s, l, self._alpha_float() + if alpha: + return h, s, l, self._alpha_float() + else: + # alpha is False + return h, s, l + + def _alpha_float(self) -> float: + return 1 if self._rgba.alpha is None else self._rgba.alpha + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls + + def __str__(self) -> str: + return self.as_named(fallback=True) + + def __repr_args__(self) -> 'ReprArgs': + return [(None, self.as_named(fallback=True))] + [('rgb', self.as_rgb_tuple())] # type: ignore + + def __eq__(self, other: Any) -> bool: + return isinstance(other, Color) and self.as_rgb_tuple() == other.as_rgb_tuple() + + def __hash__(self) -> int: + return hash(self.as_rgb_tuple()) + + +def parse_tuple(value: Tuple[Any, ...]) -> RGBA: + """ + Parse a tuple or list as a color. + """ + if len(value) == 3: + r, g, b = (parse_color_value(v) for v in value) + return RGBA(r, g, b, None) + elif len(value) == 4: + r, g, b = (parse_color_value(v) for v in value[:3]) + return RGBA(r, g, b, parse_float_alpha(value[3])) + else: + raise ColorError(reason='tuples must have length 3 or 4') + + +def parse_str(value: str) -> RGBA: + """ + Parse a string to an RGBA tuple, trying the following formats (in this order): + * named color, see COLORS_BY_NAME below + * hex short eg. `fff` (prefix can be `#`, `0x` or nothing) + * hex long eg. `ffffff` (prefix can be `#`, `0x` or nothing) + * `rgb(, , ) ` + * `rgba(, , , )` + """ + value_lower = value.lower() + try: + r, g, b = COLORS_BY_NAME[value_lower] + except KeyError: + pass + else: + return ints_to_rgba(r, g, b, None) + + m = re.fullmatch(r_hex_short, value_lower) + if m: + *rgb, a = m.groups() + r, g, b = (int(v * 2, 16) for v in rgb) + if a: + alpha: Optional[float] = int(a * 2, 16) / 255 + else: + alpha = None + return ints_to_rgba(r, g, b, alpha) + + m = re.fullmatch(r_hex_long, value_lower) + if m: + *rgb, a = m.groups() + r, g, b = (int(v, 16) for v in rgb) + if a: + alpha = int(a, 16) / 255 + else: + alpha = None + return ints_to_rgba(r, g, b, alpha) + + m = re.fullmatch(r_rgb, value_lower) + if m: + return ints_to_rgba(*m.groups(), None) # type: ignore + + m = re.fullmatch(r_rgba, value_lower) + if m: + return ints_to_rgba(*m.groups()) # type: ignore + + m = re.fullmatch(r_hsl, value_lower) + if m: + h, h_units, s, l_ = m.groups() + return parse_hsl(h, h_units, s, l_) + + m = re.fullmatch(r_hsla, value_lower) + if m: + h, h_units, s, l_, a = m.groups() + return parse_hsl(h, h_units, s, l_, parse_float_alpha(a)) + + raise ColorError(reason='string not recognised as a valid color') + + +def ints_to_rgba(r: Union[int, str], g: Union[int, str], b: Union[int, str], alpha: Optional[float]) -> RGBA: + return RGBA(parse_color_value(r), parse_color_value(g), parse_color_value(b), parse_float_alpha(alpha)) + + +def parse_color_value(value: Union[int, str], max_val: int = 255) -> float: + """ + Parse a value checking it's a valid int in the range 0 to max_val and divide by max_val to give a number + in the range 0 to 1 + """ + try: + color = float(value) + except ValueError: + raise ColorError(reason='color values must be a valid number') + if 0 <= color <= max_val: + return color / max_val + else: + raise ColorError(reason=f'color values must be in the range 0 to {max_val}') + + +def parse_float_alpha(value: Union[None, str, float, int]) -> Optional[float]: + """ + Parse a value checking it's a valid float in the range 0 to 1 + """ + if value is None: + return None + try: + if isinstance(value, str) and value.endswith('%'): + alpha = float(value[:-1]) / 100 + else: + alpha = float(value) + except ValueError: + raise ColorError(reason='alpha values must be a valid float') + + if almost_equal_floats(alpha, 1): + return None + elif 0 <= alpha <= 1: + return alpha + else: + raise ColorError(reason='alpha values must be in the range 0 to 1') + + +def parse_hsl(h: str, h_units: str, sat: str, light: str, alpha: Optional[float] = None) -> RGBA: + """ + Parse raw hue, saturation, lightness and alpha values and convert to RGBA. + """ + s_value, l_value = parse_color_value(sat, 100), parse_color_value(light, 100) + + h_value = float(h) + if h_units in {None, 'deg'}: + h_value = h_value % 360 / 360 + elif h_units == 'rad': + h_value = h_value % rads / rads + else: + # turns + h_value = h_value % 1 + + r, g, b = hls_to_rgb(h_value, l_value, s_value) + return RGBA(r, g, b, alpha) + + +def float_to_255(c: float) -> int: + return int(round(c * 255)) + + +COLORS_BY_NAME = { + 'aliceblue': (240, 248, 255), + 'antiquewhite': (250, 235, 215), + 'aqua': (0, 255, 255), + 'aquamarine': (127, 255, 212), + 'azure': (240, 255, 255), + 'beige': (245, 245, 220), + 'bisque': (255, 228, 196), + 'black': (0, 0, 0), + 'blanchedalmond': (255, 235, 205), + 'blue': (0, 0, 255), + 'blueviolet': (138, 43, 226), + 'brown': (165, 42, 42), + 'burlywood': (222, 184, 135), + 'cadetblue': (95, 158, 160), + 'chartreuse': (127, 255, 0), + 'chocolate': (210, 105, 30), + 'coral': (255, 127, 80), + 'cornflowerblue': (100, 149, 237), + 'cornsilk': (255, 248, 220), + 'crimson': (220, 20, 60), + 'cyan': (0, 255, 255), + 'darkblue': (0, 0, 139), + 'darkcyan': (0, 139, 139), + 'darkgoldenrod': (184, 134, 11), + 'darkgray': (169, 169, 169), + 'darkgreen': (0, 100, 0), + 'darkgrey': (169, 169, 169), + 'darkkhaki': (189, 183, 107), + 'darkmagenta': (139, 0, 139), + 'darkolivegreen': (85, 107, 47), + 'darkorange': (255, 140, 0), + 'darkorchid': (153, 50, 204), + 'darkred': (139, 0, 0), + 'darksalmon': (233, 150, 122), + 'darkseagreen': (143, 188, 143), + 'darkslateblue': (72, 61, 139), + 'darkslategray': (47, 79, 79), + 'darkslategrey': (47, 79, 79), + 'darkturquoise': (0, 206, 209), + 'darkviolet': (148, 0, 211), + 'deeppink': (255, 20, 147), + 'deepskyblue': (0, 191, 255), + 'dimgray': (105, 105, 105), + 'dimgrey': (105, 105, 105), + 'dodgerblue': (30, 144, 255), + 'firebrick': (178, 34, 34), + 'floralwhite': (255, 250, 240), + 'forestgreen': (34, 139, 34), + 'fuchsia': (255, 0, 255), + 'gainsboro': (220, 220, 220), + 'ghostwhite': (248, 248, 255), + 'gold': (255, 215, 0), + 'goldenrod': (218, 165, 32), + 'gray': (128, 128, 128), + 'green': (0, 128, 0), + 'greenyellow': (173, 255, 47), + 'grey': (128, 128, 128), + 'honeydew': (240, 255, 240), + 'hotpink': (255, 105, 180), + 'indianred': (205, 92, 92), + 'indigo': (75, 0, 130), + 'ivory': (255, 255, 240), + 'khaki': (240, 230, 140), + 'lavender': (230, 230, 250), + 'lavenderblush': (255, 240, 245), + 'lawngreen': (124, 252, 0), + 'lemonchiffon': (255, 250, 205), + 'lightblue': (173, 216, 230), + 'lightcoral': (240, 128, 128), + 'lightcyan': (224, 255, 255), + 'lightgoldenrodyellow': (250, 250, 210), + 'lightgray': (211, 211, 211), + 'lightgreen': (144, 238, 144), + 'lightgrey': (211, 211, 211), + 'lightpink': (255, 182, 193), + 'lightsalmon': (255, 160, 122), + 'lightseagreen': (32, 178, 170), + 'lightskyblue': (135, 206, 250), + 'lightslategray': (119, 136, 153), + 'lightslategrey': (119, 136, 153), + 'lightsteelblue': (176, 196, 222), + 'lightyellow': (255, 255, 224), + 'lime': (0, 255, 0), + 'limegreen': (50, 205, 50), + 'linen': (250, 240, 230), + 'magenta': (255, 0, 255), + 'maroon': (128, 0, 0), + 'mediumaquamarine': (102, 205, 170), + 'mediumblue': (0, 0, 205), + 'mediumorchid': (186, 85, 211), + 'mediumpurple': (147, 112, 219), + 'mediumseagreen': (60, 179, 113), + 'mediumslateblue': (123, 104, 238), + 'mediumspringgreen': (0, 250, 154), + 'mediumturquoise': (72, 209, 204), + 'mediumvioletred': (199, 21, 133), + 'midnightblue': (25, 25, 112), + 'mintcream': (245, 255, 250), + 'mistyrose': (255, 228, 225), + 'moccasin': (255, 228, 181), + 'navajowhite': (255, 222, 173), + 'navy': (0, 0, 128), + 'oldlace': (253, 245, 230), + 'olive': (128, 128, 0), + 'olivedrab': (107, 142, 35), + 'orange': (255, 165, 0), + 'orangered': (255, 69, 0), + 'orchid': (218, 112, 214), + 'palegoldenrod': (238, 232, 170), + 'palegreen': (152, 251, 152), + 'paleturquoise': (175, 238, 238), + 'palevioletred': (219, 112, 147), + 'papayawhip': (255, 239, 213), + 'peachpuff': (255, 218, 185), + 'peru': (205, 133, 63), + 'pink': (255, 192, 203), + 'plum': (221, 160, 221), + 'powderblue': (176, 224, 230), + 'purple': (128, 0, 128), + 'red': (255, 0, 0), + 'rosybrown': (188, 143, 143), + 'royalblue': (65, 105, 225), + 'saddlebrown': (139, 69, 19), + 'salmon': (250, 128, 114), + 'sandybrown': (244, 164, 96), + 'seagreen': (46, 139, 87), + 'seashell': (255, 245, 238), + 'sienna': (160, 82, 45), + 'silver': (192, 192, 192), + 'skyblue': (135, 206, 235), + 'slateblue': (106, 90, 205), + 'slategray': (112, 128, 144), + 'slategrey': (112, 128, 144), + 'snow': (255, 250, 250), + 'springgreen': (0, 255, 127), + 'steelblue': (70, 130, 180), + 'tan': (210, 180, 140), + 'teal': (0, 128, 128), + 'thistle': (216, 191, 216), + 'tomato': (255, 99, 71), + 'turquoise': (64, 224, 208), + 'violet': (238, 130, 238), + 'wheat': (245, 222, 179), + 'white': (255, 255, 255), + 'whitesmoke': (245, 245, 245), + 'yellow': (255, 255, 0), + 'yellowgreen': (154, 205, 50), +} + +COLORS_BY_VALUE = {v: k for k, v in COLORS_BY_NAME.items()} diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/config.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/config.py new file mode 100644 index 0000000..907faff --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/config.py @@ -0,0 +1,191 @@ +import json +from enum import Enum +from typing import TYPE_CHECKING, Any, Callable, Dict, ForwardRef, Optional, Tuple, Type, Union + +from typing_extensions import Literal, Protocol + +from pydantic.typing import AnyArgTCallable, AnyCallable +from pydantic.utils import GetterDict +from pydantic.version import compiled + +if TYPE_CHECKING: + from typing import overload + + from pydantic.fields import ModelField + from pydantic.main import BaseModel + + ConfigType = Type['BaseConfig'] + + class SchemaExtraCallable(Protocol): + @overload + def __call__(self, schema: Dict[str, Any]) -> None: + pass + + @overload + def __call__(self, schema: Dict[str, Any], model_class: Type[BaseModel]) -> None: + pass + +else: + SchemaExtraCallable = Callable[..., None] + +__all__ = 'BaseConfig', 'ConfigDict', 'get_config', 'Extra', 'inherit_config', 'prepare_config' + + +class Extra(str, Enum): + allow = 'allow' + ignore = 'ignore' + forbid = 'forbid' + + +# https://github.com/cython/cython/issues/4003 +# Fixed in Cython 3 and Pydantic v1 won't support Cython 3. +# Pydantic v2 doesn't depend on Cython at all. +if not compiled: + from typing_extensions import TypedDict + + class ConfigDict(TypedDict, total=False): + title: Optional[str] + anystr_lower: bool + anystr_strip_whitespace: bool + min_anystr_length: int + max_anystr_length: Optional[int] + validate_all: bool + extra: Extra + allow_mutation: bool + frozen: bool + allow_population_by_field_name: bool + use_enum_values: bool + fields: Dict[str, Union[str, Dict[str, str]]] + validate_assignment: bool + error_msg_templates: Dict[str, str] + arbitrary_types_allowed: bool + orm_mode: bool + getter_dict: Type[GetterDict] + alias_generator: Optional[Callable[[str], str]] + keep_untouched: Tuple[type, ...] + schema_extra: Union[Dict[str, object], 'SchemaExtraCallable'] + json_loads: Callable[[str], object] + json_dumps: AnyArgTCallable[str] + json_encoders: Dict[Type[object], AnyCallable] + underscore_attrs_are_private: bool + allow_inf_nan: bool + copy_on_model_validation: Literal['none', 'deep', 'shallow'] + # whether dataclass `__post_init__` should be run after validation + post_init_call: Literal['before_validation', 'after_validation'] + +else: + ConfigDict = dict # type: ignore + + +class BaseConfig: + title: Optional[str] = None + anystr_lower: bool = False + anystr_upper: bool = False + anystr_strip_whitespace: bool = False + min_anystr_length: int = 0 + max_anystr_length: Optional[int] = None + validate_all: bool = False + extra: Extra = Extra.ignore + allow_mutation: bool = True + frozen: bool = False + allow_population_by_field_name: bool = False + use_enum_values: bool = False + fields: Dict[str, Union[str, Dict[str, str]]] = {} + validate_assignment: bool = False + error_msg_templates: Dict[str, str] = {} + arbitrary_types_allowed: bool = False + orm_mode: bool = False + getter_dict: Type[GetterDict] = GetterDict + alias_generator: Optional[Callable[[str], str]] = None + keep_untouched: Tuple[type, ...] = () + schema_extra: Union[Dict[str, Any], 'SchemaExtraCallable'] = {} + json_loads: Callable[[str], Any] = json.loads + json_dumps: Callable[..., str] = json.dumps + json_encoders: Dict[Union[Type[Any], str, ForwardRef], AnyCallable] = {} + underscore_attrs_are_private: bool = False + allow_inf_nan: bool = True + + # whether inherited models as fields should be reconstructed as base model, + # and whether such a copy should be shallow or deep + copy_on_model_validation: Literal['none', 'deep', 'shallow'] = 'shallow' + + # whether `Union` should check all allowed types before even trying to coerce + smart_union: bool = False + # whether dataclass `__post_init__` should be run before or after validation + post_init_call: Literal['before_validation', 'after_validation'] = 'before_validation' + + @classmethod + def get_field_info(cls, name: str) -> Dict[str, Any]: + """ + Get properties of FieldInfo from the `fields` property of the config class. + """ + + fields_value = cls.fields.get(name) + + if isinstance(fields_value, str): + field_info: Dict[str, Any] = {'alias': fields_value} + elif isinstance(fields_value, dict): + field_info = fields_value + else: + field_info = {} + + if 'alias' in field_info: + field_info.setdefault('alias_priority', 2) + + if field_info.get('alias_priority', 0) <= 1 and cls.alias_generator: + alias = cls.alias_generator(name) + if not isinstance(alias, str): + raise TypeError(f'Config.alias_generator must return str, not {alias.__class__}') + field_info.update(alias=alias, alias_priority=1) + return field_info + + @classmethod + def prepare_field(cls, field: 'ModelField') -> None: + """ + Optional hook to check or modify fields during model creation. + """ + pass + + +def get_config(config: Union[ConfigDict, Type[object], None]) -> Type[BaseConfig]: + if config is None: + return BaseConfig + + else: + config_dict = ( + config + if isinstance(config, dict) + else {k: getattr(config, k) for k in dir(config) if not k.startswith('__')} + ) + + class Config(BaseConfig): + ... + + for k, v in config_dict.items(): + setattr(Config, k, v) + return Config + + +def inherit_config(self_config: 'ConfigType', parent_config: 'ConfigType', **namespace: Any) -> 'ConfigType': + if not self_config: + base_classes: Tuple['ConfigType', ...] = (parent_config,) + elif self_config == parent_config: + base_classes = (self_config,) + else: + base_classes = self_config, parent_config + + namespace['json_encoders'] = { + **getattr(parent_config, 'json_encoders', {}), + **getattr(self_config, 'json_encoders', {}), + **namespace.get('json_encoders', {}), + } + + return type('Config', base_classes, namespace) + + +def prepare_config(config: Type[BaseConfig], cls_name: str) -> None: + if not isinstance(config.extra, Extra): + try: + config.extra = Extra(config.extra) + except ValueError: + raise ValueError(f'"{cls_name}": {config.extra} is not a valid value for "extra"') diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/dataclasses.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/dataclasses.py new file mode 100644 index 0000000..600fb54 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/dataclasses.py @@ -0,0 +1,500 @@ +""" +The main purpose is to enhance stdlib dataclasses by adding validation +A pydantic dataclass can be generated from scratch or from a stdlib one. + +Behind the scene, a pydantic dataclass is just like a regular one on which we attach +a `BaseModel` and magic methods to trigger the validation of the data. +`__init__` and `__post_init__` are hence overridden and have extra logic to be +able to validate input data. + +When a pydantic dataclass is generated from scratch, it's just a plain dataclass +with validation triggered at initialization + +The tricky part if for stdlib dataclasses that are converted after into pydantic ones e.g. + +```py +@dataclasses.dataclass +class M: + x: int + +ValidatedM = pydantic.dataclasses.dataclass(M) +``` + +We indeed still want to support equality, hashing, repr, ... as if it was the stdlib one! + +```py +assert isinstance(ValidatedM(x=1), M) +assert ValidatedM(x=1) == M(x=1) +``` + +This means we **don't want to create a new dataclass that inherits from it** +The trick is to create a wrapper around `M` that will act as a proxy to trigger +validation without altering default `M` behaviour. +""" +import copy +import dataclasses +import sys +from contextlib import contextmanager +from functools import wraps + +try: + from functools import cached_property +except ImportError: + # cached_property available only for python3.8+ + pass + +from typing import TYPE_CHECKING, Any, Callable, ClassVar, Dict, Generator, Optional, Type, TypeVar, Union, overload + +from typing_extensions import dataclass_transform + +from pydantic.class_validators import gather_all_validators +from pydantic.config import BaseConfig, ConfigDict, Extra, get_config +from pydantic.error_wrappers import ValidationError +from pydantic.errors import DataclassTypeError +from pydantic.fields import Field, FieldInfo, Required, Undefined +from pydantic.main import create_model, validate_model +from pydantic.utils import ClassAttribute + +if TYPE_CHECKING: + from pydantic.main import BaseModel + from pydantic.typing import CallableGenerator, NoArgAnyCallable + + DataclassT = TypeVar('DataclassT', bound='Dataclass') + + DataclassClassOrWrapper = Union[Type['Dataclass'], 'DataclassProxy'] + + class Dataclass: + # stdlib attributes + __dataclass_fields__: ClassVar[Dict[str, Any]] + __dataclass_params__: ClassVar[Any] # in reality `dataclasses._DataclassParams` + __post_init__: ClassVar[Callable[..., None]] + + # Added by pydantic + __pydantic_run_validation__: ClassVar[bool] + __post_init_post_parse__: ClassVar[Callable[..., None]] + __pydantic_initialised__: ClassVar[bool] + __pydantic_model__: ClassVar[Type[BaseModel]] + __pydantic_validate_values__: ClassVar[Callable[['Dataclass'], None]] + __pydantic_has_field_info_default__: ClassVar[bool] # whether a `pydantic.Field` is used as default value + + def __init__(self, *args: object, **kwargs: object) -> None: + pass + + @classmethod + def __get_validators__(cls: Type['Dataclass']) -> 'CallableGenerator': + pass + + @classmethod + def __validate__(cls: Type['DataclassT'], v: Any) -> 'DataclassT': + pass + + +__all__ = [ + 'dataclass', + 'set_validation', + 'create_pydantic_model_from_dataclass', + 'is_builtin_dataclass', + 'make_dataclass_validator', +] + +_T = TypeVar('_T') + +if sys.version_info >= (3, 10): + + @dataclass_transform(field_specifiers=(dataclasses.field, Field)) + @overload + def dataclass( + *, + init: bool = True, + repr: bool = True, + eq: bool = True, + order: bool = False, + unsafe_hash: bool = False, + frozen: bool = False, + config: Union[ConfigDict, Type[object], None] = None, + validate_on_init: Optional[bool] = None, + use_proxy: Optional[bool] = None, + kw_only: bool = ..., + ) -> Callable[[Type[_T]], 'DataclassClassOrWrapper']: + ... + + @dataclass_transform(field_specifiers=(dataclasses.field, Field)) + @overload + def dataclass( + _cls: Type[_T], + *, + init: bool = True, + repr: bool = True, + eq: bool = True, + order: bool = False, + unsafe_hash: bool = False, + frozen: bool = False, + config: Union[ConfigDict, Type[object], None] = None, + validate_on_init: Optional[bool] = None, + use_proxy: Optional[bool] = None, + kw_only: bool = ..., + ) -> 'DataclassClassOrWrapper': + ... + +else: + + @dataclass_transform(field_specifiers=(dataclasses.field, Field)) + @overload + def dataclass( + *, + init: bool = True, + repr: bool = True, + eq: bool = True, + order: bool = False, + unsafe_hash: bool = False, + frozen: bool = False, + config: Union[ConfigDict, Type[object], None] = None, + validate_on_init: Optional[bool] = None, + use_proxy: Optional[bool] = None, + ) -> Callable[[Type[_T]], 'DataclassClassOrWrapper']: + ... + + @dataclass_transform(field_specifiers=(dataclasses.field, Field)) + @overload + def dataclass( + _cls: Type[_T], + *, + init: bool = True, + repr: bool = True, + eq: bool = True, + order: bool = False, + unsafe_hash: bool = False, + frozen: bool = False, + config: Union[ConfigDict, Type[object], None] = None, + validate_on_init: Optional[bool] = None, + use_proxy: Optional[bool] = None, + ) -> 'DataclassClassOrWrapper': + ... + + +@dataclass_transform(field_specifiers=(dataclasses.field, Field)) +def dataclass( + _cls: Optional[Type[_T]] = None, + *, + init: bool = True, + repr: bool = True, + eq: bool = True, + order: bool = False, + unsafe_hash: bool = False, + frozen: bool = False, + config: Union[ConfigDict, Type[object], None] = None, + validate_on_init: Optional[bool] = None, + use_proxy: Optional[bool] = None, + kw_only: bool = False, +) -> Union[Callable[[Type[_T]], 'DataclassClassOrWrapper'], 'DataclassClassOrWrapper']: + """ + Like the python standard lib dataclasses but with type validation. + The result is either a pydantic dataclass that will validate input data + or a wrapper that will trigger validation around a stdlib dataclass + to avoid modifying it directly + """ + the_config = get_config(config) + + def wrap(cls: Type[Any]) -> 'DataclassClassOrWrapper': + should_use_proxy = ( + use_proxy + if use_proxy is not None + else ( + is_builtin_dataclass(cls) + and (cls.__bases__[0] is object or set(dir(cls)) == set(dir(cls.__bases__[0]))) + ) + ) + if should_use_proxy: + dc_cls_doc = '' + dc_cls = DataclassProxy(cls) + default_validate_on_init = False + else: + dc_cls_doc = cls.__doc__ or '' # needs to be done before generating dataclass + if sys.version_info >= (3, 10): + dc_cls = dataclasses.dataclass( + cls, + init=init, + repr=repr, + eq=eq, + order=order, + unsafe_hash=unsafe_hash, + frozen=frozen, + kw_only=kw_only, + ) + else: + dc_cls = dataclasses.dataclass( # type: ignore + cls, init=init, repr=repr, eq=eq, order=order, unsafe_hash=unsafe_hash, frozen=frozen + ) + default_validate_on_init = True + + should_validate_on_init = default_validate_on_init if validate_on_init is None else validate_on_init + _add_pydantic_validation_attributes(cls, the_config, should_validate_on_init, dc_cls_doc) + dc_cls.__pydantic_model__.__try_update_forward_refs__(**{cls.__name__: cls}) + return dc_cls + + if _cls is None: + return wrap + + return wrap(_cls) + + +@contextmanager +def set_validation(cls: Type['DataclassT'], value: bool) -> Generator[Type['DataclassT'], None, None]: + original_run_validation = cls.__pydantic_run_validation__ + try: + cls.__pydantic_run_validation__ = value + yield cls + finally: + cls.__pydantic_run_validation__ = original_run_validation + + +class DataclassProxy: + __slots__ = '__dataclass__' + + def __init__(self, dc_cls: Type['Dataclass']) -> None: + object.__setattr__(self, '__dataclass__', dc_cls) + + def __call__(self, *args: Any, **kwargs: Any) -> Any: + with set_validation(self.__dataclass__, True): + return self.__dataclass__(*args, **kwargs) + + def __getattr__(self, name: str) -> Any: + return getattr(self.__dataclass__, name) + + def __setattr__(self, __name: str, __value: Any) -> None: + return setattr(self.__dataclass__, __name, __value) + + def __instancecheck__(self, instance: Any) -> bool: + return isinstance(instance, self.__dataclass__) + + def __copy__(self) -> 'DataclassProxy': + return DataclassProxy(copy.copy(self.__dataclass__)) + + def __deepcopy__(self, memo: Any) -> 'DataclassProxy': + return DataclassProxy(copy.deepcopy(self.__dataclass__, memo)) + + +def _add_pydantic_validation_attributes( # noqa: C901 (ignore complexity) + dc_cls: Type['Dataclass'], + config: Type[BaseConfig], + validate_on_init: bool, + dc_cls_doc: str, +) -> None: + """ + We need to replace the right method. If no `__post_init__` has been set in the stdlib dataclass + it won't even exist (code is generated on the fly by `dataclasses`) + By default, we run validation after `__init__` or `__post_init__` if defined + """ + init = dc_cls.__init__ + + @wraps(init) + def handle_extra_init(self: 'Dataclass', *args: Any, **kwargs: Any) -> None: + if config.extra == Extra.ignore: + init(self, *args, **{k: v for k, v in kwargs.items() if k in self.__dataclass_fields__}) + + elif config.extra == Extra.allow: + for k, v in kwargs.items(): + self.__dict__.setdefault(k, v) + init(self, *args, **{k: v for k, v in kwargs.items() if k in self.__dataclass_fields__}) + + else: + init(self, *args, **kwargs) + + if hasattr(dc_cls, '__post_init__'): + try: + post_init = dc_cls.__post_init__.__wrapped__ # type: ignore[attr-defined] + except AttributeError: + post_init = dc_cls.__post_init__ + + @wraps(post_init) + def new_post_init(self: 'Dataclass', *args: Any, **kwargs: Any) -> None: + if config.post_init_call == 'before_validation': + post_init(self, *args, **kwargs) + + if self.__class__.__pydantic_run_validation__: + self.__pydantic_validate_values__() + if hasattr(self, '__post_init_post_parse__'): + self.__post_init_post_parse__(*args, **kwargs) + + if config.post_init_call == 'after_validation': + post_init(self, *args, **kwargs) + + setattr(dc_cls, '__init__', handle_extra_init) + setattr(dc_cls, '__post_init__', new_post_init) + + else: + + @wraps(init) + def new_init(self: 'Dataclass', *args: Any, **kwargs: Any) -> None: + handle_extra_init(self, *args, **kwargs) + + if self.__class__.__pydantic_run_validation__: + self.__pydantic_validate_values__() + + if hasattr(self, '__post_init_post_parse__'): + # We need to find again the initvars. To do that we use `__dataclass_fields__` instead of + # public method `dataclasses.fields` + + # get all initvars and their default values + initvars_and_values: Dict[str, Any] = {} + for i, f in enumerate(self.__class__.__dataclass_fields__.values()): + if f._field_type is dataclasses._FIELD_INITVAR: # type: ignore[attr-defined] + try: + # set arg value by default + initvars_and_values[f.name] = args[i] + except IndexError: + initvars_and_values[f.name] = kwargs.get(f.name, f.default) + + self.__post_init_post_parse__(**initvars_and_values) + + setattr(dc_cls, '__init__', new_init) + + setattr(dc_cls, '__pydantic_run_validation__', ClassAttribute('__pydantic_run_validation__', validate_on_init)) + setattr(dc_cls, '__pydantic_initialised__', False) + setattr(dc_cls, '__pydantic_model__', create_pydantic_model_from_dataclass(dc_cls, config, dc_cls_doc)) + setattr(dc_cls, '__pydantic_validate_values__', _dataclass_validate_values) + setattr(dc_cls, '__validate__', classmethod(_validate_dataclass)) + setattr(dc_cls, '__get_validators__', classmethod(_get_validators)) + + if dc_cls.__pydantic_model__.__config__.validate_assignment and not dc_cls.__dataclass_params__.frozen: + setattr(dc_cls, '__setattr__', _dataclass_validate_assignment_setattr) + + +def _get_validators(cls: 'DataclassClassOrWrapper') -> 'CallableGenerator': + yield cls.__validate__ + + +def _validate_dataclass(cls: Type['DataclassT'], v: Any) -> 'DataclassT': + with set_validation(cls, True): + if isinstance(v, cls): + v.__pydantic_validate_values__() + return v + elif isinstance(v, (list, tuple)): + return cls(*v) + elif isinstance(v, dict): + return cls(**v) + else: + raise DataclassTypeError(class_name=cls.__name__) + + +def create_pydantic_model_from_dataclass( + dc_cls: Type['Dataclass'], + config: Type[Any] = BaseConfig, + dc_cls_doc: Optional[str] = None, +) -> Type['BaseModel']: + field_definitions: Dict[str, Any] = {} + for field in dataclasses.fields(dc_cls): + default: Any = Undefined + default_factory: Optional['NoArgAnyCallable'] = None + field_info: FieldInfo + + if field.default is not dataclasses.MISSING: + default = field.default + elif field.default_factory is not dataclasses.MISSING: + default_factory = field.default_factory + else: + default = Required + + if isinstance(default, FieldInfo): + field_info = default + dc_cls.__pydantic_has_field_info_default__ = True + else: + field_info = Field(default=default, default_factory=default_factory, **field.metadata) + + field_definitions[field.name] = (field.type, field_info) + + validators = gather_all_validators(dc_cls) + model: Type['BaseModel'] = create_model( + dc_cls.__name__, + __config__=config, + __module__=dc_cls.__module__, + __validators__=validators, + __cls_kwargs__={'__resolve_forward_refs__': False}, + **field_definitions, + ) + model.__doc__ = dc_cls_doc if dc_cls_doc is not None else dc_cls.__doc__ or '' + return model + + +if sys.version_info >= (3, 8): + + def _is_field_cached_property(obj: 'Dataclass', k: str) -> bool: + return isinstance(getattr(type(obj), k, None), cached_property) + +else: + + def _is_field_cached_property(obj: 'Dataclass', k: str) -> bool: + return False + + +def _dataclass_validate_values(self: 'Dataclass') -> None: + # validation errors can occur if this function is called twice on an already initialised dataclass. + # for example if Extra.forbid is enabled, it would consider __pydantic_initialised__ an invalid extra property + if getattr(self, '__pydantic_initialised__'): + return + if getattr(self, '__pydantic_has_field_info_default__', False): + # We need to remove `FieldInfo` values since they are not valid as input + # It's ok to do that because they are obviously the default values! + input_data = { + k: v + for k, v in self.__dict__.items() + if not (isinstance(v, FieldInfo) or _is_field_cached_property(self, k)) + } + else: + input_data = {k: v for k, v in self.__dict__.items() if not _is_field_cached_property(self, k)} + d, _, validation_error = validate_model(self.__pydantic_model__, input_data, cls=self.__class__) + if validation_error: + raise validation_error + self.__dict__.update(d) + object.__setattr__(self, '__pydantic_initialised__', True) + + +def _dataclass_validate_assignment_setattr(self: 'Dataclass', name: str, value: Any) -> None: + if self.__pydantic_initialised__: + d = dict(self.__dict__) + d.pop(name, None) + known_field = self.__pydantic_model__.__fields__.get(name, None) + if known_field: + value, error_ = known_field.validate(value, d, loc=name, cls=self.__class__) + if error_: + raise ValidationError([error_], self.__class__) + + object.__setattr__(self, name, value) + + +def is_builtin_dataclass(_cls: Type[Any]) -> bool: + """ + Whether a class is a stdlib dataclass + (useful to discriminated a pydantic dataclass that is actually a wrapper around a stdlib dataclass) + + we check that + - `_cls` is a dataclass + - `_cls` is not a processed pydantic dataclass (with a basemodel attached) + - `_cls` is not a pydantic dataclass inheriting directly from a stdlib dataclass + e.g. + ``` + @dataclasses.dataclass + class A: + x: int + + @pydantic.dataclasses.dataclass + class B(A): + y: int + ``` + In this case, when we first check `B`, we make an extra check and look at the annotations ('y'), + which won't be a superset of all the dataclass fields (only the stdlib fields i.e. 'x') + """ + return ( + dataclasses.is_dataclass(_cls) + and not hasattr(_cls, '__pydantic_model__') + and set(_cls.__dataclass_fields__).issuperset(set(getattr(_cls, '__annotations__', {}))) + ) + + +def make_dataclass_validator(dc_cls: Type['Dataclass'], config: Type[BaseConfig]) -> 'CallableGenerator': + """ + Create a pydantic.dataclass from a builtin dataclass to add type validation + and yield the validators + It retrieves the parameters of the dataclass and forwards them to the newly created dataclass + """ + yield from _get_validators(dataclass(dc_cls, config=config, use_proxy=True)) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/datetime_parse.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/datetime_parse.py new file mode 100644 index 0000000..fbfbec6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/datetime_parse.py @@ -0,0 +1,248 @@ +""" +Functions to parse datetime objects. + +We're using regular expressions rather than time.strptime because: +- They provide both validation and parsing. +- They're more flexible for datetimes. +- The date/datetime/time constructors produce friendlier error messages. + +Stolen from https://raw.githubusercontent.com/django/django/main/django/utils/dateparse.py at +9718fa2e8abe430c3526a9278dd976443d4ae3c6 + +Changed to: +* use standard python datetime types not django.utils.timezone +* raise ValueError when regex doesn't match rather than returning None +* support parsing unix timestamps for dates and datetimes +""" +import re +from datetime import date, datetime, time, timedelta, timezone +from typing import Dict, Optional, Type, Union + +from pydantic import errors + +date_expr = r'(?P\d{4})-(?P\d{1,2})-(?P\d{1,2})' +time_expr = ( + r'(?P\d{1,2}):(?P\d{1,2})' + r'(?::(?P\d{1,2})(?:\.(?P\d{1,6})\d{0,6})?)?' + r'(?PZ|[+-]\d{2}(?::?\d{2})?)?$' +) + +date_re = re.compile(f'{date_expr}$') +time_re = re.compile(time_expr) +datetime_re = re.compile(f'{date_expr}[T ]{time_expr}') + +standard_duration_re = re.compile( + r'^' + r'(?:(?P-?\d+) (days?, )?)?' + r'((?:(?P-?\d+):)(?=\d+:\d+))?' + r'(?:(?P-?\d+):)?' + r'(?P-?\d+)' + r'(?:\.(?P\d{1,6})\d{0,6})?' + r'$' +) + +# Support the sections of ISO 8601 date representation that are accepted by timedelta +iso8601_duration_re = re.compile( + r'^(?P[-+]?)' + r'P' + r'(?:(?P\d+(.\d+)?)D)?' + r'(?:T' + r'(?:(?P\d+(.\d+)?)H)?' + r'(?:(?P\d+(.\d+)?)M)?' + r'(?:(?P\d+(.\d+)?)S)?' + r')?' + r'$' +) + +EPOCH = datetime(1970, 1, 1) +# if greater than this, the number is in ms, if less than or equal it's in seconds +# (in seconds this is 11th October 2603, in ms it's 20th August 1970) +MS_WATERSHED = int(2e10) +# slightly more than datetime.max in ns - (datetime.max - EPOCH).total_seconds() * 1e9 +MAX_NUMBER = int(3e20) +StrBytesIntFloat = Union[str, bytes, int, float] + + +def get_numeric(value: StrBytesIntFloat, native_expected_type: str) -> Union[None, int, float]: + if isinstance(value, (int, float)): + return value + try: + return float(value) + except ValueError: + return None + except TypeError: + raise TypeError(f'invalid type; expected {native_expected_type}, string, bytes, int or float') + + +def from_unix_seconds(seconds: Union[int, float]) -> datetime: + if seconds > MAX_NUMBER: + return datetime.max + elif seconds < -MAX_NUMBER: + return datetime.min + + while abs(seconds) > MS_WATERSHED: + seconds /= 1000 + dt = EPOCH + timedelta(seconds=seconds) + return dt.replace(tzinfo=timezone.utc) + + +def _parse_timezone(value: Optional[str], error: Type[Exception]) -> Union[None, int, timezone]: + if value == 'Z': + return timezone.utc + elif value is not None: + offset_mins = int(value[-2:]) if len(value) > 3 else 0 + offset = 60 * int(value[1:3]) + offset_mins + if value[0] == '-': + offset = -offset + try: + return timezone(timedelta(minutes=offset)) + except ValueError: + raise error() + else: + return None + + +def parse_date(value: Union[date, StrBytesIntFloat]) -> date: + """ + Parse a date/int/float/string and return a datetime.date. + + Raise ValueError if the input is well formatted but not a valid date. + Raise ValueError if the input isn't well formatted. + """ + if isinstance(value, date): + if isinstance(value, datetime): + return value.date() + else: + return value + + number = get_numeric(value, 'date') + if number is not None: + return from_unix_seconds(number).date() + + if isinstance(value, bytes): + value = value.decode() + + match = date_re.match(value) # type: ignore + if match is None: + raise errors.DateError() + + kw = {k: int(v) for k, v in match.groupdict().items()} + + try: + return date(**kw) + except ValueError: + raise errors.DateError() + + +def parse_time(value: Union[time, StrBytesIntFloat]) -> time: + """ + Parse a time/string and return a datetime.time. + + Raise ValueError if the input is well formatted but not a valid time. + Raise ValueError if the input isn't well formatted, in particular if it contains an offset. + """ + if isinstance(value, time): + return value + + number = get_numeric(value, 'time') + if number is not None: + if number >= 86400: + # doesn't make sense since the time time loop back around to 0 + raise errors.TimeError() + return (datetime.min + timedelta(seconds=number)).time() + + if isinstance(value, bytes): + value = value.decode() + + match = time_re.match(value) # type: ignore + if match is None: + raise errors.TimeError() + + kw = match.groupdict() + if kw['microsecond']: + kw['microsecond'] = kw['microsecond'].ljust(6, '0') + + tzinfo = _parse_timezone(kw.pop('tzinfo'), errors.TimeError) + kw_: Dict[str, Union[None, int, timezone]] = {k: int(v) for k, v in kw.items() if v is not None} + kw_['tzinfo'] = tzinfo + + try: + return time(**kw_) # type: ignore + except ValueError: + raise errors.TimeError() + + +def parse_datetime(value: Union[datetime, StrBytesIntFloat]) -> datetime: + """ + Parse a datetime/int/float/string and return a datetime.datetime. + + This function supports time zone offsets. When the input contains one, + the output uses a timezone with a fixed offset from UTC. + + Raise ValueError if the input is well formatted but not a valid datetime. + Raise ValueError if the input isn't well formatted. + """ + if isinstance(value, datetime): + return value + + number = get_numeric(value, 'datetime') + if number is not None: + return from_unix_seconds(number) + + if isinstance(value, bytes): + value = value.decode() + + match = datetime_re.match(value) # type: ignore + if match is None: + raise errors.DateTimeError() + + kw = match.groupdict() + if kw['microsecond']: + kw['microsecond'] = kw['microsecond'].ljust(6, '0') + + tzinfo = _parse_timezone(kw.pop('tzinfo'), errors.DateTimeError) + kw_: Dict[str, Union[None, int, timezone]] = {k: int(v) for k, v in kw.items() if v is not None} + kw_['tzinfo'] = tzinfo + + try: + return datetime(**kw_) # type: ignore + except ValueError: + raise errors.DateTimeError() + + +def parse_duration(value: StrBytesIntFloat) -> timedelta: + """ + Parse a duration int/float/string and return a datetime.timedelta. + + The preferred format for durations in Django is '%d %H:%M:%S.%f'. + + Also supports ISO 8601 representation. + """ + if isinstance(value, timedelta): + return value + + if isinstance(value, (int, float)): + # below code requires a string + value = f'{value:f}' + elif isinstance(value, bytes): + value = value.decode() + + try: + match = standard_duration_re.match(value) or iso8601_duration_re.match(value) + except TypeError: + raise TypeError('invalid type; expected timedelta, string, bytes, int or float') + + if not match: + raise errors.DurationError() + + kw = match.groupdict() + sign = -1 if kw.pop('sign', '+') == '-' else 1 + if kw.get('microseconds'): + kw['microseconds'] = kw['microseconds'].ljust(6, '0') + + if kw.get('seconds') and kw.get('microseconds') and kw['seconds'].startswith('-'): + kw['microseconds'] = '-' + kw['microseconds'] + + kw_ = {k: float(v) for k, v in kw.items() if v is not None} + + return sign * timedelta(**kw_) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/decorator.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/decorator.py new file mode 100644 index 0000000..e46eb59 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/decorator.py @@ -0,0 +1,264 @@ +from functools import wraps +from typing import TYPE_CHECKING, Any, Callable, Dict, List, Mapping, Optional, Tuple, Type, TypeVar, Union, overload + +from pydantic import validator +from pydantic.config import Extra +from pydantic.errors import ConfigError +from pydantic.main import BaseModel, create_model +from pydantic.typing import get_all_type_hints +from pydantic.utils import to_camel + +__all__ = ('validate_arguments',) + +if TYPE_CHECKING: + from pydantic.typing import AnyCallable + + AnyCallableT = TypeVar('AnyCallableT', bound=AnyCallable) + ConfigType = Union[None, Type[Any], Dict[str, Any]] + + +@overload +def validate_arguments(func: None = None, *, config: 'ConfigType' = None) -> Callable[['AnyCallableT'], 'AnyCallableT']: + ... + + +@overload +def validate_arguments(func: 'AnyCallableT') -> 'AnyCallableT': + ... + + +def validate_arguments(func: Optional['AnyCallableT'] = None, *, config: 'ConfigType' = None) -> Any: + """ + Decorator to validate the arguments passed to a function. + """ + + def validate(_func: 'AnyCallable') -> 'AnyCallable': + vd = ValidatedFunction(_func, config) + + @wraps(_func) + def wrapper_function(*args: Any, **kwargs: Any) -> Any: + return vd.call(*args, **kwargs) + + wrapper_function.vd = vd # type: ignore + wrapper_function.validate = vd.init_model_instance # type: ignore + wrapper_function.raw_function = vd.raw_function # type: ignore + wrapper_function.model = vd.model # type: ignore + return wrapper_function + + if func: + return validate(func) + else: + return validate + + +ALT_V_ARGS = 'v__args' +ALT_V_KWARGS = 'v__kwargs' +V_POSITIONAL_ONLY_NAME = 'v__positional_only' +V_DUPLICATE_KWARGS = 'v__duplicate_kwargs' + + +class ValidatedFunction: + def __init__(self, function: 'AnyCallableT', config: 'ConfigType'): # noqa C901 + from inspect import Parameter, signature + + parameters: Mapping[str, Parameter] = signature(function).parameters + + if parameters.keys() & {ALT_V_ARGS, ALT_V_KWARGS, V_POSITIONAL_ONLY_NAME, V_DUPLICATE_KWARGS}: + raise ConfigError( + f'"{ALT_V_ARGS}", "{ALT_V_KWARGS}", "{V_POSITIONAL_ONLY_NAME}" and "{V_DUPLICATE_KWARGS}" ' + f'are not permitted as argument names when using the "{validate_arguments.__name__}" decorator' + ) + + self.raw_function = function + self.arg_mapping: Dict[int, str] = {} + self.positional_only_args = set() + self.v_args_name = 'args' + self.v_kwargs_name = 'kwargs' + + type_hints = get_all_type_hints(function) + takes_args = False + takes_kwargs = False + fields: Dict[str, Tuple[Any, Any]] = {} + for i, (name, p) in enumerate(parameters.items()): + if p.annotation is p.empty: + annotation = Any + else: + annotation = type_hints[name] + + default = ... if p.default is p.empty else p.default + if p.kind == Parameter.POSITIONAL_ONLY: + self.arg_mapping[i] = name + fields[name] = annotation, default + fields[V_POSITIONAL_ONLY_NAME] = List[str], None + self.positional_only_args.add(name) + elif p.kind == Parameter.POSITIONAL_OR_KEYWORD: + self.arg_mapping[i] = name + fields[name] = annotation, default + fields[V_DUPLICATE_KWARGS] = List[str], None + elif p.kind == Parameter.KEYWORD_ONLY: + fields[name] = annotation, default + elif p.kind == Parameter.VAR_POSITIONAL: + self.v_args_name = name + fields[name] = Tuple[annotation, ...], None + takes_args = True + else: + assert p.kind == Parameter.VAR_KEYWORD, p.kind + self.v_kwargs_name = name + fields[name] = Dict[str, annotation], None # type: ignore + takes_kwargs = True + + # these checks avoid a clash between "args" and a field with that name + if not takes_args and self.v_args_name in fields: + self.v_args_name = ALT_V_ARGS + + # same with "kwargs" + if not takes_kwargs and self.v_kwargs_name in fields: + self.v_kwargs_name = ALT_V_KWARGS + + if not takes_args: + # we add the field so validation below can raise the correct exception + fields[self.v_args_name] = List[Any], None + + if not takes_kwargs: + # same with kwargs + fields[self.v_kwargs_name] = Dict[Any, Any], None + + self.create_model(fields, takes_args, takes_kwargs, config) + + def init_model_instance(self, *args: Any, **kwargs: Any) -> BaseModel: + values = self.build_values(args, kwargs) + return self.model(**values) + + def call(self, *args: Any, **kwargs: Any) -> Any: + m = self.init_model_instance(*args, **kwargs) + return self.execute(m) + + def build_values(self, args: Tuple[Any, ...], kwargs: Dict[str, Any]) -> Dict[str, Any]: + values: Dict[str, Any] = {} + if args: + arg_iter = enumerate(args) + while True: + try: + i, a = next(arg_iter) + except StopIteration: + break + arg_name = self.arg_mapping.get(i) + if arg_name is not None: + values[arg_name] = a + else: + values[self.v_args_name] = [a] + [a for _, a in arg_iter] + break + + var_kwargs: Dict[str, Any] = {} + wrong_positional_args = [] + duplicate_kwargs = [] + fields_alias = [ + field.alias + for name, field in self.model.__fields__.items() + if name not in (self.v_args_name, self.v_kwargs_name) + ] + non_var_fields = set(self.model.__fields__) - {self.v_args_name, self.v_kwargs_name} + for k, v in kwargs.items(): + if k in non_var_fields or k in fields_alias: + if k in self.positional_only_args: + wrong_positional_args.append(k) + if k in values: + duplicate_kwargs.append(k) + values[k] = v + else: + var_kwargs[k] = v + + if var_kwargs: + values[self.v_kwargs_name] = var_kwargs + if wrong_positional_args: + values[V_POSITIONAL_ONLY_NAME] = wrong_positional_args + if duplicate_kwargs: + values[V_DUPLICATE_KWARGS] = duplicate_kwargs + return values + + def execute(self, m: BaseModel) -> Any: + d = {k: v for k, v in m._iter() if k in m.__fields_set__ or m.__fields__[k].default_factory} + var_kwargs = d.pop(self.v_kwargs_name, {}) + + if self.v_args_name in d: + args_: List[Any] = [] + in_kwargs = False + kwargs = {} + for name, value in d.items(): + if in_kwargs: + kwargs[name] = value + elif name == self.v_args_name: + args_ += value + in_kwargs = True + else: + args_.append(value) + return self.raw_function(*args_, **kwargs, **var_kwargs) + elif self.positional_only_args: + args_ = [] + kwargs = {} + for name, value in d.items(): + if name in self.positional_only_args: + args_.append(value) + else: + kwargs[name] = value + return self.raw_function(*args_, **kwargs, **var_kwargs) + else: + return self.raw_function(**d, **var_kwargs) + + def create_model(self, fields: Dict[str, Any], takes_args: bool, takes_kwargs: bool, config: 'ConfigType') -> None: + pos_args = len(self.arg_mapping) + + class CustomConfig: + pass + + if not TYPE_CHECKING: # pragma: no branch + if isinstance(config, dict): + CustomConfig = type('Config', (), config) # noqa: F811 + elif config is not None: + CustomConfig = config # noqa: F811 + + if hasattr(CustomConfig, 'fields') or hasattr(CustomConfig, 'alias_generator'): + raise ConfigError( + 'Setting the "fields" and "alias_generator" property on custom Config for ' + '@validate_arguments is not yet supported, please remove.' + ) + + class DecoratorBaseModel(BaseModel): + @validator(self.v_args_name, check_fields=False, allow_reuse=True) + def check_args(cls, v: Optional[List[Any]]) -> Optional[List[Any]]: + if takes_args or v is None: + return v + + raise TypeError(f'{pos_args} positional arguments expected but {pos_args + len(v)} given') + + @validator(self.v_kwargs_name, check_fields=False, allow_reuse=True) + def check_kwargs(cls, v: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]: + if takes_kwargs or v is None: + return v + + plural = '' if len(v) == 1 else 's' + keys = ', '.join(map(repr, v.keys())) + raise TypeError(f'unexpected keyword argument{plural}: {keys}') + + @validator(V_POSITIONAL_ONLY_NAME, check_fields=False, allow_reuse=True) + def check_positional_only(cls, v: Optional[List[str]]) -> None: + if v is None: + return + + plural = '' if len(v) == 1 else 's' + keys = ', '.join(map(repr, v)) + raise TypeError(f'positional-only argument{plural} passed as keyword argument{plural}: {keys}') + + @validator(V_DUPLICATE_KWARGS, check_fields=False, allow_reuse=True) + def check_duplicate_kwargs(cls, v: Optional[List[str]]) -> None: + if v is None: + return + + plural = '' if len(v) == 1 else 's' + keys = ', '.join(map(repr, v)) + raise TypeError(f'multiple values for argument{plural}: {keys}') + + class Config(CustomConfig): + extra = getattr(CustomConfig, 'extra', Extra.forbid) + + self.model = create_model(to_camel(self.raw_function.__name__), __base__=DecoratorBaseModel, **fields) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/env_settings.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/env_settings.py new file mode 100644 index 0000000..488d5ec --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/env_settings.py @@ -0,0 +1,350 @@ +import os +import warnings +from pathlib import Path +from typing import AbstractSet, Any, Callable, ClassVar, Dict, List, Mapping, Optional, Tuple, Type, Union + +from pydantic.config import BaseConfig, Extra +from pydantic.fields import ModelField +from pydantic.main import BaseModel +from pydantic.types import JsonWrapper +from pydantic.typing import StrPath, display_as_type, get_origin, is_union +from pydantic.utils import deep_update, lenient_issubclass, path_type, sequence_like + +env_file_sentinel = str(object()) + +SettingsSourceCallable = Callable[['BaseSettings'], Dict[str, Any]] +DotenvType = Union[StrPath, List[StrPath], Tuple[StrPath, ...]] + + +class SettingsError(ValueError): + pass + + +class BaseSettings(BaseModel): + """ + Base class for settings, allowing values to be overridden by environment variables. + + This is useful in production for secrets you do not wish to save in code, it plays nicely with docker(-compose), + Heroku and any 12 factor app design. + """ + + def __init__( + __pydantic_self__, + _env_file: Optional[DotenvType] = env_file_sentinel, + _env_file_encoding: Optional[str] = None, + _env_nested_delimiter: Optional[str] = None, + _secrets_dir: Optional[StrPath] = None, + **values: Any, + ) -> None: + # Uses something other than `self` the first arg to allow "self" as a settable attribute + super().__init__( + **__pydantic_self__._build_values( + values, + _env_file=_env_file, + _env_file_encoding=_env_file_encoding, + _env_nested_delimiter=_env_nested_delimiter, + _secrets_dir=_secrets_dir, + ) + ) + + def _build_values( + self, + init_kwargs: Dict[str, Any], + _env_file: Optional[DotenvType] = None, + _env_file_encoding: Optional[str] = None, + _env_nested_delimiter: Optional[str] = None, + _secrets_dir: Optional[StrPath] = None, + ) -> Dict[str, Any]: + # Configure built-in sources + init_settings = InitSettingsSource(init_kwargs=init_kwargs) + env_settings = EnvSettingsSource( + env_file=(_env_file if _env_file != env_file_sentinel else self.__config__.env_file), + env_file_encoding=( + _env_file_encoding if _env_file_encoding is not None else self.__config__.env_file_encoding + ), + env_nested_delimiter=( + _env_nested_delimiter if _env_nested_delimiter is not None else self.__config__.env_nested_delimiter + ), + env_prefix_len=len(self.__config__.env_prefix), + ) + file_secret_settings = SecretsSettingsSource(secrets_dir=_secrets_dir or self.__config__.secrets_dir) + # Provide a hook to set built-in sources priority and add / remove sources + sources = self.__config__.customise_sources( + init_settings=init_settings, env_settings=env_settings, file_secret_settings=file_secret_settings + ) + if sources: + return deep_update(*reversed([source(self) for source in sources])) + else: + # no one should mean to do this, but I think returning an empty dict is marginally preferable + # to an informative error and much better than a confusing error + return {} + + class Config(BaseConfig): + env_prefix: str = '' + env_file: Optional[DotenvType] = None + env_file_encoding: Optional[str] = None + env_nested_delimiter: Optional[str] = None + secrets_dir: Optional[StrPath] = None + validate_all: bool = True + extra: Extra = Extra.forbid + arbitrary_types_allowed: bool = True + case_sensitive: bool = False + + @classmethod + def prepare_field(cls, field: ModelField) -> None: + env_names: Union[List[str], AbstractSet[str]] + field_info_from_config = cls.get_field_info(field.name) + + env = field_info_from_config.get('env') or field.field_info.extra.get('env') + if env is None: + if field.has_alias: + warnings.warn( + 'aliases are no longer used by BaseSettings to define which environment variables to read. ' + 'Instead use the "env" field setting. ' + 'See https://pydantic-docs.helpmanual.io/usage/settings/#environment-variable-names', + FutureWarning, + ) + env_names = {cls.env_prefix + field.name} + elif isinstance(env, str): + env_names = {env} + elif isinstance(env, (set, frozenset)): + env_names = env + elif sequence_like(env): + env_names = list(env) + else: + raise TypeError(f'invalid field env: {env!r} ({display_as_type(env)}); should be string, list or set') + + if not cls.case_sensitive: + env_names = env_names.__class__(n.lower() for n in env_names) + field.field_info.extra['env_names'] = env_names + + @classmethod + def customise_sources( + cls, + init_settings: SettingsSourceCallable, + env_settings: SettingsSourceCallable, + file_secret_settings: SettingsSourceCallable, + ) -> Tuple[SettingsSourceCallable, ...]: + return init_settings, env_settings, file_secret_settings + + @classmethod + def parse_env_var(cls, field_name: str, raw_val: str) -> Any: + return cls.json_loads(raw_val) + + # populated by the metaclass using the Config class defined above, annotated here to help IDEs only + __config__: ClassVar[Type[Config]] + + +class InitSettingsSource: + __slots__ = ('init_kwargs',) + + def __init__(self, init_kwargs: Dict[str, Any]): + self.init_kwargs = init_kwargs + + def __call__(self, settings: BaseSettings) -> Dict[str, Any]: + return self.init_kwargs + + def __repr__(self) -> str: + return f'InitSettingsSource(init_kwargs={self.init_kwargs!r})' + + +class EnvSettingsSource: + __slots__ = ('env_file', 'env_file_encoding', 'env_nested_delimiter', 'env_prefix_len') + + def __init__( + self, + env_file: Optional[DotenvType], + env_file_encoding: Optional[str], + env_nested_delimiter: Optional[str] = None, + env_prefix_len: int = 0, + ): + self.env_file: Optional[DotenvType] = env_file + self.env_file_encoding: Optional[str] = env_file_encoding + self.env_nested_delimiter: Optional[str] = env_nested_delimiter + self.env_prefix_len: int = env_prefix_len + + def __call__(self, settings: BaseSettings) -> Dict[str, Any]: # noqa C901 + """ + Build environment variables suitable for passing to the Model. + """ + d: Dict[str, Any] = {} + + if settings.__config__.case_sensitive: + env_vars: Mapping[str, Optional[str]] = os.environ + else: + env_vars = {k.lower(): v for k, v in os.environ.items()} + + dotenv_vars = self._read_env_files(settings.__config__.case_sensitive) + if dotenv_vars: + env_vars = {**dotenv_vars, **env_vars} + + for field in settings.__fields__.values(): + env_val: Optional[str] = None + for env_name in field.field_info.extra['env_names']: + env_val = env_vars.get(env_name) + if env_val is not None: + break + + is_complex, allow_parse_failure = self.field_is_complex(field) + if is_complex: + if env_val is None: + # field is complex but no value found so far, try explode_env_vars + env_val_built = self.explode_env_vars(field, env_vars) + if env_val_built: + d[field.alias] = env_val_built + else: + # field is complex and there's a value, decode that as JSON, then add explode_env_vars + try: + env_val = settings.__config__.parse_env_var(field.name, env_val) + except ValueError as e: + if not allow_parse_failure: + raise SettingsError(f'error parsing env var "{env_name}"') from e + + if isinstance(env_val, dict): + d[field.alias] = deep_update(env_val, self.explode_env_vars(field, env_vars)) + else: + d[field.alias] = env_val + elif env_val is not None: + # simplest case, field is not complex, we only need to add the value if it was found + d[field.alias] = env_val + + return d + + def _read_env_files(self, case_sensitive: bool) -> Dict[str, Optional[str]]: + env_files = self.env_file + if env_files is None: + return {} + + if isinstance(env_files, (str, os.PathLike)): + env_files = [env_files] + + dotenv_vars = {} + for env_file in env_files: + env_path = Path(env_file).expanduser() + if env_path.is_file(): + dotenv_vars.update( + read_env_file(env_path, encoding=self.env_file_encoding, case_sensitive=case_sensitive) + ) + + return dotenv_vars + + def field_is_complex(self, field: ModelField) -> Tuple[bool, bool]: + """ + Find out if a field is complex, and if so whether JSON errors should be ignored + """ + if lenient_issubclass(field.annotation, JsonWrapper): + return False, False + + if field.is_complex(): + allow_parse_failure = False + elif is_union(get_origin(field.type_)) and field.sub_fields and any(f.is_complex() for f in field.sub_fields): + allow_parse_failure = True + else: + return False, False + + return True, allow_parse_failure + + def explode_env_vars(self, field: ModelField, env_vars: Mapping[str, Optional[str]]) -> Dict[str, Any]: + """ + Process env_vars and extract the values of keys containing env_nested_delimiter into nested dictionaries. + + This is applied to a single field, hence filtering by env_var prefix. + """ + prefixes = [f'{env_name}{self.env_nested_delimiter}' for env_name in field.field_info.extra['env_names']] + result: Dict[str, Any] = {} + for env_name, env_val in env_vars.items(): + if not any(env_name.startswith(prefix) for prefix in prefixes): + continue + # we remove the prefix before splitting in case the prefix has characters in common with the delimiter + env_name_without_prefix = env_name[self.env_prefix_len :] + _, *keys, last_key = env_name_without_prefix.split(self.env_nested_delimiter) + env_var = result + for key in keys: + env_var = env_var.setdefault(key, {}) + env_var[last_key] = env_val + + return result + + def __repr__(self) -> str: + return ( + f'EnvSettingsSource(env_file={self.env_file!r}, env_file_encoding={self.env_file_encoding!r}, ' + f'env_nested_delimiter={self.env_nested_delimiter!r})' + ) + + +class SecretsSettingsSource: + __slots__ = ('secrets_dir',) + + def __init__(self, secrets_dir: Optional[StrPath]): + self.secrets_dir: Optional[StrPath] = secrets_dir + + def __call__(self, settings: BaseSettings) -> Dict[str, Any]: + """ + Build fields from "secrets" files. + """ + secrets: Dict[str, Optional[str]] = {} + + if self.secrets_dir is None: + return secrets + + secrets_path = Path(self.secrets_dir).expanduser() + + if not secrets_path.exists(): + warnings.warn(f'directory "{secrets_path}" does not exist') + return secrets + + if not secrets_path.is_dir(): + raise SettingsError(f'secrets_dir must reference a directory, not a {path_type(secrets_path)}') + + for field in settings.__fields__.values(): + for env_name in field.field_info.extra['env_names']: + path = find_case_path(secrets_path, env_name, settings.__config__.case_sensitive) + if not path: + # path does not exist, we currently don't return a warning for this + continue + + if path.is_file(): + secret_value = path.read_text().strip() + if field.is_complex(): + try: + secret_value = settings.__config__.parse_env_var(field.name, secret_value) + except ValueError as e: + raise SettingsError(f'error parsing env var "{env_name}"') from e + + secrets[field.alias] = secret_value + else: + warnings.warn( + f'attempted to load secret file "{path}" but found a {path_type(path)} instead.', + stacklevel=4, + ) + return secrets + + def __repr__(self) -> str: + return f'SecretsSettingsSource(secrets_dir={self.secrets_dir!r})' + + +def read_env_file( + file_path: StrPath, *, encoding: str = None, case_sensitive: bool = False +) -> Dict[str, Optional[str]]: + try: + from dotenv import dotenv_values + except ImportError as e: + raise ImportError('python-dotenv is not installed, run `pip install pydantic[dotenv]`') from e + + file_vars: Dict[str, Optional[str]] = dotenv_values(file_path, encoding=encoding or 'utf8') + if not case_sensitive: + return {k.lower(): v for k, v in file_vars.items()} + else: + return file_vars + + +def find_case_path(dir_path: Path, file_name: str, case_sensitive: bool) -> Optional[Path]: + """ + Find a file within path's directory matching filename, optionally ignoring case. + """ + for f in dir_path.iterdir(): + if f.name == file_name: + return f + elif not case_sensitive and f.name.lower() == file_name.lower(): + return f + return None diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/error_wrappers.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/error_wrappers.py new file mode 100644 index 0000000..b9fb9a1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/error_wrappers.py @@ -0,0 +1,161 @@ +import json +from typing import TYPE_CHECKING, Any, Dict, Generator, List, Optional, Sequence, Tuple, Type, Union + +from pydantic.json import pydantic_encoder +from pydantic.utils import Representation + +if TYPE_CHECKING: + from typing_extensions import TypedDict + + from pydantic.config import BaseConfig + from pydantic.types import ModelOrDc + from pydantic.typing import ReprArgs + + Loc = Tuple[Union[int, str], ...] + + class _ErrorDictRequired(TypedDict): + loc: Loc + msg: str + type: str + + class ErrorDict(_ErrorDictRequired, total=False): + ctx: Dict[str, Any] + + +__all__ = 'ErrorWrapper', 'ValidationError' + + +class ErrorWrapper(Representation): + __slots__ = 'exc', '_loc' + + def __init__(self, exc: Exception, loc: Union[str, 'Loc']) -> None: + self.exc = exc + self._loc = loc + + def loc_tuple(self) -> 'Loc': + if isinstance(self._loc, tuple): + return self._loc + else: + return (self._loc,) + + def __repr_args__(self) -> 'ReprArgs': + return [('exc', self.exc), ('loc', self.loc_tuple())] + + +# ErrorList is something like Union[List[Union[List[ErrorWrapper], ErrorWrapper]], ErrorWrapper] +# but recursive, therefore just use: +ErrorList = Union[Sequence[Any], ErrorWrapper] + + +class ValidationError(Representation, ValueError): + __slots__ = 'raw_errors', 'model', '_error_cache' + + def __init__(self, errors: Sequence[ErrorList], model: 'ModelOrDc') -> None: + self.raw_errors = errors + self.model = model + self._error_cache: Optional[List['ErrorDict']] = None + + def errors(self) -> List['ErrorDict']: + if self._error_cache is None: + try: + config = self.model.__config__ # type: ignore + except AttributeError: + config = self.model.__pydantic_model__.__config__ # type: ignore + self._error_cache = list(flatten_errors(self.raw_errors, config)) + return self._error_cache + + def json(self, *, indent: Union[None, int, str] = 2) -> str: + return json.dumps(self.errors(), indent=indent, default=pydantic_encoder) + + def __str__(self) -> str: + errors = self.errors() + no_errors = len(errors) + return ( + f'{no_errors} validation error{"" if no_errors == 1 else "s"} for {self.model.__name__}\n' + f'{display_errors(errors)}' + ) + + def __repr_args__(self) -> 'ReprArgs': + return [('model', self.model.__name__), ('errors', self.errors())] + + +def display_errors(errors: List['ErrorDict']) -> str: + return '\n'.join(f'{_display_error_loc(e)}\n {e["msg"]} ({_display_error_type_and_ctx(e)})' for e in errors) + + +def _display_error_loc(error: 'ErrorDict') -> str: + return ' -> '.join(str(e) for e in error['loc']) + + +def _display_error_type_and_ctx(error: 'ErrorDict') -> str: + t = 'type=' + error['type'] + ctx = error.get('ctx') + if ctx: + return t + ''.join(f'; {k}={v}' for k, v in ctx.items()) + else: + return t + + +def flatten_errors( + errors: Sequence[Any], config: Type['BaseConfig'], loc: Optional['Loc'] = None +) -> Generator['ErrorDict', None, None]: + for error in errors: + if isinstance(error, ErrorWrapper): + if loc: + error_loc = loc + error.loc_tuple() + else: + error_loc = error.loc_tuple() + + if isinstance(error.exc, ValidationError): + yield from flatten_errors(error.exc.raw_errors, config, error_loc) + else: + yield error_dict(error.exc, config, error_loc) + elif isinstance(error, list): + yield from flatten_errors(error, config, loc=loc) + else: + raise RuntimeError(f'Unknown error object: {error}') + + +def error_dict(exc: Exception, config: Type['BaseConfig'], loc: 'Loc') -> 'ErrorDict': + type_ = get_exc_type(exc.__class__) + msg_template = config.error_msg_templates.get(type_) or getattr(exc, 'msg_template', None) + ctx = exc.__dict__ + if msg_template: + msg = msg_template.format(**ctx) + else: + msg = str(exc) + + d: 'ErrorDict' = {'loc': loc, 'msg': msg, 'type': type_} + + if ctx: + d['ctx'] = ctx + + return d + + +_EXC_TYPE_CACHE: Dict[Type[Exception], str] = {} + + +def get_exc_type(cls: Type[Exception]) -> str: + # slightly more efficient than using lru_cache since we don't need to worry about the cache filling up + try: + return _EXC_TYPE_CACHE[cls] + except KeyError: + r = _get_exc_type(cls) + _EXC_TYPE_CACHE[cls] = r + return r + + +def _get_exc_type(cls: Type[Exception]) -> str: + if issubclass(cls, AssertionError): + return 'assertion_error' + + base_name = 'type_error' if issubclass(cls, TypeError) else 'value_error' + if cls in (TypeError, ValueError): + # just TypeError or ValueError, no extra code + return base_name + + # if it's not a TypeError or ValueError, we just take the lowercase of the exception name + # no chaining or snake case logic, use "code" for more complex error types. + code = getattr(cls, 'code', None) or cls.__name__.replace('Error', '').lower() + return base_name + '.' + code diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/errors.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/errors.py new file mode 100644 index 0000000..75dc24c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/errors.py @@ -0,0 +1,646 @@ +from decimal import Decimal +from pathlib import Path +from typing import TYPE_CHECKING, Any, Callable, Sequence, Set, Tuple, Type, Union + +from pydantic.typing import display_as_type + +if TYPE_CHECKING: + from pydantic.typing import DictStrAny + +# explicitly state exports to avoid "from pydantic.errors import *" also importing Decimal, Path etc. +__all__ = ( + 'PydanticTypeError', + 'PydanticValueError', + 'ConfigError', + 'MissingError', + 'ExtraError', + 'NoneIsNotAllowedError', + 'NoneIsAllowedError', + 'WrongConstantError', + 'NotNoneError', + 'BoolError', + 'BytesError', + 'DictError', + 'EmailError', + 'UrlError', + 'UrlSchemeError', + 'UrlSchemePermittedError', + 'UrlUserInfoError', + 'UrlHostError', + 'UrlHostTldError', + 'UrlPortError', + 'UrlExtraError', + 'EnumError', + 'IntEnumError', + 'EnumMemberError', + 'IntegerError', + 'FloatError', + 'PathError', + 'PathNotExistsError', + 'PathNotAFileError', + 'PathNotADirectoryError', + 'PyObjectError', + 'SequenceError', + 'ListError', + 'SetError', + 'FrozenSetError', + 'TupleError', + 'TupleLengthError', + 'ListMinLengthError', + 'ListMaxLengthError', + 'ListUniqueItemsError', + 'SetMinLengthError', + 'SetMaxLengthError', + 'FrozenSetMinLengthError', + 'FrozenSetMaxLengthError', + 'AnyStrMinLengthError', + 'AnyStrMaxLengthError', + 'StrError', + 'StrRegexError', + 'NumberNotGtError', + 'NumberNotGeError', + 'NumberNotLtError', + 'NumberNotLeError', + 'NumberNotMultipleError', + 'DecimalError', + 'DecimalIsNotFiniteError', + 'DecimalMaxDigitsError', + 'DecimalMaxPlacesError', + 'DecimalWholeDigitsError', + 'DateTimeError', + 'DateError', + 'DateNotInThePastError', + 'DateNotInTheFutureError', + 'TimeError', + 'DurationError', + 'HashableError', + 'UUIDError', + 'UUIDVersionError', + 'ArbitraryTypeError', + 'ClassError', + 'SubclassError', + 'JsonError', + 'JsonTypeError', + 'PatternError', + 'DataclassTypeError', + 'CallableError', + 'IPvAnyAddressError', + 'IPvAnyInterfaceError', + 'IPvAnyNetworkError', + 'IPv4AddressError', + 'IPv6AddressError', + 'IPv4NetworkError', + 'IPv6NetworkError', + 'IPv4InterfaceError', + 'IPv6InterfaceError', + 'ColorError', + 'StrictBoolError', + 'NotDigitError', + 'LuhnValidationError', + 'InvalidLengthForBrand', + 'InvalidByteSize', + 'InvalidByteSizeUnit', + 'MissingDiscriminator', + 'InvalidDiscriminator', +) + + +def cls_kwargs(cls: Type['PydanticErrorMixin'], ctx: 'DictStrAny') -> 'PydanticErrorMixin': + """ + For built-in exceptions like ValueError or TypeError, we need to implement + __reduce__ to override the default behaviour (instead of __getstate__/__setstate__) + By default pickle protocol 2 calls `cls.__new__(cls, *args)`. + Since we only use kwargs, we need a little constructor to change that. + Note: the callable can't be a lambda as pickle looks in the namespace to find it + """ + return cls(**ctx) + + +class PydanticErrorMixin: + code: str + msg_template: str + + def __init__(self, **ctx: Any) -> None: + self.__dict__ = ctx + + def __str__(self) -> str: + return self.msg_template.format(**self.__dict__) + + def __reduce__(self) -> Tuple[Callable[..., 'PydanticErrorMixin'], Tuple[Type['PydanticErrorMixin'], 'DictStrAny']]: + return cls_kwargs, (self.__class__, self.__dict__) + + +class PydanticTypeError(PydanticErrorMixin, TypeError): + pass + + +class PydanticValueError(PydanticErrorMixin, ValueError): + pass + + +class ConfigError(RuntimeError): + pass + + +class MissingError(PydanticValueError): + msg_template = 'field required' + + +class ExtraError(PydanticValueError): + msg_template = 'extra fields not permitted' + + +class NoneIsNotAllowedError(PydanticTypeError): + code = 'none.not_allowed' + msg_template = 'none is not an allowed value' + + +class NoneIsAllowedError(PydanticTypeError): + code = 'none.allowed' + msg_template = 'value is not none' + + +class WrongConstantError(PydanticValueError): + code = 'const' + + def __str__(self) -> str: + permitted = ', '.join(repr(v) for v in self.permitted) # type: ignore + return f'unexpected value; permitted: {permitted}' + + +class NotNoneError(PydanticTypeError): + code = 'not_none' + msg_template = 'value is not None' + + +class BoolError(PydanticTypeError): + msg_template = 'value could not be parsed to a boolean' + + +class BytesError(PydanticTypeError): + msg_template = 'byte type expected' + + +class DictError(PydanticTypeError): + msg_template = 'value is not a valid dict' + + +class EmailError(PydanticValueError): + msg_template = 'value is not a valid email address' + + +class UrlError(PydanticValueError): + code = 'url' + + +class UrlSchemeError(UrlError): + code = 'url.scheme' + msg_template = 'invalid or missing URL scheme' + + +class UrlSchemePermittedError(UrlError): + code = 'url.scheme' + msg_template = 'URL scheme not permitted' + + def __init__(self, allowed_schemes: Set[str]): + super().__init__(allowed_schemes=allowed_schemes) + + +class UrlUserInfoError(UrlError): + code = 'url.userinfo' + msg_template = 'userinfo required in URL but missing' + + +class UrlHostError(UrlError): + code = 'url.host' + msg_template = 'URL host invalid' + + +class UrlHostTldError(UrlError): + code = 'url.host' + msg_template = 'URL host invalid, top level domain required' + + +class UrlPortError(UrlError): + code = 'url.port' + msg_template = 'URL port invalid, port cannot exceed 65535' + + +class UrlExtraError(UrlError): + code = 'url.extra' + msg_template = 'URL invalid, extra characters found after valid URL: {extra!r}' + + +class EnumMemberError(PydanticTypeError): + code = 'enum' + + def __str__(self) -> str: + permitted = ', '.join(repr(v.value) for v in self.enum_values) # type: ignore + return f'value is not a valid enumeration member; permitted: {permitted}' + + +class IntegerError(PydanticTypeError): + msg_template = 'value is not a valid integer' + + +class FloatError(PydanticTypeError): + msg_template = 'value is not a valid float' + + +class PathError(PydanticTypeError): + msg_template = 'value is not a valid path' + + +class _PathValueError(PydanticValueError): + def __init__(self, *, path: Path) -> None: + super().__init__(path=str(path)) + + +class PathNotExistsError(_PathValueError): + code = 'path.not_exists' + msg_template = 'file or directory at path "{path}" does not exist' + + +class PathNotAFileError(_PathValueError): + code = 'path.not_a_file' + msg_template = 'path "{path}" does not point to a file' + + +class PathNotADirectoryError(_PathValueError): + code = 'path.not_a_directory' + msg_template = 'path "{path}" does not point to a directory' + + +class PyObjectError(PydanticTypeError): + msg_template = 'ensure this value contains valid import path or valid callable: {error_message}' + + +class SequenceError(PydanticTypeError): + msg_template = 'value is not a valid sequence' + + +class IterableError(PydanticTypeError): + msg_template = 'value is not a valid iterable' + + +class ListError(PydanticTypeError): + msg_template = 'value is not a valid list' + + +class SetError(PydanticTypeError): + msg_template = 'value is not a valid set' + + +class FrozenSetError(PydanticTypeError): + msg_template = 'value is not a valid frozenset' + + +class DequeError(PydanticTypeError): + msg_template = 'value is not a valid deque' + + +class TupleError(PydanticTypeError): + msg_template = 'value is not a valid tuple' + + +class TupleLengthError(PydanticValueError): + code = 'tuple.length' + msg_template = 'wrong tuple length {actual_length}, expected {expected_length}' + + def __init__(self, *, actual_length: int, expected_length: int) -> None: + super().__init__(actual_length=actual_length, expected_length=expected_length) + + +class ListMinLengthError(PydanticValueError): + code = 'list.min_items' + msg_template = 'ensure this value has at least {limit_value} items' + + def __init__(self, *, limit_value: int) -> None: + super().__init__(limit_value=limit_value) + + +class ListMaxLengthError(PydanticValueError): + code = 'list.max_items' + msg_template = 'ensure this value has at most {limit_value} items' + + def __init__(self, *, limit_value: int) -> None: + super().__init__(limit_value=limit_value) + + +class ListUniqueItemsError(PydanticValueError): + code = 'list.unique_items' + msg_template = 'the list has duplicated items' + + +class SetMinLengthError(PydanticValueError): + code = 'set.min_items' + msg_template = 'ensure this value has at least {limit_value} items' + + def __init__(self, *, limit_value: int) -> None: + super().__init__(limit_value=limit_value) + + +class SetMaxLengthError(PydanticValueError): + code = 'set.max_items' + msg_template = 'ensure this value has at most {limit_value} items' + + def __init__(self, *, limit_value: int) -> None: + super().__init__(limit_value=limit_value) + + +class FrozenSetMinLengthError(PydanticValueError): + code = 'frozenset.min_items' + msg_template = 'ensure this value has at least {limit_value} items' + + def __init__(self, *, limit_value: int) -> None: + super().__init__(limit_value=limit_value) + + +class FrozenSetMaxLengthError(PydanticValueError): + code = 'frozenset.max_items' + msg_template = 'ensure this value has at most {limit_value} items' + + def __init__(self, *, limit_value: int) -> None: + super().__init__(limit_value=limit_value) + + +class AnyStrMinLengthError(PydanticValueError): + code = 'any_str.min_length' + msg_template = 'ensure this value has at least {limit_value} characters' + + def __init__(self, *, limit_value: int) -> None: + super().__init__(limit_value=limit_value) + + +class AnyStrMaxLengthError(PydanticValueError): + code = 'any_str.max_length' + msg_template = 'ensure this value has at most {limit_value} characters' + + def __init__(self, *, limit_value: int) -> None: + super().__init__(limit_value=limit_value) + + +class StrError(PydanticTypeError): + msg_template = 'str type expected' + + +class StrRegexError(PydanticValueError): + code = 'str.regex' + msg_template = 'string does not match regex "{pattern}"' + + def __init__(self, *, pattern: str) -> None: + super().__init__(pattern=pattern) + + +class _NumberBoundError(PydanticValueError): + def __init__(self, *, limit_value: Union[int, float, Decimal]) -> None: + super().__init__(limit_value=limit_value) + + +class NumberNotGtError(_NumberBoundError): + code = 'number.not_gt' + msg_template = 'ensure this value is greater than {limit_value}' + + +class NumberNotGeError(_NumberBoundError): + code = 'number.not_ge' + msg_template = 'ensure this value is greater than or equal to {limit_value}' + + +class NumberNotLtError(_NumberBoundError): + code = 'number.not_lt' + msg_template = 'ensure this value is less than {limit_value}' + + +class NumberNotLeError(_NumberBoundError): + code = 'number.not_le' + msg_template = 'ensure this value is less than or equal to {limit_value}' + + +class NumberNotFiniteError(PydanticValueError): + code = 'number.not_finite_number' + msg_template = 'ensure this value is a finite number' + + +class NumberNotMultipleError(PydanticValueError): + code = 'number.not_multiple' + msg_template = 'ensure this value is a multiple of {multiple_of}' + + def __init__(self, *, multiple_of: Union[int, float, Decimal]) -> None: + super().__init__(multiple_of=multiple_of) + + +class DecimalError(PydanticTypeError): + msg_template = 'value is not a valid decimal' + + +class DecimalIsNotFiniteError(PydanticValueError): + code = 'decimal.not_finite' + msg_template = 'value is not a valid decimal' + + +class DecimalMaxDigitsError(PydanticValueError): + code = 'decimal.max_digits' + msg_template = 'ensure that there are no more than {max_digits} digits in total' + + def __init__(self, *, max_digits: int) -> None: + super().__init__(max_digits=max_digits) + + +class DecimalMaxPlacesError(PydanticValueError): + code = 'decimal.max_places' + msg_template = 'ensure that there are no more than {decimal_places} decimal places' + + def __init__(self, *, decimal_places: int) -> None: + super().__init__(decimal_places=decimal_places) + + +class DecimalWholeDigitsError(PydanticValueError): + code = 'decimal.whole_digits' + msg_template = 'ensure that there are no more than {whole_digits} digits before the decimal point' + + def __init__(self, *, whole_digits: int) -> None: + super().__init__(whole_digits=whole_digits) + + +class DateTimeError(PydanticValueError): + msg_template = 'invalid datetime format' + + +class DateError(PydanticValueError): + msg_template = 'invalid date format' + + +class DateNotInThePastError(PydanticValueError): + code = 'date.not_in_the_past' + msg_template = 'date is not in the past' + + +class DateNotInTheFutureError(PydanticValueError): + code = 'date.not_in_the_future' + msg_template = 'date is not in the future' + + +class TimeError(PydanticValueError): + msg_template = 'invalid time format' + + +class DurationError(PydanticValueError): + msg_template = 'invalid duration format' + + +class HashableError(PydanticTypeError): + msg_template = 'value is not a valid hashable' + + +class UUIDError(PydanticTypeError): + msg_template = 'value is not a valid uuid' + + +class UUIDVersionError(PydanticValueError): + code = 'uuid.version' + msg_template = 'uuid version {required_version} expected' + + def __init__(self, *, required_version: int) -> None: + super().__init__(required_version=required_version) + + +class ArbitraryTypeError(PydanticTypeError): + code = 'arbitrary_type' + msg_template = 'instance of {expected_arbitrary_type} expected' + + def __init__(self, *, expected_arbitrary_type: Type[Any]) -> None: + super().__init__(expected_arbitrary_type=display_as_type(expected_arbitrary_type)) + + +class ClassError(PydanticTypeError): + code = 'class' + msg_template = 'a class is expected' + + +class SubclassError(PydanticTypeError): + code = 'subclass' + msg_template = 'subclass of {expected_class} expected' + + def __init__(self, *, expected_class: Type[Any]) -> None: + super().__init__(expected_class=display_as_type(expected_class)) + + +class JsonError(PydanticValueError): + msg_template = 'Invalid JSON' + + +class JsonTypeError(PydanticTypeError): + code = 'json' + msg_template = 'JSON object must be str, bytes or bytearray' + + +class PatternError(PydanticValueError): + code = 'regex_pattern' + msg_template = 'Invalid regular expression' + + +class DataclassTypeError(PydanticTypeError): + code = 'dataclass' + msg_template = 'instance of {class_name}, tuple or dict expected' + + +class CallableError(PydanticTypeError): + msg_template = '{value} is not callable' + + +class EnumError(PydanticTypeError): + code = 'enum_instance' + msg_template = '{value} is not a valid Enum instance' + + +class IntEnumError(PydanticTypeError): + code = 'int_enum_instance' + msg_template = '{value} is not a valid IntEnum instance' + + +class IPvAnyAddressError(PydanticValueError): + msg_template = 'value is not a valid IPv4 or IPv6 address' + + +class IPvAnyInterfaceError(PydanticValueError): + msg_template = 'value is not a valid IPv4 or IPv6 interface' + + +class IPvAnyNetworkError(PydanticValueError): + msg_template = 'value is not a valid IPv4 or IPv6 network' + + +class IPv4AddressError(PydanticValueError): + msg_template = 'value is not a valid IPv4 address' + + +class IPv6AddressError(PydanticValueError): + msg_template = 'value is not a valid IPv6 address' + + +class IPv4NetworkError(PydanticValueError): + msg_template = 'value is not a valid IPv4 network' + + +class IPv6NetworkError(PydanticValueError): + msg_template = 'value is not a valid IPv6 network' + + +class IPv4InterfaceError(PydanticValueError): + msg_template = 'value is not a valid IPv4 interface' + + +class IPv6InterfaceError(PydanticValueError): + msg_template = 'value is not a valid IPv6 interface' + + +class ColorError(PydanticValueError): + msg_template = 'value is not a valid color: {reason}' + + +class StrictBoolError(PydanticValueError): + msg_template = 'value is not a valid boolean' + + +class NotDigitError(PydanticValueError): + code = 'payment_card_number.digits' + msg_template = 'card number is not all digits' + + +class LuhnValidationError(PydanticValueError): + code = 'payment_card_number.luhn_check' + msg_template = 'card number is not luhn valid' + + +class InvalidLengthForBrand(PydanticValueError): + code = 'payment_card_number.invalid_length_for_brand' + msg_template = 'Length for a {brand} card must be {required_length}' + + +class InvalidByteSize(PydanticValueError): + msg_template = 'could not parse value and unit from byte string' + + +class InvalidByteSizeUnit(PydanticValueError): + msg_template = 'could not interpret byte unit: {unit}' + + +class MissingDiscriminator(PydanticValueError): + code = 'discriminated_union.missing_discriminator' + msg_template = 'Discriminator {discriminator_key!r} is missing in value' + + +class InvalidDiscriminator(PydanticValueError): + code = 'discriminated_union.invalid_discriminator' + msg_template = ( + 'No match for discriminator {discriminator_key!r} and value {discriminator_value!r} ' + '(allowed values: {allowed_values})' + ) + + def __init__(self, *, discriminator_key: str, discriminator_value: Any, allowed_values: Sequence[Any]) -> None: + super().__init__( + discriminator_key=discriminator_key, + discriminator_value=discriminator_value, + allowed_values=', '.join(map(repr, allowed_values)), + ) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/fields.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/fields.py new file mode 100644 index 0000000..8a75e1c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/fields.py @@ -0,0 +1,1253 @@ +import copy +import re +from collections import Counter as CollectionCounter, defaultdict, deque +from collections.abc import Callable, Hashable as CollectionsHashable, Iterable as CollectionsIterable +from typing import ( + TYPE_CHECKING, + Any, + Counter, + DefaultDict, + Deque, + Dict, + ForwardRef, + FrozenSet, + Generator, + Iterable, + Iterator, + List, + Mapping, + Optional, + Pattern, + Sequence, + Set, + Tuple, + Type, + TypeVar, + Union, +) + +from typing_extensions import Annotated, Final + +from pydantic import errors as errors_ +from pydantic.class_validators import Validator, make_generic_validator, prep_validators +from pydantic.error_wrappers import ErrorWrapper +from pydantic.errors import ConfigError, InvalidDiscriminator, MissingDiscriminator, NoneIsNotAllowedError +from pydantic.types import Json, JsonWrapper +from pydantic.typing import ( + NoArgAnyCallable, + convert_generics, + display_as_type, + get_args, + get_origin, + is_finalvar, + is_literal_type, + is_new_type, + is_none_type, + is_typeddict, + is_typeddict_special, + is_union, + new_type_supertype, +) +from pydantic.utils import ( + PyObjectStr, + Representation, + ValueItems, + get_discriminator_alias_and_values, + get_unique_discriminator_alias, + lenient_isinstance, + lenient_issubclass, + sequence_like, + smart_deepcopy, +) +from pydantic.validators import constant_validator, dict_validator, find_validators, validate_json + +Required: Any = Ellipsis + +T = TypeVar('T') + + +class UndefinedType: + def __repr__(self) -> str: + return 'PydanticUndefined' + + def __copy__(self: T) -> T: + return self + + def __reduce__(self) -> str: + return 'Undefined' + + def __deepcopy__(self: T, _: Any) -> T: + return self + + +Undefined = UndefinedType() + +if TYPE_CHECKING: + from pydantic.class_validators import ValidatorsList + from pydantic.config import BaseConfig + from pydantic.error_wrappers import ErrorList + from pydantic.types import ModelOrDc + from pydantic.typing import AbstractSetIntStr, MappingIntStrAny, ReprArgs + + ValidateReturn = Tuple[Optional[Any], Optional[ErrorList]] + LocStr = Union[Tuple[Union[int, str], ...], str] + BoolUndefined = Union[bool, UndefinedType] + + +class FieldInfo(Representation): + """ + Captures extra information about a field. + """ + + __slots__ = ( + 'default', + 'default_factory', + 'alias', + 'alias_priority', + 'title', + 'description', + 'exclude', + 'include', + 'const', + 'gt', + 'ge', + 'lt', + 'le', + 'multiple_of', + 'allow_inf_nan', + 'max_digits', + 'decimal_places', + 'min_items', + 'max_items', + 'unique_items', + 'min_length', + 'max_length', + 'allow_mutation', + 'repr', + 'regex', + 'discriminator', + 'extra', + ) + + # field constraints with the default value, it's also used in update_from_config below + __field_constraints__ = { + 'min_length': None, + 'max_length': None, + 'regex': None, + 'gt': None, + 'lt': None, + 'ge': None, + 'le': None, + 'multiple_of': None, + 'allow_inf_nan': None, + 'max_digits': None, + 'decimal_places': None, + 'min_items': None, + 'max_items': None, + 'unique_items': None, + 'allow_mutation': True, + } + + def __init__(self, default: Any = Undefined, **kwargs: Any) -> None: + self.default = default + self.default_factory = kwargs.pop('default_factory', None) + self.alias = kwargs.pop('alias', None) + self.alias_priority = kwargs.pop('alias_priority', 2 if self.alias is not None else None) + self.title = kwargs.pop('title', None) + self.description = kwargs.pop('description', None) + self.exclude = kwargs.pop('exclude', None) + self.include = kwargs.pop('include', None) + self.const = kwargs.pop('const', None) + self.gt = kwargs.pop('gt', None) + self.ge = kwargs.pop('ge', None) + self.lt = kwargs.pop('lt', None) + self.le = kwargs.pop('le', None) + self.multiple_of = kwargs.pop('multiple_of', None) + self.allow_inf_nan = kwargs.pop('allow_inf_nan', None) + self.max_digits = kwargs.pop('max_digits', None) + self.decimal_places = kwargs.pop('decimal_places', None) + self.min_items = kwargs.pop('min_items', None) + self.max_items = kwargs.pop('max_items', None) + self.unique_items = kwargs.pop('unique_items', None) + self.min_length = kwargs.pop('min_length', None) + self.max_length = kwargs.pop('max_length', None) + self.allow_mutation = kwargs.pop('allow_mutation', True) + self.regex = kwargs.pop('regex', None) + self.discriminator = kwargs.pop('discriminator', None) + self.repr = kwargs.pop('repr', True) + self.extra = kwargs + + def __repr_args__(self) -> 'ReprArgs': + field_defaults_to_hide: Dict[str, Any] = { + 'repr': True, + **self.__field_constraints__, + } + + attrs = ((s, getattr(self, s)) for s in self.__slots__) + return [(a, v) for a, v in attrs if v != field_defaults_to_hide.get(a, None)] + + def get_constraints(self) -> Set[str]: + """ + Gets the constraints set on the field by comparing the constraint value with its default value + + :return: the constraints set on field_info + """ + return {attr for attr, default in self.__field_constraints__.items() if getattr(self, attr) != default} + + def update_from_config(self, from_config: Dict[str, Any]) -> None: + """ + Update this FieldInfo based on a dict from get_field_info, only fields which have not been set are dated. + """ + for attr_name, value in from_config.items(): + try: + current_value = getattr(self, attr_name) + except AttributeError: + # attr_name is not an attribute of FieldInfo, it should therefore be added to extra + # (except if extra already has this value!) + self.extra.setdefault(attr_name, value) + else: + if current_value is self.__field_constraints__.get(attr_name, None): + setattr(self, attr_name, value) + elif attr_name == 'exclude': + self.exclude = ValueItems.merge(value, current_value) + elif attr_name == 'include': + self.include = ValueItems.merge(value, current_value, intersect=True) + + def _validate(self) -> None: + if self.default is not Undefined and self.default_factory is not None: + raise ValueError('cannot specify both default and default_factory') + + +def Field( + default: Any = Undefined, + *, + default_factory: Optional[NoArgAnyCallable] = None, + alias: Optional[str] = None, + title: Optional[str] = None, + description: Optional[str] = None, + exclude: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny', Any]] = None, + include: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny', Any]] = None, + const: Optional[bool] = None, + gt: Optional[float] = None, + ge: Optional[float] = None, + lt: Optional[float] = None, + le: Optional[float] = None, + multiple_of: Optional[float] = None, + allow_inf_nan: Optional[bool] = None, + max_digits: Optional[int] = None, + decimal_places: Optional[int] = None, + min_items: Optional[int] = None, + max_items: Optional[int] = None, + unique_items: Optional[bool] = None, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + allow_mutation: bool = True, + regex: Optional[str] = None, + discriminator: Optional[str] = None, + repr: bool = True, + **extra: Any, +) -> Any: + """ + Used to provide extra information about a field, either for the model schema or complex validation. Some arguments + apply only to number fields (``int``, ``float``, ``Decimal``) and some apply only to ``str``. + + :param default: since this is replacing the field’s default, its first argument is used + to set the default, use ellipsis (``...``) to indicate the field is required + :param default_factory: callable that will be called when a default value is needed for this field + If both `default` and `default_factory` are set, an error is raised. + :param alias: the public name of the field + :param title: can be any string, used in the schema + :param description: can be any string, used in the schema + :param exclude: exclude this field while dumping. + Takes same values as the ``include`` and ``exclude`` arguments on the ``.dict`` method. + :param include: include this field while dumping. + Takes same values as the ``include`` and ``exclude`` arguments on the ``.dict`` method. + :param const: this field is required and *must* take it's default value + :param gt: only applies to numbers, requires the field to be "greater than". The schema + will have an ``exclusiveMinimum`` validation keyword + :param ge: only applies to numbers, requires the field to be "greater than or equal to". The + schema will have a ``minimum`` validation keyword + :param lt: only applies to numbers, requires the field to be "less than". The schema + will have an ``exclusiveMaximum`` validation keyword + :param le: only applies to numbers, requires the field to be "less than or equal to". The + schema will have a ``maximum`` validation keyword + :param multiple_of: only applies to numbers, requires the field to be "a multiple of". The + schema will have a ``multipleOf`` validation keyword + :param allow_inf_nan: only applies to numbers, allows the field to be NaN or infinity (+inf or -inf), + which is a valid Python float. Default True, set to False for compatibility with JSON. + :param max_digits: only applies to Decimals, requires the field to have a maximum number + of digits within the decimal. It does not include a zero before the decimal point or trailing decimal zeroes. + :param decimal_places: only applies to Decimals, requires the field to have at most a number of decimal places + allowed. It does not include trailing decimal zeroes. + :param min_items: only applies to lists, requires the field to have a minimum number of + elements. The schema will have a ``minItems`` validation keyword + :param max_items: only applies to lists, requires the field to have a maximum number of + elements. The schema will have a ``maxItems`` validation keyword + :param unique_items: only applies to lists, requires the field not to have duplicated + elements. The schema will have a ``uniqueItems`` validation keyword + :param min_length: only applies to strings, requires the field to have a minimum length. The + schema will have a ``minLength`` validation keyword + :param max_length: only applies to strings, requires the field to have a maximum length. The + schema will have a ``maxLength`` validation keyword + :param allow_mutation: a boolean which defaults to True. When False, the field raises a TypeError if the field is + assigned on an instance. The BaseModel Config must set validate_assignment to True + :param regex: only applies to strings, requires the field match against a regular expression + pattern string. The schema will have a ``pattern`` validation keyword + :param discriminator: only useful with a (discriminated a.k.a. tagged) `Union` of sub models with a common field. + The `discriminator` is the name of this common field to shorten validation and improve generated schema + :param repr: show this field in the representation + :param **extra: any additional keyword arguments will be added as is to the schema + """ + field_info = FieldInfo( + default, + default_factory=default_factory, + alias=alias, + title=title, + description=description, + exclude=exclude, + include=include, + const=const, + gt=gt, + ge=ge, + lt=lt, + le=le, + multiple_of=multiple_of, + allow_inf_nan=allow_inf_nan, + max_digits=max_digits, + decimal_places=decimal_places, + min_items=min_items, + max_items=max_items, + unique_items=unique_items, + min_length=min_length, + max_length=max_length, + allow_mutation=allow_mutation, + regex=regex, + discriminator=discriminator, + repr=repr, + **extra, + ) + field_info._validate() + return field_info + + +# used to be an enum but changed to int's for small performance improvement as less access overhead +SHAPE_SINGLETON = 1 +SHAPE_LIST = 2 +SHAPE_SET = 3 +SHAPE_MAPPING = 4 +SHAPE_TUPLE = 5 +SHAPE_TUPLE_ELLIPSIS = 6 +SHAPE_SEQUENCE = 7 +SHAPE_FROZENSET = 8 +SHAPE_ITERABLE = 9 +SHAPE_GENERIC = 10 +SHAPE_DEQUE = 11 +SHAPE_DICT = 12 +SHAPE_DEFAULTDICT = 13 +SHAPE_COUNTER = 14 +SHAPE_NAME_LOOKUP = { + SHAPE_LIST: 'List[{}]', + SHAPE_SET: 'Set[{}]', + SHAPE_TUPLE_ELLIPSIS: 'Tuple[{}, ...]', + SHAPE_SEQUENCE: 'Sequence[{}]', + SHAPE_FROZENSET: 'FrozenSet[{}]', + SHAPE_ITERABLE: 'Iterable[{}]', + SHAPE_DEQUE: 'Deque[{}]', + SHAPE_DICT: 'Dict[{}]', + SHAPE_DEFAULTDICT: 'DefaultDict[{}]', + SHAPE_COUNTER: 'Counter[{}]', +} + +MAPPING_LIKE_SHAPES: Set[int] = {SHAPE_DEFAULTDICT, SHAPE_DICT, SHAPE_MAPPING, SHAPE_COUNTER} + + +class ModelField(Representation): + __slots__ = ( + 'type_', + 'outer_type_', + 'annotation', + 'sub_fields', + 'sub_fields_mapping', + 'key_field', + 'validators', + 'pre_validators', + 'post_validators', + 'default', + 'default_factory', + 'required', + 'final', + 'model_config', + 'name', + 'alias', + 'has_alias', + 'field_info', + 'discriminator_key', + 'discriminator_alias', + 'validate_always', + 'allow_none', + 'shape', + 'class_validators', + 'parse_json', + ) + + def __init__( + self, + *, + name: str, + type_: Type[Any], + class_validators: Optional[Dict[str, Validator]], + model_config: Type['BaseConfig'], + default: Any = None, + default_factory: Optional[NoArgAnyCallable] = None, + required: 'BoolUndefined' = Undefined, + final: bool = False, + alias: Optional[str] = None, + field_info: Optional[FieldInfo] = None, + ) -> None: + self.name: str = name + self.has_alias: bool = alias is not None + self.alias: str = alias if alias is not None else name + self.annotation = type_ + self.type_: Any = convert_generics(type_) + self.outer_type_: Any = type_ + self.class_validators = class_validators or {} + self.default: Any = default + self.default_factory: Optional[NoArgAnyCallable] = default_factory + self.required: 'BoolUndefined' = required + self.final: bool = final + self.model_config = model_config + self.field_info: FieldInfo = field_info or FieldInfo(default) + self.discriminator_key: Optional[str] = self.field_info.discriminator + self.discriminator_alias: Optional[str] = self.discriminator_key + + self.allow_none: bool = False + self.validate_always: bool = False + self.sub_fields: Optional[List[ModelField]] = None + self.sub_fields_mapping: Optional[Dict[str, 'ModelField']] = None # used for discriminated union + self.key_field: Optional[ModelField] = None + self.validators: 'ValidatorsList' = [] + self.pre_validators: Optional['ValidatorsList'] = None + self.post_validators: Optional['ValidatorsList'] = None + self.parse_json: bool = False + self.shape: int = SHAPE_SINGLETON + self.model_config.prepare_field(self) + self.prepare() + + def get_default(self) -> Any: + return smart_deepcopy(self.default) if self.default_factory is None else self.default_factory() + + @staticmethod + def _get_field_info( + field_name: str, annotation: Any, value: Any, config: Type['BaseConfig'] + ) -> Tuple[FieldInfo, Any]: + """ + Get a FieldInfo from a root typing.Annotated annotation, value, or config default. + + The FieldInfo may be set in typing.Annotated or the value, but not both. If neither contain + a FieldInfo, a new one will be created using the config. + + :param field_name: name of the field for use in error messages + :param annotation: a type hint such as `str` or `Annotated[str, Field(..., min_length=5)]` + :param value: the field's assigned value + :param config: the model's config object + :return: the FieldInfo contained in the `annotation`, the value, or a new one from the config. + """ + field_info_from_config = config.get_field_info(field_name) + + field_info = None + if get_origin(annotation) is Annotated: + field_infos = [arg for arg in get_args(annotation)[1:] if isinstance(arg, FieldInfo)] + if len(field_infos) > 1: + raise ValueError(f'cannot specify multiple `Annotated` `Field`s for {field_name!r}') + field_info = next(iter(field_infos), None) + if field_info is not None: + field_info = copy.copy(field_info) + field_info.update_from_config(field_info_from_config) + if field_info.default not in (Undefined, Required): + raise ValueError(f'`Field` default cannot be set in `Annotated` for {field_name!r}') + if value is not Undefined and value is not Required: + # check also `Required` because of `validate_arguments` that sets `...` as default value + field_info.default = value + + if isinstance(value, FieldInfo): + if field_info is not None: + raise ValueError(f'cannot specify `Annotated` and value `Field`s together for {field_name!r}') + field_info = value + field_info.update_from_config(field_info_from_config) + elif field_info is None: + field_info = FieldInfo(value, **field_info_from_config) + value = None if field_info.default_factory is not None else field_info.default + field_info._validate() + return field_info, value + + @classmethod + def infer( + cls, + *, + name: str, + value: Any, + annotation: Any, + class_validators: Optional[Dict[str, Validator]], + config: Type['BaseConfig'], + ) -> 'ModelField': + from pydantic.schema import get_annotation_from_field_info + + field_info, value = cls._get_field_info(name, annotation, value, config) + required: 'BoolUndefined' = Undefined + if value is Required: + required = True + value = None + elif value is not Undefined: + required = False + annotation = get_annotation_from_field_info(annotation, field_info, name, config.validate_assignment) + + return cls( + name=name, + type_=annotation, + alias=field_info.alias, + class_validators=class_validators, + default=value, + default_factory=field_info.default_factory, + required=required, + model_config=config, + field_info=field_info, + ) + + def set_config(self, config: Type['BaseConfig']) -> None: + self.model_config = config + info_from_config = config.get_field_info(self.name) + config.prepare_field(self) + new_alias = info_from_config.get('alias') + new_alias_priority = info_from_config.get('alias_priority') or 0 + if new_alias and new_alias_priority >= (self.field_info.alias_priority or 0): + self.field_info.alias = new_alias + self.field_info.alias_priority = new_alias_priority + self.alias = new_alias + new_exclude = info_from_config.get('exclude') + if new_exclude is not None: + self.field_info.exclude = ValueItems.merge(self.field_info.exclude, new_exclude) + new_include = info_from_config.get('include') + if new_include is not None: + self.field_info.include = ValueItems.merge(self.field_info.include, new_include, intersect=True) + + @property + def alt_alias(self) -> bool: + return self.name != self.alias + + def prepare(self) -> None: + """ + Prepare the field but inspecting self.default, self.type_ etc. + + Note: this method is **not** idempotent (because _type_analysis is not idempotent), + e.g. calling it it multiple times may modify the field and configure it incorrectly. + """ + self._set_default_and_type() + if self.type_.__class__ is ForwardRef or self.type_.__class__ is DeferredType: + # self.type_ is currently a ForwardRef and there's nothing we can do now, + # user will need to call model.update_forward_refs() + return + + self._type_analysis() + if self.required is Undefined: + self.required = True + if self.default is Undefined and self.default_factory is None: + self.default = None + self.populate_validators() + + def _set_default_and_type(self) -> None: + """ + Set the default value, infer the type if needed and check if `None` value is valid. + """ + if self.default_factory is not None: + if self.type_ is Undefined: + raise errors_.ConfigError( + f'you need to set the type of field {self.name!r} when using `default_factory`' + ) + return + + default_value = self.get_default() + + if default_value is not None and self.type_ is Undefined: + self.type_ = default_value.__class__ + self.outer_type_ = self.type_ + self.annotation = self.type_ + + if self.type_ is Undefined: + raise errors_.ConfigError(f'unable to infer type for attribute "{self.name}"') + + if self.required is False and default_value is None: + self.allow_none = True + + def _type_analysis(self) -> None: # noqa: C901 (ignore complexity) + # typing interface is horrible, we have to do some ugly checks + if lenient_issubclass(self.type_, JsonWrapper): + self.type_ = self.type_.inner_type + self.parse_json = True + elif lenient_issubclass(self.type_, Json): + self.type_ = Any + self.parse_json = True + elif isinstance(self.type_, TypeVar): + if self.type_.__bound__: + self.type_ = self.type_.__bound__ + elif self.type_.__constraints__: + self.type_ = Union[self.type_.__constraints__] + else: + self.type_ = Any + elif is_new_type(self.type_): + self.type_ = new_type_supertype(self.type_) + + if self.type_ is Any or self.type_ is object: + if self.required is Undefined: + self.required = False + self.allow_none = True + return + elif self.type_ is Pattern or self.type_ is re.Pattern: + # python 3.7 only, Pattern is a typing object but without sub fields + return + elif is_literal_type(self.type_): + return + elif is_typeddict(self.type_): + return + + if is_finalvar(self.type_): + self.final = True + + if self.type_ is Final: + self.type_ = Any + else: + self.type_ = get_args(self.type_)[0] + + self._type_analysis() + return + + origin = get_origin(self.type_) + + if origin is Annotated or is_typeddict_special(origin): + self.type_ = get_args(self.type_)[0] + self._type_analysis() + return + + if self.discriminator_key is not None and not is_union(origin): + raise TypeError('`discriminator` can only be used with `Union` type with more than one variant') + + # add extra check for `collections.abc.Hashable` for python 3.10+ where origin is not `None` + if origin is None or origin is CollectionsHashable: + # field is not "typing" object eg. Union, Dict, List etc. + # allow None for virtual superclasses of NoneType, e.g. Hashable + if isinstance(self.type_, type) and isinstance(None, self.type_): + self.allow_none = True + return + elif origin is Callable: + return + elif is_union(origin): + types_ = [] + for type_ in get_args(self.type_): + if is_none_type(type_) or type_ is Any or type_ is object: + if self.required is Undefined: + self.required = False + self.allow_none = True + if is_none_type(type_): + continue + types_.append(type_) + + if len(types_) == 1: + # Optional[] + self.type_ = types_[0] + # this is the one case where the "outer type" isn't just the original type + self.outer_type_ = self.type_ + # re-run to correctly interpret the new self.type_ + self._type_analysis() + else: + self.sub_fields = [self._create_sub_type(t, f'{self.name}_{display_as_type(t)}') for t in types_] + + if self.discriminator_key is not None: + self.prepare_discriminated_union_sub_fields() + return + elif issubclass(origin, Tuple): # type: ignore + # origin == Tuple without item type + args = get_args(self.type_) + if not args: # plain tuple + self.type_ = Any + self.shape = SHAPE_TUPLE_ELLIPSIS + elif len(args) == 2 and args[1] is Ellipsis: # e.g. Tuple[int, ...] + self.type_ = args[0] + self.shape = SHAPE_TUPLE_ELLIPSIS + self.sub_fields = [self._create_sub_type(args[0], f'{self.name}_0')] + elif args == ((),): # Tuple[()] means empty tuple + self.shape = SHAPE_TUPLE + self.type_ = Any + self.sub_fields = [] + else: + self.shape = SHAPE_TUPLE + self.sub_fields = [self._create_sub_type(t, f'{self.name}_{i}') for i, t in enumerate(args)] + return + elif issubclass(origin, List): + # Create self validators + get_validators = getattr(self.type_, '__get_validators__', None) + if get_validators: + self.class_validators.update( + {f'list_{i}': Validator(validator, pre=True) for i, validator in enumerate(get_validators())} + ) + + self.type_ = get_args(self.type_)[0] + self.shape = SHAPE_LIST + elif issubclass(origin, Set): + # Create self validators + get_validators = getattr(self.type_, '__get_validators__', None) + if get_validators: + self.class_validators.update( + {f'set_{i}': Validator(validator, pre=True) for i, validator in enumerate(get_validators())} + ) + + self.type_ = get_args(self.type_)[0] + self.shape = SHAPE_SET + elif issubclass(origin, FrozenSet): + # Create self validators + get_validators = getattr(self.type_, '__get_validators__', None) + if get_validators: + self.class_validators.update( + {f'frozenset_{i}': Validator(validator, pre=True) for i, validator in enumerate(get_validators())} + ) + + self.type_ = get_args(self.type_)[0] + self.shape = SHAPE_FROZENSET + elif issubclass(origin, Deque): + self.type_ = get_args(self.type_)[0] + self.shape = SHAPE_DEQUE + elif issubclass(origin, Sequence): + self.type_ = get_args(self.type_)[0] + self.shape = SHAPE_SEQUENCE + # priority to most common mapping: dict + elif origin is dict or origin is Dict: + self.key_field = self._create_sub_type(get_args(self.type_)[0], 'key_' + self.name, for_keys=True) + self.type_ = get_args(self.type_)[1] + self.shape = SHAPE_DICT + elif issubclass(origin, DefaultDict): + self.key_field = self._create_sub_type(get_args(self.type_)[0], 'key_' + self.name, for_keys=True) + self.type_ = get_args(self.type_)[1] + self.shape = SHAPE_DEFAULTDICT + elif issubclass(origin, Counter): + self.key_field = self._create_sub_type(get_args(self.type_)[0], 'key_' + self.name, for_keys=True) + self.type_ = int + self.shape = SHAPE_COUNTER + elif issubclass(origin, Mapping): + self.key_field = self._create_sub_type(get_args(self.type_)[0], 'key_' + self.name, for_keys=True) + self.type_ = get_args(self.type_)[1] + self.shape = SHAPE_MAPPING + # Equality check as almost everything inherits form Iterable, including str + # check for Iterable and CollectionsIterable, as it could receive one even when declared with the other + elif origin in {Iterable, CollectionsIterable}: + self.type_ = get_args(self.type_)[0] + self.shape = SHAPE_ITERABLE + self.sub_fields = [self._create_sub_type(self.type_, f'{self.name}_type')] + elif issubclass(origin, Type): # type: ignore + return + elif hasattr(origin, '__get_validators__') or self.model_config.arbitrary_types_allowed: + # Is a Pydantic-compatible generic that handles itself + # or we have arbitrary_types_allowed = True + self.shape = SHAPE_GENERIC + self.sub_fields = [self._create_sub_type(t, f'{self.name}_{i}') for i, t in enumerate(get_args(self.type_))] + self.type_ = origin + return + else: + raise TypeError(f'Fields of type "{origin}" are not supported.') + + # type_ has been refined eg. as the type of a List and sub_fields needs to be populated + self.sub_fields = [self._create_sub_type(self.type_, '_' + self.name)] + + def prepare_discriminated_union_sub_fields(self) -> None: + """ + Prepare the mapping -> and update `sub_fields` + Note that this process can be aborted if a `ForwardRef` is encountered + """ + assert self.discriminator_key is not None + + if self.type_.__class__ is DeferredType: + return + + assert self.sub_fields is not None + sub_fields_mapping: Dict[str, 'ModelField'] = {} + all_aliases: Set[str] = set() + + for sub_field in self.sub_fields: + t = sub_field.type_ + if t.__class__ is ForwardRef: + # Stopping everything...will need to call `update_forward_refs` + return + + alias, discriminator_values = get_discriminator_alias_and_values(t, self.discriminator_key) + all_aliases.add(alias) + for discriminator_value in discriminator_values: + sub_fields_mapping[discriminator_value] = sub_field + + self.sub_fields_mapping = sub_fields_mapping + self.discriminator_alias = get_unique_discriminator_alias(all_aliases, self.discriminator_key) + + def _create_sub_type(self, type_: Type[Any], name: str, *, for_keys: bool = False) -> 'ModelField': + if for_keys: + class_validators = None + else: + # validators for sub items should not have `each_item` as we want to check only the first sublevel + class_validators = { + k: Validator( + func=v.func, + pre=v.pre, + each_item=False, + always=v.always, + check_fields=v.check_fields, + skip_on_failure=v.skip_on_failure, + ) + for k, v in self.class_validators.items() + if v.each_item + } + + field_info, _ = self._get_field_info(name, type_, None, self.model_config) + + return self.__class__( + type_=type_, + name=name, + class_validators=class_validators, + model_config=self.model_config, + field_info=field_info, + ) + + def populate_validators(self) -> None: + """ + Prepare self.pre_validators, self.validators, and self.post_validators based on self.type_'s __get_validators__ + and class validators. This method should be idempotent, e.g. it should be safe to call multiple times + without mis-configuring the field. + """ + self.validate_always = getattr(self.type_, 'validate_always', False) or any( + v.always for v in self.class_validators.values() + ) + + class_validators_ = self.class_validators.values() + if not self.sub_fields or self.shape == SHAPE_GENERIC: + get_validators = getattr(self.type_, '__get_validators__', None) + v_funcs = ( + *[v.func for v in class_validators_ if v.each_item and v.pre], + *(get_validators() if get_validators else list(find_validators(self.type_, self.model_config))), + *[v.func for v in class_validators_ if v.each_item and not v.pre], + ) + self.validators = prep_validators(v_funcs) + + self.pre_validators = [] + self.post_validators = [] + + if self.field_info and self.field_info.const: + self.post_validators.append(make_generic_validator(constant_validator)) + + if class_validators_: + self.pre_validators += prep_validators(v.func for v in class_validators_ if not v.each_item and v.pre) + self.post_validators += prep_validators(v.func for v in class_validators_ if not v.each_item and not v.pre) + + if self.parse_json: + self.pre_validators.append(make_generic_validator(validate_json)) + + self.pre_validators = self.pre_validators or None + self.post_validators = self.post_validators or None + + def validate( + self, v: Any, values: Dict[str, Any], *, loc: 'LocStr', cls: Optional['ModelOrDc'] = None + ) -> 'ValidateReturn': + assert self.type_.__class__ is not DeferredType + + if self.type_.__class__ is ForwardRef: + assert cls is not None + raise ConfigError( + f'field "{self.name}" not yet prepared so type is still a ForwardRef, ' + f'you might need to call {cls.__name__}.update_forward_refs().' + ) + + errors: Optional['ErrorList'] + if self.pre_validators: + v, errors = self._apply_validators(v, values, loc, cls, self.pre_validators) + if errors: + return v, errors + + if v is None: + if is_none_type(self.type_): + # keep validating + pass + elif self.allow_none: + if self.post_validators: + return self._apply_validators(v, values, loc, cls, self.post_validators) + else: + return None, None + else: + return v, ErrorWrapper(NoneIsNotAllowedError(), loc) + + if self.shape == SHAPE_SINGLETON: + v, errors = self._validate_singleton(v, values, loc, cls) + elif self.shape in MAPPING_LIKE_SHAPES: + v, errors = self._validate_mapping_like(v, values, loc, cls) + elif self.shape == SHAPE_TUPLE: + v, errors = self._validate_tuple(v, values, loc, cls) + elif self.shape == SHAPE_ITERABLE: + v, errors = self._validate_iterable(v, values, loc, cls) + elif self.shape == SHAPE_GENERIC: + v, errors = self._apply_validators(v, values, loc, cls, self.validators) + else: + # sequence, list, set, generator, tuple with ellipsis, frozen set + v, errors = self._validate_sequence_like(v, values, loc, cls) + + if not errors and self.post_validators: + v, errors = self._apply_validators(v, values, loc, cls, self.post_validators) + return v, errors + + def _validate_sequence_like( # noqa: C901 (ignore complexity) + self, v: Any, values: Dict[str, Any], loc: 'LocStr', cls: Optional['ModelOrDc'] + ) -> 'ValidateReturn': + """ + Validate sequence-like containers: lists, tuples, sets and generators + Note that large if-else blocks are necessary to enable Cython + optimization, which is why we disable the complexity check above. + """ + if not sequence_like(v): + e: errors_.PydanticTypeError + if self.shape == SHAPE_LIST: + e = errors_.ListError() + elif self.shape in (SHAPE_TUPLE, SHAPE_TUPLE_ELLIPSIS): + e = errors_.TupleError() + elif self.shape == SHAPE_SET: + e = errors_.SetError() + elif self.shape == SHAPE_FROZENSET: + e = errors_.FrozenSetError() + else: + e = errors_.SequenceError() + return v, ErrorWrapper(e, loc) + + loc = loc if isinstance(loc, tuple) else (loc,) + result = [] + errors: List[ErrorList] = [] + for i, v_ in enumerate(v): + v_loc = *loc, i + r, ee = self._validate_singleton(v_, values, v_loc, cls) + if ee: + errors.append(ee) + else: + result.append(r) + + if errors: + return v, errors + + converted: Union[List[Any], Set[Any], FrozenSet[Any], Tuple[Any, ...], Iterator[Any], Deque[Any]] = result + + if self.shape == SHAPE_SET: + converted = set(result) + elif self.shape == SHAPE_FROZENSET: + converted = frozenset(result) + elif self.shape == SHAPE_TUPLE_ELLIPSIS: + converted = tuple(result) + elif self.shape == SHAPE_DEQUE: + converted = deque(result, maxlen=getattr(v, 'maxlen', None)) + elif self.shape == SHAPE_SEQUENCE: + if isinstance(v, tuple): + converted = tuple(result) + elif isinstance(v, set): + converted = set(result) + elif isinstance(v, Generator): + converted = iter(result) + elif isinstance(v, deque): + converted = deque(result, maxlen=getattr(v, 'maxlen', None)) + return converted, None + + def _validate_iterable( + self, v: Any, values: Dict[str, Any], loc: 'LocStr', cls: Optional['ModelOrDc'] + ) -> 'ValidateReturn': + """ + Validate Iterables. + + This intentionally doesn't validate values to allow infinite generators. + """ + + try: + iterable = iter(v) + except TypeError: + return v, ErrorWrapper(errors_.IterableError(), loc) + return iterable, None + + def _validate_tuple( + self, v: Any, values: Dict[str, Any], loc: 'LocStr', cls: Optional['ModelOrDc'] + ) -> 'ValidateReturn': + e: Optional[Exception] = None + if not sequence_like(v): + e = errors_.TupleError() + else: + actual_length, expected_length = len(v), len(self.sub_fields) # type: ignore + if actual_length != expected_length: + e = errors_.TupleLengthError(actual_length=actual_length, expected_length=expected_length) + + if e: + return v, ErrorWrapper(e, loc) + + loc = loc if isinstance(loc, tuple) else (loc,) + result = [] + errors: List[ErrorList] = [] + for i, (v_, field) in enumerate(zip(v, self.sub_fields)): # type: ignore + v_loc = *loc, i + r, ee = field.validate(v_, values, loc=v_loc, cls=cls) + if ee: + errors.append(ee) + else: + result.append(r) + + if errors: + return v, errors + else: + return tuple(result), None + + def _validate_mapping_like( + self, v: Any, values: Dict[str, Any], loc: 'LocStr', cls: Optional['ModelOrDc'] + ) -> 'ValidateReturn': + try: + v_iter = dict_validator(v) + except TypeError as exc: + return v, ErrorWrapper(exc, loc) + + loc = loc if isinstance(loc, tuple) else (loc,) + result, errors = {}, [] + for k, v_ in v_iter.items(): + v_loc = *loc, '__key__' + key_result, key_errors = self.key_field.validate(k, values, loc=v_loc, cls=cls) # type: ignore + if key_errors: + errors.append(key_errors) + continue + + v_loc = *loc, k + value_result, value_errors = self._validate_singleton(v_, values, v_loc, cls) + if value_errors: + errors.append(value_errors) + continue + + result[key_result] = value_result + if errors: + return v, errors + elif self.shape == SHAPE_DICT: + return result, None + elif self.shape == SHAPE_DEFAULTDICT: + return defaultdict(self.type_, result), None + elif self.shape == SHAPE_COUNTER: + return CollectionCounter(result), None + else: + return self._get_mapping_value(v, result), None + + def _get_mapping_value(self, original: T, converted: Dict[Any, Any]) -> Union[T, Dict[Any, Any]]: + """ + When type is `Mapping[KT, KV]` (or another unsupported mapping), we try to avoid + coercing to `dict` unwillingly. + """ + original_cls = original.__class__ + + if original_cls == dict or original_cls == Dict: + return converted + elif original_cls in {defaultdict, DefaultDict}: + return defaultdict(self.type_, converted) + else: + try: + # Counter, OrderedDict, UserDict, ... + return original_cls(converted) # type: ignore + except TypeError: + raise RuntimeError(f'Could not convert dictionary to {original_cls.__name__!r}') from None + + def _validate_singleton( + self, v: Any, values: Dict[str, Any], loc: 'LocStr', cls: Optional['ModelOrDc'] + ) -> 'ValidateReturn': + if self.sub_fields: + if self.discriminator_key is not None: + return self._validate_discriminated_union(v, values, loc, cls) + + errors = [] + + if self.model_config.smart_union and is_union(get_origin(self.type_)): + # 1st pass: check if the value is an exact instance of one of the Union types + # (e.g. to avoid coercing a bool into an int) + for field in self.sub_fields: + if v.__class__ is field.outer_type_: + return v, None + + # 2nd pass: check if the value is an instance of any subclass of the Union types + for field in self.sub_fields: + # This whole logic will be improved later on to support more complex `isinstance` checks + # It will probably be done once a strict mode is added and be something like: + # ``` + # value, error = field.validate(v, values, strict=True) + # if error is None: + # return value, None + # ``` + try: + if isinstance(v, field.outer_type_): + return v, None + except TypeError: + # compound type + if lenient_isinstance(v, get_origin(field.outer_type_)): + value, error = field.validate(v, values, loc=loc, cls=cls) + if not error: + return value, None + + # 1st pass by default or 3rd pass with `smart_union` enabled: + # check if the value can be coerced into one of the Union types + for field in self.sub_fields: + value, error = field.validate(v, values, loc=loc, cls=cls) + if error: + errors.append(error) + else: + return value, None + return v, errors + else: + return self._apply_validators(v, values, loc, cls, self.validators) + + def _validate_discriminated_union( + self, v: Any, values: Dict[str, Any], loc: 'LocStr', cls: Optional['ModelOrDc'] + ) -> 'ValidateReturn': + assert self.discriminator_key is not None + assert self.discriminator_alias is not None + + try: + try: + discriminator_value = v[self.discriminator_alias] + except KeyError: + if self.model_config.allow_population_by_field_name: + discriminator_value = v[self.discriminator_key] + else: + raise + except KeyError: + return v, ErrorWrapper(MissingDiscriminator(discriminator_key=self.discriminator_key), loc) + except TypeError: + try: + # BaseModel or dataclass + discriminator_value = getattr(v, self.discriminator_key) + except (AttributeError, TypeError): + return v, ErrorWrapper(MissingDiscriminator(discriminator_key=self.discriminator_key), loc) + + if self.sub_fields_mapping is None: + assert cls is not None + raise ConfigError( + f'field "{self.name}" not yet prepared so type is still a ForwardRef, ' + f'you might need to call {cls.__name__}.update_forward_refs().' + ) + + try: + sub_field = self.sub_fields_mapping[discriminator_value] + except (KeyError, TypeError): + # KeyError: `discriminator_value` is not in the dictionary. + # TypeError: `discriminator_value` is unhashable. + assert self.sub_fields_mapping is not None + return v, ErrorWrapper( + InvalidDiscriminator( + discriminator_key=self.discriminator_key, + discriminator_value=discriminator_value, + allowed_values=list(self.sub_fields_mapping), + ), + loc, + ) + else: + if not isinstance(loc, tuple): + loc = (loc,) + return sub_field.validate(v, values, loc=(*loc, display_as_type(sub_field.type_)), cls=cls) + + def _apply_validators( + self, v: Any, values: Dict[str, Any], loc: 'LocStr', cls: Optional['ModelOrDc'], validators: 'ValidatorsList' + ) -> 'ValidateReturn': + for validator in validators: + try: + v = validator(cls, v, values, self, self.model_config) + except (ValueError, TypeError, AssertionError) as exc: + return v, ErrorWrapper(exc, loc) + return v, None + + def is_complex(self) -> bool: + """ + Whether the field is "complex" eg. env variables should be parsed as JSON. + """ + from pydantic.main import BaseModel + + return ( + self.shape != SHAPE_SINGLETON + or hasattr(self.type_, '__pydantic_model__') + or lenient_issubclass(self.type_, (BaseModel, list, set, frozenset, dict)) + ) + + def _type_display(self) -> PyObjectStr: + t = display_as_type(self.type_) + + if self.shape in MAPPING_LIKE_SHAPES: + t = f'Mapping[{display_as_type(self.key_field.type_)}, {t}]' # type: ignore + elif self.shape == SHAPE_TUPLE: + t = 'Tuple[{}]'.format(', '.join(display_as_type(f.type_) for f in self.sub_fields)) # type: ignore + elif self.shape == SHAPE_GENERIC: + assert self.sub_fields + t = '{}[{}]'.format( + display_as_type(self.type_), ', '.join(display_as_type(f.type_) for f in self.sub_fields) + ) + elif self.shape != SHAPE_SINGLETON: + t = SHAPE_NAME_LOOKUP[self.shape].format(t) + + if self.allow_none and (self.shape != SHAPE_SINGLETON or not self.sub_fields): + t = f'Optional[{t}]' + return PyObjectStr(t) + + def __repr_args__(self) -> 'ReprArgs': + args = [('name', self.name), ('type', self._type_display()), ('required', self.required)] + + if not self.required: + if self.default_factory is not None: + args.append(('default_factory', f'')) + else: + args.append(('default', self.default)) + + if self.alt_alias: + args.append(('alias', self.alias)) + return args + + +class ModelPrivateAttr(Representation): + __slots__ = ('default', 'default_factory') + + def __init__(self, default: Any = Undefined, *, default_factory: Optional[NoArgAnyCallable] = None) -> None: + self.default = default + self.default_factory = default_factory + + def get_default(self) -> Any: + return smart_deepcopy(self.default) if self.default_factory is None else self.default_factory() + + def __eq__(self, other: Any) -> bool: + return isinstance(other, self.__class__) and (self.default, self.default_factory) == ( + other.default, + other.default_factory, + ) + + +def PrivateAttr( + default: Any = Undefined, + *, + default_factory: Optional[NoArgAnyCallable] = None, +) -> Any: + """ + Indicates that attribute is only used internally and never mixed with regular fields. + + Types or values of private attrs are not checked by pydantic and it's up to you to keep them relevant. + + Private attrs are stored in model __slots__. + + :param default: the attribute’s default value + :param default_factory: callable that will be called when a default value is needed for this attribute + If both `default` and `default_factory` are set, an error is raised. + """ + if default is not Undefined and default_factory is not None: + raise ValueError('cannot specify both default and default_factory') + + return ModelPrivateAttr( + default, + default_factory=default_factory, + ) + + +class DeferredType: + """ + Used to postpone field preparation, while creating recursive generic models. + """ + + +def is_finalvar_with_default_val(type_: Type[Any], val: Any) -> bool: + return is_finalvar(type_) and val is not Undefined and not isinstance(val, FieldInfo) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/generics.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/generics.py new file mode 100644 index 0000000..9977e45 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/generics.py @@ -0,0 +1,400 @@ +import sys +import types +import typing +from typing import ( + TYPE_CHECKING, + Any, + ClassVar, + Dict, + ForwardRef, + Generic, + Iterator, + List, + Mapping, + Optional, + Tuple, + Type, + TypeVar, + Union, + cast, +) +from weakref import WeakKeyDictionary, WeakValueDictionary + +from typing_extensions import Annotated, Literal as ExtLiteral + +from pydantic.class_validators import gather_all_validators +from pydantic.fields import DeferredType +from pydantic.main import BaseModel, create_model +from pydantic.types import JsonWrapper +from pydantic.typing import display_as_type, get_all_type_hints, get_args, get_origin, typing_base +from pydantic.utils import all_identical, lenient_issubclass + +if sys.version_info >= (3, 10): + from typing import _UnionGenericAlias +if sys.version_info >= (3, 8): + from typing import Literal + +GenericModelT = TypeVar('GenericModelT', bound='GenericModel') +TypeVarType = Any # since mypy doesn't allow the use of TypeVar as a type + +CacheKey = Tuple[Type[Any], Any, Tuple[Any, ...]] +Parametrization = Mapping[TypeVarType, Type[Any]] + +# weak dictionaries allow the dynamically created parametrized versions of generic models to get collected +# once they are no longer referenced by the caller. +if sys.version_info >= (3, 9): # Typing for weak dictionaries available at 3.9 + GenericTypesCache = WeakValueDictionary[CacheKey, Type[BaseModel]] + AssignedParameters = WeakKeyDictionary[Type[BaseModel], Parametrization] +else: + GenericTypesCache = WeakValueDictionary + AssignedParameters = WeakKeyDictionary + +# _generic_types_cache is a Mapping from __class_getitem__ arguments to the parametrized version of generic models. +# This ensures multiple calls of e.g. A[B] return always the same class. +_generic_types_cache = GenericTypesCache() + +# _assigned_parameters is a Mapping from parametrized version of generic models to assigned types of parametrizations +# as captured during construction of the class (not instances). +# E.g., for generic model `Model[A, B]`, when parametrized model `Model[int, str]` is created, +# `Model[int, str]`: {A: int, B: str}` will be stored in `_assigned_parameters`. +# (This information is only otherwise available after creation from the class name string). +_assigned_parameters = AssignedParameters() + + +class GenericModel(BaseModel): + __slots__ = () + __concrete__: ClassVar[bool] = False + + if TYPE_CHECKING: + # Putting this in a TYPE_CHECKING block allows us to replace `if Generic not in cls.__bases__` with + # `not hasattr(cls, "__parameters__")`. This means we don't need to force non-concrete subclasses of + # `GenericModel` to also inherit from `Generic`, which would require changes to the use of `create_model` below. + __parameters__: ClassVar[Tuple[TypeVarType, ...]] + + # Setting the return type as Type[Any] instead of Type[BaseModel] prevents PyCharm warnings + def __class_getitem__(cls: Type[GenericModelT], params: Union[Type[Any], Tuple[Type[Any], ...]]) -> Type[Any]: + """Instantiates a new class from a generic class `cls` and type variables `params`. + + :param params: Tuple of types the class . Given a generic class + `Model` with 2 type variables and a concrete model `Model[str, int]`, + the value `(str, int)` would be passed to `params`. + :return: New model class inheriting from `cls` with instantiated + types described by `params`. If no parameters are given, `cls` is + returned as is. + + """ + + def _cache_key(_params: Any) -> CacheKey: + args = get_args(_params) + # python returns a list for Callables, which is not hashable + if len(args) == 2 and isinstance(args[0], list): + args = (tuple(args[0]), args[1]) + return cls, _params, args + + cached = _generic_types_cache.get(_cache_key(params)) + if cached is not None: + return cached + if cls.__concrete__ and Generic not in cls.__bases__: + raise TypeError('Cannot parameterize a concrete instantiation of a generic model') + if not isinstance(params, tuple): + params = (params,) + if cls is GenericModel and any(isinstance(param, TypeVar) for param in params): + raise TypeError('Type parameters should be placed on typing.Generic, not GenericModel') + if not hasattr(cls, '__parameters__'): + raise TypeError(f'Type {cls.__name__} must inherit from typing.Generic before being parameterized') + + check_parameters_count(cls, params) + # Build map from generic typevars to passed params + typevars_map: Dict[TypeVarType, Type[Any]] = dict(zip(cls.__parameters__, params)) + if all_identical(typevars_map.keys(), typevars_map.values()) and typevars_map: + return cls # if arguments are equal to parameters it's the same object + + # Create new model with original model as parent inserting fields with DeferredType. + model_name = cls.__concrete_name__(params) + validators = gather_all_validators(cls) + + type_hints = get_all_type_hints(cls).items() + instance_type_hints = {k: v for k, v in type_hints if get_origin(v) is not ClassVar} + + fields = {k: (DeferredType(), cls.__fields__[k].field_info) for k in instance_type_hints if k in cls.__fields__} + + model_module, called_globally = get_caller_frame_info() + created_model = cast( + Type[GenericModel], # casting ensures mypy is aware of the __concrete__ and __parameters__ attributes + create_model( + model_name, + __module__=model_module or cls.__module__, + __base__=(cls,) + tuple(cls.__parameterized_bases__(typevars_map)), + __config__=None, + __validators__=validators, + __cls_kwargs__=None, + **fields, + ), + ) + + _assigned_parameters[created_model] = typevars_map + + if called_globally: # create global reference and therefore allow pickling + object_by_reference = None + reference_name = model_name + reference_module_globals = sys.modules[created_model.__module__].__dict__ + while object_by_reference is not created_model: + object_by_reference = reference_module_globals.setdefault(reference_name, created_model) + reference_name += '_' + + created_model.Config = cls.Config + + # Find any typevars that are still present in the model. + # If none are left, the model is fully "concrete", otherwise the new + # class is a generic class as well taking the found typevars as + # parameters. + new_params = tuple( + {param: None for param in iter_contained_typevars(typevars_map.values())} + ) # use dict as ordered set + created_model.__concrete__ = not new_params + if new_params: + created_model.__parameters__ = new_params + + # Save created model in cache so we don't end up creating duplicate + # models that should be identical. + _generic_types_cache[_cache_key(params)] = created_model + if len(params) == 1: + _generic_types_cache[_cache_key(params[0])] = created_model + + # Recursively walk class type hints and replace generic typevars + # with concrete types that were passed. + _prepare_model_fields(created_model, fields, instance_type_hints, typevars_map) + + return created_model + + @classmethod + def __concrete_name__(cls: Type[Any], params: Tuple[Type[Any], ...]) -> str: + """Compute class name for child classes. + + :param params: Tuple of types the class . Given a generic class + `Model` with 2 type variables and a concrete model `Model[str, int]`, + the value `(str, int)` would be passed to `params`. + :return: String representing a the new class where `params` are + passed to `cls` as type variables. + + This method can be overridden to achieve a custom naming scheme for GenericModels. + """ + param_names = [display_as_type(param) for param in params] + params_component = ', '.join(param_names) + return f'{cls.__name__}[{params_component}]' + + @classmethod + def __parameterized_bases__(cls, typevars_map: Parametrization) -> Iterator[Type[Any]]: + """ + Returns unbound bases of cls parameterised to given type variables + + :param typevars_map: Dictionary of type applications for binding subclasses. + Given a generic class `Model` with 2 type variables [S, T] + and a concrete model `Model[str, int]`, + the value `{S: str, T: int}` would be passed to `typevars_map`. + :return: an iterator of generic sub classes, parameterised by `typevars_map` + and other assigned parameters of `cls` + + e.g.: + ``` + class A(GenericModel, Generic[T]): + ... + + class B(A[V], Generic[V]): + ... + + assert A[int] in B.__parameterized_bases__({V: int}) + ``` + """ + + def build_base_model( + base_model: Type[GenericModel], mapped_types: Parametrization + ) -> Iterator[Type[GenericModel]]: + base_parameters = tuple(mapped_types[param] for param in base_model.__parameters__) + parameterized_base = base_model.__class_getitem__(base_parameters) + if parameterized_base is base_model or parameterized_base is cls: + # Avoid duplication in MRO + return + yield parameterized_base + + for base_model in cls.__bases__: + if not issubclass(base_model, GenericModel): + # not a class that can be meaningfully parameterized + continue + elif not getattr(base_model, '__parameters__', None): + # base_model is "GenericModel" (and has no __parameters__) + # or + # base_model is already concrete, and will be included transitively via cls. + continue + elif cls in _assigned_parameters: + if base_model in _assigned_parameters: + # cls is partially parameterised but not from base_model + # e.g. cls = B[S], base_model = A[S] + # B[S][int] should subclass A[int], (and will be transitively via B[int]) + # but it's not viable to consistently subclass types with arbitrary construction + # So don't attempt to include A[S][int] + continue + else: # base_model not in _assigned_parameters: + # cls is partially parameterized, base_model is original generic + # e.g. cls = B[str, T], base_model = B[S, T] + # Need to determine the mapping for the base_model parameters + mapped_types: Parametrization = { + key: typevars_map.get(value, value) for key, value in _assigned_parameters[cls].items() + } + yield from build_base_model(base_model, mapped_types) + else: + # cls is base generic, so base_class has a distinct base + # can construct the Parameterised base model using typevars_map directly + yield from build_base_model(base_model, typevars_map) + + +def replace_types(type_: Any, type_map: Mapping[Any, Any]) -> Any: + """Return type with all occurrences of `type_map` keys recursively replaced with their values. + + :param type_: Any type, class or generic alias + :param type_map: Mapping from `TypeVar` instance to concrete types. + :return: New type representing the basic structure of `type_` with all + `typevar_map` keys recursively replaced. + + >>> replace_types(Tuple[str, Union[List[str], float]], {str: int}) + Tuple[int, Union[List[int], float]] + + """ + if not type_map: + return type_ + + type_args = get_args(type_) + origin_type = get_origin(type_) + + if origin_type is Annotated: + annotated_type, *annotations = type_args + return Annotated[replace_types(annotated_type, type_map), tuple(annotations)] + + if (origin_type is ExtLiteral) or (sys.version_info >= (3, 8) and origin_type is Literal): + return type_map.get(type_, type_) + # Having type args is a good indicator that this is a typing module + # class instantiation or a generic alias of some sort. + if type_args: + resolved_type_args = tuple(replace_types(arg, type_map) for arg in type_args) + if all_identical(type_args, resolved_type_args): + # If all arguments are the same, there is no need to modify the + # type or create a new object at all + return type_ + if ( + origin_type is not None + and isinstance(type_, typing_base) + and not isinstance(origin_type, typing_base) + and getattr(type_, '_name', None) is not None + ): + # In python < 3.9 generic aliases don't exist so any of these like `list`, + # `type` or `collections.abc.Callable` need to be translated. + # See: https://www.python.org/dev/peps/pep-0585 + origin_type = getattr(typing, type_._name) + assert origin_type is not None + # PEP-604 syntax (Ex.: list | str) is represented with a types.UnionType object that does not have __getitem__. + # We also cannot use isinstance() since we have to compare types. + if sys.version_info >= (3, 10) and origin_type is types.UnionType: # noqa: E721 + return _UnionGenericAlias(origin_type, resolved_type_args) + return origin_type[resolved_type_args] + + # We handle pydantic generic models separately as they don't have the same + # semantics as "typing" classes or generic aliases + if not origin_type and lenient_issubclass(type_, GenericModel) and not type_.__concrete__: + type_args = type_.__parameters__ + resolved_type_args = tuple(replace_types(t, type_map) for t in type_args) + if all_identical(type_args, resolved_type_args): + return type_ + return type_[resolved_type_args] + + # Handle special case for typehints that can have lists as arguments. + # `typing.Callable[[int, str], int]` is an example for this. + if isinstance(type_, (List, list)): + resolved_list = list(replace_types(element, type_map) for element in type_) + if all_identical(type_, resolved_list): + return type_ + return resolved_list + + # For JsonWrapperValue, need to handle its inner type to allow correct parsing + # of generic Json arguments like Json[T] + if not origin_type and lenient_issubclass(type_, JsonWrapper): + type_.inner_type = replace_types(type_.inner_type, type_map) + return type_ + + # If all else fails, we try to resolve the type directly and otherwise just + # return the input with no modifications. + new_type = type_map.get(type_, type_) + # Convert string to ForwardRef + if isinstance(new_type, str): + return ForwardRef(new_type) + else: + return new_type + + +def check_parameters_count(cls: Type[GenericModel], parameters: Tuple[Any, ...]) -> None: + actual = len(parameters) + expected = len(cls.__parameters__) + if actual != expected: + description = 'many' if actual > expected else 'few' + raise TypeError(f'Too {description} parameters for {cls.__name__}; actual {actual}, expected {expected}') + + +DictValues: Type[Any] = {}.values().__class__ + + +def iter_contained_typevars(v: Any) -> Iterator[TypeVarType]: + """Recursively iterate through all subtypes and type args of `v` and yield any typevars that are found.""" + if isinstance(v, TypeVar): + yield v + elif hasattr(v, '__parameters__') and not get_origin(v) and lenient_issubclass(v, GenericModel): + yield from v.__parameters__ + elif isinstance(v, (DictValues, list)): + for var in v: + yield from iter_contained_typevars(var) + else: + args = get_args(v) + for arg in args: + yield from iter_contained_typevars(arg) + + +def get_caller_frame_info() -> Tuple[Optional[str], bool]: + """ + Used inside a function to check whether it was called globally + + Will only work against non-compiled code, therefore used only in pydantic.generics + + :returns Tuple[module_name, called_globally] + """ + try: + previous_caller_frame = sys._getframe(2) + except ValueError as e: + raise RuntimeError('This function must be used inside another function') from e + except AttributeError: # sys module does not have _getframe function, so there's nothing we can do about it + return None, False + frame_globals = previous_caller_frame.f_globals + return frame_globals.get('__name__'), previous_caller_frame.f_locals is frame_globals + + +def _prepare_model_fields( + created_model: Type[GenericModel], + fields: Mapping[str, Any], + instance_type_hints: Mapping[str, type], + typevars_map: Mapping[Any, type], +) -> None: + """ + Replace DeferredType fields with concrete type hints and prepare them. + """ + + for key, field in created_model.__fields__.items(): + if key not in fields: + assert field.type_.__class__ is not DeferredType + # https://github.com/nedbat/coveragepy/issues/198 + continue # pragma: no cover + + assert field.type_.__class__ is DeferredType, field.type_.__class__ + + field_type_hint = instance_type_hints[key] + concrete_type = replace_types(field_type_hint, typevars_map) + field.type_ = concrete_type + field.outer_type_ = concrete_type + field.prepare() + created_model.__annotations__[key] = concrete_type diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/json.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/json.py new file mode 100644 index 0000000..73e15e4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/json.py @@ -0,0 +1,112 @@ +import datetime +from collections import deque +from decimal import Decimal +from enum import Enum +from ipaddress import IPv4Address, IPv4Interface, IPv4Network, IPv6Address, IPv6Interface, IPv6Network +from pathlib import Path +from re import Pattern +from types import GeneratorType +from typing import Any, Callable, Dict, Type, Union +from uuid import UUID + +from pydantic.color import Color +from pydantic.networks import NameEmail +from pydantic.types import SecretBytes, SecretStr + +__all__ = 'pydantic_encoder', 'custom_pydantic_encoder', 'timedelta_isoformat' + + +def isoformat(o: Union[datetime.date, datetime.time]) -> str: + return o.isoformat() + + +def decimal_encoder(dec_value: Decimal) -> Union[int, float]: + """ + Encodes a Decimal as int of there's no exponent, otherwise float + + This is useful when we use ConstrainedDecimal to represent Numeric(x,0) + where a integer (but not int typed) is used. Encoding this as a float + results in failed round-tripping between encode and parse. + Our Id type is a prime example of this. + + >>> decimal_encoder(Decimal("1.0")) + 1.0 + + >>> decimal_encoder(Decimal("1")) + 1 + """ + if dec_value.as_tuple().exponent >= 0: + return int(dec_value) + else: + return float(dec_value) + + +ENCODERS_BY_TYPE: Dict[Type[Any], Callable[[Any], Any]] = { + bytes: lambda o: o.decode(), + Color: str, + datetime.date: isoformat, + datetime.datetime: isoformat, + datetime.time: isoformat, + datetime.timedelta: lambda td: td.total_seconds(), + Decimal: decimal_encoder, + Enum: lambda o: o.value, + frozenset: list, + deque: list, + GeneratorType: list, + IPv4Address: str, + IPv4Interface: str, + IPv4Network: str, + IPv6Address: str, + IPv6Interface: str, + IPv6Network: str, + NameEmail: str, + Path: str, + Pattern: lambda o: o.pattern, + SecretBytes: str, + SecretStr: str, + set: list, + UUID: str, +} + + +def pydantic_encoder(obj: Any) -> Any: + from dataclasses import asdict, is_dataclass + + from pydantic.main import BaseModel + + if isinstance(obj, BaseModel): + return obj.dict() + elif is_dataclass(obj): + return asdict(obj) + + # Check the class type and its superclasses for a matching encoder + for base in obj.__class__.__mro__[:-1]: + try: + encoder = ENCODERS_BY_TYPE[base] + except KeyError: + continue + return encoder(obj) + else: # We have exited the for loop without finding a suitable encoder + raise TypeError(f"Object of type '{obj.__class__.__name__}' is not JSON serializable") + + +def custom_pydantic_encoder(type_encoders: Dict[Any, Callable[[Type[Any]], Any]], obj: Any) -> Any: + # Check the class type and its superclasses for a matching encoder + for base in obj.__class__.__mro__[:-1]: + try: + encoder = type_encoders[base] + except KeyError: + continue + + return encoder(obj) + else: # We have exited the for loop without finding a suitable encoder + return pydantic_encoder(obj) + + +def timedelta_isoformat(td: datetime.timedelta) -> str: + """ + ISO 8601 encoding for Python timedelta object. + """ + minutes, seconds = divmod(td.seconds, 60) + hours, minutes = divmod(minutes, 60) + return f'{"-" if td.days < 0 else ""}P{abs(td.days)}DT{hours:d}H{minutes:d}M{seconds:d}.{td.microseconds:06d}S' diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/main.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/main.py new file mode 100644 index 0000000..f26ee46 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/main.py @@ -0,0 +1,1107 @@ +import warnings +from abc import ABCMeta +from copy import deepcopy +from enum import Enum +from functools import partial +from pathlib import Path +from types import FunctionType, prepare_class, resolve_bases +from typing import ( + TYPE_CHECKING, + AbstractSet, + Any, + Callable, + ClassVar, + Dict, + List, + Mapping, + Optional, + Tuple, + Type, + TypeVar, + Union, + cast, + no_type_check, + overload, +) + +from typing_extensions import dataclass_transform + +from pydantic.class_validators import ValidatorGroup, extract_root_validators, extract_validators, inherit_validators +from pydantic.config import BaseConfig, Extra, inherit_config, prepare_config +from pydantic.error_wrappers import ErrorWrapper, ValidationError +from pydantic.errors import ConfigError, DictError, ExtraError, MissingError +from pydantic.fields import ( + MAPPING_LIKE_SHAPES, + Field, + ModelField, + ModelPrivateAttr, + PrivateAttr, + Undefined, + is_finalvar_with_default_val, +) +from pydantic.json import custom_pydantic_encoder, pydantic_encoder +from pydantic.parse import Protocol, load_file, load_str_bytes +from pydantic.schema import default_ref_template, model_schema +from pydantic.types import PyObject, StrBytes +from pydantic.typing import ( + AnyCallable, + get_args, + get_origin, + is_classvar, + is_namedtuple, + is_union, + resolve_annotations, + update_model_forward_refs, +) +from pydantic.utils import ( + DUNDER_ATTRIBUTES, + ROOT_KEY, + ClassAttribute, + GetterDict, + Representation, + ValueItems, + generate_model_signature, + is_valid_field, + is_valid_private_name, + lenient_issubclass, + sequence_like, + smart_deepcopy, + unique_list, + validate_field_name, +) + +if TYPE_CHECKING: + from inspect import Signature + + from pydantic.class_validators import ValidatorListDict + from pydantic.types import ModelOrDc + from pydantic.typing import ( + AbstractSetIntStr, + AnyClassMethod, + CallableGenerator, + DictAny, + DictStrAny, + MappingIntStrAny, + ReprArgs, + SetStr, + TupleGenerator, + ) + + Model = TypeVar('Model', bound='BaseModel') + +__all__ = 'BaseModel', 'create_model', 'validate_model' + +_T = TypeVar('_T') + + +def validate_custom_root_type(fields: Dict[str, ModelField]) -> None: + if len(fields) > 1: + raise ValueError(f'{ROOT_KEY} cannot be mixed with other fields') + + +def generate_hash_function(frozen: bool) -> Optional[Callable[[Any], int]]: + def hash_function(self_: Any) -> int: + return hash(self_.__class__) + hash(tuple(self_.__dict__.values())) + + return hash_function if frozen else None + + +# If a field is of type `Callable`, its default value should be a function and cannot to ignored. +ANNOTATED_FIELD_UNTOUCHED_TYPES: Tuple[Any, ...] = (property, type, classmethod, staticmethod) +# When creating a `BaseModel` instance, we bypass all the methods, properties... added to the model +UNTOUCHED_TYPES: Tuple[Any, ...] = (FunctionType,) + ANNOTATED_FIELD_UNTOUCHED_TYPES +# Note `ModelMetaclass` refers to `BaseModel`, but is also used to *create* `BaseModel`, so we need to add this extra +# (somewhat hacky) boolean to keep track of whether we've created the `BaseModel` class yet, and therefore whether it's +# safe to refer to it. If it *hasn't* been created, we assume that the `__new__` call we're in the middle of is for +# the `BaseModel` class, since that's defined immediately after the metaclass. +_is_base_model_class_defined = False + + +@dataclass_transform(kw_only_default=True, field_specifiers=(Field,)) +class ModelMetaclass(ABCMeta): + @no_type_check # noqa C901 + def __new__(mcs, name, bases, namespace, **kwargs): # noqa C901 + fields: Dict[str, ModelField] = {} + config = BaseConfig + validators: 'ValidatorListDict' = {} + + pre_root_validators, post_root_validators = [], [] + private_attributes: Dict[str, ModelPrivateAttr] = {} + base_private_attributes: Dict[str, ModelPrivateAttr] = {} + slots: SetStr = namespace.get('__slots__', ()) + slots = {slots} if isinstance(slots, str) else set(slots) + class_vars: SetStr = set() + hash_func: Optional[Callable[[Any], int]] = None + + for base in reversed(bases): + if _is_base_model_class_defined and issubclass(base, BaseModel) and base != BaseModel: + fields.update(smart_deepcopy(base.__fields__)) + config = inherit_config(base.__config__, config) + validators = inherit_validators(base.__validators__, validators) + pre_root_validators += base.__pre_root_validators__ + post_root_validators += base.__post_root_validators__ + base_private_attributes.update(base.__private_attributes__) + class_vars.update(base.__class_vars__) + hash_func = base.__hash__ + + resolve_forward_refs = kwargs.pop('__resolve_forward_refs__', True) + allowed_config_kwargs: SetStr = { + key + for key in dir(config) + if not (key.startswith('__') and key.endswith('__')) # skip dunder methods and attributes + } + config_kwargs = {key: kwargs.pop(key) for key in kwargs.keys() & allowed_config_kwargs} + config_from_namespace = namespace.get('Config') + if config_kwargs and config_from_namespace: + raise TypeError('Specifying config in two places is ambiguous, use either Config attribute or class kwargs') + config = inherit_config(config_from_namespace, config, **config_kwargs) + + validators = inherit_validators(extract_validators(namespace), validators) + vg = ValidatorGroup(validators) + + for f in fields.values(): + f.set_config(config) + extra_validators = vg.get_validators(f.name) + if extra_validators: + f.class_validators.update(extra_validators) + # re-run prepare to add extra validators + f.populate_validators() + + prepare_config(config, name) + + untouched_types = ANNOTATED_FIELD_UNTOUCHED_TYPES + + def is_untouched(v: Any) -> bool: + return isinstance(v, untouched_types) or v.__class__.__name__ == 'cython_function_or_method' + + if (namespace.get('__module__'), namespace.get('__qualname__')) != ('pydantic.main', 'BaseModel'): + annotations = resolve_annotations(namespace.get('__annotations__', {}), namespace.get('__module__', None)) + # annotation only fields need to come first in fields + for ann_name, ann_type in annotations.items(): + if is_classvar(ann_type): + class_vars.add(ann_name) + elif is_finalvar_with_default_val(ann_type, namespace.get(ann_name, Undefined)): + class_vars.add(ann_name) + elif is_valid_field(ann_name): + validate_field_name(bases, ann_name) + value = namespace.get(ann_name, Undefined) + allowed_types = get_args(ann_type) if is_union(get_origin(ann_type)) else (ann_type,) + if ( + is_untouched(value) + and ann_type != PyObject + and not any( + lenient_issubclass(get_origin(allowed_type), Type) for allowed_type in allowed_types + ) + ): + continue + fields[ann_name] = ModelField.infer( + name=ann_name, + value=value, + annotation=ann_type, + class_validators=vg.get_validators(ann_name), + config=config, + ) + elif ann_name not in namespace and config.underscore_attrs_are_private: + private_attributes[ann_name] = PrivateAttr() + + untouched_types = UNTOUCHED_TYPES + config.keep_untouched + for var_name, value in namespace.items(): + can_be_changed = var_name not in class_vars and not is_untouched(value) + if isinstance(value, ModelPrivateAttr): + if not is_valid_private_name(var_name): + raise NameError( + f'Private attributes "{var_name}" must not be a valid field name; ' + f'Use sunder or dunder names, e. g. "_{var_name}" or "__{var_name}__"' + ) + private_attributes[var_name] = value + elif config.underscore_attrs_are_private and is_valid_private_name(var_name) and can_be_changed: + private_attributes[var_name] = PrivateAttr(default=value) + elif is_valid_field(var_name) and var_name not in annotations and can_be_changed: + validate_field_name(bases, var_name) + inferred = ModelField.infer( + name=var_name, + value=value, + annotation=annotations.get(var_name, Undefined), + class_validators=vg.get_validators(var_name), + config=config, + ) + if var_name in fields: + if lenient_issubclass(inferred.type_, fields[var_name].type_): + inferred.type_ = fields[var_name].type_ + else: + raise TypeError( + f'The type of {name}.{var_name} differs from the new default value; ' + f'if you wish to change the type of this field, please use a type annotation' + ) + fields[var_name] = inferred + + _custom_root_type = ROOT_KEY in fields + if _custom_root_type: + validate_custom_root_type(fields) + vg.check_for_unused() + if config.json_encoders: + json_encoder = partial(custom_pydantic_encoder, config.json_encoders) + else: + json_encoder = pydantic_encoder + pre_rv_new, post_rv_new = extract_root_validators(namespace) + + if hash_func is None: + hash_func = generate_hash_function(config.frozen) + + exclude_from_namespace = fields | private_attributes.keys() | {'__slots__'} + new_namespace = { + '__config__': config, + '__fields__': fields, + '__exclude_fields__': { + name: field.field_info.exclude for name, field in fields.items() if field.field_info.exclude is not None + } + or None, + '__include_fields__': { + name: field.field_info.include for name, field in fields.items() if field.field_info.include is not None + } + or None, + '__validators__': vg.validators, + '__pre_root_validators__': unique_list( + pre_root_validators + pre_rv_new, + name_factory=lambda v: v.__name__, + ), + '__post_root_validators__': unique_list( + post_root_validators + post_rv_new, + name_factory=lambda skip_on_failure_and_v: skip_on_failure_and_v[1].__name__, + ), + '__schema_cache__': {}, + '__json_encoder__': staticmethod(json_encoder), + '__custom_root_type__': _custom_root_type, + '__private_attributes__': {**base_private_attributes, **private_attributes}, + '__slots__': slots | private_attributes.keys(), + '__hash__': hash_func, + '__class_vars__': class_vars, + **{n: v for n, v in namespace.items() if n not in exclude_from_namespace}, + } + + cls = super().__new__(mcs, name, bases, new_namespace, **kwargs) + # set __signature__ attr only for model class, but not for its instances + cls.__signature__ = ClassAttribute('__signature__', generate_model_signature(cls.__init__, fields, config)) + if resolve_forward_refs: + cls.__try_update_forward_refs__() + + # preserve `__set_name__` protocol defined in https://peps.python.org/pep-0487 + # for attributes not in `new_namespace` (e.g. private attributes) + for name, obj in namespace.items(): + if name not in new_namespace: + set_name = getattr(obj, '__set_name__', None) + if callable(set_name): + set_name(cls, name) + + return cls + + def __instancecheck__(self, instance: Any) -> bool: + """ + Avoid calling ABC _abc_subclasscheck unless we're pretty sure. + + See #3829 and python/cpython#92810 + """ + return hasattr(instance, '__fields__') and super().__instancecheck__(instance) + + +object_setattr = object.__setattr__ + + +class BaseModel(Representation, metaclass=ModelMetaclass): + if TYPE_CHECKING: + # populated by the metaclass, defined here to help IDEs only + __fields__: ClassVar[Dict[str, ModelField]] = {} + __include_fields__: ClassVar[Optional[Mapping[str, Any]]] = None + __exclude_fields__: ClassVar[Optional[Mapping[str, Any]]] = None + __validators__: ClassVar[Dict[str, AnyCallable]] = {} + __pre_root_validators__: ClassVar[List[AnyCallable]] + __post_root_validators__: ClassVar[List[Tuple[bool, AnyCallable]]] + __config__: ClassVar[Type[BaseConfig]] = BaseConfig + __json_encoder__: ClassVar[Callable[[Any], Any]] = lambda x: x + __schema_cache__: ClassVar['DictAny'] = {} + __custom_root_type__: ClassVar[bool] = False + __signature__: ClassVar['Signature'] + __private_attributes__: ClassVar[Dict[str, ModelPrivateAttr]] + __class_vars__: ClassVar[SetStr] + __fields_set__: ClassVar[SetStr] = set() + + Config = BaseConfig + __slots__ = ('__dict__', '__fields_set__') + __doc__ = '' # Null out the Representation docstring + + def __init__(__pydantic_self__, **data: Any) -> None: + """ + Create a new model by parsing and validating input data from keyword arguments. + + Raises ValidationError if the input data cannot be parsed to form a valid model. + """ + # Uses something other than `self` the first arg to allow "self" as a settable attribute + values, fields_set, validation_error = validate_model(__pydantic_self__.__class__, data) + if validation_error: + raise validation_error + try: + object_setattr(__pydantic_self__, '__dict__', values) + except TypeError as e: + raise TypeError( + 'Model values must be a dict; you may not have returned a dictionary from a root validator' + ) from e + object_setattr(__pydantic_self__, '__fields_set__', fields_set) + __pydantic_self__._init_private_attributes() + + @no_type_check + def __setattr__(self, name, value): # noqa: C901 (ignore complexity) + if name in self.__private_attributes__ or name in DUNDER_ATTRIBUTES: + return object_setattr(self, name, value) + + if self.__config__.extra is not Extra.allow and name not in self.__fields__: + raise ValueError(f'"{self.__class__.__name__}" object has no field "{name}"') + elif not self.__config__.allow_mutation or self.__config__.frozen: + raise TypeError(f'"{self.__class__.__name__}" is immutable and does not support item assignment') + elif name in self.__fields__ and self.__fields__[name].final: + raise TypeError( + f'"{self.__class__.__name__}" object "{name}" field is final and does not support reassignment' + ) + elif self.__config__.validate_assignment: + new_values = {**self.__dict__, name: value} + + for validator in self.__pre_root_validators__: + try: + new_values = validator(self.__class__, new_values) + except (ValueError, TypeError, AssertionError) as exc: + raise ValidationError([ErrorWrapper(exc, loc=ROOT_KEY)], self.__class__) + + known_field = self.__fields__.get(name, None) + if known_field: + # We want to + # - make sure validators are called without the current value for this field inside `values` + # - keep other values (e.g. submodels) untouched (using `BaseModel.dict()` will change them into dicts) + # - keep the order of the fields + if not known_field.field_info.allow_mutation: + raise TypeError(f'"{known_field.name}" has allow_mutation set to False and cannot be assigned') + dict_without_original_value = {k: v for k, v in self.__dict__.items() if k != name} + value, error_ = known_field.validate(value, dict_without_original_value, loc=name, cls=self.__class__) + if error_: + raise ValidationError([error_], self.__class__) + else: + new_values[name] = value + + errors = [] + for skip_on_failure, validator in self.__post_root_validators__: + if skip_on_failure and errors: + continue + try: + new_values = validator(self.__class__, new_values) + except (ValueError, TypeError, AssertionError) as exc: + errors.append(ErrorWrapper(exc, loc=ROOT_KEY)) + if errors: + raise ValidationError(errors, self.__class__) + + # update the whole __dict__ as other values than just `value` + # may be changed (e.g. with `root_validator`) + object_setattr(self, '__dict__', new_values) + else: + self.__dict__[name] = value + + self.__fields_set__.add(name) + + def __getstate__(self) -> 'DictAny': + private_attrs = ((k, getattr(self, k, Undefined)) for k in self.__private_attributes__) + return { + '__dict__': self.__dict__, + '__fields_set__': self.__fields_set__, + '__private_attribute_values__': {k: v for k, v in private_attrs if v is not Undefined}, + } + + def __setstate__(self, state: 'DictAny') -> None: + object_setattr(self, '__dict__', state['__dict__']) + object_setattr(self, '__fields_set__', state['__fields_set__']) + for name, value in state.get('__private_attribute_values__', {}).items(): + object_setattr(self, name, value) + + def _init_private_attributes(self) -> None: + for name, private_attr in self.__private_attributes__.items(): + default = private_attr.get_default() + if default is not Undefined: + object_setattr(self, name, default) + + def dict( + self, + *, + include: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']] = None, + exclude: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']] = None, + by_alias: bool = False, + skip_defaults: Optional[bool] = None, + exclude_unset: bool = False, + exclude_defaults: bool = False, + exclude_none: bool = False, + ) -> 'DictStrAny': + """ + Generate a dictionary representation of the model, optionally specifying which fields to include or exclude. + + """ + if skip_defaults is not None: + warnings.warn( + f'{self.__class__.__name__}.dict(): "skip_defaults" is deprecated and replaced by "exclude_unset"', + DeprecationWarning, + ) + exclude_unset = skip_defaults + + return dict( + self._iter( + to_dict=True, + by_alias=by_alias, + include=include, + exclude=exclude, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + ) + ) + + def json( + self, + *, + include: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']] = None, + exclude: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']] = None, + by_alias: bool = False, + skip_defaults: Optional[bool] = None, + exclude_unset: bool = False, + exclude_defaults: bool = False, + exclude_none: bool = False, + encoder: Optional[Callable[[Any], Any]] = None, + models_as_dict: bool = True, + **dumps_kwargs: Any, + ) -> str: + """ + Generate a JSON representation of the model, `include` and `exclude` arguments as per `dict()`. + + `encoder` is an optional function to supply as `default` to json.dumps(), other arguments as per `json.dumps()`. + """ + if skip_defaults is not None: + warnings.warn( + f'{self.__class__.__name__}.json(): "skip_defaults" is deprecated and replaced by "exclude_unset"', + DeprecationWarning, + ) + exclude_unset = skip_defaults + encoder = cast(Callable[[Any], Any], encoder or self.__json_encoder__) + + # We don't directly call `self.dict()`, which does exactly this with `to_dict=True` + # because we want to be able to keep raw `BaseModel` instances and not as `dict`. + # This allows users to write custom JSON encoders for given `BaseModel` classes. + data = dict( + self._iter( + to_dict=models_as_dict, + by_alias=by_alias, + include=include, + exclude=exclude, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + ) + ) + if self.__custom_root_type__: + data = data[ROOT_KEY] + return self.__config__.json_dumps(data, default=encoder, **dumps_kwargs) + + @classmethod + def _enforce_dict_if_root(cls, obj: Any) -> Any: + if cls.__custom_root_type__ and ( + not (isinstance(obj, dict) and obj.keys() == {ROOT_KEY}) + and not (isinstance(obj, BaseModel) and obj.__fields__.keys() == {ROOT_KEY}) + or cls.__fields__[ROOT_KEY].shape in MAPPING_LIKE_SHAPES + ): + return {ROOT_KEY: obj} + else: + return obj + + @classmethod + def parse_obj(cls: Type['Model'], obj: Any) -> 'Model': + obj = cls._enforce_dict_if_root(obj) + if not isinstance(obj, dict): + try: + obj = dict(obj) + except (TypeError, ValueError) as e: + exc = TypeError(f'{cls.__name__} expected dict not {obj.__class__.__name__}') + raise ValidationError([ErrorWrapper(exc, loc=ROOT_KEY)], cls) from e + return cls(**obj) + + @classmethod + def parse_raw( + cls: Type['Model'], + b: StrBytes, + *, + content_type: str = None, + encoding: str = 'utf8', + proto: Protocol = None, + allow_pickle: bool = False, + ) -> 'Model': + try: + obj = load_str_bytes( + b, + proto=proto, + content_type=content_type, + encoding=encoding, + allow_pickle=allow_pickle, + json_loads=cls.__config__.json_loads, + ) + except (ValueError, TypeError, UnicodeDecodeError) as e: + raise ValidationError([ErrorWrapper(e, loc=ROOT_KEY)], cls) + return cls.parse_obj(obj) + + @classmethod + def parse_file( + cls: Type['Model'], + path: Union[str, Path], + *, + content_type: str = None, + encoding: str = 'utf8', + proto: Protocol = None, + allow_pickle: bool = False, + ) -> 'Model': + obj = load_file( + path, + proto=proto, + content_type=content_type, + encoding=encoding, + allow_pickle=allow_pickle, + json_loads=cls.__config__.json_loads, + ) + return cls.parse_obj(obj) + + @classmethod + def from_orm(cls: Type['Model'], obj: Any) -> 'Model': + if not cls.__config__.orm_mode: + raise ConfigError('You must have the config attribute orm_mode=True to use from_orm') + obj = {ROOT_KEY: obj} if cls.__custom_root_type__ else cls._decompose_class(obj) + m = cls.__new__(cls) + values, fields_set, validation_error = validate_model(cls, obj) + if validation_error: + raise validation_error + object_setattr(m, '__dict__', values) + object_setattr(m, '__fields_set__', fields_set) + m._init_private_attributes() + return m + + @classmethod + def construct(cls: Type['Model'], _fields_set: Optional['SetStr'] = None, **values: Any) -> 'Model': + """ + Creates a new model setting __dict__ and __fields_set__ from trusted or pre-validated data. + Default values are respected, but no other validation is performed. + Behaves as if `Config.extra = 'allow'` was set since it adds all passed values + """ + m = cls.__new__(cls) + fields_values: Dict[str, Any] = {} + for name, field in cls.__fields__.items(): + if field.alt_alias and field.alias in values: + fields_values[name] = values[field.alias] + elif name in values: + fields_values[name] = values[name] + elif not field.required: + fields_values[name] = field.get_default() + fields_values.update(values) + object_setattr(m, '__dict__', fields_values) + if _fields_set is None: + _fields_set = set(values.keys()) + object_setattr(m, '__fields_set__', _fields_set) + m._init_private_attributes() + return m + + def _copy_and_set_values(self: 'Model', values: 'DictStrAny', fields_set: 'SetStr', *, deep: bool) -> 'Model': + if deep: + # chances of having empty dict here are quite low for using smart_deepcopy + values = deepcopy(values) + + cls = self.__class__ + m = cls.__new__(cls) + object_setattr(m, '__dict__', values) + object_setattr(m, '__fields_set__', fields_set) + for name in self.__private_attributes__: + value = getattr(self, name, Undefined) + if value is not Undefined: + if deep: + value = deepcopy(value) + object_setattr(m, name, value) + + return m + + def copy( + self: 'Model', + *, + include: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']] = None, + exclude: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']] = None, + update: Optional['DictStrAny'] = None, + deep: bool = False, + ) -> 'Model': + """ + Duplicate a model, optionally choose which fields to include, exclude and change. + + :param include: fields to include in new model + :param exclude: fields to exclude from new model, as with values this takes precedence over include + :param update: values to change/add in the new model. Note: the data is not validated before creating + the new model: you should trust this data + :param deep: set to `True` to make a deep copy of the model + :return: new model instance + """ + + values = dict( + self._iter(to_dict=False, by_alias=False, include=include, exclude=exclude, exclude_unset=False), + **(update or {}), + ) + + # new `__fields_set__` can have unset optional fields with a set value in `update` kwarg + if update: + fields_set = self.__fields_set__ | update.keys() + else: + fields_set = set(self.__fields_set__) + + return self._copy_and_set_values(values, fields_set, deep=deep) + + @classmethod + def schema(cls, by_alias: bool = True, ref_template: str = default_ref_template) -> 'DictStrAny': + cached = cls.__schema_cache__.get((by_alias, ref_template)) + if cached is not None: + return cached + s = model_schema(cls, by_alias=by_alias, ref_template=ref_template) + cls.__schema_cache__[(by_alias, ref_template)] = s + return s + + @classmethod + def schema_json( + cls, *, by_alias: bool = True, ref_template: str = default_ref_template, **dumps_kwargs: Any + ) -> str: + from pydantic.json import pydantic_encoder + + return cls.__config__.json_dumps( + cls.schema(by_alias=by_alias, ref_template=ref_template), default=pydantic_encoder, **dumps_kwargs + ) + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.validate + + @classmethod + def validate(cls: Type['Model'], value: Any) -> 'Model': + if isinstance(value, cls): + copy_on_model_validation = cls.__config__.copy_on_model_validation + # whether to deep or shallow copy the model on validation, None means do not copy + deep_copy: Optional[bool] = None + if copy_on_model_validation not in {'deep', 'shallow', 'none'}: + # Warn about deprecated behavior + warnings.warn( + "`copy_on_model_validation` should be a string: 'deep', 'shallow' or 'none'", DeprecationWarning + ) + if copy_on_model_validation: + deep_copy = False + + if copy_on_model_validation == 'shallow': + # shallow copy + deep_copy = False + elif copy_on_model_validation == 'deep': + # deep copy + deep_copy = True + + if deep_copy is None: + return value + else: + return value._copy_and_set_values(value.__dict__, value.__fields_set__, deep=deep_copy) + + value = cls._enforce_dict_if_root(value) + + if isinstance(value, dict): + return cls(**value) + elif cls.__config__.orm_mode: + return cls.from_orm(value) + else: + try: + value_as_dict = dict(value) + except (TypeError, ValueError) as e: + raise DictError() from e + return cls(**value_as_dict) + + @classmethod + def _decompose_class(cls: Type['Model'], obj: Any) -> GetterDict: + if isinstance(obj, GetterDict): + return obj + return cls.__config__.getter_dict(obj) + + @classmethod + @no_type_check + def _get_value( + cls, + v: Any, + to_dict: bool, + by_alias: bool, + include: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']], + exclude: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']], + exclude_unset: bool, + exclude_defaults: bool, + exclude_none: bool, + ) -> Any: + if isinstance(v, BaseModel): + if to_dict: + v_dict = v.dict( + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + include=include, + exclude=exclude, + exclude_none=exclude_none, + ) + if ROOT_KEY in v_dict: + return v_dict[ROOT_KEY] + return v_dict + else: + return v.copy(include=include, exclude=exclude) + + value_exclude = ValueItems(v, exclude) if exclude else None + value_include = ValueItems(v, include) if include else None + + if isinstance(v, dict): + return { + k_: cls._get_value( + v_, + to_dict=to_dict, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + include=value_include and value_include.for_element(k_), + exclude=value_exclude and value_exclude.for_element(k_), + exclude_none=exclude_none, + ) + for k_, v_ in v.items() + if (not value_exclude or not value_exclude.is_excluded(k_)) + and (not value_include or value_include.is_included(k_)) + } + + elif sequence_like(v): + seq_args = ( + cls._get_value( + v_, + to_dict=to_dict, + by_alias=by_alias, + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + include=value_include and value_include.for_element(i), + exclude=value_exclude and value_exclude.for_element(i), + exclude_none=exclude_none, + ) + for i, v_ in enumerate(v) + if (not value_exclude or not value_exclude.is_excluded(i)) + and (not value_include or value_include.is_included(i)) + ) + + return v.__class__(*seq_args) if is_namedtuple(v.__class__) else v.__class__(seq_args) + + elif isinstance(v, Enum) and getattr(cls.Config, 'use_enum_values', False): + return v.value + + else: + return v + + @classmethod + def __try_update_forward_refs__(cls, **localns: Any) -> None: + """ + Same as update_forward_refs but will not raise exception + when forward references are not defined. + """ + update_model_forward_refs(cls, cls.__fields__.values(), cls.__config__.json_encoders, localns, (NameError,)) + + @classmethod + def update_forward_refs(cls, **localns: Any) -> None: + """ + Try to update ForwardRefs on fields based on this Model, globalns and localns. + """ + update_model_forward_refs(cls, cls.__fields__.values(), cls.__config__.json_encoders, localns) + + def __iter__(self) -> 'TupleGenerator': + """ + so `dict(model)` works + """ + yield from self.__dict__.items() + + def _iter( + self, + to_dict: bool = False, + by_alias: bool = False, + include: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']] = None, + exclude: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']] = None, + exclude_unset: bool = False, + exclude_defaults: bool = False, + exclude_none: bool = False, + ) -> 'TupleGenerator': + # Merge field set excludes with explicit exclude parameter with explicit overriding field set options. + # The extra "is not None" guards are not logically necessary but optimizes performance for the simple case. + if exclude is not None or self.__exclude_fields__ is not None: + exclude = ValueItems.merge(self.__exclude_fields__, exclude) + + if include is not None or self.__include_fields__ is not None: + include = ValueItems.merge(self.__include_fields__, include, intersect=True) + + allowed_keys = self._calculate_keys( + include=include, exclude=exclude, exclude_unset=exclude_unset # type: ignore + ) + if allowed_keys is None and not (to_dict or by_alias or exclude_unset or exclude_defaults or exclude_none): + # huge boost for plain _iter() + yield from self.__dict__.items() + return + + value_exclude = ValueItems(self, exclude) if exclude is not None else None + value_include = ValueItems(self, include) if include is not None else None + + for field_key, v in self.__dict__.items(): + if (allowed_keys is not None and field_key not in allowed_keys) or (exclude_none and v is None): + continue + + if exclude_defaults: + model_field = self.__fields__.get(field_key) + if not getattr(model_field, 'required', True) and getattr(model_field, 'default', _missing) == v: + continue + + if by_alias and field_key in self.__fields__: + dict_key = self.__fields__[field_key].alias + else: + dict_key = field_key + + if to_dict or value_include or value_exclude: + v = self._get_value( + v, + to_dict=to_dict, + by_alias=by_alias, + include=value_include and value_include.for_element(field_key), + exclude=value_exclude and value_exclude.for_element(field_key), + exclude_unset=exclude_unset, + exclude_defaults=exclude_defaults, + exclude_none=exclude_none, + ) + yield dict_key, v + + def _calculate_keys( + self, + include: Optional['MappingIntStrAny'], + exclude: Optional['MappingIntStrAny'], + exclude_unset: bool, + update: Optional['DictStrAny'] = None, + ) -> Optional[AbstractSet[str]]: + if include is None and exclude is None and exclude_unset is False: + return None + + keys: AbstractSet[str] + if exclude_unset: + keys = self.__fields_set__.copy() + else: + keys = self.__dict__.keys() + + if include is not None: + keys &= include.keys() + + if update: + keys -= update.keys() + + if exclude: + keys -= {k for k, v in exclude.items() if ValueItems.is_true(v)} + + return keys + + def __eq__(self, other: Any) -> bool: + if isinstance(other, BaseModel): + return self.dict() == other.dict() + else: + return self.dict() == other + + def __repr_args__(self) -> 'ReprArgs': + return [ + (k, v) + for k, v in self.__dict__.items() + if k not in DUNDER_ATTRIBUTES and (k not in self.__fields__ or self.__fields__[k].field_info.repr) + ] + + +_is_base_model_class_defined = True + + +@overload +def create_model( + __model_name: str, + *, + __config__: Optional[Type[BaseConfig]] = None, + __base__: None = None, + __module__: str = __name__, + __validators__: Dict[str, 'AnyClassMethod'] = None, + __cls_kwargs__: Dict[str, Any] = None, + **field_definitions: Any, +) -> Type['BaseModel']: + ... + + +@overload +def create_model( + __model_name: str, + *, + __config__: Optional[Type[BaseConfig]] = None, + __base__: Union[Type['Model'], Tuple[Type['Model'], ...]], + __module__: str = __name__, + __validators__: Dict[str, 'AnyClassMethod'] = None, + __cls_kwargs__: Dict[str, Any] = None, + **field_definitions: Any, +) -> Type['Model']: + ... + + +def create_model( + __model_name: str, + *, + __config__: Optional[Type[BaseConfig]] = None, + __base__: Union[None, Type['Model'], Tuple[Type['Model'], ...]] = None, + __module__: str = __name__, + __validators__: Dict[str, 'AnyClassMethod'] = None, + __cls_kwargs__: Dict[str, Any] = None, + __slots__: Optional[Tuple[str, ...]] = None, + **field_definitions: Any, +) -> Type['Model']: + """ + Dynamically create a model. + :param __model_name: name of the created model + :param __config__: config class to use for the new model + :param __base__: base class for the new model to inherit from + :param __module__: module of the created model + :param __validators__: a dict of method names and @validator class methods + :param __cls_kwargs__: a dict for class creation + :param __slots__: Deprecated, `__slots__` should not be passed to `create_model` + :param field_definitions: fields of the model (or extra fields if a base is supplied) + in the format `=(, )` or `=, e.g. + `foobar=(str, ...)` or `foobar=123`, or, for complex use-cases, in the format + `=` or `=(, )`, e.g. + `foo=Field(datetime, default_factory=datetime.utcnow, alias='bar')` or + `foo=(str, FieldInfo(title='Foo'))` + """ + if __slots__ is not None: + # __slots__ will be ignored from here on + warnings.warn('__slots__ should not be passed to create_model', RuntimeWarning) + + if __base__ is not None: + if __config__ is not None: + raise ConfigError('to avoid confusion __config__ and __base__ cannot be used together') + if not isinstance(__base__, tuple): + __base__ = (__base__,) + else: + __base__ = (cast(Type['Model'], BaseModel),) + + __cls_kwargs__ = __cls_kwargs__ or {} + + fields = {} + annotations = {} + + for f_name, f_def in field_definitions.items(): + if not is_valid_field(f_name): + warnings.warn(f'fields may not start with an underscore, ignoring "{f_name}"', RuntimeWarning) + if isinstance(f_def, tuple): + try: + f_annotation, f_value = f_def + except ValueError as e: + raise ConfigError( + 'field definitions should either be a tuple of (, ) or just a ' + 'default value, unfortunately this means tuples as ' + 'default values are not allowed' + ) from e + else: + f_annotation, f_value = None, f_def + + if f_annotation: + annotations[f_name] = f_annotation + fields[f_name] = f_value + + namespace: 'DictStrAny' = {'__annotations__': annotations, '__module__': __module__} + if __validators__: + namespace.update(__validators__) + namespace.update(fields) + if __config__: + namespace['Config'] = inherit_config(__config__, BaseConfig) + resolved_bases = resolve_bases(__base__) + meta, ns, kwds = prepare_class(__model_name, resolved_bases, kwds=__cls_kwargs__) + if resolved_bases is not __base__: + ns['__orig_bases__'] = __base__ + namespace.update(ns) + return meta(__model_name, resolved_bases, namespace, **kwds) + + +_missing = object() + + +def validate_model( # noqa: C901 (ignore complexity) + model: Type[BaseModel], input_data: 'DictStrAny', cls: 'ModelOrDc' = None +) -> Tuple['DictStrAny', 'SetStr', Optional[ValidationError]]: + """ + validate data against a model. + """ + values = {} + errors = [] + # input_data names, possibly alias + names_used = set() + # field names, never aliases + fields_set = set() + config = model.__config__ + check_extra = config.extra is not Extra.ignore + cls_ = cls or model + + for validator in model.__pre_root_validators__: + try: + input_data = validator(cls_, input_data) + except (ValueError, TypeError, AssertionError) as exc: + return {}, set(), ValidationError([ErrorWrapper(exc, loc=ROOT_KEY)], cls_) + + for name, field in model.__fields__.items(): + value = input_data.get(field.alias, _missing) + using_name = False + if value is _missing and config.allow_population_by_field_name and field.alt_alias: + value = input_data.get(field.name, _missing) + using_name = True + + if value is _missing: + if field.required: + errors.append(ErrorWrapper(MissingError(), loc=field.alias)) + continue + + value = field.get_default() + + if not config.validate_all and not field.validate_always: + values[name] = value + continue + else: + fields_set.add(name) + if check_extra: + names_used.add(field.name if using_name else field.alias) + + v_, errors_ = field.validate(value, values, loc=field.alias, cls=cls_) + if isinstance(errors_, ErrorWrapper): + errors.append(errors_) + elif isinstance(errors_, list): + errors.extend(errors_) + else: + values[name] = v_ + + if check_extra: + if isinstance(input_data, GetterDict): + extra = input_data.extra_keys() - names_used + else: + extra = input_data.keys() - names_used + if extra: + fields_set |= extra + if config.extra is Extra.allow: + for f in extra: + values[f] = input_data[f] + else: + for f in sorted(extra): + errors.append(ErrorWrapper(ExtraError(), loc=f)) + + for skip_on_failure, validator in model.__post_root_validators__: + if skip_on_failure and errors: + continue + try: + values = validator(cls_, values) + except (ValueError, TypeError, AssertionError) as exc: + errors.append(ErrorWrapper(exc, loc=ROOT_KEY)) + + if errors: + return values, fields_set, ValidationError(errors, cls_) + else: + return values, fields_set, None diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/mypy.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/mypy.py new file mode 100644 index 0000000..fdd05bd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/mypy.py @@ -0,0 +1,945 @@ +import sys +from configparser import ConfigParser +from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Type as TypingType, Union + +from mypy.errorcodes import ErrorCode +from mypy.nodes import ( + ARG_NAMED, + ARG_NAMED_OPT, + ARG_OPT, + ARG_POS, + ARG_STAR2, + MDEF, + Argument, + AssignmentStmt, + Block, + CallExpr, + ClassDef, + Context, + Decorator, + EllipsisExpr, + FuncBase, + FuncDef, + JsonDict, + MemberExpr, + NameExpr, + PassStmt, + PlaceholderNode, + RefExpr, + StrExpr, + SymbolNode, + SymbolTableNode, + TempNode, + TypeInfo, + TypeVarExpr, + Var, +) +from mypy.options import Options +from mypy.plugin import ( + CheckerPluginInterface, + ClassDefContext, + FunctionContext, + MethodContext, + Plugin, + ReportConfigContext, + SemanticAnalyzerPluginInterface, +) +from mypy.plugins import dataclasses +from mypy.semanal import set_callable_name # type: ignore +from mypy.server.trigger import make_wildcard_trigger +from mypy.types import ( + AnyType, + CallableType, + Instance, + NoneType, + Overloaded, + ProperType, + Type, + TypeOfAny, + TypeType, + TypeVarId, + TypeVarType, + UnionType, + get_proper_type, +) +from mypy.typevars import fill_typevars +from mypy.util import get_unique_redefinition_name +from mypy.version import __version__ as mypy_version + +from pydantic.utils import is_valid_field + +try: + from mypy.types import TypeVarDef # type: ignore[attr-defined] +except ImportError: # pragma: no cover + # Backward-compatible with TypeVarDef from Mypy 0.910. + from mypy.types import TypeVarType as TypeVarDef + +CONFIGFILE_KEY = 'pydantic-mypy' +METADATA_KEY = 'pydantic-mypy-metadata' +_NAMESPACE = __name__[:-5] # 'pydantic' in 1.10.X, 'pydantic.v1' in v2.X +BASEMODEL_FULLNAME = f'{_NAMESPACE}.main.BaseModel' +BASESETTINGS_FULLNAME = f'{_NAMESPACE}.env_settings.BaseSettings' +MODEL_METACLASS_FULLNAME = f'{_NAMESPACE}.main.ModelMetaclass' +FIELD_FULLNAME = f'{_NAMESPACE}.fields.Field' +DATACLASS_FULLNAME = f'{_NAMESPACE}.dataclasses.dataclass' + + +def parse_mypy_version(version: str) -> Tuple[int, ...]: + return tuple(map(int, version.partition('+')[0].split('.'))) + + +MYPY_VERSION_TUPLE = parse_mypy_version(mypy_version) +BUILTINS_NAME = 'builtins' if MYPY_VERSION_TUPLE >= (0, 930) else '__builtins__' + +# Increment version if plugin changes and mypy caches should be invalidated +__version__ = 2 + + +def plugin(version: str) -> 'TypingType[Plugin]': + """ + `version` is the mypy version string + + We might want to use this to print a warning if the mypy version being used is + newer, or especially older, than we expect (or need). + """ + return PydanticPlugin + + +class PydanticPlugin(Plugin): + def __init__(self, options: Options) -> None: + self.plugin_config = PydanticPluginConfig(options) + self._plugin_data = self.plugin_config.to_data() + super().__init__(options) + + def get_base_class_hook(self, fullname: str) -> 'Optional[Callable[[ClassDefContext], None]]': + sym = self.lookup_fully_qualified(fullname) + if sym and isinstance(sym.node, TypeInfo): # pragma: no branch + # No branching may occur if the mypy cache has not been cleared + if any(get_fullname(base) == BASEMODEL_FULLNAME for base in sym.node.mro): + return self._pydantic_model_class_maker_callback + return None + + def get_metaclass_hook(self, fullname: str) -> Optional[Callable[[ClassDefContext], None]]: + if fullname == MODEL_METACLASS_FULLNAME: + return self._pydantic_model_metaclass_marker_callback + return None + + def get_function_hook(self, fullname: str) -> 'Optional[Callable[[FunctionContext], Type]]': + sym = self.lookup_fully_qualified(fullname) + if sym and sym.fullname == FIELD_FULLNAME: + return self._pydantic_field_callback + return None + + def get_method_hook(self, fullname: str) -> Optional[Callable[[MethodContext], Type]]: + if fullname.endswith('.from_orm'): + return from_orm_callback + return None + + def get_class_decorator_hook(self, fullname: str) -> Optional[Callable[[ClassDefContext], None]]: + """Mark pydantic.dataclasses as dataclass. + + Mypy version 1.1.1 added support for `@dataclass_transform` decorator. + """ + if fullname == DATACLASS_FULLNAME and MYPY_VERSION_TUPLE < (1, 1): + return dataclasses.dataclass_class_maker_callback # type: ignore[return-value] + return None + + def report_config_data(self, ctx: ReportConfigContext) -> Dict[str, Any]: + """Return all plugin config data. + + Used by mypy to determine if cache needs to be discarded. + """ + return self._plugin_data + + def _pydantic_model_class_maker_callback(self, ctx: ClassDefContext) -> None: + transformer = PydanticModelTransformer(ctx, self.plugin_config) + transformer.transform() + + def _pydantic_model_metaclass_marker_callback(self, ctx: ClassDefContext) -> None: + """Reset dataclass_transform_spec attribute of ModelMetaclass. + + Let the plugin handle it. This behavior can be disabled + if 'debug_dataclass_transform' is set to True', for testing purposes. + """ + if self.plugin_config.debug_dataclass_transform: + return + info_metaclass = ctx.cls.info.declared_metaclass + assert info_metaclass, "callback not passed from 'get_metaclass_hook'" + if getattr(info_metaclass.type, 'dataclass_transform_spec', None): + info_metaclass.type.dataclass_transform_spec = None # type: ignore[attr-defined] + + def _pydantic_field_callback(self, ctx: FunctionContext) -> 'Type': + """ + Extract the type of the `default` argument from the Field function, and use it as the return type. + + In particular: + * Check whether the default and default_factory argument is specified. + * Output an error if both are specified. + * Retrieve the type of the argument which is specified, and use it as return type for the function. + """ + default_any_type = ctx.default_return_type + + assert ctx.callee_arg_names[0] == 'default', '"default" is no longer first argument in Field()' + assert ctx.callee_arg_names[1] == 'default_factory', '"default_factory" is no longer second argument in Field()' + default_args = ctx.args[0] + default_factory_args = ctx.args[1] + + if default_args and default_factory_args: + error_default_and_default_factory_specified(ctx.api, ctx.context) + return default_any_type + + if default_args: + default_type = ctx.arg_types[0][0] + default_arg = default_args[0] + + # Fallback to default Any type if the field is required + if not isinstance(default_arg, EllipsisExpr): + return default_type + + elif default_factory_args: + default_factory_type = ctx.arg_types[1][0] + + # Functions which use `ParamSpec` can be overloaded, exposing the callable's types as a parameter + # Pydantic calls the default factory without any argument, so we retrieve the first item + if isinstance(default_factory_type, Overloaded): + if MYPY_VERSION_TUPLE > (0, 910): + default_factory_type = default_factory_type.items[0] + else: + # Mypy0.910 exposes the items of overloaded types in a function + default_factory_type = default_factory_type.items()[0] # type: ignore[operator] + + if isinstance(default_factory_type, CallableType): + ret_type = default_factory_type.ret_type + # mypy doesn't think `ret_type` has `args`, you'd think mypy should know, + # add this check in case it varies by version + args = getattr(ret_type, 'args', None) + if args: + if all(isinstance(arg, TypeVarType) for arg in args): + # Looks like the default factory is a type like `list` or `dict`, replace all args with `Any` + ret_type.args = tuple(default_any_type for _ in args) # type: ignore[attr-defined] + return ret_type + + return default_any_type + + +class PydanticPluginConfig: + __slots__ = ( + 'init_forbid_extra', + 'init_typed', + 'warn_required_dynamic_aliases', + 'warn_untyped_fields', + 'debug_dataclass_transform', + ) + init_forbid_extra: bool + init_typed: bool + warn_required_dynamic_aliases: bool + warn_untyped_fields: bool + debug_dataclass_transform: bool # undocumented + + def __init__(self, options: Options) -> None: + if options.config_file is None: # pragma: no cover + return + + toml_config = parse_toml(options.config_file) + if toml_config is not None: + config = toml_config.get('tool', {}).get('pydantic-mypy', {}) + for key in self.__slots__: + setting = config.get(key, False) + if not isinstance(setting, bool): + raise ValueError(f'Configuration value must be a boolean for key: {key}') + setattr(self, key, setting) + else: + plugin_config = ConfigParser() + plugin_config.read(options.config_file) + for key in self.__slots__: + setting = plugin_config.getboolean(CONFIGFILE_KEY, key, fallback=False) + setattr(self, key, setting) + + def to_data(self) -> Dict[str, Any]: + return {key: getattr(self, key) for key in self.__slots__} + + +def from_orm_callback(ctx: MethodContext) -> Type: + """ + Raise an error if orm_mode is not enabled + """ + model_type: Instance + ctx_type = ctx.type + if isinstance(ctx_type, TypeType): + ctx_type = ctx_type.item + if isinstance(ctx_type, CallableType) and isinstance(ctx_type.ret_type, Instance): + model_type = ctx_type.ret_type # called on the class + elif isinstance(ctx_type, Instance): + model_type = ctx_type # called on an instance (unusual, but still valid) + else: # pragma: no cover + detail = f'ctx.type: {ctx_type} (of type {ctx_type.__class__.__name__})' + error_unexpected_behavior(detail, ctx.api, ctx.context) + return ctx.default_return_type + pydantic_metadata = model_type.type.metadata.get(METADATA_KEY) + if pydantic_metadata is None: + return ctx.default_return_type + orm_mode = pydantic_metadata.get('config', {}).get('orm_mode') + if orm_mode is not True: + error_from_orm(get_name(model_type.type), ctx.api, ctx.context) + return ctx.default_return_type + + +class PydanticModelTransformer: + tracked_config_fields: Set[str] = { + 'extra', + 'allow_mutation', + 'frozen', + 'orm_mode', + 'allow_population_by_field_name', + 'alias_generator', + } + + def __init__(self, ctx: ClassDefContext, plugin_config: PydanticPluginConfig) -> None: + self._ctx = ctx + self.plugin_config = plugin_config + + def transform(self) -> None: + """ + Configures the BaseModel subclass according to the plugin settings. + + In particular: + * determines the model config and fields, + * adds a fields-aware signature for the initializer and construct methods + * freezes the class if allow_mutation = False or frozen = True + * stores the fields, config, and if the class is settings in the mypy metadata for access by subclasses + """ + ctx = self._ctx + info = ctx.cls.info + + self.adjust_validator_signatures() + config = self.collect_config() + fields = self.collect_fields(config) + is_settings = any(get_fullname(base) == BASESETTINGS_FULLNAME for base in info.mro[:-1]) + self.add_initializer(fields, config, is_settings) + self.add_construct_method(fields) + self.set_frozen(fields, frozen=config.allow_mutation is False or config.frozen is True) + info.metadata[METADATA_KEY] = { + 'fields': {field.name: field.serialize() for field in fields}, + 'config': config.set_values_dict(), + } + + def adjust_validator_signatures(self) -> None: + """When we decorate a function `f` with `pydantic.validator(...), mypy sees + `f` as a regular method taking a `self` instance, even though pydantic + internally wraps `f` with `classmethod` if necessary. + + Teach mypy this by marking any function whose outermost decorator is a + `validator()` call as a classmethod. + """ + for name, sym in self._ctx.cls.info.names.items(): + if isinstance(sym.node, Decorator): + first_dec = sym.node.original_decorators[0] + if ( + isinstance(first_dec, CallExpr) + and isinstance(first_dec.callee, NameExpr) + and first_dec.callee.fullname == f'{_NAMESPACE}.class_validators.validator' + ): + sym.node.func.is_class = True + + def collect_config(self) -> 'ModelConfigData': + """ + Collects the values of the config attributes that are used by the plugin, accounting for parent classes. + """ + ctx = self._ctx + cls = ctx.cls + config = ModelConfigData() + for stmt in cls.defs.body: + if not isinstance(stmt, ClassDef): + continue + if stmt.name == 'Config': + for substmt in stmt.defs.body: + if not isinstance(substmt, AssignmentStmt): + continue + config.update(self.get_config_update(substmt)) + if ( + config.has_alias_generator + and not config.allow_population_by_field_name + and self.plugin_config.warn_required_dynamic_aliases + ): + error_required_dynamic_aliases(ctx.api, stmt) + for info in cls.info.mro[1:]: # 0 is the current class + if METADATA_KEY not in info.metadata: + continue + + # Each class depends on the set of fields in its ancestors + ctx.api.add_plugin_dependency(make_wildcard_trigger(get_fullname(info))) + for name, value in info.metadata[METADATA_KEY]['config'].items(): + config.setdefault(name, value) + return config + + def collect_fields(self, model_config: 'ModelConfigData') -> List['PydanticModelField']: + """ + Collects the fields for the model, accounting for parent classes + """ + # First, collect fields belonging to the current class. + ctx = self._ctx + cls = self._ctx.cls + fields = [] # type: List[PydanticModelField] + known_fields = set() # type: Set[str] + for stmt in cls.defs.body: + if not isinstance(stmt, AssignmentStmt): # `and stmt.new_syntax` to require annotation + continue + + lhs = stmt.lvalues[0] + if not isinstance(lhs, NameExpr) or not is_valid_field(lhs.name): + continue + + if not stmt.new_syntax and self.plugin_config.warn_untyped_fields: + error_untyped_fields(ctx.api, stmt) + + # if lhs.name == '__config__': # BaseConfig not well handled; I'm not sure why yet + # continue + + sym = cls.info.names.get(lhs.name) + if sym is None: # pragma: no cover + # This is likely due to a star import (see the dataclasses plugin for a more detailed explanation) + # This is the same logic used in the dataclasses plugin + continue + + node = sym.node + if isinstance(node, PlaceholderNode): # pragma: no cover + # See the PlaceholderNode docstring for more detail about how this can occur + # Basically, it is an edge case when dealing with complex import logic + # This is the same logic used in the dataclasses plugin + continue + if not isinstance(node, Var): # pragma: no cover + # Don't know if this edge case still happens with the `is_valid_field` check above + # but better safe than sorry + continue + + # x: ClassVar[int] is ignored by dataclasses. + if node.is_classvar: + continue + + is_required = self.get_is_required(cls, stmt, lhs) + alias, has_dynamic_alias = self.get_alias_info(stmt) + if ( + has_dynamic_alias + and not model_config.allow_population_by_field_name + and self.plugin_config.warn_required_dynamic_aliases + ): + error_required_dynamic_aliases(ctx.api, stmt) + fields.append( + PydanticModelField( + name=lhs.name, + is_required=is_required, + alias=alias, + has_dynamic_alias=has_dynamic_alias, + line=stmt.line, + column=stmt.column, + ) + ) + known_fields.add(lhs.name) + all_fields = fields.copy() + for info in cls.info.mro[1:]: # 0 is the current class, -2 is BaseModel, -1 is object + if METADATA_KEY not in info.metadata: + continue + + superclass_fields = [] + # Each class depends on the set of fields in its ancestors + ctx.api.add_plugin_dependency(make_wildcard_trigger(get_fullname(info))) + + for name, data in info.metadata[METADATA_KEY]['fields'].items(): + if name not in known_fields: + field = PydanticModelField.deserialize(info, data) + known_fields.add(name) + superclass_fields.append(field) + else: + (field,) = (a for a in all_fields if a.name == name) + all_fields.remove(field) + superclass_fields.append(field) + all_fields = superclass_fields + all_fields + return all_fields + + def add_initializer(self, fields: List['PydanticModelField'], config: 'ModelConfigData', is_settings: bool) -> None: + """ + Adds a fields-aware `__init__` method to the class. + + The added `__init__` will be annotated with types vs. all `Any` depending on the plugin settings. + """ + ctx = self._ctx + typed = self.plugin_config.init_typed + use_alias = config.allow_population_by_field_name is not True + force_all_optional = is_settings or bool( + config.has_alias_generator and not config.allow_population_by_field_name + ) + init_arguments = self.get_field_arguments( + fields, typed=typed, force_all_optional=force_all_optional, use_alias=use_alias + ) + if not self.should_init_forbid_extra(fields, config): + var = Var('kwargs') + init_arguments.append(Argument(var, AnyType(TypeOfAny.explicit), None, ARG_STAR2)) + + if '__init__' not in ctx.cls.info.names: + add_method(ctx, '__init__', init_arguments, NoneType()) + + def add_construct_method(self, fields: List['PydanticModelField']) -> None: + """ + Adds a fully typed `construct` classmethod to the class. + + Similar to the fields-aware __init__ method, but always uses the field names (not aliases), + and does not treat settings fields as optional. + """ + ctx = self._ctx + set_str = ctx.api.named_type(f'{BUILTINS_NAME}.set', [ctx.api.named_type(f'{BUILTINS_NAME}.str')]) + optional_set_str = UnionType([set_str, NoneType()]) + fields_set_argument = Argument(Var('_fields_set', optional_set_str), optional_set_str, None, ARG_OPT) + construct_arguments = self.get_field_arguments(fields, typed=True, force_all_optional=False, use_alias=False) + construct_arguments = [fields_set_argument] + construct_arguments + + obj_type = ctx.api.named_type(f'{BUILTINS_NAME}.object') + self_tvar_name = '_PydanticBaseModel' # Make sure it does not conflict with other names in the class + tvar_fullname = ctx.cls.fullname + '.' + self_tvar_name + if MYPY_VERSION_TUPLE >= (1, 4): + tvd = TypeVarType( + self_tvar_name, + tvar_fullname, + TypeVarId(-1), + [], + obj_type, + AnyType(TypeOfAny.from_omitted_generics), # type: ignore[arg-type] + ) + self_tvar_expr = TypeVarExpr( + self_tvar_name, + tvar_fullname, + [], + obj_type, + AnyType(TypeOfAny.from_omitted_generics), # type: ignore[arg-type] + ) + else: + tvd = TypeVarDef(self_tvar_name, tvar_fullname, -1, [], obj_type) + self_tvar_expr = TypeVarExpr(self_tvar_name, tvar_fullname, [], obj_type) + ctx.cls.info.names[self_tvar_name] = SymbolTableNode(MDEF, self_tvar_expr) + + # Backward-compatible with TypeVarDef from Mypy 0.910. + if isinstance(tvd, TypeVarType): + self_type = tvd + else: + self_type = TypeVarType(tvd) + + add_method( + ctx, + 'construct', + construct_arguments, + return_type=self_type, + self_type=self_type, + tvar_def=tvd, + is_classmethod=True, + ) + + def set_frozen(self, fields: List['PydanticModelField'], frozen: bool) -> None: + """ + Marks all fields as properties so that attempts to set them trigger mypy errors. + + This is the same approach used by the attrs and dataclasses plugins. + """ + ctx = self._ctx + info = ctx.cls.info + for field in fields: + sym_node = info.names.get(field.name) + if sym_node is not None: + var = sym_node.node + if isinstance(var, Var): + var.is_property = frozen + elif isinstance(var, PlaceholderNode) and not ctx.api.final_iteration: + # See https://github.com/pydantic/pydantic/issues/5191 to hit this branch for test coverage + ctx.api.defer() + else: # pragma: no cover + # I don't know whether it's possible to hit this branch, but I've added it for safety + try: + var_str = str(var) + except TypeError: + # This happens for PlaceholderNode; perhaps it will happen for other types in the future.. + var_str = repr(var) + detail = f'sym_node.node: {var_str} (of type {var.__class__})' + error_unexpected_behavior(detail, ctx.api, ctx.cls) + else: + var = field.to_var(info, use_alias=False) + var.info = info + var.is_property = frozen + var._fullname = get_fullname(info) + '.' + get_name(var) + info.names[get_name(var)] = SymbolTableNode(MDEF, var) + + def get_config_update(self, substmt: AssignmentStmt) -> Optional['ModelConfigData']: + """ + Determines the config update due to a single statement in the Config class definition. + + Warns if a tracked config attribute is set to a value the plugin doesn't know how to interpret (e.g., an int) + """ + lhs = substmt.lvalues[0] + if not (isinstance(lhs, NameExpr) and lhs.name in self.tracked_config_fields): + return None + if lhs.name == 'extra': + if isinstance(substmt.rvalue, StrExpr): + forbid_extra = substmt.rvalue.value == 'forbid' + elif isinstance(substmt.rvalue, MemberExpr): + forbid_extra = substmt.rvalue.name == 'forbid' + else: + error_invalid_config_value(lhs.name, self._ctx.api, substmt) + return None + return ModelConfigData(forbid_extra=forbid_extra) + if lhs.name == 'alias_generator': + has_alias_generator = True + if isinstance(substmt.rvalue, NameExpr) and substmt.rvalue.fullname == 'builtins.None': + has_alias_generator = False + return ModelConfigData(has_alias_generator=has_alias_generator) + if isinstance(substmt.rvalue, NameExpr) and substmt.rvalue.fullname in ('builtins.True', 'builtins.False'): + return ModelConfigData(**{lhs.name: substmt.rvalue.fullname == 'builtins.True'}) + error_invalid_config_value(lhs.name, self._ctx.api, substmt) + return None + + @staticmethod + def get_is_required(cls: ClassDef, stmt: AssignmentStmt, lhs: NameExpr) -> bool: + """ + Returns a boolean indicating whether the field defined in `stmt` is a required field. + """ + expr = stmt.rvalue + if isinstance(expr, TempNode): + # TempNode means annotation-only, so only non-required if Optional + value_type = get_proper_type(cls.info[lhs.name].type) + return not PydanticModelTransformer.type_has_implicit_default(value_type) + if isinstance(expr, CallExpr) and isinstance(expr.callee, RefExpr) and expr.callee.fullname == FIELD_FULLNAME: + # The "default value" is a call to `Field`; at this point, the field is + # only required if default is Ellipsis (i.e., `field_name: Annotation = Field(...)`) or if default_factory + # is specified. + for arg, name in zip(expr.args, expr.arg_names): + # If name is None, then this arg is the default because it is the only positional argument. + if name is None or name == 'default': + return arg.__class__ is EllipsisExpr + if name == 'default_factory': + return False + # In this case, default and default_factory are not specified, so we need to look at the annotation + value_type = get_proper_type(cls.info[lhs.name].type) + return not PydanticModelTransformer.type_has_implicit_default(value_type) + # Only required if the "default value" is Ellipsis (i.e., `field_name: Annotation = ...`) + return isinstance(expr, EllipsisExpr) + + @staticmethod + def type_has_implicit_default(type_: Optional[ProperType]) -> bool: + """ + Returns True if the passed type will be given an implicit default value. + + In pydantic v1, this is the case for Optional types and Any (with default value None). + """ + if isinstance(type_, AnyType): + # Annotated as Any + return True + if isinstance(type_, UnionType) and any( + isinstance(item, NoneType) or isinstance(item, AnyType) for item in type_.items + ): + # Annotated as Optional, or otherwise having NoneType or AnyType in the union + return True + return False + + @staticmethod + def get_alias_info(stmt: AssignmentStmt) -> Tuple[Optional[str], bool]: + """ + Returns a pair (alias, has_dynamic_alias), extracted from the declaration of the field defined in `stmt`. + + `has_dynamic_alias` is True if and only if an alias is provided, but not as a string literal. + If `has_dynamic_alias` is True, `alias` will be None. + """ + expr = stmt.rvalue + if isinstance(expr, TempNode): + # TempNode means annotation-only + return None, False + + if not ( + isinstance(expr, CallExpr) and isinstance(expr.callee, RefExpr) and expr.callee.fullname == FIELD_FULLNAME + ): + # Assigned value is not a call to pydantic.fields.Field + return None, False + + for i, arg_name in enumerate(expr.arg_names): + if arg_name != 'alias': + continue + arg = expr.args[i] + if isinstance(arg, StrExpr): + return arg.value, False + else: + return None, True + return None, False + + def get_field_arguments( + self, fields: List['PydanticModelField'], typed: bool, force_all_optional: bool, use_alias: bool + ) -> List[Argument]: + """ + Helper function used during the construction of the `__init__` and `construct` method signatures. + + Returns a list of mypy Argument instances for use in the generated signatures. + """ + info = self._ctx.cls.info + arguments = [ + field.to_argument(info, typed=typed, force_optional=force_all_optional, use_alias=use_alias) + for field in fields + if not (use_alias and field.has_dynamic_alias) + ] + return arguments + + def should_init_forbid_extra(self, fields: List['PydanticModelField'], config: 'ModelConfigData') -> bool: + """ + Indicates whether the generated `__init__` should get a `**kwargs` at the end of its signature + + We disallow arbitrary kwargs if the extra config setting is "forbid", or if the plugin config says to, + *unless* a required dynamic alias is present (since then we can't determine a valid signature). + """ + if not config.allow_population_by_field_name: + if self.is_dynamic_alias_present(fields, bool(config.has_alias_generator)): + return False + if config.forbid_extra: + return True + return self.plugin_config.init_forbid_extra + + @staticmethod + def is_dynamic_alias_present(fields: List['PydanticModelField'], has_alias_generator: bool) -> bool: + """ + Returns whether any fields on the model have a "dynamic alias", i.e., an alias that cannot be + determined during static analysis. + """ + for field in fields: + if field.has_dynamic_alias: + return True + if has_alias_generator: + for field in fields: + if field.alias is None: + return True + return False + + +class PydanticModelField: + def __init__( + self, name: str, is_required: bool, alias: Optional[str], has_dynamic_alias: bool, line: int, column: int + ): + self.name = name + self.is_required = is_required + self.alias = alias + self.has_dynamic_alias = has_dynamic_alias + self.line = line + self.column = column + + def to_var(self, info: TypeInfo, use_alias: bool) -> Var: + name = self.name + if use_alias and self.alias is not None: + name = self.alias + return Var(name, info[self.name].type) + + def to_argument(self, info: TypeInfo, typed: bool, force_optional: bool, use_alias: bool) -> Argument: + if typed and info[self.name].type is not None: + type_annotation = info[self.name].type + else: + type_annotation = AnyType(TypeOfAny.explicit) + return Argument( + variable=self.to_var(info, use_alias), + type_annotation=type_annotation, + initializer=None, + kind=ARG_NAMED_OPT if force_optional or not self.is_required else ARG_NAMED, + ) + + def serialize(self) -> JsonDict: + return self.__dict__ + + @classmethod + def deserialize(cls, info: TypeInfo, data: JsonDict) -> 'PydanticModelField': + return cls(**data) + + +class ModelConfigData: + def __init__( + self, + forbid_extra: Optional[bool] = None, + allow_mutation: Optional[bool] = None, + frozen: Optional[bool] = None, + orm_mode: Optional[bool] = None, + allow_population_by_field_name: Optional[bool] = None, + has_alias_generator: Optional[bool] = None, + ): + self.forbid_extra = forbid_extra + self.allow_mutation = allow_mutation + self.frozen = frozen + self.orm_mode = orm_mode + self.allow_population_by_field_name = allow_population_by_field_name + self.has_alias_generator = has_alias_generator + + def set_values_dict(self) -> Dict[str, Any]: + return {k: v for k, v in self.__dict__.items() if v is not None} + + def update(self, config: Optional['ModelConfigData']) -> None: + if config is None: + return + for k, v in config.set_values_dict().items(): + setattr(self, k, v) + + def setdefault(self, key: str, value: Any) -> None: + if getattr(self, key) is None: + setattr(self, key, value) + + +ERROR_ORM = ErrorCode('pydantic-orm', 'Invalid from_orm call', 'Pydantic') +ERROR_CONFIG = ErrorCode('pydantic-config', 'Invalid config value', 'Pydantic') +ERROR_ALIAS = ErrorCode('pydantic-alias', 'Dynamic alias disallowed', 'Pydantic') +ERROR_UNEXPECTED = ErrorCode('pydantic-unexpected', 'Unexpected behavior', 'Pydantic') +ERROR_UNTYPED = ErrorCode('pydantic-field', 'Untyped field disallowed', 'Pydantic') +ERROR_FIELD_DEFAULTS = ErrorCode('pydantic-field', 'Invalid Field defaults', 'Pydantic') + + +def error_from_orm(model_name: str, api: CheckerPluginInterface, context: Context) -> None: + api.fail(f'"{model_name}" does not have orm_mode=True', context, code=ERROR_ORM) + + +def error_invalid_config_value(name: str, api: SemanticAnalyzerPluginInterface, context: Context) -> None: + api.fail(f'Invalid value for "Config.{name}"', context, code=ERROR_CONFIG) + + +def error_required_dynamic_aliases(api: SemanticAnalyzerPluginInterface, context: Context) -> None: + api.fail('Required dynamic aliases disallowed', context, code=ERROR_ALIAS) + + +def error_unexpected_behavior( + detail: str, api: Union[CheckerPluginInterface, SemanticAnalyzerPluginInterface], context: Context +) -> None: # pragma: no cover + # Can't think of a good way to test this, but I confirmed it renders as desired by adding to a non-error path + link = 'https://github.com/pydantic/pydantic/issues/new/choose' + full_message = f'The pydantic mypy plugin ran into unexpected behavior: {detail}\n' + full_message += f'Please consider reporting this bug at {link} so we can try to fix it!' + api.fail(full_message, context, code=ERROR_UNEXPECTED) + + +def error_untyped_fields(api: SemanticAnalyzerPluginInterface, context: Context) -> None: + api.fail('Untyped fields disallowed', context, code=ERROR_UNTYPED) + + +def error_default_and_default_factory_specified(api: CheckerPluginInterface, context: Context) -> None: + api.fail('Field default and default_factory cannot be specified together', context, code=ERROR_FIELD_DEFAULTS) + + +def add_method( + ctx: ClassDefContext, + name: str, + args: List[Argument], + return_type: Type, + self_type: Optional[Type] = None, + tvar_def: Optional[TypeVarDef] = None, + is_classmethod: bool = False, + is_new: bool = False, + # is_staticmethod: bool = False, +) -> None: + """ + Adds a new method to a class. + + This can be dropped if/when https://github.com/python/mypy/issues/7301 is merged + """ + info = ctx.cls.info + + # First remove any previously generated methods with the same name + # to avoid clashes and problems in the semantic analyzer. + if name in info.names: + sym = info.names[name] + if sym.plugin_generated and isinstance(sym.node, FuncDef): + ctx.cls.defs.body.remove(sym.node) # pragma: no cover + + self_type = self_type or fill_typevars(info) + if is_classmethod or is_new: + first = [Argument(Var('_cls'), TypeType.make_normalized(self_type), None, ARG_POS)] + # elif is_staticmethod: + # first = [] + else: + self_type = self_type or fill_typevars(info) + first = [Argument(Var('__pydantic_self__'), self_type, None, ARG_POS)] + args = first + args + arg_types, arg_names, arg_kinds = [], [], [] + for arg in args: + assert arg.type_annotation, 'All arguments must be fully typed.' + arg_types.append(arg.type_annotation) + arg_names.append(get_name(arg.variable)) + arg_kinds.append(arg.kind) + + function_type = ctx.api.named_type(f'{BUILTINS_NAME}.function') + signature = CallableType(arg_types, arg_kinds, arg_names, return_type, function_type) + if tvar_def: + signature.variables = [tvar_def] + + func = FuncDef(name, args, Block([PassStmt()])) + func.info = info + func.type = set_callable_name(signature, func) + func.is_class = is_classmethod + # func.is_static = is_staticmethod + func._fullname = get_fullname(info) + '.' + name + func.line = info.line + + # NOTE: we would like the plugin generated node to dominate, but we still + # need to keep any existing definitions so they get semantically analyzed. + if name in info.names: + # Get a nice unique name instead. + r_name = get_unique_redefinition_name(name, info.names) + info.names[r_name] = info.names[name] + + if is_classmethod: # or is_staticmethod: + func.is_decorated = True + v = Var(name, func.type) + v.info = info + v._fullname = func._fullname + # if is_classmethod: + v.is_classmethod = True + dec = Decorator(func, [NameExpr('classmethod')], v) + # else: + # v.is_staticmethod = True + # dec = Decorator(func, [NameExpr('staticmethod')], v) + + dec.line = info.line + sym = SymbolTableNode(MDEF, dec) + else: + sym = SymbolTableNode(MDEF, func) + sym.plugin_generated = True + + info.names[name] = sym + info.defn.defs.body.append(func) + + +def get_fullname(x: Union[FuncBase, SymbolNode]) -> str: + """ + Used for compatibility with mypy 0.740; can be dropped once support for 0.740 is dropped. + """ + fn = x.fullname + if callable(fn): # pragma: no cover + return fn() + return fn + + +def get_name(x: Union[FuncBase, SymbolNode]) -> str: + """ + Used for compatibility with mypy 0.740; can be dropped once support for 0.740 is dropped. + """ + fn = x.name + if callable(fn): # pragma: no cover + return fn() + return fn + + +def parse_toml(config_file: str) -> Optional[Dict[str, Any]]: + if not config_file.endswith('.toml'): + return None + + read_mode = 'rb' + if sys.version_info >= (3, 11): + import tomllib as toml_ + else: + try: + import tomli as toml_ + except ImportError: + # older versions of mypy have toml as a dependency, not tomli + read_mode = 'r' + try: + import toml as toml_ # type: ignore[no-redef] + except ImportError: # pragma: no cover + import warnings + + warnings.warn('No TOML parser installed, cannot read configuration from `pyproject.toml`.') + return None + + with open(config_file, read_mode) as rf: + return toml_.load(rf) # type: ignore[arg-type] diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/networks.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/networks.py new file mode 100644 index 0000000..dbdff87 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/networks.py @@ -0,0 +1,747 @@ +import re +from ipaddress import ( + IPv4Address, + IPv4Interface, + IPv4Network, + IPv6Address, + IPv6Interface, + IPv6Network, + _BaseAddress, + _BaseNetwork, +) +from typing import ( + TYPE_CHECKING, + Any, + Collection, + Dict, + Generator, + List, + Match, + Optional, + Pattern, + Set, + Tuple, + Type, + Union, + cast, + no_type_check, +) + +from pydantic import errors +from pydantic.utils import Representation, update_not_none +from pydantic.validators import constr_length_validator, str_validator + +if TYPE_CHECKING: + import email_validator + from typing_extensions import TypedDict + + from pydantic.config import BaseConfig + from pydantic.fields import ModelField + from pydantic.typing import AnyCallable + + CallableGenerator = Generator[AnyCallable, None, None] + + class Parts(TypedDict, total=False): + scheme: str + user: Optional[str] + password: Optional[str] + ipv4: Optional[str] + ipv6: Optional[str] + domain: Optional[str] + port: Optional[str] + path: Optional[str] + query: Optional[str] + fragment: Optional[str] + + class HostParts(TypedDict, total=False): + host: str + tld: Optional[str] + host_type: Optional[str] + port: Optional[str] + rebuild: bool + +else: + email_validator = None + + class Parts(dict): + pass + + +NetworkType = Union[str, bytes, int, Tuple[Union[str, bytes, int], Union[str, int]]] + +__all__ = [ + 'AnyUrl', + 'AnyHttpUrl', + 'FileUrl', + 'HttpUrl', + 'stricturl', + 'EmailStr', + 'NameEmail', + 'IPvAnyAddress', + 'IPvAnyInterface', + 'IPvAnyNetwork', + 'PostgresDsn', + 'CockroachDsn', + 'AmqpDsn', + 'RedisDsn', + 'MongoDsn', + 'KafkaDsn', + 'validate_email', +] + +_url_regex_cache = None +_multi_host_url_regex_cache = None +_ascii_domain_regex_cache = None +_int_domain_regex_cache = None +_host_regex_cache = None + +_host_regex = ( + r'(?:' + r'(?P(?:\d{1,3}\.){3}\d{1,3})(?=$|[/:#?])|' # ipv4 + r'(?P\[[A-F0-9]*:[A-F0-9:]+\])(?=$|[/:#?])|' # ipv6 + r'(?P[^\s/:?#]+)' # domain, validation occurs later + r')?' + r'(?::(?P\d+))?' # port +) +_scheme_regex = r'(?:(?P[a-z][a-z0-9+\-.]+)://)?' # scheme https://tools.ietf.org/html/rfc3986#appendix-A +_user_info_regex = r'(?:(?P[^\s:/]*)(?::(?P[^\s/]*))?@)?' +_path_regex = r'(?P/[^\s?#]*)?' +_query_regex = r'(?:\?(?P[^\s#]*))?' +_fragment_regex = r'(?:#(?P[^\s#]*))?' + + +def url_regex() -> Pattern[str]: + global _url_regex_cache + if _url_regex_cache is None: + _url_regex_cache = re.compile( + rf'{_scheme_regex}{_user_info_regex}{_host_regex}{_path_regex}{_query_regex}{_fragment_regex}', + re.IGNORECASE, + ) + return _url_regex_cache + + +def multi_host_url_regex() -> Pattern[str]: + """ + Compiled multi host url regex. + + Additionally to `url_regex` it allows to match multiple hosts. + E.g. host1.db.net,host2.db.net + """ + global _multi_host_url_regex_cache + if _multi_host_url_regex_cache is None: + _multi_host_url_regex_cache = re.compile( + rf'{_scheme_regex}{_user_info_regex}' + r'(?P([^/]*))' # validation occurs later + rf'{_path_regex}{_query_regex}{_fragment_regex}', + re.IGNORECASE, + ) + return _multi_host_url_regex_cache + + +def ascii_domain_regex() -> Pattern[str]: + global _ascii_domain_regex_cache + if _ascii_domain_regex_cache is None: + ascii_chunk = r'[_0-9a-z](?:[-_0-9a-z]{0,61}[_0-9a-z])?' + ascii_domain_ending = r'(?P\.[a-z]{2,63})?\.?' + _ascii_domain_regex_cache = re.compile( + fr'(?:{ascii_chunk}\.)*?{ascii_chunk}{ascii_domain_ending}', re.IGNORECASE + ) + return _ascii_domain_regex_cache + + +def int_domain_regex() -> Pattern[str]: + global _int_domain_regex_cache + if _int_domain_regex_cache is None: + int_chunk = r'[_0-9a-\U00040000](?:[-_0-9a-\U00040000]{0,61}[_0-9a-\U00040000])?' + int_domain_ending = r'(?P(\.[^\W\d_]{2,63})|(\.(?:xn--)[_0-9a-z-]{2,63}))?\.?' + _int_domain_regex_cache = re.compile(fr'(?:{int_chunk}\.)*?{int_chunk}{int_domain_ending}', re.IGNORECASE) + return _int_domain_regex_cache + + +def host_regex() -> Pattern[str]: + global _host_regex_cache + if _host_regex_cache is None: + _host_regex_cache = re.compile( + _host_regex, + re.IGNORECASE, + ) + return _host_regex_cache + + +class AnyUrl(str): + strip_whitespace = True + min_length = 1 + max_length = 2**16 + allowed_schemes: Optional[Collection[str]] = None + tld_required: bool = False + user_required: bool = False + host_required: bool = True + hidden_parts: Set[str] = set() + + __slots__ = ('scheme', 'user', 'password', 'host', 'tld', 'host_type', 'port', 'path', 'query', 'fragment') + + @no_type_check + def __new__(cls, url: Optional[str], **kwargs) -> object: + return str.__new__(cls, cls.build(**kwargs) if url is None else url) + + def __init__( + self, + url: str, + *, + scheme: str, + user: Optional[str] = None, + password: Optional[str] = None, + host: Optional[str] = None, + tld: Optional[str] = None, + host_type: str = 'domain', + port: Optional[str] = None, + path: Optional[str] = None, + query: Optional[str] = None, + fragment: Optional[str] = None, + ) -> None: + str.__init__(url) + self.scheme = scheme + self.user = user + self.password = password + self.host = host + self.tld = tld + self.host_type = host_type + self.port = port + self.path = path + self.query = query + self.fragment = fragment + + @classmethod + def build( + cls, + *, + scheme: str, + user: Optional[str] = None, + password: Optional[str] = None, + host: str, + port: Optional[str] = None, + path: Optional[str] = None, + query: Optional[str] = None, + fragment: Optional[str] = None, + **_kwargs: str, + ) -> str: + parts = Parts( + scheme=scheme, + user=user, + password=password, + host=host, + port=port, + path=path, + query=query, + fragment=fragment, + **_kwargs, # type: ignore[misc] + ) + + url = scheme + '://' + if user: + url += user + if password: + url += ':' + password + if user or password: + url += '@' + url += host + if port and ('port' not in cls.hidden_parts or cls.get_default_parts(parts).get('port') != port): + url += ':' + port + if path: + url += path + if query: + url += '?' + query + if fragment: + url += '#' + fragment + return url + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + update_not_none(field_schema, minLength=cls.min_length, maxLength=cls.max_length, format='uri') + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.validate + + @classmethod + def validate(cls, value: Any, field: 'ModelField', config: 'BaseConfig') -> 'AnyUrl': + if value.__class__ == cls: + return value + value = str_validator(value) + if cls.strip_whitespace: + value = value.strip() + url: str = cast(str, constr_length_validator(value, field, config)) + + m = cls._match_url(url) + # the regex should always match, if it doesn't please report with details of the URL tried + assert m, 'URL regex failed unexpectedly' + + original_parts = cast('Parts', m.groupdict()) + parts = cls.apply_default_parts(original_parts) + parts = cls.validate_parts(parts) + + if m.end() != len(url): + raise errors.UrlExtraError(extra=url[m.end() :]) + + return cls._build_url(m, url, parts) + + @classmethod + def _build_url(cls, m: Match[str], url: str, parts: 'Parts') -> 'AnyUrl': + """ + Validate hosts and build the AnyUrl object. Split from `validate` so this method + can be altered in `MultiHostDsn`. + """ + host, tld, host_type, rebuild = cls.validate_host(parts) + + return cls( + None if rebuild else url, + scheme=parts['scheme'], + user=parts['user'], + password=parts['password'], + host=host, + tld=tld, + host_type=host_type, + port=parts['port'], + path=parts['path'], + query=parts['query'], + fragment=parts['fragment'], + ) + + @staticmethod + def _match_url(url: str) -> Optional[Match[str]]: + return url_regex().match(url) + + @staticmethod + def _validate_port(port: Optional[str]) -> None: + if port is not None and int(port) > 65_535: + raise errors.UrlPortError() + + @classmethod + def validate_parts(cls, parts: 'Parts', validate_port: bool = True) -> 'Parts': + """ + A method used to validate parts of a URL. + Could be overridden to set default values for parts if missing + """ + scheme = parts['scheme'] + if scheme is None: + raise errors.UrlSchemeError() + + if cls.allowed_schemes and scheme.lower() not in cls.allowed_schemes: + raise errors.UrlSchemePermittedError(set(cls.allowed_schemes)) + + if validate_port: + cls._validate_port(parts['port']) + + user = parts['user'] + if cls.user_required and user is None: + raise errors.UrlUserInfoError() + + return parts + + @classmethod + def validate_host(cls, parts: 'Parts') -> Tuple[str, Optional[str], str, bool]: + tld, host_type, rebuild = None, None, False + for f in ('domain', 'ipv4', 'ipv6'): + host = parts[f] # type: ignore[literal-required] + if host: + host_type = f + break + + if host is None: + if cls.host_required: + raise errors.UrlHostError() + elif host_type == 'domain': + is_international = False + d = ascii_domain_regex().fullmatch(host) + if d is None: + d = int_domain_regex().fullmatch(host) + if d is None: + raise errors.UrlHostError() + is_international = True + + tld = d.group('tld') + if tld is None and not is_international: + d = int_domain_regex().fullmatch(host) + assert d is not None + tld = d.group('tld') + is_international = True + + if tld is not None: + tld = tld[1:] + elif cls.tld_required: + raise errors.UrlHostTldError() + + if is_international: + host_type = 'int_domain' + rebuild = True + host = host.encode('idna').decode('ascii') + if tld is not None: + tld = tld.encode('idna').decode('ascii') + + return host, tld, host_type, rebuild # type: ignore + + @staticmethod + def get_default_parts(parts: 'Parts') -> 'Parts': + return {} + + @classmethod + def apply_default_parts(cls, parts: 'Parts') -> 'Parts': + for key, value in cls.get_default_parts(parts).items(): + if not parts[key]: # type: ignore[literal-required] + parts[key] = value # type: ignore[literal-required] + return parts + + def __repr__(self) -> str: + extra = ', '.join(f'{n}={getattr(self, n)!r}' for n in self.__slots__ if getattr(self, n) is not None) + return f'{self.__class__.__name__}({super().__repr__()}, {extra})' + + +class AnyHttpUrl(AnyUrl): + allowed_schemes = {'http', 'https'} + + __slots__ = () + + +class HttpUrl(AnyHttpUrl): + tld_required = True + # https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers + max_length = 2083 + hidden_parts = {'port'} + + @staticmethod + def get_default_parts(parts: 'Parts') -> 'Parts': + return {'port': '80' if parts['scheme'] == 'http' else '443'} + + +class FileUrl(AnyUrl): + allowed_schemes = {'file'} + host_required = False + + __slots__ = () + + +class MultiHostDsn(AnyUrl): + __slots__ = AnyUrl.__slots__ + ('hosts',) + + def __init__(self, *args: Any, hosts: Optional[List['HostParts']] = None, **kwargs: Any): + super().__init__(*args, **kwargs) + self.hosts = hosts + + @staticmethod + def _match_url(url: str) -> Optional[Match[str]]: + return multi_host_url_regex().match(url) + + @classmethod + def validate_parts(cls, parts: 'Parts', validate_port: bool = True) -> 'Parts': + return super().validate_parts(parts, validate_port=False) + + @classmethod + def _build_url(cls, m: Match[str], url: str, parts: 'Parts') -> 'MultiHostDsn': + hosts_parts: List['HostParts'] = [] + host_re = host_regex() + for host in m.groupdict()['hosts'].split(','): + d: Parts = host_re.match(host).groupdict() # type: ignore + host, tld, host_type, rebuild = cls.validate_host(d) + port = d.get('port') + cls._validate_port(port) + hosts_parts.append( + { + 'host': host, + 'host_type': host_type, + 'tld': tld, + 'rebuild': rebuild, + 'port': port, + } + ) + + if len(hosts_parts) > 1: + return cls( + None if any([hp['rebuild'] for hp in hosts_parts]) else url, + scheme=parts['scheme'], + user=parts['user'], + password=parts['password'], + path=parts['path'], + query=parts['query'], + fragment=parts['fragment'], + host_type=None, + hosts=hosts_parts, + ) + else: + # backwards compatibility with single host + host_part = hosts_parts[0] + return cls( + None if host_part['rebuild'] else url, + scheme=parts['scheme'], + user=parts['user'], + password=parts['password'], + host=host_part['host'], + tld=host_part['tld'], + host_type=host_part['host_type'], + port=host_part.get('port'), + path=parts['path'], + query=parts['query'], + fragment=parts['fragment'], + ) + + +class PostgresDsn(MultiHostDsn): + allowed_schemes = { + 'postgres', + 'postgresql', + 'postgresql+asyncpg', + 'postgresql+pg8000', + 'postgresql+psycopg', + 'postgresql+psycopg2', + 'postgresql+psycopg2cffi', + 'postgresql+py-postgresql', + 'postgresql+pygresql', + } + user_required = True + + __slots__ = () + + +class CockroachDsn(AnyUrl): + allowed_schemes = { + 'cockroachdb', + 'cockroachdb+psycopg2', + 'cockroachdb+asyncpg', + } + user_required = True + + +class AmqpDsn(AnyUrl): + allowed_schemes = {'amqp', 'amqps'} + host_required = False + + +class RedisDsn(AnyUrl): + __slots__ = () + allowed_schemes = {'redis', 'rediss'} + host_required = False + + @staticmethod + def get_default_parts(parts: 'Parts') -> 'Parts': + return { + 'domain': 'localhost' if not (parts['ipv4'] or parts['ipv6']) else '', + 'port': '6379', + 'path': '/0', + } + + +class MongoDsn(AnyUrl): + allowed_schemes = {'mongodb'} + + # TODO: Needed to generic "Parts" for "Replica Set", "Sharded Cluster", and other mongodb deployment modes + @staticmethod + def get_default_parts(parts: 'Parts') -> 'Parts': + return { + 'port': '27017', + } + + +class KafkaDsn(AnyUrl): + allowed_schemes = {'kafka'} + + @staticmethod + def get_default_parts(parts: 'Parts') -> 'Parts': + return { + 'domain': 'localhost', + 'port': '9092', + } + + +def stricturl( + *, + strip_whitespace: bool = True, + min_length: int = 1, + max_length: int = 2**16, + tld_required: bool = True, + host_required: bool = True, + allowed_schemes: Optional[Collection[str]] = None, +) -> Type[AnyUrl]: + # use kwargs then define conf in a dict to aid with IDE type hinting + namespace = dict( + strip_whitespace=strip_whitespace, + min_length=min_length, + max_length=max_length, + tld_required=tld_required, + host_required=host_required, + allowed_schemes=allowed_schemes, + ) + return type('UrlValue', (AnyUrl,), namespace) + + +def import_email_validator() -> None: + global email_validator + try: + import email_validator + except ImportError as e: + raise ImportError('email-validator is not installed, run `pip install pydantic[email]`') from e + + +class EmailStr(str): + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update(type='string', format='email') + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + # included here and below so the error happens straight away + import_email_validator() + + yield str_validator + yield cls.validate + + @classmethod + def validate(cls, value: Union[str]) -> str: + return validate_email(value)[1] + + +class NameEmail(Representation): + __slots__ = 'name', 'email' + + def __init__(self, name: str, email: str): + self.name = name + self.email = email + + def __eq__(self, other: Any) -> bool: + return isinstance(other, NameEmail) and (self.name, self.email) == (other.name, other.email) + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update(type='string', format='name-email') + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + import_email_validator() + + yield cls.validate + + @classmethod + def validate(cls, value: Any) -> 'NameEmail': + if value.__class__ == cls: + return value + value = str_validator(value) + return cls(*validate_email(value)) + + def __str__(self) -> str: + return f'{self.name} <{self.email}>' + + +class IPvAnyAddress(_BaseAddress): + __slots__ = () + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update(type='string', format='ipvanyaddress') + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.validate + + @classmethod + def validate(cls, value: Union[str, bytes, int]) -> Union[IPv4Address, IPv6Address]: + try: + return IPv4Address(value) + except ValueError: + pass + + try: + return IPv6Address(value) + except ValueError: + raise errors.IPvAnyAddressError() + + +class IPvAnyInterface(_BaseAddress): + __slots__ = () + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update(type='string', format='ipvanyinterface') + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.validate + + @classmethod + def validate(cls, value: NetworkType) -> Union[IPv4Interface, IPv6Interface]: + try: + return IPv4Interface(value) + except ValueError: + pass + + try: + return IPv6Interface(value) + except ValueError: + raise errors.IPvAnyInterfaceError() + + +class IPvAnyNetwork(_BaseNetwork): # type: ignore + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update(type='string', format='ipvanynetwork') + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.validate + + @classmethod + def validate(cls, value: NetworkType) -> Union[IPv4Network, IPv6Network]: + # Assume IP Network is defined with a default value for ``strict`` argument. + # Define your own class if you want to specify network address check strictness. + try: + return IPv4Network(value) + except ValueError: + pass + + try: + return IPv6Network(value) + except ValueError: + raise errors.IPvAnyNetworkError() + + +pretty_email_regex = re.compile(r'([\w ]*?) *<(.*)> *') +MAX_EMAIL_LENGTH = 2048 +"""Maximum length for an email. +A somewhat arbitrary but very generous number compared to what is allowed by most implementations. +""" + + +def validate_email(value: Union[str]) -> Tuple[str, str]: + """ + Email address validation using https://pypi.org/project/email-validator/ + Notes: + * raw ip address (literal) domain parts are not allowed. + * "John Doe " style "pretty" email addresses are processed + * spaces are striped from the beginning and end of addresses but no error is raised + """ + if email_validator is None: + import_email_validator() + + if len(value) > MAX_EMAIL_LENGTH: + raise errors.EmailError() + + m = pretty_email_regex.fullmatch(value) + name: Union[str, None] = None + if m: + name, value = m.groups() + email = value.strip() + try: + parts = email_validator.validate_email(email, check_deliverability=False) + except email_validator.EmailNotValidError as e: + raise errors.EmailError from e + + if hasattr(parts, 'normalized'): + # email-validator >= 2 + email = parts.normalized + assert email is not None + name = name or parts.local_part + return name, email + else: + # email-validator >1, <2 + at_index = email.index('@') + local_part = email[:at_index] # RFC 5321, local part must be case-sensitive. + global_part = email[at_index:].lower() + + return name or local_part, local_part + global_part diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/parse.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/parse.py new file mode 100644 index 0000000..6926121 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/parse.py @@ -0,0 +1,66 @@ +import json +import pickle +from enum import Enum +from pathlib import Path +from typing import Any, Callable, Union + +from pydantic.types import StrBytes + + +class Protocol(str, Enum): + json = 'json' + pickle = 'pickle' + + +def load_str_bytes( + b: StrBytes, + *, + content_type: str = None, + encoding: str = 'utf8', + proto: Protocol = None, + allow_pickle: bool = False, + json_loads: Callable[[str], Any] = json.loads, +) -> Any: + if proto is None and content_type: + if content_type.endswith(('json', 'javascript')): + pass + elif allow_pickle and content_type.endswith('pickle'): + proto = Protocol.pickle + else: + raise TypeError(f'Unknown content-type: {content_type}') + + proto = proto or Protocol.json + + if proto == Protocol.json: + if isinstance(b, bytes): + b = b.decode(encoding) + return json_loads(b) + elif proto == Protocol.pickle: + if not allow_pickle: + raise RuntimeError('Trying to decode with pickle with allow_pickle=False') + bb = b if isinstance(b, bytes) else b.encode() + return pickle.loads(bb) + else: + raise TypeError(f'Unknown protocol: {proto}') + + +def load_file( + path: Union[str, Path], + *, + content_type: str = None, + encoding: str = 'utf8', + proto: Protocol = None, + allow_pickle: bool = False, + json_loads: Callable[[str], Any] = json.loads, +) -> Any: + path = Path(path) + b = path.read_bytes() + if content_type is None: + if path.suffix in ('.js', '.json'): + proto = Protocol.json + elif path.suffix == '.pkl': + proto = Protocol.pickle + + return load_str_bytes( + b, proto=proto, content_type=content_type, encoding=encoding, allow_pickle=allow_pickle, json_loads=json_loads + ) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/py.typed b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/schema.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/schema.py new file mode 100644 index 0000000..62bed44 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/schema.py @@ -0,0 +1,1163 @@ +import re +import warnings +from collections import defaultdict +from dataclasses import is_dataclass +from datetime import date, datetime, time, timedelta +from decimal import Decimal +from enum import Enum +from ipaddress import IPv4Address, IPv4Interface, IPv4Network, IPv6Address, IPv6Interface, IPv6Network +from pathlib import Path +from typing import ( + TYPE_CHECKING, + Any, + Callable, + Dict, + ForwardRef, + FrozenSet, + Generic, + Iterable, + List, + Optional, + Pattern, + Sequence, + Set, + Tuple, + Type, + TypeVar, + Union, + cast, +) +from uuid import UUID + +from typing_extensions import Annotated, Literal + +from pydantic.fields import ( + MAPPING_LIKE_SHAPES, + SHAPE_DEQUE, + SHAPE_FROZENSET, + SHAPE_GENERIC, + SHAPE_ITERABLE, + SHAPE_LIST, + SHAPE_SEQUENCE, + SHAPE_SET, + SHAPE_SINGLETON, + SHAPE_TUPLE, + SHAPE_TUPLE_ELLIPSIS, + FieldInfo, + ModelField, +) +from pydantic.json import pydantic_encoder +from pydantic.networks import AnyUrl, EmailStr +from pydantic.types import ( + ConstrainedDecimal, + ConstrainedFloat, + ConstrainedFrozenSet, + ConstrainedInt, + ConstrainedList, + ConstrainedSet, + ConstrainedStr, + SecretBytes, + SecretStr, + StrictBytes, + StrictStr, + conbytes, + condecimal, + confloat, + confrozenset, + conint, + conlist, + conset, + constr, +) +from pydantic.typing import ( + all_literal_values, + get_args, + get_origin, + get_sub_types, + is_callable_type, + is_literal_type, + is_namedtuple, + is_none_type, + is_union, +) +from pydantic.utils import ROOT_KEY, get_model, lenient_issubclass + +if TYPE_CHECKING: + from pydantic.dataclasses import Dataclass + from pydantic.main import BaseModel + +default_prefix = '#/definitions/' +default_ref_template = '#/definitions/{model}' + +TypeModelOrEnum = Union[Type['BaseModel'], Type[Enum]] +TypeModelSet = Set[TypeModelOrEnum] + + +def _apply_modify_schema( + modify_schema: Callable[..., None], field: Optional[ModelField], field_schema: Dict[str, Any] +) -> None: + from inspect import signature + + sig = signature(modify_schema) + args = set(sig.parameters.keys()) + if 'field' in args or 'kwargs' in args: + modify_schema(field_schema, field=field) + else: + modify_schema(field_schema) + + +def schema( + models: Sequence[Union[Type['BaseModel'], Type['Dataclass']]], + *, + by_alias: bool = True, + title: Optional[str] = None, + description: Optional[str] = None, + ref_prefix: Optional[str] = None, + ref_template: str = default_ref_template, +) -> Dict[str, Any]: + """ + Process a list of models and generate a single JSON Schema with all of them defined in the ``definitions`` + top-level JSON key, including their sub-models. + + :param models: a list of models to include in the generated JSON Schema + :param by_alias: generate the schemas using the aliases defined, if any + :param title: title for the generated schema that includes the definitions + :param description: description for the generated schema + :param ref_prefix: the JSON Pointer prefix for schema references with ``$ref``, if None, will be set to the + default of ``#/definitions/``. Update it if you want the schemas to reference the definitions somewhere + else, e.g. for OpenAPI use ``#/components/schemas/``. The resulting generated schemas will still be at the + top-level key ``definitions``, so you can extract them from there. But all the references will have the set + prefix. + :param ref_template: Use a ``string.format()`` template for ``$ref`` instead of a prefix. This can be useful + for references that cannot be represented by ``ref_prefix`` such as a definition stored in another file. For + a sibling json file in a ``/schemas`` directory use ``"/schemas/${model}.json#"``. + :return: dict with the JSON Schema with a ``definitions`` top-level key including the schema definitions for + the models and sub-models passed in ``models``. + """ + clean_models = [get_model(model) for model in models] + flat_models = get_flat_models_from_models(clean_models) + model_name_map = get_model_name_map(flat_models) + definitions = {} + output_schema: Dict[str, Any] = {} + if title: + output_schema['title'] = title + if description: + output_schema['description'] = description + for model in clean_models: + m_schema, m_definitions, m_nested_models = model_process_schema( + model, + by_alias=by_alias, + model_name_map=model_name_map, + ref_prefix=ref_prefix, + ref_template=ref_template, + ) + definitions.update(m_definitions) + model_name = model_name_map[model] + definitions[model_name] = m_schema + if definitions: + output_schema['definitions'] = definitions + return output_schema + + +def model_schema( + model: Union[Type['BaseModel'], Type['Dataclass']], + by_alias: bool = True, + ref_prefix: Optional[str] = None, + ref_template: str = default_ref_template, +) -> Dict[str, Any]: + """ + Generate a JSON Schema for one model. With all the sub-models defined in the ``definitions`` top-level + JSON key. + + :param model: a Pydantic model (a class that inherits from BaseModel) + :param by_alias: generate the schemas using the aliases defined, if any + :param ref_prefix: the JSON Pointer prefix for schema references with ``$ref``, if None, will be set to the + default of ``#/definitions/``. Update it if you want the schemas to reference the definitions somewhere + else, e.g. for OpenAPI use ``#/components/schemas/``. The resulting generated schemas will still be at the + top-level key ``definitions``, so you can extract them from there. But all the references will have the set + prefix. + :param ref_template: Use a ``string.format()`` template for ``$ref`` instead of a prefix. This can be useful for + references that cannot be represented by ``ref_prefix`` such as a definition stored in another file. For a + sibling json file in a ``/schemas`` directory use ``"/schemas/${model}.json#"``. + :return: dict with the JSON Schema for the passed ``model`` + """ + model = get_model(model) + flat_models = get_flat_models_from_model(model) + model_name_map = get_model_name_map(flat_models) + model_name = model_name_map[model] + m_schema, m_definitions, nested_models = model_process_schema( + model, by_alias=by_alias, model_name_map=model_name_map, ref_prefix=ref_prefix, ref_template=ref_template + ) + if model_name in nested_models: + # model_name is in Nested models, it has circular references + m_definitions[model_name] = m_schema + m_schema = get_schema_ref(model_name, ref_prefix, ref_template, False) + if m_definitions: + m_schema.update({'definitions': m_definitions}) + return m_schema + + +def get_field_info_schema(field: ModelField, schema_overrides: bool = False) -> Tuple[Dict[str, Any], bool]: + # If no title is explicitly set, we don't set title in the schema for enums. + # The behaviour is the same as `BaseModel` reference, where the default title + # is in the definitions part of the schema. + schema_: Dict[str, Any] = {} + if field.field_info.title or not lenient_issubclass(field.type_, Enum): + schema_['title'] = field.field_info.title or field.alias.title().replace('_', ' ') + + if field.field_info.title: + schema_overrides = True + + if field.field_info.description: + schema_['description'] = field.field_info.description + schema_overrides = True + + if not field.required and field.default is not None and not is_callable_type(field.outer_type_): + schema_['default'] = encode_default(field.default) + schema_overrides = True + + return schema_, schema_overrides + + +def field_schema( + field: ModelField, + *, + by_alias: bool = True, + model_name_map: Dict[TypeModelOrEnum, str], + ref_prefix: Optional[str] = None, + ref_template: str = default_ref_template, + known_models: Optional[TypeModelSet] = None, +) -> Tuple[Dict[str, Any], Dict[str, Any], Set[str]]: + """ + Process a Pydantic field and return a tuple with a JSON Schema for it as the first item. + Also return a dictionary of definitions with models as keys and their schemas as values. If the passed field + is a model and has sub-models, and those sub-models don't have overrides (as ``title``, ``default``, etc), they + will be included in the definitions and referenced in the schema instead of included recursively. + + :param field: a Pydantic ``ModelField`` + :param by_alias: use the defined alias (if any) in the returned schema + :param model_name_map: used to generate the JSON Schema references to other models included in the definitions + :param ref_prefix: the JSON Pointer prefix to use for references to other schemas, if None, the default of + #/definitions/ will be used + :param ref_template: Use a ``string.format()`` template for ``$ref`` instead of a prefix. This can be useful for + references that cannot be represented by ``ref_prefix`` such as a definition stored in another file. For a + sibling json file in a ``/schemas`` directory use ``"/schemas/${model}.json#"``. + :param known_models: used to solve circular references + :return: tuple of the schema for this field and additional definitions + """ + s, schema_overrides = get_field_info_schema(field) + + validation_schema = get_field_schema_validations(field) + if validation_schema: + s.update(validation_schema) + schema_overrides = True + + f_schema, f_definitions, f_nested_models = field_type_schema( + field, + by_alias=by_alias, + model_name_map=model_name_map, + schema_overrides=schema_overrides, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models or set(), + ) + + # $ref will only be returned when there are no schema_overrides + if '$ref' in f_schema: + return f_schema, f_definitions, f_nested_models + else: + s.update(f_schema) + return s, f_definitions, f_nested_models + + +numeric_types = (int, float, Decimal) +_str_types_attrs: Tuple[Tuple[str, Union[type, Tuple[type, ...]], str], ...] = ( + ('max_length', numeric_types, 'maxLength'), + ('min_length', numeric_types, 'minLength'), + ('regex', str, 'pattern'), +) + +_numeric_types_attrs: Tuple[Tuple[str, Union[type, Tuple[type, ...]], str], ...] = ( + ('gt', numeric_types, 'exclusiveMinimum'), + ('lt', numeric_types, 'exclusiveMaximum'), + ('ge', numeric_types, 'minimum'), + ('le', numeric_types, 'maximum'), + ('multiple_of', numeric_types, 'multipleOf'), +) + + +def get_field_schema_validations(field: ModelField) -> Dict[str, Any]: + """ + Get the JSON Schema validation keywords for a ``field`` with an annotation of + a Pydantic ``FieldInfo`` with validation arguments. + """ + f_schema: Dict[str, Any] = {} + + if lenient_issubclass(field.type_, Enum): + # schema is already updated by `enum_process_schema`; just update with field extra + if field.field_info.extra: + f_schema.update(field.field_info.extra) + return f_schema + + if lenient_issubclass(field.type_, (str, bytes)): + for attr_name, t, keyword in _str_types_attrs: + attr = getattr(field.field_info, attr_name, None) + if isinstance(attr, t): + f_schema[keyword] = attr + if lenient_issubclass(field.type_, numeric_types) and not issubclass(field.type_, bool): + for attr_name, t, keyword in _numeric_types_attrs: + attr = getattr(field.field_info, attr_name, None) + if isinstance(attr, t): + f_schema[keyword] = attr + if field.field_info is not None and field.field_info.const: + f_schema['const'] = field.default + if field.field_info.extra: + f_schema.update(field.field_info.extra) + modify_schema = getattr(field.outer_type_, '__modify_schema__', None) + if modify_schema: + _apply_modify_schema(modify_schema, field, f_schema) + return f_schema + + +def get_model_name_map(unique_models: TypeModelSet) -> Dict[TypeModelOrEnum, str]: + """ + Process a set of models and generate unique names for them to be used as keys in the JSON Schema + definitions. By default the names are the same as the class name. But if two models in different Python + modules have the same name (e.g. "users.Model" and "items.Model"), the generated names will be + based on the Python module path for those conflicting models to prevent name collisions. + + :param unique_models: a Python set of models + :return: dict mapping models to names + """ + name_model_map = {} + conflicting_names: Set[str] = set() + for model in unique_models: + model_name = normalize_name(model.__name__) + if model_name in conflicting_names: + model_name = get_long_model_name(model) + name_model_map[model_name] = model + elif model_name in name_model_map: + conflicting_names.add(model_name) + conflicting_model = name_model_map.pop(model_name) + name_model_map[get_long_model_name(conflicting_model)] = conflicting_model + name_model_map[get_long_model_name(model)] = model + else: + name_model_map[model_name] = model + return {v: k for k, v in name_model_map.items()} + + +def get_flat_models_from_model(model: Type['BaseModel'], known_models: Optional[TypeModelSet] = None) -> TypeModelSet: + """ + Take a single ``model`` and generate a set with itself and all the sub-models in the tree. I.e. if you pass + model ``Foo`` (subclass of Pydantic ``BaseModel``) as ``model``, and it has a field of type ``Bar`` (also + subclass of ``BaseModel``) and that model ``Bar`` has a field of type ``Baz`` (also subclass of ``BaseModel``), + the return value will be ``set([Foo, Bar, Baz])``. + + :param model: a Pydantic ``BaseModel`` subclass + :param known_models: used to solve circular references + :return: a set with the initial model and all its sub-models + """ + known_models = known_models or set() + flat_models: TypeModelSet = set() + flat_models.add(model) + known_models |= flat_models + fields = cast(Sequence[ModelField], model.__fields__.values()) + flat_models |= get_flat_models_from_fields(fields, known_models=known_models) + return flat_models + + +def get_flat_models_from_field(field: ModelField, known_models: TypeModelSet) -> TypeModelSet: + """ + Take a single Pydantic ``ModelField`` (from a model) that could have been declared as a subclass of BaseModel + (so, it could be a submodel), and generate a set with its model and all the sub-models in the tree. + I.e. if you pass a field that was declared to be of type ``Foo`` (subclass of BaseModel) as ``field``, and that + model ``Foo`` has a field of type ``Bar`` (also subclass of ``BaseModel``) and that model ``Bar`` has a field of + type ``Baz`` (also subclass of ``BaseModel``), the return value will be ``set([Foo, Bar, Baz])``. + + :param field: a Pydantic ``ModelField`` + :param known_models: used to solve circular references + :return: a set with the model used in the declaration for this field, if any, and all its sub-models + """ + from pydantic.main import BaseModel + + flat_models: TypeModelSet = set() + + field_type = field.type_ + if lenient_issubclass(getattr(field_type, '__pydantic_model__', None), BaseModel): + field_type = field_type.__pydantic_model__ + + if field.sub_fields and not lenient_issubclass(field_type, BaseModel): + flat_models |= get_flat_models_from_fields(field.sub_fields, known_models=known_models) + elif lenient_issubclass(field_type, BaseModel) and field_type not in known_models: + flat_models |= get_flat_models_from_model(field_type, known_models=known_models) + elif lenient_issubclass(field_type, Enum): + flat_models.add(field_type) + return flat_models + + +def get_flat_models_from_fields(fields: Sequence[ModelField], known_models: TypeModelSet) -> TypeModelSet: + """ + Take a list of Pydantic ``ModelField``s (from a model) that could have been declared as subclasses of ``BaseModel`` + (so, any of them could be a submodel), and generate a set with their models and all the sub-models in the tree. + I.e. if you pass a the fields of a model ``Foo`` (subclass of ``BaseModel``) as ``fields``, and on of them has a + field of type ``Bar`` (also subclass of ``BaseModel``) and that model ``Bar`` has a field of type ``Baz`` (also + subclass of ``BaseModel``), the return value will be ``set([Foo, Bar, Baz])``. + + :param fields: a list of Pydantic ``ModelField``s + :param known_models: used to solve circular references + :return: a set with any model declared in the fields, and all their sub-models + """ + flat_models: TypeModelSet = set() + for field in fields: + flat_models |= get_flat_models_from_field(field, known_models=known_models) + return flat_models + + +def get_flat_models_from_models(models: Sequence[Type['BaseModel']]) -> TypeModelSet: + """ + Take a list of ``models`` and generate a set with them and all their sub-models in their trees. I.e. if you pass + a list of two models, ``Foo`` and ``Bar``, both subclasses of Pydantic ``BaseModel`` as models, and ``Bar`` has + a field of type ``Baz`` (also subclass of ``BaseModel``), the return value will be ``set([Foo, Bar, Baz])``. + """ + flat_models: TypeModelSet = set() + for model in models: + flat_models |= get_flat_models_from_model(model) + return flat_models + + +def get_long_model_name(model: TypeModelOrEnum) -> str: + return f'{model.__module__}__{model.__qualname__}'.replace('.', '__') + + +def field_type_schema( + field: ModelField, + *, + by_alias: bool, + model_name_map: Dict[TypeModelOrEnum, str], + ref_template: str, + schema_overrides: bool = False, + ref_prefix: Optional[str] = None, + known_models: TypeModelSet, +) -> Tuple[Dict[str, Any], Dict[str, Any], Set[str]]: + """ + Used by ``field_schema()``, you probably should be using that function. + + Take a single ``field`` and generate the schema for its type only, not including additional + information as title, etc. Also return additional schema definitions, from sub-models. + """ + from pydantic.main import BaseModel # noqa: F811 + + definitions = {} + nested_models: Set[str] = set() + f_schema: Dict[str, Any] + if field.shape in { + SHAPE_LIST, + SHAPE_TUPLE_ELLIPSIS, + SHAPE_SEQUENCE, + SHAPE_SET, + SHAPE_FROZENSET, + SHAPE_ITERABLE, + SHAPE_DEQUE, + }: + items_schema, f_definitions, f_nested_models = field_singleton_schema( + field, + by_alias=by_alias, + model_name_map=model_name_map, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models, + ) + definitions.update(f_definitions) + nested_models.update(f_nested_models) + f_schema = {'type': 'array', 'items': items_schema} + if field.shape in {SHAPE_SET, SHAPE_FROZENSET}: + f_schema['uniqueItems'] = True + + elif field.shape in MAPPING_LIKE_SHAPES: + f_schema = {'type': 'object'} + key_field = cast(ModelField, field.key_field) + regex = getattr(key_field.type_, 'regex', None) + items_schema, f_definitions, f_nested_models = field_singleton_schema( + field, + by_alias=by_alias, + model_name_map=model_name_map, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models, + ) + definitions.update(f_definitions) + nested_models.update(f_nested_models) + if regex: + # Dict keys have a regex pattern + # items_schema might be a schema or empty dict, add it either way + f_schema['patternProperties'] = {ConstrainedStr._get_pattern(regex): items_schema} + if items_schema: + # The dict values are not simply Any, so they need a schema + f_schema['additionalProperties'] = items_schema + elif field.shape == SHAPE_TUPLE or (field.shape == SHAPE_GENERIC and not issubclass(field.type_, BaseModel)): + sub_schema = [] + sub_fields = cast(List[ModelField], field.sub_fields) + for sf in sub_fields: + sf_schema, sf_definitions, sf_nested_models = field_type_schema( + sf, + by_alias=by_alias, + model_name_map=model_name_map, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models, + ) + definitions.update(sf_definitions) + nested_models.update(sf_nested_models) + sub_schema.append(sf_schema) + + sub_fields_len = len(sub_fields) + if field.shape == SHAPE_GENERIC: + all_of_schemas = sub_schema[0] if sub_fields_len == 1 else {'type': 'array', 'items': sub_schema} + f_schema = {'allOf': [all_of_schemas]} + else: + f_schema = { + 'type': 'array', + 'minItems': sub_fields_len, + 'maxItems': sub_fields_len, + } + if sub_fields_len >= 1: + f_schema['items'] = sub_schema + else: + assert field.shape in {SHAPE_SINGLETON, SHAPE_GENERIC}, field.shape + f_schema, f_definitions, f_nested_models = field_singleton_schema( + field, + by_alias=by_alias, + model_name_map=model_name_map, + schema_overrides=schema_overrides, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models, + ) + definitions.update(f_definitions) + nested_models.update(f_nested_models) + + # check field type to avoid repeated calls to the same __modify_schema__ method + if field.type_ != field.outer_type_: + if field.shape == SHAPE_GENERIC: + field_type = field.type_ + else: + field_type = field.outer_type_ + modify_schema = getattr(field_type, '__modify_schema__', None) + if modify_schema: + _apply_modify_schema(modify_schema, field, f_schema) + return f_schema, definitions, nested_models + + +def model_process_schema( + model: TypeModelOrEnum, + *, + by_alias: bool = True, + model_name_map: Dict[TypeModelOrEnum, str], + ref_prefix: Optional[str] = None, + ref_template: str = default_ref_template, + known_models: Optional[TypeModelSet] = None, + field: Optional[ModelField] = None, +) -> Tuple[Dict[str, Any], Dict[str, Any], Set[str]]: + """ + Used by ``model_schema()``, you probably should be using that function. + + Take a single ``model`` and generate its schema. Also return additional schema definitions, from sub-models. The + sub-models of the returned schema will be referenced, but their definitions will not be included in the schema. All + the definitions are returned as the second value. + """ + from inspect import getdoc, signature + + known_models = known_models or set() + if lenient_issubclass(model, Enum): + model = cast(Type[Enum], model) + s = enum_process_schema(model, field=field) + return s, {}, set() + model = cast(Type['BaseModel'], model) + s = {'title': model.__config__.title or model.__name__} + doc = getdoc(model) + if doc: + s['description'] = doc + known_models.add(model) + m_schema, m_definitions, nested_models = model_type_schema( + model, + by_alias=by_alias, + model_name_map=model_name_map, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models, + ) + s.update(m_schema) + schema_extra = model.__config__.schema_extra + if callable(schema_extra): + if len(signature(schema_extra).parameters) == 1: + schema_extra(s) + else: + schema_extra(s, model) + else: + s.update(schema_extra) + return s, m_definitions, nested_models + + +def model_type_schema( + model: Type['BaseModel'], + *, + by_alias: bool, + model_name_map: Dict[TypeModelOrEnum, str], + ref_template: str, + ref_prefix: Optional[str] = None, + known_models: TypeModelSet, +) -> Tuple[Dict[str, Any], Dict[str, Any], Set[str]]: + """ + You probably should be using ``model_schema()``, this function is indirectly used by that function. + + Take a single ``model`` and generate the schema for its type only, not including additional + information as title, etc. Also return additional schema definitions, from sub-models. + """ + properties = {} + required = [] + definitions: Dict[str, Any] = {} + nested_models: Set[str] = set() + for k, f in model.__fields__.items(): + try: + f_schema, f_definitions, f_nested_models = field_schema( + f, + by_alias=by_alias, + model_name_map=model_name_map, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models, + ) + except SkipField as skip: + warnings.warn(skip.message, UserWarning) + continue + definitions.update(f_definitions) + nested_models.update(f_nested_models) + if by_alias: + properties[f.alias] = f_schema + if f.required: + required.append(f.alias) + else: + properties[k] = f_schema + if f.required: + required.append(k) + if ROOT_KEY in properties: + out_schema = properties[ROOT_KEY] + out_schema['title'] = model.__config__.title or model.__name__ + else: + out_schema = {'type': 'object', 'properties': properties} + if required: + out_schema['required'] = required + if model.__config__.extra == 'forbid': + out_schema['additionalProperties'] = False + return out_schema, definitions, nested_models + + +def enum_process_schema(enum: Type[Enum], *, field: Optional[ModelField] = None) -> Dict[str, Any]: + """ + Take a single `enum` and generate its schema. + + This is similar to the `model_process_schema` function, but applies to ``Enum`` objects. + """ + import inspect + + schema_: Dict[str, Any] = { + 'title': enum.__name__, + # Python assigns all enums a default docstring value of 'An enumeration', so + # all enums will have a description field even if not explicitly provided. + 'description': inspect.cleandoc(enum.__doc__ or 'An enumeration.'), + # Add enum values and the enum field type to the schema. + 'enum': [item.value for item in cast(Iterable[Enum], enum)], + } + + add_field_type_to_schema(enum, schema_) + + modify_schema = getattr(enum, '__modify_schema__', None) + if modify_schema: + _apply_modify_schema(modify_schema, field, schema_) + + return schema_ + + +def field_singleton_sub_fields_schema( + field: ModelField, + *, + by_alias: bool, + model_name_map: Dict[TypeModelOrEnum, str], + ref_template: str, + schema_overrides: bool = False, + ref_prefix: Optional[str] = None, + known_models: TypeModelSet, +) -> Tuple[Dict[str, Any], Dict[str, Any], Set[str]]: + """ + This function is indirectly used by ``field_schema()``, you probably should be using that function. + + Take a list of Pydantic ``ModelField`` from the declaration of a type with parameters, and generate their + schema. I.e., fields used as "type parameters", like ``str`` and ``int`` in ``Tuple[str, int]``. + """ + sub_fields = cast(List[ModelField], field.sub_fields) + definitions = {} + nested_models: Set[str] = set() + if len(sub_fields) == 1: + return field_type_schema( + sub_fields[0], + by_alias=by_alias, + model_name_map=model_name_map, + schema_overrides=schema_overrides, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models, + ) + else: + s: Dict[str, Any] = {} + # https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#discriminator-object + field_has_discriminator: bool = field.discriminator_key is not None + if field_has_discriminator: + assert field.sub_fields_mapping is not None + + discriminator_models_refs: Dict[str, Union[str, Dict[str, Any]]] = {} + + for discriminator_value, sub_field in field.sub_fields_mapping.items(): + if isinstance(discriminator_value, Enum): + discriminator_value = str(discriminator_value.value) + # sub_field is either a `BaseModel` or directly an `Annotated` `Union` of many + if is_union(get_origin(sub_field.type_)): + sub_models = get_sub_types(sub_field.type_) + discriminator_models_refs[discriminator_value] = { + model_name_map[sub_model]: get_schema_ref( + model_name_map[sub_model], ref_prefix, ref_template, False + ) + for sub_model in sub_models + } + else: + sub_field_type = sub_field.type_ + if hasattr(sub_field_type, '__pydantic_model__'): + sub_field_type = sub_field_type.__pydantic_model__ + + discriminator_model_name = model_name_map[sub_field_type] + discriminator_model_ref = get_schema_ref(discriminator_model_name, ref_prefix, ref_template, False) + discriminator_models_refs[discriminator_value] = discriminator_model_ref['$ref'] + + s['discriminator'] = { + 'propertyName': field.discriminator_alias, + 'mapping': discriminator_models_refs, + } + + sub_field_schemas = [] + for sf in sub_fields: + sub_schema, sub_definitions, sub_nested_models = field_type_schema( + sf, + by_alias=by_alias, + model_name_map=model_name_map, + schema_overrides=schema_overrides, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models, + ) + definitions.update(sub_definitions) + if schema_overrides and 'allOf' in sub_schema: + # if the sub_field is a referenced schema we only need the referenced + # object. Otherwise we will end up with several allOf inside anyOf/oneOf. + # See https://github.com/pydantic/pydantic/issues/1209 + sub_schema = sub_schema['allOf'][0] + + if sub_schema.keys() == {'discriminator', 'oneOf'}: + # we don't want discriminator information inside oneOf choices, this is dealt with elsewhere + sub_schema.pop('discriminator') + sub_field_schemas.append(sub_schema) + nested_models.update(sub_nested_models) + s['oneOf' if field_has_discriminator else 'anyOf'] = sub_field_schemas + return s, definitions, nested_models + + +# Order is important, e.g. subclasses of str must go before str +# this is used only for standard library types, custom types should use __modify_schema__ instead +field_class_to_schema: Tuple[Tuple[Any, Dict[str, Any]], ...] = ( + (Path, {'type': 'string', 'format': 'path'}), + (datetime, {'type': 'string', 'format': 'date-time'}), + (date, {'type': 'string', 'format': 'date'}), + (time, {'type': 'string', 'format': 'time'}), + (timedelta, {'type': 'number', 'format': 'time-delta'}), + (IPv4Network, {'type': 'string', 'format': 'ipv4network'}), + (IPv6Network, {'type': 'string', 'format': 'ipv6network'}), + (IPv4Interface, {'type': 'string', 'format': 'ipv4interface'}), + (IPv6Interface, {'type': 'string', 'format': 'ipv6interface'}), + (IPv4Address, {'type': 'string', 'format': 'ipv4'}), + (IPv6Address, {'type': 'string', 'format': 'ipv6'}), + (Pattern, {'type': 'string', 'format': 'regex'}), + (str, {'type': 'string'}), + (bytes, {'type': 'string', 'format': 'binary'}), + (bool, {'type': 'boolean'}), + (int, {'type': 'integer'}), + (float, {'type': 'number'}), + (Decimal, {'type': 'number'}), + (UUID, {'type': 'string', 'format': 'uuid'}), + (dict, {'type': 'object'}), + (list, {'type': 'array', 'items': {}}), + (tuple, {'type': 'array', 'items': {}}), + (set, {'type': 'array', 'items': {}, 'uniqueItems': True}), + (frozenset, {'type': 'array', 'items': {}, 'uniqueItems': True}), +) + +json_scheme = {'type': 'string', 'format': 'json-string'} + + +def add_field_type_to_schema(field_type: Any, schema_: Dict[str, Any]) -> None: + """ + Update the given `schema` with the type-specific metadata for the given `field_type`. + + This function looks through `field_class_to_schema` for a class that matches the given `field_type`, + and then modifies the given `schema` with the information from that type. + """ + for type_, t_schema in field_class_to_schema: + # Fallback for `typing.Pattern` and `re.Pattern` as they are not a valid class + if lenient_issubclass(field_type, type_) or field_type is type_ is Pattern: + schema_.update(t_schema) + break + + +def get_schema_ref(name: str, ref_prefix: Optional[str], ref_template: str, schema_overrides: bool) -> Dict[str, Any]: + if ref_prefix: + schema_ref = {'$ref': ref_prefix + name} + else: + schema_ref = {'$ref': ref_template.format(model=name)} + return {'allOf': [schema_ref]} if schema_overrides else schema_ref + + +def field_singleton_schema( # noqa: C901 (ignore complexity) + field: ModelField, + *, + by_alias: bool, + model_name_map: Dict[TypeModelOrEnum, str], + ref_template: str, + schema_overrides: bool = False, + ref_prefix: Optional[str] = None, + known_models: TypeModelSet, +) -> Tuple[Dict[str, Any], Dict[str, Any], Set[str]]: + """ + This function is indirectly used by ``field_schema()``, you should probably be using that function. + + Take a single Pydantic ``ModelField``, and return its schema and any additional definitions from sub-models. + """ + from pydantic.main import BaseModel + + definitions: Dict[str, Any] = {} + nested_models: Set[str] = set() + field_type = field.type_ + + # Recurse into this field if it contains sub_fields and is NOT a + # BaseModel OR that BaseModel is a const + if field.sub_fields and ( + (field.field_info and field.field_info.const) or not lenient_issubclass(field_type, BaseModel) + ): + return field_singleton_sub_fields_schema( + field, + by_alias=by_alias, + model_name_map=model_name_map, + schema_overrides=schema_overrides, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models, + ) + if field_type is Any or field_type is object or field_type.__class__ == TypeVar or get_origin(field_type) is type: + return {}, definitions, nested_models # no restrictions + if is_none_type(field_type): + return {'type': 'null'}, definitions, nested_models + if is_callable_type(field_type): + raise SkipField(f'Callable {field.name} was excluded from schema since JSON schema has no equivalent type.') + f_schema: Dict[str, Any] = {} + if field.field_info is not None and field.field_info.const: + f_schema['const'] = field.default + + if is_literal_type(field_type): + values = tuple(x.value if isinstance(x, Enum) else x for x in all_literal_values(field_type)) + + if len({v.__class__ for v in values}) > 1: + return field_schema( + multitypes_literal_field_for_schema(values, field), + by_alias=by_alias, + model_name_map=model_name_map, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models, + ) + + # All values have the same type + field_type = values[0].__class__ + f_schema['enum'] = list(values) + add_field_type_to_schema(field_type, f_schema) + elif lenient_issubclass(field_type, Enum): + enum_name = model_name_map[field_type] + f_schema, schema_overrides = get_field_info_schema(field, schema_overrides) + f_schema.update(get_schema_ref(enum_name, ref_prefix, ref_template, schema_overrides)) + definitions[enum_name] = enum_process_schema(field_type, field=field) + elif is_namedtuple(field_type): + sub_schema, *_ = model_process_schema( + field_type.__pydantic_model__, + by_alias=by_alias, + model_name_map=model_name_map, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models, + field=field, + ) + items_schemas = list(sub_schema['properties'].values()) + f_schema.update( + { + 'type': 'array', + 'items': items_schemas, + 'minItems': len(items_schemas), + 'maxItems': len(items_schemas), + } + ) + elif not hasattr(field_type, '__pydantic_model__'): + add_field_type_to_schema(field_type, f_schema) + + modify_schema = getattr(field_type, '__modify_schema__', None) + if modify_schema: + _apply_modify_schema(modify_schema, field, f_schema) + + if f_schema: + return f_schema, definitions, nested_models + + # Handle dataclass-based models + if lenient_issubclass(getattr(field_type, '__pydantic_model__', None), BaseModel): + field_type = field_type.__pydantic_model__ + + if issubclass(field_type, BaseModel): + model_name = model_name_map[field_type] + if field_type not in known_models: + sub_schema, sub_definitions, sub_nested_models = model_process_schema( + field_type, + by_alias=by_alias, + model_name_map=model_name_map, + ref_prefix=ref_prefix, + ref_template=ref_template, + known_models=known_models, + field=field, + ) + definitions.update(sub_definitions) + definitions[model_name] = sub_schema + nested_models.update(sub_nested_models) + else: + nested_models.add(model_name) + schema_ref = get_schema_ref(model_name, ref_prefix, ref_template, schema_overrides) + return schema_ref, definitions, nested_models + + # For generics with no args + args = get_args(field_type) + if args is not None and not args and Generic in field_type.__bases__: + return f_schema, definitions, nested_models + + raise ValueError(f'Value not declarable with JSON Schema, field: {field}') + + +def multitypes_literal_field_for_schema(values: Tuple[Any, ...], field: ModelField) -> ModelField: + """ + To support `Literal` with values of different types, we split it into multiple `Literal` with same type + e.g. `Literal['qwe', 'asd', 1, 2]` becomes `Union[Literal['qwe', 'asd'], Literal[1, 2]]` + """ + literal_distinct_types = defaultdict(list) + for v in values: + literal_distinct_types[v.__class__].append(v) + distinct_literals = (Literal[tuple(same_type_values)] for same_type_values in literal_distinct_types.values()) + + return ModelField( + name=field.name, + type_=Union[tuple(distinct_literals)], # type: ignore + class_validators=field.class_validators, + model_config=field.model_config, + default=field.default, + required=field.required, + alias=field.alias, + field_info=field.field_info, + ) + + +def encode_default(dft: Any) -> Any: + from pydantic.main import BaseModel + + if isinstance(dft, BaseModel) or is_dataclass(dft): + dft = cast('dict[str, Any]', pydantic_encoder(dft)) + + if isinstance(dft, dict): + return {encode_default(k): encode_default(v) for k, v in dft.items()} + elif isinstance(dft, Enum): + return dft.value + elif isinstance(dft, (int, float, str)): + return dft + elif isinstance(dft, (list, tuple)): + t = dft.__class__ + seq_args = (encode_default(v) for v in dft) + return t(*seq_args) if is_namedtuple(t) else t(seq_args) + elif dft is None: + return None + else: + return pydantic_encoder(dft) + + +_map_types_constraint: Dict[Any, Callable[..., type]] = {int: conint, float: confloat, Decimal: condecimal} + + +def get_annotation_from_field_info( + annotation: Any, field_info: FieldInfo, field_name: str, validate_assignment: bool = False +) -> Type[Any]: + """ + Get an annotation with validation implemented for numbers and strings based on the field_info. + :param annotation: an annotation from a field specification, as ``str``, ``ConstrainedStr`` + :param field_info: an instance of FieldInfo, possibly with declarations for validations and JSON Schema + :param field_name: name of the field for use in error messages + :param validate_assignment: default False, flag for BaseModel Config value of validate_assignment + :return: the same ``annotation`` if unmodified or a new annotation with validation in place + """ + constraints = field_info.get_constraints() + used_constraints: Set[str] = set() + if constraints: + annotation, used_constraints = get_annotation_with_constraints(annotation, field_info) + if validate_assignment: + used_constraints.add('allow_mutation') + + unused_constraints = constraints - used_constraints + if unused_constraints: + raise ValueError( + f'On field "{field_name}" the following field constraints are set but not enforced: ' + f'{", ".join(unused_constraints)}. ' + f'\nFor more details see https://docs.pydantic.dev/usage/schema/#unenforced-field-constraints' + ) + + return annotation + + +def get_annotation_with_constraints(annotation: Any, field_info: FieldInfo) -> Tuple[Type[Any], Set[str]]: # noqa: C901 + """ + Get an annotation with used constraints implemented for numbers and strings based on the field_info. + + :param annotation: an annotation from a field specification, as ``str``, ``ConstrainedStr`` + :param field_info: an instance of FieldInfo, possibly with declarations for validations and JSON Schema + :return: the same ``annotation`` if unmodified or a new annotation along with the used constraints. + """ + used_constraints: Set[str] = set() + + def go(type_: Any) -> Type[Any]: + if ( + is_literal_type(type_) + or isinstance(type_, ForwardRef) + or lenient_issubclass(type_, (ConstrainedList, ConstrainedSet, ConstrainedFrozenSet)) + ): + return type_ + origin = get_origin(type_) + if origin is not None: + args: Tuple[Any, ...] = get_args(type_) + if any(isinstance(a, ForwardRef) for a in args): + # forward refs cause infinite recursion below + return type_ + + if origin is Annotated: + return go(args[0]) + if is_union(origin): + return Union[tuple(go(a) for a in args)] # type: ignore + + if issubclass(origin, List) and ( + field_info.min_items is not None + or field_info.max_items is not None + or field_info.unique_items is not None + ): + used_constraints.update({'min_items', 'max_items', 'unique_items'}) + return conlist( + go(args[0]), + min_items=field_info.min_items, + max_items=field_info.max_items, + unique_items=field_info.unique_items, + ) + + if issubclass(origin, Set) and (field_info.min_items is not None or field_info.max_items is not None): + used_constraints.update({'min_items', 'max_items'}) + return conset(go(args[0]), min_items=field_info.min_items, max_items=field_info.max_items) + + if issubclass(origin, FrozenSet) and (field_info.min_items is not None or field_info.max_items is not None): + used_constraints.update({'min_items', 'max_items'}) + return confrozenset(go(args[0]), min_items=field_info.min_items, max_items=field_info.max_items) + + for t in (Tuple, List, Set, FrozenSet, Sequence): + if issubclass(origin, t): # type: ignore + return t[tuple(go(a) for a in args)] # type: ignore + + if issubclass(origin, Dict): + return Dict[args[0], go(args[1])] # type: ignore + + attrs: Optional[Tuple[str, ...]] = None + constraint_func: Optional[Callable[..., type]] = None + if isinstance(type_, type): + if issubclass(type_, (SecretStr, SecretBytes)): + attrs = ('max_length', 'min_length') + + def constraint_func(**kw: Any) -> Type[Any]: + return type(type_.__name__, (type_,), kw) + + elif issubclass(type_, str) and not issubclass(type_, (EmailStr, AnyUrl)): + attrs = ('max_length', 'min_length', 'regex') + if issubclass(type_, StrictStr): + + def constraint_func(**kw: Any) -> Type[Any]: + return type(type_.__name__, (type_,), kw) + + else: + constraint_func = constr + elif issubclass(type_, bytes): + attrs = ('max_length', 'min_length', 'regex') + if issubclass(type_, StrictBytes): + + def constraint_func(**kw: Any) -> Type[Any]: + return type(type_.__name__, (type_,), kw) + + else: + constraint_func = conbytes + elif issubclass(type_, numeric_types) and not issubclass( + type_, + ( + ConstrainedInt, + ConstrainedFloat, + ConstrainedDecimal, + ConstrainedList, + ConstrainedSet, + ConstrainedFrozenSet, + bool, + ), + ): + # Is numeric type + attrs = ('gt', 'lt', 'ge', 'le', 'multiple_of') + if issubclass(type_, float): + attrs += ('allow_inf_nan',) + if issubclass(type_, Decimal): + attrs += ('max_digits', 'decimal_places') + numeric_type = next(t for t in numeric_types if issubclass(type_, t)) # pragma: no branch + constraint_func = _map_types_constraint[numeric_type] + + if attrs: + used_constraints.update(set(attrs)) + kwargs = { + attr_name: attr + for attr_name, attr in ((attr_name, getattr(field_info, attr_name)) for attr_name in attrs) + if attr is not None + } + if kwargs: + constraint_func = cast(Callable[..., type], constraint_func) + return constraint_func(**kwargs) + return type_ + + return go(annotation), used_constraints + + +def normalize_name(name: str) -> str: + """ + Normalizes the given name. This can be applied to either a model *or* enum. + """ + return re.sub(r'[^a-zA-Z0-9.\-_]', '_', name) + + +class SkipField(Exception): + """ + Utility exception used to exclude fields from schema. + """ + + def __init__(self, message: str) -> None: + self.message = message diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/tools.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/tools.py new file mode 100644 index 0000000..ce33c1f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/tools.py @@ -0,0 +1,92 @@ +import json +from functools import lru_cache +from pathlib import Path +from typing import TYPE_CHECKING, Any, Callable, Optional, Type, TypeVar, Union + +from pydantic.parse import Protocol, load_file, load_str_bytes +from pydantic.types import StrBytes +from pydantic.typing import display_as_type + +__all__ = ('parse_file_as', 'parse_obj_as', 'parse_raw_as', 'schema_of', 'schema_json_of') + +NameFactory = Union[str, Callable[[Type[Any]], str]] + +if TYPE_CHECKING: + from pydantic.typing import DictStrAny + + +def _generate_parsing_type_name(type_: Any) -> str: + return f'ParsingModel[{display_as_type(type_)}]' + + +@lru_cache(maxsize=2048) +def _get_parsing_type(type_: Any, *, type_name: Optional[NameFactory] = None) -> Any: + from pydantic.main import create_model + + if type_name is None: + type_name = _generate_parsing_type_name + if not isinstance(type_name, str): + type_name = type_name(type_) + return create_model(type_name, __root__=(type_, ...)) + + +T = TypeVar('T') + + +def parse_obj_as(type_: Type[T], obj: Any, *, type_name: Optional[NameFactory] = None) -> T: + model_type = _get_parsing_type(type_, type_name=type_name) # type: ignore[arg-type] + return model_type(__root__=obj).__root__ + + +def parse_file_as( + type_: Type[T], + path: Union[str, Path], + *, + content_type: str = None, + encoding: str = 'utf8', + proto: Protocol = None, + allow_pickle: bool = False, + json_loads: Callable[[str], Any] = json.loads, + type_name: Optional[NameFactory] = None, +) -> T: + obj = load_file( + path, + proto=proto, + content_type=content_type, + encoding=encoding, + allow_pickle=allow_pickle, + json_loads=json_loads, + ) + return parse_obj_as(type_, obj, type_name=type_name) + + +def parse_raw_as( + type_: Type[T], + b: StrBytes, + *, + content_type: str = None, + encoding: str = 'utf8', + proto: Protocol = None, + allow_pickle: bool = False, + json_loads: Callable[[str], Any] = json.loads, + type_name: Optional[NameFactory] = None, +) -> T: + obj = load_str_bytes( + b, + proto=proto, + content_type=content_type, + encoding=encoding, + allow_pickle=allow_pickle, + json_loads=json_loads, + ) + return parse_obj_as(type_, obj, type_name=type_name) + + +def schema_of(type_: Any, *, title: Optional[NameFactory] = None, **schema_kwargs: Any) -> 'DictStrAny': + """Generate a JSON schema (as dict) for the passed model or dynamically generated one""" + return _get_parsing_type(type_, type_name=title).schema(**schema_kwargs) + + +def schema_json_of(type_: Any, *, title: Optional[NameFactory] = None, **schema_json_kwargs: Any) -> str: + """Generate a JSON schema (as JSON) for the passed model or dynamically generated one""" + return _get_parsing_type(type_, type_name=title).schema_json(**schema_json_kwargs) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/types.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/types.py new file mode 100644 index 0000000..b236683 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/types.py @@ -0,0 +1,1205 @@ +import abc +import math +import re +import warnings +from datetime import date +from decimal import Decimal, InvalidOperation +from enum import Enum +from pathlib import Path +from types import new_class +from typing import ( + TYPE_CHECKING, + Any, + Callable, + ClassVar, + Dict, + FrozenSet, + List, + Optional, + Pattern, + Set, + Tuple, + Type, + TypeVar, + Union, + cast, + overload, +) +from uuid import UUID +from weakref import WeakSet + +from pydantic import errors +from pydantic.datetime_parse import parse_date +from pydantic.utils import import_string, update_not_none +from pydantic.validators import ( + bytes_validator, + constr_length_validator, + constr_lower, + constr_strip_whitespace, + constr_upper, + decimal_validator, + float_finite_validator, + float_validator, + frozenset_validator, + int_validator, + list_validator, + number_multiple_validator, + number_size_validator, + path_exists_validator, + path_validator, + set_validator, + str_validator, + strict_bytes_validator, + strict_float_validator, + strict_int_validator, + strict_str_validator, +) + +__all__ = [ + 'NoneStr', + 'NoneBytes', + 'StrBytes', + 'NoneStrBytes', + 'StrictStr', + 'ConstrainedBytes', + 'conbytes', + 'ConstrainedList', + 'conlist', + 'ConstrainedSet', + 'conset', + 'ConstrainedFrozenSet', + 'confrozenset', + 'ConstrainedStr', + 'constr', + 'PyObject', + 'ConstrainedInt', + 'conint', + 'PositiveInt', + 'NegativeInt', + 'NonNegativeInt', + 'NonPositiveInt', + 'ConstrainedFloat', + 'confloat', + 'PositiveFloat', + 'NegativeFloat', + 'NonNegativeFloat', + 'NonPositiveFloat', + 'FiniteFloat', + 'ConstrainedDecimal', + 'condecimal', + 'UUID1', + 'UUID3', + 'UUID4', + 'UUID5', + 'FilePath', + 'DirectoryPath', + 'Json', + 'JsonWrapper', + 'SecretField', + 'SecretStr', + 'SecretBytes', + 'StrictBool', + 'StrictBytes', + 'StrictInt', + 'StrictFloat', + 'PaymentCardNumber', + 'ByteSize', + 'PastDate', + 'FutureDate', + 'ConstrainedDate', + 'condate', +] + +NoneStr = Optional[str] +NoneBytes = Optional[bytes] +StrBytes = Union[str, bytes] +NoneStrBytes = Optional[StrBytes] +OptionalInt = Optional[int] +OptionalIntFloat = Union[OptionalInt, float] +OptionalIntFloatDecimal = Union[OptionalIntFloat, Decimal] +OptionalDate = Optional[date] +StrIntFloat = Union[str, int, float] + +if TYPE_CHECKING: + from typing_extensions import Annotated + + from pydantic.dataclasses import Dataclass + from pydantic.main import BaseModel + from pydantic.typing import CallableGenerator + + ModelOrDc = Type[Union[BaseModel, Dataclass]] + +T = TypeVar('T') +_DEFINED_TYPES: 'WeakSet[type]' = WeakSet() + + +@overload +def _registered(typ: Type[T]) -> Type[T]: + pass + + +@overload +def _registered(typ: 'ConstrainedNumberMeta') -> 'ConstrainedNumberMeta': + pass + + +def _registered(typ: Union[Type[T], 'ConstrainedNumberMeta']) -> Union[Type[T], 'ConstrainedNumberMeta']: + # In order to generate valid examples of constrained types, Hypothesis needs + # to inspect the type object - so we keep a weakref to each contype object + # until it can be registered. When (or if) our Hypothesis plugin is loaded, + # it monkeypatches this function. + # If Hypothesis is never used, the total effect is to keep a weak reference + # which has minimal memory usage and doesn't even affect garbage collection. + _DEFINED_TYPES.add(typ) + return typ + + +class ConstrainedNumberMeta(type): + def __new__(cls, name: str, bases: Any, dct: Dict[str, Any]) -> 'ConstrainedInt': # type: ignore + new_cls = cast('ConstrainedInt', type.__new__(cls, name, bases, dct)) + + if new_cls.gt is not None and new_cls.ge is not None: + raise errors.ConfigError('bounds gt and ge cannot be specified at the same time') + if new_cls.lt is not None and new_cls.le is not None: + raise errors.ConfigError('bounds lt and le cannot be specified at the same time') + + return _registered(new_cls) # type: ignore + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ BOOLEAN TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +if TYPE_CHECKING: + StrictBool = bool +else: + + class StrictBool(int): + """ + StrictBool to allow for bools which are not type-coerced. + """ + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update(type='boolean') + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.validate + + @classmethod + def validate(cls, value: Any) -> bool: + """ + Ensure that we only allow bools. + """ + if isinstance(value, bool): + return value + + raise errors.StrictBoolError() + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTEGER TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +class ConstrainedInt(int, metaclass=ConstrainedNumberMeta): + strict: bool = False + gt: OptionalInt = None + ge: OptionalInt = None + lt: OptionalInt = None + le: OptionalInt = None + multiple_of: OptionalInt = None + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + update_not_none( + field_schema, + exclusiveMinimum=cls.gt, + exclusiveMaximum=cls.lt, + minimum=cls.ge, + maximum=cls.le, + multipleOf=cls.multiple_of, + ) + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield strict_int_validator if cls.strict else int_validator + yield number_size_validator + yield number_multiple_validator + + +def conint( + *, + strict: bool = False, + gt: Optional[int] = None, + ge: Optional[int] = None, + lt: Optional[int] = None, + le: Optional[int] = None, + multiple_of: Optional[int] = None, +) -> Type[int]: + # use kwargs then define conf in a dict to aid with IDE type hinting + namespace = dict(strict=strict, gt=gt, ge=ge, lt=lt, le=le, multiple_of=multiple_of) + return type('ConstrainedIntValue', (ConstrainedInt,), namespace) + + +if TYPE_CHECKING: + PositiveInt = int + NegativeInt = int + NonPositiveInt = int + NonNegativeInt = int + StrictInt = int +else: + + class PositiveInt(ConstrainedInt): + gt = 0 + + class NegativeInt(ConstrainedInt): + lt = 0 + + class NonPositiveInt(ConstrainedInt): + le = 0 + + class NonNegativeInt(ConstrainedInt): + ge = 0 + + class StrictInt(ConstrainedInt): + strict = True + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ FLOAT TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +class ConstrainedFloat(float, metaclass=ConstrainedNumberMeta): + strict: bool = False + gt: OptionalIntFloat = None + ge: OptionalIntFloat = None + lt: OptionalIntFloat = None + le: OptionalIntFloat = None + multiple_of: OptionalIntFloat = None + allow_inf_nan: Optional[bool] = None + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + update_not_none( + field_schema, + exclusiveMinimum=cls.gt, + exclusiveMaximum=cls.lt, + minimum=cls.ge, + maximum=cls.le, + multipleOf=cls.multiple_of, + ) + # Modify constraints to account for differences between IEEE floats and JSON + if field_schema.get('exclusiveMinimum') == -math.inf: + del field_schema['exclusiveMinimum'] + if field_schema.get('minimum') == -math.inf: + del field_schema['minimum'] + if field_schema.get('exclusiveMaximum') == math.inf: + del field_schema['exclusiveMaximum'] + if field_schema.get('maximum') == math.inf: + del field_schema['maximum'] + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield strict_float_validator if cls.strict else float_validator + yield number_size_validator + yield number_multiple_validator + yield float_finite_validator + + +def confloat( + *, + strict: bool = False, + gt: float = None, + ge: float = None, + lt: float = None, + le: float = None, + multiple_of: float = None, + allow_inf_nan: Optional[bool] = None, +) -> Type[float]: + # use kwargs then define conf in a dict to aid with IDE type hinting + namespace = dict(strict=strict, gt=gt, ge=ge, lt=lt, le=le, multiple_of=multiple_of, allow_inf_nan=allow_inf_nan) + return type('ConstrainedFloatValue', (ConstrainedFloat,), namespace) + + +if TYPE_CHECKING: + PositiveFloat = float + NegativeFloat = float + NonPositiveFloat = float + NonNegativeFloat = float + StrictFloat = float + FiniteFloat = float +else: + + class PositiveFloat(ConstrainedFloat): + gt = 0 + + class NegativeFloat(ConstrainedFloat): + lt = 0 + + class NonPositiveFloat(ConstrainedFloat): + le = 0 + + class NonNegativeFloat(ConstrainedFloat): + ge = 0 + + class StrictFloat(ConstrainedFloat): + strict = True + + class FiniteFloat(ConstrainedFloat): + allow_inf_nan = False + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ BYTES TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +class ConstrainedBytes(bytes): + strip_whitespace = False + to_upper = False + to_lower = False + min_length: OptionalInt = None + max_length: OptionalInt = None + strict: bool = False + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + update_not_none(field_schema, minLength=cls.min_length, maxLength=cls.max_length) + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield strict_bytes_validator if cls.strict else bytes_validator + yield constr_strip_whitespace + yield constr_upper + yield constr_lower + yield constr_length_validator + + +def conbytes( + *, + strip_whitespace: bool = False, + to_upper: bool = False, + to_lower: bool = False, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + strict: bool = False, +) -> Type[bytes]: + # use kwargs then define conf in a dict to aid with IDE type hinting + namespace = dict( + strip_whitespace=strip_whitespace, + to_upper=to_upper, + to_lower=to_lower, + min_length=min_length, + max_length=max_length, + strict=strict, + ) + return _registered(type('ConstrainedBytesValue', (ConstrainedBytes,), namespace)) + + +if TYPE_CHECKING: + StrictBytes = bytes +else: + + class StrictBytes(ConstrainedBytes): + strict = True + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ STRING TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +class ConstrainedStr(str): + strip_whitespace = False + to_upper = False + to_lower = False + min_length: OptionalInt = None + max_length: OptionalInt = None + curtail_length: OptionalInt = None + regex: Optional[Union[str, Pattern[str]]] = None + strict = False + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + update_not_none( + field_schema, + minLength=cls.min_length, + maxLength=cls.max_length, + pattern=cls.regex and cls._get_pattern(cls.regex), + ) + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield strict_str_validator if cls.strict else str_validator + yield constr_strip_whitespace + yield constr_upper + yield constr_lower + yield constr_length_validator + yield cls.validate + + @classmethod + def validate(cls, value: Union[str]) -> Union[str]: + if cls.curtail_length and len(value) > cls.curtail_length: + value = value[: cls.curtail_length] + + if cls.regex: + if not re.match(cls.regex, value): + raise errors.StrRegexError(pattern=cls._get_pattern(cls.regex)) + + return value + + @staticmethod + def _get_pattern(regex: Union[str, Pattern[str]]) -> str: + return regex if isinstance(regex, str) else regex.pattern + + +def constr( + *, + strip_whitespace: bool = False, + to_upper: bool = False, + to_lower: bool = False, + strict: bool = False, + min_length: Optional[int] = None, + max_length: Optional[int] = None, + curtail_length: Optional[int] = None, + regex: Optional[str] = None, +) -> Type[str]: + # use kwargs then define conf in a dict to aid with IDE type hinting + namespace = dict( + strip_whitespace=strip_whitespace, + to_upper=to_upper, + to_lower=to_lower, + strict=strict, + min_length=min_length, + max_length=max_length, + curtail_length=curtail_length, + regex=regex and re.compile(regex), + ) + return _registered(type('ConstrainedStrValue', (ConstrainedStr,), namespace)) + + +if TYPE_CHECKING: + StrictStr = str +else: + + class StrictStr(ConstrainedStr): + strict = True + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SET TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +# This types superclass should be Set[T], but cython chokes on that... +class ConstrainedSet(set): # type: ignore + # Needed for pydantic to detect that this is a set + __origin__ = set + __args__: Set[Type[T]] # type: ignore + + min_items: Optional[int] = None + max_items: Optional[int] = None + item_type: Type[T] # type: ignore + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.set_length_validator + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + update_not_none(field_schema, minItems=cls.min_items, maxItems=cls.max_items) + + @classmethod + def set_length_validator(cls, v: 'Optional[Set[T]]') -> 'Optional[Set[T]]': + if v is None: + return None + + v = set_validator(v) + v_len = len(v) + + if cls.min_items is not None and v_len < cls.min_items: + raise errors.SetMinLengthError(limit_value=cls.min_items) + + if cls.max_items is not None and v_len > cls.max_items: + raise errors.SetMaxLengthError(limit_value=cls.max_items) + + return v + + +def conset(item_type: Type[T], *, min_items: Optional[int] = None, max_items: Optional[int] = None) -> Type[Set[T]]: + # __args__ is needed to conform to typing generics api + namespace = {'min_items': min_items, 'max_items': max_items, 'item_type': item_type, '__args__': [item_type]} + # We use new_class to be able to deal with Generic types + return new_class('ConstrainedSetValue', (ConstrainedSet,), {}, lambda ns: ns.update(namespace)) + + +# This types superclass should be FrozenSet[T], but cython chokes on that... +class ConstrainedFrozenSet(frozenset): # type: ignore + # Needed for pydantic to detect that this is a set + __origin__ = frozenset + __args__: FrozenSet[Type[T]] # type: ignore + + min_items: Optional[int] = None + max_items: Optional[int] = None + item_type: Type[T] # type: ignore + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.frozenset_length_validator + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + update_not_none(field_schema, minItems=cls.min_items, maxItems=cls.max_items) + + @classmethod + def frozenset_length_validator(cls, v: 'Optional[FrozenSet[T]]') -> 'Optional[FrozenSet[T]]': + if v is None: + return None + + v = frozenset_validator(v) + v_len = len(v) + + if cls.min_items is not None and v_len < cls.min_items: + raise errors.FrozenSetMinLengthError(limit_value=cls.min_items) + + if cls.max_items is not None and v_len > cls.max_items: + raise errors.FrozenSetMaxLengthError(limit_value=cls.max_items) + + return v + + +def confrozenset( + item_type: Type[T], *, min_items: Optional[int] = None, max_items: Optional[int] = None +) -> Type[FrozenSet[T]]: + # __args__ is needed to conform to typing generics api + namespace = {'min_items': min_items, 'max_items': max_items, 'item_type': item_type, '__args__': [item_type]} + # We use new_class to be able to deal with Generic types + return new_class('ConstrainedFrozenSetValue', (ConstrainedFrozenSet,), {}, lambda ns: ns.update(namespace)) + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LIST TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +# This types superclass should be List[T], but cython chokes on that... +class ConstrainedList(list): # type: ignore + # Needed for pydantic to detect that this is a list + __origin__ = list + __args__: Tuple[Type[T], ...] # type: ignore + + min_items: Optional[int] = None + max_items: Optional[int] = None + unique_items: Optional[bool] = None + item_type: Type[T] # type: ignore + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.list_length_validator + if cls.unique_items: + yield cls.unique_items_validator + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + update_not_none(field_schema, minItems=cls.min_items, maxItems=cls.max_items, uniqueItems=cls.unique_items) + + @classmethod + def list_length_validator(cls, v: 'Optional[List[T]]') -> 'Optional[List[T]]': + if v is None: + return None + + v = list_validator(v) + v_len = len(v) + + if cls.min_items is not None and v_len < cls.min_items: + raise errors.ListMinLengthError(limit_value=cls.min_items) + + if cls.max_items is not None and v_len > cls.max_items: + raise errors.ListMaxLengthError(limit_value=cls.max_items) + + return v + + @classmethod + def unique_items_validator(cls, v: 'Optional[List[T]]') -> 'Optional[List[T]]': + if v is None: + return None + + for i, value in enumerate(v, start=1): + if value in v[i:]: + raise errors.ListUniqueItemsError() + + return v + + +def conlist( + item_type: Type[T], *, min_items: Optional[int] = None, max_items: Optional[int] = None, unique_items: bool = None +) -> Type[List[T]]: + # __args__ is needed to conform to typing generics api + namespace = dict( + min_items=min_items, max_items=max_items, unique_items=unique_items, item_type=item_type, __args__=(item_type,) + ) + # We use new_class to be able to deal with Generic types + return new_class('ConstrainedListValue', (ConstrainedList,), {}, lambda ns: ns.update(namespace)) + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PYOBJECT TYPE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +if TYPE_CHECKING: + PyObject = Callable[..., Any] +else: + + class PyObject: + validate_always = True + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.validate + + @classmethod + def validate(cls, value: Any) -> Any: + if isinstance(value, Callable): + return value + + try: + value = str_validator(value) + except errors.StrError: + raise errors.PyObjectError(error_message='value is neither a valid import path not a valid callable') + + try: + return import_string(value) + except ImportError as e: + raise errors.PyObjectError(error_message=str(e)) + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DECIMAL TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +class ConstrainedDecimal(Decimal, metaclass=ConstrainedNumberMeta): + gt: OptionalIntFloatDecimal = None + ge: OptionalIntFloatDecimal = None + lt: OptionalIntFloatDecimal = None + le: OptionalIntFloatDecimal = None + max_digits: OptionalInt = None + decimal_places: OptionalInt = None + multiple_of: OptionalIntFloatDecimal = None + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + update_not_none( + field_schema, + exclusiveMinimum=cls.gt, + exclusiveMaximum=cls.lt, + minimum=cls.ge, + maximum=cls.le, + multipleOf=cls.multiple_of, + ) + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield decimal_validator + yield number_size_validator + yield number_multiple_validator + yield cls.validate + + @classmethod + def validate(cls, value: Decimal) -> Decimal: + try: + normalized_value = value.normalize() + except InvalidOperation: + normalized_value = value + digit_tuple, exponent = normalized_value.as_tuple()[1:] + if exponent in {'F', 'n', 'N'}: + raise errors.DecimalIsNotFiniteError() + + if exponent >= 0: + # A positive exponent adds that many trailing zeros. + digits = len(digit_tuple) + exponent + decimals = 0 + else: + # If the absolute value of the negative exponent is larger than the + # number of digits, then it's the same as the number of digits, + # because it'll consume all of the digits in digit_tuple and then + # add abs(exponent) - len(digit_tuple) leading zeros after the + # decimal point. + if abs(exponent) > len(digit_tuple): + digits = decimals = abs(exponent) + else: + digits = len(digit_tuple) + decimals = abs(exponent) + whole_digits = digits - decimals + + if cls.max_digits is not None and digits > cls.max_digits: + raise errors.DecimalMaxDigitsError(max_digits=cls.max_digits) + + if cls.decimal_places is not None and decimals > cls.decimal_places: + raise errors.DecimalMaxPlacesError(decimal_places=cls.decimal_places) + + if cls.max_digits is not None and cls.decimal_places is not None: + expected = cls.max_digits - cls.decimal_places + if whole_digits > expected: + raise errors.DecimalWholeDigitsError(whole_digits=expected) + + return value + + +def condecimal( + *, + gt: Decimal = None, + ge: Decimal = None, + lt: Decimal = None, + le: Decimal = None, + max_digits: Optional[int] = None, + decimal_places: Optional[int] = None, + multiple_of: Decimal = None, +) -> Type[Decimal]: + # use kwargs then define conf in a dict to aid with IDE type hinting + namespace = dict( + gt=gt, ge=ge, lt=lt, le=le, max_digits=max_digits, decimal_places=decimal_places, multiple_of=multiple_of + ) + return type('ConstrainedDecimalValue', (ConstrainedDecimal,), namespace) + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ UUID TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +if TYPE_CHECKING: + UUID1 = UUID + UUID3 = UUID + UUID4 = UUID + UUID5 = UUID +else: + + class UUID1(UUID): + _required_version = 1 + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update(type='string', format=f'uuid{cls._required_version}') + + class UUID3(UUID1): + _required_version = 3 + + class UUID4(UUID1): + _required_version = 4 + + class UUID5(UUID1): + _required_version = 5 + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PATH TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +if TYPE_CHECKING: + FilePath = Path + DirectoryPath = Path +else: + + class FilePath(Path): + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update(format='file-path') + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield path_validator + yield path_exists_validator + yield cls.validate + + @classmethod + def validate(cls, value: Path) -> Path: + if not value.is_file(): + raise errors.PathNotAFileError(path=value) + + return value + + class DirectoryPath(Path): + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update(format='directory-path') + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield path_validator + yield path_exists_validator + yield cls.validate + + @classmethod + def validate(cls, value: Path) -> Path: + if not value.is_dir(): + raise errors.PathNotADirectoryError(path=value) + + return value + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON TYPE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +class JsonWrapper: + pass + + +class JsonMeta(type): + def __getitem__(self, t: Type[Any]) -> Type[JsonWrapper]: + if t is Any: + return Json # allow Json[Any] to replecate plain Json + return _registered(type('JsonWrapperValue', (JsonWrapper,), {'inner_type': t})) + + +if TYPE_CHECKING: + Json = Annotated[T, ...] # Json[list[str]] will be recognized by type checkers as list[str] + +else: + + class Json(metaclass=JsonMeta): + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + field_schema.update(type='string', format='json-string') + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SECRET TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +class SecretField(abc.ABC): + """ + Note: this should be implemented as a generic like `SecretField(ABC, Generic[T])`, + the `__init__()` should be part of the abstract class and the + `get_secret_value()` method should use the generic `T` type. + + However Cython doesn't support very well generics at the moment and + the generated code fails to be imported (see + https://github.com/cython/cython/issues/2753). + """ + + def __eq__(self, other: Any) -> bool: + return isinstance(other, self.__class__) and self.get_secret_value() == other.get_secret_value() + + def __str__(self) -> str: + return '**********' if self.get_secret_value() else '' + + def __hash__(self) -> int: + return hash(self.get_secret_value()) + + @abc.abstractmethod + def get_secret_value(self) -> Any: # pragma: no cover + ... + + +class SecretStr(SecretField): + min_length: OptionalInt = None + max_length: OptionalInt = None + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + update_not_none( + field_schema, + type='string', + writeOnly=True, + format='password', + minLength=cls.min_length, + maxLength=cls.max_length, + ) + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.validate + yield constr_length_validator + + @classmethod + def validate(cls, value: Any) -> 'SecretStr': + if isinstance(value, cls): + return value + value = str_validator(value) + return cls(value) + + def __init__(self, value: str): + self._secret_value = value + + def __repr__(self) -> str: + return f"SecretStr('{self}')" + + def __len__(self) -> int: + return len(self._secret_value) + + def display(self) -> str: + warnings.warn('`secret_str.display()` is deprecated, use `str(secret_str)` instead', DeprecationWarning) + return str(self) + + def get_secret_value(self) -> str: + return self._secret_value + + +class SecretBytes(SecretField): + min_length: OptionalInt = None + max_length: OptionalInt = None + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + update_not_none( + field_schema, + type='string', + writeOnly=True, + format='password', + minLength=cls.min_length, + maxLength=cls.max_length, + ) + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.validate + yield constr_length_validator + + @classmethod + def validate(cls, value: Any) -> 'SecretBytes': + if isinstance(value, cls): + return value + value = bytes_validator(value) + return cls(value) + + def __init__(self, value: bytes): + self._secret_value = value + + def __repr__(self) -> str: + return f"SecretBytes(b'{self}')" + + def __len__(self) -> int: + return len(self._secret_value) + + def display(self) -> str: + warnings.warn('`secret_bytes.display()` is deprecated, use `str(secret_bytes)` instead', DeprecationWarning) + return str(self) + + def get_secret_value(self) -> bytes: + return self._secret_value + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PAYMENT CARD TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +class PaymentCardBrand(str, Enum): + # If you add another card type, please also add it to the + # Hypothesis strategy in `pydantic._hypothesis_plugin`. + amex = 'American Express' + mastercard = 'Mastercard' + visa = 'Visa' + other = 'other' + + def __str__(self) -> str: + return self.value + + +class PaymentCardNumber(str): + """ + Based on: https://en.wikipedia.org/wiki/Payment_card_number + """ + + strip_whitespace: ClassVar[bool] = True + min_length: ClassVar[int] = 12 + max_length: ClassVar[int] = 19 + bin: str + last4: str + brand: PaymentCardBrand + + def __init__(self, card_number: str): + self.bin = card_number[:6] + self.last4 = card_number[-4:] + self.brand = self._get_brand(card_number) + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield str_validator + yield constr_strip_whitespace + yield constr_length_validator + yield cls.validate_digits + yield cls.validate_luhn_check_digit + yield cls + yield cls.validate_length_for_brand + + @property + def masked(self) -> str: + num_masked = len(self) - 10 # len(bin) + len(last4) == 10 + return f'{self.bin}{"*" * num_masked}{self.last4}' + + @classmethod + def validate_digits(cls, card_number: str) -> str: + if not card_number.isdigit(): + raise errors.NotDigitError + return card_number + + @classmethod + def validate_luhn_check_digit(cls, card_number: str) -> str: + """ + Based on: https://en.wikipedia.org/wiki/Luhn_algorithm + """ + sum_ = int(card_number[-1]) + length = len(card_number) + parity = length % 2 + for i in range(length - 1): + digit = int(card_number[i]) + if i % 2 == parity: + digit *= 2 + if digit > 9: + digit -= 9 + sum_ += digit + valid = sum_ % 10 == 0 + if not valid: + raise errors.LuhnValidationError + return card_number + + @classmethod + def validate_length_for_brand(cls, card_number: 'PaymentCardNumber') -> 'PaymentCardNumber': + """ + Validate length based on BIN for major brands: + https://en.wikipedia.org/wiki/Payment_card_number#Issuer_identification_number_(IIN) + """ + required_length: Union[None, int, str] = None + if card_number.brand in PaymentCardBrand.mastercard: + required_length = 16 + valid = len(card_number) == required_length + elif card_number.brand == PaymentCardBrand.visa: + required_length = '13, 16 or 19' + valid = len(card_number) in {13, 16, 19} + elif card_number.brand == PaymentCardBrand.amex: + required_length = 15 + valid = len(card_number) == required_length + else: + valid = True + if not valid: + raise errors.InvalidLengthForBrand(brand=card_number.brand, required_length=required_length) + return card_number + + @staticmethod + def _get_brand(card_number: str) -> PaymentCardBrand: + if card_number[0] == '4': + brand = PaymentCardBrand.visa + elif 51 <= int(card_number[:2]) <= 55: + brand = PaymentCardBrand.mastercard + elif card_number[:2] in {'34', '37'}: + brand = PaymentCardBrand.amex + else: + brand = PaymentCardBrand.other + return brand + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ BYTE SIZE TYPE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +BYTE_SIZES = { + 'b': 1, + 'kb': 10**3, + 'mb': 10**6, + 'gb': 10**9, + 'tb': 10**12, + 'pb': 10**15, + 'eb': 10**18, + 'kib': 2**10, + 'mib': 2**20, + 'gib': 2**30, + 'tib': 2**40, + 'pib': 2**50, + 'eib': 2**60, +} +BYTE_SIZES.update({k.lower()[0]: v for k, v in BYTE_SIZES.items() if 'i' not in k}) +byte_string_re = re.compile(r'^\s*(\d*\.?\d+)\s*(\w+)?', re.IGNORECASE) + + +class ByteSize(int): + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield cls.validate + + @classmethod + def validate(cls, v: StrIntFloat) -> 'ByteSize': + try: + return cls(int(v)) + except ValueError: + pass + + str_match = byte_string_re.match(str(v)) + if str_match is None: + raise errors.InvalidByteSize() + + scalar, unit = str_match.groups() + if unit is None: + unit = 'b' + + try: + unit_mult = BYTE_SIZES[unit.lower()] + except KeyError: + raise errors.InvalidByteSizeUnit(unit=unit) + + return cls(int(float(scalar) * unit_mult)) + + def human_readable(self, decimal: bool = False) -> str: + if decimal: + divisor = 1000 + units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'] + final_unit = 'EB' + else: + divisor = 1024 + units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB'] + final_unit = 'EiB' + + num = float(self) + for unit in units: + if abs(num) < divisor: + return f'{num:0.1f}{unit}' + num /= divisor + + return f'{num:0.1f}{final_unit}' + + def to(self, unit: str) -> float: + try: + unit_div = BYTE_SIZES[unit.lower()] + except KeyError: + raise errors.InvalidByteSizeUnit(unit=unit) + + return self / unit_div + + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DATE TYPES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +if TYPE_CHECKING: + PastDate = date + FutureDate = date +else: + + class PastDate(date): + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield parse_date + yield cls.validate + + @classmethod + def validate(cls, value: date) -> date: + if value >= date.today(): + raise errors.DateNotInThePastError() + + return value + + class FutureDate(date): + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield parse_date + yield cls.validate + + @classmethod + def validate(cls, value: date) -> date: + if value <= date.today(): + raise errors.DateNotInTheFutureError() + + return value + + +class ConstrainedDate(date, metaclass=ConstrainedNumberMeta): + gt: OptionalDate = None + ge: OptionalDate = None + lt: OptionalDate = None + le: OptionalDate = None + + @classmethod + def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None: + update_not_none(field_schema, exclusiveMinimum=cls.gt, exclusiveMaximum=cls.lt, minimum=cls.ge, maximum=cls.le) + + @classmethod + def __get_validators__(cls) -> 'CallableGenerator': + yield parse_date + yield number_size_validator + + +def condate( + *, + gt: date = None, + ge: date = None, + lt: date = None, + le: date = None, +) -> Type[date]: + # use kwargs then define conf in a dict to aid with IDE type hinting + namespace = dict(gt=gt, ge=ge, lt=lt, le=le) + return type('ConstrainedDateValue', (ConstrainedDate,), namespace) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/typing.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/typing.py new file mode 100644 index 0000000..297021d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/typing.py @@ -0,0 +1,605 @@ +import sys +import typing +from collections.abc import Callable +from os import PathLike +from typing import ( # type: ignore + TYPE_CHECKING, + AbstractSet, + Any, + Callable as TypingCallable, + ClassVar, + Dict, + ForwardRef, + Generator, + Iterable, + List, + Mapping, + NewType, + Optional, + Sequence, + Set, + Tuple, + Type, + TypeVar, + Union, + _eval_type, + cast, + get_type_hints, +) + +from typing_extensions import ( + Annotated, + Final, + Literal, + NotRequired as TypedDictNotRequired, + Required as TypedDictRequired, +) + +try: + from typing import _TypingBase as typing_base # type: ignore +except ImportError: + from typing import _Final as typing_base # type: ignore + +try: + from typing import GenericAlias as TypingGenericAlias # type: ignore +except ImportError: + # python < 3.9 does not have GenericAlias (list[int], tuple[str, ...] and so on) + TypingGenericAlias = () + +try: + from types import UnionType as TypesUnionType # type: ignore +except ImportError: + # python < 3.10 does not have UnionType (str | int, byte | bool and so on) + TypesUnionType = () + + +if sys.version_info < (3, 9): + + def evaluate_forwardref(type_: ForwardRef, globalns: Any, localns: Any) -> Any: + return type_._evaluate(globalns, localns) + +else: + + def evaluate_forwardref(type_: ForwardRef, globalns: Any, localns: Any) -> Any: + # Even though it is the right signature for python 3.9, mypy complains with + # `error: Too many arguments for "_evaluate" of "ForwardRef"` hence the cast... + # Python 3.13/3.12.4+ made `recursive_guard` a kwarg, so name it explicitly to avoid: + # TypeError: ForwardRef._evaluate() missing 1 required keyword-only argument: 'recursive_guard' + return cast(Any, type_)._evaluate(globalns, localns, recursive_guard=set()) + + +if sys.version_info < (3, 9): + # Ensure we always get all the whole `Annotated` hint, not just the annotated type. + # For 3.7 to 3.8, `get_type_hints` doesn't recognize `typing_extensions.Annotated`, + # so it already returns the full annotation + get_all_type_hints = get_type_hints + +else: + + def get_all_type_hints(obj: Any, globalns: Any = None, localns: Any = None) -> Any: + return get_type_hints(obj, globalns, localns, include_extras=True) + + +_T = TypeVar('_T') + +AnyCallable = TypingCallable[..., Any] +NoArgAnyCallable = TypingCallable[[], Any] + +# workaround for https://github.com/python/mypy/issues/9496 +AnyArgTCallable = TypingCallable[..., _T] + + +# Annotated[...] is implemented by returning an instance of one of these classes, depending on +# python/typing_extensions version. +AnnotatedTypeNames = {'AnnotatedMeta', '_AnnotatedAlias'} + + +LITERAL_TYPES: Set[Any] = {Literal} +if hasattr(typing, 'Literal'): + LITERAL_TYPES.add(typing.Literal) + + +if sys.version_info < (3, 8): + + def get_origin(t: Type[Any]) -> Optional[Type[Any]]: + if type(t).__name__ in AnnotatedTypeNames: + # weirdly this is a runtime requirement, as well as for mypy + return cast(Type[Any], Annotated) + return getattr(t, '__origin__', None) + +else: + from typing import get_origin as _typing_get_origin + + def get_origin(tp: Type[Any]) -> Optional[Type[Any]]: + """ + We can't directly use `typing.get_origin` since we need a fallback to support + custom generic classes like `ConstrainedList` + It should be useless once https://github.com/cython/cython/issues/3537 is + solved and https://github.com/pydantic/pydantic/pull/1753 is merged. + """ + if type(tp).__name__ in AnnotatedTypeNames: + return cast(Type[Any], Annotated) # mypy complains about _SpecialForm + return _typing_get_origin(tp) or getattr(tp, '__origin__', None) + + +if sys.version_info < (3, 8): + from typing import _GenericAlias + + def get_args(t: Type[Any]) -> Tuple[Any, ...]: + """Compatibility version of get_args for python 3.7. + + Mostly compatible with the python 3.8 `typing` module version + and able to handle almost all use cases. + """ + if type(t).__name__ in AnnotatedTypeNames: + return t.__args__ + t.__metadata__ + if isinstance(t, _GenericAlias): + res = t.__args__ + if t.__origin__ is Callable and res and res[0] is not Ellipsis: + res = (list(res[:-1]), res[-1]) + return res + return getattr(t, '__args__', ()) + +else: + from typing import get_args as _typing_get_args + + def _generic_get_args(tp: Type[Any]) -> Tuple[Any, ...]: + """ + In python 3.9, `typing.Dict`, `typing.List`, ... + do have an empty `__args__` by default (instead of the generic ~T for example). + In order to still support `Dict` for example and consider it as `Dict[Any, Any]`, + we retrieve the `_nparams` value that tells us how many parameters it needs. + """ + if hasattr(tp, '_nparams'): + return (Any,) * tp._nparams + # Special case for `tuple[()]`, which used to return ((),) with `typing.Tuple` + # in python 3.10- but now returns () for `tuple` and `Tuple`. + # This will probably be clarified in pydantic v2 + try: + if tp == Tuple[()] or sys.version_info >= (3, 9) and tp == tuple[()]: # type: ignore[misc] + return ((),) + # there is a TypeError when compiled with cython + except TypeError: # pragma: no cover + pass + return () + + def get_args(tp: Type[Any]) -> Tuple[Any, ...]: + """Get type arguments with all substitutions performed. + + For unions, basic simplifications used by Union constructor are performed. + Examples:: + get_args(Dict[str, int]) == (str, int) + get_args(int) == () + get_args(Union[int, Union[T, int], str][int]) == (int, str) + get_args(Union[int, Tuple[T, int]][str]) == (int, Tuple[str, int]) + get_args(Callable[[], T][int]) == ([], int) + """ + if type(tp).__name__ in AnnotatedTypeNames: + return tp.__args__ + tp.__metadata__ + # the fallback is needed for the same reasons as `get_origin` (see above) + return _typing_get_args(tp) or getattr(tp, '__args__', ()) or _generic_get_args(tp) + + +if sys.version_info < (3, 9): + + def convert_generics(tp: Type[Any]) -> Type[Any]: + """Python 3.9 and older only supports generics from `typing` module. + They convert strings to ForwardRef automatically. + + Examples:: + typing.List['Hero'] == typing.List[ForwardRef('Hero')] + """ + return tp + +else: + from typing import _UnionGenericAlias # type: ignore + + from typing_extensions import _AnnotatedAlias + + def convert_generics(tp: Type[Any]) -> Type[Any]: + """ + Recursively searches for `str` type hints and replaces them with ForwardRef. + + Examples:: + convert_generics(list['Hero']) == list[ForwardRef('Hero')] + convert_generics(dict['Hero', 'Team']) == dict[ForwardRef('Hero'), ForwardRef('Team')] + convert_generics(typing.Dict['Hero', 'Team']) == typing.Dict[ForwardRef('Hero'), ForwardRef('Team')] + convert_generics(list[str | 'Hero'] | int) == list[str | ForwardRef('Hero')] | int + """ + origin = get_origin(tp) + if not origin or not hasattr(tp, '__args__'): + return tp + + args = get_args(tp) + + # typing.Annotated needs special treatment + if origin is Annotated: + return _AnnotatedAlias(convert_generics(args[0]), args[1:]) + + # recursively replace `str` instances inside of `GenericAlias` with `ForwardRef(arg)` + converted = tuple( + ForwardRef(arg) if isinstance(arg, str) and isinstance(tp, TypingGenericAlias) else convert_generics(arg) + for arg in args + ) + + if converted == args: + return tp + elif isinstance(tp, TypingGenericAlias): + return TypingGenericAlias(origin, converted) + elif isinstance(tp, TypesUnionType): + # recreate types.UnionType (PEP604, Python >= 3.10) + return _UnionGenericAlias(origin, converted) + else: + try: + setattr(tp, '__args__', converted) + except AttributeError: + pass + return tp + + +if sys.version_info < (3, 10): + + def is_union(tp: Optional[Type[Any]]) -> bool: + return tp is Union + + WithArgsTypes = (TypingGenericAlias,) + +else: + import types + import typing + + def is_union(tp: Optional[Type[Any]]) -> bool: + return tp is Union or tp is types.UnionType # noqa: E721 + + WithArgsTypes = (typing._GenericAlias, types.GenericAlias, types.UnionType) + + +StrPath = Union[str, PathLike] + + +if TYPE_CHECKING: + from pydantic.fields import ModelField + + TupleGenerator = Generator[Tuple[str, Any], None, None] + DictStrAny = Dict[str, Any] + DictAny = Dict[Any, Any] + SetStr = Set[str] + ListStr = List[str] + IntStr = Union[int, str] + AbstractSetIntStr = AbstractSet[IntStr] + DictIntStrAny = Dict[IntStr, Any] + MappingIntStrAny = Mapping[IntStr, Any] + CallableGenerator = Generator[AnyCallable, None, None] + ReprArgs = Sequence[Tuple[Optional[str], Any]] + + MYPY = False + if MYPY: + AnyClassMethod = classmethod[Any] + else: + # classmethod[TargetType, CallableParamSpecType, CallableReturnType] + AnyClassMethod = classmethod[Any, Any, Any] + +__all__ = ( + 'AnyCallable', + 'NoArgAnyCallable', + 'NoneType', + 'is_none_type', + 'display_as_type', + 'resolve_annotations', + 'is_callable_type', + 'is_literal_type', + 'all_literal_values', + 'is_namedtuple', + 'is_typeddict', + 'is_typeddict_special', + 'is_new_type', + 'new_type_supertype', + 'is_classvar', + 'is_finalvar', + 'update_field_forward_refs', + 'update_model_forward_refs', + 'TupleGenerator', + 'DictStrAny', + 'DictAny', + 'SetStr', + 'ListStr', + 'IntStr', + 'AbstractSetIntStr', + 'DictIntStrAny', + 'CallableGenerator', + 'ReprArgs', + 'AnyClassMethod', + 'CallableGenerator', + 'WithArgsTypes', + 'get_args', + 'get_origin', + 'get_sub_types', + 'typing_base', + 'get_all_type_hints', + 'is_union', + 'StrPath', + 'MappingIntStrAny', +) + + +NoneType = None.__class__ + + +NONE_TYPES: Tuple[Any, Any, Any] = (None, NoneType, Literal[None]) + + +if sys.version_info < (3, 8): + # Even though this implementation is slower, we need it for python 3.7: + # In python 3.7 "Literal" is not a builtin type and uses a different + # mechanism. + # for this reason `Literal[None] is Literal[None]` evaluates to `False`, + # breaking the faster implementation used for the other python versions. + + def is_none_type(type_: Any) -> bool: + return type_ in NONE_TYPES + +elif sys.version_info[:2] == (3, 8): + + def is_none_type(type_: Any) -> bool: + for none_type in NONE_TYPES: + if type_ is none_type: + return True + # With python 3.8, specifically 3.8.10, Literal "is" check sare very flakey + # can change on very subtle changes like use of types in other modules, + # hopefully this check avoids that issue. + if is_literal_type(type_): # pragma: no cover + return all_literal_values(type_) == (None,) + return False + +else: + + def is_none_type(type_: Any) -> bool: + return type_ in NONE_TYPES + + +def display_as_type(v: Type[Any]) -> str: + if not isinstance(v, typing_base) and not isinstance(v, WithArgsTypes) and not isinstance(v, type): + v = v.__class__ + + if is_union(get_origin(v)): + return f'Union[{", ".join(map(display_as_type, get_args(v)))}]' + + if isinstance(v, WithArgsTypes): + # Generic alias are constructs like `list[int]` + return str(v).replace('typing.', '') + + try: + return v.__name__ + except AttributeError: + # happens with typing objects + return str(v).replace('typing.', '') + + +def resolve_annotations(raw_annotations: Dict[str, Type[Any]], module_name: Optional[str]) -> Dict[str, Type[Any]]: + """ + Partially taken from typing.get_type_hints. + + Resolve string or ForwardRef annotations into type objects if possible. + """ + base_globals: Optional[Dict[str, Any]] = None + if module_name: + try: + module = sys.modules[module_name] + except KeyError: + # happens occasionally, see https://github.com/pydantic/pydantic/issues/2363 + pass + else: + base_globals = module.__dict__ + + annotations = {} + for name, value in raw_annotations.items(): + if isinstance(value, str): + if (3, 10) > sys.version_info >= (3, 9, 8) or sys.version_info >= (3, 10, 1): + value = ForwardRef(value, is_argument=False, is_class=True) + else: + value = ForwardRef(value, is_argument=False) + try: + value = _eval_type(value, base_globals, None) + except NameError: + # this is ok, it can be fixed with update_forward_refs + pass + annotations[name] = value + return annotations + + +def is_callable_type(type_: Type[Any]) -> bool: + return type_ is Callable or get_origin(type_) is Callable + + +def is_literal_type(type_: Type[Any]) -> bool: + return Literal is not None and get_origin(type_) in LITERAL_TYPES + + +def literal_values(type_: Type[Any]) -> Tuple[Any, ...]: + return get_args(type_) + + +def all_literal_values(type_: Type[Any]) -> Tuple[Any, ...]: + """ + This method is used to retrieve all Literal values as + Literal can be used recursively (see https://www.python.org/dev/peps/pep-0586) + e.g. `Literal[Literal[Literal[1, 2, 3], "foo"], 5, None]` + """ + if not is_literal_type(type_): + return (type_,) + + values = literal_values(type_) + return tuple(x for value in values for x in all_literal_values(value)) + + +def is_namedtuple(type_: Type[Any]) -> bool: + """ + Check if a given class is a named tuple. + It can be either a `typing.NamedTuple` or `collections.namedtuple` + """ + from pydantic.utils import lenient_issubclass + + return lenient_issubclass(type_, tuple) and hasattr(type_, '_fields') + + +def is_typeddict(type_: Type[Any]) -> bool: + """ + Check if a given class is a typed dict (from `typing` or `typing_extensions`) + In 3.10, there will be a public method (https://docs.python.org/3.10/library/typing.html#typing.is_typeddict) + """ + from pydantic.utils import lenient_issubclass + + return lenient_issubclass(type_, dict) and hasattr(type_, '__total__') + + +def _check_typeddict_special(type_: Any) -> bool: + return type_ is TypedDictRequired or type_ is TypedDictNotRequired + + +def is_typeddict_special(type_: Any) -> bool: + """ + Check if type is a TypedDict special form (Required or NotRequired). + """ + return _check_typeddict_special(type_) or _check_typeddict_special(get_origin(type_)) + + +test_type = NewType('test_type', str) + + +def is_new_type(type_: Type[Any]) -> bool: + """ + Check whether type_ was created using typing.NewType + """ + return isinstance(type_, test_type.__class__) and hasattr(type_, '__supertype__') # type: ignore + + +def new_type_supertype(type_: Type[Any]) -> Type[Any]: + while hasattr(type_, '__supertype__'): + type_ = type_.__supertype__ + return type_ + + +def _check_classvar(v: Optional[Type[Any]]) -> bool: + if v is None: + return False + + return v.__class__ == ClassVar.__class__ and getattr(v, '_name', None) == 'ClassVar' + + +def _check_finalvar(v: Optional[Type[Any]]) -> bool: + """ + Check if a given type is a `typing.Final` type. + """ + if v is None: + return False + + return v.__class__ == Final.__class__ and (sys.version_info < (3, 8) or getattr(v, '_name', None) == 'Final') + + +def is_classvar(ann_type: Type[Any]) -> bool: + if _check_classvar(ann_type) or _check_classvar(get_origin(ann_type)): + return True + + # this is an ugly workaround for class vars that contain forward references and are therefore themselves + # forward references, see #3679 + if ann_type.__class__ == ForwardRef and ann_type.__forward_arg__.startswith('ClassVar['): + return True + + return False + + +def is_finalvar(ann_type: Type[Any]) -> bool: + return _check_finalvar(ann_type) or _check_finalvar(get_origin(ann_type)) + + +def update_field_forward_refs(field: 'ModelField', globalns: Any, localns: Any) -> None: + """ + Try to update ForwardRefs on fields based on this ModelField, globalns and localns. + """ + prepare = False + if field.type_.__class__ == ForwardRef: + prepare = True + field.type_ = evaluate_forwardref(field.type_, globalns, localns or None) + if field.outer_type_.__class__ == ForwardRef: + prepare = True + field.outer_type_ = evaluate_forwardref(field.outer_type_, globalns, localns or None) + if prepare: + field.prepare() + + if field.sub_fields: + for sub_f in field.sub_fields: + update_field_forward_refs(sub_f, globalns=globalns, localns=localns) + + if field.discriminator_key is not None: + field.prepare_discriminated_union_sub_fields() + + +def update_model_forward_refs( + model: Type[Any], + fields: Iterable['ModelField'], + json_encoders: Dict[Union[Type[Any], str, ForwardRef], AnyCallable], + localns: 'DictStrAny', + exc_to_suppress: Tuple[Type[BaseException], ...] = (), +) -> None: + """ + Try to update model fields ForwardRefs based on model and localns. + """ + if model.__module__ in sys.modules: + globalns = sys.modules[model.__module__].__dict__.copy() + else: + globalns = {} + + globalns.setdefault(model.__name__, model) + + for f in fields: + try: + update_field_forward_refs(f, globalns=globalns, localns=localns) + except exc_to_suppress: + pass + + for key in set(json_encoders.keys()): + if isinstance(key, str): + fr: ForwardRef = ForwardRef(key) + elif isinstance(key, ForwardRef): + fr = key + else: + continue + + try: + new_key = evaluate_forwardref(fr, globalns, localns or None) + except exc_to_suppress: # pragma: no cover + continue + + json_encoders[new_key] = json_encoders.pop(key) + + +def get_class(type_: Type[Any]) -> Union[None, bool, Type[Any]]: + """ + Tries to get the class of a Type[T] annotation. Returns True if Type is used + without brackets. Otherwise returns None. + """ + if type_ is type: + return True + + if get_origin(type_) is None: + return None + + args = get_args(type_) + if not args or not isinstance(args[0], type): + return True + else: + return args[0] + + +def get_sub_types(tp: Any) -> List[Any]: + """ + Return all the types that are allowed by type `tp` + `tp` can be a `Union` of allowed types or an `Annotated` type + """ + origin = get_origin(tp) + if origin is Annotated: + return get_sub_types(get_args(tp)[0]) + elif is_union(origin): + return [x for t in get_args(tp) for x in get_sub_types(t)] + else: + return [tp] diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/utils.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/utils.py new file mode 100644 index 0000000..7cf9c88 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/utils.py @@ -0,0 +1,803 @@ +import keyword +import warnings +import weakref +from collections import OrderedDict, defaultdict, deque +from copy import deepcopy +from itertools import islice, zip_longest +from types import BuiltinFunctionType, CodeType, FunctionType, GeneratorType, LambdaType, ModuleType +from typing import ( + TYPE_CHECKING, + AbstractSet, + Any, + Callable, + Collection, + Dict, + Generator, + Iterable, + Iterator, + List, + Mapping, + NoReturn, + Optional, + Set, + Tuple, + Type, + TypeVar, + Union, +) + +from typing_extensions import Annotated + +from pydantic.errors import ConfigError +from pydantic.typing import ( + NoneType, + WithArgsTypes, + all_literal_values, + display_as_type, + get_args, + get_origin, + is_literal_type, + is_union, +) +from pydantic.version import version_info + +if TYPE_CHECKING: + from inspect import Signature + from pathlib import Path + + from pydantic.config import BaseConfig + from pydantic.dataclasses import Dataclass + from pydantic.fields import ModelField + from pydantic.main import BaseModel + from pydantic.typing import AbstractSetIntStr, DictIntStrAny, IntStr, MappingIntStrAny, ReprArgs + + RichReprResult = Iterable[Union[Any, Tuple[Any], Tuple[str, Any], Tuple[str, Any, Any]]] + +__all__ = ( + 'import_string', + 'sequence_like', + 'validate_field_name', + 'lenient_isinstance', + 'lenient_issubclass', + 'in_ipython', + 'is_valid_identifier', + 'deep_update', + 'update_not_none', + 'almost_equal_floats', + 'get_model', + 'to_camel', + 'is_valid_field', + 'smart_deepcopy', + 'PyObjectStr', + 'Representation', + 'GetterDict', + 'ValueItems', + 'version_info', # required here to match behaviour in v1.3 + 'ClassAttribute', + 'path_type', + 'ROOT_KEY', + 'get_unique_discriminator_alias', + 'get_discriminator_alias_and_values', + 'DUNDER_ATTRIBUTES', +) + +ROOT_KEY = '__root__' +# these are types that are returned unchanged by deepcopy +IMMUTABLE_NON_COLLECTIONS_TYPES: Set[Type[Any]] = { + int, + float, + complex, + str, + bool, + bytes, + type, + NoneType, + FunctionType, + BuiltinFunctionType, + LambdaType, + weakref.ref, + CodeType, + # note: including ModuleType will differ from behaviour of deepcopy by not producing error. + # It might be not a good idea in general, but considering that this function used only internally + # against default values of fields, this will allow to actually have a field with module as default value + ModuleType, + NotImplemented.__class__, + Ellipsis.__class__, +} + +# these are types that if empty, might be copied with simple copy() instead of deepcopy() +BUILTIN_COLLECTIONS: Set[Type[Any]] = { + list, + set, + tuple, + frozenset, + dict, + OrderedDict, + defaultdict, + deque, +} + + +def import_string(dotted_path: str) -> Any: + """ + Stolen approximately from django. Import a dotted module path and return the attribute/class designated by the + last name in the path. Raise ImportError if the import fails. + """ + from importlib import import_module + + try: + module_path, class_name = dotted_path.strip(' ').rsplit('.', 1) + except ValueError as e: + raise ImportError(f'"{dotted_path}" doesn\'t look like a module path') from e + + module = import_module(module_path) + try: + return getattr(module, class_name) + except AttributeError as e: + raise ImportError(f'Module "{module_path}" does not define a "{class_name}" attribute') from e + + +def truncate(v: Union[str], *, max_len: int = 80) -> str: + """ + Truncate a value and add a unicode ellipsis (three dots) to the end if it was too long + """ + warnings.warn('`truncate` is no-longer used by pydantic and is deprecated', DeprecationWarning) + if isinstance(v, str) and len(v) > (max_len - 2): + # -3 so quote + string + … + quote has correct length + return (v[: (max_len - 3)] + '…').__repr__() + try: + v = v.__repr__() + except TypeError: + v = v.__class__.__repr__(v) # in case v is a type + if len(v) > max_len: + v = v[: max_len - 1] + '…' + return v + + +def sequence_like(v: Any) -> bool: + return isinstance(v, (list, tuple, set, frozenset, GeneratorType, deque)) + + +def validate_field_name(bases: List[Type['BaseModel']], field_name: str) -> None: + """ + Ensure that the field's name does not shadow an existing attribute of the model. + """ + for base in bases: + if getattr(base, field_name, None): + raise NameError( + f'Field name "{field_name}" shadows a BaseModel attribute; ' + f'use a different field name with "alias=\'{field_name}\'".' + ) + + +def lenient_isinstance(o: Any, class_or_tuple: Union[Type[Any], Tuple[Type[Any], ...], None]) -> bool: + try: + return isinstance(o, class_or_tuple) # type: ignore[arg-type] + except TypeError: + return False + + +def lenient_issubclass(cls: Any, class_or_tuple: Union[Type[Any], Tuple[Type[Any], ...], None]) -> bool: + try: + return isinstance(cls, type) and issubclass(cls, class_or_tuple) # type: ignore[arg-type] + except TypeError: + if isinstance(cls, WithArgsTypes): + return False + raise # pragma: no cover + + +def in_ipython() -> bool: + """ + Check whether we're in an ipython environment, including jupyter notebooks. + """ + try: + eval('__IPYTHON__') + except NameError: + return False + else: # pragma: no cover + return True + + +def is_valid_identifier(identifier: str) -> bool: + """ + Checks that a string is a valid identifier and not a Python keyword. + :param identifier: The identifier to test. + :return: True if the identifier is valid. + """ + return identifier.isidentifier() and not keyword.iskeyword(identifier) + + +KeyType = TypeVar('KeyType') + + +def deep_update(mapping: Dict[KeyType, Any], *updating_mappings: Dict[KeyType, Any]) -> Dict[KeyType, Any]: + updated_mapping = mapping.copy() + for updating_mapping in updating_mappings: + for k, v in updating_mapping.items(): + if k in updated_mapping and isinstance(updated_mapping[k], dict) and isinstance(v, dict): + updated_mapping[k] = deep_update(updated_mapping[k], v) + else: + updated_mapping[k] = v + return updated_mapping + + +def update_not_none(mapping: Dict[Any, Any], **update: Any) -> None: + mapping.update({k: v for k, v in update.items() if v is not None}) + + +def almost_equal_floats(value_1: float, value_2: float, *, delta: float = 1e-8) -> bool: + """ + Return True if two floats are almost equal + """ + return abs(value_1 - value_2) <= delta + + +def generate_model_signature( + init: Callable[..., None], fields: Dict[str, 'ModelField'], config: Type['BaseConfig'] +) -> 'Signature': + """ + Generate signature for model based on its fields + """ + from inspect import Parameter, Signature, signature + + from pydantic.config import Extra + + present_params = signature(init).parameters.values() + merged_params: Dict[str, Parameter] = {} + var_kw = None + use_var_kw = False + + for param in islice(present_params, 1, None): # skip self arg + if param.kind is param.VAR_KEYWORD: + var_kw = param + continue + merged_params[param.name] = param + + if var_kw: # if custom init has no var_kw, fields which are not declared in it cannot be passed through + allow_names = config.allow_population_by_field_name + for field_name, field in fields.items(): + param_name = field.alias + if field_name in merged_params or param_name in merged_params: + continue + elif not is_valid_identifier(param_name): + if allow_names and is_valid_identifier(field_name): + param_name = field_name + else: + use_var_kw = True + continue + + # TODO: replace annotation with actual expected types once #1055 solved + kwargs = {'default': field.default} if not field.required else {} + merged_params[param_name] = Parameter( + param_name, Parameter.KEYWORD_ONLY, annotation=field.annotation, **kwargs + ) + + if config.extra is Extra.allow: + use_var_kw = True + + if var_kw and use_var_kw: + # Make sure the parameter for extra kwargs + # does not have the same name as a field + default_model_signature = [ + ('__pydantic_self__', Parameter.POSITIONAL_OR_KEYWORD), + ('data', Parameter.VAR_KEYWORD), + ] + if [(p.name, p.kind) for p in present_params] == default_model_signature: + # if this is the standard model signature, use extra_data as the extra args name + var_kw_name = 'extra_data' + else: + # else start from var_kw + var_kw_name = var_kw.name + + # generate a name that's definitely unique + while var_kw_name in fields: + var_kw_name += '_' + merged_params[var_kw_name] = var_kw.replace(name=var_kw_name) + + return Signature(parameters=list(merged_params.values()), return_annotation=None) + + +def get_model(obj: Union[Type['BaseModel'], Type['Dataclass']]) -> Type['BaseModel']: + from pydantic.main import BaseModel + + try: + model_cls = obj.__pydantic_model__ # type: ignore + except AttributeError: + model_cls = obj + + if not issubclass(model_cls, BaseModel): + raise TypeError('Unsupported type, must be either BaseModel or dataclass') + return model_cls + + +def to_camel(string: str) -> str: + return ''.join(word.capitalize() for word in string.split('_')) + + +def to_lower_camel(string: str) -> str: + if len(string) >= 1: + pascal_string = to_camel(string) + return pascal_string[0].lower() + pascal_string[1:] + return string.lower() + + +T = TypeVar('T') + + +def unique_list( + input_list: Union[List[T], Tuple[T, ...]], + *, + name_factory: Callable[[T], str] = str, +) -> List[T]: + """ + Make a list unique while maintaining order. + We update the list if another one with the same name is set + (e.g. root validator overridden in subclass) + """ + result: List[T] = [] + result_names: List[str] = [] + for v in input_list: + v_name = name_factory(v) + if v_name not in result_names: + result_names.append(v_name) + result.append(v) + else: + result[result_names.index(v_name)] = v + + return result + + +class PyObjectStr(str): + """ + String class where repr doesn't include quotes. Useful with Representation when you want to return a string + representation of something that valid (or pseudo-valid) python. + """ + + def __repr__(self) -> str: + return str(self) + + +class Representation: + """ + Mixin to provide __str__, __repr__, and __pretty__ methods. See #884 for more details. + + __pretty__ is used by [devtools](https://python-devtools.helpmanual.io/) to provide human readable representations + of objects. + """ + + __slots__: Tuple[str, ...] = tuple() + + def __repr_args__(self) -> 'ReprArgs': + """ + Returns the attributes to show in __str__, __repr__, and __pretty__ this is generally overridden. + + Can either return: + * name - value pairs, e.g.: `[('foo_name', 'foo'), ('bar_name', ['b', 'a', 'r'])]` + * or, just values, e.g.: `[(None, 'foo'), (None, ['b', 'a', 'r'])]` + """ + attrs = ((s, getattr(self, s)) for s in self.__slots__) + return [(a, v) for a, v in attrs if v is not None] + + def __repr_name__(self) -> str: + """ + Name of the instance's class, used in __repr__. + """ + return self.__class__.__name__ + + def __repr_str__(self, join_str: str) -> str: + return join_str.join(repr(v) if a is None else f'{a}={v!r}' for a, v in self.__repr_args__()) + + def __pretty__(self, fmt: Callable[[Any], Any], **kwargs: Any) -> Generator[Any, None, None]: + """ + Used by devtools (https://python-devtools.helpmanual.io/) to provide a human readable representations of objects + """ + yield self.__repr_name__() + '(' + yield 1 + for name, value in self.__repr_args__(): + if name is not None: + yield name + '=' + yield fmt(value) + yield ',' + yield 0 + yield -1 + yield ')' + + def __str__(self) -> str: + return self.__repr_str__(' ') + + def __repr__(self) -> str: + return f'{self.__repr_name__()}({self.__repr_str__(", ")})' + + def __rich_repr__(self) -> 'RichReprResult': + """Get fields for Rich library""" + for name, field_repr in self.__repr_args__(): + if name is None: + yield field_repr + else: + yield name, field_repr + + +class GetterDict(Representation): + """ + Hack to make object's smell just enough like dicts for validate_model. + + We can't inherit from Mapping[str, Any] because it upsets cython so we have to implement all methods ourselves. + """ + + __slots__ = ('_obj',) + + def __init__(self, obj: Any): + self._obj = obj + + def __getitem__(self, key: str) -> Any: + try: + return getattr(self._obj, key) + except AttributeError as e: + raise KeyError(key) from e + + def get(self, key: Any, default: Any = None) -> Any: + return getattr(self._obj, key, default) + + def extra_keys(self) -> Set[Any]: + """ + We don't want to get any other attributes of obj if the model didn't explicitly ask for them + """ + return set() + + def keys(self) -> List[Any]: + """ + Keys of the pseudo dictionary, uses a list not set so order information can be maintained like python + dictionaries. + """ + return list(self) + + def values(self) -> List[Any]: + return [self[k] for k in self] + + def items(self) -> Iterator[Tuple[str, Any]]: + for k in self: + yield k, self.get(k) + + def __iter__(self) -> Iterator[str]: + for name in dir(self._obj): + if not name.startswith('_'): + yield name + + def __len__(self) -> int: + return sum(1 for _ in self) + + def __contains__(self, item: Any) -> bool: + return item in self.keys() + + def __eq__(self, other: Any) -> bool: + return dict(self) == dict(other.items()) + + def __repr_args__(self) -> 'ReprArgs': + return [(None, dict(self))] + + def __repr_name__(self) -> str: + return f'GetterDict[{display_as_type(self._obj)}]' + + +class ValueItems(Representation): + """ + Class for more convenient calculation of excluded or included fields on values. + """ + + __slots__ = ('_items', '_type') + + def __init__(self, value: Any, items: Union['AbstractSetIntStr', 'MappingIntStrAny']) -> None: + items = self._coerce_items(items) + + if isinstance(value, (list, tuple)): + items = self._normalize_indexes(items, len(value)) + + self._items: 'MappingIntStrAny' = items + + def is_excluded(self, item: Any) -> bool: + """ + Check if item is fully excluded. + + :param item: key or index of a value + """ + return self.is_true(self._items.get(item)) + + def is_included(self, item: Any) -> bool: + """ + Check if value is contained in self._items + + :param item: key or index of value + """ + return item in self._items + + def for_element(self, e: 'IntStr') -> Optional[Union['AbstractSetIntStr', 'MappingIntStrAny']]: + """ + :param e: key or index of element on value + :return: raw values for element if self._items is dict and contain needed element + """ + + item = self._items.get(e) + return item if not self.is_true(item) else None + + def _normalize_indexes(self, items: 'MappingIntStrAny', v_length: int) -> 'DictIntStrAny': + """ + :param items: dict or set of indexes which will be normalized + :param v_length: length of sequence indexes of which will be + + >>> self._normalize_indexes({0: True, -2: True, -1: True}, 4) + {0: True, 2: True, 3: True} + >>> self._normalize_indexes({'__all__': True}, 4) + {0: True, 1: True, 2: True, 3: True} + """ + + normalized_items: 'DictIntStrAny' = {} + all_items = None + for i, v in items.items(): + if not (isinstance(v, Mapping) or isinstance(v, AbstractSet) or self.is_true(v)): + raise TypeError(f'Unexpected type of exclude value for index "{i}" {v.__class__}') + if i == '__all__': + all_items = self._coerce_value(v) + continue + if not isinstance(i, int): + raise TypeError( + 'Excluding fields from a sequence of sub-models or dicts must be performed index-wise: ' + 'expected integer keys or keyword "__all__"' + ) + normalized_i = v_length + i if i < 0 else i + normalized_items[normalized_i] = self.merge(v, normalized_items.get(normalized_i)) + + if not all_items: + return normalized_items + if self.is_true(all_items): + for i in range(v_length): + normalized_items.setdefault(i, ...) + return normalized_items + for i in range(v_length): + normalized_item = normalized_items.setdefault(i, {}) + if not self.is_true(normalized_item): + normalized_items[i] = self.merge(all_items, normalized_item) + return normalized_items + + @classmethod + def merge(cls, base: Any, override: Any, intersect: bool = False) -> Any: + """ + Merge a ``base`` item with an ``override`` item. + + Both ``base`` and ``override`` are converted to dictionaries if possible. + Sets are converted to dictionaries with the sets entries as keys and + Ellipsis as values. + + Each key-value pair existing in ``base`` is merged with ``override``, + while the rest of the key-value pairs are updated recursively with this function. + + Merging takes place based on the "union" of keys if ``intersect`` is + set to ``False`` (default) and on the intersection of keys if + ``intersect`` is set to ``True``. + """ + override = cls._coerce_value(override) + base = cls._coerce_value(base) + if override is None: + return base + if cls.is_true(base) or base is None: + return override + if cls.is_true(override): + return base if intersect else override + + # intersection or union of keys while preserving ordering: + if intersect: + merge_keys = [k for k in base if k in override] + [k for k in override if k in base] + else: + merge_keys = list(base) + [k for k in override if k not in base] + + merged: 'DictIntStrAny' = {} + for k in merge_keys: + merged_item = cls.merge(base.get(k), override.get(k), intersect=intersect) + if merged_item is not None: + merged[k] = merged_item + + return merged + + @staticmethod + def _coerce_items(items: Union['AbstractSetIntStr', 'MappingIntStrAny']) -> 'MappingIntStrAny': + if isinstance(items, Mapping): + pass + elif isinstance(items, AbstractSet): + items = dict.fromkeys(items, ...) + else: + class_name = getattr(items, '__class__', '???') + assert_never( + items, + f'Unexpected type of exclude value {class_name}', + ) + return items + + @classmethod + def _coerce_value(cls, value: Any) -> Any: + if value is None or cls.is_true(value): + return value + return cls._coerce_items(value) + + @staticmethod + def is_true(v: Any) -> bool: + return v is True or v is ... + + def __repr_args__(self) -> 'ReprArgs': + return [(None, self._items)] + + +class ClassAttribute: + """ + Hide class attribute from its instances + """ + + __slots__ = ( + 'name', + 'value', + ) + + def __init__(self, name: str, value: Any) -> None: + self.name = name + self.value = value + + def __get__(self, instance: Any, owner: Type[Any]) -> None: + if instance is None: + return self.value + raise AttributeError(f'{self.name!r} attribute of {owner.__name__!r} is class-only') + + +path_types = { + 'is_dir': 'directory', + 'is_file': 'file', + 'is_mount': 'mount point', + 'is_symlink': 'symlink', + 'is_block_device': 'block device', + 'is_char_device': 'char device', + 'is_fifo': 'FIFO', + 'is_socket': 'socket', +} + + +def path_type(p: 'Path') -> str: + """ + Find out what sort of thing a path is. + """ + assert p.exists(), 'path does not exist' + for method, name in path_types.items(): + if getattr(p, method)(): + return name + + return 'unknown' + + +Obj = TypeVar('Obj') + + +def smart_deepcopy(obj: Obj) -> Obj: + """ + Return type as is for immutable built-in types + Use obj.copy() for built-in empty collections + Use copy.deepcopy() for non-empty collections and unknown objects + """ + + obj_type = obj.__class__ + if obj_type in IMMUTABLE_NON_COLLECTIONS_TYPES: + return obj # fastest case: obj is immutable and not collection therefore will not be copied anyway + try: + if not obj and obj_type in BUILTIN_COLLECTIONS: + # faster way for empty collections, no need to copy its members + return obj if obj_type is tuple else obj.copy() # type: ignore # tuple doesn't have copy method + except (TypeError, ValueError, RuntimeError): + # do we really dare to catch ALL errors? Seems a bit risky + pass + + return deepcopy(obj) # slowest way when we actually might need a deepcopy + + +def is_valid_field(name: str) -> bool: + if not name.startswith('_'): + return True + return ROOT_KEY == name + + +DUNDER_ATTRIBUTES = { + '__annotations__', + '__classcell__', + '__doc__', + '__module__', + '__orig_bases__', + '__orig_class__', + '__qualname__', +} + + +def is_valid_private_name(name: str) -> bool: + return not is_valid_field(name) and name not in DUNDER_ATTRIBUTES + + +_EMPTY = object() + + +def all_identical(left: Iterable[Any], right: Iterable[Any]) -> bool: + """ + Check that the items of `left` are the same objects as those in `right`. + + >>> a, b = object(), object() + >>> all_identical([a, b, a], [a, b, a]) + True + >>> all_identical([a, b, [a]], [a, b, [a]]) # new list object, while "equal" is not "identical" + False + """ + for left_item, right_item in zip_longest(left, right, fillvalue=_EMPTY): + if left_item is not right_item: + return False + return True + + +def assert_never(obj: NoReturn, msg: str) -> NoReturn: + """ + Helper to make sure that we have covered all possible types. + + This is mostly useful for ``mypy``, docs: + https://mypy.readthedocs.io/en/latest/literal_types.html#exhaustive-checks + """ + raise TypeError(msg) + + +def get_unique_discriminator_alias(all_aliases: Collection[str], discriminator_key: str) -> str: + """Validate that all aliases are the same and if that's the case return the alias""" + unique_aliases = set(all_aliases) + if len(unique_aliases) > 1: + raise ConfigError( + f'Aliases for discriminator {discriminator_key!r} must be the same (got {", ".join(sorted(all_aliases))})' + ) + return unique_aliases.pop() + + +def get_discriminator_alias_and_values(tp: Any, discriminator_key: str) -> Tuple[str, Tuple[str, ...]]: + """ + Get alias and all valid values in the `Literal` type of the discriminator field + `tp` can be a `BaseModel` class or directly an `Annotated` `Union` of many. + """ + is_root_model = getattr(tp, '__custom_root_type__', False) + + if get_origin(tp) is Annotated: + tp = get_args(tp)[0] + + if hasattr(tp, '__pydantic_model__'): + tp = tp.__pydantic_model__ + + if is_union(get_origin(tp)): + alias, all_values = _get_union_alias_and_all_values(tp, discriminator_key) + return alias, tuple(v for values in all_values for v in values) + elif is_root_model: + union_type = tp.__fields__[ROOT_KEY].type_ + alias, all_values = _get_union_alias_and_all_values(union_type, discriminator_key) + + if len(set(all_values)) > 1: + raise ConfigError( + f'Field {discriminator_key!r} is not the same for all submodels of {display_as_type(tp)!r}' + ) + + return alias, all_values[0] + + else: + try: + t_discriminator_type = tp.__fields__[discriminator_key].type_ + except AttributeError as e: + raise TypeError(f'Type {tp.__name__!r} is not a valid `BaseModel` or `dataclass`') from e + except KeyError as e: + raise ConfigError(f'Model {tp.__name__!r} needs a discriminator field for key {discriminator_key!r}') from e + + if not is_literal_type(t_discriminator_type): + raise ConfigError(f'Field {discriminator_key!r} of model {tp.__name__!r} needs to be a `Literal`') + + return tp.__fields__[discriminator_key].alias, all_literal_values(t_discriminator_type) + + +def _get_union_alias_and_all_values( + union_type: Type[Any], discriminator_key: str +) -> Tuple[str, Tuple[Tuple[str, ...], ...]]: + zipped_aliases_values = [get_discriminator_alias_and_values(t, discriminator_key) for t in get_args(union_type)] + # unzip: [('alias_a',('v1', 'v2)), ('alias_b', ('v3',))] => [('alias_a', 'alias_b'), (('v1', 'v2'), ('v3',))] + all_aliases, all_values = zip(*zipped_aliases_values) + return get_unique_discriminator_alias(all_aliases, discriminator_key), all_values diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/v1.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/v1.py new file mode 100644 index 0000000..6b3692d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/v1.py @@ -0,0 +1,130 @@ +# NOTE This file aliases the pydantic namespace as pydantic.v1 for smoother v1 -> v2 transition +# flake8: noqa +import importlib +import os +from typing import Any + +import pydantic +from pydantic import * + + +# allows importing of objects from modules directly +# i.e. from pydantic.v1.fields import ModelField +def __getattr__(name: str) -> Any: + """Module level `__getattr__` to allow imports directly from the `pydantic.v1` + namespace for all pydantic modules.""" + return getattr(pydantic, name) + + +# WARNING __all__ from pydantic.errors is not included here, it will be removed as an export here in v2 +# please use "from pydantic.errors import ..." instead +__all__ = [ + # annotated types utils + "create_model_from_namedtuple", + "create_model_from_typeddict", + # dataclasses + "dataclasses", + # class_validators + "root_validator", + "validator", + # config + "BaseConfig", + "ConfigDict", + "Extra", + # decorator + "validate_arguments", + # env_settings + "BaseSettings", + # error_wrappers + "ValidationError", + # fields + "Field", + "Required", + # main + "BaseModel", + "create_model", + "validate_model", + # network + "AnyUrl", + "AnyHttpUrl", + "FileUrl", + "HttpUrl", + "stricturl", + "EmailStr", + "NameEmail", + "IPvAnyAddress", + "IPvAnyInterface", + "IPvAnyNetwork", + "PostgresDsn", + "CockroachDsn", + "AmqpDsn", + "RedisDsn", + "MongoDsn", + "KafkaDsn", + "validate_email", + # parse + "Protocol", + # tools + "parse_file_as", + "parse_obj_as", + "parse_raw_as", + "schema_of", + "schema_json_of", + # types + "NoneStr", + "NoneBytes", + "StrBytes", + "NoneStrBytes", + "StrictStr", + "ConstrainedBytes", + "conbytes", + "ConstrainedList", + "conlist", + "ConstrainedSet", + "conset", + "ConstrainedFrozenSet", + "confrozenset", + "ConstrainedStr", + "constr", + "PyObject", + "ConstrainedInt", + "conint", + "PositiveInt", + "NegativeInt", + "NonNegativeInt", + "NonPositiveInt", + "ConstrainedFloat", + "confloat", + "PositiveFloat", + "NegativeFloat", + "NonNegativeFloat", + "NonPositiveFloat", + "FiniteFloat", + "ConstrainedDecimal", + "condecimal", + "ConstrainedDate", + "condate", + "UUID1", + "UUID3", + "UUID4", + "UUID5", + "FilePath", + "DirectoryPath", + "Json", + "JsonWrapper", + "SecretField", + "SecretStr", + "SecretBytes", + "StrictBool", + "StrictBytes", + "StrictInt", + "StrictFloat", + "PaymentCardNumber", + "PrivateAttr", + "ByteSize", + "PastDate", + "FutureDate", + # version + "compiled", + "VERSION", +] diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/validators.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/validators.py new file mode 100644 index 0000000..51a48ee --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/validators.py @@ -0,0 +1,765 @@ +import math +import re +from collections import OrderedDict, deque +from collections.abc import Hashable as CollectionsHashable +from datetime import date, datetime, time, timedelta +from decimal import Decimal, DecimalException +from enum import Enum, IntEnum +from ipaddress import IPv4Address, IPv4Interface, IPv4Network, IPv6Address, IPv6Interface, IPv6Network +from pathlib import Path +from typing import ( + TYPE_CHECKING, + Any, + Callable, + Deque, + Dict, + ForwardRef, + FrozenSet, + Generator, + Hashable, + List, + NamedTuple, + Pattern, + Set, + Tuple, + Type, + TypeVar, + Union, +) +from uuid import UUID + +from pydantic import errors +from pydantic.datetime_parse import parse_date, parse_datetime, parse_duration, parse_time +from pydantic.typing import ( + AnyCallable, + all_literal_values, + display_as_type, + get_class, + is_callable_type, + is_literal_type, + is_namedtuple, + is_none_type, + is_typeddict, +) +from pydantic.utils import almost_equal_floats, lenient_issubclass, sequence_like + +if TYPE_CHECKING: + from typing_extensions import Literal, TypedDict + + from pydantic.config import BaseConfig + from pydantic.fields import ModelField + from pydantic.types import ConstrainedDecimal, ConstrainedFloat, ConstrainedInt + + ConstrainedNumber = Union[ConstrainedDecimal, ConstrainedFloat, ConstrainedInt] + AnyOrderedDict = OrderedDict[Any, Any] + Number = Union[int, float, Decimal] + StrBytes = Union[str, bytes] + + +def str_validator(v: Any) -> Union[str]: + if isinstance(v, str): + if isinstance(v, Enum): + return v.value + else: + return v + elif isinstance(v, (float, int, Decimal)): + # is there anything else we want to add here? If you think so, create an issue. + return str(v) + elif isinstance(v, (bytes, bytearray)): + return v.decode() + else: + raise errors.StrError() + + +def strict_str_validator(v: Any) -> Union[str]: + if isinstance(v, str) and not isinstance(v, Enum): + return v + raise errors.StrError() + + +def bytes_validator(v: Any) -> Union[bytes]: + if isinstance(v, bytes): + return v + elif isinstance(v, bytearray): + return bytes(v) + elif isinstance(v, str): + return v.encode() + elif isinstance(v, (float, int, Decimal)): + return str(v).encode() + else: + raise errors.BytesError() + + +def strict_bytes_validator(v: Any) -> Union[bytes]: + if isinstance(v, bytes): + return v + elif isinstance(v, bytearray): + return bytes(v) + else: + raise errors.BytesError() + + +BOOL_FALSE = {0, '0', 'off', 'f', 'false', 'n', 'no'} +BOOL_TRUE = {1, '1', 'on', 't', 'true', 'y', 'yes'} + + +def bool_validator(v: Any) -> bool: + if v is True or v is False: + return v + if isinstance(v, bytes): + v = v.decode() + if isinstance(v, str): + v = v.lower() + try: + if v in BOOL_TRUE: + return True + if v in BOOL_FALSE: + return False + except TypeError: + raise errors.BoolError() + raise errors.BoolError() + + +# matches the default limit cpython, see https://github.com/python/cpython/pull/96500 +max_str_int = 4_300 + + +def int_validator(v: Any) -> int: + if isinstance(v, int) and not (v is True or v is False): + return v + + # see https://github.com/pydantic/pydantic/issues/1477 and in turn, https://github.com/python/cpython/issues/95778 + # this check should be unnecessary once patch releases are out for 3.7, 3.8, 3.9 and 3.10 + # but better to check here until then. + # NOTICE: this does not fully protect user from the DOS risk since the standard library JSON implementation + # (and other std lib modules like xml) use `int()` and are likely called before this, the best workaround is to + # 1. update to the latest patch release of python once released, 2. use a different JSON library like ujson + if isinstance(v, (str, bytes, bytearray)) and len(v) > max_str_int: + raise errors.IntegerError() + + try: + return int(v) + except (TypeError, ValueError, OverflowError): + raise errors.IntegerError() + + +def strict_int_validator(v: Any) -> int: + if isinstance(v, int) and not (v is True or v is False): + return v + raise errors.IntegerError() + + +def float_validator(v: Any) -> float: + if isinstance(v, float): + return v + + try: + return float(v) + except (TypeError, ValueError): + raise errors.FloatError() + + +def strict_float_validator(v: Any) -> float: + if isinstance(v, float): + return v + raise errors.FloatError() + + +def float_finite_validator(v: 'Number', field: 'ModelField', config: 'BaseConfig') -> 'Number': + allow_inf_nan = getattr(field.type_, 'allow_inf_nan', None) + if allow_inf_nan is None: + allow_inf_nan = config.allow_inf_nan + + if allow_inf_nan is False and (math.isnan(v) or math.isinf(v)): + raise errors.NumberNotFiniteError() + return v + + +def number_multiple_validator(v: 'Number', field: 'ModelField') -> 'Number': + field_type: ConstrainedNumber = field.type_ + if field_type.multiple_of is not None: + mod = float(v) / float(field_type.multiple_of) % 1 + if not almost_equal_floats(mod, 0.0) and not almost_equal_floats(mod, 1.0): + raise errors.NumberNotMultipleError(multiple_of=field_type.multiple_of) + return v + + +def number_size_validator(v: 'Number', field: 'ModelField') -> 'Number': + field_type: ConstrainedNumber = field.type_ + if field_type.gt is not None and not v > field_type.gt: + raise errors.NumberNotGtError(limit_value=field_type.gt) + elif field_type.ge is not None and not v >= field_type.ge: + raise errors.NumberNotGeError(limit_value=field_type.ge) + + if field_type.lt is not None and not v < field_type.lt: + raise errors.NumberNotLtError(limit_value=field_type.lt) + if field_type.le is not None and not v <= field_type.le: + raise errors.NumberNotLeError(limit_value=field_type.le) + + return v + + +def constant_validator(v: 'Any', field: 'ModelField') -> 'Any': + """Validate ``const`` fields. + + The value provided for a ``const`` field must be equal to the default value + of the field. This is to support the keyword of the same name in JSON + Schema. + """ + if v != field.default: + raise errors.WrongConstantError(given=v, permitted=[field.default]) + + return v + + +def anystr_length_validator(v: 'StrBytes', config: 'BaseConfig') -> 'StrBytes': + v_len = len(v) + + min_length = config.min_anystr_length + if v_len < min_length: + raise errors.AnyStrMinLengthError(limit_value=min_length) + + max_length = config.max_anystr_length + if max_length is not None and v_len > max_length: + raise errors.AnyStrMaxLengthError(limit_value=max_length) + + return v + + +def anystr_strip_whitespace(v: 'StrBytes') -> 'StrBytes': + return v.strip() + + +def anystr_upper(v: 'StrBytes') -> 'StrBytes': + return v.upper() + + +def anystr_lower(v: 'StrBytes') -> 'StrBytes': + return v.lower() + + +def ordered_dict_validator(v: Any) -> 'AnyOrderedDict': + if isinstance(v, OrderedDict): + return v + + try: + return OrderedDict(v) + except (TypeError, ValueError): + raise errors.DictError() + + +def dict_validator(v: Any) -> Dict[Any, Any]: + if isinstance(v, dict): + return v + + try: + return dict(v) + except (TypeError, ValueError): + raise errors.DictError() + + +def list_validator(v: Any) -> List[Any]: + if isinstance(v, list): + return v + elif sequence_like(v): + return list(v) + else: + raise errors.ListError() + + +def tuple_validator(v: Any) -> Tuple[Any, ...]: + if isinstance(v, tuple): + return v + elif sequence_like(v): + return tuple(v) + else: + raise errors.TupleError() + + +def set_validator(v: Any) -> Set[Any]: + if isinstance(v, set): + return v + elif sequence_like(v): + return set(v) + else: + raise errors.SetError() + + +def frozenset_validator(v: Any) -> FrozenSet[Any]: + if isinstance(v, frozenset): + return v + elif sequence_like(v): + return frozenset(v) + else: + raise errors.FrozenSetError() + + +def deque_validator(v: Any) -> Deque[Any]: + if isinstance(v, deque): + return v + elif sequence_like(v): + return deque(v) + else: + raise errors.DequeError() + + +def enum_member_validator(v: Any, field: 'ModelField', config: 'BaseConfig') -> Enum: + try: + enum_v = field.type_(v) + except ValueError: + # field.type_ should be an enum, so will be iterable + raise errors.EnumMemberError(enum_values=list(field.type_)) + return enum_v.value if config.use_enum_values else enum_v + + +def uuid_validator(v: Any, field: 'ModelField') -> UUID: + try: + if isinstance(v, str): + v = UUID(v) + elif isinstance(v, (bytes, bytearray)): + try: + v = UUID(v.decode()) + except ValueError: + # 16 bytes in big-endian order as the bytes argument fail + # the above check + v = UUID(bytes=v) + except ValueError: + raise errors.UUIDError() + + if not isinstance(v, UUID): + raise errors.UUIDError() + + required_version = getattr(field.type_, '_required_version', None) + if required_version and v.version != required_version: + raise errors.UUIDVersionError(required_version=required_version) + + return v + + +def decimal_validator(v: Any) -> Decimal: + if isinstance(v, Decimal): + return v + elif isinstance(v, (bytes, bytearray)): + v = v.decode() + + v = str(v).strip() + + try: + v = Decimal(v) + except DecimalException: + raise errors.DecimalError() + + if not v.is_finite(): + raise errors.DecimalIsNotFiniteError() + + return v + + +def hashable_validator(v: Any) -> Hashable: + if isinstance(v, Hashable): + return v + + raise errors.HashableError() + + +def ip_v4_address_validator(v: Any) -> IPv4Address: + if isinstance(v, IPv4Address): + return v + + try: + return IPv4Address(v) + except ValueError: + raise errors.IPv4AddressError() + + +def ip_v6_address_validator(v: Any) -> IPv6Address: + if isinstance(v, IPv6Address): + return v + + try: + return IPv6Address(v) + except ValueError: + raise errors.IPv6AddressError() + + +def ip_v4_network_validator(v: Any) -> IPv4Network: + """ + Assume IPv4Network initialised with a default ``strict`` argument + + See more: + https://docs.python.org/library/ipaddress.html#ipaddress.IPv4Network + """ + if isinstance(v, IPv4Network): + return v + + try: + return IPv4Network(v) + except ValueError: + raise errors.IPv4NetworkError() + + +def ip_v6_network_validator(v: Any) -> IPv6Network: + """ + Assume IPv6Network initialised with a default ``strict`` argument + + See more: + https://docs.python.org/library/ipaddress.html#ipaddress.IPv6Network + """ + if isinstance(v, IPv6Network): + return v + + try: + return IPv6Network(v) + except ValueError: + raise errors.IPv6NetworkError() + + +def ip_v4_interface_validator(v: Any) -> IPv4Interface: + if isinstance(v, IPv4Interface): + return v + + try: + return IPv4Interface(v) + except ValueError: + raise errors.IPv4InterfaceError() + + +def ip_v6_interface_validator(v: Any) -> IPv6Interface: + if isinstance(v, IPv6Interface): + return v + + try: + return IPv6Interface(v) + except ValueError: + raise errors.IPv6InterfaceError() + + +def path_validator(v: Any) -> Path: + if isinstance(v, Path): + return v + + try: + return Path(v) + except TypeError: + raise errors.PathError() + + +def path_exists_validator(v: Any) -> Path: + if not v.exists(): + raise errors.PathNotExistsError(path=v) + + return v + + +def callable_validator(v: Any) -> AnyCallable: + """ + Perform a simple check if the value is callable. + + Note: complete matching of argument type hints and return types is not performed + """ + if callable(v): + return v + + raise errors.CallableError(value=v) + + +def enum_validator(v: Any) -> Enum: + if isinstance(v, Enum): + return v + + raise errors.EnumError(value=v) + + +def int_enum_validator(v: Any) -> IntEnum: + if isinstance(v, IntEnum): + return v + + raise errors.IntEnumError(value=v) + + +def make_literal_validator(type_: Any) -> Callable[[Any], Any]: + permitted_choices = all_literal_values(type_) + + # To have a O(1) complexity and still return one of the values set inside the `Literal`, + # we create a dict with the set values (a set causes some problems with the way intersection works). + # In some cases the set value and checked value can indeed be different (see `test_literal_validator_str_enum`) + allowed_choices = {v: v for v in permitted_choices} + + def literal_validator(v: Any) -> Any: + try: + return allowed_choices[v] + except (KeyError, TypeError): + raise errors.WrongConstantError(given=v, permitted=permitted_choices) + + return literal_validator + + +def constr_length_validator(v: 'StrBytes', field: 'ModelField', config: 'BaseConfig') -> 'StrBytes': + v_len = len(v) + + min_length = field.type_.min_length if field.type_.min_length is not None else config.min_anystr_length + if v_len < min_length: + raise errors.AnyStrMinLengthError(limit_value=min_length) + + max_length = field.type_.max_length if field.type_.max_length is not None else config.max_anystr_length + if max_length is not None and v_len > max_length: + raise errors.AnyStrMaxLengthError(limit_value=max_length) + + return v + + +def constr_strip_whitespace(v: 'StrBytes', field: 'ModelField', config: 'BaseConfig') -> 'StrBytes': + strip_whitespace = field.type_.strip_whitespace or config.anystr_strip_whitespace + if strip_whitespace: + v = v.strip() + + return v + + +def constr_upper(v: 'StrBytes', field: 'ModelField', config: 'BaseConfig') -> 'StrBytes': + upper = field.type_.to_upper or config.anystr_upper + if upper: + v = v.upper() + + return v + + +def constr_lower(v: 'StrBytes', field: 'ModelField', config: 'BaseConfig') -> 'StrBytes': + lower = field.type_.to_lower or config.anystr_lower + if lower: + v = v.lower() + return v + + +def validate_json(v: Any, config: 'BaseConfig') -> Any: + if v is None: + # pass None through to other validators + return v + try: + return config.json_loads(v) # type: ignore + except ValueError: + raise errors.JsonError() + except TypeError: + raise errors.JsonTypeError() + + +T = TypeVar('T') + + +def make_arbitrary_type_validator(type_: Type[T]) -> Callable[[T], T]: + def arbitrary_type_validator(v: Any) -> T: + if isinstance(v, type_): + return v + raise errors.ArbitraryTypeError(expected_arbitrary_type=type_) + + return arbitrary_type_validator + + +def make_class_validator(type_: Type[T]) -> Callable[[Any], Type[T]]: + def class_validator(v: Any) -> Type[T]: + if lenient_issubclass(v, type_): + return v + raise errors.SubclassError(expected_class=type_) + + return class_validator + + +def any_class_validator(v: Any) -> Type[T]: + if isinstance(v, type): + return v + raise errors.ClassError() + + +def none_validator(v: Any) -> 'Literal[None]': + if v is None: + return v + raise errors.NotNoneError() + + +def pattern_validator(v: Any) -> Pattern[str]: + if isinstance(v, Pattern): + return v + + str_value = str_validator(v) + + try: + return re.compile(str_value) + except re.error: + raise errors.PatternError() + + +NamedTupleT = TypeVar('NamedTupleT', bound=NamedTuple) + + +def make_namedtuple_validator( + namedtuple_cls: Type[NamedTupleT], config: Type['BaseConfig'] +) -> Callable[[Tuple[Any, ...]], NamedTupleT]: + from pydantic.annotated_types import create_model_from_namedtuple + + NamedTupleModel = create_model_from_namedtuple( + namedtuple_cls, + __config__=config, + __module__=namedtuple_cls.__module__, + ) + namedtuple_cls.__pydantic_model__ = NamedTupleModel # type: ignore[attr-defined] + + def namedtuple_validator(values: Tuple[Any, ...]) -> NamedTupleT: + annotations = NamedTupleModel.__annotations__ + + if len(values) > len(annotations): + raise errors.ListMaxLengthError(limit_value=len(annotations)) + + dict_values: Dict[str, Any] = dict(zip(annotations, values)) + validated_dict_values: Dict[str, Any] = dict(NamedTupleModel(**dict_values)) + return namedtuple_cls(**validated_dict_values) + + return namedtuple_validator + + +def make_typeddict_validator( + typeddict_cls: Type['TypedDict'], config: Type['BaseConfig'] # type: ignore[valid-type] +) -> Callable[[Any], Dict[str, Any]]: + from pydantic.annotated_types import create_model_from_typeddict + + TypedDictModel = create_model_from_typeddict( + typeddict_cls, + __config__=config, + __module__=typeddict_cls.__module__, + ) + typeddict_cls.__pydantic_model__ = TypedDictModel # type: ignore[attr-defined] + + def typeddict_validator(values: 'TypedDict') -> Dict[str, Any]: # type: ignore[valid-type] + return TypedDictModel.parse_obj(values).dict(exclude_unset=True) + + return typeddict_validator + + +class IfConfig: + def __init__(self, validator: AnyCallable, *config_attr_names: str, ignored_value: Any = False) -> None: + self.validator = validator + self.config_attr_names = config_attr_names + self.ignored_value = ignored_value + + def check(self, config: Type['BaseConfig']) -> bool: + return any(getattr(config, name) not in {None, self.ignored_value} for name in self.config_attr_names) + + +# order is important here, for example: bool is a subclass of int so has to come first, datetime before date same, +# IPv4Interface before IPv4Address, etc +_VALIDATORS: List[Tuple[Type[Any], List[Any]]] = [ + (IntEnum, [int_validator, enum_member_validator]), + (Enum, [enum_member_validator]), + ( + str, + [ + str_validator, + IfConfig(anystr_strip_whitespace, 'anystr_strip_whitespace'), + IfConfig(anystr_upper, 'anystr_upper'), + IfConfig(anystr_lower, 'anystr_lower'), + IfConfig(anystr_length_validator, 'min_anystr_length', 'max_anystr_length'), + ], + ), + ( + bytes, + [ + bytes_validator, + IfConfig(anystr_strip_whitespace, 'anystr_strip_whitespace'), + IfConfig(anystr_upper, 'anystr_upper'), + IfConfig(anystr_lower, 'anystr_lower'), + IfConfig(anystr_length_validator, 'min_anystr_length', 'max_anystr_length'), + ], + ), + (bool, [bool_validator]), + (int, [int_validator]), + (float, [float_validator, IfConfig(float_finite_validator, 'allow_inf_nan', ignored_value=True)]), + (Path, [path_validator]), + (datetime, [parse_datetime]), + (date, [parse_date]), + (time, [parse_time]), + (timedelta, [parse_duration]), + (OrderedDict, [ordered_dict_validator]), + (dict, [dict_validator]), + (list, [list_validator]), + (tuple, [tuple_validator]), + (set, [set_validator]), + (frozenset, [frozenset_validator]), + (deque, [deque_validator]), + (UUID, [uuid_validator]), + (Decimal, [decimal_validator]), + (IPv4Interface, [ip_v4_interface_validator]), + (IPv6Interface, [ip_v6_interface_validator]), + (IPv4Address, [ip_v4_address_validator]), + (IPv6Address, [ip_v6_address_validator]), + (IPv4Network, [ip_v4_network_validator]), + (IPv6Network, [ip_v6_network_validator]), +] + + +def find_validators( # noqa: C901 (ignore complexity) + type_: Type[Any], config: Type['BaseConfig'] +) -> Generator[AnyCallable, None, None]: + from pydantic.dataclasses import is_builtin_dataclass, make_dataclass_validator + + if type_ is Any or type_ is object: + return + type_type = type_.__class__ + if type_type == ForwardRef or type_type == TypeVar: + return + + if is_none_type(type_): + yield none_validator + return + if type_ is Pattern or type_ is re.Pattern: + yield pattern_validator + return + if type_ is Hashable or type_ is CollectionsHashable: + yield hashable_validator + return + if is_callable_type(type_): + yield callable_validator + return + if is_literal_type(type_): + yield make_literal_validator(type_) + return + if is_builtin_dataclass(type_): + yield from make_dataclass_validator(type_, config) + return + if type_ is Enum: + yield enum_validator + return + if type_ is IntEnum: + yield int_enum_validator + return + if is_namedtuple(type_): + yield tuple_validator + yield make_namedtuple_validator(type_, config) + return + if is_typeddict(type_): + yield make_typeddict_validator(type_, config) + return + + class_ = get_class(type_) + if class_ is not None: + if class_ is not Any and isinstance(class_, type): + yield make_class_validator(class_) + else: + yield any_class_validator + return + + for val_type, validators in _VALIDATORS: + try: + if issubclass(type_, val_type): + for v in validators: + if isinstance(v, IfConfig): + if v.check(config): + yield v.validator + else: + yield v + return + except TypeError: + raise RuntimeError(f'error checking inheritance of {type_!r} (type: {display_as_type(type_)})') + + if config.arbitrary_types_allowed: + yield make_arbitrary_type_validator(type_) + else: + raise RuntimeError(f'no validator found for {type_}, see `arbitrary_types_allowed` in Config') diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/version.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/version.py new file mode 100644 index 0000000..8bd591d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/pydantic/version.py @@ -0,0 +1,38 @@ +__all__ = 'compiled', 'VERSION', 'version_info' + +VERSION = '1.10.16' + +try: + import cython # type: ignore +except ImportError: + compiled: bool = False +else: # pragma: no cover + try: + compiled = cython.compiled + except AttributeError: + compiled = False + + +def version_info() -> str: + import platform + import sys + from importlib import import_module + from pathlib import Path + + optional_deps = [] + for p in ('devtools', 'dotenv', 'email-validator', 'typing-extensions'): + try: + import_module(p.replace('-', '_')) + except ImportError: + continue + optional_deps.append(p) + + info = { + 'pydantic version': VERSION, + 'pydantic compiled': compiled, + 'install path': Path(__file__).resolve().parent, + 'python version': sys.version, + 'platform': platform.platform(), + 'optional deps. installed': optional_deps, + } + return '\n'.join('{:>30} {}'.format(k + ':', str(v).replace('\n', ' ')) for k, v in info.items()) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette-0.27.0.dist-info/INSTALLER b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette-0.27.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette-0.27.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette-0.27.0.dist-info/METADATA b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette-0.27.0.dist-info/METADATA new file mode 100644 index 0000000..9319ad3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette-0.27.0.dist-info/METADATA @@ -0,0 +1,179 @@ +Metadata-Version: 2.4 +Name: starlette +Version: 0.27.0 +Summary: The little ASGI library that shines. +Project-URL: Homepage, https://github.com/encode/starlette +Project-URL: Documentation, https://www.starlette.io/ +Project-URL: Changelog, https://www.starlette.io/release-notes/ +Project-URL: Funding, https://github.com/sponsors/encode +Project-URL: Source, https://github.com/encode/starlette +Author-email: Tom Christie +License-Expression: BSD-3-Clause +License-File: LICENSE.md +Classifier: Development Status :: 3 - Alpha +Classifier: Environment :: Web Environment +Classifier: Framework :: AnyIO +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Topic :: Internet :: WWW/HTTP +Requires-Python: >=3.7 +Requires-Dist: anyio<5,>=3.4.0 +Requires-Dist: typing-extensions>=3.10.0; python_version < '3.10' +Provides-Extra: full +Requires-Dist: httpx>=0.22.0; extra == 'full' +Requires-Dist: itsdangerous; extra == 'full' +Requires-Dist: jinja2; extra == 'full' +Requires-Dist: python-multipart; extra == 'full' +Requires-Dist: pyyaml; extra == 'full' +Description-Content-Type: text/markdown + +

    + starlette +

    +

    + ✨ The little ASGI framework that shines. ✨ +

    +

    + + Build Status + + + Package version + +

    + +--- + +**Documentation**: [https://www.starlette.io/](https://www.starlette.io/) + +--- + +# Starlette + +Starlette is a lightweight [ASGI][asgi] framework/toolkit, +which is ideal for building async web services in Python. + +It is production-ready, and gives you the following: + +* A lightweight, low-complexity HTTP web framework. +* WebSocket support. +* In-process background tasks. +* Startup and shutdown events. +* Test client built on `httpx`. +* CORS, GZip, Static Files, Streaming responses. +* Session and Cookie support. +* 100% test coverage. +* 100% type annotated codebase. +* Few hard dependencies. +* Compatible with `asyncio` and `trio` backends. +* Great overall performance [against independent benchmarks][techempower]. + +## Requirements + +Python 3.7+ (For Python 3.6 support, install version 0.19.1) + +## Installation + +```shell +$ pip3 install starlette +``` + +You'll also want to install an ASGI server, such as [uvicorn](http://www.uvicorn.org/), [daphne](https://github.com/django/daphne/), or [hypercorn](https://pgjones.gitlab.io/hypercorn/). + +```shell +$ pip3 install uvicorn +``` + +## Example + +**example.py**: + +```python +from starlette.applications import Starlette +from starlette.responses import JSONResponse +from starlette.routing import Route + + +async def homepage(request): + return JSONResponse({'hello': 'world'}) + +routes = [ + Route("/", endpoint=homepage) +] + +app = Starlette(debug=True, routes=routes) +``` + +Then run the application using Uvicorn: + +```shell +$ uvicorn example:app +``` + +For a more complete example, see [encode/starlette-example](https://github.com/encode/starlette-example). + +## Dependencies + +Starlette only requires `anyio`, and the following are optional: + +* [`httpx`][httpx] - Required if you want to use the `TestClient`. +* [`jinja2`][jinja2] - Required if you want to use `Jinja2Templates`. +* [`python-multipart`][python-multipart] - Required if you want to support form parsing, with `request.form()`. +* [`itsdangerous`][itsdangerous] - Required for `SessionMiddleware` support. +* [`pyyaml`][pyyaml] - Required for `SchemaGenerator` support. + +You can install all of these with `pip3 install starlette[full]`. + +## Framework or Toolkit + +Starlette is designed to be used either as a complete framework, or as +an ASGI toolkit. You can use any of its components independently. + +```python +from starlette.responses import PlainTextResponse + + +async def app(scope, receive, send): + assert scope['type'] == 'http' + response = PlainTextResponse('Hello, world!') + await response(scope, receive, send) +``` + +Run the `app` application in `example.py`: + +```shell +$ uvicorn example:app +INFO: Started server process [11509] +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +Run uvicorn with `--reload` to enable auto-reloading on code changes. + +## Modularity + +The modularity that Starlette is designed on promotes building re-usable +components that can be shared between any ASGI framework. This should enable +an ecosystem of shared middleware and mountable applications. + +The clean API separation also means it's easier to understand each component +in isolation. + +--- + +

    Starlette is BSD licensed code.
    Designed & crafted with care.

    — ⭐️ —

    + +[asgi]: https://asgi.readthedocs.io/en/latest/ +[httpx]: https://www.python-httpx.org/ +[jinja2]: https://jinja.palletsprojects.com/ +[python-multipart]: https://andrew-d.github.io/python-multipart/ +[itsdangerous]: https://pythonhosted.org/itsdangerous/ +[sqlalchemy]: https://www.sqlalchemy.org +[pyyaml]: https://pyyaml.org/wiki/PyYAMLDocumentation +[techempower]: https://www.techempower.com/benchmarks/#hw=ph&test=fortune&l=zijzen-sf diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette-0.27.0.dist-info/RECORD b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette-0.27.0.dist-info/RECORD new file mode 100644 index 0000000..978921d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette-0.27.0.dist-info/RECORD @@ -0,0 +1,40 @@ +starlette-0.27.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +starlette-0.27.0.dist-info/METADATA,sha256=aRGS5IZiIcH4LHlaxCEFiEiMwsiEFB2OQFqRSX6PqOc,5836 +starlette-0.27.0.dist-info/RECORD,, +starlette-0.27.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87 +starlette-0.27.0.dist-info/licenses/LICENSE.md,sha256=3LlWd6AiQCQxh-lk-UGEfRmxeCHPmeWvrmhPqzKMGb8,1518 +starlette/__init__.py,sha256=Hjsc9XQ3AkqXm-5cdlX-H8iKjURzi1FQeWNi2xx34Uo,23 +starlette/_compat.py,sha256=pcaBiAKr9ON7PFVg780yWlgH88AYXTGfcyV6c3awVY4,1148 +starlette/_utils.py,sha256=bfWqFx4MTDFQErQbUUc2Ju4jXebAfxt9babj_vfYJsA,2091 +starlette/applications.py,sha256=_2J5gLuYJHx1TlY7XP0AAGafY-cJUcsNfedXI9GpNto,10508 +starlette/authentication.py,sha256=D75AvQ1h0lieiDiuCnomd4Jgu-SIq-79LUjkaKMsydI,5246 +starlette/background.py,sha256=g0ouyGnoI2CdtE2N_AJiOYUf1ChyLJcaqFqU8gIlAFo,1259 +starlette/concurrency.py,sha256=IIxlJASchhv7T1ik_WQRuN-6Pd0r--_x4gqt9odO0Yc,1741 +starlette/config.py,sha256=3KVOFI4_HY0TOI8rx3fo5SSgdsLQVq4EOiwVErsMDOA,4607 +starlette/convertors.py,sha256=qVnVaf9FGvqBJvINMhDmIY9z-yfXrAIIvPRseo3C0CA,2168 +starlette/datastructures.py,sha256=6T4D5cKic6OrW4Vm4KNZRIakL1YE2VpIu1k_Q7DlC4Y,23087 +starlette/endpoints.py,sha256=MhchWhZad027dSGnevk5xRNjQDAFhr9SAy46xbxOWxQ,5143 +starlette/exceptions.py,sha256=1m1T-7xlfk1WWWfmQg0VdehYOemsCNh0Igxq43euoek,1648 +starlette/formparsers.py,sha256=D8C4PPjEzeSIaKNOtqhqRQxrgRrMa6TB8Gz72NFJmuI,10423 +starlette/middleware/__init__.py,sha256=tEegvh1lBhUfHaJ0p-T_9FU7PRT1WHoIc2vZX0pUlm8,546 +starlette/middleware/authentication.py,sha256=rP3t8t7HoO3xW8LH48Yo_GY8jzyx7WCrT88m_1O_kJ4,1787 +starlette/middleware/base.py,sha256=cCGePX-4DVn14F1bUgYchKbpt9-3J6NehEfZZsbm-z8,5010 +starlette/middleware/cors.py,sha256=ugLUxg0vxwTdKDKKZ7TniEhkVfQvri-qB9KdZQnbJzE,7075 +starlette/middleware/errors.py,sha256=vbvLJWnZZicLXjd9SgA0iQo9LxDUIOnu5uWHr-nabv8,7833 +starlette/middleware/exceptions.py,sha256=lNklm6eq3CRN2_Y6fLUNYe9gAZ7CfUkc8l6-U9Dyow4,4128 +starlette/middleware/gzip.py,sha256=4PwBc42TLGo50SNUn8PNMndiJmN6VHdIBI5x1Pyq4go,4507 +starlette/middleware/httpsredirect.py,sha256=SNTleaYALGoITV7xwbic4gB6VYdM8Ylea_ykciUz31g,848 +starlette/middleware/sessions.py,sha256=-F3j-pXq1cNmvVh1qxrn4pnVHJwxzOCWC90vd7y8apo,3612 +starlette/middleware/trustedhost.py,sha256=5oTnnGRXQC4KJTROs802G9tJzBij2zI9ze11aEdbins,2207 +starlette/middleware/wsgi.py,sha256=YbjlcETXYzaN5--Rk2uC2vEvxAiKwuvWQ7IuOFjU3H4,4906 +starlette/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +starlette/requests.py,sha256=C-BhdMh4SEyKc_6I6FtTs_1kyVsHPhattIfRsp5KMhU,10757 +starlette/responses.py,sha256=rk_xoeA0Ahvr9PyHUrU3BoA_VZzV7PhTQZOTkbBkMk4,13147 +starlette/routing.py,sha256=55K6eE1nQQJobnOtleXs-HzhRNmWpQ8l2tGtKh4eXK0,32447 +starlette/schemas.py,sha256=ONSfw5dKamzhp1J33R-hdMRe7LFFAaVkLKltNHHpgiw,4959 +starlette/staticfiles.py,sha256=OIpJNoYbEPuXrD_VDq0EYW_QvrKtPfFpS58L5S52_p8,8733 +starlette/status.py,sha256=lv40V7igYhk_ONySJzUzQ4T3gTgnvNLCOb846ZUONSE,6086 +starlette/templating.py,sha256=8OBittl-UDFuURCkn8fZLK6zvdEIbKUK_G7td7Be7Ac,4170 +starlette/testclient.py,sha256=M0kjDdhyYICRgkQME490XBjd_G3TGqKHFohXjMHyBnY,29208 +starlette/types.py,sha256=1rDF_9STRMax4qG1cbL8YYyJx85_IyJefGCo7Q1Sv9M,613 +starlette/websockets.py,sha256=4jcG-f6BacONwAyhuUzCAnsIr8P--3pXF0TdtVCLurg,7360 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette-0.27.0.dist-info/WHEEL b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette-0.27.0.dist-info/WHEEL new file mode 100644 index 0000000..12228d4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette-0.27.0.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: hatchling 1.27.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette-0.27.0.dist-info/licenses/LICENSE.md b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette-0.27.0.dist-info/licenses/LICENSE.md new file mode 100644 index 0000000..d16a60e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette-0.27.0.dist-info/licenses/LICENSE.md @@ -0,0 +1,27 @@ +Copyright © 2018, [Encode OSS Ltd](https://www.encode.io/). +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/__init__.py new file mode 100644 index 0000000..cde6d89 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/__init__.py @@ -0,0 +1 @@ +__version__ = "0.27.0" diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/_compat.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/_compat.py new file mode 100644 index 0000000..9087a76 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/_compat.py @@ -0,0 +1,28 @@ +import hashlib + +# Compat wrapper to always include the `usedforsecurity=...` parameter, +# which is only added from Python 3.9 onwards. +# We use this flag to indicate that we use `md5` hashes only for non-security +# cases (our ETag checksums). +# If we don't indicate that we're using MD5 for non-security related reasons, +# then attempting to use this function will raise an error when used +# environments which enable a strict "FIPs mode". +# +# See issue: https://github.com/encode/starlette/issues/1365 +try: + # check if the Python version supports the parameter + # using usedforsecurity=False to avoid an exception on FIPS systems + # that reject usedforsecurity=True + hashlib.md5(b"data", usedforsecurity=False) # type: ignore[call-arg] + + def md5_hexdigest( + data: bytes, *, usedforsecurity: bool = True + ) -> str: # pragma: no cover + return hashlib.md5( # type: ignore[call-arg] + data, usedforsecurity=usedforsecurity + ).hexdigest() + +except TypeError: # pragma: no cover + + def md5_hexdigest(data: bytes, *, usedforsecurity: bool = True) -> str: + return hashlib.md5(data).hexdigest() diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/_utils.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/_utils.py new file mode 100644 index 0000000..d781647 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/_utils.py @@ -0,0 +1,74 @@ +import asyncio +import functools +import sys +import typing +from types import TracebackType + +if sys.version_info < (3, 8): # pragma: no cover + from typing_extensions import Protocol +else: # pragma: no cover + from typing import Protocol + + +def is_async_callable(obj: typing.Any) -> bool: + while isinstance(obj, functools.partial): + obj = obj.func + + return asyncio.iscoroutinefunction(obj) or ( + callable(obj) and asyncio.iscoroutinefunction(obj.__call__) + ) + + +T_co = typing.TypeVar("T_co", covariant=True) + + +# TODO: once 3.8 is the minimum supported version (27 Jun 2023) +# this can just become +# class AwaitableOrContextManager( +# typing.Awaitable[T_co], +# typing.AsyncContextManager[T_co], +# typing.Protocol[T_co], +# ): +# pass +class AwaitableOrContextManager(Protocol[T_co]): + def __await__(self) -> typing.Generator[typing.Any, None, T_co]: + ... # pragma: no cover + + async def __aenter__(self) -> T_co: + ... # pragma: no cover + + async def __aexit__( + self, + __exc_type: typing.Optional[typing.Type[BaseException]], + __exc_value: typing.Optional[BaseException], + __traceback: typing.Optional[TracebackType], + ) -> typing.Union[bool, None]: + ... # pragma: no cover + + +class SupportsAsyncClose(Protocol): + async def close(self) -> None: + ... # pragma: no cover + + +SupportsAsyncCloseType = typing.TypeVar( + "SupportsAsyncCloseType", bound=SupportsAsyncClose, covariant=False +) + + +class AwaitableOrContextManagerWrapper(typing.Generic[SupportsAsyncCloseType]): + __slots__ = ("aw", "entered") + + def __init__(self, aw: typing.Awaitable[SupportsAsyncCloseType]) -> None: + self.aw = aw + + def __await__(self) -> typing.Generator[typing.Any, None, SupportsAsyncCloseType]: + return self.aw.__await__() + + async def __aenter__(self) -> SupportsAsyncCloseType: + self.entered = await self.aw + return self.entered + + async def __aexit__(self, *args: typing.Any) -> typing.Union[None, bool]: + await self.entered.close() + return None diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/applications.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/applications.py new file mode 100644 index 0000000..013364b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/applications.py @@ -0,0 +1,261 @@ +import typing +import warnings + +from starlette.datastructures import State, URLPath +from starlette.middleware import Middleware +from starlette.middleware.base import BaseHTTPMiddleware +from starlette.middleware.errors import ServerErrorMiddleware +from starlette.middleware.exceptions import ExceptionMiddleware +from starlette.requests import Request +from starlette.responses import Response +from starlette.routing import BaseRoute, Router +from starlette.types import ASGIApp, Lifespan, Receive, Scope, Send + +AppType = typing.TypeVar("AppType", bound="Starlette") + + +class Starlette: + """ + Creates an application instance. + + **Parameters:** + + * **debug** - Boolean indicating if debug tracebacks should be returned on errors. + * **routes** - A list of routes to serve incoming HTTP and WebSocket requests. + * **middleware** - A list of middleware to run for every request. A starlette + application will always automatically include two middleware classes. + `ServerErrorMiddleware` is added as the very outermost middleware, to handle + any uncaught errors occurring anywhere in the entire stack. + `ExceptionMiddleware` is added as the very innermost middleware, to deal + with handled exception cases occurring in the routing or endpoints. + * **exception_handlers** - A mapping of either integer status codes, + or exception class types onto callables which handle the exceptions. + Exception handler callables should be of the form + `handler(request, exc) -> response` and may be be either standard functions, or + async functions. + * **on_startup** - A list of callables to run on application startup. + Startup handler callables do not take any arguments, and may be be either + standard functions, or async functions. + * **on_shutdown** - A list of callables to run on application shutdown. + Shutdown handler callables do not take any arguments, and may be be either + standard functions, or async functions. + * **lifespan** - A lifespan context function, which can be used to perform + startup and shutdown tasks. This is a newer style that replaces the + `on_startup` and `on_shutdown` handlers. Use one or the other, not both. + """ + + def __init__( + self: "AppType", + debug: bool = False, + routes: typing.Optional[typing.Sequence[BaseRoute]] = None, + middleware: typing.Optional[typing.Sequence[Middleware]] = None, + exception_handlers: typing.Optional[ + typing.Mapping[ + typing.Any, + typing.Callable[ + [Request, Exception], + typing.Union[Response, typing.Awaitable[Response]], + ], + ] + ] = None, + on_startup: typing.Optional[typing.Sequence[typing.Callable]] = None, + on_shutdown: typing.Optional[typing.Sequence[typing.Callable]] = None, + lifespan: typing.Optional[Lifespan["AppType"]] = None, + ) -> None: + # The lifespan context function is a newer style that replaces + # on_startup / on_shutdown handlers. Use one or the other, not both. + assert lifespan is None or ( + on_startup is None and on_shutdown is None + ), "Use either 'lifespan' or 'on_startup'/'on_shutdown', not both." + + self.debug = debug + self.state = State() + self.router = Router( + routes, on_startup=on_startup, on_shutdown=on_shutdown, lifespan=lifespan + ) + self.exception_handlers = ( + {} if exception_handlers is None else dict(exception_handlers) + ) + self.user_middleware = [] if middleware is None else list(middleware) + self.middleware_stack: typing.Optional[ASGIApp] = None + + def build_middleware_stack(self) -> ASGIApp: + debug = self.debug + error_handler = None + exception_handlers: typing.Dict[ + typing.Any, typing.Callable[[Request, Exception], Response] + ] = {} + + for key, value in self.exception_handlers.items(): + if key in (500, Exception): + error_handler = value + else: + exception_handlers[key] = value + + middleware = ( + [Middleware(ServerErrorMiddleware, handler=error_handler, debug=debug)] + + self.user_middleware + + [ + Middleware( + ExceptionMiddleware, handlers=exception_handlers, debug=debug + ) + ] + ) + + app = self.router + for cls, options in reversed(middleware): + app = cls(app=app, **options) + return app + + @property + def routes(self) -> typing.List[BaseRoute]: + return self.router.routes + + # TODO: Make `__name` a positional-only argument when we drop Python 3.7 support. + def url_path_for(self, __name: str, **path_params: typing.Any) -> URLPath: + return self.router.url_path_for(__name, **path_params) + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + scope["app"] = self + if self.middleware_stack is None: + self.middleware_stack = self.build_middleware_stack() + await self.middleware_stack(scope, receive, send) + + def on_event(self, event_type: str) -> typing.Callable: # pragma: nocover + return self.router.on_event(event_type) + + def mount( + self, path: str, app: ASGIApp, name: typing.Optional[str] = None + ) -> None: # pragma: nocover + self.router.mount(path, app=app, name=name) + + def host( + self, host: str, app: ASGIApp, name: typing.Optional[str] = None + ) -> None: # pragma: no cover + self.router.host(host, app=app, name=name) + + def add_middleware(self, middleware_class: type, **options: typing.Any) -> None: + if self.middleware_stack is not None: # pragma: no cover + raise RuntimeError("Cannot add middleware after an application has started") + self.user_middleware.insert(0, Middleware(middleware_class, **options)) + + def add_exception_handler( + self, + exc_class_or_status_code: typing.Union[int, typing.Type[Exception]], + handler: typing.Callable, + ) -> None: # pragma: no cover + self.exception_handlers[exc_class_or_status_code] = handler + + def add_event_handler( + self, event_type: str, func: typing.Callable + ) -> None: # pragma: no cover + self.router.add_event_handler(event_type, func) + + def add_route( + self, + path: str, + route: typing.Callable, + methods: typing.Optional[typing.List[str]] = None, + name: typing.Optional[str] = None, + include_in_schema: bool = True, + ) -> None: # pragma: no cover + self.router.add_route( + path, route, methods=methods, name=name, include_in_schema=include_in_schema + ) + + def add_websocket_route( + self, path: str, route: typing.Callable, name: typing.Optional[str] = None + ) -> None: # pragma: no cover + self.router.add_websocket_route(path, route, name=name) + + def exception_handler( + self, exc_class_or_status_code: typing.Union[int, typing.Type[Exception]] + ) -> typing.Callable: + warnings.warn( + "The `exception_handler` decorator is deprecated, and will be removed in version 1.0.0. " # noqa: E501 + "Refer to https://www.starlette.io/exceptions/ for the recommended approach.", # noqa: E501 + DeprecationWarning, + ) + + def decorator(func: typing.Callable) -> typing.Callable: + self.add_exception_handler(exc_class_or_status_code, func) + return func + + return decorator + + def route( + self, + path: str, + methods: typing.Optional[typing.List[str]] = None, + name: typing.Optional[str] = None, + include_in_schema: bool = True, + ) -> typing.Callable: + """ + We no longer document this decorator style API, and its usage is discouraged. + Instead you should use the following approach: + + >>> routes = [Route(path, endpoint=...), ...] + >>> app = Starlette(routes=routes) + """ + warnings.warn( + "The `route` decorator is deprecated, and will be removed in version 1.0.0. " # noqa: E501 + "Refer to https://www.starlette.io/routing/ for the recommended approach.", # noqa: E501 + DeprecationWarning, + ) + + def decorator(func: typing.Callable) -> typing.Callable: + self.router.add_route( + path, + func, + methods=methods, + name=name, + include_in_schema=include_in_schema, + ) + return func + + return decorator + + def websocket_route( + self, path: str, name: typing.Optional[str] = None + ) -> typing.Callable: + """ + We no longer document this decorator style API, and its usage is discouraged. + Instead you should use the following approach: + + >>> routes = [WebSocketRoute(path, endpoint=...), ...] + >>> app = Starlette(routes=routes) + """ + warnings.warn( + "The `websocket_route` decorator is deprecated, and will be removed in version 1.0.0. " # noqa: E501 + "Refer to https://www.starlette.io/routing/#websocket-routing for the recommended approach.", # noqa: E501 + DeprecationWarning, + ) + + def decorator(func: typing.Callable) -> typing.Callable: + self.router.add_websocket_route(path, func, name=name) + return func + + return decorator + + def middleware(self, middleware_type: str) -> typing.Callable: + """ + We no longer document this decorator style API, and its usage is discouraged. + Instead you should use the following approach: + + >>> middleware = [Middleware(...), ...] + >>> app = Starlette(middleware=middleware) + """ + warnings.warn( + "The `middleware` decorator is deprecated, and will be removed in version 1.0.0. " # noqa: E501 + "Refer to https://www.starlette.io/middleware/#using-middleware for recommended approach.", # noqa: E501 + DeprecationWarning, + ) + assert ( + middleware_type == "http" + ), 'Currently only middleware("http") is supported.' + + def decorator(func: typing.Callable) -> typing.Callable: + self.add_middleware(BaseHTTPMiddleware, dispatch=func) + return func + + return decorator diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/authentication.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/authentication.py new file mode 100644 index 0000000..32713eb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/authentication.py @@ -0,0 +1,153 @@ +import functools +import inspect +import typing +from urllib.parse import urlencode + +from starlette._utils import is_async_callable +from starlette.exceptions import HTTPException +from starlette.requests import HTTPConnection, Request +from starlette.responses import RedirectResponse, Response +from starlette.websockets import WebSocket + +_CallableType = typing.TypeVar("_CallableType", bound=typing.Callable) + + +def has_required_scope(conn: HTTPConnection, scopes: typing.Sequence[str]) -> bool: + for scope in scopes: + if scope not in conn.auth.scopes: + return False + return True + + +def requires( + scopes: typing.Union[str, typing.Sequence[str]], + status_code: int = 403, + redirect: typing.Optional[str] = None, +) -> typing.Callable[[_CallableType], _CallableType]: + scopes_list = [scopes] if isinstance(scopes, str) else list(scopes) + + def decorator(func: typing.Callable) -> typing.Callable: + sig = inspect.signature(func) + for idx, parameter in enumerate(sig.parameters.values()): + if parameter.name == "request" or parameter.name == "websocket": + type_ = parameter.name + break + else: + raise Exception( + f'No "request" or "websocket" argument on function "{func}"' + ) + + if type_ == "websocket": + # Handle websocket functions. (Always async) + @functools.wraps(func) + async def websocket_wrapper( + *args: typing.Any, **kwargs: typing.Any + ) -> None: + websocket = kwargs.get( + "websocket", args[idx] if idx < len(args) else None + ) + assert isinstance(websocket, WebSocket) + + if not has_required_scope(websocket, scopes_list): + await websocket.close() + else: + await func(*args, **kwargs) + + return websocket_wrapper + + elif is_async_callable(func): + # Handle async request/response functions. + @functools.wraps(func) + async def async_wrapper( + *args: typing.Any, **kwargs: typing.Any + ) -> Response: + request = kwargs.get("request", args[idx] if idx < len(args) else None) + assert isinstance(request, Request) + + if not has_required_scope(request, scopes_list): + if redirect is not None: + orig_request_qparam = urlencode({"next": str(request.url)}) + next_url = "{redirect_path}?{orig_request}".format( + redirect_path=request.url_for(redirect), + orig_request=orig_request_qparam, + ) + return RedirectResponse(url=next_url, status_code=303) + raise HTTPException(status_code=status_code) + return await func(*args, **kwargs) + + return async_wrapper + + else: + # Handle sync request/response functions. + @functools.wraps(func) + def sync_wrapper(*args: typing.Any, **kwargs: typing.Any) -> Response: + request = kwargs.get("request", args[idx] if idx < len(args) else None) + assert isinstance(request, Request) + + if not has_required_scope(request, scopes_list): + if redirect is not None: + orig_request_qparam = urlencode({"next": str(request.url)}) + next_url = "{redirect_path}?{orig_request}".format( + redirect_path=request.url_for(redirect), + orig_request=orig_request_qparam, + ) + return RedirectResponse(url=next_url, status_code=303) + raise HTTPException(status_code=status_code) + return func(*args, **kwargs) + + return sync_wrapper + + return decorator # type: ignore[return-value] + + +class AuthenticationError(Exception): + pass + + +class AuthenticationBackend: + async def authenticate( + self, conn: HTTPConnection + ) -> typing.Optional[typing.Tuple["AuthCredentials", "BaseUser"]]: + raise NotImplementedError() # pragma: no cover + + +class AuthCredentials: + def __init__(self, scopes: typing.Optional[typing.Sequence[str]] = None): + self.scopes = [] if scopes is None else list(scopes) + + +class BaseUser: + @property + def is_authenticated(self) -> bool: + raise NotImplementedError() # pragma: no cover + + @property + def display_name(self) -> str: + raise NotImplementedError() # pragma: no cover + + @property + def identity(self) -> str: + raise NotImplementedError() # pragma: no cover + + +class SimpleUser(BaseUser): + def __init__(self, username: str) -> None: + self.username = username + + @property + def is_authenticated(self) -> bool: + return True + + @property + def display_name(self) -> str: + return self.username + + +class UnauthenticatedUser(BaseUser): + @property + def is_authenticated(self) -> bool: + return False + + @property + def display_name(self) -> str: + return "" diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/background.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/background.py new file mode 100644 index 0000000..4aaf7ae --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/background.py @@ -0,0 +1,43 @@ +import sys +import typing + +if sys.version_info >= (3, 10): # pragma: no cover + from typing import ParamSpec +else: # pragma: no cover + from typing_extensions import ParamSpec + +from starlette._utils import is_async_callable +from starlette.concurrency import run_in_threadpool + +P = ParamSpec("P") + + +class BackgroundTask: + def __init__( + self, func: typing.Callable[P, typing.Any], *args: P.args, **kwargs: P.kwargs + ) -> None: + self.func = func + self.args = args + self.kwargs = kwargs + self.is_async = is_async_callable(func) + + async def __call__(self) -> None: + if self.is_async: + await self.func(*self.args, **self.kwargs) + else: + await run_in_threadpool(self.func, *self.args, **self.kwargs) + + +class BackgroundTasks(BackgroundTask): + def __init__(self, tasks: typing.Optional[typing.Sequence[BackgroundTask]] = None): + self.tasks = list(tasks) if tasks else [] + + def add_task( + self, func: typing.Callable[P, typing.Any], *args: P.args, **kwargs: P.kwargs + ) -> None: + task = BackgroundTask(func, *args, **kwargs) + self.tasks.append(task) + + async def __call__(self) -> None: + for task in self.tasks: + await task() diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/concurrency.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/concurrency.py new file mode 100644 index 0000000..5c76cb3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/concurrency.py @@ -0,0 +1,65 @@ +import functools +import sys +import typing +import warnings + +import anyio + +if sys.version_info >= (3, 10): # pragma: no cover + from typing import ParamSpec +else: # pragma: no cover + from typing_extensions import ParamSpec + + +T = typing.TypeVar("T") +P = ParamSpec("P") + + +async def run_until_first_complete(*args: typing.Tuple[typing.Callable, dict]) -> None: + warnings.warn( + "run_until_first_complete is deprecated " + "and will be removed in a future version.", + DeprecationWarning, + ) + + async with anyio.create_task_group() as task_group: + + async def run(func: typing.Callable[[], typing.Coroutine]) -> None: + await func() + task_group.cancel_scope.cancel() + + for func, kwargs in args: + task_group.start_soon(run, functools.partial(func, **kwargs)) + + +async def run_in_threadpool( + func: typing.Callable[P, T], *args: P.args, **kwargs: P.kwargs +) -> T: + if kwargs: # pragma: no cover + # run_sync doesn't accept 'kwargs', so bind them in here + func = functools.partial(func, **kwargs) + return await anyio.to_thread.run_sync(func, *args) + + +class _StopIteration(Exception): + pass + + +def _next(iterator: typing.Iterator[T]) -> T: + # We can't raise `StopIteration` from within the threadpool iterator + # and catch it outside that context, so we coerce them into a different + # exception type. + try: + return next(iterator) + except StopIteration: + raise _StopIteration + + +async def iterate_in_threadpool( + iterator: typing.Iterator[T], +) -> typing.AsyncIterator[T]: + while True: + try: + yield await anyio.to_thread.run_sync(_next, iterator) + except _StopIteration: + break diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/config.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/config.py new file mode 100644 index 0000000..795232c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/config.py @@ -0,0 +1,149 @@ +import os +import typing +from collections.abc import MutableMapping +from pathlib import Path + + +class undefined: + pass + + +class EnvironError(Exception): + pass + + +class Environ(MutableMapping): + def __init__(self, environ: typing.MutableMapping = os.environ): + self._environ = environ + self._has_been_read: typing.Set[typing.Any] = set() + + def __getitem__(self, key: typing.Any) -> typing.Any: + self._has_been_read.add(key) + return self._environ.__getitem__(key) + + def __setitem__(self, key: typing.Any, value: typing.Any) -> None: + if key in self._has_been_read: + raise EnvironError( + f"Attempting to set environ['{key}'], but the value has already been " + "read." + ) + self._environ.__setitem__(key, value) + + def __delitem__(self, key: typing.Any) -> None: + if key in self._has_been_read: + raise EnvironError( + f"Attempting to delete environ['{key}'], but the value has already " + "been read." + ) + self._environ.__delitem__(key) + + def __iter__(self) -> typing.Iterator: + return iter(self._environ) + + def __len__(self) -> int: + return len(self._environ) + + +environ = Environ() + +T = typing.TypeVar("T") + + +class Config: + def __init__( + self, + env_file: typing.Optional[typing.Union[str, Path]] = None, + environ: typing.Mapping[str, str] = environ, + env_prefix: str = "", + ) -> None: + self.environ = environ + self.env_prefix = env_prefix + self.file_values: typing.Dict[str, str] = {} + if env_file is not None and os.path.isfile(env_file): + self.file_values = self._read_file(env_file) + + @typing.overload + def __call__(self, key: str, *, default: None) -> typing.Optional[str]: + ... + + @typing.overload + def __call__(self, key: str, cast: typing.Type[T], default: T = ...) -> T: + ... + + @typing.overload + def __call__( + self, key: str, cast: typing.Type[str] = ..., default: str = ... + ) -> str: + ... + + @typing.overload + def __call__( + self, + key: str, + cast: typing.Callable[[typing.Any], T] = ..., + default: typing.Any = ..., + ) -> T: + ... + + @typing.overload + def __call__( + self, key: str, cast: typing.Type[str] = ..., default: T = ... + ) -> typing.Union[T, str]: + ... + + def __call__( + self, + key: str, + cast: typing.Optional[typing.Callable] = None, + default: typing.Any = undefined, + ) -> typing.Any: + return self.get(key, cast, default) + + def get( + self, + key: str, + cast: typing.Optional[typing.Callable] = None, + default: typing.Any = undefined, + ) -> typing.Any: + key = self.env_prefix + key + if key in self.environ: + value = self.environ[key] + return self._perform_cast(key, value, cast) + if key in self.file_values: + value = self.file_values[key] + return self._perform_cast(key, value, cast) + if default is not undefined: + return self._perform_cast(key, default, cast) + raise KeyError(f"Config '{key}' is missing, and has no default.") + + def _read_file(self, file_name: typing.Union[str, Path]) -> typing.Dict[str, str]: + file_values: typing.Dict[str, str] = {} + with open(file_name) as input_file: + for line in input_file.readlines(): + line = line.strip() + if "=" in line and not line.startswith("#"): + key, value = line.split("=", 1) + key = key.strip() + value = value.strip().strip("\"'") + file_values[key] = value + return file_values + + def _perform_cast( + self, key: str, value: typing.Any, cast: typing.Optional[typing.Callable] = None + ) -> typing.Any: + if cast is None or value is None: + return value + elif cast is bool and isinstance(value, str): + mapping = {"true": True, "1": True, "false": False, "0": False} + value = value.lower() + if value not in mapping: + raise ValueError( + f"Config '{key}' has value '{value}'. Not a valid bool." + ) + return mapping[value] + try: + return cast(value) + except (TypeError, ValueError): + raise ValueError( + f"Config '{key}' has value '{value}'. Not a valid {cast.__name__}." + ) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/convertors.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/convertors.py new file mode 100644 index 0000000..3ade9f7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/convertors.py @@ -0,0 +1,87 @@ +import math +import typing +import uuid + +T = typing.TypeVar("T") + + +class Convertor(typing.Generic[T]): + regex: typing.ClassVar[str] = "" + + def convert(self, value: str) -> T: + raise NotImplementedError() # pragma: no cover + + def to_string(self, value: T) -> str: + raise NotImplementedError() # pragma: no cover + + +class StringConvertor(Convertor): + regex = "[^/]+" + + def convert(self, value: str) -> str: + return value + + def to_string(self, value: str) -> str: + value = str(value) + assert "/" not in value, "May not contain path separators" + assert value, "Must not be empty" + return value + + +class PathConvertor(Convertor): + regex = ".*" + + def convert(self, value: str) -> str: + return str(value) + + def to_string(self, value: str) -> str: + return str(value) + + +class IntegerConvertor(Convertor): + regex = "[0-9]+" + + def convert(self, value: str) -> int: + return int(value) + + def to_string(self, value: int) -> str: + value = int(value) + assert value >= 0, "Negative integers are not supported" + return str(value) + + +class FloatConvertor(Convertor): + regex = r"[0-9]+(\.[0-9]+)?" + + def convert(self, value: str) -> float: + return float(value) + + def to_string(self, value: float) -> str: + value = float(value) + assert value >= 0.0, "Negative floats are not supported" + assert not math.isnan(value), "NaN values are not supported" + assert not math.isinf(value), "Infinite values are not supported" + return ("%0.20f" % value).rstrip("0").rstrip(".") + + +class UUIDConvertor(Convertor): + regex = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" + + def convert(self, value: str) -> uuid.UUID: + return uuid.UUID(value) + + def to_string(self, value: uuid.UUID) -> str: + return str(value) + + +CONVERTOR_TYPES = { + "str": StringConvertor(), + "path": PathConvertor(), + "int": IntegerConvertor(), + "float": FloatConvertor(), + "uuid": UUIDConvertor(), +} + + +def register_url_convertor(key: str, convertor: Convertor) -> None: + CONVERTOR_TYPES[key] = convertor diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/datastructures.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/datastructures.py new file mode 100644 index 0000000..236f9fa --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/datastructures.py @@ -0,0 +1,708 @@ +import typing +from collections.abc import Sequence +from shlex import shlex +from urllib.parse import SplitResult, parse_qsl, urlencode, urlsplit + +from starlette.concurrency import run_in_threadpool +from starlette.types import Scope + + +class Address(typing.NamedTuple): + host: str + port: int + + +_KeyType = typing.TypeVar("_KeyType") +# Mapping keys are invariant but their values are covariant since +# you can only read them +# that is, you can't do `Mapping[str, Animal]()["fido"] = Dog()` +_CovariantValueType = typing.TypeVar("_CovariantValueType", covariant=True) + + +class URL: + def __init__( + self, + url: str = "", + scope: typing.Optional[Scope] = None, + **components: typing.Any, + ) -> None: + if scope is not None: + assert not url, 'Cannot set both "url" and "scope".' + assert not components, 'Cannot set both "scope" and "**components".' + scheme = scope.get("scheme", "http") + server = scope.get("server", None) + path = scope.get("root_path", "") + scope["path"] + query_string = scope.get("query_string", b"") + + host_header = None + for key, value in scope["headers"]: + if key == b"host": + host_header = value.decode("latin-1") + break + + if host_header is not None: + url = f"{scheme}://{host_header}{path}" + elif server is None: + url = path + else: + host, port = server + default_port = {"http": 80, "https": 443, "ws": 80, "wss": 443}[scheme] + if port == default_port: + url = f"{scheme}://{host}{path}" + else: + url = f"{scheme}://{host}:{port}{path}" + + if query_string: + url += "?" + query_string.decode() + elif components: + assert not url, 'Cannot set both "url" and "**components".' + url = URL("").replace(**components).components.geturl() + + self._url = url + + @property + def components(self) -> SplitResult: + if not hasattr(self, "_components"): + self._components = urlsplit(self._url) + return self._components + + @property + def scheme(self) -> str: + return self.components.scheme + + @property + def netloc(self) -> str: + return self.components.netloc + + @property + def path(self) -> str: + return self.components.path + + @property + def query(self) -> str: + return self.components.query + + @property + def fragment(self) -> str: + return self.components.fragment + + @property + def username(self) -> typing.Union[None, str]: + return self.components.username + + @property + def password(self) -> typing.Union[None, str]: + return self.components.password + + @property + def hostname(self) -> typing.Union[None, str]: + return self.components.hostname + + @property + def port(self) -> typing.Optional[int]: + return self.components.port + + @property + def is_secure(self) -> bool: + return self.scheme in ("https", "wss") + + def replace(self, **kwargs: typing.Any) -> "URL": + if ( + "username" in kwargs + or "password" in kwargs + or "hostname" in kwargs + or "port" in kwargs + ): + hostname = kwargs.pop("hostname", None) + port = kwargs.pop("port", self.port) + username = kwargs.pop("username", self.username) + password = kwargs.pop("password", self.password) + + if hostname is None: + netloc = self.netloc + _, _, hostname = netloc.rpartition("@") + + if hostname[-1] != "]": + hostname = hostname.rsplit(":", 1)[0] + + netloc = hostname + if port is not None: + netloc += f":{port}" + if username is not None: + userpass = username + if password is not None: + userpass += f":{password}" + netloc = f"{userpass}@{netloc}" + + kwargs["netloc"] = netloc + + components = self.components._replace(**kwargs) + return self.__class__(components.geturl()) + + def include_query_params(self, **kwargs: typing.Any) -> "URL": + params = MultiDict(parse_qsl(self.query, keep_blank_values=True)) + params.update({str(key): str(value) for key, value in kwargs.items()}) + query = urlencode(params.multi_items()) + return self.replace(query=query) + + def replace_query_params(self, **kwargs: typing.Any) -> "URL": + query = urlencode([(str(key), str(value)) for key, value in kwargs.items()]) + return self.replace(query=query) + + def remove_query_params( + self, keys: typing.Union[str, typing.Sequence[str]] + ) -> "URL": + if isinstance(keys, str): + keys = [keys] + params = MultiDict(parse_qsl(self.query, keep_blank_values=True)) + for key in keys: + params.pop(key, None) + query = urlencode(params.multi_items()) + return self.replace(query=query) + + def __eq__(self, other: typing.Any) -> bool: + return str(self) == str(other) + + def __str__(self) -> str: + return self._url + + def __repr__(self) -> str: + url = str(self) + if self.password: + url = str(self.replace(password="********")) + return f"{self.__class__.__name__}({repr(url)})" + + +class URLPath(str): + """ + A URL path string that may also hold an associated protocol and/or host. + Used by the routing to return `url_path_for` matches. + """ + + def __new__(cls, path: str, protocol: str = "", host: str = "") -> "URLPath": + assert protocol in ("http", "websocket", "") + return str.__new__(cls, path) + + def __init__(self, path: str, protocol: str = "", host: str = "") -> None: + self.protocol = protocol + self.host = host + + def make_absolute_url(self, base_url: typing.Union[str, URL]) -> URL: + if isinstance(base_url, str): + base_url = URL(base_url) + if self.protocol: + scheme = { + "http": {True: "https", False: "http"}, + "websocket": {True: "wss", False: "ws"}, + }[self.protocol][base_url.is_secure] + else: + scheme = base_url.scheme + + netloc = self.host or base_url.netloc + path = base_url.path.rstrip("/") + str(self) + return URL(scheme=scheme, netloc=netloc, path=path) + + +class Secret: + """ + Holds a string value that should not be revealed in tracebacks etc. + You should cast the value to `str` at the point it is required. + """ + + def __init__(self, value: str): + self._value = value + + def __repr__(self) -> str: + class_name = self.__class__.__name__ + return f"{class_name}('**********')" + + def __str__(self) -> str: + return self._value + + def __bool__(self) -> bool: + return bool(self._value) + + +class CommaSeparatedStrings(Sequence): + def __init__(self, value: typing.Union[str, typing.Sequence[str]]): + if isinstance(value, str): + splitter = shlex(value, posix=True) + splitter.whitespace = "," + splitter.whitespace_split = True + self._items = [item.strip() for item in splitter] + else: + self._items = list(value) + + def __len__(self) -> int: + return len(self._items) + + def __getitem__(self, index: typing.Union[int, slice]) -> typing.Any: + return self._items[index] + + def __iter__(self) -> typing.Iterator[str]: + return iter(self._items) + + def __repr__(self) -> str: + class_name = self.__class__.__name__ + items = [item for item in self] + return f"{class_name}({items!r})" + + def __str__(self) -> str: + return ", ".join(repr(item) for item in self) + + +class ImmutableMultiDict(typing.Mapping[_KeyType, _CovariantValueType]): + _dict: typing.Dict[_KeyType, _CovariantValueType] + + def __init__( + self, + *args: typing.Union[ + "ImmutableMultiDict[_KeyType, _CovariantValueType]", + typing.Mapping[_KeyType, _CovariantValueType], + typing.Iterable[typing.Tuple[_KeyType, _CovariantValueType]], + ], + **kwargs: typing.Any, + ) -> None: + assert len(args) < 2, "Too many arguments." + + value: typing.Any = args[0] if args else [] + if kwargs: + value = ( + ImmutableMultiDict(value).multi_items() + + ImmutableMultiDict(kwargs).multi_items() # type: ignore[operator] + ) + + if not value: + _items: typing.List[typing.Tuple[typing.Any, typing.Any]] = [] + elif hasattr(value, "multi_items"): + value = typing.cast( + ImmutableMultiDict[_KeyType, _CovariantValueType], value + ) + _items = list(value.multi_items()) + elif hasattr(value, "items"): + value = typing.cast(typing.Mapping[_KeyType, _CovariantValueType], value) + _items = list(value.items()) + else: + value = typing.cast( + typing.List[typing.Tuple[typing.Any, typing.Any]], value + ) + _items = list(value) + + self._dict = {k: v for k, v in _items} + self._list = _items + + def getlist(self, key: typing.Any) -> typing.List[_CovariantValueType]: + return [item_value for item_key, item_value in self._list if item_key == key] + + def keys(self) -> typing.KeysView[_KeyType]: + return self._dict.keys() + + def values(self) -> typing.ValuesView[_CovariantValueType]: + return self._dict.values() + + def items(self) -> typing.ItemsView[_KeyType, _CovariantValueType]: + return self._dict.items() + + def multi_items(self) -> typing.List[typing.Tuple[_KeyType, _CovariantValueType]]: + return list(self._list) + + def __getitem__(self, key: _KeyType) -> _CovariantValueType: + return self._dict[key] + + def __contains__(self, key: typing.Any) -> bool: + return key in self._dict + + def __iter__(self) -> typing.Iterator[_KeyType]: + return iter(self.keys()) + + def __len__(self) -> int: + return len(self._dict) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, self.__class__): + return False + return sorted(self._list) == sorted(other._list) + + def __repr__(self) -> str: + class_name = self.__class__.__name__ + items = self.multi_items() + return f"{class_name}({items!r})" + + +class MultiDict(ImmutableMultiDict[typing.Any, typing.Any]): + def __setitem__(self, key: typing.Any, value: typing.Any) -> None: + self.setlist(key, [value]) + + def __delitem__(self, key: typing.Any) -> None: + self._list = [(k, v) for k, v in self._list if k != key] + del self._dict[key] + + def pop(self, key: typing.Any, default: typing.Any = None) -> typing.Any: + self._list = [(k, v) for k, v in self._list if k != key] + return self._dict.pop(key, default) + + def popitem(self) -> typing.Tuple: + key, value = self._dict.popitem() + self._list = [(k, v) for k, v in self._list if k != key] + return key, value + + def poplist(self, key: typing.Any) -> typing.List: + values = [v for k, v in self._list if k == key] + self.pop(key) + return values + + def clear(self) -> None: + self._dict.clear() + self._list.clear() + + def setdefault(self, key: typing.Any, default: typing.Any = None) -> typing.Any: + if key not in self: + self._dict[key] = default + self._list.append((key, default)) + + return self[key] + + def setlist(self, key: typing.Any, values: typing.List) -> None: + if not values: + self.pop(key, None) + else: + existing_items = [(k, v) for (k, v) in self._list if k != key] + self._list = existing_items + [(key, value) for value in values] + self._dict[key] = values[-1] + + def append(self, key: typing.Any, value: typing.Any) -> None: + self._list.append((key, value)) + self._dict[key] = value + + def update( + self, + *args: typing.Union[ + "MultiDict", + typing.Mapping, + typing.List[typing.Tuple[typing.Any, typing.Any]], + ], + **kwargs: typing.Any, + ) -> None: + value = MultiDict(*args, **kwargs) + existing_items = [(k, v) for (k, v) in self._list if k not in value.keys()] + self._list = existing_items + value.multi_items() + self._dict.update(value) + + +class QueryParams(ImmutableMultiDict[str, str]): + """ + An immutable multidict. + """ + + def __init__( + self, + *args: typing.Union[ + "ImmutableMultiDict", + typing.Mapping, + typing.List[typing.Tuple[typing.Any, typing.Any]], + str, + bytes, + ], + **kwargs: typing.Any, + ) -> None: + assert len(args) < 2, "Too many arguments." + + value = args[0] if args else [] + + if isinstance(value, str): + super().__init__(parse_qsl(value, keep_blank_values=True), **kwargs) + elif isinstance(value, bytes): + super().__init__( + parse_qsl(value.decode("latin-1"), keep_blank_values=True), **kwargs + ) + else: + super().__init__(*args, **kwargs) # type: ignore[arg-type] + self._list = [(str(k), str(v)) for k, v in self._list] + self._dict = {str(k): str(v) for k, v in self._dict.items()} + + def __str__(self) -> str: + return urlencode(self._list) + + def __repr__(self) -> str: + class_name = self.__class__.__name__ + query_string = str(self) + return f"{class_name}({query_string!r})" + + +class UploadFile: + """ + An uploaded file included as part of the request data. + """ + + def __init__( + self, + file: typing.BinaryIO, + *, + size: typing.Optional[int] = None, + filename: typing.Optional[str] = None, + headers: "typing.Optional[Headers]" = None, + ) -> None: + self.filename = filename + self.file = file + self.size = size + self.headers = headers or Headers() + + @property + def content_type(self) -> typing.Optional[str]: + return self.headers.get("content-type", None) + + @property + def _in_memory(self) -> bool: + # check for SpooledTemporaryFile._rolled + rolled_to_disk = getattr(self.file, "_rolled", True) + return not rolled_to_disk + + async def write(self, data: bytes) -> None: + if self.size is not None: + self.size += len(data) + + if self._in_memory: + self.file.write(data) + else: + await run_in_threadpool(self.file.write, data) + + async def read(self, size: int = -1) -> bytes: + if self._in_memory: + return self.file.read(size) + return await run_in_threadpool(self.file.read, size) + + async def seek(self, offset: int) -> None: + if self._in_memory: + self.file.seek(offset) + else: + await run_in_threadpool(self.file.seek, offset) + + async def close(self) -> None: + if self._in_memory: + self.file.close() + else: + await run_in_threadpool(self.file.close) + + +class FormData(ImmutableMultiDict[str, typing.Union[UploadFile, str]]): + """ + An immutable multidict, containing both file uploads and text input. + """ + + def __init__( + self, + *args: typing.Union[ + "FormData", + typing.Mapping[str, typing.Union[str, UploadFile]], + typing.List[typing.Tuple[str, typing.Union[str, UploadFile]]], + ], + **kwargs: typing.Union[str, UploadFile], + ) -> None: + super().__init__(*args, **kwargs) + + async def close(self) -> None: + for key, value in self.multi_items(): + if isinstance(value, UploadFile): + await value.close() + + +class Headers(typing.Mapping[str, str]): + """ + An immutable, case-insensitive multidict. + """ + + def __init__( + self, + headers: typing.Optional[typing.Mapping[str, str]] = None, + raw: typing.Optional[typing.List[typing.Tuple[bytes, bytes]]] = None, + scope: typing.Optional[typing.MutableMapping[str, typing.Any]] = None, + ) -> None: + self._list: typing.List[typing.Tuple[bytes, bytes]] = [] + if headers is not None: + assert raw is None, 'Cannot set both "headers" and "raw".' + assert scope is None, 'Cannot set both "headers" and "scope".' + self._list = [ + (key.lower().encode("latin-1"), value.encode("latin-1")) + for key, value in headers.items() + ] + elif raw is not None: + assert scope is None, 'Cannot set both "raw" and "scope".' + self._list = raw + elif scope is not None: + # scope["headers"] isn't necessarily a list + # it might be a tuple or other iterable + self._list = scope["headers"] = list(scope["headers"]) + + @property + def raw(self) -> typing.List[typing.Tuple[bytes, bytes]]: + return list(self._list) + + def keys(self) -> typing.List[str]: # type: ignore[override] + return [key.decode("latin-1") for key, value in self._list] + + def values(self) -> typing.List[str]: # type: ignore[override] + return [value.decode("latin-1") for key, value in self._list] + + def items(self) -> typing.List[typing.Tuple[str, str]]: # type: ignore[override] + return [ + (key.decode("latin-1"), value.decode("latin-1")) + for key, value in self._list + ] + + def getlist(self, key: str) -> typing.List[str]: + get_header_key = key.lower().encode("latin-1") + return [ + item_value.decode("latin-1") + for item_key, item_value in self._list + if item_key == get_header_key + ] + + def mutablecopy(self) -> "MutableHeaders": + return MutableHeaders(raw=self._list[:]) + + def __getitem__(self, key: str) -> str: + get_header_key = key.lower().encode("latin-1") + for header_key, header_value in self._list: + if header_key == get_header_key: + return header_value.decode("latin-1") + raise KeyError(key) + + def __contains__(self, key: typing.Any) -> bool: + get_header_key = key.lower().encode("latin-1") + for header_key, header_value in self._list: + if header_key == get_header_key: + return True + return False + + def __iter__(self) -> typing.Iterator[typing.Any]: + return iter(self.keys()) + + def __len__(self) -> int: + return len(self._list) + + def __eq__(self, other: typing.Any) -> bool: + if not isinstance(other, Headers): + return False + return sorted(self._list) == sorted(other._list) + + def __repr__(self) -> str: + class_name = self.__class__.__name__ + as_dict = dict(self.items()) + if len(as_dict) == len(self): + return f"{class_name}({as_dict!r})" + return f"{class_name}(raw={self.raw!r})" + + +class MutableHeaders(Headers): + def __setitem__(self, key: str, value: str) -> None: + """ + Set the header `key` to `value`, removing any duplicate entries. + Retains insertion order. + """ + set_key = key.lower().encode("latin-1") + set_value = value.encode("latin-1") + + found_indexes: "typing.List[int]" = [] + for idx, (item_key, item_value) in enumerate(self._list): + if item_key == set_key: + found_indexes.append(idx) + + for idx in reversed(found_indexes[1:]): + del self._list[idx] + + if found_indexes: + idx = found_indexes[0] + self._list[idx] = (set_key, set_value) + else: + self._list.append((set_key, set_value)) + + def __delitem__(self, key: str) -> None: + """ + Remove the header `key`. + """ + del_key = key.lower().encode("latin-1") + + pop_indexes: "typing.List[int]" = [] + for idx, (item_key, item_value) in enumerate(self._list): + if item_key == del_key: + pop_indexes.append(idx) + + for idx in reversed(pop_indexes): + del self._list[idx] + + def __ior__(self, other: typing.Mapping[str, str]) -> "MutableHeaders": + if not isinstance(other, typing.Mapping): + raise TypeError(f"Expected a mapping but got {other.__class__.__name__}") + self.update(other) + return self + + def __or__(self, other: typing.Mapping[str, str]) -> "MutableHeaders": + if not isinstance(other, typing.Mapping): + raise TypeError(f"Expected a mapping but got {other.__class__.__name__}") + new = self.mutablecopy() + new.update(other) + return new + + @property + def raw(self) -> typing.List[typing.Tuple[bytes, bytes]]: + return self._list + + def setdefault(self, key: str, value: str) -> str: + """ + If the header `key` does not exist, then set it to `value`. + Returns the header value. + """ + set_key = key.lower().encode("latin-1") + set_value = value.encode("latin-1") + + for idx, (item_key, item_value) in enumerate(self._list): + if item_key == set_key: + return item_value.decode("latin-1") + self._list.append((set_key, set_value)) + return value + + def update(self, other: typing.Mapping[str, str]) -> None: + for key, val in other.items(): + self[key] = val + + def append(self, key: str, value: str) -> None: + """ + Append a header, preserving any duplicate entries. + """ + append_key = key.lower().encode("latin-1") + append_value = value.encode("latin-1") + self._list.append((append_key, append_value)) + + def add_vary_header(self, vary: str) -> None: + existing = self.get("vary") + if existing is not None: + vary = ", ".join([existing, vary]) + self["vary"] = vary + + +class State: + """ + An object that can be used to store arbitrary state. + + Used for `request.state` and `app.state`. + """ + + _state: typing.Dict[str, typing.Any] + + def __init__(self, state: typing.Optional[typing.Dict[str, typing.Any]] = None): + if state is None: + state = {} + super().__setattr__("_state", state) + + def __setattr__(self, key: typing.Any, value: typing.Any) -> None: + self._state[key] = value + + def __getattr__(self, key: typing.Any) -> typing.Any: + try: + return self._state[key] + except KeyError: + message = "'{}' object has no attribute '{}'" + raise AttributeError(message.format(self.__class__.__name__, key)) + + def __delattr__(self, key: typing.Any) -> None: + del self._state[key] diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/endpoints.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/endpoints.py new file mode 100644 index 0000000..95cd764 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/endpoints.py @@ -0,0 +1,130 @@ +import json +import typing + +from starlette import status +from starlette._utils import is_async_callable +from starlette.concurrency import run_in_threadpool +from starlette.exceptions import HTTPException +from starlette.requests import Request +from starlette.responses import PlainTextResponse, Response +from starlette.types import Message, Receive, Scope, Send +from starlette.websockets import WebSocket + + +class HTTPEndpoint: + def __init__(self, scope: Scope, receive: Receive, send: Send) -> None: + assert scope["type"] == "http" + self.scope = scope + self.receive = receive + self.send = send + self._allowed_methods = [ + method + for method in ("GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS") + if getattr(self, method.lower(), None) is not None + ] + + def __await__(self) -> typing.Generator: + return self.dispatch().__await__() + + async def dispatch(self) -> None: + request = Request(self.scope, receive=self.receive) + handler_name = ( + "get" + if request.method == "HEAD" and not hasattr(self, "head") + else request.method.lower() + ) + + handler: typing.Callable[[Request], typing.Any] = getattr( + self, handler_name, self.method_not_allowed + ) + is_async = is_async_callable(handler) + if is_async: + response = await handler(request) + else: + response = await run_in_threadpool(handler, request) + await response(self.scope, self.receive, self.send) + + async def method_not_allowed(self, request: Request) -> Response: + # If we're running inside a starlette application then raise an + # exception, so that the configurable exception handler can deal with + # returning the response. For plain ASGI apps, just return the response. + headers = {"Allow": ", ".join(self._allowed_methods)} + if "app" in self.scope: + raise HTTPException(status_code=405, headers=headers) + return PlainTextResponse("Method Not Allowed", status_code=405, headers=headers) + + +class WebSocketEndpoint: + encoding: typing.Optional[str] = None # May be "text", "bytes", or "json". + + def __init__(self, scope: Scope, receive: Receive, send: Send) -> None: + assert scope["type"] == "websocket" + self.scope = scope + self.receive = receive + self.send = send + + def __await__(self) -> typing.Generator: + return self.dispatch().__await__() + + async def dispatch(self) -> None: + websocket = WebSocket(self.scope, receive=self.receive, send=self.send) + await self.on_connect(websocket) + + close_code = status.WS_1000_NORMAL_CLOSURE + + try: + while True: + message = await websocket.receive() + if message["type"] == "websocket.receive": + data = await self.decode(websocket, message) + await self.on_receive(websocket, data) + elif message["type"] == "websocket.disconnect": + close_code = int( + message.get("code") or status.WS_1000_NORMAL_CLOSURE + ) + break + except Exception as exc: + close_code = status.WS_1011_INTERNAL_ERROR + raise exc + finally: + await self.on_disconnect(websocket, close_code) + + async def decode(self, websocket: WebSocket, message: Message) -> typing.Any: + if self.encoding == "text": + if "text" not in message: + await websocket.close(code=status.WS_1003_UNSUPPORTED_DATA) + raise RuntimeError("Expected text websocket messages, but got bytes") + return message["text"] + + elif self.encoding == "bytes": + if "bytes" not in message: + await websocket.close(code=status.WS_1003_UNSUPPORTED_DATA) + raise RuntimeError("Expected bytes websocket messages, but got text") + return message["bytes"] + + elif self.encoding == "json": + if message.get("text") is not None: + text = message["text"] + else: + text = message["bytes"].decode("utf-8") + + try: + return json.loads(text) + except json.decoder.JSONDecodeError: + await websocket.close(code=status.WS_1003_UNSUPPORTED_DATA) + raise RuntimeError("Malformed JSON data received.") + + assert ( + self.encoding is None + ), f"Unsupported 'encoding' attribute {self.encoding}" + return message["text"] if message.get("text") else message["bytes"] + + async def on_connect(self, websocket: WebSocket) -> None: + """Override to handle an incoming websocket connection""" + await websocket.accept() + + async def on_receive(self, websocket: WebSocket, data: typing.Any) -> None: + """Override to handle an incoming websocket message""" + + async def on_disconnect(self, websocket: WebSocket, close_code: int) -> None: + """Override to handle a disconnecting websocket""" diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/exceptions.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/exceptions.py new file mode 100644 index 0000000..87da735 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/exceptions.py @@ -0,0 +1,54 @@ +import http +import typing +import warnings + +__all__ = ("HTTPException", "WebSocketException") + + +class HTTPException(Exception): + def __init__( + self, + status_code: int, + detail: typing.Optional[str] = None, + headers: typing.Optional[dict] = None, + ) -> None: + if detail is None: + detail = http.HTTPStatus(status_code).phrase + self.status_code = status_code + self.detail = detail + self.headers = headers + + def __repr__(self) -> str: + class_name = self.__class__.__name__ + return f"{class_name}(status_code={self.status_code!r}, detail={self.detail!r})" + + +class WebSocketException(Exception): + def __init__(self, code: int, reason: typing.Optional[str] = None) -> None: + self.code = code + self.reason = reason or "" + + def __repr__(self) -> str: + class_name = self.__class__.__name__ + return f"{class_name}(code={self.code!r}, reason={self.reason!r})" + + +__deprecated__ = "ExceptionMiddleware" + + +def __getattr__(name: str) -> typing.Any: # pragma: no cover + if name == __deprecated__: + from starlette.middleware.exceptions import ExceptionMiddleware + + warnings.warn( + f"{__deprecated__} is deprecated on `starlette.exceptions`. " + f"Import it from `starlette.middleware.exceptions` instead.", + category=DeprecationWarning, + stacklevel=3, + ) + return ExceptionMiddleware + raise AttributeError(f"module '{__name__}' has no attribute '{name}'") + + +def __dir__() -> typing.List[str]: + return sorted(list(__all__) + [__deprecated__]) # pragma: no cover diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/formparsers.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/formparsers.py new file mode 100644 index 0000000..eb3cba5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/formparsers.py @@ -0,0 +1,276 @@ +import typing +from dataclasses import dataclass, field +from enum import Enum +from tempfile import SpooledTemporaryFile +from urllib.parse import unquote_plus + +from starlette.datastructures import FormData, Headers, UploadFile + +try: + import multipart + from multipart.multipart import parse_options_header +except ModuleNotFoundError: # pragma: nocover + parse_options_header = None + multipart = None + + +class FormMessage(Enum): + FIELD_START = 1 + FIELD_NAME = 2 + FIELD_DATA = 3 + FIELD_END = 4 + END = 5 + + +@dataclass +class MultipartPart: + content_disposition: typing.Optional[bytes] = None + field_name: str = "" + data: bytes = b"" + file: typing.Optional[UploadFile] = None + item_headers: typing.List[typing.Tuple[bytes, bytes]] = field(default_factory=list) + + +def _user_safe_decode(src: bytes, codec: str) -> str: + try: + return src.decode(codec) + except (UnicodeDecodeError, LookupError): + return src.decode("latin-1") + + +class MultiPartException(Exception): + def __init__(self, message: str) -> None: + self.message = message + + +class FormParser: + def __init__( + self, headers: Headers, stream: typing.AsyncGenerator[bytes, None] + ) -> None: + assert ( + multipart is not None + ), "The `python-multipart` library must be installed to use form parsing." + self.headers = headers + self.stream = stream + self.messages: typing.List[typing.Tuple[FormMessage, bytes]] = [] + + def on_field_start(self) -> None: + message = (FormMessage.FIELD_START, b"") + self.messages.append(message) + + def on_field_name(self, data: bytes, start: int, end: int) -> None: + message = (FormMessage.FIELD_NAME, data[start:end]) + self.messages.append(message) + + def on_field_data(self, data: bytes, start: int, end: int) -> None: + message = (FormMessage.FIELD_DATA, data[start:end]) + self.messages.append(message) + + def on_field_end(self) -> None: + message = (FormMessage.FIELD_END, b"") + self.messages.append(message) + + def on_end(self) -> None: + message = (FormMessage.END, b"") + self.messages.append(message) + + async def parse(self) -> FormData: + # Callbacks dictionary. + callbacks = { + "on_field_start": self.on_field_start, + "on_field_name": self.on_field_name, + "on_field_data": self.on_field_data, + "on_field_end": self.on_field_end, + "on_end": self.on_end, + } + + # Create the parser. + parser = multipart.QuerystringParser(callbacks) + field_name = b"" + field_value = b"" + + items: typing.List[typing.Tuple[str, typing.Union[str, UploadFile]]] = [] + + # Feed the parser with data from the request. + async for chunk in self.stream: + if chunk: + parser.write(chunk) + else: + parser.finalize() + messages = list(self.messages) + self.messages.clear() + for message_type, message_bytes in messages: + if message_type == FormMessage.FIELD_START: + field_name = b"" + field_value = b"" + elif message_type == FormMessage.FIELD_NAME: + field_name += message_bytes + elif message_type == FormMessage.FIELD_DATA: + field_value += message_bytes + elif message_type == FormMessage.FIELD_END: + name = unquote_plus(field_name.decode("latin-1")) + value = unquote_plus(field_value.decode("latin-1")) + items.append((name, value)) + + return FormData(items) + + +class MultiPartParser: + max_file_size = 1024 * 1024 + + def __init__( + self, + headers: Headers, + stream: typing.AsyncGenerator[bytes, None], + *, + max_files: typing.Union[int, float] = 1000, + max_fields: typing.Union[int, float] = 1000, + ) -> None: + assert ( + multipart is not None + ), "The `python-multipart` library must be installed to use form parsing." + self.headers = headers + self.stream = stream + self.max_files = max_files + self.max_fields = max_fields + self.items: typing.List[typing.Tuple[str, typing.Union[str, UploadFile]]] = [] + self._current_files = 0 + self._current_fields = 0 + self._current_partial_header_name: bytes = b"" + self._current_partial_header_value: bytes = b"" + self._current_part = MultipartPart() + self._charset = "" + self._file_parts_to_write: typing.List[typing.Tuple[MultipartPart, bytes]] = [] + self._file_parts_to_finish: typing.List[MultipartPart] = [] + self._files_to_close_on_error: typing.List[SpooledTemporaryFile] = [] + + def on_part_begin(self) -> None: + self._current_part = MultipartPart() + + def on_part_data(self, data: bytes, start: int, end: int) -> None: + message_bytes = data[start:end] + if self._current_part.file is None: + self._current_part.data += message_bytes + else: + self._file_parts_to_write.append((self._current_part, message_bytes)) + + def on_part_end(self) -> None: + if self._current_part.file is None: + self.items.append( + ( + self._current_part.field_name, + _user_safe_decode(self._current_part.data, self._charset), + ) + ) + else: + self._file_parts_to_finish.append(self._current_part) + # The file can be added to the items right now even though it's not + # finished yet, because it will be finished in the `parse()` method, before + # self.items is used in the return value. + self.items.append((self._current_part.field_name, self._current_part.file)) + + def on_header_field(self, data: bytes, start: int, end: int) -> None: + self._current_partial_header_name += data[start:end] + + def on_header_value(self, data: bytes, start: int, end: int) -> None: + self._current_partial_header_value += data[start:end] + + def on_header_end(self) -> None: + field = self._current_partial_header_name.lower() + if field == b"content-disposition": + self._current_part.content_disposition = self._current_partial_header_value + self._current_part.item_headers.append( + (field, self._current_partial_header_value) + ) + self._current_partial_header_name = b"" + self._current_partial_header_value = b"" + + def on_headers_finished(self) -> None: + disposition, options = parse_options_header( + self._current_part.content_disposition + ) + try: + self._current_part.field_name = _user_safe_decode( + options[b"name"], self._charset + ) + except KeyError: + raise MultiPartException( + 'The Content-Disposition header field "name" must be ' "provided." + ) + if b"filename" in options: + self._current_files += 1 + if self._current_files > self.max_files: + raise MultiPartException( + f"Too many files. Maximum number of files is {self.max_files}." + ) + filename = _user_safe_decode(options[b"filename"], self._charset) + tempfile = SpooledTemporaryFile(max_size=self.max_file_size) + self._files_to_close_on_error.append(tempfile) + self._current_part.file = UploadFile( + file=tempfile, # type: ignore[arg-type] + size=0, + filename=filename, + headers=Headers(raw=self._current_part.item_headers), + ) + else: + self._current_fields += 1 + if self._current_fields > self.max_fields: + raise MultiPartException( + f"Too many fields. Maximum number of fields is {self.max_fields}." + ) + self._current_part.file = None + + def on_end(self) -> None: + pass + + async def parse(self) -> FormData: + # Parse the Content-Type header to get the multipart boundary. + _, params = parse_options_header(self.headers["Content-Type"]) + charset = params.get(b"charset", "utf-8") + if type(charset) == bytes: + charset = charset.decode("latin-1") + self._charset = charset + try: + boundary = params[b"boundary"] + except KeyError: + raise MultiPartException("Missing boundary in multipart.") + + # Callbacks dictionary. + callbacks = { + "on_part_begin": self.on_part_begin, + "on_part_data": self.on_part_data, + "on_part_end": self.on_part_end, + "on_header_field": self.on_header_field, + "on_header_value": self.on_header_value, + "on_header_end": self.on_header_end, + "on_headers_finished": self.on_headers_finished, + "on_end": self.on_end, + } + + # Create the parser. + parser = multipart.MultipartParser(boundary, callbacks) + try: + # Feed the parser with data from the request. + async for chunk in self.stream: + parser.write(chunk) + # Write file data, it needs to use await with the UploadFile methods + # that call the corresponding file methods *in a threadpool*, + # otherwise, if they were called directly in the callback methods above + # (regular, non-async functions), that would block the event loop in + # the main thread. + for part, data in self._file_parts_to_write: + assert part.file # for type checkers + await part.file.write(data) + for part in self._file_parts_to_finish: + assert part.file # for type checkers + await part.file.seek(0) + self._file_parts_to_write.clear() + self._file_parts_to_finish.clear() + except MultiPartException as exc: + # Close all the files if there was an error. + for file in self._files_to_close_on_error: + file.close() + raise exc + + parser.finalize() + return FormData(self.items) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/__init__.py new file mode 100644 index 0000000..5ac5b96 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/__init__.py @@ -0,0 +1,17 @@ +import typing + + +class Middleware: + def __init__(self, cls: type, **options: typing.Any) -> None: + self.cls = cls + self.options = options + + def __iter__(self) -> typing.Iterator: + as_tuple = (self.cls, self.options) + return iter(as_tuple) + + def __repr__(self) -> str: + class_name = self.__class__.__name__ + option_strings = [f"{key}={value!r}" for key, value in self.options.items()] + args_repr = ", ".join([self.cls.__name__] + option_strings) + return f"{class_name}({args_repr})" diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/authentication.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/authentication.py new file mode 100644 index 0000000..76e4a24 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/authentication.py @@ -0,0 +1,52 @@ +import typing + +from starlette.authentication import ( + AuthCredentials, + AuthenticationBackend, + AuthenticationError, + UnauthenticatedUser, +) +from starlette.requests import HTTPConnection +from starlette.responses import PlainTextResponse, Response +from starlette.types import ASGIApp, Receive, Scope, Send + + +class AuthenticationMiddleware: + def __init__( + self, + app: ASGIApp, + backend: AuthenticationBackend, + on_error: typing.Optional[ + typing.Callable[[HTTPConnection, AuthenticationError], Response] + ] = None, + ) -> None: + self.app = app + self.backend = backend + self.on_error: typing.Callable[ + [HTTPConnection, AuthenticationError], Response + ] = (on_error if on_error is not None else self.default_on_error) + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if scope["type"] not in ["http", "websocket"]: + await self.app(scope, receive, send) + return + + conn = HTTPConnection(scope) + try: + auth_result = await self.backend.authenticate(conn) + except AuthenticationError as exc: + response = self.on_error(conn, exc) + if scope["type"] == "websocket": + await send({"type": "websocket.close", "code": 1000}) + else: + await response(scope, receive, send) + return + + if auth_result is None: + auth_result = AuthCredentials(), UnauthenticatedUser() + scope["auth"], scope["user"] = auth_result + await self.app(scope, receive, send) + + @staticmethod + def default_on_error(conn: HTTPConnection, exc: Exception) -> Response: + return PlainTextResponse(str(exc), status_code=400) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/base.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/base.py new file mode 100644 index 0000000..c988020 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/base.py @@ -0,0 +1,134 @@ +import typing + +import anyio + +from starlette.background import BackgroundTask +from starlette.requests import Request +from starlette.responses import ContentStream, Response, StreamingResponse +from starlette.types import ASGIApp, Message, Receive, Scope, Send + +RequestResponseEndpoint = typing.Callable[[Request], typing.Awaitable[Response]] +DispatchFunction = typing.Callable[ + [Request, RequestResponseEndpoint], typing.Awaitable[Response] +] +T = typing.TypeVar("T") + + +class BaseHTTPMiddleware: + def __init__( + self, app: ASGIApp, dispatch: typing.Optional[DispatchFunction] = None + ) -> None: + self.app = app + self.dispatch_func = self.dispatch if dispatch is None else dispatch + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if scope["type"] != "http": + await self.app(scope, receive, send) + return + + response_sent = anyio.Event() + + async def call_next(request: Request) -> Response: + app_exc: typing.Optional[Exception] = None + send_stream, recv_stream = anyio.create_memory_object_stream() + + async def receive_or_disconnect() -> Message: + if response_sent.is_set(): + return {"type": "http.disconnect"} + + async with anyio.create_task_group() as task_group: + + async def wrap(func: typing.Callable[[], typing.Awaitable[T]]) -> T: + result = await func() + task_group.cancel_scope.cancel() + return result + + task_group.start_soon(wrap, response_sent.wait) + message = await wrap(request.receive) + + if response_sent.is_set(): + return {"type": "http.disconnect"} + + return message + + async def close_recv_stream_on_response_sent() -> None: + await response_sent.wait() + recv_stream.close() + + async def send_no_error(message: Message) -> None: + try: + await send_stream.send(message) + except anyio.BrokenResourceError: + # recv_stream has been closed, i.e. response_sent has been set. + return + + async def coro() -> None: + nonlocal app_exc + + async with send_stream: + try: + await self.app(scope, receive_or_disconnect, send_no_error) + except Exception as exc: + app_exc = exc + + task_group.start_soon(close_recv_stream_on_response_sent) + task_group.start_soon(coro) + + try: + message = await recv_stream.receive() + info = message.get("info", None) + if message["type"] == "http.response.debug" and info is not None: + message = await recv_stream.receive() + except anyio.EndOfStream: + if app_exc is not None: + raise app_exc + raise RuntimeError("No response returned.") + + assert message["type"] == "http.response.start" + + async def body_stream() -> typing.AsyncGenerator[bytes, None]: + async with recv_stream: + async for message in recv_stream: + assert message["type"] == "http.response.body" + body = message.get("body", b"") + if body: + yield body + + if app_exc is not None: + raise app_exc + + response = _StreamingResponse( + status_code=message["status"], content=body_stream(), info=info + ) + response.raw_headers = message["headers"] + return response + + async with anyio.create_task_group() as task_group: + request = Request(scope, receive=receive) + response = await self.dispatch_func(request, call_next) + await response(scope, receive, send) + response_sent.set() + + async def dispatch( + self, request: Request, call_next: RequestResponseEndpoint + ) -> Response: + raise NotImplementedError() # pragma: no cover + + +class _StreamingResponse(StreamingResponse): + def __init__( + self, + content: ContentStream, + status_code: int = 200, + headers: typing.Optional[typing.Mapping[str, str]] = None, + media_type: typing.Optional[str] = None, + background: typing.Optional[BackgroundTask] = None, + info: typing.Optional[typing.Mapping[str, typing.Any]] = None, + ) -> None: + self._info = info + super().__init__(content, status_code, headers, media_type, background) + + async def stream_response(self, send: Send) -> None: + if self._info: + await send({"type": "http.response.debug", "info": self._info}) + return await super().stream_response(send) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/cors.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/cors.py new file mode 100644 index 0000000..5c9bfa6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/cors.py @@ -0,0 +1,176 @@ +import functools +import re +import typing + +from starlette.datastructures import Headers, MutableHeaders +from starlette.responses import PlainTextResponse, Response +from starlette.types import ASGIApp, Message, Receive, Scope, Send + +ALL_METHODS = ("DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT") +SAFELISTED_HEADERS = {"Accept", "Accept-Language", "Content-Language", "Content-Type"} + + +class CORSMiddleware: + def __init__( + self, + app: ASGIApp, + allow_origins: typing.Sequence[str] = (), + allow_methods: typing.Sequence[str] = ("GET",), + allow_headers: typing.Sequence[str] = (), + allow_credentials: bool = False, + allow_origin_regex: typing.Optional[str] = None, + expose_headers: typing.Sequence[str] = (), + max_age: int = 600, + ) -> None: + if "*" in allow_methods: + allow_methods = ALL_METHODS + + compiled_allow_origin_regex = None + if allow_origin_regex is not None: + compiled_allow_origin_regex = re.compile(allow_origin_regex) + + allow_all_origins = "*" in allow_origins + allow_all_headers = "*" in allow_headers + preflight_explicit_allow_origin = not allow_all_origins or allow_credentials + + simple_headers = {} + if allow_all_origins: + simple_headers["Access-Control-Allow-Origin"] = "*" + if allow_credentials: + simple_headers["Access-Control-Allow-Credentials"] = "true" + if expose_headers: + simple_headers["Access-Control-Expose-Headers"] = ", ".join(expose_headers) + + preflight_headers = {} + if preflight_explicit_allow_origin: + # The origin value will be set in preflight_response() if it is allowed. + preflight_headers["Vary"] = "Origin" + else: + preflight_headers["Access-Control-Allow-Origin"] = "*" + preflight_headers.update( + { + "Access-Control-Allow-Methods": ", ".join(allow_methods), + "Access-Control-Max-Age": str(max_age), + } + ) + allow_headers = sorted(SAFELISTED_HEADERS | set(allow_headers)) + if allow_headers and not allow_all_headers: + preflight_headers["Access-Control-Allow-Headers"] = ", ".join(allow_headers) + if allow_credentials: + preflight_headers["Access-Control-Allow-Credentials"] = "true" + + self.app = app + self.allow_origins = allow_origins + self.allow_methods = allow_methods + self.allow_headers = [h.lower() for h in allow_headers] + self.allow_all_origins = allow_all_origins + self.allow_all_headers = allow_all_headers + self.preflight_explicit_allow_origin = preflight_explicit_allow_origin + self.allow_origin_regex = compiled_allow_origin_regex + self.simple_headers = simple_headers + self.preflight_headers = preflight_headers + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if scope["type"] != "http": # pragma: no cover + await self.app(scope, receive, send) + return + + method = scope["method"] + headers = Headers(scope=scope) + origin = headers.get("origin") + + if origin is None: + await self.app(scope, receive, send) + return + + if method == "OPTIONS" and "access-control-request-method" in headers: + response = self.preflight_response(request_headers=headers) + await response(scope, receive, send) + return + + await self.simple_response(scope, receive, send, request_headers=headers) + + def is_allowed_origin(self, origin: str) -> bool: + if self.allow_all_origins: + return True + + if self.allow_origin_regex is not None and self.allow_origin_regex.fullmatch( + origin + ): + return True + + return origin in self.allow_origins + + def preflight_response(self, request_headers: Headers) -> Response: + requested_origin = request_headers["origin"] + requested_method = request_headers["access-control-request-method"] + requested_headers = request_headers.get("access-control-request-headers") + + headers = dict(self.preflight_headers) + failures = [] + + if self.is_allowed_origin(origin=requested_origin): + if self.preflight_explicit_allow_origin: + # The "else" case is already accounted for in self.preflight_headers + # and the value would be "*". + headers["Access-Control-Allow-Origin"] = requested_origin + else: + failures.append("origin") + + if requested_method not in self.allow_methods: + failures.append("method") + + # If we allow all headers, then we have to mirror back any requested + # headers in the response. + if self.allow_all_headers and requested_headers is not None: + headers["Access-Control-Allow-Headers"] = requested_headers + elif requested_headers is not None: + for header in [h.lower() for h in requested_headers.split(",")]: + if header.strip() not in self.allow_headers: + failures.append("headers") + break + + # We don't strictly need to use 400 responses here, since its up to + # the browser to enforce the CORS policy, but its more informative + # if we do. + if failures: + failure_text = "Disallowed CORS " + ", ".join(failures) + return PlainTextResponse(failure_text, status_code=400, headers=headers) + + return PlainTextResponse("OK", status_code=200, headers=headers) + + async def simple_response( + self, scope: Scope, receive: Receive, send: Send, request_headers: Headers + ) -> None: + send = functools.partial(self.send, send=send, request_headers=request_headers) + await self.app(scope, receive, send) + + async def send( + self, message: Message, send: Send, request_headers: Headers + ) -> None: + if message["type"] != "http.response.start": + await send(message) + return + + message.setdefault("headers", []) + headers = MutableHeaders(scope=message) + headers.update(self.simple_headers) + origin = request_headers["Origin"] + has_cookie = "cookie" in request_headers + + # If request includes any cookie headers, then we must respond + # with the specific origin instead of '*'. + if self.allow_all_origins and has_cookie: + self.allow_explicit_origin(headers, origin) + + # If we only allow specific origins, then we have to mirror back + # the Origin header in the response. + elif not self.allow_all_origins and self.is_allowed_origin(origin=origin): + self.allow_explicit_origin(headers, origin) + + await send(message) + + @staticmethod + def allow_explicit_origin(headers: MutableHeaders, origin: str) -> None: + headers["Access-Control-Allow-Origin"] = origin + headers.add_vary_header("Origin") diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/errors.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/errors.py new file mode 100644 index 0000000..b9d9c69 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/errors.py @@ -0,0 +1,256 @@ +import html +import inspect +import traceback +import typing + +from starlette._utils import is_async_callable +from starlette.concurrency import run_in_threadpool +from starlette.requests import Request +from starlette.responses import HTMLResponse, PlainTextResponse, Response +from starlette.types import ASGIApp, Message, Receive, Scope, Send + +STYLES = """ +p { + color: #211c1c; +} +.traceback-container { + border: 1px solid #038BB8; +} +.traceback-title { + background-color: #038BB8; + color: lemonchiffon; + padding: 12px; + font-size: 20px; + margin-top: 0px; +} +.frame-line { + padding-left: 10px; + font-family: monospace; +} +.frame-filename { + font-family: monospace; +} +.center-line { + background-color: #038BB8; + color: #f9f6e1; + padding: 5px 0px 5px 5px; +} +.lineno { + margin-right: 5px; +} +.frame-title { + font-weight: unset; + padding: 10px 10px 10px 10px; + background-color: #E4F4FD; + margin-right: 10px; + color: #191f21; + font-size: 17px; + border: 1px solid #c7dce8; +} +.collapse-btn { + float: right; + padding: 0px 5px 1px 5px; + border: solid 1px #96aebb; + cursor: pointer; +} +.collapsed { + display: none; +} +.source-code { + font-family: courier; + font-size: small; + padding-bottom: 10px; +} +""" + +JS = """ + +""" + +TEMPLATE = """ + + + + Starlette Debugger + + +

    500 Server Error

    +

    {error}

    +
    +

    Traceback

    +
    {exc_html}
    +
    + {js} + + +""" + +FRAME_TEMPLATE = """ +
    +

    File {frame_filename}, + line {frame_lineno}, + in {frame_name} + {collapse_button} +

    +
    {code_context}
    +
    +""" # noqa: E501 + +LINE = """ +

    +{lineno}. {line}

    +""" + +CENTER_LINE = """ +

    +{lineno}. {line}

    +""" + + +class ServerErrorMiddleware: + """ + Handles returning 500 responses when a server error occurs. + + If 'debug' is set, then traceback responses will be returned, + otherwise the designated 'handler' will be called. + + This middleware class should generally be used to wrap *everything* + else up, so that unhandled exceptions anywhere in the stack + always result in an appropriate 500 response. + """ + + def __init__( + self, + app: ASGIApp, + handler: typing.Optional[typing.Callable] = None, + debug: bool = False, + ) -> None: + self.app = app + self.handler = handler + self.debug = debug + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if scope["type"] != "http": + await self.app(scope, receive, send) + return + + response_started = False + + async def _send(message: Message) -> None: + nonlocal response_started, send + + if message["type"] == "http.response.start": + response_started = True + await send(message) + + try: + await self.app(scope, receive, _send) + except Exception as exc: + request = Request(scope) + if self.debug: + # In debug mode, return traceback responses. + response = self.debug_response(request, exc) + elif self.handler is None: + # Use our default 500 error handler. + response = self.error_response(request, exc) + else: + # Use an installed 500 error handler. + if is_async_callable(self.handler): + response = await self.handler(request, exc) + else: + response = await run_in_threadpool(self.handler, request, exc) + + if not response_started: + await response(scope, receive, send) + + # We always continue to raise the exception. + # This allows servers to log the error, or allows test clients + # to optionally raise the error within the test case. + raise exc + + def format_line( + self, index: int, line: str, frame_lineno: int, frame_index: int + ) -> str: + values = { + # HTML escape - line could contain < or > + "line": html.escape(line).replace(" ", " "), + "lineno": (frame_lineno - frame_index) + index, + } + + if index != frame_index: + return LINE.format(**values) + return CENTER_LINE.format(**values) + + def generate_frame_html(self, frame: inspect.FrameInfo, is_collapsed: bool) -> str: + code_context = "".join( + self.format_line( + index, line, frame.lineno, frame.index # type: ignore[arg-type] + ) + for index, line in enumerate(frame.code_context or []) + ) + + values = { + # HTML escape - filename could contain < or >, especially if it's a virtual + # file e.g. in the REPL + "frame_filename": html.escape(frame.filename), + "frame_lineno": frame.lineno, + # HTML escape - if you try very hard it's possible to name a function with < + # or > + "frame_name": html.escape(frame.function), + "code_context": code_context, + "collapsed": "collapsed" if is_collapsed else "", + "collapse_button": "+" if is_collapsed else "‒", + } + return FRAME_TEMPLATE.format(**values) + + def generate_html(self, exc: Exception, limit: int = 7) -> str: + traceback_obj = traceback.TracebackException.from_exception( + exc, capture_locals=True + ) + + exc_html = "" + is_collapsed = False + exc_traceback = exc.__traceback__ + if exc_traceback is not None: + frames = inspect.getinnerframes(exc_traceback, limit) + for frame in reversed(frames): + exc_html += self.generate_frame_html(frame, is_collapsed) + is_collapsed = True + + # escape error class and text + error = ( + f"{html.escape(traceback_obj.exc_type.__name__)}: " + f"{html.escape(str(traceback_obj))}" + ) + + return TEMPLATE.format(styles=STYLES, js=JS, error=error, exc_html=exc_html) + + def generate_plain_text(self, exc: Exception) -> str: + return "".join(traceback.format_exception(type(exc), exc, exc.__traceback__)) + + def debug_response(self, request: Request, exc: Exception) -> Response: + accept = request.headers.get("accept", "") + + if "text/html" in accept: + content = self.generate_html(exc) + return HTMLResponse(content, status_code=500) + content = self.generate_plain_text(exc) + return PlainTextResponse(content, status_code=500) + + def error_response(self, request: Request, exc: Exception) -> Response: + return PlainTextResponse("Internal Server Error", status_code=500) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/exceptions.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/exceptions.py new file mode 100644 index 0000000..cd72941 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/exceptions.py @@ -0,0 +1,109 @@ +import typing + +from starlette._utils import is_async_callable +from starlette.concurrency import run_in_threadpool +from starlette.exceptions import HTTPException, WebSocketException +from starlette.requests import Request +from starlette.responses import PlainTextResponse, Response +from starlette.types import ASGIApp, Message, Receive, Scope, Send +from starlette.websockets import WebSocket + + +class ExceptionMiddleware: + def __init__( + self, + app: ASGIApp, + handlers: typing.Optional[ + typing.Mapping[typing.Any, typing.Callable[[Request, Exception], Response]] + ] = None, + debug: bool = False, + ) -> None: + self.app = app + self.debug = debug # TODO: We ought to handle 404 cases if debug is set. + self._status_handlers: typing.Dict[int, typing.Callable] = {} + self._exception_handlers: typing.Dict[ + typing.Type[Exception], typing.Callable + ] = { + HTTPException: self.http_exception, + WebSocketException: self.websocket_exception, + } + if handlers is not None: + for key, value in handlers.items(): + self.add_exception_handler(key, value) + + def add_exception_handler( + self, + exc_class_or_status_code: typing.Union[int, typing.Type[Exception]], + handler: typing.Callable[[Request, Exception], Response], + ) -> None: + if isinstance(exc_class_or_status_code, int): + self._status_handlers[exc_class_or_status_code] = handler + else: + assert issubclass(exc_class_or_status_code, Exception) + self._exception_handlers[exc_class_or_status_code] = handler + + def _lookup_exception_handler( + self, exc: Exception + ) -> typing.Optional[typing.Callable]: + for cls in type(exc).__mro__: + if cls in self._exception_handlers: + return self._exception_handlers[cls] + return None + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if scope["type"] not in ("http", "websocket"): + await self.app(scope, receive, send) + return + + response_started = False + + async def sender(message: Message) -> None: + nonlocal response_started + + if message["type"] == "http.response.start": + response_started = True + await send(message) + + try: + await self.app(scope, receive, sender) + except Exception as exc: + handler = None + + if isinstance(exc, HTTPException): + handler = self._status_handlers.get(exc.status_code) + + if handler is None: + handler = self._lookup_exception_handler(exc) + + if handler is None: + raise exc + + if response_started: + msg = "Caught handled exception, but response already started." + raise RuntimeError(msg) from exc + + if scope["type"] == "http": + request = Request(scope, receive=receive) + if is_async_callable(handler): + response = await handler(request, exc) + else: + response = await run_in_threadpool(handler, request, exc) + await response(scope, receive, sender) + elif scope["type"] == "websocket": + websocket = WebSocket(scope, receive=receive, send=send) + if is_async_callable(handler): + await handler(websocket, exc) + else: + await run_in_threadpool(handler, websocket, exc) + + def http_exception(self, request: Request, exc: HTTPException) -> Response: + if exc.status_code in {204, 304}: + return Response(status_code=exc.status_code, headers=exc.headers) + return PlainTextResponse( + exc.detail, status_code=exc.status_code, headers=exc.headers + ) + + async def websocket_exception( + self, websocket: WebSocket, exc: WebSocketException + ) -> None: + await websocket.close(code=exc.code, reason=exc.reason) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/gzip.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/gzip.py new file mode 100644 index 0000000..cbb0f4a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/gzip.py @@ -0,0 +1,113 @@ +import gzip +import io +import typing + +from starlette.datastructures import Headers, MutableHeaders +from starlette.types import ASGIApp, Message, Receive, Scope, Send + + +class GZipMiddleware: + def __init__( + self, app: ASGIApp, minimum_size: int = 500, compresslevel: int = 9 + ) -> None: + self.app = app + self.minimum_size = minimum_size + self.compresslevel = compresslevel + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if scope["type"] == "http": + headers = Headers(scope=scope) + if "gzip" in headers.get("Accept-Encoding", ""): + responder = GZipResponder( + self.app, self.minimum_size, compresslevel=self.compresslevel + ) + await responder(scope, receive, send) + return + await self.app(scope, receive, send) + + +class GZipResponder: + def __init__(self, app: ASGIApp, minimum_size: int, compresslevel: int = 9) -> None: + self.app = app + self.minimum_size = minimum_size + self.send: Send = unattached_send + self.initial_message: Message = {} + self.started = False + self.content_encoding_set = False + self.gzip_buffer = io.BytesIO() + self.gzip_file = gzip.GzipFile( + mode="wb", fileobj=self.gzip_buffer, compresslevel=compresslevel + ) + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + self.send = send + await self.app(scope, receive, self.send_with_gzip) + + async def send_with_gzip(self, message: Message) -> None: + message_type = message["type"] + if message_type == "http.response.start": + # Don't send the initial message until we've determined how to + # modify the outgoing headers correctly. + self.initial_message = message + headers = Headers(raw=self.initial_message["headers"]) + self.content_encoding_set = "content-encoding" in headers + elif message_type == "http.response.body" and self.content_encoding_set: + if not self.started: + self.started = True + await self.send(self.initial_message) + await self.send(message) + elif message_type == "http.response.body" and not self.started: + self.started = True + body = message.get("body", b"") + more_body = message.get("more_body", False) + if len(body) < self.minimum_size and not more_body: + # Don't apply GZip to small outgoing responses. + await self.send(self.initial_message) + await self.send(message) + elif not more_body: + # Standard GZip response. + self.gzip_file.write(body) + self.gzip_file.close() + body = self.gzip_buffer.getvalue() + + headers = MutableHeaders(raw=self.initial_message["headers"]) + headers["Content-Encoding"] = "gzip" + headers["Content-Length"] = str(len(body)) + headers.add_vary_header("Accept-Encoding") + message["body"] = body + + await self.send(self.initial_message) + await self.send(message) + else: + # Initial body in streaming GZip response. + headers = MutableHeaders(raw=self.initial_message["headers"]) + headers["Content-Encoding"] = "gzip" + headers.add_vary_header("Accept-Encoding") + del headers["Content-Length"] + + self.gzip_file.write(body) + message["body"] = self.gzip_buffer.getvalue() + self.gzip_buffer.seek(0) + self.gzip_buffer.truncate() + + await self.send(self.initial_message) + await self.send(message) + + elif message_type == "http.response.body": + # Remaining body in streaming GZip response. + body = message.get("body", b"") + more_body = message.get("more_body", False) + + self.gzip_file.write(body) + if not more_body: + self.gzip_file.close() + + message["body"] = self.gzip_buffer.getvalue() + self.gzip_buffer.seek(0) + self.gzip_buffer.truncate() + + await self.send(message) + + +async def unattached_send(message: Message) -> typing.NoReturn: + raise RuntimeError("send awaitable not set") # pragma: no cover diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/httpsredirect.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/httpsredirect.py new file mode 100644 index 0000000..a835906 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/httpsredirect.py @@ -0,0 +1,19 @@ +from starlette.datastructures import URL +from starlette.responses import RedirectResponse +from starlette.types import ASGIApp, Receive, Scope, Send + + +class HTTPSRedirectMiddleware: + def __init__(self, app: ASGIApp) -> None: + self.app = app + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if scope["type"] in ("http", "websocket") and scope["scheme"] in ("http", "ws"): + url = URL(scope=scope) + redirect_scheme = {"http": "https", "ws": "wss"}[url.scheme] + netloc = url.hostname if url.port in (80, 443) else url.netloc + url = url.replace(scheme=redirect_scheme, netloc=netloc) + response = RedirectResponse(url, status_code=307) + await response(scope, receive, send) + else: + await self.app(scope, receive, send) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/sessions.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/sessions.py new file mode 100644 index 0000000..b1e32ec --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/sessions.py @@ -0,0 +1,86 @@ +import json +import sys +import typing +from base64 import b64decode, b64encode + +import itsdangerous +from itsdangerous.exc import BadSignature + +from starlette.datastructures import MutableHeaders, Secret +from starlette.requests import HTTPConnection +from starlette.types import ASGIApp, Message, Receive, Scope, Send + +if sys.version_info >= (3, 8): # pragma: no cover + from typing import Literal +else: # pragma: no cover + from typing_extensions import Literal + + +class SessionMiddleware: + def __init__( + self, + app: ASGIApp, + secret_key: typing.Union[str, Secret], + session_cookie: str = "session", + max_age: typing.Optional[int] = 14 * 24 * 60 * 60, # 14 days, in seconds + path: str = "/", + same_site: Literal["lax", "strict", "none"] = "lax", + https_only: bool = False, + ) -> None: + self.app = app + self.signer = itsdangerous.TimestampSigner(str(secret_key)) + self.session_cookie = session_cookie + self.max_age = max_age + self.path = path + self.security_flags = "httponly; samesite=" + same_site + if https_only: # Secure flag can be used with HTTPS only + self.security_flags += "; secure" + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if scope["type"] not in ("http", "websocket"): # pragma: no cover + await self.app(scope, receive, send) + return + + connection = HTTPConnection(scope) + initial_session_was_empty = True + + if self.session_cookie in connection.cookies: + data = connection.cookies[self.session_cookie].encode("utf-8") + try: + data = self.signer.unsign(data, max_age=self.max_age) + scope["session"] = json.loads(b64decode(data)) + initial_session_was_empty = False + except BadSignature: + scope["session"] = {} + else: + scope["session"] = {} + + async def send_wrapper(message: Message) -> None: + if message["type"] == "http.response.start": + if scope["session"]: + # We have session data to persist. + data = b64encode(json.dumps(scope["session"]).encode("utf-8")) + data = self.signer.sign(data) + headers = MutableHeaders(scope=message) + header_value = "{session_cookie}={data}; path={path}; {max_age}{security_flags}".format( # noqa E501 + session_cookie=self.session_cookie, + data=data.decode("utf-8"), + path=self.path, + max_age=f"Max-Age={self.max_age}; " if self.max_age else "", + security_flags=self.security_flags, + ) + headers.append("Set-Cookie", header_value) + elif not initial_session_was_empty: + # The session has been cleared. + headers = MutableHeaders(scope=message) + header_value = "{session_cookie}={data}; path={path}; {expires}{security_flags}".format( # noqa E501 + session_cookie=self.session_cookie, + data="null", + path=self.path, + expires="expires=Thu, 01 Jan 1970 00:00:00 GMT; ", + security_flags=self.security_flags, + ) + headers.append("Set-Cookie", header_value) + await send(message) + + await self.app(scope, receive, send_wrapper) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/trustedhost.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/trustedhost.py new file mode 100644 index 0000000..e84e687 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/trustedhost.py @@ -0,0 +1,60 @@ +import typing + +from starlette.datastructures import URL, Headers +from starlette.responses import PlainTextResponse, RedirectResponse, Response +from starlette.types import ASGIApp, Receive, Scope, Send + +ENFORCE_DOMAIN_WILDCARD = "Domain wildcard patterns must be like '*.example.com'." + + +class TrustedHostMiddleware: + def __init__( + self, + app: ASGIApp, + allowed_hosts: typing.Optional[typing.Sequence[str]] = None, + www_redirect: bool = True, + ) -> None: + if allowed_hosts is None: + allowed_hosts = ["*"] + + for pattern in allowed_hosts: + assert "*" not in pattern[1:], ENFORCE_DOMAIN_WILDCARD + if pattern.startswith("*") and pattern != "*": + assert pattern.startswith("*."), ENFORCE_DOMAIN_WILDCARD + self.app = app + self.allowed_hosts = list(allowed_hosts) + self.allow_any = "*" in allowed_hosts + self.www_redirect = www_redirect + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if self.allow_any or scope["type"] not in ( + "http", + "websocket", + ): # pragma: no cover + await self.app(scope, receive, send) + return + + headers = Headers(scope=scope) + host = headers.get("host", "").split(":")[0] + is_valid_host = False + found_www_redirect = False + for pattern in self.allowed_hosts: + if host == pattern or ( + pattern.startswith("*") and host.endswith(pattern[1:]) + ): + is_valid_host = True + break + elif "www." + host == pattern: + found_www_redirect = True + + if is_valid_host: + await self.app(scope, receive, send) + else: + response: Response + if found_www_redirect and self.www_redirect: + url = URL(scope=scope) + redirect_url = url.replace(netloc="www." + url.netloc) + response = RedirectResponse(url=str(redirect_url)) + else: + response = PlainTextResponse("Invalid host header", status_code=400) + await response(scope, receive, send) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/wsgi.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/wsgi.py new file mode 100644 index 0000000..9dbd065 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/middleware/wsgi.py @@ -0,0 +1,140 @@ +import io +import math +import sys +import typing +import warnings + +import anyio + +from starlette.types import Receive, Scope, Send + +warnings.warn( + "starlette.middleware.wsgi is deprecated and will be removed in a future release. " + "Please refer to https://github.com/abersheeran/a2wsgi as a replacement.", + DeprecationWarning, +) + + +def build_environ(scope: Scope, body: bytes) -> dict: + """ + Builds a scope and request body into a WSGI environ object. + """ + environ = { + "REQUEST_METHOD": scope["method"], + "SCRIPT_NAME": scope.get("root_path", "").encode("utf8").decode("latin1"), + "PATH_INFO": scope["path"].encode("utf8").decode("latin1"), + "QUERY_STRING": scope["query_string"].decode("ascii"), + "SERVER_PROTOCOL": f"HTTP/{scope['http_version']}", + "wsgi.version": (1, 0), + "wsgi.url_scheme": scope.get("scheme", "http"), + "wsgi.input": io.BytesIO(body), + "wsgi.errors": sys.stdout, + "wsgi.multithread": True, + "wsgi.multiprocess": True, + "wsgi.run_once": False, + } + + # Get server name and port - required in WSGI, not in ASGI + server = scope.get("server") or ("localhost", 80) + environ["SERVER_NAME"] = server[0] + environ["SERVER_PORT"] = server[1] + + # Get client IP address + if scope.get("client"): + environ["REMOTE_ADDR"] = scope["client"][0] + + # Go through headers and make them into environ entries + for name, value in scope.get("headers", []): + name = name.decode("latin1") + if name == "content-length": + corrected_name = "CONTENT_LENGTH" + elif name == "content-type": + corrected_name = "CONTENT_TYPE" + else: + corrected_name = f"HTTP_{name}".upper().replace("-", "_") + # HTTPbis say only ASCII chars are allowed in headers, but we latin1 just in + # case + value = value.decode("latin1") + if corrected_name in environ: + value = environ[corrected_name] + "," + value + environ[corrected_name] = value + return environ + + +class WSGIMiddleware: + def __init__(self, app: typing.Callable) -> None: + self.app = app + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + assert scope["type"] == "http" + responder = WSGIResponder(self.app, scope) + await responder(receive, send) + + +class WSGIResponder: + def __init__(self, app: typing.Callable, scope: Scope) -> None: + self.app = app + self.scope = scope + self.status = None + self.response_headers = None + self.stream_send, self.stream_receive = anyio.create_memory_object_stream( + math.inf + ) + self.response_started = False + self.exc_info: typing.Any = None + + async def __call__(self, receive: Receive, send: Send) -> None: + body = b"" + more_body = True + while more_body: + message = await receive() + body += message.get("body", b"") + more_body = message.get("more_body", False) + environ = build_environ(self.scope, body) + + async with anyio.create_task_group() as task_group: + task_group.start_soon(self.sender, send) + async with self.stream_send: + await anyio.to_thread.run_sync(self.wsgi, environ, self.start_response) + if self.exc_info is not None: + raise self.exc_info[0].with_traceback(self.exc_info[1], self.exc_info[2]) + + async def sender(self, send: Send) -> None: + async with self.stream_receive: + async for message in self.stream_receive: + await send(message) + + def start_response( + self, + status: str, + response_headers: typing.List[typing.Tuple[str, str]], + exc_info: typing.Any = None, + ) -> None: + self.exc_info = exc_info + if not self.response_started: + self.response_started = True + status_code_string, _ = status.split(" ", 1) + status_code = int(status_code_string) + headers = [ + (name.strip().encode("ascii").lower(), value.strip().encode("ascii")) + for name, value in response_headers + ] + anyio.from_thread.run( + self.stream_send.send, + { + "type": "http.response.start", + "status": status_code, + "headers": headers, + }, + ) + + def wsgi(self, environ: dict, start_response: typing.Callable) -> None: + for chunk in self.app(environ, start_response): + anyio.from_thread.run( + self.stream_send.send, + {"type": "http.response.body", "body": chunk, "more_body": True}, + ) + + anyio.from_thread.run( + self.stream_send.send, {"type": "http.response.body", "body": b""} + ) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/py.typed b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/requests.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/requests.py new file mode 100644 index 0000000..acca322 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/requests.py @@ -0,0 +1,318 @@ +import json +import typing +from http import cookies as http_cookies + +import anyio + +from starlette._utils import AwaitableOrContextManager, AwaitableOrContextManagerWrapper +from starlette.datastructures import URL, Address, FormData, Headers, QueryParams, State +from starlette.exceptions import HTTPException +from starlette.formparsers import FormParser, MultiPartException, MultiPartParser +from starlette.types import Message, Receive, Scope, Send + +try: + from multipart.multipart import parse_options_header +except ModuleNotFoundError: # pragma: nocover + parse_options_header = None + + +if typing.TYPE_CHECKING: + from starlette.routing import Router + + +SERVER_PUSH_HEADERS_TO_COPY = { + "accept", + "accept-encoding", + "accept-language", + "cache-control", + "user-agent", +} + + +def cookie_parser(cookie_string: str) -> typing.Dict[str, str]: + """ + This function parses a ``Cookie`` HTTP header into a dict of key/value pairs. + + It attempts to mimic browser cookie parsing behavior: browsers and web servers + frequently disregard the spec (RFC 6265) when setting and reading cookies, + so we attempt to suit the common scenarios here. + + This function has been adapted from Django 3.1.0. + Note: we are explicitly _NOT_ using `SimpleCookie.load` because it is based + on an outdated spec and will fail on lots of input we want to support + """ + cookie_dict: typing.Dict[str, str] = {} + for chunk in cookie_string.split(";"): + if "=" in chunk: + key, val = chunk.split("=", 1) + else: + # Assume an empty name per + # https://bugzilla.mozilla.org/show_bug.cgi?id=169091 + key, val = "", chunk + key, val = key.strip(), val.strip() + if key or val: + # unquote using Python's algorithm. + cookie_dict[key] = http_cookies._unquote(val) + return cookie_dict + + +class ClientDisconnect(Exception): + pass + + +class HTTPConnection(typing.Mapping[str, typing.Any]): + """ + A base class for incoming HTTP connections, that is used to provide + any functionality that is common to both `Request` and `WebSocket`. + """ + + def __init__(self, scope: Scope, receive: typing.Optional[Receive] = None) -> None: + assert scope["type"] in ("http", "websocket") + self.scope = scope + + def __getitem__(self, key: str) -> typing.Any: + return self.scope[key] + + def __iter__(self) -> typing.Iterator[str]: + return iter(self.scope) + + def __len__(self) -> int: + return len(self.scope) + + # Don't use the `abc.Mapping.__eq__` implementation. + # Connection instances should never be considered equal + # unless `self is other`. + __eq__ = object.__eq__ + __hash__ = object.__hash__ + + @property + def app(self) -> typing.Any: + return self.scope["app"] + + @property + def url(self) -> URL: + if not hasattr(self, "_url"): + self._url = URL(scope=self.scope) + return self._url + + @property + def base_url(self) -> URL: + if not hasattr(self, "_base_url"): + base_url_scope = dict(self.scope) + base_url_scope["path"] = "/" + base_url_scope["query_string"] = b"" + base_url_scope["root_path"] = base_url_scope.get( + "app_root_path", base_url_scope.get("root_path", "") + ) + self._base_url = URL(scope=base_url_scope) + return self._base_url + + @property + def headers(self) -> Headers: + if not hasattr(self, "_headers"): + self._headers = Headers(scope=self.scope) + return self._headers + + @property + def query_params(self) -> QueryParams: + if not hasattr(self, "_query_params"): + self._query_params = QueryParams(self.scope["query_string"]) + return self._query_params + + @property + def path_params(self) -> typing.Dict[str, typing.Any]: + return self.scope.get("path_params", {}) + + @property + def cookies(self) -> typing.Dict[str, str]: + if not hasattr(self, "_cookies"): + cookies: typing.Dict[str, str] = {} + cookie_header = self.headers.get("cookie") + + if cookie_header: + cookies = cookie_parser(cookie_header) + self._cookies = cookies + return self._cookies + + @property + def client(self) -> typing.Optional[Address]: + # client is a 2 item tuple of (host, port), None or missing + host_port = self.scope.get("client") + if host_port is not None: + return Address(*host_port) + return None + + @property + def session(self) -> typing.Dict[str, typing.Any]: + assert ( + "session" in self.scope + ), "SessionMiddleware must be installed to access request.session" + return self.scope["session"] + + @property + def auth(self) -> typing.Any: + assert ( + "auth" in self.scope + ), "AuthenticationMiddleware must be installed to access request.auth" + return self.scope["auth"] + + @property + def user(self) -> typing.Any: + assert ( + "user" in self.scope + ), "AuthenticationMiddleware must be installed to access request.user" + return self.scope["user"] + + @property + def state(self) -> State: + if not hasattr(self, "_state"): + # Ensure 'state' has an empty dict if it's not already populated. + self.scope.setdefault("state", {}) + # Create a state instance with a reference to the dict in which it should + # store info + self._state = State(self.scope["state"]) + return self._state + + def url_for(self, __name: str, **path_params: typing.Any) -> URL: + router: Router = self.scope["router"] + url_path = router.url_path_for(__name, **path_params) + return url_path.make_absolute_url(base_url=self.base_url) + + +async def empty_receive() -> typing.NoReturn: + raise RuntimeError("Receive channel has not been made available") + + +async def empty_send(message: Message) -> typing.NoReturn: + raise RuntimeError("Send channel has not been made available") + + +class Request(HTTPConnection): + _form: typing.Optional[FormData] + + def __init__( + self, scope: Scope, receive: Receive = empty_receive, send: Send = empty_send + ): + super().__init__(scope) + assert scope["type"] == "http" + self._receive = receive + self._send = send + self._stream_consumed = False + self._is_disconnected = False + self._form = None + + @property + def method(self) -> str: + return self.scope["method"] + + @property + def receive(self) -> Receive: + return self._receive + + async def stream(self) -> typing.AsyncGenerator[bytes, None]: + if hasattr(self, "_body"): + yield self._body + yield b"" + return + if self._stream_consumed: + raise RuntimeError("Stream consumed") + self._stream_consumed = True + while True: + message = await self._receive() + if message["type"] == "http.request": + body = message.get("body", b"") + if body: + yield body + if not message.get("more_body", False): + break + elif message["type"] == "http.disconnect": + self._is_disconnected = True + raise ClientDisconnect() + yield b"" + + async def body(self) -> bytes: + if not hasattr(self, "_body"): + chunks: "typing.List[bytes]" = [] + async for chunk in self.stream(): + chunks.append(chunk) + self._body = b"".join(chunks) + return self._body + + async def json(self) -> typing.Any: + if not hasattr(self, "_json"): + body = await self.body() + self._json = json.loads(body) + return self._json + + async def _get_form( + self, + *, + max_files: typing.Union[int, float] = 1000, + max_fields: typing.Union[int, float] = 1000, + ) -> FormData: + if self._form is None: + assert ( + parse_options_header is not None + ), "The `python-multipart` library must be installed to use form parsing." + content_type_header = self.headers.get("Content-Type") + content_type: bytes + content_type, _ = parse_options_header(content_type_header) + if content_type == b"multipart/form-data": + try: + multipart_parser = MultiPartParser( + self.headers, + self.stream(), + max_files=max_files, + max_fields=max_fields, + ) + self._form = await multipart_parser.parse() + except MultiPartException as exc: + if "app" in self.scope: + raise HTTPException(status_code=400, detail=exc.message) + raise exc + elif content_type == b"application/x-www-form-urlencoded": + form_parser = FormParser(self.headers, self.stream()) + self._form = await form_parser.parse() + else: + self._form = FormData() + return self._form + + def form( + self, + *, + max_files: typing.Union[int, float] = 1000, + max_fields: typing.Union[int, float] = 1000, + ) -> AwaitableOrContextManager[FormData]: + return AwaitableOrContextManagerWrapper( + self._get_form(max_files=max_files, max_fields=max_fields) + ) + + async def close(self) -> None: + if self._form is not None: + await self._form.close() + + async def is_disconnected(self) -> bool: + if not self._is_disconnected: + message: Message = {} + + # If message isn't immediately available, move on + with anyio.CancelScope() as cs: + cs.cancel() + message = await self._receive() + + if message.get("type") == "http.disconnect": + self._is_disconnected = True + + return self._is_disconnected + + async def send_push_promise(self, path: str) -> None: + if "http.response.push" in self.scope.get("extensions", {}): + raw_headers: "typing.List[typing.Tuple[bytes, bytes]]" = [] + for name in SERVER_PUSH_HEADERS_TO_COPY: + for value in self.headers.getlist(name): + raw_headers.append( + (name.encode("latin-1"), value.encode("latin-1")) + ) + await self._send( + {"type": "http.response.push", "path": path, "headers": raw_headers} + ) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/responses.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/responses.py new file mode 100644 index 0000000..453bbb1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/responses.py @@ -0,0 +1,366 @@ +import http.cookies +import json +import os +import stat +import sys +import typing +from datetime import datetime +from email.utils import format_datetime, formatdate +from functools import partial +from mimetypes import guess_type as mimetypes_guess_type +from urllib.parse import quote + +import anyio + +from starlette._compat import md5_hexdigest +from starlette.background import BackgroundTask +from starlette.concurrency import iterate_in_threadpool +from starlette.datastructures import URL, MutableHeaders +from starlette.types import Receive, Scope, Send + +if sys.version_info >= (3, 8): # pragma: no cover + from typing import Literal +else: # pragma: no cover + from typing_extensions import Literal + +# Workaround for adding samesite support to pre 3.8 python +http.cookies.Morsel._reserved["samesite"] = "SameSite" # type: ignore[attr-defined] + + +# Compatibility wrapper for `mimetypes.guess_type` to support `os.PathLike` on typing.Tuple[typing.Optional[str], typing.Optional[str]]: + if sys.version_info < (3, 8): # pragma: no cover + url = os.fspath(url) + return mimetypes_guess_type(url, strict) + + +class Response: + media_type = None + charset = "utf-8" + + def __init__( + self, + content: typing.Any = None, + status_code: int = 200, + headers: typing.Optional[typing.Mapping[str, str]] = None, + media_type: typing.Optional[str] = None, + background: typing.Optional[BackgroundTask] = None, + ) -> None: + self.status_code = status_code + if media_type is not None: + self.media_type = media_type + self.background = background + self.body = self.render(content) + self.init_headers(headers) + + def render(self, content: typing.Any) -> bytes: + if content is None: + return b"" + if isinstance(content, bytes): + return content + return content.encode(self.charset) + + def init_headers( + self, headers: typing.Optional[typing.Mapping[str, str]] = None + ) -> None: + if headers is None: + raw_headers: typing.List[typing.Tuple[bytes, bytes]] = [] + populate_content_length = True + populate_content_type = True + else: + raw_headers = [ + (k.lower().encode("latin-1"), v.encode("latin-1")) + for k, v in headers.items() + ] + keys = [h[0] for h in raw_headers] + populate_content_length = b"content-length" not in keys + populate_content_type = b"content-type" not in keys + + body = getattr(self, "body", None) + if ( + body is not None + and populate_content_length + and not (self.status_code < 200 or self.status_code in (204, 304)) + ): + content_length = str(len(body)) + raw_headers.append((b"content-length", content_length.encode("latin-1"))) + + content_type = self.media_type + if content_type is not None and populate_content_type: + if content_type.startswith("text/"): + content_type += "; charset=" + self.charset + raw_headers.append((b"content-type", content_type.encode("latin-1"))) + + self.raw_headers = raw_headers + + @property + def headers(self) -> MutableHeaders: + if not hasattr(self, "_headers"): + self._headers = MutableHeaders(raw=self.raw_headers) + return self._headers + + def set_cookie( + self, + key: str, + value: str = "", + max_age: typing.Optional[int] = None, + expires: typing.Optional[typing.Union[datetime, str, int]] = None, + path: str = "/", + domain: typing.Optional[str] = None, + secure: bool = False, + httponly: bool = False, + samesite: typing.Optional[Literal["lax", "strict", "none"]] = "lax", + ) -> None: + cookie: "http.cookies.BaseCookie[str]" = http.cookies.SimpleCookie() + cookie[key] = value + if max_age is not None: + cookie[key]["max-age"] = max_age + if expires is not None: + if isinstance(expires, datetime): + cookie[key]["expires"] = format_datetime(expires, usegmt=True) + else: + cookie[key]["expires"] = expires + if path is not None: + cookie[key]["path"] = path + if domain is not None: + cookie[key]["domain"] = domain + if secure: + cookie[key]["secure"] = True + if httponly: + cookie[key]["httponly"] = True + if samesite is not None: + assert samesite.lower() in [ + "strict", + "lax", + "none", + ], "samesite must be either 'strict', 'lax' or 'none'" + cookie[key]["samesite"] = samesite + cookie_val = cookie.output(header="").strip() + self.raw_headers.append((b"set-cookie", cookie_val.encode("latin-1"))) + + def delete_cookie( + self, + key: str, + path: str = "/", + domain: typing.Optional[str] = None, + secure: bool = False, + httponly: bool = False, + samesite: typing.Optional[Literal["lax", "strict", "none"]] = "lax", + ) -> None: + self.set_cookie( + key, + max_age=0, + expires=0, + path=path, + domain=domain, + secure=secure, + httponly=httponly, + samesite=samesite, + ) + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + await send( + { + "type": "http.response.start", + "status": self.status_code, + "headers": self.raw_headers, + } + ) + await send({"type": "http.response.body", "body": self.body}) + + if self.background is not None: + await self.background() + + +class HTMLResponse(Response): + media_type = "text/html" + + +class PlainTextResponse(Response): + media_type = "text/plain" + + +class JSONResponse(Response): + media_type = "application/json" + + def __init__( + self, + content: typing.Any, + status_code: int = 200, + headers: typing.Optional[typing.Dict[str, str]] = None, + media_type: typing.Optional[str] = None, + background: typing.Optional[BackgroundTask] = None, + ) -> None: + super().__init__(content, status_code, headers, media_type, background) + + def render(self, content: typing.Any) -> bytes: + return json.dumps( + content, + ensure_ascii=False, + allow_nan=False, + indent=None, + separators=(",", ":"), + ).encode("utf-8") + + +class RedirectResponse(Response): + def __init__( + self, + url: typing.Union[str, URL], + status_code: int = 307, + headers: typing.Optional[typing.Mapping[str, str]] = None, + background: typing.Optional[BackgroundTask] = None, + ) -> None: + super().__init__( + content=b"", status_code=status_code, headers=headers, background=background + ) + self.headers["location"] = quote(str(url), safe=":/%#?=@[]!$&'()*+,;") + + +Content = typing.Union[str, bytes] +SyncContentStream = typing.Iterator[Content] +AsyncContentStream = typing.AsyncIterable[Content] +ContentStream = typing.Union[AsyncContentStream, SyncContentStream] + + +class StreamingResponse(Response): + body_iterator: AsyncContentStream + + def __init__( + self, + content: ContentStream, + status_code: int = 200, + headers: typing.Optional[typing.Mapping[str, str]] = None, + media_type: typing.Optional[str] = None, + background: typing.Optional[BackgroundTask] = None, + ) -> None: + if isinstance(content, typing.AsyncIterable): + self.body_iterator = content + else: + self.body_iterator = iterate_in_threadpool(content) + self.status_code = status_code + self.media_type = self.media_type if media_type is None else media_type + self.background = background + self.init_headers(headers) + + async def listen_for_disconnect(self, receive: Receive) -> None: + while True: + message = await receive() + if message["type"] == "http.disconnect": + break + + async def stream_response(self, send: Send) -> None: + await send( + { + "type": "http.response.start", + "status": self.status_code, + "headers": self.raw_headers, + } + ) + async for chunk in self.body_iterator: + if not isinstance(chunk, bytes): + chunk = chunk.encode(self.charset) + await send({"type": "http.response.body", "body": chunk, "more_body": True}) + + await send({"type": "http.response.body", "body": b"", "more_body": False}) + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + async with anyio.create_task_group() as task_group: + + async def wrap(func: "typing.Callable[[], typing.Awaitable[None]]") -> None: + await func() + task_group.cancel_scope.cancel() + + task_group.start_soon(wrap, partial(self.stream_response, send)) + await wrap(partial(self.listen_for_disconnect, receive)) + + if self.background is not None: + await self.background() + + +class FileResponse(Response): + chunk_size = 64 * 1024 + + def __init__( + self, + path: typing.Union[str, "os.PathLike[str]"], + status_code: int = 200, + headers: typing.Optional[typing.Mapping[str, str]] = None, + media_type: typing.Optional[str] = None, + background: typing.Optional[BackgroundTask] = None, + filename: typing.Optional[str] = None, + stat_result: typing.Optional[os.stat_result] = None, + method: typing.Optional[str] = None, + content_disposition_type: str = "attachment", + ) -> None: + self.path = path + self.status_code = status_code + self.filename = filename + self.send_header_only = method is not None and method.upper() == "HEAD" + if media_type is None: + media_type = guess_type(filename or path)[0] or "text/plain" + self.media_type = media_type + self.background = background + self.init_headers(headers) + if self.filename is not None: + content_disposition_filename = quote(self.filename) + if content_disposition_filename != self.filename: + content_disposition = "{}; filename*=utf-8''{}".format( + content_disposition_type, content_disposition_filename + ) + else: + content_disposition = '{}; filename="{}"'.format( + content_disposition_type, self.filename + ) + self.headers.setdefault("content-disposition", content_disposition) + self.stat_result = stat_result + if stat_result is not None: + self.set_stat_headers(stat_result) + + def set_stat_headers(self, stat_result: os.stat_result) -> None: + content_length = str(stat_result.st_size) + last_modified = formatdate(stat_result.st_mtime, usegmt=True) + etag_base = str(stat_result.st_mtime) + "-" + str(stat_result.st_size) + etag = md5_hexdigest(etag_base.encode(), usedforsecurity=False) + + self.headers.setdefault("content-length", content_length) + self.headers.setdefault("last-modified", last_modified) + self.headers.setdefault("etag", etag) + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if self.stat_result is None: + try: + stat_result = await anyio.to_thread.run_sync(os.stat, self.path) + self.set_stat_headers(stat_result) + except FileNotFoundError: + raise RuntimeError(f"File at path {self.path} does not exist.") + else: + mode = stat_result.st_mode + if not stat.S_ISREG(mode): + raise RuntimeError(f"File at path {self.path} is not a file.") + await send( + { + "type": "http.response.start", + "status": self.status_code, + "headers": self.raw_headers, + } + ) + if self.send_header_only: + await send({"type": "http.response.body", "body": b"", "more_body": False}) + else: + async with await anyio.open_file(self.path, mode="rb") as file: + more_body = True + while more_body: + chunk = await file.read(self.chunk_size) + more_body = len(chunk) == self.chunk_size + await send( + { + "type": "http.response.body", + "body": chunk, + "more_body": more_body, + } + ) + if self.background is not None: + await self.background() diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/routing.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/routing.py new file mode 100644 index 0000000..52cf174 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/routing.py @@ -0,0 +1,862 @@ +import contextlib +import functools +import inspect +import re +import traceback +import types +import typing +import warnings +from contextlib import asynccontextmanager +from enum import Enum + +from starlette._utils import is_async_callable +from starlette.concurrency import run_in_threadpool +from starlette.convertors import CONVERTOR_TYPES, Convertor +from starlette.datastructures import URL, Headers, URLPath +from starlette.exceptions import HTTPException +from starlette.middleware import Middleware +from starlette.requests import Request +from starlette.responses import PlainTextResponse, RedirectResponse +from starlette.types import ASGIApp, Lifespan, Receive, Scope, Send +from starlette.websockets import WebSocket, WebSocketClose + + +class NoMatchFound(Exception): + """ + Raised by `.url_for(name, **path_params)` and `.url_path_for(name, **path_params)` + if no matching route exists. + """ + + def __init__(self, name: str, path_params: typing.Dict[str, typing.Any]) -> None: + params = ", ".join(list(path_params.keys())) + super().__init__(f'No route exists for name "{name}" and params "{params}".') + + +class Match(Enum): + NONE = 0 + PARTIAL = 1 + FULL = 2 + + +def iscoroutinefunction_or_partial(obj: typing.Any) -> bool: # pragma: no cover + """ + Correctly determines if an object is a coroutine function, + including those wrapped in functools.partial objects. + """ + warnings.warn( + "iscoroutinefunction_or_partial is deprecated, " + "and will be removed in a future release.", + DeprecationWarning, + ) + while isinstance(obj, functools.partial): + obj = obj.func + return inspect.iscoroutinefunction(obj) + + +def request_response(func: typing.Callable) -> ASGIApp: + """ + Takes a function or coroutine `func(request) -> response`, + and returns an ASGI application. + """ + is_coroutine = is_async_callable(func) + + async def app(scope: Scope, receive: Receive, send: Send) -> None: + request = Request(scope, receive=receive, send=send) + if is_coroutine: + response = await func(request) + else: + response = await run_in_threadpool(func, request) + await response(scope, receive, send) + + return app + + +def websocket_session(func: typing.Callable) -> ASGIApp: + """ + Takes a coroutine `func(session)`, and returns an ASGI application. + """ + # assert asyncio.iscoroutinefunction(func), "WebSocket endpoints must be async" + + async def app(scope: Scope, receive: Receive, send: Send) -> None: + session = WebSocket(scope, receive=receive, send=send) + await func(session) + + return app + + +def get_name(endpoint: typing.Callable) -> str: + if inspect.isroutine(endpoint) or inspect.isclass(endpoint): + return endpoint.__name__ + return endpoint.__class__.__name__ + + +def replace_params( + path: str, + param_convertors: typing.Dict[str, Convertor], + path_params: typing.Dict[str, str], +) -> typing.Tuple[str, dict]: + for key, value in list(path_params.items()): + if "{" + key + "}" in path: + convertor = param_convertors[key] + value = convertor.to_string(value) + path = path.replace("{" + key + "}", value) + path_params.pop(key) + return path, path_params + + +# Match parameters in URL paths, eg. '{param}', and '{param:int}' +PARAM_REGEX = re.compile("{([a-zA-Z_][a-zA-Z0-9_]*)(:[a-zA-Z_][a-zA-Z0-9_]*)?}") + + +def compile_path( + path: str, +) -> typing.Tuple[typing.Pattern, str, typing.Dict[str, Convertor]]: + """ + Given a path string, like: "/{username:str}", + or a host string, like: "{subdomain}.mydomain.org", return a three-tuple + of (regex, format, {param_name:convertor}). + + regex: "/(?P[^/]+)" + format: "/{username}" + convertors: {"username": StringConvertor()} + """ + is_host = not path.startswith("/") + + path_regex = "^" + path_format = "" + duplicated_params = set() + + idx = 0 + param_convertors = {} + for match in PARAM_REGEX.finditer(path): + param_name, convertor_type = match.groups("str") + convertor_type = convertor_type.lstrip(":") + assert ( + convertor_type in CONVERTOR_TYPES + ), f"Unknown path convertor '{convertor_type}'" + convertor = CONVERTOR_TYPES[convertor_type] + + path_regex += re.escape(path[idx : match.start()]) + path_regex += f"(?P<{param_name}>{convertor.regex})" + + path_format += path[idx : match.start()] + path_format += "{%s}" % param_name + + if param_name in param_convertors: + duplicated_params.add(param_name) + + param_convertors[param_name] = convertor + + idx = match.end() + + if duplicated_params: + names = ", ".join(sorted(duplicated_params)) + ending = "s" if len(duplicated_params) > 1 else "" + raise ValueError(f"Duplicated param name{ending} {names} at path {path}") + + if is_host: + # Align with `Host.matches()` behavior, which ignores port. + hostname = path[idx:].split(":")[0] + path_regex += re.escape(hostname) + "$" + else: + path_regex += re.escape(path[idx:]) + "$" + + path_format += path[idx:] + + return re.compile(path_regex), path_format, param_convertors + + +class BaseRoute: + def matches(self, scope: Scope) -> typing.Tuple[Match, Scope]: + raise NotImplementedError() # pragma: no cover + + def url_path_for(self, __name: str, **path_params: typing.Any) -> URLPath: + raise NotImplementedError() # pragma: no cover + + async def handle(self, scope: Scope, receive: Receive, send: Send) -> None: + raise NotImplementedError() # pragma: no cover + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + """ + A route may be used in isolation as a stand-alone ASGI app. + This is a somewhat contrived case, as they'll almost always be used + within a Router, but could be useful for some tooling and minimal apps. + """ + match, child_scope = self.matches(scope) + if match == Match.NONE: + if scope["type"] == "http": + response = PlainTextResponse("Not Found", status_code=404) + await response(scope, receive, send) + elif scope["type"] == "websocket": + websocket_close = WebSocketClose() + await websocket_close(scope, receive, send) + return + + scope.update(child_scope) + await self.handle(scope, receive, send) + + +class Route(BaseRoute): + def __init__( + self, + path: str, + endpoint: typing.Callable, + *, + methods: typing.Optional[typing.List[str]] = None, + name: typing.Optional[str] = None, + include_in_schema: bool = True, + ) -> None: + assert path.startswith("/"), "Routed paths must start with '/'" + self.path = path + self.endpoint = endpoint + self.name = get_name(endpoint) if name is None else name + self.include_in_schema = include_in_schema + + endpoint_handler = endpoint + while isinstance(endpoint_handler, functools.partial): + endpoint_handler = endpoint_handler.func + if inspect.isfunction(endpoint_handler) or inspect.ismethod(endpoint_handler): + # Endpoint is function or method. Treat it as `func(request) -> response`. + self.app = request_response(endpoint) + if methods is None: + methods = ["GET"] + else: + # Endpoint is a class. Treat it as ASGI. + self.app = endpoint + + if methods is None: + self.methods = None + else: + self.methods = {method.upper() for method in methods} + if "GET" in self.methods: + self.methods.add("HEAD") + + self.path_regex, self.path_format, self.param_convertors = compile_path(path) + + def matches(self, scope: Scope) -> typing.Tuple[Match, Scope]: + if scope["type"] == "http": + match = self.path_regex.match(scope["path"]) + if match: + matched_params = match.groupdict() + for key, value in matched_params.items(): + matched_params[key] = self.param_convertors[key].convert(value) + path_params = dict(scope.get("path_params", {})) + path_params.update(matched_params) + child_scope = {"endpoint": self.endpoint, "path_params": path_params} + if self.methods and scope["method"] not in self.methods: + return Match.PARTIAL, child_scope + else: + return Match.FULL, child_scope + return Match.NONE, {} + + def url_path_for(self, __name: str, **path_params: typing.Any) -> URLPath: + seen_params = set(path_params.keys()) + expected_params = set(self.param_convertors.keys()) + + if __name != self.name or seen_params != expected_params: + raise NoMatchFound(__name, path_params) + + path, remaining_params = replace_params( + self.path_format, self.param_convertors, path_params + ) + assert not remaining_params + return URLPath(path=path, protocol="http") + + async def handle(self, scope: Scope, receive: Receive, send: Send) -> None: + if self.methods and scope["method"] not in self.methods: + headers = {"Allow": ", ".join(self.methods)} + if "app" in scope: + raise HTTPException(status_code=405, headers=headers) + else: + response = PlainTextResponse( + "Method Not Allowed", status_code=405, headers=headers + ) + await response(scope, receive, send) + else: + await self.app(scope, receive, send) + + def __eq__(self, other: typing.Any) -> bool: + return ( + isinstance(other, Route) + and self.path == other.path + and self.endpoint == other.endpoint + and self.methods == other.methods + ) + + def __repr__(self) -> str: + class_name = self.__class__.__name__ + methods = sorted(self.methods or []) + path, name = self.path, self.name + return f"{class_name}(path={path!r}, name={name!r}, methods={methods!r})" + + +class WebSocketRoute(BaseRoute): + def __init__( + self, path: str, endpoint: typing.Callable, *, name: typing.Optional[str] = None + ) -> None: + assert path.startswith("/"), "Routed paths must start with '/'" + self.path = path + self.endpoint = endpoint + self.name = get_name(endpoint) if name is None else name + + endpoint_handler = endpoint + while isinstance(endpoint_handler, functools.partial): + endpoint_handler = endpoint_handler.func + if inspect.isfunction(endpoint_handler) or inspect.ismethod(endpoint_handler): + # Endpoint is function or method. Treat it as `func(websocket)`. + self.app = websocket_session(endpoint) + else: + # Endpoint is a class. Treat it as ASGI. + self.app = endpoint + + self.path_regex, self.path_format, self.param_convertors = compile_path(path) + + def matches(self, scope: Scope) -> typing.Tuple[Match, Scope]: + if scope["type"] == "websocket": + match = self.path_regex.match(scope["path"]) + if match: + matched_params = match.groupdict() + for key, value in matched_params.items(): + matched_params[key] = self.param_convertors[key].convert(value) + path_params = dict(scope.get("path_params", {})) + path_params.update(matched_params) + child_scope = {"endpoint": self.endpoint, "path_params": path_params} + return Match.FULL, child_scope + return Match.NONE, {} + + def url_path_for(self, __name: str, **path_params: typing.Any) -> URLPath: + seen_params = set(path_params.keys()) + expected_params = set(self.param_convertors.keys()) + + if __name != self.name or seen_params != expected_params: + raise NoMatchFound(__name, path_params) + + path, remaining_params = replace_params( + self.path_format, self.param_convertors, path_params + ) + assert not remaining_params + return URLPath(path=path, protocol="websocket") + + async def handle(self, scope: Scope, receive: Receive, send: Send) -> None: + await self.app(scope, receive, send) + + def __eq__(self, other: typing.Any) -> bool: + return ( + isinstance(other, WebSocketRoute) + and self.path == other.path + and self.endpoint == other.endpoint + ) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}(path={self.path!r}, name={self.name!r})" + + +class Mount(BaseRoute): + def __init__( + self, + path: str, + app: typing.Optional[ASGIApp] = None, + routes: typing.Optional[typing.Sequence[BaseRoute]] = None, + name: typing.Optional[str] = None, + *, + middleware: typing.Optional[typing.Sequence[Middleware]] = None, + ) -> None: + assert path == "" or path.startswith("/"), "Routed paths must start with '/'" + assert ( + app is not None or routes is not None + ), "Either 'app=...', or 'routes=' must be specified" + self.path = path.rstrip("/") + if app is not None: + self._base_app: ASGIApp = app + else: + self._base_app = Router(routes=routes) + self.app = self._base_app + if middleware is not None: + for cls, options in reversed(middleware): + self.app = cls(app=self.app, **options) + self.name = name + self.path_regex, self.path_format, self.param_convertors = compile_path( + self.path + "/{path:path}" + ) + + @property + def routes(self) -> typing.List[BaseRoute]: + return getattr(self._base_app, "routes", []) + + def matches(self, scope: Scope) -> typing.Tuple[Match, Scope]: + if scope["type"] in ("http", "websocket"): + path = scope["path"] + match = self.path_regex.match(path) + if match: + matched_params = match.groupdict() + for key, value in matched_params.items(): + matched_params[key] = self.param_convertors[key].convert(value) + remaining_path = "/" + matched_params.pop("path") + matched_path = path[: -len(remaining_path)] + path_params = dict(scope.get("path_params", {})) + path_params.update(matched_params) + root_path = scope.get("root_path", "") + child_scope = { + "path_params": path_params, + "app_root_path": scope.get("app_root_path", root_path), + "root_path": root_path + matched_path, + "path": remaining_path, + "endpoint": self.app, + } + return Match.FULL, child_scope + return Match.NONE, {} + + def url_path_for(self, __name: str, **path_params: typing.Any) -> URLPath: + if self.name is not None and __name == self.name and "path" in path_params: + # 'name' matches "". + path_params["path"] = path_params["path"].lstrip("/") + path, remaining_params = replace_params( + self.path_format, self.param_convertors, path_params + ) + if not remaining_params: + return URLPath(path=path) + elif self.name is None or __name.startswith(self.name + ":"): + if self.name is None: + # No mount name. + remaining_name = __name + else: + # 'name' matches ":". + remaining_name = __name[len(self.name) + 1 :] + path_kwarg = path_params.get("path") + path_params["path"] = "" + path_prefix, remaining_params = replace_params( + self.path_format, self.param_convertors, path_params + ) + if path_kwarg is not None: + remaining_params["path"] = path_kwarg + for route in self.routes or []: + try: + url = route.url_path_for(remaining_name, **remaining_params) + return URLPath( + path=path_prefix.rstrip("/") + str(url), protocol=url.protocol + ) + except NoMatchFound: + pass + raise NoMatchFound(__name, path_params) + + async def handle(self, scope: Scope, receive: Receive, send: Send) -> None: + await self.app(scope, receive, send) + + def __eq__(self, other: typing.Any) -> bool: + return ( + isinstance(other, Mount) + and self.path == other.path + and self.app == other.app + ) + + def __repr__(self) -> str: + class_name = self.__class__.__name__ + name = self.name or "" + return f"{class_name}(path={self.path!r}, name={name!r}, app={self.app!r})" + + +class Host(BaseRoute): + def __init__( + self, host: str, app: ASGIApp, name: typing.Optional[str] = None + ) -> None: + assert not host.startswith("/"), "Host must not start with '/'" + self.host = host + self.app = app + self.name = name + self.host_regex, self.host_format, self.param_convertors = compile_path(host) + + @property + def routes(self) -> typing.List[BaseRoute]: + return getattr(self.app, "routes", []) + + def matches(self, scope: Scope) -> typing.Tuple[Match, Scope]: + if scope["type"] in ("http", "websocket"): + headers = Headers(scope=scope) + host = headers.get("host", "").split(":")[0] + match = self.host_regex.match(host) + if match: + matched_params = match.groupdict() + for key, value in matched_params.items(): + matched_params[key] = self.param_convertors[key].convert(value) + path_params = dict(scope.get("path_params", {})) + path_params.update(matched_params) + child_scope = {"path_params": path_params, "endpoint": self.app} + return Match.FULL, child_scope + return Match.NONE, {} + + def url_path_for(self, __name: str, **path_params: typing.Any) -> URLPath: + if self.name is not None and __name == self.name and "path" in path_params: + # 'name' matches "". + path = path_params.pop("path") + host, remaining_params = replace_params( + self.host_format, self.param_convertors, path_params + ) + if not remaining_params: + return URLPath(path=path, host=host) + elif self.name is None or __name.startswith(self.name + ":"): + if self.name is None: + # No mount name. + remaining_name = __name + else: + # 'name' matches ":". + remaining_name = __name[len(self.name) + 1 :] + host, remaining_params = replace_params( + self.host_format, self.param_convertors, path_params + ) + for route in self.routes or []: + try: + url = route.url_path_for(remaining_name, **remaining_params) + return URLPath(path=str(url), protocol=url.protocol, host=host) + except NoMatchFound: + pass + raise NoMatchFound(__name, path_params) + + async def handle(self, scope: Scope, receive: Receive, send: Send) -> None: + await self.app(scope, receive, send) + + def __eq__(self, other: typing.Any) -> bool: + return ( + isinstance(other, Host) + and self.host == other.host + and self.app == other.app + ) + + def __repr__(self) -> str: + class_name = self.__class__.__name__ + name = self.name or "" + return f"{class_name}(host={self.host!r}, name={name!r}, app={self.app!r})" + + +_T = typing.TypeVar("_T") + + +class _AsyncLiftContextManager(typing.AsyncContextManager[_T]): + def __init__(self, cm: typing.ContextManager[_T]): + self._cm = cm + + async def __aenter__(self) -> _T: + return self._cm.__enter__() + + async def __aexit__( + self, + exc_type: typing.Optional[typing.Type[BaseException]], + exc_value: typing.Optional[BaseException], + traceback: typing.Optional[types.TracebackType], + ) -> typing.Optional[bool]: + return self._cm.__exit__(exc_type, exc_value, traceback) + + +def _wrap_gen_lifespan_context( + lifespan_context: typing.Callable[[typing.Any], typing.Generator] +) -> typing.Callable[[typing.Any], typing.AsyncContextManager]: + cmgr = contextlib.contextmanager(lifespan_context) + + @functools.wraps(cmgr) + def wrapper(app: typing.Any) -> _AsyncLiftContextManager: + return _AsyncLiftContextManager(cmgr(app)) + + return wrapper + + +class _DefaultLifespan: + def __init__(self, router: "Router"): + self._router = router + + async def __aenter__(self) -> None: + await self._router.startup() + + async def __aexit__(self, *exc_info: object) -> None: + await self._router.shutdown() + + def __call__(self: _T, app: object) -> _T: + return self + + +class Router: + def __init__( + self, + routes: typing.Optional[typing.Sequence[BaseRoute]] = None, + redirect_slashes: bool = True, + default: typing.Optional[ASGIApp] = None, + on_startup: typing.Optional[typing.Sequence[typing.Callable]] = None, + on_shutdown: typing.Optional[typing.Sequence[typing.Callable]] = None, + # the generic to Lifespan[AppType] is the type of the top level application + # which the router cannot know statically, so we use typing.Any + lifespan: typing.Optional[Lifespan[typing.Any]] = None, + ) -> None: + self.routes = [] if routes is None else list(routes) + self.redirect_slashes = redirect_slashes + self.default = self.not_found if default is None else default + self.on_startup = [] if on_startup is None else list(on_startup) + self.on_shutdown = [] if on_shutdown is None else list(on_shutdown) + + if on_startup or on_shutdown: + warnings.warn( + "The on_startup and on_shutdown parameters are deprecated, and they " + "will be removed on version 1.0. Use the lifespan parameter instead. " + "See more about it on https://www.starlette.io/lifespan/.", + DeprecationWarning, + ) + + if lifespan is None: + self.lifespan_context: Lifespan = _DefaultLifespan(self) + + elif inspect.isasyncgenfunction(lifespan): + warnings.warn( + "async generator function lifespans are deprecated, " + "use an @contextlib.asynccontextmanager function instead", + DeprecationWarning, + ) + self.lifespan_context = asynccontextmanager( + lifespan, # type: ignore[arg-type] + ) + elif inspect.isgeneratorfunction(lifespan): + warnings.warn( + "generator function lifespans are deprecated, " + "use an @contextlib.asynccontextmanager function instead", + DeprecationWarning, + ) + self.lifespan_context = _wrap_gen_lifespan_context( + lifespan, # type: ignore[arg-type] + ) + else: + self.lifespan_context = lifespan + + async def not_found(self, scope: Scope, receive: Receive, send: Send) -> None: + if scope["type"] == "websocket": + websocket_close = WebSocketClose() + await websocket_close(scope, receive, send) + return + + # If we're running inside a starlette application then raise an + # exception, so that the configurable exception handler can deal with + # returning the response. For plain ASGI apps, just return the response. + if "app" in scope: + raise HTTPException(status_code=404) + else: + response = PlainTextResponse("Not Found", status_code=404) + await response(scope, receive, send) + + def url_path_for(self, __name: str, **path_params: typing.Any) -> URLPath: + for route in self.routes: + try: + return route.url_path_for(__name, **path_params) + except NoMatchFound: + pass + raise NoMatchFound(__name, path_params) + + async def startup(self) -> None: + """ + Run any `.on_startup` event handlers. + """ + for handler in self.on_startup: + if is_async_callable(handler): + await handler() + else: + handler() + + async def shutdown(self) -> None: + """ + Run any `.on_shutdown` event handlers. + """ + for handler in self.on_shutdown: + if is_async_callable(handler): + await handler() + else: + handler() + + async def lifespan(self, scope: Scope, receive: Receive, send: Send) -> None: + """ + Handle ASGI lifespan messages, which allows us to manage application + startup and shutdown events. + """ + started = False + app: typing.Any = scope.get("app") + await receive() + try: + async with self.lifespan_context(app) as maybe_state: + if maybe_state is not None: + if "state" not in scope: + raise RuntimeError( + 'The server does not support "state" in the lifespan scope.' + ) + scope["state"].update(maybe_state) + await send({"type": "lifespan.startup.complete"}) + started = True + await receive() + except BaseException: + exc_text = traceback.format_exc() + if started: + await send({"type": "lifespan.shutdown.failed", "message": exc_text}) + else: + await send({"type": "lifespan.startup.failed", "message": exc_text}) + raise + else: + await send({"type": "lifespan.shutdown.complete"}) + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + """ + The main entry point to the Router class. + """ + assert scope["type"] in ("http", "websocket", "lifespan") + + if "router" not in scope: + scope["router"] = self + + if scope["type"] == "lifespan": + await self.lifespan(scope, receive, send) + return + + partial = None + + for route in self.routes: + # Determine if any route matches the incoming scope, + # and hand over to the matching route if found. + match, child_scope = route.matches(scope) + if match == Match.FULL: + scope.update(child_scope) + await route.handle(scope, receive, send) + return + elif match == Match.PARTIAL and partial is None: + partial = route + partial_scope = child_scope + + if partial is not None: + #  Handle partial matches. These are cases where an endpoint is + # able to handle the request, but is not a preferred option. + # We use this in particular to deal with "405 Method Not Allowed". + scope.update(partial_scope) + await partial.handle(scope, receive, send) + return + + if scope["type"] == "http" and self.redirect_slashes and scope["path"] != "/": + redirect_scope = dict(scope) + if scope["path"].endswith("/"): + redirect_scope["path"] = redirect_scope["path"].rstrip("/") + else: + redirect_scope["path"] = redirect_scope["path"] + "/" + + for route in self.routes: + match, child_scope = route.matches(redirect_scope) + if match != Match.NONE: + redirect_url = URL(scope=redirect_scope) + response = RedirectResponse(url=str(redirect_url)) + await response(scope, receive, send) + return + + await self.default(scope, receive, send) + + def __eq__(self, other: typing.Any) -> bool: + return isinstance(other, Router) and self.routes == other.routes + + def mount( + self, path: str, app: ASGIApp, name: typing.Optional[str] = None + ) -> None: # pragma: nocover + route = Mount(path, app=app, name=name) + self.routes.append(route) + + def host( + self, host: str, app: ASGIApp, name: typing.Optional[str] = None + ) -> None: # pragma: no cover + route = Host(host, app=app, name=name) + self.routes.append(route) + + def add_route( + self, + path: str, + endpoint: typing.Callable, + methods: typing.Optional[typing.List[str]] = None, + name: typing.Optional[str] = None, + include_in_schema: bool = True, + ) -> None: # pragma: nocover + route = Route( + path, + endpoint=endpoint, + methods=methods, + name=name, + include_in_schema=include_in_schema, + ) + self.routes.append(route) + + def add_websocket_route( + self, path: str, endpoint: typing.Callable, name: typing.Optional[str] = None + ) -> None: # pragma: no cover + route = WebSocketRoute(path, endpoint=endpoint, name=name) + self.routes.append(route) + + def route( + self, + path: str, + methods: typing.Optional[typing.List[str]] = None, + name: typing.Optional[str] = None, + include_in_schema: bool = True, + ) -> typing.Callable: + """ + We no longer document this decorator style API, and its usage is discouraged. + Instead you should use the following approach: + + >>> routes = [Route(path, endpoint=...), ...] + >>> app = Starlette(routes=routes) + """ + warnings.warn( + "The `route` decorator is deprecated, and will be removed in version 1.0.0." + "Refer to https://www.starlette.io/routing/#http-routing for the recommended approach.", # noqa: E501 + DeprecationWarning, + ) + + def decorator(func: typing.Callable) -> typing.Callable: + self.add_route( + path, + func, + methods=methods, + name=name, + include_in_schema=include_in_schema, + ) + return func + + return decorator + + def websocket_route( + self, path: str, name: typing.Optional[str] = None + ) -> typing.Callable: + """ + We no longer document this decorator style API, and its usage is discouraged. + Instead you should use the following approach: + + >>> routes = [WebSocketRoute(path, endpoint=...), ...] + >>> app = Starlette(routes=routes) + """ + warnings.warn( + "The `websocket_route` decorator is deprecated, and will be removed in version 1.0.0. Refer to " # noqa: E501 + "https://www.starlette.io/routing/#websocket-routing for the recommended approach.", # noqa: E501 + DeprecationWarning, + ) + + def decorator(func: typing.Callable) -> typing.Callable: + self.add_websocket_route(path, func, name=name) + return func + + return decorator + + def add_event_handler( + self, event_type: str, func: typing.Callable + ) -> None: # pragma: no cover + assert event_type in ("startup", "shutdown") + + if event_type == "startup": + self.on_startup.append(func) + else: + self.on_shutdown.append(func) + + def on_event(self, event_type: str) -> typing.Callable: + warnings.warn( + "The `on_event` decorator is deprecated, and will be removed in version 1.0.0. " # noqa: E501 + "Refer to https://www.starlette.io/lifespan/ for recommended approach.", + DeprecationWarning, + ) + + def decorator(func: typing.Callable) -> typing.Callable: + self.add_event_handler(event_type, func) + return func + + return decorator diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/schemas.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/schemas.py new file mode 100644 index 0000000..f939cb5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/schemas.py @@ -0,0 +1,145 @@ +import inspect +import re +import typing + +from starlette.requests import Request +from starlette.responses import Response +from starlette.routing import BaseRoute, Mount, Route + +try: + import yaml +except ModuleNotFoundError: # pragma: nocover + yaml = None # type: ignore[assignment] + + +class OpenAPIResponse(Response): + media_type = "application/vnd.oai.openapi" + + def render(self, content: typing.Any) -> bytes: + assert yaml is not None, "`pyyaml` must be installed to use OpenAPIResponse." + assert isinstance( + content, dict + ), "The schema passed to OpenAPIResponse should be a dictionary." + return yaml.dump(content, default_flow_style=False).encode("utf-8") + + +class EndpointInfo(typing.NamedTuple): + path: str + http_method: str + func: typing.Callable + + +class BaseSchemaGenerator: + def get_schema(self, routes: typing.List[BaseRoute]) -> dict: + raise NotImplementedError() # pragma: no cover + + def get_endpoints( + self, routes: typing.List[BaseRoute] + ) -> typing.List[EndpointInfo]: + """ + Given the routes, yields the following information: + + - path + eg: /users/ + - http_method + one of 'get', 'post', 'put', 'patch', 'delete', 'options' + - func + method ready to extract the docstring + """ + endpoints_info: list = [] + + for route in routes: + if isinstance(route, Mount): + path = self._remove_converter(route.path) + routes = route.routes or [] + sub_endpoints = [ + EndpointInfo( + path="".join((path, sub_endpoint.path)), + http_method=sub_endpoint.http_method, + func=sub_endpoint.func, + ) + for sub_endpoint in self.get_endpoints(routes) + ] + endpoints_info.extend(sub_endpoints) + + elif not isinstance(route, Route) or not route.include_in_schema: + continue + + elif inspect.isfunction(route.endpoint) or inspect.ismethod(route.endpoint): + path = self._remove_converter(route.path) + for method in route.methods or ["GET"]: + if method == "HEAD": + continue + endpoints_info.append( + EndpointInfo(path, method.lower(), route.endpoint) + ) + else: + path = self._remove_converter(route.path) + for method in ["get", "post", "put", "patch", "delete", "options"]: + if not hasattr(route.endpoint, method): + continue + func = getattr(route.endpoint, method) + endpoints_info.append(EndpointInfo(path, method.lower(), func)) + + return endpoints_info + + def _remove_converter(self, path: str) -> str: + """ + Remove the converter from the path. + For example, a route like this: + Route("/users/{id:int}", endpoint=get_user, methods=["GET"]) + Should be represented as `/users/{id}` in the OpenAPI schema. + """ + return re.sub(r":\w+}", "}", path) + + def parse_docstring(self, func_or_method: typing.Callable) -> dict: + """ + Given a function, parse the docstring as YAML and return a dictionary of info. + """ + docstring = func_or_method.__doc__ + if not docstring: + return {} + + assert yaml is not None, "`pyyaml` must be installed to use parse_docstring." + + # We support having regular docstrings before the schema + # definition. Here we return just the schema part from + # the docstring. + docstring = docstring.split("---")[-1] + + parsed = yaml.safe_load(docstring) + + if not isinstance(parsed, dict): + # A regular docstring (not yaml formatted) can return + # a simple string here, which wouldn't follow the schema. + return {} + + return parsed + + def OpenAPIResponse(self, request: Request) -> Response: + routes = request.app.routes + schema = self.get_schema(routes=routes) + return OpenAPIResponse(schema) + + +class SchemaGenerator(BaseSchemaGenerator): + def __init__(self, base_schema: dict) -> None: + self.base_schema = base_schema + + def get_schema(self, routes: typing.List[BaseRoute]) -> dict: + schema = dict(self.base_schema) + schema.setdefault("paths", {}) + endpoints_info = self.get_endpoints(routes) + + for endpoint in endpoints_info: + parsed = self.parse_docstring(endpoint.func) + + if not parsed: + continue + + if endpoint.path not in schema["paths"]: + schema["paths"][endpoint.path] = {} + + schema["paths"][endpoint.path][endpoint.http_method] = parsed + + return schema diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/staticfiles.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/staticfiles.py new file mode 100644 index 0000000..4c85606 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/staticfiles.py @@ -0,0 +1,246 @@ +import importlib.util +import os +import stat +import typing +from email.utils import parsedate + +import anyio + +from starlette.datastructures import URL, Headers +from starlette.exceptions import HTTPException +from starlette.responses import FileResponse, RedirectResponse, Response +from starlette.types import Receive, Scope, Send + +PathLike = typing.Union[str, "os.PathLike[str]"] + + +class NotModifiedResponse(Response): + NOT_MODIFIED_HEADERS = ( + "cache-control", + "content-location", + "date", + "etag", + "expires", + "vary", + ) + + def __init__(self, headers: Headers): + super().__init__( + status_code=304, + headers={ + name: value + for name, value in headers.items() + if name in self.NOT_MODIFIED_HEADERS + }, + ) + + +class StaticFiles: + def __init__( + self, + *, + directory: typing.Optional[PathLike] = None, + packages: typing.Optional[ + typing.List[typing.Union[str, typing.Tuple[str, str]]] + ] = None, + html: bool = False, + check_dir: bool = True, + follow_symlink: bool = False, + ) -> None: + self.directory = directory + self.packages = packages + self.all_directories = self.get_directories(directory, packages) + self.html = html + self.config_checked = False + self.follow_symlink = follow_symlink + if check_dir and directory is not None and not os.path.isdir(directory): + raise RuntimeError(f"Directory '{directory}' does not exist") + + def get_directories( + self, + directory: typing.Optional[PathLike] = None, + packages: typing.Optional[ + typing.List[typing.Union[str, typing.Tuple[str, str]]] + ] = None, + ) -> typing.List[PathLike]: + """ + Given `directory` and `packages` arguments, return a list of all the + directories that should be used for serving static files from. + """ + directories = [] + if directory is not None: + directories.append(directory) + + for package in packages or []: + if isinstance(package, tuple): + package, statics_dir = package + else: + statics_dir = "statics" + spec = importlib.util.find_spec(package) + assert spec is not None, f"Package {package!r} could not be found." + assert spec.origin is not None, f"Package {package!r} could not be found." + package_directory = os.path.normpath( + os.path.join(spec.origin, "..", statics_dir) + ) + assert os.path.isdir( + package_directory + ), f"Directory '{statics_dir!r}' in package {package!r} could not be found." + directories.append(package_directory) + + return directories + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + """ + The ASGI entry point. + """ + assert scope["type"] == "http" + + if not self.config_checked: + await self.check_config() + self.config_checked = True + + path = self.get_path(scope) + response = await self.get_response(path, scope) + await response(scope, receive, send) + + def get_path(self, scope: Scope) -> str: + """ + Given the ASGI scope, return the `path` string to serve up, + with OS specific path separators, and any '..', '.' components removed. + """ + return os.path.normpath(os.path.join(*scope["path"].split("/"))) + + async def get_response(self, path: str, scope: Scope) -> Response: + """ + Returns an HTTP response, given the incoming path, method and request headers. + """ + if scope["method"] not in ("GET", "HEAD"): + raise HTTPException(status_code=405) + + try: + full_path, stat_result = await anyio.to_thread.run_sync( + self.lookup_path, path + ) + except PermissionError: + raise HTTPException(status_code=401) + except OSError: + raise + + if stat_result and stat.S_ISREG(stat_result.st_mode): + # We have a static file to serve. + return self.file_response(full_path, stat_result, scope) + + elif stat_result and stat.S_ISDIR(stat_result.st_mode) and self.html: + # We're in HTML mode, and have got a directory URL. + # Check if we have 'index.html' file to serve. + index_path = os.path.join(path, "index.html") + full_path, stat_result = await anyio.to_thread.run_sync( + self.lookup_path, index_path + ) + if stat_result is not None and stat.S_ISREG(stat_result.st_mode): + if not scope["path"].endswith("/"): + # Directory URLs should redirect to always end in "/". + url = URL(scope=scope) + url = url.replace(path=url.path + "/") + return RedirectResponse(url=url) + return self.file_response(full_path, stat_result, scope) + + if self.html: + # Check for '404.html' if we're in HTML mode. + full_path, stat_result = await anyio.to_thread.run_sync( + self.lookup_path, "404.html" + ) + if stat_result and stat.S_ISREG(stat_result.st_mode): + return FileResponse( + full_path, + stat_result=stat_result, + method=scope["method"], + status_code=404, + ) + raise HTTPException(status_code=404) + + def lookup_path( + self, path: str + ) -> typing.Tuple[str, typing.Optional[os.stat_result]]: + for directory in self.all_directories: + joined_path = os.path.join(directory, path) + if self.follow_symlink: + full_path = os.path.abspath(joined_path) + else: + full_path = os.path.realpath(joined_path) + directory = os.path.realpath(directory) + if os.path.commonpath([full_path, directory]) != directory: + # Don't allow misbehaving clients to break out of the static files + # directory. + continue + try: + return full_path, os.stat(full_path) + except (FileNotFoundError, NotADirectoryError): + continue + return "", None + + def file_response( + self, + full_path: PathLike, + stat_result: os.stat_result, + scope: Scope, + status_code: int = 200, + ) -> Response: + method = scope["method"] + request_headers = Headers(scope=scope) + + response = FileResponse( + full_path, status_code=status_code, stat_result=stat_result, method=method + ) + if self.is_not_modified(response.headers, request_headers): + return NotModifiedResponse(response.headers) + return response + + async def check_config(self) -> None: + """ + Perform a one-off configuration check that StaticFiles is actually + pointed at a directory, so that we can raise loud errors rather than + just returning 404 responses. + """ + if self.directory is None: + return + + try: + stat_result = await anyio.to_thread.run_sync(os.stat, self.directory) + except FileNotFoundError: + raise RuntimeError( + f"StaticFiles directory '{self.directory}' does not exist." + ) + if not (stat.S_ISDIR(stat_result.st_mode) or stat.S_ISLNK(stat_result.st_mode)): + raise RuntimeError( + f"StaticFiles path '{self.directory}' is not a directory." + ) + + def is_not_modified( + self, response_headers: Headers, request_headers: Headers + ) -> bool: + """ + Given the request and response headers, return `True` if an HTTP + "Not Modified" response could be returned instead. + """ + try: + if_none_match = request_headers["if-none-match"] + etag = response_headers["etag"] + if if_none_match == etag: + return True + except KeyError: + pass + + try: + if_modified_since = parsedate(request_headers["if-modified-since"]) + last_modified = parsedate(response_headers["last-modified"]) + if ( + if_modified_since is not None + and last_modified is not None + and if_modified_since >= last_modified + ): + return True + except KeyError: + pass + + return False diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/status.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/status.py new file mode 100644 index 0000000..1689328 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/status.py @@ -0,0 +1,199 @@ +""" +HTTP codes +See HTTP Status Code Registry: +https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml + +And RFC 2324 - https://tools.ietf.org/html/rfc2324 +""" +import warnings +from typing import List + +__all__ = ( + "HTTP_100_CONTINUE", + "HTTP_101_SWITCHING_PROTOCOLS", + "HTTP_102_PROCESSING", + "HTTP_103_EARLY_HINTS", + "HTTP_200_OK", + "HTTP_201_CREATED", + "HTTP_202_ACCEPTED", + "HTTP_203_NON_AUTHORITATIVE_INFORMATION", + "HTTP_204_NO_CONTENT", + "HTTP_205_RESET_CONTENT", + "HTTP_206_PARTIAL_CONTENT", + "HTTP_207_MULTI_STATUS", + "HTTP_208_ALREADY_REPORTED", + "HTTP_226_IM_USED", + "HTTP_300_MULTIPLE_CHOICES", + "HTTP_301_MOVED_PERMANENTLY", + "HTTP_302_FOUND", + "HTTP_303_SEE_OTHER", + "HTTP_304_NOT_MODIFIED", + "HTTP_305_USE_PROXY", + "HTTP_306_RESERVED", + "HTTP_307_TEMPORARY_REDIRECT", + "HTTP_308_PERMANENT_REDIRECT", + "HTTP_400_BAD_REQUEST", + "HTTP_401_UNAUTHORIZED", + "HTTP_402_PAYMENT_REQUIRED", + "HTTP_403_FORBIDDEN", + "HTTP_404_NOT_FOUND", + "HTTP_405_METHOD_NOT_ALLOWED", + "HTTP_406_NOT_ACCEPTABLE", + "HTTP_407_PROXY_AUTHENTICATION_REQUIRED", + "HTTP_408_REQUEST_TIMEOUT", + "HTTP_409_CONFLICT", + "HTTP_410_GONE", + "HTTP_411_LENGTH_REQUIRED", + "HTTP_412_PRECONDITION_FAILED", + "HTTP_413_REQUEST_ENTITY_TOO_LARGE", + "HTTP_414_REQUEST_URI_TOO_LONG", + "HTTP_415_UNSUPPORTED_MEDIA_TYPE", + "HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE", + "HTTP_417_EXPECTATION_FAILED", + "HTTP_418_IM_A_TEAPOT", + "HTTP_421_MISDIRECTED_REQUEST", + "HTTP_422_UNPROCESSABLE_ENTITY", + "HTTP_423_LOCKED", + "HTTP_424_FAILED_DEPENDENCY", + "HTTP_425_TOO_EARLY", + "HTTP_426_UPGRADE_REQUIRED", + "HTTP_428_PRECONDITION_REQUIRED", + "HTTP_429_TOO_MANY_REQUESTS", + "HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE", + "HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS", + "HTTP_500_INTERNAL_SERVER_ERROR", + "HTTP_501_NOT_IMPLEMENTED", + "HTTP_502_BAD_GATEWAY", + "HTTP_503_SERVICE_UNAVAILABLE", + "HTTP_504_GATEWAY_TIMEOUT", + "HTTP_505_HTTP_VERSION_NOT_SUPPORTED", + "HTTP_506_VARIANT_ALSO_NEGOTIATES", + "HTTP_507_INSUFFICIENT_STORAGE", + "HTTP_508_LOOP_DETECTED", + "HTTP_510_NOT_EXTENDED", + "HTTP_511_NETWORK_AUTHENTICATION_REQUIRED", + "WS_1000_NORMAL_CLOSURE", + "WS_1001_GOING_AWAY", + "WS_1002_PROTOCOL_ERROR", + "WS_1003_UNSUPPORTED_DATA", + "WS_1005_NO_STATUS_RCVD", + "WS_1006_ABNORMAL_CLOSURE", + "WS_1007_INVALID_FRAME_PAYLOAD_DATA", + "WS_1008_POLICY_VIOLATION", + "WS_1009_MESSAGE_TOO_BIG", + "WS_1010_MANDATORY_EXT", + "WS_1011_INTERNAL_ERROR", + "WS_1012_SERVICE_RESTART", + "WS_1013_TRY_AGAIN_LATER", + "WS_1014_BAD_GATEWAY", + "WS_1015_TLS_HANDSHAKE", +) + +HTTP_100_CONTINUE = 100 +HTTP_101_SWITCHING_PROTOCOLS = 101 +HTTP_102_PROCESSING = 102 +HTTP_103_EARLY_HINTS = 103 +HTTP_200_OK = 200 +HTTP_201_CREATED = 201 +HTTP_202_ACCEPTED = 202 +HTTP_203_NON_AUTHORITATIVE_INFORMATION = 203 +HTTP_204_NO_CONTENT = 204 +HTTP_205_RESET_CONTENT = 205 +HTTP_206_PARTIAL_CONTENT = 206 +HTTP_207_MULTI_STATUS = 207 +HTTP_208_ALREADY_REPORTED = 208 +HTTP_226_IM_USED = 226 +HTTP_300_MULTIPLE_CHOICES = 300 +HTTP_301_MOVED_PERMANENTLY = 301 +HTTP_302_FOUND = 302 +HTTP_303_SEE_OTHER = 303 +HTTP_304_NOT_MODIFIED = 304 +HTTP_305_USE_PROXY = 305 +HTTP_306_RESERVED = 306 +HTTP_307_TEMPORARY_REDIRECT = 307 +HTTP_308_PERMANENT_REDIRECT = 308 +HTTP_400_BAD_REQUEST = 400 +HTTP_401_UNAUTHORIZED = 401 +HTTP_402_PAYMENT_REQUIRED = 402 +HTTP_403_FORBIDDEN = 403 +HTTP_404_NOT_FOUND = 404 +HTTP_405_METHOD_NOT_ALLOWED = 405 +HTTP_406_NOT_ACCEPTABLE = 406 +HTTP_407_PROXY_AUTHENTICATION_REQUIRED = 407 +HTTP_408_REQUEST_TIMEOUT = 408 +HTTP_409_CONFLICT = 409 +HTTP_410_GONE = 410 +HTTP_411_LENGTH_REQUIRED = 411 +HTTP_412_PRECONDITION_FAILED = 412 +HTTP_413_REQUEST_ENTITY_TOO_LARGE = 413 +HTTP_414_REQUEST_URI_TOO_LONG = 414 +HTTP_415_UNSUPPORTED_MEDIA_TYPE = 415 +HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE = 416 +HTTP_417_EXPECTATION_FAILED = 417 +HTTP_418_IM_A_TEAPOT = 418 +HTTP_421_MISDIRECTED_REQUEST = 421 +HTTP_422_UNPROCESSABLE_ENTITY = 422 +HTTP_423_LOCKED = 423 +HTTP_424_FAILED_DEPENDENCY = 424 +HTTP_425_TOO_EARLY = 425 +HTTP_426_UPGRADE_REQUIRED = 426 +HTTP_428_PRECONDITION_REQUIRED = 428 +HTTP_429_TOO_MANY_REQUESTS = 429 +HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE = 431 +HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS = 451 +HTTP_500_INTERNAL_SERVER_ERROR = 500 +HTTP_501_NOT_IMPLEMENTED = 501 +HTTP_502_BAD_GATEWAY = 502 +HTTP_503_SERVICE_UNAVAILABLE = 503 +HTTP_504_GATEWAY_TIMEOUT = 504 +HTTP_505_HTTP_VERSION_NOT_SUPPORTED = 505 +HTTP_506_VARIANT_ALSO_NEGOTIATES = 506 +HTTP_507_INSUFFICIENT_STORAGE = 507 +HTTP_508_LOOP_DETECTED = 508 +HTTP_510_NOT_EXTENDED = 510 +HTTP_511_NETWORK_AUTHENTICATION_REQUIRED = 511 + + +""" +WebSocket codes +https://www.iana.org/assignments/websocket/websocket.xml#close-code-number +https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent +""" +WS_1000_NORMAL_CLOSURE = 1000 +WS_1001_GOING_AWAY = 1001 +WS_1002_PROTOCOL_ERROR = 1002 +WS_1003_UNSUPPORTED_DATA = 1003 +WS_1005_NO_STATUS_RCVD = 1005 +WS_1006_ABNORMAL_CLOSURE = 1006 +WS_1007_INVALID_FRAME_PAYLOAD_DATA = 1007 +WS_1008_POLICY_VIOLATION = 1008 +WS_1009_MESSAGE_TOO_BIG = 1009 +WS_1010_MANDATORY_EXT = 1010 +WS_1011_INTERNAL_ERROR = 1011 +WS_1012_SERVICE_RESTART = 1012 +WS_1013_TRY_AGAIN_LATER = 1013 +WS_1014_BAD_GATEWAY = 1014 +WS_1015_TLS_HANDSHAKE = 1015 + + +__deprecated__ = {"WS_1004_NO_STATUS_RCVD": 1004, "WS_1005_ABNORMAL_CLOSURE": 1005} + + +def __getattr__(name: str) -> int: + deprecation_changes = { + "WS_1004_NO_STATUS_RCVD": "WS_1005_NO_STATUS_RCVD", + "WS_1005_ABNORMAL_CLOSURE": "WS_1006_ABNORMAL_CLOSURE", + } + deprecated = __deprecated__.get(name) + if deprecated: + warnings.warn( + f"'{name}' is deprecated. Use '{deprecation_changes[name]}' instead.", + category=DeprecationWarning, + stacklevel=3, + ) + return deprecated + raise AttributeError(f"module '{__name__}' has no attribute '{name}'") + + +def __dir__() -> List[str]: + return sorted(list(__all__) + list(__deprecated__.keys())) # pragma: no cover diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/templating.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/templating.py new file mode 100644 index 0000000..7df8f6d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/templating.py @@ -0,0 +1,120 @@ +import typing +from os import PathLike + +from starlette.background import BackgroundTask +from starlette.datastructures import URL +from starlette.requests import Request +from starlette.responses import Response +from starlette.types import Receive, Scope, Send + +try: + import jinja2 + + # @contextfunction was renamed to @pass_context in Jinja 3.0, and was removed in 3.1 + # hence we try to get pass_context (most installs will be >=3.1) + # and fall back to contextfunction, + # adding a type ignore for mypy to let us access an attribute that may not exist + if hasattr(jinja2, "pass_context"): + pass_context = jinja2.pass_context + else: # pragma: nocover + pass_context = jinja2.contextfunction # type: ignore[attr-defined] +except ModuleNotFoundError: # pragma: nocover + jinja2 = None # type: ignore[assignment] + + +class _TemplateResponse(Response): + media_type = "text/html" + + def __init__( + self, + template: typing.Any, + context: dict, + status_code: int = 200, + headers: typing.Optional[typing.Mapping[str, str]] = None, + media_type: typing.Optional[str] = None, + background: typing.Optional[BackgroundTask] = None, + ): + self.template = template + self.context = context + content = template.render(context) + super().__init__(content, status_code, headers, media_type, background) + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + request = self.context.get("request", {}) + extensions = request.get("extensions", {}) + if "http.response.debug" in extensions: + await send( + { + "type": "http.response.debug", + "info": { + "template": self.template, + "context": self.context, + }, + } + ) + await super().__call__(scope, receive, send) + + +class Jinja2Templates: + """ + templates = Jinja2Templates("templates") + + return templates.TemplateResponse("index.html", {"request": request}) + """ + + def __init__( + self, + directory: typing.Union[str, PathLike], + context_processors: typing.Optional[ + typing.List[typing.Callable[[Request], typing.Dict[str, typing.Any]]] + ] = None, + **env_options: typing.Any, + ) -> None: + assert jinja2 is not None, "jinja2 must be installed to use Jinja2Templates" + self.env = self._create_env(directory, **env_options) + self.context_processors = context_processors or [] + + def _create_env( + self, directory: typing.Union[str, PathLike], **env_options: typing.Any + ) -> "jinja2.Environment": + @pass_context + def url_for(context: dict, name: str, **path_params: typing.Any) -> URL: + request = context["request"] + return request.url_for(name, **path_params) + + loader = jinja2.FileSystemLoader(directory) + env_options.setdefault("loader", loader) + env_options.setdefault("autoescape", True) + + env = jinja2.Environment(**env_options) + env.globals["url_for"] = url_for + return env + + def get_template(self, name: str) -> "jinja2.Template": + return self.env.get_template(name) + + def TemplateResponse( + self, + name: str, + context: dict, + status_code: int = 200, + headers: typing.Optional[typing.Mapping[str, str]] = None, + media_type: typing.Optional[str] = None, + background: typing.Optional[BackgroundTask] = None, + ) -> _TemplateResponse: + if "request" not in context: + raise ValueError('context must include a "request" key') + + request = typing.cast(Request, context["request"]) + for context_processor in self.context_processors: + context.update(context_processor(request)) + + template = self.get_template(name) + return _TemplateResponse( + template, + context, + status_code=status_code, + headers=headers, + media_type=media_type, + background=background, + ) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/testclient.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/testclient.py new file mode 100644 index 0000000..a66b901 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/testclient.py @@ -0,0 +1,797 @@ +import contextlib +import inspect +import io +import json +import math +import queue +import sys +import typing +import warnings +from concurrent.futures import Future +from types import GeneratorType +from urllib.parse import unquote, urljoin + +import anyio +import anyio.from_thread +import httpx +from anyio.streams.stapled import StapledObjectStream + +from starlette._utils import is_async_callable +from starlette.types import ASGIApp, Message, Receive, Scope, Send +from starlette.websockets import WebSocketDisconnect + +if sys.version_info >= (3, 8): # pragma: no cover + from typing import TypedDict +else: # pragma: no cover + from typing_extensions import TypedDict + +_PortalFactoryType = typing.Callable[ + [], typing.ContextManager[anyio.abc.BlockingPortal] +] + +ASGIInstance = typing.Callable[[Receive, Send], typing.Awaitable[None]] +ASGI2App = typing.Callable[[Scope], ASGIInstance] +ASGI3App = typing.Callable[[Scope, Receive, Send], typing.Awaitable[None]] + + +_RequestData = typing.Mapping[str, typing.Union[str, typing.Iterable[str]]] + + +def _is_asgi3(app: typing.Union[ASGI2App, ASGI3App]) -> bool: + if inspect.isclass(app): + return hasattr(app, "__await__") + return is_async_callable(app) + + +class _WrapASGI2: + """ + Provide an ASGI3 interface onto an ASGI2 app. + """ + + def __init__(self, app: ASGI2App) -> None: + self.app = app + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + instance = self.app(scope) + await instance(receive, send) + + +class _AsyncBackend(TypedDict): + backend: str + backend_options: typing.Dict[str, typing.Any] + + +class _Upgrade(Exception): + def __init__(self, session: "WebSocketTestSession") -> None: + self.session = session + + +class WebSocketTestSession: + def __init__( + self, + app: ASGI3App, + scope: Scope, + portal_factory: _PortalFactoryType, + ) -> None: + self.app = app + self.scope = scope + self.accepted_subprotocol = None + self.portal_factory = portal_factory + self._receive_queue: "queue.Queue[typing.Any]" = queue.Queue() + self._send_queue: "queue.Queue[typing.Any]" = queue.Queue() + self.extra_headers = None + + def __enter__(self) -> "WebSocketTestSession": + self.exit_stack = contextlib.ExitStack() + self.portal = self.exit_stack.enter_context(self.portal_factory()) + + try: + _: "Future[None]" = self.portal.start_task_soon(self._run) + self.send({"type": "websocket.connect"}) + message = self.receive() + self._raise_on_close(message) + except Exception: + self.exit_stack.close() + raise + self.accepted_subprotocol = message.get("subprotocol", None) + self.extra_headers = message.get("headers", None) + return self + + def __exit__(self, *args: typing.Any) -> None: + try: + self.close(1000) + finally: + self.exit_stack.close() + while not self._send_queue.empty(): + message = self._send_queue.get() + if isinstance(message, BaseException): + raise message + + async def _run(self) -> None: + """ + The sub-thread in which the websocket session runs. + """ + scope = self.scope + receive = self._asgi_receive + send = self._asgi_send + try: + await self.app(scope, receive, send) + except BaseException as exc: + self._send_queue.put(exc) + raise + + async def _asgi_receive(self) -> Message: + while self._receive_queue.empty(): + await anyio.sleep(0) + return self._receive_queue.get() + + async def _asgi_send(self, message: Message) -> None: + self._send_queue.put(message) + + def _raise_on_close(self, message: Message) -> None: + if message["type"] == "websocket.close": + raise WebSocketDisconnect( + message.get("code", 1000), message.get("reason", "") + ) + + def send(self, message: Message) -> None: + self._receive_queue.put(message) + + def send_text(self, data: str) -> None: + self.send({"type": "websocket.receive", "text": data}) + + def send_bytes(self, data: bytes) -> None: + self.send({"type": "websocket.receive", "bytes": data}) + + def send_json(self, data: typing.Any, mode: str = "text") -> None: + assert mode in ["text", "binary"] + text = json.dumps(data, separators=(",", ":")) + if mode == "text": + self.send({"type": "websocket.receive", "text": text}) + else: + self.send({"type": "websocket.receive", "bytes": text.encode("utf-8")}) + + def close(self, code: int = 1000) -> None: + self.send({"type": "websocket.disconnect", "code": code}) + + def receive(self) -> Message: + message = self._send_queue.get() + if isinstance(message, BaseException): + raise message + return message + + def receive_text(self) -> str: + message = self.receive() + self._raise_on_close(message) + return message["text"] + + def receive_bytes(self) -> bytes: + message = self.receive() + self._raise_on_close(message) + return message["bytes"] + + def receive_json(self, mode: str = "text") -> typing.Any: + assert mode in ["text", "binary"] + message = self.receive() + self._raise_on_close(message) + if mode == "text": + text = message["text"] + else: + text = message["bytes"].decode("utf-8") + return json.loads(text) + + +class _TestClientTransport(httpx.BaseTransport): + def __init__( + self, + app: ASGI3App, + portal_factory: _PortalFactoryType, + raise_server_exceptions: bool = True, + root_path: str = "", + *, + app_state: typing.Dict[str, typing.Any], + ) -> None: + self.app = app + self.raise_server_exceptions = raise_server_exceptions + self.root_path = root_path + self.portal_factory = portal_factory + self.app_state = app_state + + def handle_request(self, request: httpx.Request) -> httpx.Response: + scheme = request.url.scheme + netloc = request.url.netloc.decode(encoding="ascii") + path = request.url.path + raw_path = request.url.raw_path + query = request.url.query.decode(encoding="ascii") + + default_port = {"http": 80, "ws": 80, "https": 443, "wss": 443}[scheme] + + if ":" in netloc: + host, port_string = netloc.split(":", 1) + port = int(port_string) + else: + host = netloc + port = default_port + + # Include the 'host' header. + if "host" in request.headers: + headers: typing.List[typing.Tuple[bytes, bytes]] = [] + elif port == default_port: # pragma: no cover + headers = [(b"host", host.encode())] + else: # pragma: no cover + headers = [(b"host", (f"{host}:{port}").encode())] + + # Include other request headers. + headers += [ + (key.lower().encode(), value.encode()) + for key, value in request.headers.items() + ] + + scope: typing.Dict[str, typing.Any] + + if scheme in {"ws", "wss"}: + subprotocol = request.headers.get("sec-websocket-protocol", None) + if subprotocol is None: + subprotocols: typing.Sequence[str] = [] + else: + subprotocols = [value.strip() for value in subprotocol.split(",")] + scope = { + "type": "websocket", + "path": unquote(path), + "raw_path": raw_path, + "root_path": self.root_path, + "scheme": scheme, + "query_string": query.encode(), + "headers": headers, + "client": ["testclient", 50000], + "server": [host, port], + "subprotocols": subprotocols, + "state": self.app_state.copy(), + } + session = WebSocketTestSession(self.app, scope, self.portal_factory) + raise _Upgrade(session) + + scope = { + "type": "http", + "http_version": "1.1", + "method": request.method, + "path": unquote(path), + "raw_path": raw_path, + "root_path": self.root_path, + "scheme": scheme, + "query_string": query.encode(), + "headers": headers, + "client": ["testclient", 50000], + "server": [host, port], + "extensions": {"http.response.debug": {}}, + "state": self.app_state.copy(), + } + + request_complete = False + response_started = False + response_complete: anyio.Event + raw_kwargs: typing.Dict[str, typing.Any] = {"stream": io.BytesIO()} + template = None + context = None + + async def receive() -> Message: + nonlocal request_complete + + if request_complete: + if not response_complete.is_set(): + await response_complete.wait() + return {"type": "http.disconnect"} + + body = request.read() + if isinstance(body, str): + body_bytes: bytes = body.encode("utf-8") # pragma: no cover + elif body is None: + body_bytes = b"" # pragma: no cover + elif isinstance(body, GeneratorType): + try: # pragma: no cover + chunk = body.send(None) + if isinstance(chunk, str): + chunk = chunk.encode("utf-8") + return {"type": "http.request", "body": chunk, "more_body": True} + except StopIteration: # pragma: no cover + request_complete = True + return {"type": "http.request", "body": b""} + else: + body_bytes = body + + request_complete = True + return {"type": "http.request", "body": body_bytes} + + async def send(message: Message) -> None: + nonlocal raw_kwargs, response_started, template, context + + if message["type"] == "http.response.start": + assert ( + not response_started + ), 'Received multiple "http.response.start" messages.' + raw_kwargs["status_code"] = message["status"] + raw_kwargs["headers"] = [ + (key.decode(), value.decode()) + for key, value in message.get("headers", []) + ] + response_started = True + elif message["type"] == "http.response.body": + assert ( + response_started + ), 'Received "http.response.body" without "http.response.start".' + assert ( + not response_complete.is_set() + ), 'Received "http.response.body" after response completed.' + body = message.get("body", b"") + more_body = message.get("more_body", False) + if request.method != "HEAD": + raw_kwargs["stream"].write(body) + if not more_body: + raw_kwargs["stream"].seek(0) + response_complete.set() + elif message["type"] == "http.response.debug": + template = message["info"]["template"] + context = message["info"]["context"] + + try: + with self.portal_factory() as portal: + response_complete = portal.call(anyio.Event) + portal.call(self.app, scope, receive, send) + except BaseException as exc: + if self.raise_server_exceptions: + raise exc + + if self.raise_server_exceptions: + assert response_started, "TestClient did not receive any response." + elif not response_started: + raw_kwargs = { + "status_code": 500, + "headers": [], + "stream": io.BytesIO(), + } + + raw_kwargs["stream"] = httpx.ByteStream(raw_kwargs["stream"].read()) + + response = httpx.Response(**raw_kwargs, request=request) + if template is not None: + response.template = template # type: ignore[attr-defined] + response.context = context # type: ignore[attr-defined] + return response + + +class TestClient(httpx.Client): + __test__ = False + task: "Future[None]" + portal: typing.Optional[anyio.abc.BlockingPortal] = None + + def __init__( + self, + app: ASGIApp, + base_url: str = "http://testserver", + raise_server_exceptions: bool = True, + root_path: str = "", + backend: str = "asyncio", + backend_options: typing.Optional[typing.Dict[str, typing.Any]] = None, + cookies: httpx._client.CookieTypes = None, + headers: typing.Dict[str, str] = None, + ) -> None: + self.async_backend = _AsyncBackend( + backend=backend, backend_options=backend_options or {} + ) + if _is_asgi3(app): + app = typing.cast(ASGI3App, app) + asgi_app = app + else: + app = typing.cast(ASGI2App, app) # type: ignore[assignment] + asgi_app = _WrapASGI2(app) # type: ignore[arg-type] + self.app = asgi_app + self.app_state: typing.Dict[str, typing.Any] = {} + transport = _TestClientTransport( + self.app, + portal_factory=self._portal_factory, + raise_server_exceptions=raise_server_exceptions, + root_path=root_path, + app_state=self.app_state, + ) + if headers is None: + headers = {} + headers.setdefault("user-agent", "testclient") + super().__init__( + app=self.app, + base_url=base_url, + headers=headers, + transport=transport, + follow_redirects=True, + cookies=cookies, + ) + + @contextlib.contextmanager + def _portal_factory(self) -> typing.Generator[anyio.abc.BlockingPortal, None, None]: + if self.portal is not None: + yield self.portal + else: + with anyio.from_thread.start_blocking_portal( + **self.async_backend + ) as portal: + yield portal + + def _choose_redirect_arg( + self, + follow_redirects: typing.Optional[bool], + allow_redirects: typing.Optional[bool], + ) -> typing.Union[bool, httpx._client.UseClientDefault]: + redirect: typing.Union[ + bool, httpx._client.UseClientDefault + ] = httpx._client.USE_CLIENT_DEFAULT + if allow_redirects is not None: + message = ( + "The `allow_redirects` argument is deprecated. " + "Use `follow_redirects` instead." + ) + warnings.warn(message, DeprecationWarning) + redirect = allow_redirects + if follow_redirects is not None: + redirect = follow_redirects + elif allow_redirects is not None and follow_redirects is not None: + raise RuntimeError( # pragma: no cover + "Cannot use both `allow_redirects` and `follow_redirects`." + ) + return redirect + + def request( # type: ignore[override] + self, + method: str, + url: httpx._types.URLTypes, + *, + content: typing.Optional[httpx._types.RequestContent] = None, + data: typing.Optional[_RequestData] = None, + files: typing.Optional[httpx._types.RequestFiles] = None, + json: typing.Any = None, + params: typing.Optional[httpx._types.QueryParamTypes] = None, + headers: typing.Optional[httpx._types.HeaderTypes] = None, + cookies: typing.Optional[httpx._types.CookieTypes] = None, + auth: typing.Union[ + httpx._types.AuthTypes, httpx._client.UseClientDefault + ] = httpx._client.USE_CLIENT_DEFAULT, + follow_redirects: typing.Optional[bool] = None, + allow_redirects: typing.Optional[bool] = None, + timeout: typing.Union[ + httpx._client.TimeoutTypes, httpx._client.UseClientDefault + ] = httpx._client.USE_CLIENT_DEFAULT, + extensions: typing.Optional[typing.Dict[str, typing.Any]] = None, + ) -> httpx.Response: + url = self.base_url.join(url) + redirect = self._choose_redirect_arg(follow_redirects, allow_redirects) + return super().request( + method, + url, + content=content, + data=data, # type: ignore[arg-type] + files=files, + json=json, + params=params, + headers=headers, + cookies=cookies, + auth=auth, + follow_redirects=redirect, + timeout=timeout, + extensions=extensions, + ) + + def get( # type: ignore[override] + self, + url: httpx._types.URLTypes, + *, + params: typing.Optional[httpx._types.QueryParamTypes] = None, + headers: typing.Optional[httpx._types.HeaderTypes] = None, + cookies: typing.Optional[httpx._types.CookieTypes] = None, + auth: typing.Union[ + httpx._types.AuthTypes, httpx._client.UseClientDefault + ] = httpx._client.USE_CLIENT_DEFAULT, + follow_redirects: typing.Optional[bool] = None, + allow_redirects: typing.Optional[bool] = None, + timeout: typing.Union[ + httpx._client.TimeoutTypes, httpx._client.UseClientDefault + ] = httpx._client.USE_CLIENT_DEFAULT, + extensions: typing.Optional[typing.Dict[str, typing.Any]] = None, + ) -> httpx.Response: + redirect = self._choose_redirect_arg(follow_redirects, allow_redirects) + return super().get( + url, + params=params, + headers=headers, + cookies=cookies, + auth=auth, + follow_redirects=redirect, + timeout=timeout, + extensions=extensions, + ) + + def options( # type: ignore[override] + self, + url: httpx._types.URLTypes, + *, + params: typing.Optional[httpx._types.QueryParamTypes] = None, + headers: typing.Optional[httpx._types.HeaderTypes] = None, + cookies: typing.Optional[httpx._types.CookieTypes] = None, + auth: typing.Union[ + httpx._types.AuthTypes, httpx._client.UseClientDefault + ] = httpx._client.USE_CLIENT_DEFAULT, + follow_redirects: typing.Optional[bool] = None, + allow_redirects: typing.Optional[bool] = None, + timeout: typing.Union[ + httpx._client.TimeoutTypes, httpx._client.UseClientDefault + ] = httpx._client.USE_CLIENT_DEFAULT, + extensions: typing.Optional[typing.Dict[str, typing.Any]] = None, + ) -> httpx.Response: + redirect = self._choose_redirect_arg(follow_redirects, allow_redirects) + return super().options( + url, + params=params, + headers=headers, + cookies=cookies, + auth=auth, + follow_redirects=redirect, + timeout=timeout, + extensions=extensions, + ) + + def head( # type: ignore[override] + self, + url: httpx._types.URLTypes, + *, + params: typing.Optional[httpx._types.QueryParamTypes] = None, + headers: typing.Optional[httpx._types.HeaderTypes] = None, + cookies: typing.Optional[httpx._types.CookieTypes] = None, + auth: typing.Union[ + httpx._types.AuthTypes, httpx._client.UseClientDefault + ] = httpx._client.USE_CLIENT_DEFAULT, + follow_redirects: typing.Optional[bool] = None, + allow_redirects: typing.Optional[bool] = None, + timeout: typing.Union[ + httpx._client.TimeoutTypes, httpx._client.UseClientDefault + ] = httpx._client.USE_CLIENT_DEFAULT, + extensions: typing.Optional[typing.Dict[str, typing.Any]] = None, + ) -> httpx.Response: + redirect = self._choose_redirect_arg(follow_redirects, allow_redirects) + return super().head( + url, + params=params, + headers=headers, + cookies=cookies, + auth=auth, + follow_redirects=redirect, + timeout=timeout, + extensions=extensions, + ) + + def post( # type: ignore[override] + self, + url: httpx._types.URLTypes, + *, + content: typing.Optional[httpx._types.RequestContent] = None, + data: typing.Optional[_RequestData] = None, + files: typing.Optional[httpx._types.RequestFiles] = None, + json: typing.Any = None, + params: typing.Optional[httpx._types.QueryParamTypes] = None, + headers: typing.Optional[httpx._types.HeaderTypes] = None, + cookies: typing.Optional[httpx._types.CookieTypes] = None, + auth: typing.Union[ + httpx._types.AuthTypes, httpx._client.UseClientDefault + ] = httpx._client.USE_CLIENT_DEFAULT, + follow_redirects: typing.Optional[bool] = None, + allow_redirects: typing.Optional[bool] = None, + timeout: typing.Union[ + httpx._client.TimeoutTypes, httpx._client.UseClientDefault + ] = httpx._client.USE_CLIENT_DEFAULT, + extensions: typing.Optional[typing.Dict[str, typing.Any]] = None, + ) -> httpx.Response: + redirect = self._choose_redirect_arg(follow_redirects, allow_redirects) + return super().post( + url, + content=content, + data=data, # type: ignore[arg-type] + files=files, + json=json, + params=params, + headers=headers, + cookies=cookies, + auth=auth, + follow_redirects=redirect, + timeout=timeout, + extensions=extensions, + ) + + def put( # type: ignore[override] + self, + url: httpx._types.URLTypes, + *, + content: typing.Optional[httpx._types.RequestContent] = None, + data: typing.Optional[_RequestData] = None, + files: typing.Optional[httpx._types.RequestFiles] = None, + json: typing.Any = None, + params: typing.Optional[httpx._types.QueryParamTypes] = None, + headers: typing.Optional[httpx._types.HeaderTypes] = None, + cookies: typing.Optional[httpx._types.CookieTypes] = None, + auth: typing.Union[ + httpx._types.AuthTypes, httpx._client.UseClientDefault + ] = httpx._client.USE_CLIENT_DEFAULT, + follow_redirects: typing.Optional[bool] = None, + allow_redirects: typing.Optional[bool] = None, + timeout: typing.Union[ + httpx._client.TimeoutTypes, httpx._client.UseClientDefault + ] = httpx._client.USE_CLIENT_DEFAULT, + extensions: typing.Optional[typing.Dict[str, typing.Any]] = None, + ) -> httpx.Response: + redirect = self._choose_redirect_arg(follow_redirects, allow_redirects) + return super().put( + url, + content=content, + data=data, # type: ignore[arg-type] + files=files, + json=json, + params=params, + headers=headers, + cookies=cookies, + auth=auth, + follow_redirects=redirect, + timeout=timeout, + extensions=extensions, + ) + + def patch( # type: ignore[override] + self, + url: httpx._types.URLTypes, + *, + content: typing.Optional[httpx._types.RequestContent] = None, + data: typing.Optional[_RequestData] = None, + files: typing.Optional[httpx._types.RequestFiles] = None, + json: typing.Any = None, + params: typing.Optional[httpx._types.QueryParamTypes] = None, + headers: typing.Optional[httpx._types.HeaderTypes] = None, + cookies: typing.Optional[httpx._types.CookieTypes] = None, + auth: typing.Union[ + httpx._types.AuthTypes, httpx._client.UseClientDefault + ] = httpx._client.USE_CLIENT_DEFAULT, + follow_redirects: typing.Optional[bool] = None, + allow_redirects: typing.Optional[bool] = None, + timeout: typing.Union[ + httpx._client.TimeoutTypes, httpx._client.UseClientDefault + ] = httpx._client.USE_CLIENT_DEFAULT, + extensions: typing.Optional[typing.Dict[str, typing.Any]] = None, + ) -> httpx.Response: + redirect = self._choose_redirect_arg(follow_redirects, allow_redirects) + return super().patch( + url, + content=content, + data=data, # type: ignore[arg-type] + files=files, + json=json, + params=params, + headers=headers, + cookies=cookies, + auth=auth, + follow_redirects=redirect, + timeout=timeout, + extensions=extensions, + ) + + def delete( # type: ignore[override] + self, + url: httpx._types.URLTypes, + *, + params: typing.Optional[httpx._types.QueryParamTypes] = None, + headers: typing.Optional[httpx._types.HeaderTypes] = None, + cookies: typing.Optional[httpx._types.CookieTypes] = None, + auth: typing.Union[ + httpx._types.AuthTypes, httpx._client.UseClientDefault + ] = httpx._client.USE_CLIENT_DEFAULT, + follow_redirects: typing.Optional[bool] = None, + allow_redirects: typing.Optional[bool] = None, + timeout: typing.Union[ + httpx._client.TimeoutTypes, httpx._client.UseClientDefault + ] = httpx._client.USE_CLIENT_DEFAULT, + extensions: typing.Optional[typing.Dict[str, typing.Any]] = None, + ) -> httpx.Response: + redirect = self._choose_redirect_arg(follow_redirects, allow_redirects) + return super().delete( + url, + params=params, + headers=headers, + cookies=cookies, + auth=auth, + follow_redirects=redirect, + timeout=timeout, + extensions=extensions, + ) + + def websocket_connect( + self, url: str, subprotocols: typing.Sequence[str] = None, **kwargs: typing.Any + ) -> typing.Any: + url = urljoin("ws://testserver", url) + headers = kwargs.get("headers", {}) + headers.setdefault("connection", "upgrade") + headers.setdefault("sec-websocket-key", "testserver==") + headers.setdefault("sec-websocket-version", "13") + if subprotocols is not None: + headers.setdefault("sec-websocket-protocol", ", ".join(subprotocols)) + kwargs["headers"] = headers + try: + super().request("GET", url, **kwargs) + except _Upgrade as exc: + session = exc.session + else: + raise RuntimeError("Expected WebSocket upgrade") # pragma: no cover + + return session + + def __enter__(self) -> "TestClient": + with contextlib.ExitStack() as stack: + self.portal = portal = stack.enter_context( + anyio.from_thread.start_blocking_portal(**self.async_backend) + ) + + @stack.callback + def reset_portal() -> None: + self.portal = None + + self.stream_send = StapledObjectStream( + *anyio.create_memory_object_stream(math.inf) + ) + self.stream_receive = StapledObjectStream( + *anyio.create_memory_object_stream(math.inf) + ) + self.task = portal.start_task_soon(self.lifespan) + portal.call(self.wait_startup) + + @stack.callback + def wait_shutdown() -> None: + portal.call(self.wait_shutdown) + + self.exit_stack = stack.pop_all() + + return self + + def __exit__(self, *args: typing.Any) -> None: + self.exit_stack.close() + + async def lifespan(self) -> None: + scope = {"type": "lifespan", "state": self.app_state} + try: + await self.app(scope, self.stream_receive.receive, self.stream_send.send) + finally: + await self.stream_send.send(None) + + async def wait_startup(self) -> None: + await self.stream_receive.send({"type": "lifespan.startup"}) + + async def receive() -> typing.Any: + message = await self.stream_send.receive() + if message is None: + self.task.result() + return message + + message = await receive() + assert message["type"] in ( + "lifespan.startup.complete", + "lifespan.startup.failed", + ) + if message["type"] == "lifespan.startup.failed": + await receive() + + async def wait_shutdown(self) -> None: + async def receive() -> typing.Any: + message = await self.stream_send.receive() + if message is None: + self.task.result() + return message + + async with self.stream_send: + await self.stream_receive.send({"type": "lifespan.shutdown"}) + message = await receive() + assert message["type"] in ( + "lifespan.shutdown.complete", + "lifespan.shutdown.failed", + ) + if message["type"] == "lifespan.shutdown.failed": + await receive() diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/types.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/types.py new file mode 100644 index 0000000..713d18a --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/types.py @@ -0,0 +1,17 @@ +import typing + +AppType = typing.TypeVar("AppType") + +Scope = typing.MutableMapping[str, typing.Any] +Message = typing.MutableMapping[str, typing.Any] + +Receive = typing.Callable[[], typing.Awaitable[Message]] +Send = typing.Callable[[Message], typing.Awaitable[None]] + +ASGIApp = typing.Callable[[Scope, Receive, Send], typing.Awaitable[None]] + +StatelessLifespan = typing.Callable[[AppType], typing.AsyncContextManager[None]] +StatefulLifespan = typing.Callable[ + [AppType], typing.AsyncContextManager[typing.Mapping[str, typing.Any]] +] +Lifespan = typing.Union[StatelessLifespan[AppType], StatefulLifespan[AppType]] diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/websockets.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/websockets.py new file mode 100644 index 0000000..5aa4118 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/starlette/websockets.py @@ -0,0 +1,193 @@ +import enum +import json +import typing + +from starlette.requests import HTTPConnection +from starlette.types import Message, Receive, Scope, Send + + +class WebSocketState(enum.Enum): + CONNECTING = 0 + CONNECTED = 1 + DISCONNECTED = 2 + + +class WebSocketDisconnect(Exception): + def __init__(self, code: int = 1000, reason: typing.Optional[str] = None) -> None: + self.code = code + self.reason = reason or "" + + +class WebSocket(HTTPConnection): + def __init__(self, scope: Scope, receive: Receive, send: Send) -> None: + super().__init__(scope) + assert scope["type"] == "websocket" + self._receive = receive + self._send = send + self.client_state = WebSocketState.CONNECTING + self.application_state = WebSocketState.CONNECTING + + async def receive(self) -> Message: + """ + Receive ASGI websocket messages, ensuring valid state transitions. + """ + if self.client_state == WebSocketState.CONNECTING: + message = await self._receive() + message_type = message["type"] + if message_type != "websocket.connect": + raise RuntimeError( + 'Expected ASGI message "websocket.connect", ' + f"but got {message_type!r}" + ) + self.client_state = WebSocketState.CONNECTED + return message + elif self.client_state == WebSocketState.CONNECTED: + message = await self._receive() + message_type = message["type"] + if message_type not in {"websocket.receive", "websocket.disconnect"}: + raise RuntimeError( + 'Expected ASGI message "websocket.receive" or ' + f'"websocket.disconnect", but got {message_type!r}' + ) + if message_type == "websocket.disconnect": + self.client_state = WebSocketState.DISCONNECTED + return message + else: + raise RuntimeError( + 'Cannot call "receive" once a disconnect message has been received.' + ) + + async def send(self, message: Message) -> None: + """ + Send ASGI websocket messages, ensuring valid state transitions. + """ + if self.application_state == WebSocketState.CONNECTING: + message_type = message["type"] + if message_type not in {"websocket.accept", "websocket.close"}: + raise RuntimeError( + 'Expected ASGI message "websocket.accept" or ' + f'"websocket.close", but got {message_type!r}' + ) + if message_type == "websocket.close": + self.application_state = WebSocketState.DISCONNECTED + else: + self.application_state = WebSocketState.CONNECTED + await self._send(message) + elif self.application_state == WebSocketState.CONNECTED: + message_type = message["type"] + if message_type not in {"websocket.send", "websocket.close"}: + raise RuntimeError( + 'Expected ASGI message "websocket.send" or "websocket.close", ' + f"but got {message_type!r}" + ) + if message_type == "websocket.close": + self.application_state = WebSocketState.DISCONNECTED + await self._send(message) + else: + raise RuntimeError('Cannot call "send" once a close message has been sent.') + + async def accept( + self, + subprotocol: typing.Optional[str] = None, + headers: typing.Optional[typing.Iterable[typing.Tuple[bytes, bytes]]] = None, + ) -> None: + headers = headers or [] + + if self.client_state == WebSocketState.CONNECTING: + # If we haven't yet seen the 'connect' message, then wait for it first. + await self.receive() + await self.send( + {"type": "websocket.accept", "subprotocol": subprotocol, "headers": headers} + ) + + def _raise_on_disconnect(self, message: Message) -> None: + if message["type"] == "websocket.disconnect": + raise WebSocketDisconnect(message["code"]) + + async def receive_text(self) -> str: + if self.application_state != WebSocketState.CONNECTED: + raise RuntimeError( + 'WebSocket is not connected. Need to call "accept" first.' + ) + message = await self.receive() + self._raise_on_disconnect(message) + return message["text"] + + async def receive_bytes(self) -> bytes: + if self.application_state != WebSocketState.CONNECTED: + raise RuntimeError( + 'WebSocket is not connected. Need to call "accept" first.' + ) + message = await self.receive() + self._raise_on_disconnect(message) + return message["bytes"] + + async def receive_json(self, mode: str = "text") -> typing.Any: + if mode not in {"text", "binary"}: + raise RuntimeError('The "mode" argument should be "text" or "binary".') + if self.application_state != WebSocketState.CONNECTED: + raise RuntimeError( + 'WebSocket is not connected. Need to call "accept" first.' + ) + message = await self.receive() + self._raise_on_disconnect(message) + + if mode == "text": + text = message["text"] + else: + text = message["bytes"].decode("utf-8") + return json.loads(text) + + async def iter_text(self) -> typing.AsyncIterator[str]: + try: + while True: + yield await self.receive_text() + except WebSocketDisconnect: + pass + + async def iter_bytes(self) -> typing.AsyncIterator[bytes]: + try: + while True: + yield await self.receive_bytes() + except WebSocketDisconnect: + pass + + async def iter_json(self) -> typing.AsyncIterator[typing.Any]: + try: + while True: + yield await self.receive_json() + except WebSocketDisconnect: + pass + + async def send_text(self, data: str) -> None: + await self.send({"type": "websocket.send", "text": data}) + + async def send_bytes(self, data: bytes) -> None: + await self.send({"type": "websocket.send", "bytes": data}) + + async def send_json(self, data: typing.Any, mode: str = "text") -> None: + if mode not in {"text", "binary"}: + raise RuntimeError('The "mode" argument should be "text" or "binary".') + text = json.dumps(data, separators=(",", ":")) + if mode == "text": + await self.send({"type": "websocket.send", "text": text}) + else: + await self.send({"type": "websocket.send", "bytes": text.encode("utf-8")}) + + async def close( + self, code: int = 1000, reason: typing.Optional[str] = None + ) -> None: + await self.send( + {"type": "websocket.close", "code": code, "reason": reason or ""} + ) + + +class WebSocketClose: + def __init__(self, code: int = 1000, reason: typing.Optional[str] = None) -> None: + self.code = code + self.reason = reason or "" + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + await send( + {"type": "websocket.close", "code": self.code, "reason": self.reason} + ) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/typing_extensions-4.15.0.dist-info/INSTALLER b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/typing_extensions-4.15.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/typing_extensions-4.15.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/typing_extensions-4.15.0.dist-info/METADATA b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/typing_extensions-4.15.0.dist-info/METADATA new file mode 100644 index 0000000..b09cb50 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/typing_extensions-4.15.0.dist-info/METADATA @@ -0,0 +1,72 @@ +Metadata-Version: 2.4 +Name: typing_extensions +Version: 4.15.0 +Summary: Backported and Experimental Type Hints for Python 3.9+ +Keywords: annotations,backport,checker,checking,function,hinting,hints,type,typechecking,typehinting,typehints,typing +Author-email: "Guido van Rossum, Jukka Lehtosalo, Łukasz Langa, Michael Lee" +Requires-Python: >=3.9 +Description-Content-Type: text/markdown +License-Expression: PSF-2.0 +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Console +Classifier: Intended Audience :: Developers +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 +Classifier: Programming Language :: Python :: 3.14 +Classifier: Topic :: Software Development +License-File: LICENSE +Project-URL: Bug Tracker, https://github.com/python/typing_extensions/issues +Project-URL: Changes, https://github.com/python/typing_extensions/blob/main/CHANGELOG.md +Project-URL: Documentation, https://typing-extensions.readthedocs.io/ +Project-URL: Home, https://github.com/python/typing_extensions +Project-URL: Q & A, https://github.com/python/typing/discussions +Project-URL: Repository, https://github.com/python/typing_extensions + +# Typing Extensions + +[![Chat at https://gitter.im/python/typing](https://badges.gitter.im/python/typing.svg)](https://gitter.im/python/typing) + +[Documentation](https://typing-extensions.readthedocs.io/en/latest/#) – +[PyPI](https://pypi.org/project/typing-extensions/) + +## Overview + +The `typing_extensions` module serves two related purposes: + +- Enable use of new type system features on older Python versions. For example, + `typing.TypeGuard` is new in Python 3.10, but `typing_extensions` allows + users on previous Python versions to use it too. +- Enable experimentation with new type system PEPs before they are accepted and + added to the `typing` module. + +`typing_extensions` is treated specially by static type checkers such as +mypy and pyright. Objects defined in `typing_extensions` are treated the same +way as equivalent forms in `typing`. + +`typing_extensions` uses +[Semantic Versioning](https://semver.org/). The +major version will be incremented only for backwards-incompatible changes. +Therefore, it's safe to depend +on `typing_extensions` like this: `typing_extensions ~=x.y`, +where `x.y` is the first version that includes all features you need. +[This](https://packaging.python.org/en/latest/specifications/version-specifiers/#compatible-release) +is equivalent to `typing_extensions >=x.y, <(x+1)`. Do not depend on `~= x.y.z` +unless you really know what you're doing; that defeats the purpose of +semantic versioning. + +## Included items + +See [the documentation](https://typing-extensions.readthedocs.io/en/latest/#) for a +complete listing of module contents. + +## Contributing + +See [CONTRIBUTING.md](https://github.com/python/typing_extensions/blob/main/CONTRIBUTING.md) +for how to contribute to `typing_extensions`. + diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/typing_extensions-4.15.0.dist-info/RECORD b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/typing_extensions-4.15.0.dist-info/RECORD new file mode 100644 index 0000000..b3527e5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/typing_extensions-4.15.0.dist-info/RECORD @@ -0,0 +1,6 @@ +typing_extensions-4.15.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +typing_extensions-4.15.0.dist-info/METADATA,sha256=wTg3j-jxiTSsmd4GBTXFPsbBOu7WXpTDJkHafuMZKnI,3259 +typing_extensions-4.15.0.dist-info/RECORD,, +typing_extensions-4.15.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82 +typing_extensions-4.15.0.dist-info/licenses/LICENSE,sha256=Oy-B_iHRgcSZxZolbI4ZaEVdZonSaaqFNzv7avQdo78,13936 +typing_extensions.py,sha256=Qz0R0XDTok0usGXrwb_oSM6n49fOaFZ6tSvqLUwvftg,160429 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/typing_extensions-4.15.0.dist-info/WHEEL b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/typing_extensions-4.15.0.dist-info/WHEEL new file mode 100644 index 0000000..d8b9936 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/typing_extensions-4.15.0.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.12.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/typing_extensions-4.15.0.dist-info/licenses/LICENSE b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/typing_extensions-4.15.0.dist-info/licenses/LICENSE new file mode 100644 index 0000000..f26bcf4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/typing_extensions-4.15.0.dist-info/licenses/LICENSE @@ -0,0 +1,279 @@ +A. HISTORY OF THE SOFTWARE +========================== + +Python was created in the early 1990s by Guido van Rossum at Stichting +Mathematisch Centrum (CWI, see https://www.cwi.nl) in the Netherlands +as a successor of a language called ABC. Guido remains Python's +principal author, although it includes many contributions from others. + +In 1995, Guido continued his work on Python at the Corporation for +National Research Initiatives (CNRI, see https://www.cnri.reston.va.us) +in Reston, Virginia where he released several versions of the +software. + +In May 2000, Guido and the Python core development team moved to +BeOpen.com to form the BeOpen PythonLabs team. In October of the same +year, the PythonLabs team moved to Digital Creations, which became +Zope Corporation. In 2001, the Python Software Foundation (PSF, see +https://www.python.org/psf/) was formed, a non-profit organization +created specifically to own Python-related Intellectual Property. +Zope Corporation was a sponsoring member of the PSF. + +All Python releases are Open Source (see https://opensource.org for +the Open Source Definition). Historically, most, but not all, Python +releases have also been GPL-compatible; the table below summarizes +the various releases. + + Release Derived Year Owner GPL- + from compatible? (1) + + 0.9.0 thru 1.2 1991-1995 CWI yes + 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes + 1.6 1.5.2 2000 CNRI no + 2.0 1.6 2000 BeOpen.com no + 1.6.1 1.6 2001 CNRI yes (2) + 2.1 2.0+1.6.1 2001 PSF no + 2.0.1 2.0+1.6.1 2001 PSF yes + 2.1.1 2.1+2.0.1 2001 PSF yes + 2.1.2 2.1.1 2002 PSF yes + 2.1.3 2.1.2 2002 PSF yes + 2.2 and above 2.1.1 2001-now PSF yes + +Footnotes: + +(1) GPL-compatible doesn't mean that we're distributing Python under + the GPL. All Python licenses, unlike the GPL, let you distribute + a modified version without making your changes open source. The + GPL-compatible licenses make it possible to combine Python with + other software that is released under the GPL; the others don't. + +(2) According to Richard Stallman, 1.6.1 is not GPL-compatible, + because its license has a choice of law clause. According to + CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1 + is "not incompatible" with the GPL. + +Thanks to the many outside volunteers who have worked under Guido's +direction to make these releases possible. + + +B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON +=============================================================== + +Python software and documentation are licensed under the +Python Software Foundation License Version 2. + +Starting with Python 3.8.6, examples, recipes, and other code in +the documentation are dual licensed under the PSF License Version 2 +and the Zero-Clause BSD license. + +Some software incorporated into Python is under different licenses. +The licenses are listed with code falling under that license. + + +PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 +-------------------------------------------- + +1. This LICENSE AGREEMENT is between the Python Software Foundation +("PSF"), and the Individual or Organization ("Licensee") accessing and +otherwise using this software ("Python") in source or binary form and +its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, PSF hereby +grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, +analyze, test, perform and/or display publicly, prepare derivative works, +distribute, and otherwise use Python alone or in any derivative version, +provided, however, that PSF's License Agreement and PSF's notice of copyright, +i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Python Software Foundation; +All Rights Reserved" are retained in Python alone or in any derivative version +prepared by Licensee. + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python. + +4. PSF is making Python available to Licensee on an "AS IS" +basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. Nothing in this License Agreement shall be deemed to create any +relationship of agency, partnership, or joint venture between PSF and +Licensee. This License Agreement does not grant permission to use PSF +trademarks or trade name in a trademark sense to endorse or promote +products or services of Licensee, or any third party. + +8. By copying, installing or otherwise using Python, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. + + +BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 +------------------------------------------- + +BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 + +1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an +office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the +Individual or Organization ("Licensee") accessing and otherwise using +this software in source or binary form and its associated +documentation ("the Software"). + +2. Subject to the terms and conditions of this BeOpen Python License +Agreement, BeOpen hereby grants Licensee a non-exclusive, +royalty-free, world-wide license to reproduce, analyze, test, perform +and/or display publicly, prepare derivative works, distribute, and +otherwise use the Software alone or in any derivative version, +provided, however, that the BeOpen Python License is retained in the +Software, alone or in any derivative version prepared by Licensee. + +3. BeOpen is making the Software available to Licensee on an "AS IS" +basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE +SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS +AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY +DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +5. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +6. This License Agreement shall be governed by and interpreted in all +respects by the law of the State of California, excluding conflict of +law provisions. Nothing in this License Agreement shall be deemed to +create any relationship of agency, partnership, or joint venture +between BeOpen and Licensee. This License Agreement does not grant +permission to use BeOpen trademarks or trade names in a trademark +sense to endorse or promote products or services of Licensee, or any +third party. As an exception, the "BeOpen Python" logos available at +http://www.pythonlabs.com/logos.html may be used according to the +permissions granted on that web page. + +7. By copying, installing or otherwise using the software, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. + + +CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 +--------------------------------------- + +1. This LICENSE AGREEMENT is between the Corporation for National +Research Initiatives, having an office at 1895 Preston White Drive, +Reston, VA 20191 ("CNRI"), and the Individual or Organization +("Licensee") accessing and otherwise using Python 1.6.1 software in +source or binary form and its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, CNRI +hereby grants Licensee a nonexclusive, royalty-free, world-wide +license to reproduce, analyze, test, perform and/or display publicly, +prepare derivative works, distribute, and otherwise use Python 1.6.1 +alone or in any derivative version, provided, however, that CNRI's +License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) +1995-2001 Corporation for National Research Initiatives; All Rights +Reserved" are retained in Python 1.6.1 alone or in any derivative +version prepared by Licensee. Alternately, in lieu of CNRI's License +Agreement, Licensee may substitute the following text (omitting the +quotes): "Python 1.6.1 is made available subject to the terms and +conditions in CNRI's License Agreement. This Agreement together with +Python 1.6.1 may be located on the internet using the following +unique, persistent identifier (known as a handle): 1895.22/1013. This +Agreement may also be obtained from a proxy server on the internet +using the following URL: http://hdl.handle.net/1895.22/1013". + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python 1.6.1 or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python 1.6.1. + +4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" +basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. This License Agreement shall be governed by the federal +intellectual property law of the United States, including without +limitation the federal copyright law, and, to the extent such +U.S. federal law does not apply, by the law of the Commonwealth of +Virginia, excluding Virginia's conflict of law provisions. +Notwithstanding the foregoing, with regard to derivative works based +on Python 1.6.1 that incorporate non-separable material that was +previously distributed under the GNU General Public License (GPL), the +law of the Commonwealth of Virginia shall govern this License +Agreement only as to issues arising under or with respect to +Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this +License Agreement shall be deemed to create any relationship of +agency, partnership, or joint venture between CNRI and Licensee. This +License Agreement does not grant permission to use CNRI trademarks or +trade name in a trademark sense to endorse or promote products or +services of Licensee, or any third party. + +8. By clicking on the "ACCEPT" button where indicated, or by copying, +installing or otherwise using Python 1.6.1, Licensee agrees to be +bound by the terms and conditions of this License Agreement. + + ACCEPT + + +CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 +-------------------------------------------------- + +Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, +The Netherlands. All rights reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +ZERO-CLAUSE BSD LICENSE FOR CODE IN THE PYTHON DOCUMENTATION +---------------------------------------------------------------------- + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/typing_extensions.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/typing_extensions.py new file mode 100644 index 0000000..77f33e1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/typing_extensions.py @@ -0,0 +1,4317 @@ +import abc +import builtins +import collections +import collections.abc +import contextlib +import enum +import functools +import inspect +import io +import keyword +import operator +import sys +import types as _types +import typing +import warnings + +# Breakpoint: https://github.com/python/cpython/pull/119891 +if sys.version_info >= (3, 14): + import annotationlib + +__all__ = [ + # Super-special typing primitives. + 'Any', + 'ClassVar', + 'Concatenate', + 'Final', + 'LiteralString', + 'ParamSpec', + 'ParamSpecArgs', + 'ParamSpecKwargs', + 'Self', + 'Type', + 'TypeVar', + 'TypeVarTuple', + 'Unpack', + + # ABCs (from collections.abc). + 'Awaitable', + 'AsyncIterator', + 'AsyncIterable', + 'Coroutine', + 'AsyncGenerator', + 'AsyncContextManager', + 'Buffer', + 'ChainMap', + + # Concrete collection types. + 'ContextManager', + 'Counter', + 'Deque', + 'DefaultDict', + 'NamedTuple', + 'OrderedDict', + 'TypedDict', + + # Structural checks, a.k.a. protocols. + 'SupportsAbs', + 'SupportsBytes', + 'SupportsComplex', + 'SupportsFloat', + 'SupportsIndex', + 'SupportsInt', + 'SupportsRound', + 'Reader', + 'Writer', + + # One-off things. + 'Annotated', + 'assert_never', + 'assert_type', + 'clear_overloads', + 'dataclass_transform', + 'deprecated', + 'disjoint_base', + 'Doc', + 'evaluate_forward_ref', + 'get_overloads', + 'final', + 'Format', + 'get_annotations', + 'get_args', + 'get_origin', + 'get_original_bases', + 'get_protocol_members', + 'get_type_hints', + 'IntVar', + 'is_protocol', + 'is_typeddict', + 'Literal', + 'NewType', + 'overload', + 'override', + 'Protocol', + 'Sentinel', + 'reveal_type', + 'runtime', + 'runtime_checkable', + 'Text', + 'TypeAlias', + 'TypeAliasType', + 'TypeForm', + 'TypeGuard', + 'TypeIs', + 'TYPE_CHECKING', + 'type_repr', + 'Never', + 'NoReturn', + 'ReadOnly', + 'Required', + 'NotRequired', + 'NoDefault', + 'NoExtraItems', + + # Pure aliases, have always been in typing + 'AbstractSet', + 'AnyStr', + 'BinaryIO', + 'Callable', + 'Collection', + 'Container', + 'Dict', + 'ForwardRef', + 'FrozenSet', + 'Generator', + 'Generic', + 'Hashable', + 'IO', + 'ItemsView', + 'Iterable', + 'Iterator', + 'KeysView', + 'List', + 'Mapping', + 'MappingView', + 'Match', + 'MutableMapping', + 'MutableSequence', + 'MutableSet', + 'Optional', + 'Pattern', + 'Reversible', + 'Sequence', + 'Set', + 'Sized', + 'TextIO', + 'Tuple', + 'Union', + 'ValuesView', + 'cast', + 'no_type_check', + 'no_type_check_decorator', +] + +# for backward compatibility +PEP_560 = True +GenericMeta = type +# Breakpoint: https://github.com/python/cpython/pull/116129 +_PEP_696_IMPLEMENTED = sys.version_info >= (3, 13, 0, "beta") + +# Added with bpo-45166 to 3.10.1+ and some 3.9 versions +_FORWARD_REF_HAS_CLASS = "__forward_is_class__" in typing.ForwardRef.__slots__ + +# The functions below are modified copies of typing internal helpers. +# They are needed by _ProtocolMeta and they provide support for PEP 646. + + +class _Sentinel: + def __repr__(self): + return "" + + +_marker = _Sentinel() + + +# Breakpoint: https://github.com/python/cpython/pull/27342 +if sys.version_info >= (3, 10): + def _should_collect_from_parameters(t): + return isinstance( + t, (typing._GenericAlias, _types.GenericAlias, _types.UnionType) + ) +else: + def _should_collect_from_parameters(t): + return isinstance(t, (typing._GenericAlias, _types.GenericAlias)) + + +NoReturn = typing.NoReturn + +# Some unconstrained type variables. These are used by the container types. +# (These are not for export.) +T = typing.TypeVar('T') # Any type. +KT = typing.TypeVar('KT') # Key type. +VT = typing.TypeVar('VT') # Value type. +T_co = typing.TypeVar('T_co', covariant=True) # Any type covariant containers. +T_contra = typing.TypeVar('T_contra', contravariant=True) # Ditto contravariant. + + +# Breakpoint: https://github.com/python/cpython/pull/31841 +if sys.version_info >= (3, 11): + from typing import Any +else: + + class _AnyMeta(type): + def __instancecheck__(self, obj): + if self is Any: + raise TypeError("typing_extensions.Any cannot be used with isinstance()") + return super().__instancecheck__(obj) + + def __repr__(self): + if self is Any: + return "typing_extensions.Any" + return super().__repr__() + + class Any(metaclass=_AnyMeta): + """Special type indicating an unconstrained type. + - Any is compatible with every type. + - Any assumed to have all methods. + - All values assumed to be instances of Any. + Note that all the above statements are true from the point of view of + static type checkers. At runtime, Any should not be used with instance + checks. + """ + def __new__(cls, *args, **kwargs): + if cls is Any: + raise TypeError("Any cannot be instantiated") + return super().__new__(cls, *args, **kwargs) + + +ClassVar = typing.ClassVar + +# Vendored from cpython typing._SpecialFrom +# Having a separate class means that instances will not be rejected by +# typing._type_check. +class _SpecialForm(typing._Final, _root=True): + __slots__ = ('_name', '__doc__', '_getitem') + + def __init__(self, getitem): + self._getitem = getitem + self._name = getitem.__name__ + self.__doc__ = getitem.__doc__ + + def __getattr__(self, item): + if item in {'__name__', '__qualname__'}: + return self._name + + raise AttributeError(item) + + def __mro_entries__(self, bases): + raise TypeError(f"Cannot subclass {self!r}") + + def __repr__(self): + return f'typing_extensions.{self._name}' + + def __reduce__(self): + return self._name + + def __call__(self, *args, **kwds): + raise TypeError(f"Cannot instantiate {self!r}") + + def __or__(self, other): + return typing.Union[self, other] + + def __ror__(self, other): + return typing.Union[other, self] + + def __instancecheck__(self, obj): + raise TypeError(f"{self} cannot be used with isinstance()") + + def __subclasscheck__(self, cls): + raise TypeError(f"{self} cannot be used with issubclass()") + + @typing._tp_cache + def __getitem__(self, parameters): + return self._getitem(self, parameters) + + +# Note that inheriting from this class means that the object will be +# rejected by typing._type_check, so do not use it if the special form +# is arguably valid as a type by itself. +class _ExtensionsSpecialForm(typing._SpecialForm, _root=True): + def __repr__(self): + return 'typing_extensions.' + self._name + + +Final = typing.Final + +# Breakpoint: https://github.com/python/cpython/pull/30530 +if sys.version_info >= (3, 11): + final = typing.final +else: + # @final exists in 3.8+, but we backport it for all versions + # before 3.11 to keep support for the __final__ attribute. + # See https://bugs.python.org/issue46342 + def final(f): + """This decorator can be used to indicate to type checkers that + the decorated method cannot be overridden, and decorated class + cannot be subclassed. For example: + + class Base: + @final + def done(self) -> None: + ... + class Sub(Base): + def done(self) -> None: # Error reported by type checker + ... + @final + class Leaf: + ... + class Other(Leaf): # Error reported by type checker + ... + + There is no runtime checking of these properties. The decorator + sets the ``__final__`` attribute to ``True`` on the decorated object + to allow runtime introspection. + """ + try: + f.__final__ = True + except (AttributeError, TypeError): + # Skip the attribute silently if it is not writable. + # AttributeError happens if the object has __slots__ or a + # read-only property, TypeError if it's a builtin class. + pass + return f + + +if hasattr(typing, "disjoint_base"): # 3.15 + disjoint_base = typing.disjoint_base +else: + def disjoint_base(cls): + """This decorator marks a class as a disjoint base. + + Child classes of a disjoint base cannot inherit from other disjoint bases that are + not parent classes of the disjoint base. + + For example: + + @disjoint_base + class Disjoint1: pass + + @disjoint_base + class Disjoint2: pass + + class Disjoint3(Disjoint1, Disjoint2): pass # Type checker error + + Type checkers can use knowledge of disjoint bases to detect unreachable code + and determine when two types can overlap. + + See PEP 800.""" + cls.__disjoint_base__ = True + return cls + + +def IntVar(name): + return typing.TypeVar(name) + + +# A Literal bug was fixed in 3.11.0, 3.10.1 and 3.9.8 +# Breakpoint: https://github.com/python/cpython/pull/29334 +if sys.version_info >= (3, 10, 1): + Literal = typing.Literal +else: + def _flatten_literal_params(parameters): + """An internal helper for Literal creation: flatten Literals among parameters""" + params = [] + for p in parameters: + if isinstance(p, _LiteralGenericAlias): + params.extend(p.__args__) + else: + params.append(p) + return tuple(params) + + def _value_and_type_iter(params): + for p in params: + yield p, type(p) + + class _LiteralGenericAlias(typing._GenericAlias, _root=True): + def __eq__(self, other): + if not isinstance(other, _LiteralGenericAlias): + return NotImplemented + these_args_deduped = set(_value_and_type_iter(self.__args__)) + other_args_deduped = set(_value_and_type_iter(other.__args__)) + return these_args_deduped == other_args_deduped + + def __hash__(self): + return hash(frozenset(_value_and_type_iter(self.__args__))) + + class _LiteralForm(_ExtensionsSpecialForm, _root=True): + def __init__(self, doc: str): + self._name = 'Literal' + self._doc = self.__doc__ = doc + + def __getitem__(self, parameters): + if not isinstance(parameters, tuple): + parameters = (parameters,) + + parameters = _flatten_literal_params(parameters) + + val_type_pairs = list(_value_and_type_iter(parameters)) + try: + deduped_pairs = set(val_type_pairs) + except TypeError: + # unhashable parameters + pass + else: + # similar logic to typing._deduplicate on Python 3.9+ + if len(deduped_pairs) < len(val_type_pairs): + new_parameters = [] + for pair in val_type_pairs: + if pair in deduped_pairs: + new_parameters.append(pair[0]) + deduped_pairs.remove(pair) + assert not deduped_pairs, deduped_pairs + parameters = tuple(new_parameters) + + return _LiteralGenericAlias(self, parameters) + + Literal = _LiteralForm(doc="""\ + A type that can be used to indicate to type checkers + that the corresponding value has a value literally equivalent + to the provided parameter. For example: + + var: Literal[4] = 4 + + The type checker understands that 'var' is literally equal to + the value 4 and no other value. + + Literal[...] cannot be subclassed. There is no runtime + checking verifying that the parameter is actually a value + instead of a type.""") + + +_overload_dummy = typing._overload_dummy + + +if hasattr(typing, "get_overloads"): # 3.11+ + overload = typing.overload + get_overloads = typing.get_overloads + clear_overloads = typing.clear_overloads +else: + # {module: {qualname: {firstlineno: func}}} + _overload_registry = collections.defaultdict( + functools.partial(collections.defaultdict, dict) + ) + + def overload(func): + """Decorator for overloaded functions/methods. + + In a stub file, place two or more stub definitions for the same + function in a row, each decorated with @overload. For example: + + @overload + def utf8(value: None) -> None: ... + @overload + def utf8(value: bytes) -> bytes: ... + @overload + def utf8(value: str) -> bytes: ... + + In a non-stub file (i.e. a regular .py file), do the same but + follow it with an implementation. The implementation should *not* + be decorated with @overload. For example: + + @overload + def utf8(value: None) -> None: ... + @overload + def utf8(value: bytes) -> bytes: ... + @overload + def utf8(value: str) -> bytes: ... + def utf8(value): + # implementation goes here + + The overloads for a function can be retrieved at runtime using the + get_overloads() function. + """ + # classmethod and staticmethod + f = getattr(func, "__func__", func) + try: + _overload_registry[f.__module__][f.__qualname__][ + f.__code__.co_firstlineno + ] = func + except AttributeError: + # Not a normal function; ignore. + pass + return _overload_dummy + + def get_overloads(func): + """Return all defined overloads for *func* as a sequence.""" + # classmethod and staticmethod + f = getattr(func, "__func__", func) + if f.__module__ not in _overload_registry: + return [] + mod_dict = _overload_registry[f.__module__] + if f.__qualname__ not in mod_dict: + return [] + return list(mod_dict[f.__qualname__].values()) + + def clear_overloads(): + """Clear all overloads in the registry.""" + _overload_registry.clear() + + +# This is not a real generic class. Don't use outside annotations. +Type = typing.Type + +# Various ABCs mimicking those in collections.abc. +# A few are simply re-exported for completeness. +Awaitable = typing.Awaitable +Coroutine = typing.Coroutine +AsyncIterable = typing.AsyncIterable +AsyncIterator = typing.AsyncIterator +Deque = typing.Deque +DefaultDict = typing.DefaultDict +OrderedDict = typing.OrderedDict +Counter = typing.Counter +ChainMap = typing.ChainMap +Text = typing.Text +TYPE_CHECKING = typing.TYPE_CHECKING + + +# Breakpoint: https://github.com/python/cpython/pull/118681 +if sys.version_info >= (3, 13, 0, "beta"): + from typing import AsyncContextManager, AsyncGenerator, ContextManager, Generator +else: + def _is_dunder(attr): + return attr.startswith('__') and attr.endswith('__') + + + class _SpecialGenericAlias(typing._SpecialGenericAlias, _root=True): + def __init__(self, origin, nparams, *, inst=True, name=None, defaults=()): + super().__init__(origin, nparams, inst=inst, name=name) + self._defaults = defaults + + def __setattr__(self, attr, val): + allowed_attrs = {'_name', '_inst', '_nparams', '_defaults'} + if _is_dunder(attr) or attr in allowed_attrs: + object.__setattr__(self, attr, val) + else: + setattr(self.__origin__, attr, val) + + @typing._tp_cache + def __getitem__(self, params): + if not isinstance(params, tuple): + params = (params,) + msg = "Parameters to generic types must be types." + params = tuple(typing._type_check(p, msg) for p in params) + if ( + self._defaults + and len(params) < self._nparams + and len(params) + len(self._defaults) >= self._nparams + ): + params = (*params, *self._defaults[len(params) - self._nparams:]) + actual_len = len(params) + + if actual_len != self._nparams: + if self._defaults: + expected = f"at least {self._nparams - len(self._defaults)}" + else: + expected = str(self._nparams) + if not self._nparams: + raise TypeError(f"{self} is not a generic class") + raise TypeError( + f"Too {'many' if actual_len > self._nparams else 'few'}" + f" arguments for {self};" + f" actual {actual_len}, expected {expected}" + ) + return self.copy_with(params) + + _NoneType = type(None) + Generator = _SpecialGenericAlias( + collections.abc.Generator, 3, defaults=(_NoneType, _NoneType) + ) + AsyncGenerator = _SpecialGenericAlias( + collections.abc.AsyncGenerator, 2, defaults=(_NoneType,) + ) + ContextManager = _SpecialGenericAlias( + contextlib.AbstractContextManager, + 2, + name="ContextManager", + defaults=(typing.Optional[bool],) + ) + AsyncContextManager = _SpecialGenericAlias( + contextlib.AbstractAsyncContextManager, + 2, + name="AsyncContextManager", + defaults=(typing.Optional[bool],) + ) + + +_PROTO_ALLOWLIST = { + 'collections.abc': [ + 'Callable', 'Awaitable', 'Iterable', 'Iterator', 'AsyncIterable', + 'Hashable', 'Sized', 'Container', 'Collection', 'Reversible', 'Buffer', + ], + 'contextlib': ['AbstractContextManager', 'AbstractAsyncContextManager'], + 'typing_extensions': ['Buffer'], +} + + +_EXCLUDED_ATTRS = frozenset(typing.EXCLUDED_ATTRIBUTES) | { + "__match_args__", "__protocol_attrs__", "__non_callable_proto_members__", + "__final__", +} + + +def _get_protocol_attrs(cls): + attrs = set() + for base in cls.__mro__[:-1]: # without object + if base.__name__ in {'Protocol', 'Generic'}: + continue + annotations = getattr(base, '__annotations__', {}) + for attr in (*base.__dict__, *annotations): + if (not attr.startswith('_abc_') and attr not in _EXCLUDED_ATTRS): + attrs.add(attr) + return attrs + + +def _caller(depth=1, default='__main__'): + try: + return sys._getframemodulename(depth + 1) or default + except AttributeError: # For platforms without _getframemodulename() + pass + try: + return sys._getframe(depth + 1).f_globals.get('__name__', default) + except (AttributeError, ValueError): # For platforms without _getframe() + pass + return None + + +# `__match_args__` attribute was removed from protocol members in 3.13, +# we want to backport this change to older Python versions. +# Breakpoint: https://github.com/python/cpython/pull/110683 +if sys.version_info >= (3, 13): + Protocol = typing.Protocol +else: + def _allow_reckless_class_checks(depth=2): + """Allow instance and class checks for special stdlib modules. + The abc and functools modules indiscriminately call isinstance() and + issubclass() on the whole MRO of a user class, which may contain protocols. + """ + return _caller(depth) in {'abc', 'functools', None} + + def _no_init(self, *args, **kwargs): + if type(self)._is_protocol: + raise TypeError('Protocols cannot be instantiated') + + def _type_check_issubclass_arg_1(arg): + """Raise TypeError if `arg` is not an instance of `type` + in `issubclass(arg, )`. + + In most cases, this is verified by type.__subclasscheck__. + Checking it again unnecessarily would slow down issubclass() checks, + so, we don't perform this check unless we absolutely have to. + + For various error paths, however, + we want to ensure that *this* error message is shown to the user + where relevant, rather than a typing.py-specific error message. + """ + if not isinstance(arg, type): + # Same error message as for issubclass(1, int). + raise TypeError('issubclass() arg 1 must be a class') + + # Inheriting from typing._ProtocolMeta isn't actually desirable, + # but is necessary to allow typing.Protocol and typing_extensions.Protocol + # to mix without getting TypeErrors about "metaclass conflict" + class _ProtocolMeta(type(typing.Protocol)): + # This metaclass is somewhat unfortunate, + # but is necessary for several reasons... + # + # NOTE: DO NOT call super() in any methods in this class + # That would call the methods on typing._ProtocolMeta on Python <=3.11 + # and those are slow + def __new__(mcls, name, bases, namespace, **kwargs): + if name == "Protocol" and len(bases) < 2: + pass + elif {Protocol, typing.Protocol} & set(bases): + for base in bases: + if not ( + base in {object, typing.Generic, Protocol, typing.Protocol} + or base.__name__ in _PROTO_ALLOWLIST.get(base.__module__, []) + or is_protocol(base) + ): + raise TypeError( + f"Protocols can only inherit from other protocols, " + f"got {base!r}" + ) + return abc.ABCMeta.__new__(mcls, name, bases, namespace, **kwargs) + + def __init__(cls, *args, **kwargs): + abc.ABCMeta.__init__(cls, *args, **kwargs) + if getattr(cls, "_is_protocol", False): + cls.__protocol_attrs__ = _get_protocol_attrs(cls) + + def __subclasscheck__(cls, other): + if cls is Protocol: + return type.__subclasscheck__(cls, other) + if ( + getattr(cls, '_is_protocol', False) + and not _allow_reckless_class_checks() + ): + if not getattr(cls, '_is_runtime_protocol', False): + _type_check_issubclass_arg_1(other) + raise TypeError( + "Instance and class checks can only be used with " + "@runtime_checkable protocols" + ) + if ( + # this attribute is set by @runtime_checkable: + cls.__non_callable_proto_members__ + and cls.__dict__.get("__subclasshook__") is _proto_hook + ): + _type_check_issubclass_arg_1(other) + non_method_attrs = sorted(cls.__non_callable_proto_members__) + raise TypeError( + "Protocols with non-method members don't support issubclass()." + f" Non-method members: {str(non_method_attrs)[1:-1]}." + ) + return abc.ABCMeta.__subclasscheck__(cls, other) + + def __instancecheck__(cls, instance): + # We need this method for situations where attributes are + # assigned in __init__. + if cls is Protocol: + return type.__instancecheck__(cls, instance) + if not getattr(cls, "_is_protocol", False): + # i.e., it's a concrete subclass of a protocol + return abc.ABCMeta.__instancecheck__(cls, instance) + + if ( + not getattr(cls, '_is_runtime_protocol', False) and + not _allow_reckless_class_checks() + ): + raise TypeError("Instance and class checks can only be used with" + " @runtime_checkable protocols") + + if abc.ABCMeta.__instancecheck__(cls, instance): + return True + + for attr in cls.__protocol_attrs__: + try: + val = inspect.getattr_static(instance, attr) + except AttributeError: + break + # this attribute is set by @runtime_checkable: + if val is None and attr not in cls.__non_callable_proto_members__: + break + else: + return True + + return False + + def __eq__(cls, other): + # Hack so that typing.Generic.__class_getitem__ + # treats typing_extensions.Protocol + # as equivalent to typing.Protocol + if abc.ABCMeta.__eq__(cls, other) is True: + return True + return cls is Protocol and other is typing.Protocol + + # This has to be defined, or the abc-module cache + # complains about classes with this metaclass being unhashable, + # if we define only __eq__! + def __hash__(cls) -> int: + return type.__hash__(cls) + + @classmethod + def _proto_hook(cls, other): + if not cls.__dict__.get('_is_protocol', False): + return NotImplemented + + for attr in cls.__protocol_attrs__: + for base in other.__mro__: + # Check if the members appears in the class dictionary... + if attr in base.__dict__: + if base.__dict__[attr] is None: + return NotImplemented + break + + # ...or in annotations, if it is a sub-protocol. + annotations = getattr(base, '__annotations__', {}) + if ( + isinstance(annotations, collections.abc.Mapping) + and attr in annotations + and is_protocol(other) + ): + break + else: + return NotImplemented + return True + + class Protocol(typing.Generic, metaclass=_ProtocolMeta): + __doc__ = typing.Protocol.__doc__ + __slots__ = () + _is_protocol = True + _is_runtime_protocol = False + + def __init_subclass__(cls, *args, **kwargs): + super().__init_subclass__(*args, **kwargs) + + # Determine if this is a protocol or a concrete subclass. + if not cls.__dict__.get('_is_protocol', False): + cls._is_protocol = any(b is Protocol for b in cls.__bases__) + + # Set (or override) the protocol subclass hook. + if '__subclasshook__' not in cls.__dict__: + cls.__subclasshook__ = _proto_hook + + # Prohibit instantiation for protocol classes + if cls._is_protocol and cls.__init__ is Protocol.__init__: + cls.__init__ = _no_init + + +# Breakpoint: https://github.com/python/cpython/pull/113401 +if sys.version_info >= (3, 13): + runtime_checkable = typing.runtime_checkable +else: + def runtime_checkable(cls): + """Mark a protocol class as a runtime protocol. + + Such protocol can be used with isinstance() and issubclass(). + Raise TypeError if applied to a non-protocol class. + This allows a simple-minded structural check very similar to + one trick ponies in collections.abc such as Iterable. + + For example:: + + @runtime_checkable + class Closable(Protocol): + def close(self): ... + + assert isinstance(open('/some/file'), Closable) + + Warning: this will check only the presence of the required methods, + not their type signatures! + """ + if not issubclass(cls, typing.Generic) or not getattr(cls, '_is_protocol', False): + raise TypeError(f'@runtime_checkable can be only applied to protocol classes,' + f' got {cls!r}') + cls._is_runtime_protocol = True + + # typing.Protocol classes on <=3.11 break if we execute this block, + # because typing.Protocol classes on <=3.11 don't have a + # `__protocol_attrs__` attribute, and this block relies on the + # `__protocol_attrs__` attribute. Meanwhile, typing.Protocol classes on 3.12.2+ + # break if we *don't* execute this block, because *they* assume that all + # protocol classes have a `__non_callable_proto_members__` attribute + # (which this block sets) + if isinstance(cls, _ProtocolMeta) or sys.version_info >= (3, 12, 2): + # PEP 544 prohibits using issubclass() + # with protocols that have non-method members. + # See gh-113320 for why we compute this attribute here, + # rather than in `_ProtocolMeta.__init__` + cls.__non_callable_proto_members__ = set() + for attr in cls.__protocol_attrs__: + try: + is_callable = callable(getattr(cls, attr, None)) + except Exception as e: + raise TypeError( + f"Failed to determine whether protocol member {attr!r} " + "is a method member" + ) from e + else: + if not is_callable: + cls.__non_callable_proto_members__.add(attr) + + return cls + + +# The "runtime" alias exists for backwards compatibility. +runtime = runtime_checkable + + +# Our version of runtime-checkable protocols is faster on Python <=3.11 +# Breakpoint: https://github.com/python/cpython/pull/112717 +if sys.version_info >= (3, 12): + SupportsInt = typing.SupportsInt + SupportsFloat = typing.SupportsFloat + SupportsComplex = typing.SupportsComplex + SupportsBytes = typing.SupportsBytes + SupportsIndex = typing.SupportsIndex + SupportsAbs = typing.SupportsAbs + SupportsRound = typing.SupportsRound +else: + @runtime_checkable + class SupportsInt(Protocol): + """An ABC with one abstract method __int__.""" + __slots__ = () + + @abc.abstractmethod + def __int__(self) -> int: + pass + + @runtime_checkable + class SupportsFloat(Protocol): + """An ABC with one abstract method __float__.""" + __slots__ = () + + @abc.abstractmethod + def __float__(self) -> float: + pass + + @runtime_checkable + class SupportsComplex(Protocol): + """An ABC with one abstract method __complex__.""" + __slots__ = () + + @abc.abstractmethod + def __complex__(self) -> complex: + pass + + @runtime_checkable + class SupportsBytes(Protocol): + """An ABC with one abstract method __bytes__.""" + __slots__ = () + + @abc.abstractmethod + def __bytes__(self) -> bytes: + pass + + @runtime_checkable + class SupportsIndex(Protocol): + __slots__ = () + + @abc.abstractmethod + def __index__(self) -> int: + pass + + @runtime_checkable + class SupportsAbs(Protocol[T_co]): + """ + An ABC with one abstract method __abs__ that is covariant in its return type. + """ + __slots__ = () + + @abc.abstractmethod + def __abs__(self) -> T_co: + pass + + @runtime_checkable + class SupportsRound(Protocol[T_co]): + """ + An ABC with one abstract method __round__ that is covariant in its return type. + """ + __slots__ = () + + @abc.abstractmethod + def __round__(self, ndigits: int = 0) -> T_co: + pass + + +if hasattr(io, "Reader") and hasattr(io, "Writer"): + Reader = io.Reader + Writer = io.Writer +else: + @runtime_checkable + class Reader(Protocol[T_co]): + """Protocol for simple I/O reader instances. + + This protocol only supports blocking I/O. + """ + + __slots__ = () + + @abc.abstractmethod + def read(self, size: int = ..., /) -> T_co: + """Read data from the input stream and return it. + + If *size* is specified, at most *size* items (bytes/characters) will be + read. + """ + + @runtime_checkable + class Writer(Protocol[T_contra]): + """Protocol for simple I/O writer instances. + + This protocol only supports blocking I/O. + """ + + __slots__ = () + + @abc.abstractmethod + def write(self, data: T_contra, /) -> int: + """Write *data* to the output stream and return the number of items written.""" # noqa: E501 + + +_NEEDS_SINGLETONMETA = ( + not hasattr(typing, "NoDefault") or not hasattr(typing, "NoExtraItems") +) + +if _NEEDS_SINGLETONMETA: + class SingletonMeta(type): + def __setattr__(cls, attr, value): + # TypeError is consistent with the behavior of NoneType + raise TypeError( + f"cannot set {attr!r} attribute of immutable type {cls.__name__!r}" + ) + + +if hasattr(typing, "NoDefault"): + NoDefault = typing.NoDefault +else: + class NoDefaultType(metaclass=SingletonMeta): + """The type of the NoDefault singleton.""" + + __slots__ = () + + def __new__(cls): + return globals().get("NoDefault") or object.__new__(cls) + + def __repr__(self): + return "typing_extensions.NoDefault" + + def __reduce__(self): + return "NoDefault" + + NoDefault = NoDefaultType() + del NoDefaultType + +if hasattr(typing, "NoExtraItems"): + NoExtraItems = typing.NoExtraItems +else: + class NoExtraItemsType(metaclass=SingletonMeta): + """The type of the NoExtraItems singleton.""" + + __slots__ = () + + def __new__(cls): + return globals().get("NoExtraItems") or object.__new__(cls) + + def __repr__(self): + return "typing_extensions.NoExtraItems" + + def __reduce__(self): + return "NoExtraItems" + + NoExtraItems = NoExtraItemsType() + del NoExtraItemsType + +if _NEEDS_SINGLETONMETA: + del SingletonMeta + + +# Update this to something like >=3.13.0b1 if and when +# PEP 728 is implemented in CPython +_PEP_728_IMPLEMENTED = False + +if _PEP_728_IMPLEMENTED: + # The standard library TypedDict in Python 3.9.0/1 does not honour the "total" + # keyword with old-style TypedDict(). See https://bugs.python.org/issue42059 + # The standard library TypedDict below Python 3.11 does not store runtime + # information about optional and required keys when using Required or NotRequired. + # Generic TypedDicts are also impossible using typing.TypedDict on Python <3.11. + # Aaaand on 3.12 we add __orig_bases__ to TypedDict + # to enable better runtime introspection. + # On 3.13 we deprecate some odd ways of creating TypedDicts. + # Also on 3.13, PEP 705 adds the ReadOnly[] qualifier. + # PEP 728 (still pending) makes more changes. + TypedDict = typing.TypedDict + _TypedDictMeta = typing._TypedDictMeta + is_typeddict = typing.is_typeddict +else: + # 3.10.0 and later + _TAKES_MODULE = "module" in inspect.signature(typing._type_check).parameters + + def _get_typeddict_qualifiers(annotation_type): + while True: + annotation_origin = get_origin(annotation_type) + if annotation_origin is Annotated: + annotation_args = get_args(annotation_type) + if annotation_args: + annotation_type = annotation_args[0] + else: + break + elif annotation_origin is Required: + yield Required + annotation_type, = get_args(annotation_type) + elif annotation_origin is NotRequired: + yield NotRequired + annotation_type, = get_args(annotation_type) + elif annotation_origin is ReadOnly: + yield ReadOnly + annotation_type, = get_args(annotation_type) + else: + break + + class _TypedDictMeta(type): + + def __new__(cls, name, bases, ns, *, total=True, closed=None, + extra_items=NoExtraItems): + """Create new typed dict class object. + + This method is called when TypedDict is subclassed, + or when TypedDict is instantiated. This way + TypedDict supports all three syntax forms described in its docstring. + Subclasses and instances of TypedDict return actual dictionaries. + """ + for base in bases: + if type(base) is not _TypedDictMeta and base is not typing.Generic: + raise TypeError('cannot inherit from both a TypedDict type ' + 'and a non-TypedDict base class') + if closed is not None and extra_items is not NoExtraItems: + raise TypeError(f"Cannot combine closed={closed!r} and extra_items") + + if any(issubclass(b, typing.Generic) for b in bases): + generic_base = (typing.Generic,) + else: + generic_base = () + + ns_annotations = ns.pop('__annotations__', None) + + # typing.py generally doesn't let you inherit from plain Generic, unless + # the name of the class happens to be "Protocol" + tp_dict = type.__new__(_TypedDictMeta, "Protocol", (*generic_base, dict), ns) + tp_dict.__name__ = name + if tp_dict.__qualname__ == "Protocol": + tp_dict.__qualname__ = name + + if not hasattr(tp_dict, '__orig_bases__'): + tp_dict.__orig_bases__ = bases + + annotations = {} + own_annotate = None + if ns_annotations is not None: + own_annotations = ns_annotations + elif sys.version_info >= (3, 14): + if hasattr(annotationlib, "get_annotate_from_class_namespace"): + own_annotate = annotationlib.get_annotate_from_class_namespace(ns) + else: + # 3.14.0a7 and earlier + own_annotate = ns.get("__annotate__") + if own_annotate is not None: + own_annotations = annotationlib.call_annotate_function( + own_annotate, Format.FORWARDREF, owner=tp_dict + ) + else: + own_annotations = {} + else: + own_annotations = {} + msg = "TypedDict('Name', {f0: t0, f1: t1, ...}); each t must be a type" + if _TAKES_MODULE: + own_checked_annotations = { + n: typing._type_check(tp, msg, module=tp_dict.__module__) + for n, tp in own_annotations.items() + } + else: + own_checked_annotations = { + n: typing._type_check(tp, msg) + for n, tp in own_annotations.items() + } + required_keys = set() + optional_keys = set() + readonly_keys = set() + mutable_keys = set() + extra_items_type = extra_items + + for base in bases: + base_dict = base.__dict__ + + if sys.version_info <= (3, 14): + annotations.update(base_dict.get('__annotations__', {})) + required_keys.update(base_dict.get('__required_keys__', ())) + optional_keys.update(base_dict.get('__optional_keys__', ())) + readonly_keys.update(base_dict.get('__readonly_keys__', ())) + mutable_keys.update(base_dict.get('__mutable_keys__', ())) + + # This was specified in an earlier version of PEP 728. Support + # is retained for backwards compatibility, but only for Python + # 3.13 and lower. + if (closed and sys.version_info < (3, 14) + and "__extra_items__" in own_checked_annotations): + annotation_type = own_checked_annotations.pop("__extra_items__") + qualifiers = set(_get_typeddict_qualifiers(annotation_type)) + if Required in qualifiers: + raise TypeError( + "Special key __extra_items__ does not support " + "Required" + ) + if NotRequired in qualifiers: + raise TypeError( + "Special key __extra_items__ does not support " + "NotRequired" + ) + extra_items_type = annotation_type + + annotations.update(own_checked_annotations) + for annotation_key, annotation_type in own_checked_annotations.items(): + qualifiers = set(_get_typeddict_qualifiers(annotation_type)) + + if Required in qualifiers: + required_keys.add(annotation_key) + elif NotRequired in qualifiers: + optional_keys.add(annotation_key) + elif total: + required_keys.add(annotation_key) + else: + optional_keys.add(annotation_key) + if ReadOnly in qualifiers: + mutable_keys.discard(annotation_key) + readonly_keys.add(annotation_key) + else: + mutable_keys.add(annotation_key) + readonly_keys.discard(annotation_key) + + # Breakpoint: https://github.com/python/cpython/pull/119891 + if sys.version_info >= (3, 14): + def __annotate__(format): + annos = {} + for base in bases: + if base is Generic: + continue + base_annotate = base.__annotate__ + if base_annotate is None: + continue + base_annos = annotationlib.call_annotate_function( + base_annotate, format, owner=base) + annos.update(base_annos) + if own_annotate is not None: + own = annotationlib.call_annotate_function( + own_annotate, format, owner=tp_dict) + if format != Format.STRING: + own = { + n: typing._type_check(tp, msg, module=tp_dict.__module__) + for n, tp in own.items() + } + elif format == Format.STRING: + own = annotationlib.annotations_to_string(own_annotations) + elif format in (Format.FORWARDREF, Format.VALUE): + own = own_checked_annotations + else: + raise NotImplementedError(format) + annos.update(own) + return annos + + tp_dict.__annotate__ = __annotate__ + else: + tp_dict.__annotations__ = annotations + tp_dict.__required_keys__ = frozenset(required_keys) + tp_dict.__optional_keys__ = frozenset(optional_keys) + tp_dict.__readonly_keys__ = frozenset(readonly_keys) + tp_dict.__mutable_keys__ = frozenset(mutable_keys) + tp_dict.__total__ = total + tp_dict.__closed__ = closed + tp_dict.__extra_items__ = extra_items_type + return tp_dict + + __call__ = dict # static method + + def __subclasscheck__(cls, other): + # Typed dicts are only for static structural subtyping. + raise TypeError('TypedDict does not support instance and class checks') + + __instancecheck__ = __subclasscheck__ + + _TypedDict = type.__new__(_TypedDictMeta, 'TypedDict', (), {}) + + def _create_typeddict( + typename, + fields, + /, + *, + typing_is_inline, + total, + closed, + extra_items, + **kwargs, + ): + if fields is _marker or fields is None: + if fields is _marker: + deprecated_thing = ( + "Failing to pass a value for the 'fields' parameter" + ) + else: + deprecated_thing = "Passing `None` as the 'fields' parameter" + + example = f"`{typename} = TypedDict({typename!r}, {{}})`" + deprecation_msg = ( + f"{deprecated_thing} is deprecated and will be disallowed in " + "Python 3.15. To create a TypedDict class with 0 fields " + "using the functional syntax, pass an empty dictionary, e.g. " + ) + example + "." + warnings.warn(deprecation_msg, DeprecationWarning, stacklevel=2) + # Support a field called "closed" + if closed is not False and closed is not True and closed is not None: + kwargs["closed"] = closed + closed = None + # Or "extra_items" + if extra_items is not NoExtraItems: + kwargs["extra_items"] = extra_items + extra_items = NoExtraItems + fields = kwargs + elif kwargs: + raise TypeError("TypedDict takes either a dict or keyword arguments," + " but not both") + if kwargs: + # Breakpoint: https://github.com/python/cpython/pull/104891 + if sys.version_info >= (3, 13): + raise TypeError("TypedDict takes no keyword arguments") + warnings.warn( + "The kwargs-based syntax for TypedDict definitions is deprecated " + "in Python 3.11, will be removed in Python 3.13, and may not be " + "understood by third-party type checkers.", + DeprecationWarning, + stacklevel=2, + ) + + ns = {'__annotations__': dict(fields)} + module = _caller(depth=4 if typing_is_inline else 2) + if module is not None: + # Setting correct module is necessary to make typed dict classes + # pickleable. + ns['__module__'] = module + + td = _TypedDictMeta(typename, (), ns, total=total, closed=closed, + extra_items=extra_items) + td.__orig_bases__ = (TypedDict,) + return td + + class _TypedDictSpecialForm(_SpecialForm, _root=True): + def __call__( + self, + typename, + fields=_marker, + /, + *, + total=True, + closed=None, + extra_items=NoExtraItems, + **kwargs + ): + return _create_typeddict( + typename, + fields, + typing_is_inline=False, + total=total, + closed=closed, + extra_items=extra_items, + **kwargs, + ) + + def __mro_entries__(self, bases): + return (_TypedDict,) + + @_TypedDictSpecialForm + def TypedDict(self, args): + """A simple typed namespace. At runtime it is equivalent to a plain dict. + + TypedDict creates a dictionary type such that a type checker will expect all + instances to have a certain set of keys, where each key is + associated with a value of a consistent type. This expectation + is not checked at runtime. + + Usage:: + + class Point2D(TypedDict): + x: int + y: int + label: str + + a: Point2D = {'x': 1, 'y': 2, 'label': 'good'} # OK + b: Point2D = {'z': 3, 'label': 'bad'} # Fails type check + + assert Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first') + + The type info can be accessed via the Point2D.__annotations__ dict, and + the Point2D.__required_keys__ and Point2D.__optional_keys__ frozensets. + TypedDict supports an additional equivalent form:: + + Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str}) + + By default, all keys must be present in a TypedDict. It is possible + to override this by specifying totality:: + + class Point2D(TypedDict, total=False): + x: int + y: int + + This means that a Point2D TypedDict can have any of the keys omitted. A type + checker is only expected to support a literal False or True as the value of + the total argument. True is the default, and makes all items defined in the + class body be required. + + The Required and NotRequired special forms can also be used to mark + individual keys as being required or not required:: + + class Point2D(TypedDict): + x: int # the "x" key must always be present (Required is the default) + y: NotRequired[int] # the "y" key can be omitted + + See PEP 655 for more details on Required and NotRequired. + """ + # This runs when creating inline TypedDicts: + if not isinstance(args, dict): + raise TypeError( + "TypedDict[...] should be used with a single dict argument" + ) + + return _create_typeddict( + "", + args, + typing_is_inline=True, + total=True, + closed=True, + extra_items=NoExtraItems, + ) + + _TYPEDDICT_TYPES = (typing._TypedDictMeta, _TypedDictMeta) + + def is_typeddict(tp): + """Check if an annotation is a TypedDict class + + For example:: + class Film(TypedDict): + title: str + year: int + + is_typeddict(Film) # => True + is_typeddict(Union[list, str]) # => False + """ + return isinstance(tp, _TYPEDDICT_TYPES) + + +if hasattr(typing, "assert_type"): + assert_type = typing.assert_type + +else: + def assert_type(val, typ, /): + """Assert (to the type checker) that the value is of the given type. + + When the type checker encounters a call to assert_type(), it + emits an error if the value is not of the specified type:: + + def greet(name: str) -> None: + assert_type(name, str) # ok + assert_type(name, int) # type checker error + + At runtime this returns the first argument unchanged and otherwise + does nothing. + """ + return val + + +if hasattr(typing, "ReadOnly"): # 3.13+ + get_type_hints = typing.get_type_hints +else: # <=3.13 + # replaces _strip_annotations() + def _strip_extras(t): + """Strips Annotated, Required and NotRequired from a given type.""" + if isinstance(t, typing._AnnotatedAlias): + return _strip_extras(t.__origin__) + if hasattr(t, "__origin__") and t.__origin__ in (Required, NotRequired, ReadOnly): + return _strip_extras(t.__args__[0]) + if isinstance(t, typing._GenericAlias): + stripped_args = tuple(_strip_extras(a) for a in t.__args__) + if stripped_args == t.__args__: + return t + return t.copy_with(stripped_args) + if hasattr(_types, "GenericAlias") and isinstance(t, _types.GenericAlias): + stripped_args = tuple(_strip_extras(a) for a in t.__args__) + if stripped_args == t.__args__: + return t + return _types.GenericAlias(t.__origin__, stripped_args) + if hasattr(_types, "UnionType") and isinstance(t, _types.UnionType): + stripped_args = tuple(_strip_extras(a) for a in t.__args__) + if stripped_args == t.__args__: + return t + return functools.reduce(operator.or_, stripped_args) + + return t + + def get_type_hints(obj, globalns=None, localns=None, include_extras=False): + """Return type hints for an object. + + This is often the same as obj.__annotations__, but it handles + forward references encoded as string literals, adds Optional[t] if a + default value equal to None is set and recursively replaces all + 'Annotated[T, ...]', 'Required[T]' or 'NotRequired[T]' with 'T' + (unless 'include_extras=True'). + + The argument may be a module, class, method, or function. The annotations + are returned as a dictionary. For classes, annotations include also + inherited members. + + TypeError is raised if the argument is not of a type that can contain + annotations, and an empty dictionary is returned if no annotations are + present. + + BEWARE -- the behavior of globalns and localns is counterintuitive + (unless you are familiar with how eval() and exec() work). The + search order is locals first, then globals. + + - If no dict arguments are passed, an attempt is made to use the + globals from obj (or the respective module's globals for classes), + and these are also used as the locals. If the object does not appear + to have globals, an empty dictionary is used. + + - If one dict argument is passed, it is used for both globals and + locals. + + - If two dict arguments are passed, they specify globals and + locals, respectively. + """ + hint = typing.get_type_hints( + obj, globalns=globalns, localns=localns, include_extras=True + ) + # Breakpoint: https://github.com/python/cpython/pull/30304 + if sys.version_info < (3, 11): + _clean_optional(obj, hint, globalns, localns) + if include_extras: + return hint + return {k: _strip_extras(t) for k, t in hint.items()} + + _NoneType = type(None) + + def _could_be_inserted_optional(t): + """detects Union[..., None] pattern""" + if not isinstance(t, typing._UnionGenericAlias): + return False + # Assume if last argument is not None they are user defined + if t.__args__[-1] is not _NoneType: + return False + return True + + # < 3.11 + def _clean_optional(obj, hints, globalns=None, localns=None): + # reverts injected Union[..., None] cases from typing.get_type_hints + # when a None default value is used. + # see https://github.com/python/typing_extensions/issues/310 + if not hints or isinstance(obj, type): + return + defaults = typing._get_defaults(obj) # avoid accessing __annotations___ + if not defaults: + return + original_hints = obj.__annotations__ + for name, value in hints.items(): + # Not a Union[..., None] or replacement conditions not fullfilled + if (not _could_be_inserted_optional(value) + or name not in defaults + or defaults[name] is not None + ): + continue + original_value = original_hints[name] + # value=NoneType should have caused a skip above but check for safety + if original_value is None: + original_value = _NoneType + # Forward reference + if isinstance(original_value, str): + if globalns is None: + if isinstance(obj, _types.ModuleType): + globalns = obj.__dict__ + else: + nsobj = obj + # Find globalns for the unwrapped object. + while hasattr(nsobj, '__wrapped__'): + nsobj = nsobj.__wrapped__ + globalns = getattr(nsobj, '__globals__', {}) + if localns is None: + localns = globalns + elif localns is None: + localns = globalns + + original_value = ForwardRef( + original_value, + is_argument=not isinstance(obj, _types.ModuleType) + ) + original_evaluated = typing._eval_type(original_value, globalns, localns) + # Compare if values differ. Note that even if equal + # value might be cached by typing._tp_cache contrary to original_evaluated + if original_evaluated != value or ( + # 3.10: ForwardRefs of UnionType might be turned into _UnionGenericAlias + hasattr(_types, "UnionType") + and isinstance(original_evaluated, _types.UnionType) + and not isinstance(value, _types.UnionType) + ): + hints[name] = original_evaluated + +# Python 3.9 has get_origin() and get_args() but those implementations don't support +# ParamSpecArgs and ParamSpecKwargs, so only Python 3.10's versions will do. +# Breakpoint: https://github.com/python/cpython/pull/25298 +if sys.version_info >= (3, 10): + get_origin = typing.get_origin + get_args = typing.get_args +# 3.9 +else: + def get_origin(tp): + """Get the unsubscripted version of a type. + + This supports generic types, Callable, Tuple, Union, Literal, Final, ClassVar + and Annotated. Return None for unsupported types. Examples:: + + get_origin(Literal[42]) is Literal + get_origin(int) is None + get_origin(ClassVar[int]) is ClassVar + get_origin(Generic) is Generic + get_origin(Generic[T]) is Generic + get_origin(Union[T, int]) is Union + get_origin(List[Tuple[T, T]][int]) == list + get_origin(P.args) is P + """ + if isinstance(tp, typing._AnnotatedAlias): + return Annotated + if isinstance(tp, (typing._BaseGenericAlias, _types.GenericAlias, + ParamSpecArgs, ParamSpecKwargs)): + return tp.__origin__ + if tp is typing.Generic: + return typing.Generic + return None + + def get_args(tp): + """Get type arguments with all substitutions performed. + + For unions, basic simplifications used by Union constructor are performed. + Examples:: + get_args(Dict[str, int]) == (str, int) + get_args(int) == () + get_args(Union[int, Union[T, int], str][int]) == (int, str) + get_args(Union[int, Tuple[T, int]][str]) == (int, Tuple[str, int]) + get_args(Callable[[], T][int]) == ([], int) + """ + if isinstance(tp, typing._AnnotatedAlias): + return (tp.__origin__, *tp.__metadata__) + if isinstance(tp, (typing._GenericAlias, _types.GenericAlias)): + res = tp.__args__ + if get_origin(tp) is collections.abc.Callable and res[0] is not Ellipsis: + res = (list(res[:-1]), res[-1]) + return res + return () + + +# 3.10+ +if hasattr(typing, 'TypeAlias'): + TypeAlias = typing.TypeAlias +# 3.9 +else: + @_ExtensionsSpecialForm + def TypeAlias(self, parameters): + """Special marker indicating that an assignment should + be recognized as a proper type alias definition by type + checkers. + + For example:: + + Predicate: TypeAlias = Callable[..., bool] + + It's invalid when used anywhere except as in the example above. + """ + raise TypeError(f"{self} is not subscriptable") + + +def _set_default(type_param, default): + type_param.has_default = lambda: default is not NoDefault + type_param.__default__ = default + + +def _set_module(typevarlike): + # for pickling: + def_mod = _caller(depth=2) + if def_mod != 'typing_extensions': + typevarlike.__module__ = def_mod + + +class _DefaultMixin: + """Mixin for TypeVarLike defaults.""" + + __slots__ = () + __init__ = _set_default + + +# Classes using this metaclass must provide a _backported_typevarlike ClassVar +class _TypeVarLikeMeta(type): + def __instancecheck__(cls, __instance: Any) -> bool: + return isinstance(__instance, cls._backported_typevarlike) + + +if _PEP_696_IMPLEMENTED: + from typing import TypeVar +else: + # Add default and infer_variance parameters from PEP 696 and 695 + class TypeVar(metaclass=_TypeVarLikeMeta): + """Type variable.""" + + _backported_typevarlike = typing.TypeVar + + def __new__(cls, name, *constraints, bound=None, + covariant=False, contravariant=False, + default=NoDefault, infer_variance=False): + if hasattr(typing, "TypeAliasType"): + # PEP 695 implemented (3.12+), can pass infer_variance to typing.TypeVar + typevar = typing.TypeVar(name, *constraints, bound=bound, + covariant=covariant, contravariant=contravariant, + infer_variance=infer_variance) + else: + typevar = typing.TypeVar(name, *constraints, bound=bound, + covariant=covariant, contravariant=contravariant) + if infer_variance and (covariant or contravariant): + raise ValueError("Variance cannot be specified with infer_variance.") + typevar.__infer_variance__ = infer_variance + + _set_default(typevar, default) + _set_module(typevar) + + def _tvar_prepare_subst(alias, args): + if ( + typevar.has_default() + and alias.__parameters__.index(typevar) == len(args) + ): + args += (typevar.__default__,) + return args + + typevar.__typing_prepare_subst__ = _tvar_prepare_subst + return typevar + + def __init_subclass__(cls) -> None: + raise TypeError(f"type '{__name__}.TypeVar' is not an acceptable base type") + + +# Python 3.10+ has PEP 612 +if hasattr(typing, 'ParamSpecArgs'): + ParamSpecArgs = typing.ParamSpecArgs + ParamSpecKwargs = typing.ParamSpecKwargs +# 3.9 +else: + class _Immutable: + """Mixin to indicate that object should not be copied.""" + __slots__ = () + + def __copy__(self): + return self + + def __deepcopy__(self, memo): + return self + + class ParamSpecArgs(_Immutable): + """The args for a ParamSpec object. + + Given a ParamSpec object P, P.args is an instance of ParamSpecArgs. + + ParamSpecArgs objects have a reference back to their ParamSpec: + + P.args.__origin__ is P + + This type is meant for runtime introspection and has no special meaning to + static type checkers. + """ + def __init__(self, origin): + self.__origin__ = origin + + def __repr__(self): + return f"{self.__origin__.__name__}.args" + + def __eq__(self, other): + if not isinstance(other, ParamSpecArgs): + return NotImplemented + return self.__origin__ == other.__origin__ + + class ParamSpecKwargs(_Immutable): + """The kwargs for a ParamSpec object. + + Given a ParamSpec object P, P.kwargs is an instance of ParamSpecKwargs. + + ParamSpecKwargs objects have a reference back to their ParamSpec: + + P.kwargs.__origin__ is P + + This type is meant for runtime introspection and has no special meaning to + static type checkers. + """ + def __init__(self, origin): + self.__origin__ = origin + + def __repr__(self): + return f"{self.__origin__.__name__}.kwargs" + + def __eq__(self, other): + if not isinstance(other, ParamSpecKwargs): + return NotImplemented + return self.__origin__ == other.__origin__ + + +if _PEP_696_IMPLEMENTED: + from typing import ParamSpec + +# 3.10+ +elif hasattr(typing, 'ParamSpec'): + + # Add default parameter - PEP 696 + class ParamSpec(metaclass=_TypeVarLikeMeta): + """Parameter specification.""" + + _backported_typevarlike = typing.ParamSpec + + def __new__(cls, name, *, bound=None, + covariant=False, contravariant=False, + infer_variance=False, default=NoDefault): + if hasattr(typing, "TypeAliasType"): + # PEP 695 implemented, can pass infer_variance to typing.TypeVar + paramspec = typing.ParamSpec(name, bound=bound, + covariant=covariant, + contravariant=contravariant, + infer_variance=infer_variance) + else: + paramspec = typing.ParamSpec(name, bound=bound, + covariant=covariant, + contravariant=contravariant) + paramspec.__infer_variance__ = infer_variance + + _set_default(paramspec, default) + _set_module(paramspec) + + def _paramspec_prepare_subst(alias, args): + params = alias.__parameters__ + i = params.index(paramspec) + if i == len(args) and paramspec.has_default(): + args = [*args, paramspec.__default__] + if i >= len(args): + raise TypeError(f"Too few arguments for {alias}") + # Special case where Z[[int, str, bool]] == Z[int, str, bool] in PEP 612. + if len(params) == 1 and not typing._is_param_expr(args[0]): + assert i == 0 + args = (args,) + # Convert lists to tuples to help other libraries cache the results. + elif isinstance(args[i], list): + args = (*args[:i], tuple(args[i]), *args[i + 1:]) + return args + + paramspec.__typing_prepare_subst__ = _paramspec_prepare_subst + return paramspec + + def __init_subclass__(cls) -> None: + raise TypeError(f"type '{__name__}.ParamSpec' is not an acceptable base type") + +# 3.9 +else: + + # Inherits from list as a workaround for Callable checks in Python < 3.9.2. + class ParamSpec(list, _DefaultMixin): + """Parameter specification variable. + + Usage:: + + P = ParamSpec('P') + + Parameter specification variables exist primarily for the benefit of static + type checkers. They are used to forward the parameter types of one + callable to another callable, a pattern commonly found in higher order + functions and decorators. They are only valid when used in ``Concatenate``, + or s the first argument to ``Callable``. In Python 3.10 and higher, + they are also supported in user-defined Generics at runtime. + See class Generic for more information on generic types. An + example for annotating a decorator:: + + T = TypeVar('T') + P = ParamSpec('P') + + def add_logging(f: Callable[P, T]) -> Callable[P, T]: + '''A type-safe decorator to add logging to a function.''' + def inner(*args: P.args, **kwargs: P.kwargs) -> T: + logging.info(f'{f.__name__} was called') + return f(*args, **kwargs) + return inner + + @add_logging + def add_two(x: float, y: float) -> float: + '''Add two numbers together.''' + return x + y + + Parameter specification variables defined with covariant=True or + contravariant=True can be used to declare covariant or contravariant + generic types. These keyword arguments are valid, but their actual semantics + are yet to be decided. See PEP 612 for details. + + Parameter specification variables can be introspected. e.g.: + + P.__name__ == 'T' + P.__bound__ == None + P.__covariant__ == False + P.__contravariant__ == False + + Note that only parameter specification variables defined in global scope can + be pickled. + """ + + # Trick Generic __parameters__. + __class__ = typing.TypeVar + + @property + def args(self): + return ParamSpecArgs(self) + + @property + def kwargs(self): + return ParamSpecKwargs(self) + + def __init__(self, name, *, bound=None, covariant=False, contravariant=False, + infer_variance=False, default=NoDefault): + list.__init__(self, [self]) + self.__name__ = name + self.__covariant__ = bool(covariant) + self.__contravariant__ = bool(contravariant) + self.__infer_variance__ = bool(infer_variance) + if bound: + self.__bound__ = typing._type_check(bound, 'Bound must be a type.') + else: + self.__bound__ = None + _DefaultMixin.__init__(self, default) + + # for pickling: + def_mod = _caller() + if def_mod != 'typing_extensions': + self.__module__ = def_mod + + def __repr__(self): + if self.__infer_variance__: + prefix = '' + elif self.__covariant__: + prefix = '+' + elif self.__contravariant__: + prefix = '-' + else: + prefix = '~' + return prefix + self.__name__ + + def __hash__(self): + return object.__hash__(self) + + def __eq__(self, other): + return self is other + + def __reduce__(self): + return self.__name__ + + # Hack to get typing._type_check to pass. + def __call__(self, *args, **kwargs): + pass + + +# 3.9 +if not hasattr(typing, 'Concatenate'): + # Inherits from list as a workaround for Callable checks in Python < 3.9.2. + + # 3.9.0-1 + if not hasattr(typing, '_type_convert'): + def _type_convert(arg, module=None, *, allow_special_forms=False): + """For converting None to type(None), and strings to ForwardRef.""" + if arg is None: + return type(None) + if isinstance(arg, str): + if sys.version_info <= (3, 9, 6): + return ForwardRef(arg) + if sys.version_info <= (3, 9, 7): + return ForwardRef(arg, module=module) + return ForwardRef(arg, module=module, is_class=allow_special_forms) + return arg + else: + _type_convert = typing._type_convert + + class _ConcatenateGenericAlias(list): + + # Trick Generic into looking into this for __parameters__. + __class__ = typing._GenericAlias + + def __init__(self, origin, args): + super().__init__(args) + self.__origin__ = origin + self.__args__ = args + + def __repr__(self): + _type_repr = typing._type_repr + return (f'{_type_repr(self.__origin__)}' + f'[{", ".join(_type_repr(arg) for arg in self.__args__)}]') + + def __hash__(self): + return hash((self.__origin__, self.__args__)) + + # Hack to get typing._type_check to pass in Generic. + def __call__(self, *args, **kwargs): + pass + + @property + def __parameters__(self): + return tuple( + tp for tp in self.__args__ if isinstance(tp, (typing.TypeVar, ParamSpec)) + ) + + # 3.9 used by __getitem__ below + def copy_with(self, params): + if isinstance(params[-1], _ConcatenateGenericAlias): + params = (*params[:-1], *params[-1].__args__) + elif isinstance(params[-1], (list, tuple)): + return (*params[:-1], *params[-1]) + elif (not (params[-1] is ... or isinstance(params[-1], ParamSpec))): + raise TypeError("The last parameter to Concatenate should be a " + "ParamSpec variable or ellipsis.") + return self.__class__(self.__origin__, params) + + # 3.9; accessed during GenericAlias.__getitem__ when substituting + def __getitem__(self, args): + if self.__origin__ in (Generic, Protocol): + # Can't subscript Generic[...] or Protocol[...]. + raise TypeError(f"Cannot subscript already-subscripted {self}") + if not self.__parameters__: + raise TypeError(f"{self} is not a generic class") + + if not isinstance(args, tuple): + args = (args,) + args = _unpack_args(*(_type_convert(p) for p in args)) + params = self.__parameters__ + for param in params: + prepare = getattr(param, "__typing_prepare_subst__", None) + if prepare is not None: + args = prepare(self, args) + # 3.9 & typing.ParamSpec + elif isinstance(param, ParamSpec): + i = params.index(param) + if ( + i == len(args) + and getattr(param, '__default__', NoDefault) is not NoDefault + ): + args = [*args, param.__default__] + if i >= len(args): + raise TypeError(f"Too few arguments for {self}") + # Special case for Z[[int, str, bool]] == Z[int, str, bool] + if len(params) == 1 and not _is_param_expr(args[0]): + assert i == 0 + args = (args,) + elif ( + isinstance(args[i], list) + # 3.9 + # This class inherits from list do not convert + and not isinstance(args[i], _ConcatenateGenericAlias) + ): + args = (*args[:i], tuple(args[i]), *args[i + 1:]) + + alen = len(args) + plen = len(params) + if alen != plen: + raise TypeError( + f"Too {'many' if alen > plen else 'few'} arguments for {self};" + f" actual {alen}, expected {plen}" + ) + + subst = dict(zip(self.__parameters__, args)) + # determine new args + new_args = [] + for arg in self.__args__: + if isinstance(arg, type): + new_args.append(arg) + continue + if isinstance(arg, TypeVar): + arg = subst[arg] + if ( + (isinstance(arg, typing._GenericAlias) and _is_unpack(arg)) + or ( + hasattr(_types, "GenericAlias") + and isinstance(arg, _types.GenericAlias) + and getattr(arg, "__unpacked__", False) + ) + ): + raise TypeError(f"{arg} is not valid as type argument") + + elif isinstance(arg, + typing._GenericAlias + if not hasattr(_types, "GenericAlias") else + (typing._GenericAlias, _types.GenericAlias) + ): + subparams = arg.__parameters__ + if subparams: + subargs = tuple(subst[x] for x in subparams) + arg = arg[subargs] + new_args.append(arg) + return self.copy_with(tuple(new_args)) + +# 3.10+ +else: + _ConcatenateGenericAlias = typing._ConcatenateGenericAlias + + # 3.10 + if sys.version_info < (3, 11): + + class _ConcatenateGenericAlias(typing._ConcatenateGenericAlias, _root=True): + # needed for checks in collections.abc.Callable to accept this class + __module__ = "typing" + + def copy_with(self, params): + if isinstance(params[-1], (list, tuple)): + return (*params[:-1], *params[-1]) + if isinstance(params[-1], typing._ConcatenateGenericAlias): + params = (*params[:-1], *params[-1].__args__) + elif not (params[-1] is ... or isinstance(params[-1], ParamSpec)): + raise TypeError("The last parameter to Concatenate should be a " + "ParamSpec variable or ellipsis.") + return super(typing._ConcatenateGenericAlias, self).copy_with(params) + + def __getitem__(self, args): + value = super().__getitem__(args) + if isinstance(value, tuple) and any(_is_unpack(t) for t in value): + return tuple(_unpack_args(*(n for n in value))) + return value + + +# 3.9.2 +class _EllipsisDummy: ... + + +# <=3.10 +def _create_concatenate_alias(origin, parameters): + if parameters[-1] is ... and sys.version_info < (3, 9, 2): + # Hack: Arguments must be types, replace it with one. + parameters = (*parameters[:-1], _EllipsisDummy) + if sys.version_info >= (3, 10, 3): + concatenate = _ConcatenateGenericAlias(origin, parameters, + _typevar_types=(TypeVar, ParamSpec), + _paramspec_tvars=True) + else: + concatenate = _ConcatenateGenericAlias(origin, parameters) + if parameters[-1] is not _EllipsisDummy: + return concatenate + # Remove dummy again + concatenate.__args__ = tuple(p if p is not _EllipsisDummy else ... + for p in concatenate.__args__) + if sys.version_info < (3, 10): + # backport needs __args__ adjustment only + return concatenate + concatenate.__parameters__ = tuple(p for p in concatenate.__parameters__ + if p is not _EllipsisDummy) + return concatenate + + +# <=3.10 +@typing._tp_cache +def _concatenate_getitem(self, parameters): + if parameters == (): + raise TypeError("Cannot take a Concatenate of no types.") + if not isinstance(parameters, tuple): + parameters = (parameters,) + if not (parameters[-1] is ... or isinstance(parameters[-1], ParamSpec)): + raise TypeError("The last parameter to Concatenate should be a " + "ParamSpec variable or ellipsis.") + msg = "Concatenate[arg, ...]: each arg must be a type." + parameters = (*(typing._type_check(p, msg) for p in parameters[:-1]), + parameters[-1]) + return _create_concatenate_alias(self, parameters) + + +# 3.11+; Concatenate does not accept ellipsis in 3.10 +# Breakpoint: https://github.com/python/cpython/pull/30969 +if sys.version_info >= (3, 11): + Concatenate = typing.Concatenate +# <=3.10 +else: + @_ExtensionsSpecialForm + def Concatenate(self, parameters): + """Used in conjunction with ``ParamSpec`` and ``Callable`` to represent a + higher order function which adds, removes or transforms parameters of a + callable. + + For example:: + + Callable[Concatenate[int, P], int] + + See PEP 612 for detailed information. + """ + return _concatenate_getitem(self, parameters) + + +# 3.10+ +if hasattr(typing, 'TypeGuard'): + TypeGuard = typing.TypeGuard +# 3.9 +else: + @_ExtensionsSpecialForm + def TypeGuard(self, parameters): + """Special typing form used to annotate the return type of a user-defined + type guard function. ``TypeGuard`` only accepts a single type argument. + At runtime, functions marked this way should return a boolean. + + ``TypeGuard`` aims to benefit *type narrowing* -- a technique used by static + type checkers to determine a more precise type of an expression within a + program's code flow. Usually type narrowing is done by analyzing + conditional code flow and applying the narrowing to a block of code. The + conditional expression here is sometimes referred to as a "type guard". + + Sometimes it would be convenient to use a user-defined boolean function + as a type guard. Such a function should use ``TypeGuard[...]`` as its + return type to alert static type checkers to this intention. + + Using ``-> TypeGuard`` tells the static type checker that for a given + function: + + 1. The return value is a boolean. + 2. If the return value is ``True``, the type of its argument + is the type inside ``TypeGuard``. + + For example:: + + def is_str(val: Union[str, float]): + # "isinstance" type guard + if isinstance(val, str): + # Type of ``val`` is narrowed to ``str`` + ... + else: + # Else, type of ``val`` is narrowed to ``float``. + ... + + Strict type narrowing is not enforced -- ``TypeB`` need not be a narrower + form of ``TypeA`` (it can even be a wider form) and this may lead to + type-unsafe results. The main reason is to allow for things like + narrowing ``List[object]`` to ``List[str]`` even though the latter is not + a subtype of the former, since ``List`` is invariant. The responsibility of + writing type-safe type guards is left to the user. + + ``TypeGuard`` also works with type variables. For more information, see + PEP 647 (User-Defined Type Guards). + """ + item = typing._type_check(parameters, f'{self} accepts only a single type.') + return typing._GenericAlias(self, (item,)) + + +# 3.13+ +if hasattr(typing, 'TypeIs'): + TypeIs = typing.TypeIs +# <=3.12 +else: + @_ExtensionsSpecialForm + def TypeIs(self, parameters): + """Special typing form used to annotate the return type of a user-defined + type narrower function. ``TypeIs`` only accepts a single type argument. + At runtime, functions marked this way should return a boolean. + + ``TypeIs`` aims to benefit *type narrowing* -- a technique used by static + type checkers to determine a more precise type of an expression within a + program's code flow. Usually type narrowing is done by analyzing + conditional code flow and applying the narrowing to a block of code. The + conditional expression here is sometimes referred to as a "type guard". + + Sometimes it would be convenient to use a user-defined boolean function + as a type guard. Such a function should use ``TypeIs[...]`` as its + return type to alert static type checkers to this intention. + + Using ``-> TypeIs`` tells the static type checker that for a given + function: + + 1. The return value is a boolean. + 2. If the return value is ``True``, the type of its argument + is the intersection of the type inside ``TypeIs`` and the argument's + previously known type. + + For example:: + + def is_awaitable(val: object) -> TypeIs[Awaitable[Any]]: + return hasattr(val, '__await__') + + def f(val: Union[int, Awaitable[int]]) -> int: + if is_awaitable(val): + assert_type(val, Awaitable[int]) + else: + assert_type(val, int) + + ``TypeIs`` also works with type variables. For more information, see + PEP 742 (Narrowing types with TypeIs). + """ + item = typing._type_check(parameters, f'{self} accepts only a single type.') + return typing._GenericAlias(self, (item,)) + + +# 3.14+? +if hasattr(typing, 'TypeForm'): + TypeForm = typing.TypeForm +# <=3.13 +else: + class _TypeFormForm(_ExtensionsSpecialForm, _root=True): + # TypeForm(X) is equivalent to X but indicates to the type checker + # that the object is a TypeForm. + def __call__(self, obj, /): + return obj + + @_TypeFormForm + def TypeForm(self, parameters): + """A special form representing the value that results from the evaluation + of a type expression. This value encodes the information supplied in the + type expression, and it represents the type described by that type expression. + + When used in a type expression, TypeForm describes a set of type form objects. + It accepts a single type argument, which must be a valid type expression. + ``TypeForm[T]`` describes the set of all type form objects that represent + the type T or types that are assignable to T. + + Usage: + + def cast[T](typ: TypeForm[T], value: Any) -> T: ... + + reveal_type(cast(int, "x")) # int + + See PEP 747 for more information. + """ + item = typing._type_check(parameters, f'{self} accepts only a single type.') + return typing._GenericAlias(self, (item,)) + + + + +if hasattr(typing, "LiteralString"): # 3.11+ + LiteralString = typing.LiteralString +else: + @_SpecialForm + def LiteralString(self, params): + """Represents an arbitrary literal string. + + Example:: + + from typing_extensions import LiteralString + + def query(sql: LiteralString) -> ...: + ... + + query("SELECT * FROM table") # ok + query(f"SELECT * FROM {input()}") # not ok + + See PEP 675 for details. + + """ + raise TypeError(f"{self} is not subscriptable") + + +if hasattr(typing, "Self"): # 3.11+ + Self = typing.Self +else: + @_SpecialForm + def Self(self, params): + """Used to spell the type of "self" in classes. + + Example:: + + from typing import Self + + class ReturnsSelf: + def parse(self, data: bytes) -> Self: + ... + return self + + """ + + raise TypeError(f"{self} is not subscriptable") + + +if hasattr(typing, "Never"): # 3.11+ + Never = typing.Never +else: + @_SpecialForm + def Never(self, params): + """The bottom type, a type that has no members. + + This can be used to define a function that should never be + called, or a function that never returns:: + + from typing_extensions import Never + + def never_call_me(arg: Never) -> None: + pass + + def int_or_str(arg: int | str) -> None: + never_call_me(arg) # type checker error + match arg: + case int(): + print("It's an int") + case str(): + print("It's a str") + case _: + never_call_me(arg) # ok, arg is of type Never + + """ + + raise TypeError(f"{self} is not subscriptable") + + +if hasattr(typing, 'Required'): # 3.11+ + Required = typing.Required + NotRequired = typing.NotRequired +else: # <=3.10 + @_ExtensionsSpecialForm + def Required(self, parameters): + """A special typing construct to mark a key of a total=False TypedDict + as required. For example: + + class Movie(TypedDict, total=False): + title: Required[str] + year: int + + m = Movie( + title='The Matrix', # typechecker error if key is omitted + year=1999, + ) + + There is no runtime checking that a required key is actually provided + when instantiating a related TypedDict. + """ + item = typing._type_check(parameters, f'{self._name} accepts only a single type.') + return typing._GenericAlias(self, (item,)) + + @_ExtensionsSpecialForm + def NotRequired(self, parameters): + """A special typing construct to mark a key of a TypedDict as + potentially missing. For example: + + class Movie(TypedDict): + title: str + year: NotRequired[int] + + m = Movie( + title='The Matrix', # typechecker error if key is omitted + year=1999, + ) + """ + item = typing._type_check(parameters, f'{self._name} accepts only a single type.') + return typing._GenericAlias(self, (item,)) + + +if hasattr(typing, 'ReadOnly'): + ReadOnly = typing.ReadOnly +else: # <=3.12 + @_ExtensionsSpecialForm + def ReadOnly(self, parameters): + """A special typing construct to mark an item of a TypedDict as read-only. + + For example: + + class Movie(TypedDict): + title: ReadOnly[str] + year: int + + def mutate_movie(m: Movie) -> None: + m["year"] = 1992 # allowed + m["title"] = "The Matrix" # typechecker error + + There is no runtime checking for this property. + """ + item = typing._type_check(parameters, f'{self._name} accepts only a single type.') + return typing._GenericAlias(self, (item,)) + + +_UNPACK_DOC = """\ +Type unpack operator. + +The type unpack operator takes the child types from some container type, +such as `tuple[int, str]` or a `TypeVarTuple`, and 'pulls them out'. For +example: + + # For some generic class `Foo`: + Foo[Unpack[tuple[int, str]]] # Equivalent to Foo[int, str] + + Ts = TypeVarTuple('Ts') + # Specifies that `Bar` is generic in an arbitrary number of types. + # (Think of `Ts` as a tuple of an arbitrary number of individual + # `TypeVar`s, which the `Unpack` is 'pulling out' directly into the + # `Generic[]`.) + class Bar(Generic[Unpack[Ts]]): ... + Bar[int] # Valid + Bar[int, str] # Also valid + +From Python 3.11, this can also be done using the `*` operator: + + Foo[*tuple[int, str]] + class Bar(Generic[*Ts]): ... + +The operator can also be used along with a `TypedDict` to annotate +`**kwargs` in a function signature. For instance: + + class Movie(TypedDict): + name: str + year: int + + # This function expects two keyword arguments - *name* of type `str` and + # *year* of type `int`. + def foo(**kwargs: Unpack[Movie]): ... + +Note that there is only some runtime checking of this operator. Not +everything the runtime allows may be accepted by static type checkers. + +For more information, see PEP 646 and PEP 692. +""" + + +# PEP 692 changed the repr of Unpack[] +# Breakpoint: https://github.com/python/cpython/pull/104048 +if sys.version_info >= (3, 12): + Unpack = typing.Unpack + + def _is_unpack(obj): + return get_origin(obj) is Unpack + +else: # <=3.11 + class _UnpackSpecialForm(_ExtensionsSpecialForm, _root=True): + def __init__(self, getitem): + super().__init__(getitem) + self.__doc__ = _UNPACK_DOC + + class _UnpackAlias(typing._GenericAlias, _root=True): + if sys.version_info < (3, 11): + # needed for compatibility with Generic[Unpack[Ts]] + __class__ = typing.TypeVar + + @property + def __typing_unpacked_tuple_args__(self): + assert self.__origin__ is Unpack + assert len(self.__args__) == 1 + arg, = self.__args__ + if isinstance(arg, (typing._GenericAlias, _types.GenericAlias)): + if arg.__origin__ is not tuple: + raise TypeError("Unpack[...] must be used with a tuple type") + return arg.__args__ + return None + + @property + def __typing_is_unpacked_typevartuple__(self): + assert self.__origin__ is Unpack + assert len(self.__args__) == 1 + return isinstance(self.__args__[0], TypeVarTuple) + + def __getitem__(self, args): + if self.__typing_is_unpacked_typevartuple__: + return args + return super().__getitem__(args) + + @_UnpackSpecialForm + def Unpack(self, parameters): + item = typing._type_check(parameters, f'{self._name} accepts only a single type.') + return _UnpackAlias(self, (item,)) + + def _is_unpack(obj): + return isinstance(obj, _UnpackAlias) + + +def _unpack_args(*args): + newargs = [] + for arg in args: + subargs = getattr(arg, '__typing_unpacked_tuple_args__', None) + if subargs is not None and (not (subargs and subargs[-1] is ...)): + newargs.extend(subargs) + else: + newargs.append(arg) + return newargs + + +if _PEP_696_IMPLEMENTED: + from typing import TypeVarTuple + +elif hasattr(typing, "TypeVarTuple"): # 3.11+ + + # Add default parameter - PEP 696 + class TypeVarTuple(metaclass=_TypeVarLikeMeta): + """Type variable tuple.""" + + _backported_typevarlike = typing.TypeVarTuple + + def __new__(cls, name, *, default=NoDefault): + tvt = typing.TypeVarTuple(name) + _set_default(tvt, default) + _set_module(tvt) + + def _typevartuple_prepare_subst(alias, args): + params = alias.__parameters__ + typevartuple_index = params.index(tvt) + for param in params[typevartuple_index + 1:]: + if isinstance(param, TypeVarTuple): + raise TypeError( + f"More than one TypeVarTuple parameter in {alias}" + ) + + alen = len(args) + plen = len(params) + left = typevartuple_index + right = plen - typevartuple_index - 1 + var_tuple_index = None + fillarg = None + for k, arg in enumerate(args): + if not isinstance(arg, type): + subargs = getattr(arg, '__typing_unpacked_tuple_args__', None) + if subargs and len(subargs) == 2 and subargs[-1] is ...: + if var_tuple_index is not None: + raise TypeError( + "More than one unpacked " + "arbitrary-length tuple argument" + ) + var_tuple_index = k + fillarg = subargs[0] + if var_tuple_index is not None: + left = min(left, var_tuple_index) + right = min(right, alen - var_tuple_index - 1) + elif left + right > alen: + raise TypeError(f"Too few arguments for {alias};" + f" actual {alen}, expected at least {plen - 1}") + if left == alen - right and tvt.has_default(): + replacement = _unpack_args(tvt.__default__) + else: + replacement = args[left: alen - right] + + return ( + *args[:left], + *([fillarg] * (typevartuple_index - left)), + replacement, + *([fillarg] * (plen - right - left - typevartuple_index - 1)), + *args[alen - right:], + ) + + tvt.__typing_prepare_subst__ = _typevartuple_prepare_subst + return tvt + + def __init_subclass__(self, *args, **kwds): + raise TypeError("Cannot subclass special typing classes") + +else: # <=3.10 + class TypeVarTuple(_DefaultMixin): + """Type variable tuple. + + Usage:: + + Ts = TypeVarTuple('Ts') + + In the same way that a normal type variable is a stand-in for a single + type such as ``int``, a type variable *tuple* is a stand-in for a *tuple* + type such as ``Tuple[int, str]``. + + Type variable tuples can be used in ``Generic`` declarations. + Consider the following example:: + + class Array(Generic[*Ts]): ... + + The ``Ts`` type variable tuple here behaves like ``tuple[T1, T2]``, + where ``T1`` and ``T2`` are type variables. To use these type variables + as type parameters of ``Array``, we must *unpack* the type variable tuple using + the star operator: ``*Ts``. The signature of ``Array`` then behaves + as if we had simply written ``class Array(Generic[T1, T2]): ...``. + In contrast to ``Generic[T1, T2]``, however, ``Generic[*Shape]`` allows + us to parameterise the class with an *arbitrary* number of type parameters. + + Type variable tuples can be used anywhere a normal ``TypeVar`` can. + This includes class definitions, as shown above, as well as function + signatures and variable annotations:: + + class Array(Generic[*Ts]): + + def __init__(self, shape: Tuple[*Ts]): + self._shape: Tuple[*Ts] = shape + + def get_shape(self) -> Tuple[*Ts]: + return self._shape + + shape = (Height(480), Width(640)) + x: Array[Height, Width] = Array(shape) + y = abs(x) # Inferred type is Array[Height, Width] + z = x + x # ... is Array[Height, Width] + x.get_shape() # ... is tuple[Height, Width] + + """ + + # Trick Generic __parameters__. + __class__ = typing.TypeVar + + def __iter__(self): + yield self.__unpacked__ + + def __init__(self, name, *, default=NoDefault): + self.__name__ = name + _DefaultMixin.__init__(self, default) + + # for pickling: + def_mod = _caller() + if def_mod != 'typing_extensions': + self.__module__ = def_mod + + self.__unpacked__ = Unpack[self] + + def __repr__(self): + return self.__name__ + + def __hash__(self): + return object.__hash__(self) + + def __eq__(self, other): + return self is other + + def __reduce__(self): + return self.__name__ + + def __init_subclass__(self, *args, **kwds): + if '_root' not in kwds: + raise TypeError("Cannot subclass special typing classes") + + +if hasattr(typing, "reveal_type"): # 3.11+ + reveal_type = typing.reveal_type +else: # <=3.10 + def reveal_type(obj: T, /) -> T: + """Reveal the inferred type of a variable. + + When a static type checker encounters a call to ``reveal_type()``, + it will emit the inferred type of the argument:: + + x: int = 1 + reveal_type(x) + + Running a static type checker (e.g., ``mypy``) on this example + will produce output similar to 'Revealed type is "builtins.int"'. + + At runtime, the function prints the runtime type of the + argument and returns it unchanged. + + """ + print(f"Runtime type is {type(obj).__name__!r}", file=sys.stderr) + return obj + + +if hasattr(typing, "_ASSERT_NEVER_REPR_MAX_LENGTH"): # 3.11+ + _ASSERT_NEVER_REPR_MAX_LENGTH = typing._ASSERT_NEVER_REPR_MAX_LENGTH +else: # <=3.10 + _ASSERT_NEVER_REPR_MAX_LENGTH = 100 + + +if hasattr(typing, "assert_never"): # 3.11+ + assert_never = typing.assert_never +else: # <=3.10 + def assert_never(arg: Never, /) -> Never: + """Assert to the type checker that a line of code is unreachable. + + Example:: + + def int_or_str(arg: int | str) -> None: + match arg: + case int(): + print("It's an int") + case str(): + print("It's a str") + case _: + assert_never(arg) + + If a type checker finds that a call to assert_never() is + reachable, it will emit an error. + + At runtime, this throws an exception when called. + + """ + value = repr(arg) + if len(value) > _ASSERT_NEVER_REPR_MAX_LENGTH: + value = value[:_ASSERT_NEVER_REPR_MAX_LENGTH] + '...' + raise AssertionError(f"Expected code to be unreachable, but got: {value}") + + +# dataclass_transform exists in 3.11 but lacks the frozen_default parameter +# Breakpoint: https://github.com/python/cpython/pull/99958 +if sys.version_info >= (3, 12): # 3.12+ + dataclass_transform = typing.dataclass_transform +else: # <=3.11 + def dataclass_transform( + *, + eq_default: bool = True, + order_default: bool = False, + kw_only_default: bool = False, + frozen_default: bool = False, + field_specifiers: typing.Tuple[ + typing.Union[typing.Type[typing.Any], typing.Callable[..., typing.Any]], + ... + ] = (), + **kwargs: typing.Any, + ) -> typing.Callable[[T], T]: + """Decorator that marks a function, class, or metaclass as providing + dataclass-like behavior. + + Example: + + from typing_extensions import dataclass_transform + + _T = TypeVar("_T") + + # Used on a decorator function + @dataclass_transform() + def create_model(cls: type[_T]) -> type[_T]: + ... + return cls + + @create_model + class CustomerModel: + id: int + name: str + + # Used on a base class + @dataclass_transform() + class ModelBase: ... + + class CustomerModel(ModelBase): + id: int + name: str + + # Used on a metaclass + @dataclass_transform() + class ModelMeta(type): ... + + class ModelBase(metaclass=ModelMeta): ... + + class CustomerModel(ModelBase): + id: int + name: str + + Each of the ``CustomerModel`` classes defined in this example will now + behave similarly to a dataclass created with the ``@dataclasses.dataclass`` + decorator. For example, the type checker will synthesize an ``__init__`` + method. + + The arguments to this decorator can be used to customize this behavior: + - ``eq_default`` indicates whether the ``eq`` parameter is assumed to be + True or False if it is omitted by the caller. + - ``order_default`` indicates whether the ``order`` parameter is + assumed to be True or False if it is omitted by the caller. + - ``kw_only_default`` indicates whether the ``kw_only`` parameter is + assumed to be True or False if it is omitted by the caller. + - ``frozen_default`` indicates whether the ``frozen`` parameter is + assumed to be True or False if it is omitted by the caller. + - ``field_specifiers`` specifies a static list of supported classes + or functions that describe fields, similar to ``dataclasses.field()``. + + At runtime, this decorator records its arguments in the + ``__dataclass_transform__`` attribute on the decorated object. + + See PEP 681 for details. + + """ + def decorator(cls_or_fn): + cls_or_fn.__dataclass_transform__ = { + "eq_default": eq_default, + "order_default": order_default, + "kw_only_default": kw_only_default, + "frozen_default": frozen_default, + "field_specifiers": field_specifiers, + "kwargs": kwargs, + } + return cls_or_fn + return decorator + + +if hasattr(typing, "override"): # 3.12+ + override = typing.override +else: # <=3.11 + _F = typing.TypeVar("_F", bound=typing.Callable[..., typing.Any]) + + def override(arg: _F, /) -> _F: + """Indicate that a method is intended to override a method in a base class. + + Usage: + + class Base: + def method(self) -> None: + pass + + class Child(Base): + @override + def method(self) -> None: + super().method() + + When this decorator is applied to a method, the type checker will + validate that it overrides a method with the same name on a base class. + This helps prevent bugs that may occur when a base class is changed + without an equivalent change to a child class. + + There is no runtime checking of these properties. The decorator + sets the ``__override__`` attribute to ``True`` on the decorated object + to allow runtime introspection. + + See PEP 698 for details. + + """ + try: + arg.__override__ = True + except (AttributeError, TypeError): + # Skip the attribute silently if it is not writable. + # AttributeError happens if the object has __slots__ or a + # read-only property, TypeError if it's a builtin class. + pass + return arg + + +# Python 3.13.3+ contains a fix for the wrapped __new__ +# Breakpoint: https://github.com/python/cpython/pull/132160 +if sys.version_info >= (3, 13, 3): + deprecated = warnings.deprecated +else: + _T = typing.TypeVar("_T") + + class deprecated: + """Indicate that a class, function or overload is deprecated. + + When this decorator is applied to an object, the type checker + will generate a diagnostic on usage of the deprecated object. + + Usage: + + @deprecated("Use B instead") + class A: + pass + + @deprecated("Use g instead") + def f(): + pass + + @overload + @deprecated("int support is deprecated") + def g(x: int) -> int: ... + @overload + def g(x: str) -> int: ... + + The warning specified by *category* will be emitted at runtime + on use of deprecated objects. For functions, that happens on calls; + for classes, on instantiation and on creation of subclasses. + If the *category* is ``None``, no warning is emitted at runtime. + The *stacklevel* determines where the + warning is emitted. If it is ``1`` (the default), the warning + is emitted at the direct caller of the deprecated object; if it + is higher, it is emitted further up the stack. + Static type checker behavior is not affected by the *category* + and *stacklevel* arguments. + + The deprecation message passed to the decorator is saved in the + ``__deprecated__`` attribute on the decorated object. + If applied to an overload, the decorator + must be after the ``@overload`` decorator for the attribute to + exist on the overload as returned by ``get_overloads()``. + + See PEP 702 for details. + + """ + def __init__( + self, + message: str, + /, + *, + category: typing.Optional[typing.Type[Warning]] = DeprecationWarning, + stacklevel: int = 1, + ) -> None: + if not isinstance(message, str): + raise TypeError( + "Expected an object of type str for 'message', not " + f"{type(message).__name__!r}" + ) + self.message = message + self.category = category + self.stacklevel = stacklevel + + def __call__(self, arg: _T, /) -> _T: + # Make sure the inner functions created below don't + # retain a reference to self. + msg = self.message + category = self.category + stacklevel = self.stacklevel + if category is None: + arg.__deprecated__ = msg + return arg + elif isinstance(arg, type): + import functools + from types import MethodType + + original_new = arg.__new__ + + @functools.wraps(original_new) + def __new__(cls, /, *args, **kwargs): + if cls is arg: + warnings.warn(msg, category=category, stacklevel=stacklevel + 1) + if original_new is not object.__new__: + return original_new(cls, *args, **kwargs) + # Mirrors a similar check in object.__new__. + elif cls.__init__ is object.__init__ and (args or kwargs): + raise TypeError(f"{cls.__name__}() takes no arguments") + else: + return original_new(cls) + + arg.__new__ = staticmethod(__new__) + + original_init_subclass = arg.__init_subclass__ + # We need slightly different behavior if __init_subclass__ + # is a bound method (likely if it was implemented in Python) + if isinstance(original_init_subclass, MethodType): + original_init_subclass = original_init_subclass.__func__ + + @functools.wraps(original_init_subclass) + def __init_subclass__(*args, **kwargs): + warnings.warn(msg, category=category, stacklevel=stacklevel + 1) + return original_init_subclass(*args, **kwargs) + + arg.__init_subclass__ = classmethod(__init_subclass__) + # Or otherwise, which likely means it's a builtin such as + # object's implementation of __init_subclass__. + else: + @functools.wraps(original_init_subclass) + def __init_subclass__(*args, **kwargs): + warnings.warn(msg, category=category, stacklevel=stacklevel + 1) + return original_init_subclass(*args, **kwargs) + + arg.__init_subclass__ = __init_subclass__ + + arg.__deprecated__ = __new__.__deprecated__ = msg + __init_subclass__.__deprecated__ = msg + return arg + elif callable(arg): + import asyncio.coroutines + import functools + import inspect + + @functools.wraps(arg) + def wrapper(*args, **kwargs): + warnings.warn(msg, category=category, stacklevel=stacklevel + 1) + return arg(*args, **kwargs) + + if asyncio.coroutines.iscoroutinefunction(arg): + # Breakpoint: https://github.com/python/cpython/pull/99247 + if sys.version_info >= (3, 12): + wrapper = inspect.markcoroutinefunction(wrapper) + else: + wrapper._is_coroutine = asyncio.coroutines._is_coroutine + + arg.__deprecated__ = wrapper.__deprecated__ = msg + return wrapper + else: + raise TypeError( + "@deprecated decorator with non-None category must be applied to " + f"a class or callable, not {arg!r}" + ) + +# Breakpoint: https://github.com/python/cpython/pull/23702 +if sys.version_info < (3, 10): + def _is_param_expr(arg): + return arg is ... or isinstance( + arg, (tuple, list, ParamSpec, _ConcatenateGenericAlias) + ) +else: + def _is_param_expr(arg): + return arg is ... or isinstance( + arg, + ( + tuple, + list, + ParamSpec, + _ConcatenateGenericAlias, + typing._ConcatenateGenericAlias, + ), + ) + + +# We have to do some monkey patching to deal with the dual nature of +# Unpack/TypeVarTuple: +# - We want Unpack to be a kind of TypeVar so it gets accepted in +# Generic[Unpack[Ts]] +# - We want it to *not* be treated as a TypeVar for the purposes of +# counting generic parameters, so that when we subscript a generic, +# the runtime doesn't try to substitute the Unpack with the subscripted type. +if not hasattr(typing, "TypeVarTuple"): + def _check_generic(cls, parameters, elen=_marker): + """Check correct count for parameters of a generic cls (internal helper). + + This gives a nice error message in case of count mismatch. + """ + # If substituting a single ParamSpec with multiple arguments + # we do not check the count + if (inspect.isclass(cls) and issubclass(cls, typing.Generic) + and len(cls.__parameters__) == 1 + and isinstance(cls.__parameters__[0], ParamSpec) + and parameters + and not _is_param_expr(parameters[0]) + ): + # Generic modifies parameters variable, but here we cannot do this + return + + if not elen: + raise TypeError(f"{cls} is not a generic class") + if elen is _marker: + if not hasattr(cls, "__parameters__") or not cls.__parameters__: + raise TypeError(f"{cls} is not a generic class") + elen = len(cls.__parameters__) + alen = len(parameters) + if alen != elen: + expect_val = elen + if hasattr(cls, "__parameters__"): + parameters = [p for p in cls.__parameters__ if not _is_unpack(p)] + num_tv_tuples = sum(isinstance(p, TypeVarTuple) for p in parameters) + if (num_tv_tuples > 0) and (alen >= elen - num_tv_tuples): + return + + # deal with TypeVarLike defaults + # required TypeVarLikes cannot appear after a defaulted one. + if alen < elen: + # since we validate TypeVarLike default in _collect_type_vars + # or _collect_parameters we can safely check parameters[alen] + if ( + getattr(parameters[alen], '__default__', NoDefault) + is not NoDefault + ): + return + + num_default_tv = sum(getattr(p, '__default__', NoDefault) + is not NoDefault for p in parameters) + + elen -= num_default_tv + + expect_val = f"at least {elen}" + + # Breakpoint: https://github.com/python/cpython/pull/27515 + things = "arguments" if sys.version_info >= (3, 10) else "parameters" + raise TypeError(f"Too {'many' if alen > elen else 'few'} {things}" + f" for {cls}; actual {alen}, expected {expect_val}") +else: + # Python 3.11+ + + def _check_generic(cls, parameters, elen): + """Check correct count for parameters of a generic cls (internal helper). + + This gives a nice error message in case of count mismatch. + """ + if not elen: + raise TypeError(f"{cls} is not a generic class") + alen = len(parameters) + if alen != elen: + expect_val = elen + if hasattr(cls, "__parameters__"): + parameters = [p for p in cls.__parameters__ if not _is_unpack(p)] + + # deal with TypeVarLike defaults + # required TypeVarLikes cannot appear after a defaulted one. + if alen < elen: + # since we validate TypeVarLike default in _collect_type_vars + # or _collect_parameters we can safely check parameters[alen] + if ( + getattr(parameters[alen], '__default__', NoDefault) + is not NoDefault + ): + return + + num_default_tv = sum(getattr(p, '__default__', NoDefault) + is not NoDefault for p in parameters) + + elen -= num_default_tv + + expect_val = f"at least {elen}" + + raise TypeError(f"Too {'many' if alen > elen else 'few'} arguments" + f" for {cls}; actual {alen}, expected {expect_val}") + +if not _PEP_696_IMPLEMENTED: + typing._check_generic = _check_generic + + +def _has_generic_or_protocol_as_origin() -> bool: + try: + frame = sys._getframe(2) + # - Catch AttributeError: not all Python implementations have sys._getframe() + # - Catch ValueError: maybe we're called from an unexpected module + # and the call stack isn't deep enough + except (AttributeError, ValueError): + return False # err on the side of leniency + else: + # If we somehow get invoked from outside typing.py, + # also err on the side of leniency + if frame.f_globals.get("__name__") != "typing": + return False + origin = frame.f_locals.get("origin") + # Cannot use "in" because origin may be an object with a buggy __eq__ that + # throws an error. + return origin is typing.Generic or origin is Protocol or origin is typing.Protocol + + +_TYPEVARTUPLE_TYPES = {TypeVarTuple, getattr(typing, "TypeVarTuple", None)} + + +def _is_unpacked_typevartuple(x) -> bool: + if get_origin(x) is not Unpack: + return False + args = get_args(x) + return ( + bool(args) + and len(args) == 1 + and type(args[0]) in _TYPEVARTUPLE_TYPES + ) + + +# Python 3.11+ _collect_type_vars was renamed to _collect_parameters +if hasattr(typing, '_collect_type_vars'): + def _collect_type_vars(types, typevar_types=None): + """Collect all type variable contained in types in order of + first appearance (lexicographic order). For example:: + + _collect_type_vars((T, List[S, T])) == (T, S) + """ + if typevar_types is None: + typevar_types = typing.TypeVar + tvars = [] + + # A required TypeVarLike cannot appear after a TypeVarLike with a default + # if it was a direct call to `Generic[]` or `Protocol[]` + enforce_default_ordering = _has_generic_or_protocol_as_origin() + default_encountered = False + + # Also, a TypeVarLike with a default cannot appear after a TypeVarTuple + type_var_tuple_encountered = False + + for t in types: + if _is_unpacked_typevartuple(t): + type_var_tuple_encountered = True + elif ( + isinstance(t, typevar_types) and not isinstance(t, _UnpackAlias) + and t not in tvars + ): + if enforce_default_ordering: + has_default = getattr(t, '__default__', NoDefault) is not NoDefault + if has_default: + if type_var_tuple_encountered: + raise TypeError('Type parameter with a default' + ' follows TypeVarTuple') + default_encountered = True + elif default_encountered: + raise TypeError(f'Type parameter {t!r} without a default' + ' follows type parameter with a default') + + tvars.append(t) + if _should_collect_from_parameters(t): + tvars.extend([t for t in t.__parameters__ if t not in tvars]) + elif isinstance(t, tuple): + # Collect nested type_vars + # tuple wrapped by _prepare_paramspec_params(cls, params) + for x in t: + for collected in _collect_type_vars([x]): + if collected not in tvars: + tvars.append(collected) + return tuple(tvars) + + typing._collect_type_vars = _collect_type_vars +else: + def _collect_parameters(args): + """Collect all type variables and parameter specifications in args + in order of first appearance (lexicographic order). + + For example:: + + assert _collect_parameters((T, Callable[P, T])) == (T, P) + """ + parameters = [] + + # A required TypeVarLike cannot appear after a TypeVarLike with default + # if it was a direct call to `Generic[]` or `Protocol[]` + enforce_default_ordering = _has_generic_or_protocol_as_origin() + default_encountered = False + + # Also, a TypeVarLike with a default cannot appear after a TypeVarTuple + type_var_tuple_encountered = False + + for t in args: + if isinstance(t, type): + # We don't want __parameters__ descriptor of a bare Python class. + pass + elif isinstance(t, tuple): + # `t` might be a tuple, when `ParamSpec` is substituted with + # `[T, int]`, or `[int, *Ts]`, etc. + for x in t: + for collected in _collect_parameters([x]): + if collected not in parameters: + parameters.append(collected) + elif hasattr(t, '__typing_subst__'): + if t not in parameters: + if enforce_default_ordering: + has_default = ( + getattr(t, '__default__', NoDefault) is not NoDefault + ) + + if type_var_tuple_encountered and has_default: + raise TypeError('Type parameter with a default' + ' follows TypeVarTuple') + + if has_default: + default_encountered = True + elif default_encountered: + raise TypeError(f'Type parameter {t!r} without a default' + ' follows type parameter with a default') + + parameters.append(t) + else: + if _is_unpacked_typevartuple(t): + type_var_tuple_encountered = True + for x in getattr(t, '__parameters__', ()): + if x not in parameters: + parameters.append(x) + + return tuple(parameters) + + if not _PEP_696_IMPLEMENTED: + typing._collect_parameters = _collect_parameters + +# Backport typing.NamedTuple as it exists in Python 3.13. +# In 3.11, the ability to define generic `NamedTuple`s was supported. +# This was explicitly disallowed in 3.9-3.10, and only half-worked in <=3.8. +# On 3.12, we added __orig_bases__ to call-based NamedTuples +# On 3.13, we deprecated kwargs-based NamedTuples +# Breakpoint: https://github.com/python/cpython/pull/105609 +if sys.version_info >= (3, 13): + NamedTuple = typing.NamedTuple +else: + def _make_nmtuple(name, types, module, defaults=()): + fields = [n for n, t in types] + annotations = {n: typing._type_check(t, f"field {n} annotation must be a type") + for n, t in types} + nm_tpl = collections.namedtuple(name, fields, + defaults=defaults, module=module) + nm_tpl.__annotations__ = nm_tpl.__new__.__annotations__ = annotations + return nm_tpl + + _prohibited_namedtuple_fields = typing._prohibited + _special_namedtuple_fields = frozenset({'__module__', '__name__', '__annotations__'}) + + class _NamedTupleMeta(type): + def __new__(cls, typename, bases, ns): + assert _NamedTuple in bases + for base in bases: + if base is not _NamedTuple and base is not typing.Generic: + raise TypeError( + 'can only inherit from a NamedTuple type and Generic') + bases = tuple(tuple if base is _NamedTuple else base for base in bases) + if "__annotations__" in ns: + types = ns["__annotations__"] + elif "__annotate__" in ns: + # TODO: Use inspect.VALUE here, and make the annotations lazily evaluated + types = ns["__annotate__"](1) + else: + types = {} + default_names = [] + for field_name in types: + if field_name in ns: + default_names.append(field_name) + elif default_names: + raise TypeError(f"Non-default namedtuple field {field_name} " + f"cannot follow default field" + f"{'s' if len(default_names) > 1 else ''} " + f"{', '.join(default_names)}") + nm_tpl = _make_nmtuple( + typename, types.items(), + defaults=[ns[n] for n in default_names], + module=ns['__module__'] + ) + nm_tpl.__bases__ = bases + if typing.Generic in bases: + if hasattr(typing, '_generic_class_getitem'): # 3.12+ + nm_tpl.__class_getitem__ = classmethod(typing._generic_class_getitem) + else: + class_getitem = typing.Generic.__class_getitem__.__func__ + nm_tpl.__class_getitem__ = classmethod(class_getitem) + # update from user namespace without overriding special namedtuple attributes + for key, val in ns.items(): + if key in _prohibited_namedtuple_fields: + raise AttributeError("Cannot overwrite NamedTuple attribute " + key) + elif key not in _special_namedtuple_fields: + if key not in nm_tpl._fields: + setattr(nm_tpl, key, ns[key]) + try: + set_name = type(val).__set_name__ + except AttributeError: + pass + else: + try: + set_name(val, nm_tpl, key) + except BaseException as e: + msg = ( + f"Error calling __set_name__ on {type(val).__name__!r} " + f"instance {key!r} in {typename!r}" + ) + # BaseException.add_note() existed on py311, + # but the __set_name__ machinery didn't start + # using add_note() until py312. + # Making sure exceptions are raised in the same way + # as in "normal" classes seems most important here. + # Breakpoint: https://github.com/python/cpython/pull/95915 + if sys.version_info >= (3, 12): + e.add_note(msg) + raise + else: + raise RuntimeError(msg) from e + + if typing.Generic in bases: + nm_tpl.__init_subclass__() + return nm_tpl + + _NamedTuple = type.__new__(_NamedTupleMeta, 'NamedTuple', (), {}) + + def _namedtuple_mro_entries(bases): + assert NamedTuple in bases + return (_NamedTuple,) + + def NamedTuple(typename, fields=_marker, /, **kwargs): + """Typed version of namedtuple. + + Usage:: + + class Employee(NamedTuple): + name: str + id: int + + This is equivalent to:: + + Employee = collections.namedtuple('Employee', ['name', 'id']) + + The resulting class has an extra __annotations__ attribute, giving a + dict that maps field names to types. (The field names are also in + the _fields attribute, which is part of the namedtuple API.) + An alternative equivalent functional syntax is also accepted:: + + Employee = NamedTuple('Employee', [('name', str), ('id', int)]) + """ + if fields is _marker: + if kwargs: + deprecated_thing = "Creating NamedTuple classes using keyword arguments" + deprecation_msg = ( + "{name} is deprecated and will be disallowed in Python {remove}. " + "Use the class-based or functional syntax instead." + ) + else: + deprecated_thing = "Failing to pass a value for the 'fields' parameter" + example = f"`{typename} = NamedTuple({typename!r}, [])`" + deprecation_msg = ( + "{name} is deprecated and will be disallowed in Python {remove}. " + "To create a NamedTuple class with 0 fields " + "using the functional syntax, " + "pass an empty list, e.g. " + ) + example + "." + elif fields is None: + if kwargs: + raise TypeError( + "Cannot pass `None` as the 'fields' parameter " + "and also specify fields using keyword arguments" + ) + else: + deprecated_thing = "Passing `None` as the 'fields' parameter" + example = f"`{typename} = NamedTuple({typename!r}, [])`" + deprecation_msg = ( + "{name} is deprecated and will be disallowed in Python {remove}. " + "To create a NamedTuple class with 0 fields " + "using the functional syntax, " + "pass an empty list, e.g. " + ) + example + "." + elif kwargs: + raise TypeError("Either list of fields or keywords" + " can be provided to NamedTuple, not both") + if fields is _marker or fields is None: + warnings.warn( + deprecation_msg.format(name=deprecated_thing, remove="3.15"), + DeprecationWarning, + stacklevel=2, + ) + fields = kwargs.items() + nt = _make_nmtuple(typename, fields, module=_caller()) + nt.__orig_bases__ = (NamedTuple,) + return nt + + NamedTuple.__mro_entries__ = _namedtuple_mro_entries + + +if hasattr(collections.abc, "Buffer"): + Buffer = collections.abc.Buffer +else: + class Buffer(abc.ABC): # noqa: B024 + """Base class for classes that implement the buffer protocol. + + The buffer protocol allows Python objects to expose a low-level + memory buffer interface. Before Python 3.12, it is not possible + to implement the buffer protocol in pure Python code, or even + to check whether a class implements the buffer protocol. In + Python 3.12 and higher, the ``__buffer__`` method allows access + to the buffer protocol from Python code, and the + ``collections.abc.Buffer`` ABC allows checking whether a class + implements the buffer protocol. + + To indicate support for the buffer protocol in earlier versions, + inherit from this ABC, either in a stub file or at runtime, + or use ABC registration. This ABC provides no methods, because + there is no Python-accessible methods shared by pre-3.12 buffer + classes. It is useful primarily for static checks. + + """ + + # As a courtesy, register the most common stdlib buffer classes. + Buffer.register(memoryview) + Buffer.register(bytearray) + Buffer.register(bytes) + + +# Backport of types.get_original_bases, available on 3.12+ in CPython +if hasattr(_types, "get_original_bases"): + get_original_bases = _types.get_original_bases +else: + def get_original_bases(cls, /): + """Return the class's "original" bases prior to modification by `__mro_entries__`. + + Examples:: + + from typing import TypeVar, Generic + from typing_extensions import NamedTuple, TypedDict + + T = TypeVar("T") + class Foo(Generic[T]): ... + class Bar(Foo[int], float): ... + class Baz(list[str]): ... + Eggs = NamedTuple("Eggs", [("a", int), ("b", str)]) + Spam = TypedDict("Spam", {"a": int, "b": str}) + + assert get_original_bases(Bar) == (Foo[int], float) + assert get_original_bases(Baz) == (list[str],) + assert get_original_bases(Eggs) == (NamedTuple,) + assert get_original_bases(Spam) == (TypedDict,) + assert get_original_bases(int) == (object,) + """ + try: + return cls.__dict__.get("__orig_bases__", cls.__bases__) + except AttributeError: + raise TypeError( + f'Expected an instance of type, not {type(cls).__name__!r}' + ) from None + + +# NewType is a class on Python 3.10+, making it pickleable +# The error message for subclassing instances of NewType was improved on 3.11+ +# Breakpoint: https://github.com/python/cpython/pull/30268 +if sys.version_info >= (3, 11): + NewType = typing.NewType +else: + class NewType: + """NewType creates simple unique types with almost zero + runtime overhead. NewType(name, tp) is considered a subtype of tp + by static type checkers. At runtime, NewType(name, tp) returns + a dummy callable that simply returns its argument. Usage:: + UserId = NewType('UserId', int) + def name_by_id(user_id: UserId) -> str: + ... + UserId('user') # Fails type check + name_by_id(42) # Fails type check + name_by_id(UserId(42)) # OK + num = UserId(5) + 1 # type: int + """ + + def __call__(self, obj, /): + return obj + + def __init__(self, name, tp): + self.__qualname__ = name + if '.' in name: + name = name.rpartition('.')[-1] + self.__name__ = name + self.__supertype__ = tp + def_mod = _caller() + if def_mod != 'typing_extensions': + self.__module__ = def_mod + + def __mro_entries__(self, bases): + # We defined __mro_entries__ to get a better error message + # if a user attempts to subclass a NewType instance. bpo-46170 + supercls_name = self.__name__ + + class Dummy: + def __init_subclass__(cls): + subcls_name = cls.__name__ + raise TypeError( + f"Cannot subclass an instance of NewType. " + f"Perhaps you were looking for: " + f"`{subcls_name} = NewType({subcls_name!r}, {supercls_name})`" + ) + + return (Dummy,) + + def __repr__(self): + return f'{self.__module__}.{self.__qualname__}' + + def __reduce__(self): + return self.__qualname__ + + # Breakpoint: https://github.com/python/cpython/pull/21515 + if sys.version_info >= (3, 10): + # PEP 604 methods + # It doesn't make sense to have these methods on Python <3.10 + + def __or__(self, other): + return typing.Union[self, other] + + def __ror__(self, other): + return typing.Union[other, self] + + +# Breakpoint: https://github.com/python/cpython/pull/124795 +if sys.version_info >= (3, 14): + TypeAliasType = typing.TypeAliasType +# <=3.13 +else: + # Breakpoint: https://github.com/python/cpython/pull/103764 + if sys.version_info >= (3, 12): + # 3.12-3.13 + def _is_unionable(obj): + """Corresponds to is_unionable() in unionobject.c in CPython.""" + return obj is None or isinstance(obj, ( + type, + _types.GenericAlias, + _types.UnionType, + typing.TypeAliasType, + TypeAliasType, + )) + else: + # <=3.11 + def _is_unionable(obj): + """Corresponds to is_unionable() in unionobject.c in CPython.""" + return obj is None or isinstance(obj, ( + type, + _types.GenericAlias, + _types.UnionType, + TypeAliasType, + )) + + if sys.version_info < (3, 10): + # Copied and pasted from https://github.com/python/cpython/blob/986a4e1b6fcae7fe7a1d0a26aea446107dd58dd2/Objects/genericaliasobject.c#L568-L582, + # so that we emulate the behaviour of `types.GenericAlias` + # on the latest versions of CPython + _ATTRIBUTE_DELEGATION_EXCLUSIONS = frozenset({ + "__class__", + "__bases__", + "__origin__", + "__args__", + "__unpacked__", + "__parameters__", + "__typing_unpacked_tuple_args__", + "__mro_entries__", + "__reduce_ex__", + "__reduce__", + "__copy__", + "__deepcopy__", + }) + + class _TypeAliasGenericAlias(typing._GenericAlias, _root=True): + def __getattr__(self, attr): + if attr in _ATTRIBUTE_DELEGATION_EXCLUSIONS: + return object.__getattr__(self, attr) + return getattr(self.__origin__, attr) + + + class TypeAliasType: + """Create named, parameterized type aliases. + + This provides a backport of the new `type` statement in Python 3.12: + + type ListOrSet[T] = list[T] | set[T] + + is equivalent to: + + T = TypeVar("T") + ListOrSet = TypeAliasType("ListOrSet", list[T] | set[T], type_params=(T,)) + + The name ListOrSet can then be used as an alias for the type it refers to. + + The type_params argument should contain all the type parameters used + in the value of the type alias. If the alias is not generic, this + argument is omitted. + + Static type checkers should only support type aliases declared using + TypeAliasType that follow these rules: + + - The first argument (the name) must be a string literal. + - The TypeAliasType instance must be immediately assigned to a variable + of the same name. (For example, 'X = TypeAliasType("Y", int)' is invalid, + as is 'X, Y = TypeAliasType("X", int), TypeAliasType("Y", int)'). + + """ + + def __init__(self, name: str, value, *, type_params=()): + if not isinstance(name, str): + raise TypeError("TypeAliasType name must be a string") + if not isinstance(type_params, tuple): + raise TypeError("type_params must be a tuple") + self.__value__ = value + self.__type_params__ = type_params + + default_value_encountered = False + parameters = [] + for type_param in type_params: + if ( + not isinstance(type_param, (TypeVar, TypeVarTuple, ParamSpec)) + # <=3.11 + # Unpack Backport passes isinstance(type_param, TypeVar) + or _is_unpack(type_param) + ): + raise TypeError(f"Expected a type param, got {type_param!r}") + has_default = ( + getattr(type_param, '__default__', NoDefault) is not NoDefault + ) + if default_value_encountered and not has_default: + raise TypeError(f"non-default type parameter '{type_param!r}'" + " follows default type parameter") + if has_default: + default_value_encountered = True + if isinstance(type_param, TypeVarTuple): + parameters.extend(type_param) + else: + parameters.append(type_param) + self.__parameters__ = tuple(parameters) + def_mod = _caller() + if def_mod != 'typing_extensions': + self.__module__ = def_mod + # Setting this attribute closes the TypeAliasType from further modification + self.__name__ = name + + def __setattr__(self, name: str, value: object, /) -> None: + if hasattr(self, "__name__"): + self._raise_attribute_error(name) + super().__setattr__(name, value) + + def __delattr__(self, name: str, /) -> Never: + self._raise_attribute_error(name) + + def _raise_attribute_error(self, name: str) -> Never: + # Match the Python 3.12 error messages exactly + if name == "__name__": + raise AttributeError("readonly attribute") + elif name in {"__value__", "__type_params__", "__parameters__", "__module__"}: + raise AttributeError( + f"attribute '{name}' of 'typing.TypeAliasType' objects " + "is not writable" + ) + else: + raise AttributeError( + f"'typing.TypeAliasType' object has no attribute '{name}'" + ) + + def __repr__(self) -> str: + return self.__name__ + + if sys.version_info < (3, 11): + def _check_single_param(self, param, recursion=0): + # Allow [], [int], [int, str], [int, ...], [int, T] + if param is ...: + return ... + if param is None: + return None + # Note in <= 3.9 _ConcatenateGenericAlias inherits from list + if isinstance(param, list) and recursion == 0: + return [self._check_single_param(arg, recursion+1) + for arg in param] + return typing._type_check( + param, f'Subscripting {self.__name__} requires a type.' + ) + + def _check_parameters(self, parameters): + if sys.version_info < (3, 11): + return tuple( + self._check_single_param(item) + for item in parameters + ) + return tuple(typing._type_check( + item, f'Subscripting {self.__name__} requires a type.' + ) + for item in parameters + ) + + def __getitem__(self, parameters): + if not self.__type_params__: + raise TypeError("Only generic type aliases are subscriptable") + if not isinstance(parameters, tuple): + parameters = (parameters,) + # Using 3.9 here will create problems with Concatenate + if sys.version_info >= (3, 10): + return _types.GenericAlias(self, parameters) + type_vars = _collect_type_vars(parameters) + parameters = self._check_parameters(parameters) + alias = _TypeAliasGenericAlias(self, parameters) + # alias.__parameters__ is not complete if Concatenate is present + # as it is converted to a list from which no parameters are extracted. + if alias.__parameters__ != type_vars: + alias.__parameters__ = type_vars + return alias + + def __reduce__(self): + return self.__name__ + + def __init_subclass__(cls, *args, **kwargs): + raise TypeError( + "type 'typing_extensions.TypeAliasType' is not an acceptable base type" + ) + + # The presence of this method convinces typing._type_check + # that TypeAliasTypes are types. + def __call__(self): + raise TypeError("Type alias is not callable") + + # Breakpoint: https://github.com/python/cpython/pull/21515 + if sys.version_info >= (3, 10): + def __or__(self, right): + # For forward compatibility with 3.12, reject Unions + # that are not accepted by the built-in Union. + if not _is_unionable(right): + return NotImplemented + return typing.Union[self, right] + + def __ror__(self, left): + if not _is_unionable(left): + return NotImplemented + return typing.Union[left, self] + + +if hasattr(typing, "is_protocol"): + is_protocol = typing.is_protocol + get_protocol_members = typing.get_protocol_members +else: + def is_protocol(tp: type, /) -> bool: + """Return True if the given type is a Protocol. + + Example:: + + >>> from typing_extensions import Protocol, is_protocol + >>> class P(Protocol): + ... def a(self) -> str: ... + ... b: int + >>> is_protocol(P) + True + >>> is_protocol(int) + False + """ + return ( + isinstance(tp, type) + and getattr(tp, '_is_protocol', False) + and tp is not Protocol + and tp is not typing.Protocol + ) + + def get_protocol_members(tp: type, /) -> typing.FrozenSet[str]: + """Return the set of members defined in a Protocol. + + Example:: + + >>> from typing_extensions import Protocol, get_protocol_members + >>> class P(Protocol): + ... def a(self) -> str: ... + ... b: int + >>> get_protocol_members(P) + frozenset({'a', 'b'}) + + Raise a TypeError for arguments that are not Protocols. + """ + if not is_protocol(tp): + raise TypeError(f'{tp!r} is not a Protocol') + if hasattr(tp, '__protocol_attrs__'): + return frozenset(tp.__protocol_attrs__) + return frozenset(_get_protocol_attrs(tp)) + + +if hasattr(typing, "Doc"): + Doc = typing.Doc +else: + class Doc: + """Define the documentation of a type annotation using ``Annotated``, to be + used in class attributes, function and method parameters, return values, + and variables. + + The value should be a positional-only string literal to allow static tools + like editors and documentation generators to use it. + + This complements docstrings. + + The string value passed is available in the attribute ``documentation``. + + Example:: + + >>> from typing_extensions import Annotated, Doc + >>> def hi(to: Annotated[str, Doc("Who to say hi to")]) -> None: ... + """ + def __init__(self, documentation: str, /) -> None: + self.documentation = documentation + + def __repr__(self) -> str: + return f"Doc({self.documentation!r})" + + def __hash__(self) -> int: + return hash(self.documentation) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, Doc): + return NotImplemented + return self.documentation == other.documentation + + +_CapsuleType = getattr(_types, "CapsuleType", None) + +if _CapsuleType is None: + try: + import _socket + except ImportError: + pass + else: + _CAPI = getattr(_socket, "CAPI", None) + if _CAPI is not None: + _CapsuleType = type(_CAPI) + +if _CapsuleType is not None: + CapsuleType = _CapsuleType + __all__.append("CapsuleType") + + +if sys.version_info >= (3, 14): + from annotationlib import Format, get_annotations +else: + # Available since Python 3.14.0a3 + # PR: https://github.com/python/cpython/pull/124415 + class Format(enum.IntEnum): + VALUE = 1 + VALUE_WITH_FAKE_GLOBALS = 2 + FORWARDREF = 3 + STRING = 4 + + # Available since Python 3.14.0a1 + # PR: https://github.com/python/cpython/pull/119891 + def get_annotations(obj, *, globals=None, locals=None, eval_str=False, + format=Format.VALUE): + """Compute the annotations dict for an object. + + obj may be a callable, class, or module. + Passing in an object of any other type raises TypeError. + + Returns a dict. get_annotations() returns a new dict every time + it's called; calling it twice on the same object will return two + different but equivalent dicts. + + This is a backport of `inspect.get_annotations`, which has been + in the standard library since Python 3.10. See the standard library + documentation for more: + + https://docs.python.org/3/library/inspect.html#inspect.get_annotations + + This backport adds the *format* argument introduced by PEP 649. The + three formats supported are: + * VALUE: the annotations are returned as-is. This is the default and + it is compatible with the behavior on previous Python versions. + * FORWARDREF: return annotations as-is if possible, but replace any + undefined names with ForwardRef objects. The implementation proposed by + PEP 649 relies on language changes that cannot be backported; the + typing-extensions implementation simply returns the same result as VALUE. + * STRING: return annotations as strings, in a format close to the original + source. Again, this behavior cannot be replicated directly in a backport. + As an approximation, typing-extensions retrieves the annotations under + VALUE semantics and then stringifies them. + + The purpose of this backport is to allow users who would like to use + FORWARDREF or STRING semantics once PEP 649 is implemented, but who also + want to support earlier Python versions, to simply write: + + typing_extensions.get_annotations(obj, format=Format.FORWARDREF) + + """ + format = Format(format) + if format is Format.VALUE_WITH_FAKE_GLOBALS: + raise ValueError( + "The VALUE_WITH_FAKE_GLOBALS format is for internal use only" + ) + + if eval_str and format is not Format.VALUE: + raise ValueError("eval_str=True is only supported with format=Format.VALUE") + + if isinstance(obj, type): + # class + obj_dict = getattr(obj, '__dict__', None) + if obj_dict and hasattr(obj_dict, 'get'): + ann = obj_dict.get('__annotations__', None) + if isinstance(ann, _types.GetSetDescriptorType): + ann = None + else: + ann = None + + obj_globals = None + module_name = getattr(obj, '__module__', None) + if module_name: + module = sys.modules.get(module_name, None) + if module: + obj_globals = getattr(module, '__dict__', None) + obj_locals = dict(vars(obj)) + unwrap = obj + elif isinstance(obj, _types.ModuleType): + # module + ann = getattr(obj, '__annotations__', None) + obj_globals = obj.__dict__ + obj_locals = None + unwrap = None + elif callable(obj): + # this includes types.Function, types.BuiltinFunctionType, + # types.BuiltinMethodType, functools.partial, functools.singledispatch, + # "class funclike" from Lib/test/test_inspect... on and on it goes. + ann = getattr(obj, '__annotations__', None) + obj_globals = getattr(obj, '__globals__', None) + obj_locals = None + unwrap = obj + elif hasattr(obj, '__annotations__'): + ann = obj.__annotations__ + obj_globals = obj_locals = unwrap = None + else: + raise TypeError(f"{obj!r} is not a module, class, or callable.") + + if ann is None: + return {} + + if not isinstance(ann, dict): + raise ValueError(f"{obj!r}.__annotations__ is neither a dict nor None") + + if not ann: + return {} + + if not eval_str: + if format is Format.STRING: + return { + key: value if isinstance(value, str) else typing._type_repr(value) + for key, value in ann.items() + } + return dict(ann) + + if unwrap is not None: + while True: + if hasattr(unwrap, '__wrapped__'): + unwrap = unwrap.__wrapped__ + continue + if isinstance(unwrap, functools.partial): + unwrap = unwrap.func + continue + break + if hasattr(unwrap, "__globals__"): + obj_globals = unwrap.__globals__ + + if globals is None: + globals = obj_globals + if locals is None: + locals = obj_locals or {} + + # "Inject" type parameters into the local namespace + # (unless they are shadowed by assignments *in* the local namespace), + # as a way of emulating annotation scopes when calling `eval()` + if type_params := getattr(obj, "__type_params__", ()): + locals = {param.__name__: param for param in type_params} | locals + + return_value = {key: + value if not isinstance(value, str) else eval(value, globals, locals) + for key, value in ann.items() } + return return_value + + +if hasattr(typing, "evaluate_forward_ref"): + evaluate_forward_ref = typing.evaluate_forward_ref +else: + # Implements annotationlib.ForwardRef.evaluate + def _eval_with_owner( + forward_ref, *, owner=None, globals=None, locals=None, type_params=None + ): + if forward_ref.__forward_evaluated__: + return forward_ref.__forward_value__ + if getattr(forward_ref, "__cell__", None) is not None: + try: + value = forward_ref.__cell__.cell_contents + except ValueError: + pass + else: + forward_ref.__forward_evaluated__ = True + forward_ref.__forward_value__ = value + return value + if owner is None: + owner = getattr(forward_ref, "__owner__", None) + + if ( + globals is None + and getattr(forward_ref, "__forward_module__", None) is not None + ): + globals = getattr( + sys.modules.get(forward_ref.__forward_module__, None), "__dict__", None + ) + if globals is None: + globals = getattr(forward_ref, "__globals__", None) + if globals is None: + if isinstance(owner, type): + module_name = getattr(owner, "__module__", None) + if module_name: + module = sys.modules.get(module_name, None) + if module: + globals = getattr(module, "__dict__", None) + elif isinstance(owner, _types.ModuleType): + globals = getattr(owner, "__dict__", None) + elif callable(owner): + globals = getattr(owner, "__globals__", None) + + # If we pass None to eval() below, the globals of this module are used. + if globals is None: + globals = {} + + if locals is None: + locals = {} + if isinstance(owner, type): + locals.update(vars(owner)) + + if type_params is None and owner is not None: + # "Inject" type parameters into the local namespace + # (unless they are shadowed by assignments *in* the local namespace), + # as a way of emulating annotation scopes when calling `eval()` + type_params = getattr(owner, "__type_params__", None) + + # Type parameters exist in their own scope, which is logically + # between the locals and the globals. We simulate this by adding + # them to the globals. + if type_params is not None: + globals = dict(globals) + for param in type_params: + globals[param.__name__] = param + + arg = forward_ref.__forward_arg__ + if arg.isidentifier() and not keyword.iskeyword(arg): + if arg in locals: + value = locals[arg] + elif arg in globals: + value = globals[arg] + elif hasattr(builtins, arg): + return getattr(builtins, arg) + else: + raise NameError(arg) + else: + code = forward_ref.__forward_code__ + value = eval(code, globals, locals) + forward_ref.__forward_evaluated__ = True + forward_ref.__forward_value__ = value + return value + + def evaluate_forward_ref( + forward_ref, + *, + owner=None, + globals=None, + locals=None, + type_params=None, + format=None, + _recursive_guard=frozenset(), + ): + """Evaluate a forward reference as a type hint. + + This is similar to calling the ForwardRef.evaluate() method, + but unlike that method, evaluate_forward_ref() also: + + * Recursively evaluates forward references nested within the type hint. + * Rejects certain objects that are not valid type hints. + * Replaces type hints that evaluate to None with types.NoneType. + * Supports the *FORWARDREF* and *STRING* formats. + + *forward_ref* must be an instance of ForwardRef. *owner*, if given, + should be the object that holds the annotations that the forward reference + derived from, such as a module, class object, or function. It is used to + infer the namespaces to use for looking up names. *globals* and *locals* + can also be explicitly given to provide the global and local namespaces. + *type_params* is a tuple of type parameters that are in scope when + evaluating the forward reference. This parameter must be provided (though + it may be an empty tuple) if *owner* is not given and the forward reference + does not already have an owner set. *format* specifies the format of the + annotation and is a member of the annotationlib.Format enum. + + """ + if format == Format.STRING: + return forward_ref.__forward_arg__ + if forward_ref.__forward_arg__ in _recursive_guard: + return forward_ref + + # Evaluate the forward reference + try: + value = _eval_with_owner( + forward_ref, + owner=owner, + globals=globals, + locals=locals, + type_params=type_params, + ) + except NameError: + if format == Format.FORWARDREF: + return forward_ref + else: + raise + + if isinstance(value, str): + value = ForwardRef(value) + + # Recursively evaluate the type + if isinstance(value, ForwardRef): + if getattr(value, "__forward_module__", True) is not None: + globals = None + return evaluate_forward_ref( + value, + globals=globals, + locals=locals, + type_params=type_params, owner=owner, + _recursive_guard=_recursive_guard, format=format + ) + if sys.version_info < (3, 12, 5) and type_params: + # Make use of type_params + locals = dict(locals) if locals else {} + for tvar in type_params: + if tvar.__name__ not in locals: # lets not overwrite something present + locals[tvar.__name__] = tvar + if sys.version_info < (3, 12, 5): + return typing._eval_type( + value, + globals, + locals, + recursive_guard=_recursive_guard | {forward_ref.__forward_arg__}, + ) + else: + return typing._eval_type( + value, + globals, + locals, + type_params, + recursive_guard=_recursive_guard | {forward_ref.__forward_arg__}, + ) + + +class Sentinel: + """Create a unique sentinel object. + + *name* should be the name of the variable to which the return value shall be assigned. + + *repr*, if supplied, will be used for the repr of the sentinel object. + If not provided, "" will be used. + """ + + def __init__( + self, + name: str, + repr: typing.Optional[str] = None, + ): + self._name = name + self._repr = repr if repr is not None else f'<{name}>' + + def __repr__(self): + return self._repr + + if sys.version_info < (3, 11): + # The presence of this method convinces typing._type_check + # that Sentinels are types. + def __call__(self, *args, **kwargs): + raise TypeError(f"{type(self).__name__!r} object is not callable") + + # Breakpoint: https://github.com/python/cpython/pull/21515 + if sys.version_info >= (3, 10): + def __or__(self, other): + return typing.Union[self, other] + + def __ror__(self, other): + return typing.Union[other, self] + + def __getstate__(self): + raise TypeError(f"Cannot pickle {type(self).__name__!r} object") + + +if sys.version_info >= (3, 14, 0, "beta"): + type_repr = annotationlib.type_repr +else: + def type_repr(value): + """Convert a Python value to a format suitable for use with the STRING format. + + This is intended as a helper for tools that support the STRING format but do + not have access to the code that originally produced the annotations. It uses + repr() for most objects. + + """ + if isinstance(value, (type, _types.FunctionType, _types.BuiltinFunctionType)): + if value.__module__ == "builtins": + return value.__qualname__ + return f"{value.__module__}.{value.__qualname__}" + if value is ...: + return "..." + return repr(value) + + +# Aliases for items that are in typing in all supported versions. +# We use hasattr() checks so this library will continue to import on +# future versions of Python that may remove these names. +_typing_names = [ + "AbstractSet", + "AnyStr", + "BinaryIO", + "Callable", + "Collection", + "Container", + "Dict", + "FrozenSet", + "Hashable", + "IO", + "ItemsView", + "Iterable", + "Iterator", + "KeysView", + "List", + "Mapping", + "MappingView", + "Match", + "MutableMapping", + "MutableSequence", + "MutableSet", + "Optional", + "Pattern", + "Reversible", + "Sequence", + "Set", + "Sized", + "TextIO", + "Tuple", + "Union", + "ValuesView", + "cast", + "no_type_check", + "no_type_check_decorator", + # This is private, but it was defined by typing_extensions for a long time + # and some users rely on it. + "_AnnotatedAlias", +] +globals().update( + {name: getattr(typing, name) for name in _typing_names if hasattr(typing, name)} +) +# These are defined unconditionally because they are used in +# typing-extensions itself. +Generic = typing.Generic +ForwardRef = typing.ForwardRef +Annotated = typing.Annotated diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn-0.23.2.dist-info/INSTALLER b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn-0.23.2.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn-0.23.2.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn-0.23.2.dist-info/METADATA b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn-0.23.2.dist-info/METADATA new file mode 100644 index 0000000..f379265 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn-0.23.2.dist-info/METADATA @@ -0,0 +1,179 @@ +Metadata-Version: 2.4 +Name: uvicorn +Version: 0.23.2 +Summary: The lightning-fast ASGI server. +Project-URL: Changelog, https://github.com/encode/uvicorn/blob/master/CHANGELOG.md +Project-URL: Funding, https://github.com/sponsors/encode +Project-URL: Homepage, https://www.uvicorn.org/ +Project-URL: Source, https://github.com/encode/uvicorn +Author-email: Tom Christie +License-Expression: BSD-3-Clause +License-File: LICENSE.md +Classifier: Development Status :: 4 - Beta +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Internet :: WWW/HTTP +Requires-Python: >=3.8 +Requires-Dist: click>=7.0 +Requires-Dist: h11>=0.8 +Requires-Dist: typing-extensions>=4.0; python_version < '3.11' +Provides-Extra: standard +Requires-Dist: colorama>=0.4; (sys_platform == 'win32') and extra == 'standard' +Requires-Dist: httptools>=0.5.0; extra == 'standard' +Requires-Dist: python-dotenv>=0.13; extra == 'standard' +Requires-Dist: pyyaml>=5.1; extra == 'standard' +Requires-Dist: uvloop!=0.15.0,!=0.15.1,>=0.14.0; (sys_platform != 'win32' and (sys_platform != 'cygwin' and platform_python_implementation != 'PyPy')) and extra == 'standard' +Requires-Dist: watchfiles>=0.13; extra == 'standard' +Requires-Dist: websockets>=10.4; extra == 'standard' +Description-Content-Type: text/markdown + +

    + uvicorn +

    + +

    +An ASGI web server, for Python. +

    + +--- + +[![Build Status](https://github.com/encode/uvicorn/workflows/Test%20Suite/badge.svg)](https://github.com/encode/uvicorn/actions) +[![Package version](https://badge.fury.io/py/uvicorn.svg)](https://pypi.python.org/pypi/uvicorn) + +**Documentation**: [https://www.uvicorn.org](https://www.uvicorn.org) + +**Requirements**: Python 3.8+ + +Uvicorn is an ASGI web server implementation for Python. + +Until recently Python has lacked a minimal low-level server/application interface for +async frameworks. The [ASGI specification][asgi] fills this gap, and means we're now able to +start building a common set of tooling usable across all async frameworks. + +Uvicorn supports HTTP/1.1 and WebSockets. + +## Quickstart + +Install using `pip`: + +```shell +$ pip install uvicorn +``` + +This will install uvicorn with minimal (pure Python) dependencies. + +```shell +$ pip install 'uvicorn[standard]' +``` + +This will install uvicorn with "Cython-based" dependencies (where possible) and other "optional extras". + +In this context, "Cython-based" means the following: + +- the event loop `uvloop` will be installed and used if possible. +- the http protocol will be handled by `httptools` if possible. + +Moreover, "optional extras" means that: + +- the websocket protocol will be handled by `websockets` (should you want to use `wsproto` you'd need to install it manually) if possible. +- the `--reload` flag in development mode will use `watchfiles`. +- windows users will have `colorama` installed for the colored logs. +- `python-dotenv` will be installed should you want to use the `--env-file` option. +- `PyYAML` will be installed to allow you to provide a `.yaml` file to `--log-config`, if desired. + +Create an application, in `example.py`: + +```python +async def app(scope, receive, send): + assert scope['type'] == 'http' + + await send({ + 'type': 'http.response.start', + 'status': 200, + 'headers': [ + (b'content-type', b'text/plain'), + ], + }) + await send({ + 'type': 'http.response.body', + 'body': b'Hello, world!', + }) +``` + +Run the server: + +```shell +$ uvicorn example:app +``` + +--- + +## Why ASGI? + +Most well established Python Web frameworks started out as WSGI-based frameworks. + +WSGI applications are a single, synchronous callable that takes a request and returns a response. +This doesn’t allow for long-lived connections, like you get with long-poll HTTP or WebSocket connections, +which WSGI doesn't support well. + +Having an async concurrency model also allows for options such as lightweight background tasks, +and can be less of a limiting factor for endpoints that have long periods being blocked on network +I/O such as dealing with slow HTTP requests. + +--- + +## Alternative ASGI servers + +A strength of the ASGI protocol is that it decouples the server implementation +from the application framework. This allows for an ecosystem of interoperating +webservers and application frameworks. + +### Daphne + +The first ASGI server implementation, originally developed to power Django Channels, is [the Daphne webserver][daphne]. + +It is run widely in production, and supports HTTP/1.1, HTTP/2, and WebSockets. + +Any of the example applications given here can equally well be run using `daphne` instead. + +``` +$ pip install daphne +$ daphne app:App +``` + +### Hypercorn + +[Hypercorn][hypercorn] was initially part of the Quart web framework, before +being separated out into a standalone ASGI server. + +Hypercorn supports HTTP/1.1, HTTP/2, and WebSockets. + +It also supports [the excellent `trio` async framework][trio], as an alternative to `asyncio`. + +``` +$ pip install hypercorn +$ hypercorn app:App +``` + +### Mangum + +[Mangum][mangum] is an adapter for using ASGI applications with AWS Lambda & API Gateway. + +--- + +

    Uvicorn is BSD licensed code.
    Designed & crafted with care.

    — 🦄 —

    + +[asgi]: https://asgi.readthedocs.io/en/latest/ +[daphne]: https://github.com/django/daphne +[hypercorn]: https://github.com/pgjones/hypercorn +[mangum]: https://mangum.io +[trio]: https://trio.readthedocs.io diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn-0.23.2.dist-info/RECORD b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn-0.23.2.dist-info/RECORD new file mode 100644 index 0000000..a3da51d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn-0.23.2.dist-info/RECORD @@ -0,0 +1,48 @@ +../../bin/uvicorn,sha256=HkB_q6nOUy2QHmO2UWY1X7Oh475eNTUofDTU6CVj7FM,201 +uvicorn-0.23.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +uvicorn-0.23.2.dist-info/METADATA,sha256=68vxsrXCCeWXgmpm4nAwdVeY40bqaaexGCltgpD3uIs,6173 +uvicorn-0.23.2.dist-info/RECORD,, +uvicorn-0.23.2.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +uvicorn-0.23.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87 +uvicorn-0.23.2.dist-info/entry_points.txt,sha256=FW1w-hkc9QgwaGoovMvm0ZY73w_NcycWdGAUfDsNGxw,46 +uvicorn-0.23.2.dist-info/licenses/LICENSE.md,sha256=7-Gs8-YvuZwoiw7HPlp3O3Jo70Mg_nV-qZQhTktjw3E,1526 +uvicorn/__init__.py,sha256=5yqqy0VCxIqcsdpTBBB0eDEMP6VHFUIhc_1nsFzuzC8,147 +uvicorn/__main__.py,sha256=DQizy6nKP0ywhPpnCHgmRDYIMfcqZKVEzNIWQZjqtVQ,62 +uvicorn/_subprocess.py,sha256=zip7kqIlWL_GG7dBnl9dVuzScnjDt97VJJNH5PJFcts,2403 +uvicorn/_types.py,sha256=D6RGBlRV7_5_NDHmnmetSpiX8kGajdrAG7efhNHbPzs,7458 +uvicorn/config.py,sha256=q0vZZxKSK1l0kJDrUZvt2rxsnZZvDQ8Pl-Xd2dbAUls,21364 +uvicorn/importer.py,sha256=rUjBcH3xCBIvuEE7Buq4uWxjAzHPjEfP1dESQyAmPpU,1174 +uvicorn/lifespan/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +uvicorn/lifespan/off.py,sha256=vzXBbSkw_DmW7y9Kgba7fRWdJFBeJPtnzTnxUuJA8nM,302 +uvicorn/lifespan/on.py,sha256=XzBnwAjJFpO7GRA-sR2gGnnrCHBQH9niA4X-d8EIlyo,5182 +uvicorn/logging.py,sha256=dHOiKuWbWq8jtnEGScceF9_Q_LvHoMbCDhgnaW1aBvw,4255 +uvicorn/loops/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +uvicorn/loops/asyncio.py,sha256=VcornZKJoV8yBYgLON3Gd8YKpUxlLlardxy_LJq_PhE,276 +uvicorn/loops/auto.py,sha256=BWVq18ce9SoFTo3z5zNW2IU2850u2tRrc6WyK7idsdI,400 +uvicorn/loops/uvloop.py,sha256=K4QybYVxtK9C2emDhDPUCkBXR4XMT5Ofv9BPFPoX0ok,148 +uvicorn/main.py,sha256=6IlaWhFGK2fqgpIAdxp-1o0pic4JvfzFz4o5hAeuohk,16939 +uvicorn/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +uvicorn/middleware/asgi2.py,sha256=U5zg_1wqQMuPGWWs-uJqlUiqhDmluuVf3hYe3J9dC_k,408 +uvicorn/middleware/message_logger.py,sha256=IHEZUSnFNaMFUFdwtZO3AuFATnYcSor-gVtOjbCzt8M,2859 +uvicorn/middleware/proxy_headers.py,sha256=hYZAAXSk5_iMohtMzdO9lQ4kVBZnU950FuLnjvIBZfc,3261 +uvicorn/middleware/wsgi.py,sha256=BnPKY1qlV9W9QP0ZAuqLq2jWTXCr5_D8B-xjN5M5mmo,7014 +uvicorn/protocols/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +uvicorn/protocols/http/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +uvicorn/protocols/http/auto.py,sha256=fvYmlgqD3ockeVj13Hhjc3kMWBu8zj2D0npUQcvIraM,391 +uvicorn/protocols/http/flow_control.py,sha256=4ERvUKBa8Ocsmw-kpRmVkwbEnmuxPmKnOE-NV4mkE2M,1777 +uvicorn/protocols/http/h11_impl.py,sha256=TRO0ubSxPTxbVyoYGsYYn8fkgflk_ExftzCb53Q2644,19869 +uvicorn/protocols/http/httptools_impl.py,sha256=CeuBFgxeD-A6cL6QeeBt1Ya1pbd3YAyEmj89jS2m4Gs,21673 +uvicorn/protocols/utils.py,sha256=dwRewBrq5Y8-XzrnKOpUfzuolieN_tQkkZLJG-49RKs,1839 +uvicorn/protocols/websockets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +uvicorn/protocols/websockets/auto.py,sha256=H7irPeGN2MdHE29hdPKwca9YTA7HaOuWdIxvRuOgRtM,548 +uvicorn/protocols/websockets/websockets_impl.py,sha256=8Pvv2HeDDgEw09mxBgeLNGf9eJ8XGhXqv4-_qh1MCDk,13567 +uvicorn/protocols/websockets/wsproto_impl.py,sha256=nFj-v7D0LZy7uwQmaHi777BKkSvl7lSxmX80XGpSO8M,13040 +uvicorn/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 +uvicorn/server.py,sha256=jw2ZAvP1c8PpjYFlhwF90CD-bzyMw40QBt8yDYCmoXY,12253 +uvicorn/supervisors/__init__.py,sha256=YSH0n2BiqyN5m3QaT_QAkS0DkFE2xXHpKDc4ORbh82o,670 +uvicorn/supervisors/basereload.py,sha256=mVZwTaxbGCR2Jzfx60V3gEUHUWIcALoTSd15QcW4Nm8,3922 +uvicorn/supervisors/multiprocess.py,sha256=b-LzO1MiEN0HyhHJGx2gYMk9-Tuv2-tgmXzyJlnn7rA,2232 +uvicorn/supervisors/statreload.py,sha256=p4_6gR9wOWRT6k04DBiwtQl6GINwuKdoTZJz6afArT4,1580 +uvicorn/supervisors/watchfilesreload.py,sha256=zBi-AlpK7f82dQv83EqA0NRmT4mfvrL3wA1pjeq_BFw,2924 +uvicorn/supervisors/watchgodreload.py,sha256=Dg8jmR4d8S5J-ucj9-UP2MGWMzv3r1DUGr8Q3RCxE6A,5490 +uvicorn/workers.py,sha256=XKDxsZ4qrCc3adtWh6wtl3qQlExWPS0EGOsdBOvm1xg,3675 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn-0.23.2.dist-info/REQUESTED b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn-0.23.2.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn-0.23.2.dist-info/WHEEL b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn-0.23.2.dist-info/WHEEL new file mode 100644 index 0000000..12228d4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn-0.23.2.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: hatchling 1.27.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn-0.23.2.dist-info/entry_points.txt b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn-0.23.2.dist-info/entry_points.txt new file mode 100644 index 0000000..4b00fcb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn-0.23.2.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[console_scripts] +uvicorn = uvicorn.main:main diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn-0.23.2.dist-info/licenses/LICENSE.md b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn-0.23.2.dist-info/licenses/LICENSE.md new file mode 100644 index 0000000..a6bba14 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn-0.23.2.dist-info/licenses/LICENSE.md @@ -0,0 +1,27 @@ +Copyright © 2017-present, [Encode OSS Ltd](https://www.encode.io/). +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/__init__.py new file mode 100644 index 0000000..ff96505 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/__init__.py @@ -0,0 +1,5 @@ +from uvicorn.config import Config +from uvicorn.main import Server, main, run + +__version__ = "0.23.2" +__all__ = ["main", "run", "Config", "Server"] diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/__main__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/__main__.py new file mode 100644 index 0000000..8a1dc97 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/__main__.py @@ -0,0 +1,4 @@ +import uvicorn + +if __name__ == "__main__": + uvicorn.main() diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/_subprocess.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/_subprocess.py new file mode 100644 index 0000000..e05473c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/_subprocess.py @@ -0,0 +1,76 @@ +""" +Some light wrappers around Python's multiprocessing, to deal with cleanly +starting child processes. +""" +import multiprocessing +import os +import sys +from multiprocessing.context import SpawnProcess +from socket import socket +from typing import Callable, List, Optional + +from uvicorn.config import Config + +multiprocessing.allow_connection_pickling() +spawn = multiprocessing.get_context("spawn") + + +def get_subprocess( + config: Config, + target: Callable[..., None], + sockets: List[socket], +) -> SpawnProcess: + """ + Called in the parent process, to instantiate a new child process instance. + The child is not yet started at this point. + + * config - The Uvicorn configuration instance. + * target - A callable that accepts a list of sockets. In practice this will + be the `Server.run()` method. + * sockets - A list of sockets to pass to the server. Sockets are bound once + by the parent process, and then passed to the child processes. + """ + # We pass across the stdin fileno, and reopen it in the child process. + # This is required for some debugging environments. + stdin_fileno: Optional[int] + try: + stdin_fileno = sys.stdin.fileno() + except OSError: + stdin_fileno = None + + kwargs = { + "config": config, + "target": target, + "sockets": sockets, + "stdin_fileno": stdin_fileno, + } + + return spawn.Process(target=subprocess_started, kwargs=kwargs) + + +def subprocess_started( + config: Config, + target: Callable[..., None], + sockets: List[socket], + stdin_fileno: Optional[int], +) -> None: + """ + Called when the child process starts. + + * config - The Uvicorn configuration instance. + * target - A callable that accepts a list of sockets. In practice this will + be the `Server.run()` method. + * sockets - A list of sockets to pass to the server. Sockets are bound once + by the parent process, and then passed to the child processes. + * stdin_fileno - The file number of sys.stdin, so that it can be reattached + to the child process. + """ + # Re-open stdin. + if stdin_fileno is not None: + sys.stdin = os.fdopen(stdin_fileno) + + # Logging needs to be setup again for each child. + config.configure_logging() + + # Now we can call into `Server.run(sockets=sockets)` + target(sockets=sockets) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/_types.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/_types.py new file mode 100644 index 0000000..ecc3bd5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/_types.py @@ -0,0 +1,281 @@ +""" +Copyright (c) Django Software Foundation and individual contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of Django nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" + +import sys +import types +from typing import ( + Any, + Awaitable, + Callable, + Dict, + Iterable, + MutableMapping, + Optional, + Tuple, + Type, + Union, +) + +if sys.version_info >= (3, 8): # pragma: py-lt-38 + from typing import Literal, Protocol, TypedDict +else: # pragma: py-gte-38 + from typing_extensions import Literal, Protocol, TypedDict + +if sys.version_info >= (3, 11): # pragma: py-lt-311 + from typing import NotRequired +else: # pragma: py-gte-311 + from typing_extensions import NotRequired + +# WSGI +Environ = MutableMapping[str, Any] +ExcInfo = Tuple[Type[BaseException], BaseException, Optional[types.TracebackType]] +StartResponse = Callable[[str, Iterable[Tuple[str, str]], Optional[ExcInfo]], None] +WSGIApp = Callable[[Environ, StartResponse], Union[Iterable[bytes], BaseException]] + + +# ASGI +class ASGIVersions(TypedDict): + spec_version: str + version: Union[Literal["2.0"], Literal["3.0"]] + + +class HTTPScope(TypedDict): + type: Literal["http"] + asgi: ASGIVersions + http_version: str + method: str + scheme: str + path: str + raw_path: bytes + query_string: bytes + root_path: str + headers: Iterable[Tuple[bytes, bytes]] + client: Optional[Tuple[str, int]] + server: Optional[Tuple[str, Optional[int]]] + state: NotRequired[Dict[str, Any]] + extensions: NotRequired[Dict[str, Dict[object, object]]] + + +class WebSocketScope(TypedDict): + type: Literal["websocket"] + asgi: ASGIVersions + http_version: str + scheme: str + path: str + raw_path: bytes + query_string: bytes + root_path: str + headers: Iterable[Tuple[bytes, bytes]] + client: Optional[Tuple[str, int]] + server: Optional[Tuple[str, Optional[int]]] + subprotocols: Iterable[str] + state: NotRequired[Dict[str, Any]] + extensions: NotRequired[Dict[str, Dict[object, object]]] + + +class LifespanScope(TypedDict): + type: Literal["lifespan"] + asgi: ASGIVersions + state: NotRequired[Dict[str, Any]] + + +WWWScope = Union[HTTPScope, WebSocketScope] +Scope = Union[HTTPScope, WebSocketScope, LifespanScope] + + +class HTTPRequestEvent(TypedDict): + type: Literal["http.request"] + body: bytes + more_body: bool + + +class HTTPResponseDebugEvent(TypedDict): + type: Literal["http.response.debug"] + info: Dict[str, object] + + +class HTTPResponseStartEvent(TypedDict): + type: Literal["http.response.start"] + status: int + headers: Iterable[Tuple[bytes, bytes]] + trailers: NotRequired[bool] + + +class HTTPResponseBodyEvent(TypedDict): + type: Literal["http.response.body"] + body: bytes + more_body: bool + + +class HTTPResponseTrailersEvent(TypedDict): + type: Literal["http.response.trailers"] + headers: Iterable[Tuple[bytes, bytes]] + more_trailers: bool + + +class HTTPServerPushEvent(TypedDict): + type: Literal["http.response.push"] + path: str + headers: Iterable[Tuple[bytes, bytes]] + + +class HTTPDisconnectEvent(TypedDict): + type: Literal["http.disconnect"] + + +class WebSocketConnectEvent(TypedDict): + type: Literal["websocket.connect"] + + +class WebSocketAcceptEvent(TypedDict): + type: Literal["websocket.accept"] + subprotocol: Optional[str] + headers: Iterable[Tuple[bytes, bytes]] + + +class WebSocketReceiveEvent(TypedDict): + type: Literal["websocket.receive"] + bytes: Optional[bytes] + text: Optional[str] + + +class WebSocketSendEvent(TypedDict): + type: Literal["websocket.send"] + bytes: Optional[bytes] + text: Optional[str] + + +class WebSocketResponseStartEvent(TypedDict): + type: Literal["websocket.http.response.start"] + status: int + headers: Iterable[Tuple[bytes, bytes]] + + +class WebSocketResponseBodyEvent(TypedDict): + type: Literal["websocket.http.response.body"] + body: bytes + more_body: bool + + +class WebSocketDisconnectEvent(TypedDict): + type: Literal["websocket.disconnect"] + code: int + + +class WebSocketCloseEvent(TypedDict): + type: Literal["websocket.close"] + code: int + reason: Optional[str] + + +class LifespanStartupEvent(TypedDict): + type: Literal["lifespan.startup"] + + +class LifespanShutdownEvent(TypedDict): + type: Literal["lifespan.shutdown"] + + +class LifespanStartupCompleteEvent(TypedDict): + type: Literal["lifespan.startup.complete"] + + +class LifespanStartupFailedEvent(TypedDict): + type: Literal["lifespan.startup.failed"] + message: str + + +class LifespanShutdownCompleteEvent(TypedDict): + type: Literal["lifespan.shutdown.complete"] + + +class LifespanShutdownFailedEvent(TypedDict): + type: Literal["lifespan.shutdown.failed"] + message: str + + +WebSocketEvent = Union[ + WebSocketReceiveEvent, WebSocketDisconnectEvent, WebSocketConnectEvent +] + + +ASGIReceiveEvent = Union[ + HTTPRequestEvent, + HTTPDisconnectEvent, + WebSocketConnectEvent, + WebSocketReceiveEvent, + WebSocketDisconnectEvent, + LifespanStartupEvent, + LifespanShutdownEvent, +] + + +ASGISendEvent = Union[ + HTTPResponseStartEvent, + HTTPResponseBodyEvent, + HTTPResponseTrailersEvent, + HTTPServerPushEvent, + HTTPDisconnectEvent, + WebSocketAcceptEvent, + WebSocketSendEvent, + WebSocketResponseStartEvent, + WebSocketResponseBodyEvent, + WebSocketCloseEvent, + LifespanStartupCompleteEvent, + LifespanStartupFailedEvent, + LifespanShutdownCompleteEvent, + LifespanShutdownFailedEvent, +] + + +ASGIReceiveCallable = Callable[[], Awaitable[ASGIReceiveEvent]] +ASGISendCallable = Callable[[ASGISendEvent], Awaitable[None]] + + +class ASGI2Protocol(Protocol): + def __init__(self, scope: Scope) -> None: + ... # pragma: no cover + + async def __call__( + self, receive: ASGIReceiveCallable, send: ASGISendCallable + ) -> None: + ... # pragma: no cover + + +ASGI2Application = Type[ASGI2Protocol] +ASGI3Application = Callable[ + [ + Scope, + ASGIReceiveCallable, + ASGISendCallable, + ], + Awaitable[None], +] +ASGIApplication = Union[ASGI2Application, ASGI3Application] diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/config.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/config.py new file mode 100644 index 0000000..d1c66a4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/config.py @@ -0,0 +1,577 @@ +import asyncio +import inspect +import json +import logging +import logging.config +import os +import socket +import ssl +import sys +from pathlib import Path +from typing import ( + Any, + Awaitable, + Callable, + Dict, + List, + Literal, + Optional, + Tuple, + Type, + Union, +) + +import click + +from uvicorn._types import ASGIApplication +from uvicorn.importer import ImportFromStringError, import_from_string +from uvicorn.logging import TRACE_LOG_LEVEL +from uvicorn.middleware.asgi2 import ASGI2Middleware +from uvicorn.middleware.message_logger import MessageLoggerMiddleware +from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware +from uvicorn.middleware.wsgi import WSGIMiddleware + +HTTPProtocolType = Literal["auto", "h11", "httptools"] +WSProtocolType = Literal["auto", "none", "websockets", "wsproto"] +LifespanType = Literal["auto", "on", "off"] +LoopSetupType = Literal["none", "auto", "asyncio", "uvloop"] +InterfaceType = Literal["auto", "asgi3", "asgi2", "wsgi"] + +LOG_LEVELS: Dict[str, int] = { + "critical": logging.CRITICAL, + "error": logging.ERROR, + "warning": logging.WARNING, + "info": logging.INFO, + "debug": logging.DEBUG, + "trace": TRACE_LOG_LEVEL, +} +HTTP_PROTOCOLS: Dict[HTTPProtocolType, str] = { + "auto": "uvicorn.protocols.http.auto:AutoHTTPProtocol", + "h11": "uvicorn.protocols.http.h11_impl:H11Protocol", + "httptools": "uvicorn.protocols.http.httptools_impl:HttpToolsProtocol", +} +WS_PROTOCOLS: Dict[WSProtocolType, Optional[str]] = { + "auto": "uvicorn.protocols.websockets.auto:AutoWebSocketsProtocol", + "none": None, + "websockets": "uvicorn.protocols.websockets.websockets_impl:WebSocketProtocol", + "wsproto": "uvicorn.protocols.websockets.wsproto_impl:WSProtocol", +} +LIFESPAN: Dict[LifespanType, str] = { + "auto": "uvicorn.lifespan.on:LifespanOn", + "on": "uvicorn.lifespan.on:LifespanOn", + "off": "uvicorn.lifespan.off:LifespanOff", +} +LOOP_SETUPS: Dict[LoopSetupType, Optional[str]] = { + "none": None, + "auto": "uvicorn.loops.auto:auto_loop_setup", + "asyncio": "uvicorn.loops.asyncio:asyncio_setup", + "uvloop": "uvicorn.loops.uvloop:uvloop_setup", +} +INTERFACES: List[InterfaceType] = ["auto", "asgi3", "asgi2", "wsgi"] + +SSL_PROTOCOL_VERSION: int = ssl.PROTOCOL_TLS_SERVER + +LOGGING_CONFIG: Dict[str, Any] = { + "version": 1, + "disable_existing_loggers": False, + "formatters": { + "default": { + "()": "uvicorn.logging.DefaultFormatter", + "fmt": "%(levelprefix)s %(message)s", + "use_colors": None, + }, + "access": { + "()": "uvicorn.logging.AccessFormatter", + "fmt": '%(levelprefix)s %(client_addr)s - "%(request_line)s" %(status_code)s', # noqa: E501 + }, + }, + "handlers": { + "default": { + "formatter": "default", + "class": "logging.StreamHandler", + "stream": "ext://sys.stderr", + }, + "access": { + "formatter": "access", + "class": "logging.StreamHandler", + "stream": "ext://sys.stdout", + }, + }, + "loggers": { + "uvicorn": {"handlers": ["default"], "level": "INFO", "propagate": False}, + "uvicorn.error": {"level": "INFO"}, + "uvicorn.access": {"handlers": ["access"], "level": "INFO", "propagate": False}, + }, +} + +logger = logging.getLogger("uvicorn.error") + + +def create_ssl_context( + certfile: Union[str, os.PathLike], + keyfile: Optional[Union[str, os.PathLike]], + password: Optional[str], + ssl_version: int, + cert_reqs: int, + ca_certs: Optional[Union[str, os.PathLike]], + ciphers: Optional[str], +) -> ssl.SSLContext: + ctx = ssl.SSLContext(ssl_version) + get_password = (lambda: password) if password else None + ctx.load_cert_chain(certfile, keyfile, get_password) + ctx.verify_mode = ssl.VerifyMode(cert_reqs) + if ca_certs: + ctx.load_verify_locations(ca_certs) + if ciphers: + ctx.set_ciphers(ciphers) + return ctx + + +def is_dir(path: Path) -> bool: + try: + if not path.is_absolute(): + path = path.resolve() + return path.is_dir() + except OSError: + return False + + +def resolve_reload_patterns( + patterns_list: List[str], directories_list: List[str] +) -> Tuple[List[str], List[Path]]: + directories: List[Path] = list(set(map(Path, directories_list.copy()))) + patterns: List[str] = patterns_list.copy() + + current_working_directory = Path.cwd() + for pattern in patterns_list: + # Special case for the .* pattern, otherwise this would only match + # hidden directories which is probably undesired + if pattern == ".*": + continue + patterns.append(pattern) + if is_dir(Path(pattern)): + directories.append(Path(pattern)) + else: + for match in current_working_directory.glob(pattern): + if is_dir(match): + directories.append(match) + + directories = list(set(directories)) + directories = list(map(Path, directories)) + directories = list(map(lambda x: x.resolve(), directories)) + directories = list( + {reload_path for reload_path in directories if is_dir(reload_path)} + ) + + children = [] + for j in range(len(directories)): + for k in range(j + 1, len(directories)): + if directories[j] in directories[k].parents: + children.append(directories[k]) # pragma: py-darwin + elif directories[k] in directories[j].parents: + children.append(directories[j]) + + directories = list(set(directories).difference(set(children))) + + return list(set(patterns)), directories + + +def _normalize_dirs(dirs: Union[List[str], str, None]) -> List[str]: + if dirs is None: + return [] + if isinstance(dirs, str): + return [dirs] + return list(set(dirs)) + + +class Config: + def __init__( + self, + app: Union["ASGIApplication", Callable, str], + host: str = "127.0.0.1", + port: int = 8000, + uds: Optional[str] = None, + fd: Optional[int] = None, + loop: LoopSetupType = "auto", + http: Union[Type[asyncio.Protocol], HTTPProtocolType] = "auto", + ws: Union[Type[asyncio.Protocol], WSProtocolType] = "auto", + ws_max_size: int = 16 * 1024 * 1024, + ws_max_queue: int = 32, + ws_ping_interval: Optional[float] = 20.0, + ws_ping_timeout: Optional[float] = 20.0, + ws_per_message_deflate: bool = True, + lifespan: LifespanType = "auto", + env_file: Optional[Union[str, os.PathLike]] = None, + log_config: Optional[Union[Dict[str, Any], str]] = LOGGING_CONFIG, + log_level: Optional[Union[str, int]] = None, + access_log: bool = True, + use_colors: Optional[bool] = None, + interface: InterfaceType = "auto", + reload: bool = False, + reload_dirs: Optional[Union[List[str], str]] = None, + reload_delay: float = 0.25, + reload_includes: Optional[Union[List[str], str]] = None, + reload_excludes: Optional[Union[List[str], str]] = None, + workers: Optional[int] = None, + proxy_headers: bool = True, + server_header: bool = True, + date_header: bool = True, + forwarded_allow_ips: Optional[Union[List[str], str]] = None, + root_path: str = "", + limit_concurrency: Optional[int] = None, + limit_max_requests: Optional[int] = None, + backlog: int = 2048, + timeout_keep_alive: int = 5, + timeout_notify: int = 30, + timeout_graceful_shutdown: Optional[int] = None, + callback_notify: Optional[Callable[..., Awaitable[None]]] = None, + ssl_keyfile: Optional[str] = None, + ssl_certfile: Optional[Union[str, os.PathLike]] = None, + ssl_keyfile_password: Optional[str] = None, + ssl_version: int = SSL_PROTOCOL_VERSION, + ssl_cert_reqs: int = ssl.CERT_NONE, + ssl_ca_certs: Optional[str] = None, + ssl_ciphers: str = "TLSv1", + headers: Optional[List[Tuple[str, str]]] = None, + factory: bool = False, + h11_max_incomplete_event_size: Optional[int] = None, + ): + self.app = app + self.host = host + self.port = port + self.uds = uds + self.fd = fd + self.loop = loop + self.http = http + self.ws = ws + self.ws_max_size = ws_max_size + self.ws_max_queue = ws_max_queue + self.ws_ping_interval = ws_ping_interval + self.ws_ping_timeout = ws_ping_timeout + self.ws_per_message_deflate = ws_per_message_deflate + self.lifespan = lifespan + self.log_config = log_config + self.log_level = log_level + self.access_log = access_log + self.use_colors = use_colors + self.interface = interface + self.reload = reload + self.reload_delay = reload_delay + self.workers = workers or 1 + self.proxy_headers = proxy_headers + self.server_header = server_header + self.date_header = date_header + self.root_path = root_path + self.limit_concurrency = limit_concurrency + self.limit_max_requests = limit_max_requests + self.backlog = backlog + self.timeout_keep_alive = timeout_keep_alive + self.timeout_notify = timeout_notify + self.timeout_graceful_shutdown = timeout_graceful_shutdown + self.callback_notify = callback_notify + self.ssl_keyfile = ssl_keyfile + self.ssl_certfile = ssl_certfile + self.ssl_keyfile_password = ssl_keyfile_password + self.ssl_version = ssl_version + self.ssl_cert_reqs = ssl_cert_reqs + self.ssl_ca_certs = ssl_ca_certs + self.ssl_ciphers = ssl_ciphers + self.headers: List[Tuple[str, str]] = headers or [] + self.encoded_headers: List[Tuple[bytes, bytes]] = [] + self.factory = factory + self.h11_max_incomplete_event_size = h11_max_incomplete_event_size + + self.loaded = False + self.configure_logging() + + self.reload_dirs: List[Path] = [] + self.reload_dirs_excludes: List[Path] = [] + self.reload_includes: List[str] = [] + self.reload_excludes: List[str] = [] + + if ( + reload_dirs or reload_includes or reload_excludes + ) and not self.should_reload: + logger.warning( + "Current configuration will not reload as not all conditions are met, " + "please refer to documentation." + ) + + if self.should_reload: + reload_dirs = _normalize_dirs(reload_dirs) + reload_includes = _normalize_dirs(reload_includes) + reload_excludes = _normalize_dirs(reload_excludes) + + self.reload_includes, self.reload_dirs = resolve_reload_patterns( + reload_includes, reload_dirs + ) + + self.reload_excludes, self.reload_dirs_excludes = resolve_reload_patterns( + reload_excludes, [] + ) + + reload_dirs_tmp = self.reload_dirs.copy() + + for directory in self.reload_dirs_excludes: + for reload_directory in reload_dirs_tmp: + if ( + directory == reload_directory + or directory in reload_directory.parents + ): + try: + self.reload_dirs.remove(reload_directory) + except ValueError: + pass + + for pattern in self.reload_excludes: + if pattern in self.reload_includes: + self.reload_includes.remove(pattern) + + if not self.reload_dirs: + if reload_dirs: + logger.warning( + "Provided reload directories %s did not contain valid " + + "directories, watching current working directory.", + reload_dirs, + ) + self.reload_dirs = [Path(os.getcwd())] + + logger.info( + "Will watch for changes in these directories: %s", + sorted(list(map(str, self.reload_dirs))), + ) + + if env_file is not None: + from dotenv import load_dotenv + + logger.info("Loading environment from '%s'", env_file) + load_dotenv(dotenv_path=env_file) + + if workers is None and "WEB_CONCURRENCY" in os.environ: + self.workers = int(os.environ["WEB_CONCURRENCY"]) + + self.forwarded_allow_ips: Union[List[str], str] + if forwarded_allow_ips is None: + self.forwarded_allow_ips = os.environ.get( + "FORWARDED_ALLOW_IPS", "127.0.0.1" + ) + else: + self.forwarded_allow_ips = forwarded_allow_ips + + if self.reload and self.workers > 1: + logger.warning('"workers" flag is ignored when reloading is enabled.') + + @property + def asgi_version(self) -> Literal["2.0", "3.0"]: + mapping: Dict[str, Literal["2.0", "3.0"]] = { + "asgi2": "2.0", + "asgi3": "3.0", + "wsgi": "3.0", + } + return mapping[self.interface] + + @property + def is_ssl(self) -> bool: + return bool(self.ssl_keyfile or self.ssl_certfile) + + @property + def use_subprocess(self) -> bool: + return bool(self.reload or self.workers > 1) + + def configure_logging(self) -> None: + logging.addLevelName(TRACE_LOG_LEVEL, "TRACE") + + if self.log_config is not None: + if isinstance(self.log_config, dict): + if self.use_colors in (True, False): + self.log_config["formatters"]["default"][ + "use_colors" + ] = self.use_colors + self.log_config["formatters"]["access"][ + "use_colors" + ] = self.use_colors + logging.config.dictConfig(self.log_config) + elif self.log_config.endswith(".json"): + with open(self.log_config) as file: + loaded_config = json.load(file) + logging.config.dictConfig(loaded_config) + elif self.log_config.endswith((".yaml", ".yml")): + # Install the PyYAML package or the uvicorn[standard] optional + # dependencies to enable this functionality. + import yaml + + with open(self.log_config) as file: + loaded_config = yaml.safe_load(file) + logging.config.dictConfig(loaded_config) + else: + # See the note about fileConfig() here: + # https://docs.python.org/3/library/logging.config.html#configuration-file-format + logging.config.fileConfig( + self.log_config, disable_existing_loggers=False + ) + + if self.log_level is not None: + if isinstance(self.log_level, str): + log_level = LOG_LEVELS[self.log_level] + else: + log_level = self.log_level + logging.getLogger("uvicorn.error").setLevel(log_level) + logging.getLogger("uvicorn.access").setLevel(log_level) + logging.getLogger("uvicorn.asgi").setLevel(log_level) + if self.access_log is False: + logging.getLogger("uvicorn.access").handlers = [] + logging.getLogger("uvicorn.access").propagate = False + + def load(self) -> None: + assert not self.loaded + + if self.is_ssl: + assert self.ssl_certfile + self.ssl: Optional[ssl.SSLContext] = create_ssl_context( + keyfile=self.ssl_keyfile, + certfile=self.ssl_certfile, + password=self.ssl_keyfile_password, + ssl_version=self.ssl_version, + cert_reqs=self.ssl_cert_reqs, + ca_certs=self.ssl_ca_certs, + ciphers=self.ssl_ciphers, + ) + else: + self.ssl = None + + encoded_headers = [ + (key.lower().encode("latin1"), value.encode("latin1")) + for key, value in self.headers + ] + self.encoded_headers = ( + [(b"server", b"uvicorn")] + encoded_headers + if b"server" not in dict(encoded_headers) and self.server_header + else encoded_headers + ) + + if isinstance(self.http, str): + http_protocol_class = import_from_string(HTTP_PROTOCOLS[self.http]) + self.http_protocol_class: Type[asyncio.Protocol] = http_protocol_class + else: + self.http_protocol_class = self.http + + if isinstance(self.ws, str): + ws_protocol_class = import_from_string(WS_PROTOCOLS[self.ws]) + self.ws_protocol_class: Optional[Type[asyncio.Protocol]] = ws_protocol_class + else: + self.ws_protocol_class = self.ws + + self.lifespan_class = import_from_string(LIFESPAN[self.lifespan]) + + try: + self.loaded_app = import_from_string(self.app) + except ImportFromStringError as exc: + logger.error("Error loading ASGI app. %s" % exc) + sys.exit(1) + + try: + self.loaded_app = self.loaded_app() + except TypeError as exc: + if self.factory: + logger.error("Error loading ASGI app factory: %s", exc) + sys.exit(1) + else: + if not self.factory: + logger.warning( + "ASGI app factory detected. Using it, " + "but please consider setting the --factory flag explicitly." + ) + + if self.interface == "auto": + if inspect.isclass(self.loaded_app): + use_asgi_3 = hasattr(self.loaded_app, "__await__") + elif inspect.isfunction(self.loaded_app): + use_asgi_3 = asyncio.iscoroutinefunction(self.loaded_app) + else: + call = getattr(self.loaded_app, "__call__", None) + use_asgi_3 = asyncio.iscoroutinefunction(call) + self.interface = "asgi3" if use_asgi_3 else "asgi2" + + if self.interface == "wsgi": + self.loaded_app = WSGIMiddleware(self.loaded_app) + self.ws_protocol_class = None + elif self.interface == "asgi2": + self.loaded_app = ASGI2Middleware(self.loaded_app) + + if logger.getEffectiveLevel() <= TRACE_LOG_LEVEL: + self.loaded_app = MessageLoggerMiddleware(self.loaded_app) + if self.proxy_headers: + self.loaded_app = ProxyHeadersMiddleware( + self.loaded_app, trusted_hosts=self.forwarded_allow_ips + ) + + self.loaded = True + + def setup_event_loop(self) -> None: + loop_setup: Optional[Callable] = import_from_string(LOOP_SETUPS[self.loop]) + if loop_setup is not None: + loop_setup(use_subprocess=self.use_subprocess) + + def bind_socket(self) -> socket.socket: + logger_args: List[Union[str, int]] + if self.uds: # pragma: py-win32 + path = self.uds + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + try: + sock.bind(path) + uds_perms = 0o666 + os.chmod(self.uds, uds_perms) + except OSError as exc: + logger.error(exc) + sys.exit(1) + + message = "Uvicorn running on unix socket %s (Press CTRL+C to quit)" + sock_name_format = "%s" + color_message = ( + "Uvicorn running on " + + click.style(sock_name_format, bold=True) + + " (Press CTRL+C to quit)" + ) + logger_args = [self.uds] + elif self.fd: # pragma: py-win32 + sock = socket.fromfd(self.fd, socket.AF_UNIX, socket.SOCK_STREAM) + message = "Uvicorn running on socket %s (Press CTRL+C to quit)" + fd_name_format = "%s" + color_message = ( + "Uvicorn running on " + + click.style(fd_name_format, bold=True) + + " (Press CTRL+C to quit)" + ) + logger_args = [sock.getsockname()] + else: + family = socket.AF_INET + addr_format = "%s://%s:%d" + + if self.host and ":" in self.host: # pragma: py-win32 + # It's an IPv6 address. + family = socket.AF_INET6 + addr_format = "%s://[%s]:%d" + + sock = socket.socket(family=family) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + try: + sock.bind((self.host, self.port)) + except OSError as exc: + logger.error(exc) + sys.exit(1) + + message = f"Uvicorn running on {addr_format} (Press CTRL+C to quit)" + color_message = ( + "Uvicorn running on " + + click.style(addr_format, bold=True) + + " (Press CTRL+C to quit)" + ) + protocol_name = "https" if self.is_ssl else "http" + logger_args = [protocol_name, self.host, sock.getsockname()[1]] + logger.info(message, *logger_args, extra={"color_message": color_message}) + sock.set_inheritable(True) + return sock + + @property + def should_reload(self) -> bool: + return isinstance(self.app, str) and self.reload diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/importer.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/importer.py new file mode 100644 index 0000000..338eba2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/importer.py @@ -0,0 +1,38 @@ +import importlib +from typing import Any + + +class ImportFromStringError(Exception): + pass + + +def import_from_string(import_str: Any) -> Any: + if not isinstance(import_str, str): + return import_str + + module_str, _, attrs_str = import_str.partition(":") + if not module_str or not attrs_str: + message = ( + 'Import string "{import_str}" must be in format ":".' + ) + raise ImportFromStringError(message.format(import_str=import_str)) + + try: + module = importlib.import_module(module_str) + except ModuleNotFoundError as exc: + if exc.name != module_str: + raise exc from None + message = 'Could not import module "{module_str}".' + raise ImportFromStringError(message.format(module_str=module_str)) + + instance = module + try: + for attr_str in attrs_str.split("."): + instance = getattr(instance, attr_str) + except AttributeError: + message = 'Attribute "{attrs_str}" not found in module "{module_str}".' + raise ImportFromStringError( + message.format(attrs_str=attrs_str, module_str=module_str) + ) + + return instance diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/lifespan/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/lifespan/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/lifespan/off.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/lifespan/off.py new file mode 100644 index 0000000..e1516f1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/lifespan/off.py @@ -0,0 +1,15 @@ +from typing import Any, Dict + +from uvicorn import Config + + +class LifespanOff: + def __init__(self, config: Config) -> None: + self.should_exit = False + self.state: Dict[str, Any] = {} + + async def startup(self) -> None: + pass + + async def shutdown(self) -> None: + pass diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/lifespan/on.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/lifespan/on.py new file mode 100644 index 0000000..34dfdb1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/lifespan/on.py @@ -0,0 +1,137 @@ +import asyncio +import logging +from asyncio import Queue +from typing import Any, Dict, Union + +from uvicorn import Config +from uvicorn._types import ( + LifespanScope, + LifespanShutdownCompleteEvent, + LifespanShutdownEvent, + LifespanShutdownFailedEvent, + LifespanStartupCompleteEvent, + LifespanStartupEvent, + LifespanStartupFailedEvent, +) + +LifespanReceiveMessage = Union[LifespanStartupEvent, LifespanShutdownEvent] +LifespanSendMessage = Union[ + LifespanStartupFailedEvent, + LifespanShutdownFailedEvent, + LifespanStartupCompleteEvent, + LifespanShutdownCompleteEvent, +] + + +STATE_TRANSITION_ERROR = "Got invalid state transition on lifespan protocol." + + +class LifespanOn: + def __init__(self, config: Config) -> None: + if not config.loaded: + config.load() + + self.config = config + self.logger = logging.getLogger("uvicorn.error") + self.startup_event = asyncio.Event() + self.shutdown_event = asyncio.Event() + self.receive_queue: "Queue[LifespanReceiveMessage]" = asyncio.Queue() + self.error_occured = False + self.startup_failed = False + self.shutdown_failed = False + self.should_exit = False + self.state: Dict[str, Any] = {} + + async def startup(self) -> None: + self.logger.info("Waiting for application startup.") + + loop = asyncio.get_event_loop() + main_lifespan_task = loop.create_task(self.main()) # noqa: F841 + # Keep a hard reference to prevent garbage collection + # See https://github.com/encode/uvicorn/pull/972 + startup_event: LifespanStartupEvent = {"type": "lifespan.startup"} + await self.receive_queue.put(startup_event) + await self.startup_event.wait() + + if self.startup_failed or (self.error_occured and self.config.lifespan == "on"): + self.logger.error("Application startup failed. Exiting.") + self.should_exit = True + else: + self.logger.info("Application startup complete.") + + async def shutdown(self) -> None: + if self.error_occured: + return + self.logger.info("Waiting for application shutdown.") + shutdown_event: LifespanShutdownEvent = {"type": "lifespan.shutdown"} + await self.receive_queue.put(shutdown_event) + await self.shutdown_event.wait() + + if self.shutdown_failed or ( + self.error_occured and self.config.lifespan == "on" + ): + self.logger.error("Application shutdown failed. Exiting.") + self.should_exit = True + else: + self.logger.info("Application shutdown complete.") + + async def main(self) -> None: + try: + app = self.config.loaded_app + scope: LifespanScope = { + "type": "lifespan", + "asgi": {"version": self.config.asgi_version, "spec_version": "2.0"}, + "state": self.state, + } + await app(scope, self.receive, self.send) + except BaseException as exc: + self.asgi = None + self.error_occured = True + if self.startup_failed or self.shutdown_failed: + return + if self.config.lifespan == "auto": + msg = "ASGI 'lifespan' protocol appears unsupported." + self.logger.info(msg) + else: + msg = "Exception in 'lifespan' protocol\n" + self.logger.error(msg, exc_info=exc) + finally: + self.startup_event.set() + self.shutdown_event.set() + + async def send(self, message: "LifespanSendMessage") -> None: + assert message["type"] in ( + "lifespan.startup.complete", + "lifespan.startup.failed", + "lifespan.shutdown.complete", + "lifespan.shutdown.failed", + ) + + if message["type"] == "lifespan.startup.complete": + assert not self.startup_event.is_set(), STATE_TRANSITION_ERROR + assert not self.shutdown_event.is_set(), STATE_TRANSITION_ERROR + self.startup_event.set() + + elif message["type"] == "lifespan.startup.failed": + assert not self.startup_event.is_set(), STATE_TRANSITION_ERROR + assert not self.shutdown_event.is_set(), STATE_TRANSITION_ERROR + self.startup_event.set() + self.startup_failed = True + if message.get("message"): + self.logger.error(message["message"]) + + elif message["type"] == "lifespan.shutdown.complete": + assert self.startup_event.is_set(), STATE_TRANSITION_ERROR + assert not self.shutdown_event.is_set(), STATE_TRANSITION_ERROR + self.shutdown_event.set() + + elif message["type"] == "lifespan.shutdown.failed": + assert self.startup_event.is_set(), STATE_TRANSITION_ERROR + assert not self.shutdown_event.is_set(), STATE_TRANSITION_ERROR + self.shutdown_event.set() + self.shutdown_failed = True + if message.get("message"): + self.logger.error(message["message"]) + + async def receive(self) -> "LifespanReceiveMessage": + return await self.receive_queue.get() diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/logging.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/logging.py new file mode 100644 index 0000000..c88d5fe --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/logging.py @@ -0,0 +1,117 @@ +import http +import logging +import sys +from copy import copy +from typing import Literal, Optional + +import click + +TRACE_LOG_LEVEL = 5 + + +class ColourizedFormatter(logging.Formatter): + """ + A custom log formatter class that: + + * Outputs the LOG_LEVEL with an appropriate color. + * If a log call includes an `extras={"color_message": ...}` it will be used + for formatting the output, instead of the plain text message. + """ + + level_name_colors = { + TRACE_LOG_LEVEL: lambda level_name: click.style(str(level_name), fg="blue"), + logging.DEBUG: lambda level_name: click.style(str(level_name), fg="cyan"), + logging.INFO: lambda level_name: click.style(str(level_name), fg="green"), + logging.WARNING: lambda level_name: click.style(str(level_name), fg="yellow"), + logging.ERROR: lambda level_name: click.style(str(level_name), fg="red"), + logging.CRITICAL: lambda level_name: click.style( + str(level_name), fg="bright_red" + ), + } + + def __init__( + self, + fmt: Optional[str] = None, + datefmt: Optional[str] = None, + style: Literal["%", "{", "$"] = "%", + use_colors: Optional[bool] = None, + ): + if use_colors in (True, False): + self.use_colors = use_colors + else: + self.use_colors = sys.stdout.isatty() + super().__init__(fmt=fmt, datefmt=datefmt, style=style) + + def color_level_name(self, level_name: str, level_no: int) -> str: + def default(level_name: str) -> str: + return str(level_name) # pragma: no cover + + func = self.level_name_colors.get(level_no, default) + return func(level_name) + + def should_use_colors(self) -> bool: + return True # pragma: no cover + + def formatMessage(self, record: logging.LogRecord) -> str: + recordcopy = copy(record) + levelname = recordcopy.levelname + seperator = " " * (8 - len(recordcopy.levelname)) + if self.use_colors: + levelname = self.color_level_name(levelname, recordcopy.levelno) + if "color_message" in recordcopy.__dict__: + recordcopy.msg = recordcopy.__dict__["color_message"] + recordcopy.__dict__["message"] = recordcopy.getMessage() + recordcopy.__dict__["levelprefix"] = levelname + ":" + seperator + return super().formatMessage(recordcopy) + + +class DefaultFormatter(ColourizedFormatter): + def should_use_colors(self) -> bool: + return sys.stderr.isatty() # pragma: no cover + + +class AccessFormatter(ColourizedFormatter): + status_code_colours = { + 1: lambda code: click.style(str(code), fg="bright_white"), + 2: lambda code: click.style(str(code), fg="green"), + 3: lambda code: click.style(str(code), fg="yellow"), + 4: lambda code: click.style(str(code), fg="red"), + 5: lambda code: click.style(str(code), fg="bright_red"), + } + + def get_status_code(self, status_code: int) -> str: + try: + status_phrase = http.HTTPStatus(status_code).phrase + except ValueError: + status_phrase = "" + status_and_phrase = "%s %s" % (status_code, status_phrase) + if self.use_colors: + + def default(code: int) -> str: + return status_and_phrase # pragma: no cover + + func = self.status_code_colours.get(status_code // 100, default) + return func(status_and_phrase) + return status_and_phrase + + def formatMessage(self, record: logging.LogRecord) -> str: + recordcopy = copy(record) + ( + client_addr, + method, + full_path, + http_version, + status_code, + ) = recordcopy.args # type: ignore[misc] + status_code = self.get_status_code(int(status_code)) # type: ignore[arg-type] + request_line = "%s %s HTTP/%s" % (method, full_path, http_version) + if self.use_colors: + request_line = click.style(request_line, bold=True) + recordcopy.__dict__.update( + { + "client_addr": client_addr, + "request_line": request_line, + "status_code": status_code, + } + ) + return super().formatMessage(recordcopy) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/loops/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/loops/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/loops/asyncio.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/loops/asyncio.py new file mode 100644 index 0000000..b24f4fe --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/loops/asyncio.py @@ -0,0 +1,10 @@ +import asyncio +import logging +import sys + +logger = logging.getLogger("uvicorn.error") + + +def asyncio_setup(use_subprocess: bool = False) -> None: + if sys.platform == "win32" and use_subprocess: + asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/loops/auto.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/loops/auto.py new file mode 100644 index 0000000..2285457 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/loops/auto.py @@ -0,0 +1,11 @@ +def auto_loop_setup(use_subprocess: bool = False) -> None: + try: + import uvloop # noqa + except ImportError: # pragma: no cover + from uvicorn.loops.asyncio import asyncio_setup as loop_setup + + loop_setup(use_subprocess=use_subprocess) + else: # pragma: no cover + from uvicorn.loops.uvloop import uvloop_setup + + uvloop_setup(use_subprocess=use_subprocess) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/loops/uvloop.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/loops/uvloop.py new file mode 100644 index 0000000..0e2fd1e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/loops/uvloop.py @@ -0,0 +1,7 @@ +import asyncio + +import uvloop + + +def uvloop_setup(use_subprocess: bool = False) -> None: + asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/main.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/main.py new file mode 100644 index 0000000..6156f85 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/main.py @@ -0,0 +1,596 @@ +import asyncio +import logging +import os +import platform +import ssl +import sys +import typing + +import click + +import uvicorn +from uvicorn._types import ASGIApplication +from uvicorn.config import ( + HTTP_PROTOCOLS, + INTERFACES, + LIFESPAN, + LOG_LEVELS, + LOGGING_CONFIG, + LOOP_SETUPS, + SSL_PROTOCOL_VERSION, + WS_PROTOCOLS, + Config, + HTTPProtocolType, + InterfaceType, + LifespanType, + LoopSetupType, + WSProtocolType, +) +from uvicorn.server import Server, ServerState # noqa: F401 # Used to be defined here. +from uvicorn.supervisors import ChangeReload, Multiprocess + +LEVEL_CHOICES = click.Choice(list(LOG_LEVELS.keys())) +HTTP_CHOICES = click.Choice(list(HTTP_PROTOCOLS.keys())) +WS_CHOICES = click.Choice(list(WS_PROTOCOLS.keys())) +LIFESPAN_CHOICES = click.Choice(list(LIFESPAN.keys())) +LOOP_CHOICES = click.Choice([key for key in LOOP_SETUPS.keys() if key != "none"]) +INTERFACE_CHOICES = click.Choice(INTERFACES) + +STARTUP_FAILURE = 3 + +logger = logging.getLogger("uvicorn.error") + + +def print_version(ctx: click.Context, param: click.Parameter, value: bool) -> None: + if not value or ctx.resilient_parsing: + return + click.echo( + "Running uvicorn %s with %s %s on %s" + % ( + uvicorn.__version__, + platform.python_implementation(), + platform.python_version(), + platform.system(), + ) + ) + ctx.exit() + + +@click.command(context_settings={"auto_envvar_prefix": "UVICORN"}) +@click.argument("app") +@click.option( + "--host", + type=str, + default="127.0.0.1", + help="Bind socket to this host.", + show_default=True, +) +@click.option( + "--port", + type=int, + default=8000, + help="Bind socket to this port. If 0, an available port will be picked.", + show_default=True, +) +@click.option("--uds", type=str, default=None, help="Bind to a UNIX domain socket.") +@click.option( + "--fd", type=int, default=None, help="Bind to socket from this file descriptor." +) +@click.option("--reload", is_flag=True, default=False, help="Enable auto-reload.") +@click.option( + "--reload-dir", + "reload_dirs", + multiple=True, + help="Set reload directories explicitly, instead of using the current working" + " directory.", + type=click.Path(exists=True), +) +@click.option( + "--reload-include", + "reload_includes", + multiple=True, + help="Set glob patterns to include while watching for files. Includes '*.py' " + "by default; these defaults can be overridden with `--reload-exclude`. " + "This option has no effect unless watchfiles is installed.", +) +@click.option( + "--reload-exclude", + "reload_excludes", + multiple=True, + help="Set glob patterns to exclude while watching for files. Includes " + "'.*, .py[cod], .sw.*, ~*' by default; these defaults can be overridden " + "with `--reload-include`. This option has no effect unless watchfiles is " + "installed.", +) +@click.option( + "--reload-delay", + type=float, + default=0.25, + show_default=True, + help="Delay between previous and next check if application needs to be." + " Defaults to 0.25s.", +) +@click.option( + "--workers", + default=None, + type=int, + help="Number of worker processes. Defaults to the $WEB_CONCURRENCY environment" + " variable if available, or 1. Not valid with --reload.", +) +@click.option( + "--loop", + type=LOOP_CHOICES, + default="auto", + help="Event loop implementation.", + show_default=True, +) +@click.option( + "--http", + type=HTTP_CHOICES, + default="auto", + help="HTTP protocol implementation.", + show_default=True, +) +@click.option( + "--ws", + type=WS_CHOICES, + default="auto", + help="WebSocket protocol implementation.", + show_default=True, +) +@click.option( + "--ws-max-size", + type=int, + default=16777216, + help="WebSocket max size message in bytes", + show_default=True, +) +@click.option( + "--ws-max-queue", + type=int, + default=32, + help="The maximum length of the WebSocket message queue.", + show_default=True, +) +@click.option( + "--ws-ping-interval", + type=float, + default=20.0, + help="WebSocket ping interval", + show_default=True, +) +@click.option( + "--ws-ping-timeout", + type=float, + default=20.0, + help="WebSocket ping timeout", + show_default=True, +) +@click.option( + "--ws-per-message-deflate", + type=bool, + default=True, + help="WebSocket per-message-deflate compression", + show_default=True, +) +@click.option( + "--lifespan", + type=LIFESPAN_CHOICES, + default="auto", + help="Lifespan implementation.", + show_default=True, +) +@click.option( + "--interface", + type=INTERFACE_CHOICES, + default="auto", + help="Select ASGI3, ASGI2, or WSGI as the application interface.", + show_default=True, +) +@click.option( + "--env-file", + type=click.Path(exists=True), + default=None, + help="Environment configuration file.", + show_default=True, +) +@click.option( + "--log-config", + type=click.Path(exists=True), + default=None, + help="Logging configuration file. Supported formats: .ini, .json, .yaml.", + show_default=True, +) +@click.option( + "--log-level", + type=LEVEL_CHOICES, + default=None, + help="Log level. [default: info]", + show_default=True, +) +@click.option( + "--access-log/--no-access-log", + is_flag=True, + default=True, + help="Enable/Disable access log.", +) +@click.option( + "--use-colors/--no-use-colors", + is_flag=True, + default=None, + help="Enable/Disable colorized logging.", +) +@click.option( + "--proxy-headers/--no-proxy-headers", + is_flag=True, + default=True, + help="Enable/Disable X-Forwarded-Proto, X-Forwarded-For, X-Forwarded-Port to " + "populate remote address info.", +) +@click.option( + "--server-header/--no-server-header", + is_flag=True, + default=True, + help="Enable/Disable default Server header.", +) +@click.option( + "--date-header/--no-date-header", + is_flag=True, + default=True, + help="Enable/Disable default Date header.", +) +@click.option( + "--forwarded-allow-ips", + type=str, + default=None, + help="Comma separated list of IPs to trust with proxy headers. Defaults to" + " the $FORWARDED_ALLOW_IPS environment variable if available, or '127.0.0.1'.", +) +@click.option( + "--root-path", + type=str, + default="", + help="Set the ASGI 'root_path' for applications submounted below a given URL path.", +) +@click.option( + "--limit-concurrency", + type=int, + default=None, + help="Maximum number of concurrent connections or tasks to allow, before issuing" + " HTTP 503 responses.", +) +@click.option( + "--backlog", + type=int, + default=2048, + help="Maximum number of connections to hold in backlog", +) +@click.option( + "--limit-max-requests", + type=int, + default=None, + help="Maximum number of requests to service before terminating the process.", +) +@click.option( + "--timeout-keep-alive", + type=int, + default=5, + help="Close Keep-Alive connections if no new data is received within this timeout.", + show_default=True, +) +@click.option( + "--timeout-graceful-shutdown", + type=int, + default=None, + help="Maximum number of seconds to wait for graceful shutdown.", +) +@click.option( + "--ssl-keyfile", type=str, default=None, help="SSL key file", show_default=True +) +@click.option( + "--ssl-certfile", + type=str, + default=None, + help="SSL certificate file", + show_default=True, +) +@click.option( + "--ssl-keyfile-password", + type=str, + default=None, + help="SSL keyfile password", + show_default=True, +) +@click.option( + "--ssl-version", + type=int, + default=int(SSL_PROTOCOL_VERSION), + help="SSL version to use (see stdlib ssl module's)", + show_default=True, +) +@click.option( + "--ssl-cert-reqs", + type=int, + default=int(ssl.CERT_NONE), + help="Whether client certificate is required (see stdlib ssl module's)", + show_default=True, +) +@click.option( + "--ssl-ca-certs", + type=str, + default=None, + help="CA certificates file", + show_default=True, +) +@click.option( + "--ssl-ciphers", + type=str, + default="TLSv1", + help="Ciphers to use (see stdlib ssl module's)", + show_default=True, +) +@click.option( + "--header", + "headers", + multiple=True, + help="Specify custom default HTTP response headers as a Name:Value pair", +) +@click.option( + "--version", + is_flag=True, + callback=print_version, + expose_value=False, + is_eager=True, + help="Display the uvicorn version and exit.", +) +@click.option( + "--app-dir", + default="", + show_default=True, + help="Look for APP in the specified directory, by adding this to the PYTHONPATH." + " Defaults to the current working directory.", +) +@click.option( + "--h11-max-incomplete-event-size", + "h11_max_incomplete_event_size", + type=int, + default=None, + help="For h11, the maximum number of bytes to buffer of an incomplete event.", +) +@click.option( + "--factory", + is_flag=True, + default=False, + help="Treat APP as an application factory, i.e. a () -> callable.", + show_default=True, +) +def main( + app: str, + host: str, + port: int, + uds: str, + fd: int, + loop: LoopSetupType, + http: HTTPProtocolType, + ws: WSProtocolType, + ws_max_size: int, + ws_max_queue: int, + ws_ping_interval: float, + ws_ping_timeout: float, + ws_per_message_deflate: bool, + lifespan: LifespanType, + interface: InterfaceType, + reload: bool, + reload_dirs: typing.List[str], + reload_includes: typing.List[str], + reload_excludes: typing.List[str], + reload_delay: float, + workers: int, + env_file: str, + log_config: str, + log_level: str, + access_log: bool, + proxy_headers: bool, + server_header: bool, + date_header: bool, + forwarded_allow_ips: str, + root_path: str, + limit_concurrency: int, + backlog: int, + limit_max_requests: int, + timeout_keep_alive: int, + timeout_graceful_shutdown: typing.Optional[int], + ssl_keyfile: str, + ssl_certfile: str, + ssl_keyfile_password: str, + ssl_version: int, + ssl_cert_reqs: int, + ssl_ca_certs: str, + ssl_ciphers: str, + headers: typing.List[str], + use_colors: bool, + app_dir: str, + h11_max_incomplete_event_size: typing.Optional[int], + factory: bool, +) -> None: + run( + app, + host=host, + port=port, + uds=uds, + fd=fd, + loop=loop, + http=http, + ws=ws, + ws_max_size=ws_max_size, + ws_max_queue=ws_max_queue, + ws_ping_interval=ws_ping_interval, + ws_ping_timeout=ws_ping_timeout, + ws_per_message_deflate=ws_per_message_deflate, + lifespan=lifespan, + env_file=env_file, + log_config=LOGGING_CONFIG if log_config is None else log_config, + log_level=log_level, + access_log=access_log, + interface=interface, + reload=reload, + reload_dirs=reload_dirs or None, + reload_includes=reload_includes or None, + reload_excludes=reload_excludes or None, + reload_delay=reload_delay, + workers=workers, + proxy_headers=proxy_headers, + server_header=server_header, + date_header=date_header, + forwarded_allow_ips=forwarded_allow_ips, + root_path=root_path, + limit_concurrency=limit_concurrency, + backlog=backlog, + limit_max_requests=limit_max_requests, + timeout_keep_alive=timeout_keep_alive, + timeout_graceful_shutdown=timeout_graceful_shutdown, + ssl_keyfile=ssl_keyfile, + ssl_certfile=ssl_certfile, + ssl_keyfile_password=ssl_keyfile_password, + ssl_version=ssl_version, + ssl_cert_reqs=ssl_cert_reqs, + ssl_ca_certs=ssl_ca_certs, + ssl_ciphers=ssl_ciphers, + headers=[header.split(":", 1) for header in headers], # type: ignore[misc] + use_colors=use_colors, + factory=factory, + app_dir=app_dir, + h11_max_incomplete_event_size=h11_max_incomplete_event_size, + ) + + +def run( + app: typing.Union["ASGIApplication", typing.Callable, str], + *, + host: str = "127.0.0.1", + port: int = 8000, + uds: typing.Optional[str] = None, + fd: typing.Optional[int] = None, + loop: LoopSetupType = "auto", + http: typing.Union[typing.Type[asyncio.Protocol], HTTPProtocolType] = "auto", + ws: typing.Union[typing.Type[asyncio.Protocol], WSProtocolType] = "auto", + ws_max_size: int = 16777216, + ws_max_queue: int = 32, + ws_ping_interval: typing.Optional[float] = 20.0, + ws_ping_timeout: typing.Optional[float] = 20.0, + ws_per_message_deflate: bool = True, + lifespan: LifespanType = "auto", + interface: InterfaceType = "auto", + reload: bool = False, + reload_dirs: typing.Optional[typing.Union[typing.List[str], str]] = None, + reload_includes: typing.Optional[typing.Union[typing.List[str], str]] = None, + reload_excludes: typing.Optional[typing.Union[typing.List[str], str]] = None, + reload_delay: float = 0.25, + workers: typing.Optional[int] = None, + env_file: typing.Optional[typing.Union[str, os.PathLike]] = None, + log_config: typing.Optional[ + typing.Union[typing.Dict[str, typing.Any], str] + ] = LOGGING_CONFIG, + log_level: typing.Optional[typing.Union[str, int]] = None, + access_log: bool = True, + proxy_headers: bool = True, + server_header: bool = True, + date_header: bool = True, + forwarded_allow_ips: typing.Optional[typing.Union[typing.List[str], str]] = None, + root_path: str = "", + limit_concurrency: typing.Optional[int] = None, + backlog: int = 2048, + limit_max_requests: typing.Optional[int] = None, + timeout_keep_alive: int = 5, + timeout_graceful_shutdown: typing.Optional[int] = None, + ssl_keyfile: typing.Optional[str] = None, + ssl_certfile: typing.Optional[typing.Union[str, os.PathLike]] = None, + ssl_keyfile_password: typing.Optional[str] = None, + ssl_version: int = SSL_PROTOCOL_VERSION, + ssl_cert_reqs: int = ssl.CERT_NONE, + ssl_ca_certs: typing.Optional[str] = None, + ssl_ciphers: str = "TLSv1", + headers: typing.Optional[typing.List[typing.Tuple[str, str]]] = None, + use_colors: typing.Optional[bool] = None, + app_dir: typing.Optional[str] = None, + factory: bool = False, + h11_max_incomplete_event_size: typing.Optional[int] = None, +) -> None: + if app_dir is not None: + sys.path.insert(0, app_dir) + + config = Config( + app, + host=host, + port=port, + uds=uds, + fd=fd, + loop=loop, + http=http, + ws=ws, + ws_max_size=ws_max_size, + ws_max_queue=ws_max_queue, + ws_ping_interval=ws_ping_interval, + ws_ping_timeout=ws_ping_timeout, + ws_per_message_deflate=ws_per_message_deflate, + lifespan=lifespan, + interface=interface, + reload=reload, + reload_dirs=reload_dirs, + reload_includes=reload_includes, + reload_excludes=reload_excludes, + reload_delay=reload_delay, + workers=workers, + env_file=env_file, + log_config=log_config, + log_level=log_level, + access_log=access_log, + proxy_headers=proxy_headers, + server_header=server_header, + date_header=date_header, + forwarded_allow_ips=forwarded_allow_ips, + root_path=root_path, + limit_concurrency=limit_concurrency, + backlog=backlog, + limit_max_requests=limit_max_requests, + timeout_keep_alive=timeout_keep_alive, + timeout_graceful_shutdown=timeout_graceful_shutdown, + ssl_keyfile=ssl_keyfile, + ssl_certfile=ssl_certfile, + ssl_keyfile_password=ssl_keyfile_password, + ssl_version=ssl_version, + ssl_cert_reqs=ssl_cert_reqs, + ssl_ca_certs=ssl_ca_certs, + ssl_ciphers=ssl_ciphers, + headers=headers, + use_colors=use_colors, + factory=factory, + h11_max_incomplete_event_size=h11_max_incomplete_event_size, + ) + server = Server(config=config) + + if (config.reload or config.workers > 1) and not isinstance(app, str): + logger = logging.getLogger("uvicorn.error") + logger.warning( + "You must pass the application as an import string to enable 'reload' or " + "'workers'." + ) + sys.exit(1) + + if config.should_reload: + sock = config.bind_socket() + ChangeReload(config, target=server.run, sockets=[sock]).run() + elif config.workers > 1: + sock = config.bind_socket() + Multiprocess(config, target=server.run, sockets=[sock]).run() + else: + server.run() + if config.uds and os.path.exists(config.uds): + os.remove(config.uds) # pragma: py-win32 + + if not server.started and not config.should_reload and config.workers == 1: + sys.exit(STARTUP_FAILURE) + + +if __name__ == "__main__": + main() # pragma: no cover diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/middleware/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/middleware/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/middleware/asgi2.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/middleware/asgi2.py new file mode 100644 index 0000000..75145f7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/middleware/asgi2.py @@ -0,0 +1,17 @@ +from uvicorn._types import ( + ASGI2Application, + ASGIReceiveCallable, + ASGISendCallable, + Scope, +) + + +class ASGI2Middleware: + def __init__(self, app: "ASGI2Application"): + self.app = app + + async def __call__( + self, scope: "Scope", receive: "ASGIReceiveCallable", send: "ASGISendCallable" + ) -> None: + instance = self.app(scope) + await instance(receive, send) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/middleware/message_logger.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/middleware/message_logger.py new file mode 100644 index 0000000..0174bcc --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/middleware/message_logger.py @@ -0,0 +1,87 @@ +import logging +from typing import Any + +from uvicorn._types import ( + ASGI3Application, + ASGIReceiveCallable, + ASGIReceiveEvent, + ASGISendCallable, + ASGISendEvent, + WWWScope, +) +from uvicorn.logging import TRACE_LOG_LEVEL + +PLACEHOLDER_FORMAT = { + "body": "<{length} bytes>", + "bytes": "<{length} bytes>", + "text": "<{length} chars>", + "headers": "<...>", +} + + +def message_with_placeholders(message: Any) -> Any: + """ + Return an ASGI message, with any body-type content omitted and replaced + with a placeholder. + """ + new_message = message.copy() + for attr in PLACEHOLDER_FORMAT.keys(): + if message.get(attr) is not None: + content = message[attr] + placeholder = PLACEHOLDER_FORMAT[attr].format(length=len(content)) + new_message[attr] = placeholder + return new_message + + +class MessageLoggerMiddleware: + def __init__(self, app: "ASGI3Application"): + self.task_counter = 0 + self.app = app + self.logger = logging.getLogger("uvicorn.asgi") + + def trace(message: Any, *args: Any, **kwargs: Any) -> None: + self.logger.log(TRACE_LOG_LEVEL, message, *args, **kwargs) + + self.logger.trace = trace # type: ignore + + async def __call__( + self, + scope: "WWWScope", + receive: "ASGIReceiveCallable", + send: "ASGISendCallable", + ) -> None: + self.task_counter += 1 + + task_counter = self.task_counter + client = scope.get("client") + prefix = "%s:%d - ASGI" % (client[0], client[1]) if client else "ASGI" + + async def inner_receive() -> "ASGIReceiveEvent": + message = await receive() + logged_message = message_with_placeholders(message) + log_text = "%s [%d] Receive %s" + self.logger.trace( # type: ignore + log_text, prefix, task_counter, logged_message + ) + return message + + async def inner_send(message: "ASGISendEvent") -> None: + logged_message = message_with_placeholders(message) + log_text = "%s [%d] Send %s" + self.logger.trace( # type: ignore + log_text, prefix, task_counter, logged_message + ) + await send(message) + + logged_scope = message_with_placeholders(scope) + log_text = "%s [%d] Started scope=%s" + self.logger.trace(log_text, prefix, task_counter, logged_scope) # type: ignore + try: + await self.app(scope, inner_receive, inner_send) + except BaseException as exc: + log_text = "%s [%d] Raised exception" + self.logger.trace(log_text, prefix, task_counter) # type: ignore + raise exc from None + else: + log_text = "%s [%d] Completed" + self.logger.trace(log_text, prefix, task_counter) # type: ignore diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/middleware/proxy_headers.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/middleware/proxy_headers.py new file mode 100644 index 0000000..28277e1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/middleware/proxy_headers.py @@ -0,0 +1,84 @@ +""" +This middleware can be used when a known proxy is fronting the application, +and is trusted to be properly setting the `X-Forwarded-Proto` and +`X-Forwarded-For` headers with the connecting client information. + +Modifies the `client` and `scheme` information so that they reference +the connecting client, rather that the connecting proxy. + +https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers#Proxies +""" +from typing import List, Optional, Tuple, Union, cast + +from uvicorn._types import ( + ASGI3Application, + ASGIReceiveCallable, + ASGISendCallable, + HTTPScope, + Scope, + WebSocketScope, +) + + +class ProxyHeadersMiddleware: + def __init__( + self, + app: "ASGI3Application", + trusted_hosts: Union[List[str], str] = "127.0.0.1", + ) -> None: + self.app = app + if isinstance(trusted_hosts, str): + self.trusted_hosts = {item.strip() for item in trusted_hosts.split(",")} + else: + self.trusted_hosts = set(trusted_hosts) + self.always_trust = "*" in self.trusted_hosts + + def get_trusted_client_host( + self, x_forwarded_for_hosts: List[str] + ) -> Optional[str]: + if self.always_trust: + return x_forwarded_for_hosts[0] + + for host in reversed(x_forwarded_for_hosts): + if host not in self.trusted_hosts: + return host + + return None + + async def __call__( + self, scope: "Scope", receive: "ASGIReceiveCallable", send: "ASGISendCallable" + ) -> None: + if scope["type"] in ("http", "websocket"): + scope = cast(Union["HTTPScope", "WebSocketScope"], scope) + client_addr: Optional[Tuple[str, int]] = scope.get("client") + client_host = client_addr[0] if client_addr else None + + if self.always_trust or client_host in self.trusted_hosts: + headers = dict(scope["headers"]) + + if b"x-forwarded-proto" in headers: + # Determine if the incoming request was http or https based on + # the X-Forwarded-Proto header. + x_forwarded_proto = ( + headers[b"x-forwarded-proto"].decode("latin1").strip() + ) + if scope["type"] == "websocket": + scope["scheme"] = ( + "wss" if x_forwarded_proto == "https" else "ws" + ) + else: + scope["scheme"] = x_forwarded_proto + + if b"x-forwarded-for" in headers: + # Determine the client address from the last trusted IP in the + # X-Forwarded-For header. We've lost the connecting client's port + # information by now, so only include the host. + x_forwarded_for = headers[b"x-forwarded-for"].decode("latin1") + x_forwarded_for_hosts = [ + item.strip() for item in x_forwarded_for.split(",") + ] + host = self.get_trusted_client_host(x_forwarded_for_hosts) + port = 0 + scope["client"] = (host, port) # type: ignore[arg-type] + + return await self.app(scope, receive, send) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/middleware/wsgi.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/middleware/wsgi.py new file mode 100644 index 0000000..381eca6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/middleware/wsgi.py @@ -0,0 +1,203 @@ +import asyncio +import concurrent.futures +import io +import sys +import warnings +from collections import deque +from typing import Deque, Iterable, Optional, Tuple + +from uvicorn._types import ( + ASGIReceiveCallable, + ASGIReceiveEvent, + ASGISendCallable, + ASGISendEvent, + Environ, + ExcInfo, + HTTPRequestEvent, + HTTPResponseBodyEvent, + HTTPResponseStartEvent, + HTTPScope, + StartResponse, + WSGIApp, +) + + +def build_environ( + scope: "HTTPScope", message: "ASGIReceiveEvent", body: io.BytesIO +) -> Environ: + """ + Builds a scope and request message into a WSGI environ object. + """ + environ = { + "REQUEST_METHOD": scope["method"], + "SCRIPT_NAME": "", + "PATH_INFO": scope["path"].encode("utf8").decode("latin1"), + "QUERY_STRING": scope["query_string"].decode("ascii"), + "SERVER_PROTOCOL": "HTTP/%s" % scope["http_version"], + "wsgi.version": (1, 0), + "wsgi.url_scheme": scope.get("scheme", "http"), + "wsgi.input": body, + "wsgi.errors": sys.stdout, + "wsgi.multithread": True, + "wsgi.multiprocess": True, + "wsgi.run_once": False, + } + + # Get server name and port - required in WSGI, not in ASGI + server = scope.get("server") + if server is None: + server = ("localhost", 80) + environ["SERVER_NAME"] = server[0] + environ["SERVER_PORT"] = server[1] + + # Get client IP address + client = scope.get("client") + if client is not None: + environ["REMOTE_ADDR"] = client[0] + + # Go through headers and make them into environ entries + for name, value in scope.get("headers", []): + name_str: str = name.decode("latin1") + if name_str == "content-length": + corrected_name = "CONTENT_LENGTH" + elif name_str == "content-type": + corrected_name = "CONTENT_TYPE" + else: + corrected_name = "HTTP_%s" % name_str.upper().replace("-", "_") + # HTTPbis say only ASCII chars are allowed in headers, but we latin1 + # just in case + value_str: str = value.decode("latin1") + if corrected_name in environ: + corrected_name_environ = environ[corrected_name] + assert isinstance(corrected_name_environ, str) + value_str = corrected_name_environ + "," + value_str + environ[corrected_name] = value_str + return environ + + +class _WSGIMiddleware: + def __init__(self, app: WSGIApp, workers: int = 10): + warnings.warn( + "Uvicorn's native WSGI implementation is deprecated, you " + "should switch to a2wsgi (`pip install a2wsgi`).", + DeprecationWarning, + ) + self.app = app + self.executor = concurrent.futures.ThreadPoolExecutor(max_workers=workers) + + async def __call__( + self, + scope: "HTTPScope", + receive: "ASGIReceiveCallable", + send: "ASGISendCallable", + ) -> None: + assert scope["type"] == "http" + instance = WSGIResponder(self.app, self.executor, scope) + await instance(receive, send) + + +class WSGIResponder: + def __init__( + self, + app: WSGIApp, + executor: concurrent.futures.ThreadPoolExecutor, + scope: "HTTPScope", + ): + self.app = app + self.executor = executor + self.scope = scope + self.status = None + self.response_headers = None + self.send_event = asyncio.Event() + self.send_queue: Deque[Optional["ASGISendEvent"]] = deque() + self.loop: asyncio.AbstractEventLoop = asyncio.get_event_loop() + self.response_started = False + self.exc_info: Optional[ExcInfo] = None + + async def __call__( + self, receive: "ASGIReceiveCallable", send: "ASGISendCallable" + ) -> None: + message: HTTPRequestEvent = await receive() # type: ignore[assignment] + body = io.BytesIO(message.get("body", b"")) + more_body = message.get("more_body", False) + if more_body: + body.seek(0, io.SEEK_END) + while more_body: + body_message: "HTTPRequestEvent" = ( + await receive() # type: ignore[assignment] + ) + body.write(body_message.get("body", b"")) + more_body = body_message.get("more_body", False) + body.seek(0) + environ = build_environ(self.scope, message, body) + self.loop = asyncio.get_event_loop() + wsgi = self.loop.run_in_executor( + self.executor, self.wsgi, environ, self.start_response + ) + sender = self.loop.create_task(self.sender(send)) + try: + await asyncio.wait_for(wsgi, None) + finally: + self.send_queue.append(None) + self.send_event.set() + await asyncio.wait_for(sender, None) + if self.exc_info is not None: + raise self.exc_info[0].with_traceback(self.exc_info[1], self.exc_info[2]) + + async def sender(self, send: "ASGISendCallable") -> None: + while True: + if self.send_queue: + message = self.send_queue.popleft() + if message is None: + return + await send(message) + else: + await self.send_event.wait() + self.send_event.clear() + + def start_response( + self, + status: str, + response_headers: Iterable[Tuple[str, str]], + exc_info: Optional[ExcInfo] = None, + ) -> None: + self.exc_info = exc_info + if not self.response_started: + self.response_started = True + status_code_str, _ = status.split(" ", 1) + status_code = int(status_code_str) + headers = [ + (name.encode("ascii"), value.encode("ascii")) + for name, value in response_headers + ] + http_response_start_event: HTTPResponseStartEvent = { + "type": "http.response.start", + "status": status_code, + "headers": headers, + } + self.send_queue.append(http_response_start_event) + self.loop.call_soon_threadsafe(self.send_event.set) + + def wsgi(self, environ: Environ, start_response: StartResponse) -> None: + for chunk in self.app(environ, start_response): # type: ignore + response_body: HTTPResponseBodyEvent = { + "type": "http.response.body", + "body": chunk, + "more_body": True, + } + self.send_queue.append(response_body) + self.loop.call_soon_threadsafe(self.send_event.set) + + empty_body: HTTPResponseBodyEvent = { + "type": "http.response.body", + "body": b"", + "more_body": False, + } + self.send_queue.append(empty_body) + self.loop.call_soon_threadsafe(self.send_event.set) + + +try: + from a2wsgi import WSGIMiddleware +except ModuleNotFoundError: # pragma: no cover + WSGIMiddleware = _WSGIMiddleware # type: ignore[misc, assignment] diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/http/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/http/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/http/auto.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/http/auto.py new file mode 100644 index 0000000..1aa9967 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/http/auto.py @@ -0,0 +1,14 @@ +import asyncio +from typing import Type + +AutoHTTPProtocol: Type[asyncio.Protocol] +try: + import httptools # noqa +except ImportError: # pragma: no cover + from uvicorn.protocols.http.h11_impl import H11Protocol + + AutoHTTPProtocol = H11Protocol +else: # pragma: no cover + from uvicorn.protocols.http.httptools_impl import HttpToolsProtocol + + AutoHTTPProtocol = HttpToolsProtocol diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/http/flow_control.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/http/flow_control.py new file mode 100644 index 0000000..df642c7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/http/flow_control.py @@ -0,0 +1,66 @@ +import asyncio + +from uvicorn._types import ( + ASGIReceiveCallable, + ASGISendCallable, + HTTPResponseBodyEvent, + HTTPResponseStartEvent, + Scope, +) + +CLOSE_HEADER = (b"connection", b"close") + +HIGH_WATER_LIMIT = 65536 + + +class FlowControl: + def __init__(self, transport: asyncio.Transport) -> None: + self._transport = transport + self.read_paused = False + self.write_paused = False + self._is_writable_event = asyncio.Event() + self._is_writable_event.set() + + async def drain(self) -> None: + await self._is_writable_event.wait() + + def pause_reading(self) -> None: + if not self.read_paused: + self.read_paused = True + self._transport.pause_reading() + + def resume_reading(self) -> None: + if self.read_paused: + self.read_paused = False + self._transport.resume_reading() + + def pause_writing(self) -> None: + if not self.write_paused: + self.write_paused = True + self._is_writable_event.clear() + + def resume_writing(self) -> None: + if self.write_paused: + self.write_paused = False + self._is_writable_event.set() + + +async def service_unavailable( + scope: "Scope", receive: "ASGIReceiveCallable", send: "ASGISendCallable" +) -> None: + response_start: "HTTPResponseStartEvent" = { + "type": "http.response.start", + "status": 503, + "headers": [ + (b"content-type", b"text/plain; charset=utf-8"), + (b"connection", b"close"), + ], + } + await send(response_start) + + response_body: "HTTPResponseBodyEvent" = { + "type": "http.response.body", + "body": b"Service Unavailable", + "more_body": False, + } + await send(response_body) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/http/h11_impl.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/http/h11_impl.py new file mode 100644 index 0000000..0c0efea --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/http/h11_impl.py @@ -0,0 +1,550 @@ +import asyncio +import http +import logging +from typing import ( + Any, + Callable, + Dict, + List, + Literal, + Optional, + Tuple, + cast, +) +from urllib.parse import unquote + +import h11 +from h11._connection import DEFAULT_MAX_INCOMPLETE_EVENT_SIZE + +from uvicorn._types import ( + ASGI3Application, + ASGIReceiveEvent, + ASGISendEvent, + HTTPRequestEvent, + HTTPResponseBodyEvent, + HTTPResponseStartEvent, + HTTPScope, +) +from uvicorn.config import Config +from uvicorn.logging import TRACE_LOG_LEVEL +from uvicorn.protocols.http.flow_control import ( + CLOSE_HEADER, + HIGH_WATER_LIMIT, + FlowControl, + service_unavailable, +) +from uvicorn.protocols.utils import ( + get_client_addr, + get_local_addr, + get_path_with_query_string, + get_remote_addr, + is_ssl, +) +from uvicorn.server import ServerState + + +def _get_status_phrase(status_code: int) -> bytes: + try: + return http.HTTPStatus(status_code).phrase.encode() + except ValueError: + return b"" + + +STATUS_PHRASES = { + status_code: _get_status_phrase(status_code) for status_code in range(100, 600) +} + + +class H11Protocol(asyncio.Protocol): + def __init__( + self, + config: Config, + server_state: ServerState, + app_state: Dict[str, Any], + _loop: Optional[asyncio.AbstractEventLoop] = None, + ) -> None: + if not config.loaded: + config.load() + + self.config = config + self.app = config.loaded_app + self.loop = _loop or asyncio.get_event_loop() + self.logger = logging.getLogger("uvicorn.error") + self.access_logger = logging.getLogger("uvicorn.access") + self.access_log = self.access_logger.hasHandlers() + self.conn = h11.Connection( + h11.SERVER, + config.h11_max_incomplete_event_size + if config.h11_max_incomplete_event_size is not None + else DEFAULT_MAX_INCOMPLETE_EVENT_SIZE, + ) + self.ws_protocol_class = config.ws_protocol_class + self.root_path = config.root_path + self.limit_concurrency = config.limit_concurrency + self.app_state = app_state + + # Timeouts + self.timeout_keep_alive_task: Optional[asyncio.TimerHandle] = None + self.timeout_keep_alive = config.timeout_keep_alive + + # Shared server state + self.server_state = server_state + self.connections = server_state.connections + self.tasks = server_state.tasks + + # Per-connection state + self.transport: asyncio.Transport = None # type: ignore[assignment] + self.flow: FlowControl = None # type: ignore[assignment] + self.server: Optional[Tuple[str, int]] = None + self.client: Optional[Tuple[str, int]] = None + self.scheme: Optional[Literal["http", "https"]] = None + + # Per-request state + self.scope: HTTPScope = None # type: ignore[assignment] + self.headers: List[Tuple[bytes, bytes]] = None # type: ignore[assignment] + self.cycle: RequestResponseCycle = None # type: ignore[assignment] + + # Protocol interface + def connection_made( # type: ignore[override] + self, transport: asyncio.Transport + ) -> None: + self.connections.add(self) + + self.transport = transport + self.flow = FlowControl(transport) + self.server = get_local_addr(transport) + self.client = get_remote_addr(transport) + self.scheme = "https" if is_ssl(transport) else "http" + + if self.logger.level <= TRACE_LOG_LEVEL: + prefix = "%s:%d - " % self.client if self.client else "" + self.logger.log(TRACE_LOG_LEVEL, "%sHTTP connection made", prefix) + + def connection_lost(self, exc: Optional[Exception]) -> None: + self.connections.discard(self) + + if self.logger.level <= TRACE_LOG_LEVEL: + prefix = "%s:%d - " % self.client if self.client else "" + self.logger.log(TRACE_LOG_LEVEL, "%sHTTP connection lost", prefix) + + if self.cycle and not self.cycle.response_complete: + self.cycle.disconnected = True + if self.conn.our_state != h11.ERROR: + event = h11.ConnectionClosed() + try: + self.conn.send(event) + except h11.LocalProtocolError: + # Premature client disconnect + pass + + if self.cycle is not None: + self.cycle.message_event.set() + if self.flow is not None: + self.flow.resume_writing() + if exc is None: + self.transport.close() + self._unset_keepalive_if_required() + + def eof_received(self) -> None: + pass + + def _unset_keepalive_if_required(self) -> None: + if self.timeout_keep_alive_task is not None: + self.timeout_keep_alive_task.cancel() + self.timeout_keep_alive_task = None + + def _get_upgrade(self) -> Optional[bytes]: + connection = [] + upgrade = None + for name, value in self.headers: + if name == b"connection": + connection = [token.lower().strip() for token in value.split(b",")] + if name == b"upgrade": + upgrade = value.lower() + if b"upgrade" in connection: + return upgrade + return None + + def _should_upgrade_to_ws(self) -> bool: + if self.ws_protocol_class is None: + if self.config.ws == "auto": + msg = "Unsupported upgrade request." + self.logger.warning(msg) + msg = "No supported WebSocket library detected. Please use \"pip install 'uvicorn[standard]'\", or install 'websockets' or 'wsproto' manually." # noqa: E501 + self.logger.warning(msg) + return False + return True + + def data_received(self, data: bytes) -> None: + self._unset_keepalive_if_required() + + self.conn.receive_data(data) + self.handle_events() + + def handle_events(self) -> None: + while True: + try: + event = self.conn.next_event() + except h11.RemoteProtocolError: + msg = "Invalid HTTP request received." + self.logger.warning(msg) + self.send_400_response(msg) + return + + if event is h11.NEED_DATA: + break + + elif event is h11.PAUSED: + # This case can occur in HTTP pipelining, so we need to + # stop reading any more data, and ensure that at the end + # of the active request/response cycle we handle any + # events that have been buffered up. + self.flow.pause_reading() + break + + elif isinstance(event, h11.Request): + self.headers = [(key.lower(), value) for key, value in event.headers] + raw_path, _, query_string = event.target.partition(b"?") + self.scope = { + "type": "http", + "asgi": { + "version": self.config.asgi_version, + "spec_version": "2.3", + }, + "http_version": event.http_version.decode("ascii"), + "server": self.server, + "client": self.client, + "scheme": self.scheme, # type: ignore[typeddict-item] + "method": event.method.decode("ascii"), + "root_path": self.root_path, + "path": unquote(raw_path.decode("ascii")), + "raw_path": raw_path, + "query_string": query_string, + "headers": self.headers, + "state": self.app_state.copy(), + } + + upgrade = self._get_upgrade() + if upgrade == b"websocket" and self._should_upgrade_to_ws(): + self.handle_websocket_upgrade(event) + return + + # Handle 503 responses when 'limit_concurrency' is exceeded. + if self.limit_concurrency is not None and ( + len(self.connections) >= self.limit_concurrency + or len(self.tasks) >= self.limit_concurrency + ): + app = service_unavailable + message = "Exceeded concurrency limit." + self.logger.warning(message) + else: + app = self.app + + self.cycle = RequestResponseCycle( + scope=self.scope, + conn=self.conn, + transport=self.transport, + flow=self.flow, + logger=self.logger, + access_logger=self.access_logger, + access_log=self.access_log, + default_headers=self.server_state.default_headers, + message_event=asyncio.Event(), + on_response=self.on_response_complete, + ) + task = self.loop.create_task(self.cycle.run_asgi(app)) + task.add_done_callback(self.tasks.discard) + self.tasks.add(task) + + elif isinstance(event, h11.Data): + if self.conn.our_state is h11.DONE: + continue + self.cycle.body += event.data + if len(self.cycle.body) > HIGH_WATER_LIMIT: + self.flow.pause_reading() + self.cycle.message_event.set() + + elif isinstance(event, h11.EndOfMessage): + if self.conn.our_state is h11.DONE: + self.transport.resume_reading() + self.conn.start_next_cycle() + continue + self.cycle.more_body = False + self.cycle.message_event.set() + + def handle_websocket_upgrade(self, event: h11.Request) -> None: + if self.logger.level <= TRACE_LOG_LEVEL: + prefix = "%s:%d - " % self.client if self.client else "" + self.logger.log(TRACE_LOG_LEVEL, "%sUpgrading to WebSocket", prefix) + + self.connections.discard(self) + output = [event.method, b" ", event.target, b" HTTP/1.1\r\n"] + for name, value in self.headers: + output += [name, b": ", value, b"\r\n"] + output.append(b"\r\n") + protocol = self.ws_protocol_class( # type: ignore[call-arg, misc] + config=self.config, + server_state=self.server_state, + app_state=self.app_state, + ) + protocol.connection_made(self.transport) + protocol.data_received(b"".join(output)) + self.transport.set_protocol(protocol) + + def send_400_response(self, msg: str) -> None: + reason = STATUS_PHRASES[400] + headers: List[Tuple[bytes, bytes]] = [ + (b"content-type", b"text/plain; charset=utf-8"), + (b"connection", b"close"), + ] + event = h11.Response(status_code=400, headers=headers, reason=reason) + output = self.conn.send(event) + self.transport.write(output) + + output = self.conn.send(event=h11.Data(data=msg.encode("ascii"))) + self.transport.write(output) + + output = self.conn.send(event=h11.EndOfMessage()) + self.transport.write(output) + + self.transport.close() + + def on_response_complete(self) -> None: + self.server_state.total_requests += 1 + + if self.transport.is_closing(): + return + + # Set a short Keep-Alive timeout. + self._unset_keepalive_if_required() + + self.timeout_keep_alive_task = self.loop.call_later( + self.timeout_keep_alive, self.timeout_keep_alive_handler + ) + + # Unpause data reads if needed. + self.flow.resume_reading() + + # Unblock any pipelined events. + if self.conn.our_state is h11.DONE and self.conn.their_state is h11.DONE: + self.conn.start_next_cycle() + self.handle_events() + + def shutdown(self) -> None: + """ + Called by the server to commence a graceful shutdown. + """ + if self.cycle is None or self.cycle.response_complete: + event = h11.ConnectionClosed() + self.conn.send(event) + self.transport.close() + else: + self.cycle.keep_alive = False + + def pause_writing(self) -> None: + """ + Called by the transport when the write buffer exceeds the high water mark. + """ + self.flow.pause_writing() + + def resume_writing(self) -> None: + """ + Called by the transport when the write buffer drops below the low water mark. + """ + self.flow.resume_writing() + + def timeout_keep_alive_handler(self) -> None: + """ + Called on a keep-alive connection if no new data is received after a short + delay. + """ + if not self.transport.is_closing(): + event = h11.ConnectionClosed() + self.conn.send(event) + self.transport.close() + + +class RequestResponseCycle: + def __init__( + self, + scope: "HTTPScope", + conn: h11.Connection, + transport: asyncio.Transport, + flow: FlowControl, + logger: logging.Logger, + access_logger: logging.Logger, + access_log: bool, + default_headers: List[Tuple[bytes, bytes]], + message_event: asyncio.Event, + on_response: Callable[..., None], + ) -> None: + self.scope = scope + self.conn = conn + self.transport = transport + self.flow = flow + self.logger = logger + self.access_logger = access_logger + self.access_log = access_log + self.default_headers = default_headers + self.message_event = message_event + self.on_response = on_response + + # Connection state + self.disconnected = False + self.keep_alive = True + self.waiting_for_100_continue = conn.they_are_waiting_for_100_continue + + # Request state + self.body = b"" + self.more_body = True + + # Response state + self.response_started = False + self.response_complete = False + + # ASGI exception wrapper + async def run_asgi(self, app: "ASGI3Application") -> None: + try: + result = await app( # type: ignore[func-returns-value] + self.scope, self.receive, self.send + ) + except BaseException as exc: + msg = "Exception in ASGI application\n" + self.logger.error(msg, exc_info=exc) + if not self.response_started: + await self.send_500_response() + else: + self.transport.close() + else: + if result is not None: + msg = "ASGI callable should return None, but returned '%s'." + self.logger.error(msg, result) + self.transport.close() + elif not self.response_started and not self.disconnected: + msg = "ASGI callable returned without starting response." + self.logger.error(msg) + await self.send_500_response() + elif not self.response_complete and not self.disconnected: + msg = "ASGI callable returned without completing response." + self.logger.error(msg) + self.transport.close() + finally: + self.on_response = lambda: None + + async def send_500_response(self) -> None: + response_start_event: "HTTPResponseStartEvent" = { + "type": "http.response.start", + "status": 500, + "headers": [ + (b"content-type", b"text/plain; charset=utf-8"), + (b"connection", b"close"), + ], + } + await self.send(response_start_event) + response_body_event: "HTTPResponseBodyEvent" = { + "type": "http.response.body", + "body": b"Internal Server Error", + "more_body": False, + } + await self.send(response_body_event) + + # ASGI interface + async def send(self, message: "ASGISendEvent") -> None: + message_type = message["type"] + + if self.flow.write_paused and not self.disconnected: + await self.flow.drain() + + if self.disconnected: + return + + if not self.response_started: + # Sending response status line and headers + if message_type != "http.response.start": + msg = "Expected ASGI message 'http.response.start', but got '%s'." + raise RuntimeError(msg % message_type) + message = cast("HTTPResponseStartEvent", message) + + self.response_started = True + self.waiting_for_100_continue = False + + status = message["status"] + headers = self.default_headers + list(message.get("headers", [])) + + if CLOSE_HEADER in self.scope["headers"] and CLOSE_HEADER not in headers: + headers = headers + [CLOSE_HEADER] + + if self.access_log: + self.access_logger.info( + '%s - "%s %s HTTP/%s" %d', + get_client_addr(self.scope), + self.scope["method"], + get_path_with_query_string(self.scope), + self.scope["http_version"], + status, + ) + + # Write response status line and headers + reason = STATUS_PHRASES[status] + response = h11.Response(status_code=status, headers=headers, reason=reason) + output = self.conn.send(event=response) + self.transport.write(output) + + elif not self.response_complete: + # Sending response body + if message_type != "http.response.body": + msg = "Expected ASGI message 'http.response.body', but got '%s'." + raise RuntimeError(msg % message_type) + message = cast("HTTPResponseBodyEvent", message) + + body = message.get("body", b"") + more_body = message.get("more_body", False) + + # Write response body + data = b"" if self.scope["method"] == "HEAD" else body + output = self.conn.send(event=h11.Data(data=data)) + self.transport.write(output) + + # Handle response completion + if not more_body: + self.response_complete = True + self.message_event.set() + output = self.conn.send(event=h11.EndOfMessage()) + self.transport.write(output) + + else: + # Response already sent + msg = "Unexpected ASGI message '%s' sent, after response already completed." + raise RuntimeError(msg % message_type) + + if self.response_complete: + if self.conn.our_state is h11.MUST_CLOSE or not self.keep_alive: + self.conn.send(event=h11.ConnectionClosed()) + self.transport.close() + self.on_response() + + async def receive(self) -> "ASGIReceiveEvent": + if self.waiting_for_100_continue and not self.transport.is_closing(): + headers: List[Tuple[str, str]] = [] + event = h11.InformationalResponse( + status_code=100, headers=headers, reason="Continue" + ) + output = self.conn.send(event=event) + self.transport.write(output) + self.waiting_for_100_continue = False + + if not self.disconnected and not self.response_complete: + self.flow.resume_reading() + await self.message_event.wait() + self.message_event.clear() + + if self.disconnected or self.response_complete: + return {"type": "http.disconnect"} + + message: "HTTPRequestEvent" = { + "type": "http.request", + "body": self.body, + "more_body": self.more_body, + } + self.body = b"" + return message diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/http/httptools_impl.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/http/httptools_impl.py new file mode 100644 index 0000000..8d1a054 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/http/httptools_impl.py @@ -0,0 +1,601 @@ +import asyncio +import http +import logging +import re +import urllib +from asyncio.events import TimerHandle +from collections import deque +from typing import ( + Any, + Callable, + Deque, + Dict, + List, + Literal, + Optional, + Tuple, + Union, + cast, +) + +import httptools + +from uvicorn._types import ( + ASGI3Application, + ASGIReceiveEvent, + ASGISendEvent, + HTTPDisconnectEvent, + HTTPRequestEvent, + HTTPResponseBodyEvent, + HTTPResponseStartEvent, + HTTPScope, +) +from uvicorn.config import Config +from uvicorn.logging import TRACE_LOG_LEVEL +from uvicorn.protocols.http.flow_control import ( + CLOSE_HEADER, + HIGH_WATER_LIMIT, + FlowControl, + service_unavailable, +) +from uvicorn.protocols.utils import ( + get_client_addr, + get_local_addr, + get_path_with_query_string, + get_remote_addr, + is_ssl, +) +from uvicorn.server import ServerState + +HEADER_RE = re.compile(b'[\x00-\x1F\x7F()<>@,;:[]={} \t\\"]') +HEADER_VALUE_RE = re.compile(b"[\x00-\x1F\x7F]") + + +def _get_status_line(status_code: int) -> bytes: + try: + phrase = http.HTTPStatus(status_code).phrase.encode() + except ValueError: + phrase = b"" + return b"".join([b"HTTP/1.1 ", str(status_code).encode(), b" ", phrase, b"\r\n"]) + + +STATUS_LINE = { + status_code: _get_status_line(status_code) for status_code in range(100, 600) +} + + +class HttpToolsProtocol(asyncio.Protocol): + def __init__( + self, + config: Config, + server_state: ServerState, + app_state: Dict[str, Any], + _loop: Optional[asyncio.AbstractEventLoop] = None, + ) -> None: + if not config.loaded: + config.load() + + self.config = config + self.app = config.loaded_app + self.loop = _loop or asyncio.get_event_loop() + self.logger = logging.getLogger("uvicorn.error") + self.access_logger = logging.getLogger("uvicorn.access") + self.access_log = self.access_logger.hasHandlers() + self.parser = httptools.HttpRequestParser(self) + self.ws_protocol_class = config.ws_protocol_class + self.root_path = config.root_path + self.limit_concurrency = config.limit_concurrency + self.app_state = app_state + + # Timeouts + self.timeout_keep_alive_task: Optional[TimerHandle] = None + self.timeout_keep_alive = config.timeout_keep_alive + + # Global state + self.server_state = server_state + self.connections = server_state.connections + self.tasks = server_state.tasks + + # Per-connection state + self.transport: asyncio.Transport = None # type: ignore[assignment] + self.flow: FlowControl = None # type: ignore[assignment] + self.server: Optional[Tuple[str, int]] = None + self.client: Optional[Tuple[str, int]] = None + self.scheme: Optional[Literal["http", "https"]] = None + self.pipeline: Deque[Tuple[RequestResponseCycle, ASGI3Application]] = deque() + + # Per-request state + self.scope: HTTPScope = None # type: ignore[assignment] + self.headers: List[Tuple[bytes, bytes]] = None # type: ignore[assignment] + self.expect_100_continue = False + self.cycle: RequestResponseCycle = None # type: ignore[assignment] + + # Protocol interface + def connection_made( # type: ignore[override] + self, transport: asyncio.Transport + ) -> None: + self.connections.add(self) + + self.transport = transport + self.flow = FlowControl(transport) + self.server = get_local_addr(transport) + self.client = get_remote_addr(transport) + self.scheme = "https" if is_ssl(transport) else "http" + + if self.logger.level <= TRACE_LOG_LEVEL: + prefix = "%s:%d - " % self.client if self.client else "" + self.logger.log(TRACE_LOG_LEVEL, "%sHTTP connection made", prefix) + + def connection_lost(self, exc: Optional[Exception]) -> None: + self.connections.discard(self) + + if self.logger.level <= TRACE_LOG_LEVEL: + prefix = "%s:%d - " % self.client if self.client else "" + self.logger.log(TRACE_LOG_LEVEL, "%sHTTP connection lost", prefix) + + if self.cycle and not self.cycle.response_complete: + self.cycle.disconnected = True + if self.cycle is not None: + self.cycle.message_event.set() + if self.flow is not None: + self.flow.resume_writing() + if exc is None: + self.transport.close() + self._unset_keepalive_if_required() + + self.parser = None + + def eof_received(self) -> None: + pass + + def _unset_keepalive_if_required(self) -> None: + if self.timeout_keep_alive_task is not None: + self.timeout_keep_alive_task.cancel() + self.timeout_keep_alive_task = None + + def _get_upgrade(self) -> Optional[bytes]: + connection = [] + upgrade = None + for name, value in self.headers: + if name == b"connection": + connection = [token.lower().strip() for token in value.split(b",")] + if name == b"upgrade": + upgrade = value.lower() + if b"upgrade" in connection: + return upgrade + return None + + def _should_upgrade_to_ws(self, upgrade: Optional[bytes]) -> bool: + if upgrade == b"websocket" and self.ws_protocol_class is not None: + return True + if self.config.ws == "auto": + msg = "Unsupported upgrade request." + self.logger.warning(msg) + msg = "No supported WebSocket library detected. Please use \"pip install 'uvicorn[standard]'\", or install 'websockets' or 'wsproto' manually." # noqa: E501 + self.logger.warning(msg) + return False + + def _should_upgrade(self) -> bool: + upgrade = self._get_upgrade() + return self._should_upgrade_to_ws(upgrade) + + def data_received(self, data: bytes) -> None: + self._unset_keepalive_if_required() + + try: + self.parser.feed_data(data) + except httptools.HttpParserError: + msg = "Invalid HTTP request received." + self.logger.warning(msg) + self.send_400_response(msg) + return + except httptools.HttpParserUpgrade: + upgrade = self._get_upgrade() + if self._should_upgrade_to_ws(upgrade): + self.handle_websocket_upgrade() + + def handle_websocket_upgrade(self) -> None: + if self.logger.level <= TRACE_LOG_LEVEL: + prefix = "%s:%d - " % self.client if self.client else "" + self.logger.log(TRACE_LOG_LEVEL, "%sUpgrading to WebSocket", prefix) + + self.connections.discard(self) + method = self.scope["method"].encode() + output = [method, b" ", self.url, b" HTTP/1.1\r\n"] + for name, value in self.scope["headers"]: + output += [name, b": ", value, b"\r\n"] + output.append(b"\r\n") + protocol = self.ws_protocol_class( # type: ignore[call-arg, misc] + config=self.config, + server_state=self.server_state, + app_state=self.app_state, + ) + protocol.connection_made(self.transport) + protocol.data_received(b"".join(output)) + self.transport.set_protocol(protocol) + + def send_400_response(self, msg: str) -> None: + content = [STATUS_LINE[400]] + for name, value in self.server_state.default_headers: + content.extend([name, b": ", value, b"\r\n"]) + content.extend( + [ + b"content-type: text/plain; charset=utf-8\r\n", + b"content-length: " + str(len(msg)).encode("ascii") + b"\r\n", + b"connection: close\r\n", + b"\r\n", + msg.encode("ascii"), + ] + ) + self.transport.write(b"".join(content)) + self.transport.close() + + def on_message_begin(self) -> None: + self.url = b"" + self.expect_100_continue = False + self.headers = [] + self.scope = { # type: ignore[typeddict-item] + "type": "http", + "asgi": {"version": self.config.asgi_version, "spec_version": "2.3"}, + "http_version": "1.1", + "server": self.server, + "client": self.client, + "scheme": self.scheme, # type: ignore[typeddict-item] + "root_path": self.root_path, + "headers": self.headers, + "state": self.app_state.copy(), + } + + # Parser callbacks + def on_url(self, url: bytes) -> None: + self.url += url + + def on_header(self, name: bytes, value: bytes) -> None: + name = name.lower() + if name == b"expect" and value.lower() == b"100-continue": + self.expect_100_continue = True + self.headers.append((name, value)) + + def on_headers_complete(self) -> None: + http_version = self.parser.get_http_version() + method = self.parser.get_method() + self.scope["method"] = method.decode("ascii") + if http_version != "1.1": + self.scope["http_version"] = http_version + if self.parser.should_upgrade() and self._should_upgrade(): + return + parsed_url = httptools.parse_url(self.url) + raw_path = parsed_url.path + path = raw_path.decode("ascii") + if "%" in path: + path = urllib.parse.unquote(path) + self.scope["path"] = path + self.scope["raw_path"] = raw_path + self.scope["query_string"] = parsed_url.query or b"" + + # Handle 503 responses when 'limit_concurrency' is exceeded. + if self.limit_concurrency is not None and ( + len(self.connections) >= self.limit_concurrency + or len(self.tasks) >= self.limit_concurrency + ): + app = service_unavailable + message = "Exceeded concurrency limit." + self.logger.warning(message) + else: + app = self.app + + existing_cycle = self.cycle + self.cycle = RequestResponseCycle( + scope=self.scope, + transport=self.transport, + flow=self.flow, + logger=self.logger, + access_logger=self.access_logger, + access_log=self.access_log, + default_headers=self.server_state.default_headers, + message_event=asyncio.Event(), + expect_100_continue=self.expect_100_continue, + keep_alive=http_version != "1.0", + on_response=self.on_response_complete, + ) + if existing_cycle is None or existing_cycle.response_complete: + # Standard case - start processing the request. + task = self.loop.create_task(self.cycle.run_asgi(app)) + task.add_done_callback(self.tasks.discard) + self.tasks.add(task) + else: + # Pipelined HTTP requests need to be queued up. + self.flow.pause_reading() + self.pipeline.appendleft((self.cycle, app)) + + def on_body(self, body: bytes) -> None: + if ( + self.parser.should_upgrade() and self._should_upgrade() + ) or self.cycle.response_complete: + return + self.cycle.body += body + if len(self.cycle.body) > HIGH_WATER_LIMIT: + self.flow.pause_reading() + self.cycle.message_event.set() + + def on_message_complete(self) -> None: + if ( + self.parser.should_upgrade() and self._should_upgrade() + ) or self.cycle.response_complete: + return + self.cycle.more_body = False + self.cycle.message_event.set() + + def on_response_complete(self) -> None: + # Callback for pipelined HTTP requests to be started. + self.server_state.total_requests += 1 + + if self.transport.is_closing(): + return + + # Set a short Keep-Alive timeout. + self._unset_keepalive_if_required() + + self.timeout_keep_alive_task = self.loop.call_later( + self.timeout_keep_alive, self.timeout_keep_alive_handler + ) + + # Unpause data reads if needed. + self.flow.resume_reading() + + # Unblock any pipelined events. + if self.pipeline: + cycle, app = self.pipeline.pop() + task = self.loop.create_task(cycle.run_asgi(app)) + task.add_done_callback(self.tasks.discard) + self.tasks.add(task) + + def shutdown(self) -> None: + """ + Called by the server to commence a graceful shutdown. + """ + if self.cycle is None or self.cycle.response_complete: + self.transport.close() + else: + self.cycle.keep_alive = False + + def pause_writing(self) -> None: + """ + Called by the transport when the write buffer exceeds the high water mark. + """ + self.flow.pause_writing() + + def resume_writing(self) -> None: + """ + Called by the transport when the write buffer drops below the low water mark. + """ + self.flow.resume_writing() + + def timeout_keep_alive_handler(self) -> None: + """ + Called on a keep-alive connection if no new data is received after a short + delay. + """ + if not self.transport.is_closing(): + self.transport.close() + + +class RequestResponseCycle: + def __init__( + self, + scope: "HTTPScope", + transport: asyncio.Transport, + flow: FlowControl, + logger: logging.Logger, + access_logger: logging.Logger, + access_log: bool, + default_headers: List[Tuple[bytes, bytes]], + message_event: asyncio.Event, + expect_100_continue: bool, + keep_alive: bool, + on_response: Callable[..., None], + ): + self.scope = scope + self.transport = transport + self.flow = flow + self.logger = logger + self.access_logger = access_logger + self.access_log = access_log + self.default_headers = default_headers + self.message_event = message_event + self.on_response = on_response + + # Connection state + self.disconnected = False + self.keep_alive = keep_alive + self.waiting_for_100_continue = expect_100_continue + + # Request state + self.body = b"" + self.more_body = True + + # Response state + self.response_started = False + self.response_complete = False + self.chunked_encoding: Optional[bool] = None + self.expected_content_length = 0 + + # ASGI exception wrapper + async def run_asgi(self, app: "ASGI3Application") -> None: + try: + result = await app( # type: ignore[func-returns-value] + self.scope, self.receive, self.send + ) + except BaseException as exc: + msg = "Exception in ASGI application\n" + self.logger.error(msg, exc_info=exc) + if not self.response_started: + await self.send_500_response() + else: + self.transport.close() + else: + if result is not None: + msg = "ASGI callable should return None, but returned '%s'." + self.logger.error(msg, result) + self.transport.close() + elif not self.response_started and not self.disconnected: + msg = "ASGI callable returned without starting response." + self.logger.error(msg) + await self.send_500_response() + elif not self.response_complete and not self.disconnected: + msg = "ASGI callable returned without completing response." + self.logger.error(msg) + self.transport.close() + finally: + self.on_response = lambda: None + + async def send_500_response(self) -> None: + response_start_event: "HTTPResponseStartEvent" = { + "type": "http.response.start", + "status": 500, + "headers": [ + (b"content-type", b"text/plain; charset=utf-8"), + (b"connection", b"close"), + ], + } + await self.send(response_start_event) + response_body_event: "HTTPResponseBodyEvent" = { + "type": "http.response.body", + "body": b"Internal Server Error", + "more_body": False, + } + await self.send(response_body_event) + + # ASGI interface + async def send(self, message: "ASGISendEvent") -> None: + message_type = message["type"] + + if self.flow.write_paused and not self.disconnected: + await self.flow.drain() + + if self.disconnected: + return + + if not self.response_started: + # Sending response status line and headers + if message_type != "http.response.start": + msg = "Expected ASGI message 'http.response.start', but got '%s'." + raise RuntimeError(msg % message_type) + message = cast("HTTPResponseStartEvent", message) + + self.response_started = True + self.waiting_for_100_continue = False + + status_code = message["status"] + headers = self.default_headers + list(message.get("headers", [])) + + if CLOSE_HEADER in self.scope["headers"] and CLOSE_HEADER not in headers: + headers = headers + [CLOSE_HEADER] + + if self.access_log: + self.access_logger.info( + '%s - "%s %s HTTP/%s" %d', + get_client_addr(self.scope), + self.scope["method"], + get_path_with_query_string(self.scope), + self.scope["http_version"], + status_code, + ) + + # Write response status line and headers + content = [STATUS_LINE[status_code]] + + for name, value in headers: + if HEADER_RE.search(name): + raise RuntimeError("Invalid HTTP header name.") + if HEADER_VALUE_RE.search(value): + raise RuntimeError("Invalid HTTP header value.") + + name = name.lower() + if name == b"content-length" and self.chunked_encoding is None: + self.expected_content_length = int(value.decode()) + self.chunked_encoding = False + elif name == b"transfer-encoding" and value.lower() == b"chunked": + self.expected_content_length = 0 + self.chunked_encoding = True + elif name == b"connection" and value.lower() == b"close": + self.keep_alive = False + content.extend([name, b": ", value, b"\r\n"]) + + if ( + self.chunked_encoding is None + and self.scope["method"] != "HEAD" + and status_code not in (204, 304) + ): + # Neither content-length nor transfer-encoding specified + self.chunked_encoding = True + content.append(b"transfer-encoding: chunked\r\n") + + content.append(b"\r\n") + self.transport.write(b"".join(content)) + + elif not self.response_complete: + # Sending response body + if message_type != "http.response.body": + msg = "Expected ASGI message 'http.response.body', but got '%s'." + raise RuntimeError(msg % message_type) + + body = cast(bytes, message.get("body", b"")) + more_body = message.get("more_body", False) + + # Write response body + if self.scope["method"] == "HEAD": + self.expected_content_length = 0 + elif self.chunked_encoding: + if body: + content = [b"%x\r\n" % len(body), body, b"\r\n"] + else: + content = [] + if not more_body: + content.append(b"0\r\n\r\n") + self.transport.write(b"".join(content)) + else: + num_bytes = len(body) + if num_bytes > self.expected_content_length: + raise RuntimeError("Response content longer than Content-Length") + else: + self.expected_content_length -= num_bytes + self.transport.write(body) + + # Handle response completion + if not more_body: + if self.expected_content_length != 0: + raise RuntimeError("Response content shorter than Content-Length") + self.response_complete = True + self.message_event.set() + if not self.keep_alive: + self.transport.close() + self.on_response() + + else: + # Response already sent + msg = "Unexpected ASGI message '%s' sent, after response already completed." + raise RuntimeError(msg % message_type) + + async def receive(self) -> "ASGIReceiveEvent": + if self.waiting_for_100_continue and not self.transport.is_closing(): + self.transport.write(b"HTTP/1.1 100 Continue\r\n\r\n") + self.waiting_for_100_continue = False + + if not self.disconnected and not self.response_complete: + self.flow.resume_reading() + await self.message_event.wait() + self.message_event.clear() + + message: "Union[HTTPDisconnectEvent, HTTPRequestEvent]" + if self.disconnected or self.response_complete: + message = {"type": "http.disconnect"} + else: + message = { + "type": "http.request", + "body": self.body, + "more_body": self.more_body, + } + self.body = b"" + + return message diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/utils.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/utils.py new file mode 100644 index 0000000..d0697fe --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/utils.py @@ -0,0 +1,54 @@ +import asyncio +import urllib.parse +from typing import Optional, Tuple + +from uvicorn._types import WWWScope + + +def get_remote_addr(transport: asyncio.Transport) -> Optional[Tuple[str, int]]: + socket_info = transport.get_extra_info("socket") + if socket_info is not None: + try: + info = socket_info.getpeername() + return (str(info[0]), int(info[1])) if isinstance(info, tuple) else None + except OSError: # pragma: no cover + # This case appears to inconsistently occur with uvloop + # bound to a unix domain socket. + return None + + info = transport.get_extra_info("peername") + if info is not None and isinstance(info, (list, tuple)) and len(info) == 2: + return (str(info[0]), int(info[1])) + return None + + +def get_local_addr(transport: asyncio.Transport) -> Optional[Tuple[str, int]]: + socket_info = transport.get_extra_info("socket") + if socket_info is not None: + info = socket_info.getsockname() + + return (str(info[0]), int(info[1])) if isinstance(info, tuple) else None + info = transport.get_extra_info("sockname") + if info is not None and isinstance(info, (list, tuple)) and len(info) == 2: + return (str(info[0]), int(info[1])) + return None + + +def is_ssl(transport: asyncio.Transport) -> bool: + return bool(transport.get_extra_info("sslcontext")) + + +def get_client_addr(scope: "WWWScope") -> str: + client = scope.get("client") + if not client: + return "" + return "%s:%d" % client + + +def get_path_with_query_string(scope: "WWWScope") -> str: + path_with_query_string = urllib.parse.quote(scope["path"]) + if scope["query_string"]: + path_with_query_string = "{}?{}".format( + path_with_query_string, scope["query_string"].decode("ascii") + ) + return path_with_query_string diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/websockets/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/websockets/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/websockets/auto.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/websockets/auto.py new file mode 100644 index 0000000..368b982 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/websockets/auto.py @@ -0,0 +1,19 @@ +import asyncio +import typing + +AutoWebSocketsProtocol: typing.Optional[typing.Callable[..., asyncio.Protocol]] +try: + import websockets # noqa +except ImportError: # pragma: no cover + try: + import wsproto # noqa + except ImportError: + AutoWebSocketsProtocol = None + else: + from uvicorn.protocols.websockets.wsproto_impl import WSProtocol + + AutoWebSocketsProtocol = WSProtocol +else: + from uvicorn.protocols.websockets.websockets_impl import WebSocketProtocol + + AutoWebSocketsProtocol = WebSocketProtocol diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/websockets/websockets_impl.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/websockets/websockets_impl.py new file mode 100644 index 0000000..089eeb5 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/websockets/websockets_impl.py @@ -0,0 +1,376 @@ +import asyncio +import http +import logging +from typing import ( + Any, + Dict, + List, + Literal, + Optional, + Sequence, + Tuple, + Union, + cast, +) +from urllib.parse import unquote + +import websockets +from websockets.datastructures import Headers +from websockets.exceptions import ConnectionClosed +from websockets.extensions.permessage_deflate import ServerPerMessageDeflateFactory +from websockets.legacy.server import HTTPResponse +from websockets.server import WebSocketServerProtocol +from websockets.typing import Subprotocol + +from uvicorn._types import ( + ASGISendEvent, + WebSocketAcceptEvent, + WebSocketCloseEvent, + WebSocketConnectEvent, + WebSocketDisconnectEvent, + WebSocketReceiveEvent, + WebSocketScope, + WebSocketSendEvent, +) +from uvicorn.config import Config +from uvicorn.logging import TRACE_LOG_LEVEL +from uvicorn.protocols.utils import ( + get_local_addr, + get_path_with_query_string, + get_remote_addr, + is_ssl, +) +from uvicorn.server import ServerState + + +class Server: + closing = False + + def register(self, ws: WebSocketServerProtocol) -> None: + pass + + def unregister(self, ws: WebSocketServerProtocol) -> None: + pass + + def is_serving(self) -> bool: + return not self.closing + + +class WebSocketProtocol(WebSocketServerProtocol): + extra_headers: List[Tuple[str, str]] + + def __init__( + self, + config: Config, + server_state: ServerState, + app_state: Dict[str, Any], + _loop: Optional[asyncio.AbstractEventLoop] = None, + ): + if not config.loaded: + config.load() + + self.config = config + self.app = config.loaded_app + self.loop = _loop or asyncio.get_event_loop() + self.root_path = config.root_path + self.app_state = app_state + + # Shared server state + self.connections = server_state.connections + self.tasks = server_state.tasks + + # Connection state + self.transport: asyncio.Transport = None # type: ignore[assignment] + self.server: Optional[Tuple[str, int]] = None + self.client: Optional[Tuple[str, int]] = None + self.scheme: Literal["wss", "ws"] = None # type: ignore[assignment] + + # Connection events + self.scope: WebSocketScope = None # type: ignore[assignment] + self.handshake_started_event = asyncio.Event() + self.handshake_completed_event = asyncio.Event() + self.closed_event = asyncio.Event() + self.initial_response: Optional[HTTPResponse] = None + self.connect_sent = False + self.lost_connection_before_handshake = False + self.accepted_subprotocol: Optional[Subprotocol] = None + + self.ws_server: Server = Server() # type: ignore[assignment] + + extensions = [] + if self.config.ws_per_message_deflate: + extensions.append(ServerPerMessageDeflateFactory()) + + super().__init__( + ws_handler=self.ws_handler, + ws_server=self.ws_server, # type: ignore[arg-type] + max_size=self.config.ws_max_size, + max_queue=self.config.ws_max_queue, + ping_interval=self.config.ws_ping_interval, + ping_timeout=self.config.ws_ping_timeout, + extensions=extensions, + logger=logging.getLogger("uvicorn.error"), + ) + self.server_header = None + self.extra_headers = [ + (name.decode("latin-1"), value.decode("latin-1")) + for name, value in server_state.default_headers + ] + + def connection_made( # type: ignore[override] + self, transport: asyncio.Transport + ) -> None: + self.connections.add(self) + self.transport = transport + self.server = get_local_addr(transport) + self.client = get_remote_addr(transport) + self.scheme = "wss" if is_ssl(transport) else "ws" + + if self.logger.isEnabledFor(TRACE_LOG_LEVEL): + prefix = "%s:%d - " % self.client if self.client else "" + self.logger.log(TRACE_LOG_LEVEL, "%sWebSocket connection made", prefix) + + super().connection_made(transport) + + def connection_lost(self, exc: Optional[Exception]) -> None: + self.connections.remove(self) + + if self.logger.isEnabledFor(TRACE_LOG_LEVEL): + prefix = "%s:%d - " % self.client if self.client else "" + self.logger.log(TRACE_LOG_LEVEL, "%sWebSocket connection lost", prefix) + + self.lost_connection_before_handshake = ( + not self.handshake_completed_event.is_set() + ) + self.handshake_completed_event.set() + super().connection_lost(exc) + if exc is None: + self.transport.close() + + def shutdown(self) -> None: + self.ws_server.closing = True + if self.handshake_completed_event.is_set(): + self.fail_connection(1012) + else: + self.send_500_response() + self.transport.close() + + def on_task_complete(self, task: asyncio.Task) -> None: + self.tasks.discard(task) + + async def process_request( + self, path: str, headers: Headers + ) -> Optional[HTTPResponse]: + """ + This hook is called to determine if the websocket should return + an HTTP response and close. + + Our behavior here is to start the ASGI application, and then wait + for either `accept` or `close` in order to determine if we should + close the connection. + """ + path_portion, _, query_string = path.partition("?") + + websockets.legacy.handshake.check_request(headers) + + subprotocols = [] + for header in headers.get_all("Sec-WebSocket-Protocol"): + subprotocols.extend([token.strip() for token in header.split(",")]) + + asgi_headers = [ + (name.encode("ascii"), value.encode("ascii", errors="surrogateescape")) + for name, value in headers.raw_items() + ] + + self.scope = { + "type": "websocket", + "asgi": {"version": self.config.asgi_version, "spec_version": "2.3"}, + "http_version": "1.1", + "scheme": self.scheme, + "server": self.server, + "client": self.client, + "root_path": self.root_path, + "path": unquote(path_portion), + "raw_path": path_portion.encode("ascii"), + "query_string": query_string.encode("ascii"), + "headers": asgi_headers, + "subprotocols": subprotocols, + "state": self.app_state.copy(), + } + task = self.loop.create_task(self.run_asgi()) + task.add_done_callback(self.on_task_complete) + self.tasks.add(task) + await self.handshake_started_event.wait() + return self.initial_response + + def process_subprotocol( + self, headers: Headers, available_subprotocols: Optional[Sequence[Subprotocol]] + ) -> Optional[Subprotocol]: + """ + We override the standard 'process_subprotocol' behavior here so that + we return whatever subprotocol is sent in the 'accept' message. + """ + return self.accepted_subprotocol + + def send_500_response(self) -> None: + msg = b"Internal Server Error" + content = [ + b"HTTP/1.1 500 Internal Server Error\r\n" + b"content-type: text/plain; charset=utf-8\r\n", + b"content-length: " + str(len(msg)).encode("ascii") + b"\r\n", + b"connection: close\r\n", + b"\r\n", + msg, + ] + self.transport.write(b"".join(content)) + # Allow handler task to terminate cleanly, as websockets doesn't cancel it by + # itself (see https://github.com/encode/uvicorn/issues/920) + self.handshake_started_event.set() + + async def ws_handler( # type: ignore[override] + self, protocol: WebSocketServerProtocol, path: str + ) -> Any: + """ + This is the main handler function for the 'websockets' implementation + to call into. We just wait for close then return, and instead allow + 'send' and 'receive' events to drive the flow. + """ + self.handshake_completed_event.set() + await self.wait_closed() + + async def run_asgi(self) -> None: + """ + Wrapper around the ASGI callable, handling exceptions and unexpected + termination states. + """ + try: + result = await self.app(self.scope, self.asgi_receive, self.asgi_send) + except BaseException as exc: + self.closed_event.set() + msg = "Exception in ASGI application\n" + self.logger.error(msg, exc_info=exc) + if not self.handshake_started_event.is_set(): + self.send_500_response() + else: + await self.handshake_completed_event.wait() + self.transport.close() + else: + self.closed_event.set() + if not self.handshake_started_event.is_set(): + msg = "ASGI callable returned without sending handshake." + self.logger.error(msg) + self.send_500_response() + self.transport.close() + elif result is not None: + msg = "ASGI callable should return None, but returned '%s'." + self.logger.error(msg, result) + await self.handshake_completed_event.wait() + self.transport.close() + + async def asgi_send(self, message: "ASGISendEvent") -> None: + message_type = message["type"] + + if not self.handshake_started_event.is_set(): + if message_type == "websocket.accept": + message = cast("WebSocketAcceptEvent", message) + self.logger.info( + '%s - "WebSocket %s" [accepted]', + self.scope["client"], + get_path_with_query_string(self.scope), + ) + self.initial_response = None + self.accepted_subprotocol = cast( + Optional[Subprotocol], message.get("subprotocol") + ) + if "headers" in message: + self.extra_headers.extend( + # ASGI spec requires bytes + # But for compatibility we need to convert it to strings + (name.decode("latin-1"), value.decode("latin-1")) + for name, value in message["headers"] + ) + self.handshake_started_event.set() + + elif message_type == "websocket.close": + message = cast("WebSocketCloseEvent", message) + self.logger.info( + '%s - "WebSocket %s" 403', + self.scope["client"], + get_path_with_query_string(self.scope), + ) + self.initial_response = (http.HTTPStatus.FORBIDDEN, [], b"") + self.handshake_started_event.set() + self.closed_event.set() + + else: + msg = ( + "Expected ASGI message 'websocket.accept' or 'websocket.close', " + "but got '%s'." + ) + raise RuntimeError(msg % message_type) + + elif not self.closed_event.is_set(): + await self.handshake_completed_event.wait() + + if message_type == "websocket.send": + message = cast("WebSocketSendEvent", message) + bytes_data = message.get("bytes") + text_data = message.get("text") + data = text_data if bytes_data is None else bytes_data + await self.send(data) # type: ignore[arg-type] + + elif message_type == "websocket.close": + message = cast("WebSocketCloseEvent", message) + code = message.get("code", 1000) + reason = message.get("reason", "") or "" + await self.close(code, reason) + self.closed_event.set() + + else: + msg = ( + "Expected ASGI message 'websocket.send' or 'websocket.close'," + " but got '%s'." + ) + raise RuntimeError(msg % message_type) + + else: + msg = "Unexpected ASGI message '%s', after sending 'websocket.close'." + raise RuntimeError(msg % message_type) + + async def asgi_receive( + self, + ) -> Union[ + "WebSocketDisconnectEvent", "WebSocketConnectEvent", "WebSocketReceiveEvent" + ]: + if not self.connect_sent: + self.connect_sent = True + return {"type": "websocket.connect"} + + await self.handshake_completed_event.wait() + + if self.lost_connection_before_handshake: + # If the handshake failed or the app closed before handshake completion, + # use 1006 Abnormal Closure. + return {"type": "websocket.disconnect", "code": 1006} + + if self.closed_event.is_set(): + return {"type": "websocket.disconnect", "code": 1005} + + try: + data = await self.recv() + except ConnectionClosed as exc: + self.closed_event.set() + if self.ws_server.closing: + return {"type": "websocket.disconnect", "code": 1012} + return {"type": "websocket.disconnect", "code": exc.code} + + msg: WebSocketReceiveEvent = { # type: ignore[typeddict-item] + "type": "websocket.receive" + } + + if isinstance(data, str): + msg["text"] = data + else: + msg["bytes"] = data + + return msg diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/websockets/wsproto_impl.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/websockets/wsproto_impl.py new file mode 100644 index 0000000..aa4bec8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/protocols/websockets/wsproto_impl.py @@ -0,0 +1,342 @@ +import asyncio +import logging +import typing +from typing import Literal +from urllib.parse import unquote + +import wsproto +from wsproto import ConnectionType, events +from wsproto.connection import ConnectionState +from wsproto.extensions import Extension, PerMessageDeflate +from wsproto.utilities import RemoteProtocolError + +from uvicorn._types import ( + ASGISendEvent, + WebSocketAcceptEvent, + WebSocketCloseEvent, + WebSocketEvent, + WebSocketReceiveEvent, + WebSocketScope, + WebSocketSendEvent, +) +from uvicorn.config import Config +from uvicorn.logging import TRACE_LOG_LEVEL +from uvicorn.protocols.utils import ( + get_local_addr, + get_path_with_query_string, + get_remote_addr, + is_ssl, +) +from uvicorn.server import ServerState + + +class WSProtocol(asyncio.Protocol): + def __init__( + self, + config: Config, + server_state: ServerState, + app_state: typing.Dict[str, typing.Any], + _loop: typing.Optional[asyncio.AbstractEventLoop] = None, + ) -> None: + if not config.loaded: + config.load() + + self.config = config + self.app = config.loaded_app + self.loop = _loop or asyncio.get_event_loop() + self.logger = logging.getLogger("uvicorn.error") + self.root_path = config.root_path + self.app_state = app_state + + # Shared server state + self.connections = server_state.connections + self.tasks = server_state.tasks + self.default_headers = server_state.default_headers + + # Connection state + self.transport: asyncio.Transport = None # type: ignore[assignment] + self.server: typing.Optional[typing.Tuple[str, int]] = None + self.client: typing.Optional[typing.Tuple[str, int]] = None + self.scheme: Literal["wss", "ws"] = None # type: ignore[assignment] + + # WebSocket state + self.queue: asyncio.Queue["WebSocketEvent"] = asyncio.Queue() + self.handshake_complete = False + self.close_sent = False + + self.conn = wsproto.WSConnection(connection_type=ConnectionType.SERVER) + + self.read_paused = False + self.writable = asyncio.Event() + self.writable.set() + + # Buffers + self.bytes = b"" + self.text = "" + + # Protocol interface + + def connection_made( # type: ignore[override] + self, transport: asyncio.Transport + ) -> None: + self.connections.add(self) + self.transport = transport + self.server = get_local_addr(transport) + self.client = get_remote_addr(transport) + self.scheme = "wss" if is_ssl(transport) else "ws" + + if self.logger.level <= TRACE_LOG_LEVEL: + prefix = "%s:%d - " % self.client if self.client else "" + self.logger.log(TRACE_LOG_LEVEL, "%sWebSocket connection made", prefix) + + def connection_lost(self, exc: typing.Optional[Exception]) -> None: + code = 1005 if self.handshake_complete else 1006 + self.queue.put_nowait({"type": "websocket.disconnect", "code": code}) + self.connections.remove(self) + + if self.logger.level <= TRACE_LOG_LEVEL: + prefix = "%s:%d - " % self.client if self.client else "" + self.logger.log(TRACE_LOG_LEVEL, "%sWebSocket connection lost", prefix) + + self.handshake_complete = True + if exc is None: + self.transport.close() + + def eof_received(self) -> None: + pass + + def data_received(self, data: bytes) -> None: + try: + self.conn.receive_data(data) + except RemoteProtocolError as err: + # TODO: Remove `type: ignore` when wsproto fixes the type annotation. + self.transport.write(self.conn.send(err.event_hint)) # type: ignore[arg-type] # noqa: E501 + self.transport.close() + else: + self.handle_events() + + def handle_events(self) -> None: + for event in self.conn.events(): + if isinstance(event, events.Request): + self.handle_connect(event) + elif isinstance(event, events.TextMessage): + self.handle_text(event) + elif isinstance(event, events.BytesMessage): + self.handle_bytes(event) + elif isinstance(event, events.CloseConnection): + self.handle_close(event) + elif isinstance(event, events.Ping): + self.handle_ping(event) + + def pause_writing(self) -> None: + """ + Called by the transport when the write buffer exceeds the high water mark. + """ + self.writable.clear() + + def resume_writing(self) -> None: + """ + Called by the transport when the write buffer drops below the low water mark. + """ + self.writable.set() + + def shutdown(self) -> None: + if self.handshake_complete: + self.queue.put_nowait({"type": "websocket.disconnect", "code": 1012}) + output = self.conn.send(wsproto.events.CloseConnection(code=1012)) + self.transport.write(output) + else: + self.send_500_response() + self.transport.close() + + def on_task_complete(self, task: asyncio.Task) -> None: + self.tasks.discard(task) + + # Event handlers + + def handle_connect(self, event: events.Request) -> None: + headers = [(b"host", event.host.encode())] + headers += [(key.lower(), value) for key, value in event.extra_headers] + raw_path, _, query_string = event.target.partition("?") + self.scope: "WebSocketScope" = { + "type": "websocket", + "asgi": {"version": self.config.asgi_version, "spec_version": "2.3"}, + "http_version": "1.1", + "scheme": self.scheme, + "server": self.server, + "client": self.client, + "root_path": self.root_path, + "path": unquote(raw_path), + "raw_path": raw_path.encode("ascii"), + "query_string": query_string.encode("ascii"), + "headers": headers, + "subprotocols": event.subprotocols, + "state": self.app_state.copy(), + } + self.queue.put_nowait({"type": "websocket.connect"}) + task = self.loop.create_task(self.run_asgi()) + task.add_done_callback(self.on_task_complete) + self.tasks.add(task) + + def handle_text(self, event: events.TextMessage) -> None: + self.text += event.data + if event.message_finished: + msg: "WebSocketReceiveEvent" = { # type: ignore[typeddict-item] + "type": "websocket.receive", + "text": self.text, + } + self.queue.put_nowait(msg) + self.text = "" + if not self.read_paused: + self.read_paused = True + self.transport.pause_reading() + + def handle_bytes(self, event: events.BytesMessage) -> None: + self.bytes += event.data + # todo: we may want to guard the size of self.bytes and self.text + if event.message_finished: + msg: "WebSocketReceiveEvent" = { # type: ignore[typeddict-item] + "type": "websocket.receive", + "bytes": self.bytes, + } + self.queue.put_nowait(msg) + self.bytes = b"" + if not self.read_paused: + self.read_paused = True + self.transport.pause_reading() + + def handle_close(self, event: events.CloseConnection) -> None: + if self.conn.state == ConnectionState.REMOTE_CLOSING: + self.transport.write(self.conn.send(event.response())) + self.queue.put_nowait({"type": "websocket.disconnect", "code": event.code}) + self.transport.close() + + def handle_ping(self, event: events.Ping) -> None: + self.transport.write(self.conn.send(event.response())) + + def send_500_response(self) -> None: + headers = [ + (b"content-type", b"text/plain; charset=utf-8"), + (b"connection", b"close"), + ] + output = self.conn.send( + wsproto.events.RejectConnection( + status_code=500, headers=headers, has_body=True + ) + ) + output += self.conn.send( + wsproto.events.RejectData(data=b"Internal Server Error") + ) + self.transport.write(output) + + async def run_asgi(self) -> None: + try: + result = await self.app(self.scope, self.receive, self.send) + except BaseException: + self.logger.exception("Exception in ASGI application\n") + if not self.handshake_complete: + self.send_500_response() + self.transport.close() + else: + if not self.handshake_complete: + msg = "ASGI callable returned without completing handshake." + self.logger.error(msg) + self.send_500_response() + self.transport.close() + elif result is not None: + msg = "ASGI callable should return None, but returned '%s'." + self.logger.error(msg, result) + self.transport.close() + + async def send(self, message: "ASGISendEvent") -> None: + await self.writable.wait() + + message_type = message["type"] + + if not self.handshake_complete: + if message_type == "websocket.accept": + message = typing.cast("WebSocketAcceptEvent", message) + self.logger.info( + '%s - "WebSocket %s" [accepted]', + self.scope["client"], + get_path_with_query_string(self.scope), + ) + subprotocol = message.get("subprotocol") + extra_headers = self.default_headers + list(message.get("headers", [])) + extensions: typing.List[Extension] = [] + if self.config.ws_per_message_deflate: + extensions.append(PerMessageDeflate()) + if not self.transport.is_closing(): + self.handshake_complete = True + output = self.conn.send( + wsproto.events.AcceptConnection( + subprotocol=subprotocol, + extensions=extensions, + extra_headers=extra_headers, + ) + ) + self.transport.write(output) + + elif message_type == "websocket.close": + self.queue.put_nowait({"type": "websocket.disconnect", "code": 1006}) + self.logger.info( + '%s - "WebSocket %s" 403', + self.scope["client"], + get_path_with_query_string(self.scope), + ) + self.handshake_complete = True + self.close_sent = True + event = events.RejectConnection(status_code=403, headers=[]) + output = self.conn.send(event) + self.transport.write(output) + self.transport.close() + + else: + msg = ( + "Expected ASGI message 'websocket.accept' or 'websocket.close', " + "but got '%s'." + ) + raise RuntimeError(msg % message_type) + + elif not self.close_sent: + if message_type == "websocket.send": + message = typing.cast("WebSocketSendEvent", message) + bytes_data = message.get("bytes") + text_data = message.get("text") + data = text_data if bytes_data is None else bytes_data + output = self.conn.send( + wsproto.events.Message(data=data) # type: ignore[type-var] + ) + if not self.transport.is_closing(): + self.transport.write(output) + + elif message_type == "websocket.close": + message = typing.cast("WebSocketCloseEvent", message) + self.close_sent = True + code = message.get("code", 1000) + reason = message.get("reason", "") or "" + self.queue.put_nowait({"type": "websocket.disconnect", "code": code}) + output = self.conn.send( + wsproto.events.CloseConnection(code=code, reason=reason) + ) + if not self.transport.is_closing(): + self.transport.write(output) + self.transport.close() + + else: + msg = ( + "Expected ASGI message 'websocket.send' or 'websocket.close'," + " but got '%s'." + ) + raise RuntimeError(msg % message_type) + + else: + msg = "Unexpected ASGI message '%s', after sending 'websocket.close'." + raise RuntimeError(msg % message_type) + + async def receive(self) -> "WebSocketEvent": + message = await self.queue.get() + if self.read_paused and self.queue.empty(): + self.read_paused = False + self.transport.resume_reading() + return message diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/py.typed b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/py.typed new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/py.typed @@ -0,0 +1 @@ + diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/server.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/server.py new file mode 100644 index 0000000..3e0db9d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/server.py @@ -0,0 +1,334 @@ +import asyncio +import logging +import os +import platform +import signal +import socket +import sys +import threading +import time +from email.utils import formatdate +from types import FrameType +from typing import TYPE_CHECKING, List, Optional, Sequence, Set, Tuple, Union + +import click + +from uvicorn.config import Config + +if TYPE_CHECKING: + from uvicorn.protocols.http.h11_impl import H11Protocol + from uvicorn.protocols.http.httptools_impl import HttpToolsProtocol + from uvicorn.protocols.websockets.websockets_impl import WebSocketProtocol + from uvicorn.protocols.websockets.wsproto_impl import WSProtocol + + Protocols = Union[H11Protocol, HttpToolsProtocol, WSProtocol, WebSocketProtocol] + + +HANDLED_SIGNALS = ( + signal.SIGINT, # Unix signal 2. Sent by Ctrl+C. + signal.SIGTERM, # Unix signal 15. Sent by `kill `. +) +if sys.platform == "win32": # pragma: py-not-win32 + HANDLED_SIGNALS += (signal.SIGBREAK,) # Windows signal 21. Sent by Ctrl+Break. + +logger = logging.getLogger("uvicorn.error") + + +class ServerState: + """ + Shared servers state that is available between all protocol instances. + """ + + def __init__(self) -> None: + self.total_requests = 0 + self.connections: Set["Protocols"] = set() + self.tasks: Set[asyncio.Task] = set() + self.default_headers: List[Tuple[bytes, bytes]] = [] + + +class Server: + def __init__(self, config: Config) -> None: + self.config = config + self.server_state = ServerState() + + self.started = False + self.should_exit = False + self.force_exit = False + self.last_notified = 0.0 + + def run(self, sockets: Optional[List[socket.socket]] = None) -> None: + self.config.setup_event_loop() + return asyncio.run(self.serve(sockets=sockets)) + + async def serve(self, sockets: Optional[List[socket.socket]] = None) -> None: + process_id = os.getpid() + + config = self.config + if not config.loaded: + config.load() + + self.lifespan = config.lifespan_class(config) + + self.install_signal_handlers() + + message = "Started server process [%d]" + color_message = "Started server process [" + click.style("%d", fg="cyan") + "]" + logger.info(message, process_id, extra={"color_message": color_message}) + + await self.startup(sockets=sockets) + if self.should_exit: + return + await self.main_loop() + await self.shutdown(sockets=sockets) + + message = "Finished server process [%d]" + color_message = "Finished server process [" + click.style("%d", fg="cyan") + "]" + logger.info(message, process_id, extra={"color_message": color_message}) + + async def startup(self, sockets: Optional[List[socket.socket]] = None) -> None: + await self.lifespan.startup() + if self.lifespan.should_exit: + self.should_exit = True + return + + config = self.config + + def create_protocol( + _loop: Optional[asyncio.AbstractEventLoop] = None, + ) -> asyncio.Protocol: + return config.http_protocol_class( # type: ignore[call-arg] + config=config, + server_state=self.server_state, + app_state=self.lifespan.state, + _loop=_loop, + ) + + loop = asyncio.get_running_loop() + + listeners: Sequence[socket.SocketType] + if sockets is not None: + # Explicitly passed a list of open sockets. + # We use this when the server is run from a Gunicorn worker. + + def _share_socket( + sock: socket.SocketType, + ) -> socket.SocketType: # pragma py-linux pragma: py-darwin + # Windows requires the socket be explicitly shared across + # multiple workers (processes). + from socket import fromshare # type: ignore[attr-defined] + + sock_data = sock.share(os.getpid()) # type: ignore[attr-defined] + return fromshare(sock_data) + + self.servers: List[asyncio.base_events.Server] = [] + for sock in sockets: + is_windows = platform.system() == "Windows" + if config.workers > 1 and is_windows: # pragma: py-not-win32 + sock = _share_socket(sock) # type: ignore[assignment] + server = await loop.create_server( + create_protocol, sock=sock, ssl=config.ssl, backlog=config.backlog + ) + self.servers.append(server) + listeners = sockets + + elif config.fd is not None: # pragma: py-win32 + # Use an existing socket, from a file descriptor. + sock = socket.fromfd(config.fd, socket.AF_UNIX, socket.SOCK_STREAM) + server = await loop.create_server( + create_protocol, sock=sock, ssl=config.ssl, backlog=config.backlog + ) + assert server.sockets is not None # mypy + listeners = server.sockets + self.servers = [server] + + elif config.uds is not None: # pragma: py-win32 + # Create a socket using UNIX domain socket. + uds_perms = 0o666 + if os.path.exists(config.uds): + uds_perms = os.stat(config.uds).st_mode + server = await loop.create_unix_server( + create_protocol, path=config.uds, ssl=config.ssl, backlog=config.backlog + ) + os.chmod(config.uds, uds_perms) + assert server.sockets is not None # mypy + listeners = server.sockets + self.servers = [server] + + else: + # Standard case. Create a socket from a host/port pair. + try: + server = await loop.create_server( + create_protocol, + host=config.host, + port=config.port, + ssl=config.ssl, + backlog=config.backlog, + ) + except OSError as exc: + logger.error(exc) + await self.lifespan.shutdown() + sys.exit(1) + + assert server.sockets is not None + listeners = server.sockets + self.servers = [server] + + if sockets is None: + self._log_started_message(listeners) + else: + # We're most likely running multiple workers, so a message has already been + # logged by `config.bind_socket()`. + pass + + self.started = True + + def _log_started_message(self, listeners: Sequence[socket.SocketType]) -> None: + config = self.config + + if config.fd is not None: # pragma: py-win32 + sock = listeners[0] + logger.info( + "Uvicorn running on socket %s (Press CTRL+C to quit)", + sock.getsockname(), + ) + + elif config.uds is not None: # pragma: py-win32 + logger.info( + "Uvicorn running on unix socket %s (Press CTRL+C to quit)", config.uds + ) + + else: + addr_format = "%s://%s:%d" + host = "0.0.0.0" if config.host is None else config.host + if ":" in host: + # It's an IPv6 address. + addr_format = "%s://[%s]:%d" + + port = config.port + if port == 0: + port = listeners[0].getsockname()[1] + + protocol_name = "https" if config.ssl else "http" + message = f"Uvicorn running on {addr_format} (Press CTRL+C to quit)" + color_message = ( + "Uvicorn running on " + + click.style(addr_format, bold=True) + + " (Press CTRL+C to quit)" + ) + logger.info( + message, + protocol_name, + host, + port, + extra={"color_message": color_message}, + ) + + async def main_loop(self) -> None: + counter = 0 + should_exit = await self.on_tick(counter) + while not should_exit: + counter += 1 + counter = counter % 864000 + await asyncio.sleep(0.1) + should_exit = await self.on_tick(counter) + + async def on_tick(self, counter: int) -> bool: + # Update the default headers, once per second. + if counter % 10 == 0: + current_time = time.time() + current_date = formatdate(current_time, usegmt=True).encode() + + if self.config.date_header: + date_header = [(b"date", current_date)] + else: + date_header = [] + + self.server_state.default_headers = ( + date_header + self.config.encoded_headers + ) + + # Callback to `callback_notify` once every `timeout_notify` seconds. + if self.config.callback_notify is not None: + if current_time - self.last_notified > self.config.timeout_notify: + self.last_notified = current_time + await self.config.callback_notify() + + # Determine if we should exit. + if self.should_exit: + return True + if self.config.limit_max_requests is not None: + return self.server_state.total_requests >= self.config.limit_max_requests + return False + + async def shutdown(self, sockets: Optional[List[socket.socket]] = None) -> None: + logger.info("Shutting down") + + # Stop accepting new connections. + for server in self.servers: + server.close() + for sock in sockets or []: + sock.close() + for server in self.servers: + await server.wait_closed() + + # Request shutdown on all existing connections. + for connection in list(self.server_state.connections): + connection.shutdown() + await asyncio.sleep(0.1) + + # When 3.10 is not supported anymore, use `async with asyncio.timeout(...):`. + try: + await asyncio.wait_for( + self._wait_tasks_to_complete(), + timeout=self.config.timeout_graceful_shutdown, + ) + except asyncio.TimeoutError: + logger.error( + "Cancel %s running task(s), timeout graceful shutdown exceeded", + len(self.server_state.tasks), + ) + for t in self.server_state.tasks: + if sys.version_info < (3, 9): # pragma: py-gte-39 + t.cancel() + else: # pragma: py-lt-39 + t.cancel(msg="Task cancelled, timeout graceful shutdown exceeded") + + # Send the lifespan shutdown event, and wait for application shutdown. + if not self.force_exit: + await self.lifespan.shutdown() + + async def _wait_tasks_to_complete(self) -> None: + # Wait for existing connections to finish sending responses. + if self.server_state.connections and not self.force_exit: + msg = "Waiting for connections to close. (CTRL+C to force quit)" + logger.info(msg) + while self.server_state.connections and not self.force_exit: + await asyncio.sleep(0.1) + + # Wait for existing tasks to complete. + if self.server_state.tasks and not self.force_exit: + msg = "Waiting for background tasks to complete. (CTRL+C to force quit)" + logger.info(msg) + while self.server_state.tasks and not self.force_exit: + await asyncio.sleep(0.1) + + def install_signal_handlers(self) -> None: + if threading.current_thread() is not threading.main_thread(): + # Signals can only be listened to from the main thread. + return + + loop = asyncio.get_event_loop() + + try: + for sig in HANDLED_SIGNALS: + loop.add_signal_handler(sig, self.handle_exit, sig, None) + except NotImplementedError: # pragma: no cover + # Windows + for sig in HANDLED_SIGNALS: + signal.signal(sig, self.handle_exit) + + def handle_exit(self, sig: int, frame: Optional[FrameType]) -> None: + if self.should_exit and sig == signal.SIGINT: + self.force_exit = True + else: + self.should_exit = True diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/supervisors/__init__.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/supervisors/__init__.py new file mode 100644 index 0000000..deaf12e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/supervisors/__init__.py @@ -0,0 +1,21 @@ +from typing import TYPE_CHECKING, Type + +from uvicorn.supervisors.basereload import BaseReload +from uvicorn.supervisors.multiprocess import Multiprocess + +if TYPE_CHECKING: + ChangeReload: Type[BaseReload] +else: + try: + from uvicorn.supervisors.watchfilesreload import ( + WatchFilesReload as ChangeReload, + ) + except ImportError: # pragma: no cover + try: + from uvicorn.supervisors.watchgodreload import ( + WatchGodReload as ChangeReload, + ) + except ImportError: + from uvicorn.supervisors.statreload import StatReload as ChangeReload + +__all__ = ["Multiprocess", "ChangeReload"] diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/supervisors/basereload.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/supervisors/basereload.py new file mode 100644 index 0000000..0c1dc25 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/supervisors/basereload.py @@ -0,0 +1,125 @@ +import logging +import os +import signal +import sys +import threading +from pathlib import Path +from socket import socket +from types import FrameType +from typing import Callable, Iterator, List, Optional + +import click + +from uvicorn._subprocess import get_subprocess +from uvicorn.config import Config + +HANDLED_SIGNALS = ( + signal.SIGINT, # Unix signal 2. Sent by Ctrl+C. + signal.SIGTERM, # Unix signal 15. Sent by `kill `. +) + +logger = logging.getLogger("uvicorn.error") + + +class BaseReload: + def __init__( + self, + config: Config, + target: Callable[[Optional[List[socket]]], None], + sockets: List[socket], + ) -> None: + self.config = config + self.target = target + self.sockets = sockets + self.should_exit = threading.Event() + self.pid = os.getpid() + self.is_restarting = False + self.reloader_name: Optional[str] = None + + def signal_handler(self, sig: int, frame: Optional[FrameType]) -> None: + """ + A signal handler that is registered with the parent process. + """ + if sys.platform == "win32" and self.is_restarting: + self.is_restarting = False # pragma: py-not-win32 + else: + self.should_exit.set() # pragma: py-win32 + + def run(self) -> None: + self.startup() + for changes in self: + if changes: + logger.warning( + "%s detected changes in %s. Reloading...", + self.reloader_name, + ", ".join(map(_display_path, changes)), + ) + self.restart() + + self.shutdown() + + def pause(self) -> None: + if self.should_exit.wait(self.config.reload_delay): + raise StopIteration() + + def __iter__(self) -> Iterator[Optional[List[Path]]]: + return self + + def __next__(self) -> Optional[List[Path]]: + return self.should_restart() + + def startup(self) -> None: + message = f"Started reloader process [{self.pid}] using {self.reloader_name}" + color_message = "Started reloader process [{}] using {}".format( + click.style(str(self.pid), fg="cyan", bold=True), + click.style(str(self.reloader_name), fg="cyan", bold=True), + ) + logger.info(message, extra={"color_message": color_message}) + + for sig in HANDLED_SIGNALS: + signal.signal(sig, self.signal_handler) + + self.process = get_subprocess( + config=self.config, target=self.target, sockets=self.sockets + ) + self.process.start() + + def restart(self) -> None: + if sys.platform == "win32": # pragma: py-not-win32 + self.is_restarting = True + assert self.process.pid is not None + os.kill(self.process.pid, signal.CTRL_C_EVENT) + else: # pragma: py-win32 + self.process.terminate() + self.process.join() + + self.process = get_subprocess( + config=self.config, target=self.target, sockets=self.sockets + ) + self.process.start() + + def shutdown(self) -> None: + if sys.platform == "win32": + self.should_exit.set() # pragma: py-not-win32 + else: + self.process.terminate() # pragma: py-win32 + self.process.join() + + for sock in self.sockets: + sock.close() + + message = "Stopping reloader process [{}]".format(str(self.pid)) + color_message = "Stopping reloader process [{}]".format( + click.style(str(self.pid), fg="cyan", bold=True) + ) + logger.info(message, extra={"color_message": color_message}) + + def should_restart(self) -> Optional[List[Path]]: + raise NotImplementedError("Reload strategies should override should_restart()") + + +def _display_path(path: Path) -> str: + try: + return f"'{path.relative_to(Path.cwd())}'" + except ValueError: + return f"'{path}'" diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/supervisors/multiprocess.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/supervisors/multiprocess.py new file mode 100644 index 0000000..87ce91f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/supervisors/multiprocess.py @@ -0,0 +1,74 @@ +import logging +import os +import signal +import threading +from multiprocessing.context import SpawnProcess +from socket import socket +from types import FrameType +from typing import Callable, List, Optional + +import click + +from uvicorn._subprocess import get_subprocess +from uvicorn.config import Config + +HANDLED_SIGNALS = ( + signal.SIGINT, # Unix signal 2. Sent by Ctrl+C. + signal.SIGTERM, # Unix signal 15. Sent by `kill `. +) + +logger = logging.getLogger("uvicorn.error") + + +class Multiprocess: + def __init__( + self, + config: Config, + target: Callable[[Optional[List[socket]]], None], + sockets: List[socket], + ) -> None: + self.config = config + self.target = target + self.sockets = sockets + self.processes: List[SpawnProcess] = [] + self.should_exit = threading.Event() + self.pid = os.getpid() + + def signal_handler(self, sig: int, frame: Optional[FrameType]) -> None: + """ + A signal handler that is registered with the parent process. + """ + self.should_exit.set() + + def run(self) -> None: + self.startup() + self.should_exit.wait() + self.shutdown() + + def startup(self) -> None: + message = "Started parent process [{}]".format(str(self.pid)) + color_message = "Started parent process [{}]".format( + click.style(str(self.pid), fg="cyan", bold=True) + ) + logger.info(message, extra={"color_message": color_message}) + + for sig in HANDLED_SIGNALS: + signal.signal(sig, self.signal_handler) + + for _idx in range(self.config.workers): + process = get_subprocess( + config=self.config, target=self.target, sockets=self.sockets + ) + process.start() + self.processes.append(process) + + def shutdown(self) -> None: + for process in self.processes: + process.terminate() + process.join() + + message = "Stopping parent process [{}]".format(str(self.pid)) + color_message = "Stopping parent process [{}]".format( + click.style(str(self.pid), fg="cyan", bold=True) + ) + logger.info(message, extra={"color_message": color_message}) diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/supervisors/statreload.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/supervisors/statreload.py new file mode 100644 index 0000000..7cbcce3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/supervisors/statreload.py @@ -0,0 +1,53 @@ +import logging +from pathlib import Path +from socket import socket +from typing import Callable, Dict, Iterator, List, Optional + +from uvicorn.config import Config +from uvicorn.supervisors.basereload import BaseReload + +logger = logging.getLogger("uvicorn.error") + + +class StatReload(BaseReload): + def __init__( + self, + config: Config, + target: Callable[[Optional[List[socket]]], None], + sockets: List[socket], + ) -> None: + super().__init__(config, target, sockets) + self.reloader_name = "StatReload" + self.mtimes: Dict[Path, float] = {} + + if config.reload_excludes or config.reload_includes: + logger.warning( + "--reload-include and --reload-exclude have no effect unless " + "watchfiles is installed." + ) + + def should_restart(self) -> Optional[List[Path]]: + self.pause() + + for file in self.iter_py_files(): + try: + mtime = file.stat().st_mtime + except OSError: # pragma: nocover + continue + + old_time = self.mtimes.get(file) + if old_time is None: + self.mtimes[file] = mtime + continue + elif mtime > old_time: + return [file] + return None + + def restart(self) -> None: + self.mtimes = {} + return super().restart() + + def iter_py_files(self) -> Iterator[Path]: + for reload_dir in self.config.reload_dirs: + for path in list(reload_dir.rglob("*.py")): + yield path.resolve() diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/supervisors/watchfilesreload.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/supervisors/watchfilesreload.py new file mode 100644 index 0000000..1863683 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/supervisors/watchfilesreload.py @@ -0,0 +1,91 @@ +from pathlib import Path +from socket import socket +from typing import Callable, List, Optional + +from watchfiles import watch + +from uvicorn.config import Config +from uvicorn.supervisors.basereload import BaseReload + + +class FileFilter: + def __init__(self, config: Config): + default_includes = ["*.py"] + self.includes = [ + default + for default in default_includes + if default not in config.reload_excludes + ] + self.includes.extend(config.reload_includes) + self.includes = list(set(self.includes)) + + default_excludes = [".*", ".py[cod]", ".sw.*", "~*"] + self.excludes = [ + default + for default in default_excludes + if default not in config.reload_includes + ] + self.exclude_dirs = [] + for e in config.reload_excludes: + p = Path(e) + try: + is_dir = p.is_dir() + except OSError: # pragma: no cover + # gets raised on Windows for values like "*.py" + is_dir = False + + if is_dir: + self.exclude_dirs.append(p) + else: + self.excludes.append(e) + self.excludes = list(set(self.excludes)) + + def __call__(self, path: Path) -> bool: + for include_pattern in self.includes: + if path.match(include_pattern): + for exclude_dir in self.exclude_dirs: + if exclude_dir in path.parents: + return False + + for exclude_pattern in self.excludes: + if path.match(exclude_pattern): + return False + + return True + return False + + +class WatchFilesReload(BaseReload): + def __init__( + self, + config: Config, + target: Callable[[Optional[List[socket]]], None], + sockets: List[socket], + ) -> None: + super().__init__(config, target, sockets) + self.reloader_name = "WatchFiles" + self.reload_dirs = [] + for directory in config.reload_dirs: + if Path.cwd() not in directory.parents: + self.reload_dirs.append(directory) + if Path.cwd() not in self.reload_dirs: + self.reload_dirs.append(Path.cwd()) + + self.watch_filter = FileFilter(config) + self.watcher = watch( + *self.reload_dirs, + watch_filter=None, + stop_event=self.should_exit, + # using yield_on_timeout here mostly to make sure tests don't + # hang forever, won't affect the class's behavior + yield_on_timeout=True, + ) + + def should_restart(self) -> Optional[List[Path]]: + self.pause() + + changes = next(self.watcher) + if changes: + unique_paths = {Path(c[1]) for c in changes} + return [p for p in unique_paths if self.watch_filter(p)] + return None diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/supervisors/watchgodreload.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/supervisors/watchgodreload.py new file mode 100644 index 0000000..d8bceac --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/supervisors/watchgodreload.py @@ -0,0 +1,158 @@ +import logging +import warnings +from pathlib import Path +from socket import socket +from typing import TYPE_CHECKING, Callable, Dict, List, Optional + +from watchgod import DefaultWatcher + +from uvicorn.config import Config +from uvicorn.supervisors.basereload import BaseReload + +if TYPE_CHECKING: + import os + + DirEntry = os.DirEntry[str] + +logger = logging.getLogger("uvicorn.error") + + +class CustomWatcher(DefaultWatcher): + def __init__(self, root_path: Path, config: Config): + default_includes = ["*.py"] + self.includes = [ + default + for default in default_includes + if default not in config.reload_excludes + ] + self.includes.extend(config.reload_includes) + self.includes = list(set(self.includes)) + + default_excludes = [".*", ".py[cod]", ".sw.*", "~*"] + self.excludes = [ + default + for default in default_excludes + if default not in config.reload_includes + ] + self.excludes.extend(config.reload_excludes) + self.excludes = list(set(self.excludes)) + + self.watched_dirs: Dict[str, bool] = {} + self.watched_files: Dict[str, bool] = {} + self.dirs_includes = set(config.reload_dirs) + self.dirs_excludes = set(config.reload_dirs_excludes) + self.resolved_root = root_path + super().__init__(str(root_path)) + + def should_watch_file(self, entry: "DirEntry") -> bool: + cached_result = self.watched_files.get(entry.path) + if cached_result is not None: + return cached_result + + entry_path = Path(entry) + + # cwd is not verified through should_watch_dir, so we need to verify here + if entry_path.parent == Path.cwd() and Path.cwd() not in self.dirs_includes: + self.watched_files[entry.path] = False + return False + for include_pattern in self.includes: + if entry_path.match(include_pattern): + for exclude_pattern in self.excludes: + if entry_path.match(exclude_pattern): + self.watched_files[entry.path] = False + return False + self.watched_files[entry.path] = True + return True + self.watched_files[entry.path] = False + return False + + def should_watch_dir(self, entry: "DirEntry") -> bool: + cached_result = self.watched_dirs.get(entry.path) + if cached_result is not None: + return cached_result + + entry_path = Path(entry) + + if entry_path in self.dirs_excludes: + self.watched_dirs[entry.path] = False + return False + + for exclude_pattern in self.excludes: + if entry_path.match(exclude_pattern): + is_watched = False + if entry_path in self.dirs_includes: + is_watched = True + + for directory in self.dirs_includes: + if directory in entry_path.parents: + is_watched = True + + if is_watched: + logger.debug( + "WatchGodReload detected a new excluded dir '%s' in '%s'; " + "Adding to exclude list.", + entry_path.relative_to(self.resolved_root), + str(self.resolved_root), + ) + self.watched_dirs[entry.path] = False + self.dirs_excludes.add(entry_path) + return False + + if entry_path in self.dirs_includes: + self.watched_dirs[entry.path] = True + return True + + for directory in self.dirs_includes: + if directory in entry_path.parents: + self.watched_dirs[entry.path] = True + return True + + for include_pattern in self.includes: + if entry_path.match(include_pattern): + logger.info( + "WatchGodReload detected a new reload dir '%s' in '%s'; " + "Adding to watch list.", + str(entry_path.relative_to(self.resolved_root)), + str(self.resolved_root), + ) + self.dirs_includes.add(entry_path) + self.watched_dirs[entry.path] = True + return True + + self.watched_dirs[entry.path] = False + return False + + +class WatchGodReload(BaseReload): + def __init__( + self, + config: Config, + target: Callable[[Optional[List[socket]]], None], + sockets: List[socket], + ) -> None: + warnings.warn( + '"watchgod" is deprecated, you should switch ' + "to watchfiles (`pip install watchfiles`).", + DeprecationWarning, + ) + super().__init__(config, target, sockets) + self.reloader_name = "WatchGod" + self.watchers = [] + reload_dirs = [] + for directory in config.reload_dirs: + if Path.cwd() not in directory.parents: + reload_dirs.append(directory) + if Path.cwd() not in reload_dirs: + reload_dirs.append(Path.cwd()) + for w in reload_dirs: + self.watchers.append(CustomWatcher(w.resolve(), self.config)) + + def should_restart(self) -> Optional[List[Path]]: + self.pause() + + for watcher in self.watchers: + change = watcher.check() + if change != set(): + return list({Path(c[1]) for c in change}) + + return None diff --git a/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/workers.py b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/workers.py new file mode 100644 index 0000000..0d6b49b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi-shared/.pypackages/uvicorn/workers.py @@ -0,0 +1,105 @@ +import asyncio +import logging +import signal +import sys +from typing import Any, Dict + +from gunicorn.arbiter import Arbiter +from gunicorn.workers.base import Worker + +from uvicorn.config import Config +from uvicorn.main import Server + + +class UvicornWorker(Worker): + """ + A worker class for Gunicorn that interfaces with an ASGI consumer callable, + rather than a WSGI callable. + """ + + CONFIG_KWARGS: Dict[str, Any] = {"loop": "auto", "http": "auto"} + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super(UvicornWorker, self).__init__(*args, **kwargs) + + logger = logging.getLogger("uvicorn.error") + logger.handlers = self.log.error_log.handlers + logger.setLevel(self.log.error_log.level) + logger.propagate = False + + logger = logging.getLogger("uvicorn.access") + logger.handlers = self.log.access_log.handlers + logger.setLevel(self.log.access_log.level) + logger.propagate = False + + config_kwargs: dict = { + "app": None, + "log_config": None, + "timeout_keep_alive": self.cfg.keepalive, + "timeout_notify": self.timeout, + "callback_notify": self.callback_notify, + "limit_max_requests": self.max_requests, + "forwarded_allow_ips": self.cfg.forwarded_allow_ips, + } + + if self.cfg.is_ssl: + ssl_kwargs = { + "ssl_keyfile": self.cfg.ssl_options.get("keyfile"), + "ssl_certfile": self.cfg.ssl_options.get("certfile"), + "ssl_keyfile_password": self.cfg.ssl_options.get("password"), + "ssl_version": self.cfg.ssl_options.get("ssl_version"), + "ssl_cert_reqs": self.cfg.ssl_options.get("cert_reqs"), + "ssl_ca_certs": self.cfg.ssl_options.get("ca_certs"), + "ssl_ciphers": self.cfg.ssl_options.get("ciphers"), + } + config_kwargs.update(ssl_kwargs) + + if self.cfg.settings["backlog"].value: + config_kwargs["backlog"] = self.cfg.settings["backlog"].value + + config_kwargs.update(self.CONFIG_KWARGS) + + self.config = Config(**config_kwargs) + + def init_process(self) -> None: + self.config.setup_event_loop() + super(UvicornWorker, self).init_process() + + def init_signals(self) -> None: + # Reset signals so Gunicorn doesn't swallow subprocess return codes + # other signals are set up by Server.install_signal_handlers() + # See: https://github.com/encode/uvicorn/issues/894 + for s in self.SIGNALS: + signal.signal(s, signal.SIG_DFL) + + signal.signal(signal.SIGUSR1, self.handle_usr1) + # Don't let SIGUSR1 disturb active requests by interrupting system calls + signal.siginterrupt(signal.SIGUSR1, False) + + def _install_sigquit_handler(self) -> None: + """Install a SIGQUIT handler on workers. + + - https://github.com/encode/uvicorn/issues/1116 + - https://github.com/benoitc/gunicorn/issues/2604 + """ + + loop = asyncio.get_running_loop() + loop.add_signal_handler(signal.SIGQUIT, self.handle_exit, signal.SIGQUIT, None) + + async def _serve(self) -> None: + self.config.app = self.wsgi + server = Server(config=self.config) + self._install_sigquit_handler() + await server.serve(sockets=self.sockets) + if not server.started: + sys.exit(Arbiter.WORKER_BOOT_ERROR) + + def run(self) -> None: + return asyncio.run(self._serve()) + + async def callback_notify(self) -> None: + self.notify() + + +class UvicornH11Worker(UvicornWorker): + CONFIG_KWARGS = {"loop": "asyncio", "http": "h11"} diff --git a/app/src/main/assets/sample_projects/python-fastapi/main.py b/app/src/main/assets/sample_projects/python-fastapi/main.py new file mode 100644 index 0000000..43a73ff --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi/main.py @@ -0,0 +1,181 @@ + +""" +FastAPI API Monitor — 精美的 API 监控仪表盘 +展示 FastAPI 的高性能异步能力,包含交互式 API 文档 +""" +import os +import random +import time +from datetime import datetime +from fastapi import FastAPI +from fastapi.responses import HTMLResponse, JSONResponse +from pydantic import BaseModel +from typing import List, Optional + +app = FastAPI(title="API Monitor", version="2.0.0") + +class Book(BaseModel): + id: int + title: str + author: str + price: float + +books_db: List[Book] = [ + Book(id=1, title="Python Crash Course", author="Eric Matthes", price=29.99), + Book(id=2, title="Clean Code", author="Robert C. Martin", price=35.50), + Book(id=3, title="Design Patterns", author="Gang of Four", price=42.00), +] + +start_time = time.time() + +DASHBOARD = """ + + + + +FastAPI Monitor + + + +
    +
    +

    ⚡ FastAPI Monitor

    高性能 API 监控仪表盘

    +
    在线
    +
    +
    +
    0s
    运行时间
    +
    0
    请求数
    +
    <1ms
    平均延迟
    +
    +
    +
    API 端点6 个路由
    +
    GET
    /
    仪表盘首页
    <1ms
    +
    GET
    /api/books
    获取所有书籍
    ~2ms
    +
    GET
    /api/books/{id}
    获取指定书籍
    ~1ms
    +
    POST
    /api/books
    添加新书籍
    ~3ms
    +
    GET
    /api/health
    健康检查
    <1ms
    +
    GET
    /docs
    Swagger 文档
    自动生成
    +
    +
    +
    实时测试🧪 交互
    +
    + + + +
    +
    +
    +
    +
    性能指标📊 实时
    +
    CPU
    0%
    +
    内存
    0%
    +
    磁盘
    0%
    +
    + +
    + + +""" + +@app.get("/", response_class=HTMLResponse) +async def dashboard(): + return DASHBOARD + +@app.get("/api/books", response_model=List[Book]) +async def list_books(): + return books_db + +@app.get("/api/books/{book_id}") +async def get_book(book_id: int): + for b in books_db: + if b.id == book_id: + return b + return JSONResponse({"error": "Book not found"}, status_code=404) + +@app.post("/api/books", response_model=Book) +async def create_book(book: Book): + books_db.append(book) + return book + +@app.get("/api/health") +async def health(): + return { + "status": "healthy", + "uptime_seconds": round(time.time() - start_time, 1), + "framework": "FastAPI", + "books_count": len(books_db), + "timestamp": datetime.now().isoformat() + } diff --git a/app/src/main/assets/sample_projects/python-fastapi/requirements.txt b/app/src/main/assets/sample_projects/python-fastapi/requirements.txt new file mode 100644 index 0000000..244b15d --- /dev/null +++ b/app/src/main/assets/sample_projects/python-fastapi/requirements.txt @@ -0,0 +1,3 @@ +fastapi==0.99.1 +uvicorn==0.23.2 +pydantic==1.10.16 diff --git a/app/src/main/assets/sample_projects/python-flask-ar/app.py b/app/src/main/assets/sample_projects/python-flask-ar/app.py new file mode 100644 index 0000000..55ead53 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-ar/app.py @@ -0,0 +1,168 @@ + +""" +Flask Analytics Dashboard — تطبيق ويب بايثون جميل +لوحة تحليلات حديثة تعرض قدرات Flask +""" +import os +import json +import random +from datetime import datetime +from flask import Flask, render_template_string, jsonify + +app = Flask(__name__) + +def generate_weekly_data(): + days = ['الإثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت', 'الأحد'] + return [{'day': d, 'users': random.randint(180, 420)} for d in days] + +def generate_activities(): + actions = [ + ('اشترى الخطة المميزة', '💎', '#7c3aed'), + ('أكمل أول طلب', '🛒', '#3b82f6'), + ('ترقية إلى المؤسسة', '🚀', '#10b981'), + ('جدد الاشتراك السنوي', '🔄', '#f59e0b'), + ('دعا 3 أعضاء فريق', '👥', '#ec4899'), + ('صدّر تقرير البيانات', '📊', '#06b6d4'), + ] + names = ['أحمد', 'فاطمة', 'محمد', 'سارة', 'عمر', 'نور'] + result = [] + for i in range(6): + action, icon, color = actions[i] + m = random.randint(5, 720) + time_str = f'{m} دقيقة' if m < 60 else f'{m//60} ساعة' + result.append({'name': names[i], 'action': action, 'icon': icon, 'color': color, 'time': time_str}) + return result + +DASHBOARD_HTML = r""" + + + + +Flask Analytics + + + +
    +
    +

    Flask Analytics

    {{ current_date }}

    +
    🐍
    +
    +
    +
    المستخدمون
    👥
    12,847
    ↑ 12.5%
    +
    الإيرادات
    💰
    $128.5K
    ↑ 8.3%
    +
    الطلبات
    📦
    3,421
    ↑ 15.2%
    +
    النمو
    📈
    +24.6%
    ↑ مستقر
    +
    +
    +
    نظرة أسبوعية📊 مباشر
    +
    + {% for day in weekly_data %} +
    {{ day.day }}
    + {% endfor %} +
    +
    +
    +
    النشاط الأخير🔔 اليوم
    + {% for a in activities %} +
    {{ a.icon }}
    {{ a.name }}
    {{ a.action }}
    {{ a.time }}
    + {% endfor %} +
    +
    Flask {{ flask_version }} · Python {{ python_version }} · يعمل
    +
    + + +""" + +@app.route('/') +def index(): + import sys + weekly = generate_weekly_data() + max_u = max(d['users'] for d in weekly) or 1 + for d in weekly: d['users_pct'] = int(d['users'] / max_u * 85) + 15 + flask_ver = '3.0' + try: + import flask as _f; flask_ver = getattr(_f, '__version__', '3.0') + except: pass + return render_template_string(DASHBOARD_HTML, weekly_data=weekly, activities=generate_activities(), + current_date=datetime.now().strftime('%Y/%m/%d'), flask_version=flask_ver, python_version=f'{sys.version_info.major}.{sys.version_info.minor}') + +@app.route('/api/stats') +def api_stats(): + return jsonify({'status':'ok','data':{'users':12847,'orders':3421,'revenue':128500,'growth':24.6}}) + +if __name__ == '__main__': + port = int(os.environ.get('PORT', 5000)) + app.run(host='0.0.0.0', port=port) diff --git a/app/src/main/assets/sample_projects/python-flask-ar/requirements.txt b/app/src/main/assets/sample_projects/python-flask-ar/requirements.txt new file mode 100644 index 0000000..dfce325 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-ar/requirements.txt @@ -0,0 +1,2 @@ +flask==3.0.0 +jinja2>=3.1 diff --git a/app/src/main/assets/sample_projects/python-flask-en/app.py b/app/src/main/assets/sample_projects/python-flask-en/app.py new file mode 100644 index 0000000..14409ea --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-en/app.py @@ -0,0 +1,183 @@ + +""" +Flask Analytics Dashboard — Beautiful Python Web App Demo +A modern analytics dashboard showcasing Flask's capabilities +""" +import importlib.metadata +import os +import json +import random +import math +from datetime import datetime, timedelta +from flask import Flask, render_template_string, jsonify, request + +app = Flask(__name__) + +def generate_weekly_data(): + days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] + return [ + {'day': d, 'users': random.randint(180, 420), 'orders': random.randint(30, 95), 'revenue': random.randint(2800, 9500)} + for d in days + ] + +def generate_activities(): + actions = [ + ('Purchased Premium Plan', '💎', '#7c3aed'), + ('Completed first order', '🛒', '#3b82f6'), + ('Upgraded to Enterprise', '🚀', '#10b981'), + ('Renewed annual subscription', '🔄', '#f59e0b'), + ('Invited 3 team members', '👥', '#ec4899'), + ('Exported data report', '📊', '#06b6d4'), + ('Created new project', '📁', '#8b5cf6'), + ('Completed security verification', '🔒', '#10b981'), + ] + names = ['Alex Chen', 'Emily Wang', 'James Lee', 'Sarah Kim', 'Michael Liu', 'Anna Park', 'David Wu', 'Lisa Zhang'] + result = [] + now = datetime.now() + for i in range(8): + action, icon, color = actions[i % len(actions)] + minutes_ago = random.randint(5, 720) + if minutes_ago < 60: + time_str = f'{minutes_ago}m ago' + elif minutes_ago < 1440: + time_str = f'{minutes_ago // 60}h ago' + else: + time_str = f'{minutes_ago // 1440}d ago' + result.append({ + 'name': names[i % len(names)], + 'action': action, + 'icon': icon, + 'color': color, + 'time': time_str, + }) + return result + +DASHBOARD_HTML = r""" + + + + +Flask Analytics + + + +
    +
    +

    Flask Analytics

    {{ current_date }}

    +
    🐍
    +
    +
    +
    Users
    👥
    12,847
    ↑ 12.5%
    +
    Revenue
    💰
    $128.5K
    ↑ 8.3%
    +
    Orders
    📦
    3,421
    ↑ 15.2%
    +
    Growth
    📈
    +24.6%
    ↑ Steady
    +
    +
    +
    Weekly Overview📊 Live
    +
    + {% for day in weekly_data %} +
    {{ day.day }}
    + {% endfor %} +
    +
    +
    +
    Recent Activity🔔 Today
    + {% for a in activities %} +
    {{ a.icon }}
    {{ a.name }}
    {{ a.action }}
    {{ a.time }}
    + {% endfor %} +
    +
    Flask {{ flask_version }} · Python {{ python_version }} · Running
    +
    + + +""" + +@app.route('/') +def index(): + import sys + weekly = generate_weekly_data() + max_u = max(d['users'] for d in weekly) or 1 + for d in weekly: d['users_pct'] = int(d['users'] / max_u * 85) + 15 + flask_ver = '3.0' + try: + flask_ver = importlib.metadata.version('flask') + except: pass + return render_template_string(DASHBOARD_HTML, weekly_data=weekly, activities=generate_activities()[:6], + current_date=datetime.now().strftime('%B %d, %Y'), flask_version=flask_ver, python_version=f'{sys.version_info.major}.{sys.version_info.minor}') + +@app.route('/api/stats') +def api_stats(): + return jsonify({'status':'ok','data':{'users':12847,'orders':3421,'revenue':128500,'growth':24.6,'weekly':generate_weekly_data()}}) + +if __name__ == '__main__': + port = int(os.environ.get('PORT', 5000)) + app.run(host='0.0.0.0', port=port) diff --git a/app/src/main/assets/sample_projects/python-flask-en/requirements.txt b/app/src/main/assets/sample_projects/python-flask-en/requirements.txt new file mode 100644 index 0000000..dfce325 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-en/requirements.txt @@ -0,0 +1,2 @@ +flask==3.0.0 +jinja2>=3.1 diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/blinker/__init__.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/blinker/__init__.py new file mode 100644 index 0000000..1772fa4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/blinker/__init__.py @@ -0,0 +1,17 @@ +from __future__ import annotations + +from .base import ANY +from .base import default_namespace +from .base import NamedSignal +from .base import Namespace +from .base import Signal +from .base import signal + +__all__ = [ + "ANY", + "default_namespace", + "NamedSignal", + "Namespace", + "Signal", + "signal", +] diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/blinker/_utilities.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/blinker/_utilities.py new file mode 100644 index 0000000..000c902 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/blinker/_utilities.py @@ -0,0 +1,64 @@ +from __future__ import annotations + +import collections.abc as c +import inspect +import typing as t +from weakref import ref +from weakref import WeakMethod + +T = t.TypeVar("T") + + +class Symbol: + """A constant symbol, nicer than ``object()``. Repeated calls return the + same instance. + + >>> Symbol('foo') is Symbol('foo') + True + >>> Symbol('foo') + foo + """ + + symbols: t.ClassVar[dict[str, Symbol]] = {} + + def __new__(cls, name: str) -> Symbol: + if name in cls.symbols: + return cls.symbols[name] + + obj = super().__new__(cls) + cls.symbols[name] = obj + return obj + + def __init__(self, name: str) -> None: + self.name = name + + def __repr__(self) -> str: + return self.name + + def __getnewargs__(self) -> tuple[t.Any, ...]: + return (self.name,) + + +def make_id(obj: object) -> c.Hashable: + """Get a stable identifier for a receiver or sender, to be used as a dict + key or in a set. + """ + if inspect.ismethod(obj): + # The id of a bound method is not stable, but the id of the unbound + # function and instance are. + return id(obj.__func__), id(obj.__self__) + + if isinstance(obj, (str, int)): + # Instances with the same value always compare equal and have the same + # hash, even if the id may change. + return obj + + # Assume other types are not hashable but will always be the same instance. + return id(obj) + + +def make_ref(obj: T, callback: c.Callable[[ref[T]], None] | None = None) -> ref[T]: + if inspect.ismethod(obj): + return WeakMethod(obj, callback) # type: ignore[arg-type, return-value] + + return ref(obj, callback) diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/blinker/base.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/blinker/base.py new file mode 100644 index 0000000..d051b94 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/blinker/base.py @@ -0,0 +1,512 @@ +from __future__ import annotations + +import collections.abc as c +import sys +import typing as t +import weakref +from collections import defaultdict +from contextlib import contextmanager +from functools import cached_property +from inspect import iscoroutinefunction + +from ._utilities import make_id +from ._utilities import make_ref +from ._utilities import Symbol + +F = t.TypeVar("F", bound=c.Callable[..., t.Any]) + +ANY = Symbol("ANY") +"""Symbol for "any sender".""" + +ANY_ID = 0 + + +class Signal: + """A notification emitter. + + :param doc: The docstring for the signal. + """ + + ANY = ANY + """An alias for the :data:`~blinker.ANY` sender symbol.""" + + set_class: type[set[t.Any]] = set + """The set class to use for tracking connected receivers and senders. + Python's ``set`` is unordered. If receivers must be dispatched in the order + they were connected, an ordered set implementation can be used. + + .. versionadded:: 1.7 + """ + + @cached_property + def receiver_connected(self) -> Signal: + """Emitted at the end of each :meth:`connect` call. + + The signal sender is the signal instance, and the :meth:`connect` + arguments are passed through: ``receiver``, ``sender``, and ``weak``. + + .. versionadded:: 1.2 + """ + return Signal(doc="Emitted after a receiver connects.") + + @cached_property + def receiver_disconnected(self) -> Signal: + """Emitted at the end of each :meth:`disconnect` call. + + The sender is the signal instance, and the :meth:`disconnect` arguments + are passed through: ``receiver`` and ``sender``. + + This signal is emitted **only** when :meth:`disconnect` is called + explicitly. This signal cannot be emitted by an automatic disconnect + when a weakly referenced receiver or sender goes out of scope, as the + instance is no longer be available to be used as the sender for this + signal. + + An alternative approach is available by subscribing to + :attr:`receiver_connected` and setting up a custom weakref cleanup + callback on weak receivers and senders. + + .. versionadded:: 1.2 + """ + return Signal(doc="Emitted after a receiver disconnects.") + + def __init__(self, doc: str | None = None) -> None: + if doc: + self.__doc__ = doc + + self.receivers: dict[ + t.Any, weakref.ref[c.Callable[..., t.Any]] | c.Callable[..., t.Any] + ] = {} + """The map of connected receivers. Useful to quickly check if any + receivers are connected to the signal: ``if s.receivers:``. The + structure and data is not part of the public API, but checking its + boolean value is. + """ + + self.is_muted: bool = False + self._by_receiver: dict[t.Any, set[t.Any]] = defaultdict(self.set_class) + self._by_sender: dict[t.Any, set[t.Any]] = defaultdict(self.set_class) + self._weak_senders: dict[t.Any, weakref.ref[t.Any]] = {} + + def connect(self, receiver: F, sender: t.Any = ANY, weak: bool = True) -> F: + """Connect ``receiver`` to be called when the signal is sent by + ``sender``. + + :param receiver: The callable to call when :meth:`send` is called with + the given ``sender``, passing ``sender`` as a positional argument + along with any extra keyword arguments. + :param sender: Any object or :data:`ANY`. ``receiver`` will only be + called when :meth:`send` is called with this sender. If ``ANY``, the + receiver will be called for any sender. A receiver may be connected + to multiple senders by calling :meth:`connect` multiple times. + :param weak: Track the receiver with a :mod:`weakref`. The receiver will + be automatically disconnected when it is garbage collected. When + connecting a receiver defined within a function, set to ``False``, + otherwise it will be disconnected when the function scope ends. + """ + receiver_id = make_id(receiver) + sender_id = ANY_ID if sender is ANY else make_id(sender) + + if weak: + self.receivers[receiver_id] = make_ref( + receiver, self._make_cleanup_receiver(receiver_id) + ) + else: + self.receivers[receiver_id] = receiver + + self._by_sender[sender_id].add(receiver_id) + self._by_receiver[receiver_id].add(sender_id) + + if sender is not ANY and sender_id not in self._weak_senders: + # store a cleanup for weakref-able senders + try: + self._weak_senders[sender_id] = make_ref( + sender, self._make_cleanup_sender(sender_id) + ) + except TypeError: + pass + + if "receiver_connected" in self.__dict__ and self.receiver_connected.receivers: + try: + self.receiver_connected.send( + self, receiver=receiver, sender=sender, weak=weak + ) + except TypeError: + # TODO no explanation or test for this + self.disconnect(receiver, sender) + raise + + return receiver + + def connect_via(self, sender: t.Any, weak: bool = False) -> c.Callable[[F], F]: + """Connect the decorated function to be called when the signal is sent + by ``sender``. + + The decorated function will be called when :meth:`send` is called with + the given ``sender``, passing ``sender`` as a positional argument along + with any extra keyword arguments. + + :param sender: Any object or :data:`ANY`. ``receiver`` will only be + called when :meth:`send` is called with this sender. If ``ANY``, the + receiver will be called for any sender. A receiver may be connected + to multiple senders by calling :meth:`connect` multiple times. + :param weak: Track the receiver with a :mod:`weakref`. The receiver will + be automatically disconnected when it is garbage collected. When + connecting a receiver defined within a function, set to ``False``, + otherwise it will be disconnected when the function scope ends.= + + .. versionadded:: 1.1 + """ + + def decorator(fn: F) -> F: + self.connect(fn, sender, weak) + return fn + + return decorator + + @contextmanager + def connected_to( + self, receiver: c.Callable[..., t.Any], sender: t.Any = ANY + ) -> c.Generator[None, None, None]: + """A context manager that temporarily connects ``receiver`` to the + signal while a ``with`` block executes. When the block exits, the + receiver is disconnected. Useful for tests. + + :param receiver: The callable to call when :meth:`send` is called with + the given ``sender``, passing ``sender`` as a positional argument + along with any extra keyword arguments. + :param sender: Any object or :data:`ANY`. ``receiver`` will only be + called when :meth:`send` is called with this sender. If ``ANY``, the + receiver will be called for any sender. + + .. versionadded:: 1.1 + """ + self.connect(receiver, sender=sender, weak=False) + + try: + yield None + finally: + self.disconnect(receiver) + + @contextmanager + def muted(self) -> c.Generator[None, None, None]: + """A context manager that temporarily disables the signal. No receivers + will be called if the signal is sent, until the ``with`` block exits. + Useful for tests. + """ + self.is_muted = True + + try: + yield None + finally: + self.is_muted = False + + def send( + self, + sender: t.Any | None = None, + /, + *, + _async_wrapper: c.Callable[ + [c.Callable[..., c.Coroutine[t.Any, t.Any, t.Any]]], c.Callable[..., t.Any] + ] + | None = None, + **kwargs: t.Any, + ) -> list[tuple[c.Callable[..., t.Any], t.Any]]: + """Call all receivers that are connected to the given ``sender`` + or :data:`ANY`. Each receiver is called with ``sender`` as a positional + argument along with any extra keyword arguments. Return a list of + ``(receiver, return value)`` tuples. + + The order receivers are called is undefined, but can be influenced by + setting :attr:`set_class`. + + If a receiver raises an exception, that exception will propagate up. + This makes debugging straightforward, with an assumption that correctly + implemented receivers will not raise. + + :param sender: Call receivers connected to this sender, in addition to + those connected to :data:`ANY`. + :param _async_wrapper: Will be called on any receivers that are async + coroutines to turn them into sync callables. For example, could run + the receiver with an event loop. + :param kwargs: Extra keyword arguments to pass to each receiver. + + .. versionchanged:: 1.7 + Added the ``_async_wrapper`` argument. + """ + if self.is_muted: + return [] + + results = [] + + for receiver in self.receivers_for(sender): + if iscoroutinefunction(receiver): + if _async_wrapper is None: + raise RuntimeError("Cannot send to a coroutine function.") + + result = _async_wrapper(receiver)(sender, **kwargs) + else: + result = receiver(sender, **kwargs) + + results.append((receiver, result)) + + return results + + async def send_async( + self, + sender: t.Any | None = None, + /, + *, + _sync_wrapper: c.Callable[ + [c.Callable[..., t.Any]], c.Callable[..., c.Coroutine[t.Any, t.Any, t.Any]] + ] + | None = None, + **kwargs: t.Any, + ) -> list[tuple[c.Callable[..., t.Any], t.Any]]: + """Await all receivers that are connected to the given ``sender`` + or :data:`ANY`. Each receiver is called with ``sender`` as a positional + argument along with any extra keyword arguments. Return a list of + ``(receiver, return value)`` tuples. + + The order receivers are called is undefined, but can be influenced by + setting :attr:`set_class`. + + If a receiver raises an exception, that exception will propagate up. + This makes debugging straightforward, with an assumption that correctly + implemented receivers will not raise. + + :param sender: Call receivers connected to this sender, in addition to + those connected to :data:`ANY`. + :param _sync_wrapper: Will be called on any receivers that are sync + callables to turn them into async coroutines. For example, + could call the receiver in a thread. + :param kwargs: Extra keyword arguments to pass to each receiver. + + .. versionadded:: 1.7 + """ + if self.is_muted: + return [] + + results = [] + + for receiver in self.receivers_for(sender): + if not iscoroutinefunction(receiver): + if _sync_wrapper is None: + raise RuntimeError("Cannot send to a non-coroutine function.") + + result = await _sync_wrapper(receiver)(sender, **kwargs) + else: + result = await receiver(sender, **kwargs) + + results.append((receiver, result)) + + return results + + def has_receivers_for(self, sender: t.Any) -> bool: + """Check if there is at least one receiver that will be called with the + given ``sender``. A receiver connected to :data:`ANY` will always be + called, regardless of sender. Does not check if weakly referenced + receivers are still live. See :meth:`receivers_for` for a stronger + search. + + :param sender: Check for receivers connected to this sender, in addition + to those connected to :data:`ANY`. + """ + if not self.receivers: + return False + + if self._by_sender[ANY_ID]: + return True + + if sender is ANY: + return False + + return make_id(sender) in self._by_sender + + def receivers_for( + self, sender: t.Any + ) -> c.Generator[c.Callable[..., t.Any], None, None]: + """Yield each receiver to be called for ``sender``, in addition to those + to be called for :data:`ANY`. Weakly referenced receivers that are not + live will be disconnected and skipped. + + :param sender: Yield receivers connected to this sender, in addition + to those connected to :data:`ANY`. + """ + # TODO: test receivers_for(ANY) + if not self.receivers: + return + + sender_id = make_id(sender) + + if sender_id in self._by_sender: + ids = self._by_sender[ANY_ID] | self._by_sender[sender_id] + else: + ids = self._by_sender[ANY_ID].copy() + + for receiver_id in ids: + receiver = self.receivers.get(receiver_id) + + if receiver is None: + continue + + if isinstance(receiver, weakref.ref): + strong = receiver() + + if strong is None: + self._disconnect(receiver_id, ANY_ID) + continue + + yield strong + else: + yield receiver + + def disconnect(self, receiver: c.Callable[..., t.Any], sender: t.Any = ANY) -> None: + """Disconnect ``receiver`` from being called when the signal is sent by + ``sender``. + + :param receiver: A connected receiver callable. + :param sender: Disconnect from only this sender. By default, disconnect + from all senders. + """ + sender_id: c.Hashable + + if sender is ANY: + sender_id = ANY_ID + else: + sender_id = make_id(sender) + + receiver_id = make_id(receiver) + self._disconnect(receiver_id, sender_id) + + if ( + "receiver_disconnected" in self.__dict__ + and self.receiver_disconnected.receivers + ): + self.receiver_disconnected.send(self, receiver=receiver, sender=sender) + + def _disconnect(self, receiver_id: c.Hashable, sender_id: c.Hashable) -> None: + if sender_id == ANY_ID: + if self._by_receiver.pop(receiver_id, None) is not None: + for bucket in self._by_sender.values(): + bucket.discard(receiver_id) + + self.receivers.pop(receiver_id, None) + else: + self._by_sender[sender_id].discard(receiver_id) + self._by_receiver[receiver_id].discard(sender_id) + + def _make_cleanup_receiver( + self, receiver_id: c.Hashable + ) -> c.Callable[[weakref.ref[c.Callable[..., t.Any]]], None]: + """Create a callback function to disconnect a weakly referenced + receiver when it is garbage collected. + """ + + def cleanup(ref: weakref.ref[c.Callable[..., t.Any]]) -> None: + # If the interpreter is shutting down, disconnecting can result in a + # weird ignored exception. Don't call it in that case. + if not sys.is_finalizing(): + self._disconnect(receiver_id, ANY_ID) + + return cleanup + + def _make_cleanup_sender( + self, sender_id: c.Hashable + ) -> c.Callable[[weakref.ref[t.Any]], None]: + """Create a callback function to disconnect all receivers for a weakly + referenced sender when it is garbage collected. + """ + assert sender_id != ANY_ID + + def cleanup(ref: weakref.ref[t.Any]) -> None: + self._weak_senders.pop(sender_id, None) + + for receiver_id in self._by_sender.pop(sender_id, ()): + self._by_receiver[receiver_id].discard(sender_id) + + return cleanup + + def _cleanup_bookkeeping(self) -> None: + """Prune unused sender/receiver bookkeeping. Not threadsafe. + + Connecting & disconnecting leaves behind a small amount of bookkeeping + data. Typical workloads using Blinker, for example in most web apps, + Flask, CLI scripts, etc., are not adversely affected by this + bookkeeping. + + With a long-running process performing dynamic signal routing with high + volume, e.g. connecting to function closures, senders are all unique + object instances. Doing all of this over and over may cause memory usage + to grow due to extraneous bookkeeping. (An empty ``set`` for each stale + sender/receiver pair.) + + This method will prune that bookkeeping away, with the caveat that such + pruning is not threadsafe. The risk is that cleanup of a fully + disconnected receiver/sender pair occurs while another thread is + connecting that same pair. If you are in the highly dynamic, unique + receiver/sender situation that has lead you to this method, that failure + mode is perhaps not a big deal for you. + """ + for mapping in (self._by_sender, self._by_receiver): + for ident, bucket in list(mapping.items()): + if not bucket: + mapping.pop(ident, None) + + def _clear_state(self) -> None: + """Disconnect all receivers and senders. Useful for tests.""" + self._weak_senders.clear() + self.receivers.clear() + self._by_sender.clear() + self._by_receiver.clear() + + +class NamedSignal(Signal): + """A named generic notification emitter. The name is not used by the signal + itself, but matches the key in the :class:`Namespace` that it belongs to. + + :param name: The name of the signal within the namespace. + :param doc: The docstring for the signal. + """ + + def __init__(self, name: str, doc: str | None = None) -> None: + super().__init__(doc) + + #: The name of this signal. + self.name: str = name + + def __repr__(self) -> str: + base = super().__repr__() + return f"{base[:-1]}; {self.name!r}>" # noqa: E702 + + +class Namespace(dict[str, NamedSignal]): + """A dict mapping names to signals.""" + + def signal(self, name: str, doc: str | None = None) -> NamedSignal: + """Return the :class:`NamedSignal` for the given ``name``, creating it + if required. Repeated calls with the same name return the same signal. + + :param name: The name of the signal. + :param doc: The docstring of the signal. + """ + if name not in self: + self[name] = NamedSignal(name, doc) + + return self[name] + + +class _PNamespaceSignal(t.Protocol): + def __call__(self, name: str, doc: str | None = None) -> NamedSignal: ... + + +default_namespace: Namespace = Namespace() +"""A default :class:`Namespace` for creating named signals. :func:`signal` +creates a :class:`NamedSignal` in this namespace. +""" + +signal: _PNamespaceSignal = default_namespace.signal +"""Return a :class:`NamedSignal` in :data:`default_namespace` with the given +``name``, creating it if required. Repeated calls with the same name return the +same signal. +""" diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/blinker/py.typed b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/blinker/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/__init__.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/__init__.py new file mode 100644 index 0000000..2610d0e --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/__init__.py @@ -0,0 +1,75 @@ +""" +Click is a simple Python module inspired by the stdlib optparse to make +writing command line scripts fun. Unlike other modules, it's based +around a simple API that does not come with too much magic and is +composable. +""" + +from .core import Argument as Argument +from .core import BaseCommand as BaseCommand +from .core import Command as Command +from .core import CommandCollection as CommandCollection +from .core import Context as Context +from .core import Group as Group +from .core import MultiCommand as MultiCommand +from .core import Option as Option +from .core import Parameter as Parameter +from .decorators import argument as argument +from .decorators import command as command +from .decorators import confirmation_option as confirmation_option +from .decorators import group as group +from .decorators import help_option as help_option +from .decorators import HelpOption as HelpOption +from .decorators import make_pass_decorator as make_pass_decorator +from .decorators import option as option +from .decorators import pass_context as pass_context +from .decorators import pass_obj as pass_obj +from .decorators import password_option as password_option +from .decorators import version_option as version_option +from .exceptions import Abort as Abort +from .exceptions import BadArgumentUsage as BadArgumentUsage +from .exceptions import BadOptionUsage as BadOptionUsage +from .exceptions import BadParameter as BadParameter +from .exceptions import ClickException as ClickException +from .exceptions import FileError as FileError +from .exceptions import MissingParameter as MissingParameter +from .exceptions import NoSuchOption as NoSuchOption +from .exceptions import UsageError as UsageError +from .formatting import HelpFormatter as HelpFormatter +from .formatting import wrap_text as wrap_text +from .globals import get_current_context as get_current_context +from .parser import OptionParser as OptionParser +from .termui import clear as clear +from .termui import confirm as confirm +from .termui import echo_via_pager as echo_via_pager +from .termui import edit as edit +from .termui import getchar as getchar +from .termui import launch as launch +from .termui import pause as pause +from .termui import progressbar as progressbar +from .termui import prompt as prompt +from .termui import secho as secho +from .termui import style as style +from .termui import unstyle as unstyle +from .types import BOOL as BOOL +from .types import Choice as Choice +from .types import DateTime as DateTime +from .types import File as File +from .types import FLOAT as FLOAT +from .types import FloatRange as FloatRange +from .types import INT as INT +from .types import IntRange as IntRange +from .types import ParamType as ParamType +from .types import Path as Path +from .types import STRING as STRING +from .types import Tuple as Tuple +from .types import UNPROCESSED as UNPROCESSED +from .types import UUID as UUID +from .utils import echo as echo +from .utils import format_filename as format_filename +from .utils import get_app_dir as get_app_dir +from .utils import get_binary_stream as get_binary_stream +from .utils import get_text_stream as get_text_stream +from .utils import open_file as open_file + +__version__ = "8.1.8" diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/_compat.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/_compat.py new file mode 100644 index 0000000..9153d15 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/_compat.py @@ -0,0 +1,623 @@ +import codecs +import io +import os +import re +import sys +import typing as t +from weakref import WeakKeyDictionary + +CYGWIN = sys.platform.startswith("cygwin") +WIN = sys.platform.startswith("win") +auto_wrap_for_ansi: t.Optional[t.Callable[[t.TextIO], t.TextIO]] = None +_ansi_re = re.compile(r"\033\[[;?0-9]*[a-zA-Z]") + + +def _make_text_stream( + stream: t.BinaryIO, + encoding: t.Optional[str], + errors: t.Optional[str], + force_readable: bool = False, + force_writable: bool = False, +) -> t.TextIO: + if encoding is None: + encoding = get_best_encoding(stream) + if errors is None: + errors = "replace" + return _NonClosingTextIOWrapper( + stream, + encoding, + errors, + line_buffering=True, + force_readable=force_readable, + force_writable=force_writable, + ) + + +def is_ascii_encoding(encoding: str) -> bool: + """Checks if a given encoding is ascii.""" + try: + return codecs.lookup(encoding).name == "ascii" + except LookupError: + return False + + +def get_best_encoding(stream: t.IO[t.Any]) -> str: + """Returns the default stream encoding if not found.""" + rv = getattr(stream, "encoding", None) or sys.getdefaultencoding() + if is_ascii_encoding(rv): + return "utf-8" + return rv + + +class _NonClosingTextIOWrapper(io.TextIOWrapper): + def __init__( + self, + stream: t.BinaryIO, + encoding: t.Optional[str], + errors: t.Optional[str], + force_readable: bool = False, + force_writable: bool = False, + **extra: t.Any, + ) -> None: + self._stream = stream = t.cast( + t.BinaryIO, _FixupStream(stream, force_readable, force_writable) + ) + super().__init__(stream, encoding, errors, **extra) + + def __del__(self) -> None: + try: + self.detach() + except Exception: + pass + + def isatty(self) -> bool: + # https://bitbucket.org/pypy/pypy/issue/1803 + return self._stream.isatty() + + +class _FixupStream: + """The new io interface needs more from streams than streams + traditionally implement. As such, this fix-up code is necessary in + some circumstances. + + The forcing of readable and writable flags are there because some tools + put badly patched objects on sys (one such offender are certain version + of jupyter notebook). + """ + + def __init__( + self, + stream: t.BinaryIO, + force_readable: bool = False, + force_writable: bool = False, + ): + self._stream = stream + self._force_readable = force_readable + self._force_writable = force_writable + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._stream, name) + + def read1(self, size: int) -> bytes: + f = getattr(self._stream, "read1", None) + + if f is not None: + return t.cast(bytes, f(size)) + + return self._stream.read(size) + + def readable(self) -> bool: + if self._force_readable: + return True + x = getattr(self._stream, "readable", None) + if x is not None: + return t.cast(bool, x()) + try: + self._stream.read(0) + except Exception: + return False + return True + + def writable(self) -> bool: + if self._force_writable: + return True + x = getattr(self._stream, "writable", None) + if x is not None: + return t.cast(bool, x()) + try: + self._stream.write("") # type: ignore + except Exception: + try: + self._stream.write(b"") + except Exception: + return False + return True + + def seekable(self) -> bool: + x = getattr(self._stream, "seekable", None) + if x is not None: + return t.cast(bool, x()) + try: + self._stream.seek(self._stream.tell()) + except Exception: + return False + return True + + +def _is_binary_reader(stream: t.IO[t.Any], default: bool = False) -> bool: + try: + return isinstance(stream.read(0), bytes) + except Exception: + return default + # This happens in some cases where the stream was already + # closed. In this case, we assume the default. + + +def _is_binary_writer(stream: t.IO[t.Any], default: bool = False) -> bool: + try: + stream.write(b"") + except Exception: + try: + stream.write("") + return False + except Exception: + pass + return default + return True + + +def _find_binary_reader(stream: t.IO[t.Any]) -> t.Optional[t.BinaryIO]: + # We need to figure out if the given stream is already binary. + # This can happen because the official docs recommend detaching + # the streams to get binary streams. Some code might do this, so + # we need to deal with this case explicitly. + if _is_binary_reader(stream, False): + return t.cast(t.BinaryIO, stream) + + buf = getattr(stream, "buffer", None) + + # Same situation here; this time we assume that the buffer is + # actually binary in case it's closed. + if buf is not None and _is_binary_reader(buf, True): + return t.cast(t.BinaryIO, buf) + + return None + + +def _find_binary_writer(stream: t.IO[t.Any]) -> t.Optional[t.BinaryIO]: + # We need to figure out if the given stream is already binary. + # This can happen because the official docs recommend detaching + # the streams to get binary streams. Some code might do this, so + # we need to deal with this case explicitly. + if _is_binary_writer(stream, False): + return t.cast(t.BinaryIO, stream) + + buf = getattr(stream, "buffer", None) + + # Same situation here; this time we assume that the buffer is + # actually binary in case it's closed. + if buf is not None and _is_binary_writer(buf, True): + return t.cast(t.BinaryIO, buf) + + return None + + +def _stream_is_misconfigured(stream: t.TextIO) -> bool: + """A stream is misconfigured if its encoding is ASCII.""" + # If the stream does not have an encoding set, we assume it's set + # to ASCII. This appears to happen in certain unittest + # environments. It's not quite clear what the correct behavior is + # but this at least will force Click to recover somehow. + return is_ascii_encoding(getattr(stream, "encoding", None) or "ascii") + + +def _is_compat_stream_attr(stream: t.TextIO, attr: str, value: t.Optional[str]) -> bool: + """A stream attribute is compatible if it is equal to the + desired value or the desired value is unset and the attribute + has a value. + """ + stream_value = getattr(stream, attr, None) + return stream_value == value or (value is None and stream_value is not None) + + +def _is_compatible_text_stream( + stream: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str] +) -> bool: + """Check if a stream's encoding and errors attributes are + compatible with the desired values. + """ + return _is_compat_stream_attr( + stream, "encoding", encoding + ) and _is_compat_stream_attr(stream, "errors", errors) + + +def _force_correct_text_stream( + text_stream: t.IO[t.Any], + encoding: t.Optional[str], + errors: t.Optional[str], + is_binary: t.Callable[[t.IO[t.Any], bool], bool], + find_binary: t.Callable[[t.IO[t.Any]], t.Optional[t.BinaryIO]], + force_readable: bool = False, + force_writable: bool = False, +) -> t.TextIO: + if is_binary(text_stream, False): + binary_reader = t.cast(t.BinaryIO, text_stream) + else: + text_stream = t.cast(t.TextIO, text_stream) + # If the stream looks compatible, and won't default to a + # misconfigured ascii encoding, return it as-is. + if _is_compatible_text_stream(text_stream, encoding, errors) and not ( + encoding is None and _stream_is_misconfigured(text_stream) + ): + return text_stream + + # Otherwise, get the underlying binary reader. + possible_binary_reader = find_binary(text_stream) + + # If that's not possible, silently use the original reader + # and get mojibake instead of exceptions. + if possible_binary_reader is None: + return text_stream + + binary_reader = possible_binary_reader + + # Default errors to replace instead of strict in order to get + # something that works. + if errors is None: + errors = "replace" + + # Wrap the binary stream in a text stream with the correct + # encoding parameters. + return _make_text_stream( + binary_reader, + encoding, + errors, + force_readable=force_readable, + force_writable=force_writable, + ) + + +def _force_correct_text_reader( + text_reader: t.IO[t.Any], + encoding: t.Optional[str], + errors: t.Optional[str], + force_readable: bool = False, +) -> t.TextIO: + return _force_correct_text_stream( + text_reader, + encoding, + errors, + _is_binary_reader, + _find_binary_reader, + force_readable=force_readable, + ) + + +def _force_correct_text_writer( + text_writer: t.IO[t.Any], + encoding: t.Optional[str], + errors: t.Optional[str], + force_writable: bool = False, +) -> t.TextIO: + return _force_correct_text_stream( + text_writer, + encoding, + errors, + _is_binary_writer, + _find_binary_writer, + force_writable=force_writable, + ) + + +def get_binary_stdin() -> t.BinaryIO: + reader = _find_binary_reader(sys.stdin) + if reader is None: + raise RuntimeError("Was not able to determine binary stream for sys.stdin.") + return reader + + +def get_binary_stdout() -> t.BinaryIO: + writer = _find_binary_writer(sys.stdout) + if writer is None: + raise RuntimeError("Was not able to determine binary stream for sys.stdout.") + return writer + + +def get_binary_stderr() -> t.BinaryIO: + writer = _find_binary_writer(sys.stderr) + if writer is None: + raise RuntimeError("Was not able to determine binary stream for sys.stderr.") + return writer + + +def get_text_stdin( + encoding: t.Optional[str] = None, errors: t.Optional[str] = None +) -> t.TextIO: + rv = _get_windows_console_stream(sys.stdin, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_reader(sys.stdin, encoding, errors, force_readable=True) + + +def get_text_stdout( + encoding: t.Optional[str] = None, errors: t.Optional[str] = None +) -> t.TextIO: + rv = _get_windows_console_stream(sys.stdout, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_writer(sys.stdout, encoding, errors, force_writable=True) + + +def get_text_stderr( + encoding: t.Optional[str] = None, errors: t.Optional[str] = None +) -> t.TextIO: + rv = _get_windows_console_stream(sys.stderr, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_writer(sys.stderr, encoding, errors, force_writable=True) + + +def _wrap_io_open( + file: t.Union[str, "os.PathLike[str]", int], + mode: str, + encoding: t.Optional[str], + errors: t.Optional[str], +) -> t.IO[t.Any]: + """Handles not passing ``encoding`` and ``errors`` in binary mode.""" + if "b" in mode: + return open(file, mode) + + return open(file, mode, encoding=encoding, errors=errors) + + +def open_stream( + filename: "t.Union[str, os.PathLike[str]]", + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + atomic: bool = False, +) -> t.Tuple[t.IO[t.Any], bool]: + binary = "b" in mode + filename = os.fspath(filename) + + # Standard streams first. These are simple because they ignore the + # atomic flag. Use fsdecode to handle Path("-"). + if os.fsdecode(filename) == "-": + if any(m in mode for m in ["w", "a", "x"]): + if binary: + return get_binary_stdout(), False + return get_text_stdout(encoding=encoding, errors=errors), False + if binary: + return get_binary_stdin(), False + return get_text_stdin(encoding=encoding, errors=errors), False + + # Non-atomic writes directly go out through the regular open functions. + if not atomic: + return _wrap_io_open(filename, mode, encoding, errors), True + + # Some usability stuff for atomic writes + if "a" in mode: + raise ValueError( + "Appending to an existing file is not supported, because that" + " would involve an expensive `copy`-operation to a temporary" + " file. Open the file in normal `w`-mode and copy explicitly" + " if that's what you're after." + ) + if "x" in mode: + raise ValueError("Use the `overwrite`-parameter instead.") + if "w" not in mode: + raise ValueError("Atomic writes only make sense with `w`-mode.") + + # Atomic writes are more complicated. They work by opening a file + # as a proxy in the same folder and then using the fdopen + # functionality to wrap it in a Python file. Then we wrap it in an + # atomic file that moves the file over on close. + import errno + import random + + try: + perm: t.Optional[int] = os.stat(filename).st_mode + except OSError: + perm = None + + flags = os.O_RDWR | os.O_CREAT | os.O_EXCL + + if binary: + flags |= getattr(os, "O_BINARY", 0) + + while True: + tmp_filename = os.path.join( + os.path.dirname(filename), + f".__atomic-write{random.randrange(1 << 32):08x}", + ) + try: + fd = os.open(tmp_filename, flags, 0o666 if perm is None else perm) + break + except OSError as e: + if e.errno == errno.EEXIST or ( + os.name == "nt" + and e.errno == errno.EACCES + and os.path.isdir(e.filename) + and os.access(e.filename, os.W_OK) + ): + continue + raise + + if perm is not None: + os.chmod(tmp_filename, perm) # in case perm includes bits in umask + + f = _wrap_io_open(fd, mode, encoding, errors) + af = _AtomicFile(f, tmp_filename, os.path.realpath(filename)) + return t.cast(t.IO[t.Any], af), True + + +class _AtomicFile: + def __init__(self, f: t.IO[t.Any], tmp_filename: str, real_filename: str) -> None: + self._f = f + self._tmp_filename = tmp_filename + self._real_filename = real_filename + self.closed = False + + @property + def name(self) -> str: + return self._real_filename + + def close(self, delete: bool = False) -> None: + if self.closed: + return + self._f.close() + os.replace(self._tmp_filename, self._real_filename) + self.closed = True + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._f, name) + + def __enter__(self) -> "_AtomicFile": + return self + + def __exit__(self, exc_type: t.Optional[t.Type[BaseException]], *_: t.Any) -> None: + self.close(delete=exc_type is not None) + + def __repr__(self) -> str: + return repr(self._f) + + +def strip_ansi(value: str) -> str: + return _ansi_re.sub("", value) + + +def _is_jupyter_kernel_output(stream: t.IO[t.Any]) -> bool: + while isinstance(stream, (_FixupStream, _NonClosingTextIOWrapper)): + stream = stream._stream + + return stream.__class__.__module__.startswith("ipykernel.") + + +def should_strip_ansi( + stream: t.Optional[t.IO[t.Any]] = None, color: t.Optional[bool] = None +) -> bool: + if color is None: + if stream is None: + stream = sys.stdin + return not isatty(stream) and not _is_jupyter_kernel_output(stream) + return not color + + +# On Windows, wrap the output streams with colorama to support ANSI +# color codes. +# NOTE: double check is needed so mypy does not analyze this on Linux +if sys.platform.startswith("win") and WIN: + from ._winconsole import _get_windows_console_stream + + def _get_argv_encoding() -> str: + import locale + + return locale.getpreferredencoding() + + _ansi_stream_wrappers: t.MutableMapping[t.TextIO, t.TextIO] = WeakKeyDictionary() + + def auto_wrap_for_ansi( + stream: t.TextIO, color: t.Optional[bool] = None + ) -> t.TextIO: + """Support ANSI color and style codes on Windows by wrapping a + stream with colorama. + """ + try: + cached = _ansi_stream_wrappers.get(stream) + except Exception: + cached = None + + if cached is not None: + return cached + + import colorama + + strip = should_strip_ansi(stream, color) + ansi_wrapper = colorama.AnsiToWin32(stream, strip=strip) + rv = t.cast(t.TextIO, ansi_wrapper.stream) + _write = rv.write + + def _safe_write(s): + try: + return _write(s) + except BaseException: + ansi_wrapper.reset_all() + raise + + rv.write = _safe_write + + try: + _ansi_stream_wrappers[stream] = rv + except Exception: + pass + + return rv + +else: + + def _get_argv_encoding() -> str: + return getattr(sys.stdin, "encoding", None) or sys.getfilesystemencoding() + + def _get_windows_console_stream( + f: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str] + ) -> t.Optional[t.TextIO]: + return None + + +def term_len(x: str) -> int: + return len(strip_ansi(x)) + + +def isatty(stream: t.IO[t.Any]) -> bool: + try: + return stream.isatty() + except Exception: + return False + + +def _make_cached_stream_func( + src_func: t.Callable[[], t.Optional[t.TextIO]], + wrapper_func: t.Callable[[], t.TextIO], +) -> t.Callable[[], t.Optional[t.TextIO]]: + cache: t.MutableMapping[t.TextIO, t.TextIO] = WeakKeyDictionary() + + def func() -> t.Optional[t.TextIO]: + stream = src_func() + + if stream is None: + return None + + try: + rv = cache.get(stream) + except Exception: + rv = None + if rv is not None: + return rv + rv = wrapper_func() + try: + cache[stream] = rv + except Exception: + pass + return rv + + return func + + +_default_text_stdin = _make_cached_stream_func(lambda: sys.stdin, get_text_stdin) +_default_text_stdout = _make_cached_stream_func(lambda: sys.stdout, get_text_stdout) +_default_text_stderr = _make_cached_stream_func(lambda: sys.stderr, get_text_stderr) + + +binary_streams: t.Mapping[str, t.Callable[[], t.BinaryIO]] = { + "stdin": get_binary_stdin, + "stdout": get_binary_stdout, + "stderr": get_binary_stderr, +} + +text_streams: t.Mapping[ + str, t.Callable[[t.Optional[str], t.Optional[str]], t.TextIO] +] = { + "stdin": get_text_stdin, + "stdout": get_text_stdout, + "stderr": get_text_stderr, +} diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/_termui_impl.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/_termui_impl.py new file mode 100644 index 0000000..ad9f8f6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/_termui_impl.py @@ -0,0 +1,788 @@ +""" +This module contains implementations for the termui module. To keep the +import time of Click down, some infrequently used functionality is +placed in this module and only imported as needed. +""" + +import contextlib +import math +import os +import sys +import time +import typing as t +from gettext import gettext as _ +from io import StringIO +from shutil import which +from types import TracebackType + +from ._compat import _default_text_stdout +from ._compat import CYGWIN +from ._compat import get_best_encoding +from ._compat import isatty +from ._compat import open_stream +from ._compat import strip_ansi +from ._compat import term_len +from ._compat import WIN +from .exceptions import ClickException +from .utils import echo + +V = t.TypeVar("V") + +if os.name == "nt": + BEFORE_BAR = "\r" + AFTER_BAR = "\n" +else: + BEFORE_BAR = "\r\033[?25l" + AFTER_BAR = "\033[?25h\n" + + +class ProgressBar(t.Generic[V]): + def __init__( + self, + iterable: t.Optional[t.Iterable[V]], + length: t.Optional[int] = None, + fill_char: str = "#", + empty_char: str = " ", + bar_template: str = "%(bar)s", + info_sep: str = " ", + show_eta: bool = True, + show_percent: t.Optional[bool] = None, + show_pos: bool = False, + item_show_func: t.Optional[t.Callable[[t.Optional[V]], t.Optional[str]]] = None, + label: t.Optional[str] = None, + file: t.Optional[t.TextIO] = None, + color: t.Optional[bool] = None, + update_min_steps: int = 1, + width: int = 30, + ) -> None: + self.fill_char = fill_char + self.empty_char = empty_char + self.bar_template = bar_template + self.info_sep = info_sep + self.show_eta = show_eta + self.show_percent = show_percent + self.show_pos = show_pos + self.item_show_func = item_show_func + self.label: str = label or "" + + if file is None: + file = _default_text_stdout() + + # There are no standard streams attached to write to. For example, + # pythonw on Windows. + if file is None: + file = StringIO() + + self.file = file + self.color = color + self.update_min_steps = update_min_steps + self._completed_intervals = 0 + self.width: int = width + self.autowidth: bool = width == 0 + + if length is None: + from operator import length_hint + + length = length_hint(iterable, -1) + + if length == -1: + length = None + if iterable is None: + if length is None: + raise TypeError("iterable or length is required") + iterable = t.cast(t.Iterable[V], range(length)) + self.iter: t.Iterable[V] = iter(iterable) + self.length = length + self.pos = 0 + self.avg: t.List[float] = [] + self.last_eta: float + self.start: float + self.start = self.last_eta = time.time() + self.eta_known: bool = False + self.finished: bool = False + self.max_width: t.Optional[int] = None + self.entered: bool = False + self.current_item: t.Optional[V] = None + self.is_hidden: bool = not isatty(self.file) + self._last_line: t.Optional[str] = None + + def __enter__(self) -> "ProgressBar[V]": + self.entered = True + self.render_progress() + return self + + def __exit__( + self, + exc_type: t.Optional[t.Type[BaseException]], + exc_value: t.Optional[BaseException], + tb: t.Optional[TracebackType], + ) -> None: + self.render_finish() + + def __iter__(self) -> t.Iterator[V]: + if not self.entered: + raise RuntimeError("You need to use progress bars in a with block.") + self.render_progress() + return self.generator() + + def __next__(self) -> V: + # Iteration is defined in terms of a generator function, + # returned by iter(self); use that to define next(). This works + # because `self.iter` is an iterable consumed by that generator, + # so it is re-entry safe. Calling `next(self.generator())` + # twice works and does "what you want". + return next(iter(self)) + + def render_finish(self) -> None: + if self.is_hidden: + return + self.file.write(AFTER_BAR) + self.file.flush() + + @property + def pct(self) -> float: + if self.finished: + return 1.0 + return min(self.pos / (float(self.length or 1) or 1), 1.0) + + @property + def time_per_iteration(self) -> float: + if not self.avg: + return 0.0 + return sum(self.avg) / float(len(self.avg)) + + @property + def eta(self) -> float: + if self.length is not None and not self.finished: + return self.time_per_iteration * (self.length - self.pos) + return 0.0 + + def format_eta(self) -> str: + if self.eta_known: + t = int(self.eta) + seconds = t % 60 + t //= 60 + minutes = t % 60 + t //= 60 + hours = t % 24 + t //= 24 + if t > 0: + return f"{t}d {hours:02}:{minutes:02}:{seconds:02}" + else: + return f"{hours:02}:{minutes:02}:{seconds:02}" + return "" + + def format_pos(self) -> str: + pos = str(self.pos) + if self.length is not None: + pos += f"/{self.length}" + return pos + + def format_pct(self) -> str: + return f"{int(self.pct * 100): 4}%"[1:] + + def format_bar(self) -> str: + if self.length is not None: + bar_length = int(self.pct * self.width) + bar = self.fill_char * bar_length + bar += self.empty_char * (self.width - bar_length) + elif self.finished: + bar = self.fill_char * self.width + else: + chars = list(self.empty_char * (self.width or 1)) + if self.time_per_iteration != 0: + chars[ + int( + (math.cos(self.pos * self.time_per_iteration) / 2.0 + 0.5) + * self.width + ) + ] = self.fill_char + bar = "".join(chars) + return bar + + def format_progress_line(self) -> str: + show_percent = self.show_percent + + info_bits = [] + if self.length is not None and show_percent is None: + show_percent = not self.show_pos + + if self.show_pos: + info_bits.append(self.format_pos()) + if show_percent: + info_bits.append(self.format_pct()) + if self.show_eta and self.eta_known and not self.finished: + info_bits.append(self.format_eta()) + if self.item_show_func is not None: + item_info = self.item_show_func(self.current_item) + if item_info is not None: + info_bits.append(item_info) + + return ( + self.bar_template + % { + "label": self.label, + "bar": self.format_bar(), + "info": self.info_sep.join(info_bits), + } + ).rstrip() + + def render_progress(self) -> None: + import shutil + + if self.is_hidden: + # Only output the label as it changes if the output is not a + # TTY. Use file=stderr if you expect to be piping stdout. + if self._last_line != self.label: + self._last_line = self.label + echo(self.label, file=self.file, color=self.color) + + return + + buf = [] + # Update width in case the terminal has been resized + if self.autowidth: + old_width = self.width + self.width = 0 + clutter_length = term_len(self.format_progress_line()) + new_width = max(0, shutil.get_terminal_size().columns - clutter_length) + if new_width < old_width: + buf.append(BEFORE_BAR) + buf.append(" " * self.max_width) # type: ignore + self.max_width = new_width + self.width = new_width + + clear_width = self.width + if self.max_width is not None: + clear_width = self.max_width + + buf.append(BEFORE_BAR) + line = self.format_progress_line() + line_len = term_len(line) + if self.max_width is None or self.max_width < line_len: + self.max_width = line_len + + buf.append(line) + buf.append(" " * (clear_width - line_len)) + line = "".join(buf) + # Render the line only if it changed. + + if line != self._last_line: + self._last_line = line + echo(line, file=self.file, color=self.color, nl=False) + self.file.flush() + + def make_step(self, n_steps: int) -> None: + self.pos += n_steps + if self.length is not None and self.pos >= self.length: + self.finished = True + + if (time.time() - self.last_eta) < 1.0: + return + + self.last_eta = time.time() + + # self.avg is a rolling list of length <= 7 of steps where steps are + # defined as time elapsed divided by the total progress through + # self.length. + if self.pos: + step = (time.time() - self.start) / self.pos + else: + step = time.time() - self.start + + self.avg = self.avg[-6:] + [step] + + self.eta_known = self.length is not None + + def update(self, n_steps: int, current_item: t.Optional[V] = None) -> None: + """Update the progress bar by advancing a specified number of + steps, and optionally set the ``current_item`` for this new + position. + + :param n_steps: Number of steps to advance. + :param current_item: Optional item to set as ``current_item`` + for the updated position. + + .. versionchanged:: 8.0 + Added the ``current_item`` optional parameter. + + .. versionchanged:: 8.0 + Only render when the number of steps meets the + ``update_min_steps`` threshold. + """ + if current_item is not None: + self.current_item = current_item + + self._completed_intervals += n_steps + + if self._completed_intervals >= self.update_min_steps: + self.make_step(self._completed_intervals) + self.render_progress() + self._completed_intervals = 0 + + def finish(self) -> None: + self.eta_known = False + self.current_item = None + self.finished = True + + def generator(self) -> t.Iterator[V]: + """Return a generator which yields the items added to the bar + during construction, and updates the progress bar *after* the + yielded block returns. + """ + # WARNING: the iterator interface for `ProgressBar` relies on + # this and only works because this is a simple generator which + # doesn't create or manage additional state. If this function + # changes, the impact should be evaluated both against + # `iter(bar)` and `next(bar)`. `next()` in particular may call + # `self.generator()` repeatedly, and this must remain safe in + # order for that interface to work. + if not self.entered: + raise RuntimeError("You need to use progress bars in a with block.") + + if self.is_hidden: + yield from self.iter + else: + for rv in self.iter: + self.current_item = rv + + # This allows show_item_func to be updated before the + # item is processed. Only trigger at the beginning of + # the update interval. + if self._completed_intervals == 0: + self.render_progress() + + yield rv + self.update(1) + + self.finish() + self.render_progress() + + +def pager(generator: t.Iterable[str], color: t.Optional[bool] = None) -> None: + """Decide what method to use for paging through text.""" + stdout = _default_text_stdout() + + # There are no standard streams attached to write to. For example, + # pythonw on Windows. + if stdout is None: + stdout = StringIO() + + if not isatty(sys.stdin) or not isatty(stdout): + return _nullpager(stdout, generator, color) + pager_cmd = (os.environ.get("PAGER", None) or "").strip() + if pager_cmd: + if WIN: + if _tempfilepager(generator, pager_cmd, color): + return + elif _pipepager(generator, pager_cmd, color): + return + if os.environ.get("TERM") in ("dumb", "emacs"): + return _nullpager(stdout, generator, color) + if (WIN or sys.platform.startswith("os2")) and _tempfilepager( + generator, "more", color + ): + return + if _pipepager(generator, "less", color): + return + + import tempfile + + fd, filename = tempfile.mkstemp() + os.close(fd) + try: + if _pipepager(generator, "more", color): + return + return _nullpager(stdout, generator, color) + finally: + os.unlink(filename) + + +def _pipepager(generator: t.Iterable[str], cmd: str, color: t.Optional[bool]) -> bool: + """Page through text by feeding it to another program. Invoking a + pager through this might support colors. + + Returns True if the command was found, False otherwise and thus another + pager should be attempted. + """ + cmd_absolute = which(cmd) + if cmd_absolute is None: + return False + + import subprocess + + env = dict(os.environ) + + # If we're piping to less we might support colors under the + # condition that + cmd_detail = cmd.rsplit("/", 1)[-1].split() + if color is None and cmd_detail[0] == "less": + less_flags = f"{os.environ.get('LESS', '')}{' '.join(cmd_detail[1:])}" + if not less_flags: + env["LESS"] = "-R" + color = True + elif "r" in less_flags or "R" in less_flags: + color = True + + c = subprocess.Popen( + [cmd_absolute], + shell=True, + stdin=subprocess.PIPE, + env=env, + errors="replace", + text=True, + ) + assert c.stdin is not None + try: + for text in generator: + if not color: + text = strip_ansi(text) + + c.stdin.write(text) + except (OSError, KeyboardInterrupt): + pass + else: + c.stdin.close() + + # Less doesn't respect ^C, but catches it for its own UI purposes (aborting + # search or other commands inside less). + # + # That means when the user hits ^C, the parent process (click) terminates, + # but less is still alive, paging the output and messing up the terminal. + # + # If the user wants to make the pager exit on ^C, they should set + # `LESS='-K'`. It's not our decision to make. + while True: + try: + c.wait() + except KeyboardInterrupt: + pass + else: + break + + return True + + +def _tempfilepager( + generator: t.Iterable[str], + cmd: str, + color: t.Optional[bool], +) -> bool: + """Page through text by invoking a program on a temporary file. + + Returns True if the command was found, False otherwise and thus another + pager should be attempted. + """ + # Which is necessary for Windows, it is also recommended in the Popen docs. + cmd_absolute = which(cmd) + if cmd_absolute is None: + return False + + import subprocess + import tempfile + + fd, filename = tempfile.mkstemp() + # TODO: This never terminates if the passed generator never terminates. + text = "".join(generator) + if not color: + text = strip_ansi(text) + encoding = get_best_encoding(sys.stdout) + with open_stream(filename, "wb")[0] as f: + f.write(text.encode(encoding)) + try: + subprocess.call([cmd_absolute, filename]) + except OSError: + # Command not found + pass + finally: + os.close(fd) + os.unlink(filename) + + return True + + +def _nullpager( + stream: t.TextIO, generator: t.Iterable[str], color: t.Optional[bool] +) -> None: + """Simply print unformatted text. This is the ultimate fallback.""" + for text in generator: + if not color: + text = strip_ansi(text) + stream.write(text) + + +class Editor: + def __init__( + self, + editor: t.Optional[str] = None, + env: t.Optional[t.Mapping[str, str]] = None, + require_save: bool = True, + extension: str = ".txt", + ) -> None: + self.editor = editor + self.env = env + self.require_save = require_save + self.extension = extension + + def get_editor(self) -> str: + if self.editor is not None: + return self.editor + for key in "VISUAL", "EDITOR": + rv = os.environ.get(key) + if rv: + return rv + if WIN: + return "notepad" + for editor in "sensible-editor", "vim", "nano": + if which(editor) is not None: + return editor + return "vi" + + def edit_file(self, filename: str) -> None: + import subprocess + + editor = self.get_editor() + environ: t.Optional[t.Dict[str, str]] = None + + if self.env: + environ = os.environ.copy() + environ.update(self.env) + + try: + c = subprocess.Popen(f'{editor} "{filename}"', env=environ, shell=True) + exit_code = c.wait() + if exit_code != 0: + raise ClickException( + _("{editor}: Editing failed").format(editor=editor) + ) + except OSError as e: + raise ClickException( + _("{editor}: Editing failed: {e}").format(editor=editor, e=e) + ) from e + + def edit(self, text: t.Optional[t.AnyStr]) -> t.Optional[t.AnyStr]: + import tempfile + + if not text: + data = b"" + elif isinstance(text, (bytes, bytearray)): + data = text + else: + if text and not text.endswith("\n"): + text += "\n" + + if WIN: + data = text.replace("\n", "\r\n").encode("utf-8-sig") + else: + data = text.encode("utf-8") + + fd, name = tempfile.mkstemp(prefix="editor-", suffix=self.extension) + f: t.BinaryIO + + try: + with os.fdopen(fd, "wb") as f: + f.write(data) + + # If the filesystem resolution is 1 second, like Mac OS + # 10.12 Extended, or 2 seconds, like FAT32, and the editor + # closes very fast, require_save can fail. Set the modified + # time to be 2 seconds in the past to work around this. + os.utime(name, (os.path.getatime(name), os.path.getmtime(name) - 2)) + # Depending on the resolution, the exact value might not be + # recorded, so get the new recorded value. + timestamp = os.path.getmtime(name) + + self.edit_file(name) + + if self.require_save and os.path.getmtime(name) == timestamp: + return None + + with open(name, "rb") as f: + rv = f.read() + + if isinstance(text, (bytes, bytearray)): + return rv + + return rv.decode("utf-8-sig").replace("\r\n", "\n") # type: ignore + finally: + os.unlink(name) + + +def open_url(url: str, wait: bool = False, locate: bool = False) -> int: + import subprocess + + def _unquote_file(url: str) -> str: + from urllib.parse import unquote + + if url.startswith("file://"): + url = unquote(url[7:]) + + return url + + if sys.platform == "darwin": + args = ["open"] + if wait: + args.append("-W") + if locate: + args.append("-R") + args.append(_unquote_file(url)) + null = open("/dev/null", "w") + try: + return subprocess.Popen(args, stderr=null).wait() + finally: + null.close() + elif WIN: + if locate: + url = _unquote_file(url) + args = ["explorer", f"/select,{url}"] + else: + args = ["start"] + if wait: + args.append("/WAIT") + args.append("") + args.append(url) + try: + return subprocess.call(args) + except OSError: + # Command not found + return 127 + elif CYGWIN: + if locate: + url = _unquote_file(url) + args = ["cygstart", os.path.dirname(url)] + else: + args = ["cygstart"] + if wait: + args.append("-w") + args.append(url) + try: + return subprocess.call(args) + except OSError: + # Command not found + return 127 + + try: + if locate: + url = os.path.dirname(_unquote_file(url)) or "." + else: + url = _unquote_file(url) + c = subprocess.Popen(["xdg-open", url]) + if wait: + return c.wait() + return 0 + except OSError: + if url.startswith(("http://", "https://")) and not locate and not wait: + import webbrowser + + webbrowser.open(url) + return 0 + return 1 + + +def _translate_ch_to_exc(ch: str) -> t.Optional[BaseException]: + if ch == "\x03": + raise KeyboardInterrupt() + + if ch == "\x04" and not WIN: # Unix-like, Ctrl+D + raise EOFError() + + if ch == "\x1a" and WIN: # Windows, Ctrl+Z + raise EOFError() + + return None + + +if WIN: + import msvcrt + + @contextlib.contextmanager + def raw_terminal() -> t.Iterator[int]: + yield -1 + + def getchar(echo: bool) -> str: + # The function `getch` will return a bytes object corresponding to + # the pressed character. Since Windows 10 build 1803, it will also + # return \x00 when called a second time after pressing a regular key. + # + # `getwch` does not share this probably-bugged behavior. Moreover, it + # returns a Unicode object by default, which is what we want. + # + # Either of these functions will return \x00 or \xe0 to indicate + # a special key, and you need to call the same function again to get + # the "rest" of the code. The fun part is that \u00e0 is + # "latin small letter a with grave", so if you type that on a French + # keyboard, you _also_ get a \xe0. + # E.g., consider the Up arrow. This returns \xe0 and then \x48. The + # resulting Unicode string reads as "a with grave" + "capital H". + # This is indistinguishable from when the user actually types + # "a with grave" and then "capital H". + # + # When \xe0 is returned, we assume it's part of a special-key sequence + # and call `getwch` again, but that means that when the user types + # the \u00e0 character, `getchar` doesn't return until a second + # character is typed. + # The alternative is returning immediately, but that would mess up + # cross-platform handling of arrow keys and others that start with + # \xe0. Another option is using `getch`, but then we can't reliably + # read non-ASCII characters, because return values of `getch` are + # limited to the current 8-bit codepage. + # + # Anyway, Click doesn't claim to do this Right(tm), and using `getwch` + # is doing the right thing in more situations than with `getch`. + func: t.Callable[[], str] + + if echo: + func = msvcrt.getwche # type: ignore + else: + func = msvcrt.getwch # type: ignore + + rv = func() + + if rv in ("\x00", "\xe0"): + # \x00 and \xe0 are control characters that indicate special key, + # see above. + rv += func() + + _translate_ch_to_exc(rv) + return rv + +else: + import termios + import tty + + @contextlib.contextmanager + def raw_terminal() -> t.Iterator[int]: + f: t.Optional[t.TextIO] + fd: int + + if not isatty(sys.stdin): + f = open("/dev/tty") + fd = f.fileno() + else: + fd = sys.stdin.fileno() + f = None + + try: + old_settings = termios.tcgetattr(fd) + + try: + tty.setraw(fd) + yield fd + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) + sys.stdout.flush() + + if f is not None: + f.close() + except termios.error: + pass + + def getchar(echo: bool) -> str: + with raw_terminal() as fd: + ch = os.read(fd, 32).decode(get_best_encoding(sys.stdin), "replace") + + if echo and isatty(sys.stdout): + sys.stdout.write(ch) + + _translate_ch_to_exc(ch) + return ch diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/_textwrap.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/_textwrap.py new file mode 100644 index 0000000..b47dcbd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/_textwrap.py @@ -0,0 +1,49 @@ +import textwrap +import typing as t +from contextlib import contextmanager + + +class TextWrapper(textwrap.TextWrapper): + def _handle_long_word( + self, + reversed_chunks: t.List[str], + cur_line: t.List[str], + cur_len: int, + width: int, + ) -> None: + space_left = max(width - cur_len, 1) + + if self.break_long_words: + last = reversed_chunks[-1] + cut = last[:space_left] + res = last[space_left:] + cur_line.append(cut) + reversed_chunks[-1] = res + elif not cur_line: + cur_line.append(reversed_chunks.pop()) + + @contextmanager + def extra_indent(self, indent: str) -> t.Iterator[None]: + old_initial_indent = self.initial_indent + old_subsequent_indent = self.subsequent_indent + self.initial_indent += indent + self.subsequent_indent += indent + + try: + yield + finally: + self.initial_indent = old_initial_indent + self.subsequent_indent = old_subsequent_indent + + def indent_only(self, text: str) -> str: + rv = [] + + for idx, line in enumerate(text.splitlines()): + indent = self.initial_indent + + if idx > 0: + indent = self.subsequent_indent + + rv.append(f"{indent}{line}") + + return "\n".join(rv) diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/_winconsole.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/_winconsole.py new file mode 100644 index 0000000..6b20df3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/_winconsole.py @@ -0,0 +1,279 @@ +# This module is based on the excellent work by Adam Bartoš who +# provided a lot of what went into the implementation here in +# the discussion to issue1602 in the Python bug tracker. +# +# There are some general differences in regards to how this works +# compared to the original patches as we do not need to patch +# the entire interpreter but just work in our little world of +# echo and prompt. +import io +import sys +import time +import typing as t +from ctypes import byref +from ctypes import c_char +from ctypes import c_char_p +from ctypes import c_int +from ctypes import c_ssize_t +from ctypes import c_ulong +from ctypes import c_void_p +from ctypes import POINTER +from ctypes import py_object +from ctypes import Structure +from ctypes.wintypes import DWORD +from ctypes.wintypes import HANDLE +from ctypes.wintypes import LPCWSTR +from ctypes.wintypes import LPWSTR + +from ._compat import _NonClosingTextIOWrapper + +assert sys.platform == "win32" +import msvcrt # noqa: E402 +from ctypes import windll # noqa: E402 +from ctypes import WINFUNCTYPE # noqa: E402 + +c_ssize_p = POINTER(c_ssize_t) + +kernel32 = windll.kernel32 +GetStdHandle = kernel32.GetStdHandle +ReadConsoleW = kernel32.ReadConsoleW +WriteConsoleW = kernel32.WriteConsoleW +GetConsoleMode = kernel32.GetConsoleMode +GetLastError = kernel32.GetLastError +GetCommandLineW = WINFUNCTYPE(LPWSTR)(("GetCommandLineW", windll.kernel32)) +CommandLineToArgvW = WINFUNCTYPE(POINTER(LPWSTR), LPCWSTR, POINTER(c_int))( + ("CommandLineToArgvW", windll.shell32) +) +LocalFree = WINFUNCTYPE(c_void_p, c_void_p)(("LocalFree", windll.kernel32)) + +STDIN_HANDLE = GetStdHandle(-10) +STDOUT_HANDLE = GetStdHandle(-11) +STDERR_HANDLE = GetStdHandle(-12) + +PyBUF_SIMPLE = 0 +PyBUF_WRITABLE = 1 + +ERROR_SUCCESS = 0 +ERROR_NOT_ENOUGH_MEMORY = 8 +ERROR_OPERATION_ABORTED = 995 + +STDIN_FILENO = 0 +STDOUT_FILENO = 1 +STDERR_FILENO = 2 + +EOF = b"\x1a" +MAX_BYTES_WRITTEN = 32767 + +try: + from ctypes import pythonapi +except ImportError: + # On PyPy we cannot get buffers so our ability to operate here is + # severely limited. + get_buffer = None +else: + + class Py_buffer(Structure): + _fields_ = [ + ("buf", c_void_p), + ("obj", py_object), + ("len", c_ssize_t), + ("itemsize", c_ssize_t), + ("readonly", c_int), + ("ndim", c_int), + ("format", c_char_p), + ("shape", c_ssize_p), + ("strides", c_ssize_p), + ("suboffsets", c_ssize_p), + ("internal", c_void_p), + ] + + PyObject_GetBuffer = pythonapi.PyObject_GetBuffer + PyBuffer_Release = pythonapi.PyBuffer_Release + + def get_buffer(obj, writable=False): + buf = Py_buffer() + flags = PyBUF_WRITABLE if writable else PyBUF_SIMPLE + PyObject_GetBuffer(py_object(obj), byref(buf), flags) + + try: + buffer_type = c_char * buf.len + return buffer_type.from_address(buf.buf) + finally: + PyBuffer_Release(byref(buf)) + + +class _WindowsConsoleRawIOBase(io.RawIOBase): + def __init__(self, handle): + self.handle = handle + + def isatty(self): + super().isatty() + return True + + +class _WindowsConsoleReader(_WindowsConsoleRawIOBase): + def readable(self): + return True + + def readinto(self, b): + bytes_to_be_read = len(b) + if not bytes_to_be_read: + return 0 + elif bytes_to_be_read % 2: + raise ValueError( + "cannot read odd number of bytes from UTF-16-LE encoded console" + ) + + buffer = get_buffer(b, writable=True) + code_units_to_be_read = bytes_to_be_read // 2 + code_units_read = c_ulong() + + rv = ReadConsoleW( + HANDLE(self.handle), + buffer, + code_units_to_be_read, + byref(code_units_read), + None, + ) + if GetLastError() == ERROR_OPERATION_ABORTED: + # wait for KeyboardInterrupt + time.sleep(0.1) + if not rv: + raise OSError(f"Windows error: {GetLastError()}") + + if buffer[0] == EOF: + return 0 + return 2 * code_units_read.value + + +class _WindowsConsoleWriter(_WindowsConsoleRawIOBase): + def writable(self): + return True + + @staticmethod + def _get_error_message(errno): + if errno == ERROR_SUCCESS: + return "ERROR_SUCCESS" + elif errno == ERROR_NOT_ENOUGH_MEMORY: + return "ERROR_NOT_ENOUGH_MEMORY" + return f"Windows error {errno}" + + def write(self, b): + bytes_to_be_written = len(b) + buf = get_buffer(b) + code_units_to_be_written = min(bytes_to_be_written, MAX_BYTES_WRITTEN) // 2 + code_units_written = c_ulong() + + WriteConsoleW( + HANDLE(self.handle), + buf, + code_units_to_be_written, + byref(code_units_written), + None, + ) + bytes_written = 2 * code_units_written.value + + if bytes_written == 0 and bytes_to_be_written > 0: + raise OSError(self._get_error_message(GetLastError())) + return bytes_written + + +class ConsoleStream: + def __init__(self, text_stream: t.TextIO, byte_stream: t.BinaryIO) -> None: + self._text_stream = text_stream + self.buffer = byte_stream + + @property + def name(self) -> str: + return self.buffer.name + + def write(self, x: t.AnyStr) -> int: + if isinstance(x, str): + return self._text_stream.write(x) + try: + self.flush() + except Exception: + pass + return self.buffer.write(x) + + def writelines(self, lines: t.Iterable[t.AnyStr]) -> None: + for line in lines: + self.write(line) + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._text_stream, name) + + def isatty(self) -> bool: + return self.buffer.isatty() + + def __repr__(self): + return f"" + + +def _get_text_stdin(buffer_stream: t.BinaryIO) -> t.TextIO: + text_stream = _NonClosingTextIOWrapper( + io.BufferedReader(_WindowsConsoleReader(STDIN_HANDLE)), + "utf-16-le", + "strict", + line_buffering=True, + ) + return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) + + +def _get_text_stdout(buffer_stream: t.BinaryIO) -> t.TextIO: + text_stream = _NonClosingTextIOWrapper( + io.BufferedWriter(_WindowsConsoleWriter(STDOUT_HANDLE)), + "utf-16-le", + "strict", + line_buffering=True, + ) + return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) + + +def _get_text_stderr(buffer_stream: t.BinaryIO) -> t.TextIO: + text_stream = _NonClosingTextIOWrapper( + io.BufferedWriter(_WindowsConsoleWriter(STDERR_HANDLE)), + "utf-16-le", + "strict", + line_buffering=True, + ) + return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) + + +_stream_factories: t.Mapping[int, t.Callable[[t.BinaryIO], t.TextIO]] = { + 0: _get_text_stdin, + 1: _get_text_stdout, + 2: _get_text_stderr, +} + + +def _is_console(f: t.TextIO) -> bool: + if not hasattr(f, "fileno"): + return False + + try: + fileno = f.fileno() + except (OSError, io.UnsupportedOperation): + return False + + handle = msvcrt.get_osfhandle(fileno) + return bool(GetConsoleMode(handle, byref(DWORD()))) + + +def _get_windows_console_stream( + f: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str] +) -> t.Optional[t.TextIO]: + if ( + get_buffer is not None + and encoding in {"utf-16-le", None} + and errors in {"strict", None} + and _is_console(f) + ): + func = _stream_factories.get(f.fileno()) + if func is not None: + b = getattr(f, "buffer", None) + + if b is None: + return None + + return func(b) diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/core.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/core.py new file mode 100644 index 0000000..e630501 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/core.py @@ -0,0 +1,3047 @@ +import enum +import errno +import inspect +import os +import sys +import typing as t +from collections import abc +from contextlib import contextmanager +from contextlib import ExitStack +from functools import update_wrapper +from gettext import gettext as _ +from gettext import ngettext +from itertools import repeat +from types import TracebackType + +from . import types +from .exceptions import Abort +from .exceptions import BadParameter +from .exceptions import ClickException +from .exceptions import Exit +from .exceptions import MissingParameter +from .exceptions import UsageError +from .formatting import HelpFormatter +from .formatting import join_options +from .globals import pop_context +from .globals import push_context +from .parser import _flag_needs_value +from .parser import OptionParser +from .parser import split_opt +from .termui import confirm +from .termui import prompt +from .termui import style +from .utils import _detect_program_name +from .utils import _expand_args +from .utils import echo +from .utils import make_default_short_help +from .utils import make_str +from .utils import PacifyFlushWrapper + +if t.TYPE_CHECKING: + import typing_extensions as te + + from .decorators import HelpOption + from .shell_completion import CompletionItem + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) +V = t.TypeVar("V") + + +def _complete_visible_commands( + ctx: "Context", incomplete: str +) -> t.Iterator[t.Tuple[str, "Command"]]: + """List all the subcommands of a group that start with the + incomplete value and aren't hidden. + + :param ctx: Invocation context for the group. + :param incomplete: Value being completed. May be empty. + """ + multi = t.cast(MultiCommand, ctx.command) + + for name in multi.list_commands(ctx): + if name.startswith(incomplete): + command = multi.get_command(ctx, name) + + if command is not None and not command.hidden: + yield name, command + + +def _check_multicommand( + base_command: "MultiCommand", cmd_name: str, cmd: "Command", register: bool = False +) -> None: + if not base_command.chain or not isinstance(cmd, MultiCommand): + return + if register: + hint = ( + "It is not possible to add multi commands as children to" + " another multi command that is in chain mode." + ) + else: + hint = ( + "Found a multi command as subcommand to a multi command" + " that is in chain mode. This is not supported." + ) + raise RuntimeError( + f"{hint}. Command {base_command.name!r} is set to chain and" + f" {cmd_name!r} was added as a subcommand but it in itself is a" + f" multi command. ({cmd_name!r} is a {type(cmd).__name__}" + f" within a chained {type(base_command).__name__} named" + f" {base_command.name!r})." + ) + + +def batch(iterable: t.Iterable[V], batch_size: int) -> t.List[t.Tuple[V, ...]]: + return list(zip(*repeat(iter(iterable), batch_size))) + + +@contextmanager +def augment_usage_errors( + ctx: "Context", param: t.Optional["Parameter"] = None +) -> t.Iterator[None]: + """Context manager that attaches extra information to exceptions.""" + try: + yield + except BadParameter as e: + if e.ctx is None: + e.ctx = ctx + if param is not None and e.param is None: + e.param = param + raise + except UsageError as e: + if e.ctx is None: + e.ctx = ctx + raise + + +def iter_params_for_processing( + invocation_order: t.Sequence["Parameter"], + declaration_order: t.Sequence["Parameter"], +) -> t.List["Parameter"]: + """Returns all declared parameters in the order they should be processed. + + The declared parameters are re-shuffled depending on the order in which + they were invoked, as well as the eagerness of each parameters. + + The invocation order takes precedence over the declaration order. I.e. the + order in which the user provided them to the CLI is respected. + + This behavior and its effect on callback evaluation is detailed at: + https://click.palletsprojects.com/en/stable/advanced/#callback-evaluation-order + """ + + def sort_key(item: "Parameter") -> t.Tuple[bool, float]: + try: + idx: float = invocation_order.index(item) + except ValueError: + idx = float("inf") + + return not item.is_eager, idx + + return sorted(declaration_order, key=sort_key) + + +class ParameterSource(enum.Enum): + """This is an :class:`~enum.Enum` that indicates the source of a + parameter's value. + + Use :meth:`click.Context.get_parameter_source` to get the + source for a parameter by name. + + .. versionchanged:: 8.0 + Use :class:`~enum.Enum` and drop the ``validate`` method. + + .. versionchanged:: 8.0 + Added the ``PROMPT`` value. + """ + + COMMANDLINE = enum.auto() + """The value was provided by the command line args.""" + ENVIRONMENT = enum.auto() + """The value was provided with an environment variable.""" + DEFAULT = enum.auto() + """Used the default specified by the parameter.""" + DEFAULT_MAP = enum.auto() + """Used a default provided by :attr:`Context.default_map`.""" + PROMPT = enum.auto() + """Used a prompt to confirm a default or provide a value.""" + + +class Context: + """The context is a special internal object that holds state relevant + for the script execution at every single level. It's normally invisible + to commands unless they opt-in to getting access to it. + + The context is useful as it can pass internal objects around and can + control special execution features such as reading data from + environment variables. + + A context can be used as context manager in which case it will call + :meth:`close` on teardown. + + :param command: the command class for this context. + :param parent: the parent context. + :param info_name: the info name for this invocation. Generally this + is the most descriptive name for the script or + command. For the toplevel script it is usually + the name of the script, for commands below it it's + the name of the script. + :param obj: an arbitrary object of user data. + :param auto_envvar_prefix: the prefix to use for automatic environment + variables. If this is `None` then reading + from environment variables is disabled. This + does not affect manually set environment + variables which are always read. + :param default_map: a dictionary (like object) with default values + for parameters. + :param terminal_width: the width of the terminal. The default is + inherit from parent context. If no context + defines the terminal width then auto + detection will be applied. + :param max_content_width: the maximum width for content rendered by + Click (this currently only affects help + pages). This defaults to 80 characters if + not overridden. In other words: even if the + terminal is larger than that, Click will not + format things wider than 80 characters by + default. In addition to that, formatters might + add some safety mapping on the right. + :param resilient_parsing: if this flag is enabled then Click will + parse without any interactivity or callback + invocation. Default values will also be + ignored. This is useful for implementing + things such as completion support. + :param allow_extra_args: if this is set to `True` then extra arguments + at the end will not raise an error and will be + kept on the context. The default is to inherit + from the command. + :param allow_interspersed_args: if this is set to `False` then options + and arguments cannot be mixed. The + default is to inherit from the command. + :param ignore_unknown_options: instructs click to ignore options it does + not know and keeps them for later + processing. + :param help_option_names: optionally a list of strings that define how + the default help parameter is named. The + default is ``['--help']``. + :param token_normalize_func: an optional function that is used to + normalize tokens (options, choices, + etc.). This for instance can be used to + implement case insensitive behavior. + :param color: controls if the terminal supports ANSI colors or not. The + default is autodetection. This is only needed if ANSI + codes are used in texts that Click prints which is by + default not the case. This for instance would affect + help output. + :param show_default: Show the default value for commands. If this + value is not set, it defaults to the value from the parent + context. ``Command.show_default`` overrides this default for the + specific command. + + .. versionchanged:: 8.1 + The ``show_default`` parameter is overridden by + ``Command.show_default``, instead of the other way around. + + .. versionchanged:: 8.0 + The ``show_default`` parameter defaults to the value from the + parent context. + + .. versionchanged:: 7.1 + Added the ``show_default`` parameter. + + .. versionchanged:: 4.0 + Added the ``color``, ``ignore_unknown_options``, and + ``max_content_width`` parameters. + + .. versionchanged:: 3.0 + Added the ``allow_extra_args`` and ``allow_interspersed_args`` + parameters. + + .. versionchanged:: 2.0 + Added the ``resilient_parsing``, ``help_option_names``, and + ``token_normalize_func`` parameters. + """ + + #: The formatter class to create with :meth:`make_formatter`. + #: + #: .. versionadded:: 8.0 + formatter_class: t.Type["HelpFormatter"] = HelpFormatter + + def __init__( + self, + command: "Command", + parent: t.Optional["Context"] = None, + info_name: t.Optional[str] = None, + obj: t.Optional[t.Any] = None, + auto_envvar_prefix: t.Optional[str] = None, + default_map: t.Optional[t.MutableMapping[str, t.Any]] = None, + terminal_width: t.Optional[int] = None, + max_content_width: t.Optional[int] = None, + resilient_parsing: bool = False, + allow_extra_args: t.Optional[bool] = None, + allow_interspersed_args: t.Optional[bool] = None, + ignore_unknown_options: t.Optional[bool] = None, + help_option_names: t.Optional[t.List[str]] = None, + token_normalize_func: t.Optional[t.Callable[[str], str]] = None, + color: t.Optional[bool] = None, + show_default: t.Optional[bool] = None, + ) -> None: + #: the parent context or `None` if none exists. + self.parent = parent + #: the :class:`Command` for this context. + self.command = command + #: the descriptive information name + self.info_name = info_name + #: Map of parameter names to their parsed values. Parameters + #: with ``expose_value=False`` are not stored. + self.params: t.Dict[str, t.Any] = {} + #: the leftover arguments. + self.args: t.List[str] = [] + #: protected arguments. These are arguments that are prepended + #: to `args` when certain parsing scenarios are encountered but + #: must be never propagated to another arguments. This is used + #: to implement nested parsing. + self.protected_args: t.List[str] = [] + #: the collected prefixes of the command's options. + self._opt_prefixes: t.Set[str] = set(parent._opt_prefixes) if parent else set() + + if obj is None and parent is not None: + obj = parent.obj + + #: the user object stored. + self.obj: t.Any = obj + self._meta: t.Dict[str, t.Any] = getattr(parent, "meta", {}) + + #: A dictionary (-like object) with defaults for parameters. + if ( + default_map is None + and info_name is not None + and parent is not None + and parent.default_map is not None + ): + default_map = parent.default_map.get(info_name) + + self.default_map: t.Optional[t.MutableMapping[str, t.Any]] = default_map + + #: This flag indicates if a subcommand is going to be executed. A + #: group callback can use this information to figure out if it's + #: being executed directly or because the execution flow passes + #: onwards to a subcommand. By default it's None, but it can be + #: the name of the subcommand to execute. + #: + #: If chaining is enabled this will be set to ``'*'`` in case + #: any commands are executed. It is however not possible to + #: figure out which ones. If you require this knowledge you + #: should use a :func:`result_callback`. + self.invoked_subcommand: t.Optional[str] = None + + if terminal_width is None and parent is not None: + terminal_width = parent.terminal_width + + #: The width of the terminal (None is autodetection). + self.terminal_width: t.Optional[int] = terminal_width + + if max_content_width is None and parent is not None: + max_content_width = parent.max_content_width + + #: The maximum width of formatted content (None implies a sensible + #: default which is 80 for most things). + self.max_content_width: t.Optional[int] = max_content_width + + if allow_extra_args is None: + allow_extra_args = command.allow_extra_args + + #: Indicates if the context allows extra args or if it should + #: fail on parsing. + #: + #: .. versionadded:: 3.0 + self.allow_extra_args = allow_extra_args + + if allow_interspersed_args is None: + allow_interspersed_args = command.allow_interspersed_args + + #: Indicates if the context allows mixing of arguments and + #: options or not. + #: + #: .. versionadded:: 3.0 + self.allow_interspersed_args: bool = allow_interspersed_args + + if ignore_unknown_options is None: + ignore_unknown_options = command.ignore_unknown_options + + #: Instructs click to ignore options that a command does not + #: understand and will store it on the context for later + #: processing. This is primarily useful for situations where you + #: want to call into external programs. Generally this pattern is + #: strongly discouraged because it's not possibly to losslessly + #: forward all arguments. + #: + #: .. versionadded:: 4.0 + self.ignore_unknown_options: bool = ignore_unknown_options + + if help_option_names is None: + if parent is not None: + help_option_names = parent.help_option_names + else: + help_option_names = ["--help"] + + #: The names for the help options. + self.help_option_names: t.List[str] = help_option_names + + if token_normalize_func is None and parent is not None: + token_normalize_func = parent.token_normalize_func + + #: An optional normalization function for tokens. This is + #: options, choices, commands etc. + self.token_normalize_func: t.Optional[t.Callable[[str], str]] = ( + token_normalize_func + ) + + #: Indicates if resilient parsing is enabled. In that case Click + #: will do its best to not cause any failures and default values + #: will be ignored. Useful for completion. + self.resilient_parsing: bool = resilient_parsing + + # If there is no envvar prefix yet, but the parent has one and + # the command on this level has a name, we can expand the envvar + # prefix automatically. + if auto_envvar_prefix is None: + if ( + parent is not None + and parent.auto_envvar_prefix is not None + and self.info_name is not None + ): + auto_envvar_prefix = ( + f"{parent.auto_envvar_prefix}_{self.info_name.upper()}" + ) + else: + auto_envvar_prefix = auto_envvar_prefix.upper() + + if auto_envvar_prefix is not None: + auto_envvar_prefix = auto_envvar_prefix.replace("-", "_") + + self.auto_envvar_prefix: t.Optional[str] = auto_envvar_prefix + + if color is None and parent is not None: + color = parent.color + + #: Controls if styling output is wanted or not. + self.color: t.Optional[bool] = color + + if show_default is None and parent is not None: + show_default = parent.show_default + + #: Show option default values when formatting help text. + self.show_default: t.Optional[bool] = show_default + + self._close_callbacks: t.List[t.Callable[[], t.Any]] = [] + self._depth = 0 + self._parameter_source: t.Dict[str, ParameterSource] = {} + self._exit_stack = ExitStack() + + def to_info_dict(self) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. This traverses the entire CLI + structure. + + .. code-block:: python + + with Context(cli) as ctx: + info = ctx.to_info_dict() + + .. versionadded:: 8.0 + """ + return { + "command": self.command.to_info_dict(self), + "info_name": self.info_name, + "allow_extra_args": self.allow_extra_args, + "allow_interspersed_args": self.allow_interspersed_args, + "ignore_unknown_options": self.ignore_unknown_options, + "auto_envvar_prefix": self.auto_envvar_prefix, + } + + def __enter__(self) -> "Context": + self._depth += 1 + push_context(self) + return self + + def __exit__( + self, + exc_type: t.Optional[t.Type[BaseException]], + exc_value: t.Optional[BaseException], + tb: t.Optional[TracebackType], + ) -> None: + self._depth -= 1 + if self._depth == 0: + self.close() + pop_context() + + @contextmanager + def scope(self, cleanup: bool = True) -> t.Iterator["Context"]: + """This helper method can be used with the context object to promote + it to the current thread local (see :func:`get_current_context`). + The default behavior of this is to invoke the cleanup functions which + can be disabled by setting `cleanup` to `False`. The cleanup + functions are typically used for things such as closing file handles. + + If the cleanup is intended the context object can also be directly + used as a context manager. + + Example usage:: + + with ctx.scope(): + assert get_current_context() is ctx + + This is equivalent:: + + with ctx: + assert get_current_context() is ctx + + .. versionadded:: 5.0 + + :param cleanup: controls if the cleanup functions should be run or + not. The default is to run these functions. In + some situations the context only wants to be + temporarily pushed in which case this can be disabled. + Nested pushes automatically defer the cleanup. + """ + if not cleanup: + self._depth += 1 + try: + with self as rv: + yield rv + finally: + if not cleanup: + self._depth -= 1 + + @property + def meta(self) -> t.Dict[str, t.Any]: + """This is a dictionary which is shared with all the contexts + that are nested. It exists so that click utilities can store some + state here if they need to. It is however the responsibility of + that code to manage this dictionary well. + + The keys are supposed to be unique dotted strings. For instance + module paths are a good choice for it. What is stored in there is + irrelevant for the operation of click. However what is important is + that code that places data here adheres to the general semantics of + the system. + + Example usage:: + + LANG_KEY = f'{__name__}.lang' + + def set_language(value): + ctx = get_current_context() + ctx.meta[LANG_KEY] = value + + def get_language(): + return get_current_context().meta.get(LANG_KEY, 'en_US') + + .. versionadded:: 5.0 + """ + return self._meta + + def make_formatter(self) -> HelpFormatter: + """Creates the :class:`~click.HelpFormatter` for the help and + usage output. + + To quickly customize the formatter class used without overriding + this method, set the :attr:`formatter_class` attribute. + + .. versionchanged:: 8.0 + Added the :attr:`formatter_class` attribute. + """ + return self.formatter_class( + width=self.terminal_width, max_width=self.max_content_width + ) + + def with_resource(self, context_manager: t.ContextManager[V]) -> V: + """Register a resource as if it were used in a ``with`` + statement. The resource will be cleaned up when the context is + popped. + + Uses :meth:`contextlib.ExitStack.enter_context`. It calls the + resource's ``__enter__()`` method and returns the result. When + the context is popped, it closes the stack, which calls the + resource's ``__exit__()`` method. + + To register a cleanup function for something that isn't a + context manager, use :meth:`call_on_close`. Or use something + from :mod:`contextlib` to turn it into a context manager first. + + .. code-block:: python + + @click.group() + @click.option("--name") + @click.pass_context + def cli(ctx): + ctx.obj = ctx.with_resource(connect_db(name)) + + :param context_manager: The context manager to enter. + :return: Whatever ``context_manager.__enter__()`` returns. + + .. versionadded:: 8.0 + """ + return self._exit_stack.enter_context(context_manager) + + def call_on_close(self, f: t.Callable[..., t.Any]) -> t.Callable[..., t.Any]: + """Register a function to be called when the context tears down. + + This can be used to close resources opened during the script + execution. Resources that support Python's context manager + protocol which would be used in a ``with`` statement should be + registered with :meth:`with_resource` instead. + + :param f: The function to execute on teardown. + """ + return self._exit_stack.callback(f) + + def close(self) -> None: + """Invoke all close callbacks registered with + :meth:`call_on_close`, and exit all context managers entered + with :meth:`with_resource`. + """ + self._exit_stack.close() + # In case the context is reused, create a new exit stack. + self._exit_stack = ExitStack() + + @property + def command_path(self) -> str: + """The computed command path. This is used for the ``usage`` + information on the help page. It's automatically created by + combining the info names of the chain of contexts to the root. + """ + rv = "" + if self.info_name is not None: + rv = self.info_name + if self.parent is not None: + parent_command_path = [self.parent.command_path] + + if isinstance(self.parent.command, Command): + for param in self.parent.command.get_params(self): + parent_command_path.extend(param.get_usage_pieces(self)) + + rv = f"{' '.join(parent_command_path)} {rv}" + return rv.lstrip() + + def find_root(self) -> "Context": + """Finds the outermost context.""" + node = self + while node.parent is not None: + node = node.parent + return node + + def find_object(self, object_type: t.Type[V]) -> t.Optional[V]: + """Finds the closest object of a given type.""" + node: t.Optional[Context] = self + + while node is not None: + if isinstance(node.obj, object_type): + return node.obj + + node = node.parent + + return None + + def ensure_object(self, object_type: t.Type[V]) -> V: + """Like :meth:`find_object` but sets the innermost object to a + new instance of `object_type` if it does not exist. + """ + rv = self.find_object(object_type) + if rv is None: + self.obj = rv = object_type() + return rv + + @t.overload + def lookup_default( + self, name: str, call: "te.Literal[True]" = True + ) -> t.Optional[t.Any]: ... + + @t.overload + def lookup_default( + self, name: str, call: "te.Literal[False]" = ... + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: ... + + def lookup_default(self, name: str, call: bool = True) -> t.Optional[t.Any]: + """Get the default for a parameter from :attr:`default_map`. + + :param name: Name of the parameter. + :param call: If the default is a callable, call it. Disable to + return the callable instead. + + .. versionchanged:: 8.0 + Added the ``call`` parameter. + """ + if self.default_map is not None: + value = self.default_map.get(name) + + if call and callable(value): + return value() + + return value + + return None + + def fail(self, message: str) -> "te.NoReturn": + """Aborts the execution of the program with a specific error + message. + + :param message: the error message to fail with. + """ + raise UsageError(message, self) + + def abort(self) -> "te.NoReturn": + """Aborts the script.""" + raise Abort() + + def exit(self, code: int = 0) -> "te.NoReturn": + """Exits the application with a given exit code.""" + raise Exit(code) + + def get_usage(self) -> str: + """Helper method to get formatted usage string for the current + context and command. + """ + return self.command.get_usage(self) + + def get_help(self) -> str: + """Helper method to get formatted help page for the current + context and command. + """ + return self.command.get_help(self) + + def _make_sub_context(self, command: "Command") -> "Context": + """Create a new context of the same type as this context, but + for a new command. + + :meta private: + """ + return type(self)(command, info_name=command.name, parent=self) + + @t.overload + def invoke( + __self, + __callback: "t.Callable[..., V]", + *args: t.Any, + **kwargs: t.Any, + ) -> V: ... + + @t.overload + def invoke( + __self, + __callback: "Command", + *args: t.Any, + **kwargs: t.Any, + ) -> t.Any: ... + + def invoke( + __self, + __callback: t.Union["Command", "t.Callable[..., V]"], + *args: t.Any, + **kwargs: t.Any, + ) -> t.Union[t.Any, V]: + """Invokes a command callback in exactly the way it expects. There + are two ways to invoke this method: + + 1. the first argument can be a callback and all other arguments and + keyword arguments are forwarded directly to the function. + 2. the first argument is a click command object. In that case all + arguments are forwarded as well but proper click parameters + (options and click arguments) must be keyword arguments and Click + will fill in defaults. + + Note that before Click 3.2 keyword arguments were not properly filled + in against the intention of this code and no context was created. For + more information about this change and why it was done in a bugfix + release see :ref:`upgrade-to-3.2`. + + .. versionchanged:: 8.0 + All ``kwargs`` are tracked in :attr:`params` so they will be + passed if :meth:`forward` is called at multiple levels. + """ + if isinstance(__callback, Command): + other_cmd = __callback + + if other_cmd.callback is None: + raise TypeError( + "The given command does not have a callback that can be invoked." + ) + else: + __callback = t.cast("t.Callable[..., V]", other_cmd.callback) + + ctx = __self._make_sub_context(other_cmd) + + for param in other_cmd.params: + if param.name not in kwargs and param.expose_value: + kwargs[param.name] = param.type_cast_value( # type: ignore + ctx, param.get_default(ctx) + ) + + # Track all kwargs as params, so that forward() will pass + # them on in subsequent calls. + ctx.params.update(kwargs) + else: + ctx = __self + + with augment_usage_errors(__self): + with ctx: + return __callback(*args, **kwargs) + + def forward(__self, __cmd: "Command", *args: t.Any, **kwargs: t.Any) -> t.Any: + """Similar to :meth:`invoke` but fills in default keyword + arguments from the current context if the other command expects + it. This cannot invoke callbacks directly, only other commands. + + .. versionchanged:: 8.0 + All ``kwargs`` are tracked in :attr:`params` so they will be + passed if ``forward`` is called at multiple levels. + """ + # Can only forward to other commands, not direct callbacks. + if not isinstance(__cmd, Command): + raise TypeError("Callback is not a command.") + + for param in __self.params: + if param not in kwargs: + kwargs[param] = __self.params[param] + + return __self.invoke(__cmd, *args, **kwargs) + + def set_parameter_source(self, name: str, source: ParameterSource) -> None: + """Set the source of a parameter. This indicates the location + from which the value of the parameter was obtained. + + :param name: The name of the parameter. + :param source: A member of :class:`~click.core.ParameterSource`. + """ + self._parameter_source[name] = source + + def get_parameter_source(self, name: str) -> t.Optional[ParameterSource]: + """Get the source of a parameter. This indicates the location + from which the value of the parameter was obtained. + + This can be useful for determining when a user specified a value + on the command line that is the same as the default value. It + will be :attr:`~click.core.ParameterSource.DEFAULT` only if the + value was actually taken from the default. + + :param name: The name of the parameter. + :rtype: ParameterSource + + .. versionchanged:: 8.0 + Returns ``None`` if the parameter was not provided from any + source. + """ + return self._parameter_source.get(name) + + +class BaseCommand: + """The base command implements the minimal API contract of commands. + Most code will never use this as it does not implement a lot of useful + functionality but it can act as the direct subclass of alternative + parsing methods that do not depend on the Click parser. + + For instance, this can be used to bridge Click and other systems like + argparse or docopt. + + Because base commands do not implement a lot of the API that other + parts of Click take for granted, they are not supported for all + operations. For instance, they cannot be used with the decorators + usually and they have no built-in callback system. + + .. versionchanged:: 2.0 + Added the `context_settings` parameter. + + :param name: the name of the command to use unless a group overrides it. + :param context_settings: an optional dictionary with defaults that are + passed to the context object. + """ + + #: The context class to create with :meth:`make_context`. + #: + #: .. versionadded:: 8.0 + context_class: t.Type[Context] = Context + #: the default for the :attr:`Context.allow_extra_args` flag. + allow_extra_args = False + #: the default for the :attr:`Context.allow_interspersed_args` flag. + allow_interspersed_args = True + #: the default for the :attr:`Context.ignore_unknown_options` flag. + ignore_unknown_options = False + + def __init__( + self, + name: t.Optional[str], + context_settings: t.Optional[t.MutableMapping[str, t.Any]] = None, + ) -> None: + #: the name the command thinks it has. Upon registering a command + #: on a :class:`Group` the group will default the command name + #: with this information. You should instead use the + #: :class:`Context`\'s :attr:`~Context.info_name` attribute. + self.name = name + + if context_settings is None: + context_settings = {} + + #: an optional dictionary with defaults passed to the context. + self.context_settings: t.MutableMapping[str, t.Any] = context_settings + + def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. This traverses the entire structure + below this command. + + Use :meth:`click.Context.to_info_dict` to traverse the entire + CLI structure. + + :param ctx: A :class:`Context` representing this command. + + .. versionadded:: 8.0 + """ + return {"name": self.name} + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} {self.name}>" + + def get_usage(self, ctx: Context) -> str: + raise NotImplementedError("Base commands cannot get usage") + + def get_help(self, ctx: Context) -> str: + raise NotImplementedError("Base commands cannot get help") + + def make_context( + self, + info_name: t.Optional[str], + args: t.List[str], + parent: t.Optional[Context] = None, + **extra: t.Any, + ) -> Context: + """This function when given an info name and arguments will kick + off the parsing and create a new :class:`Context`. It does not + invoke the actual command callback though. + + To quickly customize the context class used without overriding + this method, set the :attr:`context_class` attribute. + + :param info_name: the info name for this invocation. Generally this + is the most descriptive name for the script or + command. For the toplevel script it's usually + the name of the script, for commands below it's + the name of the command. + :param args: the arguments to parse as list of strings. + :param parent: the parent context if available. + :param extra: extra keyword arguments forwarded to the context + constructor. + + .. versionchanged:: 8.0 + Added the :attr:`context_class` attribute. + """ + for key, value in self.context_settings.items(): + if key not in extra: + extra[key] = value + + ctx = self.context_class( + self, # type: ignore[arg-type] + info_name=info_name, + parent=parent, + **extra, + ) + + with ctx.scope(cleanup=False): + self.parse_args(ctx, args) + return ctx + + def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: + """Given a context and a list of arguments this creates the parser + and parses the arguments, then modifies the context as necessary. + This is automatically invoked by :meth:`make_context`. + """ + raise NotImplementedError("Base commands do not know how to parse arguments.") + + def invoke(self, ctx: Context) -> t.Any: + """Given a context, this invokes the command. The default + implementation is raising a not implemented error. + """ + raise NotImplementedError("Base commands are not invocable by default") + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. Looks + at the names of chained multi-commands. + + Any command could be part of a chained multi-command, so sibling + commands are valid at any point during command completion. Other + command classes will return more completions. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + results: t.List[CompletionItem] = [] + + while ctx.parent is not None: + ctx = ctx.parent + + if isinstance(ctx.command, MultiCommand) and ctx.command.chain: + results.extend( + CompletionItem(name, help=command.get_short_help_str()) + for name, command in _complete_visible_commands(ctx, incomplete) + if name not in ctx.protected_args + ) + + return results + + @t.overload + def main( + self, + args: t.Optional[t.Sequence[str]] = None, + prog_name: t.Optional[str] = None, + complete_var: t.Optional[str] = None, + standalone_mode: "te.Literal[True]" = True, + **extra: t.Any, + ) -> "te.NoReturn": ... + + @t.overload + def main( + self, + args: t.Optional[t.Sequence[str]] = None, + prog_name: t.Optional[str] = None, + complete_var: t.Optional[str] = None, + standalone_mode: bool = ..., + **extra: t.Any, + ) -> t.Any: ... + + def main( + self, + args: t.Optional[t.Sequence[str]] = None, + prog_name: t.Optional[str] = None, + complete_var: t.Optional[str] = None, + standalone_mode: bool = True, + windows_expand_args: bool = True, + **extra: t.Any, + ) -> t.Any: + """This is the way to invoke a script with all the bells and + whistles as a command line application. This will always terminate + the application after a call. If this is not wanted, ``SystemExit`` + needs to be caught. + + This method is also available by directly calling the instance of + a :class:`Command`. + + :param args: the arguments that should be used for parsing. If not + provided, ``sys.argv[1:]`` is used. + :param prog_name: the program name that should be used. By default + the program name is constructed by taking the file + name from ``sys.argv[0]``. + :param complete_var: the environment variable that controls the + bash completion support. The default is + ``"__COMPLETE"`` with prog_name in + uppercase. + :param standalone_mode: the default behavior is to invoke the script + in standalone mode. Click will then + handle exceptions and convert them into + error messages and the function will never + return but shut down the interpreter. If + this is set to `False` they will be + propagated to the caller and the return + value of this function is the return value + of :meth:`invoke`. + :param windows_expand_args: Expand glob patterns, user dir, and + env vars in command line args on Windows. + :param extra: extra keyword arguments are forwarded to the context + constructor. See :class:`Context` for more information. + + .. versionchanged:: 8.0.1 + Added the ``windows_expand_args`` parameter to allow + disabling command line arg expansion on Windows. + + .. versionchanged:: 8.0 + When taking arguments from ``sys.argv`` on Windows, glob + patterns, user dir, and env vars are expanded. + + .. versionchanged:: 3.0 + Added the ``standalone_mode`` parameter. + """ + if args is None: + args = sys.argv[1:] + + if os.name == "nt" and windows_expand_args: + args = _expand_args(args) + else: + args = list(args) + + if prog_name is None: + prog_name = _detect_program_name() + + # Process shell completion requests and exit early. + self._main_shell_completion(extra, prog_name, complete_var) + + try: + try: + with self.make_context(prog_name, args, **extra) as ctx: + rv = self.invoke(ctx) + if not standalone_mode: + return rv + # it's not safe to `ctx.exit(rv)` here! + # note that `rv` may actually contain data like "1" which + # has obvious effects + # more subtle case: `rv=[None, None]` can come out of + # chained commands which all returned `None` -- so it's not + # even always obvious that `rv` indicates success/failure + # by its truthiness/falsiness + ctx.exit() + except (EOFError, KeyboardInterrupt) as e: + echo(file=sys.stderr) + raise Abort() from e + except ClickException as e: + if not standalone_mode: + raise + e.show() + sys.exit(e.exit_code) + except OSError as e: + if e.errno == errno.EPIPE: + sys.stdout = t.cast(t.TextIO, PacifyFlushWrapper(sys.stdout)) + sys.stderr = t.cast(t.TextIO, PacifyFlushWrapper(sys.stderr)) + sys.exit(1) + else: + raise + except Exit as e: + if standalone_mode: + sys.exit(e.exit_code) + else: + # in non-standalone mode, return the exit code + # note that this is only reached if `self.invoke` above raises + # an Exit explicitly -- thus bypassing the check there which + # would return its result + # the results of non-standalone execution may therefore be + # somewhat ambiguous: if there are codepaths which lead to + # `ctx.exit(1)` and to `return 1`, the caller won't be able to + # tell the difference between the two + return e.exit_code + except Abort: + if not standalone_mode: + raise + echo(_("Aborted!"), file=sys.stderr) + sys.exit(1) + + def _main_shell_completion( + self, + ctx_args: t.MutableMapping[str, t.Any], + prog_name: str, + complete_var: t.Optional[str] = None, + ) -> None: + """Check if the shell is asking for tab completion, process + that, then exit early. Called from :meth:`main` before the + program is invoked. + + :param prog_name: Name of the executable in the shell. + :param complete_var: Name of the environment variable that holds + the completion instruction. Defaults to + ``_{PROG_NAME}_COMPLETE``. + + .. versionchanged:: 8.2.0 + Dots (``.``) in ``prog_name`` are replaced with underscores (``_``). + """ + if complete_var is None: + complete_name = prog_name.replace("-", "_").replace(".", "_") + complete_var = f"_{complete_name}_COMPLETE".upper() + + instruction = os.environ.get(complete_var) + + if not instruction: + return + + from .shell_completion import shell_complete + + rv = shell_complete(self, ctx_args, prog_name, complete_var, instruction) + sys.exit(rv) + + def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Any: + """Alias for :meth:`main`.""" + return self.main(*args, **kwargs) + + +class Command(BaseCommand): + """Commands are the basic building block of command line interfaces in + Click. A basic command handles command line parsing and might dispatch + more parsing to commands nested below it. + + :param name: the name of the command to use unless a group overrides it. + :param context_settings: an optional dictionary with defaults that are + passed to the context object. + :param callback: the callback to invoke. This is optional. + :param params: the parameters to register with this command. This can + be either :class:`Option` or :class:`Argument` objects. + :param help: the help string to use for this command. + :param epilog: like the help string but it's printed at the end of the + help page after everything else. + :param short_help: the short help to use for this command. This is + shown on the command listing of the parent command. + :param add_help_option: by default each command registers a ``--help`` + option. This can be disabled by this parameter. + :param no_args_is_help: this controls what happens if no arguments are + provided. This option is disabled by default. + If enabled this will add ``--help`` as argument + if no arguments are passed + :param hidden: hide this command from help outputs. + + :param deprecated: issues a message indicating that + the command is deprecated. + + .. versionchanged:: 8.1 + ``help``, ``epilog``, and ``short_help`` are stored unprocessed, + all formatting is done when outputting help text, not at init, + and is done even if not using the ``@command`` decorator. + + .. versionchanged:: 8.0 + Added a ``repr`` showing the command name. + + .. versionchanged:: 7.1 + Added the ``no_args_is_help`` parameter. + + .. versionchanged:: 2.0 + Added the ``context_settings`` parameter. + """ + + def __init__( + self, + name: t.Optional[str], + context_settings: t.Optional[t.MutableMapping[str, t.Any]] = None, + callback: t.Optional[t.Callable[..., t.Any]] = None, + params: t.Optional[t.List["Parameter"]] = None, + help: t.Optional[str] = None, + epilog: t.Optional[str] = None, + short_help: t.Optional[str] = None, + options_metavar: t.Optional[str] = "[OPTIONS]", + add_help_option: bool = True, + no_args_is_help: bool = False, + hidden: bool = False, + deprecated: bool = False, + ) -> None: + super().__init__(name, context_settings) + #: the callback to execute when the command fires. This might be + #: `None` in which case nothing happens. + self.callback = callback + #: the list of parameters for this command in the order they + #: should show up in the help page and execute. Eager parameters + #: will automatically be handled before non eager ones. + self.params: t.List[Parameter] = params or [] + self.help = help + self.epilog = epilog + self.options_metavar = options_metavar + self.short_help = short_help + self.add_help_option = add_help_option + self._help_option: t.Optional[HelpOption] = None + self.no_args_is_help = no_args_is_help + self.hidden = hidden + self.deprecated = deprecated + + def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict(ctx) + info_dict.update( + params=[param.to_info_dict() for param in self.get_params(ctx)], + help=self.help, + epilog=self.epilog, + short_help=self.short_help, + hidden=self.hidden, + deprecated=self.deprecated, + ) + return info_dict + + def get_usage(self, ctx: Context) -> str: + """Formats the usage line into a string and returns it. + + Calls :meth:`format_usage` internally. + """ + formatter = ctx.make_formatter() + self.format_usage(ctx, formatter) + return formatter.getvalue().rstrip("\n") + + def get_params(self, ctx: Context) -> t.List["Parameter"]: + rv = self.params + help_option = self.get_help_option(ctx) + + if help_option is not None: + rv = [*rv, help_option] + + return rv + + def format_usage(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the usage line into the formatter. + + This is a low-level method called by :meth:`get_usage`. + """ + pieces = self.collect_usage_pieces(ctx) + formatter.write_usage(ctx.command_path, " ".join(pieces)) + + def collect_usage_pieces(self, ctx: Context) -> t.List[str]: + """Returns all the pieces that go into the usage line and returns + it as a list of strings. + """ + rv = [self.options_metavar] if self.options_metavar else [] + + for param in self.get_params(ctx): + rv.extend(param.get_usage_pieces(ctx)) + + return rv + + def get_help_option_names(self, ctx: Context) -> t.List[str]: + """Returns the names for the help option.""" + all_names = set(ctx.help_option_names) + for param in self.params: + all_names.difference_update(param.opts) + all_names.difference_update(param.secondary_opts) + return list(all_names) + + def get_help_option(self, ctx: Context) -> t.Optional["Option"]: + """Returns the help option object. + + Unless ``add_help_option`` is ``False``. + + .. versionchanged:: 8.1.8 + The help option is now cached to avoid creating it multiple times. + """ + help_options = self.get_help_option_names(ctx) + + if not help_options or not self.add_help_option: + return None + + # Cache the help option object in private _help_option attribute to + # avoid creating it multiple times. Not doing this will break the + # callback odering by iter_params_for_processing(), which relies on + # object comparison. + if self._help_option is None: + # Avoid circular import. + from .decorators import HelpOption + + self._help_option = HelpOption(help_options) + + return self._help_option + + def make_parser(self, ctx: Context) -> OptionParser: + """Creates the underlying option parser for this command.""" + parser = OptionParser(ctx) + for param in self.get_params(ctx): + param.add_to_parser(parser, ctx) + return parser + + def get_help(self, ctx: Context) -> str: + """Formats the help into a string and returns it. + + Calls :meth:`format_help` internally. + """ + formatter = ctx.make_formatter() + self.format_help(ctx, formatter) + return formatter.getvalue().rstrip("\n") + + def get_short_help_str(self, limit: int = 45) -> str: + """Gets short help for the command or makes it by shortening the + long help string. + """ + if self.short_help: + text = inspect.cleandoc(self.short_help) + elif self.help: + text = make_default_short_help(self.help, limit) + else: + text = "" + + if self.deprecated: + text = _("(Deprecated) {text}").format(text=text) + + return text.strip() + + def format_help(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the help into the formatter if it exists. + + This is a low-level method called by :meth:`get_help`. + + This calls the following methods: + + - :meth:`format_usage` + - :meth:`format_help_text` + - :meth:`format_options` + - :meth:`format_epilog` + """ + self.format_usage(ctx, formatter) + self.format_help_text(ctx, formatter) + self.format_options(ctx, formatter) + self.format_epilog(ctx, formatter) + + def format_help_text(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the help text to the formatter if it exists.""" + if self.help is not None: + # truncate the help text to the first form feed + text = inspect.cleandoc(self.help).partition("\f")[0] + else: + text = "" + + if self.deprecated: + text = _("(Deprecated) {text}").format(text=text) + + if text: + formatter.write_paragraph() + + with formatter.indentation(): + formatter.write_text(text) + + def format_options(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes all the options into the formatter if they exist.""" + opts = [] + for param in self.get_params(ctx): + rv = param.get_help_record(ctx) + if rv is not None: + opts.append(rv) + + if opts: + with formatter.section(_("Options")): + formatter.write_dl(opts) + + def format_epilog(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the epilog into the formatter if it exists.""" + if self.epilog: + epilog = inspect.cleandoc(self.epilog) + formatter.write_paragraph() + + with formatter.indentation(): + formatter.write_text(epilog) + + def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: + if not args and self.no_args_is_help and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + parser = self.make_parser(ctx) + opts, args, param_order = parser.parse_args(args=args) + + for param in iter_params_for_processing(param_order, self.get_params(ctx)): + value, args = param.handle_parse_result(ctx, opts, args) + + if args and not ctx.allow_extra_args and not ctx.resilient_parsing: + ctx.fail( + ngettext( + "Got unexpected extra argument ({args})", + "Got unexpected extra arguments ({args})", + len(args), + ).format(args=" ".join(map(str, args))) + ) + + ctx.args = args + ctx._opt_prefixes.update(parser._opt_prefixes) + return args + + def invoke(self, ctx: Context) -> t.Any: + """Given a context, this invokes the attached callback (if it exists) + in the right way. + """ + if self.deprecated: + message = _( + "DeprecationWarning: The command {name!r} is deprecated." + ).format(name=self.name) + echo(style(message, fg="red"), err=True) + + if self.callback is not None: + return ctx.invoke(self.callback, **ctx.params) + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. Looks + at the names of options and chained multi-commands. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + results: t.List[CompletionItem] = [] + + if incomplete and not incomplete[0].isalnum(): + for param in self.get_params(ctx): + if ( + not isinstance(param, Option) + or param.hidden + or ( + not param.multiple + and ctx.get_parameter_source(param.name) # type: ignore + is ParameterSource.COMMANDLINE + ) + ): + continue + + results.extend( + CompletionItem(name, help=param.help) + for name in [*param.opts, *param.secondary_opts] + if name.startswith(incomplete) + ) + + results.extend(super().shell_complete(ctx, incomplete)) + return results + + +class MultiCommand(Command): + """A multi command is the basic implementation of a command that + dispatches to subcommands. The most common version is the + :class:`Group`. + + :param invoke_without_command: this controls how the multi command itself + is invoked. By default it's only invoked + if a subcommand is provided. + :param no_args_is_help: this controls what happens if no arguments are + provided. This option is enabled by default if + `invoke_without_command` is disabled or disabled + if it's enabled. If enabled this will add + ``--help`` as argument if no arguments are + passed. + :param subcommand_metavar: the string that is used in the documentation + to indicate the subcommand place. + :param chain: if this is set to `True` chaining of multiple subcommands + is enabled. This restricts the form of commands in that + they cannot have optional arguments but it allows + multiple commands to be chained together. + :param result_callback: The result callback to attach to this multi + command. This can be set or changed later with the + :meth:`result_callback` decorator. + :param attrs: Other command arguments described in :class:`Command`. + """ + + allow_extra_args = True + allow_interspersed_args = False + + def __init__( + self, + name: t.Optional[str] = None, + invoke_without_command: bool = False, + no_args_is_help: t.Optional[bool] = None, + subcommand_metavar: t.Optional[str] = None, + chain: bool = False, + result_callback: t.Optional[t.Callable[..., t.Any]] = None, + **attrs: t.Any, + ) -> None: + super().__init__(name, **attrs) + + if no_args_is_help is None: + no_args_is_help = not invoke_without_command + + self.no_args_is_help = no_args_is_help + self.invoke_without_command = invoke_without_command + + if subcommand_metavar is None: + if chain: + subcommand_metavar = "COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]..." + else: + subcommand_metavar = "COMMAND [ARGS]..." + + self.subcommand_metavar = subcommand_metavar + self.chain = chain + # The result callback that is stored. This can be set or + # overridden with the :func:`result_callback` decorator. + self._result_callback = result_callback + + if self.chain: + for param in self.params: + if isinstance(param, Argument) and not param.required: + raise RuntimeError( + "Multi commands in chain mode cannot have" + " optional arguments." + ) + + def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict(ctx) + commands = {} + + for name in self.list_commands(ctx): + command = self.get_command(ctx, name) + + if command is None: + continue + + sub_ctx = ctx._make_sub_context(command) + + with sub_ctx.scope(cleanup=False): + commands[name] = command.to_info_dict(sub_ctx) + + info_dict.update(commands=commands, chain=self.chain) + return info_dict + + def collect_usage_pieces(self, ctx: Context) -> t.List[str]: + rv = super().collect_usage_pieces(ctx) + rv.append(self.subcommand_metavar) + return rv + + def format_options(self, ctx: Context, formatter: HelpFormatter) -> None: + super().format_options(ctx, formatter) + self.format_commands(ctx, formatter) + + def result_callback(self, replace: bool = False) -> t.Callable[[F], F]: + """Adds a result callback to the command. By default if a + result callback is already registered this will chain them but + this can be disabled with the `replace` parameter. The result + callback is invoked with the return value of the subcommand + (or the list of return values from all subcommands if chaining + is enabled) as well as the parameters as they would be passed + to the main callback. + + Example:: + + @click.group() + @click.option('-i', '--input', default=23) + def cli(input): + return 42 + + @cli.result_callback() + def process_result(result, input): + return result + input + + :param replace: if set to `True` an already existing result + callback will be removed. + + .. versionchanged:: 8.0 + Renamed from ``resultcallback``. + + .. versionadded:: 3.0 + """ + + def decorator(f: F) -> F: + old_callback = self._result_callback + + if old_callback is None or replace: + self._result_callback = f + return f + + def function(__value, *args, **kwargs): # type: ignore + inner = old_callback(__value, *args, **kwargs) + return f(inner, *args, **kwargs) + + self._result_callback = rv = update_wrapper(t.cast(F, function), f) + return rv # type: ignore[return-value] + + return decorator + + def format_commands(self, ctx: Context, formatter: HelpFormatter) -> None: + """Extra format methods for multi methods that adds all the commands + after the options. + """ + commands = [] + for subcommand in self.list_commands(ctx): + cmd = self.get_command(ctx, subcommand) + # What is this, the tool lied about a command. Ignore it + if cmd is None: + continue + if cmd.hidden: + continue + + commands.append((subcommand, cmd)) + + # allow for 3 times the default spacing + if len(commands): + limit = formatter.width - 6 - max(len(cmd[0]) for cmd in commands) + + rows = [] + for subcommand, cmd in commands: + help = cmd.get_short_help_str(limit) + rows.append((subcommand, help)) + + if rows: + with formatter.section(_("Commands")): + formatter.write_dl(rows) + + def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: + if not args and self.no_args_is_help and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + rest = super().parse_args(ctx, args) + + if self.chain: + ctx.protected_args = rest + ctx.args = [] + elif rest: + ctx.protected_args, ctx.args = rest[:1], rest[1:] + + return ctx.args + + def invoke(self, ctx: Context) -> t.Any: + def _process_result(value: t.Any) -> t.Any: + if self._result_callback is not None: + value = ctx.invoke(self._result_callback, value, **ctx.params) + return value + + if not ctx.protected_args: + if self.invoke_without_command: + # No subcommand was invoked, so the result callback is + # invoked with the group return value for regular + # groups, or an empty list for chained groups. + with ctx: + rv = super().invoke(ctx) + return _process_result([] if self.chain else rv) + ctx.fail(_("Missing command.")) + + # Fetch args back out + args = [*ctx.protected_args, *ctx.args] + ctx.args = [] + ctx.protected_args = [] + + # If we're not in chain mode, we only allow the invocation of a + # single command but we also inform the current context about the + # name of the command to invoke. + if not self.chain: + # Make sure the context is entered so we do not clean up + # resources until the result processor has worked. + with ctx: + cmd_name, cmd, args = self.resolve_command(ctx, args) + assert cmd is not None + ctx.invoked_subcommand = cmd_name + super().invoke(ctx) + sub_ctx = cmd.make_context(cmd_name, args, parent=ctx) + with sub_ctx: + return _process_result(sub_ctx.command.invoke(sub_ctx)) + + # In chain mode we create the contexts step by step, but after the + # base command has been invoked. Because at that point we do not + # know the subcommands yet, the invoked subcommand attribute is + # set to ``*`` to inform the command that subcommands are executed + # but nothing else. + with ctx: + ctx.invoked_subcommand = "*" if args else None + super().invoke(ctx) + + # Otherwise we make every single context and invoke them in a + # chain. In that case the return value to the result processor + # is the list of all invoked subcommand's results. + contexts = [] + while args: + cmd_name, cmd, args = self.resolve_command(ctx, args) + assert cmd is not None + sub_ctx = cmd.make_context( + cmd_name, + args, + parent=ctx, + allow_extra_args=True, + allow_interspersed_args=False, + ) + contexts.append(sub_ctx) + args, sub_ctx.args = sub_ctx.args, [] + + rv = [] + for sub_ctx in contexts: + with sub_ctx: + rv.append(sub_ctx.command.invoke(sub_ctx)) + return _process_result(rv) + + def resolve_command( + self, ctx: Context, args: t.List[str] + ) -> t.Tuple[t.Optional[str], t.Optional[Command], t.List[str]]: + cmd_name = make_str(args[0]) + original_cmd_name = cmd_name + + # Get the command + cmd = self.get_command(ctx, cmd_name) + + # If we can't find the command but there is a normalization + # function available, we try with that one. + if cmd is None and ctx.token_normalize_func is not None: + cmd_name = ctx.token_normalize_func(cmd_name) + cmd = self.get_command(ctx, cmd_name) + + # If we don't find the command we want to show an error message + # to the user that it was not provided. However, there is + # something else we should do: if the first argument looks like + # an option we want to kick off parsing again for arguments to + # resolve things like --help which now should go to the main + # place. + if cmd is None and not ctx.resilient_parsing: + if split_opt(cmd_name)[0]: + self.parse_args(ctx, ctx.args) + ctx.fail(_("No such command {name!r}.").format(name=original_cmd_name)) + return cmd_name if cmd else None, cmd, args[1:] + + def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: + """Given a context and a command name, this returns a + :class:`Command` object if it exists or returns `None`. + """ + raise NotImplementedError + + def list_commands(self, ctx: Context) -> t.List[str]: + """Returns a list of subcommand names in the order they should + appear. + """ + return [] + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. Looks + at the names of options, subcommands, and chained + multi-commands. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + results = [ + CompletionItem(name, help=command.get_short_help_str()) + for name, command in _complete_visible_commands(ctx, incomplete) + ] + results.extend(super().shell_complete(ctx, incomplete)) + return results + + +class Group(MultiCommand): + """A group allows a command to have subcommands attached. This is + the most common way to implement nesting in Click. + + :param name: The name of the group command. + :param commands: A dict mapping names to :class:`Command` objects. + Can also be a list of :class:`Command`, which will use + :attr:`Command.name` to create the dict. + :param attrs: Other command arguments described in + :class:`MultiCommand`, :class:`Command`, and + :class:`BaseCommand`. + + .. versionchanged:: 8.0 + The ``commands`` argument can be a list of command objects. + """ + + #: If set, this is used by the group's :meth:`command` decorator + #: as the default :class:`Command` class. This is useful to make all + #: subcommands use a custom command class. + #: + #: .. versionadded:: 8.0 + command_class: t.Optional[t.Type[Command]] = None + + #: If set, this is used by the group's :meth:`group` decorator + #: as the default :class:`Group` class. This is useful to make all + #: subgroups use a custom group class. + #: + #: If set to the special value :class:`type` (literally + #: ``group_class = type``), this group's class will be used as the + #: default class. This makes a custom group class continue to make + #: custom groups. + #: + #: .. versionadded:: 8.0 + group_class: t.Optional[t.Union[t.Type["Group"], t.Type[type]]] = None + # Literal[type] isn't valid, so use Type[type] + + def __init__( + self, + name: t.Optional[str] = None, + commands: t.Optional[ + t.Union[t.MutableMapping[str, Command], t.Sequence[Command]] + ] = None, + **attrs: t.Any, + ) -> None: + super().__init__(name, **attrs) + + if commands is None: + commands = {} + elif isinstance(commands, abc.Sequence): + commands = {c.name: c for c in commands if c.name is not None} + + #: The registered subcommands by their exported names. + self.commands: t.MutableMapping[str, Command] = commands + + def add_command(self, cmd: Command, name: t.Optional[str] = None) -> None: + """Registers another :class:`Command` with this group. If the name + is not provided, the name of the command is used. + """ + name = name or cmd.name + if name is None: + raise TypeError("Command has no name.") + _check_multicommand(self, name, cmd, register=True) + self.commands[name] = cmd + + @t.overload + def command(self, __func: t.Callable[..., t.Any]) -> Command: ... + + @t.overload + def command( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[t.Callable[..., t.Any]], Command]: ... + + def command( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Union[t.Callable[[t.Callable[..., t.Any]], Command], Command]: + """A shortcut decorator for declaring and attaching a command to + the group. This takes the same arguments as :func:`command` and + immediately registers the created command with this group by + calling :meth:`add_command`. + + To customize the command class used, set the + :attr:`command_class` attribute. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + + .. versionchanged:: 8.0 + Added the :attr:`command_class` attribute. + """ + from .decorators import command + + func: t.Optional[t.Callable[..., t.Any]] = None + + if args and callable(args[0]): + assert ( + len(args) == 1 and not kwargs + ), "Use 'command(**kwargs)(callable)' to provide arguments." + (func,) = args + args = () + + if self.command_class and kwargs.get("cls") is None: + kwargs["cls"] = self.command_class + + def decorator(f: t.Callable[..., t.Any]) -> Command: + cmd: Command = command(*args, **kwargs)(f) + self.add_command(cmd) + return cmd + + if func is not None: + return decorator(func) + + return decorator + + @t.overload + def group(self, __func: t.Callable[..., t.Any]) -> "Group": ... + + @t.overload + def group( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[t.Callable[..., t.Any]], "Group"]: ... + + def group( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Union[t.Callable[[t.Callable[..., t.Any]], "Group"], "Group"]: + """A shortcut decorator for declaring and attaching a group to + the group. This takes the same arguments as :func:`group` and + immediately registers the created group with this group by + calling :meth:`add_command`. + + To customize the group class used, set the :attr:`group_class` + attribute. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + + .. versionchanged:: 8.0 + Added the :attr:`group_class` attribute. + """ + from .decorators import group + + func: t.Optional[t.Callable[..., t.Any]] = None + + if args and callable(args[0]): + assert ( + len(args) == 1 and not kwargs + ), "Use 'group(**kwargs)(callable)' to provide arguments." + (func,) = args + args = () + + if self.group_class is not None and kwargs.get("cls") is None: + if self.group_class is type: + kwargs["cls"] = type(self) + else: + kwargs["cls"] = self.group_class + + def decorator(f: t.Callable[..., t.Any]) -> "Group": + cmd: Group = group(*args, **kwargs)(f) + self.add_command(cmd) + return cmd + + if func is not None: + return decorator(func) + + return decorator + + def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: + return self.commands.get(cmd_name) + + def list_commands(self, ctx: Context) -> t.List[str]: + return sorted(self.commands) + + +class CommandCollection(MultiCommand): + """A command collection is a multi command that merges multiple multi + commands together into one. This is a straightforward implementation + that accepts a list of different multi commands as sources and + provides all the commands for each of them. + + See :class:`MultiCommand` and :class:`Command` for the description of + ``name`` and ``attrs``. + """ + + def __init__( + self, + name: t.Optional[str] = None, + sources: t.Optional[t.List[MultiCommand]] = None, + **attrs: t.Any, + ) -> None: + super().__init__(name, **attrs) + #: The list of registered multi commands. + self.sources: t.List[MultiCommand] = sources or [] + + def add_source(self, multi_cmd: MultiCommand) -> None: + """Adds a new multi command to the chain dispatcher.""" + self.sources.append(multi_cmd) + + def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: + for source in self.sources: + rv = source.get_command(ctx, cmd_name) + + if rv is not None: + if self.chain: + _check_multicommand(self, cmd_name, rv) + + return rv + + return None + + def list_commands(self, ctx: Context) -> t.List[str]: + rv: t.Set[str] = set() + + for source in self.sources: + rv.update(source.list_commands(ctx)) + + return sorted(rv) + + +def _check_iter(value: t.Any) -> t.Iterator[t.Any]: + """Check if the value is iterable but not a string. Raises a type + error, or return an iterator over the value. + """ + if isinstance(value, str): + raise TypeError + + return iter(value) + + +class Parameter: + r"""A parameter to a command comes in two versions: they are either + :class:`Option`\s or :class:`Argument`\s. Other subclasses are currently + not supported by design as some of the internals for parsing are + intentionally not finalized. + + Some settings are supported by both options and arguments. + + :param param_decls: the parameter declarations for this option or + argument. This is a list of flags or argument + names. + :param type: the type that should be used. Either a :class:`ParamType` + or a Python type. The latter is converted into the former + automatically if supported. + :param required: controls if this is optional or not. + :param default: the default value if omitted. This can also be a callable, + in which case it's invoked when the default is needed + without any arguments. + :param callback: A function to further process or validate the value + after type conversion. It is called as ``f(ctx, param, value)`` + and must return the value. It is called for all sources, + including prompts. + :param nargs: the number of arguments to match. If not ``1`` the return + value is a tuple instead of single value. The default for + nargs is ``1`` (except if the type is a tuple, then it's + the arity of the tuple). If ``nargs=-1``, all remaining + parameters are collected. + :param metavar: how the value is represented in the help page. + :param expose_value: if this is `True` then the value is passed onwards + to the command callback and stored on the context, + otherwise it's skipped. + :param is_eager: eager values are processed before non eager ones. This + should not be set for arguments or it will inverse the + order of processing. + :param envvar: a string or list of strings that are environment variables + that should be checked. + :param shell_complete: A function that returns custom shell + completions. Used instead of the param's type completion if + given. Takes ``ctx, param, incomplete`` and must return a list + of :class:`~click.shell_completion.CompletionItem` or a list of + strings. + + .. versionchanged:: 8.0 + ``process_value`` validates required parameters and bounded + ``nargs``, and invokes the parameter callback before returning + the value. This allows the callback to validate prompts. + ``full_process_value`` is removed. + + .. versionchanged:: 8.0 + ``autocompletion`` is renamed to ``shell_complete`` and has new + semantics described above. The old name is deprecated and will + be removed in 8.1, until then it will be wrapped to match the + new requirements. + + .. versionchanged:: 8.0 + For ``multiple=True, nargs>1``, the default must be a list of + tuples. + + .. versionchanged:: 8.0 + Setting a default is no longer required for ``nargs>1``, it will + default to ``None``. ``multiple=True`` or ``nargs=-1`` will + default to ``()``. + + .. versionchanged:: 7.1 + Empty environment variables are ignored rather than taking the + empty string value. This makes it possible for scripts to clear + variables if they can't unset them. + + .. versionchanged:: 2.0 + Changed signature for parameter callback to also be passed the + parameter. The old callback format will still work, but it will + raise a warning to give you a chance to migrate the code easier. + """ + + param_type_name = "parameter" + + def __init__( + self, + param_decls: t.Optional[t.Sequence[str]] = None, + type: t.Optional[t.Union[types.ParamType, t.Any]] = None, + required: bool = False, + default: t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]] = None, + callback: t.Optional[t.Callable[[Context, "Parameter", t.Any], t.Any]] = None, + nargs: t.Optional[int] = None, + multiple: bool = False, + metavar: t.Optional[str] = None, + expose_value: bool = True, + is_eager: bool = False, + envvar: t.Optional[t.Union[str, t.Sequence[str]]] = None, + shell_complete: t.Optional[ + t.Callable[ + [Context, "Parameter", str], + t.Union[t.List["CompletionItem"], t.List[str]], + ] + ] = None, + ) -> None: + self.name: t.Optional[str] + self.opts: t.List[str] + self.secondary_opts: t.List[str] + self.name, self.opts, self.secondary_opts = self._parse_decls( + param_decls or (), expose_value + ) + self.type: types.ParamType = types.convert_type(type, default) + + # Default nargs to what the type tells us if we have that + # information available. + if nargs is None: + if self.type.is_composite: + nargs = self.type.arity + else: + nargs = 1 + + self.required = required + self.callback = callback + self.nargs = nargs + self.multiple = multiple + self.expose_value = expose_value + self.default = default + self.is_eager = is_eager + self.metavar = metavar + self.envvar = envvar + self._custom_shell_complete = shell_complete + + if __debug__: + if self.type.is_composite and nargs != self.type.arity: + raise ValueError( + f"'nargs' must be {self.type.arity} (or None) for" + f" type {self.type!r}, but it was {nargs}." + ) + + # Skip no default or callable default. + check_default = default if not callable(default) else None + + if check_default is not None: + if multiple: + try: + # Only check the first value against nargs. + check_default = next(_check_iter(check_default), None) + except TypeError: + raise ValueError( + "'default' must be a list when 'multiple' is true." + ) from None + + # Can be None for multiple with empty default. + if nargs != 1 and check_default is not None: + try: + _check_iter(check_default) + except TypeError: + if multiple: + message = ( + "'default' must be a list of lists when 'multiple' is" + " true and 'nargs' != 1." + ) + else: + message = "'default' must be a list when 'nargs' != 1." + + raise ValueError(message) from None + + if nargs > 1 and len(check_default) != nargs: + subject = "item length" if multiple else "length" + raise ValueError( + f"'default' {subject} must match nargs={nargs}." + ) + + def to_info_dict(self) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. + + Use :meth:`click.Context.to_info_dict` to traverse the entire + CLI structure. + + .. versionadded:: 8.0 + """ + return { + "name": self.name, + "param_type_name": self.param_type_name, + "opts": self.opts, + "secondary_opts": self.secondary_opts, + "type": self.type.to_info_dict(), + "required": self.required, + "nargs": self.nargs, + "multiple": self.multiple, + "default": self.default, + "envvar": self.envvar, + } + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} {self.name}>" + + def _parse_decls( + self, decls: t.Sequence[str], expose_value: bool + ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: + raise NotImplementedError() + + @property + def human_readable_name(self) -> str: + """Returns the human readable name of this parameter. This is the + same as the name for options, but the metavar for arguments. + """ + return self.name # type: ignore + + def make_metavar(self) -> str: + if self.metavar is not None: + return self.metavar + + metavar = self.type.get_metavar(self) + + if metavar is None: + metavar = self.type.name.upper() + + if self.nargs != 1: + metavar += "..." + + return metavar + + @t.overload + def get_default( + self, ctx: Context, call: "te.Literal[True]" = True + ) -> t.Optional[t.Any]: ... + + @t.overload + def get_default( + self, ctx: Context, call: bool = ... + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: ... + + def get_default( + self, ctx: Context, call: bool = True + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + """Get the default for the parameter. Tries + :meth:`Context.lookup_default` first, then the local default. + + :param ctx: Current context. + :param call: If the default is a callable, call it. Disable to + return the callable instead. + + .. versionchanged:: 8.0.2 + Type casting is no longer performed when getting a default. + + .. versionchanged:: 8.0.1 + Type casting can fail in resilient parsing mode. Invalid + defaults will not prevent showing help text. + + .. versionchanged:: 8.0 + Looks at ``ctx.default_map`` first. + + .. versionchanged:: 8.0 + Added the ``call`` parameter. + """ + value = ctx.lookup_default(self.name, call=False) # type: ignore + + if value is None: + value = self.default + + if call and callable(value): + value = value() + + return value + + def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: + raise NotImplementedError() + + def consume_value( + self, ctx: Context, opts: t.Mapping[str, t.Any] + ) -> t.Tuple[t.Any, ParameterSource]: + value = opts.get(self.name) # type: ignore + source = ParameterSource.COMMANDLINE + + if value is None: + value = self.value_from_envvar(ctx) + source = ParameterSource.ENVIRONMENT + + if value is None: + value = ctx.lookup_default(self.name) # type: ignore + source = ParameterSource.DEFAULT_MAP + + if value is None: + value = self.get_default(ctx) + source = ParameterSource.DEFAULT + + return value, source + + def type_cast_value(self, ctx: Context, value: t.Any) -> t.Any: + """Convert and validate a value against the option's + :attr:`type`, :attr:`multiple`, and :attr:`nargs`. + """ + if value is None: + return () if self.multiple or self.nargs == -1 else None + + def check_iter(value: t.Any) -> t.Iterator[t.Any]: + try: + return _check_iter(value) + except TypeError: + # This should only happen when passing in args manually, + # the parser should construct an iterable when parsing + # the command line. + raise BadParameter( + _("Value must be an iterable."), ctx=ctx, param=self + ) from None + + if self.nargs == 1 or self.type.is_composite: + + def convert(value: t.Any) -> t.Any: + return self.type(value, param=self, ctx=ctx) + + elif self.nargs == -1: + + def convert(value: t.Any) -> t.Any: # t.Tuple[t.Any, ...] + return tuple(self.type(x, self, ctx) for x in check_iter(value)) + + else: # nargs > 1 + + def convert(value: t.Any) -> t.Any: # t.Tuple[t.Any, ...] + value = tuple(check_iter(value)) + + if len(value) != self.nargs: + raise BadParameter( + ngettext( + "Takes {nargs} values but 1 was given.", + "Takes {nargs} values but {len} were given.", + len(value), + ).format(nargs=self.nargs, len=len(value)), + ctx=ctx, + param=self, + ) + + return tuple(self.type(x, self, ctx) for x in value) + + if self.multiple: + return tuple(convert(x) for x in check_iter(value)) + + return convert(value) + + def value_is_missing(self, value: t.Any) -> bool: + if value is None: + return True + + if (self.nargs != 1 or self.multiple) and value == (): + return True + + return False + + def process_value(self, ctx: Context, value: t.Any) -> t.Any: + value = self.type_cast_value(ctx, value) + + if self.required and self.value_is_missing(value): + raise MissingParameter(ctx=ctx, param=self) + + if self.callback is not None: + value = self.callback(ctx, self, value) + + return value + + def resolve_envvar_value(self, ctx: Context) -> t.Optional[str]: + if self.envvar is None: + return None + + if isinstance(self.envvar, str): + rv = os.environ.get(self.envvar) + + if rv: + return rv + else: + for envvar in self.envvar: + rv = os.environ.get(envvar) + + if rv: + return rv + + return None + + def value_from_envvar(self, ctx: Context) -> t.Optional[t.Any]: + rv: t.Optional[t.Any] = self.resolve_envvar_value(ctx) + + if rv is not None and self.nargs != 1: + rv = self.type.split_envvar_value(rv) + + return rv + + def handle_parse_result( + self, ctx: Context, opts: t.Mapping[str, t.Any], args: t.List[str] + ) -> t.Tuple[t.Any, t.List[str]]: + with augment_usage_errors(ctx, param=self): + value, source = self.consume_value(ctx, opts) + ctx.set_parameter_source(self.name, source) # type: ignore + + try: + value = self.process_value(ctx, value) + except Exception: + if not ctx.resilient_parsing: + raise + + value = None + + if self.expose_value: + ctx.params[self.name] = value # type: ignore + + return value, args + + def get_help_record(self, ctx: Context) -> t.Optional[t.Tuple[str, str]]: + pass + + def get_usage_pieces(self, ctx: Context) -> t.List[str]: + return [] + + def get_error_hint(self, ctx: Context) -> str: + """Get a stringified version of the param for use in error messages to + indicate which param caused the error. + """ + hint_list = self.opts or [self.human_readable_name] + return " / ".join(f"'{x}'" for x in hint_list) + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. If a + ``shell_complete`` function was given during init, it is used. + Otherwise, the :attr:`type` + :meth:`~click.types.ParamType.shell_complete` function is used. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + if self._custom_shell_complete is not None: + results = self._custom_shell_complete(ctx, self, incomplete) + + if results and isinstance(results[0], str): + from click.shell_completion import CompletionItem + + results = [CompletionItem(c) for c in results] + + return t.cast(t.List["CompletionItem"], results) + + return self.type.shell_complete(ctx, self, incomplete) + + +class Option(Parameter): + """Options are usually optional values on the command line and + have some extra features that arguments don't have. + + All other parameters are passed onwards to the parameter constructor. + + :param show_default: Show the default value for this option in its + help text. Values are not shown by default, unless + :attr:`Context.show_default` is ``True``. If this value is a + string, it shows that string in parentheses instead of the + actual value. This is particularly useful for dynamic options. + For single option boolean flags, the default remains hidden if + its value is ``False``. + :param show_envvar: Controls if an environment variable should be + shown on the help page. Normally, environment variables are not + shown. + :param prompt: If set to ``True`` or a non empty string then the + user will be prompted for input. If set to ``True`` the prompt + will be the option name capitalized. + :param confirmation_prompt: Prompt a second time to confirm the + value if it was prompted for. Can be set to a string instead of + ``True`` to customize the message. + :param prompt_required: If set to ``False``, the user will be + prompted for input only when the option was specified as a flag + without a value. + :param hide_input: If this is ``True`` then the input on the prompt + will be hidden from the user. This is useful for password input. + :param is_flag: forces this option to act as a flag. The default is + auto detection. + :param flag_value: which value should be used for this flag if it's + enabled. This is set to a boolean automatically if + the option string contains a slash to mark two options. + :param multiple: if this is set to `True` then the argument is accepted + multiple times and recorded. This is similar to ``nargs`` + in how it works but supports arbitrary number of + arguments. + :param count: this flag makes an option increment an integer. + :param allow_from_autoenv: if this is enabled then the value of this + parameter will be pulled from an environment + variable in case a prefix is defined on the + context. + :param help: the help string. + :param hidden: hide this option from help outputs. + :param attrs: Other command arguments described in :class:`Parameter`. + + .. versionchanged:: 8.1.0 + Help text indentation is cleaned here instead of only in the + ``@option`` decorator. + + .. versionchanged:: 8.1.0 + The ``show_default`` parameter overrides + ``Context.show_default``. + + .. versionchanged:: 8.1.0 + The default of a single option boolean flag is not shown if the + default value is ``False``. + + .. versionchanged:: 8.0.1 + ``type`` is detected from ``flag_value`` if given. + """ + + param_type_name = "option" + + def __init__( + self, + param_decls: t.Optional[t.Sequence[str]] = None, + show_default: t.Union[bool, str, None] = None, + prompt: t.Union[bool, str] = False, + confirmation_prompt: t.Union[bool, str] = False, + prompt_required: bool = True, + hide_input: bool = False, + is_flag: t.Optional[bool] = None, + flag_value: t.Optional[t.Any] = None, + multiple: bool = False, + count: bool = False, + allow_from_autoenv: bool = True, + type: t.Optional[t.Union[types.ParamType, t.Any]] = None, + help: t.Optional[str] = None, + hidden: bool = False, + show_choices: bool = True, + show_envvar: bool = False, + **attrs: t.Any, + ) -> None: + if help: + help = inspect.cleandoc(help) + + default_is_missing = "default" not in attrs + super().__init__(param_decls, type=type, multiple=multiple, **attrs) + + if prompt is True: + if self.name is None: + raise TypeError("'name' is required with 'prompt=True'.") + + prompt_text: t.Optional[str] = self.name.replace("_", " ").capitalize() + elif prompt is False: + prompt_text = None + else: + prompt_text = prompt + + self.prompt = prompt_text + self.confirmation_prompt = confirmation_prompt + self.prompt_required = prompt_required + self.hide_input = hide_input + self.hidden = hidden + + # If prompt is enabled but not required, then the option can be + # used as a flag to indicate using prompt or flag_value. + self._flag_needs_value = self.prompt is not None and not self.prompt_required + + if is_flag is None: + if flag_value is not None: + # Implicitly a flag because flag_value was set. + is_flag = True + elif self._flag_needs_value: + # Not a flag, but when used as a flag it shows a prompt. + is_flag = False + else: + # Implicitly a flag because flag options were given. + is_flag = bool(self.secondary_opts) + elif is_flag is False and not self._flag_needs_value: + # Not a flag, and prompt is not enabled, can be used as a + # flag if flag_value is set. + self._flag_needs_value = flag_value is not None + + self.default: t.Union[t.Any, t.Callable[[], t.Any]] + + if is_flag and default_is_missing and not self.required: + if multiple: + self.default = () + else: + self.default = False + + if flag_value is None: + flag_value = not self.default + + self.type: types.ParamType + if is_flag and type is None: + # Re-guess the type from the flag value instead of the + # default. + self.type = types.convert_type(None, flag_value) + + self.is_flag: bool = is_flag + self.is_bool_flag: bool = is_flag and isinstance(self.type, types.BoolParamType) + self.flag_value: t.Any = flag_value + + # Counting + self.count = count + if count: + if type is None: + self.type = types.IntRange(min=0) + if default_is_missing: + self.default = 0 + + self.allow_from_autoenv = allow_from_autoenv + self.help = help + self.show_default = show_default + self.show_choices = show_choices + self.show_envvar = show_envvar + + if __debug__: + if self.nargs == -1: + raise TypeError("nargs=-1 is not supported for options.") + + if self.prompt and self.is_flag and not self.is_bool_flag: + raise TypeError("'prompt' is not valid for non-boolean flag.") + + if not self.is_bool_flag and self.secondary_opts: + raise TypeError("Secondary flag is not valid for non-boolean flag.") + + if self.is_bool_flag and self.hide_input and self.prompt is not None: + raise TypeError( + "'prompt' with 'hide_input' is not valid for boolean flag." + ) + + if self.count: + if self.multiple: + raise TypeError("'count' is not valid with 'multiple'.") + + if self.is_flag: + raise TypeError("'count' is not valid with 'is_flag'.") + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update( + help=self.help, + prompt=self.prompt, + is_flag=self.is_flag, + flag_value=self.flag_value, + count=self.count, + hidden=self.hidden, + ) + return info_dict + + def _parse_decls( + self, decls: t.Sequence[str], expose_value: bool + ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: + opts = [] + secondary_opts = [] + name = None + possible_names = [] + + for decl in decls: + if decl.isidentifier(): + if name is not None: + raise TypeError(f"Name '{name}' defined twice") + name = decl + else: + split_char = ";" if decl[:1] == "/" else "/" + if split_char in decl: + first, second = decl.split(split_char, 1) + first = first.rstrip() + if first: + possible_names.append(split_opt(first)) + opts.append(first) + second = second.lstrip() + if second: + secondary_opts.append(second.lstrip()) + if first == second: + raise ValueError( + f"Boolean option {decl!r} cannot use the" + " same flag for true/false." + ) + else: + possible_names.append(split_opt(decl)) + opts.append(decl) + + if name is None and possible_names: + possible_names.sort(key=lambda x: -len(x[0])) # group long options first + name = possible_names[0][1].replace("-", "_").lower() + if not name.isidentifier(): + name = None + + if name is None: + if not expose_value: + return None, opts, secondary_opts + raise TypeError( + f"Could not determine name for option with declarations {decls!r}" + ) + + if not opts and not secondary_opts: + raise TypeError( + f"No options defined but a name was passed ({name})." + " Did you mean to declare an argument instead? Did" + f" you mean to pass '--{name}'?" + ) + + return name, opts, secondary_opts + + def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: + if self.multiple: + action = "append" + elif self.count: + action = "count" + else: + action = "store" + + if self.is_flag: + action = f"{action}_const" + + if self.is_bool_flag and self.secondary_opts: + parser.add_option( + obj=self, opts=self.opts, dest=self.name, action=action, const=True + ) + parser.add_option( + obj=self, + opts=self.secondary_opts, + dest=self.name, + action=action, + const=False, + ) + else: + parser.add_option( + obj=self, + opts=self.opts, + dest=self.name, + action=action, + const=self.flag_value, + ) + else: + parser.add_option( + obj=self, + opts=self.opts, + dest=self.name, + action=action, + nargs=self.nargs, + ) + + def get_help_record(self, ctx: Context) -> t.Optional[t.Tuple[str, str]]: + if self.hidden: + return None + + any_prefix_is_slash = False + + def _write_opts(opts: t.Sequence[str]) -> str: + nonlocal any_prefix_is_slash + + rv, any_slashes = join_options(opts) + + if any_slashes: + any_prefix_is_slash = True + + if not self.is_flag and not self.count: + rv += f" {self.make_metavar()}" + + return rv + + rv = [_write_opts(self.opts)] + + if self.secondary_opts: + rv.append(_write_opts(self.secondary_opts)) + + help = self.help or "" + extra = [] + + if self.show_envvar: + envvar = self.envvar + + if envvar is None: + if ( + self.allow_from_autoenv + and ctx.auto_envvar_prefix is not None + and self.name is not None + ): + envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}" + + if envvar is not None: + var_str = ( + envvar + if isinstance(envvar, str) + else ", ".join(str(d) for d in envvar) + ) + extra.append(_("env var: {var}").format(var=var_str)) + + # Temporarily enable resilient parsing to avoid type casting + # failing for the default. Might be possible to extend this to + # help formatting in general. + resilient = ctx.resilient_parsing + ctx.resilient_parsing = True + + try: + default_value = self.get_default(ctx, call=False) + finally: + ctx.resilient_parsing = resilient + + show_default = False + show_default_is_str = False + + if self.show_default is not None: + if isinstance(self.show_default, str): + show_default_is_str = show_default = True + else: + show_default = self.show_default + elif ctx.show_default is not None: + show_default = ctx.show_default + + if show_default_is_str or (show_default and (default_value is not None)): + if show_default_is_str: + default_string = f"({self.show_default})" + elif isinstance(default_value, (list, tuple)): + default_string = ", ".join(str(d) for d in default_value) + elif inspect.isfunction(default_value): + default_string = _("(dynamic)") + elif self.is_bool_flag and self.secondary_opts: + # For boolean flags that have distinct True/False opts, + # use the opt without prefix instead of the value. + default_string = split_opt( + (self.opts if default_value else self.secondary_opts)[0] + )[1] + elif self.is_bool_flag and not self.secondary_opts and not default_value: + default_string = "" + elif default_value == "": + default_string = '""' + else: + default_string = str(default_value) + + if default_string: + extra.append(_("default: {default}").format(default=default_string)) + + if ( + isinstance(self.type, types._NumberRangeBase) + # skip count with default range type + and not (self.count and self.type.min == 0 and self.type.max is None) + ): + range_str = self.type._describe_range() + + if range_str: + extra.append(range_str) + + if self.required: + extra.append(_("required")) + + if extra: + extra_str = "; ".join(extra) + help = f"{help} [{extra_str}]" if help else f"[{extra_str}]" + + return ("; " if any_prefix_is_slash else " / ").join(rv), help + + @t.overload + def get_default( + self, ctx: Context, call: "te.Literal[True]" = True + ) -> t.Optional[t.Any]: ... + + @t.overload + def get_default( + self, ctx: Context, call: bool = ... + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: ... + + def get_default( + self, ctx: Context, call: bool = True + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + # If we're a non boolean flag our default is more complex because + # we need to look at all flags in the same group to figure out + # if we're the default one in which case we return the flag + # value as default. + if self.is_flag and not self.is_bool_flag: + for param in ctx.command.params: + if param.name == self.name and param.default: + return t.cast(Option, param).flag_value + + return None + + return super().get_default(ctx, call=call) + + def prompt_for_value(self, ctx: Context) -> t.Any: + """This is an alternative flow that can be activated in the full + value processing if a value does not exist. It will prompt the + user until a valid value exists and then returns the processed + value as result. + """ + assert self.prompt is not None + + # Calculate the default before prompting anything to be stable. + default = self.get_default(ctx) + + # If this is a prompt for a flag we need to handle this + # differently. + if self.is_bool_flag: + return confirm(self.prompt, default) + + return prompt( + self.prompt, + default=default, + type=self.type, + hide_input=self.hide_input, + show_choices=self.show_choices, + confirmation_prompt=self.confirmation_prompt, + value_proc=lambda x: self.process_value(ctx, x), + ) + + def resolve_envvar_value(self, ctx: Context) -> t.Optional[str]: + rv = super().resolve_envvar_value(ctx) + + if rv is not None: + return rv + + if ( + self.allow_from_autoenv + and ctx.auto_envvar_prefix is not None + and self.name is not None + ): + envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}" + rv = os.environ.get(envvar) + + if rv: + return rv + + return None + + def value_from_envvar(self, ctx: Context) -> t.Optional[t.Any]: + rv: t.Optional[t.Any] = self.resolve_envvar_value(ctx) + + if rv is None: + return None + + value_depth = (self.nargs != 1) + bool(self.multiple) + + if value_depth > 0: + rv = self.type.split_envvar_value(rv) + + if self.multiple and self.nargs != 1: + rv = batch(rv, self.nargs) + + return rv + + def consume_value( + self, ctx: Context, opts: t.Mapping[str, "Parameter"] + ) -> t.Tuple[t.Any, ParameterSource]: + value, source = super().consume_value(ctx, opts) + + # The parser will emit a sentinel value if the option can be + # given as a flag without a value. This is different from None + # to distinguish from the flag not being given at all. + if value is _flag_needs_value: + if self.prompt is not None and not ctx.resilient_parsing: + value = self.prompt_for_value(ctx) + source = ParameterSource.PROMPT + else: + value = self.flag_value + source = ParameterSource.COMMANDLINE + + elif ( + self.multiple + and value is not None + and any(v is _flag_needs_value for v in value) + ): + value = [self.flag_value if v is _flag_needs_value else v for v in value] + source = ParameterSource.COMMANDLINE + + # The value wasn't set, or used the param's default, prompt if + # prompting is enabled. + elif ( + source in {None, ParameterSource.DEFAULT} + and self.prompt is not None + and (self.required or self.prompt_required) + and not ctx.resilient_parsing + ): + value = self.prompt_for_value(ctx) + source = ParameterSource.PROMPT + + return value, source + + +class Argument(Parameter): + """Arguments are positional parameters to a command. They generally + provide fewer features than options but can have infinite ``nargs`` + and are required by default. + + All parameters are passed onwards to the constructor of :class:`Parameter`. + """ + + param_type_name = "argument" + + def __init__( + self, + param_decls: t.Sequence[str], + required: t.Optional[bool] = None, + **attrs: t.Any, + ) -> None: + if required is None: + if attrs.get("default") is not None: + required = False + else: + required = attrs.get("nargs", 1) > 0 + + if "multiple" in attrs: + raise TypeError("__init__() got an unexpected keyword argument 'multiple'.") + + super().__init__(param_decls, required=required, **attrs) + + if __debug__: + if self.default is not None and self.nargs == -1: + raise TypeError("'default' is not supported for nargs=-1.") + + @property + def human_readable_name(self) -> str: + if self.metavar is not None: + return self.metavar + return self.name.upper() # type: ignore + + def make_metavar(self) -> str: + if self.metavar is not None: + return self.metavar + var = self.type.get_metavar(self) + if not var: + var = self.name.upper() # type: ignore + if not self.required: + var = f"[{var}]" + if self.nargs != 1: + var += "..." + return var + + def _parse_decls( + self, decls: t.Sequence[str], expose_value: bool + ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: + if not decls: + if not expose_value: + return None, [], [] + raise TypeError("Argument is marked as exposed, but does not have a name.") + if len(decls) == 1: + name = arg = decls[0] + name = name.replace("-", "_").lower() + else: + raise TypeError( + "Arguments take exactly one parameter declaration, got" + f" {len(decls)}." + ) + return name, [arg], [] + + def get_usage_pieces(self, ctx: Context) -> t.List[str]: + return [self.make_metavar()] + + def get_error_hint(self, ctx: Context) -> str: + return f"'{self.make_metavar()}'" + + def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: + parser.add_argument(dest=self.name, nargs=self.nargs, obj=self) diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/decorators.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/decorators.py new file mode 100644 index 0000000..bcf8906 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/decorators.py @@ -0,0 +1,562 @@ +import inspect +import types +import typing as t +from functools import update_wrapper +from gettext import gettext as _ + +from .core import Argument +from .core import Command +from .core import Context +from .core import Group +from .core import Option +from .core import Parameter +from .globals import get_current_context +from .utils import echo + +if t.TYPE_CHECKING: + import typing_extensions as te + + P = te.ParamSpec("P") + +R = t.TypeVar("R") +T = t.TypeVar("T") +_AnyCallable = t.Callable[..., t.Any] +FC = t.TypeVar("FC", bound=t.Union[_AnyCallable, Command]) + + +def pass_context(f: "t.Callable[te.Concatenate[Context, P], R]") -> "t.Callable[P, R]": + """Marks a callback as wanting to receive the current context + object as first argument. + """ + + def new_func(*args: "P.args", **kwargs: "P.kwargs") -> "R": + return f(get_current_context(), *args, **kwargs) + + return update_wrapper(new_func, f) + + +def pass_obj(f: "t.Callable[te.Concatenate[t.Any, P], R]") -> "t.Callable[P, R]": + """Similar to :func:`pass_context`, but only pass the object on the + context onwards (:attr:`Context.obj`). This is useful if that object + represents the state of a nested system. + """ + + def new_func(*args: "P.args", **kwargs: "P.kwargs") -> "R": + return f(get_current_context().obj, *args, **kwargs) + + return update_wrapper(new_func, f) + + +def make_pass_decorator( + object_type: t.Type[T], ensure: bool = False +) -> t.Callable[["t.Callable[te.Concatenate[T, P], R]"], "t.Callable[P, R]"]: + """Given an object type this creates a decorator that will work + similar to :func:`pass_obj` but instead of passing the object of the + current context, it will find the innermost context of type + :func:`object_type`. + + This generates a decorator that works roughly like this:: + + from functools import update_wrapper + + def decorator(f): + @pass_context + def new_func(ctx, *args, **kwargs): + obj = ctx.find_object(object_type) + return ctx.invoke(f, obj, *args, **kwargs) + return update_wrapper(new_func, f) + return decorator + + :param object_type: the type of the object to pass. + :param ensure: if set to `True`, a new object will be created and + remembered on the context if it's not there yet. + """ + + def decorator(f: "t.Callable[te.Concatenate[T, P], R]") -> "t.Callable[P, R]": + def new_func(*args: "P.args", **kwargs: "P.kwargs") -> "R": + ctx = get_current_context() + + obj: t.Optional[T] + if ensure: + obj = ctx.ensure_object(object_type) + else: + obj = ctx.find_object(object_type) + + if obj is None: + raise RuntimeError( + "Managed to invoke callback without a context" + f" object of type {object_type.__name__!r}" + " existing." + ) + + return ctx.invoke(f, obj, *args, **kwargs) + + return update_wrapper(new_func, f) + + return decorator + + +def pass_meta_key( + key: str, *, doc_description: t.Optional[str] = None +) -> "t.Callable[[t.Callable[te.Concatenate[t.Any, P], R]], t.Callable[P, R]]": + """Create a decorator that passes a key from + :attr:`click.Context.meta` as the first argument to the decorated + function. + + :param key: Key in ``Context.meta`` to pass. + :param doc_description: Description of the object being passed, + inserted into the decorator's docstring. Defaults to "the 'key' + key from Context.meta". + + .. versionadded:: 8.0 + """ + + def decorator(f: "t.Callable[te.Concatenate[t.Any, P], R]") -> "t.Callable[P, R]": + def new_func(*args: "P.args", **kwargs: "P.kwargs") -> R: + ctx = get_current_context() + obj = ctx.meta[key] + return ctx.invoke(f, obj, *args, **kwargs) + + return update_wrapper(new_func, f) + + if doc_description is None: + doc_description = f"the {key!r} key from :attr:`click.Context.meta`" + + decorator.__doc__ = ( + f"Decorator that passes {doc_description} as the first argument" + " to the decorated function." + ) + return decorator + + +CmdType = t.TypeVar("CmdType", bound=Command) + + +# variant: no call, directly as decorator for a function. +@t.overload +def command(name: _AnyCallable) -> Command: ... + + +# variant: with positional name and with positional or keyword cls argument: +# @command(namearg, CommandCls, ...) or @command(namearg, cls=CommandCls, ...) +@t.overload +def command( + name: t.Optional[str], + cls: t.Type[CmdType], + **attrs: t.Any, +) -> t.Callable[[_AnyCallable], CmdType]: ... + + +# variant: name omitted, cls _must_ be a keyword argument, @command(cls=CommandCls, ...) +@t.overload +def command( + name: None = None, + *, + cls: t.Type[CmdType], + **attrs: t.Any, +) -> t.Callable[[_AnyCallable], CmdType]: ... + + +# variant: with optional string name, no cls argument provided. +@t.overload +def command( + name: t.Optional[str] = ..., cls: None = None, **attrs: t.Any +) -> t.Callable[[_AnyCallable], Command]: ... + + +def command( + name: t.Union[t.Optional[str], _AnyCallable] = None, + cls: t.Optional[t.Type[CmdType]] = None, + **attrs: t.Any, +) -> t.Union[Command, t.Callable[[_AnyCallable], t.Union[Command, CmdType]]]: + r"""Creates a new :class:`Command` and uses the decorated function as + callback. This will also automatically attach all decorated + :func:`option`\s and :func:`argument`\s as parameters to the command. + + The name of the command defaults to the name of the function with + underscores replaced by dashes. If you want to change that, you can + pass the intended name as the first argument. + + All keyword arguments are forwarded to the underlying command class. + For the ``params`` argument, any decorated params are appended to + the end of the list. + + Once decorated the function turns into a :class:`Command` instance + that can be invoked as a command line utility or be attached to a + command :class:`Group`. + + :param name: the name of the command. This defaults to the function + name with underscores replaced by dashes. + :param cls: the command class to instantiate. This defaults to + :class:`Command`. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + + .. versionchanged:: 8.1 + The ``params`` argument can be used. Decorated params are + appended to the end of the list. + """ + + func: t.Optional[t.Callable[[_AnyCallable], t.Any]] = None + + if callable(name): + func = name + name = None + assert cls is None, "Use 'command(cls=cls)(callable)' to specify a class." + assert not attrs, "Use 'command(**kwargs)(callable)' to provide arguments." + + if cls is None: + cls = t.cast(t.Type[CmdType], Command) + + def decorator(f: _AnyCallable) -> CmdType: + if isinstance(f, Command): + raise TypeError("Attempted to convert a callback into a command twice.") + + attr_params = attrs.pop("params", None) + params = attr_params if attr_params is not None else [] + + try: + decorator_params = f.__click_params__ # type: ignore + except AttributeError: + pass + else: + del f.__click_params__ # type: ignore + params.extend(reversed(decorator_params)) + + if attrs.get("help") is None: + attrs["help"] = f.__doc__ + + if t.TYPE_CHECKING: + assert cls is not None + assert not callable(name) + + cmd = cls( + name=name or f.__name__.lower().replace("_", "-"), + callback=f, + params=params, + **attrs, + ) + cmd.__doc__ = f.__doc__ + return cmd + + if func is not None: + return decorator(func) + + return decorator + + +GrpType = t.TypeVar("GrpType", bound=Group) + + +# variant: no call, directly as decorator for a function. +@t.overload +def group(name: _AnyCallable) -> Group: ... + + +# variant: with positional name and with positional or keyword cls argument: +# @group(namearg, GroupCls, ...) or @group(namearg, cls=GroupCls, ...) +@t.overload +def group( + name: t.Optional[str], + cls: t.Type[GrpType], + **attrs: t.Any, +) -> t.Callable[[_AnyCallable], GrpType]: ... + + +# variant: name omitted, cls _must_ be a keyword argument, @group(cmd=GroupCls, ...) +@t.overload +def group( + name: None = None, + *, + cls: t.Type[GrpType], + **attrs: t.Any, +) -> t.Callable[[_AnyCallable], GrpType]: ... + + +# variant: with optional string name, no cls argument provided. +@t.overload +def group( + name: t.Optional[str] = ..., cls: None = None, **attrs: t.Any +) -> t.Callable[[_AnyCallable], Group]: ... + + +def group( + name: t.Union[str, _AnyCallable, None] = None, + cls: t.Optional[t.Type[GrpType]] = None, + **attrs: t.Any, +) -> t.Union[Group, t.Callable[[_AnyCallable], t.Union[Group, GrpType]]]: + """Creates a new :class:`Group` with a function as callback. This + works otherwise the same as :func:`command` just that the `cls` + parameter is set to :class:`Group`. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + """ + if cls is None: + cls = t.cast(t.Type[GrpType], Group) + + if callable(name): + return command(cls=cls, **attrs)(name) + + return command(name, cls, **attrs) + + +def _param_memo(f: t.Callable[..., t.Any], param: Parameter) -> None: + if isinstance(f, Command): + f.params.append(param) + else: + if not hasattr(f, "__click_params__"): + f.__click_params__ = [] # type: ignore + + f.__click_params__.append(param) # type: ignore + + +def argument( + *param_decls: str, cls: t.Optional[t.Type[Argument]] = None, **attrs: t.Any +) -> t.Callable[[FC], FC]: + """Attaches an argument to the command. All positional arguments are + passed as parameter declarations to :class:`Argument`; all keyword + arguments are forwarded unchanged (except ``cls``). + This is equivalent to creating an :class:`Argument` instance manually + and attaching it to the :attr:`Command.params` list. + + For the default argument class, refer to :class:`Argument` and + :class:`Parameter` for descriptions of parameters. + + :param cls: the argument class to instantiate. This defaults to + :class:`Argument`. + :param param_decls: Passed as positional arguments to the constructor of + ``cls``. + :param attrs: Passed as keyword arguments to the constructor of ``cls``. + """ + if cls is None: + cls = Argument + + def decorator(f: FC) -> FC: + _param_memo(f, cls(param_decls, **attrs)) + return f + + return decorator + + +def option( + *param_decls: str, cls: t.Optional[t.Type[Option]] = None, **attrs: t.Any +) -> t.Callable[[FC], FC]: + """Attaches an option to the command. All positional arguments are + passed as parameter declarations to :class:`Option`; all keyword + arguments are forwarded unchanged (except ``cls``). + This is equivalent to creating an :class:`Option` instance manually + and attaching it to the :attr:`Command.params` list. + + For the default option class, refer to :class:`Option` and + :class:`Parameter` for descriptions of parameters. + + :param cls: the option class to instantiate. This defaults to + :class:`Option`. + :param param_decls: Passed as positional arguments to the constructor of + ``cls``. + :param attrs: Passed as keyword arguments to the constructor of ``cls``. + """ + if cls is None: + cls = Option + + def decorator(f: FC) -> FC: + _param_memo(f, cls(param_decls, **attrs)) + return f + + return decorator + + +def confirmation_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Add a ``--yes`` option which shows a prompt before continuing if + not passed. If the prompt is declined, the program will exit. + + :param param_decls: One or more option names. Defaults to the single + value ``"--yes"``. + :param kwargs: Extra arguments are passed to :func:`option`. + """ + + def callback(ctx: Context, param: Parameter, value: bool) -> None: + if not value: + ctx.abort() + + if not param_decls: + param_decls = ("--yes",) + + kwargs.setdefault("is_flag", True) + kwargs.setdefault("callback", callback) + kwargs.setdefault("expose_value", False) + kwargs.setdefault("prompt", "Do you want to continue?") + kwargs.setdefault("help", "Confirm the action without prompting.") + return option(*param_decls, **kwargs) + + +def password_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Add a ``--password`` option which prompts for a password, hiding + input and asking to enter the value again for confirmation. + + :param param_decls: One or more option names. Defaults to the single + value ``"--password"``. + :param kwargs: Extra arguments are passed to :func:`option`. + """ + if not param_decls: + param_decls = ("--password",) + + kwargs.setdefault("prompt", True) + kwargs.setdefault("confirmation_prompt", True) + kwargs.setdefault("hide_input", True) + return option(*param_decls, **kwargs) + + +def version_option( + version: t.Optional[str] = None, + *param_decls: str, + package_name: t.Optional[str] = None, + prog_name: t.Optional[str] = None, + message: t.Optional[str] = None, + **kwargs: t.Any, +) -> t.Callable[[FC], FC]: + """Add a ``--version`` option which immediately prints the version + number and exits the program. + + If ``version`` is not provided, Click will try to detect it using + :func:`importlib.metadata.version` to get the version for the + ``package_name``. On Python < 3.8, the ``importlib_metadata`` + backport must be installed. + + If ``package_name`` is not provided, Click will try to detect it by + inspecting the stack frames. This will be used to detect the + version, so it must match the name of the installed package. + + :param version: The version number to show. If not provided, Click + will try to detect it. + :param param_decls: One or more option names. Defaults to the single + value ``"--version"``. + :param package_name: The package name to detect the version from. If + not provided, Click will try to detect it. + :param prog_name: The name of the CLI to show in the message. If not + provided, it will be detected from the command. + :param message: The message to show. The values ``%(prog)s``, + ``%(package)s``, and ``%(version)s`` are available. Defaults to + ``"%(prog)s, version %(version)s"``. + :param kwargs: Extra arguments are passed to :func:`option`. + :raise RuntimeError: ``version`` could not be detected. + + .. versionchanged:: 8.0 + Add the ``package_name`` parameter, and the ``%(package)s`` + value for messages. + + .. versionchanged:: 8.0 + Use :mod:`importlib.metadata` instead of ``pkg_resources``. The + version is detected based on the package name, not the entry + point name. The Python package name must match the installed + package name, or be passed with ``package_name=``. + """ + if message is None: + message = _("%(prog)s, version %(version)s") + + if version is None and package_name is None: + frame = inspect.currentframe() + f_back = frame.f_back if frame is not None else None + f_globals = f_back.f_globals if f_back is not None else None + # break reference cycle + # https://docs.python.org/3/library/inspect.html#the-interpreter-stack + del frame + + if f_globals is not None: + package_name = f_globals.get("__name__") + + if package_name == "__main__": + package_name = f_globals.get("__package__") + + if package_name: + package_name = package_name.partition(".")[0] + + def callback(ctx: Context, param: Parameter, value: bool) -> None: + if not value or ctx.resilient_parsing: + return + + nonlocal prog_name + nonlocal version + + if prog_name is None: + prog_name = ctx.find_root().info_name + + if version is None and package_name is not None: + metadata: t.Optional[types.ModuleType] + + try: + from importlib import metadata + except ImportError: + # Python < 3.8 + import importlib_metadata as metadata # type: ignore + + try: + version = metadata.version(package_name) # type: ignore + except metadata.PackageNotFoundError: # type: ignore + raise RuntimeError( + f"{package_name!r} is not installed. Try passing" + " 'package_name' instead." + ) from None + + if version is None: + raise RuntimeError( + f"Could not determine the version for {package_name!r} automatically." + ) + + echo( + message % {"prog": prog_name, "package": package_name, "version": version}, + color=ctx.color, + ) + ctx.exit() + + if not param_decls: + param_decls = ("--version",) + + kwargs.setdefault("is_flag", True) + kwargs.setdefault("expose_value", False) + kwargs.setdefault("is_eager", True) + kwargs.setdefault("help", _("Show the version and exit.")) + kwargs["callback"] = callback + return option(*param_decls, **kwargs) + + +class HelpOption(Option): + """Pre-configured ``--help`` option which immediately prints the help page + and exits the program. + """ + + def __init__( + self, + param_decls: t.Optional[t.Sequence[str]] = None, + **kwargs: t.Any, + ) -> None: + if not param_decls: + param_decls = ("--help",) + + kwargs.setdefault("is_flag", True) + kwargs.setdefault("expose_value", False) + kwargs.setdefault("is_eager", True) + kwargs.setdefault("help", _("Show this message and exit.")) + kwargs.setdefault("callback", self.show_help) + + super().__init__(param_decls, **kwargs) + + @staticmethod + def show_help(ctx: Context, param: Parameter, value: bool) -> None: + """Callback that print the help page on ```` and exits.""" + if value and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + +def help_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Decorator for the pre-configured ``--help`` option defined above. + + :param param_decls: One or more option names. Defaults to the single + value ``"--help"``. + :param kwargs: Extra arguments are passed to :func:`option`. + """ + kwargs.setdefault("cls", HelpOption) + return option(*param_decls, **kwargs) diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/exceptions.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/exceptions.py new file mode 100644 index 0000000..0b83151 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/exceptions.py @@ -0,0 +1,296 @@ +import typing as t +from gettext import gettext as _ +from gettext import ngettext + +from ._compat import get_text_stderr +from .globals import resolve_color_default +from .utils import echo +from .utils import format_filename + +if t.TYPE_CHECKING: + from .core import Command + from .core import Context + from .core import Parameter + + +def _join_param_hints( + param_hint: t.Optional[t.Union[t.Sequence[str], str]], +) -> t.Optional[str]: + if param_hint is not None and not isinstance(param_hint, str): + return " / ".join(repr(x) for x in param_hint) + + return param_hint + + +class ClickException(Exception): + """An exception that Click can handle and show to the user.""" + + #: The exit code for this exception. + exit_code = 1 + + def __init__(self, message: str) -> None: + super().__init__(message) + # The context will be removed by the time we print the message, so cache + # the color settings here to be used later on (in `show`) + self.show_color: t.Optional[bool] = resolve_color_default() + self.message = message + + def format_message(self) -> str: + return self.message + + def __str__(self) -> str: + return self.message + + def show(self, file: t.Optional[t.IO[t.Any]] = None) -> None: + if file is None: + file = get_text_stderr() + + echo( + _("Error: {message}").format(message=self.format_message()), + file=file, + color=self.show_color, + ) + + +class UsageError(ClickException): + """An internal exception that signals a usage error. This typically + aborts any further handling. + + :param message: the error message to display. + :param ctx: optionally the context that caused this error. Click will + fill in the context automatically in some situations. + """ + + exit_code = 2 + + def __init__(self, message: str, ctx: t.Optional["Context"] = None) -> None: + super().__init__(message) + self.ctx = ctx + self.cmd: t.Optional[Command] = self.ctx.command if self.ctx else None + + def show(self, file: t.Optional[t.IO[t.Any]] = None) -> None: + if file is None: + file = get_text_stderr() + color = None + hint = "" + if ( + self.ctx is not None + and self.ctx.command.get_help_option(self.ctx) is not None + ): + hint = _("Try '{command} {option}' for help.").format( + command=self.ctx.command_path, option=self.ctx.help_option_names[0] + ) + hint = f"{hint}\n" + if self.ctx is not None: + color = self.ctx.color + echo(f"{self.ctx.get_usage()}\n{hint}", file=file, color=color) + echo( + _("Error: {message}").format(message=self.format_message()), + file=file, + color=color, + ) + + +class BadParameter(UsageError): + """An exception that formats out a standardized error message for a + bad parameter. This is useful when thrown from a callback or type as + Click will attach contextual information to it (for instance, which + parameter it is). + + .. versionadded:: 2.0 + + :param param: the parameter object that caused this error. This can + be left out, and Click will attach this info itself + if possible. + :param param_hint: a string that shows up as parameter name. This + can be used as alternative to `param` in cases + where custom validation should happen. If it is + a string it's used as such, if it's a list then + each item is quoted and separated. + """ + + def __init__( + self, + message: str, + ctx: t.Optional["Context"] = None, + param: t.Optional["Parameter"] = None, + param_hint: t.Optional[str] = None, + ) -> None: + super().__init__(message, ctx) + self.param = param + self.param_hint = param_hint + + def format_message(self) -> str: + if self.param_hint is not None: + param_hint = self.param_hint + elif self.param is not None: + param_hint = self.param.get_error_hint(self.ctx) # type: ignore + else: + return _("Invalid value: {message}").format(message=self.message) + + return _("Invalid value for {param_hint}: {message}").format( + param_hint=_join_param_hints(param_hint), message=self.message + ) + + +class MissingParameter(BadParameter): + """Raised if click required an option or argument but it was not + provided when invoking the script. + + .. versionadded:: 4.0 + + :param param_type: a string that indicates the type of the parameter. + The default is to inherit the parameter type from + the given `param`. Valid values are ``'parameter'``, + ``'option'`` or ``'argument'``. + """ + + def __init__( + self, + message: t.Optional[str] = None, + ctx: t.Optional["Context"] = None, + param: t.Optional["Parameter"] = None, + param_hint: t.Optional[str] = None, + param_type: t.Optional[str] = None, + ) -> None: + super().__init__(message or "", ctx, param, param_hint) + self.param_type = param_type + + def format_message(self) -> str: + if self.param_hint is not None: + param_hint: t.Optional[str] = self.param_hint + elif self.param is not None: + param_hint = self.param.get_error_hint(self.ctx) # type: ignore + else: + param_hint = None + + param_hint = _join_param_hints(param_hint) + param_hint = f" {param_hint}" if param_hint else "" + + param_type = self.param_type + if param_type is None and self.param is not None: + param_type = self.param.param_type_name + + msg = self.message + if self.param is not None: + msg_extra = self.param.type.get_missing_message(self.param) + if msg_extra: + if msg: + msg += f". {msg_extra}" + else: + msg = msg_extra + + msg = f" {msg}" if msg else "" + + # Translate param_type for known types. + if param_type == "argument": + missing = _("Missing argument") + elif param_type == "option": + missing = _("Missing option") + elif param_type == "parameter": + missing = _("Missing parameter") + else: + missing = _("Missing {param_type}").format(param_type=param_type) + + return f"{missing}{param_hint}.{msg}" + + def __str__(self) -> str: + if not self.message: + param_name = self.param.name if self.param else None + return _("Missing parameter: {param_name}").format(param_name=param_name) + else: + return self.message + + +class NoSuchOption(UsageError): + """Raised if click attempted to handle an option that does not + exist. + + .. versionadded:: 4.0 + """ + + def __init__( + self, + option_name: str, + message: t.Optional[str] = None, + possibilities: t.Optional[t.Sequence[str]] = None, + ctx: t.Optional["Context"] = None, + ) -> None: + if message is None: + message = _("No such option: {name}").format(name=option_name) + + super().__init__(message, ctx) + self.option_name = option_name + self.possibilities = possibilities + + def format_message(self) -> str: + if not self.possibilities: + return self.message + + possibility_str = ", ".join(sorted(self.possibilities)) + suggest = ngettext( + "Did you mean {possibility}?", + "(Possible options: {possibilities})", + len(self.possibilities), + ).format(possibility=possibility_str, possibilities=possibility_str) + return f"{self.message} {suggest}" + + +class BadOptionUsage(UsageError): + """Raised if an option is generally supplied but the use of the option + was incorrect. This is for instance raised if the number of arguments + for an option is not correct. + + .. versionadded:: 4.0 + + :param option_name: the name of the option being used incorrectly. + """ + + def __init__( + self, option_name: str, message: str, ctx: t.Optional["Context"] = None + ) -> None: + super().__init__(message, ctx) + self.option_name = option_name + + +class BadArgumentUsage(UsageError): + """Raised if an argument is generally supplied but the use of the argument + was incorrect. This is for instance raised if the number of values + for an argument is not correct. + + .. versionadded:: 6.0 + """ + + +class FileError(ClickException): + """Raised if a file cannot be opened.""" + + def __init__(self, filename: str, hint: t.Optional[str] = None) -> None: + if hint is None: + hint = _("unknown error") + + super().__init__(hint) + self.ui_filename: str = format_filename(filename) + self.filename = filename + + def format_message(self) -> str: + return _("Could not open file {filename!r}: {message}").format( + filename=self.ui_filename, message=self.message + ) + + +class Abort(RuntimeError): + """An internal signalling exception that signals Click to abort.""" + + +class Exit(RuntimeError): + """An exception that indicates that the application should exit with some + status code. + + :param code: the status code to exit with. + """ + + __slots__ = ("exit_code",) + + def __init__(self, code: int = 0) -> None: + self.exit_code: int = code diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/formatting.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/formatting.py new file mode 100644 index 0000000..ddd2a2f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/formatting.py @@ -0,0 +1,301 @@ +import typing as t +from contextlib import contextmanager +from gettext import gettext as _ + +from ._compat import term_len +from .parser import split_opt + +# Can force a width. This is used by the test system +FORCED_WIDTH: t.Optional[int] = None + + +def measure_table(rows: t.Iterable[t.Tuple[str, str]]) -> t.Tuple[int, ...]: + widths: t.Dict[int, int] = {} + + for row in rows: + for idx, col in enumerate(row): + widths[idx] = max(widths.get(idx, 0), term_len(col)) + + return tuple(y for x, y in sorted(widths.items())) + + +def iter_rows( + rows: t.Iterable[t.Tuple[str, str]], col_count: int +) -> t.Iterator[t.Tuple[str, ...]]: + for row in rows: + yield row + ("",) * (col_count - len(row)) + + +def wrap_text( + text: str, + width: int = 78, + initial_indent: str = "", + subsequent_indent: str = "", + preserve_paragraphs: bool = False, +) -> str: + """A helper function that intelligently wraps text. By default, it + assumes that it operates on a single paragraph of text but if the + `preserve_paragraphs` parameter is provided it will intelligently + handle paragraphs (defined by two empty lines). + + If paragraphs are handled, a paragraph can be prefixed with an empty + line containing the ``\\b`` character (``\\x08``) to indicate that + no rewrapping should happen in that block. + + :param text: the text that should be rewrapped. + :param width: the maximum width for the text. + :param initial_indent: the initial indent that should be placed on the + first line as a string. + :param subsequent_indent: the indent string that should be placed on + each consecutive line. + :param preserve_paragraphs: if this flag is set then the wrapping will + intelligently handle paragraphs. + """ + from ._textwrap import TextWrapper + + text = text.expandtabs() + wrapper = TextWrapper( + width, + initial_indent=initial_indent, + subsequent_indent=subsequent_indent, + replace_whitespace=False, + ) + if not preserve_paragraphs: + return wrapper.fill(text) + + p: t.List[t.Tuple[int, bool, str]] = [] + buf: t.List[str] = [] + indent = None + + def _flush_par() -> None: + if not buf: + return + if buf[0].strip() == "\b": + p.append((indent or 0, True, "\n".join(buf[1:]))) + else: + p.append((indent or 0, False, " ".join(buf))) + del buf[:] + + for line in text.splitlines(): + if not line: + _flush_par() + indent = None + else: + if indent is None: + orig_len = term_len(line) + line = line.lstrip() + indent = orig_len - term_len(line) + buf.append(line) + _flush_par() + + rv = [] + for indent, raw, text in p: + with wrapper.extra_indent(" " * indent): + if raw: + rv.append(wrapper.indent_only(text)) + else: + rv.append(wrapper.fill(text)) + + return "\n\n".join(rv) + + +class HelpFormatter: + """This class helps with formatting text-based help pages. It's + usually just needed for very special internal cases, but it's also + exposed so that developers can write their own fancy outputs. + + At present, it always writes into memory. + + :param indent_increment: the additional increment for each level. + :param width: the width for the text. This defaults to the terminal + width clamped to a maximum of 78. + """ + + def __init__( + self, + indent_increment: int = 2, + width: t.Optional[int] = None, + max_width: t.Optional[int] = None, + ) -> None: + import shutil + + self.indent_increment = indent_increment + if max_width is None: + max_width = 80 + if width is None: + width = FORCED_WIDTH + if width is None: + width = max(min(shutil.get_terminal_size().columns, max_width) - 2, 50) + self.width = width + self.current_indent = 0 + self.buffer: t.List[str] = [] + + def write(self, string: str) -> None: + """Writes a unicode string into the internal buffer.""" + self.buffer.append(string) + + def indent(self) -> None: + """Increases the indentation.""" + self.current_indent += self.indent_increment + + def dedent(self) -> None: + """Decreases the indentation.""" + self.current_indent -= self.indent_increment + + def write_usage( + self, prog: str, args: str = "", prefix: t.Optional[str] = None + ) -> None: + """Writes a usage line into the buffer. + + :param prog: the program name. + :param args: whitespace separated list of arguments. + :param prefix: The prefix for the first line. Defaults to + ``"Usage: "``. + """ + if prefix is None: + prefix = f"{_('Usage:')} " + + usage_prefix = f"{prefix:>{self.current_indent}}{prog} " + text_width = self.width - self.current_indent + + if text_width >= (term_len(usage_prefix) + 20): + # The arguments will fit to the right of the prefix. + indent = " " * term_len(usage_prefix) + self.write( + wrap_text( + args, + text_width, + initial_indent=usage_prefix, + subsequent_indent=indent, + ) + ) + else: + # The prefix is too long, put the arguments on the next line. + self.write(usage_prefix) + self.write("\n") + indent = " " * (max(self.current_indent, term_len(prefix)) + 4) + self.write( + wrap_text( + args, text_width, initial_indent=indent, subsequent_indent=indent + ) + ) + + self.write("\n") + + def write_heading(self, heading: str) -> None: + """Writes a heading into the buffer.""" + self.write(f"{'':>{self.current_indent}}{heading}:\n") + + def write_paragraph(self) -> None: + """Writes a paragraph into the buffer.""" + if self.buffer: + self.write("\n") + + def write_text(self, text: str) -> None: + """Writes re-indented text into the buffer. This rewraps and + preserves paragraphs. + """ + indent = " " * self.current_indent + self.write( + wrap_text( + text, + self.width, + initial_indent=indent, + subsequent_indent=indent, + preserve_paragraphs=True, + ) + ) + self.write("\n") + + def write_dl( + self, + rows: t.Sequence[t.Tuple[str, str]], + col_max: int = 30, + col_spacing: int = 2, + ) -> None: + """Writes a definition list into the buffer. This is how options + and commands are usually formatted. + + :param rows: a list of two item tuples for the terms and values. + :param col_max: the maximum width of the first column. + :param col_spacing: the number of spaces between the first and + second column. + """ + rows = list(rows) + widths = measure_table(rows) + if len(widths) != 2: + raise TypeError("Expected two columns for definition list") + + first_col = min(widths[0], col_max) + col_spacing + + for first, second in iter_rows(rows, len(widths)): + self.write(f"{'':>{self.current_indent}}{first}") + if not second: + self.write("\n") + continue + if term_len(first) <= first_col - col_spacing: + self.write(" " * (first_col - term_len(first))) + else: + self.write("\n") + self.write(" " * (first_col + self.current_indent)) + + text_width = max(self.width - first_col - 2, 10) + wrapped_text = wrap_text(second, text_width, preserve_paragraphs=True) + lines = wrapped_text.splitlines() + + if lines: + self.write(f"{lines[0]}\n") + + for line in lines[1:]: + self.write(f"{'':>{first_col + self.current_indent}}{line}\n") + else: + self.write("\n") + + @contextmanager + def section(self, name: str) -> t.Iterator[None]: + """Helpful context manager that writes a paragraph, a heading, + and the indents. + + :param name: the section name that is written as heading. + """ + self.write_paragraph() + self.write_heading(name) + self.indent() + try: + yield + finally: + self.dedent() + + @contextmanager + def indentation(self) -> t.Iterator[None]: + """A context manager that increases the indentation.""" + self.indent() + try: + yield + finally: + self.dedent() + + def getvalue(self) -> str: + """Returns the buffer contents.""" + return "".join(self.buffer) + + +def join_options(options: t.Sequence[str]) -> t.Tuple[str, bool]: + """Given a list of option strings this joins them in the most appropriate + way and returns them in the form ``(formatted_string, + any_prefix_is_slash)`` where the second item in the tuple is a flag that + indicates if any of the option prefixes was a slash. + """ + rv = [] + any_prefix_is_slash = False + + for opt in options: + prefix = split_opt(opt)[0] + + if prefix == "/": + any_prefix_is_slash = True + + rv.append((len(prefix), opt)) + + rv.sort(key=lambda x: x[0]) + return ", ".join(x[1] for x in rv), any_prefix_is_slash diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/globals.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/globals.py new file mode 100644 index 0000000..191e712 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/globals.py @@ -0,0 +1,67 @@ +import typing as t +from threading import local + +if t.TYPE_CHECKING: + import typing_extensions as te + + from .core import Context + +_local = local() + + +@t.overload +def get_current_context(silent: "te.Literal[False]" = False) -> "Context": ... + + +@t.overload +def get_current_context(silent: bool = ...) -> t.Optional["Context"]: ... + + +def get_current_context(silent: bool = False) -> t.Optional["Context"]: + """Returns the current click context. This can be used as a way to + access the current context object from anywhere. This is a more implicit + alternative to the :func:`pass_context` decorator. This function is + primarily useful for helpers such as :func:`echo` which might be + interested in changing its behavior based on the current context. + + To push the current context, :meth:`Context.scope` can be used. + + .. versionadded:: 5.0 + + :param silent: if set to `True` the return value is `None` if no context + is available. The default behavior is to raise a + :exc:`RuntimeError`. + """ + try: + return t.cast("Context", _local.stack[-1]) + except (AttributeError, IndexError) as e: + if not silent: + raise RuntimeError("There is no active click context.") from e + + return None + + +def push_context(ctx: "Context") -> None: + """Pushes a new context to the current stack.""" + _local.__dict__.setdefault("stack", []).append(ctx) + + +def pop_context() -> None: + """Removes the top level from the stack.""" + _local.stack.pop() + + +def resolve_color_default(color: t.Optional[bool] = None) -> t.Optional[bool]: + """Internal helper to get the default value of the color flag. If a + value is passed it's returned unchanged, otherwise it's looked up from + the current context. + """ + if color is not None: + return color + + ctx = get_current_context(silent=True) + + if ctx is not None: + return ctx.color + + return None diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/parser.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/parser.py new file mode 100644 index 0000000..600b843 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/parser.py @@ -0,0 +1,531 @@ +""" +This module started out as largely a copy paste from the stdlib's +optparse module with the features removed that we do not need from +optparse because we implement them in Click on a higher level (for +instance type handling, help formatting and a lot more). + +The plan is to remove more and more from here over time. + +The reason this is a different module and not optparse from the stdlib +is that there are differences in 2.x and 3.x about the error messages +generated and optparse in the stdlib uses gettext for no good reason +and might cause us issues. + +Click uses parts of optparse written by Gregory P. Ward and maintained +by the Python Software Foundation. This is limited to code in parser.py. + +Copyright 2001-2006 Gregory P. Ward. All rights reserved. +Copyright 2002-2006 Python Software Foundation. All rights reserved. +""" + +# This code uses parts of optparse written by Gregory P. Ward and +# maintained by the Python Software Foundation. +# Copyright 2001-2006 Gregory P. Ward +# Copyright 2002-2006 Python Software Foundation +import typing as t +from collections import deque +from gettext import gettext as _ +from gettext import ngettext + +from .exceptions import BadArgumentUsage +from .exceptions import BadOptionUsage +from .exceptions import NoSuchOption +from .exceptions import UsageError + +if t.TYPE_CHECKING: + import typing_extensions as te + + from .core import Argument as CoreArgument + from .core import Context + from .core import Option as CoreOption + from .core import Parameter as CoreParameter + +V = t.TypeVar("V") + +# Sentinel value that indicates an option was passed as a flag without a +# value but is not a flag option. Option.consume_value uses this to +# prompt or use the flag_value. +_flag_needs_value = object() + + +def _unpack_args( + args: t.Sequence[str], nargs_spec: t.Sequence[int] +) -> t.Tuple[t.Sequence[t.Union[str, t.Sequence[t.Optional[str]], None]], t.List[str]]: + """Given an iterable of arguments and an iterable of nargs specifications, + it returns a tuple with all the unpacked arguments at the first index + and all remaining arguments as the second. + + The nargs specification is the number of arguments that should be consumed + or `-1` to indicate that this position should eat up all the remainders. + + Missing items are filled with `None`. + """ + args = deque(args) + nargs_spec = deque(nargs_spec) + rv: t.List[t.Union[str, t.Tuple[t.Optional[str], ...], None]] = [] + spos: t.Optional[int] = None + + def _fetch(c: "te.Deque[V]") -> t.Optional[V]: + try: + if spos is None: + return c.popleft() + else: + return c.pop() + except IndexError: + return None + + while nargs_spec: + nargs = _fetch(nargs_spec) + + if nargs is None: + continue + + if nargs == 1: + rv.append(_fetch(args)) + elif nargs > 1: + x = [_fetch(args) for _ in range(nargs)] + + # If we're reversed, we're pulling in the arguments in reverse, + # so we need to turn them around. + if spos is not None: + x.reverse() + + rv.append(tuple(x)) + elif nargs < 0: + if spos is not None: + raise TypeError("Cannot have two nargs < 0") + + spos = len(rv) + rv.append(None) + + # spos is the position of the wildcard (star). If it's not `None`, + # we fill it with the remainder. + if spos is not None: + rv[spos] = tuple(args) + args = [] + rv[spos + 1 :] = reversed(rv[spos + 1 :]) + + return tuple(rv), list(args) + + +def split_opt(opt: str) -> t.Tuple[str, str]: + first = opt[:1] + if first.isalnum(): + return "", opt + if opt[1:2] == first: + return opt[:2], opt[2:] + return first, opt[1:] + + +def normalize_opt(opt: str, ctx: t.Optional["Context"]) -> str: + if ctx is None or ctx.token_normalize_func is None: + return opt + prefix, opt = split_opt(opt) + return f"{prefix}{ctx.token_normalize_func(opt)}" + + +def split_arg_string(string: str) -> t.List[str]: + """Split an argument string as with :func:`shlex.split`, but don't + fail if the string is incomplete. Ignores a missing closing quote or + incomplete escape sequence and uses the partial token as-is. + + .. code-block:: python + + split_arg_string("example 'my file") + ["example", "my file"] + + split_arg_string("example my\\") + ["example", "my"] + + :param string: String to split. + """ + import shlex + + lex = shlex.shlex(string, posix=True) + lex.whitespace_split = True + lex.commenters = "" + out = [] + + try: + for token in lex: + out.append(token) + except ValueError: + # Raised when end-of-string is reached in an invalid state. Use + # the partial token as-is. The quote or escape character is in + # lex.state, not lex.token. + out.append(lex.token) + + return out + + +class Option: + def __init__( + self, + obj: "CoreOption", + opts: t.Sequence[str], + dest: t.Optional[str], + action: t.Optional[str] = None, + nargs: int = 1, + const: t.Optional[t.Any] = None, + ): + self._short_opts = [] + self._long_opts = [] + self.prefixes: t.Set[str] = set() + + for opt in opts: + prefix, value = split_opt(opt) + if not prefix: + raise ValueError(f"Invalid start character for option ({opt})") + self.prefixes.add(prefix[0]) + if len(prefix) == 1 and len(value) == 1: + self._short_opts.append(opt) + else: + self._long_opts.append(opt) + self.prefixes.add(prefix) + + if action is None: + action = "store" + + self.dest = dest + self.action = action + self.nargs = nargs + self.const = const + self.obj = obj + + @property + def takes_value(self) -> bool: + return self.action in ("store", "append") + + def process(self, value: t.Any, state: "ParsingState") -> None: + if self.action == "store": + state.opts[self.dest] = value # type: ignore + elif self.action == "store_const": + state.opts[self.dest] = self.const # type: ignore + elif self.action == "append": + state.opts.setdefault(self.dest, []).append(value) # type: ignore + elif self.action == "append_const": + state.opts.setdefault(self.dest, []).append(self.const) # type: ignore + elif self.action == "count": + state.opts[self.dest] = state.opts.get(self.dest, 0) + 1 # type: ignore + else: + raise ValueError(f"unknown action '{self.action}'") + state.order.append(self.obj) + + +class Argument: + def __init__(self, obj: "CoreArgument", dest: t.Optional[str], nargs: int = 1): + self.dest = dest + self.nargs = nargs + self.obj = obj + + def process( + self, + value: t.Union[t.Optional[str], t.Sequence[t.Optional[str]]], + state: "ParsingState", + ) -> None: + if self.nargs > 1: + assert value is not None + holes = sum(1 for x in value if x is None) + if holes == len(value): + value = None + elif holes != 0: + raise BadArgumentUsage( + _("Argument {name!r} takes {nargs} values.").format( + name=self.dest, nargs=self.nargs + ) + ) + + if self.nargs == -1 and self.obj.envvar is not None and value == (): + # Replace empty tuple with None so that a value from the + # environment may be tried. + value = None + + state.opts[self.dest] = value # type: ignore + state.order.append(self.obj) + + +class ParsingState: + def __init__(self, rargs: t.List[str]) -> None: + self.opts: t.Dict[str, t.Any] = {} + self.largs: t.List[str] = [] + self.rargs = rargs + self.order: t.List[CoreParameter] = [] + + +class OptionParser: + """The option parser is an internal class that is ultimately used to + parse options and arguments. It's modelled after optparse and brings + a similar but vastly simplified API. It should generally not be used + directly as the high level Click classes wrap it for you. + + It's not nearly as extensible as optparse or argparse as it does not + implement features that are implemented on a higher level (such as + types or defaults). + + :param ctx: optionally the :class:`~click.Context` where this parser + should go with. + """ + + def __init__(self, ctx: t.Optional["Context"] = None) -> None: + #: The :class:`~click.Context` for this parser. This might be + #: `None` for some advanced use cases. + self.ctx = ctx + #: This controls how the parser deals with interspersed arguments. + #: If this is set to `False`, the parser will stop on the first + #: non-option. Click uses this to implement nested subcommands + #: safely. + self.allow_interspersed_args: bool = True + #: This tells the parser how to deal with unknown options. By + #: default it will error out (which is sensible), but there is a + #: second mode where it will ignore it and continue processing + #: after shifting all the unknown options into the resulting args. + self.ignore_unknown_options: bool = False + + if ctx is not None: + self.allow_interspersed_args = ctx.allow_interspersed_args + self.ignore_unknown_options = ctx.ignore_unknown_options + + self._short_opt: t.Dict[str, Option] = {} + self._long_opt: t.Dict[str, Option] = {} + self._opt_prefixes = {"-", "--"} + self._args: t.List[Argument] = [] + + def add_option( + self, + obj: "CoreOption", + opts: t.Sequence[str], + dest: t.Optional[str], + action: t.Optional[str] = None, + nargs: int = 1, + const: t.Optional[t.Any] = None, + ) -> None: + """Adds a new option named `dest` to the parser. The destination + is not inferred (unlike with optparse) and needs to be explicitly + provided. Action can be any of ``store``, ``store_const``, + ``append``, ``append_const`` or ``count``. + + The `obj` can be used to identify the option in the order list + that is returned from the parser. + """ + opts = [normalize_opt(opt, self.ctx) for opt in opts] + option = Option(obj, opts, dest, action=action, nargs=nargs, const=const) + self._opt_prefixes.update(option.prefixes) + for opt in option._short_opts: + self._short_opt[opt] = option + for opt in option._long_opts: + self._long_opt[opt] = option + + def add_argument( + self, obj: "CoreArgument", dest: t.Optional[str], nargs: int = 1 + ) -> None: + """Adds a positional argument named `dest` to the parser. + + The `obj` can be used to identify the option in the order list + that is returned from the parser. + """ + self._args.append(Argument(obj, dest=dest, nargs=nargs)) + + def parse_args( + self, args: t.List[str] + ) -> t.Tuple[t.Dict[str, t.Any], t.List[str], t.List["CoreParameter"]]: + """Parses positional arguments and returns ``(values, args, order)`` + for the parsed options and arguments as well as the leftover + arguments if there are any. The order is a list of objects as they + appear on the command line. If arguments appear multiple times they + will be memorized multiple times as well. + """ + state = ParsingState(args) + try: + self._process_args_for_options(state) + self._process_args_for_args(state) + except UsageError: + if self.ctx is None or not self.ctx.resilient_parsing: + raise + return state.opts, state.largs, state.order + + def _process_args_for_args(self, state: ParsingState) -> None: + pargs, args = _unpack_args( + state.largs + state.rargs, [x.nargs for x in self._args] + ) + + for idx, arg in enumerate(self._args): + arg.process(pargs[idx], state) + + state.largs = args + state.rargs = [] + + def _process_args_for_options(self, state: ParsingState) -> None: + while state.rargs: + arg = state.rargs.pop(0) + arglen = len(arg) + # Double dashes always handled explicitly regardless of what + # prefixes are valid. + if arg == "--": + return + elif arg[:1] in self._opt_prefixes and arglen > 1: + self._process_opts(arg, state) + elif self.allow_interspersed_args: + state.largs.append(arg) + else: + state.rargs.insert(0, arg) + return + + # Say this is the original argument list: + # [arg0, arg1, ..., arg(i-1), arg(i), arg(i+1), ..., arg(N-1)] + # ^ + # (we are about to process arg(i)). + # + # Then rargs is [arg(i), ..., arg(N-1)] and largs is a *subset* of + # [arg0, ..., arg(i-1)] (any options and their arguments will have + # been removed from largs). + # + # The while loop will usually consume 1 or more arguments per pass. + # If it consumes 1 (eg. arg is an option that takes no arguments), + # then after _process_arg() is done the situation is: + # + # largs = subset of [arg0, ..., arg(i)] + # rargs = [arg(i+1), ..., arg(N-1)] + # + # If allow_interspersed_args is false, largs will always be + # *empty* -- still a subset of [arg0, ..., arg(i-1)], but + # not a very interesting subset! + + def _match_long_opt( + self, opt: str, explicit_value: t.Optional[str], state: ParsingState + ) -> None: + if opt not in self._long_opt: + from difflib import get_close_matches + + possibilities = get_close_matches(opt, self._long_opt) + raise NoSuchOption(opt, possibilities=possibilities, ctx=self.ctx) + + option = self._long_opt[opt] + if option.takes_value: + # At this point it's safe to modify rargs by injecting the + # explicit value, because no exception is raised in this + # branch. This means that the inserted value will be fully + # consumed. + if explicit_value is not None: + state.rargs.insert(0, explicit_value) + + value = self._get_value_from_state(opt, option, state) + + elif explicit_value is not None: + raise BadOptionUsage( + opt, _("Option {name!r} does not take a value.").format(name=opt) + ) + + else: + value = None + + option.process(value, state) + + def _match_short_opt(self, arg: str, state: ParsingState) -> None: + stop = False + i = 1 + prefix = arg[0] + unknown_options = [] + + for ch in arg[1:]: + opt = normalize_opt(f"{prefix}{ch}", self.ctx) + option = self._short_opt.get(opt) + i += 1 + + if not option: + if self.ignore_unknown_options: + unknown_options.append(ch) + continue + raise NoSuchOption(opt, ctx=self.ctx) + if option.takes_value: + # Any characters left in arg? Pretend they're the + # next arg, and stop consuming characters of arg. + if i < len(arg): + state.rargs.insert(0, arg[i:]) + stop = True + + value = self._get_value_from_state(opt, option, state) + + else: + value = None + + option.process(value, state) + + if stop: + break + + # If we got any unknown options we recombine the string of the + # remaining options and re-attach the prefix, then report that + # to the state as new larg. This way there is basic combinatorics + # that can be achieved while still ignoring unknown arguments. + if self.ignore_unknown_options and unknown_options: + state.largs.append(f"{prefix}{''.join(unknown_options)}") + + def _get_value_from_state( + self, option_name: str, option: Option, state: ParsingState + ) -> t.Any: + nargs = option.nargs + + if len(state.rargs) < nargs: + if option.obj._flag_needs_value: + # Option allows omitting the value. + value = _flag_needs_value + else: + raise BadOptionUsage( + option_name, + ngettext( + "Option {name!r} requires an argument.", + "Option {name!r} requires {nargs} arguments.", + nargs, + ).format(name=option_name, nargs=nargs), + ) + elif nargs == 1: + next_rarg = state.rargs[0] + + if ( + option.obj._flag_needs_value + and isinstance(next_rarg, str) + and next_rarg[:1] in self._opt_prefixes + and len(next_rarg) > 1 + ): + # The next arg looks like the start of an option, don't + # use it as the value if omitting the value is allowed. + value = _flag_needs_value + else: + value = state.rargs.pop(0) + else: + value = tuple(state.rargs[:nargs]) + del state.rargs[:nargs] + + return value + + def _process_opts(self, arg: str, state: ParsingState) -> None: + explicit_value = None + # Long option handling happens in two parts. The first part is + # supporting explicitly attached values. In any case, we will try + # to long match the option first. + if "=" in arg: + long_opt, explicit_value = arg.split("=", 1) + else: + long_opt = arg + norm_long_opt = normalize_opt(long_opt, self.ctx) + + # At this point we will match the (assumed) long option through + # the long option matching code. Note that this allows options + # like "-foo" to be matched as long options. + try: + self._match_long_opt(norm_long_opt, explicit_value, state) + except NoSuchOption: + # At this point the long option matching failed, and we need + # to try with short options. However there is a special rule + # which says, that if we have a two character options prefix + # (applies to "--foo" for instance), we do not dispatch to the + # short option code and will instead raise the no option + # error. + if arg[:2] not in self._opt_prefixes: + self._match_short_opt(arg, state) + return + + if not self.ignore_unknown_options: + raise + + state.largs.append(arg) diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/py.typed b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/shell_completion.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/shell_completion.py new file mode 100644 index 0000000..07d0f09 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/shell_completion.py @@ -0,0 +1,603 @@ +import os +import re +import typing as t +from gettext import gettext as _ + +from .core import Argument +from .core import BaseCommand +from .core import Context +from .core import MultiCommand +from .core import Option +from .core import Parameter +from .core import ParameterSource +from .parser import split_arg_string +from .utils import echo + + +def shell_complete( + cli: BaseCommand, + ctx_args: t.MutableMapping[str, t.Any], + prog_name: str, + complete_var: str, + instruction: str, +) -> int: + """Perform shell completion for the given CLI program. + + :param cli: Command being called. + :param ctx_args: Extra arguments to pass to + ``cli.make_context``. + :param prog_name: Name of the executable in the shell. + :param complete_var: Name of the environment variable that holds + the completion instruction. + :param instruction: Value of ``complete_var`` with the completion + instruction and shell, in the form ``instruction_shell``. + :return: Status code to exit with. + """ + shell, _, instruction = instruction.partition("_") + comp_cls = get_completion_class(shell) + + if comp_cls is None: + return 1 + + comp = comp_cls(cli, ctx_args, prog_name, complete_var) + + if instruction == "source": + echo(comp.source()) + return 0 + + if instruction == "complete": + echo(comp.complete()) + return 0 + + return 1 + + +class CompletionItem: + """Represents a completion value and metadata about the value. The + default metadata is ``type`` to indicate special shell handling, + and ``help`` if a shell supports showing a help string next to the + value. + + Arbitrary parameters can be passed when creating the object, and + accessed using ``item.attr``. If an attribute wasn't passed, + accessing it returns ``None``. + + :param value: The completion suggestion. + :param type: Tells the shell script to provide special completion + support for the type. Click uses ``"dir"`` and ``"file"``. + :param help: String shown next to the value if supported. + :param kwargs: Arbitrary metadata. The built-in implementations + don't use this, but custom type completions paired with custom + shell support could use it. + """ + + __slots__ = ("value", "type", "help", "_info") + + def __init__( + self, + value: t.Any, + type: str = "plain", + help: t.Optional[str] = None, + **kwargs: t.Any, + ) -> None: + self.value: t.Any = value + self.type: str = type + self.help: t.Optional[str] = help + self._info = kwargs + + def __getattr__(self, name: str) -> t.Any: + return self._info.get(name) + + +# Only Bash >= 4.4 has the nosort option. +_SOURCE_BASH = """\ +%(complete_func)s() { + local IFS=$'\\n' + local response + + response=$(env COMP_WORDS="${COMP_WORDS[*]}" COMP_CWORD=$COMP_CWORD \ +%(complete_var)s=bash_complete $1) + + for completion in $response; do + IFS=',' read type value <<< "$completion" + + if [[ $type == 'dir' ]]; then + COMPREPLY=() + compopt -o dirnames + elif [[ $type == 'file' ]]; then + COMPREPLY=() + compopt -o default + elif [[ $type == 'plain' ]]; then + COMPREPLY+=($value) + fi + done + + return 0 +} + +%(complete_func)s_setup() { + complete -o nosort -F %(complete_func)s %(prog_name)s +} + +%(complete_func)s_setup; +""" + +_SOURCE_ZSH = """\ +#compdef %(prog_name)s + +%(complete_func)s() { + local -a completions + local -a completions_with_descriptions + local -a response + (( ! $+commands[%(prog_name)s] )) && return 1 + + response=("${(@f)$(env COMP_WORDS="${words[*]}" COMP_CWORD=$((CURRENT-1)) \ +%(complete_var)s=zsh_complete %(prog_name)s)}") + + for type key descr in ${response}; do + if [[ "$type" == "plain" ]]; then + if [[ "$descr" == "_" ]]; then + completions+=("$key") + else + completions_with_descriptions+=("$key":"$descr") + fi + elif [[ "$type" == "dir" ]]; then + _path_files -/ + elif [[ "$type" == "file" ]]; then + _path_files -f + fi + done + + if [ -n "$completions_with_descriptions" ]; then + _describe -V unsorted completions_with_descriptions -U + fi + + if [ -n "$completions" ]; then + compadd -U -V unsorted -a completions + fi +} + +if [[ $zsh_eval_context[-1] == loadautofunc ]]; then + # autoload from fpath, call function directly + %(complete_func)s "$@" +else + # eval/source/. command, register function for later + compdef %(complete_func)s %(prog_name)s +fi +""" + +_SOURCE_FISH = """\ +function %(complete_func)s; + set -l response (env %(complete_var)s=fish_complete COMP_WORDS=(commandline -cp) \ +COMP_CWORD=(commandline -t) %(prog_name)s); + + for completion in $response; + set -l metadata (string split "," $completion); + + if test $metadata[1] = "dir"; + __fish_complete_directories $metadata[2]; + else if test $metadata[1] = "file"; + __fish_complete_path $metadata[2]; + else if test $metadata[1] = "plain"; + echo $metadata[2]; + end; + end; +end; + +complete --no-files --command %(prog_name)s --arguments \ +"(%(complete_func)s)"; +""" + + +class ShellComplete: + """Base class for providing shell completion support. A subclass for + a given shell will override attributes and methods to implement the + completion instructions (``source`` and ``complete``). + + :param cli: Command being called. + :param prog_name: Name of the executable in the shell. + :param complete_var: Name of the environment variable that holds + the completion instruction. + + .. versionadded:: 8.0 + """ + + name: t.ClassVar[str] + """Name to register the shell as with :func:`add_completion_class`. + This is used in completion instructions (``{name}_source`` and + ``{name}_complete``). + """ + + source_template: t.ClassVar[str] + """Completion script template formatted by :meth:`source`. This must + be provided by subclasses. + """ + + def __init__( + self, + cli: BaseCommand, + ctx_args: t.MutableMapping[str, t.Any], + prog_name: str, + complete_var: str, + ) -> None: + self.cli = cli + self.ctx_args = ctx_args + self.prog_name = prog_name + self.complete_var = complete_var + + @property + def func_name(self) -> str: + """The name of the shell function defined by the completion + script. + """ + safe_name = re.sub(r"\W*", "", self.prog_name.replace("-", "_"), flags=re.ASCII) + return f"_{safe_name}_completion" + + def source_vars(self) -> t.Dict[str, t.Any]: + """Vars for formatting :attr:`source_template`. + + By default this provides ``complete_func``, ``complete_var``, + and ``prog_name``. + """ + return { + "complete_func": self.func_name, + "complete_var": self.complete_var, + "prog_name": self.prog_name, + } + + def source(self) -> str: + """Produce the shell script that defines the completion + function. By default this ``%``-style formats + :attr:`source_template` with the dict returned by + :meth:`source_vars`. + """ + return self.source_template % self.source_vars() + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + """Use the env vars defined by the shell script to return a + tuple of ``args, incomplete``. This must be implemented by + subclasses. + """ + raise NotImplementedError + + def get_completions( + self, args: t.List[str], incomplete: str + ) -> t.List[CompletionItem]: + """Determine the context and last complete command or parameter + from the complete args. Call that object's ``shell_complete`` + method to get the completions for the incomplete value. + + :param args: List of complete args before the incomplete value. + :param incomplete: Value being completed. May be empty. + """ + ctx = _resolve_context(self.cli, self.ctx_args, self.prog_name, args) + obj, incomplete = _resolve_incomplete(ctx, args, incomplete) + return obj.shell_complete(ctx, incomplete) + + def format_completion(self, item: CompletionItem) -> str: + """Format a completion item into the form recognized by the + shell script. This must be implemented by subclasses. + + :param item: Completion item to format. + """ + raise NotImplementedError + + def complete(self) -> str: + """Produce the completion data to send back to the shell. + + By default this calls :meth:`get_completion_args`, gets the + completions, then calls :meth:`format_completion` for each + completion. + """ + args, incomplete = self.get_completion_args() + completions = self.get_completions(args, incomplete) + out = [self.format_completion(item) for item in completions] + return "\n".join(out) + + +class BashComplete(ShellComplete): + """Shell completion for Bash.""" + + name = "bash" + source_template = _SOURCE_BASH + + @staticmethod + def _check_version() -> None: + import shutil + import subprocess + + bash_exe = shutil.which("bash") + + if bash_exe is None: + match = None + else: + output = subprocess.run( + [bash_exe, "--norc", "-c", 'echo "${BASH_VERSION}"'], + stdout=subprocess.PIPE, + ) + match = re.search(r"^(\d+)\.(\d+)\.\d+", output.stdout.decode()) + + if match is not None: + major, minor = match.groups() + + if major < "4" or major == "4" and minor < "4": + echo( + _( + "Shell completion is not supported for Bash" + " versions older than 4.4." + ), + err=True, + ) + else: + echo( + _("Couldn't detect Bash version, shell completion is not supported."), + err=True, + ) + + def source(self) -> str: + self._check_version() + return super().source() + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + cword = int(os.environ["COMP_CWORD"]) + args = cwords[1:cword] + + try: + incomplete = cwords[cword] + except IndexError: + incomplete = "" + + return args, incomplete + + def format_completion(self, item: CompletionItem) -> str: + return f"{item.type},{item.value}" + + +class ZshComplete(ShellComplete): + """Shell completion for Zsh.""" + + name = "zsh" + source_template = _SOURCE_ZSH + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + cword = int(os.environ["COMP_CWORD"]) + args = cwords[1:cword] + + try: + incomplete = cwords[cword] + except IndexError: + incomplete = "" + + return args, incomplete + + def format_completion(self, item: CompletionItem) -> str: + return f"{item.type}\n{item.value}\n{item.help if item.help else '_'}" + + +class FishComplete(ShellComplete): + """Shell completion for Fish.""" + + name = "fish" + source_template = _SOURCE_FISH + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + incomplete = os.environ["COMP_CWORD"] + args = cwords[1:] + + # Fish stores the partial word in both COMP_WORDS and + # COMP_CWORD, remove it from complete args. + if incomplete and args and args[-1] == incomplete: + args.pop() + + return args, incomplete + + def format_completion(self, item: CompletionItem) -> str: + if item.help: + return f"{item.type},{item.value}\t{item.help}" + + return f"{item.type},{item.value}" + + +ShellCompleteType = t.TypeVar("ShellCompleteType", bound=t.Type[ShellComplete]) + + +_available_shells: t.Dict[str, t.Type[ShellComplete]] = { + "bash": BashComplete, + "fish": FishComplete, + "zsh": ZshComplete, +} + + +def add_completion_class( + cls: ShellCompleteType, name: t.Optional[str] = None +) -> ShellCompleteType: + """Register a :class:`ShellComplete` subclass under the given name. + The name will be provided by the completion instruction environment + variable during completion. + + :param cls: The completion class that will handle completion for the + shell. + :param name: Name to register the class under. Defaults to the + class's ``name`` attribute. + """ + if name is None: + name = cls.name + + _available_shells[name] = cls + + return cls + + +def get_completion_class(shell: str) -> t.Optional[t.Type[ShellComplete]]: + """Look up a registered :class:`ShellComplete` subclass by the name + provided by the completion instruction environment variable. If the + name isn't registered, returns ``None``. + + :param shell: Name the class is registered under. + """ + return _available_shells.get(shell) + + +def _is_incomplete_argument(ctx: Context, param: Parameter) -> bool: + """Determine if the given parameter is an argument that can still + accept values. + + :param ctx: Invocation context for the command represented by the + parsed complete args. + :param param: Argument object being checked. + """ + if not isinstance(param, Argument): + return False + + assert param.name is not None + # Will be None if expose_value is False. + value = ctx.params.get(param.name) + return ( + param.nargs == -1 + or ctx.get_parameter_source(param.name) is not ParameterSource.COMMANDLINE + or ( + param.nargs > 1 + and isinstance(value, (tuple, list)) + and len(value) < param.nargs + ) + ) + + +def _start_of_option(ctx: Context, value: str) -> bool: + """Check if the value looks like the start of an option.""" + if not value: + return False + + c = value[0] + return c in ctx._opt_prefixes + + +def _is_incomplete_option(ctx: Context, args: t.List[str], param: Parameter) -> bool: + """Determine if the given parameter is an option that needs a value. + + :param args: List of complete args before the incomplete value. + :param param: Option object being checked. + """ + if not isinstance(param, Option): + return False + + if param.is_flag or param.count: + return False + + last_option = None + + for index, arg in enumerate(reversed(args)): + if index + 1 > param.nargs: + break + + if _start_of_option(ctx, arg): + last_option = arg + + return last_option is not None and last_option in param.opts + + +def _resolve_context( + cli: BaseCommand, + ctx_args: t.MutableMapping[str, t.Any], + prog_name: str, + args: t.List[str], +) -> Context: + """Produce the context hierarchy starting with the command and + traversing the complete arguments. This only follows the commands, + it doesn't trigger input prompts or callbacks. + + :param cli: Command being called. + :param prog_name: Name of the executable in the shell. + :param args: List of complete args before the incomplete value. + """ + ctx_args["resilient_parsing"] = True + ctx = cli.make_context(prog_name, args.copy(), **ctx_args) + args = ctx.protected_args + ctx.args + + while args: + command = ctx.command + + if isinstance(command, MultiCommand): + if not command.chain: + name, cmd, args = command.resolve_command(ctx, args) + + if cmd is None: + return ctx + + ctx = cmd.make_context(name, args, parent=ctx, resilient_parsing=True) + args = ctx.protected_args + ctx.args + else: + sub_ctx = ctx + + while args: + name, cmd, args = command.resolve_command(ctx, args) + + if cmd is None: + return ctx + + sub_ctx = cmd.make_context( + name, + args, + parent=ctx, + allow_extra_args=True, + allow_interspersed_args=False, + resilient_parsing=True, + ) + args = sub_ctx.args + + ctx = sub_ctx + args = [*sub_ctx.protected_args, *sub_ctx.args] + else: + break + + return ctx + + +def _resolve_incomplete( + ctx: Context, args: t.List[str], incomplete: str +) -> t.Tuple[t.Union[BaseCommand, Parameter], str]: + """Find the Click object that will handle the completion of the + incomplete value. Return the object and the incomplete value. + + :param ctx: Invocation context for the command represented by + the parsed complete args. + :param args: List of complete args before the incomplete value. + :param incomplete: Value being completed. May be empty. + """ + # Different shells treat an "=" between a long option name and + # value differently. Might keep the value joined, return the "=" + # as a separate item, or return the split name and value. Always + # split and discard the "=" to make completion easier. + if incomplete == "=": + incomplete = "" + elif "=" in incomplete and _start_of_option(ctx, incomplete): + name, _, incomplete = incomplete.partition("=") + args.append(name) + + # The "--" marker tells Click to stop treating values as options + # even if they start with the option character. If it hasn't been + # given and the incomplete arg looks like an option, the current + # command will provide option name completions. + if "--" not in args and _start_of_option(ctx, incomplete): + return ctx.command, incomplete + + params = ctx.command.get_params(ctx) + + # If the last complete arg is an option name with an incomplete + # value, the option will provide value completions. + for param in params: + if _is_incomplete_option(ctx, args, param): + return param, incomplete + + # It's not an option name or value. The first argument without a + # parsed value will provide value completions. + for param in params: + if _is_incomplete_argument(ctx, param): + return param, incomplete + + # There were no unparsed arguments, the command may be a group that + # will provide command name completions. + return ctx.command, incomplete diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/termui.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/termui.py new file mode 100644 index 0000000..c084f19 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/termui.py @@ -0,0 +1,784 @@ +import inspect +import io +import itertools +import sys +import typing as t +from gettext import gettext as _ + +from ._compat import isatty +from ._compat import strip_ansi +from .exceptions import Abort +from .exceptions import UsageError +from .globals import resolve_color_default +from .types import Choice +from .types import convert_type +from .types import ParamType +from .utils import echo +from .utils import LazyFile + +if t.TYPE_CHECKING: + from ._termui_impl import ProgressBar + +V = t.TypeVar("V") + +# The prompt functions to use. The doc tools currently override these +# functions to customize how they work. +visible_prompt_func: t.Callable[[str], str] = input + +_ansi_colors = { + "black": 30, + "red": 31, + "green": 32, + "yellow": 33, + "blue": 34, + "magenta": 35, + "cyan": 36, + "white": 37, + "reset": 39, + "bright_black": 90, + "bright_red": 91, + "bright_green": 92, + "bright_yellow": 93, + "bright_blue": 94, + "bright_magenta": 95, + "bright_cyan": 96, + "bright_white": 97, +} +_ansi_reset_all = "\033[0m" + + +def hidden_prompt_func(prompt: str) -> str: + import getpass + + return getpass.getpass(prompt) + + +def _build_prompt( + text: str, + suffix: str, + show_default: bool = False, + default: t.Optional[t.Any] = None, + show_choices: bool = True, + type: t.Optional[ParamType] = None, +) -> str: + prompt = text + if type is not None and show_choices and isinstance(type, Choice): + prompt += f" ({', '.join(map(str, type.choices))})" + if default is not None and show_default: + prompt = f"{prompt} [{_format_default(default)}]" + return f"{prompt}{suffix}" + + +def _format_default(default: t.Any) -> t.Any: + if isinstance(default, (io.IOBase, LazyFile)) and hasattr(default, "name"): + return default.name + + return default + + +def prompt( + text: str, + default: t.Optional[t.Any] = None, + hide_input: bool = False, + confirmation_prompt: t.Union[bool, str] = False, + type: t.Optional[t.Union[ParamType, t.Any]] = None, + value_proc: t.Optional[t.Callable[[str], t.Any]] = None, + prompt_suffix: str = ": ", + show_default: bool = True, + err: bool = False, + show_choices: bool = True, +) -> t.Any: + """Prompts a user for input. This is a convenience function that can + be used to prompt a user for input later. + + If the user aborts the input by sending an interrupt signal, this + function will catch it and raise a :exc:`Abort` exception. + + :param text: the text to show for the prompt. + :param default: the default value to use if no input happens. If this + is not given it will prompt until it's aborted. + :param hide_input: if this is set to true then the input value will + be hidden. + :param confirmation_prompt: Prompt a second time to confirm the + value. Can be set to a string instead of ``True`` to customize + the message. + :param type: the type to use to check the value against. + :param value_proc: if this parameter is provided it's a function that + is invoked instead of the type conversion to + convert a value. + :param prompt_suffix: a suffix that should be added to the prompt. + :param show_default: shows or hides the default value in the prompt. + :param err: if set to true the file defaults to ``stderr`` instead of + ``stdout``, the same as with echo. + :param show_choices: Show or hide choices if the passed type is a Choice. + For example if type is a Choice of either day or week, + show_choices is true and text is "Group by" then the + prompt will be "Group by (day, week): ". + + .. versionadded:: 8.0 + ``confirmation_prompt`` can be a custom string. + + .. versionadded:: 7.0 + Added the ``show_choices`` parameter. + + .. versionadded:: 6.0 + Added unicode support for cmd.exe on Windows. + + .. versionadded:: 4.0 + Added the `err` parameter. + + """ + + def prompt_func(text: str) -> str: + f = hidden_prompt_func if hide_input else visible_prompt_func + try: + # Write the prompt separately so that we get nice + # coloring through colorama on Windows + echo(text.rstrip(" "), nl=False, err=err) + # Echo a space to stdout to work around an issue where + # readline causes backspace to clear the whole line. + return f(" ") + except (KeyboardInterrupt, EOFError): + # getpass doesn't print a newline if the user aborts input with ^C. + # Allegedly this behavior is inherited from getpass(3). + # A doc bug has been filed at https://bugs.python.org/issue24711 + if hide_input: + echo(None, err=err) + raise Abort() from None + + if value_proc is None: + value_proc = convert_type(type, default) + + prompt = _build_prompt( + text, prompt_suffix, show_default, default, show_choices, type + ) + + if confirmation_prompt: + if confirmation_prompt is True: + confirmation_prompt = _("Repeat for confirmation") + + confirmation_prompt = _build_prompt(confirmation_prompt, prompt_suffix) + + while True: + while True: + value = prompt_func(prompt) + if value: + break + elif default is not None: + value = default + break + try: + result = value_proc(value) + except UsageError as e: + if hide_input: + echo(_("Error: The value you entered was invalid."), err=err) + else: + echo(_("Error: {e.message}").format(e=e), err=err) + continue + if not confirmation_prompt: + return result + while True: + value2 = prompt_func(confirmation_prompt) + is_empty = not value and not value2 + if value2 or is_empty: + break + if value == value2: + return result + echo(_("Error: The two entered values do not match."), err=err) + + +def confirm( + text: str, + default: t.Optional[bool] = False, + abort: bool = False, + prompt_suffix: str = ": ", + show_default: bool = True, + err: bool = False, +) -> bool: + """Prompts for confirmation (yes/no question). + + If the user aborts the input by sending a interrupt signal this + function will catch it and raise a :exc:`Abort` exception. + + :param text: the question to ask. + :param default: The default value to use when no input is given. If + ``None``, repeat until input is given. + :param abort: if this is set to `True` a negative answer aborts the + exception by raising :exc:`Abort`. + :param prompt_suffix: a suffix that should be added to the prompt. + :param show_default: shows or hides the default value in the prompt. + :param err: if set to true the file defaults to ``stderr`` instead of + ``stdout``, the same as with echo. + + .. versionchanged:: 8.0 + Repeat until input is given if ``default`` is ``None``. + + .. versionadded:: 4.0 + Added the ``err`` parameter. + """ + prompt = _build_prompt( + text, + prompt_suffix, + show_default, + "y/n" if default is None else ("Y/n" if default else "y/N"), + ) + + while True: + try: + # Write the prompt separately so that we get nice + # coloring through colorama on Windows + echo(prompt.rstrip(" "), nl=False, err=err) + # Echo a space to stdout to work around an issue where + # readline causes backspace to clear the whole line. + value = visible_prompt_func(" ").lower().strip() + except (KeyboardInterrupt, EOFError): + raise Abort() from None + if value in ("y", "yes"): + rv = True + elif value in ("n", "no"): + rv = False + elif default is not None and value == "": + rv = default + else: + echo(_("Error: invalid input"), err=err) + continue + break + if abort and not rv: + raise Abort() + return rv + + +def echo_via_pager( + text_or_generator: t.Union[t.Iterable[str], t.Callable[[], t.Iterable[str]], str], + color: t.Optional[bool] = None, +) -> None: + """This function takes a text and shows it via an environment specific + pager on stdout. + + .. versionchanged:: 3.0 + Added the `color` flag. + + :param text_or_generator: the text to page, or alternatively, a + generator emitting the text to page. + :param color: controls if the pager supports ANSI colors or not. The + default is autodetection. + """ + color = resolve_color_default(color) + + if inspect.isgeneratorfunction(text_or_generator): + i = t.cast(t.Callable[[], t.Iterable[str]], text_or_generator)() + elif isinstance(text_or_generator, str): + i = [text_or_generator] + else: + i = iter(t.cast(t.Iterable[str], text_or_generator)) + + # convert every element of i to a text type if necessary + text_generator = (el if isinstance(el, str) else str(el) for el in i) + + from ._termui_impl import pager + + return pager(itertools.chain(text_generator, "\n"), color) + + +def progressbar( + iterable: t.Optional[t.Iterable[V]] = None, + length: t.Optional[int] = None, + label: t.Optional[str] = None, + show_eta: bool = True, + show_percent: t.Optional[bool] = None, + show_pos: bool = False, + item_show_func: t.Optional[t.Callable[[t.Optional[V]], t.Optional[str]]] = None, + fill_char: str = "#", + empty_char: str = "-", + bar_template: str = "%(label)s [%(bar)s] %(info)s", + info_sep: str = " ", + width: int = 36, + file: t.Optional[t.TextIO] = None, + color: t.Optional[bool] = None, + update_min_steps: int = 1, +) -> "ProgressBar[V]": + """This function creates an iterable context manager that can be used + to iterate over something while showing a progress bar. It will + either iterate over the `iterable` or `length` items (that are counted + up). While iteration happens, this function will print a rendered + progress bar to the given `file` (defaults to stdout) and will attempt + to calculate remaining time and more. By default, this progress bar + will not be rendered if the file is not a terminal. + + The context manager creates the progress bar. When the context + manager is entered the progress bar is already created. With every + iteration over the progress bar, the iterable passed to the bar is + advanced and the bar is updated. When the context manager exits, + a newline is printed and the progress bar is finalized on screen. + + Note: The progress bar is currently designed for use cases where the + total progress can be expected to take at least several seconds. + Because of this, the ProgressBar class object won't display + progress that is considered too fast, and progress where the time + between steps is less than a second. + + No printing must happen or the progress bar will be unintentionally + destroyed. + + Example usage:: + + with progressbar(items) as bar: + for item in bar: + do_something_with(item) + + Alternatively, if no iterable is specified, one can manually update the + progress bar through the `update()` method instead of directly + iterating over the progress bar. The update method accepts the number + of steps to increment the bar with:: + + with progressbar(length=chunks.total_bytes) as bar: + for chunk in chunks: + process_chunk(chunk) + bar.update(chunks.bytes) + + The ``update()`` method also takes an optional value specifying the + ``current_item`` at the new position. This is useful when used + together with ``item_show_func`` to customize the output for each + manual step:: + + with click.progressbar( + length=total_size, + label='Unzipping archive', + item_show_func=lambda a: a.filename + ) as bar: + for archive in zip_file: + archive.extract() + bar.update(archive.size, archive) + + :param iterable: an iterable to iterate over. If not provided the length + is required. + :param length: the number of items to iterate over. By default the + progressbar will attempt to ask the iterator about its + length, which might or might not work. If an iterable is + also provided this parameter can be used to override the + length. If an iterable is not provided the progress bar + will iterate over a range of that length. + :param label: the label to show next to the progress bar. + :param show_eta: enables or disables the estimated time display. This is + automatically disabled if the length cannot be + determined. + :param show_percent: enables or disables the percentage display. The + default is `True` if the iterable has a length or + `False` if not. + :param show_pos: enables or disables the absolute position display. The + default is `False`. + :param item_show_func: A function called with the current item which + can return a string to show next to the progress bar. If the + function returns ``None`` nothing is shown. The current item can + be ``None``, such as when entering and exiting the bar. + :param fill_char: the character to use to show the filled part of the + progress bar. + :param empty_char: the character to use to show the non-filled part of + the progress bar. + :param bar_template: the format string to use as template for the bar. + The parameters in it are ``label`` for the label, + ``bar`` for the progress bar and ``info`` for the + info section. + :param info_sep: the separator between multiple info items (eta etc.) + :param width: the width of the progress bar in characters, 0 means full + terminal width + :param file: The file to write to. If this is not a terminal then + only the label is printed. + :param color: controls if the terminal supports ANSI colors or not. The + default is autodetection. This is only needed if ANSI + codes are included anywhere in the progress bar output + which is not the case by default. + :param update_min_steps: Render only when this many updates have + completed. This allows tuning for very fast iterators. + + .. versionchanged:: 8.0 + Output is shown even if execution time is less than 0.5 seconds. + + .. versionchanged:: 8.0 + ``item_show_func`` shows the current item, not the previous one. + + .. versionchanged:: 8.0 + Labels are echoed if the output is not a TTY. Reverts a change + in 7.0 that removed all output. + + .. versionadded:: 8.0 + Added the ``update_min_steps`` parameter. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. Added the ``update`` method to + the object. + + .. versionadded:: 2.0 + """ + from ._termui_impl import ProgressBar + + color = resolve_color_default(color) + return ProgressBar( + iterable=iterable, + length=length, + show_eta=show_eta, + show_percent=show_percent, + show_pos=show_pos, + item_show_func=item_show_func, + fill_char=fill_char, + empty_char=empty_char, + bar_template=bar_template, + info_sep=info_sep, + file=file, + label=label, + width=width, + color=color, + update_min_steps=update_min_steps, + ) + + +def clear() -> None: + """Clears the terminal screen. This will have the effect of clearing + the whole visible space of the terminal and moving the cursor to the + top left. This does not do anything if not connected to a terminal. + + .. versionadded:: 2.0 + """ + if not isatty(sys.stdout): + return + + # ANSI escape \033[2J clears the screen, \033[1;1H moves the cursor + echo("\033[2J\033[1;1H", nl=False) + + +def _interpret_color( + color: t.Union[int, t.Tuple[int, int, int], str], offset: int = 0 +) -> str: + if isinstance(color, int): + return f"{38 + offset};5;{color:d}" + + if isinstance(color, (tuple, list)): + r, g, b = color + return f"{38 + offset};2;{r:d};{g:d};{b:d}" + + return str(_ansi_colors[color] + offset) + + +def style( + text: t.Any, + fg: t.Optional[t.Union[int, t.Tuple[int, int, int], str]] = None, + bg: t.Optional[t.Union[int, t.Tuple[int, int, int], str]] = None, + bold: t.Optional[bool] = None, + dim: t.Optional[bool] = None, + underline: t.Optional[bool] = None, + overline: t.Optional[bool] = None, + italic: t.Optional[bool] = None, + blink: t.Optional[bool] = None, + reverse: t.Optional[bool] = None, + strikethrough: t.Optional[bool] = None, + reset: bool = True, +) -> str: + """Styles a text with ANSI styles and returns the new string. By + default the styling is self contained which means that at the end + of the string a reset code is issued. This can be prevented by + passing ``reset=False``. + + Examples:: + + click.echo(click.style('Hello World!', fg='green')) + click.echo(click.style('ATTENTION!', blink=True)) + click.echo(click.style('Some things', reverse=True, fg='cyan')) + click.echo(click.style('More colors', fg=(255, 12, 128), bg=117)) + + Supported color names: + + * ``black`` (might be a gray) + * ``red`` + * ``green`` + * ``yellow`` (might be an orange) + * ``blue`` + * ``magenta`` + * ``cyan`` + * ``white`` (might be light gray) + * ``bright_black`` + * ``bright_red`` + * ``bright_green`` + * ``bright_yellow`` + * ``bright_blue`` + * ``bright_magenta`` + * ``bright_cyan`` + * ``bright_white`` + * ``reset`` (reset the color code only) + + If the terminal supports it, color may also be specified as: + + - An integer in the interval [0, 255]. The terminal must support + 8-bit/256-color mode. + - An RGB tuple of three integers in [0, 255]. The terminal must + support 24-bit/true-color mode. + + See https://en.wikipedia.org/wiki/ANSI_color and + https://gist.github.com/XVilka/8346728 for more information. + + :param text: the string to style with ansi codes. + :param fg: if provided this will become the foreground color. + :param bg: if provided this will become the background color. + :param bold: if provided this will enable or disable bold mode. + :param dim: if provided this will enable or disable dim mode. This is + badly supported. + :param underline: if provided this will enable or disable underline. + :param overline: if provided this will enable or disable overline. + :param italic: if provided this will enable or disable italic. + :param blink: if provided this will enable or disable blinking. + :param reverse: if provided this will enable or disable inverse + rendering (foreground becomes background and the + other way round). + :param strikethrough: if provided this will enable or disable + striking through text. + :param reset: by default a reset-all code is added at the end of the + string which means that styles do not carry over. This + can be disabled to compose styles. + + .. versionchanged:: 8.0 + A non-string ``message`` is converted to a string. + + .. versionchanged:: 8.0 + Added support for 256 and RGB color codes. + + .. versionchanged:: 8.0 + Added the ``strikethrough``, ``italic``, and ``overline`` + parameters. + + .. versionchanged:: 7.0 + Added support for bright colors. + + .. versionadded:: 2.0 + """ + if not isinstance(text, str): + text = str(text) + + bits = [] + + if fg: + try: + bits.append(f"\033[{_interpret_color(fg)}m") + except KeyError: + raise TypeError(f"Unknown color {fg!r}") from None + + if bg: + try: + bits.append(f"\033[{_interpret_color(bg, 10)}m") + except KeyError: + raise TypeError(f"Unknown color {bg!r}") from None + + if bold is not None: + bits.append(f"\033[{1 if bold else 22}m") + if dim is not None: + bits.append(f"\033[{2 if dim else 22}m") + if underline is not None: + bits.append(f"\033[{4 if underline else 24}m") + if overline is not None: + bits.append(f"\033[{53 if overline else 55}m") + if italic is not None: + bits.append(f"\033[{3 if italic else 23}m") + if blink is not None: + bits.append(f"\033[{5 if blink else 25}m") + if reverse is not None: + bits.append(f"\033[{7 if reverse else 27}m") + if strikethrough is not None: + bits.append(f"\033[{9 if strikethrough else 29}m") + bits.append(text) + if reset: + bits.append(_ansi_reset_all) + return "".join(bits) + + +def unstyle(text: str) -> str: + """Removes ANSI styling information from a string. Usually it's not + necessary to use this function as Click's echo function will + automatically remove styling if necessary. + + .. versionadded:: 2.0 + + :param text: the text to remove style information from. + """ + return strip_ansi(text) + + +def secho( + message: t.Optional[t.Any] = None, + file: t.Optional[t.IO[t.AnyStr]] = None, + nl: bool = True, + err: bool = False, + color: t.Optional[bool] = None, + **styles: t.Any, +) -> None: + """This function combines :func:`echo` and :func:`style` into one + call. As such the following two calls are the same:: + + click.secho('Hello World!', fg='green') + click.echo(click.style('Hello World!', fg='green')) + + All keyword arguments are forwarded to the underlying functions + depending on which one they go with. + + Non-string types will be converted to :class:`str`. However, + :class:`bytes` are passed directly to :meth:`echo` without applying + style. If you want to style bytes that represent text, call + :meth:`bytes.decode` first. + + .. versionchanged:: 8.0 + A non-string ``message`` is converted to a string. Bytes are + passed through without style applied. + + .. versionadded:: 2.0 + """ + if message is not None and not isinstance(message, (bytes, bytearray)): + message = style(message, **styles) + + return echo(message, file=file, nl=nl, err=err, color=color) + + +def edit( + text: t.Optional[t.AnyStr] = None, + editor: t.Optional[str] = None, + env: t.Optional[t.Mapping[str, str]] = None, + require_save: bool = True, + extension: str = ".txt", + filename: t.Optional[str] = None, +) -> t.Optional[t.AnyStr]: + r"""Edits the given text in the defined editor. If an editor is given + (should be the full path to the executable but the regular operating + system search path is used for finding the executable) it overrides + the detected editor. Optionally, some environment variables can be + used. If the editor is closed without changes, `None` is returned. In + case a file is edited directly the return value is always `None` and + `require_save` and `extension` are ignored. + + If the editor cannot be opened a :exc:`UsageError` is raised. + + Note for Windows: to simplify cross-platform usage, the newlines are + automatically converted from POSIX to Windows and vice versa. As such, + the message here will have ``\n`` as newline markers. + + :param text: the text to edit. + :param editor: optionally the editor to use. Defaults to automatic + detection. + :param env: environment variables to forward to the editor. + :param require_save: if this is true, then not saving in the editor + will make the return value become `None`. + :param extension: the extension to tell the editor about. This defaults + to `.txt` but changing this might change syntax + highlighting. + :param filename: if provided it will edit this file instead of the + provided text contents. It will not use a temporary + file as an indirection in that case. + """ + from ._termui_impl import Editor + + ed = Editor(editor=editor, env=env, require_save=require_save, extension=extension) + + if filename is None: + return ed.edit(text) + + ed.edit_file(filename) + return None + + +def launch(url: str, wait: bool = False, locate: bool = False) -> int: + """This function launches the given URL (or filename) in the default + viewer application for this file type. If this is an executable, it + might launch the executable in a new session. The return value is + the exit code of the launched application. Usually, ``0`` indicates + success. + + Examples:: + + click.launch('https://click.palletsprojects.com/') + click.launch('/my/downloaded/file', locate=True) + + .. versionadded:: 2.0 + + :param url: URL or filename of the thing to launch. + :param wait: Wait for the program to exit before returning. This + only works if the launched program blocks. In particular, + ``xdg-open`` on Linux does not block. + :param locate: if this is set to `True` then instead of launching the + application associated with the URL it will attempt to + launch a file manager with the file located. This + might have weird effects if the URL does not point to + the filesystem. + """ + from ._termui_impl import open_url + + return open_url(url, wait=wait, locate=locate) + + +# If this is provided, getchar() calls into this instead. This is used +# for unittesting purposes. +_getchar: t.Optional[t.Callable[[bool], str]] = None + + +def getchar(echo: bool = False) -> str: + """Fetches a single character from the terminal and returns it. This + will always return a unicode character and under certain rare + circumstances this might return more than one character. The + situations which more than one character is returned is when for + whatever reason multiple characters end up in the terminal buffer or + standard input was not actually a terminal. + + Note that this will always read from the terminal, even if something + is piped into the standard input. + + Note for Windows: in rare cases when typing non-ASCII characters, this + function might wait for a second character and then return both at once. + This is because certain Unicode characters look like special-key markers. + + .. versionadded:: 2.0 + + :param echo: if set to `True`, the character read will also show up on + the terminal. The default is to not show it. + """ + global _getchar + + if _getchar is None: + from ._termui_impl import getchar as f + + _getchar = f + + return _getchar(echo) + + +def raw_terminal() -> t.ContextManager[int]: + from ._termui_impl import raw_terminal as f + + return f() + + +def pause(info: t.Optional[str] = None, err: bool = False) -> None: + """This command stops execution and waits for the user to press any + key to continue. This is similar to the Windows batch "pause" + command. If the program is not run through a terminal, this command + will instead do nothing. + + .. versionadded:: 2.0 + + .. versionadded:: 4.0 + Added the `err` parameter. + + :param info: The message to print before pausing. Defaults to + ``"Press any key to continue..."``. + :param err: if set to message goes to ``stderr`` instead of + ``stdout``, the same as with echo. + """ + if not isatty(sys.stdin) or not isatty(sys.stdout): + return + + if info is None: + info = _("Press any key to continue...") + + try: + if info: + echo(info, nl=False, err=err) + try: + getchar() + except (KeyboardInterrupt, EOFError): + pass + finally: + if info: + echo(err=err) diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/testing.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/testing.py new file mode 100644 index 0000000..772b215 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/testing.py @@ -0,0 +1,483 @@ +import contextlib +import io +import os +import shlex +import shutil +import sys +import tempfile +import typing as t +from types import TracebackType + +from . import _compat +from . import formatting +from . import termui +from . import utils +from ._compat import _find_binary_reader + +if t.TYPE_CHECKING: + from .core import BaseCommand + + +class EchoingStdin: + def __init__(self, input: t.BinaryIO, output: t.BinaryIO) -> None: + self._input = input + self._output = output + self._paused = False + + def __getattr__(self, x: str) -> t.Any: + return getattr(self._input, x) + + def _echo(self, rv: bytes) -> bytes: + if not self._paused: + self._output.write(rv) + + return rv + + def read(self, n: int = -1) -> bytes: + return self._echo(self._input.read(n)) + + def read1(self, n: int = -1) -> bytes: + return self._echo(self._input.read1(n)) # type: ignore + + def readline(self, n: int = -1) -> bytes: + return self._echo(self._input.readline(n)) + + def readlines(self) -> t.List[bytes]: + return [self._echo(x) for x in self._input.readlines()] + + def __iter__(self) -> t.Iterator[bytes]: + return iter(self._echo(x) for x in self._input) + + def __repr__(self) -> str: + return repr(self._input) + + +@contextlib.contextmanager +def _pause_echo(stream: t.Optional[EchoingStdin]) -> t.Iterator[None]: + if stream is None: + yield + else: + stream._paused = True + yield + stream._paused = False + + +class _NamedTextIOWrapper(io.TextIOWrapper): + def __init__( + self, buffer: t.BinaryIO, name: str, mode: str, **kwargs: t.Any + ) -> None: + super().__init__(buffer, **kwargs) + self._name = name + self._mode = mode + + @property + def name(self) -> str: + return self._name + + @property + def mode(self) -> str: + return self._mode + + +def make_input_stream( + input: t.Optional[t.Union[str, bytes, t.IO[t.Any]]], charset: str +) -> t.BinaryIO: + # Is already an input stream. + if hasattr(input, "read"): + rv = _find_binary_reader(t.cast(t.IO[t.Any], input)) + + if rv is not None: + return rv + + raise TypeError("Could not find binary reader for input stream.") + + if input is None: + input = b"" + elif isinstance(input, str): + input = input.encode(charset) + + return io.BytesIO(input) + + +class Result: + """Holds the captured result of an invoked CLI script.""" + + def __init__( + self, + runner: "CliRunner", + stdout_bytes: bytes, + stderr_bytes: t.Optional[bytes], + return_value: t.Any, + exit_code: int, + exception: t.Optional[BaseException], + exc_info: t.Optional[ + t.Tuple[t.Type[BaseException], BaseException, TracebackType] + ] = None, + ): + #: The runner that created the result + self.runner = runner + #: The standard output as bytes. + self.stdout_bytes = stdout_bytes + #: The standard error as bytes, or None if not available + self.stderr_bytes = stderr_bytes + #: The value returned from the invoked command. + #: + #: .. versionadded:: 8.0 + self.return_value = return_value + #: The exit code as integer. + self.exit_code = exit_code + #: The exception that happened if one did. + self.exception = exception + #: The traceback + self.exc_info = exc_info + + @property + def output(self) -> str: + """The (standard) output as unicode string.""" + return self.stdout + + @property + def stdout(self) -> str: + """The standard output as unicode string.""" + return self.stdout_bytes.decode(self.runner.charset, "replace").replace( + "\r\n", "\n" + ) + + @property + def stderr(self) -> str: + """The standard error as unicode string.""" + if self.stderr_bytes is None: + raise ValueError("stderr not separately captured") + return self.stderr_bytes.decode(self.runner.charset, "replace").replace( + "\r\n", "\n" + ) + + def __repr__(self) -> str: + exc_str = repr(self.exception) if self.exception else "okay" + return f"<{type(self).__name__} {exc_str}>" + + +class CliRunner: + """The CLI runner provides functionality to invoke a Click command line + script for unittesting purposes in a isolated environment. This only + works in single-threaded systems without any concurrency as it changes the + global interpreter state. + + :param charset: the character set for the input and output data. + :param env: a dictionary with environment variables for overriding. + :param echo_stdin: if this is set to `True`, then reading from stdin writes + to stdout. This is useful for showing examples in + some circumstances. Note that regular prompts + will automatically echo the input. + :param mix_stderr: if this is set to `False`, then stdout and stderr are + preserved as independent streams. This is useful for + Unix-philosophy apps that have predictable stdout and + noisy stderr, such that each may be measured + independently + """ + + def __init__( + self, + charset: str = "utf-8", + env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + echo_stdin: bool = False, + mix_stderr: bool = True, + ) -> None: + self.charset = charset + self.env: t.Mapping[str, t.Optional[str]] = env or {} + self.echo_stdin = echo_stdin + self.mix_stderr = mix_stderr + + def get_default_prog_name(self, cli: "BaseCommand") -> str: + """Given a command object it will return the default program name + for it. The default is the `name` attribute or ``"root"`` if not + set. + """ + return cli.name or "root" + + def make_env( + self, overrides: t.Optional[t.Mapping[str, t.Optional[str]]] = None + ) -> t.Mapping[str, t.Optional[str]]: + """Returns the environment overrides for invoking a script.""" + rv = dict(self.env) + if overrides: + rv.update(overrides) + return rv + + @contextlib.contextmanager + def isolation( + self, + input: t.Optional[t.Union[str, bytes, t.IO[t.Any]]] = None, + env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + color: bool = False, + ) -> t.Iterator[t.Tuple[io.BytesIO, t.Optional[io.BytesIO]]]: + """A context manager that sets up the isolation for invoking of a + command line tool. This sets up stdin with the given input data + and `os.environ` with the overrides from the given dictionary. + This also rebinds some internals in Click to be mocked (like the + prompt functionality). + + This is automatically done in the :meth:`invoke` method. + + :param input: the input stream to put into sys.stdin. + :param env: the environment overrides as dictionary. + :param color: whether the output should contain color codes. The + application can still override this explicitly. + + .. versionchanged:: 8.0 + ``stderr`` is opened with ``errors="backslashreplace"`` + instead of the default ``"strict"``. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. + """ + bytes_input = make_input_stream(input, self.charset) + echo_input = None + + old_stdin = sys.stdin + old_stdout = sys.stdout + old_stderr = sys.stderr + old_forced_width = formatting.FORCED_WIDTH + formatting.FORCED_WIDTH = 80 + + env = self.make_env(env) + + bytes_output = io.BytesIO() + + if self.echo_stdin: + bytes_input = echo_input = t.cast( + t.BinaryIO, EchoingStdin(bytes_input, bytes_output) + ) + + sys.stdin = text_input = _NamedTextIOWrapper( + bytes_input, encoding=self.charset, name="", mode="r" + ) + + if self.echo_stdin: + # Force unbuffered reads, otherwise TextIOWrapper reads a + # large chunk which is echoed early. + text_input._CHUNK_SIZE = 1 # type: ignore + + sys.stdout = _NamedTextIOWrapper( + bytes_output, encoding=self.charset, name="", mode="w" + ) + + bytes_error = None + if self.mix_stderr: + sys.stderr = sys.stdout + else: + bytes_error = io.BytesIO() + sys.stderr = _NamedTextIOWrapper( + bytes_error, + encoding=self.charset, + name="", + mode="w", + errors="backslashreplace", + ) + + @_pause_echo(echo_input) # type: ignore + def visible_input(prompt: t.Optional[str] = None) -> str: + sys.stdout.write(prompt or "") + val = text_input.readline().rstrip("\r\n") + sys.stdout.write(f"{val}\n") + sys.stdout.flush() + return val + + @_pause_echo(echo_input) # type: ignore + def hidden_input(prompt: t.Optional[str] = None) -> str: + sys.stdout.write(f"{prompt or ''}\n") + sys.stdout.flush() + return text_input.readline().rstrip("\r\n") + + @_pause_echo(echo_input) # type: ignore + def _getchar(echo: bool) -> str: + char = sys.stdin.read(1) + + if echo: + sys.stdout.write(char) + + sys.stdout.flush() + return char + + default_color = color + + def should_strip_ansi( + stream: t.Optional[t.IO[t.Any]] = None, color: t.Optional[bool] = None + ) -> bool: + if color is None: + return not default_color + return not color + + old_visible_prompt_func = termui.visible_prompt_func + old_hidden_prompt_func = termui.hidden_prompt_func + old__getchar_func = termui._getchar + old_should_strip_ansi = utils.should_strip_ansi # type: ignore + old__compat_should_strip_ansi = _compat.should_strip_ansi + termui.visible_prompt_func = visible_input + termui.hidden_prompt_func = hidden_input + termui._getchar = _getchar + utils.should_strip_ansi = should_strip_ansi # type: ignore + _compat.should_strip_ansi = should_strip_ansi + + old_env = {} + try: + for key, value in env.items(): + old_env[key] = os.environ.get(key) + if value is None: + try: + del os.environ[key] + except Exception: + pass + else: + os.environ[key] = value + yield (bytes_output, bytes_error) + finally: + for key, value in old_env.items(): + if value is None: + try: + del os.environ[key] + except Exception: + pass + else: + os.environ[key] = value + sys.stdout = old_stdout + sys.stderr = old_stderr + sys.stdin = old_stdin + termui.visible_prompt_func = old_visible_prompt_func + termui.hidden_prompt_func = old_hidden_prompt_func + termui._getchar = old__getchar_func + utils.should_strip_ansi = old_should_strip_ansi # type: ignore + _compat.should_strip_ansi = old__compat_should_strip_ansi + formatting.FORCED_WIDTH = old_forced_width + + def invoke( + self, + cli: "BaseCommand", + args: t.Optional[t.Union[str, t.Sequence[str]]] = None, + input: t.Optional[t.Union[str, bytes, t.IO[t.Any]]] = None, + env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + catch_exceptions: bool = True, + color: bool = False, + **extra: t.Any, + ) -> Result: + """Invokes a command in an isolated environment. The arguments are + forwarded directly to the command line script, the `extra` keyword + arguments are passed to the :meth:`~clickpkg.Command.main` function of + the command. + + This returns a :class:`Result` object. + + :param cli: the command to invoke + :param args: the arguments to invoke. It may be given as an iterable + or a string. When given as string it will be interpreted + as a Unix shell command. More details at + :func:`shlex.split`. + :param input: the input data for `sys.stdin`. + :param env: the environment overrides. + :param catch_exceptions: Whether to catch any other exceptions than + ``SystemExit``. + :param extra: the keyword arguments to pass to :meth:`main`. + :param color: whether the output should contain color codes. The + application can still override this explicitly. + + .. versionchanged:: 8.0 + The result object has the ``return_value`` attribute with + the value returned from the invoked command. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. + + .. versionchanged:: 3.0 + Added the ``catch_exceptions`` parameter. + + .. versionchanged:: 3.0 + The result object has the ``exc_info`` attribute with the + traceback if available. + """ + exc_info = None + with self.isolation(input=input, env=env, color=color) as outstreams: + return_value = None + exception: t.Optional[BaseException] = None + exit_code = 0 + + if isinstance(args, str): + args = shlex.split(args) + + try: + prog_name = extra.pop("prog_name") + except KeyError: + prog_name = self.get_default_prog_name(cli) + + try: + return_value = cli.main(args=args or (), prog_name=prog_name, **extra) + except SystemExit as e: + exc_info = sys.exc_info() + e_code = t.cast(t.Optional[t.Union[int, t.Any]], e.code) + + if e_code is None: + e_code = 0 + + if e_code != 0: + exception = e + + if not isinstance(e_code, int): + sys.stdout.write(str(e_code)) + sys.stdout.write("\n") + e_code = 1 + + exit_code = e_code + + except Exception as e: + if not catch_exceptions: + raise + exception = e + exit_code = 1 + exc_info = sys.exc_info() + finally: + sys.stdout.flush() + stdout = outstreams[0].getvalue() + if self.mix_stderr: + stderr = None + else: + stderr = outstreams[1].getvalue() # type: ignore + + return Result( + runner=self, + stdout_bytes=stdout, + stderr_bytes=stderr, + return_value=return_value, + exit_code=exit_code, + exception=exception, + exc_info=exc_info, # type: ignore + ) + + @contextlib.contextmanager + def isolated_filesystem( + self, temp_dir: t.Optional[t.Union[str, "os.PathLike[str]"]] = None + ) -> t.Iterator[str]: + """A context manager that creates a temporary directory and + changes the current working directory to it. This isolates tests + that affect the contents of the CWD to prevent them from + interfering with each other. + + :param temp_dir: Create the temporary directory under this + directory. If given, the created directory is not removed + when exiting. + + .. versionchanged:: 8.0 + Added the ``temp_dir`` parameter. + """ + cwd = os.getcwd() + dt = tempfile.mkdtemp(dir=temp_dir) + os.chdir(dt) + + try: + yield dt + finally: + os.chdir(cwd) + + if temp_dir is None: + try: + shutil.rmtree(dt) + except OSError: + pass diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/types.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/types.py new file mode 100644 index 0000000..a70fd58 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/types.py @@ -0,0 +1,1093 @@ +import os +import stat +import sys +import typing as t +from datetime import datetime +from gettext import gettext as _ +from gettext import ngettext + +from ._compat import _get_argv_encoding +from ._compat import open_stream +from .exceptions import BadParameter +from .utils import format_filename +from .utils import LazyFile +from .utils import safecall + +if t.TYPE_CHECKING: + import typing_extensions as te + + from .core import Context + from .core import Parameter + from .shell_completion import CompletionItem + + +class ParamType: + """Represents the type of a parameter. Validates and converts values + from the command line or Python into the correct type. + + To implement a custom type, subclass and implement at least the + following: + + - The :attr:`name` class attribute must be set. + - Calling an instance of the type with ``None`` must return + ``None``. This is already implemented by default. + - :meth:`convert` must convert string values to the correct type. + - :meth:`convert` must accept values that are already the correct + type. + - It must be able to convert a value if the ``ctx`` and ``param`` + arguments are ``None``. This can occur when converting prompt + input. + """ + + is_composite: t.ClassVar[bool] = False + arity: t.ClassVar[int] = 1 + + #: the descriptive name of this type + name: str + + #: if a list of this type is expected and the value is pulled from a + #: string environment variable, this is what splits it up. `None` + #: means any whitespace. For all parameters the general rule is that + #: whitespace splits them up. The exception are paths and files which + #: are split by ``os.path.pathsep`` by default (":" on Unix and ";" on + #: Windows). + envvar_list_splitter: t.ClassVar[t.Optional[str]] = None + + def to_info_dict(self) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. + + Use :meth:`click.Context.to_info_dict` to traverse the entire + CLI structure. + + .. versionadded:: 8.0 + """ + # The class name without the "ParamType" suffix. + param_type = type(self).__name__.partition("ParamType")[0] + param_type = param_type.partition("ParameterType")[0] + + # Custom subclasses might not remember to set a name. + if hasattr(self, "name"): + name = self.name + else: + name = param_type + + return {"param_type": param_type, "name": name} + + def __call__( + self, + value: t.Any, + param: t.Optional["Parameter"] = None, + ctx: t.Optional["Context"] = None, + ) -> t.Any: + if value is not None: + return self.convert(value, param, ctx) + + def get_metavar(self, param: "Parameter") -> t.Optional[str]: + """Returns the metavar default for this param if it provides one.""" + + def get_missing_message(self, param: "Parameter") -> t.Optional[str]: + """Optionally might return extra information about a missing + parameter. + + .. versionadded:: 2.0 + """ + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + """Convert the value to the correct type. This is not called if + the value is ``None`` (the missing value). + + This must accept string values from the command line, as well as + values that are already the correct type. It may also convert + other compatible types. + + The ``param`` and ``ctx`` arguments may be ``None`` in certain + situations, such as when converting prompt input. + + If the value cannot be converted, call :meth:`fail` with a + descriptive message. + + :param value: The value to convert. + :param param: The parameter that is using this type to convert + its value. May be ``None``. + :param ctx: The current context that arrived at this value. May + be ``None``. + """ + return value + + def split_envvar_value(self, rv: str) -> t.Sequence[str]: + """Given a value from an environment variable this splits it up + into small chunks depending on the defined envvar list splitter. + + If the splitter is set to `None`, which means that whitespace splits, + then leading and trailing whitespace is ignored. Otherwise, leading + and trailing splitters usually lead to empty items being included. + """ + return (rv or "").split(self.envvar_list_splitter) + + def fail( + self, + message: str, + param: t.Optional["Parameter"] = None, + ctx: t.Optional["Context"] = None, + ) -> "t.NoReturn": + """Helper method to fail with an invalid value message.""" + raise BadParameter(message, ctx=ctx, param=param) + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Return a list of + :class:`~click.shell_completion.CompletionItem` objects for the + incomplete value. Most types do not provide completions, but + some do, and this allows custom types to provide custom + completions as well. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + return [] + + +class CompositeParamType(ParamType): + is_composite = True + + @property + def arity(self) -> int: # type: ignore + raise NotImplementedError() + + +class FuncParamType(ParamType): + def __init__(self, func: t.Callable[[t.Any], t.Any]) -> None: + self.name: str = func.__name__ + self.func = func + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["func"] = self.func + return info_dict + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + try: + return self.func(value) + except ValueError: + try: + value = str(value) + except UnicodeError: + value = value.decode("utf-8", "replace") + + self.fail(value, param, ctx) + + +class UnprocessedParamType(ParamType): + name = "text" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + return value + + def __repr__(self) -> str: + return "UNPROCESSED" + + +class StringParamType(ParamType): + name = "text" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + if isinstance(value, bytes): + enc = _get_argv_encoding() + try: + value = value.decode(enc) + except UnicodeError: + fs_enc = sys.getfilesystemencoding() + if fs_enc != enc: + try: + value = value.decode(fs_enc) + except UnicodeError: + value = value.decode("utf-8", "replace") + else: + value = value.decode("utf-8", "replace") + return value + return str(value) + + def __repr__(self) -> str: + return "STRING" + + +class Choice(ParamType): + """The choice type allows a value to be checked against a fixed set + of supported values. All of these values have to be strings. + + You should only pass a list or tuple of choices. Other iterables + (like generators) may lead to surprising results. + + The resulting value will always be one of the originally passed choices + regardless of ``case_sensitive`` or any ``ctx.token_normalize_func`` + being specified. + + See :ref:`choice-opts` for an example. + + :param case_sensitive: Set to false to make choices case + insensitive. Defaults to true. + """ + + name = "choice" + + def __init__(self, choices: t.Sequence[str], case_sensitive: bool = True) -> None: + self.choices = choices + self.case_sensitive = case_sensitive + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["choices"] = self.choices + info_dict["case_sensitive"] = self.case_sensitive + return info_dict + + def get_metavar(self, param: "Parameter") -> str: + choices_str = "|".join(self.choices) + + # Use curly braces to indicate a required argument. + if param.required and param.param_type_name == "argument": + return f"{{{choices_str}}}" + + # Use square braces to indicate an option or optional argument. + return f"[{choices_str}]" + + def get_missing_message(self, param: "Parameter") -> str: + return _("Choose from:\n\t{choices}").format(choices=",\n\t".join(self.choices)) + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + # Match through normalization and case sensitivity + # first do token_normalize_func, then lowercase + # preserve original `value` to produce an accurate message in + # `self.fail` + normed_value = value + normed_choices = {choice: choice for choice in self.choices} + + if ctx is not None and ctx.token_normalize_func is not None: + normed_value = ctx.token_normalize_func(value) + normed_choices = { + ctx.token_normalize_func(normed_choice): original + for normed_choice, original in normed_choices.items() + } + + if not self.case_sensitive: + normed_value = normed_value.casefold() + normed_choices = { + normed_choice.casefold(): original + for normed_choice, original in normed_choices.items() + } + + if normed_value in normed_choices: + return normed_choices[normed_value] + + choices_str = ", ".join(map(repr, self.choices)) + self.fail( + ngettext( + "{value!r} is not {choice}.", + "{value!r} is not one of {choices}.", + len(self.choices), + ).format(value=value, choice=choices_str, choices=choices_str), + param, + ctx, + ) + + def __repr__(self) -> str: + return f"Choice({list(self.choices)})" + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Complete choices that start with the incomplete value. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + str_choices = map(str, self.choices) + + if self.case_sensitive: + matched = (c for c in str_choices if c.startswith(incomplete)) + else: + incomplete = incomplete.lower() + matched = (c for c in str_choices if c.lower().startswith(incomplete)) + + return [CompletionItem(c) for c in matched] + + +class DateTime(ParamType): + """The DateTime type converts date strings into `datetime` objects. + + The format strings which are checked are configurable, but default to some + common (non-timezone aware) ISO 8601 formats. + + When specifying *DateTime* formats, you should only pass a list or a tuple. + Other iterables, like generators, may lead to surprising results. + + The format strings are processed using ``datetime.strptime``, and this + consequently defines the format strings which are allowed. + + Parsing is tried using each format, in order, and the first format which + parses successfully is used. + + :param formats: A list or tuple of date format strings, in the order in + which they should be tried. Defaults to + ``'%Y-%m-%d'``, ``'%Y-%m-%dT%H:%M:%S'``, + ``'%Y-%m-%d %H:%M:%S'``. + """ + + name = "datetime" + + def __init__(self, formats: t.Optional[t.Sequence[str]] = None): + self.formats: t.Sequence[str] = formats or [ + "%Y-%m-%d", + "%Y-%m-%dT%H:%M:%S", + "%Y-%m-%d %H:%M:%S", + ] + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["formats"] = self.formats + return info_dict + + def get_metavar(self, param: "Parameter") -> str: + return f"[{'|'.join(self.formats)}]" + + def _try_to_convert_date(self, value: t.Any, format: str) -> t.Optional[datetime]: + try: + return datetime.strptime(value, format) + except ValueError: + return None + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + if isinstance(value, datetime): + return value + + for format in self.formats: + converted = self._try_to_convert_date(value, format) + + if converted is not None: + return converted + + formats_str = ", ".join(map(repr, self.formats)) + self.fail( + ngettext( + "{value!r} does not match the format {format}.", + "{value!r} does not match the formats {formats}.", + len(self.formats), + ).format(value=value, format=formats_str, formats=formats_str), + param, + ctx, + ) + + def __repr__(self) -> str: + return "DateTime" + + +class _NumberParamTypeBase(ParamType): + _number_class: t.ClassVar[t.Type[t.Any]] + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + try: + return self._number_class(value) + except ValueError: + self.fail( + _("{value!r} is not a valid {number_type}.").format( + value=value, number_type=self.name + ), + param, + ctx, + ) + + +class _NumberRangeBase(_NumberParamTypeBase): + def __init__( + self, + min: t.Optional[float] = None, + max: t.Optional[float] = None, + min_open: bool = False, + max_open: bool = False, + clamp: bool = False, + ) -> None: + self.min = min + self.max = max + self.min_open = min_open + self.max_open = max_open + self.clamp = clamp + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update( + min=self.min, + max=self.max, + min_open=self.min_open, + max_open=self.max_open, + clamp=self.clamp, + ) + return info_dict + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + import operator + + rv = super().convert(value, param, ctx) + lt_min: bool = self.min is not None and ( + operator.le if self.min_open else operator.lt + )(rv, self.min) + gt_max: bool = self.max is not None and ( + operator.ge if self.max_open else operator.gt + )(rv, self.max) + + if self.clamp: + if lt_min: + return self._clamp(self.min, 1, self.min_open) # type: ignore + + if gt_max: + return self._clamp(self.max, -1, self.max_open) # type: ignore + + if lt_min or gt_max: + self.fail( + _("{value} is not in the range {range}.").format( + value=rv, range=self._describe_range() + ), + param, + ctx, + ) + + return rv + + def _clamp(self, bound: float, dir: "te.Literal[1, -1]", open: bool) -> float: + """Find the valid value to clamp to bound in the given + direction. + + :param bound: The boundary value. + :param dir: 1 or -1 indicating the direction to move. + :param open: If true, the range does not include the bound. + """ + raise NotImplementedError + + def _describe_range(self) -> str: + """Describe the range for use in help text.""" + if self.min is None: + op = "<" if self.max_open else "<=" + return f"x{op}{self.max}" + + if self.max is None: + op = ">" if self.min_open else ">=" + return f"x{op}{self.min}" + + lop = "<" if self.min_open else "<=" + rop = "<" if self.max_open else "<=" + return f"{self.min}{lop}x{rop}{self.max}" + + def __repr__(self) -> str: + clamp = " clamped" if self.clamp else "" + return f"<{type(self).__name__} {self._describe_range()}{clamp}>" + + +class IntParamType(_NumberParamTypeBase): + name = "integer" + _number_class = int + + def __repr__(self) -> str: + return "INT" + + +class IntRange(_NumberRangeBase, IntParamType): + """Restrict an :data:`click.INT` value to a range of accepted + values. See :ref:`ranges`. + + If ``min`` or ``max`` are not passed, any value is accepted in that + direction. If ``min_open`` or ``max_open`` are enabled, the + corresponding boundary is not included in the range. + + If ``clamp`` is enabled, a value outside the range is clamped to the + boundary instead of failing. + + .. versionchanged:: 8.0 + Added the ``min_open`` and ``max_open`` parameters. + """ + + name = "integer range" + + def _clamp( # type: ignore + self, bound: int, dir: "te.Literal[1, -1]", open: bool + ) -> int: + if not open: + return bound + + return bound + dir + + +class FloatParamType(_NumberParamTypeBase): + name = "float" + _number_class = float + + def __repr__(self) -> str: + return "FLOAT" + + +class FloatRange(_NumberRangeBase, FloatParamType): + """Restrict a :data:`click.FLOAT` value to a range of accepted + values. See :ref:`ranges`. + + If ``min`` or ``max`` are not passed, any value is accepted in that + direction. If ``min_open`` or ``max_open`` are enabled, the + corresponding boundary is not included in the range. + + If ``clamp`` is enabled, a value outside the range is clamped to the + boundary instead of failing. This is not supported if either + boundary is marked ``open``. + + .. versionchanged:: 8.0 + Added the ``min_open`` and ``max_open`` parameters. + """ + + name = "float range" + + def __init__( + self, + min: t.Optional[float] = None, + max: t.Optional[float] = None, + min_open: bool = False, + max_open: bool = False, + clamp: bool = False, + ) -> None: + super().__init__( + min=min, max=max, min_open=min_open, max_open=max_open, clamp=clamp + ) + + if (min_open or max_open) and clamp: + raise TypeError("Clamping is not supported for open bounds.") + + def _clamp(self, bound: float, dir: "te.Literal[1, -1]", open: bool) -> float: + if not open: + return bound + + # Could use Python 3.9's math.nextafter here, but clamping an + # open float range doesn't seem to be particularly useful. It's + # left up to the user to write a callback to do it if needed. + raise RuntimeError("Clamping is not supported for open bounds.") + + +class BoolParamType(ParamType): + name = "boolean" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + if value in {False, True}: + return bool(value) + + norm = value.strip().lower() + + if norm in {"1", "true", "t", "yes", "y", "on"}: + return True + + if norm in {"0", "false", "f", "no", "n", "off"}: + return False + + self.fail( + _("{value!r} is not a valid boolean.").format(value=value), param, ctx + ) + + def __repr__(self) -> str: + return "BOOL" + + +class UUIDParameterType(ParamType): + name = "uuid" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + import uuid + + if isinstance(value, uuid.UUID): + return value + + value = value.strip() + + try: + return uuid.UUID(value) + except ValueError: + self.fail( + _("{value!r} is not a valid UUID.").format(value=value), param, ctx + ) + + def __repr__(self) -> str: + return "UUID" + + +class File(ParamType): + """Declares a parameter to be a file for reading or writing. The file + is automatically closed once the context tears down (after the command + finished working). + + Files can be opened for reading or writing. The special value ``-`` + indicates stdin or stdout depending on the mode. + + By default, the file is opened for reading text data, but it can also be + opened in binary mode or for writing. The encoding parameter can be used + to force a specific encoding. + + The `lazy` flag controls if the file should be opened immediately or upon + first IO. The default is to be non-lazy for standard input and output + streams as well as files opened for reading, `lazy` otherwise. When opening a + file lazily for reading, it is still opened temporarily for validation, but + will not be held open until first IO. lazy is mainly useful when opening + for writing to avoid creating the file until it is needed. + + Files can also be opened atomically in which case all writes go into a + separate file in the same folder and upon completion the file will + be moved over to the original location. This is useful if a file + regularly read by other users is modified. + + See :ref:`file-args` for more information. + + .. versionchanged:: 2.0 + Added the ``atomic`` parameter. + """ + + name = "filename" + envvar_list_splitter: t.ClassVar[str] = os.path.pathsep + + def __init__( + self, + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + lazy: t.Optional[bool] = None, + atomic: bool = False, + ) -> None: + self.mode = mode + self.encoding = encoding + self.errors = errors + self.lazy = lazy + self.atomic = atomic + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update(mode=self.mode, encoding=self.encoding) + return info_dict + + def resolve_lazy_flag(self, value: "t.Union[str, os.PathLike[str]]") -> bool: + if self.lazy is not None: + return self.lazy + if os.fspath(value) == "-": + return False + elif "w" in self.mode: + return True + return False + + def convert( + self, + value: t.Union[str, "os.PathLike[str]", t.IO[t.Any]], + param: t.Optional["Parameter"], + ctx: t.Optional["Context"], + ) -> t.IO[t.Any]: + if _is_file_like(value): + return value + + value = t.cast("t.Union[str, os.PathLike[str]]", value) + + try: + lazy = self.resolve_lazy_flag(value) + + if lazy: + lf = LazyFile( + value, self.mode, self.encoding, self.errors, atomic=self.atomic + ) + + if ctx is not None: + ctx.call_on_close(lf.close_intelligently) + + return t.cast(t.IO[t.Any], lf) + + f, should_close = open_stream( + value, self.mode, self.encoding, self.errors, atomic=self.atomic + ) + + # If a context is provided, we automatically close the file + # at the end of the context execution (or flush out). If a + # context does not exist, it's the caller's responsibility to + # properly close the file. This for instance happens when the + # type is used with prompts. + if ctx is not None: + if should_close: + ctx.call_on_close(safecall(f.close)) + else: + ctx.call_on_close(safecall(f.flush)) + + return f + except OSError as e: + self.fail(f"'{format_filename(value)}': {e.strerror}", param, ctx) + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Return a special completion marker that tells the completion + system to use the shell to provide file path completions. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + return [CompletionItem(incomplete, type="file")] + + +def _is_file_like(value: t.Any) -> "te.TypeGuard[t.IO[t.Any]]": + return hasattr(value, "read") or hasattr(value, "write") + + +class Path(ParamType): + """The ``Path`` type is similar to the :class:`File` type, but + returns the filename instead of an open file. Various checks can be + enabled to validate the type of file and permissions. + + :param exists: The file or directory needs to exist for the value to + be valid. If this is not set to ``True``, and the file does not + exist, then all further checks are silently skipped. + :param file_okay: Allow a file as a value. + :param dir_okay: Allow a directory as a value. + :param readable: if true, a readable check is performed. + :param writable: if true, a writable check is performed. + :param executable: if true, an executable check is performed. + :param resolve_path: Make the value absolute and resolve any + symlinks. A ``~`` is not expanded, as this is supposed to be + done by the shell only. + :param allow_dash: Allow a single dash as a value, which indicates + a standard stream (but does not open it). Use + :func:`~click.open_file` to handle opening this value. + :param path_type: Convert the incoming path value to this type. If + ``None``, keep Python's default, which is ``str``. Useful to + convert to :class:`pathlib.Path`. + + .. versionchanged:: 8.1 + Added the ``executable`` parameter. + + .. versionchanged:: 8.0 + Allow passing ``path_type=pathlib.Path``. + + .. versionchanged:: 6.0 + Added the ``allow_dash`` parameter. + """ + + envvar_list_splitter: t.ClassVar[str] = os.path.pathsep + + def __init__( + self, + exists: bool = False, + file_okay: bool = True, + dir_okay: bool = True, + writable: bool = False, + readable: bool = True, + resolve_path: bool = False, + allow_dash: bool = False, + path_type: t.Optional[t.Type[t.Any]] = None, + executable: bool = False, + ): + self.exists = exists + self.file_okay = file_okay + self.dir_okay = dir_okay + self.readable = readable + self.writable = writable + self.executable = executable + self.resolve_path = resolve_path + self.allow_dash = allow_dash + self.type = path_type + + if self.file_okay and not self.dir_okay: + self.name: str = _("file") + elif self.dir_okay and not self.file_okay: + self.name = _("directory") + else: + self.name = _("path") + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update( + exists=self.exists, + file_okay=self.file_okay, + dir_okay=self.dir_okay, + writable=self.writable, + readable=self.readable, + allow_dash=self.allow_dash, + ) + return info_dict + + def coerce_path_result( + self, value: "t.Union[str, os.PathLike[str]]" + ) -> "t.Union[str, bytes, os.PathLike[str]]": + if self.type is not None and not isinstance(value, self.type): + if self.type is str: + return os.fsdecode(value) + elif self.type is bytes: + return os.fsencode(value) + else: + return t.cast("os.PathLike[str]", self.type(value)) + + return value + + def convert( + self, + value: "t.Union[str, os.PathLike[str]]", + param: t.Optional["Parameter"], + ctx: t.Optional["Context"], + ) -> "t.Union[str, bytes, os.PathLike[str]]": + rv = value + + is_dash = self.file_okay and self.allow_dash and rv in (b"-", "-") + + if not is_dash: + if self.resolve_path: + # os.path.realpath doesn't resolve symlinks on Windows + # until Python 3.8. Use pathlib for now. + import pathlib + + rv = os.fsdecode(pathlib.Path(rv).resolve()) + + try: + st = os.stat(rv) + except OSError: + if not self.exists: + return self.coerce_path_result(rv) + self.fail( + _("{name} {filename!r} does not exist.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + if not self.file_okay and stat.S_ISREG(st.st_mode): + self.fail( + _("{name} {filename!r} is a file.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + if not self.dir_okay and stat.S_ISDIR(st.st_mode): + self.fail( + _("{name} {filename!r} is a directory.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + if self.readable and not os.access(rv, os.R_OK): + self.fail( + _("{name} {filename!r} is not readable.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + if self.writable and not os.access(rv, os.W_OK): + self.fail( + _("{name} {filename!r} is not writable.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + if self.executable and not os.access(value, os.X_OK): + self.fail( + _("{name} {filename!r} is not executable.").format( + name=self.name.title(), filename=format_filename(value) + ), + param, + ctx, + ) + + return self.coerce_path_result(rv) + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Return a special completion marker that tells the completion + system to use the shell to provide path completions for only + directories or any paths. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + type = "dir" if self.dir_okay and not self.file_okay else "file" + return [CompletionItem(incomplete, type=type)] + + +class Tuple(CompositeParamType): + """The default behavior of Click is to apply a type on a value directly. + This works well in most cases, except for when `nargs` is set to a fixed + count and different types should be used for different items. In this + case the :class:`Tuple` type can be used. This type can only be used + if `nargs` is set to a fixed number. + + For more information see :ref:`tuple-type`. + + This can be selected by using a Python tuple literal as a type. + + :param types: a list of types that should be used for the tuple items. + """ + + def __init__(self, types: t.Sequence[t.Union[t.Type[t.Any], ParamType]]) -> None: + self.types: t.Sequence[ParamType] = [convert_type(ty) for ty in types] + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["types"] = [t.to_info_dict() for t in self.types] + return info_dict + + @property + def name(self) -> str: # type: ignore + return f"<{' '.join(ty.name for ty in self.types)}>" + + @property + def arity(self) -> int: # type: ignore + return len(self.types) + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + len_type = len(self.types) + len_value = len(value) + + if len_value != len_type: + self.fail( + ngettext( + "{len_type} values are required, but {len_value} was given.", + "{len_type} values are required, but {len_value} were given.", + len_value, + ).format(len_type=len_type, len_value=len_value), + param=param, + ctx=ctx, + ) + + return tuple(ty(x, param, ctx) for ty, x in zip(self.types, value)) + + +def convert_type(ty: t.Optional[t.Any], default: t.Optional[t.Any] = None) -> ParamType: + """Find the most appropriate :class:`ParamType` for the given Python + type. If the type isn't provided, it can be inferred from a default + value. + """ + guessed_type = False + + if ty is None and default is not None: + if isinstance(default, (tuple, list)): + # If the default is empty, ty will remain None and will + # return STRING. + if default: + item = default[0] + + # A tuple of tuples needs to detect the inner types. + # Can't call convert recursively because that would + # incorrectly unwind the tuple to a single type. + if isinstance(item, (tuple, list)): + ty = tuple(map(type, item)) + else: + ty = type(item) + else: + ty = type(default) + + guessed_type = True + + if isinstance(ty, tuple): + return Tuple(ty) + + if isinstance(ty, ParamType): + return ty + + if ty is str or ty is None: + return STRING + + if ty is int: + return INT + + if ty is float: + return FLOAT + + if ty is bool: + return BOOL + + if guessed_type: + return STRING + + if __debug__: + try: + if issubclass(ty, ParamType): + raise AssertionError( + f"Attempted to use an uninstantiated parameter type ({ty})." + ) + except TypeError: + # ty is an instance (correct), so issubclass fails. + pass + + return FuncParamType(ty) + + +#: A dummy parameter type that just does nothing. From a user's +#: perspective this appears to just be the same as `STRING` but +#: internally no string conversion takes place if the input was bytes. +#: This is usually useful when working with file paths as they can +#: appear in bytes and unicode. +#: +#: For path related uses the :class:`Path` type is a better choice but +#: there are situations where an unprocessed type is useful which is why +#: it is is provided. +#: +#: .. versionadded:: 4.0 +UNPROCESSED = UnprocessedParamType() + +#: A unicode string parameter type which is the implicit default. This +#: can also be selected by using ``str`` as type. +STRING = StringParamType() + +#: An integer parameter. This can also be selected by using ``int`` as +#: type. +INT = IntParamType() + +#: A floating point value parameter. This can also be selected by using +#: ``float`` as type. +FLOAT = FloatParamType() + +#: A boolean parameter. This is the default for boolean flags. This can +#: also be selected by using ``bool`` as a type. +BOOL = BoolParamType() + +#: A UUID parameter. +UUID = UUIDParameterType() diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/utils.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/utils.py new file mode 100644 index 0000000..836c6f2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/click/utils.py @@ -0,0 +1,624 @@ +import os +import re +import sys +import typing as t +from functools import update_wrapper +from types import ModuleType +from types import TracebackType + +from ._compat import _default_text_stderr +from ._compat import _default_text_stdout +from ._compat import _find_binary_writer +from ._compat import auto_wrap_for_ansi +from ._compat import binary_streams +from ._compat import open_stream +from ._compat import should_strip_ansi +from ._compat import strip_ansi +from ._compat import text_streams +from ._compat import WIN +from .globals import resolve_color_default + +if t.TYPE_CHECKING: + import typing_extensions as te + + P = te.ParamSpec("P") + +R = t.TypeVar("R") + + +def _posixify(name: str) -> str: + return "-".join(name.split()).lower() + + +def safecall(func: "t.Callable[P, R]") -> "t.Callable[P, t.Optional[R]]": + """Wraps a function so that it swallows exceptions.""" + + def wrapper(*args: "P.args", **kwargs: "P.kwargs") -> t.Optional[R]: + try: + return func(*args, **kwargs) + except Exception: + pass + return None + + return update_wrapper(wrapper, func) + + +def make_str(value: t.Any) -> str: + """Converts a value into a valid string.""" + if isinstance(value, bytes): + try: + return value.decode(sys.getfilesystemencoding()) + except UnicodeError: + return value.decode("utf-8", "replace") + return str(value) + + +def make_default_short_help(help: str, max_length: int = 45) -> str: + """Returns a condensed version of help string.""" + # Consider only the first paragraph. + paragraph_end = help.find("\n\n") + + if paragraph_end != -1: + help = help[:paragraph_end] + + # Collapse newlines, tabs, and spaces. + words = help.split() + + if not words: + return "" + + # The first paragraph started with a "no rewrap" marker, ignore it. + if words[0] == "\b": + words = words[1:] + + total_length = 0 + last_index = len(words) - 1 + + for i, word in enumerate(words): + total_length += len(word) + (i > 0) + + if total_length > max_length: # too long, truncate + break + + if word[-1] == ".": # sentence end, truncate without "..." + return " ".join(words[: i + 1]) + + if total_length == max_length and i != last_index: + break # not at sentence end, truncate with "..." + else: + return " ".join(words) # no truncation needed + + # Account for the length of the suffix. + total_length += len("...") + + # remove words until the length is short enough + while i > 0: + total_length -= len(words[i]) + (i > 0) + + if total_length <= max_length: + break + + i -= 1 + + return " ".join(words[:i]) + "..." + + +class LazyFile: + """A lazy file works like a regular file but it does not fully open + the file but it does perform some basic checks early to see if the + filename parameter does make sense. This is useful for safely opening + files for writing. + """ + + def __init__( + self, + filename: t.Union[str, "os.PathLike[str]"], + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + atomic: bool = False, + ): + self.name: str = os.fspath(filename) + self.mode = mode + self.encoding = encoding + self.errors = errors + self.atomic = atomic + self._f: t.Optional[t.IO[t.Any]] + self.should_close: bool + + if self.name == "-": + self._f, self.should_close = open_stream(filename, mode, encoding, errors) + else: + if "r" in mode: + # Open and close the file in case we're opening it for + # reading so that we can catch at least some errors in + # some cases early. + open(filename, mode).close() + self._f = None + self.should_close = True + + def __getattr__(self, name: str) -> t.Any: + return getattr(self.open(), name) + + def __repr__(self) -> str: + if self._f is not None: + return repr(self._f) + return f"" + + def open(self) -> t.IO[t.Any]: + """Opens the file if it's not yet open. This call might fail with + a :exc:`FileError`. Not handling this error will produce an error + that Click shows. + """ + if self._f is not None: + return self._f + try: + rv, self.should_close = open_stream( + self.name, self.mode, self.encoding, self.errors, atomic=self.atomic + ) + except OSError as e: + from .exceptions import FileError + + raise FileError(self.name, hint=e.strerror) from e + self._f = rv + return rv + + def close(self) -> None: + """Closes the underlying file, no matter what.""" + if self._f is not None: + self._f.close() + + def close_intelligently(self) -> None: + """This function only closes the file if it was opened by the lazy + file wrapper. For instance this will never close stdin. + """ + if self.should_close: + self.close() + + def __enter__(self) -> "LazyFile": + return self + + def __exit__( + self, + exc_type: t.Optional[t.Type[BaseException]], + exc_value: t.Optional[BaseException], + tb: t.Optional[TracebackType], + ) -> None: + self.close_intelligently() + + def __iter__(self) -> t.Iterator[t.AnyStr]: + self.open() + return iter(self._f) # type: ignore + + +class KeepOpenFile: + def __init__(self, file: t.IO[t.Any]) -> None: + self._file: t.IO[t.Any] = file + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._file, name) + + def __enter__(self) -> "KeepOpenFile": + return self + + def __exit__( + self, + exc_type: t.Optional[t.Type[BaseException]], + exc_value: t.Optional[BaseException], + tb: t.Optional[TracebackType], + ) -> None: + pass + + def __repr__(self) -> str: + return repr(self._file) + + def __iter__(self) -> t.Iterator[t.AnyStr]: + return iter(self._file) + + +def echo( + message: t.Optional[t.Any] = None, + file: t.Optional[t.IO[t.Any]] = None, + nl: bool = True, + err: bool = False, + color: t.Optional[bool] = None, +) -> None: + """Print a message and newline to stdout or a file. This should be + used instead of :func:`print` because it provides better support + for different data, files, and environments. + + Compared to :func:`print`, this does the following: + + - Ensures that the output encoding is not misconfigured on Linux. + - Supports Unicode in the Windows console. + - Supports writing to binary outputs, and supports writing bytes + to text outputs. + - Supports colors and styles on Windows. + - Removes ANSI color and style codes if the output does not look + like an interactive terminal. + - Always flushes the output. + + :param message: The string or bytes to output. Other objects are + converted to strings. + :param file: The file to write to. Defaults to ``stdout``. + :param err: Write to ``stderr`` instead of ``stdout``. + :param nl: Print a newline after the message. Enabled by default. + :param color: Force showing or hiding colors and other styles. By + default Click will remove color if the output does not look like + an interactive terminal. + + .. versionchanged:: 6.0 + Support Unicode output on the Windows console. Click does not + modify ``sys.stdout``, so ``sys.stdout.write()`` and ``print()`` + will still not support Unicode. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. + + .. versionadded:: 3.0 + Added the ``err`` parameter. + + .. versionchanged:: 2.0 + Support colors on Windows if colorama is installed. + """ + if file is None: + if err: + file = _default_text_stderr() + else: + file = _default_text_stdout() + + # There are no standard streams attached to write to. For example, + # pythonw on Windows. + if file is None: + return + + # Convert non bytes/text into the native string type. + if message is not None and not isinstance(message, (str, bytes, bytearray)): + out: t.Optional[t.Union[str, bytes]] = str(message) + else: + out = message + + if nl: + out = out or "" + if isinstance(out, str): + out += "\n" + else: + out += b"\n" + + if not out: + file.flush() + return + + # If there is a message and the value looks like bytes, we manually + # need to find the binary stream and write the message in there. + # This is done separately so that most stream types will work as you + # would expect. Eg: you can write to StringIO for other cases. + if isinstance(out, (bytes, bytearray)): + binary_file = _find_binary_writer(file) + + if binary_file is not None: + file.flush() + binary_file.write(out) + binary_file.flush() + return + + # ANSI style code support. For no message or bytes, nothing happens. + # When outputting to a file instead of a terminal, strip codes. + else: + color = resolve_color_default(color) + + if should_strip_ansi(file, color): + out = strip_ansi(out) + elif WIN: + if auto_wrap_for_ansi is not None: + file = auto_wrap_for_ansi(file, color) # type: ignore + elif not color: + out = strip_ansi(out) + + file.write(out) # type: ignore + file.flush() + + +def get_binary_stream(name: "te.Literal['stdin', 'stdout', 'stderr']") -> t.BinaryIO: + """Returns a system stream for byte processing. + + :param name: the name of the stream to open. Valid names are ``'stdin'``, + ``'stdout'`` and ``'stderr'`` + """ + opener = binary_streams.get(name) + if opener is None: + raise TypeError(f"Unknown standard stream '{name}'") + return opener() + + +def get_text_stream( + name: "te.Literal['stdin', 'stdout', 'stderr']", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", +) -> t.TextIO: + """Returns a system stream for text processing. This usually returns + a wrapped stream around a binary stream returned from + :func:`get_binary_stream` but it also can take shortcuts for already + correctly configured streams. + + :param name: the name of the stream to open. Valid names are ``'stdin'``, + ``'stdout'`` and ``'stderr'`` + :param encoding: overrides the detected default encoding. + :param errors: overrides the default error mode. + """ + opener = text_streams.get(name) + if opener is None: + raise TypeError(f"Unknown standard stream '{name}'") + return opener(encoding, errors) + + +def open_file( + filename: t.Union[str, "os.PathLike[str]"], + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + lazy: bool = False, + atomic: bool = False, +) -> t.IO[t.Any]: + """Open a file, with extra behavior to handle ``'-'`` to indicate + a standard stream, lazy open on write, and atomic write. Similar to + the behavior of the :class:`~click.File` param type. + + If ``'-'`` is given to open ``stdout`` or ``stdin``, the stream is + wrapped so that using it in a context manager will not close it. + This makes it possible to use the function without accidentally + closing a standard stream: + + .. code-block:: python + + with open_file(filename) as f: + ... + + :param filename: The name or Path of the file to open, or ``'-'`` for + ``stdin``/``stdout``. + :param mode: The mode in which to open the file. + :param encoding: The encoding to decode or encode a file opened in + text mode. + :param errors: The error handling mode. + :param lazy: Wait to open the file until it is accessed. For read + mode, the file is temporarily opened to raise access errors + early, then closed until it is read again. + :param atomic: Write to a temporary file and replace the given file + on close. + + .. versionadded:: 3.0 + """ + if lazy: + return t.cast( + t.IO[t.Any], LazyFile(filename, mode, encoding, errors, atomic=atomic) + ) + + f, should_close = open_stream(filename, mode, encoding, errors, atomic=atomic) + + if not should_close: + f = t.cast(t.IO[t.Any], KeepOpenFile(f)) + + return f + + +def format_filename( + filename: "t.Union[str, bytes, os.PathLike[str], os.PathLike[bytes]]", + shorten: bool = False, +) -> str: + """Format a filename as a string for display. Ensures the filename can be + displayed by replacing any invalid bytes or surrogate escapes in the name + with the replacement character ``�``. + + Invalid bytes or surrogate escapes will raise an error when written to a + stream with ``errors="strict"``. This will typically happen with ``stdout`` + when the locale is something like ``en_GB.UTF-8``. + + Many scenarios *are* safe to write surrogates though, due to PEP 538 and + PEP 540, including: + + - Writing to ``stderr``, which uses ``errors="backslashreplace"``. + - The system has ``LANG=C.UTF-8``, ``C``, or ``POSIX``. Python opens + stdout and stderr with ``errors="surrogateescape"``. + - None of ``LANG/LC_*`` are set. Python assumes ``LANG=C.UTF-8``. + - Python is started in UTF-8 mode with ``PYTHONUTF8=1`` or ``-X utf8``. + Python opens stdout and stderr with ``errors="surrogateescape"``. + + :param filename: formats a filename for UI display. This will also convert + the filename into unicode without failing. + :param shorten: this optionally shortens the filename to strip of the + path that leads up to it. + """ + if shorten: + filename = os.path.basename(filename) + else: + filename = os.fspath(filename) + + if isinstance(filename, bytes): + filename = filename.decode(sys.getfilesystemencoding(), "replace") + else: + filename = filename.encode("utf-8", "surrogateescape").decode( + "utf-8", "replace" + ) + + return filename + + +def get_app_dir(app_name: str, roaming: bool = True, force_posix: bool = False) -> str: + r"""Returns the config folder for the application. The default behavior + is to return whatever is most appropriate for the operating system. + + To give you an idea, for an app called ``"Foo Bar"``, something like + the following folders could be returned: + + Mac OS X: + ``~/Library/Application Support/Foo Bar`` + Mac OS X (POSIX): + ``~/.foo-bar`` + Unix: + ``~/.config/foo-bar`` + Unix (POSIX): + ``~/.foo-bar`` + Windows (roaming): + ``C:\Users\\AppData\Roaming\Foo Bar`` + Windows (not roaming): + ``C:\Users\\AppData\Local\Foo Bar`` + + .. versionadded:: 2.0 + + :param app_name: the application name. This should be properly capitalized + and can contain whitespace. + :param roaming: controls if the folder should be roaming or not on Windows. + Has no effect otherwise. + :param force_posix: if this is set to `True` then on any POSIX system the + folder will be stored in the home folder with a leading + dot instead of the XDG config home or darwin's + application support folder. + """ + if WIN: + key = "APPDATA" if roaming else "LOCALAPPDATA" + folder = os.environ.get(key) + if folder is None: + folder = os.path.expanduser("~") + return os.path.join(folder, app_name) + if force_posix: + return os.path.join(os.path.expanduser(f"~/.{_posixify(app_name)}")) + if sys.platform == "darwin": + return os.path.join( + os.path.expanduser("~/Library/Application Support"), app_name + ) + return os.path.join( + os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config")), + _posixify(app_name), + ) + + +class PacifyFlushWrapper: + """This wrapper is used to catch and suppress BrokenPipeErrors resulting + from ``.flush()`` being called on broken pipe during the shutdown/final-GC + of the Python interpreter. Notably ``.flush()`` is always called on + ``sys.stdout`` and ``sys.stderr``. So as to have minimal impact on any + other cleanup code, and the case where the underlying file is not a broken + pipe, all calls and attributes are proxied. + """ + + def __init__(self, wrapped: t.IO[t.Any]) -> None: + self.wrapped = wrapped + + def flush(self) -> None: + try: + self.wrapped.flush() + except OSError as e: + import errno + + if e.errno != errno.EPIPE: + raise + + def __getattr__(self, attr: str) -> t.Any: + return getattr(self.wrapped, attr) + + +def _detect_program_name( + path: t.Optional[str] = None, _main: t.Optional[ModuleType] = None +) -> str: + """Determine the command used to run the program, for use in help + text. If a file or entry point was executed, the file name is + returned. If ``python -m`` was used to execute a module or package, + ``python -m name`` is returned. + + This doesn't try to be too precise, the goal is to give a concise + name for help text. Files are only shown as their name without the + path. ``python`` is only shown for modules, and the full path to + ``sys.executable`` is not shown. + + :param path: The Python file being executed. Python puts this in + ``sys.argv[0]``, which is used by default. + :param _main: The ``__main__`` module. This should only be passed + during internal testing. + + .. versionadded:: 8.0 + Based on command args detection in the Werkzeug reloader. + + :meta private: + """ + if _main is None: + _main = sys.modules["__main__"] + + if not path: + path = sys.argv[0] + + # The value of __package__ indicates how Python was called. It may + # not exist if a setuptools script is installed as an egg. It may be + # set incorrectly for entry points created with pip on Windows. + # It is set to "" inside a Shiv or PEX zipapp. + if getattr(_main, "__package__", None) in {None, ""} or ( + os.name == "nt" + and _main.__package__ == "" + and not os.path.exists(path) + and os.path.exists(f"{path}.exe") + ): + # Executed a file, like "python app.py". + return os.path.basename(path) + + # Executed a module, like "python -m example". + # Rewritten by Python from "-m script" to "/path/to/script.py". + # Need to look at main module to determine how it was executed. + py_module = t.cast(str, _main.__package__) + name = os.path.splitext(os.path.basename(path))[0] + + # A submodule like "example.cli". + if name != "__main__": + py_module = f"{py_module}.{name}" + + return f"python -m {py_module.lstrip('.')}" + + +def _expand_args( + args: t.Iterable[str], + *, + user: bool = True, + env: bool = True, + glob_recursive: bool = True, +) -> t.List[str]: + """Simulate Unix shell expansion with Python functions. + + See :func:`glob.glob`, :func:`os.path.expanduser`, and + :func:`os.path.expandvars`. + + This is intended for use on Windows, where the shell does not do any + expansion. It may not exactly match what a Unix shell would do. + + :param args: List of command line arguments to expand. + :param user: Expand user home directory. + :param env: Expand environment variables. + :param glob_recursive: ``**`` matches directories recursively. + + .. versionchanged:: 8.1 + Invalid glob patterns are treated as empty expansions rather + than raising an error. + + .. versionadded:: 8.0 + + :meta private: + """ + from glob import glob + + out = [] + + for arg in args: + if user: + arg = os.path.expanduser(arg) + + if env: + arg = os.path.expandvars(arg) + + try: + matches = glob(arg, recursive=glob_recursive) + except re.error: + matches = [] + + if not matches: + out.append(arg) + else: + out.extend(matches) + + return out diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/__init__.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/__init__.py new file mode 100644 index 0000000..e86eb43 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/__init__.py @@ -0,0 +1,60 @@ +from __future__ import annotations + +import typing as t + +from . import json as json +from .app import Flask as Flask +from .blueprints import Blueprint as Blueprint +from .config import Config as Config +from .ctx import after_this_request as after_this_request +from .ctx import copy_current_request_context as copy_current_request_context +from .ctx import has_app_context as has_app_context +from .ctx import has_request_context as has_request_context +from .globals import current_app as current_app +from .globals import g as g +from .globals import request as request +from .globals import session as session +from .helpers import abort as abort +from .helpers import flash as flash +from .helpers import get_flashed_messages as get_flashed_messages +from .helpers import get_template_attribute as get_template_attribute +from .helpers import make_response as make_response +from .helpers import redirect as redirect +from .helpers import send_file as send_file +from .helpers import send_from_directory as send_from_directory +from .helpers import stream_with_context as stream_with_context +from .helpers import url_for as url_for +from .json import jsonify as jsonify +from .signals import appcontext_popped as appcontext_popped +from .signals import appcontext_pushed as appcontext_pushed +from .signals import appcontext_tearing_down as appcontext_tearing_down +from .signals import before_render_template as before_render_template +from .signals import got_request_exception as got_request_exception +from .signals import message_flashed as message_flashed +from .signals import request_finished as request_finished +from .signals import request_started as request_started +from .signals import request_tearing_down as request_tearing_down +from .signals import template_rendered as template_rendered +from .templating import render_template as render_template +from .templating import render_template_string as render_template_string +from .templating import stream_template as stream_template +from .templating import stream_template_string as stream_template_string +from .wrappers import Request as Request +from .wrappers import Response as Response + + +def __getattr__(name: str) -> t.Any: + if name == "__version__": + import importlib.metadata + import warnings + + warnings.warn( + "The '__version__' attribute is deprecated and will be removed in" + " Flask 3.1. Use feature detection or" + " 'importlib.metadata.version(\"flask\")' instead.", + DeprecationWarning, + stacklevel=2, + ) + return importlib.metadata.version("flask") + + raise AttributeError(name) diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/__main__.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/__main__.py new file mode 100644 index 0000000..4e28416 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/__main__.py @@ -0,0 +1,3 @@ +from .cli import main + +main() diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/app.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/app.py new file mode 100644 index 0000000..d710cb9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/app.py @@ -0,0 +1,1478 @@ +from __future__ import annotations + +import os +import sys +import typing as t +import weakref +from collections.abc import Iterator as _abc_Iterator +from datetime import timedelta +from inspect import iscoroutinefunction +from itertools import chain +from types import TracebackType +from urllib.parse import quote as _url_quote + +import click +from werkzeug.datastructures import Headers +from werkzeug.datastructures import ImmutableDict +from werkzeug.exceptions import BadRequestKeyError +from werkzeug.exceptions import HTTPException +from werkzeug.exceptions import InternalServerError +from werkzeug.routing import BuildError +from werkzeug.routing import MapAdapter +from werkzeug.routing import RequestRedirect +from werkzeug.routing import RoutingException +from werkzeug.routing import Rule +from werkzeug.serving import is_running_from_reloader +from werkzeug.wrappers import Response as BaseResponse + +from . import cli +from . import typing as ft +from .ctx import AppContext +from .ctx import RequestContext +from .globals import _cv_app +from .globals import _cv_request +from .globals import current_app +from .globals import g +from .globals import request +from .globals import request_ctx +from .globals import session +from .helpers import get_debug_flag +from .helpers import get_flashed_messages +from .helpers import get_load_dotenv +from .helpers import send_from_directory +from .sansio.app import App +from .sansio.scaffold import _sentinel +from .sessions import SecureCookieSessionInterface +from .sessions import SessionInterface +from .signals import appcontext_tearing_down +from .signals import got_request_exception +from .signals import request_finished +from .signals import request_started +from .signals import request_tearing_down +from .templating import Environment +from .wrappers import Request +from .wrappers import Response + +if t.TYPE_CHECKING: # pragma: no cover + from .testing import FlaskClient + from .testing import FlaskCliRunner + +T_shell_context_processor = t.TypeVar( + "T_shell_context_processor", bound=ft.ShellContextProcessorCallable +) +T_teardown = t.TypeVar("T_teardown", bound=ft.TeardownCallable) +T_template_filter = t.TypeVar("T_template_filter", bound=ft.TemplateFilterCallable) +T_template_global = t.TypeVar("T_template_global", bound=ft.TemplateGlobalCallable) +T_template_test = t.TypeVar("T_template_test", bound=ft.TemplateTestCallable) + + +def _make_timedelta(value: timedelta | int | None) -> timedelta | None: + if value is None or isinstance(value, timedelta): + return value + + return timedelta(seconds=value) + + +class Flask(App): + """The flask object implements a WSGI application and acts as the central + object. It is passed the name of the module or package of the + application. Once it is created it will act as a central registry for + the view functions, the URL rules, template configuration and much more. + + The name of the package is used to resolve resources from inside the + package or the folder the module is contained in depending on if the + package parameter resolves to an actual python package (a folder with + an :file:`__init__.py` file inside) or a standard module (just a ``.py`` file). + + For more information about resource loading, see :func:`open_resource`. + + Usually you create a :class:`Flask` instance in your main module or + in the :file:`__init__.py` file of your package like this:: + + from flask import Flask + app = Flask(__name__) + + .. admonition:: About the First Parameter + + The idea of the first parameter is to give Flask an idea of what + belongs to your application. This name is used to find resources + on the filesystem, can be used by extensions to improve debugging + information and a lot more. + + So it's important what you provide there. If you are using a single + module, `__name__` is always the correct value. If you however are + using a package, it's usually recommended to hardcode the name of + your package there. + + For example if your application is defined in :file:`yourapplication/app.py` + you should create it with one of the two versions below:: + + app = Flask('yourapplication') + app = Flask(__name__.split('.')[0]) + + Why is that? The application will work even with `__name__`, thanks + to how resources are looked up. However it will make debugging more + painful. Certain extensions can make assumptions based on the + import name of your application. For example the Flask-SQLAlchemy + extension will look for the code in your application that triggered + an SQL query in debug mode. If the import name is not properly set + up, that debugging information is lost. (For example it would only + pick up SQL queries in `yourapplication.app` and not + `yourapplication.views.frontend`) + + .. versionadded:: 0.7 + The `static_url_path`, `static_folder`, and `template_folder` + parameters were added. + + .. versionadded:: 0.8 + The `instance_path` and `instance_relative_config` parameters were + added. + + .. versionadded:: 0.11 + The `root_path` parameter was added. + + .. versionadded:: 1.0 + The ``host_matching`` and ``static_host`` parameters were added. + + .. versionadded:: 1.0 + The ``subdomain_matching`` parameter was added. Subdomain + matching needs to be enabled manually now. Setting + :data:`SERVER_NAME` does not implicitly enable it. + + :param import_name: the name of the application package + :param static_url_path: can be used to specify a different path for the + static files on the web. Defaults to the name + of the `static_folder` folder. + :param static_folder: The folder with static files that is served at + ``static_url_path``. Relative to the application ``root_path`` + or an absolute path. Defaults to ``'static'``. + :param static_host: the host to use when adding the static route. + Defaults to None. Required when using ``host_matching=True`` + with a ``static_folder`` configured. + :param host_matching: set ``url_map.host_matching`` attribute. + Defaults to False. + :param subdomain_matching: consider the subdomain relative to + :data:`SERVER_NAME` when matching routes. Defaults to False. + :param template_folder: the folder that contains the templates that should + be used by the application. Defaults to + ``'templates'`` folder in the root path of the + application. + :param instance_path: An alternative instance path for the application. + By default the folder ``'instance'`` next to the + package or module is assumed to be the instance + path. + :param instance_relative_config: if set to ``True`` relative filenames + for loading the config are assumed to + be relative to the instance path instead + of the application root. + :param root_path: The path to the root of the application files. + This should only be set manually when it can't be detected + automatically, such as for namespace packages. + """ + + default_config = ImmutableDict( + { + "DEBUG": None, + "TESTING": False, + "PROPAGATE_EXCEPTIONS": None, + "SECRET_KEY": None, + "PERMANENT_SESSION_LIFETIME": timedelta(days=31), + "USE_X_SENDFILE": False, + "SERVER_NAME": None, + "APPLICATION_ROOT": "/", + "SESSION_COOKIE_NAME": "session", + "SESSION_COOKIE_DOMAIN": None, + "SESSION_COOKIE_PATH": None, + "SESSION_COOKIE_HTTPONLY": True, + "SESSION_COOKIE_SECURE": False, + "SESSION_COOKIE_SAMESITE": None, + "SESSION_REFRESH_EACH_REQUEST": True, + "MAX_CONTENT_LENGTH": None, + "SEND_FILE_MAX_AGE_DEFAULT": None, + "TRAP_BAD_REQUEST_ERRORS": None, + "TRAP_HTTP_EXCEPTIONS": False, + "EXPLAIN_TEMPLATE_LOADING": False, + "PREFERRED_URL_SCHEME": "http", + "TEMPLATES_AUTO_RELOAD": None, + "MAX_COOKIE_SIZE": 4093, + } + ) + + #: The class that is used for request objects. See :class:`~flask.Request` + #: for more information. + request_class = Request + + #: The class that is used for response objects. See + #: :class:`~flask.Response` for more information. + response_class = Response + + #: the session interface to use. By default an instance of + #: :class:`~flask.sessions.SecureCookieSessionInterface` is used here. + #: + #: .. versionadded:: 0.8 + session_interface: SessionInterface = SecureCookieSessionInterface() + + def __init__( + self, + import_name: str, + static_url_path: str | None = None, + static_folder: str | os.PathLike | None = "static", + static_host: str | None = None, + host_matching: bool = False, + subdomain_matching: bool = False, + template_folder: str | os.PathLike | None = "templates", + instance_path: str | None = None, + instance_relative_config: bool = False, + root_path: str | None = None, + ): + super().__init__( + import_name=import_name, + static_url_path=static_url_path, + static_folder=static_folder, + static_host=static_host, + host_matching=host_matching, + subdomain_matching=subdomain_matching, + template_folder=template_folder, + instance_path=instance_path, + instance_relative_config=instance_relative_config, + root_path=root_path, + ) + + # Add a static route using the provided static_url_path, static_host, + # and static_folder if there is a configured static_folder. + # Note we do this without checking if static_folder exists. + # For one, it might be created while the server is running (e.g. during + # development). Also, Google App Engine stores static files somewhere + if self.has_static_folder: + assert ( + bool(static_host) == host_matching + ), "Invalid static_host/host_matching combination" + # Use a weakref to avoid creating a reference cycle between the app + # and the view function (see #3761). + self_ref = weakref.ref(self) + self.add_url_rule( + f"{self.static_url_path}/", + endpoint="static", + host=static_host, + view_func=lambda **kw: self_ref().send_static_file(**kw), # type: ignore # noqa: B950 + ) + + def get_send_file_max_age(self, filename: str | None) -> int | None: + """Used by :func:`send_file` to determine the ``max_age`` cache + value for a given file path if it wasn't passed. + + By default, this returns :data:`SEND_FILE_MAX_AGE_DEFAULT` from + the configuration of :data:`~flask.current_app`. This defaults + to ``None``, which tells the browser to use conditional requests + instead of a timed cache, which is usually preferable. + + Note this is a duplicate of the same method in the Flask + class. + + .. versionchanged:: 2.0 + The default configuration is ``None`` instead of 12 hours. + + .. versionadded:: 0.9 + """ + value = current_app.config["SEND_FILE_MAX_AGE_DEFAULT"] + + if value is None: + return None + + if isinstance(value, timedelta): + return int(value.total_seconds()) + + return value + + def send_static_file(self, filename: str) -> Response: + """The view function used to serve files from + :attr:`static_folder`. A route is automatically registered for + this view at :attr:`static_url_path` if :attr:`static_folder` is + set. + + Note this is a duplicate of the same method in the Flask + class. + + .. versionadded:: 0.5 + + """ + if not self.has_static_folder: + raise RuntimeError("'static_folder' must be set to serve static_files.") + + # send_file only knows to call get_send_file_max_age on the app, + # call it here so it works for blueprints too. + max_age = self.get_send_file_max_age(filename) + return send_from_directory( + t.cast(str, self.static_folder), filename, max_age=max_age + ) + + def open_resource(self, resource: str, mode: str = "rb") -> t.IO[t.AnyStr]: + """Open a resource file relative to :attr:`root_path` for + reading. + + For example, if the file ``schema.sql`` is next to the file + ``app.py`` where the ``Flask`` app is defined, it can be opened + with: + + .. code-block:: python + + with app.open_resource("schema.sql") as f: + conn.executescript(f.read()) + + :param resource: Path to the resource relative to + :attr:`root_path`. + :param mode: Open the file in this mode. Only reading is + supported, valid values are "r" (or "rt") and "rb". + + Note this is a duplicate of the same method in the Flask + class. + + """ + if mode not in {"r", "rt", "rb"}: + raise ValueError("Resources can only be opened for reading.") + + return open(os.path.join(self.root_path, resource), mode) + + def open_instance_resource(self, resource: str, mode: str = "rb") -> t.IO[t.AnyStr]: + """Opens a resource from the application's instance folder + (:attr:`instance_path`). Otherwise works like + :meth:`open_resource`. Instance resources can also be opened for + writing. + + :param resource: the name of the resource. To access resources within + subfolders use forward slashes as separator. + :param mode: resource file opening mode, default is 'rb'. + """ + return open(os.path.join(self.instance_path, resource), mode) + + def create_jinja_environment(self) -> Environment: + """Create the Jinja environment based on :attr:`jinja_options` + and the various Jinja-related methods of the app. Changing + :attr:`jinja_options` after this will have no effect. Also adds + Flask-related globals and filters to the environment. + + .. versionchanged:: 0.11 + ``Environment.auto_reload`` set in accordance with + ``TEMPLATES_AUTO_RELOAD`` configuration option. + + .. versionadded:: 0.5 + """ + options = dict(self.jinja_options) + + if "autoescape" not in options: + options["autoescape"] = self.select_jinja_autoescape + + if "auto_reload" not in options: + auto_reload = self.config["TEMPLATES_AUTO_RELOAD"] + + if auto_reload is None: + auto_reload = self.debug + + options["auto_reload"] = auto_reload + + rv = self.jinja_environment(self, **options) + rv.globals.update( + url_for=self.url_for, + get_flashed_messages=get_flashed_messages, + config=self.config, + # request, session and g are normally added with the + # context processor for efficiency reasons but for imported + # templates we also want the proxies in there. + request=request, + session=session, + g=g, + ) + rv.policies["json.dumps_function"] = self.json.dumps + return rv + + def create_url_adapter(self, request: Request | None) -> MapAdapter | None: + """Creates a URL adapter for the given request. The URL adapter + is created at a point where the request context is not yet set + up so the request is passed explicitly. + + .. versionadded:: 0.6 + + .. versionchanged:: 0.9 + This can now also be called without a request object when the + URL adapter is created for the application context. + + .. versionchanged:: 1.0 + :data:`SERVER_NAME` no longer implicitly enables subdomain + matching. Use :attr:`subdomain_matching` instead. + """ + if request is not None: + # If subdomain matching is disabled (the default), use the + # default subdomain in all cases. This should be the default + # in Werkzeug but it currently does not have that feature. + if not self.subdomain_matching: + subdomain = self.url_map.default_subdomain or None + else: + subdomain = None + + return self.url_map.bind_to_environ( + request.environ, + server_name=self.config["SERVER_NAME"], + subdomain=subdomain, + ) + # We need at the very least the server name to be set for this + # to work. + if self.config["SERVER_NAME"] is not None: + return self.url_map.bind( + self.config["SERVER_NAME"], + script_name=self.config["APPLICATION_ROOT"], + url_scheme=self.config["PREFERRED_URL_SCHEME"], + ) + + return None + + def raise_routing_exception(self, request: Request) -> t.NoReturn: + """Intercept routing exceptions and possibly do something else. + + In debug mode, intercept a routing redirect and replace it with + an error if the body will be discarded. + + With modern Werkzeug this shouldn't occur, since it now uses a + 308 status which tells the browser to resend the method and + body. + + .. versionchanged:: 2.1 + Don't intercept 307 and 308 redirects. + + :meta private: + :internal: + """ + if ( + not self.debug + or not isinstance(request.routing_exception, RequestRedirect) + or request.routing_exception.code in {307, 308} + or request.method in {"GET", "HEAD", "OPTIONS"} + ): + raise request.routing_exception # type: ignore + + from .debughelpers import FormDataRoutingRedirect + + raise FormDataRoutingRedirect(request) + + def update_template_context(self, context: dict) -> None: + """Update the template context with some commonly used variables. + This injects request, session, config and g into the template + context as well as everything template context processors want + to inject. Note that the as of Flask 0.6, the original values + in the context will not be overridden if a context processor + decides to return a value with the same key. + + :param context: the context as a dictionary that is updated in place + to add extra variables. + """ + names: t.Iterable[str | None] = (None,) + + # A template may be rendered outside a request context. + if request: + names = chain(names, reversed(request.blueprints)) + + # The values passed to render_template take precedence. Keep a + # copy to re-apply after all context functions. + orig_ctx = context.copy() + + for name in names: + if name in self.template_context_processors: + for func in self.template_context_processors[name]: + context.update(self.ensure_sync(func)()) + + context.update(orig_ctx) + + def make_shell_context(self) -> dict: + """Returns the shell context for an interactive shell for this + application. This runs all the registered shell context + processors. + + .. versionadded:: 0.11 + """ + rv = {"app": self, "g": g} + for processor in self.shell_context_processors: + rv.update(processor()) + return rv + + def run( + self, + host: str | None = None, + port: int | None = None, + debug: bool | None = None, + load_dotenv: bool = True, + **options: t.Any, + ) -> None: + """Runs the application on a local development server. + + Do not use ``run()`` in a production setting. It is not intended to + meet security and performance requirements for a production server. + Instead, see :doc:`/deploying/index` for WSGI server recommendations. + + If the :attr:`debug` flag is set the server will automatically reload + for code changes and show a debugger in case an exception happened. + + If you want to run the application in debug mode, but disable the + code execution on the interactive debugger, you can pass + ``use_evalex=False`` as parameter. This will keep the debugger's + traceback screen active, but disable code execution. + + It is not recommended to use this function for development with + automatic reloading as this is badly supported. Instead you should + be using the :command:`flask` command line script's ``run`` support. + + .. admonition:: Keep in Mind + + Flask will suppress any server error with a generic error page + unless it is in debug mode. As such to enable just the + interactive debugger without the code reloading, you have to + invoke :meth:`run` with ``debug=True`` and ``use_reloader=False``. + Setting ``use_debugger`` to ``True`` without being in debug mode + won't catch any exceptions because there won't be any to + catch. + + :param host: the hostname to listen on. Set this to ``'0.0.0.0'`` to + have the server available externally as well. Defaults to + ``'127.0.0.1'`` or the host in the ``SERVER_NAME`` config variable + if present. + :param port: the port of the webserver. Defaults to ``5000`` or the + port defined in the ``SERVER_NAME`` config variable if present. + :param debug: if given, enable or disable debug mode. See + :attr:`debug`. + :param load_dotenv: Load the nearest :file:`.env` and :file:`.flaskenv` + files to set environment variables. Will also change the working + directory to the directory containing the first file found. + :param options: the options to be forwarded to the underlying Werkzeug + server. See :func:`werkzeug.serving.run_simple` for more + information. + + .. versionchanged:: 1.0 + If installed, python-dotenv will be used to load environment + variables from :file:`.env` and :file:`.flaskenv` files. + + The :envvar:`FLASK_DEBUG` environment variable will override :attr:`debug`. + + Threaded mode is enabled by default. + + .. versionchanged:: 0.10 + The default port is now picked from the ``SERVER_NAME`` + variable. + """ + # Ignore this call so that it doesn't start another server if + # the 'flask run' command is used. + if os.environ.get("FLASK_RUN_FROM_CLI") == "true": + if not is_running_from_reloader(): + click.secho( + " * Ignoring a call to 'app.run()' that would block" + " the current 'flask' CLI command.\n" + " Only call 'app.run()' in an 'if __name__ ==" + ' "__main__"\' guard.', + fg="red", + ) + + return + + if get_load_dotenv(load_dotenv): + cli.load_dotenv() + + # if set, env var overrides existing value + if "FLASK_DEBUG" in os.environ: + self.debug = get_debug_flag() + + # debug passed to method overrides all other sources + if debug is not None: + self.debug = bool(debug) + + server_name = self.config.get("SERVER_NAME") + sn_host = sn_port = None + + if server_name: + sn_host, _, sn_port = server_name.partition(":") + + if not host: + if sn_host: + host = sn_host + else: + host = "127.0.0.1" + + if port or port == 0: + port = int(port) + elif sn_port: + port = int(sn_port) + else: + port = 5000 + + options.setdefault("use_reloader", self.debug) + options.setdefault("use_debugger", self.debug) + options.setdefault("threaded", True) + + cli.show_server_banner(self.debug, self.name) + + from werkzeug.serving import run_simple + + try: + run_simple(t.cast(str, host), port, self, **options) + finally: + # reset the first request information if the development server + # reset normally. This makes it possible to restart the server + # without reloader and that stuff from an interactive shell. + self._got_first_request = False + + def test_client(self, use_cookies: bool = True, **kwargs: t.Any) -> FlaskClient: + """Creates a test client for this application. For information + about unit testing head over to :doc:`/testing`. + + Note that if you are testing for assertions or exceptions in your + application code, you must set ``app.testing = True`` in order for the + exceptions to propagate to the test client. Otherwise, the exception + will be handled by the application (not visible to the test client) and + the only indication of an AssertionError or other exception will be a + 500 status code response to the test client. See the :attr:`testing` + attribute. For example:: + + app.testing = True + client = app.test_client() + + The test client can be used in a ``with`` block to defer the closing down + of the context until the end of the ``with`` block. This is useful if + you want to access the context locals for testing:: + + with app.test_client() as c: + rv = c.get('/?vodka=42') + assert request.args['vodka'] == '42' + + Additionally, you may pass optional keyword arguments that will then + be passed to the application's :attr:`test_client_class` constructor. + For example:: + + from flask.testing import FlaskClient + + class CustomClient(FlaskClient): + def __init__(self, *args, **kwargs): + self._authentication = kwargs.pop("authentication") + super(CustomClient,self).__init__( *args, **kwargs) + + app.test_client_class = CustomClient + client = app.test_client(authentication='Basic ....') + + See :class:`~flask.testing.FlaskClient` for more information. + + .. versionchanged:: 0.4 + added support for ``with`` block usage for the client. + + .. versionadded:: 0.7 + The `use_cookies` parameter was added as well as the ability + to override the client to be used by setting the + :attr:`test_client_class` attribute. + + .. versionchanged:: 0.11 + Added `**kwargs` to support passing additional keyword arguments to + the constructor of :attr:`test_client_class`. + """ + cls = self.test_client_class + if cls is None: + from .testing import FlaskClient as cls + return cls( # type: ignore + self, self.response_class, use_cookies=use_cookies, **kwargs + ) + + def test_cli_runner(self, **kwargs: t.Any) -> FlaskCliRunner: + """Create a CLI runner for testing CLI commands. + See :ref:`testing-cli`. + + Returns an instance of :attr:`test_cli_runner_class`, by default + :class:`~flask.testing.FlaskCliRunner`. The Flask app object is + passed as the first argument. + + .. versionadded:: 1.0 + """ + cls = self.test_cli_runner_class + + if cls is None: + from .testing import FlaskCliRunner as cls + + return cls(self, **kwargs) # type: ignore + + def handle_http_exception( + self, e: HTTPException + ) -> HTTPException | ft.ResponseReturnValue: + """Handles an HTTP exception. By default this will invoke the + registered error handlers and fall back to returning the + exception as response. + + .. versionchanged:: 1.0.3 + ``RoutingException``, used internally for actions such as + slash redirects during routing, is not passed to error + handlers. + + .. versionchanged:: 1.0 + Exceptions are looked up by code *and* by MRO, so + ``HTTPException`` subclasses can be handled with a catch-all + handler for the base ``HTTPException``. + + .. versionadded:: 0.3 + """ + # Proxy exceptions don't have error codes. We want to always return + # those unchanged as errors + if e.code is None: + return e + + # RoutingExceptions are used internally to trigger routing + # actions, such as slash redirects raising RequestRedirect. They + # are not raised or handled in user code. + if isinstance(e, RoutingException): + return e + + handler = self._find_error_handler(e, request.blueprints) + if handler is None: + return e + return self.ensure_sync(handler)(e) + + def handle_user_exception( + self, e: Exception + ) -> HTTPException | ft.ResponseReturnValue: + """This method is called whenever an exception occurs that + should be handled. A special case is :class:`~werkzeug + .exceptions.HTTPException` which is forwarded to the + :meth:`handle_http_exception` method. This function will either + return a response value or reraise the exception with the same + traceback. + + .. versionchanged:: 1.0 + Key errors raised from request data like ``form`` show the + bad key in debug mode rather than a generic bad request + message. + + .. versionadded:: 0.7 + """ + if isinstance(e, BadRequestKeyError) and ( + self.debug or self.config["TRAP_BAD_REQUEST_ERRORS"] + ): + e.show_exception = True + + if isinstance(e, HTTPException) and not self.trap_http_exception(e): + return self.handle_http_exception(e) + + handler = self._find_error_handler(e, request.blueprints) + + if handler is None: + raise + + return self.ensure_sync(handler)(e) + + def handle_exception(self, e: Exception) -> Response: + """Handle an exception that did not have an error handler + associated with it, or that was raised from an error handler. + This always causes a 500 ``InternalServerError``. + + Always sends the :data:`got_request_exception` signal. + + If :data:`PROPAGATE_EXCEPTIONS` is ``True``, such as in debug + mode, the error will be re-raised so that the debugger can + display it. Otherwise, the original exception is logged, and + an :exc:`~werkzeug.exceptions.InternalServerError` is returned. + + If an error handler is registered for ``InternalServerError`` or + ``500``, it will be used. For consistency, the handler will + always receive the ``InternalServerError``. The original + unhandled exception is available as ``e.original_exception``. + + .. versionchanged:: 1.1.0 + Always passes the ``InternalServerError`` instance to the + handler, setting ``original_exception`` to the unhandled + error. + + .. versionchanged:: 1.1.0 + ``after_request`` functions and other finalization is done + even for the default 500 response when there is no handler. + + .. versionadded:: 0.3 + """ + exc_info = sys.exc_info() + got_request_exception.send(self, _async_wrapper=self.ensure_sync, exception=e) + propagate = self.config["PROPAGATE_EXCEPTIONS"] + + if propagate is None: + propagate = self.testing or self.debug + + if propagate: + # Re-raise if called with an active exception, otherwise + # raise the passed in exception. + if exc_info[1] is e: + raise + + raise e + + self.log_exception(exc_info) + server_error: InternalServerError | ft.ResponseReturnValue + server_error = InternalServerError(original_exception=e) + handler = self._find_error_handler(server_error, request.blueprints) + + if handler is not None: + server_error = self.ensure_sync(handler)(server_error) + + return self.finalize_request(server_error, from_error_handler=True) + + def log_exception( + self, + exc_info: (tuple[type, BaseException, TracebackType] | tuple[None, None, None]), + ) -> None: + """Logs an exception. This is called by :meth:`handle_exception` + if debugging is disabled and right before the handler is called. + The default implementation logs the exception as error on the + :attr:`logger`. + + .. versionadded:: 0.8 + """ + self.logger.error( + f"Exception on {request.path} [{request.method}]", exc_info=exc_info + ) + + def dispatch_request(self) -> ft.ResponseReturnValue: + """Does the request dispatching. Matches the URL and returns the + return value of the view or error handler. This does not have to + be a response object. In order to convert the return value to a + proper response object, call :func:`make_response`. + + .. versionchanged:: 0.7 + This no longer does the exception handling, this code was + moved to the new :meth:`full_dispatch_request`. + """ + req = request_ctx.request + if req.routing_exception is not None: + self.raise_routing_exception(req) + rule: Rule = req.url_rule # type: ignore[assignment] + # if we provide automatic options for this URL and the + # request came with the OPTIONS method, reply automatically + if ( + getattr(rule, "provide_automatic_options", False) + and req.method == "OPTIONS" + ): + return self.make_default_options_response() + # otherwise dispatch to the handler for that endpoint + view_args: dict[str, t.Any] = req.view_args # type: ignore[assignment] + return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) + + def full_dispatch_request(self) -> Response: + """Dispatches the request and on top of that performs request + pre and postprocessing as well as HTTP exception catching and + error handling. + + .. versionadded:: 0.7 + """ + self._got_first_request = True + + try: + request_started.send(self, _async_wrapper=self.ensure_sync) + rv = self.preprocess_request() + if rv is None: + rv = self.dispatch_request() + except Exception as e: + rv = self.handle_user_exception(e) + return self.finalize_request(rv) + + def finalize_request( + self, + rv: ft.ResponseReturnValue | HTTPException, + from_error_handler: bool = False, + ) -> Response: + """Given the return value from a view function this finalizes + the request by converting it into a response and invoking the + postprocessing functions. This is invoked for both normal + request dispatching as well as error handlers. + + Because this means that it might be called as a result of a + failure a special safe mode is available which can be enabled + with the `from_error_handler` flag. If enabled, failures in + response processing will be logged and otherwise ignored. + + :internal: + """ + response = self.make_response(rv) + try: + response = self.process_response(response) + request_finished.send( + self, _async_wrapper=self.ensure_sync, response=response + ) + except Exception: + if not from_error_handler: + raise + self.logger.exception( + "Request finalizing failed with an error while handling an error" + ) + return response + + def make_default_options_response(self) -> Response: + """This method is called to create the default ``OPTIONS`` response. + This can be changed through subclassing to change the default + behavior of ``OPTIONS`` responses. + + .. versionadded:: 0.7 + """ + adapter = request_ctx.url_adapter + methods = adapter.allowed_methods() # type: ignore[union-attr] + rv = self.response_class() + rv.allow.update(methods) + return rv + + def ensure_sync(self, func: t.Callable) -> t.Callable: + """Ensure that the function is synchronous for WSGI workers. + Plain ``def`` functions are returned as-is. ``async def`` + functions are wrapped to run and wait for the response. + + Override this method to change how the app runs async views. + + .. versionadded:: 2.0 + """ + if iscoroutinefunction(func): + return self.async_to_sync(func) + + return func + + def async_to_sync( + self, func: t.Callable[..., t.Coroutine] + ) -> t.Callable[..., t.Any]: + """Return a sync function that will run the coroutine function. + + .. code-block:: python + + result = app.async_to_sync(func)(*args, **kwargs) + + Override this method to change how the app converts async code + to be synchronously callable. + + .. versionadded:: 2.0 + """ + try: + from asgiref.sync import async_to_sync as asgiref_async_to_sync + except ImportError: + raise RuntimeError( + "Install Flask with the 'async' extra in order to use async views." + ) from None + + return asgiref_async_to_sync(func) + + def url_for( + self, + /, + endpoint: str, + *, + _anchor: str | None = None, + _method: str | None = None, + _scheme: str | None = None, + _external: bool | None = None, + **values: t.Any, + ) -> str: + """Generate a URL to the given endpoint with the given values. + + This is called by :func:`flask.url_for`, and can be called + directly as well. + + An *endpoint* is the name of a URL rule, usually added with + :meth:`@app.route() `, and usually the same name as the + view function. A route defined in a :class:`~flask.Blueprint` + will prepend the blueprint's name separated by a ``.`` to the + endpoint. + + In some cases, such as email messages, you want URLs to include + the scheme and domain, like ``https://example.com/hello``. When + not in an active request, URLs will be external by default, but + this requires setting :data:`SERVER_NAME` so Flask knows what + domain to use. :data:`APPLICATION_ROOT` and + :data:`PREFERRED_URL_SCHEME` should also be configured as + needed. This config is only used when not in an active request. + + Functions can be decorated with :meth:`url_defaults` to modify + keyword arguments before the URL is built. + + If building fails for some reason, such as an unknown endpoint + or incorrect values, the app's :meth:`handle_url_build_error` + method is called. If that returns a string, that is returned, + otherwise a :exc:`~werkzeug.routing.BuildError` is raised. + + :param endpoint: The endpoint name associated with the URL to + generate. If this starts with a ``.``, the current blueprint + name (if any) will be used. + :param _anchor: If given, append this as ``#anchor`` to the URL. + :param _method: If given, generate the URL associated with this + method for the endpoint. + :param _scheme: If given, the URL will have this scheme if it + is external. + :param _external: If given, prefer the URL to be internal + (False) or require it to be external (True). External URLs + include the scheme and domain. When not in an active + request, URLs are external by default. + :param values: Values to use for the variable parts of the URL + rule. Unknown keys are appended as query string arguments, + like ``?a=b&c=d``. + + .. versionadded:: 2.2 + Moved from ``flask.url_for``, which calls this method. + """ + req_ctx = _cv_request.get(None) + + if req_ctx is not None: + url_adapter = req_ctx.url_adapter + blueprint_name = req_ctx.request.blueprint + + # If the endpoint starts with "." and the request matches a + # blueprint, the endpoint is relative to the blueprint. + if endpoint[:1] == ".": + if blueprint_name is not None: + endpoint = f"{blueprint_name}{endpoint}" + else: + endpoint = endpoint[1:] + + # When in a request, generate a URL without scheme and + # domain by default, unless a scheme is given. + if _external is None: + _external = _scheme is not None + else: + app_ctx = _cv_app.get(None) + + # If called by helpers.url_for, an app context is active, + # use its url_adapter. Otherwise, app.url_for was called + # directly, build an adapter. + if app_ctx is not None: + url_adapter = app_ctx.url_adapter + else: + url_adapter = self.create_url_adapter(None) + + if url_adapter is None: + raise RuntimeError( + "Unable to build URLs outside an active request" + " without 'SERVER_NAME' configured. Also configure" + " 'APPLICATION_ROOT' and 'PREFERRED_URL_SCHEME' as" + " needed." + ) + + # When outside a request, generate a URL with scheme and + # domain by default. + if _external is None: + _external = True + + # It is an error to set _scheme when _external=False, in order + # to avoid accidental insecure URLs. + if _scheme is not None and not _external: + raise ValueError("When specifying '_scheme', '_external' must be True.") + + self.inject_url_defaults(endpoint, values) + + try: + rv = url_adapter.build( # type: ignore[union-attr] + endpoint, + values, + method=_method, + url_scheme=_scheme, + force_external=_external, + ) + except BuildError as error: + values.update( + _anchor=_anchor, _method=_method, _scheme=_scheme, _external=_external + ) + return self.handle_url_build_error(error, endpoint, values) + + if _anchor is not None: + _anchor = _url_quote(_anchor, safe="%!#$&'()*+,/:;=?@") + rv = f"{rv}#{_anchor}" + + return rv + + def make_response(self, rv: ft.ResponseReturnValue) -> Response: + """Convert the return value from a view function to an instance of + :attr:`response_class`. + + :param rv: the return value from the view function. The view function + must return a response. Returning ``None``, or the view ending + without returning, is not allowed. The following types are allowed + for ``view_rv``: + + ``str`` + A response object is created with the string encoded to UTF-8 + as the body. + + ``bytes`` + A response object is created with the bytes as the body. + + ``dict`` + A dictionary that will be jsonify'd before being returned. + + ``list`` + A list that will be jsonify'd before being returned. + + ``generator`` or ``iterator`` + A generator that returns ``str`` or ``bytes`` to be + streamed as the response. + + ``tuple`` + Either ``(body, status, headers)``, ``(body, status)``, or + ``(body, headers)``, where ``body`` is any of the other types + allowed here, ``status`` is a string or an integer, and + ``headers`` is a dictionary or a list of ``(key, value)`` + tuples. If ``body`` is a :attr:`response_class` instance, + ``status`` overwrites the exiting value and ``headers`` are + extended. + + :attr:`response_class` + The object is returned unchanged. + + other :class:`~werkzeug.wrappers.Response` class + The object is coerced to :attr:`response_class`. + + :func:`callable` + The function is called as a WSGI application. The result is + used to create a response object. + + .. versionchanged:: 2.2 + A generator will be converted to a streaming response. + A list will be converted to a JSON response. + + .. versionchanged:: 1.1 + A dict will be converted to a JSON response. + + .. versionchanged:: 0.9 + Previously a tuple was interpreted as the arguments for the + response object. + """ + + status = headers = None + + # unpack tuple returns + if isinstance(rv, tuple): + len_rv = len(rv) + + # a 3-tuple is unpacked directly + if len_rv == 3: + rv, status, headers = rv # type: ignore[misc] + # decide if a 2-tuple has status or headers + elif len_rv == 2: + if isinstance(rv[1], (Headers, dict, tuple, list)): + rv, headers = rv + else: + rv, status = rv # type: ignore[assignment,misc] + # other sized tuples are not allowed + else: + raise TypeError( + "The view function did not return a valid response tuple." + " The tuple must have the form (body, status, headers)," + " (body, status), or (body, headers)." + ) + + # the body must not be None + if rv is None: + raise TypeError( + f"The view function for {request.endpoint!r} did not" + " return a valid response. The function either returned" + " None or ended without a return statement." + ) + + # make sure the body is an instance of the response class + if not isinstance(rv, self.response_class): + if isinstance(rv, (str, bytes, bytearray)) or isinstance(rv, _abc_Iterator): + # let the response class set the status and headers instead of + # waiting to do it manually, so that the class can handle any + # special logic + rv = self.response_class( + rv, + status=status, + headers=headers, # type: ignore[arg-type] + ) + status = headers = None + elif isinstance(rv, (dict, list)): + rv = self.json.response(rv) + elif isinstance(rv, BaseResponse) or callable(rv): + # evaluate a WSGI callable, or coerce a different response + # class to the correct type + try: + rv = self.response_class.force_type( + rv, request.environ # type: ignore[arg-type] + ) + except TypeError as e: + raise TypeError( + f"{e}\nThe view function did not return a valid" + " response. The return type must be a string," + " dict, list, tuple with headers or status," + " Response instance, or WSGI callable, but it" + f" was a {type(rv).__name__}." + ).with_traceback(sys.exc_info()[2]) from None + else: + raise TypeError( + "The view function did not return a valid" + " response. The return type must be a string," + " dict, list, tuple with headers or status," + " Response instance, or WSGI callable, but it was a" + f" {type(rv).__name__}." + ) + + rv = t.cast(Response, rv) + # prefer the status if it was provided + if status is not None: + if isinstance(status, (str, bytes, bytearray)): + rv.status = status + else: + rv.status_code = status + + # extend existing headers with provided headers + if headers: + rv.headers.update(headers) # type: ignore[arg-type] + + return rv + + def preprocess_request(self) -> ft.ResponseReturnValue | None: + """Called before the request is dispatched. Calls + :attr:`url_value_preprocessors` registered with the app and the + current blueprint (if any). Then calls :attr:`before_request_funcs` + registered with the app and the blueprint. + + If any :meth:`before_request` handler returns a non-None value, the + value is handled as if it was the return value from the view, and + further request handling is stopped. + """ + names = (None, *reversed(request.blueprints)) + + for name in names: + if name in self.url_value_preprocessors: + for url_func in self.url_value_preprocessors[name]: + url_func(request.endpoint, request.view_args) + + for name in names: + if name in self.before_request_funcs: + for before_func in self.before_request_funcs[name]: + rv = self.ensure_sync(before_func)() + + if rv is not None: + return rv + + return None + + def process_response(self, response: Response) -> Response: + """Can be overridden in order to modify the response object + before it's sent to the WSGI server. By default this will + call all the :meth:`after_request` decorated functions. + + .. versionchanged:: 0.5 + As of Flask 0.5 the functions registered for after request + execution are called in reverse order of registration. + + :param response: a :attr:`response_class` object. + :return: a new response object or the same, has to be an + instance of :attr:`response_class`. + """ + ctx = request_ctx._get_current_object() # type: ignore[attr-defined] + + for func in ctx._after_request_functions: + response = self.ensure_sync(func)(response) + + for name in chain(request.blueprints, (None,)): + if name in self.after_request_funcs: + for func in reversed(self.after_request_funcs[name]): + response = self.ensure_sync(func)(response) + + if not self.session_interface.is_null_session(ctx.session): + self.session_interface.save_session(self, ctx.session, response) + + return response + + def do_teardown_request( + self, exc: BaseException | None = _sentinel # type: ignore + ) -> None: + """Called after the request is dispatched and the response is + returned, right before the request context is popped. + + This calls all functions decorated with + :meth:`teardown_request`, and :meth:`Blueprint.teardown_request` + if a blueprint handled the request. Finally, the + :data:`request_tearing_down` signal is sent. + + This is called by + :meth:`RequestContext.pop() `, + which may be delayed during testing to maintain access to + resources. + + :param exc: An unhandled exception raised while dispatching the + request. Detected from the current exception information if + not passed. Passed to each teardown function. + + .. versionchanged:: 0.9 + Added the ``exc`` argument. + """ + if exc is _sentinel: + exc = sys.exc_info()[1] + + for name in chain(request.blueprints, (None,)): + if name in self.teardown_request_funcs: + for func in reversed(self.teardown_request_funcs[name]): + self.ensure_sync(func)(exc) + + request_tearing_down.send(self, _async_wrapper=self.ensure_sync, exc=exc) + + def do_teardown_appcontext( + self, exc: BaseException | None = _sentinel # type: ignore + ) -> None: + """Called right before the application context is popped. + + When handling a request, the application context is popped + after the request context. See :meth:`do_teardown_request`. + + This calls all functions decorated with + :meth:`teardown_appcontext`. Then the + :data:`appcontext_tearing_down` signal is sent. + + This is called by + :meth:`AppContext.pop() `. + + .. versionadded:: 0.9 + """ + if exc is _sentinel: + exc = sys.exc_info()[1] + + for func in reversed(self.teardown_appcontext_funcs): + self.ensure_sync(func)(exc) + + appcontext_tearing_down.send(self, _async_wrapper=self.ensure_sync, exc=exc) + + def app_context(self) -> AppContext: + """Create an :class:`~flask.ctx.AppContext`. Use as a ``with`` + block to push the context, which will make :data:`current_app` + point at this application. + + An application context is automatically pushed by + :meth:`RequestContext.push() ` + when handling a request, and when running a CLI command. Use + this to manually create a context outside of these situations. + + :: + + with app.app_context(): + init_db() + + See :doc:`/appcontext`. + + .. versionadded:: 0.9 + """ + return AppContext(self) + + def request_context(self, environ: dict) -> RequestContext: + """Create a :class:`~flask.ctx.RequestContext` representing a + WSGI environment. Use a ``with`` block to push the context, + which will make :data:`request` point at this request. + + See :doc:`/reqcontext`. + + Typically you should not call this from your own code. A request + context is automatically pushed by the :meth:`wsgi_app` when + handling a request. Use :meth:`test_request_context` to create + an environment and context instead of this method. + + :param environ: a WSGI environment + """ + return RequestContext(self, environ) + + def test_request_context(self, *args: t.Any, **kwargs: t.Any) -> RequestContext: + """Create a :class:`~flask.ctx.RequestContext` for a WSGI + environment created from the given values. This is mostly useful + during testing, where you may want to run a function that uses + request data without dispatching a full request. + + See :doc:`/reqcontext`. + + Use a ``with`` block to push the context, which will make + :data:`request` point at the request for the created + environment. :: + + with app.test_request_context(...): + generate_report() + + When using the shell, it may be easier to push and pop the + context manually to avoid indentation. :: + + ctx = app.test_request_context(...) + ctx.push() + ... + ctx.pop() + + Takes the same arguments as Werkzeug's + :class:`~werkzeug.test.EnvironBuilder`, with some defaults from + the application. See the linked Werkzeug docs for most of the + available arguments. Flask-specific behavior is listed here. + + :param path: URL path being requested. + :param base_url: Base URL where the app is being served, which + ``path`` is relative to. If not given, built from + :data:`PREFERRED_URL_SCHEME`, ``subdomain``, + :data:`SERVER_NAME`, and :data:`APPLICATION_ROOT`. + :param subdomain: Subdomain name to append to + :data:`SERVER_NAME`. + :param url_scheme: Scheme to use instead of + :data:`PREFERRED_URL_SCHEME`. + :param data: The request body, either as a string or a dict of + form keys and values. + :param json: If given, this is serialized as JSON and passed as + ``data``. Also defaults ``content_type`` to + ``application/json``. + :param args: other positional arguments passed to + :class:`~werkzeug.test.EnvironBuilder`. + :param kwargs: other keyword arguments passed to + :class:`~werkzeug.test.EnvironBuilder`. + """ + from .testing import EnvironBuilder + + builder = EnvironBuilder(self, *args, **kwargs) + + try: + return self.request_context(builder.get_environ()) + finally: + builder.close() + + def wsgi_app(self, environ: dict, start_response: t.Callable) -> t.Any: + """The actual WSGI application. This is not implemented in + :meth:`__call__` so that middlewares can be applied without + losing a reference to the app object. Instead of doing this:: + + app = MyMiddleware(app) + + It's a better idea to do this instead:: + + app.wsgi_app = MyMiddleware(app.wsgi_app) + + Then you still have the original application object around and + can continue to call methods on it. + + .. versionchanged:: 0.7 + Teardown events for the request and app contexts are called + even if an unhandled error occurs. Other events may not be + called depending on when an error occurs during dispatch. + See :ref:`callbacks-and-errors`. + + :param environ: A WSGI environment. + :param start_response: A callable accepting a status code, + a list of headers, and an optional exception context to + start the response. + """ + ctx = self.request_context(environ) + error: BaseException | None = None + try: + try: + ctx.push() + response = self.full_dispatch_request() + except Exception as e: + error = e + response = self.handle_exception(e) + except: # noqa: B001 + error = sys.exc_info()[1] + raise + return response(environ, start_response) + finally: + if "werkzeug.debug.preserve_context" in environ: + environ["werkzeug.debug.preserve_context"](_cv_app.get()) + environ["werkzeug.debug.preserve_context"](_cv_request.get()) + + if error is not None and self.should_ignore_error(error): + error = None + + ctx.pop(error) + + def __call__(self, environ: dict, start_response: t.Callable) -> t.Any: + """The WSGI server calls the Flask application object as the + WSGI application. This calls :meth:`wsgi_app`, which can be + wrapped to apply middleware. + """ + return self.wsgi_app(environ, start_response) diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/blueprints.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/blueprints.py new file mode 100644 index 0000000..3a37a2c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/blueprints.py @@ -0,0 +1,91 @@ +from __future__ import annotations + +import os +import typing as t +from datetime import timedelta + +from .globals import current_app +from .helpers import send_from_directory +from .sansio.blueprints import Blueprint as SansioBlueprint +from .sansio.blueprints import BlueprintSetupState as BlueprintSetupState # noqa + +if t.TYPE_CHECKING: # pragma: no cover + from .wrappers import Response + + +class Blueprint(SansioBlueprint): + def get_send_file_max_age(self, filename: str | None) -> int | None: + """Used by :func:`send_file` to determine the ``max_age`` cache + value for a given file path if it wasn't passed. + + By default, this returns :data:`SEND_FILE_MAX_AGE_DEFAULT` from + the configuration of :data:`~flask.current_app`. This defaults + to ``None``, which tells the browser to use conditional requests + instead of a timed cache, which is usually preferable. + + Note this is a duplicate of the same method in the Flask + class. + + .. versionchanged:: 2.0 + The default configuration is ``None`` instead of 12 hours. + + .. versionadded:: 0.9 + """ + value = current_app.config["SEND_FILE_MAX_AGE_DEFAULT"] + + if value is None: + return None + + if isinstance(value, timedelta): + return int(value.total_seconds()) + + return value + + def send_static_file(self, filename: str) -> Response: + """The view function used to serve files from + :attr:`static_folder`. A route is automatically registered for + this view at :attr:`static_url_path` if :attr:`static_folder` is + set. + + Note this is a duplicate of the same method in the Flask + class. + + .. versionadded:: 0.5 + + """ + if not self.has_static_folder: + raise RuntimeError("'static_folder' must be set to serve static_files.") + + # send_file only knows to call get_send_file_max_age on the app, + # call it here so it works for blueprints too. + max_age = self.get_send_file_max_age(filename) + return send_from_directory( + t.cast(str, self.static_folder), filename, max_age=max_age + ) + + def open_resource(self, resource: str, mode: str = "rb") -> t.IO[t.AnyStr]: + """Open a resource file relative to :attr:`root_path` for + reading. + + For example, if the file ``schema.sql`` is next to the file + ``app.py`` where the ``Flask`` app is defined, it can be opened + with: + + .. code-block:: python + + with app.open_resource("schema.sql") as f: + conn.executescript(f.read()) + + :param resource: Path to the resource relative to + :attr:`root_path`. + :param mode: Open the file in this mode. Only reading is + supported, valid values are "r" (or "rt") and "rb". + + Note this is a duplicate of the same method in the Flask + class. + + """ + if mode not in {"r", "rt", "rb"}: + raise ValueError("Resources can only be opened for reading.") + + return open(os.path.join(self.root_path, resource), mode) diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/cli.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/cli.py new file mode 100644 index 0000000..dda266b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/cli.py @@ -0,0 +1,1068 @@ +from __future__ import annotations + +import ast +import importlib.metadata +import inspect +import os +import platform +import re +import sys +import traceback +import typing as t +from functools import update_wrapper +from operator import itemgetter + +import click +from click.core import ParameterSource +from werkzeug import run_simple +from werkzeug.serving import is_running_from_reloader +from werkzeug.utils import import_string + +from .globals import current_app +from .helpers import get_debug_flag +from .helpers import get_load_dotenv + +if t.TYPE_CHECKING: + from .app import Flask + + +class NoAppException(click.UsageError): + """Raised if an application cannot be found or loaded.""" + + +def find_best_app(module): + """Given a module instance this tries to find the best possible + application in the module or raises an exception. + """ + from . import Flask + + # Search for the most common names first. + for attr_name in ("app", "application"): + app = getattr(module, attr_name, None) + + if isinstance(app, Flask): + return app + + # Otherwise find the only object that is a Flask instance. + matches = [v for v in module.__dict__.values() if isinstance(v, Flask)] + + if len(matches) == 1: + return matches[0] + elif len(matches) > 1: + raise NoAppException( + "Detected multiple Flask applications in module" + f" '{module.__name__}'. Use '{module.__name__}:name'" + " to specify the correct one." + ) + + # Search for app factory functions. + for attr_name in ("create_app", "make_app"): + app_factory = getattr(module, attr_name, None) + + if inspect.isfunction(app_factory): + try: + app = app_factory() + + if isinstance(app, Flask): + return app + except TypeError as e: + if not _called_with_wrong_args(app_factory): + raise + + raise NoAppException( + f"Detected factory '{attr_name}' in module '{module.__name__}'," + " but could not call it without arguments. Use" + f" '{module.__name__}:{attr_name}(args)'" + " to specify arguments." + ) from e + + raise NoAppException( + "Failed to find Flask application or factory in module" + f" '{module.__name__}'. Use '{module.__name__}:name'" + " to specify one." + ) + + +def _called_with_wrong_args(f): + """Check whether calling a function raised a ``TypeError`` because + the call failed or because something in the factory raised the + error. + + :param f: The function that was called. + :return: ``True`` if the call failed. + """ + tb = sys.exc_info()[2] + + try: + while tb is not None: + if tb.tb_frame.f_code is f.__code__: + # In the function, it was called successfully. + return False + + tb = tb.tb_next + + # Didn't reach the function. + return True + finally: + # Delete tb to break a circular reference. + # https://docs.python.org/2/library/sys.html#sys.exc_info + del tb + + +def find_app_by_string(module, app_name): + """Check if the given string is a variable name or a function. Call + a function to get the app instance, or return the variable directly. + """ + from . import Flask + + # Parse app_name as a single expression to determine if it's a valid + # attribute name or function call. + try: + expr = ast.parse(app_name.strip(), mode="eval").body + except SyntaxError: + raise NoAppException( + f"Failed to parse {app_name!r} as an attribute name or function call." + ) from None + + if isinstance(expr, ast.Name): + name = expr.id + args = [] + kwargs = {} + elif isinstance(expr, ast.Call): + # Ensure the function name is an attribute name only. + if not isinstance(expr.func, ast.Name): + raise NoAppException( + f"Function reference must be a simple name: {app_name!r}." + ) + + name = expr.func.id + + # Parse the positional and keyword arguments as literals. + try: + args = [ast.literal_eval(arg) for arg in expr.args] + kwargs = {kw.arg: ast.literal_eval(kw.value) for kw in expr.keywords} + except ValueError: + # literal_eval gives cryptic error messages, show a generic + # message with the full expression instead. + raise NoAppException( + f"Failed to parse arguments as literal values: {app_name!r}." + ) from None + else: + raise NoAppException( + f"Failed to parse {app_name!r} as an attribute name or function call." + ) + + try: + attr = getattr(module, name) + except AttributeError as e: + raise NoAppException( + f"Failed to find attribute {name!r} in {module.__name__!r}." + ) from e + + # If the attribute is a function, call it with any args and kwargs + # to get the real application. + if inspect.isfunction(attr): + try: + app = attr(*args, **kwargs) + except TypeError as e: + if not _called_with_wrong_args(attr): + raise + + raise NoAppException( + f"The factory {app_name!r} in module" + f" {module.__name__!r} could not be called with the" + " specified arguments." + ) from e + else: + app = attr + + if isinstance(app, Flask): + return app + + raise NoAppException( + "A valid Flask application was not obtained from" + f" '{module.__name__}:{app_name}'." + ) + + +def prepare_import(path): + """Given a filename this will try to calculate the python path, add it + to the search path and return the actual module name that is expected. + """ + path = os.path.realpath(path) + + fname, ext = os.path.splitext(path) + if ext == ".py": + path = fname + + if os.path.basename(path) == "__init__": + path = os.path.dirname(path) + + module_name = [] + + # move up until outside package structure (no __init__.py) + while True: + path, name = os.path.split(path) + module_name.append(name) + + if not os.path.exists(os.path.join(path, "__init__.py")): + break + + if sys.path[0] != path: + sys.path.insert(0, path) + + return ".".join(module_name[::-1]) + + +def locate_app(module_name, app_name, raise_if_not_found=True): + try: + __import__(module_name) + except ImportError: + # Reraise the ImportError if it occurred within the imported module. + # Determine this by checking whether the trace has a depth > 1. + if sys.exc_info()[2].tb_next: + raise NoAppException( + f"While importing {module_name!r}, an ImportError was" + f" raised:\n\n{traceback.format_exc()}" + ) from None + elif raise_if_not_found: + raise NoAppException(f"Could not import {module_name!r}.") from None + else: + return + + module = sys.modules[module_name] + + if app_name is None: + return find_best_app(module) + else: + return find_app_by_string(module, app_name) + + +def get_version(ctx, param, value): + if not value or ctx.resilient_parsing: + return + + flask_version = importlib.metadata.version("flask") + werkzeug_version = importlib.metadata.version("werkzeug") + + click.echo( + f"Python {platform.python_version()}\n" + f"Flask {flask_version}\n" + f"Werkzeug {werkzeug_version}", + color=ctx.color, + ) + ctx.exit() + + +version_option = click.Option( + ["--version"], + help="Show the Flask version.", + expose_value=False, + callback=get_version, + is_flag=True, + is_eager=True, +) + + +class ScriptInfo: + """Helper object to deal with Flask applications. This is usually not + necessary to interface with as it's used internally in the dispatching + to click. In future versions of Flask this object will most likely play + a bigger role. Typically it's created automatically by the + :class:`FlaskGroup` but you can also manually create it and pass it + onwards as click object. + """ + + def __init__( + self, + app_import_path: str | None = None, + create_app: t.Callable[..., Flask] | None = None, + set_debug_flag: bool = True, + ) -> None: + #: Optionally the import path for the Flask application. + self.app_import_path = app_import_path + #: Optionally a function that is passed the script info to create + #: the instance of the application. + self.create_app = create_app + #: A dictionary with arbitrary data that can be associated with + #: this script info. + self.data: dict[t.Any, t.Any] = {} + self.set_debug_flag = set_debug_flag + self._loaded_app: Flask | None = None + + def load_app(self) -> Flask: + """Loads the Flask app (if not yet loaded) and returns it. Calling + this multiple times will just result in the already loaded app to + be returned. + """ + if self._loaded_app is not None: + return self._loaded_app + + if self.create_app is not None: + app = self.create_app() + else: + if self.app_import_path: + path, name = ( + re.split(r":(?![\\/])", self.app_import_path, maxsplit=1) + [None] + )[:2] + import_name = prepare_import(path) + app = locate_app(import_name, name) + else: + for path in ("wsgi.py", "app.py"): + import_name = prepare_import(path) + app = locate_app(import_name, None, raise_if_not_found=False) + + if app: + break + + if not app: + raise NoAppException( + "Could not locate a Flask application. Use the" + " 'flask --app' option, 'FLASK_APP' environment" + " variable, or a 'wsgi.py' or 'app.py' file in the" + " current directory." + ) + + if self.set_debug_flag: + # Update the app's debug flag through the descriptor so that + # other values repopulate as well. + app.debug = get_debug_flag() + + self._loaded_app = app + return app + + +pass_script_info = click.make_pass_decorator(ScriptInfo, ensure=True) + + +def with_appcontext(f): + """Wraps a callback so that it's guaranteed to be executed with the + script's application context. + + Custom commands (and their options) registered under ``app.cli`` or + ``blueprint.cli`` will always have an app context available, this + decorator is not required in that case. + + .. versionchanged:: 2.2 + The app context is active for subcommands as well as the + decorated callback. The app context is always available to + ``app.cli`` command and parameter callbacks. + """ + + @click.pass_context + def decorator(__ctx, *args, **kwargs): + if not current_app: + app = __ctx.ensure_object(ScriptInfo).load_app() + __ctx.with_resource(app.app_context()) + + return __ctx.invoke(f, *args, **kwargs) + + return update_wrapper(decorator, f) + + +class AppGroup(click.Group): + """This works similar to a regular click :class:`~click.Group` but it + changes the behavior of the :meth:`command` decorator so that it + automatically wraps the functions in :func:`with_appcontext`. + + Not to be confused with :class:`FlaskGroup`. + """ + + def command(self, *args, **kwargs): + """This works exactly like the method of the same name on a regular + :class:`click.Group` but it wraps callbacks in :func:`with_appcontext` + unless it's disabled by passing ``with_appcontext=False``. + """ + wrap_for_ctx = kwargs.pop("with_appcontext", True) + + def decorator(f): + if wrap_for_ctx: + f = with_appcontext(f) + return click.Group.command(self, *args, **kwargs)(f) + + return decorator + + def group(self, *args, **kwargs): + """This works exactly like the method of the same name on a regular + :class:`click.Group` but it defaults the group class to + :class:`AppGroup`. + """ + kwargs.setdefault("cls", AppGroup) + return click.Group.group(self, *args, **kwargs) + + +def _set_app(ctx: click.Context, param: click.Option, value: str | None) -> str | None: + if value is None: + return None + + info = ctx.ensure_object(ScriptInfo) + info.app_import_path = value + return value + + +# This option is eager so the app will be available if --help is given. +# --help is also eager, so --app must be before it in the param list. +# no_args_is_help bypasses eager processing, so this option must be +# processed manually in that case to ensure FLASK_APP gets picked up. +_app_option = click.Option( + ["-A", "--app"], + metavar="IMPORT", + help=( + "The Flask application or factory function to load, in the form 'module:name'." + " Module can be a dotted import or file path. Name is not required if it is" + " 'app', 'application', 'create_app', or 'make_app', and can be 'name(args)' to" + " pass arguments." + ), + is_eager=True, + expose_value=False, + callback=_set_app, +) + + +def _set_debug(ctx: click.Context, param: click.Option, value: bool) -> bool | None: + # If the flag isn't provided, it will default to False. Don't use + # that, let debug be set by env in that case. + source = ctx.get_parameter_source(param.name) # type: ignore[arg-type] + + if source is not None and source in ( + ParameterSource.DEFAULT, + ParameterSource.DEFAULT_MAP, + ): + return None + + # Set with env var instead of ScriptInfo.load so that it can be + # accessed early during a factory function. + os.environ["FLASK_DEBUG"] = "1" if value else "0" + return value + + +_debug_option = click.Option( + ["--debug/--no-debug"], + help="Set debug mode.", + expose_value=False, + callback=_set_debug, +) + + +def _env_file_callback( + ctx: click.Context, param: click.Option, value: str | None +) -> str | None: + if value is None: + return None + + import importlib + + try: + importlib.import_module("dotenv") + except ImportError: + raise click.BadParameter( + "python-dotenv must be installed to load an env file.", + ctx=ctx, + param=param, + ) from None + + # Don't check FLASK_SKIP_DOTENV, that only disables automatically + # loading .env and .flaskenv files. + load_dotenv(value) + return value + + +# This option is eager so env vars are loaded as early as possible to be +# used by other options. +_env_file_option = click.Option( + ["-e", "--env-file"], + type=click.Path(exists=True, dir_okay=False), + help="Load environment variables from this file. python-dotenv must be installed.", + is_eager=True, + expose_value=False, + callback=_env_file_callback, +) + + +class FlaskGroup(AppGroup): + """Special subclass of the :class:`AppGroup` group that supports + loading more commands from the configured Flask app. Normally a + developer does not have to interface with this class but there are + some very advanced use cases for which it makes sense to create an + instance of this. see :ref:`custom-scripts`. + + :param add_default_commands: if this is True then the default run and + shell commands will be added. + :param add_version_option: adds the ``--version`` option. + :param create_app: an optional callback that is passed the script info and + returns the loaded app. + :param load_dotenv: Load the nearest :file:`.env` and :file:`.flaskenv` + files to set environment variables. Will also change the working + directory to the directory containing the first file found. + :param set_debug_flag: Set the app's debug flag. + + .. versionchanged:: 2.2 + Added the ``-A/--app``, ``--debug/--no-debug``, ``-e/--env-file`` options. + + .. versionchanged:: 2.2 + An app context is pushed when running ``app.cli`` commands, so + ``@with_appcontext`` is no longer required for those commands. + + .. versionchanged:: 1.0 + If installed, python-dotenv will be used to load environment variables + from :file:`.env` and :file:`.flaskenv` files. + """ + + def __init__( + self, + add_default_commands: bool = True, + create_app: t.Callable[..., Flask] | None = None, + add_version_option: bool = True, + load_dotenv: bool = True, + set_debug_flag: bool = True, + **extra: t.Any, + ) -> None: + params = list(extra.pop("params", None) or ()) + # Processing is done with option callbacks instead of a group + # callback. This allows users to make a custom group callback + # without losing the behavior. --env-file must come first so + # that it is eagerly evaluated before --app. + params.extend((_env_file_option, _app_option, _debug_option)) + + if add_version_option: + params.append(version_option) + + if "context_settings" not in extra: + extra["context_settings"] = {} + + extra["context_settings"].setdefault("auto_envvar_prefix", "FLASK") + + super().__init__(params=params, **extra) + + self.create_app = create_app + self.load_dotenv = load_dotenv + self.set_debug_flag = set_debug_flag + + if add_default_commands: + self.add_command(run_command) + self.add_command(shell_command) + self.add_command(routes_command) + + self._loaded_plugin_commands = False + + def _load_plugin_commands(self): + if self._loaded_plugin_commands: + return + + if sys.version_info >= (3, 10): + from importlib import metadata + else: + # Use a backport on Python < 3.10. We technically have + # importlib.metadata on 3.8+, but the API changed in 3.10, + # so use the backport for consistency. + import importlib_metadata as metadata + + for ep in metadata.entry_points(group="flask.commands"): + self.add_command(ep.load(), ep.name) + + self._loaded_plugin_commands = True + + def get_command(self, ctx, name): + self._load_plugin_commands() + # Look up built-in and plugin commands, which should be + # available even if the app fails to load. + rv = super().get_command(ctx, name) + + if rv is not None: + return rv + + info = ctx.ensure_object(ScriptInfo) + + # Look up commands provided by the app, showing an error and + # continuing if the app couldn't be loaded. + try: + app = info.load_app() + except NoAppException as e: + click.secho(f"Error: {e.format_message()}\n", err=True, fg="red") + return None + + # Push an app context for the loaded app unless it is already + # active somehow. This makes the context available to parameter + # and command callbacks without needing @with_appcontext. + if not current_app or current_app._get_current_object() is not app: + ctx.with_resource(app.app_context()) + + return app.cli.get_command(ctx, name) + + def list_commands(self, ctx): + self._load_plugin_commands() + # Start with the built-in and plugin commands. + rv = set(super().list_commands(ctx)) + info = ctx.ensure_object(ScriptInfo) + + # Add commands provided by the app, showing an error and + # continuing if the app couldn't be loaded. + try: + rv.update(info.load_app().cli.list_commands(ctx)) + except NoAppException as e: + # When an app couldn't be loaded, show the error message + # without the traceback. + click.secho(f"Error: {e.format_message()}\n", err=True, fg="red") + except Exception: + # When any other errors occurred during loading, show the + # full traceback. + click.secho(f"{traceback.format_exc()}\n", err=True, fg="red") + + return sorted(rv) + + def make_context( + self, + info_name: str | None, + args: list[str], + parent: click.Context | None = None, + **extra: t.Any, + ) -> click.Context: + # Set a flag to tell app.run to become a no-op. If app.run was + # not in a __name__ == __main__ guard, it would start the server + # when importing, blocking whatever command is being called. + os.environ["FLASK_RUN_FROM_CLI"] = "true" + + # Attempt to load .env and .flask env files. The --env-file + # option can cause another file to be loaded. + if get_load_dotenv(self.load_dotenv): + load_dotenv() + + if "obj" not in extra and "obj" not in self.context_settings: + extra["obj"] = ScriptInfo( + create_app=self.create_app, set_debug_flag=self.set_debug_flag + ) + + return super().make_context(info_name, args, parent=parent, **extra) + + def parse_args(self, ctx: click.Context, args: list[str]) -> list[str]: + if not args and self.no_args_is_help: + # Attempt to load --env-file and --app early in case they + # were given as env vars. Otherwise no_args_is_help will not + # see commands from app.cli. + _env_file_option.handle_parse_result(ctx, {}, []) + _app_option.handle_parse_result(ctx, {}, []) + + return super().parse_args(ctx, args) + + +def _path_is_ancestor(path, other): + """Take ``other`` and remove the length of ``path`` from it. Then join it + to ``path``. If it is the original value, ``path`` is an ancestor of + ``other``.""" + return os.path.join(path, other[len(path) :].lstrip(os.sep)) == other + + +def load_dotenv(path: str | os.PathLike | None = None) -> bool: + """Load "dotenv" files in order of precedence to set environment variables. + + If an env var is already set it is not overwritten, so earlier files in the + list are preferred over later files. + + This is a no-op if `python-dotenv`_ is not installed. + + .. _python-dotenv: https://github.com/theskumar/python-dotenv#readme + + :param path: Load the file at this location instead of searching. + :return: ``True`` if a file was loaded. + + .. versionchanged:: 2.0 + The current directory is not changed to the location of the + loaded file. + + .. versionchanged:: 2.0 + When loading the env files, set the default encoding to UTF-8. + + .. versionchanged:: 1.1.0 + Returns ``False`` when python-dotenv is not installed, or when + the given path isn't a file. + + .. versionadded:: 1.0 + """ + try: + import dotenv + except ImportError: + if path or os.path.isfile(".env") or os.path.isfile(".flaskenv"): + click.secho( + " * Tip: There are .env or .flaskenv files present." + ' Do "pip install python-dotenv" to use them.', + fg="yellow", + err=True, + ) + + return False + + # Always return after attempting to load a given path, don't load + # the default files. + if path is not None: + if os.path.isfile(path): + return dotenv.load_dotenv(path, encoding="utf-8") + + return False + + loaded = False + + for name in (".env", ".flaskenv"): + path = dotenv.find_dotenv(name, usecwd=True) + + if not path: + continue + + dotenv.load_dotenv(path, encoding="utf-8") + loaded = True + + return loaded # True if at least one file was located and loaded. + + +def show_server_banner(debug, app_import_path): + """Show extra startup messages the first time the server is run, + ignoring the reloader. + """ + if is_running_from_reloader(): + return + + if app_import_path is not None: + click.echo(f" * Serving Flask app '{app_import_path}'") + + if debug is not None: + click.echo(f" * Debug mode: {'on' if debug else 'off'}") + + +class CertParamType(click.ParamType): + """Click option type for the ``--cert`` option. Allows either an + existing file, the string ``'adhoc'``, or an import for a + :class:`~ssl.SSLContext` object. + """ + + name = "path" + + def __init__(self): + self.path_type = click.Path(exists=True, dir_okay=False, resolve_path=True) + + def convert(self, value, param, ctx): + try: + import ssl + except ImportError: + raise click.BadParameter( + 'Using "--cert" requires Python to be compiled with SSL support.', + ctx, + param, + ) from None + + try: + return self.path_type(value, param, ctx) + except click.BadParameter: + value = click.STRING(value, param, ctx).lower() + + if value == "adhoc": + try: + import cryptography # noqa: F401 + except ImportError: + raise click.BadParameter( + "Using ad-hoc certificates requires the cryptography library.", + ctx, + param, + ) from None + + return value + + obj = import_string(value, silent=True) + + if isinstance(obj, ssl.SSLContext): + return obj + + raise + + +def _validate_key(ctx, param, value): + """The ``--key`` option must be specified when ``--cert`` is a file. + Modifies the ``cert`` param to be a ``(cert, key)`` pair if needed. + """ + cert = ctx.params.get("cert") + is_adhoc = cert == "adhoc" + + try: + import ssl + except ImportError: + is_context = False + else: + is_context = isinstance(cert, ssl.SSLContext) + + if value is not None: + if is_adhoc: + raise click.BadParameter( + 'When "--cert" is "adhoc", "--key" is not used.', ctx, param + ) + + if is_context: + raise click.BadParameter( + 'When "--cert" is an SSLContext object, "--key is not used.', ctx, param + ) + + if not cert: + raise click.BadParameter('"--cert" must also be specified.', ctx, param) + + ctx.params["cert"] = cert, value + + else: + if cert and not (is_adhoc or is_context): + raise click.BadParameter('Required when using "--cert".', ctx, param) + + return value + + +class SeparatedPathType(click.Path): + """Click option type that accepts a list of values separated by the + OS's path separator (``:``, ``;`` on Windows). Each value is + validated as a :class:`click.Path` type. + """ + + def convert(self, value, param, ctx): + items = self.split_envvar_value(value) + super_convert = super().convert + return [super_convert(item, param, ctx) for item in items] + + +@click.command("run", short_help="Run a development server.") +@click.option("--host", "-h", default="127.0.0.1", help="The interface to bind to.") +@click.option("--port", "-p", default=5000, help="The port to bind to.") +@click.option( + "--cert", + type=CertParamType(), + help="Specify a certificate file to use HTTPS.", + is_eager=True, +) +@click.option( + "--key", + type=click.Path(exists=True, dir_okay=False, resolve_path=True), + callback=_validate_key, + expose_value=False, + help="The key file to use when specifying a certificate.", +) +@click.option( + "--reload/--no-reload", + default=None, + help="Enable or disable the reloader. By default the reloader " + "is active if debug is enabled.", +) +@click.option( + "--debugger/--no-debugger", + default=None, + help="Enable or disable the debugger. By default the debugger " + "is active if debug is enabled.", +) +@click.option( + "--with-threads/--without-threads", + default=True, + help="Enable or disable multithreading.", +) +@click.option( + "--extra-files", + default=None, + type=SeparatedPathType(), + help=( + "Extra files that trigger a reload on change. Multiple paths" + f" are separated by {os.path.pathsep!r}." + ), +) +@click.option( + "--exclude-patterns", + default=None, + type=SeparatedPathType(), + help=( + "Files matching these fnmatch patterns will not trigger a reload" + " on change. Multiple patterns are separated by" + f" {os.path.pathsep!r}." + ), +) +@pass_script_info +def run_command( + info, + host, + port, + reload, + debugger, + with_threads, + cert, + extra_files, + exclude_patterns, +): + """Run a local development server. + + This server is for development purposes only. It does not provide + the stability, security, or performance of production WSGI servers. + + The reloader and debugger are enabled by default with the '--debug' + option. + """ + try: + app = info.load_app() + except Exception as e: + if is_running_from_reloader(): + # When reloading, print out the error immediately, but raise + # it later so the debugger or server can handle it. + traceback.print_exc() + err = e + + def app(environ, start_response): + raise err from None + + else: + # When not reloading, raise the error immediately so the + # command fails. + raise e from None + + debug = get_debug_flag() + + if reload is None: + reload = debug + + if debugger is None: + debugger = debug + + show_server_banner(debug, info.app_import_path) + + run_simple( + host, + port, + app, + use_reloader=reload, + use_debugger=debugger, + threaded=with_threads, + ssl_context=cert, + extra_files=extra_files, + exclude_patterns=exclude_patterns, + ) + + +run_command.params.insert(0, _debug_option) + + +@click.command("shell", short_help="Run a shell in the app context.") +@with_appcontext +def shell_command() -> None: + """Run an interactive Python shell in the context of a given + Flask application. The application will populate the default + namespace of this shell according to its configuration. + + This is useful for executing small snippets of management code + without having to manually configure the application. + """ + import code + + banner = ( + f"Python {sys.version} on {sys.platform}\n" + f"App: {current_app.import_name}\n" + f"Instance: {current_app.instance_path}" + ) + ctx: dict = {} + + # Support the regular Python interpreter startup script if someone + # is using it. + startup = os.environ.get("PYTHONSTARTUP") + if startup and os.path.isfile(startup): + with open(startup) as f: + eval(compile(f.read(), startup, "exec"), ctx) + + ctx.update(current_app.make_shell_context()) + + # Site, customize, or startup script can set a hook to call when + # entering interactive mode. The default one sets up readline with + # tab and history completion. + interactive_hook = getattr(sys, "__interactivehook__", None) + + if interactive_hook is not None: + try: + import readline + from rlcompleter import Completer + except ImportError: + pass + else: + # rlcompleter uses __main__.__dict__ by default, which is + # flask.__main__. Use the shell context instead. + readline.set_completer(Completer(ctx).complete) + + interactive_hook() + + code.interact(banner=banner, local=ctx) + + +@click.command("routes", short_help="Show the routes for the app.") +@click.option( + "--sort", + "-s", + type=click.Choice(("endpoint", "methods", "domain", "rule", "match")), + default="endpoint", + help=( + "Method to sort routes by. 'match' is the order that Flask will match routes" + " when dispatching a request." + ), +) +@click.option("--all-methods", is_flag=True, help="Show HEAD and OPTIONS methods.") +@with_appcontext +def routes_command(sort: str, all_methods: bool) -> None: + """Show all registered routes with endpoints and methods.""" + rules = list(current_app.url_map.iter_rules()) + + if not rules: + click.echo("No routes were registered.") + return + + ignored_methods = set() if all_methods else {"HEAD", "OPTIONS"} + host_matching = current_app.url_map.host_matching + has_domain = any(rule.host if host_matching else rule.subdomain for rule in rules) + rows = [] + + for rule in rules: + row = [ + rule.endpoint, + ", ".join(sorted((rule.methods or set()) - ignored_methods)), + ] + + if has_domain: + row.append((rule.host if host_matching else rule.subdomain) or "") + + row.append(rule.rule) + rows.append(row) + + headers = ["Endpoint", "Methods"] + sorts = ["endpoint", "methods"] + + if has_domain: + headers.append("Host" if host_matching else "Subdomain") + sorts.append("domain") + + headers.append("Rule") + sorts.append("rule") + + try: + rows.sort(key=itemgetter(sorts.index(sort))) + except ValueError: + pass + + rows.insert(0, headers) + widths = [max(len(row[i]) for row in rows) for i in range(len(headers))] + rows.insert(1, ["-" * w for w in widths]) + template = " ".join(f"{{{i}:<{w}}}" for i, w in enumerate(widths)) + + for row in rows: + click.echo(template.format(*row)) + + +cli = FlaskGroup( + name="flask", + help="""\ +A general utility script for Flask applications. + +An application to load must be given with the '--app' option, +'FLASK_APP' environment variable, or with a 'wsgi.py' or 'app.py' file +in the current directory. +""", +) + + +def main() -> None: + cli.main() + + +if __name__ == "__main__": + main() diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/config.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/config.py new file mode 100644 index 0000000..5f921b4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/config.py @@ -0,0 +1,347 @@ +from __future__ import annotations + +import errno +import json +import os +import types +import typing as t + +from werkzeug.utils import import_string + + +class ConfigAttribute: + """Makes an attribute forward to the config""" + + def __init__(self, name: str, get_converter: t.Callable | None = None) -> None: + self.__name__ = name + self.get_converter = get_converter + + def __get__(self, obj: t.Any, owner: t.Any = None) -> t.Any: + if obj is None: + return self + rv = obj.config[self.__name__] + if self.get_converter is not None: + rv = self.get_converter(rv) + return rv + + def __set__(self, obj: t.Any, value: t.Any) -> None: + obj.config[self.__name__] = value + + +class Config(dict): + """Works exactly like a dict but provides ways to fill it from files + or special dictionaries. There are two common patterns to populate the + config. + + Either you can fill the config from a config file:: + + app.config.from_pyfile('yourconfig.cfg') + + Or alternatively you can define the configuration options in the + module that calls :meth:`from_object` or provide an import path to + a module that should be loaded. It is also possible to tell it to + use the same module and with that provide the configuration values + just before the call:: + + DEBUG = True + SECRET_KEY = 'development key' + app.config.from_object(__name__) + + In both cases (loading from any Python file or loading from modules), + only uppercase keys are added to the config. This makes it possible to use + lowercase values in the config file for temporary values that are not added + to the config or to define the config keys in the same file that implements + the application. + + Probably the most interesting way to load configurations is from an + environment variable pointing to a file:: + + app.config.from_envvar('YOURAPPLICATION_SETTINGS') + + In this case before launching the application you have to set this + environment variable to the file you want to use. On Linux and OS X + use the export statement:: + + export YOURAPPLICATION_SETTINGS='/path/to/config/file' + + On windows use `set` instead. + + :param root_path: path to which files are read relative from. When the + config object is created by the application, this is + the application's :attr:`~flask.Flask.root_path`. + :param defaults: an optional dictionary of default values + """ + + def __init__( + self, root_path: str | os.PathLike, defaults: dict | None = None + ) -> None: + super().__init__(defaults or {}) + self.root_path = root_path + + def from_envvar(self, variable_name: str, silent: bool = False) -> bool: + """Loads a configuration from an environment variable pointing to + a configuration file. This is basically just a shortcut with nicer + error messages for this line of code:: + + app.config.from_pyfile(os.environ['YOURAPPLICATION_SETTINGS']) + + :param variable_name: name of the environment variable + :param silent: set to ``True`` if you want silent failure for missing + files. + :return: ``True`` if the file was loaded successfully. + """ + rv = os.environ.get(variable_name) + if not rv: + if silent: + return False + raise RuntimeError( + f"The environment variable {variable_name!r} is not set" + " and as such configuration could not be loaded. Set" + " this variable and make it point to a configuration" + " file" + ) + return self.from_pyfile(rv, silent=silent) + + def from_prefixed_env( + self, prefix: str = "FLASK", *, loads: t.Callable[[str], t.Any] = json.loads + ) -> bool: + """Load any environment variables that start with ``FLASK_``, + dropping the prefix from the env key for the config key. Values + are passed through a loading function to attempt to convert them + to more specific types than strings. + + Keys are loaded in :func:`sorted` order. + + The default loading function attempts to parse values as any + valid JSON type, including dicts and lists. + + Specific items in nested dicts can be set by separating the + keys with double underscores (``__``). If an intermediate key + doesn't exist, it will be initialized to an empty dict. + + :param prefix: Load env vars that start with this prefix, + separated with an underscore (``_``). + :param loads: Pass each string value to this function and use + the returned value as the config value. If any error is + raised it is ignored and the value remains a string. The + default is :func:`json.loads`. + + .. versionadded:: 2.1 + """ + prefix = f"{prefix}_" + len_prefix = len(prefix) + + for key in sorted(os.environ): + if not key.startswith(prefix): + continue + + value = os.environ[key] + + try: + value = loads(value) + except Exception: + # Keep the value as a string if loading failed. + pass + + # Change to key.removeprefix(prefix) on Python >= 3.9. + key = key[len_prefix:] + + if "__" not in key: + # A non-nested key, set directly. + self[key] = value + continue + + # Traverse nested dictionaries with keys separated by "__". + current = self + *parts, tail = key.split("__") + + for part in parts: + # If an intermediate dict does not exist, create it. + if part not in current: + current[part] = {} + + current = current[part] + + current[tail] = value + + return True + + def from_pyfile(self, filename: str | os.PathLike, silent: bool = False) -> bool: + """Updates the values in the config from a Python file. This function + behaves as if the file was imported as module with the + :meth:`from_object` function. + + :param filename: the filename of the config. This can either be an + absolute filename or a filename relative to the + root path. + :param silent: set to ``True`` if you want silent failure for missing + files. + :return: ``True`` if the file was loaded successfully. + + .. versionadded:: 0.7 + `silent` parameter. + """ + filename = os.path.join(self.root_path, filename) + d = types.ModuleType("config") + d.__file__ = filename + try: + with open(filename, mode="rb") as config_file: + exec(compile(config_file.read(), filename, "exec"), d.__dict__) + except OSError as e: + if silent and e.errno in (errno.ENOENT, errno.EISDIR, errno.ENOTDIR): + return False + e.strerror = f"Unable to load configuration file ({e.strerror})" + raise + self.from_object(d) + return True + + def from_object(self, obj: object | str) -> None: + """Updates the values from the given object. An object can be of one + of the following two types: + + - a string: in this case the object with that name will be imported + - an actual object reference: that object is used directly + + Objects are usually either modules or classes. :meth:`from_object` + loads only the uppercase attributes of the module/class. A ``dict`` + object will not work with :meth:`from_object` because the keys of a + ``dict`` are not attributes of the ``dict`` class. + + Example of module-based configuration:: + + app.config.from_object('yourapplication.default_config') + from yourapplication import default_config + app.config.from_object(default_config) + + Nothing is done to the object before loading. If the object is a + class and has ``@property`` attributes, it needs to be + instantiated before being passed to this method. + + You should not use this function to load the actual configuration but + rather configuration defaults. The actual config should be loaded + with :meth:`from_pyfile` and ideally from a location not within the + package because the package might be installed system wide. + + See :ref:`config-dev-prod` for an example of class-based configuration + using :meth:`from_object`. + + :param obj: an import name or object + """ + if isinstance(obj, str): + obj = import_string(obj) + for key in dir(obj): + if key.isupper(): + self[key] = getattr(obj, key) + + def from_file( + self, + filename: str | os.PathLike, + load: t.Callable[[t.IO[t.Any]], t.Mapping], + silent: bool = False, + text: bool = True, + ) -> bool: + """Update the values in the config from a file that is loaded + using the ``load`` parameter. The loaded data is passed to the + :meth:`from_mapping` method. + + .. code-block:: python + + import json + app.config.from_file("config.json", load=json.load) + + import tomllib + app.config.from_file("config.toml", load=tomllib.load, text=False) + + :param filename: The path to the data file. This can be an + absolute path or relative to the config root path. + :param load: A callable that takes a file handle and returns a + mapping of loaded data from the file. + :type load: ``Callable[[Reader], Mapping]`` where ``Reader`` + implements a ``read`` method. + :param silent: Ignore the file if it doesn't exist. + :param text: Open the file in text or binary mode. + :return: ``True`` if the file was loaded successfully. + + .. versionchanged:: 2.3 + The ``text`` parameter was added. + + .. versionadded:: 2.0 + """ + filename = os.path.join(self.root_path, filename) + + try: + with open(filename, "r" if text else "rb") as f: + obj = load(f) + except OSError as e: + if silent and e.errno in (errno.ENOENT, errno.EISDIR): + return False + + e.strerror = f"Unable to load configuration file ({e.strerror})" + raise + + return self.from_mapping(obj) + + def from_mapping( + self, mapping: t.Mapping[str, t.Any] | None = None, **kwargs: t.Any + ) -> bool: + """Updates the config like :meth:`update` ignoring items with + non-upper keys. + + :return: Always returns ``True``. + + .. versionadded:: 0.11 + """ + mappings: dict[str, t.Any] = {} + if mapping is not None: + mappings.update(mapping) + mappings.update(kwargs) + for key, value in mappings.items(): + if key.isupper(): + self[key] = value + return True + + def get_namespace( + self, namespace: str, lowercase: bool = True, trim_namespace: bool = True + ) -> dict[str, t.Any]: + """Returns a dictionary containing a subset of configuration options + that match the specified namespace/prefix. Example usage:: + + app.config['IMAGE_STORE_TYPE'] = 'fs' + app.config['IMAGE_STORE_PATH'] = '/var/app/images' + app.config['IMAGE_STORE_BASE_URL'] = 'http://img.website.com' + image_store_config = app.config.get_namespace('IMAGE_STORE_') + + The resulting dictionary `image_store_config` would look like:: + + { + 'type': 'fs', + 'path': '/var/app/images', + 'base_url': 'http://img.website.com' + } + + This is often useful when configuration options map directly to + keyword arguments in functions or class constructors. + + :param namespace: a configuration namespace + :param lowercase: a flag indicating if the keys of the resulting + dictionary should be lowercase + :param trim_namespace: a flag indicating if the keys of the resulting + dictionary should not include the namespace + + .. versionadded:: 0.11 + """ + rv = {} + for k, v in self.items(): + if not k.startswith(namespace): + continue + if trim_namespace: + key = k[len(namespace) :] + else: + key = k + if lowercase: + key = key.lower() + rv[key] = v + return rv + + def __repr__(self) -> str: + return f"<{type(self).__name__} {dict.__repr__(self)}>" diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/ctx.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/ctx.py new file mode 100644 index 0000000..b37e4e0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/ctx.py @@ -0,0 +1,440 @@ +from __future__ import annotations + +import contextvars +import sys +import typing as t +from functools import update_wrapper +from types import TracebackType + +from werkzeug.exceptions import HTTPException + +from . import typing as ft +from .globals import _cv_app +from .globals import _cv_request +from .signals import appcontext_popped +from .signals import appcontext_pushed + +if t.TYPE_CHECKING: # pragma: no cover + from .app import Flask + from .sessions import SessionMixin + from .wrappers import Request + + +# a singleton sentinel value for parameter defaults +_sentinel = object() + + +class _AppCtxGlobals: + """A plain object. Used as a namespace for storing data during an + application context. + + Creating an app context automatically creates this object, which is + made available as the :data:`g` proxy. + + .. describe:: 'key' in g + + Check whether an attribute is present. + + .. versionadded:: 0.10 + + .. describe:: iter(g) + + Return an iterator over the attribute names. + + .. versionadded:: 0.10 + """ + + # Define attr methods to let mypy know this is a namespace object + # that has arbitrary attributes. + + def __getattr__(self, name: str) -> t.Any: + try: + return self.__dict__[name] + except KeyError: + raise AttributeError(name) from None + + def __setattr__(self, name: str, value: t.Any) -> None: + self.__dict__[name] = value + + def __delattr__(self, name: str) -> None: + try: + del self.__dict__[name] + except KeyError: + raise AttributeError(name) from None + + def get(self, name: str, default: t.Any | None = None) -> t.Any: + """Get an attribute by name, or a default value. Like + :meth:`dict.get`. + + :param name: Name of attribute to get. + :param default: Value to return if the attribute is not present. + + .. versionadded:: 0.10 + """ + return self.__dict__.get(name, default) + + def pop(self, name: str, default: t.Any = _sentinel) -> t.Any: + """Get and remove an attribute by name. Like :meth:`dict.pop`. + + :param name: Name of attribute to pop. + :param default: Value to return if the attribute is not present, + instead of raising a ``KeyError``. + + .. versionadded:: 0.11 + """ + if default is _sentinel: + return self.__dict__.pop(name) + else: + return self.__dict__.pop(name, default) + + def setdefault(self, name: str, default: t.Any = None) -> t.Any: + """Get the value of an attribute if it is present, otherwise + set and return a default value. Like :meth:`dict.setdefault`. + + :param name: Name of attribute to get. + :param default: Value to set and return if the attribute is not + present. + + .. versionadded:: 0.11 + """ + return self.__dict__.setdefault(name, default) + + def __contains__(self, item: str) -> bool: + return item in self.__dict__ + + def __iter__(self) -> t.Iterator[str]: + return iter(self.__dict__) + + def __repr__(self) -> str: + ctx = _cv_app.get(None) + if ctx is not None: + return f"" + return object.__repr__(self) + + +def after_this_request(f: ft.AfterRequestCallable) -> ft.AfterRequestCallable: + """Executes a function after this request. This is useful to modify + response objects. The function is passed the response object and has + to return the same or a new one. + + Example:: + + @app.route('/') + def index(): + @after_this_request + def add_header(response): + response.headers['X-Foo'] = 'Parachute' + return response + return 'Hello World!' + + This is more useful if a function other than the view function wants to + modify a response. For instance think of a decorator that wants to add + some headers without converting the return value into a response object. + + .. versionadded:: 0.9 + """ + ctx = _cv_request.get(None) + + if ctx is None: + raise RuntimeError( + "'after_this_request' can only be used when a request" + " context is active, such as in a view function." + ) + + ctx._after_request_functions.append(f) + return f + + +def copy_current_request_context(f: t.Callable) -> t.Callable: + """A helper function that decorates a function to retain the current + request context. This is useful when working with greenlets. The moment + the function is decorated a copy of the request context is created and + then pushed when the function is called. The current session is also + included in the copied request context. + + Example:: + + import gevent + from flask import copy_current_request_context + + @app.route('/') + def index(): + @copy_current_request_context + def do_some_work(): + # do some work here, it can access flask.request or + # flask.session like you would otherwise in the view function. + ... + gevent.spawn(do_some_work) + return 'Regular response' + + .. versionadded:: 0.10 + """ + ctx = _cv_request.get(None) + + if ctx is None: + raise RuntimeError( + "'copy_current_request_context' can only be used when a" + " request context is active, such as in a view function." + ) + + ctx = ctx.copy() + + def wrapper(*args, **kwargs): + with ctx: + return ctx.app.ensure_sync(f)(*args, **kwargs) + + return update_wrapper(wrapper, f) + + +def has_request_context() -> bool: + """If you have code that wants to test if a request context is there or + not this function can be used. For instance, you may want to take advantage + of request information if the request object is available, but fail + silently if it is unavailable. + + :: + + class User(db.Model): + + def __init__(self, username, remote_addr=None): + self.username = username + if remote_addr is None and has_request_context(): + remote_addr = request.remote_addr + self.remote_addr = remote_addr + + Alternatively you can also just test any of the context bound objects + (such as :class:`request` or :class:`g`) for truthness:: + + class User(db.Model): + + def __init__(self, username, remote_addr=None): + self.username = username + if remote_addr is None and request: + remote_addr = request.remote_addr + self.remote_addr = remote_addr + + .. versionadded:: 0.7 + """ + return _cv_request.get(None) is not None + + +def has_app_context() -> bool: + """Works like :func:`has_request_context` but for the application + context. You can also just do a boolean check on the + :data:`current_app` object instead. + + .. versionadded:: 0.9 + """ + return _cv_app.get(None) is not None + + +class AppContext: + """The app context contains application-specific information. An app + context is created and pushed at the beginning of each request if + one is not already active. An app context is also pushed when + running CLI commands. + """ + + def __init__(self, app: Flask) -> None: + self.app = app + self.url_adapter = app.create_url_adapter(None) + self.g: _AppCtxGlobals = app.app_ctx_globals_class() + self._cv_tokens: list[contextvars.Token] = [] + + def push(self) -> None: + """Binds the app context to the current context.""" + self._cv_tokens.append(_cv_app.set(self)) + appcontext_pushed.send(self.app, _async_wrapper=self.app.ensure_sync) + + def pop(self, exc: BaseException | None = _sentinel) -> None: # type: ignore + """Pops the app context.""" + try: + if len(self._cv_tokens) == 1: + if exc is _sentinel: + exc = sys.exc_info()[1] + self.app.do_teardown_appcontext(exc) + finally: + ctx = _cv_app.get() + _cv_app.reset(self._cv_tokens.pop()) + + if ctx is not self: + raise AssertionError( + f"Popped wrong app context. ({ctx!r} instead of {self!r})" + ) + + appcontext_popped.send(self.app, _async_wrapper=self.app.ensure_sync) + + def __enter__(self) -> AppContext: + self.push() + return self + + def __exit__( + self, + exc_type: type | None, + exc_value: BaseException | None, + tb: TracebackType | None, + ) -> None: + self.pop(exc_value) + + +class RequestContext: + """The request context contains per-request information. The Flask + app creates and pushes it at the beginning of the request, then pops + it at the end of the request. It will create the URL adapter and + request object for the WSGI environment provided. + + Do not attempt to use this class directly, instead use + :meth:`~flask.Flask.test_request_context` and + :meth:`~flask.Flask.request_context` to create this object. + + When the request context is popped, it will evaluate all the + functions registered on the application for teardown execution + (:meth:`~flask.Flask.teardown_request`). + + The request context is automatically popped at the end of the + request. When using the interactive debugger, the context will be + restored so ``request`` is still accessible. Similarly, the test + client can preserve the context after the request ends. However, + teardown functions may already have closed some resources such as + database connections. + """ + + def __init__( + self, + app: Flask, + environ: dict, + request: Request | None = None, + session: SessionMixin | None = None, + ) -> None: + self.app = app + if request is None: + request = app.request_class(environ) + request.json_module = app.json + self.request: Request = request + self.url_adapter = None + try: + self.url_adapter = app.create_url_adapter(self.request) + except HTTPException as e: + self.request.routing_exception = e + self.flashes: list[tuple[str, str]] | None = None + self.session: SessionMixin | None = session + # Functions that should be executed after the request on the response + # object. These will be called before the regular "after_request" + # functions. + self._after_request_functions: list[ft.AfterRequestCallable] = [] + + self._cv_tokens: list[tuple[contextvars.Token, AppContext | None]] = [] + + def copy(self) -> RequestContext: + """Creates a copy of this request context with the same request object. + This can be used to move a request context to a different greenlet. + Because the actual request object is the same this cannot be used to + move a request context to a different thread unless access to the + request object is locked. + + .. versionadded:: 0.10 + + .. versionchanged:: 1.1 + The current session object is used instead of reloading the original + data. This prevents `flask.session` pointing to an out-of-date object. + """ + return self.__class__( + self.app, + environ=self.request.environ, + request=self.request, + session=self.session, + ) + + def match_request(self) -> None: + """Can be overridden by a subclass to hook into the matching + of the request. + """ + try: + result = self.url_adapter.match(return_rule=True) # type: ignore + self.request.url_rule, self.request.view_args = result # type: ignore + except HTTPException as e: + self.request.routing_exception = e + + def push(self) -> None: + # Before we push the request context we have to ensure that there + # is an application context. + app_ctx = _cv_app.get(None) + + if app_ctx is None or app_ctx.app is not self.app: + app_ctx = self.app.app_context() + app_ctx.push() + else: + app_ctx = None + + self._cv_tokens.append((_cv_request.set(self), app_ctx)) + + # Open the session at the moment that the request context is available. + # This allows a custom open_session method to use the request context. + # Only open a new session if this is the first time the request was + # pushed, otherwise stream_with_context loses the session. + if self.session is None: + session_interface = self.app.session_interface + self.session = session_interface.open_session(self.app, self.request) + + if self.session is None: + self.session = session_interface.make_null_session(self.app) + + # Match the request URL after loading the session, so that the + # session is available in custom URL converters. + if self.url_adapter is not None: + self.match_request() + + def pop(self, exc: BaseException | None = _sentinel) -> None: # type: ignore + """Pops the request context and unbinds it by doing that. This will + also trigger the execution of functions registered by the + :meth:`~flask.Flask.teardown_request` decorator. + + .. versionchanged:: 0.9 + Added the `exc` argument. + """ + clear_request = len(self._cv_tokens) == 1 + + try: + if clear_request: + if exc is _sentinel: + exc = sys.exc_info()[1] + self.app.do_teardown_request(exc) + + request_close = getattr(self.request, "close", None) + if request_close is not None: + request_close() + finally: + ctx = _cv_request.get() + token, app_ctx = self._cv_tokens.pop() + _cv_request.reset(token) + + # get rid of circular dependencies at the end of the request + # so that we don't require the GC to be active. + if clear_request: + ctx.request.environ["werkzeug.request"] = None + + if app_ctx is not None: + app_ctx.pop(exc) + + if ctx is not self: + raise AssertionError( + f"Popped wrong request context. ({ctx!r} instead of {self!r})" + ) + + def __enter__(self) -> RequestContext: + self.push() + return self + + def __exit__( + self, + exc_type: type | None, + exc_value: BaseException | None, + tb: TracebackType | None, + ) -> None: + self.pop(exc_value) + + def __repr__(self) -> str: + return ( + f"<{type(self).__name__} {self.request.url!r}" + f" [{self.request.method}] of {self.app.name}>" + ) diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/debughelpers.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/debughelpers.py new file mode 100644 index 0000000..e836004 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/debughelpers.py @@ -0,0 +1,160 @@ +from __future__ import annotations + +import typing as t + +from .blueprints import Blueprint +from .globals import request_ctx +from .sansio.app import App + + +class UnexpectedUnicodeError(AssertionError, UnicodeError): + """Raised in places where we want some better error reporting for + unexpected unicode or binary data. + """ + + +class DebugFilesKeyError(KeyError, AssertionError): + """Raised from request.files during debugging. The idea is that it can + provide a better error message than just a generic KeyError/BadRequest. + """ + + def __init__(self, request, key): + form_matches = request.form.getlist(key) + buf = [ + f"You tried to access the file {key!r} in the request.files" + " dictionary but it does not exist. The mimetype for the" + f" request is {request.mimetype!r} instead of" + " 'multipart/form-data' which means that no file contents" + " were transmitted. To fix this error you should provide" + ' enctype="multipart/form-data" in your form.' + ] + if form_matches: + names = ", ".join(repr(x) for x in form_matches) + buf.append( + "\n\nThe browser instead transmitted some file names. " + f"This was submitted: {names}" + ) + self.msg = "".join(buf) + + def __str__(self): + return self.msg + + +class FormDataRoutingRedirect(AssertionError): + """This exception is raised in debug mode if a routing redirect + would cause the browser to drop the method or body. This happens + when method is not GET, HEAD or OPTIONS and the status code is not + 307 or 308. + """ + + def __init__(self, request): + exc = request.routing_exception + buf = [ + f"A request was sent to '{request.url}', but routing issued" + f" a redirect to the canonical URL '{exc.new_url}'." + ] + + if f"{request.base_url}/" == exc.new_url.partition("?")[0]: + buf.append( + " The URL was defined with a trailing slash. Flask" + " will redirect to the URL with a trailing slash if it" + " was accessed without one." + ) + + buf.append( + " Send requests to the canonical URL, or use 307 or 308 for" + " routing redirects. Otherwise, browsers will drop form" + " data.\n\n" + "This exception is only raised in debug mode." + ) + super().__init__("".join(buf)) + + +def attach_enctype_error_multidict(request): + """Patch ``request.files.__getitem__`` to raise a descriptive error + about ``enctype=multipart/form-data``. + + :param request: The request to patch. + :meta private: + """ + oldcls = request.files.__class__ + + class newcls(oldcls): + def __getitem__(self, key): + try: + return super().__getitem__(key) + except KeyError as e: + if key not in request.form: + raise + + raise DebugFilesKeyError(request, key).with_traceback( + e.__traceback__ + ) from None + + newcls.__name__ = oldcls.__name__ + newcls.__module__ = oldcls.__module__ + request.files.__class__ = newcls + + +def _dump_loader_info(loader) -> t.Generator: + yield f"class: {type(loader).__module__}.{type(loader).__name__}" + for key, value in sorted(loader.__dict__.items()): + if key.startswith("_"): + continue + if isinstance(value, (tuple, list)): + if not all(isinstance(x, str) for x in value): + continue + yield f"{key}:" + for item in value: + yield f" - {item}" + continue + elif not isinstance(value, (str, int, float, bool)): + continue + yield f"{key}: {value!r}" + + +def explain_template_loading_attempts(app: App, template, attempts) -> None: + """This should help developers understand what failed""" + info = [f"Locating template {template!r}:"] + total_found = 0 + blueprint = None + if request_ctx and request_ctx.request.blueprint is not None: + blueprint = request_ctx.request.blueprint + + for idx, (loader, srcobj, triple) in enumerate(attempts): + if isinstance(srcobj, App): + src_info = f"application {srcobj.import_name!r}" + elif isinstance(srcobj, Blueprint): + src_info = f"blueprint {srcobj.name!r} ({srcobj.import_name})" + else: + src_info = repr(srcobj) + + info.append(f"{idx + 1:5}: trying loader of {src_info}") + + for line in _dump_loader_info(loader): + info.append(f" {line}") + + if triple is None: + detail = "no match" + else: + detail = f"found ({triple[1] or ''!r})" + total_found += 1 + info.append(f" -> {detail}") + + seems_fishy = False + if total_found == 0: + info.append("Error: the template could not be found.") + seems_fishy = True + elif total_found > 1: + info.append("Warning: multiple loaders returned a match for the template.") + seems_fishy = True + + if blueprint is not None and seems_fishy: + info.append( + " The template was looked up from an endpoint that belongs" + f" to the blueprint {blueprint!r}." + ) + info.append(" Maybe you did not place a template in the right folder?") + info.append(" See https://flask.palletsprojects.com/blueprints/#templates") + + app.logger.info("\n".join(info)) diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/globals.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/globals.py new file mode 100644 index 0000000..e2c410c --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/globals.py @@ -0,0 +1,51 @@ +from __future__ import annotations + +import typing as t +from contextvars import ContextVar + +from werkzeug.local import LocalProxy + +if t.TYPE_CHECKING: # pragma: no cover + from .app import Flask + from .ctx import _AppCtxGlobals + from .ctx import AppContext + from .ctx import RequestContext + from .sessions import SessionMixin + from .wrappers import Request + + +_no_app_msg = """\ +Working outside of application context. + +This typically means that you attempted to use functionality that needed +the current application. To solve this, set up an application context +with app.app_context(). See the documentation for more information.\ +""" +_cv_app: ContextVar[AppContext] = ContextVar("flask.app_ctx") +app_ctx: AppContext = LocalProxy( # type: ignore[assignment] + _cv_app, unbound_message=_no_app_msg +) +current_app: Flask = LocalProxy( # type: ignore[assignment] + _cv_app, "app", unbound_message=_no_app_msg +) +g: _AppCtxGlobals = LocalProxy( # type: ignore[assignment] + _cv_app, "g", unbound_message=_no_app_msg +) + +_no_req_msg = """\ +Working outside of request context. + +This typically means that you attempted to use functionality that needed +an active HTTP request. Consult the documentation on testing for +information about how to avoid this problem.\ +""" +_cv_request: ContextVar[RequestContext] = ContextVar("flask.request_ctx") +request_ctx: RequestContext = LocalProxy( # type: ignore[assignment] + _cv_request, unbound_message=_no_req_msg +) +request: Request = LocalProxy( # type: ignore[assignment] + _cv_request, "request", unbound_message=_no_req_msg +) +session: SessionMixin = LocalProxy( # type: ignore[assignment] + _cv_request, "session", unbound_message=_no_req_msg +) diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/helpers.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/helpers.py new file mode 100644 index 0000000..13a5aa2 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/helpers.py @@ -0,0 +1,623 @@ +from __future__ import annotations + +import importlib.util +import os +import sys +import typing as t +from datetime import datetime +from functools import lru_cache +from functools import update_wrapper + +import werkzeug.utils +from werkzeug.exceptions import abort as _wz_abort +from werkzeug.utils import redirect as _wz_redirect + +from .globals import _cv_request +from .globals import current_app +from .globals import request +from .globals import request_ctx +from .globals import session +from .signals import message_flashed + +if t.TYPE_CHECKING: # pragma: no cover + from werkzeug.wrappers import Response as BaseResponse + from .wrappers import Response + + +def get_debug_flag() -> bool: + """Get whether debug mode should be enabled for the app, indicated by the + :envvar:`FLASK_DEBUG` environment variable. The default is ``False``. + """ + val = os.environ.get("FLASK_DEBUG") + return bool(val and val.lower() not in {"0", "false", "no"}) + + +def get_load_dotenv(default: bool = True) -> bool: + """Get whether the user has disabled loading default dotenv files by + setting :envvar:`FLASK_SKIP_DOTENV`. The default is ``True``, load + the files. + + :param default: What to return if the env var isn't set. + """ + val = os.environ.get("FLASK_SKIP_DOTENV") + + if not val: + return default + + return val.lower() in ("0", "false", "no") + + +def stream_with_context( + generator_or_function: ( + t.Iterator[t.AnyStr] | t.Callable[..., t.Iterator[t.AnyStr]] + ) +) -> t.Iterator[t.AnyStr]: + """Request contexts disappear when the response is started on the server. + This is done for efficiency reasons and to make it less likely to encounter + memory leaks with badly written WSGI middlewares. The downside is that if + you are using streamed responses, the generator cannot access request bound + information any more. + + This function however can help you keep the context around for longer:: + + from flask import stream_with_context, request, Response + + @app.route('/stream') + def streamed_response(): + @stream_with_context + def generate(): + yield 'Hello ' + yield request.args['name'] + yield '!' + return Response(generate()) + + Alternatively it can also be used around a specific generator:: + + from flask import stream_with_context, request, Response + + @app.route('/stream') + def streamed_response(): + def generate(): + yield 'Hello ' + yield request.args['name'] + yield '!' + return Response(stream_with_context(generate())) + + .. versionadded:: 0.9 + """ + try: + gen = iter(generator_or_function) # type: ignore + except TypeError: + + def decorator(*args: t.Any, **kwargs: t.Any) -> t.Any: + gen = generator_or_function(*args, **kwargs) # type: ignore + return stream_with_context(gen) + + return update_wrapper(decorator, generator_or_function) # type: ignore + + def generator() -> t.Generator: + ctx = _cv_request.get(None) + if ctx is None: + raise RuntimeError( + "'stream_with_context' can only be used when a request" + " context is active, such as in a view function." + ) + with ctx: + # Dummy sentinel. Has to be inside the context block or we're + # not actually keeping the context around. + yield None + + # The try/finally is here so that if someone passes a WSGI level + # iterator in we're still running the cleanup logic. Generators + # don't need that because they are closed on their destruction + # automatically. + try: + yield from gen + finally: + if hasattr(gen, "close"): + gen.close() + + # The trick is to start the generator. Then the code execution runs until + # the first dummy None is yielded at which point the context was already + # pushed. This item is discarded. Then when the iteration continues the + # real generator is executed. + wrapped_g = generator() + next(wrapped_g) + return wrapped_g + + +def make_response(*args: t.Any) -> Response: + """Sometimes it is necessary to set additional headers in a view. Because + views do not have to return response objects but can return a value that + is converted into a response object by Flask itself, it becomes tricky to + add headers to it. This function can be called instead of using a return + and you will get a response object which you can use to attach headers. + + If view looked like this and you want to add a new header:: + + def index(): + return render_template('index.html', foo=42) + + You can now do something like this:: + + def index(): + response = make_response(render_template('index.html', foo=42)) + response.headers['X-Parachutes'] = 'parachutes are cool' + return response + + This function accepts the very same arguments you can return from a + view function. This for example creates a response with a 404 error + code:: + + response = make_response(render_template('not_found.html'), 404) + + The other use case of this function is to force the return value of a + view function into a response which is helpful with view + decorators:: + + response = make_response(view_function()) + response.headers['X-Parachutes'] = 'parachutes are cool' + + Internally this function does the following things: + + - if no arguments are passed, it creates a new response argument + - if one argument is passed, :meth:`flask.Flask.make_response` + is invoked with it. + - if more than one argument is passed, the arguments are passed + to the :meth:`flask.Flask.make_response` function as tuple. + + .. versionadded:: 0.6 + """ + if not args: + return current_app.response_class() + if len(args) == 1: + args = args[0] + return current_app.make_response(args) # type: ignore + + +def url_for( + endpoint: str, + *, + _anchor: str | None = None, + _method: str | None = None, + _scheme: str | None = None, + _external: bool | None = None, + **values: t.Any, +) -> str: + """Generate a URL to the given endpoint with the given values. + + This requires an active request or application context, and calls + :meth:`current_app.url_for() `. See that method + for full documentation. + + :param endpoint: The endpoint name associated with the URL to + generate. If this starts with a ``.``, the current blueprint + name (if any) will be used. + :param _anchor: If given, append this as ``#anchor`` to the URL. + :param _method: If given, generate the URL associated with this + method for the endpoint. + :param _scheme: If given, the URL will have this scheme if it is + external. + :param _external: If given, prefer the URL to be internal (False) or + require it to be external (True). External URLs include the + scheme and domain. When not in an active request, URLs are + external by default. + :param values: Values to use for the variable parts of the URL rule. + Unknown keys are appended as query string arguments, like + ``?a=b&c=d``. + + .. versionchanged:: 2.2 + Calls ``current_app.url_for``, allowing an app to override the + behavior. + + .. versionchanged:: 0.10 + The ``_scheme`` parameter was added. + + .. versionchanged:: 0.9 + The ``_anchor`` and ``_method`` parameters were added. + + .. versionchanged:: 0.9 + Calls ``app.handle_url_build_error`` on build errors. + """ + return current_app.url_for( + endpoint, + _anchor=_anchor, + _method=_method, + _scheme=_scheme, + _external=_external, + **values, + ) + + +def redirect( + location: str, code: int = 302, Response: type[BaseResponse] | None = None +) -> BaseResponse: + """Create a redirect response object. + + If :data:`~flask.current_app` is available, it will use its + :meth:`~flask.Flask.redirect` method, otherwise it will use + :func:`werkzeug.utils.redirect`. + + :param location: The URL to redirect to. + :param code: The status code for the redirect. + :param Response: The response class to use. Not used when + ``current_app`` is active, which uses ``app.response_class``. + + .. versionadded:: 2.2 + Calls ``current_app.redirect`` if available instead of always + using Werkzeug's default ``redirect``. + """ + if current_app: + return current_app.redirect(location, code=code) + + return _wz_redirect(location, code=code, Response=Response) + + +def abort(code: int | BaseResponse, *args: t.Any, **kwargs: t.Any) -> t.NoReturn: + """Raise an :exc:`~werkzeug.exceptions.HTTPException` for the given + status code. + + If :data:`~flask.current_app` is available, it will call its + :attr:`~flask.Flask.aborter` object, otherwise it will use + :func:`werkzeug.exceptions.abort`. + + :param code: The status code for the exception, which must be + registered in ``app.aborter``. + :param args: Passed to the exception. + :param kwargs: Passed to the exception. + + .. versionadded:: 2.2 + Calls ``current_app.aborter`` if available instead of always + using Werkzeug's default ``abort``. + """ + if current_app: + current_app.aborter(code, *args, **kwargs) + + _wz_abort(code, *args, **kwargs) + + +def get_template_attribute(template_name: str, attribute: str) -> t.Any: + """Loads a macro (or variable) a template exports. This can be used to + invoke a macro from within Python code. If you for example have a + template named :file:`_cider.html` with the following contents: + + .. sourcecode:: html+jinja + + {% macro hello(name) %}Hello {{ name }}!{% endmacro %} + + You can access this from Python code like this:: + + hello = get_template_attribute('_cider.html', 'hello') + return hello('World') + + .. versionadded:: 0.2 + + :param template_name: the name of the template + :param attribute: the name of the variable of macro to access + """ + return getattr(current_app.jinja_env.get_template(template_name).module, attribute) + + +def flash(message: str, category: str = "message") -> None: + """Flashes a message to the next request. In order to remove the + flashed message from the session and to display it to the user, + the template has to call :func:`get_flashed_messages`. + + .. versionchanged:: 0.3 + `category` parameter added. + + :param message: the message to be flashed. + :param category: the category for the message. The following values + are recommended: ``'message'`` for any kind of message, + ``'error'`` for errors, ``'info'`` for information + messages and ``'warning'`` for warnings. However any + kind of string can be used as category. + """ + # Original implementation: + # + # session.setdefault('_flashes', []).append((category, message)) + # + # This assumed that changes made to mutable structures in the session are + # always in sync with the session object, which is not true for session + # implementations that use external storage for keeping their keys/values. + flashes = session.get("_flashes", []) + flashes.append((category, message)) + session["_flashes"] = flashes + app = current_app._get_current_object() # type: ignore + message_flashed.send( + app, + _async_wrapper=app.ensure_sync, + message=message, + category=category, + ) + + +def get_flashed_messages( + with_categories: bool = False, category_filter: t.Iterable[str] = () +) -> list[str] | list[tuple[str, str]]: + """Pulls all flashed messages from the session and returns them. + Further calls in the same request to the function will return + the same messages. By default just the messages are returned, + but when `with_categories` is set to ``True``, the return value will + be a list of tuples in the form ``(category, message)`` instead. + + Filter the flashed messages to one or more categories by providing those + categories in `category_filter`. This allows rendering categories in + separate html blocks. The `with_categories` and `category_filter` + arguments are distinct: + + * `with_categories` controls whether categories are returned with message + text (``True`` gives a tuple, where ``False`` gives just the message text). + * `category_filter` filters the messages down to only those matching the + provided categories. + + See :doc:`/patterns/flashing` for examples. + + .. versionchanged:: 0.3 + `with_categories` parameter added. + + .. versionchanged:: 0.9 + `category_filter` parameter added. + + :param with_categories: set to ``True`` to also receive categories. + :param category_filter: filter of categories to limit return values. Only + categories in the list will be returned. + """ + flashes = request_ctx.flashes + if flashes is None: + flashes = session.pop("_flashes") if "_flashes" in session else [] + request_ctx.flashes = flashes + if category_filter: + flashes = list(filter(lambda f: f[0] in category_filter, flashes)) + if not with_categories: + return [x[1] for x in flashes] + return flashes + + +def _prepare_send_file_kwargs(**kwargs: t.Any) -> dict[str, t.Any]: + if kwargs.get("max_age") is None: + kwargs["max_age"] = current_app.get_send_file_max_age + + kwargs.update( + environ=request.environ, + use_x_sendfile=current_app.config["USE_X_SENDFILE"], + response_class=current_app.response_class, + _root_path=current_app.root_path, # type: ignore + ) + return kwargs + + +def send_file( + path_or_file: os.PathLike | str | t.BinaryIO, + mimetype: str | None = None, + as_attachment: bool = False, + download_name: str | None = None, + conditional: bool = True, + etag: bool | str = True, + last_modified: datetime | int | float | None = None, + max_age: None | (int | t.Callable[[str | None], int | None]) = None, +) -> Response: + """Send the contents of a file to the client. + + The first argument can be a file path or a file-like object. Paths + are preferred in most cases because Werkzeug can manage the file and + get extra information from the path. Passing a file-like object + requires that the file is opened in binary mode, and is mostly + useful when building a file in memory with :class:`io.BytesIO`. + + Never pass file paths provided by a user. The path is assumed to be + trusted, so a user could craft a path to access a file you didn't + intend. Use :func:`send_from_directory` to safely serve + user-requested paths from within a directory. + + If the WSGI server sets a ``file_wrapper`` in ``environ``, it is + used, otherwise Werkzeug's built-in wrapper is used. Alternatively, + if the HTTP server supports ``X-Sendfile``, configuring Flask with + ``USE_X_SENDFILE = True`` will tell the server to send the given + path, which is much more efficient than reading it in Python. + + :param path_or_file: The path to the file to send, relative to the + current working directory if a relative path is given. + Alternatively, a file-like object opened in binary mode. Make + sure the file pointer is seeked to the start of the data. + :param mimetype: The MIME type to send for the file. If not + provided, it will try to detect it from the file name. + :param as_attachment: Indicate to a browser that it should offer to + save the file instead of displaying it. + :param download_name: The default name browsers will use when saving + the file. Defaults to the passed file name. + :param conditional: Enable conditional and range responses based on + request headers. Requires passing a file path and ``environ``. + :param etag: Calculate an ETag for the file, which requires passing + a file path. Can also be a string to use instead. + :param last_modified: The last modified time to send for the file, + in seconds. If not provided, it will try to detect it from the + file path. + :param max_age: How long the client should cache the file, in + seconds. If set, ``Cache-Control`` will be ``public``, otherwise + it will be ``no-cache`` to prefer conditional caching. + + .. versionchanged:: 2.0 + ``download_name`` replaces the ``attachment_filename`` + parameter. If ``as_attachment=False``, it is passed with + ``Content-Disposition: inline`` instead. + + .. versionchanged:: 2.0 + ``max_age`` replaces the ``cache_timeout`` parameter. + ``conditional`` is enabled and ``max_age`` is not set by + default. + + .. versionchanged:: 2.0 + ``etag`` replaces the ``add_etags`` parameter. It can be a + string to use instead of generating one. + + .. versionchanged:: 2.0 + Passing a file-like object that inherits from + :class:`~io.TextIOBase` will raise a :exc:`ValueError` rather + than sending an empty file. + + .. versionadded:: 2.0 + Moved the implementation to Werkzeug. This is now a wrapper to + pass some Flask-specific arguments. + + .. versionchanged:: 1.1 + ``filename`` may be a :class:`~os.PathLike` object. + + .. versionchanged:: 1.1 + Passing a :class:`~io.BytesIO` object supports range requests. + + .. versionchanged:: 1.0.3 + Filenames are encoded with ASCII instead of Latin-1 for broader + compatibility with WSGI servers. + + .. versionchanged:: 1.0 + UTF-8 filenames as specified in :rfc:`2231` are supported. + + .. versionchanged:: 0.12 + The filename is no longer automatically inferred from file + objects. If you want to use automatic MIME and etag support, + pass a filename via ``filename_or_fp`` or + ``attachment_filename``. + + .. versionchanged:: 0.12 + ``attachment_filename`` is preferred over ``filename`` for MIME + detection. + + .. versionchanged:: 0.9 + ``cache_timeout`` defaults to + :meth:`Flask.get_send_file_max_age`. + + .. versionchanged:: 0.7 + MIME guessing and etag support for file-like objects was + removed because it was unreliable. Pass a filename if you are + able to, otherwise attach an etag yourself. + + .. versionchanged:: 0.5 + The ``add_etags``, ``cache_timeout`` and ``conditional`` + parameters were added. The default behavior is to add etags. + + .. versionadded:: 0.2 + """ + return werkzeug.utils.send_file( # type: ignore[return-value] + **_prepare_send_file_kwargs( + path_or_file=path_or_file, + environ=request.environ, + mimetype=mimetype, + as_attachment=as_attachment, + download_name=download_name, + conditional=conditional, + etag=etag, + last_modified=last_modified, + max_age=max_age, + ) + ) + + +def send_from_directory( + directory: os.PathLike | str, + path: os.PathLike | str, + **kwargs: t.Any, +) -> Response: + """Send a file from within a directory using :func:`send_file`. + + .. code-block:: python + + @app.route("/uploads/") + def download_file(name): + return send_from_directory( + app.config['UPLOAD_FOLDER'], name, as_attachment=True + ) + + This is a secure way to serve files from a folder, such as static + files or uploads. Uses :func:`~werkzeug.security.safe_join` to + ensure the path coming from the client is not maliciously crafted to + point outside the specified directory. + + If the final path does not point to an existing regular file, + raises a 404 :exc:`~werkzeug.exceptions.NotFound` error. + + :param directory: The directory that ``path`` must be located under, + relative to the current application's root path. + :param path: The path to the file to send, relative to + ``directory``. + :param kwargs: Arguments to pass to :func:`send_file`. + + .. versionchanged:: 2.0 + ``path`` replaces the ``filename`` parameter. + + .. versionadded:: 2.0 + Moved the implementation to Werkzeug. This is now a wrapper to + pass some Flask-specific arguments. + + .. versionadded:: 0.5 + """ + return werkzeug.utils.send_from_directory( # type: ignore[return-value] + directory, path, **_prepare_send_file_kwargs(**kwargs) + ) + + +def get_root_path(import_name: str) -> str: + """Find the root path of a package, or the path that contains a + module. If it cannot be found, returns the current working + directory. + + Not to be confused with the value returned by :func:`find_package`. + + :meta private: + """ + # Module already imported and has a file attribute. Use that first. + mod = sys.modules.get(import_name) + + if mod is not None and hasattr(mod, "__file__") and mod.__file__ is not None: + return os.path.dirname(os.path.abspath(mod.__file__)) + + # Next attempt: check the loader. + try: + spec = importlib.util.find_spec(import_name) + + if spec is None: + raise ValueError + except (ImportError, ValueError): + loader = None + else: + loader = spec.loader + + # Loader does not exist or we're referring to an unloaded main + # module or a main module without path (interactive sessions), go + # with the current working directory. + if loader is None: + return os.getcwd() + + if hasattr(loader, "get_filename"): + filepath = loader.get_filename(import_name) + else: + # Fall back to imports. + __import__(import_name) + mod = sys.modules[import_name] + filepath = getattr(mod, "__file__", None) + + # If we don't have a file path it might be because it is a + # namespace package. In this case pick the root path from the + # first module that is contained in the package. + if filepath is None: + raise RuntimeError( + "No root path can be found for the provided module" + f" {import_name!r}. This can happen because the module" + " came from an import hook that does not provide file" + " name information or because it's a namespace package." + " In this case the root path needs to be explicitly" + " provided." + ) + + # filepath is import_name.py for a module, or __init__.py for a package. + return os.path.dirname(os.path.abspath(filepath)) + + +@lru_cache(maxsize=None) +def _split_blueprint_path(name: str) -> list[str]: + out: list[str] = [name] + + if "." in name: + out.extend(_split_blueprint_path(name.rpartition(".")[0])) + + return out diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/json/__init__.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/json/__init__.py new file mode 100644 index 0000000..f15296f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/json/__init__.py @@ -0,0 +1,170 @@ +from __future__ import annotations + +import json as _json +import typing as t + +from ..globals import current_app +from .provider import _default + +if t.TYPE_CHECKING: # pragma: no cover + from ..wrappers import Response + + +def dumps(obj: t.Any, **kwargs: t.Any) -> str: + """Serialize data as JSON. + + If :data:`~flask.current_app` is available, it will use its + :meth:`app.json.dumps() ` + method, otherwise it will use :func:`json.dumps`. + + :param obj: The data to serialize. + :param kwargs: Arguments passed to the ``dumps`` implementation. + + .. versionchanged:: 2.3 + The ``app`` parameter was removed. + + .. versionchanged:: 2.2 + Calls ``current_app.json.dumps``, allowing an app to override + the behavior. + + .. versionchanged:: 2.0.2 + :class:`decimal.Decimal` is supported by converting to a string. + + .. versionchanged:: 2.0 + ``encoding`` will be removed in Flask 2.1. + + .. versionchanged:: 1.0.3 + ``app`` can be passed directly, rather than requiring an app + context for configuration. + """ + if current_app: + return current_app.json.dumps(obj, **kwargs) + + kwargs.setdefault("default", _default) + return _json.dumps(obj, **kwargs) + + +def dump(obj: t.Any, fp: t.IO[str], **kwargs: t.Any) -> None: + """Serialize data as JSON and write to a file. + + If :data:`~flask.current_app` is available, it will use its + :meth:`app.json.dump() ` + method, otherwise it will use :func:`json.dump`. + + :param obj: The data to serialize. + :param fp: A file opened for writing text. Should use the UTF-8 + encoding to be valid JSON. + :param kwargs: Arguments passed to the ``dump`` implementation. + + .. versionchanged:: 2.3 + The ``app`` parameter was removed. + + .. versionchanged:: 2.2 + Calls ``current_app.json.dump``, allowing an app to override + the behavior. + + .. versionchanged:: 2.0 + Writing to a binary file, and the ``encoding`` argument, will be + removed in Flask 2.1. + """ + if current_app: + current_app.json.dump(obj, fp, **kwargs) + else: + kwargs.setdefault("default", _default) + _json.dump(obj, fp, **kwargs) + + +def loads(s: str | bytes, **kwargs: t.Any) -> t.Any: + """Deserialize data as JSON. + + If :data:`~flask.current_app` is available, it will use its + :meth:`app.json.loads() ` + method, otherwise it will use :func:`json.loads`. + + :param s: Text or UTF-8 bytes. + :param kwargs: Arguments passed to the ``loads`` implementation. + + .. versionchanged:: 2.3 + The ``app`` parameter was removed. + + .. versionchanged:: 2.2 + Calls ``current_app.json.loads``, allowing an app to override + the behavior. + + .. versionchanged:: 2.0 + ``encoding`` will be removed in Flask 2.1. The data must be a + string or UTF-8 bytes. + + .. versionchanged:: 1.0.3 + ``app`` can be passed directly, rather than requiring an app + context for configuration. + """ + if current_app: + return current_app.json.loads(s, **kwargs) + + return _json.loads(s, **kwargs) + + +def load(fp: t.IO[t.AnyStr], **kwargs: t.Any) -> t.Any: + """Deserialize data as JSON read from a file. + + If :data:`~flask.current_app` is available, it will use its + :meth:`app.json.load() ` + method, otherwise it will use :func:`json.load`. + + :param fp: A file opened for reading text or UTF-8 bytes. + :param kwargs: Arguments passed to the ``load`` implementation. + + .. versionchanged:: 2.3 + The ``app`` parameter was removed. + + .. versionchanged:: 2.2 + Calls ``current_app.json.load``, allowing an app to override + the behavior. + + .. versionchanged:: 2.2 + The ``app`` parameter will be removed in Flask 2.3. + + .. versionchanged:: 2.0 + ``encoding`` will be removed in Flask 2.1. The file must be text + mode, or binary mode with UTF-8 bytes. + """ + if current_app: + return current_app.json.load(fp, **kwargs) + + return _json.load(fp, **kwargs) + + +def jsonify(*args: t.Any, **kwargs: t.Any) -> Response: + """Serialize the given arguments as JSON, and return a + :class:`~flask.Response` object with the ``application/json`` + mimetype. A dict or list returned from a view will be converted to a + JSON response automatically without needing to call this. + + This requires an active request or application context, and calls + :meth:`app.json.response() `. + + In debug mode, the output is formatted with indentation to make it + easier to read. This may also be controlled by the provider. + + Either positional or keyword arguments can be given, not both. + If no arguments are given, ``None`` is serialized. + + :param args: A single value to serialize, or multiple values to + treat as a list to serialize. + :param kwargs: Treat as a dict to serialize. + + .. versionchanged:: 2.2 + Calls ``current_app.json.response``, allowing an app to override + the behavior. + + .. versionchanged:: 2.0.2 + :class:`decimal.Decimal` is supported by converting to a string. + + .. versionchanged:: 0.11 + Added support for serializing top-level arrays. This was a + security risk in ancient browsers. See :ref:`security-json`. + + .. versionadded:: 0.2 + """ + return current_app.json.response(*args, **kwargs) diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/json/provider.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/json/provider.py new file mode 100644 index 0000000..3c22bc8 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/json/provider.py @@ -0,0 +1,216 @@ +from __future__ import annotations + +import dataclasses +import decimal +import json +import typing as t +import uuid +import weakref +from datetime import date + +from werkzeug.http import http_date + +if t.TYPE_CHECKING: # pragma: no cover + from ..sansio.app import App + from ..wrappers import Response + + +class JSONProvider: + """A standard set of JSON operations for an application. Subclasses + of this can be used to customize JSON behavior or use different + JSON libraries. + + To implement a provider for a specific library, subclass this base + class and implement at least :meth:`dumps` and :meth:`loads`. All + other methods have default implementations. + + To use a different provider, either subclass ``Flask`` and set + :attr:`~flask.Flask.json_provider_class` to a provider class, or set + :attr:`app.json ` to an instance of the class. + + :param app: An application instance. This will be stored as a + :class:`weakref.proxy` on the :attr:`_app` attribute. + + .. versionadded:: 2.2 + """ + + def __init__(self, app: App) -> None: + self._app = weakref.proxy(app) + + def dumps(self, obj: t.Any, **kwargs: t.Any) -> str: + """Serialize data as JSON. + + :param obj: The data to serialize. + :param kwargs: May be passed to the underlying JSON library. + """ + raise NotImplementedError + + def dump(self, obj: t.Any, fp: t.IO[str], **kwargs: t.Any) -> None: + """Serialize data as JSON and write to a file. + + :param obj: The data to serialize. + :param fp: A file opened for writing text. Should use the UTF-8 + encoding to be valid JSON. + :param kwargs: May be passed to the underlying JSON library. + """ + fp.write(self.dumps(obj, **kwargs)) + + def loads(self, s: str | bytes, **kwargs: t.Any) -> t.Any: + """Deserialize data as JSON. + + :param s: Text or UTF-8 bytes. + :param kwargs: May be passed to the underlying JSON library. + """ + raise NotImplementedError + + def load(self, fp: t.IO[t.AnyStr], **kwargs: t.Any) -> t.Any: + """Deserialize data as JSON read from a file. + + :param fp: A file opened for reading text or UTF-8 bytes. + :param kwargs: May be passed to the underlying JSON library. + """ + return self.loads(fp.read(), **kwargs) + + def _prepare_response_obj( + self, args: tuple[t.Any, ...], kwargs: dict[str, t.Any] + ) -> t.Any: + if args and kwargs: + raise TypeError("app.json.response() takes either args or kwargs, not both") + + if not args and not kwargs: + return None + + if len(args) == 1: + return args[0] + + return args or kwargs + + def response(self, *args: t.Any, **kwargs: t.Any) -> Response: + """Serialize the given arguments as JSON, and return a + :class:`~flask.Response` object with the ``application/json`` + mimetype. + + The :func:`~flask.json.jsonify` function calls this method for + the current application. + + Either positional or keyword arguments can be given, not both. + If no arguments are given, ``None`` is serialized. + + :param args: A single value to serialize, or multiple values to + treat as a list to serialize. + :param kwargs: Treat as a dict to serialize. + """ + obj = self._prepare_response_obj(args, kwargs) + return self._app.response_class(self.dumps(obj), mimetype="application/json") + + +def _default(o: t.Any) -> t.Any: + if isinstance(o, date): + return http_date(o) + + if isinstance(o, (decimal.Decimal, uuid.UUID)): + return str(o) + + if dataclasses and dataclasses.is_dataclass(o): + return dataclasses.asdict(o) + + if hasattr(o, "__html__"): + return str(o.__html__()) + + raise TypeError(f"Object of type {type(o).__name__} is not JSON serializable") + + +class DefaultJSONProvider(JSONProvider): + """Provide JSON operations using Python's built-in :mod:`json` + library. Serializes the following additional data types: + + - :class:`datetime.datetime` and :class:`datetime.date` are + serialized to :rfc:`822` strings. This is the same as the HTTP + date format. + - :class:`uuid.UUID` is serialized to a string. + - :class:`dataclasses.dataclass` is passed to + :func:`dataclasses.asdict`. + - :class:`~markupsafe.Markup` (or any object with a ``__html__`` + method) will call the ``__html__`` method to get a string. + """ + + default: t.Callable[[t.Any], t.Any] = staticmethod( + _default + ) # type: ignore[assignment] + """Apply this function to any object that :meth:`json.dumps` does + not know how to serialize. It should return a valid JSON type or + raise a ``TypeError``. + """ + + ensure_ascii = True + """Replace non-ASCII characters with escape sequences. This may be + more compatible with some clients, but can be disabled for better + performance and size. + """ + + sort_keys = True + """Sort the keys in any serialized dicts. This may be useful for + some caching situations, but can be disabled for better performance. + When enabled, keys must all be strings, they are not converted + before sorting. + """ + + compact: bool | None = None + """If ``True``, or ``None`` out of debug mode, the :meth:`response` + output will not add indentation, newlines, or spaces. If ``False``, + or ``None`` in debug mode, it will use a non-compact representation. + """ + + mimetype = "application/json" + """The mimetype set in :meth:`response`.""" + + def dumps(self, obj: t.Any, **kwargs: t.Any) -> str: + """Serialize data as JSON to a string. + + Keyword arguments are passed to :func:`json.dumps`. Sets some + parameter defaults from the :attr:`default`, + :attr:`ensure_ascii`, and :attr:`sort_keys` attributes. + + :param obj: The data to serialize. + :param kwargs: Passed to :func:`json.dumps`. + """ + kwargs.setdefault("default", self.default) + kwargs.setdefault("ensure_ascii", self.ensure_ascii) + kwargs.setdefault("sort_keys", self.sort_keys) + return json.dumps(obj, **kwargs) + + def loads(self, s: str | bytes, **kwargs: t.Any) -> t.Any: + """Deserialize data as JSON from a string or bytes. + + :param s: Text or UTF-8 bytes. + :param kwargs: Passed to :func:`json.loads`. + """ + return json.loads(s, **kwargs) + + def response(self, *args: t.Any, **kwargs: t.Any) -> Response: + """Serialize the given arguments as JSON, and return a + :class:`~flask.Response` object with it. The response mimetype + will be "application/json" and can be changed with + :attr:`mimetype`. + + If :attr:`compact` is ``False`` or debug mode is enabled, the + output will be formatted to be easier to read. + + Either positional or keyword arguments can be given, not both. + If no arguments are given, ``None`` is serialized. + + :param args: A single value to serialize, or multiple values to + treat as a list to serialize. + :param kwargs: Treat as a dict to serialize. + """ + obj = self._prepare_response_obj(args, kwargs) + dump_args: dict[str, t.Any] = {} + + if (self.compact is None and self._app.debug) or self.compact is False: + dump_args.setdefault("indent", 2) + else: + dump_args.setdefault("separators", (",", ":")) + + return self._app.response_class( + f"{self.dumps(obj, **dump_args)}\n", mimetype=self.mimetype + ) diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/json/tag.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/json/tag.py new file mode 100644 index 0000000..91cc441 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/json/tag.py @@ -0,0 +1,314 @@ +""" +Tagged JSON +~~~~~~~~~~~ + +A compact representation for lossless serialization of non-standard JSON +types. :class:`~flask.sessions.SecureCookieSessionInterface` uses this +to serialize the session data, but it may be useful in other places. It +can be extended to support other types. + +.. autoclass:: TaggedJSONSerializer + :members: + +.. autoclass:: JSONTag + :members: + +Let's see an example that adds support for +:class:`~collections.OrderedDict`. Dicts don't have an order in JSON, so +to handle this we will dump the items as a list of ``[key, value]`` +pairs. Subclass :class:`JSONTag` and give it the new key ``' od'`` to +identify the type. The session serializer processes dicts first, so +insert the new tag at the front of the order since ``OrderedDict`` must +be processed before ``dict``. + +.. code-block:: python + + from flask.json.tag import JSONTag + + class TagOrderedDict(JSONTag): + __slots__ = ('serializer',) + key = ' od' + + def check(self, value): + return isinstance(value, OrderedDict) + + def to_json(self, value): + return [[k, self.serializer.tag(v)] for k, v in iteritems(value)] + + def to_python(self, value): + return OrderedDict(value) + + app.session_interface.serializer.register(TagOrderedDict, index=0) +""" +from __future__ import annotations + +import typing as t +from base64 import b64decode +from base64 import b64encode +from datetime import datetime +from uuid import UUID + +from markupsafe import Markup +from werkzeug.http import http_date +from werkzeug.http import parse_date + +from ..json import dumps +from ..json import loads + + +class JSONTag: + """Base class for defining type tags for :class:`TaggedJSONSerializer`.""" + + __slots__ = ("serializer",) + + #: The tag to mark the serialized object with. If ``None``, this tag is + #: only used as an intermediate step during tagging. + key: str | None = None + + def __init__(self, serializer: TaggedJSONSerializer) -> None: + """Create a tagger for the given serializer.""" + self.serializer = serializer + + def check(self, value: t.Any) -> bool: + """Check if the given value should be tagged by this tag.""" + raise NotImplementedError + + def to_json(self, value: t.Any) -> t.Any: + """Convert the Python object to an object that is a valid JSON type. + The tag will be added later.""" + raise NotImplementedError + + def to_python(self, value: t.Any) -> t.Any: + """Convert the JSON representation back to the correct type. The tag + will already be removed.""" + raise NotImplementedError + + def tag(self, value: t.Any) -> t.Any: + """Convert the value to a valid JSON type and add the tag structure + around it.""" + return {self.key: self.to_json(value)} + + +class TagDict(JSONTag): + """Tag for 1-item dicts whose only key matches a registered tag. + + Internally, the dict key is suffixed with `__`, and the suffix is removed + when deserializing. + """ + + __slots__ = () + key = " di" + + def check(self, value: t.Any) -> bool: + return ( + isinstance(value, dict) + and len(value) == 1 + and next(iter(value)) in self.serializer.tags + ) + + def to_json(self, value: t.Any) -> t.Any: + key = next(iter(value)) + return {f"{key}__": self.serializer.tag(value[key])} + + def to_python(self, value: t.Any) -> t.Any: + key = next(iter(value)) + return {key[:-2]: value[key]} + + +class PassDict(JSONTag): + __slots__ = () + + def check(self, value: t.Any) -> bool: + return isinstance(value, dict) + + def to_json(self, value: t.Any) -> t.Any: + # JSON objects may only have string keys, so don't bother tagging the + # key here. + return {k: self.serializer.tag(v) for k, v in value.items()} + + tag = to_json + + +class TagTuple(JSONTag): + __slots__ = () + key = " t" + + def check(self, value: t.Any) -> bool: + return isinstance(value, tuple) + + def to_json(self, value: t.Any) -> t.Any: + return [self.serializer.tag(item) for item in value] + + def to_python(self, value: t.Any) -> t.Any: + return tuple(value) + + +class PassList(JSONTag): + __slots__ = () + + def check(self, value: t.Any) -> bool: + return isinstance(value, list) + + def to_json(self, value: t.Any) -> t.Any: + return [self.serializer.tag(item) for item in value] + + tag = to_json + + +class TagBytes(JSONTag): + __slots__ = () + key = " b" + + def check(self, value: t.Any) -> bool: + return isinstance(value, bytes) + + def to_json(self, value: t.Any) -> t.Any: + return b64encode(value).decode("ascii") + + def to_python(self, value: t.Any) -> t.Any: + return b64decode(value) + + +class TagMarkup(JSONTag): + """Serialize anything matching the :class:`~markupsafe.Markup` API by + having a ``__html__`` method to the result of that method. Always + deserializes to an instance of :class:`~markupsafe.Markup`.""" + + __slots__ = () + key = " m" + + def check(self, value: t.Any) -> bool: + return callable(getattr(value, "__html__", None)) + + def to_json(self, value: t.Any) -> t.Any: + return str(value.__html__()) + + def to_python(self, value: t.Any) -> t.Any: + return Markup(value) + + +class TagUUID(JSONTag): + __slots__ = () + key = " u" + + def check(self, value: t.Any) -> bool: + return isinstance(value, UUID) + + def to_json(self, value: t.Any) -> t.Any: + return value.hex + + def to_python(self, value: t.Any) -> t.Any: + return UUID(value) + + +class TagDateTime(JSONTag): + __slots__ = () + key = " d" + + def check(self, value: t.Any) -> bool: + return isinstance(value, datetime) + + def to_json(self, value: t.Any) -> t.Any: + return http_date(value) + + def to_python(self, value: t.Any) -> t.Any: + return parse_date(value) + + +class TaggedJSONSerializer: + """Serializer that uses a tag system to compactly represent objects that + are not JSON types. Passed as the intermediate serializer to + :class:`itsdangerous.Serializer`. + + The following extra types are supported: + + * :class:`dict` + * :class:`tuple` + * :class:`bytes` + * :class:`~markupsafe.Markup` + * :class:`~uuid.UUID` + * :class:`~datetime.datetime` + """ + + __slots__ = ("tags", "order") + + #: Tag classes to bind when creating the serializer. Other tags can be + #: added later using :meth:`~register`. + default_tags = [ + TagDict, + PassDict, + TagTuple, + PassList, + TagBytes, + TagMarkup, + TagUUID, + TagDateTime, + ] + + def __init__(self) -> None: + self.tags: dict[str, JSONTag] = {} + self.order: list[JSONTag] = [] + + for cls in self.default_tags: + self.register(cls) + + def register( + self, + tag_class: type[JSONTag], + force: bool = False, + index: int | None = None, + ) -> None: + """Register a new tag with this serializer. + + :param tag_class: tag class to register. Will be instantiated with this + serializer instance. + :param force: overwrite an existing tag. If false (default), a + :exc:`KeyError` is raised. + :param index: index to insert the new tag in the tag order. Useful when + the new tag is a special case of an existing tag. If ``None`` + (default), the tag is appended to the end of the order. + + :raise KeyError: if the tag key is already registered and ``force`` is + not true. + """ + tag = tag_class(self) + key = tag.key + + if key is not None: + if not force and key in self.tags: + raise KeyError(f"Tag '{key}' is already registered.") + + self.tags[key] = tag + + if index is None: + self.order.append(tag) + else: + self.order.insert(index, tag) + + def tag(self, value: t.Any) -> dict[str, t.Any]: + """Convert a value to a tagged representation if necessary.""" + for tag in self.order: + if tag.check(value): + return tag.tag(value) + + return value + + def untag(self, value: dict[str, t.Any]) -> t.Any: + """Convert a tagged representation back to the original type.""" + if len(value) != 1: + return value + + key = next(iter(value)) + + if key not in self.tags: + return value + + return self.tags[key].to_python(value[key]) + + def dumps(self, value: t.Any) -> str: + """Tag the value and dump it to a compact JSON string.""" + return dumps(self.tag(value), separators=(",", ":")) + + def loads(self, value: str) -> t.Any: + """Load data from a JSON string and deserialized any tagged objects.""" + return loads(value, object_hook=self.untag) diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/logging.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/logging.py new file mode 100644 index 0000000..b452f71 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/logging.py @@ -0,0 +1,76 @@ +from __future__ import annotations + +import logging +import sys +import typing as t + +from werkzeug.local import LocalProxy + +from .globals import request + +if t.TYPE_CHECKING: # pragma: no cover + from .sansio.app import App + + +@LocalProxy +def wsgi_errors_stream() -> t.TextIO: + """Find the most appropriate error stream for the application. If a request + is active, log to ``wsgi.errors``, otherwise use ``sys.stderr``. + + If you configure your own :class:`logging.StreamHandler`, you may want to + use this for the stream. If you are using file or dict configuration and + can't import this directly, you can refer to it as + ``ext://flask.logging.wsgi_errors_stream``. + """ + return request.environ["wsgi.errors"] if request else sys.stderr + + +def has_level_handler(logger: logging.Logger) -> bool: + """Check if there is a handler in the logging chain that will handle the + given logger's :meth:`effective level <~logging.Logger.getEffectiveLevel>`. + """ + level = logger.getEffectiveLevel() + current = logger + + while current: + if any(handler.level <= level for handler in current.handlers): + return True + + if not current.propagate: + break + + current = current.parent # type: ignore + + return False + + +#: Log messages to :func:`~flask.logging.wsgi_errors_stream` with the format +#: ``[%(asctime)s] %(levelname)s in %(module)s: %(message)s``. +default_handler = logging.StreamHandler(wsgi_errors_stream) # type: ignore +default_handler.setFormatter( + logging.Formatter("[%(asctime)s] %(levelname)s in %(module)s: %(message)s") +) + + +def create_logger(app: App) -> logging.Logger: + """Get the Flask app's logger and configure it if needed. + + The logger name will be the same as + :attr:`app.import_name `. + + When :attr:`~flask.Flask.debug` is enabled, set the logger level to + :data:`logging.DEBUG` if it is not set. + + If there is no handler for the logger's effective level, add a + :class:`~logging.StreamHandler` for + :func:`~flask.logging.wsgi_errors_stream` with a basic format. + """ + logger = logging.getLogger(app.name) + + if app.debug and not logger.level: + logger.setLevel(logging.DEBUG) + + if not has_level_handler(logger): + logger.addHandler(default_handler) + + return logger diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/py.typed b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/sansio/README.md b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/sansio/README.md new file mode 100644 index 0000000..623ac19 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/sansio/README.md @@ -0,0 +1,6 @@ +# Sansio + +This folder contains code that can be used by alternative Flask +implementations, for example Quart. The code therefore cannot do any +IO, nor be part of a likely IO path. Finally this code cannot use the +Flask globals. diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/sansio/app.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/sansio/app.py new file mode 100644 index 0000000..0f7d2cb --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/sansio/app.py @@ -0,0 +1,964 @@ +from __future__ import annotations + +import logging +import os +import sys +import typing as t +from datetime import timedelta +from itertools import chain + +from werkzeug.exceptions import Aborter +from werkzeug.exceptions import BadRequest +from werkzeug.exceptions import BadRequestKeyError +from werkzeug.routing import BuildError +from werkzeug.routing import Map +from werkzeug.routing import Rule +from werkzeug.sansio.response import Response +from werkzeug.utils import cached_property +from werkzeug.utils import redirect as _wz_redirect + +from .. import typing as ft +from ..config import Config +from ..config import ConfigAttribute +from ..ctx import _AppCtxGlobals +from ..helpers import _split_blueprint_path +from ..helpers import get_debug_flag +from ..json.provider import DefaultJSONProvider +from ..json.provider import JSONProvider +from ..logging import create_logger +from ..templating import DispatchingJinjaLoader +from ..templating import Environment +from .scaffold import _endpoint_from_view_func +from .scaffold import find_package +from .scaffold import Scaffold +from .scaffold import setupmethod + +if t.TYPE_CHECKING: # pragma: no cover + from werkzeug.wrappers import Response as BaseResponse + from .blueprints import Blueprint + from ..testing import FlaskClient + from ..testing import FlaskCliRunner + +T_shell_context_processor = t.TypeVar( + "T_shell_context_processor", bound=ft.ShellContextProcessorCallable +) +T_teardown = t.TypeVar("T_teardown", bound=ft.TeardownCallable) +T_template_filter = t.TypeVar("T_template_filter", bound=ft.TemplateFilterCallable) +T_template_global = t.TypeVar("T_template_global", bound=ft.TemplateGlobalCallable) +T_template_test = t.TypeVar("T_template_test", bound=ft.TemplateTestCallable) + + +def _make_timedelta(value: timedelta | int | None) -> timedelta | None: + if value is None or isinstance(value, timedelta): + return value + + return timedelta(seconds=value) + + +class App(Scaffold): + """The flask object implements a WSGI application and acts as the central + object. It is passed the name of the module or package of the + application. Once it is created it will act as a central registry for + the view functions, the URL rules, template configuration and much more. + + The name of the package is used to resolve resources from inside the + package or the folder the module is contained in depending on if the + package parameter resolves to an actual python package (a folder with + an :file:`__init__.py` file inside) or a standard module (just a ``.py`` file). + + For more information about resource loading, see :func:`open_resource`. + + Usually you create a :class:`Flask` instance in your main module or + in the :file:`__init__.py` file of your package like this:: + + from flask import Flask + app = Flask(__name__) + + .. admonition:: About the First Parameter + + The idea of the first parameter is to give Flask an idea of what + belongs to your application. This name is used to find resources + on the filesystem, can be used by extensions to improve debugging + information and a lot more. + + So it's important what you provide there. If you are using a single + module, `__name__` is always the correct value. If you however are + using a package, it's usually recommended to hardcode the name of + your package there. + + For example if your application is defined in :file:`yourapplication/app.py` + you should create it with one of the two versions below:: + + app = Flask('yourapplication') + app = Flask(__name__.split('.')[0]) + + Why is that? The application will work even with `__name__`, thanks + to how resources are looked up. However it will make debugging more + painful. Certain extensions can make assumptions based on the + import name of your application. For example the Flask-SQLAlchemy + extension will look for the code in your application that triggered + an SQL query in debug mode. If the import name is not properly set + up, that debugging information is lost. (For example it would only + pick up SQL queries in `yourapplication.app` and not + `yourapplication.views.frontend`) + + .. versionadded:: 0.7 + The `static_url_path`, `static_folder`, and `template_folder` + parameters were added. + + .. versionadded:: 0.8 + The `instance_path` and `instance_relative_config` parameters were + added. + + .. versionadded:: 0.11 + The `root_path` parameter was added. + + .. versionadded:: 1.0 + The ``host_matching`` and ``static_host`` parameters were added. + + .. versionadded:: 1.0 + The ``subdomain_matching`` parameter was added. Subdomain + matching needs to be enabled manually now. Setting + :data:`SERVER_NAME` does not implicitly enable it. + + :param import_name: the name of the application package + :param static_url_path: can be used to specify a different path for the + static files on the web. Defaults to the name + of the `static_folder` folder. + :param static_folder: The folder with static files that is served at + ``static_url_path``. Relative to the application ``root_path`` + or an absolute path. Defaults to ``'static'``. + :param static_host: the host to use when adding the static route. + Defaults to None. Required when using ``host_matching=True`` + with a ``static_folder`` configured. + :param host_matching: set ``url_map.host_matching`` attribute. + Defaults to False. + :param subdomain_matching: consider the subdomain relative to + :data:`SERVER_NAME` when matching routes. Defaults to False. + :param template_folder: the folder that contains the templates that should + be used by the application. Defaults to + ``'templates'`` folder in the root path of the + application. + :param instance_path: An alternative instance path for the application. + By default the folder ``'instance'`` next to the + package or module is assumed to be the instance + path. + :param instance_relative_config: if set to ``True`` relative filenames + for loading the config are assumed to + be relative to the instance path instead + of the application root. + :param root_path: The path to the root of the application files. + This should only be set manually when it can't be detected + automatically, such as for namespace packages. + """ + + #: The class of the object assigned to :attr:`aborter`, created by + #: :meth:`create_aborter`. That object is called by + #: :func:`flask.abort` to raise HTTP errors, and can be + #: called directly as well. + #: + #: Defaults to :class:`werkzeug.exceptions.Aborter`. + #: + #: .. versionadded:: 2.2 + aborter_class = Aborter + + #: The class that is used for the Jinja environment. + #: + #: .. versionadded:: 0.11 + jinja_environment = Environment + + #: The class that is used for the :data:`~flask.g` instance. + #: + #: Example use cases for a custom class: + #: + #: 1. Store arbitrary attributes on flask.g. + #: 2. Add a property for lazy per-request database connectors. + #: 3. Return None instead of AttributeError on unexpected attributes. + #: 4. Raise exception if an unexpected attr is set, a "controlled" flask.g. + #: + #: In Flask 0.9 this property was called `request_globals_class` but it + #: was changed in 0.10 to :attr:`app_ctx_globals_class` because the + #: flask.g object is now application context scoped. + #: + #: .. versionadded:: 0.10 + app_ctx_globals_class = _AppCtxGlobals + + #: The class that is used for the ``config`` attribute of this app. + #: Defaults to :class:`~flask.Config`. + #: + #: Example use cases for a custom class: + #: + #: 1. Default values for certain config options. + #: 2. Access to config values through attributes in addition to keys. + #: + #: .. versionadded:: 0.11 + config_class = Config + + #: The testing flag. Set this to ``True`` to enable the test mode of + #: Flask extensions (and in the future probably also Flask itself). + #: For example this might activate test helpers that have an + #: additional runtime cost which should not be enabled by default. + #: + #: If this is enabled and PROPAGATE_EXCEPTIONS is not changed from the + #: default it's implicitly enabled. + #: + #: This attribute can also be configured from the config with the + #: ``TESTING`` configuration key. Defaults to ``False``. + testing = ConfigAttribute("TESTING") + + #: If a secret key is set, cryptographic components can use this to + #: sign cookies and other things. Set this to a complex random value + #: when you want to use the secure cookie for instance. + #: + #: This attribute can also be configured from the config with the + #: :data:`SECRET_KEY` configuration key. Defaults to ``None``. + secret_key = ConfigAttribute("SECRET_KEY") + + #: A :class:`~datetime.timedelta` which is used to set the expiration + #: date of a permanent session. The default is 31 days which makes a + #: permanent session survive for roughly one month. + #: + #: This attribute can also be configured from the config with the + #: ``PERMANENT_SESSION_LIFETIME`` configuration key. Defaults to + #: ``timedelta(days=31)`` + permanent_session_lifetime = ConfigAttribute( + "PERMANENT_SESSION_LIFETIME", get_converter=_make_timedelta + ) + + json_provider_class: type[JSONProvider] = DefaultJSONProvider + """A subclass of :class:`~flask.json.provider.JSONProvider`. An + instance is created and assigned to :attr:`app.json` when creating + the app. + + The default, :class:`~flask.json.provider.DefaultJSONProvider`, uses + Python's built-in :mod:`json` library. A different provider can use + a different JSON library. + + .. versionadded:: 2.2 + """ + + #: Options that are passed to the Jinja environment in + #: :meth:`create_jinja_environment`. Changing these options after + #: the environment is created (accessing :attr:`jinja_env`) will + #: have no effect. + #: + #: .. versionchanged:: 1.1.0 + #: This is a ``dict`` instead of an ``ImmutableDict`` to allow + #: easier configuration. + #: + jinja_options: dict = {} + + #: The rule object to use for URL rules created. This is used by + #: :meth:`add_url_rule`. Defaults to :class:`werkzeug.routing.Rule`. + #: + #: .. versionadded:: 0.7 + url_rule_class = Rule + + #: The map object to use for storing the URL rules and routing + #: configuration parameters. Defaults to :class:`werkzeug.routing.Map`. + #: + #: .. versionadded:: 1.1.0 + url_map_class = Map + + #: The :meth:`test_client` method creates an instance of this test + #: client class. Defaults to :class:`~flask.testing.FlaskClient`. + #: + #: .. versionadded:: 0.7 + test_client_class: type[FlaskClient] | None = None + + #: The :class:`~click.testing.CliRunner` subclass, by default + #: :class:`~flask.testing.FlaskCliRunner` that is used by + #: :meth:`test_cli_runner`. Its ``__init__`` method should take a + #: Flask app object as the first argument. + #: + #: .. versionadded:: 1.0 + test_cli_runner_class: type[FlaskCliRunner] | None = None + + default_config: dict + response_class: type[Response] + + def __init__( + self, + import_name: str, + static_url_path: str | None = None, + static_folder: str | os.PathLike | None = "static", + static_host: str | None = None, + host_matching: bool = False, + subdomain_matching: bool = False, + template_folder: str | os.PathLike | None = "templates", + instance_path: str | None = None, + instance_relative_config: bool = False, + root_path: str | None = None, + ): + super().__init__( + import_name=import_name, + static_folder=static_folder, + static_url_path=static_url_path, + template_folder=template_folder, + root_path=root_path, + ) + + if instance_path is None: + instance_path = self.auto_find_instance_path() + elif not os.path.isabs(instance_path): + raise ValueError( + "If an instance path is provided it must be absolute." + " A relative path was given instead." + ) + + #: Holds the path to the instance folder. + #: + #: .. versionadded:: 0.8 + self.instance_path = instance_path + + #: The configuration dictionary as :class:`Config`. This behaves + #: exactly like a regular dictionary but supports additional methods + #: to load a config from files. + self.config = self.make_config(instance_relative_config) + + #: An instance of :attr:`aborter_class` created by + #: :meth:`make_aborter`. This is called by :func:`flask.abort` + #: to raise HTTP errors, and can be called directly as well. + #: + #: .. versionadded:: 2.2 + #: Moved from ``flask.abort``, which calls this object. + self.aborter = self.make_aborter() + + self.json: JSONProvider = self.json_provider_class(self) + """Provides access to JSON methods. Functions in ``flask.json`` + will call methods on this provider when the application context + is active. Used for handling JSON requests and responses. + + An instance of :attr:`json_provider_class`. Can be customized by + changing that attribute on a subclass, or by assigning to this + attribute afterwards. + + The default, :class:`~flask.json.provider.DefaultJSONProvider`, + uses Python's built-in :mod:`json` library. A different provider + can use a different JSON library. + + .. versionadded:: 2.2 + """ + + #: A list of functions that are called by + #: :meth:`handle_url_build_error` when :meth:`.url_for` raises a + #: :exc:`~werkzeug.routing.BuildError`. Each function is called + #: with ``error``, ``endpoint`` and ``values``. If a function + #: returns ``None`` or raises a ``BuildError``, it is skipped. + #: Otherwise, its return value is returned by ``url_for``. + #: + #: .. versionadded:: 0.9 + self.url_build_error_handlers: list[ + t.Callable[[Exception, str, dict[str, t.Any]], str] + ] = [] + + #: A list of functions that are called when the application context + #: is destroyed. Since the application context is also torn down + #: if the request ends this is the place to store code that disconnects + #: from databases. + #: + #: .. versionadded:: 0.9 + self.teardown_appcontext_funcs: list[ft.TeardownCallable] = [] + + #: A list of shell context processor functions that should be run + #: when a shell context is created. + #: + #: .. versionadded:: 0.11 + self.shell_context_processors: list[ft.ShellContextProcessorCallable] = [] + + #: Maps registered blueprint names to blueprint objects. The + #: dict retains the order the blueprints were registered in. + #: Blueprints can be registered multiple times, this dict does + #: not track how often they were attached. + #: + #: .. versionadded:: 0.7 + self.blueprints: dict[str, Blueprint] = {} + + #: a place where extensions can store application specific state. For + #: example this is where an extension could store database engines and + #: similar things. + #: + #: The key must match the name of the extension module. For example in + #: case of a "Flask-Foo" extension in `flask_foo`, the key would be + #: ``'foo'``. + #: + #: .. versionadded:: 0.7 + self.extensions: dict = {} + + #: The :class:`~werkzeug.routing.Map` for this instance. You can use + #: this to change the routing converters after the class was created + #: but before any routes are connected. Example:: + #: + #: from werkzeug.routing import BaseConverter + #: + #: class ListConverter(BaseConverter): + #: def to_python(self, value): + #: return value.split(',') + #: def to_url(self, values): + #: return ','.join(super(ListConverter, self).to_url(value) + #: for value in values) + #: + #: app = Flask(__name__) + #: app.url_map.converters['list'] = ListConverter + self.url_map = self.url_map_class(host_matching=host_matching) + + self.subdomain_matching = subdomain_matching + + # tracks internally if the application already handled at least one + # request. + self._got_first_request = False + + # Set the name of the Click group in case someone wants to add + # the app's commands to another CLI tool. + self.cli.name = self.name + + def _check_setup_finished(self, f_name: str) -> None: + if self._got_first_request: + raise AssertionError( + f"The setup method '{f_name}' can no longer be called" + " on the application. It has already handled its first" + " request, any changes will not be applied" + " consistently.\n" + "Make sure all imports, decorators, functions, etc." + " needed to set up the application are done before" + " running it." + ) + + @cached_property + def name(self) -> str: # type: ignore + """The name of the application. This is usually the import name + with the difference that it's guessed from the run file if the + import name is main. This name is used as a display name when + Flask needs the name of the application. It can be set and overridden + to change the value. + + .. versionadded:: 0.8 + """ + if self.import_name == "__main__": + fn = getattr(sys.modules["__main__"], "__file__", None) + if fn is None: + return "__main__" + return os.path.splitext(os.path.basename(fn))[0] + return self.import_name + + @cached_property + def logger(self) -> logging.Logger: + """A standard Python :class:`~logging.Logger` for the app, with + the same name as :attr:`name`. + + In debug mode, the logger's :attr:`~logging.Logger.level` will + be set to :data:`~logging.DEBUG`. + + If there are no handlers configured, a default handler will be + added. See :doc:`/logging` for more information. + + .. versionchanged:: 1.1.0 + The logger takes the same name as :attr:`name` rather than + hard-coding ``"flask.app"``. + + .. versionchanged:: 1.0.0 + Behavior was simplified. The logger is always named + ``"flask.app"``. The level is only set during configuration, + it doesn't check ``app.debug`` each time. Only one format is + used, not different ones depending on ``app.debug``. No + handlers are removed, and a handler is only added if no + handlers are already configured. + + .. versionadded:: 0.3 + """ + return create_logger(self) + + @cached_property + def jinja_env(self) -> Environment: + """The Jinja environment used to load templates. + + The environment is created the first time this property is + accessed. Changing :attr:`jinja_options` after that will have no + effect. + """ + return self.create_jinja_environment() + + def create_jinja_environment(self) -> Environment: + raise NotImplementedError() + + def make_config(self, instance_relative: bool = False) -> Config: + """Used to create the config attribute by the Flask constructor. + The `instance_relative` parameter is passed in from the constructor + of Flask (there named `instance_relative_config`) and indicates if + the config should be relative to the instance path or the root path + of the application. + + .. versionadded:: 0.8 + """ + root_path = self.root_path + if instance_relative: + root_path = self.instance_path + defaults = dict(self.default_config) + defaults["DEBUG"] = get_debug_flag() + return self.config_class(root_path, defaults) + + def make_aborter(self) -> Aborter: + """Create the object to assign to :attr:`aborter`. That object + is called by :func:`flask.abort` to raise HTTP errors, and can + be called directly as well. + + By default, this creates an instance of :attr:`aborter_class`, + which defaults to :class:`werkzeug.exceptions.Aborter`. + + .. versionadded:: 2.2 + """ + return self.aborter_class() + + def auto_find_instance_path(self) -> str: + """Tries to locate the instance path if it was not provided to the + constructor of the application class. It will basically calculate + the path to a folder named ``instance`` next to your main file or + the package. + + .. versionadded:: 0.8 + """ + prefix, package_path = find_package(self.import_name) + if prefix is None: + return os.path.join(package_path, "instance") + return os.path.join(prefix, "var", f"{self.name}-instance") + + def create_global_jinja_loader(self) -> DispatchingJinjaLoader: + """Creates the loader for the Jinja2 environment. Can be used to + override just the loader and keeping the rest unchanged. It's + discouraged to override this function. Instead one should override + the :meth:`jinja_loader` function instead. + + The global loader dispatches between the loaders of the application + and the individual blueprints. + + .. versionadded:: 0.7 + """ + return DispatchingJinjaLoader(self) + + def select_jinja_autoescape(self, filename: str) -> bool: + """Returns ``True`` if autoescaping should be active for the given + template name. If no template name is given, returns `True`. + + .. versionchanged:: 2.2 + Autoescaping is now enabled by default for ``.svg`` files. + + .. versionadded:: 0.5 + """ + if filename is None: + return True + return filename.endswith((".html", ".htm", ".xml", ".xhtml", ".svg")) + + @property + def debug(self) -> bool: + """Whether debug mode is enabled. When using ``flask run`` to start the + development server, an interactive debugger will be shown for unhandled + exceptions, and the server will be reloaded when code changes. This maps to the + :data:`DEBUG` config key. It may not behave as expected if set late. + + **Do not enable debug mode when deploying in production.** + + Default: ``False`` + """ + return self.config["DEBUG"] + + @debug.setter + def debug(self, value: bool) -> None: + self.config["DEBUG"] = value + + if self.config["TEMPLATES_AUTO_RELOAD"] is None: + self.jinja_env.auto_reload = value + + @setupmethod + def register_blueprint(self, blueprint: Blueprint, **options: t.Any) -> None: + """Register a :class:`~flask.Blueprint` on the application. Keyword + arguments passed to this method will override the defaults set on the + blueprint. + + Calls the blueprint's :meth:`~flask.Blueprint.register` method after + recording the blueprint in the application's :attr:`blueprints`. + + :param blueprint: The blueprint to register. + :param url_prefix: Blueprint routes will be prefixed with this. + :param subdomain: Blueprint routes will match on this subdomain. + :param url_defaults: Blueprint routes will use these default values for + view arguments. + :param options: Additional keyword arguments are passed to + :class:`~flask.blueprints.BlueprintSetupState`. They can be + accessed in :meth:`~flask.Blueprint.record` callbacks. + + .. versionchanged:: 2.0.1 + The ``name`` option can be used to change the (pre-dotted) + name the blueprint is registered with. This allows the same + blueprint to be registered multiple times with unique names + for ``url_for``. + + .. versionadded:: 0.7 + """ + blueprint.register(self, options) + + def iter_blueprints(self) -> t.ValuesView[Blueprint]: + """Iterates over all blueprints by the order they were registered. + + .. versionadded:: 0.11 + """ + return self.blueprints.values() + + @setupmethod + def add_url_rule( + self, + rule: str, + endpoint: str | None = None, + view_func: ft.RouteCallable | None = None, + provide_automatic_options: bool | None = None, + **options: t.Any, + ) -> None: + if endpoint is None: + endpoint = _endpoint_from_view_func(view_func) # type: ignore + options["endpoint"] = endpoint + methods = options.pop("methods", None) + + # if the methods are not given and the view_func object knows its + # methods we can use that instead. If neither exists, we go with + # a tuple of only ``GET`` as default. + if methods is None: + methods = getattr(view_func, "methods", None) or ("GET",) + if isinstance(methods, str): + raise TypeError( + "Allowed methods must be a list of strings, for" + ' example: @app.route(..., methods=["POST"])' + ) + methods = {item.upper() for item in methods} + + # Methods that should always be added + required_methods = set(getattr(view_func, "required_methods", ())) + + # starting with Flask 0.8 the view_func object can disable and + # force-enable the automatic options handling. + if provide_automatic_options is None: + provide_automatic_options = getattr( + view_func, "provide_automatic_options", None + ) + + if provide_automatic_options is None: + if "OPTIONS" not in methods: + provide_automatic_options = True + required_methods.add("OPTIONS") + else: + provide_automatic_options = False + + # Add the required methods now. + methods |= required_methods + + rule = self.url_rule_class(rule, methods=methods, **options) + rule.provide_automatic_options = provide_automatic_options # type: ignore + + self.url_map.add(rule) + if view_func is not None: + old_func = self.view_functions.get(endpoint) + if old_func is not None and old_func != view_func: + raise AssertionError( + "View function mapping is overwriting an existing" + f" endpoint function: {endpoint}" + ) + self.view_functions[endpoint] = view_func + + @setupmethod + def template_filter( + self, name: str | None = None + ) -> t.Callable[[T_template_filter], T_template_filter]: + """A decorator that is used to register custom template filter. + You can specify a name for the filter, otherwise the function + name will be used. Example:: + + @app.template_filter() + def reverse(s): + return s[::-1] + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + + def decorator(f: T_template_filter) -> T_template_filter: + self.add_template_filter(f, name=name) + return f + + return decorator + + @setupmethod + def add_template_filter( + self, f: ft.TemplateFilterCallable, name: str | None = None + ) -> None: + """Register a custom template filter. Works exactly like the + :meth:`template_filter` decorator. + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + self.jinja_env.filters[name or f.__name__] = f + + @setupmethod + def template_test( + self, name: str | None = None + ) -> t.Callable[[T_template_test], T_template_test]: + """A decorator that is used to register custom template test. + You can specify a name for the test, otherwise the function + name will be used. Example:: + + @app.template_test() + def is_prime(n): + if n == 2: + return True + for i in range(2, int(math.ceil(math.sqrt(n))) + 1): + if n % i == 0: + return False + return True + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + + def decorator(f: T_template_test) -> T_template_test: + self.add_template_test(f, name=name) + return f + + return decorator + + @setupmethod + def add_template_test( + self, f: ft.TemplateTestCallable, name: str | None = None + ) -> None: + """Register a custom template test. Works exactly like the + :meth:`template_test` decorator. + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + self.jinja_env.tests[name or f.__name__] = f + + @setupmethod + def template_global( + self, name: str | None = None + ) -> t.Callable[[T_template_global], T_template_global]: + """A decorator that is used to register a custom template global function. + You can specify a name for the global function, otherwise the function + name will be used. Example:: + + @app.template_global() + def double(n): + return 2 * n + + .. versionadded:: 0.10 + + :param name: the optional name of the global function, otherwise the + function name will be used. + """ + + def decorator(f: T_template_global) -> T_template_global: + self.add_template_global(f, name=name) + return f + + return decorator + + @setupmethod + def add_template_global( + self, f: ft.TemplateGlobalCallable, name: str | None = None + ) -> None: + """Register a custom template global function. Works exactly like the + :meth:`template_global` decorator. + + .. versionadded:: 0.10 + + :param name: the optional name of the global function, otherwise the + function name will be used. + """ + self.jinja_env.globals[name or f.__name__] = f + + @setupmethod + def teardown_appcontext(self, f: T_teardown) -> T_teardown: + """Registers a function to be called when the application + context is popped. The application context is typically popped + after the request context for each request, at the end of CLI + commands, or after a manually pushed context ends. + + .. code-block:: python + + with app.app_context(): + ... + + When the ``with`` block exits (or ``ctx.pop()`` is called), the + teardown functions are called just before the app context is + made inactive. Since a request context typically also manages an + application context it would also be called when you pop a + request context. + + When a teardown function was called because of an unhandled + exception it will be passed an error object. If an + :meth:`errorhandler` is registered, it will handle the exception + and the teardown will not receive it. + + Teardown functions must avoid raising exceptions. If they + execute code that might fail they must surround that code with a + ``try``/``except`` block and log any errors. + + The return values of teardown functions are ignored. + + .. versionadded:: 0.9 + """ + self.teardown_appcontext_funcs.append(f) + return f + + @setupmethod + def shell_context_processor( + self, f: T_shell_context_processor + ) -> T_shell_context_processor: + """Registers a shell context processor function. + + .. versionadded:: 0.11 + """ + self.shell_context_processors.append(f) + return f + + def _find_error_handler( + self, e: Exception, blueprints: list[str] + ) -> ft.ErrorHandlerCallable | None: + """Return a registered error handler for an exception in this order: + blueprint handler for a specific code, app handler for a specific code, + blueprint handler for an exception class, app handler for an exception + class, or ``None`` if a suitable handler is not found. + """ + exc_class, code = self._get_exc_class_and_code(type(e)) + names = (*blueprints, None) + + for c in (code, None) if code is not None else (None,): + for name in names: + handler_map = self.error_handler_spec[name][c] + + if not handler_map: + continue + + for cls in exc_class.__mro__: + handler = handler_map.get(cls) + + if handler is not None: + return handler + return None + + def trap_http_exception(self, e: Exception) -> bool: + """Checks if an HTTP exception should be trapped or not. By default + this will return ``False`` for all exceptions except for a bad request + key error if ``TRAP_BAD_REQUEST_ERRORS`` is set to ``True``. It + also returns ``True`` if ``TRAP_HTTP_EXCEPTIONS`` is set to ``True``. + + This is called for all HTTP exceptions raised by a view function. + If it returns ``True`` for any exception the error handler for this + exception is not called and it shows up as regular exception in the + traceback. This is helpful for debugging implicitly raised HTTP + exceptions. + + .. versionchanged:: 1.0 + Bad request errors are not trapped by default in debug mode. + + .. versionadded:: 0.8 + """ + if self.config["TRAP_HTTP_EXCEPTIONS"]: + return True + + trap_bad_request = self.config["TRAP_BAD_REQUEST_ERRORS"] + + # if unset, trap key errors in debug mode + if ( + trap_bad_request is None + and self.debug + and isinstance(e, BadRequestKeyError) + ): + return True + + if trap_bad_request: + return isinstance(e, BadRequest) + + return False + + def should_ignore_error(self, error: BaseException | None) -> bool: + """This is called to figure out if an error should be ignored + or not as far as the teardown system is concerned. If this + function returns ``True`` then the teardown handlers will not be + passed the error. + + .. versionadded:: 0.10 + """ + return False + + def redirect(self, location: str, code: int = 302) -> BaseResponse: + """Create a redirect response object. + + This is called by :func:`flask.redirect`, and can be called + directly as well. + + :param location: The URL to redirect to. + :param code: The status code for the redirect. + + .. versionadded:: 2.2 + Moved from ``flask.redirect``, which calls this method. + """ + return _wz_redirect( + location, code=code, Response=self.response_class # type: ignore[arg-type] + ) + + def inject_url_defaults(self, endpoint: str, values: dict) -> None: + """Injects the URL defaults for the given endpoint directly into + the values dictionary passed. This is used internally and + automatically called on URL building. + + .. versionadded:: 0.7 + """ + names: t.Iterable[str | None] = (None,) + + # url_for may be called outside a request context, parse the + # passed endpoint instead of using request.blueprints. + if "." in endpoint: + names = chain( + names, reversed(_split_blueprint_path(endpoint.rpartition(".")[0])) + ) + + for name in names: + if name in self.url_default_functions: + for func in self.url_default_functions[name]: + func(endpoint, values) + + def handle_url_build_error( + self, error: BuildError, endpoint: str, values: dict[str, t.Any] + ) -> str: + """Called by :meth:`.url_for` if a + :exc:`~werkzeug.routing.BuildError` was raised. If this returns + a value, it will be returned by ``url_for``, otherwise the error + will be re-raised. + + Each function in :attr:`url_build_error_handlers` is called with + ``error``, ``endpoint`` and ``values``. If a function returns + ``None`` or raises a ``BuildError``, it is skipped. Otherwise, + its return value is returned by ``url_for``. + + :param error: The active ``BuildError`` being handled. + :param endpoint: The endpoint being built. + :param values: The keyword arguments passed to ``url_for``. + """ + for handler in self.url_build_error_handlers: + try: + rv = handler(error, endpoint, values) + except BuildError as e: + # make error available outside except block + error = e + else: + if rv is not None: + return rv + + # Re-raise if called with an active exception, otherwise raise + # the passed in exception. + if error is sys.exc_info()[1]: + raise + + raise error diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/sansio/blueprints.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/sansio/blueprints.py new file mode 100644 index 0000000..38c92f4 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/sansio/blueprints.py @@ -0,0 +1,626 @@ +from __future__ import annotations + +import os +import typing as t +from collections import defaultdict +from functools import update_wrapper + +from .. import typing as ft +from .scaffold import _endpoint_from_view_func +from .scaffold import _sentinel +from .scaffold import Scaffold +from .scaffold import setupmethod + +if t.TYPE_CHECKING: # pragma: no cover + from .app import App + +DeferredSetupFunction = t.Callable[["BlueprintSetupState"], t.Callable] +T_after_request = t.TypeVar("T_after_request", bound=ft.AfterRequestCallable) +T_before_request = t.TypeVar("T_before_request", bound=ft.BeforeRequestCallable) +T_error_handler = t.TypeVar("T_error_handler", bound=ft.ErrorHandlerCallable) +T_teardown = t.TypeVar("T_teardown", bound=ft.TeardownCallable) +T_template_context_processor = t.TypeVar( + "T_template_context_processor", bound=ft.TemplateContextProcessorCallable +) +T_template_filter = t.TypeVar("T_template_filter", bound=ft.TemplateFilterCallable) +T_template_global = t.TypeVar("T_template_global", bound=ft.TemplateGlobalCallable) +T_template_test = t.TypeVar("T_template_test", bound=ft.TemplateTestCallable) +T_url_defaults = t.TypeVar("T_url_defaults", bound=ft.URLDefaultCallable) +T_url_value_preprocessor = t.TypeVar( + "T_url_value_preprocessor", bound=ft.URLValuePreprocessorCallable +) + + +class BlueprintSetupState: + """Temporary holder object for registering a blueprint with the + application. An instance of this class is created by the + :meth:`~flask.Blueprint.make_setup_state` method and later passed + to all register callback functions. + """ + + def __init__( + self, + blueprint: Blueprint, + app: App, + options: t.Any, + first_registration: bool, + ) -> None: + #: a reference to the current application + self.app = app + + #: a reference to the blueprint that created this setup state. + self.blueprint = blueprint + + #: a dictionary with all options that were passed to the + #: :meth:`~flask.Flask.register_blueprint` method. + self.options = options + + #: as blueprints can be registered multiple times with the + #: application and not everything wants to be registered + #: multiple times on it, this attribute can be used to figure + #: out if the blueprint was registered in the past already. + self.first_registration = first_registration + + subdomain = self.options.get("subdomain") + if subdomain is None: + subdomain = self.blueprint.subdomain + + #: The subdomain that the blueprint should be active for, ``None`` + #: otherwise. + self.subdomain = subdomain + + url_prefix = self.options.get("url_prefix") + if url_prefix is None: + url_prefix = self.blueprint.url_prefix + #: The prefix that should be used for all URLs defined on the + #: blueprint. + self.url_prefix = url_prefix + + self.name = self.options.get("name", blueprint.name) + self.name_prefix = self.options.get("name_prefix", "") + + #: A dictionary with URL defaults that is added to each and every + #: URL that was defined with the blueprint. + self.url_defaults = dict(self.blueprint.url_values_defaults) + self.url_defaults.update(self.options.get("url_defaults", ())) + + def add_url_rule( + self, + rule: str, + endpoint: str | None = None, + view_func: t.Callable | None = None, + **options: t.Any, + ) -> None: + """A helper method to register a rule (and optionally a view function) + to the application. The endpoint is automatically prefixed with the + blueprint's name. + """ + if self.url_prefix is not None: + if rule: + rule = "/".join((self.url_prefix.rstrip("/"), rule.lstrip("/"))) + else: + rule = self.url_prefix + options.setdefault("subdomain", self.subdomain) + if endpoint is None: + endpoint = _endpoint_from_view_func(view_func) # type: ignore + defaults = self.url_defaults + if "defaults" in options: + defaults = dict(defaults, **options.pop("defaults")) + + self.app.add_url_rule( + rule, + f"{self.name_prefix}.{self.name}.{endpoint}".lstrip("."), + view_func, + defaults=defaults, + **options, + ) + + +class Blueprint(Scaffold): + """Represents a blueprint, a collection of routes and other + app-related functions that can be registered on a real application + later. + + A blueprint is an object that allows defining application functions + without requiring an application object ahead of time. It uses the + same decorators as :class:`~flask.Flask`, but defers the need for an + application by recording them for later registration. + + Decorating a function with a blueprint creates a deferred function + that is called with :class:`~flask.blueprints.BlueprintSetupState` + when the blueprint is registered on an application. + + See :doc:`/blueprints` for more information. + + :param name: The name of the blueprint. Will be prepended to each + endpoint name. + :param import_name: The name of the blueprint package, usually + ``__name__``. This helps locate the ``root_path`` for the + blueprint. + :param static_folder: A folder with static files that should be + served by the blueprint's static route. The path is relative to + the blueprint's root path. Blueprint static files are disabled + by default. + :param static_url_path: The url to serve static files from. + Defaults to ``static_folder``. If the blueprint does not have + a ``url_prefix``, the app's static route will take precedence, + and the blueprint's static files won't be accessible. + :param template_folder: A folder with templates that should be added + to the app's template search path. The path is relative to the + blueprint's root path. Blueprint templates are disabled by + default. Blueprint templates have a lower precedence than those + in the app's templates folder. + :param url_prefix: A path to prepend to all of the blueprint's URLs, + to make them distinct from the rest of the app's routes. + :param subdomain: A subdomain that blueprint routes will match on by + default. + :param url_defaults: A dict of default values that blueprint routes + will receive by default. + :param root_path: By default, the blueprint will automatically set + this based on ``import_name``. In certain situations this + automatic detection can fail, so the path can be specified + manually instead. + + .. versionchanged:: 1.1.0 + Blueprints have a ``cli`` group to register nested CLI commands. + The ``cli_group`` parameter controls the name of the group under + the ``flask`` command. + + .. versionadded:: 0.7 + """ + + _got_registered_once = False + + def __init__( + self, + name: str, + import_name: str, + static_folder: str | os.PathLike | None = None, + static_url_path: str | None = None, + template_folder: str | os.PathLike | None = None, + url_prefix: str | None = None, + subdomain: str | None = None, + url_defaults: dict | None = None, + root_path: str | None = None, + cli_group: str | None = _sentinel, # type: ignore + ): + super().__init__( + import_name=import_name, + static_folder=static_folder, + static_url_path=static_url_path, + template_folder=template_folder, + root_path=root_path, + ) + + if not name: + raise ValueError("'name' may not be empty.") + + if "." in name: + raise ValueError("'name' may not contain a dot '.' character.") + + self.name = name + self.url_prefix = url_prefix + self.subdomain = subdomain + self.deferred_functions: list[DeferredSetupFunction] = [] + + if url_defaults is None: + url_defaults = {} + + self.url_values_defaults = url_defaults + self.cli_group = cli_group + self._blueprints: list[tuple[Blueprint, dict]] = [] + + def _check_setup_finished(self, f_name: str) -> None: + if self._got_registered_once: + raise AssertionError( + f"The setup method '{f_name}' can no longer be called on the blueprint" + f" '{self.name}'. It has already been registered at least once, any" + " changes will not be applied consistently.\n" + "Make sure all imports, decorators, functions, etc. needed to set up" + " the blueprint are done before registering it." + ) + + @setupmethod + def record(self, func: t.Callable) -> None: + """Registers a function that is called when the blueprint is + registered on the application. This function is called with the + state as argument as returned by the :meth:`make_setup_state` + method. + """ + self.deferred_functions.append(func) + + @setupmethod + def record_once(self, func: t.Callable) -> None: + """Works like :meth:`record` but wraps the function in another + function that will ensure the function is only called once. If the + blueprint is registered a second time on the application, the + function passed is not called. + """ + + def wrapper(state: BlueprintSetupState) -> None: + if state.first_registration: + func(state) + + self.record(update_wrapper(wrapper, func)) + + def make_setup_state( + self, app: App, options: dict, first_registration: bool = False + ) -> BlueprintSetupState: + """Creates an instance of :meth:`~flask.blueprints.BlueprintSetupState` + object that is later passed to the register callback functions. + Subclasses can override this to return a subclass of the setup state. + """ + return BlueprintSetupState(self, app, options, first_registration) + + @setupmethod + def register_blueprint(self, blueprint: Blueprint, **options: t.Any) -> None: + """Register a :class:`~flask.Blueprint` on this blueprint. Keyword + arguments passed to this method will override the defaults set + on the blueprint. + + .. versionchanged:: 2.0.1 + The ``name`` option can be used to change the (pre-dotted) + name the blueprint is registered with. This allows the same + blueprint to be registered multiple times with unique names + for ``url_for``. + + .. versionadded:: 2.0 + """ + if blueprint is self: + raise ValueError("Cannot register a blueprint on itself") + self._blueprints.append((blueprint, options)) + + def register(self, app: App, options: dict) -> None: + """Called by :meth:`Flask.register_blueprint` to register all + views and callbacks registered on the blueprint with the + application. Creates a :class:`.BlueprintSetupState` and calls + each :meth:`record` callback with it. + + :param app: The application this blueprint is being registered + with. + :param options: Keyword arguments forwarded from + :meth:`~Flask.register_blueprint`. + + .. versionchanged:: 2.3 + Nested blueprints now correctly apply subdomains. + + .. versionchanged:: 2.1 + Registering the same blueprint with the same name multiple + times is an error. + + .. versionchanged:: 2.0.1 + Nested blueprints are registered with their dotted name. + This allows different blueprints with the same name to be + nested at different locations. + + .. versionchanged:: 2.0.1 + The ``name`` option can be used to change the (pre-dotted) + name the blueprint is registered with. This allows the same + blueprint to be registered multiple times with unique names + for ``url_for``. + """ + name_prefix = options.get("name_prefix", "") + self_name = options.get("name", self.name) + name = f"{name_prefix}.{self_name}".lstrip(".") + + if name in app.blueprints: + bp_desc = "this" if app.blueprints[name] is self else "a different" + existing_at = f" '{name}'" if self_name != name else "" + + raise ValueError( + f"The name '{self_name}' is already registered for" + f" {bp_desc} blueprint{existing_at}. Use 'name=' to" + f" provide a unique name." + ) + + first_bp_registration = not any(bp is self for bp in app.blueprints.values()) + first_name_registration = name not in app.blueprints + + app.blueprints[name] = self + self._got_registered_once = True + state = self.make_setup_state(app, options, first_bp_registration) + + if self.has_static_folder: + state.add_url_rule( + f"{self.static_url_path}/", + view_func=self.send_static_file, # type: ignore[attr-defined] + endpoint="static", + ) + + # Merge blueprint data into parent. + if first_bp_registration or first_name_registration: + self._merge_blueprint_funcs(app, name) + + for deferred in self.deferred_functions: + deferred(state) + + cli_resolved_group = options.get("cli_group", self.cli_group) + + if self.cli.commands: + if cli_resolved_group is None: + app.cli.commands.update(self.cli.commands) + elif cli_resolved_group is _sentinel: + self.cli.name = name + app.cli.add_command(self.cli) + else: + self.cli.name = cli_resolved_group + app.cli.add_command(self.cli) + + for blueprint, bp_options in self._blueprints: + bp_options = bp_options.copy() + bp_url_prefix = bp_options.get("url_prefix") + bp_subdomain = bp_options.get("subdomain") + + if bp_subdomain is None: + bp_subdomain = blueprint.subdomain + + if state.subdomain is not None and bp_subdomain is not None: + bp_options["subdomain"] = bp_subdomain + "." + state.subdomain + elif bp_subdomain is not None: + bp_options["subdomain"] = bp_subdomain + elif state.subdomain is not None: + bp_options["subdomain"] = state.subdomain + + if bp_url_prefix is None: + bp_url_prefix = blueprint.url_prefix + + if state.url_prefix is not None and bp_url_prefix is not None: + bp_options["url_prefix"] = ( + state.url_prefix.rstrip("/") + "/" + bp_url_prefix.lstrip("/") + ) + elif bp_url_prefix is not None: + bp_options["url_prefix"] = bp_url_prefix + elif state.url_prefix is not None: + bp_options["url_prefix"] = state.url_prefix + + bp_options["name_prefix"] = name + blueprint.register(app, bp_options) + + def _merge_blueprint_funcs(self, app: App, name: str) -> None: + def extend(bp_dict, parent_dict): + for key, values in bp_dict.items(): + key = name if key is None else f"{name}.{key}" + parent_dict[key].extend(values) + + for key, value in self.error_handler_spec.items(): + key = name if key is None else f"{name}.{key}" + value = defaultdict( + dict, + { + code: {exc_class: func for exc_class, func in code_values.items()} + for code, code_values in value.items() + }, + ) + app.error_handler_spec[key] = value + + for endpoint, func in self.view_functions.items(): + app.view_functions[endpoint] = func + + extend(self.before_request_funcs, app.before_request_funcs) + extend(self.after_request_funcs, app.after_request_funcs) + extend( + self.teardown_request_funcs, + app.teardown_request_funcs, + ) + extend(self.url_default_functions, app.url_default_functions) + extend(self.url_value_preprocessors, app.url_value_preprocessors) + extend(self.template_context_processors, app.template_context_processors) + + @setupmethod + def add_url_rule( + self, + rule: str, + endpoint: str | None = None, + view_func: ft.RouteCallable | None = None, + provide_automatic_options: bool | None = None, + **options: t.Any, + ) -> None: + """Register a URL rule with the blueprint. See :meth:`.Flask.add_url_rule` for + full documentation. + + The URL rule is prefixed with the blueprint's URL prefix. The endpoint name, + used with :func:`url_for`, is prefixed with the blueprint's name. + """ + if endpoint and "." in endpoint: + raise ValueError("'endpoint' may not contain a dot '.' character.") + + if view_func and hasattr(view_func, "__name__") and "." in view_func.__name__: + raise ValueError("'view_func' name may not contain a dot '.' character.") + + self.record( + lambda s: s.add_url_rule( + rule, + endpoint, + view_func, + provide_automatic_options=provide_automatic_options, + **options, + ) + ) + + @setupmethod + def app_template_filter( + self, name: str | None = None + ) -> t.Callable[[T_template_filter], T_template_filter]: + """Register a template filter, available in any template rendered by the + application. Equivalent to :meth:`.Flask.template_filter`. + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + + def decorator(f: T_template_filter) -> T_template_filter: + self.add_app_template_filter(f, name=name) + return f + + return decorator + + @setupmethod + def add_app_template_filter( + self, f: ft.TemplateFilterCallable, name: str | None = None + ) -> None: + """Register a template filter, available in any template rendered by the + application. Works like the :meth:`app_template_filter` decorator. Equivalent to + :meth:`.Flask.add_template_filter`. + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + + def register_template(state: BlueprintSetupState) -> None: + state.app.jinja_env.filters[name or f.__name__] = f + + self.record_once(register_template) + + @setupmethod + def app_template_test( + self, name: str | None = None + ) -> t.Callable[[T_template_test], T_template_test]: + """Register a template test, available in any template rendered by the + application. Equivalent to :meth:`.Flask.template_test`. + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + + def decorator(f: T_template_test) -> T_template_test: + self.add_app_template_test(f, name=name) + return f + + return decorator + + @setupmethod + def add_app_template_test( + self, f: ft.TemplateTestCallable, name: str | None = None + ) -> None: + """Register a template test, available in any template rendered by the + application. Works like the :meth:`app_template_test` decorator. Equivalent to + :meth:`.Flask.add_template_test`. + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + + def register_template(state: BlueprintSetupState) -> None: + state.app.jinja_env.tests[name or f.__name__] = f + + self.record_once(register_template) + + @setupmethod + def app_template_global( + self, name: str | None = None + ) -> t.Callable[[T_template_global], T_template_global]: + """Register a template global, available in any template rendered by the + application. Equivalent to :meth:`.Flask.template_global`. + + .. versionadded:: 0.10 + + :param name: the optional name of the global, otherwise the + function name will be used. + """ + + def decorator(f: T_template_global) -> T_template_global: + self.add_app_template_global(f, name=name) + return f + + return decorator + + @setupmethod + def add_app_template_global( + self, f: ft.TemplateGlobalCallable, name: str | None = None + ) -> None: + """Register a template global, available in any template rendered by the + application. Works like the :meth:`app_template_global` decorator. Equivalent to + :meth:`.Flask.add_template_global`. + + .. versionadded:: 0.10 + + :param name: the optional name of the global, otherwise the + function name will be used. + """ + + def register_template(state: BlueprintSetupState) -> None: + state.app.jinja_env.globals[name or f.__name__] = f + + self.record_once(register_template) + + @setupmethod + def before_app_request(self, f: T_before_request) -> T_before_request: + """Like :meth:`before_request`, but before every request, not only those handled + by the blueprint. Equivalent to :meth:`.Flask.before_request`. + """ + self.record_once( + lambda s: s.app.before_request_funcs.setdefault(None, []).append(f) + ) + return f + + @setupmethod + def after_app_request(self, f: T_after_request) -> T_after_request: + """Like :meth:`after_request`, but after every request, not only those handled + by the blueprint. Equivalent to :meth:`.Flask.after_request`. + """ + self.record_once( + lambda s: s.app.after_request_funcs.setdefault(None, []).append(f) + ) + return f + + @setupmethod + def teardown_app_request(self, f: T_teardown) -> T_teardown: + """Like :meth:`teardown_request`, but after every request, not only those + handled by the blueprint. Equivalent to :meth:`.Flask.teardown_request`. + """ + self.record_once( + lambda s: s.app.teardown_request_funcs.setdefault(None, []).append(f) + ) + return f + + @setupmethod + def app_context_processor( + self, f: T_template_context_processor + ) -> T_template_context_processor: + """Like :meth:`context_processor`, but for templates rendered by every view, not + only by the blueprint. Equivalent to :meth:`.Flask.context_processor`. + """ + self.record_once( + lambda s: s.app.template_context_processors.setdefault(None, []).append(f) + ) + return f + + @setupmethod + def app_errorhandler( + self, code: type[Exception] | int + ) -> t.Callable[[T_error_handler], T_error_handler]: + """Like :meth:`errorhandler`, but for every request, not only those handled by + the blueprint. Equivalent to :meth:`.Flask.errorhandler`. + """ + + def decorator(f: T_error_handler) -> T_error_handler: + self.record_once(lambda s: s.app.errorhandler(code)(f)) + return f + + return decorator + + @setupmethod + def app_url_value_preprocessor( + self, f: T_url_value_preprocessor + ) -> T_url_value_preprocessor: + """Like :meth:`url_value_preprocessor`, but for every request, not only those + handled by the blueprint. Equivalent to :meth:`.Flask.url_value_preprocessor`. + """ + self.record_once( + lambda s: s.app.url_value_preprocessors.setdefault(None, []).append(f) + ) + return f + + @setupmethod + def app_url_defaults(self, f: T_url_defaults) -> T_url_defaults: + """Like :meth:`url_defaults`, but for every request, not only those handled by + the blueprint. Equivalent to :meth:`.Flask.url_defaults`. + """ + self.record_once( + lambda s: s.app.url_default_functions.setdefault(None, []).append(f) + ) + return f diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/sansio/scaffold.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/sansio/scaffold.py new file mode 100644 index 0000000..a43f6fd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/sansio/scaffold.py @@ -0,0 +1,802 @@ +from __future__ import annotations + +import importlib.util +import os +import pathlib +import sys +import typing as t +from collections import defaultdict +from functools import update_wrapper + +from jinja2 import FileSystemLoader +from werkzeug.exceptions import default_exceptions +from werkzeug.exceptions import HTTPException +from werkzeug.utils import cached_property + +from .. import typing as ft +from ..cli import AppGroup +from ..helpers import get_root_path +from ..templating import _default_template_ctx_processor + +# a singleton sentinel value for parameter defaults +_sentinel = object() + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) +T_after_request = t.TypeVar("T_after_request", bound=ft.AfterRequestCallable) +T_before_request = t.TypeVar("T_before_request", bound=ft.BeforeRequestCallable) +T_error_handler = t.TypeVar("T_error_handler", bound=ft.ErrorHandlerCallable) +T_teardown = t.TypeVar("T_teardown", bound=ft.TeardownCallable) +T_template_context_processor = t.TypeVar( + "T_template_context_processor", bound=ft.TemplateContextProcessorCallable +) +T_url_defaults = t.TypeVar("T_url_defaults", bound=ft.URLDefaultCallable) +T_url_value_preprocessor = t.TypeVar( + "T_url_value_preprocessor", bound=ft.URLValuePreprocessorCallable +) +T_route = t.TypeVar("T_route", bound=ft.RouteCallable) + + +def setupmethod(f: F) -> F: + f_name = f.__name__ + + def wrapper_func(self, *args: t.Any, **kwargs: t.Any) -> t.Any: + self._check_setup_finished(f_name) + return f(self, *args, **kwargs) + + return t.cast(F, update_wrapper(wrapper_func, f)) + + +class Scaffold: + """Common behavior shared between :class:`~flask.Flask` and + :class:`~flask.blueprints.Blueprint`. + + :param import_name: The import name of the module where this object + is defined. Usually :attr:`__name__` should be used. + :param static_folder: Path to a folder of static files to serve. + If this is set, a static route will be added. + :param static_url_path: URL prefix for the static route. + :param template_folder: Path to a folder containing template files. + for rendering. If this is set, a Jinja loader will be added. + :param root_path: The path that static, template, and resource files + are relative to. Typically not set, it is discovered based on + the ``import_name``. + + .. versionadded:: 2.0 + """ + + name: str + _static_folder: str | None = None + _static_url_path: str | None = None + + def __init__( + self, + import_name: str, + static_folder: str | os.PathLike | None = None, + static_url_path: str | None = None, + template_folder: str | os.PathLike | None = None, + root_path: str | None = None, + ): + #: The name of the package or module that this object belongs + #: to. Do not change this once it is set by the constructor. + self.import_name = import_name + + self.static_folder = static_folder # type: ignore + self.static_url_path = static_url_path + + #: The path to the templates folder, relative to + #: :attr:`root_path`, to add to the template loader. ``None`` if + #: templates should not be added. + self.template_folder = template_folder + + if root_path is None: + root_path = get_root_path(self.import_name) + + #: Absolute path to the package on the filesystem. Used to look + #: up resources contained in the package. + self.root_path = root_path + + #: The Click command group for registering CLI commands for this + #: object. The commands are available from the ``flask`` command + #: once the application has been discovered and blueprints have + #: been registered. + self.cli = AppGroup() + + #: A dictionary mapping endpoint names to view functions. + #: + #: To register a view function, use the :meth:`route` decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.view_functions: dict[str, t.Callable] = {} + + #: A data structure of registered error handlers, in the format + #: ``{scope: {code: {class: handler}}}``. The ``scope`` key is + #: the name of a blueprint the handlers are active for, or + #: ``None`` for all requests. The ``code`` key is the HTTP + #: status code for ``HTTPException``, or ``None`` for + #: other exceptions. The innermost dictionary maps exception + #: classes to handler functions. + #: + #: To register an error handler, use the :meth:`errorhandler` + #: decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.error_handler_spec: dict[ + ft.AppOrBlueprintKey, + dict[int | None, dict[type[Exception], ft.ErrorHandlerCallable]], + ] = defaultdict(lambda: defaultdict(dict)) + + #: A data structure of functions to call at the beginning of + #: each request, in the format ``{scope: [functions]}``. The + #: ``scope`` key is the name of a blueprint the functions are + #: active for, or ``None`` for all requests. + #: + #: To register a function, use the :meth:`before_request` + #: decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.before_request_funcs: dict[ + ft.AppOrBlueprintKey, list[ft.BeforeRequestCallable] + ] = defaultdict(list) + + #: A data structure of functions to call at the end of each + #: request, in the format ``{scope: [functions]}``. The + #: ``scope`` key is the name of a blueprint the functions are + #: active for, or ``None`` for all requests. + #: + #: To register a function, use the :meth:`after_request` + #: decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.after_request_funcs: dict[ + ft.AppOrBlueprintKey, list[ft.AfterRequestCallable] + ] = defaultdict(list) + + #: A data structure of functions to call at the end of each + #: request even if an exception is raised, in the format + #: ``{scope: [functions]}``. The ``scope`` key is the name of a + #: blueprint the functions are active for, or ``None`` for all + #: requests. + #: + #: To register a function, use the :meth:`teardown_request` + #: decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.teardown_request_funcs: dict[ + ft.AppOrBlueprintKey, list[ft.TeardownCallable] + ] = defaultdict(list) + + #: A data structure of functions to call to pass extra context + #: values when rendering templates, in the format + #: ``{scope: [functions]}``. The ``scope`` key is the name of a + #: blueprint the functions are active for, or ``None`` for all + #: requests. + #: + #: To register a function, use the :meth:`context_processor` + #: decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.template_context_processors: dict[ + ft.AppOrBlueprintKey, list[ft.TemplateContextProcessorCallable] + ] = defaultdict(list, {None: [_default_template_ctx_processor]}) + + #: A data structure of functions to call to modify the keyword + #: arguments passed to the view function, in the format + #: ``{scope: [functions]}``. The ``scope`` key is the name of a + #: blueprint the functions are active for, or ``None`` for all + #: requests. + #: + #: To register a function, use the + #: :meth:`url_value_preprocessor` decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.url_value_preprocessors: dict[ + ft.AppOrBlueprintKey, + list[ft.URLValuePreprocessorCallable], + ] = defaultdict(list) + + #: A data structure of functions to call to modify the keyword + #: arguments when generating URLs, in the format + #: ``{scope: [functions]}``. The ``scope`` key is the name of a + #: blueprint the functions are active for, or ``None`` for all + #: requests. + #: + #: To register a function, use the :meth:`url_defaults` + #: decorator. + #: + #: This data structure is internal. It should not be modified + #: directly and its format may change at any time. + self.url_default_functions: dict[ + ft.AppOrBlueprintKey, list[ft.URLDefaultCallable] + ] = defaultdict(list) + + def __repr__(self) -> str: + return f"<{type(self).__name__} {self.name!r}>" + + def _check_setup_finished(self, f_name: str) -> None: + raise NotImplementedError + + @property + def static_folder(self) -> str | None: + """The absolute path to the configured static folder. ``None`` + if no static folder is set. + """ + if self._static_folder is not None: + return os.path.join(self.root_path, self._static_folder) + else: + return None + + @static_folder.setter + def static_folder(self, value: str | os.PathLike | None) -> None: + if value is not None: + value = os.fspath(value).rstrip(r"\/") + + self._static_folder = value + + @property + def has_static_folder(self) -> bool: + """``True`` if :attr:`static_folder` is set. + + .. versionadded:: 0.5 + """ + return self.static_folder is not None + + @property + def static_url_path(self) -> str | None: + """The URL prefix that the static route will be accessible from. + + If it was not configured during init, it is derived from + :attr:`static_folder`. + """ + if self._static_url_path is not None: + return self._static_url_path + + if self.static_folder is not None: + basename = os.path.basename(self.static_folder) + return f"/{basename}".rstrip("/") + + return None + + @static_url_path.setter + def static_url_path(self, value: str | None) -> None: + if value is not None: + value = value.rstrip("/") + + self._static_url_path = value + + @cached_property + def jinja_loader(self) -> FileSystemLoader | None: + """The Jinja loader for this object's templates. By default this + is a class :class:`jinja2.loaders.FileSystemLoader` to + :attr:`template_folder` if it is set. + + .. versionadded:: 0.5 + """ + if self.template_folder is not None: + return FileSystemLoader(os.path.join(self.root_path, self.template_folder)) + else: + return None + + def _method_route( + self, + method: str, + rule: str, + options: dict, + ) -> t.Callable[[T_route], T_route]: + if "methods" in options: + raise TypeError("Use the 'route' decorator to use the 'methods' argument.") + + return self.route(rule, methods=[method], **options) + + @setupmethod + def get(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: + """Shortcut for :meth:`route` with ``methods=["GET"]``. + + .. versionadded:: 2.0 + """ + return self._method_route("GET", rule, options) + + @setupmethod + def post(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: + """Shortcut for :meth:`route` with ``methods=["POST"]``. + + .. versionadded:: 2.0 + """ + return self._method_route("POST", rule, options) + + @setupmethod + def put(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: + """Shortcut for :meth:`route` with ``methods=["PUT"]``. + + .. versionadded:: 2.0 + """ + return self._method_route("PUT", rule, options) + + @setupmethod + def delete(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: + """Shortcut for :meth:`route` with ``methods=["DELETE"]``. + + .. versionadded:: 2.0 + """ + return self._method_route("DELETE", rule, options) + + @setupmethod + def patch(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: + """Shortcut for :meth:`route` with ``methods=["PATCH"]``. + + .. versionadded:: 2.0 + """ + return self._method_route("PATCH", rule, options) + + @setupmethod + def route(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]: + """Decorate a view function to register it with the given URL + rule and options. Calls :meth:`add_url_rule`, which has more + details about the implementation. + + .. code-block:: python + + @app.route("/") + def index(): + return "Hello, World!" + + See :ref:`url-route-registrations`. + + The endpoint name for the route defaults to the name of the view + function if the ``endpoint`` parameter isn't passed. + + The ``methods`` parameter defaults to ``["GET"]``. ``HEAD`` and + ``OPTIONS`` are added automatically. + + :param rule: The URL rule string. + :param options: Extra options passed to the + :class:`~werkzeug.routing.Rule` object. + """ + + def decorator(f: T_route) -> T_route: + endpoint = options.pop("endpoint", None) + self.add_url_rule(rule, endpoint, f, **options) + return f + + return decorator + + @setupmethod + def add_url_rule( + self, + rule: str, + endpoint: str | None = None, + view_func: ft.RouteCallable | None = None, + provide_automatic_options: bool | None = None, + **options: t.Any, + ) -> None: + """Register a rule for routing incoming requests and building + URLs. The :meth:`route` decorator is a shortcut to call this + with the ``view_func`` argument. These are equivalent: + + .. code-block:: python + + @app.route("/") + def index(): + ... + + .. code-block:: python + + def index(): + ... + + app.add_url_rule("/", view_func=index) + + See :ref:`url-route-registrations`. + + The endpoint name for the route defaults to the name of the view + function if the ``endpoint`` parameter isn't passed. An error + will be raised if a function has already been registered for the + endpoint. + + The ``methods`` parameter defaults to ``["GET"]``. ``HEAD`` is + always added automatically, and ``OPTIONS`` is added + automatically by default. + + ``view_func`` does not necessarily need to be passed, but if the + rule should participate in routing an endpoint name must be + associated with a view function at some point with the + :meth:`endpoint` decorator. + + .. code-block:: python + + app.add_url_rule("/", endpoint="index") + + @app.endpoint("index") + def index(): + ... + + If ``view_func`` has a ``required_methods`` attribute, those + methods are added to the passed and automatic methods. If it + has a ``provide_automatic_methods`` attribute, it is used as the + default if the parameter is not passed. + + :param rule: The URL rule string. + :param endpoint: The endpoint name to associate with the rule + and view function. Used when routing and building URLs. + Defaults to ``view_func.__name__``. + :param view_func: The view function to associate with the + endpoint name. + :param provide_automatic_options: Add the ``OPTIONS`` method and + respond to ``OPTIONS`` requests automatically. + :param options: Extra options passed to the + :class:`~werkzeug.routing.Rule` object. + """ + raise NotImplementedError + + @setupmethod + def endpoint(self, endpoint: str) -> t.Callable[[F], F]: + """Decorate a view function to register it for the given + endpoint. Used if a rule is added without a ``view_func`` with + :meth:`add_url_rule`. + + .. code-block:: python + + app.add_url_rule("/ex", endpoint="example") + + @app.endpoint("example") + def example(): + ... + + :param endpoint: The endpoint name to associate with the view + function. + """ + + def decorator(f: F) -> F: + self.view_functions[endpoint] = f + return f + + return decorator + + @setupmethod + def before_request(self, f: T_before_request) -> T_before_request: + """Register a function to run before each request. + + For example, this can be used to open a database connection, or + to load the logged in user from the session. + + .. code-block:: python + + @app.before_request + def load_user(): + if "user_id" in session: + g.user = db.session.get(session["user_id"]) + + The function will be called without any arguments. If it returns + a non-``None`` value, the value is handled as if it was the + return value from the view, and further request handling is + stopped. + + This is available on both app and blueprint objects. When used on an app, this + executes before every request. When used on a blueprint, this executes before + every request that the blueprint handles. To register with a blueprint and + execute before every request, use :meth:`.Blueprint.before_app_request`. + """ + self.before_request_funcs.setdefault(None, []).append(f) + return f + + @setupmethod + def after_request(self, f: T_after_request) -> T_after_request: + """Register a function to run after each request to this object. + + The function is called with the response object, and must return + a response object. This allows the functions to modify or + replace the response before it is sent. + + If a function raises an exception, any remaining + ``after_request`` functions will not be called. Therefore, this + should not be used for actions that must execute, such as to + close resources. Use :meth:`teardown_request` for that. + + This is available on both app and blueprint objects. When used on an app, this + executes after every request. When used on a blueprint, this executes after + every request that the blueprint handles. To register with a blueprint and + execute after every request, use :meth:`.Blueprint.after_app_request`. + """ + self.after_request_funcs.setdefault(None, []).append(f) + return f + + @setupmethod + def teardown_request(self, f: T_teardown) -> T_teardown: + """Register a function to be called when the request context is + popped. Typically this happens at the end of each request, but + contexts may be pushed manually as well during testing. + + .. code-block:: python + + with app.test_request_context(): + ... + + When the ``with`` block exits (or ``ctx.pop()`` is called), the + teardown functions are called just before the request context is + made inactive. + + When a teardown function was called because of an unhandled + exception it will be passed an error object. If an + :meth:`errorhandler` is registered, it will handle the exception + and the teardown will not receive it. + + Teardown functions must avoid raising exceptions. If they + execute code that might fail they must surround that code with a + ``try``/``except`` block and log any errors. + + The return values of teardown functions are ignored. + + This is available on both app and blueprint objects. When used on an app, this + executes after every request. When used on a blueprint, this executes after + every request that the blueprint handles. To register with a blueprint and + execute after every request, use :meth:`.Blueprint.teardown_app_request`. + """ + self.teardown_request_funcs.setdefault(None, []).append(f) + return f + + @setupmethod + def context_processor( + self, + f: T_template_context_processor, + ) -> T_template_context_processor: + """Registers a template context processor function. These functions run before + rendering a template. The keys of the returned dict are added as variables + available in the template. + + This is available on both app and blueprint objects. When used on an app, this + is called for every rendered template. When used on a blueprint, this is called + for templates rendered from the blueprint's views. To register with a blueprint + and affect every template, use :meth:`.Blueprint.app_context_processor`. + """ + self.template_context_processors[None].append(f) + return f + + @setupmethod + def url_value_preprocessor( + self, + f: T_url_value_preprocessor, + ) -> T_url_value_preprocessor: + """Register a URL value preprocessor function for all view + functions in the application. These functions will be called before the + :meth:`before_request` functions. + + The function can modify the values captured from the matched url before + they are passed to the view. For example, this can be used to pop a + common language code value and place it in ``g`` rather than pass it to + every view. + + The function is passed the endpoint name and values dict. The return + value is ignored. + + This is available on both app and blueprint objects. When used on an app, this + is called for every request. When used on a blueprint, this is called for + requests that the blueprint handles. To register with a blueprint and affect + every request, use :meth:`.Blueprint.app_url_value_preprocessor`. + """ + self.url_value_preprocessors[None].append(f) + return f + + @setupmethod + def url_defaults(self, f: T_url_defaults) -> T_url_defaults: + """Callback function for URL defaults for all view functions of the + application. It's called with the endpoint and values and should + update the values passed in place. + + This is available on both app and blueprint objects. When used on an app, this + is called for every request. When used on a blueprint, this is called for + requests that the blueprint handles. To register with a blueprint and affect + every request, use :meth:`.Blueprint.app_url_defaults`. + """ + self.url_default_functions[None].append(f) + return f + + @setupmethod + def errorhandler( + self, code_or_exception: type[Exception] | int + ) -> t.Callable[[T_error_handler], T_error_handler]: + """Register a function to handle errors by code or exception class. + + A decorator that is used to register a function given an + error code. Example:: + + @app.errorhandler(404) + def page_not_found(error): + return 'This page does not exist', 404 + + You can also register handlers for arbitrary exceptions:: + + @app.errorhandler(DatabaseError) + def special_exception_handler(error): + return 'Database connection failed', 500 + + This is available on both app and blueprint objects. When used on an app, this + can handle errors from every request. When used on a blueprint, this can handle + errors from requests that the blueprint handles. To register with a blueprint + and affect every request, use :meth:`.Blueprint.app_errorhandler`. + + .. versionadded:: 0.7 + Use :meth:`register_error_handler` instead of modifying + :attr:`error_handler_spec` directly, for application wide error + handlers. + + .. versionadded:: 0.7 + One can now additionally also register custom exception types + that do not necessarily have to be a subclass of the + :class:`~werkzeug.exceptions.HTTPException` class. + + :param code_or_exception: the code as integer for the handler, or + an arbitrary exception + """ + + def decorator(f: T_error_handler) -> T_error_handler: + self.register_error_handler(code_or_exception, f) + return f + + return decorator + + @setupmethod + def register_error_handler( + self, + code_or_exception: type[Exception] | int, + f: ft.ErrorHandlerCallable, + ) -> None: + """Alternative error attach function to the :meth:`errorhandler` + decorator that is more straightforward to use for non decorator + usage. + + .. versionadded:: 0.7 + """ + exc_class, code = self._get_exc_class_and_code(code_or_exception) + self.error_handler_spec[None][code][exc_class] = f + + @staticmethod + def _get_exc_class_and_code( + exc_class_or_code: type[Exception] | int, + ) -> tuple[type[Exception], int | None]: + """Get the exception class being handled. For HTTP status codes + or ``HTTPException`` subclasses, return both the exception and + status code. + + :param exc_class_or_code: Any exception class, or an HTTP status + code as an integer. + """ + exc_class: type[Exception] + + if isinstance(exc_class_or_code, int): + try: + exc_class = default_exceptions[exc_class_or_code] + except KeyError: + raise ValueError( + f"'{exc_class_or_code}' is not a recognized HTTP" + " error code. Use a subclass of HTTPException with" + " that code instead." + ) from None + else: + exc_class = exc_class_or_code + + if isinstance(exc_class, Exception): + raise TypeError( + f"{exc_class!r} is an instance, not a class. Handlers" + " can only be registered for Exception classes or HTTP" + " error codes." + ) + + if not issubclass(exc_class, Exception): + raise ValueError( + f"'{exc_class.__name__}' is not a subclass of Exception." + " Handlers can only be registered for Exception classes" + " or HTTP error codes." + ) + + if issubclass(exc_class, HTTPException): + return exc_class, exc_class.code + else: + return exc_class, None + + +def _endpoint_from_view_func(view_func: t.Callable) -> str: + """Internal helper that returns the default endpoint for a given + function. This always is the function name. + """ + assert view_func is not None, "expected view func if endpoint is not provided." + return view_func.__name__ + + +def _path_is_relative_to(path: pathlib.PurePath, base: str) -> bool: + # Path.is_relative_to doesn't exist until Python 3.9 + try: + path.relative_to(base) + return True + except ValueError: + return False + + +def _find_package_path(import_name): + """Find the path that contains the package or module.""" + root_mod_name, _, _ = import_name.partition(".") + + try: + root_spec = importlib.util.find_spec(root_mod_name) + + if root_spec is None: + raise ValueError("not found") + except (ImportError, ValueError): + # ImportError: the machinery told us it does not exist + # ValueError: + # - the module name was invalid + # - the module name is __main__ + # - we raised `ValueError` due to `root_spec` being `None` + return os.getcwd() + + if root_spec.origin in {"namespace", None}: + # namespace package + package_spec = importlib.util.find_spec(import_name) + + if package_spec is not None and package_spec.submodule_search_locations: + # Pick the path in the namespace that contains the submodule. + package_path = pathlib.Path( + os.path.commonpath(package_spec.submodule_search_locations) + ) + search_location = next( + location + for location in root_spec.submodule_search_locations + if _path_is_relative_to(package_path, location) + ) + else: + # Pick the first path. + search_location = root_spec.submodule_search_locations[0] + + return os.path.dirname(search_location) + elif root_spec.submodule_search_locations: + # package with __init__.py + return os.path.dirname(os.path.dirname(root_spec.origin)) + else: + # module + return os.path.dirname(root_spec.origin) + + +def find_package(import_name: str): + """Find the prefix that a package is installed under, and the path + that it would be imported from. + + The prefix is the directory containing the standard directory + hierarchy (lib, bin, etc.). If the package is not installed to the + system (:attr:`sys.prefix`) or a virtualenv (``site-packages``), + ``None`` is returned. + + The path is the entry in :attr:`sys.path` that contains the package + for import. If the package is not installed, it's assumed that the + package was imported from the current working directory. + """ + package_path = _find_package_path(import_name) + py_prefix = os.path.abspath(sys.prefix) + + # installed to the system + if _path_is_relative_to(pathlib.PurePath(package_path), py_prefix): + return py_prefix, package_path + + site_parent, site_folder = os.path.split(package_path) + + # installed to a virtualenv + if site_folder.lower() == "site-packages": + parent, folder = os.path.split(site_parent) + + # Windows (prefix/lib/site-packages) + if folder.lower() == "lib": + return parent, package_path + + # Unix (prefix/lib/pythonX.Y/site-packages) + if os.path.basename(parent).lower() == "lib": + return os.path.dirname(parent), package_path + + # something else (prefix/site-packages) + return site_parent, package_path + + # not installed + return None, package_path diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/sessions.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/sessions.py new file mode 100644 index 0000000..e5650d6 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/sessions.py @@ -0,0 +1,367 @@ +from __future__ import annotations + +import hashlib +import typing as t +from collections.abc import MutableMapping +from datetime import datetime +from datetime import timezone + +from itsdangerous import BadSignature +from itsdangerous import URLSafeTimedSerializer +from werkzeug.datastructures import CallbackDict + +from .json.tag import TaggedJSONSerializer + +if t.TYPE_CHECKING: # pragma: no cover + from .app import Flask + from .wrappers import Request, Response + + +class SessionMixin(MutableMapping): + """Expands a basic dictionary with session attributes.""" + + @property + def permanent(self) -> bool: + """This reflects the ``'_permanent'`` key in the dict.""" + return self.get("_permanent", False) + + @permanent.setter + def permanent(self, value: bool) -> None: + self["_permanent"] = bool(value) + + #: Some implementations can detect whether a session is newly + #: created, but that is not guaranteed. Use with caution. The mixin + # default is hard-coded ``False``. + new = False + + #: Some implementations can detect changes to the session and set + #: this when that happens. The mixin default is hard coded to + #: ``True``. + modified = True + + #: Some implementations can detect when session data is read or + #: written and set this when that happens. The mixin default is hard + #: coded to ``True``. + accessed = True + + +class SecureCookieSession(CallbackDict, SessionMixin): + """Base class for sessions based on signed cookies. + + This session backend will set the :attr:`modified` and + :attr:`accessed` attributes. It cannot reliably track whether a + session is new (vs. empty), so :attr:`new` remains hard coded to + ``False``. + """ + + #: When data is changed, this is set to ``True``. Only the session + #: dictionary itself is tracked; if the session contains mutable + #: data (for example a nested dict) then this must be set to + #: ``True`` manually when modifying that data. The session cookie + #: will only be written to the response if this is ``True``. + modified = False + + #: When data is read or written, this is set to ``True``. Used by + # :class:`.SecureCookieSessionInterface` to add a ``Vary: Cookie`` + #: header, which allows caching proxies to cache different pages for + #: different users. + accessed = False + + def __init__(self, initial: t.Any = None) -> None: + def on_update(self) -> None: + self.modified = True + self.accessed = True + + super().__init__(initial, on_update) + + def __getitem__(self, key: str) -> t.Any: + self.accessed = True + return super().__getitem__(key) + + def get(self, key: str, default: t.Any = None) -> t.Any: + self.accessed = True + return super().get(key, default) + + def setdefault(self, key: str, default: t.Any = None) -> t.Any: + self.accessed = True + return super().setdefault(key, default) + + +class NullSession(SecureCookieSession): + """Class used to generate nicer error messages if sessions are not + available. Will still allow read-only access to the empty session + but fail on setting. + """ + + def _fail(self, *args: t.Any, **kwargs: t.Any) -> t.NoReturn: + raise RuntimeError( + "The session is unavailable because no secret " + "key was set. Set the secret_key on the " + "application to something unique and secret." + ) + + __setitem__ = __delitem__ = clear = pop = popitem = update = setdefault = _fail # type: ignore # noqa: B950 + del _fail + + +class SessionInterface: + """The basic interface you have to implement in order to replace the + default session interface which uses werkzeug's securecookie + implementation. The only methods you have to implement are + :meth:`open_session` and :meth:`save_session`, the others have + useful defaults which you don't need to change. + + The session object returned by the :meth:`open_session` method has to + provide a dictionary like interface plus the properties and methods + from the :class:`SessionMixin`. We recommend just subclassing a dict + and adding that mixin:: + + class Session(dict, SessionMixin): + pass + + If :meth:`open_session` returns ``None`` Flask will call into + :meth:`make_null_session` to create a session that acts as replacement + if the session support cannot work because some requirement is not + fulfilled. The default :class:`NullSession` class that is created + will complain that the secret key was not set. + + To replace the session interface on an application all you have to do + is to assign :attr:`flask.Flask.session_interface`:: + + app = Flask(__name__) + app.session_interface = MySessionInterface() + + Multiple requests with the same session may be sent and handled + concurrently. When implementing a new session interface, consider + whether reads or writes to the backing store must be synchronized. + There is no guarantee on the order in which the session for each + request is opened or saved, it will occur in the order that requests + begin and end processing. + + .. versionadded:: 0.8 + """ + + #: :meth:`make_null_session` will look here for the class that should + #: be created when a null session is requested. Likewise the + #: :meth:`is_null_session` method will perform a typecheck against + #: this type. + null_session_class = NullSession + + #: A flag that indicates if the session interface is pickle based. + #: This can be used by Flask extensions to make a decision in regards + #: to how to deal with the session object. + #: + #: .. versionadded:: 0.10 + pickle_based = False + + def make_null_session(self, app: Flask) -> NullSession: + """Creates a null session which acts as a replacement object if the + real session support could not be loaded due to a configuration + error. This mainly aids the user experience because the job of the + null session is to still support lookup without complaining but + modifications are answered with a helpful error message of what + failed. + + This creates an instance of :attr:`null_session_class` by default. + """ + return self.null_session_class() + + def is_null_session(self, obj: object) -> bool: + """Checks if a given object is a null session. Null sessions are + not asked to be saved. + + This checks if the object is an instance of :attr:`null_session_class` + by default. + """ + return isinstance(obj, self.null_session_class) + + def get_cookie_name(self, app: Flask) -> str: + """The name of the session cookie. Uses``app.config["SESSION_COOKIE_NAME"]``.""" + return app.config["SESSION_COOKIE_NAME"] + + def get_cookie_domain(self, app: Flask) -> str | None: + """The value of the ``Domain`` parameter on the session cookie. If not set, + browsers will only send the cookie to the exact domain it was set from. + Otherwise, they will send it to any subdomain of the given value as well. + + Uses the :data:`SESSION_COOKIE_DOMAIN` config. + + .. versionchanged:: 2.3 + Not set by default, does not fall back to ``SERVER_NAME``. + """ + rv = app.config["SESSION_COOKIE_DOMAIN"] + return rv if rv else None + + def get_cookie_path(self, app: Flask) -> str: + """Returns the path for which the cookie should be valid. The + default implementation uses the value from the ``SESSION_COOKIE_PATH`` + config var if it's set, and falls back to ``APPLICATION_ROOT`` or + uses ``/`` if it's ``None``. + """ + return app.config["SESSION_COOKIE_PATH"] or app.config["APPLICATION_ROOT"] + + def get_cookie_httponly(self, app: Flask) -> bool: + """Returns True if the session cookie should be httponly. This + currently just returns the value of the ``SESSION_COOKIE_HTTPONLY`` + config var. + """ + return app.config["SESSION_COOKIE_HTTPONLY"] + + def get_cookie_secure(self, app: Flask) -> bool: + """Returns True if the cookie should be secure. This currently + just returns the value of the ``SESSION_COOKIE_SECURE`` setting. + """ + return app.config["SESSION_COOKIE_SECURE"] + + def get_cookie_samesite(self, app: Flask) -> str: + """Return ``'Strict'`` or ``'Lax'`` if the cookie should use the + ``SameSite`` attribute. This currently just returns the value of + the :data:`SESSION_COOKIE_SAMESITE` setting. + """ + return app.config["SESSION_COOKIE_SAMESITE"] + + def get_expiration_time(self, app: Flask, session: SessionMixin) -> datetime | None: + """A helper method that returns an expiration date for the session + or ``None`` if the session is linked to the browser session. The + default implementation returns now + the permanent session + lifetime configured on the application. + """ + if session.permanent: + return datetime.now(timezone.utc) + app.permanent_session_lifetime + return None + + def should_set_cookie(self, app: Flask, session: SessionMixin) -> bool: + """Used by session backends to determine if a ``Set-Cookie`` header + should be set for this session cookie for this response. If the session + has been modified, the cookie is set. If the session is permanent and + the ``SESSION_REFRESH_EACH_REQUEST`` config is true, the cookie is + always set. + + This check is usually skipped if the session was deleted. + + .. versionadded:: 0.11 + """ + + return session.modified or ( + session.permanent and app.config["SESSION_REFRESH_EACH_REQUEST"] + ) + + def open_session(self, app: Flask, request: Request) -> SessionMixin | None: + """This is called at the beginning of each request, after + pushing the request context, before matching the URL. + + This must return an object which implements a dictionary-like + interface as well as the :class:`SessionMixin` interface. + + This will return ``None`` to indicate that loading failed in + some way that is not immediately an error. The request + context will fall back to using :meth:`make_null_session` + in this case. + """ + raise NotImplementedError() + + def save_session( + self, app: Flask, session: SessionMixin, response: Response + ) -> None: + """This is called at the end of each request, after generating + a response, before removing the request context. It is skipped + if :meth:`is_null_session` returns ``True``. + """ + raise NotImplementedError() + + +session_json_serializer = TaggedJSONSerializer() + + +class SecureCookieSessionInterface(SessionInterface): + """The default session interface that stores sessions in signed cookies + through the :mod:`itsdangerous` module. + """ + + #: the salt that should be applied on top of the secret key for the + #: signing of cookie based sessions. + salt = "cookie-session" + #: the hash function to use for the signature. The default is sha1 + digest_method = staticmethod(hashlib.sha1) + #: the name of the itsdangerous supported key derivation. The default + #: is hmac. + key_derivation = "hmac" + #: A python serializer for the payload. The default is a compact + #: JSON derived serializer with support for some extra Python types + #: such as datetime objects or tuples. + serializer = session_json_serializer + session_class = SecureCookieSession + + def get_signing_serializer(self, app: Flask) -> URLSafeTimedSerializer | None: + if not app.secret_key: + return None + signer_kwargs = dict( + key_derivation=self.key_derivation, digest_method=self.digest_method + ) + return URLSafeTimedSerializer( + app.secret_key, + salt=self.salt, + serializer=self.serializer, + signer_kwargs=signer_kwargs, + ) + + def open_session(self, app: Flask, request: Request) -> SecureCookieSession | None: + s = self.get_signing_serializer(app) + if s is None: + return None + val = request.cookies.get(self.get_cookie_name(app)) + if not val: + return self.session_class() + max_age = int(app.permanent_session_lifetime.total_seconds()) + try: + data = s.loads(val, max_age=max_age) + return self.session_class(data) + except BadSignature: + return self.session_class() + + def save_session( + self, app: Flask, session: SessionMixin, response: Response + ) -> None: + name = self.get_cookie_name(app) + domain = self.get_cookie_domain(app) + path = self.get_cookie_path(app) + secure = self.get_cookie_secure(app) + samesite = self.get_cookie_samesite(app) + httponly = self.get_cookie_httponly(app) + + # Add a "Vary: Cookie" header if the session was accessed at all. + if session.accessed: + response.vary.add("Cookie") + + # If the session is modified to be empty, remove the cookie. + # If the session is empty, return without setting the cookie. + if not session: + if session.modified: + response.delete_cookie( + name, + domain=domain, + path=path, + secure=secure, + samesite=samesite, + httponly=httponly, + ) + response.vary.add("Cookie") + + return + + if not self.should_set_cookie(app, session): + return + + expires = self.get_expiration_time(app, session) + val = self.get_signing_serializer(app).dumps(dict(session)) # type: ignore + response.set_cookie( + name, + val, # type: ignore + expires=expires, + httponly=httponly, + domain=domain, + path=path, + secure=secure, + samesite=samesite, + ) + response.vary.add("Cookie") diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/signals.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/signals.py new file mode 100644 index 0000000..444fda9 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/signals.py @@ -0,0 +1,17 @@ +from __future__ import annotations + +from blinker import Namespace + +# This namespace is only for signals provided by Flask itself. +_signals = Namespace() + +template_rendered = _signals.signal("template-rendered") +before_render_template = _signals.signal("before-render-template") +request_started = _signals.signal("request-started") +request_finished = _signals.signal("request-finished") +request_tearing_down = _signals.signal("request-tearing-down") +got_request_exception = _signals.signal("got-request-exception") +appcontext_tearing_down = _signals.signal("appcontext-tearing-down") +appcontext_pushed = _signals.signal("appcontext-pushed") +appcontext_popped = _signals.signal("appcontext-popped") +message_flashed = _signals.signal("message-flashed") diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/templating.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/templating.py new file mode 100644 index 0000000..8dff8ba --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/templating.py @@ -0,0 +1,221 @@ +from __future__ import annotations + +import typing as t + +from jinja2 import BaseLoader +from jinja2 import Environment as BaseEnvironment +from jinja2 import Template +from jinja2 import TemplateNotFound + +from .globals import _cv_app +from .globals import _cv_request +from .globals import current_app +from .globals import request +from .helpers import stream_with_context +from .signals import before_render_template +from .signals import template_rendered + +if t.TYPE_CHECKING: # pragma: no cover + from .app import Flask + from .sansio.app import App + from .sansio.scaffold import Scaffold + + +def _default_template_ctx_processor() -> dict[str, t.Any]: + """Default template context processor. Injects `request`, + `session` and `g`. + """ + appctx = _cv_app.get(None) + reqctx = _cv_request.get(None) + rv: dict[str, t.Any] = {} + if appctx is not None: + rv["g"] = appctx.g + if reqctx is not None: + rv["request"] = reqctx.request + rv["session"] = reqctx.session + return rv + + +class Environment(BaseEnvironment): + """Works like a regular Jinja2 environment but has some additional + knowledge of how Flask's blueprint works so that it can prepend the + name of the blueprint to referenced templates if necessary. + """ + + def __init__(self, app: App, **options: t.Any) -> None: + if "loader" not in options: + options["loader"] = app.create_global_jinja_loader() + BaseEnvironment.__init__(self, **options) + self.app = app + + +class DispatchingJinjaLoader(BaseLoader): + """A loader that looks for templates in the application and all + the blueprint folders. + """ + + def __init__(self, app: App) -> None: + self.app = app + + def get_source( # type: ignore + self, environment: Environment, template: str + ) -> tuple[str, str | None, t.Callable | None]: + if self.app.config["EXPLAIN_TEMPLATE_LOADING"]: + return self._get_source_explained(environment, template) + return self._get_source_fast(environment, template) + + def _get_source_explained( + self, environment: Environment, template: str + ) -> tuple[str, str | None, t.Callable | None]: + attempts = [] + rv: tuple[str, str | None, t.Callable[[], bool] | None] | None + trv: None | (tuple[str, str | None, t.Callable[[], bool] | None]) = None + + for srcobj, loader in self._iter_loaders(template): + try: + rv = loader.get_source(environment, template) + if trv is None: + trv = rv + except TemplateNotFound: + rv = None + attempts.append((loader, srcobj, rv)) + + from .debughelpers import explain_template_loading_attempts + + explain_template_loading_attempts(self.app, template, attempts) + + if trv is not None: + return trv + raise TemplateNotFound(template) + + def _get_source_fast( + self, environment: Environment, template: str + ) -> tuple[str, str | None, t.Callable | None]: + for _srcobj, loader in self._iter_loaders(template): + try: + return loader.get_source(environment, template) + except TemplateNotFound: + continue + raise TemplateNotFound(template) + + def _iter_loaders( + self, template: str + ) -> t.Generator[tuple[Scaffold, BaseLoader], None, None]: + loader = self.app.jinja_loader + if loader is not None: + yield self.app, loader + + for blueprint in self.app.iter_blueprints(): + loader = blueprint.jinja_loader + if loader is not None: + yield blueprint, loader + + def list_templates(self) -> list[str]: + result = set() + loader = self.app.jinja_loader + if loader is not None: + result.update(loader.list_templates()) + + for blueprint in self.app.iter_blueprints(): + loader = blueprint.jinja_loader + if loader is not None: + for template in loader.list_templates(): + result.add(template) + + return list(result) + + +def _render(app: Flask, template: Template, context: dict[str, t.Any]) -> str: + app.update_template_context(context) + before_render_template.send( + app, _async_wrapper=app.ensure_sync, template=template, context=context + ) + rv = template.render(context) + template_rendered.send( + app, _async_wrapper=app.ensure_sync, template=template, context=context + ) + return rv + + +def render_template( + template_name_or_list: str | Template | list[str | Template], + **context: t.Any, +) -> str: + """Render a template by name with the given context. + + :param template_name_or_list: The name of the template to render. If + a list is given, the first name to exist will be rendered. + :param context: The variables to make available in the template. + """ + app = current_app._get_current_object() # type: ignore[attr-defined] + template = app.jinja_env.get_or_select_template(template_name_or_list) + return _render(app, template, context) + + +def render_template_string(source: str, **context: t.Any) -> str: + """Render a template from the given source string with the given + context. + + :param source: The source code of the template to render. + :param context: The variables to make available in the template. + """ + app = current_app._get_current_object() # type: ignore[attr-defined] + template = app.jinja_env.from_string(source) + return _render(app, template, context) + + +def _stream( + app: Flask, template: Template, context: dict[str, t.Any] +) -> t.Iterator[str]: + app.update_template_context(context) + before_render_template.send( + app, _async_wrapper=app.ensure_sync, template=template, context=context + ) + + def generate() -> t.Iterator[str]: + yield from template.generate(context) + template_rendered.send( + app, _async_wrapper=app.ensure_sync, template=template, context=context + ) + + rv = generate() + + # If a request context is active, keep it while generating. + if request: + rv = stream_with_context(rv) + + return rv + + +def stream_template( + template_name_or_list: str | Template | list[str | Template], + **context: t.Any, +) -> t.Iterator[str]: + """Render a template by name with the given context as a stream. + This returns an iterator of strings, which can be used as a + streaming response from a view. + + :param template_name_or_list: The name of the template to render. If + a list is given, the first name to exist will be rendered. + :param context: The variables to make available in the template. + + .. versionadded:: 2.2 + """ + app = current_app._get_current_object() # type: ignore[attr-defined] + template = app.jinja_env.get_or_select_template(template_name_or_list) + return _stream(app, template, context) + + +def stream_template_string(source: str, **context: t.Any) -> t.Iterator[str]: + """Render a template from the given source string with the given + context as a stream. This returns an iterator of strings, which can + be used as a streaming response from a view. + + :param source: The source code of the template to render. + :param context: The variables to make available in the template. + + .. versionadded:: 2.2 + """ + app = current_app._get_current_object() # type: ignore[attr-defined] + template = app.jinja_env.from_string(source) + return _stream(app, template, context) diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/testing.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/testing.py new file mode 100644 index 0000000..69aa785 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/testing.py @@ -0,0 +1,295 @@ +from __future__ import annotations + +import importlib.metadata +import typing as t +from contextlib import contextmanager +from contextlib import ExitStack +from copy import copy +from types import TracebackType +from urllib.parse import urlsplit + +import werkzeug.test +from click.testing import CliRunner +from werkzeug.test import Client +from werkzeug.wrappers import Request as BaseRequest + +from .cli import ScriptInfo +from .sessions import SessionMixin + +if t.TYPE_CHECKING: # pragma: no cover + from werkzeug.test import TestResponse + + from .app import Flask + + +class EnvironBuilder(werkzeug.test.EnvironBuilder): + """An :class:`~werkzeug.test.EnvironBuilder`, that takes defaults from the + application. + + :param app: The Flask application to configure the environment from. + :param path: URL path being requested. + :param base_url: Base URL where the app is being served, which + ``path`` is relative to. If not given, built from + :data:`PREFERRED_URL_SCHEME`, ``subdomain``, + :data:`SERVER_NAME`, and :data:`APPLICATION_ROOT`. + :param subdomain: Subdomain name to append to :data:`SERVER_NAME`. + :param url_scheme: Scheme to use instead of + :data:`PREFERRED_URL_SCHEME`. + :param json: If given, this is serialized as JSON and passed as + ``data``. Also defaults ``content_type`` to + ``application/json``. + :param args: other positional arguments passed to + :class:`~werkzeug.test.EnvironBuilder`. + :param kwargs: other keyword arguments passed to + :class:`~werkzeug.test.EnvironBuilder`. + """ + + def __init__( + self, + app: Flask, + path: str = "/", + base_url: str | None = None, + subdomain: str | None = None, + url_scheme: str | None = None, + *args: t.Any, + **kwargs: t.Any, + ) -> None: + assert not (base_url or subdomain or url_scheme) or ( + base_url is not None + ) != bool( + subdomain or url_scheme + ), 'Cannot pass "subdomain" or "url_scheme" with "base_url".' + + if base_url is None: + http_host = app.config.get("SERVER_NAME") or "localhost" + app_root = app.config["APPLICATION_ROOT"] + + if subdomain: + http_host = f"{subdomain}.{http_host}" + + if url_scheme is None: + url_scheme = app.config["PREFERRED_URL_SCHEME"] + + url = urlsplit(path) + base_url = ( + f"{url.scheme or url_scheme}://{url.netloc or http_host}" + f"/{app_root.lstrip('/')}" + ) + path = url.path + + if url.query: + sep = b"?" if isinstance(url.query, bytes) else "?" + path += sep + url.query + + self.app = app + super().__init__(path, base_url, *args, **kwargs) + + def json_dumps(self, obj: t.Any, **kwargs: t.Any) -> str: # type: ignore + """Serialize ``obj`` to a JSON-formatted string. + + The serialization will be configured according to the config associated + with this EnvironBuilder's ``app``. + """ + return self.app.json.dumps(obj, **kwargs) + + +_werkzeug_version = "" + + +def _get_werkzeug_version() -> str: + global _werkzeug_version + + if not _werkzeug_version: + _werkzeug_version = importlib.metadata.version("werkzeug") + + return _werkzeug_version + + +class FlaskClient(Client): + """Works like a regular Werkzeug test client but has knowledge about + Flask's contexts to defer the cleanup of the request context until + the end of a ``with`` block. For general information about how to + use this class refer to :class:`werkzeug.test.Client`. + + .. versionchanged:: 0.12 + `app.test_client()` includes preset default environment, which can be + set after instantiation of the `app.test_client()` object in + `client.environ_base`. + + Basic usage is outlined in the :doc:`/testing` chapter. + """ + + application: Flask + + def __init__(self, *args: t.Any, **kwargs: t.Any) -> None: + super().__init__(*args, **kwargs) + self.preserve_context = False + self._new_contexts: list[t.ContextManager[t.Any]] = [] + self._context_stack = ExitStack() + self.environ_base = { + "REMOTE_ADDR": "127.0.0.1", + "HTTP_USER_AGENT": f"Werkzeug/{_get_werkzeug_version()}", + } + + @contextmanager + def session_transaction( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Generator[SessionMixin, None, None]: + """When used in combination with a ``with`` statement this opens a + session transaction. This can be used to modify the session that + the test client uses. Once the ``with`` block is left the session is + stored back. + + :: + + with client.session_transaction() as session: + session['value'] = 42 + + Internally this is implemented by going through a temporary test + request context and since session handling could depend on + request variables this function accepts the same arguments as + :meth:`~flask.Flask.test_request_context` which are directly + passed through. + """ + if self._cookies is None: + raise TypeError( + "Cookies are disabled. Create a client with 'use_cookies=True'." + ) + + app = self.application + ctx = app.test_request_context(*args, **kwargs) + self._add_cookies_to_wsgi(ctx.request.environ) + + with ctx: + sess = app.session_interface.open_session(app, ctx.request) + + if sess is None: + raise RuntimeError("Session backend did not open a session.") + + yield sess + resp = app.response_class() + + if app.session_interface.is_null_session(sess): + return + + with ctx: + app.session_interface.save_session(app, sess, resp) + + self._update_cookies_from_response( + ctx.request.host.partition(":")[0], + ctx.request.path, + resp.headers.getlist("Set-Cookie"), + ) + + def _copy_environ(self, other): + out = {**self.environ_base, **other} + + if self.preserve_context: + out["werkzeug.debug.preserve_context"] = self._new_contexts.append + + return out + + def _request_from_builder_args(self, args, kwargs): + kwargs["environ_base"] = self._copy_environ(kwargs.get("environ_base", {})) + builder = EnvironBuilder(self.application, *args, **kwargs) + + try: + return builder.get_request() + finally: + builder.close() + + def open( + self, + *args: t.Any, + buffered: bool = False, + follow_redirects: bool = False, + **kwargs: t.Any, + ) -> TestResponse: + if args and isinstance( + args[0], (werkzeug.test.EnvironBuilder, dict, BaseRequest) + ): + if isinstance(args[0], werkzeug.test.EnvironBuilder): + builder = copy(args[0]) + builder.environ_base = self._copy_environ(builder.environ_base or {}) + request = builder.get_request() + elif isinstance(args[0], dict): + request = EnvironBuilder.from_environ( + args[0], app=self.application, environ_base=self._copy_environ({}) + ).get_request() + else: + # isinstance(args[0], BaseRequest) + request = copy(args[0]) + request.environ = self._copy_environ(request.environ) + else: + # request is None + request = self._request_from_builder_args(args, kwargs) + + # Pop any previously preserved contexts. This prevents contexts + # from being preserved across redirects or multiple requests + # within a single block. + self._context_stack.close() + + response = super().open( + request, + buffered=buffered, + follow_redirects=follow_redirects, + ) + response.json_module = self.application.json # type: ignore[assignment] + + # Re-push contexts that were preserved during the request. + while self._new_contexts: + cm = self._new_contexts.pop() + self._context_stack.enter_context(cm) + + return response + + def __enter__(self) -> FlaskClient: + if self.preserve_context: + raise RuntimeError("Cannot nest client invocations") + self.preserve_context = True + return self + + def __exit__( + self, + exc_type: type | None, + exc_value: BaseException | None, + tb: TracebackType | None, + ) -> None: + self.preserve_context = False + self._context_stack.close() + + +class FlaskCliRunner(CliRunner): + """A :class:`~click.testing.CliRunner` for testing a Flask app's + CLI commands. Typically created using + :meth:`~flask.Flask.test_cli_runner`. See :ref:`testing-cli`. + """ + + def __init__(self, app: Flask, **kwargs: t.Any) -> None: + self.app = app + super().__init__(**kwargs) + + def invoke( # type: ignore + self, cli: t.Any = None, args: t.Any = None, **kwargs: t.Any + ) -> t.Any: + """Invokes a CLI command in an isolated environment. See + :meth:`CliRunner.invoke ` for + full method documentation. See :ref:`testing-cli` for examples. + + If the ``obj`` argument is not given, passes an instance of + :class:`~flask.cli.ScriptInfo` that knows how to load the Flask + app being tested. + + :param cli: Command object to invoke. Default is the app's + :attr:`~flask.app.Flask.cli` group. + :param args: List of strings to invoke the command with. + + :return: a :class:`~click.testing.Result` object. + """ + if cli is None: + cli = self.app.cli # type: ignore + + if "obj" not in kwargs: + kwargs["obj"] = ScriptInfo(create_app=lambda: self.app) + + return super().invoke(cli, args, **kwargs) diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/typing.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/typing.py new file mode 100644 index 0000000..a8c9ba0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/typing.py @@ -0,0 +1,88 @@ +from __future__ import annotations + +import typing as t + +if t.TYPE_CHECKING: # pragma: no cover + from _typeshed.wsgi import WSGIApplication # noqa: F401 + from werkzeug.datastructures import Headers # noqa: F401 + from werkzeug.sansio.response import Response # noqa: F401 + +# The possible types that are directly convertible or are a Response object. +ResponseValue = t.Union[ + "Response", + str, + bytes, + t.List[t.Any], + # Only dict is actually accepted, but Mapping allows for TypedDict. + t.Mapping[str, t.Any], + t.Iterator[str], + t.Iterator[bytes], +] + +# the possible types for an individual HTTP header +# This should be a Union, but mypy doesn't pass unless it's a TypeVar. +HeaderValue = t.Union[str, t.List[str], t.Tuple[str, ...]] + +# the possible types for HTTP headers +HeadersValue = t.Union[ + "Headers", + t.Mapping[str, HeaderValue], + t.Sequence[t.Tuple[str, HeaderValue]], +] + +# The possible types returned by a route function. +ResponseReturnValue = t.Union[ + ResponseValue, + t.Tuple[ResponseValue, HeadersValue], + t.Tuple[ResponseValue, int], + t.Tuple[ResponseValue, int, HeadersValue], + "WSGIApplication", +] + +# Allow any subclass of werkzeug.Response, such as the one from Flask, +# as a callback argument. Using werkzeug.Response directly makes a +# callback annotated with flask.Response fail type checking. +ResponseClass = t.TypeVar("ResponseClass", bound="Response") + +AppOrBlueprintKey = t.Optional[str] # The App key is None, whereas blueprints are named +AfterRequestCallable = t.Union[ + t.Callable[[ResponseClass], ResponseClass], + t.Callable[[ResponseClass], t.Awaitable[ResponseClass]], +] +BeforeFirstRequestCallable = t.Union[ + t.Callable[[], None], t.Callable[[], t.Awaitable[None]] +] +BeforeRequestCallable = t.Union[ + t.Callable[[], t.Optional[ResponseReturnValue]], + t.Callable[[], t.Awaitable[t.Optional[ResponseReturnValue]]], +] +ShellContextProcessorCallable = t.Callable[[], t.Dict[str, t.Any]] +TeardownCallable = t.Union[ + t.Callable[[t.Optional[BaseException]], None], + t.Callable[[t.Optional[BaseException]], t.Awaitable[None]], +] +TemplateContextProcessorCallable = t.Union[ + t.Callable[[], t.Dict[str, t.Any]], + t.Callable[[], t.Awaitable[t.Dict[str, t.Any]]], +] +TemplateFilterCallable = t.Callable[..., t.Any] +TemplateGlobalCallable = t.Callable[..., t.Any] +TemplateTestCallable = t.Callable[..., bool] +URLDefaultCallable = t.Callable[[str, dict], None] +URLValuePreprocessorCallable = t.Callable[[t.Optional[str], t.Optional[dict]], None] + +# This should take Exception, but that either breaks typing the argument +# with a specific exception, or decorating multiple times with different +# exceptions (and using a union type on the argument). +# https://github.com/pallets/flask/issues/4095 +# https://github.com/pallets/flask/issues/4295 +# https://github.com/pallets/flask/issues/4297 +ErrorHandlerCallable = t.Union[ + t.Callable[[t.Any], ResponseReturnValue], + t.Callable[[t.Any], t.Awaitable[ResponseReturnValue]], +] + +RouteCallable = t.Union[ + t.Callable[..., ResponseReturnValue], + t.Callable[..., t.Awaitable[ResponseReturnValue]], +] diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/views.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/views.py new file mode 100644 index 0000000..c7a2b62 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/views.py @@ -0,0 +1,190 @@ +from __future__ import annotations + +import typing as t + +from . import typing as ft +from .globals import current_app +from .globals import request + + +http_method_funcs = frozenset( + ["get", "post", "head", "options", "delete", "put", "trace", "patch"] +) + + +class View: + """Subclass this class and override :meth:`dispatch_request` to + create a generic class-based view. Call :meth:`as_view` to create a + view function that creates an instance of the class with the given + arguments and calls its ``dispatch_request`` method with any URL + variables. + + See :doc:`views` for a detailed guide. + + .. code-block:: python + + class Hello(View): + init_every_request = False + + def dispatch_request(self, name): + return f"Hello, {name}!" + + app.add_url_rule( + "/hello/", view_func=Hello.as_view("hello") + ) + + Set :attr:`methods` on the class to change what methods the view + accepts. + + Set :attr:`decorators` on the class to apply a list of decorators to + the generated view function. Decorators applied to the class itself + will not be applied to the generated view function! + + Set :attr:`init_every_request` to ``False`` for efficiency, unless + you need to store request-global data on ``self``. + """ + + #: The methods this view is registered for. Uses the same default + #: (``["GET", "HEAD", "OPTIONS"]``) as ``route`` and + #: ``add_url_rule`` by default. + methods: t.ClassVar[t.Collection[str] | None] = None + + #: Control whether the ``OPTIONS`` method is handled automatically. + #: Uses the same default (``True``) as ``route`` and + #: ``add_url_rule`` by default. + provide_automatic_options: t.ClassVar[bool | None] = None + + #: A list of decorators to apply, in order, to the generated view + #: function. Remember that ``@decorator`` syntax is applied bottom + #: to top, so the first decorator in the list would be the bottom + #: decorator. + #: + #: .. versionadded:: 0.8 + decorators: t.ClassVar[list[t.Callable]] = [] + + #: Create a new instance of this view class for every request by + #: default. If a view subclass sets this to ``False``, the same + #: instance is used for every request. + #: + #: A single instance is more efficient, especially if complex setup + #: is done during init. However, storing data on ``self`` is no + #: longer safe across requests, and :data:`~flask.g` should be used + #: instead. + #: + #: .. versionadded:: 2.2 + init_every_request: t.ClassVar[bool] = True + + def dispatch_request(self) -> ft.ResponseReturnValue: + """The actual view function behavior. Subclasses must override + this and return a valid response. Any variables from the URL + rule are passed as keyword arguments. + """ + raise NotImplementedError() + + @classmethod + def as_view( + cls, name: str, *class_args: t.Any, **class_kwargs: t.Any + ) -> ft.RouteCallable: + """Convert the class into a view function that can be registered + for a route. + + By default, the generated view will create a new instance of the + view class for every request and call its + :meth:`dispatch_request` method. If the view class sets + :attr:`init_every_request` to ``False``, the same instance will + be used for every request. + + Except for ``name``, all other arguments passed to this method + are forwarded to the view class ``__init__`` method. + + .. versionchanged:: 2.2 + Added the ``init_every_request`` class attribute. + """ + if cls.init_every_request: + + def view(**kwargs: t.Any) -> ft.ResponseReturnValue: + self = view.view_class( # type: ignore[attr-defined] + *class_args, **class_kwargs + ) + return current_app.ensure_sync(self.dispatch_request)(**kwargs) + + else: + self = cls(*class_args, **class_kwargs) + + def view(**kwargs: t.Any) -> ft.ResponseReturnValue: + return current_app.ensure_sync(self.dispatch_request)(**kwargs) + + if cls.decorators: + view.__name__ = name + view.__module__ = cls.__module__ + for decorator in cls.decorators: + view = decorator(view) + + # We attach the view class to the view function for two reasons: + # first of all it allows us to easily figure out what class-based + # view this thing came from, secondly it's also used for instantiating + # the view class so you can actually replace it with something else + # for testing purposes and debugging. + view.view_class = cls # type: ignore + view.__name__ = name + view.__doc__ = cls.__doc__ + view.__module__ = cls.__module__ + view.methods = cls.methods # type: ignore + view.provide_automatic_options = cls.provide_automatic_options # type: ignore + return view + + +class MethodView(View): + """Dispatches request methods to the corresponding instance methods. + For example, if you implement a ``get`` method, it will be used to + handle ``GET`` requests. + + This can be useful for defining a REST API. + + :attr:`methods` is automatically set based on the methods defined on + the class. + + See :doc:`views` for a detailed guide. + + .. code-block:: python + + class CounterAPI(MethodView): + def get(self): + return str(session.get("counter", 0)) + + def post(self): + session["counter"] = session.get("counter", 0) + 1 + return redirect(url_for("counter")) + + app.add_url_rule( + "/counter", view_func=CounterAPI.as_view("counter") + ) + """ + + def __init_subclass__(cls, **kwargs: t.Any) -> None: + super().__init_subclass__(**kwargs) + + if "methods" not in cls.__dict__: + methods = set() + + for base in cls.__bases__: + if getattr(base, "methods", None): + methods.update(base.methods) # type: ignore[attr-defined] + + for key in http_method_funcs: + if hasattr(cls, key): + methods.add(key.upper()) + + if methods: + cls.methods = methods + + def dispatch_request(self, **kwargs: t.Any) -> ft.ResponseReturnValue: + meth = getattr(self, request.method.lower(), None) + + # If the request method is HEAD and we don't have a handler for it + # retry with GET. + if meth is None and request.method == "HEAD": + meth = getattr(self, "get", None) + + assert meth is not None, f"Unimplemented method {request.method!r}" + return current_app.ensure_sync(meth)(**kwargs) diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/wrappers.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/wrappers.py new file mode 100644 index 0000000..ef7aa38 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/flask/wrappers.py @@ -0,0 +1,173 @@ +from __future__ import annotations + +import typing as t + +from werkzeug.exceptions import BadRequest +from werkzeug.wrappers import Request as RequestBase +from werkzeug.wrappers import Response as ResponseBase + +from . import json +from .globals import current_app +from .helpers import _split_blueprint_path + +if t.TYPE_CHECKING: # pragma: no cover + from werkzeug.routing import Rule + + +class Request(RequestBase): + """The request object used by default in Flask. Remembers the + matched endpoint and view arguments. + + It is what ends up as :class:`~flask.request`. If you want to replace + the request object used you can subclass this and set + :attr:`~flask.Flask.request_class` to your subclass. + + The request object is a :class:`~werkzeug.wrappers.Request` subclass and + provides all of the attributes Werkzeug defines plus a few Flask + specific ones. + """ + + json_module: t.Any = json + + #: The internal URL rule that matched the request. This can be + #: useful to inspect which methods are allowed for the URL from + #: a before/after handler (``request.url_rule.methods``) etc. + #: Though if the request's method was invalid for the URL rule, + #: the valid list is available in ``routing_exception.valid_methods`` + #: instead (an attribute of the Werkzeug exception + #: :exc:`~werkzeug.exceptions.MethodNotAllowed`) + #: because the request was never internally bound. + #: + #: .. versionadded:: 0.6 + url_rule: Rule | None = None + + #: A dict of view arguments that matched the request. If an exception + #: happened when matching, this will be ``None``. + view_args: dict[str, t.Any] | None = None + + #: If matching the URL failed, this is the exception that will be + #: raised / was raised as part of the request handling. This is + #: usually a :exc:`~werkzeug.exceptions.NotFound` exception or + #: something similar. + routing_exception: Exception | None = None + + @property + def max_content_length(self) -> int | None: # type: ignore + """Read-only view of the ``MAX_CONTENT_LENGTH`` config key.""" + if current_app: + return current_app.config["MAX_CONTENT_LENGTH"] + else: + return None + + @property + def endpoint(self) -> str | None: + """The endpoint that matched the request URL. + + This will be ``None`` if matching failed or has not been + performed yet. + + This in combination with :attr:`view_args` can be used to + reconstruct the same URL or a modified URL. + """ + if self.url_rule is not None: + return self.url_rule.endpoint + + return None + + @property + def blueprint(self) -> str | None: + """The registered name of the current blueprint. + + This will be ``None`` if the endpoint is not part of a + blueprint, or if URL matching failed or has not been performed + yet. + + This does not necessarily match the name the blueprint was + created with. It may have been nested, or registered with a + different name. + """ + endpoint = self.endpoint + + if endpoint is not None and "." in endpoint: + return endpoint.rpartition(".")[0] + + return None + + @property + def blueprints(self) -> list[str]: + """The registered names of the current blueprint upwards through + parent blueprints. + + This will be an empty list if there is no current blueprint, or + if URL matching failed. + + .. versionadded:: 2.0.1 + """ + name = self.blueprint + + if name is None: + return [] + + return _split_blueprint_path(name) + + def _load_form_data(self) -> None: + super()._load_form_data() + + # In debug mode we're replacing the files multidict with an ad-hoc + # subclass that raises a different error for key errors. + if ( + current_app + and current_app.debug + and self.mimetype != "multipart/form-data" + and not self.files + ): + from .debughelpers import attach_enctype_error_multidict + + attach_enctype_error_multidict(self) + + def on_json_loading_failed(self, e: ValueError | None) -> t.Any: + try: + return super().on_json_loading_failed(e) + except BadRequest as e: + if current_app and current_app.debug: + raise + + raise BadRequest() from e + + +class Response(ResponseBase): + """The response object that is used by default in Flask. Works like the + response object from Werkzeug but is set to have an HTML mimetype by + default. Quite often you don't have to create this object yourself because + :meth:`~flask.Flask.make_response` will take care of that for you. + + If you want to replace the response object used you can subclass this and + set :attr:`~flask.Flask.response_class` to your subclass. + + .. versionchanged:: 1.0 + JSON support is added to the response, like the request. This is useful + when testing to get the test client response data as JSON. + + .. versionchanged:: 1.0 + + Added :attr:`max_cookie_size`. + """ + + default_mimetype: str | None = "text/html" + + json_module = json + + autocorrect_location_header = False + + @property + def max_cookie_size(self) -> int: # type: ignore + """Read-only view of the :data:`MAX_COOKIE_SIZE` config key. + + See :attr:`~werkzeug.wrappers.Response.max_cookie_size` in + Werkzeug's docs. + """ + if current_app: + return current_app.config["MAX_COOKIE_SIZE"] + + # return Werkzeug's default when not in an app context + return super().max_cookie_size diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/__init__.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/__init__.py new file mode 100644 index 0000000..ea55256 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/__init__.py @@ -0,0 +1,38 @@ +from __future__ import annotations + +import typing as t + +from .encoding import base64_decode as base64_decode +from .encoding import base64_encode as base64_encode +from .encoding import want_bytes as want_bytes +from .exc import BadData as BadData +from .exc import BadHeader as BadHeader +from .exc import BadPayload as BadPayload +from .exc import BadSignature as BadSignature +from .exc import BadTimeSignature as BadTimeSignature +from .exc import SignatureExpired as SignatureExpired +from .serializer import Serializer as Serializer +from .signer import HMACAlgorithm as HMACAlgorithm +from .signer import NoneAlgorithm as NoneAlgorithm +from .signer import Signer as Signer +from .timed import TimedSerializer as TimedSerializer +from .timed import TimestampSigner as TimestampSigner +from .url_safe import URLSafeSerializer as URLSafeSerializer +from .url_safe import URLSafeTimedSerializer as URLSafeTimedSerializer + + +def __getattr__(name: str) -> t.Any: + if name == "__version__": + import importlib.metadata + import warnings + + warnings.warn( + "The '__version__' attribute is deprecated and will be removed in" + " ItsDangerous 2.3. Use feature detection or" + " 'importlib.metadata.version(\"itsdangerous\")' instead.", + DeprecationWarning, + stacklevel=2, + ) + return importlib.metadata.version("itsdangerous") + + raise AttributeError(name) diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/_json.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/_json.py new file mode 100644 index 0000000..fc23fea --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/_json.py @@ -0,0 +1,18 @@ +from __future__ import annotations + +import json as _json +import typing as t + + +class _CompactJSON: + """Wrapper around json module that strips whitespace.""" + + @staticmethod + def loads(payload: str | bytes) -> t.Any: + return _json.loads(payload) + + @staticmethod + def dumps(obj: t.Any, **kwargs: t.Any) -> str: + kwargs.setdefault("ensure_ascii", False) + kwargs.setdefault("separators", (",", ":")) + return _json.dumps(obj, **kwargs) diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/encoding.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/encoding.py new file mode 100644 index 0000000..f5ca80f --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/encoding.py @@ -0,0 +1,54 @@ +from __future__ import annotations + +import base64 +import string +import struct +import typing as t + +from .exc import BadData + + +def want_bytes( + s: str | bytes, encoding: str = "utf-8", errors: str = "strict" +) -> bytes: + if isinstance(s, str): + s = s.encode(encoding, errors) + + return s + + +def base64_encode(string: str | bytes) -> bytes: + """Base64 encode a string of bytes or text. The resulting bytes are + safe to use in URLs. + """ + string = want_bytes(string) + return base64.urlsafe_b64encode(string).rstrip(b"=") + + +def base64_decode(string: str | bytes) -> bytes: + """Base64 decode a URL-safe string of bytes or text. The result is + bytes. + """ + string = want_bytes(string, encoding="ascii", errors="ignore") + string += b"=" * (-len(string) % 4) + + try: + return base64.urlsafe_b64decode(string) + except (TypeError, ValueError) as e: + raise BadData("Invalid base64-encoded data") from e + + +# The alphabet used by base64.urlsafe_* +_base64_alphabet = f"{string.ascii_letters}{string.digits}-_=".encode("ascii") + +_int64_struct = struct.Struct(">Q") +_int_to_bytes = _int64_struct.pack +_bytes_to_int = t.cast("t.Callable[[bytes], tuple[int]]", _int64_struct.unpack) + + +def int_to_bytes(num: int) -> bytes: + return _int_to_bytes(num).lstrip(b"\x00") + + +def bytes_to_int(bytestr: bytes) -> int: + return _bytes_to_int(bytestr.rjust(8, b"\x00"))[0] diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/exc.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/exc.py new file mode 100644 index 0000000..a75adcd --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/exc.py @@ -0,0 +1,106 @@ +from __future__ import annotations + +import typing as t +from datetime import datetime + + +class BadData(Exception): + """Raised if bad data of any sort was encountered. This is the base + for all exceptions that ItsDangerous defines. + + .. versionadded:: 0.15 + """ + + def __init__(self, message: str): + super().__init__(message) + self.message = message + + def __str__(self) -> str: + return self.message + + +class BadSignature(BadData): + """Raised if a signature does not match.""" + + def __init__(self, message: str, payload: t.Any | None = None): + super().__init__(message) + + #: The payload that failed the signature test. In some + #: situations you might still want to inspect this, even if + #: you know it was tampered with. + #: + #: .. versionadded:: 0.14 + self.payload: t.Any | None = payload + + +class BadTimeSignature(BadSignature): + """Raised if a time-based signature is invalid. This is a subclass + of :class:`BadSignature`. + """ + + def __init__( + self, + message: str, + payload: t.Any | None = None, + date_signed: datetime | None = None, + ): + super().__init__(message, payload) + + #: If the signature expired this exposes the date of when the + #: signature was created. This can be helpful in order to + #: tell the user how long a link has been gone stale. + #: + #: .. versionchanged:: 2.0 + #: The datetime value is timezone-aware rather than naive. + #: + #: .. versionadded:: 0.14 + self.date_signed = date_signed + + +class SignatureExpired(BadTimeSignature): + """Raised if a signature timestamp is older than ``max_age``. This + is a subclass of :exc:`BadTimeSignature`. + """ + + +class BadHeader(BadSignature): + """Raised if a signed header is invalid in some form. This only + happens for serializers that have a header that goes with the + signature. + + .. versionadded:: 0.24 + """ + + def __init__( + self, + message: str, + payload: t.Any | None = None, + header: t.Any | None = None, + original_error: Exception | None = None, + ): + super().__init__(message, payload) + + #: If the header is actually available but just malformed it + #: might be stored here. + self.header: t.Any | None = header + + #: If available, the error that indicates why the payload was + #: not valid. This might be ``None``. + self.original_error: Exception | None = original_error + + +class BadPayload(BadData): + """Raised if a payload is invalid. This could happen if the payload + is loaded despite an invalid signature, or if there is a mismatch + between the serializer and deserializer. The original exception + that occurred during loading is stored on as :attr:`original_error`. + + .. versionadded:: 0.15 + """ + + def __init__(self, message: str, original_error: Exception | None = None): + super().__init__(message) + + #: If available, the error that indicates why the payload was + #: not valid. This might be ``None``. + self.original_error: Exception | None = original_error diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/py.typed b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/serializer.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/serializer.py new file mode 100644 index 0000000..5ddf387 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/serializer.py @@ -0,0 +1,406 @@ +from __future__ import annotations + +import collections.abc as cabc +import json +import typing as t + +from .encoding import want_bytes +from .exc import BadPayload +from .exc import BadSignature +from .signer import _make_keys_list +from .signer import Signer + +if t.TYPE_CHECKING: + import typing_extensions as te + + # This should be either be str or bytes. To avoid having to specify the + # bound type, it falls back to a union if structural matching fails. + _TSerialized = te.TypeVar( + "_TSerialized", bound=t.Union[str, bytes], default=t.Union[str, bytes] + ) +else: + # Still available at runtime on Python < 3.13, but without the default. + _TSerialized = t.TypeVar("_TSerialized", bound=t.Union[str, bytes]) + + +class _PDataSerializer(t.Protocol[_TSerialized]): + def loads(self, payload: _TSerialized, /) -> t.Any: ... + # A signature with additional arguments is not handled correctly by type + # checkers right now, so an overload is used below for serializers that + # don't match this strict protocol. + def dumps(self, obj: t.Any, /) -> _TSerialized: ... + + +# Use TypeIs once it's available in typing_extensions or 3.13. +def is_text_serializer( + serializer: _PDataSerializer[t.Any], +) -> te.TypeGuard[_PDataSerializer[str]]: + """Checks whether a serializer generates text or binary.""" + return isinstance(serializer.dumps({}), str) + + +class Serializer(t.Generic[_TSerialized]): + """A serializer wraps a :class:`~itsdangerous.signer.Signer` to + enable serializing and securely signing data other than bytes. It + can unsign to verify that the data hasn't been changed. + + The serializer provides :meth:`dumps` and :meth:`loads`, similar to + :mod:`json`, and by default uses :mod:`json` internally to serialize + the data to bytes. + + The secret key should be a random string of ``bytes`` and should not + be saved to code or version control. Different salts should be used + to distinguish signing in different contexts. See :doc:`/concepts` + for information about the security of the secret key and salt. + + :param secret_key: The secret key to sign and verify with. Can be a + list of keys, oldest to newest, to support key rotation. + :param salt: Extra key to combine with ``secret_key`` to distinguish + signatures in different contexts. + :param serializer: An object that provides ``dumps`` and ``loads`` + methods for serializing data to a string. Defaults to + :attr:`default_serializer`, which defaults to :mod:`json`. + :param serializer_kwargs: Keyword arguments to pass when calling + ``serializer.dumps``. + :param signer: A ``Signer`` class to instantiate when signing data. + Defaults to :attr:`default_signer`, which defaults to + :class:`~itsdangerous.signer.Signer`. + :param signer_kwargs: Keyword arguments to pass when instantiating + the ``Signer`` class. + :param fallback_signers: List of signer parameters to try when + unsigning with the default signer fails. Each item can be a dict + of ``signer_kwargs``, a ``Signer`` class, or a tuple of + ``(signer, signer_kwargs)``. Defaults to + :attr:`default_fallback_signers`. + + .. versionchanged:: 2.0 + Added support for key rotation by passing a list to + ``secret_key``. + + .. versionchanged:: 2.0 + Removed the default SHA-512 fallback signer from + ``default_fallback_signers``. + + .. versionchanged:: 1.1 + Added support for ``fallback_signers`` and configured a default + SHA-512 fallback. This fallback is for users who used the yanked + 1.0.0 release which defaulted to SHA-512. + + .. versionchanged:: 0.14 + The ``signer`` and ``signer_kwargs`` parameters were added to + the constructor. + """ + + #: The default serialization module to use to serialize data to a + #: string internally. The default is :mod:`json`, but can be changed + #: to any object that provides ``dumps`` and ``loads`` methods. + default_serializer: _PDataSerializer[t.Any] = json + + #: The default ``Signer`` class to instantiate when signing data. + #: The default is :class:`itsdangerous.signer.Signer`. + default_signer: type[Signer] = Signer + + #: The default fallback signers to try when unsigning fails. + default_fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] = [] + + # Serializer[str] if no data serializer is provided, or if it returns str. + @t.overload + def __init__( + self: Serializer[str], + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None = b"itsdangerous", + serializer: None | _PDataSerializer[str] = None, + serializer_kwargs: dict[str, t.Any] | None = None, + signer: type[Signer] | None = None, + signer_kwargs: dict[str, t.Any] | None = None, + fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] + | None = None, + ): ... + + # Serializer[bytes] with a bytes data serializer positional argument. + @t.overload + def __init__( + self: Serializer[bytes], + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None, + serializer: _PDataSerializer[bytes], + serializer_kwargs: dict[str, t.Any] | None = None, + signer: type[Signer] | None = None, + signer_kwargs: dict[str, t.Any] | None = None, + fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] + | None = None, + ): ... + + # Serializer[bytes] with a bytes data serializer keyword argument. + @t.overload + def __init__( + self: Serializer[bytes], + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None = b"itsdangerous", + *, + serializer: _PDataSerializer[bytes], + serializer_kwargs: dict[str, t.Any] | None = None, + signer: type[Signer] | None = None, + signer_kwargs: dict[str, t.Any] | None = None, + fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] + | None = None, + ): ... + + # Fall back with a positional argument. If the strict signature of + # _PDataSerializer doesn't match, fall back to a union, requiring the user + # to specify the type. + @t.overload + def __init__( + self, + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None, + serializer: t.Any, + serializer_kwargs: dict[str, t.Any] | None = None, + signer: type[Signer] | None = None, + signer_kwargs: dict[str, t.Any] | None = None, + fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] + | None = None, + ): ... + + # Fall back with a keyword argument. + @t.overload + def __init__( + self, + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None = b"itsdangerous", + *, + serializer: t.Any, + serializer_kwargs: dict[str, t.Any] | None = None, + signer: type[Signer] | None = None, + signer_kwargs: dict[str, t.Any] | None = None, + fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] + | None = None, + ): ... + + def __init__( + self, + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None = b"itsdangerous", + serializer: t.Any | None = None, + serializer_kwargs: dict[str, t.Any] | None = None, + signer: type[Signer] | None = None, + signer_kwargs: dict[str, t.Any] | None = None, + fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] + | None = None, + ): + #: The list of secret keys to try for verifying signatures, from + #: oldest to newest. The newest (last) key is used for signing. + #: + #: This allows a key rotation system to keep a list of allowed + #: keys and remove expired ones. + self.secret_keys: list[bytes] = _make_keys_list(secret_key) + + if salt is not None: + salt = want_bytes(salt) + # if salt is None then the signer's default is used + + self.salt = salt + + if serializer is None: + serializer = self.default_serializer + + self.serializer: _PDataSerializer[_TSerialized] = serializer + self.is_text_serializer: bool = is_text_serializer(serializer) + + if signer is None: + signer = self.default_signer + + self.signer: type[Signer] = signer + self.signer_kwargs: dict[str, t.Any] = signer_kwargs or {} + + if fallback_signers is None: + fallback_signers = list(self.default_fallback_signers) + + self.fallback_signers: list[ + dict[str, t.Any] | tuple[type[Signer], dict[str, t.Any]] | type[Signer] + ] = fallback_signers + self.serializer_kwargs: dict[str, t.Any] = serializer_kwargs or {} + + @property + def secret_key(self) -> bytes: + """The newest (last) entry in the :attr:`secret_keys` list. This + is for compatibility from before key rotation support was added. + """ + return self.secret_keys[-1] + + def load_payload( + self, payload: bytes, serializer: _PDataSerializer[t.Any] | None = None + ) -> t.Any: + """Loads the encoded object. This function raises + :class:`.BadPayload` if the payload is not valid. The + ``serializer`` parameter can be used to override the serializer + stored on the class. The encoded ``payload`` should always be + bytes. + """ + if serializer is None: + use_serializer = self.serializer + is_text = self.is_text_serializer + else: + use_serializer = serializer + is_text = is_text_serializer(serializer) + + try: + if is_text: + return use_serializer.loads(payload.decode("utf-8")) # type: ignore[arg-type] + + return use_serializer.loads(payload) # type: ignore[arg-type] + except Exception as e: + raise BadPayload( + "Could not load the payload because an exception" + " occurred on unserializing the data.", + original_error=e, + ) from e + + def dump_payload(self, obj: t.Any) -> bytes: + """Dumps the encoded object. The return value is always bytes. + If the internal serializer returns text, the value will be + encoded as UTF-8. + """ + return want_bytes(self.serializer.dumps(obj, **self.serializer_kwargs)) + + def make_signer(self, salt: str | bytes | None = None) -> Signer: + """Creates a new instance of the signer to be used. The default + implementation uses the :class:`.Signer` base class. + """ + if salt is None: + salt = self.salt + + return self.signer(self.secret_keys, salt=salt, **self.signer_kwargs) + + def iter_unsigners(self, salt: str | bytes | None = None) -> cabc.Iterator[Signer]: + """Iterates over all signers to be tried for unsigning. Starts + with the configured signer, then constructs each signer + specified in ``fallback_signers``. + """ + if salt is None: + salt = self.salt + + yield self.make_signer(salt) + + for fallback in self.fallback_signers: + if isinstance(fallback, dict): + kwargs = fallback + fallback = self.signer + elif isinstance(fallback, tuple): + fallback, kwargs = fallback + else: + kwargs = self.signer_kwargs + + for secret_key in self.secret_keys: + yield fallback(secret_key, salt=salt, **kwargs) + + def dumps(self, obj: t.Any, salt: str | bytes | None = None) -> _TSerialized: + """Returns a signed string serialized with the internal + serializer. The return value can be either a byte or unicode + string depending on the format of the internal serializer. + """ + payload = want_bytes(self.dump_payload(obj)) + rv = self.make_signer(salt).sign(payload) + + if self.is_text_serializer: + return rv.decode("utf-8") # type: ignore[return-value] + + return rv # type: ignore[return-value] + + def dump(self, obj: t.Any, f: t.IO[t.Any], salt: str | bytes | None = None) -> None: + """Like :meth:`dumps` but dumps into a file. The file handle has + to be compatible with what the internal serializer expects. + """ + f.write(self.dumps(obj, salt)) + + def loads( + self, s: str | bytes, salt: str | bytes | None = None, **kwargs: t.Any + ) -> t.Any: + """Reverse of :meth:`dumps`. Raises :exc:`.BadSignature` if the + signature validation fails. + """ + s = want_bytes(s) + last_exception = None + + for signer in self.iter_unsigners(salt): + try: + return self.load_payload(signer.unsign(s)) + except BadSignature as err: + last_exception = err + + raise t.cast(BadSignature, last_exception) + + def load(self, f: t.IO[t.Any], salt: str | bytes | None = None) -> t.Any: + """Like :meth:`loads` but loads from a file.""" + return self.loads(f.read(), salt) + + def loads_unsafe( + self, s: str | bytes, salt: str | bytes | None = None + ) -> tuple[bool, t.Any]: + """Like :meth:`loads` but without verifying the signature. This + is potentially very dangerous to use depending on how your + serializer works. The return value is ``(signature_valid, + payload)`` instead of just the payload. The first item will be a + boolean that indicates if the signature is valid. This function + never fails. + + Use it for debugging only and if you know that your serializer + module is not exploitable (for example, do not use it with a + pickle serializer). + + .. versionadded:: 0.15 + """ + return self._loads_unsafe_impl(s, salt) + + def _loads_unsafe_impl( + self, + s: str | bytes, + salt: str | bytes | None, + load_kwargs: dict[str, t.Any] | None = None, + load_payload_kwargs: dict[str, t.Any] | None = None, + ) -> tuple[bool, t.Any]: + """Low level helper function to implement :meth:`loads_unsafe` + in serializer subclasses. + """ + if load_kwargs is None: + load_kwargs = {} + + try: + return True, self.loads(s, salt=salt, **load_kwargs) + except BadSignature as e: + if e.payload is None: + return False, None + + if load_payload_kwargs is None: + load_payload_kwargs = {} + + try: + return ( + False, + self.load_payload(e.payload, **load_payload_kwargs), + ) + except BadPayload: + return False, None + + def load_unsafe( + self, f: t.IO[t.Any], salt: str | bytes | None = None + ) -> tuple[bool, t.Any]: + """Like :meth:`loads_unsafe` but loads from a file. + + .. versionadded:: 0.15 + """ + return self.loads_unsafe(f.read(), salt=salt) diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/signer.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/signer.py new file mode 100644 index 0000000..e324dc0 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/signer.py @@ -0,0 +1,266 @@ +from __future__ import annotations + +import collections.abc as cabc +import hashlib +import hmac +import typing as t + +from .encoding import _base64_alphabet +from .encoding import base64_decode +from .encoding import base64_encode +from .encoding import want_bytes +from .exc import BadSignature + + +class SigningAlgorithm: + """Subclasses must implement :meth:`get_signature` to provide + signature generation functionality. + """ + + def get_signature(self, key: bytes, value: bytes) -> bytes: + """Returns the signature for the given key and value.""" + raise NotImplementedError() + + def verify_signature(self, key: bytes, value: bytes, sig: bytes) -> bool: + """Verifies the given signature matches the expected + signature. + """ + return hmac.compare_digest(sig, self.get_signature(key, value)) + + +class NoneAlgorithm(SigningAlgorithm): + """Provides an algorithm that does not perform any signing and + returns an empty signature. + """ + + def get_signature(self, key: bytes, value: bytes) -> bytes: + return b"" + + +def _lazy_sha1(string: bytes = b"") -> t.Any: + """Don't access ``hashlib.sha1`` until runtime. FIPS builds may not include + SHA-1, in which case the import and use as a default would fail before the + developer can configure something else. + """ + return hashlib.sha1(string) + + +class HMACAlgorithm(SigningAlgorithm): + """Provides signature generation using HMACs.""" + + #: The digest method to use with the MAC algorithm. This defaults to + #: SHA1, but can be changed to any other function in the hashlib + #: module. + default_digest_method: t.Any = staticmethod(_lazy_sha1) + + def __init__(self, digest_method: t.Any = None): + if digest_method is None: + digest_method = self.default_digest_method + + self.digest_method: t.Any = digest_method + + def get_signature(self, key: bytes, value: bytes) -> bytes: + mac = hmac.new(key, msg=value, digestmod=self.digest_method) + return mac.digest() + + +def _make_keys_list( + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], +) -> list[bytes]: + if isinstance(secret_key, (str, bytes)): + return [want_bytes(secret_key)] + + return [want_bytes(s) for s in secret_key] # pyright: ignore + + +class Signer: + """A signer securely signs bytes, then unsigns them to verify that + the value hasn't been changed. + + The secret key should be a random string of ``bytes`` and should not + be saved to code or version control. Different salts should be used + to distinguish signing in different contexts. See :doc:`/concepts` + for information about the security of the secret key and salt. + + :param secret_key: The secret key to sign and verify with. Can be a + list of keys, oldest to newest, to support key rotation. + :param salt: Extra key to combine with ``secret_key`` to distinguish + signatures in different contexts. + :param sep: Separator between the signature and value. + :param key_derivation: How to derive the signing key from the secret + key and salt. Possible values are ``concat``, ``django-concat``, + or ``hmac``. Defaults to :attr:`default_key_derivation`, which + defaults to ``django-concat``. + :param digest_method: Hash function to use when generating the HMAC + signature. Defaults to :attr:`default_digest_method`, which + defaults to :func:`hashlib.sha1`. Note that the security of the + hash alone doesn't apply when used intermediately in HMAC. + :param algorithm: A :class:`SigningAlgorithm` instance to use + instead of building a default :class:`HMACAlgorithm` with the + ``digest_method``. + + .. versionchanged:: 2.0 + Added support for key rotation by passing a list to + ``secret_key``. + + .. versionchanged:: 0.18 + ``algorithm`` was added as an argument to the class constructor. + + .. versionchanged:: 0.14 + ``key_derivation`` and ``digest_method`` were added as arguments + to the class constructor. + """ + + #: The default digest method to use for the signer. The default is + #: :func:`hashlib.sha1`, but can be changed to any :mod:`hashlib` or + #: compatible object. Note that the security of the hash alone + #: doesn't apply when used intermediately in HMAC. + #: + #: .. versionadded:: 0.14 + default_digest_method: t.Any = staticmethod(_lazy_sha1) + + #: The default scheme to use to derive the signing key from the + #: secret key and salt. The default is ``django-concat``. Possible + #: values are ``concat``, ``django-concat``, and ``hmac``. + #: + #: .. versionadded:: 0.14 + default_key_derivation: str = "django-concat" + + def __init__( + self, + secret_key: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes], + salt: str | bytes | None = b"itsdangerous.Signer", + sep: str | bytes = b".", + key_derivation: str | None = None, + digest_method: t.Any | None = None, + algorithm: SigningAlgorithm | None = None, + ): + #: The list of secret keys to try for verifying signatures, from + #: oldest to newest. The newest (last) key is used for signing. + #: + #: This allows a key rotation system to keep a list of allowed + #: keys and remove expired ones. + self.secret_keys: list[bytes] = _make_keys_list(secret_key) + self.sep: bytes = want_bytes(sep) + + if self.sep in _base64_alphabet: + raise ValueError( + "The given separator cannot be used because it may be" + " contained in the signature itself. ASCII letters," + " digits, and '-_=' must not be used." + ) + + if salt is not None: + salt = want_bytes(salt) + else: + salt = b"itsdangerous.Signer" + + self.salt = salt + + if key_derivation is None: + key_derivation = self.default_key_derivation + + self.key_derivation: str = key_derivation + + if digest_method is None: + digest_method = self.default_digest_method + + self.digest_method: t.Any = digest_method + + if algorithm is None: + algorithm = HMACAlgorithm(self.digest_method) + + self.algorithm: SigningAlgorithm = algorithm + + @property + def secret_key(self) -> bytes: + """The newest (last) entry in the :attr:`secret_keys` list. This + is for compatibility from before key rotation support was added. + """ + return self.secret_keys[-1] + + def derive_key(self, secret_key: str | bytes | None = None) -> bytes: + """This method is called to derive the key. The default key + derivation choices can be overridden here. Key derivation is not + intended to be used as a security method to make a complex key + out of a short password. Instead you should use large random + secret keys. + + :param secret_key: A specific secret key to derive from. + Defaults to the last item in :attr:`secret_keys`. + + .. versionchanged:: 2.0 + Added the ``secret_key`` parameter. + """ + if secret_key is None: + secret_key = self.secret_keys[-1] + else: + secret_key = want_bytes(secret_key) + + if self.key_derivation == "concat": + return t.cast(bytes, self.digest_method(self.salt + secret_key).digest()) + elif self.key_derivation == "django-concat": + return t.cast( + bytes, self.digest_method(self.salt + b"signer" + secret_key).digest() + ) + elif self.key_derivation == "hmac": + mac = hmac.new(secret_key, digestmod=self.digest_method) + mac.update(self.salt) + return mac.digest() + elif self.key_derivation == "none": + return secret_key + else: + raise TypeError("Unknown key derivation method") + + def get_signature(self, value: str | bytes) -> bytes: + """Returns the signature for the given value.""" + value = want_bytes(value) + key = self.derive_key() + sig = self.algorithm.get_signature(key, value) + return base64_encode(sig) + + def sign(self, value: str | bytes) -> bytes: + """Signs the given string.""" + value = want_bytes(value) + return value + self.sep + self.get_signature(value) + + def verify_signature(self, value: str | bytes, sig: str | bytes) -> bool: + """Verifies the signature for the given value.""" + try: + sig = base64_decode(sig) + except Exception: + return False + + value = want_bytes(value) + + for secret_key in reversed(self.secret_keys): + key = self.derive_key(secret_key) + + if self.algorithm.verify_signature(key, value, sig): + return True + + return False + + def unsign(self, signed_value: str | bytes) -> bytes: + """Unsigns the given string.""" + signed_value = want_bytes(signed_value) + + if self.sep not in signed_value: + raise BadSignature(f"No {self.sep!r} found in value") + + value, sig = signed_value.rsplit(self.sep, 1) + + if self.verify_signature(value, sig): + return value + + raise BadSignature(f"Signature {sig!r} does not match", payload=value) + + def validate(self, signed_value: str | bytes) -> bool: + """Only validates the given signed value. Returns ``True`` if + the signature exists and is valid. + """ + try: + self.unsign(signed_value) + return True + except BadSignature: + return False diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/timed.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/timed.py new file mode 100644 index 0000000..7384375 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/timed.py @@ -0,0 +1,228 @@ +from __future__ import annotations + +import collections.abc as cabc +import time +import typing as t +from datetime import datetime +from datetime import timezone + +from .encoding import base64_decode +from .encoding import base64_encode +from .encoding import bytes_to_int +from .encoding import int_to_bytes +from .encoding import want_bytes +from .exc import BadSignature +from .exc import BadTimeSignature +from .exc import SignatureExpired +from .serializer import _TSerialized +from .serializer import Serializer +from .signer import Signer + + +class TimestampSigner(Signer): + """Works like the regular :class:`.Signer` but also records the time + of the signing and can be used to expire signatures. The + :meth:`unsign` method can raise :exc:`.SignatureExpired` if the + unsigning failed because the signature is expired. + """ + + def get_timestamp(self) -> int: + """Returns the current timestamp. The function must return an + integer. + """ + return int(time.time()) + + def timestamp_to_datetime(self, ts: int) -> datetime: + """Convert the timestamp from :meth:`get_timestamp` into an + aware :class`datetime.datetime` in UTC. + + .. versionchanged:: 2.0 + The timestamp is returned as a timezone-aware ``datetime`` + in UTC rather than a naive ``datetime`` assumed to be UTC. + """ + return datetime.fromtimestamp(ts, tz=timezone.utc) + + def sign(self, value: str | bytes) -> bytes: + """Signs the given string and also attaches time information.""" + value = want_bytes(value) + timestamp = base64_encode(int_to_bytes(self.get_timestamp())) + sep = want_bytes(self.sep) + value = value + sep + timestamp + return value + sep + self.get_signature(value) + + # Ignore overlapping signatures check, return_timestamp is the only + # parameter that affects the return type. + + @t.overload + def unsign( # type: ignore[overload-overlap] + self, + signed_value: str | bytes, + max_age: int | None = None, + return_timestamp: t.Literal[False] = False, + ) -> bytes: ... + + @t.overload + def unsign( + self, + signed_value: str | bytes, + max_age: int | None = None, + return_timestamp: t.Literal[True] = True, + ) -> tuple[bytes, datetime]: ... + + def unsign( + self, + signed_value: str | bytes, + max_age: int | None = None, + return_timestamp: bool = False, + ) -> tuple[bytes, datetime] | bytes: + """Works like the regular :meth:`.Signer.unsign` but can also + validate the time. See the base docstring of the class for + the general behavior. If ``return_timestamp`` is ``True`` the + timestamp of the signature will be returned as an aware + :class:`datetime.datetime` object in UTC. + + .. versionchanged:: 2.0 + The timestamp is returned as a timezone-aware ``datetime`` + in UTC rather than a naive ``datetime`` assumed to be UTC. + """ + try: + result = super().unsign(signed_value) + sig_error = None + except BadSignature as e: + sig_error = e + result = e.payload or b"" + + sep = want_bytes(self.sep) + + # If there is no timestamp in the result there is something + # seriously wrong. In case there was a signature error, we raise + # that one directly, otherwise we have a weird situation in + # which we shouldn't have come except someone uses a time-based + # serializer on non-timestamp data, so catch that. + if sep not in result: + if sig_error: + raise sig_error + + raise BadTimeSignature("timestamp missing", payload=result) + + value, ts_bytes = result.rsplit(sep, 1) + ts_int: int | None = None + ts_dt: datetime | None = None + + try: + ts_int = bytes_to_int(base64_decode(ts_bytes)) + except Exception: + pass + + # Signature is *not* okay. Raise a proper error now that we have + # split the value and the timestamp. + if sig_error is not None: + if ts_int is not None: + try: + ts_dt = self.timestamp_to_datetime(ts_int) + except (ValueError, OSError, OverflowError) as exc: + # Windows raises OSError + # 32-bit raises OverflowError + raise BadTimeSignature( + "Malformed timestamp", payload=value + ) from exc + + raise BadTimeSignature(str(sig_error), payload=value, date_signed=ts_dt) + + # Signature was okay but the timestamp is actually not there or + # malformed. Should not happen, but we handle it anyway. + if ts_int is None: + raise BadTimeSignature("Malformed timestamp", payload=value) + + # Check timestamp is not older than max_age + if max_age is not None: + age = self.get_timestamp() - ts_int + + if age > max_age: + raise SignatureExpired( + f"Signature age {age} > {max_age} seconds", + payload=value, + date_signed=self.timestamp_to_datetime(ts_int), + ) + + if age < 0: + raise SignatureExpired( + f"Signature age {age} < 0 seconds", + payload=value, + date_signed=self.timestamp_to_datetime(ts_int), + ) + + if return_timestamp: + return value, self.timestamp_to_datetime(ts_int) + + return value + + def validate(self, signed_value: str | bytes, max_age: int | None = None) -> bool: + """Only validates the given signed value. Returns ``True`` if + the signature exists and is valid.""" + try: + self.unsign(signed_value, max_age=max_age) + return True + except BadSignature: + return False + + +class TimedSerializer(Serializer[_TSerialized]): + """Uses :class:`TimestampSigner` instead of the default + :class:`.Signer`. + """ + + default_signer: type[TimestampSigner] = TimestampSigner + + def iter_unsigners( + self, salt: str | bytes | None = None + ) -> cabc.Iterator[TimestampSigner]: + return t.cast("cabc.Iterator[TimestampSigner]", super().iter_unsigners(salt)) + + # TODO: Signature is incompatible because parameters were added + # before salt. + + def loads( # type: ignore[override] + self, + s: str | bytes, + max_age: int | None = None, + return_timestamp: bool = False, + salt: str | bytes | None = None, + ) -> t.Any: + """Reverse of :meth:`dumps`, raises :exc:`.BadSignature` if the + signature validation fails. If a ``max_age`` is provided it will + ensure the signature is not older than that time in seconds. In + case the signature is outdated, :exc:`.SignatureExpired` is + raised. All arguments are forwarded to the signer's + :meth:`~TimestampSigner.unsign` method. + """ + s = want_bytes(s) + last_exception = None + + for signer in self.iter_unsigners(salt): + try: + base64d, timestamp = signer.unsign( + s, max_age=max_age, return_timestamp=True + ) + payload = self.load_payload(base64d) + + if return_timestamp: + return payload, timestamp + + return payload + except SignatureExpired: + # The signature was unsigned successfully but was + # expired. Do not try the next signer. + raise + except BadSignature as err: + last_exception = err + + raise t.cast(BadSignature, last_exception) + + def loads_unsafe( # type: ignore[override] + self, + s: str | bytes, + max_age: int | None = None, + salt: str | bytes | None = None, + ) -> tuple[bool, t.Any]: + return self._loads_unsafe_impl(s, salt, load_kwargs={"max_age": max_age}) diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/url_safe.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/url_safe.py new file mode 100644 index 0000000..56a0793 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/itsdangerous/url_safe.py @@ -0,0 +1,83 @@ +from __future__ import annotations + +import typing as t +import zlib + +from ._json import _CompactJSON +from .encoding import base64_decode +from .encoding import base64_encode +from .exc import BadPayload +from .serializer import _PDataSerializer +from .serializer import Serializer +from .timed import TimedSerializer + + +class URLSafeSerializerMixin(Serializer[str]): + """Mixed in with a regular serializer it will attempt to zlib + compress the string to make it shorter if necessary. It will also + base64 encode the string so that it can safely be placed in a URL. + """ + + default_serializer: _PDataSerializer[str] = _CompactJSON + + def load_payload( + self, + payload: bytes, + *args: t.Any, + serializer: t.Any | None = None, + **kwargs: t.Any, + ) -> t.Any: + decompress = False + + if payload.startswith(b"."): + payload = payload[1:] + decompress = True + + try: + json = base64_decode(payload) + except Exception as e: + raise BadPayload( + "Could not base64 decode the payload because of an exception", + original_error=e, + ) from e + + if decompress: + try: + json = zlib.decompress(json) + except Exception as e: + raise BadPayload( + "Could not zlib decompress the payload before decoding the payload", + original_error=e, + ) from e + + return super().load_payload(json, *args, **kwargs) + + def dump_payload(self, obj: t.Any) -> bytes: + json = super().dump_payload(obj) + is_compressed = False + compressed = zlib.compress(json) + + if len(compressed) < (len(json) - 1): + json = compressed + is_compressed = True + + base64d = base64_encode(json) + + if is_compressed: + base64d = b"." + base64d + + return base64d + + +class URLSafeSerializer(URLSafeSerializerMixin, Serializer[str]): + """Works like :class:`.Serializer` but dumps and loads into a URL + safe string consisting of the upper and lowercase character of the + alphabet as well as ``'_'``, ``'-'`` and ``'.'``. + """ + + +class URLSafeTimedSerializer(URLSafeSerializerMixin, TimedSerializer[str]): + """Works like :class:`.TimedSerializer` but dumps and loads into a + URL safe string consisting of the upper and lowercase character of + the alphabet as well as ``'_'``, ``'-'`` and ``'.'``. + """ diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/__init__.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/__init__.py new file mode 100644 index 0000000..1a423a3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/__init__.py @@ -0,0 +1,38 @@ +"""Jinja is a template engine written in pure Python. It provides a +non-XML syntax that supports inline expressions and an optional +sandboxed environment. +""" + +from .bccache import BytecodeCache as BytecodeCache +from .bccache import FileSystemBytecodeCache as FileSystemBytecodeCache +from .bccache import MemcachedBytecodeCache as MemcachedBytecodeCache +from .environment import Environment as Environment +from .environment import Template as Template +from .exceptions import TemplateAssertionError as TemplateAssertionError +from .exceptions import TemplateError as TemplateError +from .exceptions import TemplateNotFound as TemplateNotFound +from .exceptions import TemplateRuntimeError as TemplateRuntimeError +from .exceptions import TemplatesNotFound as TemplatesNotFound +from .exceptions import TemplateSyntaxError as TemplateSyntaxError +from .exceptions import UndefinedError as UndefinedError +from .loaders import BaseLoader as BaseLoader +from .loaders import ChoiceLoader as ChoiceLoader +from .loaders import DictLoader as DictLoader +from .loaders import FileSystemLoader as FileSystemLoader +from .loaders import FunctionLoader as FunctionLoader +from .loaders import ModuleLoader as ModuleLoader +from .loaders import PackageLoader as PackageLoader +from .loaders import PrefixLoader as PrefixLoader +from .runtime import ChainableUndefined as ChainableUndefined +from .runtime import DebugUndefined as DebugUndefined +from .runtime import make_logging_undefined as make_logging_undefined +from .runtime import StrictUndefined as StrictUndefined +from .runtime import Undefined as Undefined +from .utils import clear_caches as clear_caches +from .utils import is_undefined as is_undefined +from .utils import pass_context as pass_context +from .utils import pass_environment as pass_environment +from .utils import pass_eval_context as pass_eval_context +from .utils import select_autoescape as select_autoescape + +__version__ = "3.1.6" diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/_identifier.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/_identifier.py new file mode 100644 index 0000000..928c150 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/_identifier.py @@ -0,0 +1,6 @@ +import re + +# generated by scripts/generate_identifier_pattern.py +pattern = re.compile( + r"[\w·̀-ͯ·҃-֑҇-ׇֽֿׁׂׅׄؐ-ًؚ-ٰٟۖ-ۜ۟-۪ۤۧۨ-ܑۭܰ-݊ަ-ް߫-߽߳ࠖ-࠙ࠛ-ࠣࠥ-ࠧࠩ-࡙࠭-࡛࣓-ࣣ࣡-ःऺ-़ा-ॏ॑-ॗॢॣঁ-ঃ়া-ৄেৈো-্ৗৢৣ৾ਁ-ਃ਼ਾ-ੂੇੈੋ-੍ੑੰੱੵઁ-ઃ઼ા-ૅે-ૉો-્ૢૣૺ-૿ଁ-ଃ଼ା-ୄେୈୋ-୍ୖୗୢୣஂா-ூெ-ைொ-்ௗఀ-ఄా-ౄె-ైొ-్ౕౖౢౣಁ-ಃ಼ಾ-ೄೆ-ೈೊ-್ೕೖೢೣഀ-ഃ഻഼ാ-ൄെ-ൈൊ-്ൗൢൣංඃ්ා-ුූෘ-ෟෲෳัิ-ฺ็-๎ັິ-ູົຼ່-ໍ༹༘༙༵༷༾༿ཱ-྄྆྇ྍ-ྗྙ-ྼ࿆ါ-ှၖ-ၙၞ-ၠၢ-ၤၧ-ၭၱ-ၴႂ-ႍႏႚ-ႝ፝-፟ᜒ-᜔ᜲ-᜴ᝒᝓᝲᝳ឴-៓៝᠋-᠍ᢅᢆᢩᤠ-ᤫᤰ-᤻ᨗ-ᨛᩕ-ᩞ᩠-᩿᩼᪰-᪽ᬀ-ᬄ᬴-᭄᭫-᭳ᮀ-ᮂᮡ-ᮭ᯦-᯳ᰤ-᰷᳐-᳔᳒-᳨᳭ᳲ-᳴᳷-᳹᷀-᷹᷻-᷿‿⁀⁔⃐-⃥⃜⃡-⃰℘℮⳯-⵿⳱ⷠ-〪ⷿ-゙゚〯꙯ꙴ-꙽ꚞꚟ꛰꛱ꠂ꠆ꠋꠣ-ꠧꢀꢁꢴ-ꣅ꣠-꣱ꣿꤦ-꤭ꥇ-꥓ꦀ-ꦃ꦳-꧀ꧥꨩ-ꨶꩃꩌꩍꩻ-ꩽꪰꪲ-ꪴꪷꪸꪾ꪿꫁ꫫ-ꫯꫵ꫶ꯣ-ꯪ꯬꯭ﬞ︀-️︠-︯︳︴﹍-﹏_𐇽𐋠𐍶-𐍺𐨁-𐨃𐨅𐨆𐨌-𐨏𐨸-𐨿𐨺𐫦𐫥𐴤-𐽆𐴧-𐽐𑀀-𑀂𑀸-𑁆𑁿-𑂂𑂰-𑂺𑄀-𑄂𑄧-𑄴𑅅𑅆𑅳𑆀-𑆂𑆳-𑇀𑇉-𑇌𑈬-𑈷𑈾𑋟-𑋪𑌀-𑌃𑌻𑌼𑌾-𑍄𑍇𑍈𑍋-𑍍𑍗𑍢𑍣𑍦-𑍬𑍰-𑍴𑐵-𑑆𑑞𑒰-𑓃𑖯-𑖵𑖸-𑗀𑗜𑗝𑘰-𑙀𑚫-𑚷𑜝-𑜫𑠬-𑠺𑨁-𑨊𑨳-𑨹𑨻-𑨾𑩇𑩑-𑩛𑪊-𑪙𑰯-𑰶𑰸-𑰿𑲒-𑲧𑲩-𑲶𑴱-𑴶𑴺𑴼𑴽𑴿-𑵅𑵇𑶊-𑶎𑶐𑶑𑶓-𑶗𑻳-𑻶𖫰-𖫴𖬰-𖬶𖽑-𖽾𖾏-𖾒𛲝𛲞𝅥-𝅩𝅭-𝅲𝅻-𝆂𝆅-𝆋𝆪-𝆭𝉂-𝉄𝨀-𝨶𝨻-𝩬𝩵𝪄𝪛-𝪟𝪡-𝪯𞀀-𞀆𞀈-𞀘𞀛-𞀡𞀣𞀤𞀦-𞣐𞀪-𞣖𞥄-𞥊󠄀-󠇯]+" # noqa: B950 +) diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/async_utils.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/async_utils.py new file mode 100644 index 0000000..f0c1402 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/async_utils.py @@ -0,0 +1,99 @@ +import inspect +import typing as t +from functools import WRAPPER_ASSIGNMENTS +from functools import wraps + +from .utils import _PassArg +from .utils import pass_eval_context + +if t.TYPE_CHECKING: + import typing_extensions as te + +V = t.TypeVar("V") + + +def async_variant(normal_func): # type: ignore + def decorator(async_func): # type: ignore + pass_arg = _PassArg.from_obj(normal_func) + need_eval_context = pass_arg is None + + if pass_arg is _PassArg.environment: + + def is_async(args: t.Any) -> bool: + return t.cast(bool, args[0].is_async) + + else: + + def is_async(args: t.Any) -> bool: + return t.cast(bool, args[0].environment.is_async) + + # Take the doc and annotations from the sync function, but the + # name from the async function. Pallets-Sphinx-Themes + # build_function_directive expects __wrapped__ to point to the + # sync function. + async_func_attrs = ("__module__", "__name__", "__qualname__") + normal_func_attrs = tuple(set(WRAPPER_ASSIGNMENTS).difference(async_func_attrs)) + + @wraps(normal_func, assigned=normal_func_attrs) + @wraps(async_func, assigned=async_func_attrs, updated=()) + def wrapper(*args, **kwargs): # type: ignore + b = is_async(args) + + if need_eval_context: + args = args[1:] + + if b: + return async_func(*args, **kwargs) + + return normal_func(*args, **kwargs) + + if need_eval_context: + wrapper = pass_eval_context(wrapper) + + wrapper.jinja_async_variant = True # type: ignore[attr-defined] + return wrapper + + return decorator + + +_common_primitives = {int, float, bool, str, list, dict, tuple, type(None)} + + +async def auto_await(value: t.Union[t.Awaitable["V"], "V"]) -> "V": + # Avoid a costly call to isawaitable + if type(value) in _common_primitives: + return t.cast("V", value) + + if inspect.isawaitable(value): + return await t.cast("t.Awaitable[V]", value) + + return value + + +class _IteratorToAsyncIterator(t.Generic[V]): + def __init__(self, iterator: "t.Iterator[V]"): + self._iterator = iterator + + def __aiter__(self) -> "te.Self": + return self + + async def __anext__(self) -> V: + try: + return next(self._iterator) + except StopIteration as e: + raise StopAsyncIteration(e.value) from e + + +def auto_aiter( + iterable: "t.Union[t.AsyncIterable[V], t.Iterable[V]]", +) -> "t.AsyncIterator[V]": + if hasattr(iterable, "__aiter__"): + return iterable.__aiter__() + else: + return _IteratorToAsyncIterator(iter(iterable)) + + +async def auto_to_list( + value: "t.Union[t.AsyncIterable[V], t.Iterable[V]]", +) -> t.List["V"]: + return [x async for x in auto_aiter(value)] diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/bccache.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/bccache.py new file mode 100644 index 0000000..ada8b09 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/bccache.py @@ -0,0 +1,408 @@ +"""The optional bytecode cache system. This is useful if you have very +complex template situations and the compilation of all those templates +slows down your application too much. + +Situations where this is useful are often forking web applications that +are initialized on the first request. +""" + +import errno +import fnmatch +import marshal +import os +import pickle +import stat +import sys +import tempfile +import typing as t +from hashlib import sha1 +from io import BytesIO +from types import CodeType + +if t.TYPE_CHECKING: + import typing_extensions as te + + from .environment import Environment + + class _MemcachedClient(te.Protocol): + def get(self, key: str) -> bytes: ... + + def set( + self, key: str, value: bytes, timeout: t.Optional[int] = None + ) -> None: ... + + +bc_version = 5 +# Magic bytes to identify Jinja bytecode cache files. Contains the +# Python major and minor version to avoid loading incompatible bytecode +# if a project upgrades its Python version. +bc_magic = ( + b"j2" + + pickle.dumps(bc_version, 2) + + pickle.dumps((sys.version_info[0] << 24) | sys.version_info[1], 2) +) + + +class Bucket: + """Buckets are used to store the bytecode for one template. It's created + and initialized by the bytecode cache and passed to the loading functions. + + The buckets get an internal checksum from the cache assigned and use this + to automatically reject outdated cache material. Individual bytecode + cache subclasses don't have to care about cache invalidation. + """ + + def __init__(self, environment: "Environment", key: str, checksum: str) -> None: + self.environment = environment + self.key = key + self.checksum = checksum + self.reset() + + def reset(self) -> None: + """Resets the bucket (unloads the bytecode).""" + self.code: t.Optional[CodeType] = None + + def load_bytecode(self, f: t.BinaryIO) -> None: + """Loads bytecode from a file or file like object.""" + # make sure the magic header is correct + magic = f.read(len(bc_magic)) + if magic != bc_magic: + self.reset() + return + # the source code of the file changed, we need to reload + checksum = pickle.load(f) + if self.checksum != checksum: + self.reset() + return + # if marshal_load fails then we need to reload + try: + self.code = marshal.load(f) + except (EOFError, ValueError, TypeError): + self.reset() + return + + def write_bytecode(self, f: t.IO[bytes]) -> None: + """Dump the bytecode into the file or file like object passed.""" + if self.code is None: + raise TypeError("can't write empty bucket") + f.write(bc_magic) + pickle.dump(self.checksum, f, 2) + marshal.dump(self.code, f) + + def bytecode_from_string(self, string: bytes) -> None: + """Load bytecode from bytes.""" + self.load_bytecode(BytesIO(string)) + + def bytecode_to_string(self) -> bytes: + """Return the bytecode as bytes.""" + out = BytesIO() + self.write_bytecode(out) + return out.getvalue() + + +class BytecodeCache: + """To implement your own bytecode cache you have to subclass this class + and override :meth:`load_bytecode` and :meth:`dump_bytecode`. Both of + these methods are passed a :class:`~jinja2.bccache.Bucket`. + + A very basic bytecode cache that saves the bytecode on the file system:: + + from os import path + + class MyCache(BytecodeCache): + + def __init__(self, directory): + self.directory = directory + + def load_bytecode(self, bucket): + filename = path.join(self.directory, bucket.key) + if path.exists(filename): + with open(filename, 'rb') as f: + bucket.load_bytecode(f) + + def dump_bytecode(self, bucket): + filename = path.join(self.directory, bucket.key) + with open(filename, 'wb') as f: + bucket.write_bytecode(f) + + A more advanced version of a filesystem based bytecode cache is part of + Jinja. + """ + + def load_bytecode(self, bucket: Bucket) -> None: + """Subclasses have to override this method to load bytecode into a + bucket. If they are not able to find code in the cache for the + bucket, it must not do anything. + """ + raise NotImplementedError() + + def dump_bytecode(self, bucket: Bucket) -> None: + """Subclasses have to override this method to write the bytecode + from a bucket back to the cache. If it unable to do so it must not + fail silently but raise an exception. + """ + raise NotImplementedError() + + def clear(self) -> None: + """Clears the cache. This method is not used by Jinja but should be + implemented to allow applications to clear the bytecode cache used + by a particular environment. + """ + + def get_cache_key( + self, name: str, filename: t.Optional[t.Union[str]] = None + ) -> str: + """Returns the unique hash key for this template name.""" + hash = sha1(name.encode("utf-8")) + + if filename is not None: + hash.update(f"|{filename}".encode()) + + return hash.hexdigest() + + def get_source_checksum(self, source: str) -> str: + """Returns a checksum for the source.""" + return sha1(source.encode("utf-8")).hexdigest() + + def get_bucket( + self, + environment: "Environment", + name: str, + filename: t.Optional[str], + source: str, + ) -> Bucket: + """Return a cache bucket for the given template. All arguments are + mandatory but filename may be `None`. + """ + key = self.get_cache_key(name, filename) + checksum = self.get_source_checksum(source) + bucket = Bucket(environment, key, checksum) + self.load_bytecode(bucket) + return bucket + + def set_bucket(self, bucket: Bucket) -> None: + """Put the bucket into the cache.""" + self.dump_bytecode(bucket) + + +class FileSystemBytecodeCache(BytecodeCache): + """A bytecode cache that stores bytecode on the filesystem. It accepts + two arguments: The directory where the cache items are stored and a + pattern string that is used to build the filename. + + If no directory is specified a default cache directory is selected. On + Windows the user's temp directory is used, on UNIX systems a directory + is created for the user in the system temp directory. + + The pattern can be used to have multiple separate caches operate on the + same directory. The default pattern is ``'__jinja2_%s.cache'``. ``%s`` + is replaced with the cache key. + + >>> bcc = FileSystemBytecodeCache('/tmp/jinja_cache', '%s.cache') + + This bytecode cache supports clearing of the cache using the clear method. + """ + + def __init__( + self, directory: t.Optional[str] = None, pattern: str = "__jinja2_%s.cache" + ) -> None: + if directory is None: + directory = self._get_default_cache_dir() + self.directory = directory + self.pattern = pattern + + def _get_default_cache_dir(self) -> str: + def _unsafe_dir() -> "te.NoReturn": + raise RuntimeError( + "Cannot determine safe temp directory. You " + "need to explicitly provide one." + ) + + tmpdir = tempfile.gettempdir() + + # On windows the temporary directory is used specific unless + # explicitly forced otherwise. We can just use that. + if os.name == "nt": + return tmpdir + if not hasattr(os, "getuid"): + _unsafe_dir() + + dirname = f"_jinja2-cache-{os.getuid()}" + actual_dir = os.path.join(tmpdir, dirname) + + try: + os.mkdir(actual_dir, stat.S_IRWXU) + except OSError as e: + if e.errno != errno.EEXIST: + raise + try: + os.chmod(actual_dir, stat.S_IRWXU) + actual_dir_stat = os.lstat(actual_dir) + if ( + actual_dir_stat.st_uid != os.getuid() + or not stat.S_ISDIR(actual_dir_stat.st_mode) + or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU + ): + _unsafe_dir() + except OSError as e: + if e.errno != errno.EEXIST: + raise + + actual_dir_stat = os.lstat(actual_dir) + if ( + actual_dir_stat.st_uid != os.getuid() + or not stat.S_ISDIR(actual_dir_stat.st_mode) + or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU + ): + _unsafe_dir() + + return actual_dir + + def _get_cache_filename(self, bucket: Bucket) -> str: + return os.path.join(self.directory, self.pattern % (bucket.key,)) + + def load_bytecode(self, bucket: Bucket) -> None: + filename = self._get_cache_filename(bucket) + + # Don't test for existence before opening the file, since the + # file could disappear after the test before the open. + try: + f = open(filename, "rb") + except (FileNotFoundError, IsADirectoryError, PermissionError): + # PermissionError can occur on Windows when an operation is + # in progress, such as calling clear(). + return + + with f: + bucket.load_bytecode(f) + + def dump_bytecode(self, bucket: Bucket) -> None: + # Write to a temporary file, then rename to the real name after + # writing. This avoids another process reading the file before + # it is fully written. + name = self._get_cache_filename(bucket) + f = tempfile.NamedTemporaryFile( + mode="wb", + dir=os.path.dirname(name), + prefix=os.path.basename(name), + suffix=".tmp", + delete=False, + ) + + def remove_silent() -> None: + try: + os.remove(f.name) + except OSError: + # Another process may have called clear(). On Windows, + # another program may be holding the file open. + pass + + try: + with f: + bucket.write_bytecode(f) + except BaseException: + remove_silent() + raise + + try: + os.replace(f.name, name) + except OSError: + # Another process may have called clear(). On Windows, + # another program may be holding the file open. + remove_silent() + except BaseException: + remove_silent() + raise + + def clear(self) -> None: + # imported lazily here because google app-engine doesn't support + # write access on the file system and the function does not exist + # normally. + from os import remove + + files = fnmatch.filter(os.listdir(self.directory), self.pattern % ("*",)) + for filename in files: + try: + remove(os.path.join(self.directory, filename)) + except OSError: + pass + + +class MemcachedBytecodeCache(BytecodeCache): + """This class implements a bytecode cache that uses a memcache cache for + storing the information. It does not enforce a specific memcache library + (tummy's memcache or cmemcache) but will accept any class that provides + the minimal interface required. + + Libraries compatible with this class: + + - `cachelib `_ + - `python-memcached `_ + + (Unfortunately the django cache interface is not compatible because it + does not support storing binary data, only text. You can however pass + the underlying cache client to the bytecode cache which is available + as `django.core.cache.cache._client`.) + + The minimal interface for the client passed to the constructor is this: + + .. class:: MinimalClientInterface + + .. method:: set(key, value[, timeout]) + + Stores the bytecode in the cache. `value` is a string and + `timeout` the timeout of the key. If timeout is not provided + a default timeout or no timeout should be assumed, if it's + provided it's an integer with the number of seconds the cache + item should exist. + + .. method:: get(key) + + Returns the value for the cache key. If the item does not + exist in the cache the return value must be `None`. + + The other arguments to the constructor are the prefix for all keys that + is added before the actual cache key and the timeout for the bytecode in + the cache system. We recommend a high (or no) timeout. + + This bytecode cache does not support clearing of used items in the cache. + The clear method is a no-operation function. + + .. versionadded:: 2.7 + Added support for ignoring memcache errors through the + `ignore_memcache_errors` parameter. + """ + + def __init__( + self, + client: "_MemcachedClient", + prefix: str = "jinja2/bytecode/", + timeout: t.Optional[int] = None, + ignore_memcache_errors: bool = True, + ): + self.client = client + self.prefix = prefix + self.timeout = timeout + self.ignore_memcache_errors = ignore_memcache_errors + + def load_bytecode(self, bucket: Bucket) -> None: + try: + code = self.client.get(self.prefix + bucket.key) + except Exception: + if not self.ignore_memcache_errors: + raise + else: + bucket.bytecode_from_string(code) + + def dump_bytecode(self, bucket: Bucket) -> None: + key = self.prefix + bucket.key + value = bucket.bytecode_to_string() + + try: + if self.timeout is not None: + self.client.set(key, value, self.timeout) + else: + self.client.set(key, value) + except Exception: + if not self.ignore_memcache_errors: + raise diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/compiler.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/compiler.py new file mode 100644 index 0000000..a4ff6a1 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/compiler.py @@ -0,0 +1,1998 @@ +"""Compiles nodes from the parser into Python code.""" + +import typing as t +from contextlib import contextmanager +from functools import update_wrapper +from io import StringIO +from itertools import chain +from keyword import iskeyword as is_python_keyword + +from markupsafe import escape +from markupsafe import Markup + +from . import nodes +from .exceptions import TemplateAssertionError +from .idtracking import Symbols +from .idtracking import VAR_LOAD_ALIAS +from .idtracking import VAR_LOAD_PARAMETER +from .idtracking import VAR_LOAD_RESOLVE +from .idtracking import VAR_LOAD_UNDEFINED +from .nodes import EvalContext +from .optimizer import Optimizer +from .utils import _PassArg +from .utils import concat +from .visitor import NodeVisitor + +if t.TYPE_CHECKING: + import typing_extensions as te + + from .environment import Environment + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) + +operators = { + "eq": "==", + "ne": "!=", + "gt": ">", + "gteq": ">=", + "lt": "<", + "lteq": "<=", + "in": "in", + "notin": "not in", +} + + +def optimizeconst(f: F) -> F: + def new_func( + self: "CodeGenerator", node: nodes.Expr, frame: "Frame", **kwargs: t.Any + ) -> t.Any: + # Only optimize if the frame is not volatile + if self.optimizer is not None and not frame.eval_ctx.volatile: + new_node = self.optimizer.visit(node, frame.eval_ctx) + + if new_node != node: + return self.visit(new_node, frame) + + return f(self, node, frame, **kwargs) + + return update_wrapper(new_func, f) # type: ignore[return-value] + + +def _make_binop(op: str) -> t.Callable[["CodeGenerator", nodes.BinExpr, "Frame"], None]: + @optimizeconst + def visitor(self: "CodeGenerator", node: nodes.BinExpr, frame: Frame) -> None: + if ( + self.environment.sandboxed and op in self.environment.intercepted_binops # type: ignore + ): + self.write(f"environment.call_binop(context, {op!r}, ") + self.visit(node.left, frame) + self.write(", ") + self.visit(node.right, frame) + else: + self.write("(") + self.visit(node.left, frame) + self.write(f" {op} ") + self.visit(node.right, frame) + + self.write(")") + + return visitor + + +def _make_unop( + op: str, +) -> t.Callable[["CodeGenerator", nodes.UnaryExpr, "Frame"], None]: + @optimizeconst + def visitor(self: "CodeGenerator", node: nodes.UnaryExpr, frame: Frame) -> None: + if ( + self.environment.sandboxed and op in self.environment.intercepted_unops # type: ignore + ): + self.write(f"environment.call_unop(context, {op!r}, ") + self.visit(node.node, frame) + else: + self.write("(" + op) + self.visit(node.node, frame) + + self.write(")") + + return visitor + + +def generate( + node: nodes.Template, + environment: "Environment", + name: t.Optional[str], + filename: t.Optional[str], + stream: t.Optional[t.TextIO] = None, + defer_init: bool = False, + optimized: bool = True, +) -> t.Optional[str]: + """Generate the python source for a node tree.""" + if not isinstance(node, nodes.Template): + raise TypeError("Can't compile non template nodes") + + generator = environment.code_generator_class( + environment, name, filename, stream, defer_init, optimized + ) + generator.visit(node) + + if stream is None: + return generator.stream.getvalue() # type: ignore + + return None + + +def has_safe_repr(value: t.Any) -> bool: + """Does the node have a safe representation?""" + if value is None or value is NotImplemented or value is Ellipsis: + return True + + if type(value) in {bool, int, float, complex, range, str, Markup}: + return True + + if type(value) in {tuple, list, set, frozenset}: + return all(has_safe_repr(v) for v in value) + + if type(value) is dict: # noqa E721 + return all(has_safe_repr(k) and has_safe_repr(v) for k, v in value.items()) + + return False + + +def find_undeclared( + nodes: t.Iterable[nodes.Node], names: t.Iterable[str] +) -> t.Set[str]: + """Check if the names passed are accessed undeclared. The return value + is a set of all the undeclared names from the sequence of names found. + """ + visitor = UndeclaredNameVisitor(names) + try: + for node in nodes: + visitor.visit(node) + except VisitorExit: + pass + return visitor.undeclared + + +class MacroRef: + def __init__(self, node: t.Union[nodes.Macro, nodes.CallBlock]) -> None: + self.node = node + self.accesses_caller = False + self.accesses_kwargs = False + self.accesses_varargs = False + + +class Frame: + """Holds compile time information for us.""" + + def __init__( + self, + eval_ctx: EvalContext, + parent: t.Optional["Frame"] = None, + level: t.Optional[int] = None, + ) -> None: + self.eval_ctx = eval_ctx + + # the parent of this frame + self.parent = parent + + if parent is None: + self.symbols = Symbols(level=level) + + # in some dynamic inheritance situations the compiler needs to add + # write tests around output statements. + self.require_output_check = False + + # inside some tags we are using a buffer rather than yield statements. + # this for example affects {% filter %} or {% macro %}. If a frame + # is buffered this variable points to the name of the list used as + # buffer. + self.buffer: t.Optional[str] = None + + # the name of the block we're in, otherwise None. + self.block: t.Optional[str] = None + + else: + self.symbols = Symbols(parent.symbols, level=level) + self.require_output_check = parent.require_output_check + self.buffer = parent.buffer + self.block = parent.block + + # a toplevel frame is the root + soft frames such as if conditions. + self.toplevel = False + + # the root frame is basically just the outermost frame, so no if + # conditions. This information is used to optimize inheritance + # situations. + self.rootlevel = False + + # variables set inside of loops and blocks should not affect outer frames, + # but they still needs to be kept track of as part of the active context. + self.loop_frame = False + self.block_frame = False + + # track whether the frame is being used in an if-statement or conditional + # expression as it determines which errors should be raised during runtime + # or compile time. + self.soft_frame = False + + def copy(self) -> "te.Self": + """Create a copy of the current one.""" + rv = object.__new__(self.__class__) + rv.__dict__.update(self.__dict__) + rv.symbols = self.symbols.copy() + return rv + + def inner(self, isolated: bool = False) -> "Frame": + """Return an inner frame.""" + if isolated: + return Frame(self.eval_ctx, level=self.symbols.level + 1) + return Frame(self.eval_ctx, self) + + def soft(self) -> "te.Self": + """Return a soft frame. A soft frame may not be modified as + standalone thing as it shares the resources with the frame it + was created of, but it's not a rootlevel frame any longer. + + This is only used to implement if-statements and conditional + expressions. + """ + rv = self.copy() + rv.rootlevel = False + rv.soft_frame = True + return rv + + __copy__ = copy + + +class VisitorExit(RuntimeError): + """Exception used by the `UndeclaredNameVisitor` to signal a stop.""" + + +class DependencyFinderVisitor(NodeVisitor): + """A visitor that collects filter and test calls.""" + + def __init__(self) -> None: + self.filters: t.Set[str] = set() + self.tests: t.Set[str] = set() + + def visit_Filter(self, node: nodes.Filter) -> None: + self.generic_visit(node) + self.filters.add(node.name) + + def visit_Test(self, node: nodes.Test) -> None: + self.generic_visit(node) + self.tests.add(node.name) + + def visit_Block(self, node: nodes.Block) -> None: + """Stop visiting at blocks.""" + + +class UndeclaredNameVisitor(NodeVisitor): + """A visitor that checks if a name is accessed without being + declared. This is different from the frame visitor as it will + not stop at closure frames. + """ + + def __init__(self, names: t.Iterable[str]) -> None: + self.names = set(names) + self.undeclared: t.Set[str] = set() + + def visit_Name(self, node: nodes.Name) -> None: + if node.ctx == "load" and node.name in self.names: + self.undeclared.add(node.name) + if self.undeclared == self.names: + raise VisitorExit() + else: + self.names.discard(node.name) + + def visit_Block(self, node: nodes.Block) -> None: + """Stop visiting a blocks.""" + + +class CompilerExit(Exception): + """Raised if the compiler encountered a situation where it just + doesn't make sense to further process the code. Any block that + raises such an exception is not further processed. + """ + + +class CodeGenerator(NodeVisitor): + def __init__( + self, + environment: "Environment", + name: t.Optional[str], + filename: t.Optional[str], + stream: t.Optional[t.TextIO] = None, + defer_init: bool = False, + optimized: bool = True, + ) -> None: + if stream is None: + stream = StringIO() + self.environment = environment + self.name = name + self.filename = filename + self.stream = stream + self.created_block_context = False + self.defer_init = defer_init + self.optimizer: t.Optional[Optimizer] = None + + if optimized: + self.optimizer = Optimizer(environment) + + # aliases for imports + self.import_aliases: t.Dict[str, str] = {} + + # a registry for all blocks. Because blocks are moved out + # into the global python scope they are registered here + self.blocks: t.Dict[str, nodes.Block] = {} + + # the number of extends statements so far + self.extends_so_far = 0 + + # some templates have a rootlevel extends. In this case we + # can safely assume that we're a child template and do some + # more optimizations. + self.has_known_extends = False + + # the current line number + self.code_lineno = 1 + + # registry of all filters and tests (global, not block local) + self.tests: t.Dict[str, str] = {} + self.filters: t.Dict[str, str] = {} + + # the debug information + self.debug_info: t.List[t.Tuple[int, int]] = [] + self._write_debug_info: t.Optional[int] = None + + # the number of new lines before the next write() + self._new_lines = 0 + + # the line number of the last written statement + self._last_line = 0 + + # true if nothing was written so far. + self._first_write = True + + # used by the `temporary_identifier` method to get new + # unique, temporary identifier + self._last_identifier = 0 + + # the current indentation + self._indentation = 0 + + # Tracks toplevel assignments + self._assign_stack: t.List[t.Set[str]] = [] + + # Tracks parameter definition blocks + self._param_def_block: t.List[t.Set[str]] = [] + + # Tracks the current context. + self._context_reference_stack = ["context"] + + @property + def optimized(self) -> bool: + return self.optimizer is not None + + # -- Various compilation helpers + + def fail(self, msg: str, lineno: int) -> "te.NoReturn": + """Fail with a :exc:`TemplateAssertionError`.""" + raise TemplateAssertionError(msg, lineno, self.name, self.filename) + + def temporary_identifier(self) -> str: + """Get a new unique identifier.""" + self._last_identifier += 1 + return f"t_{self._last_identifier}" + + def buffer(self, frame: Frame) -> None: + """Enable buffering for the frame from that point onwards.""" + frame.buffer = self.temporary_identifier() + self.writeline(f"{frame.buffer} = []") + + def return_buffer_contents( + self, frame: Frame, force_unescaped: bool = False + ) -> None: + """Return the buffer contents of the frame.""" + if not force_unescaped: + if frame.eval_ctx.volatile: + self.writeline("if context.eval_ctx.autoescape:") + self.indent() + self.writeline(f"return Markup(concat({frame.buffer}))") + self.outdent() + self.writeline("else:") + self.indent() + self.writeline(f"return concat({frame.buffer})") + self.outdent() + return + elif frame.eval_ctx.autoescape: + self.writeline(f"return Markup(concat({frame.buffer}))") + return + self.writeline(f"return concat({frame.buffer})") + + def indent(self) -> None: + """Indent by one.""" + self._indentation += 1 + + def outdent(self, step: int = 1) -> None: + """Outdent by step.""" + self._indentation -= step + + def start_write(self, frame: Frame, node: t.Optional[nodes.Node] = None) -> None: + """Yield or write into the frame buffer.""" + if frame.buffer is None: + self.writeline("yield ", node) + else: + self.writeline(f"{frame.buffer}.append(", node) + + def end_write(self, frame: Frame) -> None: + """End the writing process started by `start_write`.""" + if frame.buffer is not None: + self.write(")") + + def simple_write( + self, s: str, frame: Frame, node: t.Optional[nodes.Node] = None + ) -> None: + """Simple shortcut for start_write + write + end_write.""" + self.start_write(frame, node) + self.write(s) + self.end_write(frame) + + def blockvisit(self, nodes: t.Iterable[nodes.Node], frame: Frame) -> None: + """Visit a list of nodes as block in a frame. If the current frame + is no buffer a dummy ``if 0: yield None`` is written automatically. + """ + try: + self.writeline("pass") + for node in nodes: + self.visit(node, frame) + except CompilerExit: + pass + + def write(self, x: str) -> None: + """Write a string into the output stream.""" + if self._new_lines: + if not self._first_write: + self.stream.write("\n" * self._new_lines) + self.code_lineno += self._new_lines + if self._write_debug_info is not None: + self.debug_info.append((self._write_debug_info, self.code_lineno)) + self._write_debug_info = None + self._first_write = False + self.stream.write(" " * self._indentation) + self._new_lines = 0 + self.stream.write(x) + + def writeline( + self, x: str, node: t.Optional[nodes.Node] = None, extra: int = 0 + ) -> None: + """Combination of newline and write.""" + self.newline(node, extra) + self.write(x) + + def newline(self, node: t.Optional[nodes.Node] = None, extra: int = 0) -> None: + """Add one or more newlines before the next write.""" + self._new_lines = max(self._new_lines, 1 + extra) + if node is not None and node.lineno != self._last_line: + self._write_debug_info = node.lineno + self._last_line = node.lineno + + def signature( + self, + node: t.Union[nodes.Call, nodes.Filter, nodes.Test], + frame: Frame, + extra_kwargs: t.Optional[t.Mapping[str, t.Any]] = None, + ) -> None: + """Writes a function call to the stream for the current node. + A leading comma is added automatically. The extra keyword + arguments may not include python keywords otherwise a syntax + error could occur. The extra keyword arguments should be given + as python dict. + """ + # if any of the given keyword arguments is a python keyword + # we have to make sure that no invalid call is created. + kwarg_workaround = any( + is_python_keyword(t.cast(str, k)) + for k in chain((x.key for x in node.kwargs), extra_kwargs or ()) + ) + + for arg in node.args: + self.write(", ") + self.visit(arg, frame) + + if not kwarg_workaround: + for kwarg in node.kwargs: + self.write(", ") + self.visit(kwarg, frame) + if extra_kwargs is not None: + for key, value in extra_kwargs.items(): + self.write(f", {key}={value}") + if node.dyn_args: + self.write(", *") + self.visit(node.dyn_args, frame) + + if kwarg_workaround: + if node.dyn_kwargs is not None: + self.write(", **dict({") + else: + self.write(", **{") + for kwarg in node.kwargs: + self.write(f"{kwarg.key!r}: ") + self.visit(kwarg.value, frame) + self.write(", ") + if extra_kwargs is not None: + for key, value in extra_kwargs.items(): + self.write(f"{key!r}: {value}, ") + if node.dyn_kwargs is not None: + self.write("}, **") + self.visit(node.dyn_kwargs, frame) + self.write(")") + else: + self.write("}") + + elif node.dyn_kwargs is not None: + self.write(", **") + self.visit(node.dyn_kwargs, frame) + + def pull_dependencies(self, nodes: t.Iterable[nodes.Node]) -> None: + """Find all filter and test names used in the template and + assign them to variables in the compiled namespace. Checking + that the names are registered with the environment is done when + compiling the Filter and Test nodes. If the node is in an If or + CondExpr node, the check is done at runtime instead. + + .. versionchanged:: 3.0 + Filters and tests in If and CondExpr nodes are checked at + runtime instead of compile time. + """ + visitor = DependencyFinderVisitor() + + for node in nodes: + visitor.visit(node) + + for id_map, names, dependency in ( + (self.filters, visitor.filters, "filters"), + ( + self.tests, + visitor.tests, + "tests", + ), + ): + for name in sorted(names): + if name not in id_map: + id_map[name] = self.temporary_identifier() + + # add check during runtime that dependencies used inside of executed + # blocks are defined, as this step may be skipped during compile time + self.writeline("try:") + self.indent() + self.writeline(f"{id_map[name]} = environment.{dependency}[{name!r}]") + self.outdent() + self.writeline("except KeyError:") + self.indent() + self.writeline("@internalcode") + self.writeline(f"def {id_map[name]}(*unused):") + self.indent() + self.writeline( + f'raise TemplateRuntimeError("No {dependency[:-1]}' + f' named {name!r} found.")' + ) + self.outdent() + self.outdent() + + def enter_frame(self, frame: Frame) -> None: + undefs = [] + for target, (action, param) in frame.symbols.loads.items(): + if action == VAR_LOAD_PARAMETER: + pass + elif action == VAR_LOAD_RESOLVE: + self.writeline(f"{target} = {self.get_resolve_func()}({param!r})") + elif action == VAR_LOAD_ALIAS: + self.writeline(f"{target} = {param}") + elif action == VAR_LOAD_UNDEFINED: + undefs.append(target) + else: + raise NotImplementedError("unknown load instruction") + if undefs: + self.writeline(f"{' = '.join(undefs)} = missing") + + def leave_frame(self, frame: Frame, with_python_scope: bool = False) -> None: + if not with_python_scope: + undefs = [] + for target in frame.symbols.loads: + undefs.append(target) + if undefs: + self.writeline(f"{' = '.join(undefs)} = missing") + + def choose_async(self, async_value: str = "async ", sync_value: str = "") -> str: + return async_value if self.environment.is_async else sync_value + + def func(self, name: str) -> str: + return f"{self.choose_async()}def {name}" + + def macro_body( + self, node: t.Union[nodes.Macro, nodes.CallBlock], frame: Frame + ) -> t.Tuple[Frame, MacroRef]: + """Dump the function def of a macro or call block.""" + frame = frame.inner() + frame.symbols.analyze_node(node) + macro_ref = MacroRef(node) + + explicit_caller = None + skip_special_params = set() + args = [] + + for idx, arg in enumerate(node.args): + if arg.name == "caller": + explicit_caller = idx + if arg.name in ("kwargs", "varargs"): + skip_special_params.add(arg.name) + args.append(frame.symbols.ref(arg.name)) + + undeclared = find_undeclared(node.body, ("caller", "kwargs", "varargs")) + + if "caller" in undeclared: + # In older Jinja versions there was a bug that allowed caller + # to retain the special behavior even if it was mentioned in + # the argument list. However thankfully this was only really + # working if it was the last argument. So we are explicitly + # checking this now and error out if it is anywhere else in + # the argument list. + if explicit_caller is not None: + try: + node.defaults[explicit_caller - len(node.args)] + except IndexError: + self.fail( + "When defining macros or call blocks the " + 'special "caller" argument must be omitted ' + "or be given a default.", + node.lineno, + ) + else: + args.append(frame.symbols.declare_parameter("caller")) + macro_ref.accesses_caller = True + if "kwargs" in undeclared and "kwargs" not in skip_special_params: + args.append(frame.symbols.declare_parameter("kwargs")) + macro_ref.accesses_kwargs = True + if "varargs" in undeclared and "varargs" not in skip_special_params: + args.append(frame.symbols.declare_parameter("varargs")) + macro_ref.accesses_varargs = True + + # macros are delayed, they never require output checks + frame.require_output_check = False + frame.symbols.analyze_node(node) + self.writeline(f"{self.func('macro')}({', '.join(args)}):", node) + self.indent() + + self.buffer(frame) + self.enter_frame(frame) + + self.push_parameter_definitions(frame) + for idx, arg in enumerate(node.args): + ref = frame.symbols.ref(arg.name) + self.writeline(f"if {ref} is missing:") + self.indent() + try: + default = node.defaults[idx - len(node.args)] + except IndexError: + self.writeline( + f'{ref} = undefined("parameter {arg.name!r} was not provided",' + f" name={arg.name!r})" + ) + else: + self.writeline(f"{ref} = ") + self.visit(default, frame) + self.mark_parameter_stored(ref) + self.outdent() + self.pop_parameter_definitions() + + self.blockvisit(node.body, frame) + self.return_buffer_contents(frame, force_unescaped=True) + self.leave_frame(frame, with_python_scope=True) + self.outdent() + + return frame, macro_ref + + def macro_def(self, macro_ref: MacroRef, frame: Frame) -> None: + """Dump the macro definition for the def created by macro_body.""" + arg_tuple = ", ".join(repr(x.name) for x in macro_ref.node.args) + name = getattr(macro_ref.node, "name", None) + if len(macro_ref.node.args) == 1: + arg_tuple += "," + self.write( + f"Macro(environment, macro, {name!r}, ({arg_tuple})," + f" {macro_ref.accesses_kwargs!r}, {macro_ref.accesses_varargs!r}," + f" {macro_ref.accesses_caller!r}, context.eval_ctx.autoescape)" + ) + + def position(self, node: nodes.Node) -> str: + """Return a human readable position for the node.""" + rv = f"line {node.lineno}" + if self.name is not None: + rv = f"{rv} in {self.name!r}" + return rv + + def dump_local_context(self, frame: Frame) -> str: + items_kv = ", ".join( + f"{name!r}: {target}" + for name, target in frame.symbols.dump_stores().items() + ) + return f"{{{items_kv}}}" + + def write_commons(self) -> None: + """Writes a common preamble that is used by root and block functions. + Primarily this sets up common local helpers and enforces a generator + through a dead branch. + """ + self.writeline("resolve = context.resolve_or_missing") + self.writeline("undefined = environment.undefined") + self.writeline("concat = environment.concat") + # always use the standard Undefined class for the implicit else of + # conditional expressions + self.writeline("cond_expr_undefined = Undefined") + self.writeline("if 0: yield None") + + def push_parameter_definitions(self, frame: Frame) -> None: + """Pushes all parameter targets from the given frame into a local + stack that permits tracking of yet to be assigned parameters. In + particular this enables the optimization from `visit_Name` to skip + undefined expressions for parameters in macros as macros can reference + otherwise unbound parameters. + """ + self._param_def_block.append(frame.symbols.dump_param_targets()) + + def pop_parameter_definitions(self) -> None: + """Pops the current parameter definitions set.""" + self._param_def_block.pop() + + def mark_parameter_stored(self, target: str) -> None: + """Marks a parameter in the current parameter definitions as stored. + This will skip the enforced undefined checks. + """ + if self._param_def_block: + self._param_def_block[-1].discard(target) + + def push_context_reference(self, target: str) -> None: + self._context_reference_stack.append(target) + + def pop_context_reference(self) -> None: + self._context_reference_stack.pop() + + def get_context_ref(self) -> str: + return self._context_reference_stack[-1] + + def get_resolve_func(self) -> str: + target = self._context_reference_stack[-1] + if target == "context": + return "resolve" + return f"{target}.resolve" + + def derive_context(self, frame: Frame) -> str: + return f"{self.get_context_ref()}.derived({self.dump_local_context(frame)})" + + def parameter_is_undeclared(self, target: str) -> bool: + """Checks if a given target is an undeclared parameter.""" + if not self._param_def_block: + return False + return target in self._param_def_block[-1] + + def push_assign_tracking(self) -> None: + """Pushes a new layer for assignment tracking.""" + self._assign_stack.append(set()) + + def pop_assign_tracking(self, frame: Frame) -> None: + """Pops the topmost level for assignment tracking and updates the + context variables if necessary. + """ + vars = self._assign_stack.pop() + if ( + not frame.block_frame + and not frame.loop_frame + and not frame.toplevel + or not vars + ): + return + public_names = [x for x in vars if x[:1] != "_"] + if len(vars) == 1: + name = next(iter(vars)) + ref = frame.symbols.ref(name) + if frame.loop_frame: + self.writeline(f"_loop_vars[{name!r}] = {ref}") + return + if frame.block_frame: + self.writeline(f"_block_vars[{name!r}] = {ref}") + return + self.writeline(f"context.vars[{name!r}] = {ref}") + else: + if frame.loop_frame: + self.writeline("_loop_vars.update({") + elif frame.block_frame: + self.writeline("_block_vars.update({") + else: + self.writeline("context.vars.update({") + for idx, name in enumerate(sorted(vars)): + if idx: + self.write(", ") + ref = frame.symbols.ref(name) + self.write(f"{name!r}: {ref}") + self.write("})") + if not frame.block_frame and not frame.loop_frame and public_names: + if len(public_names) == 1: + self.writeline(f"context.exported_vars.add({public_names[0]!r})") + else: + names_str = ", ".join(map(repr, sorted(public_names))) + self.writeline(f"context.exported_vars.update(({names_str}))") + + # -- Statement Visitors + + def visit_Template( + self, node: nodes.Template, frame: t.Optional[Frame] = None + ) -> None: + assert frame is None, "no root frame allowed" + eval_ctx = EvalContext(self.environment, self.name) + + from .runtime import async_exported + from .runtime import exported + + if self.environment.is_async: + exported_names = sorted(exported + async_exported) + else: + exported_names = sorted(exported) + + self.writeline("from jinja2.runtime import " + ", ".join(exported_names)) + + # if we want a deferred initialization we cannot move the + # environment into a local name + envenv = "" if self.defer_init else ", environment=environment" + + # do we have an extends tag at all? If not, we can save some + # overhead by just not processing any inheritance code. + have_extends = node.find(nodes.Extends) is not None + + # find all blocks + for block in node.find_all(nodes.Block): + if block.name in self.blocks: + self.fail(f"block {block.name!r} defined twice", block.lineno) + self.blocks[block.name] = block + + # find all imports and import them + for import_ in node.find_all(nodes.ImportedName): + if import_.importname not in self.import_aliases: + imp = import_.importname + self.import_aliases[imp] = alias = self.temporary_identifier() + if "." in imp: + module, obj = imp.rsplit(".", 1) + self.writeline(f"from {module} import {obj} as {alias}") + else: + self.writeline(f"import {imp} as {alias}") + + # add the load name + self.writeline(f"name = {self.name!r}") + + # generate the root render function. + self.writeline( + f"{self.func('root')}(context, missing=missing{envenv}):", extra=1 + ) + self.indent() + self.write_commons() + + # process the root + frame = Frame(eval_ctx) + if "self" in find_undeclared(node.body, ("self",)): + ref = frame.symbols.declare_parameter("self") + self.writeline(f"{ref} = TemplateReference(context)") + frame.symbols.analyze_node(node) + frame.toplevel = frame.rootlevel = True + frame.require_output_check = have_extends and not self.has_known_extends + if have_extends: + self.writeline("parent_template = None") + self.enter_frame(frame) + self.pull_dependencies(node.body) + self.blockvisit(node.body, frame) + self.leave_frame(frame, with_python_scope=True) + self.outdent() + + # make sure that the parent root is called. + if have_extends: + if not self.has_known_extends: + self.indent() + self.writeline("if parent_template is not None:") + self.indent() + if not self.environment.is_async: + self.writeline("yield from parent_template.root_render_func(context)") + else: + self.writeline("agen = parent_template.root_render_func(context)") + self.writeline("try:") + self.indent() + self.writeline("async for event in agen:") + self.indent() + self.writeline("yield event") + self.outdent() + self.outdent() + self.writeline("finally: await agen.aclose()") + self.outdent(1 + (not self.has_known_extends)) + + # at this point we now have the blocks collected and can visit them too. + for name, block in self.blocks.items(): + self.writeline( + f"{self.func('block_' + name)}(context, missing=missing{envenv}):", + block, + 1, + ) + self.indent() + self.write_commons() + # It's important that we do not make this frame a child of the + # toplevel template. This would cause a variety of + # interesting issues with identifier tracking. + block_frame = Frame(eval_ctx) + block_frame.block_frame = True + undeclared = find_undeclared(block.body, ("self", "super")) + if "self" in undeclared: + ref = block_frame.symbols.declare_parameter("self") + self.writeline(f"{ref} = TemplateReference(context)") + if "super" in undeclared: + ref = block_frame.symbols.declare_parameter("super") + self.writeline(f"{ref} = context.super({name!r}, block_{name})") + block_frame.symbols.analyze_node(block) + block_frame.block = name + self.writeline("_block_vars = {}") + self.enter_frame(block_frame) + self.pull_dependencies(block.body) + self.blockvisit(block.body, block_frame) + self.leave_frame(block_frame, with_python_scope=True) + self.outdent() + + blocks_kv_str = ", ".join(f"{x!r}: block_{x}" for x in self.blocks) + self.writeline(f"blocks = {{{blocks_kv_str}}}", extra=1) + debug_kv_str = "&".join(f"{k}={v}" for k, v in self.debug_info) + self.writeline(f"debug_info = {debug_kv_str!r}") + + def visit_Block(self, node: nodes.Block, frame: Frame) -> None: + """Call a block and register it for the template.""" + level = 0 + if frame.toplevel: + # if we know that we are a child template, there is no need to + # check if we are one + if self.has_known_extends: + return + if self.extends_so_far > 0: + self.writeline("if parent_template is None:") + self.indent() + level += 1 + + if node.scoped: + context = self.derive_context(frame) + else: + context = self.get_context_ref() + + if node.required: + self.writeline(f"if len(context.blocks[{node.name!r}]) <= 1:", node) + self.indent() + self.writeline( + f'raise TemplateRuntimeError("Required block {node.name!r} not found")', + node, + ) + self.outdent() + + if not self.environment.is_async and frame.buffer is None: + self.writeline( + f"yield from context.blocks[{node.name!r}][0]({context})", node + ) + else: + self.writeline(f"gen = context.blocks[{node.name!r}][0]({context})") + self.writeline("try:") + self.indent() + self.writeline( + f"{self.choose_async()}for event in gen:", + node, + ) + self.indent() + self.simple_write("event", frame) + self.outdent() + self.outdent() + self.writeline( + f"finally: {self.choose_async('await gen.aclose()', 'gen.close()')}" + ) + + self.outdent(level) + + def visit_Extends(self, node: nodes.Extends, frame: Frame) -> None: + """Calls the extender.""" + if not frame.toplevel: + self.fail("cannot use extend from a non top-level scope", node.lineno) + + # if the number of extends statements in general is zero so + # far, we don't have to add a check if something extended + # the template before this one. + if self.extends_so_far > 0: + # if we have a known extends we just add a template runtime + # error into the generated code. We could catch that at compile + # time too, but i welcome it not to confuse users by throwing the + # same error at different times just "because we can". + if not self.has_known_extends: + self.writeline("if parent_template is not None:") + self.indent() + self.writeline('raise TemplateRuntimeError("extended multiple times")') + + # if we have a known extends already we don't need that code here + # as we know that the template execution will end here. + if self.has_known_extends: + raise CompilerExit() + else: + self.outdent() + + self.writeline("parent_template = environment.get_template(", node) + self.visit(node.template, frame) + self.write(f", {self.name!r})") + self.writeline("for name, parent_block in parent_template.blocks.items():") + self.indent() + self.writeline("context.blocks.setdefault(name, []).append(parent_block)") + self.outdent() + + # if this extends statement was in the root level we can take + # advantage of that information and simplify the generated code + # in the top level from this point onwards + if frame.rootlevel: + self.has_known_extends = True + + # and now we have one more + self.extends_so_far += 1 + + def visit_Include(self, node: nodes.Include, frame: Frame) -> None: + """Handles includes.""" + if node.ignore_missing: + self.writeline("try:") + self.indent() + + func_name = "get_or_select_template" + if isinstance(node.template, nodes.Const): + if isinstance(node.template.value, str): + func_name = "get_template" + elif isinstance(node.template.value, (tuple, list)): + func_name = "select_template" + elif isinstance(node.template, (nodes.Tuple, nodes.List)): + func_name = "select_template" + + self.writeline(f"template = environment.{func_name}(", node) + self.visit(node.template, frame) + self.write(f", {self.name!r})") + if node.ignore_missing: + self.outdent() + self.writeline("except TemplateNotFound:") + self.indent() + self.writeline("pass") + self.outdent() + self.writeline("else:") + self.indent() + + def loop_body() -> None: + self.indent() + self.simple_write("event", frame) + self.outdent() + + if node.with_context: + self.writeline( + f"gen = template.root_render_func(" + "template.new_context(context.get_all(), True," + f" {self.dump_local_context(frame)}))" + ) + self.writeline("try:") + self.indent() + self.writeline(f"{self.choose_async()}for event in gen:") + loop_body() + self.outdent() + self.writeline( + f"finally: {self.choose_async('await gen.aclose()', 'gen.close()')}" + ) + elif self.environment.is_async: + self.writeline( + "for event in (await template._get_default_module_async())" + "._body_stream:" + ) + loop_body() + else: + self.writeline("yield from template._get_default_module()._body_stream") + + if node.ignore_missing: + self.outdent() + + def _import_common( + self, node: t.Union[nodes.Import, nodes.FromImport], frame: Frame + ) -> None: + self.write(f"{self.choose_async('await ')}environment.get_template(") + self.visit(node.template, frame) + self.write(f", {self.name!r}).") + + if node.with_context: + f_name = f"make_module{self.choose_async('_async')}" + self.write( + f"{f_name}(context.get_all(), True, {self.dump_local_context(frame)})" + ) + else: + self.write(f"_get_default_module{self.choose_async('_async')}(context)") + + def visit_Import(self, node: nodes.Import, frame: Frame) -> None: + """Visit regular imports.""" + self.writeline(f"{frame.symbols.ref(node.target)} = ", node) + if frame.toplevel: + self.write(f"context.vars[{node.target!r}] = ") + + self._import_common(node, frame) + + if frame.toplevel and not node.target.startswith("_"): + self.writeline(f"context.exported_vars.discard({node.target!r})") + + def visit_FromImport(self, node: nodes.FromImport, frame: Frame) -> None: + """Visit named imports.""" + self.newline(node) + self.write("included_template = ") + self._import_common(node, frame) + var_names = [] + discarded_names = [] + for name in node.names: + if isinstance(name, tuple): + name, alias = name + else: + alias = name + self.writeline( + f"{frame.symbols.ref(alias)} =" + f" getattr(included_template, {name!r}, missing)" + ) + self.writeline(f"if {frame.symbols.ref(alias)} is missing:") + self.indent() + # The position will contain the template name, and will be formatted + # into a string that will be compiled into an f-string. Curly braces + # in the name must be replaced with escapes so that they will not be + # executed as part of the f-string. + position = self.position(node).replace("{", "{{").replace("}", "}}") + message = ( + "the template {included_template.__name__!r}" + f" (imported on {position})" + f" does not export the requested name {name!r}" + ) + self.writeline( + f"{frame.symbols.ref(alias)} = undefined(f{message!r}, name={name!r})" + ) + self.outdent() + if frame.toplevel: + var_names.append(alias) + if not alias.startswith("_"): + discarded_names.append(alias) + + if var_names: + if len(var_names) == 1: + name = var_names[0] + self.writeline(f"context.vars[{name!r}] = {frame.symbols.ref(name)}") + else: + names_kv = ", ".join( + f"{name!r}: {frame.symbols.ref(name)}" for name in var_names + ) + self.writeline(f"context.vars.update({{{names_kv}}})") + if discarded_names: + if len(discarded_names) == 1: + self.writeline(f"context.exported_vars.discard({discarded_names[0]!r})") + else: + names_str = ", ".join(map(repr, discarded_names)) + self.writeline( + f"context.exported_vars.difference_update(({names_str}))" + ) + + def visit_For(self, node: nodes.For, frame: Frame) -> None: + loop_frame = frame.inner() + loop_frame.loop_frame = True + test_frame = frame.inner() + else_frame = frame.inner() + + # try to figure out if we have an extended loop. An extended loop + # is necessary if the loop is in recursive mode if the special loop + # variable is accessed in the body if the body is a scoped block. + extended_loop = ( + node.recursive + or "loop" + in find_undeclared(node.iter_child_nodes(only=("body",)), ("loop",)) + or any(block.scoped for block in node.find_all(nodes.Block)) + ) + + loop_ref = None + if extended_loop: + loop_ref = loop_frame.symbols.declare_parameter("loop") + + loop_frame.symbols.analyze_node(node, for_branch="body") + if node.else_: + else_frame.symbols.analyze_node(node, for_branch="else") + + if node.test: + loop_filter_func = self.temporary_identifier() + test_frame.symbols.analyze_node(node, for_branch="test") + self.writeline(f"{self.func(loop_filter_func)}(fiter):", node.test) + self.indent() + self.enter_frame(test_frame) + self.writeline(self.choose_async("async for ", "for ")) + self.visit(node.target, loop_frame) + self.write(" in ") + self.write(self.choose_async("auto_aiter(fiter)", "fiter")) + self.write(":") + self.indent() + self.writeline("if ", node.test) + self.visit(node.test, test_frame) + self.write(":") + self.indent() + self.writeline("yield ") + self.visit(node.target, loop_frame) + self.outdent(3) + self.leave_frame(test_frame, with_python_scope=True) + + # if we don't have an recursive loop we have to find the shadowed + # variables at that point. Because loops can be nested but the loop + # variable is a special one we have to enforce aliasing for it. + if node.recursive: + self.writeline( + f"{self.func('loop')}(reciter, loop_render_func, depth=0):", node + ) + self.indent() + self.buffer(loop_frame) + + # Use the same buffer for the else frame + else_frame.buffer = loop_frame.buffer + + # make sure the loop variable is a special one and raise a template + # assertion error if a loop tries to write to loop + if extended_loop: + self.writeline(f"{loop_ref} = missing") + + for name in node.find_all(nodes.Name): + if name.ctx == "store" and name.name == "loop": + self.fail( + "Can't assign to special loop variable in for-loop target", + name.lineno, + ) + + if node.else_: + iteration_indicator = self.temporary_identifier() + self.writeline(f"{iteration_indicator} = 1") + + self.writeline(self.choose_async("async for ", "for "), node) + self.visit(node.target, loop_frame) + if extended_loop: + self.write(f", {loop_ref} in {self.choose_async('Async')}LoopContext(") + else: + self.write(" in ") + + if node.test: + self.write(f"{loop_filter_func}(") + if node.recursive: + self.write("reciter") + else: + if self.environment.is_async and not extended_loop: + self.write("auto_aiter(") + self.visit(node.iter, frame) + if self.environment.is_async and not extended_loop: + self.write(")") + if node.test: + self.write(")") + + if node.recursive: + self.write(", undefined, loop_render_func, depth):") + else: + self.write(", undefined):" if extended_loop else ":") + + self.indent() + self.enter_frame(loop_frame) + + self.writeline("_loop_vars = {}") + self.blockvisit(node.body, loop_frame) + if node.else_: + self.writeline(f"{iteration_indicator} = 0") + self.outdent() + self.leave_frame( + loop_frame, with_python_scope=node.recursive and not node.else_ + ) + + if node.else_: + self.writeline(f"if {iteration_indicator}:") + self.indent() + self.enter_frame(else_frame) + self.blockvisit(node.else_, else_frame) + self.leave_frame(else_frame) + self.outdent() + + # if the node was recursive we have to return the buffer contents + # and start the iteration code + if node.recursive: + self.return_buffer_contents(loop_frame) + self.outdent() + self.start_write(frame, node) + self.write(f"{self.choose_async('await ')}loop(") + if self.environment.is_async: + self.write("auto_aiter(") + self.visit(node.iter, frame) + if self.environment.is_async: + self.write(")") + self.write(", loop)") + self.end_write(frame) + + # at the end of the iteration, clear any assignments made in the + # loop from the top level + if self._assign_stack: + self._assign_stack[-1].difference_update(loop_frame.symbols.stores) + + def visit_If(self, node: nodes.If, frame: Frame) -> None: + if_frame = frame.soft() + self.writeline("if ", node) + self.visit(node.test, if_frame) + self.write(":") + self.indent() + self.blockvisit(node.body, if_frame) + self.outdent() + for elif_ in node.elif_: + self.writeline("elif ", elif_) + self.visit(elif_.test, if_frame) + self.write(":") + self.indent() + self.blockvisit(elif_.body, if_frame) + self.outdent() + if node.else_: + self.writeline("else:") + self.indent() + self.blockvisit(node.else_, if_frame) + self.outdent() + + def visit_Macro(self, node: nodes.Macro, frame: Frame) -> None: + macro_frame, macro_ref = self.macro_body(node, frame) + self.newline() + if frame.toplevel: + if not node.name.startswith("_"): + self.write(f"context.exported_vars.add({node.name!r})") + self.writeline(f"context.vars[{node.name!r}] = ") + self.write(f"{frame.symbols.ref(node.name)} = ") + self.macro_def(macro_ref, macro_frame) + + def visit_CallBlock(self, node: nodes.CallBlock, frame: Frame) -> None: + call_frame, macro_ref = self.macro_body(node, frame) + self.writeline("caller = ") + self.macro_def(macro_ref, call_frame) + self.start_write(frame, node) + self.visit_Call(node.call, frame, forward_caller=True) + self.end_write(frame) + + def visit_FilterBlock(self, node: nodes.FilterBlock, frame: Frame) -> None: + filter_frame = frame.inner() + filter_frame.symbols.analyze_node(node) + self.enter_frame(filter_frame) + self.buffer(filter_frame) + self.blockvisit(node.body, filter_frame) + self.start_write(frame, node) + self.visit_Filter(node.filter, filter_frame) + self.end_write(frame) + self.leave_frame(filter_frame) + + def visit_With(self, node: nodes.With, frame: Frame) -> None: + with_frame = frame.inner() + with_frame.symbols.analyze_node(node) + self.enter_frame(with_frame) + for target, expr in zip(node.targets, node.values): + self.newline() + self.visit(target, with_frame) + self.write(" = ") + self.visit(expr, frame) + self.blockvisit(node.body, with_frame) + self.leave_frame(with_frame) + + def visit_ExprStmt(self, node: nodes.ExprStmt, frame: Frame) -> None: + self.newline(node) + self.visit(node.node, frame) + + class _FinalizeInfo(t.NamedTuple): + const: t.Optional[t.Callable[..., str]] + src: t.Optional[str] + + @staticmethod + def _default_finalize(value: t.Any) -> t.Any: + """The default finalize function if the environment isn't + configured with one. Or, if the environment has one, this is + called on that function's output for constants. + """ + return str(value) + + _finalize: t.Optional[_FinalizeInfo] = None + + def _make_finalize(self) -> _FinalizeInfo: + """Build the finalize function to be used on constants and at + runtime. Cached so it's only created once for all output nodes. + + Returns a ``namedtuple`` with the following attributes: + + ``const`` + A function to finalize constant data at compile time. + + ``src`` + Source code to output around nodes to be evaluated at + runtime. + """ + if self._finalize is not None: + return self._finalize + + finalize: t.Optional[t.Callable[..., t.Any]] + finalize = default = self._default_finalize + src = None + + if self.environment.finalize: + src = "environment.finalize(" + env_finalize = self.environment.finalize + pass_arg = { + _PassArg.context: "context", + _PassArg.eval_context: "context.eval_ctx", + _PassArg.environment: "environment", + }.get( + _PassArg.from_obj(env_finalize) # type: ignore + ) + finalize = None + + if pass_arg is None: + + def finalize(value: t.Any) -> t.Any: # noqa: F811 + return default(env_finalize(value)) + + else: + src = f"{src}{pass_arg}, " + + if pass_arg == "environment": + + def finalize(value: t.Any) -> t.Any: # noqa: F811 + return default(env_finalize(self.environment, value)) + + self._finalize = self._FinalizeInfo(finalize, src) + return self._finalize + + def _output_const_repr(self, group: t.Iterable[t.Any]) -> str: + """Given a group of constant values converted from ``Output`` + child nodes, produce a string to write to the template module + source. + """ + return repr(concat(group)) + + def _output_child_to_const( + self, node: nodes.Expr, frame: Frame, finalize: _FinalizeInfo + ) -> str: + """Try to optimize a child of an ``Output`` node by trying to + convert it to constant, finalized data at compile time. + + If :exc:`Impossible` is raised, the node is not constant and + will be evaluated at runtime. Any other exception will also be + evaluated at runtime for easier debugging. + """ + const = node.as_const(frame.eval_ctx) + + if frame.eval_ctx.autoescape: + const = escape(const) + + # Template data doesn't go through finalize. + if isinstance(node, nodes.TemplateData): + return str(const) + + return finalize.const(const) # type: ignore + + def _output_child_pre( + self, node: nodes.Expr, frame: Frame, finalize: _FinalizeInfo + ) -> None: + """Output extra source code before visiting a child of an + ``Output`` node. + """ + if frame.eval_ctx.volatile: + self.write("(escape if context.eval_ctx.autoescape else str)(") + elif frame.eval_ctx.autoescape: + self.write("escape(") + else: + self.write("str(") + + if finalize.src is not None: + self.write(finalize.src) + + def _output_child_post( + self, node: nodes.Expr, frame: Frame, finalize: _FinalizeInfo + ) -> None: + """Output extra source code after visiting a child of an + ``Output`` node. + """ + self.write(")") + + if finalize.src is not None: + self.write(")") + + def visit_Output(self, node: nodes.Output, frame: Frame) -> None: + # If an extends is active, don't render outside a block. + if frame.require_output_check: + # A top-level extends is known to exist at compile time. + if self.has_known_extends: + return + + self.writeline("if parent_template is None:") + self.indent() + + finalize = self._make_finalize() + body: t.List[t.Union[t.List[t.Any], nodes.Expr]] = [] + + # Evaluate constants at compile time if possible. Each item in + # body will be either a list of static data or a node to be + # evaluated at runtime. + for child in node.nodes: + try: + if not ( + # If the finalize function requires runtime context, + # constants can't be evaluated at compile time. + finalize.const + # Unless it's basic template data that won't be + # finalized anyway. + or isinstance(child, nodes.TemplateData) + ): + raise nodes.Impossible() + + const = self._output_child_to_const(child, frame, finalize) + except (nodes.Impossible, Exception): + # The node was not constant and needs to be evaluated at + # runtime. Or another error was raised, which is easier + # to debug at runtime. + body.append(child) + continue + + if body and isinstance(body[-1], list): + body[-1].append(const) + else: + body.append([const]) + + if frame.buffer is not None: + if len(body) == 1: + self.writeline(f"{frame.buffer}.append(") + else: + self.writeline(f"{frame.buffer}.extend((") + + self.indent() + + for item in body: + if isinstance(item, list): + # A group of constant data to join and output. + val = self._output_const_repr(item) + + if frame.buffer is None: + self.writeline("yield " + val) + else: + self.writeline(val + ",") + else: + if frame.buffer is None: + self.writeline("yield ", item) + else: + self.newline(item) + + # A node to be evaluated at runtime. + self._output_child_pre(item, frame, finalize) + self.visit(item, frame) + self._output_child_post(item, frame, finalize) + + if frame.buffer is not None: + self.write(",") + + if frame.buffer is not None: + self.outdent() + self.writeline(")" if len(body) == 1 else "))") + + if frame.require_output_check: + self.outdent() + + def visit_Assign(self, node: nodes.Assign, frame: Frame) -> None: + self.push_assign_tracking() + + # ``a.b`` is allowed for assignment, and is parsed as an NSRef. However, + # it is only valid if it references a Namespace object. Emit a check for + # that for each ref here, before assignment code is emitted. This can't + # be done in visit_NSRef as the ref could be in the middle of a tuple. + seen_refs: t.Set[str] = set() + + for nsref in node.find_all(nodes.NSRef): + if nsref.name in seen_refs: + # Only emit the check for each reference once, in case the same + # ref is used multiple times in a tuple, `ns.a, ns.b = c, d`. + continue + + seen_refs.add(nsref.name) + ref = frame.symbols.ref(nsref.name) + self.writeline(f"if not isinstance({ref}, Namespace):") + self.indent() + self.writeline( + "raise TemplateRuntimeError" + '("cannot assign attribute on non-namespace object")' + ) + self.outdent() + + self.newline(node) + self.visit(node.target, frame) + self.write(" = ") + self.visit(node.node, frame) + self.pop_assign_tracking(frame) + + def visit_AssignBlock(self, node: nodes.AssignBlock, frame: Frame) -> None: + self.push_assign_tracking() + block_frame = frame.inner() + # This is a special case. Since a set block always captures we + # will disable output checks. This way one can use set blocks + # toplevel even in extended templates. + block_frame.require_output_check = False + block_frame.symbols.analyze_node(node) + self.enter_frame(block_frame) + self.buffer(block_frame) + self.blockvisit(node.body, block_frame) + self.newline(node) + self.visit(node.target, frame) + self.write(" = (Markup if context.eval_ctx.autoescape else identity)(") + if node.filter is not None: + self.visit_Filter(node.filter, block_frame) + else: + self.write(f"concat({block_frame.buffer})") + self.write(")") + self.pop_assign_tracking(frame) + self.leave_frame(block_frame) + + # -- Expression Visitors + + def visit_Name(self, node: nodes.Name, frame: Frame) -> None: + if node.ctx == "store" and ( + frame.toplevel or frame.loop_frame or frame.block_frame + ): + if self._assign_stack: + self._assign_stack[-1].add(node.name) + ref = frame.symbols.ref(node.name) + + # If we are looking up a variable we might have to deal with the + # case where it's undefined. We can skip that case if the load + # instruction indicates a parameter which are always defined. + if node.ctx == "load": + load = frame.symbols.find_load(ref) + if not ( + load is not None + and load[0] == VAR_LOAD_PARAMETER + and not self.parameter_is_undeclared(ref) + ): + self.write( + f"(undefined(name={node.name!r}) if {ref} is missing else {ref})" + ) + return + + self.write(ref) + + def visit_NSRef(self, node: nodes.NSRef, frame: Frame) -> None: + # NSRef is a dotted assignment target a.b=c, but uses a[b]=c internally. + # visit_Assign emits code to validate that each ref is to a Namespace + # object only. That can't be emitted here as the ref could be in the + # middle of a tuple assignment. + ref = frame.symbols.ref(node.name) + self.writeline(f"{ref}[{node.attr!r}]") + + def visit_Const(self, node: nodes.Const, frame: Frame) -> None: + val = node.as_const(frame.eval_ctx) + if isinstance(val, float): + self.write(str(val)) + else: + self.write(repr(val)) + + def visit_TemplateData(self, node: nodes.TemplateData, frame: Frame) -> None: + try: + self.write(repr(node.as_const(frame.eval_ctx))) + except nodes.Impossible: + self.write( + f"(Markup if context.eval_ctx.autoescape else identity)({node.data!r})" + ) + + def visit_Tuple(self, node: nodes.Tuple, frame: Frame) -> None: + self.write("(") + idx = -1 + for idx, item in enumerate(node.items): + if idx: + self.write(", ") + self.visit(item, frame) + self.write(",)" if idx == 0 else ")") + + def visit_List(self, node: nodes.List, frame: Frame) -> None: + self.write("[") + for idx, item in enumerate(node.items): + if idx: + self.write(", ") + self.visit(item, frame) + self.write("]") + + def visit_Dict(self, node: nodes.Dict, frame: Frame) -> None: + self.write("{") + for idx, item in enumerate(node.items): + if idx: + self.write(", ") + self.visit(item.key, frame) + self.write(": ") + self.visit(item.value, frame) + self.write("}") + + visit_Add = _make_binop("+") + visit_Sub = _make_binop("-") + visit_Mul = _make_binop("*") + visit_Div = _make_binop("/") + visit_FloorDiv = _make_binop("//") + visit_Pow = _make_binop("**") + visit_Mod = _make_binop("%") + visit_And = _make_binop("and") + visit_Or = _make_binop("or") + visit_Pos = _make_unop("+") + visit_Neg = _make_unop("-") + visit_Not = _make_unop("not ") + + @optimizeconst + def visit_Concat(self, node: nodes.Concat, frame: Frame) -> None: + if frame.eval_ctx.volatile: + func_name = "(markup_join if context.eval_ctx.volatile else str_join)" + elif frame.eval_ctx.autoescape: + func_name = "markup_join" + else: + func_name = "str_join" + self.write(f"{func_name}((") + for arg in node.nodes: + self.visit(arg, frame) + self.write(", ") + self.write("))") + + @optimizeconst + def visit_Compare(self, node: nodes.Compare, frame: Frame) -> None: + self.write("(") + self.visit(node.expr, frame) + for op in node.ops: + self.visit(op, frame) + self.write(")") + + def visit_Operand(self, node: nodes.Operand, frame: Frame) -> None: + self.write(f" {operators[node.op]} ") + self.visit(node.expr, frame) + + @optimizeconst + def visit_Getattr(self, node: nodes.Getattr, frame: Frame) -> None: + if self.environment.is_async: + self.write("(await auto_await(") + + self.write("environment.getattr(") + self.visit(node.node, frame) + self.write(f", {node.attr!r})") + + if self.environment.is_async: + self.write("))") + + @optimizeconst + def visit_Getitem(self, node: nodes.Getitem, frame: Frame) -> None: + # slices bypass the environment getitem method. + if isinstance(node.arg, nodes.Slice): + self.visit(node.node, frame) + self.write("[") + self.visit(node.arg, frame) + self.write("]") + else: + if self.environment.is_async: + self.write("(await auto_await(") + + self.write("environment.getitem(") + self.visit(node.node, frame) + self.write(", ") + self.visit(node.arg, frame) + self.write(")") + + if self.environment.is_async: + self.write("))") + + def visit_Slice(self, node: nodes.Slice, frame: Frame) -> None: + if node.start is not None: + self.visit(node.start, frame) + self.write(":") + if node.stop is not None: + self.visit(node.stop, frame) + if node.step is not None: + self.write(":") + self.visit(node.step, frame) + + @contextmanager + def _filter_test_common( + self, node: t.Union[nodes.Filter, nodes.Test], frame: Frame, is_filter: bool + ) -> t.Iterator[None]: + if self.environment.is_async: + self.write("(await auto_await(") + + if is_filter: + self.write(f"{self.filters[node.name]}(") + func = self.environment.filters.get(node.name) + else: + self.write(f"{self.tests[node.name]}(") + func = self.environment.tests.get(node.name) + + # When inside an If or CondExpr frame, allow the filter to be + # undefined at compile time and only raise an error if it's + # actually called at runtime. See pull_dependencies. + if func is None and not frame.soft_frame: + type_name = "filter" if is_filter else "test" + self.fail(f"No {type_name} named {node.name!r}.", node.lineno) + + pass_arg = { + _PassArg.context: "context", + _PassArg.eval_context: "context.eval_ctx", + _PassArg.environment: "environment", + }.get( + _PassArg.from_obj(func) # type: ignore + ) + + if pass_arg is not None: + self.write(f"{pass_arg}, ") + + # Back to the visitor function to handle visiting the target of + # the filter or test. + yield + + self.signature(node, frame) + self.write(")") + + if self.environment.is_async: + self.write("))") + + @optimizeconst + def visit_Filter(self, node: nodes.Filter, frame: Frame) -> None: + with self._filter_test_common(node, frame, True): + # if the filter node is None we are inside a filter block + # and want to write to the current buffer + if node.node is not None: + self.visit(node.node, frame) + elif frame.eval_ctx.volatile: + self.write( + f"(Markup(concat({frame.buffer}))" + f" if context.eval_ctx.autoescape else concat({frame.buffer}))" + ) + elif frame.eval_ctx.autoescape: + self.write(f"Markup(concat({frame.buffer}))") + else: + self.write(f"concat({frame.buffer})") + + @optimizeconst + def visit_Test(self, node: nodes.Test, frame: Frame) -> None: + with self._filter_test_common(node, frame, False): + self.visit(node.node, frame) + + @optimizeconst + def visit_CondExpr(self, node: nodes.CondExpr, frame: Frame) -> None: + frame = frame.soft() + + def write_expr2() -> None: + if node.expr2 is not None: + self.visit(node.expr2, frame) + return + + self.write( + f'cond_expr_undefined("the inline if-expression on' + f" {self.position(node)} evaluated to false and no else" + f' section was defined.")' + ) + + self.write("(") + self.visit(node.expr1, frame) + self.write(" if ") + self.visit(node.test, frame) + self.write(" else ") + write_expr2() + self.write(")") + + @optimizeconst + def visit_Call( + self, node: nodes.Call, frame: Frame, forward_caller: bool = False + ) -> None: + if self.environment.is_async: + self.write("(await auto_await(") + if self.environment.sandboxed: + self.write("environment.call(context, ") + else: + self.write("context.call(") + self.visit(node.node, frame) + extra_kwargs = {"caller": "caller"} if forward_caller else None + loop_kwargs = {"_loop_vars": "_loop_vars"} if frame.loop_frame else {} + block_kwargs = {"_block_vars": "_block_vars"} if frame.block_frame else {} + if extra_kwargs: + extra_kwargs.update(loop_kwargs, **block_kwargs) + elif loop_kwargs or block_kwargs: + extra_kwargs = dict(loop_kwargs, **block_kwargs) + self.signature(node, frame, extra_kwargs) + self.write(")") + if self.environment.is_async: + self.write("))") + + def visit_Keyword(self, node: nodes.Keyword, frame: Frame) -> None: + self.write(node.key + "=") + self.visit(node.value, frame) + + # -- Unused nodes for extensions + + def visit_MarkSafe(self, node: nodes.MarkSafe, frame: Frame) -> None: + self.write("Markup(") + self.visit(node.expr, frame) + self.write(")") + + def visit_MarkSafeIfAutoescape( + self, node: nodes.MarkSafeIfAutoescape, frame: Frame + ) -> None: + self.write("(Markup if context.eval_ctx.autoescape else identity)(") + self.visit(node.expr, frame) + self.write(")") + + def visit_EnvironmentAttribute( + self, node: nodes.EnvironmentAttribute, frame: Frame + ) -> None: + self.write("environment." + node.name) + + def visit_ExtensionAttribute( + self, node: nodes.ExtensionAttribute, frame: Frame + ) -> None: + self.write(f"environment.extensions[{node.identifier!r}].{node.name}") + + def visit_ImportedName(self, node: nodes.ImportedName, frame: Frame) -> None: + self.write(self.import_aliases[node.importname]) + + def visit_InternalName(self, node: nodes.InternalName, frame: Frame) -> None: + self.write(node.name) + + def visit_ContextReference( + self, node: nodes.ContextReference, frame: Frame + ) -> None: + self.write("context") + + def visit_DerivedContextReference( + self, node: nodes.DerivedContextReference, frame: Frame + ) -> None: + self.write(self.derive_context(frame)) + + def visit_Continue(self, node: nodes.Continue, frame: Frame) -> None: + self.writeline("continue", node) + + def visit_Break(self, node: nodes.Break, frame: Frame) -> None: + self.writeline("break", node) + + def visit_Scope(self, node: nodes.Scope, frame: Frame) -> None: + scope_frame = frame.inner() + scope_frame.symbols.analyze_node(node) + self.enter_frame(scope_frame) + self.blockvisit(node.body, scope_frame) + self.leave_frame(scope_frame) + + def visit_OverlayScope(self, node: nodes.OverlayScope, frame: Frame) -> None: + ctx = self.temporary_identifier() + self.writeline(f"{ctx} = {self.derive_context(frame)}") + self.writeline(f"{ctx}.vars = ") + self.visit(node.context, frame) + self.push_context_reference(ctx) + + scope_frame = frame.inner(isolated=True) + scope_frame.symbols.analyze_node(node) + self.enter_frame(scope_frame) + self.blockvisit(node.body, scope_frame) + self.leave_frame(scope_frame) + self.pop_context_reference() + + def visit_EvalContextModifier( + self, node: nodes.EvalContextModifier, frame: Frame + ) -> None: + for keyword in node.options: + self.writeline(f"context.eval_ctx.{keyword.key} = ") + self.visit(keyword.value, frame) + try: + val = keyword.value.as_const(frame.eval_ctx) + except nodes.Impossible: + frame.eval_ctx.volatile = True + else: + setattr(frame.eval_ctx, keyword.key, val) + + def visit_ScopedEvalContextModifier( + self, node: nodes.ScopedEvalContextModifier, frame: Frame + ) -> None: + old_ctx_name = self.temporary_identifier() + saved_ctx = frame.eval_ctx.save() + self.writeline(f"{old_ctx_name} = context.eval_ctx.save()") + self.visit_EvalContextModifier(node, frame) + for child in node.body: + self.visit(child, frame) + frame.eval_ctx.revert(saved_ctx) + self.writeline(f"context.eval_ctx.revert({old_ctx_name})") diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/constants.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/constants.py new file mode 100644 index 0000000..41a1c23 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/constants.py @@ -0,0 +1,20 @@ +#: list of lorem ipsum words used by the lipsum() helper function +LOREM_IPSUM_WORDS = """\ +a ac accumsan ad adipiscing aenean aliquam aliquet amet ante aptent arcu at +auctor augue bibendum blandit class commodo condimentum congue consectetuer +consequat conubia convallis cras cubilia cum curabitur curae cursus dapibus +diam dictum dictumst dignissim dis dolor donec dui duis egestas eget eleifend +elementum elit enim erat eros est et etiam eu euismod facilisi facilisis fames +faucibus felis fermentum feugiat fringilla fusce gravida habitant habitasse hac +hendrerit hymenaeos iaculis id imperdiet in inceptos integer interdum ipsum +justo lacinia lacus laoreet lectus leo libero ligula litora lobortis lorem +luctus maecenas magna magnis malesuada massa mattis mauris metus mi molestie +mollis montes morbi mus nam nascetur natoque nec neque netus nibh nisi nisl non +nonummy nostra nulla nullam nunc odio orci ornare parturient pede pellentesque +penatibus per pharetra phasellus placerat platea porta porttitor posuere +potenti praesent pretium primis proin pulvinar purus quam quis quisque rhoncus +ridiculus risus rutrum sagittis sapien scelerisque sed sem semper senectus sit +sociis sociosqu sodales sollicitudin suscipit suspendisse taciti tellus tempor +tempus tincidunt torquent tortor tristique turpis ullamcorper ultrices +ultricies urna ut varius vehicula vel velit venenatis vestibulum vitae vivamus +viverra volutpat vulputate""" diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/debug.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/debug.py new file mode 100644 index 0000000..eeeeee7 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/debug.py @@ -0,0 +1,191 @@ +import sys +import typing as t +from types import CodeType +from types import TracebackType + +from .exceptions import TemplateSyntaxError +from .utils import internal_code +from .utils import missing + +if t.TYPE_CHECKING: + from .runtime import Context + + +def rewrite_traceback_stack(source: t.Optional[str] = None) -> BaseException: + """Rewrite the current exception to replace any tracebacks from + within compiled template code with tracebacks that look like they + came from the template source. + + This must be called within an ``except`` block. + + :param source: For ``TemplateSyntaxError``, the original source if + known. + :return: The original exception with the rewritten traceback. + """ + _, exc_value, tb = sys.exc_info() + exc_value = t.cast(BaseException, exc_value) + tb = t.cast(TracebackType, tb) + + if isinstance(exc_value, TemplateSyntaxError) and not exc_value.translated: + exc_value.translated = True + exc_value.source = source + # Remove the old traceback, otherwise the frames from the + # compiler still show up. + exc_value.with_traceback(None) + # Outside of runtime, so the frame isn't executing template + # code, but it still needs to point at the template. + tb = fake_traceback( + exc_value, None, exc_value.filename or "", exc_value.lineno + ) + else: + # Skip the frame for the render function. + tb = tb.tb_next + + stack = [] + + # Build the stack of traceback object, replacing any in template + # code with the source file and line information. + while tb is not None: + # Skip frames decorated with @internalcode. These are internal + # calls that aren't useful in template debugging output. + if tb.tb_frame.f_code in internal_code: + tb = tb.tb_next + continue + + template = tb.tb_frame.f_globals.get("__jinja_template__") + + if template is not None: + lineno = template.get_corresponding_lineno(tb.tb_lineno) + fake_tb = fake_traceback(exc_value, tb, template.filename, lineno) + stack.append(fake_tb) + else: + stack.append(tb) + + tb = tb.tb_next + + tb_next = None + + # Assign tb_next in reverse to avoid circular references. + for tb in reversed(stack): + tb.tb_next = tb_next + tb_next = tb + + return exc_value.with_traceback(tb_next) + + +def fake_traceback( # type: ignore + exc_value: BaseException, tb: t.Optional[TracebackType], filename: str, lineno: int +) -> TracebackType: + """Produce a new traceback object that looks like it came from the + template source instead of the compiled code. The filename, line + number, and location name will point to the template, and the local + variables will be the current template context. + + :param exc_value: The original exception to be re-raised to create + the new traceback. + :param tb: The original traceback to get the local variables and + code info from. + :param filename: The template filename. + :param lineno: The line number in the template source. + """ + if tb is not None: + # Replace the real locals with the context that would be + # available at that point in the template. + locals = get_template_locals(tb.tb_frame.f_locals) + locals.pop("__jinja_exception__", None) + else: + locals = {} + + globals = { + "__name__": filename, + "__file__": filename, + "__jinja_exception__": exc_value, + } + # Raise an exception at the correct line number. + code: CodeType = compile( + "\n" * (lineno - 1) + "raise __jinja_exception__", filename, "exec" + ) + + # Build a new code object that points to the template file and + # replaces the location with a block name. + location = "template" + + if tb is not None: + function = tb.tb_frame.f_code.co_name + + if function == "root": + location = "top-level template code" + elif function.startswith("block_"): + location = f"block {function[6:]!r}" + + if sys.version_info >= (3, 8): + code = code.replace(co_name=location) + else: + code = CodeType( + code.co_argcount, + code.co_kwonlyargcount, + code.co_nlocals, + code.co_stacksize, + code.co_flags, + code.co_code, + code.co_consts, + code.co_names, + code.co_varnames, + code.co_filename, + location, + code.co_firstlineno, + code.co_lnotab, + code.co_freevars, + code.co_cellvars, + ) + + # Execute the new code, which is guaranteed to raise, and return + # the new traceback without this frame. + try: + exec(code, globals, locals) + except BaseException: + return sys.exc_info()[2].tb_next # type: ignore + + +def get_template_locals(real_locals: t.Mapping[str, t.Any]) -> t.Dict[str, t.Any]: + """Based on the runtime locals, get the context that would be + available at that point in the template. + """ + # Start with the current template context. + ctx: t.Optional[Context] = real_locals.get("context") + + if ctx is not None: + data: t.Dict[str, t.Any] = ctx.get_all().copy() + else: + data = {} + + # Might be in a derived context that only sets local variables + # rather than pushing a context. Local variables follow the scheme + # l_depth_name. Find the highest-depth local that has a value for + # each name. + local_overrides: t.Dict[str, t.Tuple[int, t.Any]] = {} + + for name, value in real_locals.items(): + if not name.startswith("l_") or value is missing: + # Not a template variable, or no longer relevant. + continue + + try: + _, depth_str, name = name.split("_", 2) + depth = int(depth_str) + except ValueError: + continue + + cur_depth = local_overrides.get(name, (-1,))[0] + + if cur_depth < depth: + local_overrides[name] = (depth, value) + + # Modify the context with any derived context. + for name, (_, value) in local_overrides.items(): + if value is missing: + data.pop(name, None) + else: + data[name] = value + + return data diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/defaults.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/defaults.py new file mode 100644 index 0000000..638cad3 --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/defaults.py @@ -0,0 +1,48 @@ +import typing as t + +from .filters import FILTERS as DEFAULT_FILTERS # noqa: F401 +from .tests import TESTS as DEFAULT_TESTS # noqa: F401 +from .utils import Cycler +from .utils import generate_lorem_ipsum +from .utils import Joiner +from .utils import Namespace + +if t.TYPE_CHECKING: + import typing_extensions as te + +# defaults for the parser / lexer +BLOCK_START_STRING = "{%" +BLOCK_END_STRING = "%}" +VARIABLE_START_STRING = "{{" +VARIABLE_END_STRING = "}}" +COMMENT_START_STRING = "{#" +COMMENT_END_STRING = "#}" +LINE_STATEMENT_PREFIX: t.Optional[str] = None +LINE_COMMENT_PREFIX: t.Optional[str] = None +TRIM_BLOCKS = False +LSTRIP_BLOCKS = False +NEWLINE_SEQUENCE: "te.Literal['\\n', '\\r\\n', '\\r']" = "\n" +KEEP_TRAILING_NEWLINE = False + +# default filters, tests and namespace + +DEFAULT_NAMESPACE = { + "range": range, + "dict": dict, + "lipsum": generate_lorem_ipsum, + "cycler": Cycler, + "joiner": Joiner, + "namespace": Namespace, +} + +# default policies +DEFAULT_POLICIES: t.Dict[str, t.Any] = { + "compiler.ascii_str": True, + "urlize.rel": "noopener", + "urlize.target": None, + "urlize.extra_schemes": None, + "truncate.leeway": 5, + "json.dumps_function": None, + "json.dumps_kwargs": {"sort_keys": True}, + "ext.i18n.trimmed": False, +} diff --git a/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/environment.py b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/environment.py new file mode 100644 index 0000000..0fc6e5b --- /dev/null +++ b/app/src/main/assets/sample_projects/python-flask-shared/.pypackages/jinja2/environment.py @@ -0,0 +1,1672 @@ +"""Classes for managing templates and their runtime and compile time +options. +""" + +import os +import typing +import typing as t +import weakref +from collections import ChainMap +from functools import lru_cache +from functools import partial +from functools import reduce +from types import CodeType + +from markupsafe import Markup + +from . import nodes +from .compiler import CodeGenerator +from .compiler import generate +from .defaults import BLOCK_END_STRING +from .defaults import BLOCK_START_STRING +from .defaults import COMMENT_END_STRING +from .defaults import COMMENT_START_STRING +from .defaults import DEFAULT_FILTERS # type: ignore[attr-defined] +from .defaults import DEFAULT_NAMESPACE +from .defaults import DEFAULT_POLICIES +from .defaults import DEFAULT_TESTS # type: ignore[attr-defined] +from .defaults import KEEP_TRAILING_NEWLINE +from .defaults import LINE_COMMENT_PREFIX +from .defaults import LINE_STATEMENT_PREFIX +from .defaults import LSTRIP_BLOCKS +from .defaults import NEWLINE_SEQUENCE +from .defaults import TRIM_BLOCKS +from .defaults import VARIABLE_END_STRING +from .defaults import VARIABLE_START_STRING +from .exceptions import TemplateNotFound +from .exceptions import TemplateRuntimeError +from .exceptions import TemplatesNotFound +from .exceptions import TemplateSyntaxError +from .exceptions import UndefinedError +from .lexer import get_lexer +from .lexer import Lexer +from .lexer import TokenStream +from .nodes import EvalContext +from .parser import Parser +from .runtime import Context +from .runtime import new_context +from .runtime import Undefined +from .utils import _PassArg +from .utils import concat +from .utils import consume +from .utils import import_string +from .utils import internalcode +from .utils import LRUCache +from .utils import missing + +if t.TYPE_CHECKING: + import typing_extensions as te + + from .bccache import BytecodeCache + from .ext import Extension + from .loaders import BaseLoader + +_env_bound = t.TypeVar("_env_bound", bound="Environment") + + +# for direct template usage we have up to ten living environments +@lru_cache(maxsize=10) +def get_spontaneous_environment(cls: t.Type[_env_bound], *args: t.Any) -> _env_bound: + """Return a new spontaneous environment. A spontaneous environment + is used for templates created directly rather than through an + existing environment. + + :param cls: Environment class to create. + :param args: Positional arguments passed to environment. + """ + env = cls(*args) + env.shared = True + return env + + +def create_cache( + size: int, +) -> t.Optional[t.MutableMapping[t.Tuple["weakref.ref[t.Any]", str], "Template"]]: + """Return the cache class for the given size.""" + if size == 0: + return None + + if size < 0: + return {} + + return LRUCache(size) # type: ignore + + +def copy_cache( + cache: t.Optional[t.MutableMapping[t.Any, t.Any]], +) -> t.Optional[t.MutableMapping[t.Tuple["weakref.ref[t.Any]", str], "Template"]]: + """Create an empty copy of the given cache.""" + if cache is None: + return None + + if type(cache) is dict: # noqa E721 + return {} + + return LRUCache(cache.capacity) # type: ignore + + +def load_extensions( + environment: "Environment", + extensions: t.Sequence[t.Union[str, t.Type["Extension"]]], +) -> t.Dict[str, "Extension"]: + """Load the extensions from the list and bind it to the environment. + Returns a dict of instantiated extensions. + """ + result = {} + + for extension in extensions: + if isinstance(extension, str): + extension = t.cast(t.Type["Extension"], import_string(extension)) + + result[extension.identifier] = extension(environment) + + return result + + +def _environment_config_check(environment: _env_bound) -> _env_bound: + """Perform a sanity check on the environment.""" + assert issubclass( + environment.undefined, Undefined + ), "'undefined' must be a subclass of 'jinja2.Undefined'." + assert ( + environment.block_start_string + != environment.variable_start_string + != environment.comment_start_string + ), "block, variable and comment start strings must be different." + assert environment.newline_sequence in { + "\r", + "\r\n", + "\n", + }, "'newline_sequence' must be one of '\\n', '\\r\\n', or '\\r'." + return environment + + +class Environment: + r"""The core component of Jinja is the `Environment`. It contains + important shared variables like configuration, filters, tests, + globals and others. Instances of this class may be modified if + they are not shared and if no template was loaded so far. + Modifications on environments after the first template was loaded + will lead to surprising effects and undefined behavior. + + Here are the possible initialization parameters: + + `block_start_string` + The string marking the beginning of a block. Defaults to ``'{%'``. + + `block_end_string` + The string marking the end of a block. Defaults to ``'%}'``. + + `variable_start_string` + The string marking the beginning of a print statement. + Defaults to ``'{{'``. + + `variable_end_string` + The string marking the end of a print statement. Defaults to + ``'}}'``. + + `comment_start_string` + The string marking the beginning of a comment. Defaults to ``'{#'``. + + `comment_end_string` + The string marking the end of a comment. Defaults to ``'#}'``. + + `line_statement_prefix` + If given and a string, this will be used as prefix for line based + statements. See also :ref:`line-statements`. + + `line_comment_prefix` + If given and a string, this will be used as prefix for line based + comments. See also :ref:`line-statements`. + + .. versionadded:: 2.2 + + `trim_blocks` + If this is set to ``True`` the first newline after a block is + removed (block, not variable tag!). Defaults to `False`. + + `lstrip_blocks` + If this is set to ``True`` leading spaces and tabs are stripped + from the start of a line to a block. Defaults to `False`. + + `newline_sequence` + The sequence that starts a newline. Must be one of ``'\r'``, + ``'\n'`` or ``'\r\n'``. The default is ``'\n'`` which is a + useful default for Linux and OS X systems as well as web + applications. + + `keep_trailing_newline` + Preserve the trailing newline when rendering templates. + The default is ``False``, which causes a single newline, + if present, to be stripped from the end of the template. + + .. versionadded:: 2.7 + + `extensions` + List of Jinja extensions to use. This can either be import paths + as strings or extension classes. For more information have a + look at :ref:`the extensions documentation `. + + `optimized` + should the optimizer be enabled? Default is ``True``. + + `undefined` + :class:`Undefined` or a subclass of it that is used to represent + undefined values in the template. + + `finalize` + A callable that can be used to process the result of a variable + expression before it is output. For example one can convert + ``None`` implicitly into an empty string here. + + `autoescape` + If set to ``True`` the XML/HTML autoescaping feature is enabled by + default. For more details about autoescaping see + :class:`~markupsafe.Markup`. As of Jinja 2.4 this can also + be a callable that is passed the template name and has to + return ``True`` or ``False`` depending on autoescape should be + enabled by default. + + .. versionchanged:: 2.4 + `autoescape` can now be a function + + `loader` + The template loader for this environment. + + `cache_size` + The size of the cache. Per default this is ``400`` which means + that if more than 400 templates are loaded the loader will clean + out the least recently used template. If the cache size is set to + ``0`` templates are recompiled all the time, if the cache size is + ``-1`` the cache will not be cleaned. + + .. versionchanged:: 2.8 + The cache size was increased to 400 from a low 50. + + `auto_reload` + Some loaders load templates from locations where the template + sources may change (ie: file system or database). If + ``auto_reload`` is set to ``True`` (default) every time a template is + requested the loader checks if the source changed and if yes, it + will reload the template. For higher performance it's possible to + disable that. + + `bytecode_cache` + If set to a bytecode cache object, this object will provide a + cache for the internal Jinja bytecode so that templates don't + have to be parsed if they were not changed. + + See :ref:`bytecode-cache` for more information. + + `enable_async` + If set to true this enables async template execution which + allows using async functions and generators. + """ + + #: if this environment is sandboxed. Modifying this variable won't make + #: the environment sandboxed though. For a real sandboxed environment + #: have a look at jinja2.sandbox. This flag alone controls the code + #: generation by the compiler. + sandboxed = False + + #: True if the environment is just an overlay + overlayed = False + + #: the environment this environment is linked to if it is an overlay + linked_to: t.Optional["Environment"] = None + + #: shared environments have this set to `True`. A shared environment + #: must not be modified + shared = False + + #: the class that is used for code generation. See + #: :class:`~jinja2.compiler.CodeGenerator` for more information. + code_generator_class: t.Type["CodeGenerator"] = CodeGenerator + + concat = "".join + + #: the context class that is used for templates. See + #: :class:`~jinja2.runtime.Context` for more information. + context_class: t.Type[Context] = Context + + template_class: t.Type["Template"] + + def __init__( + self, + block_start_string: str = BLOCK_START_STRING, + block_end_string: str = BLOCK_END_STRING, + variable_start_string: str = VARIABLE_START_STRING, + variable_end_string: str = VARIABLE_END_STRING, + comment_start_string: str = COMMENT_START_STRING, + comment_end_string: str = COMMENT_END_STRING, + line_statement_prefix: t.Optional[str] = LINE_STATEMENT_PREFIX, + line_comment_prefix: t.Optional[str] = LINE_COMMENT_PREFIX, + trim_blocks: bool = TRIM_BLOCKS, + lstrip_blocks: bool = LSTRIP_BLOCKS, + newline_sequence: "te.Literal['\\n', '\\r\\n', '\\r']" = NEWLINE_SEQUENCE, + keep_trailing_newline: bool = KEEP_TRAILING_NEWLINE, + extensions: t.Sequence[t.Union[str, t.Type["Extension"]]] = (), + optimized: bool = True, + undefined: t.Type[Undefined] = Undefined, + finalize: t.Optional[t.Callable[..., t.Any]] = None, + autoescape: t.Union[bool, t.Callable[[t.Optional[str]], bool]] = False, + loader: t.Optional["BaseLoader"] = None, + cache_size: int = 400, + auto_reload: bool = True, + bytecode_cache: t.Optional["BytecodeCache"] = None, + enable_async: bool = False, + ): + # !!Important notice!! + # The constructor accepts quite a few arguments that should be + # passed by keyword rather than position. However it's important to + # not change the order of arguments because it's used at least + # internally in those cases: + # - spontaneous environments (i18n extension and Template) + # - unittests + # If parameter changes are required only add parameters at the end + # and don't change the arguments (or the defaults!) of the arguments + # existing already. + + # lexer / parser information + self.block_start_string = block_start_string + self.block_end_string = block_end_string + self.variable_start_string = variable_start_string + self.variable_end_string = variable_end_string + self.comment_start_string = comment_start_string + self.comment_end_string = comment_end_string + self.line_statement_prefix = line_statement_prefix + self.line_comment_prefix = line_comment_prefix + self.trim_blocks = trim_blocks + self.lstrip_blocks = lstrip_blocks + self.newline_sequence = newline_sequence + self.keep_trailing_newline = keep_trailing_newline + + # runtime information + self.undefined: t.Type[Undefined] = undefined + self.optimized = optimized + self.finalize = finalize + self.autoescape = autoescape + + # defaults + self.filters = DEFAULT_FILTERS.copy() + self.tests = DEFAULT_TESTS.copy() + self.globals = DEFAULT_NAMESPACE.copy() + + # set the loader provided + self.loader = loader + self.cache = create_cache(cache_size) + self.bytecode_cache = bytecode_cache + self.auto_reload = auto_reload + + # configurable policies + self.policies = DEFAULT_POLICIES.copy() + + # load extensions + self.extensions = load_extensions(self, extensions) + + self.is_async = enable_async + _environment_config_check(self) + + def add_extension(self, extension: t.Union[str, t.Type["Extension"]]) -> None: + """Adds an extension after the environment was created. + + .. versionadded:: 2.5 + """ + self.extensions.update(load_extensions(self, [extension])) + + def extend(self, **attributes: t.Any) -> None: + """Add the items to the instance of the environment if they do not exist + yet. This is used by :ref:`extensions ` to register + callbacks and configuration values without breaking inheritance. + """ + for key, value in attributes.items(): + if not hasattr(self, key): + setattr(self, key, value) + + def overlay( + self, + block_start_string: str = missing, + block_end_string: str = missing, + variable_start_string: str = missing, + variable_end_string: str = missing, + comment_start_string: str = missing, + comment_end_string: str = missing, + line_statement_prefix: t.Optional[str] = missing, + line_comment_prefix: t.Optional[str] = missing, + trim_blocks: bool = missing, + lstrip_blocks: bool = missing, + newline_sequence: "te.Literal['\\n', '\\r\\n', '\\r']" = missing, + keep_trailing_newline: bool = missing, + extensions: t.Sequence[t.Union[str, t.Type["Extension"]]] = missing, + optimized: bool = missing, + undefined: t.Type[Undefined] = missing, + finalize: t.Optional[t.Callable[..., t.Any]] = missing, + autoescape: t.Union[bool, t.Callable[[t.Optional[str]], bool]] = missing, + loader: t.Optional["BaseLoader"] = missing, + cache_size: int = missing, + auto_reload: bool = missing, + bytecode_cache: t.Optional["BytecodeCache"] = missing, + enable_async: bool = missing, + ) -> "te.Self": + """Create a new overlay environment that shares all the data with the + current environment except for cache and the overridden attributes. + Extensions cannot be removed for an overlayed environment. An overlayed + environment automatically gets all the extensions of the environment it + is linked to plus optional extra extensions. + + Creating overlays should happen after the initial environment was set + up completely. Not all attributes are truly linked, some are just + copied over so modifications on the original environment may not shine + through. + + .. versionchanged:: 3.1.5 + ``enable_async`` is applied correctly. + + .. versionchanged:: 3.1.2 + Added the ``newline_sequence``, ``keep_trailing_newline``, + and ``enable_async`` parameters to match ``__init__``. + """ + args = dict(locals()) + del args["self"], args["cache_size"], args["extensions"], args["enable_async"] + + rv = object.__new__(self.__class__) + rv.__dict__.update(self.__dict__) + rv.overlayed = True + rv.linked_to = self + + for key, value in args.items(): + if value is not missing: + setattr(rv, key, value) + + if cache_size is not missing: + rv.cache = create_cache(cache_size) + else: + rv.cache = copy_cache(self.cache) + + rv.extensions = {} + for key, value in self.extensions.items(): + rv.extensions[key] = value.bind(rv) + if extensions is not missing: + rv.extensions.update(load_extensions(rv, extensions)) + + if enable_async is not missing: + rv.is_async = enable_async + + return _environment_config_check(rv) + + @property + def lexer(self) -> Lexer: + """The lexer for this environment.""" + return get_lexer(self) + + def iter_extensions(self) -> t.Iterator["Extension"]: + """Iterates over the extensions by priority.""" + return iter(sorted(self.extensions.values(), key=lambda x: x.priority)) + + def getitem( + self, obj: t.Any, argument: t.Union[str, t.Any] + ) -> t.Union[t.Any, Undefined]: + """Get an item or attribute of an object but prefer the item.""" + try: + return obj[argument] + except (AttributeError, TypeError, LookupError): + if isinstance(argument, str): + try: + attr = str(argument) + except Exception: + pass + else: + try: + return getattr(obj, attr) + except AttributeError: + pass + return self.undefined(obj=obj, name=argument) + + def getattr(self, obj: t.Any, attribute: str) -> t.Any: + """Get an item or attribute of an object but prefer the attribute. + Unlike :meth:`getitem` the attribute *must* be a string. + """ + try: + return getattr(obj, attribute) + except AttributeError: + pass + try: + return obj[attribute] + except (TypeError, LookupError, AttributeError): + return self.undefined(obj=obj, name=attribute) + + def _filter_test_common( + self, + name: t.Union[str, Undefined], + value: t.Any, + args: t.Optional[t.Sequence[t.Any]], + kwargs: t.Optional[t.Mapping[str, t.Any]], + context: t.Optional[Context], + eval_ctx: t.Optional[EvalContext], + is_filter: bool, + ) -> t.Any: + if is_filter: + env_map = self.filters + type_name = "filter" + else: + env_map = self.tests + type_name = "test" + + func = env_map.get(name) # type: ignore + + if func is None: + msg = f"No {type_name} named {name!r}." + + if isinstance(name, Undefined): + try: + name._fail_with_undefined_error() + except Exception as e: + msg = f"{msg} ({e}; did you forget to quote the callable name?)" + + raise TemplateRuntimeError(msg) + + args = [value, *(args if args is not None else ())] + kwargs = kwargs if kwargs is not None else {} + pass_arg = _PassArg.from_obj(func) + + if pass_arg is _PassArg.context: + if context is None: + raise TemplateRuntimeError( + f"Attempted to invoke a context {type_name} without context." + ) + + args.insert(0, context) + elif pass_arg is _PassArg.eval_context: + if eval_ctx is None: + if context is not None: + eval_ctx = context.eval_ctx + else: + eval_ctx = EvalContext(self) + + args.insert(0, eval_ctx) + elif pass_arg is _PassArg.environment: + args.insert(0, self) + + return func(*args, **kwargs) + + def call_filter( + self, + name: str, + value: t.Any, + args: t.Optional[t.Sequence[t.Any]] = None, + kwargs: t.Optional[t.Mapping[str, t.Any]] = None, + context: t.Optional[Context] = None, + eval_ctx: t.Optional[EvalContext] = None, + ) -> t.Any: + """Invoke a filter on a value the same way the compiler does. + + This might return a coroutine if the filter is running from an + environment in async mode and the filter supports async + execution. It's your responsibility to await this if needed. + + .. versionadded:: 2.7 + """ + return self._filter_test_common( + name, value, args, kwargs, context, eval_ctx, True + ) + + def call_test( + self, + name: str, + value: t.Any, + args: t.Optional[t.Sequence[t.Any]] = None, + kwargs: t.Optional[t.Mapping[str, t.Any]] = None, + context: t.Optional[Context] = None, + eval_ctx: t.Optional[EvalContext] = None, + ) -> t.Any: + """Invoke a test on a value the same way the compiler does. + + This might return a coroutine if the test is running from an + environment in async mode and the test supports async execution. + It's your responsibility to await this if needed. + + .. versionchanged:: 3.0 + Tests support ``@pass_context``, etc. decorators. Added + the ``context`` and ``eval_ctx`` parameters. + + .. versionadded:: 2.7 + """ + return self._filter_test_common( + name, value, args, kwargs, context, eval_ctx, False + ) + + @internalcode + def parse( + self, + source: str, + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + ) -> nodes.Template: + """Parse the sourcecode and return the abstract syntax tree. This + tree of nodes is used by the compiler to convert the template into + executable source- or bytecode. This is useful for debugging or to + extract information from templates. + + If you are :ref:`developing Jinja extensions ` + this gives you a good overview of the node tree generated. + """ + try: + return self._parse(source, name, filename) + except TemplateSyntaxError: + self.handle_exception(source=source) + + def _parse( + self, source: str, name: t.Optional[str], filename: t.Optional[str] + ) -> nodes.Template: + """Internal parsing function used by `parse` and `compile`.""" + return Parser(self, source, name, filename).parse() + + def lex( + self, + source: str, + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + ) -> t.Iterator[t.Tuple[int, str, str]]: + """Lex the given sourcecode and return a generator that yields + tokens as tuples in the form ``(lineno, token_type, value)``. + This can be useful for :ref:`extension development ` + and debugging templates. + + This does not perform preprocessing. If you want the preprocessing + of the extensions to be applied you have to filter source through + the :meth:`preprocess` method. + """ + source = str(source) + try: + return self.lexer.tokeniter(source, name, filename) + except TemplateSyntaxError: + self.handle_exception(source=source) + + def preprocess( + self, + source: str, + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + ) -> str: + """Preprocesses the source with all extensions. This is automatically + called for all parsing and compiling methods but *not* for :meth:`lex` + because there you usually only want the actual source tokenized. + """ + return reduce( + lambda s, e: e.preprocess(s, name, filename), + self.iter_extensions(), + str(source), + ) + + def _tokenize( + self, + source: str, + name: t.Optional[str], + filename: t.Optional[str] = None, + state: t.Optional[str] = None, + ) -> TokenStream: + """Called by the parser to do the preprocessing and filtering + for all the extensions. Returns a :class:`~jinja2.lexer.TokenStream`. + """ + source = self.preprocess(source, name, filename) + stream = self.lexer.tokenize(source, name, filename, state) + + for ext in self.iter_extensions(): + stream = ext.filter_stream(stream) # type: ignore + + if not isinstance(stream, TokenStream): + stream = TokenStream(stream, name, filename) + + return stream + + def _generate( + self, + source: nodes.Template, + name: t.Optional[str], + filename: t.Optional[str], + defer_init: bool = False, + ) -> str: + """Internal hook that can be overridden to hook a different generate + method in. + + .. versionadded:: 2.5 + """ + return generate( # type: ignore + source, + self, + name, + filename, + defer_init=defer_init, + optimized=self.optimized, + ) + + def _compile(self, source: str, filename: str) -> CodeType: + """Internal hook that can be overridden to hook a different compile + method in. + + .. versionadded:: 2.5 + """ + return compile(source, filename, "exec") + + @typing.overload + def compile( + self, + source: t.Union[str, nodes.Template], + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + raw: "te.Literal[False]" = False, + defer_init: bool = False, + ) -> CodeType: ... + + @typing.overload + def compile( + self, + source: t.Union[str, nodes.Template], + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + raw: "te.Literal[True]" = ..., + defer_init: bool = False, + ) -> str: ... + + @internalcode + def compile( + self, + source: t.Union[str, nodes.Template], + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + raw: bool = False, + defer_init: bool = False, + ) -> t.Union[str, CodeType]: + """Compile a node or template source code. The `name` parameter is + the load name of the template after it was joined using + :meth:`join_path` if necessary, not the filename on the file system. + the `filename` parameter is the estimated filename of the template on + the file system. If the template came from a database or memory this + can be omitted. + + The return value of this method is a python code object. If the `raw` + parameter is `True` the return value will be a string with python + code equivalent to the bytecode returned otherwise. This method is + mainly used internally. + + `defer_init` is use internally to aid the module code generator. This + causes the generated code to be able to import without the global + environment variable to be set. + + .. versionadded:: 2.4 + `defer_init` parameter added. + """ + source_hint = None + try: + if isinstance(source, str): + source_hint = source + source = self._parse(source, name, filename) + source = self._generate(source, name, filename, defer_init=defer_init) + if raw: + return source + if filename is None: + filename = "